Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
risk-monitor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蔡建
risk-monitor
Commits
75b87091
提交
75b87091
authored
3月 30, 2026
作者:
朱政
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat:增加政策及多智库分析观点标题跳转详情页功能,基本完成智库调查与国会听证会前端页面
上级
31c4cb68
流水线
#179
已失败 于阶段
变更
12
流水线
1
显示空白字符变更
内嵌
并排
正在显示
12 个修改的文件
包含
2795 行增加
和
3 行删除
+2795
-3
index.vue
src/components/base/Ai/AiSummary/index.vue
+1
-0
thinktank.js
src/router/modules/thinktank.js
+12
-0
image-down.png
...views/thinkTank/CongressHearingView/images/image-down.png
+0
-0
image-open.png
...views/thinkTank/CongressHearingView/images/image-open.png
+0
-0
image-up.png
src/views/thinkTank/CongressHearingView/images/image-up.png
+0
-0
paper-image.png
...iews/thinkTank/CongressHearingView/images/paper-image.png
+0
-0
pdf-image.png
src/views/thinkTank/CongressHearingView/images/pdf-image.png
+0
-0
index.vue
src/views/thinkTank/CongressHearingView/index.vue
+1671
-0
index.vue
src/views/thinkTank/MultiThinkTankViewAnalysis/index.vue
+1
-1
index.vue
src/views/thinkTank/SurveyProjectView/index.vue
+1108
-0
index.vue
src/views/thinkTank/ThinkTankDetail/PolicyTracking/index.vue
+1
-1
ThinkTankPolicyAdviceOverview.vue
...ws/thinkTank/components/ThinkTankPolicyAdviceOverview.vue
+1
-1
没有找到文件。
src/components/base/Ai/AiSummary/index.vue
浏览文件 @
75b87091
...
@@ -46,6 +46,7 @@
...
@@ -46,6 +46,7 @@
img
{
img
{
width
:
100%
;
width
:
100%
;
height
:
100%
;
height
:
100%
;
display
:
block
;
}
}
}
}
...
...
src/router/modules/thinktank.js
浏览文件 @
75b87091
...
@@ -2,6 +2,8 @@
...
@@ -2,6 +2,8 @@
const
thinkTank
=
()
=>
import
(
'@/views/thinkTank/index.vue'
)
const
thinkTank
=
()
=>
import
(
'@/views/thinkTank/index.vue'
)
const
ThinkTankDetail
=
()
=>
import
(
'@/views/thinkTank/ThinkTankDetail/index.vue'
)
const
ThinkTankDetail
=
()
=>
import
(
'@/views/thinkTank/ThinkTankDetail/index.vue'
)
const
ReportDetail
=
()
=>
import
(
'@/views/thinkTank/ReportDetail/index.vue'
)
const
ReportDetail
=
()
=>
import
(
'@/views/thinkTank/ReportDetail/index.vue'
)
const
SurveyProjectView
=
()
=>
import
(
'@/views/thinkTank/SurveyProjectView/index.vue'
)
const
CongressHearingView
=
()
=>
import
(
'@/views/thinkTank/CongressHearingView/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
MultiThinkTankViewAnalysis
=
()
=>
import
(
'@/views/thinkTank/MultiThinkTankViewAnalysis/index.vue'
)
...
@@ -39,6 +41,16 @@ const thinktankRoutes = [
...
@@ -39,6 +41,16 @@ const thinktankRoutes = [
name
:
"ReportOriginal"
,
name
:
"ReportOriginal"
,
component
:
ReportOriginal
,
component
:
ReportOriginal
,
},
{
path
:
"/thinkTank/SurveyProjectView/:id"
,
name
:
"SurveyProjectView"
,
component
:
SurveyProjectView
,
},
{
path
:
"/thinkTank/CongressHearingView/:id"
,
name
:
"CongressHearingView"
,
component
:
CongressHearingView
,
},
},
{
{
path
:
"/thinkTank/allThinkTank"
,
path
:
"/thinkTank/allThinkTank"
,
...
...
src/views/thinkTank/CongressHearingView/images/image-down.png
0 → 100644
浏览文件 @
75b87091
10.5 KB
src/views/thinkTank/CongressHearingView/images/image-open.png
0 → 100644
浏览文件 @
75b87091
15.2 KB
src/views/thinkTank/CongressHearingView/images/image-up.png
0 → 100644
浏览文件 @
75b87091
1.2 KB
src/views/thinkTank/CongressHearingView/images/paper-image.png
0 → 100644
浏览文件 @
75b87091
13.9 KB
src/views/thinkTank/CongressHearingView/images/pdf-image.png
0 → 100644
浏览文件 @
75b87091
26.7 KB
src/views/thinkTank/CongressHearingView/index.vue
0 → 100644
浏览文件 @
75b87091
<
template
>
<div
class=
"wrap"
>
<div
class=
"scroll-inner"
>
<div
class=
"header"
>
<div
class=
"header-top"
>
<div
class=
"header-top-left"
>
<img
src=
"../assets/images/box1-logo.png"
alt=
""
/>
<div>
<div
class=
"title"
>
{{
thinkInfo
.
name
}}
</div>
<div
class=
"en-title"
>
{{
thinkInfo
.
ename
}}
.
{{
thinkInfo
.
times
}}
</div>
<div
class=
"tag-box"
>
<!--
<div
class=
"tag-box"
v-for=
"value,index in thinkInfo.tags"
:key=
"index"
>
<div
class=
"tag"
>
{{
value
.
industryName
}}
</div>
</div>
-->
<AreaTag
v-for=
"(value, index) in thinkInfo.tags"
:key=
"index"
:tagName=
"value.industryName"
></AreaTag>
</div>
</div>
</div>
<div
class=
"header-top-right"
>
<div
class=
"image-name-box"
>
<div
class=
"image"
><img
:src=
"thinkInfo.thinkTankLogoUrl"
alt=
""
/></div>
<div
class=
"name"
>
{{
thinkInfo
.
thinkTankName
}}
</div>
</div>
<div
class=
"btn-box"
>
<!--
<div
class=
"btn"
>
<div
class=
"icon"
>
<img
src=
"./images/btn-icon1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"查看官网"
}}
</div>
</div>
-->
<!--
<div
class=
"btn"
>
<div
class=
"icon"
>
<img
src=
"./images/btn-icon2.png"
alt=
""
/>
</div>
<div
class=
"text"
@
click=
"goToOfficialWebsite()"
>
{{
"查看官网"
}}
</div>
</div>
-->
<div
class=
"btn"
>
<div
class=
"icon"
>
<img
src=
"./images/pdf-image.png"
alt=
""
/>
</div>
<div
class=
"text"
@
click=
"toReport()"
>
{{
"文档下载"
}}
</div>
</div>
<!--
<div
class=
"btn"
@
click=
"handleDownloadDocument"
>
<div
class=
"icon"
>
<img
src=
"./images/btn-icon3.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"文档下载"
}}
</div>
</div>
-->
<div
class=
"btn btn1"
@
click=
"handleAnalysisClick"
>
<div
class=
"icon"
>
<img
src=
"./images/paper-image.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"查看原文"
}}
</div>
</div>
</div>
</div>
</div>
</div>
<div
class=
"bottom-row"
>
<div
class=
"left"
>
<div
class=
"box1"
>
<!--
<div
class=
"box-header"
>
<div
class=
"header-left"
></div>
<div
class=
"title"
>
内容摘要
</div>
<div
class=
"header-right"
>
<div
class=
"icon"
>
<img
src=
"@/assets/icons/box-header-icon2.png"
alt=
""
/>
</div>
<div
class=
"icon"
>
<img
src=
"@/assets/icons/box-header-icon3.png"
alt=
""
/>
</div>
</div>
</div>
<div
class=
"box1-main"
>
{{
box1Data
}}
</div>
-->
<AnalysisBox
title=
"基本信息"
:showAllBtn=
"true"
>
<div
class=
"box1-main"
>
<div
class=
"text-box"
>
<div
class=
"time"
>
<div
class=
"time-title"
>
发布时间:
</div>
<div
class=
"time-content"
>
{{
publishTime
}}
</div>
</div>
<div
class=
"topic"
>
<div
class=
"topic-title"
>
报告主题:
</div>
<div
class=
"topic-content"
>
{{
reportTopic
}}
</div>
</div>
<div
class=
"author"
>
<div
class=
"author-title"
>
报告作者:
</div>
<div
class=
"author-content"
>
<template
v-if=
"Array.isArray(reportAuthors) && reportAuthors.length"
>
<span
v-if=
"reportAuthors.length === 1"
>
{{
reportAuthors
[
0
].
name
}}
</span>
<!-- 多个作者:显示第一个 + 等 -->
<span
v-else
>
{{
reportAuthors
[
0
].
name
}}
等
{{
reportAuthors
.
length
}}
人
</span>
</
template
>
</div>
</div>
</div>
<div
class=
"author-box"
>
<div
class=
"author-item"
v-for=
"(author, idx) in reportAuthors"
:key=
"idx"
v-if=
"Array.isArray(reportAuthors) && reportAuthors.length"
@
click=
"handleClickReportAuthor(author)"
>
<div
class=
"image"
><img
:src=
"author.avatar ? author.avatar : DefaultIcon1"
alt=
""
@
error=
"() => { if (author.avatar) author.avatar = null; }"
/></div>
<div
class=
"author-text"
>
<div
class=
"author-name"
>
{{ author.name }}
</div>
</div>
</div>
</div>
</div>
</AnalysisBox>
</div>
<div
class=
"box5"
>
<AnalysisBox
title=
"关键词云"
:showAllBtn=
"true"
>
<div
class=
"box5-main"
>
<
template
v-if=
"!hasBox5ChartData"
>
<el-empty
class=
"box5-el-empty"
description=
"暂无数据"
:image-size=
"100"
/>
</
template
>
<
template
v-else
>
<div
class=
"box5Chart"
>
<!-- 有数据后再挂载子组件:子组件仅在 onMounted 初始化,异步数据到达后需 v-if + key 强制重新挂载 -->
<WordCloudChart
v-if=
"box5Data.length"
:key=
"box5WordCloudKey"
:data=
"box5Data"
width=
"432px"
height=
"272px"
/>
</div>
<div
class=
"box5-footer"
>
<TipTab
:text=
"REPORT_ANALYSIS_TIP_BOX5"
/>
</div>
<div
class=
"ai-wrap"
@
mouseenter=
"handleSwitchAiContentShowBox5(true)"
>
<AiButton
/>
</div>
<div
class=
"ai-content"
v-if=
"isShowAiContentBox5"
@
mouseleave=
"handleSwitchAiContentShowBox5(false)"
>
<AiPane
:aiContent=
"aiContentBox5"
/>
</div>
</
template
>
</div>
</AnalysisBox>
</div>
</div>
<div
class=
"right"
>
<div
class=
"box3"
>
<AnalysisBox
title=
"内容摘要"
:showAllBtn=
"true"
>
<div
class=
"box3-main"
>
<AiSummary>
<
template
#
summary-content
>
{{
box1Data
}}
</
template
>
</AiSummary>
</div>
</AnalysisBox>
</div>
<div
class=
"box4"
>
<AnalysisBox
title=
"听证会内容"
:showAllBtn=
"true"
>
<div
class=
"search-box"
>
<el-input
placeholder=
"搜索内容"
v-model=
"searchOpinions"
style=
"width: 180px"
@
keyup
.
enter=
"handleSearchOpinions"
/>
<div
class=
"icon"
>
<img
src=
"../assets/images/Line_Search.png"
alt=
""
@
click=
"handleSearchOpinions"
/>
</div>
</div>
<div
class=
"box4-main"
>
<div
class=
"box4-main-main"
>
<div
class=
"box4-item"
v-for=
"(item, index) in filteredOpinions"
:key=
"item.id != null ? item.id : index"
>
<div
class=
"top-row"
>
<div
class=
"left"
>
{{ index + 1 }}
</div>
<div
class=
"center"
>
<div
class=
"title"
v-html=
"highlightOpinionText(item.titleZh)"
></div>
<div>
<img
src=
"./images/image-open.png"
alt=
""
class=
"center-image"
@
click=
"handleOpenReportOriginal(item)"
/>
</div>
<div>
<img
v-if=
"!isOpinionExpanded(item, index)"
src=
"./images/image-down.png"
alt=
""
class=
"center-image"
@
click=
"toggleOpinion(item, index)"
/>
<img
v-else
src=
"./images/image-up.png"
alt=
""
class=
"center-image"
@
click=
"toggleOpinion(item, index)"
/>
</div>
</div>
</div>
<div
v-if=
"isOpinionExpanded(item, index)"
class=
"desc"
v-html=
"highlightOpinionText(item.contentZh)"
>
</div>
<!-- <div class="right"> -->
<!-- <div class="tag" v-for="(val, idx) in item.hylyList" :key="idx">
{{ val }}
</div>
<div class="tag" v-for="(val, idx) in item.serialNum" :key="idx">
{{ val }}
</div> -->
<!-- <AreaTag v-for="(val, idx) in item.hylyList" :key="idx" :tagName="val"></AreaTag>
</div> -->
<!-- <div class="more">
<img src="@/assets/icons/open.png" alt="" />
</div> -->
</div>
</div>
<div
class=
"box4-main-footer"
>
<div
class=
"info"
>
共{{ opinionsTotal }}条听证会提问
</div>
<div
class=
"page-box"
>
<el-pagination
:page-size=
"pageSize"
background
layout=
"prev, pager, next"
:total=
"opinionsTotal"
@
current-change=
"handleCurrentChange"
:current-page=
"currentPage"
/>
</div>
</div>
</div>
</AnalysisBox>
</div>
</div>
</div>
</div>
</div>
</template>
<
script
setup
>
import
DefaultIcon1
from
'@/assets/icons/default-icon1.png'
import
WarningPane
from
"@/components/base/WarningPane/index.vue"
import
WordCloudChart
from
"@/components/base/WordCloundChart/index.vue"
import
SearchContainer
from
"@/components/SearchContainer.vue"
;
import
{
ref
,
onMounted
,
computed
,
defineProps
}
from
"vue"
;
import
{
ElMessage
}
from
"element-plus"
;
import
{
getThinkTankReportAbstract
,
getThinkTankReportContent
,
getThinkTankReportIndustry
,
getThinkTankReportIndustryCloud
,
getThinkTankReportViewpoint
}
from
"@/api/thinkTank/overview"
;
import
{
getChartAnalysis
}
from
"@/api/aiAnalysis/index"
;
import
{
useRouter
}
from
"vue-router"
;
import
"echarts-wordcloud"
;
import
AiSummary
from
'@/components/base/Ai/AiSummary/index.vue'
import
{
getPersonSummaryInfo
}
from
"@/api/common/index"
;
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"
;
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
({
reportList
:
{
type
:
Object
,
default
:
()
=>
({})
}
});
const
thinkInfo
=
ref
({
name
:
"探讨中国开发和管理的跨大陆电网的安全影响"
,
ename
:
"调查项目"
,
tags
:
[{
industryName
:
"深海"
},
{
industryName
:
"人工智能"
}],
thinkTankName
:
"兰德科技智库"
,
thinkTankLogoUrl
:
"http://8.140.26.4:10010/kjb-files/images/org/land.webp"
,
times
:
"2024-05-28"
})
const
REPORT_ANALYSIS_TIP_BOX5
=
"智库报告关键词云,数据来源:美国兰德公司官网"
;
// 刷新后默认展示「报告关键词云」AI 总结
const
isShowAiContentBox5
=
ref
(
true
);
const
aiContentBox5
=
ref
(
""
);
const
isBox5InterpretLoading
=
ref
(
false
);
const
handleSwitchAiContentShowBox5
=
(
val
)
=>
{
isShowAiContentBox5
.
value
=
val
;
if
(
val
)
{
fetchBox5ChartInterpretation
();
}
};
const
searchOpinions
=
ref
(
''
);
const
escapeHtml
=
(
text
)
=>
{
return
String
(
text
??
""
)
.
replace
(
/&/g
,
"&"
)
.
replace
(
/</g
,
"<"
)
.
replace
(
/>/g
,
">"
)
.
replace
(
/"/g
,
"""
)
.
replace
(
/'/g
,
"'"
);
};
const
escapeRegExp
=
(
text
)
=>
{
return
String
(
text
??
""
).
replace
(
/
[
.*+?^${}()|[
\]\\]
/g
,
"
\\
$&"
);
};
const
highlightOpinionText
=
(
text
)
=>
{
const
safeText
=
escapeHtml
(
text
);
const
keyword
=
(
searchOpinions
.
value
||
""
).
trim
();
if
(
!
keyword
)
return
safeText
;
const
pattern
=
new
RegExp
(
`(
${
escapeRegExp
(
keyword
)}
)`
,
"gi"
);
return
safeText
.
replace
(
pattern
,
`<span class="opinion-keyword-highlight">$1</span>`
);
};
const
handleSearchOpinions
=
()
=>
{
currentPage
.
value
=
1
;
handleGetThinkTankReportViewpoint
();
};
/** 可同时展开多条;用 id 区分项,避免翻页后索引与展开状态错位 */
const
expandedOpinionKeys
=
ref
(
new
Set
());
const
filteredOpinions
=
computed
(()
=>
majorOpinions
.
value
);
const
opinionsTotal
=
computed
(()
=>
total
.
value
);
const
getOpinionExpandKey
=
(
item
,
index
)
=>
{
if
(
item
!=
null
&&
item
.
id
!=
null
&&
item
.
id
!==
""
)
{
return
String
(
item
.
id
);
}
return
`idx-
${
index
}
`
;
};
const
isOpinionExpanded
=
(
item
,
index
)
=>
{
return
expandedOpinionKeys
.
value
.
has
(
getOpinionExpandKey
(
item
,
index
));
};
const
toggleOpinion
=
(
item
,
index
)
=>
{
const
key
=
getOpinionExpandKey
(
item
,
index
);
const
next
=
new
Set
(
expandedOpinionKeys
.
value
);
if
(
next
.
has
(
key
))
{
next
.
delete
(
key
);
}
else
{
next
.
add
(
key
);
}
expandedOpinionKeys
.
value
=
next
;
};
const
publishTime
=
computed
(()
=>
{
const
info
=
props
.
thinkInfo
||
{};
// 优先用 times,其次用 reportTime 的日期部分
if
(
info
.
times
)
return
info
.
times
;
if
(
info
.
reportTime
&&
typeof
info
.
reportTime
===
"string"
)
{
return
info
.
reportTime
.
split
(
"T"
)[
0
];
}
return
""
;
});
const
reportTopic
=
computed
(()
=>
{
const
info
=
props
.
thinkInfo
||
{};
return
info
.
summary
;
});
const
reportAuthors
=
computed
(()
=>
{
const
info
=
props
.
thinkInfo
||
{};
if
(
Array
.
isArray
(
info
.
authors
)
&&
info
.
authors
.
length
)
{
return
info
.
authors
;
}
return
[];
});
// 点击报告作者头像,跳转到人物主页
// 与核心研究人员逻辑一致:核心依赖 personId,本页面依赖作者的 id(作为 personId 传入)
const
handleClickReportAuthor
=
async
(
author
)
=>
{
const
personId
=
author
?.
id
;
if
(
!
personId
)
return
;
const
params
=
{
personId
};
const
res
=
await
getPersonSummaryInfo
(
params
);
if
(
res
.
code
!==
200
||
!
res
.
data
)
return
;
window
.
sessionStorage
.
setItem
(
"curTabName"
,
author
?.
name
||
""
);
const
route
=
router
.
resolve
({
path
:
"/characterPage"
,
query
:
{
personId
}
});
window
.
open
(
route
.
href
,
"_blank"
);
};
const
riskSignal
=
computed
(()
=>
{
const
info
=
props
.
thinkInfo
||
{};
return
info
.
riskSignal
;
});
// 内容摘要
const
box1Data
=
ref
(
`包括经济竞争在内的美中竞争自2017年以来一直在定义美国外交政策。这两个经济体是世界上第一和第二大国家经济体,并且深深交织在一起。改变关系,无论多么必要,可能是昂贵的。因此,美国面临着一项挑战,确保其经济在耦合的战略竞争条件下满足国家的需求。
为了应对这一挑战,兰德大学的研究人员对美中竞争进行了经济和制度分析,进行了参与式的远见练习,以了解确保美国经济健康的长期路径,并创建了两个经济竞争游戏,探索多个国家在相互交流的同时确保经济健康的动态...`
);
//获取内容摘要
const
handleGetThinkTankReportAbstract
=
async
()
=>
{
try
{
const
res
=
await
getThinkTankReportAbstract
(
router
.
currentRoute
.
_value
.
params
.
id
);
console
.
log
(
"内容摘要"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
box1Data
.
value
=
res
.
data
;
}
}
catch
(
error
)
{
console
.
error
(
"获取内容摘要error"
,
error
);
}
};
// 涉及科技领域
const
areaList
=
ref
([]);
const
activeArea
=
ref
(
6
);
const
handleClickArea
=
area
=>
{
activeArea
.
value
=
area
;
handleGetThinkTankReportIndustryCloud
();
};
const
box2Data
=
ref
([
// {
// name: "通用人工智能",
// value: 100
// },
// {
// name: "AI芯片",
// value: 66
// },
// {
// name: "计算能力又是",
// value: 72
// },
// {
// name: "基准测试",
// value: 88
// },
// {
// name: "出口管制",
// value: 78
// },
// {
// name: "军事AI",
// value: 85
// },
// {
// name: "生态系统",
// value: 88
// },
// {
// name: "模型能力",
// value: 89
// }
]);
// 报告关键词云
const
box5Data
=
ref
([]);
const
hasBox5ChartData
=
computed
(()
=>
Array
.
isArray
(
box5Data
.
value
)
&&
box5Data
.
value
.
length
>
0
);
/** 词云子组件不 watch 数据,每次接口成功有数据时递增 key,强制重新挂载以触发 onMounted */
const
box5WordCloudKey
=
ref
(
0
);
//获取科技领域词云
const
handleGetThinkTankReportIndustryCloud
=
async
()
=>
{
try
{
const
params
=
{
id
:
router
.
currentRoute
.
_value
.
params
.
id
// industryId: activeArea.value
};
const
res
=
await
getThinkTankReportIndustryCloud
(
params
);
console
.
log
(
"科技领域词云"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
const
data
=
(
res
.
data
||
[]).
map
(
item
=>
({
name
:
item
.
clause
,
value
:
item
.
count
}));
// 该接口数据用于「报告关键词云」
box5Data
.
value
=
data
;
if
(
data
.
length
)
{
box5WordCloudKey
.
value
+=
1
;
}
// 刷新后默认展开 AI:数据就绪即触发解读
if
(
isShowAiContentBox5
.
value
)
{
fetchBox5ChartInterpretation
();
}
}
else
{
box5Data
.
value
=
[];
}
}
catch
(
error
)
{
console
.
error
(
"获取科技领域词云error"
,
error
);
box5Data
.
value
=
[];
}
};
//涉及科技领域
const
handleGetThinkTankReportIndustry
=
async
()
=>
{
try
{
const
res
=
await
getThinkTankReportIndustry
(
router
.
currentRoute
.
_value
.
params
.
id
);
console
.
log
(
"涉及科技领域"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
areaList
.
value
=
res
.
data
;
}
}
catch
(
error
)
{
console
.
error
(
"获取涉及科技领域error"
,
error
);
}
};
// 主要观点
const
majorOpinions
=
ref
([
{
id
:
1
,
title
:
"我是示例标题"
,
desc
:
"我是示例内容"
,
tagList
:
[
{
name
:
"关税"
,
status
:
2
},
{
name
:
"跨境电商"
,
status
:
1
}
]
},
{
id
:
2
,
title
:
"我是示例标题"
,
desc
:
"我是示例内容"
,
tagList
:
[
{
name
:
"私有经济"
,
status
:
2
}
]
}
]);
//处理点击详情页事件
const
handleOpenReportOriginal
=
item
=>
{
const
route
=
router
.
resolve
({
name
:
"ReportOriginal"
,
params
:
{
id
:
router
.
currentRoute
.
_value
.
params
.
id
},
query
:
{
currentPage
:
currentPage
.
value
,
pageSize
:
pageSize
.
value
,
opinionId
:
item
?.
id
??
""
,
opinionContent
:
item
?.
content
??
""
}
});
window
.
open
(
route
.
href
,
"_blank"
);
};
const
tabActiveName
=
ref
(
"报告分析"
);
const
switchTab
=
name
=>
{
tabActiveName
.
value
=
name
;
};
// 处理页码改变事件
const
currentPage
=
ref
(
1
);
const
pageSize
=
ref
(
10
);
const
total
=
ref
(
0
);
const
handleCurrentChange
=
page
=>
{
currentPage
.
value
=
page
;
handleGetThinkTankReportViewpoint
();
};
// 获取报告核心论点(支持搜索)
const
handleGetThinkTankReportViewpoint
=
async
()
=>
{
try
{
const
params
=
{
reportId
:
router
.
currentRoute
.
_value
.
params
.
id
,
currentPage
:
currentPage
.
value
-
1
,
pageSize
:
pageSize
.
value
,
keyword
:
(
searchOpinions
.
value
||
""
).
trim
(),
orgIds
:
""
};
const
res
=
await
getThinkTankReportViewpoint
(
params
);
console
.
log
(
"核心论点"
,
res
.
data
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
const
nextOpinions
=
res
.
data
.
content
||
[];
majorOpinions
.
value
=
nextOpinions
;
total
.
value
=
res
.
data
.
totalElements
||
0
;
// 默认:第一条展开,其余关闭
const
nextExpandedKeys
=
new
Set
();
if
(
Array
.
isArray
(
nextOpinions
)
&&
nextOpinions
.
length
>
0
)
{
nextExpandedKeys
.
add
(
getOpinionExpandKey
(
nextOpinions
[
0
],
0
));
}
expandedOpinionKeys
.
value
=
nextExpandedKeys
;
}
}
catch
(
error
)
{
console
.
error
(
"获取主要观点error"
,
error
);
}
};
// 获取图表分析内容
const
box3AnalysisContent
=
ref
(
""
);
const
handleGetBox3AnalysisContent
=
async
textJson
=>
{
const
params
=
{
text
:
textJson
};
const
res
=
await
getChartAnalysis
(
params
);
console
.
log
(
"图表解析内容"
,
res
);
};
const
getInterpretationTextFromChartResponse
=
(
res
)
=>
{
const
list
=
res
?.
data
;
const
first
=
Array
.
isArray
(
list
)
?
list
[
0
]
:
null
;
return
(
first
?.[
"解读"
]
||
first
?.[
"interpretation"
]
||
first
?.[
"analysis"
]
||
first
?.[
"content"
]
||
""
);
};
const
appendAiInterpretationChunk
=
(
targetRef
,
chunk
,
loadingText
=
"解读生成中…"
)
=>
{
if
(
!
chunk
)
{
return
;
}
const
current
=
String
(
targetRef
.
value
||
""
);
const
base
=
current
===
loadingText
?
""
:
current
;
targetRef
.
value
=
base
+
String
(
chunk
);
};
const
fetchBox5ChartInterpretation
=
async
()
=>
{
const
list
=
Array
.
isArray
(
box5Data
.
value
)
?
box5Data
.
value
:
[];
if
(
!
list
.
length
)
{
aiContentBox5
.
value
=
"暂无图表数据"
;
return
;
}
const
hasValidContent
=
aiContentBox5
.
value
&&
aiContentBox5
.
value
!==
"解读生成中…"
&&
aiContentBox5
.
value
!==
"解读加载失败"
&&
aiContentBox5
.
value
!==
"暂无图表数据"
;
if
(
hasValidContent
||
isBox5InterpretLoading
.
value
)
{
return
;
}
isBox5InterpretLoading
.
value
=
true
;
aiContentBox5
.
value
=
"解读生成中…"
;
const
chartPayload
=
{
type
:
"词云图"
,
name
:
"报告关键词云"
,
data
:
list
.
map
((
item
)
=>
({
name
:
item
.
name
,
value
:
item
.
value
}))
};
try
{
const
res
=
await
getChartAnalysis
(
{
text
:
JSON
.
stringify
(
chartPayload
)
},
{
onChunk
:
chunk
=>
{
appendAiInterpretationChunk
(
aiContentBox5
,
chunk
);
}
}
);
const
text
=
getInterpretationTextFromChartResponse
(
res
);
aiContentBox5
.
value
=
text
||
aiContentBox5
.
value
||
"未返回有效解读内容"
;
}
catch
(
error
)
{
console
.
error
(
"报告关键词云图表解读请求失败"
,
error
);
aiContentBox5
.
value
=
"解读加载失败"
;
}
finally
{
isBox5InterpretLoading
.
value
=
false
;
}
};
onMounted
(()
=>
{
handleGetThinkTankReportAbstract
();
handleGetThinkTankReportViewpoint
();
handleGetThinkTankReportIndustry
();
handleGetThinkTankReportIndustryCloud
();
});
</
script
>
<
style
lang=
"scss"
scoped
>
.wrap
{
position
:
absolute
;
inset
:
0
;
box-sizing
:
border-box
;
width
:
100%
;
overflow
:
hidden
;
.scroll-inner
{
box-sizing
:
border-box
;
width
:
100%
;
height
:
100%
;
min-height
:
0
;
padding-bottom
:
16px
;
overflow-x
:
hidden
;
overflow-y
:
auto
;
scrollbar-gutter
:
stable
;
scrollbar-width
:
thin
;
&
:
:-
webkit-scrollbar
{
width
:
8px
;
}
&
:
:-
webkit-scrollbar-thumb
{
border-radius
:
4px
;
}
}
.header
{
width
:
100%
;
height
:
126px
;
box-sizing
:
border-box
;
border-bottom
:
1px
solid
rgba
(
234
,
236
,
238
,
1
);
box-shadow
:
0px
0px
20px
0px
rgba
(
25
,
69
,
130
,
0
.1
);
background
:
rgba
(
255
,
255
,
255
,
1
);
position
:
sticky
;
top
:
0
;
z-index
:
99999
;
overflow
:
hidden
;
.header-top
{
margin
:
0
auto
;
margin-top
:
20px
;
width
:
1600px
;
display
:
flex
;
justify-content
:
space-between
;
.header-top-left
{
display
:
flex
;
img
{
width
:
72px
;
height
:
88px
;
}
.title
{
margin-left
:
16px
;
height
:
26px
;
color
:
rgb
(
59
,
65
,
75
);
font-family
:
"Source Han Sans CN"
;
font-weight
:
700
;
font-size
:
20px
;
line-height
:
26px
;
letter-spacing
:
0px
;
text-align
:
left
;
}
.en-title
{
margin-top
:
4px
;
margin-left
:
16px
;
height
:
24px
;
color
:
rgb
(
95
,
101
,
108
);
font-family
:
"Source Han Sans CN"
;
font-weight
:
400
;
font-size
:
16px
;
line-height
:
24px
;
letter-spacing
:
0px
;
text-align
:
left
;
}
.tag-box
{
margin-top
:
12px
;
display
:
flex
;
gap
:
8px
;
margin-left
:
16px
;
}
}
.header-top-right
{
display
:
flex
;
flex-direction
:
column
;
text-align
:
right
;
align-items
:
flex-end
;
.image-name-box
{
width
:
118px
;
height
:
24px
;
gap
:
6px
;
text-align
:
right
;
display
:
flex
;
justify-content
:
flex-end
;
.name
{
height
:
24px
;
color
:
rgba
(
95
,
101
,
108
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
400
;
line-height
:
24px
;
letter-spacing
:
0px
;
text-align
:
right
;
}
.image
{
width
:
16px
;
height
:
16px
;
margin-top
:
5px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
}
.btn-box
{
display
:
flex
;
gap
:
12px
;
margin-top
:
34px
;
.btn
{
width
:
120px
;
height
:
36px
;
box-sizing
:
border-box
;
border
:
1px
solid
rgba
(
230
,
231
,
232
,
1
);
border-radius
:
6px
;
background
:
rgba
(
255
,
255
,
255
,
1
);
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
gap
:
8px
;
.icon
{
width
:
16px
;
height
:
16px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.text
{
width
:
66px
;
height
:
22px
;
color
:
rgba
(
95
,
101
,
108
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
400
;
line-height
:
22px
;
letter-spacing
:
0px
;
text-align
:
center
;
}
}
.btn1
{
border-radius
:
6px
;
background
:
var
(
--
color-main-active
);
.text
{
color
:
rgba
(
255
,
255
,
255
,
1
);
}
}
}
.time
{
height
:
24px
;
margin-top
:
5px
;
color
:
rgba
(
95
,
101
,
108
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
400
;
line-height
:
24px
;
letter-spacing
:
0px
;
text-align
:
right
;
}
}
}
}
.bottom-row
{
flex-direction
:
row
;
justify-content
:
center
;
display
:
flex
;
gap
:
16px
;
.left
{
gap
:
16px
;
display
:
flex
;
flex-direction
:
column
;
margin-top
:
16px
;
.box1
{
width
:
480px
;
// 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);
.box1-main
{
width
:
480px
;
.text-box
{
width
:
437px
;
margin-left
:
22px
;
margin-top
:
8px
;
gap
:
12px
;
display
:
flex
;
flex-direction
:
column
;
.time
{
height
:
24px
;
display
:
flex
;
gap
:
4px
;
.time-title
{
width
:
88px
;
font-family
:
"Source Han Sans CN"
;
font-weight
:
700
;
font-size
:
16px
;
line-height
:
24px
;
letter-spacing
:
1px
;
text-align
:
left
;
color
:
rgb
(
59
,
65
,
75
);
}
.time-content
{
width
:
345px
;
font-family
:
"Source Han Sans CN"
;
font-weight
:
400
;
font-size
:
16px
;
line-height
:
24px
;
letter-spacing
:
0px
;
text-align
:
left
;
color
:
rgb
(
59
,
65
,
75
);
}
}
.topic
{
display
:
flex
;
gap
:
4px
;
.topic-title
{
width
:
88px
;
font-family
:
"Source Han Sans CN"
;
font-weight
:
700
;
font-size
:
16px
;
line-height
:
24px
;
letter-spacing
:
1px
;
text-align
:
left
;
color
:
rgb
(
59
,
65
,
75
);
}
.topic-content
{
width
:
345px
;
font-family
:
"Source Han Sans CN"
;
font-weight
:
400
;
font-size
:
16px
;
line-height
:
30px
;
letter-spacing
:
0px
;
text-align
:
left
;
color
:
rgb
(
59
,
65
,
75
);
}
}
.author
{
display
:
flex
;
gap
:
4px
;
.author-title
{
width
:
88px
;
font-family
:
"Source Han Sans CN"
;
font-weight
:
700
;
font-size
:
16px
;
line-height
:
24px
;
letter-spacing
:
1px
;
text-align
:
left
;
color
:
rgb
(
59
,
65
,
75
);
}
.author-content
{
width
:
345px
;
font-family
:
"Source Han Sans CN"
;
font-weight
:
400
;
font-size
:
16px
;
line-height
:
24px
;
letter-spacing
:
0px
;
text-align
:
left
;
color
:
rgb
(
59
,
65
,
75
);
}
}
}
.author-box
{
width
:
437px
;
height
:
auto
;
margin-top
:
34px
;
margin-left
:
18px
;
display
:
grid
;
grid-template-columns
:
1fr
1fr
;
/* 两列等宽 */
column-gap
:
4px
;
/* 左右间距(同一行) */
row-gap
:
8px
;
/* 上下间距(同一列) */
margin-bottom
:
38px
;
.author-item
{
width
:
213px
;
height
:
49px
;
display
:
flex
;
gap
:
11px
;
.image
{
width
:
42px
;
height
:
42px
;
margin-top
:
3px
;
margin-left
:
3px
;
display
:
inline-block
;
cursor
:
pointer
;
img
{
width
:
100%
;
height
:
100%
;
border-radius
:
50%
;
}
}
.author-text
{
width
:
154px
;
height
:
49px
;
.author-name
{
width
:
154px
;
height
:
24px
;
font-family
:
"Source Han Sans CN"
;
font-weight
:
700
;
font-size
:
16px
;
line-height
:
24px
;
letter-spacing
:
0
;
text-align
:
left
;
color
:
rgb
(
59
,
65
,
75
);
overflow
:
hidden
;
white-space
:
nowrap
;
text-overflow
:
ellipsis
;
}
.author-position
{
width
:
154px
;
height
:
22px
;
font-family
:
"Source Han Sans CN"
;
font-weight
:
400
;
font-size
:
14px
;
line-height
:
22px
;
letter-spacing
:
0
;
text-align
:
left
;
color
:
rgb
(
95
,
101
,
108
);
overflow
:
hidden
;
white-space
:
nowrap
;
text-overflow
:
ellipsis
;
}
}
}
}
}
}
.box5
{
width
:
480px
;
height
:
415px
;
.box5-main
{
width
:
480px
;
height
:
361px
;
padding
:
24px
24px
65px
24px
;
display
:
flex
;
flex-direction
:
column
;
box-sizing
:
border-box
;
overflow
:
hidden
;
position
:
relative
;
.box5Chart
{
width
:
100%
;
height
:
100%
;
margin
:
0
auto
;
overflow
:
hidden
;
}
.box5-footer
{
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
position
:
absolute
;
bottom
:
20px
;
left
:
32px
;
}
.ai-wrap
{
position
:
absolute
;
bottom
:
18px
;
right
:
0
;
cursor
:
pointer
;
}
.ai-content
{
position
:
absolute
;
bottom
:
0
;
right
:
0
;
min-width
:
480px
;
min-height
:
156px
;
}
}
}
.box2
{
width
:
480px
;
// 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);
.box2-main
{
width
:
436px
;
margin-top
:
5px
;
margin-left
:
23px
;
.box2-item
{
height
:
103px
;
width
:
100%
;
border-bottom
:
1px
solid
rgba
(
234
,
236
,
238
,
1
);
border-top
:
1px
solid
rgba
(
234
,
236
,
238
,
1
);
.box2-item-content
{
width
:
100%
;
height
:
90px
;
margin-top
:
7px
;
display
:
flex
;
.left
{
width
:
56px
;
height
:
74px
;
margin-top
:
8px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.right-content
{
margin-left
:
13px
;
width
:
365px
;
height
:
76px
;
margin-top
:
7px
;
.report-title
{
height
:
48px
;
font-family
:
"Source Han Sans CN"
;
font-weight
:
700
;
font-size
:
16px
;
line-height
:
24px
;
letter-spacing
:
0
;
text-align
:
left
;
/* 👇 下面是 两行文本超出省略 核心代码 */
display
:
-
webkit-box
;
-webkit-line-clamp
:
2
;
/* 限制显示 2 行 */
-webkit-box-orient
:
vertical
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
word-break
:
break-all
;
}
.report-footer
{
margin-top
:
4px
;
height
:
22px
;
justify-content
:
space-between
;
display
:
flex
;
.report-time
{
height
:
22px
;
width
:
97px
;
font-family
:
"Source Han Sans CN"
;
font-weight
:
400
;
font-size
:
14px
;
line-height
:
22px
;
letter-spacing
:
0
;
text-align
:
left
;
color
:
rgb
(
95
,
101
,
108
);
}
.report-footer-right
{
height
:
22px
;
display
:
flex
;
gap
:
6px
;
.footer-image
{
width
:
16px
;
height
:
16px
;
margin-top
:
3px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.think-name
{
height
:
22px
;
}
}
}
}
}
}
}
.box2-btn
{
margin-top
:
16px
;
margin-bottom
:
21px
;
margin-left
:
23px
;
width
:
436px
;
height
:
36px
;
background-color
:
rgb
(
5
,
95
,
194
);
border-radius
:
6px
;
display
:
flex
;
.btn-text
{
color
:
rgb
(
255
,
255
,
255
);
font-family
:
"Source Han Sans CN"
;
font-weight
:
400
;
font-size
:
16px
;
line-height
:
22px
;
letter-spacing
:
0
;
margin-left
:
120px
;
margin-top
:
7px
;
}
.btn-image
{
width
:
13px
;
height
:
8px
;
margin-left
:
8px
;
display
:
inline-block
;
margin-top
:
14px
;
img
{
width
:
100%
;
height
:
100%
;
display
:
block
;
}
}
}
}
}
.right
{
margin-top
:
16px
;
gap
:
16px
;
display
:
flex
;
flex-direction
:
column
;
.box3
{
width
:
1103px
;
// 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);
.box3-main
{
width
:
1058px
;
margin-top
:
3px
;
margin-left
:
22px
;
padding-bottom
:
22px
;
:deep
(
.summary-main
)
{
margin-bottom
:
25px
;
font-family
:
"Source Han Sans CN"
;
font-weight
:
400
;
/* Regular 常规 */
font-size
:
16px
;
line-height
:
30px
;
letter-spacing
:
0px
;
text-align
:
justify
;
color
:
rgb
(
59
,
65
,
75
);
/* 两端对齐 */
}
.box3-top
{
width
:
1058px
;
height
:
48px
;
background
:
linear-gradient
(
rgb
(
137
,
193
,
255
,
0
.1
)
,
rgb
(
255
,
255
,
255
));
display
:
flex
;
.top-title
{
width
:
1010px
;
height
:
32px
;
margin-left
:
24px
;
margin-top
:
16px
;
.title-image
{
width
:
199px
;
height
:
32px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
}
}
.box3-text
{
width
:
1006px
;
margin-top
:
24px
;
margin-left
:
26px
;
font-family
:
"Source Han Sans CN"
;
font-weight
:
400
;
font-size
:
16px
;
line-height
:
30px
;
letter-spacing
:
0px
;
text-align
:
justify
;
text-justify
:
inter-ideograph
;
}
}
}
.box4
{
width
:
1103px
;
height
:
auto
;
// 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
;
.search-box
{
display
:
flex
;
width
:
180px
;
height
:
32px
;
box-sizing
:
border-box
;
border
:
1px
solid
rgba
(
230
,
231
,
232
,
1
);
border-radius
:
4px
;
background
:
rgba
(
255
,
255
,
255
,
1
);
position
:
relative
;
margin-top
:
3px
;
margin-bottom
:
16px
;
margin-left
:
23px
;
.icon
{
width
:
16px
;
height
:
16px
;
cursor
:
pointer
;
position
:
absolute
;
right
:
8px
;
top
:
8px
;
display
:
flex
;
justify-content
:
flex-end
;
z-index
:
10000
;
img
{
width
:
100%
;
height
:
100%
;
}
}
}
.box4-main
{
width
:
1057px
;
height
:
auto
;
margin
:
0
auto
;
.box4-main-main
{
height
:
auto
;
overflow
:
visible
;
.box4-item
{
width
:
1057px
;
box-sizing
:
border-box
;
border-radius
:
4px
;
display
:
flex
;
flex-direction
:
column
;
position
:
relative
;
border-bottom
:
1px
solid
rgba
(
234
,
236
,
238
,
1
);
&
:first-child
{
border-top
:
1px
solid
rgba
(
234
,
236
,
238
,
1
);
}
.top-row
{
display
:
flex
;
align-items
:
flex-start
;
}
.left
{
margin-top
:
19px
;
margin-left
:
15px
;
width
:
24px
;
height
:
24px
;
border-radius
:
12px
;
line-height
:
24px
;
text-align
:
center
;
background
:
rgba
(
231
,
243
,
255
,
1
);
color
:
var
(
--
color-main-active
);
font-family
:
Microsoft
YaHei
;
font-size
:
12px
;
font-weight
:
400
;
letter-spacing
:
0px
;
}
.center
{
min-height
:
62px
;
margin-left
:
18px
;
display
:
flex
;
align-items
:
center
;
// overflow: hidden;
// text-overflow: ellipsis;
// white-space: nowrap;
.title
{
width
:
918px
;
// height: 55px;
color
:
rgba
(
59
,
65
,
75
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
700
;
line-height
:
30px
;
letter-spacing
:
0px
;
text-align
:
left
;
overflow
:
hidden
;
// text-overflow: ellipsis;
// white-space: nowrap;
display
:
-
webkit-box
;
-webkit-line-clamp
:
2
;
-webkit-box-orient
:
vertical
;
overflow
:
hidden
;
}
.center-image
{
width
:
16px
;
height
:
24px
;
margin-top
:
12px
;
margin-left
:
18px
;
}
}
.right
{
margin-top
:
26px
;
width
:
180px
;
height
:
22px
;
display
:
flex
;
margin-top
:
26px
;
margin-left
:
20px
;
height
:
22px
;
display
:
flex
;
gap
:
4px
;
.tag
{
height
:
22px
;
padding
:
0
8px
;
box-sizing
:
border-box
;
border
:
1px
solid
rgba
(
217
,
247
,
190
,
1
);
border-radius
:
4px
;
background
:
rgba
(
246
,
255
,
237
,
1
);
color
:
rgba
(
82
,
196
,
26
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
14px
;
font-weight
:
400
;
line-height
:
20px
;
}
}
.more
{
width
:
16px
;
height
:
16px
;
position
:
absolute
;
top
:
28px
;
right
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.desc
{
padding-top
:
22px
;
padding-bottom
:
23px
;
padding-left
:
56px
;
// 24(left) + 13(center margin) + 一点间距
color
:
rgb
(
59
,
65
,
75
);
font-family
:
"Source Han Sans CN"
;
font-weight
:
400
;
/* Regular 常规 */
font-size
:
16px
;
line-height
:
30px
;
letter-spacing
:
0px
;
text-align
:
justify
;
/* 两端对齐 */
border-top
:
1px
solid
rgba
(
234
,
236
,
238
,
1
);
}
.title
:deep
(
.opinion-keyword-highlight
),
.desc
:deep
(
.opinion-keyword-highlight
)
{
background-color
:
#fff59d
;
}
}
}
.box4-main-footer
{
height
:
80px
;
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
padding
:
30px
5px
;
box-sizing
:
border-box
;
overflow
:
hidden
;
.info
{
flex
:
1
1
auto
;
min-width
:
0
;
color
:
rgba
(
132
,
136
,
142
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
14px
;
font-weight
:
400
;
line-height
:
18px
;
letter-spacing
:
0px
;
text-align
:
left
;
}
.page-box
{
/* 最大 300px:允许变小,但绝不变大 */
flex
:
0
1
300px
;
width
:
100%
;
max-width
:
300px
;
min-width
:
0
;
display
:
flex
;
justify-content
:
flex-end
;
overflow
:
hidden
;
}
.page-box
:deep
(
.el-pagination
)
{
max-width
:
100%
;
min-width
:
0
;
overflow
:
hidden
;
}
}
}
.box4-footer
{
position
:
absolute
;
left
:
22px
;
bottom
:
19px
;
width
:
1057px
;
height
:
64px
;
box-sizing
:
border-box
;
border
:
1px
solid
rgba
(
231
,
243
,
255
,
1
);
border-radius
:
4px
;
background
:
rgba
(
246
,
250
,
255
,
1
);
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
gap
:
13px
;
.footer-left
{
width
:
19px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.footer-center
{
width
:
964px
;
height
:
48px
;
color
:
var
(
--
color-main-active
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
400
;
line-height
:
24px
;
letter-spacing
:
0px
;
text-align
:
justify
;
}
.footer-right
{
width
:
24px
;
height
:
24px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
}
}
.box5
{
width
:
1103px
;
height
:
auto
;
// 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
;
}
}
}
}
:deep
(
.analysis-box-wrapper
.wrapper-header
)
{
height
:
54px
!
important
;
display
:
flex
;
align-items
:
center
;
.header-title
>
div
{
line-height
:
54px
;
}
}
</
style
>
src/views/thinkTank/MultiThinkTankViewAnalysis/index.vue
浏览文件 @
75b87091
...
@@ -474,7 +474,7 @@ const handleOpenReportOriginalFromSource = (sv) => {
...
@@ -474,7 +474,7 @@ const handleOpenReportOriginalFromSource = (sv) => {
const
id
=
String
(
sv
?.
report_id
??
""
).
trim
()
const
id
=
String
(
sv
?.
report_id
??
""
).
trim
()
if
(
!
id
)
return
if
(
!
id
)
return
const
route
=
router
.
resolve
({
const
route
=
router
.
resolve
({
name
:
"Report
Origina
l"
,
name
:
"Report
Detai
l"
,
params
:
{
id
}
params
:
{
id
}
}
)
}
)
window
.
open
(
route
.
href
,
"_blank"
)
window
.
open
(
route
.
href
,
"_blank"
)
...
...
src/views/thinkTank/SurveyProjectView/index.vue
0 → 100644
浏览文件 @
75b87091
<
template
>
<div
class=
"wrap"
>
<div
class=
"scroll-inner"
>
<div
class=
"header"
>
<div
class=
"header-top"
>
<div
class=
"header-top-left"
>
<img
src=
"../assets/images/box1-logo.png"
alt=
""
/>
<div>
<div
class=
"title"
>
{{
thinkInfo
.
name
}}
</div>
<div
class=
"en-title"
>
{{
thinkInfo
.
ename
}}
</div>
</div>
</div>
<div
class=
"header-top-right"
>
<div
class=
"image-name-box"
>
<div
class=
"image"
><img
src=
"../assets/images/box1-logo.png"
alt=
""
/></div>
<div
class=
"name"
>
{{
thinkInfo
.
thinkTankName
}}
</div>
</div>
<div
class=
"tag-box"
>
<AreaTag
v-for=
"(value, index) in thinkInfo.tags"
:key=
"index"
:tagName=
"value.industryName"
></AreaTag>
</div>
</div>
</div>
</div>
<div
class=
"bottom-row"
>
<div
class=
"left"
>
<div
class=
"box1"
>
<AnalysisBox
title=
"关键词云"
:showAllBtn=
"true"
>
<div
class=
"box1-main"
>
<template
v-if=
"!hasBox5ChartData"
>
<el-empty
class=
"box5-el-empty"
description=
"暂无数据"
:image-size=
"100"
/>
</
template
>
<
template
v-else
>
<div
class=
"box5Chart"
>
<!-- 有数据后再挂载子组件:子组件仅在 onMounted 初始化,异步数据到达后需 v-if + key 强制重新挂载 -->
<WordCloudChart
v-if=
"box5Data.length"
:key=
"box5WordCloudKey"
:data=
"box5Data"
width=
"432px"
height=
"272px"
/>
</div>
<div
class=
"box1-footer"
>
<TipTab
:text=
"REPORT_ANALYSIS_TIP_BOX5"
/>
</div>
<div
class=
"ai-wrap"
@
mouseenter=
"handleSwitchAiContentShowBox5(true)"
>
<AiButton
/>
</div>
<div
class=
"ai-content"
v-if=
"isShowAiContentBox5"
@
mouseleave=
"handleSwitchAiContentShowBox5(false)"
>
<AiPane
:aiContent=
"aiContentBox5"
/>
</div>
</
template
>
</div>
</AnalysisBox>
</div>
<div
class=
"box2"
>
<!-- <div class="box-header">
<div class="header-left"></div>
<div class="title">涉及科技领域</div>
<div class="header-right">
<div class="icon">
<img src="@/assets/icons/box-header-icon2.png" alt="" />
</div>
<div class="icon">
<img src="@/assets/icons/box-header-icon3.png" alt="" />
</div>
</div>
</div>
<div class="box2-main">
<div class="box2-content" id="box2Chart"></div>
</div> -->
<AnalysisBox
title=
"项目报告"
:showAllBtn=
"true"
>
<div
class=
"box2-main"
>
<div
class=
"box2-item"
v-for=
"(report, idx) in reportList"
:key=
"idx"
>
<div
class=
"box2-item-content"
>
<div
class=
"left"
><img
:src=
"report.image"
alt=
""
/></div>
<div
class=
"right-content"
>
<div
class=
"report-title"
>
{{ report.name }}
</div>
<div
class=
"report-footer"
>
<div
class=
"report-time"
>
{{ report.postDate }}
</div>
<div
class=
"report-footer-right"
>
<div
class=
"footer-image"
>
<img
:src=
"report.thinktankLogo"
alt=
""
/>
</div>
<div
class=
"think-name"
>
{{ report.thinktankName }}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</AnalysisBox>
</div>
</div>
<div
class=
"right"
>
<div
class=
"box3"
>
<AnalysisBox
title=
"内容摘要"
:showAllBtn=
"true"
>
<div
class=
"box3-main"
>
<AiSummary>
<
template
#
summary-content
>
{{
box1Data
}}
</
template
>
</AiSummary>
</div>
</AnalysisBox>
</div>
<div
class=
"box4"
>
<AnalysisBox
title=
"项目背景"
:showAllBtn=
"true"
>
<div
class=
"box4-main"
>
<div
class=
"text"
>
{{
"可再生能源和清洁能源创新为摆脱对化石燃料的依赖提供了机会。然而,可再生能源的间歇性也对电网的实时供需平衡构成挑战。作为解决方案,中国提出开发全球能源互联(GEI)倡议,通过超高压输电线路和智能技术,直接将可再生能源生产者与全球消费者连接起来。北京认识到GEI的潜力,正站在GEI发展的前沿,领导关键推动技术的研究,输出中国技术和标准,支持海外发电和输电基础设施的发展。中国还在联合国和海湾合作委员会等国际组织推动GEI"
}}
</div>
</div>
</AnalysisBox>
</div>
<div
class=
"box5"
>
<AnalysisBox
title=
"项目团队"
:showAllBtn=
"true"
>
<div
class=
"box5-main"
>
<div
class=
"box5-main-item-box"
>
<div
class=
"item"
>
<div
class=
"item-left"
>
<img
src=
"../assets/images/rand-image.png"
alt=
""
/>
</div>
<div
class=
"item-right"
>
<div
class=
"item-name"
>
{{ "纳迪娅·阿尔马萨尔基" }}
</div>
<div
class=
"item-position"
>
{{ "副秘书" }}
</div>
</div>
</div>
<div
class=
"item"
>
<div
class=
"item-left"
>
<img
src=
"../assets/images/rand-image.png"
alt=
""
/>
</div>
<div
class=
"item-right"
>
<div
class=
"item-name"
>
{{ "纳迪娅·阿尔马萨尔基" }}
</div>
<div
class=
"item-position"
>
{{ "副秘书" }}
</div>
</div>
</div>
<div
class=
"item"
>
<div
class=
"item-left"
>
<img
src=
"../assets/images/rand-image.png"
alt=
""
/>
</div>
<div
class=
"item-right"
>
<div
class=
"item-name"
>
{{ "纳迪娅·阿尔马萨尔基" }}
</div>
<div
class=
"item-position"
>
{{ "副秘书" }}
</div>
</div>
</div>
<div
class=
"item"
>
<div
class=
"item-left"
>
<img
src=
"../assets/images/rand-image.png"
alt=
""
/>
</div>
<div
class=
"item-right"
>
<div
class=
"item-name"
>
{{ "纳迪娅·阿尔马萨尔基" }}
</div>
<div
class=
"item-position"
>
{{ "副秘书" }}
</div>
</div>
</div>
<div
class=
"item"
>
<div
class=
"item-left"
>
<img
src=
"../assets/images/rand-image.png"
alt=
""
/>
</div>
<div
class=
"item-right"
>
<div
class=
"item-name"
>
{{ "纳迪娅·阿尔马萨尔基" }}
</div>
<div
class=
"item-position"
>
{{ "副秘书" }}
</div>
</div>
</div>
<div
class=
"item"
>
<div
class=
"item-left"
>
<img
src=
"../assets/images/rand-image.png"
alt=
""
/>
</div>
<div
class=
"item-right"
>
<div
class=
"item-name"
>
{{ "纳迪娅·阿尔马萨尔基" }}
</div>
<div
class=
"item-position"
>
{{ "副秘书" }}
</div>
</div>
</div>
</div>
</div>
</AnalysisBox>
</div>
</div>
</div>
</div>
</div>
</template>
<
script
setup
>
import
DefaultIcon1
from
'@/assets/icons/default-icon1.png'
import
WarningPane
from
"@/components/base/WarningPane/index.vue"
import
WordCloudChart
from
"@/components/base/WordCloundChart/index.vue"
import
SearchContainer
from
"@/components/SearchContainer.vue"
;
import
{
ref
,
onMounted
,
computed
,
defineProps
}
from
"vue"
;
import
{
ElMessage
}
from
"element-plus"
;
import
{
getThinkTankReportAbstract
,
getThinkTankReportContent
,
getThinkTankReportIndustry
,
getThinkTankReportIndustryCloud
,
getThinkTankReportViewpoint
}
from
"@/api/thinkTank/overview"
;
import
{
getChartAnalysis
}
from
"@/api/aiAnalysis/index"
;
import
{
useRouter
}
from
"vue-router"
;
import
"echarts-wordcloud"
;
import
AiSummary
from
'@/components/base/Ai/AiSummary/index.vue'
import
{
getPersonSummaryInfo
}
from
"@/api/common/index"
;
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"
;
const
router
=
useRouter
();
const
thinkInfo
=
ref
({
name
:
"探讨中国开发和管理的跨大陆电网的安全影响"
,
ename
:
"调查项目"
,
tags
:
[{
industryName
:
"深海"
},
{
industryName
:
"人工智能"
}],
thinkTankName
:
"兰德科技智库"
})
const
REPORT_ANALYSIS_TIP_BOX5
=
"智库报告关键词云,数据来源:美国兰德公司官网"
;
// 刷新后默认展示「报告关键词云」AI 总结
const
isShowAiContentBox5
=
ref
(
true
);
const
aiContentBox5
=
ref
(
""
);
const
isBox5InterpretLoading
=
ref
(
false
);
const
handleSwitchAiContentShowBox5
=
(
val
)
=>
{
isShowAiContentBox5
.
value
=
val
;
if
(
val
)
{
fetchBox5ChartInterpretation
();
}
};
const
searchOpinions
=
ref
(
''
);
const
escapeHtml
=
(
text
)
=>
{
return
String
(
text
??
""
)
.
replace
(
/&/g
,
"&"
)
.
replace
(
/</g
,
"<"
)
.
replace
(
/>/g
,
">"
)
.
replace
(
/"/g
,
"""
)
.
replace
(
/'/g
,
"'"
);
};
const
escapeRegExp
=
(
text
)
=>
{
return
String
(
text
??
""
).
replace
(
/
[
.*+?^${}()|[
\]\\]
/g
,
"
\\
$&"
);
};
/** 可同时展开多条;用 id 区分项,避免翻页后索引与展开状态错位 */
const
expandedOpinionKeys
=
ref
(
new
Set
());
const
getOpinionExpandKey
=
(
item
,
index
)
=>
{
if
(
item
!=
null
&&
item
.
id
!=
null
&&
item
.
id
!==
""
)
{
return
String
(
item
.
id
);
}
return
`idx-
${
index
}
`
;
};
// 内容摘要
const
box1Data
=
ref
(
`包括经济竞争在内的美中竞争自2017年以来一直在定义美国外交政策。这两个经济体是世界上第一和第二大国家经济体,并且深深交织在一起。改变关系,无论多么必要,可能是昂贵的。因此,美国面临着一项挑战,确保其经济在耦合的战略竞争条件下满足国家的需求。
为了应对这一挑战,兰德大学的研究人员对美中竞争进行了经济和制度分析,进行了参与式的远见练习,以了解确保美国经济健康的长期路径,并创建了两个经济竞争游戏,探索多个国家在相互交流的同时确保经济健康的动态...`
);
//获取内容摘要
const
handleGetThinkTankReportAbstract
=
async
()
=>
{
try
{
const
res
=
await
getThinkTankReportAbstract
(
router
.
currentRoute
.
_value
.
params
.
id
);
console
.
log
(
"内容摘要"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
box1Data
.
value
=
res
.
data
;
}
}
catch
(
error
)
{
console
.
error
(
"获取内容摘要error"
,
error
);
}
};
// 涉及科技领域
const
areaList
=
ref
([]);
const
activeArea
=
ref
(
6
);
const
handleClickArea
=
area
=>
{
activeArea
.
value
=
area
;
handleGetThinkTankReportIndustryCloud
();
};
const
box2Data
=
ref
([
// {
// name: "通用人工智能",
// value: 100
// },
// {
// name: "AI芯片",
// value: 66
// },
// {
// name: "计算能力又是",
// value: 72
// },
// {
// name: "基准测试",
// value: 88
// },
// {
// name: "出口管制",
// value: 78
// },
// {
// name: "军事AI",
// value: 85
// },
// {
// name: "生态系统",
// value: 88
// },
// {
// name: "模型能力",
// value: 89
// }
]);
// 报告关键词云
const
box5Data
=
ref
([]);
const
hasBox5ChartData
=
computed
(()
=>
Array
.
isArray
(
box5Data
.
value
)
&&
box5Data
.
value
.
length
>
0
);
/** 词云子组件不 watch 数据,每次接口成功有数据时递增 key,强制重新挂载以触发 onMounted */
const
box5WordCloudKey
=
ref
(
0
);
//获取科技领域词云
const
handleGetThinkTankReportIndustryCloud
=
async
()
=>
{
try
{
const
params
=
{
id
:
router
.
currentRoute
.
_value
.
params
.
id
// industryId: activeArea.value
};
const
res
=
await
getThinkTankReportIndustryCloud
(
params
);
console
.
log
(
"科技领域词云"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
const
data
=
(
res
.
data
||
[]).
map
(
item
=>
({
name
:
item
.
clause
,
value
:
item
.
count
}));
// 该接口数据用于「报告关键词云」
box5Data
.
value
=
data
;
if
(
data
.
length
)
{
box5WordCloudKey
.
value
+=
1
;
}
// 刷新后默认展开 AI:数据就绪即触发解读
if
(
isShowAiContentBox5
.
value
)
{
fetchBox5ChartInterpretation
();
}
}
else
{
box5Data
.
value
=
[];
}
}
catch
(
error
)
{
console
.
error
(
"获取科技领域词云error"
,
error
);
box5Data
.
value
=
[];
}
};
//涉及科技领域
const
handleGetThinkTankReportIndustry
=
async
()
=>
{
try
{
const
res
=
await
getThinkTankReportIndustry
(
router
.
currentRoute
.
_value
.
params
.
id
);
console
.
log
(
"涉及科技领域"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
areaList
.
value
=
res
.
data
;
}
}
catch
(
error
)
{
console
.
error
(
"获取涉及科技领域error"
,
error
);
}
};
// 主要观点
const
majorOpinions
=
ref
([
{
id
:
1
,
title
:
"我是示例标题"
,
desc
:
"我是示例内容"
,
tagList
:
[
{
name
:
"关税"
,
status
:
2
},
{
name
:
"跨境电商"
,
status
:
1
}
]
},
{
id
:
2
,
title
:
"我是示例标题"
,
desc
:
"我是示例内容"
,
tagList
:
[
{
name
:
"私有经济"
,
status
:
2
}
]
}
]);
//处理点击详情页事件
const
handleOpenReportOriginal
=
item
=>
{
const
route
=
router
.
resolve
({
name
:
"ReportOriginal"
,
params
:
{
id
:
router
.
currentRoute
.
_value
.
params
.
id
},
query
:
{
currentPage
:
currentPage
.
value
,
pageSize
:
pageSize
.
value
,
opinionId
:
item
?.
id
??
""
,
opinionContent
:
item
?.
content
??
""
}
});
window
.
open
(
route
.
href
,
"_blank"
);
};
const
tabActiveName
=
ref
(
"报告分析"
);
const
switchTab
=
name
=>
{
tabActiveName
.
value
=
name
;
};
// 处理页码改变事件
const
currentPage
=
ref
(
1
);
const
pageSize
=
ref
(
10
);
const
total
=
ref
(
0
);
const
handleCurrentChange
=
page
=>
{
currentPage
.
value
=
page
;
handleGetThinkTankReportViewpoint
();
};
// 获取报告核心论点(支持搜索)
const
handleGetThinkTankReportViewpoint
=
async
()
=>
{
try
{
const
params
=
{
reportId
:
router
.
currentRoute
.
_value
.
params
.
id
,
currentPage
:
currentPage
.
value
-
1
,
pageSize
:
pageSize
.
value
,
keyword
:
(
searchOpinions
.
value
||
""
).
trim
(),
orgIds
:
""
};
const
res
=
await
getThinkTankReportViewpoint
(
params
);
console
.
log
(
"核心论点"
,
res
.
data
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
const
nextOpinions
=
res
.
data
.
content
||
[];
majorOpinions
.
value
=
nextOpinions
;
total
.
value
=
res
.
data
.
totalElements
||
0
;
// 默认:第一条展开,其余关闭
const
nextExpandedKeys
=
new
Set
();
if
(
Array
.
isArray
(
nextOpinions
)
&&
nextOpinions
.
length
>
0
)
{
nextExpandedKeys
.
add
(
getOpinionExpandKey
(
nextOpinions
[
0
],
0
));
}
expandedOpinionKeys
.
value
=
nextExpandedKeys
;
}
}
catch
(
error
)
{
console
.
error
(
"获取主要观点error"
,
error
);
}
};
// 获取图表分析内容
const
box3AnalysisContent
=
ref
(
""
);
const
handleGetBox3AnalysisContent
=
async
textJson
=>
{
const
params
=
{
text
:
textJson
};
const
res
=
await
getChartAnalysis
(
params
);
console
.
log
(
"图表解析内容"
,
res
);
};
const
getInterpretationTextFromChartResponse
=
(
res
)
=>
{
const
list
=
res
?.
data
;
const
first
=
Array
.
isArray
(
list
)
?
list
[
0
]
:
null
;
return
(
first
?.[
"解读"
]
||
first
?.[
"interpretation"
]
||
first
?.[
"analysis"
]
||
first
?.[
"content"
]
||
""
);
};
const
appendAiInterpretationChunk
=
(
targetRef
,
chunk
,
loadingText
=
"解读生成中…"
)
=>
{
if
(
!
chunk
)
{
return
;
}
const
current
=
String
(
targetRef
.
value
||
""
);
const
base
=
current
===
loadingText
?
""
:
current
;
targetRef
.
value
=
base
+
String
(
chunk
);
};
const
fetchBox5ChartInterpretation
=
async
()
=>
{
const
list
=
Array
.
isArray
(
box5Data
.
value
)
?
box5Data
.
value
:
[];
if
(
!
list
.
length
)
{
aiContentBox5
.
value
=
"暂无图表数据"
;
return
;
}
const
hasValidContent
=
aiContentBox5
.
value
&&
aiContentBox5
.
value
!==
"解读生成中…"
&&
aiContentBox5
.
value
!==
"解读加载失败"
&&
aiContentBox5
.
value
!==
"暂无图表数据"
;
if
(
hasValidContent
||
isBox5InterpretLoading
.
value
)
{
return
;
}
isBox5InterpretLoading
.
value
=
true
;
aiContentBox5
.
value
=
"解读生成中…"
;
const
chartPayload
=
{
type
:
"词云图"
,
name
:
"报告关键词云"
,
data
:
list
.
map
((
item
)
=>
({
name
:
item
.
name
,
value
:
item
.
value
}))
};
try
{
const
res
=
await
getChartAnalysis
(
{
text
:
JSON
.
stringify
(
chartPayload
)
},
{
onChunk
:
chunk
=>
{
appendAiInterpretationChunk
(
aiContentBox5
,
chunk
);
}
}
);
const
text
=
getInterpretationTextFromChartResponse
(
res
);
aiContentBox5
.
value
=
text
||
aiContentBox5
.
value
||
"未返回有效解读内容"
;
}
catch
(
error
)
{
console
.
error
(
"报告关键词云图表解读请求失败"
,
error
);
aiContentBox5
.
value
=
"解读加载失败"
;
}
finally
{
isBox5InterpretLoading
.
value
=
false
;
}
};
onMounted
(()
=>
{
handleGetThinkTankReportAbstract
();
handleGetThinkTankReportViewpoint
();
handleGetThinkTankReportIndustry
();
handleGetThinkTankReportIndustryCloud
();
});
</
script
>
<
style
lang=
"scss"
scoped
>
.wrap
{
position
:
absolute
;
inset
:
0
;
box-sizing
:
border-box
;
width
:
100%
;
overflow
:
hidden
;
.scroll-inner
{
box-sizing
:
border-box
;
width
:
100%
;
height
:
100%
;
min-height
:
0
;
padding-bottom
:
16px
;
overflow-x
:
hidden
;
overflow-y
:
auto
;
scrollbar-gutter
:
stable
;
scrollbar-width
:
thin
;
&
:
:-
webkit-scrollbar
{
width
:
8px
;
}
&
:
:-
webkit-scrollbar-thumb
{
border-radius
:
4px
;
}
}
.header
{
width
:
100%
;
min-height
:
94px
;
box-sizing
:
border-box
;
border-bottom
:
1px
solid
rgba
(
234
,
236
,
238
,
1
);
box-shadow
:
0px
0px
20px
0px
rgba
(
25
,
69
,
130
,
0
.1
);
background
:
rgba
(
255
,
255
,
255
,
1
);
position
:
sticky
;
top
:
0
;
z-index
:
99999
;
overflow
:
hidden
;
.header-top
{
margin
:
0
auto
;
margin-top
:
20px
;
width
:
1600px
;
display
:
flex
;
justify-content
:
space-between
;
.header-top-left
{
display
:
flex
;
img
{
width
:
54px
;
height
:
54px
;
}
.title
{
margin-left
:
20px
;
font-family
:
"Source Han Sans CN"
;
font-weight
:
700
;
font-size
:
20px
;
line-height
:
26px
;
letter-spacing
:
0
;
text-align
:
left
;
color
:
rgb
(
59
,
65
,
75
);
}
.en-title
{
margin-left
:
20px
;
margin-top
:
4px
;
font-family
:
"Source Han Sans CN"
;
font-weight
:
400
;
font-size
:
16px
;
line-height
:
24px
;
letter-spacing
:
0
;
text-align
:
left
;
color
:
rgb
(
95
,
101
,
108
);
}
}
.header-top-right
{
display
:
flex
;
flex-direction
:
column
;
text-align
:
right
;
align-items
:
flex-end
;
.image-name-box
{
width
:
118px
;
height
:
24px
;
gap
:
6px
;
text-align
:
right
;
display
:
flex
;
justify-content
:
flex-end
;
.name
{
height
:
24px
;
color
:
rgba
(
95
,
101
,
108
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
400
;
line-height
:
24px
;
letter-spacing
:
0px
;
text-align
:
right
;
}
.image
{
width
:
16px
;
height
:
16px
;
margin-top
:
5px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
}
.tag-box
{
margin-top
:
7px
;
display
:
flex
;
gap
:
8px
;
}
}
}
}
.bottom-row
{
flex-direction
:
row
;
justify-content
:
center
;
display
:
flex
;
gap
:
16px
;
margin-bottom
:
70px
;
.left
{
gap
:
16px
;
display
:
flex
;
flex-direction
:
column
;
.box1
{
width
:
480px
;
height
:
415px
;
margin-top
:
17px
;
.box1-main
{
width
:
480px
;
height
:
361px
;
padding
:
24px
24px
65px
24px
;
display
:
flex
;
flex-direction
:
column
;
box-sizing
:
border-box
;
overflow
:
hidden
;
position
:
relative
;
.box5Chart
{
width
:
100%
;
height
:
100%
;
margin
:
0
auto
;
overflow
:
hidden
;
}
.box1-footer
{
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
position
:
absolute
;
bottom
:
20px
;
left
:
32px
;
}
.ai-wrap
{
position
:
absolute
;
bottom
:
18px
;
right
:
0
;
cursor
:
pointer
;
}
.ai-content
{
position
:
absolute
;
bottom
:
0
;
right
:
0
;
min-width
:
480px
;
min-height
:
156px
;
}
}
}
.box2
{
width
:
480px
;
// 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);
.box2-main
{
width
:
436px
;
margin-top
:
5px
;
margin-left
:
23px
;
.box2-item
{
height
:
103px
;
width
:
100%
;
border-bottom
:
1px
solid
rgba
(
234
,
236
,
238
,
1
);
border-top
:
1px
solid
rgba
(
234
,
236
,
238
,
1
);
.box2-item-content
{
width
:
100%
;
height
:
90px
;
margin-top
:
7px
;
display
:
flex
;
.left
{
width
:
56px
;
height
:
74px
;
margin-top
:
8px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.right-content
{
margin-left
:
13px
;
width
:
365px
;
height
:
76px
;
margin-top
:
7px
;
.report-title
{
height
:
48px
;
font-family
:
"Source Han Sans CN"
;
font-weight
:
700
;
font-size
:
16px
;
line-height
:
24px
;
letter-spacing
:
0
;
text-align
:
left
;
/* 👇 下面是 两行文本超出省略 核心代码 */
display
:
-
webkit-box
;
-webkit-line-clamp
:
2
;
/* 限制显示 2 行 */
-webkit-box-orient
:
vertical
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
word-break
:
break-all
;
}
.report-footer
{
margin-top
:
4px
;
height
:
22px
;
justify-content
:
space-between
;
display
:
flex
;
.report-time
{
height
:
22px
;
width
:
97px
;
font-family
:
"Source Han Sans CN"
;
font-weight
:
400
;
font-size
:
14px
;
line-height
:
22px
;
letter-spacing
:
0
;
text-align
:
left
;
color
:
rgb
(
95
,
101
,
108
);
}
.report-footer-right
{
height
:
22px
;
display
:
flex
;
gap
:
6px
;
.footer-image
{
width
:
16px
;
height
:
16px
;
margin-top
:
3px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.think-name
{
height
:
22px
;
}
}
}
}
}
}
}
.box2-btn
{
margin-top
:
16px
;
margin-bottom
:
21px
;
margin-left
:
23px
;
width
:
436px
;
height
:
36px
;
background-color
:
rgb
(
5
,
95
,
194
);
border-radius
:
6px
;
display
:
flex
;
.btn-text
{
color
:
rgb
(
255
,
255
,
255
);
font-family
:
"Source Han Sans CN"
;
font-weight
:
400
;
font-size
:
16px
;
line-height
:
22px
;
letter-spacing
:
0
;
margin-left
:
120px
;
margin-top
:
7px
;
}
.btn-image
{
width
:
13px
;
height
:
8px
;
margin-left
:
8px
;
display
:
inline-block
;
margin-top
:
14px
;
img
{
width
:
100%
;
height
:
100%
;
display
:
block
;
}
}
}
}
}
.right
{
margin-top
:
17px
;
gap
:
16px
;
display
:
flex
;
flex-direction
:
column
;
.box3
{
width
:
1103px
;
// 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);
.box3-main
{
width
:
1058px
;
margin-top
:
3px
;
margin-left
:
22px
;
padding-bottom
:
22px
;
:deep
(
.summary-main
)
{
margin-bottom
:
25px
;
font-family
:
"Source Han Sans CN"
;
font-weight
:
400
;
/* Regular 常规 */
font-size
:
16px
;
line-height
:
30px
;
letter-spacing
:
0px
;
text-align
:
justify
;
color
:
rgb
(
59
,
65
,
75
);
/* 两端对齐 */
}
.box3-top
{
width
:
1058px
;
height
:
48px
;
background
:
linear-gradient
(
rgb
(
137
,
193
,
255
,
0
.1
)
,
rgb
(
255
,
255
,
255
));
display
:
flex
;
.top-title
{
width
:
1010px
;
height
:
32px
;
margin-left
:
24px
;
margin-top
:
16px
;
.title-image
{
width
:
199px
;
height
:
32px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
}
}
.box3-text
{
width
:
1006px
;
margin-top
:
24px
;
margin-left
:
26px
;
font-family
:
"Source Han Sans CN"
;
font-weight
:
400
;
font-size
:
16px
;
line-height
:
30px
;
letter-spacing
:
0px
;
text-align
:
justify
;
text-justify
:
inter-ideograph
;
}
}
}
.box4
{
width
:
1103px
;
height
:
auto
;
// 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
;
.box4-main
{
width
:
1103px
;
padding
:
5px
24px
21px
28px
;
.text
{
font-family
:
"Source Han Sans CN"
;
font-weight
:
400
;
/* Regular */
font-size
:
16px
;
line-height
:
30px
;
letter-spacing
:
0px
;
text-align
:
left
;
color
:
rgb
(
59
,
65
,
75
);
}
}
}
.box5
{
width
:
1103px
;
height
:
auto
;
position
:
relative
;
.box5-main
{
width
:
1103px
;
padding
:
3px
18px
21px
20px
;
.box5-main-item-box
{
width
:
1065px
;
display
:
grid
;
grid-template-columns
:
1fr
1fr
;
gap
:
12px
0
;
.item
{
width
:
532
.5px
;
height
:
49px
;
display
:
flex
;
flex-direction
:
row
;
.item-left
{
width
:
42px
;
height
:
42px
;
border-radius
:
50%
;
margin-top
:
3px
;
margin-left
:
3px
;
img
{
width
:
100%
;
height
:
100%
;
display
:
block
;
border-radius
:
50%
;
/* 图片也要加,不然会漏出直角 */
object-fit
:
cover
;
/* 防止图片变形 */
}
}
.item-right
{
height
:
49px
;
margin-left
:
11px
;
display
:
flex
;
flex-direction
:
column
;
.item-name
{
height
:
24px
;
margin-top
:
1px
;
font-family
:
"Source Han Sans CN"
;
font-weight
:
700
;
/* Bold 粗体 */
font-size
:
16px
;
line-height
:
24px
;
letter-spacing
:
0px
;
text-align
:
left
;
color
:
rgb
(
59
,
65
,
75
);
}
.item-position
{
height
:
22px
;
font-family
:
"Source Han Sans CN"
;
font-weight
:
400
;
/* Regular */
font-size
:
14px
;
line-height
:
22px
;
letter-spacing
:
0
;
text-align
:
left
;
color
:
rgb
(
95
,
101
,
108
);
}
}
}
}
}
}
}
}
}
:deep
(
.analysis-box-wrapper
.wrapper-header
)
{
height
:
54px
!
important
;
display
:
flex
;
align-items
:
center
;
.header-title
>
div
{
line-height
:
54px
;
}
}
</
style
>
src/views/thinkTank/ThinkTankDetail/PolicyTracking/index.vue
浏览文件 @
75b87091
...
@@ -1221,7 +1221,7 @@ function mapPolicyRowToView(row) {
...
@@ -1221,7 +1221,7 @@ function mapPolicyRowToView(row) {
const
toDetail
=
item
=>
{
const
toDetail
=
item
=>
{
window
.
sessionStorage
.
setItem
(
"curTabName"
,
item
.
contentZh
??
item
.
content
??
""
);
window
.
sessionStorage
.
setItem
(
"curTabName"
,
item
.
contentZh
??
item
.
content
??
""
);
const
route
=
router
.
resolve
({
const
route
=
router
.
resolve
({
name
:
"Report
Origina
l"
,
name
:
"Report
Detai
l"
,
params
:
{
params
:
{
id
:
item
.
reportId
id
:
item
.
reportId
}
}
...
...
src/views/thinkTank/components/ThinkTankPolicyAdviceOverview.vue
浏览文件 @
75b87091
...
@@ -120,7 +120,7 @@ const handleOpenReportOriginal = (item) => {
...
@@ -120,7 +120,7 @@ const handleOpenReportOriginal = (item) => {
const
reportId
=
item
?.
reportId
||
item
?.
report_id
||
item
?.
id
const
reportId
=
item
?.
reportId
||
item
?.
report_id
||
item
?.
id
if
(
!
reportId
)
return
if
(
!
reportId
)
return
const
route
=
router
.
resolve
({
const
route
=
router
.
resolve
({
name
:
"Report
Origina
l"
,
name
:
"Report
Detai
l"
,
params
:
{
id
:
String
(
reportId
)
}
params
:
{
id
:
String
(
reportId
)
}
})
})
window
.
open
(
route
.
href
,
"_blank"
)
window
.
open
(
route
.
href
,
"_blank"
)
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论