fix: DevicePage fix
- remove dblclick of device node - auto scroll to selected device node
This commit is contained in:
@@ -24,9 +24,10 @@ import {
|
|||||||
type TagProps,
|
type TagProps,
|
||||||
type TreeInst,
|
type TreeInst,
|
||||||
type TreeOption,
|
type TreeOption,
|
||||||
|
type TreeOverrideNodeClickBehavior,
|
||||||
} from 'naive-ui';
|
} from 'naive-ui';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { h, nextTick, onMounted, useTemplateRef } from 'vue';
|
import { h, onMounted, useTemplateRef } from 'vue';
|
||||||
import { computed, ref, watch } from 'vue';
|
import { computed, ref, watch } from 'vue';
|
||||||
import { useRoute, useRouter, type LocationQuery } from 'vue-router';
|
import { useRoute, useRouter, type LocationQuery } from 'vue-router';
|
||||||
import { destr } from 'destr';
|
import { destr } from 'destr';
|
||||||
@@ -49,6 +50,7 @@ const stationStore = useStationStore();
|
|||||||
const { stationList } = storeToRefs(stationStore);
|
const { stationList } = storeToRefs(stationStore);
|
||||||
const { data: lineDevices } = useLineDevicesQuery();
|
const { data: lineDevices } = useLineDevicesQuery();
|
||||||
|
|
||||||
|
// ========== 设备树数据 ==========
|
||||||
const lineDeviceTreeData = computed<Record<string, TreeOption[]>>(() => {
|
const lineDeviceTreeData = computed<Record<string, TreeOption[]>>(() => {
|
||||||
const treeData: Record<string, TreeOption[]> = {};
|
const treeData: Record<string, TreeOption[]> = {};
|
||||||
deviceTabPanes.forEach(({ name: paneName /* , tab: paneTab */ }) => {
|
deviceTabPanes.forEach(({ name: paneName /* , tab: paneTab */ }) => {
|
||||||
@@ -86,7 +88,7 @@ const lineDeviceTreeData = computed<Record<string, TreeOption[]>>(() => {
|
|||||||
key: nvr.id,
|
key: nvr.id,
|
||||||
suffix: () => `${nvr.ipAddress}`,
|
suffix: () => `${nvr.ipAddress}`,
|
||||||
prefix: () => {
|
prefix: () => {
|
||||||
return renderDeviceNodePrefix(nvrCluster, stationCode);
|
return renderDeviceNodePrefix(nvr, stationCode);
|
||||||
},
|
},
|
||||||
// 当选择设备时,能获取到设备的所有信息,以及设备所属的车站
|
// 当选择设备时,能获取到设备的所有信息,以及设备所属的车站
|
||||||
device: nvr,
|
device: nvr,
|
||||||
@@ -152,11 +154,13 @@ const renderDeviceNodePrefix = (device: NdmDeviceResultVO, stationCode: string)
|
|||||||
return h('div', [renderViewDeviceButton(device, stationCode), renderDeviceStatusTag(device)]);
|
return h('div', [renderViewDeviceButton(device, stationCode), renderDeviceStatusTag(device)]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ========== 选中设备 ==========
|
||||||
const selectedTab = ref<DeviceTypeCode>(DeviceType.Camera);
|
const selectedTab = ref<DeviceTypeCode>(DeviceType.Camera);
|
||||||
const selectedKeys = ref<string[]>();
|
const selectedKeys = ref<string[]>();
|
||||||
|
const expandedKeys = ref<string[]>();
|
||||||
const selectedDevice = ref<NdmDeviceResultVO>();
|
const selectedDevice = ref<NdmDeviceResultVO>();
|
||||||
// 从路由参数中设置选中的设备
|
// 从路由参数中设置选中的设备
|
||||||
const setFromRouteQuery = (query: LocationQuery) => {
|
const setDeviceTreePropsFromRouteQuery = (query: LocationQuery) => {
|
||||||
const { stationCode, deviceType, deviceDBId } = query;
|
const { stationCode, deviceType, deviceDBId } = query;
|
||||||
let stnCode = '';
|
let stnCode = '';
|
||||||
let devType: DeviceTypeCode = DeviceType.Camera;
|
let devType: DeviceTypeCode = DeviceType.Camera;
|
||||||
@@ -164,6 +168,7 @@ const setFromRouteQuery = (query: LocationQuery) => {
|
|||||||
if (stationCode) stnCode = stationCode as string;
|
if (stationCode) stnCode = stationCode as string;
|
||||||
if (deviceType) devType = deviceType as DeviceTypeCode;
|
if (deviceType) devType = deviceType as DeviceTypeCode;
|
||||||
if (deviceDBId) devDBId = deviceDBId as string;
|
if (deviceDBId) devDBId = deviceDBId as string;
|
||||||
|
|
||||||
selectedTab.value = devType;
|
selectedTab.value = devType;
|
||||||
selectedKeys.value = [devDBId];
|
selectedKeys.value = [devDBId];
|
||||||
const stnDevices = lineDevices.value?.[stnCode];
|
const stnDevices = lineDevices.value?.[stnCode];
|
||||||
@@ -172,35 +177,24 @@ const setFromRouteQuery = (query: LocationQuery) => {
|
|||||||
selectedDevice.value = devices?.find((device) => device.id === devDBId) ?? selectedDevice.value;
|
selectedDevice.value = devices?.find((device) => device.id === devDBId) ?? selectedDevice.value;
|
||||||
};
|
};
|
||||||
// 页面加载时,需要设置选中的设备
|
// 页面加载时,需要设置选中的设备
|
||||||
onMounted(() => setFromRouteQuery(route.query));
|
onMounted(() => {
|
||||||
|
setDeviceTreePropsFromRouteQuery(route.query);
|
||||||
|
scrollDeviceTreeToSelectedDevice();
|
||||||
|
});
|
||||||
// 页面加载时设备数据可能不存在,因此当设备数据更新时,需要重新设置选中的设备
|
// 页面加载时设备数据可能不存在,因此当设备数据更新时,需要重新设置选中的设备
|
||||||
watch(lineDevices, () => setFromRouteQuery(route.query), { immediate: true });
|
watch(lineDevices, () => setDeviceTreePropsFromRouteQuery(route.query), { immediate: true });
|
||||||
// 更改选择的设备类型时,更新路由查询参数
|
// 更改选择的设备类型时,更新路由查询参数
|
||||||
watch(selectedTab, (newTab) => router.replace({ query: { ...route.query, deviceType: newTab } }));
|
watch(selectedTab, (newTab) => router.replace({ query: { ...route.query, deviceType: newTab } }));
|
||||||
// 双击设备时更新路由查询参数
|
const override: TreeOverrideNodeClickBehavior = ({ option }) => {
|
||||||
const nodeProps = ({ option }: { option: TreeOption }) => {
|
if (!option['device']) {
|
||||||
return {
|
return 'none';
|
||||||
ondblclick: () => {
|
}
|
||||||
if (option['device']) {
|
return 'default';
|
||||||
const device = option['device'] as NdmDeviceResultVO;
|
|
||||||
selectedKeys.value = device.id ? [device.id] : undefined; // 更新选中的树节点
|
|
||||||
selectedDevice.value = device; // 更新选中的设备
|
|
||||||
router.replace({
|
|
||||||
query: {
|
|
||||||
...route.query,
|
|
||||||
stationCode: option['stationCode'] as string,
|
|
||||||
deviceType: selectedTab.value,
|
|
||||||
deviceDBId: device.id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ========== 设备树搜索 ==========
|
||||||
const searchInput = ref('');
|
const searchInput = ref('');
|
||||||
const statusInput = ref('');
|
const statusInput = ref('');
|
||||||
|
|
||||||
// 设备树将搜索框和单选框的值都交给NTree的pattern属性
|
// 设备树将搜索框和单选框的值都交给NTree的pattern属性
|
||||||
// 但是如果一个车站下没有匹配的设备,那么这个车站节点也不会显示
|
// 但是如果一个车站下没有匹配的设备,那么这个车站节点也不会显示
|
||||||
const searchPattern = computed(() => {
|
const searchPattern = computed(() => {
|
||||||
@@ -218,15 +212,22 @@ const searchFilter = (pattern: string, node: TreeOption): boolean => {
|
|||||||
return searchMatched && statusMatched;
|
return searchMatched && statusMatched;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ========== 设备树交互 ==========
|
||||||
// 定位到选中的设备
|
// 定位到选中的设备
|
||||||
const deviceTreeInsts = useTemplateRef<TreeInst[]>('deviceTreeInsts');
|
const deviceTreeInsts = useTemplateRef<TreeInst[]>('deviceTreeInsts');
|
||||||
const onClickLocateDeviceTree = () => {
|
const onClickLocateDeviceTree = () => {
|
||||||
selectedTab.value = (selectedDevice.value?.deviceType ?? selectedTab.value) as DeviceTypeCode;
|
selectedTab.value = (selectedDevice.value?.deviceType ?? selectedTab.value) as DeviceTypeCode;
|
||||||
// 等待Tab切换完成后再执行滚动
|
selectedKeys.value = selectedDevice.value?.id ? [selectedDevice.value.id] : undefined;
|
||||||
nextTick(() => {
|
expandedKeys.value = route.query['stationCode'] ? [route.query['stationCode'] as string] : undefined;
|
||||||
|
// 由于数据量大所以开启虚拟滚动,
|
||||||
|
// 但是无法知晓NTree内部的虚拟列表容器何时创建完成,所以使用setTimeout延迟固定时间后执行滚动
|
||||||
|
scrollDeviceTreeToSelectedDevice();
|
||||||
|
};
|
||||||
|
const scrollDeviceTreeToSelectedDevice = (timeout: number = 500) => {
|
||||||
|
setTimeout(() => {
|
||||||
const inst = deviceTreeInsts.value?.at(0);
|
const inst = deviceTreeInsts.value?.at(0);
|
||||||
inst?.scrollTo({ key: selectedDevice.value?.id, behavior: 'smooth' });
|
inst?.scrollTo({ key: selectedDevice.value?.id, behavior: 'smooth' });
|
||||||
});
|
}, timeout);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -252,17 +253,18 @@ const onClickLocateDeviceTree = () => {
|
|||||||
<NTabs v-model:value="selectedTab" animated type="line" placement="left" style="height: 100%">
|
<NTabs v-model:value="selectedTab" animated type="line" placement="left" style="height: 100%">
|
||||||
<NTabPane v-for="pane in deviceTabPanes" :key="pane.name" :name="pane.name" :tab="pane.tab">
|
<NTabPane v-for="pane in deviceTabPanes" :key="pane.name" :name="pane.name" :tab="pane.tab">
|
||||||
<NTree
|
<NTree
|
||||||
:ref="'deviceTreeInsts'"
|
|
||||||
v-model:selected-keys="selectedKeys"
|
v-model:selected-keys="selectedKeys"
|
||||||
|
v-model:expanded-keys="expandedKeys"
|
||||||
|
:ref="'deviceTreeInsts'"
|
||||||
:data="lineDeviceTreeData[pane.name]"
|
:data="lineDeviceTreeData[pane.name]"
|
||||||
:node-props="nodeProps"
|
|
||||||
:show-irrelevant-nodes="false"
|
:show-irrelevant-nodes="false"
|
||||||
:pattern="searchPattern"
|
:pattern="searchPattern"
|
||||||
:filter="searchFilter"
|
:filter="searchFilter"
|
||||||
|
:override-default-node-click-behavior="override"
|
||||||
|
default-expand-all
|
||||||
block-line
|
block-line
|
||||||
block-node
|
block-node
|
||||||
show-line
|
show-line
|
||||||
default-expand-all
|
|
||||||
virtual-scroll
|
virtual-scroll
|
||||||
style="height: 100%"
|
style="height: 100%"
|
||||||
/>
|
/>
|
||||||
@@ -281,6 +283,7 @@ const onClickLocateDeviceTree = () => {
|
|||||||
</template>
|
</template>
|
||||||
</NPageHeader>
|
</NPageHeader>
|
||||||
<div>selectedKeys: {{ selectedKeys }}</div>
|
<div>selectedKeys: {{ selectedKeys }}</div>
|
||||||
|
<div>expandedKeys: {{ expandedKeys }}</div>
|
||||||
<div>selectedDevice: {{ selectedDevice?.deviceId }}</div>
|
<div>selectedDevice: {{ selectedDevice?.deviceId }}</div>
|
||||||
<NScrollbar style="width: 500px; height: 400px; border: solid 1px salmon">
|
<NScrollbar style="width: 500px; height: 400px; border: solid 1px salmon">
|
||||||
<pre>{{ selectedDevice }}</pre>
|
<pre>{{ selectedDevice }}</pre>
|
||||||
|
|||||||
Reference in New Issue
Block a user