【功能完善】IoT:增加 device config 配置

This commit is contained in:
YunaiV 2025-03-13 08:18:12 +08:00
parent 6636068bd5
commit 3685e438fa
4 changed files with 64 additions and 61 deletions

View File

@ -27,6 +27,7 @@ export interface DeviceVO {
areaId: number // 地区编码
address: string // 设备详细地址
serialNumber: string // 设备序列号
config: string // 设备配置
groupIds?: number[] // 添加分组 ID
}
@ -72,7 +73,7 @@ export interface IotDeviceDownstreamReqVO {
data: any // 请求参数
}
// MQTT连接参数 VO
// MQTT 连接参数 VO
export interface MqttConnectionParamsVO {
mqttClientId: string // MQTT 客户端 ID
mqttUsername: string // MQTT 用户名

View File

@ -11,9 +11,8 @@
<!-- JSON 编辑器读模式 -->
<Vue3Jsoneditor
ref="editor"
v-if="isEditing"
v-model="deviceConfigState"
v-model="config"
:options="editorOptions"
height="500px"
currentMode="code"
@ -21,62 +20,48 @@
/>
<!-- JSON 编辑器写模式 -->
<Vue3Jsoneditor
ref="editor"
v-else
v-model="deviceConfigState"
v-model="config"
:options="editorOptions"
height="500px"
currentMode="view"
v-loading.fullscreen.lock="loading"
@error="onError"
/>
<div class="flex justify-center mt-24">
<div class="mt-5 text-center">
<el-button v-if="isEditing" @click="cancelEdit">取消</el-button>
<el-button v-if="isEditing" type="primary" @click="saveConfig">保存</el-button>
<el-button v-if="isEditing" type="primary" @click="saveConfig" :disabled="hasJsonError"
>保存</el-button
>
<el-button v-else @click="enableEdit">编辑</el-button>
<!-- TODO @芋艿缺一个下发按钮 -->
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, computed } from 'vue'
import Vue3Jsoneditor from 'v3-jsoneditor/src/Vue3Jsoneditor.vue'
import { DeviceApi } from '@/api/iot/device/device/index'
import { useTagsViewStore } from '@/store/modules/tagsView'
import { DeviceVO } from '../../../../../api/iot/device/device/index';
import { DeviceApi, DeviceVO } from '@/api/iot/device/device'
import { jsonParse } from '@/utils'
const props = defineProps<{
device: DeviceVO
}>()
const emit = defineEmits<{
(e: 'success'): void // success
}>()
const route = useRoute()
const message = useMessage()
const { delView } = useTagsViewStore() //
const { currentRoute } = useRouter() //
const id = Number(route.params.id) //
const loading = ref(true) //
const deviceConfigState = ref({}) //
const loading = ref(false) //
const config = ref<any>({}) // config
const hasJsonError = ref(false) // JSON
//
const getDeviceConfig = async (id: number) => {
try {
loading.value = true
const res = await DeviceApi.getDevice(id)
deviceConfigState.value = res
} catch (error) {
console.error(error)
} finally {
loading.value = false
}
}
onMounted(async () => {
if (!id) {
message.warning('参数错误,产品不能为空!')
delView(unref(currentRoute))
return
}
await getDeviceConfig(id)
/** 监听 props.device 的变化,只更新 config 字段 */
watchEffect(() => {
config.value = jsonParse(props.device.config)
})
const isEditing = ref(false) //
const editorOptions = computed(() => ({
mainMenuBar: false,
@ -87,40 +72,48 @@ const editorOptions = computed(() => ({
/** 启用编辑模式的函数 */
const enableEdit = () => {
isEditing.value = true
hasJsonError.value = false //
}
/** 取消编辑的函数 */
const cancelEdit = () => {
config.value = jsonParse(props.device.config)
isEditing.value = false
//
console.log('取消编辑')
hasJsonError.value = false //
}
/** 保存配置的函数 */
const saveConfig = async () => {
const params = {
...deviceConfigState.value
} as DeviceVO
await updateDeviceConfig(params)
if (hasJsonError.value) {
message.error('JSON格式错误请修正后再提交')
return
}
await updateDeviceConfig()
isEditing.value = false
}
/** 处理 JSON 编辑器错误的函数 */
const onError = (e: any) => {
console.log('onError', e)
}
//
const updateDeviceConfig = async (params: DeviceVO) => {
/** 更新设备配置 */
const updateDeviceConfig = async () => {
try {
//
loading.value = true
await DeviceApi.updateDevice(params)
await getDeviceConfig(id)
await DeviceApi.updateDevice({
id: props.device.id,
config: JSON.stringify(config.value)
} as DeviceVO)
message.success('更新成功!')
// success
emit('success')
} catch (error) {
console.error(error)
} finally {
loading.value = false
}
}
/** 处理 JSON 编辑器错误的函数 */
const onError = (e: any) => {
console.log('onError', e)
hasJsonError.value = true
}
</script>

View File

@ -63,7 +63,11 @@
</el-input>
</el-form-item>
<el-form-item label="passwd">
<el-input v-model="mqttParams.mqttPassword" readonly :type="passwordVisible ? 'text' : 'password'">
<el-input
v-model="mqttParams.mqttPassword"
readonly
:type="passwordVisible ? 'text' : 'password'"
>
<template #append>
<el-button @click="passwordVisible = !passwordVisible" type="primary">
<Icon :icon="passwordVisible ? 'ph:eye-slash' : 'ph:eye'" />
@ -117,13 +121,14 @@ const copyToClipboard = async (text: string) => {
const openMqttParams = async () => {
try {
const res = await DeviceApi.getMqttConnectionParams(device.id)
// API
// API
mqttParams.value = {
mqttClientId: res.mqttClientId || 'N/A',
mqttUsername: res.mqttUsername || 'N/A',
mqttPassword: res.mqttPassword || 'N/A'
}
// MQTT
mqttDialogVisible.value = true
} catch (error) {
console.error('获取MQTT连接参数出错', error)

View File

@ -27,7 +27,11 @@
/>
</el-tab-pane>
<el-tab-pane label="设备配置" name="config">
<DeviceDetailConfig />
<DeviceDetailConfig
v-if="activeTab === 'config'"
:device="device"
@success="getDeviceData"
/>
</el-tab-pane>
</el-tabs>
</el-col>
@ -41,7 +45,7 @@ import DeviceDetailsInfo from './DeviceDetailsInfo.vue'
import DeviceDetailsModel from './DeviceDetailsModel.vue'
import DeviceDetailsLog from './DeviceDetailsLog.vue'
import DeviceDetailsSimulator from './DeviceDetailsSimulator.vue'
import DeviceDetailConfig from './DeviceDetailConfig.vue';
import DeviceDetailConfig from './DeviceDetailConfig.vue'
defineOptions({ name: 'IoTDeviceDetail' })
@ -54,7 +58,7 @@ const device = ref<DeviceVO>({} as DeviceVO) // 设备详情
const activeTab = ref('info') //
/** 获取设备详情 */
const getDeviceData = async (id: number) => {
const getDeviceData = async () => {
loading.value = true
try {
device.value = await DeviceApi.getDevice(id)
@ -78,7 +82,7 @@ onMounted(async () => {
delView(unref(currentRoute))
return
}
await getDeviceData(id)
await getDeviceData()
activeTab.value = (route.query.tab as string) || 'info'
})
</script>