Compare commits
6 Commits
1c71151a6b
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f9f761b4e9 | ||
|
|
4090c7e6c5 | ||
|
|
38b43b1c45 | ||
|
|
9eafc7871b | ||
|
|
3eb5b06f59 | ||
|
|
f2fc2e732d |
@@ -3,6 +3,7 @@
|
|||||||
"version": "0.39.0",
|
"version": "0.39.0",
|
||||||
"date": "2026-03-02",
|
"date": "2026-03-02",
|
||||||
"changes": {
|
"changes": {
|
||||||
|
"fixes": [{ "content": "修复设备树搜索时节点错乱的问题" }],
|
||||||
"feats": [{ "content": "新版录像记录诊断卡片" }, { "content": "新增平台更新记录页面" }]
|
"feats": [{ "content": "新版录像记录诊断卡片" }, { "content": "新增平台更新记录页面" }]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"version": "0.39.0",
|
"version": "0.39.0",
|
||||||
"buildTime": "2026-03-02 15:14:53"
|
"buildTime": "2026-03-11 14:35:45"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -626,9 +626,14 @@ const columns: DataTableColumns<DailyLossItem['chunks'][number]> = [
|
|||||||
<template #default>
|
<template #default>
|
||||||
<template v-if="!!dailyCheckContext.info">
|
<template v-if="!!dailyCheckContext.info">
|
||||||
<div>日期:{{ dailyCheckContext.info.date }}</div>
|
<div>日期:{{ dailyCheckContext.info.date }}</div>
|
||||||
|
<template v-if="dailyCheckContext.info.percent > 0">
|
||||||
<div>缺失时长:{{ formatDuration(dailyCheckContext.info.total, { withinDay: true }) }}</div>
|
<div>缺失时长:{{ formatDuration(dailyCheckContext.info.total, { withinDay: true }) }}</div>
|
||||||
<div>缺失比例:{{ dailyCheckContext.info.percent.toFixed(2) }}%</div>
|
<div>缺失比例:{{ dailyCheckContext.info.percent.toFixed(2) }}%</div>
|
||||||
<div v-if="dailyCheckContext.info.percent > 0" style="font-size: xx-small; opacity: 0.5; cursor: pointer" @click="onClickDailyCheck">点击查看详情</div>
|
<div style="font-size: xx-small; opacity: 0.5; cursor: pointer" @click="onClickDailyCheck">点击查看详情</div>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<div>录像完整</div>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</NPopover>
|
</NPopover>
|
||||||
|
|||||||
@@ -11,15 +11,19 @@ import {
|
|||||||
NButton,
|
NButton,
|
||||||
NDropdown,
|
NDropdown,
|
||||||
NFlex,
|
NFlex,
|
||||||
|
NGrid,
|
||||||
|
NGridItem,
|
||||||
NInput,
|
NInput,
|
||||||
NRadio,
|
NRadio,
|
||||||
NRadioGroup,
|
NRadioGroup,
|
||||||
|
NSelect,
|
||||||
NTab,
|
NTab,
|
||||||
NTabs,
|
NTabs,
|
||||||
NTag,
|
NTag,
|
||||||
NTree,
|
NTree,
|
||||||
useThemeVars,
|
useThemeVars,
|
||||||
type DropdownOption,
|
type DropdownOption,
|
||||||
|
type SelectOption,
|
||||||
type TagProps,
|
type TagProps,
|
||||||
type TreeInst,
|
type TreeInst,
|
||||||
type TreeOption,
|
type TreeOption,
|
||||||
@@ -348,7 +352,7 @@ const lineDeviceTreeData = computed<Record<Station['code'], TreeOption[]>>(() =>
|
|||||||
const device = dev as NdmDeviceResultVO;
|
const device = dev as NdmDeviceResultVO;
|
||||||
return {
|
return {
|
||||||
label: `${device.name}`,
|
label: `${device.name}`,
|
||||||
key: `${device.id}`,
|
key: `${device.name}${device.ipAddress}`,
|
||||||
prefix: () => renderDeviceNodePrefix(device, stationCode),
|
prefix: () => renderDeviceNodePrefix(device, stationCode),
|
||||||
suffix: () => `${device.ipAddress}`,
|
suffix: () => `${device.ipAddress}`,
|
||||||
// 当选择设备时,能获取到设备的所有信息,以及设备所属的车站
|
// 当选择设备时,能获取到设备的所有信息,以及设备所属的车站
|
||||||
@@ -382,13 +386,13 @@ const stationDeviceTreeData = computed<TreeOption[]>(() => {
|
|||||||
children: clusters.map<TreeOption>((device) => {
|
children: clusters.map<TreeOption>((device) => {
|
||||||
return {
|
return {
|
||||||
label: `${device.name}`,
|
label: `${device.name}`,
|
||||||
key: `${device.id}`,
|
key: `${device.name}${device.ipAddress}`,
|
||||||
prefix: () => renderDeviceNodePrefix(device, stationCode),
|
prefix: () => renderDeviceNodePrefix(device, stationCode),
|
||||||
suffix: () => `${device.ipAddress}`,
|
suffix: () => `${device.ipAddress}`,
|
||||||
children: singletons.map<TreeOption>((device) => {
|
children: singletons.map<TreeOption>((device) => {
|
||||||
return {
|
return {
|
||||||
label: `${device.name}`,
|
label: `${device.name}`,
|
||||||
key: `${device.id}`,
|
key: `${device.name}${device.ipAddress}`,
|
||||||
prefix: () => renderDeviceNodePrefix(device, stationCode),
|
prefix: () => renderDeviceNodePrefix(device, stationCode),
|
||||||
suffix: () => `${device.ipAddress}`,
|
suffix: () => `${device.ipAddress}`,
|
||||||
stationCode,
|
stationCode,
|
||||||
@@ -410,7 +414,7 @@ const stationDeviceTreeData = computed<TreeOption[]>(() => {
|
|||||||
children: stationDevices[deviceType].map<TreeOption>((device) => {
|
children: stationDevices[deviceType].map<TreeOption>((device) => {
|
||||||
return {
|
return {
|
||||||
label: `${device.name}`,
|
label: `${device.name}`,
|
||||||
key: `${device.id}`,
|
key: `${device.name}${device.ipAddress}`,
|
||||||
prefix: () => renderDeviceNodePrefix(device, stationCode),
|
prefix: () => renderDeviceNodePrefix(device, stationCode),
|
||||||
suffix: () => `${device.ipAddress}`,
|
suffix: () => `${device.ipAddress}`,
|
||||||
stationCode,
|
stationCode,
|
||||||
@@ -425,20 +429,26 @@ const stationDeviceTreeData = computed<TreeOption[]>(() => {
|
|||||||
|
|
||||||
// ========== 设备树搜索 ==========
|
// ========== 设备树搜索 ==========
|
||||||
const searchInput = ref('');
|
const searchInput = ref('');
|
||||||
|
const searchTypeOptions: SelectOption[] = [
|
||||||
|
{ label: '设备名称', value: 'name' },
|
||||||
|
{ label: 'IP地址', value: 'ipAddress' },
|
||||||
|
];
|
||||||
|
type SearchType = 'name' | 'ipAddress';
|
||||||
|
const typeInput = ref<SearchType>('name');
|
||||||
const statusInput = ref('');
|
const statusInput = ref('');
|
||||||
// 设备树将搜索框和单选框的值都交给NTree的pattern属性
|
// 设备树将搜索框、选择器以及单选框的值都交给NTree的pattern属性
|
||||||
// 但是如果一个车站下没有匹配的设备,那么这个车站节点也不会显示
|
// 但是如果一个车站下没有匹配的设备,那么这个车站节点也不会显示
|
||||||
const searchPattern = computed(() => {
|
const searchPattern = computed(() => {
|
||||||
const search = searchInput.value;
|
const search = searchInput.value;
|
||||||
const status = statusInput.value;
|
const status = statusInput.value;
|
||||||
if (!search && !status) return ''; // 如果pattern非空会导致NTree组件认为筛选完成,UI上发生全量匹配
|
if (!search && !status) return ''; // 如果pattern非空会导致NTree组件认为筛选完成,UI上发生全量匹配
|
||||||
return JSON.stringify({ search: searchInput.value, status: statusInput.value });
|
return JSON.stringify({ search: searchInput.value, type: typeInput.value, status: statusInput.value });
|
||||||
});
|
});
|
||||||
const searchFilter = (pattern: string, node: TreeOption): boolean => {
|
const searchFilter = (pattern: string, node: TreeOption): boolean => {
|
||||||
const { search, status } = destr<{ search: string; status: string }>(pattern);
|
const { search, type, status } = destr<{ search: string; type: SearchType; status: string }>(pattern);
|
||||||
const device = node['device'] as NdmDeviceResultVO | undefined;
|
const device = node['device'] as NdmDeviceResultVO | undefined;
|
||||||
const { name, ipAddress, deviceId, deviceStatus } = device ?? {};
|
const { deviceStatus } = device ?? {};
|
||||||
const searchMatched = (name ?? '').includes(search) || (ipAddress ?? '').includes(search) || (deviceId ?? '').includes(search);
|
const searchMatched = !!device?.[type]?.includes(search);
|
||||||
const statusMatched = status === '' || status === deviceStatus;
|
const statusMatched = status === '' || status === deviceStatus;
|
||||||
return searchMatched && statusMatched;
|
return searchMatched && statusMatched;
|
||||||
};
|
};
|
||||||
@@ -523,7 +533,14 @@ onMounted(() => {
|
|||||||
<div style="height: 100%; display: flex; flex-direction: column">
|
<div style="height: 100%; display: flex; flex-direction: column">
|
||||||
<!-- 搜索和筛选 -->
|
<!-- 搜索和筛选 -->
|
||||||
<div style="padding: 12px; flex: 0 0 auto">
|
<div style="padding: 12px; flex: 0 0 auto">
|
||||||
<NInput v-model:value="searchInput" placeholder="搜索设备名称、设备ID或IP地址" clearable />
|
<NGrid :cols="10" :x-gap="8">
|
||||||
|
<NGridItem :span="7">
|
||||||
|
<NInput v-model:value="searchInput" placeholder="搜索设备名称或IP地址" clearable />
|
||||||
|
</NGridItem>
|
||||||
|
<NGridItem :span="3">
|
||||||
|
<NSelect v-model:value="typeInput" :options="searchTypeOptions" placeholder="搜索类型" />
|
||||||
|
</NGridItem>
|
||||||
|
</NGrid>
|
||||||
<NFlex align="center">
|
<NFlex align="center">
|
||||||
<NRadioGroup v-model:value="statusInput">
|
<NRadioGroup v-model:value="statusInput">
|
||||||
<NRadio value="">全部</NRadio>
|
<NRadio value="">全部</NRadio>
|
||||||
|
|||||||
@@ -76,6 +76,44 @@ const line01ApiProxyList: ProxyItem[] = [
|
|||||||
{ key: '/0128/api', target: 'http://10.14.55.10:18760', rewrite: ['/0128/api', '/api'] },
|
{ key: '/0128/api', target: 'http://10.14.55.10:18760', rewrite: ['/0128/api', '/api'] },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const line02ApiProxyList: ProxyItem[] = [
|
||||||
|
{ key: '/0275/api', target: 'http://10.14.128.10:18760', rewrite: ['/0275/api', '/api'] },
|
||||||
|
{ key: '/0202/api', target: 'http://10.14.129.10:18760', rewrite: ['/0202/api', '/api'] },
|
||||||
|
{ key: '/0203/api', target: 'http://10.14.131.10:18760', rewrite: ['/0203/api', '/api'] },
|
||||||
|
{ key: '/0204/api', target: 'http://10.14.133.10:18760', rewrite: ['/0204/api', '/api'] },
|
||||||
|
{ key: '/0205/api', target: 'http://10.14.135.10:18760', rewrite: ['/0205/api', '/api'] },
|
||||||
|
{ key: '/0206/api', target: 'http://10.14.137.10:18760', rewrite: ['/0206/api', '/api'] },
|
||||||
|
{ key: '/0207/api', target: 'http://10.14.139.10:18760', rewrite: ['/0207/api', '/api'] },
|
||||||
|
{ key: '/0208/api', target: 'http://10.14.141.10:18760', rewrite: ['/0208/api', '/api'] },
|
||||||
|
{ key: '/0209/api', target: 'http://10.14.143.10:18760', rewrite: ['/0209/api', '/api'] },
|
||||||
|
{ key: '/0210/api', target: 'http://10.14.145.10:18760', rewrite: ['/0210/api', '/api'] },
|
||||||
|
{ key: '/0211/api', target: 'http://10.14.147.10:18760', rewrite: ['/0211/api', '/api'] },
|
||||||
|
{ key: '/0212/api', target: 'http://10.14.149.10:18760', rewrite: ['/0212/api', '/api'] },
|
||||||
|
{ key: '/0213/api', target: 'http://10.14.151.10:18760', rewrite: ['/0213/api', '/api'] },
|
||||||
|
{ key: '/0214/api', target: 'http://10.14.153.10:18760', rewrite: ['/0214/api', '/api'] },
|
||||||
|
{ key: '/0215/api', target: 'http://10.14.155.10:18760', rewrite: ['/0215/api', '/api'] },
|
||||||
|
{ key: '/0216/api', target: 'http://10.14.157.10:18760', rewrite: ['/0216/api', '/api'] },
|
||||||
|
{ key: '/0217/api', target: 'http://10.14.159.10:18760', rewrite: ['/0217/api', '/api'] },
|
||||||
|
{ key: '/0224/api', target: 'http://10.14.161.10:18760', rewrite: ['/0224/api', '/api'] },
|
||||||
|
{ key: '/0225/api', target: 'http://10.14.163.10:18760', rewrite: ['/0225/api', '/api'] },
|
||||||
|
{ key: '/0226/api', target: 'http://10.14.165.10:18760', rewrite: ['/0226/api', '/api'] },
|
||||||
|
{ key: '/0227/api', target: 'http://10.14.167.10:18760', rewrite: ['/0227/api', '/api'] },
|
||||||
|
{ key: '/0228/api', target: 'http://10.14.169.10:18760', rewrite: ['/0228/api', '/api'] },
|
||||||
|
{ key: '/0229/api', target: 'http://10.14.171.10:18760', rewrite: ['/0229/api', '/api'] },
|
||||||
|
{ key: '/0230/api', target: 'http://10.14.173.10:18760', rewrite: ['/0230/api', '/api'] },
|
||||||
|
{ key: '/0231/api', target: 'http://10.14.175.10:18760', rewrite: ['/0231/api', '/api'] },
|
||||||
|
{ key: '/0232/api', target: 'http://10.14.177.10:18760', rewrite: ['/0232/api', '/api'] },
|
||||||
|
{ key: '/0233/api', target: 'http://10.14.179.10:18760', rewrite: ['/0233/api', '/api'] },
|
||||||
|
{ key: '/0234/api', target: 'http://10.14.181.10:18760', rewrite: ['/0234/api', '/api'] },
|
||||||
|
{ key: '/0235/api', target: 'http://10.14.183.10:18760', rewrite: ['/0235/api', '/api'] },
|
||||||
|
{ key: '/0236/api', target: 'http://10.14.185.10:18760', rewrite: ['/0236/api', '/api'] },
|
||||||
|
{ key: '/0237/api', target: 'http://10.14.187.10:18760', rewrite: ['/0237/api', '/api'] },
|
||||||
|
{ key: '/0238/api', target: 'http://10.14.191.10:18760', rewrite: ['/0238/api', '/api'] },
|
||||||
|
{ key: '/0280/api', target: 'http://10.14.244.10:18760', rewrite: ['/0280/api', '/api'] },
|
||||||
|
{ key: '/0281/api', target: 'http://10.14.248.10:18760', rewrite: ['/0281/api', '/api'] },
|
||||||
|
{ key: '/0282/api', target: 'http://10.14.252.10:18760', rewrite: ['/0282/api', '/api'] },
|
||||||
|
];
|
||||||
|
|
||||||
const line04ApiProxyList: ProxyItem[] = [
|
const line04ApiProxyList: ProxyItem[] = [
|
||||||
{ key: '/0475/api', target: 'http://10.15.128.10:18760', rewrite: ['/0475/api', '/api'] },
|
{ key: '/0475/api', target: 'http://10.15.128.10:18760', rewrite: ['/0475/api', '/api'] },
|
||||||
{ key: '/0480/api', target: 'http://10.15.244.10:18760', rewrite: ['/0480/api', '/api'] },
|
{ key: '/0480/api', target: 'http://10.15.244.10:18760', rewrite: ['/0480/api', '/api'] },
|
||||||
@@ -143,6 +181,11 @@ const apiProxyList: ProxyItem[] = [
|
|||||||
// { key: '/ws', target: 'ws://10.14.0.10:18103', ws: true },
|
// { key: '/ws', target: 'ws://10.14.0.10:18103', ws: true },
|
||||||
...line01ApiProxyList,
|
...line01ApiProxyList,
|
||||||
|
|
||||||
|
// { key: '/minio', target: 'http://10.14.128.10:9000', rewrite: ['/minio', ''] },
|
||||||
|
// { key: '/api', target: 'http://10.14.128.10:18760' },
|
||||||
|
// { key: '/ws', target: 'ws://10.14.128.10:18103', ws: true },
|
||||||
|
...line02ApiProxyList,
|
||||||
|
|
||||||
// { key: '/minio', target: 'http://10.15.128.10:9000', rewrite: ['/minio', ''] },
|
// { key: '/minio', target: 'http://10.15.128.10:9000', rewrite: ['/minio', ''] },
|
||||||
// { key: '/api', target: 'http://10.15.128.10:18760' },
|
// { key: '/api', target: 'http://10.15.128.10:18760' },
|
||||||
// { key: '/ws', target: 'ws://10.15.128.10:18103', ws: true },
|
// { key: '/ws', target: 'ws://10.15.128.10:18103', ws: true },
|
||||||
|
|||||||
Reference in New Issue
Block a user