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