| | |
| | | import KpiCard from '../../components/kpi-card.vue'; |
| | | import PanelCard from '../../components/panel-card.vue'; |
| | | import { TIME_RANGE_OPTIONS } from '../../data/screen'; |
| | | import { chartSeries, pieTooltipFormatter, toPieData } from '../../data/screen-chart'; |
| | | import { useChartTheme, useScreenData, useScreenFieldSource } from '../../hooks/use-screen'; |
| | | |
| | | const { data, timeRange } = useScreenData(); |
| | |
| | | })); |
| | | |
| | | const sourceOption = computed(() => ({ |
| | | tooltip: { trigger: 'item', formatter: '{b}<br/>{c} kgCO₂e ({d}%)', ...tooltip() }, |
| | | tooltip: { trigger: 'item', ...tooltip(), formatter: pieTooltipFormatter('kgCO₂e') }, |
| | | legend: { bottom: 0, textStyle: { color: mutedColor.value } }, |
| | | series: [ |
| | | { |
| | |
| | | padAngle: 3, |
| | | itemStyle: { borderRadius: 6 }, |
| | | label: { color: textColor.value, formatter: '{b}\n{d}%' }, |
| | | data: data.value.recycleItems.map(e => ({ |
| | | name: e.name + '回收', |
| | | value: e.carbon, |
| | | itemStyle: { color: e.color } |
| | | })) |
| | | data: toPieData( |
| | | chartSeries(data.value.recycleItems, e => e.carbon, { carbon: true }), |
| | | e => e.name + '回收', |
| | | e => e.color |
| | | ) |
| | | } |
| | | ] |
| | | })); |
| | |
| | | import ScreenMapPanel from '../../components/screen-map-panel.vue'; |
| | | import CameraMonitor from '../../../monitor/views/cameras.vue'; |
| | | import { TIME_RANGE_OPTIONS } from '../../data/screen'; |
| | | import { chartSeries, pieTooltipFormatter, toPieData } from '../../data/screen-chart'; |
| | | import { useChartTheme, useScreenData, useScreenFieldSource } from '../../hooks/use-screen'; |
| | | |
| | | const { data, timeRange } = useScreenData(); |
| | |
| | | |
| | | /** 垃圾分类结构(饼) */ |
| | | const mixOption = computed(() => ({ |
| | | tooltip: { trigger: 'item', formatter: '{b}<br/>{c} ({d}%)', ...tooltip() }, |
| | | tooltip: { trigger: 'item', ...tooltip(), formatter: pieTooltipFormatter() }, |
| | | series: [ |
| | | { |
| | | type: 'pie', |
| | |
| | | padAngle: 3, |
| | | itemStyle: { borderRadius: 6 }, |
| | | label: { color: textColor.value, formatter: '{b}\n{d}%' }, |
| | | data: data.value.wasteMix.map(e => ({ |
| | | name: e.name, |
| | | value: e[mixMetric.value], |
| | | itemStyle: { color: e.color } |
| | | })) |
| | | data: toPieData( |
| | | chartSeries(data.value.wasteMix, e => e[mixMetric.value]), |
| | | e => e.name, |
| | | e => e.color |
| | | ) |
| | | } |
| | | ] |
| | | })); |
| | | |
| | | /** 碳减排来源(饼) */ |
| | | /** 碳减排来源(饼):碳值可为负,按绝对值展示减排量 */ |
| | | const carbonOption = computed(() => ({ |
| | | tooltip: { trigger: 'item', formatter: '{b}<br/>{c} kgCO₂e ({d}%)', ...tooltip() }, |
| | | tooltip: { trigger: 'item', ...tooltip(), formatter: pieTooltipFormatter('kgCO₂e') }, |
| | | series: [ |
| | | { |
| | | type: 'pie', |
| | |
| | | padAngle: 3, |
| | | itemStyle: { borderRadius: 6 }, |
| | | label: { color: textColor.value, formatter: '{b}\n{d}%' }, |
| | | data: data.value.recycleItems.map(e => ({ |
| | | name: e.name + '回收', |
| | | value: e.carbon, |
| | | itemStyle: { color: e.color } |
| | | })) |
| | | data: toPieData( |
| | | chartSeries(data.value.recycleItems, e => e.carbon, { carbon: true }), |
| | | e => e.name + '回收', |
| | | e => e.color |
| | | ) |
| | | } |
| | | ] |
| | | })); |
| | |
| | | |
| | | /** 各类回收量(横向条形) */ |
| | | const itemOption = computed(() => { |
| | | // 反转让数值最大的排在顶部 |
| | | const rows = [...data.value.recycleItems].reverse(); |
| | | const carbon = itemMetric.value === 'carbon'; |
| | | const rows = chartSeries( |
| | | data.value.recycleItems, |
| | | e => Number(e[itemMetric.value] || 0), |
| | | { carbon, evenSplit: false } |
| | | ).reverse(); |
| | | return { |
| | | grid: { containLabel: true, left: 8, right: 24, top: 12, bottom: 8 }, |
| | | tooltip: { |
| | |
| | | }, |
| | | yAxis: { |
| | | type: 'category', |
| | | data: rows.map(e => e.name), |
| | | data: rows.map(e => e.item.name), |
| | | axisLabel: { color: textColor.value }, |
| | | axisLine: { show: false }, |
| | | axisTick: { show: false } |
| | |
| | | { |
| | | type: 'bar', |
| | | barWidth: 14, |
| | | data: rows.map(e => Number(e[itemMetric.value] || 0)), |
| | | data: rows.map(e => e.value), |
| | | itemStyle: { |
| | | borderRadius: [0, 8, 8, 0], |
| | | // 沿用各类自身配色,与左侧碳减排饼图视觉一致 |
| | | color: (params: any) => rows[params.dataIndex]?.color || primary.value |
| | | color: (params: any) => rows[params.dataIndex]?.item.color || primary.value |
| | | } |
| | | } |
| | | ] |
| | |
| | | import PanelCard from '../../components/panel-card.vue'; |
| | | import ScreenCameraPreview from '../../components/screen-camera-preview.vue'; |
| | | import { TIME_RANGE_OPTIONS } from '../../data/screen'; |
| | | import { chartSeries, pieTooltipFormatter, toPieData } from '../../data/screen-chart'; |
| | | import { useChartTheme, useScreenData, useScreenFieldSource } from '../../hooks/use-screen'; |
| | | |
| | | const { data, timeRange } = useScreenData(); |
| | |
| | | ]); |
| | | |
| | | const mixOption = computed(() => ({ |
| | | tooltip: { trigger: 'item', formatter: '{b}<br/>{c} ({d}%)', ...tooltip() }, |
| | | tooltip: { trigger: 'item', ...tooltip(), formatter: pieTooltipFormatter() }, |
| | | legend: { bottom: 0, textStyle: { color: mutedColor.value } }, |
| | | series: [ |
| | | { |
| | |
| | | padAngle: 3, |
| | | itemStyle: { borderRadius: 6 }, |
| | | label: { color: textColor.value, formatter: '{b}\n{d}%' }, |
| | | data: data.value.wasteMix.map(e => ({ |
| | | name: e.name, |
| | | value: e[mixMetric.value], |
| | | itemStyle: { color: e.color } |
| | | })) |
| | | data: toPieData( |
| | | chartSeries(data.value.wasteMix, e => e[mixMetric.value]), |
| | | e => e.name, |
| | | e => e.color |
| | | ) |
| | | } |
| | | ] |
| | | })); |
| | |
| | | import { computed } from 'vue'; |
| | | import KpiCard from '../../components/kpi-card.vue'; |
| | | import PanelCard from '../../components/panel-card.vue'; |
| | | import { chartSeries, pieTooltipFormatter, toPieData } from '../../data/screen-chart'; |
| | | import { useChartTheme, useScreenData, useScreenFieldSource } from '../../hooks/use-screen'; |
| | | |
| | | const { data } = useScreenData(); |
| | |
| | | ]); |
| | | |
| | | const pieOption = computed(() => ({ |
| | | tooltip: { trigger: 'item', formatter: '{b}<br/>{c} kg ({d}%)', ...tooltip() }, |
| | | tooltip: { trigger: 'item', ...tooltip(), formatter: pieTooltipFormatter('kg') }, |
| | | legend: { bottom: 0, textStyle: { color: mutedColor.value } }, |
| | | series: [ |
| | | { |
| | |
| | | padAngle: 3, |
| | | itemStyle: { borderRadius: 6 }, |
| | | label: { color: textColor.value, formatter: '{b} {d}%' }, |
| | | data: data.value.recycleItems.map(e => ({ |
| | | name: e.name, |
| | | value: e.weight, |
| | | itemStyle: { color: e.color } |
| | | })) |
| | | data: toPieData( |
| | | chartSeries(data.value.recycleItems, e => e.weight), |
| | | e => e.name, |
| | | e => e.color |
| | | ) |
| | | } |
| | | ] |
| | | })); |
| | | |
| | | const weightRows = computed(() => |
| | | chartSeries(data.value.recycleItems, e => e.weight, { evenSplit: false }).reverse() |
| | | ); |
| | | |
| | | const weightOption = computed(() => ({ |
| | | grid: { containLabel: true, left: 8, right: 28, top: 12, bottom: 8 }, |
| | |
| | | }, |
| | | yAxis: { |
| | | type: 'category', |
| | | data: data.value.recycleItems.map(e => e.name).reverse(), |
| | | data: weightRows.value.map(e => e.item.name), |
| | | axisLabel: { color: textColor.value }, |
| | | axisLine: { show: false }, |
| | | axisTick: { show: false } |
| | |
| | | { |
| | | type: 'bar', |
| | | barWidth: 16, |
| | | data: data.value.recycleItems |
| | | .map(e => ({ value: e.weight, itemStyle: { color: e.color, borderRadius: [0, 8, 8, 0] } })) |
| | | .reverse() |
| | | data: weightRows.value.map(e => ({ |
| | | value: e.value, |
| | | itemStyle: { color: e.item.color, borderRadius: [0, 8, 8, 0] } |
| | | })) |
| | | } |
| | | ] |
| | | })); |
| | | |
| | | const valueRows = computed(() => |
| | | chartSeries(data.value.recycleItems, e => e.value, { evenSplit: false }) |
| | | ); |
| | | |
| | | const valueOption = computed(() => ({ |
| | | grid: { containLabel: true, left: 16, right: 16, top: 28, bottom: 8 }, |
| | | tooltip: { trigger: 'axis', ...tooltip() }, |
| | | xAxis: { |
| | | type: 'category', |
| | | data: data.value.recycleItems.map(e => e.name), |
| | | data: valueRows.value.map(e => e.item.name), |
| | | axisLabel: { color: mutedColor.value }, |
| | | axisLine: { show: false }, |
| | | axisTick: { show: false } |
| | |
| | | { |
| | | type: 'bar', |
| | | barWidth: 28, |
| | | data: data.value.recycleItems.map(e => e.value), |
| | | data: valueRows.value.map(e => e.value), |
| | | itemStyle: { color: primary.value, borderRadius: [6, 6, 0, 0] } |
| | | } |
| | | ] |