```
feat(import): 添加区域字段支持和改进模板路径处理 - 在OLT设备导入功能中添加region字段支持,从Excel模板读取区域信息 - 修复模板文件路径问题,使用相对路径动态构建模板文件路径 - 更新导入服务中的验证错误格式,包含行号和MAC地址信息 feat(check): 增强设备检测服务的端口信息同步 - 在CheckService中添加端口和OLT归属信息的同步逻辑 - 改进设备状态检查时的端口信息更新策略,避免用None覆盖现有值 - 扩展返回数据结构,包含端口ID、槽位号、端口号和OLT位置信息 feat(frontend): 添加设备列表刷新冷却机制和端口验证 - 实现设备状态刷新的60秒冷却时间限制,防止频繁操作 - 改进业务下发按钮的启用条件,同时支持port_id或slot_number+port_number组合 - 优化导入结果显示,显示具体的MAC地址信息 feat(olt): 添加重复MAC记录批量清除功能 - 新增批量清除重复MAC记录的功能,支持按OLT分组处理 - 实现SSH端口清除和自动忽略的批量操作流程 - 添加批量操作的进度提示和错误处理机制 ```
This commit is contained in:
@@ -10,8 +10,8 @@
|
||||
<el-button v-if="!isMobile && can('device.delete')" type="danger" plain size="small" @click="clearStatus" :loading="clearing">
|
||||
清空状态
|
||||
</el-button>
|
||||
<el-button v-if="can('device.check')" type="warning" size="small" @click="refreshAllStatus" :loading="refreshing">
|
||||
{{ refreshing ? '更新中…' : '全部更新' }}
|
||||
<el-button v-if="can('device.check')" type="warning" size="small" @click="refreshAllStatus" :loading="refreshing" :disabled="refreshing || refreshCooldown > 0">
|
||||
{{ refreshing ? '更新中…' : refreshCooldown > 0 ? `冷却 ${refreshCooldown}s` : '全部更新' }}
|
||||
</el-button>
|
||||
<el-button v-if="can('device.import')" type="success" size="small" @click="importDialogVisible = true">
|
||||
数据导入
|
||||
@@ -203,7 +203,7 @@
|
||||
v-if="can('device.edit')"
|
||||
class="card-action-btn card-action-btn--primary"
|
||||
@click.stop="openProvisionFromCard(device)"
|
||||
:disabled="device.status !== 'online' || !device.port_id"
|
||||
:disabled="device.status !== 'online' || (!device.port_id && !(device.slot_number && device.port_number))"
|
||||
>
|
||||
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/>
|
||||
@@ -347,7 +347,7 @@
|
||||
<el-button v-if="can('device.check')" type="info" :loading="deviceRefreshing" @click="doRefreshDevice" :disabled="!selectedDevice.olt_id">更新</el-button>
|
||||
<el-button v-if="can('device.edit')" type="warning" @click="openReplace">更换</el-button>
|
||||
<el-button v-if="can('device.edit')" type="primary" @click="openEdit">编辑</el-button>
|
||||
<el-button v-if="can('device.edit')" type="success" @click="openProvision" :disabled="selectedDevice.status !== 'online' || !selectedDevice.port_id">
|
||||
<el-button v-if="can('device.edit')" type="success" @click="openProvision" :disabled="selectedDevice.status !== 'online' || (!selectedDevice.port_id && !(selectedDevice.slot_number && selectedDevice.port_number))">
|
||||
业务下发
|
||||
</el-button>
|
||||
<el-button @click="detailVisible = false">关闭</el-button>
|
||||
@@ -480,7 +480,7 @@ save force</pre>
|
||||
/>
|
||||
<div v-if="importResult.failed?.length" style="margin-top: 10px; max-height: 160px; overflow-y: auto">
|
||||
<div v-for="f in importResult.failed" :key="f.row" style="font-size: 12px; color: var(--danger); padding: 2px 0">
|
||||
第 {{ f.row }} 行:{{ f.reason }}
|
||||
第 {{ f.row }} 行<template v-if="f.mac">({{ f.mac }})</template>:{{ f.reason }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -521,6 +521,8 @@ const provisionVisible = ref(false)
|
||||
const provisionLoading = ref(false)
|
||||
const provisionResult = ref(null)
|
||||
const refreshing = ref(false)
|
||||
const refreshCooldown = ref(0)
|
||||
let cooldownTimer = null
|
||||
const clearing = ref(false)
|
||||
|
||||
const editVisible = ref(false)
|
||||
@@ -636,6 +638,7 @@ const clearStatus = async () => {
|
||||
}
|
||||
|
||||
const refreshAllStatus = async () => {
|
||||
if (refreshCooldown.value > 0) return
|
||||
refreshing.value = true
|
||||
checkResultVisible.value = true
|
||||
checkInProgress.value = true
|
||||
@@ -654,6 +657,15 @@ const refreshAllStatus = async () => {
|
||||
} finally {
|
||||
checkInProgress.value = false
|
||||
refreshing.value = false
|
||||
clearInterval(cooldownTimer)
|
||||
refreshCooldown.value = 60
|
||||
cooldownTimer = setInterval(() => {
|
||||
refreshCooldown.value--
|
||||
if (refreshCooldown.value <= 0) {
|
||||
clearInterval(cooldownTimer)
|
||||
refreshCooldown.value = 0
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -691,6 +703,10 @@ const doRefreshDevice = async () => {
|
||||
selectedDevice.value.status = data.status
|
||||
selectedDevice.value.distance_m = data.distance_m
|
||||
if (data.model) selectedDevice.value.model = data.model
|
||||
if (data.port_id !== undefined) selectedDevice.value.port_id = data.port_id
|
||||
if (data.slot_number !== undefined) selectedDevice.value.slot_number = data.slot_number
|
||||
if (data.port_number !== undefined) selectedDevice.value.port_number = data.port_number
|
||||
if (data.olt_location !== undefined) selectedDevice.value.olt_location = data.olt_location
|
||||
ElMessage.success(`更新完成:${data.status === 'online' ? '在线' : '离线'}${data.distance_m ? ',距离 ' + formatDistance(data.distance_m) : ''}`)
|
||||
loadDevices()
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user