| | |
| | | import { computed, ref } from 'vue'; |
| | | import { SCATTER_SYMBOL_SIZE, getChatChartOption } from '../../../common'; |
| | | import { useDrawChatChart } from '../../../hooks/useDrawChatChart'; |
| | | import { ChartTypeEnum } from '../../../types'; |
| | | import YRange from './components/YRange.vue'; |
| | | import type { RecordSet, RecordSetParamsItem } from './types'; |
| | | import { RecordSetParamsType, recordSetMapCom } from './types'; |
| | | import { RecordSetParamsType, recordSetMapCom, scoreMap } from './types'; |
| | | import { filterQuery } from '/@/api/ai/chat'; |
| | | import { deepClone } from '/@/utils/other'; |
| | | import { debounce } from '/@/utils/util'; |
| | | import { ChartTypeEnum } from '../../../types'; |
| | | import { axisLabelFormatter } from '/@/utils/chart'; |
| | | |
| | | const chartRef = ref<HTMLDivElement>(null); |
| | | const defaultDisplayType = 'line'; |
| | | const yRange = ref({ |
| | | min: null as number, |
| | | max: null as number, |
| | |
| | | |
| | | let preData = null; |
| | | |
| | | |
| | | const originChartType = props.data.chart_type; |
| | | let activeChartType: ChartTypeEnum = props.data?.chart_type ?? ChartTypeEnum.Line; |
| | | |
| | | const getChartTypeSeriesOption = (type: ChartTypeEnum) => { |
| | |
| | | }; |
| | | |
| | | break; |
| | | case ChartTypeEnum.Score: |
| | | result = { |
| | | type: 'bar', |
| | | symbol: 'none', |
| | | }; |
| | | |
| | | break; |
| | | |
| | | default: |
| | | break; |
| | | } |
| | |
| | | return { |
| | | name: item === 'default' ? '' : item, |
| | | data: values.map((item) => [item[timeIndex], item[valueIndex]]), |
| | | ...getChartTypeSeriesOption(activeChartType) |
| | | |
| | | ...getChartTypeSeriesOption(activeChartType), |
| | | }; |
| | | }); |
| | | } |
| | | const combineOption = _.defaultsDeep(extraOption, getChatChartOption(), { |
| | | grid: { |
| | | bottom: 20, |
| | | }, |
| | | legend: { |
| | | top: 19, |
| | | show: series?.length > 1, |
| | | type: 'scroll', |
| | | }, |
| | | toolbox: { |
| | | show: true, |
| | | feature: { |
| | | myBar: { |
| | | onclick: () => { |
| | | activeChartType = ChartTypeEnum.Bar; |
| | | chartInstance.value.setOption({ |
| | | series: series.map((item) => ({ |
| | | ...item, |
| | | ...getChartTypeSeriesOption(activeChartType), |
| | | })), |
| | | }); |
| | | }, |
| | | }, |
| | | const yAxisFormatter = |
| | | originChartType === ChartTypeEnum.Score |
| | | ? (value) => { |
| | | return scoreMap[value]; |
| | | } |
| | | : axisLabelFormatter; |
| | | |
| | | myScatter: { |
| | | onclick: () => { |
| | | activeChartType = ChartTypeEnum.Scatter; |
| | | const tooltipValueFormatter = |
| | | originChartType === ChartTypeEnum.Score |
| | | ? (value) => { |
| | | return scoreMap[value]; |
| | | } |
| | | : undefined; |
| | | |
| | | chartInstance.value.setOption({ |
| | | series: series.map((item) => ({ |
| | | ...item, |
| | | ...getChartTypeSeriesOption(activeChartType), |
| | | })), |
| | | }); |
| | | const scoreYAxisOption: echarts.YAXisComponentOption = { |
| | | min: 0, |
| | | max: 4, |
| | | interval: 1, |
| | | axisLabel: { |
| | | formatter: yAxisFormatter, |
| | | }, |
| | | }; |
| | | const combineOption = _.defaultsDeep( |
| | | { |
| | | grid: { |
| | | bottom: 20, |
| | | }, |
| | | legend: { |
| | | top: 19, |
| | | show: true, |
| | | type: 'scroll', |
| | | }, |
| | | tooltip: { |
| | | valueFormatter: tooltipValueFormatter, |
| | | }, |
| | | toolbox: { |
| | | show: true, |
| | | feature: { |
| | | myBar: { |
| | | onclick: () => { |
| | | activeChartType = originChartType === ChartTypeEnum.Score ? ChartTypeEnum.Score : ChartTypeEnum.Bar; |
| | | chartInstance.value.setOption({ |
| | | series: series.map((item) => ({ |
| | | ...item, |
| | | ...getChartTypeSeriesOption(activeChartType), |
| | | })), |
| | | }); |
| | | }, |
| | | }, |
| | | }, |
| | | myLine: { |
| | | onclick: () => { |
| | | activeChartType = ChartTypeEnum.Line; |
| | | chartInstance.value.setOption({ |
| | | series: series.map((item) => ({ |
| | | ...item, |
| | | ...getChartTypeSeriesOption(activeChartType), |
| | | })), |
| | | }); |
| | | |
| | | myScatter: { |
| | | onclick: () => { |
| | | activeChartType = ChartTypeEnum.Scatter; |
| | | |
| | | chartInstance.value.setOption({ |
| | | series: series.map((item) => ({ |
| | | ...item, |
| | | ...getChartTypeSeriesOption(activeChartType), |
| | | })), |
| | | }); |
| | | }, |
| | | }, |
| | | myLine: { |
| | | onclick: () => { |
| | | activeChartType = ChartTypeEnum.Line; |
| | | chartInstance.value.setOption({ |
| | | series: series.map((item) => ({ |
| | | ...item, |
| | | ...getChartTypeSeriesOption(activeChartType), |
| | | })), |
| | | }); |
| | | }, |
| | | }, |
| | | }, |
| | | }, |
| | | }, |
| | | |
| | | title: { |
| | | text: preData?.title, |
| | | }, |
| | | xAxis: { |
| | | name: timeCol?.title, |
| | | }, |
| | | yAxis: { |
| | | name: valueCol?.title, |
| | | /** @description 不强制保留0 */ |
| | | scale: true, |
| | | }, |
| | | series: series, |
| | | } as echarts.EChartsOption); |
| | | title: { |
| | | text: preData?.title, |
| | | }, |
| | | xAxis: { |
| | | name: timeCol?.title, |
| | | }, |
| | | yAxis: { |
| | | name: valueCol?.title, |
| | | /** @description 不强制保留 */ |
| | | scale: true, |
| | | ...(originChartType === ChartTypeEnum.Score ? scoreYAxisOption : {}), |
| | | }, |
| | | series: series, |
| | | } as echarts.EChartsOption, |
| | | extraOption, |
| | | getChatChartOption() |
| | | ); |
| | | chartInstance.value.setOption(combineOption, { |
| | | notMerge: true, |
| | | }); |
| | |
| | | } |
| | | }; |
| | | |
| | | const getSingleDayOption = (day=COMMON_DAY) => ({ |
| | | tooltip: { |
| | | show: true, |
| | | trigger: 'axis', |
| | | formatter(params) { |
| | | const itemList = params.map((item, index) => { |
| | | return `<div style="margin: ${index === 0 ? 0 : 10}px 0 0; line-height: 1"> |
| | | const getSingleDayOption = (day = COMMON_DAY) => |
| | | ({ |
| | | tooltip: { |
| | | show: true, |
| | | trigger: 'axis', |
| | | formatter(params) { |
| | | const itemList = params.map((item, index) => { |
| | | return `<div style="margin: ${index === 0 ? 0 : 10}px 0 0; line-height: 1"> |
| | | <div style="margin: 0px 0 0; line-height: 1"> |
| | | ${item.marker}<span style="font-size: 14px; color: #666; font-weight: 400; margin-left: 2px" |
| | | >${item.seriesName}</span |
| | | ><span style="float: right; margin-left: 20px; font-size: 14px; color: #666; font-weight: 900">${item.data[1]}</span> |
| | | ><span style="float: right; margin-left: 20px; font-size: 14px; color: #666; font-weight: 900">${ |
| | | originChartType === ChartTypeEnum.Score ? scoreMap[item.data[1]] : item.data[1] |
| | | }</span> |
| | | <div style="clear: both"></div> |
| | | </div> |
| | | <div style="clear: both"></div> |
| | | </div>`; |
| | | }); |
| | | }); |
| | | |
| | | const result = `<div style="margin: 0px 0 0; line-height: 1"> |
| | | const result = `<div style="margin: 0px 0 0; line-height: 1"> |
| | | <div style="margin: 0px 0 0; line-height: 1"> |
| | | <div style="font-size: 14px; color: #666; font-weight: 400; line-height: 1">${params?.[0]?.data[0]?.slice(10, 16)}</div> |
| | | <div style="margin: 10px 0 0; line-height: 1"> |
| | |
| | | </div> |
| | | <div style="clear: both"></div> |
| | | </div>`; |
| | | return result; |
| | | }, |
| | | }, |
| | | xAxis: { |
| | | min: day + ' 00:00:00', |
| | | max: day + ' 23:59:59', |
| | | splitNumber: 10, |
| | | axisLabel: { |
| | | formatter: (val) => { |
| | | const newVal = moment(val).format('HH:mm'); |
| | | return newVal; |
| | | return result; |
| | | }, |
| | | showMaxLabel: true, |
| | | }, |
| | | }, |
| | | } as echarts.EChartsOption); |
| | | xAxis: { |
| | | min: day + ' 00:00:00', |
| | | max: day + ' 23:59:59', |
| | | splitNumber: 10, |
| | | axisLabel: { |
| | | formatter: (val) => { |
| | | const newVal = moment(val).format('HH:mm'); |
| | | return newVal; |
| | | }, |
| | | showMaxLabel: true, |
| | | }, |
| | | }, |
| | | } as echarts.EChartsOption); |
| | | //#region ====================== 设置Y范围 ====================== |
| | | const debounceSetYRange = debounce((val) => { |
| | | chartInstance.value.setOption({ |
| | |
| | | [RecordSetParamsType.StartTime]:Timestamp, |
| | | [RecordSetParamsType.EndTime]:Timestamp |
| | | }; |
| | | export const scoreMap = { |
| | | '0': '未评估', |
| | | '1': '坏', |
| | | '2': '中', |
| | | '3': '良', |
| | | '4': '优', |
| | | }; |
| | |
| | | <!-- 查询最新警告信息 --> |
| | | <template> |
| | | <div> |
| | | <span v-if="data?.title" class="text-base font-bold flex-center mb-5">{{ data?.title }}</span> |
| | | <div class="w-full" style="height: 70vh" ref="containerRef" v-resize="resizeHandler"> |
| | | <!-- <span v-if="data?.title" class="text-base font-bold flex-center mb-5">{{ data?.title }}</span> --> |
| | | <div class="w-full" ref="containerRef" v-resize="resizeHandler"> |
| | | <el-table |
| | | ref="tableRef" |
| | | maxHeight="70vh" |
| | | border |
| | | :cell-style="tableCellStyle" |
| | | :header-cell-style="tableHeaderCellStyle" |
| | | :data="data?.values" |
| | | :spanMethod="objectSpanMethod" |
| | | |
| | | class="w-full h-full" |
| | | cellClassName="text-sm" |
| | | headerCellClassName="text-sm" |
| | | > |
| | | <template v-if="data?.cols?.length > 0"> |
| | | <el-table-column |
| | | v-for="(item, index) in colList" |
| | | :label="item.title" |
| | | :width="item.width" |
| | | :sortable="item.type === 'time'" |
| | | :key="index" |
| | | :prop="index + ''" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column v-if="data?.title" :label="data?.title" show-overflow-tooltip> |
| | | <template v-if="data?.cols?.length > 0"> |
| | | <el-table-column |
| | | v-for="(item, index) in colList" |
| | | :label="item.title" |
| | | :width="item.width" |
| | | :sortable="item.type === 'time'" |
| | | :key="index" |
| | | :prop="index + ''" |
| | | show-overflow-tooltip |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <template v-else> |
| | | <template v-if="data?.cols?.length > 0"> |
| | | <el-table-column |
| | | v-for="(item, index) in colList" |
| | | :label="item.title" |
| | | :width="item.width" |
| | | :sortable="item.type === 'time'" |
| | | :key="index" |
| | | :prop="index + ''" |
| | | show-overflow-tooltip |
| | | /> |
| | | </template> |
| | | </template> |
| | | </el-table> |
| | | </div> |
| | |
| | | const containerRef = ref<HTMLDivElement>(null); |
| | | const tableRef = ref<TableInstance>(null); |
| | | const measureWidthOffset = 28; |
| | | |
| | | const groupColIndex = []; |
| | | (props.data?.cols ?? []).map((item, index) => { |
| | | if (item.group) { |
| | |
| | | const resizeHandler = debounce(resizeEvent); |
| | | //#region ====================== 样式 ====================== |
| | | const tableCellStyle = ({ row, rowIndex, column, columnIndex }): CSSProperties => { |
| | | const extraStyle = |
| | | columnIndex === 0 |
| | | ? { |
| | | borderLeft: `${THICK_BORDER_WIDTH}px solid ${BORDER_COLOR}`, |
| | | } |
| | | : {}; |
| | | if (columnIndex === 0) { |
| | | } |
| | | const extraStyle = { |
| | | ...(columnIndex === 0 ? { borderLeft: `${THICK_BORDER_WIDTH}px solid ${BORDER_COLOR}` } : {}), |
| | | }; |
| | | |
| | | return { |
| | | textAlign: 'center', |
| | | borderColor: BORDER_COLOR, |
| | |
| | | }; |
| | | |
| | | const tableHeaderCellStyle = ({ row, rowIndex, column, columnIndex }): CSSProperties => { |
| | | const extraStyle = |
| | | columnIndex === 0 |
| | | ? { |
| | | borderLeft: `${THICK_BORDER_WIDTH}px solid ${BORDER_COLOR}`, |
| | | } |
| | | : {}; |
| | | const extraStyle = { |
| | | ...(columnIndex === 0 ? { borderLeft: `${THICK_BORDER_WIDTH}px solid ${BORDER_COLOR}` } : {}), |
| | | ...(rowIndex === 0 ? { borderTop: `${THICK_BORDER_WIDTH}px solid ${BORDER_COLOR}`, backgroundColor: '#8db4e2',fontSize: '1rem'} : {}), |
| | | }; |
| | | |
| | | return { |
| | | textAlign: 'center', |
| | |
| | | }); |
| | | </script> |
| | | <style scoped lang="scss"> |
| | | |
| | | // :deep(.el-table--striped .el-table__body tr.el-table__row--striped td.el-table__cell){ |
| | | // background-color: v-bind(stripedBgColor); |
| | | // } |
| | |
| | | |
| | | export const enum ChartTypeEnum { |
| | | Scatter, |
| | | Line, |
| | | Bar, |
| | | Scatter = 'scatter', |
| | | Line = 'line', |
| | | Bar = 'bar', |
| | | Score = 'score' |
| | | } |
| | | |
| | | export const chartTypeMapName = { |
| | | [ChartTypeEnum.Line]: '折线图', |
| | | [ChartTypeEnum.Scatter]: '散点图', |
| | | [ChartTypeEnum.Bar]: '柱状图', |
| | | [ChartTypeEnum.Score]: '', |
| | | |
| | | }; |
| | | |
| | | export const chartTypeMapEchart = { |
| | | [ChartTypeEnum.Scatter]: 'scatter', |
| | | [ChartTypeEnum.Line]: 'line', |
| | | [ChartTypeEnum.Bar]: 'bar', |
| | | }; |