Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
risk-monitor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
1
合并请求
1
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蔡建
risk-monitor
Commits
95cb197b
提交
95cb197b
authored
3月 24, 2026
作者:
yanpeng
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' into yp-dev
上级
afd6e682
7a6c33cb
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
48 个修改的文件
包含
769 行增加
和
314 行删除
+769
-314
.gitignore
.gitignore
+1
-0
App.vue
src/App.vue
+19
-0
index.js
src/api/aiAnalysis/index.js
+77
-3
api_doc.md
src/api/api_doc.md
+9
-0
overview.js
src/api/thinkTank/overview.js
+98
-11
down.png
src/components/base/WarningPane/icons/down.png
+0
-0
up.png
src/components/base/WarningPane/icons/up.png
+0
-0
index.vue
src/components/base/WarningPane/index.vue
+64
-10
IntelligentEntityText.vue
src/components/base/texts/IntelligentEntityText.vue
+97
-97
TextTranslatePane.vue
src/components/base/texts/TextTranslatePane.vue
+106
-93
index.js
src/router/index.js
+1
-0
company.js
src/router/modules/company.js
+7
-0
comprehensiveSearch.js
src/router/modules/comprehensiveSearch.js
+36
-37
setChart.js
src/utils/setChart.js
+23
-2
index.vue
src/views/bill/billHome/index.vue
+24
-10
index.vue
src/views/dataLibrary/bill/countryBill/index.vue
+0
-0
index.vue
src/views/dataLibrary/components/ChartHeader/index.vue
+1
-1
index.vue
src/views/dataLibrary/index.vue
+117
-4
index.vue
src/views/home/index.vue
+3
-3
NewsDetial.vue
src/views/newsBrief/NewsDetial.vue
+0
-0
NewsMain.vue
src/views/newsBrief/NewsMain.vue
+9
-7
index.vue
src/views/thinkTank/MultiThinkTankViewAnalysis/index.vue
+0
-0
index.vue
src/views/thinkTank/ReportDetail/policyTracking/index.vue
+3
-3
index.vue
src/views/thinkTank/ReportDetail/reportAnalysis/index.vue
+0
-0
index.vue
src/views/thinkTank/ThinkTankDetail/PolicyTracking/index.vue
+0
-0
multiLineChart.js
...nk/ThinkTankDetail/PolicyTracking/utils/multiLineChart.js
+74
-33
index.vue
...k/ThinkTankDetail/thinkDynamics/CongressHearing/index.vue
+0
-0
index.vue
...nkTank/ThinkTankDetail/thinkDynamics/SurveyForm/index.vue
+0
-0
index.vue
...k/ThinkTankDetail/thinkDynamics/ThinkTankReport/index.vue
+0
-0
index.vue
src/views/thinkTank/ThinkTankDetail/thinkDynamics/index.vue
+0
-0
left-page-btn.png
...nkTank/ThinkTankDetail/thinkInfo/images/left-page-btn.png
+0
-0
right-page-btn.png
...kTank/ThinkTankDetail/thinkInfo/images/right-page-btn.png
+0
-0
index.vue
src/views/thinkTank/ThinkTankDetail/thinkInfo/index.vue
+0
-0
index.vue
src/views/thinkTank/allThinkTank/index.vue
+0
-0
being-analysis-circle.png
src/views/thinkTank/assets/images/being-analysis-circle.png
+0
-0
being-analysis.png
src/views/thinkTank/assets/images/being-analysis.png
+0
-0
blue-down.png
src/views/thinkTank/assets/images/blue-down.png
+0
-0
blue-up.png
src/views/thinkTank/assets/images/blue-up.png
+0
-0
empty-analysis.png
src/views/thinkTank/assets/images/empty-analysis.png
+0
-0
empty-image.png
src/views/thinkTank/assets/images/empty-image.png
+0
-0
HomeMainFooterMain.vue
src/views/thinkTank/components/HomeMainFooterMain.vue
+0
-0
HomeMainFooterSurvey.vue
src/views/thinkTank/components/HomeMainFooterSurvey.vue
+0
-0
ThinkTankCongressHearingOverview.vue
...thinkTank/components/ThinkTankCongressHearingOverview.vue
+0
-0
ThinkTankPolicyAdviceOverview.vue
...ws/thinkTank/components/ThinkTankPolicyAdviceOverview.vue
+0
-0
index.vue
src/views/thinkTank/index.vue
+0
-0
multiLineChart.js
src/views/thinkTank/utils/multiLineChart.js
+0
-0
resourceLibraryFilters.js
src/views/thinkTank/utils/resourceLibraryFilters.js
+0
-0
sankey.js
src/views/thinkTank/utils/sankey.js
+0
-0
没有找到文件。
.gitignore
浏览文件 @
95cb197b
...
...
@@ -14,6 +14,7 @@ lerna-debug.log*
# Dependencies
node_modules
*node_modules
.pnpm
.npm
...
...
src/App.vue
浏览文件 @
95cb197b
...
...
@@ -29,6 +29,25 @@ import { ElMessage } from "element-plus";
const
router
=
useRouter
();
const
route
=
useRoute
();
import
useTagsViewStore
from
'@/stores/tagsView.js'
const
tagsViewStore
=
useTagsViewStore
()
// 在路由全局守卫中处理
router
.
beforeEach
((
to
,
from
,
next
)
=>
{
// 路由允许添加标签(排除掉隐藏的布局页如 /404, /login 等)
if
(
to
.
path
.
includes
(
'dataLibrary'
))
{
tagsViewStore
.
addView
({
path
:
to
.
path
,
name
:
to
.
name
,
// 对应组件的 name,用于缓存
meta
:
{
...
to
.
meta
},
active
:
true
})
}
next
()
})
const
isShowAiBox
=
ref
(
false
);
...
...
src/api/aiAnalysis/index.js
浏览文件 @
95cb197b
...
...
@@ -36,6 +36,47 @@ function parseChartInterpretationArray(buffer) {
throw
new
Error
(
"无法解析图表解读 JSON 数组"
);
}
/**
* 从数组结果中提取可展示的解读文本
* @param {unknown[]} arr
* @returns {string}
*/
function
pickInterpretationText
(
arr
)
{
if
(
!
Array
.
isArray
(
arr
)
||
arr
.
length
===
0
)
{
return
""
;
}
const
first
=
arr
[
0
]
||
{};
return
(
first
[
"解读"
]
||
first
[
"interpretation"
]
||
first
[
"analysis"
]
||
first
[
"content"
]
||
""
);
}
/**
* 从非标准 JSON 文本中兜底提取“解读”字段(兼容单引号/双引号)
* 示例:
* [{'图表标题': '数量变化趋势', '解读': 'xxx'}]
* [{"图表标题":"数量变化趋势","解读":"xxx"}]
* @param {string} text
* @returns {string}
*/
function
extractInterpretationFromLooseText
(
text
)
{
const
raw
=
String
(
text
||
""
);
if
(
!
raw
)
{
return
""
;
}
const
reg
=
/
[
"'
]
解读
[
"'
]\s
*:
\s
*
[
"'
]([\s\S]
*
?)[
"'
]\s
*
(?:[
,}
\]])
/
;
const
m
=
raw
.
match
(
reg
);
if
(
!
m
||
!
m
[
1
])
{
return
""
;
}
return
String
(
m
[
1
]).
replace
(
/
\\
n/g
,
"
\
n"
).
trim
();
}
/**
* 图表解读(SSE 流式)
* @param {object} data - 请求体
...
...
@@ -44,9 +85,15 @@ function parseChartInterpretationArray(buffer) {
* @returns {Promise<{data: unknown[]}>}
*/
export
function
getChartAnalysis
(
data
,
options
=
{})
{
const
{
onChunk
}
=
options
;
const
onDelta
=
typeof
options
?.
onChunk
===
"function"
?
options
.
onChunk
:
typeof
options
?.
onInterpretationDelta
===
"function"
?
options
.
onInterpretationDelta
:
null
;
return
new
Promise
((
resolve
,
reject
)
=>
{
let
buffer
=
""
;
let
latestInterpretation
=
""
;
let
settled
=
false
;
const
abortController
=
new
AbortController
();
...
...
@@ -119,9 +166,18 @@ export function getChartAnalysis(data, options = {}) {
buffer
+=
raw
;
}
// 兜底:非标准 JSON(如单引号 Python 风格)时,尝试直接从文本提取“解读”
const
looseInterpretation
=
extractInterpretationFromLooseText
(
raw
);
if
(
looseInterpretation
)
{
latestInterpretation
=
looseInterpretation
;
safeResolve
({
data
:
[{
解读
:
looseInterpretation
}]
});
abortController
.
abort
();
return
;
}
// 每收到一条消息即回调,用于流式渲染
if
(
chunk
&&
typeof
onChunk
===
"function"
)
{
on
Chunk
(
chunk
);
if
(
chunk
&&
onDelta
)
{
on
Delta
(
chunk
);
}
// 如果 buffer 已经拼完 markdown code fence,则提前解析并中断连接
...
...
@@ -129,6 +185,10 @@ export function getChartAnalysis(data, options = {}) {
if
(
trimmed
.
endsWith
(
"```"
))
{
try
{
const
arr
=
parseChartInterpretationArray
(
trimmed
);
const
interpretation
=
pickInterpretationText
(
arr
);
if
(
interpretation
)
{
latestInterpretation
=
interpretation
;
}
safeResolve
({
data
:
arr
});
abortController
.
abort
();
}
catch
(
_
)
{
}
...
...
@@ -137,8 +197,22 @@ export function getChartAnalysis(data, options = {}) {
onclose
:
()
=>
{
try
{
const
arr
=
parseChartInterpretationArray
(
buffer
);
const
interpretation
=
pickInterpretationText
(
arr
);
if
(
interpretation
)
{
latestInterpretation
=
interpretation
;
}
safeResolve
({
data
:
arr
});
}
catch
(
e
)
{
// 兜底:整体 buffer 不是标准 JSON(如单引号)时直接提取“解读”
const
looseInterpretation
=
extractInterpretationFromLooseText
(
buffer
);
if
(
looseInterpretation
)
{
safeResolve
({
data
:
[{
解读
:
looseInterpretation
}]
});
return
;
}
if
(
latestInterpretation
)
{
safeResolve
({
data
:
[{
解读
:
latestInterpretation
}]
});
return
;
}
safeReject
(
e
);
}
},
...
...
src/api/api_doc.md
浏览文件 @
95cb197b
...
...
@@ -1156,6 +1156,15 @@
| -------- | -------- | ----- | -------- | -------- | ------ |
|areas|区域名称列表|query|false|array|string|
|researchTypeIds|研究类型ID列表|query|false|array|string|
|domainIds|科技领域 ID 列表(逗号分隔)|query|false|string||
|startDate|发布时间起 YYYY-MM-DD(与政策追踪发布时间逻辑一致)|query|false|string||
|endDate|发布时间止 YYYY-MM-DD|query|false|string||
|category|分类(如调查项目)|query|false|string||
|pageNum|页码|query|false|integer||
|pageSize|每页条数|query|false|integer||
|sortFun|排序|query|false|boolean||
|thinkTankId|智库 ID(详情页动态列表限定当前智库)|query|false|string||
|keyword|关键词搜索(智库动态)|query|false|string||
|token|Token Request Header|header|false|string||
...
...
src/api/thinkTank/overview.js
浏览文件 @
95cb197b
// 智库概览信息
import
request
from
"@/api/request.js"
;
import
request
,
{
getToken
}
from
"@/api/request.js"
;
// 智库列表
export
function
getThinkTankList
()
{
...
...
@@ -87,7 +87,11 @@ export function getHylyList() {
}
//获取智库报告
/**
* 智库概览/智库动态-智库报告、调查项目
* GET /api/thinkTankOverview/report
* 常用 query:pageNum, pageSize, sortFun, domainIds, startDate, endDate, category(调查项目), thinkTankId(详情页), keyword(动态搜索)
*/
export
function
getThinkTankReport
(
params
)
{
return
request
({
method
:
'GET'
,
...
...
@@ -158,6 +162,7 @@ export function getThinkDynamicsReport(params) {
// 智库领域观点分析(流式)
// [POST] 8.140.26.4:10029/report-domain-view-analysis
// 每次请求体:{ domain, report_view_list }(一个 domain);多领域由前端按领域循环多次调用
export
function
postReportDomainViewAnalysis
(
data
)
{
return
request
({
method
:
'POST'
,
...
...
@@ -167,6 +172,86 @@ export function postReportDomainViewAnalysis(data) {
})
}
/**
* 智库领域观点分析(真正流式,逐 chunk 回调)
* @param {object} data
* @param {{ onReasoningChunk?: (chunk: string) => void, onMessage?: (msg: any) => void }} handlers
*/
export
async
function
postReportDomainViewAnalysisStream
(
data
,
handlers
=
{})
{
const
{
onReasoningChunk
,
onMessage
}
=
handlers
const
token
=
getToken
()
const
response
=
await
fetch
(
'/intelligent-api/report-domain-view-analysis'
,
{
method
:
'POST'
,
headers
:
{
'Content-Type'
:
'application/json'
,
...(
token
?
{
token
}
:
{})
},
body
:
JSON
.
stringify
(
data
)
})
if
(
!
response
.
ok
)
{
throw
new
Error
(
`流式分析请求失败:
${
response
.
status
}
`
)
}
// 兜底:非流式返回时仍可读取文本继续后续解析
if
(
!
response
.
body
)
{
return
await
response
.
text
()
}
const
reader
=
response
.
body
.
getReader
()
const
decoder
=
new
TextDecoder
(
'utf-8'
)
let
done
=
false
let
pending
=
''
let
fullText
=
''
while
(
!
done
)
{
const
result
=
await
reader
.
read
()
done
=
result
.
done
if
(
result
.
value
)
{
const
chunkText
=
decoder
.
decode
(
result
.
value
,
{
stream
:
!
done
})
fullText
+=
chunkText
pending
+=
chunkText
const
lines
=
pending
.
split
(
/
\r?\n
/
)
pending
=
lines
.
pop
()
??
''
for
(
const
rawLine
of
lines
)
{
const
line
=
String
(
rawLine
||
''
).
trim
()
if
(
!
line
||
!
line
.
startsWith
(
'data:'
))
continue
const
jsonText
=
line
.
slice
(
5
).
trim
()
if
(
!
jsonText
||
jsonText
===
'[DONE]'
)
continue
try
{
const
msg
=
JSON
.
parse
(
jsonText
)
if
(
typeof
onMessage
===
'function'
)
onMessage
(
msg
)
if
(
msg
?.
type
===
'reasoning'
&&
msg
?.
chunk
!=
null
&&
typeof
onReasoningChunk
===
'function'
)
{
const
c
=
String
(
msg
.
chunk
)
if
(
c
)
onReasoningChunk
(
c
)
}
}
catch
(
e
)
{
// 忽略非 JSON 数据行
}
}
}
}
// 处理最后一行残留
const
last
=
String
(
pending
||
''
).
trim
()
if
(
last
.
startsWith
(
'data:'
))
{
const
jsonText
=
last
.
slice
(
5
).
trim
()
if
(
jsonText
&&
jsonText
!==
'[DONE]'
)
{
try
{
const
msg
=
JSON
.
parse
(
jsonText
)
if
(
typeof
onMessage
===
'function'
)
onMessage
(
msg
)
if
(
msg
?.
type
===
'reasoning'
&&
msg
?.
chunk
!=
null
&&
typeof
onReasoningChunk
===
'function'
)
{
const
c
=
String
(
msg
.
chunk
)
if
(
c
)
onReasoningChunk
(
c
)
}
}
catch
(
e
)
{
// ignore
}
}
}
return
fullText
}
//提出建议领域分布
export
function
getThinkPolicyIndustry
(
params
)
{
...
...
@@ -240,18 +325,12 @@ export function getThinkTankInfoBranch(params) {
})
}
//获取经费来源统计
export
function
getThinkTankFundsTotal
(
params
)
{
return
request
({
method
:
'GET'
,
url
:
`/api/thinkTankInfo/fundsTotal/
${
params
}
`
,
})
}
//获取经费来源
export
function
getThinkTankFundsSource
(
params
)
{
return
request
({
method
:
'GET'
,
url
:
`/api/thinkTankInfo/fundsS
ource
/
${
params
}
`
,
url
:
`/api/thinkTankInfo/fundsS
tatistics
/
${
params
}
`
,
})
}
...
...
@@ -265,9 +344,17 @@ export function getThinkTankResearchAreae(params) {
//获取核心研究人员
export
function
getThinkTankPerson
(
params
)
{
const
{
thinkTankId
,
currentPage
,
pageSize
}
=
params
return
request
({
method
:
'GET'
,
url
:
`/api/thinkTankInfo/person/
${
params
}
`
,
url
:
`/api/thinkTankInfo/person/page`
,
params
:
{
currentPage
,
pageNum
:
currentPage
,
page
:
currentPage
,
pageSize
,
thinkTankId
}
})
}
...
...
src/components/base/WarningPane/icons/down.png
0 → 100644
浏览文件 @
95cb197b
953 Bytes
src/components/base/WarningPane/icons/up.png
0 → 100644
浏览文件 @
95cb197b
517 Bytes
src/components/base/WarningPane/index.vue
浏览文件 @
95cb197b
<
template
>
<div
class=
"warnning-pane-wrapper"
:style=
"
{ width: width ? width : '1600px'
, height: height ? height : 'auto', minHeight: height ? undefined : '116px'
}"
<div
class=
"warnning-pane-wrapper"
:style=
"
{ width: width ? width : '1600px' }"
:class="{
level1: warnningLevel === '特别重大风险',
level2: warnningLevel === '重大风险',
...
...
@@ -27,12 +27,22 @@
</div>
</div>
<div
class=
"warnning-pane-content text-regular"
>
{{
warnningContent
}}
{{
showContent
}}
<div
class=
"show-all-btn"
v-if=
"props.warnningContent.length > 185"
@
click
.
stop=
"handleClickShowAll"
>
<div
class=
"text text-tip-2"
>
{{
isShowAllContent
?
'收起'
:
'展开'
}}
</div>
<div
class=
"icon"
>
<img
v-if=
"!isShowAllContent"
src=
"./icons/down.png"
alt=
""
>
<img
v-else
src=
"./icons/up.png"
alt=
""
>
</div>
</div>
</div>
</div>
</
template
>
<
script
setup
>
import
{
ref
,
computed
}
from
'vue'
import
{
ElMessage
}
from
'element-plus'
...
...
@@ -50,6 +60,14 @@ const props = defineProps(
}
)
const
showContent
=
computed
(()
=>
{
if
(
!
isShowAllContent
.
value
)
{
return
props
.
warnningContent
.
length
>
185
?
props
.
warnningContent
.
slice
(
0
,
185
)
+
'...'
:
props
.
warnningContent
}
else
{
return
props
.
warnningContent
}
})
const
emit
=
defineEmits
([
'clickPane'
])
const
handleClickPane
=
()
=>
{
...
...
@@ -57,6 +75,12 @@ const handleClickPane = () => {
emit
(
'clickPane'
)
}
const
isShowAllContent
=
ref
(
false
)
const
handleClickShowAll
=
()
=>
{
isShowAllContent
.
value
=
!
isShowAllContent
.
value
}
</
script
>
<
style
lang=
"scss"
scoped
>
...
...
@@ -64,7 +88,8 @@ const handleClickPane = () => {
border-radius
:
10px
;
border
:
1px
solid
var
(
--
color-primary-100
);
box-shadow
:
0px
0px
20px
0px
rgba
(
25
,
69
,
130
,
0
.1
);
cursor
:
pointer
;
// cursor: pointer;
height
:
max-content
;
}
.level1
{
...
...
@@ -146,12 +171,40 @@ const handleClickPane = () => {
.warnning-pane-content
{
width
:
calc
(
100%
-
40px
);
margin
:
0
auto
;
margin-bottom
:
16px
;
min-height
:
60px
;
height
:
auto
;
display
:
block
;
overflow
:
visible
;
white-space
:
pre-wrap
;
word-break
:
break-word
;
// height: 60px;
// display: -webkit-box;
// /* 2. 设置内部布局方向为垂直 */
// -webkit-box-orient: vertical;
// /* 3. 限制显示的行数为 2 行 */
// -webkit-line-clamp: 2;
// /* 4. 隐藏超出部分 */
// overflow: hidden;
// /* 5. 设置文本溢出显示省略号 */
// text-overflow: ellipsis;
position
:
relative
;
.show-all-btn
{
position
:
absolute
;
right
:
0px
;
bottom
:
4px
;
width
:
48px
;
height
:
22px
;
display
:
flex
;
gap
:
4px
;
cursor
:
pointer
;
.text
{
color
:
var
(
--
text-primary-50-color
);
&
:hover
{
color
:
var
(
--
color-primary-100
);
}
}
.icon
{
width
:
16px
;
height
:
16px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
}
}
</
style
>
\ No newline at end of file
src/components/base/texts/IntelligentEntityText.vue
浏览文件 @
95cb197b
<
template
>
<p
class=
"p-regular-rereg"
>
<span
class=
"text-regular"
v-for=
"(segment, index) in processedText"
:key=
"index"
>
<a
v-if=
"segment.isEntity"
:href=
"`https://cn.bing.com/search?q=$
{segment.entity?.text_span}`"
class="entity-link" target="_blank" rel="noopener noreferrer">
{{
segment
.
entity
?.
text_span
}}
<img
:src=
"SearchIcon"
:width=
"10"
:height=
"10"
alt=
"search"
/>
</a>
<span
v-else
>
{{
segment
.
text
}}
</span>
</span>
</p>
<p
class=
"p-regular-rereg"
>
<span
class=
"text-regular"
v-for=
"(segment, index) in processedText"
:key=
"index"
>
<span
v-if=
"segment.isEntity"
@
click=
"$emit('onEntityClick', segment.entity)"
class=
"entity-link"
>
{{
segment
.
entity
?.
text_span
}}
<img
:src=
"SearchIcon"
:width=
"10"
:height=
"10"
alt=
"search"
/>
</span>
<span
v-else
>
{{
segment
.
text
}}
</span>
</span>
</p>
</
template
>
<
script
lang=
"ts"
setup
>
import
{
TextEntity
}
from
'@/api/intelligent'
;
import
{
ref
,
watch
,
onMounted
}
from
'vue'
;
import
SearchIcon
from
'./images/search.png'
import
{
TextEntity
}
from
"@/api/intelligent"
;
import
{
ref
,
watch
,
onMounted
}
from
"vue"
;
import
SearchIcon
from
"./images/search.png"
;
export
interface
ProcessedTextSegment
{
text
:
string
isEntity
:
boolean
entity
?:
TextEntity
text
:
string
;
isEntity
:
boolean
;
entity
?:
TextEntity
;
}
const
props
=
defineProps
({
text
:
{
type
:
String
,
default
:
''
},
entities
:
{
type
:
Array
<
TextEntity
>
,
default
:
()
=>
[]
}
})
text
:
{
type
:
String
,
default
:
""
},
entities
:
{
type
:
Array
<
TextEntity
>
,
default
:
()
=>
[]
}
})
;
const
emit
=
defineEmits
([
"onEntityClick"
]);
// 处理后的文本段
const
processedText
=
ref
<
ProcessedTextSegment
[]
>
([])
const
processedText
=
ref
<
ProcessedTextSegment
[]
>
([]);
// 处理文本,识别并替换实体
const
processText
=
()
=>
{
console
.
log
(
'props.entities.length'
,
props
.
entities
.
length
)
if
(
!
props
.
text
||
!
props
.
entities
)
{
// console.log('props.text', props.entities.length)
processedText
.
value
=
[{
text
:
''
,
isEntity
:
false
}]
return
}
console
.
log
(
"props.entities.length"
,
props
.
entities
.
length
);
if
(
!
props
.
text
||
!
props
.
entities
)
{
// console.log('props.text', props.entities.length)
processedText
.
value
=
[{
text
:
""
,
isEntity
:
false
}];
return
;
}
const
result
=
[]
let
currentPosition
=
0
const
result
=
[];
let
currentPosition
=
0
;
// 按实体文本长度排序,优先匹配长文本
const
sortedEntities
=
[...
props
.
entities
].
sort
((
a
,
b
)
=>
b
.
text_span
.
length
-
a
.
text_span
.
length
)
// 按实体文本长度排序,优先匹配长文本
const
sortedEntities
=
[...
props
.
entities
].
sort
((
a
,
b
)
=>
b
.
text_span
.
length
-
a
.
text_span
.
length
);
while
(
currentPosition
<
props
.
text
.
length
)
{
let
matched
=
false
while
(
currentPosition
<
props
.
text
.
length
)
{
let
matched
=
false
;
for
(
const
entity
of
sortedEntities
)
{
const
entityText
=
entity
.
text_span
const
endPosition
=
currentPosition
+
entityText
.
length
for
(
const
entity
of
sortedEntities
)
{
const
entityText
=
entity
.
text_span
;
const
endPosition
=
currentPosition
+
entityText
.
length
;
if
(
props
.
text
.
substring
(
currentPosition
,
endPosition
)
===
entityText
)
{
// 如果当前位置是实体,添加到结果
result
.
push
({
isEntity
:
true
,
entity
:
{
...
entity
}
})
currentPosition
=
endPosition
matched
=
true
break
}
}
if
(
props
.
text
.
substring
(
currentPosition
,
endPosition
)
===
entityText
)
{
// 如果当前位置是实体,添加到结果
result
.
push
({
isEntity
:
true
,
entity
:
{
...
entity
}
});
currentPosition
=
endPosition
;
matched
=
true
;
break
;
}
}
if
(
!
matched
)
{
// 如果不是实体,收集普通文本
let
nextEntityStart
=
props
.
text
.
length
if
(
!
matched
)
{
// 如果不是实体,收集普通文本
let
nextEntityStart
=
props
.
text
.
length
;
for
(
const
entity
of
sortedEntities
)
{
const
pos
=
props
.
text
.
indexOf
(
entity
.
text_span
,
currentPosition
)
if
(
pos
!==
-
1
&&
pos
<
nextEntityStart
)
{
nextEntityStart
=
pos
}
}
for
(
const
entity
of
sortedEntities
)
{
const
pos
=
props
.
text
.
indexOf
(
entity
.
text_span
,
currentPosition
);
if
(
pos
!==
-
1
&&
pos
<
nextEntityStart
)
{
nextEntityStart
=
pos
;
}
}
if
(
nextEntityStart
>
currentPosition
)
{
const
plainText
=
props
.
text
.
substring
(
currentPosition
,
nextEntityStart
)
result
.
push
({
text
:
plainText
,
isEntity
:
false
})
currentPosition
=
nextEntityStart
}
else
{
// 没有更多实体,添加剩余文本
const
remainingText
=
props
.
text
.
substring
(
currentPosition
)
if
(
remainingText
)
{
result
.
push
({
text
:
remainingText
,
isEntity
:
false
})
}
currentPosition
=
props
.
text
.
length
}
}
}
if
(
nextEntityStart
>
currentPosition
)
{
const
plainText
=
props
.
text
.
substring
(
currentPosition
,
nextEntityStart
);
result
.
push
({
text
:
plainText
,
isEntity
:
false
});
currentPosition
=
nextEntityStart
;
}
else
{
// 没有更多实体,添加剩余文本
const
remainingText
=
props
.
text
.
substring
(
currentPosition
);
if
(
remainingText
)
{
result
.
push
({
text
:
remainingText
,
isEntity
:
false
});
}
currentPosition
=
props
.
text
.
length
;
}
}
}
processedText
.
value
=
result
}
processedText
.
value
=
result
;
}
;
// 监听文本和实体变化
watch
(()
=>
props
.
text
,
processText
)
watch
(()
=>
props
.
entities
,
processText
,
{
deep
:
true
})
watch
(()
=>
props
.
text
,
processText
)
;
watch
(()
=>
props
.
entities
,
processText
,
{
deep
:
true
})
;
// 初始化处理
onMounted
(
processText
)
onMounted
(
processText
)
;
</
script
>
<
style
lang=
"scss"
scoped
>
@use
'@/styles/common.scss'
;
@use
"@/styles/common.scss"
;
.entity-link
{
color
:
var
(
--
color-primary-100
);
color
:
var
(
--
color-primary-100
);
&
:hover
{
cursor
:
pointer
;
}
}
.p-regular-rereg
{
text-indent
:
2em
;
margin
:
4px
0
;
text-indent
:
2em
;
margin
:
4px
0
;
}
</
style
>
\ No newline at end of file
</
style
>
src/components/base/texts/TextTranslatePane.vue
浏览文件 @
95cb197b
<
template
>
<div
class=
"full-width"
>
<div
class=
"flex-display"
style=
"align-items: center;"
>
<common-text
class=
"text-title-3-bold"
color=
"var(--text-primary-80-color)"
>
{{
isOpenTranslation
?
'中文'
:
'原文'
}}
</common-text>
<div
class=
"flex-fill"
style=
"margin: 0 10px;"
>
<el-divider></el-divider>
</div>
<el-button
v-if=
"showMoreVisible"
@
click=
"() =>
{ showMore = !showMore; updateText() }">
{{
showMore
?
'收起'
:
'展开'
}}
<el-icon>
<arrow-up
v-if=
"showMore"
/>
<arrow-down
v-else
/>
</el-icon>
</el-button>
</div>
<el-row
:gutter=
"32"
>
<el-col
:span=
"textColSpan"
v-for=
"(item, index) in allTexts"
:key=
"index"
>
<!--
<p
class=
"p-news-content"
>
{{
item
}}
</p>
-->
<intelligent-entity-text
:text=
"item"
:entities=
"isHighlightEntity ? textEntities : []"
></intelligent-entity-text>
</el-col>
</el-row>
</div>
<div
class=
"full-width"
>
<div
class=
"flex-display"
style=
"align-items: center"
>
<common-text
class=
"text-title-3-bold"
color=
"var(--text-primary-80-color)"
>
{{
isOpenTranslation
?
"中文"
:
"原文"
}}
</common-text>
<div
class=
"flex-fill"
style=
"margin: 0 10px"
>
<el-divider></el-divider>
</div>
<el-button
v-if=
"showMoreVisible"
@
click=
"
() =>
{
showMore = !showMore;
updateText();
}
"
>
{{
showMore
?
"收起"
:
"展开"
}}
<el-icon>
<arrow-up
v-if=
"showMore"
/>
<arrow-down
v-else
/>
</el-icon>
</el-button>
</div>
<el-row
:gutter=
"32"
>
<el-col
:span=
"textColSpan"
v-for=
"(item, index) in allTexts"
:key=
"index"
>
<!--
<p
class=
"p-news-content"
>
{{
item
}}
</p>
-->
<intelligent-entity-text
:text=
"item"
@
on-entity-click=
"e => $emit('onEntityClick', e)"
:entities=
"isHighlightEntity ? textEntities : []"
></intelligent-entity-text>
</el-col>
</el-row>
</div>
</
template
>
<
script
lang=
"ts"
setup
>
import
'@/styles/container.scss'
;
import
'@/styles/common.scss'
;
import
"@/styles/container.scss"
;
import
"@/styles/common.scss"
;
import
{
ref
,
watch
,
onMounted
}
from
'vue'
;
import
{
TextEntity
}
from
'@/api/intelligent'
;
import
IntelligentEntityText
from
'@/components/base/texts/IntelligentEntityText.vue'
;
import
{
ElIcon
,
ElButton
,
ElDivider
,
ElRow
,
ElCol
}
from
'element-plus'
;
import
CommonText
from
'./CommonText.vue'
;
import
{
ref
,
watch
,
onMounted
}
from
"vue"
;
import
{
TextEntity
}
from
"@/api/intelligent"
;
import
IntelligentEntityText
from
"@/components/base/texts/IntelligentEntityText.vue"
;
import
{
ElIcon
,
ElButton
,
ElDivider
,
ElRow
,
ElCol
}
from
"element-plus"
;
import
CommonText
from
"./CommonText.vue"
;
const
allTexts
=
ref
([]);
const
textColSpan
=
ref
(
12
);
...
...
@@ -39,71 +51,73 @@ const hasTranslation = ref(false);
const
showMore
=
ref
(
false
);
const
showMoreVisible
=
ref
(
false
);
const
props
=
defineProps
({
//段落列表: 原始文本
textsRaw
:
{
type
:
Array
<
String
>
,
default
:
()
=>
[]
},
//段落列表: 翻译文本
textsTranslate
:
{
type
:
Array
<
String
>
,
default
:
()
=>
[]
},
//是否显示翻译
isOpenTranslation
:
{
type
:
Boolean
,
default
:
true
},
//是否高亮实体
isHighlightEntity
:
{
type
:
Boolean
,
default
:
true
},
//实体列表
textEntities
:
{
type
:
Array
<
TextEntity
>
,
default
:
()
=>
[]
}
})
//段落列表: 原始文本
textsRaw
:
{
type
:
Array
<
String
>
,
default
:
()
=>
[]
},
//段落列表: 翻译文本
textsTranslate
:
{
type
:
Array
<
String
>
,
default
:
()
=>
[]
},
//是否显示翻译
isOpenTranslation
:
{
type
:
Boolean
,
default
:
true
},
//是否高亮实体
isHighlightEntity
:
{
type
:
Boolean
,
default
:
true
},
//实体列表
textEntities
:
{
type
:
Array
<
TextEntity
>
,
default
:
()
=>
[]
}
})
;
const
emit
=
defineEmits
([
"onEntityClick"
]);
function
updateText
()
{
const
tempTexts
=
[]
const
tempRaws
=
props
.
textsRaw
??
[]
const
tempTranslates
=
props
.
textsTranslate
??
[]
hasTranslation
.
value
=
tempTranslates
.
length
>
0
const
tempTexts
=
[];
const
tempRaws
=
props
.
textsRaw
??
[];
const
tempTranslates
=
props
.
textsTranslate
??
[];
hasTranslation
.
value
=
tempTranslates
.
length
>
0
;
if
(
hasTranslation
.
value
&&
props
.
isOpenTranslation
)
{
// 遍历原始文本和翻译文本,将它们交替添加到 tempTexts 中,并保持原始文本和翻译文本的的数量一致
const
maxCount
=
Math
.
max
(
tempRaws
.
length
,
tempTranslates
.
length
)
for
(
let
i
=
0
;
i
<
maxCount
;
i
++
)
{
if
(
i
<
tempTranslates
.
length
)
{
tempTexts
.
push
(
tempTranslates
[
i
]);
}
else
{
tempTexts
.
push
(
''
);
}
if
(
i
<
tempRaws
.
length
)
{
tempTexts
.
push
(
tempRaws
[
i
]);
}
else
{
tempTexts
.
push
(
''
);
}
}
console
.
log
(
tempTexts
.
length
)
textColSpan
.
value
=
12
;
showMoreVisible
.
value
=
tempTexts
.
length
>
6
;
allTexts
.
value
=
showMore
.
value
?
tempTexts
:
tempTexts
.
slice
(
0
,
6
);
}
else
{
textColSpan
.
value
=
24
;
showMoreVisible
.
value
=
tempRaws
.
length
>
3
;
allTexts
.
value
=
showMore
.
value
?
tempRaws
:
tempRaws
.
slice
(
0
,
3
);
}
if
(
hasTranslation
.
value
&&
props
.
isOpenTranslation
)
{
// 遍历原始文本和翻译文本,将它们交替添加到 tempTexts 中,并保持原始文本和翻译文本的的数量一致
const
maxCount
=
Math
.
max
(
tempRaws
.
length
,
tempTranslates
.
length
);
for
(
let
i
=
0
;
i
<
maxCount
;
i
++
)
{
if
(
i
<
tempTranslates
.
length
)
{
tempTexts
.
push
(
tempTranslates
[
i
]);
}
else
{
tempTexts
.
push
(
""
);
}
if
(
i
<
tempRaws
.
length
)
{
tempTexts
.
push
(
tempRaws
[
i
]);
}
else
{
tempTexts
.
push
(
""
);
}
}
console
.
log
(
tempTexts
.
length
);
textColSpan
.
value
=
12
;
showMoreVisible
.
value
=
tempTexts
.
length
>
6
;
allTexts
.
value
=
showMore
.
value
?
tempTexts
:
tempTexts
.
slice
(
0
,
6
);
}
else
{
textColSpan
.
value
=
24
;
showMoreVisible
.
value
=
tempRaws
.
length
>
3
;
allTexts
.
value
=
showMore
.
value
?
tempRaws
:
tempRaws
.
slice
(
0
,
3
);
}
}
watch
(()
=>
[
props
.
textsRaw
,
props
.
textsTranslate
,
props
.
isOpenTranslation
],
()
=>
{
updateText
();
})
watch
(
()
=>
[
props
.
textsRaw
,
props
.
textsTranslate
,
props
.
isOpenTranslation
],
()
=>
{
updateText
();
}
);
onMounted
(()
=>
{
updateText
();
})
</
script
>
\ No newline at end of file
updateText
();
});
</
script
>
src/router/index.js
浏览文件 @
95cb197b
...
...
@@ -65,4 +65,5 @@ router.beforeEach((to, from, next) => {
next
();
});
export
default
router
;
src/router/modules/company.js
浏览文件 @
95cb197b
//企业主页
import
{
useGotoPage
}
from
"../common.js"
;
const
companyPages
=
()
=>
import
(
'@/views/companyPages/index.vue'
)
const
companyPages2
=
()
=>
import
(
'@/views/companyPages2/index.vue'
)
...
...
@@ -28,4 +29,9 @@ const companyPagesRoutes = [
]
export
function
useGotoCompanyPages
()
{
const
gotoPage
=
useGotoPage
();
return
(
id
,
isNewTabs
=
true
)
=>
gotoPage
(
"/companyPages/"
+
id
,
{},
isNewTabs
)
}
export
default
companyPagesRoutes
\ No newline at end of file
src/router/modules/comprehensiveSearch.js
浏览文件 @
95cb197b
// 综合搜索
const
ComprehensiveSearch
=
()
=>
import
(
'@/views/comprehensiveSearch/index.vue'
)
const
SearchResults
=
()
=>
import
(
'@/views/comprehensiveSearch/searchResults/index.vue'
)
const
Chat
=
()
=>
import
(
'@/views/comprehensiveSearch/chat/index.vue'
)
const
ComprehensiveSearch
=
()
=>
import
(
"@/views/comprehensiveSearch/index.vue"
);
const
SearchResults
=
()
=>
import
(
"@/views/comprehensiveSearch/searchResults/index.vue"
);
const
Chat
=
()
=>
import
(
"@/views/comprehensiveSearch/chat/index.vue"
);
const
comprehensiveSearchRoutes
=
[
// 综合搜索
{
path
:
"/comprehensiveSearch"
,
name
:
"comprehensiveSearch"
,
component
:
ComprehensiveSearch
,
meta
:
{
title
:
"搜索-科技安全"
}
},
{
path
:
"/searchResults"
,
name
:
"searchResults"
,
component
:
SearchResults
,
meta
:
{
title
:
"搜索结果"
,
dynamicTitle
:
true
}
},
{
path
:
"/chat"
,
name
:
"chat"
,
component
:
Chat
,
meta
:
{
title
:
"智能问答"
}
},
]
// 综合搜索
{
path
:
"/comprehensiveSearch"
,
name
:
"comprehensiveSearch"
,
component
:
ComprehensiveSearch
,
meta
:
{
title
:
"搜索-科技安全"
}
},
{
path
:
"/searchResults"
,
name
:
"searchResults"
,
component
:
SearchResults
,
meta
:
{
title
:
"搜索结果"
,
dynamicTitle
:
true
}
},
{
path
:
"/chat"
,
name
:
"chat"
,
component
:
Chat
,
meta
:
{
title
:
"智能问答"
}
}
];
import
{
useGotoPage
}
from
"../common.js"
;
export
function
useGotoComprehensiveSearch
()
{
const
gotoPage
=
useGotoPage
();
return
(
isNewTabs
=
true
)
=>
gotoPage
(
"/comprehensiveSearch/"
,
{},
isNewTabs
)
const
gotoPage
=
useGotoPage
();
return
(
isNewTabs
=
true
)
=>
gotoPage
(
"/comprehensiveSearch/"
,
{},
isNewTabs
);
}
export
function
useGotoSearchResults
()
{
const
gotoPage
=
useGotoPage
();
return
(
isNewTabs
=
true
)
=>
gotoPage
(
"/searchResults/"
,
{
searchText
,
areaName
},
isNewTabs
)
const
gotoPage
=
useGotoPage
();
return
(
searchText
,
areaName
,
isNewTabs
=
true
)
=>
gotoPage
(
"/searchResults/"
,
{
searchText
,
areaName
},
isNewTabs
);
}
export
default
comprehensiveSearchRoutes
\ No newline at end of file
export
default
comprehensiveSearchRoutes
;
src/utils/setChart.js
浏览文件 @
95cb197b
...
...
@@ -11,14 +11,35 @@ const setChart = (option, chartId, allowClick, selectParam) => {
let
chart
=
echarts
.
init
(
chartDom
);
chart
.
setOption
(
option
);
if
(
allowClick
)
{
// 3. 添加点击事件监听
chart
.
on
(
'click'
,
function
(
params
)
{
switch
(
selectParam
.
moduleType
)
{
case
'国会法案'
:
// 判断点击的是否为饼图的数据项
if
(
params
.
componentType
===
'series'
&&
params
.
seriesType
===
'pie'
)
{
console
.
log
(
'点击的扇形名称:'
,
params
.
name
);
selectParam
.
domains
=
JSON
.
stringify
([
params
.
name
])
if
(
selectParam
.
key
===
'领域'
)
{
selectParam
.
domains
=
JSON
.
stringify
([
params
.
name
])
}
else
if
(
selectParam
.
key
===
'议院委员会'
)
{
if
(
params
.
name
===
'众议院'
||
params
.
name
===
'参议院'
)
{
selectParam
.
selectedCongress
=
params
.
name
selectParam
.
selectedOrg
=
''
}
else
{
selectParam
.
selectedOrg
=
params
.
name
selectParam
.
selectedCongress
=
''
}
}
const
route
=
router
.
resolve
({
path
:
"/dataLibrary/countryBill"
,
query
:
selectParam
});
window
.
open
(
route
.
href
,
"_blank"
);
}
else
if
(
params
.
componentType
===
'series'
&&
params
.
seriesType
===
'bar'
)
{
if
(
params
.
name
===
'已立法'
)
{
selectParam
.
selectedStauts
=
1
}
else
{
selectParam
.
selectedStauts
=
0
}
const
route
=
router
.
resolve
({
path
:
"/dataLibrary/countryBill"
,
query
:
selectParam
...
...
src/views/bill/billHome/index.vue
浏览文件 @
95cb197b
...
...
@@ -866,14 +866,20 @@ const handleBox7Data = async () => {
if
(
t1
!==
t2
)
return
t1
-
t2
;
return
(
b
.
value
??
0
)
-
(
a
.
value
??
0
);
});
const
selectParam
=
{
moduleType
:
'国会法案'
,
key
:
'议院委员会'
,
selectedDate
:
box7selectetedTime
.
value
,
}
const
box7Chart
=
getDoublePieChart
(
data1
,
data2
);
setChart
(
box7Chart
,
"box7Chart"
);
setChart
(
box7Chart
,
"box7Chart"
,
true
,
selectParam
);
box7AiData
.
value
=
{
inner
:
data1
,
outer
:
data2
};
}
else
{
// 接口异常(如500)时,清空图表数据以避免报错或显示错误信息
box7HasData
.
value
=
false
;
setChart
({},
"box7Chart"
);
setChart
({},
"box7Chart"
,
true
,
selectParam
);
box7AiData
.
value
=
{
inner
:
[],
outer
:
[]
};
}
}
catch
(
error
)
{
...
...
@@ -987,9 +993,9 @@ const handleBox9Data = async () => {
);
const
selectParam
=
{
moduleType
:
'国会法案'
,
proposedDateStart
:
box9selectetedTime
.
value
,
status
:
box9LegislativeStatus
.
value
===
'提出法案'
?
0
:
1
selectedDate
:
box9selectetedTime
.
value
,
status
:
box9LegislativeStatus
.
value
===
'提出法案'
?
0
:
1
,
isInvolveCn
:
1
}
box9ChartInstance
=
setChart
(
box9Chart
,
"box9Chart"
,
true
,
selectParam
);
}
...
...
@@ -1166,9 +1172,17 @@ const handleBox8Data = async () => {
box8HasData
.
value
=
true
;
box8Summary
.
value
=
countMap
.
get
(
"完成立法"
)
||
0
;
box8StageList
.
value
=
stages
;
const
selectParam
=
{
moduleType
:
'国会法案'
,
key
:
'领域'
,
selectedDate
:
box8selectetedTime
.
value
,
isInvolveCn
:
1
}
await
nextTick
();
const
box8Chart
=
getBox8ChartOption
(
stages
);
box8ChartInstance
=
setChart
(
box8Chart
,
"box8Chart"
);
box8ChartInstance
=
setChart
(
box8Chart
,
"box8Chart"
,
true
,
selectParam
);
}
else
{
const
data
=
box8MockDataByYear
[
box8selectetedTime
.
value
];
if
(
data
&&
data
.
stages
&&
data
.
stages
.
length
>
0
)
{
...
...
@@ -1177,12 +1191,12 @@ const handleBox8Data = async () => {
box8StageList
.
value
=
data
.
stages
;
await
nextTick
();
const
box8Chart
=
getBox8ChartOption
(
data
.
stages
);
box8ChartInstance
=
setChart
(
box8Chart
,
"box8Chart"
);
box8ChartInstance
=
setChart
(
box8Chart
,
"box8Chart"
,
true
,
selectParam
);
}
else
{
box8HasData
.
value
=
false
;
box8Summary
.
value
=
0
;
box8StageList
.
value
=
[];
setChart
({},
"box8Chart"
);
setChart
({},
"box8Chart"
,
true
,
selectParam
);
}
}
}
catch
(
error
)
{
...
...
@@ -1194,12 +1208,12 @@ const handleBox8Data = async () => {
box8StageList
.
value
=
data
.
stages
;
await
nextTick
();
const
box8Chart
=
getBox8ChartOption
(
data
.
stages
);
box8ChartInstance
=
setChart
(
box8Chart
,
"box8Chart"
);
box8ChartInstance
=
setChart
(
box8Chart
,
"box8Chart"
,
true
,
selectParam
);
}
else
{
box8HasData
.
value
=
false
;
box8Summary
.
value
=
0
;
box8StageList
.
value
=
[];
setChart
({},
"box8Chart"
);
setChart
({},
"box8Chart"
,
true
,
selectParam
);
}
}
};
...
...
src/views/dataLibrary/bill/countryBill/index.vue
浏览文件 @
95cb197b
差异被折叠。
点击展开。
src/views/dataLibrary/components/ChartHeader/index.vue
浏览文件 @
95cb197b
...
...
@@ -39,7 +39,7 @@ const handleClickItem = (item) => {
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
.left
{
display
:
flex
;
gap
:
8px
;
...
...
src/views/dataLibrary/index.vue
浏览文件 @
95cb197b
...
...
@@ -111,13 +111,13 @@ const siderList = ref([
{
name
:
'科技法案'
,
icon
:
Icon1
,
active
:
tru
e
,
isExpanded
:
tru
e
,
active
:
fals
e
,
isExpanded
:
fals
e
,
children
:
[
{
name
:
'国会法案'
,
path
:
'/dataLibrary/countryBill'
,
active
:
tru
e
,
active
:
fals
e
,
},
{
name
:
'州法案'
,
...
...
@@ -477,6 +477,118 @@ const handleClickToolBox = () => {
};
onMounted
(()
=>
{
const
path
=
route
.
path
switch
(
path
)
{
case
'/dataLibrary/countryBill'
:
siderList
.
value
[
0
].
active
=
true
siderList
.
value
[
0
].
isExpanded
=
true
siderList
.
value
[
0
].
children
[
0
].
active
=
true
break
case
'/dataLibrary/stateBill'
:
siderList
.
value
[
0
].
active
=
true
siderList
.
value
[
0
].
isExpanded
=
true
siderList
.
value
[
0
].
children
[
1
].
active
=
true
break
case
'/dataLibrary/dataDecree'
:
siderList
.
value
[
1
].
active
=
true
break
case
'/dataLibrary/dataThinkTank'
:
siderList
.
value
[
2
].
active
=
true
break
case
'/dataLibrary/dataEntityList'
:
siderList
.
value
[
3
].
active
=
true
siderList
.
value
[
3
].
isExpanded
=
true
siderList
.
value
[
3
].
children
[
0
].
active
=
true
break
case
'/dataLibrary/dataCommerceControlList'
:
siderList
.
value
[
3
].
active
=
true
siderList
.
value
[
3
].
isExpanded
=
true
siderList
.
value
[
3
].
children
[
1
].
active
=
true
break
case
'/dataLibrary/dataEntityListEvent'
:
siderList
.
value
[
3
].
active
=
true
siderList
.
value
[
3
].
isExpanded
=
true
siderList
.
value
[
3
].
children
[
2
].
active
=
true
break
case
'/dataLibrary/dataCommerceControlListEvent'
:
siderList
.
value
[
3
].
active
=
true
siderList
.
value
[
3
].
isExpanded
=
true
siderList
.
value
[
3
].
children
[
3
].
active
=
true
break
case
'/dataLibrary/sDNList'
:
siderList
.
value
[
4
].
active
=
true
siderList
.
value
[
4
].
isExpanded
=
true
siderList
.
value
[
4
].
children
[
0
].
active
=
true
break
case
'/dataLibrary/mREList'
:
siderList
.
value
[
4
].
active
=
true
siderList
.
value
[
4
].
isExpanded
=
true
siderList
.
value
[
4
].
children
[
1
].
active
=
true
break
case
'/dataLibrary/sDNListEvent'
:
siderList
.
value
[
4
].
active
=
true
siderList
.
value
[
4
].
isExpanded
=
true
siderList
.
value
[
4
].
children
[
2
].
active
=
true
break
case
'/dataLibrary/mREListEvent'
:
siderList
.
value
[
4
].
active
=
true
siderList
.
value
[
4
].
isExpanded
=
true
siderList
.
value
[
4
].
children
[
3
].
active
=
true
break
case
'/dataLibrary/case337'
:
siderList
.
value
[
5
].
active
=
true
siderList
.
value
[
5
].
isExpanded
=
true
siderList
.
value
[
5
].
children
[
0
].
active
=
true
break
case
'/dataLibrary/case232'
:
siderList
.
value
[
5
].
active
=
true
siderList
.
value
[
5
].
isExpanded
=
true
siderList
.
value
[
5
].
children
[
1
].
active
=
true
break
case
'/dataLibrary/case301'
:
siderList
.
value
[
5
].
active
=
true
siderList
.
value
[
5
].
isExpanded
=
true
siderList
.
value
[
5
].
children
[
2
].
active
=
true
break
case
'/dataLibrary/congressMan'
:
siderList
.
value
[
6
].
active
=
true
siderList
.
value
[
6
].
isExpanded
=
true
siderList
.
value
[
6
].
children
[
0
].
active
=
true
break
case
'/dataLibrary/technologyLeader'
:
siderList
.
value
[
6
].
active
=
true
siderList
.
value
[
6
].
isExpanded
=
true
siderList
.
value
[
6
].
children
[
1
].
active
=
true
break
case
'/dataLibrary/minister'
:
siderList
.
value
[
6
].
active
=
true
siderList
.
value
[
6
].
isExpanded
=
true
siderList
.
value
[
6
].
children
[
2
].
active
=
true
break
case
'/dataLibrary/thinkTankResearcher'
:
siderList
.
value
[
6
].
active
=
true
siderList
.
value
[
6
].
isExpanded
=
true
siderList
.
value
[
6
].
children
[
3
].
active
=
true
break
case
'/dataLibrary/technologyCompany'
:
siderList
.
value
[
7
].
active
=
true
siderList
.
value
[
7
].
isExpanded
=
true
siderList
.
value
[
7
].
children
[
0
].
active
=
true
break
case
'/dataLibrary/researchUniversity'
:
siderList
.
value
[
7
].
active
=
true
siderList
.
value
[
7
].
isExpanded
=
true
siderList
.
value
[
7
].
children
[
1
].
active
=
true
break
case
'/dataLibrary/keyLab'
:
siderList
.
value
[
7
].
active
=
true
siderList
.
value
[
7
].
isExpanded
=
true
siderList
.
value
[
7
].
children
[
2
].
active
=
true
break
}
})
...
...
@@ -683,7 +795,8 @@ onMounted(() => {
.icon
{
width
:
16px
;
height
:
16px
;
&
:hover
{
&
:hover
{
border-radius
:
8px
;
background
:
var
(
--
color-primary-10
);
}
...
...
src/views/home/index.vue
浏览文件 @
95cb197b
...
...
@@ -77,7 +77,7 @@ import { useRoute } from "vue-router";
import
AiBox
from
"@/components/AiBox.vue"
;
import
{
getPersonType
}
from
"@/api/common/index"
;
// import { useDraggable } from "@vueuse/core";
import
ModuleHeader
from
'@/components/base/
M
oduleHeader/index.vue'
import
ModuleHeader
from
'@/components/base/
m
oduleHeader/index.vue'
import
Menu1
from
"@/assets/icons/overview/menu1.png"
;
import
Menu2
from
"@/assets/icons/overview/menu2.png"
;
...
...
@@ -120,7 +120,7 @@ const handleGetPersonType = async () => {
personTypeList
.
value
=
[];
}
window
.
sessionStorage
.
setItem
(
"personTypeList"
,
JSON
.
stringify
(
personTypeList
.
value
));
}
catch
(
error
)
{}
}
catch
(
error
)
{
}
};
const
isCurrentOverview
=
computed
(()
=>
{
...
...
@@ -298,7 +298,7 @@ body {
text-align
:
justify
;
}
.el-popper
[
data-popper-placement
^=
"top"
]
>
.el-popper__arrow
:before
{
.el-popper
[
data-popper-placement
^=
"top"
]
>
.el-popper__arrow
:before
{
display
:
none
;
}
...
...
src/views/newsBrief/NewsDetial.vue
浏览文件 @
95cb197b
差异被折叠。
点击展开。
src/views/newsBrief/NewsMain.vue
浏览文件 @
95cb197b
...
...
@@ -25,20 +25,21 @@
<img
src=
"@/assets/icons/subject-icon.png"
/>
</
template
>
<el-space
:size=
"16"
direction=
"vertical"
fill
class=
"full-width common-padding"
>
<el-space
v-for=
"(item, index) in subjectData.slice(0, 3)"
:key=
"index"
class=
"mouse-hover"
<el-space
v-for=
"(item, index) in subjectData.slice(0, 3)"
:key=
"index"
@
click=
"() => gotoNewsDetail(item.newsId)"
alignment=
"center"
>
<common-text
class=
"text-bold"
<common-text
class=
"text-bold
text-hover
"
:color=
"index === 0 ? 'var(--color-red-100)' : (index === 1 ? 'var(--color-orange-100)' : 'var(--text-primary-65-color)')"
>
{{ `${index + 1}` }}
</common-text>
<common-text
class=
"text-bold"
color=
"var(--text-primary-80-color)"
>
{{
<common-text
class=
"text-bold
text-hover
"
color=
"var(--text-primary-80-color)"
>
{{
item.newsTitle
}}
</common-text>
}}
</common-text>
</el-space>
<el-space
v-for=
"(item, index) in subjectData.slice(3)"
:key=
"index"
class=
"mouse-hover"
>
<common-text
class=
"text-regular"
color=
"var(--text-primary-80-color)"
>
{{
<el-space
v-for=
"(item, index) in subjectData.slice(3)"
:key=
"index"
@
click=
"() => gotoNewsDetail(item.newsId)"
>
<common-text
class=
"text-regular text-hover"
color=
"var(--text-primary-80-color)"
>
{{
"• " + item.newsTitle
}}
</common-text>
}}
</common-text>
</el-space>
</el-space>
</box-background>
...
...
@@ -48,6 +49,7 @@
</template>
<
script
setup
>
import
{
ref
,
onMounted
}
from
"vue"
;
import
'@/styles/common.scss'
;
import
'@/styles/container.scss'
;
import
'@/styles/radio.scss'
;
import
{
useGotoNewsModule
,
useGotoNewsDetail
}
from
"@/router/modules/news"
;
...
...
src/views/thinkTank/MultiThinkTankViewAnalysis/index.vue
浏览文件 @
95cb197b
差异被折叠。
点击展开。
src/views/thinkTank/ReportDetail/policyTracking/index.vue
浏览文件 @
95cb197b
...
...
@@ -330,11 +330,11 @@ onMounted(async () => {
.box1
{
margin-top
:
19px
;
width
:
1600px
;
height
:
1173px
;
.box1-main
{
margin-top
:
8px
;
height
:
1097
px
;
min-height
:
778
px
;
padding-left
:
21px
;
padding-right
:
50px
;
padding-bottom
:
21px
;
...
...
@@ -421,7 +421,7 @@ onMounted(async () => {
.item-box
{
width
:
506px
;
height
:
100%
;
min-height
:
639
.2px
;
border-top
:
1px
solid
rgb
(
234
,
236
,
238
);
.item
{
...
...
src/views/thinkTank/ReportDetail/reportAnalysis/index.vue
浏览文件 @
95cb197b
差异被折叠。
点击展开。
src/views/thinkTank/ThinkTankDetail/PolicyTracking/index.vue
浏览文件 @
95cb197b
差异被折叠。
点击展开。
src/views/thinkTank/ThinkTankDetail/PolicyTracking/utils/multiLineChart.js
浏览文件 @
95cb197b
import
*
as
echarts
from
'echarts'
/** 政策追踪「研究领域变化趋势」图例分页:每页条数(与概览数量变化趋势逻辑一致,条数按产品要求为 4) */
export
const
POLICY_TRACKING_LEGEND_PAGE_SIZE
=
4
const
colorList
=
[
'rgba(5, 95, 194, 1)'
,
'rgba(19, 168, 168, 1)'
,
...
...
@@ -35,22 +32,16 @@ const parseRgba = (colorStr) => {
/**
* @param {{ title: unknown[], data: Array<{ name: string, value: unknown[], color?: string }> }} chartInput
* @param {{ legendShowCount?: number, legendPageIndex?: number }} [options]
*/
const
getMultiLineChart
=
(
chartInput
,
options
=
{}
)
=>
{
const
getMultiLineChart
=
(
chartInput
)
=>
{
const
title
=
chartInput
.
title
const
series
=
chartInput
.
data
||
[]
const
legendShowCount
=
typeof
options
.
legendShowCount
===
'number'
&&
options
.
legendShowCount
>
0
?
options
.
legendShowCount
:
POLICY_TRACKING_LEGEND_PAGE_SIZE
const
rawPageIndex
=
Number
(
options
.
legendPageIndex
)
||
0
const
allNames
=
series
.
map
((
item
)
=>
item
.
name
)
const
pageCount
=
Math
.
max
(
1
,
Math
.
ceil
(
allNames
.
length
/
legendShowCount
)
)
const
legend
PageIndex
=
Math
.
min
(
Math
.
max
(
0
,
rawPageIndex
),
pageCount
-
1
)
const
legend
Start
=
legendPageIndex
*
legendShowCount
const
legend
Data
=
allNames
.
slice
(
legendStart
,
legendStart
+
legendShowCount
)
const
lineSize
=
Math
.
ceil
(
allNames
.
length
/
3
)
const
legend
Line1
=
allNames
.
slice
(
0
,
lineSize
)
const
legend
Line2
=
allNames
.
slice
(
lineSize
,
lineSize
*
2
)
const
legend
Line3
=
allNames
.
slice
(
lineSize
*
2
)
const
xCount
=
Array
.
isArray
(
title
)
?
title
.
length
:
0
const
labelFontSize
=
xCount
>
8
?
10
:
xCount
>
5
?
11
:
12
...
...
@@ -91,31 +82,71 @@ const getMultiLineChart = (chartInput, options = {}) => {
},
/* 贴满 #box3Chart:四边 0,由 containLabel 在网格内为轴文字留位,避免左侧/底部大块留白 */
grid
:
{
top
:
50
,
top
:
92
,
right
:
10
,
bottom
:
0
,
left
:
20
,
containLabel
:
true
},
legend
:
{
show
:
true
,
type
:
'plain'
,
data
:
legendData
,
top
:
4
,
left
:
'center'
,
icon
:
'circle'
,
textStyle
:
{
fontFamily
:
'Source Han Sans CN'
,
fontWeight
:
400
,
fontSize
:
14
,
lineHeight
:
24
,
letterSpacing
:
0
,
align
:
'left'
,
color
:
'rgb(95, 101, 108)'
legend
:
[
{
show
:
true
,
type
:
'plain'
,
data
:
legendLine1
,
top
:
4
,
left
:
'center'
,
icon
:
'circle'
,
textStyle
:
{
fontFamily
:
'Source Han Sans CN'
,
fontWeight
:
400
,
fontSize
:
14
,
lineHeight
:
24
,
letterSpacing
:
0
,
align
:
'left'
,
color
:
'rgb(95, 101, 108)'
},
itemWidth
:
12
,
itemHeight
:
12
},
itemWidth
:
12
,
itemHeight
:
12
},
{
show
:
legendLine2
.
length
>
0
,
type
:
'plain'
,
data
:
legendLine2
,
top
:
30
,
left
:
'center'
,
icon
:
'circle'
,
textStyle
:
{
fontFamily
:
'Source Han Sans CN'
,
fontWeight
:
400
,
fontSize
:
14
,
lineHeight
:
24
,
letterSpacing
:
0
,
align
:
'left'
,
color
:
'rgb(95, 101, 108)'
},
itemWidth
:
12
,
itemHeight
:
12
},
{
show
:
legendLine3
.
length
>
0
,
type
:
'plain'
,
data
:
legendLine3
,
top
:
56
,
left
:
'center'
,
icon
:
'circle'
,
textStyle
:
{
fontFamily
:
'Source Han Sans CN'
,
fontWeight
:
400
,
fontSize
:
14
,
lineHeight
:
24
,
letterSpacing
:
0
,
align
:
'left'
,
color
:
'rgb(95, 101, 108)'
},
itemWidth
:
12
,
itemHeight
:
12
}
],
color
:
colorList
,
xAxis
:
[
{
...
...
@@ -142,6 +173,16 @@ const getMultiLineChart = (chartInput, options = {}) => {
yAxis
:
[
{
type
:
'value'
,
name
:
'数量'
,
nameLocation
:
'end'
,
nameGap
:
20
,
nameTextStyle
:
{
color
:
'rgb(132, 136, 142)'
,
fontFamily
:
'Source Han Sans CN'
,
fontWeight
:
400
,
fontSize
:
11
,
padding
:
[
0
,
0
,
0
,
-
20
]
// 👈 这个是左移 4px(上、右、下、左)
},
splitNumber
:
4
,
axisLabel
:
{
color
:
'rgb(132, 136, 142)'
,
...
...
src/views/thinkTank/ThinkTankDetail/thinkDynamics/CongressHearing/index.vue
浏览文件 @
95cb197b
差异被折叠。
点击展开。
src/views/thinkTank/ThinkTankDetail/thinkDynamics/SurveyForm/index.vue
浏览文件 @
95cb197b
差异被折叠。
点击展开。
src/views/thinkTank/ThinkTankDetail/thinkDynamics/ThinkTankReport/index.vue
浏览文件 @
95cb197b
差异被折叠。
点击展开。
src/views/thinkTank/ThinkTankDetail/thinkDynamics/index.vue
浏览文件 @
95cb197b
差异被折叠。
点击展开。
src/views/thinkTank/ThinkTankDetail/thinkInfo/images/left-page-btn.png
0 → 100644
浏览文件 @
95cb197b
差异被折叠。
点击展开。
src/views/thinkTank/ThinkTankDetail/thinkInfo/images/right-page-btn.png
0 → 100644
浏览文件 @
95cb197b
差异被折叠。
点击展开。
src/views/thinkTank/ThinkTankDetail/thinkInfo/index.vue
浏览文件 @
95cb197b
差异被折叠。
点击展开。
src/views/thinkTank/allThinkTank/index.vue
浏览文件 @
95cb197b
差异被折叠。
点击展开。
src/views/thinkTank/assets/images/being-analysis-circle.png
0 → 100644
浏览文件 @
95cb197b
差异被折叠。
点击展开。
src/views/thinkTank/assets/images/being-analysis.png
0 → 100644
浏览文件 @
95cb197b
差异被折叠。
点击展开。
src/views/thinkTank/assets/images/blue-down.png
0 → 100644
浏览文件 @
95cb197b
差异被折叠。
点击展开。
src/views/thinkTank/assets/images/blue-up.png
0 → 100644
浏览文件 @
95cb197b
差异被折叠。
点击展开。
src/views/thinkTank/assets/images/empty-analysis.png
0 → 100644
浏览文件 @
95cb197b
差异被折叠。
点击展开。
src/views/thinkTank/assets/images/empty-image.png
查看替换文件 @
afd6e682
浏览文件 @
95cb197b
差异被折叠。
点击展开。
src/views/thinkTank/components/HomeMainFooterMain.vue
浏览文件 @
95cb197b
差异被折叠。
点击展开。
src/views/thinkTank/components/HomeMainFooterSurvey.vue
浏览文件 @
95cb197b
差异被折叠。
点击展开。
src/views/thinkTank/components/ThinkTankCongressHearingOverview.vue
浏览文件 @
95cb197b
差异被折叠。
点击展开。
src/views/thinkTank/components/ThinkTankPolicyAdviceOverview.vue
浏览文件 @
95cb197b
差异被折叠。
点击展开。
src/views/thinkTank/index.vue
浏览文件 @
95cb197b
差异被折叠。
点击展开。
src/views/thinkTank/utils/multiLineChart.js
浏览文件 @
95cb197b
差异被折叠。
点击展开。
src/views/thinkTank/utils/resourceLibraryFilters.js
0 → 100644
浏览文件 @
95cb197b
差异被折叠。
点击展开。
src/views/thinkTank/utils/sankey.js
浏览文件 @
95cb197b
差异被折叠。
点击展开。
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论