提交 43078ff0 authored 作者: 张伊明's avatar 张伊明

合并分支 'zz-dev' 到 'pre'

feat:美国科研资助体系概览页样式与功能 查看合并请求 !302
流水线 #311 已通过 于阶段
in 3 分 18 秒
...@@ -126,11 +126,25 @@ export function getAreaType() { ...@@ -126,11 +126,25 @@ export function getAreaType() {
}) })
} }
/**
* 资助项目列表:领域、年份用逗号拼接为一个查询参数(arealist=1,2,3&yearlist=2025,2024)
*/
function normalizeProjectListQueryParams(params) {
const next = { ...(params || {}) }
if (Array.isArray(next.arealist)) {
next.arealist = next.arealist.filter((v) => v !== undefined && v !== null && v !== "").join(",")
}
if (Array.isArray(next.yearlist)) {
next.yearlist = next.yearlist.filter((v) => v !== undefined && v !== null && v !== "").join(",")
}
return next
}
//资助体系v2.0:资助项目列表分页 //资助体系v2.0:资助项目列表分页
export function getProjectListNew(params) { export function getProjectListNew(params) {
return request({ return request({
method: 'GET', method: 'GET',
url: `/api/fund/getProjectListNew`, url: `/api/fund/getProjectListNew`,
params params: normalizeProjectListQueryParams(params)
}) })
} }
...@@ -70,7 +70,9 @@ router.beforeEach((to, from, next) => { ...@@ -70,7 +70,9 @@ router.beforeEach((to, from, next) => {
if (to.meta.dynamicTitle) { if (to.meta.dynamicTitle) {
console.log('to', to); console.log('to', to);
const storageKey = to.meta.titleStorageKey || "curTabName"; const storageKey = to.meta.titleStorageKey || "curTabName";
document.title = window.sessionStorage.getItem(storageKey) || to.meta.title; // 新开页签时 sessionStorage 不共享,优先用 query 带过来的 title/name
const queryTitle = (to.query && (to.query.title || to.query.name)) ? String(to.query.title || to.query.name) : "";
document.title = queryTitle || window.sessionStorage.getItem(storageKey) || to.meta.title;
} else { } else {
document.title = to.meta.title document.title = to.meta.title
......
...@@ -88,7 +88,8 @@ const decreeRoutes = [ ...@@ -88,7 +88,8 @@ const decreeRoutes = [
component: Institution, component: Institution,
meta: { meta: {
title: "行政机构主页", title: "行政机构主页",
dynamicTitle: true dynamicTitle: true,
titleStorageKey: "institutionTabName"
} }
}, },
{ {
......
...@@ -23,8 +23,8 @@ ...@@ -23,8 +23,8 @@
</div> </div>
</div> --> </div> -->
<NewsList :newsList="leftList" @more-click="handleToMoreNews" img="newsImage" title="newsTitle" <NewsList :newsList="leftList" @more-click="handleToMoreNews" img="newsImage" title="newsTitle"
content="newsContent" from="from" /> content="newsContent" from="from" @item-click="item => gotoNewsDetail(item.newsId)" />
<MessageBubble :messageList="rightList" @more-click="handleToSocialDetail" source="orgName" content="remarks" <MessageBubble :messageList="rightList" @person-click="handleToSocialDetail" source="orgName" content="remarks"
name="personName" imageUrl="personImage"> name="personName" imageUrl="personImage">
</MessageBubble> </MessageBubble>
<!-- <div class="right-box"> <!-- <div class="right-box">
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
import NewsList from "@/components/base/newsList/index.vue"; import NewsList from "@/components/base/newsList/index.vue";
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
import { useGotoNewsDetail } from "@/router/modules/news";
import { import {
getSocialMediaInfo, getNews getSocialMediaInfo, getNews
} from "@/api/scientificFunding/overview"; } from "@/api/scientificFunding/overview";
...@@ -171,15 +172,19 @@ const handleToMoreNews = () => { ...@@ -171,15 +172,19 @@ const handleToMoreNews = () => {
}; };
// 查看社交媒体详情 // 查看社交媒体详情
const handleToSocialDetail = item => { const handleToSocialDetail = item => {
const personId = item?.personId || item?.id;
if (!personId) return;
const route = router.resolve({ const route = router.resolve({
path: "/characterPage", path: "/characterPage",
query: { query: {
personId: item.id personId
} }
}); });
window.open(route.href, "_blank"); window.open(route.href, "_blank");
}; };
const gotoNewsDetail = useGotoNewsDetail();
onMounted(async () => { onMounted(async () => {
handleNews() handleNews()
handleSocialMediaInfo() handleSocialMediaInfo()
......
...@@ -21,23 +21,30 @@ ...@@ -21,23 +21,30 @@
<div class="left-center-main-ul"> <div class="left-center-main-ul">
<ul> <ul>
<li> <li>
<img src="./assets/icon-black.png" alt="" class="li-img" />
<span class="ul-title">投资主体:</span> <span class="ul-title">投资主体:</span>
<span class="ul-content">美国国家科学基金会</span> <span class="ul-content">美国国家科学基金会</span>
</li> </li>
<li> <li>
<img src="./assets/icon-black.png" alt="" class="li-img" />
<span class="ul-title">发布日期:</span> <span class="ul-title">发布日期:</span>
<span class="ul-content">{{ itemData.publicationDate }}</span> <span class="ul-content">{{ itemData.publicationDate }}</span>
</li> </li>
<li> <li>
<img src="./assets/icon-black.png" alt="" class="li-img" />
<span class="ul-title">资助经费:</span> <span class="ul-title">资助经费:</span>
<span class="ul-content">{{ itemData.amount }}</span> <span class="ul-content">{{ itemData.amount }}</span>
</li> </li>
<li> <li>
<img src="./assets/icon-black.png" alt="" class="li-img" />
<span class="ul-title">涉及领域:</span> <span class="ul-title">涉及领域:</span>
<span class="ul-pie cl1" v-for="value in itemData.toOrgNameList">{{ value }}</span> <span class="ul-pie cl1">
<AreaTag v-for="(val, idx) in itemData.areaList" :key="idx" :tagName="val" />
</span>
</li> </li>
<li> <li>
<img src="./assets/icon-black.png" alt="" class="li-img" />
<span class="ul-title">资助对象:</span> <span class="ul-title">资助对象:</span>
<span class="ul-content">{{ itemData.fromOrgNameList.join(',') }}</span> <span class="ul-content">{{ itemData.fromOrgNameList.join(',') }}</span>
</li> </li>
...@@ -97,42 +104,7 @@ import { ...@@ -97,42 +104,7 @@ import {
import router from "@/router"; import router from "@/router";
const list = ref([ const list = ref([
{
id: 1,
title: "特别重大",
content: "NSF宣布新的“新兴技术体验式学习”计划资...",
time: "一天前"
},
{
id: 2,
title: "一般风险",
content: "美国NASA公布NIAC计划2025年度第一轮资助",
time: "一天前"
},
{
id: 3,
title: "特别重大",
content: "美国NASA公布“早期创新计划”2026年资助...",
time: "一天前"
},
{
id: 4,
title: "重大风险",
content: '美国NIH冻结多所顶尖大学资金引发广泛争议"',
time: "一天前"
},
{
id: 5,
title: "重大风险",
content: "美国NIH终止哥伦比亚大学研究项目拨款引发...",
time: "一天前"
},
{
id: 6,
title: "特别重大",
content: "美国DARPA资助可调控生物功能微系统技术开发",
time: "一天前"
}
]); ]);
//// 获取风险信号 //// 获取风险信号
...@@ -286,7 +258,7 @@ onMounted(async () => { ...@@ -286,7 +258,7 @@ onMounted(async () => {
height: 175px; height: 175px;
.left-center-main-title { .left-center-main-title {
margin-left: 19px; margin-left: 22px;
margin-bottom: 17px; margin-bottom: 17px;
font-size: 20px; font-size: 20px;
font-weight: 700; font-weight: 700;
...@@ -305,6 +277,20 @@ onMounted(async () => { ...@@ -305,6 +277,20 @@ onMounted(async () => {
width: 100%; width: 100%;
height: 24px; height: 24px;
margin-bottom: 12px; margin-bottom: 12px;
display: flex;
.li-img {
width: 4px;
height: 4px;
margin-right: 18px;
margin-top: 10px;
img {
width: 100%;
height: 100%;
display: block;
}
}
.ul-title { .ul-title {
display: inline-block; display: inline-block;
...@@ -326,19 +312,14 @@ onMounted(async () => { ...@@ -326,19 +312,14 @@ onMounted(async () => {
} }
.ul-pie { .ul-pie {
display: inline-block; display: flex;
gap: 8px;
box-sizing: border-box; box-sizing: border-box;
padding: 2px 8px; flex-direction: row;
border: 1px solid;
border-radius: 4px;
margin-right: 8px; margin-right: 8px;
} }
.cl1 {
border-color: rgba(186, 224, 255, 1);
background-color: rgba(230, 244, 255, 1);
color: rgba(22, 119, 255, 1);
}
.cl2 { .cl2 {
border-color: rgba(255, 163, 158, 1); border-color: rgba(255, 163, 158, 1);
......
...@@ -5,20 +5,34 @@ ...@@ -5,20 +5,34 @@
<div class="left-title"> <div class="left-title">
<img src="./assets/icon01.png" alt="" /> <img src="./assets/icon01.png" alt="" />
<div class="tit">资助领域分布情况</div> <div class="tit">资助领域分布情况</div>
<div :class="radio1 === true ? 'btn-select' : 'btn'" style=" right:250px;" @click="changeradio1()"> <div :class="radio1 === true ? 'btn-select' : 'btn'" style=" right:250px;" @click="setRadio1(true)">
资助经费 资助经费
</div> </div>
<div :class="radio1 === false ? 'btn-select' : 'btn'" style=" right: 150px;" @click="changeradio1()"> <div :class="radio1 === false ? 'btn-select' : 'btn'" style=" right: 150px;" @click="setRadio1(false)">
资助项目 资助项目
</div> </div>
<el-select v-model="value1" placeholder="Select" class="select" style=" right: 31px;"> <el-select v-model="value1" placeholder="Select" class="select" style=" right: 31px;"
@change="handleLeft1YearChange">
<el-option v-for="item in options1" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in options1" :key="item.value" :label="item.label" :value="item.value" />
</el-select> </el-select>
</div> </div>
<div class="left-main"> <div class="left-main">
<div class="left-main-echarts" ref="leftChartRef" v-show="radio1 === true">资助经费</div> <div class="left-main-echarts" ref="leftChartRef" v-show="radio1 === true"></div>
<div class="left-main-echarts" ref="leftChartRef1" v-show="radio1 === false">资助项目</div> <div class="left-main-echarts" ref="leftChartRef1" v-show="radio1 === false"></div>
<el-empty v-show="!hasLeft1ChartData && !isLeft1Loading" class="datasub-el-empty" description="暂无数据"
:image-size="100" />
<div class="source" v-show="hasLeft1ChartData">
<TipTab :text="'资助领域分布情况,数据来源:美国国会官网'" />
</div>
<div class="chart-box" v-show="hasLeft1ChartData">
<div class="btn-box" v-if="!isShowAiContentLeft1" @mouseenter="handleSwitchAiLeft1(true)">
<AiButton />
</div>
<div class="content-box" v-else @mouseleave="handleSwitchAiLeft1(false)">
<AiPane :aiContent="aiContentLeft1" />
</div>
</div>
</div> </div>
</div> </div>
<div class="left"> <div class="left">
...@@ -31,6 +45,18 @@ ...@@ -31,6 +45,18 @@
</div> </div>
<div class="left-main1"> <div class="left-main1">
<div class="left-sankey-echarts" ref="leftSankeyRef"></div> <div class="left-sankey-echarts" ref="leftSankeyRef"></div>
<el-empty v-show="!hasLeft2ChartData" class="datasub-el-empty" description="暂无数据" :image-size="100" />
<div class="source" v-show="hasLeft2ChartData">
<TipTab :text="'机构资助领域情况,数据来源:美国国会官网'" />
</div>
<div class="chart-box" v-show="hasLeft2ChartData">
<div class="btn-box" v-if="!isShowAiContentLeft2" @mouseenter="handleSwitchAiLeft2(true)">
<AiButton />
</div>
<div class="content-box" v-else @mouseleave="handleSwitchAiLeft2(false)">
<AiPane :aiContent="aiContentLeft2" />
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
...@@ -39,33 +65,58 @@ ...@@ -39,33 +65,58 @@
<div class="right-title"> <div class="right-title">
<img src="./assets/icon02.png" alt="" /> <img src="./assets/icon02.png" alt="" />
<div class="tit">资助经费变化情况</div> <div class="tit">资助经费变化情况</div>
<div :class="radio2 === true ? 'btn-select' : 'btn'" style=" right:250px;" @click="changeradio2()"> <div :class="radio2 === true ? 'btn-select' : 'btn'" style=" right:250px;" @click="setRadio2(true)">
资助经费 资助经费
</div> </div>
<div :class="radio2 === false ? 'btn-select' : 'btn'" style=" right: 150px;" @click="changeradio2()"> <div :class="radio2 === false ? 'btn-select' : 'btn'" style=" right: 150px;" @click="setRadio2(false)">
资助项目 资助项目
</div> </div>
<el-select v-model="value" placeholder="Select" class="select"> <el-select v-model="value" placeholder="Select" class="select" @change="handleRight1RangeChange">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
</el-select> </el-select>
</div> </div>
<div class="right-main"> <div class="right-main">
<div class="right-main-echarts" ref="rightChartRef" v-show="radio2 === true"></div> <div class="right-main-echarts" ref="rightChartRef" v-show="radio2 === true"></div>
<div class="right-main-echarts" ref="rightChartRef1" v-show="radio2 === false"></div> <div class="right-main-echarts" ref="rightChartRef1" v-show="radio2 === false"></div>
<div class="right-main-tit">亿美元</div> <div class="right-main-tit" v-show="hasRight1ChartData">亿美元</div>
<el-empty v-show="!hasRight1ChartData && !isRight1Loading" class="datasub-el-empty" description="暂无数据"
:image-size="100" />
<div class="source" v-show="hasRight1ChartData">
<TipTab :text="'资助经费变化情况,数据来源:美国国会官网'" />
</div>
<div class="chart-box" v-show="hasRight1ChartData">
<div class="btn-box" v-if="!isShowAiContentRight1" @mouseenter="handleSwitchAiRight1(true)">
<AiButton />
</div>
<div class="content-box" v-else @mouseleave="handleSwitchAiRight1(false)">
<AiPane :aiContent="aiContentRight1" />
</div>
</div>
</div> </div>
</div> </div>
<div class="right"> <div class="right">
<div class="right-title"> <div class="right-title">
<img src="./assets/icon04.png" alt="" /> <img src="./assets/icon04.png" alt="" />
<div class="tit">项目资助强度分布</div> <div class="tit">项目资助强度分布</div>
<el-select v-model="value3" placeholder="Select" class="select"> <el-select v-model="value3" placeholder="Select" class="select" @change="handleRight2YearChange">
<el-option v-for="item in options1" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in options1" :key="item.value" :label="item.label" :value="item.value" />
</el-select> </el-select>
</div> </div>
<div class="right-main1"> <div class="right-main1">
<div class="right-boxplot-echarts" ref="boxplotChartRef"></div> <div class="right-boxplot-echarts" ref="boxplotChartRef"></div>
<div class="right-main1-tit">单位:亿美元</div> <div class="right-main1-tit" v-show="hasRight2ChartData">单位:亿美元</div>
<el-empty v-show="!hasRight2ChartData" class="datasub-el-empty" description="暂无数据" :image-size="100" />
<div class="source" v-show="hasRight2ChartData">
<TipTab :text="'项目资助强度分布,数据来源:美国国会官网'" />
</div>
<div class="chart-box" v-show="hasRight2ChartData">
<div class="btn-box" v-if="!isShowAiContentRight2" @mouseenter="handleSwitchAiRight2(true)">
<AiButton />
</div>
<div class="content-box" v-else @mouseleave="handleSwitchAiRight2(false)">
<AiPane :aiContent="aiContentRight2" />
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
...@@ -73,13 +124,31 @@ ...@@ -73,13 +124,31 @@
</template> </template>
<script setup> <script setup>
import { ref, onMounted, onBeforeUnmount, nextTick } from "vue"; import { ref, onMounted, onBeforeUnmount, nextTick, computed } from "vue";
import { getChartAnalysis } from "@/api/aiAnalysis";
import AiButton from "@/components/base/Ai/AiButton/index.vue";
import AiPane from "@/components/base/Ai/AiPane/index.vue";
import TipTab from "@/views/thinkTank/TipTab/index.vue";
import { import {
findFundField, findCountryProjectAreaList, getCountryFundingChange, getCountryFundProjectChange, getOrgFundsArea, getOrgFundStrength findFundField, findCountryProjectAreaList, getCountryFundingChange, getCountryFundProjectChange, getOrgFundsArea, getOrgFundStrength
} from "@/api/scientificFunding/overview"; } from "@/api/scientificFunding/overview";
import * as echarts from "echarts"; import * as echarts from "echarts";
const isNonEmptyArray = (v) => Array.isArray(v) && v.length > 0;
// 兼容后端多种返回结构:[] / {data:[]} / {content:[]} 等
const extractArrayData = (res) => {
const d = res?.data;
if (Array.isArray(d)) return d;
if (Array.isArray(d?.data)) return d.data;
if (Array.isArray(d?.content)) return d.content;
if (Array.isArray(d?.list)) return d.list;
return [];
};
const isSuccessCode = (res) => Number(res?.code) === 200;
const value = ref(10); const value = ref(10);
...@@ -107,54 +176,153 @@ const options1 = [ ...@@ -107,54 +176,153 @@ const options1 = [
label: "2024年" label: "2024年"
} }
]; ];
//获取当前时间x年前的日期 const normalizeYearParam = (val) => {
function getDateYearsAgo(years) { const y = Number(val);
// 获取当前日期 return Number.isFinite(y) ? y : val;
const currentDate = new Date(); };
// 计算指定年数之前的日期
const pastDate = new Date(currentDate.getFullYear() - years, currentDate.getMonth(), currentDate.getDate()); /** 资助经费变化情况:固定时间窗起点 */
// 格式化日期为 "YYYY-MM-DD" 的形式 const buildStartDateByRange = (rangeYears) => {
const year = pastDate.getFullYear(); const n = Number(rangeYears);
const month = String(pastDate.getMonth() + 1).padStart(2, "0"); // 月份从0开始,需要加1 if (n === 10) return "2015-01-01";
const day = String(pastDate.getDate()).padStart(2, "0"); if (n === 5) return "2020-01-01";
return `${year}-${month}-${day}`; // 兜底:保持原逻辑的“年初”
} const y = new Date().getFullYear() - (Number.isFinite(n) ? n : 0);
return `${y}-01-01`;
};
const radio1 = ref(true) const radio1 = ref(true)
const changeradio1 = () => { const setRadio1 = (val) => {
radio1.value = !radio1.value if (radio1.value === val) return;
} radio1.value = val;
// 切换模式:先清空当前模式数据与图表,再按当前年份重新拉数
if (val) {
left1RawFund.value = [];
if (leftChart) {
leftChart.dispose();
leftChart = null;
}
} else {
left1RawProject.value = [];
if (leftChart1) {
leftChart1.dispose();
leftChart1 = null;
}
}
handleLeft1YearChange();
// 切换显示后强制当前图表 resize,确保 canvas 尺寸稳定
nextTick(() => {
if (radio1.value) {
if (leftChart) leftChart.resize();
} else {
if (leftChart1) leftChart1.resize();
}
});
};
const value1 = ref(2025); const value1 = ref(2025);
const leftChartRef = ref(null); const leftChartRef = ref(null);
const leftChartRef1 = ref(null); const leftChartRef1 = ref(null);
const left1RawFund = ref([]);
const left1RawProject = ref([]);
const left1FundLoading = ref(false);
const left1ProjLoading = ref(false);
const hasLeft1ChartData = computed(() => {
return radio1.value ? isNonEmptyArray(left1RawFund.value) : isNonEmptyArray(left1RawProject.value);
});
const isLeft1Loading = computed(() => (radio1.value ? left1FundLoading.value : left1ProjLoading.value));
let left1FundReqSeq = 0;
let left1ProjReqSeq = 0;
const handleLeft1YearChange = () => {
// 根据当前“资助经费/资助项目”切换状态请求对应接口
if (radio1.value) {
handleGetFundField();
} else {
handleFindCountryProjectAreaList();
}
};
// 资助体系v2.0:资助领域分布情况:资助经费 // 资助体系v2.0:资助领域分布情况:资助经费
const handleGetFundField = async () => { const handleGetFundField = async () => {
const seq = ++left1FundReqSeq;
left1FundLoading.value = true;
try { try {
let params = { let params = {
year: value1.value year: normalizeYearParam(value1.value)
} }
const res = await findFundField(params); const res = await findFundField(params);
if (seq !== left1FundReqSeq) return;
console.log("资助领域分布情况", res); console.log("资助领域分布情况", res);
if (res.code === 200 && res.data) { if (isSuccessCode(res)) {
initLeftDonut(res.data, true) const list = extractArrayData(res);
left1RawFund.value = list;
if (list.length) {
await nextTick();
initLeftDonut(list, true)
} else if (leftChart) {
leftChart.dispose();
leftChart = null;
}
} else {
left1RawFund.value = [];
if (leftChart) {
leftChart.dispose();
leftChart = null;
}
} }
} catch (error) { } catch (error) {
if (seq !== left1FundReqSeq) return;
console.error("获取资助领域分布情况error", error); console.error("获取资助领域分布情况error", error);
left1RawFund.value = [];
if (leftChart) {
leftChart.dispose();
leftChart = null;
}
} finally {
if (seq === left1FundReqSeq) {
left1FundLoading.value = false;
}
} }
}; };
//资助体系v2.0:资助领域分布情况:资助项目 //资助体系v2.0:资助领域分布情况:资助项目
const handleFindCountryProjectAreaList = async () => { const handleFindCountryProjectAreaList = async () => {
const seq = ++left1ProjReqSeq;
left1ProjLoading.value = true;
try { try {
let params = { let params = {
year: value1.value year: normalizeYearParam(value1.value)
} }
const res = await findCountryProjectAreaList(params); const res = await findCountryProjectAreaList(params);
if (seq !== left1ProjReqSeq) return;
console.log("资助领域分布情况", res); console.log("资助领域分布情况", res);
if (res.code === 200 && res.data) { if (isSuccessCode(res)) {
initLeftDonut(res.data, false) const list = extractArrayData(res);
left1RawProject.value = list;
if (list.length) {
await nextTick();
initLeftDonut(list, false)
} else if (leftChart1) {
leftChart1.dispose();
leftChart1 = null;
}
} else {
left1RawProject.value = [];
if (leftChart1) {
leftChart1.dispose();
leftChart1 = null;
}
} }
} catch (error) { } catch (error) {
if (seq !== left1ProjReqSeq) return;
console.error("获取资助领域分布情况error", error); console.error("获取资助领域分布情况error", error);
left1RawProject.value = [];
if (leftChart1) {
leftChart1.dispose();
leftChart1 = null;
}
} finally {
if (seq === left1ProjReqSeq) {
left1ProjLoading.value = false;
}
} }
}; };
// 资助领域分布情况 // 资助领域分布情况
...@@ -208,68 +376,179 @@ const initLeftDonut = (rawData, show) => { ...@@ -208,68 +376,179 @@ const initLeftDonut = (rawData, show) => {
}; };
if (show == true) { if (show == true) {
if (leftChart) leftChart.dispose();
leftChart = echarts.init(leftChartRef.value); leftChart = echarts.init(leftChartRef.value);
leftChart.setOption(option); leftChart.setOption(option);
nextTick(() => leftChart && leftChart.resize());
} else { } else {
if (leftChart1) leftChart1.dispose();
leftChart1 = echarts.init(leftChartRef1.value); leftChart1 = echarts.init(leftChartRef1.value);
leftChart1.setOption(option); leftChart1.setOption(option);
nextTick(() => leftChart1 && leftChart1.resize());
} }
}; };
const rightChartRef = ref(null); const rightChartRef = ref(null);
const rightChartRef1 = ref(null); const rightChartRef1 = ref(null);
const right1RawFund = ref([]);
const right1RawProject = ref([]);
const right1FundLoading = ref(false);
const right1ProjLoading = ref(false);
const hasRight1ChartData = computed(() => {
return radio2.value ? isNonEmptyArray(right1RawFund.value) : isNonEmptyArray(right1RawProject.value);
});
const isRight1Loading = computed(() => (radio2.value ? right1FundLoading.value : right1ProjLoading.value));
const radio2 = ref(true) const radio2 = ref(true)
const changeradio2 = () => { const handleRight1RangeChange = () => {
radio2.value ? handlegetCountryFundingChange() : handlegetCountryFundProjectChange() // 根据当前“资助经费/资助项目”切换状态请求对应接口
radio2.value = !radio2.value if (radio2.value) {
} handlegetCountryFundingChange();
} else {
handlegetCountryFundProjectChange();
}
};
const setRadio2 = (val) => {
if (radio2.value === val) return;
radio2.value = val;
// 切换模式:先清空当前模式数据与图表,再按当前时间窗重新拉数
if (val) {
right1RawFund.value = [];
if (rightChart) {
rightChart.dispose();
rightChart = null;
}
} else {
right1RawProject.value = [];
if (rightChart1) {
rightChart1.dispose();
rightChart1 = null;
}
}
handleRight1RangeChange();
// 切换显示后强制当前图表 resize,确保 canvas 尺寸稳定
nextTick(() => {
if (radio2.value) {
if (rightChart) rightChart.resize();
} else {
if (rightChart1) rightChart1.resize();
}
});
};
// 资助体系v2.0:资助经费变化情况:资助经费 // 资助体系v2.0:资助经费变化情况:资助经费
const handlegetCountryFundingChange = async () => { const handlegetCountryFundingChange = async () => {
try { try {
right1FundLoading.value = true;
let params = { let params = {
startDate: getDateYearsAgo(value.value) startDate: buildStartDateByRange(value.value)
} }
const res = await getCountryFundingChange(params); const res = await getCountryFundingChange(params);
console.log("资助经费变化情况", res); console.log("资助经费变化情况", res);
if (res.code === 200 && res.data) { if (isSuccessCode(res)) {
initRightLine(res.data, true) const list = extractArrayData(res);
right1RawFund.value = list;
if (list.length) {
await nextTick();
initRightLine(list, true)
} else if (rightChart) {
rightChart.dispose();
rightChart = null;
}
} else {
right1RawFund.value = [];
if (rightChart) {
rightChart.dispose();
rightChart = null;
}
} }
} catch (error) { } catch (error) {
console.error("获取资助经费变化情况error", error); console.error("获取资助经费变化情况error", error);
right1RawFund.value = [];
if (rightChart) {
rightChart.dispose();
rightChart = null;
}
} finally {
right1FundLoading.value = false;
} }
}; };
//资助体系v2.0:资助经费变化情况:资助项目 //资助体系v2.0:资助经费变化情况:资助项目
const handlegetCountryFundProjectChange = async () => { const handlegetCountryFundProjectChange = async () => {
try { try {
right1ProjLoading.value = true;
let params = { let params = {
startDate: getDateYearsAgo(value.value) startDate: buildStartDateByRange(value.value)
} }
const res = await getCountryFundProjectChange(params); const res = await getCountryFundProjectChange(params);
console.log("资助项目变化情况", res); console.log("资助项目变化情况", res);
if (res.code === 200 && res.data) { if (isSuccessCode(res)) {
initRightLine(res.data) const list = extractArrayData(res);
right1RawProject.value = list;
if (list.length) {
await nextTick();
initRightLine(list)
} else if (rightChart1) {
rightChart1.dispose();
rightChart1 = null;
}
} else {
right1RawProject.value = [];
if (rightChart1) {
rightChart1.dispose();
rightChart1 = null;
}
} }
} catch (error) { } catch (error) {
console.error("获取资助项目变化情况error", error); console.error("获取资助项目变化情况error", error);
right1RawProject.value = [];
if (rightChart1) {
rightChart1.dispose();
rightChart1 = null;
}
} finally {
right1ProjLoading.value = false;
} }
}; };
//项目资助强度分布 //项目资助强度分布
const value3 = ref(2025); const value3 = ref(2025);
const boxplotChartRef = ref(null); const boxplotChartRef = ref(null);
const right2RawStrength = ref([]);
const hasRight2ChartData = computed(() => isNonEmptyArray(right2RawStrength.value));
const handleRight2YearChange = () => {
handlegetOrgFundStrength();
};
const handlegetOrgFundStrength = async () => { const handlegetOrgFundStrength = async () => {
try { try {
let params = { let params = {
year: value3.value year: normalizeYearParam(value3.value)
} }
const res = await getOrgFundStrength(params); const res = await getOrgFundStrength(params);
console.log("项目资助强度分布", res); console.log("项目资助强度分布", res);
if (res.code === 200 && res.data) { if (isSuccessCode(res)) {
initBoxPlot(res.data) const list = extractArrayData(res);
right2RawStrength.value = list;
if (list.length) {
await nextTick();
initBoxPlot(list)
} else if (boxplotChart) {
boxplotChart.dispose();
boxplotChart = null;
}
} else {
right2RawStrength.value = [];
if (boxplotChart) {
boxplotChart.dispose();
boxplotChart = null;
}
} }
} catch (error) { } catch (error) {
console.error("获取项目资助强度分布error", error); console.error("获取项目资助强度分布error", error);
right2RawStrength.value = [];
if (boxplotChart) {
boxplotChart.dispose();
boxplotChart = null;
}
} }
}; };
//项目资助强度分布 //项目资助强度分布
...@@ -420,11 +699,152 @@ const initBoxPlot = (data) => { ...@@ -420,11 +699,152 @@ const initBoxPlot = (data) => {
let leftChart; let leftChart;
let leftChart1; let leftChart1;
// let rightChart; let rightChart;
// let rightChart1; let rightChart1;
let leftSankey; let leftSankey;
let boxplotChart; let boxplotChart;
// ------- AI 解读(刷新后默认展开,行为对齐智库概览) -------
const isShowAiContentLeft1 = ref(true);
const isShowAiContentLeft2 = ref(true);
const isShowAiContentRight1 = ref(true);
const isShowAiContentRight2 = ref(true);
const aiContentLeft1 = ref("");
const aiContentLeft2 = ref("");
const aiContentRight1 = ref("");
const aiContentRight2 = ref("");
const isAiLoadingLeft1 = ref(false);
const isAiLoadingLeft2 = ref(false);
const isAiLoadingRight1 = ref(false);
const isAiLoadingRight2 = ref(false);
const appendAiInterpretationChunk = (targetRef, chunk, loadingText = "解读生成中…") => {
if (!chunk) return;
const current = String(targetRef.value || "");
const base = current === loadingText ? "" : current;
targetRef.value = base + String(chunk);
};
const getInterpretationTextFromChartResponse = (res) => {
const list = res?.data;
const first = Array.isArray(list) ? list[0] : null;
return (
first?.["解读"] ||
first?.["interpretation"] ||
first?.["analysis"] ||
first?.["content"] ||
""
);
};
const fetchChartInterpretationOnce = async (payload, targetRef, loadingRef) => {
if (loadingRef.value) return;
const hasValidContent =
targetRef.value &&
targetRef.value !== "解读生成中…" &&
targetRef.value !== "解读加载失败" &&
targetRef.value !== "暂无图表数据";
if (hasValidContent) return;
loadingRef.value = true;
targetRef.value = "解读生成中…";
try {
const res = await getChartAnalysis(
{ text: JSON.stringify(payload) },
{
onChunk: (chunk) => appendAiInterpretationChunk(targetRef, chunk)
}
);
const text = getInterpretationTextFromChartResponse(res);
targetRef.value = text || targetRef.value || "未返回有效解读内容";
} catch (e) {
console.error("图表解读请求失败", e);
targetRef.value = "解读加载失败";
} finally {
loadingRef.value = false;
}
};
const buildPayloadLeft1 = () => {
const raw = radio1.value ? left1RawFund.value : left1RawProject.value;
if (!Array.isArray(raw) || raw.length === 0) return null;
return {
type: "分布图",
name: radio1.value ? "资助领域分布情况-资助经费" : "资助领域分布情况-资助项目",
data: raw
};
};
const buildPayloadLeft2 = () => {
const raw = left2RawSankey.value;
if (!Array.isArray(raw) || raw.length === 0) return null;
return {
type: "桑基图",
name: "机构资助领域情况",
data: raw
};
};
const buildPayloadRight1 = () => {
const raw = radio2.value ? right1RawFund.value : right1RawProject.value;
if (!Array.isArray(raw) || raw.length === 0) return null;
return {
type: "折线图",
name: radio2.value ? "资助经费变化情况-资助经费" : "资助经费变化情况-资助项目",
data: raw
};
};
const buildPayloadRight2 = () => {
const raw = right2RawStrength.value;
if (!Array.isArray(raw) || raw.length === 0) return null;
return {
type: "箱线图",
name: "项目资助强度分布",
data: raw
};
};
const handleSwitchAiLeft1 = async (val) => {
isShowAiContentLeft1.value = val;
if (!val) return;
const payload = buildPayloadLeft1();
if (!payload) {
aiContentLeft1.value = "暂无图表数据";
return;
}
await fetchChartInterpretationOnce(payload, aiContentLeft1, isAiLoadingLeft1);
};
const handleSwitchAiLeft2 = async (val) => {
isShowAiContentLeft2.value = val;
if (!val) return;
const payload = buildPayloadLeft2();
if (!payload) {
aiContentLeft2.value = "暂无图表数据";
return;
}
await fetchChartInterpretationOnce(payload, aiContentLeft2, isAiLoadingLeft2);
};
const handleSwitchAiRight1 = async (val) => {
isShowAiContentRight1.value = val;
if (!val) return;
const payload = buildPayloadRight1();
if (!payload) {
aiContentRight1.value = "暂无图表数据";
return;
}
await fetchChartInterpretationOnce(payload, aiContentRight1, isAiLoadingRight1);
};
const handleSwitchAiRight2 = async (val) => {
isShowAiContentRight2.value = val;
if (!val) return;
const payload = buildPayloadRight2();
if (!payload) {
aiContentRight2.value = "暂无图表数据";
return;
}
await fetchChartInterpretationOnce(payload, aiContentRight2, isAiLoadingRight2);
};
//资助经费变化情况 //资助经费变化情况
...@@ -463,8 +883,10 @@ const initRightLine = (data, show) => { ...@@ -463,8 +883,10 @@ const initRightLine = (data, show) => {
name: orgName, name: orgName,
type: "line", type: "line",
data: values, data: values,
symbol: "none", smooth: true,
showSymbol: false, symbol: "emptyCircle",
showSymbol: true,
symbolSize: 6,
endLabel: { endLabel: {
show: true, show: true,
formatter: orgName, // 只显示 orgName formatter: orgName, // 只显示 orgName
...@@ -522,30 +944,55 @@ const initRightLine = (data, show) => { ...@@ -522,30 +944,55 @@ const initRightLine = (data, show) => {
}; };
if (show == true) { if (show == true) {
let rightChart = echarts.init(rightChartRef.value); if (rightChart) rightChart.dispose();
rightChart = echarts.init(rightChartRef.value);
rightChart.setOption(option); rightChart.setOption(option);
nextTick(() => rightChart && rightChart.resize());
} else { } else {
let rightChart1 = echarts.init(rightChartRef1.value); if (rightChart1) rightChart1.dispose();
rightChart1 = echarts.init(rightChartRef1.value);
rightChart1.setOption(option); rightChart1.setOption(option);
nextTick(() => rightChart1 && rightChart1.resize());
} }
}; };
const leftSankeyRef = ref(null); const leftSankeyRef = ref(null);
const value2 = ref(2025); const value2 = ref(2025);
const left2RawSankey = ref([]);
const hasLeft2ChartData = computed(() => isNonEmptyArray(left2RawSankey.value));
// 机构资助领域情况 // 机构资助领域情况
const handleGetOrgFundsArea = async () => { const handleGetOrgFundsArea = async () => {
try { try {
let params = { let params = {
year: value2.value year: normalizeYearParam(value2.value)
} }
const res = await getOrgFundsArea(params); const res = await getOrgFundsArea(params);
console.log("机构资助领域情况", res); console.log("机构资助领域情况", res);
if (res.code === 200 && res.data) { if (isSuccessCode(res)) {
initLeftSankey(res.data) const list = extractArrayData(res);
left2RawSankey.value = list;
if (list.length) {
await nextTick();
initLeftSankey(list)
} else if (leftSankey) {
leftSankey.dispose();
leftSankey = null;
}
} else {
left2RawSankey.value = [];
if (leftSankey) {
leftSankey.dispose();
leftSankey = null;
}
} }
} catch (error) { } catch (error) {
console.error("获取机构资助领域情况error", error); console.error("获取机构资助领域情况error", error);
left2RawSankey.value = [];
if (leftSankey) {
leftSankey.dispose();
leftSankey = null;
}
} }
}; };
//机构资助领域情况 //机构资助领域情况
...@@ -638,6 +1085,7 @@ const initLeftSankey = (data) => { ...@@ -638,6 +1085,7 @@ const initLeftSankey = (data) => {
}; };
leftSankey.setOption(option); leftSankey.setOption(option);
nextTick(() => leftSankey && leftSankey.resize());
}; };
...@@ -650,13 +1098,21 @@ const initLeftSankey = (data) => { ...@@ -650,13 +1098,21 @@ const initLeftSankey = (data) => {
// }; // };
onMounted(() => { onMounted(() => {
handleGetFundField() // 刷新后 AiPane 默认展开:先给出“解读生成中…”占位,再在数据到位后触发解读请求
handleFindCountryProjectAreaList() aiContentLeft1.value = "解读生成中…";
handlegetCountryFundingChange() aiContentLeft2.value = "解读生成中…";
handlegetCountryFundProjectChange() aiContentRight1.value = "解读生成中…";
handleGetOrgFundsArea() aiContentRight2.value = "解读生成中…";
handlegetOrgFundStrength()
// 先拉数据;每块数据到位后立即触发一次 AI 解读(不必等其它块完成)
void handleGetFundField().then(() => handleSwitchAiLeft1(true));
void handleFindCountryProjectAreaList();
void handlegetCountryFundingChange().then(() => handleSwitchAiRight1(true));
void handlegetCountryFundProjectChange();
void handleGetOrgFundsArea().then(() => handleSwitchAiLeft2(true));
void handlegetOrgFundStrength().then(() => handleSwitchAiRight2(true));
}); });
// onBeforeUnmount(() => { // onBeforeUnmount(() => {
// window.removeEventListener("resize", handleResize); // window.removeEventListener("resize", handleResize);
...@@ -746,18 +1202,24 @@ onMounted(() => { ...@@ -746,18 +1202,24 @@ onMounted(() => {
.left-main { .left-main {
width: 792px; width: 792px;
height: 412px; height: 412px;
padding: 52px 60px 78px 61px; box-sizing: border-box;
/* 对齐智库概览-数据总览内边距 */
padding: 24px 24px 65px 24px;
position: relative;
.left-main-echarts { .left-main-echarts {
width: 780px; width: 100%;
height: 350px; height: 100%;
} }
} }
.left-main1 { .left-main1 {
width: 792px; width: 792px;
height: 412px; height: 412px;
padding: 30px 30px 30px 30px; box-sizing: border-box;
/* 对齐智库概览-数据总览内边距 */
padding: 24px 24px 65px 24px;
position: relative;
.left-sankey-echarts { .left-sankey-echarts {
width: 100%; width: 100%;
...@@ -825,14 +1287,16 @@ onMounted(() => { ...@@ -825,14 +1287,16 @@ onMounted(() => {
.right-main { .right-main {
width: 792px; width: 792px;
height: 421px; height: 412px;
padding: 40px 5px 30px 22px; box-sizing: border-box;
/* 对齐智库概览-数据总览内边距 */
padding: 24px 24px 65px 24px;
position: relative; position: relative;
.right-main-echarts { .right-main-echarts {
/* 矢量 476 */ /* 矢量 476 */
width: 780px; width: 100%;
height: 350px; height: 100%;
} }
.right-main-tit { .right-main-tit {
...@@ -849,15 +1313,16 @@ onMounted(() => { ...@@ -849,15 +1313,16 @@ onMounted(() => {
.right-main1 { .right-main1 {
width: 792px; width: 792px;
height: 421px; height: 412px;
padding: 20px 20px; /* 对齐智库概览-数据总览内边距 */
padding: 24px 24px 65px 24px;
position: relative; position: relative;
box-sizing: border-box; box-sizing: border-box;
.right-boxplot-echarts { .right-boxplot-echarts {
width: 100%; width: 100%;
height: 100%; height: 323px;
min-height: 300px;
} }
.right-main1-tit { .right-main1-tit {
...@@ -876,6 +1341,50 @@ onMounted(() => { ...@@ -876,6 +1341,50 @@ onMounted(() => {
} }
} }
/* 数据总览内:TipTab 与 AI 解读(尽量复用智库概览的定位) */
.source {
position: absolute;
left: 24px;
bottom: 21px;
z-index: 2;
}
.chart-box {
position: absolute;
right: 0px;
bottom: 18px;
width: 74px;
height: 28px;
z-index: 3;
.btn-box {
width: 74px;
height: 28px;
}
.content-box {
width: 792px;
position: absolute;
right: 0;
bottom: -18px;
}
}
.datasub-el-empty {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
padding: 0;
margin: 0;
z-index: 5;
:deep(.el-empty__description) {
margin-top: 8px;
}
}
.btn { .btn {
position: absolute; position: absolute;
top: 11px; top: 11px;
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
{{ item.orgName }} {{ item.orgName }}
</div> </div>
</div> </div>
<div class="select-box"> <div class="reslib-sort-box">
<div class="paixu-btn" @click="handleSwithSort()"> <div class="paixu-btn" @click="handleSwithSort()">
<div class="icon1"> <div class="icon1">
<img v-if="sort" src="@/assets/icons/shengxu1.png" alt="" /> <img v-if="sort" src="@/assets/icons/shengxu1.png" alt="" />
...@@ -21,42 +21,41 @@ ...@@ -21,42 +21,41 @@
</div> </div>
<div class="main"> <div class="main">
<div class="left"> <div class="left">
<div class="left-ti1"></div> <div class="select-box">
<div class="left-ti2"></div> <div class="header">
<!-- <div class="left-title">项目经费</div> <div class="icon"></div>
<div class="left-content"> <div class="title">科技领域</div>
<div v-for="(item, i) in dataList" :key="item.id" class="left-item">
<input type="checkbox" checked />{{ item.name }}
</div> </div>
</div> --> <div class="select-main">
<div class="left-title cl1">涉及领域</div> <el-checkbox-group class="checkbox-group" :model-value="selectedAreaListModel"
<div class="left-content"> @change="handleAreaGroupChange">
<el-checkbox v-model="checkAll" :indeterminate="isIndeterminate" class="all-checkbox" <el-checkbox class="filter-checkbox all-checkbox" :label="RESOURCE_FILTER_ALL_AREA">
@change="handleCheckAllChange"> {{ RESOURCE_FILTER_ALL_AREA }}
全部领域
</el-checkbox> </el-checkbox>
<el-checkbox v-for="research in areaList" :key="research.id" v-model="selectedAreaList" :label="research.id" <el-checkbox v-for="research in areaList" :key="research.id" class="filter-checkbox" :label="research.id">
@change="handleCheckedAreaChange()" class="filter-checkbox">
{{ research.name }} {{ research.name }}
</el-checkbox> </el-checkbox>
<!-- <div v-for="(item, i) in areaList" :key="item.id" class="left-item"> </el-checkbox-group>
<input type="checkbox" :checked="i === 0" />{{ item.name }} </div>
</div> -->
</div> </div>
<div class="left-title cl1">发布时间</div> <div class="select-box">
<div class="left-content"> <div class="header">
<el-checkbox v-model="checkAllTime" class="all-checkbox" :indeterminate="isIndeterminateTime" <div class="icon"></div>
@change="handleCheckAllChangeTime"> <div class="title">发布时间</div>
全部时间 </div>
<div class="select-main">
<el-checkbox-group class="checkbox-group" :model-value="selectedPubTimeListModel"
@change="handleTimeGroupChange">
<el-checkbox class="filter-checkbox all-checkbox" :label="RESOURCE_FILTER_ALL_TIME">
{{ RESOURCE_FILTER_ALL_TIME }}
</el-checkbox> </el-checkbox>
<el-checkbox-group v-model="selectedPubTimeList"> <el-checkbox v-for="time in pubTimeList" :key="time.id" class="filter-checkbox" :label="time.id">
<el-checkbox v-for="time in pubTimeList" :key="time.id" :label="time.id" class="filter-checkbox"
@change="handleCheckedAreaChangeTime()">
{{ time.name }} {{ time.name }}
</el-checkbox> </el-checkbox>
</el-checkbox-group> </el-checkbox-group>
</div> </div>
</div> </div>
</div>
<div class="right"> <div class="right">
<div class="right-title"> <div class="right-title">
<img src="./assets/icon01.png" alt="" /> <img src="./assets/icon01.png" alt="" />
...@@ -68,29 +67,22 @@ ...@@ -68,29 +67,22 @@
<div class="right-item-title">{{ item.projectName }}</div> <div class="right-item-title">{{ item.projectName }}</div>
<div class="right-item-content">{{ item.abstractContent }}</div> <div class="right-item-content">{{ item.abstractContent }}</div>
<div class="right-item-pie"> <div class="right-item-pie">
<div v-for="(pie, i) in item.areaList" :key="i" class="right-item-pie-item" :class="{
cl1: pie === '新材料', <AreaTag v-for="(val, idx) in item.areaList" :key="idx" :tagName="val" />
cl2: pie === '人工智能',
cl3: pie === '量子科技',
cl4: pie === '能源',
cl5: pie === '生物科技',
cl6: pie === '航空航天'
}">
{{ pie }}
</div>
</div> </div>
<div class="right-item-time">{{ item.publicationDate }}</div> <div class="right-item-time">{{ item.publicationDate }}</div>
<div class="right-item-money" <div class="right-item-money"
:style="{ color: item.amount <= 1000 ? 'rgba(232, 189, 11, 1)' : item.amount <= 10000 ? 'rgba(255, 149, 77, 1)' : 'rgba(206, 79, 81, 1)' }"> :style="{ color: item.amount <= 1000 ? 'rgba(232, 189, 11, 1)' : item.amount <= 10000 ? 'rgba(255, 149, 77, 1)' : 'rgba(206, 79, 81, 1)' }">
{{ '$' + item.amount + '万' }}</div> {{ '$' + item.amount + '万' }}</div>
</div> </div>
<div class="page"> <div class="page">
<div class="count">{{ total }}</div> <div class="count">{{ total }}</div>
<el-pagination v-model:current-page="currentPage" :page-size="pageSize" :total="total" <el-pagination v-model:current-page="currentPage" :page-size="pageSize" :total="total"
layout="prev, pager, next" background @current-change="handlePageChange" /> layout="prev, pager, next" background @current-change="handlePageChange" />
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
...@@ -101,49 +93,35 @@ import { ref, onMounted } from "vue"; ...@@ -101,49 +93,35 @@ import { ref, onMounted } from "vue";
import { import {
getProjectListNew, geFundSourceOrg, getAreaType getProjectListNew, geFundSourceOrg, getAreaType
} from "@/api/scientificFunding/overview"; } from "@/api/scientificFunding/overview";
import {
RESOURCE_FILTER_ALL_AREA,
RESOURCE_FILTER_ALL_TIME,
RESOURCE_FILTER_EARLIER,
normalizeExclusiveAllOption,
stripAllAreaForRequest,
stripAllTimeForRequest,
isSelectionCoveringAllOptions,
expandEarlierNumericYears
} from "@/views/thinkTank/utils/resourceLibraryFilters";
/** 领域字典与接口 arealist 使用数字 id(1、2、3…) */
const normalizeAreaId = (id) => {
const n = Number(id);
return Number.isFinite(n) ? n : id;
};
/** 请求用:仅保留合法整数领域 id */
const toAreaIdListForRequest = (ids) => {
const list = Array.isArray(ids) ? ids : [];
return list
.map((id) => normalizeAreaId(id))
.filter((id) => typeof id === "number" && Number.isInteger(id));
};
const navList = ref([]); const navList = ref([]);
const activeItem = ref(""); const activeItem = ref("");
const areaList = ref([ const areaList = ref([]);
{
id: 1,
name: "全部领域"
},
{
id: 2,
name: "人工智能"
},
{
id: 3,
name: "集成电路"
},
{
id: 4,
name: "通信网络"
},
{
id: 5,
name: "量子科技"
},
{
id: 6,
name: "能源"
},
{
id: 7,
name: "生物科技"
},
{
id: 8,
name: "航空航天"
},
{
id: 9,
name: "海洋"
}
]);
// 来源机构列表 // 来源机构列表
...@@ -160,99 +138,97 @@ const handleGeFundSourceOrg = async () => { ...@@ -160,99 +138,97 @@ const handleGeFundSourceOrg = async () => {
} }
}; };
const checkAll = ref(false); const selectedAreaListModel = ref([RESOURCE_FILTER_ALL_AREA]);
const isIndeterminate = ref(true); const selectedPubTimeListModel = ref([RESOURCE_FILTER_ALL_TIME]);
const selectedAreaList = ref([]);
const handleAreaGroupChange = (val) => {
const handleCheckAllChange = val => { selectedAreaListModel.value = normalizeExclusiveAllOption(val, RESOURCE_FILTER_ALL_AREA).map((item) =>
// console.log(val, "handleCheckAllChange"); item === RESOURCE_FILTER_ALL_AREA ? item : normalizeAreaId(item)
if (val) { );
isIndeterminate.value = false;
selectedAreaList.value.length !== areaList.value.length
? (selectedAreaList.value = areaList.value.map(obj => obj.id))
: "";
} else {
selectedAreaList.value = [];
}
// selectedAreaList.value = val ? areaList : []
// isIndeterminate.value = false
handleGetProjectListNew(); handleGetProjectListNew();
}; };
const handleCheckedAreaChange = () => {
// console.log(selectedAreaList.value, "handleCheckedAreaChange"); const handleTimeGroupChange = (val) => {
console.log(selectedAreaList.value, "当前选中的领域"); selectedPubTimeListModel.value = normalizeExclusiveAllOption(val, RESOURCE_FILTER_ALL_TIME);
selectedAreaList.value.length !== areaList.value.length
? (isIndeterminate.value = true)
: ((checkAll.value = true), (isIndeterminate.value = false));
handleGetProjectListNew(); handleGetProjectListNew();
}; };
const pubTimeList = ref([ const pubTimeList = ref([
{ {
id: 2025, id: 2025,
name: "2025" name: "2025"
}, },
{ {
id: 2024, id: 2024,
name: "2024" name: "2024"
}, },
{ {
id: 2023, id: 2023,
name: "2023" name: "2023"
}, },
{ {
id: 2022, id: 2022,
name: "2022" name: "2022"
}, },
{ {
id: 2021, id: 2021,
name: "2021" name: "2021年"
},
{
id: RESOURCE_FILTER_EARLIER,
name: RESOURCE_FILTER_EARLIER
} }
// {
// id: "更早时间",
// name: "更早时间"
// }
]); ]);
const selectedPubTimeList = ref([""]);
const checkAllTime = ref(false); /** 选择「全部时间」时,yearlist 传 2000~2025 逐年 */
const isIndeterminateTime = ref(true); const YEAR_ALL_RANGE_START = 2000;
const YEAR_ALL_RANGE_END = 2025;
const buildYearlistForRequest = (selectedTimeModel) => {
const strippedTime = stripAllTimeForRequest(selectedTimeModel);
// 仅勾选「全部时间」、未选具体年份时,传 2000~2025 逐年
if (strippedTime.length === 0) {
const out = [];
for (let y = YEAR_ALL_RANGE_START; y <= YEAR_ALL_RANGE_END; y += 1) {
out.push(String(y));
}
return out;
}
const hasEarlier = strippedTime.includes(RESOURCE_FILTER_EARLIER);
const numericOnly = strippedTime.filter((id) => id !== RESOURCE_FILTER_EARLIER);
const strippedNums = numericOnly
.map((id) => Number(id))
.filter((n) => Number.isInteger(n));
// 勾选「更早」:展开为 2000~2020,并与已选数字年合并(可与其他年份同时选)
if (hasEarlier) {
const yearsSet = new Set(expandEarlierNumericYears());
strippedNums.forEach((n) => yearsSet.add(n));
return [...yearsSet]
.sort((a, b) => a - b)
.map((n) => String(n));
}
return strippedNums.map((n) => String(n));
};
const sort = ref(false); const sort = ref(false);
const handleSwithSort = () => { const handleSwithSort = () => {
sort.value = !sort.value; sort.value = !sort.value;
handleGetProjectListNew(); handleGetProjectListNew();
}; };
const handleCheckAllChangeTime = val => {
// console.log(val, "handleCheckAllChange");
if (val) {
isIndeterminateTime.value = false;
selectedPubTimeList.value.length !== pubTimeList.value.length
? (selectedPubTimeList.value = pubTimeList.value.map(obj => obj.id))
: "";
} else {
selectedPubTimeList.value = [];
}
// selectedAreaList.value = val ? areaList : []
// isIndeterminate.value = false
handleGetProjectListNew();
};
const handleCheckedAreaChangeTime = () => {
// console.log(selectedAreaList.value, "handleCheckedAreaChange");
console.log(selectedPubTimeList.value, "当前选中的时间");
selectedPubTimeList.value.length !== pubTimeList.value.length
? (isIndeterminateTime.value = true)
: ((checkAllTime.value = true), (isIndeterminateTime.value = false));
handleGetProjectListNew();
};
// 获取行业领域列表 // 获取行业领域列表
const handleGetAreaType = async () => { const handleGetAreaType = async () => {
try { try {
const res = await getAreaType(); const res = await getAreaType();
console.log("获取行业领域列表", res); console.log("获取行业领域列表", res);
if (res.code === 200 && res.data) { if (res.code === 200 && res.data) {
areaList.value = res.data areaList.value = res.data.map((row) => ({
...row,
id: normalizeAreaId(row.id)
}));
} }
} catch (error) { } catch (error) {
console.error("获取行业领域列表error", error); console.error("获取行业领域列表error", error);
...@@ -270,11 +246,22 @@ const handlePageChange = p => { ...@@ -270,11 +246,22 @@ const handlePageChange = p => {
// 资助体系v2.0:资助项目列表分页 // 资助体系v2.0:资助项目列表分页
const handleGetProjectListNew = async () => { const handleGetProjectListNew = async () => {
try { try {
const strippedArea = toAreaIdListForRequest(
stripAllAreaForRequest(selectedAreaListModel.value)
);
const allAreaIds = toAreaIdListForRequest(areaList.value.map((obj) => obj.id));
const arealist =
strippedArea.length === 0 || isSelectionCoveringAllOptions(strippedArea, allAreaIds)
? allAreaIds
: strippedArea;
const yearlist = buildYearlistForRequest(selectedPubTimeListModel.value);
let params = { let params = {
arealist: selectedAreaList.value, arealist,
currentPage: currentPage.value, currentPage: currentPage.value,
pageSize: 10, pageSize: 10,
yearlist: selectedPubTimeList.value.map(item => item.toString().trim()).filter(item => item !== ""), yearlist,
funSort: sort.value ? 'desc' : 'asc', funSort: sort.value ? 'desc' : 'asc',
orgId: activeItem.value orgId: activeItem.value
} }
...@@ -305,11 +292,10 @@ onMounted(async () => { ...@@ -305,11 +292,10 @@ onMounted(async () => {
.reslib-page { .reslib-page {
width: 1600px; width: 1600px;
height: 1565px;
position: relative;
.select-box { position: relative;
.reslib-sort-box {
width: 128px; width: 128px;
position: absolute; position: absolute;
top: 7px; top: 7px;
...@@ -370,15 +356,15 @@ onMounted(async () => { ...@@ -370,15 +356,15 @@ onMounted(async () => {
} }
.nav { .nav {
width: calc(100% - 100px);
height: 42px; height: 42px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between;
margin-bottom: 34px; margin-bottom: 34px;
.nav-item { .nav-item {
width: 100%;
text-align: center; text-align: center;
cursor: pointer; cursor: pointer;
padding: 8px 20px; padding: 8px 20px;
...@@ -397,133 +383,85 @@ onMounted(async () => { ...@@ -397,133 +383,85 @@ onMounted(async () => {
} }
} }
.select {
width: 128px;
position: absolute;
top: 7px;
right: 0px;
}
.main { .main {
width: 1600px; width: 1600px;
height: 1489px;
display: flex; display: flex;
margin-bottom: 100px;
.left { .left {
width: 300px; width: 360px;
margin-right: 16px; margin-right: 16px;
height: 100%;
padding-bottom: 24px;
box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1);
border-radius: 10px; border-radius: 10px;
background-color: #fff; box-shadow: 0px 0px 20px 0px rgba(94, 95, 95, 0.1);
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1); background: rgba(255, 255, 255, 1);
position: relative; position: relative;
.left-ti1 { .select-box {
width: 8px; margin-top: 16px;
height: 16px;
background-color: rgb(5, 95, 194);
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
position: absolute;
top: 17px;
left: 0px;
}
.left-ti2 { .header {
display: flex;
gap: 17px;
.icon {
margin-top: 4px;
width: 8px; width: 8px;
height: 16px; height: 16px;
background-color: rgb(5, 95, 194); background: var(--color-main-active);
border-top-right-radius: 3px; border-radius: 0 4px 4px 0;
border-bottom-right-radius: 3px;
position: absolute;
top: 207px;
left: 0px;
} }
.left-title { .title {
margin-left: 25px; height: 24px;
color: rgb(5, 95, 194); color: var(--color-main-active);
font-family: "Source Han Sans CN";
font-size: 16px; font-size: 16px;
font-weight: 700; font-weight: 700;
font-family: "Microsoft YaHei";
line-height: 24px; line-height: 24px;
margin-top: 13px; letter-spacing: 1px;
text-align: left;
}
} }
.left-content { .select-main {
width: 253px; margin-left: 24px;
// height: 132px; margin-top: 12px;
margin-left: 25px;
margin-top: 13px;
display: flex;
flex-wrap: wrap;
/* 允许内容换行 */
justify-content: space-between;
/* 两端对齐 */
.left-item {
white-space: nowrap;
/* 保持在一行内 */
overflow: hidden;
/* 隐藏超出部分 */
text-overflow: ellipsis;
/* 超出部分显示省略号 */
width: calc(50% - 8px);
/* 每个选项占一半宽度,减去间距 */
height: 30px;
margin-bottom: 4px;
font-size: 16px;
font-weight: 400;
font-family: "Microsoft YaHei";
line-height: 24px;
color: rgb(95, 101, 108);
input[type="checkbox"] { .checkbox-group {
-webkit-appearance: none; display: grid;
appearance: none; grid-template-columns: repeat(2, 160px);
width: 14px; gap: 8px 4px;
height: 14px;
margin-right: 8px;
border: 1px solid rgb(200, 204, 210);
border-radius: 4px;
background-color: #fff;
vertical-align: middle;
}
input[type="checkbox"]:checked { :deep(.all-checkbox) {
background-color: rgb(5, 95, 194); width: 160px;
border-top-right-radius: 3px; height: 24px;
border-bottom-right-radius: 3px; margin: 0;
margin-right: 17px;
} }
input[type="checkbox"]:checked::after { :deep(.filter-checkbox) {
content: ""; width: 160px;
display: block; height: 24px;
width: 4px; margin-right: 0 !important;
height: 8px;
margin: 1px auto 0;
border: 2px solid #fff;
border-top: none;
border-left: none;
transform: rotate(45deg);
} }
} }
} }
.cl1 {
margin-top: 21px;
} }
} }
.right { .right {
width: 1284px; width: 1224px;
height: 1489px;
border-radius: 10px; border-radius: 10px;
background-color: #fff; background-color: #fff;
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1); box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
.right-title { .right-title {
width: 1284px; width: 1224px;
height: 48px; height: 48px;
border-bottom: 1px solid rgb(235, 238, 242); border-bottom: 1px solid rgb(235, 238, 242);
position: relative; position: relative;
...@@ -550,13 +488,13 @@ onMounted(async () => { ...@@ -550,13 +488,13 @@ onMounted(async () => {
} }
.right-main { .right-main {
width: 1284px; width: 1224px;
height: 1441px;
padding: 19px 34px 20px 29px; padding: 19px 34px 20px 29px;
position: relative; position: relative;
.right-item { .right-item {
width: 1221px; width: 1161px;
height: 124px; height: 124px;
border-bottom: 1px solid rgb(234, 236, 238); border-bottom: 1px solid rgb(234, 236, 238);
margin-bottom: 8px; margin-bottom: 8px;
...@@ -588,7 +526,7 @@ onMounted(async () => { ...@@ -588,7 +526,7 @@ onMounted(async () => {
/* 隐藏超出部分 */ /* 隐藏超出部分 */
text-overflow: ellipsis; text-overflow: ellipsis;
/* 超出部分显示省略号 */ /* 超出部分显示省略号 */
width: 90%; width: 1112px;
/* 设置一个固定的宽度或百分比 */ /* 设置一个固定的宽度或百分比 */
position: absolute; position: absolute;
top: 44px; top: 44px;
...@@ -605,6 +543,7 @@ onMounted(async () => { ...@@ -605,6 +543,7 @@ onMounted(async () => {
top: 76px; top: 76px;
left: 56px; left: 56px;
display: flex; display: flex;
gap: 8px;
.right-item-pie-item { .right-item-pie-item {
padding: 2px 8px; padding: 2px 8px;
...@@ -677,15 +616,16 @@ onMounted(async () => { ...@@ -677,15 +616,16 @@ onMounted(async () => {
} }
.page { .page {
width: 1221px; width: 1161px;
height: 40px; height: 40px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
position: absolute;
bottom: 20px;
left: 20px; margin-top: 29px;
padding-left: 11px;
.count { .count {
font-size: 16px; font-size: 16px;
...@@ -749,7 +689,10 @@ onMounted(async () => { ...@@ -749,7 +689,10 @@ onMounted(async () => {
background-color: #fff; background-color: #fff;
} }
} }
} }
} }
} }
} }
......
...@@ -14,14 +14,8 @@ ...@@ -14,14 +14,8 @@
<div class="main-content" ref="containerRef"> <div class="main-content" ref="containerRef">
<div class="home-top-bg"></div> <div class="home-top-bg"></div>
<!-- 搜索栏部分 --> <!-- 搜索栏部分 -->
<SearchContainer <SearchContainer style="margin-bottom: 48px; height: fit-content" v-if="containerRef" :countInfo="countInfo"
style="margin-bottom: 48px; height: fit-content" placeholder="搜索科研资助实体、资助记录" :containerRef="containerRef" areaName="" />
v-if="containerRef"
:countInfo="countInfo"
placeholder="搜索科研资助实体、资助记录"
:containerRef="containerRef"
areaName=""
/>
<!-- <div class="search"> --> <!-- <div class="search"> -->
<!-- <div class="search-main"> <!-- <div class="search-main">
...@@ -78,7 +72,8 @@ ...@@ -78,7 +72,8 @@
<!-- </div> --> <!-- </div> -->
<!-- 6个数据 --> <!-- 6个数据 -->
<div class="data"> <div class="data">
<div v-for="(item, index) in dataList" :key="item.id" class="data-item"> <div v-for="(item, index) in dataList" :key="item.orgId || item.id" class="data-item"
@click="handleClickOrg(item)">
<img v-if="item.logoUrl && /\\.(jpe?g|png)$/i.test(item.logoUrl)" :src="item.logoUrl" alt="" /> <img v-if="item.logoUrl && /\\.(jpe?g|png)$/i.test(item.logoUrl)" :src="item.logoUrl" alt="" />
<img v-else src="./assets/images/nullcorpimg.png" alt="" /> <img v-else src="./assets/images/nullcorpimg.png" alt="" />
<div class="data-text-item"> <div class="data-text-item">
...@@ -91,28 +86,28 @@ ...@@ -91,28 +86,28 @@
</div> </div>
<!-- 最新动态 --> <!-- 最新动态 -->
<div class="newdata" id="position1"> <div class="newdata" id="position1">
<com-title title="最新动态" /> <com-title title="最新动态" style="width: 1600px;" />
<div class="newdata-main"> <div class="newdata-main">
<newData /> <newData />
</div> </div>
</div> </div>
<!-- 资讯要问 --> <!-- 资讯要问 -->
<div class="ask" id="position2"> <div class="ask" id="position2">
<com-title title="资讯要闻" /> <com-title title="资讯要闻" style="width: 1600px;" />
<div class="ask-main"> <div class="ask-main">
<askPage /> <askPage />
</div> </div>
</div> </div>
<!-- 数据总览 --> <!-- 数据总览 -->
<div class="datasub" id="position3"> <div class="datasub" id="position3">
<com-title title="数据总览" /> <com-title title="数据总览" style="width: 1600px;" />
<div class="datasub-main"> <div class="datasub-main">
<dataSub /> <dataSub />
</div> </div>
</div> </div>
<!-- 资源库 --> <!-- 资源库 -->
<div class="reslib" id="position4"> <div class="reslib" id="position4">
<com-title title="资源库" /> <com-title title="资源库" style="width: 1600px;" />
<div class="reslib-main"> <div class="reslib-main">
<resLib /> <resLib />
</div> </div>
...@@ -170,6 +165,21 @@ const handleBackHome = () => { ...@@ -170,6 +165,21 @@ const handleBackHome = () => {
path: "/overview" path: "/overview"
}); });
}; };
// 点击机构卡片跳转机构详情
const handleClickOrg = (item) => {
const orgId = item?.orgId;
if (!orgId) return;
// Institution 路由开启了 dynamicTitle,这里提前写入标题,避免沿用上一次的“白宫”等旧值
const title = item?.orgName || "";
window.sessionStorage.setItem("institutionTabName", title);
window.sessionStorage.setItem("curTabName", title);
const route = router.resolve({
path: "/institution",
query: { id: orgId, name: title }
});
window.open(route.href, "_blank");
};
// 固定数据 // 固定数据
const dataList = ref([ const dataList = ref([
{ {
...@@ -576,12 +586,12 @@ onMounted(async () => { ...@@ -576,12 +586,12 @@ onMounted(async () => {
.reslib { .reslib {
width: 1600px; width: 1600px;
height: 1633px;
margin: 0 auto 0px auto; margin: 0 auto 0px auto;
.reslib-main { .reslib-main {
width: 1600px; width: 1600px;
height: 1565px;
margin-top: 26px; margin-top: 26px;
} }
} }
......
...@@ -399,7 +399,8 @@ const reportAuthors = computed(() => { ...@@ -399,7 +399,8 @@ const reportAuthors = computed(() => {
// 点击报告作者头像,跳转到人物主页 // 点击报告作者头像,跳转到人物主页
// 与核心研究人员逻辑一致:核心依赖 personId,本页面依赖作者的 id(作为 personId 传入) // 与核心研究人员逻辑一致:核心依赖 personId,本页面依赖作者的 id(作为 personId 传入)
const handleClickReportAuthor = async (author) => { const handleClickReportAuthor = async (author) => {
const personId = author?.id;
const personId = author?.personId;
if (!personId) return; if (!personId) return;
......
...@@ -96,6 +96,7 @@ ...@@ -96,6 +96,7 @@
</div> </div>
<div class="divider" v-if="index !== hearingData.length - 1"></div> <div class="divider" v-if="index !== hearingData.length - 1"></div>
</div> </div>
</div> </div>
</div> </div>
<div class="right-footer"> <div class="right-footer">
...@@ -107,6 +108,7 @@ ...@@ -107,6 +108,7 @@
@current-change="handleCurrentChange" :current-page="currentPage" /> @current-change="handleCurrentChange" :current-page="currentPage" />
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
...@@ -287,6 +289,12 @@ const handleToReportDetail = item => { ...@@ -287,6 +289,12 @@ const handleToReportDetail = item => {
.main-content { .main-content {
display: flex; display: flex;
gap: 16px; gap: 16px;
height: 100%;
margin-bottom: 100px;
.left { .left {
width: 360px; width: 360px;
...@@ -299,6 +307,7 @@ const handleToReportDetail = item => { ...@@ -299,6 +307,7 @@ const handleToReportDetail = item => {
background: rgba(255, 255, 255, 1); background: rgba(255, 255, 255, 1);
position: relative; position: relative;
.select-research-box { .select-research-box {
width: 360px; width: 360px;
height: 100%; height: 100%;
...@@ -480,14 +489,20 @@ const handleToReportDetail = item => { ...@@ -480,14 +489,20 @@ const handleToReportDetail = item => {
.right { .right {
width: 1224px; width: 1224px;
height: 1377px;
.card-box { .card-box {
width: 100%;
height: 1248px; height: 100%;
display: flex; display: flex;
background: rgba(255, 255, 255, 1); background: rgba(255, 255, 255, 1);
box-sizing: border-box; box-sizing: border-box;
border: 1px solid rgba(234, 236, 238, 1); border: 1px solid rgba(234, 236, 238, 1);
...@@ -495,12 +510,15 @@ const handleToReportDetail = item => { ...@@ -495,12 +510,15 @@ const handleToReportDetail = item => {
box-shadow: 0px 0px 20px 0px rgba(94, 95, 95, 0.1); box-shadow: 0px 0px 20px 0px rgba(94, 95, 95, 0.1);
background: rgba(255, 255, 255, 1); background: rgba(255, 255, 255, 1);
.card-content { .card-content {
width: 1211px; width: 1211px;
height: 1067px;
margin-top: 33px;
margin-top: 33px;
margin-left: 37px; margin-left: 37px;
padding-bottom: 27px;
.card-item { .card-item {
width: 100%; width: 100%;
...@@ -585,8 +603,13 @@ const handleToReportDetail = item => { ...@@ -585,8 +603,13 @@ const handleToReportDetail = item => {
} }
}
.right-footer { .right-footer {
margin-top: 43px;
margin-top: 35px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
...@@ -601,7 +624,6 @@ const handleToReportDetail = item => { ...@@ -601,7 +624,6 @@ const handleToReportDetail = item => {
text-align: left; text-align: left;
} }
} }
}
} }
:deep(.el-checkbox) { :deep(.el-checkbox) {
......
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
<div class="right"> <div class="right">
<div class="card-box"> <div class="card-box">
<div class="card-content"> <div class="card-content">
<div v-for="(item, index) in hearingData" :key="item.id ?? index"> <div v-for="(item, index) in hearingData" :key="item.id ?? index">
<div class="card-item"> <div class="card-item">
<img class="card-item-img" :src="item.coverImgUrl" alt="report image" /> <img class="card-item-img" :src="item.coverImgUrl" alt="report image" />
...@@ -80,9 +81,10 @@ ...@@ -80,9 +81,10 @@
</div> </div>
<div class="divider" v-if="index !== hearingData.length - 1"></div> <div class="divider" v-if="index !== hearingData.length - 1"></div>
</div> </div>
</div>
</div> </div>
</div>
<div class="right-footer"> <div class="right-footer">
<div class="info"> <div class="info">
{{ hearingData.length }} 篇智库报告 {{ hearingData.length }} 篇智库报告
...@@ -92,6 +94,7 @@ ...@@ -92,6 +94,7 @@
@current-change="handlePageChange" :current-page="currentPage" /> @current-change="handlePageChange" :current-page="currentPage" />
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
...@@ -186,6 +189,7 @@ const handlePageChange = page => { ...@@ -186,6 +189,7 @@ const handlePageChange = page => {
.home-main-footer-main { .home-main-footer-main {
margin: 0 auto; margin: 0 auto;
margin-top: 36px; margin-top: 36px;
width: 1600px; width: 1600px;
display: flex; display: flex;
gap: 16px; gap: 16px;
...@@ -270,11 +274,11 @@ const handlePageChange = page => { ...@@ -270,11 +274,11 @@ const handlePageChange = page => {
.right { .right {
width: 1224px; width: 1224px;
height: 1377px;
.card-box { .card-box {
width: 100%; width: 100%;
height: 1134px;
display: flex; display: flex;
background: rgba(255, 255, 255, 1); background: rgba(255, 255, 255, 1);
box-sizing: border-box; box-sizing: border-box;
...@@ -282,16 +286,22 @@ const handlePageChange = page => { ...@@ -282,16 +286,22 @@ const handlePageChange = page => {
border-radius: 10px; border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(94, 95, 95, 0.1); box-shadow: 0px 0px 20px 0px rgba(94, 95, 95, 0.1);
padding-right: 36px; padding-right: 36px;
height: 100%;
.card-content { .card-content {
width: 1211px; width: 1211px;
height: 1067px;
margin-top: 33px; margin-top: 33px;
margin-left: 37px; margin-left: 37px;
padding-bottom: 27px;
} }
} }
.right-footer {
}
.right-footer {
margin-top: 43px; margin-top: 43px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
...@@ -306,7 +316,6 @@ const handlePageChange = page => { ...@@ -306,7 +316,6 @@ const handlePageChange = page => {
letter-spacing: 0px; letter-spacing: 0px;
text-align: left; text-align: left;
} }
}
} }
.card-item { .card-item {
......
...@@ -369,8 +369,9 @@ ...@@ -369,8 +369,9 @@
<ThinkTankCongressHearingOverview v-else-if="activeCate === '国会听证会'" :key="`congress-${resourceTabResetKey}`" <ThinkTankCongressHearingOverview v-else-if="activeCate === '国会听证会'" :key="`congress-${resourceTabResetKey}`"
:hearing-data="hearingData" :research-type-list="areaList" :research-time-list="pubTimeList" :hearing-data="hearingData" :research-type-list="areaList" :research-time-list="pubTimeList"
v-model:selectedAreaList="congressSelectedAreaList" v-model:selectedPubTimeList="congressSelectedPubTimeList" v-model:selectedAreaList="congressSelectedAreaList"
:total="congressTotal" :current-page="congressCurrentPage" @filter-change="handleCongressFilterChange" v-model:selectedPubTimeList="congressSelectedPubTimeList" :total="congressTotal"
:current-page="congressCurrentPage" @filter-change="handleCongressFilterChange"
@page-change="handleCongressCurrentChange" @report-click="handleToHearingDetail" /> @page-change="handleCongressCurrentChange" @report-click="handleToHearingDetail" />
<ThinkTankPolicyAdviceOverview v-else :key="`policy-${resourceTabResetKey}`" :research-type-list="areaList" <ThinkTankPolicyAdviceOverview v-else :key="`policy-${resourceTabResetKey}`" :research-type-list="areaList"
...@@ -2194,7 +2195,7 @@ const handleSearch = () => { ...@@ -2194,7 +2195,7 @@ const handleSearch = () => {
// 下钻至数据资源库 // 下钻至数据资源库
const handleToDataLibrary = (item) => { const handleToDataLibrary = (item) => {
if(!item.reportNumber) { if (!item.reportNumber) {
ElMessage.warning('当前智库没有相关报告!') ElMessage.warning('当前智库没有相关报告!')
return return
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论