完成了课程模块的订单部分

This commit is contained in:
2025-06-24 19:49:24 +08:00
parent 502f079194
commit 1f7e1211cf
12 changed files with 273 additions and 144 deletions

View File

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

View File

@ -1,9 +1,7 @@
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.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;
@ -14,7 +12,6 @@ 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.CommonStringRequest;
import com.greenorange.promotion.model.dto.course.CourseAddRequest; import com.greenorange.promotion.model.dto.course.CourseAddRequest;
import com.greenorange.promotion.model.dto.course.CourseQrcodeAddRequest;
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;
@ -30,6 +27,7 @@ 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;
@ -38,6 +36,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
/** /**
@ -62,6 +61,27 @@ public class CourseController {
private WechatGetQrcodeService wechatGetQrcodeService; private WechatGetQrcodeService wechatGetQrcodeService;
/**
* 小程序端用户查看热门课程列表
* @return 课程信息列表
*/
@PostMapping("query/hot")
@Operation(summary = "小程序端用户查看热门课程列表", description = "参数权限管理员方法名miniQueryHotCourseList")
@RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
@SysLog(title = "课程管理", content = "小程序端用户查看热门课程列表")
public BaseResponse<List<CourseCardVO>> miniQueryHotCourseList() {
List<Course> courseList = courseService.list();
// 降序排序并取前四个元素
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 课程类别 * @param commonStringRequest 课程类别
@ -103,15 +123,15 @@ public class CourseController {
/** /**
* 小程序端用户生成课程推广码 * 小程序端用户生成课程推广码
* @param courseQrcodeAddRequest 课程id * @param commonRequest 课程id
* @return 课程信息列表 * @return 课程信息列表
*/ */
@PostMapping("generate/qrcode") @PostMapping("generate/qrcode")
@Operation(summary = "小程序端用户生成课程推广码", description = "参数课程id权限管理员方法名miniGenerateQrcode") @Operation(summary = "小程序端用户生成课程推广码", description = "参数课程id权限管理员方法名miniGenerateQrcode")
@RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE) @RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
@SysLog(title = "课程管理", content = "小程序端用户生成课程推广码") @SysLog(title = "课程管理", content = "小程序端用户生成课程推广码")
public BaseResponse<String> miniGenerateQrcode(@Valid @RequestBody CourseQrcodeAddRequest courseQrcodeAddRequest) throws Exception { public BaseResponse<String> miniGenerateQrcode(@Valid @RequestBody CommonRequest commonRequest, HttpServletRequest request) throws Exception {
String videoView = wechatGetQrcodeService.getWxCourseQrCode(courseQrcodeAddRequest); String videoView = wechatGetQrcodeService.getWxCourseQrCode(commonRequest, request);
return ResultUtils.success(videoView); return ResultUtils.success(videoView);
} }
@ -135,6 +155,8 @@ public class CourseController {
/** /**
* web端管理员添加课程 * web端管理员添加课程
* @param courseAddRequest 课程添加请求体 * @param courseAddRequest 课程添加请求体
@ -156,7 +178,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) {

View File

@ -1,21 +1,31 @@
package com.greenorange.promotion.controller.course; 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.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
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.OrderStatusConstant;
import com.greenorange.promotion.constant.UserConstant; 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.CommonBatchRequest;
import com.greenorange.promotion.model.dto.CommonRequest; import com.greenorange.promotion.model.dto.CommonRequest;
import com.greenorange.promotion.model.dto.courseOrder.CourseOrderAddRequest; import com.greenorange.promotion.model.dto.courseOrder.CourseOrderAddRequest;
import com.greenorange.promotion.model.dto.courseOrder.CourseOrderQueryRequest; import com.greenorange.promotion.model.dto.courseOrder.CourseOrderQueryRequest;
import com.greenorange.promotion.model.dto.courseOrder.CourseOrderUpdateRequest; 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.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.model.vo.courseOrder.CourseOrderVO;
import com.greenorange.promotion.service.common.CommonService; import com.greenorange.promotion.service.common.CommonService;
import com.greenorange.promotion.service.course.CourseOrderService; 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.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;
@ -27,6 +37,7 @@ 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.util.Collections;
import java.util.List; import java.util.List;
@ -39,6 +50,9 @@ import java.util.List;
@Tag(name = "课程订单模块") @Tag(name = "课程订单模块")
public class CourseOrderController { public class CourseOrderController {
@Resource
private CourseService courseService;
@Resource @Resource
private CourseOrderService courseOrderService; private CourseOrderService courseOrderService;
@ -46,35 +60,103 @@ public class CourseOrderController {
private CommonService commonService; private CommonService commonService;
/** /**
* web端管理员添加课程订单 * 小程序端用户生成课程订单
* @param courseOrderAddRequest 课程订单添加请求体 * @param courseOrderAddRequest 课程id
* @return 是否添加成功 * @return 是否添加成功
*/ */
@PostMapping("add") @PostMapping("add")
@Operation(summary = "web端管理员添加课程订单", description = "参数:课程订单添加请求体权限管理员方法名addCourseOrder") @Operation(summary = "小程序端用户生成课程订单", description = "参数:课程id权限管理员方法名addCourseOrder")
@RequiresPermission(mustRole = UserConstant.ADMIN_ROLE) @RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
@SysLog(title = "课程订单管理", content = "web端管理员添加课程订单") @SysLog(title = "课程订单管理", content = "小程序端用户生成课程订单")
public BaseResponse<Long> addCourseOrder(@Valid @RequestBody CourseOrderAddRequest courseOrderAddRequest, HttpServletRequest request) { public BaseResponse<Long> addCourseOrder(@Valid @RequestBody CourseOrderAddRequest courseOrderAddRequest, HttpServletRequest request) {
CourseOrder courseOrder = commonService.copyProperties(courseOrderAddRequest, CourseOrder.class); 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); courseOrderService.save(courseOrder);
return ResultUtils.success(courseOrder.getId()); return ResultUtils.success(courseOrder.getId());
} }
/** /**
* web端管理员根据id修改课程订单信息 * 小程序端用户取消课程订单
* @param courseOrderUpdateRequest 课程订单更新请求体 * @param courseOrderAddRequest 课程id
* @return 是否更新成功 * @return 是否添加成功
*/ */
@PostMapping("update") @PostMapping("cancel")
@Operation(summary = "web端管理员根据id修改课程订单", description = "参数:课程订单更新请求体,权限:管理员,方法名:updateCourseOrder") @Operation(summary = "小程序端用户取消课程订单", description = "参数:订单id,权限:管理员,方法名:cancelCourseOrder")
@RequiresPermission(mustRole = UserConstant.ADMIN_ROLE) @RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
@SysLog(title = "课程订单管理", content = "web端管理员根据id修改课程订单信息") @SysLog(title = "课程订单管理", content = "小程序端用户取消课程订单")
public BaseResponse<Boolean> updateCourseOrder(@Valid @RequestBody CourseOrderUpdateRequest courseOrderUpdateRequest) { public BaseResponse<Long> cancelCourseOrder(@Valid @RequestBody CourseOrderAddRequest courseOrderAddRequest) {
CourseOrder courseOrder = commonService.copyProperties(courseOrderUpdateRequest, CourseOrder.class); Long courseId = courseOrderAddRequest.getCourseId();
courseOrderService.updateById(courseOrder); CourseOrder courseOrder = courseOrderService.getById(courseId);
return ResultUtils.success(true); 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());
} }
/**
* 小程序端用户在提交订单页中显示课程信息
* @param commonRequest 课程id
* @return 是否添加成功
*/
@PostMapping("show/info")
@Operation(summary = "小程序端用户在提交订单页中显示课程信息", description = "参数订单id权限管理员方法名showCourseInfo")
@RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
@SysLog(title = "课程订单管理", content = "小程序端用户在提交订单页中显示课程信息")
public BaseResponse<CourseCardVO> showCourseInfo(@Valid @RequestBody CommonRequest commonRequest) {
Long id = commonRequest.getId();
Course course = courseService.getById(id);
CourseCardVO courseCardVO = commonService.copyProperties(course, CourseCardVO.class);
return ResultUtils.success(courseCardVO);
}
/**
* 小程序端用户查询课程订单列表
* @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删除课程订单 * web端管理员根据id删除课程订单
* @param commonRequest 课程订单删除请求体 * @param commonRequest 课程订单删除请求体
@ -86,6 +168,9 @@ public class CourseOrderController {
@SysLog(title = "课程订单管理", content = "web端管理员根据id删除课程订单") @SysLog(title = "课程订单管理", content = "web端管理员根据id删除课程订单")
public BaseResponse<Boolean> delCourseOrder(@Valid @RequestBody CommonRequest commonRequest) { public BaseResponse<Boolean> delCourseOrder(@Valid @RequestBody CommonRequest commonRequest) {
Long id = commonRequest.getId(); Long id = commonRequest.getId();
CourseOrder courseOrder = courseOrderService.getById(id);
ThrowUtils.throwIf(courseOrder == null || !courseOrder.getOrderStatus().equals(OrderStatusConstant.CLOSED),
ErrorCode.OPERATION_ERROR, "该课程订单不存在或订单状态错误");
courseOrderService.removeById(id); courseOrderService.removeById(id);
return ResultUtils.success(true); return ResultUtils.success(true);
} }
@ -101,6 +186,10 @@ public class CourseOrderController {
@SysLog(title = "课程订单管理", content = "web端管理员批量删除课程订单") @SysLog(title = "课程订单管理", content = "web端管理员批量删除课程订单")
public BaseResponse<Boolean> delBatchCourseOrder(@Valid @RequestBody CommonBatchRequest commonBatchRequest) { public BaseResponse<Boolean> delBatchCourseOrder(@Valid @RequestBody CommonBatchRequest commonBatchRequest) {
List<Long> ids = commonBatchRequest.getIds(); 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); courseOrderService.removeByIds(ids);
return ResultUtils.success(true); return ResultUtils.success(true);
} }

View File

@ -1,20 +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.model.dto.course.CourseQrcodeAddRequest;
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;
@ -22,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
@ -93,8 +74,8 @@ public class WechatGetQrcodeController {
@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 CourseQrcodeAddRequest courseQrcodeAddRequest) throws Exception { public BaseResponse<String> getCourseQrcode(@Valid @RequestBody CommonRequest commonRequest, HttpServletRequest request) throws Exception {
String view = wechatGetQrcodeService.getWxCourseQrCode(courseQrcodeAddRequest); String view = wechatGetQrcodeService.getWxCourseQrCode(commonRequest, request);
return ResultUtils.success(view); return ResultUtils.success(view);
} }

View File

@ -1,78 +0,0 @@
package com.greenorange.promotion.model.dto.course;
import com.greenorange.promotion.annotation.EnumValue;
import com.greenorange.promotion.model.enums.CourseTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 课程推广码生成请求体
*/
@Data
@Schema(description = "课程推广码生成请求体", requiredProperties = {
"id",
"name",
"type",
"image",
"originPrice",
"discountPrice",
"invitationCode"
})
public class CourseQrcodeAddRequest implements Serializable {
/**
* 课程ID
*/
@Min(value = 1L, message = "课程ID ID不能小于1")
@Schema(description = "课程ID", example = "1")
private Long id;
/**
* 课程名称
*/
@NotBlank(message = "课程名称不能为空")
@Schema(description = "课程名称", example = "数据分析工程师训练营")
private String name;
/**
* 课程类别[考公考研,自媒体,财经]
*/
@NotBlank(message = "课程类别不能为空")
@EnumValue(enumClass = CourseTypeEnum.class)
@Schema(description = "课程类别[考公考研,自媒体,财经]", example = "自媒体")
private String type;
/**
* 课程图片URL
*/
@NotBlank(message = "课程图片URL不能为空")
@Schema(description = "课程图片URL", example = "324IEHJDE")
private String image;
/**
* 课程原价
*/
@DecimalMin(value = "0.0", message = "课程原价不能小于0")
@Schema(description = "课程原价", example = "3499")
private BigDecimal originPrice;
/**
* 折扣价格
*/
@DecimalMin(value = "0.0", message = "折扣价格不能小于0")
@Schema(description = "折扣价格", example = "2499")
private BigDecimal discountPrice;
/**
* 邀请码
*/
@Schema(description = "邀请码", example = "666999")
@NotBlank(message = "邀请码不能为空")
private String invitationCode;
}

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

