add customer disease word cloud chart
This commit is contained in:
@@ -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>
|
||||
Reference in New Issue
Block a user