wujingjing
2024-07-24 4eb6092c32df67d752101ab8ae23c9b2236db0dc
监测点列表
已修改4个文件
已添加4个文件
322 ■■■■■ 文件已修改
src/components/chat/Chat.vue 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/chatComponents/summaryCom/SummaryCom.vue 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/chatComponents/summaryCom/components/deviceLastValue/DeviceLastValueCom.vue 203 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/chatComponents/summaryCom/components/deviceLastValue/MonitorContent.vue 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/chatComponents/summaryCom/components/deviceLastValue/constants.ts 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/chatComponents/summaryCom/components/deviceLastValue/types.ts 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/chatComponents/summaryCom/components/types.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/hooks/useAssistantContentOpt.ts 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/Chat.vue
@@ -36,7 +36,7 @@
                                                        v-for="fixItem in item.content.origin.err_json.fix_question?.values"
                                                        :key="fixItem"
                                                        class="bg-gray-200 p-3 hover:bg-[#c5e0ff] hover:text-[#1c86ff] cursor-pointer rounded-lg"
                                                        @click="fixQuestionClick(fixItem)"
                                                        @click="fixQuestionClick(fixItem, item.content.origin)"
                                                    >
                                                        {{ fixItem.title }}
                                                    </div>
@@ -237,6 +237,11 @@
        ElMessage.warning('发送失败,未确定应用场景!');
    }
    processId.value = uuidv4();
    const judgeParams = !preQuestion.value
        ? {}
        : {
                prev_question: preQuestion.value,
          };
    const params = {
        process_id: processId.value,
        question: text,
@@ -244,7 +249,7 @@
        section_a_id: currentSectionId,
        history_group_id: currentRouteId,
        raw_mode: roomConfig.value?.[currentRouteId]?.isAnswerByLLM ?? false,
        next_chat: isNextChat.value,
        ...judgeParams,
    } as any;
    if (currentSampleId) {
@@ -404,7 +409,7 @@
    feedbackClick,
    askMoreClick,
    fixQuestionClick,
    isNextChat,
    preQuestion,
    showFixQuestion,
    showAskMore,
} = useAssistantContentOpt({
src/components/chat/chatComponents/summaryCom/SummaryCom.vue
@@ -2,17 +2,20 @@
    <div class="w-full space-y-3">
        <template v-if="data && data.length > 0">
            <!-- ä¸èƒ½ä½¿ç”¨ index -->
            <component v-for="(item, index) in data" :key="item.id" :id="item.id" :is="summaryAnswerTypeMapCom[item.type]" :data="item"></component>
            <component
                v-for="(item, index) in data"
                :key="item.id"
                :id="item.id"
                :is="summaryAnswerTypeMapCom[item.type]"
                :data="item"
            ></component>
        </template>
    </div>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { chatComProps } from '../common';
import { summaryAnswerTypeMapCom } from './components/types';
const props = defineProps(chatComProps);
</script>
<style scoped lang="scss"></style>
src/components/chat/chatComponents/summaryCom/components/deviceLastValue/DeviceLastValueCom.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,203 @@
<template>
    <div ref="containerRef" class="w-full flex justify-center" v-resize="resizeHandler">
        <div class="inline-block">
            <div
                :class="`space-y-[${THICK_BORDER_WIDTH}px]`"
                :style="{
                    border: `${THICK_BORDER_WIDTH}px solid ${BORDER_COLOR}`,
                    backgroundColor: BORDER_COLOR,
                }"
            >
                <div
                    v-for="(rowChunk, index) in currentRowChunkList"
                    :key="index"
                    :class="`space-y-[${THIN_BORDER_WIDTH}px]`"
                    :style="{
                        backgroundColor: BORDER_COLOR,
                    }"
                >
                    <!-- è¡¨å¤´ï¼Œå’Œè¡¨æ ¼å†…容第一行 -->
                    <div
                        :class="`space-y-[${THICK_BORDER_WIDTH}px]`"
                        :style="{
                            backgroundColor: BORDER_COLOR,
                        }"
                    >
                        <div
                            class="flex"
                            :class="`space-x-[${THICK_BORDER_WIDTH}px]`"
                            :style="{
                                backgroundColor: COL_HEADER_CELL_BG_COLOR,
                            }"
                        >
                            <div
                                v-for="(item, index) in maxColsNum"
                                :key="item"
                                :class="COL_HEADER_CELL_CLASS"
                                :style="{
                                    width: `${CELL_WIDTH}px`,
                                    height: `${CELL_HEIGHT}px`,
                                    backgroundColor: COL_HEADER_CELL_BG_COLOR,
                                }"
                            >
                                {{ index === 0 ? '' : rowChunk[index - 1]?.OTITLE }}
                            </div>
                        </div>
                        <MonitorContent v-if="firstRow" :title="firstRow.title" :type="firstRow.id" :values="rowChunk" />
                    </div>
                    <!-- å‰©ä½™è¡Œ -->
                    <MonitorContent v-for="(row, index) in restRows" :key="index" :title="row.title" :type="row.id" :values="rowChunk" />
                </div>
            </div>
            <el-pagination
                small
                hide-on-single-page
                v-model:current-page="pageIndex"
                v-model:page-size="pageSize"
                layout="total,prev,pager,next,jumper"
                :total="total"
                @current-change="handleCurrentChange"
            />
        </div>
    </div>
