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
|
@RestController
|
||||||
@RequestMapping("api/cmsContent")
|
@RequestMapping("api/cmsContent")
|
||||||
@Tag(name = "内容(skills)管理 Api")
|
@Tag(name = "skill(skills)管理 Api")
|
||||||
@CrossOrigin(origins = "*")
|
@CrossOrigin(origins = "*")
|
||||||
public class CmsContentController {
|
public class CmsContentController {
|
||||||
/**
|
/**
|
||||||
|
|
@ -60,7 +60,7 @@ public class CmsContentController {
|
||||||
* @return 单条数据
|
* @return 单条数据
|
||||||
*/
|
*/
|
||||||
@PostMapping("queryById/{contentId}")
|
@PostMapping("queryById/{contentId}")
|
||||||
@Operation(summary = "通过ID查询内容", description = "通过ID查询内容")
|
@Operation(summary = "通过ID查询skill", description = "通过ID查询skill")
|
||||||
public CommonResult<CmsContent> queryById(@PathVariable("contentId") Long contentId) {
|
public CommonResult<CmsContent> queryById(@PathVariable("contentId") Long contentId) {
|
||||||
// 增加阅读量
|
// 增加阅读量
|
||||||
cmsContentService.increaseViewCount(contentId);
|
cmsContentService.increaseViewCount(contentId);
|
||||||
|
|
@ -74,7 +74,7 @@ public class CmsContentController {
|
||||||
* @return 新增结果
|
* @return 新增结果
|
||||||
*/
|
*/
|
||||||
@PostMapping("/insert")
|
@PostMapping("/insert")
|
||||||
@Operation(summary = "新增内容", description = "新增内容")
|
@Operation(summary = "新增skill", description = "新增skill")
|
||||||
@RequireAuth
|
@RequireAuth
|
||||||
public CommonResult<CmsContent> insert(@RequestBody CmsContent cmsContent) {
|
public CommonResult<CmsContent> insert(@RequestBody CmsContent cmsContent) {
|
||||||
return CommonResult.success(cmsContentService.insert(cmsContent));
|
return CommonResult.success(cmsContentService.insert(cmsContent));
|
||||||
|
|
@ -87,7 +87,7 @@ public class CmsContentController {
|
||||||
* @return 编辑结果
|
* @return 编辑结果
|
||||||
*/
|
*/
|
||||||
@PostMapping("/update")
|
@PostMapping("/update")
|
||||||
@Operation(summary = "更新内容", description = "更新内容")
|
@Operation(summary = "更新skill", description = "更新skill")
|
||||||
@RequireAuth
|
@RequireAuth
|
||||||
public CommonResult<CmsContent> update(@RequestBody CmsContent cmsContent) {
|
public CommonResult<CmsContent> update(@RequestBody CmsContent cmsContent) {
|
||||||
return CommonResult.success(cmsContentService.update(cmsContent));
|
return CommonResult.success(cmsContentService.update(cmsContent));
|
||||||
|
|
@ -96,7 +96,7 @@ public class CmsContentController {
|
||||||
/**
|
/**
|
||||||
* 更新审核状态
|
* 更新审核状态
|
||||||
*
|
*
|
||||||
* @param contentId 内容ID
|
* @param contentId skillID
|
||||||
* @param auditStatus 审核状态
|
* @param auditStatus 审核状态
|
||||||
* @param reviewerId 审核人ID
|
* @param reviewerId 审核人ID
|
||||||
* @param reviewerName 审核人名称
|
* @param reviewerName 审核人名称
|
||||||
|
|
@ -117,7 +117,7 @@ public class CmsContentController {
|
||||||
/**
|
/**
|
||||||
* 更新发布状态
|
* 更新发布状态
|
||||||
*
|
*
|
||||||
* @param contentId 内容ID
|
* @param contentId skillID
|
||||||
* @param publishStatus 发布状态
|
* @param publishStatus 发布状态
|
||||||
* @param publishTime 发布时间
|
* @param publishTime 发布时间
|
||||||
* @param updateBy 更新人
|
* @param updateBy 更新人
|
||||||
|
|
@ -136,7 +136,7 @@ public class CmsContentController {
|
||||||
/**
|
/**
|
||||||
* 增加阅读量
|
* 增加阅读量
|
||||||
*
|
*
|
||||||
* @param contentId 内容ID
|
* @param contentId skillID
|
||||||
* @return 增加结果
|
* @return 增加结果
|
||||||
*/
|
*/
|
||||||
@PostMapping("/increaseViewCount/{contentId}")
|
@PostMapping("/increaseViewCount/{contentId}")
|
||||||
|
|
@ -152,7 +152,7 @@ public class CmsContentController {
|
||||||
* @return 删除数据
|
* @return 删除数据
|
||||||
*/
|
*/
|
||||||
@PostMapping("/logicDeleteById")
|
@PostMapping("/logicDeleteById")
|
||||||
@Operation(summary = "逻辑删除内容", description = "逻辑删除内容")
|
@Operation(summary = "逻辑删除skill", description = "逻辑删除skill")
|
||||||
@RequireAuth
|
@RequireAuth
|
||||||
public CommonResult<Boolean> logicDeleteById(@RequestBody IdDto idDto) {
|
public CommonResult<Boolean> logicDeleteById(@RequestBody IdDto idDto) {
|
||||||
return CommonResult.success(cmsContentService.logicDeleteById(idDto.getId(), "admin") > 0);
|
return CommonResult.success(cmsContentService.logicDeleteById(idDto.getId(), "admin") > 0);
|
||||||
|
|
@ -165,7 +165,7 @@ public class CmsContentController {
|
||||||
* @return 删除数据
|
* @return 删除数据
|
||||||
*/
|
*/
|
||||||
@PostMapping("deleteById/{contentId}")
|
@PostMapping("deleteById/{contentId}")
|
||||||
@Operation(summary = "物理删除内容", description = "物理删除内容")
|
@Operation(summary = "物理删除skill", description = "物理删除skill")
|
||||||
@RequireAuth
|
@RequireAuth
|
||||||
public CommonResult<Boolean> deleteById(@PathVariable("contentId") Long contentId) {
|
public CommonResult<Boolean> deleteById(@PathVariable("contentId") Long contentId) {
|
||||||
return CommonResult.success(cmsContentService.deleteById(contentId) > 0);
|
return CommonResult.success(cmsContentService.deleteById(contentId) > 0);
|
||||||
|
|
@ -174,26 +174,91 @@ public class CmsContentController {
|
||||||
/**
|
/**
|
||||||
* 添加收藏
|
* 添加收藏
|
||||||
*
|
*
|
||||||
* @param contentId 内容ID
|
* @param contentId skillID
|
||||||
* @return 操作结果
|
* @return 操作结果
|
||||||
*/
|
*/
|
||||||
@PostMapping("/addFavorite")
|
@PostMapping("/addFavorite")
|
||||||
@Operation(summary = "添加收藏", description = "添加内容收藏")
|
@Operation(summary = "添加收藏", description = "添加skill收藏")
|
||||||
@RequireAuth
|
@RequireAuth
|
||||||
public CommonResult<Boolean> addFavorite(@RequestParam("contentId") Long contentId) {
|
public CommonResult<Boolean> addFavorite(@RequestParam("contentId") Long contentId) {
|
||||||
return CommonResult.success(cmsContentService.addFavorite(contentId) > 0);
|
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 操作结果
|
* @return 操作结果
|
||||||
*/
|
*/
|
||||||
@PostMapping("/addView")
|
@PostMapping("/addView")
|
||||||
@Operation(summary = "添加查看记录", description = "添加内容查看记录")
|
@Operation(summary = "添加查看记录", description = "添加skill查看记录")
|
||||||
@RequireAuth
|
@RequireAuth
|
||||||
public CommonResult<Boolean> addView(@RequestParam("contentId") Long contentId) {
|
public CommonResult<Boolean> addView(@RequestParam("contentId") Long contentId) {
|
||||||
return CommonResult.success(cmsContentService.addView(contentId) > 0);
|
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")
|
@PostMapping("/wx/create")
|
||||||
public CommonResult<Map<String, String>> createWechatPay(@RequestBody PaymentOrder order) {
|
public CommonResult<Map<String, String>> createWechatPay(@RequestBody PaymentOrder order) {
|
||||||
try {
|
try {
|
||||||
|
// 设置支付类型为微信支付(1)
|
||||||
|
order.setPayType(1);
|
||||||
// 创建支付订单
|
// 创建支付订单
|
||||||
PaymentOrder createdOrder = paymentOrderService.createPaymentOrder(order);
|
PaymentOrder createdOrder = paymentOrderService.createPaymentOrder(order);
|
||||||
// 生成微信支付参数
|
// 生成微信支付参数
|
||||||
|
|
@ -56,7 +58,7 @@ public class PayController {
|
||||||
* @return 回调响应
|
* @return 回调响应
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "处理微信支付回调", description = "处理微信支付回调")
|
@Operation(summary = "处理微信支付回调", description = "处理微信支付回调")
|
||||||
@PostMapping("/pay/wx/notify")
|
@PostMapping("/wx/notify")
|
||||||
public String handleWechatPayNotify(HttpServletRequest request) {
|
public String handleWechatPayNotify(HttpServletRequest request) {
|
||||||
return payService.handleWechatPayNotify(request);
|
return payService.handleWechatPayNotify(request);
|
||||||
}
|
}
|
||||||
|
|
@ -70,6 +72,8 @@ public class PayController {
|
||||||
@PostMapping("/alipay/create")
|
@PostMapping("/alipay/create")
|
||||||
public CommonResult<String> createAlipay(@RequestBody PaymentOrder order) {
|
public CommonResult<String> createAlipay(@RequestBody PaymentOrder order) {
|
||||||
try {
|
try {
|
||||||
|
// 设置支付类型为支付宝(2)
|
||||||
|
order.setPayType(2);
|
||||||
// 创建支付订单
|
// 创建支付订单
|
||||||
PaymentOrder createdOrder = paymentOrderService.createPaymentOrder(order);
|
PaymentOrder createdOrder = paymentOrderService.createPaymentOrder(order);
|
||||||
// 生成支付宝支付表单
|
// 生成支付宝支付表单
|
||||||
|
|
@ -87,7 +91,7 @@ public class PayController {
|
||||||
* @return 回调响应
|
* @return 回调响应
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "处理支付宝支付回调", description = "处理支付宝支付回调")
|
@Operation(summary = "处理支付宝支付回调", description = "处理支付宝支付回调")
|
||||||
@PostMapping("/ali-pay/trade/notify")
|
@PostMapping("/alipay/trade/notify")
|
||||||
public String handleAlipayNotify(HttpServletRequest request) {
|
public String handleAlipayNotify(HttpServletRequest request) {
|
||||||
return payService.handleAlipayNotify(request);
|
return payService.handleAlipayNotify(request);
|
||||||
}
|
}
|
||||||
|
|
@ -98,7 +102,7 @@ public class PayController {
|
||||||
* @return 同步回调响应
|
* @return 同步回调响应
|
||||||
*/
|
*/
|
||||||
@Operation(summary = "处理支付宝支付同步回调", description = "处理支付宝支付同步回调")
|
@Operation(summary = "处理支付宝支付同步回调", description = "处理支付宝支付同步回调")
|
||||||
@GetMapping("/ali-pay/trade/return")
|
@GetMapping("/alipay/trade/return")
|
||||||
public CommonResult<Map<String, Object>> handleAlipayReturn(HttpServletRequest request) {
|
public CommonResult<Map<String, Object>> handleAlipayReturn(HttpServletRequest request) {
|
||||||
Map<String, Object> result = payService.handleAlipayReturn(request);
|
Map<String, Object> result = payService.handleAlipayReturn(request);
|
||||||
if (result.get("success").equals(true)) {
|
if (result.get("success").equals(true)) {
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ package com.kexue.skills.controller;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.kexue.skills.common.CommonResult;
|
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.SkillGenRequest;
|
||||||
import com.kexue.skills.entity.request.SkillPreGenRequest;
|
import com.kexue.skills.entity.request.SkillPreGenRequest;
|
||||||
import com.kexue.skills.entity.response.SkillResponse;
|
import com.kexue.skills.entity.response.SkillResponse;
|
||||||
|
|
@ -32,14 +34,26 @@ public class SkillGenController {
|
||||||
* @return 生成结果
|
* @return 生成结果
|
||||||
*/
|
*/
|
||||||
@PostMapping("/preGenerate")
|
@PostMapping("/preGenerate")
|
||||||
@Operation(summary = "生成技能", description = "生成技能")
|
@Operation(summary = "预生成技能", description = "生成技能")
|
||||||
public CommonResult<SkillResponse> preGenerate(@RequestBody SkillPreGenRequest request) {
|
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")
|
@PostMapping("/generate")
|
||||||
@Operation(summary = "生成Skill对应的md文件", description = "生成Skill对应的md文件")
|
@Operation(summary = "生成技能", description = "生成技能")
|
||||||
public CommonResult<JSONObject> generate(@RequestBody SkillGenRequest request) {
|
public CommonResult<CmsContent> generate(@RequestBody SkillGenRequest request) {
|
||||||
return CommonResult.success(skillGenService.generate(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) {
|
public CommonResult<String> analyze(@RequestBody com.kexue.skills.entity.request.SkillAnalyzeRequest request) {
|
||||||
return CommonResult.success(skillGenService.analyzeSkill(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是")
|
@Schema(description ="是否是官方:0否,1是")
|
||||||
private Boolean isOfficial;
|
private Boolean isOfficial;
|
||||||
|
|
||||||
@Schema(description ="分类ID列表,逗号分隔")
|
|
||||||
private String categoryIds;
|
|
||||||
|
|
||||||
@Schema(description ="图标")
|
@Schema(description ="图标")
|
||||||
private String icon;
|
private String icon;
|
||||||
|
|
||||||
|
|
@ -45,6 +42,15 @@ public class CmsContent extends BaseEntity implements Serializable {
|
||||||
@Schema(description ="内容摘要")
|
@Schema(description ="内容摘要")
|
||||||
private String summary;
|
private String summary;
|
||||||
|
|
||||||
|
@Schema(description ="详细描述")
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
@Schema(description ="需求说明")
|
||||||
|
private String requirement;
|
||||||
|
|
||||||
|
@Schema(description ="介绍信息")
|
||||||
|
private String introduce;
|
||||||
|
|
||||||
@Schema(description ="分享数量")
|
@Schema(description ="分享数量")
|
||||||
private Integer shareCount;
|
private Integer shareCount;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,9 @@ public class CmsTag extends BaseEntity implements Serializable {
|
||||||
@Schema(description ="状态(1启用,2禁用)")
|
@Schema(description ="状态(1启用,2禁用)")
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
|
@Schema(description ="标签图标")
|
||||||
|
private String icon;
|
||||||
|
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
@Schema(description ="创建时间")
|
@Schema(description ="创建时间")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@ public class CmsTagDto extends BaseQueryDto {
|
||||||
|
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
|
private String icon;
|
||||||
|
|
||||||
private Integer deleteFlag;
|
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;
|
private String description;
|
||||||
@Schema(description = "技能标签")
|
@Schema(description = "技能标签")
|
||||||
private List<String> tags;
|
private List<String> tags;
|
||||||
@Schema(description = "技能内容ID(参照模板ID)")
|
@Schema(description = "需求说明")
|
||||||
private String contentId;
|
private String requirement;
|
||||||
}
|
}
|
||||||
|
|
@ -5,6 +5,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 技能生成请求参数
|
* 技能生成请求参数
|
||||||
|
|
@ -19,7 +20,11 @@ public class SkillPreGenRequest implements Serializable {
|
||||||
@Schema(description = "用户提示词")
|
@Schema(description = "用户提示词")
|
||||||
private String prompt;
|
private String prompt;
|
||||||
|
|
||||||
@Schema(description = "模板id")
|
@Schema(description = "文件地址")
|
||||||
private Long contentId;
|
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() {
|
public static SkillRequest createDefault() {
|
||||||
return new SkillRequest(true);
|
return new SkillRequest(true);
|
||||||
}
|
}
|
||||||
|
|
@ -100,7 +143,27 @@ public class SkillRequest implements Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private String role;
|
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
|
@Data
|
||||||
|
|
|
||||||
|
|
@ -12,4 +12,5 @@ public class SkillResponse implements Serializable {
|
||||||
private String name;
|
private String name;
|
||||||
private String description;
|
private String description;
|
||||||
private List<String> tags;
|
private List<String> tags;
|
||||||
|
private String summary;
|
||||||
}
|
}
|
||||||
|
|
@ -10,7 +10,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ControllerAdvice
|
@ControllerAdvice
|
||||||
public class BizExceptionAdvice {
|
public class BizExceptionAdvice {
|
||||||
@ExceptionHandler(value = RuntimeException.class)
|
@ExceptionHandler(value = BizException.class)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public CommonResult handleException(BizException e){
|
public CommonResult handleException(BizException e){
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|
|
||||||
|
|
@ -135,4 +135,78 @@ public interface CmsContentMapper {
|
||||||
* @return 内容ID列表
|
* @return 内容ID列表
|
||||||
*/
|
*/
|
||||||
List<Long> queryRecentCreatedByUserId(@Param("userId") Long userId, @Param("limit") int limit);
|
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 影响行数
|
* @return 影响行数
|
||||||
*/
|
*/
|
||||||
int addView(Long contentId);
|
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;
|
package com.kexue.skills.service;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.kexue.skills.entity.CmsContent;
|
||||||
import com.kexue.skills.entity.request.SkillGenRequest;
|
import com.kexue.skills.entity.request.SkillGenRequest;
|
||||||
import com.kexue.skills.entity.request.SkillPreGenRequest;
|
import com.kexue.skills.entity.request.SkillPreGenRequest;
|
||||||
import com.kexue.skills.entity.request.SkillAnalyzeRequest;
|
import com.kexue.skills.entity.request.SkillAnalyzeRequest;
|
||||||
|
|
@ -22,7 +23,10 @@ public interface SkillGenService {
|
||||||
*/
|
*/
|
||||||
SkillResponse preGenerate(SkillPreGenRequest request);
|
SkillResponse preGenerate(SkillPreGenRequest request);
|
||||||
|
|
||||||
JSONObject generate(SkillGenRequest request);
|
SkillResponse preGenerateV2(SkillPreGenRequest request);
|
||||||
|
|
||||||
|
CmsContent generate(SkillGenRequest request);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分析技能
|
* 分析技能
|
||||||
|
|
@ -31,4 +35,12 @@ public interface SkillGenService {
|
||||||
* @return 分析结果
|
* @return 分析结果
|
||||||
*/
|
*/
|
||||||
String analyzeSkill(SkillAnalyzeRequest request);
|
String analyzeSkill(SkillAnalyzeRequest request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成技能介绍
|
||||||
|
*
|
||||||
|
* @param content 技能内容
|
||||||
|
* @return 技能介绍
|
||||||
|
*/
|
||||||
|
String genIntroduce(String content);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -110,4 +110,12 @@ public interface SysUserService extends BaseService {
|
||||||
* @return 登录结果
|
* @return 登录结果
|
||||||
*/
|
*/
|
||||||
LoginUserDto phoneLogin(PhoneLoginDto phoneLoginDto);
|
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.PageHelper;
|
||||||
import com.github.pagehelper.PageInfo;
|
import com.github.pagehelper.PageInfo;
|
||||||
|
import com.kexue.skills.common.LoginUserCacheUtil;
|
||||||
import com.kexue.skills.entity.CmsContent;
|
import com.kexue.skills.entity.CmsContent;
|
||||||
import com.kexue.skills.entity.CmsContentView;
|
import com.kexue.skills.entity.CmsContentView;
|
||||||
import com.kexue.skills.entity.CmsContentLike;
|
import com.kexue.skills.entity.CmsContentLike;
|
||||||
|
|
@ -38,6 +39,9 @@ public class CmsContentServiceImpl implements CmsContentService {
|
||||||
@Resource
|
@Resource
|
||||||
private CmsContentLikeMapper cmsContentLikeMapper;
|
private CmsContentLikeMapper cmsContentLikeMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private LoginUserCacheUtil loginUserCacheUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页查询
|
* 分页查询
|
||||||
*
|
*
|
||||||
|
|
@ -54,17 +58,10 @@ public class CmsContentServiceImpl implements CmsContentService {
|
||||||
queryDto.setPageSize(BaseQueryDto.DEFAULT_PAGE_SIZE);
|
queryDto.setPageSize(BaseQueryDto.DEFAULT_PAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 打印分页参数
|
|
||||||
System.out.println("PageNum: " + queryDto.getPageNum() + ", PageSize: " + queryDto.getPageSize());
|
|
||||||
|
|
||||||
// 使用PageHelper进行分页
|
// 使用PageHelper进行分页
|
||||||
PageHelper.startPage(queryDto.getPageNum(), queryDto.getPageSize());
|
PageHelper.startPage(queryDto.getPageNum(), queryDto.getPageSize());
|
||||||
List<CmsContent> list = this.cmsContentMapper.getPageList(queryDto);
|
List<CmsContent> list = this.cmsContentMapper.getPageList(queryDto);
|
||||||
PageInfo<CmsContent> pageInfo = new PageInfo<>(list);
|
PageInfo<CmsContent> pageInfo = new PageInfo<>(list);
|
||||||
|
|
||||||
// 打印分页结果
|
|
||||||
System.out.println("Total: " + pageInfo.getTotal() + ", PageSize: " + pageInfo.getPageSize() + ", List Size: " + list.size());
|
|
||||||
|
|
||||||
return pageInfo;
|
return pageInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -238,7 +235,19 @@ public class CmsContentServiceImpl implements CmsContentService {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int increaseViewCount(Long contentId) {
|
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
|
* @param contentId 内容ID
|
||||||
* @return 影响行数
|
* @return 影响行数
|
||||||
|
|
@ -285,11 +294,19 @@ public class CmsContentServiceImpl implements CmsContentService {
|
||||||
|
|
||||||
// 检查用户是否已经收藏过该内容
|
// 检查用户是否已经收藏过该内容
|
||||||
CmsContentLike existingLike = cmsContentLikeMapper.queryByUserIdAndContentId(userId, contentId);
|
CmsContentLike existingLike = cmsContentLikeMapper.queryByUserIdAndContentId(userId, contentId);
|
||||||
if (existingLike != null) {
|
int result = 0;
|
||||||
return 0; // 已经收藏过,不允许再次收藏
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新增收藏记录
|
if (existingLike != null) {
|
||||||
|
// 已经收藏过,执行取消收藏操作
|
||||||
|
result = cmsContentLikeMapper.deleteById(existingLike.getLikeId());
|
||||||
|
|
||||||
|
// 减少内容的点赞数
|
||||||
|
if (content.getLikeCount() > 0) {
|
||||||
|
content.setLikeCount(content.getLikeCount() - 1);
|
||||||
|
this.cmsContentMapper.update(content);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 未收藏过,执行添加收藏操作
|
||||||
CmsContentLike likeRecord = new CmsContentLike();
|
CmsContentLike likeRecord = new CmsContentLike();
|
||||||
likeRecord.setUserId(userId);
|
likeRecord.setUserId(userId);
|
||||||
likeRecord.setUserName(userName);
|
likeRecord.setUserName(userName);
|
||||||
|
|
@ -302,7 +319,18 @@ public class CmsContentServiceImpl implements CmsContentService {
|
||||||
content.setLikeCount(content.getLikeCount() + 1);
|
content.setLikeCount(content.getLikeCount() + 1);
|
||||||
this.cmsContentMapper.update(content);
|
this.cmsContentMapper.update(content);
|
||||||
|
|
||||||
return cmsContentLikeMapper.insert(likeRecord);
|
result = cmsContentLikeMapper.insert(likeRecord);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新Redis中的LoginUser对象
|
||||||
|
if (result > 0) {
|
||||||
|
String token = loginUserCacheUtil.getTokenFromRequest();
|
||||||
|
if (token != null) {
|
||||||
|
loginUserCacheUtil.updateFavorites(token, userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -332,6 +360,14 @@ public class CmsContentServiceImpl implements CmsContentService {
|
||||||
this.cmsContentMapper.update(content);
|
this.cmsContentMapper.update(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 更新Redis中的LoginUser对象
|
||||||
|
if (result > 0) {
|
||||||
|
String token = loginUserCacheUtil.getTokenFromRequest();
|
||||||
|
if (token != null) {
|
||||||
|
loginUserCacheUtil.updateFavorites(token, userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -376,6 +412,7 @@ public class CmsContentServiceImpl implements CmsContentService {
|
||||||
|
|
||||||
// 检查用户是否已经查看过该内容(5分钟内)
|
// 检查用户是否已经查看过该内容(5分钟内)
|
||||||
CmsContentView existingView = cmsContentViewMapper.queryByUserIdAndContentId(userId, contentId);
|
CmsContentView existingView = cmsContentViewMapper.queryByUserIdAndContentId(userId, contentId);
|
||||||
|
int result = 0;
|
||||||
if (existingView == null) {
|
if (existingView == null) {
|
||||||
// 新增查看记录
|
// 新增查看记录
|
||||||
CmsContentView viewRecord = new CmsContentView();
|
CmsContentView viewRecord = new CmsContentView();
|
||||||
|
|
@ -387,7 +424,7 @@ public class CmsContentServiceImpl implements CmsContentService {
|
||||||
viewRecord.setDeleteFlag(0);
|
viewRecord.setDeleteFlag(0);
|
||||||
viewRecord.setCreateBy(userName);
|
viewRecord.setCreateBy(userName);
|
||||||
viewRecord.setUpdateBy(userName);
|
viewRecord.setUpdateBy(userName);
|
||||||
return cmsContentViewMapper.insert(viewRecord);
|
result = cmsContentViewMapper.insert(viewRecord);
|
||||||
} else {
|
} else {
|
||||||
// 检查是否超过5分钟
|
// 检查是否超过5分钟
|
||||||
Date fiveMinutesAgo = new Date(System.currentTimeMillis() - 5 * 60 * 1000);
|
Date fiveMinutesAgo = new Date(System.currentTimeMillis() - 5 * 60 * 1000);
|
||||||
|
|
@ -395,13 +432,147 @@ public class CmsContentServiceImpl implements CmsContentService {
|
||||||
// 更新查看时间
|
// 更新查看时间
|
||||||
existingView.setViewTime(new Date());
|
existingView.setViewTime(new Date());
|
||||||
existingView.setUpdateBy(userName);
|
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) {
|
} catch (Exception e) {
|
||||||
// 未登录用户,不记录查看历史
|
// 未登录用户,不记录查看历史
|
||||||
return 0;
|
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.PageHelper;
|
||||||
import com.github.pagehelper.PageInfo;
|
import com.github.pagehelper.PageInfo;
|
||||||
|
import com.kexue.skills.common.LoginUserCacheUtil;
|
||||||
import com.kexue.skills.entity.CmsContent;
|
import com.kexue.skills.entity.CmsContent;
|
||||||
import com.kexue.skills.entity.ContentPurchase;
|
import com.kexue.skills.entity.ContentPurchase;
|
||||||
import com.kexue.skills.entity.dto.ContentPurchaseDto;
|
import com.kexue.skills.entity.dto.ContentPurchaseDto;
|
||||||
|
|
@ -21,6 +22,8 @@ import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (ContentPurchase)表服务实现类
|
* (ContentPurchase)表服务实现类
|
||||||
*
|
*
|
||||||
|
|
@ -42,6 +45,9 @@ public class ContentPurchaseServiceImpl implements ContentPurchaseService {
|
||||||
@Resource
|
@Resource
|
||||||
private PointsAccountService pointsAccountService;
|
private PointsAccountService pointsAccountService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private LoginUserCacheUtil loginUserCacheUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页查询
|
* 分页查询
|
||||||
*
|
*
|
||||||
|
|
@ -195,6 +201,7 @@ public class ContentPurchaseServiceImpl implements ContentPurchaseService {
|
||||||
|
|
||||||
// 5. 根据支付方式处理支付
|
// 5. 根据支付方式处理支付
|
||||||
String transactionNo = UUID.randomUUID().toString().replaceAll("-", "");
|
String transactionNo = UUID.randomUUID().toString().replaceAll("-", "");
|
||||||
|
boolean isPaid = false;
|
||||||
if (payType == 1) {
|
if (payType == 1) {
|
||||||
// 余额支付
|
// 余额支付
|
||||||
BigDecimal price = content.getPrice();
|
BigDecimal price = content.getPrice();
|
||||||
|
|
@ -208,6 +215,7 @@ public class ContentPurchaseServiceImpl implements ContentPurchaseService {
|
||||||
purchase.setStatus(2); // 已支付
|
purchase.setStatus(2); // 已支付
|
||||||
purchase.setPurchaseTime(new Date());
|
purchase.setPurchaseTime(new Date());
|
||||||
this.insert(purchase);
|
this.insert(purchase);
|
||||||
|
isPaid = true;
|
||||||
} else if (payType == 2) {
|
} else if (payType == 2) {
|
||||||
// 积分支付
|
// 积分支付
|
||||||
Assert.isTrue(content.getSupportPointsPay() == 1, "该内容不支持积分支付");
|
Assert.isTrue(content.getSupportPointsPay() == 1, "该内容不支持积分支付");
|
||||||
|
|
@ -223,6 +231,7 @@ public class ContentPurchaseServiceImpl implements ContentPurchaseService {
|
||||||
purchase.setStatus(2); // 已支付
|
purchase.setStatus(2); // 已支付
|
||||||
purchase.setPurchaseTime(new Date());
|
purchase.setPurchaseTime(new Date());
|
||||||
this.insert(purchase);
|
this.insert(purchase);
|
||||||
|
isPaid = true;
|
||||||
} else if (payType == 3 || payType == 4) {
|
} else if (payType == 3 || payType == 4) {
|
||||||
// 微信支付或支付宝支付
|
// 微信支付或支付宝支付
|
||||||
// 这里只创建购买记录,实际支付由前端调用支付接口完成
|
// 这里只创建购买记录,实际支付由前端调用支付接口完成
|
||||||
|
|
@ -237,6 +246,14 @@ public class ContentPurchaseServiceImpl implements ContentPurchaseService {
|
||||||
Assert.isTrue(false, "不支持的支付方式");
|
Assert.isTrue(false, "不支持的支付方式");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 更新Redis中的LoginUser对象
|
||||||
|
if (isPaid) {
|
||||||
|
String token = loginUserCacheUtil.getTokenFromRequest();
|
||||||
|
if (token != null) {
|
||||||
|
loginUserCacheUtil.updateHas(token, userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return purchase;
|
return purchase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -153,10 +153,26 @@ public class PayServiceImpl implements PayService {
|
||||||
|
|
||||||
// 构建请求XML
|
// 构建请求XML
|
||||||
String xml = mapToXml(params);
|
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);
|
Map<String, String> result = xmlToMap(xmlResult);
|
||||||
|
logger.info("解析后的微信支付响应: {}", result);
|
||||||
|
|
||||||
// 处理响应
|
// 处理响应
|
||||||
if ("SUCCESS".equals(result.get("return_code")) && "SUCCESS".equals(result.get("result_code"))) {
|
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());
|
payParams.put("order_no", order.getOrderNo());
|
||||||
return payParams;
|
return payParams;
|
||||||
} else {
|
} else {
|
||||||
logger.error("微信支付下单失败: {}", result.get("return_msg"));
|
String returnMsg = result.get("return_msg") != null ? result.get("return_msg") : "未知错误";
|
||||||
throw new RuntimeException("微信支付下单失败: " + result.get("return_msg"));
|
logger.error("微信支付下单失败: {}", returnMsg);
|
||||||
|
throw new RuntimeException("微信支付下单失败: " + returnMsg);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("创建微信支付订单失败", e);
|
logger.error("创建微信支付订单失败", e);
|
||||||
|
|
@ -181,10 +198,11 @@ public class PayServiceImpl implements PayService {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String handleWechatPayNotify(HttpServletRequest request) {
|
public String handleWechatPayNotify(HttpServletRequest request) {
|
||||||
|
BufferedReader reader = null;
|
||||||
try {
|
try {
|
||||||
// 读取回调数据
|
// 读取回调数据
|
||||||
InputStream inputStream = request.getInputStream();
|
InputStream inputStream = request.getInputStream();
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
|
reader = new BufferedReader(new InputStreamReader(inputStream));
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
String line;
|
String line;
|
||||||
while ((line = reader.readLine()) != null) {
|
while ((line = reader.readLine()) != null) {
|
||||||
|
|
@ -197,6 +215,10 @@ public class PayServiceImpl implements PayService {
|
||||||
|
|
||||||
// 验证签名
|
// 验证签名
|
||||||
String sign = params.get("sign");
|
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");
|
params.remove("sign");
|
||||||
String expectedSign = generateSignature(params, paymentConfig.getWechat().getMchKey());
|
String expectedSign = generateSignature(params, paymentConfig.getWechat().getMchKey());
|
||||||
|
|
||||||
|
|
@ -211,10 +233,12 @@ public class PayServiceImpl implements PayService {
|
||||||
String transactionId = params.get("transaction_id");
|
String transactionId = params.get("transaction_id");
|
||||||
|
|
||||||
// 更新支付订单状态
|
// 更新支付订单状态
|
||||||
|
if (orderNo != null) {
|
||||||
PaymentOrder order = paymentOrderService.queryByOrderNo(orderNo);
|
PaymentOrder order = paymentOrderService.queryByOrderNo(orderNo);
|
||||||
if (order != null) {
|
if (order != null) {
|
||||||
paymentOrderService.updateStatus(order.getOrderId(), 2, transactionId);
|
paymentOrderService.updateStatus(order.getOrderId(), 2, transactionId);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
|
return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -224,6 +248,14 @@ public class PayServiceImpl implements PayService {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("处理微信支付回调失败", e);
|
logger.error("处理微信支付回调失败", e);
|
||||||
return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[处理失败]]></return_msg></xml>";
|
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<>();
|
Map<String, String> params = new HashMap<>();
|
||||||
request.getParameterMap().forEach((key, values) -> {
|
request.getParameterMap().forEach((key, values) -> {
|
||||||
|
if (values != null && values.length > 0) {
|
||||||
params.put(key, values[0]);
|
params.put(key, values[0]);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 初始化支付宝客户端
|
// 初始化支付宝客户端
|
||||||
|
|
@ -317,10 +351,12 @@ public class PayServiceImpl implements PayService {
|
||||||
String transactionId = params.get("trade_no");
|
String transactionId = params.get("trade_no");
|
||||||
|
|
||||||
// 更新支付订单状态
|
// 更新支付订单状态
|
||||||
|
if (orderNo != null) {
|
||||||
PaymentOrder order = paymentOrderService.queryByOrderNo(orderNo);
|
PaymentOrder order = paymentOrderService.queryByOrderNo(orderNo);
|
||||||
if (order != null) {
|
if (order != null) {
|
||||||
paymentOrderService.updateStatus(order.getOrderId(), 2, transactionId);
|
paymentOrderService.updateStatus(order.getOrderId(), 2, transactionId);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return "success";
|
return "success";
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ import com.kexue.skills.entity.dto.PaymentOrderDto;
|
||||||
import com.kexue.skills.mapper.PaymentOrderMapper;
|
import com.kexue.skills.mapper.PaymentOrderMapper;
|
||||||
import com.kexue.skills.service.AccountService;
|
import com.kexue.skills.service.AccountService;
|
||||||
import com.kexue.skills.service.PaymentOrderService;
|
import com.kexue.skills.service.PaymentOrderService;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
|
@ -24,6 +26,8 @@ import java.util.UUID;
|
||||||
@Service("paymentOrderService")
|
@Service("paymentOrderService")
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public class PaymentOrderServiceImpl implements PaymentOrderService {
|
public class PaymentOrderServiceImpl implements PaymentOrderService {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(PaymentOrderServiceImpl.class);
|
||||||
@Resource
|
@Resource
|
||||||
private PaymentOrderMapper paymentOrderMapper;
|
private PaymentOrderMapper paymentOrderMapper;
|
||||||
|
|
||||||
|
|
@ -162,6 +166,13 @@ public class PaymentOrderServiceImpl implements PaymentOrderService {
|
||||||
paymentOrder.setOrderNo(orderNo);
|
paymentOrder.setOrderNo(orderNo);
|
||||||
// 设置初始状态
|
// 设置初始状态
|
||||||
paymentOrder.setStatus(1); // 1.待支付
|
paymentOrder.setStatus(1); // 1.待支付
|
||||||
|
// 设置支付类型默认值(防止null)
|
||||||
|
if (paymentOrder.getPayType() == null) {
|
||||||
|
paymentOrder.setPayType(1); // 默认微信支付
|
||||||
|
logger.info("设置默认支付类型为微信支付(1)");
|
||||||
|
} else {
|
||||||
|
logger.info("支付类型已设置为: {}", paymentOrder.getPayType());
|
||||||
|
}
|
||||||
// 设置创建时间和更新时间
|
// 设置创建时间和更新时间
|
||||||
Date now = new Date();
|
Date now = new Date();
|
||||||
paymentOrder.setCreateTime(now);
|
paymentOrder.setCreateTime(now);
|
||||||
|
|
@ -169,7 +180,9 @@ public class PaymentOrderServiceImpl implements PaymentOrderService {
|
||||||
// 设置默认值
|
// 设置默认值
|
||||||
paymentOrder.setDeleteFlag(0);
|
paymentOrder.setDeleteFlag(0);
|
||||||
// 保存订单
|
// 保存订单
|
||||||
|
logger.info("准备保存支付订单,payType: {}", paymentOrder.getPayType());
|
||||||
this.paymentOrderMapper.insert(paymentOrder);
|
this.paymentOrderMapper.insert(paymentOrder);
|
||||||
|
logger.info("支付订单保存成功");
|
||||||
return paymentOrder;
|
return paymentOrder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -209,7 +222,7 @@ public class PaymentOrderServiceImpl implements PaymentOrderService {
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} 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;
|
package com.kexue.skills.service.impl;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.kexue.skills.common.util.HttpUtil;
|
import com.kexue.skills.common.util.HttpUtil;
|
||||||
import com.kexue.skills.config.DeepSeekConfig;
|
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.CmsTag;
|
||||||
import com.kexue.skills.entity.dto.CmsTagDto;
|
import com.kexue.skills.entity.dto.CmsTagDto;
|
||||||
import com.kexue.skills.entity.request.SkillAnalyzeRequest;
|
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.SkillPreGenRequest;
|
||||||
import com.kexue.skills.entity.request.SkillRequest;
|
import com.kexue.skills.entity.request.SkillRequest;
|
||||||
import com.kexue.skills.entity.response.SkillResponse;
|
import com.kexue.skills.entity.response.SkillResponse;
|
||||||
|
import com.kexue.skills.mapper.CmsContentMapper;
|
||||||
import com.kexue.skills.service.CmsTagService;
|
import com.kexue.skills.service.CmsTagService;
|
||||||
import com.kexue.skills.service.SkillGenService;
|
import com.kexue.skills.service.SkillGenService;
|
||||||
|
import jodd.util.StringUtil;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
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.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 技能生成服务实现
|
* 技能生成服务实现
|
||||||
|
|
@ -32,9 +42,15 @@ public class SkillGenServiceImpl implements SkillGenService {
|
||||||
@Autowired
|
@Autowired
|
||||||
private DeepSeekConfig deepSeekConfig;
|
private DeepSeekConfig deepSeekConfig;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private GlmConfig glmConfig;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private CmsTagService cmsTagService;
|
private CmsTagService cmsTagService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CmsContentMapper cmsContentMapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成技能
|
* 生成技能
|
||||||
*
|
*
|
||||||
|
|
@ -99,7 +115,80 @@ public class SkillGenServiceImpl implements SkillGenService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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);
|
log.info("生成技能请求: {}", request);
|
||||||
String url = deepSeekConfig.getBaseUrl() + "/v1/chat/completions";
|
String url = deepSeekConfig.getBaseUrl() + "/v1/chat/completions";
|
||||||
|
|
||||||
|
|
@ -113,31 +202,69 @@ public class SkillGenServiceImpl implements SkillGenService {
|
||||||
|
|
||||||
// 将标签名称拼接成逗号分隔的字符串
|
// 将标签名称拼接成逗号分隔的字符串
|
||||||
StringBuilder tagsList = new StringBuilder();
|
StringBuilder tagsList = new StringBuilder();
|
||||||
|
String defaultIcon = "";
|
||||||
for (int i = 0; i < tags.size(); i++) {
|
for (int i = 0; i < tags.size(); i++) {
|
||||||
CmsTag tag = tags.get(i);
|
CmsTag tag = tags.get(i);
|
||||||
if (tags1.contains(tag.getTagId()+"")) {
|
if (tags1.contains(tag.getTagId()+"")) {
|
||||||
|
if (StringUtil.isEmpty(defaultIcon)){
|
||||||
|
defaultIcon = tag.getIcon();
|
||||||
|
}
|
||||||
tagsList.append(tag.getTagName());
|
tagsList.append(tag.getTagName());
|
||||||
if (i < tags.size() - 1) {
|
if (i < tags.size() - 1) {
|
||||||
tagsList.append(",");
|
tagsList.append(",");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String systemContent = "你是一个专业的AI技能设计助手。请基于用户提供的Skill名称、描述、标签,按照skills目录结构输出完整的skills内容,包括skills.md本体内容、scripts目录中的脚本等,并打包成一个YAML文件技能包。请严格遵循以下规范:1. 包含必需的文件和目录;2. 多行内容使用 | 字面块;3. 内容从行首开始;4. 空目录用 children: [] 表示;5. 文件内容要实际有用;6.输出一个完整的YAML文档。无需其他额外说明。";
|
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 。";
|
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());
|
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");
|
SkillRequest skillRequest = new SkillRequest(true, deepSeekConfig.getChat().getModel(),systemContent,userContent,deepSeekConfig.getChat().getTemperature(), 8192,"text");
|
||||||
try {
|
try {
|
||||||
// 发送HTTP请求到deepseek API
|
// 发送HTTP请求到deepseek API
|
||||||
String deepseekResponse = HttpUtil.sendPostRequest(url, skillRequest, deepSeekConfig.getApiKey(), null);
|
String deepseekResponse = HttpUtil.sendPostRequest(url, skillRequest, deepSeekConfig.getApiKey(), null);
|
||||||
log.info("Deepseek API响应: {}", deepseekResponse);
|
log.info("Deepseek API响应: {}", deepseekResponse);
|
||||||
JSONObject responseJson = JSON.parseObject(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) {
|
} catch (Exception e) {
|
||||||
log.error("调用Deepseek API失败: {}", e.getMessage(), e);
|
log.error("调用Deepseek API失败: {}", e.getMessage(), e);
|
||||||
}
|
}
|
||||||
return null;
|
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();
|
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.Assert;
|
||||||
import com.kexue.skills.common.CacheManager;
|
import com.kexue.skills.common.CacheManager;
|
||||||
import com.kexue.skills.common.Const;
|
import com.kexue.skills.common.Const;
|
||||||
|
import com.kexue.skills.common.LoginUserCacheUtil;
|
||||||
import com.kexue.skills.config.CaptchaConfig;
|
import com.kexue.skills.config.CaptchaConfig;
|
||||||
import com.kexue.skills.entity.*;
|
import com.kexue.skills.entity.*;
|
||||||
import com.kexue.skills.entity.dto.ContentPurchaseDto;
|
import com.kexue.skills.entity.dto.ContentPurchaseDto;
|
||||||
|
|
@ -136,8 +137,9 @@ public class SysUserServiceImpl implements SysUserService {
|
||||||
//写一个salt生成方法
|
//写一个salt生成方法
|
||||||
sysUser.setSalt(System.currentTimeMillis()+"");
|
sysUser.setSalt(System.currentTimeMillis()+"");
|
||||||
try {
|
try {
|
||||||
String md5Pwd = MD5Util.encryptToHex(sysUser.getPwd()+sysUser.getSalt());
|
// 假设客户端已经对密码进行了一次MD5加密,服务端使用双重加密验证
|
||||||
sysUser.setPwd(md5Pwd);
|
String encryptedPwd = MD5Util.doubleEncrypt(sysUser.getPwd(), sysUser.getSalt());
|
||||||
|
sysUser.setPwd(encryptedPwd);
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
@ -219,12 +221,24 @@ public class SysUserServiceImpl implements SysUserService {
|
||||||
// 验证码验证
|
// 验证码验证
|
||||||
validateCaptcha(loginDto);
|
validateCaptcha(loginDto);
|
||||||
|
|
||||||
// 查询用户
|
// 查询用户(支持用户名或手机号)
|
||||||
SysUser sysUser = getUserByUsername(loginDto.getUsername());
|
SysUser sysUser = getUserByUsernameOrPhone(loginDto.getUsername());
|
||||||
|
|
||||||
// 密码验证
|
// 密码验证
|
||||||
validatePassword(loginDto.getPassword(), sysUser);
|
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
|
// 生成token
|
||||||
String token = generateToken(sysUser.getUserId());
|
String token = generateToken(sysUser.getUserId());
|
||||||
|
|
||||||
|
|
@ -234,6 +248,9 @@ public class SysUserServiceImpl implements SysUserService {
|
||||||
// 存储登录信息到Redis
|
// 存储登录信息到Redis
|
||||||
saveLoginUserToRedis(token, loginUser);
|
saveLoginUserToRedis(token, loginUser);
|
||||||
|
|
||||||
|
// 存储token与用户名的映射关系到CacheManager
|
||||||
|
CacheManager.putTokenToCache(sysUser.getUserName(), token);
|
||||||
|
|
||||||
// 构建返回对象
|
// 构建返回对象
|
||||||
LoginUserDto sysUserDto = buildLoginUserDto(loginUser);
|
LoginUserDto sysUserDto = buildLoginUserDto(loginUser);
|
||||||
|
|
||||||
|
|
@ -248,7 +265,7 @@ public class SysUserServiceImpl implements SysUserService {
|
||||||
* @param loginDto 登录请求参数
|
* @param loginDto 登录请求参数
|
||||||
*/
|
*/
|
||||||
private void validateLoginParams(LoginDto loginDto) {
|
private void validateLoginParams(LoginDto loginDto) {
|
||||||
Assert.notNull(loginDto.getUsername(), "用户名不能位空");
|
Assert.notNull(loginDto.getUsername(), "用户名或手机号不能位空");
|
||||||
Assert.notNull(loginDto.getPassword(), "密码不能位空");
|
Assert.notNull(loginDto.getPassword(), "密码不能位空");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -283,6 +300,23 @@ public class SysUserServiceImpl implements SysUserService {
|
||||||
return sysUser;
|
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;
|
return sysUserDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private LoginUserCacheUtil loginUserCacheUtil;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean resetPassword(ResetPasswordDto resetPasswordDto) {
|
public boolean resetPassword(ResetPasswordDto resetPasswordDto) {
|
||||||
Assert.notNull(resetPasswordDto.getUserName(), "用户名不能位空");
|
Assert.notNull(resetPasswordDto.getUserName(), "用户名或手机号不能位空");
|
||||||
Assert.notNull(resetPasswordDto.getOldPassword(), "旧密码不能位空");
|
Assert.notNull(resetPasswordDto.getOldPassword(), "旧密码不能位空");
|
||||||
Assert.notNull(resetPasswordDto.getNewPassword(), "新密码不能位空");
|
Assert.notNull(resetPasswordDto.getNewPassword(), "新密码不能位空");
|
||||||
|
|
||||||
SysUser sysUser = sysUserMapper.getByUsername(resetPasswordDto.getUserName());
|
// 获取当前登录用户ID
|
||||||
Assert.notNull(sysUser, "用户名不存在");
|
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 {
|
try {
|
||||||
String oldMd5Pwd = MD5Util.encryptToHex(resetPasswordDto.getOldPassword() + sysUser.getSalt());
|
// 假设客户端已经对密码进行了一次MD5加密,服务端使用双重加密验证
|
||||||
Assert.equals(oldMd5Pwd, sysUser.getPwd(), "旧密码不正确");
|
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);
|
sysUserMapper.update(sysUser);
|
||||||
|
|
||||||
// 清除旧的token
|
// 清除旧的token
|
||||||
CacheManager.removeTokenFromCache(resetPasswordDto.getUserName());
|
CacheManager.removeTokenFromCache(sysUser.getUserName());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
|
@ -551,19 +599,20 @@ public class SysUserServiceImpl implements SysUserService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean resetPasswordByAdmin(ResetPasswordDto resetPasswordDto) {
|
public boolean resetPasswordByAdmin(ResetPasswordDto resetPasswordDto) {
|
||||||
Assert.notNull(resetPasswordDto.getUserName(), "用户名不能位空");
|
Assert.notNull(resetPasswordDto.getUserName(), "用户名或手机号不能位空");
|
||||||
Assert.notNull(resetPasswordDto.getNewPassword(), "新密码不能位空");
|
Assert.notNull(resetPasswordDto.getNewPassword(), "新密码不能位空");
|
||||||
|
|
||||||
SysUser sysUser = sysUserMapper.getByUsername(resetPasswordDto.getUserName());
|
// 查询用户(支持用户名或手机号)
|
||||||
Assert.notNull(sysUser, "用户名不存在");
|
SysUser sysUser = getUserByUsernameOrPhone(resetPasswordDto.getUserName());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String newMd5Pwd = MD5Util.encryptToHex(resetPasswordDto.getNewPassword() + sysUser.getSalt());
|
// 假设客户端已经对密码进行了一次MD5加密,服务端使用双重加密验证
|
||||||
sysUser.setPwd(newMd5Pwd);
|
String newEncryptedPwd = MD5Util.doubleEncrypt(resetPasswordDto.getNewPassword(), sysUser.getSalt());
|
||||||
|
sysUser.setPwd(newEncryptedPwd);
|
||||||
sysUserMapper.update(sysUser);
|
sysUserMapper.update(sysUser);
|
||||||
|
|
||||||
// 清除旧的token
|
// 清除旧的token
|
||||||
CacheManager.removeTokenFromCache(resetPasswordDto.getUserName());
|
CacheManager.removeTokenFromCache(sysUser.getUserName());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
|
@ -587,17 +636,23 @@ public class SysUserServiceImpl implements SysUserService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean resetPwd(Long userId, String newPassword, String operator) {
|
public boolean resetPwd(Long userId, String newPassword, String operator) {
|
||||||
// 检查操作人是否为管理员
|
// 获取当前登录用户ID
|
||||||
Assert.isTrue(Const.ADMIN_USER_LIST.contains(operator.toLowerCase()), "只有管理员才能执行此操作");
|
Long currentUserId = loginUserCacheUtil.getCurrentUserId();
|
||||||
|
Assert.notNull(currentUserId, "请先登录");
|
||||||
|
|
||||||
// 查询用户是否存在
|
// 查询用户是否存在
|
||||||
SysUser sysUser = sysUserMapper.queryById(userId);
|
SysUser sysUser = sysUserMapper.queryById(userId);
|
||||||
Assert.notNull(sysUser, "用户不存在");
|
Assert.notNull(sysUser, "用户不存在");
|
||||||
|
|
||||||
|
// 检查是否是用户自己修改密码,或者是管理员
|
||||||
|
boolean isAdmin = Const.ADMIN_USER_LIST.contains(operator.toLowerCase());
|
||||||
|
boolean isSelf = currentUserId.equals(sysUser.getUserId());
|
||||||
|
Assert.isTrue(isAdmin || isSelf, "只能修改自己的密码");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 生成新的加密密码
|
// 假设客户端已经对密码进行了一次MD5加密,服务端使用双重加密验证
|
||||||
String newMd5Pwd = MD5Util.encryptToHex(newPassword + sysUser.getSalt());
|
String newEncryptedPwd = MD5Util.doubleEncrypt(newPassword, sysUser.getSalt());
|
||||||
sysUser.setPwd(newMd5Pwd);
|
sysUser.setPwd(newEncryptedPwd);
|
||||||
|
|
||||||
// 更新用户密码
|
// 更新用户密码
|
||||||
sysUserMapper.update(sysUser);
|
sysUserMapper.update(sysUser);
|
||||||
|
|
@ -613,8 +668,9 @@ public class SysUserServiceImpl implements SysUserService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean resetPasswordByUsernameOrPhone(String usernameOrPhone, String newPassword, String operator) {
|
public boolean resetPasswordByUsernameOrPhone(String usernameOrPhone, String newPassword, String operator) {
|
||||||
// 检查操作人是否为管理员
|
// 获取当前登录用户ID
|
||||||
//Assert.isTrue(Const.ADMIN_USER_LIST.contains(operator.toLowerCase()), "只有管理员才能执行此操作");
|
Long currentUserId = loginUserCacheUtil.getCurrentUserId();
|
||||||
|
Assert.notNull(currentUserId, "请先登录");
|
||||||
|
|
||||||
// 查询用户是否存在(先尝试通过用户名查询,再尝试通过手机号查询)
|
// 查询用户是否存在(先尝试通过用户名查询,再尝试通过手机号查询)
|
||||||
SysUser sysUser = sysUserMapper.getByUsername(usernameOrPhone);
|
SysUser sysUser = sysUserMapper.getByUsername(usernameOrPhone);
|
||||||
|
|
@ -623,10 +679,15 @@ public class SysUserServiceImpl implements SysUserService {
|
||||||
}
|
}
|
||||||
Assert.notNull(sysUser, "用户不存在");
|
Assert.notNull(sysUser, "用户不存在");
|
||||||
|
|
||||||
|
// 检查是否是用户自己修改密码,或者是管理员
|
||||||
|
boolean isAdmin = Const.ADMIN_USER_LIST.contains(operator.toLowerCase());
|
||||||
|
boolean isSelf = currentUserId.equals(sysUser.getUserId());
|
||||||
|
Assert.isTrue(isAdmin || isSelf, "只能修改自己的密码");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 生成新的加密密码
|
// 假设客户端已经对密码进行了一次MD5加密,服务端使用双重加密验证
|
||||||
String newMd5Pwd = MD5Util.encryptToHex(newPassword + sysUser.getSalt());
|
String newEncryptedPwd = MD5Util.doubleEncrypt(newPassword, sysUser.getSalt());
|
||||||
sysUser.setPwd(newMd5Pwd);
|
sysUser.setPwd(newEncryptedPwd);
|
||||||
|
|
||||||
// 更新用户密码
|
// 更新用户密码
|
||||||
sysUserMapper.update(sysUser);
|
sysUserMapper.update(sysUser);
|
||||||
|
|
@ -732,6 +793,18 @@ public class SysUserServiceImpl implements SysUserService {
|
||||||
sysUser = createUserByPhone(phone);
|
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
|
// 使用Sa-Token登录,生成token
|
||||||
cn.dev33.satoken.stp.StpUtil.login(sysUser.getUserId());
|
cn.dev33.satoken.stp.StpUtil.login(sysUser.getUserId());
|
||||||
// 获取生成的token
|
// 获取生成的token
|
||||||
|
|
@ -806,6 +879,9 @@ public class SysUserServiceImpl implements SysUserService {
|
||||||
// 将LoginUser对象存储到Redis缓存中,使用token作为key
|
// 将LoginUser对象存储到Redis缓存中,使用token作为key
|
||||||
redissonClient.getBucket("loginUser:" + token).set(cn.hutool.json.JSONUtil.toJsonStr(loginUser), 86400, java.util.concurrent.TimeUnit.SECONDS);
|
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返回对象
|
||||||
LoginUserDto sysUserDto = buildLoginUserDto(loginUser);
|
LoginUserDto sysUserDto = buildLoginUserDto(loginUser);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@
|
||||||
common:
|
common:
|
||||||
# Redis配置
|
# Redis配置
|
||||||
redis:
|
redis:
|
||||||
host: 127.0.0.1
|
# host: 127.0.0.1
|
||||||
port: 6379
|
# port: 6379
|
||||||
# host: 43.248.97.19
|
host: 43.248.97.19
|
||||||
# port: 16379
|
port: 16379
|
||||||
password: 654321
|
password: 654321
|
||||||
database: 1
|
database: 1
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,7 @@ web:
|
||||||
path: /kexue/agent-skills/upload/
|
path: /kexue/agent-skills/upload/
|
||||||
|
|
||||||
# 支付配置
|
# 支付配置
|
||||||
|
|
||||||
payment:
|
payment:
|
||||||
# 微信支付配置
|
# 微信支付配置
|
||||||
wechat:
|
wechat:
|
||||||
|
|
@ -115,14 +116,14 @@ payment:
|
||||||
mchSerialNo: 5EFC47D3AA59BFD1AAE548F96B5E19E1C60F067D
|
mchSerialNo: 5EFC47D3AA59BFD1AAE548F96B5E19E1C60F067D
|
||||||
privateKeyPath: apiclient_key.pem
|
privateKeyPath: apiclient_key.pem
|
||||||
domain: https://api.mch.weixin.qq.com
|
domain: https://api.mch.weixin.qq.com
|
||||||
notifyUrl: http://127.0.0.1:19001/pay/wx/notify
|
notifyUrl: http://127.0.0.1:19001/api/pay/wx/notify
|
||||||
returnUrl: http://127.0.0.1:19001/pay/success
|
returnUrl: http://127.0.0.1:19001/api/pay/success
|
||||||
# 支付宝支付配置
|
# 支付宝支付配置
|
||||||
alipay:
|
alipay:
|
||||||
appId: 2021004138642603
|
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=="
|
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"
|
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
|
returnUrl: https://shuziren.xueai.art/alipay-success
|
||||||
signType: RSA2
|
signType: RSA2
|
||||||
charset: UTF-8
|
charset: UTF-8
|
||||||
|
|
|
||||||
|
|
@ -101,3 +101,25 @@ jetcache:
|
||||||
web:
|
web:
|
||||||
upload:
|
upload:
|
||||||
path: /kexue/agent-skills/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:
|
spring:
|
||||||
profiles:
|
profiles:
|
||||||
active: dev
|
active: prod
|
||||||
application:
|
application:
|
||||||
name: agentSkills
|
name: agentSkills
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
|
|
@ -35,6 +35,13 @@ spring:
|
||||||
model: deepseek-chat
|
model: deepseek-chat
|
||||||
temperature: 0.3
|
temperature: 0.3
|
||||||
max-tokens: 500
|
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:
|
spring.config.import:
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<configuration scan="true" scanPeriod="60 seconds">
|
<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">
|
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
|
@ -13,10 +13,10 @@
|
||||||
|
|
||||||
<!-- 每日滚动文件输出 -->
|
<!-- 每日滚动文件输出 -->
|
||||||
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
<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">
|
<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 天的历史日志文件 -->
|
<!-- 保留 30 天的历史日志文件 -->
|
||||||
<maxHistory>30</maxHistory>
|
<maxHistory>30</maxHistory>
|
||||||
</rollingPolicy>
|
</rollingPolicy>
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,9 @@
|
||||||
<result property="subtitle" column="subtitle" jdbcType="VARCHAR"/>
|
<result property="subtitle" column="subtitle" jdbcType="VARCHAR"/>
|
||||||
<result property="contentType" column="content_type" jdbcType="INTEGER"/>
|
<result property="contentType" column="content_type" jdbcType="INTEGER"/>
|
||||||
<result property="summary" column="summary" jdbcType="VARCHAR"/>
|
<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="content" column="content" jdbcType="LONGVARCHAR"/>
|
||||||
<result property="coverImage" column="cover_image" jdbcType="VARCHAR"/>
|
<result property="coverImage" column="cover_image" jdbcType="VARCHAR"/>
|
||||||
<result property="authorId" column="author_id" jdbcType="BIGINT"/>
|
<result property="authorId" column="author_id" jdbcType="BIGINT"/>
|
||||||
|
|
@ -43,7 +46,7 @@
|
||||||
<!--查询单个-->
|
<!--查询单个-->
|
||||||
<select id="queryById" resultMap="CmsContentMap">
|
<select id="queryById" resultMap="CmsContentMap">
|
||||||
select
|
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,
|
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
|
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
|
from cms_content
|
||||||
|
|
@ -53,7 +56,7 @@
|
||||||
<!--查询分页列表-->
|
<!--查询分页列表-->
|
||||||
<select id="getPageList" resultMap="CmsContentMap">
|
<select id="getPageList" resultMap="CmsContentMap">
|
||||||
select
|
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,
|
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
|
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
|
from cms_content
|
||||||
|
|
@ -103,7 +106,7 @@
|
||||||
<!--带分页的查询-->
|
<!--带分页的查询-->
|
||||||
<select id="getPageListWithPagination" resultMap="CmsContentMap">
|
<select id="getPageListWithPagination" resultMap="CmsContentMap">
|
||||||
select
|
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,
|
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
|
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
|
from cms_content
|
||||||
|
|
@ -195,7 +198,7 @@
|
||||||
<!--查询列表-->
|
<!--查询列表-->
|
||||||
<select id="getList" resultMap="CmsContentMap">
|
<select id="getList" resultMap="CmsContentMap">
|
||||||
select
|
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,
|
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
|
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
|
from cms_content
|
||||||
|
|
@ -233,10 +236,10 @@
|
||||||
|
|
||||||
<!--新增所有列-->
|
<!--新增所有列-->
|
||||||
<insert id="insert" keyProperty="contentId" useGeneratedKeys="true">
|
<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,
|
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)
|
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},
|
#{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})
|
#{viewCount}, #{likeCount}, #{commentCount}, #{sort}, #{isPaid}, #{price}, #{requiredPoints}, #{supportPointsPay}, #{isOfficial}, #{shareCount}, #{fileUrl}, #{icon}, #{background}, #{origin}, #{tags}, #{createTime}, #{updateTime}, #{createBy}, #{updateBy}, #{deleteFlag})
|
||||||
</insert>
|
</insert>
|
||||||
|
|
@ -257,6 +260,15 @@
|
||||||
<if test="summary != null">
|
<if test="summary != null">
|
||||||
summary = #{summary},
|
summary = #{summary},
|
||||||
</if>
|
</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">
|
<if test="content != null">
|
||||||
content = #{content},
|
content = #{content},
|
||||||
</if>
|
</if>
|
||||||
|
|
@ -391,4 +403,92 @@
|
||||||
limit #{limit}
|
limit #{limit}
|
||||||
</select>
|
</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>
|
</mapper>
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
<result property="description" column="description" jdbcType="VARCHAR"/>
|
<result property="description" column="description" jdbcType="VARCHAR"/>
|
||||||
<result property="useCount" column="use_count" jdbcType="INTEGER"/>
|
<result property="useCount" column="use_count" jdbcType="INTEGER"/>
|
||||||
<result property="status" column="status" 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="createTime" column="create_time" jdbcType="TIMESTAMP"/>
|
||||||
<result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
|
<result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
|
||||||
<result property="createBy" column="create_by" jdbcType="VARCHAR"/>
|
<result property="createBy" column="create_by" jdbcType="VARCHAR"/>
|
||||||
|
|
@ -18,7 +19,7 @@
|
||||||
<!--查询单个-->
|
<!--查询单个-->
|
||||||
<select id="queryById" resultMap="CmsTagMap">
|
<select id="queryById" resultMap="CmsTagMap">
|
||||||
select
|
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
|
from cms_tag
|
||||||
where tag_id = #{tagId}
|
where tag_id = #{tagId}
|
||||||
</select>
|
</select>
|
||||||
|
|
@ -26,7 +27,7 @@
|
||||||
<!--查询分页列表-->
|
<!--查询分页列表-->
|
||||||
<select id="getPageList" resultMap="CmsTagMap">
|
<select id="getPageList" resultMap="CmsTagMap">
|
||||||
select
|
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
|
from cms_tag
|
||||||
<where>
|
<where>
|
||||||
<if test="tagId != null">
|
<if test="tagId != null">
|
||||||
|
|
@ -48,7 +49,7 @@
|
||||||
<!--查询列表-->
|
<!--查询列表-->
|
||||||
<select id="getList" resultMap="CmsTagMap">
|
<select id="getList" resultMap="CmsTagMap">
|
||||||
select
|
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
|
from cms_tag
|
||||||
<where>
|
<where>
|
||||||
<if test="tagId != null">
|
<if test="tagId != null">
|
||||||
|
|
@ -69,8 +70,8 @@
|
||||||
|
|
||||||
<!--新增所有列-->
|
<!--新增所有列-->
|
||||||
<insert id="insert" keyProperty="tagId" useGeneratedKeys="true">
|
<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)
|
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}, #{createTime}, #{updateTime}, #{createBy}, #{updateBy}, #{deleteFlag})
|
values (#{tagName}, #{description}, #{useCount}, #{status}, #{icon}, #{createTime}, #{updateTime}, #{createBy}, #{updateBy}, #{deleteFlag})
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
<!--通过主键修改数据-->
|
<!--通过主键修改数据-->
|
||||||
|
|
@ -89,6 +90,9 @@
|
||||||
<if test="status != null">
|
<if test="status != null">
|
||||||
status = #{status},
|
status = #{status},
|
||||||
</if>
|
</if>
|
||||||
|
<if test="icon != null">
|
||||||
|
icon = #{icon},
|
||||||
|
</if>
|
||||||
<if test="updateTime != null">
|
<if test="updateTime != null">
|
||||||
update_time = #{updateTime},
|
update_time = #{updateTime},
|
||||||
</if>
|
</if>
|
||||||
|
|
@ -114,7 +118,7 @@
|
||||||
<!--根据分类ID查询标签列表-->
|
<!--根据分类ID查询标签列表-->
|
||||||
<select id="getTagsByCategoryId" resultMap="CmsTagMap">
|
<select id="getTagsByCategoryId" resultMap="CmsTagMap">
|
||||||
select
|
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
|
from cms_tag t
|
||||||
inner join cms_category_tag ct on t.tag_id = ct.tag_id
|
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
|
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="payType" column="pay_type" jdbcType="INTEGER"/>
|
||||||
<result property="status" column="status" jdbcType="INTEGER"/>
|
<result property="status" column="status" jdbcType="INTEGER"/>
|
||||||
<result property="channelOrderNo" column="channel_order_no" jdbcType="VARCHAR"/>
|
<result property="channelOrderNo" column="channel_order_no" jdbcType="VARCHAR"/>
|
||||||
<result property="BusinessId" column="business_id" jdbcType="BIGINT"/>
|
<result property="businessId" column="business_id" jdbcType="BIGINT"/>
|
||||||
<result property="BusinessType" column="business_type" jdbcType="VARCHAR"/>
|
<result property="businessType" column="business_type" jdbcType="VARCHAR"/>
|
||||||
<result property="remark" column="remark" jdbcType="VARCHAR"/>
|
<result property="remark" column="remark" jdbcType="VARCHAR"/>
|
||||||
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
|
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
|
||||||
<result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
|
<result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
|
||||||
|
|
@ -118,7 +118,7 @@
|
||||||
<if test="userId != null">user_id,</if>
|
<if test="userId != null">user_id,</if>
|
||||||
<if test="userName != null">user_name,</if>
|
<if test="userName != null">user_name,</if>
|
||||||
<if test="amount != null">amount,</if>
|
<if test="amount != null">amount,</if>
|
||||||
<if test="payType != null">pay_type,</if>
|
pay_type,
|
||||||
<if test="status != null">status,</if>
|
<if test="status != null">status,</if>
|
||||||
<if test="channelOrderNo != null">channel_order_no,</if>
|
<if test="channelOrderNo != null">channel_order_no,</if>
|
||||||
<if test="businessId != null">business_id,</if>
|
<if test="businessId != null">business_id,</if>
|
||||||
|
|
@ -135,7 +135,7 @@
|
||||||
<if test="userId != null">#{userId},</if>
|
<if test="userId != null">#{userId},</if>
|
||||||
<if test="userName != null">#{userName},</if>
|
<if test="userName != null">#{userName},</if>
|
||||||
<if test="amount != null">#{amount},</if>
|
<if test="amount != null">#{amount},</if>
|
||||||
<if test="payType != null">#{payType},</if>
|
#{payType},
|
||||||
<if test="status != null">#{status},</if>
|
<if test="status != null">#{status},</if>
|
||||||
<if test="channelOrderNo != null">#{channelOrderNo},</if>
|
<if test="channelOrderNo != null">#{channelOrderNo},</if>
|
||||||
<if test="businessId != null">#{businessId},</if>
|
<if test="businessId != null">#{businessId},</if>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue