Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
risk-monitor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蔡建
risk-monitor
Commits
e4bc83d4
提交
e4bc83d4
authored
3月 27, 2026
作者:
张伊明
浏览文件
操作
浏览文件
下载
差异文件
合并分支 'yp-dev' 到 'pre'
Yp dev 查看合并请求
!245
上级
bb991b9d
603c6875
流水线
#115
已取消 于阶段
in 3 分 26 秒
变更
12
流水线
1
全部展开
显示空白字符变更
内嵌
并排
正在显示
12 个修改的文件
包含
390 行增加
和
52 行删除
+390
-52
analysisBox.vue
src/components/base/boxBackground/analysisBox.vue
+24
-27
index.vue
src/views/exportControl/index.vue
+82
-7
common.js
src/views/exportControl/utils/common.js
+63
-0
index.vue
...ontrol/v2.0EntityList/components/dataStatistics/index.vue
+0
-0
index.vue
src/views/exportControl/v2.0EntityList/index.vue
+1
-1
index.vue
...ol/v2.0SingleSanction/components/dataStatistics/index.vue
+0
-0
RelationGraph.vue
...nction/components/deepMining/components/RelationGraph.vue
+64
-2
index.vue
...ents/impactAnalysis/components/industrialImpact/index.vue
+0
-0
index.vue
...onents/impactAnalysis/components/researchImpact/index.vue
+0
-0
index.vue
src/views/exportControl/v2.0SingleSanction/index.vue
+144
-2
mock.json
src/views/exportControl/v2.0SingleSanction/mock.json
+0
-0
index.vue
src/views/thinkTank/ReportDetail/index.vue
+12
-13
没有找到文件。
src/components/base/boxBackground/analysisBox.vue
浏览文件 @
e4bc83d4
...
@@ -14,13 +14,13 @@
...
@@ -14,13 +14,13 @@
</div>
</div>
<div
class=
"header-right"
>
<div
class=
"header-right"
>
<div
class=
"header-right-btn"
@
click=
"handleSave"
v-if=
"showAllBtn"
>
<div
class=
"header-right-btn"
@
click=
"handleSave"
v-if=
"showAllBtn"
>
<img
src=
"@/assets/icons/box-header-icon1.png"
alt=
""
>
<img
src=
"@/assets/icons/box-header-icon1.png"
alt=
""
/
>
</div>
</div>
<div
class=
"header-right-btn"
@
click=
"handleDownload"
>
<div
class=
"header-right-btn"
@
click=
"handleDownload"
>
<img
src=
"@/assets/icons/box-header-icon2.png"
alt=
""
>
<img
src=
"@/assets/icons/box-header-icon2.png"
alt=
""
/
>
</div>
</div>
<div
class=
"header-right-btn"
@
click=
"handleCollect"
>
<div
class=
"header-right-btn"
@
click=
"handleCollect"
>
<img
src=
"@/assets/icons/box-header-icon3.png"
alt=
""
>
<img
src=
"@/assets/icons/box-header-icon3.png"
alt=
""
/
>
</div>
</div>
</div>
</div>
</div>
</div>
...
@@ -31,21 +31,21 @@
...
@@ -31,21 +31,21 @@
</
template
>
</
template
>
<
script
setup
>
<
script
setup
>
import
{
ElMessage
}
from
'element-plus'
import
{
ElMessage
}
from
"element-plus"
;
import
{
ref
,
computed
}
from
'vue'
import
{
ref
,
computed
}
from
"vue"
;
const
props
=
defineProps
({
const
props
=
defineProps
({
title
:
{
title
:
{
type
:
String
,
type
:
String
,
default
:
''
default
:
""
},
},
width
:
{
width
:
{
type
:
String
,
type
:
String
,
default
:
''
default
:
""
},
},
height
:
{
height
:
{
type
:
String
,
type
:
String
,
default
:
''
default
:
""
},
},
showAllBtn
:
{
showAllBtn
:
{
type
:
Boolean
,
type
:
Boolean
,
...
@@ -56,39 +56,36 @@ const props = defineProps({
...
@@ -56,39 +56,36 @@ const props = defineProps({
type
:
Boolean
,
type
:
Boolean
,
default
:
false
default
:
false
}
}
})
})
;
const
handleSave
=
()
=>
{
const
handleSave
=
()
=>
{
if
(
props
.
devTip
)
{
if
(
props
.
devTip
)
{
ElMessage
.
warning
(
'当前功能正在开发中,敬请期待!'
)
ElMessage
.
warning
(
"当前功能正在开发中,敬请期待!"
);
return
return
;
}
}
ElMessage
.
success
(
'保存当前内容'
)
ElMessage
.
success
(
"保存当前内容"
);
// emit('save')
// emit('save')
}
}
;
const
handleDownload
=
()
=>
{
const
handleDownload
=
()
=>
{
if
(
props
.
devTip
)
{
if
(
props
.
devTip
)
{
ElMessage
.
warning
(
'当前功能正在开发中,敬请期待!'
)
ElMessage
.
warning
(
"当前功能正在开发中,敬请期待!"
);
return
return
;
}
}
ElMessage
.
success
(
'下载当前内容'
)
ElMessage
.
success
(
"下载当前内容"
);
// emit('download')
// emit('download')
};
}
const
handleCollect
=
()
=>
{
const
handleCollect
=
()
=>
{
if
(
props
.
devTip
)
{
if
(
props
.
devTip
)
{
ElMessage
.
warning
(
'当前功能正在开发中,敬请期待!'
)
ElMessage
.
warning
(
"当前功能正在开发中,敬请期待!"
);
return
return
;
}
}
ElMessage
.
success
(
'收藏当前内容'
)
ElMessage
.
success
(
"收藏当前内容"
);
// emit('collect')
// emit('collect')
};
}
const
emit
=
defineEmits
([
"save"
,
"download"
,
"collect"
]);
const
emit
=
defineEmits
([
'save'
,
'download'
,
'collect'
])
</
script
>
</
script
>
<
style
lang=
"scss"
scoped
>
<
style
lang=
"scss"
scoped
>
...
@@ -97,7 +94,7 @@ const emit = defineEmits(['save', 'download', 'collect'])
...
@@ -97,7 +94,7 @@ const emit = defineEmits(['save', 'download', 'collect'])
border-radius
:
10px
;
border-radius
:
10px
;
box-shadow
:
0px
0px
20px
0px
rgba
(
25
,
69
,
130
,
0
.1
);
box-shadow
:
0px
0px
20px
0px
rgba
(
25
,
69
,
130
,
0
.1
);
background
:
rgba
(
255
,
255
,
255
,
1
);
background
:
rgba
(
255
,
255
,
255
,
1
);
position
:
relative
;
.wrapper-header
{
.wrapper-header
{
height
:
45px
;
height
:
45px
;
display
:
flex
;
display
:
flex
;
...
@@ -123,7 +120,7 @@ const emit = defineEmits(['save', 'download', 'collect'])
...
@@ -123,7 +120,7 @@ const emit = defineEmits(['save', 'download', 'collect'])
// line-height: 26px;
// line-height: 26px;
// letter-spacing: 0px;
// letter-spacing: 0px;
height
:
100%
;
height
:
100%
;
&
>
div
{
&
>
div
{
height
:
100%
;
height
:
100%
;
color
:
var
(
--
color-main-active
);
color
:
var
(
--
color-main-active
);
font-family
:
Microsoft
YaHei
;
font-family
:
Microsoft
YaHei
;
...
...
src/views/exportControl/index.vue
浏览文件 @
e4bc83d4
...
@@ -368,19 +368,29 @@
...
@@ -368,19 +368,29 @@
</el-col>
</el-col>
</el-row>
</el-row>
<el-row
:gutter=
"20"
style=
"width: 1600px; margin: 0 auto; height: 5
05
px; margin-top: 16px"
>
<el-row
:gutter=
"20"
style=
"width: 1600px; margin: 0 auto; height: 5
40
px; margin-top: 16px"
>
<el-col
:span=
"8"
>
<el-col
:span=
"8"
>
<custom-container
title=
"实体领域分布"
:titleIcon=
"radarIcon"
height=
"
48
0px"
>
<custom-container
title=
"实体领域分布"
:titleIcon=
"radarIcon"
height=
"
54
0px"
>
<
template
#
header-right
>
<
template
#
header-right
>
<el-checkbox
v-model=
"domainChecked"
label=
"50%规则"
size=
"large"
/>
<el-checkbox
v-model=
"domainChecked"
label=
"50%规则"
size=
"large"
/>
</
template
>
</
template
>
<
template
#
default
>
<
template
#
default
>
<EChart
:option=
"radarOption"
autoresize
:style=
"
{ height: '460px' }" />
<EChart
:option=
"radarOption"
autoresize
:style=
"
{ height: '420px' }" />
<div
class=
"data-origin-box"
>
<div
class=
"data-origin-icon"
>
<img
:src=
"tipsIcon"
alt=
""
/>
</div>
<div
class=
"data-origin-text"
>
实体领域分布情况,数据来源:美国各行政机构官网
</div>
</div>
<div
class=
"ai-pane"
>
<AiButton
/>
<AiPane
:aiContent=
"radarChart.loading ? '解读生成中...' : radarChart.interpretation"
/>
</div>
</
template
>
</
template
>
</custom-container>
</custom-container>
</el-col>
</el-col>
<el-col
:span=
"16"
>
<el-col
:span=
"16"
>
<custom-container
title=
"实体清单数量增长趋势"
:titleIcon=
"qushiIcon"
height=
"
48
0px"
>
<custom-container
title=
"实体清单数量增长趋势"
:titleIcon=
"qushiIcon"
height=
"
54
0px"
>
<
template
#
header-right
>
<
template
#
header-right
>
<div
style=
"display: flex; align-items: center; gap: 16px"
>
<div
style=
"display: flex; align-items: center; gap: 16px"
>
<el-checkbox
v-model=
"trendChecked"
label=
"50%规则"
size=
"large"
/>
<el-checkbox
v-model=
"trendChecked"
label=
"50%规则"
size=
"large"
/>
...
@@ -390,13 +400,23 @@
...
@@ -390,13 +400,23 @@
</div>
</div>
</
template
>
</
template
>
<
template
#
default
>
<
template
#
default
>
<EChart
:option=
"trendOption"
autoresize
:style=
"
{ height: '400px' }" />
<EChart
:option=
"trendOption"
autoresize
:style=
"
{ height: '420px' }" />
<div
class=
"data-origin-box"
>
<div
class=
"data-origin-icon"
>
<img
:src=
"tipsIcon"
alt=
""
/>
</div>
<div
class=
"data-origin-text"
>
实体清单数量增长趋势情况,数据来源:美国各行政机构官网
</div>
</div>
<div
class=
"ai-pane"
>
<AiButton
/>
<AiPane
:aiContent=
"trendChart.loading ? '解读生成中...' : trendChart.interpretation"
/>
</div>
</
template
>
</
template
>
</custom-container>
</custom-container>
</el-col>
</el-col>
</el-row>
</el-row>
<el-row
:gutter=
"20"
style=
"width: 1600px; margin: 0 auto; margin-top: 39px"
>
<el-row
:gutter=
"20"
style=
"width: 1600px; margin: 0 auto; margin-top: 39px
; padding-bottom: 60px
"
>
<CustomTitle
id=
"position4"
title=
"资源库"
style=
"margin-top: 0px"
/>
<CustomTitle
id=
"position4"
title=
"资源库"
style=
"margin-top: 0px"
/>
<div
class=
"resource-tabs"
>
<div
class=
"resource-tabs"
>
<div
<div
...
@@ -714,11 +734,18 @@ import { ElMessage, ElMessageBox } from "element-plus";
...
@@ -714,11 +734,18 @@ import { ElMessage, ElMessageBox } from "element-plus";
import
{
DArrowRight
,
Warning
,
Search
}
from
"@element-plus/icons-vue"
;
import
{
DArrowRight
,
Warning
,
Search
}
from
"@element-plus/icons-vue"
;
import
EChart
from
"@/components/Chart/index.vue"
;
import
EChart
from
"@/components/Chart/index.vue"
;
import
tipsIcon
from
"./assets/icons/info-icon.png"
;
import
AiButton
from
"@/components/base/Ai/AiButton/index.vue"
;
import
AiPane
from
"@/components/base/Ai/AiPane/index.vue"
;
import
{
useChartInterpretation
}
from
"@/views/exportControl/utils/common"
;
const
sanctionCountChart
=
useChartInterpretation
();
import
{
TAGTYPE
}
from
"@/public/constant"
;
import
{
TAGTYPE
}
from
"@/public/constant"
;
import
{
useGotoCompanyPages
}
from
"@/router/modules/company"
;
import
{
useGotoCompanyPages
}
from
"@/router/modules/company"
;
import
{
useGotoNewsDetail
}
from
"@/router/modules/news"
;
import
{
useGotoNewsDetail
}
from
"@/router/modules/news"
;
const
gotoCompanyPages
=
useGotoCompanyPages
();
const
gotoCompanyPages
=
useGotoCompanyPages
();
const
gotoNewsDetail
=
useGotoNewsDetail
();
const
gotoNewsDetail
=
useGotoNewsDetail
();
const
trendChart
=
useChartInterpretation
();
const
radarChart
=
useChartInterpretation
();
import
{
useRouter
}
from
"vue-router"
;
import
{
useRouter
}
from
"vue-router"
;
...
@@ -1026,6 +1053,7 @@ const fetchTrendData = async () => {
...
@@ -1026,6 +1053,7 @@ const fetchTrendData = async () => {
});
});
if
(
res
&&
res
[
0
]
&&
res
[
0
].
yearDomainCount
)
{
if
(
res
&&
res
[
0
]
&&
res
[
0
].
yearDomainCount
)
{
trendOption
.
value
=
processYearDomainCountData
(
res
[
0
].
yearDomainCount
);
trendOption
.
value
=
processYearDomainCountData
(
res
[
0
].
yearDomainCount
);
trendChart
.
interpret
({
type
:
"柱状图"
,
name
:
"实体清单数量增长趋势"
,
data
:
res
[
0
].
yearDomainCount
});
}
}
}
catch
(
error
)
{
}
catch
(
error
)
{
console
.
error
(
"获取趋势图数据失败:"
,
error
);
console
.
error
(
"获取趋势图数据失败:"
,
error
);
...
@@ -1297,6 +1325,7 @@ const fetchRadarData = async checked => {
...
@@ -1297,6 +1325,7 @@ const fetchRadarData = async checked => {
}
}
};
};
});
});
radarChart
.
interpret
({
type
:
"雷达图"
,
name
:
"实体领域分布"
,
data
:
data
});
}
}
}
catch
(
error
)
{
}
catch
(
error
)
{
console
.
error
(
"获取雷达图数据失败:"
,
error
);
console
.
error
(
"获取雷达图数据失败:"
,
error
);
...
@@ -3573,7 +3602,7 @@ const handleMediaClick = item => {
...
@@ -3573,7 +3602,7 @@ const handleMediaClick = item => {
}
}
.scroll-main
{
.scroll-main
{
height
:
calc
(
100%
-
144px
)
!
important
;
//
height: calc(100% - 144px) !important;
}
}
.center-center
{
.center-center
{
...
@@ -3596,4 +3625,50 @@ const handleMediaClick = item => {
...
@@ -3596,4 +3625,50 @@ const handleMediaClick = item => {
background
:
rgba
(
255
,
255
,
255
,
1
);
background
:
rgba
(
255
,
255
,
255
,
1
);
}
}
}
}
.data-origin-box
{
width
:
100%
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
padding
:
22px
0
;
.data-origin-icon
{
width
:
16px
;
height
:
16px
;
font-size
:
0px
;
margin-right
:
8px
;
img
{
width
:
100%
;
height
:
100%
;
}
}
.data-origin-text
{
font-family
:
Source
Han
Sans
CN
;
font-size
:
14px
;
color
:
var
(
--
text-primary-50-color
);
}
}
.ai-pane
{
position
:
absolute
;
right
:
0px
;
bottom
:
15px
;
z-index
:
2
;
:deep
(
.ai-pane-wrapper
)
{
display
:
none
;
}
:deep
(
.ai-button-wrapper
)
{
display
:
flex
;
}
&
:hover
{
width
:
100%
;
bottom
:
0px
;
:deep
(
.ai-pane-wrapper
)
{
display
:
block
;
}
:deep
(
.ai-button-wrapper
)
{
display
:
none
;
}
}
}
</
style
>
</
style
>
src/views/exportControl/utils/common.js
0 → 100644
浏览文件 @
e4bc83d4
import
{
ref
}
from
"vue"
;
export
const
useChartInterpretation
=
()
=>
{
const
loading
=
ref
(
false
);
const
interpretation
=
ref
(
""
);
const
error
=
ref
(
null
);
const
interpret
=
async
text
=>
{
loading
.
value
=
true
;
error
.
value
=
null
;
interpretation
.
value
=
""
;
try
{
const
response
=
await
fetch
(
"/aiAnalysis/chart_interpretation"
,
{
method
:
"POST"
,
headers
:
{
"X-API-Key"
:
"aircasKEY19491001"
,
"Content-Type"
:
"application/json"
},
body
:
JSON
.
stringify
({
text
})
});
if
(
!
response
.
ok
)
{
throw
new
Error
(
`HTTP error! status:
${
response
.
status
}
`
);
}
const
reader
=
response
.
body
.
getReader
();
const
decoder
=
new
TextDecoder
();
let
buffer
=
""
;
while
(
true
)
{
const
{
done
,
value
}
=
await
reader
.
read
();
if
(
done
)
break
;
buffer
+=
decoder
.
decode
(
value
,
{
stream
:
true
});
const
lines
=
buffer
.
split
(
"
\
n"
);
buffer
=
lines
.
pop
()
||
""
;
for
(
const
line
of
lines
)
{
if
(
line
.
startsWith
(
"data: "
))
{
const
content
=
line
.
substring
(
6
);
const
textMatch
=
content
.
match
(
/"解读":
\s
*"
([^
"
]
*
)
"/
);
if
(
textMatch
&&
textMatch
[
1
])
{
interpretation
.
value
=
textMatch
[
1
];
}
}
}
}
}
catch
(
err
)
{
error
.
value
=
err
.
message
||
"AI 解读失败"
;
console
.
error
(
"AI Chart Interpretation Error:"
,
err
);
}
finally
{
loading
.
value
=
false
;
}
};
return
{
loading
,
interpretation
,
error
,
interpret
};
};
src/views/exportControl/v2.0EntityList/components/dataStatistics/index.vue
浏览文件 @
e4bc83d4
差异被折叠。
点击展开。
src/views/exportControl/v2.0EntityList/index.vue
浏览文件 @
e4bc83d4
...
@@ -12,7 +12,7 @@
...
@@ -12,7 +12,7 @@
{{
headerTitle
.
department
}}
{{
headerTitle
.
department
}}
</div>
</div>
</div>
</div>
<
div
class=
"btn"
><img
:src=
"icon01"
alt=
""
/>
切换
</div
>
<
!--
<div
class=
"btn"
><img
:src=
"icon01"
alt=
""
/>
切换
</div>
--
>
</div>
</div>
<div
class=
"header-nav"
>
<div
class=
"header-nav"
>
<div
<div
...
...
src/views/exportControl/v2.0SingleSanction/components/dataStatistics/index.vue
浏览文件 @
e4bc83d4
差异被折叠。
点击展开。
src/views/exportControl/v2.0SingleSanction/components/deepMining/components/RelationGraph.vue
浏览文件 @
e4bc83d4
...
@@ -23,7 +23,7 @@
...
@@ -23,7 +23,7 @@
</div>
</div>
</div>
</div>
<div
ref=
"containerRef"
class=
"graph-container"
></div>
<div
ref=
"containerRef"
class=
"graph-container"
></div>
<!--
<GraphChart
v-if=
"currentLayoutType === 1"
:nodes=
"graphNodes"
:links=
"graphLinks"
/>
-->
<div
v-if=
"selectedNode"
class=
"node-popup"
>
<div
v-if=
"selectedNode"
class=
"node-popup"
>
<div
class=
"popup-header"
>
<div
class=
"popup-header"
>
<img
:src=
"selectedNode.image || defaultIcon"
alt=
""
class=
"popup-icon"
/>
<img
:src=
"selectedNode.image || defaultIcon"
alt=
""
class=
"popup-icon"
/>
...
@@ -55,6 +55,8 @@ import echartsIcon02 from "../assets/echartsIcon02.png";
...
@@ -55,6 +55,8 @@ import echartsIcon02 from "../assets/echartsIcon02.png";
import
echartsIcon03
from
"../assets/echartsIcon03.png"
;
import
echartsIcon03
from
"../assets/echartsIcon03.png"
;
import
defaultIcon
from
"../assets/echartsIcon03.png"
;
import
defaultIcon
from
"../assets/echartsIcon03.png"
;
// import GraphChart from "@/components/base/GraphChart/index.vue";
import
GraphChart
from
"@/views/companyPages2/component/SupplyChain/GraphChart.vue"
;
import
{
getSingleSanctionEntityInfo
}
from
"@/api/exportControlV2.0"
;
import
{
getSingleSanctionEntityInfo
}
from
"@/api/exportControlV2.0"
;
const
props
=
defineProps
({
const
props
=
defineProps
({
...
@@ -107,7 +109,7 @@ const initGraph = (layoutType = 1) => {
...
@@ -107,7 +109,7 @@ const initGraph = (layoutType = 1) => {
const
initNormalGraph
=
(
layoutType
,
width
,
height
)
=>
{
const
initNormalGraph
=
(
layoutType
,
width
,
height
)
=>
{
const
data
=
processGraphData
(
props
.
graphData
);
const
data
=
processGraphData
(
props
.
graphData
);
console
.
log
(
"初始数据"
,
props
.
graphData
);
if
(
!
data
.
nodes
||
data
.
nodes
.
length
===
0
)
return
;
if
(
!
data
.
nodes
||
data
.
nodes
.
length
===
0
)
return
;
const
layout
=
{
const
layout
=
{
...
@@ -653,6 +655,56 @@ const bindGraphEvents = () => {
...
@@ -653,6 +655,56 @@ const bindGraphEvents = () => {
});
});
};
};
// 将传入的 graphData 转换为 GraphChart.vue 需要的格式
// GraphChart.vue 需要节点有 x, y 坐标,所以我们需要一个简单的布局算法
const
graphNodes
=
ref
([]);
const
graphLinks
=
ref
([]);
const
applyStarLayout
=
(
rawNodes
,
rawLinks
)
=>
{
if
(
!
rawNodes
?.
length
)
return
{
nodes
:
[],
links
:
[]
};
const
centerX
=
0
;
const
centerY
=
0
;
const
radius
=
200
;
// 环绕半径
const
nodes
=
rawNodes
.
map
((
node
,
index
)
=>
{
let
x
,
y
;
if
(
index
===
0
)
{
// 中心节点
x
=
centerX
;
y
=
centerY
;
}
else
{
// 其他节点均匀分布在圆周上
const
angle
=
(
2
*
Math
.
PI
*
(
index
-
1
))
/
(
rawNodes
.
length
-
1
);
x
=
centerX
+
radius
*
Math
.
cos
(
angle
);
y
=
centerY
+
radius
*
Math
.
sin
(
angle
);
}
return
{
id
:
String
(
node
.
id
??
index
),
name
:
node
.
name
||
""
,
type
:
node
.
isSanctioned
?
"sanctioned"
:
"normal"
,
// 用于区分样式(如果需要)
symbolSize
:
node
.
symbolSize
||
(
index
===
0
?
60
:
40
),
symbol
:
`image://
${
node
.
image
||
defaultIcon
}
`
,
isSanctioned
:
node
.
isSanctioned
,
image
:
node
.
image
||
defaultIcon
,
x
:
x
,
y
:
y
,
...
node
// 透传其他字段
};
});
const
links
=
(
rawLinks
||
[]).
map
(
link
=>
({
source
:
String
(
link
.
source
),
target
:
String
(
link
.
target
),
type
:
link
.
name
||
"relation"
,
// GraphChart.vue 使用 type 字段
label
:
{
show
:
true
,
formatter
:
link
.
name
||
""
}
}));
return
{
nodes
,
links
};
};
const
handleClickControlBtn
=
btn
=>
{
const
handleClickControlBtn
=
btn
=>
{
currentLayoutType
.
value
=
btn
;
currentLayoutType
.
value
=
btn
;
emit
(
"layoutChange"
,
btn
);
emit
(
"layoutChange"
,
btn
);
...
@@ -675,6 +727,16 @@ const handleResize = () => {
...
@@ -675,6 +727,16 @@ const handleResize = () => {
}
}
};
};
watch
(
()
=>
props
.
graphData
,
newVal
=>
{
const
{
nodes
,
links
}
=
applyStarLayout
(
newVal
.
nodes
,
newVal
.
links
);
graphNodes
.
value
=
JSON
.
parse
(
JSON
.
stringify
(
nodes
));
graphLinks
.
value
=
JSON
.
parse
(
JSON
.
stringify
(
links
));
},
{
deep
:
true
,
immediate
:
true
}
);
watch
(
watch
(
()
=>
props
.
graphData
,
()
=>
props
.
graphData
,
()
=>
{
()
=>
{
...
...
src/views/exportControl/v2.0SingleSanction/components/impactAnalysis/components/industrialImpact/index.vue
浏览文件 @
e4bc83d4
差异被折叠。
点击展开。
src/views/exportControl/v2.0SingleSanction/components/impactAnalysis/components/researchImpact/index.vue
浏览文件 @
e4bc83d4
差异被折叠。
点击展开。
src/views/exportControl/v2.0SingleSanction/index.vue
浏览文件 @
e4bc83d4
...
@@ -12,7 +12,7 @@
...
@@ -12,7 +12,7 @@
{{
headerTitle
.
department
}}
{{
headerTitle
.
department
}}
</div>
</div>
</div>
</div>
<div
class=
"btn"
><img
:src=
"icon01"
alt=
""
/>
切换
</div>
<div
class=
"btn"
@
click=
"openSanctionModal"
><img
:src=
"icon01"
alt=
""
/>
切换
</div>
</div>
</div>
<div
class=
"header-nav"
>
<div
class=
"header-nav"
>
<div
<div
...
@@ -44,12 +44,46 @@
...
@@ -44,12 +44,46 @@
<deep-mining
v-if=
"activeIndex === 2"
></deep-mining>
<deep-mining
v-if=
"activeIndex === 2"
></deep-mining>
<impact-analysis
v-if=
"activeIndex === 3"
></impact-analysis>
<impact-analysis
v-if=
"activeIndex === 3"
></impact-analysis>
</div>
</div>
<el-dialog
v-model=
"sanctionModalVisible"
title=
"制裁事件列表"
width=
"600px"
:close-on-click-modal=
"false"
@
close=
"resetModal"
>
<div
class=
"sanction-list"
>
<div
v-for=
"item in sanctionList"
:key=
"item.id"
class=
"sanction-item"
:class=
"
{ active: selectedSanctionId === item.id }"
@click="selectSanction(item)"
>
{{
item
.
name
}}
</div>
</div>
<template
#
footer
>
<div
class=
"pagination-footer"
>
<el-pagination
v-model:current-page=
"currentPage"
v-model:page-size=
"pageSize"
:total=
"totalElements"
:page-sizes=
"[10]"
layout=
"total, prev, pager, next"
background
@
current-change=
"handlePageChange"
/>
</div>
</
template
>
</el-dialog>
</div>
</div>
</template>
</template>
<
script
setup
>
<
script
setup
>
import
{
ref
,
onMounted
}
from
"vue"
;
import
{
ref
,
onMounted
}
from
"vue"
;
import
{
ElDialog
,
ElPagination
}
from
"element-plus"
;
import
sanctionsOverview
from
"./components/sanctionsOverview/index.vue"
;
import
sanctionsOverview
from
"./components/sanctionsOverview/index.vue"
;
import
dataStatistics
from
"./components/dataStatistics/index.vue"
;
import
dataStatistics
from
"./components/dataStatistics/index.vue"
;
import
deepMining
from
"./components/deepMining/index.vue"
;
import
deepMining
from
"./components/deepMining/index.vue"
;
...
@@ -67,6 +101,7 @@ import icon3 from "../assets/icons/icon3.png";
...
@@ -67,6 +101,7 @@ import icon3 from "../assets/icons/icon3.png";
import
icon3Active
from
"../assets/icons/icon3_active.png"
;
import
icon3Active
from
"../assets/icons/icon3_active.png"
;
import
{
getSingleSanctionOverview
}
from
"@/api/exportControlV2.0.js"
;
import
{
getSingleSanctionOverview
}
from
"@/api/exportControlV2.0.js"
;
import
{
getSanctionProcess
}
from
"@/api/exportControl"
;
import
router
from
"@/router"
;
import
router
from
"@/router"
;
// 处理点击实体清单原文按钮
// 处理点击实体清单原文按钮
...
@@ -157,6 +192,77 @@ const handleAnalysisClick = () => {
...
@@ -157,6 +192,77 @@ const handleAnalysisClick = () => {
});
});
};
};
// ========== 新增响应式状态 ==========
const
sanctionModalVisible
=
ref
(
false
);
const
sanctionList
=
ref
([]);
const
selectedSanctionId
=
ref
(
null
);
const
currentPage
=
ref
(
1
);
const
pageSize
=
ref
(
10
);
const
totalElements
=
ref
(
0
);
// ========== 打开弹窗并加载第一页 ==========
const
openSanctionModal
=
async
()
=>
{
sanctionModalVisible
.
value
=
true
;
console
.
log
(
"制裁事件列表11:"
,
sanctionList
.
value
);
await
fetchSanctionData
();
};
// ========== 获取制裁数据 ==========
const
fetchSanctionData
=
async
()
=>
{
try
{
const
res
=
await
getSanctionProcess
([
1
],
currentPage
.
value
,
10
);
if
(
res
&&
!!
res
.
content
)
{
sanctionList
.
value
=
res
.
content
||
[];
totalElements
.
value
=
res
.
totalElements
||
0
;
// 如果当前选中的不在新数据中,清空选中
if
(
selectedSanctionId
.
value
&&
!
sanctionList
.
value
.
some
(
item
=>
item
.
id
===
selectedSanctionId
.
value
))
{
selectedSanctionId
.
value
=
null
;
}
console
.
log
(
"制裁事件列表:"
,
sanctionList
.
value
);
}
else
{
sanctionList
.
value
=
[];
totalElements
.
value
=
0
;
}
}
catch
(
error
)
{
console
.
error
(
"获取制裁事件失败:"
,
error
);
sanctionList
.
value
=
[];
totalElements
.
value
=
0
;
}
};
// ========== 翻页处理 ==========
const
handlePageChange
=
async
newPage
=>
{
currentPage
.
value
=
newPage
;
await
fetchSanctionData
();
};
// ========== 选择某项 ==========
const
selectSanction
=
item
=>
{
selectedSanctionId
.
value
=
item
.
id
;
// 可在此处触发其他逻辑,如查看详情
// 替换当前路由参数,并重新加载数据
router
.
replace
({
path
:
window
.
location
.
pathname
,
query
:
{
id
:
item
.
id
,
sanTypeId
:
item
.
sanTypeId
}
});
// 3. 立即重新加载数据(关键!)
getSingleSanctionOverviewData
();
// 4. 可选:关闭弹窗
sanctionModalVisible
.
value
=
false
;
};
// ========== 关闭弹窗时重置 ==========
const
resetModal
=
()
=>
{
sanctionList
.
value
=
[];
selectedSanctionId
.
value
=
null
;
currentPage
.
value
=
1
;
totalElements
.
value
=
0
;
};
onMounted
(()
=>
{
onMounted
(()
=>
{
getUrlParams
();
getUrlParams
();
getSingleSanctionOverviewData
();
getSingleSanctionOverviewData
();
...
@@ -350,4 +456,40 @@ onMounted(() => {
...
@@ -350,4 +456,40 @@ onMounted(() => {
background-color
:
#f7f8f9
;
background-color
:
#f7f8f9
;
}
}
}
}
.sanction-list
{
max-height
:
400px
;
overflow-y
:
auto
;
padding
:
0
10px
;
}
.sanction-item
{
padding
:
7px
;
margin
:
6px
0
;
border-radius
:
4px
;
cursor
:
pointer
;
font-size
:
14px
;
color
:
#333
;
transition
:
background-color
0
.2s
;
}
.sanction-item
:hover
{
background-color
:
#f5f7fa
;
}
.sanction-item.active
{
background-color
:
#e6f0ff
;
color
:
#1890ff
;
font-weight
:
bold
;
}
.pagination-footer
{
display
:
flex
;
justify-content
:
center
;
margin-top
:
12px
;
}
:deep
(
.el-pagination.is-background
.el-pager
li
:not
(
.is-disabled
)
.is-active
)
{
background-color
:
#0e78f1
;
}
</
style
>
</
style
>
src/views/exportControl/v2.0SingleSanction/mock.json
0 → 100644
浏览文件 @
e4bc83d4
差异被折叠。
点击展开。
src/views/thinkTank/ReportDetail/index.vue
浏览文件 @
e4bc83d4
...
@@ -14,13 +14,17 @@
...
@@ -14,13 +14,17 @@
<div
class=
"tag"
>
{{
value
.
industryName
}}
</div>
<div
class=
"tag"
>
{{
value
.
industryName
}}
</div>
</div>
-->
</div>
-->
<AreaTag
v-for=
"value, index in thinkInfo.tags"
:key=
"index"
:tagName=
"value.industryName"
></AreaTag>
<AreaTag
v-for=
"(value, index) in thinkInfo.tags"
:key=
"index"
:tagName=
"value.industryName"
></AreaTag>
</div>
</div>
</div>
</div>
</div>
</div>
<div
class=
"header-top-right"
>
<div
class=
"header-top-right"
>
<div
class=
"image-name-box"
>
<div
class=
"image-name-box"
>
<div
class=
"image"
>
<img
:src=
thinkInfo.thinkTankLogoUrl
alt=
""
/></div>
<div
class=
"image"
>
<img
:src=
"thinkInfo.thinkTankLogoUrl"
alt=
""
/></div>
<div
class=
"name"
>
{{
thinkInfo
.
thinkTankName
}}
</div>
<div
class=
"name"
>
{{
thinkInfo
.
thinkTankName
}}
</div>
</div>
</div>
<div
class=
"time"
>
{{
thinkInfo
.
times
}}
</div>
<div
class=
"time"
>
{{
thinkInfo
.
times
}}
</div>
...
@@ -95,7 +99,7 @@ const router = useRouter();
...
@@ -95,7 +99,7 @@ const router = useRouter();
const
route
=
useRoute
();
const
route
=
useRoute
();
const
reportUrl
=
ref
(
""
);
const
reportUrl
=
ref
(
""
);
const
thinkInfo
=
ref
({});
const
thinkInfo
=
ref
({});
const
reportList
=
ref
({})
const
reportList
=
ref
({})
;
// 获取报告全局信息
// 获取报告全局信息
const
handleGetThinkTankReportSummary
=
async
()
=>
{
const
handleGetThinkTankReportSummary
=
async
()
=>
{
...
@@ -105,7 +109,7 @@ const handleGetThinkTankReportSummary = async () => {
...
@@ -105,7 +109,7 @@ const handleGetThinkTankReportSummary = async () => {
if
(
res
.
code
===
200
&&
res
.
data
)
{
if
(
res
.
code
===
200
&&
res
.
data
)
{
reportUrl
.
value
=
res
.
data
.
reportUrl
;
reportUrl
.
value
=
res
.
data
.
reportUrl
;
thinkInfo
.
value
=
res
.
data
;
thinkInfo
.
value
=
res
.
data
;
console
.
log
(
reportUrl
.
value
,
'reportUrl.value'
)
console
.
log
(
reportUrl
.
value
,
"reportUrl.value"
);
}
}
}
catch
(
error
)
{
}
catch
(
error
)
{
console
.
error
(
"获取报告全局信息error"
,
error
);
console
.
error
(
"获取报告全局信息error"
,
error
);
...
@@ -117,9 +121,7 @@ const handleGetThinkTankReport = async () => {
...
@@ -117,9 +121,7 @@ const handleGetThinkTankReport = async () => {
const
res
=
await
getThinkTankReportRelated
(
router
.
currentRoute
.
_value
.
params
.
id
);
const
res
=
await
getThinkTankReportRelated
(
router
.
currentRoute
.
_value
.
params
.
id
);
console
.
log
(
"报告全局信息"
,
res
);
console
.
log
(
"报告全局信息"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
if
(
res
.
code
===
200
&&
res
.
data
)
{
reportList
.
value
=
res
.
data
;
reportList
.
value
=
res
.
data
;
}
}
}
catch
(
error
)
{
}
catch
(
error
)
{
console
.
error
(
"获取相关报告error"
,
error
);
console
.
error
(
"获取相关报告error"
,
error
);
...
@@ -133,6 +135,8 @@ const toReport = () => {
...
@@ -133,6 +135,8 @@ const toReport = () => {
id
:
router
.
currentRoute
.
_value
.
params
.
id
id
:
router
.
currentRoute
.
_value
.
params
.
id
}
}
});
});
console
.
log
(
"route.href"
,
route
.
href
);
window
.
open
(
route
.
href
,
"_blank"
);
window
.
open
(
route
.
href
,
"_blank"
);
};
};
const
tabActiveName
=
ref
(
"报告分析"
);
const
tabActiveName
=
ref
(
"报告分析"
);
...
@@ -167,7 +171,7 @@ const goToOfficialWebsite = () => {
...
@@ -167,7 +171,7 @@ const goToOfficialWebsite = () => {
const
downloadOnePdf
=
async
(
url
,
filename
)
=>
{
const
downloadOnePdf
=
async
(
url
,
filename
)
=>
{
const
response
=
await
fetch
(
url
,
{
const
response
=
await
fetch
(
url
,
{
method
:
"GET"
,
method
:
"GET"
,
headers
:
{
"Content-Type"
:
"application/pdf"
}
,
headers
:
{
"Content-Type"
:
"application/pdf"
}
});
});
if
(
!
response
.
ok
)
throw
new
Error
(
`HTTP error! status:
${
response
.
status
}
`
);
if
(
!
response
.
ok
)
throw
new
Error
(
`HTTP error! status:
${
response
.
status
}
`
);
const
blob
=
await
response
.
blob
();
const
blob
=
await
response
.
blob
();
...
@@ -209,10 +213,9 @@ const handleDownloadDocument = async () => {
...
@@ -209,10 +213,9 @@ const handleDownloadDocument = async () => {
try
{
try
{
const
{
ElMessage
}
=
await
import
(
"element-plus"
);
const
{
ElMessage
}
=
await
import
(
"element-plus"
);
ElMessage
.
error
(
"PDF 下载失败,请稍后重试"
);
ElMessage
.
error
(
"PDF 下载失败,请稍后重试"
);
}
catch
(
_
)
{
}
}
catch
(
_
)
{}
}
}
};
};
</
script
>
</
script
>
<
style
lang=
"scss"
scoped
>
<
style
lang=
"scss"
scoped
>
...
@@ -305,7 +308,6 @@ const handleDownloadDocument = async () => {
...
@@ -305,7 +308,6 @@ const handleDownloadDocument = async () => {
line-height
:
24px
;
line-height
:
24px
;
letter-spacing
:
0px
;
letter-spacing
:
0px
;
text-align
:
right
;
text-align
:
right
;
}
}
.image
{
.image
{
...
@@ -314,12 +316,9 @@ const handleDownloadDocument = async () => {
...
@@ -314,12 +316,9 @@ const handleDownloadDocument = async () => {
margin-top
:
5px
;
margin-top
:
5px
;
img
{
img
{
width
:
100%
;
width
:
100%
;
height
:
100%
;
height
:
100%
;
}
}
}
}
}
}
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论