Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
risk-monitor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蔡建
risk-monitor
Commits
273f345b
提交
273f345b
authored
12月 17, 2025
作者:
coderBryanFu
浏览文件
操作
浏览文件
下载
差异文件
update
上级
1b14c707
af566f60
隐藏空白字符变更
内嵌
并排
正在显示
46 个修改的文件
包含
4458 行增加
和
2270 行删除
+4458
-2270
bill.js
src/api/bill.js
+17
-5
billHome.js
src/api/bill/billHome.js
+34
-2
deepdig.js
src/api/deepdig.js
+12
-0
exportControl.js
src/api/exportControl.js
+49
-16
button.vue
src/components/button/button.vue
+1
-0
buttonList.vue
src/components/buttonList/buttonList.vue
+1
-0
index.vue
src/views/bill/background/index.vue
+38
-30
index.vue
src/views/bill/billHome/index.vue
+197
-102
multiLineChart.js
src/views/bill/billHome/utils/multiLineChart.js
+60
-16
worldCloudChart.js
src/views/bill/billHome/utils/worldCloudChart.js
+2
-0
index.vue
src/views/bill/deepDig/processAnalysis/index.vue
+55
-6
boxplot.js
src/views/bill/deepDig/processAnalysis/utils/boxplot.js
+36
-4
STimeline.vue
src/views/bill/introdoction/STimeline.vue
+121
-47
index.vue
src/views/bill/introdoction/index.vue
+97
-51
index.vue
src/views/bill/template/index.vue
+108
-45
piechart.js
src/views/bill/template/utils/piechart.js
+4
-1
fishbone-back.vue
...views/exportControl/analysis/components/fishbone-back.vue
+98
-492
fishbone-mock.json
...iews/exportControl/analysis/components/fishbone-mock.json
+671
-13
fishbone.vue
src/views/exportControl/analysis/components/fishbone.vue
+250
-156
influencePanel2.vue
...ews/exportControl/analysis/components/influencePanel2.vue
+9
-25
mapCharts.vue
src/views/exportControl/analysis/components/mapCharts.vue
+14
-0
panel1.vue
src/views/exportControl/analysis/components/panel1.vue
+29
-8
panel3.vue
src/views/exportControl/analysis/components/panel3.vue
+14
-4
pieCharts.vue
src/views/exportControl/analysis/components/pieCharts.vue
+1
-1
overview.vue
src/views/exportControl/analysis/content/overview.vue
+128
-25
index.vue
src/views/exportControl/analysis/index.vue
+8
-3
info.vue
src/views/exportControl/components/info.vue
+5
-1
index.vue
src/views/exportControl/index.vue
+273
-203
charts.js
src/views/exportControl/utils/charts.js
+937
-901
bg.png
src/views/gjOverView/assets/bg.png
+0
-0
icon1.png
src/views/gjOverView/assets/icon1.png
+0
-0
MeansAnalysis.vue
src/views/gjOverView/component/MeansAnalysis.vue
+1
-1
ResourceAnalysis.vue
src/views/gjOverView/component/ResourceAnalysis.vue
+49
-20
Timeline.vue
src/views/gjOverView/component/Timeline.vue
+47
-12
index.vue
src/views/gjOverView/index.vue
+82
-16
barChart2.js
src/views/gjOverView/js/barChart2.js
+12
-4
multiLineChart2.js
src/views/gjOverView/js/multiLineChart2.js
+1
-1
radarChart2.js
src/views/gjOverView/js/radarChart2.js
+67
-36
TechnologyFigures-icon1.png
...chnologyFigures/assets/images/TechnologyFigures-icon1.png
+0
-0
TechnologyFigures-icon2.png
...chnologyFigures/assets/images/TechnologyFigures-icon2.png
+0
-0
TechnologyFigures-icon3.png
...chnologyFigures/assets/images/TechnologyFigures-icon3.png
+0
-0
TechnologyFigures-icon4.png
...chnologyFigures/assets/images/TechnologyFigures-icon4.png
+0
-0
SourceLibrary.vue
src/views/technologyFigures/component/SourceLibrary.vue
+81
-0
index.vue
src/views/technologyFigures/index.vue
+7
-7
source.json
src/views/technologyFigures/json/source.json
+32
-16
出口管制接口.md
出口管制接口.md
+810
-0
没有找到文件。
src/api/bill.js
浏览文件 @
273f345b
...
...
@@ -14,13 +14,13 @@ export function getBillInfo(params) {
// 提出人-根据动议ID获取对应的提出人信息
/**
* @param {
i
d}
* @param {
billI
d}
* @header token
*/
export
function
getBillPerson
(
params
)
{
return
request
({
method
:
'GET'
,
url
:
`/api/billInfoBean/person/
${
params
.
i
d
}
`
,
url
:
`/api/billInfoBean/person/
${
params
.
billI
d
}
`
,
params
,
})
}
...
...
@@ -63,6 +63,18 @@ export function getBillBackground(params) {
params
,
})
}
// 相关事件-根据法案ID获取相关事件信息
/**
* @param {id}
* @header token
*/
export
function
getBillInfoEvent
(
params
)
{
return
request
({
method
:
'GET'
,
url
:
`/api/billInfoBean/event/
${
params
.
id
}
`
,
params
,
})
}
// 议员相关性-根据法案ID获取议员分析信息(现在只包括名称 支持 反对,没有标签和事件动态)
/**
...
...
@@ -92,20 +104,20 @@ export function getBillContentId(params) {
// 主要条款-根据原文ID获取条款内容
/**
* @param {id,cRelated,currentPage,pageSize}
* @param {
billid,
id,cRelated,currentPage,pageSize}
* @header token
*/
export
function
getBillContentTk
(
params
)
{
return
request
({
method
:
'GET'
,
url
:
`/api/billInfoBean/content/tk/
${
params
.
id
}
`
,
url
:
`/api/billInfoBean/content/tk/
${
params
.
billid
}
/
${
params
.
id
}
`
,
params
,
})
}
// 限制方式-根据法案原文ID获取限制方式列表
/**
* @param {
i
d}
* @param {
billI
d}
* @header token
*/
export
function
getBillContentXzfs
(
params
)
{
...
...
src/api/bill/billHome.js
浏览文件 @
273f345b
...
...
@@ -13,11 +13,11 @@ export function getBillIndustry(params) {
}
// 涉华法案统计
export
function
getBillCount
()
{
export
function
getBillCount
(
params
)
{
return
request
({
method
:
'GET'
,
url
:
`/api/BillOverview/billCount`
,
params
})
}
...
...
@@ -64,4 +64,35 @@ export function getHylyList() {
method
:
'GET'
,
url
:
`/api/billImpactAnalysis/industry/hylyList`
,
})
}
// 获取法案提出部门
/**
* @param {year}
*/
export
function
getBillPostOrg
(
params
)
{
return
request
({
method
:
'GET'
,
url
:
`/api/BillOverview/billPostOrg/
${
params
.
year
}
`
,
})
}
// 获取关键议员提案
/**
* @param {year}
*/
export
function
getMemberProposal
(
params
)
{
return
request
({
method
:
'GET'
,
url
:
`/api/BillOverview/memberProposal/
${
params
.
year
}
`
,
})
}
// 获取资源库
export
function
getBills
(
params
)
{
return
request
({
method
:
'GET'
,
url
:
`/api/BillOverview/bills`
,
params
})
}
\ No newline at end of file
src/api/deepdig.js
浏览文件 @
273f345b
...
...
@@ -12,6 +12,18 @@ export function getBillTimeAnalyze(params) {
})
}
// 修正案次数分析
/**
* @param {id}
*/
export
function
getBillAmeAnalyzeCount
(
params
)
{
return
request
({
method
:
'GET'
,
url
:
`/api/billDeepDive/ameAnalyze/count/
${
params
.
id
}
`
,
params
,
})
}
// 根据法案ID获取党派政治献金
/**
* @param {id, personCongress}
...
...
src/api/exportControl.js
浏览文件 @
273f345b
...
...
@@ -23,7 +23,8 @@ export function getEntitiesDataCount() {
return
request200
(
request
({
method
:
"GET"
,
url
:
"/api/entitiesDataCount/countData"
// url: "/api/entitiesDataCount/countData",
url
:
"/api/sanctionList/export/getTotalInfo"
})
);
}
...
...
@@ -62,12 +63,15 @@ export function getEntitiesDataInfo() {
* maxCount: number
* }[]>}
*/
export
function
getIndustryCountByYear
()
{
export
function
getIndustryCountByYear
(
sanTypeId
)
{
return
request200
(
request
({
method
:
"GET"
,
// url: "/api/entitiesDataCount/industryCountByYear"
url
:
"/api/entitiesDataCount/getAnnualCount"
url
:
"/api/entitiesDataCount/getAnnualCount"
,
params
:
{
sanTypeId
}
})
);
}
...
...
@@ -84,11 +88,16 @@ export function getIndustryCountByYear() {
* domains: string[]
* }>}
*/
export
function
getCountDomainByYear
()
{
export
function
getCountDomainByYear
(
isRule
,
startYear
=
"2020"
,
endYear
=
new
Date
().
getFullYear
()
)
{
return
request200
(
request
({
method
:
"GET"
,
url
:
"/api/entitiesDataCount/countDomainByYear"
method
:
"POST"
,
url
:
"/api/entitiesDataCount/getAnnualSanDomain"
,
data
:
{
isRule
,
startYear
,
endYear
}
})
);
}
...
...
@@ -187,6 +196,21 @@ export function getKeyEntityList(date, keyword = "") {
);
}
/**
* 区域分布查询
*/
export
function
getAreaDistribution
(
date
)
{
return
request200
(
request
({
method
:
"GET"
,
url
:
"/api/entitiesDataInfo/getRegionDistribution"
,
params
:
{
sanctionDate
:
date
||
"2025-11-11"
}
})
);
}
/**
* 不同领域实体统计
* @param {string} startTime - 统计开始时间,格式为 'YYYY-MM-DD'
...
...
@@ -292,7 +316,7 @@ export function getDomainDistribution(sanctionDate = "2025-11-11") {
* startTime: string
* }[]>}
*/
export
function
getEntitiesList
(
typeName
=
"实体清单"
,
pageNum
=
1
,
pageSize
=
10
)
{
export
function
getEntitiesList
(
typeName
=
"实体清单"
,
pageNum
=
1
,
pageSize
=
10
,
sanctionDate
=
""
,
rule
=
false
)
{
return
request200
(
request
({
method
:
"POST"
,
...
...
@@ -300,7 +324,9 @@ export function getEntitiesList(typeName = "实体清单", pageNum = 1, pageSize
data
:
{
typeName
,
pageNum
,
pageSize
pageSize
,
sanctionDate
,
rule
}
})
);
...
...
@@ -340,15 +366,16 @@ export function getCompareCountSan(startTime) {
* count:number
* }[]>}
*/
export
function
getEntitiesChangeCount
(
dom
ain
,
type
)
{
export
function
getEntitiesChangeCount
(
dom
ianId
,
typeId
)
{
return
request200
(
request
({
method
:
"GET"
,
// url: '/api/entitiesDataCount/entitiesChangeCount',
url
:
"/api/entitiesDataCount/sanCountByYear"
,
// url: "/api/entitiesDataCount/sanCountByYear",
url
:
"/api/entitiesDataInfo/getCountByDomianAndType"
,
params
:
{
dom
ain
,
type
dom
ianId
,
type
Id
}
})
);
...
...
@@ -377,11 +404,14 @@ export function getEntitiesGrowthTrend() {
* xAxis: string[]
* }>}
*/
export
function
getEntitiesUpdateCount
()
{
export
function
getEntitiesUpdateCount
(
sanTypeId
=
1
)
{
return
request200
(
request
({
method
:
"GET"
,
url
:
"/api/entitiesDataCount/entitiesUpdateCount"
url
:
"/api/entitiesDataCount/getAnnualCount"
,
params
:
{
sanTypeId
}
})
);
}
...
...
@@ -389,11 +419,14 @@ export function getEntitiesUpdateCount() {
/**
* 制裁领域分析
*/
export
function
getSanDomainCount
()
{
export
function
getSanDomainCount
(
rule
)
{
return
request200
(
request
({
method
:
"GET"
,
url
:
"/api/entitiesDataCount/getSanDomainCount"
url
:
"/api/entitiesDataCount/getSanDomainCount"
,
params
:
{
rule
}
})
);
}
...
...
src/components/button/button.vue
浏览文件 @
273f345b
...
...
@@ -32,6 +32,7 @@ const emit = defineEmits(["click"]);
cursor
:
pointer
;
padding-left
:
8px
;
padding-right
:
8px
;
flex-shrink
:
0
;
}
.activeButton
{
border
:
1px
solid
rgb
(
10
,
87
,
166
);
...
...
src/components/buttonList/buttonList.vue
浏览文件 @
273f345b
...
...
@@ -61,5 +61,6 @@ function setActiveIndex(item) {
.buttonList
{
display
:
flex
;
gap
:
8px
;
overflow-x
:
auto
;
}
</
style
>
src/views/bill/background/index.vue
浏览文件 @
273f345b
...
...
@@ -35,8 +35,8 @@
v-for=
"(item, index) in backgroundList"
:key=
"item.id"
>
<div
class=
"id"
>
{{
index
+
1
}}
</div>
<div
class=
"title"
>
{{
item
.
b
jnr
}}
</div>
<div
class=
"id"
>
{{
(
currentPage
-
1
)
*
10
+
index
+
1
}}
</div>
<div
class=
"title"
>
{{
item
.
b
ackgroundTitle
}}
</div>
<div
class=
"share"
>
<img
src=
"./assets/icons/open.png"
alt=
"打开"
/>
</div>
...
...
@@ -45,7 +45,7 @@
<div
class=
"box1-main-footer"
>
<div
class=
"info"
>
{{
`共有${
backgroundList.length
}
条${
`共有${
total
}
条${
box1BtnActive === 1 ? "涉华" : "全部"
}
背景`
}}
...
...
@@ -54,7 +54,9 @@
<
el
-
pagination
background
layout
=
"prev, pager, next"
:
total
=
"backgroundList.length"
:
total
=
"total"
v
-
model
:
current
-
page
=
"currentPage"
@
current
-
change
=
"handleGetBillBackground"
/>
<
/div
>
<
/div
>
...
...
@@ -80,7 +82,7 @@
:
key
=
"index"
>
<
div
class
=
"left"
>
<
img
:
src
=
"item.image"
alt
=
""
/>
<
img
:
src
=
"item.image
Url || item.image
"
alt
=
""
/>
<
/div
>
<
div
class
=
"center"
>
<
div
class
=
"title"
>
{{
item
.
sjbt
}}
<
/div
>
...
...
@@ -157,7 +159,7 @@
/><
/el-icon
>
<
/div
>
<
div
class
=
"right-box1-main-bottom"
>
<
WordCloudMap
:
data
=
"wordCloudData"
:
shape
=
"circle"
/>
<
WordCloudMap
:
data
=
"wordCloudData"
shape
=
"circle"
/>
<
/div
>
<
/div
>
<
/div
>
...
...
@@ -214,25 +216,26 @@ import {
getBillBackground
,
getBillEvent
,
getBillPersonAnalyze
,
getBillInfoEvent
}
from
"@/api/bill"
;
const
box1BtnActive
=
ref
(
1
);
const
currentPage
=
ref
(
1
);
const
total
=
ref
(
0
);
const
handleClickBox1Btn
=
(
index
)
=>
{
box1BtnActive
.
value
=
index
;
if
(
index
===
2
)
{
handleGetBillBackground
(
false
);
}
else
{
handleGetBillBackground
(
true
);
}
currentPage
.
value
=
1
;
handleGetBillBackground
();
}
;
const
box2BtnActive
=
ref
(
1
);
const
handleClickBox2Btn
=
(
index
)
=>
{
box2BtnActive
.
value
=
index
;
if
(
index
===
1
)
{
handleGetBillPersonAnalyze
(
true
);
}
else
{
handleGetBillPersonAnalyze
(
false
);
}
else
{
handleGetBillPersonAnalyze
(
true
);
}
}
;
...
...
@@ -439,27 +442,29 @@ const wordCloudData = [
];
// 获取立法背景内容
const
handleGetBillBackground
=
async
(
cRelated
)
=>
{
const
handleGetBillBackground
=
async
()
=>
{
const
cRelated
=
box1BtnActive
.
value
===
1
?
'Y'
:
'N'
;
const
params
=
{
cRelated
:
cRelated
,
id
:
window
.
sessionStorage
.
getItem
(
"billId"
),
currentPage
:
0
,
currentPage
:
currentPage
.
value
-
1
,
pageSize
:
10
,
}
;
try
{
const
res
=
await
getBillBackground
(
params
);
console
.
log
(
"立法背景"
,
res
);
backgroundList
.
value
=
res
.
data
.
content
;
total
.
value
=
res
.
data
.
totalElements
;
// 假设API返回totalElements
}
catch
(
error
)
{
}
}
;
// 获取相关事件
const
handleGetRelatedEvent
=
async
()
=>
{
const
params
=
{
id
:
1
,
id
:
window
.
sessionStorage
.
getItem
(
"billId"
)
,
}
;
try
{
const
res
=
await
getBillEvent
(
params
);
const
res
=
await
getBill
Info
Event
(
params
);
console
.
log
(
"相关事件"
,
res
);
eventList
.
value
=
res
.
data
;
eventList
.
value
.
forEach
((
item
,
index
)
=>
{
...
...
@@ -488,8 +493,9 @@ const handleGetBillPersonAnalyze = async (isOppose) => {
const
res
=
await
getBillPersonAnalyze
(
params
);
console
.
log
(
"议员相关性分析"
,
res
);
personList
.
value
=
res
.
data
;
personList
.
value
.
forEach
((
item
)
=>
{
item
.
image
=
user1
;
personList
.
value
.
forEach
((
item
,
index
)
=>
{
const
imgList
=
[
user1
,
user2
,
user3
,
user4
,
user5
];
item
.
image
=
imgList
[
index
%
imgList
.
length
];
item
.
icon
=
userIcon
;
item
.
icon1
=
userIcon1
;
}
);
...
...
@@ -497,9 +503,9 @@ const handleGetBillPersonAnalyze = async (isOppose) => {
}
;
onMounted
(()
=>
{
handleGetBillBackground
(
true
);
handleGetBillBackground
();
handleGetRelatedEvent
();
handleGetBillPersonAnalyze
(
tru
e
);
handleGetBillPersonAnalyze
(
fals
e
);
}
);
<
/script
>
...
...
@@ -572,7 +578,7 @@ onMounted(() => {
display
:
flex
;
flex
-
wrap
:
wrap
;
justify
-
content
:
space
-
between
;
align
-
content
:
flex
-
start
;
.
box1
-
main
-
item
{
width
:
544
px
;
height
:
48
px
;
...
...
@@ -598,11 +604,12 @@ onMounted(() => {
width
:
440
px
;
height
:
48
px
;
line
-
height
:
48
px
;
color
:
rgb
a
(
95
,
101
,
108
,
1
);
font
-
family
:
Microsoft
YaHei
;
font
-
size
:
1
4
px
;
color
:
rgb
(
59
,
65
,
75
);
font
-
family
:
"Microsoft YaHei"
;
font
-
size
:
1
6
px
;
font
-
weight
:
400
;
text
-
align
:
left
;
overflow
:
hidden
;
}
.
share
{
margin
-
left
:
13
px
;
...
...
@@ -626,8 +633,8 @@ onMounted(() => {
.
info
{
height
:
22
px
;
line
-
height
:
22
px
;
color
:
rgb
a
(
132
,
136
,
142
,
1
);
font
-
family
:
Microsoft
YaHei
;
color
:
rgb
(
132
,
136
,
142
);
font
-
family
:
"Microsoft YaHei"
;
font
-
size
:
14
px
;
font
-
weight
:
400
;
text
-
align
:
left
;
...
...
@@ -645,6 +652,7 @@ onMounted(() => {
margin
-
top
:
9
px
;
margin
-
left
:
23
px
;
height
:
300
px
;
overflow
:
auto
;
.
box2
-
main
-
item
{
width
:
1103
px
;
height
:
60
px
;
...
...
@@ -659,9 +667,9 @@ onMounted(() => {
width
:
64
px
;
height
:
48
px
;
border
-
radius
:
2
px
;
im
age
{
width
:
100
px
;
height
:
100
%
;
im
g
{
width
:
64
px
;
height
:
48
px
;
}
}
.
center
{
...
...
src/views/bill/billHome/index.vue
浏览文件 @
273f345b
...
...
@@ -84,6 +84,7 @@
<div
class=
"btn-icon"
>
<img
src=
"@/assets/icons/arrow-right-icon.png"
alt=
""
/>
</div>
</div>
<div
class=
"btn"
@
click=
"handleToPosi('position2')"
>
<div
class=
"btn-text"
>
{{
"资讯要闻"
}}
</div>
...
...
@@ -140,15 +141,15 @@
<div
class=
"info-box"
:class=
"
{
info1: i
tem.status === 1
,
info2: i
tem.status === 2
,
info3: i
tem.status === 3
,
info4: i
tem.status === 4
info1: i
ndex === 0
,
info2: i
ndex === 1
,
info3: i
ndex === 2
,
info4: i
ndex === 3
}"
v-for="(item, index) in curBill.hylyList"
:key="index"
>
{{
item
}}
{{
item
.
industryName
}}
</div>
</div>
<div
class=
"box1-main-left-info1"
>
...
...
@@ -307,6 +308,12 @@
<div
class=
"header-right-text"
>
{{
"数据来源:美国国会官方网站"
}}
</div>
</div>
</div>
<div
class=
"box5-select"
>
<el-select
v-model=
"box5Select"
placeholder=
"选择领域"
@
change=
"handleBox5Change"
style=
"width: 150px"
>
<el-option
label=
"全部领域"
value=
"全部领域"
/>
<el-option
v-for=
"item in categoryList.slice(1)"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
</el-select>
</div>
<div
class=
"box5-main"
id=
"box5Chart"
></div>
</div>
<div
class=
"box6"
>
...
...
@@ -386,13 +393,13 @@
@
click=
"handleClcikToCharacter(0)"
>
<div
class=
"box8-main-item-left"
>
<img
:src=
"item.img"
alt=
""
/>
<img
:src=
"item.img"
alt=
""
referrerpolicy=
"no-referrer"
class=
"left-img"
/>
<div
class=
"left-icon1"
>
<img
:src=
"item.dangpai"
alt=
""
/>
</div>
<div
class=
"left-icon2"
>
<img
:src=
"item.yuan"
alt=
""
/>
</div>
</div>
</div>
<div
class=
"box8-main-item-center"
>
<div
class=
"box8-main-item-center-top"
>
{{
item
.
name
}}
</div>
...
...
@@ -448,16 +455,7 @@
{{
cate
.
name
}}
<
/div
>
<
/div
>
<
div
class
=
"select-box"
>
<
el
-
select
v
-
model
=
"releaseTime"
placeholder
=
"选择发布时间"
style
=
"width: 120px"
>
<
el
-
option
v
-
for
=
"item in releaseTimeList"
:
key
=
"item.value"
:
label
=
"item.label"
:
value
=
"item.value"
/>
<
/el-select
>
<
/div
>
<
/div
>
<
div
class
=
"home-main-footer-main"
>
<
div
class
=
"left"
>
...
...
@@ -467,17 +465,16 @@
<
div
class
=
"title"
>
{{
"科技领域"
}}
<
/div
>
<
/div
>
<
div
class
=
"select-main"
>
<
div
class
=
"checkbox-group
"
>
<
el
-
checkbox
-
group
class
=
"checkbox-group"
v
-
model
=
"activeAreaList
"
>
<
el
-
checkbox
v
-
for
=
"
area
in areaList"
v
-
for
=
"
(area, index)
in areaList"
:
key
=
"area.id"
v
-
model
=
"activeAreaList"
:
label
=
"area.id"
class
=
"filter-checkbox"
>
{{
area
.
name
}}
<
/el-checkbox
>
<
/
div
>
<
/
el-checkbox-group
>
<
/div
>
<
/div
>
<
div
class
=
"select-box"
>
...
...
@@ -485,18 +482,17 @@
<
div
class
=
"icon"
><
/div
>
<
div
class
=
"title"
>
{{
"党派"
}}
<
/div
>
<
/div
>
<
div
class
=
"select-main
select-main1
"
>
<
div
class
=
"checkbox-group
"
>
<
div
class
=
"select-main"
>
<
el
-
checkbox
-
group
class
=
"checkbox-group"
v
-
model
=
"activeDpList
"
>
<
el
-
checkbox
v
-
for
=
"
dp
in dpList"
v
-
for
=
"
(dp, index)
in dpList"
:
key
=
"dp.id"
v
-
model
=
"activeDpList"
:
label
=
"dp.id"
class
=
"filter-checkbox"
>
{{
dp
.
name
}}
<
/el-checkbox
>
<
/
div
>
<
/
el-checkbox-group
>
<
/div
>
<
/div
>
<
div
class
=
"select-box"
>
...
...
@@ -505,17 +501,16 @@
<
div
class
=
"title"
>
{{
"议院"
}}
<
/div
>
<
/div
>
<
div
class
=
"select-main"
>
<
div
class
=
"checkbox-group
"
>
<
el
-
checkbox
-
group
class
=
"checkbox-group"
v
-
model
=
"activeYyList
"
>
<
el
-
checkbox
v
-
for
=
"
yy
in yyList"
v
-
for
=
"
(yy, index)
in yyList"
:
key
=
"yy.id"
v
-
model
=
"activeYyList"
:
label
=
"yy.id"
class
=
"filter-checkbox"
>
{{
yy
.
name
}}
<
/el-checkbox
>
<
/
div
>
<
/
el-checkbox-group
>
<
/div
>
<
/div
>
...
...
@@ -525,17 +520,16 @@
<
div
class
=
"title"
>
{{
"发布时间"
}}
<
/div
>
<
/div
>
<
div
class
=
"select-main"
>
<
div
class
=
"checkbox-group
"
>
<
el
-
checkbox
-
group
class
=
"checkbox-group"
v
-
model
=
"activePubTime
"
>
<
el
-
checkbox
v
-
for
=
"
time
in pubTime"
v
-
for
=
"
(time, index)
in pubTime"
:
key
=
"time.id"
v
-
model
=
"activePubTime"
:
label
=
"time.id"
class
=
"filter-checkbox"
>
{{
time
.
name
}}
<
/el-checkbox
>
<
/
div
>
<
/
el-checkbox-group
>
<
/div
>
<
/div
>
<
/div
>
...
...
@@ -561,6 +555,16 @@
/>
<
/el-select
>
<
/div
>
<
div
class
=
"right-header-box"
style
=
"margin-left: auto;"
>
<
el
-
select
v
-
model
=
"releaseTime"
placeholder
=
"选择发布时间"
style
=
"width: 120px"
>
<
el
-
option
v
-
for
=
"item in releaseTimeList"
:
key
=
"item.value"
:
label
=
"item.label"
:
value
=
"item.value"
/>
<
/el-select
>
<
/div
>
<
/div
>
<
div
class
=
"right-main"
>
<
div
class
=
"right-main-box"
v
-
for
=
"(item, index) in footerBillList"
:
key
=
"index"
>
...
...
@@ -620,7 +624,7 @@
<
/template
>
<
script
setup
>
import
{
onMounted
,
ref
,
computed
,
onUnmounted
,
nextTick
}
from
"vue"
;
import
{
onMounted
,
ref
,
computed
,
onUnmounted
,
nextTick
,
watch
}
from
"vue"
;
import
router
from
"@/router/index"
;
import
setChart
from
"@/utils/setChart"
;
...
...
@@ -631,7 +635,9 @@ import {
getBillsByType
,
getHylyList
,
getBillOverviewKeyTK
,
getBillCount
getBillCount
,
getBillPostOrg
,
getMemberProposal
}
from
"@/api/bill/billHome"
;
import
DivideHeader
from
"@/components/DivideHeader.vue"
;
...
...
@@ -1138,6 +1144,7 @@ const handleGetBillsByType = async () => {
}
;
// 涉华法案数量
const
box5Select
=
ref
(
"全部领域"
);
const
box5Data
=
ref
({
title
:
[
"2024-09"
,
...
...
@@ -1166,11 +1173,31 @@ const box5Data = ref({
}
);
const
handleGetBillCount
=
async
()
=>
{
try
{
const
res
=
await
getBillCount
();
let
params
=
{
}
;
if
(
box5Select
.
value
!==
"全部领域"
)
{
params
.
industryId
=
box5Select
.
value
;
}
const
res
=
await
getBillCount
(
params
);
console
.
log
(
"涉华法案统计"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
const
sortedData
=
res
.
data
.
sort
((
a
,
b
)
=>
a
.
month
.
localeCompare
(
b
.
month
));
box5Data
.
value
=
{
title
:
sortedData
.
map
(
item
=>
item
.
month
),
data
:
[
{
name
:
"提出法案"
,
value
:
sortedData
.
map
(
item
=>
item
.
totalCount
)
}
,
{
name
:
"通过法案"
,
value
:
sortedData
.
map
(
item
=>
item
.
passCount
)
}
],
percent
:
sortedData
.
map
(
item
=>
item
.
percent
)
}
;
}
else
{
box5Data
.
value
=
{
}
;
// 保持默认数据或清空
// box5Data.value =
{
}
;
}
}
catch
(
error
)
{
console
.
error
(
"获取涉华法案统计error"
,
error
);
...
...
@@ -1179,10 +1206,60 @@ const handleGetBillCount = async () => {
const
handleBox5
=
async
()
=>
{
await
handleGetBillCount
();
let
box5Chart
=
getMultiLineChart
(
box5Data
.
value
.
title
,
box5Data
.
value
.
data
[
0
].
value
,
box5Data
.
value
.
data
[
1
].
value
);
const
proposed
=
box5Data
.
value
.
data
[
0
].
value
;
const
passed
=
box5Data
.
value
.
data
[
1
].
value
;
const
rate
=
box5Data
.
value
.
percent
||
proposed
.
map
((
p
,
i
)
=>
{
const
pass
=
passed
[
i
]
||
0
;
return
p
?
((
pass
/
p
)
*
100
).
toFixed
(
2
)
:
0
;
}
);
let
box5Chart
=
getMultiLineChart
(
box5Data
.
value
.
title
,
proposed
,
passed
,
rate
);
setChart
(
box5Chart
,
"box5Chart"
);
}
;
const
handleBox5Change
=
()
=>
{
handleBox5
();
}
;
// 法案提出部门
const
handleBox7Data
=
async
()
=>
{
try
{
const
res
=
await
getBillPostOrg
({
year
:
box7selectetedTime
.
value
}
);
console
.
log
(
"法案提出部门"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
const
apiData
=
res
.
data
;
const
houseItems
=
apiData
.
filter
(
i
=>
i
.
congressName
===
"House"
);
const
senateItems
=
apiData
.
filter
(
i
=>
i
.
congressName
===
"Senate"
);
const
houseTotal
=
houseItems
.
reduce
((
sum
,
i
)
=>
sum
+
i
.
countBill
,
0
);
const
senateTotal
=
senateItems
.
reduce
((
sum
,
i
)
=>
sum
+
i
.
countBill
,
0
);
const
data1
=
[];
if
(
houseItems
.
length
>
0
)
{
data1
.
push
({
name
:
"众议院"
,
value
:
houseTotal
}
);
}
if
(
senateItems
.
length
>
0
)
{
data1
.
push
({
name
:
"参议院"
,
value
:
senateTotal
}
);
}
const
data2
=
[...
houseItems
,
...
senateItems
].
map
(
item
=>
({
name
:
item
.
originDepart
,
value
:
item
.
countBill
,
type
:
item
.
congressName
===
"House"
?
"众议院"
:
"参议院"
}
));
const
box7Chart
=
getDoublePieChart
(
data1
,
data2
);
setChart
(
box7Chart
,
"box7Chart"
);
}
}
catch
(
error
)
{
console
.
error
(
"获取法案提出部门数据失败"
,
error
);
}
}
;
watch
(
box7selectetedTime
,
()
=>
{
handleBox7Data
();
}
);
// 关键条款
const
wordCloudData
=
ref
([
{
name
:
"限制中国获取能源技术"
,
value
:
100
}
,
...
...
@@ -1379,48 +1456,30 @@ const box7Data = ref([
]
]);
const
box8Data
=
ref
([
{
name
:
"汤姆·科顿"
,
zhiwei
:
"参议院情报委员会主席"
,
img
:
Message3
,
dangpai
:
Cyy
,
yuan
:
Ghd
,
num
:
8
}
,
{
name
:
"吉姆·里施"
,
zhiwei
:
"参议院外交关系委员会主席"
,
img
:
Message3
,
dangpai
:
Cyy
,
yuan
:
Ghd
,
num
:
4
}
,
{
name
:
"特德·克鲁兹"
,
zhiwei
:
"参议院商务、科学和交通委员会主席"
,
img
:
Message3
,
dangpai
:
Cyy
,
yuan
:
Ghd
,
num
:
2
}
,
{
name
:
"里克·克劳福德"
,
zhiwei
:
"众议院美中战略竞争特设委员会主席"
,
img
:
Message3
,
dangpai
:
Cyy
,
yuan
:
Ghd
,
num
:
2
}
,
{
name
:
"布莱恩·马斯特"
,
zhiwei
:
"众议院情报委员会主席"
,
img
:
Message3
,
dangpai
:
Cyy
,
yuan
:
Ghd
,
num
:
2
const
box8Data
=
ref
([]);
const
handleBox8Data
=
async
()
=>
{
try
{
const
res
=
await
getMemberProposal
({
year
:
box8selectetedTime
.
value
}
);
console
.
log
(
"关键议员提案"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
box8Data
.
value
=
res
.
data
.
map
(
item
=>
({
name
:
item
.
memberName
,
zhiwei
:
item
.
position
,
img
:
item
.
imageUrl
,
num
:
item
.
countProposal
,
dangpai
:
Cyy
,
yuan
:
item
.
position
===
"Democratic"
?
Mzd
:
Ghd
}
));
}
}
catch
(
error
)
{
console
.
error
(
"获取关键议员提案失败"
,
error
);
}
]);
}
;
watch
(
box8selectetedTime
,
()
=>
{
handleBox8Data
();
}
);
const
handleToPosi
=
id
=>
{
// 0 618 1240 2350
...
...
@@ -1464,26 +1523,36 @@ const handleClickTab = tab => {
}
;
const
areaList
=
[
{
id
:
"全部领域"
,
name
:
"全部领域"
}
,
{
id
:
"人工智能"
,
name
:
"人工智能"
}
,
{
id
:
"集成电路"
,
name
:
"集成电路"
}
,
{
id
:
"通信网络"
,
name
:
"通信网络"
}
,
{
id
:
"量子科技"
,
name
:
"量子科技"
}
{
id
:
"先进制造"
,
name
:
"先进制造"
}
,
{
id
:
"量子科技"
,
name
:
"量子科技"
}
,
{
id
:
"生物科技"
,
name
:
"生物科技"
}
,
{
id
:
"能源"
,
name
:
"能源"
}
,
{
id
:
"航空航天"
,
name
:
"航空航天"
}
,
{
id
:
"新材料"
,
name
:
"新材料"
}
,
{
id
:
"海洋"
,
name
:
"海洋"
}
];
const
activeAreaList
=
[
"人工智能"
]
;
const
activeAreaList
=
ref
([
"全部领域"
])
;
const
dpList
=
ref
([
{
id
:
"全部党派"
,
name
:
"全部党派"
}
,
{
id
:
"民主党"
,
name
:
"民主党"
}
,
{
id
:
"共和党"
,
name
:
"共和党"
}
]);
const
activeDpList
=
[
"民主党"
]
;
const
activeDpList
=
ref
([
"全部党派"
])
;
const
yyList
=
ref
([
{
id
:
"全部议院"
,
name
:
"全部议院"
}
,
{
id
:
"参议院"
,
name
:
"参议院"
}
,
{
id
:
"众议院"
,
name
:
"众议院"
}
]);
const
activeYyList
=
[
"参议院"
]
;
const
activeYyList
=
ref
([
"全部议院"
])
;
const
pubTime
=
ref
([
{
id
:
"全部时间"
,
name
:
"全部时间"
}
,
{
id
:
"2025年"
,
name
:
"2025年"
}
,
{
id
:
"2024年"
,
name
:
"2024年"
}
,
{
id
:
"2023年"
,
name
:
"2023年"
}
,
...
...
@@ -1491,7 +1560,7 @@ const pubTime = ref([
{
id
:
"2021年"
,
name
:
"2021年"
}
,
{
id
:
"更早时间"
,
name
:
"更早时间"
}
]);
const
activePubTime
=
ref
([
"
2025年
"
]);
const
activePubTime
=
ref
([
"
全部时间
"
]);
const
footerSelectList1
=
ref
([
{
...
...
@@ -1549,8 +1618,9 @@ onMounted(async () => {
handleBox5
();
//涉华法案统计
handleBox6
();
// 关键条款
const
box7Chart
=
getDoublePieChart
(
box7Data
.
value
[
0
],
box7Data
.
value
[
1
]);
setChart
(
box7Chart
,
"box7Chart"
);
handleBox7Data
();
handleBox8Data
();
await
handleGetHotBills
();
curBill
.
value
=
hotBillList
.
value
[
0
];
...
...
@@ -1929,15 +1999,14 @@ onUnmounted(() => {});
padding
-
left
:
31
px
;
.
box1
-
main
-
left
{
margin
-
left
:
39
px
;
// flex: 1;
width
:
484
px
;
.
box1
-
main
-
left
-
title
{
height
:
22
px
;
color
:
rgba
(
20
,
89
,
187
,
1
);
font
-
family
:
Microsoft
YaHei
;
font
-
family
:
"Microsoft YaHei"
;
font
-
size
:
20
px
;
font
-
weight
:
700
;
line
-
height
:
22
px
;
margin
-
bottom
:
14
px
;
}
.
box1
-
main
-
left
-
info
{
margin
-
top
:
17
px
;
...
...
@@ -2549,6 +2618,7 @@ onUnmounted(() => {});
border
-
radius
:
10
px
;
box
-
shadow
:
0
px
0
px
15
px
0
px
rgba
(
22
,
119
,
255
,
0.1
);
background
:
rgba
(
255
,
255
,
255
,
1
);
position
:
relative
;
.
box5
-
header
{
height
:
53
px
;
border
-
bottom
:
1
px
solid
rgba
(
240
,
242
,
244
,
1
);
...
...
@@ -2605,6 +2675,12 @@ onUnmounted(() => {});
.
box5
-
main
{
height
:
397
px
;
}
.
box5
-
select
{
position
:
absolute
;
top
:
50
px
;
left
:
100
px
;
z
-
index
:
100
;
}
}
.
box6
{
margin
-
left
:
20
px
;
...
...
@@ -2615,7 +2691,7 @@ onUnmounted(() => {});
background
:
rgba
(
255
,
255
,
255
,
1
);
.
box6
-
header
{
width
:
521
px
;
height
:
48
px
;
height
:
53
px
;
border
-
bottom
:
1
px
solid
rgba
(
240
,
242
,
244
,
1
);
display
:
flex
;
box
-
sizing
:
border
-
box
;
...
...
@@ -2665,8 +2741,8 @@ onUnmounted(() => {});
}
}
.
box6
-
main
{
width
:
452
px
;
height
:
402
px
;
width
:
100
%
;
height
:
calc
(
100
%
-
53
px
)
;
}
}
}
...
...
@@ -2816,6 +2892,8 @@ onUnmounted(() => {});
}
.
box8
-
main
{
height
:
340
px
;
overflow
-
y
:
auto
;
overflow
-
x
:
hidden
;
.
box8
-
main
-
item
{
margin
:
0
auto
;
width
:
478
px
;
...
...
@@ -2833,9 +2911,10 @@ onUnmounted(() => {});
position
:
relative
;
width
:
42
px
;
height
:
42
px
;
img
{
width
:
100
%
;
height
:
100
%
;
.
left
-
img
{
width
:
42
px
;
height
:
42
px
;
border
-
radius
:
50
%
;
}
.
left
-
icon1
{
position
:
absolute
;
...
...
@@ -2892,11 +2971,10 @@ onUnmounted(() => {});
position
:
absolute
;
top
:
0
;
right
:
10
px
;
width
:
92
px
;
height
:
51
px
;
text
-
align
:
right
;
color
:
rgba
(
95
,
101
,
108
,
1
);
font
-
family
:
Microsoft
YaHei
;
font
-
family
:
"Microsoft YaHei"
;
font
-
size
:
16
px
;
font
-
weight
:
400
;
line
-
height
:
51
px
;
...
...
@@ -3051,7 +3129,7 @@ onUnmounted(() => {});
box
-
shadow
:
0
px
0
px
20
px
0
px
rgba
(
25
,
69
,
130
,
0.1
);
background
:
rgba
(
255
,
255
,
255
,
1
);
.
select
-
box
{
margin
-
top
:
2
1
px
;
margin
-
top
:
2
0
px
;
.
select
-
box
-
header
{
display
:
flex
;
gap
:
17
px
;
...
...
@@ -3063,18 +3141,35 @@ onUnmounted(() => {});
border
-
radius
:
0
4
px
4
px
0
;
}
.
title
{
height
:
24
px
;
//
height: 24px;
color
:
var
(
--
color
-
main
-
active
);
font
-
family
:
Microsoft
YaHei
;
font
-
size
:
16
px
;
font
-
size
:
20
px
;
font
-
weight
:
700
;
line
-
height
:
2
4
px
;
line
-
height
:
2
6
px
;
letter
-
spacing
:
1
px
;
text
-
align
:
left
;
}
}
.
select
-
main
{
margin
-
left
:
25
px
;
margin
-
top
:
16
px
;
.
checkbox
-
group
{
display
:
flex
;
flex
-
wrap
:
wrap
;
.
filter
-
checkbox
{
width
:
50
%
;
margin
-
right
:
0
;
margin
-
bottom
:
4
px
;
:
deep
(.
el
-
checkbox__label
)
{
color
:
rgb
(
95
,
101
,
108
);
font
-
size
:
16
px
;
font
-
weight
:
400
;
font
-
family
:
"Microsoft YaHei"
;
line
-
height
:
24
px
;
}
}
}
}
.
select
-
main1
{
width
:
100
px
;
...
...
src/views/bill/billHome/utils/multiLineChart.js
浏览文件 @
273f345b
import
*
as
echarts
from
'echarts'
const
getMultiLineChart
=
(
dataX
,
dataY1
,
dataY2
)
=>
{
const
getMultiLineChart
=
(
dataX
,
dataY1
,
dataY2
,
dataY3
)
=>
{
return
{
tooltip
:
{
trigger
:
'axis'
,
...
...
@@ -9,25 +9,34 @@ const getMultiLineChart = (dataX, dataY1, dataY2) => {
label
:
{
backgroundColor
:
'#6a7985'
}
},
formatter
:
function
(
params
)
{
let
res
=
params
[
0
].
name
+
'<br/>'
;
params
.
forEach
(
item
=>
{
res
+=
item
.
marker
+
item
.
seriesName
+
': '
+
item
.
value
+
(
item
.
seriesName
===
'通过率'
?
'%'
:
''
)
+
'<br/>'
;
});
return
res
;
}
},
grid
:
{
top
:
'
8
%'
,
top
:
'
15
%'
,
right
:
'5%'
,
bottom
:
'5%'
,
left
:
'5%'
,
containLabel
:
true
},
legend
:
{
data
:
[
'提出法案'
,
'通过法案'
],
data
:
[
'提出法案'
,
'通过法案'
,
'通过率'
],
show
:
true
,
top
:
0
,
icon
:
'circle'
,
textStyle
:
{
color
:
'rgba(95, 101, 108, 1)'
,
fontFamily
:
'Microsoft YaHei'
,
fontSize
:
'1
6
px'
,
fontSize
:
'1
4
px'
,
}
},
color
:
[
'#1
459bb'
,
'#fa8c16
'
],
color
:
[
'#1
677FF'
,
'#FA8C16'
,
'#D9001B
'
],
xAxis
:
[
{
type
:
'category'
,
...
...
@@ -37,47 +46,83 @@ const getMultiLineChart = (dataX, dataY1, dataY2) => {
],
yAxis
:
[
{
type
:
'value'
type
:
'value'
,
position
:
'left'
,
axisLabel
:
{
color
:
'#666'
}
},
{
type
:
'value'
,
position
:
'right'
,
min
:
0
,
max
:
100
,
interval
:
20
,
axisLabel
:
{
formatter
:
'{value}%'
,
color
:
'#666'
},
splitLine
:
{
show
:
false
}
}
],
series
:
[
{
name
:
'提出法案'
,
type
:
'line'
,
symbol
:
'emptyCircle'
,
symbolSize
:
6
,
areaStyle
:
{
color
:
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
0
,
1
,
[{
offset
:
0
,
color
:
'rgba(22, 119, 255,
1
)'
// 起始颜色
color
:
'rgba(22, 119, 255,
0.4
)'
// 起始颜色
},
{
offset
:
1
,
color
:
'rgba(22, 119, 255, 0)'
// 结束颜色
}])
},
emphasis
:
{
focus
:
'series
'
itemStyle
:
{
color
:
'#1677FF
'
},
data
:
dataY1
},
{
name
:
'通过法案'
,
type
:
'line'
,
symbol
:
'emptyCircle'
,
symbolSize
:
6
,
areaStyle
:
{
color
:
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
0
,
1
,
[{
offset
:
0
,
color
:
'rgba(25
5, 172, 77, 1
)'
// 起始颜色
color
:
'rgba(25
0, 140, 22, 0.4
)'
// 起始颜色
},
{
offset
:
1
,
color
:
'rgba(25
5, 172, 77
, 0)'
// 结束颜色
color
:
'rgba(25
0, 140, 22
, 0)'
// 结束颜色
}])
},
emphasis
:
{
focus
:
'series
'
itemStyle
:
{
color
:
'#FA8C16
'
},
data
:
dataY2
},
{
name
:
'通过率'
,
type
:
'line'
,
yAxisIndex
:
1
,
symbol
:
'emptyCircle'
,
symbolSize
:
4
,
lineStyle
:
{
type
:
'dashed'
,
width
:
2
},
itemStyle
:
{
color
:
'#D9001B'
},
data
:
dataY3
}
]
}
}
export
default
getMultiLineChart
\ No newline at end of file
export
default
getMultiLineChart
src/views/bill/billHome/utils/worldCloudChart.js
浏览文件 @
273f345b
...
...
@@ -11,6 +11,8 @@ const getWordCloudChart = (data) => {
series
:
[
{
type
:
"wordCloud"
,
width
:
'80%'
,
height
:
'80%'
,
shape
:
"rect"
,
//
// 其他形状你可以使用形状路径
// 或者自定义路径
...
...
src/views/bill/deepDig/processAnalysis/index.vue
浏览文件 @
273f345b
...
...
@@ -35,7 +35,7 @@
<div
class=
"box2"
>
<div
class=
"box-header"
>
<div
class=
"header-left"
></div>
<div
class=
"title"
>
辩论投票时长
</div>
<div
class=
"title"
>
修正案次数分析
</div>
<div
class=
"header-right"
>
<div
class=
"icon"
>
<img
src=
"@/assets/icons/box-header-icon1.png"
alt=
""
/>
...
...
@@ -320,7 +320,7 @@
<
script
setup
>
import
{
ref
,
onMounted
}
from
"vue"
;
import
{
getBillTimeAnalyze
,
getBill
Xj
,
getBillTotalXj
,
getBillTp
}
from
"@/api/deepdig"
;
import
{
getBillTimeAnalyze
,
getBill
AmeAnalyzeCount
,
getBillTp
}
from
"@/api/deepdig"
;
import
getBoxPlotChcart
from
"./utils/boxplot"
;
import
*
as
echarts
from
"echarts"
;
...
...
@@ -563,20 +563,69 @@ const handleGetBillTimeAnalyze = async () => {
return
item
.
lcmc
;
}
);
chartData1
.
value
.
dataY
=
res
.
data
.
map
(
item
=>
{
return
[
item
.
z
dhs
,
item
.
zshs
,
item
.
pjs
,
item
.
pjx
,
item
.
zw
s
,
item
.
dysc
];
return
[
item
.
z
shs
,
item
.
pjx
,
item
.
zws
,
item
.
pjs
,
item
.
zdh
s
,
item
.
dysc
];
}
);
}
catch
(
error
)
{
}
}
;
// 辩论投票时长
// 修正案次数分析
const
handleGetBillAmeAnalyzeCount
=
async
()
=>
{
const
params
=
{
id
:
window
.
sessionStorage
.
getItem
(
"billId"
)
}
;
try
{
const
res
=
await
getBillAmeAnalyzeCount
(
params
);
console
.
log
(
"修正案次数分析"
,
res
);
chartData2
.
value
.
dataX
=
res
.
data
.
map
(
item
=>
{
return
item
.
lcmc
;
}
);
chartData2
.
value
.
dataY
=
res
.
data
.
map
(
item
=>
{
// 兼容多种字段名,防止字段不存在导致图表消失
// 顺序:最小(min), Q1(小), 中位数(median), Q3(大), 最大(max), 该法案(current)
return
[
item
.
zsCount
||
item
.
zscs
||
item
.
zshs
||
0
,
item
.
jsx
||
item
.
pjx
||
0
,
item
.
zws
||
item
.
zwcs
||
0
,
item
.
pjs
||
item
.
pjcs
||
0
,
item
.
zdCount
||
item
.
zdcs
||
item
.
zdhs
||
0
,
item
.
dysc
||
item
.
dycs
||
0
];
}
);
}
catch
(
error
)
{
console
.
error
(
"修正案次数分析 error"
,
error
);
}
}
;
// 获取投票分析
const
handleGetBillVoteAnalyze
=
async
()
=>
{
const
params
=
{
id
:
window
.
sessionStorage
.
getItem
(
"billId"
)
}
;
try
{
const
res
=
await
getBillTp
(
params
);
console
.
log
(
"投票分析"
,
res
);
}
catch
(
error
)
{
console
.
error
(
"投票分析 error"
,
error
);
}
}
;
onMounted
(
async
()
=>
{
await
handleGetBillTimeAnalyze
();
await
handleGetBillAmeAnalyzeCount
();
await
handleGetBillVoteAnalyze
();
let
chart1
=
getBoxPlotChcart
(
chartData1
.
value
,
"天"
);
setChart
(
chart1
,
"chart1"
);
let
chart2
=
getBoxPlotChcart
(
chartData2
.
value
,
"小时"
);
const
countLabels
=
{
max
:
'最大次数'
,
q3
:
'平均次数大'
,
median
:
'次数中位数'
,
q1
:
'平均次数小'
,
min
:
'最小次数'
,
current
:
'该法案修正案数量'
}
;
let
chart2
=
getBoxPlotChcart
(
chartData2
.
value
,
"次"
,
countLabels
);
setChart
(
chart2
,
"chart2"
);
}
);
<
/script
>
...
...
src/views/bill/deepDig/processAnalysis/utils/boxplot.js
浏览文件 @
273f345b
const
getBoxPlotChcart
=
(
data
,
unit
)
=>
{
const
getBoxPlotChcart
=
(
data
,
unit
,
labelConfig
=
{})
=>
{
const
labels
=
{
max
:
labelConfig
.
max
||
'最大耗时'
,
q3
:
labelConfig
.
q3
||
'平均耗时大'
,
median
:
labelConfig
.
median
||
'耗时中位数'
,
q1
:
labelConfig
.
q1
||
'平均耗时小'
,
min
:
labelConfig
.
min
||
'最小耗时'
,
current
:
labelConfig
.
current
||
'该法案耗时'
};
let
option
=
{
// title: [
// {
...
...
@@ -11,6 +20,22 @@ const getBoxPlotChcart = (data,unit) => {
trigger
:
'item'
,
axisPointer
:
{
type
:
'shadow'
},
formatter
:
function
(
params
)
{
if
(
params
.
seriesType
===
'scatter'
)
{
return
`
${
params
.
name
}
<br/>
${
labels
.
current
}
:
${
params
.
data
[
1
]}
${
unit
}
`
;
}
const
{
name
,
data
}
=
params
;
let
tip
=
`
${
name
}
<br/>`
;
tip
+=
`
${
labels
.
max
}
:
${
data
[
5
]}
${
unit
}
<br/>`
;
tip
+=
`
${
labels
.
q3
}
:
${
data
[
4
]}
${
unit
}
<br/>`
;
tip
+=
`
${
labels
.
median
}
:
${
data
[
3
]}
${
unit
}
<br/>`
;
tip
+=
`
${
labels
.
q1
}
:
${
data
[
2
]}
${
unit
}
<br/>`
;
tip
+=
`
${
labels
.
min
}
:
${
data
[
1
]}
${
unit
}
<br/>`
;
if
(
data
[
6
]
!==
undefined
&&
data
[
6
]
!==
null
)
{
tip
+=
`
${
labels
.
current
}
:
${
data
[
6
]}
${
unit
}
`
;
}
return
tip
;
}
},
grid
:
{
...
...
@@ -48,13 +73,20 @@ const getBoxPlotChcart = (data,unit) => {
{
name
:
'boxplot'
,
type
:
'boxplot'
,
datasetIndex
:
1
,
data
:
data
.
dataY
,
},
{
name
:
'outlier'
,
name
:
labels
.
current
,
type
:
'scatter'
,
datasetIndex
:
2
data
:
data
.
dataY
.
map
((
item
,
index
)
=>
[
index
,
item
[
5
]]),
itemStyle
:
{
color
:
'#ff5722'
},
tooltip
:
{
formatter
:
function
(
params
)
{
return
`
${
params
.
name
}
<br/>
${
labels
.
current
}
:
${
params
.
data
[
1
]}
${
unit
}
`
;
}
}
}
]
}
...
...
src/views/bill/introdoction/STimeline.vue
浏览文件 @
273f345b
<
template
>
<div
class=
"container"
>
<div
class=
"svg-timeline"
>
<svg
:
width=
"svgWidth"
:height=
"svgHeight
"
>
<svg
:
viewBox=
"`0 0 $
{svgWidth} ${svgHeight}`" width="100%" height="100%
">
<!--
<line
:x1=
"lines[0].x1 - 100"
:y1=
"lines[0].y1"
...
...
@@ -31,10 +31,11 @@
stroke-width=
"2"
/>
-->
<line
:x1=
"lines[0].x1 - 100"
:y1=
"lines[0].y1"
:x2=
"lines[0].x1"
:y2=
"lines[0].y1"
v-if=
"nodes.length > 0"
:x1=
"nodes[0].x - 100"
:y1=
"nodes[0].y"
:x2=
"nodes[0].x"
:y2=
"nodes[0].y"
stroke=
"#e8f2ff"
stroke-width=
"2"
marker-end=
"url(#arrow)"
...
...
@@ -68,51 +69,60 @@
v-for=
"(node, idx) in nodes.slice(0, nodes.length)"
:key=
"'line' + idx"
:x1=
"node.x"
:y1=
"node.y +
2
"
:y1=
"node.y +
4
"
:x2=
"node.x"
:y2=
"node.
dyms ? node.y + 80 : node.y + 50
"
:y2=
"node.
y + verticalLineLength
"
stroke=
"#1677ff"
stroke-width=
"2
"
:stroke-width=
"verticalLineWidth
"
/>
<
tex
t
<
foreignObjec
t
v-for=
"(node, idx) in nodes"
:key=
"'actionDate' + idx"
:x=
"node.x + 10"
:y=
"node.y + 30"
text-anchor=
"start"
fill=
"#1677ff"
font-size=
"14"
font-weight=
"600"
:key=
"'fo-' + idx"
:x=
"node.x + 15"
:y=
"node.y + 5"
:width=
"nodeGapX - 30"
height=
"100"
style=
"overflow: visible;"
>
{{
node
.
actionDate
}}
</text>
<div
class=
"node-content"
xmlns=
"http://www.w3.org/1999/xhtml"
>
<div
class=
"date"
>
{{
node
.
formattedDate
}}
</div>
<div
class=
"title"
>
{{
node
.
actionTitle
}}
</div>
<div
class=
"votes"
v-if=
"node.voteString"
>
{{
node
.
voteString
}}
</div>
</div>
</foreignObject>
<text
v-for=
"(node, idx) in nodes"
:key=
"'actionTitle' + idx"
:x=
"node.x + 10"
:y=
"node.y + 50"
text-anchor=
"start"
fill=
"#3b414b"
font-size=
"14"
textLength=
"170"
lengthAdjust=
"spacing"
font-weight=
"bold"
v-if=
"startMonth && nodes.length > 0"
:x=
"nodes[0].x - 110"
:y=
"nodes[0].y + 5"
text-anchor=
"end"
fill=
"rgb(5, 95, 194)"
font-size=
"16"
font-weight=
"700"
>
{{
node
.
actionTitle
.
slice
(
0
,
24
)
}}
{{
startMonth
}}
</text>
<line
v-if=
"nodes.length > 0"
:x1=
"nodes[nodes.length - 1].x"
:y1=
"nodes[nodes.length - 1].y"
:x2=
"nodes[nodes.length - 1].row % 2 === 0 ? nodes[nodes.length - 1].x + 100 : nodes[nodes.length - 1].x - 100"
:y2=
"nodes[nodes.length - 1].y"
stroke=
"#e8f2ff"
stroke-width=
"2"
marker-end=
"url(#arrow)"
/>
<text
v-for=
"(node, idx) in nodes"
:key=
"'actionTitle' + idx"
:x=
"node.x + 10"
:y=
"node.y + 70"
text-anchor=
"start"
fill=
"#84888e"
font-size=
"14"
v-if=
"endMonth && nodes.length > 0"
:x=
"nodes[nodes.length - 1].row % 2 === 0 ? nodes[nodes.length - 1].x + 110 : nodes[nodes.length - 1].x - 110"
:y=
"nodes[nodes.length - 1].y + 5"
:text-anchor=
"nodes[nodes.length - 1].row % 2 === 0 ? 'start' : 'end'"
fill=
"rgb(5, 95, 194)"
font-size=
"16"
font-weight=
"700"
>
{{
node
.
dyms
?
node
.
dyms
:
""
}}
{{
endMonth
}}
</text>
</svg>
</div>
...
...
@@ -134,26 +144,55 @@ export default {
// ],
maxPerRow
:
5
,
nodeGapX
:
200
,
nodeGapY
:
100
nodeGapY
:
180
,
leftMargin
:
150
,
verticalLineLength
:
80
,
verticalLineWidth
:
1
};
},
computed
:
{
startMonth
()
{
if
(
this
.
sortedDataList
.
length
===
0
)
return
''
;
const
date
=
new
Date
(
this
.
sortedDataList
[
0
].
actionDate
);
return
`
${
date
.
getFullYear
()}
年
${
date
.
getMonth
()
+
1
}
月`
;
},
endMonth
()
{
if
(
this
.
sortedDataList
.
length
===
0
)
return
''
;
const
date
=
new
Date
(
this
.
sortedDataList
[
this
.
sortedDataList
.
length
-
1
].
actionDate
);
return
`
${
date
.
getFullYear
()}
年
${
date
.
getMonth
()
+
1
}
月`
;
},
sortedDataList
()
{
if
(
!
this
.
dataList
)
return
[];
// Clone and sort by date ascending (Old -> New)
return
[...
this
.
dataList
].
sort
((
a
,
b
)
=>
new
Date
(
a
.
actionDate
)
-
new
Date
(
b
.
actionDate
));
},
nodes
()
{
// 计算每个节点的坐标(蛇形)
return
this
.
d
ataList
.
map
((
item
,
idx
)
=>
{
return
this
.
sortedD
ataList
.
map
((
item
,
idx
)
=>
{
const
row
=
Math
.
floor
(
idx
/
this
.
maxPerRow
);
const
col
=
idx
%
this
.
maxPerRow
;
let
x
,
y
;
const
leftMargin
=
1
0
;
// 你可以自定义这个值
// const leftMargin = 15
0; // 你可以自定义这个值
if
(
row
%
2
===
0
)
{
x
=
leftMargin
+
col
*
this
.
nodeGapX
+
50
;
x
=
this
.
leftMargin
+
col
*
this
.
nodeGapX
+
50
;
}
else
{
x
=
leftMargin
+
(
this
.
maxPerRow
-
1
-
col
)
*
this
.
nodeGapX
+
50
;
x
=
this
.
leftMargin
+
(
this
.
maxPerRow
-
1
-
col
)
*
this
.
nodeGapX
+
50
;
}
// 节点纵坐标起始值
y
=
60
+
row
*
this
.
nodeGapY
;
return
{
...
item
,
x
,
y
,
row
};
// Format Date: 2025-07-04 -> 7月4日
const
dateObj
=
new
Date
(
item
.
actionDate
);
const
formattedDate
=
`
${
dateObj
.
getMonth
()
+
1
}
月
${
dateObj
.
getDate
()}
日`
;
// Format Votes
let
voteString
=
''
;
if
(
item
.
agreeVote
!==
null
&&
item
.
disagreeVote
!==
null
)
{
voteString
=
`
${
item
.
agreeVote
}
票赞成 :
${
item
.
disagreeVote
}
票反对`
;
}
return
{
...
item
,
x
,
y
,
row
,
formattedDate
,
voteString
};
});
},
lines
()
{
...
...
@@ -194,7 +233,7 @@ export default {
console
.
log
(
"prev"
,
prev
);
// 判断是否是行尾转折点
const
isTurnPoint
=
i
%
5
===
0
;
const
isTurnPoint
=
i
%
this
.
maxPerRow
===
0
;
if
(
isTurnPoint
)
{
// 计算半圆路径
...
...
@@ -221,7 +260,7 @@ export default {
return
path
;
},
svgWidth
()
{
return
this
.
maxPerRow
*
this
.
nodeGapX
+
10
0
;
return
this
.
leftMargin
+
this
.
maxPerRow
*
this
.
nodeGapX
+
5
0
;
},
svgHeight
()
{
// SVG高度
...
...
@@ -240,7 +279,7 @@ export default {
align-items
:
center
;
}
.svg-timeline
{
width
:
100
0px
;
width
:
100
%
;
// background-size: 100% 100%;
// position: relative;
// .title {
...
...
@@ -264,5 +303,40 @@ export default {
// height: 24px;
// }
// }
.node-content
{
font-family
:
Microsoft
YaHei
,
sans-serif
;
text-align
:
left
;
padding-left
:
4px
;
.date
{
color
:
rgb
(
5
,
95
,
194
);
font-weight
:
700
;
font-size
:
14px
;
line-height
:
22px
;
margin-bottom
:
0px
;
margin-top
:
6px
;
}
.title
{
color
:
rgb
(
59
,
65
,
75
);
font-weight
:
700
;
font-size
:
14px
;
line-height
:
22px
;
margin-bottom
:
0px
;
white-space
:
nowrap
;
/* Keep text on one line */
overflow
:
hidden
;
/* Hide overflow */
text-overflow
:
ellipsis
;
/* Show ... for overflow */
width
:
100%
;
/* Ensure it takes full width of container */
display
:
block
;
/* Block level for ellipsis to work */
}
.votes
{
color
:
rgb
(
95
,
101
,
108
);
font-size
:
14px
;
font-weight
:
400
;
line-height
:
22px
;
}
}
}
</
style
>
src/views/bill/introdoction/index.vue
浏览文件 @
273f345b
...
...
@@ -31,9 +31,10 @@
<div
class=
"box1-right-item"
>
<div
class=
"item-left"
>
相关领域:
</div>
<div
class=
"item-right1"
>
<div
class=
"right1-item"
>
跨境电商
</div>
<
!--
<
div
class=
"right1-item"
>
跨境电商
</div>
<div
class=
"right1-item"
>
新能源产业
</div>
<div
class=
"right1-item"
>
半导体产业
</div>
<div
class=
"right1-item"
>
半导体产业
</div>
-->
<div
class=
"right1-item"
v-for=
"item in basicInfo.hylyList"
:key=
"item"
>
{{
item
}}
</div>
</div>
</div>
<div
class=
"box1-right-item"
>
...
...
@@ -81,7 +82,7 @@
<
div
class
=
"box-header"
>
<
div
class
=
"header-left"
><
/div
>
<
div
class
=
"title"
>
法案进展
<
/div
>
<
div
class
=
"header-btn-box"
>
<
!--
<
div
class
=
"header-btn-box"
>
<
div
class
=
"btn"
@
click
=
"handleClcikBox2Btn(1)"
>
<
el
-
badge
:
value
=
"warningNum"
>
<
el
-
button
type
=
"primary"
plain
v
-
if
=
"box2BtnActive === 1"
>
最新进展
<
/el-button
>
...
...
@@ -92,7 +93,7 @@
<
el
-
button
type
=
"primary"
plain
v
-
if
=
"box2BtnActive === 2"
>
前期进展
<
/el-button
>
<
el
-
button
type
=
"info"
plain
v
-
else
>
前期进展
<
/el-button
>
<
/div
>
<
/div
>
<
/div>
--
>
<
div
class
=
"header-right"
>
<
div
class
=
"icon"
>
<
img
src
=
"@/assets/icons/box-header-icon2.png"
alt
=
""
/>
...
...
@@ -104,8 +105,8 @@
<
/div
>
<
div
class
=
"box2-main"
>
<
div
class
=
"box2-main-center"
>
<
STimeline
v
-
if
=
"box2BtnActive == 2"
:
dataList
=
"timelineData"
/>
<
div
class
=
"box2-center-item-box"
v
-
if
=
"box2BtnActive == 1"
>
<
STimeline
:
dataList
=
"timelineData"
/>
<
!--
<
div
class
=
"box2-center-item-box"
v
-
if
=
"box2BtnActive == 1"
>
<
div
class
=
"box2-center-item"
v
-
for
=
"(item, index) in progressList"
:
key
=
"index"
>
<
div
class
=
"tip"
:
class
=
"{ tipActive: item.fxdj
}
"
><
/div
>
<
div
class
=
"date"
>
{{
item
.
actionDate
}}
<
/div
>
...
...
@@ -128,7 +129,7 @@
<
el
-
icon
size
=
"22"
color
=
"#777"
><
ArrowRightBold
/><
/el-icon
>
<
/div
>
<
/div
>
<
/div
>
<
/div>
--
>
<
/div
>
<
/div
>
<
div
class
=
"box2-footer"
>
...
...
@@ -210,15 +211,15 @@
<
div
class
=
"tag-box"
:
class
=
"{
status0:
tag.status === 0
,
status1:
tag.status === 1
,
status2:
tag.status === 2
,
status3:
tag.status === 3
status0:
index === 0 || index === 4
,
status1:
index === 1 || index === 5
,
status2:
index === 2 || index === 6
,
status3:
index === 3 || index === 7
}
"
v
-
for
=
"(tag, index) in tagList"
v
-
for
=
"(tag, index) in
curPerson.
tagList"
:
key
=
"index"
>
{{
tag
.
title
}}
{{
tag
}}
<
/div
>
<
/div
>
<
div
class
=
"right-main-box3"
>
...
...
@@ -231,13 +232,13 @@
<
div
class
=
"right-main-box3-main"
>
<
el
-
timeline
style
=
"max-width: 500px"
>
<
el
-
timeline
-
item
:
timestamp
=
"item.
sjsj
"
:
timestamp
=
"item.
newsDate
"
placement
=
"top"
v
-
for
=
"(item, index) in
personEvent
List"
v
-
for
=
"(item, index) in
curPerson.news
List"
:
key
=
"index"
>
<
div
class
=
"timeline-content"
>
{{
item
.
sjnr
}}
{{
item
.
newsContent
}}
<
/div
>
<
/el-timeline-item
>
<!--
<
el
-
timeline
-
item
timestamp
=
"2018/4/3"
placement
=
"top"
>
...
...
@@ -324,14 +325,14 @@
<
div
class
=
"inner-right-main"
>
<
el
-
timeline
style
=
"max-width: 840px"
>
<
el
-
timeline
-
item
:
timestamp
=
"item.
sjsj
"
:
timestamp
=
"item.
newsDate
"
placement
=
"top"
v
-
for
=
"(item, index) in
personEvent
List"
v
-
for
=
"(item, index) in
curPerson.news
List"
:
key
=
"index"
>
<
div
class
=
"timeline-content1"
>
<
div
class
=
"text"
>
{{
item
.
sjnr
}}
{{
item
.
newsContent
}}
<
/div
>
<
div
class
=
"pic"
>
<
img
src
=
"./assets/imgs/img1.png"
alt
=
""
/>
...
...
@@ -544,6 +545,7 @@ const handleGetBasicInfo = async () => {
const
res
=
await
getBillInfo
(
params
);
console
.
log
(
"基本信息"
,
res
);
basicInfo
.
value
=
res
.
data
basicInfo
.
value
.
stageList
.
reverse
()
}
catch
(
error
)
{
console
.
error
(
error
);
}
...
...
@@ -552,24 +554,24 @@ const handleGetBasicInfo = async () => {
const
warningNum
=
ref
(
0
);
// 法案进展 获取最新进展
const
handleGetBillEvent
=
async
()
=>
{
warningNum
.
value
=
0
;
const
params
=
{
id
:
window
.
sessionStorage
.
getItem
(
"billId"
)
}
;
try
{
const
res
=
await
getBillEvent
(
params
);
console
.
log
(
"最新进展"
,
res
);
progressList
.
value
=
res
.
data
;
progressList
.
value
.
forEach
(
item
=>
{
if
(
item
.
fxdj
)
{
warningNum
.
value
++
;
}
}
);
}
catch
(
error
)
{
console
.
error
(
error
);
}
}
;
//
const handleGetBillEvent = async () =>
{
//
warningNum.value = 0;
//
const params =
{
//
id: window.sessionStorage.getItem("billId")
//
}
;
//
try
{
//
const res = await getBillEvent(params);
//
console.log("最新进展", res);
//
progressList.value = res.data;
//
progressList.value.forEach(item =>
{
//
if (item.fxdj)
{
//
warningNum.value++;
//
}
//
}
);
//
}
catch
(
error
)
{
//
console.error(error);
//
}
//
}
;
// 法案进展 获取前期进展 --也是提出人左上角列表
const
handleGetBillDyqk
=
async
()
=>
{
...
...
@@ -601,9 +603,26 @@ const curPerson = ref({});
const
personEventList
=
ref
([]);
// 提出人 --动议id
const
handleGetBillPerson
=
async
id
=>
{
// const handleGetBillPerson = async id =>
{
// const params =
{
// id: id
//
}
;
// try
{
// const res = await getBillPerson(params);
// console.log("提出人", res);
// personList.value = res.data;
// box3BtnActive.value = res.data.length ? res.data[0].name : "";
// curPerson.value = res.data.length ? res.data[0] :
{
}
;
// personEventList.value = res.data.length ? res.data[0].eventList : [];
//
}
catch
(
error
)
{
// console.error(error);
//
}
//
}
;
// 法案提出人
const
handleGetBillPerson
=
async
()
=>
{
const
params
=
{
id
:
id
billId
:
window
.
sessionStorage
.
getItem
(
"billId"
)
}
;
try
{
const
res
=
await
getBillPerson
(
params
);
...
...
@@ -619,8 +638,9 @@ const handleGetBillPerson = async id => {
onMounted
(()
=>
{
handleGetBasicInfo
();
handleGetBillEvent
();
//
handleGetBillEvent();
handleGetBillDyqk
();
handleGetBillPerson
();
}
);
<
/script
>
...
...
@@ -695,11 +715,11 @@ onMounted(() => {
.
box1
-
right
{
margin
-
left
:
31
px
;
margin
-
top
:
5
px
;
width
:
623
px
;
//
width: 623px;
height
:
350
px
;
.
box1
-
right
-
item
{
display
:
flex
;
margin
-
bottom
:
2
4
px
;
margin
-
bottom
:
2
1
px
;
.
item
-
left
{
width
:
100
px
;
height
:
14
px
;
...
...
@@ -722,7 +742,23 @@ onMounted(() => {
}
.
item
-
right1
{
display
:
flex
;
align
-
items
:
center
;
width
:
700
px
;
height
:
40
px
;
overflow
-
x
:
auto
;
overflow
-
y
:
hidden
;
&
::
-
webkit
-
scrollbar
{
height
:
4
px
;
}
&
::
-
webkit
-
scrollbar
-
thumb
{
border
-
radius
:
4
px
;
background
:
#
e1e1e1
;
}
&
::
-
webkit
-
scrollbar
-
track
{
background
:
transparent
;
}
.
right1
-
item
{
flex
-
shrink
:
0
;
margin
-
right
:
10
px
;
padding
:
1
px
8
px
;
box
-
sizing
:
border
-
box
;
...
...
@@ -774,10 +810,14 @@ onMounted(() => {
text
-
align
:
center
;
position
:
relative
;
.
step
-
box
{
padding
:
0
10
px
0
2
0
px
;
padding
:
4
px
1
0
px
;
color
:
#
333
;
position
:
relative
;
font
-
size
:
14
px
;
font
-
weight
:
400
;
font
-
family
:
"Microsoft YaHei"
;
line
-
height
:
14
px
;
margin
-
left
:
10
px
;
.
right
-
arrow
{
position
:
absolute
;
right
:
-
21
px
;
...
...
@@ -792,7 +832,7 @@ onMounted(() => {
}
}
.
step
-
box
-
active
{
padding
:
0
12
px
;
padding
:
4
10
px
;
color
:
#
fff
;
background
:
#
ce4f51
;
position
:
relative
;
...
...
@@ -851,11 +891,13 @@ onMounted(() => {
box
-
shadow
:
0
px
0
px
15
px
0
px
rgba
(
22
,
119
,
255
,
0.1
);
.
box2
-
main
{
margin
-
top
:
10
px
;
height
:
calc
(
100
%
-
70
px
);
// Subtract header height
width
:
100
%
;
.
box2
-
main
-
center
{
margin
-
left
:
23
px
;
border
-
top
:
1
px
solid
rgba
(
243
,
243
,
244
,
1
);
// width: 100%;
height
:
300
px
;
width
:
calc
(
100
%
-
46
px
);
// Subtract margin
height
:
100
%
;
// background: orange;
.
box2
-
center
-
item
{
display
:
flex
;
...
...
@@ -1082,10 +1124,10 @@ onMounted(() => {
}
}
.
right
-
main
-
box2
{
width
:
576
px
;
height
:
150
px
;
//
width: 576px;
//
height: 150px;
box
-
sizing
:
border
-
box
;
padding
:
10
px
26
px
;
padding
:
22
px
26
px
;
// border-bottom: 1px solid rgb(243, 243, 244);
// display: flex;
// flex-wrap: wrap;
...
...
@@ -1140,7 +1182,7 @@ onMounted(() => {
}
.
right
-
main
-
box3
-
main
{
margin
-
top
:
18
px
;
height
:
299
px
;
height
:
412
px
;
overflow
-
y
:
auto
;
}
.
right
-
main
-
box3
-
footer
{
...
...
@@ -1330,6 +1372,10 @@ onMounted(() => {
color
:
var
(
--
btn
-
active
-
text
-
color
);
}
}
.
inner
-
right
-
main
{
height
:
860
px
;
overflow
:
auto
;
}
}
}
}
...
...
src/views/bill/template/index.vue
浏览文件 @
273f345b
...
...
@@ -16,9 +16,15 @@
</div>
<div
class=
"left-top"
>
<el-select
v-model=
"curBill"
placeholder=
"请选择"
style=
"width: 240px"
@
change=
"handleChangeBill"
>
<el-option
v-for=
"item in billList"
:key=
"item.
value"
:label=
"item.label"
:value=
"item.id
"
/>
<el-option
v-for=
"item in billList"
:key=
"item.
id"
:label=
"item.label"
:value=
"item.value
"
/>
</el-select>
<el-checkbox
style=
"margin-left: 30px"
v-model=
"checkedValue"
label=
"只看涉华条款"
size=
"large"
/>
<el-checkbox
style=
"margin-left: 30px"
v-model=
"checkedValue"
label=
"只看涉华条款"
size=
"large"
@
change=
"handleChangeCheckbox"
/>
<div
class=
"search"
style=
"width: 240px; margin-left: 475px"
>
<el-input
v-model=
"searchValue"
style=
"width: 240px"
placeholder=
"搜索条款"
/>
<div
class=
"icon"
>
...
...
@@ -28,32 +34,32 @@
</div>
<div
class=
"left-main"
>
<div
class=
"left-main-item"
v-for=
"(term, index) in mainTermsList"
:key=
"index"
>
<div
class=
"id"
>
{{
index
+
1
}}
</div>
<div
class=
"id"
>
{{
(
currentPage
-
1
)
*
pageSize
+
index
+
1
}}
</div>
<div
class=
"info"
>
<div
class=
"title"
>
<span
class=
"title-active"
>
{{
term
.
header
}}
</span>
{{
term
.
title
}}
<span
class=
"title-active"
>
第
{{
term
.
tkxh
}}
条.
</span>
{{
term
.
fynr
}}
</div>
<div
class=
"content"
>
<span
class=
"content-active"
>
{{
term
.
headerEn
}}
</span>
{{
term
.
content
}}
<span
class=
"content-active"
>
Sec.
{{
term
.
tkxh
}}
</span>
{{
term
.
ywnr
}}
</div>
</div>
<div
class=
"tags-box"
>
<div
class=
"tag"
v-for=
"(val, idx) in
term.tags
"
v-for=
"(val, idx) in
(term.hylyList || []).slice(0, 2)
"
:key=
"idx"
:class=
"
{
tag1: val.status === 1
,
tag2: val.status === 2
,
tag3: val.status === 3
,
tag4: val.status === 4
,
tag5: val.status === 5
,
tag6: val.status === 6
'tag1': val === '人工智能'
,
'tag2': val === '新一代信息技术' || !['人工智能', '政治', '经济', '军事', '科技'].includes(val)
,
'tag3': val === '政治'
,
'tag4': val === '经济'
,
'tag5': val === '军事'
,
'tag6': val === '科技'
}"
>
{{
val
.
name
}}
{{
val
}}
</div>
</div>
<div
class=
"open"
>
...
...
@@ -63,10 +69,17 @@
</div>
<div
class=
"left-footer"
>
<div
class=
"left-footer-text"
>
{{
"共96条涉华条款"
}}
{{
`共${total
}
条${checkedValue ? "涉华" : ""
}
条款`
}}
<
/div
>
<
div
class
=
"left-footer-right"
>
<el-pagination
background
layout=
"prev, pager, next"
:total=
"96"
/>
<
el
-
pagination
background
layout
=
"prev, pager, next"
:
total
=
"total"
v
-
model
:
current
-
page
=
"currentPage"
v
-
model
:
page
-
size
=
"pageSize"
@
current
-
change
=
"handleCurrentChange"
/>
<
/div
>
<
/div
>
<
/div
>
...
...
@@ -137,16 +150,12 @@ import { getBillContentId, getBillContentTk, getBillContentXzfs, getBillHyly } f
const
curBill
=
ref
(
""
);
const
curBillId
=
ref
(
null
);
const
billList
=
ref
([
{
value
:
"公法(2025年7月4日)"
,
label
:
"公法(2025年7月4日)"
},
{
value
:
"公法(2025年7月8日)"
,
label
:
"公法(2025年7月8日)"
}
]);
const
checkedValue
=
ref
(
false
);
const
searchValue
=
ref
(
""
);
const
billList
=
ref
([]);
const
currentPage
=
ref
(
1
);
const
pageSize
=
ref
(
10
);
const
total
=
ref
(
0
);
const
mainTermsList
=
ref
([
{
...
...
@@ -351,7 +360,13 @@ const setChart = (option, chartId) => {
// 切换原文
const
handleChangeBill
=
val
=>
{
curBillId
.
value
=
val
;
curBill
.
value
=
val
;
const
item
=
billList
.
value
.
find
(
item
=>
item
.
value
===
val
);
if
(
item
)
{
curBillId
.
value
=
item
.
id
;
currentPage
.
value
=
1
;
handleGetBillContentTk
(
checkedValue
.
value
?
"Y"
:
"N"
);
}
}
;
// 获取法案id列表
...
...
@@ -369,22 +384,69 @@ const handleGetBillList = async () => {
id
:
item
.
ywid
}
;
}
);
curBill
.
value
=
billList
.
value
[
0
].
label
;
curBillId
.
value
=
billList
.
value
[
0
].
id
;
if
(
billList
.
value
.
length
>
0
)
{
curBill
.
value
=
billList
.
value
[
0
].
value
;
curBillId
.
value
=
billList
.
value
[
0
].
id
;
}
}
catch
(
error
)
{
}
}
;
const
handleChangeCheckbox
=
val
=>
{
currentPage
.
value
=
1
;
handleGetBillContentTk
(
val
?
"Y"
:
"N"
);
}
;
const
handleCurrentChange
=
val
=>
{
currentPage
.
value
=
val
;
handleGetBillContentTk
(
checkedValue
.
value
?
"Y"
:
"N"
);
}
;
// 根据原文ID获取条款列表
const
handleGetBillContentTk
=
async
cRelated
=>
{
const
params
=
{
id
:
curBillId
.
value
,
billid
:
window
.
sessionStorage
.
getItem
(
"billId"
),
id
:
curBill
.
value
,
cRelated
:
cRelated
,
currentPage
:
0
,
pageSize
:
10
currentPage
:
currentPage
.
value
-
1
,
pageSize
:
pageSize
.
value
}
;
try
{
const
res
=
await
getBillContentTk
(
params
);
console
.
log
(
"条款内容"
,
res
);
mainTermsList
.
value
=
res
.
data
.
content
.
map
(
item
=>
{
// 处理 fynr
if
(
item
.
fynr
)
{
const
matchComplex
=
item
.
fynr
.
match
(
/^
(?:
正文内容
[
::
]\s
*
)?[
“"
]?\s
*第
\s
*
([
0-9a-zA-Z
]
+
)\s
*
[
条节
][
::
\.\。]?[
”"
]?\s
*/
);
if
(
matchComplex
)
{
// 匹配 "第xxx条"、"正文内容:第xxx条"、"“第xxx条" 等
if
(
!
item
.
tkxh
)
{
item
.
tkxh
=
matchComplex
[
1
];
}
item
.
fynr
=
item
.
fynr
.
replace
(
matchComplex
[
0
],
""
);
}
else
{
// 匹配 "xxx."
item
.
fynr
=
item
.
fynr
.
replace
(
/^
\d
+
\.\s
*/
,
""
);
}
}
// 处理 ywnr
if
(
item
.
ywnr
)
{
const
matchSec
=
item
.
ywnr
.
match
(
/^
(?:
SEC
\.
|SECTION
)\s
*
([
0-9a-zA-Z
]
+
)[\.
:
]?\s
*/i
);
if
(
matchSec
)
{
if
(
!
item
.
tkxh
)
{
item
.
tkxh
=
matchSec
[
1
];
}
item
.
ywnr
=
item
.
ywnr
.
replace
(
matchSec
[
0
],
""
);
}
else
{
item
.
ywnr
=
item
.
ywnr
.
replace
(
/^
\d
+
\.\s
*/
,
""
);
}
}
// 处理 tkxh 末尾的点
if
(
item
.
tkxh
)
{
item
.
tkxh
=
item
.
tkxh
.
replace
(
/
\.
$/
,
""
);
}
return
item
;
}
);
total
.
value
=
res
.
data
.
totalElements
;
}
catch
(
error
)
{
}
}
;
...
...
@@ -430,7 +492,7 @@ const handleGetBillHyly = async () => {
onMounted
(
async
()
=>
{
await
handleGetBillList
();
handleGetBillContentTk
(
false
);
handleGetBillContentTk
(
"N"
);
await
handleGetBillContentXzfs
();
await
handleGetBillHyly
();
let
chart1
=
getPieChart
(
chart1Data
.
value
,
chart1ColorList
.
value
);
...
...
@@ -528,6 +590,7 @@ onMounted(async () => {
border
-
radius
:
2
px
;
background
:
rgba
(
255
,
255
,
255
,
1
);
display
:
flex
;
position
:
relative
;
.
id
{
margin
-
top
:
20
px
;
margin
-
left
:
15
px
;
...
...
@@ -543,7 +606,7 @@ onMounted(async () => {
.
info
{
margin
-
left
:
13
px
;
margin
-
top
:
15
px
;
width
:
813
px
;
width
:
780
px
;
.
title
{
height
:
14
px
;
color
:
rgba
(
59
,
65
,
75
,
1
);
...
...
@@ -577,20 +640,19 @@ onMounted(async () => {
}
}
.
tags
-
box
{
margin-left
:
20px
;
margin-top
:
21px
;
width
:
160px
;
height
:
22px
;
display
:
flex
;
justify-content
:
flex-end
;
justify
-
content
:
right
;
align
-
items
:
center
;
flex
:
1
;
margin
-
right
:
50
px
;
.
tag
{
height
:
18px
;
text
-
align
:
right
;
line
-
height
:
18
px
;
padding
:
0
8px
;
padding
:
1
px
8
px
;
border
-
radius
:
4
px
;
margin
-
left
:
5
px
;
font
-
size
:
12
px
;
font-family
:
Microsoft
YaHei
;
font
-
family
:
"Microsoft YaHei"
;
font
-
size
:
14
px
;
font
-
weight
:
400
;
}
...
...
@@ -626,8 +688,9 @@ onMounted(async () => {
}
}
.
open
{
margin-left
:
10px
;
margin-top
:
22px
;
position
:
absolute
;
top
:
22
px
;
right
:
23
px
;
width
:
20
px
;
height
:
20
px
;
img
{
...
...
src/views/bill/template/utils/piechart.js
浏览文件 @
273f345b
...
...
@@ -4,6 +4,7 @@ const getPieChart = (data,colorList) => {
series
:
[
{
type
:
'pie'
,
minAngle
:
28
,
radius
:
[
70
,
100
],
height
:
'100%'
,
left
:
'center'
,
...
...
@@ -38,7 +39,9 @@ const getPieChart = (data,colorList) => {
?
params
.
labelRect
.
x
:
params
.
labelRect
.
x
+
params
.
labelRect
.
width
;
return
{
labelLinePoints
:
points
labelLinePoints
:
points
,
hideOverlap
:
false
,
moveOverlap
:
'shiftY'
};
},
data
:
data
...
...
src/views/exportControl/analysis/components/fishbone-back.vue
浏览文件 @
273f345b
<
template
>
<div
class=
"fishbone"
>
<div
class=
"main-line"
></div>
<div
class=
"top-bone
"
>
<div
v-for=
"(causeGroup, groupIndex) in fishboneData.causes"
:key=
"groupIndex"
:class=
"getBoneClass(groupIndex)
"
>
<div
class=
"left-bone"
>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
</div>
<div
class=
"right-bone"
>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
</div>
</div>
<div
class=
"top-bone1"
>
<div
class=
"left-bone"
>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
</div>
<div
class=
"right-bone"
>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
</div>
</div>
<div
class=
"top-bone2"
>
<div
class=
"left-bone"
>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
</div>
<div
class=
"right-bone"
>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
</div>
</div>
<div
class=
"bottom-bone"
>
<div
class=
"left-bone"
>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"left-bone-item"
v-for=
"(item, index) in getLeftItems(causeGroup.causes)"
:key=
"index"
>
<!--
<div
class=
"icon"
>
<img
:src=
"item.picture"
alt=
""
/>
</div>
-->
<div
class=
"text"
>
{{
item
.
name
}}
</div>
<div
class=
"line"
></div>
</div>
</div>
<div
class=
"right-bone"
>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
<div
class=
"right-bone-item"
>
<div
class=
"right-bone-item"
v-for=
"(item, index) in getRightItems(causeGroup.causes)"
:key=
"index"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
</div>
</div>
<div
class=
"bottom-bone1"
>
<div
class=
"left-bone"
>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
</div>
<div
class=
"right-bone"
>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
</div>
</div>
<div
class=
"bottom-bone2"
>
<div
class=
"left-bone"
>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
<div
class=
"left-bone-item"
>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"line"
></div>
</div>
</div>
<div
class=
"right-bone"
>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
</div>
<div
class=
"right-bone-item"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
</div>
<div
class=
"text"
>
{{
item
.
name
}}
</div>
<!--
<div
class=
"icon"
>
<img
:src=
"item.picture"
:alt=
"item.name"
/>
</div>
-->
</div>
</div>
</div>
...
...
@@ -474,12 +27,39 @@
<
script
setup
>
import
{
getChainFishbone
}
from
"@/api/exportControl"
;
import
{
onMounted
,
ref
}
from
"vue"
;
const
chainId
=
ref
(
""
);
const
chainFishbone
=
ref
([]);
const
chainId
=
ref
(
1
);
const
fishboneData
=
ref
({
text
:
""
,
causes
:
[]
});
// 根据索引确定鱼骨图位置类名
const
getBoneClass
=
index
=>
{
const
positions
=
[
"top-bone"
,
"top-bone1"
,
"top-bone2"
,
"bottom-bone"
,
"bottom-bone1"
,
"bottom-bone2"
];
return
positions
[
index
]
||
"top-bone"
;
};
// 获取左侧显示的项目(前半部分)
const
getLeftItems
=
items
=>
{
const
midpoint
=
Math
.
ceil
(
items
.
length
/
2
);
return
items
.
slice
(
0
,
midpoint
);
};
// 获取右侧显示的项目(后半部分)
const
getRightItems
=
items
=>
{
const
midpoint
=
Math
.
ceil
(
items
.
length
/
2
);
return
items
.
slice
(
midpoint
);
};
onMounted
(
async
()
=>
{
try
{
const
chainFishboneData
=
await
getChainFishbone
(
chainId
.
value
);
chainFishbone
.
value
=
chainFishboneData
??
[];
fishboneData
.
value
=
chainFishboneData
??
{
text
:
""
,
causes
:
[]
};
console
.
log
(
"鱼骨图数据:"
,
fishboneData
.
value
);
}
catch
(
error
)
{
console
.
log
(
error
);
}
...
...
@@ -487,11 +67,14 @@ onMounted(async () => {
</
script
>
<
style
lang=
"scss"
scoped
>
/* ... 原有的样式保持不变 ... */
.fishbone
{
position
:
relative
;
width
:
100%
;
height
:
100%
;
margin-top
:
40px
;
overflow-x
:
auto
;
.main-line
{
position
:
absolute
;
top
:
280px
;
...
...
@@ -501,6 +84,7 @@ onMounted(async () => {
background
:
rgba
(
174
,
208
,
255
,
1
);
}
}
.top-bone
{
position
:
absolute
;
top
:
20px
;
...
...
@@ -517,13 +101,11 @@ onMounted(async () => {
left
:
-150px
;
width
:
150px
;
height
:
260px
;
// background: orange;
.left-bone-item
{
transform
:
skew
(
-30deg
);
height
:
35px
;
margin-bottom
:
5px
;
margin-top
:
15px
;
// background: #fff;
display
:
flex
;
justify-content
:
flex-end
;
.icon
{
...
...
@@ -537,8 +119,11 @@ onMounted(async () => {
}
.text
{
margin-left
:
4px
;
height
:
35
px
;
height
:
70
px
;
line-height
:
35px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
.line
{
margin-left
:
7px
;
...
...
@@ -556,7 +141,6 @@ onMounted(async () => {
right
:
-150px
;
width
:
150px
;
height
:
260px
;
// background: pink;
.right-bone-item
{
transform
:
skew
(
-30deg
);
height
:
35px
;
...
...
@@ -564,7 +148,6 @@ onMounted(async () => {
margin-top
:
5px
;
display
:
flex
;
justify-content
:
flex-start
;
.line
{
margin-right
:
7px
;
margin-top
:
16px
;
...
...
@@ -572,11 +155,14 @@ onMounted(async () => {
height
:
2px
;
background
:
rgba
(
174
,
208
,
255
,
1
);
}
.text
{
width
:
100px
;
margin-right
:
4px
;
height
:
35px
;
line-height
:
35px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
.icon
{
margin-top
:
7px
;
...
...
@@ -590,6 +176,7 @@ onMounted(async () => {
}
}
}
.top-bone1
{
position
:
absolute
;
top
:
20px
;
...
...
@@ -606,13 +193,11 @@ onMounted(async () => {
left
:
-150px
;
width
:
150px
;
height
:
260px
;
// background: orange;
.left-bone-item
{
transform
:
skew
(
-30deg
);
height
:
35px
;
margin-bottom
:
5px
;
margin-top
:
15px
;
// background: #fff;
display
:
flex
;
justify-content
:
flex-end
;
.icon
{
...
...
@@ -625,9 +210,13 @@ onMounted(async () => {
}
}
.text
{
width
:
100px
;
margin-left
:
4px
;
height
:
35px
;
line-height
:
35px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
.line
{
margin-left
:
7px
;
...
...
@@ -645,7 +234,6 @@ onMounted(async () => {
right
:
-150px
;
width
:
150px
;
height
:
260px
;
// background: pink;
.right-bone-item
{
transform
:
skew
(
-30deg
);
height
:
35px
;
...
...
@@ -653,7 +241,6 @@ onMounted(async () => {
margin-top
:
5px
;
display
:
flex
;
justify-content
:
flex-start
;
.line
{
margin-right
:
7px
;
margin-top
:
16px
;
...
...
@@ -661,11 +248,14 @@ onMounted(async () => {
height
:
2px
;
background
:
rgba
(
174
,
208
,
255
,
1
);
}
.text
{
width
:
100px
;
margin-right
:
4px
;
height
:
35px
;
line-height
:
35px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
.icon
{
margin-top
:
7px
;
...
...
@@ -679,6 +269,7 @@ onMounted(async () => {
}
}
}
.top-bone2
{
position
:
absolute
;
top
:
20px
;
...
...
@@ -695,13 +286,11 @@ onMounted(async () => {
left
:
-150px
;
width
:
150px
;
height
:
260px
;
// background: orange;
.left-bone-item
{
transform
:
skew
(
-30deg
);
height
:
35px
;
margin-bottom
:
5px
;
margin-top
:
15px
;
// background: #fff;
display
:
flex
;
justify-content
:
flex-end
;
.icon
{
...
...
@@ -714,9 +303,13 @@ onMounted(async () => {
}
}
.text
{
width
:
100px
;
margin-left
:
4px
;
height
:
35px
;
line-height
:
35px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
.line
{
margin-left
:
7px
;
...
...
@@ -734,7 +327,6 @@ onMounted(async () => {
right
:
-150px
;
width
:
150px
;
height
:
260px
;
// background: pink;
.right-bone-item
{
transform
:
skew
(
-30deg
);
height
:
35px
;
...
...
@@ -742,7 +334,6 @@ onMounted(async () => {
margin-top
:
5px
;
display
:
flex
;
justify-content
:
flex-start
;
.line
{
margin-right
:
7px
;
margin-top
:
16px
;
...
...
@@ -750,11 +341,14 @@ onMounted(async () => {
height
:
2px
;
background
:
rgba
(
174
,
208
,
255
,
1
);
}
.text
{
width
:
100px
;
margin-right
:
4px
;
height
:
35px
;
line-height
:
35px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
.icon
{
margin-top
:
7px
;
...
...
@@ -768,6 +362,7 @@ onMounted(async () => {
}
}
}
.bottom-bone
{
position
:
absolute
;
top
:
280px
;
...
...
@@ -784,13 +379,11 @@ onMounted(async () => {
left
:
-150px
;
width
:
150px
;
height
:
260px
;
// background: orange;
.left-bone-item
{
transform
:
skew
(
30deg
);
height
:
35px
;
margin-bottom
:
5px
;
margin-top
:
15px
;
// background: #fff;
display
:
flex
;
justify-content
:
flex-end
;
.icon
{
...
...
@@ -803,9 +396,13 @@ onMounted(async () => {
}
}
.text
{
width
:
100px
;
margin-left
:
4px
;
height
:
35px
;
line-height
:
35px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
.line
{
margin-left
:
7px
;
...
...
@@ -823,7 +420,6 @@ onMounted(async () => {
right
:
-150px
;
width
:
150px
;
height
:
260px
;
// background: pink;
.right-bone-item
{
transform
:
skew
(
30deg
);
height
:
35px
;
...
...
@@ -831,7 +427,6 @@ onMounted(async () => {
margin-top
:
5px
;
display
:
flex
;
justify-content
:
flex-start
;
.line
{
margin-right
:
7px
;
margin-top
:
16px
;
...
...
@@ -839,11 +434,14 @@ onMounted(async () => {
height
:
2px
;
background
:
rgba
(
174
,
208
,
255
,
1
);
}
.text
{
width
:
100px
;
margin-right
:
4px
;
height
:
35px
;
line-height
:
35px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
.icon
{
margin-top
:
7px
;
...
...
@@ -857,6 +455,7 @@ onMounted(async () => {
}
}
}
.bottom-bone1
{
position
:
absolute
;
top
:
280px
;
...
...
@@ -873,13 +472,11 @@ onMounted(async () => {
left
:
-150px
;
width
:
150px
;
height
:
260px
;
// background: orange;
.left-bone-item
{
transform
:
skew
(
30deg
);
height
:
35px
;
margin-bottom
:
5px
;
margin-top
:
15px
;
// background: #fff;
display
:
flex
;
justify-content
:
flex-end
;
.icon
{
...
...
@@ -892,9 +489,13 @@ onMounted(async () => {
}
}
.text
{
width
:
100px
;
margin-left
:
4px
;
height
:
35px
;
line-height
:
35px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
.line
{
margin-left
:
7px
;
...
...
@@ -912,7 +513,6 @@ onMounted(async () => {
right
:
-150px
;
width
:
150px
;
height
:
260px
;
// background: pink;
.right-bone-item
{
transform
:
skew
(
30deg
);
height
:
35px
;
...
...
@@ -920,7 +520,6 @@ onMounted(async () => {
margin-top
:
5px
;
display
:
flex
;
justify-content
:
flex-start
;
.line
{
margin-right
:
7px
;
margin-top
:
16px
;
...
...
@@ -928,11 +527,14 @@ onMounted(async () => {
height
:
2px
;
background
:
rgba
(
174
,
208
,
255
,
1
);
}
.text
{
width
:
100px
;
margin-right
:
4px
;
height
:
35px
;
line-height
:
35px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
.icon
{
margin-top
:
7px
;
...
...
@@ -946,6 +548,7 @@ onMounted(async () => {
}
}
}
.bottom-bone2
{
position
:
absolute
;
top
:
280px
;
...
...
@@ -962,13 +565,11 @@ onMounted(async () => {
left
:
-150px
;
width
:
150px
;
height
:
260px
;
// background: orange;
.left-bone-item
{
transform
:
skew
(
30deg
);
height
:
35px
;
margin-bottom
:
5px
;
margin-top
:
15px
;
// background: #fff;
display
:
flex
;
justify-content
:
flex-end
;
.icon
{
...
...
@@ -981,9 +582,13 @@ onMounted(async () => {
}
}
.text
{
width
:
100px
;
margin-left
:
4px
;
height
:
35px
;
line-height
:
35px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
.line
{
margin-left
:
7px
;
...
...
@@ -1001,7 +606,6 @@ onMounted(async () => {
right
:
-150px
;
width
:
150px
;
height
:
260px
;
// background: pink;
.right-bone-item
{
transform
:
skew
(
30deg
);
height
:
35px
;
...
...
@@ -1009,7 +613,6 @@ onMounted(async () => {
margin-top
:
5px
;
display
:
flex
;
justify-content
:
flex-start
;
.line
{
margin-right
:
7px
;
margin-top
:
16px
;
...
...
@@ -1017,11 +620,14 @@ onMounted(async () => {
height
:
2px
;
background
:
rgba
(
174
,
208
,
255
,
1
);
}
.text
{
width
:
100px
;
margin-right
:
4px
;
height
:
35px
;
line-height
:
35px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
.icon
{
margin-top
:
7px
;
...
...
src/views/exportControl/analysis/components/fishbone-mock.json
浏览文件 @
273f345b
[
{
"id"
:
null
,
"name"
:
"2025-10-09"
,
"count"
:
10
},
{
"id"
:
null
,
"name"
:
"2025-10-08"
,
"count"
:
8
},
{
"id"
:
null
,
"name"
:
"2025-09-16"
,
"count"
:
16
"yearDomainCount"
:
[
{
"sanTypeName"
:
null
,
"year"
:
2020
,
"domainCountInfo"
:
[
{
"year"
:
2020
,
"id"
:
"1"
,
"name"
:
"人工智能"
,
"count"
:
11
},
{
"year"
:
2020
,
"id"
:
"2"
,
"name"
:
"生物科技"
,
"count"
:
2
},
{
"year"
:
2020
,
"id"
:
"3"
,
"name"
:
"新一代信息技术"
,
"count"
:
13
},
{
"year"
:
2020
,
"id"
:
"4"
,
"name"
:
"量子科技"
,
"count"
:
0
},
{
"year"
:
2020
,
"id"
:
"5"
,
"name"
:
"新能源"
,
"count"
:
0
},
{
"year"
:
2020
,
"id"
:
"6"
,
"name"
:
"集成电路"
,
"count"
:
1
},
{
"year"
:
2020
,
"id"
:
"7"
,
"name"
:
"海洋"
,
"count"
:
47
},
{
"year"
:
2020
,
"id"
:
"8"
,
"name"
:
"先进制造"
,
"count"
:
22
},
{
"year"
:
2020
,
"id"
:
"9"
,
"name"
:
"新材料"
,
"count"
:
0
},
{
"year"
:
2020
,
"id"
:
"10"
,
"name"
:
"航空航天"
,
"count"
:
18
},
{
"year"
:
2020
,
"id"
:
"99"
,
"name"
:
"其他"
,
"count"
:
0
},
{
"year"
:
2020
,
"id"
:
"13"
,
"name"
:
"太空"
,
"count"
:
0
},
{
"year"
:
2020
,
"id"
:
"11"
,
"name"
:
"深海"
,
"count"
:
0
},
{
"year"
:
2020
,
"id"
:
"12"
,
"name"
:
"极地"
,
"count"
:
0
},
{
"year"
:
2020
,
"id"
:
"14"
,
"name"
:
"核"
,
"count"
:
10
}
]
},
{
"sanTypeName"
:
null
,
"year"
:
2021
,
"domainCountInfo"
:
[
{
"year"
:
2021
,
"id"
:
"1"
,
"name"
:
"人工智能"
,
"count"
:
15
},
{
"year"
:
2021
,
"id"
:
"2"
,
"name"
:
"生物科技"
,
"count"
:
12
},
{
"year"
:
2021
,
"id"
:
"3"
,
"name"
:
"新一代信息技术"
,
"count"
:
5
},
{
"year"
:
2021
,
"id"
:
"4"
,
"name"
:
"量子科技"
,
"count"
:
7
},
{
"year"
:
2021
,
"id"
:
"5"
,
"name"
:
"新能源"
,
"count"
:
3
},
{
"year"
:
2021
,
"id"
:
"6"
,
"name"
:
"集成电路"
,
"count"
:
22
},
{
"year"
:
2021
,
"id"
:
"7"
,
"name"
:
"海洋"
,
"count"
:
5
},
{
"year"
:
2021
,
"id"
:
"8"
,
"name"
:
"先进制造"
,
"count"
:
27
},
{
"year"
:
2021
,
"id"
:
"9"
,
"name"
:
"新材料"
,
"count"
:
7
},
{
"year"
:
2021
,
"id"
:
"10"
,
"name"
:
"航空航天"
,
"count"
:
4
},
{
"year"
:
2021
,
"id"
:
"99"
,
"name"
:
"其他"
,
"count"
:
0
},
{
"year"
:
2021
,
"id"
:
"13"
,
"name"
:
"太空"
,
"count"
:
0
},
{
"year"
:
2021
,
"id"
:
"11"
,
"name"
:
"深海"
,
"count"
:
3
},
{
"year"
:
2021
,
"id"
:
"12"
,
"name"
:
"极地"
,
"count"
:
0
},
{
"year"
:
2021
,
"id"
:
"14"
,
"name"
:
"核"
,
"count"
:
3
}
]
},
{
"sanTypeName"
:
null
,
"year"
:
2022
,
"domainCountInfo"
:
[
{
"year"
:
2022
,
"id"
:
"1"
,
"name"
:
"人工智能"
,
"count"
:
22
},
{
"year"
:
2022
,
"id"
:
"2"
,
"name"
:
"生物科技"
,
"count"
:
0
},
{
"year"
:
2022
,
"id"
:
"3"
,
"name"
:
"新一代信息技术"
,
"count"
:
2
},
{
"year"
:
2022
,
"id"
:
"4"
,
"name"
:
"量子科技"
,
"count"
:
0
},
{
"year"
:
2022
,
"id"
:
"5"
,
"name"
:
"新能源"
,
"count"
:
0
},
{
"year"
:
2022
,
"id"
:
"6"
,
"name"
:
"集成电路"
,
"count"
:
33
},
{
"year"
:
2022
,
"id"
:
"7"
,
"name"
:
"海洋"
,
"count"
:
7
},
{
"year"
:
2022
,
"id"
:
"8"
,
"name"
:
"先进制造"
,
"count"
:
27
},
{
"year"
:
2022
,
"id"
:
"9"
,
"name"
:
"新材料"
,
"count"
:
1
},
{
"year"
:
2022
,
"id"
:
"10"
,
"name"
:
"航空航天"
,
"count"
:
12
},
{
"year"
:
2022
,
"id"
:
"99"
,
"name"
:
"其他"
,
"count"
:
0
},
{
"year"
:
2022
,
"id"
:
"13"
,
"name"
:
"太空"
,
"count"
:
0
},
{
"year"
:
2022
,
"id"
:
"11"
,
"name"
:
"深海"
,
"count"
:
2
},
{
"year"
:
2022
,
"id"
:
"12"
,
"name"
:
"极地"
,
"count"
:
0
},
{
"year"
:
2022
,
"id"
:
"14"
,
"name"
:
"核"
,
"count"
:
0
}
]
},
{
"sanTypeName"
:
null
,
"year"
:
2023
,
"domainCountInfo"
:
[
{
"year"
:
2023
,
"id"
:
"1"
,
"name"
:
"人工智能"
,
"count"
:
31
},
{
"year"
:
2023
,
"id"
:
"2"
,
"name"
:
"生物科技"
,
"count"
:
5
},
{
"year"
:
2023
,
"id"
:
"3"
,
"name"
:
"新一代信息技术"
,
"count"
:
3
},
{
"year"
:
2023
,
"id"
:
"4"
,
"name"
:
"量子科技"
,
"count"
:
1
},
{
"year"
:
2023
,
"id"
:
"5"
,
"name"
:
"新能源"
,
"count"
:
0
},
{
"year"
:
2023
,
"id"
:
"6"
,
"name"
:
"集成电路"
,
"count"
:
82
},
{
"year"
:
2023
,
"id"
:
"7"
,
"name"
:
"海洋"
,
"count"
:
7
},
{
"year"
:
2023
,
"id"
:
"8"
,
"name"
:
"先进制造"
,
"count"
:
36
},
{
"year"
:
2023
,
"id"
:
"9"
,
"name"
:
"新材料"
,
"count"
:
1
},
{
"year"
:
2023
,
"id"
:
"10"
,
"name"
:
"航空航天"
,
"count"
:
55
},
{
"year"
:
2023
,
"id"
:
"99"
,
"name"
:
"其他"
,
"count"
:
0
},
{
"year"
:
2023
,
"id"
:
"13"
,
"name"
:
"太空"
,
"count"
:
1
},
{
"year"
:
2023
,
"id"
:
"11"
,
"name"
:
"深海"
,
"count"
:
0
},
{
"year"
:
2023
,
"id"
:
"12"
,
"name"
:
"极地"
,
"count"
:
0
},
{
"year"
:
2023
,
"id"
:
"14"
,
"name"
:
"核"
,
"count"
:
7
}
]
},
{
"sanTypeName"
:
null
,
"year"
:
2024
,
"domainCountInfo"
:
[
{
"year"
:
2024
,
"id"
:
"1"
,
"name"
:
"人工智能"
,
"count"
:
33
},
{
"year"
:
2024
,
"id"
:
"2"
,
"name"
:
"生物科技"
,
"count"
:
0
},
{
"year"
:
2024
,
"id"
:
"3"
,
"name"
:
"新一代信息技术"
,
"count"
:
10
},
{
"year"
:
2024
,
"id"
:
"4"
,
"name"
:
"量子科技"
,
"count"
:
22
},
{
"year"
:
2024
,
"id"
:
"5"
,
"name"
:
"新能源"
,
"count"
:
0
},
{
"year"
:
2024
,
"id"
:
"6"
,
"name"
:
"集成电路"
,
"count"
:
190
},
{
"year"
:
2024
,
"id"
:
"7"
,
"name"
:
"海洋"
,
"count"
:
0
},
{
"year"
:
2024
,
"id"
:
"8"
,
"name"
:
"先进制造"
,
"count"
:
27
},
{
"year"
:
2024
,
"id"
:
"9"
,
"name"
:
"新材料"
,
"count"
:
13
},
{
"year"
:
2024
,
"id"
:
"10"
,
"name"
:
"航空航天"
,
"count"
:
29
},
{
"year"
:
2024
,
"id"
:
"99"
,
"name"
:
"其他"
,
"count"
:
0
},
{
"year"
:
2024
,
"id"
:
"13"
,
"name"
:
"太空"
,
"count"
:
0
},
{
"year"
:
2024
,
"id"
:
"11"
,
"name"
:
"深海"
,
"count"
:
0
},
{
"year"
:
2024
,
"id"
:
"12"
,
"name"
:
"极地"
,
"count"
:
0
},
{
"year"
:
2024
,
"id"
:
"14"
,
"name"
:
"核"
,
"count"
:
2
}
]
},
{
"sanTypeName"
:
null
,
"year"
:
2025
,
"domainCountInfo"
:
[
{
"year"
:
2025
,
"id"
:
"1"
,
"name"
:
"人工智能"
,
"count"
:
12
},
{
"year"
:
2025
,
"id"
:
"2"
,
"name"
:
"生物科技"
,
"count"
:
0
},
{
"year"
:
2025
,
"id"
:
"3"
,
"name"
:
"新一代信息技术"
,
"count"
:
11
},
{
"year"
:
2025
,
"id"
:
"4"
,
"name"
:
"量子科技"
,
"count"
:
9
},
{
"year"
:
2025
,
"id"
:
"5"
,
"name"
:
"新能源"
,
"count"
:
0
},
{
"year"
:
2025
,
"id"
:
"6"
,
"name"
:
"集成电路"
,
"count"
:
35
},
{
"year"
:
2025
,
"id"
:
"7"
,
"name"
:
"海洋"
,
"count"
:
0
},
{
"year"
:
2025
,
"id"
:
"8"
,
"name"
:
"先进制造"
,
"count"
:
42
},
{
"year"
:
2025
,
"id"
:
"9"
,
"name"
:
"新材料"
,
"count"
:
11
},
{
"year"
:
2025
,
"id"
:
"10"
,
"name"
:
"航空航天"
,
"count"
:
26
},
{
"year"
:
2025
,
"id"
:
"99"
,
"name"
:
"其他"
,
"count"
:
0
},
{
"year"
:
2025
,
"id"
:
"13"
,
"name"
:
"太空"
,
"count"
:
1
},
{
"year"
:
2025
,
"id"
:
"11"
,
"name"
:
"深海"
,
"count"
:
0
},
{
"year"
:
2025
,
"id"
:
"12"
,
"name"
:
"极地"
,
"count"
:
0
},
{
"year"
:
2025
,
"id"
:
"14"
,
"name"
:
"核"
,
"count"
:
1
}
]
}
],
"domians"
:
[
{
"year"
:
null
,
"id"
:
"1"
,
"name"
:
"人工智能"
,
"count"
:
null
},
{
"year"
:
null
,
"id"
:
"2"
,
"name"
:
"生物科技"
,
"count"
:
null
},
{
"year"
:
null
,
"id"
:
"3"
,
"name"
:
"新一代信息技术"
,
"count"
:
null
},
{
"year"
:
null
,
"id"
:
"4"
,
"name"
:
"量子科技"
,
"count"
:
null
},
{
"year"
:
null
,
"id"
:
"5"
,
"name"
:
"新能源"
,
"count"
:
null
},
{
"year"
:
null
,
"id"
:
"6"
,
"name"
:
"集成电路"
,
"count"
:
null
},
{
"year"
:
null
,
"id"
:
"7"
,
"name"
:
"海洋"
,
"count"
:
null
},
{
"year"
:
null
,
"id"
:
"8"
,
"name"
:
"先进制造"
,
"count"
:
null
},
{
"year"
:
null
,
"id"
:
"9"
,
"name"
:
"新材料"
,
"count"
:
null
},
{
"year"
:
null
,
"id"
:
"10"
,
"name"
:
"航空航天"
,
"count"
:
null
},
{
"year"
:
null
,
"id"
:
"99"
,
"name"
:
"其他"
,
"count"
:
null
},
{
"year"
:
null
,
"id"
:
"13"
,
"name"
:
"太空"
,
"count"
:
null
},
{
"year"
:
null
,
"id"
:
"11"
,
"name"
:
"深海"
,
"count"
:
null
},
{
"year"
:
null
,
"id"
:
"12"
,
"name"
:
"极地"
,
"count"
:
null
},
{
"year"
:
null
,
"id"
:
"14"
,
"name"
:
"核"
,
"count"
:
null
}
]
}
]
\ No newline at end of file
src/views/exportControl/analysis/components/fishbone.vue
浏览文件 @
273f345b
<
template
>
<div
class=
"fishbone"
>
<div
class=
"main-line"
></div>
<div
v-for=
"(causeGroup, groupIndex) in fishboneData.causes"
:key=
"groupIndex"
:class=
"getBoneClass(groupIndex)"
>
<div
class=
"left-bone"
>
<div
class=
"left-bone-item"
v-for=
"(item, index) in getLeftItems(causeGroup.causes)"
:key=
"index"
>
<!--
<div
class=
"icon"
>
<img
:src=
"item.picture"
alt=
""
/>
</div>
-->
<div
class=
"text"
>
{{
item
.
name
}}
</div>
<div
class=
"line"
></div>
<div
class=
"fishbone-wrapper"
>
<div
class=
"fishbone-scroll-container"
ref=
"scrollContainerRef"
>
<div
class=
"fishbone"
ref=
"fishboneRef"
v-if=
"fishboneData.length > 0"
>
<div
class=
"main-line"
:style=
"
{ width: (fishboneData.length / 2) * 340 - 275 + 'px' }">
</div>
<!-- 奇数索引的数据组放在上方 -->
<div
v-for=
"(causeGroup, groupIndex) in getOddGroups(fishboneData)"
:key=
"'top-' + groupIndex"
:class=
"getTopBoneClass(groupIndex)"
:style=
"
{ left: groupIndex * 300 + 400 + 'px' }"
>
<div
class=
"left-bone"
>
<div
class=
"left-bone-item"
v-for=
"(item, index) in getLeftItems(causeGroup.causes)"
:key=
"'left-' + index"
>
<div
class=
"text"
>
{{
item
.
name
}}
</div>
<div
class=
"line"
></div>
</div>
</div>
<div
class=
"right-bone"
>
<div
class=
"right-bone-item"
v-for=
"(item, index) in getRightItems(causeGroup.causes)"
:key=
"'right-' + index"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
item
.
name
}}
</div>
</div>
</div>
</div>
</div>
<div
class=
"right-bone"
>
<div
class=
"right-bone-item"
v-for=
"(item, index) in getRightItems(causeGroup.causes)"
:key=
"index"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
item
.
name
}}
</div>
<!--
<div
class=
"icon"
>
<img
:src=
"item.picture"
:alt=
"item.name"
/>
</div>
-->
<!-- 偶数索引的数据组放在下方 -->
<div
v-for=
"(causeGroup, groupIndex) in getEvenGroups(fishboneData)"
:key=
"'bottom-' + groupIndex"
:class=
"getBottomBoneClass(groupIndex)"
:style=
"
{ left: groupIndex * 300 + 200 + 'px' }"
>
<div
class=
"left-bone"
>
<div
class=
"left-bone-item"
v-for=
"(item, index) in getLeftItems(causeGroup.causes)"
:key=
"'left-bottom-' + index"
>
<div
class=
"text"
>
{{
item
.
name
}}
</div>
<div
class=
"line"
></div>
</div>
</div>
<div
class=
"right-bone"
>
<div
class=
"right-bone-item"
v-for=
"(item, index) in getRightItems(causeGroup.causes)"
:key=
"'right-bottom-' + index"
>
<div
class=
"line"
></div>
<div
class=
"text"
>
{{
item
.
name
}}
</div>
</div>
</div>
</div>
</div>
<div
v-else
style=
"display: flex; justify-content: center; align-items: center; height: 200px; width: 100%"
>
<el-empty
description=
"暂无相关数据"
/>
</div>
</div>
<!-- 滚动指示器 -->
<!--
<div
class=
"scroll-indicators"
v-if=
"showScrollIndicator"
>
<div
class=
"scroll-btn left"
:class=
"
{ disabled: !canScrollLeft }" @click="scrollLeft">‹
</div>
<div
class=
"scroll-btn right"
:class=
"
{ disabled: !canScrollRight }" @click="scrollRight">›
</div>
</div>
-->
</div>
</
template
>
<
script
setup
>
import
{
getChainFishbone
}
from
"@/api/exportControl"
;
import
{
onMounted
,
ref
}
from
"vue"
;
const
chainId
=
ref
(
1
);
const
fishboneData
=
ref
({
text
:
""
,
causes
:
[]
import
{
onMounted
,
ref
,
nextTick
,
watch
}
from
"vue"
;
// 这儿需要接收父组件传递来的产业链ID
const
props
=
defineProps
({
chainId
:
{
type
:
Number
,
default
:
1
}
});
// 根据索引确定鱼骨图位置类名
const
getBoneClass
=
index
=>
{
const
positions
=
[
"top-bone"
,
"top-bone1"
,
"top-bone2"
,
"bottom-bone"
,
"bottom-bone1"
,
"bottom-bone2"
];
return
positions
[
index
]
||
"top-bone"
;
// const chainId = ref(1);
const
fishboneData
=
ref
([]);
const
scrollContainerRef
=
ref
(
null
);
const
fishboneRef
=
ref
(
null
);
const
showScrollIndicator
=
ref
(
false
);
const
canScrollLeft
=
ref
(
false
);
const
canScrollRight
=
ref
(
true
);
// 获取奇数索引的数据组(放在上方)
const
getOddGroups
=
data
=>
{
console
.
log
(
"getOddGroups:"
,
data
.
filter
((
_
,
index
)
=>
index
%
2
===
1
)
);
return
data
.
filter
((
_
,
index
)
=>
index
%
2
===
1
);
};
// 获取偶数索引的数据组(放在下方)
const
getEvenGroups
=
data
=>
{
console
.
log
(
"getEvenGroups:"
,
data
.
filter
((
_
,
index
)
=>
index
%
2
===
0
)
);
return
data
.
filter
((
_
,
index
)
=>
index
%
2
===
0
);
};
// 获取上方鱼骨图位置类名
const
getTopBoneClass
=
index
=>
{
const
positions
=
[
"top-bone"
,
"top-bone1"
,
"top-bone2"
];
return
positions
[
index
%
3
]
||
"top-bone"
;
};
// 获取下方鱼骨图位置类名
const
getBottomBoneClass
=
index
=>
{
const
positions
=
[
"bottom-bone"
,
"bottom-bone1"
,
"bottom-bone2"
];
return
positions
[
index
%
3
]
||
"bottom-bone"
;
};
// 获取左侧显示的项目(前半部分)
...
...
@@ -52,32 +135,109 @@ const getRightItems = items => {
return
items
.
slice
(
midpoint
);
};
// 检查滚动状态
const
updateScrollState
=
()
=>
{
if
(
!
scrollContainerRef
.
value
)
return
;
const
container
=
scrollContainerRef
.
value
;
canScrollLeft
.
value
=
container
.
scrollLeft
>
0
;
canScrollRight
.
value
=
container
.
scrollLeft
<
container
.
scrollWidth
-
container
.
clientWidth
;
};
// 滚动处理
const
scrollLeft
=
()
=>
{
if
(
scrollContainerRef
.
value
)
{
scrollContainerRef
.
value
.
scrollBy
({
left
:
-
200
,
behavior
:
"smooth"
});
}
};
const
scrollRight
=
()
=>
{
if
(
scrollContainerRef
.
value
)
{
scrollContainerRef
.
value
.
scrollBy
({
left
:
200
,
behavior
:
"smooth"
});
}
};
// 处理滚动事件
const
handleScroll
=
()
=>
{
updateScrollState
();
};
onMounted
(
async
()
=>
{
try
{
const
chainFishboneData
=
await
getChainFishbone
(
chainId
.
value
);
fishboneData
.
value
=
chainFishboneData
??
{
text
:
""
,
causes
:
[]
};
const
chainFishboneData
=
await
getChainFishbone
(
props
.
chainId
);
fishboneData
.
value
=
chainFishboneData
?.
causes
??
[];
// 等待DOM更新后检查是否需要滚动
nextTick
(()
=>
{
if
(
scrollContainerRef
.
value
&&
fishboneRef
.
value
)
{
showScrollIndicator
.
value
=
fishboneRef
.
value
.
scrollWidth
>
scrollContainerRef
.
value
.
clientWidth
;
updateScrollState
();
}
});
console
.
log
(
"鱼骨图数据:"
,
fishboneData
.
value
);
}
catch
(
error
)
{
console
.
log
(
error
);
}
});
// 监听props中的chainId变化
watch
(
()
=>
props
.
chainId
,
async
()
=>
{
try
{
const
chainFishboneData
=
await
getChainFishbone
(
props
.
chainId
);
fishboneData
.
value
=
chainFishboneData
?.
causes
??
[];
}
catch
(
error
)
{
console
.
log
(
error
);
}
}
);
</
script
>
<
style
lang=
"scss"
scoped
>
.fishbone-wrapper
{
position
:
relative
;
width
:
100%
;
height
:
100%
;
}
.fishbone-scroll-container
{
display
:
flex
;
align-items
:
center
;
width
:
100%
;
height
:
100%
;
overflow-x
:
auto
;
overflow-y
:
hidden
;
scrollbar-width
:
thin
;
scrollbar-color
:
rgba
(
144
,
202
,
249
,
0
.5
)
transparent
;
&
:
:-
webkit-scrollbar
{
height
:
6px
;
}
&
:
:-
webkit-scrollbar-track
{
background
:
transparent
;
}
&
:
:-
webkit-scrollbar-thumb
{
background-color
:
rgba
(
144
,
202
,
249
,
0
.5
);
border-radius
:
3px
;
}
}
/* ... 原有的样式保持不变 ... */
.fishbone
{
position
:
relative
;
width
:
100%
;
width
:
fit-content
;
height
:
100%
;
margin-top
:
40px
;
min-width
:
100%
;
padding-left
:
275px
;
.main-line
{
position
:
absolute
;
top
:
280px
;
right
:
0
;
width
:
888px
;
margin-top
:
280px
;
width
:
1888px
;
height
:
3px
;
background
:
rgba
(
174
,
208
,
255
,
1
);
}
...
...
@@ -106,15 +266,6 @@ onMounted(async () => {
margin-top
:
15px
;
display
:
flex
;
justify-content
:
flex-end
;
.icon
{
margin-top
:
7px
;
width
:
20px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.text
{
margin-left
:
4px
;
height
:
70px
;
...
...
@@ -154,7 +305,7 @@ onMounted(async () => {
background
:
rgba
(
174
,
208
,
255
,
1
);
}
.text
{
width
:
100px
;
width
:
100px
;
margin-right
:
4px
;
height
:
35px
;
line-height
:
35px
;
...
...
@@ -162,15 +313,6 @@ onMounted(async () => {
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
.icon
{
margin-top
:
7px
;
width
:
20px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
}
}
}
...
...
@@ -198,17 +340,8 @@ onMounted(async () => {
margin-top
:
15px
;
display
:
flex
;
justify-content
:
flex-end
;
.icon
{
margin-top
:
7px
;
width
:
20px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.text
{
width
:
100px
;
width
:
100px
;
margin-left
:
4px
;
height
:
35px
;
line-height
:
35px
;
...
...
@@ -247,7 +380,7 @@ onMounted(async () => {
background
:
rgba
(
174
,
208
,
255
,
1
);
}
.text
{
width
:
100px
;
width
:
100px
;
margin-right
:
4px
;
height
:
35px
;
line-height
:
35px
;
...
...
@@ -255,15 +388,6 @@ onMounted(async () => {
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
.icon
{
margin-top
:
7px
;
width
:
20px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
}
}
}
...
...
@@ -291,17 +415,8 @@ onMounted(async () => {
margin-top
:
15px
;
display
:
flex
;
justify-content
:
flex-end
;
.icon
{
margin-top
:
7px
;
width
:
20px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.text
{
width
:
100px
;
width
:
100px
;
margin-left
:
4px
;
height
:
35px
;
line-height
:
35px
;
...
...
@@ -340,7 +455,7 @@ onMounted(async () => {
background
:
rgba
(
174
,
208
,
255
,
1
);
}
.text
{
width
:
100px
;
width
:
100px
;
margin-right
:
4px
;
height
:
35px
;
line-height
:
35px
;
...
...
@@ -348,15 +463,6 @@ onMounted(async () => {
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
.icon
{
margin-top
:
7px
;
width
:
20px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
}
}
}
...
...
@@ -384,17 +490,8 @@ onMounted(async () => {
margin-top
:
15px
;
display
:
flex
;
justify-content
:
flex-end
;
.icon
{
margin-top
:
7px
;
width
:
20px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.text
{
width
:
100px
;
width
:
100px
;
margin-left
:
4px
;
height
:
35px
;
line-height
:
35px
;
...
...
@@ -433,7 +530,7 @@ onMounted(async () => {
background
:
rgba
(
174
,
208
,
255
,
1
);
}
.text
{
width
:
100px
;
width
:
100px
;
margin-right
:
4px
;
height
:
35px
;
line-height
:
35px
;
...
...
@@ -441,15 +538,6 @@ onMounted(async () => {
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
.icon
{
margin-top
:
7px
;
width
:
20px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
}
}
}
...
...
@@ -477,17 +565,8 @@ onMounted(async () => {
margin-top
:
15px
;
display
:
flex
;
justify-content
:
flex-end
;
.icon
{
margin-top
:
7px
;
width
:
20px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.text
{
width
:
100px
;
width
:
100px
;
margin-left
:
4px
;
height
:
35px
;
line-height
:
35px
;
...
...
@@ -526,7 +605,7 @@ onMounted(async () => {
background
:
rgba
(
174
,
208
,
255
,
1
);
}
.text
{
width
:
100px
;
width
:
100px
;
margin-right
:
4px
;
height
:
35px
;
line-height
:
35px
;
...
...
@@ -534,15 +613,6 @@ onMounted(async () => {
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
.icon
{
margin-top
:
7px
;
width
:
20px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
}
}
}
...
...
@@ -570,17 +640,8 @@ onMounted(async () => {
margin-top
:
15px
;
display
:
flex
;
justify-content
:
flex-end
;
.icon
{
margin-top
:
7px
;
width
:
20px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.text
{
width
:
100px
;
width
:
100px
;
margin-left
:
4px
;
height
:
35px
;
line-height
:
35px
;
...
...
@@ -627,16 +688,49 @@ onMounted(async () => {
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
.icon
{
margin-top
:
7px
;
width
:
20px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
}
}
}
.scroll-indicators
{
position
:
absolute
;
top
:
50%
;
left
:
0
;
right
:
0
;
transform
:
translateY
(
-50%
);
display
:
flex
;
justify-content
:
space-between
;
pointer-events
:
none
;
padding
:
0
10px
;
z-index
:
10
;
}
.scroll-btn
{
width
:
30px
;
height
:
30px
;
border-radius
:
50%
;
background
:
rgba
(
255
,
255
,
255
,
0
.8
);
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
font-size
:
20px
;
font-weight
:
bold
;
color
:
#90caf9
;
cursor
:
pointer
;
pointer-events
:
auto
;
box-shadow
:
0
1px
4px
rgba
(
0
,
0
,
0
,
0
.2
);
transition
:
all
0
.2s
ease
;
&
:hover:not
(
.disabled
)
{
background
:
#90caf9
;
color
:
white
;
transform
:
scale
(
1
.1
);
}
&
.disabled
{
color
:
#c0c4cc
;
cursor
:
not
-
allowed
;
background
:
rgba
(
255
,
255
,
255
,
0
.5
);
}
}
</
style
>
src/views/exportControl/analysis/components/influencePanel2.vue
浏览文件 @
273f345b
...
...
@@ -25,7 +25,7 @@
<div
class=
"chartsWrap"
>
<div
class=
"right-main-content"
>
<div
class=
"right-main-content-main"
>
<Fishbone
/>
<Fishbone
:chainId=
"activeButtonId"
/>
</div>
<div
class=
"right-main-content-footer"
>
<div
class=
"footer-item1"
>
...
...
@@ -76,30 +76,12 @@ import Echarts from "@/components/Chart/index.vue";
import
Hint
from
"./hint.vue"
;
import
ButtonList
from
"@/components/buttonList/buttonList.vue"
;
import
Fishbone
from
"./fishbone.vue"
;
import
college1
from
"../../assets/images/college1.png"
;
import
college2
from
"../../assets/images/college2.png"
;
import
college3
from
"../../assets/images/college3.png"
;
import
college4
from
"../../assets/images/college4.png"
;
import
college5
from
"../../assets/images/college5.png"
;
import
college6
from
"../../assets/images/college6.png"
;
import
college7
from
"../../assets/images/college7.png"
;
import
college8
from
"../../assets/images/college8.png"
;
import
college9
from
"../../assets/images/college9.png"
;
import
college10
from
"../../assets/images/college10.png"
;
import
college11
from
"../../assets/images/college11.png"
;
import
{
getHorizontalBarChart2
}
from
"../../utils/charts"
;
import
{
getDomainDistribution
,
getChainEntities
}
from
"@/api/exportControl"
;
import
{
useRoute
}
from
"vue-router"
;
const
route
=
useRoute
();
const
buttonList
=
ref
([
{
id
:
1
,
text
:
"新能源"
},
{
id
:
2
,
text
:
"半导体"
},
{
id
:
3
,
text
:
"跨境电商"
},
{
id
:
4
,
text
:
"金融业"
},
{
id
:
5
,
text
:
"军工"
},
{
id
:
6
,
text
:
"贸易"
}
]);
const
activeButtonId
=
ref
(
buttonList
.
value
[
0
].
id
);
const
buttonList
=
ref
([]);
const
activeButtonId
=
ref
(
buttonList
.
value
[
0
]?.
id
||
1
);
const
setActiveButtonId
=
id
=>
{
activeButtonId
.
value
=
id
;
};
...
...
@@ -178,10 +160,12 @@ const fetchDomainDistribution = async () => {
horizontalBarOptions
.
value
=
getHorizontalBarChart2
(
yAxisData
,
seriesData
,
false
);
// 更新buttonList
buttonList
.
value
=
sortedData
.
map
(
item
=>
({
id
:
item
.
id
,
text
:
item
.
name
}));
buttonList
.
value
=
sortedData
.
map
(
item
=>
({
id
:
item
.
id
,
text
:
item
.
name
}))
.
sort
((
a
,
b
)
=>
a
.
id
-
b
.
id
);
console
.
log
(
"buttonList.value"
,
buttonList
.
value
);
setActiveButtonId
(
buttonList
.
value
[
0
].
id
);
}
...
...
src/views/exportControl/analysis/components/mapCharts.vue
浏览文件 @
273f345b
...
...
@@ -8,9 +8,23 @@
import
Echarts
from
"@/components/Chart/index.vue"
;
import
{
getMapOption
}
from
"../../utils/charts"
;
import
{
ref
,
onMounted
,
shallowRef
}
from
"vue"
;
import
{
getAreaDistribution
}
from
"@/api/exportControl"
;
// 这儿接收父组件传递过来的date参数
const
props
=
defineProps
({
date
:
{
type
:
String
,
default
:
""
}
});
const
mapOption
=
shallowRef
({});
onMounted
(()
=>
{
mapOption
.
value
=
getMapOption
();
// 区域分布查询
getAreaDistribution
(
props
.
date
).
then
(
res
=>
{
console
.
log
(
"res"
,
res
);
});
});
</
script
>
...
...
src/views/exportControl/analysis/components/panel1.vue
浏览文件 @
273f345b
...
...
@@ -8,6 +8,7 @@
size="mini"
v-model="domainValue"
placeholder="领域选择"
@change="handleDomainChange"
>
<el-option
v-for=
"item in domainOptions"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
>
</el-option>
...
...
@@ -24,7 +25,8 @@
</
template
>
<div
class=
"subPanel1"
>
<div
class=
"chartsWrap"
:style=
"{ paddingBottom: '10px' }"
>
<Echarts
:option=
"bar1Option"
height=
"100%"
></Echarts>
<Echarts
v-if=
"!bar1DataIsEmpty"
:option=
"bar1Option"
height=
"100%"
></Echarts>
<el-empty
v-else
description=
"暂无数据"
/>
</div>
<Hint
text=
"近几次新增受制裁实体中,中国实体占比提高,美方针对中国的出口管制风险显著增加。"
></Hint>
</div>
...
...
@@ -123,7 +125,7 @@ onMounted(async () => {
try
{
const
[
entitiesGrowthTrendData
,
entitiesUpdateCountData
]
=
await
Promise
.
all
([
getEntitiesGrowthTrend
(),
getEntitiesUpdateCount
()
getEntitiesUpdateCount
(
1
)
]);
const
list
=
_
.
reverse
(
entitiesGrowthTrendData
);
...
...
@@ -133,12 +135,25 @@ onMounted(async () => {
});
line1Option
.
value
=
getLineChart
({
xAxisData
,
seriesData
,
name
:
"增长趋势"
,
color
:
"rgba(146, 84, 222, 1)"
},
true
);
bar2Option
.
value
=
getBarChart
(
_
.
reverse
(
entitiesUpdateCountData
.
xAxis
),
_
.
reverse
(
entitiesUpdateCountData
.
series
),
[
"rgba(22, 119, 255, 1)"
,
"rgba(22, 119, 255, 0)"
],
"更新频率"
);
if
(
entitiesUpdateCountData
&&
Array
.
isArray
(
entitiesUpdateCountData
))
{
const
sortedData
=
_
.
sortBy
(
entitiesUpdateCountData
,
"year"
);
// 提取 x 轴数据(年份)
const
xAxisData
=
sortedData
.
map
(
item
=>
item
.
year
.
toString
());
// 提取 y 轴数据(数量)
const
seriesData
=
sortedData
.
map
(
item
=>
item
.
count
);
bar2Option
.
value
=
getBarChart
(
xAxisData
,
seriesData
,
[
"rgba(22, 119, 255, 1)"
,
"rgba(22, 119, 255, 0)"
],
"更新频率"
);
}
else
{
// 保持原有逻辑以防数据格式不符合预期
bar2Option
.
value
=
getBarChart
(
_
.
reverse
(
entitiesUpdateCountData
.
xAxis
),
_
.
reverse
(
entitiesUpdateCountData
.
series
),
[
"rgba(22, 119, 255, 1)"
,
"rgba(22, 119, 255, 0)"
],
"更新频率"
);
}
// 获取重点实体列表数据
await
fetchKeyEntityList
(
route
.
query
.
startTime
);
}
catch
(
err
)
{
...
...
@@ -248,11 +263,13 @@ const typeOptions = [
const
domainValue
=
ref
(
domainOptions
[
0
].
value
);
const
typeValue
=
ref
(
typeOptions
[
0
].
value
);
const
bar1Option
=
shallowRef
({});
const
bar1DataIsEmpty
=
ref
(
false
);
watch
(
[
domainValue
,
typeValue
],
async
([
domain
,
type
])
=>
{
let
EntitiesChangeCount
=
await
getEntitiesChangeCount
(
domain
,
type
);
EntitiesChangeCount
=
_
.
reverse
(
EntitiesChangeCount
);
bar1DataIsEmpty
.
value
=
EntitiesChangeCount
.
length
===
0
;
bar1Option
.
value
=
getBarChart
(
_
.
map
(
EntitiesChangeCount
,
"year"
),
_
.
map
(
EntitiesChangeCount
,
"count"
),
...
...
@@ -317,6 +334,10 @@ watch(
await
fetchKeyEntityList
(
route
.
query
.
startTime
,
newVal
);
},
300
)
);
const
handleDomainChange
=
async
domain
=>
{
await
fetchKeyEntityList
(
route
.
query
.
startTime
,
value3
.
value
,
domain
);
};
</
script
>
<
style
lang=
"scss"
scoped
>
...
...
src/views/exportControl/analysis/components/panel3.vue
浏览文件 @
273f345b
...
...
@@ -19,7 +19,7 @@
</CardCustom>
</div>
<div
class=
"row"
>
<CardCustom
title=
"历
次
制裁涉及领域数"
:style=
"
{ width: '798px', height: '422px' }">
<CardCustom
title=
"历
年
制裁涉及领域数"
:style=
"
{ width: '798px', height: '422px' }">
<div
class=
"subPanel3"
>
<div
class=
"chartsWrap"
:style=
"
{ paddingBottom: '10px' }">
<Echarts
:option=
"bar2Option"
height=
"100%"
></Echarts>
...
...
@@ -46,7 +46,12 @@ import { Search } from "@element-plus/icons-vue";
import
Echarts
from
"@/components/Chart/index.vue"
;
import
{
getBarChart
,
getLineChart
,
getPieOption1
}
from
"../../utils/charts"
;
import
Hint
from
"./hint.vue"
;
import
{
getEntitiesAreaCountByYear
,
getEntitiesDomainCount
,
getCountThisDomain
}
from
"@/api/exportControl"
;
import
{
getEntitiesAreaCountByYear
,
getEntitiesDomainCount
,
getCountThisDomain
,
getDomainDistribution
}
from
"@/api/exportControl"
;
import
_
from
"lodash"
;
import
{
useRoute
}
from
"vue-router"
;
const
route
=
useRoute
();
...
...
@@ -85,13 +90,18 @@ const fetchEntitiesDomainCount = async () => {
onMounted
(
async
()
=>
{
try
{
const
[
entitiesAreaCountByYearData
,
countThisDomainData4
,
countThisDomainData10
]
=
await
Promise
.
all
([
get
EntitiesAreaCountByYear
(
route
.
query
.
startTime
),
get
DomainDistribution
(
route
.
query
.
startTime
),
getCountThisDomain
(
"4"
),
// getEntitiesDomainCount(),
getCountThisDomain
(
"10"
)
]);
pie1Option
.
value
=
getPieOption1
(
entitiesAreaCountByYearData
??
[]);
pie1Option
.
value
=
getPieOption1
(
entitiesAreaCountByYearData
.
map
(
item
=>
({
name
:
item
.
name
,
value
:
item
.
count
}))
??
[]
);
const
list4
=
_
.
reverse
(
countThisDomainData4
??
[]);
line1Option
.
value
=
getLineChart
({
xAxisData
:
_
.
map
(
list4
,
"year"
),
...
...
src/views/exportControl/analysis/components/pieCharts.vue
浏览文件 @
273f345b
...
...
@@ -42,7 +42,7 @@ onMounted(async () => {
.
filter
(
item
=>
item
.
count
>
0
)
.
map
(
item
=>
{
return
{
name
:
item
?.
typ
e
,
name
:
item
?.
nam
e
,
value
:
item
?.
count
};
})
...
...
src/views/exportControl/analysis/content/overview.vue
浏览文件 @
273f345b
...
...
@@ -57,7 +57,7 @@
<div
class=
"panel3"
>
<div
class=
"chartWrap"
>
<PieCharts
v-if=
"panel3ActiveIndex === 1"
></PieCharts>
<MapCharts
v-if=
"panel3ActiveIndex === 2"
></MapCharts>
<MapCharts
v-if=
"panel3ActiveIndex === 2"
:date=
"route.query.startTime"
></MapCharts>
</div>
<Hint
text=
"本次制裁共新增83个实体,其中53个中国大陆实体、1个中国台湾实体。"
></Hint>
</div>
...
...
@@ -94,7 +94,7 @@
家
</div>
</div>
<div
class=
"tableWrap"
>
<div
class=
"tableWrap"
ref=
"tableWrapRef"
@
scroll=
"handleScroll"
>
<el-table
:data=
"selectEntitiesList"
class=
"sanction-table"
...
...
@@ -115,7 +115,7 @@
</
template
>
</el-table-column>
<el-table-column
prop=
"domains"
label=
"涉及领域"
width=
"1
0
0"
>
<el-table-column
prop=
"domains"
label=
"涉及领域"
width=
"1
8
0"
>
<
template
#
default=
"{ row }"
>
<div
class=
"domain-tags"
>
<el-tag
v-for=
"tag in row.domains"
:key=
"tag"
:type=
"panel5TypeMap[tag]"
>
{{
...
...
@@ -125,11 +125,11 @@
</
template
>
</el-table-column>
<el-table-column
prop=
"address"
label=
"上市地点"
width=
"90"
align=
"center"
>
<
!-- <
el-table-column prop="address" label="上市地点" width="90" align="center">
<template #default="{ row }">
{{ row.address }}
</template>
</el-table-column>
</el-table-column>
-->
<el-table-column
prop=
"time"
label=
"制裁时间"
width=
"120"
align=
"center"
>
<
template
#
default=
"{ row }"
>
...
...
@@ -137,11 +137,11 @@
</
template
>
</el-table-column>
<el-table-column
prop=
"revenue"
label=
"营收(亿元)"
width=
"100"
align=
"center"
>
<
!-- <
el-table-column prop="revenue" label="营收(亿元)" width="100" align="center">
<template #default="{ row }">
{{ row.revenue }}
</template>
</el-table-column>
</el-table-column>
-->
<el-table-column
prop=
"subCompany"
label=
"50%规则子企业"
min-width=
"140"
align=
"left"
>
<
template
#
default=
"{ row }"
>
...
...
@@ -183,7 +183,7 @@ import PieCharts from "../components/pieCharts.vue";
import
MapCharts
from
"../components/mapCharts.vue"
;
import
ButtonList
from
"@/components/buttonList/buttonList.vue"
;
import
Hint
from
"../components/hint.vue"
;
import
{
onMounted
,
reactive
,
ref
,
shallowRef
}
from
"vue"
;
import
{
onMounted
,
reactive
,
ref
,
shallowRef
,
watch
}
from
"vue"
;
import
panel1_1
from
"../../assets/images/panel1_1.png"
;
import
panel2_1
from
"../../assets/images/panel2_1.png"
;
import
panel2_2
from
"../../assets/images/panel2_2.png"
;
...
...
@@ -197,7 +197,14 @@ import panel5_5 from "../../assets/images/panel5_5.png";
import
panel5_6
from
"../../assets/images/panel5_6.png"
;
import
panel5_7
from
"../../assets/images/panel5_7.png"
;
import
panel5_8
from
"../../assets/images/panel5_8.png"
;
import
{
getOrganizationInfo
,
getPersonList
,
getSanReasonSelect
,
getSelectEntitiesList
}
from
"@/api/exportControl"
;
import
{
getOrganizationInfo
,
getPersonList
,
getSanReasonSelect
,
getSelectEntitiesList
,
getEntitiesList
}
from
"@/api/exportControl"
;
import
_
from
"lodash"
;
import
{
useRoute
}
from
"vue-router"
;
import
{
formatAnyDateToChinese
}
from
"../../utils"
;
...
...
@@ -246,15 +253,26 @@ const sanReasonSelect = shallowRef([
text
:
"将中国定位为“通过强制技术转让获取先进制程的威胁”"
}
]);
const
panel5IsChecked
=
ref
(
true
);
const
selectEntitiesList
=
shallowRef
([]);
const
currentPage
=
ref
(
1
);
const
pageSize
=
ref
(
10
);
const
total
=
ref
(
0
);
const
loading
=
ref
(
false
);
const
tableWrapRef
=
ref
(
null
);
const
noMoreData
=
ref
(
false
);
onMounted
(
async
()
=>
{
try
{
const
[
organizationInfoData
,
personListData
,
sanReasonSelectData
,
selectEntitiesLis
tData
]
=
await
Promise
.
all
([
const
[
organizationInfoData
,
sanReasonSelec
tData
]
=
await
Promise
.
all
([
getOrganizationInfo
(),
getPersonList
(),
getSanReasonSelect
(
route
.
query
.
startTime
)
,
getSelectEntitiesList
(
route
.
query
.
startTime
)
//
getPersonList(),
getSanReasonSelect
(
route
.
query
.
startTime
)
//
getSelectEntitiesList(route.query.startTime)
]);
console
.
log
(
"organizationInfoData"
,
organizationInfoData
);
organizationInfo
.
value
=
{
img
:
panel1_1
,
mingcheng
:
organizationInfoData
?.
orgNameZh
,
...
...
@@ -274,22 +292,103 @@ onMounted(async () => {
return
{
text
:
item
};
});
selectEntitiesList
.
value
=
_
.
map
(
selectEntitiesListData
,
item
=>
{
return
{
name
:
item
?.
entityNameZh
,
domains
:
item
.
techDomainList
,
// selectEntitiesList.value = _.map(selectEntitiesListData, item => {
// return {
// name: item?.entityNameZh,
// domains: item.techDomainList,
// address: "--",
// time: formatAnyDateToChinese(item?.startTime),
// isUp: true,
// revenue: "--",
// subCompany: "--",
// img: ""
// };
// });
// 初始化加载第一页数据
await
fetchEntitiesList
(
currentPage
.
value
,
pageSize
.
value
);
}
catch
(
err
)
{
console
.
log
(
err
);
}
});
// 获取实体清单数据
const
fetchEntitiesList
=
async
(
page
=
1
,
size
=
10
)
=>
{
if
(
loading
.
value
||
noMoreData
.
value
)
return
;
loading
.
value
=
true
;
try
{
const
res
=
await
getEntitiesList
(
"实体清单"
,
page
,
size
,
route
.
query
.
startTime
,
panel5IsChecked
.
value
);
if
(
res
)
{
const
newData
=
res
.
content
.
map
(
item
=>
({
...
item
,
name
:
item
.
entityNameZh
,
enName
:
item
.
entityName
,
domains
:
item
.
techDomains
,
time
:
formatAnyDateToChinese
(
item
.
startTime
),
address
:
"--"
,
time
:
formatAnyDateToChinese
(
item
?.
startTime
),
isUp
:
true
,
revenue
:
"--"
,
subCompany
:
"--"
,
img
:
""
};
});
}));
// 如果是第一页,替换数据;否则追加数据
if
(
page
===
1
)
{
selectEntitiesList
.
value
=
newData
;
}
else
{
selectEntitiesList
.
value
=
[...
selectEntitiesList
.
value
,
...
newData
];
}
total
.
value
=
res
.
totalElements
;
currentPage
.
value
=
res
.
number
+
1
;
// 检查是否还有更多数据
if
(
selectEntitiesList
.
value
.
length
>=
total
.
value
)
{
noMoreData
.
value
=
true
;
}
}
}
catch
(
err
)
{
console
.
log
(
err
);
console
.
error
(
err
);
if
(
currentPage
.
value
>
1
)
{
currentPage
.
value
--
;
}
}
finally
{
loading
.
value
=
false
;
}
});
};
watch
(
()
=>
panel5IsChecked
.
value
,
newVal
=>
{
fetchEntitiesList
(
1
,
10
);
}
);
// 处理滚动事件
const
debounceFlag
=
ref
(
false
);
const
handleScroll
=
()
=>
{
if
(
!
tableWrapRef
.
value
||
debounceFlag
.
value
)
return
;
const
{
scrollTop
,
scrollHeight
,
clientHeight
}
=
tableWrapRef
.
value
;
// 当距离底部小于50px时加载更多
if
(
scrollHeight
-
scrollTop
-
clientHeight
<
50
)
{
// 设置防抖标志
debounceFlag
.
value
=
true
;
loadMore
();
// 延迟重置防抖标志,防止连续触发
setTimeout
(()
=>
{
debounceFlag
.
value
=
false
;
},
300
);
}
};
// 加载更多数据
const
loadMore
=
()
=>
{
if
(
!
loading
.
value
&&
!
noMoreData
.
value
)
{
currentPage
.
value
++
;
fetchEntitiesList
(
currentPage
.
value
,
pageSize
.
value
);
}
};
const
panel3ActiveIndex
=
ref
(
1
);
const
setPanel3ActiveIndex
=
index
=>
{
...
...
@@ -304,7 +403,7 @@ const panel5ButtonAcitveID = ref(panel5ButtonList[0].id);
const
panel5SetButtonAcitveID
=
id
=>
{
panel5ButtonAcitveID
.
value
=
id
;
};
const
panel5IsChecked
=
ref
(
true
);
const
panel5TypeMap
=
{
人工智能
:
"danger"
,
通信网络
:
"warning"
,
...
...
@@ -662,6 +761,10 @@ const panel6 = ref([
margin-top
:
14px
;
min-height
:
0
;
overflow
:
auto
;
.domain-tags
{
display
:
flex
;
gap
:
4px
;
}
}
.name
{
display
:
flex
;
...
...
src/views/exportControl/analysis/index.vue
浏览文件 @
273f345b
...
...
@@ -35,14 +35,19 @@
</div>
<div
class=
"layout-main-header-right-box"
>
<div
class=
"right-box-top"
>
<div
class=
"time"
>
{{
"2025年7月"
}}
</div>
<div
class=
"time"
>
{{
route
.
query
.
startTime
}}
</div>
<div
class=
"name"
>
{{
"美国商务部工业与安全局"
}}
</div>
</div>
<div
class=
"right-box-bottom"
>
<el-button
type=
"plain"
size=
"large"
icon=
"Search"
@
click=
"handleSwitchActiveName('实体清单原文')"
<el-button
type=
"plain"
size=
"large"
disabled
icon=
"Search"
@
click=
"handleSwitchActiveName('实体清单原文')"
>
实体清单原文
</el-button
>
<el-button
type=
"primary"
size=
"large"
icon=
"EditPen"
>
分析报告
</el-button>
<el-button
type=
"primary"
size=
"large"
disabled
icon=
"EditPen"
>
分析报告
</el-button>
</div>
</div>
</div>
...
...
src/views/exportControl/components/info.vue
浏览文件 @
273f345b
...
...
@@ -7,7 +7,7 @@
<div
class=
"sub-title"
>
{{
subtitle
}}
</div>
</div>
<div
class=
"description"
>
{{
description
}}
</div>
<div
v-if=
"quantity > 0"
class=
"quantity"
:style=
"
{ color: color }">
{{
quantity
}}
个
</div>
<div
v-if=
"quantity > 0"
class=
"quantity"
:style=
"
{ color: color }">
{{
quantity
}}
{{
unit
||
"个"
}}
</div>
</div>
</div>
</
template
>
...
...
@@ -30,6 +30,10 @@ defineProps({
type
:
[
Number
,
String
],
default
:
0
},
unit
:
{
type
:
String
,
default
:
""
},
color
:
{
type
:
String
,
default
:
"#409EFF"
...
...
src/views/exportControl/index.vue
浏览文件 @
273f345b
...
...
@@ -67,13 +67,14 @@
</div>
<div
class=
"home-main-header-footer-info"
>
<InfoCard
v-for=
"item in infoList"
:key=
"item.title"
:title=
"item.title"
:subtitle=
"item.subTitle"
:description=
"item.des"
:quantity=
"item.num"
:color=
"item.color"
v-for=
"(item, index) in infoList"
:key=
"item.id"
:title=
"item.nameZh"
:subtitle=
"item.nameAbbr"
:description=
"item.description"
:quantity=
"item.postCount"
unit=
"次"
:color=
"infoListColor[index]"
/>
</div>
</div>
...
...
@@ -90,95 +91,80 @@
<
template
#
default
>
<div
class=
"box1"
>
<!--
<el-image
:src=
"box1Image"
alt=
""
style=
"width: 458px; height: 353px; object-fit: cover; flex-shrink: 0"
></el-image>
-->
<!--
<div
class=
"box1-right"
>
<div
class=
"box1-right-title"
>
关于进一步延长TikTok执法宽限期的行政令
</div>
<div
class=
"box1-right-tags"
>
<el-tag
type=
"primary"
>
互联网
</el-tag>
<el-tag
type=
"danger"
>
人工智能
</el-tag>
</div>
<div
class=
"box1-right-content"
>
9月16日,美国白宫官方网站发布总统政令,再次推迟(第四次)对TikTok禁令的执法,新的宽限期截止日为2025年12月16日。在宽限期内及对于宽限期前的行为,司法部不得强制执行《保护美国人免受外国对手控制应用程序法》或因此处罚相关实体(如TikTok及其分发平台)。司法部还需向提供商发出无违规和无责任的信函,并强调执行该法的权力专属联邦司法部长,意在阻止各州或私人提起诉讼。
</div>
<div
class=
"box1-right-footer"
>
<span
class=
"box1-right-footer-time"
>
2025年9月16日
</span>
<el-button
type=
"primary"
link
>
美国白宫官方网站
<el-image
src=
"./assets/images/icon-open.png"
alt=
""
style=
"width: 16px; height: 16px; margin-left: 4px"
></el-image>
</el-button>
</div>
</div>
-->
<div
class=
"box1-top"
>
<div
class=
"box1-top-title"
>
{{
entitiesDataInfoReactive
.
startTime
}}
——BIS《实体清单增列与修订条目》
</div>
<div
class=
"box1-top-content"
>
<div
class=
"box1-top-content-item"
>
<span
class=
"box1-top-content-item-title"
>
· 发布机构:
</span>
<span
class=
"box1-top-content-item-content"
>
{{
entitiesDataInfoReactive
.
orgName
}}
</span>
</div>
<div
class=
"box1-top-content-item"
>
<span
class=
"box1-top-content-item-title"
>
· 生效日期:
</span>
<span
class=
"box1-top-content-item-content"
>
{{
entitiesDataInfoReactive
.
startTime
}}
</span>
</div>
<div
class=
"box1-top-content-item"
>
<span
class=
"box1-top-content-item-title"
>
· 涉及领域:
</span>
<div
class=
"box1-top-content-item-tags"
v-for=
"item in entitiesDataInfoReactive.domains"
:key=
"item"
>
<el-tag
:type=
"
item === '航空航天' ? 'primary' : item === '人工智能' ? 'danger' : 'info'
"
>
{{
item
}}
</el-tag
>
<el-carousel
ref=
"carouselRef"
trigger=
"click"
height=
"350px"
:autoplay=
"true"
>
<el-carousel-item
v-for=
"(item, index) in entitiesDataInfoList"
:key=
"item.id + index"
>
<div>
<div
class=
"box1-top"
>
<div
class=
"box1-top-title"
>
{{
item
.
postDate
}}
——BIS《实体清单增列与修订条目》
</div>
<div
class=
"box1-top-content"
>
<div
class=
"box1-top-content-item"
>
<span
class=
"box1-top-content-item-title"
>
· 发布机构:
</span>
<span
class=
"box1-top-content-item-content"
>
{{
item
.
postOrgName
}}
</span>
</div>
<div
class=
"box1-top-content-item"
>
<span
class=
"box1-top-content-item-title"
>
· 生效日期:
</span>
<span
class=
"box1-top-content-item-content"
>
{{
item
.
postDate
}}
</span>
</div>
<div
class=
"box1-top-content-item"
>
<span
class=
"box1-top-content-item-title"
>
· 涉及领域:
</span>
<div
class=
"box1-top-content-item-tags"
v-for=
"domainItem in item.domains"
:key=
"domainItem"
>
<el-tag
:type=
"
domainItem === '航空航天'
? 'primary'
: item === '人工智能'
? 'danger'
: 'info'
"
>
{{
domainItem
}}
</el-tag
>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div
class=
"box1-bottom"
>
<div
class=
"box1-bottom-title"
>
· 涉及主要实体:
</div>
<div
class=
"box1-bottom-content"
>
<div
class=
"box1-bottom-content-item"
v-for=
"(item, index) in entitiesDataInfoReactive.entityList"
:key=
"index"
>
<el-image
v-if=
"item.img"
class=
"box1-bottom-content-item-img"
:src=
"item.img"
alt=
""
></el-image>
<div
v-else
class=
"box1-bottom-content-item-imgUndefined"
>
{{
(
item
.
name
||
item
.
enName
)?.
match
(
/
[\u
4e00-
\u
9fa5a-zA-Z0-9
]
/
)?.[
0
]
}}
<div
class=
"box1-bottom"
>
<div
class=
"box1-bottom-title"
>
· 涉及主要实体:
</div>
<div
class=
"box1-bottom-content"
>
<div
class=
"box1-bottom-content-item"
v-for=
"(ett, index) in item.sanEntities"
:key=
"index"
>
<el-image
v-if=
"ett.img"
class=
"box1-bottom-content-item-img"
:src=
"ett.img"
alt=
""
></el-image>
<div
v-else
class=
"box1-bottom-content-item-imgUndefined"
>
{{
(
ett
.
entityNameZh
||
ett
.
enName
)?.
match
(
/
[\u
4e00-
\u
9fa5a-zA-Z0-9
]
/
)?.[
0
]
}}
</div>
<div
class=
"box1-bottom-content-item-txt"
>
{{
ett
.
name
||
ett
.
entityNameZh
}}
</div>
</div>
</div>
</div>
<div
class=
"box1-absolute"
>
<div
class=
"box1-absolute-des"
>
<el-icon><Warning
color=
"rgba(206, 79, 81, 1)"
/></el-icon>
<span>
新增中国实体
</span>
</div>
<div
class=
"box1-absolute-num"
>
{{
item
.
cnEntityCount
}}
家
</div>
</div>
<div
class=
"box1-bottom-content-item-txt"
>
{{
item
.
name
||
item
.
enName
}}
</div>
</div>
</div>
</div>
<div
class=
"box1-absolute"
>
<div
class=
"box1-absolute-des"
>
<el-icon><Warning
color=
"rgba(206, 79, 81, 1)"
/></el-icon>
<span>
新增中国实体
</span>
</div>
<div
class=
"box1-absolute-num"
>
{{
entitiesDataInfoReactive
.
chNum
}}
家
</div>
</div>
</el-carousel-item>
</el-carousel>
</div>
</
template
>
</custom-container>
...
...
@@ -300,9 +286,11 @@
</div>
</
template
>
</el-table-column>
<el-table-column
label=
"重点领域"
width=
"180"
>
<el-table-column
label=
"重点领域"
width=
"180"
align=
"center"
>
<
template
#
default=
"scope"
>
<div
style=
"display: flex; align-items: center; gap: 5px"
>
<div
style=
"display: flex; justify-content: center; align-items: center; gap: 5px"
>
<el-tag
v-for=
"tag in scope.row.tags"
:key=
"tag"
...
...
@@ -334,9 +322,11 @@
</div>
</
template
>
</el-table-column>
<el-table-column
label=
"重点领域"
width=
"180"
>
<el-table-column
label=
"重点领域"
width=
"180"
align=
"center"
>
<
template
#
default=
"scope"
>
<div
style=
"display: flex; align-items: center; gap: 5px"
>
<div
style=
"display: flex; justify-content: center; align-items: center; gap: 5px"
>
<el-tag
v-for=
"tag in scope.row.tags"
:key=
"tag"
...
...
@@ -352,7 +342,7 @@
</el-table-column>
</el-table>
</div>
<div
class=
"box3-content"
>
<div
class=
"box3-content"
style=
"display: none"
>
<div
class=
"box3-content-title"
>
关键与新兴技术清单(CETs)
</div>
<el-table
:data=
"tableData1"
stripe
style=
"width: 100%"
>
<el-table-column
prop=
"year"
label=
"年份"
width=
"100"
/>
...
...
@@ -394,19 +384,19 @@
<el-row
:gutter=
"20"
style=
"width: 1600px; margin: 0 auto"
>
<el-col
:span=
"8"
>
<custom-container
title=
"制裁领域分析"
:titleIcon=
"radarIcon"
height=
"4
5
0px"
>
<custom-container
title=
"制裁领域分析"
:titleIcon=
"radarIcon"
height=
"4
8
0px"
>
<
template
#
header-right
>
<el-checkbox
v-model=
"
c
hecked"
label=
"50%规则"
size=
"large"
/>
<el-checkbox
v-model=
"
domainC
hecked"
label=
"50%规则"
size=
"large"
/>
</
template
>
<
template
#
default
>
<EChart
:option=
"radarOption"
autoresize
:style=
"
{ height: '
38
0px' }" />
<EChart
:option=
"radarOption"
autoresize
:style=
"
{ height: '
45
0px' }" />
</
template
>
</custom-container>
</el-col>
<el-col
:span=
"16"
>
<custom-container
title=
"制裁清单数量增长趋势"
:titleIcon=
"qushiIcon"
height=
"4
5
0px"
>
<custom-container
title=
"制裁清单数量增长趋势"
:titleIcon=
"qushiIcon"
height=
"4
8
0px"
>
<
template
#
header-right
>
<el-checkbox
v-model=
"
c
hecked"
label=
"50%规则"
size=
"large"
/>
<el-checkbox
v-model=
"
trendC
hecked"
label=
"50%规则"
size=
"large"
/>
</
template
>
<
template
#
default
>
<EChart
:option=
"trendOption"
autoresize
:style=
"
{ height: '400px' }" />
...
...
@@ -421,23 +411,25 @@
<custom-container
title=
"历次制裁过程"
:titleIcon=
"listIcon"
height=
"845px"
>
<
template
#
default
>
<div
class=
"box4"
>
<div
class=
"box4-item"
v-for=
"(item, idx) in sanctionProcessList"
:key=
"item.title"
>
<div
class=
"box4-item-left"
>
<el-image
:src=
"dotIcon"
alt=
"图片"
class=
"box4-item-left-icon"
/>
<div
class=
"box4-item-left-line"
v-if=
"idx + 1 != sanctionProcessList.length"
></div>
</div>
<div
class=
"box4-item-right"
>
<div
class=
"box4-item-right-header"
>
<span
class=
"box4-item-right-header-title"
>
{{
item
.
title
}}
</span>
<span
class=
"box4-item-right-header-desc"
>
{{
item
.
desc
}}
</span>
<div
style=
"height: 90%; overflow-y: auto; padding-top: 10px"
>
<div
class=
"box4-item"
v-for=
"(item, idx) in sanctionProcessList"
:key=
"item.title"
>
<div
class=
"box4-item-left"
>
<el-image
:src=
"dotIcon"
alt=
"图片"
class=
"box4-item-left-icon"
/>
<div
class=
"box4-item-left-line"
v-if=
"idx + 1 != sanctionProcessList.length"
></div>
</div>
<div
class=
"box4-item-right-content"
>
{{
item
.
content
}}
<div
class=
"box4-item-right"
>
<div
class=
"box4-item-right-header"
@
click=
"handleSanc(item)"
>
<span
class=
"box4-item-right-header-title"
>
{{
item
.
title
}}
</span>
<span
class=
"box4-item-right-header-desc"
>
{{
item
.
desc
}}
</span>
</div>
<div
class=
"box4-item-right-content"
>
{{
item
.
content
}}
</div>
</div>
</div>
</div>
<div
class=
"box4-footer"
:style=
"
{ marginTop: sanctionProcessList.length > 0 ? '0px' : 'auto' }">
<el-button
type=
"primary"
link
:icon=
"DownRight"
<el-button
type=
"primary"
link
:icon=
"DownRight"
@
click=
"handleGetMore"
>
查看更多
<el-icon><DArrowRight
/></el-icon>
</el-button>
...
...
@@ -470,7 +462,7 @@
<el-table-column
prop=
"name"
label=
"实体名称"
min-width=
"200"
>
<
template
#
default=
"scope"
>
<div
class=
"tableName"
>
<div
class=
"tableName"
@
click=
"handleCompClick(scope.row)"
>
<el-image
v-if=
"scope.row.img"
class=
"box1-bottom-content-item-img"
...
...
@@ -571,7 +563,7 @@
</template>
<
script
setup
>
import
{
onMounted
,
ref
,
computed
,
reactive
,
shallowRef
}
from
"vue"
;
import
{
onMounted
,
ref
,
computed
,
reactive
,
shallowRef
,
watch
}
from
"vue"
;
import
scrollToTop
from
"@/utils/scrollToTop"
;
import
*
as
echarts
from
"echarts"
;
import
setChart
from
"@/utils/setChart"
;
...
...
@@ -645,50 +637,45 @@ import { getMultipleBarChart_m } from "./utils/charts";
import
{
formatAnyDateToChinese
}
from
"./utils"
;
import
_
from
"lodash"
;
const
handleCompClick
=
item
=>
{
console
.
log
(
"item"
,
item
);
const
route
=
router
.
resolve
({
path
:
"/companyPages"
,
query
:
{
id
:
item
.
id
}
});
window
.
open
(
route
.
href
,
"_blank"
);
};
const
tagsType
=
[
"primary"
,
"success"
,
"info"
,
"warning"
,
"danger"
];
//数据定义
const
entitiesDataInfoReactive
=
shallowRef
({
chNum
:
undefined
,
entityList
:
[],
domains
:
[],
startTime
:
""
,
rawStartTime
:
""
,
orgName
:
""
});
const
entitiesDataInfoList
=
shallowRef
([]);
// 趋势图
const
trendOption
=
ref
({});
const
trendChecked
=
ref
(
false
);
// 发布频度
const
tableData1
=
ref
([]);
// 历次制裁过程
const
sanctionProcessList
=
ref
([]);
const
sanctionPage
=
ref
(
1
);
// 制裁实体清单
const
entitiesList
=
ref
([]);
onMounted
(
async
()
=>
{
try
{
const
[
dataCount
,
entitiesDataInfo
,
industryCountByYear
,
countDomainByYear
,
sanctionsInfoCount
,
entityBody
]
=
await
Promise
.
all
([
getEntitiesDataCount
(),
getEntitiesDataInfo
(),
getIndustryCountByYear
(),
getCountDomainByYear
()
// getSanctionsInfoCount()
// getEntitiesList("实体清单")
]);
infoList
.
value
[
0
].
num
=
dataCount
;
const
[
dataCount
,
entitiesDataInfo
,
industryCountByYear
,
countDomainByYear
]
=
await
Promise
.
all
([
getEntitiesDataCount
(),
getEntitiesDataInfo
(),
getIndustryCountByYear
(
1
),
getCountDomainByYear
(
trendChecked
.
value
)
]);
infoList
.
value
=
dataCount
;
const
entityList
=
_
.
map
(
entitiesDataInfo
?.
sanEntities
??
[],
({
entityNameZh
,
entityName
})
=>
{
return
{
name
:
entityNameZh
,
enName
:
entityName
};
});
entitiesDataInfoReactive
.
value
=
{
entityList
,
chNum
:
entitiesDataInfo
?.
cnEntityCount
,
domains
:
entitiesDataInfo
?.
domains
??
[],
// startTime: formatAnyDateToChinese(entitiesDataInfo?.startTime ?? ""),
startTime
:
entitiesDataInfo
.
postDate
,
rawStartTime
:
entitiesDataInfo
?.
startTime
??
""
,
orgName
:
entitiesDataInfo
?.
postOrgName
};
entitiesDataInfoList
.
value
=
entitiesDataInfo
||
[];
const
list
=
_
.
chain
(
industryCountByYear
).
filter
(
"year"
).
orderBy
(
"year"
,
"desc"
).
value
();
const
total
=
_
.
sumBy
(
list
,
"count"
);
tableData1
.
value
=
_
.
map
(
list
,
item
=>
{
...
...
@@ -699,8 +686,12 @@ onMounted(async () => {
tags
:
item
.
domain
};
}).
slice
(
0
,
5
);
console
.
log
(
"tableData1"
,
tableData1
.
value
);
trendOption
.
value
=
getMultipleBarChart_m
(
countDomainByYear
);
console
.
log
(
"countDomainByYear"
,
countDomainByYear
);
// 整理柱状图数据并应用到趋势图
if
(
countDomainByYear
&&
countDomainByYear
[
0
].
yearDomainCount
)
{
trendOption
.
value
=
processYearDomainCountData
(
countDomainByYear
[
0
].
yearDomainCount
);
}
// trendOption.value = getMultipleBarChart_m(countDomainByYear);
// sanctionProcessList.value = _.map(_.slice(sanctionsInfoCount, 0, 5), item => {
// return {
// title: item.tittle,
...
...
@@ -711,9 +702,9 @@ onMounted(async () => {
// };
// });
await
fetchEntitiesList
(
currentPage
.
value
,
pageSize
.
value
);
await
fetchSanctionProcess
(
1
,
pageSize
.
value
);
await
fetchSanctionProcess
(
sanctionPage
.
value
,
10
);
// 获取雷达图数据
await
fetchRadarData
();
await
fetchRadarData
(
domainChecked
.
value
);
// console.log("entitiesList entitiesList", entityBody);
// entitiesList.value = _.map(entityBody.content, item => {
// return {
...
...
@@ -729,67 +720,93 @@ onMounted(async () => {
console
.
log
(
err
);
}
});
// 新增函数:处理 yearDomainCount 数据并使用 getMultipleBarChart_m 方法生成图表配置
const
processYearDomainCountData
=
yearDomainCountData
=>
{
// 提取所有年份并排序
const
years
=
[...
new
Set
(
yearDomainCountData
.
map
(
item
=>
item
.
year
))].
sort
();
// 提取所有领域名称
const
allDomains
=
[...
new
Set
(
yearDomainCountData
.
flatMap
(
item
=>
item
.
domainCountInfo
.
map
(
domain
=>
domain
.
name
)))];
// 构造 getMultipleBarChart_m 所需的数据结构
const
chartData
=
{
domains
:
allDomains
,
data
:
years
.
map
(
year
=>
{
const
yearData
=
yearDomainCountData
.
find
(
item
=>
item
.
year
===
year
);
const
domainCounts
=
{};
// 初始化所有领域的计数为0
allDomains
.
forEach
(
domain
=>
{
domainCounts
[
domain
]
=
0
;
});
// 填充实际数据
if
(
yearData
&&
yearData
.
domainCountInfo
)
{
yearData
.
domainCountInfo
.
forEach
(
domain
=>
{
domainCounts
[
domain
.
name
]
=
domain
.
count
;
});
}
return
{
year
:
year
,
domainNum
:
domainCounts
};
})
};
// 使用 getMultipleBarChart_m 生成图表配置
return
getMultipleBarChart_m
(
chartData
);
};
watch
(
()
=>
trendChecked
.
value
,
async
checked
=>
{
const
res
=
await
getCountDomainByYear
(
checked
);
// if (res && Array.isArray(res) && res.length > 0) {
// trendOption.value = getMultipleBarChart_m(res);
// }
// 整理数据并更新趋势图
if
(
res
&&
res
.
yearDomainCount
)
{
trendOption
.
value
=
processYearDomainCountData
(
res
[
0
].
yearDomainCount
);
}
}
);
// 返回首页
const
handleBackHome
=
()
=>
{
router
.
push
({
path
:
"/overview"
});
};
const
carouselRef
=
ref
(
null
);
const
handleToDetail
=
()
=>
{
// router.push({
// path: "/exportControlAnalysis"
// });
// router.push({
// path: "/exportControl/analysis"
// });
let
activeIndex
=
0
;
if
(
carouselRef
.
value
)
{
activeIndex
=
carouselRef
.
value
.
activeIndex
;
}
const
route
=
router
.
resolve
({
path
:
"/exportControlAnalysis"
,
query
:
{
startTime
:
entitiesDataInfoReactive
.
value
.
startTime
}
});
window
.
open
(
route
.
href
,
"_blank"
);
console
.
log
(
"当前 Carousel 激活索引:"
,
activeIndex
);
// 使用当前激活项的数据
const
currentItem
=
entitiesDataInfoList
.
value
[
activeIndex
];
if
(
currentItem
)
{
const
route
=
router
.
resolve
({
path
:
"/exportControlAnalysis"
,
query
:
{
startTime
:
currentItem
.
postDate
}
});
window
.
open
(
route
.
href
,
"_blank"
);
}
};
const
billList
=
ref
([]);
const
curBillListIndex
=
ref
(
0
);
const
searchKey
=
ref
(
""
);
const
infoList
=
ref
([
{
title
:
"实体清单"
,
subTitle
:
"Entity List"
,
des
:
"美国商务部工业与安全局依据《出口管理条例》建立的出口管制机制"
,
num
:
null
,
color
:
"rgba(206, 79, 81, 1)"
},
{
title
:
"商业管制清单 "
,
subTitle
:
"CCL"
,
des
:
"美国《出口管制条例》中列明受管制军民两用物项的清单"
,
num
:
253
,
// color: "rgba(114, 46, 209, 1)"
color
:
"rgba(132, 136, 142, 1)"
},
{
title
:
"关键与新兴技术清单"
,
subTitle
:
"CETs"
,
des
:
"美国为维护其技术领导地位与国家安全而制定的18项优先发展技术清单"
,
num
:
52
,
// color: "rgba(250, 140, 22, 1)"
color
:
"rgba(132, 136, 142, 1)"
},
{
title
:
"军事最终用户清单 "
,
subTitle
:
"MEU"
,
des
:
"美国商务部制定的限制特定外国实体获取可能用于军事用途的美国技术的清单"
,
num
:
0
,
color
:
"rgba(132, 136, 142, 1)"
}
]);
const
infoListColor
=
ref
([
"rgba(206, 79, 81, 1)"
,
"rgba(132, 136, 142, 1)"
,
"rgba(132, 136, 142, 1)"
,
"rgba(132, 136, 142, 1)"
]);
const
infoList
=
ref
([]);
const
entityList
=
ref
([
{
...
...
@@ -865,15 +882,20 @@ const customNewsData = ref([
]);
// 雷达图
const
domainChecked
=
ref
(
false
);
const
radarOption
=
ref
({
title
:
{
text
:
""
},
legend
:
{
top
:
0
,
top
:
"0%"
,
icon
:
"circle"
,
data
:
[
"实体清单"
,
"商业管制清单"
,
"关键和新型技术清单"
]
},
grid
:
{
top
:
"15%"
,
containLabel
:
true
},
radar
:
{
// shape: 'circle',
indicator
:
[
...
...
@@ -923,9 +945,9 @@ const radarOption = ref({
});
// 获取雷达图数据
const
fetchRadarData
=
async
()
=>
{
const
fetchRadarData
=
async
checked
=>
{
try
{
const
data
=
await
getSanDomainCount
();
const
data
=
await
getSanDomainCount
(
checked
);
if
(
data
&&
Array
.
isArray
(
data
)
&&
data
.
length
>
0
)
{
// 收集所有可能的领域名称
const
allDomains
=
new
Set
();
...
...
@@ -984,6 +1006,11 @@ const fetchRadarData = async () => {
}
};
watch
(
()
=>
domainChecked
.
value
,
()
=>
fetchRadarData
(
domainChecked
.
value
)
);
// 进度条状态
const
getStatus
=
_percent
=>
{
const
percent
=
_percent
*
100
;
...
...
@@ -1020,12 +1047,37 @@ const fetchEntitiesList = async (page = 1, size = 10) => {
}
};
const
handleGetMore
=
async
()
=>
{
sanctionPage
.
value
++
;
try
{
const
res
=
await
getSanctionProcess
(
"实体清单"
,
sanctionPage
.
value
,
10
);
if
(
res
&&
res
.
content
)
{
// 将新数据合并到现有列表中
const
newData
=
res
.
content
.
map
(
item
=>
({
...
item
,
title
:
item
.
name
,
desc
:
`
${
item
.
cnEntityCount
}
家中国实体`
,
content
:
item
.
summary
||
"2025年3月25日,美国商务部工业与安全局以从事有悖于美国国家安全和外交政策利益的活动为由,宣布将来自中国的54家实体新增至“实体清单”。"
}));
// 合并新数据到现有列表
sanctionProcessList
.
value
=
[...
sanctionProcessList
.
value
,
...
newData
];
}
}
catch
(
err
)
{
console
.
error
(
err
);
// 如果请求失败,回退页码
sanctionPage
.
value
--
;
}
};
// 获取历次制裁过程数据
const
fetchSanctionProcess
=
async
(
page
=
1
,
size
=
10
)
=>
{
try
{
const
res
=
await
getSanctionProcess
(
"实体清单"
,
page
,
size
);
if
(
res
)
{
sanctionProcessList
.
value
=
res
.
content
.
slice
(
0
,
5
).
map
(
item
=>
({
sanctionProcessList
.
value
=
res
.
content
.
map
(
item
=>
({
...
item
,
title
:
item
.
name
,
desc
:
`
${
item
.
cnEntityCount
}
家中国实体`
,
...
...
@@ -1416,6 +1468,17 @@ const chart1Data = ref({
]
});
const
handleSanc
=
item
=>
{
console
.
log
(
item
);
const
route
=
router
.
resolve
({
path
:
"/exportControlAnalysis"
,
query
:
{
startTime
:
item
.
postDate
}
});
window
.
open
(
route
.
href
,
"_blank"
);
};
// 获取热门法案
const
handleGetHotBills
=
async
()
=>
{
try
{
...
...
@@ -1742,8 +1805,9 @@ onMounted(async () => {
.box3
{
display
:
flex
;
justify-content
:
space-between
;
//
justify-content: space-between;
align-items
:
flex-start
;
gap
:
60px
;
.box3-content-title
{
font-size
:
18px
;
font-weight
:
700
;
...
...
@@ -1769,7 +1833,10 @@ onMounted(async () => {
overflow
:
auto
;
display
:
flex
;
flex-direction
:
column
;
justify-content
:
space-between
;
padding-top
:
16px
;
// padding-bottom: 50px;
position
:
relative
;
.box4-item
{
display
:
flex
;
gap
:
10px
;
...
...
@@ -1802,6 +1869,7 @@ onMounted(async () => {
position
:
relative
;
top
:
-7
.5px
;
padding-bottom
:
8px
;
cursor
:
pointer
;
&
-title
{
font-size
:
18px
;
color
:
$base-color
;
...
...
@@ -1827,14 +1895,15 @@ onMounted(async () => {
}
}
.box4-footer
{
margin-top
:
auto
;
position
:
absolute
;
// margin-top: auto;
display
:
flex
;
justify-content
:
center
;
align-items
:
center
;
bottom
:
30px
;
left
:
50%
;
margin-left
:
-
2
0px
;
margin-bottom
:
30px
;
margin-left
:
-
3
0px
;
//
margin-bottom: 30px;
}
}
...
...
@@ -2550,6 +2619,7 @@ onMounted(async () => {
display
:
flex
;
align-items
:
center
;
gap
:
10px
;
cursor
:
pointer
;
.box1-bottom-content-item-imgUndefined
{
width
:
24px
;
height
:
24px
;
...
...
src/views/exportControl/utils/charts.js
浏览文件 @
273f345b
import
*
as
echarts
from
'echarts'
;
import
chinaJson
from
'./China.json'
import
_
from
'lodash'
;
import
*
as
echarts
from
"echarts"
;
import
chinaJson
from
"./China.json"
;
import
_
from
"lodash"
;
//饼图
export
function
getPieOption
(
data
,
title
)
{
let
option
=
{
color
:
[
"#4096ff"
,
"#b37feb"
,
"#ff7875"
,
"#85a5ff"
,
"#69b1ff"
,
"#ffc069"
,
"#87e8de"
],
title
:
{
text
:
title
,
top
:
10
,
left
:
10
,
textStyle
:
{
color
:
"rgba(59, 65, 75, 1)"
,
fontSize
:
16
,
fontWeight
:
700
}
},
series
:
[
{
type
:
'pie'
,
radius
:
[
75
,
132
],
height
:
'100%'
,
center
:
[
'50%'
,
'50%'
],
width
:
'100%'
,
itemStyle
:
{
borderColor
:
'#fff'
,
borderWidth
:
1
},
label
:
{
alignTo
:
'edge'
,
formatter
:
'{b} {d}%'
,
minMargin
:
5
,
edgeDistance
:
10
,
lineHeight
:
15
,
rich
:
{
time
:
{
fontSize
:
10
,
color
:
'#999'
}
}
},
labelLine
:
{
length
:
15
,
length2
:
0
,
maxSurfaceAngle
:
80
},
labelLayout
:
function
(
params
)
{
const
isLeft
=
params
.
labelRect
.
x
<
556
/
2
;
const
points
=
params
.
labelLinePoints
;
// Update the end point.
points
[
2
][
0
]
=
isLeft
?
params
.
labelRect
.
x
:
params
.
labelRect
.
x
+
params
.
labelRect
.
width
;
return
{
labelLinePoints
:
points
};
},
data
:
data
}]
}
return
option
let
option
=
{
color
:
[
"#4096ff"
,
"#b37feb"
,
"#ff7875"
,
"#85a5ff"
,
"#69b1ff"
,
"#ffc069"
,
"#87e8de"
],
title
:
{
text
:
title
,
top
:
10
,
left
:
10
,
textStyle
:
{
color
:
"rgba(59, 65, 75, 1)"
,
fontSize
:
16
,
fontWeight
:
700
}
},
series
:
[
{
type
:
"pie"
,
radius
:
[
75
,
132
],
height
:
"100%"
,
center
:
[
"50%"
,
"50%"
],
width
:
"100%"
,
itemStyle
:
{
borderColor
:
"#fff"
,
borderWidth
:
1
},
label
:
{
alignTo
:
"edge"
,
formatter
:
"{b} {d}%"
,
minMargin
:
5
,
edgeDistance
:
10
,
lineHeight
:
15
,
rich
:
{
time
:
{
fontSize
:
10
,
color
:
"#999"
}
}
},
labelLine
:
{
length
:
15
,
length2
:
0
,
maxSurfaceAngle
:
80
},
labelLayout
:
function
(
params
)
{
const
isLeft
=
params
.
labelRect
.
x
<
556
/
2
;
const
points
=
params
.
labelLinePoints
;
// Update the end point.
points
[
2
][
0
]
=
isLeft
?
params
.
labelRect
.
x
:
params
.
labelRect
.
x
+
params
.
labelRect
.
width
;
return
{
labelLinePoints
:
points
};
},
data
:
data
}
]
};
return
option
;
}
export
function
getPieOption1
(
data
,
title
)
{
let
option
=
{
color
:
[
"#4096ff"
,
"#b37feb"
,
"#ff7875"
,
"#85a5ff"
,
"#69b1ff"
,
"#ffc069"
,
"#87e8de"
],
title
:
{
text
:
title
,
top
:
10
,
left
:
10
,
textStyle
:
{
color
:
"rgba(59, 65, 75, 1)"
,
fontSize
:
16
,
fontWeight
:
700
}
},
series
:
[
{
type
:
'pie'
,
radius
:
[
70
,
110
],
height
:
'100%'
,
center
:
[
'50%'
,
'50%'
],
width
:
'100%'
,
itemStyle
:
{
borderColor
:
'#fff'
,
borderWidth
:
1
},
label
:
{
alignTo
:
'edge'
,
formatter
:
`{b}
${
data
.
length
<
10
?
'
\
n'
:
''
}
{two|{c}家 {d}%}`
,
fontSize
:
17.6
,
fontWeight
:
700
,
minMargin
:
5
,
edgeDistance
:
10
,
lineHeight
:
23
,
rich
:
{
two
:
{
fontSize
:
15
,
color
:
' rgba(95, 101, 108, 1)'
,
}
}
},
labelLine
:
{
length
:
15
,
length2
:
0
,
maxSurfaceAngle
:
80
},
labelLayout
:
function
(
params
)
{
console
.
log
(
'labelLayoutparams'
,
params
)
const
isLeft
=
params
.
labelRect
.
x
<
556
/
2
;
const
points
=
params
.
labelLinePoints
;
// Update the end point.
points
[
2
][
0
]
=
isLeft
?
data
.
length
<
10
?
params
.
labelRect
.
x
:
(
params
.
labelRect
.
x
+
params
.
labelRect
.
width
)
:
data
.
length
<
10
?
(
params
.
labelRect
.
x
+
params
.
labelRect
.
width
)
:
params
.
labelRect
.
x
;
return
{
labelLinePoints
:
points
};
},
data
:
data
}]
}
return
option
let
option
=
{
color
:
[
"#4096ff"
,
"#b37feb"
,
"#ff7875"
,
"#85a5ff"
,
"#69b1ff"
,
"#ffc069"
,
"#87e8de"
],
title
:
{
text
:
title
,
top
:
10
,
left
:
10
,
textStyle
:
{
color
:
"rgba(59, 65, 75, 1)"
,
fontSize
:
16
,
fontWeight
:
700
}
},
series
:
[
{
type
:
"pie"
,
radius
:
[
70
,
110
],
height
:
"100%"
,
center
:
[
"50%"
,
"50%"
],
width
:
"100%"
,
itemStyle
:
{
borderColor
:
"#fff"
,
borderWidth
:
1
},
label
:
{
alignTo
:
"edge"
,
formatter
:
`{b}
${
data
.
length
<
10
?
"
\
n"
:
""
}
{two|{c}家 {d}%}`
,
fontSize
:
17.6
,
fontWeight
:
700
,
minMargin
:
5
,
edgeDistance
:
10
,
lineHeight
:
23
,
rich
:
{
two
:
{
fontSize
:
15
,
color
:
" rgba(95, 101, 108, 1)"
}
}
},
labelLine
:
{
length
:
15
,
length2
:
0
,
maxSurfaceAngle
:
80
},
labelLayout
:
function
(
params
)
{
console
.
log
(
"labelLayoutparams"
,
params
);
const
isLeft
=
params
.
labelRect
.
x
<
556
/
2
;
const
points
=
params
.
labelLinePoints
;
// Update the end point.
points
[
2
][
0
]
=
isLeft
?
data
.
length
<
10
?
params
.
labelRect
.
x
:
params
.
labelRect
.
x
+
params
.
labelRect
.
width
:
data
.
length
<
10
?
params
.
labelRect
.
x
+
params
.
labelRect
.
width
:
params
.
labelRect
.
x
;
return
{
labelLinePoints
:
points
};
},
data
:
data
}
]
};
return
option
;
}
export
function
getPieOption2
(
data
,
title
)
{
let
option
=
{
color
:
[
"#4096ff"
,
"#b37feb"
,
"#ff7875"
,
"#85a5ff"
,
"#69b1ff"
,
"#ffc069"
,
"#87e8de"
],
title
:
{
text
:
title
,
top
:
10
,
left
:
10
,
textStyle
:
{
color
:
"rgba(59, 65, 75, 1)"
,
fontSize
:
16
,
fontWeight
:
700
}
},
legend
:
{
icon
:
'rect'
,
top
:
'center'
,
right
:
'40'
,
orient
:
'vertical'
,
itemWidth
:
30
,
itemHeight
:
20
,
borderRadius
:
2
,
formatter
:
function
(
name
)
{
// 获取系列数据,假设第一个系列为饼图
let
seriesData
=
option
.
series
[
0
].
data
;
// [citation:8]
// 也可以考虑使用 this.getSeries()[0].data [citation:8]
let
currentValue
;
// 计算数据总和并查找当前图例名对应的数值
seriesData
.
forEach
(
item
=>
{
if
(
item
.
name
===
name
)
{
currentValue
=
item
.
value
;
}
});
return
`
${
name
}
${
currentValue
}
%`
},
itemGap
:
10
,
textStyle
:
{
color
:
'rgba(59, 65, 75 ,0.8)'
,
fontSize
:
18
,
fontWeight
:
500
},
},
series
:
[
{
type
:
'pie'
,
radius
:
[
70
,
120
],
height
:
'100%'
,
center
:
[
'33%'
,
'50%'
],
width
:
'100%'
,
itemStyle
:
{
borderColor
:
'#fff'
,
borderWidth
:
1
},
emphasis
:
{
scale
:
false
,
},
label
:
{
show
:
false
,
},
data
:
data
}]
}
return
option
let
option
=
{
color
:
[
"#4096ff"
,
"#b37feb"
,
"#ff7875"
,
"#85a5ff"
,
"#69b1ff"
,
"#ffc069"
,
"#87e8de"
],
title
:
{
text
:
title
,
top
:
10
,
left
:
10
,
textStyle
:
{
color
:
"rgba(59, 65, 75, 1)"
,
fontSize
:
16
,
fontWeight
:
700
}
},
legend
:
{
icon
:
"rect"
,
top
:
"center"
,
right
:
"40"
,
orient
:
"vertical"
,
itemWidth
:
30
,
itemHeight
:
20
,
borderRadius
:
2
,
formatter
:
function
(
name
)
{
// 获取系列数据,假设第一个系列为饼图
let
seriesData
=
option
.
series
[
0
].
data
;
// [citation:8]
// 也可以考虑使用 this.getSeries()[0].data [citation:8]
let
currentValue
;
// 计算数据总和并查找当前图例名对应的数值
seriesData
.
forEach
(
item
=>
{
if
(
item
.
name
===
name
)
{
currentValue
=
item
.
value
;
}
});
return
`
${
name
}
${
currentValue
}
%`
;
},
itemGap
:
10
,
textStyle
:
{
color
:
"rgba(59, 65, 75 ,0.8)"
,
fontSize
:
18
,
fontWeight
:
500
}
},
series
:
[
{
type
:
"pie"
,
radius
:
[
70
,
120
],
height
:
"100%"
,
center
:
[
"33%"
,
"50%"
],
width
:
"100%"
,
itemStyle
:
{
borderColor
:
"#fff"
,
borderWidth
:
1
},
emphasis
:
{
scale
:
false
},
label
:
{
show
:
false
},
data
:
data
}
]
};
return
option
;
}
export
function
getMapOption
()
{
echarts
.
registerMap
(
'china'
,
chinaJson
);
let
data
=
[{
name
:
'2256'
,
value
:
2256
},
{
name
:
'578'
,
value
:
578
},
{
name
:
'744'
,
value
:
744
},
{
name
:
'806'
,
value
:
806
},
{
name
:
'336'
,
value
:
336
},
{
name
:
'325'
,
value
:
325
},
{
name
:
'487'
,
value
:
487
},
{
name
:
'343'
,
value
:
343
},
{
name
:
'432'
,
value
:
432
},
{
name
:
'273'
,
value
:
273
},
{
name
:
'1055'
,
value
:
1055
},
{
name
:
'590'
,
value
:
590
},
{
name
:
'319'
,
value
:
319
},
{
name
:
'349'
,
value
:
349
},
{
name
:
'126'
,
value
:
126
},
{
name
:
'97'
,
value
:
97
},
{
name
:
'201'
,
value
:
201
},
{
name
:
'398'
,
value
:
398
},
{
name
:
'795'
,
value
:
795
},
{
name
:
'655'
,
value
:
655
},
{
name
:
'295'
,
value
:
295
},
{
name
:
'311'
,
value
:
311
},
{
name
:
'993'
,
value
:
993
},
{
name
:
'601'
,
value
:
601
},
{
name
:
'275'
,
value
:
275
},
{
name
:
'317'
,
value
:
317
},
{
name
:
'1000'
,
value
:
1000
},
{
name
:
'186'
,
value
:
186
},
{
name
:
'261'
,
value
:
261
},
{
name
:
'132'
,
value
:
132
},
{
name
:
'18'
,
value
:
18
},
{
name
:
'11'
,
value
:
11
},];
echarts
.
registerMap
(
"china"
,
chinaJson
);
let
data
=
[
{
name
:
"2256"
,
value
:
2256
},
{
name
:
"578"
,
value
:
578
},
{
name
:
"744"
,
value
:
744
},
{
name
:
"806"
,
value
:
806
},
{
name
:
"336"
,
value
:
336
},
{
name
:
"325"
,
value
:
325
},
{
name
:
"487"
,
value
:
487
},
{
name
:
"343"
,
value
:
343
},
{
name
:
"432"
,
value
:
432
},
{
name
:
"273"
,
value
:
273
},
{
name
:
"1055"
,
value
:
1055
},
{
name
:
"590"
,
value
:
590
},
{
name
:
"319"
,
value
:
319
},
{
name
:
"349"
,
value
:
349
},
{
name
:
"126"
,
value
:
126
},
{
name
:
"97"
,
value
:
97
},
{
name
:
"201"
,
value
:
201
},
{
name
:
"398"
,
value
:
398
},
{
name
:
"795"
,
value
:
795
},
{
name
:
"655"
,
value
:
655
},
{
name
:
"295"
,
value
:
295
},
{
name
:
"311"
,
value
:
311
},
{
name
:
"993"
,
value
:
993
},
{
name
:
"601"
,
value
:
601
},
{
name
:
"275"
,
value
:
275
},
{
name
:
"317"
,
value
:
317
},
{
name
:
"1000"
,
value
:
1000
},
{
name
:
"186"
,
value
:
186
},
{
name
:
"261"
,
value
:
261
},
{
name
:
"132"
,
value
:
132
},
{
name
:
"18"
,
value
:
18
},
{
name
:
"11"
,
value
:
11
}
];
let
geoCoordMap
=
{
'2256'
:
[
116.46
,
39.92
],
'578'
:
[
121.29
,
31.14
],
'744'
:
[
117.2
,
39.13
],
'806'
:
[
106.32
,
29.32
],
'336'
:
[
126.41
,
45.45
],
'325'
:
[
125.19
,
43.52
],
'487'
:
[
123.24
,
41.50
],
'343'
:
[
111.48
,
40.49
],
'432'
:
[
114.28
,
38.02
],
'273'
:
[
112.34
,
37.52
],
'1055'
:
[
117
,
36.38
],
'590'
:
[
113.42
,
34.48
],
'319'
:
[
108.54
,
34.16
],
'349'
:
[
103.49
,
36.03
],
'126'
:
[
106.16
,
38.20
],
'97'
:
[
101.45
,
36.38
],
'201'
:
[
87.36
,
43.48
],
'398'
:
[
117.18
,
31.51
],
'795'
:
[
118.50
,
32.02
],
'655'
:
[
120.09
,
30.14
],
'295'
:
[
113
,
28.11
],
'311'
:
[
115.52
,
28.41
],
'993'
:
[
114.21
,
30.37
],
'601'
:
[
104.05
,
30.39
],
'275'
:
[
106.42
,
26.35
],
'317'
:
[
119.18
,
26.05
],
'1000'
:
[
113.15
,
23.08
],
'186'
:
[
110.20
,
20.02
],
'261'
:
[
108.20
,
22.48
],
'132'
:
[
102.41
,
25
],
'18'
:
[
91.10
,
29.40
],
'11'
:
[
114.10
,
22.18
],
};
let
geoCoordMap
=
{
2256
:
[
116.46
,
39.92
],
578
:
[
121.29
,
31.14
],
744
:
[
117.2
,
39.13
],
806
:
[
106.32
,
29.32
],
336
:
[
126.41
,
45.45
],
325
:
[
125.19
,
43.52
],
487
:
[
123.24
,
41.5
],
343
:
[
111.48
,
40.49
],
432
:
[
114.28
,
38.02
],
273
:
[
112.34
,
37.52
],
1055
:
[
117
,
36.38
],
590
:
[
113.42
,
34.48
],
319
:
[
108.54
,
34.16
],
349
:
[
103.49
,
36.03
],
126
:
[
106.16
,
38.2
],
97
:
[
101.45
,
36.38
],
201
:
[
87.36
,
43.48
],
398
:
[
117.18
,
31.51
],
795
:
[
118.5
,
32.02
],
655
:
[
120.09
,
30.14
],
295
:
[
113
,
28.11
],
311
:
[
115.52
,
28.41
],
993
:
[
114.21
,
30.37
],
601
:
[
104.05
,
30.39
],
275
:
[
106.42
,
26.35
],
317
:
[
119.18
,
26.05
],
1000
:
[
113.15
,
23.08
],
186
:
[
110.2
,
20.02
],
261
:
[
108.2
,
22.48
],
132
:
[
102.41
,
25
],
18
:
[
91.1
,
29.4
],
11
:
[
114.1
,
22.18
]
};
function
convertData
(
data
)
{
var
res
=
[];
for
(
var
i
=
0
;
i
<
data
.
length
;
i
++
)
{
var
geoCoord
=
geoCoordMap
[
data
[
i
].
name
];
if
(
geoCoord
)
{
res
.
push
({
name
:
data
[
i
].
name
,
value
:
geoCoord
.
concat
(
data
[
i
].
value
)
});
}
}
console
.
log
(
res
)
return
res
;
}
function
convertData
(
data
)
{
var
res
=
[];
for
(
var
i
=
0
;
i
<
data
.
length
;
i
++
)
{
var
geoCoord
=
geoCoordMap
[
data
[
i
].
name
];
if
(
geoCoord
)
{
res
.
push
({
name
:
data
[
i
].
name
,
value
:
geoCoord
.
concat
(
data
[
i
].
value
)
});
}
}
console
.
log
(
res
);
return
res
;
}
let
option
=
{
tooltip
:
{
show
:
false
},
let
option
=
{
tooltip
:
{
show
:
false
},
geo
:
{
map
:
'china'
,
roam
:
true
,
center
:
[
104.95
,
35.27
],
// 地图尺寸为容器宽高较小值的80%
zoom
:
1.7
,
// scaleLimit:{
// max:'1.2',
// min:'0.7'
// },
label
:
{
normal
:
{
show
:
false
,
textStyle
:
{
color
:
'rgba(0,0,0,0.6)'
}
}
},
itemStyle
:
{
areaColor
:
'rgba(231, 243, 255, 1)'
,
// 设置所有区域的默认填充色[citation:8]
borderColor
:
'rgb(5, 95, 194)'
,
// 设置边界线颜色[citation:8]
borderWidth
:
1
// 设置边界线宽度[citation:8]
},
},
// backgroundColor: 'rgba(0,51,102, 1)',
series
:
[{
type
:
'scatter'
,
coordinateSystem
:
'geo'
,
data
:
convertData
(
data
),
symbolSize
:
10
,
symbolRotate
:
0
,
symbolOffset
:
[
'50%'
,
'-100%'
],
tooltip
:
{
show
:
true
},
label
:
{
normal
:
{
formatter
:
'{a}'
,
position
:
'top'
,
show
:
false
,
textStyle
:
{
color
:
'#000000'
,
fontSize
:
16
}
},
emphasis
:
{
show
:
false
}
},
itemStyle
:
{
normal
:
{
borderWidth
:
3
,
borderColor
:
'rgba(255, 163, 158, 1)'
,
color
:
'rgba(255, 77, 79, 1)'
}
}
}]
};
return
option
geo
:
{
map
:
"china"
,
roam
:
true
,
center
:
[
104.95
,
35.27
],
// 地图尺寸为容器宽高较小值的80%
zoom
:
1.7
,
// scaleLimit:{
// max:'1.2',
// min:'0.7'
// },
label
:
{
normal
:
{
show
:
false
,
textStyle
:
{
color
:
"rgba(0,0,0,0.6)"
}
}
},
itemStyle
:
{
areaColor
:
"rgba(231, 243, 255, 1)"
,
// 设置所有区域的默认填充色[citation:8]
borderColor
:
"rgb(5, 95, 194)"
,
// 设置边界线颜色[citation:8]
borderWidth
:
1
// 设置边界线宽度[citation:8]
}
},
// backgroundColor: 'rgba(0,51,102, 1)',
series
:
[
{
type
:
"scatter"
,
coordinateSystem
:
"geo"
,
data
:
convertData
(
data
),
symbolSize
:
10
,
symbolRotate
:
0
,
symbolOffset
:
[
"50%"
,
"-100%"
],
tooltip
:
{
show
:
true
},
label
:
{
normal
:
{
formatter
:
"{a}"
,
position
:
"top"
,
show
:
false
,
textStyle
:
{
color
:
"#000000"
,
fontSize
:
16
}
},
emphasis
:
{
show
:
false
}
},
itemStyle
:
{
normal
:
{
borderWidth
:
3
,
borderColor
:
"rgba(255, 163, 158, 1)"
,
color
:
"rgba(255, 77, 79, 1)"
}
}
}
]
};
return
option
;
}
export
const
getBarChart
=
(
nameList
,
valueList
,
color
=
[
'rgba(255, 159, 22, 1)'
,
'rgba(255, 159, 22, 0)'
],
name
)
=>
{
const
option
=
{
tooltip
:
{
trigger
:
"axis"
,
formatter
:
function
(
params
)
{
let
result
=
params
[
0
].
name
+
'<br/>'
;
params
.
forEach
(
function
(
item
,
index
)
{
// 自定义颜色数组
const
customColors
=
[
color
[
0
]];
const
dotColor
=
customColors
[
index
%
customColors
.
length
];
// 循环取色
// 创建彩色圆点图标
const
dot
=
`<span style="display:inline-block;margin-right:5px;border-radius:50%;width:10px;height:10px;background-color:
${
dotColor
}
;"></span>`
;
result
+=
dot
+
`
${
item
.
seriesName
}
:
${
item
.
value
}
<br/>`
;
});
return
result
;
}
},
grid
:
{
top
:
'3%'
,
right
:
'3%'
,
bottom
:
'1%'
,
left
:
'1%'
,
containLabel
:
true
},
xAxis
:
{
axisLine
:
{
lineStyle
:
{
width
:
1
,
color
:
"rgba(231, 243, 255, 1)"
}
},
axisTick
:
{
show
:
false
},
type
:
"category"
,
boundaryGap
:
[
100
,
100
],
axisLabel
:
{
color
:
"rgba(95, 101, 108, 1)"
,
// fontSize: 22,
// fontWeight: 400
},
data
:
nameList
},
yAxis
:
{
type
:
"value"
,
axisLine
:
{
lineStyle
:
{
type
:
"dashed"
}
},
export
const
getBarChart
=
(
nameList
,
valueList
,
color
=
[
"rgba(255, 159, 22, 1)"
,
"rgba(255, 159, 22, 0)"
],
name
)
=>
{
const
option
=
{
tooltip
:
{
trigger
:
"axis"
,
formatter
:
function
(
params
)
{
let
result
=
params
[
0
].
name
+
"<br/>"
;
params
.
forEach
(
function
(
item
,
index
)
{
// 自定义颜色数组
const
customColors
=
[
color
[
0
]];
const
dotColor
=
customColors
[
index
%
customColors
.
length
];
// 循环取色
// 创建彩色圆点图标
const
dot
=
`<span style="display:inline-block;margin-right:5px;border-radius:50%;width:10px;height:10px;background-color:
${
dotColor
}
;"></span>`
;
result
+=
dot
+
`
${
item
.
seriesName
}
:
${
item
.
value
}
<br/>`
;
});
return
result
;
}
},
grid
:
{
top
:
"3%"
,
right
:
"3%"
,
bottom
:
"1%"
,
left
:
"1%"
,
containLabel
:
true
},
xAxis
:
{
axisLine
:
{
lineStyle
:
{
width
:
1
,
color
:
"rgba(231, 243, 255, 1)"
}
},
axisTick
:
{
show
:
false
},
type
:
"category"
,
boundaryGap
:
[
100
,
100
],
axisLabel
:
{
color
:
"rgba(95, 101, 108, 1)"
// fontSize: 22,
// fontWeight: 400
},
data
:
nameList
},
yAxis
:
{
type
:
"value"
,
axisLine
:
{
lineStyle
:
{
type
:
"dashed"
}
},
axisLabel
:
{
color
:
"rgba(95, 101, 108, 1)"
,
// fontSize: 22,
// fontWeight: 400
},
splitNumber
:
8
,
splitLine
:
{
lineStyle
:
{
width
:
1
,
type
:
"dashed"
,
color
:
"rgba(231, 243, 255, 1)"
},
axisLabel
:
{
color
:
"rgba(95, 101, 108, 1)"
// fontSize: 22,
// fontWeight: 400
},
splitNumber
:
8
,
splitLine
:
{
lineStyle
:
{
width
:
1
,
type
:
"dashed"
,
color
:
"rgba(231, 243, 255, 1)"
}
}
},
series
:
[
{
name
:
name
,
type
:
"bar"
,
data
:
valueList
,
}
},
series
:
[{
name
:
name
,
type
:
'bar'
,
data
:
valueList
,
barWidth
:
12
,
itemStyle
:
{
color
:
function
(
params
)
{
return
new
echarts
.
graphic
.
LinearGradient
(
0
,
1
,
0
,
0
,
[{
offset
:
0
,
color
:
color
[
1
]
},
{
offset
:
1
,
color
:
color
[
0
]
}
]);
},
barBorderRadius
:
10
,
}
}]
}
return
option
}
barWidth
:
12
,
itemStyle
:
{
color
:
function
(
params
)
{
return
new
echarts
.
graphic
.
LinearGradient
(
0
,
1
,
0
,
0
,
[
{
offset
:
0
,
color
:
color
[
1
]
},
{
offset
:
1
,
color
:
color
[
0
]
}
]);
},
barBorderRadius
:
10
}
}
]
};
return
option
;
};
export
const
getLineChart
=
(
object
,
isPercent
)
=>
{
const
option
=
{
title
:
{
text
:
""
},
tooltip
:
{
trigger
:
"axis"
,
formatter
:
function
(
params
)
{
let
result
=
params
[
0
].
name
+
'<br/>'
;
params
.
forEach
(
function
(
item
,
index
)
{
// 自定义颜色数组
const
customColors
=
[
object
.
color
];
const
dotColor
=
customColors
[
index
%
customColors
.
length
];
// 循环取色
// 创建彩色圆点图标
const
dot
=
`<span style="display:inline-block;margin-right:5px;border-radius:50%;width:10px;height:10px;background-color:
${
dotColor
}
;"></span>`
;
result
+=
dot
+
`
${
item
.
seriesName
}
:
${
item
.
value
}${
isPercent
?
'%'
:
''
}
<br/>`
;
});
return
result
;
}
},
grid
:
{
top
:
'3%'
,
right
:
'3%'
,
bottom
:
'1%'
,
left
:
'1%'
,
containLabel
:
true
},
// toolbox: {
// feature: {
// saveAsImage: {}
// }
// },
xAxis
:
{
axisLine
:
{
lineStyle
:
{
width
:
1
,
color
:
"rgba(231, 243, 255, 1)"
}
},
axisTick
:
{
show
:
false
},
type
:
"category"
,
boundaryGap
:
[
100
,
100
],
axisLabel
:
{
color
:
"rgba(95, 101, 108, 1)"
,
// fontSize: 22,
// fontWeight: 400
},
data
:
object
.
xAxisData
},
yAxis
:
{
type
:
"value"
,
axisLine
:
{
lineStyle
:
{
type
:
"dashed"
}
},
const
option
=
{
title
:
{
text
:
""
},
tooltip
:
{
trigger
:
"axis"
,
formatter
:
function
(
params
)
{
let
result
=
params
[
0
].
name
+
"<br/>"
;
params
.
forEach
(
function
(
item
,
index
)
{
// 自定义颜色数组
const
customColors
=
[
object
.
color
];
const
dotColor
=
customColors
[
index
%
customColors
.
length
];
// 循环取色
// 创建彩色圆点图标
const
dot
=
`<span style="display:inline-block;margin-right:5px;border-radius:50%;width:10px;height:10px;background-color:
${
dotColor
}
;"></span>`
;
result
+=
dot
+
`
${
item
.
seriesName
}
:
${
item
.
value
}${
isPercent
?
"%"
:
""
}
<br/>`
;
});
return
result
;
}
},
grid
:
{
top
:
"3%"
,
right
:
"3%"
,
bottom
:
"1%"
,
left
:
"1%"
,
containLabel
:
true
},
// toolbox: {
// feature: {
// saveAsImage: {}
// }
// },
xAxis
:
{
axisLine
:
{
lineStyle
:
{
width
:
1
,
color
:
"rgba(231, 243, 255, 1)"
}
},
axisTick
:
{
show
:
false
},
type
:
"category"
,
boundaryGap
:
[
100
,
100
],
axisLabel
:
{
color
:
"rgba(95, 101, 108, 1)"
// fontSize: 22,
// fontWeight: 400
},
data
:
object
.
xAxisData
},
yAxis
:
{
type
:
"value"
,
axisLine
:
{
lineStyle
:
{
type
:
"dashed"
}
},
axisLabel
:
{
color
:
"rgba(95, 101, 108, 1)"
,
// fontSize: 22,
// fontWeight: 400
formatter
:
`{value}
${
isPercent
?
'%'
:
''
}
`
},
axisLabel
:
{
color
:
"rgba(95, 101, 108, 1)"
,
// fontSize: 22,
// fontWeight: 400
formatter
:
`{value}
${
isPercent
?
"%"
:
""
}
`
},
splitNumber
:
8
,
splitLine
:
{
lineStyle
:
{
width
:
1
,
type
:
"dashed"
,
color
:
"rgba(231, 243, 255, 1)"
},
}
},
series
:
[
{
name
:
object
.
name
,
type
:
"line"
,
symbolSize
:
8
,
symbol
:
'circle'
,
itemStyle
:
{
color
:
"#ffffff"
,
borderColor
:
object
.
color
,
borderWidth
:
3
},
lineStyle
:
{
color
:
object
.
color
,
},
data
:
object
.
seriesData
}
]
};
return
option
;
}
splitNumber
:
8
,
splitLine
:
{
lineStyle
:
{
width
:
1
,
type
:
"dashed"
,
color
:
"rgba(231, 243, 255, 1)"
}
}
},
series
:
[
{
name
:
object
.
name
,
type
:
"line"
,
symbolSize
:
8
,
symbol
:
"circle"
,
itemStyle
:
{
color
:
"#ffffff"
,
borderColor
:
object
.
color
,
borderWidth
:
3
},
lineStyle
:
{
color
:
object
.
color
},
data
:
object
.
seriesData
}
]
};
return
option
;
};
export
const
getHorizontalBarChart1
=
(
nameList
,
valueList
,
isPer
)
=>
{
const
colorList
=
[
'#ce4f51'
,
'#1778ff'
]
const
option
=
{
tooltip
:
{},
grid
:
{
top
:
'3%'
,
right
:
'3%'
,
bottom
:
'1%'
,
left
:
'1%'
,
containLabel
:
true
},
color
:
[
'#ce4f51'
,
'#1778ff'
],
xAxis
:
{
type
:
'value'
,
splitLine
:
{
show
:
false
},
show
:
false
},
yAxis
:
{
type
:
'category'
,
data
:
nameList
,
splitLine
:
{
show
:
false
},
axisTick
:
{
show
:
false
},
axisLine
:
{
show
:
false
},
axisLabel
:
{
show
:
true
}
},
series
:
[{
type
:
'bar'
,
data
:
valueList
.
map
((
item
,
index
)
=>
{
return
{
value
:
item
,
label
:
{
textStyle
:
{
color
:
index
<
4
?
'#1778ff'
:
'#ce4f51'
}
}
};
}),
label
:
{
show
:
true
,
position
:
[
450
,
-
2
],
formatter
:
function
(
params
)
{
return
isPer
?
params
.
value
+
'%'
:
params
.
value
}
},
barWidth
:
8
,
itemStyle
:
{
color
:
function
(
params
)
{
if
(
params
.
dataIndex
<
4
)
{
return
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
1
,
0
,
[{
offset
:
0
,
color
:
'rgba(22, 119, 255, 0)'
},
{
offset
:
1
,
color
:
colorList
[
1
]
}
]);
}
else
{
return
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
1
,
0
,
[{
offset
:
0
,
color
:
'rgba(206, 79, 81, 0)'
},
{
offset
:
1
,
color
:
colorList
[
0
]
}
]);
}
},
barBorderRadius
:
4
,
}
}]
}
return
option
}
const
colorList
=
[
"#ce4f51"
,
"#1778ff"
];
const
option
=
{
tooltip
:
{},
grid
:
{
top
:
"3%"
,
right
:
"3%"
,
bottom
:
"1%"
,
left
:
"1%"
,
containLabel
:
true
},
color
:
[
"#ce4f51"
,
"#1778ff"
],
xAxis
:
{
type
:
"value"
,
splitLine
:
{
show
:
false
},
show
:
false
},
yAxis
:
{
type
:
"category"
,
data
:
nameList
,
splitLine
:
{
show
:
false
},
axisTick
:
{
show
:
false
},
axisLine
:
{
show
:
false
},
axisLabel
:
{
show
:
true
}
},
series
:
[
{
type
:
"bar"
,
data
:
valueList
.
map
((
item
,
index
)
=>
{
return
{
value
:
item
,
label
:
{
textStyle
:
{
color
:
index
<
4
?
"#1778ff"
:
"#ce4f51"
}
}
};
}),
label
:
{
show
:
true
,
position
:
[
450
,
-
2
],
formatter
:
function
(
params
)
{
return
isPer
?
params
.
value
+
"%"
:
params
.
value
;
}
},
barWidth
:
8
,
itemStyle
:
{
color
:
function
(
params
)
{
if
(
params
.
dataIndex
<
4
)
{
return
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
1
,
0
,
[
{
offset
:
0
,
color
:
"rgba(22, 119, 255, 0)"
},
{
offset
:
1
,
color
:
colorList
[
1
]
}
]);
}
else
{
return
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
1
,
0
,
[
{
offset
:
0
,
color
:
"rgba(206, 79, 81, 0)"
},
{
offset
:
1
,
color
:
colorList
[
0
]
}
]);
}
},
barBorderRadius
:
4
}
}
]
};
return
option
;
};
export
const
getHorizontalBarChart2
=
(
nameList
,
valueList
,
isPer
)
=>
{
const
colorList
=
[
[
'rgba(64, 150, 255, 1)'
,
'rgba(64, 150, 255, 0)'
],
[
'rgba(255, 120, 117, 1)'
,
'rgba(255, 120, 117, 0)'
],
[
'rgba(89, 126, 247, 1)'
,
'rgba(89, 126, 247, 0)'
],
[
'rgba(54, 207, 201, 1)'
,
'rgba(54, 207, 201, 0)'
],
[
'rgba(255, 197, 61, 1)'
,
'rgba(255, 197, 61, 0)'
],
[
'rgba(179, 127, 235, 1)'
,
'rgba(179, 127, 235, 0)'
]
]
console
.
log
(
colorList
)
const
option
=
{
tooltip
:
{},
grid
:
{
top
:
'6%'
,
right
:
'6%'
,
bottom
:
'0'
,
left
:
'1%'
,
containLabel
:
true
},
xAxis
:
{
type
:
'value'
,
splitLine
:
{
show
:
false
},
show
:
false
},
yAxis
:
{
type
:
'category'
,
data
:
nameList
,
splitLine
:
{
show
:
false
},
axisTick
:
{
show
:
false
},
axisLine
:
{
show
:
false
},
axisLabel
:
{
show
:
true
}
},
series
:
[{
type
:
'bar'
,
data
:
valueList
.
map
((
item
,
index
)
=>
{
return
{
value
:
item
,
label
:
{
textStyle
:
{
color
:
colorList
[
index
][
0
]
}
}
};
}),
label
:
{
show
:
true
,
position
:
[
340
,
-
2
],
formatter
:
function
(
params
)
{
return
isPer
?
params
.
value
+
'%'
:
params
.
value
}
},
barWidth
:
8
,
itemStyle
:
{
color
:
function
(
params
)
{
console
.
log
(
'params'
,
params
)
return
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
1
,
0
,
[{
offset
:
0
,
color
:
colorList
[
params
.
dataIndex
][
1
]
},
{
offset
:
1
,
color
:
colorList
[
params
.
dataIndex
][
0
]
}
]);
const
colorList
=
[
[
"rgba(64, 150, 255, 1)"
,
"rgba(64, 150, 255, 0)"
],
[
"rgba(255, 120, 117, 1)"
,
"rgba(255, 120, 117, 0)"
],
[
"rgba(89, 126, 247, 1)"
,
"rgba(89, 126, 247, 0)"
],
[
"rgba(54, 207, 201, 1)"
,
"rgba(54, 207, 201, 0)"
],
[
"rgba(255, 197, 61, 1)"
,
"rgba(255, 197, 61, 0)"
],
[
"rgba(179, 127, 235, 1)"
,
"rgba(179, 127, 235, 0)"
]
];
console
.
log
(
colorList
);
const
option
=
{
tooltip
:
{},
grid
:
{
top
:
"6%"
,
right
:
"6%"
,
bottom
:
"0"
,
left
:
"1%"
,
containLabel
:
true
},
xAxis
:
{
type
:
"value"
,
splitLine
:
{
show
:
false
},
show
:
false
},
yAxis
:
{
type
:
"category"
,
data
:
nameList
,
splitLine
:
{
show
:
false
},
axisTick
:
{
show
:
false
},
axisLine
:
{
show
:
false
},
axisLabel
:
{
show
:
true
}
},
series
:
[
{
type
:
"bar"
,
data
:
valueList
.
map
((
item
,
index
)
=>
{
return
{
value
:
item
,
label
:
{
textStyle
:
{
color
:
colorList
[
index
%
6
][
0
]
}
}
};
}),
label
:
{
show
:
true
,
position
:
[
340
,
-
2
],
formatter
:
function
(
params
)
{
return
isPer
?
params
.
value
+
"%"
:
params
.
value
;
}
},
barWidth
:
8
,
itemStyle
:
{
color
:
function
(
params
)
{
console
.
log
(
"params"
,
params
);
return
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
1
,
0
,
[
{
offset
:
0
,
color
:
colorList
[
params
.
dataIndex
%
6
][
1
]
},
{
offset
:
1
,
color
:
colorList
[
params
.
dataIndex
%
6
][
0
]
}
]);
},
barBorderRadius
:
4
}
}
]
};
return
option
;
};
export
const
getMultipleLineChart
=
obj
=>
{
const
color
=
[
"rgba(19, 168, 168, 1)"
,
"rgba(146, 84, 222, 1)"
,
"rgba(250, 140, 22, 1)"
,
"rgba(206, 79, 81, 1)"
];
const
option
=
{
title
:
{
text
:
""
},
tooltip
:
{
trigger
:
"axis"
,
formatter
:
function
(
params
)
{
let
result
=
params
[
0
].
name
+
"<br/>"
;
params
.
forEach
(
function
(
item
,
index
)
{
// 自定义颜色数组
const
customColors
=
color
;
const
dotColor
=
customColors
[
index
%
customColors
.
length
];
// 循环取色
// 创建彩色圆点图标
const
dot
=
`<span style="display:inline-block;margin-right:5px;border-radius:50%;width:10px;height:10px;background-color:
${
dotColor
}
;"></span>`
;
result
+=
dot
+
`
${
item
.
seriesName
}
:
${
item
.
value
}
<br/>`
;
});
return
result
;
}
},
grid
:
{
top
:
"12%"
,
right
:
"3%"
,
bottom
:
"3%"
,
left
:
"1%"
,
containLabel
:
true
},
legend
:
{
right
:
"5%"
,
icon
:
"circle"
,
itemWidth
:
15
,
textStyle
:
{
color
:
"rgba(0, 0, 0, 0.8)"
,
fontSize
:
14
,
fontWeight
:
400
},
itemGap
:
17
,
data
:
obj
.
data
.
map
((
item
,
index
)
=>
{
return
{
name
:
item
.
name
,
itemStyle
:
{
color
:
color
[
index
]
}
};
})
},
xAxis
:
{
axisLine
:
{
lineStyle
:
{
width
:
1
,
color
:
"rgba(231, 243, 255, 1)"
}
},
axisTick
:
{
show
:
false
},
type
:
"category"
,
boundaryGap
:
[
100
,
100
],
axisLabel
:
{
color
:
"rgba(95, 101, 108, 1)"
// fontSize: 22,
// fontWeight: 400
},
data
:
obj
.
dates
},
yAxis
:
{
type
:
"value"
,
axisLine
:
{
lineStyle
:
{
type
:
"dashed"
}
},
},
barBorderRadius
:
4
,
}
}]
}
return
option
}
export
const
getMultipleLineChart
=
(
obj
)
=>
{
const
color
=
[
'rgba(19, 168, 168, 1)'
,
'rgba(146, 84, 222, 1)'
,
'rgba(250, 140, 22, 1)'
,
'rgba(206, 79, 81, 1)'
]
const
option
=
{
title
:
{
text
:
""
},
tooltip
:
{
trigger
:
"axis"
,
formatter
:
function
(
params
)
{
let
result
=
params
[
0
].
name
+
'<br/>'
;
params
.
forEach
(
function
(
item
,
index
)
{
// 自定义颜色数组
const
customColors
=
color
;
const
dotColor
=
customColors
[
index
%
customColors
.
length
];
// 循环取色
// 创建彩色圆点图标
const
dot
=
`<span style="display:inline-block;margin-right:5px;border-radius:50%;width:10px;height:10px;background-color:
${
dotColor
}
;"></span>`
;
result
+=
dot
+
`
${
item
.
seriesName
}
:
${
item
.
value
}
<br/>`
;
});
return
result
;
}
},
grid
:
{
top
:
'12%'
,
right
:
'3%'
,
bottom
:
'3%'
,
left
:
'1%'
,
containLabel
:
true
},
legend
:
{
right
:
"5%"
,
icon
:
"circle"
,
itemWidth
:
15
,
textStyle
:
{
color
:
"rgba(0, 0, 0, 0.8)"
,
fontSize
:
14
,
fontWeight
:
400
},
itemGap
:
17
,
data
:
obj
.
data
.
map
((
item
,
index
)
=>
{
return
{
name
:
item
.
name
,
itemStyle
:
{
color
:
color
[
index
]
}
}
})
},
xAxis
:
{
axisLine
:
{
lineStyle
:
{
width
:
1
,
color
:
"rgba(231, 243, 255, 1)"
}
},
axisTick
:
{
show
:
false
},
type
:
"category"
,
boundaryGap
:
[
100
,
100
],
axisLabel
:
{
color
:
"rgba(95, 101, 108, 1)"
,
// fontSize: 22,
// fontWeight: 400
},
data
:
obj
.
dates
},
yAxis
:
{
type
:
"value"
,
axisLine
:
{
lineStyle
:
{
type
:
"dashed"
}
},
axisLabel
:
{
color
:
"rgba(95, 101, 108, 1)"
,
// fontSize: 22,
// fontWeight: 400
},
splitNumber
:
8
,
splitLine
:
{
lineStyle
:
{
width
:
1
,
type
:
"dashed"
,
color
:
"rgba(231, 243, 255, 1)"
},
}
},
series
:
obj
.
data
.
map
((
item
,
index
)
=>
{
return
{
name
:
item
.
name
,
type
:
"line"
,
symbolSize
:
6
,
symbol
:
'circle'
,
itemStyle
:
{
color
:
"#ffffff"
,
borderColor
:
color
[
index
],
borderWidth
:
2
},
lineStyle
:
{
width
:
1
,
color
:
color
[
index
],
},
data
:
item
.
value
}
})
};
return
option
;
}
axisLabel
:
{
color
:
"rgba(95, 101, 108, 1)"
// fontSize: 22,
// fontWeight: 400
},
splitNumber
:
8
,
splitLine
:
{
lineStyle
:
{
width
:
1
,
type
:
"dashed"
,
color
:
"rgba(231, 243, 255, 1)"
}
}
},
series
:
obj
.
data
.
map
((
item
,
index
)
=>
{
return
{
name
:
item
.
name
,
type
:
"line"
,
symbolSize
:
6
,
symbol
:
"circle"
,
itemStyle
:
{
color
:
"#ffffff"
,
borderColor
:
color
[
index
],
borderWidth
:
2
},
lineStyle
:
{
width
:
1
,
color
:
color
[
index
]
},
data
:
item
.
value
};
})
};
return
option
;
};
//出口管制主页接口
export
const
getMultipleBarChart_m
=
(
object
)
=>
{
const
list
=
_
.
chain
(
object
.
data
).
filter
(
'year'
).
orderBy
(
'year'
,
'asc'
).
value
();
const
colors
=
[
[
'rgba(22, 119, 255, 1)'
,
'rgba(22, 119, 255, 0)'
],
[
'rgba(206, 79, 81, 1)'
,
'rgba(206, 79, 81, 0)'
],
[
'rgba(255, 197, 61, 1)'
,
'rgba(255, 197, 61, 0)'
],
[
'rgba(255, 204, 199, 1)'
,
'rgba(255, 204, 199, 0)'
],
[
'rgba(179, 127, 235, 1)'
,
'rgba(179, 127, 235, 0)'
],
[
'rgba(127, 218, 235, 1)'
,
'rgba(127, 214, 235, 0)'
],
];
const
names
=
_
.
map
(
list
,
'year'
);
const
datas
=
_
.
chain
(
object
.
domains
).
splice
(
0
,
6
).
map
((
name
,
index
)
=>
{
console
.
log
(
_
.
map
(
list
,
name
))
return
{
name
,
data
:
_
.
map
(
list
,
`domainNum.
${
name
}
`
),
type
:
"bar"
,
barWidth
:
12
,
itemStyle
:
{
color
:
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
0
,
1
,
[
{
offset
:
0
,
color
:
colors
[
index
%
colors
.
length
][
0
]
},
// { offset: 0.5, color: '#188df0' },
{
offset
:
1
,
color
:
colors
[
index
%
colors
.
length
][
1
]
}
]),
borderRadius
:
[
6
,
6
,
0
,
0
]
}
}
}).
value
();
console
.
log
(
'names'
,
names
)
const
option
=
{
tooltip
:
{
trigger
:
"axis"
,
axisPointer
:
{
type
:
"shadow"
}
},
grid
:
{
top
:
50
},
legend
:
{
// type: "scroll",
// show: true,
// orient: "horizontal",
icon
:
"circle"
,
},
xAxis
:
{
type
:
"category"
,
data
:
names
},
yAxis
:
{
type
:
"value"
},
series
:
datas
}
return
option
;
}
export
const
getMultipleBarChart_m
=
object
=>
{
const
list
=
_
.
chain
(
object
.
data
).
filter
(
"year"
).
orderBy
(
"year"
,
"asc"
).
value
();
const
colors
=
[
[
"rgba(22, 119, 255, 1)"
,
"rgba(22, 119, 255, 0)"
],
[
"rgba(206, 79, 81, 1)"
,
"rgba(206, 79, 81, 0)"
],
[
"rgba(255, 197, 61, 1)"
,
"rgba(255, 197, 61, 0)"
],
[
"rgba(255, 204, 199, 1)"
,
"rgba(255, 204, 199, 0)"
],
[
"rgba(179, 127, 235, 1)"
,
"rgba(179, 127, 235, 0)"
],
[
"rgba(127, 218, 235, 1)"
,
"rgba(127, 214, 235, 0)"
]
];
const
names
=
_
.
map
(
list
,
"year"
);
const
datas
=
_
.
chain
(
object
.
domains
)
.
splice
(
0
,
6
)
.
map
((
name
,
index
)
=>
{
console
.
log
(
_
.
map
(
list
,
name
));
return
{
name
,
data
:
_
.
map
(
list
,
`domainNum.
${
name
}
`
),
type
:
"bar"
,
barWidth
:
12
,
itemStyle
:
{
color
:
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
0
,
1
,
[
{
offset
:
0
,
color
:
colors
[
index
%
colors
.
length
][
0
]
},
// { offset: 0.5, color: '#188df0' },
{
offset
:
1
,
color
:
colors
[
index
%
colors
.
length
][
1
]
}
]),
borderRadius
:
[
6
,
6
,
0
,
0
]
}
};
})
.
value
();
console
.
log
(
"names"
,
names
);
const
option
=
{
tooltip
:
{
trigger
:
"axis"
,
axisPointer
:
{
type
:
"shadow"
}
},
grid
:
{
top
:
50
},
legend
:
{
// type: "scroll",
// show: true,
// orient: "horizontal",
icon
:
"circle"
},
xAxis
:
{
type
:
"category"
,
data
:
names
},
yAxis
:
{
type
:
"value"
},
series
:
datas
};
return
option
;
};
src/views/gjOverView/assets/bg.png
0 → 100644
浏览文件 @
273f345b
780.8 KB
src/views/gjOverView/assets/icon1.png
0 → 100644
浏览文件 @
273f345b
1.0 KB
src/views/gjOverView/component/MeansAnalysis.vue
浏览文件 @
273f345b
...
...
@@ -9,7 +9,7 @@
<div
class=
"divider"
></div>
<div
class=
"thematic-content"
>
<div
class=
"item-header"
>
<img
class=
"item-header-icon"
src=
"
@/assets/images/icon/thematic-card-header-time
.png"
></img>
<img
class=
"item-header-icon"
src=
"
../assets/icon1
.png"
></img>
<div
class=
"item-header-text"
>
科技博弈历程
</div>
</div>
...
...
src/views/gjOverView/component/ResourceAnalysis.vue
浏览文件 @
273f345b
...
...
@@ -13,8 +13,10 @@
<img
class=
"item-header-icon"
src=
"@/assets/images/icon/thematic-card-header-time.png"
></img>
<div
class=
"item-header-text"
>
科技人才对比分析
</div>
<div
class=
"item-header-btn"
>
<img
class=
"item-header-ibtn-con"
src=
"@/assets/images/icon/header-btn.png"
></img>
数据来源:美国某某发展基金会
<img
class=
"item-header-btn-icon"
src=
"@/assets/images/icon/header-btn.png"
></img>
<div
style=
""
>
数据来源:美国某某发展基金会
</div>
</div>
</div>
<div
class=
"divider"
></div>
...
...
@@ -31,8 +33,10 @@
<img
class=
"item-header-icon"
src=
"@/assets/images/icon/thematic-card-header-time.png"
></img>
<div
class=
"item-header-text"
>
科研投入对比分析
</div>
<div
class=
"item-header-btn"
>
<img
class=
"item-header-ibtn-con"
src=
"@/assets/images/icon/header-btn.png"
></img>
数据来源:美国某某发展基金会
<img
class=
"item-header-btn-icon"
src=
"@/assets/images/icon/header-btn.png"
></img>
<div
style=
""
>
数据来源:美国某某发展基金会
</div>
</div>
</div>
...
...
@@ -55,8 +59,10 @@
<img
class=
"item-header-icon"
src=
"@/assets/images/icon/thematic-card-header-time.png"
></img>
<div
class=
"item-header-text"
>
创新主体对比分析
</div>
<div
class=
"item-header-btn"
>
<img
class=
"item-header-icon"
src=
"@/assets/images/icon/header-btn.png"
></img>
数据来源:美国某某发展基金会
<img
class=
"item-header-btn-icon"
src=
"@/assets/images/icon/header-btn.png"
></img>
<div
style=
""
>
数据来源:美国某某发展基金会
</div>
</div>
</div>
<div
class=
"divider"
></div>
...
...
@@ -73,21 +79,23 @@
<img
class=
"item-header-icon"
src=
"@/assets/images/icon/thematic-card-header-time.png"
></img>
<div
class=
"item-header-text"
>
科学数据对比分析
</div>
<div
class=
"item-header-btn"
>
<img
class=
"item-header-ibtn-con"
src=
"@/assets/images/icon/header-btn.png"
></img>
数据来源:美国某某发展基金会
<img
class=
"item-header-btn-icon"
src=
"@/assets/images/icon/header-btn.png"
></img>
<div
style=
""
>
数据来源:美国某某发展基金会
</div>
</div>
</div>
<div
class=
"divider"
></div>
<div
style=
"display: flex;"
>
<div
style=
"display: flex;height: 3
20px;width: calc(50% - 40px) ;margin: 20px;
"
id=
"char7"
>
<div
style=
"display: flex;height: 3
60px;width: 433px ;
"
id=
"char7"
>
</div>
<div
style=
"width: 50%;padding-top:
50
px;"
>
<div
style=
"width: 50%;padding-top:
34
px;"
>
<div
v-for=
"value in radar2Data"
class=
"radar2Data-line"
>
<div
class=
"radar2Data-circle"
:style=
"
{ backgroundColor: value.color }">
</div>
<div
style=
"
width: 40px;margin: 0 7px
"
>
{{
value
.
name
}}
</div>
<div
style=
"width:
calc(100% - 150px) ;padding: 10px;"
>
<el-progress
:percentage=
"value.percent
"
:
color=
"value.color"
:
show-text=
"false"
/></div>
<div
style=
"
margin: 0 5px;font-size: 16px;
"
>
{{
value
.
name
}}
</div>
<div
style=
"width:
168px ; "
>
<el-progress
:percentage=
"value.percent"
:color=
"value.color
"
:show-text=
"false"
/></div>
<div
style=
" width: 70px;text-align: right;"
>
{{
value
.
percent
<
50
?
'低依赖'
:
value
.
percent
<
80
?
'中度依赖'
:
'高度依赖'
}}
</div>
</div>
...
...
@@ -312,7 +320,6 @@ onMounted(() => {
display
:
flex
;
color
:
rgba
(
132
,
136
,
142
,
1
);
width
:
calc
(
100%
-
210px
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
...
...
@@ -322,10 +329,23 @@ onMounted(() => {
text-align
:
right
;
}
.item-header-
ibtn-
con
{
width
:
1
6
px
;
.item-header-
btn-i
con
{
width
:
1
4
px
;
height
:
16px
;
margin-top
:
15px
;
margin-left
:
270px
;
margin-right
:
4px
;
}
.item-header-btn-text
{
color
:
rgba
(
132
,
136
,
142
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
400
;
line-height
:
24px
;
letter-spacing
:
0px
;
text-align
:
left
;
}
}
...
...
@@ -384,13 +404,17 @@ onMounted(() => {
width
:
100%
;
height
:
30px
;
margin-top
:
18px
;
align-items
:
center
;
/* 垂直居中 */
color
:
rgba
(
95
,
101
,
108
,
1
);
font-size
:
16px
;
font-family
:
Microsoft
YaHei
;
font-size
:
14px
;
font-weight
:
400
;
line-height
:
2
4
px
;
line-height
:
2
2
px
;
letter-spacing
:
0px
;
align-items
:
center
;
/* 垂直居中 */
text-align
:
right
;
}
...
...
@@ -400,4 +424,9 @@ onMounted(() => {
height
:
12px
;
border-radius
:
50%
;
}
:deep
(
.el-progress-bar__outer
)
{
height
:
8px
!
important
;
}
</
style
>
src/views/gjOverView/component/Timeline.vue
浏览文件 @
273f345b
...
...
@@ -20,13 +20,13 @@
</div>
<!-- 卡片 -->
<div
class=
"card"
:class=
"[cardPos(item), 'right-side']"
:style=
"widthStyle()"
@
click=
"$emit('click-card', item)"
>
<div
class=
"card"
:class=
"[cardPos(item), 'right-side']"
@
click=
"$emit('click-card', item)"
>
<img
:src=
"`/icon/$
{item.unit}.png`" class="icon">
</img>
<div
class=
"title"
>
{{
item
.
time
}}
</div>
<div
class=
"title"
:style=
"
{
color: item.unit === '中国' ? ' #CF4F51' : ''
}">
{{
item
.
title
}}
</div>
<div
class=
"time"
>
{{
item
.
time
}}
</div>
<div
class=
"content"
>
{{
item
.
content
}}
</div>
</div>
</div>
...
...
@@ -50,7 +50,15 @@ export default {
},
/* 水平位置:按索引均匀分布 */
leftStyle
(
i
)
{
return
{
left
:
`
${(
i
*
100
)
/
(
this
.
data
.
length
-
1
)}
vw`
};
// let pos = ``
// if (i === 0) {
// pos = 0
// } else {
// this.linePos(this.data[i - 1]) !== this.linePos(this.data[i]) ? pos = { left: `${(i * 270) - 125}px` } : pos = { left: `${(i * 270)}px` }
// }
return
{
left
:
`
${(
i
*
270
)}
px`
}
// return pos;
},
/* 卡片上下位置:unit=0 -> 下侧,其余 -> 上侧 */
cardPos
(
item
)
{
...
...
@@ -166,28 +174,30 @@ export default {
.dot.up
::after
{
bottom
:
100%
;
height
:
18
0px
height
:
24
0px
}
.dot.down
::after
{
top
:
100%
;
height
:
18
0px
height
:
24
0px
}
.card
{
position
:
absolute
;
height
:
180px
;
/* 容器 28 */
width
:
220px
;
height
:
176px
;
padding
:
8px
20px
;
font-size
:
14px
;
cursor
:
pointer
}
.card.up
{
bottom
:
20
px
bottom
:
86
px
}
.card.down
{
top
:
20
px
;
top
:
94
px
;
}
...
...
@@ -196,15 +206,39 @@ export default {
}
.title
{
/* 美国进一步收紧对华AI芯片出口限制 */
width
:
220px
;
color
:
#055fc2
;
font-size
:
18px
;
font-weight
:
700
;
line-height
:
26px
line-height
:
26px
;
margin-top
:
-25px
;
margin-left
:
10px
;
}
.time
{
color
:
rgba
(
95
,
101
,
108
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
400
;
line-height
:
30px
;
letter-spacing
:
0px
;
text-align
:
justify
;
margin-left
:
10px
;
}
.content
{
color
:
#5f656c
;
width
:
220px
;
height
:
90px
;
color
:
rgba
(
59
,
65
,
75
,
1
);
margin-left
:
10px
;
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
line-height
:
24px
font-weight
:
400
;
line-height
:
30px
;
letter-spacing
:
0px
;
text-align
:
justify
;
}
</
style
>
\ No newline at end of file
src/views/gjOverView/index.vue
浏览文件 @
273f345b
...
...
@@ -46,13 +46,16 @@
</div>
<div
class=
"item-card-right"
>
<div
style=
"
overflow: auto;
height: 400px;"
>
<div
style=
"
height: 400px;"
>
<div
v-for=
"(item, index) in technologicalTrends.data"
:key=
"index"
style=
"height: 46px;"
>
<div
class=
"list-row"
>
<div
class=
"item-list-punblier"
>
{{
item
.
tag1
}}
</div>
<div
class=
"item-list-content"
>
{{
item
.
text
}}
</div>
<div
class=
"item-list-time"
>
{{
item
.
time
}}
</div>
<div
class=
"item-list-punblier"
>
{{
item
.
tag2
}}
</div>
<div
class=
"item-list-punblier"
:style=
"
{ color: item.tagColor, backgroundColor: item.tagBg, borderColor: item.color }">
{{
item
.
tag2
}}
</div>
</div>
<div
class=
"item-header-divider"
/>
</div>
...
...
@@ -66,7 +69,7 @@
<div
class=
"item-header"
>
<img
class=
"item-header-icon"
src=
"@/assets/images/icon/waring-card-header-icon.png"
/>
<div
class=
"item-header-text"
style=
"background-color: #ce4f51"
>
风险信号
<div
class=
"num"
>
{{
warningList
.
length
}}
</div>
}}
</div>
</div>
</div>
...
...
@@ -130,14 +133,70 @@ const technologicalTrends = ref({
txt
:
'2025年9月14日,欧盟委员会宣布通过“地平线欧洲”2025年工作计划投入约73亿欧元的专项资金,增强欧洲的科研创新引擎和'
,
},
data
:
[
{
tag1
:
'科研仪器'
,
text
:
'欧盟投资73亿欧元推进数字化转型'
,
time
:
'1小时前'
,
tag2
:
'新能源'
},
{
tag1
:
'创新主体'
,
text
:
'美财政部发布拟议规则限制对华网...'
,
time
:
'3小时前'
,
tag2
:
'人工智能'
},
{
tag1
:
'科技人才'
,
text
:
'美NIST发布《美国关键和新兴技术....'
,
time
:
'昨天'
,
tag2
:
'量子科技'
},
{
tag1
:
'创新主体'
,
text
:
'美《开创未来先进计算生态系统:战...'
,
time
:
'昨天'
,
tag2
:
'人工智能'
},
{
tag1
:
'科研仪器'
,
text
:
'欧盟启动初代“数字地球”系统..'
,
time
:
'昨天'
,
tag2
:
'量子科技'
},
{
tag1
:
'科研仪器'
,
text
:
'美NSF投建国家AI可编程云实验室网...'
,
time
:
'昨天'
,
tag2
:
'新能源'
},
{
tag1
:
'科研仪器'
,
text
:
'英启动全球顶尖科技人才引进计划瞄...'
,
time
:
'昨天'
,
tag2
:
'新能源'
},
{
tag1
:
'科研仪器'
,
text
:
'美国家科学基金会致力改进下一代无...'
,
time
:
'昨天'
,
tag2
:
'新能源'
},
{
"tag1"
:
"科研仪器"
,
"text"
:
"欧盟投资73亿欧元推进数字化转型"
,
"time"
:
"1小时前"
,
"tag2"
:
"新能源"
,
"tagColor"
:
"rgba(250, 140, 22, 1)"
,
"tagBg"
:
"rgba(255, 247, 230, 1)"
},
{
"tag1"
:
"创新主体"
,
"text"
:
"美财政部发布拟议规则限制对华网..."
,
"time"
:
"3小时前"
,
"tag2"
:
"人工智能"
,
"tagColor"
:
"rgba(114, 46, 209, 1)"
,
"tagBg"
:
"rgba(249, 240, 255, 1)"
},
{
"tag1"
:
"科技人才"
,
"text"
:
"美NIST发布《美国关键和新兴技术...."
,
"time"
:
"昨天"
,
"tag2"
:
"量子科技"
,
"tagColor"
:
"rgba(206, 79, 81, 1)"
,
"tagBg"
:
"rgba(255, 241, 240, 1)"
},
{
"tag1"
:
"创新主体"
,
"text"
:
"美《开创未来先进计算生态系统:战..."
,
"time"
:
"昨天"
,
"tag2"
:
"人工智能"
,
"tagColor"
:
"rgba(114, 46, 209, 1)"
,
"tagBg"
:
"rgba(249, 240, 255, 1)"
},
{
"tag1"
:
"科研仪器"
,
"text"
:
"欧盟启动初代“数字地球”系统.."
,
"time"
:
"昨天"
,
"tag2"
:
"量子科技"
,
"tagColor"
:
"rgba(206, 79, 81, 1)"
,
"tagBg"
:
"rgba(255, 241, 240, 1)"
},
{
"tag1"
:
"科研仪器"
,
"text"
:
"美NSF投建国家AI可编程云实验室网..."
,
"time"
:
"昨天"
,
"tag2"
:
"新能源"
,
"tagColor"
:
"rgba(250, 140, 22, 1)"
,
"tagBg"
:
"rgba(255, 247, 230, 1)"
},
{
"tag1"
:
"科研仪器"
,
"text"
:
"英启动全球顶尖科技人才引进计划瞄..."
,
"time"
:
"昨天"
,
"tag2"
:
"新能源"
,
"tagColor"
:
"rgba(250, 140, 22, 1)"
,
"tagBg"
:
"rgba(255, 247, 230, 1)"
},
{
"tag1"
:
"科研仪器"
,
"text"
:
"美国家科学基金会致力改进下一代无..."
,
"time"
:
"昨天"
,
"tag2"
:
"新能源"
,
"tagColor"
:
"rgba(250, 140, 22, 1)"
,
"tagBg"
:
"rgba(255, 247, 230, 1)"
}
],
});
...
...
@@ -158,10 +217,16 @@ const handleToMoreRiskSignal = () => {
<
style
lang=
"scss"
scoped
>
.content-main
{
width
:
100%
;
height
:
100%
;
overflow
:
hidden
;
font-family
:
Microsoft
YaHei
;
// width: 100%;
// height: 100%;
// overflow: hidden;
// font-family: Microsoft YaHei;
width
:
1920px
;
margin
:
0
auto
;
background
:
url("./assets/bg.png")
;
background-repeat
:
no-repeat
;
background-color
:
#fff
;
background-size
:
contain
;
}
.content-title
{
...
...
@@ -355,7 +420,7 @@ const handleToMoreRiskSignal = () => {
.list-row
{
display
:
flex
;
align-items
:
center
;
margin
:
10
px
0
;
margin
:
5
px
0
;
height
:
40px
;
...
...
@@ -382,6 +447,7 @@ const handleToMoreRiskSignal = () => {
.item-list-time
{
width
:
68px
;
text-align
:
right
;
margin-right
:
8px
;
color
:
rgba
(
132
,
136
,
142
,
1
);
}
}
...
...
src/views/gjOverView/js/barChart2.js
浏览文件 @
273f345b
...
...
@@ -31,14 +31,22 @@ const getColumnChart = (nameList, series1, series2, isPer) => {
axisLine
:
{
show
:
false
},
axisTick
:
{
show
:
false
},
axisLabel
:
{
show
:
true
,
color
:
'#666'
},
splitLine
:
{
show
:
true
,
lineStyle
:
{
color
:
'#ebebeb'
}
}
splitLine
:
{
show
:
true
,
lineStyle
:
{
type
:
"dashed"
,
color
:
"#E7F3FF"
}
},
},
series
:
[
{
name
:
'研究型大学'
,
type
:
'bar'
,
data
:
series1
,
barWidth
:
8
,
barWidth
:
12
,
barGap
:
'60%'
,
// 同一类别内不同系列的间隔
barCategoryGap
:
"-60%"
,
label
:
{
show
:
false
},
itemStyle
:
{
borderRadius
:
[
8
,
8
,
0
,
0
],
color
:
gradBlue
}
},
...
...
@@ -46,7 +54,7 @@ const getColumnChart = (nameList, series1, series2, isPer) => {
name
:
'科技企业'
,
type
:
'bar'
,
data
:
series2
,
barWidth
:
8
,
barWidth
:
12
,
label
:
{
show
:
false
},
itemStyle
:
{
borderRadius
:
[
8
,
8
,
0
,
0
],
color
:
gradCyan
}
},
...
...
@@ -54,7 +62,7 @@ const getColumnChart = (nameList, series1, series2, isPer) => {
name
:
'研究机构'
,
type
:
'bar'
,
data
:
series2
,
barWidth
:
8
,
barWidth
:
12
,
label
:
{
show
:
false
},
itemStyle
:
{
borderRadius
:
[
8
,
8
,
0
,
0
],
color
:
'#FFC63D'
}
}
...
...
src/views/gjOverView/js/multiLineChart2.js
浏览文件 @
273f345b
...
...
@@ -67,7 +67,7 @@ const getMultiLineChart = (dataX, dataY1, dataY2, dataY3, dataY4, dataY5) => {
return
{
tooltip
:
{
trigger
:
'axis'
,
axisPointer
:
{
type
:
'cross'
}
},
grid
:
{
top
:
'5%'
,
right
:
'0%'
,
bottom
:
'0%'
,
left
:
'0%'
,
containLabel
:
true
},
grid
:
{
top
:
'5%'
,
right
:
'
1
0%'
,
bottom
:
'0%'
,
left
:
'0%'
,
containLabel
:
true
},
xAxis
:
{
type
:
'category'
,
boundaryGap
:
false
,
data
:
dataX
},
yAxis
:
{
...
...
src/views/gjOverView/js/radarChart2.js
浏览文件 @
273f345b
import
*
as
echarts
from
"echarts"
;
const
getBarChart
=
(
nameList
,
valueList
,
isPer
)
=>
{
const
colors
=
[
'rgba(165, 42, 42, 1)'
,
// 红色
'rgba(0, 0, 128, 1)'
,
// 蓝色
'rgba(0, 128, 128, 1)'
,
// 青色
'rgba(75, 0, 130, 1)'
,
// 紫色
'rgba(255, 165, 0, 1)'
,
// 橙色
'rgba(173, 216, 230, 1)'
// 浅蓝色
];
const
getRadarChart
=
()
=>
{
const
option
=
{
title
:
{
text
:
''
},
tooltip
:
{},
radar
:
{
radius
:
'50%'
,
// 关键:缩小整个雷达
center
:
[
'50%'
,
'45%'
],
// 可选:再往下挪一点,避免图例挤在一起
radius
:
'50%'
,
center
:
[
'50%'
,
'45%'
],
indicator
:
[
{
name
:
'能源
'
,
max
:
65
00
},
{
name
:
'集成电路'
,
max
:
1
60
00
},
{
name
:
'
人工智能'
,
max
:
300
00
},
{
name
:
'
通信网络'
,
max
:
380
00
},
{
name
:
'
量子科技'
,
max
:
520
00
},
{
name
:
'
生物科技'
,
max
:
250
00
}
{
name
:
'能源
领域'
,
max
:
1
00
},
{
name
:
'集成电路'
,
max
:
100
},
{
name
:
'
生物科技'
,
max
:
1
00
},
{
name
:
'
人工智能'
,
max
:
1
00
},
{
name
:
'
通信网络'
,
max
:
1
00
},
{
name
:
'
量子科技'
,
max
:
1
00
}
],
axisName
:
{
formatter
:
'{value}'
,
color
:
'rgba(59, 65, 75, 1)'
,
fontSize
:
1
4
,
fontSize
:
1
6
,
fontWeight
:
400
}
},
series
:
[
{
name
:
'
Budget vs spending
'
,
name
:
'
科技领域表现
'
,
type
:
'radar'
,
symbol
:
'none'
,
data
:
[
{
value
:
[
4200
,
3000
,
20000
,
35000
,
50000
,
18000
],
name
:
'中国'
,
areaStyle
:
{
color
:
'rgba(10, 87, 166, 0.2)'
}
"value"
:
[
20
,
95
,
30
,
85
,
70
,
60
],
"name"
:
"中国"
,
"areaStyle"
:
{
"color"
:
"rgba(165, 42, 42, 0.2)"
},
lineStyle
:
{
width
:
1.5
,
// 设置线条宽度为2
color
:
'rgba(165, 42, 42, 1)'
// 设置线条颜色
}
},
{
value
:
[
5000
,
14000
,
28000
,
26000
,
42000
,
21000
],
name
:
'美国'
,
areaStyle
:
{
color
:
'rgba(206, 79, 81, 0.2)'
}
"value"
:
[
90
,
40
,
85
,
20
,
60
,
75
],
"name"
:
"美国"
,
"areaStyle"
:
{
"color"
:
"rgba(0, 0, 128, 0.2)"
},
lineStyle
:
{
width
:
1.5
,
// 设置线条宽度为2
color
:
'rgba(0, 0, 128, 1)'
// 设置线条颜色
}
},
{
value
:
[
4000
,
14000
,
18000
,
21000
,
32000
,
10000
],
name
:
'欧盟'
,
areaStyle
:
{
color
:
'rgba(250, 140, 22, 0.2)'
}
"value"
:
[
80
,
68
,
92
,
82
,
58
,
88
],
"name"
:
"欧盟"
,
"areaStyle"
:
{
"color"
:
"rgba(0, 128, 128, 0.2)"
},
lineStyle
:
{
width
:
1.5
,
// 设置线条宽度为2
color
:
'rgba(0, 128, 128, 1)'
// 设置线条颜色
}
},
{
value
:
[
4000
,
14000
,
18000
,
21000
,
32000
,
10000
],
name
:
'英国'
,
areaStyle
:
{
color
:
'rgba(250, 140, 22, 0.2)'
}
"value"
:
[
57
,
81
,
76
,
91
,
87
,
67
],
"name"
:
"英国"
,
"areaStyle"
:
{
"color"
:
"rgba(75, 0, 130, 0.2)"
},
lineStyle
:
{
width
:
1.5
,
// 设置线条宽度为2
color
:
'rgba(75, 0, 130, 1)'
// 设置线条颜色
}
},
{
value
:
[
4000
,
14000
,
18000
,
21000
,
32000
,
10000
],
name
:
'日本'
,
areaStyle
:
{
color
:
'rgba(250, 140, 22, 0.2)'
}
"value"
:
[
93
,
59
,
79
,
89
,
69
,
83
],
"name"
:
"日本"
,
"areaStyle"
:
{
"color"
:
"rgba(255, 165, 0, 0.2)"
},
lineStyle
:
{
width
:
1.5
,
// 设置线条宽度为2
color
:
'rgba(255, 165, 0, 1)'
// 设置线条颜色
}
},
{
value
:
[
4000
,
14000
,
18000
,
21000
,
32000
,
10000
],
name
:
'韩国'
,
areaStyle
:
{
color
:
'rgba(250, 140, 22, 0.2)'
}
"value"
:
[
86
,
56
,
77
,
94
,
80
,
66
],
"name"
:
"韩国"
,
"areaStyle"
:
{
"color"
:
"rgba(173, 216, 230,0.2)"
},
lineStyle
:
{
width
:
1.5
,
// 设置线条宽度为2
color
:
'rgba(173, 216, 230, 1)'
// 设置线条颜色
}
}
]
}
]
}
return
option
}
}
;
return
option
;
}
;
export
default
getBarChart
\ No newline at end of file
export
default
getRadarChart
;
\ No newline at end of file
src/views/technologyFigures/assets/images/TechnologyFigures-icon1.png
0 → 100644
浏览文件 @
273f345b
525 Bytes
src/views/technologyFigures/assets/images/TechnologyFigures-icon2.png
0 → 100644
浏览文件 @
273f345b
837 Bytes
src/views/technologyFigures/assets/images/TechnologyFigures-icon3.png
0 → 100644
浏览文件 @
273f345b
664 Bytes
src/views/technologyFigures/assets/images/TechnologyFigures-icon4.png
0 → 100644
浏览文件 @
273f345b
718 Bytes
src/views/technologyFigures/component/SourceLibrary.vue
浏览文件 @
273f345b
<!-- SourceLibrary.vue -->
<
template
>
<<<<<<<
HEAD
<div
class=
"source-library-container"
>
<div
class=
"source-library-grid"
>
<div
v-for=
"(item, index) in sourceLibraryData"
:key=
"index"
class=
"source-library-card"
>
...
...
@@ -36,6 +37,42 @@
/>
</div>
</div>
=======
<div
class=
"source-library-container"
>
<div
class=
"source-library-grid"
>
<div
v-for=
"(item, index) in sourceLibraryData"
:key=
"index"
class=
"source-library-card"
>
<div
class=
"source-library-avatar-wrapper"
>
<img
:src=
"item.avatar"
alt=
""
class=
"source-library-avatar"
/>
<div
class=
"person-tags"
>
<div
class=
"person-tag-bg"
v-for=
"(tag, tIdx) in item.icon"
:key=
"tIdx"
>
<img
:src=
"'/public/icon/header-icon' + tag + '.png'"
class=
"tag-icon"
alt=
"tag"
/>
</div>
</div>
</div>
<div
class=
"source-library-text-content"
>
<div
style=
" width: 240px;"
>
<h3
class=
"source-library-name"
>
{{
item
.
name
}}
</h3>
<p
class=
"source-library-title"
>
{{
item
.
title
}}
</p>
<p
class=
"source-library-tag"
:style=
"
{
background: item.colorArray[2],
color: item.colorArray[0],
borderColor: item.colorArray[1],
}">
{{
item
.
tag
}}
</p>
</div>
</div>
</div>
</div>
<div
class=
"page"
>
<div
class=
"count"
>
共1205项调查
</div>
<el-pagination
v-model:current-page=
"currentPage"
:page-size=
"pageSize"
:total=
"total"
layout=
"prev, pager, next"
background
@
current-change=
"handlePageChange"
/>
</div>
</div>
>>>>>>> af566f60d3ab2563ec38173a60323b1404cd7081
</
template
>
<
script
setup
>
...
...
@@ -84,6 +121,28 @@ const handlePageChange = p => {
margin-right
:
18px
;
}
.person-tags
{
display
:
flex
;
margin-top
:
-20px
;
width
:
42px
;
padding-left
:
28px
;
text-align
:
center
;
}
.person-tag-bg
{
/* 椭圆 6 */
width
:
32px
;
height
:
32px
;
background
:
rgba
(
255
,
255
,
255
,
0
.8
);
border-radius
:
50%
;
}
.tag-icon
{
width
:
24px
;
height
:
24px
;
object-fit
:
contain
;
}
.source-library-avatar
{
/* 椭圆 142 */
width
:
88px
;
...
...
@@ -145,6 +204,7 @@ const handlePageChange = p => {
}
.page
{
<<<<<<<
HEAD
/*
width
:
1221px
;
*/
width
:
1600px
;
height
:
40px
;
...
...
@@ -162,6 +222,27 @@ const handlePageChange = p => {
letter-spacing
:
0px
;
text-align
:
left
;
}
=======
width
:
1600px
;
height
:
40px
;
display
:
flex
;
align-items
:
center
;
justify-content
:
space-between
;
margin
:
36px
0
0
0
;
padding-left
:
11px
;
.count
{
color
:
rgba
(
59
,
65
,
75
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
16px
;
font-weight
:
400
;
line-height
:
24px
;
letter-spacing
:
0px
;
text-align
:
left
;
}
>>>>>>>
af566f60d3ab2563ec38173a60323b1404cd7081
}
:deep
(
.el-pagination
)
{
...
...
src/views/technologyFigures/index.vue
浏览文件 @
273f345b
...
...
@@ -76,7 +76,7 @@
<div
class=
"box1-header"
>
<div
class=
"box1-header-left"
>
<div
class=
"icon"
>
<img
src=
"./assets/images/
box1-header-icon
.png"
alt=
""
/>
<img
src=
"./assets/images/
TechnologyFigures-icon4
.png"
alt=
""
/>
</div>
<div
class=
"title"
>
{{
"人物新闻动态"
}}
</div>
</div>
...
...
@@ -128,7 +128,7 @@
<div
class=
"box3-header"
>
<div
class=
"box3-header-left"
>
<div
class=
"box3-header-icon"
>
<img
src=
"./assets/images/
header-news
.png"
alt=
""
/>
<img
src=
"./assets/images/
TechnologyFigures-icon3
.png"
alt=
""
/>
</div>
<!--
<div
class=
"box3-header-title"
>
{{
"人物动向"
}}
</div>
-->
<div
class=
"header-title"
...
...
@@ -178,7 +178,7 @@
<div
class=
"box5-header"
>
<div
class=
"box5-header-left"
>
<div
class=
"box5-header-icon"
>
<img
src=
"./assets/images/
box3-header-icon
.png"
alt=
""
<img
src=
"./assets/images/
TechnologyFigures-icon1
.png"
alt=
""
style=
"margin: 13px 21px 13px 21px; height: 22px"
/>
<div
class=
"box5-header-title"
>
{{
"科技人物观点词云"
}}
</div>
</div>
...
...
@@ -200,7 +200,7 @@
<div
class=
"box6"
>
<div
class=
"box6-header"
style=
"width: 790px"
>
<div
class=
"header-icon"
>
<img
src=
"./assets/images/box
6
-header-icon.png"
alt=
""
/>
<img
src=
"./assets/images/box
3
-header-icon.png"
alt=
""
/>
</div>
<div
class=
"header-title"
style=
"display: flex; width: 740px; justify-content: space-between; align-items: center"
>
...
...
@@ -223,7 +223,7 @@
<div
class=
"box7-header"
>
<div
class=
"box7-header-left"
>
<div
class=
"box7-header-icon"
>
<img
src=
"./assets/images/
box3-header-icon
.png"
alt=
""
/>
<img
src=
"./assets/images/
TechnologyFigures-icon2
.png"
alt=
""
/>
</div>
<div
class=
"box7-header-title"
>
{{
"科技人物类型"
}}
</div>
</div>
...
...
@@ -234,7 +234,7 @@
<div
class=
"box8-header"
>
<div
class=
"box8-header-left"
>
<div
class=
"box8-header-icon"
>
<img
src=
"./assets/images/
box6-header-icon
.png"
alt=
""
/>
<img
src=
"./assets/images/
TechnologyFigures-icon2
.png"
alt=
""
/>
</div>
<div
style=
"display: flex; width: 730px; justify-content: space-between; align-items: center"
>
<div
class=
"box8-header-title"
>
{{
"主要人物涉华观点统计"
}}
</div>
...
...
@@ -839,7 +839,7 @@ onMounted(() => {
line-height
:
47px
;
color
:
rgba
(
132
,
136
,
142
,
1
);
font-family
:
Microsoft
YaHei
;
font-size
:
1
4
px
;
font-size
:
1
6
px
;
font-weight
:
400
;
}
}
...
...
src/views/technologyFigures/json/source.json
浏览文件 @
273f345b
...
...
@@ -4,111 +4,127 @@
"title"
:
"美国总统(2017-2021、2025-至今),共和党党员"
,
"tag"
:
"行政主管"
,
"avatar"
:
"/public/testData/data2.png"
,
"colorArray"
:
[
"#1677FF"
,
"#BAE0FF"
,
"#E6F4FF"
]
"colorArray"
:
[
"#1677FF"
,
"#BAE0FF"
,
"#E6F4FF"
],
"icon"
:
[
"1"
]
},
{
"name"
:
"詹姆斯·戴维·万斯"
,
"title"
:
"美国副总统、参议院议长、共和党全国委员会财务主席"
,
"tag"
:
"行政主管"
,
"avatar"
:
"/public/testData/data2.png"
,
"colorArray"
:
[
"#1677FF"
,
"#BAE0FF"
,
"#E6F4FF"
]
"colorArray"
:
[
"#1677FF"
,
"#BAE0FF"
,
"#E6F4FF"
],
"icon"
:
[]
},
{
"name"
:
"黄仁勋"
,
"title"
:
"NVIDIA公司创始人兼首席执行官,美国工程院院士"
,
"tag"
:
"科技企业领袖"
,
"avatar"
:
"/public/testData/data2.png"
,
"colorArray"
:
[
"#13A8A8"
,
"#87E8DE"
,
"#E6FFFFB"
]
"colorArray"
:
[
"#13A8A8"
,
"#87E8DE"
,
"#E6FFFFB"
],
"icon"
:
[
"1"
]
},
{
"name"
:
"马尔科·鲁比奥"
,
"title"
:
"美国国务卿,美国总统国家安全事务临时助理"
,
"tag"
:
"行政主管"
,
"avatar"
:
"/public/testData/data2.png"
,
"colorArray"
:
[
"#1677FF"
,
"#BAE0FF"
,
"#E6F4FF"
]
"colorArray"
:
[
"#1677FF"
,
"#BAE0FF"
,
"#E6F4FF"
],
"icon"
:
[]
},
{
"name"
:
"埃隆·马斯克"
,
"title"
:
"特斯拉创始人兼首席执行官、SpaceX、美国党创始人"
,
"tag"
:
"科技企业领袖"
,
"avatar"
:
"/public/testData/data2.png"
,
"colorArray"
:
[
"#13A8A8"
,
"#87E8DE"
,
"#E6FFFFB"
]
"colorArray"
:
[
"#13A8A8"
,
"#87E8DE"
,
"#E6FFFFB"
],
"icon"
:
[
"1"
]
},
{
"name"
:
"乔迪·阿灵顿"
,
"title"
:
"共和党党员,美国国会众议院议员,预算委员会主席"
,
"tag"
:
"国会议员"
,
"avatar"
:
"/public/testData/data2.png"
,
"colorArray"
:
[
"#FAAD14"
,
"#FFE58F"
,
"#FFFBE6"
]
"colorArray"
:
[
"#FAAD14"
,
"#FFE58F"
,
"#FFFBE6"
],
"icon"
:
[]
},
{
"name"
:
"霍华德·卢特尼克"
,
"title"
:
"美国商务部长"
,
"tag"
:
"行政主管"
,
"avatar"
:
"/public/testData/data2.png"
,
"colorArray"
:
[
"#1677FF"
,
"#BAE0FF"
,
"#E6F4FF"
]
"colorArray"
:
[
"#1677FF"
,
"#BAE0FF"
,
"#E6F4FF"
],
"icon"
:
[
"1"
]
},
{
"name"
:
"蒂姆·库克"
,
"title"
:
"苹果公司首席执行官,清华大学经济管理学院顾问委员会主席"
,
"tag"
:
"科技企业领袖"
,
"avatar"
:
"/public/testData/data2.png"
,
"colorArray"
:
[
"#13A8A8"
,
"#87E8DE"
,
"#E6FFFFB"
]
"colorArray"
:
[
"#13A8A8"
,
"#87E8DE"
,
"#E6FFFFB"
],
"icon"
:
[]
},
{
"name"
:
"朱棣文"
,
"title"
:
"第12任美国能源部部长,主要研究领域为原子物理、激光科学"
,
"tag"
:
"顶级科学家"
,
"avatar"
:
"/public/testData/data2.png"
,
"colorArray"
:
[
"#722ED1"
,
"#D3ADF7"
,
"#F9F0FF"
]
"colorArray"
:
[
"#722ED1"
,
"#D3ADF7"
,
"#F9F0FF"
],
"icon"
:
[
"1"
]
},
{
"name"
:
"约翰·图恩"
,
"title"
:
"共和党党员,美国国会众议院议员"
,
"tag"
:
"国会议员"
,
"avatar"
:
"/public/testData/data2.png"
,
"colorArray"
:
[
"#FAAD14"
,
"#FFE58F"
,
"#FFFBE6"
]
"colorArray"
:
[
"#FAAD14"
,
"#FFE58F"
,
"#FFFBE6"
],
"icon"
:
[]
},
{
"name"
:
"珍妮弗·道德纳"
,
"title"
:
"主要研究领域为RNA领域和基因编辑技术"
,
"tag"
:
"顶级科学家"
,
"avatar"
:
"/public/testData/data2.png"
,
"colorArray"
:
[
"#722ED1"
,
"#D3ADF7"
,
"#F9F0FF"
]
"colorArray"
:
[
"#722ED1"
,
"#D3ADF7"
,
"#F9F0FF"
],
"icon"
:
[
"1"
]
},
{
"name"
:
"迈克·约翰逊"
,
"title"
:
"美国众议院议长"
,
"tag"
:
"国会议员"
,
"avatar"
:
"/public/testData/data2.png"
,
"colorArray"
:
[
"#FAAD14"
,
"#FFE58F"
,
"#FFFBE6"
]
"colorArray"
:
[
"#FAAD14"
,
"#FFE58F"
,
"#FFFBE6"
],
"icon"
:
[]
},
{
"name"
:
"亚当·史密斯"
,
"title"
:
"美国国会众议院议员,众议院军事委员会民主党领袖"
,
"tag"
:
"国会议员"
,
"avatar"
:
"/public/testData/data2.png"
,
"colorArray"
:
[
"#FAAD14"
,
"#FFE58F"
,
"#FFFBE6"
]
"colorArray"
:
[
"#FAAD14"
,
"#FFE58F"
,
"#FFFBE6"
],
"icon"
:
[
"1"
]
},
{
"name"
:
"查尔斯·本内特"
,
"title"
:
"美国国家科学院院士、美国物理学会院士,量子信息论主要创立者"
,
"tag"
:
"顶级科学家"
,
"avatar"
:
"/public/testData/data2.png"
,
"colorArray"
:
[
"#722ED1"
,
"#D3ADF7"
,
"#F9F0FF"
]
"colorArray"
:
[
"#722ED1"
,
"#D3ADF7"
,
"#F9F0FF"
],
"icon"
:
[]
},
{
"name"
:
"桑达尔·皮查伊"
,
"title"
:
"谷歌母公司Alphabet首席执行官"
,
"tag"
:
"科技企业领袖"
,
"avatar"
:
"/public/testData/data2.png"
,
"colorArray"
:
[
"#13A8A8"
,
"#87E8DE"
,
"#E6FFFFB"
]
"colorArray"
:
[
"#13A8A8"
,
"#87E8DE"
,
"#E6FFFFB"
],
"icon"
:
[
"1"
]
},
{
"name"
:
"威康·汤姆逊"
,
"title"
:
"美国国家科学院院士、美国物理学会院士,量子信息论主要创立者"
,
"tag"
:
"顶级科学家"
,
"avatar"
:
"/public/testData/data2.png"
,
"colorArray"
:
[
"#722ED1"
,
"#D3ADF7"
,
"#F9F0FF"
]
"colorArray"
:
[
"#722ED1"
,
"#D3ADF7"
,
"#F9F0FF"
],
"icon"
:
[]
}
]
出口管制接口.md
0 → 100644
浏览文件 @
273f345b
# 交互消息类
## ApiResult
```
java
public
class
ApiResult
<
T
>
{
@ApiModelProperty
(
"响应码"
)
private
int
code
;
@ApiModelProperty
(
"响应消息"
)
private
String
message
;
@ApiModelProperty
(
"是否成功"
)
private
boolean
success
;
@ApiModelProperty
(
"响应数据"
)
private
T
data
;
}
```
## LatestExportControlInfo
```
java
public
class
LatestExportControlInfo
{
// 出口管制事件ID
private
String
id
;
// 管制信息标题
private
String
name
;
// 管制内容简述
private
String
summary
;
// 发布机构名称
private
String
postOrgName
;
// 发布时间
private
Date
postDate
;
// 涉及领域
private
List
<
String
>
domains
;
// 涉及中国实体数
private
Integer
cnEntityCount
;
// 涉及主要实体
private
List
<
SanctionListBean
>
sanEntities
;
}
```
## AnnualCount
```
java
public
class
AnnualCount
{
// 年份
private
Integer
year
;
// 数量
private
Integer
count
;
// 领域列表
private
List
<
String
>
domain
;
}
```
## DomainCount
```
java
public
class
DomainCount
{
// 制裁类型名称
private
String
sanTypeName
;
// 领域统计信息
private
List
<
BaseCount
>
domainCountInfo
;
}
```
## BaseCount
```
java
public
class
BaseCount
{
// 统计名称
private
String
name
;
// 数量
private
Integer
count
;
}
```
## ExportPageQuery
```
java
public
class
ExportPageQuery
extends
BasePageQuery
{
// 类型名称(实体清单)
private
String
typeName
;
// 制裁时间
@JsonFormat
(
pattern
=
"yyyy-MM-dd"
,
timezone
=
"GMT+8"
)
private
Date
sanctionDate
;
// 是否只看中国实体
private
Boolean
isCn
;
}
```
## BasePageQuery
```
java
public
class
BasePageQuery
{
// 查询页
private
Integer
pageNum
=
1
;
// 每页数量
private
Integer
pageSize
=
10
;
// 排序字段
private
String
sortField
;
// 排序方式
private
String
sortOrder
;
}
```
## SanctionProcess
```
java
public
class
SanctionProcess
{
// 制裁事件ID
private
String
id
;
// 制裁时间
private
Date
postDate
;
// 制裁标题
private
String
name
;
// 制裁内容简述
private
String
summary
;
// 涉及中国实体数
private
Integer
cnEntityCount
;
}
```
## SanctionListBean
```
java
public
class
SanctionListBean
extends
BaseBean
{
@Id
@Column
(
name
=
"ID"
,
nullable
=
false
)
private
String
id
;
@Column
(
name
=
"ENTITY_NAME"
)
private
String
entityName
;
@Column
(
name
=
"SAN_TYPE_ID"
)
private
Integer
sanTypeId
;
@Column
(
name
=
"ENTITY_TYPE"
)
private
Integer
entityType
;
@Column
(
name
=
"ENTITY_ID"
)
private
String
entityId
;
@Column
(
name
=
"ENTITY_NAME_ZH"
)
private
String
entityNameZh
;
@Column
(
name
=
"COUNTRY_ID"
)
private
String
countryId
;
@Column
(
name
=
"SAN_REASON"
)
private
String
sanReason
;
@Column
(
name
=
"SAN_INTENSITY"
)
private
char
sanIntensity
;
@Column
(
name
=
"START_TIME"
)
private
Date
startTime
;
@Column
(
name
=
"END_TIME"
)
private
Date
endTime
;
@Column
(
name
=
"IS_KEY"
)
private
char
isKey
;
@Transient
private
List
<
TechDomainBean
>
techDomainList
;
/**
* 领域列表
*/
@Transient
private
List
<
String
>
techDomains
;
/**
* 50%规则子企业数
*/
@Transient
private
Integer
ruleOrgCount
;
}
```
## OrgInfo
```
java
public
class
OrgInfo
{
// 机构id
private
String
id
;
// 机构名称
private
String
orgName
;
// 相关制裁措施列表
private
List
<
String
>
sanTypeList
;
// 机构职责
private
String
orgDuty
;
// 机构图片
private
String
imageUrl
;
// 人员列表
private
List
<
PersonInfo
>
personList
;
}
```
## PersonInfo
```
java
public
class
PersonInfo
{
// id
private
String
id
;
// 姓名
private
String
name
;
// 党派
private
String
party
;
// 职位
private
String
position
;
// 头像链接
private
String
imageUrl
;
}
```
## SanCountInfo
```
java
public
class
SanCountInfo
{
// 实体数
private
Integer
entityNum
;
// 实体变动数
private
Integer
entityChange
;
// 上市公司数
private
Integer
listedCompanyNum
;
// 上市公司变动数
private
Integer
listedCompanyChange
;
// 涉及领域名数
private
Integer
domainNum
;
// 涉及领域变动数
private
Integer
domainChange
;
// 实体类型数
private
Integer
typeNum
;
// 实体类型变动数
private
Integer
typeChange
;
}
```
## Chain
```
java
public
class
Chain
{
@Id
@Column
(
name
=
"id"
)
@GeneratedValue
(
strategy
=
GenerationType
.
IDENTITY
)
private
Integer
id
;
// 名称
@Column
(
name
=
"name"
)
private
String
name
;
// 中文名称
@Column
(
name
=
"name_zh"
)
private
String
nameZh
;
// 值
@Column
(
name
=
"description"
)
private
String
description
;
// 父级id
@Column
(
name
=
"parent_id"
)
private
Integer
parentId
;
// 是否为产业链主分支
@Column
(
name
=
"is_main_branch"
)
private
String
isMainBranch
;
// 下属产业链分支
@Transient
private
List
<
Chain
>
children
;
}
```
## FishboneResp
```
java
public
class
FishboneResp
<
T
>
{
private
String
text
;
private
List
<
T
>
causes
;
}
```
## AreasStreamResp
```
java
public
class
AreasStreamResp
{
// 上游国内企业数量
private
int
upstreamInternalCount
;
// 上游国内占比
private
double
upstreamInternalRate
;
// 上游受制裁企业数量
private
int
upstreamEntityCount
;
// 上游受制裁占比
private
double
upstreamEntityRate
;
// 中游国内企业数量
private
int
midstreamInternalCount
;
// 中游国内占比
private
double
midstreamInternalRate
;
// 中游受制裁企业数量
private
int
midstreamEntityCount
;
// 中游受制裁占比
private
double
midstreamEntityRate
;
// 下游国内企业数量
private
int
downstreamInternalCount
;
// 下游国内占比
private
double
downstreamInternalRate
;
// 下游受制裁企业数量
private
int
downstreamEntityCount
;
// 下游受制裁占比
private
double
downstreamEntityRate
;
}
```
## AnnualDomainQuery
```
java
public
class
AnnualDomainQuery
{
// 开始年份
private
Integer
startYear
;
// 结束年份
private
Integer
endYear
;
// 是否考虑50%规则
private
Boolean
isRule
;
}
```
## AnnualDomainCount
```
java
public
class
AnnualDomainCount
{
// 年度领域统计
private
List
<
DomainCount
>
yearDomainCount
;
// 所有领域
private
List
<
BaseCount
>
domians
;
}
```
## SanctionTypeBean
```
java
public
class
SanctionTypeBean
extends
BaseBean
{
@Id
@Column
(
name
=
"ID"
,
nullable
=
false
)
private
Integer
id
;
@Column
(
name
=
"NAME"
)
private
String
name
;
@Column
(
name
=
"NAME_ZH"
)
private
String
nameZh
;
@Column
(
name
=
"NAME_ABBR"
)
private
String
nameAbbr
;
@Column
(
name
=
"DESCRIPTION"
)
private
String
description
;
// 发布国家
@Column
(
name
=
"POST_COUNTRY_ID"
)
private
String
postCountryId
;
// 发布机构
@Column
(
name
=
"POST_ORG_ID"
)
private
String
postOrgId
;
// 是否出口管制 1:是 0:否
@Column
(
name
=
"IS_EXPORT_CONTROL"
)
private
String
isExportControl
;
// 总发布次数
@Transient
private
Integer
postCount
;
}
```
# 字典
## 领域类别(id:name)
1:人工智能、2:生物科技、3:新一代信息技术、4:量子科技、5:新能源、6:集成电路、7:海洋、8:先进制造、9:新材料、10:航空航天、11:深海、12:极地、13:太空、14:核
## 实体类别(id:name)
1:人物、2:机构
# 出口管制
## **获取出口管制类清单统计信息**
请求地址:/sanctionList/export/getTotalInfo
请求类型:GET
输入参数:
参数:无输入
请求头:携带token,内容为:
```
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkYXRhLWNlbnRlciIsImF1ZCI6IndlYiIsImlzcyI6ImRhdGEtY2VudGVyIiwiZXhwIjozODI1ODM1NTkxLCJpYXQiOjE2NzgzNTE5NTMsImp0aSI6IjI4YmY1NTZjMTc0MDQ3YjJiNTExNWM3NzVhYjhlNWRmIiwidXNlcm5hbWUiOiJzdXBlcl91c2VyIn0.zHyVzsleX2lEqjDBYRpwluu_wy2nZKGl0dw3IUGnKNw
```
输出结果:ApiResult
<List
<
SanctionTypeBean
>
>
## 最新出口管制政策(4条)
请求地址:http://8.140.26.4:9085/entitiesDataInfo/getLatestInfo
请求类型:GET
输入参数:
参数:无输入
请求头:携带token,内容为:
```
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkYXRhLWNlbnRlciIsImF1ZCI6IndlYiIsImlzcyI6ImRhdGEtY2VudGVyIiwiZXhwIjozODI1ODM1NTkxLCJpYXQiOjE2NzgzNTE5NTMsImp0aSI6IjI4YmY1NTZjMTc0MDQ3YjJiNTExNWM3NzVhYjhlNWRmIiwidXNlcm5hbWUiOiJzdXBlcl91c2VyIn0.zHyVzsleX2lEqjDBYRpwluu_wy2nZKGl0dw3IUGnKNw
```
输出结果:ApiResult
<LatestExportControlInfo>
## 发布(更新)频度
请求地址:http://8.140.26.4:9085/entitiesDataCount/getAnnualCount
请求类型:GET
输入参数:
参数:Integer sanTypeId(制裁类别)
实体清单发布频度:1;CCL发布频度:X(待定,暂无数据)
请求头:携带token,内容为:
```
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkYXRhLWNlbnRlciIsImF1ZCI6IndlYiIsImlzcyI6ImRhdGEtY2VudGVyIiwiZXhwIjozODI1ODM1NTkxLCJpYXQiOjE2NzgzNTE5NTMsImp0aSI6IjI4YmY1NTZjMTc0MDQ3YjJiNTExNWM3NzVhYjhlNWRmIiwidXNlcm5hbWUiOiJzdXBlcl91c2VyIn0.zHyVzsleX2lEqjDBYRpwluu_wy2nZKGl0dw3IUGnKNw
```
输出结果:ApiResult
<List
<
AnnualCount
>
>
## **制裁领域分析**(20251215)
请求地址:http://8.140.26.4:9085/entitiesDataCount/getSanDomainCount
请求类型:GET
输入参数:
参数:Boolean rule(是否勾选50%规则)
请求头:携带token,内容为:
```
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkYXRhLWNlbnRlciIsImF1ZCI6IndlYiIsImlzcyI6ImRhdGEtY2VudGVyIiwiZXhwIjozODI1ODM1NTkxLCJpYXQiOjE2NzgzNTE5NTMsImp0aSI6IjI4YmY1NTZjMTc0MDQ3YjJiNTExNWM3NzVhYjhlNWRmIiwidXNlcm5hbWUiOiJzdXBlcl91c2VyIn0.zHyVzsleX2lEqjDBYRpwluu_wy2nZKGl0dw3IUGnKNw
```
输出结果:ApiResult
<List
<
DomainCount
>
>
## **历次制裁过程**
请求地址:http://8.140.26.4:9085/entitiesDataCount/getSanctionProcess
请求类型:POST
输入参数:
参数:ExportPageQuery exportPageQuery
请求头:携带token,内容为:
```
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkYXRhLWNlbnRlciIsImF1ZCI6IndlYiIsImlzcyI6ImRhdGEtY2VudGVyIiwiZXhwIjozODI1ODM1NTkxLCJpYXQiOjE2NzgzNTE5NTMsImp0aSI6IjI4YmY1NTZjMTc0MDQ3YjJiNTExNWM3NzVhYjhlNWRmIiwidXNlcm5hbWUiOiJzdXBlcl91c2VyIn0.zHyVzsleX2lEqjDBYRpwluu_wy2nZKGl0dw3IUGnKNw
```
输出结果:ApiResult
<Page
<
SanctionProcess
>
>
## **制裁实体清单**列表(20251215)
请求地址:http://8.140.26.4:9085/sanctionList/pageQuery
请求类型:POST
输入参数:
参数:ExportPageQuery exportPageQuery
出口管制-概览页请求时:typeName=实体清单
实体清单-制裁概览页请求时:typeName=实体清单,sanctionDate=该次制裁的具体时间
请求头:携带token,内容为:
```
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkYXRhLWNlbnRlciIsImF1ZCI6IndlYiIsImlzcyI6ImRhdGEtY2VudGVyIiwiZXhwIjozODI1ODM1NTkxLCJpYXQiOjE2NzgzNTE5NTMsImp0aSI6IjI4YmY1NTZjMTc0MDQ3YjJiNTExNWM3NzVhYjhlNWRmIiwidXNlcm5hbWUiOiJzdXBlcl91c2VyIn0.zHyVzsleX2lEqjDBYRpwluu_wy2nZKGl0dw3IUGnKNw
```
输出结果:ApiResult
<Page
<
SanctionListBean
>
>
## **发布机构与重点人物**
请求地址:/sanctionList/getPublishedOrg
请求类型:GET
输入参数:
参数:Integer sanTypeId
暂时固定输入:1;对应实体清单发布机构
请求头:携带token
输出结果:ApiResult
<OrgInfo>
## **领域分布查询**
请求地址:/entitiesDataInfo/getDomianDistribution
请求类型:GET
输入参数:
参数:String sanctionDate (制裁时间)
请求头:携带token
输出结果:ApiResult
<List
<
BaseCount
>
>
## **类型分布查询**
请求地址:/entitiesDataInfo/getTypeDistribution
请求类型:GET
输入参数:
参数:String sanctionDate (制裁时间)
请求头:携带token
输出结果:ApiResult
<List
<
BaseCount
>
>
## **区域分布查询**
请求地址:/entitiesDataInfo/getRegionDistribution
请求类型:GET
输入参数:
参数:String sanctionDate (制裁时间)
请求头:携带token
输出结果:ApiResult
<List
<
BaseCount
>
>
## **制裁理由查询**
请求地址:/entitiesDataInfo/getSanReason
请求类型:GET
输入参数:
参数:String sanctionDate (制裁时间)
请求头:携带token
输出结果:ApiResult
<List
<
String
>
>
## **深度挖掘-制裁信息变化统计**
请求地址:/entitiesDataInfo/getSanCountInfo
请求类型:GET
输入参数:
参数:String sanctionDate (制裁时间)
请求头:携带token
输出结果:ApiResult
<SanCountInfo>
## **年度实体数统计**
请求地址:/entitiesDataInfo/getCountByDomianAndType
请求类型:GET
输入参数:
参数:String domianId (非必需,领域类别ID),Integer typeId (非必需,实体类别ID)
参考字典
请求头:携带token
输出结果:ApiResult
<SanCountInfo>
## **重点实体列表查询**
请求地址:/entitiesDataInfo/getKeyEntities
请求类型:GET
输入参数:
参数:String sanctionDate(必需),String searchText(非必需,检索文本)
请求头:携带token
输出结果:ApiResult
<List
<
OrgInfo
>
>
## **上市企业制裁强度**
请求地址:/entitiesDataInfo/listedEntity/sanInfo
请求类型:GET
输入参数:
参数:无
请求头:携带token
输出结果:ApiResult
<List
<
BaseCount
>
>
## **上市企业融资变化情况**
请求地址:/entitiesDataInfo/listedEntity/financing
请求类型:GET
输入参数:
参数:无
请求头:携带token
输出结果:ApiResult
<List
<
BaseCount
>
>
## **上市企业市值变化情况**
请求地址:/entitiesDataInfo/listedEntity/market
请求类型:GET
输入参数:
参数:无
请求头:携带token
输出结果:ApiResult
<List
<
BaseCount
>
>
## **重点上市企业列表**
请求地址:/entitiesDataInfo/listedEntity/keyEntity
请求类型:GET
输入参数:
参数:String sanctionDate(必需),String searchText(非必需,检索文本)
请求头:携带token
输出结果:ApiResult
<List
<
OrgInfo
>
>
## **历次制裁涉及领域数查询**
请求地址:/entitiesDataInfo/getPreviousDomian
请求类型:GET
输入参数:
参数:无
请求头:携带token
输出结果:ApiResult
<List
<
BaseCount
>
>
## **具体领域的制裁实体数统计**
请求地址:/entitiesDataInfo/getDomianAnnual
请求类型:GET
输入参数:
参数:String domainId
请求头:携带token
输出结果:ApiResult
<List
<
AnnualCount
>
>
## **具体实体类型的制裁实体数统计**
请求地址:/entitiesDataInfo/getEntityTypeAnnual
请求类型:GET
输入参数:
参数:Integer entityTypeId
请求头:携带token
输出结果:ApiResult
<List
<
AnnualCount
>
>
## **产业链结构查询**
请求地址:/chain/getChainTree
请求类型:GET
输入参数:
参数:Integer chainId,非必需
请求头:携带token
输出结果:ApiResult
<List
<
Chain
>
>
## **产业链鱼骨图信息查询**
请求地址:/chain/getChainFishbone
请求类型:GET
输入参数:
参数:Integer chainId
请求头:携带token
输出结果:ApiResult
<FishboneResp>
## **产业链中国企业实体信息查询**
请求地址:/chain/getChainEntityStat
请求类型:GET
输入参数:
参数:Integer chainId
请求头:携带token
输出结果:ApiResult
<AreasStreamResp>
## **实体列表查询**
请求地址:/entitiesDataInfo/getEntityList
请求类型:GET
输入参数:
参数:String sanctionDate(制裁时间),String domainId(领域ID)
请求头:携带token
输出结果:ApiResult
<List
<
OrgInfo
>
>
## **历年制裁领域统计**
请求地址:/entitiesDataCount/getAnnualSanDomain
请求类型:POST
输入参数:
参数:AnnualDomainQuery annualDomainQuery
请求头:携带token
输出结果:ApiResult
<List
<
AnnualDomainCount
>
>
## **新增实体数量增长趋势**
请求地址:/entitiesDataInfo/yoyComparison
请求类型:GET
输入参数:
参数:无输入
请求头:携带token
输出结果:ApiResult
<List
<
AnnualCount
>
>
\ No newline at end of file
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论