@ -6,6 +6,7 @@ import lombok.Data;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Date;
/** /**
* 课程订单 视图对象 * 课程订单 视图对象
@ -86,6 +87,18 @@ public class CourseOrderVO implements Serializable {
@Schema(description = "用户id", example = "1") @Schema(description = "用户id", example = "1")
private Long userId; 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 @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@ -2,10 +2,13 @@ package com.greenorange.promotion.service.course.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 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.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;
/** /**
@ -25,7 +28,13 @@ public class CourseOrderServiceImpl extends ServiceImpl<CourseOrderMapper, Cours
public QueryWrapper<CourseOrder> getQueryWrapper(CourseOrderQueryRequest courseOrderQueryRequest) { public QueryWrapper<CourseOrder> getQueryWrapper(CourseOrderQueryRequest courseOrderQueryRequest) {
String orderNumber = courseOrderQueryRequest.getOrderNumber(); String orderNumber = courseOrderQueryRequest.getOrderNumber();
String orderStatus = courseOrderQueryRequest.getOrderStatus(); String orderStatus = courseOrderQueryRequest.getOrderStatus();
return null; 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

@ -1,7 +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.course.CourseQrcodeAddRequest; import com.greenorange.promotion.model.dto.CommonRequest;
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException; import java.io.IOException;
@ -28,5 +29,5 @@ public interface WechatGetQrcodeService {
/** /**
* 微信小程序获取课程码 * 微信小程序获取课程码
*/ */
String getWxCourseQrCode(CourseQrcodeAddRequest courseQrcodeAddRequest) throws Exception; String getWxCourseQrCode(CommonRequest courseQrcodeAddRequest, HttpServletRequest request) throws Exception;
} }

