Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
risk-monitor
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
蔡建
risk-monitor
Commits
04628bc9
提交
04628bc9
authored
4月 21, 2026
作者:
张烨
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat:封装AI智能报告组件
上级
0204674d
隐藏空白字符变更
内嵌
并排
正在显示
2 个修改的文件
包含
147 行增加
和
67 行删除
+147
-67
AiReport.vue
...arketAccessRestrictions/marketAccessHome/com/AiReport.vue
+116
-0
index.vue
...views/marketAccessRestrictions/marketAccessHome/index.vue
+31
-67
没有找到文件。
src/views/marketAccessRestrictions/marketAccessHome/com/AiReport.vue
0 → 100644
浏览文件 @
04628bc9
<
template
>
<div
class=
"view-box"
@
mouseenter=
"handleMouseEnter"
@
mouseleave=
"handleMouseLeave"
>
<AiButton
/>
<AiPane
:aiContent=
"myParams.content"
/>
</div>
</
template
>
<
script
setup
lang=
"ts"
name=
"AiReport"
>
import
{
reactive
}
from
"vue"
import
AiButton
from
'@/components/base/Ai/AiButton/index.vue'
;
import
AiPane
from
'@/components/base/Ai/AiPane/index.vue'
;
const
myParams
=
reactive
({
data
:
""
,
content
:
""
,
isState
:
false
,
})
const
onDataInfo
=
(
event
:
any
)
=>
{
console
.
log
(
"需要分析的数据"
,
event
);
myParams
.
isState
=
false
;
myParams
.
data
=
JSON
.
stringify
(
event
);
}
let
controller
=
null
;
let
reader
=
null
;
// 鼠标进入监听
const
handleMouseEnter
=
async
()
=>
{
if
(
myParams
.
isState
)
return
;
myParams
.
content
=
"正在生成..."
;
if
(
controller
)
controller
.
abort
();
controller
=
new
AbortController
();
try
{
const
res
=
await
fetch
(
'/aiAnalysis/chart_interpretation'
,
{
method
:
'POST'
,
headers
:
{
"X-API-Key"
:
"aircasKEY19491001"
,
'Content-Type'
:
'application/json'
,
},
body
:
JSON
.
stringify
({
text
:
myParams
.
data
}),
signal
:
controller
.
signal
});
if
(
!
res
.
ok
)
throw
new
Error
(
`HTTP
${
res
.
status
}
`
);
reader
=
res
.
body
.
getReader
();
const
decoder
=
new
TextDecoder
();
while
(
true
)
{
const
{
done
,
value
}
=
await
reader
.
read
();
if
(
done
)
break
;
const
chunk
=
decoder
.
decode
(
value
,
{
stream
:
true
});
const
match
=
chunk
.
match
(
/"解读":
\s
*"
([^
"
]
*
)
"/
);
if
(
match
?.[
1
])
{
myParams
.
content
=
match
[
1
];
myParams
.
isState
=
true
;
return
;
// 获取到结果直接返回
}
}
myParams
.
content
=
"未获取到解读内容"
;
}
catch
(
err
)
{
myParams
.
content
=
"系统异常,生成失败"
;
}
finally
{
reader
?.
cancel
();
reader
=
null
;
}
};
// 鼠标离开监听
const
handleMouseLeave
=
()
=>
{
controller
?.
abort
();
reader
?.
cancel
();
controller
=
null
;
reader
=
null
;
};
defineExpose
({
onDataInfo
})
</
script
>
<
style
scoped
lang=
"scss"
>
.view-box
{
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
>
\ No newline at end of file
src/views/marketAccessRestrictions/marketAccessHome/index.vue
浏览文件 @
04628bc9
...
...
@@ -98,10 +98,7 @@
<
div
v
-
if
=
"box5ChartData.title.length"
style
=
"width: 100%; height: 100%;"
ref
=
"box5Ref"
><
/div
>
<
/div
>
<
TipTab
text
=
"数据来源:美国国际贸易委员会、商务部、贸易代表办公室官网"
style
=
"margin-top: 16px;"
/>
<
div
class
=
"ai-pane"
>
<
AiButton
/>
<
AiPane
:
aiContent
=
"aiContent.content5"
/>
<
/div
>
<
AiReport
ref
=
"refAiReport5"
><
/AiReport
>
<
/div
>
<
/OverviewNormalBox
>
<
/div
>
...
...
@@ -123,10 +120,7 @@
<
div
v
-
if
=
"box6Data.title.length"
style
=
"width: 100%; height: 100%;"
id
=
"box6Chart"
><
/div
>
<
/div
>
<
TipTab
text
=
"数据来源:美国国际贸易委员会、商务部、贸易代表办公室官网"
style
=
"padding-right: 50px;"
/>
<
div
class
=
"ai-pane"
>
<
AiButton
/>
<
AiPane
:
aiContent
=
"aiContent.content6"
/>
<
/div
>
<
AiReport
ref
=
"refAiReport6"
><
/AiReport
>
<
/div
>
<
/OverviewNormalBox
>
<
/div
>
...
...
@@ -155,10 +149,7 @@
<
div
v
-
if
=
"box7Data.data.length"
style
=
"width: 100%; height: 100%;"
id
=
"box7Chart"
><
/div
>
<
/div
>
<
TipTab
:
text
=
"`数据来源:${box7TipText
}
`"
style
=
"margin-top: 10px;"
/>
<
div
class
=
"ai-pane"
>
<
AiButton
/>
<
AiPane
:
aiContent
=
"aiContent.content7"
/>
<
/div
>
<
AiReport
ref
=
"refAiReport7"
><
/AiReport
>
<
/div
>
<
/OverviewNormalBox
>
<
/div
>
...
...
@@ -180,10 +171,7 @@
<
div
v
-
if
=
"box8Data.length"
style
=
"width: 100%; height: 100%;"
ref
=
"box8Ref"
><
/div
>
<
/div
>
<
TipTab
:
text
=
"`数据来源:${box8TipText
}
`"
style
=
"padding-right: 50px;"
/>
<
div
class
=
"ai-pane"
>
<
AiButton
/>
<
AiPane
:
aiContent
=
"aiContent.content8"
/>
<
/div
>
<
AiReport
ref
=
"refAiReport8"
><
/AiReport
>
<
/div
>
<
/OverviewNormalBox
>
<
/div
>
...
...
@@ -300,7 +288,7 @@ import CarouselItem301 from '@/views/marketAccessRestrictions/marketAccessHome/c
import
CarouselItem232
from
'@/views/marketAccessRestrictions/marketAccessHome/com/CarouselItem232.vue'
;
import
setChart
from
"@/utils/setChart"
;
import
{
getDateBefore
,
get
AIReport
,
get
NearYearList
}
from
"@/views/marketAccessRestrictions/utils/index.ts"
;
import
{
getDateBefore
,
getNearYearList
}
from
"@/views/marketAccessRestrictions/utils/index.ts"
;
import
router
from
"@/router"
;
import
{
navigateToViewRiskSignal
}
from
"@/utils/riskSignalOverviewNavigate"
;
...
...
@@ -308,8 +296,7 @@ import createLineChart from "@/views/marketAccessRestrictions/utils/baseLineChar
import
createPieChart
from
"@/views/marketAccessRestrictions/utils/basePiechart.js"
;
import
getRadarChart
from
"./utils/radarChart"
;
import
getBarChart
from
"./utils/barChart1"
;
import
AiButton
from
'@/components/base/Ai/AiButton/index.vue'
;
import
AiPane
from
'@/components/base/Ai/AiPane/index.vue'
;
import
AiReport
from
'@/views/marketAccessRestrictions/marketAccessHome/com/AiReport.vue'
;
import
{
getPersonSummaryInfo
}
from
"@/api/common/index"
;
import
{
...
...
@@ -332,15 +319,10 @@ import tipsTcon from "./assets/icons/tips-icon.png";
const
getCardClass
=
(
code
)
=>
[
'theme-card'
,
`theme-${code
}
`
]
// 获取AI智能报告
const
aiContent
=
reactive
({
content5
:
"正在生成..."
,
content6
:
"正在生成..."
,
content7
:
"正在生成..."
,
content8
:
"正在生成..."
,
}
)
const
onAIReport
=
(
data
,
key
)
=>
{
getAIReport
(
data
).
then
(
res
=>
{
aiContent
[
key
]
=
res
}
)
}
const
refAiReport5
=
ref
(
null
)
const
refAiReport6
=
ref
(
null
)
const
refAiReport7
=
ref
(
null
)
const
refAiReport8
=
ref
(
null
)
const
handleToPosi
=
id
=>
{
const
element
=
document
.
getElementById
(
id
);
...
...
@@ -663,7 +645,6 @@ const hadleGetStatNum = async (event) => {
}
else
{
box5ChartData
.
value
=
transformAllData
(
res
.
data
);
}
onAIReport
({
type
:
"折线图"
,
name
:
"数量变化趋势"
,
data
:
res
.
data
}
,
"content5"
)
}
else
{
box5ChartData
.
value
.
title
=
[];
box5ChartData
.
value
.
list
=
[
...
...
@@ -671,7 +652,6 @@ const hadleGetStatNum = async (event) => {
{
name
:
"301调查"
,
value
:
[]
}
,
{
name
:
"232调查"
,
value
:
[]
}
]
aiContent
.
content5
=
""
;
}
}
catch
(
error
)
{
box5ChartData
.
value
.
title
=
[];
...
...
@@ -680,8 +660,8 @@ const hadleGetStatNum = async (event) => {
{
name
:
"301调查"
,
value
:
[]
}
,
{
name
:
"232调查"
,
value
:
[]
}
]
aiContent
.
content5
=
""
;
}
refAiReport5
.
value
?.
onDataInfo
({
type
:
"折线图"
,
name
:
"数量变化趋势"
,
data
:
box5ChartData
.
value
}
)
nextTick
(()
=>
{
createLineChart
(
box5Ref
,
box5ChartData
.
value
)
}
)
}
;
...
...
@@ -707,17 +687,11 @@ const handleGetStatArea = async () => {
const
res
=
await
getStatArea
(
params
);
console
.
log
(
"领域分布情况"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
const
arr
=
res
.
data
.
map
(
item
=>
{
return
item
.
areaname
;
}
);
const
arr
=
res
.
data
.
map
(
item
=>
item
.
areaname
);
box6Data
.
value
.
title
=
[...
new
Set
(
arr
)];
const
arr1
=
res
.
data
.
filter
(
item
=>
{
return
item
.
sortname
===
"337调查"
;
}
);
const
arr1Name
=
arr1
.
map
(
item
=>
{
return
item
.
areaname
;
}
);
const
arr1
=
res
.
data
.
filter
(
item
=>
item
.
sortname
===
"337调查"
);
const
arr1Name
=
arr1
.
map
(
item
=>
item
.
areaname
);
box6Data
.
value
.
title
.
forEach
((
item
,
index
)
=>
{
if
(
arr1Name
.
indexOf
(
item
)
>
-
1
)
{
const
idx
=
arr1Name
.
indexOf
(
item
);
...
...
@@ -727,12 +701,8 @@ const handleGetStatArea = async () => {
}
}
);
const
arr2
=
res
.
data
.
filter
(
item
=>
{
return
item
.
sortname
===
"232调查"
;
}
);
const
arr2Name
=
arr2
.
map
(
item
=>
{
return
item
.
areaname
;
}
);
const
arr2
=
res
.
data
.
filter
(
item
=>
item
.
sortname
===
"232调查"
);
const
arr2Name
=
arr2
.
map
(
item
=>
item
.
areaname
);
box6Data
.
value
.
title
.
forEach
((
item
,
index
)
=>
{
if
(
arr2Name
.
indexOf
(
item
)
>
-
1
)
{
const
idx
=
arr2Name
.
indexOf
(
item
);
...
...
@@ -742,12 +712,8 @@ const handleGetStatArea = async () => {
}
}
);
const
arr3
=
res
.
data
.
filter
(
item
=>
{
return
item
.
sortname
===
"301调查"
;
}
);
const
arr3Name
=
arr3
.
map
(
item
=>
{
return
item
.
areaname
;
}
);
const
arr3
=
res
.
data
.
filter
(
item
=>
item
.
sortname
===
"301调查"
);
const
arr3Name
=
arr3
.
map
(
item
=>
item
.
areaname
);
box6Data
.
value
.
title
.
forEach
((
item
,
index
)
=>
{
if
(
arr3Name
.
indexOf
(
item
)
>
-
1
)
{
const
idx
=
arr3Name
.
indexOf
(
item
);
...
...
@@ -756,14 +722,8 @@ const handleGetStatArea = async () => {
box6Data
.
value
.
data
[
2
].
value
[
index
]
=
0
;
}
}
);
const
numArr
=
res
.
data
.
map
(
item
=>
{
return
item
.
AREACOUNT
;
}
);
const
numArr
=
res
.
data
.
map
(
item
=>
item
.
AREACOUNT
);
box6Data
.
value
.
maxNum
=
Math
.
max
(...
numArr
);
onAIReport
({
type
:
"雷达图"
,
name
:
"领域分布情况"
,
data
:
res
.
data
}
,
"content6"
)
}
else
{
box6Data
.
value
.
title
=
[];
box6Data
.
value
.
data
=
[
...
...
@@ -772,9 +732,17 @@ const handleGetStatArea = async () => {
{
name
:
"301调查"
,
value
:
[]
}
];
box6Data
.
value
.
maxNum
=
0
;
aiContent
.
content6
=
""
;
}
}
catch
(
error
)
{
}
}
catch
(
error
)
{
box6Data
.
value
.
title
=
[];
box6Data
.
value
.
data
=
[
{
name
:
"337调查"
,
value
:
[]
}
,
{
name
:
"232调查"
,
value
:
[]
}
,
{
name
:
"301调查"
,
value
:
[]
}
];
box6Data
.
value
.
maxNum
=
0
;
}
refAiReport6
.
value
?.
onDataInfo
({
type
:
"雷达图"
,
name
:
"领域分布情况"
,
data
:
box6Data
.
value
}
)
}
;
const
handleBox6
=
async
()
=>
{
await
handleGetStatArea
();
...
...
@@ -814,17 +782,15 @@ const handleGetBox7Data = async () => {
box7Data
.
data
=
res
.
data
.
map
(
item
=>
{
return
item
.
NUM
;
}
);
onAIReport
({
type
:
"柱状图"
,
name
:
"国家分布情况"
,
data
:
res
.
data
}
,
"content7"
)
}
else
{
box7Data
.
title
=
[];
box7Data
.
data
=
[];
aiContent
.
content7
=
""
;
}
}
catch
(
error
)
{
box7Data
.
title
=
[];
box7Data
.
data
=
[];
aiContent
.
content7
=
""
;
}
refAiReport7
.
value
?.
onDataInfo
({
type
:
"柱状图"
,
name
:
"国家分布情况"
,
data
:
box7Data
}
)
}
;
const
handleBox7
=
async
()
=>
{
...
...
@@ -854,15 +820,13 @@ const handleGetBox8Data = async () => {
console
.
log
(
"结果分布情况"
,
res
);
if
(
res
.
code
===
200
&&
res
.
data
)
{
box8Data
.
value
=
res
.
data
.
map
(
item
=>
({
name
:
item
.
RESULTNAME
,
value
:
item
.
RESULTNUM
}
))
onAIReport
({
type
:
"环形图"
,
name
:
"结果分布情况"
,
data
:
res
.
data
}
,
"content8"
)
}
else
{
box8Data
.
value
=
[]
aiContent
.
content8
=
""
;
}
}
catch
(
error
)
{
box8Data
.
value
=
[]
aiContent
.
content8
=
""
;
}
refAiReport8
.
value
?.
onDataInfo
({
type
:
"环形图"
,
name
:
"结果分布情况"
,
data
:
box8Data
.
value
}
)
nextTick
(()
=>
{
createPieChart
(
box8Ref
,
box8Data
.
value
)
}
)
}
;
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论