Compare commits

15 Commits

Author SHA1 Message Date
78403af455 我修复了项目状态如果不是运行中的话无法申请推广码 2025-06-29 17:02:27 +08:00
f51d42230c Merge remote-tracking branch 'origin/yyt' into yyt 2025-06-27 15:04:32 +08:00
5c6b502c1e 我修复了boss与admin创建相同账号无校验 2025-06-27 14:57:42 +08:00
e880431e07 修改了环境 2025-06-27 14:56:23 +08:00
1513ea51dc 删除了字体 2025-06-26 09:15:57 +08:00
bbd063c4cd ------------- 2025-06-25 16:48:42 +08:00
42aff09dae 修改了课程分页查询接口 2025-06-25 09:04:25 +08:00
77c73355e2 修复了上架字段的非空注解 2025-06-25 08:54:05 +08:00
3d8fd5591e 添加的功能:小程序端用户查看当前课程推广码
修改的bug: Web端管理员根据课程id分页查询课程章节
2025-06-24 22:34:58 +08:00
ad6eb74170 修复课程模块的bug 2025-06-24 21:53:12 +08:00
1f7e1211cf 完成了课程模块的订单部分 2025-06-24 19:49:24 +08:00
502f079194 解决了全局异常处理bug 2025-06-24 16:15:39 +08:00
a0e60bece6 --------------- 2025-06-24 13:51:31 +08:00
f871d61650 修改了课程模块接口,添加了课程订单模块 2025-06-24 13:31:54 +08:00
95d30cc5f6 添加了课程模块的功能:
1.小程序端用户根据类别查看课程列表
2.小程序端用户根据id查询课程详情
3.小程序端用户生成推广码
2025-06-24 10:42:28 +08:00
73 changed files with 1731 additions and 317 deletions

View File

@ -214,6 +214,13 @@
<version>2.6.9</version> <version>2.6.9</version>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
<version>5.8.7</version> <!-- 换成你项目里使用的 Spring Security 版本 -->
</dependency>

View File

@ -2,6 +2,8 @@ package com.greenorange.promotion.annotation;
import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext; import jakarta.validation.ConstraintValidatorContext;
import org.apache.commons.lang3.StringUtils;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -23,6 +25,6 @@ public class EnumValueValidator implements ConstraintValidator<EnumValue, String
@Override @Override
public boolean isValid(String value, ConstraintValidatorContext context) { public boolean isValid(String value, ConstraintValidatorContext context) {
return validValues.contains(value); return StringUtils.isBlank(value) || validValues.contains(value);
} }
} }

View File

