add customer disease word cloud chart

This commit is contained in:
Timi
2026-09-11 17:33:48 +08:00
parent 62add33884
commit c1a328a514
@@ -0,0 +1,156 @@
<template>
<section class="chart-section">
<h2>客户病症词云</h2>
<div v-if="isLoading" class="center-tips" v-text="'正在分析客户病症'" />
<div v-else-if="!wordList.length" class="center-tips" v-text="'暂无可分析的病症描述'" />
<div v-else ref="chartElement" class="chart" />
</section>
</template>
<script setup lang="ts">
import type { ECharts, EChartsOption } from "echarts";
import { init, use } from "echarts/core";
import { TooltipComponent } from "echarts/components";
import "echarts-wordcloud";
import { CanvasRenderer } from "echarts/renderers";
import CustomerChartAPI from "@/api/CustomerChartAPI";
import type { CustomerDiseaseWordView } from "@/types/Customer";
import { getErrorMessage } from "@/utils/error";
import { Message } from "@/utils/message";
use([TooltipComponent, CanvasRenderer]);
defineOptions({
name: "StoreCustomerDiseaseWordCloudChart"
});
const chartColorList = ["#2563eb", "#0f766e", "#d97706", "#db2777", "#7c3aed", "#0891b2"];
// ---------- 图表数据 ----------
const wordList = ref<CustomerDiseaseWordView[]>([]);
const isLoading = ref(false);
const chartElement = ref<HTMLElement>();
let chart: ECharts | undefined;
let requestId = 0;
const chartOption = computed<EChartsOption>(() => ({
tooltip: {
trigger: "item",
formatter: "{b}:{c} 次"
},
series: [
{
name: "客户病症",
type: "wordCloud",
shape: "circle",
left: "center",
top: "center",
width: "94%",
height: "92%",
gridSize: 8,
sizeRange: [14, 48],
rotationRange: [0, 0],
rotationStep: 0,
drawOutOfBound: false,
layoutAnimation: false,
textStyle: {
fontFamily: "sans-serif",
fontWeight: "bold"
},
data: wordList.value.map((item, index) => ({
name: item.word || "",
value: item.value || 0,
textStyle: {
color: chartColorList[index % chartColorList.length]
}
}))
}
] as unknown as EChartsOption["series"]
}));
// ---------- 图表生命周期 ----------
watch(wordList, async () => {
await nextTick();
renderChart();
}, { deep: true });
onMounted(async () => {
await loadWordList();
window.addEventListener("resize", resizeChart);
});
onBeforeUnmount(() => {
window.removeEventListener("resize", resizeChart);
chart?.dispose();
chart = undefined;
});
async function loadWordList(): Promise<void> {
const currentRequestId = ++requestId;
isLoading.value = true;
try {
const list = await CustomerChartAPI.diseaseWord(60);
if (currentRequestId === requestId) {
wordList.value = list || [];
}
} catch (error) {
if (currentRequestId === requestId) {
Message.error(getErrorMessage(error, "客户病症词云加载失败"));
}
} finally {
if (currentRequestId === requestId) {
isLoading.value = false;
}
}
}
function renderChart(): void {
if (!chartElement.value || !wordList.value.length) {
return;
}
chart = chart || init(chartElement.value);
chart.setOption(chartOption.value, true);
chart.resize();
}
function resizeChart(): void {
chart?.resize();
}
</script>
<style scoped lang="less">
.chart-section {
padding: 1rem;
background: rgba(255, 255, 255, .92);
box-shadow: var(--td-shadow-1);
border-radius: 1.25rem;
h2 {
margin: 0;
color: #0f172a;
font-size: 1rem;
font-weight: 700;
}
.chart {
width: 100%;
height: 18rem;
}
}
:global(html.theme-dark) {
.chart-section {
background: rgba(15, 23, 42, .88);
box-shadow: 0 .75rem 2rem rgba(2, 6, 23, .32);
.heading {
h2 {
color: #e2e8f0;
}
}
}
}
</style>