wujingjing
2024-07-25 3a64511eaac77a4677d0ecf41c65af6b56ea7978
表格自适应
已修改5个文件
已添加2个文件
210 ■■■■ 文件已修改
src/components/chat/chatComponents/summaryCom/components/deviceLastValue/DeviceLastValueCom.vue 135 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/chatComponents/summaryCom/components/deviceLastValue/MonitorContent.vue 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/chatComponents/summaryCom/components/deviceLastValue/constants.ts 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/extend/index.ts 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/extend/string.extensions.ts 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/util.ts 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/chatComponents/summaryCom/components/deviceLastValue/DeviceLastValueCom.vue
@@ -27,7 +27,7 @@
                            class="flex"
                            :class="`space-x-[${THICK_BORDER_WIDTH}px]`"
                            :style="{
                                backgroundColor: COL_HEADER_CELL_BG_COLOR,
                                backgroundColor: BORDER_COLOR,
                            }"
                        >
                            <div
@@ -35,7 +35,7 @@
                                :key="item"
                                :class="COL_HEADER_CELL_CLASS"
                                :style="{
                                    width: `${CELL_WIDTH}px`,
                                    width: `${index === 0 ? firstColWidth : restColWidth}px`,
                                    height: `${CELL_HEIGHT}px`,
                                    backgroundColor: COL_HEADER_CELL_BG_COLOR,
                                }"
@@ -43,13 +43,29 @@
                                {{ index === 0 ? '' : rowChunk[index - 1]?.OTITLE }}
                            </div>
                        </div>
                        <MonitorContent v-if="firstRow" :title="firstRow.title" :type="firstRow.id" :values="rowChunk" />
                        <MonitorContent
                            v-if="firstRow"
                            :firstColWidth="firstColWidth"
                            :restColWidth="restColWidth"
                            :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" />
                    <MonitorContent
                        v-for="(row, index) in restRows"
                        :key="index"
                        :firstColWidth="firstColWidth"
                        :restColWidth="restColWidth"
                        :title="row.title"
                        :type="row.id"
                        :values="rowChunk"
                    />
                </div>
            </div>
            <el-pagination
                style="margin-bottom: 0 !important"
                small
                hide-on-single-page
                v-model:current-page="pageIndex"
