Browse Source

fix: 关键词图表

jcq 3 weeks ago
parent
commit
3a0735d35a
3 changed files with 165 additions and 19 deletions
  1. 1 1
      src/views/home/custom-panel.vue
  2. 119 0
      src/views/home/echarts/keyword-frequency.vue
  3. 45 18
      src/views/home/index.vue

+ 1 - 1
src/views/home/custom-panel.vue

@@ -2,7 +2,7 @@
   <el-card>
     <div class="panel-top">
       <div class="panel-name">{{prop.title}}</div>
-      <div style="cursor: pointer;">
+      <div class="cursor-pointer"  @click="$emit('reload')">
         <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
           <path d="M16.7167 6.66667C15.4895 4.19712 12.9411 2.5 9.99637 2.5C7.05158 2.5 4.56062 4.19712 3.33337 6.66667" stroke="#ADBFD7" stroke-linecap="round"/>
           <path d="M3.33337 3.33334V6.66667" stroke="#ADBFD7" stroke-linecap="round"/>

+ 119 - 0
src/views/home/echarts/keyword-frequency.vue

@@ -0,0 +1,119 @@
+<!-- 访客趋势图组件 -->
+<template>
+	<div class="bubble-chart-container">
+		<div ref="chartRef" class="chart"></div>
+	</div>
+</template>
+
+<script setup lang="ts" name="keywordFrequency">
+import { ref, onMounted, onUnmounted, watch } from 'vue';
+import * as echarts from 'echarts';
+import { markRaw } from 'vue';
+
+interface ChartDataItem {
+  name: string;
+  value: number;
+  color: string;
+}
+
+const props = defineProps<{
+  chartData: ChartDataItem[];
+}>();
+
+const chartRef = ref<HTMLElement | null>(null);
+let chartInstance: echarts.ECharts | null = null;
+console.log(chartInstance);
+
+// 初始化图表
+const initChart = () => {
+  if (!chartRef.value) return;
+  
+  // 销毁旧实例(如果存在)
+  if (chartInstance) {
+    chartInstance.dispose();
+  }
+  
+  // 创建新实例
+  chartInstance = markRaw(echarts.init(chartRef.value));
+  console.log(chartInstance);
+
+  // 处理数据
+  const scatterData = props.chartData.map((item: ChartDataItem) => ({
+    value: [Math.random() * 100, Math.random() * 100, 30 + Math.random() * 20],
+    itemStyle: { color: item.color },
+    name: `${item.name}\n${item.value}`
+  }));
+  
+  
+  // 配置项
+  const option = {
+    tooltip: {
+      trigger: 'item',
+      formatter: '{b}'
+    },
+    xAxis: { show: false },
+    yAxis: { show: false },
+    series: [{
+      type: 'scatter',
+      data: scatterData,
+      symbolSize: function (data: any) {
+        return data[2]*2.4; // 使用第三个值作为气泡大小
+      },
+      label: {
+        show: true,
+        position: 'inside',
+        color: '#fff',
+        fontSize: 14,
+        formatter: '{b}'
+      },
+      emphasis: {
+        label: { show: true }
+      }
+    }]
+  };
+  
+  // 设置配置项
+  chartInstance.setOption(option);
+  
+  // 添加响应式
+  window.addEventListener('resize', handleResize);
+};
+
+// 响应窗口大小变化
+const handleResize = () => {
+  if (chartInstance) {
+    chartInstance.resize();
+  }
+};
+
+// 生命周期钩子
+onMounted(() => {
+  initChart();
+});
+
+onUnmounted(() => {
+  if (chartInstance) {
+    window.removeEventListener('resize', handleResize);
+    chartInstance.dispose();
+    chartInstance = null;
+  }
+});
+
+// 监听数据变化,更新图表
+watch(() => props.chartData, () => {
+  initChart();
+}, { deep: true });
+</script>
+
+<style scoped lang="scss">
+.bubble-chart-container {
+  width: 465px;
+  height: 330px;
+  min-height: 330px;
+}
+
+.chart {
+  width: 100%;
+  height: 100%;
+}
+</style>    

+ 45 - 18
src/views/home/index.vue

@@ -1,26 +1,53 @@
 <template>
-  <splitpanes style="height: 410px">
-    <pane size="20">
-      <custom-panel :title="'访客趋势图'">
-        <visitor-trend-chart />
-      </custom-panel>
-    </pane>
-    <pane size="40">
-      <custom-panel :title="'访客趋势图'">
-        <visitor-trend-chart />
-      </custom-panel>
-    </pane>
-    <pane size="40">
-      <custom-panel :title="'访客趋势图'">
-        <visitor-trend-chart />
-      </custom-panel>
-    </pane>
-  </splitpanes>
+	<div>
+		<splitpanes style="height: 410px">
+			<pane size="20">
+				<custom-panel :title="'访客趋势图'">
+					<visitor-trend-chart />
+				</custom-panel>
+			</pane>
+			<pane size="40">
+				<custom-panel :title="'访客趋势图'">
+					<visitor-trend-chart />
+				</custom-panel>
+			</pane>
+			<pane size="40">
+				<custom-panel :title="'访客趋势图'">
+					<visitor-trend-chart />
+				</custom-panel>
+			</pane>
+		</splitpanes>
+		<splitpanes style="height: 410px">
+			<pane size="40">
+				<custom-panel :title="'访客趋势图'">
+					<visitor-trend-chart />
+				</custom-panel>
+			</pane>
+			<pane size="30">
+				<custom-panel :title="'关键词频率'">
+					<keyword-frequency :chart-data="chartData" />
+				</custom-panel>
+			</pane>
+			<pane size="30">
+				<custom-panel :title="'关键词频率'" @reload="chartData = chartData.slice().sort(() => Math.random() - 0.5)">
+					<keyword-frequency :chart-data="chartData" />
+				</custom-panel>
+			</pane>
+		</splitpanes>
+	</div>
 </template>
 
 <script setup lang="ts" name="home">
-import { defineAsyncComponent } from 'vue';
+import { defineAsyncComponent,ref } from 'vue';
 
 const customPanel = defineAsyncComponent(() => import('./custom-panel.vue'));
 const visitorTrendChart = defineAsyncComponent(() => import('./visitor-trend-chart.vue'));
+const keywordFrequency = defineAsyncComponent(() => import('./echarts/keyword-frequency.vue'));
+const chartData =ref( [
+  { name: '下载', value: 30, color: '#ff6384' },
+  { name: '张三', value: 20, color: '#36a2eb' },
+  { name: '里斯', value: 25, color: '#cc65fe' },
+  { name: '王五', value: 15, color: '#ffce56' },
+  { name: '宅六', value: 10, color: '#4bc0c0' },
+]);
 </script>