gerson
2024-08-04 f052d279131a056cb82c178ae195f463caa72c33
新增表格展示方式
已修改4个文件
已添加1个文件
258 ■■■■ 文件已修改
src/components/chat/chatComponents/normalTextCom/NormalTextCom.vue 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/chatComponents/summaryCom/SummaryCom.vue 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/chatComponents/summaryCom/components/recordSet/RecordSet.vue 91 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/chatComponents/summaryCom/components/recordSetTable/RecordSetTable.vue 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/chatComponents/summaryCom/components/types.ts 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/chatComponents/normalTextCom/NormalTextCom.vue
@@ -6,6 +6,8 @@
import { md } from '../../libs/markdown';
import { chatComProps } from '../common';
const props = defineProps(chatComProps);
const props = defineProps({
    data:String
});
</script>
<style scoped lang="scss"></style>
src/components/chat/chatComponents/summaryCom/SummaryCom.vue
@@ -1,8 +1,8 @@
<template>
    <div class="w-full space-y-3">
        <template v-if="data && data.length > 0">
        <template v-if="parsedData && parsedData.length > 0">
            <component
                v-for="(item, index) in data"
                v-for="(item, index) in parsedData"
                :key="item.id"
                :id="item.id"
                :is="summaryAnswerTypeMapCom[item.type]"