@@ -66,16 +82,17 @@
import _ from 'lodash';
import { computed, onMounted, ref } from 'vue';
import MonitorContent from './MonitorContent.vue';
import { debounce } from '/@/utils/util';
import { debounce, getTextWidth } from '/@/utils/util';
import { chatComProps } from '../../../common';
import {
    BORDER_COLOR,
    CELL_HEIGHT,
    CELL_WIDTH,
    CELL_MAX_WIDTH,
    COL_HEADER_CELL_BG_COLOR,
    COL_HEADER_CELL_CLASS,
    PAGE_HEIGHT,
    ROW_HEADER_CELL_MAX_WIDTH,
    THICK_BORDER_WIDTH,
    THIN_BORDER_WIDTH,
} from './constants';
@@ -89,27 +106,105 @@
const pageSize = ref(null);
const containerRef = ref<HTMLDivElement>(null);
const measureWidthOffset = 2;
/** @description æµ‹é‡é¦–列内容宽度 */
const rowHeaderCellContentWidth = computed(() => {
    if (!props.data.rows || props.data.rows.length === 0) return 0;
    let maxLen = 0;
    let maxTitle = '';
    for (const item of props.data.rows) {
        const { title } = item;
        const len = title.gblen();
        if (len > maxLen) {
            maxLen = len;
            maxTitle = title;
        }
    }
    let maxWidth = getTextWidth(maxTitle, {
        size: '0.875rem',
    });
    maxWidth += measureWidthOffset;
    if (maxWidth > ROW_HEADER_CELL_MAX_WIDTH) {
        maxWidth = ROW_HEADER_CELL_MAX_WIDTH;
    }
    return maxWidth;
});
/** @description æµ‹é‡å…¶ä»–列内容宽度 */
const colHeaderCellContentWidth = computed(() => {
    if (!props.data.values || props.data.values.length === 0) return 0;
    let maxLen = 0;
    let maxTitle = '';
    for (const item of props.data.values) {
        const { OTITLE } = item;
        const len = OTITLE.gblen();
        if (len > maxLen) {
            maxLen = len;
            maxTitle = OTITLE;
        }
    }
    let maxWidth = getTextWidth(maxTitle, {
        size: '0.875rem',
    });
    maxWidth += measureWidthOffset;
    if (maxWidth > CELL_MAX_WIDTH) {
        maxWidth = CELL_MAX_WIDTH;
    }
    return maxWidth;
});
const firstColWidth = ref(rowHeaderCellContentWidth.value);
const restColWidth = ref(colHeaderCellContentWidth.value);
const calcMaxRowsNum = (groupCount: number, height, extraHeight = 0) => {
    return Math.floor(
        (height - THICK_BORDER_WIDTH - extraHeight) /
            (CELL_HEIGHT * groupCount + 2 * THICK_BORDER_WIDTH + THIN_BORDER_WIDTH * (groupCount - 2))
    );
};
let maxColsNum = ref<number>(null);
const resizeEvent = ({ width, height }) => {
    // æŒ‰æœ€å¤§å®½åº¦ç®—最大列数
    maxColsNum.value = Math.floor((width - THICK_BORDER_WIDTH) / (CELL_WIDTH + THICK_BORDER_WIDTH));
    maxColsNum.value = Math.floor(
        (width - THICK_BORDER_WIDTH + colHeaderCellContentWidth.value - rowHeaderCellContentWidth.value) /
            (colHeaderCellContentWidth.value + THICK_BORDER_WIDTH)
    );
    const currentWidth =
        (maxColsNum.value - 1) * colHeaderCellContentWidth.value +
        rowHeaderCellContentWidth.value +
        THICK_BORDER_WIDTH * (maxColsNum.value - 1) +
        THICK_BORDER_WIDTH * 2;
    let restWidth = width - currentWidth;
    // å°½å¯èƒ½åˆ†ç»™ç¬¬ä¸€åˆ—
    if (rowHeaderCellContentWidth.value + restWidth > ROW_HEADER_CELL_MAX_WIDTH) {
        restWidth = rowHeaderCellContentWidth.value - ROW_HEADER_CELL_MAX_WIDTH;
        firstColWidth.value = ROW_HEADER_CELL_MAX_WIDTH;
    } else {
        firstColWidth.value = rowHeaderCellContentWidth.value + restWidth;
        restWidth = 0;
    }
    // å…¶ä½™åˆ†ç»™å…¶ä»–列
    if (restWidth !== 0) {
        const currentWidth = colHeaderCellContentWidth.value + restWidth;
        restColWidth.value = currentWidth > CELL_MAX_WIDTH ? CELL_MAX_WIDTH : currentWidth;
    }
    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);
    let rowsNum = calcMaxRowsNum(groupCount, height);
    // æŒ‰æœ€å¤§åˆ—数铺
    const maxColsRowsNum = Math.ceil(total / maxColsNum.value);
    const isNeedPage = maxColsRowsNum > rowsNum;
    rowsNum = isNeedPage ? calcMaxRowsNum(height, PAGE_HEIGHT) : maxColsRowsNum;
    rowsNum = isNeedPage ? calcMaxRowsNum(groupCount, height, PAGE_HEIGHT) : maxColsRowsNum;
    // rowsNum è¡Œï¼ŒmaxColsNum列,第一列不算
    pageSize.value = isNeedPage ? rowsNum * (maxColsNum.value - 1) : total;
    pageIndex.value = 1;
