fix: 修复设备编辑请求字段 (#56)

This commit is contained in:
QiuSW
2026-08-13 22:35:25 +08:00
parent 14c97760a7
commit 8e3a25d1d6
4 changed files with 54 additions and 2 deletions
+2 -1
View File
@@ -11,7 +11,8 @@
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "eslint \"src/**/*.{js,vue}\"",
"test:navigation": "node --test tests/navigation.test.cjs"
"test:navigation": "node --test tests/navigation.test.cjs",
"test:device-payload": "node --test tests/devicePayload.test.mjs"
},
"dependencies": {
"@element-plus/icons-vue": "2.3.2",
+2 -1
View File
@@ -52,6 +52,7 @@ import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Search } from '@element-plus/icons-vue'
import { useStore } from 'vuex'
import { createDevice, disableDevice, listDevices, updateCredential, updateDevice } from '../../../api/sense/device'
import { createDevicePayload, updateDevicePayload } from './devicePayload.mjs'
const store = useStore()
const loading = ref(false), saving = ref(false), deviceDialog = ref(false), credentialDialog = ref(false)
@@ -69,7 +70,7 @@ function reset() { Object.assign(query, { keyword: '', page: 1, page_size: 20 })
function openCreate() { editing.value = null; Object.assign(deviceForm, { name: '', location: '', modality: 'video', capabilities: ['video'] }); deviceDialog.value = true }
function openEdit(row) { editing.value = row; Object.assign(deviceForm, { name: row.name, location: row.location, modality: row.modality, capabilities: row.capabilities }); deviceDialog.value = true }
function openCredential(row) { credentialTarget.value = row; Object.assign(credentialForm, { onvif_username: '', onvif_password: '', rtsp_same_as_onvif: row.rtsp_credential_same_as_onvif !== false, rtsp_username: '', rtsp_password: '' }); credentialDialog.value = true }
async function saveDevice() { const valid = await deviceFormRef.value?.validate().catch(() => false); if (!valid) return; saving.value = true; try { if (editing.value) await updateDevice(editing.value.id, { ...deviceForm, version: editing.value.version }); else await createDevice(deviceForm); ElMessage.success('设备已保存'); deviceDialog.value = false; await load() } catch (error) { ElMessage.error(error.message || '保存失败') } finally { saving.value = false } }
async function saveDevice() { const valid = await deviceFormRef.value?.validate().catch(() => false); if (!valid) return; saving.value = true; try { if (editing.value) await updateDevice(editing.value.id, updateDevicePayload(deviceForm, editing.value.version)); else await createDevice(createDevicePayload(deviceForm)); ElMessage.success('设备已保存'); deviceDialog.value = false; await load() } catch (error) { ElMessage.error(error.message || '保存失败') } finally { saving.value = false } }
async function saveCredential() { const valid = await credentialFormRef.value?.validate().catch(() => false); if (!valid) return; saving.value = true; try { await updateCredential(credentialTarget.value.id, credentialForm); Object.assign(credentialForm, { onvif_username: '', onvif_password: '', rtsp_same_as_onvif: true, rtsp_username: '', rtsp_password: '' }); ElMessage.success('ONVIF 与 RTSP 凭据已安全更新'); credentialDialog.value = false; await load() } catch (error) { ElMessage.error(error.message || '更新失败') } finally { saving.value = false } }
async function disable(row) { await ElMessageBox.confirm(`停用“${row.name}”后将停止后续接入,设备记录和审计仍保留。`, '确认停用', { type: 'warning' }); await disableDevice(row.id, row.version); ElMessage.success('设备已停用'); await load() }
onMounted(load)
@@ -0,0 +1,17 @@
export function createDevicePayload(form) {
return {
name: form.name,
location: form.location,
modality: form.modality,
capabilities: [...form.capabilities]
}
}
export function updateDevicePayload(form, version) {
return {
name: form.name,
location: form.location,
capabilities: [...form.capabilities],
version
}
}
+33
View File
@@ -0,0 +1,33 @@
import assert from 'node:assert/strict'
import test from 'node:test'
import { createDevicePayload, updateDevicePayload } from '../src/views/sense/device/devicePayload.mjs'
const form = {
name: '东门摄像机',
location: '教学楼一楼东门',
modality: 'video',
capabilities: ['video'],
id: 'read-only-id'
}
test('create payload keeps Chinese values and includes modality', () => {
assert.deepEqual(createDevicePayload(form), {
name: '东门摄像机',
location: '教学楼一楼东门',
modality: 'video',
capabilities: ['video']
})
})
test('update payload uses the PATCH allowlist and excludes modality', () => {
const payload = updateDevicePayload(form, 9)
assert.deepEqual(payload, {
name: '东门摄像机',
location: '教学楼一楼东门',
capabilities: ['video'],
version: 9
})
assert.equal('modality' in payload, false)
assert.equal('id' in payload, false)
})