fix: 修复设备管理无法提交备注信息的问题。

chore: 将设备自动更新状态接口重构为设备信息更新接口,以此实现备注、自动更新合并在一个接口内
This commit is contained in:
caixypromise
2025-06-16 03:27:12 +08:00
parent f5583717d5
commit 9885d4758b
4 changed files with 138 additions and 63 deletions
@@ -2,8 +2,11 @@ package xiaozhi.modules.device.controller;
import java.util.List; import java.util.List;
import jakarta.validation.Valid;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
@@ -22,6 +25,7 @@ import xiaozhi.common.user.UserDetail;
import xiaozhi.common.utils.Result; import xiaozhi.common.utils.Result;
import xiaozhi.modules.device.dto.DeviceRegisterDTO; import xiaozhi.modules.device.dto.DeviceRegisterDTO;
import xiaozhi.modules.device.dto.DeviceUnBindDTO; import xiaozhi.modules.device.dto.DeviceUnBindDTO;
import xiaozhi.modules.device.dto.DeviceUpdateDTO;
import xiaozhi.modules.device.entity.DeviceEntity; import xiaozhi.modules.device.entity.DeviceEntity;
import xiaozhi.modules.device.service.DeviceService; import xiaozhi.modules.device.service.DeviceService;
import xiaozhi.modules.security.user.SecurityUser; import xiaozhi.modules.security.user.SecurityUser;
@@ -80,15 +84,15 @@ public class DeviceController {
return new Result<Void>(); return new Result<Void>();
} }
@PutMapping("/enableOta/{id}/{status}") @PutMapping("/update/{id}")
@Operation(summary = "启用/关闭OTA自动升级") @Operation(summary = "更新设备信息")
@RequiresPermissions("sys:role:normal") @RequiresPermissions("sys:role:normal")
public Result<Void> enableOtaUpgrade(@PathVariable String id, @PathVariable Integer status) { public Result<Void> updateDeviceInfo(@PathVariable String id, @Valid @RequestBody DeviceUpdateDTO deviceUpdateDTO) {
DeviceEntity entity = deviceService.selectById(id); DeviceEntity entity = deviceService.selectById(id);
if (entity == null) { if (entity == null) {
return new Result<Void>().error("设备不存在"); return new Result<Void>().error("设备不存在");
} }
entity.setAutoUpdate(status); BeanUtils.copyProperties(deviceUpdateDTO, entity);
deviceService.updateById(entity); deviceService.updateById(entity);
return new Result<Void>(); return new Result<Void>();
} }
@@ -0,0 +1,29 @@
package xiaozhi.modules.device.dto;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.io.Serializable;
/**
* 设备更新DTO
*/
@Data
public class DeviceUpdateDTO implements Serializable {
/**
* 自动更新状态
*/
@Max(1)
@Min(0)
private Integer autoUpdate;
/**
* 设备别名
*/
@Size(max = 64)
private String alias;
private static final long serialVersionUID = 1L;
}
+4 -3
View File
@@ -51,10 +51,11 @@ export default {
}); });
}).send(); }).send();
}, },
enableOtaUpgrade(id, status, callback) { updateDeviceInfo(id, payload, callback) {
RequestService.sendRequest() RequestService.sendRequest()
.url(`${getServiceUrl()}/device/enableOta/${id}/${status}`) .url(`${getServiceUrl()}/device/update/${id}`)
.method('PUT') .method('PUT')
.data(payload)
.success((res) => { .success((res) => {
RequestService.clearRequestTime() RequestService.clearRequestTime()
callback(res) callback(res)
@@ -63,7 +64,7 @@ export default {
console.error('更新OTA状态失败:', err) console.error('更新OTA状态失败:', err)
this.$message.error(err.msg || '更新OTA状态失败') this.$message.error(err.msg || '更新OTA状态失败')
RequestService.reAjaxFun(() => { RequestService.reAjaxFun(() => {
this.enableOtaUpgrade(id, status, callback) this.updateDeviceInfo(id, payload, callback)
}) })
}).send() }).send()
}, },
+68 -27
View File
@@ -16,7 +16,8 @@
<div class="content-area"> <div class="content-area">
<el-card class="device-card" shadow="never"> <el-card class="device-card" shadow="never">
<el-table ref="deviceTable" :data="paginatedDeviceList" class="transparent-table" <el-table ref="deviceTable" :data="paginatedDeviceList" class="transparent-table"
:header-cell-class-name="headerCellClassName" v-loading="loading" element-loading-text="拼命加载中" :header-cell-class-name="headerCellClassName" v-loading="loading"
element-loading-text="拼命加载中"
element-loading-spinner="el-icon-loading" element-loading-background="rgba(255, 255, 255, 0.7)"> element-loading-spinner="el-icon-loading" element-loading-background="rgba(255, 255, 255, 0.7)">
<el-table-column label="选择" align="center" width="120"> <el-table-column label="选择" align="center" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
@@ -33,14 +34,24 @@
<el-table-column label="绑定时间" prop="bindTime" align="center"></el-table-column> <el-table-column label="绑定时间" prop="bindTime" align="center"></el-table-column>
<el-table-column label="最近对话" prop="lastConversation" align="center"></el-table-column> <el-table-column label="最近对话" prop="lastConversation" align="center"></el-table-column>
<el-table-column label="备注" align="center"> <el-table-column label="备注" align="center">
<template slot-scope="scope"> <template #default="{ row }">
<el-input v-if="scope.row.isEdit" v-model="scope.row.remark" size="mini" <el-input
@blur="stopEditRemark(scope.$index)"></el-input> v-show="row.isEdit"
<span v-else> v-model="row.remark"
<i v-if="!scope.row.remark" class="el-icon-edit" size="mini"
@click="startEditRemark(scope.$index, scope.row)"></i> maxlength="64"
<span v-else @click="startEditRemark(scope.$index, scope.row)"> show-word-limit
{{ scope.row.remark }} @blur="onRemarkBlur(row)"
@keyup.enter.native="onRemarkEnter(row)"
/>
<span v-show="!row.isEdit" class="remark-view">
<i
class="el-icon-edit"
@click="row.isEdit = true"
style="cursor: pointer;"
></i>
<span @click="row.isEdit = true">
{{ row.remark || '' }}
</span> </span>
</span> </span>
</template> </template>
@@ -133,10 +144,7 @@ export default {
paginatedDeviceList() { paginatedDeviceList() {
const start = (this.currentPage - 1) * this.pageSize; const start = (this.currentPage - 1) * this.pageSize;
const end = start + this.pageSize; const end = start + this.pageSize;
return this.filteredDeviceList.slice(start, end).map(item => ({ return this.filteredDeviceList.slice(start, end);
...item,
selected: false
}));
}, },
pageCount() { pageCount() {
return Math.ceil(this.filteredDeviceList.length / this.pageSize); return Math.ceil(this.filteredDeviceList.length / this.pageSize);
@@ -212,7 +220,6 @@ export default {
this.batchUnbindDevices(deviceIds); this.batchUnbindDevices(deviceIds);
}); });
}, },
batchUnbindDevices(deviceIds) { batchUnbindDevices(deviceIds) {
const promises = deviceIds.map(id => { const promises = deviceIds.map(id => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@@ -225,7 +232,6 @@ export default {
}); });
}); });
}); });
Promise.all(promises) Promise.all(promises)
.then(() => { .then(() => {
this.$message.success({ this.$message.success({
@@ -243,15 +249,44 @@ export default {
}); });
}); });
}, },
handleAddDevice() { handleAddDevice() {
this.addDeviceDialogVisible = true; this.addDeviceDialogVisible = true;
}, },
startEditRemark(index, row) { submitRemark(row) {
this.deviceList[index].isEdit = true; if (row._submitting) return;
const text = (row.remark || '').trim();
if (text.length > 64) {
this.$message.warning('备注不能超过 64 字符');
return;
}
if (text === row._originalRemark) {
return;
}
row._submitting = true;
this.updateDeviceInfo(row.device_id, { alias: text }, (ok, resp) => {
if (ok) {
row._originalRemark = text;
this.$message.success('备注已保存');
} else {
row.remark = row._originalRemark;
this.$message.error(resp.msg || '备注保存失败');
}
row._submitting = false;
});
}, },
stopEditRemark(index) { // 备注输入框:失焦时提交
this.deviceList[index].isEdit = false; onRemarkBlur(row) {
row.isEdit = false;
setTimeout(() => {
this.submitRemark(row);
}, 100); // 延迟 100ms,避开 enter+blur 同时触发的窗口
},
// 备注输入框:按回车时提交
onRemarkEnter(row) {
row.isEdit = false;
this.submitRemark(row);
}, },
handleUnbind(device_id) { handleUnbind(device_id) {
this.$confirm('确认要解绑该设备吗?', '警告', { this.$confirm('确认要解绑该设备吗?', '警告', {
@@ -302,7 +337,9 @@ export default {
bindTime: device.createDate, bindTime: device.createDate,
lastConversation: device.lastConnectedAt, lastConversation: device.lastConnectedAt,
remark: device.alias, remark: device.alias,
_originalRemark: device.alias,
isEdit: false, isEdit: false,
_submitting: false,
otaSwitch: device.autoUpdate === 1, otaSwitch: device.autoUpdate === 1,
rawBindTime: new Date(device.createDate).getTime() rawBindTime: new Date(device.createDate).getTime()
}; };
@@ -325,14 +362,19 @@ export default {
const firmwareType = this.firmwareTypes.find(item => item.key === type) const firmwareType = this.firmwareTypes.find(item => item.key === type)
return firmwareType ? firmwareType.name : type return firmwareType ? firmwareType.name : type
}, },
updateDeviceInfo(device_id, payload, callback) {
return Api.device.updateDeviceInfo(device_id, payload, ({data}) => {
callback(data.code === 0, data);
})
},
handleOtaSwitchChange(row) { handleOtaSwitchChange(row) {
Api.device.enableOtaUpgrade(row.device_id, row.otaSwitch ? 1 : 0, ({ data }) => { this.updateDeviceInfo(row.device_id, {autoUpdate: row.otaSwitch ? 1 : 0}, (result, {msg}) => {
if (data.code === 0) { if (result) {
this.$message.success(row.otaSwitch ? '已设置成自动升级' : '已关闭自动升级') this.$message.success(row.otaSwitch ? '已设置成自动升级' : '已关闭自动升级');
} else { return;
row.otaSwitch = !row.otaSwitch
this.$message.error(data.msg || '操作失败')
} }
row.otaSwitch = !row.otaSwitch
this.$message.error(msg || '操作失败')
}) })
}, },
} }
@@ -645,7 +687,6 @@ export default {
} }
:deep(.el-table .el-button--text) { :deep(.el-table .el-button--text) {
color: #7079aa; color: #7079aa;
} }