feat:手动获取摄像头
This commit is contained in:
1 parent
fa9701c92c
commit
4c8dc3c2a4
3 files changed
+74
-22
No files matched your search
@@ -77,6 +77,11 @@ export interface PlatformDeviceDifferenceAction {
|
||||
deviceCodes?: string[];
|
||||
}
|
||||
|
||||
/** 通道差异处理参数;编码为空时处理当前全部同类差异 */
|
||||
export interface PlatformChannelDifferenceAction {
|
||||
channelCodes?: string[];
|
||||
}
|
||||
|
||||
export function getStatus() {
|
||||
return request({
|
||||
url: "/admin/third/platform/status",
|
||||
@@ -126,3 +131,27 @@ export function deleteLocalExtraDevices(data: PlatformDeviceDifferenceAction = {
|
||||
timeout: 300000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 ICC 存在但本地缺少的通道同步到本地
|
||||
*/
|
||||
export function syncMissingChannels(data: PlatformChannelDifferenceAction = {}) {
|
||||
return request({
|
||||
url: "/admin/third/platform/channel/sync-missing",
|
||||
method: "post",
|
||||
data,
|
||||
timeout: 300000,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除经 ICC 实时复核后仍属于本地多余的同步通道
|
||||
*/
|
||||
export function deleteLocalExtraChannels(data: PlatformChannelDifferenceAction = {}) {
|
||||
return request({
|
||||
url: "/admin/third/platform/channel/local-extra",
|
||||
method: "delete",
|
||||
data,
|
||||
timeout: 300000,
|
||||
});
|
||||
}
|
||||
@@ -24,22 +24,22 @@
|
||||
<el-alert v-if="isDifferenceView" class="difference-alert" :type="differenceAlertType"
|
||||
:closable="false" show-icon :title="differenceConclusion" />
|
||||
|
||||
<!-- 设备差异支持批量修复,也保留表格逐条处理入口。 -->
|
||||
<section v-if="isDeviceDifferenceView" class="difference-actions" aria-label="设备差异处理">
|
||||
<!-- 设备和通道差异均支持批量修复,也保留表格逐条处理入口。 -->
|
||||
<section v-if="isActionableDifferenceView" class="difference-actions" :aria-label="`${resourceLabel}差异处理`">
|
||||
<div class="difference-actions__description">
|
||||
<strong>快速处理设备差异</strong>
|
||||
<span>操作前会重新读取 ICC 并复核设备编码,已变化的数据会自动跳过。</span>
|
||||
<strong>快速处理{{ resourceLabel }}差异</strong>
|
||||
<span>操作前会重新读取 ICC 并复核{{ resourceLabel }}编码,已变化的数据会自动跳过。</span>
|
||||
</div>
|
||||
<div class="difference-actions__buttons">
|
||||
<el-button type="primary" icon="RefreshRight" :loading="state.actionKey === 'SYNC_ALL'"
|
||||
:disabled="actionBusy || state.result.remoteOnlyCount === 0"
|
||||
v-auth="'admin_deviceManage_edit'" @click="handleDifferenceAction('SYNC')">
|
||||
同步本地缺少设备({{ state.result.remoteOnlyCount }})
|
||||
同步本地缺少{{ resourceLabel }}({{ state.result.remoteOnlyCount }})
|
||||
</el-button>
|
||||
<el-button type="danger" plain icon="Delete" :loading="state.actionKey === 'DELETE_ALL'"
|
||||
:disabled="actionBusy || state.result.localOnlyCount === 0"
|
||||
v-auth="'admin_deviceManage_del'" @click="handleDifferenceAction('DELETE')">
|
||||
删除本地多余设备({{ state.result.localOnlyCount }})
|
||||
删除本地多余{{ resourceLabel }}({{ state.result.localOnlyCount }})
|
||||
</el-button>
|
||||
</div>
|
||||
</section>
|
||||
@@ -64,7 +64,7 @@
|
||||
</template>
|
||||
</el-alert>
|
||||
|
||||
<el-table v-else :data="state.result.records" border :height="isDeviceDifferenceView ? 360 : 430"
|
||||
<el-table v-else :data="state.result.records" border :height="isActionableDifferenceView ? 360 : 430"
|
||||
empty-text="暂无明细数据"
|
||||
row-key="code">
|
||||
<el-table-column v-if="isDifferenceView" label="差异结论" width="190" fixed="left">
|
||||
@@ -117,7 +117,7 @@
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="isDeviceDifferenceView" label="操作" width="104" align="center"
|
||||
<el-table-column v-if="isActionableDifferenceView" label="操作" width="104" align="center"
|
||||
fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button v-if="row.differenceType === 'REMOTE_ONLY'" type="primary" link
|
||||
@@ -171,7 +171,7 @@ const emptyResult = (): PlatformDetailResult => ({
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
/** 设备差异处理完成后通知主页面刷新统计。 */
|
||||
/** 资源差异处理完成后通知主页面刷新统计。 */
|
||||
(event: "changed"): void;
|
||||
}>();
|
||||
|
||||
@@ -192,7 +192,8 @@ const state = reactive({
|
||||
|
||||
const isDevice = computed(() => state.query.resourceType === "DEVICE");
|
||||
const isDifferenceView = computed(() => state.query.viewType === "DIFFERENCE");
|
||||
const isDeviceDifferenceView = computed(() => isDevice.value && isDifferenceView.value);
|
||||
const isActionableDifferenceView = computed(() => isDifferenceView.value);
|
||||
const resourceLabel = computed(() => isDevice.value ? "设备" : "通道");
|
||||
const actionBusy = computed(() => Boolean(state.actionKey));
|
||||
|
||||
// 兼容旧服务未完整返回 total 的情况,差异页可由双方独有数量准确计算总数。
|
||||
@@ -260,7 +261,7 @@ const handleSizeChange = () => {
|
||||
};
|
||||
|
||||
/**
|
||||
* 同步 ICC 独有设备或删除本地独有设备,编码为空时处理当前全部同类差异
|
||||
* 同步 ICC 独有资源或删除本地独有资源,编码为空时处理当前全部同类差异
|
||||
*/
|
||||
const handleDifferenceAction = async (action: "SYNC" | "DELETE", code?: string) => {
|
||||
const isSync = action === "SYNC";
|
||||
@@ -268,20 +269,30 @@ const handleDifferenceAction = async (action: "SYNC" | "DELETE", code?: string)
|
||||
? 1
|
||||
: isSync ? state.result.remoteOnlyCount : state.result.localOnlyCount;
|
||||
const actionText = isSync ? "同步" : "删除";
|
||||
const targetText = isSync ? "本地缺少设备" : "本地多余设备及其通道";
|
||||
const targetText = isSync
|
||||
? `本地缺少${resourceLabel.value}`
|
||||
: isDevice.value ? "本地多余设备及其通道" : "本地多余通道";
|
||||
try {
|
||||
await useMessageBox().confirm(`确认${actionText}${code ? `设备 ${code}` : `全部 ${count} 条${targetText}`}?`);
|
||||
await useMessageBox().confirm(`确认${actionText}${code ? `${resourceLabel.value} ${code}` : `全部 ${count} 条${targetText}`}?`);
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
state.actionKey = `${action}_${code || "ALL"}`;
|
||||
try {
|
||||
const actionApi = isSync
|
||||
? VideoPlatformApi.syncMissingDevices
|
||||
: VideoPlatformApi.deleteLocalExtraDevices;
|
||||
const { data } = await actionApi({ deviceCodes: code ? [code] : [] });
|
||||
useMessage().success(`${actionText}完成,共处理 ${Number(data) || 0} 条设备`);
|
||||
let data: unknown;
|
||||
if (isDevice.value) {
|
||||
const response = isSync
|
||||
? await VideoPlatformApi.syncMissingDevices({ deviceCodes: code ? [code] : [] })
|
||||
: await VideoPlatformApi.deleteLocalExtraDevices({ deviceCodes: code ? [code] : [] });
|
||||
data = response.data;
|
||||
} else {
|
||||
const response = isSync
|
||||
? await VideoPlatformApi.syncMissingChannels({ channelCodes: code ? [code] : [] })
|
||||
: await VideoPlatformApi.deleteLocalExtraChannels({ channelCodes: code ? [code] : [] });
|
||||
data = response.data;
|
||||
}
|
||||
useMessage().success(`${actionText}完成,共处理 ${Number(data) || 0} 条${resourceLabel.value}`);
|
||||
state.query.current = 1;
|
||||
await loadDetail();
|
||||
emit("changed");
|
||||
|
||||
@@ -88,11 +88,22 @@ const getSceneNodeValues = (nodes: SceneNode[] = []) => nodes
|
||||
.map((node) => node.nodeType === "CHANNEL" ? node.channelCode : node.deviceCode)
|
||||
.filter((value): value is string => Boolean(value))
|
||||
|
||||
const handleSourceNodesChange = (_values: string[], nodes: SceneNode[]) => {
|
||||
form.sourceNodes = normalizeSceneNodes(nodes)
|
||||
/** 选择器不是 Element Plus 原生表单控件,变更后需主动刷新对应字段校验状态。 */
|
||||
const validateNodeField = (field: "sourceNodes" | "targetNodes") => {
|
||||
nextTick(() => {
|
||||
formRef.value?.validateField(field).catch(() => {})
|
||||
})
|
||||
}
|
||||
const handleTargetNodesChange = (_values: string[], nodes: SceneNode[]) => {
|
||||
|
||||
const handleSourceNodesChange = (values: string[], nodes: SceneNode[] = []) => {
|
||||
sourceNodeValues.value = Array.isArray(values) ? values : []
|
||||
form.sourceNodes = normalizeSceneNodes(nodes)
|
||||
validateNodeField("sourceNodes")
|
||||
}
|
||||
const handleTargetNodesChange = (values: string[], nodes: SceneNode[] = []) => {
|
||||
targetNodeValues.value = Array.isArray(values) ? values : []
|
||||
form.targetNodes = normalizeSceneNodes(nodes)
|
||||
validateNodeField("targetNodes")
|
||||
}
|
||||
|
||||
const open = async (id?: string | number) => {
|
||||
@@ -104,7 +115,8 @@ const open = async (id?: string | number) => {
|
||||
visible.value = true
|
||||
}
|
||||
const submit = async () => {
|
||||
await formRef.value.validate()
|
||||
const valid = await formRef.value.validate().catch(() => false)
|
||||
if (!valid) return
|
||||
saving.value = true
|
||||
try { await (form.id ? api.updateConfig(form) : api.addConfig(form)); useMessage().success("保存成功"); visible.value = false; emit("refresh") } finally { saving.value = false }
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user