提交 df03f9c4 authored 作者: coderBryanFu's avatar coderBryanFu

新增301调查、行政机构主页

上级 0f82a1ac
......@@ -7,6 +7,8 @@ import DecreeBackground from "@/views/decree/decreeLayout/overview/background/in
import DecreeDeepDig from "@/views/decree/decreeLayout/deepdig/index.vue";
import DecreeInfluence from "@/views/decree/decreeLayout/influence/index.vue";
import Institution from "@/views/decree/institution/index.vue"
const decreeRoutes = [
// 政令首页
{
......@@ -69,6 +71,14 @@ const decreeRoutes = [
}
]
},
{
path: "/institution",
name: "Institution",
component: Institution,
meta: {
title: "行政机构主页"
}
}
]
......
......@@ -2,7 +2,6 @@
import MarketAccessRestrictions from "@/views/marketAccessRestrictions/marketAccessHome/index.vue";
import MarketAccessLayout from "@/views/marketAccessRestrictions/marketAccessLayout/index.vue";
import MarketAccessOverview from "@/views/marketAccessRestrictions/marketAccessLayout/overview/index.vue";
import MarketAccessDeepdig from "@/views/marketAccessRestrictions/marketAccessLayout/deepdig/index.vue"
import MarketAccessCase from "@/views/marketAccessRestrictions/marketAccessLayout/case/index.vue";
import MarketSingleCaseLayout from "@/views/marketAccessRestrictions/singleCaseLayout/index.vue";
import MarketSingleCaseOverview from "@/views/marketAccessRestrictions/singleCaseLayout/overview/index.vue";
......@@ -36,14 +35,6 @@ const marketAccessRestrictionsRoutes = [
title: "调查概况"
}
},
{
path: "deepdig",
name: "MarketAccessDeepdig",
component: MarketAccessDeepdig,
meta: {
title: "调查概况"
}
},
{
path: "case",
name: "MarketAccessCase",
......
......@@ -40,18 +40,27 @@
<div v-for="(message, index) in messages" :key="index">
<!-- AI 消息 -->
<div v-if="message.type === 'ai'" class="ai-item">
<div class="ai-header">
<div class="ai-header" v-if="!isLoading">
<div class="icon">
<img src="./assets/images/ai-avator.png" alt="" />
</div>
<div class="text">{{ `已深度思考` }}</div>
</div>
<div v-if="message.think" class="think-title">思考内容</div>
<!-- <div v-if="message.think" class="think-title">思考内容</div>
<div
v-if="message.think"
class="content think-content"
v-html="renderMarkdown(message.think)"
></div>
></div> -->
<div v-if="message.source" class="source-title">知识库检索结果:</div>
<div v-if="message.source" class="content source-content">
<div
class="source-item"
v-for="(item, index) in message.source"
:key="index"
v-html="item"
></div>
</div>
<div v-if="message.content" class="answer-title">正文内容</div>
<div
v-if="message.content"
......@@ -85,7 +94,13 @@
</div>
</div>
<div class="right-main-footer">
<el-input @keyup.enter="sendMessage" type="textarea" placeholder="发送消息" :rows="4" v-model="userInput" />
<el-input
@keyup.enter="sendMessage"
type="textarea"
placeholder="发送消息"
:rows="4"
v-model="userInput"
/>
<div class="input-footer">
<div class="icon1">
<el-tooltip effect="dark" content="录音" placement="top">
......@@ -135,14 +150,14 @@ const abortController = ref(null);
// 消息数据
const messages = ref([
{
type: "user",
content: "你好"
},
{
type: "ai",
content: "您好!我是AI助手,有什么可以帮助您的吗?"
}
// {
// type: "user",
// content: "你好"
// },
// {
// type: "ai",
// content: "您好!我是AI助手,有什么可以帮助您的吗?"
// }
]);
// Markdown 渲染器
......@@ -209,10 +224,109 @@ function parseOuterOnly(json5String, maxDepth = 1) {
}
// 使用 fetchEventSource 连接
// const connectSSE = async question => {
// // 添加用户消息
// addMessage("user", question);
// // 添加空的 AI 消息用于流式更新
// addMessage("ai", "");
// isLoading.value = true;
// // 创建 AbortController 用于取消请求
// abortController.value = new AbortController();
// const params = {
// // question: "川普1期对华制裁领域分布情况"
// question: question
// // knowledge_base_name: "kb_test251112",
// // top_k: 6,
// // score_threshold: 0.5,
// // metadata: { year: 2024 }
// };
// fetchEventSource("/sseChat/rag/chat/stream", {
// method: "POST",
// headers: {
// "Content-Type": "application/json"
// },
// body: JSON.stringify(params),
// signal: abortController.value.signal,
// openWhenHidden: true,
// async onopen(res) {
// isLoading.value = false;
// console.log("流式回答开始", res);
// },
// async onmessage(res) {
// console.log("res", res);
// let msgData = parseOuterOnly(res.data);
// if (res.event === "end_of_workflow") {
// ElMessage.success("问答完成!");
// abortController.value.abort();
// abortController.value = new AbortController();
// return;
// }
// if (res.event === "start_of_agent" && msgData.agent_name === "answer") {
// isCurAnswerMessage.value = true;
// aiMessage.value = "";
// }
// if (res.event === "message") {
// let content = msgData.delta.content;
// console.log("msgData", msgData);
// console.log("content", content);
// if (content !== "[DONE]") {
// aiMessage.value += content;
// updateLastAIMessage(aiMessage.value);
// } else {
// aiMessage.value = "";
// abortController.value.abort();
// abortController.value = new AbortController();
// }
// }
// },
// onerror(error) {
// ElMessage({
// message: "问答报错!",
// type: "warning"
// });
// abortController.value.abort();
// abortController.value = new AbortController();
// throw new Error(error);
// }
// }).catch(error => {
// ElMessage({
// message: "问答报错!",
// type: "warning"
// });
// abortController.value.abort();
// abortController.value = new AbortController();
// throw new Error(error);
// });
// };
// 定义正则替换
function removeHttpParentheses(str) {
// 匹配 (http://... 开头,以 ) 结尾的内容
return str.replace(/\(http:\/\/[^)]*\)/g, "");
}
// 将字符串中符合以'['开头以'.txt]'结尾的字符串中的'.txt'替换为空
function removeTxtInBrackets(str) {
// 匹配 [开头,.txt]结尾的内容,并替换其中的.txt为空
return str.replace(/\[([^[\]]*)\.txt\]/g, '[$1]');
}
const connectSSE = async question => {
// 添加用户消息
addMessage("user", question);
let mesParam = messages.value.map(item => {
return {
role: item.type,
content: item.content
};
});
// 添加空的 AI 消息用于流式更新
addMessage("ai", "");
......@@ -222,15 +336,17 @@ const connectSSE = async question => {
abortController.value = new AbortController();
const params = {
// question: "川普1期对华制裁领域分布情况"
question: question
// knowledge_base_name: "kb_test251112",
// top_k: 6,
// score_threshold: 0.5,
// metadata: { year: 2024 }
model: "qwen-plus",
messages: mesParam,
stream: true,
temperature: 0.3,
top_k: 9,
score_threshold: 0.1,
prompt_name: "default",
return_direct: false
};
fetchEventSource("/sseChat/rag/chat/stream", {
fetchEventSource("/sseChat/knowledge_base/local_kb/bills-500/chat/completions", {
method: "POST",
headers: {
"Content-Type": "application/json"
......@@ -244,30 +360,50 @@ const connectSSE = async question => {
},
async onmessage(res) {
console.log("res", res);
let msgData = parseOuterOnly(res.data);
if (res.event === "end_of_workflow") {
ElMessage.success("问答完成!");
abortController.value.abort();
abortController.value = new AbortController();
return;
let msgData = JSON.parse(res.data);
if (msgData.docs) {
console.log("docs", msgData.docs);
const lastMessage = messages.value[messages.value.length - 1];
if (lastMessage && lastMessage.type === "ai") {
let newDocs = msgData.docs.map(item => {
return removeHttpParentheses(item);
}).map(val => {
return removeTxtInBrackets(val)
})
lastMessage.source = newDocs;
scrollToBottom();
}
}
if (res.event === "start_of_agent" && msgData.agent_name === "answer") {
if (msgData.choices) {
isCurAnswerMessage.value = true;
aiMessage.value = "";
}
if (res.event === "message") {
let content = msgData.delta.content;
console.log("msgData", msgData);
console.log("content", content);
if (content !== "[DONE]") {
aiMessage.value += content;
updateLastAIMessage(aiMessage.value);
} else {
aiMessage.value = "";
abortController.value.abort();
abortController.value = new AbortController();
}
let content = msgData.choices[0].delta.content;
aiMessage.value += content;
updateLastAIMessage(aiMessage.value);
}
// if (res.event === "end_of_workflow") {
// ElMessage.success("问答完成!");
// abortController.value.abort();
// abortController.value = new AbortController();
// return;
// }
// if (res.event === "start_of_agent" && msgData.agent_name === "answer") {
// isCurAnswerMessage.value = true;
// aiMessage.value = "";
// }
// if (res.event === "message") {
// let content = msgData.delta.content;
// console.log("msgData", msgData);
// console.log("content", content);
// if (content !== "[DONE]") {
// aiMessage.value += content;
// updateLastAIMessage(aiMessage.value);
// } else {
// aiMessage.value = "";
// abortController.value.abort();
// abortController.value = new AbortController();
// }
// }
},
onerror(error) {
ElMessage({
......@@ -684,6 +820,31 @@ onUnmounted(() => {
padding: 1px 10px;
border-radius: 5px;
}
.source-title {
margin-left: 26px;
height: 22px;
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 22px;
letter-spacing: 0px;
text-align: left;
}
.source-content {
background: rgba(245, 245, 245, 0.5);
width: 900px;
margin-left: 26px;
padding: 1px 10px;
border-radius: 5px;
// max-height: 300px;
// overflow-y: auto;
.source-item {
text-indent: 30px;
line-height: 30px;
color: #333;
}
}
.ai-content {
margin-top: 10px;
width: 900px;
......
......@@ -88,7 +88,7 @@
</div>
</div>
<div class="home-main-header-item-box">
<div class="item" v-for="(item, index) in govInsList" :key="index">
<div class="item" v-for="(item, index) in govInsList" :key="index" @click="handleToInstitution(item)">
<div class="item-left">
<img :src="item.img" alt="" />
</div>
......@@ -646,6 +646,14 @@ import Message1 from "./assets/images/message-icon1.png";
import Message2 from "./assets/images/message-icon2.png";
import Message3 from "./assets/images/message-icon3.png";
// 跳转行政机构主页
const handleToInstitution = item => {
if (item.name === "美国商务部") {
const curRoute = router.resolve("/institution");
window.open(curRoute.href, "_blank");
}
};
// 返回首页
const handleBackHome = () => {
router.push({
......@@ -2766,7 +2774,7 @@ onMounted(async () => {
height: 84px;
border-bottom: 1px solid rgba(234, 236, 238, 1);
cursor: pointer;
&:hover{
&:hover {
background: var(--color-bg-hover);
}
.main-item-left {
......
差异被折叠。
const getGraphChart = (graphData) => {
const option = {
title: { text: "", left: "center" },
tooltip: {},
// legend: {
// data: graphData.categories.map(item => item.name),
// left: "left"
// },
series: [
{
type: "graph",
layout: "force", // 力导向布局
force: {
repulsion: 500, // 节点排斥力
edgeLength: [30, 80] // 边长度范围
},
data: graphData.nodes,
links: graphData.links,
categories: graphData.categories,
roam: true, // 支持缩放、平移
label: {
show: true,
fontSize: 14,
position: "bottom",
formatter: function (params) {
// 根据条件返回不同样式的文本
if (params.data.category === 0) {
return `{a|${params.name}}`; // 使用富文本样式
} else if (params.data.category === 1) {
return `{b|${params.name}}`;
} else {
return params.name; // 默认样式
}
},
rich: {
a: {
// 重要节点的样式
color: "#000",
fontSize: 14,
padding: [2, 4],
borderRadius: 2
},
b: {
// 普通节点的样式
color: "rgba(5, 95, 194, 1)",
fontSize: 14,
fontWeight: "bold",
}
}
},
edgeSymbol: ["arrow", "none"], // 边的箭头
edgeSymbolSize: [8, 50],
itemStyle: {
color: "rgba(5, 95, 194, 1)"
// borderColor: "red",
// borderWidth: 1
},
lineStyle: {
color: "rgba(174, 214, 255, 1)",
width: 2,
opacity: 0.5
},
emphasis: {
focus: "adjacency",
lineStyle: {
width: 2
}
}
}
]
};
return option
}
export default getGraphChart
\ No newline at end of file
const getPieChart = (data) => {
let option = {
color: ['#69B1FF','#FFC069','#87E8DE','#597EF7','#D6E4FF','#FF7875','#B37FEB','#FFA39E'],
series: [
{
type: 'pie',
radius: [95, 115],
height: '100%',
left: 'center',
width: '85%',
itemStyle: {
borderColor: '#fff',
borderWidth: 1
},
label: {
alignTo: 'edge',
formatter: '{name|{b}} {num|{c} 项 {d}%}\n',
minMargin: 5,
edgeDistance: 10,
// lineHeight: 15,
rich: {
name: {
fontSize: 16,
fontWeight: 700,
fontFamily: 'Microsoft YaHei',
color: 'rgba(59, 65, 75, 1)',
// lineHeight: 24,
// height: 24
},
num: {
fontSize: 14,
color: 'rgba(95, 101, 108, 1)',
fontWeight: 400
}
}
},
labelLine: {
length: 15,
length2: 0,
maxSurfaceAngle: 80
},
labelLayout: function (params) {
const isLeft = params.labelRect.x < 556 / 2;
const points = params.labelLinePoints;
points[2][0] = isLeft
? params.labelRect.x
: params.labelRect.x + params.labelRect.width;
return {
labelLinePoints: points
};
},
data: data
}]
}
return option
}
export default getPieChart;
\ No newline at end of file
const getSankeyChart = (nodes, links) => {
const option = {
series: {
type: 'sankey',
layout: 'none',
left: '2%',
right: '26%',
top: '5%',
bottom: '5%',
emphasis: {
focus: 'adjacency'
},
nodeWidth: 40,
label: {
show: true,
formatter: function (params) {
return `${params.name}`;
},
position: 'right',
textStyle: {
fontSize: '14px',
color: '#555'
}
},
data: nodes,
links: links
}
};
return option
}
export default getSankeyChart
\ No newline at end of file
const getWordCloudChart = (data) => {
const option = {
grid: {
left: '1%',
top: '1%',
right: '1%',
bottom: '1%',
},
series: [
{
type: "wordCloud",
// shape: "rect", //
// 其他形状你可以使用形状路径
// 或者自定义路径
shape: 'circle', // 圆形(默认)
// shape: 'rect' // 矩形
// shape: 'roundRect', // 圆角矩形
// shape: 'triangle' // 三角形
// shape: 'diamond', // 菱形
// shape: 'pentagon' // 五边形
// shape: 'star', // 星形
// shape: 'cardioid' // 心形
gridSize: 20, // 网格大小,影响词间距。
sizeRange: [10, 30], // 定义词云中文字大小的范围
rotationRange: [0, 0],
rotationStep: 10,
drawOutOfBound: false, // 是否超出画布
// 字体
textStyle: {
// normal: {
// color: function () {
// return 'rgb(' + [
// Math.round(Math.random() * 160),
// Math.round(Math.random() * 160),
// Math.round(Math.random() * 160)
// ].join(',') + ')';
// }
// },
color: function () {
let colors = [
"rgba(189, 33, 33, 1)",
"rgba(232, 151, 21, 1)",
"rgba(220, 190, 68, 1)",
"rgba(96, 58, 186, 1)",
"rgba(32, 121, 69, 1)",
"rgba(22, 119, 255, 1)",
];
return colors[parseInt(Math.random() * colors.length)];
},
emphasis: {
shadowBlur: 5,
shadowColor: "#333",
},
},
// 设置词云数据
data: data,
},
],
}
return option
}
export default getWordCloudChart
\ No newline at end of file
<template>
<div class="wrap">
<div class="header">
<div class="header-left">
<img src="@/assets/images/decree-org.png" alt="" />
</div>
<div class="header-right">
<div class="title">{{ institutionInfo.name }}</div>
<div class="en-title">{{ institutionInfo.enName }}</div>
<div class="desc">{{ institutionInfo.desc }}</div>
<div class="tag-box">
<div class="tag" v-for="(tag, index) in institutionInfo.tagList" :key="index">
{{ tag }}
</div>
</div>
</div>
<div class="header-btn">
<div class="icon">
<img src="@/assets/images/links-icon.png" alt="" />
</div>
<div class="text">{{ "查看官网" }}</div>
</div>
</div>
<div class="tab-box">
<div
class="tab"
@click="handleClickTab(item, index)"
:class="{ tabActive: item.active }"
v-for="(item, index) in tabList"
:key="index"
>
{{ item.name }}
</div>
</div>
<div class="main">
<InsDetail v-if="activeTabName === '机构详情'"></InsDetail>
<Deepdig v-else-if="activeTabName === '深度挖掘'"></Deepdig>
<Sanction v-else></Sanction>
</div>
</div>
</template>
<script setup>
import { ref, computed, onMounted } from "vue";
import InsDetail from "./insDetail/index.vue";
import Deepdig from "./deepdig/index.vue";
import Sanction from "./sanction/index.vue";
const institutionInfo = ref({
name: "美国商务部",
enName: "United States Department of Commerce",
desc: "美国联邦政府的重要经济部门,主要职责为国际贸易、进出口管制、经济数据统计及专利商标管理。",
tagList: ["实体清单", "232调查", "行政令"]
});
const activeTabName = ref("机构详情");
const tabList = ref([
{
name: "机构详情",
active: true
},
{
name: "深度挖掘",
active: false
},
{
name: "对话制裁",
active: false
}
]);
const handleClickTab = (val, index) => {
tabList.value.forEach(item => {
item.active = false;
});
tabList.value[index].active = true;
activeTabName.value = val.name;
};
</script>
<style lang="scss" scoped>
.wrap {
width: 1920px;
height: 100%;
background-image: url("./assets/images/bg.png");
background-repeat: no-repeat;
background-size: 100% auto;
padding-top: 16px;
.header {
width: 1600px;
height: 200px;
margin: 0 auto 16px;
box-sizing: border-box;
border: 1px solid rgba(255, 255, 255, 1);
border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 0.8);
display: flex;
position: relative;
.header-left {
width: 160px;
height: 160px;
margin: 20px;
img {
width: 100%;
height: 100%;
}
}
.header-right {
margin-left: 24px;
.title {
margin-top: 26px;
height: 42px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 32px;
font-weight: 700;
line-height: 42px;
letter-spacing: 0px;
text-align: left;
}
.en-title {
margin-top: 8px;
height: 24px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
text-align: left;
}
.desc {
margin-top: 6px;
height: 24px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 24px;
letter-spacing: 0px;
text-align: justify;
}
.tag-box {
margin-top: 14px;
display: flex;
gap: 8px;
.tag {
height: 24px;
padding: 0px 8px;
border-radius: 4px;
background: rgba(231, 243, 255, 1);
color: var(--color-main-active);
font-family: Microsoft YaHei;
font-size: 14px;
font-weight: 400;
line-height: 20px;
letter-spacing: 0px;
}
}
}
.header-btn {
position: absolute;
top: 26px;
right: 30px;
width: 120px;
height: 36px;
border-radius: 6px;
background: rgba(5, 95, 194, 1);
display: flex;
gap: 3px;
justify-content: center;
align-items: center;
cursor: pointer;
.icon {
width: 16px;
height: 16px;
img {
width: 100%;
height: 100%;
}
}
.text {
height: 22px;
color: rgba(255, 255, 255, 1);
font-family: Microsoft YaHei;
font-size: 16px;
font-weight: 400;
line-height: 22px;
}
}
}
.tab-box {
width: 1600px;
height: 64px;
margin: 0 auto;
box-sizing: border-box;
border: 1px solid rgba(255, 255, 255, 1);
border-radius: 10px;
box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
background: rgba(255, 255, 255, 0.8);
display: flex;
justify-content: space-between;
align-items: center;
.tab {
width: 526px;
height: 54px;
box-sizing: border-box;
border: 2px solid transparent;
border-radius: 10px;
text-align: center;
line-height: 50px;
color: rgba(59, 65, 75, 1);
font-family: Microsoft YaHei;
font-size: 20px;
font-weight: 400;
letter-spacing: 0px;
cursor: pointer;
&:hover {
background: rgba(231, 243, 255, 1);
}
}
.tabActive {
border: 2px solid rgba(174, 214, 255, 1);
background: rgba(231, 243, 255, 1);
color: rgba(5, 95, 194, 1);
font-size: 24px;
font-weight: 700;
}
}
.main {
height: 800px;
width: 1600px;
margin: 16px auto;
}
}
</style>
\ No newline at end of file
import * as echarts from 'echarts'
const getMultiLineChart = (dataX, dataY1, dataY2) => {
return {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
}
},
grid: {
top: '8%',
right: '5%',
bottom: '5%',
left: '5%',
containLabel: true
},
legend: {
show: true,
textStyle: {
color: 'rgba(95, 101, 108, 1)',
fontFamily: 'Microsoft YaHei',
fontSize: '16px',
}
},
color: ['rgba(5, 95, 194, 1)', 'rgba(206, 79, 81, 1)'],
xAxis: [
{
type: 'category',
boundaryGap: false,
data: dataX
}
],
yAxis: [
{
type: 'value'
}
],
series: [
{
name: '提出法案',
type: 'line',
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(5, 95, 194, 1)' // 起始颜色
}, {
offset: 1,
color: 'rgba(5, 95, 194, 0)' // 结束颜色
}])
},
emphasis: {
focus: 'series'
},
data: dataY1
},
{
name: '通过法案',
type: 'line',
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(206, 79, 81, 1)' // 起始颜色
}, {
offset: 1,
color: 'rgba(206, 79, 81, 0.1)' // 结束颜色
}])
},
emphasis: {
focus: 'series'
},
data: dataY2
}
]
}
}
export default getMultiLineChart
\ No newline at end of file
const getPieChart = (data) => {
let option = {
color: ['#69B1FF','#FFC069','#87E8DE','#597EF7','#D6E4FF','#FF7875','#B37FEB','#FFA39E'],
series: [
{
type: 'pie',
radius: [80, 100],
height: '100%',
left: 'center',
width: '95%',
itemStyle: {
borderColor: '#fff',
borderWidth: 1
},
label: {
alignTo: 'edge',
formatter: '{name|{b}} {num|{c} 项 {d}%}\n',
minMargin: 5,
edgeDistance: 10,
// lineHeight: 15,
rich: {
name: {
fontSize: 16,
fontWeight: 700,
fontFamily: 'Microsoft YaHei',
color: 'rgba(59, 65, 75, 1)',
// lineHeight: 24,
// height: 24
},
num: {
fontSize: 14,
color: 'rgba(95, 101, 108, 1)',
fontWeight: 400
}
}
},
labelLine: {
length: 15,
length2: 0,
maxSurfaceAngle: 80
},
labelLayout: function (params) {
const isLeft = params.labelRect.x < 556 / 2;
const points = params.labelLinePoints;
points[2][0] = isLeft
? params.labelRect.x
: params.labelRect.x + params.labelRect.width;
return {
labelLinePoints: points
};
},
data: data
}]
}
return option
}
export default getPieChart;
\ No newline at end of file
<template>
<div class="wrap">
我是深度挖掘页面!!!!!
</div>
</template>
<script setup>
</script>
<style lang="scss" scoped>
.wrap{
width: 200px;
height: 200px;
background: orange;
color: #000;
}
</style>
\ No newline at end of file
......@@ -58,45 +58,20 @@ import Img301 from "./assets/images/301.png";
import { useRoute } from "vue-router";
const route = useRoute();
const btnList = computed(() => {
if (route.query.id === "301") {
return [
{
name: "调查概况",
icon: icon1,
acitveIcon: icon1Active,
path: "/marketAccessLayout/overview"
},
{
name: "深度挖掘",
icon: icon2,
acitveIcon: icon2Active,
path: "/marketAccessLayout/deepdig"
},
{
name: "调查案件",
icon: icon2,
acitveIcon: icon2Active,
path: "/marketAccessLayout/case"
}
];
} else {
return [
{
name: "调查概况",
icon: icon1,
acitveIcon: icon1Active,
path: "/marketAccessLayout/overview"
},
{
name: "调查案件",
icon: icon2,
acitveIcon: icon2Active,
path: "/marketAccessLayout/case"
}
];
const btnList = ref([
{
name: "调查概况",
icon: icon1,
acitveIcon: icon1Active,
path: "/marketAccessLayout/overview"
},
{
name: "调查案件",
icon: icon2,
acitveIcon: icon2Active,
path: "/marketAccessLayout/case"
}
});
]);
const curSurvey = computed(() => {
if (route.query.id === "301") {
......@@ -133,6 +108,8 @@ const handleClickBtn = item => {
};
onMounted(() => {});
</script>
<style lang="scss" scoped>
......
import * as echarts from "echarts";
const getBarChart = (nameList, valueList) => {
const option = {
tooltip: {},
grid: {
top: '5%',
right: '3%',
bottom: '1%',
left: '1%',
containLabel: true
},
yAxis: {
type: 'value',
splitLine: {
show: false
},
show: false
},
xAxis: {
type: 'category',
data: nameList.map(item => {
return item.name
}),
splitLine: {
show: false
},
axisTick: {
show: false
},
axisLine: {
show: false
},
axisLabel: {
show: true
}
},
series: [{
type: 'bar',
data: valueList,
label: {
show: true,
position: 'top',
textStyle: {
color: 'rgba(5, 95, 194, 1)',
fontSize: 16,
fontWeight: 700,
fontFamily: 'Microsoft YaHei'
},
formatter: function (params) {
return params.value
}
},
barWidth: 20,
markPoint: {
symbol: 'circle',
symbolSize: 0,
data: (function () {
const data = [];
nameList.forEach((item, index) => {
data.push({
name: 'icon',
// value: '',
xAxis: index,
yAxis: valueList[index],
symbol: `image://${item.img}`,
symbolSize: [20, 20],
symbolOffset: [0, 10]
});
});
return data;
})()
},
itemStyle: {
color: function (params) {
return new echarts.graphic.LinearGradient(0, 1, 0, 0,
[{
offset: 0,
color: 'rgba(5, 95, 194, 0)'
},
{
offset: 1,
color: 'rgba(5, 95, 194, 1)'
}
]);
},
barBorderRadius: [10, 10, 4, 4],
}
}]
}
return option
}
export default getBarChart
\ No newline at end of file
import * as echarts from 'echarts'
const getLineChart = (dataX, dataY) => {
return {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
}
},
grid: {
top: '8%',
right: '5%',
bottom: '5%',
left: '5%',
containLabel: true
},
legend: {
data: ['提出法案', '通过法案'],
show: false
},
color: ['#1459bb', '#fa8c16'],
xAxis: [
{
type: 'category',
boundaryGap: false,
data: dataX
}
],
yAxis: [
{
type: 'value'
}
],
series: [
{
name: '301调查',
type: 'line',
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(22, 119, 255, 0.5)' // 起始颜色
}, {
offset: 1,
color: 'rgba(5, 95, 194, 0)' // 结束颜色
}])
},
lineStyle: {
color: '#055FC2',
width: 1
},
emphasis: {
focus: 'series'
},
data: dataY
},
]
}
}
export default getLineChart
\ No newline at end of file
const getPieChart = (data) => {
let option = {
color: ['#69B1FF','#FFC069','#87E8DE','#597EF7','#D6E4FF','#FF7875','#B37FEB','#FFA39E'],
series: [
{
type: 'pie',
radius: [95, 115],
height: '100%',
left: 'center',
width: '85%',
itemStyle: {
borderColor: '#fff',
borderWidth: 1
},
label: {
alignTo: 'edge',
formatter: '{name|{b}} {num|{c} 项 {d}%}\n',
minMargin: 5,
edgeDistance: 10,
// lineHeight: 15,
rich: {
name: {
fontSize: 16,
fontWeight: 700,
fontFamily: 'Microsoft YaHei',
color: 'rgba(59, 65, 75, 1)',
// lineHeight: 24,
// height: 24
},
num: {
fontSize: 14,
color: 'rgba(95, 101, 108, 1)',
fontWeight: 400
}
}
},
labelLine: {
length: 15,
length2: 0,
maxSurfaceAngle: 80
},
labelLayout: function (params) {
const isLeft = params.labelRect.x < 556 / 2;
const points = params.labelLinePoints;
points[2][0] = isLeft
? params.labelRect.x
: params.labelRect.x + params.labelRect.width;
return {
labelLinePoints: points
};
},
data: data
}]
}
return option
}
export default getPieChart;
\ No newline at end of file
const getSankeyChart = (nodes, links) => {
const option = {
series: {
type: 'sankey',
layout: 'none',
left: '5%',
right: '12%',
top: '5%',
bottom: '5%',
emphasis: {
focus: 'adjacency'
},
nodeWidth: 30,
label: {
show: true,
formatter: function (params) {
return `${params.name}`;
},
position: 'right',
textStyle: {
fontSize: '14px',
color: '#555'
}
},
data: nodes,
links: links
}
};
return option
}
export default getSankeyChart
\ No newline at end of file
......@@ -2,6 +2,7 @@
<div class="overview-wrap">
<Discussion1 v-if="showDiscussion ==='337'"></Discussion1>
<Discussion2 v-else-if="showDiscussion ==='232'"></Discussion2>
<Discussion3 v-else></Discussion3>
</div>
</template>
......@@ -9,6 +10,7 @@
import { ref, onMounted, computed } from "vue";
import Discussion1 from './337/index.vue'
import Discussion2 from './232/index.vue'
import Discussion3 from './301/index.vue'
import { useRoute } from "vue-router";
const route = useRoute()
......
......@@ -5,7 +5,7 @@
<div class="header-top-left">{{ curSurvey.name }}</div>
<div class="header-top-right">
<div class="title">
{{curSurvey.title }}
{{ curSurvey.title }}
</div>
<div class="time">{{ curSurvey.time }}</div>
</div>
......@@ -51,7 +51,7 @@
</template>
<script setup>
import { ref, onMounted } from "vue";
import { ref, onMounted, computed } from "vue";
import router from "@/router";
import NavIcon1 from "./assets/images/nav-icon1.png";
import NavIcon1Active from "./assets/images/nav-icon1-active.png";
......@@ -76,7 +76,7 @@ const navList = ref([
activeIcon: NavIcon2Active,
isActive: false,
path: "/marketSingleCaseLayout/deepdig"
},
}
// {
// name: "影响分析",
// icon: NavIcon3,
......@@ -102,29 +102,40 @@ const handleClickNav = index => {
const surveyList = ref([
{
title: "337-TA-1443:外国制造的半导体器件及其下游产品和组件",
time: '2025年7月18日',
name: '337'
time: "2025年7月18日",
name: "337"
},
{
{
title: "231-TA-1225:进口药及进口原材料的调查",
time: '2021年9月21日',
name: '232'
time: "2021年9月21日",
name: "232"
},
{
title: "美国贸易代表第301条关于中国针对海事、物流和造船业以争取主导地位的行动",
time: "2025年4月17日",
name: "301"
}
]);
const curSurvey = ref( {
title: "337-TA-1443:外国制造的半导体器件及其下游产品和组件",
time: '2025年7月18日',
name: '337'
});
// const curSurvey = ref( {
// title: "337-TA-1443:外国制造的半导体器件及其下游产品和组件",
// time: '2025年7月18日',
// name: '337'
// });
onMounted(() => {
const curSurvey = computed(() => {
let survey;
if (route.query.id === "232") {
curSurvey.value = surveyList.value[1];
survey = surveyList.value[1];
} else if (route.query.id === "301") {
survey = surveyList.value[2];
} else {
survey = surveyList.value[0];
}
return survey;
});
onMounted(() => {});
</script>
<style lang="scss" scoped>
......
......@@ -2,6 +2,7 @@
<div class="overview-wrap">
<Discussion1 v-if="showSurvey ==='337'"></Discussion1>
<Discussion2 v-else-if="showSurvey ==='232'"></Discussion2>
<Discussion3 v-else-if="showSurvey ==='301'"></Discussion3>
</div>
</template>
......@@ -9,6 +10,7 @@
import { ref, onMounted, computed } from "vue";
import Discussion1 from './337/index.vue'
import Discussion2 from './232/index.vue'
import Discussion3 from './301/index.vue'
import { useRoute } from "vue-router";
const route = useRoute()
......
......@@ -42,7 +42,8 @@ export default defineConfig({
},
'/sseChat': {
// target: 'http://192.168.26.115:8000',
target: 'http://8.140.26.4:10018/',
// target: 'http://8.140.26.4:10018/',
target: 'http://8.140.26.4:10019/',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/sseChat/, '')
},
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论