View File

@ -14,13 +14,18 @@ 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.constant.SystemConstant;
import com.greenorange.promotion.exception.BusinessException; import com.greenorange.promotion.exception.BusinessException;
import com.greenorange.promotion.model.dto.course.CourseQrcodeAddRequest; import com.greenorange.promotion.model.dto.CommonRequest;
import com.greenorange.promotion.model.entity.Course;
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.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;
@ -33,7 +38,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;
@ -42,7 +46,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;
@ -65,10 +68,15 @@ 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 UserInfoService userInfoService;
@Resource
private CourseService courseService;
/** /**
* 获取接口调用凭据 * 获取接口调用凭据
@ -199,13 +207,23 @@ public class WechatGetQrcodeServiceImpl implements WechatGetQrcodeService {
*/ */
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public String getWxCourseQrCode(CourseQrcodeAddRequest courseQrcodeAddRequest) 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();
} }
String invitationCode = courseQrcodeAddRequest.getInvitationCode(); // 获取用户邀请码
Long id = courseQrcodeAddRequest.getId(); Long userId = (Long) request.getAttribute("userId");
UserInfo userInfo = userInfoService.getById(userId);
String invitationCode = userInfo.getInvitationCode();
// 获取课程信息
Long id = commonRequest.getId();
Course course = courseService.getById(id);
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=" + invitationCode + "&courseId=" + id); param.put("scene", "invitationCode=" + invitationCode + "&courseId=" + id);
@ -220,10 +238,7 @@ public class WechatGetQrcodeServiceImpl implements WechatGetQrcodeService {
.execute() .execute()
.bodyBytes(); .bodyBytes();
String courseTitle = courseQrcodeAddRequest.getName();
String originalPrice = String.valueOf(courseQrcodeAddRequest.getOriginPrice());
String discountPrice = String.valueOf(courseQrcodeAddRequest.getDiscountPrice());
String discountText = "元券后价";
String FontType = "Microsoft YaHei UI"; String FontType = "Microsoft YaHei UI";
int FontStyle = Font.PLAIN; int FontStyle = Font.PLAIN;
@ -232,7 +247,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 = SystemConstant.FILE_COMMON_PREFIX + courseQrcodeAddRequest.getImage(); 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();

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

@ -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) {