feat: 车站卡片布局列数自适应

This commit is contained in:
yangsy
2026-01-21 15:23:08 +08:00
parent 6771abec31
commit 82789c78a9

View File

@@ -4,11 +4,11 @@ import { AlarmDetailModal, DeviceDetailModal, DeviceParamConfigModal, IcmpExport
import { useBatchActions, useLineDevicesQuery } from '@/composables';
import { useAlarmStore, useDeviceStore, useSettingStore, useStationStore } from '@/stores';
import { useMutation } from '@tanstack/vue-query';
import { objectEntries } from '@vueuse/core';
import { objectEntries, useElementSize } from '@vueuse/core';
import { isCancel } from 'axios';
import { NButton, NButtonGroup, NCheckbox, NFlex, NGrid, NGridItem, NScrollbar } from 'naive-ui';
import { storeToRefs } from 'pinia';
import { computed, ref } from 'vue';
import { computed, ref, useTemplateRef } from 'vue';
const settingStore = useSettingStore();
const { stationGridCols } = storeToRefs(settingStore);
@@ -22,6 +22,21 @@ const { lineDevices } = storeToRefs(deviceStore);
const alarmStore = useAlarmStore();
const { lineAlarms } = storeToRefs(alarmStore);
const STATION_CARD_MIN_WIDTH = 230;
const STATION_GRID_PADDING = 8;
const STATION_GRID_GAP = 6;
const STATION_GRID_REF_NAME = 'stationGridRef';
const stationGridRef = useTemplateRef<HTMLDivElement>(STATION_GRID_REF_NAME);
const { width: stationGridWidth } = useElementSize(stationGridRef);
// 计算合适的车站布局列数
const actualStationGridColumns = computed(() => {
const currentStationCardWidth = (stationGridWidth.value - STATION_GRID_PADDING * 2 - (stationGridCols.value - 1) * STATION_GRID_GAP) / stationGridCols.value;
// 当卡片宽度大于最小宽度时,说明用户的设置没有问题,直接返回列数
if (currentStationCardWidth > STATION_CARD_MIN_WIDTH) return stationGridCols.value;
// 否则,说明用户的设置不合适,需要根据当前布局宽度重新计算列数
return Math.floor((stationGridWidth.value - STATION_GRID_PADDING * 2 + STATION_GRID_GAP) / STATION_CARD_MIN_WIDTH);
});
const showIcmpExportModal = ref(false);
const showRecordCheckExportModal = ref(false);
@@ -155,7 +170,7 @@ const onClickDetail: StationCardProps['onClickDetail'] = (type, station) => {
<template>
<NScrollbar content-style="padding-right: 8px" style="width: 100%; height: 100%">
<!-- 工具栏 -->
<NFlex align="center" style="padding: 8px 8px 0 8px">
<NFlex align="center" :style="{ padding: `${STATION_GRID_PADDING}px ${STATION_GRID_PADDING}px 0 ${STATION_GRID_PADDING}px` }">
<NButtonGroup>
<template v-for="batchAction in batchActions" :key="batchAction.key">
<NButton :secondary="!batchAction.active" :focusable="false" @click="() => toggleSelectAction(batchAction)">{{ batchAction.label }}</NButton>
@@ -174,19 +189,21 @@ const onClickDetail: StationCardProps['onClickDetail'] = (type, station) => {
</NFlex>
<!-- 车站 -->
<NGrid :cols="stationGridCols" :x-gap="6" :y-gap="6" style="padding: 8px">
<NGridItem v-for="station in stations" :key="station.code">
<StationCard
:station="station"
:devices="lineDevices[station.code] ?? initStationDevices()"
:alarms="lineAlarms[station.code] ?? initStationAlarms()"
:selectable="!!selectableStations.find((selectable) => selectable.code === station.code)"
v-model:selected="stationSelection[station.code]"
@click-detail="onClickDetail"
@click-config="onClickConfig"
/>
</NGridItem>
</NGrid>
<div :ref="STATION_GRID_REF_NAME">
<NGrid :cols="actualStationGridColumns" :x-gap="STATION_GRID_GAP" :y-gap="STATION_GRID_GAP" :style="{ padding: `${STATION_GRID_PADDING}px` }">
<NGridItem v-for="station in stations" :key="station.code">
<StationCard
:station="station"
:devices="lineDevices[station.code] ?? initStationDevices()"
:alarms="lineAlarms[station.code] ?? initStationAlarms()"
:selectable="!!selectableStations.find((selectable) => selectable.code === station.code)"
v-model:selected="stationSelection[station.code]"
@click-detail="onClickDetail"
@click-config="onClickConfig"
/>
</NGridItem>
</NGrid>
</div>
</NScrollbar>
<IcmpExportModal v-model:show="showIcmpExportModal" :stations="stations.filter((station) => stationSelection[station.code])" @after-leave="cancelAction" />