Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
risk-monitor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蔡建
risk-monitor
Commits
1a528d62
提交
1a528d62
authored
4月 02, 2026
作者:
朱政
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat:美国科研资助体系概览页样式与功能
上级
ac2f6b40
流水线
#309
已通过 于阶段
in 1 分 26 秒
变更
13
流水线
1
显示空白字符变更
内嵌
并排
正在显示
13 个修改的文件
包含
899 行增加
和
401 行删除
+899
-401
overview.js
src/api/scientificFunding/overview.js
+15
-1
index.js
src/router/index.js
+3
-1
decree.js
src/router/modules/decree.js
+2
-1
index.vue
src/views/scientificFunding/components/askPage/index.vue
+8
-3
icon-black.png
...cientificFunding/components/dataNew/assets/icon-black.png
+0
-0
index.vue
src/views/scientificFunding/components/dataNew/index.vue
+28
-47
index.vue
src/views/scientificFunding/components/dataSub/index.vue
+582
-73
index.vue
src/views/scientificFunding/components/resLib/index.vue
+186
-243
index.vue
src/views/scientificFunding/index.vue
+25
-15
index.vue
src/views/thinkTank/CongressHearingView/index.vue
+2
-1
index.vue
...k/ThinkTankDetail/thinkDynamics/CongressHearing/index.vue
+29
-7
ThinkTankCongressHearingOverview.vue
...thinkTank/components/ThinkTankCongressHearingOverview.vue
+15
-6
index.vue
src/views/thinkTank/index.vue
+4
-3
没有找到文件。
src/api/scientificFunding/overview.js
浏览文件 @
1a528d62
...
...
@@ -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:资助项目列表分页
export
function
getProjectListNew
(
params
)
{
return
request
({
method
:
'GET'
,
url
:
`/api/fund/getProjectListNew`
,
params
params
:
normalizeProjectListQueryParams
(
params
)
})
}
src/router/index.js
浏览文件 @
1a528d62
...
...
@@ -70,7 +70,9 @@ router.beforeEach((to, from, next) => {
if
(
to
.
meta
.
dynamicTitle
)
{
console
.
log
(
'to'
,
to
);
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
{
document
.
title
=
to
.
meta
.
title
...
...
src/router/modules/decree.js
浏览文件 @
1a528d62
...
...
@@ -88,7 +88,8 @@ const decreeRoutes = [
component
:
Institution
,
meta
:
{
title
:
"行政机构主页"
,
dynamicTitle
:
true
dynamicTitle
:
true
,
titleStorageKey
:
"institutionTabName"
}
},
{
...
...
src/views/scientificFunding/components/askPage/index.vue
浏览文件 @
1a528d62
...
...
@@ -23,8 +23,8 @@
</div>
</div>
-->
<NewsList
:newsList=
"leftList"
@
more-click=
"handleToMoreNews"
img=
"newsImage"
title=
"newsTitle"
content=
"newsContent"
from=
"from"
/>
<MessageBubble
:messageList=
"rightList"
@
more
-click=
"handleToSocialDetail"
source=
"orgName"
content=
"remarks"
content=
"newsContent"
from=
"from"
@
item-click=
"item => gotoNewsDetail(item.newsId)"
/>
<MessageBubble
:messageList=
"rightList"
@
person
-click=
"handleToSocialDetail"
source=
"orgName"
content=
"remarks"
name=
"personName"
imageUrl=
"personImage"
>
</MessageBubble>
<!--
<div
class=
"right-box"
>
...
...
@@ -56,6 +56,7 @@
import
NewsList
from
"@/components/base/newsList/index.vue"
;
import
{
ref
,
onMounted
}
from
"vue"
;
import
{
useGotoNewsDetail
}
from
"@/router/modules/news"
;
import
{
getSocialMediaInfo
,
getNews
}
from
"@/api/scientificFunding/overview"
;
...
...
@@ -171,15 +172,19 @@ const handleToMoreNews = () => {
};
// 查看社交媒体详情
const
handleToSocialDetail
=
item
=>
{
const
personId
=
item
?.
personId
||
item
?.
id
;
if
(
!
personId
)
return
;
const
route
=
router
.
resolve
({
path
:
"/characterPage"
,
query
:
{
personId
:
item
.
id
personId
}
});
window
.
open
(
route
.
href
,
"_blank"
);
};
const
gotoNewsDetail
=
useGotoNewsDetail
();
onMounted
(
async
()
=>
{
handleNews
()
handleSocialMediaInfo
()
...
...
src/views/scientificFunding/components/dataNew/assets/icon-black.png
0 → 100644
浏览文件 @
1a528d62
17.6 KB
src/views/scientificFunding/components/dataNew/index.vue
浏览文件 @
1a528d62
...
...
@@ -21,23 +21,30 @@
<div
class=
"left-center-main-ul"
>
<ul>
<li>
<img
src=
"./assets/icon-black.png"
alt=
""
class=
"li-img"
/>
<span
class=
"ul-title"
>
投资主体:
</span>
<span
class=
"ul-content"
>
美国国家科学基金会
</span>
</li>
<li>
<img
src=
"./assets/icon-black.png"
alt=
""
class=
"li-img"
/>
<span
class=
"ul-title"
>
发布日期:
</span>
<span
class=
"ul-content"
>
{{
itemData
.
publicationDate
}}
</span>
</li>
<li>
<img
src=
"./assets/icon-black.png"
alt=
""
class=
"li-img"
/>
<span
class=
"ul-title"
>
资助经费:
</span>
<span
class=
"ul-content"
>
{{
itemData
.
amount
}}
</span>
</li>
<li>
<img
src=
"./assets/icon-black.png"
alt=
""
class=
"li-img"
/>
<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>
<img
src=
"./assets/icon-black.png"
alt=
""
class=
"li-img"
/>
<span
class=
"ul-title"
>
资助对象:
</span>
<span
class=
"ul-content"
>
{{
itemData
.
fromOrgNameList
.
join
(
','
)
}}
</span>
</li>
...
...
@@ -97,42 +104,7 @@ import {
import
router
from
"@/router"
;
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 () => {
height
:
175px
;
.left-center-main-title
{
margin-left
:
19
px
;
margin-left
:
22
px
;
margin-bottom
:
17px
;
font-size
:
20px
;
font-weight
:
700
;
...
...
@@ -305,6 +277,20 @@ onMounted(async () => {
width
:
100%
;
height
:
24px
;
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
{
display
:
inline-block
;
...
...
@@ -326,19 +312,14 @@ onMounted(async () => {
}
.ul-pie
{
display
:
inline-block
;
display
:
flex
;
gap
:
8px
;
box-sizing
:
border-box
;
padding
:
2px
8px
;
border
:
1px
solid
;
border-radius
:
4px
;
flex-direction
:
row
;
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
{
border-color
:
rgba
(
255
,
163
,
158
,
1
);
...
...
src/views/scientificFunding/components/dataSub/index.vue
浏览文件 @
1a528d62
...
...
@@ -5,20 +5,34 @@
<div
class=
"left-title"
>
<img
src=
"./assets/icon01.png"
alt=
""
/>
<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
: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>
<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-select>
</div>
<div
class=
"left-main"
>
<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=
"leftChartRef"
v-show=
"radio1 === true"
></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
class=
"left"
>
...
...
@@ -31,6 +45,18 @@
</div>
<div
class=
"left-main1"
>
<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>
...
...
@@ -39,33 +65,58 @@
<div
class=
"right-title"
>
<img
src=
"./assets/icon02.png"
alt=
""
/>
<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
: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>
<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-select>
</div>
<div
class=
"right-main"
>
<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-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
class=
"right"
>
<div
class=
"right-title"
>
<img
src=
"./assets/icon04.png"
alt=
""
/>
<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-select>
</div>
<div
class=
"right-main1"
>
<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>
...
...
@@ -73,13 +124,31 @@
</
template
>
<
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
{
findFundField
,
findCountryProjectAreaList
,
getCountryFundingChange
,
getCountryFundProjectChange
,
getOrgFundsArea
,
getOrgFundStrength
}
from
"@/api/scientificFunding/overview"
;
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
);
...
...
@@ -107,54 +176,153 @@ const options1 = [
label
:
"2024年"
}
];
//获取当前时间x年前的日期
function
getDateYearsAgo
(
years
)
{
// 获取当前日期
const
currentDate
=
new
Date
();
// 计算指定年数之前的日期
const
pastDate
=
new
Date
(
currentDate
.
getFullYear
()
-
years
,
currentDate
.
getMonth
(),
currentDate
.
getDate
());
// 格式化日期为 "YYYY-MM-DD" 的形式
const
year
=
pastDate
.
getFullYear
();
const
month
=
String
(
pastDate
.
getMonth
()
+
1
).
padStart
(
2
,
"0"
);
// 月份从0开始,需要加1
const
day
=
String
(
pastDate
.
getDate
()).
padStart
(
2
,
"0"
);
return
`
${
year
}
-
${
month
}
-
${
day
}
`
;
}
const
normalizeYearParam
=
(
val
)
=>
{
const
y
=
Number
(
val
);
return
Number
.
isFinite
(
y
)
?
y
:
val
;
};
/** 资助经费变化情况:固定时间窗起点 */
const
buildStartDateByRange
=
(
rangeYears
)
=>
{
const
n
=
Number
(
rangeYears
);
if
(
n
===
10
)
return
"2015-01-01"
;
if
(
n
===
5
)
return
"2020-01-01"
;
// 兜底:保持原逻辑的“年初”
const
y
=
new
Date
().
getFullYear
()
-
(
Number
.
isFinite
(
n
)
?
n
:
0
);
return
`
${
y
}
-01-01`
;
};
const
radio1
=
ref
(
true
)
const
changeradio1
=
()
=>
{
radio1
.
value
=
!
radio1
.
value
}
const
setRadio1
=
(
val
)
=>
{
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
leftChartRef
=
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:资助领域分布情况:资助经费
const
handleGetFundField
=
async
()
=>
{
const
seq
=
++
left1FundReqSeq
;
left1FundLoading
.
value
=
true
;
try
{
let
params
=
{
year
:
value1
.
value
year
:
normalizeYearParam
(
value1
.
value
)
}
const
res
=
await
findFundField
(
params
);
if
(
seq
!==
left1FundReqSeq
)
return
;
console
.
log
(
"资助领域分布情况"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
initLeftDonut
(
res
.
data
,
true
)
if
(
isSuccessCode
(
res
))
{
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
)
{
if
(
seq
!==
left1FundReqSeq
)
return
;
console
.
error
(
"获取资助领域分布情况error"
,
error
);
left1RawFund
.
value
=
[];
if
(
leftChart
)
{
leftChart
.
dispose
();
leftChart
=
null
;
}
}
finally
{
if
(
seq
===
left1FundReqSeq
)
{
left1FundLoading
.
value
=
false
;
}
}
};
//资助体系v2.0:资助领域分布情况:资助项目
const
handleFindCountryProjectAreaList
=
async
()
=>
{
const
seq
=
++
left1ProjReqSeq
;
left1ProjLoading
.
value
=
true
;
try
{
let
params
=
{
year
:
value1
.
value
year
:
normalizeYearParam
(
value1
.
value
)
}
const
res
=
await
findCountryProjectAreaList
(
params
);
if
(
seq
!==
left1ProjReqSeq
)
return
;
console
.
log
(
"资助领域分布情况"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
initLeftDonut
(
res
.
data
,
false
)
if
(
isSuccessCode
(
res
))
{
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
)
{
if
(
seq
!==
left1ProjReqSeq
)
return
;
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) => {
};
if
(
show
==
true
)
{
if
(
leftChart
)
leftChart
.
dispose
();
leftChart
=
echarts
.
init
(
leftChartRef
.
value
);
leftChart
.
setOption
(
option
);
nextTick
(()
=>
leftChart
&&
leftChart
.
resize
());
}
else
{
if
(
leftChart1
)
leftChart1
.
dispose
();
leftChart1
=
echarts
.
init
(
leftChartRef1
.
value
);
leftChart1
.
setOption
(
option
);
nextTick
(()
=>
leftChart1
&&
leftChart1
.
resize
());
}
};
const
rightChartRef
=
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
changeradio2
=
()
=>
{
radio2
.
value
?
handlegetCountryFundingChange
()
:
handlegetCountryFundProjectChange
()
radio2
.
value
=
!
radio2
.
value
}
const
handleRight1RangeChange
=
()
=>
{
// 根据当前“资助经费/资助项目”切换状态请求对应接口
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:资助经费变化情况:资助经费
const
handlegetCountryFundingChange
=
async
()
=>
{
try
{
right1FundLoading
.
value
=
true
;
let
params
=
{
startDate
:
getDateYearsAgo
(
value
.
value
)
startDate
:
buildStartDateByRange
(
value
.
value
)
}
const
res
=
await
getCountryFundingChange
(
params
);
console
.
log
(
"资助经费变化情况"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
initRightLine
(
res
.
data
,
true
)
if
(
isSuccessCode
(
res
))
{
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
)
{
console
.
error
(
"获取资助经费变化情况error"
,
error
);
right1RawFund
.
value
=
[];
if
(
rightChart
)
{
rightChart
.
dispose
();
rightChart
=
null
;
}
}
finally
{
right1FundLoading
.
value
=
false
;
}
};
//资助体系v2.0:资助经费变化情况:资助项目
const
handlegetCountryFundProjectChange
=
async
()
=>
{
try
{
right1ProjLoading
.
value
=
true
;
let
params
=
{
startDate
:
getDateYearsAgo
(
value
.
value
)
startDate
:
buildStartDateByRange
(
value
.
value
)
}
const
res
=
await
getCountryFundProjectChange
(
params
);
console
.
log
(
"资助项目变化情况"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
initRightLine
(
res
.
data
)
if
(
isSuccessCode
(
res
))
{
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
)
{
console
.
error
(
"获取资助项目变化情况error"
,
error
);
right1RawProject
.
value
=
[];
if
(
rightChart1
)
{
rightChart1
.
dispose
();
rightChart1
=
null
;
}
}
finally
{
right1ProjLoading
.
value
=
false
;
}
};
//项目资助强度分布
const
value3
=
ref
(
2025
);
const
boxplotChartRef
=
ref
(
null
);
const
right2RawStrength
=
ref
([]);
const
hasRight2ChartData
=
computed
(()
=>
isNonEmptyArray
(
right2RawStrength
.
value
));
const
handleRight2YearChange
=
()
=>
{
handlegetOrgFundStrength
();
};
const
handlegetOrgFundStrength
=
async
()
=>
{
try
{
let
params
=
{
year
:
value3
.
value
year
:
normalizeYearParam
(
value3
.
value
)
}
const
res
=
await
getOrgFundStrength
(
params
);
console
.
log
(
"项目资助强度分布"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
initBoxPlot
(
res
.
data
)
if
(
isSuccessCode
(
res
))
{
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
)
{
console
.
error
(
"获取项目资助强度分布error"
,
error
);
right2RawStrength
.
value
=
[];
if
(
boxplotChart
)
{
boxplotChart
.
dispose
();
boxplotChart
=
null
;
}
}
};
//项目资助强度分布
...
...
@@ -420,11 +699,152 @@ const initBoxPlot = (data) => {
let
leftChart
;
let
leftChart1
;
//
let rightChart;
//
let rightChart1;
let
rightChart
;
let
rightChart1
;
let
leftSankey
;
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) => {
name
:
orgName
,
type
:
"line"
,
data
:
values
,
symbol
:
"none"
,
showSymbol
:
false
,
smooth
:
true
,
symbol
:
"emptyCircle"
,
showSymbol
:
true
,
symbolSize
:
6
,
endLabel
:
{
show
:
true
,
formatter
:
orgName
,
// 只显示 orgName
...
...
@@ -522,30 +944,55 @@ const initRightLine = (data, show) => {
};
if
(
show
==
true
)
{
let
rightChart
=
echarts
.
init
(
rightChartRef
.
value
);
if
(
rightChart
)
rightChart
.
dispose
();
rightChart
=
echarts
.
init
(
rightChartRef
.
value
);
rightChart
.
setOption
(
option
);
nextTick
(()
=>
rightChart
&&
rightChart
.
resize
());
}
else
{
let
rightChart1
=
echarts
.
init
(
rightChartRef1
.
value
);
if
(
rightChart1
)
rightChart1
.
dispose
();
rightChart1
=
echarts
.
init
(
rightChartRef1
.
value
);
rightChart1
.
setOption
(
option
);
nextTick
(()
=>
rightChart1
&&
rightChart1
.
resize
());
}
};
const
leftSankeyRef
=
ref
(
null
);
const
value2
=
ref
(
2025
);
const
left2RawSankey
=
ref
([]);
const
hasLeft2ChartData
=
computed
(()
=>
isNonEmptyArray
(
left2RawSankey
.
value
));
// 机构资助领域情况
const
handleGetOrgFundsArea
=
async
()
=>
{
try
{
let
params
=
{
year
:
value2
.
value
year
:
normalizeYearParam
(
value2
.
value
)
}
const
res
=
await
getOrgFundsArea
(
params
);
console
.
log
(
"机构资助领域情况"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
initLeftSankey
(
res
.
data
)
if
(
isSuccessCode
(
res
))
{
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
)
{
console
.
error
(
"获取机构资助领域情况error"
,
error
);
left2RawSankey
.
value
=
[];
if
(
leftSankey
)
{
leftSankey
.
dispose
();
leftSankey
=
null
;
}
}
};
//机构资助领域情况
...
...
@@ -638,6 +1085,7 @@ const initLeftSankey = (data) => {
};
leftSankey
.
setOption
(
option
);
nextTick
(()
=>
leftSankey
&&
leftSankey
.
resize
());
};
...
...
@@ -650,13 +1098,21 @@ const initLeftSankey = (data) => {
// };
onMounted
(()
=>
{
handleGetFundField
()
handleFindCountryProjectAreaList
()
handlegetCountryFundingChange
()
handlegetCountryFundProjectChange
()
handleGetOrgFundsArea
()
handlegetOrgFundStrength
()
// 刷新后 AiPane 默认展开:先给出“解读生成中…”占位,再在数据到位后触发解读请求
aiContentLeft1
.
value
=
"解读生成中…"
;
aiContentLeft2
.
value
=
"解读生成中…"
;
aiContentRight1
.
value
=
"解读生成中…"
;
aiContentRight2
.
value
=
"解读生成中…"
;
// 先拉数据;每块数据到位后立即触发一次 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(() => {
// window.removeEventListener("resize", handleResize);
...
...
@@ -746,18 +1202,24 @@ onMounted(() => {
.left-main
{
width
:
792px
;
height
:
412px
;
padding
:
52px
60px
78px
61px
;
box-sizing
:
border-box
;
/* 对齐智库概览-数据总览内边距 */
padding
:
24px
24px
65px
24px
;
position
:
relative
;
.left-main-echarts
{
width
:
780px
;
height
:
350px
;
width
:
100%
;
height
:
100%
;
}
}
.left-main1
{
width
:
792px
;
height
:
412px
;
padding
:
30px
30px
30px
30px
;
box-sizing
:
border-box
;
/* 对齐智库概览-数据总览内边距 */
padding
:
24px
24px
65px
24px
;
position
:
relative
;
.left-sankey-echarts
{
width
:
100%
;
...
...
@@ -825,14 +1287,16 @@ onMounted(() => {
.right-main
{
width
:
792px
;
height
:
421px
;
padding
:
40px
5px
30px
22px
;
height
:
412px
;
box-sizing
:
border-box
;
/* 对齐智库概览-数据总览内边距 */
padding
:
24px
24px
65px
24px
;
position
:
relative
;
.right-main-echarts
{
/* 矢量 476 */
width
:
780px
;
height
:
350px
;
width
:
100%
;
height
:
100%
;
}
.right-main-tit
{
...
...
@@ -849,15 +1313,16 @@ onMounted(() => {
.right-main1
{
width
:
792px
;
height
:
421px
;
padding
:
20px
20px
;
height
:
412px
;
/* 对齐智库概览-数据总览内边距 */
padding
:
24px
24px
65px
24px
;
position
:
relative
;
box-sizing
:
border-box
;
.right-boxplot-echarts
{
width
:
100%
;
height
:
100%
;
min-height
:
300px
;
height
:
323px
;
}
.right-main1-tit
{
...
...
@@ -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
{
position
:
absolute
;
top
:
11px
;
...
...
src/views/scientificFunding/components/resLib/index.vue
浏览文件 @
1a528d62
...
...
@@ -6,7 +6,7 @@
{{
item
.
orgName
}}
</div>
</div>
<div
class=
"
selec
t-box"
>
<div
class=
"
reslib-sor
t-box"
>
<div
class=
"paixu-btn"
@
click=
"handleSwithSort()"
>
<div
class=
"icon1"
>
<img
v-if=
"sort"
src=
"@/assets/icons/shengxu1.png"
alt=
""
/>
...
...
@@ -21,42 +21,41 @@
</div>
<div
class=
"main"
>
<div
class=
"left"
>
<div
class=
"left-ti1"
></div>
<div
class=
"left-ti2"
></div>
<!--
<div
class=
"left-title"
>
项目经费
</div>
<div
class=
"left-content"
>
<div
v-for=
"(item, i) in dataList"
:key=
"item.id"
class=
"left-item"
>
<input
type=
"checkbox"
checked
/>
{{
item
.
name
}}
<div
class=
"select-box"
>
<div
class=
"header"
>
<div
class=
"icon"
></div>
<div
class=
"title"
>
科技领域
</div>
</div>
</div>
-->
<div
class=
"left-title cl1"
>
涉及领域
</div>
<div
class=
"left-content"
>
<el-checkbox
v-model=
"checkAll"
:indeterminate=
"isIndeterminate"
class=
"all-checkbox"
@
change=
"handleCheckAllChange"
>
全部领域
<div
class=
"select-main"
>
<el-checkbox-group
class=
"checkbox-group"
:model-value=
"selectedAreaListModel"
@
change=
"handleAreaGroupChange"
>
<el-checkbox
class=
"filter-checkbox all-checkbox"
:label=
"RESOURCE_FILTER_ALL_AREA"
>
{{
RESOURCE_FILTER_ALL_AREA
}}
</el-checkbox>
<el-checkbox
v-for=
"research in areaList"
:key=
"research.id"
v-model=
"selectedAreaList"
:label=
"research.id"
@
change=
"handleCheckedAreaChange()"
class=
"filter-checkbox"
>
<el-checkbox
v-for=
"research in areaList"
:key=
"research.id"
class=
"filter-checkbox"
:label=
"research.id"
>
{{
research
.
name
}}
</el-checkbox>
<!--
<div
v-for=
"(item, i) in areaList"
:key=
"item.id"
class=
"left-item"
>
<input
type=
"checkbox"
:checked=
"i === 0"
/>
{{
item
.
name
}}
</div>
-->
</el-checkbox-group>
</div>
</div>
<div
class=
"left-title cl1"
>
发布时间
</div>
<div
class=
"left-content"
>
<el-checkbox
v-model=
"checkAllTime"
class=
"all-checkbox"
:indeterminate=
"isIndeterminateTime"
@
change=
"handleCheckAllChangeTime"
>
全部时间
<div
class=
"select-box"
>
<div
class=
"header"
>
<div
class=
"icon"
></div>
<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-group
v-model=
"selectedPubTimeList"
>
<el-checkbox
v-for=
"time in pubTimeList"
:key=
"time.id"
:label=
"time.id"
class=
"filter-checkbox"
@
change=
"handleCheckedAreaChangeTime()"
>
<el-checkbox
v-for=
"time in pubTimeList"
:key=
"time.id"
class=
"filter-checkbox"
:label=
"time.id"
>
{{
time
.
name
}}
</el-checkbox>
</el-checkbox-group>
</div>
</div>
</div>
<div
class=
"right"
>
<div
class=
"right-title"
>
<img
src=
"./assets/icon01.png"
alt=
""
/>
...
...
@@ -68,29 +67,22 @@
<div
class=
"right-item-title"
>
{{
item
.
projectName
}}
</div>
<div
class=
"right-item-content"
>
{{
item
.
abstractContent
}}
</div>
<div
class=
"right-item-pie"
>
<div
v-for=
"(pie, i) in item.areaList"
:key=
"i"
class=
"right-item-pie-item"
:class=
"
{
cl1: pie === '新材料',
cl2: pie === '人工智能',
cl3: pie === '量子科技',
cl4: pie === '能源',
cl5: pie === '生物科技',
cl6: pie === '航空航天'
}">
{{
pie
}}
</div>
<AreaTag
v-for=
"(val, idx) in item.areaList"
:key=
"idx"
:tagName=
"val"
/>
</div>
<div
class=
"right-item-time"
>
{{
item
.
publicationDate
}}
</div>
<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
)'
}"
>
{{
'$'
+
item
.
amount
+
'万'
}}
</div>
</div>
<div
class=
"page"
>
<div
class=
"count"
>
共
{{
total
}}
项
</div>
<el-pagination
v-model:current-page=
"currentPage"
:page-size=
"pageSize"
:total=
"total"
layout=
"prev, pager, next"
background
@
current-change=
"handlePageChange"
/>
</div>
</div>
</div>
</div>
</div>
...
...
@@ -101,49 +93,35 @@ import { ref, onMounted } from "vue";
import
{
getProjectListNew
,
geFundSourceOrg
,
getAreaType
}
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
activeItem
=
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
:
"海洋"
}
]);
const
areaList
=
ref
([]);
// 来源机构列表
...
...
@@ -160,99 +138,97 @@ const handleGeFundSourceOrg = async () => {
}
};
const
checkAll
=
ref
(
false
);
const
isIndeterminate
=
ref
(
true
);
const
selectedAreaList
=
ref
([]);
const
handleCheckAllChange
=
val
=>
{
// console.log(val, "handleCheckAllChange");
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
const
selectedAreaListModel
=
ref
([
RESOURCE_FILTER_ALL_AREA
]);
const
selectedPubTimeListModel
=
ref
([
RESOURCE_FILTER_ALL_TIME
]);
const
handleAreaGroupChange
=
(
val
)
=>
{
selectedAreaListModel
.
value
=
normalizeExclusiveAllOption
(
val
,
RESOURCE_FILTER_ALL_AREA
).
map
((
item
)
=>
item
===
RESOURCE_FILTER_ALL_AREA
?
item
:
normalizeAreaId
(
item
)
);
handleGetProjectListNew
();
};
const
handleCheckedAreaChange
=
()
=>
{
// console.log(selectedAreaList.value, "handleCheckedAreaChange");
console
.
log
(
selectedAreaList
.
value
,
"当前选中的领域"
);
selectedAreaList
.
value
.
length
!==
areaList
.
value
.
length
?
(
isIndeterminate
.
value
=
true
)
:
((
checkAll
.
value
=
true
),
(
isIndeterminate
.
value
=
false
));
const
handleTimeGroupChange
=
(
val
)
=>
{
selectedPubTimeListModel
.
value
=
normalizeExclusiveAllOption
(
val
,
RESOURCE_FILTER_ALL_TIME
);
handleGetProjectListNew
();
};
const
pubTimeList
=
ref
([
{
id
:
2025
,
name
:
"2025"
name
:
"2025
年
"
},
{
id
:
2024
,
name
:
"2024"
name
:
"2024
年
"
},
{
id
:
2023
,
name
:
"2023"
name
:
"2023
年
"
},
{
id
:
2022
,
name
:
"2022"
name
:
"2022
年
"
},
{
id
:
2021
,
name
:
"2021"
name
:
"2021年"
},
{
id
:
RESOURCE_FILTER_EARLIER
,
name
:
RESOURCE_FILTER_EARLIER
}
// {
// id: "更早时间",
// name: "更早时间"
// }
]);
const
selectedPubTimeList
=
ref
([
""
]);
const
checkAllTime
=
ref
(
false
);
const
isIndeterminateTime
=
ref
(
true
);
/** 选择「全部时间」时,yearlist 传 2000~2025 逐年 */
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
handleSwithSort
=
()
=>
{
sort
.
value
=
!
sort
.
value
;
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
()
=>
{
try
{
const
res
=
await
getAreaType
();
console
.
log
(
"获取行业领域列表"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
areaList
.
value
=
res
.
data
areaList
.
value
=
res
.
data
.
map
((
row
)
=>
({
...
row
,
id
:
normalizeAreaId
(
row
.
id
)
}));
}
}
catch
(
error
)
{
console
.
error
(
"获取行业领域列表error"
,
error
);
...
...
@@ -270,11 +246,22 @@ const handlePageChange = p => {
// 资助体系v2.0:资助项目列表分页
const
handleGetProjectListNew
=
async
()
=>
{
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
=
{
arealist
:
selectedAreaList
.
value
,
arealist
,
currentPage
:
currentPage
.
value
,
pageSize
:
10
,
yearlist
:
selectedPubTimeList
.
value
.
map
(
item
=>
item
.
toString
().
trim
()).
filter
(
item
=>
item
!==
""
)
,
yearlist
,
funSort
:
sort
.
value
?
'desc'
:
'asc'
,
orgId
:
activeItem
.
value
}
...
...
@@ -305,11 +292,10 @@ onMounted(async () => {
.reslib-page
{
width
:
1600px
;
height
:
1565px
;
position
:
relative
;
.select-box
{
position
:
relative
;
.reslib-sort-box
{
width
:
128px
;
position
:
absolute
;
top
:
7px
;
...
...
@@ -370,15 +356,15 @@ onMounted(async () => {
}
.nav
{
width
:
calc
(
100%
-
100px
);
height
:
42px
;
display
:
flex
;
align-items
:
center
;
justify-content
:
space-between
;
margin-bottom
:
34px
;
.nav-item
{
width
:
100%
;
text-align
:
center
;
cursor
:
pointer
;
padding
:
8px
20px
;
...
...
@@ -397,133 +383,85 @@ onMounted(async () => {
}
}
.select
{
width
:
128px
;
position
:
absolute
;
top
:
7px
;
right
:
0px
;
}
.main
{
width
:
1600px
;
height
:
1489px
;
display
:
flex
;
margin-bottom
:
100px
;
.left
{
width
:
3
0
0px
;
width
:
3
6
0px
;
margin-right
:
16px
;
height
:
100%
;
padding-bottom
:
24px
;
box-sizing
:
border-box
;
border
:
1px
solid
rgba
(
234
,
236
,
238
,
1
);
border-radius
:
10px
;
b
ackground-color
:
#fff
;
b
ox-shadow
:
0px
0px
20px
0px
rgba
(
25
,
69
,
130
,
0
.
1
);
b
ox-shadow
:
0px
0px
20px
0px
rgba
(
94
,
95
,
95
,
0
.1
)
;
b
ackground
:
rgba
(
255
,
255
,
255
,
1
);
position
:
relative
;
.left-ti1
{
width
:
8px
;
height
:
16px
;
background-color
:
rgb
(
5
,
95
,
194
);
border-top-right-radius
:
3px
;
border-bottom-right-radius
:
3px
;
position
:
absolute
;
top
:
17px
;
left
:
0px
;
}
.select-box
{
margin-top
:
16px
;
.left-ti2
{
.header
{
display
:
flex
;
gap
:
17px
;
.icon
{
margin-top
:
4px
;
width
:
8px
;
height
:
16px
;
background-color
:
rgb
(
5
,
95
,
194
);
border-top-right-radius
:
3px
;
border-bottom-right-radius
:
3px
;
position
:
absolute
;
top
:
207px
;
left
:
0px
;
background
:
var
(
--
color-main-active
);
border-radius
:
0
4px
4px
0
;
}
.left-title
{
margin-left
:
25px
;
color
:
rgb
(
5
,
95
,
194
);
.title
{
height
:
24px
;
color
:
var
(
--
color-main-active
);
font-family
:
"Source Han Sans CN"
;
font-size
:
16px
;
font-weight
:
700
;
font-family
:
"Microsoft YaHei"
;
line-height
:
24px
;
margin-top
:
13px
;
letter-spacing
:
1px
;
text-align
:
left
;
}
}
.left-content
{
width
:
253px
;
// height: 132px;
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
);
.select-main
{
margin-left
:
24px
;
margin-top
:
12px
;
input
[
type
=
"checkbox"
]
{
-webkit-appearance
:
none
;
appearance
:
none
;
width
:
14px
;
height
:
14px
;
margin-right
:
8px
;
border
:
1px
solid
rgb
(
200
,
204
,
210
);
border-radius
:
4px
;
background-color
:
#fff
;
vertical-align
:
middle
;
}
.checkbox-group
{
display
:
grid
;
grid-template-columns
:
repeat
(
2
,
160px
);
gap
:
8px
4px
;
input
[
type
=
"checkbox"
]
:checked
{
background-color
:
rgb
(
5
,
95
,
194
);
border-top-right-radius
:
3px
;
border-bottom-right-radius
:
3px
;
margin-right
:
17px
;
:deep
(
.all-checkbox
)
{
width
:
160px
;
height
:
24px
;
margin
:
0
;
}
input
[
type
=
"checkbox"
]
:checked::after
{
content
:
""
;
display
:
block
;
width
:
4px
;
height
:
8px
;
margin
:
1px
auto
0
;
border
:
2px
solid
#fff
;
border-top
:
none
;
border-left
:
none
;
transform
:
rotate
(
45deg
);
:deep
(
.filter-checkbox
)
{
width
:
160px
;
height
:
24px
;
margin-right
:
0
!
important
;
}
}
}
.cl1
{
margin-top
:
21px
;
}
}
.right
{
width
:
12
8
4px
;
height
:
1489px
;
width
:
12
2
4px
;
border-radius
:
10px
;
background-color
:
#fff
;
box-shadow
:
0px
0px
20px
0px
rgba
(
25
,
69
,
130
,
0
.1
);
.right-title
{
width
:
12
8
4px
;
width
:
12
2
4px
;
height
:
48px
;
border-bottom
:
1px
solid
rgb
(
235
,
238
,
242
);
position
:
relative
;
...
...
@@ -550,13 +488,13 @@ onMounted(async () => {
}
.right-main
{
width
:
12
8
4px
;
height
:
1441px
;
width
:
12
2
4px
;
padding
:
19px
34px
20px
29px
;
position
:
relative
;
.right-item
{
width
:
1
22
1px
;
width
:
1
16
1px
;
height
:
124px
;
border-bottom
:
1px
solid
rgb
(
234
,
236
,
238
);
margin-bottom
:
8px
;
...
...
@@ -588,7 +526,7 @@ onMounted(async () => {
/* 隐藏超出部分 */
text-overflow
:
ellipsis
;
/* 超出部分显示省略号 */
width
:
90%
;
width
:
1112px
;
/* 设置一个固定的宽度或百分比 */
position
:
absolute
;
top
:
44px
;
...
...
@@ -605,6 +543,7 @@ onMounted(async () => {
top
:
76px
;
left
:
56px
;
display
:
flex
;
gap
:
8px
;
.right-item-pie-item
{
padding
:
2px
8px
;
...
...
@@ -677,15 +616,16 @@ onMounted(async () => {
}
.page
{
width
:
1
22
1px
;
width
:
1
16
1px
;
height
:
40px
;
display
:
flex
;
align-items
:
center
;
justify-content
:
space-between
;
position
:
absolute
;
bottom
:
20px
;
left
:
20px
;
padding-left
:
11px
;
margin-top
:
29px
;
.count
{
font-size
:
16px
;
...
...
@@ -749,7 +689,10 @@ onMounted(async () => {
background-color
:
#fff
;
}
}
}
}
}
}
...
...
src/views/scientificFunding/index.vue
浏览文件 @
1a528d62
...
...
@@ -14,14 +14,8 @@
<div
class=
"main-content"
ref=
"containerRef"
>
<div
class=
"home-top-bg"
></div>
<!-- 搜索栏部分 -->
<SearchContainer
style=
"margin-bottom: 48px; height: fit-content"
v-if=
"containerRef"
:countInfo=
"countInfo"
placeholder=
"搜索科研资助实体、资助记录"
:containerRef=
"containerRef"
areaName=
""
/>
<SearchContainer
style=
"margin-bottom: 48px; height: fit-content"
v-if=
"containerRef"
:countInfo=
"countInfo"
placeholder=
"搜索科研资助实体、资助记录"
:containerRef=
"containerRef"
areaName=
""
/>
<!--
<div
class=
"search"
>
-->
<!--
<div
class=
"search-main"
>
...
...
@@ -78,7 +72,8 @@
<!--
</div>
-->
<!-- 6个数据 -->
<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-else
src=
"./assets/images/nullcorpimg.png"
alt=
""
/>
<div
class=
"data-text-item"
>
...
...
@@ -91,28 +86,28 @@
</div>
<!-- 最新动态 -->
<div
class=
"newdata"
id=
"position1"
>
<com-title
title=
"最新动态"
/>
<com-title
title=
"最新动态"
style=
"width: 1600px;"
/>
<div
class=
"newdata-main"
>
<newData
/>
</div>
</div>
<!-- 资讯要问 -->
<div
class=
"ask"
id=
"position2"
>
<com-title
title=
"资讯要闻"
/>
<com-title
title=
"资讯要闻"
style=
"width: 1600px;"
/>
<div
class=
"ask-main"
>
<askPage
/>
</div>
</div>
<!-- 数据总览 -->
<div
class=
"datasub"
id=
"position3"
>
<com-title
title=
"数据总览"
/>
<com-title
title=
"数据总览"
style=
"width: 1600px;"
/>
<div
class=
"datasub-main"
>
<dataSub
/>
</div>
</div>
<!-- 资源库 -->
<div
class=
"reslib"
id=
"position4"
>
<com-title
title=
"资源库"
/>
<com-title
title=
"资源库"
style=
"width: 1600px;"
/>
<div
class=
"reslib-main"
>
<resLib
/>
</div>
...
...
@@ -170,6 +165,21 @@ const handleBackHome = () => {
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
([
{
...
...
@@ -576,12 +586,12 @@ onMounted(async () => {
.reslib
{
width
:
1600px
;
height
:
1633px
;
margin
:
0
auto
0px
auto
;
.reslib-main
{
width
:
1600px
;
height
:
1565px
;
margin-top
:
26px
;
}
}
...
...
src/views/thinkTank/CongressHearingView/index.vue
浏览文件 @
1a528d62
...
...
@@ -399,7 +399,8 @@ const reportAuthors = computed(() => {
// 点击报告作者头像,跳转到人物主页
// 与核心研究人员逻辑一致:核心依赖 personId,本页面依赖作者的 id(作为 personId 传入)
const
handleClickReportAuthor
=
async
(
author
)
=>
{
const
personId
=
author
?.
id
;
const
personId
=
author
?.
personId
;
if
(
!
personId
)
return
;
...
...
src/views/thinkTank/ThinkTankDetail/thinkDynamics/CongressHearing/index.vue
浏览文件 @
1a528d62
...
...
@@ -96,6 +96,7 @@
</div>
<div
class=
"divider"
v-if=
"index !== hearingData.length - 1"
></div>
</div>
</div>
</div>
<div
class=
"right-footer"
>
...
...
@@ -107,6 +108,7 @@
@
current-change=
"handleCurrentChange"
:current-page=
"currentPage"
/>
</div>
</div>
</div>
</div>
</
template
>
...
...
@@ -287,6 +289,12 @@ const handleToReportDetail = item => {
.main-content
{
display
:
flex
;
gap
:
16px
;
height
:
100%
;
margin-bottom
:
100px
;
.left
{
width
:
360px
;
...
...
@@ -299,6 +307,7 @@ const handleToReportDetail = item => {
background
:
rgba
(
255
,
255
,
255
,
1
);
position
:
relative
;
.select-research-box
{
width
:
360px
;
height
:
100%
;
...
...
@@ -480,14 +489,20 @@ const handleToReportDetail = item => {
.right
{
width
:
1224px
;
height
:
1377px
;
.card-box
{
width
:
100%
;
height
:
1248px
;
height
:
100%
;
display
:
flex
;
background
:
rgba
(
255
,
255
,
255
,
1
);
box-sizing
:
border-box
;
border
:
1px
solid
rgba
(
234
,
236
,
238
,
1
);
...
...
@@ -495,12 +510,15 @@ const handleToReportDetail = item => {
box-shadow
:
0px
0px
20px
0px
rgba
(
94
,
95
,
95
,
0
.1
);
background
:
rgba
(
255
,
255
,
255
,
1
);
.card-content
{
width
:
1211px
;
height
:
1067px
;
margin-top
:
33px
;
margin-top
:
33px
;
margin-left
:
37px
;
padding-bottom
:
27px
;
.card-item
{
width
:
100%
;
...
...
@@ -585,8 +603,13 @@ const handleToReportDetail = item => {
}
}
.right-footer
{
margin-top
:
43px
;
margin-top
:
35px
;
display
:
flex
;
justify-content
:
space-between
;
...
...
@@ -601,7 +624,6 @@ const handleToReportDetail = item => {
text-align
:
left
;
}
}
}
}
:deep
(
.el-checkbox
)
{
...
...
src/views/thinkTank/components/ThinkTankCongressHearingOverview.vue
浏览文件 @
1a528d62
...
...
@@ -58,6 +58,7 @@
<div
class=
"right"
>
<div
class=
"card-box"
>
<div
class=
"card-content"
>
<div
v-for=
"(item, index) in hearingData"
:key=
"item.id ?? index"
>
<div
class=
"card-item"
>
<img
class=
"card-item-img"
:src=
"item.coverImgUrl"
alt=
"report image"
/>
...
...
@@ -80,9 +81,10 @@
</div>
<div
class=
"divider"
v-if=
"index !== hearingData.length - 1"
></div>
</div>
</div>
</div>
</div>
<div
class=
"right-footer"
>
<div
class=
"info"
>
共
{{
hearingData
.
length
}}
篇智库报告
...
...
@@ -92,6 +94,7 @@
@
current-change=
"handlePageChange"
:current-page=
"currentPage"
/>
</div>
</div>
</div>
</div>
</
template
>
...
...
@@ -186,6 +189,7 @@ const handlePageChange = page => {
.home-main-footer-main
{
margin
:
0
auto
;
margin-top
:
36px
;
width
:
1600px
;
display
:
flex
;
gap
:
16px
;
...
...
@@ -270,11 +274,11 @@ const handlePageChange = page => {
.right
{
width
:
1224px
;
height
:
1377px
;
.card-box
{
width
:
100%
;
height
:
1134px
;
display
:
flex
;
background
:
rgba
(
255
,
255
,
255
,
1
);
box-sizing
:
border-box
;
...
...
@@ -282,16 +286,22 @@ const handlePageChange = page => {
border-radius
:
10px
;
box-shadow
:
0px
0px
20px
0px
rgba
(
94
,
95
,
95
,
0
.1
);
padding-right
:
36px
;
height
:
100%
;
.card-content
{
width
:
1211px
;
height
:
1067px
;
margin-top
:
33px
;
margin-left
:
37px
;
padding-bottom
:
27px
;
}
}
.right-footer
{
}
.right-footer
{
margin-top
:
43px
;
display
:
flex
;
justify-content
:
space-between
;
...
...
@@ -306,7 +316,6 @@ const handlePageChange = page => {
letter-spacing
:
0px
;
text-align
:
left
;
}
}
}
.card-item
{
...
...
src/views/thinkTank/index.vue
浏览文件 @
1a528d62
...
...
@@ -369,8 +369,9 @@
<ThinkTankCongressHearingOverview
v-else-if=
"activeCate === '国会听证会'"
:key=
"`congress-${resourceTabResetKey}`"
:hearing-data=
"hearingData"
:research-type-list=
"areaList"
:research-time-list=
"pubTimeList"
v-model:selectedAreaList=
"congressSelectedAreaList"
v-model:selectedPubTimeList=
"congressSelectedPubTimeList"
:total=
"congressTotal"
:current-page=
"congressCurrentPage"
@
filter-change=
"handleCongressFilterChange"
v-model:selectedAreaList=
"congressSelectedAreaList"
v-model:selectedPubTimeList=
"congressSelectedPubTimeList"
:total=
"congressTotal"
:current-page=
"congressCurrentPage"
@
filter-change=
"handleCongressFilterChange"
@
page-change=
"handleCongressCurrentChange"
@
report-click=
"handleToHearingDetail"
/>
<ThinkTankPolicyAdviceOverview
v-else
:key=
"`policy-${resourceTabResetKey}`"
:research-type-list=
"areaList"
...
...
@@ -2194,7 +2195,7 @@ const handleSearch = () => {
// 下钻至数据资源库
const
handleToDataLibrary
=
(
item
)
=>
{
if
(
!
item
.
reportNumber
)
{
if
(
!
item
.
reportNumber
)
{
ElMessage
.
warning
(
'当前智库没有相关报告!'
)
return
}
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论