This commit is contained in:
Free-sss 2025-08-27 15:26:27 +08:00
commit d9d12a34d1
4 changed files with 415 additions and 112 deletions

View File

@ -5,7 +5,7 @@ export const LineGraph01: ConfigType = {
key: 'LineGraph01Haz', key: 'LineGraph01Haz',
chartKey: 'VLineGraph01Haz', chartKey: 'VLineGraph01Haz',
conKey: 'VCLineGraph01Haz', conKey: 'VCLineGraph01Haz',
title: '曲线图(带边框,标题)', title: '报警处置情况',
category: 'HazardousChemicalsSpace', category: 'HazardousChemicalsSpace',
categoryName: '危化品场景', categoryName: '危化品场景',
package: 'Charts', package: 'Charts',

View File

@ -3,7 +3,7 @@
<img src="./assets/title.svg" class="svg" /> <img src="./assets/title.svg" class="svg" />
<div class="buttonContent"> <div class="buttonContent">
<span class="title">{{ configData.title }}</span> <span class="title">报警处置情况</span>
</div> </div>
<!-- 使用新的下拉选择器组件 --> <!-- 使用新的下拉选择器组件 -->
@ -15,25 +15,22 @@
<div class="textContent"> <div class="textContent">
<div class="textInContent"> <div class="textInContent">
<span class="smallText">{{ configData.names[0] }} </span> <span class="smallText">报警总数 </span>
<span class="bigText">{{ configData.dataSource[selectedIndex].values[0]?.toLocaleString('en-US') <span class="bigText">{{ currentData.alertTotal?.toLocaleString('en-US') || '0' }}</span>
}}</span>
</div> </div>
<div class="textInContent"> <div class="textInContent">
<span class="smallText">{{ configData.names[1] }}</span> <span class="smallText">未处置报警数</span>
<span class="bigText">{{ configData.dataSource[selectedIndex].values[1]?.toLocaleString('en-US') <span class="bigText">{{ currentData.unprocessedAlert?.toLocaleString('en-US') || '0' }}</span>
}}</span>
</div> </div>
<div class="textInContent"> <div class="textInContent">
<span class="smallText">{{ configData.names[2] }}</span> <span class="smallText">平均处置时长</span>
<span class="bigText">{{ configData.dataSource[selectedIndex].values[2]?.toLocaleString('en-US') <span class="bigText">{{ currentData.averageResolutionTime?.toLocaleString('en-US') || '0' }}</span>
}}</span>
</div> </div>
</div> </div>
<div class="chartsContent"> <div class="chartsContent">
<span class="smallText Tips"> <span class="smallText Tips">
<img class="icon" src="./icon01.png" alt=""> <img class="icon" src="./icon01.png" alt="">
{{ configData.tip }}</span> 数据统计图表</span>
<v-chart ref="vChartRef" :init-options="initOptions" :theme="themeColor" :option="chartOption" :update-options="{ <v-chart ref="vChartRef" :init-options="initOptions" :theme="themeColor" :option="chartOption" :update-options="{
replaceMerge: replaceMergeArr replaceMerge: replaceMergeArr
}" autoresize> }" autoresize>
@ -42,20 +39,20 @@
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { PropType, computed, watch, ref, nextTick, onMounted, onUnmounted } from 'vue' import { PropType, computed, watch, ref, nextTick } from 'vue'
import VChart from 'vue-echarts' import VChart from 'vue-echarts'
import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook' import { useCanvasInitOptions } from '@/hooks/useCanvasInitOptions.hook'
import { use } from 'echarts/core' import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers' import { CanvasRenderer } from 'echarts/renderers'
import { LineChart } from 'echarts/charts' import { LineChart } from 'echarts/charts'
import Config, { DatasType, includes, seriesItem } from './config' import Config, { includes, seriesItem } from './config'
import { mergeTheme } from '@/packages/public/chart' import { mergeTheme } from '@/packages/public/chart'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { useChartDataFetch } from '@/hooks' import { useChartDataFetch } from '@/hooks'
import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components' import { DatasetComponent, GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'
import isObject from 'lodash/isObject' import isObject from 'lodash/isObject'
import CustomSelect from './select.vue' import CustomSelect from './select.vue'
import mockData1 from './mock1.json'
const props = defineProps({ const props = defineProps({
themeSetting: { themeSetting: {
@ -82,105 +79,118 @@ use([DatasetComponent, CanvasRenderer, LineChart, GridComponent, TooltipComponen
const replaceMergeArr = ref<string[]>() const replaceMergeArr = ref<string[]>()
// //
const selectOptions = computed(() => { const selectedTimeRange = ref('day')
return configData.value.dataSource.map((item, index) => ({
label: item.dataname, // mock1.jsonmock.json
value: index const convertMock1ToMockFormat = (mock1Data: any) => {
})) const convertedData: any = {}
Object.keys(mock1Data).forEach(timeRange => {
const dataArray = mock1Data[timeRange]
if (!Array.isArray(dataArray) || dataArray.length === 0) {
convertedData[timeRange] = {
alertTotal: 0,
unprocessedAlert: 0,
averageResolutionTime: 0,
datavalues: [['时间', '数值']]
}
return
}
//
const alertTotal = dataArray.reduce((sum, item) => sum + (item.alarm_count || 0), 0)
const unprocessedAlert = dataArray.reduce((sum, item) => sum + (item.un_alarm_count || 0), 0)
const avgHandleTimeSum = dataArray.reduce((sum, item) => sum + (item.avg_handle_time_seconds || 0), 0)
const averageResolutionTime = Math.round(avgHandleTimeSum / dataArray.length)
// datavalues
let datavalues: (string | number)[][] = [['时间', '数值']]
switch (timeRange) {
case 'day':
datavalues = [['时间', '数值'], ...dataArray.map(item => [
`${item.alarm_hour}:00`,
item.avg_handle_time_seconds || 0
])]
break
case 'week':
datavalues = [['时间', '数值'], ...dataArray.map(item => [
item.week_day_name || '',
item.avg_handle_time_seconds || 0
])]
break
case 'month':
datavalues = [['时间', '数值'], ...dataArray.map(item => [
item.alarm_date || '',
item.avg_handle_time_seconds || 0
])]
break
case 'quarter':
datavalues = [['时间', '数值'], ...dataArray.map(item => [
`${item.month}`,
item.avg_handle_time_seconds || 0
])]
break
case 'year':
datavalues = [['时间', '数值'], ...dataArray.map(item => [
`${item.month}`,
item.avg_handle_time_seconds || 0
])]
break
default:
datavalues = [['时间', '数值']]
}
convertedData[timeRange] = {
alertTotal,
unprocessedAlert,
averageResolutionTime,
datavalues
}
})
return convertedData
}
// mock1mock
const convertedMockData = convertMock1ToMockFormat(mockData1)
//
const getMockDataByTimeRange = (timeRange: string) => {
const defaultData = {
alertTotal: 0,
unprocessedAlert: 0,
averageResolutionTime: 0,
datavalues: [['时间', '数值']]
}
if (convertedMockData && convertedMockData[timeRange]) {
return convertedMockData[timeRange]
}
return defaultData
}
//
const currentData = computed(() => {
return getMockDataByTimeRange(selectedTimeRange.value)
}) })
const selectedIndex = ref(0); // //
// mockData
const parseMockData = (mockData: any): DatasType => {
const DEFAULT_MOCK_DATA: DatasType = {
title: '默认标题',
names: ['项1', '项2', '项3'],
tip: "默认提示",
dataIndex: 0,
dataSource: [{
dataname: '默认数据',
values: [0, 0, 0],
datavalues: [
['维度', '数值'],
['0', 0],
['1', 0],
['2', 0]
]
}]
};
let parsedData: DatasType;
if (typeof mockData === 'string') {
try {
const tempParsed = JSON.parse(mockData);
parsedData = (typeof tempParsed === 'object' && tempParsed !== null) ? tempParsed : DEFAULT_MOCK_DATA;
} catch (e) {
console.error('解析 mockData 字符串失败:', e);
parsedData = DEFAULT_MOCK_DATA;
}
} else if (typeof mockData === 'object' && mockData !== null) {
parsedData = mockData;
} else {
parsedData = DEFAULT_MOCK_DATA;
}
if (parsedData.dataIndex === undefined || parsedData.dataIndex < 0 || parsedData.dataIndex >= parsedData.dataSource.length) {
parsedData.dataIndex = 0;
}
if (!parsedData.dataSource || parsedData.dataSource.length === 0) {
parsedData.dataSource = DEFAULT_MOCK_DATA.dataSource;
}
if (!parsedData.names || parsedData.names.length === 0) parsedData.names = DEFAULT_MOCK_DATA.names;
return parsedData;
};
const configData = computed<DatasType>(() => {
return parseMockData(props.chartConfig.mockData);
});
// mockData selectedIndex
watch(
() => props.chartConfig.mockData,
(newMockData) => {
const parsedData = parseMockData(newMockData);
selectedIndex.value = parsedData.dataIndex;
},
{ immediate: true, deep: true }
);
const chartOption = computed(() => { const chartOption = computed(() => {
const mergedOption = mergeTheme(props.chartConfig.option, props.themeSetting, includes); const mergedOption = mergeTheme(props.chartConfig.option, props.themeSetting, includes)
const currentDataSourceItem = configData.value.dataSource[selectedIndex.value];
const currentDatavalues = currentDataSourceItem ? currentDataSourceItem.datavalues : [];
if (!mergedOption.dataset) { if (!mergedOption.dataset) {
mergedOption.dataset = {}; mergedOption.dataset = {}
} }
mergedOption.dataset.source = currentDatavalues; mergedOption.dataset.source = currentData.value.datavalues
return mergedOption; return mergedOption
}); })
const wrapperStyle = computed(() => ({ // dataset
width: props.chartConfig.attr.w + 'px',
height: "16%"
}))
// dataset ()
watch( watch(
() => props.chartConfig.option.dataset, () => props.chartConfig.option.dataset,
(newData: { dimensions: any }, oldData) => { (newData: { dimensions: any }, oldData) => {
@ -207,15 +217,17 @@ watch(
) )
const { vChartRef } = useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => { const { vChartRef } = useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
//
}); })
// //
const handleSelectChange = (value: any) => { const handleSelectChange = (value: any) => {
props.chartConfig.option.dateTime.selectValue = value props.chartConfig.option.dateTime.selectValue = value
// selectedIndex.value = value selectedTimeRange.value = value
} }
//
selectedTimeRange.value = props.chartConfig.option.dateTime.selectValue || 'day'
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@include go(border-box) { @include go(border-box) {

View File

@ -0,0 +1,197 @@
{
"day": {
"alertTotal": 2623,
"unprocessedAlert ": 2624,
"averageResolutionTime": 2625,
"datavalues": [
[
"时间",
"数值"
],
[
"13:00",
99
],
[
"14:00",
19
],
[
"15:00",
75
],
[
"16:00",
26
],
[
"17:00",
35
],
[
"18:00",
20
],
[
"19:00",
10
]
]
},
"week": {
"alertTotal": 12623,
"unprocessedAlert ": 12624,
"averageResolutionTime": 12625,
"datavalues": [
[
"时间",
"数值"
],
[
"13:00",
93
],
[
"14:00",
20
],
[
"15:00",
88
],
[
"16:00",
23
],
[
"17:00",
90
],
[
"18:00",
1
],
[
"19:00",
29
]
]
},
"month": {
"alertTotal": 112623,
"unprocessedAlert ": 112624,
"averageResolutionTime": 625,
"datavalues": [
[
"时间",
"数值"
],
[
"13:00",
73
],
[
"14:00",
12
],
[
"15:00",
32
],
[
"16:00",
44
],
[
"17:00",
33
],
[
"18:00",
89
],
[
"19:00",
83
]
]
},
"quarter": {
"alertTotal": 312623,
"unprocessedAlert ": 312624,
"averageResolutionTime": 312625,
"datavalues": [
[
"时间",
"数值"
],
[
"13:00",
93
],
[
"14:00",
33
],
[
"15:00",
22
],
[
"16:00",
88
],
[
"17:00",
78
],
[
"18:00",
42
],
[
"19:00",
77
]
]
},
"year": {
"alertTotal": 1112623,
"unprocessedAlert ": 1112624,
"averageResolutionTime": 3625,
"datavalues": [
[
"时间",
"数值"
],
[
"13:00",
33
],
[
"14:00",
22
],
[
"15:00",
54
],
[
"16:00",
99
],
[
"17:00",
44
],
[
"18:00",
32
],
[
"19:00",
54
]
]
}
}

View File

@ -0,0 +1,94 @@
{
"day": [
{
"alarm_count": 79,
"un_alarm_count": 45,
"alarm_hour": 12,
"avg_handle_time_seconds": 9307.5949
},
{
"alarm_count": 71,
"un_alarm_count": 45,
"alarm_hour": 13,
"avg_handle_time_seconds": 5568.1831
}
],
"week": [
{
"alarm_count": 10,
"un_alarm_count": 45,
"week_day_name": "星期一",
"avg_handle_time_seconds": 6360,
"day_of_week": 2
},
{
"alarm_count": 15,
"un_alarm_count": 45,
"week_day_name": "星期二",
"avg_handle_time_seconds": 11996,
"day_of_week": 3
},
{
"alarm_count": 150,
"un_alarm_count": 45,
"week_day_name": "星期三",
"avg_handle_time_seconds": 7537.6067,
"day_of_week": 4
}
],
"month": [
{
"alarm_count": 10,
"un_alarm_count": 45,
"alarm_date": "2025-08-25",
"avg_handle_time_seconds": 6360,
"day_of_month": 25
},
{
"alarm_count": 15,
"un_alarm_count": 45,
"alarm_date": "2025-08-26",
"avg_handle_time_seconds": 11996,
"day_of_month": 26
},
{
"alarm_count": 150,
"un_alarm_count": 45,
"alarm_date": "2025-08-27",
"avg_handle_time_seconds": 7537.6067,
"day_of_month": 27
}
],
"quarter": [
{
"alarm_count": 175,
"un_alarm_count": 45,
"month": 7,
"avg_handle_time_seconds": 7852.4629,
"quarter": 3
},
{
"alarm_count": 175,
"un_alarm_count": 45,
"month": 8,
"avg_handle_time_seconds": 7852.4629,
"quarter": 3
}
],
"year": [
{
"alarm_count": 175,
"un_alarm_count": 45,
"month": 7,
"year": 2025,
"avg_handle_time_seconds": 7852.4629
},
{
"alarm_count": 175,
"un_alarm_count": 45,
"month": 8,
"year": 2025,
"avg_handle_time_seconds": 7852.4629
}
]
}