@ -4,7 +4,7 @@ import lombok.Getter;
@Getter @Getter
public enum ErrorCode { public enum ErrorCode {
// private static final SUCESS = new ErrorCode(1, "ok");
SUCCESS(1,"ok"), SUCCESS(1,"ok"),
PARAMS_ERROR(40000,"请求参数错误"), PARAMS_ERROR(40000,"请求参数错误"),
NOT_LOGIN_ERROR(40100,"未登录"), NOT_LOGIN_ERROR(40100,"未登录"),

View File

@ -0,0 +1,17 @@
package com.greenorange.promotion.constant;
/**
* 订单状态常量
*/
public interface OrderStatusConstant {
String CLOSED = "交易关闭";
String SUCCESS = "交易成功";
String PENDING = "待支付";
String REFUNDED = "已退款";
}

View File

@ -7,4 +7,10 @@ public interface SystemConstant {
*/ */
String VERIFICATION_CODE = "verificationCode"; String VERIFICATION_CODE = "verificationCode";
/**
* 文件公共前缀
*/
String FILE_COMMON_PREFIX = "http://27.30.77.229:9091/file/download/";
} }

View File

@ -121,15 +121,15 @@ public class CourseChapterController {
} }
/** /**
* Web端管理员分页查询课程章节 * Web端管理员根据课程id分页查询课程章节
* @param courseChapterQueryRequest 课程章节查询请求体 * @param courseChapterQueryRequest 课程章节查询请求体
* @return 课程章节列表 * @return 课程章节列表
*/ */
@PostMapping("page") @PostMapping("page")
@Operation(summary = "Web端管理员分页查询课程章节", description = "参数课程章节查询请求体权限管理员方法名listCourseChapterByPage") @Operation(summary = "Web端管理员根据课程id分页查询课程章节", description = "参数课程章节查询请求体权限管理员方法名listCourseChapterByPageByCourseId")
@RequiresPermission(mustRole = UserConstant.ADMIN_ROLE) @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
@SysLog(title = "课程章节管理", content = "Web端管理员分页查询课程章节") @SysLog(title = "课程章节管理", content = "Web端管理员根据课程id分页查询课程章节")
public BaseResponse<Page<CourseChapterVO>> listCourseChapterByPage(@Valid @RequestBody CourseChapterQueryRequest courseChapterQueryRequest) { public BaseResponse<Page<CourseChapterVO>> listCourseChapterByPageByCourseId(@Valid @RequestBody CourseChapterQueryRequest courseChapterQueryRequest) {
long current = courseChapterQueryRequest.getCurrent(); long current = courseChapterQueryRequest.getCurrent();
long pageSize = courseChapterQueryRequest.getPageSize(); long pageSize = courseChapterQueryRequest.getPageSize();
QueryWrapper<CourseChapter> queryWrapper = courseChapterService.getQueryWrapper(courseChapterQueryRequest); QueryWrapper<CourseChapter> queryWrapper = courseChapterService.getQueryWrapper(courseChapterQueryRequest);

View File

@ -1,29 +1,40 @@
package com.greenorange.promotion.controller.course; package com.greenorange.promotion.controller.course;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.greenorange.promotion.annotation.RequiresPermission; import com.greenorange.promotion.annotation.RequiresPermission;
import com.greenorange.promotion.annotation.SysLog; import com.greenorange.promotion.annotation.SysLog;
import com.greenorange.promotion.common.BaseResponse; import com.greenorange.promotion.common.BaseResponse;
import com.greenorange.promotion.common.ErrorCode;
import com.greenorange.promotion.common.ResultUtils; import com.greenorange.promotion.common.ResultUtils;
import com.greenorange.promotion.constant.UserConstant; import com.greenorange.promotion.constant.UserConstant;
import com.greenorange.promotion.exception.BusinessException;
import com.greenorange.promotion.exception.ThrowUtils;
import com.greenorange.promotion.model.dto.CommonBatchRequest; import com.greenorange.promotion.model.dto.CommonBatchRequest;
import com.greenorange.promotion.model.dto.CommonRequest; import com.greenorange.promotion.model.dto.CommonRequest;
import com.greenorange.promotion.model.dto.CommonStringRequest;
import com.greenorange.promotion.model.dto.course.CourseAddRequest; import com.greenorange.promotion.model.dto.course.CourseAddRequest;
import com.greenorange.promotion.model.dto.course.CourseQueryRequest; import com.greenorange.promotion.model.dto.course.CourseQueryRequest;
import com.greenorange.promotion.model.dto.course.CourseUpdateRequest; import com.greenorange.promotion.model.dto.course.CourseUpdateRequest;
import com.greenorange.promotion.model.entity.Course; import com.greenorange.promotion.model.entity.Course;
import com.greenorange.promotion.model.entity.CourseChapter; import com.greenorange.promotion.model.entity.CourseChapter;
import com.greenorange.promotion.model.entity.CourseQrcodeApply;
import com.greenorange.promotion.model.entity.ProjectCommission;
import com.greenorange.promotion.model.vo.course.CourseCardVO;
import com.greenorange.promotion.model.vo.course.CourseDetailVO;
import com.greenorange.promotion.model.vo.course.CourseVO; import com.greenorange.promotion.model.vo.course.CourseVO;
import com.greenorange.promotion.model.vo.courseChapter.CourseChapterVO;
import com.greenorange.promotion.service.common.CommonService; import com.greenorange.promotion.service.common.CommonService;
import com.greenorange.promotion.service.course.CourseChapterService; import com.greenorange.promotion.service.course.CourseChapterService;
import com.greenorange.promotion.service.course.CourseQrcodeApplyService;
import com.greenorange.promotion.service.course.CourseService; import com.greenorange.promotion.service.course.CourseService;
import com.greenorange.promotion.service.wechat.WechatGetQrcodeService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
@ -31,7 +42,10 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/** /**
@ -52,6 +66,130 @@ public class CourseController {
@Resource @Resource
private CourseChapterService courseChapterService; private CourseChapterService courseChapterService;
@Resource
private WechatGetQrcodeService wechatGetQrcodeService;
@Resource
private CourseQrcodeApplyService courseQrcodeApplyService;
/**
* 小程序端用户查看热门课程列表
* @return 课程信息列表
*/
@PostMapping("query/hot")
@Operation(summary = "小程序端用户查看热门课程列表", description = "参数权限管理员方法名miniQueryHotCourseList")
@RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
@SysLog(title = "课程管理", content = "小程序端用户查看热门课程列表")
public BaseResponse<List<CourseCardVO>> miniQueryHotCourseList() {
List<Course> courseList = commonService.findByFieldEqTargetField(Course::getIsShelves, true, courseService);
// 降序排序并取前四个元素
courseList = courseList.stream()
.sorted((course1, course2) -> Integer.compare(course2.getOrderCount(), course1.getOrderCount())) // 降序排序
.limit(4) // 取前四个元素
.collect(Collectors.toList());
List<CourseCardVO> courseCardVOS = commonService.convertList(courseList, CourseCardVO.class);
return ResultUtils.success(courseCardVOS);
}
/**
* 小程序端用户根据类别查看课程列表
* @param commonStringRequest 课程类别
* @return 课程信息列表
*/
@PostMapping("query/type")
@Operation(summary = "小程序端用户根据类别查看课程列表", description = "参数课程添加请求体权限管理员方法名miniQueryCourseByType")
@RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
@SysLog(title = "课程管理", content = "小程序端用户根据类别查看课程列表")
public BaseResponse<List<CourseCardVO>> miniQueryCourseByType(@Valid @RequestBody CommonStringRequest commonStringRequest) {
String courseType = commonStringRequest.getTemplateString();
Map<SFunction<Course, ?>, Object> fieldConditions = Map.of(Course::getType, courseType, Course::getIsShelves, true);
List<Course> courseList = commonService.findByFieldEqTargetFields(fieldConditions, courseService);
List<CourseCardVO> courseCardVOS = commonService.convertList(courseList, CourseCardVO.class);
return ResultUtils.success(courseCardVOS);
}
/**
* 小程序端用户根据id查询课程详情
* @param commonRequest 课程id
* @return 课程信息列表
*/
@PostMapping("query/id")
@Operation(summary = "小程序端用户根据id查询课程详情", description = "参数课程id权限管理员方法名miniQueryCourseById")
@SysLog(title = "课程管理", content = "小程序端用户根据id查询课程详情")
public BaseResponse<CourseDetailVO> miniQueryCourseById(@Valid @RequestBody CommonRequest commonRequest) {
Long id = commonRequest.getId();
Course course = courseService.getById(id);
CourseDetailVO courseDetailVO = commonService.copyProperties(course, CourseDetailVO.class);
LambdaQueryWrapper<CourseChapter> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(CourseChapter::getCourseId, id);
List<CourseChapter> courseChapterList = courseChapterService.list(lambdaQueryWrapper);
List<CourseChapterVO> courseChapterVOS = commonService.convertList(courseChapterList, CourseChapterVO.class);
courseDetailVO.setCourseChapters(courseChapterVOS);
return ResultUtils.success(courseDetailVO);
}
/**
* 小程序端用户生成课程推广码
* @param commonRequest 课程id
* @return 课程信息列表
*/
@PostMapping("generate/qrcode")
@Operation(summary = "小程序端用户生成课程推广码", description = "参数课程id权限管理员方法名miniGenerateQrcode")
@RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
@SysLog(title = "课程管理", content = "小程序端用户生成课程推广码")
public BaseResponse<String> miniGenerateQrcode(@Valid @RequestBody CommonRequest commonRequest, HttpServletRequest request) throws Exception {
String videoView = wechatGetQrcodeService.getWxCourseQrCode(commonRequest, request);
return ResultUtils.success(videoView);
}
/**
* 小程序端用户根据id查看课程基本信息
* @param commonRequest 课程id
* @return 课程基本信息
*/
@PostMapping("detail/id")
@Operation(summary = "小程序端用户根据id查看课程基本信息", description = "参数课程id权限管理员方法名miniQueryCourseBaseInfo")
@RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
@SysLog(title = "课程管理", content = "小程序端用户根据id查看课程基本信息")
public BaseResponse<CourseCardVO> miniQueryCourseBaseInfo(@Valid @RequestBody CommonRequest commonRequest) {
Long id = commonRequest.getId();
Course course = courseService.getById(id);
CourseCardVO courseCardVO = commonService.copyProperties(course, CourseCardVO.class);
return ResultUtils.success(courseCardVO);
}
/**
* 小程序端用户查看当前课程推广码
* @param commonRequest 课程id
* @return 课程推广码(view值)
*/
@PostMapping("verify")
@Operation(summary = "小程序端用户查看当前课程推广码", description = "参数课程id权限管理员方法名verifyIsApplyCourseQrcode")
@RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
@SysLog(title = "课程管理", content = "小程序端用户查看当前课程推广码")
public BaseResponse<String> verifyIsApplyCourseQrcode(@Valid @RequestBody CommonRequest commonRequest, HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
Long courseId = commonRequest.getId();
LambdaQueryWrapper<CourseQrcodeApply> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(CourseQrcodeApply::getUserId, userId).eq(CourseQrcodeApply::getCourseId, courseId);
CourseQrcodeApply courseQrcodeApply = courseQrcodeApplyService.getOne(lambdaQueryWrapper);
ThrowUtils.throwIf(courseQrcodeApply == null, ErrorCode.OPERATION_ERROR, "当前用户尚未申请该课程的推广码");
return ResultUtils.success(courseQrcodeApply.getCourseQrcode());
}
/** /**
* web端管理员添加课程 * web端管理员添加课程
* @param courseAddRequest 课程添加请求体 * @param courseAddRequest 课程添加请求体
@ -62,6 +200,9 @@ public class CourseController {
@RequiresPermission(mustRole = UserConstant.ADMIN_ROLE) @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
@SysLog(title = "课程管理", content = "web端管理员添加课程") @SysLog(title = "课程管理", content = "web端管理员添加课程")
public BaseResponse<Long> addCourse(@Valid @RequestBody CourseAddRequest courseAddRequest) { public BaseResponse<Long> addCourse(@Valid @RequestBody CourseAddRequest courseAddRequest) {
BigDecimal firstLevelRate = courseAddRequest.getFirstLevelRate();
BigDecimal secondLevelRate = courseAddRequest.getSecondLevelRate();
ThrowUtils.throwIf(firstLevelRate.compareTo(secondLevelRate) < 0, ErrorCode.PARAMS_ERROR, "一级佣金比例不能小于二级佣金比例");
Course course = commonService.copyProperties(courseAddRequest, Course.class); Course course = commonService.copyProperties(courseAddRequest, Course.class);
courseService.save(course); courseService.save(course);
return ResultUtils.success(course.getId()); return ResultUtils.success(course.getId());
@ -73,7 +214,7 @@ public class CourseController {
* @return 是否更新成功 * @return 是否更新成功
*/ */
@PostMapping("update") @PostMapping("update")
@Operation(summary = "web端管理员根据id修改课程", description = "参数课程更新请求体权限管理员方法名updateCourse") @Operation(summary = "web端管理员根据id修改课程信息", description = "参数课程更新请求体权限管理员方法名updateCourse")
@RequiresPermission(mustRole = UserConstant.ADMIN_ROLE) @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
@SysLog(title = "课程管理", content = "web端管理员根据id修改课程信息") @SysLog(title = "课程管理", content = "web端管理员根据id修改课程信息")
public BaseResponse<Boolean> updateCourse(@Valid @RequestBody CourseUpdateRequest courseUpdateRequest) { public BaseResponse<Boolean> updateCourse(@Valid @RequestBody CourseUpdateRequest courseUpdateRequest) {
@ -135,6 +276,25 @@ public class CourseController {
return ResultUtils.success(courseVO); return ResultUtils.success(courseVO);
} }
/**
* web端管理员上架课程
* @param commonRequest 课程id
* @return 课程信息
*/
@PostMapping("isShelves")
@Operation(summary = "web端管理员上架课程", description = "参数课程查询请求体权限管理员方法名updateCourseShelvesStatus")
@RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
@SysLog(title = "课程管理", content = "web端管理员上架课程")
public BaseResponse<Boolean> updateCourseShelvesStatus(@Valid @RequestBody CommonRequest commonRequest) {
Long id = commonRequest.getId();
Course course = courseService.getById(id);
course.setIsShelves(!course.getIsShelves());
courseService.updateById(course);
return ResultUtils.success(true);
}
/** /**
* Web端管理员分页查询课程 * Web端管理员分页查询课程
* @param courseQueryRequest 课程查询请求体 * @param courseQueryRequest 课程查询请求体

View File

@ -0,0 +1,218 @@
package com.greenorange.promotion.controller.course;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.greenorange.promotion.annotation.RequiresPermission;
import com.greenorange.promotion.annotation.SysLog;
import com.greenorange.promotion.common.BaseResponse;
import com.greenorange.promotion.common.ErrorCode;
import com.greenorange.promotion.common.ResultUtils;
import com.greenorange.promotion.constant.OrderStatusConstant;
import com.greenorange.promotion.constant.UserConstant;
import com.greenorange.promotion.exception.ThrowUtils;
import com.greenorange.promotion.model.dto.CommonBatchRequest;
import com.greenorange.promotion.model.dto.CommonRequest;
import com.greenorange.promotion.model.dto.courseOrder.CourseOrderAddRequest;
import com.greenorange.promotion.model.dto.courseOrder.CourseOrderQueryRequest;
import com.greenorange.promotion.model.dto.courseOrder.CourseOrderUpdateRequest;
import com.greenorange.promotion.model.entity.Course;
import com.greenorange.promotion.model.entity.CourseOrder;
import com.greenorange.promotion.model.vo.course.CourseCardVO;
import com.greenorange.promotion.model.vo.courseOrder.CourseOrderCardVO;
import com.greenorange.promotion.model.vo.courseOrder.CourseOrderVO;
import com.greenorange.promotion.service.common.CommonService;
import com.greenorange.promotion.service.course.CourseOrderService;
import com.greenorange.promotion.service.course.CourseService;
import com.greenorange.promotion.utils.OrderNumberUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
import java.util.List;
/**
* 课程订单 控制器
*/
@RestController
@RequestMapping("courseOrder")
@Slf4j
@Tag(name = "课程订单模块")
public class CourseOrderController {
@Resource
private CourseService courseService;
@Resource
private CourseOrderService courseOrderService;
@Resource
private CommonService commonService;
/**
* 小程序端用户生成课程订单
* @param courseOrderAddRequest 课程id
* @return 是否添加成功
*/
@PostMapping("add")
@Operation(summary = "小程序端用户生成课程订单", description = "参数课程id权限管理员方法名addCourseOrder")
@RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
@SysLog(title = "课程订单管理", content = "小程序端用户生成课程订单")
public BaseResponse<Long> addCourseOrder(@Valid @RequestBody CourseOrderAddRequest courseOrderAddRequest, HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
Long courseId = courseOrderAddRequest.getCourseId();
Course course = courseService.getById(courseId);
ThrowUtils.throwIf(course == null, ErrorCode.OPERATION_ERROR, "该课程不存在");
CourseOrder courseOrder = commonService.copyProperties(course, CourseOrder.class);
courseOrder.setOrderNumber(OrderNumberUtils.generateOrderId());
courseOrder.setTotalAmount(course.getDiscountPrice());
courseOrder.setUserId(userId);
courseOrderService.save(courseOrder);
return ResultUtils.success(courseOrder.getId());
}
/**
* 小程序端用户取消课程订单
* @param courseOrderAddRequest 课程id
* @return 是否添加成功
*/
@PostMapping("cancel")
@Operation(summary = "小程序端用户取消课程订单", description = "参数订单id权限管理员方法名cancelCourseOrder")
@RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
@SysLog(title = "课程订单管理", content = "小程序端用户取消课程订单")
public BaseResponse<Long> cancelCourseOrder(@Valid @RequestBody CourseOrderAddRequest courseOrderAddRequest) {
Long courseId = courseOrderAddRequest.getCourseId();
CourseOrder courseOrder = courseOrderService.getById(courseId);
ThrowUtils.throwIf(courseOrder == null || !courseOrder.getOrderStatus().equals(OrderStatusConstant.PENDING),
ErrorCode.OPERATION_ERROR, "该订单不存在或者订单状态错误");
LambdaUpdateWrapper<CourseOrder> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(CourseOrder::getId, courseId).set(CourseOrder::getOrderStatus, OrderStatusConstant.CLOSED);
courseOrderService.update(updateWrapper);
return ResultUtils.success(courseOrder.getId());
}
/**
* 小程序端用户查询课程订单列表
* @return 课程订单列表
*/
@PostMapping("query/list")
@Operation(summary = "小程序端用户查询课程订单列表", description = "参数:无,权限:管理员,方法名:queryCourseOrderList")
@RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
@SysLog(title = "课程订单管理", content = "小程序端用户查询课程订单列表")
public BaseResponse<List<CourseOrderCardVO>> queryCourseOrderList(HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
List<CourseOrder> courseOrderList = commonService.findByFieldEqTargetField(CourseOrder::getUserId, userId, courseOrderService);
List<CourseOrderCardVO> courseOrderCardVOS = commonService.convertList(courseOrderList, CourseOrderCardVO.class);
Collections.reverse(courseOrderCardVOS);
return ResultUtils.success(courseOrderCardVOS);
}
/**
* 小程序端用户根据id查询订单详情
* @return 课程订单列表
*/
@PostMapping("query/detail")
@Operation(summary = "小程序端用户根据id查询订单详情", description = "参数订单id权限管理员方法名:queryCourseOrderDetailById")
@RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
@SysLog(title = "课程订单管理", content = "小程序端用户根据id查询订单详情")
public BaseResponse<CourseOrderVO> queryCourseOrderDetailById(@RequestBody CommonRequest commonRequest) {
Long id = commonRequest.getId();
CourseOrder courseOrder = courseOrderService.getById(id);
CourseOrderVO courseOrderVO = commonService.copyProperties(courseOrder, CourseOrderVO.class);
return ResultUtils.success(courseOrderVO);
}
/**
* web端管理员根据id删除课程订单
* @param commonRequest 课程订单删除请求体
* @return 是否删除成功
*/
@PostMapping("delete")
@Operation(summary = "web端管理员根据id删除课程订单", description = "参数课程订单删除请求体权限管理员方法名delCourseOrder")
@RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
@SysLog(title = "课程订单管理", content = "web端管理员根据id删除课程订单")
public BaseResponse<Boolean> delCourseOrder(@Valid @RequestBody CommonRequest commonRequest) {
Long id = commonRequest.getId();
CourseOrder courseOrder = courseOrderService.getById(id);
ThrowUtils.throwIf(courseOrder == null || !courseOrder.getOrderStatus().equals(OrderStatusConstant.CLOSED),
ErrorCode.OPERATION_ERROR, "该课程订单不存在或订单状态错误");
courseOrderService.removeById(id);
return ResultUtils.success(true);
}
/**
* web端管理员批量删除课程订单
* @param commonBatchRequest 课程订单批量删除请求体
* @return 是否删除成功
*/
@PostMapping("delBatch")
@Operation(summary = "web端管理员批量删除课程订单", description = "参数课程订单批量删除请求体权限管理员方法名delBatchCourseOrder")
@RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
@SysLog(title = "课程订单管理", content = "web端管理员批量删除课程订单")
public BaseResponse<Boolean> delBatchCourseOrder(@Valid @RequestBody CommonBatchRequest commonBatchRequest) {
List<Long> ids = commonBatchRequest.getIds();
LambdaQueryWrapper<CourseOrder> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.ne(CourseOrder::getOrderStatus, OrderStatusConstant.CLOSED);
long count = courseOrderService.count(queryWrapper);
ThrowUtils.throwIf(count > 0, ErrorCode.OPERATION_ERROR, "存在未关闭的课程订单");
courseOrderService.removeByIds(ids);
return ResultUtils.success(true);
}
/**
* web端管理员根据id查询课程订单
* @param commonRequest 课程订单查询请求体
* @return 课程订单信息
*/
@PostMapping("queryById")
@Operation(summary = "web端管理员根据id查询课程订单", description = "参数课程订单查询请求体权限管理员方法名queryCourseOrderById")
@RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
@SysLog(title = "课程订单管理", content = "web端管理员根据id查询课程订单")
public BaseResponse<CourseOrderVO> queryCourseOrderById(@Valid @RequestBody CommonRequest commonRequest) {
Long id = commonRequest.getId();
CourseOrder courseOrder = courseOrderService.getById(id);
CourseOrderVO courseOrderVO = commonService.copyProperties(courseOrder, CourseOrderVO.class);
return ResultUtils.success(courseOrderVO);
}
/**
* Web端管理员分页查询课程订单
* @param courseOrderQueryRequest 课程订单查询请求体
* @return 课程订单列表
*/
@PostMapping("page")
@Operation(summary = "Web端管理员分页查询课程订单", description = "参数课程订单查询请求体权限管理员方法名listCourseOrderByPage")
@RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
@SysLog(title = "课程订单管理", content = "Web端管理员分页查询课程订单")
public BaseResponse<Page<CourseOrderVO>> listCourseOrderByPage(@Valid @RequestBody CourseOrderQueryRequest courseOrderQueryRequest) {
long current = courseOrderQueryRequest.getCurrent();
long pageSize = courseOrderQueryRequest.getPageSize();
QueryWrapper<CourseOrder> queryWrapper = courseOrderService.getQueryWrapper(courseOrderQueryRequest);
Page<CourseOrder> page = courseOrderService.page(new Page<>(current, pageSize), queryWrapper);
List<CourseOrder> courseOrderList = page.getRecords();
List<CourseOrderVO> courseOrderVOList = commonService.convertList(courseOrderList, CourseOrderVO.class);
Page<CourseOrderVO> voPage = new Page<>(current, pageSize);
voPage.setRecords(courseOrderVOList);
voPage.setPages(page.getPages());
voPage.setTotal(page.getTotal());
return ResultUtils.success(voPage);
}
}

View File

@ -0,0 +1,15 @@
package com.greenorange.promotion.controller.practice;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class IdCardNumRequest {
private String idcardnum;
}

View File

@ -0,0 +1,16 @@
package com.greenorange.promotion.controller.practice;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.checkerframework.checker.units.qual.A;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Project_commission {
private Long userid;
}

View File

@ -0,0 +1,15 @@
package com.greenorange.promotion.controller.practice;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Promo_code_apply {
private Long userid;
}

View File

@ -0,0 +1,19 @@
package com.greenorange.promotion.controller.practice;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
//有getset方法to-string方法
@Data
//无参构造函数
@NoArgsConstructor
//全参构造函数
@AllArgsConstructor
public class QueryRequest {
private Long pagesize;
private Long pagenum;
}

View File

@ -0,0 +1,16 @@
package com.greenorange.promotion.controller.practice;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Toselect {
private String phoneNumber;
private String bankNumber;
}

View File

@ -0,0 +1,223 @@
package com.greenorange.promotion.controller.practice;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.greenorange.promotion.common.BaseResponse;
import com.greenorange.promotion.common.ErrorCode;
import com.greenorange.promotion.common.ResultUtils;
import com.greenorange.promotion.exception.BusinessException;
import com.greenorange.promotion.model.dto.CommonRequest;
import com.greenorange.promotion.model.dto.userAccount.UserAccountAddRequest;
import com.greenorange.promotion.model.dto.userAccount.UserAccountUpdateRequest;
import com.greenorange.promotion.model.entity.ProjectCommission;
import com.greenorange.promotion.model.entity.PromoCodeApply;
import com.greenorange.promotion.model.entity.UserAccount;
import com.greenorange.promotion.service.project.ProjectCommissionService;
import com.greenorange.promotion.service.project.PromoCodeApplyService;
import com.greenorange.promotion.service.project.impl.PromoCodeApplyServiceImpl;
import com.greenorange.promotion.service.settle.UserAccountService;
import jakarta.annotation.Resource;
import org.checkerframework.common.util.report.qual.ReportWrite;
import org.jacoco.agent.rt.internal_f3994fa.IExceptionLogger;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import java.util.*;
//@ResponseBody 把返回值传到浏览器上
//@Controller 把当前类的对象创建出来存放到SpringIOC容器
//@RestController = @Controller + @ResponseBody
@RestController
// ip + 端口号用于运行这个服务
// ip + 端口号 + /test/hello
// @Controller @Service @Mapper 把当前类的对象创建出来存放到SpringIOC容器
@RequestMapping("test")
public class UserAccountTestController {
// 对userAccount表实现功能
// 1.插入删除修改全部查询根据id查询
@Resource
// 从容器中取出名字为userAccountService的对象
private UserAccountService userAccountService;
@PostMapping("/add")
public BaseResponse<String> add(@RequestBody UserAccountAddRequest userAccountAddRequest){
if (userAccountAddRequest == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数不能为空");
}
if (userAccountAddRequest.getBankCardNumber() == null ||
userAccountAddRequest.getPhoneNumber() == null ||
userAccountAddRequest.getIdCardNumber() == null ||
userAccountAddRequest.getCardHolder() == null ||
userAccountAddRequest.getOpenBank() == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "必填字段不能为空");
}
UserAccount userAccount = new UserAccount();
// userAccount.setId(null);
// userAccount.setBankCardNumber(userAccountAddRequest.getBankCardNumber());
// userAccount.setOpenBank(userAccountAddRequest.getOpenBank());
// userAccount.setPhoneNumber(userAccountAddRequest.getPhoneNumber());
// userAccount.setIdCardNumber(userAccountAddRequest.getIdCardNumber());
// userAccount.setCardHolder(userAccountAddRequest.getCardHolder());
// userAccount.setUserId(1L);
BeanUtils.copyProperties(userAccountAddRequest, userAccount);
boolean result = userAccountService.save(userAccount);
if (!result) {
throw new BusinessException(ErrorCode.SYSTEM_ERROR, "新增用户账户失败");
}
return ResultUtils.success("插入成功");
}
// @GetMapping("/delete")
// public String delete(@RequestParam Long id) {
// boolean removed = userAccountService.removeById(id);
// return removed ? "删除成功" : "删除失败";
// @GetMapping("/delete/{id}")
// public String delete(@PathVariable Long id) {
// boolean removed = userAccountService.removeById(id);
// return removed ? "删除成功" : "删除失败";
// }
@PostMapping("/delete")
public BaseResponse<String> delete(@RequestBody CommonRequest commonRequest){
Long id = commonRequest.getId();
if(id == null) throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数 id 不能为空");
boolean removed = userAccountService.removeById(id);
return ResultUtils.success(removed ? "删除成功" : "删除失败");
}
@PostMapping("/update")
public BaseResponse<String> update(@RequestBody UserAccountUpdateRequest userAccountUpdateRequest){
if (userAccountUpdateRequest == null || userAccountUpdateRequest.getId() == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "更新操作必须提供 ID");
}
UserAccount existing = userAccountService.getById(userAccountUpdateRequest.getId());
if (existing == null) {
throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "要更新的用户账户不存在");
}
UserAccount userAccount = new UserAccount();
// userAccount.setId(userAccountUpdateRequest.getId());
// userAccount.setOpenBank(userAccountUpdateRequest.getOpenBank());
// userAccount.setPhoneNumber(userAccountUpdateRequest.getPhoneNumber());
// userAccount.setCardHolder(userAccountUpdateRequest.getCardHolder());
// userAccount.setIdCardNumber(userAccountUpdateRequest.getIdCardNumber());
// userAccount.setUserId(1L);
BeanUtils.copyProperties(userAccountUpdateRequest, userAccount);
userAccountService.updateById(userAccount);
boolean result = userAccountService.updateById(userAccount);
if (!result) {
throw new BusinessException(ErrorCode.SYSTEM_ERROR, "更新失败,请稍后再试");
}
return ResultUtils.success("更新成功");
}
//根据id查询
@PostMapping("/select")
public BaseResponse<UserAccount> select(@RequestBody CommonRequest commonRequest){
Long id = commonRequest.getId();
if (id == null) {
throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数 id 不能为空");
}
UserAccount selected = userAccountService.getById(id);
if (selected == null) {
throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "未找到对应的用户记录");
}
return ResultUtils.success(selected);
}
@GetMapping("success")
public BaseResponse<String> test() {
for (int i = 0; i < 10; i ++ )
System.out.println("运行了这个程序");
String template = "运行程序";
return ResultUtils.success(template);
// return new BaseResponse<>(1, template, "ok");
}
//查询所有数据
@PostMapping("/list")
public BaseResponse<List<UserAccount>> list(){
// 这里你可以根据 queryRequest 构造查询条件
return ResultUtils.success(userAccountService.list());
}
//分页查询
// @PostMapping("/pagelist")
// public BaseResponse<List<UserAccount>> pagelist(@RequestBody QueryRequest queryRequest){
// System.out.println(queryRequest.toString());
// Long start = queryRequest.getPagesize() * (queryRequest.getPagenum() - 1);
// List<UserAccount> list = userAccountService.list();
// List<UserAccount> newlist = list.subList(start.intValue(), start.intValue() + queryRequest.getPagesize().intValue());
// return ResultUtils.success(newlist);
// }
@PostMapping("/pagelist")
public BaseResponse<Page<UserAccount>> pagelist(@RequestBody QueryRequest queryRequest){
Long pagesize = queryRequest.getPagesize();
Long pagenum = queryRequest.getPagenum();
Page<UserAccount> userAccountPage = new Page<>(pagenum, pagesize);//分页的规则
Page<UserAccount> page = userAccountService.page(userAccountPage);//根据分页规则取出集合里对应的部分
return ResultUtils.success(page);
}
//根据IdCardnum查询
@PostMapping("/idcardnumselect")
public BaseResponse<UserAccount> idcardnumselect(@RequestBody IdCardNumRequest idCardNumRequest) throws Exception {
String idcardnum = idCardNumRequest.getIdcardnum();
// LambdaQueryWrapper<UserAccount> queryWrapper = new LambdaQueryWrapper<>();
QueryWrapper<UserAccount> queryWrapper = new QueryWrapper<>();
// queryWrapper.eq(UserAccount::getIdCardNumber, idcardnum);
queryWrapper.eq("idCardNumber", idcardnum);
UserAccount userAccount = userAccountService.getOne(queryWrapper);
if(userAccount == null) throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "这条记录不存在");
// if(userAccount == null) ResultUtils.error(ErrorCode.NOT_FOUND_ERROR);
return ResultUtils.success(userAccount);
}
//根据phoneNumber,bankCardNumber
@PostMapping("phonebankNumberselect")
public BaseResponse<List<UserAccount>> phonebankselect(@RequestBody Toselect toselect){
String phoneNumber = toselect.getPhoneNumber();
String bankNumber = toselect.getBankNumber();
LambdaQueryWrapper<UserAccount> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(UserAccount::getPhoneNumber, phoneNumber);
queryWrapper.eq(UserAccount::getBankCardNumber, bankNumber);
List<UserAccount> list = userAccountService.list(queryWrapper);
if (list == null || list.isEmpty()) {
throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "没有符合条件的用户账户信息");
}
return ResultUtils.success(list);
}
@Resource
private PromoCodeApplyService promoCodeApplyService;
@Resource
private ProjectCommissionService projectCommissionService;
@PostMapping("/queryByIds")
public BaseResponse<List<ProjectCommission>> phonebankselectHello(){
List<PromoCodeApply> list = promoCodeApplyService.list();
List<Long> ids = list.stream().map(PromoCodeApply::getUserId).toList();
LambdaQueryWrapper<ProjectCommission> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.in(ProjectCommission::getUserId, ids);
List<ProjectCommission> projectCommissions = projectCommissionService.list(lambdaQueryWrapper);
return ResultUtils.success(projectCommissions);
}
// @GetMapping("error")
// public BaseResponse<String> error() throws Exception {
//// String error = "空指针异常";
// String template = null;
// if (template == null) throw new Exception("空指针异常");
// return ResultUtils.success("error");
// }
}

