mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-22 23:23:55 +08:00
feature:OTA能力完善
This commit is contained in:
+36
-18
@@ -9,6 +9,7 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.beanutils.BeanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import xiaozhi.common.controller.BaseController;
|
||||
import xiaozhi.common.redis.RedisUtils;
|
||||
@@ -48,21 +49,22 @@ public class UserAgentController extends BaseController {
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "添加智能体")
|
||||
@RequiresPermissions("sys:role:normal")
|
||||
public Result<Agent> addAgent(@RequestBody Agent agent) {
|
||||
UserDetail user = SecurityUser.getUser();
|
||||
if(StringUtils.isBlank(agent.getAgentName())){
|
||||
if (StringUtils.isBlank(agent.getAgentName())) {
|
||||
log.error("智能体名称不能为空");
|
||||
}
|
||||
Agent oldAgent = agentService.getOne(new QueryWrapper<Agent>().eq("agent_name", agent.getAgentName()));
|
||||
if(ObjectUtils.isNull(oldAgent)){
|
||||
if (ObjectUtils.isNull(oldAgent)) {
|
||||
AgentTemplate agentTemplate = agentTemplateService.getOne(new QueryWrapper<AgentTemplate>().eq("is_default", 1));
|
||||
if(ObjectUtils.isNull(agentTemplate)){
|
||||
if (ObjectUtils.isNull(agentTemplate)) {
|
||||
|
||||
}else{
|
||||
} else {
|
||||
try {
|
||||
oldAgent = new Agent();
|
||||
BeanUtils.copyProperties(oldAgent, agentTemplate);
|
||||
oldAgent.setId(UUID.randomUUID().toString().replace("-",""));
|
||||
oldAgent.setId(UUID.randomUUID().toString().replace("-", ""));
|
||||
oldAgent.setAgentName(agent.getAgentName());
|
||||
oldAgent.setUserId(user.getId());
|
||||
oldAgent.setCreator(user.getId());
|
||||
@@ -72,17 +74,33 @@ public class UserAgentController extends BaseController {
|
||||
log.error("对象赋值异常", e);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
} else {
|
||||
|
||||
}
|
||||
return new Result<Agent>().ok(agent);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{agentId}")
|
||||
@Operation(summary = "删除智能体")
|
||||
@RequiresPermissions("sys:role:normal")
|
||||
public Result<Agent> delAgent(@PathVariable String agentId) {
|
||||
UserDetail user = SecurityUser.getUser();
|
||||
if (StringUtils.isBlank(agentId)) {
|
||||
log.error("智能体ID不能为空");
|
||||
}
|
||||
boolean bool = agentService.removeById(agentId);
|
||||
if (!bool) {
|
||||
return new Result<Agent>().error("删除失败");
|
||||
}
|
||||
return new Result<Agent>().ok(null);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@Operation(summary = "智能体列表")
|
||||
@RequiresPermissions("sys:role:normal")
|
||||
public Result<List<AgentVO>> agentList() {
|
||||
UserDetail user = SecurityUser.getUser();
|
||||
List<Agent> agents = agentService.list(new QueryWrapper<Agent>().eq("user_id",user.getId()));
|
||||
List<Agent> agents = agentService.list(new QueryWrapper<Agent>().eq("user_id", user.getId()));
|
||||
List<AgentVO> list = new ArrayList<>();
|
||||
this.convertAgetVOList(list, agents);
|
||||
return new Result<List<AgentVO>>().ok(list);
|
||||
@@ -90,19 +108,18 @@ public class UserAgentController extends BaseController {
|
||||
|
||||
@GetMapping("/loadAgentConfig/{deviceId}")
|
||||
@Operation(summary = "下载智能体配置")
|
||||
// public Result<AgentConfigVO> loadAgentConfig(@PathVariable String deviceId){
|
||||
public Result<JSONObject> loadAgentConfig(@PathVariable String deviceId){
|
||||
public Result<JSONObject> loadAgentConfig(@PathVariable String deviceId) {
|
||||
Device device = deviceService.getOne(new QueryWrapper<Device>().eq("mac_address", deviceId.toUpperCase()));
|
||||
if(ObjectUtils.isNull(device)){
|
||||
if (ObjectUtils.isNull(device)) {
|
||||
return new Result<JSONObject>().error("设备不存在");
|
||||
}
|
||||
Agent agent = agentService.getOne(new QueryWrapper<Agent>().eq("id", device.getAgentId()));
|
||||
if(ObjectUtils.isNull(agent)){
|
||||
if (ObjectUtils.isNull(agent)) {
|
||||
return new Result<JSONObject>().error("智能体不存在");
|
||||
}
|
||||
AgentConfigVO agentConfigVO = new AgentConfigVO();
|
||||
// return new Result<AgentConfigVO>().ok(agentConfigVO);
|
||||
String json = "{\n" +
|
||||
String json = "{\n" +
|
||||
" \"ASR\": {\n" +
|
||||
" \"FunASR\": {\n" +
|
||||
" \"model_dir\": \"models/SenseVoiceSmall\",\n" +
|
||||
@@ -160,9 +177,9 @@ public class UserAgentController extends BaseController {
|
||||
* @param agentVOList 转换后的AgentVO对象列表
|
||||
* @param agentList 原始的Agent对象列表
|
||||
*/
|
||||
private void convertAgetVOList(List<AgentVO> agentVOList, List<Agent> agentList){
|
||||
private void convertAgetVOList(List<AgentVO> agentVOList, List<Agent> agentList) {
|
||||
// 遍历Agent对象列表
|
||||
for(Agent agent : agentList) {
|
||||
for (Agent agent : agentList) {
|
||||
// 创建一个新的AgentVO对象
|
||||
AgentVO agentVO = new AgentVO();
|
||||
// 将当前Agent对象的属性值转换并设置到AgentVO对象中
|
||||
@@ -171,17 +188,18 @@ public class UserAgentController extends BaseController {
|
||||
agentVOList.add(agentVO);
|
||||
}
|
||||
}
|
||||
private void convertAgentVO(AgentVO agentVO, Agent agent){
|
||||
|
||||
private void convertAgentVO(AgentVO agentVO, Agent agent) {
|
||||
try {
|
||||
BeanUtils.copyProperties(agentVO, agent);
|
||||
agentVO.setTtsModelName("未知");
|
||||
TtsVoice ttsVoice = ttsVoiceService.getOne(new QueryWrapper<TtsVoice>().eq("id", agent.getTtsVoiceId()));
|
||||
if(ObjectUtils.isNotNull(ttsVoice)){
|
||||
if (ObjectUtils.isNotNull(ttsVoice)) {
|
||||
agentVO.setTtsModelName(ttsVoice.getName());
|
||||
}
|
||||
agentVO.setLlmModelName("未知");
|
||||
ModelConfig modelConfig = modelConfigService.getOne(new QueryWrapper<ModelConfig>().eq("id", agent.getLlmModelId()));
|
||||
if(ObjectUtils.isNotNull(modelConfig)){
|
||||
if (ObjectUtils.isNotNull(modelConfig)) {
|
||||
agentVO.setLlmModelName(modelConfig.getModelName());
|
||||
}
|
||||
agentVO.setLastConnectedAt("今天");
|
||||
@@ -189,7 +207,7 @@ public class UserAgentController extends BaseController {
|
||||
long deviceCount = deviceService.count(new QueryWrapper<Device>().eq("agent_id", agent.getId()));
|
||||
agentVO.setDeviceCount(deviceCount);
|
||||
} catch (Exception e) {
|
||||
log.error("[convertAgentVO]对象转换报错",e);
|
||||
log.error("[convertAgentVO]对象转换报错", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+48
-1
@@ -2,6 +2,7 @@ package xiaozhi.modules.device.controller;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
@@ -9,6 +10,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import xiaozhi.common.controller.BaseController;
|
||||
import xiaozhi.common.redis.RedisUtils;
|
||||
@@ -20,6 +22,7 @@ import xiaozhi.modules.device.constant.DeviceConstant;
|
||||
import xiaozhi.modules.device.domain.Device;
|
||||
import xiaozhi.modules.device.service.DeviceService;
|
||||
import xiaozhi.modules.device.vo.DeviceCodeVO;
|
||||
import xiaozhi.modules.ota.domain.Ota;
|
||||
import xiaozhi.modules.security.user.SecurityUser;
|
||||
|
||||
import java.util.Date;
|
||||
@@ -36,6 +39,7 @@ public class UserDeviceController extends BaseController {
|
||||
|
||||
@GetMapping("/bind/{agentId}")
|
||||
@Operation(summary = "已绑定设备列表")
|
||||
@RequiresPermissions("sys:role:normal")
|
||||
public Result<Page<Device>> bindDeviceList(@PathVariable String agentId, @RequestParam Integer pageNo, @RequestParam Integer pageSize) {
|
||||
if (StringUtils.isBlank(agentId)) {
|
||||
log.error("智能体ID不能为空");
|
||||
@@ -56,6 +60,7 @@ public class UserDeviceController extends BaseController {
|
||||
|
||||
@PostMapping("/bind/{agentId}")
|
||||
@Operation(summary = "绑定设备")
|
||||
@RequiresPermissions("sys:role:normal")
|
||||
public Result<Device> bindDevice(@PathVariable String agentId, @RequestBody DeviceCodeVO deviceCodeVO) {
|
||||
if (ObjectUtils.isNull(deviceCodeVO) || StringUtils.isBlank(deviceCodeVO.getDeviceCode())) {
|
||||
log.error("授权码不能为空");
|
||||
@@ -112,16 +117,58 @@ public class UserDeviceController extends BaseController {
|
||||
|
||||
@PutMapping("/unbind/{deviceId}")
|
||||
@Operation(summary = "解绑设备")
|
||||
@RequiresPermissions("sys:role:normal")
|
||||
public Result<Device> bindDevice(@PathVariable String deviceId) {
|
||||
if (StringUtils.isBlank(deviceId)) {
|
||||
log.error("设备ID不能为空");
|
||||
return new Result().error("设备ID不能为空");
|
||||
}
|
||||
UserDetail user = SecurityUser.getUser();
|
||||
boolean bool = deviceService.removeById(deviceId);
|
||||
if (!bool) {
|
||||
return new Result().error("解绑失败");
|
||||
}
|
||||
return new Result<Device>().ok(null);
|
||||
}
|
||||
|
||||
@PostMapping("/autoUpdate/{deviceId}")
|
||||
@Operation(summary = "切换设备OTA升级状态")
|
||||
@RequiresPermissions("sys:role:normal")
|
||||
public Result<Device> toggleAutoUpdate(@PathVariable String deviceId, @RequestBody Device device) {
|
||||
if (StringUtils.isBlank(deviceId)) {
|
||||
log.error("设备ID不能为空");
|
||||
return new Result().error("设备ID不能为空");
|
||||
}
|
||||
UserDetail user = SecurityUser.getUser();
|
||||
boolean bool = deviceService.update(
|
||||
new UpdateWrapper<Device>().eq("id", deviceId)
|
||||
.set("auto_update", device.getAutoUpdate())
|
||||
.set("updater", user.getId())
|
||||
.set("update_date", new Date())
|
||||
);
|
||||
if (!bool) {
|
||||
return new Result<Device>().error("切换设备OTA升级状态失败");
|
||||
}
|
||||
return new Result<Device>().ok(null);
|
||||
}
|
||||
|
||||
@PostMapping("/alias/{deviceId}")
|
||||
@Operation(summary = "设置设备别名")
|
||||
@RequiresPermissions("sys:role:normal")
|
||||
public Result<Device> setAlias(@PathVariable String deviceId, @RequestBody Device device) {
|
||||
if (StringUtils.isBlank(deviceId)) {
|
||||
log.error("设备ID不能为空");
|
||||
return new Result().error("设备ID不能为空");
|
||||
}
|
||||
UserDetail user = SecurityUser.getUser();
|
||||
boolean bool = deviceService.update(
|
||||
new UpdateWrapper<Device>().eq("id", deviceId)
|
||||
.set("alias", device.getAlias())
|
||||
.set("updater", user.getId())
|
||||
.set("update_date", new Date())
|
||||
);
|
||||
if (!bool) {
|
||||
return new Result<Device>().error("设置设备别名失败");
|
||||
}
|
||||
return new Result<Device>().ok(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package xiaozhi.modules.model.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 模型配置表
|
||||
* @TableName ai_model_provider
|
||||
*/
|
||||
@TableName(value ="ai_model_provider")
|
||||
@Data
|
||||
public class ModelProvider implements Serializable {
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@TableId
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 模型类型(Memory/ASR/VAD/LLM/TTS)
|
||||
*/
|
||||
private String modelType;
|
||||
|
||||
/**
|
||||
* 供应器类型
|
||||
*/
|
||||
private String providerCode;
|
||||
|
||||
/**
|
||||
* 供应器名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 供应器字段列表(JSON格式)
|
||||
*/
|
||||
private Object fields;
|
||||
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
private Integer sort;
|
||||
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
private Long creator;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createDate;
|
||||
|
||||
/**
|
||||
* 更新者
|
||||
*/
|
||||
private Long updater;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateDate;
|
||||
|
||||
@TableField(exist = false)
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package xiaozhi.modules.model.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import xiaozhi.modules.model.domain.ModelProvider;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* @author chenerlei
|
||||
* @description 针对表【ai_model_provider(模型配置表)】的数据库操作Mapper
|
||||
* @createDate 2025-03-24 18:24:13
|
||||
* @Entity xiaozhi.modules.model.domain.ModelProvider
|
||||
*/
|
||||
@Mapper
|
||||
public interface ModelProviderMapper extends BaseMapper<ModelProvider> {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package xiaozhi.modules.model.service;
|
||||
|
||||
import xiaozhi.modules.model.domain.ModelProvider;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* @author chenerlei
|
||||
* @description 针对表【ai_model_provider(模型配置表)】的数据库操作Service
|
||||
* @createDate 2025-03-24 18:24:13
|
||||
*/
|
||||
public interface ModelProviderService extends IService<ModelProvider> {
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package xiaozhi.modules.model.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import xiaozhi.modules.model.domain.ModelProvider;
|
||||
import xiaozhi.modules.model.service.ModelProviderService;
|
||||
import xiaozhi.modules.model.mapper.ModelProviderMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author chenerlei
|
||||
* @description 针对表【ai_model_provider(模型配置表)】的数据库操作Service实现
|
||||
* @createDate 2025-03-24 18:24:13
|
||||
*/
|
||||
@Service
|
||||
public class ModelProviderServiceImpl extends ServiceImpl<ModelProviderMapper, ModelProvider>
|
||||
implements ModelProviderService{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
+76
-9
@@ -1,26 +1,33 @@
|
||||
package xiaozhi.modules.device.controller;
|
||||
package xiaozhi.modules.ota.controller;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import xiaozhi.common.controller.BaseController;
|
||||
import xiaozhi.common.redis.RedisUtils;
|
||||
import xiaozhi.common.user.UserDetail;
|
||||
import xiaozhi.common.utils.Result;
|
||||
import xiaozhi.modules.agent.domain.Agent;
|
||||
import xiaozhi.modules.device.constant.DeviceConstant;
|
||||
import xiaozhi.modules.device.domain.Device;
|
||||
import xiaozhi.modules.device.service.DeviceService;
|
||||
import xiaozhi.modules.device.utils.CodeGeneratorUtil;
|
||||
import xiaozhi.modules.device.vo.DeviceOtaVO;
|
||||
import xiaozhi.modules.sys.service.SysParamsService;
|
||||
import xiaozhi.modules.ota.domain.Ota;
|
||||
import xiaozhi.modules.ota.service.OtaService;
|
||||
import xiaozhi.modules.security.user.SecurityUser;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@@ -31,10 +38,9 @@ import java.util.Date;
|
||||
@RequestMapping("/ota")
|
||||
public class OtaController extends BaseController {
|
||||
private final DeviceService deviceService;
|
||||
private final SysParamsService sysParamsService;
|
||||
private final OtaService otaService;
|
||||
@Resource
|
||||
private RedisUtils redisUtils;
|
||||
private final String OTA_PARAM_CODE = "OTA";
|
||||
|
||||
@CrossOrigin(originPatterns = "*", methods = {RequestMethod.GET, RequestMethod.POST})
|
||||
@RequestMapping(path = "/", method = {RequestMethod.POST, RequestMethod.GET}, produces = "application/json")
|
||||
@@ -66,16 +72,77 @@ public class OtaController extends BaseController {
|
||||
|
||||
if (ObjectUtils.isNull(device) || device.getAutoUpdate() == 1) {
|
||||
//{"version":"1.0.0","url":"http://https://youxlife.oss-cn-zhangjiakou.aliyuncs.com/v1.4.5.bin"}
|
||||
String value = sysParamsService.getValue(OTA_PARAM_CODE);
|
||||
if (StringUtils.isBlank(value)) {
|
||||
String board = ObjectUtils.isNull(device)?headers.getFirst("user-agent").split("/")[0]:device.getBoard();
|
||||
Ota ota = otaService.getOne(new UpdateWrapper<Ota>().eq("board", board).eq("is_enabled", 1));
|
||||
if (ObjectUtils.isNull(ota)) {
|
||||
log.warn("OTA升级信息未配置");
|
||||
} else {
|
||||
JSONObject object = new JSONObject(value);
|
||||
otaVO.setFirmware(new DeviceOtaVO.Firmware(object.getStr("version"), object.getStr("url")));
|
||||
otaVO.setFirmware(new DeviceOtaVO.Firmware(ota.getAppVersion(), ota.getUrl()));
|
||||
}
|
||||
}
|
||||
|
||||
otaVO.setServer_time(new DeviceOtaVO.ServerTime(new Date().getTime(), 8 * 60));
|
||||
return JSONUtil.toJsonStr(otaVO);
|
||||
}
|
||||
|
||||
@GetMapping("/sys/getOtalist")
|
||||
@Operation(summary = "设备OTA列表")
|
||||
@RequiresPermissions("sys:role:superAdmin")
|
||||
public Result<Page<Ota>> getOtalist(@RequestParam Integer pageNo, @RequestParam Integer pageSize) {
|
||||
UserDetail user = SecurityUser.getUser();
|
||||
Page page = new Page<Ota>(pageNo, pageSize);
|
||||
page = otaService.page(page);
|
||||
return new Result<Page<Ota>>().ok(page);
|
||||
}
|
||||
|
||||
@PostMapping("/sys/save")
|
||||
@Operation(summary = "添加设备OTA")
|
||||
@RequiresPermissions("sys:role:superAdmin")
|
||||
public Result<Ota> save(@RequestBody Ota ota) {
|
||||
UserDetail user = SecurityUser.getUser();
|
||||
ota.setCreator(user.getId());
|
||||
ota.setCreateDate(new Date());
|
||||
boolean bool = otaService.save(ota);
|
||||
if (!bool) {
|
||||
return new Result().error("设备OTA添加失败");
|
||||
}
|
||||
return new Result<Ota>().ok(null);
|
||||
}
|
||||
|
||||
@PostMapping("/sys/update")
|
||||
@Operation(summary = "更新设备OTA")
|
||||
@RequiresPermissions("sys:role:superAdmin")
|
||||
public Result<Ota> update(@RequestBody Ota ota) {
|
||||
UserDetail user = SecurityUser.getUser();
|
||||
boolean bool = otaService.update(
|
||||
new UpdateWrapper<Ota>().eq("id", ota.getId())
|
||||
.set("board", ota.getBoard().trim().toLowerCase())
|
||||
.set("app_version", ota.getAppVersion())
|
||||
.set("url", ota.getUrl())
|
||||
.set("is_enabled", ota.getIsEnabled())
|
||||
.set("updater", user.getId())
|
||||
.set("update_date", new Date())
|
||||
);
|
||||
if (!bool) {
|
||||
return new Result().error("设备OTA更新失败");
|
||||
}
|
||||
return new Result<Ota>().ok(null);
|
||||
}
|
||||
|
||||
@PostMapping("/sys/toggleEnabled")
|
||||
@Operation(summary = "切换设备OTA可用状态")
|
||||
@RequiresPermissions("sys:role:superAdmin")
|
||||
public Result<Ota> toggleEnabled(@RequestBody Ota ota) {
|
||||
UserDetail user = SecurityUser.getUser();
|
||||
boolean bool = otaService.update(
|
||||
new UpdateWrapper<Ota>().eq("id", ota.getId())
|
||||
.set("is_enabled", ota.getIsEnabled())
|
||||
.set("updater", user.getId())
|
||||
.set("update_date", new Date())
|
||||
);
|
||||
if (!bool) {
|
||||
return new Result().error("切换设备OTA可用状态失败");
|
||||
}
|
||||
return new Result<Ota>().ok(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package xiaozhi.modules.ota.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* OTA升级信息表
|
||||
* @TableName ai_ota
|
||||
*/
|
||||
@TableName(value ="ai_ota")
|
||||
@Data
|
||||
public class Ota implements Serializable {
|
||||
/**
|
||||
* 记录唯一标识
|
||||
*/
|
||||
@TableId
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 设备硬件型号
|
||||
*/
|
||||
private String board;
|
||||
|
||||
/**
|
||||
* 固件版本号
|
||||
*/
|
||||
private String appVersion;
|
||||
|
||||
/**
|
||||
* 下载地址
|
||||
*/
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* 是否启用
|
||||
*/
|
||||
private Integer isEnabled;
|
||||
|
||||
/**
|
||||
* 创建者
|
||||
*/
|
||||
private Long creator;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createDate;
|
||||
|
||||
/**
|
||||
* 更新者
|
||||
*/
|
||||
private Long updater;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateDate;
|
||||
|
||||
@TableField(exist = false)
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package xiaozhi.modules.ota.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import xiaozhi.modules.ota.domain.Ota;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* @author chenerlei
|
||||
* @description 针对表【ai_ota(OTA升级信息表)】的数据库操作Mapper
|
||||
* @createDate 2025-03-24 18:25:14
|
||||
* @Entity xiaozhi.modules.ota.domain.Ota
|
||||
*/
|
||||
@Mapper
|
||||
public interface OtaMapper extends BaseMapper<Ota> {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package xiaozhi.modules.ota.service;
|
||||
|
||||
import xiaozhi.modules.ota.domain.Ota;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* @author chenerlei
|
||||
* @description 针对表【ai_ota(OTA升级信息表)】的数据库操作Service
|
||||
* @createDate 2025-03-24 18:25:14
|
||||
*/
|
||||
public interface OtaService extends IService<Ota> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package xiaozhi.modules.ota.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import xiaozhi.modules.ota.domain.Ota;
|
||||
import xiaozhi.modules.ota.service.OtaService;
|
||||
import xiaozhi.modules.ota.mapper.OtaMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author chenerlei
|
||||
* @description 针对表【ai_ota(OTA升级信息表)】的数据库操作Service实现
|
||||
* @createDate 2025-03-24 18:25:14
|
||||
*/
|
||||
@Service
|
||||
public class OtaServiceImpl extends ServiceImpl<OtaMapper, Ota>
|
||||
implements OtaService{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -42,21 +42,22 @@ spring:
|
||||
wall:
|
||||
config:
|
||||
multi-statement-allow: true
|
||||
redis:
|
||||
host: localhost # Redis服务器地址
|
||||
port: 6379 # Redis服务器连接端口
|
||||
password: # Redis服务器连接密码(默认为空)
|
||||
database: 0 # Redis数据库索引(默认为0)
|
||||
# jedis:
|
||||
# pool:
|
||||
# max-active: 8 # 连接池最大连接数(使用负值表示没有限制)
|
||||
# max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
|
||||
# max-idle: 8 # 连接池中的最大空闲连接
|
||||
# min-idle: 0 # 连接池中的最小空闲连接
|
||||
timeout: 10000ms # 连接超时时间(毫秒)
|
||||
lettuce:
|
||||
pool:
|
||||
max-active: 8 # 连接池最大连接数(使用负值表示没有限制)
|
||||
max-idle: 8 # 连接池中的最大空闲连接
|
||||
min-idle: 0 # 连接池中的最小空闲连接
|
||||
shutdown-timeout: 100ms # 客户端优雅关闭的等待时间
|
||||
data:
|
||||
redis:
|
||||
host: localhost # Redis服务器地址
|
||||
port: 6379 # Redis服务器连接端口
|
||||
password: # Redis服务器连接密码(默认为空)
|
||||
database: 0 # Redis数据库索引(默认为0)
|
||||
# jedis:
|
||||
# pool:
|
||||
# max-active: 8 # 连接池最大连接数(使用负值表示没有限制)
|
||||
# max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
|
||||
# max-idle: 8 # 连接池中的最大空闲连接
|
||||
# min-idle: 0 # 连接池中的最小空闲连接
|
||||
timeout: 10000ms # 连接超时时间(毫秒)
|
||||
lettuce:
|
||||
pool:
|
||||
max-active: 8 # 连接池最大连接数(使用负值表示没有限制)
|
||||
max-idle: 8 # 连接池中的最大空闲连接
|
||||
min-idle: 0 # 连接池中的最小空闲连接
|
||||
shutdown-timeout: 100ms # 客户端优雅关闭的等待时间
|
||||
@@ -0,0 +1,15 @@
|
||||
-- OTA升级信息表
|
||||
DROP TABLE IF EXISTS `ai_ota`;
|
||||
CREATE TABLE `ai_ota` (
|
||||
`id` VARCHAR(32) NOT NULL COMMENT '记录唯一标识',
|
||||
`board` VARCHAR(50) COMMENT '设备硬件型号',
|
||||
`app_version` VARCHAR(20) COMMENT '固件版本号',
|
||||
`url` VARCHAR(500) COMMENT '下载地址',
|
||||
`is_enabled` TINYINT(1) DEFAULT 0 COMMENT '是否启用',
|
||||
`creator` BIGINT COMMENT '创建者',
|
||||
`create_date` DATETIME COMMENT '创建时间',
|
||||
`updater` BIGINT COMMENT '更新者',
|
||||
`update_date` DATETIME COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uni_ai_ota_board` (`board`) COMMENT '设备型号唯一索引,用于快速查找升级信息'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='OTA升级信息表';
|
||||
@@ -15,4 +15,11 @@ databaseChangeLog:
|
||||
changes:
|
||||
- sqlFile:
|
||||
encoding: utf8
|
||||
path: classpath:db/changelog/202503141346.sql
|
||||
path: classpath:db/changelog/202503141346.sql
|
||||
- changeSet:
|
||||
id: 202503241020
|
||||
author: dreamchen
|
||||
changes:
|
||||
- sqlFile:
|
||||
encoding: utf8
|
||||
path: classpath:db/changelog/202503241020.sql
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="xiaozhi.modules.model.mapper.ModelProviderMapper">
|
||||
|
||||
<resultMap id="BaseResultMap" type="xiaozhi.modules.model.domain.ModelProvider">
|
||||
<id property="id" column="id" />
|
||||
<result property="modelType" column="model_type" />
|
||||
<result property="providerCode" column="provider_code" />
|
||||
<result property="name" column="name" />
|
||||
<result property="fields" column="fields" />
|
||||
<result property="sort" column="sort" />
|
||||
<result property="creator" column="creator" />
|
||||
<result property="createDate" column="create_date" />
|
||||
<result property="updater" column="updater" />
|
||||
<result property="updateDate" column="update_date" />
|
||||
</resultMap>
|
||||
|
||||
<sql id="Base_Column_List">
|
||||
id,model_type,provider_code,name,fields,sort,
|
||||
creator,create_date,updater,update_date
|
||||
</sql>
|
||||
</mapper>
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="xiaozhi.modules.ota.mapper.OtaMapper">
|
||||
|
||||
<resultMap id="BaseResultMap" type="xiaozhi.modules.ota.domain.Ota">
|
||||
<id property="id" column="id" />
|
||||
<result property="board" column="board" />
|
||||
<result property="appVersion" column="app_version" />
|
||||
<result property="url" column="url" />
|
||||
<result property="isEnabled" column="is_enabled" />
|
||||
<result property="creator" column="creator" />
|
||||
<result property="createDate" column="create_date" />
|
||||
<result property="updater" column="updater" />
|
||||
<result property="updateDate" column="update_date" />
|
||||
</resultMap>
|
||||
|
||||
<sql id="Base_Column_List">
|
||||
id,board,app_version,url,is_enabled,creator,
|
||||
create_date,updater,update_date
|
||||
</sql>
|
||||
</mapper>
|
||||
@@ -2,6 +2,7 @@
|
||||
import agent from './module/agent.js'
|
||||
import device from './module/device.js'
|
||||
import user from './module/user.js'
|
||||
import ota from './module/ota.js'
|
||||
|
||||
/**
|
||||
* 接口地址
|
||||
@@ -11,7 +12,7 @@ import user from './module/user.js'
|
||||
*/
|
||||
// const DEV_API_SERVICE = 'https://m1.apifoxmock.com/m1/5931378-5618560-default'
|
||||
// 8002开发完成完成后使用这个
|
||||
const DEV_API_SERVICE = '/xiaozhi-esp32-api'
|
||||
const DEV_API_SERVICE = '/xiaozhi-esp32-api/api/v1'
|
||||
|
||||
/**
|
||||
* 根据开发环境返回接口url
|
||||
@@ -27,5 +28,6 @@ export default {
|
||||
getServiceUrl,
|
||||
user,
|
||||
agent,
|
||||
device
|
||||
device,
|
||||
ota
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import {getServiceUrl} from '../api'
|
||||
export default {
|
||||
//智能体列表
|
||||
getAgentList(callback) {
|
||||
RequestService.sendRequest().url(`${getServiceUrl()}/api/v1/user/agent`)
|
||||
RequestService.sendRequest().url(`${getServiceUrl()}/user/agent`)
|
||||
.method('GET')
|
||||
.success((res) => {
|
||||
RequestService.clearRequestTime()
|
||||
@@ -18,7 +18,7 @@ export default {
|
||||
//添加智能体
|
||||
addAgent(agentName, callback) {
|
||||
RequestService.sendRequest()
|
||||
.url(`${getServiceUrl()}/api/v1/user/agent`)
|
||||
.url(`${getServiceUrl()}/user/agent`)
|
||||
.method('POST')
|
||||
.data({agentName})
|
||||
.success((res) => {
|
||||
@@ -30,9 +30,9 @@ export default {
|
||||
}).send();
|
||||
},
|
||||
//获取智能体配置
|
||||
getAgentConfig(agent_id, callback) {
|
||||
getAgentConfig(agentId, callback) {
|
||||
RequestService.sendRequest()
|
||||
.url(`${getServiceUrl()}/api/v1/user/agent/${agent_id}`)
|
||||
.url(`${getServiceUrl()}/user/agent/${agentId}`)
|
||||
.method('GET')
|
||||
.success((res) => {
|
||||
RequestService.clearRequestTime();
|
||||
@@ -40,15 +40,15 @@ export default {
|
||||
})
|
||||
.fail((err) => {
|
||||
console.error('获取智能体配置失败:', err);
|
||||
RequestService.reAjaxFun(() => {
|
||||
this.getAgentConfig(agent_id, callback);
|
||||
});
|
||||
// RequestService.reAjaxFun(() => {
|
||||
// this.getAgentConfig(agent_id, callback);
|
||||
// });
|
||||
}).send();
|
||||
},
|
||||
//配置智能体
|
||||
saveAgentConfig(agent_id, configData, callback) {
|
||||
saveAgentConfig(agentId, configData, callback) {
|
||||
RequestService.sendRequest()
|
||||
.url(`${getServiceUrl()}/api/v1/user/agent/${agent_id}`)
|
||||
.url(`${getServiceUrl()}/user/agent/${agentId}`)
|
||||
.method('PUT')
|
||||
.data(configData)
|
||||
.success((res) => {
|
||||
@@ -57,15 +57,15 @@ export default {
|
||||
})
|
||||
.fail((err) => {
|
||||
console.error('保存智能体配置失败:', err);
|
||||
RequestService.reAjaxFun(() => {
|
||||
this.saveAgentConfig(device_id, configData, callback);
|
||||
});
|
||||
// RequestService.reAjaxFun(() => {
|
||||
// this.saveAgentConfig(device_id, configData, callback);
|
||||
// });
|
||||
}).send();
|
||||
},
|
||||
//删除智能体
|
||||
delAgent(agent_id, callback) {
|
||||
delAgent(agentId, callback) {
|
||||
RequestService.sendRequest()
|
||||
.url(`${getServiceUrl()}/api/v1/user/agent/${agent_id}`)
|
||||
.url(`${getServiceUrl()}/user/agent/${agentId}`)
|
||||
.method('DELETE')
|
||||
.success((res) => {
|
||||
RequestService.clearRequestTime();
|
||||
@@ -73,9 +73,9 @@ export default {
|
||||
})
|
||||
.fail((err) => {
|
||||
console.error('删除智能体失败:', err);
|
||||
RequestService.reAjaxFun(() => {
|
||||
this.deleteAgent(agent_id, callback);
|
||||
});
|
||||
// RequestService.reAjaxFun(() => {
|
||||
// this.deleteAgent(agent_id, callback);
|
||||
// });
|
||||
}).send();
|
||||
},
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import {getServiceUrl} from '../api'
|
||||
export default {
|
||||
//设备列表
|
||||
getDeviceList(agent_id, page, callback) {
|
||||
RequestService.sendRequest().url(`${getServiceUrl()}/api/v1/user/agent/device/bind/${agent_id}`)
|
||||
RequestService.sendRequest().url(`${getServiceUrl()}/user/agent/device/bind/${agent_id}`)
|
||||
.method('GET')
|
||||
.data(page)
|
||||
.success((res) => {
|
||||
@@ -19,7 +19,7 @@ export default {
|
||||
//绑定设备
|
||||
bindDevice(agentId, deviceCode, callback) {
|
||||
RequestService.sendRequest()
|
||||
.url(`${getServiceUrl()}/api/v1/user/agent/device/bind/${agentId}`)
|
||||
.url(`${getServiceUrl()}/user/agent/device/bind/${agentId}`)
|
||||
.method('POST')
|
||||
.data({deviceCode})
|
||||
.success((res) => {
|
||||
@@ -28,24 +28,53 @@ export default {
|
||||
})
|
||||
.fail((err) => {
|
||||
console.error('绑定设备失败:', err);
|
||||
RequestService.reAjaxFun(() => {
|
||||
this.addDevice(agentId, deviceCode, callback);
|
||||
});
|
||||
// RequestService.reAjaxFun(() => {
|
||||
// this.addDevice(agentId, deviceCode, callback);
|
||||
// });
|
||||
}).send();
|
||||
},
|
||||
// 解绑设备
|
||||
unbindDevice(deviceId, callback) {
|
||||
RequestService.sendRequest()
|
||||
.url(`${getServiceUrl()}/api/v1/user/agent/device/unbind/${deviceId}`)
|
||||
.url(`${getServiceUrl()}/user/agent/device/unbind/${deviceId}`)
|
||||
.method('PUT')
|
||||
.success((res) => {
|
||||
RequestService.clearRequestTime();
|
||||
callback(res);
|
||||
})
|
||||
.fail(() => {
|
||||
RequestService.reAjaxFun(() => {
|
||||
this.unbindDevice(deviceId, callback);
|
||||
});
|
||||
.fail((err) => {
|
||||
console.error('解绑设备失败:', err);
|
||||
// RequestService.reAjaxFun(() => {
|
||||
// this.unbindDevice(deviceId, callback);
|
||||
// });
|
||||
}).send()
|
||||
},
|
||||
// 切换设备OTA升级状态
|
||||
toggleAutoUpdate(deviceId, autoUpdate, callback) {
|
||||
RequestService.sendRequest()
|
||||
.url(`${getServiceUrl()}/user/agent/device/autoUpdate/${deviceId}`)
|
||||
.method('POST')
|
||||
.data({autoUpdate})
|
||||
.success((res) => {
|
||||
RequestService.clearRequestTime();
|
||||
callback(res);
|
||||
})
|
||||
.fail((err) => {
|
||||
console.error('切换设备OTA升级状态失败:', err);
|
||||
}).send()
|
||||
},
|
||||
// 设置设备别名
|
||||
setAlias(deviceId, alias, callback) {
|
||||
RequestService.sendRequest()
|
||||
.url(`${getServiceUrl()}/user/agent/device/alias/${deviceId}`)
|
||||
.method('POST')
|
||||
.data({alias})
|
||||
.success((res) => {
|
||||
RequestService.clearRequestTime();
|
||||
callback(res);
|
||||
})
|
||||
.fail((err) => {
|
||||
console.error('设置设备别名失败:', err);
|
||||
}).send()
|
||||
},
|
||||
|
||||
|
||||
Executable
+67
@@ -0,0 +1,67 @@
|
||||
import RequestService from '../httpRequest'
|
||||
import {getServiceUrl} from '../api'
|
||||
|
||||
|
||||
export default {
|
||||
//设备OTA列表
|
||||
getOtaList(page, callback) {
|
||||
RequestService.sendRequest().url(`${getServiceUrl()}/ota/sys/getOtalist`)
|
||||
.method('GET')
|
||||
.data(page)
|
||||
.success((res) => {
|
||||
RequestService.clearRequestTime()
|
||||
callback(res)
|
||||
})
|
||||
.fail((err) => {
|
||||
console.error('获取设备OTA列表失败:', err);
|
||||
}).send()
|
||||
},
|
||||
//添加设备OTA
|
||||
saveOta(ota, callback) {
|
||||
RequestService.sendRequest()
|
||||
.url(`${getServiceUrl()}/ota/sys/save`)
|
||||
.method('POST')
|
||||
.data(ota)
|
||||
.success((res) => {
|
||||
RequestService.clearRequestTime();
|
||||
callback(res);
|
||||
})
|
||||
.fail((err) => {
|
||||
console.error('添加设备OTA失败:', err);
|
||||
}).send();
|
||||
},
|
||||
//配置设备OTA
|
||||
updateOta(ota, callback) {
|
||||
RequestService.sendRequest()
|
||||
.url(`${getServiceUrl()}/ota/sys/update`)
|
||||
.method('POST')
|
||||
.data(ota)
|
||||
.success((res) => {
|
||||
RequestService.clearRequestTime();
|
||||
callback(res);
|
||||
})
|
||||
.fail((err) => {
|
||||
console.error('保存设备OTA配置失败:', err);
|
||||
// RequestService.reAjaxFun(() => {
|
||||
// this.saveAgentConfig(device_id, configData, callback);
|
||||
// });
|
||||
}).send();
|
||||
},
|
||||
//切换设备OTA可用状态失败
|
||||
toggleEnabled(ota, callback) {
|
||||
RequestService.sendRequest()
|
||||
.url(`${getServiceUrl()}/ota/sys/toggleEnabled`)
|
||||
.method('POST')
|
||||
.data(ota)
|
||||
.success((res) => {
|
||||
RequestService.clearRequestTime();
|
||||
callback(res);
|
||||
})
|
||||
.fail((err) => {
|
||||
console.error('切换设备OTA可用状态失败:', err);
|
||||
// RequestService.reAjaxFun(() => {
|
||||
// this.deleteAgent(agent_id, callback);
|
||||
// });
|
||||
}).send();
|
||||
},
|
||||
}
|
||||
@@ -5,53 +5,24 @@ import {getServiceUrl} from '../api'
|
||||
export default {
|
||||
// 登录
|
||||
login(loginForm, callback) {
|
||||
RequestService.sendRequest().url(`${getServiceUrl()}/api/v1/user/login`)
|
||||
RequestService.sendRequest().url(`${getServiceUrl()}/user/login`)
|
||||
.method('POST')
|
||||
.data(loginForm)
|
||||
.success((res) => {
|
||||
RequestService.clearRequestTime()
|
||||
callback(res)
|
||||
})
|
||||
.fail(() => {
|
||||
RequestService.reAjaxFun(() => {
|
||||
this.login(loginForm, callback)
|
||||
})
|
||||
.fail((err) => {
|
||||
console.error('登录失败:', err);
|
||||
// RequestService.reAjaxFun(() => {
|
||||
// this.login(loginForm, callback)
|
||||
// })
|
||||
}).send()
|
||||
},
|
||||
// 获取设备信息
|
||||
getHomeList(callback) {
|
||||
RequestService.sendRequest().url(`${getServiceUrl()}/api/v1/user/device/bind`)
|
||||
.method('GET')
|
||||
.success((res) => {
|
||||
RequestService.clearRequestTime()
|
||||
callback(res)
|
||||
})
|
||||
.fail(() => {
|
||||
RequestService.reAjaxFun(() => {
|
||||
this.getUserInfo()
|
||||
})
|
||||
}).send()
|
||||
},
|
||||
// 解绑设备
|
||||
unbindDevice(device_id, callback) {
|
||||
RequestService.sendRequest()
|
||||
.url(`${getServiceUrl()}/api/v1/user/device/unbind/${device_id}`)
|
||||
.method('PUT')
|
||||
.success((res) => {
|
||||
RequestService.clearRequestTime();
|
||||
callback(res);
|
||||
})
|
||||
.fail(() => {
|
||||
RequestService.reAjaxFun(() => {
|
||||
this.unbindDevice(device_id, callback);
|
||||
});
|
||||
}).send()
|
||||
},
|
||||
// 获取验证码
|
||||
}, // 获取验证码
|
||||
getCaptcha(uuid, callback) {
|
||||
|
||||
RequestService.sendRequest()
|
||||
.url(`${getServiceUrl()}/api/v1/user/captcha?uuid=${uuid}`)
|
||||
.url(`${getServiceUrl()}/user/captcha?uuid=${uuid}`)
|
||||
.method('GET')
|
||||
.type('blob')
|
||||
.header({
|
||||
@@ -64,104 +35,57 @@ export default {
|
||||
callback(res);
|
||||
})
|
||||
.fail((err) => { // 添加错误参数
|
||||
|
||||
console.error('获取验证码失败:', err);
|
||||
}).send()
|
||||
},
|
||||
// 注册账号
|
||||
register(registerForm, callback) {
|
||||
RequestService.sendRequest().url(`${getServiceUrl()}/api/v1/user/register`).method('POST')
|
||||
RequestService.sendRequest().url(`${getServiceUrl()}/user/register`).method('POST')
|
||||
.data(registerForm)
|
||||
.success((res) => {
|
||||
RequestService.clearRequestTime()
|
||||
callback(res)
|
||||
})
|
||||
.fail(() => {
|
||||
.fail((err) => {
|
||||
console.error('注册账号失败:', err);
|
||||
}).send()
|
||||
},
|
||||
|
||||
// 保存设备配置
|
||||
saveDeviceConfig(device_id, configData, callback) {
|
||||
RequestService.sendRequest()
|
||||
.url(`${getServiceUrl()}/api/v1/user/configDevice/${device_id}`)
|
||||
.method('PUT')
|
||||
.data(configData)
|
||||
.success((res) => {
|
||||
RequestService.clearRequestTime();
|
||||
callback(res);
|
||||
})
|
||||
.fail((err) => {
|
||||
console.error('保存配置失败:', err);
|
||||
RequestService.reAjaxFun(() => {
|
||||
this.saveDeviceConfig(device_id, configData, callback);
|
||||
});
|
||||
}).send();
|
||||
},
|
||||
// 获取设备配置
|
||||
getDeviceConfig(device_id, callback) {
|
||||
RequestService.sendRequest()
|
||||
.url(`${getServiceUrl()}/api/v1/user/configDevice/${device_id}`)
|
||||
.method('GET')
|
||||
.success((res) => {
|
||||
RequestService.clearRequestTime();
|
||||
callback(res);
|
||||
})
|
||||
.fail((err) => {
|
||||
console.error('获取配置失败:', err);
|
||||
RequestService.reAjaxFun(() => {
|
||||
this.getDeviceConfig(device_id, callback);
|
||||
});
|
||||
}).send();
|
||||
},
|
||||
// 获取所有模型名称
|
||||
getModelNames(callback) {
|
||||
RequestService.sendRequest()
|
||||
.url(`${getServiceUrl()}/api/v1/models/names`)
|
||||
.url(`${getServiceUrl()}/models/names`)
|
||||
.method('GET')
|
||||
.success((res) => {
|
||||
RequestService.clearRequestTime();
|
||||
callback(res);
|
||||
})
|
||||
.fail(() => {
|
||||
RequestService.reAjaxFun(() => {
|
||||
this.getModelNames(callback);
|
||||
});
|
||||
// RequestService.reAjaxFun(() => {
|
||||
// this.getModelNames(callback);
|
||||
// });
|
||||
}).send();
|
||||
},
|
||||
|
||||
// 获取模型音色
|
||||
getModelVoices(modelName, callback) {
|
||||
RequestService.sendRequest()
|
||||
.url(`${getServiceUrl()}/api/v1/models/${modelName}/voices`)
|
||||
.url(`${getServiceUrl()}/models/${modelName}/voices`)
|
||||
.method('GET')
|
||||
.success((res) => {
|
||||
RequestService.clearRequestTime();
|
||||
callback(res);
|
||||
})
|
||||
.fail(() => {
|
||||
RequestService.reAjaxFun(() => {
|
||||
this.getModelVoices(modelName, callback);
|
||||
});
|
||||
// RequestService.reAjaxFun(() => {
|
||||
// this.getModelVoices(modelName, callback);
|
||||
// });
|
||||
}).send();
|
||||
},
|
||||
// 获取智能体列表
|
||||
getAgentList(callback) {
|
||||
RequestService.sendRequest()
|
||||
.url(`${getServiceUrl()}/api/v1/user/agent`)
|
||||
.method('GET')
|
||||
.success((res) => {
|
||||
RequestService.clearRequestTime();
|
||||
callback(res);
|
||||
})
|
||||
.fail(() => {
|
||||
RequestService.reAjaxFun(() => {
|
||||
this.getAgentList(callback);
|
||||
});
|
||||
}).send();
|
||||
},
|
||||
|
||||
// 获取用户信息
|
||||
getUserInfo(callback) {
|
||||
RequestService.sendRequest()
|
||||
.url(`${getServiceUrl()}/api/v1/user/info`)
|
||||
.url(`${getServiceUrl()}/user/info`)
|
||||
.method('GET')
|
||||
.success((res) => {
|
||||
RequestService.clearRequestTime()
|
||||
@@ -169,26 +93,9 @@ export default {
|
||||
})
|
||||
.fail((err) => {
|
||||
console.error('接口请求失败:', err)
|
||||
RequestService.reAjaxFun(() => {
|
||||
this.getUserInfo(callback)
|
||||
})
|
||||
// RequestService.reAjaxFun(() => {
|
||||
// this.getUserInfo(callback)
|
||||
// })
|
||||
}).send()
|
||||
},
|
||||
// 添加智能体
|
||||
addAgent(agentName, callback) {
|
||||
RequestService.sendRequest()
|
||||
.url(`${getServiceUrl()}/api/v1/user/agent`)
|
||||
.method('POST')
|
||||
.data({ name: agentName })
|
||||
.success((res) => {
|
||||
RequestService.clearRequestTime();
|
||||
callback(res);
|
||||
})
|
||||
.fail(() => {
|
||||
RequestService.reAjaxFun(() => {
|
||||
this.addAgent(agentName, callback);
|
||||
});
|
||||
}).send();
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<el-dialog :visible.sync="visible" width="400px" center>
|
||||
<el-dialog :visible.sync="visible" width="400px" center :close-on-click-modal="false" :close-on-press-escape="false">
|
||||
<div style="margin: 0 10px 10px;display: flex;align-items: center;gap: 10px;font-weight: 700;font-size: 20px;text-align: left;color: #3d4566;">
|
||||
<div style="width: 40px;height: 40px;border-radius: 50%;background: #5778ff;display: flex;align-items: center;justify-content: center;">
|
||||
<img src="@/assets/home/equipment.png" alt="" style="width: 18px;height: 15px;" />
|
||||
<i class="el-icon-cpu" style="color: #fff;"></i>
|
||||
</div>
|
||||
添加智能体
|
||||
</div>
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
<template>
|
||||
<el-dialog :visible.sync="visible" width="400px" center >
|
||||
<el-dialog :visible.sync="visible" width="400px" center :close-on-click-modal="false" :close-on-press-escape="false">
|
||||
<div style="margin: 0 10px 10px;display: flex;align-items: center;gap: 10px;font-weight: 700;font-size: 20px;text-align: left;color: #3d4566;">
|
||||
<div style="width: 40px;height: 40px;border-radius: 50%;background: #5778ff;display: flex;align-items: center;justify-content: center;">
|
||||
<img src="@/assets/home/equipment.png" alt="" style="width: 18px;height: 15px;" />
|
||||
<i class="el-icon-cpu" style="color: #fff;"></i>
|
||||
</div>
|
||||
添加设备
|
||||
</div>
|
||||
<div style="height: 1px;background: #e8f0ff;" />
|
||||
<div style="margin: 22px 15px;">
|
||||
<div style="font-weight: 400;font-size: 14px;text-align: left;color: #3d4566;">
|
||||
<div style="color: red;display: inline-block;">*</div>
|
||||
<span style="font-size: 11px"> 验证码:</span>
|
||||
<div style="color: red;display: inline-block;">*</div>验证码:
|
||||
</div>
|
||||
<div class="input-46" style="margin-top: 12px;">
|
||||
<el-input placeholder="请输入设备播报的6位数验证码.." v-model="deviceCode" />
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
<template>
|
||||
<el-dialog :visible.sync="visible" width="600px" center :close-on-click-modal="false" :close-on-press-escape="false">
|
||||
<div style="margin: 0 10px 10px;display: flex;align-items: center;gap: 10px;font-weight: 700;font-size: 20px;text-align: left;color: #3d4566;">
|
||||
<div style="width: 40px;height: 40px;border-radius: 50%;background: #5778ff;display: flex;align-items: center;justify-content: center;">
|
||||
<i class="el-icon-lightning" style="color: #fff;"></i>
|
||||
</div>
|
||||
{{ data.id?'编辑':'添加' }}设备
|
||||
</div>
|
||||
<div style="height: 1px;background: #e8f0ff;" />
|
||||
|
||||
<div style="margin: 22px 15px;">
|
||||
<el-form ref="form" :model="data" label-width="80px">
|
||||
<el-form-item label="设备型号" prop="board" :rules="[{ required: true, message: '请输入设备型号', trigger: 'blur' }]">
|
||||
<el-input v-model="data.board" placeholder="请输入设备型号..."></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="固件版本" prop="appVersion" :rules="[{ required: true, message: '请输入固件版本', trigger: 'blur' }]">
|
||||
<el-input v-model="data.appVersion" placeholder="请输入固件版本..."></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="升级地址" prop="url" :rules="[{ required: true, message: '请输入升级地址', trigger: 'blur' },{ type: 'url', message: '请输入正确的升级地址', trigger: 'blur' }]">
|
||||
<el-input type="textarea" v-model="data.url" placeholder="请输入升级地址..."></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否启用">
|
||||
<el-switch v-model="data.isEnabled" size="mini" :active-value="1" :inactive-value="0" active-color="#13ce66" inactive-color="#ff4949"></el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="0">
|
||||
<div style="display: flex;margin: 15px 15px;gap: 7px;">
|
||||
<div class="dialog-btn" @click="confirm">
|
||||
确定
|
||||
</div>
|
||||
<div class="dialog-btn" style="background: #e6ebff;border: 1px solid #adbdff;color: #5778ff;" @click="cancel">
|
||||
取消
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'AddDeviceOtaDialog',
|
||||
props: {
|
||||
visible: { type: Boolean, required: true },
|
||||
data: { type: Object,
|
||||
default: () => ({
|
||||
id: "",
|
||||
board: "",
|
||||
appVersion: "",
|
||||
url: "",
|
||||
isEnabled: 1
|
||||
})
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
methods: {
|
||||
confirm() {
|
||||
this.$refs['form'].validate((valid) => {
|
||||
if (valid) {
|
||||
this.$emit(this.data.id?'confirmUpdate':'confirmSave',this.data)
|
||||
this.$emit('update:visible', false)
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
cancel() {
|
||||
this.$emit('update:visible', false)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dialog-btn {
|
||||
cursor: pointer;
|
||||
flex: 1;
|
||||
border-radius: 23px;
|
||||
background: #5778ff;
|
||||
height: 40px;
|
||||
font-weight: 500;
|
||||
font-size: 12px;
|
||||
color: #fff;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
::v-deep .el-dialog {
|
||||
border-radius: 15px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
::v-deep .el-dialog__headerbtn {
|
||||
display: none;
|
||||
}
|
||||
::v-deep .el-dialog__body {
|
||||
padding: 4px 6px;
|
||||
}
|
||||
::v-deep .el-dialog__header{
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -4,19 +4,19 @@
|
||||
<div style="display: flex;align-items: center;gap: 10px;">
|
||||
<img alt="" src="@/assets/xiaozhi-logo.png" style="width: 42px;height: 42px;"/>
|
||||
<img alt="" src="@/assets/xiaozhi-ai.png" style="width: 58px;height: 12px;"/>
|
||||
<div class="ml-20 menu-btn active" @click="goHome">
|
||||
<div ref="menu-code_agent" class="ml-20 menu-btn" @click="goToPage('/home')">
|
||||
<!-- <img alt="" src="@/assets/home/equipment.png" style="width: 12px;height: 10px;"/> -->
|
||||
<i class="el-icon-cpu"></i>
|
||||
智能体
|
||||
</div>
|
||||
<div class="menu-btn">
|
||||
<div ref="menu-code_console" class="menu-btn">
|
||||
<i class="el-icon-s-grid" style="font-size: 10px;color: #979db1;"/>
|
||||
控制台
|
||||
</div>
|
||||
<!-- <div class="menu-btn">
|
||||
设备管理
|
||||
<img alt="" src="@/assets/home/close.png" style="width: 6px;height: 6px;"/>
|
||||
</div> -->
|
||||
<div ref="menu-code_ota" class="menu-btn" @click="goToPage('/ota')">
|
||||
<i class="el-icon-lightning"></i>
|
||||
OTA管理
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex;align-items: center;gap: 7px; margin-top: 2px;">
|
||||
<div class="serach-box">
|
||||
@@ -33,7 +33,7 @@
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item icon="el-icon-user" @click.native="">个人中心</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-key" @click.native="">修改密码</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-connection" @click.native="">退出登录</el-dropdown-item>
|
||||
<el-dropdown-item icon="el-icon-connection" @click.native="handleLogout">退出登录</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
@@ -54,16 +54,37 @@ export default {
|
||||
userInfo: {
|
||||
username: '',
|
||||
mobile: ''
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$route.meta.menuCode': {
|
||||
handler(to, from) {
|
||||
const meta = this.$route.meta;
|
||||
if(meta && meta.menuCode){
|
||||
this.$nextTick(() => {
|
||||
const menu = this.$refs[`menu-code_`+ meta.menuCode]
|
||||
menu && menu.classList.add('active')
|
||||
})
|
||||
}
|
||||
},
|
||||
immediate: true,
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.fetchUserInfo()
|
||||
},
|
||||
methods: {
|
||||
goHome() {
|
||||
handleLogout() {
|
||||
// 退出登录
|
||||
this.$store.commit('setToken','')
|
||||
this.$router.push('/login')
|
||||
},
|
||||
goToPage(path) {
|
||||
// 跳转到首页
|
||||
this.$router.push('/home')
|
||||
this.$router.replace(path)
|
||||
},
|
||||
// 获取用户信息
|
||||
fetchUserInfo() {
|
||||
|
||||
@@ -28,6 +28,9 @@ const routes = [
|
||||
{
|
||||
path: '/home',
|
||||
name: 'home',
|
||||
meta: {
|
||||
menuCode: 'agent',
|
||||
},
|
||||
component: function () {
|
||||
return import('../views/home.vue')
|
||||
}
|
||||
@@ -35,6 +38,9 @@ const routes = [
|
||||
{
|
||||
path: '/role-config',
|
||||
name: 'RoleConfig',
|
||||
meta: {
|
||||
menuCode: 'agent',
|
||||
},
|
||||
component: function () {
|
||||
return import('../views/roleConfig.vue')
|
||||
}
|
||||
@@ -42,9 +48,22 @@ const routes = [
|
||||
{
|
||||
path: '/device',
|
||||
name: 'Device',
|
||||
meta: {
|
||||
menuCode: 'agent',
|
||||
},
|
||||
component: function () {
|
||||
return import('../views/device.vue')
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/ota',
|
||||
name: 'Ota',
|
||||
meta: {
|
||||
menuCode: 'ota',
|
||||
},
|
||||
component: function () {
|
||||
return import('../views/ota.vue')
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ export function checkUserLogin(fn) {
|
||||
let token = localStorage.getItem(Constant.STORAGE_KEY.TOKEN)
|
||||
let userType = localStorage.getItem(Constant.STORAGE_KEY.USER_TYPE)
|
||||
if (isNull(token) || isNull(userType)) {
|
||||
goToPage('console', true)
|
||||
return
|
||||
goToPage('/login', true)
|
||||
return false
|
||||
}
|
||||
if (fn) {
|
||||
fn()
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<el-table-column label="最近对话" prop="recent_chat_time" width="100"></el-table-column>
|
||||
<el-table-column label="备注" width="220">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="scope.row.isEdit" v-model="scope.row.alias" size="small" @blur="stopEditRemark(scope.$index)"></el-input>
|
||||
<el-input :ref="'alias_input_'+scope.$index" v-if="scope.row.isEdit" v-model="scope.row.alias" size="small" class="input-pd0" @blur="stopEditRemark(scope.$index, scope.row)"></el-input>
|
||||
<span v-else>
|
||||
{{ scope.row.alias }}
|
||||
</span>
|
||||
@@ -35,7 +35,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="OTA升级" width="100" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-switch v-model="scope.row.autoUpdate" size="mini" :active-value="1" :inactive-value="0" active-color="#13ce66" inactive-color="#ff4949"></el-switch>
|
||||
<el-switch v-model="scope.row.autoUpdate" size="mini" :active-value="1" :inactive-value="0" active-color="#13ce66" inactive-color="#ff4949" @change="handleToggleEnabled(scope.row.id, $event)"></el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80" align="center">
|
||||
@@ -64,7 +64,6 @@ import Api from '@/apis/api';
|
||||
import AddDeviceDialog from '@/components/AddDeviceDialog.vue'
|
||||
import HeaderBar from '@/components/HeaderBar.vue'
|
||||
import Footer from '@/components/Footer.vue'
|
||||
import api from '@/apis/api';
|
||||
|
||||
export default {
|
||||
name: 'DevicePage',
|
||||
@@ -74,6 +73,7 @@ export default {
|
||||
addDeviceDialogVisible: false,
|
||||
devices: [],
|
||||
agentId: this.$route.query.agentId,
|
||||
oldVal: '',
|
||||
page: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
@@ -101,10 +101,16 @@ export default {
|
||||
this.addDeviceDialogVisible = true;
|
||||
},
|
||||
startEditRemark(index, row) {
|
||||
this.oldVal = row.alias;
|
||||
this.devices[index].isEdit = true;
|
||||
this.$nextTick(()=>{
|
||||
this.$refs['alias_input_'+index].focus();
|
||||
})
|
||||
},
|
||||
stopEditRemark(index) {
|
||||
stopEditRemark(index, row) {
|
||||
this.devices[index].isEdit = false;
|
||||
if(this.oldVal === row.alias) return;
|
||||
this.handleSetAlias(row.id, row.alias);
|
||||
},
|
||||
handleUnbind(deviceId) {
|
||||
// 解绑逻辑
|
||||
@@ -119,7 +125,7 @@ export default {
|
||||
})
|
||||
},
|
||||
handleDeviceBind(deviceCode) {
|
||||
// 根据需要处理添加设备后逻辑,比如刷新设备列表等
|
||||
// 绑定逻辑
|
||||
console.log('设备验证码:', deviceCode)
|
||||
Api.device.bindDevice(this.agentId, deviceCode, ({data}) => {
|
||||
if (data.code === 0) {
|
||||
@@ -130,6 +136,28 @@ export default {
|
||||
}
|
||||
})
|
||||
},
|
||||
handleSetAlias(id, alias) {
|
||||
// 设置备注逻辑
|
||||
Api.device.setAlias(id, alias, ({data}) => {
|
||||
if (data.code === 0) {
|
||||
showSuccess('更新成功')
|
||||
this.fetchDeviceList()
|
||||
} else {
|
||||
showDanger(data.msg)
|
||||
}
|
||||
})
|
||||
},
|
||||
handleToggleEnabled(id, autoUpdate) {
|
||||
// 更新OTA升级状态
|
||||
Api.device.toggleAutoUpdate(id, autoUpdate, ({data}) => {
|
||||
if (data.code === 0) {
|
||||
showSuccess('更新成功')
|
||||
this.fetchDeviceList()
|
||||
} else {
|
||||
showDanger(data.msg)
|
||||
}
|
||||
})
|
||||
},
|
||||
formatter(row, column) {
|
||||
return formatDate(row.createDate)
|
||||
}
|
||||
@@ -196,4 +224,8 @@ export default {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.input-pd0 /deep/ .el-input__inner {
|
||||
padding: 0 2px;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -99,9 +99,9 @@ export default {
|
||||
handleAgentAdded(agentName) {
|
||||
// 添加智能体
|
||||
Api.agent.addAgent(agentName, ({data}) => {
|
||||
if (data.status === 200) {
|
||||
if (data.code === 0) {
|
||||
showSuccess('添加成功')
|
||||
this.getAgentList()
|
||||
this.fetchAgentList();
|
||||
} else {
|
||||
showDanger(data.msg)
|
||||
}
|
||||
@@ -112,7 +112,7 @@ export default {
|
||||
Api.agent.delAgent(agetnId, (data) => {
|
||||
if (data.status === 200) {
|
||||
showSuccess('删除成功')
|
||||
this.getAgentList()
|
||||
this.fetchAgentList();
|
||||
} else {
|
||||
showDanger(data.msg)
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
<div style="cursor: pointer;" @click="goToRegister">新用户注册</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="login-btn" @click="login">登陆</div>
|
||||
<div class="login-btn" @keyup.enter="login" @click="login">登陆</div>
|
||||
<div style="font-size: 14px;color: #979db1;">
|
||||
登录即同意
|
||||
<div style="display: inline-block;color: #5778FF;cursor: pointer;">《用户协议》</div>
|
||||
@@ -88,7 +88,7 @@ export default {
|
||||
methods: {
|
||||
fetchCaptcha() {
|
||||
if (this.$store.getters.getToken) {
|
||||
goToPage('/home')
|
||||
this.$router.push('/home')
|
||||
} else {
|
||||
this.captchaUuid = getUUID();
|
||||
|
||||
@@ -135,17 +135,17 @@ export default {
|
||||
// 将令牌存储到 Vuex 中
|
||||
this.$store.commit('setToken', JSON.stringify(data.data))
|
||||
|
||||
goToPage('/home')
|
||||
// this.$router.push('/home')
|
||||
})
|
||||
|
||||
// 重新获取验证码
|
||||
// 重新获取验证码(token判断逻辑,存在即跳转home页,否则刷新验证码)
|
||||
setTimeout(() => {
|
||||
this.fetchCaptcha();
|
||||
}, 1000);
|
||||
},
|
||||
|
||||
goToRegister() {
|
||||
goToPage('/register')
|
||||
this.$router.push('/register')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
<template>
|
||||
<div class="welcome">
|
||||
<!-- 公共头部 -->
|
||||
<HeaderBar />
|
||||
<!-- 首页内容 -->
|
||||
<el-main style="padding: 20px; display: flex; flex-direction: column;">
|
||||
<!-- 面包屑-->
|
||||
<div class="breadcrumbs">
|
||||
<el-breadcrumb separator="/">
|
||||
<el-breadcrumb-item>控制台</el-breadcrumb-item>
|
||||
<el-breadcrumb-item>OTA管理</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
</div>
|
||||
<div class="table-container">
|
||||
<h3 class="device-list-title">OTA设备列表</h3>
|
||||
<el-button type="primary" class="add-device-btn" @click="handleAddDeviceOta()">
|
||||
+ 添加设备
|
||||
</el-button>
|
||||
<el-table :data="otaList" style="width: 100%; margin-top: 20px" border>
|
||||
<el-table-column label="设备型号" prop="board" flex></el-table-column>
|
||||
<el-table-column label="固件版本" prop="appVersion" width="140"></el-table-column>
|
||||
<el-table-column label="升级地址" prop="url"></el-table-column>
|
||||
<el-table-column label="是否启用" width="100" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-switch v-model="scope.row.isEnabled" size="mini" :active-value="1" :inactive-value="0" active-color="#13ce66" inactive-color="#ff4949" @change="handleToggleEnabled(scope.row.id, $event)"></el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="text" @click="handleAddDeviceOta(scope.row)" style="color: #ff4949">
|
||||
编辑
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<el-pagination background :current-page="page.pageNo" :page-size="page.pageSize" :pager-count="5" layout="prev, pager, next" :total="page.total" style="margin-top: 4px;text-align: right;"></el-pagination>
|
||||
</div>
|
||||
<!-- 底部 -->
|
||||
<Footer :visible="true" />
|
||||
<!-- 添加设备OTA对话框 -->
|
||||
<AddDeviceOtaDialog :visible.sync="addDeviceOtaDialogVisible" :data="otaData" @confirmSave="handleSaveDeviceOta" @confirmUpdate="handleUpdateDeviceOta" />
|
||||
</el-main>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {getUUID, goToPage, showDanger, showSuccess} from '@/utils'
|
||||
import Api from '@/apis/api';
|
||||
import AddDeviceOtaDialog from '@/components/AddDeviceOtaDialog.vue'
|
||||
import HeaderBar from '@/components/HeaderBar.vue'
|
||||
import Footer from '@/components/Footer.vue'
|
||||
|
||||
export default {
|
||||
name: 'DeviceOtaPage',
|
||||
components: { AddDeviceOtaDialog, HeaderBar, Footer },
|
||||
data() {
|
||||
return {
|
||||
addDeviceOtaDialogVisible: false,
|
||||
otaList: [],
|
||||
otaData: {},
|
||||
page: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
total: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.fetchDeviceOtaList();
|
||||
},
|
||||
methods: {
|
||||
// 获取设备列表
|
||||
fetchDeviceOtaList() {
|
||||
Api.ota.getOtaList(this.page, ({data}) => {
|
||||
if (data.code === 0) {
|
||||
this.page = {...this.page,total:parseInt(data.data.total)}
|
||||
this.otaList = data.data.records
|
||||
} else {
|
||||
showDanger(data.msg)
|
||||
}
|
||||
})
|
||||
},
|
||||
handleAddDeviceOta(ota) {
|
||||
if (ota) {
|
||||
this.otaData = ota
|
||||
}
|
||||
// 添加设备逻辑
|
||||
this.addDeviceOtaDialogVisible = true;
|
||||
},
|
||||
handleSaveDeviceOta(ota) {
|
||||
console.log('添加设备', ota);
|
||||
Api.ota.saveOta(ota, ({data}) => {
|
||||
if (data.code === 0) {
|
||||
showSuccess('添加成功')
|
||||
this.fetchDeviceOtaList()
|
||||
} else {
|
||||
showDanger(data.msg)
|
||||
}
|
||||
this.otaData = {}
|
||||
})
|
||||
},
|
||||
handleUpdateDeviceOta(ota) {
|
||||
// 解绑逻辑
|
||||
console.log('修改设备', ota);
|
||||
Api.ota.updateOta(ota, ({data}) => {
|
||||
if (data.code === 0) {
|
||||
showSuccess('修改成功')
|
||||
this.fetchDeviceOtaList()
|
||||
} else {
|
||||
showDanger(data.msg)
|
||||
}
|
||||
this.otaData = {}
|
||||
})
|
||||
},
|
||||
handleToggleEnabled(id, isEnabled) {
|
||||
// 启用禁用逻辑
|
||||
Api.ota.toggleEnabled({id, isEnabled}, ({data}) => {
|
||||
if (data.code === 0) {
|
||||
showSuccess('更新成功')
|
||||
this.fetchDeviceOtaList()
|
||||
} else {
|
||||
showDanger(data.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.breadcrumbs{
|
||||
padding: 10px 0 0 5px;
|
||||
}
|
||||
|
||||
.welcome {
|
||||
min-width: 900px;
|
||||
min-height: 506px;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-image: url("@/assets/home/background.png");
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
-webkit-background-size: cover;
|
||||
-o-background-size: cover;
|
||||
}
|
||||
|
||||
.table-container {
|
||||
background: #f9fafc;
|
||||
padding: 20px;
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.add-device-btn {
|
||||
float: right;
|
||||
background: #409eff;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
width: 105px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 14px;
|
||||
gap: 8px;
|
||||
margin-bottom: 15px;
|
||||
&:hover {
|
||||
background: #3a8ee6;
|
||||
}
|
||||
}
|
||||
|
||||
.device-list-title {
|
||||
float: left;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
margin: 5px;
|
||||
color: #2c3e50;
|
||||
}
|
||||
|
||||
.el-icon-edit {
|
||||
color: #409eff;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user