Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
risk-monitor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蔡建
risk-monitor
Commits
29e42ed8
提交
29e42ed8
authored
3月 20, 2026
作者:
朱政
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat:多智库分析界面样式以及功能开发
上级
8055f9f1
全部展开
显示空白字符变更
内嵌
并排
正在显示
18 个修改的文件
包含
665 行增加
和
54 行删除
+665
-54
overview.js
src/api/thinkTank/overview.js
+36
-2
thinktank.js
src/router/modules/thinktank.js
+9
-6
analysisBox.vue
.../MultiThinkTankViewAnalysis/boxBackground/analysisBox.vue
+239
-0
overviewMainBox.vue
...tiThinkTankViewAnalysis/boxBackground/overviewMainBox.vue
+108
-0
overviewNormalBox.vue
...ThinkTankViewAnalysis/boxBackground/overviewNormalBox.vue
+90
-0
index.vue
src/views/thinkTank/MultiThinkTankViewAnalysis/index.vue
+0
-0
index.vue
src/views/thinkTank/ReportDetail/reportAnalysis/index.vue
+88
-20
worldCloudChart.js
...Tank/ReportDetail/reportAnalysis/utils/worldCloudChart.js
+16
-14
index.vue
src/views/thinkTank/allThinkTank/index.vue
+48
-10
down.png
src/views/thinkTank/assets/images/down.png
+0
-0
empty-image.png
src/views/thinkTank/assets/images/empty-image.png
+0
-0
minus.png
src/views/thinkTank/assets/images/minus.png
+0
-0
plus.png
src/views/thinkTank/assets/images/plus.png
+0
-0
rand-image.png
src/views/thinkTank/assets/images/rand-image.png
+0
-0
right-arrow-white.png
src/views/thinkTank/assets/images/right-arrow-white.png
+0
-0
right-arrow.png
src/views/thinkTank/assets/images/right-arrow.png
+0
-0
up.png
src/views/thinkTank/assets/images/up.png
+0
-0
index.vue
src/views/thinkTank/index.vue
+31
-2
没有找到文件。
src/api/thinkTank/overview.js
浏览文件 @
29e42ed8
...
@@ -120,10 +120,44 @@ export function getThinkDynamicsReportType() {
...
@@ -120,10 +120,44 @@ export function getThinkDynamicsReportType() {
//智库动态:获取智库报告
//智库动态:获取智库报告
export
function
getThinkDynamicsReport
(
params
)
{
export
function
getThinkDynamicsReport
(
params
)
{
const
safe
=
params
||
{}
// 兼容两种调用方式:
// 1) { id, startDate, authorName, currentPage, pageSize, researchTypeIds, searchText, sortFun, years }
// 2) { id, startDate, parmas: { authorName, currentPage, pageSize, researchTypeIds, searchText, sortFun, years } }
const
inner
=
safe
.
parmas
&&
typeof
safe
.
parmas
===
'object'
?
safe
.
parmas
:
{}
const
id
=
safe
.
id
const
startDate
=
safe
.
startDate
const
authorName
=
inner
.
authorName
??
safe
.
authorName
??
''
const
currentPage
=
inner
.
currentPage
??
safe
.
currentPage
??
1
const
pageSize
=
inner
.
pageSize
??
safe
.
pageSize
??
10
const
researchTypeIds
=
inner
.
researchTypeIds
??
safe
.
researchTypeIds
??
''
const
searchText
=
inner
.
searchText
??
safe
.
searchText
??
''
const
sortFun
=
inner
.
sortFun
??
safe
.
sortFun
??
false
const
years
=
inner
.
years
??
safe
.
years
??
null
const
query
=
{
currentPage
,
pageSize
,
sortFun
}
// 仅在有值时才传,避免后端按空值筛选
if
(
authorName
)
query
.
authorName
=
authorName
if
(
researchTypeIds
)
query
.
researchTypeIds
=
researchTypeIds
if
(
searchText
)
query
.
searchText
=
searchText
if
(
years
!==
null
&&
years
!==
undefined
&&
years
!==
''
)
query
.
years
=
years
return
request
({
return
request
({
method
:
'GET'
,
method
:
'GET'
,
url
:
`/api/thinkTankInfo/report/
${
params
.
id
}
/
${
params
.
startDate
}
`
,
url
:
`/api/thinkTankInfo/report/
${
id
}
/
${
startDate
}
`
,
params
:
params
.
parmas
params
:
query
})
}
// 智库领域观点分析(流式)
// [POST] 8.140.26.4:10029/report-domain-view-analysis
export
function
postReportDomainViewAnalysis
(
data
)
{
return
request
({
method
:
'POST'
,
// 开发环境走 Vite 同源代理,避免浏览器跨域(见 vite.config.js:/intelligent-api -> 8.140.26.4:10029)
url
:
'/intelligent-api/report-domain-view-analysis'
,
data
})
})
}
}
...
...
src/router/modules/thinktank.js
浏览文件 @
29e42ed8
...
@@ -4,6 +4,7 @@ const ThinkTankDetail = () => import('@/views/thinkTank/ThinkTankDetail/index.vu
...
@@ -4,6 +4,7 @@ const ThinkTankDetail = () => import('@/views/thinkTank/ThinkTankDetail/index.vu
const
ReportDetail
=
()
=>
import
(
'@/views/thinkTank/ReportDetail/index.vue'
)
const
ReportDetail
=
()
=>
import
(
'@/views/thinkTank/ReportDetail/index.vue'
)
const
ReportOriginal
=
()
=>
import
(
'@/views/thinkTank/reportOriginal/index.vue'
)
const
ReportOriginal
=
()
=>
import
(
'@/views/thinkTank/reportOriginal/index.vue'
)
const
allThinkTank
=
()
=>
import
(
'@/views/thinkTank/allThinkTank/index.vue'
)
const
allThinkTank
=
()
=>
import
(
'@/views/thinkTank/allThinkTank/index.vue'
)
const
MultiThinkTankViewAnalysis
=
()
=>
import
(
'@/views/thinkTank/MultiThinkTankViewAnalysis/index.vue'
)
const
thinktankRoutes
=
[
const
thinktankRoutes
=
[
// 智库系统的主要路由
// 智库系统的主要路由
...
@@ -37,17 +38,19 @@ const thinktankRoutes = [
...
@@ -37,17 +38,19 @@ const thinktankRoutes = [
path
:
"/thinkTank/reportOriginal/:id"
,
path
:
"/thinkTank/reportOriginal/:id"
,
name
:
"ReportOriginal"
,
name
:
"ReportOriginal"
,
component
:
ReportOriginal
,
component
:
ReportOriginal
,
// meta: {
// title: "报告原文"
// }
},
},
{
{
path
:
"/thinkTank/allThinkTank"
,
path
:
"/thinkTank/allThinkTank"
,
name
:
"allThinkTank"
,
name
:
"allThinkTank"
,
component
:
allThinkTank
,
component
:
allThinkTank
,
// meta: {
// title: "报告原文"
},
// }
{
path
:
"/thinkTank/MultiThinkTankViewAnalysis/:id"
,
name
:
"MultiThinkTankViewAnalysis"
,
component
:
MultiThinkTankViewAnalysis
,
},
},
]
]
...
...
src/views/thinkTank/MultiThinkTankViewAnalysis/boxBackground/analysisBox.vue
0 → 100644
浏览文件 @
29e42ed8
<
template
>
<div
class=
"analysis-box-wrapper"
:style=
"
{ width: width ? width : '100%', height: height ? height : '100%' }">
<div
class=
"wrapper-header"
>
<div
class=
"header-icon"
></div>
<div
class=
"header-title"
>
<div
v-if=
"title"
>
{{
title
}}
</div>
<slot
v-else
name=
"custom-title"
></slot>
</div>
<div
class=
"header-btn"
v-if=
"!showAllBtn"
>
<slot
name=
"header-btn"
></slot>
</div>
<div
class=
"header-btn1"
v-else
>
<slot
name=
"header-btn"
></slot>
</div>
<div
class=
"header-right"
>
<div
class=
"text-one"
:class=
"
{ 'is-active': activeView === 'consensus' }"
@click="handleTabChange('consensus')">
{{
"共识观点"
}}
</div>
<div
class=
"text-two"
:class=
"
{ 'is-active': activeView === 'divergence' }"
@click="handleTabChange('divergence')">
{{
"分歧观点"
}}
</div>
<div
class=
"header-right-btn"
@
click=
"handleSave"
v-if=
"showAllBtn"
>
<img
src=
"@/assets/icons/box-header-icon1.png"
alt=
""
>
</div>
<div
class=
"header-right-btn"
@
click=
"handleCollect"
>
<img
src=
"@/assets/icons/box-header-icon3.png"
alt=
""
>
</div>
</div>
</div>
<div
class=
"wrapper-main"
>
<slot></slot>
</div>
</div>
</
template
>
<
script
setup
>
import
{
ElMessage
}
from
'element-plus'
import
{
ref
,
computed
}
from
'vue'
const
props
=
defineProps
({
title
:
{
type
:
String
,
default
:
''
},
width
:
{
type
:
String
,
default
:
''
},
height
:
{
type
:
String
,
default
:
''
},
showAllBtn
:
{
type
:
Boolean
,
default
:
true
},
// 当业务功能尚未实现时,点击右上角图标仅弹出统一提示
devTip
:
{
type
:
Boolean
,
default
:
false
}
})
const
emit
=
defineEmits
([
'save'
,
'download'
,
'collect'
,
'tab-change'
])
// 共识/分歧:单选,默认共识观点
const
activeView
=
ref
(
'consensus'
)
const
handleTabChange
=
type
=>
{
activeView
.
value
=
type
emit
(
'tab-change'
,
type
)
}
const
handleSave
=
()
=>
{
if
(
props
.
devTip
)
{
ElMessage
.
warning
(
'当前功能正在开发中,敬请期待!'
)
return
}
ElMessage
.
success
(
'保存当前内容'
)
// emit('save')
}
const
handleDownload
=
()
=>
{
if
(
props
.
devTip
)
{
ElMessage
.
warning
(
'当前功能正在开发中,敬请期待!'
)
return
}
ElMessage
.
success
(
'下载当前内容'
)
// emit('download')
}
const
handleCollect
=
()
=>
{
if
(
props
.
devTip
)
{
ElMessage
.
warning
(
'当前功能正在开发中,敬请期待!'
)
return
}
ElMessage
.
success
(
'收藏当前内容'
)
// emit('collect')
}
</
script
>
<
style
lang=
"scss"
scoped
>
.analysis-box-wrapper
{
border
:
1px
solid
rgba
(
234
,
236
,
238
,
1
);
border-radius
:
10px
;
box-shadow
:
0px
0px
20px
0px
rgba
(
25
,
69
,
130
,
0
.1
);
background
:
rgba
(
255
,
255
,
255
,
1
);
.wrapper-header
{
height
:
45px
;
display
:
flex
;
padding-right
:
14px
;
align-items
:
center
;
box-sizing
:
border-box
;
.header-icon
{
width
:
8px
;
height
:
20px
;
background
:
var
(
--
color-main-active
);
border-radius
:
0
4px
4px
0
;
margin-right
:
14px
;
}
.header-title
{
flex
:
auto
;
width
:
20px
;
// color: var(--color-main-active);
// font-family: Source Han Sans CN;
// font-size: 20px;
// font-weight: 700;
// line-height: 26px;
// letter-spacing: 0px;
height
:
100%
;
&
>
div
{
height
:
100%
;
color
:
var
(
--
color-main-active
);
font-family
:
Microsoft
YaHei
;
font-size
:
20px
;
line-height
:
45px
;
font-weight
:
700
;
}
}
// .header-btn {
// display: flex;
// justify-content: flex-end;
// gap: 8px;
// }
// .header-btn1 {
// position: absolute;
// top: 14px;
// right: 116px;
// }
.header-right
{
height
:
28px
;
display
:
flex
;
justify-content
:
flex-end
;
gap
:
4px
;
.text-one
{
border
:
1px
solid
rgb
(
230
,
231
,
232
);
width
:
88px
;
height
:
32px
;
border-radius
:
4px
;
background-color
:
rgb
(
255
,
255
,
255
);
font-family
:
"Source Han Sans CN"
,
sans-serif
;
font-weight
:
400
;
font-size
:
18px
;
line-height
:
24px
;
letter-spacing
:
0px
;
text-align
:
left
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
cursor
:
pointer
;
&
.is-active
{
background-color
:
rgb
(
246
,
250
,
255
);
color
:
rgb
(
5
,
95
,
194
);
font-weight
:
700
;
border
:
1px
solid
rgb
(
5
,
95
,
194
);
}
}
.text-two
{
border
:
1px
solid
rgb
(
230
,
231
,
232
);
width
:
88px
;
height
:
32px
;
border-radius
:
4px
;
background-color
:
rgb
(
255
,
255
,
255
);
font-family
:
"Source Han Sans CN"
,
sans-serif
;
font-weight
:
400
;
font-size
:
18px
;
line-height
:
24px
;
letter-spacing
:
0px
;
text-align
:
left
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
cursor
:
pointer
;
&
.is-active
{
background-color
:
rgb
(
246
,
250
,
255
);
color
:
rgb
(
5
,
95
,
194
);
font-weight
:
700
;
border
:
1px
solid
rgb
(
5
,
95
,
194
);
}
}
.header-right-btn
{
width
:
28px
;
height
:
28px
;
cursor
:
pointer
;
img
{
width
:
100%
;
height
:
100%
;
}
}
}
}
.wrapper-main
{
height
:
calc
(
100%
-
45px
);
overflow
:
hidden
;
// overflow-y: auto;
padding
:
5px
auto
;
}
}
</
style
>
src/views/thinkTank/MultiThinkTankViewAnalysis/boxBackground/overviewMainBox.vue
0 → 100644
浏览文件 @
29e42ed8
<
template
>
<div
class=
"overview-main-box-wrapper"
:style=
"
{ width: width ? width : '1064px', height: height ? height : '450px' }">
<div
class=
"overview-main-box-header"
>
<div
class=
"header-left"
>
<div
class=
"header-icon"
>
<slot
name=
"header-icon"
></slot>
</div>
<div
class=
"header-title"
>
{{
title
}}
</div>
</div>
<div
class=
"header-right"
@
click=
"handleClickToDetail()"
>
{{
"查看详情 >"
}}
</div>
</div>
<div
class=
"wrapper-main"
>
<slot></slot>
</div>
</div>
</
template
>
<
script
setup
>
import
{
ref
,
computed
}
from
'vue'
const
emit
=
defineEmits
([
'toDetail'
])
const
props
=
defineProps
({
title
:
{
type
:
String
,
default
:
''
},
width
:
{
type
:
String
,
default
:
''
},
height
:
{
type
:
String
,
default
:
''
}
})
const
handleClickToDetail
=
()
=>
{
emit
(
'toDetail'
)
}
</
script
>
<
style
lang=
"scss"
scoped
>
.overview-main-box-wrapper
{
border
:
1px
solid
rgba
(
234
,
236
,
238
,
1
);
border-radius
:
10px
;
box-shadow
:
0px
0px
20px
0px
rgba
(
25
,
69
,
130
,
0
.1
);
background
:
rgba
(
255
,
255
,
255
,
1
);
position
:
relative
;
.overview-main-box-header
{
height
:
48px
;
border-bottom
:
1px
solid
rgba
(
240
,
242
,
244
,
1
);
display
:
flex
;
justify-content
:
space-between
;
box-sizing
:
border-box
;
.header-left
{
display
:
flex
;
.header-icon
{
width
:
24px
;
height
:
24px
;
margin-top
:
12px
;
margin-left
:
17px
;
}
.header-title
{
margin-left
:
19px
;
height
:
48px
;
padding
:
0
16px
;
background
:
var
(
--
color-main-active
);
color
:
#fff
;
font-family
:
Source
Han
Sans
CN
;
font-size
:
20px
;
font-weight
:
700
;
line-height
:
48px
;
text-align
:
center
;
}
}
.header-right
{
margin-right
:
27px
;
margin-top
:
12px
;
height
:
24px
;
color
:
rgba
(
20
,
89
,
187
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
400
;
line-height
:
24px
;
cursor
:
pointer
;
}
}
.wrapper-main
{
height
:
calc
(
100%
-
48px
);
overflow
:
hidden
;
// position: relative;
}
}
</
style
>
src/views/thinkTank/MultiThinkTankViewAnalysis/boxBackground/overviewNormalBox.vue
0 → 100644
浏览文件 @
29e42ed8
<
template
>
<div
class=
"overview-normal-box-wrapper"
:style=
"
{ width: width ? width : '1064px', height: height ? height : '460px' }">
<div
class=
"overview-normal-box-header"
>
<div
class=
"header-left"
>
<div
class=
"header-icon"
>
<slot
name=
"header-icon"
></slot>
</div>
<div
class=
"header-title"
>
{{
title
}}
</div>
</div>
<div
class=
"header-right"
>
<slot
name=
"header-right"
></slot>
</div>
</div>
<div
class=
"wrapper-main"
>
<slot></slot>
</div>
</div>
</
template
>
<
script
setup
>
import
{
ref
,
computed
}
from
'vue'
const
props
=
defineProps
({
title
:
{
type
:
String
,
default
:
''
},
width
:
{
type
:
String
,
default
:
''
},
height
:
{
type
:
String
,
default
:
''
}
})
</
script
>
<
style
lang=
"scss"
scoped
>
.overview-normal-box-wrapper
{
border
:
1px
solid
rgba
(
234
,
236
,
238
,
1
);
border-radius
:
10px
;
box-shadow
:
0px
0px
20px
0px
rgba
(
25
,
69
,
130
,
0
.1
);
background
:
rgba
(
255
,
255
,
255
,
1
);
position
:
relative
;
.overview-normal-box-header
{
height
:
48px
;
border-bottom
:
1px
solid
rgba
(
240
,
242
,
244
,
1
);
display
:
flex
;
justify-content
:
space-between
;
box-sizing
:
border-box
;
.header-left
{
display
:
flex
;
.header-icon
{
width
:
24px
;
height
:
24px
;
margin-top
:
14px
;
margin-left
:
19px
;
}
.header-title
{
margin-left
:
17px
;
height
:
48px
;
color
:
var
(
--
color-main-active
);
font-family
:
Source
Han
Sans
CN
;
font-size
:
20px
;
font-weight
:
700
;
line-height
:
48px
;
text-align
:
center
;
}
}
.header-right
{
height
:
48px
;
margin-right
:
28px
;
}
}
.wrapper-main
{
height
:
calc
(
100%
-
48px
);
overflow
:
hidden
;
}
}
</
style
>
src/views/thinkTank/MultiThinkTankViewAnalysis/index.vue
0 → 100644
浏览文件 @
29e42ed8
差异被折叠。
点击展开。
src/views/thinkTank/ReportDetail/reportAnalysis/index.vue
浏览文件 @
29e42ed8
...
@@ -37,18 +37,23 @@
...
@@ -37,18 +37,23 @@
<div
class=
"author-title"
>
报告作者:
</div>
<div
class=
"author-title"
>
报告作者:
</div>
<div
class=
"author-content"
>
<div
class=
"author-content"
>
<template
v-if=
"Array.isArray(reportAuthors) && reportAuthors.length"
>
<template
v-if=
"Array.isArray(reportAuthors) && reportAuthors.length"
>
<span
v-for=
"(author, idx) in reportAuthors"
:key=
"idx"
>
<span
v-if=
"reportAuthors.length === 1"
>
{{
author
.
name
}}
{{
reportAuthors
[
0
].
name
}}
<span
v-if=
"idx
<
reportAuthors
.
length
-
1
"
>
、
</span>
</span>
</span>
<!-- 多个作者:显示第一个 + 等 -->
<span
v-else
>
{{
reportAuthors
[
0
].
name
}}
等
</span>
</
template
>
</
template
>
</div>
</div>
</div>
</div>
</div>
</div>
<div
class=
"author-box"
v-for=
"(author, idx) in reportAuthors"
:key=
"idx"
<div
class=
"author-box"
>
<div
class=
"author-item"
v-for=
"(author, idx) in reportAuthors"
:key=
"idx"
v-if=
"Array.isArray(reportAuthors) && reportAuthors.length"
>
v-if=
"Array.isArray(reportAuthors) && reportAuthors.length"
>
<div
class=
"author-item"
>
<div
class=
"image"
><img
:src=
"author.avatar"
alt=
""
/></div>
<div
class=
"image"
><img
:src=
"author.avatar"
:alt=
"reportAuthors[0].name"
/></div>
<div
class=
"author-text"
>
<div
class=
"author-text"
>
<div
class=
"author-name"
>
{{ author.name }}
</div>
<div
class=
"author-name"
>
{{ author.name }}
</div>
<div
class=
"author-position"
>
{{ author.job }}
</div>
<div
class=
"author-position"
>
{{ author.job }}
</div>
...
@@ -58,6 +63,13 @@
...
@@ -58,6 +63,13 @@
</div>
</div>
</AnalysisBox>
</AnalysisBox>
</div>
</div>
<div
class=
"box5"
>
<AnalysisBox
title=
"报告关键词云"
:showAllBtn=
"true"
>
<div
class=
"box5-main"
>
<div
id=
"box5Chart"
></div>
</div>
</AnalysisBox>
</div>
<div
class=
"box2"
>
<div
class=
"box2"
>
<!-- <div class="box-header">
<!-- <div class="box-header">
<div class="header-left"></div>
<div class="header-left"></div>
...
@@ -94,7 +106,7 @@
...
@@ -94,7 +106,7 @@
</div>
</div>
</div>
</div>
</div>
</div>
<div
class=
"box2-btn"
>
<div
class=
"box2-btn"
@
click=
"goToAllThinkTank"
>
<div
class=
"btn-text"
>
<div
class=
"btn-text"
>
多智库报告观点汇聚分析
多智库报告观点汇聚分析
</div>
</div>
...
@@ -185,7 +197,7 @@
...
@@ -185,7 +197,7 @@
<
script
setup
>
<
script
setup
>
import
WarningPane
from
"@/components/base/WarningPane/index.vue"
import
WarningPane
from
"@/components/base/WarningPane/index.vue"
import
SearchContainer
from
"@/components/SearchContainer.vue"
;
import
SearchContainer
from
"@/components/SearchContainer.vue"
;
import
{
ref
,
onMounted
,
computed
,
defineProps
}
from
"vue"
;
import
{
ref
,
onMounted
,
computed
,
defineProps
,
nextTick
}
from
"vue"
;
import
setChart
from
"@/utils/setChart"
;
import
setChart
from
"@/utils/setChart"
;
import
getWordCloudChart
from
"./utils/worldCloudChart"
;
import
getWordCloudChart
from
"./utils/worldCloudChart"
;
import
{
import
{
...
@@ -197,9 +209,20 @@ import {
...
@@ -197,9 +209,20 @@ import {
}
from
"@/api/thinkTank/overview"
;
}
from
"@/api/thinkTank/overview"
;
import
{
getChartAnalysis
}
from
"@/api/aiAnalysis/index"
;
import
{
getChartAnalysis
}
from
"@/api/aiAnalysis/index"
;
import
{
useRouter
}
from
"vue-router"
;
import
{
useRouter
}
from
"vue-router"
;
const
router
=
useRouter
();
import
"echarts-wordcloud"
;
import
"echarts-wordcloud"
;
const
router
=
useRouter
();
const
goToAllThinkTank
=
()
=>
{
const
thinkTankId
=
props
?.
thinkInfo
?.
thinkTankId
||
props
?.
thinkInfo
?.
id
;
const
route
=
router
.
resolve
({
name
:
"MultiThinkTankViewAnalysis"
,
params
:
{
id
:
thinkTankId
}
});
window
.
open
(
route
.
href
,
"_blank"
);
};
const
props
=
defineProps
({
const
props
=
defineProps
({
thinkInfo
:
{
thinkInfo
:
{
type
:
Object
,
type
:
Object
,
...
@@ -321,6 +344,8 @@ const box2Data = ref([
...
@@ -321,6 +344,8 @@ const box2Data = ref([
// value: 89
// value: 89
// }
// }
]);
]);
// 报告关键词云
const
box5Data
=
ref
([]);
//获取科技领域词云
//获取科技领域词云
const
handleGetThinkTankReportIndustryCloud
=
async
()
=>
{
const
handleGetThinkTankReportIndustryCloud
=
async
()
=>
{
...
@@ -332,19 +357,22 @@ const handleGetThinkTankReportIndustryCloud = async () => {
...
@@ -332,19 +357,22 @@ const handleGetThinkTankReportIndustryCloud = async () => {
const
res
=
await
getThinkTankReportIndustryCloud
(
params
);
const
res
=
await
getThinkTankReportIndustryCloud
(
params
);
console
.
log
(
"科技领域词云"
,
res
);
console
.
log
(
"科技领域词云"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
if
(
res
.
code
===
200
&&
res
.
data
)
{
const
data
=
[];
const
data
=
(
res
.
data
||
[]).
map
(
item
=>
({
res
.
data
.
map
(
item
=>
{
data
.
push
({
name
:
item
.
clause
,
name
:
item
.
clause
,
value
:
item
.
count
value
:
item
.
count
});
}));
box2Data
.
value
=
data
;
// 该接口数据用于「报告关键词云」
const
box2Chart
=
getWordCloudChart
(
box2Data
.
value
);
box5Data
.
value
=
data
;
setChart
(
box2Chart
,
"box2Chart"
);
});
await
nextTick
();
const
box5Chart
=
getWordCloudChart
(
box5Data
.
value
);
setChart
(
box5Chart
,
"box5Chart"
);
}
else
{
box5Data
.
value
=
[];
}
}
}
catch
(
error
)
{
}
catch
(
error
)
{
console
.
error
(
"获取科技领域词云error"
,
error
);
console
.
error
(
"获取科技领域词云error"
,
error
);
box5Data
.
value
=
[];
}
}
};
};
//涉及科技领域
//涉及科技领域
...
@@ -575,7 +603,7 @@ onMounted(() => {
...
@@ -575,7 +603,7 @@ onMounted(() => {
}
}
.author
{
.author
{
height
:
24px
;
display
:
flex
;
display
:
flex
;
gap
:
4px
;
gap
:
4px
;
...
@@ -607,9 +635,18 @@ onMounted(() => {
...
@@ -607,9 +635,18 @@ onMounted(() => {
.author-box
{
.author-box
{
width
:
437px
;
width
:
437px
;
height
:
220px
;
height
:
auto
;
/* 改为自适应高度,不要固定 220px */
max-height
:
220px
;
margin-top
:
34px
;
margin-top
:
34px
;
margin-left
:
18px
;
margin-left
:
18px
;
display
:
grid
;
grid-template-columns
:
1fr
1fr
;
/* 两列等宽 */
column-gap
:
4px
;
/* 左右间距(同一行) */
row-gap
:
8px
;
/* 上下间距(同一列) */
.author-item
{
.author-item
{
width
:
213px
;
width
:
213px
;
...
@@ -646,6 +683,9 @@ onMounted(() => {
...
@@ -646,6 +683,9 @@ onMounted(() => {
letter-spacing
:
0
;
letter-spacing
:
0
;
text-align
:
left
;
text-align
:
left
;
color
:
rgb
(
59
,
65
,
75
);
color
:
rgb
(
59
,
65
,
75
);
overflow
:
hidden
;
white-space
:
nowrap
;
text-overflow
:
ellipsis
;
}
}
.author-position
{
.author-position
{
...
@@ -658,6 +698,9 @@ onMounted(() => {
...
@@ -658,6 +698,9 @@ onMounted(() => {
letter-spacing
:
0
;
letter-spacing
:
0
;
text-align
:
left
;
text-align
:
left
;
color
:
rgb
(
95
,
101
,
108
);
color
:
rgb
(
95
,
101
,
108
);
overflow
:
hidden
;
white-space
:
nowrap
;
text-overflow
:
ellipsis
;
}
}
}
}
...
@@ -669,6 +712,30 @@ onMounted(() => {
...
@@ -669,6 +712,30 @@ onMounted(() => {
}
}
.box5
{
width
:
480px
;
height
:
415px
;
.box5-main
{
width
:
480px
;
height
:
361px
;
padding-left
:
31px
;
padding-right
:
32px
;
padding-top
:
26px
;
padding-bottom
:
43px
;
display
:
flex
;
box-sizing
:
border-box
;
overflow
:
hidden
;
#box5Chart
{
width
:
100%
;
height
:
100%
;
margin
:
0
auto
;
overflow
:
hidden
;
}
}
}
.box2
{
.box2
{
width
:
480px
;
width
:
480px
;
...
@@ -1131,7 +1198,8 @@ onMounted(() => {
...
@@ -1131,7 +1198,8 @@ onMounted(() => {
height
:
54px
!
important
;
height
:
54px
!
important
;
display
:
flex
;
display
:
flex
;
align-items
:
center
;
align-items
:
center
;
.header-title
>
div
{
.header-title
>
div
{
line-height
:
54px
;
line-height
:
54px
;
}
}
}
}
...
...
src/views/thinkTank/ReportDetail/reportAnalysis/utils/worldCloudChart.js
浏览文件 @
29e42ed8
...
@@ -2,6 +2,8 @@
...
@@ -2,6 +2,8 @@
const
getWordCloudChart
=
(
data
)
=>
{
const
getWordCloudChart
=
(
data
)
=>
{
const
option
=
{
const
option
=
{
width
:
417
,
height
:
292
,
grid
:
{
grid
:
{
left
:
0
,
left
:
0
,
top
:
0
,
top
:
0
,
...
@@ -11,7 +13,13 @@ const getWordCloudChart = (data) => {
...
@@ -11,7 +13,13 @@ const getWordCloudChart = (data) => {
series
:
[
series
:
[
{
{
type
:
"wordCloud"
,
type
:
"wordCloud"
,
shape
:
"circle"
,
//
// 让词云渲染区域严格贴合容器
left
:
"center"
,
top
:
"center"
,
width
:
"100%"
,
height
:
"100%"
,
// 使用矩形词云更容易铺满容器且减少留白
shape
:
"rect"
,
// ✅ 矩形 = 文字排版最整齐、最居中
// 其他形状你可以使用形状路径
// 其他形状你可以使用形状路径
// 或者自定义路径
// 或者自定义路径
// shape: 'circle' // 圆形(默认)
// shape: 'circle' // 圆形(默认)
...
@@ -22,22 +30,16 @@ const getWordCloudChart = (data) => {
...
@@ -22,22 +30,16 @@ const getWordCloudChart = (data) => {
// shape: 'pentagon' // 五边形
// shape: 'pentagon' // 五边形
// shape: 'star' // 星形
// shape: 'star' // 星形
// shape: 'cardioid' // 心形
// shape: 'cardioid' // 心形
gridSize
:
30
,
// 网格大小,影响词间距。
// 网格越大越稀疏,越容易产生留白;这里进一步调小以便更贴合容器
sizeRange
:
[
10
,
25
],
// 定义词云中文字大小的范围
gridSize
:
5
,
// 适当放大最大字号,提升填充度(同时避免太大溢出)
sizeRange
:
[
16
,
24
],
rotationRange
:
[
0
,
0
],
rotationRange
:
[
0
,
0
],
rotationStep
:
15
,
rotationStep
:
15
,
drawOutOfBound
:
false
,
// 是否超出画布
drawOutOfBound
:
false
,
layoutAnimation
:
false
,
// 字体
// 字体
textStyle
:
{
textStyle
:
{
// normal: {
// color: function () {
// return 'rgb(' + [
// Math.round(Math.random() * 160),
// Math.round(Math.random() * 160),
// Math.round(Math.random() * 160)
// ].join(',') + ')';
// }
// },
color
:
function
()
{
color
:
function
()
{
let
colors
=
[
let
colors
=
[
"rgba(189, 33, 33, 1)"
,
"rgba(189, 33, 33, 1)"
,
...
@@ -49,12 +51,12 @@ const getWordCloudChart = (data) => {
...
@@ -49,12 +51,12 @@ const getWordCloudChart = (data) => {
];
];
return
colors
[
parseInt
(
Math
.
random
()
*
colors
.
length
)];
return
colors
[
parseInt
(
Math
.
random
()
*
colors
.
length
)];
},
},
textAlign
:
"center"
,
// ✅ 文字自身水平居中
emphasis
:
{
emphasis
:
{
shadowBlur
:
5
,
shadowBlur
:
5
,
shadowColor
:
"#333"
,
shadowColor
:
"#333"
,
},
},
},
},
// 设置词云数据
data
:
data
,
data
:
data
,
},
},
],
],
...
...
src/views/thinkTank/allThinkTank/index.vue
浏览文件 @
29e42ed8
...
@@ -24,9 +24,10 @@
...
@@ -24,9 +24,10 @@
</div>
</div>
<div
class=
"select-box"
>
<div
class=
"select-box"
>
<div
class=
"search-box"
>
<div
class=
"search-box"
>
<el-input
placeholder=
"搜索
政策建议
"
v-model=
"searchPolicy"
>
<el-input
placeholder=
"搜索
智库
"
v-model=
"searchPolicy"
>
<template
#
suffix
>
<template
#
suffix
>
<img
src=
"../assets/images/Line_Search.png"
class=
"search-icon"
alt=
"搜索"
>
<img
src=
"../assets/images/Line_Search.png"
class=
"search-icon"
alt=
"搜索"
@
click=
"handleGetThinkTankList()"
>
</
template
>
</
template
>
</el-input>
</el-input>
...
@@ -49,13 +50,13 @@
...
@@ -49,13 +50,13 @@
]
]
}"
>
}"
>
<
template
#
prefix
>
<
template
#
prefix
>
<img
src=
"../assets/images/sort-asc.png"
class=
"select-prefix-img"
alt=
""
<img
src=
"../assets/images/sort-asc.png"
class=
"select-prefix-img"
alt=
""
@
click
.
stop=
"toggleSort()"
@
click
.
stop=
"toggleSortAndFetch()"
:key=
"true"
label=
"正序"
:value=
"true"
v-if=
"sort
"
/>
:key=
"true"
label=
"正序"
:value=
"true"
v-if=
"sort === true
"
/>
<img
src=
"../assets/images/sort-desc.png"
class=
"select-prefix-img"
alt=
""
<img
src=
"../assets/images/sort-desc.png"
class=
"select-prefix-img"
alt=
""
@
click
.
stop=
"toggleSort()"
@
click
.
stop=
"toggleSortAndFetch()"
:key=
"true"
label=
"倒序"
:value=
"true"
v-if=
"!sort
"
/>
:key=
"false"
label=
"倒序"
:value=
"false"
v-if=
"sort === false
"
/>
</
template
>
</
template
>
<el-option
@
click=
"handleGetThinkDynamicsReport()"
:key=
"true"
label=
"正序"
:value=
"true"
/>
<el-option
:key=
"true"
label=
"正序"
:value=
"true"
/>
<el-option
@
click=
"handleGetThinkDynamicsReport()"
:key=
"false"
label=
"倒序"
:value=
"false"
/>
<el-option
:key=
"false"
label=
"倒序"
:value=
"false"
/>
</el-select>
</el-select>
</div>
</div>
</div>
</div>
...
@@ -73,6 +74,8 @@
...
@@ -73,6 +74,8 @@
<div
class=
"all-item"
>
<div
class=
"all-item"
>
<div
class=
"item-card"
v-for=
"(item, index) in sortedCardList"
:key=
"item.id || index"
<div
class=
"item-card"
v-for=
"(item, index) in sortedCardList"
:key=
"item.id || index"
@
click=
"handleClick(item)"
>
@
click=
"handleClick(item)"
>
<div
class=
"red-info"
v-if=
"item.increaseReportNumber != 0 && item.increaseReportNumber != null"
>
{{ "+" }}{{
item.increaseReportNumber }}
</div>
<div
class=
"item-header"
>
<div
class=
"item-header"
>
<div
class=
"item-header-image"
>
<div
class=
"item-header-image"
>
<img
:src=
item.logo
alt=
""
/>
<img
:src=
item.logo
alt=
""
/>
...
@@ -114,7 +117,8 @@ const sortedCardList = computed(() => {
...
@@ -114,7 +117,8 @@ const sortedCardList = computed(() => {
return
[...
cardList
.
value
].
sort
((
a
,
b
)
=>
{
return
[...
cardList
.
value
].
sort
((
a
,
b
)
=>
{
const
an
=
Number
(
a
?.
reportNumber
??
0
);
const
an
=
Number
(
a
?.
reportNumber
??
0
);
const
bn
=
Number
(
b
?.
reportNumber
??
0
);
const
bn
=
Number
(
b
?.
reportNumber
??
0
);
return
bn
-
an
;
// 只有选择“倒序(false)”才反转;初始为 null 时走“正序”规则
return
sort
.
value
===
false
?
an
-
bn
:
bn
-
an
;
});
});
});
});
// el-pagination 是 1-based
// el-pagination 是 1-based
...
@@ -137,9 +141,12 @@ const handleGetThinkTankList = async () => {
...
@@ -137,9 +141,12 @@ const handleGetThinkTankList = async () => {
const
res
=
await
getAllThinkTankList
({
const
res
=
await
getAllThinkTankList
({
// 后端通常是 0-based,这里做一次转换
// 后端通常是 0-based,这里做一次转换
currentPage
:
currentPage
.
value
-
1
,
currentPage
:
currentPage
.
value
-
1
,
pageSize
:
pageSize
.
value
pageSize
:
pageSize
.
value
,
keyword
:
searchPolicy
.
value
});
});
console
.
log
(
"智库列表"
,
res
);
console
.
log
(
"智库列表"
,
res
);
cardList
.
value
=
[];
total
.
value
=
0
;
if
(
res
.
code
===
200
&&
res
.
data
)
{
if
(
res
.
code
===
200
&&
res
.
data
)
{
const
list
=
res
.
data
?.
content
||
[];
const
list
=
res
.
data
?.
content
||
[];
total
.
value
=
res
.
data
.
totalElements
;
total
.
value
=
res
.
data
.
totalElements
;
...
@@ -159,9 +166,15 @@ const handleGetThinkTankList = async () => {
...
@@ -159,9 +166,15 @@ const handleGetThinkTankList = async () => {
}
}
}
catch
(
error
)
{
}
catch
(
error
)
{
console
.
error
(
"获取智库列表error"
,
error
);
console
.
error
(
"获取智库列表error"
,
error
);
cardList
.
value
=
[];
total
.
value
=
0
;
}
}
};
};
// 初始为 null:el-select 显示 placeholder;但排序仍按“正序”规则(见 sortedCardList)
const
sort
=
ref
(
null
);
const
sort
=
ref
(
null
);
const
toggleSort
=
()
=>
{
sort
.
value
=
sort
.
value
===
false
?
true
:
false
};
const
searchPolicy
=
ref
(
""
);
const
searchPolicy
=
ref
(
""
);
const
handleClick
=
tank
=>
{
const
handleClick
=
tank
=>
{
console
.
log
(
tank
);
console
.
log
(
tank
);
...
@@ -427,6 +440,31 @@ onMounted(async () => {
...
@@ -427,6 +440,31 @@ onMounted(async () => {
padding-left
:
20px
;
padding-left
:
20px
;
padding-top
:
17px
;
padding-top
:
17px
;
padding-bottom
:
21px
;
padding-bottom
:
21px
;
position
:
relative
;
.red-info
{
color
:
rgb
(
255
,
255
,
255
);
display
:
inline-flex
;
position
:
absolute
;
left
:
277px
;
bottom
:
208px
;
background-color
:
rgba
(
255
,
77
,
79
,
1
);
align-items
:
center
;
justify-content
:
center
;
border-radius
:
50px
;
border
:
1px
solid
rgb
(
255
,
255
,
255
);
width
:
auto
;
font-family
:
"Source Han Sans CN"
;
font-weight
:
700
;
font-size
:
18px
;
line-height
:
24px
;
letter-spacing
:
0px
;
padding
:
2px
8px
;
/* 左右留空隙,更美观 */
white-space
:
nowrap
}
.item-header
{
.item-header
{
width
:
287px
;
width
:
287px
;
...
...
src/views/thinkTank/assets/images/down.png
0 → 100644
浏览文件 @
29e42ed8
10.3 KB
src/views/thinkTank/assets/images/empty-image.png
0 → 100644
浏览文件 @
29e42ed8
49.4 KB
src/views/thinkTank/assets/images/minus.png
0 → 100644
浏览文件 @
29e42ed8
18.3 KB
src/views/thinkTank/assets/images/plus.png
0 → 100644
浏览文件 @
29e42ed8
19.4 KB
src/views/thinkTank/assets/images/rand-image.png
0 → 100644
浏览文件 @
29e42ed8
117.8 KB
src/views/thinkTank/assets/images/right-arrow-white.png
0 → 100644
浏览文件 @
29e42ed8
15.6 KB
src/views/thinkTank/assets/images/right-arrow.png
0 → 100644
浏览文件 @
29e42ed8
19.6 KB
src/views/thinkTank/assets/images/up.png
0 → 100644
浏览文件 @
29e42ed8
1.2 KB
src/views/thinkTank/index.vue
浏览文件 @
29e42ed8
...
@@ -54,6 +54,8 @@
...
@@ -54,6 +54,8 @@
</div>
</div>
<div
class=
"home-main-header-card-box"
>
<div
class=
"home-main-header-card-box"
>
<div
class=
"card"
v-for=
"(item, index) in sortedCardList"
:key=
"index"
@
click=
"handleClick(item)"
>
<div
class=
"card"
v-for=
"(item, index) in sortedCardList"
:key=
"index"
@
click=
"handleClick(item)"
>
<div
class=
"red-info"
v-if=
"item.increaseReportNumber != 0 && item.increaseReportNumber != null"
>
{{
"+"
}}{{
item
.
increaseReportNumber
}}
</div>
<div
class=
"card-header"
>
<div
class=
"card-header"
>
<div
class=
"icon"
>
<div
class=
"icon"
>
<img
:src=
"item.logo"
alt=
""
/>
<img
:src=
"item.logo"
alt=
""
/>
...
@@ -1511,7 +1513,7 @@ const handleSurveyCurrentChange = page => {
...
@@ -1511,7 +1513,7 @@ const handleSurveyCurrentChange = page => {
const
handleGetThinkTankSurvey
=
async
()
=>
{
const
handleGetThinkTankSurvey
=
async
()
=>
{
const
params
=
{
const
params
=
{
currentPage
:
surveyCurrentPage
.
value
-
1
,
pageNum
:
surveyCurrentPage
.
value
,
pageSize
:
12
,
pageSize
:
12
,
sortFun
:
surveySort
.
value
,
sortFun
:
surveySort
.
value
,
researchTypeIds
:
arrayToString
(
surveySelectedAreaList
.
value
),
researchTypeIds
:
arrayToString
(
surveySelectedAreaList
.
value
),
...
@@ -1655,7 +1657,7 @@ function arrayToString(arr) {
...
@@ -1655,7 +1657,7 @@ function arrayToString(arr) {
//获取智库报告
//获取智库报告
const
handleGetetThinkTankReport
=
async
()
=>
{
const
handleGetetThinkTankReport
=
async
()
=>
{
const
params
=
{
const
params
=
{
currentPage
:
currentPage
.
value
-
1
,
pageNum
:
currentPage
.
value
,
pageSize
:
12
,
pageSize
:
12
,
sortFun
:
sort
.
value
,
sortFun
:
sort
.
value
,
researchTypeIds
:
arrayToString
(
selectedAreaList
.
value
),
researchTypeIds
:
arrayToString
(
selectedAreaList
.
value
),
...
@@ -2113,10 +2115,37 @@ onMounted(async () => {
...
@@ -2113,10 +2115,37 @@ onMounted(async () => {
background
:
rgba
(
255
,
255
,
255
,
0
.65
);
background
:
rgba
(
255
,
255
,
255
,
0
.65
);
transition
:
all
0
.3s
;
transition
:
all
0
.3s
;
cursor
:
pointer
;
cursor
:
pointer
;
position
:
relative
;
// 让 red-info 按当前 card 自身定位
z-index
:
1
;
&
:hover
{
&
:hover
{
transform
:
translateY
(
-3px
);
transform
:
translateY
(
-3px
);
box-shadow
:
0
4px
16px
rgba
(
0
,
0
,
0
,
0
.15
);
box-shadow
:
0
4px
16px
rgba
(
0
,
0
,
0
,
0
.15
);
z-index
:
2
;
}
.red-info
{
color
:
rgb
(
255
,
255
,
255
);
display
:
inline-flex
;
position
:
absolute
;
left
:
233px
;
bottom
:
208px
;
background-color
:
rgba
(
255
,
77
,
79
,
1
);
align-items
:
center
;
justify-content
:
center
;
border-radius
:
50px
;
border
:
1px
solid
rgb
(
255
,
255
,
255
);
width
:
auto
;
font-family
:
"Source Han Sans CN"
;
font-weight
:
700
;
font-size
:
18px
;
line-height
:
24px
;
letter-spacing
:
0px
;
padding
:
2px
8px
;
/* 左右留空隙,更美观 */
white-space
:
nowrap
}
}
.card-header
{
.card-header
{
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论