@@ -153,10 +248,10 @@
});
// è®¡ç®—最大列数
// x* cellWidth+thickBorderWidth*(x-1)+thickBorderWidth*2 <= width;
// (x-1)* cellWidth + rowHeaderCellContentWidth.value+thickBorderWidth*(x-1)+thickBorderWidth*2 <= width;
// x*(cellWidth+thickBorderWidth)+thickBorderWidth<=width;
// x<= (width-thickBorderWidth)/(cellWidth+thickBorderWidth);
// x*(cellWidth+thickBorderWidth)+thickBorderWidth - cellWidth + rowHeaderCellContentWidth.value<=width;
// x<= (width-thickBorderWidth + cellWidth-rowHeaderCellContentWidth.value)/(cellWidth+thickBorderWidth);
// const groupCount = (TEST_DATA?.rows?.length ?? 0) + 1;
// è®¡ç®—最大行数
@@ -167,9 +262,9 @@
//     y * (groupCount - 2) * thinBorderWidth <=
//     height;
// (cellHeight * groupCount + 2 * thickBorderWidth + thinBorderWidth(groupCount - 2) * groupCount) * y + thickBorderWidth <=height;
// (cellHeight * groupCount + 2 * thickBorderWidth + thinBorderWidth(groupCount - 2)  * y + thickBorderWidth <=height;
// y<= (height-thickBorderWidth)/(cellHeight * groupCount + 2 * thickBorderWidth + thinBorderWidth(groupCount - 2) * groupCount)
// y<= (height-thickBorderWidth)/(cellHeight * groupCount + 2 * thickBorderWidth + thinBorderWidth(groupCount - 2) )
onMounted(() => {
    resizeEvent({
src/components/chat/chatComponents/summaryCom/components/deviceLastValue/MonitorContent.vue
@@ -9,7 +9,7 @@
        <div
            :class="ROW_HEADER_CELL_CLASS"
            :style="{
                width: `${CELL_WIDTH}px`,
                width: `${firstColWidth}px`,
                height: `${CELL_HEIGHT}px`,
            }"
        >
@@ -20,18 +20,20 @@
            :key="index"
            :class="CONTENT_CELL_CLASS"
            :style="{
                width: `${CELL_WIDTH}px`,
                width: `${restColWidth}px`,
                height: `${CELL_HEIGHT}px`,
            }"
        >
            {{ item[type] }}
            <span>
                {{ item[type] }}
            </span>
        </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 { BORDER_COLOR, CELL_HEIGHT, CONTENT_CELL_CLASS, ROW_HEADER_CELL_CLASS, THICK_BORDER_WIDTH } from './constants';
import type { MonitorValue } from './types';
const props = defineProps({
    /** @description æ ‡é¢˜ */
@@ -46,6 +48,13 @@
    values: {
        type: Object as PropType<MonitorValue[]>,
    },
    firstColWidth: {
        type: Number,
    },
    restColWidth: {
        type: Number,
    },
});
</script>
<style scoped lang="scss"></style>
src/components/chat/chatComponents/summaryCom/components/deviceLastValue/constants.ts
@@ -1,13 +1,18 @@
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 ROW_HEADER_CELL_MAX_WIDTH = 198;
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_MAX_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 PAGE_HEIGHT = 39;
export const rowCount = 5;
export const BORDER_COLOR = '#90b6e2';
export const BORDER_COLOR = '#90b6e2';
export const FIRST_COL_MAX_OFFSET = 4;
export const REST_COL_MAX_OFFSET = 4;
src/extend/index.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1 @@
import './string.extensions';
src/extend/string.extensions.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
interface String {
    gblen(): number;
}
/**
 * èŽ·å–ä¸­è‹±æ–‡é•¿åº¦ï¼Œä¸­æ–‡2,英文1
 */
String.prototype.gblen =function () {
    let len = 0;
    for (let i = 0; i < this.length; i++) {
        if (this.charCodeAt(i) > 127 || this.charCodeAt(i) == 94) {
            len += 2;
        } else {
            len++;
        }
    }
    return len;
};
src/main.ts
@@ -5,13 +5,13 @@
import router from '/@/router/index';
import pinia from '/@/stores/index';
import other from '/@/utils/other';
import '/@/extend';
import * as ElementPlusIconsVue from '@element-plus/icons-vue';
import ElementPlus from 'element-plus';
import VueGridLayout from 'vue-grid-layout';
import { initBackEndControlRoutes } from './router/backEnd';
import '/@/theme/index.scss';
import "@amap/amap-jsapi-types";
import '@amap/amap-jsapi-types';
const app = createApp(App);
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
src/utils/util.ts
@@ -697,3 +697,27 @@
export const arrayIsEmpty = (arr: any) => {
    return !arr || arr.length === 0;
};
type GetTextWidthOption = {
    size?: string;
    family?: string;
};
export function getTextWidth(text: string, option: GetTextWidthOption) {
    const { size = '14px', family = 'Microsoft YaHei' } = option;
    const spanEle = document.createElement('span');
    document.body.appendChild(spanEle);
    spanEle.style.font = 'times new roman';
    spanEle.style.fontSize = size;
    spanEle.style.height = 'auto';
    spanEle.style.width = 'auto';
    spanEle.style.position = 'absolute';
    spanEle.style.whiteSpace = 'no-wrap';
    spanEle.innerHTML = text;
    const width = spanEle.clientWidth;
    document.body.removeChild(spanEle);
    return width;
}