</template>
<script setup lang="ts">
import _ from 'lodash';
import { computed, onMounted, ref } from 'vue';
import MonitorContent from './MonitorContent.vue';
import { debounce } from '/@/utils/util';
import { chatComProps } from '../../../common';
import {
    BORDER_COLOR,
    CELL_HEIGHT,
    CELL_WIDTH,
    COL_HEADER_CELL_BG_COLOR,
    COL_HEADER_CELL_CLASS,
    PAGE_HEIGHT,
    THICK_BORDER_WIDTH,
    THIN_BORDER_WIDTH,
} from './constants';
import type { Monitor, MonitorValue } from './types';
const props = defineProps(chatComProps) as {
    data: Monitor;
};
const total = props.data?.values?.length ?? 0;
const pageIndex = ref(null);
const pageSize = ref(null);
const containerRef = ref<HTMLDivElement>(null);
let maxColsNum = ref<number>(null);
const resizeEvent = ({ width, height }) => {
    // æŒ‰æœ€å¤§å®½åº¦ç®—最大列数
    maxColsNum.value = Math.floor((width - THICK_BORDER_WIDTH) / (CELL_WIDTH + THICK_BORDER_WIDTH));
    const groupCount = (props.data?.rows?.length ?? 0) + 1;
    const calcMaxRowsNum = (height, extraHeight = 0) => {
        return Math.floor(
            (height - THICK_BORDER_WIDTH - extraHeight) /
                (CELL_HEIGHT * groupCount + 2 * THICK_BORDER_WIDTH + THIN_BORDER_WIDTH * (groupCount - 2))
        );
    };
    // æŒ‰æœ€å¤§é«˜åº¦ç®—最大行数
    let rowsNum = calcMaxRowsNum(height);
    // æŒ‰æœ€å¤§åˆ—数铺
    const maxColsRowsNum = Math.ceil(total / maxColsNum.value);
    const isNeedPage = maxColsRowsNum > rowsNum;
    rowsNum = isNeedPage ? calcMaxRowsNum(height, PAGE_HEIGHT) : maxColsRowsNum;
    // rowsNum è¡Œï¼ŒmaxColsNum列,第一列不算
    pageSize.value = isNeedPage ? rowsNum * (maxColsNum.value - 1) : total;
    pageIndex.value = 1;
    // isNeedPage æ˜¯å¦åˆ†é¡µï¼ŒrowsNum è¡Œæ•°ï¼ŒmaxColsNum åˆ—数,
};
const resizeHandler = debounce(resizeEvent);
const handleCurrentChange = () => {};
const firstRow = computed(() => props.data?.rows?.[0]);
const restRows = computed(() => props.data?.rows?.slice(1));
const pageChunkList = computed(() => {
    const chunkResult = _.chunk(props.data.values ?? [], pageSize.value);
    const last = chunkResult.at(-1);
    if (last) {
        const restNum = pageSize.value - last.length;
        const emptyData = _.fill(Array(restNum), {
            ONAME: '',
            OTIME: '',
            OTITLE: '',
            OTYPE: '',
        } as MonitorValue);
        const lastData = last.concat(emptyData);
        chunkResult[chunkResult.length - 1] = lastData;
    }
    return chunkResult;
});
const currentPageChunk = computed(() => {
    pageChunkList.value;
    if (pageIndex.value == null) return [];
    const pageChunk = pageChunkList.value[pageIndex.value - 1];
    return pageChunk;
});
const currentRowChunkList = computed(() => {
    if (!currentPageChunk.value || currentPageChunk.value.length === 0) return [];
    const chunkResult = _.chunk(currentPageChunk.value, maxColsNum.value - 1);
    return chunkResult;
});
// è®¡ç®—最大列数
// x* cellWidth+thickBorderWidth*(x-1)+thickBorderWidth*2 <= width;
// x*(cellWidth+thickBorderWidth)+thickBorderWidth<=width;
// x<= (width-thickBorderWidth)/(cellWidth+thickBorderWidth);
// const groupCount = (TEST_DATA?.rows?.length ?? 0) + 1;
// è®¡ç®—最大行数
// y * (cellHeight * groupCount) +
//     (y - 1) * (2 * thickBorderWidth) +
//     thickBorderWidth +
//     thickBorderWidth * 2 +
//     y * (groupCount - 2) * thinBorderWidth <=
//     height;
// (cellHeight * groupCount + 2 * thickBorderWidth + thinBorderWidth(groupCount - 2) * groupCount) * y + thickBorderWidth <=height;
// y<= (height-thickBorderWidth)/(cellHeight * groupCount + 2 * thickBorderWidth + thinBorderWidth(groupCount - 2) * groupCount)
onMounted(() => {
    resizeEvent({
        width: containerRef.value.clientWidth,
        height: 0.7 * document.body.clientHeight,
    });
});
</script>
<style scoped lang="scss">
:deep(.space-y-\[2px\] > :not([hidden]) ~ :not([hidden])) {
    --tw-space-y-reverse: 0;
    margin-top: calc(2px * calc(1 - var(--tw-space-y-reverse)));
    margin-bottom: calc(2px * var(--tw-space-y-reverse));
}
:deep(.space-y-\[1px\] > :not([hidden]) ~ :not([hidden])) {
    --tw-space-y-reverse: 0;
    margin-top: calc(1px * calc(1 - var(--tw-space-y-reverse)));
    margin-bottom: calc(1px * var(--tw-space-y-reverse));
}
:deep(.space-x-\[2px\] > :not([hidden]) ~ :not([hidden])) {
    --tw-space-x-reverse: 0;
    margin-right: calc(2px * var(--tw-space-x-reverse));
    margin-left: calc(2px * calc(1 - var(--tw-space-x-reverse)));
}
:deep(.space-x-\[1px\] > :not([hidden]) ~ :not([hidden])) {
    --tw-space-x-reverse: 0;
    margin-right: calc(1px * var(--tw-space-x-reverse));
    margin-left: calc(1px * calc(1 - var(--tw-space-x-reverse)));
}
</style>
src/components/chat/chatComponents/summaryCom/components/deviceLastValue/MonitorContent.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,51 @@
<template>
    <div
        class="flex cursor-none"
        :class="`space-x-[${THICK_BORDER_WIDTH}px]`"
        :style="{
            backgroundColor: BORDER_COLOR,
        }"
    >
        <div
            :class="ROW_HEADER_CELL_CLASS"
            :style="{
                width: `${CELL_WIDTH}px`,
                height: `${CELL_HEIGHT}px`,
            }"
        >
            {{ title }}
        </div>
        <div
            v-for="(item, index) in values"
            :key="index"
            :class="CONTENT_CELL_CLASS"
            :style="{
                width: `${CELL_WIDTH}px`,
                height: `${CELL_HEIGHT}px`,
            }"
        >
            {{ item[type] }}
        </div>
    </div>
