From f555eae653d4cdf25690e2ae84e784eb0e56000b Mon Sep 17 00:00:00 2001 From: hrz <1710360675@qq.com> Date: Fri, 25 Apr 2025 17:56:47 +0800 Subject: [PATCH] Merge pull request #999 from xinnan-tech/auto-ota-update Auto ota update --- docs/Deployment_all.md | 28 ++++++++-- docs/firmware-build.md | 14 ++--- .../common/config/RestTemplateConfig.java | 17 ++++++ .../xiaozhi/common/constant/Constant.java | 5 ++ .../device/controller/DeviceController.java | 13 +++++ .../modules/device/service/DeviceService.java | 8 +-- .../service/impl/DeviceServiceImpl.java | 43 ++++++++------- .../sys/controller/SysParamsController.java | 52 +++++++++++++++++++ .../resources/db/changelog/202504221646.sql | 6 --- .../{202504180758.sql => 202504251421.sql} | 15 +++--- .../db/changelog/db.changelog-master.yaml | 21 +++----- main/manager-web/src/apis/module/device.js | 16 ++++++ .../src/views/DeviceManagement.vue | 42 ++++++++------- 13 files changed, 197 insertions(+), 83 deletions(-) create mode 100644 main/manager-api/src/main/java/xiaozhi/common/config/RestTemplateConfig.java delete mode 100644 main/manager-api/src/main/resources/db/changelog/202504221646.sql rename main/manager-api/src/main/resources/db/changelog/{202504180758.sql => 202504251421.sql} (64%) diff --git a/docs/Deployment_all.md b/docs/Deployment_all.md index a0bb2f16..7eaa9451 100644 --- a/docs/Deployment_all.md +++ b/docs/Deployment_all.md @@ -122,11 +122,11 @@ http://localhost:8002/xiaozhi/doc.html 这时,你需要使用浏览器,打开`智控台`,链接:http://127.0.0.1:8002 ,注册第一个用户。第一个用户即是超级管理员,以后的用户都是普通用户。普通用户只能绑定设备和配置智能体;超级管理员可以进行模型管理、用户管理、参数配置等功能。 -接下来要做两件重要的事情: +接下来要做三件重要的事情: ### 第一件重要的事情 -使用超级管理员账号,登录系统,在顶部菜单找到`参数管理`,找到列表中第三条数据,参数编码是`server.secret`,复制它到`参数值`。 +使用超级管理员账号,登录系统,在顶部菜单找到`参数管理`,找到列表中第一条数据,参数编码是`server.secret`,复制它到`参数值`。 `server.secret`需要说明一下,这个`参数值`很重要,作用是让我们的`Server`端连接`manager-api`。`server.secret`是每次从零部署manager模块时,会自动随机生成的密钥。 @@ -138,7 +138,12 @@ manager-api: secret: 你的server.secret值 ``` 1、把你刚才从`智控台`复制过来的`server.secret`的`参数值`复制到`.config.yaml`文件里的`secret`里。 -2、注意,把`url`改成下面的`http://xiaozhi-esp32-server-web:8002/xiaozhi` + +2、因为你是docker部署,把`url`改成下面的`http://xiaozhi-esp32-server-web:8002/xiaozhi` + +3、因为你是docker部署,把`url`改成下面的`http://xiaozhi-esp32-server-web:8002/xiaozhi` + +4、因为你是docker部署,把`url`改成下面的`http://xiaozhi-esp32-server-web:8002/xiaozhi` 类似这样的效果 ``` @@ -182,6 +187,12 @@ Websocket接口: ws://你电脑局域网的ip:8000/xiaozhi/v1/ ``` +### 第三件重要的事情 + +使用超级管理员账号,登录系统,在顶部菜单找到`参数管理`,找到参数编码是`server.websocket`,输入你的`Websocket接口`。 + +使用超级管理员账号,登录系统,在顶部菜单找到`参数管理`,找到数编码是`server.ota`,输入你的`OTA接口`。 + 接下来,你就可以开始操作你的esp32设备了,你可以`自行编译esp32固件`也可以配置使用`虾哥编译好的1.6.1以上版本的固件`。两个任选一个 1、 [编译自己的esp32固件](firmware-build.md)了。 @@ -353,7 +364,7 @@ pip install -r requirements.txt ## 8.配置项目文件 -使用超级管理员账号,登录智控台 http://127.0.0.1:8002 ,在顶部菜单找到`参数管理`,找到列表中第三条数据,参数编码是`server.secret`,复制它到`参数值`。 +使用超级管理员账号,登录智控台 http://127.0.0.1:8002 ,在顶部菜单找到`参数管理`,找到列表中第一条数据,参数编码是`server.secret`,复制它到`参数值`。 `server.secret`需要说明一下,这个`参数值`很重要,作用是让我们的`Server`端连接`manager-api`。`server.secret`是每次从零部署manager模块时,会自动随机生成的密钥。 @@ -394,7 +405,7 @@ python app.py 25-02-23 12:01:09[core.websocket_server] - INFO - ======================================================= ``` -由于你是全模块部署,因此你有两个重要的接口需要写入到esp32中。 +由于你是全模块部署,因此你有两个重要的接口。 OTA接口: ``` @@ -406,6 +417,13 @@ Websocket接口: ws://你电脑局域网的ip:8000/xiaozhi/v1/ ``` +请你务必把以上两个接口地址写入到智控台中:他们将会影响websocket地址发放和自动升级功能。 + +1、使用超级管理员账号,登录系统,在顶部菜单找到`参数管理`,找到参数编码是`server.websocket`,输入你的`Websocket接口`。 + +2、使用超级管理员账号,登录系统,在顶部菜单找到`参数管理`,找到数编码是`server.ota`,输入你的`OTA接口`。 + + 接下来,你就可以开始操作你的esp32设备了,你可以`自行编译esp32固件`也可以配置使用`虾哥编译好的1.6.1以上版本的固件`。两个任选一个 1、 [编译自己的esp32固件](firmware-build.md)了。 diff --git a/docs/firmware-build.md b/docs/firmware-build.md index ebb7413b..4439bb9b 100644 --- a/docs/firmware-build.md +++ b/docs/firmware-build.md @@ -36,24 +36,24 @@ ws://192.168.1.25:8000/xiaozhi/v1/ ## 第4步 修改OTA地址 -找到`OTA_VERSION_URL`的`default`的内容,把`https://api.tenclass.net/xiaozhi/ota/` +找到`OTA_URL`的`default`的内容,把`https://api.tenclass.net/xiaozhi/ota/` 改成你自己的地址,例如,我的接口地址是`http://192.168.1.25:8002/xiaozhi/ota/`,就把内容改成这个。 修改前: ``` -config OTA_VERSION_URL - string "OTA Version URL" +config OTA_URL + string "Default OTA URL" default "https://api.tenclass.net/xiaozhi/ota/" help - The application will access this URL to check for updates. + The application will access this URL to check for new firmwares and server address. ``` 修改后: ``` -config OTA_VERSION_URL - string "OTA Version URL" +config OTA_URL + string "Default OTA URL" default "http://192.168.1.25:8002/xiaozhi/ota/" help - The application will access this URL to check for updates. + The application will access this URL to check for new firmwares and server address. ``` ## 第4步 设置编译参数 diff --git a/main/manager-api/src/main/java/xiaozhi/common/config/RestTemplateConfig.java b/main/manager-api/src/main/java/xiaozhi/common/config/RestTemplateConfig.java new file mode 100644 index 00000000..ecfaa359 --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/common/config/RestTemplateConfig.java @@ -0,0 +1,17 @@ +package xiaozhi.common.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +/** + * RestTemplate配置 + */ +@Configuration +public class RestTemplateConfig { + + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } +} \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/common/constant/Constant.java b/main/manager-api/src/main/java/xiaozhi/common/constant/Constant.java index 47d45e7e..1edea3fd 100644 --- a/main/manager-api/src/main/java/xiaozhi/common/constant/Constant.java +++ b/main/manager-api/src/main/java/xiaozhi/common/constant/Constant.java @@ -89,6 +89,11 @@ public interface Constant { */ String SERVER_WEBSOCKET = "server.websocket"; + /** + * ota地址 + */ + String SERVER_OTA = "server.ota"; + /** * 是否允许用户注册 */ diff --git a/main/manager-api/src/main/java/xiaozhi/modules/device/controller/DeviceController.java b/main/manager-api/src/main/java/xiaozhi/modules/device/controller/DeviceController.java index 1c68a756..5b0bf4bc 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/device/controller/DeviceController.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/device/controller/DeviceController.java @@ -7,6 +7,7 @@ import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -79,4 +80,16 @@ public class DeviceController { return new Result(); } + @PutMapping("/enableOta/{id}/{status}") + @Operation(summary = "启用/关闭OTA自动升级") + @RequiresPermissions("sys:role:normal") + public Result enableOtaUpgrade(@PathVariable String id, @PathVariable Integer status) { + DeviceEntity entity = deviceService.selectById(id); + if (entity == null) { + return new Result().error("设备不存在"); + } + entity.setAutoUpdate(status); + deviceService.updateById(entity); + return new Result(); + } } \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/device/service/DeviceService.java b/main/manager-api/src/main/java/xiaozhi/modules/device/service/DeviceService.java index 8bb203cc..aff31bff 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/device/service/DeviceService.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/device/service/DeviceService.java @@ -3,18 +3,14 @@ package xiaozhi.modules.device.service; import java.util.List; import xiaozhi.common.page.PageData; +import xiaozhi.common.service.BaseService; import xiaozhi.modules.device.dto.DevicePageUserDTO; import xiaozhi.modules.device.dto.DeviceReportReqDTO; import xiaozhi.modules.device.dto.DeviceReportRespDTO; import xiaozhi.modules.device.entity.DeviceEntity; import xiaozhi.modules.device.vo.UserShowDeviceListVO; -public interface DeviceService { - - /** - * 根据Mac地址获取设备信息 - */ - DeviceEntity getDeviceById(String macAddress); +public interface DeviceService extends BaseService { /** * 检查设备是否激活 diff --git a/main/manager-api/src/main/java/xiaozhi/modules/device/service/impl/DeviceServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/device/service/impl/DeviceServiceImpl.java index 2a451733..6fdd2689 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/device/service/impl/DeviceServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/device/service/impl/DeviceServiceImpl.java @@ -13,7 +13,6 @@ import org.springframework.stereotype.Service; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; @@ -55,13 +54,6 @@ public class DeviceServiceImpl extends BaseServiceImpl private final RedisUtils redisUtils; private final OtaService otaService; - @Override - public DeviceEntity getDeviceById(String deviceId) { - LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); - queryWrapper.eq(DeviceEntity::getId, deviceId); - return deviceDao.selectOne(queryWrapper); - } - @Override public Boolean deviceActivation(String agentId, String activationCode) { if (StringUtils.isBlank(activationCode)) { @@ -105,6 +97,7 @@ public class DeviceServiceImpl extends BaseServiceImpl deviceEntity.setMacAddress(macAddress); deviceEntity.setUserId(user.getId()); deviceEntity.setCreator(user.getId()); + deviceEntity.setAutoUpdate(1); deviceEntity.setCreateDate(currentTime); deviceEntity.setUpdater(user.getId()); deviceEntity.setUpdateDate(currentTime); @@ -123,16 +116,22 @@ public class DeviceServiceImpl extends BaseServiceImpl DeviceReportRespDTO response = new DeviceReportRespDTO(); response.setServer_time(buildServerTime()); - String type = deviceReport.getBoard() == null ? null : deviceReport.getBoard().getType(); - DeviceReportRespDTO.Firmware firmware = buildFirmwareInfo(type, macAddress); - response.setFirmware(firmware); + DeviceEntity deviceById = getDeviceByMacAddress(macAddress); + + if (deviceById == null || deviceById.getAutoUpdate() != 0) { + String type = deviceReport.getBoard() == null ? null : deviceReport.getBoard().getType(); + DeviceReportRespDTO.Firmware firmware = buildFirmwareInfo(type); + response.setFirmware(firmware); + } else { + response.setFirmware(null); + } // 添加WebSocket配置 DeviceReportRespDTO.Websocket websocket = new DeviceReportRespDTO.Websocket(); // 从系统参数获取WebSocket URL,如果未配置则使用默认值 String wsUrl = sysParamsService.getValue(Constant.SERVER_WEBSOCKET, true); if (StringUtils.isBlank(wsUrl) || wsUrl.equals("null")) { - log.error("WebSocket URL is not configured"); + log.error("WebSocket地址未配置,请登录智控台,在参数管理找到【server.websocket】配置"); wsUrl = "ws://xiaozhi.server.com:8000/xiaozhi/v1/"; websocket.setUrl(wsUrl); } else { @@ -141,14 +140,13 @@ public class DeviceServiceImpl extends BaseServiceImpl // 随机选择一个WebSocket URL websocket.setUrl(wsUrls[RandomUtil.randomInt(0, wsUrls.length)]); } else { - log.error("WebSocket URL list is empty"); + log.error("WebSocket地址未配置,请登录智控台,在参数管理找到【server.websocket】配置"); websocket.setUrl("ws://xiaozhi.server.com:8000/xiaozhi/v1/"); } } response.setWebsocket(websocket); - DeviceEntity deviceById = getDeviceById(macAddress); if (deviceById != null) { // 如果设备存在,则更新上次连接时间 deviceById.setLastConnectedAt(new Date()); deviceDao.updateById(deviceById); @@ -301,7 +299,7 @@ public class DeviceServiceImpl extends BaseServiceImpl return code; } - private DeviceReportRespDTO.Firmware buildFirmwareInfo(String type, String macAddress) { + private DeviceReportRespDTO.Firmware buildFirmwareInfo(String type) { if (StringUtils.isBlank(type)) { return null; } @@ -311,14 +309,19 @@ public class DeviceServiceImpl extends BaseServiceImpl String downloadUrl = null; if (ota != null) { - // 获取当前请求的URL - HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()) - .getRequest(); - String requestUrl = request.getRequestURL().toString(); + + String otaUrl = sysParamsService.getValue(Constant.SERVER_OTA, true); + if (StringUtils.isBlank(otaUrl) || otaUrl.equals("null")) { + log.error("OTA地址未配置,请登录智控台,在参数管理找到【server.ota】配置"); + // 尝试从请求中获取 + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()) + .getRequest(); + otaUrl = request.getRequestURL().toString(); + } // 将URL中的/ota/替换为/otaMag/download/ String uuid = UUID.randomUUID().toString(); redisUtils.set(RedisKeys.getOtaIdKey(uuid), ota.getId()); - downloadUrl = requestUrl.replace("/ota/", "/otaMag/download/") + uuid; + downloadUrl = otaUrl.replace("/ota/", "/otaMag/download/") + uuid; } firmware.setVersion(ota == null ? null : ota.getVersion()); diff --git a/main/manager-api/src/main/java/xiaozhi/modules/sys/controller/SysParamsController.java b/main/manager-api/src/main/java/xiaozhi/modules/sys/controller/SysParamsController.java index 157eb94e..9b80c76c 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/sys/controller/SysParamsController.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/sys/controller/SysParamsController.java @@ -4,6 +4,8 @@ import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @@ -12,6 +14,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.RestTemplate; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -47,6 +50,7 @@ import xiaozhi.modules.sys.utils.WebSocketValidator; public class SysParamsController { private final SysParamsService sysParamsService; private final ConfigService configService; + private final RestTemplate restTemplate; @GetMapping("page") @Operation(summary = "分页") @@ -97,6 +101,9 @@ public class SysParamsController { // 验证WebSocket地址列表 validateWebSocketUrls(dto.getParamCode(), dto.getParamValue()); + // 验证OTA地址 + validateOtaUrl(dto.getParamCode(), dto.getParamValue()); + sysParamsService.update(dto); configService.getConfig(false); return new Result(); @@ -118,6 +125,11 @@ public class SysParamsController { } for (String url : wsUrls) { if (StringUtils.isNotBlank(url)) { + // 检查是否包含localhost或127.0.0.1 + if (url.contains("localhost") || url.contains("127.0.0.1")) { + throw new RenException("WebSocket地址不能使用localhost或127.0.0.1"); + } + // 验证WebSocket地址格式 if (!WebSocketValidator.validateUrlFormat(url)) { throw new RenException("WebSocket地址格式不正确: " + url); @@ -131,6 +143,46 @@ public class SysParamsController { } } + /** + * 验证OTA地址 + */ + private void validateOtaUrl(String paramCode, String url) { + if (!paramCode.equals(Constant.SERVER_OTA)) { + return; + } + if (StringUtils.isBlank(url) || url.equals("null")) { + throw new RenException("OTA地址不能为空"); + } + + // 检查是否包含localhost或127.0.0.1 + if (url.contains("localhost") || url.contains("127.0.0.1")) { + throw new RenException("OTA地址不能使用localhost或127.0.0.1"); + } + + // 验证URL格式 + if (!url.toLowerCase().startsWith("http")) { + throw new RenException("OTA地址必须以http或https开头"); + } + if (!url.endsWith("/ota/")) { + throw new RenException("OTA地址必须以/ota/结尾"); + } + + try { + // 发送GET请求 + ResponseEntity response = restTemplate.getForEntity(url, String.class); + if (response.getStatusCode() != HttpStatus.OK) { + throw new RenException("OTA接口访问失败,状态码:" + response.getStatusCode()); + } + // 检查响应内容是否包含OTA相关信息 + String body = response.getBody(); + if (body == null || !body.contains("OTA")) { + throw new RenException("OTA接口返回内容格式不正确,可能不是一个真实的OTA接口"); + } + } catch (Exception e) { + throw new RenException("OTA接口验证失败:" + e.getMessage()); + } + } + @PostMapping("/delete") @Operation(summary = "删除") @LogOperation("删除") diff --git a/main/manager-api/src/main/resources/db/changelog/202504221646.sql b/main/manager-api/src/main/resources/db/changelog/202504221646.sql deleted file mode 100644 index 5905f672..00000000 --- a/main/manager-api/src/main/resources/db/changelog/202504221646.sql +++ /dev/null @@ -1,6 +0,0 @@ --- 删除server.ip和server.port,改成在xiaozhi-server中配置,方便运行多个websocket -delete from `sys_params` where id = 100; -delete from `sys_params` where id = 101; - -INSERT INTO `sys_params` (id, param_code, param_value, value_type, param_type, remark) VALUES (106, 'server.websocket', 'null', 'string', 1, 'websocket地址,多个用;分隔'); - diff --git a/main/manager-api/src/main/resources/db/changelog/202504180758.sql b/main/manager-api/src/main/resources/db/changelog/202504251421.sql similarity index 64% rename from main/manager-api/src/main/resources/db/changelog/202504180758.sql rename to main/manager-api/src/main/resources/db/changelog/202504251421.sql index 160a5f25..ceb9c961 100644 --- a/main/manager-api/src/main/resources/db/changelog/202504180758.sql +++ b/main/manager-api/src/main/resources/db/changelog/202504251421.sql @@ -1,8 +1,9 @@ --- 本文件用于初始化固件信息表,无需手动执行,在项目启动时会自动执行 --- ------------------------------------------------------- --- 初始化固件信息表 -drop table if exists `ai_ota`; -CREATE TABLE `ai_ota` ( +-- 增加server.ota,用于配置ota地址 +delete from `sys_params` where id = 107; +INSERT INTO `sys_params` (id, param_code, param_value, value_type, param_type, remark) VALUES (107, 'server.ota', 'null', 'string', 1, 'ota地址'); + +-- 增加固件信息表 +CREATE TABLE IF NOT EXISTS `ai_ota` ( `id` varchar(32) NOT NULL COMMENT 'ID', `firmware_name` varchar(100) DEFAULT NULL COMMENT '固件名称', `type` varchar(50) DEFAULT NULL COMMENT '固件类型', @@ -16,4 +17,6 @@ CREATE TABLE `ai_ota` ( `creator` bigint DEFAULT NULL COMMENT '创建者', `create_date` datetime DEFAULT NULL COMMENT '创建时间', PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='固件信息表'; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='固件信息表'; + +update ai_device set auto_update = 1; diff --git a/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml b/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml index 7186e013..5fc15f92 100755 --- a/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml @@ -58,13 +58,6 @@ databaseChangeLog: - sqlFile: encoding: utf8 path: classpath:db/changelog/202504181536.sql - - changeSet: - id: 202504180758 - author: jiangkunyin - changes: - - sqlFile: - encoding: utf8 - path: classpath:db/changelog/202504180758.sql - changeSet: id: 202504221135 author: John @@ -72,13 +65,6 @@ databaseChangeLog: - sqlFile: encoding: utf8 path: classpath:db/changelog/202504221135.sql - - changeSet: - id: 202504221646 - author: John - changes: - - sqlFile: - encoding: utf8 - path: classpath:db/changelog/202504221646.sql - changeSet: id: 202504221555 author: John @@ -86,3 +72,10 @@ databaseChangeLog: - sqlFile: encoding: utf8 path: classpath:db/changelog/202504221555.sql + - changeSet: + id: 202504251421 + author: jiangkunyin + changes: + - sqlFile: + encoding: utf8 + path: classpath:db/changelog/202504251421.sql \ No newline at end of file diff --git a/main/manager-web/src/apis/module/device.js b/main/manager-web/src/apis/module/device.js index a62db3b0..53738bc6 100644 --- a/main/manager-web/src/apis/module/device.js +++ b/main/manager-web/src/apis/module/device.js @@ -51,4 +51,20 @@ export default { }); }).send(); }, + enableOtaUpgrade(id, status, callback) { + RequestService.sendRequest() + .url(`${getServiceUrl()}/device/enableOta/${id}/${status}`) + .method('PUT') + .success((res) => { + RequestService.clearRequestTime() + callback(res) + }) + .fail((err) => { + console.error('更新OTA状态失败:', err) + this.$message.error(err.msg || '更新OTA状态失败') + RequestService.reAjaxFun(() => { + this.enableOtaUpgrade(id, status, callback) + }) + }).send() + }, } \ No newline at end of file diff --git a/main/manager-web/src/views/DeviceManagement.vue b/main/manager-web/src/views/DeviceManagement.vue index 662287a3..578469bc 100644 --- a/main/manager-web/src/views/DeviceManagement.vue +++ b/main/manager-web/src/views/DeviceManagement.vue @@ -15,15 +15,9 @@
- + - + @@ -53,8 +47,8 @@ @@ -326,6 +320,16 @@ export default { const firmwareType = FIRMWARE_TYPES.find(item => item.key === type); return firmwareType ? firmwareType.name : type; }, + handleOtaSwitchChange(row) { + Api.device.enableOtaUpgrade(row.device_id, row.otaSwitch ? 1 : 0, ({ data }) => { + if (data.code === 0) { + this.$message.success(row.otaSwitch ? '已设置成自动升级' : '已关闭自动升级') + } else { + row.otaSwitch = !row.otaSwitch + this.$message.error(data.msg || '操作失败') + } + }) + }, } }; @@ -472,12 +476,13 @@ export default { flex: 1; overflow: hidden; } - ::v-deep .el-card__body { - padding: 15px; - display: flex; - flex-direction: column; - flex: 1; - overflow: hidden; + +::v-deep .el-card__body { + padding: 15px; + display: flex; + flex-direction: column; + flex: 1; + overflow: hidden; } .table_bottom { @@ -691,5 +696,4 @@ export default { ::v-deep .el-table::before { display: none !important; } -