Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
risk-monitor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蔡建
risk-monitor
Commits
2e27cc08
提交
2e27cc08
authored
12月 17, 2025
作者:
闫鹏
浏览文件
操作
浏览文件
下载
差异文件
合并分支 'yp-dev' 到 'master'
Yp dev 查看合并请求
!42
上级
27588a66
b614d3d3
隐藏空白字符变更
内嵌
并排
正在显示
17 个修改的文件
包含
3281 行增加
和
1835 行删除
+3281
-1835
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
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
+256
-190
charts.js
src/views/exportControl/utils/charts.js
+937
-901
出口管制接口.md
出口管制接口.md
+810
-0
没有找到文件。
src/api/exportControl.js
浏览文件 @
2e27cc08
...
@@ -23,7 +23,8 @@ export function getEntitiesDataCount() {
...
@@ -23,7 +23,8 @@ export function getEntitiesDataCount() {
return
request200
(
return
request200
(
request
({
request
({
method
:
"GET"
,
method
:
"GET"
,
url
:
"/api/entitiesDataCount/countData"
// url: "/api/entitiesDataCount/countData",
url
:
"/api/sanctionList/export/getTotalInfo"
})
})
);
);
}
}
...
@@ -62,12 +63,15 @@ export function getEntitiesDataInfo() {
...
@@ -62,12 +63,15 @@ export function getEntitiesDataInfo() {
* maxCount: number
* maxCount: number
* }[]>}
* }[]>}
*/
*/
export
function
getIndustryCountByYear
()
{
export
function
getIndustryCountByYear
(
sanTypeId
)
{
return
request200
(
return
request200
(
request
({
request
({
method
:
"GET"
,
method
:
"GET"
,
// url: "/api/entitiesDataCount/industryCountByYear"
// url: "/api/entitiesDataCount/industryCountByYear"
url
:
"/api/entitiesDataCount/getAnnualCount"
url
:
"/api/entitiesDataCount/getAnnualCount"
,
params
:
{
sanTypeId
}
})
})
);
);
}
}
...
@@ -84,11 +88,16 @@ export function getIndustryCountByYear() {
...
@@ -84,11 +88,16 @@ export function getIndustryCountByYear() {
* domains: string[]
* domains: string[]
* }>}
* }>}
*/
*/
export
function
getCountDomainByYear
()
{
export
function
getCountDomainByYear
(
isRule
,
startYear
=
"2020"
,
endYear
=
new
Date
().
getFullYear
()
)
{
return
request200
(
return
request200
(
request
({
request
({
method
:
"GET"
,
method
:
"POST"
,
url
:
"/api/entitiesDataCount/countDomainByYear"
url
:
"/api/entitiesDataCount/getAnnualSanDomain"
,
data
:
{
isRule
,
startYear
,
endYear
}
})
})
);
);
}
}
...
@@ -187,6 +196,21 @@ export function getKeyEntityList(date, keyword = "") {
...
@@ -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'
* @param {string} startTime - 统计开始时间,格式为 'YYYY-MM-DD'
...
@@ -292,7 +316,7 @@ export function getDomainDistribution(sanctionDate = "2025-11-11") {
...
@@ -292,7 +316,7 @@ export function getDomainDistribution(sanctionDate = "2025-11-11") {
* startTime: string
* startTime: string
* }[]>}
* }[]>}
*/
*/
export
function
getEntitiesList
(
typeName
=
"实体清单"
,
pageNum
=
1
,
pageSize
=
10
)
{
export
function
getEntitiesList
(
typeName
=
"实体清单"
,
pageNum
=
1
,
pageSize
=
10
,
sanctionDate
=
""
,
rule
=
false
)
{
return
request200
(
return
request200
(
request
({
request
({
method
:
"POST"
,
method
:
"POST"
,
...
@@ -300,7 +324,9 @@ export function getEntitiesList(typeName = "实体清单", pageNum = 1, pageSize
...
@@ -300,7 +324,9 @@ export function getEntitiesList(typeName = "实体清单", pageNum = 1, pageSize
data
:
{
data
:
{
typeName
,
typeName
,
pageNum
,
pageNum
,
pageSize
pageSize
,
sanctionDate
,
rule
}
}
})
})
);
);
...
@@ -340,15 +366,16 @@ export function getCompareCountSan(startTime) {
...
@@ -340,15 +366,16 @@ export function getCompareCountSan(startTime) {
* count:number
* count:number
* }[]>}
* }[]>}
*/
*/
export
function
getEntitiesChangeCount
(
dom
ain
,
type
)
{
export
function
getEntitiesChangeCount
(
dom
ianId
,
typeId
)
{
return
request200
(
return
request200
(
request
({
request
({
method
:
"GET"
,
method
:
"GET"
,
// url: '/api/entitiesDataCount/entitiesChangeCount',
// url: '/api/entitiesDataCount/entitiesChangeCount',
url
:
"/api/entitiesDataCount/sanCountByYear"
,
// url: "/api/entitiesDataCount/sanCountByYear",
url
:
"/api/entitiesDataInfo/getCountByDomianAndType"
,
params
:
{
params
:
{
dom
ain
,
dom
ianId
,
type
type
Id
}
}
})
})
);
);
...
@@ -377,11 +404,14 @@ export function getEntitiesGrowthTrend() {
...
@@ -377,11 +404,14 @@ export function getEntitiesGrowthTrend() {
* xAxis: string[]
* xAxis: string[]
* }>}
* }>}
*/
*/
export
function
getEntitiesUpdateCount
()
{
export
function
getEntitiesUpdateCount
(
sanTypeId
=
1
)
{
return
request200
(
return
request200
(
request
({
request
({
method
:
"GET"
,
method
:
"GET"
,
url
:
"/api/entitiesDataCount/entitiesUpdateCount"
url
:
"/api/entitiesDataCount/getAnnualCount"
,
params
:
{
sanTypeId
}
})
})
);
);
}
}
...
@@ -389,11 +419,14 @@ export function getEntitiesUpdateCount() {
...
@@ -389,11 +419,14 @@ export function getEntitiesUpdateCount() {
/**
/**
* 制裁领域分析
* 制裁领域分析
*/
*/
export
function
getSanDomainCount
()
{
export
function
getSanDomainCount
(
rule
)
{
return
request200
(
return
request200
(
request
({
request
({
method
:
"GET"
,
method
:
"GET"
,
url
:
"/api/entitiesDataCount/getSanDomainCount"
url
:
"/api/entitiesDataCount/getSanDomainCount"
,
params
:
{
rule
}
})
})
);
);
}
}
...
...
src/components/button/button.vue
浏览文件 @
2e27cc08
...
@@ -32,6 +32,7 @@ const emit = defineEmits(["click"]);
...
@@ -32,6 +32,7 @@ const emit = defineEmits(["click"]);
cursor
:
pointer
;
cursor
:
pointer
;
padding-left
:
8px
;
padding-left
:
8px
;
padding-right
:
8px
;
padding-right
:
8px
;
flex-shrink
:
0
;
}
}
.activeButton
{
.activeButton
{
border
:
1px
solid
rgb
(
10
,
87
,
166
);
border
:
1px
solid
rgb
(
10
,
87
,
166
);
...
...
src/components/buttonList/buttonList.vue
浏览文件 @
2e27cc08
...
@@ -61,5 +61,6 @@ function setActiveIndex(item) {
...
@@ -61,5 +61,6 @@ function setActiveIndex(item) {
.buttonList
{
.buttonList
{
display
:
flex
;
display
:
flex
;
gap
:
8px
;
gap
:
8px
;
overflow-x
:
auto
;
}
}
</
style
>
</
style
>
src/views/exportControl/analysis/components/fishbone-back.vue
浏览文件 @
2e27cc08
<
template
>
<
template
>
<div
class=
"fishbone"
>
<div
class=
"fishbone"
>
<div
class=
"main-line"
></div>
<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"
>
<div
class=
"left-bone-item"
>
<div
class=
"left-bone-item"
v-for=
"(item, index) in getLeftItems(causeGroup.causes)"
:key=
"index"
>
<div
class=
"icon"
>
<!--
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo1.png"
alt=
""
/>
<img
:src=
"item.picture"
alt=
""
/>
</div>
</div>
-->
<div
class=
"text"
>
{{
"商汤科技"
}}
</div>
<div
class=
"text"
>
{{
item
.
name
}}
</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=
"line"
></div>
<div
class=
"line"
></div>
</div>
</div>
</div>
</div>
<div
class=
"right-bone"
>
<div
class=
"right-bone"
>
<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
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=
"line"
></div>
<div
class=
"text"
>
{{
"华为"
}}
</div>
<div
class=
"text"
>
{{
item
.
name
}}
</div>
<div
class=
"icon"
>
<!--
<div
class=
"icon"
>
<img
src=
"../../assets/images/company-logo2.png"
alt=
""
/>
<img
:src=
"item.picture"
:alt=
"item.name"
/>
</div>
</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>
</div>
</div>
</div>
</div>
</div>
...
@@ -474,12 +27,39 @@
...
@@ -474,12 +27,39 @@
<
script
setup
>
<
script
setup
>
import
{
getChainFishbone
}
from
"@/api/exportControl"
;
import
{
getChainFishbone
}
from
"@/api/exportControl"
;
import
{
onMounted
,
ref
}
from
"vue"
;
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
()
=>
{
onMounted
(
async
()
=>
{
try
{
try
{
const
chainFishboneData
=
await
getChainFishbone
(
chainId
.
value
);
const
chainFishboneData
=
await
getChainFishbone
(
chainId
.
value
);
chainFishbone
.
value
=
chainFishboneData
??
[];
fishboneData
.
value
=
chainFishboneData
??
{
text
:
""
,
causes
:
[]
};
console
.
log
(
"鱼骨图数据:"
,
fishboneData
.
value
);
}
catch
(
error
)
{
}
catch
(
error
)
{
console
.
log
(
error
);
console
.
log
(
error
);
}
}
...
@@ -487,11 +67,14 @@ onMounted(async () => {
...
@@ -487,11 +67,14 @@ onMounted(async () => {
</
script
>
</
script
>
<
style
lang=
"scss"
scoped
>
<
style
lang=
"scss"
scoped
>
/* ... 原有的样式保持不变 ... */
.fishbone
{
.fishbone
{
position
:
relative
;
position
:
relative
;
width
:
100%
;
width
:
100%
;
height
:
100%
;
height
:
100%
;
margin-top
:
40px
;
margin-top
:
40px
;
overflow-x
:
auto
;
.main-line
{
.main-line
{
position
:
absolute
;
position
:
absolute
;
top
:
280px
;
top
:
280px
;
...
@@ -501,6 +84,7 @@ onMounted(async () => {
...
@@ -501,6 +84,7 @@ onMounted(async () => {
background
:
rgba
(
174
,
208
,
255
,
1
);
background
:
rgba
(
174
,
208
,
255
,
1
);
}
}
}
}
.top-bone
{
.top-bone
{
position
:
absolute
;
position
:
absolute
;
top
:
20px
;
top
:
20px
;
...
@@ -517,13 +101,11 @@ onMounted(async () => {
...
@@ -517,13 +101,11 @@ onMounted(async () => {
left
:
-150px
;
left
:
-150px
;
width
:
150px
;
width
:
150px
;
height
:
260px
;
height
:
260px
;
// background: orange;
.left-bone-item
{
.left-bone-item
{
transform
:
skew
(
-30deg
);
transform
:
skew
(
-30deg
);
height
:
35px
;
height
:
35px
;
margin-bottom
:
5px
;
margin-bottom
:
5px
;
margin-top
:
15px
;
margin-top
:
15px
;
// background: #fff;
display
:
flex
;
display
:
flex
;
justify-content
:
flex-end
;
justify-content
:
flex-end
;
.icon
{
.icon
{
...
@@ -537,8 +119,11 @@ onMounted(async () => {
...
@@ -537,8 +119,11 @@ onMounted(async () => {
}
}
.text
{
.text
{
margin-left
:
4px
;
margin-left
:
4px
;
height
:
35
px
;
height
:
70
px
;
line-height
:
35px
;
line-height
:
35px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
}
.line
{
.line
{
margin-left
:
7px
;
margin-left
:
7px
;
...
@@ -556,7 +141,6 @@ onMounted(async () => {
...
@@ -556,7 +141,6 @@ onMounted(async () => {
right
:
-150px
;
right
:
-150px
;
width
:
150px
;
width
:
150px
;
height
:
260px
;
height
:
260px
;
// background: pink;
.right-bone-item
{
.right-bone-item
{
transform
:
skew
(
-30deg
);
transform
:
skew
(
-30deg
);
height
:
35px
;
height
:
35px
;
...
@@ -564,7 +148,6 @@ onMounted(async () => {
...
@@ -564,7 +148,6 @@ onMounted(async () => {
margin-top
:
5px
;
margin-top
:
5px
;
display
:
flex
;
display
:
flex
;
justify-content
:
flex-start
;
justify-content
:
flex-start
;
.line
{
.line
{
margin-right
:
7px
;
margin-right
:
7px
;
margin-top
:
16px
;
margin-top
:
16px
;
...
@@ -572,11 +155,14 @@ onMounted(async () => {
...
@@ -572,11 +155,14 @@ onMounted(async () => {
height
:
2px
;
height
:
2px
;
background
:
rgba
(
174
,
208
,
255
,
1
);
background
:
rgba
(
174
,
208
,
255
,
1
);
}
}
.text
{
.text
{
width
:
100px
;
margin-right
:
4px
;
margin-right
:
4px
;
height
:
35px
;
height
:
35px
;
line-height
:
35px
;
line-height
:
35px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
}
.icon
{
.icon
{
margin-top
:
7px
;
margin-top
:
7px
;
...
@@ -590,6 +176,7 @@ onMounted(async () => {
...
@@ -590,6 +176,7 @@ onMounted(async () => {
}
}
}
}
}
}
.top-bone1
{
.top-bone1
{
position
:
absolute
;
position
:
absolute
;
top
:
20px
;
top
:
20px
;
...
@@ -606,13 +193,11 @@ onMounted(async () => {
...
@@ -606,13 +193,11 @@ onMounted(async () => {
left
:
-150px
;
left
:
-150px
;
width
:
150px
;
width
:
150px
;
height
:
260px
;
height
:
260px
;
// background: orange;
.left-bone-item
{
.left-bone-item
{
transform
:
skew
(
-30deg
);
transform
:
skew
(
-30deg
);
height
:
35px
;
height
:
35px
;
margin-bottom
:
5px
;
margin-bottom
:
5px
;
margin-top
:
15px
;
margin-top
:
15px
;
// background: #fff;
display
:
flex
;
display
:
flex
;
justify-content
:
flex-end
;
justify-content
:
flex-end
;
.icon
{
.icon
{
...
@@ -625,9 +210,13 @@ onMounted(async () => {
...
@@ -625,9 +210,13 @@ onMounted(async () => {
}
}
}
}
.text
{
.text
{
width
:
100px
;
margin-left
:
4px
;
margin-left
:
4px
;
height
:
35px
;
height
:
35px
;
line-height
:
35px
;
line-height
:
35px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
}
.line
{
.line
{
margin-left
:
7px
;
margin-left
:
7px
;
...
@@ -645,7 +234,6 @@ onMounted(async () => {
...
@@ -645,7 +234,6 @@ onMounted(async () => {
right
:
-150px
;
right
:
-150px
;
width
:
150px
;
width
:
150px
;
height
:
260px
;
height
:
260px
;
// background: pink;
.right-bone-item
{
.right-bone-item
{
transform
:
skew
(
-30deg
);
transform
:
skew
(
-30deg
);
height
:
35px
;
height
:
35px
;
...
@@ -653,7 +241,6 @@ onMounted(async () => {
...
@@ -653,7 +241,6 @@ onMounted(async () => {
margin-top
:
5px
;
margin-top
:
5px
;
display
:
flex
;
display
:
flex
;
justify-content
:
flex-start
;
justify-content
:
flex-start
;
.line
{
.line
{
margin-right
:
7px
;
margin-right
:
7px
;
margin-top
:
16px
;
margin-top
:
16px
;
...
@@ -661,11 +248,14 @@ onMounted(async () => {
...
@@ -661,11 +248,14 @@ onMounted(async () => {
height
:
2px
;
height
:
2px
;
background
:
rgba
(
174
,
208
,
255
,
1
);
background
:
rgba
(
174
,
208
,
255
,
1
);
}
}
.text
{
.text
{
width
:
100px
;
margin-right
:
4px
;
margin-right
:
4px
;
height
:
35px
;
height
:
35px
;
line-height
:
35px
;
line-height
:
35px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
}
.icon
{
.icon
{
margin-top
:
7px
;
margin-top
:
7px
;
...
@@ -679,6 +269,7 @@ onMounted(async () => {
...
@@ -679,6 +269,7 @@ onMounted(async () => {
}
}
}
}
}
}
.top-bone2
{
.top-bone2
{
position
:
absolute
;
position
:
absolute
;
top
:
20px
;
top
:
20px
;
...
@@ -695,13 +286,11 @@ onMounted(async () => {
...
@@ -695,13 +286,11 @@ onMounted(async () => {
left
:
-150px
;
left
:
-150px
;
width
:
150px
;
width
:
150px
;
height
:
260px
;
height
:
260px
;
// background: orange;
.left-bone-item
{
.left-bone-item
{
transform
:
skew
(
-30deg
);
transform
:
skew
(
-30deg
);
height
:
35px
;
height
:
35px
;
margin-bottom
:
5px
;
margin-bottom
:
5px
;
margin-top
:
15px
;
margin-top
:
15px
;
// background: #fff;
display
:
flex
;
display
:
flex
;
justify-content
:
flex-end
;
justify-content
:
flex-end
;
.icon
{
.icon
{
...
@@ -714,9 +303,13 @@ onMounted(async () => {
...
@@ -714,9 +303,13 @@ onMounted(async () => {
}
}
}
}
.text
{
.text
{
width
:
100px
;
margin-left
:
4px
;
margin-left
:
4px
;
height
:
35px
;
height
:
35px
;
line-height
:
35px
;
line-height
:
35px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
}
.line
{
.line
{
margin-left
:
7px
;
margin-left
:
7px
;
...
@@ -734,7 +327,6 @@ onMounted(async () => {
...
@@ -734,7 +327,6 @@ onMounted(async () => {
right
:
-150px
;
right
:
-150px
;
width
:
150px
;
width
:
150px
;
height
:
260px
;
height
:
260px
;
// background: pink;
.right-bone-item
{
.right-bone-item
{
transform
:
skew
(
-30deg
);
transform
:
skew
(
-30deg
);
height
:
35px
;
height
:
35px
;
...
@@ -742,7 +334,6 @@ onMounted(async () => {
...
@@ -742,7 +334,6 @@ onMounted(async () => {
margin-top
:
5px
;
margin-top
:
5px
;
display
:
flex
;
display
:
flex
;
justify-content
:
flex-start
;
justify-content
:
flex-start
;
.line
{
.line
{
margin-right
:
7px
;
margin-right
:
7px
;
margin-top
:
16px
;
margin-top
:
16px
;
...
@@ -750,11 +341,14 @@ onMounted(async () => {
...
@@ -750,11 +341,14 @@ onMounted(async () => {
height
:
2px
;
height
:
2px
;
background
:
rgba
(
174
,
208
,
255
,
1
);
background
:
rgba
(
174
,
208
,
255
,
1
);
}
}
.text
{
.text
{
width
:
100px
;
margin-right
:
4px
;
margin-right
:
4px
;
height
:
35px
;
height
:
35px
;
line-height
:
35px
;
line-height
:
35px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
}
.icon
{
.icon
{
margin-top
:
7px
;
margin-top
:
7px
;
...
@@ -768,6 +362,7 @@ onMounted(async () => {
...
@@ -768,6 +362,7 @@ onMounted(async () => {
}
}
}
}
}
}
.bottom-bone
{
.bottom-bone
{
position
:
absolute
;
position
:
absolute
;
top
:
280px
;
top
:
280px
;
...
@@ -784,13 +379,11 @@ onMounted(async () => {
...
@@ -784,13 +379,11 @@ onMounted(async () => {
left
:
-150px
;
left
:
-150px
;
width
:
150px
;
width
:
150px
;
height
:
260px
;
height
:
260px
;
// background: orange;
.left-bone-item
{
.left-bone-item
{
transform
:
skew
(
30deg
);
transform
:
skew
(
30deg
);
height
:
35px
;
height
:
35px
;
margin-bottom
:
5px
;
margin-bottom
:
5px
;
margin-top
:
15px
;
margin-top
:
15px
;
// background: #fff;
display
:
flex
;
display
:
flex
;
justify-content
:
flex-end
;
justify-content
:
flex-end
;
.icon
{
.icon
{
...
@@ -803,9 +396,13 @@ onMounted(async () => {
...
@@ -803,9 +396,13 @@ onMounted(async () => {
}
}
}
}
.text
{
.text
{
width
:
100px
;
margin-left
:
4px
;
margin-left
:
4px
;
height
:
35px
;
height
:
35px
;
line-height
:
35px
;
line-height
:
35px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
}
.line
{
.line
{
margin-left
:
7px
;
margin-left
:
7px
;
...
@@ -823,7 +420,6 @@ onMounted(async () => {
...
@@ -823,7 +420,6 @@ onMounted(async () => {
right
:
-150px
;
right
:
-150px
;
width
:
150px
;
width
:
150px
;
height
:
260px
;
height
:
260px
;
// background: pink;
.right-bone-item
{
.right-bone-item
{
transform
:
skew
(
30deg
);
transform
:
skew
(
30deg
);
height
:
35px
;
height
:
35px
;
...
@@ -831,7 +427,6 @@ onMounted(async () => {
...
@@ -831,7 +427,6 @@ onMounted(async () => {
margin-top
:
5px
;
margin-top
:
5px
;
display
:
flex
;
display
:
flex
;
justify-content
:
flex-start
;
justify-content
:
flex-start
;
.line
{
.line
{
margin-right
:
7px
;
margin-right
:
7px
;
margin-top
:
16px
;
margin-top
:
16px
;
...
@@ -839,11 +434,14 @@ onMounted(async () => {
...
@@ -839,11 +434,14 @@ onMounted(async () => {
height
:
2px
;
height
:
2px
;
background
:
rgba
(
174
,
208
,
255
,
1
);
background
:
rgba
(
174
,
208
,
255
,
1
);
}
}
.text
{
.text
{
width
:
100px
;
margin-right
:
4px
;
margin-right
:
4px
;
height
:
35px
;
height
:
35px
;
line-height
:
35px
;
line-height
:
35px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
}
.icon
{
.icon
{
margin-top
:
7px
;
margin-top
:
7px
;
...
@@ -857,6 +455,7 @@ onMounted(async () => {
...
@@ -857,6 +455,7 @@ onMounted(async () => {
}
}
}
}
}
}
.bottom-bone1
{
.bottom-bone1
{
position
:
absolute
;
position
:
absolute
;
top
:
280px
;
top
:
280px
;
...
@@ -873,13 +472,11 @@ onMounted(async () => {
...
@@ -873,13 +472,11 @@ onMounted(async () => {
left
:
-150px
;
left
:
-150px
;
width
:
150px
;
width
:
150px
;
height
:
260px
;
height
:
260px
;
// background: orange;
.left-bone-item
{
.left-bone-item
{
transform
:
skew
(
30deg
);
transform
:
skew
(
30deg
);
height
:
35px
;
height
:
35px
;
margin-bottom
:
5px
;
margin-bottom
:
5px
;
margin-top
:
15px
;
margin-top
:
15px
;
// background: #fff;
display
:
flex
;
display
:
flex
;
justify-content
:
flex-end
;
justify-content
:
flex-end
;
.icon
{
.icon
{
...
@@ -892,9 +489,13 @@ onMounted(async () => {
...
@@ -892,9 +489,13 @@ onMounted(async () => {
}
}
}
}
.text
{
.text
{
width
:
100px
;
margin-left
:
4px
;
margin-left
:
4px
;
height
:
35px
;
height
:
35px
;
line-height
:
35px
;
line-height
:
35px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
}
.line
{
.line
{
margin-left
:
7px
;
margin-left
:
7px
;
...
@@ -912,7 +513,6 @@ onMounted(async () => {
...
@@ -912,7 +513,6 @@ onMounted(async () => {
right
:
-150px
;
right
:
-150px
;
width
:
150px
;
width
:
150px
;
height
:
260px
;
height
:
260px
;
// background: pink;
.right-bone-item
{
.right-bone-item
{
transform
:
skew
(
30deg
);
transform
:
skew
(
30deg
);
height
:
35px
;
height
:
35px
;
...
@@ -920,7 +520,6 @@ onMounted(async () => {
...
@@ -920,7 +520,6 @@ onMounted(async () => {
margin-top
:
5px
;
margin-top
:
5px
;
display
:
flex
;
display
:
flex
;
justify-content
:
flex-start
;
justify-content
:
flex-start
;
.line
{
.line
{
margin-right
:
7px
;
margin-right
:
7px
;
margin-top
:
16px
;
margin-top
:
16px
;
...
@@ -928,11 +527,14 @@ onMounted(async () => {
...
@@ -928,11 +527,14 @@ onMounted(async () => {
height
:
2px
;
height
:
2px
;
background
:
rgba
(
174
,
208
,
255
,
1
);
background
:
rgba
(
174
,
208
,
255
,
1
);
}
}
.text
{
.text
{
width
:
100px
;
margin-right
:
4px
;
margin-right
:
4px
;
height
:
35px
;
height
:
35px
;
line-height
:
35px
;
line-height
:
35px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
}
.icon
{
.icon
{
margin-top
:
7px
;
margin-top
:
7px
;
...
@@ -946,6 +548,7 @@ onMounted(async () => {
...
@@ -946,6 +548,7 @@ onMounted(async () => {
}
}
}
}
}
}
.bottom-bone2
{
.bottom-bone2
{
position
:
absolute
;
position
:
absolute
;
top
:
280px
;
top
:
280px
;
...
@@ -962,13 +565,11 @@ onMounted(async () => {
...
@@ -962,13 +565,11 @@ onMounted(async () => {
left
:
-150px
;
left
:
-150px
;
width
:
150px
;
width
:
150px
;
height
:
260px
;
height
:
260px
;
// background: orange;
.left-bone-item
{
.left-bone-item
{
transform
:
skew
(
30deg
);
transform
:
skew
(
30deg
);
height
:
35px
;
height
:
35px
;
margin-bottom
:
5px
;
margin-bottom
:
5px
;
margin-top
:
15px
;
margin-top
:
15px
;
// background: #fff;
display
:
flex
;
display
:
flex
;
justify-content
:
flex-end
;
justify-content
:
flex-end
;
.icon
{
.icon
{
...
@@ -981,9 +582,13 @@ onMounted(async () => {
...
@@ -981,9 +582,13 @@ onMounted(async () => {
}
}
}
}
.text
{
.text
{
width
:
100px
;
margin-left
:
4px
;
margin-left
:
4px
;
height
:
35px
;
height
:
35px
;
line-height
:
35px
;
line-height
:
35px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
}
.line
{
.line
{
margin-left
:
7px
;
margin-left
:
7px
;
...
@@ -1001,7 +606,6 @@ onMounted(async () => {
...
@@ -1001,7 +606,6 @@ onMounted(async () => {
right
:
-150px
;
right
:
-150px
;
width
:
150px
;
width
:
150px
;
height
:
260px
;
height
:
260px
;
// background: pink;
.right-bone-item
{
.right-bone-item
{
transform
:
skew
(
30deg
);
transform
:
skew
(
30deg
);
height
:
35px
;
height
:
35px
;
...
@@ -1009,7 +613,6 @@ onMounted(async () => {
...
@@ -1009,7 +613,6 @@ onMounted(async () => {
margin-top
:
5px
;
margin-top
:
5px
;
display
:
flex
;
display
:
flex
;
justify-content
:
flex-start
;
justify-content
:
flex-start
;
.line
{
.line
{
margin-right
:
7px
;
margin-right
:
7px
;
margin-top
:
16px
;
margin-top
:
16px
;
...
@@ -1017,11 +620,14 @@ onMounted(async () => {
...
@@ -1017,11 +620,14 @@ onMounted(async () => {
height
:
2px
;
height
:
2px
;
background
:
rgba
(
174
,
208
,
255
,
1
);
background
:
rgba
(
174
,
208
,
255
,
1
);
}
}
.text
{
.text
{
width
:
100px
;
margin-right
:
4px
;
margin-right
:
4px
;
height
:
35px
;
height
:
35px
;
line-height
:
35px
;
line-height
:
35px
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
}
.icon
{
.icon
{
margin-top
:
7px
;
margin-top
:
7px
;
...
...
src/views/exportControl/analysis/components/fishbone-mock.json
浏览文件 @
2e27cc08
[
[
{
{
"id"
:
null
,
"yearDomainCount"
:
[
"name"
:
"2025-10-09"
,
{
"count"
:
10
"sanTypeName"
:
null
,
},
"year"
:
2020
,
{
"domainCountInfo"
:
[
"id"
:
null
,
{
"name"
:
"2025-10-08"
,
"year"
:
2020
,
"count"
:
8
"id"
:
"1"
,
},
"name"
:
"人工智能"
,
{
"count"
:
11
"id"
:
null
,
},
"name"
:
"2025-09-16"
,
{
"count"
:
16
"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
浏览文件 @
2e27cc08
<
template
>
<
template
>
<div
class=
"fishbone"
>
<div
class=
"fishbone-wrapper"
>
<div
class=
"main-line"
></div>
<div
class=
"fishbone-scroll-container"
ref=
"scrollContainerRef"
>
<div
v-for=
"(causeGroup, groupIndex) in fishboneData.causes"
:key=
"groupIndex"
:class=
"getBoneClass(groupIndex)"
>
<div
class=
"fishbone"
ref=
"fishboneRef"
v-if=
"fishboneData.length > 0"
>
<div
class=
"left-bone"
>
<div
class=
"main-line"
:style=
"
{ width: (fishboneData.length / 2) * 340 - 275 + 'px' }">
</div>
<div
class=
"left-bone-item"
v-for=
"(item, index) in getLeftItems(causeGroup.causes)"
:key=
"index"
>
<!-- 奇数索引的数据组放在上方 -->
<!--
<div
class=
"icon"
>
<div
<img
:src=
"item.picture"
alt=
""
/>
v-for=
"(causeGroup, groupIndex) in getOddGroups(fishboneData)"
</div>
-->
:key=
"'top-' + groupIndex"
<div
class=
"text"
>
{{
item
.
name
}}
</div>
:class=
"getTopBoneClass(groupIndex)"
<div
class=
"line"
></div>
: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>
<div
class=
"right-bone"
>
<!-- 偶数索引的数据组放在下方 -->
<div
class=
"right-bone-item"
v-for=
"(item, index) in getRightItems(causeGroup.causes)"
:key=
"index"
>
<div
<div
class=
"line"
></div>
v-for=
"(causeGroup, groupIndex) in getEvenGroups(fishboneData)"
<div
class=
"text"
>
{{
item
.
name
}}
</div>
:key=
"'bottom-' + groupIndex"
<!--
<div
class=
"icon"
>
:class=
"getBottomBoneClass(groupIndex)"
<img
:src=
"item.picture"
:alt=
"item.name"
/>
:style=
"
{ left: groupIndex * 300 + 200 + 'px' }"
</div>
-->
>
<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>
</div>
<div
v-else
style=
"display: flex; justify-content: center; align-items: center; height: 200px; width: 100%"
>
<el-empty
description=
"暂无相关数据"
/>
</div>
</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>
</div>
</
template
>
</
template
>
<
script
setup
>
<
script
setup
>
import
{
getChainFishbone
}
from
"@/api/exportControl"
;
import
{
getChainFishbone
}
from
"@/api/exportControl"
;
import
{
onMounted
,
ref
}
from
"vue"
;
import
{
onMounted
,
ref
,
nextTick
,
watch
}
from
"vue"
;
// 这儿需要接收父组件传递来的产业链ID
const
chainId
=
ref
(
1
);
const
props
=
defineProps
({
const
fishboneData
=
ref
({
chainId
:
{
text
:
""
,
type
:
Number
,
causes
:
[]
default
:
1
}
});
});
// 根据索引确定鱼骨图位置类名
// const chainId = ref(1);
const
getBoneClass
=
index
=>
{
const
fishboneData
=
ref
([]);
const
positions
=
[
"top-bone"
,
"top-bone1"
,
"top-bone2"
,
"bottom-bone"
,
"bottom-bone1"
,
"bottom-bone2"
];
const
scrollContainerRef
=
ref
(
null
);
return
positions
[
index
]
||
"top-bone"
;
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 => {
...
@@ -52,32 +135,109 @@ const getRightItems = items => {
return
items
.
slice
(
midpoint
);
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
()
=>
{
onMounted
(
async
()
=>
{
try
{
try
{
const
chainFishboneData
=
await
getChainFishbone
(
chainId
.
value
);
const
chainFishboneData
=
await
getChainFishbone
(
props
.
chainId
);
fishboneData
.
value
=
chainFishboneData
??
{
fishboneData
.
value
=
chainFishboneData
?.
causes
??
[];
text
:
""
,
causes
:
[]
// 等待DOM更新后检查是否需要滚动
};
nextTick
(()
=>
{
if
(
scrollContainerRef
.
value
&&
fishboneRef
.
value
)
{
showScrollIndicator
.
value
=
fishboneRef
.
value
.
scrollWidth
>
scrollContainerRef
.
value
.
clientWidth
;
updateScrollState
();
}
});
console
.
log
(
"鱼骨图数据:"
,
fishboneData
.
value
);
}
catch
(
error
)
{
}
catch
(
error
)
{
console
.
log
(
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
>
</
script
>
<
style
lang=
"scss"
scoped
>
<
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
{
.fishbone
{
position
:
relative
;
position
:
relative
;
width
:
100%
;
width
:
fit-content
;
height
:
100%
;
height
:
100%
;
margin-top
:
40px
;
margin-top
:
40px
;
min-width
:
100%
;
padding-left
:
275px
;
.main-line
{
.main-line
{
position
:
absolute
;
margin-top
:
280px
;
top
:
280px
;
width
:
1888px
;
right
:
0
;
width
:
888px
;
height
:
3px
;
height
:
3px
;
background
:
rgba
(
174
,
208
,
255
,
1
);
background
:
rgba
(
174
,
208
,
255
,
1
);
}
}
...
@@ -106,15 +266,6 @@ onMounted(async () => {
...
@@ -106,15 +266,6 @@ onMounted(async () => {
margin-top
:
15px
;
margin-top
:
15px
;
display
:
flex
;
display
:
flex
;
justify-content
:
flex-end
;
justify-content
:
flex-end
;
.icon
{
margin-top
:
7px
;
width
:
20px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.text
{
.text
{
margin-left
:
4px
;
margin-left
:
4px
;
height
:
70px
;
height
:
70px
;
...
@@ -154,7 +305,7 @@ onMounted(async () => {
...
@@ -154,7 +305,7 @@ onMounted(async () => {
background
:
rgba
(
174
,
208
,
255
,
1
);
background
:
rgba
(
174
,
208
,
255
,
1
);
}
}
.text
{
.text
{
width
:
100px
;
width
:
100px
;
margin-right
:
4px
;
margin-right
:
4px
;
height
:
35px
;
height
:
35px
;
line-height
:
35px
;
line-height
:
35px
;
...
@@ -162,15 +313,6 @@ onMounted(async () => {
...
@@ -162,15 +313,6 @@ onMounted(async () => {
text-overflow
:
ellipsis
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
white-space
:
nowrap
;
}
}
.icon
{
margin-top
:
7px
;
width
:
20px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
}
}
}
}
}
}
...
@@ -198,17 +340,8 @@ onMounted(async () => {
...
@@ -198,17 +340,8 @@ onMounted(async () => {
margin-top
:
15px
;
margin-top
:
15px
;
display
:
flex
;
display
:
flex
;
justify-content
:
flex-end
;
justify-content
:
flex-end
;
.icon
{
margin-top
:
7px
;
width
:
20px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.text
{
.text
{
width
:
100px
;
width
:
100px
;
margin-left
:
4px
;
margin-left
:
4px
;
height
:
35px
;
height
:
35px
;
line-height
:
35px
;
line-height
:
35px
;
...
@@ -247,7 +380,7 @@ onMounted(async () => {
...
@@ -247,7 +380,7 @@ onMounted(async () => {
background
:
rgba
(
174
,
208
,
255
,
1
);
background
:
rgba
(
174
,
208
,
255
,
1
);
}
}
.text
{
.text
{
width
:
100px
;
width
:
100px
;
margin-right
:
4px
;
margin-right
:
4px
;
height
:
35px
;
height
:
35px
;
line-height
:
35px
;
line-height
:
35px
;
...
@@ -255,15 +388,6 @@ onMounted(async () => {
...
@@ -255,15 +388,6 @@ onMounted(async () => {
text-overflow
:
ellipsis
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
white-space
:
nowrap
;
}
}
.icon
{
margin-top
:
7px
;
width
:
20px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
}
}
}
}
}
}
...
@@ -291,17 +415,8 @@ onMounted(async () => {
...
@@ -291,17 +415,8 @@ onMounted(async () => {
margin-top
:
15px
;
margin-top
:
15px
;
display
:
flex
;
display
:
flex
;
justify-content
:
flex-end
;
justify-content
:
flex-end
;
.icon
{
margin-top
:
7px
;
width
:
20px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.text
{
.text
{
width
:
100px
;
width
:
100px
;
margin-left
:
4px
;
margin-left
:
4px
;
height
:
35px
;
height
:
35px
;
line-height
:
35px
;
line-height
:
35px
;
...
@@ -340,7 +455,7 @@ onMounted(async () => {
...
@@ -340,7 +455,7 @@ onMounted(async () => {
background
:
rgba
(
174
,
208
,
255
,
1
);
background
:
rgba
(
174
,
208
,
255
,
1
);
}
}
.text
{
.text
{
width
:
100px
;
width
:
100px
;
margin-right
:
4px
;
margin-right
:
4px
;
height
:
35px
;
height
:
35px
;
line-height
:
35px
;
line-height
:
35px
;
...
@@ -348,15 +463,6 @@ onMounted(async () => {
...
@@ -348,15 +463,6 @@ onMounted(async () => {
text-overflow
:
ellipsis
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
white-space
:
nowrap
;
}
}
.icon
{
margin-top
:
7px
;
width
:
20px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
}
}
}
}
}
}
...
@@ -384,17 +490,8 @@ onMounted(async () => {
...
@@ -384,17 +490,8 @@ onMounted(async () => {
margin-top
:
15px
;
margin-top
:
15px
;
display
:
flex
;
display
:
flex
;
justify-content
:
flex-end
;
justify-content
:
flex-end
;
.icon
{
margin-top
:
7px
;
width
:
20px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.text
{
.text
{
width
:
100px
;
width
:
100px
;
margin-left
:
4px
;
margin-left
:
4px
;
height
:
35px
;
height
:
35px
;
line-height
:
35px
;
line-height
:
35px
;
...
@@ -433,7 +530,7 @@ onMounted(async () => {
...
@@ -433,7 +530,7 @@ onMounted(async () => {
background
:
rgba
(
174
,
208
,
255
,
1
);
background
:
rgba
(
174
,
208
,
255
,
1
);
}
}
.text
{
.text
{
width
:
100px
;
width
:
100px
;
margin-right
:
4px
;
margin-right
:
4px
;
height
:
35px
;
height
:
35px
;
line-height
:
35px
;
line-height
:
35px
;
...
@@ -441,15 +538,6 @@ onMounted(async () => {
...
@@ -441,15 +538,6 @@ onMounted(async () => {
text-overflow
:
ellipsis
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
white-space
:
nowrap
;
}
}
.icon
{
margin-top
:
7px
;
width
:
20px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
}
}
}
}
}
}
...
@@ -477,17 +565,8 @@ onMounted(async () => {
...
@@ -477,17 +565,8 @@ onMounted(async () => {
margin-top
:
15px
;
margin-top
:
15px
;
display
:
flex
;
display
:
flex
;
justify-content
:
flex-end
;
justify-content
:
flex-end
;
.icon
{
margin-top
:
7px
;
width
:
20px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.text
{
.text
{
width
:
100px
;
width
:
100px
;
margin-left
:
4px
;
margin-left
:
4px
;
height
:
35px
;
height
:
35px
;
line-height
:
35px
;
line-height
:
35px
;
...
@@ -526,7 +605,7 @@ onMounted(async () => {
...
@@ -526,7 +605,7 @@ onMounted(async () => {
background
:
rgba
(
174
,
208
,
255
,
1
);
background
:
rgba
(
174
,
208
,
255
,
1
);
}
}
.text
{
.text
{
width
:
100px
;
width
:
100px
;
margin-right
:
4px
;
margin-right
:
4px
;
height
:
35px
;
height
:
35px
;
line-height
:
35px
;
line-height
:
35px
;
...
@@ -534,15 +613,6 @@ onMounted(async () => {
...
@@ -534,15 +613,6 @@ onMounted(async () => {
text-overflow
:
ellipsis
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
white-space
:
nowrap
;
}
}
.icon
{
margin-top
:
7px
;
width
:
20px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
}
}
}
}
}
}
...
@@ -570,17 +640,8 @@ onMounted(async () => {
...
@@ -570,17 +640,8 @@ onMounted(async () => {
margin-top
:
15px
;
margin-top
:
15px
;
display
:
flex
;
display
:
flex
;
justify-content
:
flex-end
;
justify-content
:
flex-end
;
.icon
{
margin-top
:
7px
;
width
:
20px
;
height
:
20px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.text
{
.text
{
width
:
100px
;
width
:
100px
;
margin-left
:
4px
;
margin-left
:
4px
;
height
:
35px
;
height
:
35px
;
line-height
:
35px
;
line-height
:
35px
;
...
@@ -627,16 +688,49 @@ onMounted(async () => {
...
@@ -627,16 +688,49 @@ onMounted(async () => {
text-overflow
:
ellipsis
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
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
>
</
style
>
src/views/exportControl/analysis/components/influencePanel2.vue
浏览文件 @
2e27cc08
...
@@ -25,7 +25,7 @@
...
@@ -25,7 +25,7 @@
<div
class=
"chartsWrap"
>
<div
class=
"chartsWrap"
>
<div
class=
"right-main-content"
>
<div
class=
"right-main-content"
>
<div
class=
"right-main-content-main"
>
<div
class=
"right-main-content-main"
>
<Fishbone
/>
<Fishbone
:chainId=
"activeButtonId"
/>
</div>
</div>
<div
class=
"right-main-content-footer"
>
<div
class=
"right-main-content-footer"
>
<div
class=
"footer-item1"
>
<div
class=
"footer-item1"
>
...
@@ -76,30 +76,12 @@ import Echarts from "@/components/Chart/index.vue";
...
@@ -76,30 +76,12 @@ import Echarts from "@/components/Chart/index.vue";
import
Hint
from
"./hint.vue"
;
import
Hint
from
"./hint.vue"
;
import
ButtonList
from
"@/components/buttonList/buttonList.vue"
;
import
ButtonList
from
"@/components/buttonList/buttonList.vue"
;
import
Fishbone
from
"./fishbone.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
{
getHorizontalBarChart2
}
from
"../../utils/charts"
;
import
{
getDomainDistribution
,
getChainEntities
}
from
"@/api/exportControl"
;
import
{
getDomainDistribution
,
getChainEntities
}
from
"@/api/exportControl"
;
import
{
useRoute
}
from
"vue-router"
;
import
{
useRoute
}
from
"vue-router"
;
const
route
=
useRoute
();
const
route
=
useRoute
();
const
buttonList
=
ref
([
const
buttonList
=
ref
([]);
{
id
:
1
,
text
:
"新能源"
},
const
activeButtonId
=
ref
(
buttonList
.
value
[
0
]?.
id
||
1
);
{
id
:
2
,
text
:
"半导体"
},
{
id
:
3
,
text
:
"跨境电商"
},
{
id
:
4
,
text
:
"金融业"
},
{
id
:
5
,
text
:
"军工"
},
{
id
:
6
,
text
:
"贸易"
}
]);
const
activeButtonId
=
ref
(
buttonList
.
value
[
0
].
id
);
const
setActiveButtonId
=
id
=>
{
const
setActiveButtonId
=
id
=>
{
activeButtonId
.
value
=
id
;
activeButtonId
.
value
=
id
;
};
};
...
@@ -178,10 +160,12 @@ const fetchDomainDistribution = async () => {
...
@@ -178,10 +160,12 @@ const fetchDomainDistribution = async () => {
horizontalBarOptions
.
value
=
getHorizontalBarChart2
(
yAxisData
,
seriesData
,
false
);
horizontalBarOptions
.
value
=
getHorizontalBarChart2
(
yAxisData
,
seriesData
,
false
);
// 更新buttonList
// 更新buttonList
buttonList
.
value
=
sortedData
.
map
(
item
=>
({
buttonList
.
value
=
sortedData
id
:
item
.
id
,
.
map
(
item
=>
({
text
:
item
.
name
id
:
item
.
id
,
}));
text
:
item
.
name
}))
.
sort
((
a
,
b
)
=>
a
.
id
-
b
.
id
);
console
.
log
(
"buttonList.value"
,
buttonList
.
value
);
console
.
log
(
"buttonList.value"
,
buttonList
.
value
);
setActiveButtonId
(
buttonList
.
value
[
0
].
id
);
setActiveButtonId
(
buttonList
.
value
[
0
].
id
);
}
}
...
...
src/views/exportControl/analysis/components/mapCharts.vue
浏览文件 @
2e27cc08
...
@@ -8,9 +8,23 @@
...
@@ -8,9 +8,23 @@
import
Echarts
from
"@/components/Chart/index.vue"
;
import
Echarts
from
"@/components/Chart/index.vue"
;
import
{
getMapOption
}
from
"../../utils/charts"
;
import
{
getMapOption
}
from
"../../utils/charts"
;
import
{
ref
,
onMounted
,
shallowRef
}
from
"vue"
;
import
{
ref
,
onMounted
,
shallowRef
}
from
"vue"
;
import
{
getAreaDistribution
}
from
"@/api/exportControl"
;
// 这儿接收父组件传递过来的date参数
const
props
=
defineProps
({
date
:
{
type
:
String
,
default
:
""
}
});
const
mapOption
=
shallowRef
({});
const
mapOption
=
shallowRef
({});
onMounted
(()
=>
{
onMounted
(()
=>
{
mapOption
.
value
=
getMapOption
();
mapOption
.
value
=
getMapOption
();
// 区域分布查询
getAreaDistribution
(
props
.
date
).
then
(
res
=>
{
console
.
log
(
"res"
,
res
);
});
});
});
</
script
>
</
script
>
...
...
src/views/exportControl/analysis/components/panel1.vue
浏览文件 @
2e27cc08
...
@@ -8,6 +8,7 @@
...
@@ -8,6 +8,7 @@
size="mini"
size="mini"
v-model="domainValue"
v-model="domainValue"
placeholder="领域选择"
placeholder="领域选择"
@change="handleDomainChange"
>
>
<el-option
v-for=
"item in domainOptions"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
>
<el-option
v-for=
"item in domainOptions"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
>
</el-option>
</el-option>
...
@@ -24,7 +25,8 @@
...
@@ -24,7 +25,8 @@
</
template
>
</
template
>
<div
class=
"subPanel1"
>
<div
class=
"subPanel1"
>
<div
class=
"chartsWrap"
:style=
"{ paddingBottom: '10px' }"
>
<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>
</div>
<Hint
text=
"近几次新增受制裁实体中,中国实体占比提高,美方针对中国的出口管制风险显著增加。"
></Hint>
<Hint
text=
"近几次新增受制裁实体中,中国实体占比提高,美方针对中国的出口管制风险显著增加。"
></Hint>
</div>
</div>
...
@@ -123,7 +125,7 @@ onMounted(async () => {
...
@@ -123,7 +125,7 @@ onMounted(async () => {
try
{
try
{
const
[
entitiesGrowthTrendData
,
entitiesUpdateCountData
]
=
await
Promise
.
all
([
const
[
entitiesGrowthTrendData
,
entitiesUpdateCountData
]
=
await
Promise
.
all
([
getEntitiesGrowthTrend
(),
getEntitiesGrowthTrend
(),
getEntitiesUpdateCount
()
getEntitiesUpdateCount
(
1
)
]);
]);
const
list
=
_
.
reverse
(
entitiesGrowthTrendData
);
const
list
=
_
.
reverse
(
entitiesGrowthTrendData
);
...
@@ -133,12 +135,25 @@ onMounted(async () => {
...
@@ -133,12 +135,25 @@ onMounted(async () => {
});
});
line1Option
.
value
=
getLineChart
({
xAxisData
,
seriesData
,
name
:
"增长趋势"
,
color
:
"rgba(146, 84, 222, 1)"
},
true
);
line1Option
.
value
=
getLineChart
({
xAxisData
,
seriesData
,
name
:
"增长趋势"
,
color
:
"rgba(146, 84, 222, 1)"
},
true
);
bar2Option
.
value
=
getBarChart
(
if
(
entitiesUpdateCountData
&&
Array
.
isArray
(
entitiesUpdateCountData
))
{
_
.
reverse
(
entitiesUpdateCountData
.
xAxis
),
const
sortedData
=
_
.
sortBy
(
entitiesUpdateCountData
,
"year"
);
_
.
reverse
(
entitiesUpdateCountData
.
series
),
[
"rgba(22, 119, 255, 1)"
,
"rgba(22, 119, 255, 0)"
],
// 提取 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
);
await
fetchKeyEntityList
(
route
.
query
.
startTime
);
}
catch
(
err
)
{
}
catch
(
err
)
{
...
@@ -248,11 +263,13 @@ const typeOptions = [
...
@@ -248,11 +263,13 @@ const typeOptions = [
const
domainValue
=
ref
(
domainOptions
[
0
].
value
);
const
domainValue
=
ref
(
domainOptions
[
0
].
value
);
const
typeValue
=
ref
(
typeOptions
[
0
].
value
);
const
typeValue
=
ref
(
typeOptions
[
0
].
value
);
const
bar1Option
=
shallowRef
({});
const
bar1Option
=
shallowRef
({});
const
bar1DataIsEmpty
=
ref
(
false
);
watch
(
watch
(
[
domainValue
,
typeValue
],
[
domainValue
,
typeValue
],
async
([
domain
,
type
])
=>
{
async
([
domain
,
type
])
=>
{
let
EntitiesChangeCount
=
await
getEntitiesChangeCount
(
domain
,
type
);
let
EntitiesChangeCount
=
await
getEntitiesChangeCount
(
domain
,
type
);
EntitiesChangeCount
=
_
.
reverse
(
EntitiesChangeCount
);
EntitiesChangeCount
=
_
.
reverse
(
EntitiesChangeCount
);
bar1DataIsEmpty
.
value
=
EntitiesChangeCount
.
length
===
0
;
bar1Option
.
value
=
getBarChart
(
bar1Option
.
value
=
getBarChart
(
_
.
map
(
EntitiesChangeCount
,
"year"
),
_
.
map
(
EntitiesChangeCount
,
"year"
),
_
.
map
(
EntitiesChangeCount
,
"count"
),
_
.
map
(
EntitiesChangeCount
,
"count"
),
...
@@ -317,6 +334,10 @@ watch(
...
@@ -317,6 +334,10 @@ watch(
await
fetchKeyEntityList
(
route
.
query
.
startTime
,
newVal
);
await
fetchKeyEntityList
(
route
.
query
.
startTime
,
newVal
);
},
300
)
},
300
)
);
);
const
handleDomainChange
=
async
domain
=>
{
await
fetchKeyEntityList
(
route
.
query
.
startTime
,
value3
.
value
,
domain
);
};
</
script
>
</
script
>
<
style
lang=
"scss"
scoped
>
<
style
lang=
"scss"
scoped
>
...
...
src/views/exportControl/analysis/components/panel3.vue
浏览文件 @
2e27cc08
...
@@ -19,7 +19,7 @@
...
@@ -19,7 +19,7 @@
</CardCustom>
</CardCustom>
</div>
</div>
<div
class=
"row"
>
<div
class=
"row"
>
<CardCustom
title=
"历
次
制裁涉及领域数"
:style=
"
{ width: '798px', height: '422px' }">
<CardCustom
title=
"历
年
制裁涉及领域数"
:style=
"
{ width: '798px', height: '422px' }">
<div
class=
"subPanel3"
>
<div
class=
"subPanel3"
>
<div
class=
"chartsWrap"
:style=
"
{ paddingBottom: '10px' }">
<div
class=
"chartsWrap"
:style=
"
{ paddingBottom: '10px' }">
<Echarts
:option=
"bar2Option"
height=
"100%"
></Echarts>
<Echarts
:option=
"bar2Option"
height=
"100%"
></Echarts>
...
@@ -46,7 +46,12 @@ import { Search } from "@element-plus/icons-vue";
...
@@ -46,7 +46,12 @@ import { Search } from "@element-plus/icons-vue";
import
Echarts
from
"@/components/Chart/index.vue"
;
import
Echarts
from
"@/components/Chart/index.vue"
;
import
{
getBarChart
,
getLineChart
,
getPieOption1
}
from
"../../utils/charts"
;
import
{
getBarChart
,
getLineChart
,
getPieOption1
}
from
"../../utils/charts"
;
import
Hint
from
"./hint.vue"
;
import
Hint
from
"./hint.vue"
;
import
{
getEntitiesAreaCountByYear
,
getEntitiesDomainCount
,
getCountThisDomain
}
from
"@/api/exportControl"
;
import
{
getEntitiesAreaCountByYear
,
getEntitiesDomainCount
,
getCountThisDomain
,
getDomainDistribution
}
from
"@/api/exportControl"
;
import
_
from
"lodash"
;
import
_
from
"lodash"
;
import
{
useRoute
}
from
"vue-router"
;
import
{
useRoute
}
from
"vue-router"
;
const
route
=
useRoute
();
const
route
=
useRoute
();
...
@@ -85,13 +90,18 @@ const fetchEntitiesDomainCount = async () => {
...
@@ -85,13 +90,18 @@ const fetchEntitiesDomainCount = async () => {
onMounted
(
async
()
=>
{
onMounted
(
async
()
=>
{
try
{
try
{
const
[
entitiesAreaCountByYearData
,
countThisDomainData4
,
countThisDomainData10
]
=
await
Promise
.
all
([
const
[
entitiesAreaCountByYearData
,
countThisDomainData4
,
countThisDomainData10
]
=
await
Promise
.
all
([
get
EntitiesAreaCountByYear
(
route
.
query
.
startTime
),
get
DomainDistribution
(
route
.
query
.
startTime
),
getCountThisDomain
(
"4"
),
getCountThisDomain
(
"4"
),
// getEntitiesDomainCount(),
// getEntitiesDomainCount(),
getCountThisDomain
(
"10"
)
getCountThisDomain
(
"10"
)
]);
]);
pie1Option
.
value
=
getPieOption1
(
entitiesAreaCountByYearData
??
[]);
pie1Option
.
value
=
getPieOption1
(
entitiesAreaCountByYearData
.
map
(
item
=>
({
name
:
item
.
name
,
value
:
item
.
count
}))
??
[]
);
const
list4
=
_
.
reverse
(
countThisDomainData4
??
[]);
const
list4
=
_
.
reverse
(
countThisDomainData4
??
[]);
line1Option
.
value
=
getLineChart
({
line1Option
.
value
=
getLineChart
({
xAxisData
:
_
.
map
(
list4
,
"year"
),
xAxisData
:
_
.
map
(
list4
,
"year"
),
...
...
src/views/exportControl/analysis/components/pieCharts.vue
浏览文件 @
2e27cc08
...
@@ -42,7 +42,7 @@ onMounted(async () => {
...
@@ -42,7 +42,7 @@ onMounted(async () => {
.
filter
(
item
=>
item
.
count
>
0
)
.
filter
(
item
=>
item
.
count
>
0
)
.
map
(
item
=>
{
.
map
(
item
=>
{
return
{
return
{
name
:
item
?.
typ
e
,
name
:
item
?.
nam
e
,
value
:
item
?.
count
value
:
item
?.
count
};
};
})
})
...
...
src/views/exportControl/analysis/content/overview.vue
浏览文件 @
2e27cc08
...
@@ -57,7 +57,7 @@
...
@@ -57,7 +57,7 @@
<div
class=
"panel3"
>
<div
class=
"panel3"
>
<div
class=
"chartWrap"
>
<div
class=
"chartWrap"
>
<PieCharts
v-if=
"panel3ActiveIndex === 1"
></PieCharts>
<PieCharts
v-if=
"panel3ActiveIndex === 1"
></PieCharts>
<MapCharts
v-if=
"panel3ActiveIndex === 2"
></MapCharts>
<MapCharts
v-if=
"panel3ActiveIndex === 2"
:date=
"route.query.startTime"
></MapCharts>
</div>
</div>
<Hint
text=
"本次制裁共新增83个实体,其中53个中国大陆实体、1个中国台湾实体。"
></Hint>
<Hint
text=
"本次制裁共新增83个实体,其中53个中国大陆实体、1个中国台湾实体。"
></Hint>
</div>
</div>
...
@@ -94,7 +94,7 @@
...
@@ -94,7 +94,7 @@
家
家
</div>
</div>
</div>
</div>
<div
class=
"tableWrap"
>
<div
class=
"tableWrap"
ref=
"tableWrapRef"
@
scroll=
"handleScroll"
>
<el-table
<el-table
:data=
"selectEntitiesList"
:data=
"selectEntitiesList"
class=
"sanction-table"
class=
"sanction-table"
...
@@ -115,7 +115,7 @@
...
@@ -115,7 +115,7 @@
</
template
>
</
template
>
</el-table-column>
</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 }"
>
<
template
#
default=
"{ row }"
>
<div
class=
"domain-tags"
>
<div
class=
"domain-tags"
>
<el-tag
v-for=
"tag in row.domains"
:key=
"tag"
:type=
"panel5TypeMap[tag]"
>
{{
<el-tag
v-for=
"tag in row.domains"
:key=
"tag"
:type=
"panel5TypeMap[tag]"
>
{{
...
@@ -125,11 +125,11 @@
...
@@ -125,11 +125,11 @@
</
template
>
</
template
>
</el-table-column>
</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 }">
<template #default="{ row }">
{{ row.address }}
{{ row.address }}
</template>
</template>
</el-table-column>
</el-table-column>
-->
<el-table-column
prop=
"time"
label=
"制裁时间"
width=
"120"
align=
"center"
>
<el-table-column
prop=
"time"
label=
"制裁时间"
width=
"120"
align=
"center"
>
<
template
#
default=
"{ row }"
>
<
template
#
default=
"{ row }"
>
...
@@ -137,11 +137,11 @@
...
@@ -137,11 +137,11 @@
</
template
>
</
template
>
</el-table-column>
</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 }">
<template #default="{ row }">
{{ row.revenue }}
{{ row.revenue }}
</template>
</template>
</el-table-column>
</el-table-column>
-->
<el-table-column
prop=
"subCompany"
label=
"50%规则子企业"
min-width=
"140"
align=
"left"
>
<el-table-column
prop=
"subCompany"
label=
"50%规则子企业"
min-width=
"140"
align=
"left"
>
<
template
#
default=
"{ row }"
>
<
template
#
default=
"{ row }"
>
...
@@ -183,7 +183,7 @@ import PieCharts from "../components/pieCharts.vue";
...
@@ -183,7 +183,7 @@ import PieCharts from "../components/pieCharts.vue";
import
MapCharts
from
"../components/mapCharts.vue"
;
import
MapCharts
from
"../components/mapCharts.vue"
;
import
ButtonList
from
"@/components/buttonList/buttonList.vue"
;
import
ButtonList
from
"@/components/buttonList/buttonList.vue"
;
import
Hint
from
"../components/hint.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
panel1_1
from
"../../assets/images/panel1_1.png"
;
import
panel2_1
from
"../../assets/images/panel2_1.png"
;
import
panel2_1
from
"../../assets/images/panel2_1.png"
;
import
panel2_2
from
"../../assets/images/panel2_2.png"
;
import
panel2_2
from
"../../assets/images/panel2_2.png"
;
...
@@ -197,7 +197,14 @@ import panel5_5 from "../../assets/images/panel5_5.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_6
from
"../../assets/images/panel5_6.png"
;
import
panel5_7
from
"../../assets/images/panel5_7.png"
;
import
panel5_7
from
"../../assets/images/panel5_7.png"
;
import
panel5_8
from
"../../assets/images/panel5_8.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
_
from
"lodash"
;
import
{
useRoute
}
from
"vue-router"
;
import
{
useRoute
}
from
"vue-router"
;
import
{
formatAnyDateToChinese
}
from
"../../utils"
;
import
{
formatAnyDateToChinese
}
from
"../../utils"
;
...
@@ -246,15 +253,26 @@ const sanReasonSelect = shallowRef([
...
@@ -246,15 +253,26 @@ const sanReasonSelect = shallowRef([
text
:
"将中国定位为“通过强制技术转让获取先进制程的威胁”"
text
:
"将中国定位为“通过强制技术转让获取先进制程的威胁”"
}
}
]);
]);
const
panel5IsChecked
=
ref
(
true
);
const
selectEntitiesList
=
shallowRef
([]);
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
()
=>
{
onMounted
(
async
()
=>
{
try
{
try
{
const
[
organizationInfoData
,
personListData
,
sanReasonSelectData
,
selectEntitiesLis
tData
]
=
await
Promise
.
all
([
const
[
organizationInfoData
,
sanReasonSelec
tData
]
=
await
Promise
.
all
([
getOrganizationInfo
(),
getOrganizationInfo
(),
getPersonList
(),
//
getPersonList(),
getSanReasonSelect
(
route
.
query
.
startTime
)
,
getSanReasonSelect
(
route
.
query
.
startTime
)
getSelectEntitiesList
(
route
.
query
.
startTime
)
//
getSelectEntitiesList(route.query.startTime)
]);
]);
console
.
log
(
"organizationInfoData"
,
organizationInfoData
);
organizationInfo
.
value
=
{
organizationInfo
.
value
=
{
img
:
panel1_1
,
img
:
panel1_1
,
mingcheng
:
organizationInfoData
?.
orgNameZh
,
mingcheng
:
organizationInfoData
?.
orgNameZh
,
...
@@ -274,22 +292,103 @@ onMounted(async () => {
...
@@ -274,22 +292,103 @@ onMounted(async () => {
return
{
text
:
item
};
return
{
text
:
item
};
});
});
selectEntitiesList
.
value
=
_
.
map
(
selectEntitiesListData
,
item
=>
{
// selectEntitiesList.value = _.map(selectEntitiesListData, item => {
return
{
// return {
name
:
item
?.
entityNameZh
,
// name: item?.entityNameZh,
domains
:
item
.
techDomainList
,
// 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
:
"--"
,
address
:
"--"
,
time
:
formatAnyDateToChinese
(
item
?.
startTime
),
isUp
:
true
,
revenue
:
"--"
,
subCompany
:
"--"
,
subCompany
:
"--"
,
img
:
""
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
)
{
}
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
panel3ActiveIndex
=
ref
(
1
);
const
setPanel3ActiveIndex
=
index
=>
{
const
setPanel3ActiveIndex
=
index
=>
{
...
@@ -304,7 +403,7 @@ const panel5ButtonAcitveID = ref(panel5ButtonList[0].id);
...
@@ -304,7 +403,7 @@ const panel5ButtonAcitveID = ref(panel5ButtonList[0].id);
const
panel5SetButtonAcitveID
=
id
=>
{
const
panel5SetButtonAcitveID
=
id
=>
{
panel5ButtonAcitveID
.
value
=
id
;
panel5ButtonAcitveID
.
value
=
id
;
};
};
const
panel5IsChecked
=
ref
(
true
);
const
panel5TypeMap
=
{
const
panel5TypeMap
=
{
人工智能
:
"danger"
,
人工智能
:
"danger"
,
通信网络
:
"warning"
,
通信网络
:
"warning"
,
...
@@ -662,6 +761,10 @@ const panel6 = ref([
...
@@ -662,6 +761,10 @@ const panel6 = ref([
margin-top
:
14px
;
margin-top
:
14px
;
min-height
:
0
;
min-height
:
0
;
overflow
:
auto
;
overflow
:
auto
;
.domain-tags
{
display
:
flex
;
gap
:
4px
;
}
}
}
.name
{
.name
{
display
:
flex
;
display
:
flex
;
...
...
src/views/exportControl/analysis/index.vue
浏览文件 @
2e27cc08
...
@@ -35,14 +35,19 @@
...
@@ -35,14 +35,19 @@
</div>
</div>
<div
class=
"layout-main-header-right-box"
>
<div
class=
"layout-main-header-right-box"
>
<div
class=
"right-box-top"
>
<div
class=
"right-box-top"
>
<div
class=
"time"
>
{{
"2025年7月"
}}
</div>
<div
class=
"time"
>
{{
route
.
query
.
startTime
}}
</div>
<div
class=
"name"
>
{{
"美国商务部工业与安全局"
}}
</div>
<div
class=
"name"
>
{{
"美国商务部工业与安全局"
}}
</div>
</div>
</div>
<div
class=
"right-box-bottom"
>
<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
>
>
<el-button
type=
"primary"
size=
"large"
icon=
"EditPen"
>
分析报告
</el-button>
<el-button
type=
"primary"
size=
"large"
disabled
icon=
"EditPen"
>
分析报告
</el-button>
</div>
</div>
</div>
</div>
</div>
</div>
...
...
src/views/exportControl/components/info.vue
浏览文件 @
2e27cc08
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
<div
class=
"sub-title"
>
{{
subtitle
}}
</div>
<div
class=
"sub-title"
>
{{
subtitle
}}
</div>
</div>
</div>
<div
class=
"description"
>
{{
description
}}
</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>
</div>
</div>
</
template
>
</
template
>
...
@@ -30,6 +30,10 @@ defineProps({
...
@@ -30,6 +30,10 @@ defineProps({
type
:
[
Number
,
String
],
type
:
[
Number
,
String
],
default
:
0
default
:
0
},
},
unit
:
{
type
:
String
,
default
:
""
},
color
:
{
color
:
{
type
:
String
,
type
:
String
,
default
:
"#409EFF"
default
:
"#409EFF"
...
...
src/views/exportControl/index.vue
浏览文件 @
2e27cc08
...
@@ -67,13 +67,14 @@
...
@@ -67,13 +67,14 @@
</div>
</div>
<div
class=
"home-main-header-footer-info"
>
<div
class=
"home-main-header-footer-info"
>
<InfoCard
<InfoCard
v-for=
"item in infoList"
v-for=
"(item, index) in infoList"
:key=
"item.title"
:key=
"item.id"
:title=
"item.title"
:title=
"item.nameZh"
:subtitle=
"item.subTitle"
:subtitle=
"item.nameAbbr"
:description=
"item.des"
:description=
"item.description"
:quantity=
"item.num"
:quantity=
"item.postCount"
:color=
"item.color"
unit=
"次"
:color=
"infoListColor[index]"
/>
/>
</div>
</div>
</div>
</div>
...
@@ -90,95 +91,80 @@
...
@@ -90,95 +91,80 @@
<
template
#
default
>
<
template
#
default
>
<div
class=
"box1"
>
<div
class=
"box1"
>
<!--
<el-image
<el-carousel
trigger=
"click"
height=
"350px"
:autoplay=
"true"
>
:src=
"box1Image"
<el-carousel-item
v-for=
"(item, index) in entitiesDataInfoList"
:key=
"item.id + index"
>
alt=
""
<div>
style=
"width: 458px; height: 353px; object-fit: cover; flex-shrink: 0"
<div
class=
"box1-top"
>
></el-image>
-->
<div
class=
"box1-top-title"
>
<!--
<div
class=
"box1-right"
>
{{
item
.
postDate
}}
——BIS《实体清单增列与修订条目》
<div
class=
"box1-right-title"
>
关于进一步延长TikTok执法宽限期的行政令
</div>
</div>
<div
class=
"box1-right-tags"
>
<div
class=
"box1-top-content"
>
<el-tag
type=
"primary"
>
互联网
</el-tag>
<div
class=
"box1-top-content-item"
>
<el-tag
type=
"danger"
>
人工智能
</el-tag>
<span
class=
"box1-top-content-item-title"
>
· 发布机构:
</span>
</div>
<span
class=
"box1-top-content-item-content"
>
{{
item
.
postOrgName
}}
</span>
<div
class=
"box1-right-content"
>
</div>
9月16日,美国白宫官方网站发布总统政令,再次推迟(第四次)对TikTok禁令的执法,新的宽限期截止日为2025年12月16日。在宽限期内及对于宽限期前的行为,司法部不得强制执行《保护美国人免受外国对手控制应用程序法》或因此处罚相关实体(如TikTok及其分发平台)。司法部还需向提供商发出无违规和无责任的信函,并强调执行该法的权力专属联邦司法部长,意在阻止各州或私人提起诉讼。
<div
class=
"box1-top-content-item"
>
</div>
<span
class=
"box1-top-content-item-title"
>
· 生效日期:
</span>
<div
class=
"box1-right-footer"
>
<span
class=
"box1-top-content-item-content"
>
{{
item
.
postDate
}}
</span>
<span
class=
"box1-right-footer-time"
>
2025年9月16日
</span>
</div>
<el-button
type=
"primary"
link
>
<div
class=
"box1-top-content-item"
>
美国白宫官方网站
<span
class=
"box1-top-content-item-title"
>
· 涉及领域:
</span>
<el-image
<div
src=
"./assets/images/icon-open.png"
class=
"box1-top-content-item-tags"
alt=
""
v-for=
"domainItem in item.domains"
style=
"width: 16px; height: 16px; margin-left: 4px"
:key=
"domainItem"
></el-image>
>
</el-button>
<el-tag
</div>
:type=
"
</div>
-->
domainItem === '航空航天'
? 'primary'
<div
class=
"box1-top"
>
: item === '人工智能'
<div
class=
"box1-top-title"
>
? 'danger'
{{
entitiesDataInfoReactive
.
startTime
}}
——BIS《实体清单增列与修订条目》
: 'info'
</div>
"
<div
class=
"box1-top-content"
>
>
{{
domainItem
}}
</el-tag
<div
class=
"box1-top-content-item"
>
>
<span
class=
"box1-top-content-item-title"
>
· 发布机构:
</span>
</div>
<span
class=
"box1-top-content-item-content"
>
{{
</div>
entitiesDataInfoReactive
.
orgName
</div>
}}
</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
>
</div>
</div>
</div>
<div
class=
"box1-bottom"
>
</div>
<div
class=
"box1-bottom-title"
>
· 涉及主要实体:
</div>
</div>
<div
class=
"box1-bottom-content"
>
<div
class=
"box1-bottom"
>
<div
<div
class=
"box1-bottom-title"
>
· 涉及主要实体:
</div>
class=
"box1-bottom-content-item"
<div
class=
"box1-bottom-content"
>
v-for=
"(ett, index) in item.sanEntities"
<div
:key=
"index"
class=
"box1-bottom-content-item"
>
v-for=
"(item, index) in entitiesDataInfoReactive.entityList"
<el-image
:key=
"index"
v-if=
"ett.img"
>
class=
"box1-bottom-content-item-img"
<el-image
:src=
"ett.img"
v-if=
"item.img"
alt=
""
class=
"box1-bottom-content-item-img"
></el-image>
:src=
"item.img"
<div
v-else
class=
"box1-bottom-content-item-imgUndefined"
>
alt=
""
{{
></el-image>
(
ett
.
entityNameZh
||
ett
.
enName
)?.
match
(
<div
v-else
class=
"box1-bottom-content-item-imgUndefined"
>
/
[\u
4e00-
\u
9fa5a-zA-Z0-9
]
/
{{
(
item
.
name
||
item
.
enName
)?.
match
(
/
[\u
4e00-
\u
9fa5a-zA-Z0-9
]
/
)?.[
0
]
}}
)?.[
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>
<div
class=
"box1-bottom-content-item-txt"
>
{{
item
.
name
||
item
.
enName
}}
</div>
</div>
</div>
</div>
</el-carousel-item>
</div>
</el-carousel>
<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>
</div>
</div>
</
template
>
</
template
>
</custom-container>
</custom-container>
...
@@ -300,9 +286,11 @@
...
@@ -300,9 +286,11 @@
</div>
</div>
</
template
>
</
template
>
</el-table-column>
</el-table-column>
<el-table-column
label=
"重点领域"
width=
"180"
>
<el-table-column
label=
"重点领域"
width=
"180"
align=
"center"
>
<
template
#
default=
"scope"
>
<
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
<el-tag
v-for=
"tag in scope.row.tags"
v-for=
"tag in scope.row.tags"
:key=
"tag"
:key=
"tag"
...
@@ -334,9 +322,11 @@
...
@@ -334,9 +322,11 @@
</div>
</div>
</
template
>
</
template
>
</el-table-column>
</el-table-column>
<el-table-column
label=
"重点领域"
width=
"180"
>
<el-table-column
label=
"重点领域"
width=
"180"
align=
"center"
>
<
template
#
default=
"scope"
>
<
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
<el-tag
v-for=
"tag in scope.row.tags"
v-for=
"tag in scope.row.tags"
:key=
"tag"
:key=
"tag"
...
@@ -352,7 +342,7 @@
...
@@ -352,7 +342,7 @@
</el-table-column>
</el-table-column>
</el-table>
</el-table>
</div>
</div>
<div
class=
"box3-content"
>
<div
class=
"box3-content"
style=
"display: none"
>
<div
class=
"box3-content-title"
>
关键与新兴技术清单(CETs)
</div>
<div
class=
"box3-content-title"
>
关键与新兴技术清单(CETs)
</div>
<el-table
:data=
"tableData1"
stripe
style=
"width: 100%"
>
<el-table
:data=
"tableData1"
stripe
style=
"width: 100%"
>
<el-table-column
prop=
"year"
label=
"年份"
width=
"100"
/>
<el-table-column
prop=
"year"
label=
"年份"
width=
"100"
/>
...
@@ -394,19 +384,19 @@
...
@@ -394,19 +384,19 @@
<el-row
:gutter=
"20"
style=
"width: 1600px; margin: 0 auto"
>
<el-row
:gutter=
"20"
style=
"width: 1600px; margin: 0 auto"
>
<el-col
:span=
"8"
>
<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
>
<
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
>
<
template
#
default
>
<
template
#
default
>
<EChart
:option=
"radarOption"
autoresize
:style=
"
{ height: '
38
0px' }" />
<EChart
:option=
"radarOption"
autoresize
:style=
"
{ height: '
45
0px' }" />
</
template
>
</
template
>
</custom-container>
</custom-container>
</el-col>
</el-col>
<el-col
:span=
"16"
>
<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
>
<
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
>
<
template
#
default
>
<
template
#
default
>
<EChart
:option=
"trendOption"
autoresize
:style=
"
{ height: '400px' }" />
<EChart
:option=
"trendOption"
autoresize
:style=
"
{ height: '400px' }" />
...
@@ -421,23 +411,25 @@
...
@@ -421,23 +411,25 @@
<custom-container
title=
"历次制裁过程"
:titleIcon=
"listIcon"
height=
"845px"
>
<custom-container
title=
"历次制裁过程"
:titleIcon=
"listIcon"
height=
"845px"
>
<
template
#
default
>
<
template
#
default
>
<div
class=
"box4"
>
<div
class=
"box4"
>
<div
class=
"box4-item"
v-for=
"(item, idx) in sanctionProcessList"
:key=
"item.title"
>
<div
style=
"height: 90%; overflow-y: auto; padding-top: 10px"
>
<div
class=
"box4-item-left"
>
<div
class=
"box4-item"
v-for=
"(item, idx) in sanctionProcessList"
:key=
"item.title"
>
<el-image
:src=
"dotIcon"
alt=
"图片"
class=
"box4-item-left-icon"
/>
<div
class=
"box4-item-left"
>
<div
class=
"box4-item-left-line"
v-if=
"idx + 1 != sanctionProcessList.length"
></div>
<el-image
:src=
"dotIcon"
alt=
"图片"
class=
"box4-item-left-icon"
/>
</div>
<div
class=
"box4-item-left-line"
v-if=
"idx + 1 != sanctionProcessList.length"
></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>
</div>
<div
class=
"box4-item-right-content"
>
<div
class=
"box4-item-right"
>
{{
item
.
content
}}
<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>
</div>
</div>
<div
class=
"box4-footer"
:style=
"
{ marginTop: sanctionProcessList.length > 0 ? '0px' : 'auto' }">
<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-icon><DArrowRight
/></el-icon>
</el-button>
</el-button>
...
@@ -470,7 +462,7 @@
...
@@ -470,7 +462,7 @@
<el-table-column
prop=
"name"
label=
"实体名称"
min-width=
"200"
>
<el-table-column
prop=
"name"
label=
"实体名称"
min-width=
"200"
>
<
template
#
default=
"scope"
>
<
template
#
default=
"scope"
>
<div
class=
"tableName"
>
<div
class=
"tableName"
@
click=
"handleCompClick(scope.row)"
>
<el-image
<el-image
v-if=
"scope.row.img"
v-if=
"scope.row.img"
class=
"box1-bottom-content-item-img"
class=
"box1-bottom-content-item-img"
...
@@ -571,7 +563,7 @@
...
@@ -571,7 +563,7 @@
</template>
</template>
<
script
setup
>
<
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
scrollToTop
from
"@/utils/scrollToTop"
;
import
*
as
echarts
from
"echarts"
;
import
*
as
echarts
from
"echarts"
;
import
setChart
from
"@/utils/setChart"
;
import
setChart
from
"@/utils/setChart"
;
...
@@ -645,50 +637,45 @@ import { getMultipleBarChart_m } from "./utils/charts";
...
@@ -645,50 +637,45 @@ import { getMultipleBarChart_m } from "./utils/charts";
import
{
formatAnyDateToChinese
}
from
"./utils"
;
import
{
formatAnyDateToChinese
}
from
"./utils"
;
import
_
from
"lodash"
;
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
tagsType
=
[
"primary"
,
"success"
,
"info"
,
"warning"
,
"danger"
];
//数据定义
//数据定义
const
entitiesDataInfoReactive
=
shallowRef
({
const
entitiesDataInfoList
=
shallowRef
([]);
chNum
:
undefined
,
entityList
:
[],
domains
:
[],
startTime
:
""
,
rawStartTime
:
""
,
orgName
:
""
});
// 趋势图
// 趋势图
const
trendOption
=
ref
({});
const
trendOption
=
ref
({});
const
trendChecked
=
ref
(
false
);
// 发布频度
// 发布频度
const
tableData1
=
ref
([]);
const
tableData1
=
ref
([]);
// 历次制裁过程
// 历次制裁过程
const
sanctionProcessList
=
ref
([]);
const
sanctionProcessList
=
ref
([]);
const
sanctionPage
=
ref
(
1
);
// 制裁实体清单
// 制裁实体清单
const
entitiesList
=
ref
([]);
const
entitiesList
=
ref
([]);
onMounted
(
async
()
=>
{
onMounted
(
async
()
=>
{
try
{
try
{
const
[
dataCount
,
entitiesDataInfo
,
industryCountByYear
,
countDomainByYear
,
sanctionsInfoCount
,
entityBody
]
=
const
[
dataCount
,
entitiesDataInfo
,
industryCountByYear
,
countDomainByYear
]
=
await
Promise
.
all
([
await
Promise
.
all
([
getEntitiesDataCount
(),
getEntitiesDataCount
(),
getEntitiesDataInfo
(),
getEntitiesDataInfo
(),
getIndustryCountByYear
(
1
),
getIndustryCountByYear
(),
getCountDomainByYear
(
trendChecked
.
value
)
getCountDomainByYear
()
]);
// getSanctionsInfoCount()
infoList
.
value
=
dataCount
;
// getEntitiesList("实体清单")
]);
infoList
.
value
[
0
].
num
=
dataCount
;
const
entityList
=
_
.
map
(
entitiesDataInfo
?.
sanEntities
??
[],
({
entityNameZh
,
entityName
})
=>
{
const
entityList
=
_
.
map
(
entitiesDataInfo
?.
sanEntities
??
[],
({
entityNameZh
,
entityName
})
=>
{
return
{
name
:
entityNameZh
,
enName
:
entityName
};
return
{
name
:
entityNameZh
,
enName
:
entityName
};
});
});
entitiesDataInfoReactive
.
value
=
{
entitiesDataInfoList
.
value
=
entitiesDataInfo
||
[];
entityList
,
chNum
:
entitiesDataInfo
?.
cnEntityCount
,
domains
:
entitiesDataInfo
?.
domains
??
[],
// startTime: formatAnyDateToChinese(entitiesDataInfo?.startTime ?? ""),
startTime
:
entitiesDataInfo
.
postDate
,
rawStartTime
:
entitiesDataInfo
?.
startTime
??
""
,
orgName
:
entitiesDataInfo
?.
postOrgName
};
const
list
=
_
.
chain
(
industryCountByYear
).
filter
(
"year"
).
orderBy
(
"year"
,
"desc"
).
value
();
const
list
=
_
.
chain
(
industryCountByYear
).
filter
(
"year"
).
orderBy
(
"year"
,
"desc"
).
value
();
const
total
=
_
.
sumBy
(
list
,
"count"
);
const
total
=
_
.
sumBy
(
list
,
"count"
);
tableData1
.
value
=
_
.
map
(
list
,
item
=>
{
tableData1
.
value
=
_
.
map
(
list
,
item
=>
{
...
@@ -699,8 +686,12 @@ onMounted(async () => {
...
@@ -699,8 +686,12 @@ onMounted(async () => {
tags
:
item
.
domain
tags
:
item
.
domain
};
};
}).
slice
(
0
,
5
);
}).
slice
(
0
,
5
);
console
.
log
(
"tableData1"
,
tableData1
.
value
);
console
.
log
(
"countDomainByYear"
,
countDomainByYear
);
trendOption
.
value
=
getMultipleBarChart_m
(
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 => {
// sanctionProcessList.value = _.map(_.slice(sanctionsInfoCount, 0, 5), item => {
// return {
// return {
// title: item.tittle,
// title: item.tittle,
...
@@ -711,9 +702,9 @@ onMounted(async () => {
...
@@ -711,9 +702,9 @@ onMounted(async () => {
// };
// };
// });
// });
await
fetchEntitiesList
(
currentPage
.
value
,
pageSize
.
value
);
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);
// console.log("entitiesList entitiesList", entityBody);
// entitiesList.value = _.map(entityBody.content, item => {
// entitiesList.value = _.map(entityBody.content, item => {
// return {
// return {
...
@@ -729,6 +720,59 @@ onMounted(async () => {
...
@@ -729,6 +720,59 @@ onMounted(async () => {
console
.
log
(
err
);
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
=
()
=>
{
const
handleBackHome
=
()
=>
{
router
.
push
({
router
.
push
({
...
@@ -747,7 +791,7 @@ const handleToDetail = () => {
...
@@ -747,7 +791,7 @@ const handleToDetail = () => {
const
route
=
router
.
resolve
({
const
route
=
router
.
resolve
({
path
:
"/exportControlAnalysis"
,
path
:
"/exportControlAnalysis"
,
query
:
{
query
:
{
startTime
:
entitiesDataInfo
Reactive
.
value
.
startTime
startTime
:
entitiesDataInfo
List
.
value
.
startTime
}
}
});
});
window
.
open
(
route
.
href
,
"_blank"
);
window
.
open
(
route
.
href
,
"_blank"
);
...
@@ -757,39 +801,8 @@ const billList = ref([]);
...
@@ -757,39 +801,8 @@ const billList = ref([]);
const
curBillListIndex
=
ref
(
0
);
const
curBillListIndex
=
ref
(
0
);
const
searchKey
=
ref
(
""
);
const
searchKey
=
ref
(
""
);
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
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
entityList
=
ref
([
const
entityList
=
ref
([
{
{
...
@@ -865,15 +878,20 @@ const customNewsData = ref([
...
@@ -865,15 +878,20 @@ const customNewsData = ref([
]);
]);
// 雷达图
// 雷达图
const
domainChecked
=
ref
(
false
);
const
radarOption
=
ref
({
const
radarOption
=
ref
({
title
:
{
title
:
{
text
:
""
text
:
""
},
},
legend
:
{
legend
:
{
top
:
0
,
top
:
"0%"
,
icon
:
"circle"
,
icon
:
"circle"
,
data
:
[
"实体清单"
,
"商业管制清单"
,
"关键和新型技术清单"
]
data
:
[
"实体清单"
,
"商业管制清单"
,
"关键和新型技术清单"
]
},
},
grid
:
{
top
:
"15%"
,
containLabel
:
true
},
radar
:
{
radar
:
{
// shape: 'circle',
// shape: 'circle',
indicator
:
[
indicator
:
[
...
@@ -923,9 +941,9 @@ const radarOption = ref({
...
@@ -923,9 +941,9 @@ const radarOption = ref({
});
});
// 获取雷达图数据
// 获取雷达图数据
const
fetchRadarData
=
async
()
=>
{
const
fetchRadarData
=
async
checked
=>
{
try
{
try
{
const
data
=
await
getSanDomainCount
();
const
data
=
await
getSanDomainCount
(
checked
);
if
(
data
&&
Array
.
isArray
(
data
)
&&
data
.
length
>
0
)
{
if
(
data
&&
Array
.
isArray
(
data
)
&&
data
.
length
>
0
)
{
// 收集所有可能的领域名称
// 收集所有可能的领域名称
const
allDomains
=
new
Set
();
const
allDomains
=
new
Set
();
...
@@ -984,6 +1002,11 @@ const fetchRadarData = async () => {
...
@@ -984,6 +1002,11 @@ const fetchRadarData = async () => {
}
}
};
};
watch
(
()
=>
domainChecked
.
value
,
()
=>
fetchRadarData
(
domainChecked
.
value
)
);
// 进度条状态
// 进度条状态
const
getStatus
=
_percent
=>
{
const
getStatus
=
_percent
=>
{
const
percent
=
_percent
*
100
;
const
percent
=
_percent
*
100
;
...
@@ -1020,12 +1043,37 @@ const fetchEntitiesList = async (page = 1, size = 10) => {
...
@@ -1020,12 +1043,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
)
=>
{
const
fetchSanctionProcess
=
async
(
page
=
1
,
size
=
10
)
=>
{
try
{
try
{
const
res
=
await
getSanctionProcess
(
"实体清单"
,
page
,
size
);
const
res
=
await
getSanctionProcess
(
"实体清单"
,
page
,
size
);
if
(
res
)
{
if
(
res
)
{
sanctionProcessList
.
value
=
res
.
content
.
slice
(
0
,
5
).
map
(
item
=>
({
sanctionProcessList
.
value
=
res
.
content
.
map
(
item
=>
({
...
item
,
...
item
,
title
:
item
.
name
,
title
:
item
.
name
,
desc
:
`
${
item
.
cnEntityCount
}
家中国实体`
,
desc
:
`
${
item
.
cnEntityCount
}
家中国实体`
,
...
@@ -1416,6 +1464,17 @@ const chart1Data = ref({
...
@@ -1416,6 +1464,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
()
=>
{
const
handleGetHotBills
=
async
()
=>
{
try
{
try
{
...
@@ -1742,8 +1801,9 @@ onMounted(async () => {
...
@@ -1742,8 +1801,9 @@ onMounted(async () => {
.box3
{
.box3
{
display
:
flex
;
display
:
flex
;
justify-content
:
space-between
;
//
justify-content: space-between;
align-items
:
flex-start
;
align-items
:
flex-start
;
gap
:
60px
;
.box3-content-title
{
.box3-content-title
{
font-size
:
18px
;
font-size
:
18px
;
font-weight
:
700
;
font-weight
:
700
;
...
@@ -1769,7 +1829,10 @@ onMounted(async () => {
...
@@ -1769,7 +1829,10 @@ onMounted(async () => {
overflow
:
auto
;
overflow
:
auto
;
display
:
flex
;
display
:
flex
;
flex-direction
:
column
;
flex-direction
:
column
;
justify-content
:
space-between
;
padding-top
:
16px
;
padding-top
:
16px
;
// padding-bottom: 50px;
position
:
relative
;
.box4-item
{
.box4-item
{
display
:
flex
;
display
:
flex
;
gap
:
10px
;
gap
:
10px
;
...
@@ -1802,6 +1865,7 @@ onMounted(async () => {
...
@@ -1802,6 +1865,7 @@ onMounted(async () => {
position
:
relative
;
position
:
relative
;
top
:
-7
.5px
;
top
:
-7
.5px
;
padding-bottom
:
8px
;
padding-bottom
:
8px
;
cursor
:
pointer
;
&
-title
{
&
-title
{
font-size
:
18px
;
font-size
:
18px
;
color
:
$base-color
;
color
:
$base-color
;
...
@@ -1827,14 +1891,15 @@ onMounted(async () => {
...
@@ -1827,14 +1891,15 @@ onMounted(async () => {
}
}
}
}
.box4-footer
{
.box4-footer
{
margin-top
:
auto
;
position
:
absolute
;
// margin-top: auto;
display
:
flex
;
display
:
flex
;
justify-content
:
center
;
justify-content
:
center
;
align-items
:
center
;
align-items
:
center
;
bottom
:
30px
;
bottom
:
30px
;
left
:
50%
;
left
:
50%
;
margin-left
:
-
2
0px
;
margin-left
:
-
3
0px
;
margin-bottom
:
30px
;
//
margin-bottom: 30px;
}
}
}
}
...
@@ -2550,6 +2615,7 @@ onMounted(async () => {
...
@@ -2550,6 +2615,7 @@ onMounted(async () => {
display
:
flex
;
display
:
flex
;
align-items
:
center
;
align-items
:
center
;
gap
:
10px
;
gap
:
10px
;
cursor
:
pointer
;
.box1-bottom-content-item-imgUndefined
{
.box1-bottom-content-item-imgUndefined
{
width
:
24px
;
width
:
24px
;
height
:
24px
;
height
:
24px
;
...
...
src/views/exportControl/utils/charts.js
浏览文件 @
2e27cc08
import
*
as
echarts
from
'echarts'
;
import
*
as
echarts
from
"echarts"
;
import
chinaJson
from
'./China.json'
import
chinaJson
from
"./China.json"
;
import
_
from
'lodash'
;
import
_
from
"lodash"
;
//饼图
//饼图
export
function
getPieOption
(
data
,
title
)
{
export
function
getPieOption
(
data
,
title
)
{
let
option
=
{
let
option
=
{
color
:
[
"#4096ff"
,
"#b37feb"
,
"#ff7875"
,
"#85a5ff"
,
"#69b1ff"
,
"#ffc069"
,
"#87e8de"
],
color
:
[
"#4096ff"
,
"#b37feb"
,
"#ff7875"
,
"#85a5ff"
,
"#69b1ff"
,
"#ffc069"
,
"#87e8de"
],
title
:
{
title
:
{
text
:
title
,
text
:
title
,
top
:
10
,
top
:
10
,
left
:
10
,
left
:
10
,
textStyle
:
{
textStyle
:
{
color
:
"rgba(59, 65, 75, 1)"
,
color
:
"rgba(59, 65, 75, 1)"
,
fontSize
:
16
,
fontSize
:
16
,
fontWeight
:
700
fontWeight
:
700
}
}
},
},
series
:
[
series
:
[
{
{
type
:
'pie'
,
type
:
"pie"
,
radius
:
[
75
,
132
],
radius
:
[
75
,
132
],
height
:
'100%'
,
height
:
"100%"
,
center
:
[
'50%'
,
'50%'
],
center
:
[
"50%"
,
"50%"
],
width
:
'100%'
,
width
:
"100%"
,
itemStyle
:
{
itemStyle
:
{
borderColor
:
'#fff'
,
borderColor
:
"#fff"
,
borderWidth
:
1
borderWidth
:
1
},
},
label
:
{
label
:
{
alignTo
:
'edge'
,
alignTo
:
"edge"
,
formatter
:
'{b} {d}%'
,
formatter
:
"{b} {d}%"
,
minMargin
:
5
,
minMargin
:
5
,
edgeDistance
:
10
,
edgeDistance
:
10
,
lineHeight
:
15
,
lineHeight
:
15
,
rich
:
{
rich
:
{
time
:
{
time
:
{
fontSize
:
10
,
fontSize
:
10
,
color
:
'#999'
color
:
"#999"
}
}
}
}
},
},
labelLine
:
{
labelLine
:
{
length
:
15
,
length
:
15
,
length2
:
0
,
length2
:
0
,
maxSurfaceAngle
:
80
maxSurfaceAngle
:
80
},
},
labelLayout
:
function
(
params
)
{
labelLayout
:
function
(
params
)
{
const
isLeft
=
params
.
labelRect
.
x
<
556
/
2
;
const
isLeft
=
params
.
labelRect
.
x
<
556
/
2
;
const
points
=
params
.
labelLinePoints
;
const
points
=
params
.
labelLinePoints
;
// Update the end point.
// Update the end point.
points
[
2
][
0
]
=
isLeft
points
[
2
][
0
]
=
isLeft
?
params
.
labelRect
.
x
:
params
.
labelRect
.
x
+
params
.
labelRect
.
width
;
?
params
.
labelRect
.
x
return
{
:
params
.
labelRect
.
x
+
params
.
labelRect
.
width
;
labelLinePoints
:
points
return
{
};
labelLinePoints
:
points
},
};
data
:
data
},
}
data
:
data
]
}]
};
}
return
option
;
return
option
}
}
export
function
getPieOption1
(
data
,
title
)
{
export
function
getPieOption1
(
data
,
title
)
{
let
option
=
{
let
option
=
{
color
:
[
"#4096ff"
,
"#b37feb"
,
"#ff7875"
,
"#85a5ff"
,
"#69b1ff"
,
"#ffc069"
,
"#87e8de"
],
color
:
[
"#4096ff"
,
"#b37feb"
,
"#ff7875"
,
"#85a5ff"
,
"#69b1ff"
,
"#ffc069"
,
"#87e8de"
],
title
:
{
title
:
{
text
:
title
,
text
:
title
,
top
:
10
,
top
:
10
,
left
:
10
,
left
:
10
,
textStyle
:
{
textStyle
:
{
color
:
"rgba(59, 65, 75, 1)"
,
color
:
"rgba(59, 65, 75, 1)"
,
fontSize
:
16
,
fontSize
:
16
,
fontWeight
:
700
fontWeight
:
700
}
}
},
},
series
:
[
series
:
[
{
{
type
:
'pie'
,
type
:
"pie"
,
radius
:
[
70
,
110
],
radius
:
[
70
,
110
],
height
:
'100%'
,
height
:
"100%"
,
center
:
[
'50%'
,
'50%'
],
center
:
[
"50%"
,
"50%"
],
width
:
'100%'
,
width
:
"100%"
,
itemStyle
:
{
itemStyle
:
{
borderColor
:
'#fff'
,
borderColor
:
"#fff"
,
borderWidth
:
1
borderWidth
:
1
},
},
label
:
{
label
:
{
alignTo
:
'edge'
,
alignTo
:
"edge"
,
formatter
:
`{b}
${
data
.
length
<
10
?
'
\
n'
:
''
}
{two|{c}家 {d}%}`
,
formatter
:
`{b}
${
data
.
length
<
10
?
"
\
n"
:
""
}
{two|{c}家 {d}%}`
,
fontSize
:
17.6
,
fontSize
:
17.6
,
fontWeight
:
700
,
fontWeight
:
700
,
minMargin
:
5
,
minMargin
:
5
,
edgeDistance
:
10
,
edgeDistance
:
10
,
lineHeight
:
23
,
lineHeight
:
23
,
rich
:
{
rich
:
{
two
:
{
two
:
{
fontSize
:
15
,
fontSize
:
15
,
color
:
' rgba(95, 101, 108, 1)'
,
color
:
" rgba(95, 101, 108, 1)"
}
}
}
}
},
},
labelLine
:
{
labelLine
:
{
length
:
15
,
length
:
15
,
length2
:
0
,
length2
:
0
,
maxSurfaceAngle
:
80
maxSurfaceAngle
:
80
},
},
labelLayout
:
function
(
params
)
{
labelLayout
:
function
(
params
)
{
console
.
log
(
'labelLayoutparams'
,
params
)
console
.
log
(
"labelLayoutparams"
,
params
);
const
isLeft
=
params
.
labelRect
.
x
<
556
/
2
;
const
isLeft
=
params
.
labelRect
.
x
<
556
/
2
;
const
points
=
params
.
labelLinePoints
;
const
points
=
params
.
labelLinePoints
;
// Update the end point.
// Update the end point.
points
[
2
][
0
]
=
isLeft
points
[
2
][
0
]
=
isLeft
?
data
.
length
<
10
?
params
.
labelRect
.
x
:
(
params
.
labelRect
.
x
+
params
.
labelRect
.
width
)
?
data
.
length
<
10
:
data
.
length
<
10
?
(
params
.
labelRect
.
x
+
params
.
labelRect
.
width
)
:
params
.
labelRect
.
x
;
?
params
.
labelRect
.
x
return
{
:
params
.
labelRect
.
x
+
params
.
labelRect
.
width
labelLinePoints
:
points
:
data
.
length
<
10
};
?
params
.
labelRect
.
x
+
params
.
labelRect
.
width
},
:
params
.
labelRect
.
x
;
data
:
data
return
{
}]
labelLinePoints
:
points
}
};
return
option
},
data
:
data
}
]
};
return
option
;
}
}
export
function
getPieOption2
(
data
,
title
)
{
export
function
getPieOption2
(
data
,
title
)
{
let
option
=
{
let
option
=
{
color
:
[
"#4096ff"
,
"#b37feb"
,
"#ff7875"
,
"#85a5ff"
,
"#69b1ff"
,
"#ffc069"
,
"#87e8de"
],
color
:
[
"#4096ff"
,
"#b37feb"
,
"#ff7875"
,
"#85a5ff"
,
"#69b1ff"
,
"#ffc069"
,
"#87e8de"
],
title
:
{
title
:
{
text
:
title
,
text
:
title
,
top
:
10
,
top
:
10
,
left
:
10
,
left
:
10
,
textStyle
:
{
textStyle
:
{
color
:
"rgba(59, 65, 75, 1)"
,
color
:
"rgba(59, 65, 75, 1)"
,
fontSize
:
16
,
fontSize
:
16
,
fontWeight
:
700
fontWeight
:
700
}
}
},
},
legend
:
{
legend
:
{
icon
:
'rect'
,
icon
:
"rect"
,
top
:
'center'
,
top
:
"center"
,
right
:
'40'
,
right
:
"40"
,
orient
:
'vertical'
,
orient
:
"vertical"
,
itemWidth
:
30
,
itemWidth
:
30
,
itemHeight
:
20
,
itemHeight
:
20
,
borderRadius
:
2
,
borderRadius
:
2
,
formatter
:
function
(
name
)
{
formatter
:
function
(
name
)
{
// 获取系列数据,假设第一个系列为饼图
// 获取系列数据,假设第一个系列为饼图
let
seriesData
=
option
.
series
[
0
].
data
;
// [citation:8]
let
seriesData
=
option
.
series
[
0
].
data
;
// [citation:8]
// 也可以考虑使用 this.getSeries()[0].data [citation:8]
// 也可以考虑使用 this.getSeries()[0].data [citation:8]
let
currentValue
;
let
currentValue
;
// 计算数据总和并查找当前图例名对应的数值
// 计算数据总和并查找当前图例名对应的数值
seriesData
.
forEach
(
item
=>
{
seriesData
.
forEach
(
item
=>
{
if
(
item
.
name
===
name
)
{
if
(
item
.
name
===
name
)
{
currentValue
=
item
.
value
;
currentValue
=
item
.
value
;
}
}
});
});
return
`
${
name
}
${
currentValue
}
%`
return
`
${
name
}
${
currentValue
}
%`
;
},
},
itemGap
:
10
,
itemGap
:
10
,
textStyle
:
{
textStyle
:
{
color
:
'rgba(59, 65, 75 ,0.8)'
,
color
:
"rgba(59, 65, 75 ,0.8)"
,
fontSize
:
18
,
fontSize
:
18
,
fontWeight
:
500
fontWeight
:
500
},
}
},
},
series
:
[
series
:
[
{
{
type
:
'pie'
,
type
:
"pie"
,
radius
:
[
70
,
120
],
radius
:
[
70
,
120
],
height
:
'100%'
,
height
:
"100%"
,
center
:
[
'33%'
,
'50%'
],
center
:
[
"33%"
,
"50%"
],
width
:
'100%'
,
width
:
"100%"
,
itemStyle
:
{
itemStyle
:
{
borderColor
:
'#fff'
,
borderColor
:
"#fff"
,
borderWidth
:
1
borderWidth
:
1
},
},
emphasis
:
{
emphasis
:
{
scale
:
false
,
scale
:
false
},
},
label
:
{
label
:
{
show
:
false
,
show
:
false
},
},
data
:
data
data
:
data
}]
}
}
]
return
option
};
return
option
;
}
}
export
function
getMapOption
()
{
export
function
getMapOption
()
{
echarts
.
registerMap
(
'china'
,
chinaJson
);
echarts
.
registerMap
(
"china"
,
chinaJson
);
let
data
=
[{
let
data
=
[
name
:
'2256'
,
{
value
:
2256
name
:
"2256"
,
},
{
value
:
2256
name
:
'578'
,
},
value
:
578
{
},
{
name
:
"578"
,
name
:
'744'
,
value
:
578
value
:
744
},
},
{
{
name
:
'806'
,
name
:
"744"
,
value
:
806
value
:
744
},
{
},
name
:
'336'
,
{
value
:
336
name
:
"806"
,
},
{
value
:
806
name
:
'325'
,
},
value
:
325
{
},
{
name
:
"336"
,
name
:
'487'
,
value
:
336
value
:
487
},
},
{
{
name
:
'343'
,
name
:
"325"
,
value
:
343
value
:
325
},
{
},
name
:
'432'
,
{
value
:
432
name
:
"487"
,
},
{
value
:
487
name
:
'273'
,
},
value
:
273
{
},
{
name
:
"343"
,
name
:
'1055'
,
value
:
343
value
:
1055
},
},
{
{
name
:
'590'
,
name
:
"432"
,
value
:
590
value
:
432
},
{
},
name
:
'319'
,
{
value
:
319
name
:
"273"
,
},
{
value
:
273
name
:
'349'
,
},
value
:
349
{
},
{
name
:
"1055"
,
name
:
'126'
,
value
:
1055
value
:
126
},
},
{
{
name
:
'97'
,
name
:
"590"
,
value
:
97
value
:
590
},
{
},
name
:
'201'
,
{
value
:
201
name
:
"319"
,
},
{
value
:
319
name
:
'398'
,
},
value
:
398
{
},
{
name
:
"349"
,
name
:
'795'
,
value
:
349
value
:
795
},
},
{
{
name
:
'655'
,
name
:
"126"
,
value
:
655
value
:
126
},
{
},
name
:
'295'
,
{
value
:
295
name
:
"97"
,
},
{
value
:
97
name
:
'311'
,
},
value
:
311
{
},
{
name
:
"201"
,
name
:
'993'
,
value
:
201
value
:
993
},
},
{
{
name
:
'601'
,
name
:
"398"
,
value
:
601
value
:
398
},
{
},
name
:
'275'
,
{
value
:
275
name
:
"795"
,
},
{
value
:
795
name
:
'317'
,
},
value
:
317
{
},
{
name
:
"655"
,
name
:
'1000'
,
value
:
655
value
:
1000
},
},
{
{
name
:
'186'
,
name
:
"295"
,
value
:
186
value
:
295
},
{
},
name
:
'261'
,
{
value
:
261
name
:
"311"
,
},
{
value
:
311
name
:
'132'
,
},
value
:
132
{
},
{
name
:
"993"
,
name
:
'18'
,
value
:
993
value
:
18
},
},
{
{
name
:
'11'
,
name
:
"601"
,
value
:
11
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
=
{
let
geoCoordMap
=
{
'2256'
:
[
116.46
,
39.92
],
2256
:
[
116.46
,
39.92
],
'578'
:
[
121.29
,
31.14
],
578
:
[
121.29
,
31.14
],
'744'
:
[
117.2
,
39.13
],
744
:
[
117.2
,
39.13
],
'806'
:
[
106.32
,
29.32
],
806
:
[
106.32
,
29.32
],
'336'
:
[
126.41
,
45.45
],
336
:
[
126.41
,
45.45
],
'325'
:
[
125.19
,
43.52
],
325
:
[
125.19
,
43.52
],
'487'
:
[
123.24
,
41.50
],
487
:
[
123.24
,
41.5
],
'343'
:
[
111.48
,
40.49
],
343
:
[
111.48
,
40.49
],
'432'
:
[
114.28
,
38.02
],
432
:
[
114.28
,
38.02
],
'273'
:
[
112.34
,
37.52
],
273
:
[
112.34
,
37.52
],
'1055'
:
[
117
,
36.38
],
1055
:
[
117
,
36.38
],
'590'
:
[
113.42
,
34.48
],
590
:
[
113.42
,
34.48
],
'319'
:
[
108.54
,
34.16
],
319
:
[
108.54
,
34.16
],
'349'
:
[
103.49
,
36.03
],
349
:
[
103.49
,
36.03
],
'126'
:
[
106.16
,
38.20
],
126
:
[
106.16
,
38.2
],
'97'
:
[
101.45
,
36.38
],
97
:
[
101.45
,
36.38
],
'201'
:
[
87.36
,
43.48
],
201
:
[
87.36
,
43.48
],
'398'
:
[
117.18
,
31.51
],
398
:
[
117.18
,
31.51
],
'795'
:
[
118.50
,
32.02
],
795
:
[
118.5
,
32.02
],
'655'
:
[
120.09
,
30.14
],
655
:
[
120.09
,
30.14
],
'295'
:
[
113
,
28.11
],
295
:
[
113
,
28.11
],
'311'
:
[
115.52
,
28.41
],
311
:
[
115.52
,
28.41
],
'993'
:
[
114.21
,
30.37
],
993
:
[
114.21
,
30.37
],
'601'
:
[
104.05
,
30.39
],
601
:
[
104.05
,
30.39
],
'275'
:
[
106.42
,
26.35
],
275
:
[
106.42
,
26.35
],
'317'
:
[
119.18
,
26.05
],
317
:
[
119.18
,
26.05
],
'1000'
:
[
113.15
,
23.08
],
1000
:
[
113.15
,
23.08
],
'186'
:
[
110.20
,
20.02
],
186
:
[
110.2
,
20.02
],
'261'
:
[
108.20
,
22.48
],
261
:
[
108.2
,
22.48
],
'132'
:
[
102.41
,
25
],
132
:
[
102.41
,
25
],
'18'
:
[
91.10
,
29.40
],
18
:
[
91.1
,
29.4
],
'11'
:
[
114.10
,
22.18
],
11
:
[
114.1
,
22.18
]
};
};
function
convertData
(
data
)
{
function
convertData
(
data
)
{
var
res
=
[];
var
res
=
[];
for
(
var
i
=
0
;
i
<
data
.
length
;
i
++
)
{
for
(
var
i
=
0
;
i
<
data
.
length
;
i
++
)
{
var
geoCoord
=
geoCoordMap
[
data
[
i
].
name
];
var
geoCoord
=
geoCoordMap
[
data
[
i
].
name
];
if
(
geoCoord
)
{
if
(
geoCoord
)
{
res
.
push
({
res
.
push
({
name
:
data
[
i
].
name
,
name
:
data
[
i
].
name
,
value
:
geoCoord
.
concat
(
data
[
i
].
value
)
value
:
geoCoord
.
concat
(
data
[
i
].
value
)
});
});
}
}
}
}
console
.
log
(
res
)
console
.
log
(
res
);
return
res
;
return
res
;
}
}
let
option
=
{
let
option
=
{
tooltip
:
{
tooltip
:
{
show
:
false
show
:
false
},
},
geo
:
{
geo
:
{
map
:
'china'
,
map
:
"china"
,
roam
:
true
,
roam
:
true
,
center
:
[
104.95
,
35.27
],
center
:
[
104.95
,
35.27
],
// 地图尺寸为容器宽高较小值的80%
// 地图尺寸为容器宽高较小值的80%
zoom
:
1.7
,
zoom
:
1.7
,
// scaleLimit:{
// scaleLimit:{
// max:'1.2',
// max:'1.2',
// min:'0.7'
// min:'0.7'
// },
// },
label
:
{
label
:
{
normal
:
{
normal
:
{
show
:
false
,
show
:
false
,
textStyle
:
{
textStyle
:
{
color
:
'rgba(0,0,0,0.6)'
color
:
"rgba(0,0,0,0.6)"
}
}
}
}
},
},
itemStyle
:
{
itemStyle
:
{
areaColor
:
'rgba(231, 243, 255, 1)'
,
// 设置所有区域的默认填充色[citation:8]
areaColor
:
"rgba(231, 243, 255, 1)"
,
// 设置所有区域的默认填充色[citation:8]
borderColor
:
'rgb(5, 95, 194)'
,
// 设置边界线颜色[citation:8]
borderColor
:
"rgb(5, 95, 194)"
,
// 设置边界线颜色[citation:8]
borderWidth
:
1
// 设置边界线宽度[citation:8]
borderWidth
:
1
// 设置边界线宽度[citation:8]
},
}
},
},
// backgroundColor: 'rgba(0,51,102, 1)',
// backgroundColor: 'rgba(0,51,102, 1)',
series
:
[{
series
:
[
type
:
'scatter'
,
{
coordinateSystem
:
'geo'
,
type
:
"scatter"
,
data
:
convertData
(
data
),
coordinateSystem
:
"geo"
,
symbolSize
:
10
,
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
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
)
=>
{
export
const
getBarChart
=
(
nameList
,
valueList
,
color
=
[
"rgba(255, 159, 22, 1)"
,
"rgba(255, 159, 22, 0)"
],
name
)
=>
{
const
option
=
{
const
option
=
{
tooltip
:
{
tooltip
:
{
trigger
:
"axis"
,
trigger
:
"axis"
,
formatter
:
function
(
params
)
{
formatter
:
function
(
params
)
{
let
result
=
params
[
0
].
name
+
'<br/>'
;
let
result
=
params
[
0
].
name
+
"<br/>"
;
params
.
forEach
(
function
(
item
,
index
)
{
params
.
forEach
(
function
(
item
,
index
)
{
// 自定义颜色数组
// 自定义颜色数组
const
customColors
=
[
color
[
0
]];
const
customColors
=
[
color
[
0
]];
const
dotColor
=
customColors
[
index
%
customColors
.
length
];
// 循环取色
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>`
;
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/>`
;
result
+=
dot
+
`
${
item
.
seriesName
}
:
${
item
.
value
}
<br/>`
;
});
});
return
result
;
return
result
;
}
}
},
},
grid
:
{
grid
:
{
top
:
'3%'
,
top
:
"3%"
,
right
:
'3%'
,
right
:
"3%"
,
bottom
:
'1%'
,
bottom
:
"1%"
,
left
:
'1%'
,
left
:
"1%"
,
containLabel
:
true
containLabel
:
true
},
},
xAxis
:
{
xAxis
:
{
axisLine
:
{
axisLine
:
{
lineStyle
:
{
lineStyle
:
{
width
:
1
,
width
:
1
,
color
:
"rgba(231, 243, 255, 1)"
color
:
"rgba(231, 243, 255, 1)"
}
}
},
},
axisTick
:
axisTick
:
{
show
:
false
},
{
show
:
false
},
type
:
"category"
,
type
:
"category"
,
boundaryGap
:
[
100
,
100
],
boundaryGap
:
[
100
,
100
],
axisLabel
:
{
axisLabel
:
{
color
:
"rgba(95, 101, 108, 1)"
color
:
"rgba(95, 101, 108, 1)"
,
// fontSize: 22,
// fontSize: 22,
// fontWeight: 400
// fontWeight: 400
},
},
data
:
nameList
data
:
nameList
},
},
yAxis
:
{
yAxis
:
{
type
:
"value"
,
type
:
"value"
,
axisLine
:
{
axisLine
:
{
lineStyle
:
{
lineStyle
:
{
type
:
"dashed"
type
:
"dashed"
}
}
},
},
axisLabel
:
{
axisLabel
:
{
color
:
"rgba(95, 101, 108, 1)"
,
color
:
"rgba(95, 101, 108, 1)"
// fontSize: 22,
// fontSize: 22,
// fontWeight: 400
// fontWeight: 400
},
},
splitNumber
:
8
,
splitNumber
:
8
,
splitLine
:
{
splitLine
:
{
lineStyle
:
{
lineStyle
:
{
width
:
1
,
width
:
1
,
type
:
"dashed"
,
type
:
"dashed"
,
color
:
"rgba(231, 243, 255, 1)"
color
:
"rgba(231, 243, 255, 1)"
},
}
}
},
series
:
[
{
name
:
name
,
type
:
"bar"
,
data
:
valueList
,
}
barWidth
:
12
,
},
itemStyle
:
{
series
:
[{
color
:
function
(
params
)
{
name
:
name
,
return
new
echarts
.
graphic
.
LinearGradient
(
0
,
1
,
0
,
0
,
[
type
:
'bar'
,
{
data
:
valueList
,
offset
:
0
,
color
:
color
[
1
]
barWidth
:
12
,
},
itemStyle
:
{
{
color
:
function
(
params
)
{
offset
:
1
,
return
new
echarts
.
graphic
.
LinearGradient
(
0
,
1
,
0
,
0
,
color
:
color
[
0
]
[{
}
offset
:
0
,
]);
color
:
color
[
1
]
},
},
barBorderRadius
:
10
{
}
offset
:
1
,
}
color
:
color
[
0
]
]
}
};
]);
return
option
;
},
};
barBorderRadius
:
10
,
}
}]
}
return
option
}
export
const
getLineChart
=
(
object
,
isPercent
)
=>
{
export
const
getLineChart
=
(
object
,
isPercent
)
=>
{
const
option
=
{
const
option
=
{
title
:
{
title
:
{
text
:
""
text
:
""
},
},
tooltip
:
{
tooltip
:
{
trigger
:
"axis"
,
trigger
:
"axis"
,
formatter
:
function
(
params
)
{
formatter
:
function
(
params
)
{
let
result
=
params
[
0
].
name
+
'<br/>'
;
let
result
=
params
[
0
].
name
+
"<br/>"
;
params
.
forEach
(
function
(
item
,
index
)
{
params
.
forEach
(
function
(
item
,
index
)
{
// 自定义颜色数组
// 自定义颜色数组
const
customColors
=
[
object
.
color
];
const
customColors
=
[
object
.
color
];
const
dotColor
=
customColors
[
index
%
customColors
.
length
];
// 循环取色
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>`
;
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/>`
;
result
+=
dot
+
`
${
item
.
seriesName
}
:
${
item
.
value
}${
isPercent
?
"%"
:
""
}
<br/>`
;
});
});
return
result
;
return
result
;
}
}
},
},
grid
:
{
grid
:
{
top
:
'3%'
,
top
:
"3%"
,
right
:
'3%'
,
right
:
"3%"
,
bottom
:
'1%'
,
bottom
:
"1%"
,
left
:
'1%'
,
left
:
"1%"
,
containLabel
:
true
containLabel
:
true
},
},
// toolbox: {
// toolbox: {
// feature: {
// feature: {
// saveAsImage: {}
// saveAsImage: {}
// }
// }
// },
// },
xAxis
:
{
xAxis
:
{
axisLine
:
{
axisLine
:
{
lineStyle
:
{
lineStyle
:
{
width
:
1
,
width
:
1
,
color
:
"rgba(231, 243, 255, 1)"
color
:
"rgba(231, 243, 255, 1)"
}
}
},
},
axisTick
:
axisTick
:
{
show
:
false
},
{
show
:
false
},
type
:
"category"
,
type
:
"category"
,
boundaryGap
:
[
100
,
100
],
boundaryGap
:
[
100
,
100
],
axisLabel
:
{
axisLabel
:
{
color
:
"rgba(95, 101, 108, 1)"
color
:
"rgba(95, 101, 108, 1)"
,
// fontSize: 22,
// fontSize: 22,
// fontWeight: 400
// fontWeight: 400
},
},
data
:
object
.
xAxisData
data
:
object
.
xAxisData
},
},
yAxis
:
{
yAxis
:
{
type
:
"value"
,
type
:
"value"
,
axisLine
:
{
axisLine
:
{
lineStyle
:
{
lineStyle
:
{
type
:
"dashed"
type
:
"dashed"
}
}
},
},
axisLabel
:
{
axisLabel
:
{
color
:
"rgba(95, 101, 108, 1)"
,
color
:
"rgba(95, 101, 108, 1)"
,
// fontSize: 22,
// fontSize: 22,
// fontWeight: 400
// fontWeight: 400
formatter
:
`{value}
${
isPercent
?
'%'
:
''
}
`
formatter
:
`{value}
${
isPercent
?
"%"
:
""
}
`
},
},
splitNumber
:
8
,
splitNumber
:
8
,
splitLine
:
{
splitLine
:
{
lineStyle
:
{
lineStyle
:
{
width
:
1
,
width
:
1
,
type
:
"dashed"
,
type
:
"dashed"
,
color
:
"rgba(231, 243, 255, 1)"
color
:
"rgba(231, 243, 255, 1)"
},
}
}
}
},
},
series
:
[
series
:
[
{
{
name
:
object
.
name
,
name
:
object
.
name
,
type
:
"line"
,
type
:
"line"
,
symbolSize
:
8
,
symbolSize
:
8
,
symbol
:
"circle"
,
symbol
:
'circle'
,
itemStyle
:
{
itemStyle
:
{
color
:
"#ffffff"
,
color
:
"#ffffff"
,
borderColor
:
object
.
color
,
borderColor
:
object
.
color
,
borderWidth
:
3
borderWidth
:
3
},
},
lineStyle
:
{
lineStyle
:
{
color
:
object
.
color
color
:
object
.
color
,
},
},
data
:
object
.
seriesData
data
:
object
.
seriesData
}
}
]
]
};
};
return
option
;
return
option
;
};
}
export
const
getHorizontalBarChart1
=
(
nameList
,
valueList
,
isPer
)
=>
{
export
const
getHorizontalBarChart1
=
(
nameList
,
valueList
,
isPer
)
=>
{
const
colorList
=
[
'#ce4f51'
,
'#1778ff'
]
const
colorList
=
[
"#ce4f51"
,
"#1778ff"
];
const
option
=
{
const
option
=
{
tooltip
:
{},
tooltip
:
{},
grid
:
{
grid
:
{
top
:
'3%'
,
top
:
"3%"
,
right
:
'3%'
,
right
:
"3%"
,
bottom
:
'1%'
,
bottom
:
"1%"
,
left
:
'1%'
,
left
:
"1%"
,
containLabel
:
true
containLabel
:
true
},
},
color
:
[
'#ce4f51'
,
'#1778ff'
],
color
:
[
"#ce4f51"
,
"#1778ff"
],
xAxis
:
{
xAxis
:
{
type
:
'value'
,
type
:
"value"
,
splitLine
:
{
splitLine
:
{
show
:
false
show
:
false
},
},
show
:
false
show
:
false
},
},
yAxis
:
{
yAxis
:
{
type
:
'category'
,
type
:
"category"
,
data
:
nameList
,
data
:
nameList
,
splitLine
:
{
splitLine
:
{
show
:
false
show
:
false
},
},
axisTick
:
{
axisTick
:
{
show
:
false
show
:
false
},
},
axisLine
:
{
axisLine
:
{
show
:
false
show
:
false
},
},
axisLabel
:
{
axisLabel
:
{
show
:
true
show
:
true
}
}
},
},
series
:
[{
series
:
[
type
:
'bar'
,
{
data
:
valueList
.
map
((
item
,
index
)
=>
{
type
:
"bar"
,
return
{
data
:
valueList
.
map
((
item
,
index
)
=>
{
value
:
item
,
return
{
label
:
{
value
:
item
,
textStyle
:
{
label
:
{
color
:
index
<
4
?
'#1778ff'
:
'#ce4f51'
textStyle
:
{
}
color
:
index
<
4
?
"#1778ff"
:
"#ce4f51"
}
}
};
}
}),
};
label
:
{
}),
show
:
true
,
label
:
{
position
:
[
450
,
-
2
],
show
:
true
,
formatter
:
function
(
params
)
{
position
:
[
450
,
-
2
],
return
isPer
?
params
.
value
+
'%'
:
params
.
value
formatter
:
function
(
params
)
{
}
return
isPer
?
params
.
value
+
"%"
:
params
.
value
;
},
}
barWidth
:
8
,
},
itemStyle
:
{
barWidth
:
8
,
color
:
function
(
params
)
{
itemStyle
:
{
if
(
params
.
dataIndex
<
4
)
{
color
:
function
(
params
)
{
return
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
1
,
0
,
if
(
params
.
dataIndex
<
4
)
{
[{
return
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
1
,
0
,
[
offset
:
0
,
{
color
:
'rgba(22, 119, 255, 0)'
offset
:
0
,
},
color
:
"rgba(22, 119, 255, 0)"
{
},
offset
:
1
,
{
color
:
colorList
[
1
]
offset
:
1
,
}
color
:
colorList
[
1
]
]);
}
}
else
{
]);
return
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
1
,
0
,
}
else
{
[{
return
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
1
,
0
,
[
offset
:
0
,
{
color
:
'rgba(206, 79, 81, 0)'
offset
:
0
,
},
color
:
"rgba(206, 79, 81, 0)"
{
},
offset
:
1
,
{
color
:
colorList
[
0
]
offset
:
1
,
}
color
:
colorList
[
0
]
]);
}
}
]);
}
},
},
barBorderRadius
:
4
,
barBorderRadius
:
4
}
}
}]
}
}
]
return
option
};
}
return
option
;
};
export
const
getHorizontalBarChart2
=
(
nameList
,
valueList
,
isPer
)
=>
{
export
const
getHorizontalBarChart2
=
(
nameList
,
valueList
,
isPer
)
=>
{
const
colorList
=
[
const
colorList
=
[
[
'rgba(64, 150, 255, 1)'
,
'rgba(64, 150, 255, 0)'
],
[
"rgba(64, 150, 255, 1)"
,
"rgba(64, 150, 255, 0)"
],
[
'rgba(255, 120, 117, 1)'
,
'rgba(255, 120, 117, 0)'
],
[
"rgba(255, 120, 117, 1)"
,
"rgba(255, 120, 117, 0)"
],
[
'rgba(89, 126, 247, 1)'
,
'rgba(89, 126, 247, 0)'
],
[
"rgba(89, 126, 247, 1)"
,
"rgba(89, 126, 247, 0)"
],
[
'rgba(54, 207, 201, 1)'
,
'rgba(54, 207, 201, 0)'
],
[
"rgba(54, 207, 201, 1)"
,
"rgba(54, 207, 201, 0)"
],
[
'rgba(255, 197, 61, 1)'
,
'rgba(255, 197, 61, 0)'
],
[
"rgba(255, 197, 61, 1)"
,
"rgba(255, 197, 61, 0)"
],
[
'rgba(179, 127, 235, 1)'
,
'rgba(179, 127, 235, 0)'
]
[
"rgba(179, 127, 235, 1)"
,
"rgba(179, 127, 235, 0)"
]
]
];
console
.
log
(
colorList
)
console
.
log
(
colorList
);
const
option
=
{
const
option
=
{
tooltip
:
{},
tooltip
:
{},
grid
:
{
grid
:
{
top
:
'6%'
,
top
:
"6%"
,
right
:
'6%'
,
right
:
"6%"
,
bottom
:
'0'
,
bottom
:
"0"
,
left
:
'1%'
,
left
:
"1%"
,
containLabel
:
true
containLabel
:
true
},
},
xAxis
:
{
xAxis
:
{
type
:
'value'
,
type
:
"value"
,
splitLine
:
{
splitLine
:
{
show
:
false
show
:
false
},
},
show
:
false
show
:
false
},
},
yAxis
:
{
yAxis
:
{
type
:
'category'
,
type
:
"category"
,
data
:
nameList
,
data
:
nameList
,
splitLine
:
{
splitLine
:
{
show
:
false
show
:
false
},
},
axisTick
:
{
axisTick
:
{
show
:
false
show
:
false
},
},
axisLine
:
{
axisLine
:
{
show
:
false
show
:
false
},
},
axisLabel
:
{
axisLabel
:
{
show
:
true
show
:
true
}
}
},
},
series
:
[{
series
:
[
type
:
'bar'
,
{
data
:
valueList
.
map
((
item
,
index
)
=>
{
type
:
"bar"
,
return
{
data
:
valueList
.
map
((
item
,
index
)
=>
{
value
:
item
,
return
{
label
:
{
value
:
item
,
textStyle
:
{
label
:
{
color
:
colorList
[
index
][
0
]
textStyle
:
{
}
color
:
colorList
[
index
%
6
][
0
]
}
}
};
}
}),
};
label
:
{
}),
show
:
true
,
label
:
{
position
:
[
340
,
-
2
],
show
:
true
,
formatter
:
function
(
params
)
{
position
:
[
340
,
-
2
],
return
isPer
?
params
.
value
+
'%'
:
params
.
value
formatter
:
function
(
params
)
{
}
return
isPer
?
params
.
value
+
"%"
:
params
.
value
;
},
}
barWidth
:
8
,
},
itemStyle
:
{
barWidth
:
8
,
color
:
function
(
params
)
{
itemStyle
:
{
console
.
log
(
'params'
,
params
)
color
:
function
(
params
)
{
return
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
1
,
0
,
console
.
log
(
"params"
,
params
);
[{
return
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
1
,
0
,
[
offset
:
0
,
{
color
:
colorList
[
params
.
dataIndex
][
1
]
offset
:
0
,
},
color
:
colorList
[
params
.
dataIndex
%
6
][
1
]
{
},
offset
:
1
,
{
color
:
colorList
[
params
.
dataIndex
][
0
]
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"
}
},
},
axisLabel
:
{
barBorderRadius
:
4
,
color
:
"rgba(95, 101, 108, 1)"
}
// fontSize: 22,
}]
// fontWeight: 400
}
},
return
option
splitNumber
:
8
,
}
splitLine
:
{
export
const
getMultipleLineChart
=
(
obj
)
=>
{
lineStyle
:
{
const
color
=
[
'rgba(19, 168, 168, 1)'
,
'rgba(146, 84, 222, 1)'
,
'rgba(250, 140, 22, 1)'
,
'rgba(206, 79, 81, 1)'
]
width
:
1
,
const
option
=
{
type
:
"dashed"
,
title
:
{
color
:
"rgba(231, 243, 255, 1)"
text
:
""
}
},
}
tooltip
:
{
},
trigger
:
"axis"
,
series
:
obj
.
data
.
map
((
item
,
index
)
=>
{
formatter
:
function
(
params
)
{
return
{
let
result
=
params
[
0
].
name
+
'<br/>'
;
name
:
item
.
name
,
params
.
forEach
(
function
(
item
,
index
)
{
type
:
"line"
,
// 自定义颜色数组
symbolSize
:
6
,
const
customColors
=
color
;
symbol
:
"circle"
,
const
dotColor
=
customColors
[
index
%
customColors
.
length
];
// 循环取色
itemStyle
:
{
// 创建彩色圆点图标
color
:
"#ffffff"
,
const
dot
=
`<span style="display:inline-block;margin-right:5px;border-radius:50%;width:10px;height:10px;background-color:
${
dotColor
}
;"></span>`
;
borderColor
:
color
[
index
],
result
+=
dot
+
`
${
item
.
seriesName
}
:
${
item
.
value
}
<br/>`
;
borderWidth
:
2
});
},
return
result
;
lineStyle
:
{
}
width
:
1
,
},
color
:
color
[
index
]
grid
:
{
},
top
:
'12%'
,
data
:
item
.
value
right
:
'3%'
,
};
bottom
:
'3%'
,
})
left
:
'1%'
,
};
containLabel
:
true
return
option
;
},
};
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
;
}
//出口管制主页接口
//出口管制主页接口
export
const
getMultipleBarChart_m
=
(
object
)
=>
{
export
const
getMultipleBarChart_m
=
object
=>
{
const
list
=
_
.
chain
(
object
.
data
).
filter
(
'year'
).
orderBy
(
'year'
,
'asc'
).
value
();
const
list
=
_
.
chain
(
object
.
data
).
filter
(
"year"
).
orderBy
(
"year"
,
"asc"
).
value
();
const
colors
=
[
const
colors
=
[
[
'rgba(22, 119, 255, 1)'
,
'rgba(22, 119, 255, 0)'
],
[
"rgba(22, 119, 255, 1)"
,
"rgba(22, 119, 255, 0)"
],
[
'rgba(206, 79, 81, 1)'
,
'rgba(206, 79, 81, 0)'
],
[
"rgba(206, 79, 81, 1)"
,
"rgba(206, 79, 81, 0)"
],
[
'rgba(255, 197, 61, 1)'
,
'rgba(255, 197, 61, 0)'
],
[
"rgba(255, 197, 61, 1)"
,
"rgba(255, 197, 61, 0)"
],
[
'rgba(255, 204, 199, 1)'
,
'rgba(255, 204, 199, 0)'
],
[
"rgba(255, 204, 199, 1)"
,
"rgba(255, 204, 199, 0)"
],
[
'rgba(179, 127, 235, 1)'
,
'rgba(179, 127, 235, 0)'
],
[
"rgba(179, 127, 235, 1)"
,
"rgba(179, 127, 235, 0)"
],
[
'rgba(127, 218, 235, 1)'
,
'rgba(127, 214, 235, 0)'
],
[
"rgba(127, 218, 235, 1)"
,
"rgba(127, 214, 235, 0)"
]
];
];
const
names
=
_
.
map
(
list
,
'year'
);
const
names
=
_
.
map
(
list
,
"year"
);
const
datas
=
_
.
chain
(
object
.
domains
).
splice
(
0
,
6
).
map
((
name
,
index
)
=>
{
const
datas
=
_
.
chain
(
object
.
domains
)
console
.
log
(
_
.
map
(
list
,
name
))
.
splice
(
0
,
6
)
return
{
.
map
((
name
,
index
)
=>
{
name
,
console
.
log
(
_
.
map
(
list
,
name
));
data
:
_
.
map
(
list
,
`domainNum.
${
name
}
`
),
return
{
type
:
"bar"
,
name
,
barWidth
:
12
,
data
:
_
.
map
(
list
,
`domainNum.
${
name
}
`
),
itemStyle
:
{
type
:
"bar"
,
color
:
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
0
,
1
,
[
barWidth
:
12
,
{
offset
:
0
,
color
:
colors
[
index
%
colors
.
length
][
0
]
},
itemStyle
:
{
// { offset: 0.5, color: '#188df0' },
color
:
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
0
,
1
,
[
{
offset
:
1
,
color
:
colors
[
index
%
colors
.
length
][
1
]
}
{
offset
:
0
,
color
:
colors
[
index
%
colors
.
length
][
0
]
},
]),
// { offset: 0.5, color: '#188df0' },
borderRadius
:
[
6
,
6
,
0
,
0
]
{
offset
:
1
,
color
:
colors
[
index
%
colors
.
length
][
1
]
}
}
]),
}
borderRadius
:
[
6
,
6
,
0
,
0
]
}).
value
();
}
console
.
log
(
'names'
,
names
)
};
const
option
=
{
})
tooltip
:
{
.
value
();
trigger
:
"axis"
,
console
.
log
(
"names"
,
names
);
axisPointer
:
{
const
option
=
{
type
:
"shadow"
tooltip
:
{
}
trigger
:
"axis"
,
},
axisPointer
:
{
grid
:
{
type
:
"shadow"
top
:
50
}
},
},
legend
:
{
grid
:
{
// type: "scroll",
top
:
50
// show: true,
},
// orient: "horizontal",
legend
:
{
icon
:
"circle"
,
// type: "scroll",
},
// show: true,
xAxis
:
{
// orient: "horizontal",
type
:
"category"
,
icon
:
"circle"
data
:
names
},
},
xAxis
:
{
yAxis
:
{
type
:
"category"
,
type
:
"value"
data
:
names
},
},
series
:
datas
yAxis
:
{
}
type
:
"value"
return
option
;
},
}
series
:
datas
};
return
option
;
};
出口管制接口.md
0 → 100644
浏览文件 @
2e27cc08
# 交互消息类
## 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
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论