Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
risk-monitor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蔡建
risk-monitor
Commits
273f345b
提交
273f345b
authored
12月 17, 2025
作者:
coderBryanFu
浏览文件
操作
浏览文件
下载
差异文件
update
上级
1b14c707
af566f60
全部展开
显示空白字符变更
内嵌
并排
正在显示
46 个修改的文件
包含
832 行增加
和
278 行删除
+832
-278
bill.js
src/api/bill.js
+17
-5
billHome.js
src/api/bill/billHome.js
+34
-2
deepdig.js
src/api/deepdig.js
+12
-0
exportControl.js
src/api/exportControl.js
+49
-16
button.vue
src/components/button/button.vue
+1
-0
buttonList.vue
src/components/buttonList/buttonList.vue
+1
-0
index.vue
src/views/bill/background/index.vue
+38
-30
index.vue
src/views/bill/billHome/index.vue
+0
-0
multiLineChart.js
src/views/bill/billHome/utils/multiLineChart.js
+59
-14
worldCloudChart.js
src/views/bill/billHome/utils/worldCloudChart.js
+2
-0
index.vue
src/views/bill/deepDig/processAnalysis/index.vue
+54
-5
boxplot.js
src/views/bill/deepDig/processAnalysis/utils/boxplot.js
+36
-4
STimeline.vue
src/views/bill/introdoction/STimeline.vue
+121
-47
index.vue
src/views/bill/introdoction/index.vue
+97
-51
index.vue
src/views/bill/template/index.vue
+107
-44
piechart.js
src/views/bill/template/utils/piechart.js
+4
-1
fishbone-back.vue
...views/exportControl/analysis/components/fishbone-back.vue
+0
-0
fishbone-mock.json
...iews/exportControl/analysis/components/fishbone-mock.json
+0
-0
fishbone.vue
src/views/exportControl/analysis/components/fishbone.vue
+0
-0
influencePanel2.vue
...ews/exportControl/analysis/components/influencePanel2.vue
+7
-23
mapCharts.vue
src/views/exportControl/analysis/components/mapCharts.vue
+14
-0
panel1.vue
src/views/exportControl/analysis/components/panel1.vue
+23
-2
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
+0
-0
charts.js
src/views/exportControl/utils/charts.js
+0
-0
bg.png
src/views/gjOverView/assets/bg.png
+0
-0
icon1.png
src/views/gjOverView/assets/icon1.png
+0
-0
MeansAnalysis.vue
src/views/gjOverView/component/MeansAnalysis.vue
+0
-0
ResourceAnalysis.vue
src/views/gjOverView/component/ResourceAnalysis.vue
+0
-0
Timeline.vue
src/views/gjOverView/component/Timeline.vue
+0
-0
index.vue
src/views/gjOverView/index.vue
+0
-0
barChart2.js
src/views/gjOverView/js/barChart2.js
+0
-0
multiLineChart2.js
src/views/gjOverView/js/multiLineChart2.js
+0
-0
radarChart2.js
src/views/gjOverView/js/radarChart2.js
+0
-0
TechnologyFigures-icon1.png
...chnologyFigures/assets/images/TechnologyFigures-icon1.png
+0
-0
TechnologyFigures-icon2.png
...chnologyFigures/assets/images/TechnologyFigures-icon2.png
+0
-0
TechnologyFigures-icon3.png
...chnologyFigures/assets/images/TechnologyFigures-icon3.png
+0
-0
TechnologyFigures-icon4.png
...chnologyFigures/assets/images/TechnologyFigures-icon4.png
+0
-0
SourceLibrary.vue
src/views/technologyFigures/component/SourceLibrary.vue
+0
-0
index.vue
src/views/technologyFigures/index.vue
+0
-0
source.json
src/views/technologyFigures/json/source.json
+0
-0
出口管制接口.md
出口管制接口.md
+0
-0
没有找到文件。
src/api/bill.js
浏览文件 @
273f345b
...
@@ -14,13 +14,13 @@ export function getBillInfo(params) {
...
@@ -14,13 +14,13 @@ export function getBillInfo(params) {
// 提出人-根据动议ID获取对应的提出人信息
// 提出人-根据动议ID获取对应的提出人信息
/**
/**
* @param {
i
d}
* @param {
billI
d}
* @header token
* @header token
*/
*/
export
function
getBillPerson
(
params
)
{
export
function
getBillPerson
(
params
)
{
return
request
({
return
request
({
method
:
'GET'
,
method
:
'GET'
,
url
:
`/api/billInfoBean/person/
${
params
.
i
d
}
`
,
url
:
`/api/billInfoBean/person/
${
params
.
billI
d
}
`
,
params
,
params
,
})
})
}
}
...
@@ -63,6 +63,18 @@ export function getBillBackground(params) {
...
@@ -63,6 +63,18 @@ export function getBillBackground(params) {
params
,
params
,
})
})
}
}
// 相关事件-根据法案ID获取相关事件信息
/**
* @param {id}
* @header token
*/
export
function
getBillInfoEvent
(
params
)
{
return
request
({
method
:
'GET'
,
url
:
`/api/billInfoBean/event/
${
params
.
id
}
`
,
params
,
})
}
// 议员相关性-根据法案ID获取议员分析信息(现在只包括名称 支持 反对,没有标签和事件动态)
// 议员相关性-根据法案ID获取议员分析信息(现在只包括名称 支持 反对,没有标签和事件动态)
/**
/**
...
@@ -92,20 +104,20 @@ export function getBillContentId(params) {
...
@@ -92,20 +104,20 @@ export function getBillContentId(params) {
// 主要条款-根据原文ID获取条款内容
// 主要条款-根据原文ID获取条款内容
/**
/**
* @param {id,cRelated,currentPage,pageSize}
* @param {
billid,
id,cRelated,currentPage,pageSize}
* @header token
* @header token
*/
*/
export
function
getBillContentTk
(
params
)
{
export
function
getBillContentTk
(
params
)
{
return
request
({
return
request
({
method
:
'GET'
,
method
:
'GET'
,
url
:
`/api/billInfoBean/content/tk/
${
params
.
id
}
`
,
url
:
`/api/billInfoBean/content/tk/
${
params
.
billid
}
/
${
params
.
id
}
`
,
params
,
params
,
})
})
}
}
// 限制方式-根据法案原文ID获取限制方式列表
// 限制方式-根据法案原文ID获取限制方式列表
/**
/**
* @param {
i
d}
* @param {
billI
d}
* @header token
* @header token
*/
*/
export
function
getBillContentXzfs
(
params
)
{
export
function
getBillContentXzfs
(
params
)
{
...
...
src/api/bill/billHome.js
浏览文件 @
273f345b
...
@@ -13,11 +13,11 @@ export function getBillIndustry(params) {
...
@@ -13,11 +13,11 @@ export function getBillIndustry(params) {
}
}
// 涉华法案统计
// 涉华法案统计
export
function
getBillCount
()
{
export
function
getBillCount
(
params
)
{
return
request
({
return
request
({
method
:
'GET'
,
method
:
'GET'
,
url
:
`/api/BillOverview/billCount`
,
url
:
`/api/BillOverview/billCount`
,
params
})
})
}
}
...
@@ -65,3 +65,34 @@ export function getHylyList() {
...
@@ -65,3 +65,34 @@ export function getHylyList() {
url
:
`/api/billImpactAnalysis/industry/hylyList`
,
url
:
`/api/billImpactAnalysis/industry/hylyList`
,
})
})
}
}
// 获取法案提出部门
/**
* @param {year}
*/
export
function
getBillPostOrg
(
params
)
{
return
request
({
method
:
'GET'
,
url
:
`/api/BillOverview/billPostOrg/
${
params
.
year
}
`
,
})
}
// 获取关键议员提案
/**
* @param {year}
*/
export
function
getMemberProposal
(
params
)
{
return
request
({
method
:
'GET'
,
url
:
`/api/BillOverview/memberProposal/
${
params
.
year
}
`
,
})
}
// 获取资源库
export
function
getBills
(
params
)
{
return
request
({
method
:
'GET'
,
url
:
`/api/BillOverview/bills`
,
params
})
}
\ No newline at end of file
src/api/deepdig.js
浏览文件 @
273f345b
...
@@ -12,6 +12,18 @@ export function getBillTimeAnalyze(params) {
...
@@ -12,6 +12,18 @@ export function getBillTimeAnalyze(params) {
})
})
}
}
// 修正案次数分析
/**
* @param {id}
*/
export
function
getBillAmeAnalyzeCount
(
params
)
{
return
request
({
method
:
'GET'
,
url
:
`/api/billDeepDive/ameAnalyze/count/
${
params
.
id
}
`
,
params
,
})
}
// 根据法案ID获取党派政治献金
// 根据法案ID获取党派政治献金
/**
/**
* @param {id, personCongress}
* @param {id, personCongress}
...
...
src/api/exportControl.js
浏览文件 @
273f345b
...
@@ -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
浏览文件 @
273f345b
...
@@ -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
浏览文件 @
273f345b
...
@@ -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/bill/background/index.vue
浏览文件 @
273f345b
...
@@ -35,8 +35,8 @@
...
@@ -35,8 +35,8 @@
v-for=
"(item, index) in backgroundList"
v-for=
"(item, index) in backgroundList"
:key=
"item.id"
:key=
"item.id"
>
>
<div
class=
"id"
>
{{
index
+
1
}}
</div>
<div
class=
"id"
>
{{
(
currentPage
-
1
)
*
10
+
index
+
1
}}
</div>
<div
class=
"title"
>
{{
item
.
b
jnr
}}
</div>
<div
class=
"title"
>
{{
item
.
b
ackgroundTitle
}}
</div>
<div
class=
"share"
>
<div
class=
"share"
>
<img
src=
"./assets/icons/open.png"
alt=
"打开"
/>
<img
src=
"./assets/icons/open.png"
alt=
"打开"
/>
</div>
</div>
...
@@ -45,7 +45,7 @@
...
@@ -45,7 +45,7 @@
<div
class=
"box1-main-footer"
>
<div
class=
"box1-main-footer"
>
<div
class=
"info"
>
<div
class=
"info"
>
{{
{{
`共有${
backgroundList.length
}
条${
`共有${
total
}
条${
box1BtnActive === 1 ? "涉华" : "全部"
box1BtnActive === 1 ? "涉华" : "全部"
}
背景`
}
背景`
}}
}}
...
@@ -54,7 +54,9 @@
...
@@ -54,7 +54,9 @@
<
el
-
pagination
<
el
-
pagination
background
background
layout
=
"prev, pager, next"
layout
=
"prev, pager, next"
:
total
=
"backgroundList.length"
:
total
=
"total"
v
-
model
:
current
-
page
=
"currentPage"
@
current
-
change
=
"handleGetBillBackground"
/>
/>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
...
@@ -80,7 +82,7 @@
...
@@ -80,7 +82,7 @@
:
key
=
"index"
:
key
=
"index"
>
>
<
div
class
=
"left"
>
<
div
class
=
"left"
>
<
img
:
src
=
"item.image"
alt
=
""
/>
<
img
:
src
=
"item.image
Url || item.image
"
alt
=
""
/>
<
/div
>
<
/div
>
<
div
class
=
"center"
>
<
div
class
=
"center"
>
<
div
class
=
"title"
>
{{
item
.
sjbt
}}
<
/div
>
<
div
class
=
"title"
>
{{
item
.
sjbt
}}
<
/div
>
...
@@ -157,7 +159,7 @@
...
@@ -157,7 +159,7 @@
/><
/el-icon
>
/><
/el-icon
>
<
/div
>
<
/div
>
<
div
class
=
"right-box1-main-bottom"
>
<
div
class
=
"right-box1-main-bottom"
>
<
WordCloudMap
:
data
=
"wordCloudData"
:
shape
=
"circle"
/>
<
WordCloudMap
:
data
=
"wordCloudData"
shape
=
"circle"
/>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
...
@@ -214,25 +216,26 @@ import {
...
@@ -214,25 +216,26 @@ import {
getBillBackground
,
getBillBackground
,
getBillEvent
,
getBillEvent
,
getBillPersonAnalyze
,
getBillPersonAnalyze
,
getBillInfoEvent
}
from
"@/api/bill"
;
}
from
"@/api/bill"
;
const
box1BtnActive
=
ref
(
1
);
const
box1BtnActive
=
ref
(
1
);
const
currentPage
=
ref
(
1
);
const
total
=
ref
(
0
);
const
handleClickBox1Btn
=
(
index
)
=>
{
const
handleClickBox1Btn
=
(
index
)
=>
{
box1BtnActive
.
value
=
index
;
box1BtnActive
.
value
=
index
;
if
(
index
===
2
)
{
currentPage
.
value
=
1
;
handleGetBillBackground
(
false
);
handleGetBillBackground
();
}
else
{
handleGetBillBackground
(
true
);
}
}
;
}
;
const
box2BtnActive
=
ref
(
1
);
const
box2BtnActive
=
ref
(
1
);
const
handleClickBox2Btn
=
(
index
)
=>
{
const
handleClickBox2Btn
=
(
index
)
=>
{
box2BtnActive
.
value
=
index
;
box2BtnActive
.
value
=
index
;
if
(
index
===
1
)
{
if
(
index
===
1
)
{
handleGetBillPersonAnalyze
(
true
);
}
else
{
handleGetBillPersonAnalyze
(
false
);
handleGetBillPersonAnalyze
(
false
);
}
else
{
handleGetBillPersonAnalyze
(
true
);
}
}
}
;
}
;
...
@@ -439,27 +442,29 @@ const wordCloudData = [
...
@@ -439,27 +442,29 @@ const wordCloudData = [
];
];
// 获取立法背景内容
// 获取立法背景内容
const
handleGetBillBackground
=
async
(
cRelated
)
=>
{
const
handleGetBillBackground
=
async
()
=>
{
const
cRelated
=
box1BtnActive
.
value
===
1
?
'Y'
:
'N'
;
const
params
=
{
const
params
=
{
cRelated
:
cRelated
,
cRelated
:
cRelated
,
id
:
window
.
sessionStorage
.
getItem
(
"billId"
),
id
:
window
.
sessionStorage
.
getItem
(
"billId"
),
currentPage
:
0
,
currentPage
:
currentPage
.
value
-
1
,
pageSize
:
10
,
pageSize
:
10
,
}
;
}
;
try
{
try
{
const
res
=
await
getBillBackground
(
params
);
const
res
=
await
getBillBackground
(
params
);
console
.
log
(
"立法背景"
,
res
);
console
.
log
(
"立法背景"
,
res
);
backgroundList
.
value
=
res
.
data
.
content
;
backgroundList
.
value
=
res
.
data
.
content
;
total
.
value
=
res
.
data
.
totalElements
;
// 假设API返回totalElements
}
catch
(
error
)
{
}
}
catch
(
error
)
{
}
}
;
}
;
// 获取相关事件
// 获取相关事件
const
handleGetRelatedEvent
=
async
()
=>
{
const
handleGetRelatedEvent
=
async
()
=>
{
const
params
=
{
const
params
=
{
id
:
1
,
id
:
window
.
sessionStorage
.
getItem
(
"billId"
)
,
}
;
}
;
try
{
try
{
const
res
=
await
getBillEvent
(
params
);
const
res
=
await
getBill
Info
Event
(
params
);
console
.
log
(
"相关事件"
,
res
);
console
.
log
(
"相关事件"
,
res
);
eventList
.
value
=
res
.
data
;
eventList
.
value
=
res
.
data
;
eventList
.
value
.
forEach
((
item
,
index
)
=>
{
eventList
.
value
.
forEach
((
item
,
index
)
=>
{
...
@@ -488,8 +493,9 @@ const handleGetBillPersonAnalyze = async (isOppose) => {
...
@@ -488,8 +493,9 @@ const handleGetBillPersonAnalyze = async (isOppose) => {
const
res
=
await
getBillPersonAnalyze
(
params
);
const
res
=
await
getBillPersonAnalyze
(
params
);
console
.
log
(
"议员相关性分析"
,
res
);
console
.
log
(
"议员相关性分析"
,
res
);
personList
.
value
=
res
.
data
;
personList
.
value
=
res
.
data
;
personList
.
value
.
forEach
((
item
)
=>
{
personList
.
value
.
forEach
((
item
,
index
)
=>
{
item
.
image
=
user1
;
const
imgList
=
[
user1
,
user2
,
user3
,
user4
,
user5
];
item
.
image
=
imgList
[
index
%
imgList
.
length
];
item
.
icon
=
userIcon
;
item
.
icon
=
userIcon
;
item
.
icon1
=
userIcon1
;
item
.
icon1
=
userIcon1
;
}
);
}
);
...
@@ -497,9 +503,9 @@ const handleGetBillPersonAnalyze = async (isOppose) => {
...
@@ -497,9 +503,9 @@ const handleGetBillPersonAnalyze = async (isOppose) => {
}
;
}
;
onMounted
(()
=>
{
onMounted
(()
=>
{
handleGetBillBackground
(
true
);
handleGetBillBackground
();
handleGetRelatedEvent
();
handleGetRelatedEvent
();
handleGetBillPersonAnalyze
(
tru
e
);
handleGetBillPersonAnalyze
(
fals
e
);
}
);
}
);
<
/script
>
<
/script
>
...
@@ -572,7 +578,7 @@ onMounted(() => {
...
@@ -572,7 +578,7 @@ onMounted(() => {
display
:
flex
;
display
:
flex
;
flex
-
wrap
:
wrap
;
flex
-
wrap
:
wrap
;
justify
-
content
:
space
-
between
;
justify
-
content
:
space
-
between
;
align
-
content
:
flex
-
start
;
.
box1
-
main
-
item
{
.
box1
-
main
-
item
{
width
:
544
px
;
width
:
544
px
;
height
:
48
px
;
height
:
48
px
;
...
@@ -598,11 +604,12 @@ onMounted(() => {
...
@@ -598,11 +604,12 @@ onMounted(() => {
width
:
440
px
;
width
:
440
px
;
height
:
48
px
;
height
:
48
px
;
line
-
height
:
48
px
;
line
-
height
:
48
px
;
color
:
rgb
a
(
95
,
101
,
108
,
1
);
color
:
rgb
(
59
,
65
,
75
);
font
-
family
:
Microsoft
YaHei
;
font
-
family
:
"Microsoft YaHei"
;
font
-
size
:
1
4
px
;
font
-
size
:
1
6
px
;
font
-
weight
:
400
;
font
-
weight
:
400
;
text
-
align
:
left
;
text
-
align
:
left
;
overflow
:
hidden
;
}
}
.
share
{
.
share
{
margin
-
left
:
13
px
;
margin
-
left
:
13
px
;
...
@@ -626,8 +633,8 @@ onMounted(() => {
...
@@ -626,8 +633,8 @@ onMounted(() => {
.
info
{
.
info
{
height
:
22
px
;
height
:
22
px
;
line
-
height
:
22
px
;
line
-
height
:
22
px
;
color
:
rgb
a
(
132
,
136
,
142
,
1
);
color
:
rgb
(
132
,
136
,
142
);
font
-
family
:
Microsoft
YaHei
;
font
-
family
:
"Microsoft YaHei"
;
font
-
size
:
14
px
;
font
-
size
:
14
px
;
font
-
weight
:
400
;
font
-
weight
:
400
;
text
-
align
:
left
;
text
-
align
:
left
;
...
@@ -645,6 +652,7 @@ onMounted(() => {
...
@@ -645,6 +652,7 @@ onMounted(() => {
margin
-
top
:
9
px
;
margin
-
top
:
9
px
;
margin
-
left
:
23
px
;
margin
-
left
:
23
px
;
height
:
300
px
;
height
:
300
px
;
overflow
:
auto
;
.
box2
-
main
-
item
{
.
box2
-
main
-
item
{
width
:
1103
px
;
width
:
1103
px
;
height
:
60
px
;
height
:
60
px
;
...
@@ -659,9 +667,9 @@ onMounted(() => {
...
@@ -659,9 +667,9 @@ onMounted(() => {
width
:
64
px
;
width
:
64
px
;
height
:
48
px
;
height
:
48
px
;
border
-
radius
:
2
px
;
border
-
radius
:
2
px
;
im
age
{
im
g
{
width
:
100
px
;
width
:
64
px
;
height
:
100
%
;
height
:
48
px
;
}
}
}
}
.
center
{
.
center
{
...
...
src/views/bill/billHome/index.vue
浏览文件 @
273f345b
差异被折叠。
点击展开。
src/views/bill/billHome/utils/multiLineChart.js
浏览文件 @
273f345b
import
*
as
echarts
from
'echarts'
import
*
as
echarts
from
'echarts'
const
getMultiLineChart
=
(
dataX
,
dataY1
,
dataY2
)
=>
{
const
getMultiLineChart
=
(
dataX
,
dataY1
,
dataY2
,
dataY3
)
=>
{
return
{
return
{
tooltip
:
{
tooltip
:
{
trigger
:
'axis'
,
trigger
:
'axis'
,
...
@@ -9,25 +9,34 @@ const getMultiLineChart = (dataX, dataY1, dataY2) => {
...
@@ -9,25 +9,34 @@ const getMultiLineChart = (dataX, dataY1, dataY2) => {
label
:
{
label
:
{
backgroundColor
:
'#6a7985'
backgroundColor
:
'#6a7985'
}
}
},
formatter
:
function
(
params
)
{
let
res
=
params
[
0
].
name
+
'<br/>'
;
params
.
forEach
(
item
=>
{
res
+=
item
.
marker
+
item
.
seriesName
+
': '
+
item
.
value
+
(
item
.
seriesName
===
'通过率'
?
'%'
:
''
)
+
'<br/>'
;
});
return
res
;
}
}
},
},
grid
:
{
grid
:
{
top
:
'
8
%'
,
top
:
'
15
%'
,
right
:
'5%'
,
right
:
'5%'
,
bottom
:
'5%'
,
bottom
:
'5%'
,
left
:
'5%'
,
left
:
'5%'
,
containLabel
:
true
containLabel
:
true
},
},
legend
:
{
legend
:
{
data
:
[
'提出法案'
,
'通过法案'
],
data
:
[
'提出法案'
,
'通过法案'
,
'通过率'
],
show
:
true
,
show
:
true
,
top
:
0
,
icon
:
'circle'
,
textStyle
:
{
textStyle
:
{
color
:
'rgba(95, 101, 108, 1)'
,
color
:
'rgba(95, 101, 108, 1)'
,
fontFamily
:
'Microsoft YaHei'
,
fontFamily
:
'Microsoft YaHei'
,
fontSize
:
'1
6
px'
,
fontSize
:
'1
4
px'
,
}
}
},
},
color
:
[
'#1
459bb'
,
'#fa8c16
'
],
color
:
[
'#1
677FF'
,
'#FA8C16'
,
'#D9001B
'
],
xAxis
:
[
xAxis
:
[
{
{
type
:
'category'
,
type
:
'category'
,
...
@@ -37,44 +46,80 @@ const getMultiLineChart = (dataX, dataY1, dataY2) => {
...
@@ -37,44 +46,80 @@ const getMultiLineChart = (dataX, dataY1, dataY2) => {
],
],
yAxis
:
[
yAxis
:
[
{
{
type
:
'value'
type
:
'value'
,
position
:
'left'
,
axisLabel
:
{
color
:
'#666'
}
},
{
type
:
'value'
,
position
:
'right'
,
min
:
0
,
max
:
100
,
interval
:
20
,
axisLabel
:
{
formatter
:
'{value}%'
,
color
:
'#666'
},
splitLine
:
{
show
:
false
}
}
}
],
],
series
:
[
series
:
[
{
{
name
:
'提出法案'
,
name
:
'提出法案'
,
type
:
'line'
,
type
:
'line'
,
symbol
:
'emptyCircle'
,
symbolSize
:
6
,
areaStyle
:
{
areaStyle
:
{
color
:
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
0
,
1
,
[{
color
:
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
0
,
1
,
[{
offset
:
0
,
offset
:
0
,
color
:
'rgba(22, 119, 255,
1
)'
// 起始颜色
color
:
'rgba(22, 119, 255,
0.4
)'
// 起始颜色
},
{
},
{
offset
:
1
,
offset
:
1
,
color
:
'rgba(22, 119, 255, 0)'
// 结束颜色
color
:
'rgba(22, 119, 255, 0)'
// 结束颜色
}])
}])
},
},
emphasis
:
{
itemStyle
:
{
focus
:
'series
'
color
:
'#1677FF
'
},
},
data
:
dataY1
data
:
dataY1
},
},
{
{
name
:
'通过法案'
,
name
:
'通过法案'
,
type
:
'line'
,
type
:
'line'
,
symbol
:
'emptyCircle'
,
symbolSize
:
6
,
areaStyle
:
{
areaStyle
:
{
color
:
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
0
,
1
,
[{
color
:
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
0
,
1
,
[{
offset
:
0
,
offset
:
0
,
color
:
'rgba(25
5, 172, 77, 1
)'
// 起始颜色
color
:
'rgba(25
0, 140, 22, 0.4
)'
// 起始颜色
},
{
},
{
offset
:
1
,
offset
:
1
,
color
:
'rgba(25
5, 172, 77
, 0)'
// 结束颜色
color
:
'rgba(25
0, 140, 22
, 0)'
// 结束颜色
}])
}])
},
},
emphasis
:
{
itemStyle
:
{
focus
:
'series
'
color
:
'#FA8C16
'
},
},
data
:
dataY2
data
:
dataY2
},
{
name
:
'通过率'
,
type
:
'line'
,
yAxisIndex
:
1
,
symbol
:
'emptyCircle'
,
symbolSize
:
4
,
lineStyle
:
{
type
:
'dashed'
,
width
:
2
},
itemStyle
:
{
color
:
'#D9001B'
},
data
:
dataY3
}
}
]
]
}
}
...
...
src/views/bill/billHome/utils/worldCloudChart.js
浏览文件 @
273f345b
...
@@ -11,6 +11,8 @@ const getWordCloudChart = (data) => {
...
@@ -11,6 +11,8 @@ const getWordCloudChart = (data) => {
series
:
[
series
:
[
{
{
type
:
"wordCloud"
,
type
:
"wordCloud"
,
width
:
'80%'
,
height
:
'80%'
,
shape
:
"rect"
,
//
shape
:
"rect"
,
//
// 其他形状你可以使用形状路径
// 其他形状你可以使用形状路径
// 或者自定义路径
// 或者自定义路径
...
...
src/views/bill/deepDig/processAnalysis/index.vue
浏览文件 @
273f345b
...
@@ -35,7 +35,7 @@
...
@@ -35,7 +35,7 @@
<div
class=
"box2"
>
<div
class=
"box2"
>
<div
class=
"box-header"
>
<div
class=
"box-header"
>
<div
class=
"header-left"
></div>
<div
class=
"header-left"
></div>
<div
class=
"title"
>
辩论投票时长
</div>
<div
class=
"title"
>
修正案次数分析
</div>
<div
class=
"header-right"
>
<div
class=
"header-right"
>
<div
class=
"icon"
>
<div
class=
"icon"
>
<img
src=
"@/assets/icons/box-header-icon1.png"
alt=
""
/>
<img
src=
"@/assets/icons/box-header-icon1.png"
alt=
""
/>
...
@@ -320,7 +320,7 @@
...
@@ -320,7 +320,7 @@
<
script
setup
>
<
script
setup
>
import
{
ref
,
onMounted
}
from
"vue"
;
import
{
ref
,
onMounted
}
from
"vue"
;
import
{
getBillTimeAnalyze
,
getBill
Xj
,
getBillTotalXj
,
getBillTp
}
from
"@/api/deepdig"
;
import
{
getBillTimeAnalyze
,
getBill
AmeAnalyzeCount
,
getBillTp
}
from
"@/api/deepdig"
;
import
getBoxPlotChcart
from
"./utils/boxplot"
;
import
getBoxPlotChcart
from
"./utils/boxplot"
;
import
*
as
echarts
from
"echarts"
;
import
*
as
echarts
from
"echarts"
;
...
@@ -563,20 +563,69 @@ const handleGetBillTimeAnalyze = async () => {
...
@@ -563,20 +563,69 @@ const handleGetBillTimeAnalyze = async () => {
return
item
.
lcmc
;
return
item
.
lcmc
;
}
);
}
);
chartData1
.
value
.
dataY
=
res
.
data
.
map
(
item
=>
{
chartData1
.
value
.
dataY
=
res
.
data
.
map
(
item
=>
{
return
[
item
.
z
dhs
,
item
.
zshs
,
item
.
pjs
,
item
.
pjx
,
item
.
zw
s
,
item
.
dysc
];
return
[
item
.
z
shs
,
item
.
pjx
,
item
.
zws
,
item
.
pjs
,
item
.
zdh
s
,
item
.
dysc
];
}
);
}
);
}
catch
(
error
)
{
}
}
catch
(
error
)
{
}
}
;
}
;
// 辩论投票时长
// 修正案次数分析
const
handleGetBillAmeAnalyzeCount
=
async
()
=>
{
const
params
=
{
id
:
window
.
sessionStorage
.
getItem
(
"billId"
)
}
;
try
{
const
res
=
await
getBillAmeAnalyzeCount
(
params
);
console
.
log
(
"修正案次数分析"
,
res
);
chartData2
.
value
.
dataX
=
res
.
data
.
map
(
item
=>
{
return
item
.
lcmc
;
}
);
chartData2
.
value
.
dataY
=
res
.
data
.
map
(
item
=>
{
// 兼容多种字段名,防止字段不存在导致图表消失
// 顺序:最小(min), Q1(小), 中位数(median), Q3(大), 最大(max), 该法案(current)
return
[
item
.
zsCount
||
item
.
zscs
||
item
.
zshs
||
0
,
item
.
jsx
||
item
.
pjx
||
0
,
item
.
zws
||
item
.
zwcs
||
0
,
item
.
pjs
||
item
.
pjcs
||
0
,
item
.
zdCount
||
item
.
zdcs
||
item
.
zdhs
||
0
,
item
.
dysc
||
item
.
dycs
||
0
];
}
);
}
catch
(
error
)
{
console
.
error
(
"修正案次数分析 error"
,
error
);
}
}
;
// 获取投票分析
const
handleGetBillVoteAnalyze
=
async
()
=>
{
const
params
=
{
id
:
window
.
sessionStorage
.
getItem
(
"billId"
)
}
;
try
{
const
res
=
await
getBillTp
(
params
);
console
.
log
(
"投票分析"
,
res
);
}
catch
(
error
)
{
console
.
error
(
"投票分析 error"
,
error
);
}
}
;
onMounted
(
async
()
=>
{
onMounted
(
async
()
=>
{
await
handleGetBillTimeAnalyze
();
await
handleGetBillTimeAnalyze
();
await
handleGetBillAmeAnalyzeCount
();
await
handleGetBillVoteAnalyze
();
let
chart1
=
getBoxPlotChcart
(
chartData1
.
value
,
"天"
);
let
chart1
=
getBoxPlotChcart
(
chartData1
.
value
,
"天"
);
setChart
(
chart1
,
"chart1"
);
setChart
(
chart1
,
"chart1"
);
let
chart2
=
getBoxPlotChcart
(
chartData2
.
value
,
"小时"
);
const
countLabels
=
{
max
:
'最大次数'
,
q3
:
'平均次数大'
,
median
:
'次数中位数'
,
q1
:
'平均次数小'
,
min
:
'最小次数'
,
current
:
'该法案修正案数量'
}
;
let
chart2
=
getBoxPlotChcart
(
chartData2
.
value
,
"次"
,
countLabels
);
setChart
(
chart2
,
"chart2"
);
setChart
(
chart2
,
"chart2"
);
}
);
}
);
<
/script
>
<
/script
>
...
...
src/views/bill/deepDig/processAnalysis/utils/boxplot.js
浏览文件 @
273f345b
const
getBoxPlotChcart
=
(
data
,
unit
)
=>
{
const
getBoxPlotChcart
=
(
data
,
unit
,
labelConfig
=
{})
=>
{
const
labels
=
{
max
:
labelConfig
.
max
||
'最大耗时'
,
q3
:
labelConfig
.
q3
||
'平均耗时大'
,
median
:
labelConfig
.
median
||
'耗时中位数'
,
q1
:
labelConfig
.
q1
||
'平均耗时小'
,
min
:
labelConfig
.
min
||
'最小耗时'
,
current
:
labelConfig
.
current
||
'该法案耗时'
};
let
option
=
{
let
option
=
{
// title: [
// title: [
// {
// {
...
@@ -11,6 +20,22 @@ const getBoxPlotChcart = (data,unit) => {
...
@@ -11,6 +20,22 @@ const getBoxPlotChcart = (data,unit) => {
trigger
:
'item'
,
trigger
:
'item'
,
axisPointer
:
{
axisPointer
:
{
type
:
'shadow'
type
:
'shadow'
},
formatter
:
function
(
params
)
{
if
(
params
.
seriesType
===
'scatter'
)
{
return
`
${
params
.
name
}
<br/>
${
labels
.
current
}
:
${
params
.
data
[
1
]}
${
unit
}
`
;
}
const
{
name
,
data
}
=
params
;
let
tip
=
`
${
name
}
<br/>`
;
tip
+=
`
${
labels
.
max
}
:
${
data
[
5
]}
${
unit
}
<br/>`
;
tip
+=
`
${
labels
.
q3
}
:
${
data
[
4
]}
${
unit
}
<br/>`
;
tip
+=
`
${
labels
.
median
}
:
${
data
[
3
]}
${
unit
}
<br/>`
;
tip
+=
`
${
labels
.
q1
}
:
${
data
[
2
]}
${
unit
}
<br/>`
;
tip
+=
`
${
labels
.
min
}
:
${
data
[
1
]}
${
unit
}
<br/>`
;
if
(
data
[
6
]
!==
undefined
&&
data
[
6
]
!==
null
)
{
tip
+=
`
${
labels
.
current
}
:
${
data
[
6
]}
${
unit
}
`
;
}
return
tip
;
}
}
},
},
grid
:
{
grid
:
{
...
@@ -48,13 +73,20 @@ const getBoxPlotChcart = (data,unit) => {
...
@@ -48,13 +73,20 @@ const getBoxPlotChcart = (data,unit) => {
{
{
name
:
'boxplot'
,
name
:
'boxplot'
,
type
:
'boxplot'
,
type
:
'boxplot'
,
datasetIndex
:
1
,
data
:
data
.
dataY
,
data
:
data
.
dataY
,
},
},
{
{
name
:
'outlier'
,
name
:
labels
.
current
,
type
:
'scatter'
,
type
:
'scatter'
,
datasetIndex
:
2
data
:
data
.
dataY
.
map
((
item
,
index
)
=>
[
index
,
item
[
5
]]),
itemStyle
:
{
color
:
'#ff5722'
},
tooltip
:
{
formatter
:
function
(
params
)
{
return
`
${
params
.
name
}
<br/>
${
labels
.
current
}
:
${
params
.
data
[
1
]}
${
unit
}
`
;
}
}
}
}
]
]
}
}
...
...
src/views/bill/introdoction/STimeline.vue
浏览文件 @
273f345b
<
template
>
<
template
>
<div
class=
"container"
>
<div
class=
"container"
>
<div
class=
"svg-timeline"
>
<div
class=
"svg-timeline"
>
<svg
:
width=
"svgWidth"
:height=
"svgHeight
"
>
<svg
:
viewBox=
"`0 0 $
{svgWidth} ${svgHeight}`" width="100%" height="100%
">
<!--
<line
<!--
<line
:x1=
"lines[0].x1 - 100"
:x1=
"lines[0].x1 - 100"
:y1=
"lines[0].y1"
:y1=
"lines[0].y1"
...
@@ -31,10 +31,11 @@
...
@@ -31,10 +31,11 @@
stroke-width=
"2"
stroke-width=
"2"
/>
-->
/>
-->
<line
<line
:x1=
"lines[0].x1 - 100"
v-if=
"nodes.length > 0"
:y1=
"lines[0].y1"
:x1=
"nodes[0].x - 100"
:x2=
"lines[0].x1"
:y1=
"nodes[0].y"
:y2=
"lines[0].y1"
:x2=
"nodes[0].x"
:y2=
"nodes[0].y"
stroke=
"#e8f2ff"
stroke=
"#e8f2ff"
stroke-width=
"2"
stroke-width=
"2"
marker-end=
"url(#arrow)"
marker-end=
"url(#arrow)"
...
@@ -68,51 +69,60 @@
...
@@ -68,51 +69,60 @@
v-for=
"(node, idx) in nodes.slice(0, nodes.length)"
v-for=
"(node, idx) in nodes.slice(0, nodes.length)"
:key=
"'line' + idx"
:key=
"'line' + idx"
:x1=
"node.x"
:x1=
"node.x"
:y1=
"node.y +
2
"
:y1=
"node.y +
4
"
:x2=
"node.x"
:x2=
"node.x"
:y2=
"node.
dyms ? node.y + 80 : node.y + 50
"
:y2=
"node.
y + verticalLineLength
"
stroke=
"#1677ff"
stroke=
"#1677ff"
stroke-width=
"2
"
:stroke-width=
"verticalLineWidth
"
/>
/>
<
tex
t
<
foreignObjec
t
v-for=
"(node, idx) in nodes"
v-for=
"(node, idx) in nodes"
:key=
"'actionDate' + idx"
:key=
"'fo-' + idx"
:x=
"node.x + 10"
:x=
"node.x + 15"
:y=
"node.y + 30"
:y=
"node.y + 5"
text-anchor=
"start"
:width=
"nodeGapX - 30"
fill=
"#1677ff"
height=
"100"
font-size=
"14"
style=
"overflow: visible;"
font-weight=
"600"
>
>
{{
node
.
actionDate
}}
<div
class=
"node-content"
xmlns=
"http://www.w3.org/1999/xhtml"
>
</text>
<div
class=
"date"
>
{{
node
.
formattedDate
}}
</div>
<div
class=
"title"
>
{{
node
.
actionTitle
}}
</div>
<div
class=
"votes"
v-if=
"node.voteString"
>
{{
node
.
voteString
}}
</div>
</div>
</foreignObject>
<text
<text
v-for=
"(node, idx) in nodes"
v-if=
"startMonth && nodes.length > 0"
:key=
"'actionTitle' + idx"
:x=
"nodes[0].x - 110"
:x=
"node.x + 10"
:y=
"nodes[0].y + 5"
:y=
"node.y + 50"
text-anchor=
"end"
text-anchor=
"start"
fill=
"rgb(5, 95, 194)"
fill=
"#3b414b"
font-size=
"16"
font-size=
"14"
font-weight=
"700"
textLength=
"170"
lengthAdjust=
"spacing"
font-weight=
"bold"
>
>
{{
node
.
actionTitle
.
slice
(
0
,
24
)
}}
{{
startMonth
}}
</text>
</text>
<line
v-if=
"nodes.length > 0"
:x1=
"nodes[nodes.length - 1].x"
:y1=
"nodes[nodes.length - 1].y"
:x2=
"nodes[nodes.length - 1].row % 2 === 0 ? nodes[nodes.length - 1].x + 100 : nodes[nodes.length - 1].x - 100"
:y2=
"nodes[nodes.length - 1].y"
stroke=
"#e8f2ff"
stroke-width=
"2"
marker-end=
"url(#arrow)"
/>
<text
<text
v-for=
"(node, idx) in nodes"
v-if=
"endMonth && nodes.length > 0"
:key=
"'actionTitle' + idx"
:x=
"nodes[nodes.length - 1].row % 2 === 0 ? nodes[nodes.length - 1].x + 110 : nodes[nodes.length - 1].x - 110"
:x=
"node.x + 10"
:y=
"nodes[nodes.length - 1].y + 5"
:y=
"node.y + 70"
:text-anchor=
"nodes[nodes.length - 1].row % 2 === 0 ? 'start' : 'end'"
text-anchor=
"start"
fill=
"rgb(5, 95, 194)"
fill=
"#84888e"
font-size=
"16"
font-size=
"14"
font-weight=
"700"
>
>
{{
node
.
dyms
?
node
.
dyms
:
""
}}
{{
endMonth
}}
</text>
</text>
</svg>
</svg>
</div>
</div>
...
@@ -134,26 +144,55 @@ export default {
...
@@ -134,26 +144,55 @@ export default {
// ],
// ],
maxPerRow
:
5
,
maxPerRow
:
5
,
nodeGapX
:
200
,
nodeGapX
:
200
,
nodeGapY
:
100
nodeGapY
:
180
,
leftMargin
:
150
,
verticalLineLength
:
80
,
verticalLineWidth
:
1
};
};
},
},
computed
:
{
computed
:
{
startMonth
()
{
if
(
this
.
sortedDataList
.
length
===
0
)
return
''
;
const
date
=
new
Date
(
this
.
sortedDataList
[
0
].
actionDate
);
return
`
${
date
.
getFullYear
()}
年
${
date
.
getMonth
()
+
1
}
月`
;
},
endMonth
()
{
if
(
this
.
sortedDataList
.
length
===
0
)
return
''
;
const
date
=
new
Date
(
this
.
sortedDataList
[
this
.
sortedDataList
.
length
-
1
].
actionDate
);
return
`
${
date
.
getFullYear
()}
年
${
date
.
getMonth
()
+
1
}
月`
;
},
sortedDataList
()
{
if
(
!
this
.
dataList
)
return
[];
// Clone and sort by date ascending (Old -> New)
return
[...
this
.
dataList
].
sort
((
a
,
b
)
=>
new
Date
(
a
.
actionDate
)
-
new
Date
(
b
.
actionDate
));
},
nodes
()
{
nodes
()
{
// 计算每个节点的坐标(蛇形)
// 计算每个节点的坐标(蛇形)
return
this
.
d
ataList
.
map
((
item
,
idx
)
=>
{
return
this
.
sortedD
ataList
.
map
((
item
,
idx
)
=>
{
const
row
=
Math
.
floor
(
idx
/
this
.
maxPerRow
);
const
row
=
Math
.
floor
(
idx
/
this
.
maxPerRow
);
const
col
=
idx
%
this
.
maxPerRow
;
const
col
=
idx
%
this
.
maxPerRow
;
let
x
,
y
;
let
x
,
y
;
const
leftMargin
=
1
0
;
// 你可以自定义这个值
// const leftMargin = 15
0; // 你可以自定义这个值
if
(
row
%
2
===
0
)
{
if
(
row
%
2
===
0
)
{
x
=
leftMargin
+
col
*
this
.
nodeGapX
+
50
;
x
=
this
.
leftMargin
+
col
*
this
.
nodeGapX
+
50
;
}
else
{
}
else
{
x
=
leftMargin
+
(
this
.
maxPerRow
-
1
-
col
)
*
this
.
nodeGapX
+
50
;
x
=
this
.
leftMargin
+
(
this
.
maxPerRow
-
1
-
col
)
*
this
.
nodeGapX
+
50
;
}
}
// 节点纵坐标起始值
// 节点纵坐标起始值
y
=
60
+
row
*
this
.
nodeGapY
;
y
=
60
+
row
*
this
.
nodeGapY
;
return
{
...
item
,
x
,
y
,
row
};
// Format Date: 2025-07-04 -> 7月4日
const
dateObj
=
new
Date
(
item
.
actionDate
);
const
formattedDate
=
`
${
dateObj
.
getMonth
()
+
1
}
月
${
dateObj
.
getDate
()}
日`
;
// Format Votes
let
voteString
=
''
;
if
(
item
.
agreeVote
!==
null
&&
item
.
disagreeVote
!==
null
)
{
voteString
=
`
${
item
.
agreeVote
}
票赞成 :
${
item
.
disagreeVote
}
票反对`
;
}
return
{
...
item
,
x
,
y
,
row
,
formattedDate
,
voteString
};
});
});
},
},
lines
()
{
lines
()
{
...
@@ -194,7 +233,7 @@ export default {
...
@@ -194,7 +233,7 @@ export default {
console
.
log
(
"prev"
,
prev
);
console
.
log
(
"prev"
,
prev
);
// 判断是否是行尾转折点
// 判断是否是行尾转折点
const
isTurnPoint
=
i
%
5
===
0
;
const
isTurnPoint
=
i
%
this
.
maxPerRow
===
0
;
if
(
isTurnPoint
)
{
if
(
isTurnPoint
)
{
// 计算半圆路径
// 计算半圆路径
...
@@ -221,7 +260,7 @@ export default {
...
@@ -221,7 +260,7 @@ export default {
return
path
;
return
path
;
},
},
svgWidth
()
{
svgWidth
()
{
return
this
.
maxPerRow
*
this
.
nodeGapX
+
10
0
;
return
this
.
leftMargin
+
this
.
maxPerRow
*
this
.
nodeGapX
+
5
0
;
},
},
svgHeight
()
{
svgHeight
()
{
// SVG高度
// SVG高度
...
@@ -240,7 +279,7 @@ export default {
...
@@ -240,7 +279,7 @@ export default {
align-items
:
center
;
align-items
:
center
;
}
}
.svg-timeline
{
.svg-timeline
{
width
:
100
0px
;
width
:
100
%
;
// background-size: 100% 100%;
// background-size: 100% 100%;
// position: relative;
// position: relative;
// .title {
// .title {
...
@@ -264,5 +303,40 @@ export default {
...
@@ -264,5 +303,40 @@ export default {
// height: 24px;
// height: 24px;
// }
// }
// }
// }
.node-content
{
font-family
:
Microsoft
YaHei
,
sans-serif
;
text-align
:
left
;
padding-left
:
4px
;
.date
{
color
:
rgb
(
5
,
95
,
194
);
font-weight
:
700
;
font-size
:
14px
;
line-height
:
22px
;
margin-bottom
:
0px
;
margin-top
:
6px
;
}
.title
{
color
:
rgb
(
59
,
65
,
75
);
font-weight
:
700
;
font-size
:
14px
;
line-height
:
22px
;
margin-bottom
:
0px
;
white-space
:
nowrap
;
/* Keep text on one line */
overflow
:
hidden
;
/* Hide overflow */
text-overflow
:
ellipsis
;
/* Show ... for overflow */
width
:
100%
;
/* Ensure it takes full width of container */
display
:
block
;
/* Block level for ellipsis to work */
}
.votes
{
color
:
rgb
(
95
,
101
,
108
);
font-size
:
14px
;
font-weight
:
400
;
line-height
:
22px
;
}
}
}
}
</
style
>
</
style
>
src/views/bill/introdoction/index.vue
浏览文件 @
273f345b
...
@@ -31,9 +31,10 @@
...
@@ -31,9 +31,10 @@
<div
class=
"box1-right-item"
>
<div
class=
"box1-right-item"
>
<div
class=
"item-left"
>
相关领域:
</div>
<div
class=
"item-left"
>
相关领域:
</div>
<div
class=
"item-right1"
>
<div
class=
"item-right1"
>
<div
class=
"right1-item"
>
跨境电商
</div>
<
!--
<
div
class=
"right1-item"
>
跨境电商
</div>
<div
class=
"right1-item"
>
新能源产业
</div>
<div
class=
"right1-item"
>
新能源产业
</div>
<div
class=
"right1-item"
>
半导体产业
</div>
<div
class=
"right1-item"
>
半导体产业
</div>
-->
<div
class=
"right1-item"
v-for=
"item in basicInfo.hylyList"
:key=
"item"
>
{{
item
}}
</div>
</div>
</div>
</div>
</div>
<div
class=
"box1-right-item"
>
<div
class=
"box1-right-item"
>
...
@@ -81,7 +82,7 @@
...
@@ -81,7 +82,7 @@
<
div
class
=
"box-header"
>
<
div
class
=
"box-header"
>
<
div
class
=
"header-left"
><
/div
>
<
div
class
=
"header-left"
><
/div
>
<
div
class
=
"title"
>
法案进展
<
/div
>
<
div
class
=
"title"
>
法案进展
<
/div
>
<
div
class
=
"header-btn-box"
>
<
!--
<
div
class
=
"header-btn-box"
>
<
div
class
=
"btn"
@
click
=
"handleClcikBox2Btn(1)"
>
<
div
class
=
"btn"
@
click
=
"handleClcikBox2Btn(1)"
>
<
el
-
badge
:
value
=
"warningNum"
>
<
el
-
badge
:
value
=
"warningNum"
>
<
el
-
button
type
=
"primary"
plain
v
-
if
=
"box2BtnActive === 1"
>
最新进展
<
/el-button
>
<
el
-
button
type
=
"primary"
plain
v
-
if
=
"box2BtnActive === 1"
>
最新进展
<
/el-button
>
...
@@ -92,7 +93,7 @@
...
@@ -92,7 +93,7 @@
<
el
-
button
type
=
"primary"
plain
v
-
if
=
"box2BtnActive === 2"
>
前期进展
<
/el-button
>
<
el
-
button
type
=
"primary"
plain
v
-
if
=
"box2BtnActive === 2"
>
前期进展
<
/el-button
>
<
el
-
button
type
=
"info"
plain
v
-
else
>
前期进展
<
/el-button
>
<
el
-
button
type
=
"info"
plain
v
-
else
>
前期进展
<
/el-button
>
<
/div
>
<
/div
>
<
/div
>
<
/div>
--
>
<
div
class
=
"header-right"
>
<
div
class
=
"header-right"
>
<
div
class
=
"icon"
>
<
div
class
=
"icon"
>
<
img
src
=
"@/assets/icons/box-header-icon2.png"
alt
=
""
/>
<
img
src
=
"@/assets/icons/box-header-icon2.png"
alt
=
""
/>
...
@@ -104,8 +105,8 @@
...
@@ -104,8 +105,8 @@
<
/div
>
<
/div
>
<
div
class
=
"box2-main"
>
<
div
class
=
"box2-main"
>
<
div
class
=
"box2-main-center"
>
<
div
class
=
"box2-main-center"
>
<
STimeline
v
-
if
=
"box2BtnActive == 2"
:
dataList
=
"timelineData"
/>
<
STimeline
:
dataList
=
"timelineData"
/>
<
div
class
=
"box2-center-item-box"
v
-
if
=
"box2BtnActive == 1"
>
<
!--
<
div
class
=
"box2-center-item-box"
v
-
if
=
"box2BtnActive == 1"
>
<
div
class
=
"box2-center-item"
v
-
for
=
"(item, index) in progressList"
:
key
=
"index"
>
<
div
class
=
"box2-center-item"
v
-
for
=
"(item, index) in progressList"
:
key
=
"index"
>
<
div
class
=
"tip"
:
class
=
"{ tipActive: item.fxdj
}
"
><
/div
>
<
div
class
=
"tip"
:
class
=
"{ tipActive: item.fxdj
}
"
><
/div
>
<
div
class
=
"date"
>
{{
item
.
actionDate
}}
<
/div
>
<
div
class
=
"date"
>
{{
item
.
actionDate
}}
<
/div
>
...
@@ -128,7 +129,7 @@
...
@@ -128,7 +129,7 @@
<
el
-
icon
size
=
"22"
color
=
"#777"
><
ArrowRightBold
/><
/el-icon
>
<
el
-
icon
size
=
"22"
color
=
"#777"
><
ArrowRightBold
/><
/el-icon
>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
/div>
--
>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
div
class
=
"box2-footer"
>
<
div
class
=
"box2-footer"
>
...
@@ -210,15 +211,15 @@
...
@@ -210,15 +211,15 @@
<
div
<
div
class
=
"tag-box"
class
=
"tag-box"
:
class
=
"{
:
class
=
"{
status0:
tag.status === 0
,
status0:
index === 0 || index === 4
,
status1:
tag.status === 1
,
status1:
index === 1 || index === 5
,
status2:
tag.status === 2
,
status2:
index === 2 || index === 6
,
status3:
tag.status === 3
status3:
index === 3 || index === 7
}
"
}
"
v
-
for
=
"(tag, index) in tagList"
v
-
for
=
"(tag, index) in
curPerson.
tagList"
:
key
=
"index"
:
key
=
"index"
>
>
{{
tag
.
title
}}
{{
tag
}}
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
div
class
=
"right-main-box3"
>
<
div
class
=
"right-main-box3"
>
...
@@ -231,13 +232,13 @@
...
@@ -231,13 +232,13 @@
<
div
class
=
"right-main-box3-main"
>
<
div
class
=
"right-main-box3-main"
>
<
el
-
timeline
style
=
"max-width: 500px"
>
<
el
-
timeline
style
=
"max-width: 500px"
>
<
el
-
timeline
-
item
<
el
-
timeline
-
item
:
timestamp
=
"item.
sjsj
"
:
timestamp
=
"item.
newsDate
"
placement
=
"top"
placement
=
"top"
v
-
for
=
"(item, index) in
personEvent
List"
v
-
for
=
"(item, index) in
curPerson.news
List"
:
key
=
"index"
:
key
=
"index"
>
>
<
div
class
=
"timeline-content"
>
<
div
class
=
"timeline-content"
>
{{
item
.
sjnr
}}
{{
item
.
newsContent
}}
<
/div
>
<
/div
>
<
/el-timeline-item
>
<
/el-timeline-item
>
<!--
<
el
-
timeline
-
item
timestamp
=
"2018/4/3"
placement
=
"top"
>
<!--
<
el
-
timeline
-
item
timestamp
=
"2018/4/3"
placement
=
"top"
>
...
@@ -324,14 +325,14 @@
...
@@ -324,14 +325,14 @@
<
div
class
=
"inner-right-main"
>
<
div
class
=
"inner-right-main"
>
<
el
-
timeline
style
=
"max-width: 840px"
>
<
el
-
timeline
style
=
"max-width: 840px"
>
<
el
-
timeline
-
item
<
el
-
timeline
-
item
:
timestamp
=
"item.
sjsj
"
:
timestamp
=
"item.
newsDate
"
placement
=
"top"
placement
=
"top"
v
-
for
=
"(item, index) in
personEvent
List"
v
-
for
=
"(item, index) in
curPerson.news
List"
:
key
=
"index"
:
key
=
"index"
>
>
<
div
class
=
"timeline-content1"
>
<
div
class
=
"timeline-content1"
>
<
div
class
=
"text"
>
<
div
class
=
"text"
>
{{
item
.
sjnr
}}
{{
item
.
newsContent
}}
<
/div
>
<
/div
>
<
div
class
=
"pic"
>
<
div
class
=
"pic"
>
<
img
src
=
"./assets/imgs/img1.png"
alt
=
""
/>
<
img
src
=
"./assets/imgs/img1.png"
alt
=
""
/>
...
@@ -544,6 +545,7 @@ const handleGetBasicInfo = async () => {
...
@@ -544,6 +545,7 @@ const handleGetBasicInfo = async () => {
const
res
=
await
getBillInfo
(
params
);
const
res
=
await
getBillInfo
(
params
);
console
.
log
(
"基本信息"
,
res
);
console
.
log
(
"基本信息"
,
res
);
basicInfo
.
value
=
res
.
data
basicInfo
.
value
=
res
.
data
basicInfo
.
value
.
stageList
.
reverse
()
}
catch
(
error
)
{
}
catch
(
error
)
{
console
.
error
(
error
);
console
.
error
(
error
);
}
}
...
@@ -552,24 +554,24 @@ const handleGetBasicInfo = async () => {
...
@@ -552,24 +554,24 @@ const handleGetBasicInfo = async () => {
const
warningNum
=
ref
(
0
);
const
warningNum
=
ref
(
0
);
// 法案进展 获取最新进展
// 法案进展 获取最新进展
const
handleGetBillEvent
=
async
()
=>
{
//
const handleGetBillEvent = async () =>
{
warningNum
.
value
=
0
;
//
warningNum.value = 0;
const
params
=
{
//
const params =
{
id
:
window
.
sessionStorage
.
getItem
(
"billId"
)
//
id: window.sessionStorage.getItem("billId")
}
;
//
}
;
try
{
//
try
{
const
res
=
await
getBillEvent
(
params
);
//
const res = await getBillEvent(params);
console
.
log
(
"最新进展"
,
res
);
//
console.log("最新进展", res);
progressList
.
value
=
res
.
data
;
//
progressList.value = res.data;
progressList
.
value
.
forEach
(
item
=>
{
//
progressList.value.forEach(item =>
{
if
(
item
.
fxdj
)
{
//
if (item.fxdj)
{
warningNum
.
value
++
;
//
warningNum.value++;
}
//
}
}
);
//
}
);
}
catch
(
error
)
{
//
}
catch
(
error
)
{
console
.
error
(
error
);
//
console.error(error);
}
//
}
}
;
//
}
;
// 法案进展 获取前期进展 --也是提出人左上角列表
// 法案进展 获取前期进展 --也是提出人左上角列表
const
handleGetBillDyqk
=
async
()
=>
{
const
handleGetBillDyqk
=
async
()
=>
{
...
@@ -601,9 +603,26 @@ const curPerson = ref({});
...
@@ -601,9 +603,26 @@ const curPerson = ref({});
const
personEventList
=
ref
([]);
const
personEventList
=
ref
([]);
// 提出人 --动议id
// 提出人 --动议id
const
handleGetBillPerson
=
async
id
=>
{
// const handleGetBillPerson = async id =>
{
// const params =
{
// id: id
//
}
;
// try
{
// const res = await getBillPerson(params);
// console.log("提出人", res);
// personList.value = res.data;
// box3BtnActive.value = res.data.length ? res.data[0].name : "";
// curPerson.value = res.data.length ? res.data[0] :
{
}
;
// personEventList.value = res.data.length ? res.data[0].eventList : [];
//
}
catch
(
error
)
{
// console.error(error);
//
}
//
}
;
// 法案提出人
const
handleGetBillPerson
=
async
()
=>
{
const
params
=
{
const
params
=
{
id
:
id
billId
:
window
.
sessionStorage
.
getItem
(
"billId"
)
}
;
}
;
try
{
try
{
const
res
=
await
getBillPerson
(
params
);
const
res
=
await
getBillPerson
(
params
);
...
@@ -619,8 +638,9 @@ const handleGetBillPerson = async id => {
...
@@ -619,8 +638,9 @@ const handleGetBillPerson = async id => {
onMounted
(()
=>
{
onMounted
(()
=>
{
handleGetBasicInfo
();
handleGetBasicInfo
();
handleGetBillEvent
();
//
handleGetBillEvent();
handleGetBillDyqk
();
handleGetBillDyqk
();
handleGetBillPerson
();
}
);
}
);
<
/script
>
<
/script
>
...
@@ -695,11 +715,11 @@ onMounted(() => {
...
@@ -695,11 +715,11 @@ onMounted(() => {
.
box1
-
right
{
.
box1
-
right
{
margin
-
left
:
31
px
;
margin
-
left
:
31
px
;
margin
-
top
:
5
px
;
margin
-
top
:
5
px
;
width
:
623
px
;
//
width: 623px;
height
:
350
px
;
height
:
350
px
;
.
box1
-
right
-
item
{
.
box1
-
right
-
item
{
display
:
flex
;
display
:
flex
;
margin
-
bottom
:
2
4
px
;
margin
-
bottom
:
2
1
px
;
.
item
-
left
{
.
item
-
left
{
width
:
100
px
;
width
:
100
px
;
height
:
14
px
;
height
:
14
px
;
...
@@ -722,7 +742,23 @@ onMounted(() => {
...
@@ -722,7 +742,23 @@ onMounted(() => {
}
}
.
item
-
right1
{
.
item
-
right1
{
display
:
flex
;
display
:
flex
;
align
-
items
:
center
;
width
:
700
px
;
height
:
40
px
;
overflow
-
x
:
auto
;
overflow
-
y
:
hidden
;
&
::
-
webkit
-
scrollbar
{
height
:
4
px
;
}
&
::
-
webkit
-
scrollbar
-
thumb
{
border
-
radius
:
4
px
;
background
:
#
e1e1e1
;
}
&
::
-
webkit
-
scrollbar
-
track
{
background
:
transparent
;
}
.
right1
-
item
{
.
right1
-
item
{
flex
-
shrink
:
0
;
margin
-
right
:
10
px
;
margin
-
right
:
10
px
;
padding
:
1
px
8
px
;
padding
:
1
px
8
px
;
box
-
sizing
:
border
-
box
;
box
-
sizing
:
border
-
box
;
...
@@ -774,10 +810,14 @@ onMounted(() => {
...
@@ -774,10 +810,14 @@ onMounted(() => {
text
-
align
:
center
;
text
-
align
:
center
;
position
:
relative
;
position
:
relative
;
.
step
-
box
{
.
step
-
box
{
padding
:
0
10
px
0
2
0
px
;
padding
:
4
px
1
0
px
;
color
:
#
333
;
color
:
#
333
;
position
:
relative
;
position
:
relative
;
font
-
size
:
14
px
;
font
-
weight
:
400
;
font
-
family
:
"Microsoft YaHei"
;
line
-
height
:
14
px
;
margin
-
left
:
10
px
;
.
right
-
arrow
{
.
right
-
arrow
{
position
:
absolute
;
position
:
absolute
;
right
:
-
21
px
;
right
:
-
21
px
;
...
@@ -792,7 +832,7 @@ onMounted(() => {
...
@@ -792,7 +832,7 @@ onMounted(() => {
}
}
}
}
.
step
-
box
-
active
{
.
step
-
box
-
active
{
padding
:
0
12
px
;
padding
:
4
10
px
;
color
:
#
fff
;
color
:
#
fff
;
background
:
#
ce4f51
;
background
:
#
ce4f51
;
position
:
relative
;
position
:
relative
;
...
@@ -851,11 +891,13 @@ onMounted(() => {
...
@@ -851,11 +891,13 @@ onMounted(() => {
box
-
shadow
:
0
px
0
px
15
px
0
px
rgba
(
22
,
119
,
255
,
0.1
);
box
-
shadow
:
0
px
0
px
15
px
0
px
rgba
(
22
,
119
,
255
,
0.1
);
.
box2
-
main
{
.
box2
-
main
{
margin
-
top
:
10
px
;
margin
-
top
:
10
px
;
height
:
calc
(
100
%
-
70
px
);
// Subtract header height
width
:
100
%
;
.
box2
-
main
-
center
{
.
box2
-
main
-
center
{
margin
-
left
:
23
px
;
margin
-
left
:
23
px
;
border
-
top
:
1
px
solid
rgba
(
243
,
243
,
244
,
1
);
border
-
top
:
1
px
solid
rgba
(
243
,
243
,
244
,
1
);
// width: 100%;
width
:
calc
(
100
%
-
46
px
);
// Subtract margin
height
:
300
px
;
height
:
100
%
;
// background: orange;
// background: orange;
.
box2
-
center
-
item
{
.
box2
-
center
-
item
{
display
:
flex
;
display
:
flex
;
...
@@ -1082,10 +1124,10 @@ onMounted(() => {
...
@@ -1082,10 +1124,10 @@ onMounted(() => {
}
}
}
}
.
right
-
main
-
box2
{
.
right
-
main
-
box2
{
width
:
576
px
;
//
width: 576px;
height
:
150
px
;
//
height: 150px;
box
-
sizing
:
border
-
box
;
box
-
sizing
:
border
-
box
;
padding
:
10
px
26
px
;
padding
:
22
px
26
px
;
// border-bottom: 1px solid rgb(243, 243, 244);
// border-bottom: 1px solid rgb(243, 243, 244);
// display: flex;
// display: flex;
// flex-wrap: wrap;
// flex-wrap: wrap;
...
@@ -1140,7 +1182,7 @@ onMounted(() => {
...
@@ -1140,7 +1182,7 @@ onMounted(() => {
}
}
.
right
-
main
-
box3
-
main
{
.
right
-
main
-
box3
-
main
{
margin
-
top
:
18
px
;
margin
-
top
:
18
px
;
height
:
299
px
;
height
:
412
px
;
overflow
-
y
:
auto
;
overflow
-
y
:
auto
;
}
}
.
right
-
main
-
box3
-
footer
{
.
right
-
main
-
box3
-
footer
{
...
@@ -1330,6 +1372,10 @@ onMounted(() => {
...
@@ -1330,6 +1372,10 @@ onMounted(() => {
color
:
var
(
--
btn
-
active
-
text
-
color
);
color
:
var
(
--
btn
-
active
-
text
-
color
);
}
}
}
}
.
inner
-
right
-
main
{
height
:
860
px
;
overflow
:
auto
;
}
}
}
}
}
}
}
...
...
src/views/bill/template/index.vue
浏览文件 @
273f345b
...
@@ -16,9 +16,15 @@
...
@@ -16,9 +16,15 @@
</div>
</div>
<div
class=
"left-top"
>
<div
class=
"left-top"
>
<el-select
v-model=
"curBill"
placeholder=
"请选择"
style=
"width: 240px"
@
change=
"handleChangeBill"
>
<el-select
v-model=
"curBill"
placeholder=
"请选择"
style=
"width: 240px"
@
change=
"handleChangeBill"
>
<el-option
v-for=
"item in billList"
:key=
"item.
value"
:label=
"item.label"
:value=
"item.id
"
/>
<el-option
v-for=
"item in billList"
:key=
"item.
id"
:label=
"item.label"
:value=
"item.value
"
/>
</el-select>
</el-select>
<el-checkbox
style=
"margin-left: 30px"
v-model=
"checkedValue"
label=
"只看涉华条款"
size=
"large"
/>
<el-checkbox
style=
"margin-left: 30px"
v-model=
"checkedValue"
label=
"只看涉华条款"
size=
"large"
@
change=
"handleChangeCheckbox"
/>
<div
class=
"search"
style=
"width: 240px; margin-left: 475px"
>
<div
class=
"search"
style=
"width: 240px; margin-left: 475px"
>
<el-input
v-model=
"searchValue"
style=
"width: 240px"
placeholder=
"搜索条款"
/>
<el-input
v-model=
"searchValue"
style=
"width: 240px"
placeholder=
"搜索条款"
/>
<div
class=
"icon"
>
<div
class=
"icon"
>
...
@@ -28,32 +34,32 @@
...
@@ -28,32 +34,32 @@
</div>
</div>
<div
class=
"left-main"
>
<div
class=
"left-main"
>
<div
class=
"left-main-item"
v-for=
"(term, index) in mainTermsList"
:key=
"index"
>
<div
class=
"left-main-item"
v-for=
"(term, index) in mainTermsList"
:key=
"index"
>
<div
class=
"id"
>
{{
index
+
1
}}
</div>
<div
class=
"id"
>
{{
(
currentPage
-
1
)
*
pageSize
+
index
+
1
}}
</div>
<div
class=
"info"
>
<div
class=
"info"
>
<div
class=
"title"
>
<div
class=
"title"
>
<span
class=
"title-active"
>
{{
term
.
header
}}
</span>
<span
class=
"title-active"
>
第
{{
term
.
tkxh
}}
条.
</span>
{{
term
.
title
}}
{{
term
.
fynr
}}
</div>
</div>
<div
class=
"content"
>
<div
class=
"content"
>
<span
class=
"content-active"
>
{{
term
.
headerEn
}}
</span>
<span
class=
"content-active"
>
Sec.
{{
term
.
tkxh
}}
</span>
{{
term
.
content
}}
{{
term
.
ywnr
}}
</div>
</div>
</div>
</div>
<div
class=
"tags-box"
>
<div
class=
"tags-box"
>
<div
<div
class=
"tag"
class=
"tag"
v-for=
"(val, idx) in
term.tags
"
v-for=
"(val, idx) in
(term.hylyList || []).slice(0, 2)
"
:key=
"idx"
:key=
"idx"
:class=
"
{
:class=
"
{
tag1: val.status === 1
,
'tag1': val === '人工智能'
,
tag2: val.status === 2
,
'tag2': val === '新一代信息技术' || !['人工智能', '政治', '经济', '军事', '科技'].includes(val)
,
tag3: val.status === 3
,
'tag3': val === '政治'
,
tag4: val.status === 4
,
'tag4': val === '经济'
,
tag5: val.status === 5
,
'tag5': val === '军事'
,
tag6: val.status === 6
'tag6': val === '科技'
}"
}"
>
>
{{
val
.
name
}}
{{
val
}}
</div>
</div>
</div>
</div>
<div
class=
"open"
>
<div
class=
"open"
>
...
@@ -63,10 +69,17 @@
...
@@ -63,10 +69,17 @@
</div>
</div>
<div
class=
"left-footer"
>
<div
class=
"left-footer"
>
<div
class=
"left-footer-text"
>
<div
class=
"left-footer-text"
>
{{
"共96条涉华条款"
}}
{{
`共${total
}
条${checkedValue ? "涉华" : ""
}
条款`
}}
<
/div
>
<
/div
>
<
div
class
=
"left-footer-right"
>
<
div
class
=
"left-footer-right"
>
<el-pagination
background
layout=
"prev, pager, next"
:total=
"96"
/>
<
el
-
pagination
background
layout
=
"prev, pager, next"
:
total
=
"total"
v
-
model
:
current
-
page
=
"currentPage"
v
-
model
:
page
-
size
=
"pageSize"
@
current
-
change
=
"handleCurrentChange"
/>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
...
@@ -137,16 +150,12 @@ import { getBillContentId, getBillContentTk, getBillContentXzfs, getBillHyly } f
...
@@ -137,16 +150,12 @@ import { getBillContentId, getBillContentTk, getBillContentXzfs, getBillHyly } f
const
curBill
=
ref
(
""
);
const
curBill
=
ref
(
""
);
const
curBillId
=
ref
(
null
);
const
curBillId
=
ref
(
null
);
const
billList
=
ref
([
const
checkedValue
=
ref
(
false
);
{
const
searchValue
=
ref
(
""
);
value
:
"公法(2025年7月4日)"
,
const
billList
=
ref
([]);
label
:
"公法(2025年7月4日)"
const
currentPage
=
ref
(
1
);
},
const
pageSize
=
ref
(
10
);
{
const
total
=
ref
(
0
);
value
:
"公法(2025年7月8日)"
,
label
:
"公法(2025年7月8日)"
}
]);
const
mainTermsList
=
ref
([
const
mainTermsList
=
ref
([
{
{
...
@@ -351,7 +360,13 @@ const setChart = (option, chartId) => {
...
@@ -351,7 +360,13 @@ const setChart = (option, chartId) => {
// 切换原文
// 切换原文
const
handleChangeBill
=
val
=>
{
const
handleChangeBill
=
val
=>
{
curBillId
.
value
=
val
;
curBill
.
value
=
val
;
const
item
=
billList
.
value
.
find
(
item
=>
item
.
value
===
val
);
if
(
item
)
{
curBillId
.
value
=
item
.
id
;
currentPage
.
value
=
1
;
handleGetBillContentTk
(
checkedValue
.
value
?
"Y"
:
"N"
);
}
}
;
}
;
// 获取法案id列表
// 获取法案id列表
...
@@ -369,22 +384,69 @@ const handleGetBillList = async () => {
...
@@ -369,22 +384,69 @@ const handleGetBillList = async () => {
id
:
item
.
ywid
id
:
item
.
ywid
}
;
}
;
}
);
}
);
curBill
.
value
=
billList
.
value
[
0
].
label
;
if
(
billList
.
value
.
length
>
0
)
{
curBill
.
value
=
billList
.
value
[
0
].
value
;
curBillId
.
value
=
billList
.
value
[
0
].
id
;
curBillId
.
value
=
billList
.
value
[
0
].
id
;
}
}
catch
(
error
)
{
}
}
catch
(
error
)
{
}
}
;
}
;
const
handleChangeCheckbox
=
val
=>
{
currentPage
.
value
=
1
;
handleGetBillContentTk
(
val
?
"Y"
:
"N"
);
}
;
const
handleCurrentChange
=
val
=>
{
currentPage
.
value
=
val
;
handleGetBillContentTk
(
checkedValue
.
value
?
"Y"
:
"N"
);
}
;
// 根据原文ID获取条款列表
// 根据原文ID获取条款列表
const
handleGetBillContentTk
=
async
cRelated
=>
{
const
handleGetBillContentTk
=
async
cRelated
=>
{
const
params
=
{
const
params
=
{
id
:
curBillId
.
value
,
billid
:
window
.
sessionStorage
.
getItem
(
"billId"
),
id
:
curBill
.
value
,
cRelated
:
cRelated
,
cRelated
:
cRelated
,
currentPage
:
0
,
currentPage
:
currentPage
.
value
-
1
,
pageSize
:
10
pageSize
:
pageSize
.
value
}
;
}
;
try
{
try
{
const
res
=
await
getBillContentTk
(
params
);
const
res
=
await
getBillContentTk
(
params
);
console
.
log
(
"条款内容"
,
res
);
console
.
log
(
"条款内容"
,
res
);
mainTermsList
.
value
=
res
.
data
.
content
.
map
(
item
=>
{
// 处理 fynr
if
(
item
.
fynr
)
{
const
matchComplex
=
item
.
fynr
.
match
(
/^
(?:
正文内容
[
::
]\s
*
)?[
“"
]?\s
*第
\s
*
([
0-9a-zA-Z
]
+
)\s
*
[
条节
][
::
\.\。]?[
”"
]?\s
*/
);
if
(
matchComplex
)
{
// 匹配 "第xxx条"、"正文内容:第xxx条"、"“第xxx条" 等
if
(
!
item
.
tkxh
)
{
item
.
tkxh
=
matchComplex
[
1
];
}
item
.
fynr
=
item
.
fynr
.
replace
(
matchComplex
[
0
],
""
);
}
else
{
// 匹配 "xxx."
item
.
fynr
=
item
.
fynr
.
replace
(
/^
\d
+
\.\s
*/
,
""
);
}
}
// 处理 ywnr
if
(
item
.
ywnr
)
{
const
matchSec
=
item
.
ywnr
.
match
(
/^
(?:
SEC
\.
|SECTION
)\s
*
([
0-9a-zA-Z
]
+
)[\.
:
]?\s
*/i
);
if
(
matchSec
)
{
if
(
!
item
.
tkxh
)
{
item
.
tkxh
=
matchSec
[
1
];
}
item
.
ywnr
=
item
.
ywnr
.
replace
(
matchSec
[
0
],
""
);
}
else
{
item
.
ywnr
=
item
.
ywnr
.
replace
(
/^
\d
+
\.\s
*/
,
""
);
}
}
// 处理 tkxh 末尾的点
if
(
item
.
tkxh
)
{
item
.
tkxh
=
item
.
tkxh
.
replace
(
/
\.
$/
,
""
);
}
return
item
;
}
);
total
.
value
=
res
.
data
.
totalElements
;
}
catch
(
error
)
{
}
}
catch
(
error
)
{
}
}
;
}
;
...
@@ -430,7 +492,7 @@ const handleGetBillHyly = async () => {
...
@@ -430,7 +492,7 @@ const handleGetBillHyly = async () => {
onMounted
(
async
()
=>
{
onMounted
(
async
()
=>
{
await
handleGetBillList
();
await
handleGetBillList
();
handleGetBillContentTk
(
false
);
handleGetBillContentTk
(
"N"
);
await
handleGetBillContentXzfs
();
await
handleGetBillContentXzfs
();
await
handleGetBillHyly
();
await
handleGetBillHyly
();
let
chart1
=
getPieChart
(
chart1Data
.
value
,
chart1ColorList
.
value
);
let
chart1
=
getPieChart
(
chart1Data
.
value
,
chart1ColorList
.
value
);
...
@@ -528,6 +590,7 @@ onMounted(async () => {
...
@@ -528,6 +590,7 @@ onMounted(async () => {
border
-
radius
:
2
px
;
border
-
radius
:
2
px
;
background
:
rgba
(
255
,
255
,
255
,
1
);
background
:
rgba
(
255
,
255
,
255
,
1
);
display
:
flex
;
display
:
flex
;
position
:
relative
;
.
id
{
.
id
{
margin
-
top
:
20
px
;
margin
-
top
:
20
px
;
margin
-
left
:
15
px
;
margin
-
left
:
15
px
;
...
@@ -543,7 +606,7 @@ onMounted(async () => {
...
@@ -543,7 +606,7 @@ onMounted(async () => {
.
info
{
.
info
{
margin
-
left
:
13
px
;
margin
-
left
:
13
px
;
margin
-
top
:
15
px
;
margin
-
top
:
15
px
;
width
:
813
px
;
width
:
780
px
;
.
title
{
.
title
{
height
:
14
px
;
height
:
14
px
;
color
:
rgba
(
59
,
65
,
75
,
1
);
color
:
rgba
(
59
,
65
,
75
,
1
);
...
@@ -577,20 +640,19 @@ onMounted(async () => {
...
@@ -577,20 +640,19 @@ onMounted(async () => {
}
}
}
}
.
tags
-
box
{
.
tags
-
box
{
margin-left
:
20px
;
margin-top
:
21px
;
width
:
160px
;
height
:
22px
;
display
:
flex
;
display
:
flex
;
justify-content
:
flex-end
;
justify
-
content
:
right
;
align
-
items
:
center
;
flex
:
1
;
margin
-
right
:
50
px
;
.
tag
{
.
tag
{
height
:
18px
;
text
-
align
:
right
;
line
-
height
:
18
px
;
line
-
height
:
18
px
;
padding
:
0
8px
;
padding
:
1
px
8
px
;
border
-
radius
:
4
px
;
border
-
radius
:
4
px
;
margin
-
left
:
5
px
;
margin
-
left
:
5
px
;
font
-
size
:
12
px
;
font
-
size
:
12
px
;
font-family
:
Microsoft
YaHei
;
font
-
family
:
"Microsoft YaHei"
;
font
-
size
:
14
px
;
font
-
size
:
14
px
;
font
-
weight
:
400
;
font
-
weight
:
400
;
}
}
...
@@ -626,8 +688,9 @@ onMounted(async () => {
...
@@ -626,8 +688,9 @@ onMounted(async () => {
}
}
}
}
.
open
{
.
open
{
margin-left
:
10px
;
position
:
absolute
;
margin-top
:
22px
;
top
:
22
px
;
right
:
23
px
;
width
:
20
px
;
width
:
20
px
;
height
:
20
px
;
height
:
20
px
;
img
{
img
{
...
...
src/views/bill/template/utils/piechart.js
浏览文件 @
273f345b
...
@@ -4,6 +4,7 @@ const getPieChart = (data,colorList) => {
...
@@ -4,6 +4,7 @@ const getPieChart = (data,colorList) => {
series
:
[
series
:
[
{
{
type
:
'pie'
,
type
:
'pie'
,
minAngle
:
28
,
radius
:
[
70
,
100
],
radius
:
[
70
,
100
],
height
:
'100%'
,
height
:
'100%'
,
left
:
'center'
,
left
:
'center'
,
...
@@ -38,7 +39,9 @@ const getPieChart = (data,colorList) => {
...
@@ -38,7 +39,9 @@ const getPieChart = (data,colorList) => {
?
params
.
labelRect
.
x
?
params
.
labelRect
.
x
:
params
.
labelRect
.
x
+
params
.
labelRect
.
width
;
:
params
.
labelRect
.
x
+
params
.
labelRect
.
width
;
return
{
return
{
labelLinePoints
:
points
labelLinePoints
:
points
,
hideOverlap
:
false
,
moveOverlap
:
'shiftY'
};
};
},
},
data
:
data
data
:
data
...
...
src/views/exportControl/analysis/components/fishbone-back.vue
浏览文件 @
273f345b
差异被折叠。
点击展开。
src/views/exportControl/analysis/components/fishbone-mock.json
浏览文件 @
273f345b
差异被折叠。
点击展开。
src/views/exportControl/analysis/components/fishbone.vue
浏览文件 @
273f345b
差异被折叠。
点击展开。
src/views/exportControl/analysis/components/influencePanel2.vue
浏览文件 @
273f345b
...
@@ -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
.
map
(
item
=>
({
id
:
item
.
id
,
id
:
item
.
id
,
text
:
item
.
name
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
浏览文件 @
273f345b
...
@@ -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
浏览文件 @
273f345b
...
@@ -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
);
if
(
entitiesUpdateCountData
&&
Array
.
isArray
(
entitiesUpdateCountData
))
{
const
sortedData
=
_
.
sortBy
(
entitiesUpdateCountData
,
"year"
);
// 提取 x 轴数据(年份)
const
xAxisData
=
sortedData
.
map
(
item
=>
item
.
year
.
toString
());
// 提取 y 轴数据(数量)
const
seriesData
=
sortedData
.
map
(
item
=>
item
.
count
);
bar2Option
.
value
=
getBarChart
(
xAxisData
,
seriesData
,
[
"rgba(22, 119, 255, 1)"
,
"rgba(22, 119, 255, 0)"
],
"更新频率"
);
}
else
{
// 保持原有逻辑以防数据格式不符合预期
bar2Option
.
value
=
getBarChart
(
bar2Option
.
value
=
getBarChart
(
_
.
reverse
(
entitiesUpdateCountData
.
xAxis
),
_
.
reverse
(
entitiesUpdateCountData
.
xAxis
),
_
.
reverse
(
entitiesUpdateCountData
.
series
),
_
.
reverse
(
entitiesUpdateCountData
.
series
),
[
"rgba(22, 119, 255, 1)"
,
"rgba(22, 119, 255, 0)"
],
[
"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
浏览文件 @
273f345b
...
@@ -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
浏览文件 @
273f345b
...
@@ -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
浏览文件 @
273f345b
...
@@ -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
浏览文件 @
273f345b
...
@@ -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
浏览文件 @
273f345b
...
@@ -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
浏览文件 @
273f345b
差异被折叠。
点击展开。
src/views/exportControl/utils/charts.js
浏览文件 @
273f345b
差异被折叠。
点击展开。
src/views/gjOverView/assets/bg.png
0 → 100644
浏览文件 @
273f345b
差异被折叠。
点击展开。
src/views/gjOverView/assets/icon1.png
0 → 100644
浏览文件 @
273f345b
差异被折叠。
点击展开。
src/views/gjOverView/component/MeansAnalysis.vue
浏览文件 @
273f345b
差异被折叠。
点击展开。
src/views/gjOverView/component/ResourceAnalysis.vue
浏览文件 @
273f345b
差异被折叠。
点击展开。
src/views/gjOverView/component/Timeline.vue
浏览文件 @
273f345b
差异被折叠。
点击展开。
src/views/gjOverView/index.vue
浏览文件 @
273f345b
差异被折叠。
点击展开。
src/views/gjOverView/js/barChart2.js
浏览文件 @
273f345b
差异被折叠。
点击展开。
src/views/gjOverView/js/multiLineChart2.js
浏览文件 @
273f345b
差异被折叠。
点击展开。
src/views/gjOverView/js/radarChart2.js
浏览文件 @
273f345b
差异被折叠。
点击展开。
src/views/technologyFigures/assets/images/TechnologyFigures-icon1.png
0 → 100644
浏览文件 @
273f345b
差异被折叠。
点击展开。
src/views/technologyFigures/assets/images/TechnologyFigures-icon2.png
0 → 100644
浏览文件 @
273f345b
差异被折叠。
点击展开。
src/views/technologyFigures/assets/images/TechnologyFigures-icon3.png
0 → 100644
浏览文件 @
273f345b
差异被折叠。
点击展开。
src/views/technologyFigures/assets/images/TechnologyFigures-icon4.png
0 → 100644
浏览文件 @
273f345b
差异被折叠。
点击展开。
src/views/technologyFigures/component/SourceLibrary.vue
浏览文件 @
273f345b
差异被折叠。
点击展开。
src/views/technologyFigures/index.vue
浏览文件 @
273f345b
差异被折叠。
点击展开。
src/views/technologyFigures/json/source.json
浏览文件 @
273f345b
差异被折叠。
点击展开。
出口管制接口.md
0 → 100644
浏览文件 @
273f345b
差异被折叠。
点击展开。
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论