提交 04628bc9 authored 作者: 张烨's avatar 张烨

feat:封装AI智能报告组件

上级 0204674d
<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
......@@ -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, getAIReport, getNearYearList } 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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论