浏览代码

fix: 舆情推送-补充近七天趋势折线图,兼容新旧后端数据格式

ice_1 2 周之前
父节点
当前提交
2ce6627359
共有 1 个文件被更改,包括 105 次插入2 次删除
  1. 105 2
      src/views/riskctrl/publicOpinion/index.vue

+ 105 - 2
src/views/riskctrl/publicOpinion/index.vue

@@ -56,6 +56,14 @@
       </el-col>
     </el-row>
 
+    <!-- 近七天舆情趋势图 -->
+    <el-card shadow="hover" class="mb-[10px]">
+      <template #header>
+        <span class="font-bold">近七天舆情趋势</span>
+      </template>
+      <div ref="trendChartRef" style="width: 100%; height: 350px;"></div>
+    </el-card>
+
     <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
       <div v-show="showSearch" class="mb-[10px]">
         <el-card shadow="hover">
@@ -236,8 +244,9 @@
 </template>
 
 <script setup name="PublicOpinion" lang="ts">
-import { listPublicOpinion, getPublicOpinion, delPublicOpinion, addPublicOpinion, updatePublicOpinion, handlePublicOpinion, getOpinionStats } from '@/api/riskctrl/publicOpinion';
-import { PublicOpinionForm, PublicOpinionQuery, PublicOpinionVO, OpinionStats } from '@/api/riskctrl/publicOpinion/types';
+import { listPublicOpinion, getPublicOpinion, delPublicOpinion, addPublicOpinion, updatePublicOpinion, handlePublicOpinion, getOpinionStats, getOpinionTrend } from '@/api/riskctrl/publicOpinion';
+import { PublicOpinionForm, PublicOpinionQuery, PublicOpinionVO, OpinionStats, OpinionTrend } from '@/api/riskctrl/publicOpinion/types';
+import * as echarts from 'echarts';
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { sys_normal_disable } = proxy.useDict('sys_normal_disable');
@@ -329,6 +338,10 @@ const getStatusType = (status: string): TagType => {
   return map[status] || 'info';
 };
 
+const trendChartRef = ref<HTMLDivElement>();
+let trendChart: echarts.ECharts | null = null;
+const trendData = ref<OpinionTrend[]>([]);
+
 const loadStats = async () => {
   try {
     const res = await getOpinionStats();
@@ -336,6 +349,95 @@ const loadStats = async () => {
   } catch { /* ignore */ }
 };
 
+const loadTrend = async () => {
+  try {
+    const res = await getOpinionTrend();
+    const raw = res.data || [];
+    // 兼容旧后端 {month, count} 或空数据 → 统一为 {date, total, major, processed}
+    trendData.value = raw.map((item: any) => ({
+      date: item.date || item.month?.substring(5) || '--',
+      total: item.total ?? item.count ?? 0,
+      major: item.major ?? 0,
+      processed: item.processed ?? 0
+    }));
+  } catch { /* ignore */ }
+  await nextTick();
+  initChart();
+};
+
+const initChart = () => {
+  if (!trendChartRef.value) return;
+  if (trendChart) trendChart.dispose();
+  trendChart = echarts.init(trendChartRef.value);
+
+  const dates = trendData.value.map((item) => item.date);
+  const totals = trendData.value.map((item) => item.total);
+  const majors = trendData.value.map((item) => item.major);
+  const processed = trendData.value.map((item) => item.processed);
+
+  trendChart.setOption({
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: { type: 'cross' }
+    },
+    legend: {
+      data: ['总舆情', '重大舆情', '已处理'],
+      bottom: 0
+    },
+    grid: {
+      left: '3%',
+      right: '4%',
+      bottom: '40px',
+      containLabel: true
+    },
+    xAxis: {
+      type: 'category',
+      boundaryGap: false,
+      data: dates
+    },
+    yAxis: {
+      type: 'value',
+      minInterval: 1
+    },
+    series: [
+      {
+        name: '总舆情',
+        data: totals,
+        type: 'line',
+        smooth: true,
+        itemStyle: { color: '#409EFF' },
+        areaStyle: {
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+            { offset: 0, color: 'rgba(64,158,255,0.3)' },
+            { offset: 1, color: 'rgba(64,158,255,0.05)' }
+          ])
+        }
+      },
+      {
+        name: '重大舆情',
+        data: majors,
+        type: 'line',
+        smooth: true,
+        itemStyle: { color: '#F56C6C' },
+        lineStyle: { type: 'dashed' }
+      },
+      {
+        name: '已处理',
+        data: processed,
+        type: 'line',
+        smooth: true,
+        itemStyle: { color: '#67C23A' },
+        areaStyle: {
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+            { offset: 0, color: 'rgba(103,194,58,0.3)' },
+            { offset: 1, color: 'rgba(103,194,58,0.05)' }
+          ])
+        }
+      }
+    ]
+  } as echarts.EChartsOption);
+};
+
 const getList = async () => {
   loading.value = true;
   const res = await listPublicOpinion(queryParams);
@@ -432,6 +534,7 @@ const handleDelete = async (row?: PublicOpinionVO) => {
 
 onMounted(() => {
   loadStats();
+  loadTrend();
   getList();
 });
 </script>