mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-29 02:53:57 +08:00
fix: 修复设备管理无法提交备注信息的问题。
chore: 将设备自动更新状态接口重构为设备信息更新接口,以此实现备注、自动更新合并在一个接口内
This commit is contained in:
+8
-4
@@ -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;
|
||||||
|
}
|
||||||
@@ -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()
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user