From d8d1a4eaf44d202cffdf2e693abccbe2e6aecd22 Mon Sep 17 00:00:00 2001 From: wangzhiwei Date: Wed, 25 Feb 2026 11:14:43 +0800 Subject: [PATCH] =?UTF-8?q?feat(content):=20=E9=87=8D=E6=9E=84=E5=86=85?= =?UTF-8?q?=E5=AE=B9=E7=AE=A1=E7=90=86=E7=B3=BB=E7=BB=9F=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E6=A0=87=E7=AD=BE=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改应用配置文件,统一token和session超时时间为24小时 - 配置Redis连接参数为动态引用公共配置 - 在内容实体类中替换分类相关字段为来源和标签字段 - 移除分类ID数组设置方法,优化实体映射 - 更新MyBatis映射文件中的字段映射关系 - 新增CmsCategoryTag实体类用于分类标签关联 - 实现标签服务接口,支持按分类查询标签列表 - 在内容控制器中添加标签列表获取接口 - 重构技能生成控制器,分离预生成和生成接口 - 更新技能请求参数类,支持标签列表传递 - 调整用户登录信息缓存时间至24小时 - 完善分类标签关联的数据访问层实现 --- .../controller/CmsCategoryController.java | 35 +++ .../skills/controller/SkillGenController.java | 15 +- .../kexue/skills/entity/CmsCategoryTag.java | 47 ++++ .../com/kexue/skills/entity/CmsContent.java | 25 +- .../skills/entity/dto/CmsCategoryTagDto.java | 28 +++ .../skills/entity/dto/CmsContentDto.java | 2 + .../entity/request/SkillGenRequest.java | 23 +- .../entity/request/SkillPreGenRequest.java | 25 ++ .../skills/entity/request/SkillRequest.java | 29 ++- .../skills/mapper/CmsCategoryTagMapper.java | 100 ++++++++ .../com/kexue/skills/mapper/CmsTagMapper.java | 8 + .../skills/service/CmsCategoryTagService.java | 116 ++++++++++ .../kexue/skills/service/CmsTagService.java | 8 + .../kexue/skills/service/SkillGenService.java | 6 +- .../impl/CmsCategoryTagServiceImpl.java | 219 ++++++++++++++++++ .../service/impl/CmsTagServiceImpl.java | 11 + .../service/impl/SkillGenServiceImpl.java | 68 +++++- .../service/impl/SysUserServiceImpl.java | 4 +- src/main/resources/application-dev.yml | 38 ++- src/main/resources/application-prod.yml | 10 +- .../resources/mapper/CmsCategoryTagMapper.xml | 129 +++++++++++ .../resources/mapper/CmsContentMapper.xml | 70 ++---- src/main/resources/mapper/CmsTagMapper.xml | 10 + 23 files changed, 917 insertions(+), 109 deletions(-) create mode 100644 src/main/java/com/kexue/skills/entity/CmsCategoryTag.java create mode 100644 src/main/java/com/kexue/skills/entity/dto/CmsCategoryTagDto.java create mode 100644 src/main/java/com/kexue/skills/entity/request/SkillPreGenRequest.java create mode 100644 src/main/java/com/kexue/skills/mapper/CmsCategoryTagMapper.java create mode 100644 src/main/java/com/kexue/skills/service/CmsCategoryTagService.java create mode 100644 src/main/java/com/kexue/skills/service/impl/CmsCategoryTagServiceImpl.java create mode 100644 src/main/resources/mapper/CmsCategoryTagMapper.xml diff --git a/src/main/java/com/kexue/skills/controller/CmsCategoryController.java b/src/main/java/com/kexue/skills/controller/CmsCategoryController.java index 8d8f5b0..a7264b8 100644 --- a/src/main/java/com/kexue/skills/controller/CmsCategoryController.java +++ b/src/main/java/com/kexue/skills/controller/CmsCategoryController.java @@ -7,6 +7,8 @@ import com.kexue.skills.entity.CmsCategory; import com.kexue.skills.entity.base.IdDto; import com.kexue.skills.entity.dto.CmsCategoryDto; import com.kexue.skills.service.CmsCategoryService; +import com.kexue.skills.service.CmsTagService; +import com.kexue.skills.service.CmsCategoryTagService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.web.bind.annotation.*; @@ -29,6 +31,18 @@ public class CmsCategoryController { */ @Resource private CmsCategoryService cmsCategoryService; + + /** + * 标签服务对象 + */ + @Resource + private CmsTagService cmsTagService; + + /** + * 分类标签关联服务对象 + */ + @Resource + private CmsCategoryTagService cmsCategoryTagService; /** * 分页查询 * @@ -126,4 +140,25 @@ public class CmsCategoryController { public CommonResult> getCategoryDict() { return CommonResult.success(cmsCategoryService.getCategoryDict()); } + + /** + * 获取标签列表 + * + * @param categoryId 分类ID(可选),不传则返回所有标签 + * @return 标签列表 + */ + @GetMapping("/tagList") + @Operation(summary = "获取标签列表", description = "获取标签列表,若传入分类ID则返回该分类下的标签,否则返回所有标签") + public CommonResult> getTagList(@RequestParam(value = "categoryId", required = false) Long categoryId) { + if (categoryId != null) { + // 根据分类ID查询标签列表 + return CommonResult.success(cmsCategoryTagService.getTagsByCategoryId(categoryId)); + } else { + // 查询所有标签 + com.kexue.skills.entity.dto.CmsTagDto queryDto = new com.kexue.skills.entity.dto.CmsTagDto(); + queryDto.setDeleteFlag(0); + queryDto.setStatus(1); + return CommonResult.success(cmsTagService.getList(queryDto)); + } + } } \ No newline at end of file diff --git a/src/main/java/com/kexue/skills/controller/SkillGenController.java b/src/main/java/com/kexue/skills/controller/SkillGenController.java index d0cbd48..33d69b6 100644 --- a/src/main/java/com/kexue/skills/controller/SkillGenController.java +++ b/src/main/java/com/kexue/skills/controller/SkillGenController.java @@ -1,6 +1,9 @@ package com.kexue.skills.controller; +import com.alibaba.fastjson.JSONObject; import com.kexue.skills.common.CommonResult; +import com.kexue.skills.entity.request.SkillGenRequest; +import com.kexue.skills.entity.request.SkillPreGenRequest; import com.kexue.skills.entity.response.SkillResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -28,10 +31,16 @@ public class SkillGenController { * @param request 生成请求 * @return 生成结果 */ - @PostMapping("/generate") + @PostMapping("/preGenerate") @Operation(summary = "生成技能", description = "生成技能") - public CommonResult generate(@RequestBody com.kexue.skills.entity.request.SkillGenRequest request) { - return CommonResult.success(skillGenService.generateSkill(request)); + public CommonResult preGenerate(@RequestBody SkillPreGenRequest request) { + return CommonResult.success(skillGenService.preGenerate(request)); + } + + @PostMapping("/generate") + @Operation(summary = "生成Skill对应的md文件", description = "生成Skill对应的md文件") + public CommonResult generate(@RequestBody SkillGenRequest request) { + return CommonResult.success(skillGenService.generate(request)); } /** diff --git a/src/main/java/com/kexue/skills/entity/CmsCategoryTag.java b/src/main/java/com/kexue/skills/entity/CmsCategoryTag.java new file mode 100644 index 0000000..262fa42 --- /dev/null +++ b/src/main/java/com/kexue/skills/entity/CmsCategoryTag.java @@ -0,0 +1,47 @@ +package com.kexue.skills.entity; + +import java.util.Date; + +import java.io.Serializable; +import com.kexue.skills.entity.base.BaseEntity; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * (CmsCategoryTag)实体类 + * + * @author 王志维 + * @since 2025-02-21 23:01:48 + */ +@Data +public class CmsCategoryTag extends BaseEntity implements Serializable { + private static final long serialVersionUID = 1L; + + @Schema(description ="主键ID") + private Long id; + + @Schema(description ="分类ID") + private Long categoryId; + + @Schema(description ="标签ID") + private Long tagId; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @Schema(description ="创建时间") + private Date createTime; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @Schema(description ="更新时间") + private Date updateTime; + + @Schema(description ="创建人") + private String createBy; + + @Schema(description ="更新人") + private String updateBy; + + @Schema(description ="是否删除 :0 未删除,1已删除") + private Integer deleteFlag; + +} diff --git a/src/main/java/com/kexue/skills/entity/CmsContent.java b/src/main/java/com/kexue/skills/entity/CmsContent.java index 47f72ef..f95aef9 100644 --- a/src/main/java/com/kexue/skills/entity/CmsContent.java +++ b/src/main/java/com/kexue/skills/entity/CmsContent.java @@ -129,27 +129,10 @@ public class CmsContent extends BaseEntity implements Serializable { @Schema(description ="副标题") private String subtitle; - @Schema(description ="父分类ID") - private Long parentCategoryId; + @Schema(description ="来源") + private String origin; - // 用于接收前端发送的分类ID数组 - @JsonProperty("categoryIds") - public void setCategoryIdsFromArray(List categoryIdList) { - if (categoryIdList != null && !categoryIdList.isEmpty()) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < categoryIdList.size(); i++) { - sb.append(categoryIdList.get(i)); - if (i < categoryIdList.size() - 1) { - sb.append(","); - } - } - this.categoryIds = sb.toString(); - } - } - - // 用于接收前端发送的分类ID字符串 - public void setCategoryIds(String categoryIds) { - this.categoryIds = categoryIds; - } + @Schema(description ="标签") + private String tags; } diff --git a/src/main/java/com/kexue/skills/entity/dto/CmsCategoryTagDto.java b/src/main/java/com/kexue/skills/entity/dto/CmsCategoryTagDto.java new file mode 100644 index 0000000..1a89c05 --- /dev/null +++ b/src/main/java/com/kexue/skills/entity/dto/CmsCategoryTagDto.java @@ -0,0 +1,28 @@ +package com.kexue.skills.entity.dto; + +import com.kexue.skills.entity.base.BaseQueryDto; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * (CmsCategoryTag)查询DTO + * + * @author 王志维 + * @since 2025-02-21 23:01:48 + */ +@Data +public class CmsCategoryTagDto extends BaseQueryDto { + + @Schema(description ="主键ID") + private Long id; + + @Schema(description ="分类ID") + private Long categoryId; + + @Schema(description ="标签ID") + private Long tagId; + + @Schema(description ="是否删除 :0 未删除,1已删除") + private Integer deleteFlag; + +} diff --git a/src/main/java/com/kexue/skills/entity/dto/CmsContentDto.java b/src/main/java/com/kexue/skills/entity/dto/CmsContentDto.java index 2589883..3593f38 100644 --- a/src/main/java/com/kexue/skills/entity/dto/CmsContentDto.java +++ b/src/main/java/com/kexue/skills/entity/dto/CmsContentDto.java @@ -44,4 +44,6 @@ public class CmsContentDto extends BaseQueryDto { private Long parentCategoryId; + private Long tagId; + } diff --git a/src/main/java/com/kexue/skills/entity/request/SkillGenRequest.java b/src/main/java/com/kexue/skills/entity/request/SkillGenRequest.java index 9b36a57..5c90734 100644 --- a/src/main/java/com/kexue/skills/entity/request/SkillGenRequest.java +++ b/src/main/java/com/kexue/skills/entity/request/SkillGenRequest.java @@ -1,22 +1,21 @@ package com.kexue.skills.entity.request; -import io.swagger.annotations.ApiModel; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.io.Serializable; +import java.util.List; -/** - * 技能生成请求参数 - * - * @author 维哥 - * @since 2026-01-28 - */ @Data -@ApiModel(value = "技能生成请求参数") public class SkillGenRequest implements Serializable { + private static final long serialVersionUID = 1L; - @Schema(description = "用户提示词") - private String prompt; - -} + @Schema(description = "技能名称") + private String name; + @Schema(description = "技能描述") + private String description; + @Schema(description = "技能标签") + private List tags; + @Schema(description = "技能内容ID(参照模板ID)") + private String contentId; +} \ No newline at end of file diff --git a/src/main/java/com/kexue/skills/entity/request/SkillPreGenRequest.java b/src/main/java/com/kexue/skills/entity/request/SkillPreGenRequest.java new file mode 100644 index 0000000..2fbe772 --- /dev/null +++ b/src/main/java/com/kexue/skills/entity/request/SkillPreGenRequest.java @@ -0,0 +1,25 @@ +package com.kexue.skills.entity.request; + +import io.swagger.annotations.ApiModel; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +/** + * 技能生成请求参数 + * + * @author 维哥 + * @since 2026-01-28 + */ +@Data +@ApiModel(value = "技能生成请求参数") +public class SkillPreGenRequest implements Serializable { + + @Schema(description = "用户提示词") + private String prompt; + + @Schema(description = "模板id") + private Long contentId; + +} diff --git a/src/main/java/com/kexue/skills/entity/request/SkillRequest.java b/src/main/java/com/kexue/skills/entity/request/SkillRequest.java index 587bd8f..4394997 100644 --- a/src/main/java/com/kexue/skills/entity/request/SkillRequest.java +++ b/src/main/java/com/kexue/skills/entity/request/SkillRequest.java @@ -32,7 +32,7 @@ public class SkillRequest implements Serializable { Message userMessage = new Message(); userMessage.setRole("user"); - userMessage.setContent("主题:我想要做一个将数据库设计表转换成sql schema语言并迁移到数据库服务器中的skill。请根据agent skills撰写规范帮我生成这个skill的名称、描述,并从以下标签列表中选择一个或者多个标签:\"软件开发,系统集成,网络工程,云计算,大数据,人工智能,物联网,区块链,信息安全,运维服务,测试认证,IT 咨询,外包服务,电商技术,移动开发,前端开发,后端开发,全栈开发,数据库管理\"。输出json格式,仅输出以上所提到的名称、描述、标签,节点名称分别为name、description、tags,节点内容以中文形式返回。"); + userMessage.setContent("主题:我想要做一个将数据库设计表转换成sql schema语言并迁移到数据库服务器中的skill。请根据agent skills撰写规范帮我生成这个skill的名称、描述,并从数据库中选择一个或者多个标签。输出json格式,仅输出以上所提到的名称、描述、标签,节点名称分别为name、description、tags,节点内容以中文形式返回。"); this.messages.add(userMessage); this.temperature = 0.3; @@ -43,7 +43,7 @@ public class SkillRequest implements Serializable { } } - public SkillRequest(boolean useDefaultSettings, String model, Double temperature, Integer maxTokens,String prompt) { + public SkillRequest(boolean useDefaultSettings, String model, Double temperature, Integer maxTokens, String prompt, String tagsList) { if (useDefaultSettings) { this.model = model; this.messages = new ArrayList<>(); @@ -55,7 +55,7 @@ public class SkillRequest implements Serializable { Message userMessage = new Message(); userMessage.setRole("user"); - userMessage.setContent("主题:"+ prompt +"。请根据agent skills撰写规范帮我生成这个skill的名称、描述,并从以下标签列表中选择一个或者多个标签:\"软件开发,系统集成,网络工程,云计算,大数据,人工智能,物联网,区块链,信息安全,运维服务,测试认证,IT 咨询,外包服务,电商技术,移动开发,前端开发,后端开发,全栈开发,数据库管理\"。输出json格式,仅输出以上所提到的名称、描述、标签,节点名称分别为name、description、tags,节点内容以中文形式返回。"); + userMessage.setContent("主题:"+ prompt +"。请根据agent skills撰写规范帮我生成这个skill的名称、描述,并从以下标签列表中选择一个或者多个标签:\"" + tagsList + "\"。输出json格式,仅输出以上所提到的名称、描述、标签,节点名称分别为name、description、tags,节点内容以中文形式返回,tags只需要返回序号数组"); this.messages.add(userMessage); this.temperature = temperature; @@ -66,6 +66,29 @@ public class SkillRequest implements Serializable { } } + public SkillRequest(boolean useDefaultSettings, String model, String systemContent,String userContent,Double temperature, Integer maxTokens,String type) { + if (useDefaultSettings) { + this.model = model; + this.messages = new ArrayList<>(); + + Message systemMessage = new Message(); + systemMessage.setRole("system"); + systemMessage.setContent(systemContent); + this.messages.add(systemMessage); + + Message userMessage = new Message(); + userMessage.setRole("user"); + userMessage.setContent(userContent); + this.messages.add(userMessage); + + this.temperature = temperature; + this.max_tokens = maxTokens; + + this.response_format = new ResponseFormat(); + this.response_format.setType(type); + } + } + public static SkillRequest createDefault() { return new SkillRequest(true); } diff --git a/src/main/java/com/kexue/skills/mapper/CmsCategoryTagMapper.java b/src/main/java/com/kexue/skills/mapper/CmsCategoryTagMapper.java new file mode 100644 index 0000000..36ac5ed --- /dev/null +++ b/src/main/java/com/kexue/skills/mapper/CmsCategoryTagMapper.java @@ -0,0 +1,100 @@ +package com.kexue.skills.mapper; + +import com.kexue.skills.entity.CmsCategoryTag; +import com.kexue.skills.entity.dto.CmsCategoryTagDto; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * (CmsCategoryTag)表数据库访问层 + * + * @author 王志维 + * @since 2025-02-21 23:01:48 + */ +@Mapper +public interface CmsCategoryTagMapper { + /** + * 分页查询 + * + * @param queryDto 筛选条件 + * @return 查询结果 + */ + List getPageList(CmsCategoryTagDto queryDto); + + /** + * 查询列表 + * + * @param queryDto 筛选条件 + * @return 查询结果 + */ + List getList(CmsCategoryTagDto queryDto); + + /** + * 通过ID查询单条数据 + * + * @param id 主键 + * @return 实例对象 + */ + CmsCategoryTag queryById(Long id); + + /** + * 新增数据 + * + * @param cmsCategoryTag 实例对象 + * @return 影响行数 + */ + int insert(CmsCategoryTag cmsCategoryTag); + + /** + * 更新数据 + * + * @param cmsCategoryTag 实例对象 + * @return 影响行数 + */ + int update(CmsCategoryTag cmsCategoryTag); + + /** + * 通过主键逻辑删除 + * + * @param id 主键 + * @param updateBy 更新人 + * @return 影响行数 + */ + int logicDeleteById(@Param("id") Long id, @Param("updateBy") String updateBy); + + /** + * 通过主键物理删除 + * + * @param id 主键 + * @return 影响行数 + */ + int deleteById(Long id); + + /** + * 根据分类ID删除关联 + * + * @param categoryId 分类ID + * @param updateBy 更新人 + * @return 影响行数 + */ + int deleteByCategoryId(@Param("categoryId") Long categoryId, @Param("updateBy") String updateBy); + + /** + * 根据标签ID删除关联 + * + * @param tagId 标签ID + * @param updateBy 更新人 + * @return 影响行数 + */ + int deleteByTagId(@Param("tagId") Long tagId, @Param("updateBy") String updateBy); + + /** + * 批量插入关联 + * + * @param categoryTagList 关联列表 + * @return 影响行数 + */ + int batchInsert(List categoryTagList); +} diff --git a/src/main/java/com/kexue/skills/mapper/CmsTagMapper.java b/src/main/java/com/kexue/skills/mapper/CmsTagMapper.java index 7e71c6e..0b44032 100644 --- a/src/main/java/com/kexue/skills/mapper/CmsTagMapper.java +++ b/src/main/java/com/kexue/skills/mapper/CmsTagMapper.java @@ -70,4 +70,12 @@ public interface CmsTagMapper { * @return 影响行数 */ int deleteById(Long tagId); + + /** + * 根据分类ID查询标签列表 + * + * @param categoryId 分类ID + * @return 标签列表 + */ + List getTagsByCategoryId(@Param("categoryId") Long categoryId); } \ No newline at end of file diff --git a/src/main/java/com/kexue/skills/service/CmsCategoryTagService.java b/src/main/java/com/kexue/skills/service/CmsCategoryTagService.java new file mode 100644 index 0000000..93f909b --- /dev/null +++ b/src/main/java/com/kexue/skills/service/CmsCategoryTagService.java @@ -0,0 +1,116 @@ +package com.kexue.skills.service; + +import com.github.pagehelper.PageInfo; +import com.kexue.skills.entity.CmsCategoryTag; +import com.kexue.skills.entity.dto.CmsCategoryTagDto; + +import java.util.List; + +/** + * (CmsCategoryTag)表服务接口 + * + * @author 王志维 + * @since 2025-02-21 23:01:48 + */ +public interface CmsCategoryTagService extends BaseService { + /** + * 分页查询 + * + * @param queryDto 筛选条件 + * @return 查询结果 + */ + PageInfo getPageList(CmsCategoryTagDto queryDto); + + /** + * 查询列表 + * + * @param queryDto 筛选条件 + * @return 查询结果 + */ + List getList(CmsCategoryTagDto queryDto); + + /** + * 通过主键查询单条数据 + * + * @param id 主键 + * @return 实例对象 + */ + CmsCategoryTag queryById(Long id); + + /** + * 新增数据 + * + * @param cmsCategoryTag 实例对象 + * @return 实例对象 + */ + CmsCategoryTag insert(CmsCategoryTag cmsCategoryTag); + + /** + * 更新数据 + * + * @param cmsCategoryTag 实例对象 + * @return 实例对象 + */ + CmsCategoryTag update(CmsCategoryTag cmsCategoryTag); + + /** + * 通过主键逻辑删除 + * + * @param id 主键 + * @param updateBy 更新人 + * @return 影响行数 + */ + int logicDeleteById(Long id, String updateBy); + + /** + * 通过主键物理删除 + * + * @param id 主键 + * @return 影响行数 + */ + int deleteById(Long id); + + /** + * 根据分类ID删除关联 + * + * @param categoryId 分类ID + * @param updateBy 更新人 + * @return 影响行数 + */ + int deleteByCategoryId(Long categoryId, String updateBy); + + /** + * 根据标签ID删除关联 + * + * @param tagId 标签ID + * @param updateBy 更新人 + * @return 影响行数 + */ + int deleteByTagId(Long tagId, String updateBy); + + /** + * 批量插入关联 + * + * @param categoryTagList 关联列表 + * @return 影响行数 + */ + int batchInsert(List categoryTagList); + + /** + * 批量设置分类标签关联 + * + * @param categoryId 分类ID + * @param tagIds 标签ID列表 + * @param updateBy 更新人 + * @return 影响行数 + */ + int batchSetCategoryTags(Long categoryId, List tagIds, String updateBy); + + /** + * 根据分类ID获取标签列表 + * + * @param categoryId 分类ID + * @return 标签列表 + */ + List getTagsByCategoryId(Long categoryId); +} diff --git a/src/main/java/com/kexue/skills/service/CmsTagService.java b/src/main/java/com/kexue/skills/service/CmsTagService.java index 40c8e5b..9537f22 100644 --- a/src/main/java/com/kexue/skills/service/CmsTagService.java +++ b/src/main/java/com/kexue/skills/service/CmsTagService.java @@ -69,4 +69,12 @@ public interface CmsTagService extends BaseService { * @return 影响行数 */ int deleteById(Long tagId); + + /** + * 根据分类ID查询标签列表 + * + * @param categoryId 分类ID + * @return 标签列表 + */ + List getTagsByCategoryId(Long categoryId); } \ No newline at end of file diff --git a/src/main/java/com/kexue/skills/service/SkillGenService.java b/src/main/java/com/kexue/skills/service/SkillGenService.java index 7b3c205..d1e9262 100644 --- a/src/main/java/com/kexue/skills/service/SkillGenService.java +++ b/src/main/java/com/kexue/skills/service/SkillGenService.java @@ -1,6 +1,8 @@ package com.kexue.skills.service; +import com.alibaba.fastjson.JSONObject; import com.kexue.skills.entity.request.SkillGenRequest; +import com.kexue.skills.entity.request.SkillPreGenRequest; import com.kexue.skills.entity.request.SkillAnalyzeRequest; import com.kexue.skills.entity.response.SkillResponse; @@ -18,7 +20,9 @@ public interface SkillGenService { * @param request 生成请求 * @return 生成结果 */ - SkillResponse generateSkill(SkillGenRequest request); + SkillResponse preGenerate(SkillPreGenRequest request); + + JSONObject generate(SkillGenRequest request); /** * 分析技能 diff --git a/src/main/java/com/kexue/skills/service/impl/CmsCategoryTagServiceImpl.java b/src/main/java/com/kexue/skills/service/impl/CmsCategoryTagServiceImpl.java new file mode 100644 index 0000000..97b6713 --- /dev/null +++ b/src/main/java/com/kexue/skills/service/impl/CmsCategoryTagServiceImpl.java @@ -0,0 +1,219 @@ +package com.kexue.skills.service.impl; + +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.kexue.skills.entity.CmsCategoryTag; +import com.kexue.skills.entity.CmsTag; +import com.kexue.skills.entity.dto.CmsCategoryTagDto; +import com.kexue.skills.entity.dto.CmsTagDto; +import com.kexue.skills.mapper.CmsCategoryTagMapper; +import com.kexue.skills.service.CmsCategoryTagService; +import com.kexue.skills.service.CmsTagService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * (CmsCategoryTag)表服务实现类 + * + * @author 王志维 + * @since 2025-02-21 23:01:48 + */ +@Service("cmsCategoryTagService") +@Transactional(rollbackFor = Exception.class) +public class CmsCategoryTagServiceImpl implements CmsCategoryTagService { + @Resource + private CmsCategoryTagMapper cmsCategoryTagMapper; + + @Resource + private CmsTagService cmsTagService; + + /** + * 分页查询 + * + * @param queryDto 筛选条件 + * @return 查询结果 + */ + @Override + public PageInfo getPageList(CmsCategoryTagDto queryDto) { + PageHelper.startPage(queryDto.getPageNum(), queryDto.getPageSize()); + List list = this.cmsCategoryTagMapper.getPageList(queryDto); + return new PageInfo<>(list); + } + + /** + * 查询列表 + * + * @param queryDto 筛选条件 + * @return 查询结果 + */ + @Override + public List getList(CmsCategoryTagDto queryDto) { + return this.cmsCategoryTagMapper.getList(queryDto); + } + + /** + * 通过主键查询单条数据 + * + * @param id 主键 + * @return 实例对象 + */ + @Override + public CmsCategoryTag queryById(Long id) { + return this.cmsCategoryTagMapper.queryById(id); + } + + /** + * 新增数据 + * + * @param cmsCategoryTag 实例对象 + * @return 实例对象 + */ + @Override + public CmsCategoryTag insert(CmsCategoryTag cmsCategoryTag) { + // 设置创建时间和更新时间 + Date now = new Date(); + cmsCategoryTag.setCreateTime(now); + cmsCategoryTag.setUpdateTime(now); + // 设置默认值 + cmsCategoryTag.setDeleteFlag(0); + // 保存数据 + this.cmsCategoryTagMapper.insert(cmsCategoryTag); + return cmsCategoryTag; + } + + /** + * 更新数据 + * + * @param cmsCategoryTag 实例对象 + * @return 实例对象 + */ + @Override + public CmsCategoryTag update(CmsCategoryTag cmsCategoryTag) { + // 设置更新时间 + cmsCategoryTag.setUpdateTime(new Date()); + // 更新数据 + this.cmsCategoryTagMapper.update(cmsCategoryTag); + return this.queryById(cmsCategoryTag.getId()); + } + + /** + * 通过主键逻辑删除 + * + * @param id 主键 + * @param updateBy 更新人 + * @return 影响行数 + */ + @Override + public int logicDeleteById(Long id, String updateBy) { + return this.cmsCategoryTagMapper.logicDeleteById(id, updateBy); + } + + /** + * 通过主键物理删除 + * + * @param id 主键 + * @return 影响行数 + */ + @Override + public int deleteById(Long id) { + return this.cmsCategoryTagMapper.deleteById(id); + } + + /** + * 根据分类ID删除关联 + * + * @param categoryId 分类ID + * @param updateBy 更新人 + * @return 影响行数 + */ + @Override + public int deleteByCategoryId(Long categoryId, String updateBy) { + return this.cmsCategoryTagMapper.deleteByCategoryId(categoryId, updateBy); + } + + /** + * 根据标签ID删除关联 + * + * @param tagId 标签ID + * @param updateBy 更新人 + * @return 影响行数 + */ + @Override + public int deleteByTagId(Long tagId, String updateBy) { + return this.cmsCategoryTagMapper.deleteByTagId(tagId, updateBy); + } + + /** + * 批量插入关联 + * + * @param categoryTagList 关联列表 + * @return 影响行数 + */ + @Override + public int batchInsert(List categoryTagList) { + if (categoryTagList == null || categoryTagList.isEmpty()) { + return 0; + } + // 设置默认值 + Date now = new Date(); + for (CmsCategoryTag tag : categoryTagList) { + tag.setCreateTime(now); + tag.setUpdateTime(now); + tag.setDeleteFlag(0); + } + return this.cmsCategoryTagMapper.batchInsert(categoryTagList); + } + + /** + * 批量设置分类标签关联 + * + * @param categoryId 分类ID + * @param tagIds 标签ID列表 + * @param updateBy 更新人 + * @return 影响行数 + */ + @Override + public int batchSetCategoryTags(Long categoryId, List tagIds, String updateBy) { + // 先删除该分类的所有关联 + int deleteCount = this.deleteByCategoryId(categoryId, updateBy); + + // 然后批量插入新的关联 + if (tagIds == null || tagIds.isEmpty()) { + return deleteCount; + } + + List categoryTagList = new ArrayList<>(); + Date now = new Date(); + for (Long tagId : tagIds) { + CmsCategoryTag categoryTag = new CmsCategoryTag(); + categoryTag.setCategoryId(categoryId); + categoryTag.setTagId(tagId); + categoryTag.setCreateTime(now); + categoryTag.setUpdateTime(now); + categoryTag.setCreateBy(updateBy); + categoryTag.setUpdateBy(updateBy); + categoryTag.setDeleteFlag(0); + categoryTagList.add(categoryTag); + } + + int insertCount = this.batchInsert(categoryTagList); + return deleteCount + insertCount; + } + + /** + * 根据分类ID获取标签列表 + * + * @param categoryId 分类ID + * @return 标签列表 + */ + @Override + public List getTagsByCategoryId(Long categoryId) { + // 直接使用SQL联合查询获取标签列表,提高效率 + return cmsTagService.getTagsByCategoryId(categoryId); + } +} diff --git a/src/main/java/com/kexue/skills/service/impl/CmsTagServiceImpl.java b/src/main/java/com/kexue/skills/service/impl/CmsTagServiceImpl.java index ebe20e2..5d900e1 100644 --- a/src/main/java/com/kexue/skills/service/impl/CmsTagServiceImpl.java +++ b/src/main/java/com/kexue/skills/service/impl/CmsTagServiceImpl.java @@ -122,4 +122,15 @@ public class CmsTagServiceImpl implements CmsTagService { public int deleteById(Long tagId) { return this.cmsTagMapper.deleteById(tagId); } + + /** + * 根据分类ID查询标签列表 + * + * @param categoryId 分类ID + * @return 标签列表 + */ + @Override + public List getTagsByCategoryId(Long categoryId) { + return this.cmsTagMapper.getTagsByCategoryId(categoryId); + } } \ No newline at end of file diff --git a/src/main/java/com/kexue/skills/service/impl/SkillGenServiceImpl.java b/src/main/java/com/kexue/skills/service/impl/SkillGenServiceImpl.java index aa24312..621e081 100644 --- a/src/main/java/com/kexue/skills/service/impl/SkillGenServiceImpl.java +++ b/src/main/java/com/kexue/skills/service/impl/SkillGenServiceImpl.java @@ -4,10 +4,14 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.kexue.skills.common.util.HttpUtil; import com.kexue.skills.config.DeepSeekConfig; +import com.kexue.skills.entity.CmsTag; +import com.kexue.skills.entity.dto.CmsTagDto; import com.kexue.skills.entity.request.SkillAnalyzeRequest; import com.kexue.skills.entity.request.SkillGenRequest; +import com.kexue.skills.entity.request.SkillPreGenRequest; import com.kexue.skills.entity.request.SkillRequest; import com.kexue.skills.entity.response.SkillResponse; +import com.kexue.skills.service.CmsTagService; import com.kexue.skills.service.SkillGenService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -27,6 +31,9 @@ public class SkillGenServiceImpl implements SkillGenService { @Autowired private DeepSeekConfig deepSeekConfig; + + @Autowired + private CmsTagService cmsTagService; /** * 生成技能 @@ -35,11 +42,29 @@ public class SkillGenServiceImpl implements SkillGenService { * @return 生成结果 */ @Override - public SkillResponse generateSkill(SkillGenRequest request) { + public SkillResponse preGenerate(SkillPreGenRequest request) { log.info("生成技能请求: {}", request); String url = deepSeekConfig.getBaseUrl() + "/v1/chat/completions"; + + // 从数据库中读取cms_tag表的标签信息 + CmsTagDto tagDto = new CmsTagDto(); + tagDto.setDeleteFlag(0); + tagDto.setStatus(1); + List tags = cmsTagService.getList(tagDto); + + // 将标签名称拼接成逗号分隔的字符串 + StringBuilder tagsList = new StringBuilder(); + for (int i = 0; i < tags.size(); i++) { + CmsTag tag = tags.get(i); + tagsList.append(tag.getTagId()+"."+tag.getTagName()); + if (i < tags.size() - 1) { + tagsList.append(","); + } + } + SkillRequest skillRequest = new SkillRequest(true, deepSeekConfig.getChat().getModel(), - deepSeekConfig.getChat().getTemperature(), deepSeekConfig.getChat().getMaxTokens(),request.getPrompt()); + deepSeekConfig.getChat().getTemperature(), deepSeekConfig.getChat().getMaxTokens(), + request.getPrompt(), tagsList.toString()); try { // 发送HTTP请求到deepseek API @@ -73,6 +98,45 @@ public class SkillGenServiceImpl implements SkillGenService { return null; } + @Override + public JSONObject generate(SkillGenRequest request) { + log.info("生成技能请求: {}", request); + String url = deepSeekConfig.getBaseUrl() + "/v1/chat/completions"; + + // 从数据库中读取cms_tag表的标签信息 + CmsTagDto tagDto = new CmsTagDto(); + tagDto.setDeleteFlag(0); + tagDto.setStatus(1); + List tags = cmsTagService.getList(tagDto); + + List tags1 = request.getTags(); + + // 将标签名称拼接成逗号分隔的字符串 + StringBuilder tagsList = new StringBuilder(); + for (int i = 0; i < tags.size(); i++) { + CmsTag tag = tags.get(i); + if (tags1.contains(tag.getTagId()+"")) { + tagsList.append(tag.getTagName()); + if (i < tags.size() - 1) { + tagsList.append(","); + } + } + } + String systemContent = "你是一个专业的AI技能设计助手。请基于用户提供的Skill名称、描述、标签,按照skills目录结构输出完整的skills内容,包括skills.md本体内容、scripts目录中的脚本等,并打包成一个YAML文件技能包。请严格遵循以下规范:1. 包含必需的文件和目录;2. 多行内容使用 | 字面块;3. 内容从行首开始;4. 空目录用 children: [] 表示;5. 文件内容要实际有用;6.输出一个完整的YAML文档。无需其他额外说明。"; + String userContent = "请根据以下Skill信息生成skills.md文档内容:Skill名称:SKILL_NAME,Skill描述:DESCRIPTION,Skill标签:TAGS 。"; + userContent = userContent.replace("SKILL_NAME", request.getName()).replace("DESCRIPTION", request.getDescription()).replace("TAGS", tagsList.toString()); + SkillRequest skillRequest = new SkillRequest(true, deepSeekConfig.getChat().getModel(),systemContent,userContent,deepSeekConfig.getChat().getTemperature(), 8192,"text"); + try { + // 发送HTTP请求到deepseek API + String deepseekResponse = HttpUtil.sendPostRequest(url, skillRequest, deepSeekConfig.getApiKey(), null); + log.info("Deepseek API响应: {}", deepseekResponse); + JSONObject responseJson = JSON.parseObject(deepseekResponse); + return responseJson; + } catch (Exception e) { + log.error("调用Deepseek API失败: {}", e.getMessage(), e); + } + return null; + } /** diff --git a/src/main/java/com/kexue/skills/service/impl/SysUserServiceImpl.java b/src/main/java/com/kexue/skills/service/impl/SysUserServiceImpl.java index 8830f13..610874f 100644 --- a/src/main/java/com/kexue/skills/service/impl/SysUserServiceImpl.java +++ b/src/main/java/com/kexue/skills/service/impl/SysUserServiceImpl.java @@ -503,7 +503,7 @@ public class SysUserServiceImpl implements SysUserService { */ private void saveLoginUserToRedis(String token, LoginUser loginUser) { redissonClient.getBucket("loginUser:" + token) - .set(cn.hutool.json.JSONUtil.toJsonStr(loginUser), 3600, java.util.concurrent.TimeUnit.SECONDS); + .set(cn.hutool.json.JSONUtil.toJsonStr(loginUser), 86400, java.util.concurrent.TimeUnit.SECONDS); } /** @@ -804,7 +804,7 @@ public class SysUserServiceImpl implements SysUserService { loginUser.setToken(token); // 将LoginUser对象存储到Redis缓存中,使用token作为key - redissonClient.getBucket("loginUser:" + token).set(cn.hutool.json.JSONUtil.toJsonStr(loginUser), 3600, java.util.concurrent.TimeUnit.SECONDS); + redissonClient.getBucket("loginUser:" + token).set(cn.hutool.json.JSONUtil.toJsonStr(loginUser), 86400, java.util.concurrent.TimeUnit.SECONDS); // 创建LoginUserDto返回对象 LoginUserDto sysUserDto = buildLoginUserDto(loginUser); diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 21cb56e..63523b5 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -2,7 +2,7 @@ server: port: 19001 servlet: session: - timeout: 7200s + timeout: 86400s spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver @@ -14,14 +14,27 @@ spring: maximum-pool-size: 12 connection-timeout: 60000 connection-test-query: SELECT 1 + # Redis配置,引用公共配置 + redis: + host: ${common.redis.host} + port: ${common.redis.port} + password: ${common.redis.password} + database: ${common.redis.database} + timeout: 10000 + lettuce: + pool: + max-active: 8 + max-wait: -1 + max-idle: 8 + min-idle: 0 # Sa-Token配置 sa-token: # token名称 token-name: Authorization - # token有效期(默认30天,单位:秒) - timeout: 2592000 + # token有效期(默认1天,单位:秒) + timeout: 86400 # token过期后是否允许续期 is-concurrent: true # 是否允许同一账号多地登录 @@ -34,16 +47,16 @@ sa-token: is-header: true # 是否使用Redis存储token is-redis: true - # Redis配置 + # Redis配置,引用公共配置 redis: # Redis主机地址 - host: 127.0.0.1 + host: ${common.redis.host} # Redis端口 - port: 6379 + port: ${common.redis.port} # Redis密码 - password: + password: ${common.redis.password} # Redis数据库索引 - database: 1 + database: ${common.redis.database} # 验证码配置 captcha: @@ -77,13 +90,14 @@ jetcache: minIdle: 5 maxIdle: 20 maxTotal: 50 - host: 127.0.0.1 - port: 6379 - database: 1 + host: ${common.redis.host} + port: ${common.redis.port} + password: ${common.redis.password} + database: ${common.redis.database} # 全局过期时间配置 global: # 全局默认超时时间(毫秒) - default-expire-in: 3600000 + default-expire-in: 86400000 # 全局统计间隔(毫秒) stat-interval-millis: 60000 diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index 39fd501..8e73bd8 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -2,7 +2,7 @@ server: port: 19000 servlet: session: - timeout: 7200s + timeout: 86400s spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver @@ -30,8 +30,8 @@ spring: sa-token: # token名称 token-name: Authorization - # token有效期(默认30天,单位:秒) - timeout: 2592000 + # token有效期(默认1天,单位:秒) + timeout: 86400 # token过期后是否允许续期 is-concurrent: true # 是否允许同一账号多地登录 @@ -94,10 +94,10 @@ jetcache: # 全局过期时间配置 global: # 全局默认超时时间(毫秒) - default-expire-in: 3600000 + default-expire-in: 86400000 # 全局统计间隔(毫秒) stat-interval-millis: 60000 web: upload: - path: /data/service/hyxp-portal/upload/ + path: /kexue/agent-skills/upload/ diff --git a/src/main/resources/mapper/CmsCategoryTagMapper.xml b/src/main/resources/mapper/CmsCategoryTagMapper.xml new file mode 100644 index 0000000..fbe761d --- /dev/null +++ b/src/main/resources/mapper/CmsCategoryTagMapper.xml @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + insert into cms_category_tag(category_id, tag_id, create_time, update_time, create_by, update_by, delete_flag) + values (#{categoryId}, #{tagId}, #{createTime}, #{updateTime}, #{createBy}, #{updateBy}, #{deleteFlag}) + + + + + update cms_category_tag + + + category_id = #{categoryId}, + + + tag_id = #{tagId}, + + + update_time = #{updateTime}, + + + update_by = #{updateBy}, + + + where id = #{id} + + + + + update cms_category_tag + set delete_flag = 1, update_by = #{updateBy}, update_time = now() + where id = #{id} + + + + + delete from cms_category_tag where id = #{id} + + + + + update cms_category_tag + set delete_flag = 1, update_by = #{updateBy}, update_time = now() + where category_id = #{categoryId} + + + + + update cms_category_tag + set delete_flag = 1, update_by = #{updateBy}, update_time = now() + where tag_id = #{tagId} + + + + + insert into cms_category_tag(category_id, tag_id, create_time, update_time, create_by, update_by, delete_flag) + values + + (#{item.categoryId}, #{item.tagId}, #{item.createTime}, #{item.updateTime}, #{item.createBy}, #{item.updateBy}, #{item.deleteFlag}) + + + + diff --git a/src/main/resources/mapper/CmsContentMapper.xml b/src/main/resources/mapper/CmsContentMapper.xml index 4ab92fd..24d6f3d 100644 --- a/src/main/resources/mapper/CmsContentMapper.xml +++ b/src/main/resources/mapper/CmsContentMapper.xml @@ -6,9 +6,7 @@ - - @@ -38,14 +36,16 @@ + + @@ -53,9 +53,9 @@ select - content_id, title, subtitle, parent_category_id, content_type, category_ids, summary, content, cover_image, author_id, author_name, + content_id, title, subtitle, content_type, summary, content, cover_image, author_id, author_name, reviewer_id, reviewer_name, audit_status, audit_comment, publish_status, publish_time, - view_count, like_count, comment_count, sort, is_paid, price, required_points, support_points_pay, is_official, share_count, file_url, icon, background, create_time, update_time, create_by, update_by, delete_flag + view_count, like_count, comment_count, sort, is_paid, price, required_points, support_points_pay, is_official, share_count, file_url, icon, background, origin, tags, create_time, update_time, create_by, update_by, delete_flag from cms_content @@ -130,19 +117,6 @@ and content_type = #{contentType} - - and find_in_set(#{categoryId}, category_ids) - - - - find_in_set(#{catId}, category_ids) - - - - - find_in_set(#{catId}, category_ids) - - and author_id = #{authorId} @@ -158,8 +132,8 @@ and is_official = #{isOfficial} - - and parent_category_id = #{parentCategoryId} + + and find_in_set(#{tagId}, tags) order by sort asc, create_time desc @@ -167,12 +141,12 @@ - insert into cms_content(title, subtitle, parent_category_id, content_type, category_ids, summary, content, cover_image, author_id, author_name, + insert into cms_content(title, subtitle, content_type, summary, content, cover_image, author_id, author_name, reviewer_id, reviewer_name, audit_status, audit_comment, publish_status, publish_time, - view_count, like_count, comment_count, sort, is_paid, price, required_points, support_points_pay, is_official, share_count, file_url, icon, background, create_time, update_time, create_by, update_by, delete_flag) - values (#{title}, #{subtitle}, #{parentCategoryId}, #{contentType}, #{categoryIds}, #{summary}, #{content}, #{coverImage}, #{authorId}, #{authorName}, + view_count, like_count, comment_count, sort, is_paid, price, required_points, support_points_pay, is_official, share_count, file_url, icon, background, origin, tags, create_time, update_time, create_by, update_by, delete_flag) + values (#{title}, #{subtitle}, #{contentType}, #{summary}, #{content}, #{coverImage}, #{authorId}, #{authorName}, #{reviewerId}, #{reviewerName}, #{auditStatus}, #{auditComment}, #{publishStatus}, #{publishTime}, - #{viewCount}, #{likeCount}, #{commentCount}, #{sort}, #{isPaid}, #{price}, #{requiredPoints}, #{supportPointsPay}, #{isOfficial}, #{shareCount}, #{fileUrl}, #{icon}, #{background}, #{createTime}, #{updateTime}, #{createBy}, #{updateBy}, #{deleteFlag}) + #{viewCount}, #{likeCount}, #{commentCount}, #{sort}, #{isPaid}, #{price}, #{requiredPoints}, #{supportPointsPay}, #{isOfficial}, #{shareCount}, #{fileUrl}, #{icon}, #{background}, #{origin}, #{tags}, #{createTime}, #{updateTime}, #{createBy}, #{updateBy}, #{deleteFlag}) @@ -185,15 +159,9 @@ subtitle = #{subtitle}, - - parent_category_id = #{parentCategoryId}, - content_type = #{contentType}, - - category_ids = #{categoryIds}, - summary = #{summary}, @@ -266,6 +234,12 @@ background = #{background}, + + origin = #{origin}, + + + tags = #{tags}, + update_time = #{updateTime}, diff --git a/src/main/resources/mapper/CmsTagMapper.xml b/src/main/resources/mapper/CmsTagMapper.xml index d502279..4d632ff 100644 --- a/src/main/resources/mapper/CmsTagMapper.xml +++ b/src/main/resources/mapper/CmsTagMapper.xml @@ -111,4 +111,14 @@ delete from cms_tag where tag_id = #{tagId} + + + \ No newline at end of file