@@ -15,8 +15,20 @@
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { chatComProps } from '../common';
import { summaryAnswerTypeMapCom } from './components/types';
import { SummaryAnswerType, summaryAnswerTypeMapCom } from './components/types';
const props = defineProps(chatComProps);
const parsedData = computed(() => {
    const newData = (props.data ?? []).map((item) => {
        if (item.type === SummaryAnswerType.RecordSet && item.chart === 'table') {
            item.type = SummaryAnswerType.RecordSetTable;
        }
        return item;
    });
    return newData;
});
</script>
<style scoped lang="scss"></style>
src/components/chat/chatComponents/summaryCom/components/recordSet/RecordSet.vue
@@ -341,6 +341,50 @@
    }
};
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>
                    <div style="clear: both"></div>
                </div>
                <div style="clear: both"></div>
            </div>`;
            });
            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">
                    ${itemList.join('')}
                        <div style="clear: both"></div>
                    </div>
                    <div style="clear: both"></div>
                </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;
            },
            showMaxLabel: true,
        },
    },
} as echarts.EChartsOption);
//#region ====================== è®¾ç½®Y范围 ======================
const debounceSetYRange = debounce((val) => {
    chartInstance.value.setOption({
@@ -388,52 +432,9 @@
    const series = seriesData.map<echarts.SeriesOption>((item) => ({
        name: item[0]?.[nameIndex],
        data: item.map((item) => [item[timeIndex], item[valueIndex]]),
        ...getChartTypeSeriesOption(activeChartType)
        ...getChartTypeSeriesOption(activeChartType),
    }));
    setNewOption(series, {
        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>
                    <div style="clear: both"></div>
                </div>
                <div style="clear: both"></div>
            </div>`;
                });
                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">
                    ${itemList.join('')}
                        <div style="clear: both"></div>
                    </div>
                    <div style="clear: both"></div>
                </div>
                <div style="clear: both"></div>
            </div>`;
                return result;
            },
        },
        xAxis: {
            min: COMMON_DAY + ' 00:00:00',
            max: COMMON_DAY + ' 23:59:59',
            splitNumber: 10,
            axisLabel: {
                formatter: (val) => {
                    const newVal = moment(val).format('HH:mm');
                    return newVal;
                },
                showMaxLabel: true,
            },
        },
    });
    setNewOption(series, getSingleDayOption());
};
const multiCompareChange = (val) => {
    if (!groupedValues) return;
src/components/chat/chatComponents/summaryCom/components/recordSetTable/RecordSetTable.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,135 @@
<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">
            <el-table
                ref="tableRef"
                border
                :cell-style="{ textAlign: 'center' }"
                :header-cell-style="{ textAlign: 'center' }"
                :data="data?.values"
                highlight-current-row
                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
                    />
                </template>
            </el-table>
        </div>
    </div>
</template>
<script setup lang="ts">
import type { TableInstance } from 'element-plus';
import _ from 'lodash';
import { onMounted, ref, type PropType } from 'vue';
import { debounce, getTextWidth } from '/@/utils/util';
const props = defineProps({
    data: {
        type: Object as PropType<any>,
    },
});
const colList = ref([]);
const containerRef = ref<HTMLDivElement>(null);
const tableRef = ref<TableInstance>(null);
const measureWidthOffset = 28;
const resizeEvent = ({ width, height }) => {
    if (width === 0 || height === 0) {
        return;
    }
    if (props.data?.cols?.length > 0 && props.data?.values?.length > 0) {
        const maxStrList = props.data.cols.map((item) => item.title);
        const maxLenList = props.data.cols.map((item) => item.title.gblen());
        for (const item of props.data.values) {
            item.map((subItem, index) => {
                const subItemLen = subItem?.gblen();
                if (maxLenList[index] < subItemLen) {
                    maxLenList[index] = subItemLen;
                    maxStrList[index] = subItem;
                }
            });
        }
        // æ€»å®½
        let sumWidth = 0;
        let maxWidthList = maxStrList.map((item, index) => {
            const width =
                getTextWidth(item, {
                    size: '0.875rem',
                }) + measureWidthOffset;
            sumWidth += width;
            return {
                index,
                maxWidth: width,
            };
        });
        if (sumWidth <= width) {
            maxWidthList = maxWidthList.map((item) => ({
                ...item,
                width: (item.maxWidth / sumWidth) * width,
            }));
            // å…ˆæ»¡è¶³å°çš„,剩余空间按比例均分
        } else {
            let curWidth = 0;
            const sortedWidthList = _.sortBy(maxWidthList, 'maxWidth');
            let restWidth = width;
            let notFitStartIndex = 1;
            for (let index = 0; index < sortedWidthList.length; index++) {
                const item = sortedWidthList[index];
                curWidth += item.maxWidth;
                if (curWidth < width || index === 0) {
                    maxWidthList[item.index].width = item.maxWidth;
                    continue;
                }
                restWidth = width - (curWidth - item.maxWidth);
                notFitStartIndex = index;
                break;
            }
            let sumRestMaxWidth = 0;
            const notFitIndexList = sortedWidthList.slice(notFitStartIndex).map((item) => {
                sumRestMaxWidth += item.maxWidth;
                return item.index;
            });
            // å¹³å‡åˆ†é…å‰©ä½™ç©ºé—´
            for (const item of notFitIndexList) {
                maxWidthList[item].width = restWidth * (maxWidthList[item].maxWidth / sumRestMaxWidth);
                if (maxWidthList[item].maxWidth <= restWidth) {
                    maxWidthList[item].width = restWidth;
                }
                // maxWidthList[item].width = undefined;
            }
        }
        colList.value = props.data.cols.map((item, index) => ({
            ...item,
            width: maxWidthList[index].width,
        }));
    } else {
        colList.value = [];
    }
    tableRef.value.doLayout();
};
const resizeHandler = debounce(resizeEvent);
onMounted(() => {
    resizeEvent({
        width: containerRef.value.clientWidth,
        height: 0.7 * document.body.clientHeight,
    });
});
</script>
<style scoped lang="scss"></style>
src/components/chat/chatComponents/summaryCom/components/types.ts
@@ -1,6 +1,8 @@
import HTMLCom from '../../htmlCom/HTMLCom.vue';
import MapCom from '../../mapCom/MapCom.vue';
import RecordSet from './recordSet/RecordSet.vue';
import RecordSetTable from './recordSetTable/RecordSetTable.vue';
import Summary from './summary/Summary.vue';
import DeviceLastValueCom from './deviceLastValue/DeviceLastValueCom.vue';
@@ -9,7 +11,9 @@
    Summary = 'summary',
    Url = 'url',
    Map = 'map',
    DeviceLastValue='device_last_value'
    DeviceLastValue='device_last_value',
    /** @description åŽç«¯å¹¶æ²¡æœ‰å¢žåŠ ä¸€ä¸ªæ–°çš„ table ç±»åž‹ï¼Œè€Œæ˜¯å½“成 recordset çš„一种特列 */
    RecordSetTable = 'recordsetTable'
}
export const summaryAnswerTypeMapCom = {
@@ -17,5 +21,7 @@
    [SummaryAnswerType.Summary]: Summary,
    [SummaryAnswerType.Url]: HTMLCom,
    [SummaryAnswerType.Map]: MapCom,
    [SummaryAnswerType.DeviceLastValue]:DeviceLastValueCom
    [SummaryAnswerType.DeviceLastValue]:DeviceLastValueCom,
    [SummaryAnswerType.RecordSetTable]:RecordSetTable,
};