</template>
<script setup lang="ts">
import type { PropType } from 'vue';
import { BORDER_COLOR, CELL_HEIGHT, CELL_WIDTH, CONTENT_CELL_CLASS, ROW_HEADER_CELL_CLASS, THICK_BORDER_WIDTH } from './constants';
import type { MonitorValue } from './types';
const props = defineProps({
    /** @description æ ‡é¢˜ */
    title: {
        type: String,
    },
    /** @description ç±»åž‹ */
    type: {
        type: String,
    },
    /** @description å€¼ */
    values: {
        type: Object as PropType<MonitorValue[]>,
    },
});
</script>
<style scoped lang="scss"></style>
src/components/chat/chatComponents/summaryCom/components/deviceLastValue/constants.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,13 @@
export const CONTENT_CELL_CLASS = 'bg-white flex-center flex-0 text-[#7331a5] cursor-pointer';
export const ROW_HEADER_CELL_CLASS = 'bg-white flex-center flex-0';
export const COL_HEADER_CELL_CLASS = 'font-bold  flex-center flex-0';
export const COL_HEADER_CELL_BG_COLOR = '#c5d9f1'
export const CELL_WIDTH = 198;
export const CELL_HEIGHT = 32;
export const THIN_BORDER_WIDTH = 1;
export const THICK_BORDER_WIDTH = 2;
export const PAGE_HEIGHT = 54;
export const rowCount = 5;
export const BORDER_COLOR = '#90b6e2';
src/components/chat/chatComponents/summaryCom/components/deviceLastValue/types.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
import type { SummaryAnswerType } from '../types';
export type MonitorRow = {
    id: string;
    title: string;
};
export type MonitorValue = {
    OTYPE: string;
    ONAME: string;
    OTITLE: string;
    OTIME: string;
    ZD: number;
    YL: number;
};
export type Monitor = {
    type: SummaryAnswerType.DeviceLastValue;
    rows: MonitorRow[];
    values: MonitorValue[];
};
src/components/chat/chatComponents/summaryCom/components/types.ts
@@ -2,12 +2,14 @@
import MapCom from '../../mapCom/MapCom.vue';
import RecordSet from './recordSet/RecordSet.vue';
import Summary from './summary/Summary.vue';
import DeviceLastValueCom from './deviceLastValue/DeviceLastValueCom.vue';
export const enum SummaryAnswerType {
    RecordSet = 'recordset',
    Summary = 'summary',
    Url = 'url',
    Map = 'map',
    DeviceLastValue='device_last_value'
}
export const summaryAnswerTypeMapCom = {
@@ -15,4 +17,5 @@
    [SummaryAnswerType.Summary]: Summary,
    [SummaryAnswerType.Url]: HTMLCom,
    [SummaryAnswerType.Map]: MapCom,
    [SummaryAnswerType.DeviceLastValue]:DeviceLastValueCom
};
src/components/chat/hooks/useAssistantContentOpt.ts
@@ -16,7 +16,7 @@
export const useAssistantContentOpt = (option: AssistantContentOptOption) => {
    const { forbidScroll, sendChatMessage, displayMessageList } = option;
    const { toClipboard } = useClipboard();
    const isNextChat = ref(false);
    const preQuestion = ref(null);
    const copyClick = (item) => {
        const type = item.content.type;
@@ -103,16 +103,16 @@
        sendChatMessage({ type: AnswerType.Text, values: item.question });
    };
    const fixQuestionClick = (item) => {
    const fixQuestionClick = (item,originData) => {
        if (!item.question) return;
        isNextChat.value = true;
        preQuestion.value = originData?.question;
        try {
            sendChatMessage({
                type: AnswerType.Text,
                values: item.question,
            });
        } finally {
            isNextChat.value = false;
            preQuestion.value = null;
        }
    };
@@ -129,7 +129,7 @@
        feedbackClick,
        askMoreClick,
        fixQuestionClick,
        isNextChat,
        preQuestion,
        showAskMore,
        showFixQuestion,
    };