View File

@ -33,8 +33,11 @@ import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.lang.reflect.GenericDeclaration;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.util.*; import java.util.*;
@ -138,6 +141,16 @@ public class ProjectCommissionController {
return ResultUtils.success(projectCommissionVOList); return ResultUtils.success(projectCommissionVOList);
} }
// public static void main(String[] args) {
// PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
// String encode = passwordEncoder.encode("123456");
// System.out.println(encode);
// boolean matches = passwordEncoder.matches("123456", "$2a$10$/yBGQqsHK78vlEtuMGTVY.bU/TamHQbr4wQIzj1B1H1ud/ZKPGICC");
// System.out.println(matches);
// }
// //
// /** // /**
// * 小程序用户修改项目的抽佣比例 // * 小程序用户修改项目的抽佣比例

View File

@ -9,6 +9,7 @@ import com.greenorange.promotion.common.BaseResponse;
import com.greenorange.promotion.common.ErrorCode; import com.greenorange.promotion.common.ErrorCode;
import com.greenorange.promotion.common.ResultUtils; import com.greenorange.promotion.common.ResultUtils;
import com.greenorange.promotion.constant.UserConstant; import com.greenorange.promotion.constant.UserConstant;
import com.greenorange.promotion.exception.BusinessException;
import com.greenorange.promotion.exception.ThrowUtils; import com.greenorange.promotion.exception.ThrowUtils;
import com.greenorange.promotion.model.dto.CommonBatchRequest; import com.greenorange.promotion.model.dto.CommonBatchRequest;
import com.greenorange.promotion.model.dto.promoCodeApply.PromoCodeApplyAddRequest; import com.greenorange.promotion.model.dto.promoCodeApply.PromoCodeApplyAddRequest;
@ -82,6 +83,12 @@ public class PromoCodeApplyController {
Long userId = (Long) request.getAttribute("userId"); Long userId = (Long) request.getAttribute("userId");
// 取出当前项目的推广码 // 取出当前项目的推广码
Long projectId = promoCodeApplyRequest.getProjectId(); Long projectId = promoCodeApplyRequest.getProjectId();
//项目状态如果不是运行中的话无法申请推广码
LambdaQueryWrapper<Project> projectLambdaQueryWrapper = new LambdaQueryWrapper<>();
projectLambdaQueryWrapper.eq(Project::getId, projectId);
Project project2 = projectService.getOne(projectLambdaQueryWrapper);
String projectStatus = project2.getProjectStatus();
if(!projectStatus.equals("running")) throw new BusinessException(ErrorCode.OPERATION_ERROR,"该项目未处于运行状态,无法申请推广码");
String phoneNumber = promoCodeApplyRequest.getSalespersonPhone(); String phoneNumber = promoCodeApplyRequest.getSalespersonPhone();
// 判断是否重复绑定了手机号 // 判断是否重复绑定了手机号
Map<SFunction<PromoCodeApply, ?>, Object> applyConditions = Map.of(PromoCodeApply::getUserId, userId, PromoCodeApply::getProjectId, projectId, PromoCodeApply::getSalespersonPhone, phoneNumber); Map<SFunction<PromoCodeApply, ?>, Object> applyConditions = Map.of(PromoCodeApply::getUserId, userId, PromoCodeApply::getProjectId, projectId, PromoCodeApply::getSalespersonPhone, phoneNumber);
@ -100,6 +107,9 @@ public class PromoCodeApplyController {
String promoCodeImage = promoCode.getPromoCodeImage(); String promoCodeImage = promoCode.getPromoCodeImage();
// 获取项目的参数信息 // 获取项目的参数信息
Project project = projectService.getById(projectId); Project project = projectService.getById(projectId);
// 检查项目是否处于运行中
// String projectStatus = project.getProjectStatus();
// ThrowUtils.throwIf(!projectStatus.equals("running"), ErrorCode.OPERATION_ERROR, "该项目未处于运行状态,无法申请推广码");
// 更新项目的推广人数 // 更新项目的推广人数
Map<SFunction<UserProject, ?>, Object> projectConditions = Map.of(UserProject::getProjectId, projectId, UserProject::getUserId, userId); Map<SFunction<UserProject, ?>, Object> projectConditions = Map.of(UserProject::getProjectId, projectId, UserProject::getUserId, userId);
@ -110,6 +120,8 @@ public class PromoCodeApplyController {
String projectName = project.getProjectName(); String projectName = project.getProjectName();
String projectImage = project.getProjectImage(); String projectImage = project.getProjectImage();
Integer projectSettlementCycle = project.getProjectSettlementCycle(); Integer projectSettlementCycle = project.getProjectSettlementCycle();
//判断项目推广人数是否满了
// 获取业务员信息 // 获取业务员信息
String salespersonName = promoCodeApplyRequest.getSalespersonName(); String salespersonName = promoCodeApplyRequest.getSalespersonName();
String salespersonPhone = promoCodeApplyRequest.getSalespersonPhone(); String salespersonPhone = promoCodeApplyRequest.getSalespersonPhone();

View File

@ -0,0 +1,17 @@
package com.greenorange.promotion.controller.projectSettlement;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Addqurrywithdraw {
private Long userid;
private BigDecimal payouts;
}

View File

@ -8,7 +8,9 @@ import com.greenorange.promotion.common.BaseResponse;
import com.greenorange.promotion.common.ErrorCode; import com.greenorange.promotion.common.ErrorCode;
import com.greenorange.promotion.common.ResultUtils; import com.greenorange.promotion.common.ResultUtils;
import com.greenorange.promotion.constant.UserConstant; import com.greenorange.promotion.constant.UserConstant;
import com.greenorange.promotion.exception.BusinessException;
import com.greenorange.promotion.exception.ThrowUtils; import com.greenorange.promotion.exception.ThrowUtils;
import com.greenorange.promotion.model.dto.userAccount.UserAccountQueryRequest;
import com.greenorange.promotion.model.dto.withdrawalApply.WithdrawalApplyAddRequest; import com.greenorange.promotion.model.dto.withdrawalApply.WithdrawalApplyAddRequest;
import com.greenorange.promotion.model.dto.withdrawalApply.WithdrawalApplyQueryRequest; import com.greenorange.promotion.model.dto.withdrawalApply.WithdrawalApplyQueryRequest;
import com.greenorange.promotion.model.entity.*; import com.greenorange.promotion.model.entity.*;
@ -24,9 +26,11 @@ import com.greenorange.promotion.service.userInfo.UserInfoService;
import com.greenorange.promotion.service.userInfo.UserMainInfoService; import com.greenorange.promotion.service.userInfo.UserMainInfoService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Priority;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@ -47,151 +51,46 @@ import java.util.List;
@Slf4j @Slf4j
@Tag(name = "提现申请记录管理") @Tag(name = "提现申请记录管理")
public class WithdrawalApplyController { public class WithdrawalApplyController {
@Resource
private UserAccountService userAccountService;
@Resource
private UserMainInfoService userMainInfoService;
@Resource @Resource
private WithdrawalApplyService withdrawalApplyService; private WithdrawalApplyService withdrawalApplyService;
@Resource @Resource
private FundsChangeService fundsChangeService; private FundsChangeService fundsChangeService;
@Resource @PostMapping("addqurry")
private CommonService commonService; public BaseResponse<String> addqurry(@RequestBody Addqurrywithdraw addqurrywithdraw ){
Long userid = addqurrywithdraw.getUserid();
@Resource BigDecimal payouts = addqurrywithdraw.getPayouts();
private UserMainInfoService userMainInfoService; LambdaQueryWrapper<UserMainInfo> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(UserMainInfo::getUserId, userid);
@Resource UserMainInfo one = userMainInfoService.getOne(queryWrapper);
private UserInfoService userInfoService; BigDecimal currentBalance = one.getCurrentBalance();
if(payouts.compareTo(currentBalance) > 0) throw new BusinessException(ErrorCode.OPERATION_ERROR,"提现金额超过当前的余额");
@Resource LambdaQueryWrapper<UserAccount> queryWrapper2 = new LambdaQueryWrapper<>();
private UserAccountService userAccountService; queryWrapper2.eq(UserAccount::getUserId, userid);
UserAccount two = userAccountService.getOne(queryWrapper2);
WithdrawalApply withdrawalApply = new WithdrawalApply();
/** BeanUtils.copyProperties(two, withdrawalApply);
* 小程序端用户查询账户提现状况 withdrawalApply.setId(null);
* @return 提现申请记录id withdrawalApply.setUpdateTime(null);
*/ withdrawalApply.setCreateTime(null);
@PostMapping("query/condition") withdrawalApply.setWithdrawnAmount(payouts);
@Operation(summary = "小程序端用户查询账户提现状况", description = "参数权限管理员方法名queryWithdrawalCondition") withdrawalApply.setWithdrawalStatus("processing");
@RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
public BaseResponse<UserAccountConditionVO> queryWithdrawalCondition(HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
LambdaQueryWrapper<UserMainInfo> userMainInfoLambdaQueryWrapper = commonService.buildQueryWrapperByField(UserMainInfo::getUserId, userId, userMainInfoService);
UserMainInfo userMainInfo = userMainInfoService.getOne(userMainInfoLambdaQueryWrapper);
LambdaQueryWrapper<UserAccount> userAccountLambdaQueryWrapper = commonService.buildQueryWrapperByField(UserAccount::getUserId, userId, userAccountService);
UserAccount userAccount = userAccountService.getOne(userAccountLambdaQueryWrapper);
String bankCardNumber = userAccount == null ? "" : userAccount.getBankCardNumber();
UserAccountConditionVO userAccountConditionVO = UserAccountConditionVO.builder()
.currentBalance(userMainInfo.getCurrentBalance())
.bankCardNumber(bankCardNumber)
.build();
return ResultUtils.success(userAccountConditionVO);
}
/**
* 小程序端用户申请提现
* @param withdrawalApplyAddRequest 提现申请记录查添加请求体
* @return 提现申请记录id
*/
@PostMapping("add")
@Operation(summary = "小程序端用户申请提现", description = "参数提现申请记录查添加请求体权限管理员方法名addWithdrawalApply")
@RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
// @SysLog(title = "提现申请记录管理", content = "小程序端用户申请提现")
public BaseResponse<Long> addWithdrawalApply(@Valid @RequestBody WithdrawalApplyAddRequest withdrawalApplyAddRequest, HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
LambdaQueryWrapper<UserAccount> userAccountLambdaQueryWrapper = commonService.buildQueryWrapperByField(UserAccount::getUserId, userId, userAccountService);
UserAccount userAccount = userAccountService.getOne(userAccountLambdaQueryWrapper);
ThrowUtils.throwIf(userAccount == null, ErrorCode.OPERATION_ERROR, "请先绑定银行卡");
BigDecimal withdrawnAmount = withdrawalApplyAddRequest.getWithdrawnAmount();
WithdrawalApply withdrawalApply = WithdrawalApply.builder()
.withdrawnAmount(withdrawnAmount)
.cardHolder(userAccount.getCardHolder())
.idCardNumber(userAccount.getIdCardNumber())
.phoneNumber(userAccount.getPhoneNumber())
.bankCardNumber(userAccount.getBankCardNumber())
.openBank(userAccount.getOpenBank())
.userId(userId)
.build();
withdrawalApplyService.save(withdrawalApply); withdrawalApplyService.save(withdrawalApply);
// 修改个人主要信息 BigDecimal subtract = currentBalance.subtract(payouts);
LambdaQueryWrapper<UserMainInfo> userMainInfoLambdaQueryWrapper = commonService.buildQueryWrapperByField(UserMainInfo::getUserId, userId, userMainInfoService); one.setCurrentBalance(subtract);
UserMainInfo userMainInfo = userMainInfoService.getOne(userMainInfoLambdaQueryWrapper); userMainInfoService.updateById(one);
userMainInfo.setWithdrawalAmount(userMainInfo.getWithdrawalAmount().add(withdrawnAmount)); FundsChange fundsChange = new FundsChange();
userMainInfo.setCurrentBalance(userMainInfo.getCurrentBalance().subtract(withdrawnAmount)); fundsChange.setUserId(userid);
userMainInfoService.updateById(userMainInfo); fundsChange.setChangeAmount(payouts);
// 添加资金明细记录 fundsChange.setProjectName("processing");
FundsChange fundsChange = FundsChange.builder() fundsChange.setCurrentAmount(subtract);
.projectName("用户提现") fundsChange.setProjectSettlementId(0L);
.changeAmount(withdrawnAmount.negate())
.currentAmount(userMainInfo.getCurrentBalance())
.userId(userId)
.projectSettlementId(0L)
.build();
fundsChangeService.save(fundsChange); fundsChangeService.save(fundsChange);
return ResultUtils.success(withdrawalApply.getId()); return ResultUtils.success("提现成功");
}
/**
* 小程序端用户查询提现申请记录
* @return 提现申请记录列表
*/
@PostMapping("query")
@Operation(summary = "小程序端用户查询提现申请记录", description = "参数权限管理员方法名queryWithdrawalApplyByUserId")
@RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
// @SysLog(title = "提现申请记录管理", content = "小程序端用户查询提现申请记录")
public BaseResponse<List<WithdrawalApplyVO>> queryWithdrawalApplyByUserId(HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
List<WithdrawalApply> withdrawalApplyList = commonService.findByFieldEqTargetField(WithdrawalApply::getUserId, userId, withdrawalApplyService);
List<WithdrawalApplyVO> withdrawalApplyVOS = commonService.convertList(withdrawalApplyList, WithdrawalApplyVO.class);
Collections.reverse(withdrawalApplyVOS);
return ResultUtils.success(withdrawalApplyVOS);
}
/**
* 小程序端用户查询资金变动记录
* @return 提现申请记录id
*/
@PostMapping("query/change")
@Operation(summary = "小程序端用户查询资金变动记录", description = "参数权限管理员方法名queryFundsChangeByUserId")
@RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
// @SysLog(title = "提现申请记录管理", content = "小程序端用户查询资金变动记录")
public BaseResponse<FundsItemVO> queryFundsChangeByUserId(HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
LambdaQueryWrapper<UserMainInfo> userMainInfoLambdaQueryWrapper = commonService.buildQueryWrapperByField(UserMainInfo::getUserId, userId, userMainInfoService);
UserMainInfo userMainInfo = userMainInfoService.getOne(userMainInfoLambdaQueryWrapper);
FundsItemVO fundsItemVO = commonService.copyProperties(userMainInfo, FundsItemVO.class);
List<FundsChange> fundsChangeList = commonService.findByFieldEqTargetField(FundsChange::getUserId, userId, fundsChangeService);
List<FundsChangeVO> fundsChangeVOS = commonService.convertList(fundsChangeList, FundsChangeVO.class);
Collections.reverse(fundsChangeVOS);
fundsItemVO.setFundsChangeVOList(fundsChangeVOS);
return ResultUtils.success(fundsItemVO);
}
/**
* Web端管理员分页查询提现申请记录
* @param withdrawalApplyQueryRequest 提现申请记录查询请求体
* @return 提现申请记录列表
*/
@PostMapping("page")
@Operation(summary = "Web端管理员分页查询提现申请记录", description = "参数提现申请记录查询请求体权限管理员方法名listWithdrawalApplyByPage")
@RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
@SysLog(title = "提现申请记录管理", content = "Web端管理员分页查询提现申请记录")
public BaseResponse<Page<WithdrawalApplyVO>> listWithdrawalApplyByPage(@Valid @RequestBody WithdrawalApplyQueryRequest withdrawalApplyQueryRequest) {
long current = withdrawalApplyQueryRequest.getCurrent();
long pageSize = withdrawalApplyQueryRequest.getPageSize();
QueryWrapper<WithdrawalApply> queryWrapper = withdrawalApplyService.getQueryWrapper(withdrawalApplyQueryRequest);
Page<WithdrawalApply> page = withdrawalApplyService.page(new Page<>(current, pageSize), queryWrapper);
List<WithdrawalApply> withdrawalApplyList = page.getRecords();
List<WithdrawalApplyVO> withdrawalApplyVOList = commonService.convertList(withdrawalApplyList, WithdrawalApplyVO.class);
Page<WithdrawalApplyVO> voPage = new Page<>(current, pageSize);
voPage.setRecords(withdrawalApplyVOList);
voPage.setPages(page.getPages());
voPage.setTotal(page.getTotal());
return ResultUtils.success(voPage);
} }
} }

View File

@ -10,6 +10,7 @@ import com.greenorange.promotion.common.BaseResponse;
import com.greenorange.promotion.common.ErrorCode; import com.greenorange.promotion.common.ErrorCode;
import com.greenorange.promotion.common.ResultUtils; import com.greenorange.promotion.common.ResultUtils;
import com.greenorange.promotion.constant.UserConstant; import com.greenorange.promotion.constant.UserConstant;
import com.greenorange.promotion.exception.BusinessException;
import com.greenorange.promotion.exception.ThrowUtils; import com.greenorange.promotion.exception.ThrowUtils;
import com.greenorange.promotion.model.dto.CommonBatchRequest; import com.greenorange.promotion.model.dto.CommonBatchRequest;
import com.greenorange.promotion.model.dto.CommonRequest; import com.greenorange.promotion.model.dto.CommonRequest;
@ -30,6 +31,7 @@ import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.io.JBoss6VFS;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -303,6 +305,14 @@ public class UserInfoController {
@RequiresPermission(mustRole = UserConstant.BOSS_ROLE) @RequiresPermission(mustRole = UserConstant.BOSS_ROLE)
@SysLog(title = "用户管理", content = "web端管理员添加用户") @SysLog(title = "用户管理", content = "web端管理员添加用户")
public BaseResponse<Boolean> addUserInfo(@Valid @RequestBody UserInfoAddRequest userInfoAddRequest) { public BaseResponse<Boolean> addUserInfo(@Valid @RequestBody UserInfoAddRequest userInfoAddRequest) {
String userAccount = userInfoAddRequest.getUserAccount();
String userPassword = userInfoAddRequest.getUserPassword();
LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(UserInfo::getUserRole,"boss");
UserInfo one = userInfoService.getOne(queryWrapper);
String userAccount2 = one.getUserAccount();
String userPassword2 = one.getUserPassword();
if(userAccount2.equals(userAccount) && userPassword2.equals(userPassword)) throw new BusinessException(ErrorCode.OPERATION_ERROR,"不能添加跟boss重名的账号和密码");
UserInfo userInfo = commonService.copyProperties(userInfoAddRequest, UserInfo.class); UserInfo userInfo = commonService.copyProperties(userInfoAddRequest, UserInfo.class);
userInfo.setParentUserId(-1L); userInfo.setParentUserId(-1L);
userInfo.setUserRole(UserConstant.ADMIN_ROLE); userInfo.setUserRole(UserConstant.ADMIN_ROLE);

View File

@ -1,19 +1,12 @@
package com.greenorange.promotion.controller.wechat; package com.greenorange.promotion.controller.wechat;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.freewayso.image.combiner.ImageCombiner;
import com.freewayso.image.combiner.enums.OutputFormat;
import com.greenorange.promotion.annotation.RequiresPermission;
import com.greenorange.promotion.common.BaseResponse; import com.greenorange.promotion.common.BaseResponse;
import com.greenorange.promotion.common.ErrorCode;
import com.greenorange.promotion.common.ResultUtils; import com.greenorange.promotion.common.ResultUtils;
import com.greenorange.promotion.config.WxAccessToken; import com.greenorange.promotion.config.WxAccessToken;
import com.greenorange.promotion.constant.UserConstant; import com.greenorange.promotion.model.dto.CommonRequest;
import com.greenorange.promotion.model.dto.CommonStringRequest; import com.greenorange.promotion.model.dto.CommonStringRequest;
import com.greenorange.promotion.service.wechat.WechatGetQrcodeService; import com.greenorange.promotion.service.wechat.WechatGetQrcodeService;
import com.greenorange.promotion.utils.QRCodeUtil;
import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@ -21,21 +14,10 @@ import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.FileSystemResource;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*; import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
@Slf4j @Slf4j
@ -72,7 +54,7 @@ public class WechatGetQrcodeController {
* @return * @return
* @throws IOException * @throws IOException
*/ */
// @Hidden @Hidden
@PostMapping("/get/qrcode") @PostMapping("/get/qrcode")
@Operation(summary = "微信小程序获取二维码", description = "参数:无, 权限:所有人, 方法名getQrcode") @Operation(summary = "微信小程序获取二维码", description = "参数:无, 权限:所有人, 方法名getQrcode")
// @RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE) // @RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
@ -88,13 +70,12 @@ public class WechatGetQrcodeController {
* @return * @return
* @throws IOException * @throws IOException
*/ */
// @Hidden @Hidden
@PostMapping("/get/course/qrcode") @PostMapping("/get/course/qrcode")
@Operation(summary = "微信小程序获取课程码", description = "参数:无, 权限:所有人, 方法名getCourseQrcode") @Operation(summary = "微信小程序获取课程码", description = "参数:无, 权限:所有人, 方法名getCourseQrcode")
// @RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE) // @RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
public BaseResponse<String> getCourseQrcode(@Valid @RequestBody CommonStringRequest commonStringRequest) throws Exception { public BaseResponse<String> getCourseQrcode(@Valid @RequestBody CommonRequest commonRequest, HttpServletRequest request) throws Exception {
String inviteCode = commonStringRequest.getTemplateString(); String view = wechatGetQrcodeService.getWxCourseQrCode(commonRequest, request);
String view = wechatGetQrcodeService.getWxCourseQrCode(inviteCode);
return ResultUtils.success(view); return ResultUtils.success(view);
} }

View File

@ -61,18 +61,14 @@ public class GlobalExceptionHandler {
// .append("; ")); // .append("; "));
// return ResultUtils.error(ErrorCode.PARAMS_ERROR, errors.toString()); // return ResultUtils.error(ErrorCode.PARAMS_ERROR, errors.toString());
// 从所有 FieldError 里,排序取第一个 // 按字段名排序取第一个错误的 defaultMessage
FieldError firstError = e.getBindingResult() String msg = e.getBindingResult()
.getFieldErrors().stream().min(Comparator.comparing(FieldError::getField)) .getFieldErrors().stream()
.orElse(null); .sorted(Comparator.comparing(FieldError::getField))
.map(FieldError::getDefaultMessage)
// 直接取它的 defaultMessage即注解里配置的 message .findFirst()
String msg = (firstError != null) .orElse("参数校验失败");
? firstError.getDefaultMessage() return ResultUtils.error(ErrorCode.PARAMS_ERROR, msg);
: "参数校验失败";
// 返回时只带 msg不再拼前缀或字段名
return ResultUtils.error(ErrorCode.PARAMS_ERROR, msg);
} }

View File

@ -27,13 +27,13 @@ public class Generator {
// 作者 // 作者
private static final String AUTHOR = "chenxinzhi"; private static final String AUTHOR = "chenxinzhi";
// 表注释 // 表注释
private static final String TABLE_COMMENT = "课程章节"; private static final String TABLE_COMMENT = "课程订单";
// 实体类名 // 实体类名
private static final String ENTITY_NAME = "CourseChapter"; private static final String ENTITY_NAME = "CourseOrder";
// 表名 // 表名
private static final String TABLE_NAME = "course_chapter"; private static final String TABLE_NAME = "course_order";
// 实体类属性名 // 实体类属性名
private static final String ENTITY_NAME_LOWER = "courseChapter"; private static final String ENTITY_NAME_LOWER = "courseOrder";
// 父包名 // 父包名
private static final String PARENT_PATH = "com.greenorange.promotion"; private static final String PARENT_PATH = "com.greenorange.promotion";

View File

@ -0,0 +1,18 @@
package com.greenorange.promotion.mapper;
import com.greenorange.promotion.model.entity.CourseQrcodeApply;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author 35880
* @description 针对表【course_qrcode_apply(课程推广码申请表)】的数据库操作Mapper
* @createDate 2025-06-24 22:10:39
* @Entity com.greenorange.promotion.model.entity.CourseQrcodeApply
*/
public interface CourseQrcodeApplyMapper extends BaseMapper<CourseQrcodeApply> {
}

View File

@ -5,6 +5,8 @@ import com.greenorange.promotion.model.enums.CourseTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Min; import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import jdk.jfr.BooleanFlag;
import lombok.Data; import lombok.Data;
import java.math.BigDecimal; import java.math.BigDecimal;
@ -22,19 +24,24 @@ public class CourseQueryRequest extends PageRequest implements Serializable {
/** /**
* 课程名称 * 课程名称
*/ */
@NotBlank(message = "课程名称不能为空")
@Schema(description = "课程名称", example = "数据分析工程师训练营") @Schema(description = "课程名称", example = "数据分析工程师训练营")
private String name; private String name;
/** /**
* 课程类别[考公考研,自媒体,财经] * 课程类别[考公考研,自媒体,财经]
*/ */
@NotBlank(message = "课程类别不能为空")
@EnumValue(enumClass = CourseTypeEnum.class) @EnumValue(enumClass = CourseTypeEnum.class)
@Schema(description = "课程类别[考公考研,自媒体,财经]", example = "自媒体") @Schema(description = "课程类别[考公考研,自媒体,财经]", example = "自媒体")
private String type; private String type;
/**
* 是否上架(true:上架false:下架)
*/
@Schema(description = "是否上架(true:上架false:下架)", example = "true")
private Boolean isShelves;
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
} }

View File

@ -39,11 +39,11 @@ public class CourseChapterAddRequest implements Serializable {
private Long duration; private Long duration;
/** /**
* 试看权限 * 试看权限[全集试看,部分试看,关闭,开启]
*/ */
@NotBlank(message = "试看权限不能为空") @NotBlank(message = "试看权限不能为空")
@EnumValue(enumClass = PreviewPermissionEnum.class) @EnumValue(enumClass = PreviewPermissionEnum.class)
@Schema(description = "试看权限", example = "全集试看") @Schema(description = "试看权限[全集试看,部分试看,关闭,开启]", example = "全集试看")
private String permissions; private String permissions;
/** /**

View File

@ -5,6 +5,7 @@ import com.greenorange.promotion.model.enums.PreviewPermissionEnum;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Min; import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;
import java.math.BigDecimal; import java.math.BigDecimal;
@ -22,18 +23,24 @@ public class CourseChapterQueryRequest extends PageRequest implements Serializab
/** /**
* 章节名称 * 章节名称
*/ */
@NotBlank(message = "章节名称不能为空")
@Schema(description = "章节名称", example = "企业经营管理者为什么必须懂财务?") @Schema(description = "章节名称", example = "企业经营管理者为什么必须懂财务?")
private String name; private String name;
/** /**
* 试看权限 * 试看权限[全集试看,部分试看,关闭,开启]
*/ */
@NotBlank(message = "试看权限不能为空")
@EnumValue(enumClass = PreviewPermissionEnum.class) @EnumValue(enumClass = PreviewPermissionEnum.class)
@Schema(description = "试看权限", example = "全集试看") @Schema(description = "试看权限[全集试看,部分试看,关闭,开启]", example = "全集试看")
private String permissions; private String permissions;
/**
* 课程id
*/
@NotNull(message = "课程id不能为null")
@Min(value = 1, message = "课程id不能小于1")
@Schema(description = "课程id", example = "1")
private Long courseId;
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@ -47,11 +47,11 @@ public class CourseChapterUpdateRequest implements Serializable {
private Long duration; private Long duration;
/** /**
* 试看权限 * 试看权限[全集试看,部分试看,关闭,开启]
*/ */
@NotBlank(message = "试看权限不能为空") @NotBlank(message = "试看权限不能为空")
@EnumValue(enumClass = PreviewPermissionEnum.class) @EnumValue(enumClass = PreviewPermissionEnum.class)
@Schema(description = "试看权限", example = "全集试看") @Schema(description = "试看权限[全集试看,部分试看,关闭,开启]", example = "全集试看")
private String permissions; private String permissions;
/** /**

View File

@ -0,0 +1,92 @@
package com.greenorange.promotion.model.dto.courseOrder;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 课程订单添加请求体
*/
@Data
@Schema(description = "课程订单添加请求体", requiredProperties = {
"courseId"
})
public class CourseOrderAddRequest implements Serializable {
// /**
// * 订单号
// */
// @NotBlank(message = "订单号不能为空")
// @Schema(description = "订单号", example = "202506241339232334d234234243")
// private String orderNumber;
/**
* 课程ID
*/
@Min(value = 1L, message = "课程ID ID不能小于1")
@Schema(description = "课程ID", example = "1")
private Long courseId;
// /**
// * 课程名称
// */
// @NotBlank(message = "课程名称不能为空")
// @Schema(description = "课程名称", example = "数据分析工程师训练营")
// private String name;
//
// /**
// * 课程类别
// */
// @NotBlank(message = "课程类别不能为空")
// @Schema(description = "课程类别", example = "自媒体")
// private String type;
//
// /**
// * 课程封面图片URL
// */
// @NotBlank(message = "课程封面图片URL不能为空")
// @Schema(description = "课程封面图片URL", example = "38EFJID33")
// private String image;
//
// /**
// * 课程原价
// */
// @Schema(description = "课程原价", example = "20.00")
// private BigDecimal originPrice;
//
// /**
// * 折扣价格
// */
// @Schema(description = "折扣价格", example = "80.00")
// private BigDecimal discountPrice;
//
// /**
// * 订单总金额
// */
// @Schema(description = "订单总金额", example = "80.00")
// private BigDecimal totalAmount;
//
// /**
// * 支付交易号
// */
// @NotBlank(message = "支付交易号不能为空")
// @Schema(description = "支付交易号", example = "432332333324444444444444423")
// private String transactionNumber;
//
// /**
// * 订单状态
// */
// @NotBlank(message = "订单状态不能为空")
//// @EnumValue(enumClass = CourseOrderStatusEnum.class)
// @Schema(description = "订单状态", example = "order")
// private String orderStatus;
@Serial
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,41 @@
package com.greenorange.promotion.model.dto.courseOrder;
import com.greenorange.promotion.annotation.EnumValue;
import com.greenorange.promotion.model.enums.OrderStatusEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Min;
import lombok.Data;
import java.math.BigDecimal;
import java.io.Serial;
import java.io.Serializable;
import com.greenorange.promotion.common.PageRequest;
import lombok.EqualsAndHashCode;
/**
* 课程订单查询请求体,继承自分页请求 PageRequest
*/
@Data
@Schema(description = "课程订单查询请求体", requiredProperties = {"current", "pageSize"})
public class CourseOrderQueryRequest extends PageRequest implements Serializable {
/**
* 订单号
*/
@Schema(description = "订单号", example = "202506241339232334d234234243")
private String orderNumber;
/**
* 订单状态[交易关闭,交易成功,待支付,已退款]
*/
@EnumValue(enumClass = OrderStatusEnum.class)
@Schema(description = "订单状态[交易关闭,交易成功,待支付,已退款]", example = "交易成功")
private String orderStatus;
@Serial
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,43 @@
package com.greenorange.promotion.model.dto.courseOrder;
import com.greenorange.promotion.annotation.EnumValue;
import com.greenorange.promotion.model.enums.OrderStatusEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Min;
import lombok.Data;
import java.math.BigDecimal;
import java.io.Serial;
import java.io.Serializable;
/**
* 课程订单更新请求体
*/
@Data
@Schema(description = "课程订单更新请求体", requiredProperties = {
"id",
"orderStatus"
})
public class CourseOrderUpdateRequest implements Serializable {
/**
* 订单ID
*/
@Min(value = 1L, message = "订单ID ID不能小于1")
@Schema(description = "订单ID", example = "1")
private Long id;
/**
* 订单状态[交易关闭,交易成功,待支付,已退款]
*/
@NotBlank(message = "订单状态不能为空")
@EnumValue(enumClass = OrderStatusEnum.class)
@Schema(description = "订单状态[交易关闭,交易成功,待支付,已退款]", example = "交易成功")
private String orderStatus;
@Serial
private static final long serialVersionUID = 1L;
}

View File

@ -59,6 +59,7 @@ public class ProjectAddRequest implements Serializable {
/** /**
* 项目状态[项目运行(running)|人数已满(full)|项目暂停(paused)] * 项目状态[项目运行(running)|人数已满(full)|项目暂停(paused)]
*/ */
@NotBlank(message = "项目状态不能为空")
@EnumValue(enumClass = ProjectStatusEnum.class) @EnumValue(enumClass = ProjectStatusEnum.class)
@Schema(description = "项目状态[项目运行(running)|人数已满(full)|项目暂停(paused)]", example = "running") @Schema(description = "项目状态[项目运行(running)|人数已满(full)|项目暂停(paused)]", example = "running")
private String projectStatus; private String projectStatus;

View File

@ -42,6 +42,7 @@ public class UserInfoRegisterRequest implements Serializable {
* 邀请码 * 邀请码
*/ */
@Schema(description = "邀请码", example = "666999") @Schema(description = "邀请码", example = "666999")
@NotBlank(message = "邀请码不能为空")
private String invitationCode; private String invitationCode;
/** /**

View File

@ -72,6 +72,11 @@ public class Course implements Serializable {
*/ */
private BigDecimal secondLevelRate; private BigDecimal secondLevelRate;
/**
* 是否上架(true:上架false:下架)
*/
private Boolean isShelves;
/** /**
* 是否删除 * 是否删除
*/ */

View File

@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date; import java.util.Date;
import lombok.Data; import lombok.Data;
@ -29,12 +31,12 @@ public class CourseChapter implements Serializable {
/** /**
* 章节时长(格式可自定义,如"00:10:00" * 章节时长(格式可自定义,如"00:10:00"
*/ */
private String duration; private Long duration;
/** /**
* 试看权限 * 试看权限[全集试看,部分试看,关闭,开启]
*/ */
private Object permissions; private String permissions;
/** /**
* 视频文件 view 值 * 视频文件 view 值
@ -61,6 +63,7 @@ public class CourseChapter implements Serializable {
*/ */
private Date updateTime; private Date updateTime;
@Serial
@TableField(exist = false) @TableField(exist = false)
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
} }

View File

@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Date; import java.util.Date;
@ -53,7 +55,7 @@ public class CourseOrder implements Serializable {
private BigDecimal originPrice; private BigDecimal originPrice;
/** /**
* 实际成交价格 * 折扣价格
*/ */
private BigDecimal discountPrice; private BigDecimal discountPrice;
@ -68,9 +70,14 @@ public class CourseOrder implements Serializable {
private String transactionNumber; private String transactionNumber;
/** /**
* 订单状态 * 订单状态[交易关闭,交易成功,待支付,已退款]
*/ */
private Object orderStatus; private String orderStatus;
/**
* 用户id
*/
private Long userId;
/** /**
* 是否删除 * 是否删除
@ -87,6 +94,7 @@ public class CourseOrder implements Serializable {
*/ */
private Date updateTime; private Date updateTime;
@Serial
@TableField(exist = false) @TableField(exist = false)
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
} }

View File

@ -0,0 +1,63 @@
package com.greenorange.promotion.model.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 课程推广码申请表
* @TableName course_qrcode_apply
*/
@TableName(value ="course_qrcode_apply")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class CourseQrcodeApply implements Serializable {
/**
* 课程推广码申请id
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 用户id
*/
private Long userId;
/**
* 课程id
*/
private Long courseId;
/**
* 课程推广码(view值)
*/
private String courseQrcode;
/**
* 是否删除
*/
private Integer isDelete;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,59 @@
package com.greenorange.promotion.model.enums;
import com.greenorange.promotion.annotation.BaseEnum;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* 订单状态枚举
*/
@Getter
public enum OrderStatusEnum implements BaseEnum {
CLOSED("交易关闭"),
SUCCESS("交易成功"),
PENDING("待支付"),
REFUNDED("已退款");
private final String value;
OrderStatusEnum(String value) {
this.value = value;
}
/**
* BaseEnum 要求的方法:返回枚举对应的校验值
*/
@Override
public String getValue() {
return this.value;
}
/**
* 获取所有枚举值列表
*/
public static List<String> getValues() {
return Arrays.stream(values())
.map(OrderStatusEnum::getValue)
.collect(Collectors.toList());
}
/**
* 根据值获取对应的枚举对象
*/
public static OrderStatusEnum getEnumByValue(String value) {
if (StringUtils.isBlank(value)) {
return null;
}
for (OrderStatusEnum status : OrderStatusEnum.values()) {
if (status.value.equals(value)) {
return status;
}
}
return null;
}
}

View File

@ -0,0 +1,60 @@
package com.greenorange.promotion.model.vo.course;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
@Data
@Schema(description = "课程卡片 视图对象")
public class CourseCardVO implements Serializable {
/**
* 课程ID
*/
@Schema(description = "课程ID", example = "1")
private Long id;
/**
* 课程名称
*/
@Schema(description = "课程名称", example = "数据分析工程师训练营")
private String name;
/**
* 课程类别[考公考研,自媒体,财经]
*/
@Schema(description = "课程类别[考公考研,自媒体,财经]", example = "自媒体")
private String type;
/**
* 课程图片URL
*/
@Schema(description = "课程图片URL", example = "324IEHJDE")
private String image;
/**
* 课程原价
*/
@Schema(description = "课程原价", example = "3499")
private BigDecimal originPrice;
/**
* 折扣价格
*/
@Schema(description = "折扣价格", example = "2499")
private BigDecimal discountPrice;
/**
* 已下单人数
*/
@Schema(description = "已下单人数", example = "100")
private Integer orderCount;
@Serial
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,75 @@
package com.greenorange.promotion.model.vo.course;
import com.greenorange.promotion.model.vo.courseChapter.CourseChapterVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
@Data
@Schema(description = "课程详情 视图对象")
public class CourseDetailVO implements Serializable {
/**
* 课程ID
*/
@Schema(description = "课程ID", example = "1")
private Long id;
/**
* 课程名称
*/
@Schema(description = "课程名称", example = "数据分析工程师训练营")
private String name;
/**
* 课程类别[考公考研,自媒体,财经]
*/
@Schema(description = "课程类别[考公考研,自媒体,财经]", example = "自媒体")
private String type;
/**
* 课程概述(富文本)
*/
@Schema(description = "课程概述(富文本)", example = "富文本")
private String detail;
/**
* 推广码说明(富文本)
*/
@Schema(description = "推广码说明(富文本)", example = "富文本")
private String promoCodeDesc;
/**
* 课程图片URL
*/
@Schema(description = "课程图片URL", example = "324IEHJDE")
private String image;
/**
* 课程原价
*/
@Schema(description = "课程原价", example = "3499")
private BigDecimal originPrice;
/**
* 折扣价格
*/
@Schema(description = "折扣价格", example = "2499")
private BigDecimal discountPrice;
/**
* 课程章节
*/
@Schema(description = "课程章节")
private List<CourseChapterVO> courseChapters;
@Serial
private static final long serialVersionUID = 1L;
}

View File

@ -80,6 +80,12 @@ public class CourseVO implements Serializable {
@Schema(description = "二级佣金比例(%", example = "5") @Schema(description = "二级佣金比例(%", example = "5")
private BigDecimal secondLevelRate; private BigDecimal secondLevelRate;
/**
* 是否上架(true:上架false:下架)
*/
@Schema(description = "是否上架(true:上架false:下架)", example = "true")
private Boolean isShelves;
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@ -35,9 +35,9 @@ public class CourseChapterVO implements Serializable {
private Long duration; private Long duration;
/** /**
* 试看权限 * 试看权限[全集试看,部分试看,关闭,开启]
*/ */
@Schema(description = "试看权限", example = "全集试看") @Schema(description = "试看权限[全集试看,部分试看,关闭,开启]", example = "全集试看")
private String permissions; private String permissions;
/** /**

View File

@ -0,0 +1,60 @@
package com.greenorange.promotion.model.vo.courseOrder;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 课程订单卡片 视图对象
*/
@Data
@Schema(description = "课程订单卡片 视图对象")
public class CourseOrderCardVO implements Serializable {
/**
* 课程订单ID
*/
@Schema(description = "课程订单ID", example = "1")
private Long id;
/**
* 订单号
*/
@Schema(description = "订单号", example = "202506241339232334d234234243")
private String orderNumber;
/**
* 课程名称
*/
@Schema(description = "课程名称", example = "数据分析工程师训练营")
private String name;
/**
* 课程类别
*/
@Schema(description = "课程类别", example = "自媒体")
private String type;
/**
* 订单总金额
*/
@Schema(description = "订单总金额", example = "100.00")
private BigDecimal totalAmount;
/**
* 订单状态[交易关闭,交易成功,待支付,已退款]
*/
@Schema(description = "订单状态[交易关闭,交易成功,待支付,已退款]", example = "交易成功")
private String orderStatus;
/**
* 创建时间
*/
@Schema(description = "创建时间", example = "2025-06-24 13:39:23")
private Date createTime;
}

View File

@ -0,0 +1,105 @@
package com.greenorange.promotion.model.vo.courseOrder;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 课程订单 视图对象
*/
@Data
@Schema(description = "课程订单 视图对象")
public class CourseOrderVO implements Serializable {
/**
* 课程订单ID
*/
@Schema(description = "课程订单ID", example = "1")
private Long id;
/**
* 订单号
*/
@Schema(description = "订单号", example = "202506241339232334d234234243")
private String orderNumber;
/**
* 课程ID
*/
@Schema(description = "课程ID", example = "1")
private Long courseId;
/**
* 课程名称
*/
@Schema(description = "课程名称", example = "数据分析工程师训练营")
private String name;
/**
* 课程类别
*/
@Schema(description = "课程类别", example = "自媒体")
private String type;
/**
* 课程封面图片URL
*/
@Schema(description = "课程封面图片URL", example = "32DHDF3KI")
private String image;
/**
* 课程原价
*/
@Schema(description = "课程原价", example = "100.00")
private BigDecimal originPrice;
/**
* 折扣价格
*/
@Schema(description = "折扣价格", example = "50.00")
private BigDecimal discountPrice;
/**
* 订单总金额
*/
@Schema(description = "订单总金额", example = "100.00")
private BigDecimal totalAmount;
/**
* 支付交易号
*/
@Schema(description = "支付交易号", example = "4342348232388888833333333333")
private String transactionNumber;
/**
* 订单状态[交易关闭,交易成功,待支付,已退款]
*/
@Schema(description = "订单状态[交易关闭,交易成功,待支付,已退款]", example = "交易成功")
private String orderStatus;
/**
* 用户id
*/
@Schema(description = "用户id", example = "1")
private Long userId;
/**
* 创建时间
*/
@Schema(description = "创建时间", example = "2025-06-24 13:39:23")
private Date createTime;
/**
* 更新时间
*/
@Schema(description = "更新时间", example = "2025-06-24 13:39:23")
private Date updateTime;
@Serial
private static final long serialVersionUID = 1L;
}

View File

@ -1,5 +1,7 @@
package com.greenorange.promotion.service.course; package com.greenorange.promotion.service.course;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.greenorange.promotion.model.dto.courseOrder.CourseOrderQueryRequest;
import com.greenorange.promotion.model.entity.CourseOrder; import com.greenorange.promotion.model.entity.CourseOrder;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
@ -10,4 +12,9 @@ import com.baomidou.mybatisplus.extension.service.IService;
*/ */
public interface CourseOrderService extends IService<CourseOrder> { public interface CourseOrderService extends IService<CourseOrder> {
/**
* 获取查询条件
*/
QueryWrapper<CourseOrder> getQueryWrapper(CourseOrderQueryRequest courseOrderQueryRequest);
} }

View File

@ -0,0 +1,13 @@
package com.greenorange.promotion.service.course;
import com.greenorange.promotion.model.entity.CourseQrcodeApply;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* @author 35880
* @description 针对表【course_qrcode_apply(课程推广码申请表)】的数据库操作Service
* @createDate 2025-06-24 22:10:39
*/
public interface CourseQrcodeApplyService extends IService<CourseQrcodeApply> {
}

View File

@ -25,11 +25,13 @@ public class CourseChapterServiceImpl extends ServiceImpl<CourseChapterMapper, C
*/ */
@Override @Override
public QueryWrapper<CourseChapter> getQueryWrapper(CourseChapterQueryRequest courseChapterQueryRequest) { public QueryWrapper<CourseChapter> getQueryWrapper(CourseChapterQueryRequest courseChapterQueryRequest) {
Long courseId = courseChapterQueryRequest.getCourseId();
String name = courseChapterQueryRequest.getName(); String name = courseChapterQueryRequest.getName();
String permissions = courseChapterQueryRequest.getPermissions(); String permissions = courseChapterQueryRequest.getPermissions();
String sortField = courseChapterQueryRequest.getSortField(); String sortField = courseChapterQueryRequest.getSortField();
String sortOrder = courseChapterQueryRequest.getSortOrder(); String sortOrder = courseChapterQueryRequest.getSortOrder();
QueryWrapper<CourseChapter> queryWrapper = new QueryWrapper<>(); QueryWrapper<CourseChapter> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("courseId", courseId);
queryWrapper.eq(StringUtils.isNotBlank(name), "name", name); queryWrapper.eq(StringUtils.isNotBlank(name), "name", name);
queryWrapper.eq(StringUtils.isNotBlank(permissions), "permissions", permissions); queryWrapper.eq(StringUtils.isNotBlank(permissions), "permissions", permissions);
queryWrapper.orderBy(SqlUtils.validSortField(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC), sortField); queryWrapper.orderBy(SqlUtils.validSortField(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC), sortField);

View File

@ -1,9 +1,14 @@
package com.greenorange.promotion.service.course.impl; package com.greenorange.promotion.service.course.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.greenorange.promotion.constant.CommonConstant;
import com.greenorange.promotion.model.dto.courseOrder.CourseOrderQueryRequest;
import com.greenorange.promotion.model.entity.CourseOrder; import com.greenorange.promotion.model.entity.CourseOrder;
import com.greenorange.promotion.service.course.CourseOrderService; import com.greenorange.promotion.service.course.CourseOrderService;
import com.greenorange.promotion.mapper.CourseOrderMapper; import com.greenorange.promotion.mapper.CourseOrderMapper;
import com.greenorange.promotion.utils.SqlUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
/** /**
@ -15,6 +20,22 @@ import org.springframework.stereotype.Service;
public class CourseOrderServiceImpl extends ServiceImpl<CourseOrderMapper, CourseOrder> public class CourseOrderServiceImpl extends ServiceImpl<CourseOrderMapper, CourseOrder>
implements CourseOrderService{ implements CourseOrderService{
/**
* 获取查询条件
*/
@Override
public QueryWrapper<CourseOrder> getQueryWrapper(CourseOrderQueryRequest courseOrderQueryRequest) {
String orderNumber = courseOrderQueryRequest.getOrderNumber();
String orderStatus = courseOrderQueryRequest.getOrderStatus();
String sortField = courseOrderQueryRequest.getSortField();
String sortOrder = courseOrderQueryRequest.getSortOrder();
QueryWrapper<CourseOrder> queryWrapper = new QueryWrapper<>();
queryWrapper.eq(StringUtils.isNotBlank(orderNumber), "orderNumber", orderNumber);
queryWrapper.eq(StringUtils.isNotBlank(orderStatus), "orderStatus", orderStatus);
queryWrapper.orderBy(SqlUtils.validSortField(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC), sortField);
return queryWrapper;
}
} }

View File

@ -0,0 +1,22 @@
package com.greenorange.promotion.service.course.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.greenorange.promotion.model.entity.CourseQrcodeApply;
import com.greenorange.promotion.service.course.CourseQrcodeApplyService;
import com.greenorange.promotion.mapper.CourseQrcodeApplyMapper;
import org.springframework.stereotype.Service;
/**
* @author 35880
* @description 针对表【course_qrcode_apply(课程推广码申请表)】的数据库操作Service实现
* @createDate 2025-06-24 22:10:39
*/
@Service
public class CourseQrcodeApplyServiceImpl extends ServiceImpl<CourseQrcodeApplyMapper, CourseQrcodeApply>
implements CourseQrcodeApplyService{
}

View File

@ -8,6 +8,7 @@ import com.greenorange.promotion.model.entity.Course;
import com.greenorange.promotion.service.course.CourseService; import com.greenorange.promotion.service.course.CourseService;
import com.greenorange.promotion.mapper.CourseMapper; import com.greenorange.promotion.mapper.CourseMapper;
import com.greenorange.promotion.utils.SqlUtils; import com.greenorange.promotion.utils.SqlUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -28,11 +29,13 @@ public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course>
public QueryWrapper<Course> getQueryWrapper(CourseQueryRequest courseQueryRequest) { public QueryWrapper<Course> getQueryWrapper(CourseQueryRequest courseQueryRequest) {
String name = courseQueryRequest.getName(); String name = courseQueryRequest.getName();
String type = courseQueryRequest.getType(); String type = courseQueryRequest.getType();
Boolean isShelves = courseQueryRequest.getIsShelves();
String sortField = courseQueryRequest.getSortField(); String sortField = courseQueryRequest.getSortField();
String sortOrder = courseQueryRequest.getSortOrder(); String sortOrder = courseQueryRequest.getSortOrder();
QueryWrapper<Course> queryWrapper = new QueryWrapper<>(); QueryWrapper<Course> queryWrapper = new QueryWrapper<>();
queryWrapper.eq(StringUtils.isNotBlank(name), "name", name); queryWrapper.eq(StringUtils.isNotBlank(name), "name", name);
queryWrapper.eq(StringUtils.isNotBlank(type), "type", type); queryWrapper.eq(StringUtils.isNotBlank(type), "type", type);
queryWrapper.eq(ObjectUtils.isNotEmpty(isShelves), "isShelves", isShelves);
queryWrapper.orderBy(SqlUtils.validSortField(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC), sortField); queryWrapper.orderBy(SqlUtils.validSortField(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC), sortField);
return queryWrapper; return queryWrapper;
} }

View File

@ -65,7 +65,7 @@ public class ProjectCommissionServiceImpl extends ServiceImpl<ProjectCommissionM
public void updateProjectCommissionRate(ProjectCommissionUpdateRequest projectCommissionUpdateRequest) { public void updateProjectCommissionRate(ProjectCommissionUpdateRequest projectCommissionUpdateRequest) {
Long id = projectCommissionUpdateRequest.getId(); Long id = projectCommissionUpdateRequest.getId();
BigDecimal currentCommissionRate = projectCommissionUpdateRequest.getCurrentCommissionRate(); BigDecimal currentCommissionRate = projectCommissionUpdateRequest.getCurrentCommissionRate();
// 获取当前项目明细信息 // 获取当前项目明细抽佣信息
ProjectCommission projectCommission = this.getById(id); ProjectCommission projectCommission = this.getById(id);
ThrowUtils.throwIf(projectCommission == null, ErrorCode.OPERATION_ERROR, "项目明细抽佣信息不存在"); ThrowUtils.throwIf(projectCommission == null, ErrorCode.OPERATION_ERROR, "项目明细抽佣信息不存在");
Long projectDetailId = projectCommission.getProjectDetailId(); Long projectDetailId = projectCommission.getProjectDetailId();
@ -356,7 +356,7 @@ public class ProjectCommissionServiceImpl extends ServiceImpl<ProjectCommissionM
startTime = System.currentTimeMillis(); startTime = System.currentTimeMillis();
// 更新用户项目明细抽佣记录 // 批量更新用户项目明细抽佣记录
List<SubUserProjectCommission> proCommissions = subProjectCommissions.stream().filter(subProjectCommission -> subProjectCommission.getSubUserId() == -1L).toList(); List<SubUserProjectCommission> proCommissions = subProjectCommissions.stream().filter(subProjectCommission -> subProjectCommission.getSubUserId() == -1L).toList();
List<ProjectCommission> proCommissionList = commonService.convertList(proCommissions, ProjectCommission.class); List<ProjectCommission> proCommissionList = commonService.convertList(proCommissions, ProjectCommission.class);
// this.updateBatchById(proCommissionList); // this.updateBatchById(proCommissionList);

View File

@ -68,4 +68,5 @@ public interface UserInfoService extends IService<UserInfo> {
* 查询从 userId 一路到根节点的所有 id按 depth 倒序(根先出) * 查询从 userId 一路到根节点的所有 id按 depth 倒序(根先出)
*/ */
List<Long> findPathToRoot(Long userId); List<Long> findPathToRoot(Long userId);
} }

View File

@ -1,6 +1,8 @@
package com.greenorange.promotion.service.wechat; package com.greenorange.promotion.service.wechat;
import com.greenorange.promotion.config.WxAccessToken; import com.greenorange.promotion.config.WxAccessToken;
import com.greenorange.promotion.model.dto.CommonRequest;
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException; import java.io.IOException;
@ -27,5 +29,5 @@ public interface WechatGetQrcodeService {
/** /**
* 微信小程序获取课程码 * 微信小程序获取课程码
*/ */
String getWxCourseQrCode(String inviteCode) throws Exception; String getWxCourseQrCode(CommonRequest courseQrcodeAddRequest, HttpServletRequest request) throws Exception;
} }

View File

@ -12,13 +12,23 @@ import com.freewayso.image.combiner.enums.ZoomMode;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.greenorange.promotion.common.ErrorCode; import com.greenorange.promotion.common.ErrorCode;
import com.greenorange.promotion.config.WxAccessToken; import com.greenorange.promotion.config.WxAccessToken;
import com.greenorange.promotion.constant.SystemConstant;
import com.greenorange.promotion.exception.BusinessException; import com.greenorange.promotion.exception.BusinessException;
import com.greenorange.promotion.mapper.UserInfoMapper;
import com.greenorange.promotion.model.dto.CommonRequest;
import com.greenorange.promotion.model.entity.Course;
import com.greenorange.promotion.model.entity.CourseQrcodeApply;
import com.greenorange.promotion.model.entity.FileInfo; import com.greenorange.promotion.model.entity.FileInfo;
import com.greenorange.promotion.model.entity.UserInfo;
import com.greenorange.promotion.service.course.CourseQrcodeApplyService;
import com.greenorange.promotion.service.course.CourseService;
import com.greenorange.promotion.service.file.FileInfoService; import com.greenorange.promotion.service.file.FileInfoService;
import com.greenorange.promotion.service.userInfo.UserInfoService;
import com.greenorange.promotion.service.wechat.WechatGetQrcodeService; import com.greenorange.promotion.service.wechat.WechatGetQrcodeService;
import com.greenorange.promotion.utils.QRCodeUtil; import com.greenorange.promotion.utils.QRCodeUtil;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.RandomStringUtils; import org.apache.commons.lang.RandomStringUtils;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
@ -31,7 +41,6 @@ import java.awt.*;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.*; import java.io.*;
import java.net.URL; import java.net.URL;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -40,7 +49,6 @@ import java.util.concurrent.TimeUnit;
public class WechatGetQrcodeServiceImpl implements WechatGetQrcodeService { public class WechatGetQrcodeServiceImpl implements WechatGetQrcodeService {
// 文件上传的存储目录 // 文件上传的存储目录
@Value("${file.upload-dir}") @Value("${file.upload-dir}")
private String uploadDir; private String uploadDir;
@ -63,10 +71,18 @@ public class WechatGetQrcodeServiceImpl implements WechatGetQrcodeService {
@Value("${wx.mini.appSecret}") @Value("${wx.mini.appSecret}")
private String appSecret; private String appSecret;
@Resource @Resource
private FileInfoService fileInfoService; private FileInfoService fileInfoService;
@Resource
private UserInfoMapper userInfoMapper;
@Resource
private CourseService courseService;
@Resource
private CourseQrcodeApplyService courseQrcodeApplyService;
/** /**
* 获取接口调用凭据 * 获取接口调用凭据
@ -197,14 +213,27 @@ public class WechatGetQrcodeServiceImpl implements WechatGetQrcodeService {
*/ */
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public String getWxCourseQrCode(String inviteCode) throws Exception { public String getWxCourseQrCode(CommonRequest commonRequest, HttpServletRequest request) throws Exception {
String accessToken = (String) redisTemplate.opsForValue().get(ACCESS_TOKEN_KEY); String accessToken = (String) redisTemplate.opsForValue().get(ACCESS_TOKEN_KEY);
if (accessToken == null) { if (accessToken == null) {
accessToken = this.getAccessToken().getAccess_token(); accessToken = this.getAccessToken().getAccess_token();
} }
// 获取用户邀请码
Long userId = (Long) request.getAttribute("userId");
UserInfo userInfo = userInfoMapper.selectById(userId);
String invitationCode = userInfo.getInvitationCode();
// 获取课程信息
Long courseId = commonRequest.getId();
Course course = courseService.getById(courseId);
String courseTitle = course.getName();
String originalPrice = String.valueOf(course.getOriginPrice());
String discountPrice = String.valueOf(course.getDiscountPrice());
String discountText = "元券后价";
Map<String, Object> param = new HashMap<>(); Map<String, Object> param = new HashMap<>();
param.put("page", "pages/loginModule/register/register"); param.put("page", "pages/loginModule/register/register");
param.put("scene", "invitationCode=" + inviteCode); param.put("scene", "invitationCode=" + invitationCode + "&courseId=" + courseId);
param.put("width", 430); param.put("width", 430);
param.put("check_path", false); param.put("check_path", false);
param.put("env_version", "develop"); param.put("env_version", "develop");
@ -216,10 +245,6 @@ public class WechatGetQrcodeServiceImpl implements WechatGetQrcodeService {
.execute() .execute()
.bodyBytes(); .bodyBytes();
String courseTitle = "【早鸟42折】掌握CAD技能实战技能实战技能实战技能实战工作训练营";
String originalPrice = "2680元";
String discountPrice = "1680";
String discountText = "元券后价";
String FontType = "Microsoft YaHei UI"; String FontType = "Microsoft YaHei UI";
int FontStyle = Font.PLAIN; int FontStyle = Font.PLAIN;
@ -228,7 +253,7 @@ public class WechatGetQrcodeServiceImpl implements WechatGetQrcodeService {
ImageCombiner combiner = new ImageCombiner(blankUrl, 341, 391, ZoomMode.WidthHeight, OutputFormat.PNG); ImageCombiner combiner = new ImageCombiner(blankUrl, 341, 391, ZoomMode.WidthHeight, OutputFormat.PNG);
// 加载课程图片 // 加载课程图片
String courseUrl = "https://img.picui.cn/free/2025/06/22/6856ef5908d4b.jpg"; String courseUrl = SystemConstant.FILE_COMMON_PREFIX + course.getImage();
BufferedImage courseImage = ImageIO.read(new URL(courseUrl)); BufferedImage courseImage = ImageIO.read(new URL(courseUrl));
// Graphics2D graphics = courseImage.createGraphics(); // Graphics2D graphics = courseImage.createGraphics();
@ -311,21 +336,18 @@ public class WechatGetQrcodeServiceImpl implements WechatGetQrcodeService {
.hashValue(hashValue) .hashValue(hashValue)
.build(); .build();
fileInfoService.save(fileInfo); fileInfoService.save(fileInfo);
return biz + "-" + view;
String viewValue = biz + "-" + view;
// 保存课程推广码申请记录
CourseQrcodeApply courseQrcodeApply = CourseQrcodeApply.builder()
.userId(userId)
.courseId(courseId)
.courseQrcode(viewValue)
.build();
courseQrcodeApplyService.save(courseQrcodeApply);
return viewValue;
} }
public static void main(String[] args) {
// 获取本地图形环境
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
// 列出所有可用字体家族名
String[] families = ge.getAvailableFontFamilyNames();
// 打印全部字体(可选)
System.out.println("=== Available Font Families ===");
Arrays.stream(families).forEach(System.out::println);
}

View File

@ -38,7 +38,7 @@ public class OrderNumberUtils {
// 获取时间戳(精确到秒) // 获取时间戳(精确到秒)
String timestamp = DATE_FORMAT.format(new Date()); String timestamp = DATE_FORMAT.format(new Date());
// 获取4位随机数 // 获取6位随机数
String randomNumber = generateRandomNumber(); String randomNumber = generateRandomNumber();
// 获取6位自增序列号并确保不超过最大值 // 获取6位自增序列号并确保不超过最大值
@ -56,10 +56,10 @@ public class OrderNumberUtils {
return new SimpleDateFormat("yyyyMMdd").format(new Date()); return new SimpleDateFormat("yyyyMMdd").format(new Date());
} }
// 生成4位随机数范围00009999 // 生成6位随机数范围000000到999999
private static String generateRandomNumber() { private static String generateRandomNumber() {
int random = (int) (Math.random() * 10000); // 生成0到9999之间的随机数 int random = (int) (Math.random() * 1000000); // 生成0到999999之间的随机数
return String.format("%04d", random); // 格式化为4 return String.format("%06d", random); // 格式化为6
} }
// 获取下一个自增序列号使用ReentrantLock来确保线程安全 // 获取下一个自增序列号使用ReentrantLock来确保线程安全

View File

@ -1,15 +1,21 @@
spring: spring:
datasource: datasource:
# driver-class-name: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://27.30.77.229:3306/qingcheng_caozhe?serverTimezone=Asia/Shanghai
# username: qingcheng
# password: Qc@8ls2jf
# hikari:
# maximum-pool-size: 300
# max-lifetime: 120000
driver-class-name: com.mysql.cj.jdbc.Driver driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://27.30.77.229:3306/qingcheng_caozhe?serverTimezone=Asia/Shanghai url: jdbc:mysql://43.143.28.121:3306/easybbs?serverTimezone=Asia/Shanghai
username: qingcheng username: easybbs
password: Qc@8ls2jf password: root
hikari: hikari:
maximum-pool-size: 300 maximum-pool-size: 300
max-lifetime: 120000 max-lifetime: 120000
data: data:
redis: redis:
port: 6379 port: 6379

View File

@ -1,4 +1,4 @@
spring: spring:
profiles: profiles:
active: dev active: practice

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.greenorange.promotion.mapper.CourseQrcodeApplyMapper">
<resultMap id="BaseResultMap" type="com.greenorange.promotion.model.entity.CourseQrcodeApply">
<id property="id" column="id" jdbcType="BIGINT"/>
<result property="userId" column="userId" jdbcType="BIGINT"/>
<result property="courseId" column="courseId" jdbcType="BIGINT"/>
<result property="isDelete" column="isDelete" jdbcType="TINYINT"/>
<result property="createTime" column="createTime" jdbcType="TIMESTAMP"/>
<result property="updateTime" column="updateTime" jdbcType="TIMESTAMP"/>
</resultMap>
<sql id="Base_Column_List">
id,userId,courseId,
isDelete,createTime,updateTime
</sql>
</mapper>

View File

@ -42,7 +42,7 @@ public class ${entityName}Controller {
* @return 是否更新成功 * @return 是否更新成功
*/ */
@PostMapping("update") @PostMapping("update")
@Operation(summary = "web端管理员根据id修改${entityComment}", description = "参数:${entityComment}更新请求体权限管理员方法名update${entityName}") @Operation(summary = "web端管理员根据id修改${entityComment}信息", description = "参数:${entityComment}更新请求体权限管理员方法名update${entityName}")
@RequiresPermission(mustRole = UserConstant.ADMIN_ROLE) @RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
@SysLog(title = "${entityComment}管理", content = "web端管理员根据id修改${entityComment}信息") @SysLog(title = "${entityComment}管理", content = "web端管理员根据id修改${entityComment}信息")
public BaseResponse<Boolean> update${entityName}(@Valid @RequestBody ${entityName}UpdateRequest ${entityNameLower}UpdateRequest) { public BaseResponse<Boolean> update${entityName}(@Valid @RequestBody ${entityName}UpdateRequest ${entityNameLower}UpdateRequest) {

View File

@ -1,75 +1,74 @@
package com.greenorange.promotion.junit; //package com.greenorange.promotion.junit;
//
import com.greenorange.promotion.model.dto.CommonRequest; //import com.greenorange.promotion.model.dto.CommonRequest;
import com.greenorange.promotion.model.entity.Project; //import com.greenorange.promotion.model.entity.Project;
import com.greenorange.promotion.model.vo.project.ProjectVO; //import com.greenorange.promotion.model.vo.project.ProjectVO;
import com.greenorange.promotion.service.common.CommonService; //import com.greenorange.promotion.service.common.CommonService;
import com.greenorange.promotion.service.project.ProjectService; //import com.greenorange.promotion.service.project.ProjectService;
import com.greenorange.promotion.service.project.impl.ProjectServiceImpl; //import com.greenorange.promotion.service.project.impl.ProjectServiceImpl;
import org.junit.jupiter.api.Test; //import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; //import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks; //import org.mockito.InjectMocks;
import org.mockito.Mock; //import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension; //import org.mockito.junit.jupiter.MockitoExtension;
//
import static org.junit.jupiter.api.Assertions.*; //import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*; //import static org.mockito.Mockito.*;
//
@ExtendWith(MockitoExtension.class) //@ExtendWith(MockitoExtension.class)
class ProjectServiceImplTest { //class ProjectServiceImplTest {
//
@InjectMocks // @InjectMocks
private ProjectServiceImpl service; // private ProjectServiceImpl service;
// 把真正的业务实现类注入进来 // // 把真正的业务实现类注入进来
//
@Mock // @Mock
private CommonService commonService; // private CommonService commonService;
// 用于 copyProperties // // 用于 copyProperties
//
@Mock // @Mock
private ProjectService projectService; // private ProjectService projectService;
// 用于 getById // // 用于 getById
//
@Test // @Test
void queryProjectById_notFound_throwsException() { // void queryProjectById_notFound_throwsException() {
// Arrange // // Arrange
CommonRequest req = new CommonRequest(); // CommonRequest req = new CommonRequest();
req.setId(10L); // req.setId(10L);
when(projectService.getById(10L)).thenReturn(null); // when(projectService.getById(10L)).thenReturn(null);
// // Act & Assert
// Act & Assert // RuntimeException ex = assertThrows(RuntimeException.class, () ->
RuntimeException ex = assertThrows(RuntimeException.class, () -> // service.queryProjectById(req)
service.queryProjectById(req) // );
); // assertTrue(ex.getMessage().equals("当前项目不存在"));
assertTrue(ex.getMessage().contains("当前项目不存在")); //
// // commonService.copyProperties 不应被调用
// commonService.copyProperties 不应被调用 // verify(commonService, never()).copyProperties(any(), any());
verify(commonService, never()).copyProperties(any(), any()); // }
} //
// @Test
@Test // void queryProjectById_found_returnsVO() {
void queryProjectById_found_returnsVO() { // // Arrange
// Arrange // Long projectId = 20L;
Long projectId = 20L; // CommonRequest req = new CommonRequest();
CommonRequest req = new CommonRequest(); // req.setId(projectId);
req.setId(projectId); //
// Project project = new Project();
Project project = new Project(); // project.setId(projectId);
project.setId(projectId); // project.setProjectName("示例项目");
project.setProjectName("示例项目"); // when(projectService.getById(projectId)).thenReturn(project);
when(projectService.getById(projectId)).thenReturn(project); //
// ProjectVO vo = new ProjectVO();
ProjectVO vo = new ProjectVO(); // vo.setId(projectId);
vo.setId(projectId); // vo.setProjectName("示例项目");
vo.setProjectName("示例项目"); // when(commonService.copyProperties(project, ProjectVO.class))
when(commonService.copyProperties(project, ProjectVO.class)) // .thenReturn(vo);
.thenReturn(vo); //
// // Act
// Act // ProjectVO result = service.queryProjectById(req);
ProjectVO result = service.queryProjectById(req); //
// // Assert
// Assert // assertSame(vo, result, "应返回 commonService.copyProperties 的结果");
assertSame(vo, result, "应返回 commonService.copyProperties 的结果"); // verify(commonService, times(1)).copyProperties(project, ProjectVO.class);
verify(commonService, times(1)).copyProperties(project, ProjectVO.class); // }
} //}
}