From 315c07aa4f70fa26143076f462ed0e6a44238bfa Mon Sep 17 00:00:00 2001 From: Pu Zhibing <393733352@qq.com> Date: 星期五, 28 二月 2025 14:32:30 +0800 Subject: [PATCH] Merge branch 'dev-1.2' of http://120.76.84.145:10101/gitblit/r/java/HongRuiTang --- ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/dto/XiaoeLiveDto.java | 69 + ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/miniapp/AppCourseController.java | 68 + ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/mapper/live/XiaoeLiveRecordMapper.java | 17 ruoyi-modules/ruoyi-goods/src/main/resources/mapper/live/XiaoeLiveAppointmentMapper.xml | 5 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeLiveTeacherVo.java | 23 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeLiveDetailVOV2.java | 181 ++++ ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/biz/XiaoeLiveService.java | 334 +++++++ ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/sys/SysUserController.java | 20 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeCourseGroupVO.java | 20 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeLiveVoV2.java | 182 ++++ ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeCourseChapterVO.java | 36 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/live/IXiaoeLiveAppointmentService.java | 22 ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/RemoteGoodsFallbackFactory.java | 5 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/concole/LiveController.java | 33 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/biz/XiaoeCourseService.java | 48 + ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/miniapp/AppLiveController.java | 54 + ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/domain/dto/MgtEditShopDto.java | 3 ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/constant/DelayTaskEnum.java | 1 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtLiveController.java | 90 ++ ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/live/XiaoeLiveAppointmentServiceImpl.java | 57 + ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/listener/RedisListener.java | 16 ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/domain/vo/MgtShopInfoVo.java | 3 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/business/MerLiveController.java | 112 ++ ruoyi-modules/ruoyi-goods/src/main/resources/mapper/live/XiaoeLiveRecordMapper.xml | 5 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/dto/XiaoeCourseQueryDto.java | 43 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/mapper/live/XiaoeLiveAppointmentMapper.java | 17 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeLiveVo.java | 112 ++ ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/utils/WeChatSubscribeMessageSender.java | 83 + ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/service/RemoteGoodsService.java | 10 ruoyi-modules/ruoyi-member/pom.xml | 11 ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/poji/shop/Shop.java | 6 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/live/XiaoeLiveRecordServiceImpl.java | 70 + ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/GeneratorMybatisPlus.java | 12 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/staff/StaffLiveController.java | 39 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/pojo/live/XiaoeLiveRecord.java | 64 + ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeCourseVO.java | 53 + ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/pojo/live/XiaoeLiveAppointment.java | 63 + ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/DateUtils.java | 11 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/business/MerCourseController.java | 68 + ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/dto/XiaoeLiveQueryDto.java | 41 ruoyi-common/ruoyi-common-core/pom.xml | 5 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/live/IXiaoeLiveRecordService.java | 41 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/utils/XiaoeUtils.java | 458 ++++++++++ 43 files changed, 2,601 insertions(+), 10 deletions(-) diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/constant/DelayTaskEnum.java b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/constant/DelayTaskEnum.java index d22b973..f9781f6 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/constant/DelayTaskEnum.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/constant/DelayTaskEnum.java @@ -14,6 +14,7 @@ COUPON_SEND_DELAY_TASK("优惠券延时任务","定时启动优惠券发送"), ACTIVITY_START_TASK("活动延时任务","定时开始任务"), ACTIVITY_END_TASK("活动延时任务","定时结束任务"), + LIVE_APPOINTMENT_TASK("直播预约任务","直播预约任务") ; String name; diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/poji/shop/Shop.java b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/poji/shop/Shop.java index 11230b8..92890a1 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/poji/shop/Shop.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/poji/shop/Shop.java @@ -292,6 +292,12 @@ @TableField("shop_code") private String shopCode; + /** + * 小鹅通讲师id + */ + @TableField("xiaoe_user_id") + private String xiaoeUserId; + @Override protected Serializable pkVal() { diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/RemoteGoodsFallbackFactory.java b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/RemoteGoodsFallbackFactory.java index 8513675..a5e8c61 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/RemoteGoodsFallbackFactory.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/RemoteGoodsFallbackFactory.java @@ -80,6 +80,11 @@ public R<List<String>> listGoodsNameByGoodsClass(Long classId) { return R.fail("获取分类商品列表失败:" + throwable.getMessage()); } + + @Override + public R<?> push(Long appointmentId) { + return R.fail("推送小程序订阅消息失败:" + throwable.getMessage()); + } }; } } diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/service/RemoteGoodsService.java b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/service/RemoteGoodsService.java index b82e6a5..0fca1fe 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/service/RemoteGoodsService.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/service/RemoteGoodsService.java @@ -11,6 +11,8 @@ import com.ruoyi.system.api.domain.vo.MerGoodsPriceListVo; import com.ruoyi.system.api.factory.RemoteGoodsFallbackFactory; import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -78,4 +80,12 @@ */ @PostMapping("/goods/listGoodsNameByGoodsClass") public R<List<String>> listGoodsNameByGoodsClass(@RequestBody Long classId); + + /** + * 推送微信小程序订阅消息 + * @param appointmentId + * @return + */ + @GetMapping("/live/push/{appointmentId}") + R<?> push(@PathVariable("appointmentId") Long appointmentId); } diff --git a/ruoyi-common/ruoyi-common-core/pom.xml b/ruoyi-common/ruoyi-common-core/pom.xml index ed4df6a..ad70db5 100644 --- a/ruoyi-common/ruoyi-common-core/pom.xml +++ b/ruoyi-common/ruoyi-common-core/pom.xml @@ -118,6 +118,11 @@ <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> + <dependency> + <groupId>cn.hutool</groupId> + <artifactId>hutool-all</artifactId> + <version>5.8.22</version> + </dependency> </dependencies> diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/DateUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/DateUtils.java index dee9fc5..71ea2c8 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/DateUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/DateUtils.java @@ -222,4 +222,15 @@ } return sb.toString(); } + + public static Date getTodayStartTime() { + // 获取今天的日期 + LocalDate today = LocalDate.now(); + + // 获取当天的开始时间(00:00:00) + LocalDateTime startOfDay = today.atStartOfDay(); + + // 转换为 Date 类型 + return Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant()); + } } diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/business/MerCourseController.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/business/MerCourseController.java new file mode 100644 index 0000000..931550f --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/business/MerCourseController.java @@ -0,0 +1,68 @@ +package com.ruoyi.goods.controller.business; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.common.core.domain.R; +import com.ruoyi.goods.domain.dto.XiaoeCourseQueryDto; +import com.ruoyi.goods.domain.vo.XiaoeCourseChapterVO; +import com.ruoyi.goods.domain.vo.XiaoeCourseGroupVO; +import com.ruoyi.goods.domain.vo.XiaoeCourseVO; +import com.ruoyi.goods.service.biz.XiaoeCourseService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +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 javax.validation.Valid; +import java.util.List; + +/** + * @author mitao + * @date 2025/1/10 + */ +@Api(tags = {"商户端海恒课程相关接口"}) +@Validated +@RestController +@RequestMapping("/mer/course") +@RequiredArgsConstructor +public class MerCourseController { + private final XiaoeCourseService xiaoeCourseService; + + /** + * 课程列表 + * @param dto + * @return + */ + @ApiOperation("课程列表") + @PostMapping("/page") + public R<Page<XiaoeCourseVO>> page(@Valid @RequestBody XiaoeCourseQueryDto dto) { + return R.ok(xiaoeCourseService.getCoursePageList(dto)); + } + + /** + * 课程章节详情 + * @param id + * @return + */ + @ApiOperation("课程章节详情") + @GetMapping("/detail/{id}") + public R<List<XiaoeCourseChapterVO>> detail(@ApiParam(name = "id",value = "课程id",required = true)@PathVariable("id") String id) { + return R.ok(xiaoeCourseService.getCourseDetail(id)); + } + + /** + * 获取课程分组列表 + * @return + */ + @ApiOperation("获取课程分组列表") + @GetMapping("/group") + public R<List<XiaoeCourseGroupVO>> getCourseGroupList() { + return R.ok(xiaoeCourseService.getCourseGroupList()); + } +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/business/MerLiveController.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/business/MerLiveController.java new file mode 100644 index 0000000..cb6fe5e --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/business/MerLiveController.java @@ -0,0 +1,112 @@ +package com.ruoyi.goods.controller.business; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.common.core.domain.R; +import com.ruoyi.goods.domain.dto.XiaoeLiveDto; +import com.ruoyi.goods.domain.dto.XiaoeLiveQueryDto; +import com.ruoyi.goods.domain.vo.XiaoeLiveDetailVOV2; +import com.ruoyi.goods.domain.vo.XiaoeLiveVo; +import com.ruoyi.goods.service.biz.XiaoeLiveService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +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 javax.validation.Valid; +import java.util.List; + +/** + * @author mitao + * @date 2025/1/9 + */ +@Validated +@RestController +@RequiredArgsConstructor +@Api(tags = "商户端直播相关接口") +@RequestMapping("/mer/live") +public class MerLiveController { + private final XiaoeLiveService xiaoeLiveService; + + /** + * 直播首页分页列表 + * @param dto + * @return + */ + @ApiOperation("直播首页分页列表") + @PostMapping("/page") + public R<Page<XiaoeLiveVo>> page(@Valid @RequestBody XiaoeLiveQueryDto dto) { + return R.ok(xiaoeLiveService.getLivePage(dto)); + } + + /** + * 直播详情 + * @param id + * @return + */ + @ApiOperation("直播详情") + @GetMapping("/detail/{id}") + public R<XiaoeLiveDetailVOV2> detail(@ApiParam(name = "id",value = "直播id", required = true) @PathVariable("id") String id) { + return R.ok(xiaoeLiveService.getLiveDetail(id)); + } + + /** + * 预约直播 + * @param id + * @return + */ + @ApiOperation("预约") + @GetMapping("/appointment/{id}") + public R<Boolean> appointment(@ApiParam(name = "id",value = "直播id", required = true) @PathVariable("id") String id) { + return R.ok(xiaoeLiveService.appointment(id)); + } + + /** + * 我的直播 + * @param dto + * @return + */ + @ApiOperation("我的直播") + @PostMapping("/mine") + public R<Page<XiaoeLiveVo>> minePage(@Valid @RequestBody XiaoeLiveQueryDto dto) { + return R.ok(xiaoeLiveService.getMineLivePage(dto)); + } + + /** + * 获取当前店铺讲师id列表/创建直播前校验讲师信息 + * @return + */ + @ApiOperation("获取当前店铺讲师id列表/创建直播前校验讲师信息") + @GetMapping("/xiaoe/ids") + public R<List<String>> getShopXiaoeUserIdList() { + return R.ok(xiaoeLiveService.getShopXiaoeUserIdList()); + } + /** + * 创建直播 + * @param dto + * @return + */ + @ApiOperation("创建直播") + @PostMapping("/create") + public R<?> create(@Valid @RequestBody XiaoeLiveDto dto) { + xiaoeLiveService.create(dto,2); + return R.ok(); + } + + /** + * 编辑直播 + * @param dto + * @return + */ + @ApiOperation("编辑直播") + @PostMapping + public R<Boolean> edit(@Valid @RequestBody XiaoeLiveDto dto) { + return R.ok(xiaoeLiveService.edit(dto)); + } +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/concole/LiveController.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/concole/LiveController.java new file mode 100644 index 0000000..73cda39 --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/concole/LiveController.java @@ -0,0 +1,33 @@ +package com.ruoyi.goods.controller.concole; + +import com.ruoyi.common.core.domain.R; +import com.ruoyi.goods.service.live.IXiaoeLiveAppointmentService; +import com.ruoyi.goods.utils.XiaoeUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author mitao + * @date 2025/1/10 + */ +@RestController +@RequestMapping("/live") +@RequiredArgsConstructor +public class LiveController { + private final XiaoeUtils xiaoeUtils; + private final IXiaoeLiveAppointmentService xiaoeLiveAppointmentService; + + /** + * 推送微信小程序订阅消息 + * @param appointmentId + * @return + */ + @GetMapping("/push/{appointmentId}") + public R<?> push(@PathVariable("appointmentId") Long appointmentId) { + xiaoeLiveAppointmentService.push(appointmentId); + return R.ok(); + } +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtLiveController.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtLiveController.java new file mode 100644 index 0000000..07530dd --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtLiveController.java @@ -0,0 +1,90 @@ +package com.ruoyi.goods.controller.management; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.common.core.domain.R; +import com.ruoyi.goods.domain.dto.XiaoeLiveDto; +import com.ruoyi.goods.domain.dto.XiaoeLiveQueryDto; +import com.ruoyi.goods.domain.vo.XiaoeLiveDetailVOV2; +import com.ruoyi.goods.domain.vo.XiaoeLiveVo; +import com.ruoyi.goods.service.biz.XiaoeLiveService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; + +/** + * @author mitao + * @date 2025/1/12 + */ +@Api(tags = {"管理后台直播相关接口"}) +@RestController +@RequestMapping("/mgt/live") +@RequiredArgsConstructor +public class MgtLiveController { + private final XiaoeLiveService xiaoeLiveService; + + /** + * 直播分页列表 + * @param dto + * @return + */ + @ApiOperation("直播分页列表") + @PostMapping("/page") + public R<Page<XiaoeLiveVo>> page(@Valid @RequestBody XiaoeLiveQueryDto dto) { + return R.ok(xiaoeLiveService.getMgtLivePage(dto)); + } + /** + * 直播详情 + * @param id + * @return + */ + @ApiOperation("直播详情") + @GetMapping("/detail/{id}") + public R<XiaoeLiveDetailVOV2> detail(@ApiParam(name = "id",value = "直播id", required = true) @PathVariable("id") String id) { + return R.ok(xiaoeLiveService.getLiveDetail(id)); + } + /** + * 创建直播 + * @param dto + * @return + */ + @ApiOperation("添加直播") + @PostMapping("/create") + public R<?> create(@Valid @RequestBody XiaoeLiveDto dto) { + xiaoeLiveService.create(dto,1); + return R.ok(); + } + + /** + * 编辑直播 + * @param dto + * @return + */ + @ApiOperation("编辑直播") + @PutMapping + public R<Boolean> edit(@Valid @RequestBody XiaoeLiveDto dto) { + return R.ok(xiaoeLiveService.edit(dto)); + } + + /** + * 删除直播 + * @param id + * @return + */ + @ApiOperation("删除") + @DeleteMapping("/{id}") + public R<?> delete(@ApiParam(name = "id",value = "直播id", required = true) @PathVariable("id") String id) { + xiaoeLiveService.deleteLive(id); + return R.ok(); + } +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/miniapp/AppCourseController.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/miniapp/AppCourseController.java new file mode 100644 index 0000000..d624487 --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/miniapp/AppCourseController.java @@ -0,0 +1,68 @@ +package com.ruoyi.goods.controller.miniapp; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.common.core.domain.R; +import com.ruoyi.goods.domain.dto.XiaoeCourseQueryDto; +import com.ruoyi.goods.domain.vo.XiaoeCourseChapterVO; +import com.ruoyi.goods.domain.vo.XiaoeCourseGroupVO; +import com.ruoyi.goods.domain.vo.XiaoeCourseVO; +import com.ruoyi.goods.service.biz.XiaoeCourseService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +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 javax.validation.Valid; +import java.util.List; + +/** + * @author mitao + * @date 2025/1/10 + */ +@Api(tags = {"小程序海恒课程相关接口"}) +@Validated +@RestController +@RequestMapping("/app/course") +@RequiredArgsConstructor +public class AppCourseController { + private final XiaoeCourseService xiaoeCourseService; + + /** + * 课程列表 + * @param dto + * @return + */ + @ApiOperation("课程列表") + @PostMapping("/page") + public R<Page<XiaoeCourseVO>> page(@Valid @RequestBody XiaoeCourseQueryDto dto) { + return R.ok(xiaoeCourseService.getCoursePageList(dto)); + } + + /** + * 课程章节详情 + * @param id + * @return + */ + @ApiOperation("课程章节详情") + @GetMapping("/detail/{id}") + public R<List<XiaoeCourseChapterVO>> detail(@ApiParam(name = "id",value = "课程id",required = true)@PathVariable("id") String id) { + return R.ok(xiaoeCourseService.getCourseDetail(id)); + } + + /** + * 获取课程分组列表 + * @return + */ + @ApiOperation("获取课程分组列表") + @GetMapping("/group") + public R<List<XiaoeCourseGroupVO>> getCourseGroupList() { + return R.ok(xiaoeCourseService.getCourseGroupList()); + } +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/miniapp/AppLiveController.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/miniapp/AppLiveController.java new file mode 100644 index 0000000..5c006fb --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/miniapp/AppLiveController.java @@ -0,0 +1,54 @@ +package com.ruoyi.goods.controller.miniapp; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.common.core.domain.R; +import com.ruoyi.goods.domain.dto.XiaoeLiveQueryDto; +import com.ruoyi.goods.domain.vo.XiaoeLiveVo; +import com.ruoyi.goods.service.biz.XiaoeLiveService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +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 javax.validation.Valid; + +/** + * @author mitao + * @date 2025/1/10 + */ +@Validated +@RestController +@RequiredArgsConstructor +@Api(tags = "小程序直播相关接口") +@RequestMapping("/app/live") +public class AppLiveController { + private final XiaoeLiveService xiaoeLiveService; + /** + * 直播首页分页列表 + * @param dto + * @return + */ + @ApiOperation("直播首页分页列表") + @PostMapping("/page") + public R<Page<XiaoeLiveVo>> page(@Valid @RequestBody XiaoeLiveQueryDto dto) { + return R.ok(xiaoeLiveService.getLivePage(dto)); + } + + /** + * 预约直播 + * @param id + * @return + */ + @ApiOperation("预约") + @GetMapping("/appointment/{id}") + public R<Boolean> appointment(@ApiParam(name = "id",value = "直播id", required = true) @PathVariable("id") String id) { + return R.ok(xiaoeLiveService.appointment(id)); + } +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/staff/StaffLiveController.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/staff/StaffLiveController.java new file mode 100644 index 0000000..ad947c4 --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/staff/StaffLiveController.java @@ -0,0 +1,39 @@ +package com.ruoyi.goods.controller.staff; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.common.core.domain.R; +import com.ruoyi.goods.domain.dto.XiaoeLiveQueryDto; +import com.ruoyi.goods.domain.vo.XiaoeLiveVo; +import com.ruoyi.goods.service.biz.XiaoeLiveService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +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 javax.validation.Valid; + +/** + * @author mitao + * @date 2025/1/15 + */ +@Api(tags = {"员工端直播相关接口"}) +@RestController +@RequestMapping("/staff/live") +@RequiredArgsConstructor +public class StaffLiveController { + private final XiaoeLiveService xiaoeLiveService; + + /** + * 员工端直播列表 + * @param dto + * @return + */ + @ApiOperation("直播列表") + @PostMapping("/page") + public R<Page<XiaoeLiveVo>> minePage(@Valid @RequestBody XiaoeLiveQueryDto dto) { + return R.ok(xiaoeLiveService.getStaffLivePage(dto)); + } +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/dto/XiaoeCourseQueryDto.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/dto/XiaoeCourseQueryDto.java new file mode 100644 index 0000000..ccb16f3 --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/dto/XiaoeCourseQueryDto.java @@ -0,0 +1,43 @@ +package com.ruoyi.goods.domain.dto; + +import com.alibaba.fastjson2.annotation.JSONField; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author mitao + * @date 2025/1/9 + */ +@Data +@ApiModel("小鹅通课程列表查询参数") +public class XiaoeCourseQueryDto { + + @ApiModelProperty(value = "课程名字模糊搜索") + @JSONField(name = "search_content") + private String searchContent; + + @ApiModelProperty(value = "课程创建来源 0:全部,1:课程,2:圈子") + @JSONField(name = "created_source") + private Integer createdSource; + + @ApiModelProperty("课程分组id数组") + @JSONField(name = "tags") + private List<Integer> tags; + + @ApiModelProperty(value = "当前页") + @JSONField(name = "page_index") + private Integer pageNo; + + @ApiModelProperty("每页条数") + @JSONField(name = "page_size") + private Integer pageSize; + + @ApiModelProperty("排序类型 1:创建时间倒序 2:开始时间升序") + @NotNull(message = "排序类型不能为空") + private Integer sortBy; + +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/dto/XiaoeLiveDto.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/dto/XiaoeLiveDto.java new file mode 100644 index 0000000..adf0891 --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/dto/XiaoeLiveDto.java @@ -0,0 +1,69 @@ +package com.ruoyi.goods.domain.dto; + +import com.alibaba.fastjson2.annotation.JSONField; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +@ApiModel(description = "资源信息") +@Data +public class XiaoeLiveDto { + + @ApiModelProperty(value = "直播id",notes = "添加不传,编辑必传") + @JSONField(name = "id") + private String id; + + @ApiModelProperty(value = "直播标题", required = true, notes = "字符长度必须小于45") + @NotBlank(message = "直播标题不能为空") + @JSONField(name = "title") + private String title; + + @ApiModelProperty(value = "直播简介", notes = "字符长度必须小于256,默认为空") + @NotBlank(message = "直播简介不能为空") + @Length(max = 256, message = "直播简介长度不能超过256") + @JSONField(name = "summary") + private String summary; + + @ApiModelProperty(value = "预设直播开始时间", required = true, notes = "距离当前时间不能超过五年", example = "2023-05-31 18:00:00") + @NotBlank(message = "预设直播开始时间不能为空") + @JSONField(name = "zb_start_at") + private String zbStartAt; + + @ApiModelProperty(value = "预设直播时长,单位:秒", required = true, notes = "距离预设直播开始时间不能超过十年") + @JSONField(name = "zb_stop_at") + private Integer zbStopAt; + + @ApiModelProperty(value = "直播类型 0-语音,1-录播直播,2-推流直播,默认为0-语音直播") + @NotNull(message = "直播类型不能为空") + @JSONField(name = "alive_type") + private Integer aliveType; + + @ApiModelProperty(value = "直播模式:0-横屏直播,1-竖屏直播(默认为0-横屏直播)", example = "0") + @NotNull(message = "直播模式不能为空") + @JSONField(name = "alive_mode") + private Integer aliveMode; + + @ApiModelProperty(value = "讲师用户id") + @NotBlank(message = "讲师用户id不能为空") + @JSONField(name = "user_id") + private String userId; + + @ApiModelProperty(value = "支付类型:1-免费,3-加密,仅当goods_info.sale_type=2时才可用", example = "1") + @NotNull(message = "直播类型不能为空") + @JSONField(name = "payment_type") + private Integer paymentType; + + @ApiModelProperty(value = "密码(paymentType为3时必填,否则该字段无效)") + @JSONField(name = "resource_password") + private String resourcePassword; + + @ApiModelProperty(value = "直播详情", notes = "仅允许纯文本,不得超过5000个字符,默认为空") + @NotBlank(message = "直播详情不能为空") + @Length(max = 5000, message = "直播详情长度不能超过5000") + @JSONField(name = "descrb") + private String descrb; +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/dto/XiaoeLiveQueryDto.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/dto/XiaoeLiveQueryDto.java new file mode 100644 index 0000000..c8d2a67 --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/dto/XiaoeLiveQueryDto.java @@ -0,0 +1,41 @@ +package com.ruoyi.goods.domain.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author mitao + * @date 2025/1/8 + */ +@Data +@ApiModel("直播分页查询参数") +public class XiaoeLiveQueryDto { + + @ApiModelProperty(value = "直播名称关键字") + private String searchContent; + + @ApiModelProperty(value = "直播课程类型 -1 全部;0 店铺课程; 1 转播课程;默认-1") + private Integer createMode; + + @ApiModelProperty(value = "直播商品状态 -1 全部; 0 已上架; 1 已下架;2 待上架;默认-1") + private Integer state; + + @ApiModelProperty(value = "直播模式:-1 全部;10 横屏直播;11竖屏直播;12语音直播;13录播直播;默认-1") + private Integer searchAliveType; + + @ApiModelProperty(value = "直播状态:-1全部;0未开始;1直播中;2已结束;默认-1") + private Integer alivePlayState; + + @ApiModelProperty(value = "页码,表示第几页,从1开始;默认1") + private Integer page; + + @ApiModelProperty(value = "每页条数,最大50条;默认10") + private Integer pageSize; + + @ApiModelProperty("门店id") + private Long shopId; + + @ApiModelProperty("直播类型 1:平台直播 2:商家直播") + private Integer liveType; +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/pojo/live/XiaoeLiveAppointment.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/pojo/live/XiaoeLiveAppointment.java new file mode 100644 index 0000000..540b53f --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/pojo/live/XiaoeLiveAppointment.java @@ -0,0 +1,63 @@ +package com.ruoyi.goods.domain.pojo.live; + +import com.baomidou.mybatisplus.annotation.FieldFill; +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 lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.Date; + +/** + * <p> + * 直播预约记录 + * </p> + * + * @author mitao + * @since 2025-01-09 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("t_xiaoe_live_appointment") +public class XiaoeLiveAppointment implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 直播id + */ + private String liveId; + + /** + * 预约人id + */ + private Long userId; + /** + * 直播开始时间 + */ + private Date aliveStartAt; + + /** + * 直播标题 + */ + private String title; + + /** + * 预约时间 + */ + @TableField(fill = FieldFill.INSERT) + private Date createTime; + + +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/pojo/live/XiaoeLiveRecord.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/pojo/live/XiaoeLiveRecord.java new file mode 100644 index 0000000..440c69a --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/pojo/live/XiaoeLiveRecord.java @@ -0,0 +1,64 @@ +package com.ruoyi.goods.domain.pojo.live; + +import com.baomidou.mybatisplus.annotation.FieldFill; +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 lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.Date; + +/** + * <p> + * 小鹅通直播添加记录表 + * </p> + * + * @author mitao + * @since 2025-01-09 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +@TableName("t_xiaoe_live_record") +public class XiaoeLiveRecord implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + /** + * 记录类型(1:平台 2:经销商) + */ + private Integer type; + + /** + * 直播id + */ + private String liveId; + + /** + * 店铺(仅记录类型为经销商时使用) + */ + private Long shopId; + + /** + * 店铺名称 + */ + private String shopName; + + /** + * 添加时间 + */ + @TableField(fill = FieldFill.INSERT) + private Date createTime; + + +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeCourseChapterVO.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeCourseChapterVO.java new file mode 100644 index 0000000..b764d0b --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeCourseChapterVO.java @@ -0,0 +1,36 @@ +package com.ruoyi.goods.domain.vo; + +import com.alibaba.fastjson2.annotation.JSONField; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * @author mitao + * @date 2025/1/9 + */ +@Data +@ApiModel("课程目录小节视图对象") +public class XiaoeCourseChapterVO { + @ApiModelProperty(value = "章节id") + @JSONField(name = "chapter_id") + private String chapterId; + + @ApiModelProperty(value = "章节名称") + @JSONField(name = "chapter_title") + private String chapterTitle; + + @ApiModelProperty(value = "章节类型 0-无 1-章 2-节") + @JSONField(name = "chapter_type") + private Integer chapterType; + + @ApiModelProperty(value = "关联资源的种类(1:图文,2:音频,3:视频,4:直播,20:电子书,45:AI互动课,34练习,27考试,51文档,15作业,13表单,14测试互动)") + @JSONField(name = "resource_type") + private Integer resourceType; + + @ApiModelProperty(value = "子章节集合") + @JSONField(name = "children") + private List<XiaoeCourseChapterVO> children; +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeCourseGroupVO.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeCourseGroupVO.java new file mode 100644 index 0000000..9817d41 --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeCourseGroupVO.java @@ -0,0 +1,20 @@ +package com.ruoyi.goods.domain.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author mitao + * @date 2025/1/9 + */ +@Data +@ApiModel("商品分组视图对象") +public class XiaoeCourseGroupVO { + + @ApiModelProperty("商品分组id") + private String id; + + @ApiModelProperty("商品分组名称") + private String name; +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeCourseVO.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeCourseVO.java new file mode 100644 index 0000000..cdb4edd --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeCourseVO.java @@ -0,0 +1,53 @@ +package com.ruoyi.goods.domain.vo; + +import com.alibaba.fastjson2.annotation.JSONField; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.Date; + +/** + * @author mitao + * @date 2025/1/9 + */ +@Data +@ApiModel("小鹅通课程视图对象") +public class XiaoeCourseVO { + @ApiModelProperty("课程id") + @JSONField(name = "resource_id") + private String resourceId; + + @ApiModelProperty("课程id") + @JSONField(name = "resource_type") + private Integer resourceType; + + @ApiModelProperty("课程名称") + @JSONField(name = "title") + private String title; + + @ApiModelProperty("课程封面") + @JSONField(name = "img_url") + private String imgUrl; + + @ApiModelProperty("用户数") + @JSONField(name = "user_count") + private Integer userCount; + + @ApiModelProperty("内容数") + @JSONField(name = "resource_cnt") + private Integer resourceCnt; + + @ApiModelProperty("开课时间") + @JSONField(name = "curriculum_time") + private Date curriculumTime; + + @ApiModelProperty("更新时间") + @JSONField(name = "last_updated_at") + private Date lastUpdatedAt; + + @ApiModelProperty("开课结束时间") + @JSONField(name = "curriculum_end_time") + private Date curriculumEndTime; + +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeLiveDetailVOV2.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeLiveDetailVOV2.java new file mode 100644 index 0000000..5d58758 --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeLiveDetailVOV2.java @@ -0,0 +1,181 @@ +package com.ruoyi.goods.domain.vo; + +import com.alibaba.fastjson2.annotation.JSONField; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * @author mitao + * @date 2025/1/14 + */ +@Data +@ApiModel("直播详情2.0视图对象") +public class XiaoeLiveDetailVOV2 { + @ApiModelProperty(value = "资源信息") + @JSONField(name = "resource_info") + private ResourceInfo resourceInfo; + @ApiModelProperty(value = "配置信息") + @JSONField(name = "module_info") + private ModuleInfo moduleInfo; + @ApiModelProperty(value = "商品信息") + @JSONField(name = "goods_info") + private GoodsInfo goodsInfo; + @ApiModelProperty(value = "关联信息") + @JSONField(name = "relation_info") + private RelationInfo relationInfo; + @ApiModelProperty(value = "讲师信息") + @JSONField(name = "role_info") + private List<RelationInfo.RoleInfo> roleInfo; + + @Data + @ApiModel(description = "资源信息") + public static class ResourceInfo { + @ApiModelProperty(value = "店铺id", example = "app_id") + @JSONField(name = "app_id") + private String appId; + @ApiModelProperty(value = "直播ID", example = "id") + @JSONField(name = "id") + private String id; + @ApiModelProperty(value = "直播标题", example = "title") + @JSONField(name = "title") + private String title; + @ApiModelProperty(value = "直播简介", example = "summary") + @JSONField(name = "summary") + private String summary; + @ApiModelProperty(value = "直播详情(仅允许纯文本)", example = "descrb") + @JSONField(name = "descrb") + private String descrb; + @ApiModelProperty(value = "直播类型:0-语音,1-录播直播,2-推流直播", example = "2") + @JSONField(name = "alive_type") + private Integer aliveType; + @ApiModelProperty(value = "预设直播开始时间", example = "2023-05-31 18:00:00") + @JSONField(name = "zb_start_at") + private String zbStartAt; + @ApiModelProperty(value = "预设直播时长,单位:秒", example = "3600") + @JSONField(name = "zb_stop_at") + private Integer zbStopAt; + @ApiModelProperty(value = "详情封面图素材ID", example = "img_material_id") + @JSONField(name = "img_material_id") + private String imgMaterialId; + @ApiModelProperty(value = "宣传封面图素材ID", example = "alive_img_material_id") + @JSONField(name = "alive_img_material_id") + private String aliveImgMaterialId; + @ApiModelProperty(value = "暖场封面图素材ID", example = "aliveroom_img_material_id") + @JSONField(name = "aliveroom_img_material_id") + private String aliveroomImgMaterialId; + @ApiModelProperty(value = "暖场视频封面图素材ID", example = "warm_up_video_cover_material_id") + @JSONField(name = "warm_up_video_cover_material_id") + private String warmUpVideoCoverMaterialId; + @ApiModelProperty(value = "暖场视频素材ID", example = "warm_up_video_material_id") + @JSONField(name = "warm_up_video_material_id") + private String warmUpVideoMaterialId; + @ApiModelProperty(value = "录播视频素材ID", example = "alive_video_material_id") + @JSONField(name = "alive_video_material_id") + private String aliveVideoMaterialId; + + } + + @Data + @ApiModel(description = "配置信息") + public static class ModuleInfo { + @ApiModelProperty(value = "是否开启回放:0-开启,1-关闭", example = "0") + @JSONField(name = "is_lookback") + private Integer isLookback; + @ApiModelProperty(value = "回放是否允许倍速播放或快进:0-允许,1-禁止", example = "0") + @JSONField(name = "play_fast_state_switch") + private Integer playFastStateSwitch; + @ApiModelProperty(value = "直播模式:0-横屏直播,1-竖屏直播", example = "0") + @JSONField(name = "alive_mode") + private Integer aliveMode; + @ApiModelProperty(value = "回放有效期设置:1-永久,2-限时", example = "1") + @JSONField(name = "expire_type") + private Integer expireType; + @ApiModelProperty(value = "回放过期时间", example = "2023-06-30") + @JSONField(name = "expire") + private String expire; + @ApiModelProperty(value = "暖场设置:1-暖场图,2-暖场视频", example = "1") + @JSONField(name = "warm_up") + private Integer warmUp; + @ApiModelProperty(value = "是否开启完成条件:0-关闭,1-开启", example = "0") + @JSONField(name = "is_open_complete_time") + private Integer isOpenCompleteTime; + @ApiModelProperty(value = "设置最短学习时间(单位:分钟)", example = "0") + @JSONField(name = "complete_time") + private Integer completeTime; + @ApiModelProperty(value = "是否开启联系学员:0-关闭,1-开启", example = "0") + @JSONField(name = "is_contact_on") + private Integer isContactOn; + } + + @Data + @ApiModel(description = "商品信息") + public static class GoodsInfo { + @ApiModelProperty(value = "售卖类型:1-单独售卖、2-关联售卖", example = "1") + @JSONField(name = "sale_type") + private Integer saleType; + @ApiModelProperty(value = "支付类型:1-免费,2-收费,3-加密,4-指定学员可用,5-仅关联上级资源", example = "1") + @JSONField(name = "payment_type") + private Integer paymentType; + @ApiModelProperty(value = "价格(单位:分)", example = "0") + @JSONField(name = "piece_price") + private Integer piecePrice; + @ApiModelProperty(value = "划线价格(单位:分)", example = "0") + @JSONField(name = "line_price") + private Integer linePrice; + @ApiModelProperty(value = "密码", example = "resource_password") + @JSONField(name = "resource_password") + private String resourcePassword; + @ApiModelProperty(value = "上下架:1-下架,0-上架", example = "0") + @JSONField(name = "recycle_bin_state") + private Integer recycleBinState; + @ApiModelProperty(value = "定时上架时间", example = "2023-05-31 17:19:26") + @JSONField(name = "start_at") + private String startAt; + @ApiModelProperty(value = "是否停售:0-否,1-是", example = "0") + @JSONField(name = "is_stop_sell") + private Integer isStopSell; + @ApiModelProperty(value = "商品编码", example = "goods_sn") + @JSONField(name = "goods_sn") + private String goodsSn; + @ApiModelProperty(value = "商品状态:0-可见,1-隐藏,2-删除", example = "0") + @JSONField(name = "state") + private Integer state; + } + + @Data + @ApiModel(description = "关联信息") + public static class RelationInfo { + @ApiModelProperty(value = "资源id") + @JSONField(name = "package") + private List<String> packageIds; + @ApiModelProperty(value = "预留字段,暂未支持") + @JSONField(name = "attach_goods") + private List<String> attachGoods; + @ApiModelProperty(value = "预留字段,暂未支持") + @JSONField(name = "tags") + private List<String> tags; + + @Data + @ApiModel(description = "讲师信息列表") + public static class RoleInfo { + @ApiModelProperty(value = "自定义身份标签", example = "讲师") + @JSONField(name = "role_name") + private String roleName; + @ApiModelProperty(value = "用户id", example = "u_6688888888889999999") + @JSONField(name = "user_id") + private String userId; + @ApiModelProperty(value = "用户昵称", example = "测试") + @JSONField(name = "nickname") + private String nickname; + @ApiModelProperty(value = "用户头像", example = "avator") + @JSONField(name = "avator") + private String avator; + @ApiModelProperty(value = "是否接受打赏:1-接受打赏,0-不接受打赏", example = "1") + @JSONField(name = "is_can_exceptional") + private Integer isCanExceptional; + } + } +} \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeLiveTeacherVo.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeLiveTeacherVo.java new file mode 100644 index 0000000..bc81487 --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeLiveTeacherVo.java @@ -0,0 +1,23 @@ +package com.ruoyi.goods.domain.vo; + +import com.alibaba.fastjson2.annotation.JSONField; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@ApiModel(description = "讲师信息") +@Data +public class XiaoeLiveTeacherVo { + + @ApiModelProperty(value = "讲师ID") + @JSONField(name = "user_id") + private String userId; // 讲师ID + + @ApiModelProperty(value = "讲师昵称") + @JSONField(name = "user_name") + private String userName; // 讲师昵称 + + @ApiModelProperty(value = "讲师绑定手机号") + @JSONField(name = "phone") + private String phone; // 讲师绑定手机号 +} \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeLiveVo.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeLiveVo.java new file mode 100644 index 0000000..bc529de --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeLiveVo.java @@ -0,0 +1,112 @@ +package com.ruoyi.goods.domain.vo; + +import com.alibaba.fastjson2.annotation.JSONField; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * @author mitao + * @date 2025/1/8 + */ +@Data +@ApiModel("小鹅通直播视图对象") +public class XiaoeLiveVo { + + @ApiModelProperty(value = "直播ID") + @JSONField(name = "id") + private String id; // 直播ID + + @ApiModelProperty(value = "直播手动结束时间") + @JSONField(name = "alive_manual_stop_at") + private String aliveManualStopAt; // 直播手动结束时间 + + @ApiModelProperty(value = "直播结束时间") + @JSONField(name = "alive_stop_at") + private String aliveStopAt; // 直播结束时间 + + @ApiModelProperty(value = "直播名称") + @JSONField(name = "title") + private String title; // 直播名称 + + @ApiModelProperty(value = "直播观看人次,每5分钟同步一次数据") + @JSONField(name = "view_count") + private Integer viewCount; // 直播观看人次 + + @ApiModelProperty(value = "直播类型:10 横屏直播;11竖屏直播;12语音直播;13录播直播") + @JSONField(name = "alive_type") + private Integer aliveType; // 直播类型 + + @ApiModelProperty(value = "订阅量") + @JSONField(name = "purchase_count") + private Integer purchaseCount; // 订阅量 + + @ApiModelProperty(value = "打赏金额(元)") + @JSONField(name = "reward_sum") + private String rewardSum; // 打赏金额(元) + + @ApiModelProperty(value = "直播商品状态:-1 全部; 0 已上架; 1 已下架;2 待上架") + @JSONField(name = "recycle_bin_state") + private Integer recycleBinState; // 直播商品状态 + + @ApiModelProperty(value = "直播开始时间") + @JSONField(name = "alive_start_at") + private String aliveStartAt; // 直播开始时间 + + @ApiModelProperty(value = "直播状态:-1全部;0未开始;1直播中;2已结束") + @JSONField(name = "alive_state") + private Integer aliveState; // 直播状态 + + @ApiModelProperty(value = "直播显隐状态:0-显示,1-隐藏") + @JSONField(name = "resource_state") + private Integer resourceState; // 直播显隐状态 + + @ApiModelProperty(value = "店铺直播详情页地址") + @JSONField(name = "page_url") + private String pageUrl; // 店铺直播详情页地址 + + @ApiModelProperty(value = "直播课程类型:-1 全部;0 店铺课程; 1 转播课程") + @JSONField(name = "create_mode") + private Integer createMode; // 直播课程类型 + + @ApiModelProperty(value = "封面地址") + @JSONField(name = "img_url") + private String imgUrl; // 封面地址 + + @ApiModelProperty(value = "直播宣传图地址") + @JSONField(name = "alive_img_url") + private String aliveImgUrl; // 直播宣传图地址 + + @ApiModelProperty(value = "讲师列表") + @JSONField(name = "guest_list") + private List<XiaoeLiveTeacherVo> guestList; + + @ApiModelProperty("评论数") + @JSONField(name = "comment_count") + private Integer commentCount; + + @ApiModelProperty("评论用户数") + @JSONField(name = "comment_user_count") + private Integer commentUserCount; + + @ApiModelProperty("打赏次数") + @JSONField(name = "reward_count") + private Integer rewardCount; + + @ApiModelProperty("打赏人数") + @JSONField(name = "reward_user_count") + private Integer rewardUserCount; + + @ApiModelProperty("直播简介") + @JSONField(name = "summary") + private String summary; + + @ApiModelProperty("预约状态 1:已预约 0:未预约") + private Integer appointmentState=0; + + @ApiModelProperty("创建门店") + private String shopName; + +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeLiveVoV2.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeLiveVoV2.java new file mode 100644 index 0000000..6b8a1c4 --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/domain/vo/XiaoeLiveVoV2.java @@ -0,0 +1,182 @@ +package com.ruoyi.goods.domain.vo; + +import lombok.Data; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import com.alibaba.fastjson2.annotation.JSONField; + +@Data +@ApiModel(description = "小鹅通直播视图对象2.0") +public class XiaoeLiveVoV2 { + + @ApiModelProperty(value = "店铺ID", example = "app_id") + @JSONField(name = "app_id") + private String appId; + + @ApiModelProperty(value = "直播ID", example = "id") + @JSONField(name = "id") + private String id; + + @ApiModelProperty(value = "房间ID", example = "room_id") + @JSONField(name = "room_id") + private String roomId; + + @ApiModelProperty(value = "直播标题", example = "title") + @JSONField(name = "title") + private String title; + + @ApiModelProperty(value = "直播封面图", example = "img_url") + @JSONField(name = "img_url") + private String imgUrl; + + @ApiModelProperty(value = "页面url", example = "page_url") + @JSONField(name = "page_url") + private String pageUrl; + + @ApiModelProperty(value = "封面压缩后的路径", example = "img_url_compressed") + @JSONField(name = "img_url_compressed") + private String imgUrlCompressed; + + @ApiModelProperty(value = "评论数量", example = "comment_count") + @JSONField(name = "comment_count") + private Integer commentCount; + + @ApiModelProperty(value = "带货开关:1=开,0=关", example = "1") + @JSONField(name = "is_takegoods") + private Integer isTakegoods; + + @ApiModelProperty(value = "带货商品分组ID", example = "takegoods") + @JSONField(name = "takegoods") + private String takegoods; + + @ApiModelProperty(value = "付费类型:1-免费、2-单笔、3-付费产品包", example = "1") + @JSONField(name = "payment_type") + private Integer paymentType; + + @ApiModelProperty(value = "是否公开售卖,1公开,0不公开", example = "1") + @JSONField(name = "is_public") + private Integer isPublic; + + @ApiModelProperty(value = "是否停售,0-否、1-是", example = "0") + @JSONField(name = "is_stop_sell") + private Integer isStopSell; + + @ApiModelProperty(value = "视频是否转码,0-表示未转码,1-表示已转码,2-转码失败", example = "0") + @JSONField(name = "is_transcode") + private Integer isTranscode; + + @ApiModelProperty(value = "payment_type为2时,单笔价格(分);payment_type为3时,专栏价格(分)", example = "0") + @JSONField(name = "piece_price") + private Integer piecePrice; + + @ApiModelProperty(value = "划线价", example = "0") + @JSONField(name = "line_price") + private Integer linePrice; + + @ApiModelProperty(value = "该资源是否需要密码", example = "0") + @JSONField(name = "have_password") + private Integer havePassword; + + @ApiModelProperty(value = "直播类型:0-语音直播,1-视频直播,2-推流直播,3-ppt直播", example = "1") + @JSONField(name = "alive_type") + private Integer aliveType; + + @ApiModelProperty(value = "订阅量", example = "0") + @JSONField(name = "purchase_count") + private Integer purchaseCount; + + @ApiModelProperty(value = "打赏金额", example = "0") + @JSONField(name = "reward_sum") + private Integer rewardSum; + + @ApiModelProperty(value = "强制封禁:0-否 1-是", example = "0") + @JSONField(name = "is_ban") + private Integer isBan; + + @ApiModelProperty(value = "强制下架:0-否 1-是", example = "0") + @JSONField(name = "on_shelf") + private Integer onShelf; + + @ApiModelProperty(value = "上下架状态:0-上架,1-下架", example = "0") + @JSONField(name = "recycle_bin_state") + private Integer recycleBinState; + + @ApiModelProperty(value = "推流状态,0断流,1推流中,2推流未开始", example = "0") + @JSONField(name = "push_state") + private Integer pushState; + + @ApiModelProperty(value = "直播状态:0-可见,1-关闭,2-删除", example = "0") + @JSONField(name = "state") + private Integer state; + + @ApiModelProperty(value = "上架时间", example = "2023-05-31 17:19:26") + @JSONField(name = "start_at") + private String startAt; + + @ApiModelProperty(value = "直播开始时间", example = "2023-05-31 17:19:26") + @JSONField(name = "zb_start_at") + private String zbStartAt; + + @ApiModelProperty(value = "手动结束直播时间", example = "2023-05-31 17:19:26") + @JSONField(name = "manual_stop_at") + private String manualStopAt; + + @ApiModelProperty(value = "转播店铺名称", example = "source_shop_name") + @JSONField(name = "source_shop_name") + private String sourceShopName; + + @ApiModelProperty(value = "素材状态", example = "0") + @JSONField(name = "material_state") + private Integer materialState; + + @ApiModelProperty(value = "视频时长(s)", example = "0") + @JSONField(name = "video_length") + private Integer videoLength; + + @ApiModelProperty(value = "直播状态", example = "0") + @JSONField(name = "alive_state") + private Integer aliveState; + + @ApiModelProperty(value = "直播模式:0.无;1竖屏直播", example = "0") + @JSONField(name = "alive_mode") + private Integer aliveMode; + + @ApiModelProperty(value = "创建类型:0-自创建,1-转播创建", example = "0") + @JSONField(name = "create_mode") + private Integer createMode; + + @ApiModelProperty(value = "圆桌会议功能是否开启", example = "0") + @JSONField(name = "is_round_table_on") + private Integer isRoundTableOn; + + @ApiModelProperty(value = "关联商品", example = "query_package_list") + @JSONField(name = "query_package_list") + private String queryPackageList; + + @ApiModelProperty(value = "售卖有效期", example = "course_expire") + @JSONField(name = "course_expire") + private CourseExpire courseExpire; + + @ApiModelProperty("预约状态 1:已预约 0:未预约") + private Integer appointmentState=0; + + @ApiModelProperty("创建门店") + private String shopName; + + @Data + @ApiModel(description = "Course Expire Information") + public static class CourseExpire { + + @ApiModelProperty(value = "有效期类型:0=永久有效,1=固定有效期,2=自定义有效期", example = "0") + @JSONField(name = "period_type") + private Integer periodType; + + @ApiModelProperty(value = "自定义有效时长", example = "period_value") + @JSONField(name = "period_value") + private String periodValue; + + @ApiModelProperty(value = "是否允许重复购买:1=是,0=否", example = "0") + @JSONField(name = "is_allow_repeat_purchase") + private Integer isAllowRepeatPurchase; + } +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/mapper/live/XiaoeLiveAppointmentMapper.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/mapper/live/XiaoeLiveAppointmentMapper.java new file mode 100644 index 0000000..bf98aec --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/mapper/live/XiaoeLiveAppointmentMapper.java @@ -0,0 +1,17 @@ +package com.ruoyi.goods.mapper.live; + + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.goods.domain.pojo.live.XiaoeLiveAppointment; + +/** + * <p> + * 直播预约记录 Mapper 接口 + * </p> + * + * @author mitao + * @since 2025-01-09 + */ +public interface XiaoeLiveAppointmentMapper extends BaseMapper<XiaoeLiveAppointment> { + +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/mapper/live/XiaoeLiveRecordMapper.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/mapper/live/XiaoeLiveRecordMapper.java new file mode 100644 index 0000000..60fbd6d --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/mapper/live/XiaoeLiveRecordMapper.java @@ -0,0 +1,17 @@ +package com.ruoyi.goods.mapper.live; + + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.goods.domain.pojo.live.XiaoeLiveRecord; + +/** + * <p> + * 小鹅通直播添加记录表 Mapper 接口 + * </p> + * + * @author mitao + * @since 2025-01-09 + */ +public interface XiaoeLiveRecordMapper extends BaseMapper<XiaoeLiveRecord> { + +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/biz/XiaoeCourseService.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/biz/XiaoeCourseService.java new file mode 100644 index 0000000..87b8e5b --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/biz/XiaoeCourseService.java @@ -0,0 +1,48 @@ +package com.ruoyi.goods.service.biz; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.goods.domain.dto.XiaoeCourseQueryDto; +import com.ruoyi.goods.domain.vo.XiaoeCourseChapterVO; +import com.ruoyi.goods.domain.vo.XiaoeCourseGroupVO; +import com.ruoyi.goods.domain.vo.XiaoeCourseVO; +import com.ruoyi.goods.utils.XiaoeUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author mitao + * @date 2025/1/10 + */ +@Service +@RequiredArgsConstructor +public class XiaoeCourseService { + private final XiaoeUtils xiaoeUtils; + + /** + * 课程列表 + * @param dto + * @return + */ + public Page<XiaoeCourseVO> getCoursePageList(XiaoeCourseQueryDto dto) { + return xiaoeUtils.getCoursePageList(dto); + } + + /** + * 获取课程章节详情 + * @param id + * @return + */ + public List<XiaoeCourseChapterVO> getCourseDetail(String id) { + return xiaoeUtils.getCourseChapterDetail(id); + } + + /** + * 获取课程分组列表 + * @return + */ + public List<XiaoeCourseGroupVO> getCourseGroupList() { + return xiaoeUtils.getCourseGroupList(); + } +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/biz/XiaoeLiveService.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/biz/XiaoeLiveService.java new file mode 100644 index 0000000..708299f --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/biz/XiaoeLiveService.java @@ -0,0 +1,334 @@ +package com.ruoyi.goods.service.biz; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.common.core.exception.ServiceException; +import com.ruoyi.common.core.utils.DateUtils; +import com.ruoyi.common.core.utils.StringUtils; +import com.ruoyi.common.redis.service.RedisService; +import com.ruoyi.common.security.utils.SecurityUtils; +import com.ruoyi.goods.domain.dto.XiaoeLiveDto; +import com.ruoyi.goods.domain.dto.XiaoeLiveQueryDto; +import com.ruoyi.goods.domain.pojo.live.XiaoeLiveAppointment; +import com.ruoyi.goods.domain.pojo.live.XiaoeLiveRecord; +import com.ruoyi.goods.domain.vo.XiaoeLiveDetailVOV2; +import com.ruoyi.goods.domain.vo.XiaoeLiveVo; +import com.ruoyi.goods.service.live.IXiaoeLiveAppointmentService; +import com.ruoyi.goods.service.live.IXiaoeLiveRecordService; +import com.ruoyi.goods.utils.XiaoeUtils; +import com.ruoyi.system.api.constant.DelayTaskEnum; +import com.ruoyi.system.api.domain.poji.config.DelayTask; +import com.ruoyi.system.api.domain.poji.shop.Shop; +import com.ruoyi.system.api.domain.poji.sys.SysUser; +import com.ruoyi.system.api.domain.vo.ShopRelUserVo; +import com.ruoyi.system.api.service.RemoteConfigService; +import com.ruoyi.system.api.service.RemoteShopService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +/** + * @author mitao + * @date 2025/1/9 + */ +@Service +@RequiredArgsConstructor +public class XiaoeLiveService { + private final IXiaoeLiveRecordService xiaoeLiveRecordService; + private final XiaoeUtils xiaoeUtils; + private final IXiaoeLiveAppointmentService xiaoeLiveAppointmentService; + private final RedisService redisService; + private final RemoteConfigService remoteConfigService; + private final RemoteShopService remoteShopService; + + + /** + * 直播首页分页列表 + * @param dto + * @return + */ + public Page<XiaoeLiveVo> getLivePage(XiaoeLiveQueryDto dto) { + //当前登录用户id + Long userId = SecurityUtils.getUserId(); + Page<XiaoeLiveVo> livePageList = xiaoeUtils.getLivePageList(dto); + if (CollectionUtil.isEmpty(livePageList.getRecords())) { + return new Page<>(); + } + //已预约的记录 + List<XiaoeLiveAppointment> appointments = xiaoeLiveAppointmentService.lambdaQuery() + .gt(XiaoeLiveAppointment::getAliveStartAt, DateUtils.getNowDate()).eq(XiaoeLiveAppointment::getUserId, userId).list(); + Map<String, XiaoeLiveAppointment> appointmentMap = appointments.stream().collect(Collectors.toMap(XiaoeLiveAppointment::getLiveId, appointment -> appointment)); + // 处理直播数据 + List<XiaoeLiveVo> filteredRecords = livePageList.getRecords().stream() + .filter(item -> !item.getAliveState().equals(2)) // 过滤直播状态为已结束的记录 + .peek(item -> { + // 查找对应的预约记录 + XiaoeLiveAppointment appointment = appointmentMap.get(item.getId()); + + // 如果预约记录存在且直播状态为未开始,则设置状态为已预约 + if (item.getAliveState().equals(0) && appointment != null) { + item.setAppointmentState(1); // 设置为已预约 + } + }) + .sorted(Comparator.comparing(XiaoeLiveVo::getAliveState).reversed()) // 按照直播状态排序 + .collect(Collectors.toList()); + //根据直播类型过滤平台和店铺直播 + if (Objects.nonNull(dto.getLiveType())) { + List<XiaoeLiveRecord> liveRecordList = xiaoeLiveRecordService.lambdaQuery().eq(XiaoeLiveRecord::getType, dto.getLiveType()).list(); + if (CollUtil.isEmpty(liveRecordList)) { + return new Page<>(); + } + List<String> liveIdList = liveRecordList.stream().map(XiaoeLiveRecord::getLiveId).collect(Collectors.toList()); + filteredRecords = filteredRecords.stream().filter(item -> liveIdList.contains(item.getId())).collect(Collectors.toList()); + } + + livePageList.setRecords(filteredRecords); + return livePageList; + } + + /** + * 直播详情 + * @param id + * @return + */ + public XiaoeLiveDetailVOV2 getLiveDetail(String id) { + return xiaoeUtils.getLiveDetailV2(id); + } + /** + * 预约直播 + * @param id + * @return + */ + public Boolean appointment(String id) { + //当前登录用户 + SysUser sysUser = SecurityUtils.getSysUser(); + Long userId = sysUser.getUserId(); + //查询预约记录 + Integer count = xiaoeLiveAppointmentService.lambdaQuery().eq(XiaoeLiveAppointment::getLiveId, id).gt(XiaoeLiveAppointment::getAliveStartAt, DateUtils.getNowDate()).eq(XiaoeLiveAppointment::getUserId, userId).count(); + if (count > 0) { + throw new ServiceException("您已预约过该直播,请勿重复预约"); + } + XiaoeLiveVo liveDetail = xiaoeUtils.getLiveDetail(id); + if (Objects.isNull(liveDetail)) { + throw new ServiceException("直播不存在"); + } + XiaoeLiveAppointment xiaoeLiveAppointment = new XiaoeLiveAppointment(); + xiaoeLiveAppointment.setLiveId(id); + xiaoeLiveAppointment.setUserId(userId); + Date aliveStartAt = DateUtil.parse(liveDetail.getAliveStartAt(), DatePattern.NORM_DATETIME_PATTERN); + xiaoeLiveAppointment.setAliveStartAt(aliveStartAt); + xiaoeLiveAppointment.setCreateTime(DateUtils.getNowDate()); + xiaoeLiveAppointment.setTitle(liveDetail.getTitle()); + xiaoeLiveAppointmentService.save(xiaoeLiveAppointment); + /// 若为C端用户向 redis 添加预约记录 + if (sysUser.getUserType().equals("03")) { + // 获取当前时间 + Date nowTime = new Date(); + + // 计算直播开始时间与当前时间的差值 + long startTimeDifference = aliveStartAt.getTime() - nowTime.getTime(); + startTimeDifference = Math.max(startTimeDifference, 3000L); // 确保差值至少为3秒 + + // 获取延时任务 + DelayTask startDelayTask = remoteConfigService.getDelayTask(DelayTaskEnum.LIVE_APPOINTMENT_TASK.getCode() + "-" + xiaoeLiveAppointment.getId()).getData(); + // 创建或者更新延时任务 + if (startDelayTask == null || !startDelayTask.getEndTime().equals(aliveStartAt)) { + // 删除旧的延时任务及缓存 + if (startDelayTask != null) { + remoteConfigService.deleteDelayTask(DelayTaskEnum.LIVE_APPOINTMENT_TASK.getCode() + "-" + xiaoeLiveAppointment.getId()); + redisService.deleteObject(DelayTaskEnum.LIVE_APPOINTMENT_TASK.getCode() + "-" + xiaoeLiveAppointment.getId()); + } + // 设置新的延时任务 + redisService.setCacheObject(DelayTaskEnum.LIVE_APPOINTMENT_TASK.getCode() + "-" + xiaoeLiveAppointment.getId(), aliveStartAt, startTimeDifference, TimeUnit.MILLISECONDS); + startDelayTask = new DelayTask(); + startDelayTask.setDelFlag(0); + startDelayTask.setCreateTime(new Date()); + startDelayTask.setEndTime(aliveStartAt); + startDelayTask.setRedisKey(DelayTaskEnum.LIVE_APPOINTMENT_TASK.getCode() + "-" + xiaoeLiveAppointment.getId()); + + // 添加新的延时任务 + remoteConfigService.addDelayTask(startDelayTask); + } + } + return true; + } + + /** + * 我的直播 + * @param dto + * @return + */ + public Page<XiaoeLiveVo> getMineLivePage(XiaoeLiveQueryDto dto) { + Long userId = SecurityUtils.getUserId(); + Page<XiaoeLiveVo> page = new Page<>(); + ShopRelUserVo shopRelUserVo = remoteShopService.getShopByUserId(userId).getData(); + if (Objects.isNull(shopRelUserVo)) { + return page; + } + List<XiaoeLiveRecord> xiaoeLiveRecordList = xiaoeLiveRecordService.getListByShopId(shopRelUserVo.getShopId()); + if (CollectionUtil.isEmpty(xiaoeLiveRecordList)) { + return page; + } + Page<XiaoeLiveVo> livePageList = xiaoeUtils.getLivePageList(dto); + if (CollectionUtil.isEmpty(livePageList.getRecords())) { + return page; + } + //当前商家创建的直播 + Set<String> liveIdSet = xiaoeLiveRecordList.stream().map(XiaoeLiveRecord::getLiveId).collect(Collectors.toSet()); + //过滤数据 + List<XiaoeLiveVo> filteredRecords = livePageList.getRecords().stream() + .filter(item -> liveIdSet.contains(item.getId()) && !item.getAliveState().equals(2)) + // 按照直播状态排序 + .sorted(Comparator.comparing(XiaoeLiveVo::getAliveState).reversed()).collect(Collectors.toList()); + livePageList.setRecords(filteredRecords); + return livePageList; + } + + /** + * 获取当前店铺讲师id列表 + * @return + */ + public List<String> getShopXiaoeUserIdList() { + Long userId = SecurityUtils.getUserId(); + //获取用户所属店铺 + ShopRelUserVo shopRelUserVo = remoteShopService.getShopByUserId(userId).getData(); + if (Objects.isNull(shopRelUserVo)) { + throw new ServiceException("当前用户未关联店铺,请先关联店铺"); + } + //查询店铺信息 + Shop shop = remoteShopService.getShop(shopRelUserVo.getShopId()).getData(); + if (Objects.isNull(shop)) { + throw new ServiceException("店铺不存在"); + } + if (StringUtils.isBlank(shop.getXiaoeUserId())) { + throw new ServiceException("创建失败,请联系平台添加讲师。"); + } + return Arrays.asList(shop.getXiaoeUserId().split(",")); + } + /** + * 创建直播 + * @param dto + * @param type 创建类型 1:平台 2:经销商 + * @return + */ + public void create(XiaoeLiveDto dto,Integer type) { + if (dto.getPaymentType().equals(3) && StringUtils.isBlank(dto.getResourcePassword())){ + throw new ServiceException("密码不能为空"); + } + if (type.equals(2)) { + //获取当前登录用户 + Long userId = SecurityUtils.getUserId(); + //获取用户所属店铺 + ShopRelUserVo shopRelUserVo = remoteShopService.getShopByUserId(userId).getData(); + if (Objects.isNull(shopRelUserVo)) { + throw new ServiceException("当前用户未关联店铺,请先关联店铺"); + } + //查询店铺信息 + Shop shop = remoteShopService.getShop(shopRelUserVo.getShopId()).getData(); + if (Objects.isNull(shop)) { + throw new ServiceException("店铺不存在"); + } + String liveId = xiaoeUtils.addLive(dto); + if (StringUtils.isBlank(liveId)) { + throw new ServiceException("创建直播失败,请联系平台管理员"); + } + Long shopId = shop.getShopId(); + String shopName = shop.getShopName(); + //添加直播创建记录 + xiaoeLiveRecordService.add(shopId, type, shopName, liveId); + } else { + String liveId = xiaoeUtils.addLive(dto); + if (StringUtils.isBlank(liveId)) { + throw new ServiceException("创建直播失败,请联系平台管理员"); + } + //添加直播创建记录 + xiaoeLiveRecordService.add(null, type, "鸿瑞堂", liveId); + } + } + + /** + * 编辑直播 + * @param dto + */ + public Boolean edit(XiaoeLiveDto dto) { + if (StringUtils.isBlank(dto.getId())) { + throw new ServiceException("直播id不能为空"); + } + return xiaoeUtils.editLive(dto); + } + + /** + * 管理后台直播分页列表 + * @param dto + * @return + */ + public Page<XiaoeLiveVo> getMgtLivePage(XiaoeLiveQueryDto dto) { + Page<XiaoeLiveVo> livePageList = xiaoeUtils.getLivePageList(dto); + Long shopId = dto.getShopId(); + if (Objects.nonNull(shopId)) { + List<XiaoeLiveRecord> xiaoeLiveRecords = xiaoeLiveRecordService.getListByShopId(shopId); + if (CollUtil.isEmpty(xiaoeLiveRecords)) { + return new Page<>(); + } + List<String> liveIdList = xiaoeLiveRecords.stream().map(XiaoeLiveRecord::getLiveId).collect(Collectors.toList()); + List<XiaoeLiveVo> filteredList = livePageList.getRecords().stream().filter(item -> liveIdList.contains(item.getId())).collect(Collectors.toList()); + livePageList.setRecords(filteredList); + } + List<XiaoeLiveRecord> shopRecordList = xiaoeLiveRecordService.lambdaQuery().eq(XiaoeLiveRecord::getType, 2).list(); + Map<String, String> shopNameMap = shopRecordList.stream().collect(Collectors.toMap(XiaoeLiveRecord::getLiveId, XiaoeLiveRecord::getShopName)); + livePageList.setRecords(livePageList.getRecords().stream().peek(item -> { + String name = shopNameMap.get(item.getId()); + if (StringUtils.isNotBlank(name)) { + item.setShopName(name); + } + }).collect(Collectors.toList())); + return livePageList; + } + + /** + * 删除直播 + * @param id + */ + public void deleteLive(String id) { + Boolean flag = xiaoeUtils.deleteLive(id); + if (flag) { + //删除直播添加记录 + xiaoeLiveRecordService.lambdaUpdate().eq(XiaoeLiveRecord::getLiveId, id).remove(); + } + } + + /** + * 员工端直播列表 + * @param dto + * @return + */ + public Page<XiaoeLiveVo> getStaffLivePage(XiaoeLiveQueryDto dto) { + Page<XiaoeLiveVo> page = new Page<>(); + List<XiaoeLiveRecord> xiaoeLiveRecordList = xiaoeLiveRecordService.getMgtRecord(); + if (CollectionUtil.isEmpty(xiaoeLiveRecordList)) { + return page; + } + Page<XiaoeLiveVo> livePageList = xiaoeUtils.getLivePageList(dto); + if (CollectionUtil.isEmpty(livePageList.getRecords())) { + return page; + } + //筛选平台创建的直播 + Set<String> liveIdSet = xiaoeLiveRecordList.stream().map(XiaoeLiveRecord::getLiveId).collect(Collectors.toSet()); + //过滤数据 + List<XiaoeLiveVo> filteredRecords = livePageList.getRecords().stream().filter(item -> liveIdSet.contains(item.getId()) && !item.getAliveState().equals(2)).collect(Collectors.toList()); + livePageList.setRecords(filteredRecords); + return livePageList; + } +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/live/XiaoeLiveAppointmentServiceImpl.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/live/XiaoeLiveAppointmentServiceImpl.java new file mode 100644 index 0000000..69956e1 --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/live/XiaoeLiveAppointmentServiceImpl.java @@ -0,0 +1,57 @@ +package com.ruoyi.goods.service.impl.live; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ruoyi.goods.domain.pojo.live.XiaoeLiveAppointment; +import com.ruoyi.goods.domain.pojo.live.XiaoeLiveRecord; +import com.ruoyi.goods.mapper.live.XiaoeLiveAppointmentMapper; +import com.ruoyi.goods.service.live.IXiaoeLiveAppointmentService; +import com.ruoyi.goods.service.live.IXiaoeLiveRecordService; +import com.ruoyi.goods.utils.WeChatSubscribeMessageSender; +import com.ruoyi.system.api.domain.poji.member.Member; +import com.ruoyi.system.api.service.RemoteMemberService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.Objects; + +/** + * <p> + * 直播预约记录 服务实现类 + * </p> + * + * @author mitao + * @since 2025-01-09 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class XiaoeLiveAppointmentServiceImpl extends ServiceImpl<XiaoeLiveAppointmentMapper, XiaoeLiveAppointment> implements IXiaoeLiveAppointmentService { + private final RemoteMemberService remoteMemberService; + private final IXiaoeLiveRecordService xiaoeLiveRecordService; + + /** + * 推送微信小程序订阅消息 + * @param appointmentId + * @return + */ + @Override + public void push(Long appointmentId) { + log.info("开始推送预约id为:{}的订阅消息",appointmentId); + XiaoeLiveAppointment appointment = getById(appointmentId); + if (Objects.nonNull(appointment)) { + Member member = remoteMemberService.getMember(appointment.getUserId()).getData(); + if (Objects.isNull(member)){ + return; + } + XiaoeLiveRecord record = xiaoeLiveRecordService.getByLiveId(appointment.getLiveId()); + if (Objects.isNull(record)) { + return; + } + //推送微信小程序订阅消息 + WeChatSubscribeMessageSender.push(member.getMiniOpenid(), appointment.getTitle(), record.getShopName(), appointment.getAliveStartAt()); + } + log.info("预约id为:{}的订阅消息推送成功",appointmentId); + } + +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/live/XiaoeLiveRecordServiceImpl.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/live/XiaoeLiveRecordServiceImpl.java new file mode 100644 index 0000000..cfa6fd9 --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/live/XiaoeLiveRecordServiceImpl.java @@ -0,0 +1,70 @@ +package com.ruoyi.goods.service.impl.live; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ruoyi.common.core.utils.DateUtils; +import com.ruoyi.goods.domain.pojo.live.XiaoeLiveRecord; +import com.ruoyi.goods.mapper.live.XiaoeLiveRecordMapper; +import com.ruoyi.goods.service.live.IXiaoeLiveRecordService; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * <p> + * 小鹅通直播添加记录表 服务实现类 + * </p> + * + * @author mitao + * @since 2025-01-09 + */ +@Service +public class XiaoeLiveRecordServiceImpl extends ServiceImpl<XiaoeLiveRecordMapper, XiaoeLiveRecord> implements IXiaoeLiveRecordService { + /** + * 根据直播id查询记录 + * + * @param liveId + * @return + */ + @Override + public XiaoeLiveRecord getByLiveId(String liveId) { + return lambdaQuery().eq(XiaoeLiveRecord::getLiveId, liveId).one(); + } + + /** + * 根据店铺id查询记录 + * + * @param shopId + * @return + */ + @Override + public List<XiaoeLiveRecord> getListByShopId(Long shopId) { + return lambdaQuery().eq(XiaoeLiveRecord::getType, 2).eq(XiaoeLiveRecord::getShopId, shopId).list(); + } + + /** + * 添加直播创建记录 + * @param shopId + * @param type + * @param shopName + * @param liveId + */ + @Override + public void add(Long shopId, Integer type, String shopName, String liveId) { + XiaoeLiveRecord xiaoeLiveRecord = new XiaoeLiveRecord(); + xiaoeLiveRecord.setShopId(shopId); + xiaoeLiveRecord.setType(type); + xiaoeLiveRecord.setShopName(shopName); + xiaoeLiveRecord.setLiveId(liveId); + xiaoeLiveRecord.setCreateTime(DateUtils.getNowDate()); + save(xiaoeLiveRecord); + } + + /** + * 平台直播哦添加记录 + * @return + */ + @Override + public List<XiaoeLiveRecord> getMgtRecord() { + return lambdaQuery().eq(XiaoeLiveRecord::getType, 1).list(); + } +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/live/IXiaoeLiveAppointmentService.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/live/IXiaoeLiveAppointmentService.java new file mode 100644 index 0000000..52dd780 --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/live/IXiaoeLiveAppointmentService.java @@ -0,0 +1,22 @@ +package com.ruoyi.goods.service.live; + + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ruoyi.goods.domain.pojo.live.XiaoeLiveAppointment; + +/** + * <p> + * 直播预约记录 服务类 + * </p> + * + * @author mitao + * @since 2025-01-09 + */ +public interface IXiaoeLiveAppointmentService extends IService<XiaoeLiveAppointment> { + /** + * 推送微信小程序订阅消息 + * @param appointmentId + * @return + */ + void push(Long appointmentId); +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/live/IXiaoeLiveRecordService.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/live/IXiaoeLiveRecordService.java new file mode 100644 index 0000000..44b79ac --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/live/IXiaoeLiveRecordService.java @@ -0,0 +1,41 @@ +package com.ruoyi.goods.service.live; + + +import com.baomidou.mybatisplus.extension.service.IService; +import com.ruoyi.goods.domain.pojo.live.XiaoeLiveRecord; + +import java.util.List; + +/** + * <p> + * 小鹅通直播添加记录表 服务类 + * </p> + * + * @author mitao + * @since 2025-01-09 + */ +public interface IXiaoeLiveRecordService extends IService<XiaoeLiveRecord> { + /** + * 根据直播id查询记录 + * @param liveId + * @return + */ + XiaoeLiveRecord getByLiveId(String liveId); + + /** + * 根据店铺id查询记录 + * @param shopId + * @return + */ + List<XiaoeLiveRecord> getListByShopId(Long shopId); + /** + * 添加直播创建记录 + * @param shopId + * @param type + * @param shopName + * @param liveId + */ + void add(Long shopId, Integer type, String shopName, String liveId); + + List<XiaoeLiveRecord> getMgtRecord(); +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/utils/WeChatSubscribeMessageSender.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/utils/WeChatSubscribeMessageSender.java new file mode 100644 index 0000000..66986e1 --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/utils/WeChatSubscribeMessageSender.java @@ -0,0 +1,83 @@ +package com.ruoyi.goods.utils; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.http.HttpUtil; +import com.alibaba.fastjson2.JSONObject; +import lombok.extern.slf4j.Slf4j; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * @author mitao + * @date 2025/1/10 + */ +@Slf4j +public class WeChatSubscribeMessageSender { + private static final String ACCESS_TOKEN_HOST = "https://api.weixin.qq.com/cgi-bin/token"; + private static final String STABLE_ACCESS_TOKEN_HOST = "https://api.weixin.qq.com/cgi-bin/stable_token"; + private static final String API_URL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send"; + + private static final String WX_APPID = "wxb7f0ea286fc4e535"; + + private static final String WX_SECRET = "852a2512a6ab559cafc68bae5d4160ac"; + private static final String TEMPLATE_ID = "EFeu75n2GMmOg33PxL1HNoyftp16ukco5DUbBfNBytE"; + + /** + *发送消息 + * @param touser 接收者(用户)的 openid + * @param title 直播主题 + * @param shopName 直播间名称 + * @param aliveStartAt 直播时间 + */ + public static void push(String touser, String title, String shopName, Date aliveStartAt) { + + //1,获取access_token + String accessToken = getAccessTokenByWX(); + String url = API_URL + "?access_token=" + accessToken; + Map<String, Object> params = new HashMap<>(); + params.put("template_id", TEMPLATE_ID); + params.put("page", null); + params.put("touser", touser); + // 构建订阅消息内容的JSON对象 + JSONObject messageData = new JSONObject(); + messageData.put("time5", createDataItem("直播时间", DateUtil.format(aliveStartAt, "MM-dd HH:mm:ss"))); + messageData.put("thing4", createDataItem("直播间名称", shopName)); + messageData.put("thing1", createDataItem("直播主题", title)); + params.put("data", messageData); + params.put("miniprogram_state", "trial"); + params.put("lang", "zh_CN"); + try { + log.info("发送消息参数:{}", JSONObject.toJSONString(params)); + String post = HttpUtil.post(url, JSONObject.toJSONString(params)); + log.info("发送消息返回结果:{}", post); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * 获取access_token + * @return + */ + private static String getAccessTokenByWX() { + Map<String, Object> params = new HashMap<>(); + params.put("appid", WX_APPID); + params.put("secret", WX_SECRET); + params.put("grant_type", "client_credential"); + String token = HttpUtil.post(STABLE_ACCESS_TOKEN_HOST,JSONObject.toJSONString(params)); + log.info("token:{}", token); + JSONObject jsonObject = JSONObject.parseObject(token); + return jsonObject.getString("access_token"); + } + private static Map<String, Object> createDataItem(String name, String value) { + Map<String, Object> item = new HashMap<>(); + item.put("value", value); + return item; + } + + public static void main(String[] args) throws Exception { + push("oL-gp5Fn7BobtFZCsQ3ZTY7QGU84", "直播推送", "鸿瑞堂", new Date()); + } +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/utils/XiaoeUtils.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/utils/XiaoeUtils.java new file mode 100644 index 0000000..ea90ecc --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/utils/XiaoeUtils.java @@ -0,0 +1,458 @@ +package com.ruoyi.goods.utils; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import cn.hutool.http.HttpUtil; +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.common.core.utils.DateUtils; +import com.ruoyi.common.core.utils.StringUtils; +import com.ruoyi.common.redis.service.RedisService; +import com.ruoyi.goods.domain.dto.XiaoeCourseQueryDto; +import com.ruoyi.goods.domain.dto.XiaoeLiveDto; +import com.ruoyi.goods.domain.dto.XiaoeLiveQueryDto; +import com.ruoyi.goods.domain.vo.XiaoeCourseChapterVO; +import com.ruoyi.goods.domain.vo.XiaoeCourseGroupVO; +import com.ruoyi.goods.domain.vo.XiaoeCourseVO; +import com.ruoyi.goods.domain.vo.XiaoeLiveDetailVOV2; +import com.ruoyi.goods.domain.vo.XiaoeLiveVo; +import com.ruoyi.goods.domain.vo.XiaoeLiveVoV2; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * 小鹅通工具类 + * @author mitao + * @date 2025/1/8 + */ +@Slf4j +@Component +public class XiaoeUtils { + @Resource + private RedisService redisService; + private static final String BASE_URL = "https://api.xiaoe-tech.com/token"; + //店铺的业务id + private String app_id = "appwmuwNWD48082"; + //应用的唯一标识,通过 client_id 来鉴别应用的身份 + private String client_id = "xopYwOAqNI36444"; + //应用的凭证秘钥,即client_secret,用来保证应用来源的可靠性,防止被伪造 + private String secret_key = "qKFxbGR0OlKX85PVyfCvkRF1P6fLRBEu"; + //固定填写client_credential + private String grant_type = "client_credential"; + //获取直播列表 + private static final String LIVE_PAGE_LIST = "https://api.xiaoe-tech.com/xe.alive.list.get/1.0.0"; + private static final String LIVE_PAGE_LIST_V2 = "https://api.xiaoe-tech.com/xe.alive.list.get/2.0.0"; + //获取直播详情 + private static final String LIVE_DETAIL = "https://api.xiaoe-tech.com/xe.alive.detail.get/1.0.0"; + private static final String LIVE_DETAIL_V2 = "https://api.xiaoe-tech.com/xe.alive.detail.get/2.0.0"; + //创建直播 + private static final String LIVE_ADD = "https://api.xiaoe-tech.com/xe.alive.live.create/1.0.0"; + //编辑直播 + private static final String LIVE_EDIT = "https://api.xiaoe-tech.com/xe.alive.live.update/1.0.0"; + //删除直播 + private static final String LIVE_DELETE = "https://api.xiaoe-tech.com/xe.alive.live.delete/1.0.0"; + //课程列表 + private static final String COURSE_PAGE_LIST = "https://api.xiaoe-tech.com/xe.course.course.list/1.0.0"; + //课程小节 + private static final String COURSE_CHAPTER = "https://api.xiaoe-tech.com/xe.course.course.chapter.get/1.0.0"; + //获取店铺商品分组列表 + private static final String COURSE_GROUP_LIST = "https://api.xiaoe-tech.com/xe.resource_tags.list/1.0.0"; + + + /** + * 获取小鹅通access_token + * @return + */ + private String getAccessToken() { + Boolean flag = redisService.hasKey("xiaoe:access_token"); + String accessToken = ""; + if (flag) { + accessToken = redisService.getCacheObject("xiaoe:access_token"); + } else { + String urlString = BASE_URL + + "?app_id=" + this.app_id + + "&client_id=" + this.client_id + + "&secret_key=" + this.secret_key + + "&grant_type=" + this.grant_type; + String result = null; + try { + URL reqURL = new URL(urlString); + HttpURLConnection httpURLConnection = (HttpURLConnection) reqURL.openConnection(); + InputStreamReader isr = new InputStreamReader(httpURLConnection.getInputStream()); + char[] chars = new char[1024]; + result = ""; + int len; + while ((len = isr.read(chars)) != -1) { + result += new String(chars, 0, len); + } + isr.close(); + } catch (MalformedURLException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + JSONObject jsonObject = JSONObject.parseObject(result); + log.info("获取access_token返回结果:{}", result); + Map data = (Map) jsonObject.get("data"); + accessToken = (String)data.get("access_token"); + Integer expiresIn = (int) data.get("expires_in"); + redisService.setCacheObject("xiaoe:access_token", accessToken,Long.parseLong(expiresIn.toString()), TimeUnit.SECONDS); + } + return accessToken; + } + + /** + * 获取直播列表 + * @param dto + * @return + */ + public Page<XiaoeLiveVo> getLivePageList(XiaoeLiveQueryDto dto) { + Map<String,Object> postParams = new HashMap<>(); + postParams.put("search_content", dto.getSearchContent()); + postParams.put("create_mode", dto.getCreateMode()); + postParams.put("state", 0); + postParams.put("search_alive_type", dto.getSearchAliveType()); + postParams.put("alive_play_state", dto.getAlivePlayState()); + postParams.put("page", dto.getPage()); + postParams.put("page_size", dto.getPageSize()); + postParams.put("access_token", getAccessToken()); + String post = HttpUtil.post(LIVE_PAGE_LIST, JSONObject.toJSONString(postParams)); + Page<XiaoeLiveVo> xiaoeLiveVOPage = new Page<>(); + if (StringUtils.isNotBlank(post)) { + log.info("获取直播列表返回结果:{}", post); + JSONObject jsonObject = JSONObject.parseObject(post); + if (jsonObject.get("code").equals(0) ) { + JSONObject data = jsonObject.getJSONObject("data"); + JSONArray list = data.getJSONArray("list"); + if (CollectionUtil.isNotEmpty(list)) { + List<XiaoeLiveVo> xiaoeLiveVos = JSONArray.parseArray(list.toJSONString(), XiaoeLiveVo.class); + xiaoeLiveVOPage.setRecords(xiaoeLiveVos); + xiaoeLiveVOPage.setCurrent(dto.getPage()); + xiaoeLiveVOPage.setPages(data.getLong("page_count")); + } + } + } + return xiaoeLiveVOPage; + } + + /** + *获取直播详情 + * @param id 直播ID + * @return + */ + public XiaoeLiveVo getLiveDetail(String id) { + Map<String, Object> postParams = new HashMap<>(); + postParams.put("id", id); + postParams.put("access_token", getAccessToken()); + String post = HttpUtil.post(LIVE_DETAIL, JSONObject.toJSONString(postParams)); + XiaoeLiveVo xiaoeLiveVO = null; + if (StringUtils.isNotBlank(post)) { + JSONObject jsonObject = JSONObject.parseObject(post); + if (jsonObject.get("code").equals(0)) { + JSONObject data = jsonObject.getJSONObject("data"); + xiaoeLiveVO = JSONObject.parseObject(data.toJSONString(), XiaoeLiveVo.class); + } + } + return xiaoeLiveVO; + } + + /** + * 获取直播列表2.0 + * @param dto + * @return + */ + public Page<XiaoeLiveVoV2> getLivePageListV2(XiaoeLiveQueryDto dto) { + Map<String,Object> postParams = new HashMap<>(); + postParams.put("search_content", dto.getSearchContent()); + postParams.put("create_mode", dto.getCreateMode()); + postParams.put("state", 0); + postParams.put("search_alive_type", dto.getSearchAliveType()); + postParams.put("alive_play_state", dto.getAlivePlayState()); + postParams.put("page", dto.getPage()); + postParams.put("page_size", dto.getPageSize()); + postParams.put("access_token", getAccessToken()); + postParams.put("zb_start_at_min", DateUtil.format(DateUtils.getTodayStartTime(), DatePattern.NORM_DATETIME_PATTERN)); + String post = HttpUtil.post(LIVE_PAGE_LIST_V2, JSONObject.toJSONString(postParams)); + Page<XiaoeLiveVoV2> xiaoeLiveVOPage = new Page<>(); + if (StringUtils.isNotBlank(post)) { + log.info("获取直播详情2.0返回结果:{}", post); + JSONObject jsonObject = JSONObject.parseObject(post); + if (jsonObject.get("code").equals(0)) { + JSONObject data = jsonObject.getJSONObject("data"); + JSONArray list = data.getJSONArray("live_list"); + if (!list.isEmpty()){ + List<XiaoeLiveVoV2> xiaoeLiveVos = JSONArray.parseArray(list.toJSONString(), XiaoeLiveVoV2.class); + xiaoeLiveVOPage.setRecords(xiaoeLiveVos); + xiaoeLiveVOPage.setCurrent(dto.getPage()); + xiaoeLiveVOPage.setTotal(data.getLong("total_count")); + } + } + } + return xiaoeLiveVOPage; + } + + /** + *获取直播详情 + * @param id 直播ID + * @return + */ + public XiaoeLiveDetailVOV2 getLiveDetailV2(String id) { + Map<String, Object> postParams = new HashMap<>(); + postParams.put("id", id); + postParams.put("access_token", getAccessToken()); + String post = HttpUtil.post(LIVE_DETAIL_V2, JSONObject.toJSONString(postParams)); + XiaoeLiveDetailVOV2 vo = null; + if (StringUtils.isNotBlank(post)) { + JSONObject jsonObject = JSONObject.parseObject(post); + if (jsonObject.get("code").equals(0)) { + JSONObject data = jsonObject.getJSONObject("data"); + vo = JSONObject.parseObject(data.toJSONString(), XiaoeLiveDetailVOV2.class); + } + } + return vo; + } + /** + * 创建直播 + * @param dto + * @return + */ + public String addLive(XiaoeLiveDto dto) { + Map<String, Object> requestParams = new HashMap<>(); + Map<String, Object> resourceInfoMap = new HashMap<>(); + resourceInfoMap.put("title", dto.getTitle()); + resourceInfoMap.put("summary", dto.getSummary()); + resourceInfoMap.put("zb_start_at", dto.getZbStartAt()); + resourceInfoMap.put("zb_stop_at", dto.getZbStopAt()); + resourceInfoMap.put("alive_type", dto.getAliveType()); + resourceInfoMap.put("descrb", dto.getDescrb()); + requestParams.put("resource_info", resourceInfoMap); + // 配置信息 + Map<String, Object> moudleInfoMap = new HashMap<>(); + moudleInfoMap.put("alive_mode", dto.getAliveMode()); + requestParams.put("module_info", moudleInfoMap); + //讲师信息 + List<Map<String, Object>> roleList = new ArrayList<>(); + Map<String, Object> roleInfoMap = new HashMap<>(); + roleInfoMap.put("role_name", "讲师"); + roleInfoMap.put("user_id", dto.getUserId()); + roleList.add(roleInfoMap); + requestParams.put("role_info", roleList); + //商品信息 + Map<String, Object> goodsInfoMap = new HashMap<>(); + goodsInfoMap.put("sale_type", 1);//售卖类型:1-单独售卖、2-关联售卖 + goodsInfoMap.put("payment_type", dto.getPaymentType()); + if (dto.getPaymentType().equals(3)) { + goodsInfoMap.put("resource_password", dto.getResourcePassword()); + } + requestParams.put("goods_info", goodsInfoMap); + requestParams.put("access_token", getAccessToken()); + log.info("创建直播参数:{}" ,JSONObject.toJSONString(requestParams)); + String post = HttpUtil.post(LIVE_ADD, JSONObject.toJSONString(requestParams)); + if (StringUtils.isNotBlank(post)) { + JSONObject jsonObject = JSONObject.parseObject(post); + log.info("创建直播返回结果:{}" ,post); + if (jsonObject.get("code").equals(0)) { + JSONObject data = jsonObject.getJSONObject("data"); + return data.getString("id"); + } + } + return null; + } + /** + * 编辑直播 + * @param dto + * @return + */ + public Boolean editLive(XiaoeLiveDto dto) { + boolean flag = false; + Map<String, Object> requestParams = new HashMap<>(); + Map<String, Object> resourceInfoMap = new HashMap<>(); + resourceInfoMap.put("id", dto.getId()); + resourceInfoMap.put("title", dto.getTitle()); + resourceInfoMap.put("summary", dto.getSummary()); + resourceInfoMap.put("zb_start_at", dto.getZbStartAt()); + resourceInfoMap.put("zb_stop_at", dto.getZbStopAt()); + resourceInfoMap.put("alive_type", dto.getAliveType()); + resourceInfoMap.put("descrb", dto.getDescrb()); + requestParams.put("resource_info", resourceInfoMap); + // 配置信息 + Map<String, Object> moudleInfoMap = new HashMap<>(); + moudleInfoMap.put("alive_mode", dto.getAliveMode()); + requestParams.put("module_info", moudleInfoMap); + //讲师信息 + List<Map<String, Object>> roleList = new ArrayList<>(); + Map<String, Object> roleInfoMap = new HashMap<>(); + roleInfoMap.put("role_name", "讲师"); + roleInfoMap.put("user_id", dto.getUserId()); + roleList.add(roleInfoMap); + requestParams.put("role_info", roleList); + //商品信息 + Map<String, Object> goodsInfoMap = new HashMap<>(); + goodsInfoMap.put("sale_type", 1);//售卖类型:1-单独售卖、2-关联售卖 + goodsInfoMap.put("payment_type", dto.getPaymentType()); + if (dto.getPaymentType().equals(3)) { + goodsInfoMap.put("resource_password", dto.getResourcePassword()); + } + requestParams.put("goods_info", goodsInfoMap); + requestParams.put("access_token", getAccessToken()); + log.info("编辑直播参数:{}" ,JSONObject.toJSONString(requestParams)); + String post = HttpUtil.post(LIVE_EDIT, JSONObject.toJSONString(requestParams)); + if (StringUtils.isNotBlank(post)) { + JSONObject jsonObject = JSONObject.parseObject(post); + log.info("编辑直播返回结果:{}" ,post); + if (jsonObject.get("code").equals(0)) { + flag = true; + } + } + return flag; + } + + /** + * 删除直播 + * @param id + * @return + */ + public Boolean deleteLive(String id) { + boolean flag = false; + Map<String, Object> requestParams = new HashMap<>(); + requestParams.put("id", id); + requestParams.put("access_token", getAccessToken()); + String post = HttpUtil.post(LIVE_DELETE, JSONObject.toJSONString(requestParams)); + if (StringUtils.isNotBlank(post)) { + JSONObject jsonObject = JSONObject.parseObject(post); + log.info("删除直播返回结果:{}" ,post); + if (jsonObject.get("code").equals(0)) { + flag = true; + } + } + return flag; + } + + /** + * 获取商品分组列表 + * @return + */ + public List<XiaoeCourseGroupVO> getCourseGroupList(){ + Map<String, Object> requestParams = new HashMap<>(); + requestParams.put("page", 1); + requestParams.put("page_size", 50); + requestParams.put("access_token", getAccessToken()); + String post = HttpUtil.post(COURSE_GROUP_LIST, JSONObject.toJSONString(requestParams)); + List<XiaoeCourseGroupVO> xiaoeCourseGroupVOList = new ArrayList<>(); + if (StringUtils.isNotBlank(post)) { + JSONObject jsonObject = JSONObject.parseObject(post); + log.info("获取商品分组返回结果:{}" ,post); + if (jsonObject.get("code").equals(0)) { + JSONObject data = jsonObject.getJSONObject("data"); + JSONArray jsonArray = data.getJSONArray("list"); + xiaoeCourseGroupVOList = JSONArray.parseArray(jsonArray.toJSONString(), XiaoeCourseGroupVO.class); + } + } + return xiaoeCourseGroupVOList; + } + + /** + * 获取课程列表 + * @param dto + * @return + */ + public Page<XiaoeCourseVO> getCoursePageList(XiaoeCourseQueryDto dto) { + Map<String, Object> requestParams = new HashMap<>(); + requestParams.put("search_content", dto.getSearchContent()); + requestParams.put("page_index", dto.getPageNo()); + requestParams.put("page_size", dto.getPageSize()); + requestParams.put("created_source", dto.getCreatedSource()); + requestParams.put("tags", dto.getTags()); + if (dto.getSortBy().equals(1)) { + requestParams.put("order_by", "modify");//根据创建时间排序 + requestParams.put("order_type",1); + } + + requestParams.put("sale_status", 1); + requestParams.put("access_token", getAccessToken()); + String post = HttpUtil.post(COURSE_PAGE_LIST, JSONObject.toJSONString(requestParams)); + Page<XiaoeCourseVO> page = new Page<>(); + if (StringUtils.isNotBlank(post)) { + log.info("获取课程列表返回结果:{}" ,post); + JSONObject jsonObject = JSONObject.parseObject(post); + if (jsonObject.get("code").equals(0)) { + JSONObject data = jsonObject.getJSONObject("data"); + JSONArray jsonArray = data.getJSONArray("list"); + List<XiaoeCourseVO> xiaoeCourseVOList = JSONArray.parseArray(jsonArray.toJSONString(), XiaoeCourseVO.class); + if (dto.getSortBy().equals(2)){ + xiaoeCourseVOList.sort(Comparator.comparing(XiaoeCourseVO::getCurriculumTime)); + } + page.setRecords(xiaoeCourseVOList); + page.setTotal(data.getLong("total")); + } + } + return page; + } + + /** + * 查询课程目录小节 + * @param id + * @return + */ + public List<XiaoeCourseChapterVO> getCourseChapterDetail(String id) { + Map<String, Object> requestParams = new HashMap<>(); + requestParams.put("course_id", id); + requestParams.put("access_token", getAccessToken()); + String post = HttpUtil.post(COURSE_CHAPTER, JSONObject.toJSONString(requestParams)); + List<XiaoeCourseChapterVO> courseChapterVOList = new ArrayList<>(); + if (StringUtils.isNotBlank(post)) { + log.info("查询课程目录小节返回结果:{}" ,post); + JSONObject jsonObject = JSONObject.parseObject(post); + if (jsonObject.get("code").equals(0)) { + JSONObject data = jsonObject.getJSONObject("data"); + courseChapterVOList = JSONArray.parseArray(data.getString("list"), XiaoeCourseChapterVO.class); + } + } + return courseChapterVOList; + } + public static void main(String[] args) { + String urlString = BASE_URL + + "?app_id=appwmuwNWD48082" + + "&client_id=xopYwOAqNI36444"+ + "&secret_key=qKFxbGR0OlKX85PVyfCvkRF1P6fLRBEu" + + "&grant_type=client_credential"; + String result = null; + try { + URL reqURL = new URL(urlString); + HttpURLConnection httpURLConnection = (HttpURLConnection) reqURL.openConnection(); + InputStreamReader isr = new InputStreamReader(httpURLConnection.getInputStream()); + char[] chars = new char[1024]; + result = ""; + int len; + while ((len = isr.read(chars)) != -1) { + result += new String(chars, 0, len); + } + isr.close(); + } catch (MalformedURLException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + JSONObject jsonObject = JSONObject.parseObject(result); + System.out.println(jsonObject); + Map data = (Map) jsonObject.get("data"); + String accessToken = (String) data.get("access_token"); + System.out.println(accessToken); + } + +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/resources/mapper/live/XiaoeLiveAppointmentMapper.xml b/ruoyi-modules/ruoyi-goods/src/main/resources/mapper/live/XiaoeLiveAppointmentMapper.xml new file mode 100644 index 0000000..08ed38e --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/resources/mapper/live/XiaoeLiveAppointmentMapper.xml @@ -0,0 +1,5 @@ +<?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.ruoyi.goods.mapper.live.XiaoeLiveAppointmentMapper"> + +</mapper> diff --git a/ruoyi-modules/ruoyi-goods/src/main/resources/mapper/live/XiaoeLiveRecordMapper.xml b/ruoyi-modules/ruoyi-goods/src/main/resources/mapper/live/XiaoeLiveRecordMapper.xml new file mode 100644 index 0000000..7e4d32f --- /dev/null +++ b/ruoyi-modules/ruoyi-goods/src/main/resources/mapper/live/XiaoeLiveRecordMapper.xml @@ -0,0 +1,5 @@ +<?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.ruoyi.goods.mapper.live.XiaoeLiveRecordMapper"> + +</mapper> diff --git a/ruoyi-modules/ruoyi-member/pom.xml b/ruoyi-modules/ruoyi-member/pom.xml index 57159f0..034888c 100644 --- a/ruoyi-modules/ruoyi-member/pom.xml +++ b/ruoyi-modules/ruoyi-member/pom.xml @@ -132,6 +132,17 @@ <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.mapstruct</groupId> + <artifactId>mapstruct-jdk8</artifactId> + <version>1.3.0.Final</version> + </dependency> + + <dependency> + <groupId>org.mapstruct</groupId> + <artifactId>mapstruct-processor</artifactId> + <version>1.3.0.Final</version> + </dependency> </dependencies> <build> diff --git a/ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/domain/dto/MgtEditShopDto.java b/ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/domain/dto/MgtEditShopDto.java index 116f5a9..3920dfe 100644 --- a/ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/domain/dto/MgtEditShopDto.java +++ b/ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/domain/dto/MgtEditShopDto.java @@ -139,4 +139,7 @@ @ApiModelProperty(value="商户banner 多个用,隔开") private String shopBanners; + + @ApiModelProperty(value="小鹅通讲师id 多个用,隔开") + private String xiaoeUserId; } diff --git a/ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/domain/vo/MgtShopInfoVo.java b/ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/domain/vo/MgtShopInfoVo.java index ce732c8..8bf91bf 100644 --- a/ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/domain/vo/MgtShopInfoVo.java +++ b/ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/domain/vo/MgtShopInfoVo.java @@ -149,6 +149,9 @@ @ApiModelProperty(value="证书list") private List<ShopCertificate> shopCertificateList; + @ApiModelProperty(value="小鹅通讲师id 多个用,隔开") + private String xiaoeUserId; + diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/GeneratorMybatisPlus.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/GeneratorMybatisPlus.java index b4ce83d..c005273 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/GeneratorMybatisPlus.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/GeneratorMybatisPlus.java @@ -22,7 +22,7 @@ // 全局配置 GlobalConfig globalConfig = new GlobalConfig(); //生成文件的输出目录 - String path="D:/hrt"; + String path="F:\\DeskTop"; globalConfig.setOutputDir(path); // Author设置作者 globalConfig.setAuthor("mybatis-plus"); @@ -35,7 +35,7 @@ globalConfig.setXmlName("%sMapper"); globalConfig.setServiceName("%sService"); globalConfig.setServiceImplName("%sServiceImpl"); - globalConfig.setAuthor("jqs"); + globalConfig.setAuthor("mitao"); // globalConfig.setEntityName("%s"); globalConfig.setControllerName("%sController"); autoGenerator.setGlobalConfig(globalConfig); @@ -44,16 +44,16 @@ DataSourceConfig dataSourceConfig = new DataSourceConfig(); dataSourceConfig.setDbType(DbType.MYSQL); dataSourceConfig.setTypeConvert(new MySqlTypeConvert()); - dataSourceConfig.setUrl("jdbc:mysql://47.109.78.184:10010/hrt_sys?tinyInt1isBit=false"); + dataSourceConfig.setUrl("jdbc:mysql://127.0.0.1:3306/hrt_goods?tinyInt1isBit=false"); dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver"); dataSourceConfig.setUsername("root"); - dataSourceConfig.setPassword("hrt123456"); + dataSourceConfig.setPassword("123456"); autoGenerator.setDataSource(dataSourceConfig); // 包名配置 PackageConfig packageConfig = new PackageConfig(); // 父包和子包名分开处理 - packageConfig.setParent("com.ruoyi.system"); + packageConfig.setParent("com.ruoyi.goods"); packageConfig.setController("app"); packageConfig.setEntity("domain.pojo"); packageConfig.setMapper("mapper"); @@ -74,7 +74,7 @@ strategy.setControllerMappingHyphenStyle(true); //表和前缀处理 String[] table = { - "t_file_record" + "t_xiaoe_live_record" }; strategy.setInclude(table); String[] tablePre = new String[]{"t_"}; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/sys/SysUserController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/sys/SysUserController.java index 57776ec..54c0ff6 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/sys/SysUserController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/sys/SysUserController.java @@ -1,6 +1,5 @@ package com.ruoyi.system.controller.sys; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.exception.ServiceException; import com.ruoyi.common.core.utils.StringUtils; @@ -18,19 +17,31 @@ import com.ruoyi.system.api.domain.dto.MgtFrozenMemberDto; import com.ruoyi.system.api.domain.poji.sys.SysDept; import com.ruoyi.system.api.domain.poji.sys.SysRole; +import com.ruoyi.system.api.domain.poji.sys.SysStaff; import com.ruoyi.system.api.domain.poji.sys.SysUser; import com.ruoyi.system.api.model.LoginUser; import com.ruoyi.system.api.model.QwH5LoginVo; import com.ruoyi.system.api.model.QwUserDetailDto; import com.ruoyi.system.domain.dto.UserMenuEditDto; -import com.ruoyi.system.api.domain.poji.sys.SysStaff; import com.ruoyi.system.service.staff.SysStaffService; -import com.ruoyi.system.service.sys.*; +import com.ruoyi.system.service.sys.ISysConfigService; +import com.ruoyi.system.service.sys.ISysDeptService; +import com.ruoyi.system.service.sys.ISysPermissionService; +import com.ruoyi.system.service.sys.ISysPostService; +import com.ruoyi.system.service.sys.ISysRoleService; +import com.ruoyi.system.service.sys.ISysUserService; import io.swagger.annotations.ApiOperation; import org.apache.commons.lang3.ArrayUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; @@ -459,6 +470,7 @@ * @return R<QwH5LoginVo> */ @PostMapping("/qwH5StaffLogin") + @ApiOperation(value = "员工端登录") public R<QwH5LoginVo> qwH5StaffLogin(@RequestBody QwUserDetailDto qwUserDetail) { String mobile = qwUserDetail.getMobile(); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/listener/RedisListener.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/listener/RedisListener.java index b852a0e..572ce5c 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/listener/RedisListener.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/listener/RedisListener.java @@ -7,6 +7,7 @@ import com.ruoyi.system.api.service.RemoteActivityService; import com.ruoyi.system.api.service.RemoteConfigService; import com.ruoyi.system.api.service.RemoteCouponService; +import com.ruoyi.system.api.service.RemoteGoodsService; import com.ruoyi.system.api.service.RemoteOrderService; import lombok.extern.log4j.Log4j2; import org.springframework.data.redis.connection.Message; @@ -44,6 +45,9 @@ @Resource private RemoteOrderService remoteOrderService; + @Resource + private RemoteGoodsService remoteGoodsService; + public RedisListener(RedisMessageListenerContainer listenerContainer, RedisTemplate redisTemplate) { super(listenerContainer); @@ -73,6 +77,8 @@ }else if(DelayTaskEnum.ORDER_AUTOMATIC_CANCEL.getCode().equals(operation)){ //自动结束任务 autoCancelOrder(split[1]); + } else if (DelayTaskEnum.LIVE_APPOINTMENT_TASK.getCode().equals(operation)) { + push(Long.valueOf(split[1])); } //删除失效的key @@ -84,6 +90,16 @@ } } + /** + * 推送消息 + * @param appointmentId + */ + private void push(Long appointmentId) { + remoteGoodsService.push(appointmentId); + //删除定时任务 + remoteConfigService.deleteDelayTask(DelayTaskEnum.LIVE_APPOINTMENT_TASK.getCode()+"-"+appointmentId); + } + public <T> T getAndSet(final String key, T value){ T oldValue=null; try { -- Gitblit v1.7.1