diff --git a/main/manager-api/src/main/java/xiaozhi/common/exception/ErrorCode.java b/main/manager-api/src/main/java/xiaozhi/common/exception/ErrorCode.java index 3f914e4c..59a7dcd3 100644 --- a/main/manager-api/src/main/java/xiaozhi/common/exception/ErrorCode.java +++ b/main/manager-api/src/main/java/xiaozhi/common/exception/ErrorCode.java @@ -245,4 +245,9 @@ public interface ErrorCode { int DEVICE_NOT_EXIST = 10194; // 设备不存在 int OTA_UPLOAD_COUNT_EXCEED = 10195; // OTA上传次数超过限制 + // 智能体标签相关错误码 + int AGENT_TAG_NAME_DUPLICATE = 10196; // 标签名称已存在 + int AGENT_TAG_NAME_EMPTY = 10197; // 标签名称不能为空 + int AGENT_TAG_NOT_EXIST = 10198; // 标签不存在 + } diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/controller/AgentController.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/controller/AgentController.java index 76669e67..b669ed6b 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/controller/AgentController.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/controller/AgentController.java @@ -42,6 +42,9 @@ import xiaozhi.modules.agent.dto.AgentMemoryDTO; import xiaozhi.modules.agent.dto.AgentUpdateDTO; import xiaozhi.modules.agent.entity.AgentEntity; import xiaozhi.modules.agent.entity.AgentTemplateEntity; +import xiaozhi.modules.agent.dto.AgentTagDTO; +import xiaozhi.modules.agent.entity.AgentTagEntity; +import xiaozhi.modules.agent.service.AgentTagService; import xiaozhi.modules.agent.service.AgentChatAudioService; import xiaozhi.modules.agent.service.AgentChatHistoryService; import xiaozhi.modules.agent.service.AgentChatSummaryService; @@ -69,6 +72,7 @@ public class AgentController { private final AgentContextProviderService agentContextProviderService; private final AgentChatSummaryService agentChatSummaryService; private final RedisUtils redisUtils; + private final AgentTagService agentTagService; @GetMapping("/list") @Operation(summary = "获取用户智能体列表") @@ -77,7 +81,7 @@ public class AgentController { @RequestParam(value = "keyword", required = false) String keyword, @RequestParam(value = "searchType", defaultValue = "name") String searchType) { UserDetail user = SecurityUser.getUser(); - + // 直接调用整合后的getUserAgents方法,无需再区分搜索和普通查询 List agents = agentService.getUserAgents(user.getId(), keyword, searchType); return new Result>().ok(agents); @@ -275,6 +279,50 @@ public class AgentController { .body(audioData); } + @PostMapping("/tag") + @Operation(summary = "创建标签") + @RequiresPermissions("sys:role:normal") + public Result createTag(@RequestBody Map params) { + String tagName = params.get("tagName"); + if (StringUtils.isBlank(tagName)) { + return new Result().error("标签名称不能为空"); + } + AgentTagEntity tag = agentTagService.saveTag(tagName); + return new Result().ok(tag); + } + @GetMapping("/tag/list") + @Operation(summary = "获取所有标签列表") + @RequiresPermissions("sys:role:normal") + public Result> getAllTags() { + List tags = agentTagService.getAllTags(); + return new Result>().ok(tags); + } + + @DeleteMapping("/tag/{id}") + @Operation(summary = "删除标签") + @RequiresPermissions("sys:role:normal") + public Result deleteTag(@PathVariable String id) { + agentTagService.deleteTag(id); + return new Result().ok(null); + } + + @GetMapping("/{id}/tags") + @Operation(summary = "获取智能体的标签") + @RequiresPermissions("sys:role:normal") + public Result> getAgentTags(@PathVariable String id) { + List tags = agentTagService.getTagsByAgentId(id); + return new Result>().ok(tags); + } + + @PutMapping("/{id}/tags") + @Operation(summary = "保存智能体的标签") + @RequiresPermissions("sys:role:normal") + public Result saveAgentTags(@PathVariable String id, @RequestBody Map params) { + List tagIds = (List) params.get("tagIds"); + List tagNames = (List) params.get("tagNames"); + agentTagService.saveAgentTags(id, tagIds, tagNames); + return new Result().ok(null); + } } \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/dao/AgentTagDao.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/dao/AgentTagDao.java new file mode 100644 index 00000000..e50f7c34 --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/dao/AgentTagDao.java @@ -0,0 +1,24 @@ +package xiaozhi.modules.agent.dao; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import xiaozhi.common.dao.BaseDao; +import xiaozhi.modules.agent.entity.AgentTagEntity; + +import java.util.List; + +@Mapper +public interface AgentTagDao extends BaseDao { + + List selectByAgentId(@Param("agentId") String agentId); + + List selectByAgentIds(@Param("agentIds") List agentIds); + + List selectAll(); + + List selectAgentIdsByTagName(@Param("tagName") String tagName); + + List selectByTagNames(@Param("tagNames") List tagNames); + + int batchInsert(@Param("list") List tagList); +} diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/dao/AgentTagRelationDao.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/dao/AgentTagRelationDao.java new file mode 100644 index 00000000..7169b5d5 --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/dao/AgentTagRelationDao.java @@ -0,0 +1,18 @@ +package xiaozhi.modules.agent.dao; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import xiaozhi.common.dao.BaseDao; +import xiaozhi.modules.agent.entity.AgentTagRelationEntity; + +import java.util.List; + +@Mapper +public interface AgentTagRelationDao extends BaseDao { + + int deleteByAgentId(@Param("agentId") String agentId); + + int insertRelation(AgentTagRelationEntity relation); + + int batchInsertRelation(@Param("list") List relations); +} diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/AgentDTO.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/AgentDTO.java index edad88db..77028f2a 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/AgentDTO.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/AgentDTO.java @@ -5,6 +5,7 @@ import java.util.List; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import xiaozhi.modules.agent.dto.AgentTagDTO; /** * 智能体数据传输对象 @@ -46,4 +47,7 @@ public class AgentDTO { @Schema(description = "设备数量", example = "10") private Integer deviceCount; + + @Schema(description = "标签列表") + private List tags; } \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/AgentTagDTO.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/AgentTagDTO.java new file mode 100644 index 00000000..5dfc5f52 --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/dto/AgentTagDTO.java @@ -0,0 +1,20 @@ +package xiaozhi.modules.agent.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +@Data +@Schema(description = "智能体标签DTO") +public class AgentTagDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "标签ID") + private String id; + + @Schema(description = "标签名称") + private String tagName; +} diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/entity/AgentTagEntity.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/entity/AgentTagEntity.java new file mode 100644 index 00000000..82555c3e --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/entity/AgentTagEntity.java @@ -0,0 +1,41 @@ +package xiaozhi.modules.agent.entity; + +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@TableName("ai_agent_tag") +@Schema(description = "智能体标签") +public class AgentTagEntity { + + @TableId(type = IdType.ASSIGN_UUID) + @Schema(description = "主键") + private String id; + + @Schema(description = "标签名称") + private String tagName; + + @Schema(description = "排序") + private Integer sort; + + @Schema(description = "创建者") + private Long creator; + + @Schema(description = "创建时间") + private Date createdAt; + + @Schema(description = "更新者") + private Long updater; + + @Schema(description = "更新时间") + private Date updatedAt; + + @Schema(description = "删除标记") + private Integer deleted; +} diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/entity/AgentTagRelationEntity.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/entity/AgentTagRelationEntity.java new file mode 100644 index 00000000..e142b727 --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/entity/AgentTagRelationEntity.java @@ -0,0 +1,38 @@ +package xiaozhi.modules.agent.entity; + +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@TableName("ai_agent_tag_relation") +@Schema(description = "智能体标签关联") +public class AgentTagRelationEntity { + + @TableId(type = IdType.ASSIGN_UUID) + @Schema(description = "主键") + private String id; + + @Schema(description = "智能体ID") + private String agentId; + + @Schema(description = "标签ID") + private String tagId; + + @Schema(description = "创建者") + private Long creator; + + @Schema(description = "创建时间") + private Date createdAt; + + @Schema(description = "更新者") + private Long updater; + + @Schema(description = "更新时间") + private Date updatedAt; +} diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/AgentTagService.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/AgentTagService.java new file mode 100644 index 00000000..2ef1694a --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/AgentTagService.java @@ -0,0 +1,25 @@ +package xiaozhi.modules.agent.service; + +import java.util.List; + +import xiaozhi.modules.agent.dto.AgentTagDTO; +import xiaozhi.modules.agent.entity.AgentTagEntity; + +public interface AgentTagService { + + AgentTagEntity saveTag(String tagName); + + void deleteTag(String tagId); + + List getTagsByAgentId(String agentId); + + void saveAgentTags(String agentId, List tagIds, List tagNames); + + void deleteAgentTags(String agentId); + + List getTagsByAgentIds(List agentIds); + + List getAllTags(); + + List getAgentIdsByTagName(String tagName); +} diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentServiceImpl.java index 9c423ff8..22029ec5 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentServiceImpl.java @@ -31,17 +31,21 @@ import xiaozhi.common.utils.ConvertUtils; import xiaozhi.common.utils.JsonUtils; import xiaozhi.common.utils.ToolUtil; import xiaozhi.modules.agent.dao.AgentDao; +import xiaozhi.modules.agent.dao.AgentTagDao; import xiaozhi.modules.agent.dto.AgentCreateDTO; import xiaozhi.modules.agent.dto.AgentDTO; +import xiaozhi.modules.agent.dto.AgentTagDTO; import xiaozhi.modules.agent.dto.AgentUpdateDTO; import xiaozhi.modules.agent.entity.AgentContextProviderEntity; import xiaozhi.modules.agent.entity.AgentEntity; import xiaozhi.modules.agent.entity.AgentPluginMapping; +import xiaozhi.modules.agent.entity.AgentTagEntity; import xiaozhi.modules.agent.entity.AgentTemplateEntity; import xiaozhi.modules.agent.service.AgentChatHistoryService; import xiaozhi.modules.agent.service.AgentContextProviderService; import xiaozhi.modules.agent.service.AgentPluginMappingService; import xiaozhi.modules.agent.service.AgentService; +import xiaozhi.modules.agent.service.AgentTagService; import xiaozhi.modules.agent.service.AgentTemplateService; import xiaozhi.modules.agent.vo.AgentInfoVO; import xiaozhi.modules.device.entity.DeviceEntity; @@ -59,6 +63,7 @@ import xiaozhi.modules.timbre.service.TimbreService; @AllArgsConstructor public class AgentServiceImpl extends BaseServiceImpl implements AgentService { private final AgentDao agentDao; + private final AgentTagDao agentTagDao; private final TimbreService timbreModelService; private final ModelConfigService modelConfigService; private final RedisUtils redisUtils; @@ -68,6 +73,7 @@ public class AgentServiceImpl extends BaseServiceImpl imp private final AgentTemplateService agentTemplateService; private final ModelProviderService modelProviderService; private final AgentContextProviderService agentContextProviderService; + private final AgentTagService agentTagService; @Override public PageData adminAgentList(Map params) { @@ -151,8 +157,16 @@ public class AgentServiceImpl extends BaseServiceImpl imp return new ArrayList<>(); } } else { - // 按名称搜索 - queryWrapper.like("agent_name", keyword); + // 按名称搜索(默认):同时搜索智能体名称和标签名 + List tagAgentIds = agentTagService.getAgentIdsByTagName(keyword); + if (ToolUtil.isNotEmpty(tagAgentIds)) { + queryWrapper.and(wrapper -> wrapper + .like("agent_name", keyword) + .or() + .in("id", tagAgentIds)); + } else { + queryWrapper.like("agent_name", keyword); + } } } @@ -193,6 +207,19 @@ public class AgentServiceImpl extends BaseServiceImpl imp // 获取设备数量 dto.setDeviceCount(getDeviceCountByAgentId(agent.getId())); + // 获取标签列表 + List tags = agentTagDao.selectByAgentId(agent.getId()); + if (ToolUtil.isNotEmpty(tags)) { + dto.setTags(tags.stream().map(this::convertTagToDTO).collect(Collectors.toList())); + } + + return dto; + } + + private AgentTagDTO convertTagToDTO(AgentTagEntity entity) { + AgentTagDTO dto = new AgentTagDTO(); + dto.setId(entity.getId()); + dto.setTagName(entity.getTagName()); return dto; } diff --git a/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentTagServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentTagServiceImpl.java new file mode 100644 index 00000000..f0bf0a2e --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/agent/service/impl/AgentTagServiceImpl.java @@ -0,0 +1,199 @@ +package xiaozhi.modules.agent.service.impl; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; + +import lombok.AllArgsConstructor; +import xiaozhi.common.exception.ErrorCode; +import xiaozhi.common.exception.RenException; +import xiaozhi.common.service.impl.BaseServiceImpl; +import xiaozhi.modules.agent.dao.AgentTagDao; +import xiaozhi.modules.agent.dao.AgentTagRelationDao; +import xiaozhi.modules.agent.dto.AgentTagDTO; +import xiaozhi.modules.agent.entity.AgentTagEntity; +import xiaozhi.modules.agent.entity.AgentTagRelationEntity; +import xiaozhi.modules.agent.service.AgentTagService; + +@Service +@AllArgsConstructor +public class AgentTagServiceImpl extends BaseServiceImpl implements AgentTagService { + + private final AgentTagRelationDao agentTagRelationDao; + + @Override + public AgentTagEntity saveTag(String tagName) { + if (tagName == null || tagName.trim().isEmpty()) { + throw new RenException(ErrorCode.AGENT_TAG_NAME_EMPTY); + } + + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("tag_name", tagName); + wrapper.eq("deleted", 0); + AgentTagEntity existTag = baseDao.selectOne(wrapper); + if (existTag != null) { + return existTag; + } + + AgentTagEntity tag = new AgentTagEntity(); + tag.setId(UUID.randomUUID().toString().replace("-", "")); + tag.setTagName(tagName); + tag.setSort(0); + tag.setCreatedAt(new Date()); + tag.setUpdatedAt(new Date()); + tag.setDeleted(0); + baseDao.insert(tag); + return tag; + } + + @Override + public void deleteTag(String tagId) { + AgentTagEntity tag = baseDao.selectById(tagId); + if (tag != null) { + tag.setDeleted(1); + tag.setUpdatedAt(new Date()); + baseDao.updateById(tag); + } + } + + @Override + public List getTagsByAgentId(String agentId) { + List tags = baseDao.selectByAgentId(agentId); + return tags.stream().map(this::convertToDTO).collect(Collectors.toList()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void saveAgentTags(String agentId, List tagIds, List tagNames) { + agentTagRelationDao.deleteByAgentId(agentId); + + List currentTags = baseDao.selectByAgentId(agentId); + List currentTagNames = currentTags.stream() + .map(AgentTagEntity::getTagName) + .collect(Collectors.toList()); + + List allTagIds = new ArrayList<>(); + List newTagNames = new ArrayList<>(); + + if (tagNames != null && !tagNames.isEmpty()) { + Set addedTagNames = new HashSet<>(); + for (String tagName : tagNames) { + if (tagName == null || tagName.trim().isEmpty()) { + throw new RenException(ErrorCode.AGENT_TAG_NAME_EMPTY); + } + + if (currentTagNames.contains(tagName) || addedTagNames.contains(tagName)) { + throw new RenException(ErrorCode.AGENT_TAG_NAME_DUPLICATE); + } + addedTagNames.add(tagName); + newTagNames.add(tagName); + } + } + + List existTags = new ArrayList<>(); + if (!newTagNames.isEmpty()) { + existTags = baseDao.selectByTagNames(newTagNames); + } + + List existTagNames = existTags.stream() + .map(AgentTagEntity::getTagName) + .collect(Collectors.toList()); + + List tagsToInsert = new ArrayList<>(); + for (String tagName : newTagNames) { + if (!existTagNames.contains(tagName)) { + AgentTagEntity tag = new AgentTagEntity(); + tag.setId(UUID.randomUUID().toString().replace("-", "")); + tag.setTagName(tagName); + tag.setSort(0); + tag.setDeleted(0); + tag.setCreatedAt(new Date()); + tag.setUpdatedAt(new Date()); + tagsToInsert.add(tag); + } + } + + if (!tagsToInsert.isEmpty()) { + baseDao.batchInsert(tagsToInsert); + for (AgentTagEntity tag : tagsToInsert) { + allTagIds.add(tag.getId()); + } + } + + for (AgentTagEntity existTag : existTags) { + if (!allTagIds.contains(existTag.getId())) { + allTagIds.add(existTag.getId()); + } + } + + if (tagIds != null && !tagIds.isEmpty()) { + List tagIdEntities = baseDao.selectBatchIds(tagIds); + for (AgentTagEntity tag : tagIdEntities) { + if (tag != null && (currentTagNames.contains(tag.getTagName()) || + newTagNames.contains(tag.getTagName()))) { + throw new RenException(ErrorCode.AGENT_TAG_NAME_DUPLICATE); + } + } + allTagIds.addAll(tagIds); + } + + if (allTagIds.isEmpty()) { + return; + } + + List relations = new ArrayList<>(); + Date now = new Date(); + for (String tagId : allTagIds) { + AgentTagRelationEntity relation = new AgentTagRelationEntity(); + relation.setId(UUID.randomUUID().toString().replace("-", "")); + relation.setAgentId(agentId); + relation.setTagId(tagId); + relation.setCreatedAt(now); + relation.setUpdatedAt(now); + relations.add(relation); + } + agentTagRelationDao.batchInsertRelation(relations); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteAgentTags(String agentId) { + agentTagRelationDao.deleteByAgentId(agentId); + } + + @Override + public List getTagsByAgentIds(List agentIds) { + if (agentIds == null || agentIds.isEmpty()) { + return List.of(); + } + List tags = baseDao.selectByAgentIds(agentIds); + return tags.stream().map(this::convertToDTO).collect(Collectors.toList()); + } + + @Override + public List getAllTags() { + List tags = baseDao.selectAll(); + return tags.stream().map(this::convertToDTO).collect(Collectors.toList()); + } + + @Override + public List getAgentIdsByTagName(String tagName) { + return baseDao.selectAgentIdsByTagName(tagName); + } + + private AgentTagDTO convertToDTO(AgentTagEntity entity) { + AgentTagDTO dto = new AgentTagDTO(); + dto.setId(entity.getId()); + dto.setTagName(entity.getTagName()); + return dto; + } +} diff --git a/main/manager-api/src/main/resources/db/changelog/202602281000.sql b/main/manager-api/src/main/resources/db/changelog/202602281000.sql new file mode 100644 index 00000000..5efa9696 --- /dev/null +++ b/main/manager-api/src/main/resources/db/changelog/202602281000.sql @@ -0,0 +1,29 @@ +-- 标签表 +CREATE TABLE IF NOT EXISTS ai_agent_tag ( + id VARCHAR(32) NOT NULL COMMENT '主键', + tag_name VARCHAR(64) NOT NULL COMMENT '标签名称', + sort INT UNSIGNED DEFAULT 0 COMMENT '排序', + creator BIGINT COMMENT '创建者', + created_at DATETIME COMMENT '创建时间', + updater BIGINT COMMENT '更新者', + updated_at DATETIME COMMENT '更新时间', + deleted TINYINT DEFAULT 0 COMMENT '删除标记', + PRIMARY KEY (id), + UNIQUE KEY uk_tag_name (tag_name), + INDEX idx_sort (sort) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='智能体标签表'; + +-- 智能体标签关联表 +CREATE TABLE IF NOT EXISTS ai_agent_tag_relation ( + id VARCHAR(32) NOT NULL COMMENT '主键', + agent_id VARCHAR(32) NOT NULL COMMENT '智能体ID', + tag_id VARCHAR(32) NOT NULL COMMENT '标签ID', + creator BIGINT COMMENT '创建者', + created_at DATETIME COMMENT '创建时间', + updater BIGINT COMMENT '更新者', + updated_at DATETIME COMMENT '更新时间', + PRIMARY KEY (id), + UNIQUE KEY uk_agent_tag (agent_id, tag_id), + INDEX idx_agent_id (agent_id), + INDEX idx_tag_id (tag_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='智能体标签关联表'; 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 606cefa7..2555a05a 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 @@ -543,3 +543,9 @@ databaseChangeLog: - sqlFile: encoding: utf8 path: classpath:db/changelog/202602271137.sql + id: 202602281000 + author: rainv123 + changes: + - sqlFile: + encoding: utf8 + path: classpath:db/changelog/202602281000.sql diff --git a/main/manager-api/src/main/resources/i18n/messages.properties b/main/manager-api/src/main/resources/i18n/messages.properties index 25cd7021..75a3ad4e 100644 --- a/main/manager-api/src/main/resources/i18n/messages.properties +++ b/main/manager-api/src/main/resources/i18n/messages.properties @@ -201,4 +201,7 @@ 10192=\u9002\u914D\u5668\u7C7B\u578B\u672A\u627E\u5230 10193=\u8BBE\u5907ID\u4E0D\u80FD\u4E3A\u7A7A 10194=\u8BBE\u5907\u4E0D\u5B58\u5728\u6216\u4E0D\u5728\u7EBF -10195=OTA\u4E0A\u4F20\u6B21\u6570\u8D85\u8FC7\u9650\u5236 \ No newline at end of file +10195=OTA\u4E0A\u4F20\u6B21\u6570\u8D85\u8FC7\u9650\u5236 +10196=\u6807\u7B7E\u540D\u79F0\u5DF2\u5B58\u5728 +10197=\u6807\u7B7E\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A +10198=\u6807\u7B7E\u4E0D\u5B58\u5728 \ No newline at end of file diff --git a/main/manager-api/src/main/resources/i18n/messages_de_DE.properties b/main/manager-api/src/main/resources/i18n/messages_de_DE.properties index 0b9ed96d..f6595601 100644 --- a/main/manager-api/src/main/resources/i18n/messages_de_DE.properties +++ b/main/manager-api/src/main/resources/i18n/messages_de_DE.properties @@ -201,4 +201,7 @@ 10192=Adaptertyp nicht gefunden 10193=Adapter-ID darf nicht leer sein 10194=Adapter nicht gefunden oder nicht online -10195=OTA-Upload-Anzahl \u00FCberschreitet das Limit \ No newline at end of file +10195=OTA-Upload-Anzahl \u00FCberschreitet das Limit +10196=Tag-Name existiert bereits +10197=Tag-Name darf nicht leer sein +10198=Tag nicht gefunden \ No newline at end of file diff --git a/main/manager-api/src/main/resources/i18n/messages_en_US.properties b/main/manager-api/src/main/resources/i18n/messages_en_US.properties index 17b1b961..a0f882c4 100644 --- a/main/manager-api/src/main/resources/i18n/messages_en_US.properties +++ b/main/manager-api/src/main/resources/i18n/messages_en_US.properties @@ -201,4 +201,7 @@ 10192=Adapter type not found 10193=Device ID cannot be empty 10194=Device not found or not online -10195=OTA upload times exceed the limit \ No newline at end of file +10195=OTA upload times exceed the limit +10196=Tag name already exists +10197=Tag name cannot be empty +10198=Tag not found \ No newline at end of file diff --git a/main/manager-api/src/main/resources/i18n/messages_vi_VN.properties b/main/manager-api/src/main/resources/i18n/messages_vi_VN.properties index 3b80a6dc..547a62b4 100644 --- a/main/manager-api/src/main/resources/i18n/messages_vi_VN.properties +++ b/main/manager-api/src/main/resources/i18n/messages_vi_VN.properties @@ -201,4 +201,7 @@ 10192=Kh\u00F4ng t\u00ECm th\u1EA5y lo\u1EA1i b\u1ED9 chuy\u1EC3n \u0111\u1ED5i 10193=ID thi\u1EBFt b\u1ECB kh\u00F4ng th\u1EC3 tr\u1ED1ng 10194=Kh\u00F4ng t\u00ECm th\u1EA5y thi\u1EBFt b\u1ECB ho\u1EB7c thi\u1EBFt b\u1ECB kh\u00F4ng tr\u1EF1c tuy\u1EBFn -10195=S\u1ED1 l\u1EA7n t\u1EA3i l\u00EAn OTA v\u01B0\u1EE3t qu\u00E1 gi\u1EDBi h\u1EA1n \ No newline at end of file +10195=S\u1ED1 l\u1EA7n t\u1EA3i l\u00EAn OTA v\u01B0\u1EE3t qu\u00E1 gi\u1EDBi h\u1EA1n +10196=T\u00EAn th\u1EB9� \u0111\u00E3 t\u1ED3n t\u1EA1i +10197=T\u00EAn th\u1EB9� kh\u00F4ng th\u1EC3 \u0111\u1EC3 tr\u1ED1ng +10198=Kh\u00F4ng t\u00ECm th\u1EA5y th\u1EB9� \ No newline at end of file diff --git a/main/manager-api/src/main/resources/i18n/messages_zh_TW.properties b/main/manager-api/src/main/resources/i18n/messages_zh_TW.properties index f6913eea..864be596 100644 --- a/main/manager-api/src/main/resources/i18n/messages_zh_TW.properties +++ b/main/manager-api/src/main/resources/i18n/messages_zh_TW.properties @@ -201,4 +201,7 @@ 10192=\u9002\u914D\u5668\u985E\u578B\u672A\u627E\u5230 10193=\u8A2D\u5099ID\u4E0D\u80FD\u4E3A\u7A7A 10194=\u8A2D\u5099\u4E0D\u5B58\u5728\u6216\u672A\u5728\u7DDA -10195=OTA\u4E0A\u4F20\u6B21\u6578\u8D85\u904E\u9650\u5236 \ No newline at end of file +10195=OTA\u4E0A\u4F20\u6B21\u6578\u8D85\u904E\u9650\u5236 +10196=\u6A19\u7C64\u540D\u7A31\u5DF2\u5B58\u5728 +10197=\u6A19\u7C64\u540D\u7A31\u4E0D\u80FD\u4E3A\u7A7A +10198=\u6A19\u7C64\u4E0D\u5B58\u5728 \ No newline at end of file diff --git a/main/manager-api/src/main/resources/mapper/agent/AgentTagDao.xml b/main/manager-api/src/main/resources/mapper/agent/AgentTagDao.xml new file mode 100644 index 00000000..b3d8c6c8 --- /dev/null +++ b/main/manager-api/src/main/resources/mapper/agent/AgentTagDao.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + INSERT INTO ai_agent_tag (id, tag_name, sort, deleted, creator, created_at, updater, updated_at) + VALUES + + (#{item.id}, #{item.tagName}, #{item.sort}, #{item.deleted}, #{item.creator}, #{item.createdAt}, #{item.updater}, #{item.updatedAt}) + + + + diff --git a/main/manager-api/src/main/resources/mapper/agent/AgentTagRelationDao.xml b/main/manager-api/src/main/resources/mapper/agent/AgentTagRelationDao.xml new file mode 100644 index 00000000..4569f616 --- /dev/null +++ b/main/manager-api/src/main/resources/mapper/agent/AgentTagRelationDao.xml @@ -0,0 +1,22 @@ + + + + + + DELETE FROM ai_agent_tag_relation WHERE agent_id = #{agentId} + + + + INSERT INTO ai_agent_tag_relation (id, agent_id, tag_id, creator, created_at, updater, updated_at) + VALUES (#{id}, #{agentId}, #{tagId}, #{creator}, #{createdAt}, #{updater}, #{updatedAt}) + + + + INSERT INTO ai_agent_tag_relation (id, agent_id, tag_id, creator, created_at, updater, updated_at) + VALUES + + (#{item.id}, #{item.agentId}, #{item.tagId}, #{item.creator}, #{item.createdAt}, #{item.updater}, #{item.updatedAt}) + + + + diff --git a/main/manager-web/src/apis/module/agent.js b/main/manager-web/src/apis/module/agent.js index b90c932c..5cbd60cb 100644 --- a/main/manager-web/src/apis/module/agent.js +++ b/main/manager-web/src/apis/module/agent.js @@ -398,4 +398,35 @@ export default { }); }).send(); }, + // 获取智能体标签 + getAgentTags(agentId, callback) { + RequestService.sendRequest() + .url(`${getServiceUrl()}/agent/${agentId}/tags`) + .method('GET') + .success((res) => { + RequestService.clearRequestTime(); + callback(res); + }) + .networkFail(() => { + RequestService.reAjaxFun(() => { + this.getAgentTags(agentId, callback); + }); + }).send(); + }, + // 保存智能体标签 + saveAgentTags(agentId, tags, callback) { + RequestService.sendRequest() + .url(`${getServiceUrl()}/agent/${agentId}/tags`) + .method('PUT') + .data(tags) + .success((res) => { + RequestService.clearRequestTime(); + callback(res); + }) + .networkFail(() => { + RequestService.reAjaxFun(() => { + this.saveAgentTags(agentId, tags, callback); + }); + }).send(); + }, } diff --git a/main/manager-web/src/components/AddWisdomBodyDialog.vue b/main/manager-web/src/components/AddWisdomBodyDialog.vue index 33507fab..2c886526 100644 --- a/main/manager-web/src/components/AddWisdomBodyDialog.vue +++ b/main/manager-web/src/components/AddWisdomBodyDialog.vue @@ -14,7 +14,7 @@
*
{{ $t('addAgentDialog.agentName') }}:
- +
diff --git a/main/manager-web/src/components/DeviceItem.vue b/main/manager-web/src/components/DeviceItem.vue index c29d3243..87a82687 100644 --- a/main/manager-web/src/components/DeviceItem.vue +++ b/main/manager-web/src/components/DeviceItem.vue @@ -1,13 +1,15 @@ @@ -81,6 +88,10 @@ export default { } else { return this.device.lastConnectedAt; } + }, + tags() { + if (!this.device.tags) return []; + return this.device.tags.map((tag) => tag.tagName); } }, methods: { @@ -102,16 +113,45 @@ export default { } this.$emit('chat-history', { agentId: this.device.agentId, agentName: this.device.agentName }) } + }, + watch: { + tags: { + handler(newTags) { + if (newTags.length === 0) return; + this.$nextTick(() => { + const scrollWidth = this.$refs.scrollRef.clientWidth; + const tagsWidth = this.$refs.tagsRef.clientWidth; + if (tagsWidth < scrollWidth) { + this.$refs.tagsRef.style.width = '100%'; + this.$refs.tagsRef.style.justifyContent = 'flex-end'; + } else { + this.$refs.tagsRef.style.width = 'fit-content'; + this.$refs.tagsRef.style.justifyContent = 'flex-start'; + } + }) + }, + immediate: true + } } } -