feat(content): 添加skill管理和支付配置功能
- 添加GLM大模型配置支持 - 配置生产环境Redis连接信息 - 更新支付回调URL路径配置 - 添加微信和支付宝支付配置到生产环境 - 修改异常处理器捕获BizException - 添加内容详情、需求说明和介绍字段 - 将内容管理重命名为skill管理 - 添加取消收藏功能接口 - 添加用户历史查看、收藏、购买和创建内容列表接口 - 实现用户行为统计和个性化内容推荐功能 - 更新数据库映射文件以支持新字段和查询功能
This commit is contained in:
parent
e16fbdf2d6
commit
11bc1959f0
|
|
@ -0,0 +1,5 @@
|
|||
-- 修改payment_order表,为pay_type字段添加默认值
|
||||
ALTER TABLE `payment_order` MODIFY COLUMN `pay_type` tinyint(1) NOT NULL DEFAULT 1 COMMENT '支付方式:1.微信 2.支付宝';
|
||||
|
||||
-- 输出修改结果
|
||||
SELECT '修改payment_order表pay_type字段默认值完成' AS result;
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
package com.kexue.skills.common;
|
||||
|
||||
import com.kexue.skills.entity.request.LoginUser;
|
||||
import com.kexue.skills.mapper.*;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* LoginUser缓存工具类
|
||||
* 用于更新Redis中的LoginUser对象
|
||||
*/
|
||||
@Component
|
||||
public class LoginUserCacheUtil {
|
||||
|
||||
@Resource
|
||||
private RedissonClient redissonClient;
|
||||
|
||||
@Resource
|
||||
private CmsContentLikeMapper cmsContentLikeMapper;
|
||||
|
||||
@Resource
|
||||
private CmsContentViewMapper cmsContentViewMapper;
|
||||
|
||||
@Resource
|
||||
private CmsContentMapper cmsContentMapper;
|
||||
|
||||
@Resource
|
||||
private ContentPurchaseMapper contentPurchaseMapper;
|
||||
|
||||
/**
|
||||
* 更新用户的收藏列表
|
||||
*
|
||||
* @param token 用户token
|
||||
* @param userId 用户ID
|
||||
*/
|
||||
public void updateFavorites(String token, Long userId) {
|
||||
updateLoginUserList(token, userId, "favorites", () -> cmsContentLikeMapper.queryRecentLikesByUserId(userId, 20));
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户的查看历史列表
|
||||
*
|
||||
* @param token 用户token
|
||||
* @param userId 用户ID
|
||||
*/
|
||||
public void updateHistory(String token, Long userId) {
|
||||
updateLoginUserList(token, userId, "history", () -> cmsContentViewMapper.queryRecentViewsByUserId(userId, 20));
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户的创建记录列表
|
||||
*
|
||||
* @param token 用户token
|
||||
* @param userId 用户ID
|
||||
*/
|
||||
public void updateCreate(String token, Long userId) {
|
||||
updateLoginUserList(token, userId, "create", () -> cmsContentMapper.queryRecentCreatedByUserId(userId, 20));
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新用户的购买记录列表
|
||||
*
|
||||
* @param token 用户token
|
||||
* @param userId 用户ID
|
||||
*/
|
||||
public void updateHas(String token, Long userId) {
|
||||
updateLoginUserList(token, userId, "has", () -> {
|
||||
List<Long> has = new ArrayList<>();
|
||||
try {
|
||||
com.kexue.skills.entity.dto.ContentPurchaseDto purchaseDto = new com.kexue.skills.entity.dto.ContentPurchaseDto();
|
||||
purchaseDto.setUserId(userId);
|
||||
List<com.kexue.skills.entity.ContentPurchase> purchases = contentPurchaseMapper.getList(purchaseDto);
|
||||
if (purchases != null && !purchases.isEmpty()) {
|
||||
java.util.LinkedHashSet<Long> contentIdSet = new java.util.LinkedHashSet<>();
|
||||
for (com.kexue.skills.entity.ContentPurchase purchase : purchases) {
|
||||
if (contentIdSet.size() < 20) {
|
||||
contentIdSet.add(purchase.getContentId());
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
has.addAll(contentIdSet);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
has = java.util.Collections.emptyList();
|
||||
}
|
||||
return has;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新LoginUser中的列表属性
|
||||
*
|
||||
* @param token 用户token
|
||||
* @param userId 用户ID
|
||||
* @param fieldName 字段名
|
||||
* @param supplier 列表数据提供者
|
||||
*/
|
||||
private void updateLoginUserList(String token, Long userId, String fieldName, java.util.function.Supplier<List<Long>> supplier) {
|
||||
try {
|
||||
String key = "loginUser:" + token;
|
||||
Object loginUserObj = redissonClient.getBucket(key).get();
|
||||
if (loginUserObj != null) {
|
||||
String loginUserJson = loginUserObj.toString();
|
||||
com.kexue.skills.entity.request.LoginUser loginUser = com.alibaba.fastjson.JSON.parseObject(loginUserJson, com.kexue.skills.entity.request.LoginUser.class);
|
||||
|
||||
if (loginUser != null && loginUser.getUserInfo() != null && loginUser.getUserInfo().getUserId().equals(userId)) {
|
||||
List<Long> list = supplier.get();
|
||||
|
||||
switch (fieldName) {
|
||||
case "favorites":
|
||||
loginUser.setFavorites(list);
|
||||
break;
|
||||
case "history":
|
||||
loginUser.setHistory(list);
|
||||
break;
|
||||
case "create":
|
||||
loginUser.setCreate(list);
|
||||
break;
|
||||
case "has":
|
||||
loginUser.setHas(list);
|
||||
break;
|
||||
}
|
||||
|
||||
// 写回Redis
|
||||
redissonClient.getBucket(key).set(com.alibaba.fastjson.JSON.toJSONString(loginUser));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从请求中获取token
|
||||
*
|
||||
* @return token
|
||||
*/
|
||||
public String getTokenFromRequest() {
|
||||
org.springframework.web.context.request.RequestAttributes requestAttributes = org.springframework.web.context.request.RequestContextHolder.getRequestAttributes();
|
||||
if (requestAttributes != null && requestAttributes instanceof org.springframework.web.context.request.ServletRequestAttributes) {
|
||||
HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
|
||||
if (request != null) {
|
||||
return request.getHeader("Authorization");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前登录用户ID
|
||||
*
|
||||
* @return 用户ID
|
||||
*/
|
||||
public Long getCurrentUserId() {
|
||||
try {
|
||||
Object loginId = cn.dev33.satoken.stp.StpUtil.getLoginId();
|
||||
return Long.parseLong(loginId.toString());
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
package com.kexue.skills.config;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* GLM API配置类
|
||||
*
|
||||
* @author 维哥
|
||||
* @since 2026-02-27
|
||||
*/
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "spring.ai.glm")
|
||||
public class GlmConfig {
|
||||
|
||||
private String baseUrl;
|
||||
private String apiKey;
|
||||
private ChatOptions chat;
|
||||
|
||||
public static class ChatOptions {
|
||||
private String model;
|
||||
private Double temperature;
|
||||
private Integer maxTokens;
|
||||
|
||||
public String getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
public void setModel(String model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
public Double getTemperature() {
|
||||
return temperature;
|
||||
}
|
||||
|
||||
public void setTemperature(Double temperature) {
|
||||
this.temperature = temperature;
|
||||
}
|
||||
|
||||
public Integer getMaxTokens() {
|
||||
return maxTokens;
|
||||
}
|
||||
|
||||
public void setMaxTokens(Integer maxTokens) {
|
||||
this.maxTokens = maxTokens;
|
||||
}
|
||||
}
|
||||
|
||||
public String getBaseUrl() {
|
||||
return baseUrl;
|
||||
}
|
||||
|
||||
public void setBaseUrl(String baseUrl) {
|
||||
this.baseUrl = baseUrl;
|
||||
}
|
||||
|
||||
public String getApiKey() {
|
||||
return apiKey;
|
||||
}
|
||||
|
||||
public void setApiKey(String apiKey) {
|
||||
this.apiKey = apiKey;
|
||||
}
|
||||
|
||||
public ChatOptions getChat() {
|
||||
return chat;
|
||||
}
|
||||
|
||||
public void setChat(ChatOptions chat) {
|
||||
this.chat = chat;
|
||||
}
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ import javax.annotation.Resource;
|
|||
*/
|
||||
@RestController
|
||||
@RequestMapping("api/cmsContent")
|
||||
@Tag(name = "内容(skills)管理 Api")
|
||||
@Tag(name = "skill(skills)管理 Api")
|
||||
@CrossOrigin(origins = "*")
|
||||
public class CmsContentController {
|
||||
/**
|
||||
|
|
@ -60,7 +60,7 @@ public class CmsContentController {
|
|||
* @return 单条数据
|
||||
*/
|
||||
@PostMapping("queryById/{contentId}")
|
||||
@Operation(summary = "通过ID查询内容", description = "通过ID查询内容")
|
||||
@Operation(summary = "通过ID查询skill", description = "通过ID查询skill")
|
||||
public CommonResult<CmsContent> queryById(@PathVariable("contentId") Long contentId) {
|
||||
// 增加阅读量
|
||||
cmsContentService.increaseViewCount(contentId);
|
||||
|
|
@ -74,7 +74,7 @@ public class CmsContentController {
|
|||
* @return 新增结果
|
||||
*/
|
||||
@PostMapping("/insert")
|
||||
@Operation(summary = "新增内容", description = "新增内容")
|
||||
@Operation(summary = "新增skill", description = "新增skill")
|
||||
@RequireAuth
|
||||
public CommonResult<CmsContent> insert(@RequestBody CmsContent cmsContent) {
|
||||
return CommonResult.success(cmsContentService.insert(cmsContent));
|
||||
|
|
@ -87,7 +87,7 @@ public class CmsContentController {
|
|||
* @return 编辑结果
|
||||
*/
|
||||
@PostMapping("/update")
|
||||
@Operation(summary = "更新内容", description = "更新内容")
|
||||
@Operation(summary = "更新skill", description = "更新skill")
|
||||
@RequireAuth
|
||||
public CommonResult<CmsContent> update(@RequestBody CmsContent cmsContent) {
|
||||
return CommonResult.success(cmsContentService.update(cmsContent));
|
||||
|
|
@ -96,7 +96,7 @@ public class CmsContentController {
|
|||
/**
|
||||
* 更新审核状态
|
||||
*
|
||||
* @param contentId 内容ID
|
||||
* @param contentId skillID
|
||||
* @param auditStatus 审核状态
|
||||
* @param reviewerId 审核人ID
|
||||
* @param reviewerName 审核人名称
|
||||
|
|
@ -117,7 +117,7 @@ public class CmsContentController {
|
|||
/**
|
||||
* 更新发布状态
|
||||
*
|
||||
* @param contentId 内容ID
|
||||
* @param contentId skillID
|
||||
* @param publishStatus 发布状态
|
||||
* @param publishTime 发布时间
|
||||
* @param updateBy 更新人
|
||||
|
|
@ -136,7 +136,7 @@ public class CmsContentController {
|
|||
/**
|
||||
* 增加阅读量
|
||||
*
|
||||
* @param contentId 内容ID
|
||||
* @param contentId skillID
|
||||
* @return 增加结果
|
||||
*/
|
||||
@PostMapping("/increaseViewCount/{contentId}")
|
||||
|
|
@ -152,7 +152,7 @@ public class CmsContentController {
|
|||
* @return 删除数据
|
||||
*/
|
||||
@PostMapping("/logicDeleteById")
|
||||
@Operation(summary = "逻辑删除内容", description = "逻辑删除内容")
|
||||
@Operation(summary = "逻辑删除skill", description = "逻辑删除skill")
|
||||
@RequireAuth
|
||||
public CommonResult<Boolean> logicDeleteById(@RequestBody IdDto idDto) {
|
||||
return CommonResult.success(cmsContentService.logicDeleteById(idDto.getId(), "admin") > 0);
|
||||
|
|
@ -165,7 +165,7 @@ public class CmsContentController {
|
|||
* @return 删除数据
|
||||
*/
|
||||
@PostMapping("deleteById/{contentId}")
|
||||
@Operation(summary = "物理删除内容", description = "物理删除内容")
|
||||
@Operation(summary = "物理删除skill", description = "物理删除skill")
|
||||
@RequireAuth
|
||||
public CommonResult<Boolean> deleteById(@PathVariable("contentId") Long contentId) {
|
||||
return CommonResult.success(cmsContentService.deleteById(contentId) > 0);
|
||||
|
|
@ -174,26 +174,91 @@ public class CmsContentController {
|
|||
/**
|
||||
* 添加收藏
|
||||
*
|
||||
* @param contentId 内容ID
|
||||
* @param contentId skillID
|
||||
* @return 操作结果
|
||||
*/
|
||||
@PostMapping("/addFavorite")
|
||||
@Operation(summary = "添加收藏", description = "添加内容收藏")
|
||||
@Operation(summary = "添加收藏", description = "添加skill收藏")
|
||||
@RequireAuth
|
||||
public CommonResult<Boolean> addFavorite(@RequestParam("contentId") Long contentId) {
|
||||
return CommonResult.success(cmsContentService.addFavorite(contentId) > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消收藏
|
||||
*
|
||||
* @param contentId skillID
|
||||
* @return 操作结果
|
||||
*/
|
||||
@PostMapping("/removeFavorite")
|
||||
@Operation(summary = "取消收藏", description = "取消skill收藏")
|
||||
@RequireAuth
|
||||
public CommonResult<Boolean> removeFavorite(@RequestParam("contentId") Long contentId) {
|
||||
return CommonResult.success(cmsContentService.removeFavorite(contentId) > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加查看记录
|
||||
*
|
||||
* @param contentId 内容ID
|
||||
* @param contentId skillID
|
||||
* @return 操作结果
|
||||
*/
|
||||
@PostMapping("/addView")
|
||||
@Operation(summary = "添加查看记录", description = "添加内容查看记录")
|
||||
@Operation(summary = "添加查看记录", description = "添加skill查看记录")
|
||||
@RequireAuth
|
||||
public CommonResult<Boolean> addView(@RequestParam("contentId") Long contentId) {
|
||||
return CommonResult.success(cmsContentService.addView(contentId) > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户历史查看的内容列表
|
||||
*
|
||||
* @param queryDto 筛选条件,包含分页信息
|
||||
* @return 查询结果
|
||||
*/
|
||||
@PostMapping("/getUserHistory")
|
||||
@Operation(summary = "获取用户历史查看", description = "获取当前用户历史查看的内容列表,带分页")
|
||||
@RequireAuth
|
||||
public CommonResult<PageInfo<CmsContent>> getUserHistory(@RequestBody CmsContentDto queryDto) {
|
||||
return CommonResult.success(cmsContentService.getPageListByUserHistory(queryDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户收藏的内容列表
|
||||
*
|
||||
* @param queryDto 筛选条件,包含分页信息
|
||||
* @return 查询结果
|
||||
*/
|
||||
@PostMapping("/getUserFavorites")
|
||||
@Operation(summary = "获取用户收藏", description = "获取当前用户收藏的内容列表,带分页")
|
||||
@RequireAuth
|
||||
public CommonResult<PageInfo<CmsContent>> getUserFavorites(@RequestBody CmsContentDto queryDto) {
|
||||
return CommonResult.success(cmsContentService.getPageListByUserFavorites(queryDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户购买的内容列表
|
||||
*
|
||||
* @param queryDto 筛选条件,包含分页信息
|
||||
* @return 查询结果
|
||||
*/
|
||||
@PostMapping("/getUserPurchases")
|
||||
@Operation(summary = "获取用户拥有", description = "获取当前用户购买的内容列表,带分页")
|
||||
@RequireAuth
|
||||
public CommonResult<PageInfo<CmsContent>> getUserPurchases(@RequestBody CmsContentDto queryDto) {
|
||||
return CommonResult.success(cmsContentService.getPageListByUserPurchases(queryDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户创建的内容列表
|
||||
*
|
||||
* @param queryDto 筛选条件,包含分页信息和发布状态
|
||||
* @return 查询结果
|
||||
*/
|
||||
@PostMapping("/getUserCreated")
|
||||
@Operation(summary = "获取用户创建", description = "获取当前用户创建的内容列表,带分页,可查询已发布、未发布")
|
||||
@RequireAuth
|
||||
public CommonResult<PageInfo<CmsContent>> getUserCreated(@RequestBody CmsContentDto queryDto) {
|
||||
return CommonResult.success(cmsContentService.getPageListByUserCreated(queryDto));
|
||||
}
|
||||
}
|
||||
|
|
@ -39,6 +39,8 @@ public class PayController {
|
|||
@PostMapping("/wx/create")
|
||||
public CommonResult<Map<String, String>> createWechatPay(@RequestBody PaymentOrder order) {
|
||||
try {
|
||||
// 设置支付类型为微信支付(1)
|
||||
order.setPayType(1);
|
||||
// 创建支付订单
|
||||
PaymentOrder createdOrder = paymentOrderService.createPaymentOrder(order);
|
||||
// 生成微信支付参数
|
||||
|
|
@ -56,7 +58,7 @@ public class PayController {
|
|||
* @return 回调响应
|
||||
*/
|
||||
@Operation(summary = "处理微信支付回调", description = "处理微信支付回调")
|
||||
@PostMapping("/pay/wx/notify")
|
||||
@PostMapping("/wx/notify")
|
||||
public String handleWechatPayNotify(HttpServletRequest request) {
|
||||
return payService.handleWechatPayNotify(request);
|
||||
}
|
||||
|
|
@ -70,6 +72,8 @@ public class PayController {
|
|||
@PostMapping("/alipay/create")
|
||||
public CommonResult<String> createAlipay(@RequestBody PaymentOrder order) {
|
||||
try {
|
||||
// 设置支付类型为支付宝(2)
|
||||
order.setPayType(2);
|
||||
// 创建支付订单
|
||||
PaymentOrder createdOrder = paymentOrderService.createPaymentOrder(order);
|
||||
// 生成支付宝支付表单
|
||||
|
|
@ -87,7 +91,7 @@ public class PayController {
|
|||
* @return 回调响应
|
||||
*/
|
||||
@Operation(summary = "处理支付宝支付回调", description = "处理支付宝支付回调")
|
||||
@PostMapping("/ali-pay/trade/notify")
|
||||
@PostMapping("/alipay/trade/notify")
|
||||
public String handleAlipayNotify(HttpServletRequest request) {
|
||||
return payService.handleAlipayNotify(request);
|
||||
}
|
||||
|
|
@ -98,7 +102,7 @@ public class PayController {
|
|||
* @return 同步回调响应
|
||||
*/
|
||||
@Operation(summary = "处理支付宝支付同步回调", description = "处理支付宝支付同步回调")
|
||||
@GetMapping("/ali-pay/trade/return")
|
||||
@GetMapping("/alipay/trade/return")
|
||||
public CommonResult<Map<String, Object>> handleAlipayReturn(HttpServletRequest request) {
|
||||
Map<String, Object> result = payService.handleAlipayReturn(request);
|
||||
if (result.get("success").equals(true)) {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ package com.kexue.skills.controller;
|
|||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.kexue.skills.common.CommonResult;
|
||||
import com.kexue.skills.entity.CmsContent;
|
||||
import com.kexue.skills.entity.request.GenIntroduceRequest;
|
||||
import com.kexue.skills.entity.request.SkillGenRequest;
|
||||
import com.kexue.skills.entity.request.SkillPreGenRequest;
|
||||
import com.kexue.skills.entity.response.SkillResponse;
|
||||
|
|
@ -32,14 +34,26 @@ public class SkillGenController {
|
|||
* @return 生成结果
|
||||
*/
|
||||
@PostMapping("/preGenerate")
|
||||
@Operation(summary = "生成技能", description = "生成技能")
|
||||
@Operation(summary = "预生成技能", description = "生成技能")
|
||||
public CommonResult<SkillResponse> preGenerate(@RequestBody SkillPreGenRequest request) {
|
||||
return CommonResult.success(skillGenService.preGenerate(request));
|
||||
return CommonResult.success(skillGenService.preGenerateV2(request));
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成技能V2
|
||||
*
|
||||
* @param request 生成请求
|
||||
* @return 生成结果
|
||||
*/
|
||||
@PostMapping("/preGenerateV2")
|
||||
@Operation(summary = "预生成技能V2", description = "使用新模型生成技能")
|
||||
public CommonResult<SkillResponse> preGenerateV2(@RequestBody SkillPreGenRequest request) {
|
||||
return CommonResult.success(skillGenService.preGenerateV2(request));
|
||||
}
|
||||
|
||||
@PostMapping("/generate")
|
||||
@Operation(summary = "生成Skill对应的md文件", description = "生成Skill对应的md文件")
|
||||
public CommonResult<JSONObject> generate(@RequestBody SkillGenRequest request) {
|
||||
@Operation(summary = "生成技能", description = "生成技能")
|
||||
public CommonResult<CmsContent> generate(@RequestBody SkillGenRequest request) {
|
||||
return CommonResult.success(skillGenService.generate(request));
|
||||
}
|
||||
|
||||
|
|
@ -54,4 +68,16 @@ public class SkillGenController {
|
|||
public CommonResult<String> analyze(@RequestBody com.kexue.skills.entity.request.SkillAnalyzeRequest request) {
|
||||
return CommonResult.success(skillGenService.analyzeSkill(request));
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成技能介绍
|
||||
*
|
||||
* @param request 技能内容
|
||||
* @return 技能介绍
|
||||
*/
|
||||
@PostMapping("/genIntroduce")
|
||||
@Operation(summary = "生成技能介绍", description = "生成技能介绍")
|
||||
public CommonResult<String> genIntroduce(@RequestBody GenIntroduceRequest request) {
|
||||
return CommonResult.success(skillGenService.genIntroduce(request.getContent()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,9 +30,6 @@ public class CmsContent extends BaseEntity implements Serializable {
|
|||
@Schema(description ="是否是官方:0否,1是")
|
||||
private Boolean isOfficial;
|
||||
|
||||
@Schema(description ="分类ID列表,逗号分隔")
|
||||
private String categoryIds;
|
||||
|
||||
@Schema(description ="图标")
|
||||
private String icon;
|
||||
|
||||
|
|
@ -45,6 +42,15 @@ public class CmsContent extends BaseEntity implements Serializable {
|
|||
@Schema(description ="内容摘要")
|
||||
private String summary;
|
||||
|
||||
@Schema(description ="详细描述")
|
||||
private String description;
|
||||
|
||||
@Schema(description ="需求说明")
|
||||
private String requirement;
|
||||
|
||||
@Schema(description ="介绍信息")
|
||||
private String introduce;
|
||||
|
||||
@Schema(description ="分享数量")
|
||||
private Integer shareCount;
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,9 @@ public class CmsTag extends BaseEntity implements Serializable {
|
|||
@Schema(description ="状态(1启用,2禁用)")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description ="标签图标")
|
||||
private String icon;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description ="创建时间")
|
||||
private Date createTime;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ public class CmsTagDto extends BaseQueryDto {
|
|||
|
||||
private Integer status;
|
||||
|
||||
private String icon;
|
||||
|
||||
private Integer deleteFlag;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
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 GenIntroduceRequest implements Serializable {
|
||||
|
||||
@Schema(description = "yaml或者skill.md内容", required = true)
|
||||
private String content;
|
||||
|
||||
}
|
||||
|
|
@ -16,6 +16,6 @@ public class SkillGenRequest implements Serializable {
|
|||
private String description;
|
||||
@Schema(description = "技能标签")
|
||||
private List<String> tags;
|
||||
@Schema(description = "技能内容ID(参照模板ID)")
|
||||
private String contentId;
|
||||
@Schema(description = "需求说明")
|
||||
private String requirement;
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
|||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 技能生成请求参数
|
||||
|
|
@ -19,7 +20,11 @@ public class SkillPreGenRequest implements Serializable {
|
|||
@Schema(description = "用户提示词")
|
||||
private String prompt;
|
||||
|
||||
@Schema(description = "模板id")
|
||||
private Long contentId;
|
||||
@Schema(description = "文件地址")
|
||||
private String fileUrl;
|
||||
|
||||
@Schema(description = "文件地址列表")
|
||||
private List<String> fileUrls;
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,6 +89,49 @@ public class SkillRequest implements Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
// 新的构造方法,支持文件URL列表
|
||||
public SkillRequest(String model, String systemContent, String prompt, List<String> fileUrls, double temperature, int maxTokens) {
|
||||
this.model = model;
|
||||
this.messages = new ArrayList<>();
|
||||
|
||||
Message systemMessage = new Message();
|
||||
systemMessage.setRole("system");
|
||||
systemMessage.setContent(systemContent);
|
||||
this.messages.add(systemMessage);
|
||||
|
||||
// 构建包含文件URL的用户消息
|
||||
List<MessageContent> messageContents = new ArrayList<>();
|
||||
|
||||
// 添加文件URL
|
||||
if (fileUrls != null && !fileUrls.isEmpty()) {
|
||||
for (String fileUrl : fileUrls) {
|
||||
MessageContent fileContent = new MessageContent();
|
||||
fileContent.setType("file_url");
|
||||
FileUrl fileUrlObj = new FileUrl();
|
||||
fileUrlObj.setUrl(fileUrl);
|
||||
fileContent.setFile_url(fileUrlObj);
|
||||
messageContents.add(fileContent);
|
||||
}
|
||||
}
|
||||
|
||||
// 添加文本内容
|
||||
MessageContent textContent = new MessageContent();
|
||||
textContent.setType("text");
|
||||
textContent.setText(prompt);
|
||||
messageContents.add(textContent);
|
||||
|
||||
Message userMessage = new Message();
|
||||
userMessage.setRole("user");
|
||||
userMessage.setContent(messageContents);
|
||||
this.messages.add(userMessage);
|
||||
|
||||
this.temperature = temperature;
|
||||
this.max_tokens = maxTokens;
|
||||
|
||||
this.response_format = new ResponseFormat();
|
||||
this.response_format.setType("json_object");
|
||||
}
|
||||
|
||||
public static SkillRequest createDefault() {
|
||||
return new SkillRequest(true);
|
||||
}
|
||||
|
|
@ -100,7 +143,27 @@ public class SkillRequest implements Serializable {
|
|||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String role;
|
||||
private String content;
|
||||
private Object content; // 可以是String或List<MessageContent>
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class MessageContent implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String type;
|
||||
private String text;
|
||||
private FileUrl file_url;
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class FileUrl implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String url;
|
||||
}
|
||||
|
||||
@Data
|
||||
|
|
|
|||
|
|
@ -12,4 +12,5 @@ public class SkillResponse implements Serializable {
|
|||
private String name;
|
||||
private String description;
|
||||
private List<String> tags;
|
||||
private String summary;
|
||||
}
|
||||
|
|
@ -10,7 +10,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
|||
@Slf4j
|
||||
@ControllerAdvice
|
||||
public class BizExceptionAdvice {
|
||||
@ExceptionHandler(value = RuntimeException.class)
|
||||
@ExceptionHandler(value = BizException.class)
|
||||
@ResponseBody
|
||||
public CommonResult handleException(BizException e){
|
||||
e.printStackTrace();
|
||||
|
|
|
|||
|
|
@ -135,4 +135,78 @@ public interface CmsContentMapper {
|
|||
* @return 内容ID列表
|
||||
*/
|
||||
List<Long> queryRecentCreatedByUserId(@Param("userId") Long userId, @Param("limit") int limit);
|
||||
|
||||
/**
|
||||
* 获取用户历史查看的内容列表
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param offset 偏移量
|
||||
* @param limit 限制数量
|
||||
* @return 查询结果
|
||||
*/
|
||||
List<CmsContent> getPageListByUserHistory(@Param("userId") Long userId, @Param("offset") int offset, @Param("limit") int limit);
|
||||
|
||||
/**
|
||||
* 获取用户历史查看的内容总数
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 总记录数
|
||||
*/
|
||||
int getPageListByUserHistoryCount(@Param("userId") Long userId);
|
||||
|
||||
/**
|
||||
* 获取用户收藏的内容列表
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param offset 偏移量
|
||||
* @param limit 限制数量
|
||||
* @return 查询结果
|
||||
*/
|
||||
List<CmsContent> getPageListByUserFavorites(@Param("userId") Long userId, @Param("offset") int offset, @Param("limit") int limit);
|
||||
|
||||
/**
|
||||
* 获取用户收藏的内容总数
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 总记录数
|
||||
*/
|
||||
int getPageListByUserFavoritesCount(@Param("userId") Long userId);
|
||||
|
||||
/**
|
||||
* 获取用户购买的内容列表
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param offset 偏移量
|
||||
* @param limit 限制数量
|
||||
* @return 查询结果
|
||||
*/
|
||||
List<CmsContent> getPageListByUserPurchases(@Param("userId") Long userId, @Param("offset") int offset, @Param("limit") int limit);
|
||||
|
||||
/**
|
||||
* 获取用户购买的内容总数
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 总记录数
|
||||
*/
|
||||
int getPageListByUserPurchasesCount(@Param("userId") Long userId);
|
||||
|
||||
/**
|
||||
* 获取用户创建的内容列表
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param publishStatus 发布状态
|
||||
* @param offset 偏移量
|
||||
* @param limit 限制数量
|
||||
* @return 查询结果
|
||||
*/
|
||||
List<CmsContent> getPageListByUserCreated(@Param("userId") Long userId, @Param("publishStatus") Integer publishStatus, @Param("offset") int offset, @Param("limit") int limit);
|
||||
|
||||
/**
|
||||
* 获取用户创建的内容总数
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param publishStatus 发布状态
|
||||
* @return 总记录数
|
||||
*/
|
||||
int getPageListByUserCreatedCount(@Param("userId") Long userId, @Param("publishStatus") Integer publishStatus);
|
||||
}
|
||||
|
|
@ -133,4 +133,36 @@ public interface CmsContentService extends BaseService {
|
|||
* @return 影响行数
|
||||
*/
|
||||
int addView(Long contentId);
|
||||
|
||||
/**
|
||||
* 获取用户历史查看的内容列表
|
||||
*
|
||||
* @param queryDto 筛选条件,包含分页信息
|
||||
* @return 查询结果
|
||||
*/
|
||||
PageInfo<CmsContent> getPageListByUserHistory(CmsContentDto queryDto);
|
||||
|
||||
/**
|
||||
* 获取用户收藏的内容列表
|
||||
*
|
||||
* @param queryDto 筛选条件,包含分页信息
|
||||
* @return 查询结果
|
||||
*/
|
||||
PageInfo<CmsContent> getPageListByUserFavorites(CmsContentDto queryDto);
|
||||
|
||||
/**
|
||||
* 获取用户购买的内容列表
|
||||
*
|
||||
* @param queryDto 筛选条件,包含分页信息
|
||||
* @return 查询结果
|
||||
*/
|
||||
PageInfo<CmsContent> getPageListByUserPurchases(CmsContentDto queryDto);
|
||||
|
||||
/**
|
||||
* 获取用户创建的内容列表
|
||||
*
|
||||
* @param queryDto 筛选条件,包含分页信息
|
||||
* @return 查询结果
|
||||
*/
|
||||
PageInfo<CmsContent> getPageListByUserCreated(CmsContentDto queryDto);
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package com.kexue.skills.service;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.kexue.skills.entity.CmsContent;
|
||||
import com.kexue.skills.entity.request.SkillGenRequest;
|
||||
import com.kexue.skills.entity.request.SkillPreGenRequest;
|
||||
import com.kexue.skills.entity.request.SkillAnalyzeRequest;
|
||||
|
|
@ -22,7 +23,10 @@ public interface SkillGenService {
|
|||
*/
|
||||
SkillResponse preGenerate(SkillPreGenRequest request);
|
||||
|
||||
JSONObject generate(SkillGenRequest request);
|
||||
SkillResponse preGenerateV2(SkillPreGenRequest request);
|
||||
|
||||
CmsContent generate(SkillGenRequest request);
|
||||
|
||||
|
||||
/**
|
||||
* 分析技能
|
||||
|
|
@ -31,4 +35,12 @@ public interface SkillGenService {
|
|||
* @return 分析结果
|
||||
*/
|
||||
String analyzeSkill(SkillAnalyzeRequest request);
|
||||
|
||||
/**
|
||||
* 生成技能介绍
|
||||
*
|
||||
* @param content 技能内容
|
||||
* @return 技能介绍
|
||||
*/
|
||||
String genIntroduce(String content);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,4 +110,12 @@ public interface SysUserService extends BaseService {
|
|||
* @return 登录结果
|
||||
*/
|
||||
LoginUserDto phoneLogin(PhoneLoginDto phoneLoginDto);
|
||||
|
||||
/**
|
||||
* 根据用户名或手机号查询用户
|
||||
*
|
||||
* @param usernameOrPhone 用户名或手机号
|
||||
* @return 用户对象
|
||||
*/
|
||||
SysUser getUserByUsernameOrPhone(String usernameOrPhone);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.kexue.skills.service.impl;
|
|||
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.kexue.skills.common.LoginUserCacheUtil;
|
||||
import com.kexue.skills.entity.CmsContent;
|
||||
import com.kexue.skills.entity.CmsContentView;
|
||||
import com.kexue.skills.entity.CmsContentLike;
|
||||
|
|
@ -37,6 +38,9 @@ public class CmsContentServiceImpl implements CmsContentService {
|
|||
|
||||
@Resource
|
||||
private CmsContentLikeMapper cmsContentLikeMapper;
|
||||
|
||||
@Resource
|
||||
private LoginUserCacheUtil loginUserCacheUtil;
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
|
|
@ -54,17 +58,10 @@ public class CmsContentServiceImpl implements CmsContentService {
|
|||
queryDto.setPageSize(BaseQueryDto.DEFAULT_PAGE_SIZE);
|
||||
}
|
||||
|
||||
// 打印分页参数
|
||||
System.out.println("PageNum: " + queryDto.getPageNum() + ", PageSize: " + queryDto.getPageSize());
|
||||
|
||||
// 使用PageHelper进行分页
|
||||
PageHelper.startPage(queryDto.getPageNum(), queryDto.getPageSize());
|
||||
List<CmsContent> list = this.cmsContentMapper.getPageList(queryDto);
|
||||
PageInfo<CmsContent> pageInfo = new PageInfo<>(list);
|
||||
|
||||
// 打印分页结果
|
||||
System.out.println("Total: " + pageInfo.getTotal() + ", PageSize: " + pageInfo.getPageSize() + ", List Size: " + list.size());
|
||||
|
||||
return pageInfo;
|
||||
}
|
||||
|
||||
|
|
@ -238,7 +235,19 @@ public class CmsContentServiceImpl implements CmsContentService {
|
|||
*/
|
||||
@Override
|
||||
public int increaseViewCount(Long contentId) {
|
||||
return this.cmsContentMapper.increaseViewCount(contentId);
|
||||
// 增加阅读量
|
||||
int result = this.cmsContentMapper.increaseViewCount(contentId);
|
||||
|
||||
try {
|
||||
// 尝试获取当前登录用户ID
|
||||
Long userId = Long.parseLong(StpUtil.getLoginId().toString());
|
||||
// 调用addView方法添加查看记录
|
||||
this.addView(contentId);
|
||||
} catch (Exception e) {
|
||||
// 未登录用户,不记录查看历史
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -265,7 +274,7 @@ public class CmsContentServiceImpl implements CmsContentService {
|
|||
}
|
||||
|
||||
/**
|
||||
* 添加收藏
|
||||
* 添加/取消收藏
|
||||
*
|
||||
* @param contentId 内容ID
|
||||
* @return 影响行数
|
||||
|
|
@ -285,24 +294,43 @@ public class CmsContentServiceImpl implements CmsContentService {
|
|||
|
||||
// 检查用户是否已经收藏过该内容
|
||||
CmsContentLike existingLike = cmsContentLikeMapper.queryByUserIdAndContentId(userId, contentId);
|
||||
int result = 0;
|
||||
|
||||
if (existingLike != null) {
|
||||
return 0; // 已经收藏过,不允许再次收藏
|
||||
// 已经收藏过,执行取消收藏操作
|
||||
result = cmsContentLikeMapper.deleteById(existingLike.getLikeId());
|
||||
|
||||
// 减少内容的点赞数
|
||||
if (content.getLikeCount() > 0) {
|
||||
content.setLikeCount(content.getLikeCount() - 1);
|
||||
this.cmsContentMapper.update(content);
|
||||
}
|
||||
} else {
|
||||
// 未收藏过,执行添加收藏操作
|
||||
CmsContentLike likeRecord = new CmsContentLike();
|
||||
likeRecord.setUserId(userId);
|
||||
likeRecord.setUserName(userName);
|
||||
likeRecord.setContentId(contentId);
|
||||
likeRecord.setContentTitle(content.getTitle());
|
||||
likeRecord.setLikeTime(new Date());
|
||||
likeRecord.setDeleteFlag(0);
|
||||
|
||||
// 增加内容的点赞数
|
||||
content.setLikeCount(content.getLikeCount() + 1);
|
||||
this.cmsContentMapper.update(content);
|
||||
|
||||
result = cmsContentLikeMapper.insert(likeRecord);
|
||||
}
|
||||
|
||||
// 新增收藏记录
|
||||
CmsContentLike likeRecord = new CmsContentLike();
|
||||
likeRecord.setUserId(userId);
|
||||
likeRecord.setUserName(userName);
|
||||
likeRecord.setContentId(contentId);
|
||||
likeRecord.setContentTitle(content.getTitle());
|
||||
likeRecord.setLikeTime(new Date());
|
||||
likeRecord.setDeleteFlag(0);
|
||||
// 更新Redis中的LoginUser对象
|
||||
if (result > 0) {
|
||||
String token = loginUserCacheUtil.getTokenFromRequest();
|
||||
if (token != null) {
|
||||
loginUserCacheUtil.updateFavorites(token, userId);
|
||||
}
|
||||
}
|
||||
|
||||
// 增加内容的点赞数
|
||||
content.setLikeCount(content.getLikeCount() + 1);
|
||||
this.cmsContentMapper.update(content);
|
||||
|
||||
return cmsContentLikeMapper.insert(likeRecord);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -332,6 +360,14 @@ public class CmsContentServiceImpl implements CmsContentService {
|
|||
this.cmsContentMapper.update(content);
|
||||
}
|
||||
|
||||
// 更新Redis中的LoginUser对象
|
||||
if (result > 0) {
|
||||
String token = loginUserCacheUtil.getTokenFromRequest();
|
||||
if (token != null) {
|
||||
loginUserCacheUtil.updateFavorites(token, userId);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -376,6 +412,7 @@ public class CmsContentServiceImpl implements CmsContentService {
|
|||
|
||||
// 检查用户是否已经查看过该内容(5分钟内)
|
||||
CmsContentView existingView = cmsContentViewMapper.queryByUserIdAndContentId(userId, contentId);
|
||||
int result = 0;
|
||||
if (existingView == null) {
|
||||
// 新增查看记录
|
||||
CmsContentView viewRecord = new CmsContentView();
|
||||
|
|
@ -387,7 +424,7 @@ public class CmsContentServiceImpl implements CmsContentService {
|
|||
viewRecord.setDeleteFlag(0);
|
||||
viewRecord.setCreateBy(userName);
|
||||
viewRecord.setUpdateBy(userName);
|
||||
return cmsContentViewMapper.insert(viewRecord);
|
||||
result = cmsContentViewMapper.insert(viewRecord);
|
||||
} else {
|
||||
// 检查是否超过5分钟
|
||||
Date fiveMinutesAgo = new Date(System.currentTimeMillis() - 5 * 60 * 1000);
|
||||
|
|
@ -395,13 +432,147 @@ public class CmsContentServiceImpl implements CmsContentService {
|
|||
// 更新查看时间
|
||||
existingView.setViewTime(new Date());
|
||||
existingView.setUpdateBy(userName);
|
||||
return cmsContentViewMapper.update(existingView);
|
||||
result = cmsContentViewMapper.update(existingView);
|
||||
}
|
||||
return 0; // 5分钟内已查看过,不重复记录
|
||||
// 5分钟内已查看过,不重复记录
|
||||
}
|
||||
|
||||
// 更新Redis中的LoginUser对象
|
||||
if (result > 0) {
|
||||
String token = loginUserCacheUtil.getTokenFromRequest();
|
||||
if (token != null) {
|
||||
loginUserCacheUtil.updateHistory(token, userId);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
// 未登录用户,不记录查看历史
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageInfo<CmsContent> getPageListByUserHistory(CmsContentDto queryDto) {
|
||||
// 获取当前登录用户ID
|
||||
Long userId = Long.parseLong(StpUtil.getLoginId().toString());
|
||||
|
||||
// 添加参数校验,确保分页参数有效
|
||||
if (queryDto.getPageNum() == null || queryDto.getPageNum() < 1) {
|
||||
queryDto.setPageNum(BaseQueryDto.DEFAULT_CURRENT_PAGE);
|
||||
}
|
||||
if (queryDto.getPageSize() == null || queryDto.getPageSize() < 1) {
|
||||
queryDto.setPageSize(BaseQueryDto.DEFAULT_PAGE_SIZE);
|
||||
}
|
||||
|
||||
// 计算偏移量
|
||||
int offset = (queryDto.getPageNum() - 1) * queryDto.getPageSize();
|
||||
int limit = queryDto.getPageSize();
|
||||
|
||||
// 查询数据
|
||||
List<CmsContent> list = this.cmsContentMapper.getPageListByUserHistory(userId, offset, limit);
|
||||
int total = this.cmsContentMapper.getPageListByUserHistoryCount(userId);
|
||||
|
||||
// 构建分页结果
|
||||
PageInfo<CmsContent> pageInfo = new PageInfo<>(list);
|
||||
pageInfo.setTotal(total);
|
||||
pageInfo.setPageNum(queryDto.getPageNum());
|
||||
pageInfo.setPageSize(queryDto.getPageSize());
|
||||
pageInfo.setPages((total + limit - 1) / limit);
|
||||
|
||||
return pageInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageInfo<CmsContent> getPageListByUserFavorites(CmsContentDto queryDto) {
|
||||
// 获取当前登录用户ID
|
||||
Long userId = Long.parseLong(StpUtil.getLoginId().toString());
|
||||
|
||||
// 添加参数校验,确保分页参数有效
|
||||
if (queryDto.getPageNum() == null || queryDto.getPageNum() < 1) {
|
||||
queryDto.setPageNum(BaseQueryDto.DEFAULT_CURRENT_PAGE);
|
||||
}
|
||||
if (queryDto.getPageSize() == null || queryDto.getPageSize() < 1) {
|
||||
queryDto.setPageSize(BaseQueryDto.DEFAULT_PAGE_SIZE);
|
||||
}
|
||||
|
||||
// 计算偏移量
|
||||
int offset = (queryDto.getPageNum() - 1) * queryDto.getPageSize();
|
||||
int limit = queryDto.getPageSize();
|
||||
|
||||
// 查询数据
|
||||
List<CmsContent> list = this.cmsContentMapper.getPageListByUserFavorites(userId, offset, limit);
|
||||
int total = this.cmsContentMapper.getPageListByUserFavoritesCount(userId);
|
||||
|
||||
// 构建分页结果
|
||||
PageInfo<CmsContent> pageInfo = new PageInfo<>(list);
|
||||
pageInfo.setTotal(total);
|
||||
pageInfo.setPageNum(queryDto.getPageNum());
|
||||
pageInfo.setPageSize(queryDto.getPageSize());
|
||||
pageInfo.setPages((total + limit - 1) / limit);
|
||||
|
||||
return pageInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageInfo<CmsContent> getPageListByUserPurchases(CmsContentDto queryDto) {
|
||||
// 获取当前登录用户ID
|
||||
Long userId = Long.parseLong(StpUtil.getLoginId().toString());
|
||||
|
||||
// 添加参数校验,确保分页参数有效
|
||||
if (queryDto.getPageNum() == null || queryDto.getPageNum() < 1) {
|
||||
queryDto.setPageNum(BaseQueryDto.DEFAULT_CURRENT_PAGE);
|
||||
}
|
||||
if (queryDto.getPageSize() == null || queryDto.getPageSize() < 1) {
|
||||
queryDto.setPageSize(BaseQueryDto.DEFAULT_PAGE_SIZE);
|
||||
}
|
||||
|
||||
// 计算偏移量
|
||||
int offset = (queryDto.getPageNum() - 1) * queryDto.getPageSize();
|
||||
int limit = queryDto.getPageSize();
|
||||
|
||||
// 查询数据
|
||||
List<CmsContent> list = this.cmsContentMapper.getPageListByUserPurchases(userId, offset, limit);
|
||||
int total = this.cmsContentMapper.getPageListByUserPurchasesCount(userId);
|
||||
|
||||
// 构建分页结果
|
||||
PageInfo<CmsContent> pageInfo = new PageInfo<>(list);
|
||||
pageInfo.setTotal(total);
|
||||
pageInfo.setPageNum(queryDto.getPageNum());
|
||||
pageInfo.setPageSize(queryDto.getPageSize());
|
||||
pageInfo.setPages((total + limit - 1) / limit);
|
||||
|
||||
return pageInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageInfo<CmsContent> getPageListByUserCreated(CmsContentDto queryDto) {
|
||||
// 获取当前登录用户ID
|
||||
Long userId = Long.parseLong(StpUtil.getLoginId().toString());
|
||||
|
||||
// 添加参数校验,确保分页参数有效
|
||||
if (queryDto.getPageNum() == null || queryDto.getPageNum() < 1) {
|
||||
queryDto.setPageNum(BaseQueryDto.DEFAULT_CURRENT_PAGE);
|
||||
}
|
||||
if (queryDto.getPageSize() == null || queryDto.getPageSize() < 1) {
|
||||
queryDto.setPageSize(BaseQueryDto.DEFAULT_PAGE_SIZE);
|
||||
}
|
||||
|
||||
// 计算偏移量
|
||||
int offset = (queryDto.getPageNum() - 1) * queryDto.getPageSize();
|
||||
int limit = queryDto.getPageSize();
|
||||
|
||||
// 查询数据
|
||||
List<CmsContent> list = this.cmsContentMapper.getPageListByUserCreated(userId, queryDto.getPublishStatus(), offset, limit);
|
||||
int total = this.cmsContentMapper.getPageListByUserCreatedCount(userId, queryDto.getPublishStatus());
|
||||
|
||||
// 构建分页结果
|
||||
PageInfo<CmsContent> pageInfo = new PageInfo<>(list);
|
||||
pageInfo.setTotal(total);
|
||||
pageInfo.setPageNum(queryDto.getPageNum());
|
||||
pageInfo.setPageSize(queryDto.getPageSize());
|
||||
pageInfo.setPages((total + limit - 1) / limit);
|
||||
|
||||
return pageInfo;
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.kexue.skills.service.impl;
|
|||
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.kexue.skills.common.LoginUserCacheUtil;
|
||||
import com.kexue.skills.entity.CmsContent;
|
||||
import com.kexue.skills.entity.ContentPurchase;
|
||||
import com.kexue.skills.entity.dto.ContentPurchaseDto;
|
||||
|
|
@ -21,6 +22,8 @@ import java.util.Date;
|
|||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
|
||||
/**
|
||||
* (ContentPurchase)表服务实现类
|
||||
*
|
||||
|
|
@ -41,6 +44,9 @@ public class ContentPurchaseServiceImpl implements ContentPurchaseService {
|
|||
|
||||
@Resource
|
||||
private PointsAccountService pointsAccountService;
|
||||
|
||||
@Resource
|
||||
private LoginUserCacheUtil loginUserCacheUtil;
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
|
|
@ -195,6 +201,7 @@ public class ContentPurchaseServiceImpl implements ContentPurchaseService {
|
|||
|
||||
// 5. 根据支付方式处理支付
|
||||
String transactionNo = UUID.randomUUID().toString().replaceAll("-", "");
|
||||
boolean isPaid = false;
|
||||
if (payType == 1) {
|
||||
// 余额支付
|
||||
BigDecimal price = content.getPrice();
|
||||
|
|
@ -208,6 +215,7 @@ public class ContentPurchaseServiceImpl implements ContentPurchaseService {
|
|||
purchase.setStatus(2); // 已支付
|
||||
purchase.setPurchaseTime(new Date());
|
||||
this.insert(purchase);
|
||||
isPaid = true;
|
||||
} else if (payType == 2) {
|
||||
// 积分支付
|
||||
Assert.isTrue(content.getSupportPointsPay() == 1, "该内容不支持积分支付");
|
||||
|
|
@ -223,6 +231,7 @@ public class ContentPurchaseServiceImpl implements ContentPurchaseService {
|
|||
purchase.setStatus(2); // 已支付
|
||||
purchase.setPurchaseTime(new Date());
|
||||
this.insert(purchase);
|
||||
isPaid = true;
|
||||
} else if (payType == 3 || payType == 4) {
|
||||
// 微信支付或支付宝支付
|
||||
// 这里只创建购买记录,实际支付由前端调用支付接口完成
|
||||
|
|
@ -237,6 +246,14 @@ public class ContentPurchaseServiceImpl implements ContentPurchaseService {
|
|||
Assert.isTrue(false, "不支持的支付方式");
|
||||
}
|
||||
|
||||
// 更新Redis中的LoginUser对象
|
||||
if (isPaid) {
|
||||
String token = loginUserCacheUtil.getTokenFromRequest();
|
||||
if (token != null) {
|
||||
loginUserCacheUtil.updateHas(token, userId);
|
||||
}
|
||||
}
|
||||
|
||||
return purchase;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -153,10 +153,26 @@ public class PayServiceImpl implements PayService {
|
|||
|
||||
// 构建请求XML
|
||||
String xml = mapToXml(params);
|
||||
logger.info("微信支付请求XML: {}", xml);
|
||||
|
||||
// 发送请求到微信支付接口
|
||||
String xmlResult = HttpUtil.post("https://api.mch.weixin.qq.com/pay/unifiedorder", xml);
|
||||
String xmlResult = null;
|
||||
try {
|
||||
logger.info("开始发送微信支付请求到: https://api.mch.weixin.qq.com/pay/unifiedorder");
|
||||
xmlResult = HttpUtil.post("https://api.mch.weixin.qq.com/pay/unifiedorder", xml);
|
||||
logger.info("微信支付接口返回XML: {}", xmlResult);
|
||||
} catch (Exception e) {
|
||||
logger.error("发送微信支付请求失败", e);
|
||||
throw new RuntimeException("发送微信支付请求失败: " + e.getMessage());
|
||||
}
|
||||
|
||||
if (xmlResult == null || xmlResult.isEmpty()) {
|
||||
logger.error("微信支付接口返回空响应");
|
||||
throw new RuntimeException("微信支付接口返回空响应");
|
||||
}
|
||||
|
||||
Map<String, String> result = xmlToMap(xmlResult);
|
||||
logger.info("解析后的微信支付响应: {}", result);
|
||||
|
||||
// 处理响应
|
||||
if ("SUCCESS".equals(result.get("return_code")) && "SUCCESS".equals(result.get("result_code"))) {
|
||||
|
|
@ -165,8 +181,9 @@ public class PayServiceImpl implements PayService {
|
|||
payParams.put("order_no", order.getOrderNo());
|
||||
return payParams;
|
||||
} else {
|
||||
logger.error("微信支付下单失败: {}", result.get("return_msg"));
|
||||
throw new RuntimeException("微信支付下单失败: " + result.get("return_msg"));
|
||||
String returnMsg = result.get("return_msg") != null ? result.get("return_msg") : "未知错误";
|
||||
logger.error("微信支付下单失败: {}", returnMsg);
|
||||
throw new RuntimeException("微信支付下单失败: " + returnMsg);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("创建微信支付订单失败", e);
|
||||
|
|
@ -181,10 +198,11 @@ public class PayServiceImpl implements PayService {
|
|||
*/
|
||||
@Override
|
||||
public String handleWechatPayNotify(HttpServletRequest request) {
|
||||
BufferedReader reader = null;
|
||||
try {
|
||||
// 读取回调数据
|
||||
InputStream inputStream = request.getInputStream();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
|
||||
reader = new BufferedReader(new InputStreamReader(inputStream));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
|
|
@ -197,6 +215,10 @@ public class PayServiceImpl implements PayService {
|
|||
|
||||
// 验证签名
|
||||
String sign = params.get("sign");
|
||||
if (sign == null) {
|
||||
logger.error("微信支付回调签名为空");
|
||||
return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名为空]]></return_msg></xml>";
|
||||
}
|
||||
params.remove("sign");
|
||||
String expectedSign = generateSignature(params, paymentConfig.getWechat().getMchKey());
|
||||
|
||||
|
|
@ -211,9 +233,11 @@ public class PayServiceImpl implements PayService {
|
|||
String transactionId = params.get("transaction_id");
|
||||
|
||||
// 更新支付订单状态
|
||||
PaymentOrder order = paymentOrderService.queryByOrderNo(orderNo);
|
||||
if (order != null) {
|
||||
paymentOrderService.updateStatus(order.getOrderId(), 2, transactionId);
|
||||
if (orderNo != null) {
|
||||
PaymentOrder order = paymentOrderService.queryByOrderNo(orderNo);
|
||||
if (order != null) {
|
||||
paymentOrderService.updateStatus(order.getOrderId(), 2, transactionId);
|
||||
}
|
||||
}
|
||||
|
||||
return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
|
||||
|
|
@ -224,6 +248,14 @@ public class PayServiceImpl implements PayService {
|
|||
} catch (Exception e) {
|
||||
logger.error("处理微信支付回调失败", e);
|
||||
return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[处理失败]]></return_msg></xml>";
|
||||
} finally {
|
||||
if (reader != null) {
|
||||
try {
|
||||
reader.close();
|
||||
} catch (Exception e) {
|
||||
logger.error("关闭流失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -286,7 +318,9 @@ public class PayServiceImpl implements PayService {
|
|||
// 获取回调参数
|
||||
Map<String, String> params = new HashMap<>();
|
||||
request.getParameterMap().forEach((key, values) -> {
|
||||
params.put(key, values[0]);
|
||||
if (values != null && values.length > 0) {
|
||||
params.put(key, values[0]);
|
||||
}
|
||||
});
|
||||
|
||||
// 初始化支付宝客户端
|
||||
|
|
@ -317,9 +351,11 @@ public class PayServiceImpl implements PayService {
|
|||
String transactionId = params.get("trade_no");
|
||||
|
||||
// 更新支付订单状态
|
||||
PaymentOrder order = paymentOrderService.queryByOrderNo(orderNo);
|
||||
if (order != null) {
|
||||
paymentOrderService.updateStatus(order.getOrderId(), 2, transactionId);
|
||||
if (orderNo != null) {
|
||||
PaymentOrder order = paymentOrderService.queryByOrderNo(orderNo);
|
||||
if (order != null) {
|
||||
paymentOrderService.updateStatus(order.getOrderId(), 2, transactionId);
|
||||
}
|
||||
}
|
||||
|
||||
return "success";
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ import com.kexue.skills.entity.dto.PaymentOrderDto;
|
|||
import com.kexue.skills.mapper.PaymentOrderMapper;
|
||||
import com.kexue.skills.service.AccountService;
|
||||
import com.kexue.skills.service.PaymentOrderService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
|
@ -24,6 +26,8 @@ import java.util.UUID;
|
|||
@Service("paymentOrderService")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class PaymentOrderServiceImpl implements PaymentOrderService {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(PaymentOrderServiceImpl.class);
|
||||
@Resource
|
||||
private PaymentOrderMapper paymentOrderMapper;
|
||||
|
||||
|
|
@ -162,6 +166,13 @@ public class PaymentOrderServiceImpl implements PaymentOrderService {
|
|||
paymentOrder.setOrderNo(orderNo);
|
||||
// 设置初始状态
|
||||
paymentOrder.setStatus(1); // 1.待支付
|
||||
// 设置支付类型默认值(防止null)
|
||||
if (paymentOrder.getPayType() == null) {
|
||||
paymentOrder.setPayType(1); // 默认微信支付
|
||||
logger.info("设置默认支付类型为微信支付(1)");
|
||||
} else {
|
||||
logger.info("支付类型已设置为: {}", paymentOrder.getPayType());
|
||||
}
|
||||
// 设置创建时间和更新时间
|
||||
Date now = new Date();
|
||||
paymentOrder.setCreateTime(now);
|
||||
|
|
@ -169,7 +180,9 @@ public class PaymentOrderServiceImpl implements PaymentOrderService {
|
|||
// 设置默认值
|
||||
paymentOrder.setDeleteFlag(0);
|
||||
// 保存订单
|
||||
logger.info("准备保存支付订单,payType: {}", paymentOrder.getPayType());
|
||||
this.paymentOrderMapper.insert(paymentOrder);
|
||||
logger.info("支付订单保存成功");
|
||||
return paymentOrder;
|
||||
}
|
||||
|
||||
|
|
@ -209,7 +222,7 @@ public class PaymentOrderServiceImpl implements PaymentOrderService {
|
|||
}
|
||||
} catch (Exception e) {
|
||||
// 记录错误但不影响支付回调的处理
|
||||
java.util.logging.Logger.getLogger(getClass().getName()).severe("更新购买记录状态失败: " + e.getMessage());
|
||||
logger.error("更新购买记录状态失败: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
package com.kexue.skills.service.impl;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
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.config.GlmConfig;
|
||||
import com.kexue.skills.entity.CmsContent;
|
||||
import com.kexue.skills.entity.CmsTag;
|
||||
import com.kexue.skills.entity.dto.CmsTagDto;
|
||||
import com.kexue.skills.entity.request.SkillAnalyzeRequest;
|
||||
|
|
@ -11,13 +14,20 @@ 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.mapper.CmsContentMapper;
|
||||
import com.kexue.skills.service.CmsTagService;
|
||||
import com.kexue.skills.service.SkillGenService;
|
||||
import jodd.util.StringUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 技能生成服务实现
|
||||
|
|
@ -32,9 +42,15 @@ public class SkillGenServiceImpl implements SkillGenService {
|
|||
@Autowired
|
||||
private DeepSeekConfig deepSeekConfig;
|
||||
|
||||
@Autowired
|
||||
private GlmConfig glmConfig;
|
||||
|
||||
@Autowired
|
||||
private CmsTagService cmsTagService;
|
||||
|
||||
@Resource
|
||||
private CmsContentMapper cmsContentMapper;
|
||||
|
||||
/**
|
||||
* 生成技能
|
||||
*
|
||||
|
|
@ -99,7 +115,80 @@ public class SkillGenServiceImpl implements SkillGenService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public JSONObject generate(SkillGenRequest request) {
|
||||
public SkillResponse preGenerateV2(SkillPreGenRequest request) {
|
||||
log.info("生成技能请求V2: {}", request);
|
||||
String url = glmConfig.getBaseUrl() + "/chat/completions";
|
||||
String apiKey = glmConfig.getApiKey();
|
||||
String model = glmConfig.getChat().getModel();
|
||||
double temperature = glmConfig.getChat().getTemperature();
|
||||
int maxTokens = glmConfig.getChat().getMaxTokens();
|
||||
|
||||
// 从数据库中读取cms_tag表的标签信息
|
||||
CmsTagDto tagDto = new CmsTagDto();
|
||||
tagDto.setDeleteFlag(0);
|
||||
tagDto.setStatus(1);
|
||||
List<CmsTag> tags = cmsTagService.getList(tagDto);
|
||||
|
||||
// 将标签名称拼接成逗号分隔的字符串
|
||||
StringBuilder tagsList = new StringBuilder();
|
||||
for (int i = 0; i < tags.size(); i++) {
|
||||
CmsTag tag = tags.get(i);
|
||||
tagsList.append(tag.getTagName());
|
||||
if (i < tags.size() - 1) {
|
||||
tagsList.append(",");
|
||||
}
|
||||
}
|
||||
|
||||
// 构建系统消息内容
|
||||
String systemContent = "你是一个专业的AI技能设计助手。请根据agent skills撰写规范,按照用户提出的主题描述及参考文件,生成这个skill的名称、描述,并从以下标签列表中选择一个或者多个标签:\"" + tagsList.toString() + "\",并简述这个skill的具体价值点。输出json格式,仅输出以上所提到的名称、描述、标签、价值点,节点名称分别为name、description、tags、value_point,节点内容以中文形式返回。请严格按照指定的JSON格式输出,仅包含要求的字段,以中文形式返回。";
|
||||
|
||||
// 准备文件URL列表
|
||||
List<String> fileUrls = new ArrayList<>();
|
||||
if (request.getFileUrl() != null && !request.getFileUrl().isEmpty()) {
|
||||
fileUrls.add(request.getFileUrl());
|
||||
}
|
||||
if (request.getFileUrls() != null && !request.getFileUrls().isEmpty()) {
|
||||
fileUrls.addAll(request.getFileUrls());
|
||||
}
|
||||
|
||||
// 创建技能请求
|
||||
SkillRequest skillRequest = new SkillRequest(model, systemContent, request.getPrompt(), fileUrls, temperature, maxTokens);
|
||||
|
||||
try {
|
||||
// 发送HTTP请求到API
|
||||
String response = HttpUtil.sendPostRequest(url, skillRequest, apiKey, null);
|
||||
log.info("API响应: {}", response);
|
||||
|
||||
// 解析返回结果
|
||||
JSONObject responseJson = JSON.parseObject(response);
|
||||
List<JSONObject> choices = responseJson.getJSONArray("choices").toJavaList(JSONObject.class);
|
||||
|
||||
if (choices != null && !choices.isEmpty()) {
|
||||
// 获取最新的choice(这里是第一个,因为只有一个)
|
||||
JSONObject latestChoice = choices.get(0);
|
||||
JSONObject message = latestChoice.getJSONObject("message");
|
||||
String content = message.getString("content");
|
||||
|
||||
// 解析content中的JSON
|
||||
JSONObject skillJson = JSON.parseObject(content);
|
||||
SkillResponse skillResponse = new SkillResponse();
|
||||
skillResponse.setName(skillJson.getString("name"));
|
||||
skillResponse.setDescription(skillJson.getString("description"));
|
||||
skillResponse.setTags(skillJson.getJSONArray("tags").toJavaList(String.class));
|
||||
skillResponse.setSummary(skillJson.getString("value_point"));
|
||||
|
||||
log.info("解析技能响应: {}", skillResponse);
|
||||
return skillResponse;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("调用API失败: {}", e.getMessage(), e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CmsContent generate(SkillGenRequest request) {
|
||||
log.info("生成技能请求: {}", request);
|
||||
String url = deepSeekConfig.getBaseUrl() + "/v1/chat/completions";
|
||||
|
||||
|
|
@ -113,31 +202,69 @@ public class SkillGenServiceImpl implements SkillGenService {
|
|||
|
||||
// 将标签名称拼接成逗号分隔的字符串
|
||||
StringBuilder tagsList = new StringBuilder();
|
||||
String defaultIcon = "";
|
||||
for (int i = 0; i < tags.size(); i++) {
|
||||
CmsTag tag = tags.get(i);
|
||||
if (tags1.contains(tag.getTagId()+"")) {
|
||||
if (StringUtil.isEmpty(defaultIcon)){
|
||||
defaultIcon = tag.getIcon();
|
||||
}
|
||||
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());
|
||||
String systemContent = "你是一个专业的AI技能设计助手。请基于用户提供的Skill名称、描述、标签,按照skills目录结构输出完整的skills内容,包括skills.md本体内容、scripts目录中的脚本等,并打包成一个YAML文件技能包。请严格遵循以下规范:1. 包含必需的文件和目录;2. 多行内容使用 | 字面块;3. 内容从行首开始;4. 空目录用 children: [] 表示;5. 文件内容要实际有用;6.输出一个完整的YAML文档,对于每个节点的内容要输出type,文件对应file,目录对应directory,每个节点都必须有name和content属性,无需其他额外说明。";
|
||||
String userContent = "请根据以下Skill信息生成skills.md文档内容:Skill名称:SKILL_NAME,Skill描述:DESCRIPTION,Skill标签:TAGS ,摘要:SUMMARY。";
|
||||
userContent = userContent.replace("SKILL_NAME", request.getName()).replace("DESCRIPTION", request.getDescription()).replace("TAGS", tagsList.toString()).replace("SUMMARY", request.getRequirement());
|
||||
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;
|
||||
String content = responseJson.getJSONArray("choices").toJavaList(JSONObject.class).get(0).getJSONObject("message").getString("content");
|
||||
CmsContent cmsContent = getCmsContent(request, content, StpUtil.getLoginIdAsLong(),defaultIcon);
|
||||
// 保存到数据库
|
||||
cmsContentMapper.insert(cmsContent);
|
||||
return cmsContent;
|
||||
} catch (Exception e) {
|
||||
log.error("调用Deepseek API失败: {}", e.getMessage(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private CmsContent getCmsContent(SkillGenRequest request, String CmsContent,Long userId,String defaultIcon){
|
||||
CmsContent cmsContent = new CmsContent();
|
||||
cmsContent.setTitle(request.getName());
|
||||
cmsContent.setDescription(request.getDescription());
|
||||
cmsContent.setContent(CmsContent);
|
||||
cmsContent.setTags(request.getTags().stream().map(String::valueOf).collect(Collectors.joining(",")));
|
||||
cmsContent.setIsPaid(0);//免费
|
||||
cmsContent.setIsOfficial(false);
|
||||
cmsContent.setPublishStatus(1);
|
||||
cmsContent.setAuthorId(userId);
|
||||
cmsContent.setAuthorName(null);
|
||||
cmsContent.setAuditStatus(1);
|
||||
cmsContent.setViewCount(0);
|
||||
cmsContent.setCommentCount(0);
|
||||
cmsContent.setRequiredPoints(0);
|
||||
cmsContent.setSupportPointsPay(0);
|
||||
cmsContent.setPrice(new BigDecimal(0));
|
||||
cmsContent.setLikeCount(0);
|
||||
cmsContent.setShareCount(0);
|
||||
cmsContent.setCreateTime(new Date());
|
||||
cmsContent.setUpdateTime(new Date());
|
||||
cmsContent.setContentType(1);
|
||||
cmsContent.setCreateBy(userId+"");
|
||||
cmsContent.setUpdateBy(userId+"");
|
||||
cmsContent.setDeleteFlag(0);
|
||||
cmsContent.setIcon(defaultIcon);
|
||||
cmsContent.setRequirement(request.getRequirement());
|
||||
return cmsContent;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 分析技能
|
||||
|
|
@ -152,4 +279,33 @@ public class SkillGenServiceImpl implements SkillGenService {
|
|||
// 不需要数据库操作,直接返回结果
|
||||
return "技能分析成功: " + request.getSkillId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String genIntroduce(String content) {
|
||||
log.info("生成技能介绍请求: {}", content);
|
||||
String url = deepSeekConfig.getBaseUrl() + "/v1/chat/completions";
|
||||
|
||||
String systemContent = "你是一个专业的AI技能设计助手。我会给你提供一个完整的skill的内容,请你帮我总结出skill的作用,能够解决的问题,输出一段描述文本";
|
||||
SkillRequest skillRequest = new SkillRequest(true, deepSeekConfig.getChat().getModel(), systemContent, content, 0.3, 500, "text");
|
||||
|
||||
try {
|
||||
// 发送HTTP请求到deepseek API
|
||||
String deepseekResponse = HttpUtil.sendPostRequest(url, skillRequest, deepSeekConfig.getApiKey(), null);
|
||||
log.info("Deepseek API响应: {}", deepseekResponse);
|
||||
|
||||
// 解析返回结果
|
||||
JSONObject responseJson = JSON.parseObject(deepseekResponse);
|
||||
List<JSONObject> choices = responseJson.getJSONArray("choices").toJavaList(JSONObject.class);
|
||||
|
||||
if (choices != null && !choices.isEmpty()) {
|
||||
JSONObject latestChoice = choices.get(0);
|
||||
JSONObject message = latestChoice.getJSONObject("message");
|
||||
return message.getString("content");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("调用Deepseek API失败: {}", e.getMessage(), e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import com.github.pagehelper.PageInfo;
|
|||
import com.kexue.skills.common.Assert;
|
||||
import com.kexue.skills.common.CacheManager;
|
||||
import com.kexue.skills.common.Const;
|
||||
import com.kexue.skills.common.LoginUserCacheUtil;
|
||||
import com.kexue.skills.config.CaptchaConfig;
|
||||
import com.kexue.skills.entity.*;
|
||||
import com.kexue.skills.entity.dto.ContentPurchaseDto;
|
||||
|
|
@ -136,8 +137,9 @@ public class SysUserServiceImpl implements SysUserService {
|
|||
//写一个salt生成方法
|
||||
sysUser.setSalt(System.currentTimeMillis()+"");
|
||||
try {
|
||||
String md5Pwd = MD5Util.encryptToHex(sysUser.getPwd()+sysUser.getSalt());
|
||||
sysUser.setPwd(md5Pwd);
|
||||
// 假设客户端已经对密码进行了一次MD5加密,服务端使用双重加密验证
|
||||
String encryptedPwd = MD5Util.doubleEncrypt(sysUser.getPwd(), sysUser.getSalt());
|
||||
sysUser.setPwd(encryptedPwd);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
|
@ -219,12 +221,24 @@ public class SysUserServiceImpl implements SysUserService {
|
|||
// 验证码验证
|
||||
validateCaptcha(loginDto);
|
||||
|
||||
// 查询用户
|
||||
SysUser sysUser = getUserByUsername(loginDto.getUsername());
|
||||
// 查询用户(支持用户名或手机号)
|
||||
SysUser sysUser = getUserByUsernameOrPhone(loginDto.getUsername());
|
||||
|
||||
// 密码验证
|
||||
validatePassword(loginDto.getPassword(), sysUser);
|
||||
|
||||
// 检查用户是否已有token,如果有则使旧token失效
|
||||
String oldToken = CacheManager.getTokenFromCache(sysUser.getUserName());
|
||||
if (oldToken != null && !oldToken.isEmpty()) {
|
||||
// 从Redis中删除旧token对应的登录信息
|
||||
redissonClient.getBucket("loginUser:" + oldToken).delete();
|
||||
// 使旧token失效
|
||||
cn.dev33.satoken.stp.StpUtil.logoutByTokenValue(oldToken);
|
||||
// 从缓存中移除旧token
|
||||
CacheManager.removeTokenFromCache(sysUser.getUserName());
|
||||
log.info("用户:{}的旧token已失效", sysUser.getUserName());
|
||||
}
|
||||
|
||||
// 生成token
|
||||
String token = generateToken(sysUser.getUserId());
|
||||
|
||||
|
|
@ -234,6 +248,9 @@ public class SysUserServiceImpl implements SysUserService {
|
|||
// 存储登录信息到Redis
|
||||
saveLoginUserToRedis(token, loginUser);
|
||||
|
||||
// 存储token与用户名的映射关系到CacheManager
|
||||
CacheManager.putTokenToCache(sysUser.getUserName(), token);
|
||||
|
||||
// 构建返回对象
|
||||
LoginUserDto sysUserDto = buildLoginUserDto(loginUser);
|
||||
|
||||
|
|
@ -248,7 +265,7 @@ public class SysUserServiceImpl implements SysUserService {
|
|||
* @param loginDto 登录请求参数
|
||||
*/
|
||||
private void validateLoginParams(LoginDto loginDto) {
|
||||
Assert.notNull(loginDto.getUsername(), "用户名不能位空");
|
||||
Assert.notNull(loginDto.getUsername(), "用户名或手机号不能位空");
|
||||
Assert.notNull(loginDto.getPassword(), "密码不能位空");
|
||||
}
|
||||
|
||||
|
|
@ -283,6 +300,23 @@ public class SysUserServiceImpl implements SysUserService {
|
|||
return sysUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户名或手机号查询用户
|
||||
*
|
||||
* @param usernameOrPhone 用户名或手机号
|
||||
* @return 用户对象
|
||||
*/
|
||||
public SysUser getUserByUsernameOrPhone(String usernameOrPhone) {
|
||||
// 先尝试通过用户名查询
|
||||
SysUser sysUser = sysUserMapper.getByUsername(usernameOrPhone);
|
||||
if (sysUser == null) {
|
||||
// 如果用户名查询不到,尝试通过手机号查询
|
||||
sysUser = sysUserMapper.getByTel(usernameOrPhone);
|
||||
Assert.notNull(sysUser, "用户不存在");
|
||||
}
|
||||
return sysUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* 密码验证
|
||||
*
|
||||
|
|
@ -523,25 +557,39 @@ public class SysUserServiceImpl implements SysUserService {
|
|||
return sysUserDto;
|
||||
}
|
||||
|
||||
@Resource
|
||||
private LoginUserCacheUtil loginUserCacheUtil;
|
||||
|
||||
@Override
|
||||
public boolean resetPassword(ResetPasswordDto resetPasswordDto) {
|
||||
Assert.notNull(resetPasswordDto.getUserName(), "用户名不能位空");
|
||||
Assert.notNull(resetPasswordDto.getUserName(), "用户名或手机号不能位空");
|
||||
Assert.notNull(resetPasswordDto.getOldPassword(), "旧密码不能位空");
|
||||
Assert.notNull(resetPasswordDto.getNewPassword(), "新密码不能位空");
|
||||
|
||||
SysUser sysUser = sysUserMapper.getByUsername(resetPasswordDto.getUserName());
|
||||
Assert.notNull(sysUser, "用户名不存在");
|
||||
// 获取当前登录用户ID
|
||||
Long currentUserId = loginUserCacheUtil.getCurrentUserId();
|
||||
Assert.notNull(currentUserId, "请先登录");
|
||||
|
||||
// 查询用户(支持用户名或手机号)
|
||||
SysUser sysUser = getUserByUsernameOrPhone(resetPasswordDto.getUserName());
|
||||
|
||||
// 检查是否是用户自己修改密码,或者是管理员
|
||||
boolean isAdmin = Const.ADMIN_USER_LIST.contains(sysUser.getUserName().toLowerCase());
|
||||
boolean isSelf = currentUserId.equals(sysUser.getUserId());
|
||||
Assert.isTrue(isAdmin || isSelf, "只能修改自己的密码");
|
||||
|
||||
try {
|
||||
String oldMd5Pwd = MD5Util.encryptToHex(resetPasswordDto.getOldPassword() + sysUser.getSalt());
|
||||
Assert.equals(oldMd5Pwd, sysUser.getPwd(), "旧密码不正确");
|
||||
// 假设客户端已经对密码进行了一次MD5加密,服务端使用双重加密验证
|
||||
String oldEncryptedPwd = MD5Util.doubleEncrypt(resetPasswordDto.getOldPassword(), sysUser.getSalt());
|
||||
Assert.equals(oldEncryptedPwd, sysUser.getPwd(), "旧密码不正确");
|
||||
|
||||
String newMd5Pwd = MD5Util.encryptToHex(resetPasswordDto.getNewPassword() + sysUser.getSalt());
|
||||
sysUser.setPwd(newMd5Pwd);
|
||||
// 对新密码进行双重加密
|
||||
String newEncryptedPwd = MD5Util.doubleEncrypt(resetPasswordDto.getNewPassword(), sysUser.getSalt());
|
||||
sysUser.setPwd(newEncryptedPwd);
|
||||
sysUserMapper.update(sysUser);
|
||||
|
||||
// 清除旧的token
|
||||
CacheManager.removeTokenFromCache(resetPasswordDto.getUserName());
|
||||
CacheManager.removeTokenFromCache(sysUser.getUserName());
|
||||
|
||||
return true;
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
|
|
@ -551,19 +599,20 @@ public class SysUserServiceImpl implements SysUserService {
|
|||
|
||||
@Override
|
||||
public boolean resetPasswordByAdmin(ResetPasswordDto resetPasswordDto) {
|
||||
Assert.notNull(resetPasswordDto.getUserName(), "用户名不能位空");
|
||||
Assert.notNull(resetPasswordDto.getUserName(), "用户名或手机号不能位空");
|
||||
Assert.notNull(resetPasswordDto.getNewPassword(), "新密码不能位空");
|
||||
|
||||
SysUser sysUser = sysUserMapper.getByUsername(resetPasswordDto.getUserName());
|
||||
Assert.notNull(sysUser, "用户名不存在");
|
||||
// 查询用户(支持用户名或手机号)
|
||||
SysUser sysUser = getUserByUsernameOrPhone(resetPasswordDto.getUserName());
|
||||
|
||||
try {
|
||||
String newMd5Pwd = MD5Util.encryptToHex(resetPasswordDto.getNewPassword() + sysUser.getSalt());
|
||||
sysUser.setPwd(newMd5Pwd);
|
||||
// 假设客户端已经对密码进行了一次MD5加密,服务端使用双重加密验证
|
||||
String newEncryptedPwd = MD5Util.doubleEncrypt(resetPasswordDto.getNewPassword(), sysUser.getSalt());
|
||||
sysUser.setPwd(newEncryptedPwd);
|
||||
sysUserMapper.update(sysUser);
|
||||
|
||||
// 清除旧的token
|
||||
CacheManager.removeTokenFromCache(resetPasswordDto.getUserName());
|
||||
CacheManager.removeTokenFromCache(sysUser.getUserName());
|
||||
|
||||
return true;
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
|
|
@ -587,17 +636,23 @@ public class SysUserServiceImpl implements SysUserService {
|
|||
|
||||
@Override
|
||||
public boolean resetPwd(Long userId, String newPassword, String operator) {
|
||||
// 检查操作人是否为管理员
|
||||
Assert.isTrue(Const.ADMIN_USER_LIST.contains(operator.toLowerCase()), "只有管理员才能执行此操作");
|
||||
// 获取当前登录用户ID
|
||||
Long currentUserId = loginUserCacheUtil.getCurrentUserId();
|
||||
Assert.notNull(currentUserId, "请先登录");
|
||||
|
||||
// 查询用户是否存在
|
||||
SysUser sysUser = sysUserMapper.queryById(userId);
|
||||
Assert.notNull(sysUser, "用户不存在");
|
||||
|
||||
// 检查是否是用户自己修改密码,或者是管理员
|
||||
boolean isAdmin = Const.ADMIN_USER_LIST.contains(operator.toLowerCase());
|
||||
boolean isSelf = currentUserId.equals(sysUser.getUserId());
|
||||
Assert.isTrue(isAdmin || isSelf, "只能修改自己的密码");
|
||||
|
||||
try {
|
||||
// 生成新的加密密码
|
||||
String newMd5Pwd = MD5Util.encryptToHex(newPassword + sysUser.getSalt());
|
||||
sysUser.setPwd(newMd5Pwd);
|
||||
// 假设客户端已经对密码进行了一次MD5加密,服务端使用双重加密验证
|
||||
String newEncryptedPwd = MD5Util.doubleEncrypt(newPassword, sysUser.getSalt());
|
||||
sysUser.setPwd(newEncryptedPwd);
|
||||
|
||||
// 更新用户密码
|
||||
sysUserMapper.update(sysUser);
|
||||
|
|
@ -613,8 +668,9 @@ public class SysUserServiceImpl implements SysUserService {
|
|||
|
||||
@Override
|
||||
public boolean resetPasswordByUsernameOrPhone(String usernameOrPhone, String newPassword, String operator) {
|
||||
// 检查操作人是否为管理员
|
||||
//Assert.isTrue(Const.ADMIN_USER_LIST.contains(operator.toLowerCase()), "只有管理员才能执行此操作");
|
||||
// 获取当前登录用户ID
|
||||
Long currentUserId = loginUserCacheUtil.getCurrentUserId();
|
||||
Assert.notNull(currentUserId, "请先登录");
|
||||
|
||||
// 查询用户是否存在(先尝试通过用户名查询,再尝试通过手机号查询)
|
||||
SysUser sysUser = sysUserMapper.getByUsername(usernameOrPhone);
|
||||
|
|
@ -622,11 +678,16 @@ public class SysUserServiceImpl implements SysUserService {
|
|||
sysUser = sysUserMapper.getByTel(usernameOrPhone);
|
||||
}
|
||||
Assert.notNull(sysUser, "用户不存在");
|
||||
|
||||
// 检查是否是用户自己修改密码,或者是管理员
|
||||
boolean isAdmin = Const.ADMIN_USER_LIST.contains(operator.toLowerCase());
|
||||
boolean isSelf = currentUserId.equals(sysUser.getUserId());
|
||||
Assert.isTrue(isAdmin || isSelf, "只能修改自己的密码");
|
||||
|
||||
try {
|
||||
// 生成新的加密密码
|
||||
String newMd5Pwd = MD5Util.encryptToHex(newPassword + sysUser.getSalt());
|
||||
sysUser.setPwd(newMd5Pwd);
|
||||
// 假设客户端已经对密码进行了一次MD5加密,服务端使用双重加密验证
|
||||
String newEncryptedPwd = MD5Util.doubleEncrypt(newPassword, sysUser.getSalt());
|
||||
sysUser.setPwd(newEncryptedPwd);
|
||||
|
||||
// 更新用户密码
|
||||
sysUserMapper.update(sysUser);
|
||||
|
|
@ -732,6 +793,18 @@ public class SysUserServiceImpl implements SysUserService {
|
|||
sysUser = createUserByPhone(phone);
|
||||
}
|
||||
|
||||
// 检查用户是否已有token,如果有则使旧token失效
|
||||
String oldToken = CacheManager.getTokenFromCache(sysUser.getUserName());
|
||||
if (oldToken != null && !oldToken.isEmpty()) {
|
||||
// 从Redis中删除旧token对应的登录信息
|
||||
redissonClient.getBucket("loginUser:" + oldToken).delete();
|
||||
// 使旧token失效
|
||||
cn.dev33.satoken.stp.StpUtil.logoutByTokenValue(oldToken);
|
||||
// 从缓存中移除旧token
|
||||
CacheManager.removeTokenFromCache(sysUser.getUserName());
|
||||
log.info("用户:{}的旧token已失效", sysUser.getUserName());
|
||||
}
|
||||
|
||||
// 使用Sa-Token登录,生成token
|
||||
cn.dev33.satoken.stp.StpUtil.login(sysUser.getUserId());
|
||||
// 获取生成的token
|
||||
|
|
@ -806,6 +879,9 @@ public class SysUserServiceImpl implements SysUserService {
|
|||
// 将LoginUser对象存储到Redis缓存中,使用token作为key
|
||||
redissonClient.getBucket("loginUser:" + token).set(cn.hutool.json.JSONUtil.toJsonStr(loginUser), 86400, java.util.concurrent.TimeUnit.SECONDS);
|
||||
|
||||
// 存储token与用户名的映射关系到CacheManager
|
||||
CacheManager.putTokenToCache(sysUser.getUserName(), token);
|
||||
|
||||
// 创建LoginUserDto返回对象
|
||||
LoginUserDto sysUserDto = buildLoginUserDto(loginUser);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
common:
|
||||
# Redis配置
|
||||
redis:
|
||||
host: 127.0.0.1
|
||||
port: 6379
|
||||
# host: 43.248.97.19
|
||||
# port: 16379
|
||||
# host: 127.0.0.1
|
||||
# port: 6379
|
||||
host: 43.248.97.19
|
||||
port: 16379
|
||||
password: 654321
|
||||
database: 1
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ web:
|
|||
path: /kexue/agent-skills/upload/
|
||||
|
||||
# 支付配置
|
||||
|
||||
payment:
|
||||
# 微信支付配置
|
||||
wechat:
|
||||
|
|
@ -115,15 +116,15 @@ payment:
|
|||
mchSerialNo: 5EFC47D3AA59BFD1AAE548F96B5E19E1C60F067D
|
||||
privateKeyPath: apiclient_key.pem
|
||||
domain: https://api.mch.weixin.qq.com
|
||||
notifyUrl: http://127.0.0.1:19001/pay/wx/notify
|
||||
returnUrl: http://127.0.0.1:19001/pay/success
|
||||
notifyUrl: http://127.0.0.1:19001/api/pay/wx/notify
|
||||
returnUrl: http://127.0.0.1:19001/api/pay/success
|
||||
# 支付宝支付配置
|
||||
alipay:
|
||||
appId: 2021004138642603
|
||||
privateKey: "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCBzqh/sBfx8UsiKIzSaGm3QwMape+PEmHaFYsP0XxRLyRe5d3H1r4JBvE/GBCDarXkZMvJ3PKeUpO61i7LZtNBN7M6XbMvs/eiaipUmWCNF4IK+ilhOqr8GNryjb6tBnO0uzd1c7UmAvxF+MKkxti0qfscP+Tr6pkuF14DofOyITY56x0y36DmEc85rr213llQ/bSX5nVPHWfddtrqB+TNFvrnAN10NxnUurDK+wd7fKq3TgMjYNDINPGxFYbYezeIGvYj6E34mFS3b3wyxTcB5DeL4GV1FAWqJ0Yk+3hHT3OdmK/UnNEr55w+r3liQBCDRBoE4fldbG5CtW2/ER0lAgMBAAECggEAC2kgNMFFCZaddS49Ws2k5WA1qKUHjvsdsO8N32EZ3YUYXGM2gLem0uJSWKqD4RmDTcVyiJcsmLBHnjfvux+Z2HTOA4ZzFvFqBlPwzqkA7MYxP0fIVWyz1R9WN9Yv+cPEbhG7CU8XkHTYuknoylVUfWUn1s7jD736oyuYrxcQdgsHOHpLHngvsELLa1pv2EURohvr4p+zirMjFGuz3BVaGgVpWegn0nJ/8n1y0ZTM04Mvm/zXpGQQxfuUxrK2owQMFViY7BrRQXlPVeUM/IPAx7cvxLkR5hl9UgAl+nH6FCsm5osEvUln6VLhGTmNFBLCN9piX6sZaPEKZKRBCz0GQQKBgQDD4Dq+dGQAoCmnXdkzI6DHGXOePa+sGnj1Y55dRcrPWPKtCPeEnIPxhVCJ2+cqYK49K6youhLYzs3h8y/M4lh0JQLKP4zTSyZnARmdYHW/SyTu9BcHCdiPwZBrmn7bCWotGf3r5QRIJT6ilZEj8cLnF+9+gd0YyLyRE7Rmihq2UQKBgQCpps7qghRv3JIB0Hb4nBCbAeyPMjHj+7BSUsui2Dhdg3MeTk48a7RLl+r139pMzgTm5Pj0VG6qslUeqP2HlQ46o0Z2bPeohfXH4zMJi2amh4MvAFp4t8eNCc6faeqpJPTTQj3hS4drFnHEHBeFfgFCXZKhjYeP7SP2WVLOQvUAlQKBgFIq6fmjEaBBj7ep4sdVFsjuoFWtQthLcppd47z03hMFGSgFLu/uSFs0tYhfOyXH0M/QVmmhRO62Mh+qyE6GVNzD+dultQmd6Mok5/3gzQQmHaQvuMk3FCWZ6V96O+Temi+5S499TsKE/TVu0Kfnbv9KRykmiP0wmAmz3mV1YadBAoGABc5quIX5MxbmfF9pIvscamG3efMq1/WuRDMHOyyRSUoNb5UYgmLhSdEKPp4Jt6U5b7mYd6xIGVl/Jkx8WN6WHRWnfLggBcmH7u5sub/mpH5w0/P8JLONhds3Eieq210jb/ONcJ+II/chr6eSeoQkgOP498SDRj7Eg1LtTZfnEL0CgYBnMeXQWKUae+xES5NsEX7D0lwSCotb7attTHeE6vZOI77TzsURb4jOEAhYVsdJ8lm+J1Sv1Wjnr2yMxiRH2G+I1tUxGcI8OkRT26FxFdMl1RdbTf+gDM8IjMiu+Li+plIzb28VtF8q/Umgd+5LTlSBmM2yoiL8RKtmStjr5iIuhA=="
|
||||
publicKey: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnakP04nUmsoFoveIvOhbLqkA1xQuYtvkrqq2AVvTsbtqpsEOTm9G095e2rBYLp89oDcf6L6BhtJPwdrhnA+qifUyVmACI9sprrsGeRYQgndK7y4c6spQcSnsnakSxlIp22j7pvBXNAZuqud2hQV+TOLKEUh1W3izTgMj/Ejoh3ZsCjgDRtTVgaytzSdHYrhNku+pIrl15/xVGJED99RYXkR8GHawxuK+vWVmxU0tiTCwTsqLz43v6TtCZ+/UfLL/luwp9B4ZvB+0qon82LILYr6oxs10kE2IAvryuDToAc1s/v/36jgt+7DXwqzfUDksHhVLHdJHChyc4ax5HmMsBwIDAQAB"
|
||||
notifyUrl: http://127.0.0.1:19001/pay/ali-pay/trade/notify
|
||||
notifyUrl: http://127.0.0.1:19001/api/pay/alipay/trade/notify
|
||||
returnUrl: https://shuziren.xueai.art/alipay-success
|
||||
signType: RSA2
|
||||
charset: UTF-8
|
||||
gatewayUrl: https://openapi.alipay.com/gateway.do
|
||||
gatewayUrl: https://openapi.alipay.com/gateway.do
|
||||
|
|
@ -101,3 +101,25 @@ jetcache:
|
|||
web:
|
||||
upload:
|
||||
path: /kexue/agent-skills/upload/
|
||||
|
||||
payment:
|
||||
# 微信支付配置
|
||||
wechat:
|
||||
appId: wx7d13d99de5be3bfa
|
||||
mchId: 1673321732
|
||||
mchKey: UDuZXDcmy5Eb6o0nTNZhu6ek4DDh4K8B
|
||||
mchSerialNo: 5EFC47D3AA59BFD1AAE548F96B5E19E1C60F067D
|
||||
privateKeyPath: apiclient_key.pem
|
||||
domain: https://api.mch.weixin.qq.com
|
||||
notifyUrl: http://43.248.97.19:19000/pay/wx/notify
|
||||
returnUrl: http://43.248.97.19:19000/pay/success
|
||||
# 支付宝支付配置
|
||||
alipay:
|
||||
appId: 2021004138642603
|
||||
privateKey: "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCBzqh/sBfx8UsiKIzSaGm3QwMape+PEmHaFYsP0XxRLyRe5d3H1r4JBvE/GBCDarXkZMvJ3PKeUpO61i7LZtNBN7M6XbMvs/eiaipUmWCNF4IK+ilhOqr8GNryjb6tBnO0uzd1c7UmAvxF+MKkxti0qfscP+Tr6pkuF14DofOyITY56x0y36DmEc85rr213llQ/bSX5nVPHWfddtrqB+TNFvrnAN10NxnUurDK+wd7fKq3TgMjYNDINPGxFYbYezeIGvYj6E34mFS3b3wyxTcB5DeL4GV1FAWqJ0Yk+3hHT3OdmK/UnNEr55w+r3liQBCDRBoE4fldbG5CtW2/ER0lAgMBAAECggEAC2kgNMFFCZaddS49Ws2k5WA1qKUHjvsdsO8N32EZ3YUYXGM2gLem0uJSWKqD4RmDTcVyiJcsmLBHnjfvux+Z2HTOA4ZzFvFqBlPwzqkA7MYxP0fIVWyz1R9WN9Yv+cPEbhG7CU8XkHTYuknoylVUfWUn1s7jD736oyuYrxcQdgsHOHpLHngvsELLa1pv2EURohvr4p+zirMjFGuz3BVaGgVpWegn0nJ/8n1y0ZTM04Mvm/zXpGQQxfuUxrK2owQMFViY7BrRQXlPVeUM/IPAx7cvxLkR5hl9UgAl+nH6FCsm5osEvUln6VLhGTmNFBLCN9piX6sZaPEKZKRBCz0GQQKBgQDD4Dq+dGQAoCmnXdkzI6DHGXOePa+sGnj1Y55dRcrPWPKtCPeEnIPxhVCJ2+cqYK49K6youhLYzs3h8y/M4lh0JQLKP4zTSyZnARmdYHW/SyTu9BcHCdiPwZBrmn7bCWotGf3r5QRIJT6ilZEj8cLnF+9+gd0YyLyRE7Rmihq2UQKBgQCpps7qghRv3JIB0Hb4nBCbAeyPMjHj+7BSUsui2Dhdg3MeTk48a7RLl+r139pMzgTm5Pj0VG6qslUeqP2HlQ46o0Z2bPeohfXH4zMJi2amh4MvAFp4t8eNCc6faeqpJPTTQj3hS4drFnHEHBeFfgFCXZKhjYeP7SP2WVLOQvUAlQKBgFIq6fmjEaBBj7ep4sdVFsjuoFWtQthLcppd47z03hMFGSgFLu/uSFs0tYhfOyXH0M/QVmmhRO62Mh+qyE6GVNzD+dultQmd6Mok5/3gzQQmHaQvuMk3FCWZ6V96O+Temi+5S499TsKE/TVu0Kfnbv9KRykmiP0wmAmz3mV1YadBAoGABc5quIX5MxbmfF9pIvscamG3efMq1/WuRDMHOyyRSUoNb5UYgmLhSdEKPp4Jt6U5b7mYd6xIGVl/Jkx8WN6WHRWnfLggBcmH7u5sub/mpH5w0/P8JLONhds3Eieq210jb/ONcJ+II/chr6eSeoQkgOP498SDRj7Eg1LtTZfnEL0CgYBnMeXQWKUae+xES5NsEX7D0lwSCotb7attTHeE6vZOI77TzsURb4jOEAhYVsdJ8lm+J1Sv1Wjnr2yMxiRH2G+I1tUxGcI8OkRT26FxFdMl1RdbTf+gDM8IjMiu+Li+plIzb28VtF8q/Umgd+5LTlSBmM2yoiL8RKtmStjr5iIuhA=="
|
||||
publicKey: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnakP04nUmsoFoveIvOhbLqkA1xQuYtvkrqq2AVvTsbtqpsEOTm9G095e2rBYLp89oDcf6L6BhtJPwdrhnA+qifUyVmACI9sprrsGeRYQgndK7y4c6spQcSnsnakSxlIp22j7pvBXNAZuqud2hQV+TOLKEUh1W3izTgMj/Ejoh3ZsCjgDRtTVgaytzSdHYrhNku+pIrl15/xVGJED99RYXkR8GHawxuK+vWVmxU0tiTCwTsqLz43v6TtCZ+/UfLL/luwp9B4ZvB+0qon82LILYr6oxs10kE2IAvryuDToAc1s/v/36jgt+7DXwqzfUDksHhVLHdJHChyc4ax5HmMsBwIDAQAB"
|
||||
notifyUrl: http://43.248.97.19:19000/pay/ali-pay/trade/notify
|
||||
returnUrl: https://shuziren.xueai.art/alipay-success
|
||||
signType: RSA2
|
||||
charset: UTF-8
|
||||
gatewayUrl: https://openapi.alipay.com/gateway.do
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
spring:
|
||||
profiles:
|
||||
active: dev
|
||||
active: prod
|
||||
application:
|
||||
name: agentSkills
|
||||
version: 1.0.0
|
||||
|
|
@ -35,6 +35,13 @@ spring:
|
|||
model: deepseek-chat
|
||||
temperature: 0.3
|
||||
max-tokens: 500
|
||||
glm:
|
||||
base-url: https://open.bigmodel.cn/api/paas/v4
|
||||
api-key: ${GLM_API_KEY:57a566a125bb4492900db0578969f27d.JLpuGSzr9hhLurM7}
|
||||
chat:
|
||||
model: glm-4.6v
|
||||
temperature: 0.7
|
||||
max-tokens: 8192
|
||||
|
||||
# 包含公共配置文件
|
||||
spring.config.import:
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<configuration scan="true" scanPeriod="60 seconds">
|
||||
|
||||
<!-- 定义日志文件的存储路径 -->
|
||||
<property name="LOG_HOME" value="/data/service/logs/yuelong-portal" />
|
||||
<property name="LOG_HOME" value="/kexue/agentSkills/backend/logs" />
|
||||
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||
|
|
@ -13,10 +13,10 @@
|
|||
|
||||
<!-- 每日滚动文件输出 -->
|
||||
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${LOG_HOME}/hyxp-portal.log</file>
|
||||
<file>${LOG_HOME}/skill.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 每天生成一个新的日志文件 -->
|
||||
<fileNamePattern>${LOG_HOME}/hyxp-portal.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<fileNamePattern>${LOG_HOME}/skill.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<!-- 保留 30 天的历史日志文件 -->
|
||||
<maxHistory>30</maxHistory>
|
||||
</rollingPolicy>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@
|
|||
<result property="subtitle" column="subtitle" jdbcType="VARCHAR"/>
|
||||
<result property="contentType" column="content_type" jdbcType="INTEGER"/>
|
||||
<result property="summary" column="summary" jdbcType="VARCHAR"/>
|
||||
<result property="description" column="description" jdbcType="LONGVARCHAR"/>
|
||||
<result property="requirement" column="requirement" jdbcType="LONGVARCHAR"/>
|
||||
<result property="introduce" column="introduce" jdbcType="LONGVARCHAR"/>
|
||||
<result property="content" column="content" jdbcType="LONGVARCHAR"/>
|
||||
<result property="coverImage" column="cover_image" jdbcType="VARCHAR"/>
|
||||
<result property="authorId" column="author_id" jdbcType="BIGINT"/>
|
||||
|
|
@ -43,7 +46,7 @@
|
|||
<!--查询单个-->
|
||||
<select id="queryById" resultMap="CmsContentMap">
|
||||
select
|
||||
content_id, title, subtitle, content_type, summary, content, cover_image, author_id, author_name,
|
||||
content_id, title, subtitle, content_type, summary, description, requirement, introduce, 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, origin, tags, create_time, update_time, create_by, update_by, delete_flag
|
||||
from cms_content
|
||||
|
|
@ -53,7 +56,7 @@
|
|||
<!--查询分页列表-->
|
||||
<select id="getPageList" resultMap="CmsContentMap">
|
||||
select
|
||||
content_id, title, subtitle, content_type, summary, content, cover_image, author_id, author_name,
|
||||
content_id, title, subtitle, content_type, summary, description, requirement, introduce, 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, origin, tags, create_time, update_time, create_by, update_by, delete_flag
|
||||
from cms_content
|
||||
|
|
@ -103,7 +106,7 @@
|
|||
<!--带分页的查询-->
|
||||
<select id="getPageListWithPagination" resultMap="CmsContentMap">
|
||||
select
|
||||
content_id, title, subtitle, content_type, summary, content, cover_image, author_id, author_name,
|
||||
content_id, title, subtitle, content_type, summary, description, requirement, introduce, 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, origin, tags, create_time, update_time, create_by, update_by, delete_flag
|
||||
from cms_content
|
||||
|
|
@ -195,7 +198,7 @@
|
|||
<!--查询列表-->
|
||||
<select id="getList" resultMap="CmsContentMap">
|
||||
select
|
||||
content_id, title, subtitle, content_type, summary, content, cover_image, author_id, author_name,
|
||||
content_id, title, subtitle, content_type, summary, description, requirement, introduce, 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, origin, tags, create_time, update_time, create_by, update_by, delete_flag
|
||||
from cms_content
|
||||
|
|
@ -233,10 +236,10 @@
|
|||
|
||||
<!--新增所有列-->
|
||||
<insert id="insert" keyProperty="contentId" useGeneratedKeys="true">
|
||||
insert into cms_content(title, subtitle, content_type, summary, content, cover_image, author_id, author_name,
|
||||
insert into cms_content(title, subtitle, content_type, summary, description, requirement, introduce, 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, origin, tags, create_time, update_time, create_by, update_by, delete_flag)
|
||||
values (#{title}, #{subtitle}, #{contentType}, #{summary}, #{content}, #{coverImage}, #{authorId}, #{authorName},
|
||||
values (#{title}, #{subtitle}, #{contentType}, #{summary}, #{description}, #{requirement}, #{introduce}, #{content}, #{coverImage}, #{authorId}, #{authorName},
|
||||
#{reviewerId}, #{reviewerName}, #{auditStatus}, #{auditComment}, #{publishStatus}, #{publishTime},
|
||||
#{viewCount}, #{likeCount}, #{commentCount}, #{sort}, #{isPaid}, #{price}, #{requiredPoints}, #{supportPointsPay}, #{isOfficial}, #{shareCount}, #{fileUrl}, #{icon}, #{background}, #{origin}, #{tags}, #{createTime}, #{updateTime}, #{createBy}, #{updateBy}, #{deleteFlag})
|
||||
</insert>
|
||||
|
|
@ -257,6 +260,15 @@
|
|||
<if test="summary != null">
|
||||
summary = #{summary},
|
||||
</if>
|
||||
<if test="description != null">
|
||||
description = #{description},
|
||||
</if>
|
||||
<if test="requirement != null">
|
||||
requirement = #{requirement},
|
||||
</if>
|
||||
<if test="introduce != null">
|
||||
introduce = #{introduce},
|
||||
</if>
|
||||
<if test="content != null">
|
||||
content = #{content},
|
||||
</if>
|
||||
|
|
@ -391,4 +403,92 @@
|
|||
limit #{limit}
|
||||
</select>
|
||||
|
||||
<!--获取用户历史查看的内容列表-->
|
||||
<select id="getPageListByUserHistory" resultMap="CmsContentMap">
|
||||
select
|
||||
c.content_id, c.title, c.subtitle, c.content_type, c.summary, c.description, c.requirement, c.introduce, c.content, c.cover_image, c.author_id, c.author_name,
|
||||
c.reviewer_id, c.reviewer_name, c.audit_status, c.audit_comment, c.publish_status, c.publish_time,
|
||||
c.view_count, c.like_count, c.comment_count, c.sort, c.is_paid, c.price, c.required_points, c.support_points_pay, c.is_official, c.share_count, c.file_url, c.icon, c.background, c.origin, c.tags, c.create_time, c.update_time, c.create_by, c.update_by, c.delete_flag
|
||||
from cms_content c
|
||||
inner join cms_content_view cv on c.content_id = cv.content_id
|
||||
where cv.user_id = #{userId} and c.delete_flag = 0
|
||||
order by cv.view_time desc
|
||||
limit #{offset}, #{limit}
|
||||
</select>
|
||||
|
||||
<!--获取用户历史查看的内容总数-->
|
||||
<select id="getPageListByUserHistoryCount" resultType="int">
|
||||
select count(distinct c.content_id)
|
||||
from cms_content c
|
||||
inner join cms_content_view cv on c.content_id = cv.content_id
|
||||
where cv.user_id = #{userId} and c.delete_flag = 0
|
||||
</select>
|
||||
|
||||
<!--获取用户收藏的内容列表-->
|
||||
<select id="getPageListByUserFavorites" resultMap="CmsContentMap">
|
||||
select
|
||||
c.content_id, c.title, c.subtitle, c.content_type, c.summary, c.description, c.requirement, c.introduce, c.content, c.cover_image, c.author_id, c.author_name,
|
||||
c.reviewer_id, c.reviewer_name, c.audit_status, c.audit_comment, c.publish_status, c.publish_time,
|
||||
c.view_count, c.like_count, c.comment_count, c.sort, c.is_paid, c.price, c.required_points, c.support_points_pay, c.is_official, c.share_count, c.file_url, c.icon, c.background, c.origin, c.tags, c.create_time, c.update_time, c.create_by, c.update_by, c.delete_flag
|
||||
from cms_content c
|
||||
inner join cms_content_like cl on c.content_id = cl.content_id
|
||||
where cl.user_id = #{userId} and c.delete_flag = 0
|
||||
order by cl.like_time desc
|
||||
limit #{offset}, #{limit}
|
||||
</select>
|
||||
|
||||
<!--获取用户收藏的内容总数-->
|
||||
<select id="getPageListByUserFavoritesCount" resultType="int">
|
||||
select count(distinct c.content_id)
|
||||
from cms_content c
|
||||
inner join cms_content_like cl on c.content_id = cl.content_id
|
||||
where cl.user_id = #{userId} and c.delete_flag = 0
|
||||
</select>
|
||||
|
||||
<!--获取用户购买的内容列表-->
|
||||
<select id="getPageListByUserPurchases" resultMap="CmsContentMap">
|
||||
select
|
||||
c.content_id, c.title, c.subtitle, c.content_type, c.summary, c.description, c.requirement, c.introduce, c.content, c.cover_image, c.author_id, c.author_name,
|
||||
c.reviewer_id, c.reviewer_name, c.audit_status, c.audit_comment, c.publish_status, c.publish_time,
|
||||
c.view_count, c.like_count, c.comment_count, c.sort, c.is_paid, c.price, c.required_points, c.support_points_pay, c.is_official, c.share_count, c.file_url, c.icon, c.background, c.origin, c.tags, c.create_time, c.update_time, c.create_by, c.update_by, c.delete_flag
|
||||
from cms_content c
|
||||
inner join content_purchase cp on c.content_id = cp.content_id
|
||||
where cp.user_id = #{userId} and cp.status = 1 and c.delete_flag = 0
|
||||
order by cp.purchase_time desc
|
||||
limit #{offset}, #{limit}
|
||||
</select>
|
||||
|
||||
<!--获取用户购买的内容总数-->
|
||||
<select id="getPageListByUserPurchasesCount" resultType="int">
|
||||
select count(distinct c.content_id)
|
||||
from cms_content c
|
||||
inner join content_purchase cp on c.content_id = cp.content_id
|
||||
where cp.user_id = #{userId} and cp.status = 1 and c.delete_flag = 0
|
||||
</select>
|
||||
|
||||
<!--获取用户创建的内容列表-->
|
||||
<select id="getPageListByUserCreated" resultMap="CmsContentMap">
|
||||
select
|
||||
content_id, title, subtitle, content_type, summary, description, requirement, introduce, 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, origin, tags, create_time, update_time, create_by, update_by, delete_flag
|
||||
from cms_content
|
||||
where author_id = #{userId} and delete_flag = 0
|
||||
<if test="publishStatus != null">
|
||||
and publish_status = #{publishStatus}
|
||||
</if>
|
||||
order by create_time desc
|
||||
limit #{offset}, #{limit}
|
||||
</select>
|
||||
|
||||
<!--获取用户创建的内容总数-->
|
||||
<select id="getPageListByUserCreatedCount" resultType="int">
|
||||
select count(*)
|
||||
from cms_content
|
||||
where author_id = #{userId} and delete_flag = 0
|
||||
<if test="publishStatus != null">
|
||||
and publish_status = #{publishStatus}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
<result property="description" column="description" jdbcType="VARCHAR"/>
|
||||
<result property="useCount" column="use_count" jdbcType="INTEGER"/>
|
||||
<result property="status" column="status" jdbcType="INTEGER"/>
|
||||
<result property="icon" column="icon" jdbcType="VARCHAR"/>
|
||||
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
|
||||
<result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
|
||||
<result property="createBy" column="create_by" jdbcType="VARCHAR"/>
|
||||
|
|
@ -18,7 +19,7 @@
|
|||
<!--查询单个-->
|
||||
<select id="queryById" resultMap="CmsTagMap">
|
||||
select
|
||||
tag_id, tag_name, description, use_count, status, create_time, update_time, create_by, update_by, delete_flag
|
||||
tag_id, tag_name, description, use_count, status, icon, create_time, update_time, create_by, update_by, delete_flag
|
||||
from cms_tag
|
||||
where tag_id = #{tagId}
|
||||
</select>
|
||||
|
|
@ -26,7 +27,7 @@
|
|||
<!--查询分页列表-->
|
||||
<select id="getPageList" resultMap="CmsTagMap">
|
||||
select
|
||||
tag_id, tag_name, description, use_count, status, create_time, update_time, create_by, update_by, delete_flag
|
||||
tag_id, tag_name, description, use_count, status, icon, create_time, update_time, create_by, update_by, delete_flag
|
||||
from cms_tag
|
||||
<where>
|
||||
<if test="tagId != null">
|
||||
|
|
@ -48,7 +49,7 @@
|
|||
<!--查询列表-->
|
||||
<select id="getList" resultMap="CmsTagMap">
|
||||
select
|
||||
tag_id, tag_name, description, use_count, status, create_time, update_time, create_by, update_by, delete_flag
|
||||
tag_id, tag_name, description, use_count, status, icon, create_time, update_time, create_by, update_by, delete_flag
|
||||
from cms_tag
|
||||
<where>
|
||||
<if test="tagId != null">
|
||||
|
|
@ -69,8 +70,8 @@
|
|||
|
||||
<!--新增所有列-->
|
||||
<insert id="insert" keyProperty="tagId" useGeneratedKeys="true">
|
||||
insert into cms_tag(tag_name, description, use_count, status, create_time, update_time, create_by, update_by, delete_flag)
|
||||
values (#{tagName}, #{description}, #{useCount}, #{status}, #{createTime}, #{updateTime}, #{createBy}, #{updateBy}, #{deleteFlag})
|
||||
insert into cms_tag(tag_name, description, use_count, status, icon, create_time, update_time, create_by, update_by, delete_flag)
|
||||
values (#{tagName}, #{description}, #{useCount}, #{status}, #{icon}, #{createTime}, #{updateTime}, #{createBy}, #{updateBy}, #{deleteFlag})
|
||||
</insert>
|
||||
|
||||
<!--通过主键修改数据-->
|
||||
|
|
@ -89,6 +90,9 @@
|
|||
<if test="status != null">
|
||||
status = #{status},
|
||||
</if>
|
||||
<if test="icon != null">
|
||||
icon = #{icon},
|
||||
</if>
|
||||
<if test="updateTime != null">
|
||||
update_time = #{updateTime},
|
||||
</if>
|
||||
|
|
@ -114,7 +118,7 @@
|
|||
<!--根据分类ID查询标签列表-->
|
||||
<select id="getTagsByCategoryId" resultMap="CmsTagMap">
|
||||
select
|
||||
t.tag_id, t.tag_name, t.description, t.use_count, t.status, t.create_time, t.update_time, t.create_by, t.update_by, t.delete_flag
|
||||
t.tag_id, t.tag_name, t.description, t.use_count, t.status, t.icon, t.create_time, t.update_time, t.create_by, t.update_by, t.delete_flag
|
||||
from cms_tag t
|
||||
inner join cms_category_tag ct on t.tag_id = ct.tag_id
|
||||
where ct.category_id = #{categoryId} and t.delete_flag = 0 and t.status = 1
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@
|
|||
<result property="payType" column="pay_type" jdbcType="INTEGER"/>
|
||||
<result property="status" column="status" jdbcType="INTEGER"/>
|
||||
<result property="channelOrderNo" column="channel_order_no" jdbcType="VARCHAR"/>
|
||||
<result property="BusinessId" column="business_id" jdbcType="BIGINT"/>
|
||||
<result property="BusinessType" column="business_type" jdbcType="VARCHAR"/>
|
||||
<result property="businessId" column="business_id" jdbcType="BIGINT"/>
|
||||
<result property="businessType" column="business_type" jdbcType="VARCHAR"/>
|
||||
<result property="remark" column="remark" jdbcType="VARCHAR"/>
|
||||
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
|
||||
<result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
|
||||
|
|
@ -118,7 +118,7 @@
|
|||
<if test="userId != null">user_id,</if>
|
||||
<if test="userName != null">user_name,</if>
|
||||
<if test="amount != null">amount,</if>
|
||||
<if test="payType != null">pay_type,</if>
|
||||
pay_type,
|
||||
<if test="status != null">status,</if>
|
||||
<if test="channelOrderNo != null">channel_order_no,</if>
|
||||
<if test="businessId != null">business_id,</if>
|
||||
|
|
@ -135,7 +135,7 @@
|
|||
<if test="userId != null">#{userId},</if>
|
||||
<if test="userName != null">#{userName},</if>
|
||||
<if test="amount != null">#{amount},</if>
|
||||
<if test="payType != null">#{payType},</if>
|
||||
#{payType},
|
||||
<if test="status != null">#{status},</if>
|
||||
<if test="channelOrderNo != null">#{channelOrderNo},</if>
|
||||
<if test="businessId != null">#{businessId},</if>
|
||||
|
|
|
|||
Loading…
Reference in New Issue