Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
risk-monitor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
1
合并请求
1
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蔡建
risk-monitor
Commits
2289e9a2
提交
2289e9a2
authored
3月 30, 2026
作者:
闫鹏
浏览文件
操作
浏览文件
下载
差异文件
合并分支 'yp-dev' 到 'pre'
Yp dev 查看合并请求
!276
上级
64a0296b
a7069f1e
流水线
#199
已失败 于阶段
in 4 分 22 秒
变更
14
流水线
1
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
14 个修改的文件
包含
268 行增加
和
171 行删除
+268
-171
.gitlab-ci.yml
.gitlab-ci.yml
+30
-12
App.vue
src/App.vue
+0
-0
index.js
src/api/zmOverview/risk/index.js
+39
-42
index.vue
src/views/ZMOverView/components/gameProfile/index.vue
+49
-8
index.vue
src/views/exportControl/index.vue
+12
-18
index.vue
...omponents/sanctionsOverview/components/listPage/index.vue
+50
-10
index.vue
src/views/exportControl/v2.0CommercialControlList/index.vue
+1
-1
index.vue
...ontrol/v2.0EntityList/components/dataStatistics/index.vue
+4
-4
index.vue
...omponents/sanctionsOverview/components/listPage/index.vue
+1
-0
index.vue
...ol/v2.0SingleSanction/components/dataStatistics/index.vue
+4
-12
index.vue
...ents/impactAnalysis/components/industrialImpact/index.vue
+4
-4
index.vue
...onents/impactAnalysis/components/researchImpact/index.vue
+4
-26
index.vue
...v2.0SingleSanction/components/sanctionsOverview/index.vue
+68
-28
index.vue
src/views/exportControl/v2.0SingleSanction/index.vue
+2
-6
没有找到文件。
.gitlab-ci.yml
浏览文件 @
2289e9a2
...
...
@@ -14,9 +14,7 @@ build_pre:
stage
:
build
image
:
node:20-bullseye
tags
:
-
docker
-
frontend
-
linux
-
risk-monitor-frontend
only
:
-
pre
script
:
...
...
@@ -39,17 +37,39 @@ deploy_pre:
stage
:
deploy
image
:
alpine:3.20
tags
:
-
docker
-
frontend
-
linux
-
risk-monitor-frontend
only
:
-
pre
dependencies
:
-
build_pre
script
:
-
apk add --no-cache rsync
-
test -d dist || (echo "dist not found" && exit 1)
-
test -d /nas/kjb_service/zm/pre-project/html || (echo "deploy target path not found" && exit 1)
-
apk add --no-cache rsync curl jq
# 只允许“最新一次 pre pipeline”部署到 nginx(加二次确认,避免短时间多次推送导致重复 rsync)
-
>
LATEST_PIPELINE_ID="$(
curl --silent --show-error --fail
--header "JOB-TOKEN: $CI_JOB_TOKEN"
"$CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/pipelines?ref=pre&order_by=id&sort=desc&per_page=1"
| jq -r '.[0].id'
)"
-
>
if [ -z "$LATEST_PIPELINE_ID" ] || [ "$LATEST_PIPELINE_ID" != "$CI_PIPELINE_ID" ]; then
echo "skip deploy: not latest pipeline (latest=$LATEST_PIPELINE_ID current=$CI_PIPELINE_ID)";
exit 0;
fi
-
sleep 20
-
>
LATEST_PIPELINE_ID="$(
curl --silent --show-error --fail
--header "JOB-TOKEN: $CI_JOB_TOKEN"
"$CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/pipelines?ref=pre&order_by=id&sort=desc&per_page=1"
| jq -r '.[0].id'
)"
-
>
if [ -z "$LATEST_PIPELINE_ID" ] || [ "$LATEST_PIPELINE_ID" != "$CI_PIPELINE_ID" ]; then
echo "skip deploy: not latest pipeline after debounce (latest=$LATEST_PIPELINE_ID current=$CI_PIPELINE_ID)";
exit 0;
fi
-
rsync -avz --delete dist/ /nas/kjb_service/zm/pre-project/html/
# 非 protected 分支:push 时先做 build 校验(避免合并 pre 时出现 build 报错)
...
...
@@ -57,9 +77,7 @@ build_check:
stage
:
build
image
:
node:20-bullseye
tags
:
-
docker
-
frontend
-
linux
-
risk-monitor-frontend
# 只在 push 时做构建校验,且排除 protected 分支与目标分支 pre
only
:
-
pushes
...
...
src/App.vue
浏览文件 @
2289e9a2
差异被折叠。
点击展开。
src/api/zmOverview/risk/index.js
浏览文件 @
2289e9a2
...
...
@@ -2,67 +2,65 @@ import request from "@/api/request.js";
// 中美博弈概览V2:最新风险动态统计
export
function
getLatestRiskUpdates
(
params
)
{
return
request
({
method
:
'GET'
,
url
:
`/api/rivalryIndexV2/LatestRiskUpdates`
,
params
:
params
})
return
request
({
method
:
"GET"
,
url
:
`/api/rivalryIndexV2/LatestRiskUpdates`
,
params
:
params
});
}
// 中美博弈概览V2:最新风险信号
export
function
getLatestRisks
()
{
return
request
({
method
:
'GET'
,
url
:
`/api/rivalryIndexV2/LatestRisks`
,
})
return
request
({
method
:
"GET"
,
url
:
`/api/rivalryIndexV2/LatestRisks`
});
}
// 中美博弈概览V2:美对华制裁措施数量趋势
export
function
geDomainContainmentTrend
(
params
)
{
return
request
({
method
:
'GET'
,
url
:
`/api/rivalryIndexV2/DomainContainmentTrend`
,
params
:
params
})
return
request
({
method
:
"GET"
,
url
:
`/api/rivalryIndexV2/DomainContainmentTrend`
,
params
:
params
});
}
// 中美博弈概况:获取榜单字典
export
function
getChartDict
()
{
return
request
({
method
:
'GET'
,
url
:
`/api/union/summary/chartDict`
,
})
return
request
({
method
:
"GET"
,
url
:
`/api/union/summary/chartDict`
});
}
// 中美博弈概况:获取年份
export
function
getYear
(
id
)
{
return
request
({
method
:
"GET"
,
url
:
`/api/union/summary/chartYear/
${
id
}
`
});
}
// 中美博弈概况:中美科技实力对比
export
function
getCompare
(
id
)
{
return
request
({
method
:
'GET'
,
url
:
`/api/union/summary/compare/
${
id
}
`
,
})
export
function
getCompare
(
id
,
year
)
{
return
request
({
method
:
"GET"
,
url
:
`/api/union/summary/compare/
${
id
}
/
${
year
}
`
});
}
// 中美博弈分析
export
function
getTechnologyGameAnalysis
()
{
return
request
({
method
:
'GET'
,
url
:
`/api/rivalryIndexV2/TechnologyGameAnalysis`
,
})
return
request
({
method
:
"GET"
,
url
:
`/api/rivalryIndexV2/TechnologyGameAnalysis`
});
}
//中美博弈概览V7:美国政府部门对华制裁最新动态
export
function
getGovernmentSanctionsDynamics
()
{
return
request
({
method
:
'GET'
,
url
:
`/api/rivalryIndex/governmentSanctionsDynamics`
,
})
}
\ No newline at end of file
return
request
({
method
:
"GET"
,
url
:
`/api/rivalryIndex/governmentSanctionsDynamics`
});
}
src/views/ZMOverView/components/gameProfile/index.vue
浏览文件 @
2289e9a2
...
...
@@ -14,10 +14,20 @@
size=
"default"
style=
"margin-left: 15px; width: 240px; height: 32px"
v-model=
"origin"
@
change=
"handle
GetCompar
e()"
@
change=
"handle
OriginChang
e()"
>
<el-option
:value=
"value.id"
:label=
"value.name"
v-for=
"(value, index) in originList"
:key=
"index"
/>
</el-select>
<el-select
class=
"select-item"
size=
"default"
style=
"margin-left: 15px; width: 200px; height: 32px"
v-model=
"year"
@
change=
"handleGetCompare()"
>
<el-option
:value=
"value"
:label=
"value"
v-for=
"(value, index) in yearList"
:key=
"index"
/>
</el-select>
</div>
</div>
<div
style=
"display: flex; height: 650px; width: 100%; padding-top: 12px"
>
...
...
@@ -237,7 +247,7 @@ import Echarts from "@/components/Chart/index.vue";
import
mockData
from
"./mock.json"
;
import
radarChart
from
"./radarChart3.js"
;
import
{
getCompare
,
getChartDict
,
getTechnologyGameAnalysis
}
from
"@/api/zmOverview/risk/index.js"
;
import
{
getCompare
,
getChartDict
,
get
Year
,
get
TechnologyGameAnalysis
}
from
"@/api/zmOverview/risk/index.js"
;
import
icon1
from
"./icon/btn-icon-0.png"
;
import
icon2
from
"./icon/btn-icon-1.png"
;
import
icon3
from
"./icon/btn-icon-2.png"
;
...
...
@@ -351,10 +361,32 @@ const handleGetChartDict = async () => {
console
.
error
(
"获取数据来源error"
,
error
);
}
};
const
yearList
=
ref
([]);
const
year
=
ref
(
""
);
//年份
const
handleGetYear
=
async
()
=>
{
try
{
const
res
=
await
getYear
(
origin
.
value
);
console
.
log
(
"年份"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
yearList
.
value
=
res
.
data
;
year
.
value
=
res
.
data
[
0
];
}
}
catch
(
error
)
{
console
.
error
(
"获取年份error"
,
error
);
}
};
// 数据来源改变时,年份列表也会改变
const
handleOriginChange
=
async
()
=>
{
await
handleGetYear
();
};
//中美科技实力对比
const
handleGetCompare
=
async
()
=>
{
try
{
const
res
=
await
getCompare
(
origin
.
value
);
const
res
=
await
getCompare
(
origin
.
value
,
year
.
value
);
console
.
log
(
"中美科技实力对比"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
tableData
.
value
=
res
.
data
[
0
].
children
;
...
...
@@ -392,6 +424,7 @@ const handlegetTechnologyGameAnalysis = async () => {
};
onMounted
(
async
()
=>
{
await
handleGetChartDict
();
await
handleGetYear
();
await
handleGetCompare
();
await
handlegetTechnologyGameAnalysis
();
// const dom = document.getElementById("char");
...
...
@@ -463,7 +496,13 @@ const handleIndicatorChange = indicator => {
const
years
=
chinaData
.
map
(
item
=>
item
.
year
.
toString
());
const
chinaValues
=
chinaData
.
map
(
item
=>
item
.
value
);
const
usaValues
=
usaData
.
map
(
item
=>
item
.
value
);
console
.
log
(
"中国"
,
chinaValues
);
console
.
log
(
"美国"
,
usaValues
);
// chinaValues和usaValues的最小值和最大值
const
min
=
Math
.
min
(...
chinaValues
,
...
usaValues
);
const
max
=
Math
.
max
(...
chinaValues
,
...
usaValues
);
lineOption
.
value
.
yAxis
.
min
=
Math
.
floor
(
min
-
1
);
lineOption
.
value
.
yAxis
.
max
=
Math
.
ceil
(
max
+
1
);
lineOption
.
value
.
xAxis
.
data
=
years
;
lineOption
.
value
.
series
=
[
{
...
...
@@ -566,9 +605,11 @@ const lineOption = ref({
},
yAxis
:
{
type
:
"value"
,
// name: "指数",
nameLocation
:
"top"
,
nameGap
:
35
,
min
:
77
,
name
:
"指数"
,
nameLocation
:
"end"
,
nameGap
:
1
,
padding
:
[
0
,
-
50
,
0
,
0
],
nameTextStyle
:
{
color
:
"#666"
,
fontSize
:
13
,
...
...
@@ -589,7 +630,7 @@ const lineOption = ref({
}
},
axisLabel
:
{
color
:
"#
ccc
"
,
color
:
"#
666
"
,
fontSize
:
14
,
fontWeight
:
400
,
formatter
:
value
=>
{
...
...
src/views/exportControl/index.vue
浏览文件 @
2289e9a2
...
...
@@ -384,7 +384,7 @@
</div>
<div
class=
"ai-pane"
>
<AiButton
/>
<AiPane
:aiContent=
"radarChart.
loading ? '解读生成中...' : radarChart.
interpretation"
/>
<AiPane
:aiContent=
"radarChart.interpretation"
/>
</div>
</
template
>
</custom-container>
...
...
@@ -409,7 +409,7 @@
</div>
<div
class=
"ai-pane"
>
<AiButton
/>
<AiPane
:aiContent=
"trendChart.
loading ? '解读生成中...' : trendChart.
interpretation"
/>
<AiPane
:aiContent=
"trendChart.interpretation"
/>
</div>
</
template
>
</custom-container>
...
...
@@ -830,7 +830,6 @@ const handleToRiskSignalDetail = item => {
});
// 打开新页面
window
.
open
(
routeData
.
href
,
"_blank"
);
};
const
sanctionList
=
ref
([]);
...
...
@@ -1042,7 +1041,6 @@ const handleToSocialDetail = item => {
}
});
window
.
open
(
route
.
href
,
"_blank"
);
};
// 获取趋势图数据
const
fetchTrendData
=
async
()
=>
{
...
...
@@ -1180,7 +1178,6 @@ const handleToEntityListNoId = item => {
});
// 打开一个新页面
window
.
open
(
routeData
.
href
,
"_blank"
);
}
else
if
(
item
.
nameZh
==
"商业管制清单"
)
{
const
routeData
=
router
.
resolve
({
path
:
"/exportControl/commercialControlList"
,
...
...
@@ -1195,8 +1192,8 @@ const handleToEntityListNoId = item => {
}
};
const
billList
=
ref
([]);
const
curBillListIndex
=
ref
(
0
);
//
const billList = ref([]);
//
const curBillListIndex = ref(0);
const
searchExportControlText
=
ref
(
""
);
const
infoListColor
=
ref
([
"rgba(206, 79, 81, 1)"
,
"rgba(114, 46, 209, 1)"
,
"rgba(132, 136, 142, 1)"
,
"rgba(132, 136, 142, 1)"
]);
...
...
@@ -1391,8 +1388,8 @@ const fetchSanctionList = async () => {
const
tags
=
Array
.
isArray
(
item
.
techDomains
)
?
item
.
techDomains
:
item
.
techDomain
?
[
item
.
techDomain
]
:
item
.
techDomainList
||
[];
?
[
item
.
techDomain
]
:
item
.
techDomainList
||
[];
const
fullTime
=
item
.
startTime
?
formatAnyDateToChinese
(
item
.
startTime
)
...
...
@@ -1422,8 +1419,8 @@ const fetchSanctionList = async () => {
countTag
:
item
.
cnEntityCount
?
`
${
item
.
cnEntityCount
}
家中国实体`
:
item
.
ruleOrgCount
?
`
${
item
.
ruleOrgCount
}
家关联实体`
:
item
.
countTag
||
""
?
`
${
item
.
ruleOrgCount
}
家关联实体`
:
item
.
countTag
||
""
};
});
totalAll
.
value
=
res
.
totalElements
;
...
...
@@ -1666,12 +1663,11 @@ const handlePerClick = item => {
const
route
=
router
.
resolve
({
path
:
"/characterPage"
,
query
:
{
type
:
item
.
t
ype
||
[
1
,
2
,
3
][
Math
.
floor
(
Math
.
random
()
*
3
)],
type
:
item
.
personT
ype
||
[
1
,
2
,
3
][
Math
.
floor
(
Math
.
random
()
*
3
)],
personId
:
item
.
personId
}
});
window
.
open
(
route
.
href
,
"_blank"
);
};
// 处理点击社交媒体消息的方法
// const handleInfoClick = item => {
...
...
@@ -1751,17 +1747,16 @@ const chart1Data = ref({
});
const
handleSanc
=
item
=>
{
console
.
log
(
item
);
console
.
log
(
"activeResourceTabItem.value.id"
,
activeResourceTabItem
.
value
.
id
);
window
.
sessionStorage
.
setItem
(
"curTabName"
,
`
${
item
.
postDate
}
《
${
item
.
title
}
》`
);
const
route
=
router
.
resolve
({
path
:
"/exportControl/singleSanction"
,
query
:
{
id
:
item
.
id
,
sanTypeId
:
activeResourceTabItem
.
value
.
id
sanTypeId
:
activeResourceTabItem
.
value
.
id
.
join
(
","
)
}
});
window
.
open
(
route
.
href
,
"_blank"
);
};
// 查看更多风险信号
...
...
@@ -2368,8 +2363,7 @@ const handleMediaClick = item => {
overflow-y
:
auto
;
.home-top-bg
{
background
:
url("./assets/images/background.png")
,
background
:
url("./assets/images/background.png")
,
linear-gradient
(
180deg
,
rgba
(
229
,
241
,
254
,
1
)
0%
,
rgba
(
246
,
251
,
255
,
0
)
30%
);
background-size
:
100%
100%
;
position
:
absolute
;
...
...
src/views/exportControl/v2.0CommercialControlList/components/sanctionsOverview/components/listPage/index.vue
浏览文件 @
2289e9a2
...
...
@@ -60,7 +60,7 @@
<div
class=
"list-content"
v-for=
"(ele, j) in element.cclChildren"
:key=
"j"
>
<div
class=
"content-title"
@
click=
"ele.isExpand = !ele.isExpand"
>
<div
class=
"code-zone"
>
<
!--
<div
class=
"dot"
v-if=
"ele.isDot"
></div>
--
>
<
div
class=
"dot"
v-if=
"ele.changeFlag"
></div
>
<span
class=
"code"
>
{{
ele
.
cclCode
}}
</span>
</div>
<span
class=
"name"
>
{{
ele
.
cclTitleZh
}}
</span>
...
...
@@ -121,9 +121,9 @@ const getTechFields = async () => {
const
res
=
await
getAreaType
();
if
(
res
&&
res
.
code
===
200
)
{
console
.
log
(
"-----getTechFields"
,
res
.
data
);
techFields
.
value
=
res
.
data
;
techFields
.
value
=
[{
id
:
"all"
,
name
:
"全部领域"
,
checked
:
true
}].
concat
(
res
.
data
)
;
// 默认选中第一个
techFields
.
value
[
0
].
checked
=
true
;
//
techFields.value[0].checked = true;
}
}
catch
(
error
)
{
console
.
error
(
"获取科技领域字典失败:"
,
error
);
...
...
@@ -136,9 +136,9 @@ const getControlReasonList = async () => {
const
res
=
await
getControlReason
();
if
(
res
&&
res
.
code
===
200
)
{
console
.
log
(
"-----getControlReasonList"
,
res
.
data
);
controlReason
.
value
=
res
.
data
;
controlReason
.
value
=
[{
id
:
"all"
,
name
:
"全部"
,
checked
:
true
}].
concat
(
res
.
data
)
;
// 默认选中第一个
controlReason
.
value
[
0
].
checked
=
true
;
//
controlReason.value[0].checked = true;
}
}
catch
(
error
)
{
console
.
error
(
"获取管控原因字典失败:"
,
error
);
...
...
@@ -151,8 +151,19 @@ const viewNew = ref(true);
// 获取ccl清单列表
const
getCclList
=
async
()
=>
{
let
techDomains
=
techFields
.
value
.
filter
(
item
=>
item
.
checked
).
map
(
item
=>
+
item
.
id
);
let
controls
=
controlReason
.
value
.
filter
(
item
=>
item
.
checked
).
map
(
item
=>
+
item
.
id
);
let
techDomains
=
[];
const
allTech
=
techFields
.
value
.
find
(
item
=>
item
.
id
===
"all"
);
// ✅ 修正点1
if
(
!
allTech
||
!
allTech
.
checked
)
{
techDomains
=
techFields
.
value
.
filter
(
item
=>
item
.
checked
&&
item
.
id
!==
"all"
).
map
(
item
=>
item
.
id
);
// 注意:这里 map 的是 value,假设后端需要的是 value 字段
}
let
controls
=
[];
const
allReason
=
controlReason
.
value
.
find
(
item
=>
item
.
id
===
"all"
);
// ✅ 修正点2
if
(
!
allReason
||
!
allReason
.
checked
)
{
controls
=
controlReason
.
value
.
filter
(
item
=>
item
.
checked
&&
item
.
id
!==
"all"
).
map
(
item
=>
item
.
id
);
}
// let techDomains = techFields.value.filter(item => item.checked).map(item => +item.id);
// let controls = controlReason.value.filter(item => item.checked).map(item => +item.id);
const
params
=
{
categoryCode
:
currentCCLType
.
value
,
techDomainIds
:
techDomains
,
...
...
@@ -161,7 +172,7 @@ const getCclList = async () => {
isLatest
:
viewNew
.
value
,
recordId
:
currentCCLVersion
.
value
||
""
};
console
.
log
(
JSON
.
stringify
(
params
)
);
console
.
log
(
"cclList参数:"
,
params
);
try
{
// const res = await getCclQuery(null);
const
res
=
await
getCclQuery
(
params
);
...
...
@@ -272,8 +283,34 @@ const getCCLVersionListApi = async () => {
};
// 筛选逻辑处理
const
handleFilterChange
=
(
item
,
list
,
type
)
=>
{
console
.
log
(
item
,
list
,
type
);
const
handleFilterChange
=
(
item
,
listRef
,
type
)
=>
{
const
list
=
listRef
;
const
allItem
=
list
.
find
(
i
=>
i
.
id
===
"all"
);
// ✅ 关键修正
if
(
!
allItem
)
return
;
if
(
item
.
id
===
"all"
)
{
if
(
item
.
checked
)
{
list
.
forEach
(
i
=>
{
if
(
i
.
id
!==
"all"
)
i
.
checked
=
false
;
});
}
else
{
const
hasOtherChecked
=
list
.
some
(
i
=>
i
.
id
!==
"all"
&&
i
.
checked
);
if
(
!
hasOtherChecked
&&
list
.
length
>
1
)
{
const
firstNonAll
=
list
.
find
(
i
=>
i
.
id
!==
"all"
);
if
(
firstNonAll
)
firstNonAll
.
checked
=
true
;
}
}
}
else
{
if
(
item
.
checked
)
{
allItem
.
checked
=
false
;
}
else
{
const
hasAnyChecked
=
list
.
some
(
i
=>
i
.
id
!==
"all"
&&
i
.
checked
);
if
(
!
hasAnyChecked
)
{
allItem
.
checked
=
true
;
}
}
}
getCclList
();
};
...
...
@@ -373,6 +410,9 @@ onMounted(async () => {
:deep
(
.el-input__wrapper
)
{
padding
:
0
11px
;
border
:
1px
solid
rgba
(
0
,
0
,
0
,
0
.1
);
background-color
:
#fff
;
border-radius
:
3px
;
}
:deep
(
.el-input__inner
)
{
...
...
src/views/exportControl/v2.0CommercialControlList/index.vue
浏览文件 @
2289e9a2
...
...
@@ -10,7 +10,7 @@
</div>
<div
class=
"department"
>
{{
headerTitle
.
department
}}
</div>
</div>
<
div
class=
"btn"
><img
:src=
"icon01"
alt
/>
切换
</div
>
<
!--
<div
class=
"btn"
><img
:src=
"icon01"
alt
/>
切换
</div>
--
>
</div>
<div
class=
"header-nav"
>
<div
...
...
src/views/exportControl/v2.0EntityList/components/dataStatistics/index.vue
浏览文件 @
2289e9a2
...
...
@@ -125,7 +125,7 @@
</div>
<div
class=
"ai-pane"
>
<AiButton
/>
<AiPane
:aiContent=
"sanctionCountChart.
loading ? '解读生成中...' : sanctionCountChart.
interpretation"
/>
<AiPane
:aiContent=
"sanctionCountChart.interpretation"
/>
</div>
</AnalysisBox>
</div>
...
...
@@ -174,7 +174,7 @@
</div>
<div
class=
"ai-pane"
>
<AiButton
/>
<AiPane
:aiContent=
"rankChart.
loading ? '解读生成中...' : rankChart.
interpretation"
/>
<AiPane
:aiContent=
"rankChart.interpretation"
/>
</div>
</AnalysisBox>
</div>
...
...
@@ -206,7 +206,7 @@
</div>
<div
class=
"ai-pane"
>
<AiButton
/>
<AiPane
:aiContent=
"domainChart.
loading ? '解读生成中...' : domainChart.
interpretation"
/>
<AiPane
:aiContent=
"domainChart.interpretation"
/>
</div>
</AnalysisBox>
</div>
...
...
@@ -238,7 +238,7 @@
</div>
<div
class=
"ai-pane"
>
<AiButton
/>
<AiPane
:aiContent=
"typeChart.
loading ? '解读生成中...' : typeChart.
interpretation"
/>
<AiPane
:aiContent=
"typeChart.interpretation"
/>
</div>
</AnalysisBox>
</div>
...
...
src/views/exportControl/v2.0EntityList/components/sanctionsOverview/components/listPage/index.vue
浏览文件 @
2289e9a2
...
...
@@ -532,6 +532,7 @@ watch(customDateRange, () => {
padding
:
0
11px
;
border
:
1px
solid
rgba
(
170
,
173
,
177
,
1
);
background-color
:
#fff
;
border-radius
:
3px
;
}
:deep
(
.el-input__inner
)
{
...
...
src/views/exportControl/v2.0SingleSanction/components/dataStatistics/index.vue
浏览文件 @
2289e9a2
...
...
@@ -63,7 +63,7 @@
</div>
<div
class=
"ai-pane"
>
<AiButton
/>
<AiPane
:aiContent=
"domainChart.
loading ? '解读生成中...' : domainChart.
interpretation"
/>
<AiPane
:aiContent=
"domainChart.interpretation"
/>
</div>
</AnalysisBox>
</div>
...
...
@@ -113,7 +113,7 @@
</div>
<div
class=
"ai-pane"
>
<AiButton
/>
<AiPane
:aiContent=
"typeChart.
loading ? '解读生成中...' : typeChart.
interpretation"
/>
<AiPane
:aiContent=
"typeChart.interpretation"
/>
</div>
</AnalysisBox>
</div>
...
...
@@ -154,11 +154,7 @@
</div>
<div
class=
"ai-pane"
>
<AiButton
/>
<AiPane
:aiContent=
"
countryDistributionChart.loading ? '解读生成中...' : countryDistributionChart.interpretation
"
/>
<AiPane
:aiContent=
"countryDistributionChart.interpretation"
/>
</div>
</AnalysisBox>
</div>
...
...
@@ -202,11 +198,7 @@
</div>
<div
class=
"ai-pane"
>
<AiButton
/>
<AiPane
:aiContent=
"
regionDistributionChart.loading ? '解读生成中...' : regionDistributionChart.interpretation
"
/>
<AiPane
:aiContent=
"regionDistributionChart.interpretation"
/>
</div>
</AnalysisBox>
</div>
...
...
src/views/exportControl/v2.0SingleSanction/components/impactAnalysis/components/industrialImpact/index.vue
浏览文件 @
2289e9a2
...
...
@@ -146,7 +146,7 @@
</div>
<div
class=
"ai-pane"
>
<AiButton
/>
<AiPane
:aiContent=
"revenueChart.
loading ? '解读生成中...' : revenueChart.
interpretation"
/>
<AiPane
:aiContent=
"revenueChart.interpretation"
/>
</div>
</div>
</AnalysisBox>
...
...
@@ -188,7 +188,7 @@
</div>
<div
class=
"ai-pane"
>
<AiButton
/>
<AiPane
:aiContent=
"marketChart.
loading ? '解读生成中...' : marketChart.
interpretation"
/>
<AiPane
:aiContent=
"marketChart.interpretation"
/>
</div>
</div>
</AnalysisBox>
...
...
@@ -249,7 +249,7 @@
</div>
<div
class=
"ai-pane"
>
<AiButton
/>
<AiPane
:aiContent=
"rdChart.
loading ? '解读生成中...' : rdChart.
interpretation"
/>
<AiPane
:aiContent=
"rdChart.interpretation"
/>
</div>
</div>
</AnalysisBox>
...
...
@@ -310,7 +310,7 @@
</div>
<div
class=
"ai-pane"
>
<AiButton
/>
<AiPane
:aiContent=
"shareChart.
loading ? '解读生成中...' : shareChart.
interpretation"
/>
<AiPane
:aiContent=
"shareChart.interpretation"
/>
</div>
</div>
</AnalysisBox>
...
...
src/views/exportControl/v2.0SingleSanction/components/impactAnalysis/components/researchImpact/index.vue
浏览文件 @
2289e9a2
...
...
@@ -60,13 +60,7 @@
</div>
<div
class=
"ai-pane"
>
<AiButton
/>
<AiPane
:aiContent=
"
rdInstrumentDependencyChart.loading
? '解读生成中...'
: rdInstrumentDependencyChart.interpretation
"
/>
<AiPane
:aiContent=
"rdInstrumentDependencyChart.interpretation"
/>
</div>
</div>
</AnalysisBox>
...
...
@@ -102,13 +96,7 @@
</div>
<div
class=
"ai-pane"
>
<AiButton
/>
<AiPane
:aiContent=
"
rdInstrumentImportCountryChart.loading
? '解读生成中...'
: rdInstrumentImportCountryChart.interpretation
"
/>
<AiPane
:aiContent=
"rdInstrumentImportCountryChart.interpretation"
/>
</div>
</div>
</AnalysisBox>
...
...
@@ -177,13 +165,7 @@
</div>
<div
class=
"ai-pane"
>
<AiButton
/>
<AiPane
:aiContent=
"
internationalCooperationChart.loading
? '解读生成中...'
: internationalCooperationChart.interpretation
"
/>
<AiPane
:aiContent=
"internationalCooperationChart.interpretation"
/>
</div>
</div>
</AnalysisBox>
...
...
@@ -252,11 +234,7 @@
</div>
<div
class=
"ai-pane"
>
<AiButton
/>
<AiPane
:aiContent=
"
internationalPaperChart.loading ? '解读生成中...' : internationalPaperChart.interpretation
"
/>
<AiPane
:aiContent=
"internationalPaperChart.interpretation"
/>
</div>
</div>
</AnalysisBox>
...
...
src/views/exportControl/v2.0SingleSanction/components/sanctionsOverview/index.vue
浏览文件 @
2289e9a2
...
...
@@ -31,7 +31,7 @@
<div
class=
"info-row"
>
<div
class=
"label"
>
发布人:
</div>
<div
class=
"value link"
>
<img
:src=
"defaultTitle"
alt=
""
class=
"icon avatar"
/>
<img
:src=
"
formattedData.avartar ||
defaultTitle"
alt=
""
class=
"icon avatar"
/>
<span
@
click=
"handleClick"
>
{{
formattedData
.
postPersonName
}}
>
</span>
</div>
</div>
...
...
@@ -46,13 +46,16 @@
<div
class=
"content-title"
>
制裁实体分布:
</div>
<div
class=
"distribution-list"
>
<div
class=
"list-item"
v-for=
"(item, index) in entityDistribution"
:key=
"index"
>
<img
:src=
"flag"
alt=
""
class=
"flag"
/>
<img
:src=
"
item.imageUrl ||
flag"
alt=
""
class=
"flag"
/>
<div
class=
"country-name"
>
{{
item
.
name
}}
</div>
<div
class=
"progress-bar-container"
>
<div
class=
"progress-bar"
:style=
"
{
width: item.width,
background: item.gradient
}">
</div>
<div
class=
"progress-bar"
:style=
"
{
width: item.width,
background: item.gradient
}"
>
</div>
</div>
<div
class=
"count"
:class=
"
{ highlight: index === 0 }">
{{
item
.
count
}}
家
</div>
</div>
...
...
@@ -95,13 +98,25 @@
</div>
<div
class=
"filter-right"
>
<el-checkbox
v-model=
"onlyChina"
label=
"只看中国实体"
/>
<el-select
v-model=
"filterField"
placeholder=
"全部领域"
style=
"width: 150px; margin: 0 12px 0 16px"
>
<el-select
v-model=
"filterField"
placeholder=
"全部领域"
style=
"width: 150px; margin: 0 12px 0 16px"
>
<el-option
label=
"全部领域"
value=
""
/>
<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-select>
<el-input
v-model=
"searchKeyword"
placeholder=
"搜索实体"
<el-input
v-model=
"searchKeyword"
placeholder=
"搜索实体"
style=
"width: 150px; border: 1px solid rgba(170, 173, 177, 0.4); border-radius: 5px"
:suffix-icon=
"Search"
/>
:suffix-icon=
"Search"
/>
</div>
</div>
<div
class=
"stats-row"
>
...
...
@@ -116,20 +131,28 @@
<div
class=
"stats-info"
>
<div
class=
"stat-item"
>
<span
class=
"dot red"
></span>
<span
class=
"text"
>
新增
<span
class=
"num red"
>
{{
addCount
}}
</span>
家 (50%规则涉及
<span
class=
"num red"
>
{{
addRuleCount
}}
</span>
家)
</span>
<span
class=
"text"
>
新增
<span
class=
"num red"
>
{{
addCount
}}
</span>
家 (50%规则涉及
<span
class=
"num red"
>
{{
addRuleCount
}}
</span
>
家)
</span
>
</div>
<div
class=
"stat-item"
>
<span
class=
"dot green"
></span>
<span
class=
"text"
>
移除
<span
class=
"num green"
>
{{
removeCount
}}
</span>
家 (50%规则涉及
<span
class=
"num green"
>
{{
removeRuleCount
}}
</span>
家)
</span>
<span
class=
"text"
>
移除
<span
class=
"num green"
>
{{
removeCount
}}
</span>
家 (50%规则涉及
<span
class=
"num green"
>
{{
removeRuleCount
}}
</span
>
家)
</span
>
</div>
</div>
</div>
</div>
<div
class=
"right-content"
>
<div
class=
"sanction-group-list"
>
<el-empty
v-if=
"sanctionList.length === 0"
description=
"暂无制裁清单"
/>
<div
class=
"sanction-group"
v-for=
"(group, index) in sanctionList"
:key=
"index"
>
<el-table
:data=
"group.entities"
style=
"width: 100%"
>
<el-table-column
label=
"实体名称"
min-width=
"280"
>
...
...
@@ -145,8 +168,14 @@
</el-table-column>
<el-table-column
label=
"涉及领域"
width=
"180"
align=
"center"
>
<
template
#
default=
"scope"
>
<span
v-for=
"(item, index) in scope.row.fields"
:key=
"index"
class=
"tag"
:style=
"getTagStyle(item)"
style=
"margin: 0 2px"
>
{{
item
}}
</span>
<span
v-for=
"(item, index) in scope.row.fields"
:key=
"index"
class=
"tag"
:style=
"getTagStyle(item)"
style=
"margin: 0 2px"
>
{{
item
}}
</span
>
</
template
>
</el-table-column>
<el-table-column
prop=
"location"
label=
"上市地点"
width=
"90"
align=
"center"
/>
...
...
@@ -154,8 +183,11 @@
<el-table-column
prop=
"revenue"
label=
"营收(亿元)"
width=
"110"
align=
"center"
/>
<el-table-column
label=
"50%规则子企业"
width=
"180"
align=
"center"
>
<
template
#
default=
"scope"
>
<span
v-if=
"scope.row.subsidiaryCount"
class=
"subsidiary-link"
@
click=
"handleSubsidiaryClick(scope.row)"
>
<span
v-if=
"scope.row.subsidiaryCount"
class=
"subsidiary-link"
@
click=
"handleSubsidiaryClick(scope.row)"
>
{{
scope
.
row
.
subsidiaryText
}}
<span
class=
"blue-text"
>
{{
scope
.
row
.
subsidiaryCount
}}
家 >
</span>
</span>
...
...
@@ -173,8 +205,12 @@
</div>
</div>
<!-- 50%规则子企业弹框 -->
<RuleSubsidiaryDialog
v-model=
"subsidiaryDialogVisible"
:company-name=
"currentSubsidiaryCompanyName"
:total-count=
"currentSubsidiaryCount"
:data-list=
"currentSubsidiaryList"
/>
<RuleSubsidiaryDialog
v-model=
"subsidiaryDialogVisible"
:company-name=
"currentSubsidiaryCompanyName"
:total-count=
"currentSubsidiaryCount"
:data-list=
"currentSubsidiaryList"
/>
</div>
</template>
...
...
@@ -267,7 +303,7 @@ const getSanctionOverviewList = async () => {
removeCount
.
value
=
data
.
removeCount
||
0
;
removeRuleCount
.
value
=
data
.
removeRuleCount
||
0
;
const
list
=
data
.
san
List
||
[];
const
list
=
activeTab
.
value
===
"add"
?
data
.
sanList
:
data
.
remove
List
||
[];
sanctionList
.
value
=
list
.
map
(
item
=>
({
reason
:
item
.
sanReason
,
entities
:
(
item
.
orgList
||
[]).
map
(
org
=>
({
...
...
@@ -281,8 +317,8 @@ const getSanctionOverviewList = async () => {
subsidiaryText
:
org
.
ruleOrgList
&&
org
.
ruleOrgList
.
length
>
0
?
(
org
.
ruleOrgList
[
0
].
orgName
.
length
>
10
?
org
.
ruleOrgList
[
0
].
orgName
.
slice
(
0
,
10
)
+
"..."
:
org
.
ruleOrgList
[
0
].
orgName
)
+
"...等"
?
org
.
ruleOrgList
[
0
].
orgName
.
slice
(
0
,
10
)
+
"..."
:
org
.
ruleOrgList
[
0
].
orgName
)
+
"...等"
:
""
}))
}));
...
...
@@ -342,10 +378,12 @@ const getUrlParams = () => {
// 单次制裁-制裁概况-制裁实体国家分布
const
getEntityCountry
=
async
()
=>
{
try
{
const
res
=
await
getSingleSanctionEntityCountry
(
{
const
params
=
{
sanRecordId
:
sanRecordId
.
value
,
sanTypeId
:
sanTypeId
.
value
||
1
// 实体清单固定1
});
sanTypeId
:
sanTypeId
.
value
||
1
// 默认为1
};
console
.
log
(
"params --:"
,
params
);
const
res
=
await
getSingleSanctionEntityCountry
(
params
);
if
(
res
.
code
===
200
)
{
const
rawData
=
res
.
data
||
[];
const
maxCount
=
Math
.
max
(...
rawData
.
map
(
item
=>
item
.
count
||
0
),
1
);
...
...
@@ -413,7 +451,8 @@ const formattedData = computed(() => {
fileCode
:
info
.
fileCode
?
`
${
info
.
fileCode
}
`
:
""
,
administrativeOrderId
:
info
.
administrativeOrderId
?
`No.
${
info
.
administrativeOrderId
}
`
:
""
,
postPersonName
:
info
.
postPersonName
,
domains
:
info
.
domainNames
domains
:
info
.
domainNames
,
avartar
:
info
.
postPersonAvatarUrl
};
});
...
...
@@ -510,6 +549,7 @@ const entityDistribution = ref([
const
sanTypeId
=
ref
(
""
);
onMounted
(()
=>
{
// 获取路由参数中的sanTypeId
console
.
log
(
"route.query.sanTypeId --:"
,
route
.
query
.
sanTypeId
);
sanTypeId
.
value
=
route
.
query
.
sanTypeId
||
"1"
;
// 获取URL参数
getUrlParams
();
...
...
src/views/exportControl/v2.0SingleSanction/index.vue
浏览文件 @
2289e9a2
...
...
@@ -239,8 +239,6 @@ const handlePageChange = async newPage => {
// ========== 选择某项 ==========
const
selectSanction
=
item
=>
{
selectedSanctionId
.
value
=
item
.
id
;
// 可在此处触发其他逻辑,如查看详情
// 替换当前路由参数,并重新加载数据
router
.
replace
({
path
:
window
.
location
.
pathname
,
query
:
{
...
...
@@ -248,11 +246,8 @@ const selectSanction = item => {
sanTypeId
:
item
.
sanTypeId
}
});
// 3. 立即重新加载数据(关键!)
getSingleSanctionOverviewData
();
// 4. 可选:关闭弹窗
sanctionModalVisible
.
value
=
false
;
window
.
location
.
reload
();
};
// ========== 关闭弹窗时重置 ==========
...
...
@@ -278,6 +273,7 @@ onMounted(() => {
width
:
100%
;
height
:
100%
;
overflow-y
:
auto
;
padding-bottom
:
50px
;
.header
{
width
:
100%
;
height
:
148px
;
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论