Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
risk-monitor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蔡建
risk-monitor
Commits
63313ad6
提交
63313ad6
authored
3月 17, 2026
作者:
张伊明
浏览文件
操作
浏览文件
下载
差异文件
合并分支 'zym-dev' 到 'master'
Zym dev 查看合并请求
!183
上级
54f8850d
0b438adc
全部展开
显示空白字符变更
内嵌
并排
正在显示
7 个修改的文件
包含
482 行增加
和
104 行删除
+482
-104
wordCloudChart.js
src/components/base/WordCloundChart/wordCloudChart.js
+19
-33
ProcessOverviewDetailDialog.vue
src/views/bill/ProcessOverviewDetailDialog.vue
+292
-0
index.vue
src/views/bill/background/index.vue
+2
-2
index.vue
src/views/bill/billHome/index.vue
+6
-6
index.vue
src/views/bill/deepDig/poliContribution/index.vue
+4
-59
index.vue
src/views/bill/deepDig/processOverview/index.vue
+0
-0
index.vue
src/views/bill/template/index.vue
+159
-4
没有找到文件。
src/components/base/WordCloundChart/wordCloudChart.js
浏览文件 @
63313ad6
import
'echarts-wordcloud'
;
import
{
MUTICHARTCOLORS
}
from
'@/common/constant'
;
const
getWordCloudChart
=
(
data
)
=>
{
const
getWordCloudChart
=
data
=>
{
const
option
=
{
grid
:
{
left
:
5
,
...
...
@@ -12,9 +12,9 @@ const getWordCloudChart = (data) => {
series
:
[
{
type
:
"wordCloud"
,
shape
:
'circle'
,
width
:
'100%'
,
height
:
'100%'
,
shape
:
"circle"
,
width
:
"100%"
,
height
:
"100%"
,
// 其他形状你可以使用形状路径
// shape: 'circle', // 示例
// 或者自定义路径
...
...
@@ -26,39 +26,25 @@ const getWordCloudChart = (data) => {
shrinkToFit
:
true
,
// 是否自动缩小以适应容器
// 字体
textStyle
:
{
// normal: {
// color: function () {
// return 'rgb(' + [
// Math.round(Math.random() * 160),
// Math.round(Math.random() * 160),
// Math.round(Math.random() * 160)
// ].join(',') + ')';
// }
// },
color
:
function
()
{
// let colors = [
// "rgba(189, 33, 33, 1)",
// "rgba(232, 151, 21, 1)",
// "rgba(220, 190, 68, 1)",
// "rgba(96, 58, 186, 1)",
// "rgba(32, 121, 69, 1)",
// "rgba(22, 119, 255, 1)",
// ];
// let colors = MUTICHARTCOLORS
return
MUTICHARTCOLORS
[
parseInt
(
Math
.
random
()
*
MUTICHARTCOLORS
.
length
)];
color
:
function
(
params
)
{
const
colors
=
MUTICHARTCOLORS
||
[];
if
(
!
colors
.
length
)
{
return
"#69B1FF"
;
}
return
colors
[
params
.
dataIndex
%
colors
.
length
];
},
emphasis
:
{
shadowBlur
:
5
,
shadowColor
:
"#333"
,
}
,
shadowColor
:
"#333"
}
},
// 设置词云数据
data
:
data
,
}
,
]
,
data
}
]
};
return
option
}
return
option
;
}
;
export
default
getWordCloudChart
\ No newline at end of file
export
default
getWordCloudChart
;
\ No newline at end of file
src/views/bill/ProcessOverviewDetailDialog.vue
0 → 100644
浏览文件 @
63313ad6
<
template
>
<div
v-if=
"visible"
ref=
"dialogRef"
class=
"dialog-wrapper"
:style=
"position"
>
<div
class=
"dialog-box1"
@
mousedown=
"handleMouseDown"
>
<div
class=
"icon"
>
<img
v-if=
"detailItem.orgName === '参议院'"
:src=
"logoSenate"
alt=
""
/>
<img
v-else
:src=
"logoHouse"
alt=
""
/>
</div>
<div
class=
"title"
>
<div
class=
"date"
>
{{
detailItem
.
actionDate
}}
</div>
<div
class=
"text"
>
{{
detailItem
.
actionTitle
}}
</div>
</div>
<div
class=
"close"
@
click=
"handleClose"
>
<img
:src=
"closeIcon"
alt=
""
/>
</div>
</div>
<div
class=
"dialog-box2"
v-if=
"detailItem.agreeVote !== null || detailItem.disagreeVote !== null"
>
<div
class=
"vote-bar"
>
<div
class=
"agree-bar"
:style=
"
{ flex: detailItem.agreeVote || 1 }">
</div>
<div
class=
"disagree-bar"
:style=
"
{ flex: detailItem.disagreeVote || 1 }">
</div>
</div>
<div
class=
"vote-text"
>
<div
class=
"agree-text"
>
{{
(
detailItem
.
agreeVote
||
0
)
+
"赞成"
}}
</div>
<div
class=
"disagree-text"
>
{{
(
detailItem
.
disagreeVote
||
0
)
+
"反对"
}}
</div>
</div>
</div>
<template
v-if=
"detailItem.fynrList && detailItem.fynrList.length"
>
<div
class=
"dialog-box4"
>
<div
class=
"box4-left"
>
<div
class=
"icon"
>
<img
:src=
"changeIcon"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"变更条款"
}}
</div>
</div>
</div>
<div
class=
"dialog-box5"
>
<div
class=
"box5-item"
v-for=
"(sub, subIndex) in detailItem.fynrList"
:key=
"subIndex + '-' + sub"
>
<div
class=
"icon"
></div>
<div
class=
"text"
>
{{
sub
}}
</div>
</div>
</div>
</
template
>
</div>
</template>
<
script
setup
>
import
{
ref
}
from
"vue"
;
defineProps
({
visible
:
{
type
:
Boolean
,
default
:
false
,
},
detailItem
:
{
type
:
Object
,
default
:
()
=>
({}),
},
position
:
{
type
:
Object
,
default
:
()
=>
({
left
:
"0px"
,
top
:
"0px"
}),
},
});
const
emit
=
defineEmits
([
"close"
]);
const
logoSenate
=
new
URL
(
"@/views/bill/deepDig/processOverview/assets/images/logo1.png"
,
import
.
meta
.
url
).
href
;
const
logoHouse
=
new
URL
(
"@/views/bill/deepDig/processOverview/assets/images/logo2.png"
,
import
.
meta
.
url
).
href
;
const
closeIcon
=
new
URL
(
"@/views/bill/deepDig/processOverview/assets/images/close.png"
,
import
.
meta
.
url
).
href
;
const
changeIcon
=
new
URL
(
"@/views/bill/deepDig/processOverview/assets/images/dialog-box4-icon.png"
,
import
.
meta
.
url
).
href
;
const
dialogRef
=
ref
(
null
);
const
handleClose
=
()
=>
{
emit
(
"close"
);
};
const
handleMouseDown
=
(
e
)
=>
{
const
dialog
=
dialogRef
.
value
;
if
(
!
dialog
)
return
;
const
startX
=
e
.
clientX
;
const
startY
=
e
.
clientY
;
const
initialLeft
=
dialog
.
offsetLeft
;
const
initialTop
=
dialog
.
offsetTop
;
const
move
=
(
moveEvent
)
=>
{
const
deltaX
=
moveEvent
.
clientX
-
startX
;
const
deltaY
=
moveEvent
.
clientY
-
startY
;
dialog
.
style
.
right
=
"auto"
;
dialog
.
style
.
left
=
`
${
initialLeft
+
deltaX
}
px`
;
dialog
.
style
.
top
=
`
${
initialTop
+
deltaY
}
px`
;
};
const
stop
=
()
=>
{
document
.
removeEventListener
(
"mousemove"
,
move
);
document
.
removeEventListener
(
"mouseup"
,
stop
);
};
document
.
addEventListener
(
"mousemove"
,
move
);
document
.
addEventListener
(
"mouseup"
,
stop
);
};
</
script
>
<
style
lang=
"scss"
scoped
>
.dialog-wrapper
{
position
:
absolute
;
width
:
480px
;
padding-bottom
:
20px
;
box-sizing
:
border-box
;
border
:
1px
solid
rgba
(
230
,
231
,
232
,
1
);
border-radius
:
4px
;
background
:
rgba
(
255
,
255
,
255
,
1
);
z-index
:
10000
;
box-shadow
:
0px
4px
12px
rgba
(
0
,
0
,
0
,
0
.15
);
.dialog-box1
{
display
:
flex
;
min-height
:
90px
;
height
:
auto
;
padding-bottom
:
15px
;
position
:
relative
;
border-bottom
:
1px
solid
rgba
(
240
,
242
,
244
,
1
);
cursor
:
move
;
.icon
{
width
:
48px
;
height
:
48px
;
margin-left
:
18px
;
margin-top
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.title
{
margin-top
:
20px
;
margin-left
:
16px
;
width
:
350px
;
.date
{
height
:
22px
;
color
:
rgba
(
59
,
65
,
75
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
700
;
line-height
:
22px
;
}
.text
{
margin-top
:
4px
;
color
:
rgba
(
59
,
65
,
75
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
700
;
line-height
:
22px
;
span
{
color
:
rgba
(
95
,
101
,
108
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
14px
;
font-weight
:
400
;
}
}
}
.close
{
position
:
absolute
;
top
:
14px
;
right
:
15px
;
width
:
16px
;
height
:
16px
;
cursor
:
pointer
;
img
{
width
:
100%
;
height
:
100%
;
}
}
}
.dialog-box2
{
height
:
59px
;
padding
:
0
23px
;
.vote-bar
{
display
:
flex
;
height
:
4px
;
width
:
100%
;
margin-top
:
20px
;
border-radius
:
2px
;
overflow
:
hidden
;
.agree-bar
{
background
:
#52c41a
;
margin-right
:
2px
;
}
.disagree-bar
{
background
:
#f5222d
;
}
}
.vote-text
{
display
:
flex
;
justify-content
:
space-between
;
margin-top
:
8px
;
.agree-text
{
color
:
#52c41a
;
font-size
:
14px
;
}
.disagree-text
{
color
:
#f5222d
;
font-size
:
14px
;
}
}
}
.dialog-box4
{
width
:
438px
;
margin-left
:
23px
;
margin-top
:
20px
;
display
:
flex
;
justify-content
:
space-between
;
height
:
30px
;
.box4-left
{
display
:
flex
;
.icon
{
margin-top
:
6px
;
width
:
18px
;
height
:
18px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.text
{
width
:
64px
;
height
:
30px
;
margin-left
:
6px
;
color
:
rgba
(
95
,
101
,
108
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
700
;
line-height
:
30px
;
}
}
}
.dialog-box5
{
margin-top
:
3px
;
margin-left
:
23px
;
width
:
438px
;
.box5-item
{
min-height
:
30px
;
color
:
rgba
(
132
,
136
,
142
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
400
;
line-height
:
1
.5
;
display
:
flex
;
margin-bottom
:
8px
;
.icon
{
flex-shrink
:
0
;
margin-left
:
15px
;
width
:
6px
;
height
:
6px
;
margin-top
:
9px
;
border-radius
:
3px
;
background
:
#84888e
;
}
.text
{
margin-left
:
10px
;
word-break
:
break-all
;
}
}
}
}
</
style
>
src/views/bill/background/index.vue
浏览文件 @
63313ad6
...
...
@@ -647,7 +647,7 @@ onMounted(() => {
.icon1
{
position
:
absolute
;
left
:
5
px
;
left
:
8
px
;
bottom
:
-8px
;
width
:
16px
;
height
:
16px
;
...
...
@@ -663,7 +663,7 @@ onMounted(() => {
.icon2
{
position
:
absolute
;
right
:
5
px
;
right
:
8
px
;
bottom
:
-8px
;
width
:
16px
;
height
:
16px
;
...
...
src/views/bill/billHome/index.vue
浏览文件 @
63313ad6
...
...
@@ -180,7 +180,8 @@
<OverviewCard
class=
"overview-card--single box9"
title=
"涉华法案关键条款"
:icon=
"box7HeaderIcon"
>
<div
class=
"overview-card-body box9-main"
>
<div
class=
"overview-chart-wrap"
>
<div
id=
"wordCloudChart"
class=
"overview-chart"
></div>
<el-empty
v-if=
"!wordCloudHasData"
description=
"暂无数据"
:image-size=
"100"
/>
<WordCloundChart
v-else
class=
"overview-chart"
width=
"100%"
height=
"100%"
:data=
"wordCloudData"
/>
</div>
<TipTab
class=
"overview-tip"
/>
</div>
...
...
@@ -197,8 +198,8 @@
</template>
<
script
setup
>
import
RiskSignal
from
"@/components/base/
R
iskSignal/index.vue"
;
import
{
onMounted
,
ref
,
onUnmounted
,
nextTick
,
watch
}
from
"vue"
;
import
RiskSignal
from
"@/components/base/
r
iskSignal/index.vue"
;
import
{
onMounted
,
ref
,
onUnmounted
,
nextTick
,
watch
,
computed
}
from
"vue"
;
import
router
from
"@/router/index"
;
import
setChart
from
"@/utils/setChart"
;
import
{
...
...
@@ -220,9 +221,9 @@ import OverviewCard from "./OverviewCard.vue";
import
ResourceLibrarySection
from
"./ResourceLibrarySection.vue"
;
import
{
useContainerScroll
}
from
"@/hooks/useScrollShow"
;
import
TipTab
from
"@/components/base/TipTab/index.vue"
;
import
WordCloundChart
from
"@/components/base/WordCloundChart/index.vue"
;
import
getMultiLineChart
from
"./utils/multiLineChart"
;
import
getWordCloudChart
from
"./utils/worldCloudChart"
;
import
getPieChart
from
"./utils/piechart"
;
import
getDoublePieChart
from
"./utils/doublePieChart"
;
...
...
@@ -637,6 +638,7 @@ const handleToSocialDetail = item => {
};
// 关键条款
const
wordCloudData
=
ref
([]);
const
wordCloudHasData
=
computed
(()
=>
Array
.
isArray
(
wordCloudData
.
value
)
&&
wordCloudData
.
value
.
length
>
0
);
const
handleGetKeyTK
=
async
()
=>
{
try
{
const
res
=
await
getBillOverviewKeyTK
();
...
...
@@ -655,8 +657,6 @@ const handleGetKeyTK = async () => {
};
const
handleBox6
=
async
()
=>
{
await
handleGetKeyTK
();
const
wordCloudChart
=
getWordCloudChart
(
wordCloudData
.
value
);
setChart
(
wordCloudChart
,
"wordCloudChart"
);
};
// 涉华领域分布
...
...
src/views/bill/deepDig/poliContribution/index.vue
浏览文件 @
63313ad6
...
...
@@ -111,48 +111,6 @@
</AnalysisBox>
</div>
<div
class=
"box3"
>
<!-- <div class="box-header">
<div class="icon"></div>
<div class="title">{{ "政治献金领域分布" }}</div>
<div class="header-right">
<div class="right-icon">
<img src="@/assets/icons/box-header-icon1.png" alt="" />
</div>
<div class="right-icon">
<img src="@/assets/icons/box-header-icon2.png" alt="" />
</div>
<div class="right-icon">
<img src="@/assets/icons/box-header-icon3.png" alt="" />
</div>
</div>
</div>
<div class="box3-main">
<div class="box3-main-left" id="chart2"></div>
<div class="box3-main-right">
<el-empty v-if="!areaList.length" description="暂无数据" :image-size="100" />
<div class="box3-main-right-item" v-for="(item, index) in areaList" :key="index">
<div class="id">{{ index + 1 }}</div>
<div class="name">{{ item.name }}</div>
<div class="line">
<div class="inner-line" :style="{ width: (item.num / areaList[0].num) * 100 + '%' }"></div>
</div>
<div class="num">{{ item.numtext }}</div>
<div class="more">{{ `${item.insNum}家机构 >` }}</div>
</div>
</div>
</div>
<div class="box-footer">
<div class="box-footer-left">
<img src="@/assets/icons/box-footer-left-icon.png" alt="" />
</div>
<div class="box-footer-center">
{{ currentPersonName }}的政治资金主要依赖于一个由亿万富翁、特定行业利益集团及通过“超级政治行动委员会”
运作的大额捐款网络。
</div>
<div class="box-footer-right">
<img src="@/assets/icons/box-footer-right-icon.png" alt="" />
</div>
</div> -->
<AnalysisBox
title=
"政治献金领域分布"
>
<div
class=
"box3-main"
:class=
"{ 'box3-main-no-footer': !showHardcodedTips }"
>
<div
class=
"box3-main-left"
id=
"chart2"
></div>
...
...
@@ -196,6 +154,7 @@ import setChart from "@/utils/setChart";
import
getPieChart
from
"./utils/piechart"
;
import
getSankeyChart
from
"./utils/sankey"
;
import
{
MUTICHARTCOLORS
}
from
"@/common/constant"
;
import
Img1
from
"./assets/images/1.png"
;
import
Img2
from
"./assets/images/2.png"
;
...
...
@@ -434,23 +393,9 @@ const topAreaList = computed(() => {
return
areaList
.
value
.
slice
(
0
,
5
);
});
const
chart2ColorList
=
ref
([
"#4096FF"
,
"#FFA39E"
,
"#ADC6FF"
,
"#FFC069"
,
"#B5F5EC"
,
"#B37FEB"
,
"#D6E4FF"
]);
const
sankeyColors
=
[
"#5470c6"
,
"#91cc75"
,
"#fac858"
,
"#ee6666"
,
"#73c0de"
,
"#3ba272"
,
"#fc8452"
,
"#9a60b4"
,
"#ea7ccc"
,
"#a2c0f1"
,
"#f596aa"
,
"#e6b422"
,
"#4b2c20"
];
const
chart2ColorList
=
ref
([...
MUTICHARTCOLORS
]);
const
sankeyColors
=
[...
MUTICHARTCOLORS
];
const
partyContributionList
=
ref
([
{
...
...
src/views/bill/deepDig/processOverview/index.vue
浏览文件 @
63313ad6
差异被折叠。
点击展开。
src/views/bill/template/index.vue
浏览文件 @
63313ad6
...
...
@@ -100,11 +100,11 @@
<div
class=
"term-main"
>
<div
class=
"term-row term-row-cn"
>
<div
class=
"term-no-cn"
>
第{{ term.tkxh }}条.
</div>
<div
class=
"term-content-cn"
>
{{ term.fynr }}
</div>
<div
class=
"term-content-cn"
v-html=
"getTermContentHtml(term, 'cn')"
>
</div>
</div>
<div
class=
"term-row term-row-en"
v-if=
"termsShowOriginal"
>
<div
class=
"term-no-en"
>
Sec.{{ term.tkxh }}
</div>
<div
class=
"term-content-en"
>
{{ term.ywnr }}
</div>
<div
class=
"term-content-en"
v-html=
"getTermContentHtml(term, 'en')"
>
</div>
</div>
</div>
</div>
...
...
@@ -136,6 +136,8 @@ import * as echarts from "echarts";
import
{
Search
}
from
"@element-plus/icons-vue"
;
import
getPieChart
from
"./utils/piechart"
;
import
{
getBillContentId
,
getBillContentTk
,
getBillContentXzfs
,
getBillHyly
}
from
"@/api/bill"
;
import
{
MUTICHARTCOLORS
}
from
"@/common/constant"
;
import
{
extractTextEntity
}
from
"@/api/intelligent/index"
;
const
route
=
useRoute
();
...
...
@@ -161,6 +163,134 @@ const domainLoading = ref(false);
const
termsHighlight
=
ref
(
true
);
const
termsShowOriginal
=
ref
(
true
);
const
entityRequestToken
=
ref
(
0
);
const
termEntityCache
=
ref
(
new
Map
());
const
escapeHtml
=
value
=>
{
const
str
=
String
(
value
??
""
);
return
str
.
replace
(
/&/g
,
"&"
)
.
replace
(
/</g
,
"<"
)
.
replace
(
/>/g
,
">"
)
.
replace
(
/"/g
,
"""
)
.
replace
(
/'/g
,
"'"
);
};
const
normalizeEntities
=
entities
=>
{
const
list
=
Array
.
isArray
(
entities
)
?
entities
:
[];
return
list
.
map
(
item
=>
{
return
{
text_span
:
String
(
item
?.
text_span
??
""
).
trim
(),
type
:
String
(
item
?.
type
??
""
).
trim
()
};
})
.
filter
(
item
=>
item
.
text_span
);
};
const
getEntityRanges
=
(
text
,
entities
)
=>
{
const
ranges
=
[];
const
rawText
=
String
(
text
??
""
);
if
(
!
rawText
)
return
ranges
;
const
list
=
normalizeEntities
(
entities
).
sort
((
a
,
b
)
=>
b
.
text_span
.
length
-
a
.
text_span
.
length
);
for
(
const
ent
of
list
)
{
let
startIndex
=
0
;
while
(
startIndex
<
rawText
.
length
)
{
const
idx
=
rawText
.
indexOf
(
ent
.
text_span
,
startIndex
);
if
(
idx
===
-
1
)
break
;
ranges
.
push
({
start
:
idx
,
end
:
idx
+
ent
.
text_span
.
length
,
ent
});
startIndex
=
idx
+
ent
.
text_span
.
length
;
}
}
ranges
.
sort
((
a
,
b
)
=>
a
.
start
-
b
.
start
||
b
.
end
-
a
.
end
);
const
merged
=
[];
let
lastEnd
=
0
;
for
(
const
r
of
ranges
)
{
if
(
r
.
start
<
lastEnd
)
continue
;
merged
.
push
(
r
);
lastEnd
=
r
.
end
;
}
return
merged
;
};
const
buildHighlightedHtml
=
(
text
,
entities
,
enableHighlight
)
=>
{
const
rawText
=
String
(
text
??
""
);
if
(
!
rawText
)
return
""
;
const
safeText
=
escapeHtml
(
rawText
).
replace
(
/
\n
/g
,
"<br />"
);
if
(
!
enableHighlight
)
return
safeText
;
const
ranges
=
getEntityRanges
(
rawText
,
entities
);
if
(
!
ranges
.
length
)
return
safeText
;
let
html
=
""
;
let
cursor
=
0
;
for
(
const
r
of
ranges
)
{
if
(
cursor
<
r
.
start
)
{
html
+=
escapeHtml
(
rawText
.
slice
(
cursor
,
r
.
start
));
}
const
spanText
=
rawText
.
slice
(
r
.
start
,
r
.
end
);
const
type
=
escapeHtml
(
r
.
ent
?.
type
??
""
);
html
+=
`<span class="term-entity" data-entity-type="
${
type
}
">
${
escapeHtml
(
spanText
)}
</span>`
;
cursor
=
r
.
end
;
}
if
(
cursor
<
rawText
.
length
)
{
html
+=
escapeHtml
(
rawText
.
slice
(
cursor
));
}
return
html
.
replace
(
/
\n
/g
,
"<br />"
);
};
const
getTermEntityKey
=
(
term
,
lang
)
=>
{
const
baseKey
=
getTermKey
(
term
,
-
1
);
return
`
${
baseKey
}
__
${
lang
}
`
;
};
const
ensureEntitiesForTerms
=
async
terms
=>
{
if
(
!
termsHighlight
.
value
)
return
;
const
list
=
Array
.
isArray
(
terms
)
?
terms
:
[];
if
(
!
list
.
length
)
return
;
const
currentToken
=
++
entityRequestToken
.
value
;
const
tasks
=
[];
for
(
const
term
of
list
)
{
const
cnKey
=
getTermEntityKey
(
term
,
"cn"
);
const
enKey
=
getTermEntityKey
(
term
,
"en"
);
if
(
!
termEntityCache
.
value
.
has
(
cnKey
)
&&
String
(
term
?.
fynr
??
""
).
trim
())
{
tasks
.
push
({
key
:
cnKey
,
text
:
term
.
fynr
});
}
if
(
!
termEntityCache
.
value
.
has
(
enKey
)
&&
String
(
term
?.
ywnr
??
""
).
trim
())
{
tasks
.
push
({
key
:
enKey
,
text
:
term
.
ywnr
});
}
}
if
(
!
tasks
.
length
)
return
;
try
{
const
results
=
await
Promise
.
all
(
tasks
.
map
(
async
item
=>
{
const
res
=
await
extractTextEntity
(
item
.
text
);
const
entities
=
normalizeEntities
(
res
?.
result
??
res
?.
data
?.
result
??
res
?.
data
??
res
);
return
{
key
:
item
.
key
,
entities
};
})
);
if
(
currentToken
!==
entityRequestToken
.
value
)
return
;
for
(
const
r
of
results
)
{
termEntityCache
.
value
.
set
(
r
.
key
,
r
.
entities
);
}
}
catch
(
error
)
{
if
(
currentToken
!==
entityRequestToken
.
value
)
return
;
}
};
const
getTermContentHtml
=
(
term
,
lang
)
=>
{
const
raw
=
lang
===
"en"
?
term
?.
ywnr
:
term
?.
fynr
;
const
key
=
getTermEntityKey
(
term
,
lang
);
const
entities
=
termEntityCache
.
value
.
get
(
key
)
||
[];
return
buildHighlightedHtml
(
raw
,
entities
,
termsHighlight
.
value
);
};
const
tkRequestToken
=
ref
(
0
);
const
xzfsRequestToken
=
ref
(
0
);
const
hylyRequestToken
=
ref
(
0
);
...
...
@@ -182,9 +312,9 @@ const getTermSerial = index => {
};
const
chart1Data
=
ref
([]);
const
chart1ColorList
=
ref
([
"#4096ff"
,
"#b37feb"
,
"#ff7875"
,
"#85a5ff"
,
"#69b1ff"
,
"#ffc069"
,
"#87e8de"
]);
const
chart1ColorList
=
ref
([
...
MUTICHARTCOLORS
]);
const
chart2ColorList
=
ref
([
"#ff7875"
,
"#85a5ff"
,
"#95de64"
,
"#ffc069"
,
"#85e5db"
]);
const
chart2ColorList
=
ref
([
...
MUTICHARTCOLORS
]);
const
chart2Data
=
ref
([]);
...
...
@@ -218,6 +348,14 @@ watch([selectedDomain, selectedLimit], () => {
handleGetBillContentTk
(
checkedValue
.
value
?
"Y"
:
"N"
);
});
watch
(
[
termsHighlight
,
termsShowOriginal
],
()
=>
{
ensureEntitiesForTerms
(
displayTermsList
.
value
);
},
{
immediate
:
true
}
);
const
handleSearchSubmit
=
()
=>
{
searchKeyword
.
value
=
searchValue
.
value
;
currentPage
.
value
=
1
;
...
...
@@ -362,6 +500,7 @@ const handleGetBillContentTk = async cRelated => {
return item;
});
total.value = res.data.totalElements || 0;
ensureEntitiesForTerms(mainTermsList.value);
} else {
mainTermsList.value = [];
total.value = 0;
...
...
@@ -805,6 +944,14 @@ onMounted(async () => {
font-weight
:
700
;
line-height
:
24px
;
color
:
var
(
--
text-primary-80-color
);
:deep
(
.term-entity
)
{
display
:
inline
;
padding
:
0
2px
;
border-radius
:
4px
;
background
:
rgba
(
255
,
213
,
79
,
0
.35
);
box-shadow
:
inset
0
0
0
1px
rgba
(
255
,
193
,
7
,
0
.25
);
}
}
.term-content-en
{
...
...
@@ -813,6 +960,14 @@ onMounted(async () => {
font-weight
:
400
;
line-height
:
24px
;
color
:
var
(
--
text-primary-65-color
);
:deep
(
.term-entity
)
{
display
:
inline
;
padding
:
0
2px
;
border-radius
:
4px
;
background
:
rgba
(
255
,
213
,
79
,
0
.28
);
box-shadow
:
inset
0
0
0
1px
rgba
(
255
,
193
,
7
,
0
.2
);
}
}
.open
{
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论