diff --git a/hiver-admin/test-output/test-report.html b/hiver-admin/test-output/test-report.html index 7c5f6fdd..209ddb79 100644 --- a/hiver-admin/test-output/test-report.html +++ b/hiver-admin/test-output/test-report.html @@ -35,7 +35,7 @@ Hiver
  • -五月 29, 2026 16:35:42 +五月 30, 2026 13:54:26
  • @@ -84,7 +84,7 @@

    passTest

    -

    16:35:42 下午 / 0.018 secs

    +

    13:54:27 下午 / 0.034 secs

    @@ -92,9 +92,9 @@
    #test-id=1
    passTest
    -05.29.2026 16:35:42 -05.29.2026 16:35:42 -0.018 secs +05.30.2026 13:54:27 +05.30.2026 13:54:27 +0.034 secs
    @@ -104,7 +104,7 @@ Pass - 16:35:42 + 13:54:27 Test passed @@ -128,13 +128,13 @@

    Started

    -

    五月 29, 2026 16:35:42

    +

    五月 30, 2026 13:54:26

    Ended

    -

    五月 29, 2026 16:35:43

    +

    五月 30, 2026 13:54:27

    diff --git a/hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/UserController.java b/hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/UserController.java index 44de687e..01cf7a64 100644 --- a/hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/UserController.java +++ b/hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/UserController.java @@ -106,6 +106,9 @@ public class UserController { @Autowired private SecurityUtil securityUtil; + @Autowired + private cc.hiver.mall.planet.hook.PlanetRewardHook planetRewardHook; + @PersistenceContext private EntityManager entityManager; @@ -656,6 +659,10 @@ public class UserController { userRoleService.save(ur); } } + // 鐧藉珫鏄熺悆-閭璇峰ソ鍙嬫敞鍐屾垚鍔燂紝缁欓個璇蜂汉鍙戞斁鏄熺悆鍒革紙涓嶅奖鍝嶄富娴佺▼锛 + if (wechatVo.getInviterId() != null) { + planetRewardHook.onInviteRegister(wechatVo.getInviterId(), null, wechatUser.getId()); + } // 鏇存柊瀹㈡埛淇℃伅锛岀粦瀹氱櫥褰曠敤鎴 //customerService.updateUserId(wechatVo.getCustomId(), wechatUser.getId()); // 杩斿洖褰撳墠鐧诲綍浜虹殑淇℃伅 diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/constant/PlanetConstant.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/constant/PlanetConstant.java new file mode 100644 index 00000000..14686af8 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/constant/PlanetConstant.java @@ -0,0 +1,96 @@ +package cc.hiver.mall.planet.constant; + +/** + * 鐧藉珫鏄熺悆甯搁噺 + * + * @author hiver + */ +public class PlanetConstant { + + /** 濂栨睜鐘舵 0杩涜涓 1宸插紑濂 */ + public static final int POOL_STATUS_RUNNING = 0; + public static final int POOL_STATUS_DRAWN = 1; + + /** 鍒告祦姘存潵婧愮被鍨 */ + public static final String TICKET_TYPE_ORDER = "order"; + public static final String TICKET_TYPE_GROUP = "group"; + public static final String TICKET_TYPE_INVITE = "invite"; + public static final String TICKET_TYPE_SIGN = "sign"; + public static final String TICKET_TYPE_BOX = "box"; + public static final String TICKET_TYPE_HUNT = "hunt"; + public static final String TICKET_TYPE_BUFF = "buff"; + public static final String TICKET_TYPE_DRAW = "draw"; + + /** 浠诲姟缂栫爜 */ + public static final String TASK_WAIMAI = "waimai"; + public static final String TASK_GROUP = "group"; + public static final String TASK_INVITE = "invite"; + public static final String TASK_SIGN = "sign"; + + /** BUFF绫诲瀷 */ + public static final String BUFF_DOUBLE = "double"; + public static final String BUFF_SHIELD = "shield"; + public static final String BUFF_LUCKY = "lucky"; + public static final String BUFF_HUNT = "hunt"; + public static final String BUFF_STEALTH = "stealth"; + + /** BUFF鐘舵 */ + public static final int BUFF_STATUS_ACTIVE = 0; + public static final int BUFF_STATUS_EXPIRED = 1; + + /** 杩芥崟缁撴灉 */ + public static final String HUNT_SUCCESS = "success"; + public static final String HUNT_SHIELD = "shield"; + public static final String HUNT_FAIL = "fail"; + + /** 姣忔棩杩芥崟娆℃暟涓婇檺 */ + public static final int HUNT_DAILY_LIMIT = 3; + /** 姣忔棩琚拷鎹曟垚鍔熶笂闄(杈惧埌鑷姩寮闃叉姢缃) */ + public static final int HUNTED_SUCCESS_LIMIT = 3; + /** 鑷姩闃叉姢缃╂寔缁皬鏃 */ + public static final int AUTO_SHIELD_HOURS = 24; + + /** 鍗遍櫓绛夌骇 */ + public static String dangerLevel(int ticket) { + if (ticket > 30) { + return "SSS"; + } else if (ticket >= 21) { + return "S"; + } else if (ticket >= 11) { + return "A"; + } else if (ticket >= 4) { + return "B"; + } + return "C"; + } + + public static String dangerLevelName(int ticket) { + if (ticket > 30) { + return "瀹囧畽棣栧瘜"; + } else if (ticket >= 21) { + return "S绾х洰鏍"; + } else if (ticket >= 11) { + return "A绾х洰鏍"; + } else if (ticket >= 4) { + return "B绾х洰鏍"; + } + return "C绾х洰鏍"; + } + + /** 姒滃崟鐩爣鎮祻濂栧姳锛氭寜鎺掑悕鍓嶄笁棰濆鎮祻鍒 */ + public static int bountyByRank(int rankNo) { + if (rankNo == 1) { + return 2; + } else if (rankNo == 2 || rankNo == 3) { + return 1; + } + return 0; + } + + /** 蹇绫诲瀷 */ + public static final String NEWS_RANK = "rank"; + public static final String NEWS_HUNT = "hunt"; + public static final String NEWS_BOX = "box"; + public static final String NEWS_DRAW = "draw"; + public static final String NEWS_SYS = "sys"; +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/controller/PlanetAdminController.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/controller/PlanetAdminController.java new file mode 100644 index 00000000..46f5bee0 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/controller/PlanetAdminController.java @@ -0,0 +1,235 @@ +package cc.hiver.mall.planet.controller; + +import cc.hiver.core.common.exception.HiverException; +import cc.hiver.core.common.utils.ResultUtil; +import cc.hiver.core.common.vo.PageVo; +import cc.hiver.core.common.vo.Result; +import cc.hiver.mall.planet.entity.*; +import cc.hiver.mall.planet.service.PlanetAdminService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.*; + +/** + * 鐧藉珫鏄熺悆-鍚庡彴绠$悊鎺ュ彛 + * + * @author hiver + */ +@Slf4j +@RestController +@Api(tags = "鐧藉珫鏄熺悆鍚庡彴鎺ュ彛") +@RequestMapping("/hiver/app/planet/admin") +@Transactional +public class PlanetAdminController { + + @Autowired + private PlanetAdminService adminService; + + /** 鍟嗗湀寮洪殧绂伙細鐧藉珫鏄熺悆鍚庡彴鎵鏈夊姛鑳藉潎闄愬畾鍦ㄦ湰鍟嗗湀鍐 */ + private static final String REGION_REQUIRED = "璇峰厛閫夋嫨鍟嗗湀锛岀櫧瀚栨槦鐞冧粎闄愭湰鍖哄煙鍐呰繘琛"; + + private PageVo buildPage(Integer pageNumber, Integer pageSize) { + final PageVo pageVo = new PageVo(); + pageVo.setPageNumber(pageNumber == null ? 1 : pageNumber); + pageVo.setPageSize(pageSize == null ? 10 : pageSize); + return pageVo; + } + + // ---------------- 濂栨睜 ---------------- + @ApiOperation(value = "濂栨睜鍒嗛〉") + @RequestMapping(value = "/pool/page", method = RequestMethod.GET) + public Result poolPage(@RequestParam(required = false) Integer pageNumber, + @RequestParam(required = false) Integer pageSize, + @RequestParam(required = false) String regionId, + @RequestParam(required = false) Integer status) { + if (StringUtils.isEmpty(regionId)) { + return ResultUtil.error("璇峰厛閫夋嫨鍟嗗湀锛屾娊濂栦粎闄愭湰鍖哄煙鍐呰繘琛"); + } + return new ResultUtil<>().setData(adminService.pagePools(buildPage(pageNumber, pageSize), regionId, status)); + } + + @ApiOperation(value = "淇濆瓨濂栨睜") + @RequestMapping(value = "/pool/save", method = RequestMethod.POST) + public Result poolSave(@RequestBody PlanetPool pool) { + if (pool == null || StringUtils.isEmpty(pool.getRegionId())) { + return ResultUtil.error("濂栨睜蹇呴』褰掑睘鍟嗗湀锛屾娊濂栦粎闄愭湰鍖哄煙鍐呰繘琛"); + } + return new ResultUtil<>().setData(adminService.savePool(pool)); + } + + @ApiOperation(value = "鍒犻櫎濂栨睜") + @RequestMapping(value = "/pool/delete", method = RequestMethod.POST) + public Result poolDelete(@RequestParam String id) { + adminService.deletePool(id); + return ResultUtil.success("鍒犻櫎鎴愬姛"); + } + + // ---------------- 濂栭」 ---------------- + @ApiOperation(value = "濂栨睜濂栭」鍒楄〃") + @RequestMapping(value = "/reward/list", method = RequestMethod.GET) + public Result rewardList(@RequestParam String poolId) { + return new ResultUtil<>().setData(adminService.rewardsOfPool(poolId)); + } + + @ApiOperation(value = "淇濆瓨濂栭」") + @RequestMapping(value = "/reward/save", method = RequestMethod.POST) + public Result rewardSave(@RequestBody PlanetReward reward) { + return new ResultUtil<>().setData(adminService.saveReward(reward)); + } + + @ApiOperation(value = "鍒犻櫎濂栭」") + @RequestMapping(value = "/reward/delete", method = RequestMethod.POST) + public Result rewardDelete(@RequestParam String id) { + adminService.deleteReward(id); + return ResultUtil.success("鍒犻櫎鎴愬姛"); + } + + // ---------------- 浠诲姟 ---------------- + @ApiOperation(value = "浠诲姟鍒嗛〉") + @RequestMapping(value = "/task/page", method = RequestMethod.GET) + public Result taskPage(@RequestParam(required = false) Integer pageNumber, + @RequestParam(required = false) Integer pageSize, + @RequestParam(required = false) String regionId) { + if (StringUtils.isEmpty(regionId)) { + return ResultUtil.error(REGION_REQUIRED); + } + return new ResultUtil<>().setData(adminService.pageTasks(buildPage(pageNumber, pageSize), regionId)); + } + + @ApiOperation(value = "淇濆瓨浠诲姟") + @RequestMapping(value = "/task/save", method = RequestMethod.POST) + public Result taskSave(@RequestBody PlanetTask task) { + if (task == null || StringUtils.isEmpty(task.getRegionId())) { + return ResultUtil.error("浠诲姟蹇呴』褰掑睘鍟嗗湀锛岀櫧瀚栨槦鐞冧粎闄愭湰鍖哄煙鍐呰繘琛"); + } + return new ResultUtil<>().setData(adminService.saveTask(task)); + } + + @ApiOperation(value = "鍒犻櫎浠诲姟") + @RequestMapping(value = "/task/delete", method = RequestMethod.POST) + public Result taskDelete(@RequestParam String id) { + adminService.deleteTask(id); + return ResultUtil.success("鍒犻櫎鎴愬姛"); + } + + // ---------------- BUFF ---------------- + @ApiOperation(value = "BUFF鍒嗛〉") + @RequestMapping(value = "/buff/page", method = RequestMethod.GET) + public Result buffPage(@RequestParam(required = false) Integer pageNumber, + @RequestParam(required = false) Integer pageSize, + @RequestParam(required = false) String regionId) { + if (StringUtils.isEmpty(regionId)) { + return ResultUtil.error(REGION_REQUIRED); + } + return new ResultUtil<>().setData(adminService.pageBuffs(buildPage(pageNumber, pageSize), regionId)); + } + + @ApiOperation(value = "淇濆瓨BUFF") + @RequestMapping(value = "/buff/save", method = RequestMethod.POST) + public Result buffSave(@RequestBody PlanetBuff buff) { + if (buff == null || StringUtils.isEmpty(buff.getRegionId())) { + return ResultUtil.error("BUFF蹇呴』褰掑睘鍟嗗湀锛岀櫧瀚栨槦鐞冧粎闄愭湰鍖哄煙鍐呰繘琛"); + } + return new ResultUtil<>().setData(adminService.saveBuff(buff)); + } + + @ApiOperation(value = "鍒犻櫎BUFF") + @RequestMapping(value = "/buff/delete", method = RequestMethod.POST) + public Result buffDelete(@RequestParam String id) { + adminService.deleteBuff(id); + return ResultUtil.success("鍒犻櫎鎴愬姛"); + } + + // ---------------- 蹇 ---------------- + @ApiOperation(value = "蹇鍒嗛〉") + @RequestMapping(value = "/news/page", method = RequestMethod.GET) + public Result newsPage(@RequestParam(required = false) Integer pageNumber, + @RequestParam(required = false) Integer pageSize, + @RequestParam(required = false) String regionId) { + if (StringUtils.isEmpty(regionId)) { + return ResultUtil.error(REGION_REQUIRED); + } + return new ResultUtil<>().setData(adminService.pageNews(buildPage(pageNumber, pageSize), regionId)); + } + + @ApiOperation(value = "淇濆瓨蹇") + @RequestMapping(value = "/news/save", method = RequestMethod.POST) + public Result newsSave(@RequestBody PlanetNews news) { + if (news == null || StringUtils.isEmpty(news.getRegionId())) { + return ResultUtil.error("蹇蹇呴』褰掑睘鍟嗗湀锛岀櫧瀚栨槦鐞冧粎闄愭湰鍖哄煙鍐呰繘琛"); + } + return new ResultUtil<>().setData(adminService.saveNews(news)); + } + + @ApiOperation(value = "鍒犻櫎蹇") + @RequestMapping(value = "/news/delete", method = RequestMethod.POST) + public Result newsDelete(@RequestParam String id) { + adminService.deleteNews(id); + return ResultUtil.success("鍒犻櫎鎴愬姛"); + } + + // ---------------- 鎺掕姒 ---------------- + @ApiOperation(value = "鎺掕姒滃垎椤") + @RequestMapping(value = "/rank/page", method = RequestMethod.GET) + public Result rankPage(@RequestParam(required = false) Integer pageNumber, + @RequestParam(required = false) Integer pageSize, + @RequestParam(required = false) String regionId) { + if (StringUtils.isEmpty(regionId)) { + return ResultUtil.error(REGION_REQUIRED); + } + return new ResultUtil<>().setData(adminService.pageRank(buildPage(pageNumber, pageSize), regionId)); + } + + // ---------------- 杩芥崟璁板綍 ---------------- + @ApiOperation(value = "杩芥崟璁板綍鍒嗛〉") + @RequestMapping(value = "/hunt/page", method = RequestMethod.GET) + public Result huntPage(@RequestParam(required = false) Integer pageNumber, + @RequestParam(required = false) Integer pageSize, + @RequestParam(required = false) String regionId) { + if (StringUtils.isEmpty(regionId)) { + return ResultUtil.error(REGION_REQUIRED); + } + return new ResultUtil<>().setData(adminService.pageHunts(buildPage(pageNumber, pageSize), regionId)); + } + + // ---------------- 寮濂栬褰 ---------------- + @ApiOperation(value = "寮濂栬褰曞垎椤") + @RequestMapping(value = "/draw/page", method = RequestMethod.GET) + public Result drawPage(@RequestParam(required = false) Integer pageNumber, + @RequestParam(required = false) Integer pageSize, + @RequestParam(required = false) String regionId) { + if (StringUtils.isEmpty(regionId)) { + return ResultUtil.error("璇峰厛閫夋嫨鍟嗗湀锛屼粎鍙煡鐪嬫湰鍖哄煙寮濂栬褰"); + } + return new ResultUtil<>().setData(adminService.pageDraws(buildPage(pageNumber, pageSize), regionId)); + } + + // ---------------- 涓璁板綍 ---------------- + @ApiOperation(value = "涓璁板綍鍒嗛〉") + @RequestMapping(value = "/winner/page", method = RequestMethod.GET) + public Result winnerPage(@RequestParam(required = false) Integer pageNumber, + @RequestParam(required = false) Integer pageSize, + @RequestParam(required = false) String regionId, + @RequestParam(required = false) String periodNo) { + if (StringUtils.isEmpty(regionId)) { + return ResultUtil.error("璇峰厛閫夋嫨鍟嗗湀锛屼粎鍙煡鐪嬫湰鍖哄煙涓璁板綍"); + } + return new ResultUtil<>().setData(adminService.pageWinners(buildPage(pageNumber, pageSize), regionId, periodNo)); + } + + // ---------------- 鎵嬪姩寮濂 ---------------- + @ApiOperation(value = "鎵嬪姩寮濂") + @RequestMapping(value = "/draw/manual", method = RequestMethod.POST) + public Result manualDraw(@RequestParam String poolId, + @RequestParam(required = false) String regionId) { + try { + return new ResultUtil<>().setData(adminService.manualDraw(poolId, regionId)); + } catch (HiverException e) { + return ResultUtil.error(e.getMessage()); + } + } +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/controller/PlanetController.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/controller/PlanetController.java new file mode 100644 index 00000000..e478a548 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/controller/PlanetController.java @@ -0,0 +1,234 @@ +package cc.hiver.mall.planet.controller; + +import cc.hiver.core.common.exception.HiverException; +import cc.hiver.core.common.utils.ResultUtil; +import cc.hiver.core.common.vo.Result; +import cc.hiver.mall.planet.entity.PlanetDrawRecord; +import cc.hiver.mall.planet.pojo.PlanetBoxResultVo; +import cc.hiver.mall.planet.pojo.PlanetHomeVo; +import cc.hiver.mall.planet.pojo.PlanetHuntResultVo; +import cc.hiver.mall.planet.pojo.PlanetQuery; +import cc.hiver.mall.planet.service.*; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import java.util.HashMap; +import java.util.Map; + +/** + * 鐧藉珫鏄熺悆-App绔帴鍙 + * + * @author hiver + */ +@Slf4j +@RestController +@Api(tags = "鐧藉珫鏄熺悆App鎺ュ彛") +@RequestMapping("/hiver/app/planet") +@Transactional +public class PlanetController { + + /** 鍟嗗湀寮洪殧绂伙細鐧藉珫鏄熺悆鎵鏈夊姛鑳藉潎闄愬畾鍦ㄦ湰鍟嗗湀鍐 */ + private static final String REGION_REQUIRED = "缂哄皯鍟嗗湀鍙傛暟锛岀櫧瀚栨槦鐞冧粎闄愭湰鍖哄煙鍐呰繘琛"; + + @Autowired + private PlanetService planetService; + + @Autowired + private PlanetRankService rankService; + + @Autowired + private PlanetHuntService huntService; + + @Autowired + private PlanetBoxService boxService; + + @Autowired + private PlanetTaskService taskService; + + @Autowired + private PlanetBuffService buffService; + + @Autowired + private PlanetDrawService drawService; + + @Autowired + private cc.hiver.mall.planet.service.PlanetTicketService ticketService; + + @ApiOperation(value = "棣栭〉鑱氬悎鏁版嵁") + @RequestMapping(value = "/home", method = RequestMethod.POST) + public Result home(@RequestBody PlanetQuery query) { + if (StringUtils.isEmpty(query.getUserId())) { + return ResultUtil.error("鐢ㄦ埛id涓嶈兘涓虹┖"); + } + if (StringUtils.isEmpty(query.getRegionId())) { + return ResultUtil.error("缂哄皯鍟嗗湀鍙傛暟锛岀櫧瀚栨槦鐞冧粎闄愭湰鍖哄煙鍐呰繘琛"); + } + try { + final PlanetHomeVo vo = planetService.home(query); + return new ResultUtil().setData(vo); + } catch (HiverException e) { + return ResultUtil.error(e.getMessage()); + } + } + + @ApiOperation(value = "閫氱級姒淭OP10") + @RequestMapping(value = "/rank", method = RequestMethod.POST) + public Result rank(@RequestBody PlanetQuery query) { + if (StringUtils.isEmpty(query.getRegionId())) { + return ResultUtil.error(REGION_REQUIRED); + } + return new ResultUtil<>().setData(rankService.rankTop(query.getRegionId(), 10, query.getUserId())); + } + + @ApiOperation(value = "鍙戣捣杩芥崟") + @RequestMapping(value = "/hunt", method = RequestMethod.POST) + public Result hunt(@RequestBody PlanetQuery query) { + if (StringUtils.isEmpty(query.getRegionId())) { + return ResultUtil.error(REGION_REQUIRED); + } + try { + final PlanetHuntResultVo vo = huntService.hunt(query.getUserId(), query.getRegionId(), query.getToUserId()); + return new ResultUtil().setData(vo); + } catch (HiverException e) { + return ResultUtil.error(e.getMessage()); + } + } + + @ApiOperation(value = "寮鍚瘡鏃ュ疂绠") + @RequestMapping(value = "/box/open", method = RequestMethod.POST) + public Result openBox(@RequestBody PlanetQuery query) { + if (StringUtils.isEmpty(query.getRegionId())) { + return ResultUtil.error(REGION_REQUIRED); + } + try { + final PlanetBoxResultVo vo = boxService.openDailyBox(query.getUserId(), query.getRegionId()); + return new ResultUtil().setData(vo); + } catch (HiverException e) { + return ResultUtil.error(e.getMessage()); + } + } + + @ApiOperation(value = "浠诲姟鍒楄〃") + @RequestMapping(value = "/tasks", method = RequestMethod.POST) + public Result tasks(@RequestBody PlanetQuery query) { + if (StringUtils.isEmpty(query.getRegionId())) { + return ResultUtil.error(REGION_REQUIRED); + } + return new ResultUtil<>().setData(taskService.listTasks(query.getUserId(), query.getRegionId())); + } + + @ApiOperation(value = "姣忔棩绛惧埌") + @RequestMapping(value = "/sign", method = RequestMethod.POST) + public Result sign(@RequestBody PlanetQuery query) { + if (StringUtils.isEmpty(query.getRegionId())) { + return ResultUtil.error(REGION_REQUIRED); + } + try { + final int reward = taskService.sign(query.getUserId(), query.getRegionId()); + return ResultUtil.success("绛惧埌鎴愬姛锛岃幏寰 " + reward + " 寮犳槦鐞冨埜"); + } catch (HiverException e) { + return ResultUtil.error(e.getMessage()); + } + } + + @ApiOperation(value = "棰嗗彇浠诲姟濂栧姳") + @RequestMapping(value = "/task/claim", method = RequestMethod.POST) + public Result claim(@RequestBody PlanetQuery query) { + if (StringUtils.isEmpty(query.getRegionId())) { + return ResultUtil.error(REGION_REQUIRED); + } + try { + final int reward = taskService.claim(query.getUserId(), query.getRegionId(), query.getTaskCode()); + return ResultUtil.success("棰嗗彇鎴愬姛锛岃幏寰 " + reward + " 寮犳槦鐞冨埜"); + } catch (HiverException e) { + return ResultUtil.error(e.getMessage()); + } + } + + @ApiOperation(value = "BUFF鍟嗗簵鍒楄〃") + @RequestMapping(value = "/buff/list", method = RequestMethod.POST) + public Result buffList(@RequestBody PlanetQuery query) { + if (StringUtils.isEmpty(query.getRegionId())) { + return ResultUtil.error(REGION_REQUIRED); + } + return new ResultUtil<>().setData(buffService.shopList(query.getUserId(), query.getRegionId())); + } + + @ApiOperation(value = "璐拱BUFF") + @RequestMapping(value = "/buff/buy", method = RequestMethod.POST) + public Result buyBuff(@RequestBody PlanetQuery query) { + if (StringUtils.isEmpty(query.getRegionId())) { + return ResultUtil.error(REGION_REQUIRED); + } + try { + return new ResultUtil<>().setData(buffService.buyBuff(query.getUserId(), query.getRegionId(), query.getBuffId())); + } catch (HiverException e) { + return ResultUtil.error(e.getMessage()); + } + } + + @ApiOperation(value = "鏈杩戜竴鏈熷紑濂栫粨鏋") + @RequestMapping(value = "/draw/result", method = RequestMethod.POST) + public Result drawResult(@RequestBody PlanetQuery query) { + if (StringUtils.isEmpty(query.getRegionId())) { + return ResultUtil.error("缂哄皯鍟嗗湀鍙傛暟锛屽紑濂栦粎闄愭湰鍖哄煙鍐呰繘琛"); + } + try { + final PlanetDrawRecord record = drawService.latestDrawRecord(query.getRegionId()); + final Map data = new HashMap<>(4); + data.put("record", record); + data.put("winners", record == null ? null : drawService.winnersOfDraw(record.getId())); + return new ResultUtil<>().setData(data); + } catch (HiverException e) { + return ResultUtil.error(e.getMessage()); + } + } + + @ApiOperation(value = "鎴戠殑涓璁板綍") + @RequestMapping(value = "/draw/myWinning", method = RequestMethod.POST) + public Result myWinning(@RequestBody PlanetQuery query) { + if (StringUtils.isEmpty(query.getRegionId())) { + return ResultUtil.error("缂哄皯鍟嗗湀鍙傛暟锛屼粎鍙煡鐪嬫湰鍖哄煙涓璁板綍"); + } + try { + return new ResultUtil<>().setData(drawService.myWinning(query.getUserId(), query.getRegionId())); + } catch (HiverException e) { + return ResultUtil.error(e.getMessage()); + } + } + + @ApiOperation(value = "棰嗗彇涓濂栧姳") + @RequestMapping(value = "/draw/receive", method = RequestMethod.POST) + public Result receive(@RequestBody PlanetQuery query) { + if (StringUtils.isEmpty(query.getRegionId())) { + return ResultUtil.error("缂哄皯鍟嗗湀鍙傛暟锛屼粎鍙鍙栨湰鍖哄煙涓"); + } + try { + drawService.receive(query.getUserId(), query.getRegionId(), query.getWinnerId()); + return ResultUtil.success("棰嗗彇鎴愬姛"); + } catch (HiverException e) { + return ResultUtil.error(e.getMessage()); + } + } + + @ApiOperation(value = "鎴戠殑鏄熺悆鍒告槑缁(鍒嗛〉)") + @RequestMapping(value = "/ticket/log", method = RequestMethod.POST) + public Result ticketLog(@RequestBody PlanetQuery query) { + if (StringUtils.isEmpty(query.getUserId())) { + return ResultUtil.error("鐢ㄦ埛id涓嶈兘涓虹┖"); + } + if (StringUtils.isEmpty(query.getRegionId())) { + return ResultUtil.error(REGION_REQUIRED); + } + return new ResultUtil<>().setData( + ticketService.pageLog(query.getUserId(), query.getRegionId(), query.getPageNumber(), query.getPageSize())); + } +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetBuff.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetBuff.java new file mode 100644 index 00000000..fc223b06 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetBuff.java @@ -0,0 +1,67 @@ +package cc.hiver.mall.planet.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.persistence.Id; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + * 鐧藉珫鏄熺悆-BUFF閰嶇疆 + * + * @author hiver + */ +@Data +@ApiModel(value = "鐧藉珫鏄熺悆-BUFF閰嶇疆") +@TableName(value = "t_planet_buff", autoResultMap = true) +public class PlanetBuff implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @TableId + @ApiModelProperty(value = "涓婚敭") + private String id; + + @ApiModelProperty(value = "鍟嗗湀id 绌轰负鍏ㄥ眬榛樿") + private String regionId; + + @ApiModelProperty(value = "绫诲瀷 double/shield/lucky/hunt/stealth") + private String type; + + @ApiModelProperty(value = "鍚嶇О") + private String name; + + @ApiModelProperty(value = "鎻忚堪") + private String description; + + @ApiModelProperty(value = "鍥炬爣") + private String icon; + + @ApiModelProperty(value = "娑堣楀埜鏁伴噺") + private Integer costTickets; + + @ApiModelProperty(value = "鎸佺画灏忔椂") + private Integer durationHours; + + @ApiModelProperty(value = "鏁堟灉鍊") + private BigDecimal effectValue; + + @ApiModelProperty(value = "鎺掑簭") + private Integer sort; + + @ApiModelProperty(value = "鏄惁鍚敤 1鏄 0鍚") + private Integer enabled; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "鍒涘缓鏃堕棿") + private Date createTime; +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetBuffRecord.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetBuffRecord.java new file mode 100644 index 00000000..cd5397c6 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetBuffRecord.java @@ -0,0 +1,68 @@ +package cc.hiver.mall.planet.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.persistence.Id; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + * 鐧藉珫鏄熺悆-鐢ㄦ埛BUFF璁板綍 + * + * @author hiver + */ +@Data +@ApiModel(value = "鐧藉珫鏄熺悆-鐢ㄦ埛BUFF璁板綍") +@TableName(value = "t_planet_buff_record", autoResultMap = true) +public class PlanetBuffRecord implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @TableId + @ApiModelProperty(value = "涓婚敭") + private String id; + + @ApiModelProperty(value = "鐢ㄦ埛id") + private String userId; + + @ApiModelProperty(value = "鍟嗗湀id") + private String regionId; + + @ApiModelProperty(value = "BUFF閰嶇疆id") + private String buffId; + + @ApiModelProperty(value = "绫诲瀷") + private String type; + + @ApiModelProperty(value = "鏁堟灉鍊") + private BigDecimal effectValue; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "鐢熸晥鏃堕棿") + private Date startTime; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "澶辨晥鏃堕棿") + private Date endTime; + + @ApiModelProperty(value = "鐘舵 0鐢熸晥 1宸茶繃鏈") + private Integer status; + + @ApiModelProperty(value = "鏉ユ簮 buy璐拱 box瀹濈 hunt闃叉姢") + private String source; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "鍒涘缓鏃堕棿") + private Date createTime; +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetDrawRecord.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetDrawRecord.java new file mode 100644 index 00000000..ff23a5ae --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetDrawRecord.java @@ -0,0 +1,66 @@ +package cc.hiver.mall.planet.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.persistence.Id; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + * 鐧藉珫鏄熺悆-寮濂栬褰 + * + * @author hiver + */ +@Data +@ApiModel(value = "鐧藉珫鏄熺悆-寮濂栬褰") +@TableName(value = "t_planet_draw_record", autoResultMap = true) +public class PlanetDrawRecord implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @TableId + @ApiModelProperty(value = "涓婚敭") + private String id; + + @ApiModelProperty(value = "濂栨睜id") + private String poolId; + + @ApiModelProperty(value = "鍟嗗湀id") + private String regionId; + + @ApiModelProperty(value = "鏈熷彿") + private String periodNo; + + @ApiModelProperty(value = "濂栨睜閲戦") + private BigDecimal poolAmount; + + @ApiModelProperty(value = "鍙備笌浜烘暟") + private Integer joinCount; + + @ApiModelProperty(value = "鍒告绘暟") + private Integer ticketTotal; + + @ApiModelProperty(value = "涓浜烘暟") + private Integer winnerCount; + + @ApiModelProperty(value = "鐘舵 1宸插紑濂") + private Integer status; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "寮濂栨椂闂") + private Date drawTime; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "鍒涘缓鏃堕棿") + private Date createTime; +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetDrawWinner.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetDrawWinner.java new file mode 100644 index 00000000..6ccb8669 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetDrawWinner.java @@ -0,0 +1,78 @@ +package cc.hiver.mall.planet.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.persistence.Id; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + * 鐧藉珫鏄熺悆-涓璁板綍 + * + * @author hiver + */ +@Data +@ApiModel(value = "鐧藉珫鏄熺悆-涓璁板綍") +@TableName(value = "t_planet_draw_winner", autoResultMap = true) +public class PlanetDrawWinner implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @TableId + @ApiModelProperty(value = "涓婚敭") + private String id; + + @ApiModelProperty(value = "寮濂栬褰昳d") + private String drawId; + + @ApiModelProperty(value = "濂栨睜id") + private String poolId; + + @ApiModelProperty(value = "鍟嗗湀id") + private String regionId; + + @ApiModelProperty(value = "鏈熷彿") + private String periodNo; + + @ApiModelProperty(value = "涓鐢ㄦ埛id") + private String userId; + + @ApiModelProperty(value = "涓鐢ㄦ埛鏄电О") + private String userName; + + @ApiModelProperty(value = "濂栭」灞傜骇") + private Integer rewardLevel; + + @ApiModelProperty(value = "濂栭」鍚嶇О") + private String levelName; + + @ApiModelProperty(value = "濂栧姳绫诲瀷 0鐜伴噾 1浼樻儬鍒") + private Integer rewardType; + + @ApiModelProperty(value = "涓閲戦") + private BigDecimal amount; + + @ApiModelProperty(value = "浼樻儬鍒竔d") + private String couponId; + + @ApiModelProperty(value = "鏄惁宸查鍙 0鍚 1鏄") + private Integer isReceived; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "棰嗗彇鏃堕棿") + private Date receivedTime; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "鍒涘缓鏃堕棿") + private Date createTime; +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetHuntRecord.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetHuntRecord.java new file mode 100644 index 00000000..552c3bf9 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetHuntRecord.java @@ -0,0 +1,66 @@ +package cc.hiver.mall.planet.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.persistence.Id; +import java.io.Serializable; +import java.time.LocalDate; +import java.util.Date; + +/** + * 鐧藉珫鏄熺悆-杩芥崟璁板綍 + * + * @author hiver + */ +@Data +@ApiModel(value = "鐧藉珫鏄熺悆-杩芥崟璁板綍") +@TableName(value = "t_planet_hunt_record", autoResultMap = true) +public class PlanetHuntRecord implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @TableId + @ApiModelProperty(value = "涓婚敭") + private String id; + + @ApiModelProperty(value = "鍙戣捣浜篿d") + private String fromUserId; + + @ApiModelProperty(value = "鍙戣捣浜烘樀绉") + private String fromUserName; + + @ApiModelProperty(value = "鐩爣鐢ㄦ埛id") + private String toUserId; + + @ApiModelProperty(value = "鐩爣鐢ㄦ埛鏄电О") + private String toUserName; + + @ApiModelProperty(value = "鍟嗗湀id") + private String regionId; + + @ApiModelProperty(value = "缁撴灉 success/shield/fail") + private String result; + + @ApiModelProperty(value = "缂磋幏鍒") + private Integer gainTickets; + + @ApiModelProperty(value = "鎮祻棰濆鍒") + private Integer bountyTickets; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern = "yyyy-MM-dd") + @ApiModelProperty(value = "杩芥崟鏃ユ湡") + private LocalDate huntDate; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "鍒涘缓鏃堕棿") + private Date createTime; +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetNews.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetNews.java new file mode 100644 index 00000000..59af2099 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetNews.java @@ -0,0 +1,57 @@ +package cc.hiver.mall.planet.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.persistence.Id; +import java.io.Serializable; +import java.util.Date; + +/** + * 鐧藉珫鏄熺悆-鏄熺悆蹇 + * + * @author hiver + */ +@Data +@ApiModel(value = "鐧藉珫鏄熺悆-鏄熺悆蹇") +@TableName(value = "t_planet_news", autoResultMap = true) +public class PlanetNews implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @TableId + @ApiModelProperty(value = "涓婚敭") + private String id; + + @ApiModelProperty(value = "鍟嗗湀id") + private String regionId; + + @ApiModelProperty(value = "绫诲瀷 rank/hunt/box/draw/sys") + private String type; + + @ApiModelProperty(value = "蹇鍐呭") + private String content; + + @ApiModelProperty(value = "鍏宠仈鐢ㄦ埛id") + private String userId; + + @ApiModelProperty(value = "鍏宠仈鐢ㄦ埛鏄电О") + private String userName; + + @ApiModelProperty(value = "鏄惁缃《 0鍚 1鏄") + private Integer isTop; + + @ApiModelProperty(value = "鏄惁灞曠ず 1鏄 0鍚") + private Integer enabled; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "鍒涘缓鏃堕棿") + private Date createTime; +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetPool.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetPool.java new file mode 100644 index 00000000..5079fca9 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetPool.java @@ -0,0 +1,74 @@ +package cc.hiver.mall.planet.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.persistence.Id; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + * 鐧藉珫鏄熺悆-濂栨睜鏈熸 + * + * @author hiver + */ +@Data +@ApiModel(value = "鐧藉珫鏄熺悆-濂栨睜鏈熸") +@TableName(value = "t_planet_pool", autoResultMap = true) +public class PlanetPool implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @TableId + @ApiModelProperty(value = "涓婚敭") + private String id; + + @ApiModelProperty(value = "鍟嗗湀/鏍″尯id") + private String regionId; + + @ApiModelProperty(value = "鏈熷彿") + private String periodNo; + + @ApiModelProperty(value = "鏈湡鏍囬") + private String title; + + @ApiModelProperty(value = "濂栨睜鎬婚噾棰") + private BigDecimal poolAmount; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "寮濂栨椂闂") + private Date drawTime; + + @ApiModelProperty(value = "鍙備笌浜烘暟") + private Integer joinCount; + + @ApiModelProperty(value = "鏈湡鎶曞叆鍒告绘暟") + private Integer ticketTotal; + + @ApiModelProperty(value = "涓浜烘暟") + private Integer winnerCount; + + @ApiModelProperty(value = "鐘舵 0杩涜涓 1宸插紑濂") + private Integer status; + + @ApiModelProperty(value = "澶囨敞/鍏憡") + private String remark; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "鍒涘缓鏃堕棿") + private Date createTime; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "鏇存柊鏃堕棿") + private Date updateTime; +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetReward.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetReward.java new file mode 100644 index 00000000..002ac750 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetReward.java @@ -0,0 +1,64 @@ +package cc.hiver.mall.planet.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.persistence.Id; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + * 鐧藉珫鏄熺悆-濂栭」閰嶇疆 + * + * @author hiver + */ +@Data +@ApiModel(value = "鐧藉珫鏄熺悆-濂栭」閰嶇疆") +@TableName(value = "t_planet_reward", autoResultMap = true) +public class PlanetReward implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @TableId + @ApiModelProperty(value = "涓婚敭") + private String id; + + @ApiModelProperty(value = "濂栨睜id") + private String poolId; + + @ApiModelProperty(value = "鍟嗗湀id") + private String regionId; + + @ApiModelProperty(value = "濂栭」灞傜骇 1涓绛 2浜岀瓑 3涓夌瓑 4骞歌繍") + private Integer level; + + @ApiModelProperty(value = "濂栭」鍚嶇О") + private String levelName; + + @ApiModelProperty(value = "濂栧姳绫诲瀷 0鐜伴噾 1浼樻儬鍒") + private Integer rewardType; + + @ApiModelProperty(value = "鍗曚唤閲戦") + private BigDecimal amount; + + @ApiModelProperty(value = "浼樻儬鍒竔d") + private String couponId; + + @ApiModelProperty(value = "鍚嶉鏁伴噺") + private Integer quota; + + @ApiModelProperty(value = "鎺掑簭") + private Integer sort; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "鍒涘缓鏃堕棿") + private Date createTime; +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetTask.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetTask.java new file mode 100644 index 00000000..dd70ff7f --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetTask.java @@ -0,0 +1,63 @@ +package cc.hiver.mall.planet.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.persistence.Id; +import java.io.Serializable; +import java.util.Date; + +/** + * 鐧藉珫鏄熺悆-浠诲姟瑙勫垯 + * + * @author hiver + */ +@Data +@ApiModel(value = "鐧藉珫鏄熺悆-浠诲姟瑙勫垯") +@TableName(value = "t_planet_task", autoResultMap = true) +public class PlanetTask implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @TableId + @ApiModelProperty(value = "涓婚敭") + private String id; + + @ApiModelProperty(value = "鍟嗗湀id 绌轰负鍏ㄥ眬榛樿") + private String regionId; + + @ApiModelProperty(value = "浠诲姟缂栫爜 waimai/group/invite/sign") + private String code; + + @ApiModelProperty(value = "浠诲姟鍚嶇О") + private String name; + + @ApiModelProperty(value = "鎻忚堪") + private String description; + + @ApiModelProperty(value = "鍥炬爣") + private String icon; + + @ApiModelProperty(value = "濂栧姳鍒告暟閲") + private Integer rewardTickets; + + @ApiModelProperty(value = "姣忔棩涓婇檺 0涓嶉檺") + private Integer dailyLimit; + + @ApiModelProperty(value = "鎺掑簭") + private Integer sort; + + @ApiModelProperty(value = "鏄惁鍚敤 1鏄 0鍚") + private Integer enabled; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "鍒涘缓鏃堕棿") + private Date createTime; +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetTicket.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetTicket.java new file mode 100644 index 00000000..4ee7048c --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetTicket.java @@ -0,0 +1,91 @@ +package cc.hiver.mall.planet.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.persistence.Id; +import java.io.Serializable; +import java.time.LocalDate; +import java.util.Date; + +/** + * 鐧藉珫鏄熺悆-鐢ㄦ埛鍒告眹鎬 + * + * @author hiver + */ +@Data +@ApiModel(value = "鐧藉珫鏄熺悆-鐢ㄦ埛鍒告眹鎬") +@TableName(value = "t_planet_ticket", autoResultMap = true) +public class PlanetTicket implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @TableId + @ApiModelProperty(value = "涓婚敭") + private String id; + + @ApiModelProperty(value = "鐢ㄦ埛id") + private String userId; + + @ApiModelProperty(value = "鍟嗗湀id") + private String regionId; + + @ApiModelProperty(value = "鏄电О") + private String nickname; + + @ApiModelProperty(value = "澶村儚") + private String avatar; + + @ApiModelProperty(value = "瀛﹂櫌") + private String college; + + @ApiModelProperty(value = "褰撳墠鍙敤鍒告暟閲") + private Integer ticketCount; + + @ApiModelProperty(value = "鍘嗗彶绱鑾峰緱鍒") + private Integer totalTicket; + + @ApiModelProperty(value = "杩炵画绛惧埌澶╂暟") + private Integer consecutiveSignDays; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern = "yyyy-MM-dd") + @ApiModelProperty(value = "鏈杩戠鍒版棩鏈") + private LocalDate lastSignDate; + + @ApiModelProperty(value = "杩炵画闇告澶╂暟") + private Integer rankKeepDays; + + @ApiModelProperty(value = "涓婃鎺掑悕") + private Integer lastRankNo; + + @ApiModelProperty(value = "浠婃棩宸茶拷鎹曟鏁") + private Integer huntCountToday; + + @ApiModelProperty(value = "浠婃棩琚拷鎹曟垚鍔熸鏁") + private Integer huntedSuccessToday; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") + @DateTimeFormat(pattern = "yyyy-MM-dd") + @ApiModelProperty(value = "鏈杩戝紑瀹濈鏃ユ湡") + private LocalDate boxOpenedDate; + + @ApiModelProperty(value = "鎵灞炴湡鍙") + private String periodNo; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "鍒涘缓鏃堕棿") + private Date createTime; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "鏇存柊鏃堕棿") + private Date updateTime; +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetTicketLog.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetTicketLog.java new file mode 100644 index 00000000..ada05b41 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/entity/PlanetTicketLog.java @@ -0,0 +1,60 @@ +package cc.hiver.mall.planet.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.persistence.Id; +import java.io.Serializable; +import java.util.Date; + +/** + * 鐧藉珫鏄熺悆-鍒告祦姘 + * + * @author hiver + */ +@Data +@ApiModel(value = "鐧藉珫鏄熺悆-鍒告祦姘") +@TableName(value = "t_planet_ticket_log", autoResultMap = true) +public class PlanetTicketLog implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @TableId + @ApiModelProperty(value = "涓婚敭") + private String id; + + @ApiModelProperty(value = "鐢ㄦ埛id") + private String userId; + + @ApiModelProperty(value = "鍟嗗湀id") + private String regionId; + + @ApiModelProperty(value = "鍙樻洿鏁伴噺(姝e緱璐熸墸)") + private Integer changeCount; + + @ApiModelProperty(value = "鍙樻洿鍚庝綑棰") + private Integer balance; + + @ApiModelProperty(value = "鏉ユ簮 order/group/invite/sign/box/hunt/buff/draw") + private String type; + + @ApiModelProperty(value = "鏉ユ簮涓氬姟id(骞傜瓑)") + private String sourceId; + + @ApiModelProperty(value = "鏈熷彿") + private String periodNo; + + @ApiModelProperty(value = "璇存槑") + private String remark; + + @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "鍒涘缓鏃堕棿") + private Date createTime; +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/hook/PlanetRewardHook.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/hook/PlanetRewardHook.java new file mode 100644 index 00000000..4188ff04 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/hook/PlanetRewardHook.java @@ -0,0 +1,56 @@ +package cc.hiver.mall.planet.hook; + +import cc.hiver.mall.planet.constant.PlanetConstant; +import cc.hiver.mall.planet.mq.PlanetTicketProducer; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * 鐧藉珫鏄熺悆-涓氬姟鍙戝埜鍥炶皟 + *

    + * 浠呭仛杞婚噺 MQ 鎶曢掞紝鎵鏈 DB 鎿嶄綔鏀惧埌娑堣垂绔紓姝ユ墽琛岋紝淇濊瘉涓嶅奖鍝嶄富涓氬姟閫熷害鍜屾祦绋嬶紱 + * 浠绘剰寮傚父閮借鍚炴帀锛岀粷涓嶅悜涓婃姏銆 + * + * @author hiver + */ +@Slf4j +@Component +public class PlanetRewardHook { + + @Autowired + private PlanetTicketProducer ticketProducer; + + /** + * 澶栧崠/鏅氳鍗曞畬鎴愬彂鍒 + */ + public void onOrderFinish(String userId, String regionId, String orderId) { + rewardByTask(userId, regionId, PlanetConstant.TASK_WAIMAI, PlanetConstant.TICKET_TYPE_ORDER, orderId, "澶栧崠璁㈠崟瀹屾垚"); + } + + /** + * 鍥㈣喘璁㈠崟瀹屾垚鍙戝埜 + */ + public void onGroupFinish(String userId, String regionId, String groupOrderId) { + rewardByTask(userId, regionId, PlanetConstant.TASK_GROUP, PlanetConstant.TICKET_TYPE_GROUP, groupOrderId, "鍥㈣喘璁㈠崟瀹屾垚"); + } + + /** + * 閭璇峰ソ鍙嬫敞鍐屽彂鍒 + */ + public void onInviteRegister(String inviterUserId, String regionId, String sourceId) { + rewardByTask(inviterUserId, regionId, PlanetConstant.TASK_INVITE, PlanetConstant.TICKET_TYPE_INVITE, sourceId, "閭璇峰ソ鍙嬫敞鍐"); + } + + private void rewardByTask(String userId, String regionId, String taskCode, String type, String sourceId, String remark) { + if (StringUtils.isEmpty(userId)) { + return; + } + try { + ticketProducer.sendTaskReward(userId, regionId, taskCode, type, sourceId, remark); + } catch (Exception e) { + log.warn("[鐧藉珫鏄熺悆] 鍙戝埜鎶曢掑け璐 userId={}, task={}, {}", userId, taskCode, e.getMessage()); + } + } +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetBuffMapper.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetBuffMapper.java new file mode 100644 index 00000000..3b5fecd3 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetBuffMapper.java @@ -0,0 +1,9 @@ +package cc.hiver.mall.planet.mapper; + +import cc.hiver.mall.planet.entity.PlanetBuff; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.springframework.stereotype.Repository; + +@Repository +public interface PlanetBuffMapper extends BaseMapper { +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetBuffRecordMapper.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetBuffRecordMapper.java new file mode 100644 index 00000000..86de4251 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetBuffRecordMapper.java @@ -0,0 +1,9 @@ +package cc.hiver.mall.planet.mapper; + +import cc.hiver.mall.planet.entity.PlanetBuffRecord; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.springframework.stereotype.Repository; + +@Repository +public interface PlanetBuffRecordMapper extends BaseMapper { +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetDrawRecordMapper.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetDrawRecordMapper.java new file mode 100644 index 00000000..f325abc1 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetDrawRecordMapper.java @@ -0,0 +1,9 @@ +package cc.hiver.mall.planet.mapper; + +import cc.hiver.mall.planet.entity.PlanetDrawRecord; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.springframework.stereotype.Repository; + +@Repository +public interface PlanetDrawRecordMapper extends BaseMapper { +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetDrawWinnerMapper.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetDrawWinnerMapper.java new file mode 100644 index 00000000..ae39dcc8 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetDrawWinnerMapper.java @@ -0,0 +1,9 @@ +package cc.hiver.mall.planet.mapper; + +import cc.hiver.mall.planet.entity.PlanetDrawWinner; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.springframework.stereotype.Repository; + +@Repository +public interface PlanetDrawWinnerMapper extends BaseMapper { +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetHuntRecordMapper.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetHuntRecordMapper.java new file mode 100644 index 00000000..1063589e --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetHuntRecordMapper.java @@ -0,0 +1,9 @@ +package cc.hiver.mall.planet.mapper; + +import cc.hiver.mall.planet.entity.PlanetHuntRecord; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.springframework.stereotype.Repository; + +@Repository +public interface PlanetHuntRecordMapper extends BaseMapper { +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetNewsMapper.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetNewsMapper.java new file mode 100644 index 00000000..09709196 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetNewsMapper.java @@ -0,0 +1,9 @@ +package cc.hiver.mall.planet.mapper; + +import cc.hiver.mall.planet.entity.PlanetNews; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.springframework.stereotype.Repository; + +@Repository +public interface PlanetNewsMapper extends BaseMapper { +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetPoolMapper.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetPoolMapper.java new file mode 100644 index 00000000..f0f63ff0 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetPoolMapper.java @@ -0,0 +1,9 @@ +package cc.hiver.mall.planet.mapper; + +import cc.hiver.mall.planet.entity.PlanetPool; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.springframework.stereotype.Repository; + +@Repository +public interface PlanetPoolMapper extends BaseMapper { +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetRewardMapper.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetRewardMapper.java new file mode 100644 index 00000000..88aa8166 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetRewardMapper.java @@ -0,0 +1,9 @@ +package cc.hiver.mall.planet.mapper; + +import cc.hiver.mall.planet.entity.PlanetReward; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.springframework.stereotype.Repository; + +@Repository +public interface PlanetRewardMapper extends BaseMapper { +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetTaskMapper.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetTaskMapper.java new file mode 100644 index 00000000..f8cd8a42 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetTaskMapper.java @@ -0,0 +1,9 @@ +package cc.hiver.mall.planet.mapper; + +import cc.hiver.mall.planet.entity.PlanetTask; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.springframework.stereotype.Repository; + +@Repository +public interface PlanetTaskMapper extends BaseMapper { +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetTicketLogMapper.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetTicketLogMapper.java new file mode 100644 index 00000000..8fbf547f --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetTicketLogMapper.java @@ -0,0 +1,9 @@ +package cc.hiver.mall.planet.mapper; + +import cc.hiver.mall.planet.entity.PlanetTicketLog; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.springframework.stereotype.Repository; + +@Repository +public interface PlanetTicketLogMapper extends BaseMapper { +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetTicketMapper.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetTicketMapper.java new file mode 100644 index 00000000..8539a127 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mapper/PlanetTicketMapper.java @@ -0,0 +1,9 @@ +package cc.hiver.mall.planet.mapper; + +import cc.hiver.mall.planet.entity.PlanetTicket; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.springframework.stereotype.Repository; + +@Repository +public interface PlanetTicketMapper extends BaseMapper { +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mq/PlanetMqConfig.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mq/PlanetMqConfig.java new file mode 100644 index 00000000..bdc4354a --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mq/PlanetMqConfig.java @@ -0,0 +1,54 @@ +package cc.hiver.mall.planet.mq; + +import org.springframework.amqp.core.Binding; +import org.springframework.amqp.core.BindingBuilder; +import org.springframework.amqp.core.DirectExchange; +import org.springframework.amqp.core.Queue; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 鐧藉珫鏄熺悆 MQ 閰嶇疆 + *

    + * 鍙戝埜銆佺敓鎴愬揩璁瓑闈炴牳蹇冨姩浣滃紓姝ュ寲锛岄伩鍏嶉樆濉炰笅鍗/娉ㄥ唽绛変富涓氬姟娴佺▼銆 + * + * @author hiver + */ +@Configuration +public class PlanetMqConfig { + + public static final String PLANET_EXCHANGE = "planet.direct.exchange"; + + /** 鍙戝埜闃熷垪 */ + public static final String TICKET_GRANT_QUEUE = "planet.ticket.grant.queue"; + public static final String TICKET_GRANT_ROUTING = "planet.ticket.grant.routing.key"; + + /** 蹇鐢熸垚闃熷垪 */ + public static final String NEWS_QUEUE = "planet.news.queue"; + public static final String NEWS_ROUTING = "planet.news.routing.key"; + + @Bean + public DirectExchange planetDirectExchange() { + return new DirectExchange(PLANET_EXCHANGE, true, false); + } + + @Bean + public Queue planetTicketGrantQueue() { + return new Queue(TICKET_GRANT_QUEUE, true); + } + + @Bean + public Binding bindingPlanetTicketGrantQueue() { + return BindingBuilder.bind(planetTicketGrantQueue()).to(planetDirectExchange()).with(TICKET_GRANT_ROUTING); + } + + @Bean + public Queue planetNewsQueue() { + return new Queue(NEWS_QUEUE, true); + } + + @Bean + public Binding bindingPlanetNewsQueue() { + return BindingBuilder.bind(planetNewsQueue()).to(planetDirectExchange()).with(NEWS_ROUTING); + } +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mq/PlanetTicketConsumer.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mq/PlanetTicketConsumer.java new file mode 100644 index 00000000..295e18a3 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mq/PlanetTicketConsumer.java @@ -0,0 +1,109 @@ +package cc.hiver.mall.planet.mq; + +import cc.hiver.mall.entity.MallOrder; +import cc.hiver.mall.planet.entity.PlanetTask; +import cc.hiver.mall.planet.service.PlanetNewsService; +import cc.hiver.mall.planet.service.PlanetTaskService; +import cc.hiver.mall.planet.service.PlanetTicketService; +import cc.hiver.mall.service.mybatis.MallOrderService; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.amqp.AmqpRejectAndDontRequeueException; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +/** + * 鐧藉珫鏄熺悆-鍙戝埜/蹇寮傛娑堣垂鑰 + *

    + * 鐪熸鐨勫彂鍒 DB 鎿嶄綔鍦ㄦ瀹屾垚锛沘ddTickets 閫氳繃 sourceId 骞傜瓑锛屽彲瀹夊叏搴斿 MQ 鑷冲皯涓娆℃姇閫掋 + * + * @author hiver + */ +@Slf4j +@Component +public class PlanetTicketConsumer { + + @Autowired + private PlanetTaskService taskService; + + @Autowired + private PlanetTicketService ticketService; + + @Autowired + private PlanetNewsService newsService; + + @Autowired + private MallOrderService mallOrderService; + + @RabbitListener(queues = PlanetMqConfig.TICKET_GRANT_QUEUE) + @Transactional(rollbackFor = Exception.class) + public void handleTicketGrant(String message) { + try { + final JSONObject json = JSONObject.parseObject(message); + final String userId = json.getString("userId"); + String regionId = json.getString("regionId"); + final String taskCode = json.getString("taskCode"); + final String type = json.getString("type"); + final String sourceId = json.getString("sourceId"); + final String remark = json.getString("remark"); + if (StringUtils.isEmpty(userId) || StringUtils.isEmpty(taskCode)) { + log.warn("[鐧藉珫鏄熺悆MQ] 鍙戝埜娑堟伅鍙傛暟寮傚父: {}", message); + return; + } + // 鍟嗗湀寮洪殧绂伙細娑堟伅缂 regionId 鏃讹紙濡傞個璇锋敞鍐岋級锛屼粠鐢ㄦ埛鏈杩戜竴绗旇鍗曞厹搴曡В鏋愶紝纭繚鍒稿綊灞炴纭晢鍦 + if (StringUtils.isEmpty(regionId)) { + regionId = resolveRegionByUserOrder(userId); + } + if (StringUtils.isEmpty(regionId)) { + log.warn("[鐧藉珫鏄熺悆MQ] 鏃犳硶纭畾鐢ㄦ埛鍟嗗湀锛岃烦杩囧彂鍒 userId={}, task={}", userId, taskCode); + return; + } + final PlanetTask task = taskService.getTaskConfig(regionId, taskCode); + if (task == null || task.getEnabled() == null || task.getEnabled() != 1) { + log.info("[鐧藉珫鏄熺悆MQ] 浠诲姟鏈惎鐢紝璺宠繃鍙戝埜 task={}", taskCode); + return; + } + final int reward = task.getRewardTickets() == null ? 1 : task.getRewardTickets(); + final int added = ticketService.addTickets(userId, regionId, reward, type, sourceId, remark); + log.info("[鐧藉珫鏄熺悆MQ] 鍙戝埜瀹屾垚 userId={}, task={}, 瀹炲彂={}", userId, taskCode, added); + } catch (Exception e) { + // 涓氬姟寮傚父鏃犻渶閲嶆姇锛堥噸鎶曚篃浼氬啀娆″け璐ワ級锛屼粎璁板綍鏃ュ織锛岃繘鍏ユ淇/涓㈠純 + log.error("[鐧藉珫鏄熺悆MQ] 鍙戝埜娑堟伅澶勭悊寮傚父: {}, msg={}", e.getMessage(), message, e); + throw new AmqpRejectAndDontRequeueException(e); + } + } + + /** + * 浠庣敤鎴锋渶杩戜竴绗斿甫鍟嗗湀鐨勮鍗曡В鏋 regionId锛堢敤浜庨個璇锋敞鍐岀瓑鏃犲晢鍦堜笂涓嬫枃鐨勫彂鍒革級銆 + */ + private String resolveRegionByUserOrder(String userId) { + try { + final MallOrder order = mallOrderService.getOne(new LambdaQueryWrapper() + .select(MallOrder::getRegionId) + .eq(MallOrder::getUserId, userId) + .isNotNull(MallOrder::getRegionId) + .ne(MallOrder::getRegionId, "") + .orderByDesc(MallOrder::getCreateTime) + .last("limit 1")); + return order == null ? null : order.getRegionId(); + } catch (Exception e) { + log.warn("[鐧藉珫鏄熺悆MQ] 瑙f瀽鐢ㄦ埛鍟嗗湀澶辫触 userId={}, {}", userId, e.getMessage()); + return null; + } + } + + @RabbitListener(queues = PlanetMqConfig.NEWS_QUEUE) + public void handleNews(String message) { + try { + final JSONObject json = JSONObject.parseObject(message); + newsService.addNews(json.getString("regionId"), json.getString("type"), json.getString("content"), null, null); + } catch (Exception e) { + log.error("[鐧藉珫鏄熺悆MQ] 蹇娑堟伅澶勭悊寮傚父: {}, msg={}", e.getMessage(), message, e); + throw new AmqpRejectAndDontRequeueException(e); + } + } +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mq/PlanetTicketProducer.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mq/PlanetTicketProducer.java new file mode 100644 index 00000000..167f6cad --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/mq/PlanetTicketProducer.java @@ -0,0 +1,60 @@ +package cc.hiver.mall.planet.mq; + +import com.alibaba.fastjson.JSON; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; + +/** + * 鐧藉珫鏄熺悆-鍙戝埜/蹇寮傛娑堟伅鐢熶骇鑰 + *

    + * 浠呭仛杞婚噺鎶曢掞紝涓嶅仛浠讳綍 DB 鎿嶄綔锛屼繚璇佷富涓氬姟娴佺▼涓嶈鍙戝埜閫昏緫鎷栨參銆 + * + * @author hiver + */ +@Slf4j +@Component +public class PlanetTicketProducer { + + @Autowired + private RabbitTemplate rabbitTemplate; + + /** + * 鎶曢掍竴鏉°屾寜浠诲姟鍙戝埜銆嶆秷鎭傛秷璐圭璐熻矗瑙f瀽浠诲姟閰嶇疆骞跺箓绛夊彂鍒搞 + */ + public void sendTaskReward(String userId, String regionId, String taskCode, String type, String sourceId, String remark) { + Map msg = new HashMap<>(8); + msg.put("userId", userId); + msg.put("regionId", regionId); + msg.put("taskCode", taskCode); + msg.put("type", type); + msg.put("sourceId", sourceId); + msg.put("remark", remark); + try { + rabbitTemplate.convertAndSend(PlanetMqConfig.PLANET_EXCHANGE, PlanetMqConfig.TICKET_GRANT_ROUTING, JSON.toJSONString(msg)); + log.info("[鐧藉珫鏄熺悆MQ] 宸叉姇閫掑彂鍒告秷鎭 userId={}, task={}, sourceId={}", userId, taskCode, sourceId); + } catch (Exception e) { + // 鎶曢掑け璐ヤ粎璁板綍锛岀粷涓嶅奖鍝嶄富涓氬姟 + log.warn("[鐧藉珫鏄熺悆MQ] 鍙戝埜娑堟伅鎶曢掑け璐 userId={}, task={}, {}", userId, taskCode, e.getMessage()); + } + } + + /** + * 鎶曢掍竴鏉″揩璁敓鎴愭秷鎭 + */ + public void sendNews(String regionId, String type, String content) { + Map msg = new HashMap<>(4); + msg.put("regionId", regionId); + msg.put("type", type); + msg.put("content", content); + try { + rabbitTemplate.convertAndSend(PlanetMqConfig.PLANET_EXCHANGE, PlanetMqConfig.NEWS_ROUTING, JSON.toJSONString(msg)); + } catch (Exception e) { + log.warn("[鐧藉珫鏄熺悆MQ] 蹇娑堟伅鎶曢掑け璐 regionId={}, {}", regionId, e.getMessage()); + } + } +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetBoxResultVo.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetBoxResultVo.java new file mode 100644 index 00000000..9ab3428d --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetBoxResultVo.java @@ -0,0 +1,34 @@ +package cc.hiver.mall.planet.pojo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; + +/** + * 鐧藉珫鏄熺悆-瀹濈寮鍚粨鏋 + * + * @author hiver + */ +@Data +@ApiModel(value = "鐧藉珫鏄熺悆-瀹濈寮鍚粨鏋") +public class PlanetBoxResultVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "濂栧姳绫诲瀷 ticket鍒/buff澧炵泭") + private String rewardType; + + @ApiModelProperty(value = "鑾峰緱鍒告暟閲(ticket鏃)") + private Integer ticketCount; + + @ApiModelProperty(value = "BUFF绫诲瀷(buff鏃)") + private String buffType; + + @ApiModelProperty(value = "濂栧姳鍚嶇О") + private String rewardName; + + @ApiModelProperty(value = "鎻愮ず鏂囨") + private String message; +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetBuffVo.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetBuffVo.java new file mode 100644 index 00000000..70579876 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetBuffVo.java @@ -0,0 +1,51 @@ +package cc.hiver.mall.planet.pojo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + * 鐧藉珫鏄熺悆-BUFF椤(鍚綋鍓嶆槸鍚︾敓鏁) + * + * @author hiver + */ +@Data +@ApiModel(value = "鐧藉珫鏄熺悆-BUFF椤") +public class PlanetBuffVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "BUFF閰嶇疆id") + private String id; + + @ApiModelProperty(value = "绫诲瀷") + private String type; + + @ApiModelProperty(value = "鍚嶇О") + private String name; + + @ApiModelProperty(value = "鎻忚堪") + private String description; + + @ApiModelProperty(value = "鍥炬爣") + private String icon; + + @ApiModelProperty(value = "娑堣楀埜鏁伴噺") + private Integer costTickets; + + @ApiModelProperty(value = "鎸佺画灏忔椂") + private Integer durationHours; + + @ApiModelProperty(value = "鏁堟灉鍊") + private BigDecimal effectValue; + + @ApiModelProperty(value = "褰撳墠鏄惁鐢熸晥") + private Boolean active; + + @ApiModelProperty(value = "褰撳墠鐢熸晥鍒版湡鏃堕棿") + private Date activeEndTime; +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetHomeVo.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetHomeVo.java new file mode 100644 index 00000000..cf781c52 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetHomeVo.java @@ -0,0 +1,83 @@ +package cc.hiver.mall.planet.pojo; + +import cc.hiver.mall.planet.entity.PlanetNews; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; + +/** + * 鐧藉珫鏄熺悆-棣栭〉鑱氬悎鏁版嵁 + * + * @author hiver + */ +@Data +@ApiModel(value = "鐧藉珫鏄熺悆-棣栭〉鑱氬悎鏁版嵁") +public class PlanetHomeVo implements Serializable { + + private static final long serialVersionUID = 1L; + + // ---------- 瀹囧畽Header ---------- + @ApiModelProperty(value = "鏈湡濂栭噾姹") + private BigDecimal poolAmount; + + @ApiModelProperty(value = "寮濂栨椂闂") + private Date drawTime; + + @ApiModelProperty(value = "璺濈寮濂栧墿浣欐绉") + private Long countdownMillis; + + @ApiModelProperty(value = "鏈湡鍙備笌浜烘暟") + private Integer joinCount; + + @ApiModelProperty(value = "鏈熷彿") + private String periodNo; + + // ---------- 鎴戠殑鏄熺悆涓績 ---------- + @ApiModelProperty(value = "鎴戠殑鍒告暟閲") + private Integer myTicketCount; + + @ApiModelProperty(value = "鎴戠殑鎺掑悕(0鏈笂姒)") + private Integer myRankNo; + + @ApiModelProperty(value = "鏄电О") + private String nickname; + + @ApiModelProperty(value = "澶村儚") + private String avatar; + + @ApiModelProperty(value = "杩炵画绛惧埌澶╂暟") + private Integer consecutiveSignDays; + + @ApiModelProperty(value = "浠婃棩鏄惁宸茬鍒") + private Boolean signedToday; + + @ApiModelProperty(value = "浠婃棩鍏嶈垂瀹濈鏄惁鍙紑") + private Boolean boxAvailable; + + @ApiModelProperty(value = "浠婃棩鍓╀綑杩芥崟娆℃暟") + private Integer remainHunt; + + @ApiModelProperty(value = "绛夌骇(鍗遍櫓绛夌骇)") + private String level; + + @ApiModelProperty(value = "鎴戝綋鍓嶇敓鏁堢殑BUFF") + private List myBuffs; + + // ---------- 鍚勬澘鍧 ---------- + @ApiModelProperty(value = "浠诲姟鍒楄〃") + private List tasks; + + @ApiModelProperty(value = "閫氱級姒淭OP10") + private List rankList; + + @ApiModelProperty(value = "BUFF鍟嗗簵") + private List buffShop; + + @ApiModelProperty(value = "鏄熺悆蹇") + private List newsList; +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetHuntResultVo.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetHuntResultVo.java new file mode 100644 index 00000000..a8ede5e9 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetHuntResultVo.java @@ -0,0 +1,40 @@ +package cc.hiver.mall.planet.pojo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; + +/** + * 鐧藉珫鏄熺悆-杩芥崟缁撴灉 + * + * @author hiver + */ +@Data +@ApiModel(value = "鐧藉珫鏄熺悆-杩芥崟缁撴灉") +public class PlanetHuntResultVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "缁撴灉 success缂磋幏/shield瀵规柟鎶ょ浘/fail澶辫触") + private String result; + + @ApiModelProperty(value = "缂磋幏鍒") + private Integer gainTickets; + + @ApiModelProperty(value = "鎮祻棰濆鍒") + private Integer bountyTickets; + + @ApiModelProperty(value = "鏈鍚堣鑾峰緱鍒") + private Integer totalGain; + + @ApiModelProperty(value = "鐩爣鏄电О") + private String targetName; + + @ApiModelProperty(value = "浠婃棩鍓╀綑杩芥崟娆℃暟") + private Integer remainHunt; + + @ApiModelProperty(value = "鎻愮ず鏂囨") + private String message; +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetQuery.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetQuery.java new file mode 100644 index 00000000..fa4df10b --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetQuery.java @@ -0,0 +1,52 @@ +package cc.hiver.mall.planet.pojo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; + +/** + * 鐧藉珫鏄熺悆-App绔氱敤璇锋眰鍙傛暟 + * + * @author hiver + */ +@Data +@ApiModel(value = "鐧藉珫鏄熺悆-App绔氱敤璇锋眰鍙傛暟") +public class PlanetQuery implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "鐢ㄦ埛id") + private String userId; + + @ApiModelProperty(value = "鍟嗗湀/鏍″尯id") + private String regionId; + + @ApiModelProperty(value = "鏄电О(棣栨杩涘叆鍐椾綑)") + private String nickname; + + @ApiModelProperty(value = "澶村儚(棣栨杩涘叆鍐椾綑)") + private String avatar; + + @ApiModelProperty(value = "瀛﹂櫌") + private String college; + + @ApiModelProperty(value = "鐩爣鐢ㄦ埛id(杩芥崟鐢)") + private String toUserId; + + @ApiModelProperty(value = "浠诲姟缂栫爜") + private String taskCode; + + @ApiModelProperty(value = "BUFF閰嶇疆id") + private String buffId; + + @ApiModelProperty(value = "涓璁板綍id") + private String winnerId; + + @ApiModelProperty(value = "椤电爜(浠1寮濮)") + private Integer pageNumber; + + @ApiModelProperty(value = "姣忛〉鏁伴噺") + private Integer pageSize; +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetRankItemVo.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetRankItemVo.java new file mode 100644 index 00000000..d79cde61 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetRankItemVo.java @@ -0,0 +1,55 @@ +package cc.hiver.mall.planet.pojo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; + +/** + * 鐧藉珫鏄熺悆-閫氱級姒滃崟椤 + * + * @author hiver + */ +@Data +@ApiModel(value = "鐧藉珫鏄熺悆-閫氱級姒滃崟椤") +public class PlanetRankItemVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "鎺掑悕") + private Integer rankNo; + + @ApiModelProperty(value = "鐢ㄦ埛id") + private String userId; + + @ApiModelProperty(value = "鏄电О") + private String nickname; + + @ApiModelProperty(value = "澶村儚") + private String avatar; + + @ApiModelProperty(value = "瀛﹂櫌") + private String college; + + @ApiModelProperty(value = "褰撳墠鍒告暟閲") + private Integer ticketCount; + + @ApiModelProperty(value = "鍗遍櫓绛夌骇 C/B/A/S/SSS") + private String dangerLevel; + + @ApiModelProperty(value = "鍗遍櫓绛夌骇鍚嶇О") + private String dangerLevelName; + + @ApiModelProperty(value = "杩炵画闇告澶╂暟") + private Integer rankKeepDays; + + @ApiModelProperty(value = "鎮祻棰濆鍒") + private Integer bountyTickets; + + @ApiModelProperty(value = "鏄惁寮鍚槻鎶ょ僵") + private Boolean shielded; + + @ApiModelProperty(value = "鏄惁鏄嚜宸") + private Boolean self; +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetTaskVo.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetTaskVo.java new file mode 100644 index 00000000..a4caebb6 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetTaskVo.java @@ -0,0 +1,46 @@ +package cc.hiver.mall.planet.pojo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; + +/** + * 鐧藉珫鏄熺悆-浠诲姟椤(鍚粖鏃ュ畬鎴愮姸鎬) + * + * @author hiver + */ +@Data +@ApiModel(value = "鐧藉珫鏄熺悆-浠诲姟椤") +public class PlanetTaskVo implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "浠诲姟缂栫爜") + private String code; + + @ApiModelProperty(value = "浠诲姟鍚嶇О") + private String name; + + @ApiModelProperty(value = "鎻忚堪") + private String description; + + @ApiModelProperty(value = "鍥炬爣") + private String icon; + + @ApiModelProperty(value = "濂栧姳鍒告暟閲") + private Integer rewardTickets; + + @ApiModelProperty(value = "姣忔棩涓婇檺 0涓嶉檺") + private Integer dailyLimit; + + @ApiModelProperty(value = "浠婃棩宸插畬鎴愭鏁") + private Integer todayCount; + + @ApiModelProperty(value = "浠婃棩鏄惁鍙鍙(绛惧埌绫)") + private Boolean canClaim; + + @ApiModelProperty(value = "鍔ㄤ綔绫诲瀷 claim鍙鍙/auto璁㈠崟鑷姩") + private String actionType; +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetAdminService.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetAdminService.java new file mode 100644 index 00000000..91d359bd --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetAdminService.java @@ -0,0 +1,65 @@ +package cc.hiver.mall.planet.service; + +import cc.hiver.core.common.vo.PageVo; +import cc.hiver.mall.planet.entity.*; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; + +import java.util.List; + +/** + * 鐧藉珫鏄熺悆-鍚庡彴绠$悊鏈嶅姟 + * + * @author hiver + */ +public interface PlanetAdminService { + + // 濂栨睜 + Page pagePools(PageVo pageVo, String regionId, Integer status); + + PlanetPool savePool(PlanetPool pool); + + void deletePool(String id); + + // 濂栭」 + List rewardsOfPool(String poolId); + + PlanetReward saveReward(PlanetReward reward); + + void deleteReward(String id); + + // 浠诲姟 + Page pageTasks(PageVo pageVo, String regionId); + + PlanetTask saveTask(PlanetTask task); + + void deleteTask(String id); + + // BUFF + Page pageBuffs(PageVo pageVo, String regionId); + + PlanetBuff saveBuff(PlanetBuff buff); + + void deleteBuff(String id); + + // 蹇 + Page pageNews(PageVo pageVo, String regionId); + + PlanetNews saveNews(PlanetNews news); + + void deleteNews(String id); + + // 鎺掕姒(鏌ョ湅) + Page pageRank(PageVo pageVo, String regionId); + + // 杩芥崟璁板綍 + Page pageHunts(PageVo pageVo, String regionId); + + // 寮濂栬褰 + Page pageDraws(PageVo pageVo, String regionId); + + // 涓璁板綍 + Page pageWinners(PageVo pageVo, String regionId, String periodNo); + + // 鎵嬪姩寮濂 + PlanetDrawRecord manualDraw(String poolId, String regionId); +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetBoxService.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetBoxService.java new file mode 100644 index 00000000..e7056e74 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetBoxService.java @@ -0,0 +1,21 @@ +package cc.hiver.mall.planet.service; + +import cc.hiver.mall.planet.pojo.PlanetBoxResultVo; + +/** + * 鐧藉珫鏄熺悆-骞歌繍瀹濈鏈嶅姟 + * + * @author hiver + */ +public interface PlanetBoxService { + + /** + * 寮鍚瘡鏃ュ厤璐瑰疂绠 + */ + PlanetBoxResultVo openDailyBox(String userId, String regionId); + + /** + * 浠婃棩鏄惁杩樺彲寮瀹濈 + */ + boolean boxAvailable(String userId, String regionId); +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetBuffService.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetBuffService.java new file mode 100644 index 00000000..686a6716 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetBuffService.java @@ -0,0 +1,63 @@ +package cc.hiver.mall.planet.service; + +import cc.hiver.mall.planet.entity.PlanetBuffRecord; +import cc.hiver.mall.planet.pojo.PlanetBuffVo; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * 鐧藉珫鏄熺悆-BUFF鏈嶅姟 + * + * @author hiver + */ +public interface PlanetBuffService { + + /** + * BUFF鍟嗗簵鍒楄〃(鍚綋鍓嶇敤鎴锋槸鍚︾敓鏁) + */ + List shopList(String userId, String regionId); + + /** + * 璐拱BUFF(娑堣楀埜骞剁敓鏁) + */ + PlanetBuffVo buyBuff(String userId, String regionId, String buffId); + + /** + * 褰撳墠鐢ㄦ埛鐢熸晥涓殑BUFF鍒楄〃 + */ + List activeBuffs(String userId); + + /** + * 鍒ゆ柇鏌愮被鍨婤UFF鏄惁鐢熸晥 + */ + boolean hasActiveBuff(String userId, String type); + + /** + * 缁欑敤鎴锋巿浜堜竴涓狟UFF(瀹濈/鑷姩闃叉姢浣跨敤) + */ + PlanetBuffRecord grantBuff(String userId, String regionId, String type, String source); + + /** + * 骞歌繍BUFF寮濂栨潈閲嶅姞鎴愮郴鏁(1+effectValue)锛屾棤鍒1 + */ + double luckyWeightFactor(String userId); + + /** + * 鎵归噺鏌ヨ澶氫釜鐢ㄦ埛褰撳墠鐢熸晥涓殑 BUFF 绫诲瀷闆嗗悎(涓娆℃煡搴擄紝鍐呭瓨缁勮) + * + * @param userIds 鐢ㄦ埛id闆嗗悎 + * @return Map<userId, Set<buffType>>锛屾棤鐢熸晥BUFF鐨勭敤鎴蜂笉鍦╩ap涓 + */ + Map> activeBuffTypes(Collection userIds); + + /** + * 鎵归噺鏌ヨ澶氫釜鐢ㄦ埛鐨勫垢杩怋UFF鏉冮噸绯绘暟(涓娆℃煡搴擄紝鍐呭瓨缁勮) + * + * @param userIds 鐢ㄦ埛id闆嗗悎 + * @return Map<userId, 绯绘暟(1+effectValue)>锛屾棤骞歌繍BUFF鐨勭敤鎴蜂笉鍦╩ap涓 + */ + Map luckyWeightFactors(Collection userIds); +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetDrawService.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetDrawService.java new file mode 100644 index 00000000..d463ded4 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetDrawService.java @@ -0,0 +1,52 @@ +package cc.hiver.mall.planet.service; + +import cc.hiver.mall.planet.entity.PlanetDrawRecord; +import cc.hiver.mall.planet.entity.PlanetDrawWinner; +import cc.hiver.mall.planet.entity.PlanetPool; + +import java.util.List; + +/** + * 鐧藉珫鏄熺悆-寮濂栨湇鍔 + * + * @author hiver + */ +public interface PlanetDrawService { + + /** + * 鑾峰彇褰撳墠杩涜涓殑濂栨睜(鏃犲垯鑷姩鍒涘缓榛樿濂栨睜) + */ + PlanetPool getCurrentPool(String regionId); + + /** + * 鎵ц寮濂(鍔犳潈鎶藉彇锛屽繀涓悕鍗) + * + * @return 寮濂栬褰 + */ + PlanetDrawRecord drawPool(String poolId); + + /** + * 鎵弿鎵鏈夊埌鐐规湭寮濂栫殑濂栨睜骞跺紑濂(瀹氭椂浠诲姟鐢) + */ + int drawDuePools(); + + /** + * 鏈杩戜竴鏈熷紑濂栬褰 + */ + PlanetDrawRecord latestDrawRecord(String regionId); + + /** + * 鏌愭寮濂栫殑涓鍚嶅崟 + */ + List winnersOfDraw(String drawId); + + /** + * 鎴戠殑涓璁板綍(浠呴檺鏈晢鍦) + */ + List myWinning(String userId, String regionId); + + /** + * 棰嗗彇涓濂栧姳(鏍¢獙鍟嗗湀涓鑷) + */ + void receive(String userId, String regionId, String winnerId); +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetHuntService.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetHuntService.java new file mode 100644 index 00000000..f874a317 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetHuntService.java @@ -0,0 +1,21 @@ +package cc.hiver.mall.planet.service; + +import cc.hiver.mall.planet.pojo.PlanetHuntResultVo; + +/** + * 鐧藉珫鏄熺悆-杩芥崟鏈嶅姟 + * + * @author hiver + */ +public interface PlanetHuntService { + + /** + * 鍙戣捣杩芥崟 + */ + PlanetHuntResultVo hunt(String fromUserId, String regionId, String toUserId); + + /** + * 浠婃棩鍓╀綑杩芥崟娆℃暟 + */ + int remainHunt(String userId); +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetNewsService.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetNewsService.java new file mode 100644 index 00000000..091d9a59 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetNewsService.java @@ -0,0 +1,23 @@ +package cc.hiver.mall.planet.service; + +import cc.hiver.mall.planet.entity.PlanetNews; + +import java.util.List; + +/** + * 鐧藉珫鏄熺悆-鏄熺悆蹇鏈嶅姟 + * + * @author hiver + */ +public interface PlanetNewsService { + + /** + * 鏂板蹇 + */ + void addNews(String regionId, String type, String content, String userId, String userName); + + /** + * 鑾峰彇鏈鏂板揩璁 + */ + List latest(String regionId, int limit); +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetRankService.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetRankService.java new file mode 100644 index 00000000..78d05260 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetRankService.java @@ -0,0 +1,29 @@ +package cc.hiver.mall.planet.service; + +import cc.hiver.mall.planet.entity.PlanetTicket; +import cc.hiver.mall.planet.pojo.PlanetRankItemVo; + +import java.util.List; + +/** + * 鐧藉珫鏄熺悆-閫氱級姒滄湇鍔 + * + * @author hiver + */ +public interface PlanetRankService { + + /** + * 鑾峰彇閫氱級姒淭OP N(鎺掗櫎闅愯韩BUFF鐢ㄦ埛) + */ + List rankTop(String regionId, int topN, String currentUserId); + + /** + * 鑾峰彇姒滃崟鍐呮煇鐢ㄦ埛鐨勫師濮嬪埜璁板綍(鐢ㄤ簬杩芥崟鎮祻璁$畻)锛屼笉鍦ㄦ杩斿洖null + */ + PlanetTicket getRankTarget(String regionId, String userId); + + /** + * 鐢ㄦ埛褰撳墠鎺掑悕(0鏈笂姒) + */ + int userRankNo(String regionId, String userId); +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetService.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetService.java new file mode 100644 index 00000000..d9293ee3 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetService.java @@ -0,0 +1,17 @@ +package cc.hiver.mall.planet.service; + +import cc.hiver.mall.planet.pojo.PlanetHomeVo; +import cc.hiver.mall.planet.pojo.PlanetQuery; + +/** + * 鐧藉珫鏄熺悆-棣栭〉鑱氬悎鏈嶅姟 + * + * @author hiver + */ +public interface PlanetService { + + /** + * 棣栭〉鑱氬悎鏁版嵁 + */ + PlanetHomeVo home(PlanetQuery query); +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetTaskService.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetTaskService.java new file mode 100644 index 00000000..d50e2bef --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetTaskService.java @@ -0,0 +1,41 @@ +package cc.hiver.mall.planet.service; + +import cc.hiver.mall.planet.entity.PlanetTask; +import cc.hiver.mall.planet.pojo.PlanetTaskVo; + +import java.util.List; + +/** + * 鐧藉珫鏄熺悆-浠诲姟鏈嶅姟 + * + * @author hiver + */ +public interface PlanetTaskService { + + /** + * 浠诲姟鍒楄〃(鍚粖鏃ュ畬鎴愮姸鎬) + */ + List listTasks(String userId, String regionId); + + /** + * 姣忔棩绛惧埌 + * + * @return 鑾峰緱鍒告暟閲 + */ + int sign(String userId, String regionId); + + /** + * 棰嗗彇浠诲姟濂栧姳(鐩墠浠呯鍒板彲涓诲姩棰嗗彇) + */ + int claim(String userId, String regionId, String taskCode); + + /** + * 鏍规嵁缂栫爜鑾峰彇鐢熸晥浠诲姟閰嶇疆 + */ + PlanetTask getTaskConfig(String regionId, String code); + + /** + * 浠婃棩鏄惁宸茬鍒 + */ + boolean signedToday(String userId, String regionId); +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetTicketService.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetTicketService.java new file mode 100644 index 00000000..989b4342 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetTicketService.java @@ -0,0 +1,50 @@ +package cc.hiver.mall.planet.service; + +import cc.hiver.mall.planet.entity.PlanetTicket; +import cc.hiver.mall.planet.entity.PlanetTicketLog; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; + +/** + * 鐧藉珫鏄熺悆-鏄熺悆鍒告湇鍔 + * + * @author hiver + */ +public interface PlanetTicketService { + + /** + * 鑾峰彇鎴栧垱寤虹敤鎴峰埜璁板綍(鑷姩琛ュ叏鏄电О澶村儚) + */ + PlanetTicket getOrCreate(String userId, String regionId, String nickname, String avatar, String college); + + /** + * 鏌ヨ鐢ㄦ埛鍒歌褰(涓嶅瓨鍦ㄨ繑鍥瀗ull) + */ + PlanetTicket getByUser(String userId, String regionId); + + /** + * 澧炲姞鏄熺悆鍒(鏀寔鍙屽岯UFF涓庡箓绛) + * + * @param baseCount 鍩虹鏁伴噺(BUFF鍓) + * @param type 鏉ユ簮绫诲瀷 + * @param sourceId 鏉ユ簮涓氬姟id(闈炵┖鏃跺仛骞傜瓑鍘婚噸) + * @return 瀹為檯澧炲姞鏁伴噺(0琛ㄧず琚箓绛夋嫤鎴) + */ + int addTickets(String userId, String regionId, int baseCount, String type, String sourceId, String remark); + + /** + * 鎵e噺鏄熺悆鍒(浣欓涓嶈冻鎶涘紓甯) + * + * @return 鎵e噺鍚庝綑棰 + */ + int deductTickets(String userId, String regionId, int count, String type, String sourceId, String remark); + + /** + * 褰撳墠鐢ㄦ埛鍦ㄥ晢鍦堝唴鐨勬帓鍚(0琛ㄧず鏈笂姒) + */ + int getRankNo(String regionId, String userId); + + /** + * 鍒嗛〉鏌ヨ鐢ㄦ埛鏄熺悆鍒告槑缁嗘祦姘(鎸夋椂闂村掑簭) + */ + Page pageLog(String userId, String regionId, Integer pageNumber, Integer pageSize); +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetAdminServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetAdminServiceImpl.java new file mode 100644 index 00000000..3d46e0fa --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetAdminServiceImpl.java @@ -0,0 +1,288 @@ +package cc.hiver.mall.planet.service.impl; + +import cc.hiver.core.common.exception.HiverException; +import cc.hiver.core.common.vo.PageVo; +import cc.hiver.mall.planet.entity.*; +import cc.hiver.mall.planet.mapper.*; +import cc.hiver.mall.planet.service.PlanetAdminService; +import cc.hiver.mall.planet.service.PlanetDrawService; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Date; +import java.util.List; +import java.util.UUID; + +/** + * 鐧藉珫鏄熺悆-鍚庡彴绠$悊鏈嶅姟瀹炵幇 + * + * @author hiver + */ +@Service +public class PlanetAdminServiceImpl implements PlanetAdminService { + + @Autowired + private PlanetPoolMapper poolMapper; + + @Autowired + private PlanetRewardMapper rewardMapper; + + @Autowired + private PlanetTaskMapper taskMapper; + + @Autowired + private PlanetBuffMapper buffMapper; + + @Autowired + private PlanetNewsMapper newsMapper; + + @Autowired + private PlanetTicketMapper ticketMapper; + + @Autowired + private PlanetHuntRecordMapper huntRecordMapper; + + @Autowired + private PlanetDrawRecordMapper drawRecordMapper; + + @Autowired + private PlanetDrawWinnerMapper drawWinnerMapper; + + @Autowired + private PlanetDrawService drawService; + + private static String genId() { + return UUID.randomUUID().toString().replace("-", ""); + } + + private Page page(PageVo pageVo) { + final int num = pageVo == null || pageVo.getPageNumber() <= 0 ? 1 : pageVo.getPageNumber(); + final int size = pageVo == null || pageVo.getPageSize() <= 0 ? 10 : pageVo.getPageSize(); + return new Page<>(num, size); + } + + @Override + public Page pagePools(PageVo pageVo, String regionId, Integer status) { + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + if (StringUtils.isNotEmpty(regionId)) { + qw.eq(PlanetPool::getRegionId, regionId); + } + if (status != null) { + qw.eq(PlanetPool::getStatus, status); + } + qw.orderByDesc(PlanetPool::getCreateTime); + return poolMapper.selectPage(page(pageVo), qw); + } + + @Override + public PlanetPool savePool(PlanetPool pool) { + if (StringUtils.isEmpty(pool.getId())) { + pool.setId(genId()); + if (pool.getStatus() == null) { + pool.setStatus(0); + } + if (pool.getJoinCount() == null) { + pool.setJoinCount(0); + } + if (pool.getTicketTotal() == null) { + pool.setTicketTotal(0); + } + if (pool.getWinnerCount() == null) { + pool.setWinnerCount(0); + } + pool.setCreateTime(new Date()); + pool.setUpdateTime(new Date()); + poolMapper.insert(pool); + } else { + pool.setUpdateTime(new Date()); + poolMapper.updateById(pool); + } + return pool; + } + + @Override + public void deletePool(String id) { + poolMapper.deleteById(id); + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.eq(PlanetReward::getPoolId, id); + rewardMapper.delete(qw); + } + + @Override + public List rewardsOfPool(String poolId) { + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.eq(PlanetReward::getPoolId, poolId).orderByAsc(PlanetReward::getSort); + return rewardMapper.selectList(qw); + } + + @Override + public PlanetReward saveReward(PlanetReward reward) { + if (StringUtils.isEmpty(reward.getId())) { + reward.setId(genId()); + reward.setCreateTime(new Date()); + rewardMapper.insert(reward); + } else { + rewardMapper.updateById(reward); + } + return reward; + } + + @Override + public void deleteReward(String id) { + rewardMapper.deleteById(id); + } + + @Override + public Page pageTasks(PageVo pageVo, String regionId) { + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + if (StringUtils.isNotEmpty(regionId)) { + qw.eq(PlanetTask::getRegionId, regionId); + } + qw.orderByAsc(PlanetTask::getSort); + return taskMapper.selectPage(page(pageVo), qw); + } + + @Override + public PlanetTask saveTask(PlanetTask task) { + if (StringUtils.isEmpty(task.getId())) { + task.setId(genId()); + if (task.getEnabled() == null) { + task.setEnabled(1); + } + task.setCreateTime(new Date()); + taskMapper.insert(task); + } else { + taskMapper.updateById(task); + } + return task; + } + + @Override + public void deleteTask(String id) { + taskMapper.deleteById(id); + } + + @Override + public Page pageBuffs(PageVo pageVo, String regionId) { + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + if (StringUtils.isNotEmpty(regionId)) { + qw.eq(PlanetBuff::getRegionId, regionId); + } + qw.orderByAsc(PlanetBuff::getSort); + return buffMapper.selectPage(page(pageVo), qw); + } + + @Override + public PlanetBuff saveBuff(PlanetBuff buff) { + if (StringUtils.isEmpty(buff.getId())) { + buff.setId(genId()); + if (buff.getEnabled() == null) { + buff.setEnabled(1); + } + buff.setCreateTime(new Date()); + buffMapper.insert(buff); + } else { + buffMapper.updateById(buff); + } + return buff; + } + + @Override + public void deleteBuff(String id) { + buffMapper.deleteById(id); + } + + @Override + public Page pageNews(PageVo pageVo, String regionId) { + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + if (StringUtils.isNotEmpty(regionId)) { + qw.eq(PlanetNews::getRegionId, regionId); + } + qw.orderByDesc(PlanetNews::getCreateTime); + return newsMapper.selectPage(page(pageVo), qw); + } + + @Override + public PlanetNews saveNews(PlanetNews news) { + if (StringUtils.isEmpty(news.getId())) { + news.setId(genId()); + if (news.getEnabled() == null) { + news.setEnabled(1); + } + if (news.getIsTop() == null) { + news.setIsTop(0); + } + news.setCreateTime(new Date()); + newsMapper.insert(news); + } else { + newsMapper.updateById(news); + } + return news; + } + + @Override + public void deleteNews(String id) { + newsMapper.deleteById(id); + } + + @Override + public Page pageRank(PageVo pageVo, String regionId) { + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + if (StringUtils.isNotEmpty(regionId)) { + qw.eq(PlanetTicket::getRegionId, regionId); + } + qw.orderByDesc(PlanetTicket::getTicketCount); + return ticketMapper.selectPage(page(pageVo), qw); + } + + @Override + public Page pageHunts(PageVo pageVo, String regionId) { + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + if (StringUtils.isNotEmpty(regionId)) { + qw.eq(PlanetHuntRecord::getRegionId, regionId); + } + qw.orderByDesc(PlanetHuntRecord::getCreateTime); + return huntRecordMapper.selectPage(page(pageVo), qw); + } + + @Override + public Page pageDraws(PageVo pageVo, String regionId) { + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + if (StringUtils.isNotEmpty(regionId)) { + qw.eq(PlanetDrawRecord::getRegionId, regionId); + } + qw.orderByDesc(PlanetDrawRecord::getDrawTime); + return drawRecordMapper.selectPage(page(pageVo), qw); + } + + @Override + public Page pageWinners(PageVo pageVo, String regionId, String periodNo) { + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + if (StringUtils.isNotEmpty(regionId)) { + qw.eq(PlanetDrawWinner::getRegionId, regionId); + } + if (StringUtils.isNotEmpty(periodNo)) { + qw.eq(PlanetDrawWinner::getPeriodNo, periodNo); + } + qw.orderByDesc(PlanetDrawWinner::getCreateTime); + return drawWinnerMapper.selectPage(page(pageVo), qw); + } + + @Override + public PlanetDrawRecord manualDraw(String poolId, String regionId) { + if (StringUtils.isEmpty(regionId)) { + throw new HiverException("缂哄皯鍟嗗湀鍙傛暟锛屽紑濂栦粎闄愭湰鍖哄煙鍐呰繘琛"); + } + final PlanetPool pool = poolMapper.selectById(poolId); + if (pool == null) { + throw new HiverException("濂栨睜涓嶅瓨鍦"); + } + if (!regionId.equals(pool.getRegionId())) { + throw new HiverException("鏃犳潈瀵瑰叾瀹冨晢鍦堢殑濂栨睜寮濂"); + } + return drawService.drawPool(poolId); + } +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetBoxServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetBoxServiceImpl.java new file mode 100644 index 00000000..0114885d --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetBoxServiceImpl.java @@ -0,0 +1,107 @@ +package cc.hiver.mall.planet.service.impl; + +import cc.hiver.core.common.exception.HiverException; +import cc.hiver.mall.planet.constant.PlanetConstant; +import cc.hiver.mall.planet.entity.PlanetTicket; +import cc.hiver.mall.planet.mapper.PlanetTicketMapper; +import cc.hiver.mall.planet.pojo.PlanetBoxResultVo; +import cc.hiver.mall.planet.service.PlanetBoxService; +import cc.hiver.mall.planet.service.PlanetBuffService; +import cc.hiver.mall.planet.service.PlanetNewsService; +import cc.hiver.mall.planet.service.PlanetTicketService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.LocalDate; +import java.util.Date; +import java.util.UUID; +import java.util.concurrent.ThreadLocalRandom; + +/** + * 鐧藉珫鏄熺悆-骞歌繍瀹濈鏈嶅姟瀹炵幇 + * + * @author hiver + */ +@Service +public class PlanetBoxServiceImpl implements PlanetBoxService { + + @Autowired + private PlanetTicketService ticketService; + + @Autowired + private PlanetTicketMapper ticketMapper; + + @Autowired + private PlanetBuffService buffService; + + @Autowired + private PlanetNewsService newsService; + + @Override + public PlanetBoxResultVo openDailyBox(String userId, String regionId) { + final PlanetTicket ticket = ticketService.getOrCreate(userId, regionId, null, null, null); + final LocalDate today = LocalDate.now(); + if (ticket.getBoxOpenedDate() != null && ticket.getBoxOpenedDate().isEqual(today)) { + throw new HiverException("浠婃棩瀹濈宸插紑鍚紝鏄庡ぉ鍐嶆潵"); + } + // 鏍囪宸插紑 + ticket.setBoxOpenedDate(today); + ticket.setUpdateTime(new Date()); + ticketMapper.updateById(ticket); + + // 鎶藉彇濂栧姳锛氬姞鏉冮殢鏈 + // 1鍒50% / 2鍒22% / 5鍒8% / 骞歌繍BUFF6% / 闃叉姢BUFF6% / 鍙屽岯UFF5% / 鎺犲ずBUFF3% + final int roll = ThreadLocalRandom.current().nextInt(100); + final PlanetBoxResultVo vo = new PlanetBoxResultVo(); + if (roll < 50) { + grantTicket(userId, regionId, 1, vo, "骞歌繍瀹濈寮鍑 1 寮犳槦鐞冨埜"); + } else if (roll < 72) { + grantTicket(userId, regionId, 2, vo, "骞歌繍瀹濈寮鍑 2 寮犳槦鐞冨埜"); + } else if (roll < 80) { + grantTicket(userId, regionId, 5, vo, "骞歌繍瀹濈寮鍑 5 寮犳槦鐞冨埜"); + } else if (roll < 86) { + grantBuff(userId, regionId, PlanetConstant.BUFF_LUCKY, "骞歌繍鏄熻景", vo); + } else if (roll < 92) { + grantBuff(userId, regionId, PlanetConstant.BUFF_SHIELD, "鏄熼檯闃叉姢缃", vo); + } else if (roll < 97) { + grantBuff(userId, regionId, PlanetConstant.BUFF_DOUBLE, "鍙屽嶈兘閲", vo); + } else { + grantBuff(userId, regionId, PlanetConstant.BUFF_HUNT, "杩界寧闆疯揪", vo); + } + + newsService.addNews(regionId, PlanetConstant.NEWS_BOX, + safeName(ticket.getNickname()) + " 骞歌繍寮鍚疂绠憋紝" + vo.getRewardName(), + userId, ticket.getNickname()); + return vo; + } + + @Override + public boolean boxAvailable(String userId, String regionId) { + final PlanetTicket ticket = ticketService.getByUser(userId, regionId); + if (ticket == null || ticket.getBoxOpenedDate() == null) { + return true; + } + return !ticket.getBoxOpenedDate().isEqual(LocalDate.now()); + } + + private void grantTicket(String userId, String regionId, int count, PlanetBoxResultVo vo, String name) { + ticketService.addTickets(userId, regionId, count, PlanetConstant.TICKET_TYPE_BOX, + UUID.randomUUID().toString().replace("-", ""), "瀹濈濂栧姳"); + vo.setRewardType("ticket"); + vo.setTicketCount(count); + vo.setRewardName("鑾峰緱 " + count + " 寮犳槦鐞冨埜"); + vo.setMessage(name); + } + + private void grantBuff(String userId, String regionId, String type, String name, PlanetBoxResultVo vo) { + buffService.grantBuff(userId, regionId, type, "box"); + vo.setRewardType("buff"); + vo.setBuffType(type); + vo.setRewardName("鑾峰緱銆" + name + "銆嶅鐩"); + vo.setMessage("骞歌繍瀹濈寮鍑恒" + name + "銆嶅鐩"); + } + + private String safeName(String name) { + return name == null || name.isEmpty() ? "绁炵鍚屽" : name; + } +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetBuffServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetBuffServiceImpl.java new file mode 100644 index 00000000..b7706291 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetBuffServiceImpl.java @@ -0,0 +1,276 @@ +package cc.hiver.mall.planet.service.impl; + +import cc.hiver.core.common.exception.HiverException; +import cc.hiver.mall.planet.constant.PlanetConstant; +import cc.hiver.mall.planet.entity.PlanetBuff; +import cc.hiver.mall.planet.entity.PlanetBuffRecord; +import cc.hiver.mall.planet.mapper.PlanetBuffMapper; +import cc.hiver.mall.planet.mapper.PlanetBuffRecordMapper; +import cc.hiver.mall.planet.pojo.PlanetBuffVo; +import cc.hiver.mall.planet.service.PlanetBuffService; +import cc.hiver.mall.planet.service.PlanetTicketService; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.util.*; + +/** + * 鐧藉珫鏄熺悆-BUFF鏈嶅姟瀹炵幇 + * + * @author hiver + */ +@Service +public class PlanetBuffServiceImpl implements PlanetBuffService { + + @Autowired + private PlanetBuffMapper buffMapper; + + @Autowired + private PlanetBuffRecordMapper buffRecordMapper; + + @Autowired + private PlanetTicketService ticketService; + + @Override + public List shopList(String userId, String regionId) { + final List buffs = listEnabledBuffs(regionId); + final List actives = activeBuffs(userId); + final List list = new ArrayList<>(); + for (PlanetBuff buff : buffs) { + final PlanetBuffVo vo = toVo(buff); + for (PlanetBuffRecord r : actives) { + if (r.getType() != null && r.getType().equals(buff.getType())) { + vo.setActive(true); + vo.setActiveEndTime(r.getEndTime()); + break; + } + } + list.add(vo); + } + return list; + } + + @Override + public PlanetBuffVo buyBuff(String userId, String regionId, String buffId) { + final PlanetBuff buff = buffMapper.selectById(buffId); + if (buff == null || buff.getEnabled() == null || buff.getEnabled() != 1) { + throw new HiverException("璇UFF涓嶅瓨鍦ㄦ垨宸蹭笅鏋"); + } + if (hasActiveBuff(userId, buff.getType())) { + throw new HiverException("璇ュ鐩婃鍦ㄧ敓鏁堜腑锛岃鍕块噸澶嶈喘涔"); + } + if (buff.getCostTickets() != null && buff.getCostTickets() > 0) { + ticketService.deductTickets(userId, regionId, buff.getCostTickets(), + PlanetConstant.TICKET_TYPE_BUFF, buff.getId() + ":" + System.currentTimeMillis(), + "璐拱BUFF-" + buff.getName()); + } + final PlanetBuffRecord record = grantBuffInner(userId, regionId, buff, "buy"); + final PlanetBuffVo vo = toVo(buff); + vo.setActive(true); + vo.setActiveEndTime(record.getEndTime()); + return vo; + } + + @Override + public List activeBuffs(String userId) { + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.eq(PlanetBuffRecord::getUserId, userId) + .eq(PlanetBuffRecord::getStatus, PlanetConstant.BUFF_STATUS_ACTIVE) + .gt(PlanetBuffRecord::getEndTime, new Date()) + .orderByDesc(PlanetBuffRecord::getEndTime); + return buffRecordMapper.selectList(qw); + } + + @Override + public boolean hasActiveBuff(String userId, String type) { + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.eq(PlanetBuffRecord::getUserId, userId) + .eq(PlanetBuffRecord::getType, type) + .eq(PlanetBuffRecord::getStatus, PlanetConstant.BUFF_STATUS_ACTIVE) + .gt(PlanetBuffRecord::getEndTime, new Date()); + return buffRecordMapper.selectCount(qw) > 0; + } + + @Override + public PlanetBuffRecord grantBuff(String userId, String regionId, String type, String source) { + final PlanetBuff buff = findBuffByType(regionId, type); + if (buff == null) { + final PlanetBuff temp = new PlanetBuff(); + temp.setType(type); + temp.setDurationHours(PlanetConstant.AUTO_SHIELD_HOURS); + temp.setEffectValue(BigDecimal.ZERO); + return grantBuffInner(userId, regionId, temp, source); + } + return grantBuffInner(userId, regionId, buff, source); + } + + @Override + public double luckyWeightFactor(String userId) { + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.eq(PlanetBuffRecord::getUserId, userId) + .eq(PlanetBuffRecord::getType, PlanetConstant.BUFF_LUCKY) + .eq(PlanetBuffRecord::getStatus, PlanetConstant.BUFF_STATUS_ACTIVE) + .gt(PlanetBuffRecord::getEndTime, new Date()) + .orderByDesc(PlanetBuffRecord::getEffectValue) + .last("limit 1"); + final List list = buffRecordMapper.selectList(qw); + if (list != null && !list.isEmpty() && list.get(0).getEffectValue() != null) { + return 1.0 + list.get(0).getEffectValue().doubleValue(); + } + return 1.0; + } + + @Override + public Map> activeBuffTypes(Collection userIds) { + final Map> map = new HashMap<>(); + if (userIds == null || userIds.isEmpty()) { + return map; + } + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.in(PlanetBuffRecord::getUserId, userIds) + .eq(PlanetBuffRecord::getStatus, PlanetConstant.BUFF_STATUS_ACTIVE) + .gt(PlanetBuffRecord::getEndTime, new Date()) + .select(PlanetBuffRecord::getUserId, PlanetBuffRecord::getType); + final List records = buffRecordMapper.selectList(qw); + for (PlanetBuffRecord r : records) { + map.computeIfAbsent(r.getUserId(), k -> new HashSet<>()).add(r.getType()); + } + return map; + } + + @Override + public Map luckyWeightFactors(Collection userIds) { + final Map map = new HashMap<>(); + if (userIds == null || userIds.isEmpty()) { + return map; + } + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.in(PlanetBuffRecord::getUserId, userIds) + .eq(PlanetBuffRecord::getType, PlanetConstant.BUFF_LUCKY) + .eq(PlanetBuffRecord::getStatus, PlanetConstant.BUFF_STATUS_ACTIVE) + .gt(PlanetBuffRecord::getEndTime, new Date()) + .select(PlanetBuffRecord::getUserId, PlanetBuffRecord::getEffectValue); + final List records = buffRecordMapper.selectList(qw); + for (PlanetBuffRecord r : records) { + if (r.getEffectValue() == null) { + continue; + } + final double factor = 1.0 + r.getEffectValue().doubleValue(); + // 鍚岀被鍨嬪彲鑳藉鏉★紝鍙栨渶澶у姞鎴 + map.merge(r.getUserId(), factor, Math::max); + } + return map; + } + + private PlanetBuffVo toVo(PlanetBuff buff) { + final PlanetBuffVo vo = new PlanetBuffVo(); + vo.setId(buff.getId()); + vo.setType(buff.getType()); + vo.setName(buff.getName()); + vo.setDescription(buff.getDescription()); + vo.setIcon(buff.getIcon()); + vo.setCostTickets(buff.getCostTickets()); + vo.setDurationHours(buff.getDurationHours()); + vo.setEffectValue(buff.getEffectValue()); + vo.setActive(false); + return vo; + } + + private PlanetBuffRecord grantBuffInner(String userId, String regionId, PlanetBuff buff, String source) { + final PlanetBuffRecord record = new PlanetBuffRecord(); + record.setId(UUID.randomUUID().toString().replace("-", "")); + record.setUserId(userId); + record.setRegionId(regionId); + record.setBuffId(buff.getId()); + record.setType(buff.getType()); + record.setEffectValue(buff.getEffectValue() == null ? BigDecimal.ZERO : buff.getEffectValue()); + final Date now = new Date(); + record.setStartTime(now); + final int hours = buff.getDurationHours() == null ? PlanetConstant.AUTO_SHIELD_HOURS : buff.getDurationHours(); + record.setEndTime(new Date(now.getTime() + (long) hours * 3600 * 1000)); + record.setStatus(PlanetConstant.BUFF_STATUS_ACTIVE); + record.setSource(source); + record.setCreateTime(now); + buffRecordMapper.insert(record); + return record; + } + + private PlanetBuff findBuffByType(String regionId, String type) { + // 鍟嗗湀寮洪殧绂伙細浠呮煡鏈晢鍦圔UFF閰嶇疆锛屼笉鍐嶅洖閫鍏ㄥ眬榛樿 + if (StringUtils.isEmpty(regionId)) { + return null; + } + PlanetBuff buff = selectRegionBuff(regionId, type); + if (buff == null) { + seedDefaultBuffs(regionId); + buff = selectRegionBuff(regionId, type); + } + return buff; + } + + private PlanetBuff selectRegionBuff(String regionId, String type) { + final LambdaQueryWrapper rq = new LambdaQueryWrapper<>(); + rq.eq(PlanetBuff::getType, type).eq(PlanetBuff::getEnabled, 1) + .eq(PlanetBuff::getRegionId, regionId).last("limit 1"); + return buffMapper.selectOne(rq); + } + + private List listEnabledBuffs(String regionId) { + // 鍟嗗湀寮洪殧绂伙細浠呰繑鍥炴湰鍟嗗湀BUFF锛岄娆¤闂嚜鍔ㄥ垵濮嬪寲榛樿BUFF + if (StringUtils.isEmpty(regionId)) { + return new ArrayList<>(); + } + List list = selectRegionBuffs(regionId); + if (list.isEmpty()) { + seedDefaultBuffs(regionId); + list = selectRegionBuffs(regionId); + } + return list; + } + + private List selectRegionBuffs(String regionId) { + final LambdaQueryWrapper rq = new LambdaQueryWrapper<>(); + rq.eq(PlanetBuff::getRegionId, regionId).eq(PlanetBuff::getEnabled, 1) + .orderByAsc(PlanetBuff::getSort); + final List list = buffMapper.selectList(rq); + return list == null ? new ArrayList<>() : list; + } + + /** + * 涓烘寚瀹氬晢鍦堝垵濮嬪寲榛樿BUFF閰嶇疆(骞傜瓑锛氭寜 type 瀛樺湪鍒欒烦杩)銆 + */ + private void seedDefaultBuffs(String regionId) { + if (StringUtils.isEmpty(regionId)) { + return; + } + seedBuff(regionId, PlanetConstant.BUFF_DOUBLE, "鍙屽嶈兘閲", "24灏忔椂鍐呰幏寰楁槦鐞冨埜缈诲", 5, 24, new BigDecimal("2.00"), 1); + seedBuff(regionId, PlanetConstant.BUFF_SHIELD, "鏄熼檯闃叉姢缃", "24灏忔椂鍐呭厤鐤拷鎹(鍏诲彧灏忔澗榧犺鍗)", 8, 24, BigDecimal.ZERO, 2); + seedBuff(regionId, PlanetConstant.BUFF_LUCKY, "骞歌繍鏄熻景", "寮濂栨潈閲 +20%", 6, 24, new BigDecimal("0.20"), 3); + seedBuff(regionId, PlanetConstant.BUFF_HUNT, "杩界寧闆疯揪", "杩芥崟鎴愬姛鐜囨彁鍗", 4, 24, new BigDecimal("0.30"), 4); + seedBuff(regionId, PlanetConstant.BUFF_STEALTH, "闅愯韩鏂楃", "涓嶅嚭鐜板湪閫氱級姒", 6, 24, BigDecimal.ZERO, 5); + } + + private void seedBuff(String regionId, String type, String name, String desc, int cost, int hours, BigDecimal effect, int sort) { + final LambdaQueryWrapper exist = new LambdaQueryWrapper<>(); + exist.eq(PlanetBuff::getRegionId, regionId).eq(PlanetBuff::getType, type); + if (buffMapper.selectCount(exist) > 0) { + return; + } + final PlanetBuff buff = new PlanetBuff(); + buff.setId(UUID.randomUUID().toString().replace("-", "")); + buff.setRegionId(regionId); + buff.setType(type); + buff.setName(name); + buff.setDescription(desc); + buff.setCostTickets(cost); + buff.setDurationHours(hours); + buff.setEffectValue(effect); + buff.setSort(sort); + buff.setEnabled(1); + buff.setCreateTime(new Date()); + buffMapper.insert(buff); + } +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetDrawServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetDrawServiceImpl.java new file mode 100644 index 00000000..e086c64d --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetDrawServiceImpl.java @@ -0,0 +1,393 @@ +package cc.hiver.mall.planet.service.impl; + +import cc.hiver.core.common.exception.HiverException; +import cc.hiver.mall.planet.constant.PlanetConstant; +import cc.hiver.mall.planet.entity.*; +import cc.hiver.mall.planet.mapper.*; +import cc.hiver.mall.planet.service.PlanetBuffService; +import cc.hiver.mall.planet.service.PlanetDrawService; +import cc.hiver.mall.planet.service.PlanetNewsService; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; +import java.util.stream.Collectors; + +/** + * 鐧藉珫鏄熺悆-寮濂栨湇鍔″疄鐜 + * + * @author hiver + */ +@Slf4j +@Service +public class PlanetDrawServiceImpl implements PlanetDrawService { + + /** 姣忔棩寮濂栨椂鍒(24灏忔椂鍒)锛屽埌鐐圭敱瀹氭椂浠诲姟鑷姩寮濂栵紝姣忔棩涓鎶 */ + private static final int DAILY_DRAW_HOUR = 22; + + @Autowired + private PlanetPoolMapper poolMapper; + + @Autowired + private PlanetRewardMapper rewardMapper; + + @Autowired + private PlanetTicketMapper ticketMapper; + + @Autowired + private PlanetDrawRecordMapper drawRecordMapper; + + @Autowired + private PlanetDrawWinnerMapper drawWinnerMapper; + + @Autowired + private PlanetBuffService buffService; + + @Autowired + private PlanetNewsService newsService; + + /** + * 鎶藉鍔熻兘寮哄埗鎸夊晢鍦堥殧绂伙細缂哄皯 regionId 鐩存帴鎷掔粷锛屾潨缁濊法鍖哄煙寮濂/鏌ヨ銆 + */ + private void requireRegion(String regionId) { + if (StringUtils.isEmpty(regionId)) { + throw new HiverException("缂哄皯鍟嗗湀鍙傛暟锛屾娊濂栦粎闄愭湰鍖哄煙鍐呰繘琛"); + } + } + + @Override + public PlanetPool getCurrentPool(String regionId) { + requireRegion(regionId); + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.eq(PlanetPool::getRegionId, regionId) + .eq(PlanetPool::getStatus, PlanetConstant.POOL_STATUS_RUNNING) + .orderByDesc(PlanetPool::getCreateTime) + .last("limit 1"); + PlanetPool pool = poolMapper.selectOne(qw); + if (pool == null) { + pool = createDefaultPool(regionId); + } + return pool; + } + + private PlanetPool createDefaultPool(String regionId) { + final Date now = new Date(); + final PlanetPool pool = new PlanetPool(); + pool.setId(UUID.randomUUID().toString().replace("-", "")); + pool.setRegionId(regionId); + pool.setPeriodNo(genPeriodNo()); + pool.setTitle("鐧藉珫鏄熺悆路鏈湡鐡滃垎"); + pool.setPoolAmount(new BigDecimal("88.88")); + pool.setDrawTime(nextDrawTime(now)); + pool.setJoinCount(0); + pool.setTicketTotal(0); + pool.setWinnerCount(0); + pool.setStatus(PlanetConstant.POOL_STATUS_RUNNING); + pool.setRemark("姣忔棩鎸夋槦鐞冨埜鍔犳潈鐡滃垎濂栭噾姹"); + pool.setCreateTime(now); + pool.setUpdateTime(now); + poolMapper.insert(pool); + // 榛樿濂栭」 + createDefaultRewards(pool); + return pool; + } + + private void createDefaultRewards(PlanetPool pool) { + addReward(pool, 1, "涓绛夊", new BigDecimal("28.00"), 1, 1); + addReward(pool, 2, "浜岀瓑濂", new BigDecimal("8.80"), 2, 2); + addReward(pool, 3, "涓夌瓑濂", new BigDecimal("1.00"), 10, 3); + addReward(pool, 4, "骞歌繍濂", new BigDecimal("0.50"), 50, 4); + } + + private void addReward(PlanetPool pool, int level, String name, BigDecimal amount, int quota, int sort) { + final PlanetReward reward = new PlanetReward(); + reward.setId(UUID.randomUUID().toString().replace("-", "")); + reward.setPoolId(pool.getId()); + reward.setRegionId(pool.getRegionId()); + reward.setLevel(level); + reward.setLevelName(name); + reward.setRewardType(0); + reward.setAmount(amount); + reward.setQuota(quota); + reward.setSort(sort); + reward.setCreateTime(new Date()); + rewardMapper.insert(reward); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public PlanetDrawRecord drawPool(String poolId) { + final PlanetPool pool = poolMapper.selectById(poolId); + if (pool == null) { + throw new HiverException("濂栨睜涓嶅瓨鍦"); + } + if (pool.getStatus() != null && pool.getStatus() == PlanetConstant.POOL_STATUS_DRAWN) { + throw new HiverException("璇ユ湡宸插紑濂"); + } + // 濂栨睜蹇呴』褰掑睘鏌愬晢鍦堬紝寮濂栧彧鍦ㄦ湰鍟嗗湀鍐呰繘琛 + requireRegion(pool.getRegionId()); + // 鍙備笌鑰咃細浠呮湰鍟嗗湀鍐呮寔鍒哥敤鎴 + final LambdaQueryWrapper tq = new LambdaQueryWrapper<>(); + tq.eq(PlanetTicket::getRegionId, pool.getRegionId()) + .gt(PlanetTicket::getTicketCount, 0); + final List participants = ticketMapper.selectList(tq); + + // 濂栭」鎸夊眰绾ф帓搴 + final LambdaQueryWrapper rq = new LambdaQueryWrapper<>(); + rq.eq(PlanetReward::getPoolId, poolId).orderByAsc(PlanetReward::getSort); + final List rewards = rewardMapper.selectList(rq); + + // 鎵归噺鏌ヨ鎵鏈夊弬涓庤呯殑骞歌繍绯绘暟锛屼竴娆℃煡搴擄紝閬垮厤寰幆閫愪釜鏌ヨ + final Set userIds = participants.stream().map(PlanetTicket::getUserId).collect(Collectors.toCollection(LinkedHashSet::new)); + final Map luckyMap = buffService.luckyWeightFactors(userIds); + + // 鏋勫缓鍔犳潈鍊欓(鏉冮噸= 鍒告暟閲 * 骞歌繍绯绘暟) + final List poutPool = new ArrayList<>(); + int ticketTotal = 0; + for (PlanetTicket t : participants) { + final double factor = luckyMap.getOrDefault(t.getUserId(), 1.0); + final double weight = t.getTicketCount() * factor; + poutPool.add(new Candidate(t, weight)); + ticketTotal += t.getTicketCount(); + } + + final Date now = new Date(); + // 寮濂栬褰 + final PlanetDrawRecord record = new PlanetDrawRecord(); + record.setId(UUID.randomUUID().toString().replace("-", "")); + record.setPoolId(pool.getId()); + record.setRegionId(pool.getRegionId()); + record.setPeriodNo(pool.getPeriodNo()); + record.setPoolAmount(pool.getPoolAmount()); + record.setJoinCount(participants.size()); + record.setTicketTotal(ticketTotal); + record.setStatus(1); + record.setDrawTime(now); + record.setCreateTime(now); + + int winnerCount = 0; + for (PlanetReward reward : rewards) { + final int quota = reward.getQuota() == null ? 0 : reward.getQuota(); + for (int i = 0; i < quota; i++) { + if (poutPoolEmpty(poutPool)) { + break; + } + final Candidate winner = pickWeighted(poutPoolUsable(poutPool)); + if (winner == null) { + break; + } + winner.win = true; + saveWinner(record, reward, winner.ticket, now); + winnerCount++; + } + } + record.setWinnerCount(winnerCount); + drawRecordMapper.insert(record); + + // 鏇存柊濂栨睜涓哄凡寮濂 + pool.setStatus(PlanetConstant.POOL_STATUS_DRAWN); + pool.setJoinCount(participants.size()); + pool.setTicketTotal(ticketTotal); + pool.setWinnerCount(winnerCount); + pool.setUpdateTime(now); + poolMapper.updateById(pool); + + // 蹇 + newsService.addNews(pool.getRegionId(), PlanetConstant.NEWS_DRAW, + "鏈湡濂栨睜 锟" + pool.getPoolAmount() + " 宸插紑濂栵紝" + winnerCount + " 浣嶅悓瀛︾摐鍒嗘垚鍔", + null, null); + + // 寮鍚笅涓鏈 + createNextPool(pool); + log.info("[鐧藉珫鏄熺悆] 寮濂栧畬鎴 poolId={}, 鍙備笌={}, 涓={}", poolId, participants.size(), winnerCount); + return record; + } + + private void createNextPool(PlanetPool prev) { + final Date now = new Date(); + final PlanetPool pool = new PlanetPool(); + pool.setId(UUID.randomUUID().toString().replace("-", "")); + pool.setRegionId(prev.getRegionId()); + pool.setPeriodNo(genPeriodNo()); + pool.setTitle(prev.getTitle()); + pool.setPoolAmount(prev.getPoolAmount()); + pool.setDrawTime(nextDrawTime(now)); + pool.setJoinCount(0); + pool.setTicketTotal(0); + pool.setWinnerCount(0); + pool.setStatus(PlanetConstant.POOL_STATUS_RUNNING); + pool.setRemark(prev.getRemark()); + pool.setCreateTime(now); + pool.setUpdateTime(now); + poolMapper.insert(pool); + // 澶嶅埗涓婃湡濂栭」閰嶇疆 + final LambdaQueryWrapper rq = new LambdaQueryWrapper<>(); + rq.eq(PlanetReward::getPoolId, prev.getId()).orderByAsc(PlanetReward::getSort); + for (PlanetReward r : rewardMapper.selectList(rq)) { + addReward(pool, r.getLevel(), r.getLevelName(), r.getAmount(), r.getQuota() == null ? 0 : r.getQuota(), r.getSort() == null ? 0 : r.getSort()); + } + } + + @Override + public int drawDuePools() { + // 鎵弿鎵鏈夊埌鐐规湭寮濂栫殑濂栨睜锛氭瘡涓姹犻兘褰掑睘鍞竴鏍″尯锛岄愪釜鐙珛寮濂栵紝 + // 鍚勬牎鍖哄弬涓庤/濂栭」/濂栭噾浜掍笉褰卞搷锛屽疄鐜扳滄寜鏍″尯鍒嗗埆寮濂栤濄 + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.eq(PlanetPool::getStatus, PlanetConstant.POOL_STATUS_RUNNING) + .le(PlanetPool::getDrawTime, new Date()); + final List due = poolMapper.selectList(qw); + int count = 0; + for (PlanetPool pool : due) { + // 闃插尽锛氭棤鏍″尯褰掑睘鐨勫姹犱笉鍙備笌寮濂栵紝閬垮厤璺ㄦ牎鍖 + if (StringUtils.isEmpty(pool.getRegionId())) { + log.warn("[鐧藉珫鏄熺悆] 璺宠繃鏃犳牎鍖哄姹 poolId={}, periodNo={}", pool.getId(), pool.getPeriodNo()); + continue; + } + try { + drawPool(pool.getId()); + count++; + log.info("[鐧藉珫鏄熺悆] 鏍″尯寮濂栧畬鎴 regionId={}, periodNo={}", pool.getRegionId(), pool.getPeriodNo()); + } catch (Exception e) { + log.error("[鐧藉珫鏄熺悆] 鏍″尯寮濂栧け璐 regionId={}, poolId={}, {}", pool.getRegionId(), pool.getId(), e.getMessage(), e); + } + } + return count; + } + + @Override + public PlanetDrawRecord latestDrawRecord(String regionId) { + requireRegion(regionId); + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.eq(PlanetDrawRecord::getRegionId, regionId) + .orderByDesc(PlanetDrawRecord::getDrawTime).last("limit 1"); + return drawRecordMapper.selectOne(qw); + } + + @Override + public List winnersOfDraw(String drawId) { + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.eq(PlanetDrawWinner::getDrawId, drawId).orderByAsc(PlanetDrawWinner::getRewardLevel); + return drawWinnerMapper.selectList(qw); + } + + @Override + public List myWinning(String userId, String regionId) { + requireRegion(regionId); + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.eq(PlanetDrawWinner::getUserId, userId) + .eq(PlanetDrawWinner::getRegionId, regionId) + .orderByDesc(PlanetDrawWinner::getCreateTime).last("limit 50"); + return drawWinnerMapper.selectList(qw); + } + + @Override + public void receive(String userId, String regionId, String winnerId) { + requireRegion(regionId); + final PlanetDrawWinner winner = drawWinnerMapper.selectById(winnerId); + if (winner == null || !userId.equals(winner.getUserId()) || !regionId.equals(winner.getRegionId())) { + throw new HiverException("涓璁板綍涓嶅瓨鍦"); + } + if (winner.getIsReceived() != null && winner.getIsReceived() == 1) { + throw new HiverException("宸查鍙栵紝璇峰嬁閲嶅鎿嶄綔"); + } + winner.setIsReceived(1); + winner.setReceivedTime(new Date()); + drawWinnerMapper.updateById(winner); + // TODO: 鐜伴噾濂栧姳鍙湪姝ゅ鎺ラ挶鍖呭叆璐︼紱浼樻儬鍒稿鍔卞彲瀵规帴鍙戝埜閫昏緫 + } + + private void saveWinner(PlanetDrawRecord record, PlanetReward reward, PlanetTicket ticket, Date now) { + final PlanetDrawWinner winner = new PlanetDrawWinner(); + winner.setId(UUID.randomUUID().toString().replace("-", "")); + winner.setDrawId(record.getId()); + winner.setPoolId(record.getPoolId()); + winner.setRegionId(record.getRegionId()); + winner.setPeriodNo(record.getPeriodNo()); + winner.setUserId(ticket.getUserId()); + winner.setUserName(ticket.getNickname()); + winner.setRewardLevel(reward.getLevel()); + winner.setLevelName(reward.getLevelName()); + winner.setRewardType(reward.getRewardType()); + winner.setAmount(reward.getAmount()); + winner.setCouponId(reward.getCouponId()); + winner.setIsReceived(0); + winner.setCreateTime(now); + drawWinnerMapper.insert(winner); + } + + private boolean poutPoolEmpty(List pool) { + for (Candidate c : pool) { + if (!c.win) { + return false; + } + } + return true; + } + + private List poutPoolUsable(List pool) { + final List usable = new ArrayList<>(); + for (Candidate c : pool) { + if (!c.win) { + usable.add(c); + } + } + return usable; + } + + private Candidate pickWeighted(List usable) { + if (usable.isEmpty()) { + return null; + } + double total = 0; + for (Candidate c : usable) { + total += Math.max(c.weight, 0.0001); + } + double r = ThreadLocalRandom.current().nextDouble() * total; + for (Candidate c : usable) { + r -= Math.max(c.weight, 0.0001); + if (r <= 0) { + return c; + } + } + return usable.get(usable.size() - 1); + } + + private String genPeriodNo() { + return "P" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); + } + + /** + * 璁$畻涓嬩竴娆″紑濂栨椂闂达細姣忔棩鍥哄畾 {@link #DAILY_DRAW_HOUR} 鐐瑰紑濂栵紝宸茶繃鍒欓『寤跺埌娆℃棩锛屽疄鐜版瘡鏃ヤ竴鎶姐 + */ + private Date nextDrawTime(Date from) { + final Calendar c = Calendar.getInstance(); + c.setTime(from); + c.set(Calendar.HOUR_OF_DAY, DAILY_DRAW_HOUR); + c.set(Calendar.MINUTE, 0); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + if (!c.getTime().after(from)) { + c.add(Calendar.DAY_OF_MONTH, 1); + } + return c.getTime(); + } + + /** 寮濂栧欓 */ + private static class Candidate { + private final PlanetTicket ticket; + private final double weight; + private boolean win; + + Candidate(PlanetTicket ticket, double weight) { + this.ticket = ticket; + this.weight = weight; + } + } +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetHuntServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetHuntServiceImpl.java new file mode 100644 index 00000000..9e74ad90 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetHuntServiceImpl.java @@ -0,0 +1,198 @@ +package cc.hiver.mall.planet.service.impl; + +import cc.hiver.core.common.exception.HiverException; +import cc.hiver.mall.planet.constant.PlanetConstant; +import cc.hiver.mall.planet.entity.PlanetBuffRecord; +import cc.hiver.mall.planet.entity.PlanetHuntRecord; +import cc.hiver.mall.planet.entity.PlanetTicket; +import cc.hiver.mall.planet.mapper.PlanetHuntRecordMapper; +import cc.hiver.mall.planet.pojo.PlanetHuntResultVo; +import cc.hiver.mall.planet.service.*; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.LocalDate; +import java.util.Date; +import java.util.UUID; +import java.util.concurrent.ThreadLocalRandom; + +/** + * 鐧藉珫鏄熺悆-杩芥崟鏈嶅姟瀹炵幇 + * + * @author hiver + */ +@Slf4j +@Service +public class PlanetHuntServiceImpl implements PlanetHuntService { + + /** 鍩虹杩芥崟鎴愬姛鐜 */ + private static final double BASE_SUCCESS_RATE = 0.8; + + @Autowired + private PlanetHuntRecordMapper huntRecordMapper; + + @Autowired + private PlanetTicketService ticketService; + + @Autowired + private PlanetRankService rankService; + + @Autowired + private PlanetBuffService buffService; + + @Autowired + private PlanetNewsService newsService; + + @Override + public PlanetHuntResultVo hunt(String fromUserId, String regionId, String toUserId) { + if (StringUtils.isEmpty(fromUserId) || StringUtils.isEmpty(toUserId)) { + throw new HiverException("鍙傛暟涓嶅畬鏁"); + } + if (fromUserId.equals(toUserId)) { + throw new HiverException("涓嶈兘杩芥崟鑷繁"); + } + final LocalDate today = LocalDate.now(); + // 浠婃棩杩芥崟娆℃暟鏍¢獙 + final int huntedToday = countTodayHunts(fromUserId, today); + if (huntedToday >= PlanetConstant.HUNT_DAILY_LIMIT) { + throw new HiverException("浠婃棩杩芥崟娆℃暟宸茬敤瀹岋紝鏄庡ぉ鍐嶆潵"); + } + final PlanetTicket from = ticketService.getOrCreate(fromUserId, regionId, null, null, null); + final PlanetTicket target = rankService.getRankTarget(regionId, toUserId); + if (target == null) { + throw new HiverException("鐩爣涓嶅瓨鍦"); + } + // 浠呭厑璁稿悓鍖哄煙浜掑姩 + if (StringUtils.isNotEmpty(from.getRegionId()) && StringUtils.isNotEmpty(target.getRegionId()) + && !from.getRegionId().equals(target.getRegionId())) { + throw new HiverException("鍙兘杩芥崟鍚屾牎鍖虹殑鍚屽"); + } + + final PlanetHuntResultVo vo = new PlanetHuntResultVo(); + vo.setTargetName(target.getNickname()); + vo.setGainTickets(0); + vo.setBountyTickets(0); + vo.setTotalGain(0); + + // 鐩爣闃叉姢缃╋細闃叉姢BUFF 鎴 浠婃棩宸茶杩芥崟鎴愬姛杈句笂闄 + final int targetHuntedSuccess = countTodayHuntedSuccess(toUserId, today); + final boolean shielded = buffService.hasActiveBuff(toUserId, PlanetConstant.BUFF_SHIELD) + || targetHuntedSuccess >= PlanetConstant.HUNTED_SUCCESS_LIMIT; + + String result; + if (shielded) { + result = PlanetConstant.HUNT_SHIELD; + vo.setMessage("鐩爣鍚姩浜嗘槦闄呴槻鎶ょ僵锛屾湰娆¤拷鎹曟湭鑳界即鑾"); + } else if (target.getTicketCount() == null || target.getTicketCount() <= 0) { + result = PlanetConstant.HUNT_FAIL; + vo.setMessage("鐩爣鏄熺悆绌虹┖濡備篃锛屾湭鑳界即鑾"); + } else { + // 鎴愬姛鐜囷細鍩虹 + 杩芥崟BUFF鍔犳垚 + double rate = BASE_SUCCESS_RATE; + final PlanetBuffRecord huntBuff = firstActiveBuff(fromUserId, PlanetConstant.BUFF_HUNT); + if (huntBuff != null && huntBuff.getEffectValue() != null) { + rate += huntBuff.getEffectValue().doubleValue(); + } + if (rate > 1) { + rate = 1; + } + final boolean success = ThreadLocalRandom.current().nextDouble() < rate; + if (success) { + result = PlanetConstant.HUNT_SUCCESS; + final int gain = 1; + // 璁$畻鐩爣褰撳墠鎺掑悕鐨勬偓璧忓鍔 + final int targetRank = rankService.userRankNo(regionId, toUserId); + final int bounty = PlanetConstant.bountyByRank(targetRank); + // 浠庣洰鏍囩即鑾 + ticketService.deductTickets(toUserId, target.getRegionId(), gain, + PlanetConstant.TICKET_TYPE_HUNT, UUID.randomUUID().toString().replace("-", ""), + "琚" + safeName(from.getNickname()) + "杩芥崟缂磋幏"); + // 鍙戣捣浜鸿幏寰楃即鑾峰埜 + 鎮祻鍒 + ticketService.addTickets(fromUserId, regionId, gain, + PlanetConstant.TICKET_TYPE_HUNT, UUID.randomUUID().toString().replace("-", ""), + "杩芥崟缂磋幏" + safeName(target.getNickname())); + if (bounty > 0) { + ticketService.addTickets(fromUserId, regionId, bounty, + PlanetConstant.TICKET_TYPE_HUNT, UUID.randomUUID().toString().replace("-", ""), + "閫氱級鎮祻濂栧姳"); + } + vo.setGainTickets(gain); + vo.setBountyTickets(bounty); + vo.setTotalGain(gain + bounty); + vo.setMessage("杩芥崟鎴愬姛锛佺即鑾 " + gain + " 寮犳槦鐞冨埜" + (bounty > 0 ? "锛岄澶栬幏寰 " + bounty + " 寮犳偓璧忓埜" : "")); + + // 鐩爣琚拷鎴愬姛杈句笂闄愯嚜鍔ㄥ紑闃叉姢缃 + if (targetHuntedSuccess + 1 >= PlanetConstant.HUNTED_SUCCESS_LIMIT) { + buffService.grantBuff(toUserId, target.getRegionId(), PlanetConstant.BUFF_SHIELD, "hunt"); + } + // 蹇 + newsService.addNews(regionId, PlanetConstant.NEWS_HUNT, + safeName(target.getNickname()) + " 閬亣杩芥崟锛屾崯澶 " + (gain) + " 寮犳槦鐞冨埜", + toUserId, target.getNickname()); + } else { + result = PlanetConstant.HUNT_FAIL; + vo.setMessage("鐩爣椋炶埞鐏垫椿鏈哄姩锛屾湰娆¤拷鎹曟墤绌"); + } + } + vo.setResult(result); + + // 鍐欒拷鎹曡褰 + saveHuntRecord(from, target, regionId, result, vo.getGainTickets(), vo.getBountyTickets(), today); + vo.setRemainHunt(Math.max(0, PlanetConstant.HUNT_DAILY_LIMIT - (huntedToday + 1))); + return vo; + } + + @Override + public int remainHunt(String userId) { + final int used = countTodayHunts(userId, LocalDate.now()); + return Math.max(0, PlanetConstant.HUNT_DAILY_LIMIT - used); + } + + private int countTodayHunts(String userId, LocalDate date) { + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.eq(PlanetHuntRecord::getFromUserId, userId) + .eq(PlanetHuntRecord::getHuntDate, date); + return huntRecordMapper.selectCount(qw).intValue(); + } + + private int countTodayHuntedSuccess(String userId, LocalDate date) { + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.eq(PlanetHuntRecord::getToUserId, userId) + .eq(PlanetHuntRecord::getResult, PlanetConstant.HUNT_SUCCESS) + .eq(PlanetHuntRecord::getHuntDate, date); + return huntRecordMapper.selectCount(qw).intValue(); + } + + private PlanetBuffRecord firstActiveBuff(String userId, String type) { + for (PlanetBuffRecord r : buffService.activeBuffs(userId)) { + if (type.equals(r.getType())) { + return r; + } + } + return null; + } + + private void saveHuntRecord(PlanetTicket from, PlanetTicket target, String regionId, String result, + int gain, int bounty, LocalDate date) { + final PlanetHuntRecord record = new PlanetHuntRecord(); + record.setId(UUID.randomUUID().toString().replace("-", "")); + record.setFromUserId(from.getUserId()); + record.setFromUserName(from.getNickname()); + record.setToUserId(target.getUserId()); + record.setToUserName(target.getNickname()); + record.setRegionId(regionId); + record.setResult(result); + record.setGainTickets(gain); + record.setBountyTickets(bounty); + record.setHuntDate(date); + record.setCreateTime(new Date()); + huntRecordMapper.insert(record); + } + + private String safeName(String name) { + return StringUtils.isEmpty(name) ? "绁炵鍚屽" : name; + } +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetNewsServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetNewsServiceImpl.java new file mode 100644 index 00000000..1d5cb3e0 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetNewsServiceImpl.java @@ -0,0 +1,54 @@ +package cc.hiver.mall.planet.service.impl; + +import cc.hiver.mall.planet.entity.PlanetNews; +import cc.hiver.mall.planet.mapper.PlanetNewsMapper; +import cc.hiver.mall.planet.service.PlanetNewsService; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Date; +import java.util.List; +import java.util.UUID; + +/** + * 鐧藉珫鏄熺悆-鏄熺悆蹇鏈嶅姟瀹炵幇 + * + * @author hiver + */ +@Service +public class PlanetNewsServiceImpl implements PlanetNewsService { + + @Autowired + private PlanetNewsMapper newsMapper; + + @Override + public void addNews(String regionId, String type, String content, String userId, String userName) { + final PlanetNews news = new PlanetNews(); + news.setId(UUID.randomUUID().toString().replace("-", "")); + news.setRegionId(regionId); + news.setType(type); + news.setContent(content); + news.setUserId(userId); + news.setUserName(userName); + news.setIsTop(0); + news.setEnabled(1); + news.setCreateTime(new Date()); + newsMapper.insert(news); + } + + @Override + public List latest(String regionId, int limit) { + // 鍟嗗湀寮洪殧绂伙細浠呰繑鍥炴湰鍟嗗湀蹇锛屼笉鍐嶆贩鍏ュ叏灞蹇 + if (StringUtils.isEmpty(regionId)) { + return new java.util.ArrayList<>(); + } + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.eq(PlanetNews::getEnabled, 1) + .eq(PlanetNews::getRegionId, regionId) + .orderByDesc(PlanetNews::getIsTop).orderByDesc(PlanetNews::getCreateTime) + .last("limit " + limit); + return newsMapper.selectList(qw); + } +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetRankServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetRankServiceImpl.java new file mode 100644 index 00000000..84cb0f96 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetRankServiceImpl.java @@ -0,0 +1,157 @@ +package cc.hiver.mall.planet.service.impl; + +import cc.hiver.core.common.redis.RedisTemplateHelper; +import cc.hiver.mall.planet.constant.PlanetConstant; +import cc.hiver.mall.planet.entity.PlanetTicket; +import cc.hiver.mall.planet.mapper.PlanetTicketMapper; +import cc.hiver.mall.planet.pojo.PlanetRankItemVo; +import cc.hiver.mall.planet.service.PlanetBuffService; +import cc.hiver.mall.planet.service.PlanetRankService; +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +/** + * 鐧藉珫鏄熺悆-閫氱級姒滄湇鍔″疄鐜 + * + * @author hiver + */ +@Slf4j +@Service +public class PlanetRankServiceImpl implements PlanetRankService { + + /** 閫氱級姒滅紦瀛樺墠缂(鍩虹姒滃崟锛屼笉鍚 self 鏍囪) */ + private static final String RANK_CACHE_PREFIX = "planet:rank:"; + /** 缂撳瓨鏈夋晥鏈(绉)锛屾鍗曞厑璁哥煭鏃跺急涓鑷达紝闄嶄綆楂橀鏌ュ簱鍘嬪姏 */ + private static final long RANK_CACHE_SECONDS = 30L; + + @Autowired + private PlanetTicketMapper ticketMapper; + + @Autowired + private PlanetBuffService buffService; + + @Autowired + private RedisTemplateHelper redisTemplateHelper; + + @Override + public List rankTop(String regionId, int topN, String currentUserId) { + List base = readCache(regionId, topN); + if (base == null) { + base = buildRankFromDb(regionId, topN); + writeCache(regionId, topN, base); + } + // self 鏍囪涓庤姹傜敤鎴风浉鍏筹紝缂撳瓨涓嶅瓨鍌紝杩斿洖鏃舵寜褰撳墠鐢ㄦ埛鍗虫椂鎵撴爣 + for (PlanetRankItemVo vo : base) { + vo.setSelf(vo.getUserId() != null && vo.getUserId().equals(currentUserId)); + } + return base; + } + + /** + * 浠庢暟鎹簱鏋勫缓鍩虹姒滃崟锛氬厛鎵归噺鍙栧欓夊埜璁板綍锛屽啀涓娆℃ф壒閲忔煡 BUFF锛屽唴瀛樼粍瑁咃紝閬垮厤寰幆鏌ュ簱銆 + */ + private List buildRankFromDb(String regionId, int topN) { + // 澶氬彇涓浜涗互渚胯繃婊ら殣韬敤鎴峰悗浠嶈兘鍑戞弧topN + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + if (StringUtils.isNotEmpty(regionId)) { + qw.eq(PlanetTicket::getRegionId, regionId); + } + qw.gt(PlanetTicket::getTicketCount, 0) + .orderByDesc(PlanetTicket::getTicketCount) + .orderByDesc(PlanetTicket::getTotalTicket) + .last("limit " + (topN + 20)); + final List tickets = ticketMapper.selectList(qw); + if (tickets.isEmpty()) { + return new ArrayList<>(); + } + // 鎵归噺鏌ヨ鍊欓夌敤鎴风殑鐢熸晥 BUFF 绫诲瀷锛屼竴娆℃煡搴 + final Set userIds = tickets.stream().map(PlanetTicket::getUserId).collect(Collectors.toCollection(LinkedHashSet::new)); + final Map> buffMap = buffService.activeBuffTypes(userIds); + + final List result = new ArrayList<>(); + int rankNo = 0; + for (PlanetTicket t : tickets) { + final Set buffs = buffMap.get(t.getUserId()); + // 闅愯韩BUFF鐢ㄦ埛涓嶅嚭鐜板湪姒滃崟 + if (buffs != null && buffs.contains(PlanetConstant.BUFF_STEALTH)) { + continue; + } + rankNo++; + if (rankNo > topN) { + break; + } + final PlanetRankItemVo vo = new PlanetRankItemVo(); + vo.setRankNo(rankNo); + vo.setUserId(t.getUserId()); + vo.setNickname(t.getNickname()); + vo.setAvatar(t.getAvatar()); + vo.setCollege(t.getCollege()); + vo.setTicketCount(t.getTicketCount()); + vo.setDangerLevel(PlanetConstant.dangerLevel(t.getTicketCount())); + vo.setDangerLevelName(PlanetConstant.dangerLevelName(t.getTicketCount())); + vo.setRankKeepDays(t.getRankKeepDays() == null ? 0 : t.getRankKeepDays()); + vo.setBountyTickets(PlanetConstant.bountyByRank(rankNo)); + vo.setShielded(buffs != null && buffs.contains(PlanetConstant.BUFF_SHIELD)); + vo.setSelf(false); + result.add(vo); + } + return result; + } + + private List readCache(String regionId, int topN) { + try { + final String json = redisTemplateHelper.get(cacheKey(regionId, topN)); + if (StringUtils.isNotEmpty(json)) { + return JSON.parseArray(json, PlanetRankItemVo.class); + } + } catch (Exception e) { + log.warn("[鐧藉珫鏄熺悆] 璇诲彇閫氱級姒滅紦瀛樺け璐 {}", e.getMessage()); + } + return null; + } + + private void writeCache(String regionId, int topN, List list) { + try { + redisTemplateHelper.set(cacheKey(regionId, topN), JSON.toJSONString(list), RANK_CACHE_SECONDS, TimeUnit.SECONDS); + } catch (Exception e) { + log.warn("[鐧藉珫鏄熺悆] 鍐欏叆閫氱級姒滅紦瀛樺け璐 {}", e.getMessage()); + } + } + + private String cacheKey(String regionId, int topN) { + return RANK_CACHE_PREFIX + (StringUtils.isEmpty(regionId) ? "all" : regionId) + ":" + topN; + } + + @Override + public PlanetTicket getRankTarget(String regionId, String userId) { + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.eq(PlanetTicket::getUserId, userId); + if (StringUtils.isNotEmpty(regionId)) { + qw.eq(PlanetTicket::getRegionId, regionId); + } + qw.last("limit 1"); + return ticketMapper.selectOne(qw); + } + + @Override + public int userRankNo(String regionId, String userId) { + final PlanetTicket me = getRankTarget(regionId, userId); + if (me == null || me.getTicketCount() == null || me.getTicketCount() <= 0) { + return 0; + } + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + if (StringUtils.isNotEmpty(regionId)) { + qw.eq(PlanetTicket::getRegionId, regionId); + } + qw.gt(PlanetTicket::getTicketCount, me.getTicketCount()); + return ticketMapper.selectCount(qw).intValue() + 1; + } +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetServiceImpl.java new file mode 100644 index 00000000..2b304553 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetServiceImpl.java @@ -0,0 +1,104 @@ +package cc.hiver.mall.planet.service.impl; + +import cc.hiver.mall.planet.constant.PlanetConstant; +import cc.hiver.mall.planet.entity.PlanetBuffRecord; +import cc.hiver.mall.planet.entity.PlanetPool; +import cc.hiver.mall.planet.entity.PlanetTicket; +import cc.hiver.mall.planet.pojo.PlanetBuffVo; +import cc.hiver.mall.planet.pojo.PlanetHomeVo; +import cc.hiver.mall.planet.pojo.PlanetQuery; +import cc.hiver.mall.planet.service.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * 鐧藉珫鏄熺悆-棣栭〉鑱氬悎鏈嶅姟瀹炵幇 + * + * @author hiver + */ +@Service +public class PlanetServiceImpl implements PlanetService { + + @Autowired + private PlanetTicketService ticketService; + + @Autowired + private PlanetRankService rankService; + + @Autowired + private PlanetTaskService taskService; + + @Autowired + private PlanetBuffService buffService; + + @Autowired + private PlanetBoxService boxService; + + @Autowired + private PlanetHuntService huntService; + + @Autowired + private PlanetDrawService drawService; + + @Autowired + private PlanetNewsService newsService; + + @Override + public PlanetHomeVo home(PlanetQuery query) { + final String userId = query.getUserId(); + final String regionId = query.getRegionId(); + final PlanetHomeVo vo = new PlanetHomeVo(); + + // 鍒濆鍖/琛ュ叏鐢ㄦ埛鍒歌褰 + final PlanetTicket ticket = ticketService.getOrCreate(userId, regionId, + query.getNickname(), query.getAvatar(), query.getCollege()); + + // 瀹囧畽Header锛氬綋鍓嶅姹 + final PlanetPool pool = drawService.getCurrentPool(regionId); + vo.setPoolAmount(pool.getPoolAmount() == null ? BigDecimal.ZERO : pool.getPoolAmount()); + vo.setDrawTime(pool.getDrawTime()); + vo.setPeriodNo(pool.getPeriodNo()); + if (pool.getDrawTime() != null) { + vo.setCountdownMillis(Math.max(0, pool.getDrawTime().getTime() - new Date().getTime())); + } else { + vo.setCountdownMillis(0L); + } + vo.setJoinCount(pool.getJoinCount() == null ? 0 : pool.getJoinCount()); + + // 鎴戠殑鏄熺悆涓績 + vo.setMyTicketCount(ticket.getTicketCount() == null ? 0 : ticket.getTicketCount()); + vo.setNickname(ticket.getNickname()); + vo.setAvatar(ticket.getAvatar()); + vo.setConsecutiveSignDays(ticket.getConsecutiveSignDays() == null ? 0 : ticket.getConsecutiveSignDays()); + vo.setSignedToday(taskService.signedToday(userId, regionId)); + vo.setBoxAvailable(boxService.boxAvailable(userId, regionId)); + vo.setRemainHunt(huntService.remainHunt(userId)); + vo.setLevel(PlanetConstant.dangerLevel(vo.getMyTicketCount())); + vo.setMyRankNo(rankService.userRankNo(regionId, userId)); + + // 鎴戠敓鏁堢殑BUFF + final List myBuffs = new ArrayList<>(); + for (PlanetBuffRecord r : buffService.activeBuffs(userId)) { + final PlanetBuffVo bv = new PlanetBuffVo(); + bv.setId(r.getBuffId()); + bv.setType(r.getType()); + bv.setEffectValue(r.getEffectValue()); + bv.setActive(true); + bv.setActiveEndTime(r.getEndTime()); + myBuffs.add(bv); + } + vo.setMyBuffs(myBuffs); + + // 鍚勬澘鍧 + vo.setTasks(taskService.listTasks(userId, regionId)); + vo.setRankList(rankService.rankTop(regionId, 10, userId)); + vo.setBuffShop(buffService.shopList(userId, regionId)); + vo.setNewsList(newsService.latest(regionId, 20)); + return vo; + } +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetTaskServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetTaskServiceImpl.java new file mode 100644 index 00000000..c9280cad --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetTaskServiceImpl.java @@ -0,0 +1,199 @@ +package cc.hiver.mall.planet.service.impl; + +import cc.hiver.core.common.exception.HiverException; +import cc.hiver.mall.planet.constant.PlanetConstant; +import cc.hiver.mall.planet.entity.PlanetTask; +import cc.hiver.mall.planet.entity.PlanetTicket; +import cc.hiver.mall.planet.entity.PlanetTicketLog; +import cc.hiver.mall.planet.mapper.PlanetTaskMapper; +import cc.hiver.mall.planet.mapper.PlanetTicketLogMapper; +import cc.hiver.mall.planet.mapper.PlanetTicketMapper; +import cc.hiver.mall.planet.pojo.PlanetTaskVo; +import cc.hiver.mall.planet.service.PlanetNewsService; +import cc.hiver.mall.planet.service.PlanetTaskService; +import cc.hiver.mall.planet.service.PlanetTicketService; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZoneId; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.UUID; + +/** + * 鐧藉珫鏄熺悆-浠诲姟鏈嶅姟瀹炵幇 + * + * @author hiver + */ +@Service +public class PlanetTaskServiceImpl implements PlanetTaskService { + + @Autowired + private PlanetTaskMapper taskMapper; + + @Autowired + private PlanetTicketMapper ticketMapper; + + @Autowired + private PlanetTicketLogMapper ticketLogMapper; + + @Autowired + private PlanetTicketService ticketService; + + @Autowired + private PlanetNewsService newsService; + + @Override + public List listTasks(String userId, String regionId) { + final List tasks = listEnabledTasks(regionId); + final List list = new ArrayList<>(); + for (PlanetTask task : tasks) { + final PlanetTaskVo vo = new PlanetTaskVo(); + vo.setCode(task.getCode()); + vo.setName(task.getName()); + vo.setDescription(task.getDescription()); + vo.setIcon(task.getIcon()); + vo.setRewardTickets(task.getRewardTickets()); + vo.setDailyLimit(task.getDailyLimit()); + final int todayCount = countTodayByType(userId, task.getCode()); + vo.setTodayCount(todayCount); + if (PlanetConstant.TASK_SIGN.equals(task.getCode())) { + vo.setActionType("claim"); + vo.setCanClaim(!signedToday(userId, regionId)); + } else { + vo.setActionType("auto"); + vo.setCanClaim(false); + } + list.add(vo); + } + return list; + } + + @Override + public int sign(String userId, String regionId) { + final PlanetTicket ticket = ticketService.getOrCreate(userId, regionId, null, null, null); + final LocalDate today = LocalDate.now(); + if (ticket.getLastSignDate() != null && ticket.getLastSignDate().isEqual(today)) { + throw new HiverException("浠婃棩宸茬鍒"); + } + // 杩炵画绛惧埌澶╂暟 + int days = 1; + if (ticket.getLastSignDate() != null && ticket.getLastSignDate().isEqual(today.minusDays(1))) { + days = (ticket.getConsecutiveSignDays() == null ? 0 : ticket.getConsecutiveSignDays()) + 1; + } + ticket.setConsecutiveSignDays(days); + ticket.setLastSignDate(today); + ticket.setUpdateTime(new Date()); + ticketMapper.updateById(ticket); + + final PlanetTask task = getTaskConfig(regionId, PlanetConstant.TASK_SIGN); + final int reward = task != null && task.getRewardTickets() != null ? task.getRewardTickets() : 1; + return ticketService.addTickets(userId, regionId, reward, PlanetConstant.TICKET_TYPE_SIGN, + "sign:" + userId + ":" + today, "姣忔棩绛惧埌"); + } + + @Override + public int claim(String userId, String regionId, String taskCode) { + if (PlanetConstant.TASK_SIGN.equals(taskCode)) { + return sign(userId, regionId); + } + throw new HiverException("璇ヤ换鍔¢氳繃瀹屾垚瀵瑰簲琛屼负鑷姩鍙戞斁鏄熺悆鍒"); + } + + @Override + public PlanetTask getTaskConfig(String regionId, String code) { + // 鍟嗗湀寮洪殧绂伙細浠呮煡鏈晢鍦堜换鍔¢厤缃紝涓嶅啀鍥為鍏ㄥ眬榛樿 + if (StringUtils.isEmpty(regionId)) { + return null; + } + PlanetTask t = selectRegionTask(regionId, code); + if (t == null) { + seedDefaultTasks(regionId); + t = selectRegionTask(regionId, code); + } + return t; + } + + private PlanetTask selectRegionTask(String regionId, String code) { + final LambdaQueryWrapper rq = new LambdaQueryWrapper<>(); + rq.eq(PlanetTask::getCode, code).eq(PlanetTask::getEnabled, 1) + .eq(PlanetTask::getRegionId, regionId).last("limit 1"); + return taskMapper.selectOne(rq); + } + + @Override + public boolean signedToday(String userId, String regionId) { + final PlanetTicket ticket = ticketService.getByUser(userId, regionId); + return ticket != null && ticket.getLastSignDate() != null && ticket.getLastSignDate().isEqual(LocalDate.now()); + } + + private List listEnabledTasks(String regionId) { + // 鍟嗗湀寮洪殧绂伙細浠呰繑鍥炴湰鍟嗗湀浠诲姟锛岄娆¤闂嚜鍔ㄥ垵濮嬪寲榛樿浠诲姟 + if (StringUtils.isEmpty(regionId)) { + return new ArrayList<>(); + } + List list = selectRegionTasks(regionId); + if (list.isEmpty()) { + seedDefaultTasks(regionId); + list = selectRegionTasks(regionId); + } + return list; + } + + private List selectRegionTasks(String regionId) { + final LambdaQueryWrapper rq = new LambdaQueryWrapper<>(); + rq.eq(PlanetTask::getRegionId, regionId).eq(PlanetTask::getEnabled, 1) + .orderByAsc(PlanetTask::getSort); + final List list = taskMapper.selectList(rq); + return list == null ? new ArrayList<>() : list; + } + + /** + * 涓烘寚瀹氬晢鍦堝垵濮嬪寲榛樿浠诲姟閰嶇疆(骞傜瓑锛氭寜 code 瀛樺湪鍒欒烦杩)銆 + */ + private void seedDefaultTasks(String regionId) { + if (StringUtils.isEmpty(regionId)) { + return; + } + seedTask(regionId, PlanetConstant.TASK_WAIMAI, "瀹屾垚澶栧崠璁㈠崟", "姣忓畬鎴愪竴绗斿鍗栬鍗 +1 鏄熺悆鍒", 1, 0, 1); + seedTask(regionId, PlanetConstant.TASK_GROUP, "瀹屾垚鍥㈣喘璁㈠崟", "姣忓畬鎴愪竴绗斿洟璐鍗 +1 鏄熺悆鍒", 1, 0, 2); + seedTask(regionId, PlanetConstant.TASK_INVITE, "閭璇峰ソ鍙嬫敞鍐", "姣忛個璇蜂竴浣嶅ソ鍙嬫敞鍐 +3 鏄熺悆鍒", 3, 0, 3); + seedTask(regionId, PlanetConstant.TASK_SIGN, "姣忔棩绛惧埌", "姣忔棩绛惧埌棰嗗彇 +1 鏄熺悆鍒", 1, 1, 4); + } + + private void seedTask(String regionId, String code, String name, String desc, int reward, int dailyLimit, int sort) { + final LambdaQueryWrapper exist = new LambdaQueryWrapper<>(); + exist.eq(PlanetTask::getRegionId, regionId).eq(PlanetTask::getCode, code); + if (taskMapper.selectCount(exist) > 0) { + return; + } + final PlanetTask task = new PlanetTask(); + task.setId(UUID.randomUUID().toString().replace("-", "")); + task.setRegionId(regionId); + task.setCode(code); + task.setName(name); + task.setDescription(desc); + task.setRewardTickets(reward); + task.setDailyLimit(dailyLimit); + task.setSort(sort); + task.setEnabled(1); + task.setCreateTime(new Date()); + taskMapper.insert(task); + } + + private int countTodayByType(String userId, String type) { + final LocalDateTime start = LocalDateTime.of(LocalDate.now(), LocalTime.MIN); + final Date startDate = Date.from(start.atZone(ZoneId.systemDefault()).toInstant()); + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.eq(PlanetTicketLog::getUserId, userId) + .eq(PlanetTicketLog::getType, type) + .ge(PlanetTicketLog::getCreateTime, startDate); + return ticketLogMapper.selectCount(qw).intValue(); + } +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetTicketServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetTicketServiceImpl.java new file mode 100644 index 00000000..28751d4d --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetTicketServiceImpl.java @@ -0,0 +1,229 @@ +package cc.hiver.mall.planet.service.impl; + +import cc.hiver.core.common.exception.HiverException; +import cc.hiver.core.entity.User; +import cc.hiver.core.service.UserService; +import cc.hiver.mall.planet.constant.PlanetConstant; +import cc.hiver.mall.planet.entity.PlanetBuffRecord; +import cc.hiver.mall.planet.entity.PlanetTicket; +import cc.hiver.mall.planet.entity.PlanetTicketLog; +import cc.hiver.mall.planet.mapper.PlanetBuffRecordMapper; +import cc.hiver.mall.planet.mapper.PlanetTicketLogMapper; +import cc.hiver.mall.planet.mapper.PlanetTicketMapper; +import cc.hiver.mall.planet.service.PlanetTicketService; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import java.util.UUID; + +/** + * 鐧藉珫鏄熺悆-鏄熺悆鍒告湇鍔″疄鐜 + * + * @author hiver + */ +@Slf4j +@Service +public class PlanetTicketServiceImpl implements PlanetTicketService { + + @Autowired + private PlanetTicketMapper ticketMapper; + + @Autowired + private PlanetTicketLogMapper ticketLogMapper; + + @Autowired + private PlanetBuffRecordMapper buffRecordMapper; + + @Autowired + private UserService userService; + + @Override + public PlanetTicket getOrCreate(String userId, String regionId, String nickname, String avatar, String college) { + if (StringUtils.isEmpty(userId)) { + throw new HiverException("鐢ㄦ埛id涓嶈兘涓虹┖"); + } + PlanetTicket ticket = getByUser(userId, regionId); + if (ticket == null) { + ticket = new PlanetTicket(); + ticket.setId(UUID.randomUUID().toString().replace("-", "")); + ticket.setUserId(userId); + ticket.setRegionId(regionId); + ticket.setTicketCount(0); + ticket.setTotalTicket(0); + ticket.setConsecutiveSignDays(0); + ticket.setRankKeepDays(0); + ticket.setLastRankNo(0); + ticket.setHuntCountToday(0); + ticket.setHuntedSuccessToday(0); + fillUserInfo(ticket, nickname, avatar, college); + ticket.setCreateTime(new Date()); + ticket.setUpdateTime(new Date()); + ticketMapper.insert(ticket); + } else { + // 琛ュ叏鍐椾綑淇℃伅 + boolean needUpdate = false; + if (StringUtils.isEmpty(ticket.getNickname()) && StringUtils.isNotEmpty(nickname)) { + ticket.setNickname(nickname); + needUpdate = true; + } + if (StringUtils.isEmpty(ticket.getAvatar()) && StringUtils.isNotEmpty(avatar)) { + ticket.setAvatar(avatar); + needUpdate = true; + } + if (StringUtils.isEmpty(ticket.getCollege()) && StringUtils.isNotEmpty(college)) { + ticket.setCollege(college); + needUpdate = true; + } + if (needUpdate) { + ticket.setUpdateTime(new Date()); + ticketMapper.updateById(ticket); + } + } + return ticket; + } + + private void fillUserInfo(PlanetTicket ticket, String nickname, String avatar, String college) { + ticket.setNickname(nickname); + ticket.setAvatar(avatar); + ticket.setCollege(college); + if (StringUtils.isEmpty(nickname) || StringUtils.isEmpty(avatar)) { + try { + final User user = userService.findById(ticket.getUserId()); + if (user != null) { + if (StringUtils.isEmpty(ticket.getNickname())) { + ticket.setNickname(user.getNickname()); + } + if (StringUtils.isEmpty(ticket.getAvatar())) { + ticket.setAvatar(user.getAvatar()); + } + } + } catch (Exception e) { + log.warn("[鐧藉珫鏄熺悆] 鑾峰彇鐢ㄦ埛淇℃伅澶辫触 userId={}, {}", ticket.getUserId(), e.getMessage()); + } + } + } + + @Override + public PlanetTicket getByUser(String userId, String regionId) { + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.eq(PlanetTicket::getUserId, userId); + if (StringUtils.isNotEmpty(regionId)) { + qw.eq(PlanetTicket::getRegionId, regionId); + } + qw.last("limit 1"); + return ticketMapper.selectOne(qw); + } + + @Override + public int addTickets(String userId, String regionId, int baseCount, String type, String sourceId, String remark) { + if (baseCount <= 0) { + return 0; + } + // 骞傜瓑锛氬悓涓鏉ユ簮涓氬姟id鍙彂鏀句竴娆 + if (StringUtils.isNotEmpty(sourceId)) { + final LambdaQueryWrapper exist = new LambdaQueryWrapper<>(); + exist.eq(PlanetTicketLog::getType, type) + .eq(PlanetTicketLog::getSourceId, sourceId); + if (ticketLogMapper.selectCount(exist) > 0) { + log.info("[鐧藉珫鏄熺悆] 閲嶅鍙戝埜宸叉嫤鎴 type={}, sourceId={}", type, sourceId); + return 0; + } + } + final PlanetTicket ticket = getOrCreate(userId, regionId, null, null, null); + // 鍙屽岯UFF鍔犳垚 + int finalCount = baseCount; + final BigDecimal multiplier = getActiveDoubleMultiplier(userId); + if (multiplier != null && multiplier.compareTo(BigDecimal.ONE) > 0) { + finalCount = multiplier.multiply(BigDecimal.valueOf(baseCount)).intValue(); + } + ticket.setTicketCount(ticket.getTicketCount() + finalCount); + ticket.setTotalTicket(ticket.getTotalTicket() + finalCount); + ticket.setUpdateTime(new Date()); + ticketMapper.updateById(ticket); + saveLog(userId, regionId, finalCount, ticket.getTicketCount(), type, sourceId, remark); + return finalCount; + } + + @Override + public int deductTickets(String userId, String regionId, int count, String type, String sourceId, String remark) { + if (count <= 0) { + throw new HiverException("鎵e噺鏁伴噺蹇呴』澶т簬0"); + } + final PlanetTicket ticket = getOrCreate(userId, regionId, null, null, null); + if (ticket.getTicketCount() < count) { + throw new HiverException("鏄熺悆鍒镐笉瓒"); + } + ticket.setTicketCount(ticket.getTicketCount() - count); + ticket.setUpdateTime(new Date()); + ticketMapper.updateById(ticket); + saveLog(userId, regionId, -count, ticket.getTicketCount(), type, sourceId, remark); + return ticket.getTicketCount(); + } + + @Override + public int getRankNo(String regionId, String userId) { + final PlanetTicket me = getByUser(userId, regionId); + if (me == null || me.getTicketCount() == null || me.getTicketCount() <= 0) { + return 0; + } + // 姣旀垜鍒稿鐨勪汉鏁 + 1 鍗充负鎺掑悕 + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + if (StringUtils.isNotEmpty(regionId)) { + qw.eq(PlanetTicket::getRegionId, regionId); + } + qw.gt(PlanetTicket::getTicketCount, me.getTicketCount()); + final Long greater = ticketMapper.selectCount(qw); + return greater.intValue() + 1; + } + + @Override + public Page pageLog(String userId, String regionId, Integer pageNumber, Integer pageSize) { + final int num = pageNumber == null || pageNumber <= 0 ? 1 : pageNumber; + final int size = pageSize == null || pageSize <= 0 ? 10 : Math.min(pageSize, 50); + final Page page = new Page<>(num, size); + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.eq(PlanetTicketLog::getUserId, userId); + if (StringUtils.isNotEmpty(regionId)) { + qw.eq(PlanetTicketLog::getRegionId, regionId); + } + qw.orderByDesc(PlanetTicketLog::getCreateTime); + return ticketLogMapper.selectPage(page, qw); + } + + private BigDecimal getActiveDoubleMultiplier(String userId) { + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.eq(PlanetBuffRecord::getUserId, userId) + .eq(PlanetBuffRecord::getType, PlanetConstant.BUFF_DOUBLE) + .eq(PlanetBuffRecord::getStatus, PlanetConstant.BUFF_STATUS_ACTIVE) + .gt(PlanetBuffRecord::getEndTime, new Date()) + .orderByDesc(PlanetBuffRecord::getEffectValue) + .last("limit 1"); + final List list = buffRecordMapper.selectList(qw); + if (list != null && !list.isEmpty()) { + final BigDecimal v = list.get(0).getEffectValue(); + return v == null ? BigDecimal.valueOf(2) : v; + } + return BigDecimal.ONE; + } + + private void saveLog(String userId, String regionId, int change, int balance, String type, String sourceId, String remark) { + final PlanetTicketLog logEntity = new PlanetTicketLog(); + logEntity.setId(UUID.randomUUID().toString().replace("-", "")); + logEntity.setUserId(userId); + logEntity.setRegionId(regionId); + logEntity.setChangeCount(change); + logEntity.setBalance(balance); + logEntity.setType(type); + logEntity.setSourceId(sourceId); + logEntity.setRemark(remark); + logEntity.setCreateTime(new Date()); + ticketLogMapper.insert(logEntity); + } +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/PlanetDailyResetTask.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/PlanetDailyResetTask.java new file mode 100644 index 00000000..a7998a15 --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/PlanetDailyResetTask.java @@ -0,0 +1,86 @@ +package cc.hiver.mall.quartz; + +import cc.hiver.mall.planet.constant.PlanetConstant; +import cc.hiver.mall.planet.entity.PlanetBuffRecord; +import cc.hiver.mall.planet.entity.PlanetTicket; +import cc.hiver.mall.planet.mapper.PlanetBuffRecordMapper; +import cc.hiver.mall.planet.mapper.PlanetTicketMapper; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.util.Date; +import java.util.List; + +/** + * 鐧藉珫鏄熺悆-姣忔棩閲嶇疆瀹氭椂浠诲姟 + *

    + * 姣忔棩 00:05 鎵ц锛 + * 1. 杩囨湡BUFF缃负澶辨晥鐘舵 + * 2. 閲嶇疆浠婃棩杩芥崟/琚拷璁℃暟(灞曠ず鐢) + * 3. 鏇存柊杩炵画闇告澶╂暟 + * + * @author hiver + */ +@Slf4j +@Component +public class PlanetDailyResetTask { + + @Autowired + private PlanetTicketMapper ticketMapper; + + @Autowired + private PlanetBuffRecordMapper buffRecordMapper; + + @Scheduled(cron = "0 5 0 * * ?") + public void dailyReset() { + try { + // 1. 杩囨湡BUFF + final LambdaUpdateWrapper bw = new LambdaUpdateWrapper<>(); + bw.eq(PlanetBuffRecord::getStatus, PlanetConstant.BUFF_STATUS_ACTIVE) + .lt(PlanetBuffRecord::getEndTime, new Date()) + .set(PlanetBuffRecord::getStatus, PlanetConstant.BUFF_STATUS_EXPIRED); + buffRecordMapper.update(null, bw); + + // 2. 閲嶇疆姣忔棩璁℃暟(灞曠ず瀛楁) + final LambdaUpdateWrapper tw = new LambdaUpdateWrapper<>(); + tw.set(PlanetTicket::getHuntCountToday, 0) + .set(PlanetTicket::getHuntedSuccessToday, 0); + ticketMapper.update(null, tw); + + // 3. 鏇存柊杩炵画闇告澶╂暟锛氫粛鍦═OP10鐨勭敤鎴 keepDays+1锛屽惁鍒欐竻闆 + updateRankKeepDays(); + log.info("[鐧藉珫鏄熺悆] 姣忔棩閲嶇疆浠诲姟瀹屾垚"); + } catch (Exception e) { + log.error("[鐧藉珫鏄熺悆] 姣忔棩閲嶇疆浠诲姟寮傚父: {}", e.getMessage(), e); + } + } + + private void updateRankKeepDays() { + // 鍙栨墍鏈夋寔鍒哥敤鎴凤紝鎸夊尯鍩熷垎鍒绠楀墠10 + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.gt(PlanetTicket::getTicketCount, 0).orderByDesc(PlanetTicket::getTicketCount); + final List all = ticketMapper.selectList(qw); + // 绠鍖栧鐞嗭細鍏ㄥ眬/鍚勫尯鍩熺粺涓鎸夊埜鏁版帓搴忓悗锛岃褰曞叾鍦ㄦ湰鍖哄煙鐨勫悕娆 + // 杩欓噷浠呭姣忎釜鐢ㄦ埛鍩轰簬鍏跺綋鍓嶆槸鍚﹁繘鍏ユ湰鍖哄煙TOP10鏇存柊keepDays + final java.util.Map regionRankCounter = new java.util.HashMap<>(); + for (PlanetTicket t : all) { + final String region = t.getRegionId() == null ? "" : t.getRegionId(); + final int rank = regionRankCounter.merge(region, 1, Integer::sum); + int keep = t.getRankKeepDays() == null ? 0 : t.getRankKeepDays(); + if (rank <= 10) { + keep = keep + 1; + t.setLastRankNo(rank); + } else { + keep = 0; + t.setLastRankNo(0); + } + t.setRankKeepDays(keep); + t.setUpdateTime(new Date()); + ticketMapper.updateById(t); + } + } +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/PlanetDrawTask.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/PlanetDrawTask.java new file mode 100644 index 00000000..5775a0fc --- /dev/null +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/PlanetDrawTask.java @@ -0,0 +1,33 @@ +package cc.hiver.mall.quartz; + +import cc.hiver.mall.planet.service.PlanetDrawService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +/** + * 鐧藉珫鏄熺悆-鍒扮偣寮濂栧畾鏃朵换鍔 + * 姣忓垎閽熸壂鎻忓埌杈惧紑濂栨椂闂翠笖鏈紑濂栫殑濂栨睜骞舵墽琛屽姞鏉冨紑濂 + * + * @author hiver + */ +@Slf4j +@Component +public class PlanetDrawTask { + + @Autowired + private PlanetDrawService drawService; + + @Scheduled(cron = "0 * * * * ?") + public void drawDuePools() { + try { + final int count = drawService.drawDuePools(); + if (count > 0) { + log.info("[鐧藉珫鏄熺悆] 鏈疆寮濂栧姹犳暟閲={}", count); + } + } catch (Exception e) { + log.error("[鐧藉珫鏄熺悆] 寮濂栦换鍔″紓甯: {}", e.getMessage(), e); + } + } +} diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallOrderServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallOrderServiceImpl.java index 96ec442c..4ae940ec 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallOrderServiceImpl.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallOrderServiceImpl.java @@ -184,6 +184,9 @@ public class MallOrderServiceImpl extends ServiceImpl