Files
pj_plan_cloud/src/components/nutrition-analyse/week-statistics.vue
T
2025-10-17 13:01:55 +08:00

209 lines
6.5 KiB
Vue

<template>
<div ref="chartRef" style="width: 100%; height: 100%"></div>
</template>
<script setup>
import { onMounted, onBeforeUnmount, useTemplateRef, watch } from "vue";
import * as echarts from "echarts";
import dayjs from "dayjs";
const props = defineProps({
labels: {
type: Object,
default: () => [],
},
data: {
type: Object,
default: () => [
{ text: "荤菜", name: "hc", values: [0, 0, 0, 0, 0, 0, 0, 0] },
{ text: "素菜", name: "sc", values: [0, 0, 0, 0, 0, 0, 0, 0] },
{ text: "主食", name: "zs", values: [0, 0, 0, 0, 0, 0, 0, 0] },
],
},
});
const chartRef = useTemplateRef("chartRef");
let chartInstance = null;
watch(
() => [props.data, props.labels],
(val) => {
if (!chartInstance) return;
chartInstance.setOption({
xAxis: {
data: props.labels?.map((v) => v.split("|")[1]) ?? [],
},
series: props.data.map((item, i) => {
return {
type: "bar",
stack: 'total',
name: item.text,
showBackground: false,
barGap: "50%",
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: linearGradientColors[i][2] },
{ offset: 0.5, color: linearGradientColors[i][1] },
{ offset: 1, color: linearGradientColors[i][0] },
]),
borderColor: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: linearGradientColors[i][0] },
{ offset: 0.7, color: linearGradientColors[i][1] },
{ offset: 1, color: linearGradientColors[i][0] },
]),
},
emphasis: {
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: linearGradientColors[i][2] },
{ offset: 0.5, color: linearGradientColors[i][0] },
{ offset: 1, color: linearGradientColors[i][1] },
]),
},
},
data: item.values,
};
}),
});
},
{ deep: true }
);
const colors = ["#287CE7", "#F4CF3D", "#30C6DC"];
const linearGradientColors = [
["#01A5FA", "#086BA5", "#0E385A"],
["#E0B60D", "#78752F", "#143750"],
["#15D1C4", "#117883", "#0F3654"],
];
const option = {
backgroundColor: "transparent",
grid: {
top: "14%",
left: "0%",
right: "0%",
bottom: "4%",
containLabel: true,
},
tooltip: {
trigger: "axis",
backgroundColor: "rgba(0, 0, 0, 0.8)",
borderColor: "#000000",
borderWidth: 1,
textStyle: {
color: "#ffffff",
fontSize: 12,
},
padding: 10,
valueFormatter: (value) => `${value}份`,
},
xAxis: {
type: 'category',
data: [],
axisLabel: {
color: "#ffffff",
fontSize: 10,
},
axisLine: {
lineStyle: {
color: "#21303C",
},
},
},
yAxis: {
min: 0,
axisLine: {
lineStyle: {
color: "#00ffff",
},
},
axisLabel: {
color: "#ffffff",
fontSize: 10,
},
splitLine: {
lineStyle: {
color: "rgba(255, 255, 255, 0.2)",
},
},
},
legend: {
icon: "rect",
right: 0,
top: 0,
itemWidth: 10,
itemHeight: 8,
itemGap: 16,
textStyle: { color: "#ffffff", fontSize: 9 },
itemStyle: { borderWidth: 0, borderColor: "transparent" },
data: props.data.map((item, i) => {
return { name: item.text, itemStyle: { color: colors[i], borderWidth: 0, borderColor: "transparent" } };
}),
},
series: props.data.map((item, i) => {
return {
type: "bar",
stack: 'total',
name: item.text,
showBackground: false,
barGap: "50%",
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: linearGradientColors[i][2] },
{ offset: 0.5, color: linearGradientColors[i][1] },
{ offset: 1, color: linearGradientColors[i][0] },
]),
borderColor: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: linearGradientColors[i][0] },
{ offset: 0.7, color: linearGradientColors[i][1] },
{ offset: 1, color: linearGradientColors[i][0] },
]),
},
emphasis: {
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: linearGradientColors[i][2] },
{ offset: 0.5, color: linearGradientColors[i][0] },
{ offset: 1, color: linearGradientColors[i][1] },
]),
},
},
data: item.values,
};
}),
};
const resizeHandler = () => {
if (chartInstance) chartInstance.resize();
};
onMounted(() => {
if (!chartRef.value) return;
chartInstance = echarts.init(chartRef.value);
chartInstance.setOption(option);
window.addEventListener("resize", resizeHandler);
chartInstance.on("click", function (params) {
const target = props.labels[params.dataIndex];
if (!target) return;
const [timeStr, _] = target.split("|");
const _params = {
swingTimeList: [
dayjs(timeStr).startOf("day").format("YYYY-MM-DD HH:mm:ss"),
dayjs(timeStr).endOf("day").format("YYYY-MM-DD HH:mm:ss"),
],
};
console.log(`|点击跳转|-|打卡统计|-|本周|params:|{${JSON.stringify(_params)}}|`);
jumpAdminPath("door_reign_record", _params);
});
});
onBeforeUnmount(() => {
window.removeEventListener("resize", resizeHandler);
if (chartInstance) {
chartInstance.dispose();
chartInstance = null;
}
});
</script>