diff --git a/cash-api/account-server/src/main/java/com/czg/controller/admin/ShopUserController.java b/cash-api/account-server/src/main/java/com/czg/controller/admin/ShopUserController.java index ae561f0ac..e8e9daae5 100644 --- a/cash-api/account-server/src/main/java/com/czg/controller/admin/ShopUserController.java +++ b/cash-api/account-server/src/main/java/com/czg/controller/admin/ShopUserController.java @@ -97,6 +97,17 @@ public class ShopUserController { return CzgResult.success(shopUserService.getPage(key, isVip, amount)); } + /** + * 导出用户列表 + * + * @param key 昵称或手机号 + * @param isVip 0 非vip 1 vip + */ + @GetMapping("/export") + public void exportUserList(String key, Integer isVip, HttpServletResponse response) { + shopUserService.exportUserList(key, isVip, response); + } + @GetMapping("/getPage") public CzgResult> getPage(@RequestParam(required = false)String key,@RequestParam(required = false) Integer isVip) { return CzgResult.success(shopUserService.getPage(key, isVip)); diff --git a/cash-api/market-server/src/main/java/com/czg/controller/admin/ACarouselController.java b/cash-api/market-server/src/main/java/com/czg/controller/admin/ACarouselController.java new file mode 100644 index 000000000..6e4dc48fe --- /dev/null +++ b/cash-api/market-server/src/main/java/com/czg/controller/admin/ACarouselController.java @@ -0,0 +1,61 @@ +package com.czg.controller.admin; + +import com.czg.annotation.SaAdminCheckPermission; +import com.czg.market.dto.MkCarouselDTO; +import com.czg.market.entity.MkCarousel; +import com.czg.market.service.MkCarouselService; +import com.czg.resp.CzgResult; +import com.czg.sa.StpKit; +import com.mybatisflex.core.query.QueryWrapper; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + + +/** + * 轮播图配置 + * + * @author ww + */ +@RestController +@RequestMapping("/admin/carousel") +public class ACarouselController { + + @Resource + private MkCarouselService mkCarouselService; + + /** + * 轮播图配置 + */ + @GetMapping + @SaAdminCheckPermission(parentName = "轮播图配置", value = "carousel:config", name = "轮播图-列表") + public CzgResult> getCarousels(MkCarouselDTO carouselDTO) { + carouselDTO.setShopId(StpKit.USER.getShopId()); + return CzgResult.success(mkCarouselService.getCarousels(carouselDTO)); + } + + /** + * 轮播图配置:新增/修改 + */ + @PostMapping + @SaAdminCheckPermission(parentName = "轮播图配置", value = "carousel:up", name = "轮播图-新增/修改") + public CzgResult editCarousel(@RequestBody @Validated MkCarousel carousel) { + carousel.setShopId(StpKit.USER.getShopId()); + if (carousel.getId() == null) { + return CzgResult.success(mkCarouselService.save(carousel)); + } else { + return CzgResult.success(mkCarouselService.updateById(carousel, false)); + } + } + + /** + * 轮播图配置:删除 + */ + @DeleteMapping("/{id}") + @SaAdminCheckPermission(parentName = "轮播图配置", value = "carousel:up", name = "轮播图-新增/修改") + public CzgResult deleteCarousel(@PathVariable("id") Long id) { + return CzgResult.success(mkCarouselService.remove(QueryWrapper.create().eq(MkCarousel::getId, id).eq(MkCarousel::getShopId, StpKit.USER.getShopId()))); + } +} \ No newline at end of file diff --git a/cash-api/market-server/src/main/java/com/czg/controller/admin/ADisGroupController.java b/cash-api/market-server/src/main/java/com/czg/controller/admin/ADisGroupController.java new file mode 100644 index 000000000..212c6dcef --- /dev/null +++ b/cash-api/market-server/src/main/java/com/czg/controller/admin/ADisGroupController.java @@ -0,0 +1,47 @@ +package com.czg.controller.admin; + +import com.czg.annotation.SaAdminCheckPermission; +import com.czg.market.entity.MkDistributionGroup; +import com.czg.market.service.MkDistributionGroupService; +import com.czg.resp.CzgResult; +import com.czg.sa.StpKit; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; + + +/** + * 全民股东群聊 + * + * @author ww + */ +@RestController +@RequestMapping("/admin/disGroup") +public class ADisGroupController { + + @Resource + private MkDistributionGroupService mkDistributionGroupService; + + /** + * 全民股东群聊 + */ + @GetMapping + @SaAdminCheckPermission(parentName = "全民股东群聊", value = "share:config", name = "全民股东群聊-配置") + public CzgResult getShareBase() { + return CzgResult.success(mkDistributionGroupService.getById(StpKit.USER.getShopId())); + } + + /** + * 全民股东群聊:新增/修改 + */ + @PostMapping + @SaAdminCheckPermission(parentName = "全民股东群聊", value = "share:up", name = "全民股东群聊-新增/修改") + public CzgResult editShareBase(@RequestBody MkDistributionGroup group) { + group.setShopId(StpKit.USER.getShopId()); + MkDistributionGroup share = mkDistributionGroupService.getById(group.getShopId()); + if (share == null) { + return CzgResult.success(mkDistributionGroupService.save(group)); + } else { + return CzgResult.success(mkDistributionGroupService.updateById(group, false)); + } + } +} \ No newline at end of file diff --git a/cash-api/market-server/src/main/java/com/czg/controller/admin/AShareBaseController.java b/cash-api/market-server/src/main/java/com/czg/controller/admin/AShareBaseController.java new file mode 100644 index 000000000..6d10b3d3e --- /dev/null +++ b/cash-api/market-server/src/main/java/com/czg/controller/admin/AShareBaseController.java @@ -0,0 +1,47 @@ +package com.czg.controller.admin; + +import com.czg.annotation.SaAdminCheckPermission; +import com.czg.market.entity.MkShareBase; +import com.czg.market.service.MkShareBaseService; +import com.czg.resp.CzgResult; +import com.czg.sa.StpKit; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; + + +/** + * 分享奖励基础 + * + * @author ww + */ +@RestController +@RequestMapping("/admin/shareBase") +public class AShareBaseController { + + @Resource + private MkShareBaseService mkShareBaseService; + + /** + * 分享奖励基础 + */ + @GetMapping + @SaAdminCheckPermission(parentName = "分享奖励基础", value = "share:config", name = "分享-配置") + public CzgResult getShareBase() { + return CzgResult.success(mkShareBaseService.getShareBase(StpKit.USER.getShopId())); + } + + /** + * 分享奖励基础:新增/修改 + */ + @PostMapping + @SaAdminCheckPermission(parentName = "分享奖励基础", value = "share:up", name = "分享-新增/修改") + public CzgResult editShareBase(@RequestBody MkShareBase shareBase) { + shareBase.setShopId(StpKit.USER.getShopId()); + MkShareBase share = mkShareBaseService.getById(shareBase.getShopId()); + if (share == null) { + return CzgResult.success(mkShareBaseService.save(shareBase)); + } else { + return CzgResult.success(mkShareBaseService.updateById(shareBase, false)); + } + } +} \ No newline at end of file diff --git a/cash-api/market-server/src/main/java/com/czg/controller/admin/DistributionUserController.java b/cash-api/market-server/src/main/java/com/czg/controller/admin/DistributionUserController.java index 6d54f29bd..e442bbe42 100644 --- a/cash-api/market-server/src/main/java/com/czg/controller/admin/DistributionUserController.java +++ b/cash-api/market-server/src/main/java/com/czg/controller/admin/DistributionUserController.java @@ -1,5 +1,6 @@ package com.czg.controller.admin; +import com.czg.annotation.Debounce; import com.czg.annotation.SaAdminCheckPermission; import com.czg.log.annotation.OperationLog; import com.czg.market.dto.MkDistributionUserDTO; @@ -57,6 +58,7 @@ public class DistributionUserController { * * @return 是否成功 */ + @Debounce @PostMapping @OperationLog("分销员-添加") @SaAdminCheckPermission(parentName = "分销相关",value = "distribution:user:add", name = "分销员添加") diff --git a/cash-api/market-server/src/main/java/com/czg/controller/user/UCarouselController.java b/cash-api/market-server/src/main/java/com/czg/controller/user/UCarouselController.java new file mode 100644 index 000000000..97a7adf7a --- /dev/null +++ b/cash-api/market-server/src/main/java/com/czg/controller/user/UCarouselController.java @@ -0,0 +1,70 @@ +package com.czg.controller.user; + +import com.czg.market.dto.MkCarouselDTO; +import com.czg.market.entity.MkCarousel; +import com.czg.market.entity.MkShareBase; +import com.czg.market.service.MkCarouselService; +import com.czg.market.service.MkShareBaseService; +import com.czg.resp.CzgResult; +import com.czg.sa.StpKit; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + + +/** + * 轮播图配置 + * + * @author ww + */ +@RestController +@RequestMapping("/user") +public class UCarouselController { + + @Resource + private MkCarouselService mkCarouselService; + + @Resource + private MkShareBaseService mkShareBaseService; + + + /** + * 轮播图配置 + */ + @GetMapping("/carousel") + public CzgResult> getCarousels(MkCarouselDTO carouselDTO) { + carouselDTO.setShopId(StpKit.USER.getShopId()); + carouselDTO.setIsEnabled(1); + return CzgResult.success(mkCarouselService.getCarousels(carouselDTO)); + } + + /** + * 分享 领取触发 + * + * @param tagType + * @param shopId + * @param fromUserId 分享人的shopUserId + * @param toUserId 被分享人的shopUserId + */ + public record ShareClaim(String tagType, Long shopId, Long fromUserId, Long toUserId) { + } + + /** + * 分享 基础配置 + */ + @GetMapping("/share") + public CzgResult share(@RequestParam Long shopId) { + return CzgResult.success(mkShareBaseService.getShareBase(shopId)); + } + + /** + * 分享 领取触发 + * 会绑定上下级关系 + */ + @PostMapping("/shareClaim") + public CzgResult shareClaim(@RequestBody ShareClaim shareClaim) { + mkShareBaseService.shareClaim(shareClaim.tagType, shareClaim.shopId, shareClaim.fromUserId, shareClaim.toUserId); + return CzgResult.success(); + } +} \ No newline at end of file diff --git a/cash-api/market-server/src/main/java/com/czg/controller/user/UDistributionController.java b/cash-api/market-server/src/main/java/com/czg/controller/user/UDistributionController.java index 7d5b1c4c7..3294306ee 100644 --- a/cash-api/market-server/src/main/java/com/czg/controller/user/UDistributionController.java +++ b/cash-api/market-server/src/main/java/com/czg/controller/user/UDistributionController.java @@ -3,6 +3,7 @@ package com.czg.controller.user; import com.czg.account.entity.UserInfo; import com.czg.market.dto.MkDistributionUserDTO; import com.czg.market.dto.MkDistributionWithdrawFlowDTO; +import com.czg.market.entity.MkDistributionUser; import com.czg.market.entity.MkDistributionWithdrawFlow; import com.czg.market.service.MkDistributionConfigService; import com.czg.market.service.MkDistributionFlowService; @@ -16,17 +17,16 @@ import com.czg.sa.StpKit; import com.czg.task.DistributionTask; import com.czg.utils.AssertUtil; import com.mybatisflex.core.paginate.Page; -import io.seata.core.exception.TransactionException; +import com.mybatisflex.core.query.QueryWrapper; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; -import org.springframework.core.NestedExceptionUtils; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.Map; /** - * 分销相关 + * 全民股东相关 * * @author Administrator */ @@ -60,7 +60,7 @@ public class UDistributionController { /** - * 分销员中心-获取配置 + * 全民股东=-获取配置 */ @GetMapping("/getConfig") public CzgResult getConfig(@RequestParam Long shopId) { @@ -68,7 +68,7 @@ public class UDistributionController { } /** - * 分销员中心-首页 + * 全民股东-首页 */ @PostMapping("/centerUser") public CzgResult> centerUser() { @@ -76,7 +76,7 @@ public class UDistributionController { } /** - * 分销员中心-已开通的店铺 + * 全民股东界-已开通的店铺 */ @GetMapping("/centerUser/activates") public CzgResult> activates(@RequestParam(required = false, defaultValue = "1") Integer page, @RequestParam(required = false, defaultValue = "10") Integer size) { @@ -84,7 +84,7 @@ public class UDistributionController { } /** - * 分销员中心-未开通的店铺 + * 全民股东-未开通的店铺 */ @GetMapping("/centerUser/unActivates") public CzgResult> unActivates(@RequestParam(required = false, defaultValue = "1") Integer page, @RequestParam(required = false, defaultValue = "10") Integer size) { @@ -92,7 +92,7 @@ public class UDistributionController { } /** - * 分销员中心-配置信息 + * 全民股东-配置信息 */ @GetMapping("/centerConfig") public CzgResult> centerConfig(@RequestParam Long shopId) { @@ -100,29 +100,27 @@ public class UDistributionController { } /** - * 分销员中心-获取邀请码 + * 全民股东界面-进入过标识 + */ + @GetMapping("/editIn") + public CzgResult editIn(@RequestParam Long shopUserId) { + MkDistributionUser distributionUser = new MkDistributionUser(); + distributionUser.setFirstIn(1); + distributionUserService.update(distributionUser, QueryWrapper.create().eq(MkDistributionUser::getId, shopUserId)); + return CzgResult.success(); + } + + /** + * 全民股东-获取邀请码 */ @GetMapping("/getInviteCode") public CzgResult getInviteCode(@RequestParam Long shopId, @RequestParam Long shopUserId) { return CzgResult.success(distributionUserService.getInviteCode(shopId, shopUserId)); } - /** - * 分销员中心-获取邀请码 - */ - @GetMapping("/autoGetInviteCode") - public CzgResult autoGetInviteCode(@RequestParam Long shopId, @RequestParam Long shopUserId) { - try { - return CzgResult.success(distributionUserService.getInviteCode(shopId, shopUserId)); - } catch (Exception e) { - String rootMsg = NestedExceptionUtils.getMostSpecificCause(e).getMessage(); - log.error("获取邀请码失败用户:{},:{}", shopUserId, rootMsg); - return CzgResult.success(""); - } - } /** - * 分销员中心-实名认证 + * 全民股东-实名认证 */ @PostMapping("/realNameAuth") public CzgResult> realNameAuth(@RequestBody UserInfo userInfo) { @@ -134,21 +132,7 @@ public class UDistributionController { } /** - * 分销员中心-无感-绑定邀请人 - */ - @PostMapping("/autoBindInviteUser") - public CzgResult> autoBindInviteUser(@RequestBody MkDistributionUserDTO param) throws TransactionException { - try { - bindInviteUser(param); - } catch (Exception e) { - log.error("无感绑定邀请人失败:{}", param, e); - } - return CzgResult.success(); - } - - - /** - * 分销员中心-绑定邀请人 + * 全民股东-绑定邀请人 */ @PostMapping("/bindInviteUser") public CzgResult> bindInviteUser(@RequestBody MkDistributionUserDTO param) { @@ -160,7 +144,7 @@ public class UDistributionController { } /** - * 分销员:获取邀请人分页列表 + * 全民股东:获取邀请人分页列表 */ @GetMapping("/inviteUser") public CzgResult> getInviteUser( diff --git a/cash-api/order-server/src/main/java/com/czg/controller/pay/OrderPayController.java b/cash-api/order-server/src/main/java/com/czg/controller/pay/OrderPayController.java index 1dd810962..98daf88cd 100644 --- a/cash-api/order-server/src/main/java/com/czg/controller/pay/OrderPayController.java +++ b/cash-api/order-server/src/main/java/com/czg/controller/pay/OrderPayController.java @@ -20,6 +20,7 @@ import com.mybatisflex.core.query.QueryWrapper; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletRequest; import org.apache.dubbo.config.annotation.DubboReference; +import org.springframework.beans.factory.annotation.Value; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -44,6 +45,8 @@ public class OrderPayController { private OrderInfoService orderInfoService; @DubboReference private SysParamsService paramsService; + @Value("${spring.profiles.active}") + private String env; @PostMapping("/creditPay") @Debounce(value = "#payParam.checkOrderPay.orderId") @@ -154,6 +157,7 @@ public class OrderPayController { AssertUtil.isNull(shopId, "店铺id不能为空"); AssertUtil.isNull(checkOrderPay, "订单信息不能为空"); Map map = new HashMap<>(); + map.put("env", env); map.put("shopId", shopId); map.put("orderId", checkOrderPay.getOrderId()); map.put("payAmount", checkOrderPay.getOrderAmount()); diff --git a/cash-api/order-server/src/main/java/com/czg/task/EntryManagerTask.java b/cash-api/order-server/src/main/java/com/czg/task/EntryManagerTask.java index 738c6850f..796f86f7f 100644 --- a/cash-api/order-server/src/main/java/com/czg/task/EntryManagerTask.java +++ b/cash-api/order-server/src/main/java/com/czg/task/EntryManagerTask.java @@ -38,7 +38,7 @@ public class EntryManagerTask { log.info("进件查询,定时任务执行"); long start = System.currentTimeMillis(); entryManager(null); - log.info("进件查询,定时任务执行完毕,耗时:{}ms", start - System.currentTimeMillis()); + log.info("进件查询,定时任务执行完毕,耗时:{}ms", System.currentTimeMillis() - start); } /** diff --git a/cash-api/order-server/src/main/java/com/czg/task/StatisticTask.java b/cash-api/order-server/src/main/java/com/czg/task/StatisticTask.java index 2805973b6..160a6c7db 100644 --- a/cash-api/order-server/src/main/java/com/czg/task/StatisticTask.java +++ b/cash-api/order-server/src/main/java/com/czg/task/StatisticTask.java @@ -17,6 +17,7 @@ import java.util.List; /** * 统计任务 + * * @author Administrator */ @Component @@ -43,7 +44,7 @@ public class StatisticTask { // 获取前一天 LocalDate yesterday = LocalDate.now().minusDays(1); baseStatistic(yesterday); - log.info("统计数据,定时任务执行完毕,耗时:{}ms", start - System.currentTimeMillis()); + log.info("统计数据,定时任务执行完毕,耗时:{}ms", System.currentTimeMillis() - start); } diff --git a/cash-api/product-server/src/main/java/com/czg/controller/admin/ProductController.java b/cash-api/product-server/src/main/java/com/czg/controller/admin/ProductController.java index 628edb9be..2baf25503 100644 --- a/cash-api/product-server/src/main/java/com/czg/controller/admin/ProductController.java +++ b/cash-api/product-server/src/main/java/com/czg/controller/admin/ProductController.java @@ -2,6 +2,7 @@ package com.czg.controller.admin; import cn.hutool.core.convert.Convert; import cn.hutool.core.thread.ThreadUtil; +import com.alibaba.fastjson2.JSONObject; import com.czg.account.entity.ShopInfo; import com.czg.account.service.ShopInfoService; import com.czg.config.RabbitPublisher; @@ -26,10 +27,12 @@ import com.czg.validator.group.InsertGroup; import com.czg.validator.group.UpdateGroup; import com.mybatisflex.core.paginate.Page; import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.List; +import java.util.Map; /** @@ -66,9 +69,24 @@ public class ProductController { @GetMapping("page") @OperationLog("商品-分页") //@SaAdminCheckPermission("product:page") - public CzgResult> getProductPage(ProductDTO param) { + public CzgResult> getProductPage(ProductDTO param) { Page data = productService.getProductPage(param); - return CzgResult.success(data); + Map map = JSONObject.parseObject(JSONObject.toJSONString(data), Map.class); + if (data.getRecords() != null && !data.getRecords().isEmpty()) { + ProductDTO first = data.getRecords().getFirst(); + map.put("warnLine", first.getWarnLine()); + } else { + map.put("warnLine", 0); + } + return CzgResult.success(map); + } + + /** + * 导出商品 + */ + @GetMapping("export") + public void exportProduct(ProductDTO param, HttpServletResponse response) { + productService.exportProductList(param, response); } /** @@ -82,9 +100,7 @@ public class ProductController { param.setShopId(shopId); List productList = productService.getProductCacheList(param); productService.refreshProductStock(param, productList); - productList.forEach(prod -> { - prod.setIsSaleTime(uProductService.calcIsSaleTime(prod.getDays(), prod.getStartTime(), prod.getEndTime())); - }); + productList.forEach(prod -> prod.setIsSaleTime(uProductService.calcIsSaleTime(prod.getDays(), prod.getStartTime(), prod.getEndTime()))); return CzgResult.success(productList); } @@ -111,13 +127,11 @@ public class ProductController { for (ProdSkuDTO prodSkuDTO : dto.getSkuList()) { ValidatorUtil.validateEntity(prodSkuDTO, DefaultGroup.class); } - Long shopId = StpKit.USER.getShopId(0L); + Long shopId = StpKit.USER.getShopId(); dto.setShopId(shopId); productService.addProduct(dto); asyncProductToShop(dto.getId()); - ThreadUtil.execAsync(() -> { - rabbitPublisher.sendProductInfoChangeMsg(Convert.toStr(shopId)); - }); + ThreadUtil.execAsync(() -> rabbitPublisher.sendProductInfoChangeMsg(Convert.toStr(shopId))); return CzgResult.success(); } @@ -140,13 +154,11 @@ public class ProductController { if (dto.getStockNumber() != null) { StpKit.USER.checkStaffPermission("yun_xu_xiu_gai_shang_pin_ku_cun"); } - Long shopId = StpKit.USER.getShopId(0L); + Long shopId = StpKit.USER.getShopId(); dto.setShopId(shopId); productService.updateProduct(dto); asyncProductToShop(dto.getId()); - ThreadUtil.execAsync(() -> { - rabbitPublisher.sendProductInfoChangeMsg(Convert.toStr(shopId)); - }); + ThreadUtil.execAsync(() -> rabbitPublisher.sendProductInfoChangeMsg(Convert.toStr(shopId))); return CzgResult.success(); } @@ -155,12 +167,10 @@ public class ProductController { //@SaStaffCheckPermission("yun_xu_xiu_gai_shang_pin") public CzgResult updateProductStock(@RequestBody ProductModifyStockParam param) { ValidatorUtil.validateEntity(param, DefaultGroup.class); - Long shopId = StpKit.USER.getShopId(0L); + Long shopId = StpKit.USER.getShopId(); param.setShopId(shopId); productService.updateProductStock(param); - ThreadUtil.execAsync(() -> { - rabbitPublisher.sendProductInfoChangeMsg(Convert.toStr(shopId)); - }); + ThreadUtil.execAsync(() -> rabbitPublisher.sendProductInfoChangeMsg(Convert.toStr(shopId))); return CzgResult.success(); } @@ -176,12 +186,10 @@ public class ProductController { public CzgResult deleteProduct(@PathVariable("id") Long id) { //效验数据 AssertUtil.isNull(id, "{}不能为空", "id"); - Long shopId = StpKit.USER.getShopId(0L); + Long shopId = StpKit.USER.getShopId(); productService.deleteProduct(shopId, id); asyncProductToShop(id); - ThreadUtil.execAsync(() -> { - rabbitPublisher.sendProductInfoChangeMsg(Convert.toStr(shopId)); - }); + ThreadUtil.execAsync(() -> rabbitPublisher.sendProductInfoChangeMsg(Convert.toStr(shopId))); return CzgResult.success(); } @@ -193,12 +201,10 @@ public class ProductController { //@SaStaffCheckPermission("yun_xu_shang_xia_jia_shang_pin") //@SaAdminCheckPermission("product:on-off") public CzgResult onOffProduct(@RequestBody @Validated({DefaultGroup.class}) ProductIsSaleParam param) { - Long shopId = StpKit.USER.getShopId(0L); + Long shopId = StpKit.USER.getShopId(); param.setShopId(shopId); productService.onOffProduct(param); - ThreadUtil.execAsync(() -> { - rabbitPublisher.sendProductInfoChangeMsg(Convert.toStr(shopId)); - }); + ThreadUtil.execAsync(() -> rabbitPublisher.sendProductInfoChangeMsg(Convert.toStr(shopId))); return CzgResult.success(); } @@ -210,12 +216,10 @@ public class ProductController { //@SaStaffCheckPermission("yun_xu_shou_qing_shang_pin") //@SaAdminCheckPermission("product:markIsSoldOut") public CzgResult markIsSoldOutProduct(@RequestBody @Validated({DefaultGroup.class}) ProductIsSoldOutParam param) { - Long shopId = StpKit.USER.getShopId(0L); + Long shopId = StpKit.USER.getShopId(); param.setShopId(shopId); productService.markProductIsSoldOut(param); - ThreadUtil.execAsync(() -> { - rabbitPublisher.sendProductInfoChangeMsg(Convert.toStr(shopId)); - }); + ThreadUtil.execAsync(() -> rabbitPublisher.sendProductInfoChangeMsg(Convert.toStr(shopId))); return CzgResult.success(); } @@ -312,9 +316,7 @@ public class ProductController { if (shopInfo.getMainId() == null || shopId == shopInfo.getMainId()) { throw new CzgException("不存在主子店铺关系,无需同步商品信息"); } - ThreadUtil.execAsync(() -> { - shopSyncService.sync(shopInfo.getMainId(), shopId, shopId); - }); + ThreadUtil.execAsync(() -> shopSyncService.sync(shopInfo.getMainId(), shopId, shopId)); CzgResult ret = CzgResult.success(); ret.setMsg("操作成功,数据正在后台同步中..."); return ret; @@ -322,15 +324,11 @@ public class ProductController { private void asyncProductToShop(Long id) { long shopId = StpKit.USER.getShopId(0L); - ThreadUtil.execAsync(() -> { - shopSyncService.syncProductBySourceShop(shopId, id, shopId); - }); + ThreadUtil.execAsync(() -> shopSyncService.syncProductBySourceShop(shopId, id, shopId)); } private void asyncConsProToShop(Long id) { long shopId = StpKit.USER.getShopId(0L); - ThreadUtil.execAsync(() -> { - shopSyncService.syncConsProBySourceShop(shopId, id, shopId); - }); + ThreadUtil.execAsync(() -> shopSyncService.syncConsProBySourceShop(shopId, id, shopId)); } } diff --git a/cash-api/system-server/src/main/java/com/czg/controller/admin/MiniAppPagesController.java b/cash-api/system-server/src/main/java/com/czg/controller/admin/MiniAppPagesController.java index 84faf8b88..6e44e502b 100644 --- a/cash-api/system-server/src/main/java/com/czg/controller/admin/MiniAppPagesController.java +++ b/cash-api/system-server/src/main/java/com/czg/controller/admin/MiniAppPagesController.java @@ -58,7 +58,7 @@ public class MiniAppPagesController { * @param status 小程序页面状态 -1 查全部 1 启用 0 禁用 */ @GetMapping("page") - @SaAdminCheckPermission(parentName = "小程序页面",value = "miniAppPages:page", name = "小程序页面分页") +// @SaAdminCheckPermission(parentName = "小程序页面",value = "miniAppPages:page", name = "小程序页面分页") public CzgResult> getMiniAppPage(String name, String path, Integer status) { return miniAppPageService.getMiniAppPage(name, path, status); } diff --git a/cash-common/cash-common-service/src/main/java/com/czg/account/dto/shopuser/ShopUserDTO.java b/cash-common/cash-common-service/src/main/java/com/czg/account/dto/shopuser/ShopUserDTO.java index d81826f51..aca7b9f10 100644 --- a/cash-common/cash-common-service/src/main/java/com/czg/account/dto/shopuser/ShopUserDTO.java +++ b/cash-common/cash-common-service/src/main/java/com/czg/account/dto/shopuser/ShopUserDTO.java @@ -28,5 +28,4 @@ public class ShopUserDTO extends ShopUser { private String nextMemberLevelName; private Long nextExperience; private Long pointBalance; - private boolean isNew; } diff --git a/cash-common/cash-common-service/src/main/java/com/czg/account/dto/shopuser/ShopUserExportDTO.java b/cash-common/cash-common-service/src/main/java/com/czg/account/dto/shopuser/ShopUserExportDTO.java new file mode 100644 index 000000000..b3a99931d --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/account/dto/shopuser/ShopUserExportDTO.java @@ -0,0 +1,116 @@ +package com.czg.account.dto.shopuser; + +import cn.hutool.core.util.StrUtil; +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * @author yjjie + * @date 2026/1/28 11:30 + */ +@Data +public class ShopUserExportDTO { + + @ExcelProperty("手机号") + private String phone; + + @ExcelProperty("会员生日") + private String birthDay; + + @ExcelProperty("用户昵称") + private String nickName; + + @ExcelIgnore + private Integer status; + @ExcelProperty("会员状态") + private String statusRemark; + + @ExcelIgnore + private Integer isVip; + @ExcelProperty("是否会员") + private String vipRemark; + + @ExcelProperty("会员编号") + private String code; + + @ExcelProperty("余额") + private BigDecimal amount; + + @ExcelProperty("充值次数") + private Integer rechargeCount; + + @ExcelProperty("消费累计") + private BigDecimal consumeAmount; + + @ExcelProperty("消费次数") + private Integer consumeCount; + + @ExcelProperty("经验值") + private Long experience; + + @ExcelIgnore + private String distributionShops; + @ExcelProperty("是否分销员") + private String distributionShopsRemark; + + @ExcelProperty("优惠券数量") + private Long couponNum; + + @ExcelProperty("订单数量") + private Long orderNumber; + + @ExcelProperty("充值金额") + private BigDecimal rechargeAmount; + + @ExcelProperty("会员等级") + private String memberLevelName; + + @ExcelProperty("下一级会员等级") + private String nextMemberLevelName; + + @ExcelProperty("升级所需经验值") + private Long nextExperience; + + @ExcelProperty("积分余额") + private Long pointBalance; + + @ExcelProperty("加入会员时间") + private LocalDateTime joinTime; + + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + public String getVipRemark() { + if (isVip == null || isVip == 0) { + return "否"; + } + return "是"; + } + + public String getStatusRemark() { + if (status == null || status == 0) { + return "禁用"; + } + return "正常"; + } + + public String getDistributionShopsRemark() { + if (StrUtil.isBlank(distributionShops) || !distributionShops.contains("_")) { + return "否"; + } + + String[] split = distributionShops.split("_"); + if (split.length < 2) { + return "否"; + } + if ("0".equals(split[1])) { + return "否"; + } + + return "是"; + } +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/account/service/AShopUserService.java b/cash-common/cash-common-service/src/main/java/com/czg/account/service/AShopUserService.java index fedebbd0c..905d43540 100644 --- a/cash-common/cash-common-service/src/main/java/com/czg/account/service/AShopUserService.java +++ b/cash-common/cash-common-service/src/main/java/com/czg/account/service/AShopUserService.java @@ -4,6 +4,7 @@ import com.czg.account.dto.shopuser.*; import com.czg.account.entity.ShopUser; import com.czg.market.entity.SmsPushEventUser; import com.mybatisflex.core.paginate.Page; +import jakarta.servlet.http.HttpServletResponse; import java.math.BigDecimal; import java.util.List; @@ -22,6 +23,8 @@ public interface AShopUserService { Page getPushEventUser(SmsPushEventUser smsPushEventUser); Page getAcPushEventUser(SmsPushEventUser smsPushEventUser); + void exportUserList(String key, Integer isVip, HttpServletResponse response); + Boolean add(Long shopId, ShopUserAddDTO shopUserAddDTO); diff --git a/cash-common/cash-common-service/src/main/java/com/czg/account/service/ShopConfigService.java b/cash-common/cash-common-service/src/main/java/com/czg/account/service/ShopConfigService.java index f4f21941c..a7bc942a9 100644 --- a/cash-common/cash-common-service/src/main/java/com/czg/account/service/ShopConfigService.java +++ b/cash-common/cash-common-service/src/main/java/com/czg/account/service/ShopConfigService.java @@ -5,7 +5,6 @@ import com.czg.account.entity.ShopInfo; import com.czg.exception.CzgException; import com.mybatisflex.core.service.IService; -import java.io.Serializable; import java.util.List; /** @@ -16,7 +15,7 @@ import java.util.List; */ public interface ShopConfigService extends IService { - ShopInfo getShopInfoAndConfig(Serializable id) throws CzgException; + ShopInfo getShopInfoAndConfig(Long id) throws CzgException; void editStatusByShopIdList(Long mainShopId, Integer isEnable, boolean onyUpValid, String name, String useShopType, List shopIdList); diff --git a/cash-common/cash-common-service/src/main/java/com/czg/market/dto/MkCarouselDTO.java b/cash-common/cash-common-service/src/main/java/com/czg/market/dto/MkCarouselDTO.java new file mode 100644 index 000000000..213d00b58 --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/market/dto/MkCarouselDTO.java @@ -0,0 +1,46 @@ + +package com.czg.market.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 轮播图配置表 实体类。 + * + * @author ww + * @since 2026-01-27 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class MkCarouselDTO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 店铺Id + */ + private Long shopId; + + /** + * 轮播图名称(20字内) + */ + private String name; + + /** + * 是否可分享 1=开启 0=关闭 + */ + private Integer isShareable; + + /** + * 启用状态 1=启用 0=禁用 + */ + private Integer isEnabled; +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/market/entity/MkCarousel.java b/cash-common/cash-common-service/src/main/java/com/czg/market/entity/MkCarousel.java new file mode 100644 index 000000000..41fdfcf89 --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/market/entity/MkCarousel.java @@ -0,0 +1,97 @@ +package com.czg.market.entity; + +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.KeyType; +import com.mybatisflex.annotation.Table; +import java.io.Serializable; +import java.math.BigInteger; +import java.time.LocalDateTime; + +import java.io.Serial; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 轮播图配置表 实体类。 + * + * @author ww + * @since 2026-01-27 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Table("mk_carousel") +public class MkCarousel implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 主键ID + */ + @Id(keyType = KeyType.Auto) + private BigInteger id; + + /** + * 店铺Id + */ + private Long shopId; + + /** + * 轮播图名称(20字内) + */ + private String name; + + /** + * 轮播图片地址 + */ + private String imageUrl; + + /** + * 是否可分享 1=开启 0=关闭 + */ + private Integer isShareable; + + /** + * 跳转页面 tb_mini_app_pages的 id + */ + private Long jumpPageId; + /** + * 跳转页面路径 + */ + @Column(ignore = true) + private String jumpPagePath; + + /** + * 扩展参数 + */ + private String extendParam; + + /** + * 排序值,值越大越靠前 + */ + private Integer sort; + + /** + * 启用状态 1=启用 0=禁用 + */ + private Integer isEnabled; + + /** + * 创建时间 + */ + @Column(onInsertValue = "now()") + private LocalDateTime createTime; + + /** + * 更新时间 + */ + @Column(onInsertValue = "now()", onUpdateValue = "now()") + private LocalDateTime updateTime; + +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/market/entity/MkDistributionGroup.java b/cash-common/cash-common-service/src/main/java/com/czg/market/entity/MkDistributionGroup.java new file mode 100644 index 000000000..226dab36d --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/market/entity/MkDistributionGroup.java @@ -0,0 +1,67 @@ +package com.czg.market.entity; + +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.Table; +import java.io.Serializable; +import java.time.LocalDateTime; + +import java.io.Serial; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 分销员管理群(全民股东管理) 实体类。 + * + * @author ww + * @since 2026-01-28 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Table("mk_distribution_group") +public class MkDistributionGroup implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + @Id + private Long shopId; + + /** + * 群二维码地址 + */ + private String groupUrl; + + /** + * 模块标题 15字以内 + */ + private String title; + + /** + * 模块内容 20字以内 + */ + private String content; + + /** + * 是否开启 + */ + private Integer isEnable; + + /** + * 创建时间 + */ + @Column(onInsertValue = "now()") + private LocalDateTime createTime; + + /** + * 更新时间 + */ + @Column(onInsertValue = "now()", onUpdateValue = "now()") + private LocalDateTime updateTime; + +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/market/entity/MkDistributionUser.java b/cash-common/cash-common-service/src/main/java/com/czg/market/entity/MkDistributionUser.java index c7950afca..f739c3d2a 100644 --- a/cash-common/cash-common-service/src/main/java/com/czg/market/entity/MkDistributionUser.java +++ b/cash-common/cash-common-service/src/main/java/com/czg/market/entity/MkDistributionUser.java @@ -1,7 +1,6 @@ package com.czg.market.entity; import com.mybatisflex.annotation.Id; -import com.mybatisflex.annotation.KeyType; import com.mybatisflex.annotation.Table; import lombok.AllArgsConstructor; import lombok.Builder; @@ -117,5 +116,9 @@ public class MkDistributionUser implements Serializable { * 邀请码 */ private String inviteCode; + /** + * 是否第一次进入全民股东界面 + */ + private Integer firstIn; } diff --git a/cash-common/cash-common-service/src/main/java/com/czg/market/entity/MkShareBase.java b/cash-common/cash-common-service/src/main/java/com/czg/market/entity/MkShareBase.java new file mode 100644 index 000000000..1984660dd --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/market/entity/MkShareBase.java @@ -0,0 +1,114 @@ +package com.czg.market.entity; + +import com.czg.market.dto.ShopCouponDTO; +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.Table; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * 分享奖励基础配置 实体类。 + * + * @author ww + * @since 2026-01-27 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Table("mk_share_base") +public class MkShareBase implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 店铺id + */ + @Id + private Long shopId; + + /** + * 功能开启状态 1=开启 0=关闭 + */ + private Integer isEnabled; + + /** + * 可获得奖励的分享页面,用逗号分隔, + * 店铺首页 index + * 我的 dine + * 点餐页 eat + * 点餐页 eat-detail + * 套餐推广-列表 pp-list + * 套餐推广-详情 pp-detail + * 商品拼团-列表 gb-list + * 商品拼团-详情 gb-detail + * 全民股东 dis + */ + private String rewardSharePages; + + /** + * 分享人奖励的优惠券ID,关联优惠券表 + */ + private Long sharerCouponId; + /** + * 分享人奖励的优惠券信息 + */ + @Column(ignore = true) + private ShopCouponDTO sharerCoupon; + /** + * 分享人奖励的优惠券名称 + */ + @Column(ignore = true) + private String sharerCouponName; + + /** + * 分享人单次获得优惠券数量 + */ + private Integer sharerCouponNum; + + /** + * 可获得奖励次数 1=仅1次 2=每次分享成功 + */ + private Integer rewardTimesType; + + /** + * 被分享人奖励的优惠券ID,关联优惠券表(可选) + */ + private Long sharedUserCouponId; + /** + * 被分享人奖励的优惠券名称 + */ + @Column(ignore = true) + private String sharedUserCouponName; + + /** + * 被分享人单次获得优惠券数量(可选) + */ + private Integer sharedUserCouponNum; + + /** + * 被分享人弹窗开关 1=开启 0=关闭 + */ + private Integer isSharedUserPopup; + + /** + * 创建时间 + */ + @Column(onInsertValue = "now()") + private LocalDateTime createTime; + + /** + * 更新时间 + */ + @Column(onInsertValue = "now()", onUpdateValue = "now()") + private LocalDateTime updateTime; + +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/market/service/MkCarouselService.java b/cash-common/cash-common-service/src/main/java/com/czg/market/service/MkCarouselService.java new file mode 100644 index 000000000..06beaec24 --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/market/service/MkCarouselService.java @@ -0,0 +1,19 @@ +package com.czg.market.service; + +import com.czg.market.dto.MkCarouselDTO; +import com.mybatisflex.core.service.IService; +import com.czg.market.entity.MkCarousel; + +import java.util.List; + +/** + * 轮播图配置表 服务层。 + * + * @author ww + * @since 2026-01-27 + */ +public interface MkCarouselService extends IService { + + List getCarousels(MkCarouselDTO mkCarouselDTO); + +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/market/service/MkDistributionGroupService.java b/cash-common/cash-common-service/src/main/java/com/czg/market/service/MkDistributionGroupService.java new file mode 100644 index 000000000..bbfdd0cd2 --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/market/service/MkDistributionGroupService.java @@ -0,0 +1,14 @@ +package com.czg.market.service; + +import com.mybatisflex.core.service.IService; +import com.czg.market.entity.MkDistributionGroup; + +/** + * 分销员管理群(全民股东管理) 服务层。 + * + * @author ww + * @since 2026-01-28 + */ +public interface MkDistributionGroupService extends IService { + +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/market/service/MkDistributionUserService.java b/cash-common/cash-common-service/src/main/java/com/czg/market/service/MkDistributionUserService.java index 6afc074f5..908fe49ec 100644 --- a/cash-common/cash-common-service/src/main/java/com/czg/market/service/MkDistributionUserService.java +++ b/cash-common/cash-common-service/src/main/java/com/czg/market/service/MkDistributionUserService.java @@ -60,9 +60,18 @@ public interface MkDistributionUserService extends IService /** * 分销员中心-绑定邀请人 + * 通过邀请码 */ void bindInviteUser(MkDistributionUserDTO param) throws CzgException, ValidateException; + + /** + * 分销员中心-绑定邀请人 + * 通过邀请人id + * @param fromUserId shopUserId 邀请人 + * @param toUserId 被邀请人邀请人 + */ + void bindInviteUser(Long fromUserId, Long toUserId, Long shopId) throws CzgException, ValidateException; /** * 获取分销员分页列表 */ diff --git a/cash-common/cash-common-service/src/main/java/com/czg/market/service/MkShareBaseService.java b/cash-common/cash-common-service/src/main/java/com/czg/market/service/MkShareBaseService.java new file mode 100644 index 000000000..f214c51b0 --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/market/service/MkShareBaseService.java @@ -0,0 +1,17 @@ +package com.czg.market.service; + +import com.mybatisflex.core.service.IService; +import com.czg.market.entity.MkShareBase; + +/** + * 分享奖励基础配置 服务层。 + * + * @author ww + * @since 2026-01-27 + */ +public interface MkShareBaseService extends IService { + + MkShareBase getShareBase(Long shopId); + + void shareClaim(String tagType, Long shopId, Long fromUserId, Long toUserId); +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/product/dto/ProductExportDTO.java b/cash-common/cash-common-service/src/main/java/com/czg/product/dto/ProductExportDTO.java new file mode 100644 index 000000000..a86269586 --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/product/dto/ProductExportDTO.java @@ -0,0 +1,104 @@ +package com.czg.product.dto; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalTime; + +/** + * 商品导出 + * @author yjjie + * @date 2026/1/28 14:30 + */ +@Data +public class ProductExportDTO { + + @ExcelProperty("商品名称") + @ColumnWidth(20) + private String name; + + @ExcelProperty("商品分类") + @ColumnWidth(15) + private String categoryName; + + @ExcelProperty("条码") + @ColumnWidth(20) + private String barCode; + + @ExcelProperty("商品规格") + @ColumnWidth(20) + private String specFullName; + + @ExcelProperty("售价") + @ColumnWidth(10) + private BigDecimal price; + @ExcelProperty("会员价") + @ColumnWidth(10) + private BigDecimal memberPrice; + @ExcelProperty("成本价") + @ColumnWidth(10) + private BigDecimal costPrice; + + @ExcelProperty("商品单位") + @ColumnWidth(10) + private String unitName; + + /** + * 商品类型 single-单规格商品 sku-多规格商品 package-套餐商品 weight-称重商品 coupon-团购券 + */ + @ExcelProperty("商品类型") + @ColumnWidth(15) + private String type; + + /** + * 可用开始时间 + */ + @ExcelProperty("可用开始时间") + @ColumnWidth(16) + private LocalTime startTime; + /** + * 可用结束时间 + */ + @ExcelProperty("可用结束时间") + @ColumnWidth(16) + private LocalTime endTime; + + /** + * 商品级库存数量 + */ + @ExcelProperty("库存数量") + @ColumnWidth(10) + private Integer stockNumber; + + /** + * 是否上架 + */ + @ExcelIgnore + private Integer isSale; + @ExcelProperty("是否上架") + @ColumnWidth(10) + private String isSaleRemark; + + + public String getType() { + return switch (type) { + case "single" -> "单规格商品"; + case "sku" -> "多规格商品"; + case "package" -> "套餐商品"; + case "weight" -> "称重商品"; + case "coupon" -> "团购券"; + case null, default -> "未知类型"; + }; + } + + public String getIsSaleRemark() { + return switch (isSale) { + case 0 -> "下架"; + case 1 -> "上架"; + case null, default -> "未知状态"; + }; + } +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/product/dto/ProductPackageExportDTO.java b/cash-common/cash-common-service/src/main/java/com/czg/product/dto/ProductPackageExportDTO.java new file mode 100644 index 000000000..9036e6c61 --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/product/dto/ProductPackageExportDTO.java @@ -0,0 +1,101 @@ +package com.czg.product.dto; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.ColumnWidth; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; + +/** + * 套餐商品导出 + * @author yjjie + * @date 2026/1/30 10:26 + */ +@Data +@Accessors(chain = true) +public class ProductPackageExportDTO { + + @ExcelProperty("套餐名称") + @ColumnWidth(20) + private String name; + + @ExcelProperty("套餐分类") + @ColumnWidth(15) + private String categoryName; + + @ExcelProperty("售价") + @ColumnWidth(10) + private BigDecimal price; + @ExcelProperty("会员价") + @ColumnWidth(10) + private BigDecimal memberPrice; + + /** + * 商品类型 single-单规格商品 sku-多规格商品 package-套餐商品 weight-称重商品 coupon-团购券 + */ + @ExcelIgnore() + private String type; + + /** + * 套餐类型 0 固定套餐 1可选套餐 + */ + @ExcelIgnore + private Integer groupType; + @ExcelProperty("套餐类型") + @ColumnWidth(15) + private String groupTypeRemark; + + @ExcelProperty("组名称") + @ColumnWidth(15) + private String groupTitleName; + + @ExcelProperty("商品名称") + @ColumnWidth(21) + private String groupProductName; + + @ExcelProperty("商品单位") + @ColumnWidth(10) + private String unitName; + + @ExcelProperty("套餐内选择数量") + @ColumnWidth(10) + private String groupProductNumber; + + /** + * 商品级库存数量 + */ + @ExcelProperty("库存数量") + @ColumnWidth(10) + private Integer stockNumber; + + /** + * 是否上架 + */ + @ExcelIgnore + private Integer isSale; + @ExcelProperty("是否上架") + @ColumnWidth(10) + private String isSaleRemark; + + public String getGroupTypeRemark() { + if (!"package".equals(type)) { + return ""; + } + return switch (groupType) { + case 0 -> "固定套餐"; + case 1 -> "可选套餐"; + case null, default -> "未知类型"; + }; + } + + public String getIsSaleRemark() { + return switch (isSale) { + case 0 -> "下架"; + case 1 -> "上架"; + case null, default -> "未知状态"; + }; + } + +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/product/service/ProductService.java b/cash-common/cash-common-service/src/main/java/com/czg/product/service/ProductService.java index f24801f20..420b7a7e0 100644 --- a/cash-common/cash-common-service/src/main/java/com/czg/product/service/ProductService.java +++ b/cash-common/cash-common-service/src/main/java/com/czg/product/service/ProductService.java @@ -1,13 +1,13 @@ package com.czg.product.service; import com.czg.product.dto.ProductDTO; -import com.czg.product.dto.RelatedProductDTO; import com.czg.product.entity.Product; import com.czg.product.entity.ProductStockFlow; import com.czg.product.param.*; import com.czg.product.vo.ProductStatisticsVo; import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.service.IService; +import jakarta.servlet.http.HttpServletResponse; import java.util.List; @@ -34,6 +34,8 @@ public interface ProductService extends IService { */ List getProductList(ProductDTO param); + void exportProductList(ProductDTO param, HttpServletResponse response); + /** * 从缓存里面获取商品列表 * diff --git a/cash-common/cash-common-tools/pom.xml b/cash-common/cash-common-tools/pom.xml index ccbce27f9..dd578f7da 100644 --- a/cash-common/cash-common-tools/pom.xml +++ b/cash-common/cash-common-tools/pom.xml @@ -95,6 +95,11 @@ mybatis-flex-processor provided + + + com.alibaba + easyexcel + diff --git a/cash-common/cash-common-tools/src/main/java/com/czg/excel/DataSupplier.java b/cash-common/cash-common-tools/src/main/java/com/czg/excel/DataSupplier.java new file mode 100644 index 000000000..68779d324 --- /dev/null +++ b/cash-common/cash-common-tools/src/main/java/com/czg/excel/DataSupplier.java @@ -0,0 +1,21 @@ +package com.czg.excel; + +import java.util.List; + +/** + * 数据提供者接口(用于分批获取数据) + * @author yjjie + * @date 2026/1/28 10:51 + */ +@FunctionalInterface +public interface DataSupplier { + + /** + * 获取指定页的数据 + * + * @param pageNum 页码 + * @param pageSize 每页大小 + * @return 数据列表 + */ + List getData(int pageNum, int pageSize); +} diff --git a/cash-common/cash-common-tools/src/main/java/com/czg/excel/ExcelExportConfig.java b/cash-common/cash-common-tools/src/main/java/com/czg/excel/ExcelExportConfig.java new file mode 100644 index 000000000..186cd00af --- /dev/null +++ b/cash-common/cash-common-tools/src/main/java/com/czg/excel/ExcelExportConfig.java @@ -0,0 +1,40 @@ +package com.czg.excel; + +import lombok.Data; + +/** + * Excel导出配置类 + * @author yjjie + * @date 2026/1/28 10:47 + */ +@Data +public class ExcelExportConfig { + + /** + * 默认工作表名称 + */ + private String defaultSheetName = "Sheet1"; + + /** + * 默认文件名 + */ + private String defaultFileName = "export_data"; + + /** + * 是否自动关闭流 + */ + private boolean autoCloseStream = true; + + /** + * 响应头编码 + */ + private String charset = "UTF-8"; + + public ExcelExportConfig() {} + + public ExcelExportConfig(String defaultSheetName, String defaultFileName) { + this.defaultSheetName = defaultSheetName; + this.defaultFileName = defaultFileName; + } + +} diff --git a/cash-common/cash-common-tools/src/main/java/com/czg/excel/ExcelExportUtil.java b/cash-common/cash-common-tools/src/main/java/com/czg/excel/ExcelExportUtil.java new file mode 100644 index 000000000..fffa512d7 --- /dev/null +++ b/cash-common/cash-common-tools/src/main/java/com/czg/excel/ExcelExportUtil.java @@ -0,0 +1,318 @@ +package com.czg.excel; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.write.builder.ExcelWriterBuilder; +import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder; +import com.alibaba.excel.write.handler.SheetWriteHandler; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.alibaba.excel.write.metadata.style.WriteCellStyle; +import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; +import com.czg.exception.CzgException; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.HorizontalAlignment; +import org.apache.poi.ss.usermodel.VerticalAlignment; + +import java.io.IOException; +import java.io.OutputStream; +import java.lang.reflect.Field; +import java.net.URLEncoder; +import java.util.Collections; +import java.util.List; + +/** + * EasyExcel导出工具类 + * @author yjjie + * @date 2026/1/28 10:48 + */ +@Slf4j +public class ExcelExportUtil { + + private static final ExcelExportConfig DEFAULT_CONFIG = new ExcelExportConfig(); + + /** + * 导出Excel到HttpServletResponse + * + * @param data 数据列表 + * @param clazz 数据类型 + * @param fileName 文件名(不含扩展名) + * @param response HttpServletResponse + * @param 数据类型 + */ + public static void exportToResponse(List data, Class clazz, + String fileName, HttpServletResponse response) { + exportToResponse(data, clazz, fileName, DEFAULT_CONFIG, response); + } + + /** + * 导出Excel到HttpServletResponse(自定义配置) + * + * @param data 数据列表 + * @param clazz 数据类型 + * @param fileName 文件名(不含扩展名) + * @param config 配置信息 + * @param response HttpServletResponse + * @param 数据类型 + */ + public static void exportToResponse(List data, Class clazz, + String fileName, ExcelExportConfig config, + HttpServletResponse response) { + if (data == null) { + data = Collections.emptyList(); + } + + setResponseHeader(response, fileName, config); + + try (OutputStream outputStream = response.getOutputStream()) { + ExcelWriter excelWriter = EasyExcel.write(outputStream, clazz) + .autoCloseStream(config.isAutoCloseStream()) + .build(); + + WriteSheet writeSheet = EasyExcel.writerSheet(config.getDefaultSheetName()).build(); + excelWriter.write(data, writeSheet); + excelWriter.finish(); + + log.info("Excel导出成功,文件名:{},数据量:{}", fileName, data.size()); + } catch (IOException e) { + log.error("Excel导出失败", e); + throw new CzgException("Excel导出失败", e); + } + } + + /** + * 导出Excel到文件 + * + * @param data 数据列表 + * @param clazz 数据类型 + * @param filePath 文件路径 + * @param 数据类型 + */ + public static void exportToFile(List data, Class clazz, String filePath) { + exportToFile(data, clazz, filePath, DEFAULT_CONFIG); + } + + /** + * 导出Excel到文件(自定义配置) + * + * @param data 数据列表 + * @param clazz 数据类型 + * @param filePath 文件路径 + * @param config 配置信息 + * @param 数据类型 + */ + public static void exportToFile(List data, Class clazz, + String filePath, ExcelExportConfig config) { + if (data == null) { + data = Collections.emptyList(); + } + + try { + EasyExcel.write(filePath, clazz) + .sheet(config.getDefaultSheetName()) + .doWrite(data); + log.info("Excel文件导出成功,路径:{},数据量:{}", filePath, data.size()); + } catch (Exception e) { + log.error("Excel文件导出失败", e); + throw new CzgException("Excel文件导出失败", e); + } + } + + /** + * 带样式的Excel导出到Response + * + * @param data 数据列表 + * @param clazz 数据类型 + * @param fileName 文件名 + * @param response HttpServletResponse + * @param 数据类型 + */ + public static void exportWithStyleToResponse(List data, Class clazz, + String fileName, HttpServletResponse response) { + if (data == null) { + data = Collections.emptyList(); + } + + setResponseHeader(response, fileName, DEFAULT_CONFIG); + + try (OutputStream outputStream = response.getOutputStream()) { + // 设置表格样式 + HorizontalCellStyleStrategy styleStrategy = createCellStyleStrategy(); + + ExcelWriter excelWriter = EasyExcel.write(outputStream, clazz) + .registerWriteHandler(styleStrategy) + .autoCloseStream(true) + .build(); + + WriteSheet writeSheet = EasyExcel.writerSheet(DEFAULT_CONFIG.getDefaultSheetName()).build(); + excelWriter.write(data, writeSheet); + excelWriter.finish(); + + log.info("带样式Excel导出成功,文件名:{},数据量:{}", fileName, data.size()); + } catch (IOException e) { + log.error("带样式Excel导出失败", e); + throw new CzgException("Excel导出失败", e); + } + } + + /** + * 大数据量分批导出(避免内存溢出) + * + * @param dataSupplier 数据提供者(分页获取数据) + * @param clazz 数据类型 + * @param fileName 文件名 + * @param response HttpServletResponse + * @param batchSize 每批大小 + * @param 数据类型 + */ + public static void exportBigDataToResponse(DataSupplier dataSupplier, + Class clazz, String fileName, + HttpServletResponse response, int batchSize) { + setResponseHeader(response, fileName, DEFAULT_CONFIG); + + try (OutputStream outputStream = response.getOutputStream()) { + ExcelWriter excelWriter = EasyExcel.write(outputStream, clazz) + .autoCloseStream(true) + .build(); + + WriteSheet writeSheet = EasyExcel.writerSheet(DEFAULT_CONFIG.getDefaultSheetName()).build(); + + int pageNum = 1; + List batchData; + boolean hasNext = true; + + while (hasNext) { + batchData = dataSupplier.getData(pageNum, batchSize); + if (batchData != null && !batchData.isEmpty()) { + excelWriter.write(batchData, writeSheet); + pageNum++; + } else { + hasNext = false; + } + } + + excelWriter.finish(); + log.info("大数据量Excel导出成功,文件名:{},总页数:{}", fileName, pageNum - 1); + } catch (IOException e) { + log.error("大数据量Excel导出失败", e); + throw new CzgException("Excel导出失败", e); + } + } + + /** + * 设置响应头 + */ + private static void setResponseHeader(HttpServletResponse response, String fileName, ExcelExportConfig config) { + try { + String encodedFileName = URLEncoder.encode(fileName, config.getCharset()) + .replaceAll("\\+", "%20"); + String contentDisposition = "attachment;filename*=utf-8''" + encodedFileName + ".xlsx"; + + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setCharacterEncoding(config.getCharset()); + response.setHeader("Content-Disposition", contentDisposition); + } catch (Exception e) { + log.warn("设置响应头失败", e); + } + } + + /** + * 创建表格样式策略 + */ + private static HorizontalCellStyleStrategy createCellStyleStrategy() { + // 表头样式 + WriteCellStyle headStyle = new WriteCellStyle(); + headStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); + headStyle.setVerticalAlignment(VerticalAlignment.CENTER); + + // 内容样式 + WriteCellStyle contentStyle = new WriteCellStyle(); + contentStyle.setHorizontalAlignment(HorizontalAlignment.LEFT); + contentStyle.setVerticalAlignment(VerticalAlignment.CENTER); + + return new HorizontalCellStyleStrategy(headStyle, contentStyle); + } + + /** + * 获取数据总行数(用于前端显示进度) + */ + public static int getDataCount(Class clazz) { + Field[] fields = clazz.getDeclaredFields(); + int count = 0; + for (Field field : fields) { + if (field.isAnnotationPresent(ExcelProperty.class)) { + count++; + } + } + return count; + } + + /** + * 带合并单元格的导出到Response + * 多sheet导出到response + * + * @param sheetDataList 数据列表 + * @param fileName 文件名 + * @param response HttpServletResponse + */ + public static void exportMultipleSheetsToResponse(List sheetDataList, + String fileName, + HttpServletResponse response) { + if (CollectionUtil.isEmpty(sheetDataList)) { + throw new CzgException("数据列表不能为空"); + } + + setResponseHeader(response, fileName, DEFAULT_CONFIG); + + try (OutputStream outputStream = response.getOutputStream()) { + // 创建样式策略 + WriteCellStyle headStyle = new WriteCellStyle(); + headStyle.setHorizontalAlignment(HorizontalAlignment.LEFT); + headStyle.setVerticalAlignment(VerticalAlignment.CENTER); + + WriteCellStyle contentStyle = new WriteCellStyle(); + contentStyle.setHorizontalAlignment(HorizontalAlignment.LEFT); + contentStyle.setVerticalAlignment(VerticalAlignment.CENTER); + + HorizontalCellStyleStrategy styleStrategy = new HorizontalCellStyleStrategy(headStyle, contentStyle); + + // 创建ExcelWriter + ExcelWriterBuilder builder = EasyExcel.write(outputStream) + .autoCloseStream(true) + .registerConverter(new LocalTimeConverter()) + .registerWriteHandler(styleStrategy); + + ExcelWriter excelWriter = builder.build(); + + // 逐个写入sheet + for (int i = 0; i < sheetDataList.size(); i++) { + SheetData sheetData = sheetDataList.get(i); + String sheetName = StrUtil.isNotBlank(sheetData.getSheetName()) + ? sheetData.getSheetName() + : DEFAULT_CONFIG.getDefaultSheetName() + (i + 1); + + ExcelWriterSheetBuilder sheetBuilder = EasyExcel.writerSheet(sheetName); + + // 注册该sheet的合并处理器 + if (sheetData.getHandlers() != null && !sheetData.getHandlers().isEmpty()) { + for (SheetWriteHandler handler : sheetData.getHandlers()) { + sheetBuilder.registerWriteHandler(handler); + } + } + + WriteSheet writeSheet = sheetBuilder.head(sheetData.getClazz()).build(); + excelWriter.write(sheetData.getData(), writeSheet); + } + + excelWriter.finish(); + log.info("多sheet商品Excel导出成功,文件名:{},共{}个sheet", fileName, sheetDataList.size()); + } catch (IOException e) { + log.error("多sheet商品Excel导出失败", e); + throw new CzgException("Excel导出失败", e); + } + } + +} diff --git a/cash-common/cash-common-tools/src/main/java/com/czg/excel/LocalTimeConverter.java b/cash-common/cash-common-tools/src/main/java/com/czg/excel/LocalTimeConverter.java new file mode 100644 index 000000000..3672f9af8 --- /dev/null +++ b/cash-common/cash-common-tools/src/main/java/com/czg/excel/LocalTimeConverter.java @@ -0,0 +1,47 @@ +package com.czg.excel; + +import com.alibaba.excel.converters.Converter; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.metadata.GlobalConfiguration; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.metadata.property.ExcelContentProperty; + +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; + +/** + * @author yjjie + * @date 2026/1/28 16:16 + */ +public class LocalTimeConverter implements Converter { + + private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss"); + + @Override + public Class supportJavaTypeKey() { + return LocalTime.class; + } + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return CellDataTypeEnum.STRING; + } + + @Override + public LocalTime convertToJavaData(ReadCellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + String stringValue = cellData.getStringValue(); + if (stringValue == null || stringValue.trim().isEmpty()) { + return null; + } + return LocalTime.parse(stringValue, FORMATTER); + } + + @Override + public WriteCellData convertToExcelData(LocalTime value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { + if (value == null) { + return new WriteCellData<>(""); + } + return new WriteCellData<>(value.format(FORMATTER)); + } +} diff --git a/cash-common/cash-common-tools/src/main/java/com/czg/excel/SheetData.java b/cash-common/cash-common-tools/src/main/java/com/czg/excel/SheetData.java new file mode 100644 index 000000000..806bbc7c9 --- /dev/null +++ b/cash-common/cash-common-tools/src/main/java/com/czg/excel/SheetData.java @@ -0,0 +1,21 @@ +package com.czg.excel; + +import com.alibaba.excel.write.handler.SheetWriteHandler; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.List; + +/** + * 多sheet导出数据封装类 + * @author yjjie + * @date 2026/1/30 10:53 + */ +@Data +@Accessors(chain = true) +public class SheetData { + private List data; + private Class clazz; + private String sheetName; + private List handlers; +} diff --git a/cash-dependencies/pom.xml b/cash-dependencies/pom.xml index a598172c8..3622a95df 100644 --- a/cash-dependencies/pom.xml +++ b/cash-dependencies/pom.xml @@ -44,6 +44,7 @@ 4.1.128.Final 0.2.17 3.1.65.ALL + 4.0.3 @@ -282,6 +283,12 @@ alipay-sdk-java-v3 ${apipay-v3.version} + + + com.alibaba + easyexcel + ${easyexcel.version} + diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/EntryManager.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/EntryManager.java index 5ba69d428..c7df7b292 100644 --- a/cash-sdk/aggregation-pay/src/main/java/com/czg/EntryManager.java +++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/EntryManager.java @@ -384,8 +384,8 @@ public class EntryManager { // verifyEntryParam(merchantDto); // uploadParamImage(merchantDto); //// System.out.println(merchantDto); - EntryRespDto respDto = entryMerchant(merchantDto, PayCst.Type.WECHAT); -// entryMerchant(merchantDto, PayCst.Type.ALIPAY); +// EntryRespDto respDto = entryMerchant(merchantDto, PayCst.Type.WECHAT); + EntryRespDto respDto = entryMerchant(merchantDto, PayCst.Type.ALIPAY); // entryMerchant(merchantDto, PayCst.Type.WECHAT, PayCst.Type.ALIPAY); System.out.println(respDto); } diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/third/alipay/AlipayIsvEntryManager.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/third/alipay/AlipayIsvEntryManager.java index 87b0b5fa3..d0ac6e2ab 100644 --- a/cash-sdk/aggregation-pay/src/main/java/com/czg/third/alipay/AlipayIsvEntryManager.java +++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/third/alipay/AlipayIsvEntryManager.java @@ -1,5 +1,6 @@ package com.czg.third.alipay; +import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson2.JSONObject; import com.alipay.v3.ApiException; import com.alipay.v3.api.*; @@ -110,7 +111,10 @@ public class AlipayIsvEntryManager { respDto.setEntryId(batchNo); AlipayOpenAgentFacetofaceSignModel signModel = buildFaceToFaceModel(reqDto, batchNo); - File businessLicensePic = UploadFileUtil.getFileByUrl(reqDto.getBusinessLicenceInfo().getLicensePic().getUrl()); + File businessLicensePic = null; + if (reqDto.getBusinessLicenceInfo() != null && reqDto.getBusinessLicenceInfo().getLicensePic() != null && StrUtil.isNotBlank(reqDto.getBusinessLicenceInfo().getLicensePic().getUrl())) { + businessLicensePic = UploadFileUtil.getFileByUrl(reqDto.getBusinessLicenceInfo().getLicensePic().getUrl()); + } File shopScenePic = UploadFileUtil.getFileByUrl(reqDto.getStoreInfo().getInsidePic().getUrl()); File shopSignBoardPic = UploadFileUtil.getFileByUrl(reqDto.getStoreInfo().getDoorPic().getUrl()); @@ -237,10 +241,12 @@ public class AlipayIsvEntryManager { signModel.setRate("0.38"); signModel.setSignAndAuth(true); - signModel.setBusinessLicenseNo(licenceInfo.getLicenceNo()); - signModel.setBusinessLicenseMobile(legalPersonInfo.getLegalPersonPhone()); - signModel.setLongTerm(PayCst.LONG_TERM_DATE.equals(licenceInfo.getLicenceEndDate())); - signModel.setDateLimitation(licenceInfo.getLicenceStartDate()); + if (licenceInfo != null) { + signModel.setBusinessLicenseNo(licenceInfo.getLicenceNo()); + signModel.setBusinessLicenseMobile(legalPersonInfo.getLegalPersonPhone()); + signModel.setLongTerm(PayCst.LONG_TERM_DATE.equals(licenceInfo.getLicenceEndDate())); + signModel.setDateLimitation(licenceInfo.getLicenceStartDate()); + } signModel.setShopName(baseInfo.getShortName()); @@ -258,6 +264,32 @@ public class AlipayIsvEntryManager { public static void main(String[] args) { // confirmRequest("2026010815384505500018243"); - queryMerchantBatchStatus(null, "2026010815384505500018243"); + queryMerchantBatchStatus(null, "2026012310512107600067177"); + +// AggregateMerchantDto merchantDto = new AggregateMerchantDto(); +// merchantDto.setMerchantCode("CZG20260112151202099"); +// +// MerchantBaseInfoDto baseInfoDto = new MerchantBaseInfoDto(); +// baseInfoDto.setUserType("3"); +// baseInfoDto.setShortName("巩奕杰_商户"); +// baseInfoDto.setMccCode("A0001_B0199"); +// baseInfoDto.setAlipayAccount("15596653310"); +// baseInfoDto.setContactPersonType("SUPER"); +// baseInfoDto.setContactName("巩奕杰"); +// baseInfoDto.setCertType("0"); +// baseInfoDto.setContactPhone("15596653310"); +// baseInfoDto.setContactEmail("sankejuzi@163.com"); +// merchantDto.setMerchantBaseInfo(baseInfoDto); +// +// StoreInfoDto storeInfoDto = new StoreInfoDto(); +// storeInfoDto.setBusinessAddress("陕西省西安市浐灞欧亚国际"); +// storeInfoDto.setMercAreaCode("610113"); +// storeInfoDto.setMercProvCode("610000"); +// storeInfoDto.setMercCityCode("610100"); +// storeInfoDto.setDoorPic(new ImageDto().setUrl("https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/1/2c207c6f4a764ad18e501ed10fbfad59.png")); +// storeInfoDto.setInsidePic(new ImageDto().setUrl("https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/1/394b4834698a47e9b75419a5fd7f7de7.jpg")); +// merchantDto.setStoreInfo(storeInfoDto); +// +// entryMerchant(null, merchantDto); } } diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/third/wechat/WechatEntryManager.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/third/wechat/WechatEntryManager.java index 39621969e..d7c70f066 100644 --- a/cash-sdk/aggregation-pay/src/main/java/com/czg/third/wechat/WechatEntryManager.java +++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/third/wechat/WechatEntryManager.java @@ -313,8 +313,8 @@ public class WechatEntryManager { bizStoreInfo.setBizStoreName(baseInfo.getShortName()); bizStoreInfo.setBizAddressCode(storeInfo.getMercAreaCode()); bizStoreInfo.setBizStoreAddress(storeInfo.getBusinessAddress()); - bizStoreInfo.setStoreEntrancePic(storeInfo.getDoorPic().getWechatId()); - bizStoreInfo.setIndoorPic(storeInfo.getInsidePic().getWechatId()); + bizStoreInfo.setStoreEntrancePic(List.of(storeInfo.getDoorPic().getWechatId())); + bizStoreInfo.setIndoorPic(List.of(storeInfo.getInsidePic().getWechatId())); salesInfo.setBizStoreInfo(bizStoreInfo); WechatEntryMiniProgramReqDto miniProgramInfo = new WechatEntryMiniProgramReqDto(); miniProgramInfo.setMiniProgramAppid("wxd88fffa983758a30"); diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/third/wechat/dto/req/entry/business/sales/WechatEntryStoreInfoReqDto.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/third/wechat/dto/req/entry/business/sales/WechatEntryStoreInfoReqDto.java index 298741d7e..ae3b8018b 100644 --- a/cash-sdk/aggregation-pay/src/main/java/com/czg/third/wechat/dto/req/entry/business/sales/WechatEntryStoreInfoReqDto.java +++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/third/wechat/dto/req/entry/business/sales/WechatEntryStoreInfoReqDto.java @@ -55,8 +55,8 @@ public class WechatEntryStoreInfoReqDto { * 2、请填写通过图片上传API预先上传图片生成好的MediaID。 */ @JSONField(name = "store_entrance_pic") -// private List storeEntrancePic; - private String storeEntrancePic; + private List storeEntrancePic; +// private String storeEntrancePic; /** * 【必填】 @@ -65,8 +65,8 @@ public class WechatEntryStoreInfoReqDto { * 2、请填写通过图片上传API预先上传图片生成好的MediaID。 */ @JSONField(name = "indoor_pic") -// private List indoorPic; - private String indoorPic; + private List indoorPic; +// private String indoorPic; /** * 【选填】 diff --git a/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/AShopUserServiceImpl.java b/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/AShopUserServiceImpl.java index 1c9da9464..e70795843 100644 --- a/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/AShopUserServiceImpl.java +++ b/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/AShopUserServiceImpl.java @@ -4,12 +4,14 @@ import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; import com.czg.account.dto.shopuser.*; +import com.czg.account.entity.ShopInfo; import com.czg.account.entity.ShopUser; import com.czg.account.entity.UserInfo; import com.czg.account.service.AShopUserService; import com.czg.account.service.ShopInfoService; import com.czg.account.service.ShopUserService; import com.czg.account.service.UserInfoService; +import com.czg.excel.ExcelExportUtil; import com.czg.exception.CzgException; import com.czg.market.entity.MemberLevelConfig; import com.czg.market.entity.MkShopCouponRecord; @@ -28,6 +30,7 @@ import com.github.pagehelper.PageInfo; import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.query.QueryWrapper; import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.apache.dubbo.config.annotation.DubboReference; import org.springframework.stereotype.Service; @@ -124,6 +127,18 @@ public class AShopUserServiceImpl implements AShopUserService { } } + @Override + public void exportUserList(String key, Integer isVip, HttpServletResponse response) { + Long mainIdByShopId = shopInfoService.getMainIdByShopId(StpKit.USER.getShopId()); + ShopInfo shopInfo = shopInfoService.getById(StpKit.USER.getShopId()); + PageHelper.startPage(PageUtil.buildPageHelp()); + List dtoList = shopUserMapper.selectPageByKeyAndIsVip(mainIdByShopId, isVip, key, null); + + // 将 dtoList 转换为 ShopUserExportDTO 列表 + List exportList = BeanUtil.copyToList(dtoList, ShopUserExportDTO.class); + ExcelExportUtil.exportToResponse(exportList, ShopUserExportDTO.class, shopInfo == null ? "店铺用户列表" : shopInfo.getShopName() + "_用户列表", response); + } + @Override public Boolean updateInfo(Long shopId, ShopUserEditDTO shopUserEditDTO) { diff --git a/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/ShopConfigServiceImpl.java b/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/ShopConfigServiceImpl.java index d74b8b2be..e411597cf 100644 --- a/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/ShopConfigServiceImpl.java +++ b/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/ShopConfigServiceImpl.java @@ -14,7 +14,6 @@ import jakarta.annotation.Resource; import org.apache.dubbo.config.annotation.DubboService; import org.springframework.cache.annotation.Cacheable; -import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -37,7 +36,7 @@ public class ShopConfigServiceImpl extends ServiceImpl i @Override public ShopInfo getById(Serializable id) throws CzgException { - return shopConfigService.getShopInfoAndConfig(id); + return shopConfigService.getShopInfoAndConfig((Long) id); } @Override diff --git a/cash-service/market-service/src/main/java/com/czg/service/market/mapper/MkCarouselMapper.java b/cash-service/market-service/src/main/java/com/czg/service/market/mapper/MkCarouselMapper.java new file mode 100644 index 000000000..53c41e46e --- /dev/null +++ b/cash-service/market-service/src/main/java/com/czg/service/market/mapper/MkCarouselMapper.java @@ -0,0 +1,14 @@ +package com.czg.service.market.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.czg.market.entity.MkCarousel; + +/** + * 轮播图配置表 映射层。 + * + * @author ww + * @since 2026-01-27 + */ +public interface MkCarouselMapper extends BaseMapper { + +} diff --git a/cash-service/market-service/src/main/java/com/czg/service/market/mapper/MkDistributionGroupMapper.java b/cash-service/market-service/src/main/java/com/czg/service/market/mapper/MkDistributionGroupMapper.java new file mode 100644 index 000000000..3461cb49e --- /dev/null +++ b/cash-service/market-service/src/main/java/com/czg/service/market/mapper/MkDistributionGroupMapper.java @@ -0,0 +1,14 @@ +package com.czg.service.market.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.czg.market.entity.MkDistributionGroup; + +/** + * 分销员管理群(全民股东管理) 映射层。 + * + * @author ww + * @since 2026-01-28 + */ +public interface MkDistributionGroupMapper extends BaseMapper { + +} diff --git a/cash-service/market-service/src/main/java/com/czg/service/market/mapper/MkShareBaseMapper.java b/cash-service/market-service/src/main/java/com/czg/service/market/mapper/MkShareBaseMapper.java new file mode 100644 index 000000000..57b2b5a9c --- /dev/null +++ b/cash-service/market-service/src/main/java/com/czg/service/market/mapper/MkShareBaseMapper.java @@ -0,0 +1,14 @@ +package com.czg.service.market.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.czg.market.entity.MkShareBase; + +/** + * 分享奖励基础配置 映射层。 + * + * @author ww + * @since 2026-01-27 + */ +public interface MkShareBaseMapper extends BaseMapper { + +} diff --git a/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkCarouselServiceImpl.java b/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkCarouselServiceImpl.java new file mode 100644 index 000000000..e00c742d9 --- /dev/null +++ b/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkCarouselServiceImpl.java @@ -0,0 +1,48 @@ +package com.czg.service.market.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.czg.market.dto.MkCarouselDTO; +import com.czg.system.entity.MiniAppPages; +import com.czg.system.service.MiniAppPageService; +import com.mybatisflex.core.query.QueryWrapper; +import com.mybatisflex.spring.service.impl.ServiceImpl; +import com.czg.market.entity.MkCarousel; +import com.czg.market.service.MkCarouselService; +import com.czg.service.market.mapper.MkCarouselMapper; +import org.apache.dubbo.config.annotation.DubboReference; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 轮播图配置表 服务层实现。 + * + * @author ww + * @since 2026-01-27 + */ +@Service +public class MkCarouselServiceImpl extends ServiceImpl implements MkCarouselService { + @DubboReference + private MiniAppPageService miniAppPageService; + + @Override + public List getCarousels(MkCarouselDTO mkCarouselDTO) { + QueryWrapper queryWrapper = query().eq(MkCarousel::getShopId, mkCarouselDTO.getShopId()) + .eq(MkCarousel::getIsEnabled, mkCarouselDTO.getIsEnabled()) + .eq(MkCarousel::getIsShareable, mkCarouselDTO.getIsShareable()) + .orderBy(MkCarousel::getSort, false); + if (StrUtil.isNotBlank(mkCarouselDTO.getName())) { + queryWrapper.like(MkCarousel::getName, mkCarouselDTO.getName()); + } + List list = list(queryWrapper); + list.forEach(mkCarousel -> { + if (mkCarousel.getJumpPageId() != null) { + MiniAppPages miniAppPages = miniAppPageService.getById(mkCarousel.getJumpPageId()); + if (miniAppPages != null) { + mkCarousel.setJumpPagePath(miniAppPages.getPath()); + } + } + }); + return list; + } +} diff --git a/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkDistributionGroupServiceImpl.java b/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkDistributionGroupServiceImpl.java new file mode 100644 index 000000000..2143aa9c8 --- /dev/null +++ b/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkDistributionGroupServiceImpl.java @@ -0,0 +1,18 @@ +package com.czg.service.market.service.impl; + +import com.mybatisflex.spring.service.impl.ServiceImpl; +import com.czg.market.entity.MkDistributionGroup; +import com.czg.market.service.MkDistributionGroupService; +import com.czg.service.market.mapper.MkDistributionGroupMapper; +import org.springframework.stereotype.Service; + +/** + * 分销员管理群(全民股东管理) 服务层实现。 + * + * @author ww + * @since 2026-01-28 + */ +@Service +public class MkDistributionGroupServiceImpl extends ServiceImpl implements MkDistributionGroupService{ + +} diff --git a/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkDistributionUserServiceImpl.java b/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkDistributionUserServiceImpl.java index 098617e46..774f8feb0 100644 --- a/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkDistributionUserServiceImpl.java +++ b/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkDistributionUserServiceImpl.java @@ -61,6 +61,8 @@ import java.util.stream.Collectors; @Service public class MkDistributionUserServiceImpl extends ServiceImpl implements MkDistributionUserService { + @Resource + private MkDistributionGroupService mkDistributionGroupService; @Resource private MkDistributionConfigService mkDistributionConfigService; @Resource @@ -156,6 +158,9 @@ public class MkDistributionUserServiceImpl extends ServiceImpl distributionUser = new HashMap<>(); distributionUser.put("distributionId", mkDistributionUser.getId()); @@ -165,6 +170,7 @@ public class MkDistributionUserServiceImpl extends ServiceImpl levelConfigList = mkDistributionConfigVO.getLevelConfigList(); @@ -186,8 +192,6 @@ public class MkDistributionUserServiceImpl extends ServiceImpl= mkDistributionConfig.getInviteCount()) { + ShopUser parentShopUser1 = new ShopUser(); + parentShopUser1.setId(parentShopUser.getId()); + parentShopUser1.upDistributionShop(shopId, 1); + shopUserService.updateById(parentShopUser1); + } + } + if (mkDistributionConfig != null && !"not_upgrade".equals(mkDistributionConfig.getUpgradeType()) && parent.getIsAssignLevel() == 0) { + if ("invite".equals(mkDistributionConfig.getUpgradeType())) { + if (mkDistributionConfig.getInviteConsume() == 1) { + long count = orderInfoService.count(QueryWrapper.create() + .eq(OrderInfo::getUserId, shopUser.getUserId()) + .eq(OrderInfo::getShopId, parent.getShopId()) + .eq(OrderInfo::getStatus, OrderStatusEnums.DONE.getCode())); + if (count < 1) { + throw new CzgException("绑定失败,被邀请人需要成功支付一笔订单"); + } + } + MkDistributionLevelConfig levelConfig = levelConfigService.getOne(QueryWrapper.create() + .eq(MkDistributionLevelConfig::getShopId, parent.getShopId()) + .le(MkDistributionLevelConfig::getInviteCount, newDistributionUser.getInviteCount()) + .orderBy(MkDistributionLevelConfig::getId).desc().limit(1)); + if (levelConfig != null) { + newDistributionUser.setDistributionLevelId(levelConfig.getId()); + newDistributionUser.setDistributionLevelName(levelConfig.getName()); + newDistributionUser.setStatus(1); + } + } else if ("cost".equals(mkDistributionConfig.getUpgradeType())) { + costUpgradeLevel(parent.getId(), parent.getShopId()); + } + } + update(newDistributionUser, QueryWrapper.create().eq(MkDistributionUser::getId, parent.getId()) + .eq(MkDistributionUser::getShopId, parent.getShopId())); + } + @Override public void costUpgradeLevelBefore(Long userId, Long shopId) { ShopUser shopUser = shopUserService.getShopUserInfo(shopId, userId); @@ -377,8 +467,10 @@ public class MkDistributionUserServiceImpl extends ServiceImpl shopUser)); + List shopUserList = shopUserService.list(QueryWrapper.create().in(ShopUser::getId, shopUserIds)); + if (CollUtil.isNotEmpty(shopUserList)) { + shopUserMap = shopUserList.stream().collect(Collectors.toMap(ShopUser::getId, shopUser -> shopUser)); + } } for (MkDistributionUserDTO record : page.getRecords()) { ShopUser shopUser = shopUserMap.get(record.getId()); diff --git a/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkShareBaseServiceImpl.java b/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkShareBaseServiceImpl.java new file mode 100644 index 000000000..6d774d416 --- /dev/null +++ b/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkShareBaseServiceImpl.java @@ -0,0 +1,135 @@ +package com.czg.service.market.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.czg.market.dto.MkShopCouponGiftDTO; +import com.czg.market.dto.ShopCouponDTO; +import com.czg.market.entity.MkShopCouponRecord; +import com.czg.market.service.MkDistributionUserService; +import com.czg.market.service.MkShopCouponRecordService; +import com.czg.market.service.ShopCouponService; +import com.czg.utils.FunUtils; +import com.mybatisflex.spring.service.impl.ServiceImpl; +import com.czg.market.entity.MkShareBase; +import com.czg.market.service.MkShareBaseService; +import com.czg.service.market.mapper.MkShareBaseMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * 分享奖励基础配置 服务层实现。 + * + * @author ww + * @since 2026-01-27 + */ +@Service +public class MkShareBaseServiceImpl extends ServiceImpl implements MkShareBaseService { + + @Resource + private ShopCouponService shopCouponService; + @Resource + private MkDistributionUserService distributionUserService; + @Resource + private MkShopCouponRecordService mkShopCouponRecordService; + + @Override + public MkShareBase getShareBase(Long shopId) { + MkShareBase shareBase = getById(shopId); + if (shareBase != null) { + if (shareBase.getSharerCouponId() != null) { + ShopCouponDTO sharerCoupon = shopCouponService.getCouponById(shareBase.getSharerCouponId()); + if (sharerCoupon != null) { + shareBase.setSharerCouponName(sharerCoupon.getTitle()); + shareBase.setSharerCoupon(sharerCoupon); + } + } + if (shareBase.getSharedUserCouponId() != null) { + ShopCouponDTO shareUserCoupon = shopCouponService.getCouponById(shareBase.getSharedUserCouponId()); + if (shareUserCoupon != null) { + shareBase.setSharedUserCouponName(shareUserCoupon.getTitle()); + } + } + } + return shareBase; + } + + @Override + public void shareClaim(String tagType, Long shopId, Long fromUserId, Long toUserId) { + //获取邀请码 + String inviteCode = null; + try { + inviteCode = distributionUserService.getInviteCode(shopId, fromUserId); + } catch (Exception _) { + } + //绑定上下级 + if (StrUtil.isNotBlank(inviteCode)) { + FunUtils.asyncSafeRunVoid(() -> distributionUserService.bindInviteUser(fromUserId, toUserId, shopId)); + } + MkShareBase shareBase = getById(shopId); + if (shareBase == null || !shareBase.getIsEnabled().equals(1) || StrUtil.isBlank(shareBase.getRewardSharePages())) { + return; + } + if (!shareBase.getRewardSharePages().contains(tagType)) { + return; + } + FunUtils.safeRun(() -> { + //发放分享人优惠券 + if (shareBase.getSharerCouponId() != null) { + boolean grant = true; + if (shareBase.getRewardTimesType().equals(1)) { + boolean exists = mkShopCouponRecordService.exists(query() + .eq(MkShopCouponRecord::getShopId, shopId) + .eq(MkShopCouponRecord::getShopUserId, fromUserId) + .eq(MkShopCouponRecord::getSource, "邀请获得")); + grant = !exists; + } + if (grant) { + grant = !mkShopCouponRecordService.exists(query() + .eq(MkShopCouponRecord::getShopId, shopId) + .eq(MkShopCouponRecord::getShopUserId, fromUserId) + .eq(MkShopCouponRecord::getSourceFlowId, toUserId) + .eq(MkShopCouponRecord::getSource, "邀请获得")); + } + if (grant) { + MkShopCouponGiftDTO giftDTO = new MkShopCouponGiftDTO(); + giftDTO.setShopId(shopId) + .setSourceId(shareBase.getShopId()) + .setSourceFlowId(toUserId) + .setShopUserId(fromUserId) + .setCouponId(shareBase.getSharerCouponId()) + .setSource("邀请获得"); + int receiveNum = 1; + if (shareBase.getSharerCouponNum() != null && shareBase.getSharerCouponNum() > 0) { + receiveNum = shareBase.getSharerCouponNum(); + } + mkShopCouponRecordService.receiveCoupon(giftDTO, receiveNum, false); + } + } + return null; + }, "邀请人获取优惠券"); + FunUtils.safeRun(() -> { + //发放被分享人优惠券 + if (shareBase.getSharedUserCouponId() != null) { + boolean exists = mkShopCouponRecordService.exists(query() + .eq(MkShopCouponRecord::getShopId, shopId) + .eq(MkShopCouponRecord::getShopUserId, toUserId) + .eq(MkShopCouponRecord::getSourceFlowId, fromUserId) + .eq(MkShopCouponRecord::getSource, "参与分享获得")); + if (!exists) { + MkShopCouponGiftDTO giftDTO = new MkShopCouponGiftDTO(); + giftDTO.setShopId(shopId) + .setSourceId(shareBase.getShopId()) + .setShopUserId(toUserId) + .setSourceFlowId(fromUserId) + .setCouponId(shareBase.getSharedUserCouponId()) + .setSource("参与分享获得"); + int receiveNum = 1; + if (shareBase.getSharedUserCouponNum() != null && shareBase.getSharedUserCouponNum() > 0) { + receiveNum = shareBase.getSharedUserCouponNum(); + } + mkShopCouponRecordService.receiveCoupon(giftDTO, receiveNum, false); + } + } + return null; + }, "被分享人获取优惠券"); + } +} diff --git a/cash-service/market-service/src/main/resources/mapper/MkCarouselMapper.xml b/cash-service/market-service/src/main/resources/mapper/MkCarouselMapper.xml new file mode 100644 index 000000000..ebac91f72 --- /dev/null +++ b/cash-service/market-service/src/main/resources/mapper/MkCarouselMapper.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/cash-service/market-service/src/main/resources/mapper/MkDistributionGroupMapper.xml b/cash-service/market-service/src/main/resources/mapper/MkDistributionGroupMapper.xml new file mode 100644 index 000000000..238da2a04 --- /dev/null +++ b/cash-service/market-service/src/main/resources/mapper/MkDistributionGroupMapper.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/cash-service/market-service/src/main/resources/mapper/MkShareBaseMapper.xml b/cash-service/market-service/src/main/resources/mapper/MkShareBaseMapper.xml new file mode 100644 index 000000000..4a29cba9a --- /dev/null +++ b/cash-service/market-service/src/main/resources/mapper/MkShareBaseMapper.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/cash-service/product-service/src/main/java/com/czg/service/product/service/impl/ProductServiceImpl.java b/cash-service/product-service/src/main/java/com/czg/service/product/service/impl/ProductServiceImpl.java index 751400229..d80c65797 100644 --- a/cash-service/product-service/src/main/java/com/czg/service/product/service/impl/ProductServiceImpl.java +++ b/cash-service/product-service/src/main/java/com/czg/service/product/service/impl/ProductServiceImpl.java @@ -5,17 +5,22 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; +import com.alibaba.excel.write.handler.SheetWriteHandler; +import com.alibaba.excel.write.merge.OnceAbsoluteMergeStrategy; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONWriter; import com.czg.constant.CacheConstant; import com.czg.constants.SystemConstants; +import com.czg.excel.ExcelExportUtil; +import com.czg.excel.SheetData; import com.czg.exception.CzgException; import com.czg.product.dto.*; import com.czg.product.entity.*; import com.czg.product.enums.*; import com.czg.product.param.*; import com.czg.product.service.*; +import com.czg.product.vo.ProductGroupVo; import com.czg.product.vo.ProductStatisticsVo; import com.czg.sa.StpKit; import com.czg.service.RedisService; @@ -30,6 +35,7 @@ import com.mybatisflex.core.update.UpdateChain; import com.mybatisflex.spring.service.impl.ServiceImpl; import jakarta.annotation.PostConstruct; import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.dubbo.config.annotation.DubboService; @@ -43,6 +49,7 @@ import java.time.LocalDate; import java.time.LocalTime; import java.time.format.TextStyle; import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; import static com.czg.constant.CacheConstant.ADMIN_CLIENT_PRODUCT_LIST; @@ -65,7 +72,6 @@ public class ProductServiceImpl extends ServiceImpl impl private final ProdSkuMapper prodSkuMapper; private final ProdConsRelationMapper prodConsRelationMapper; private final ConsInfoMapper consInfoMapper; - private final ConsStockFlowMapper consStockFlowMapper; private final ProductStockFlowMapper productStockFlowMapper; private final ProductStockFlowService productStockFlowService; private final ConsStockFlowService consStockFlowService; @@ -138,6 +144,7 @@ public class ProductServiceImpl extends ServiceImpl impl private void buildProductExtInfo(List records) { records.forEach(record -> { record.setIsSaleTime(calcIsSaleTime(record.getDays(), record.getStartTime(), record.getEndTime())); + record.setProGroupVo(JSONArray.parseArray(record.getGroupSnap().toString(), ProductGroupVo.class)); List skuList = prodSkuMapper.selectListByQueryAs(query().eq(ProdSku::getProductId, record.getId()).eq(ProdSku::getIsDel, SystemConstants.OneZero.ZERO), ProdSkuDTO.class); if (CollUtil.isNotEmpty(skuList)) { Optional lowPriceIsPresent = skuList.stream().map(obj -> NumberUtil.nullToZero(obj.getSalePrice())).min(BigDecimal::compareTo); @@ -175,6 +182,155 @@ public class ProductServiceImpl extends ServiceImpl impl return records; } + @Override + public void exportProductList(ProductDTO param, HttpServletResponse response) { + // 1. 查询并构建完整数据 + QueryWrapper queryWrapper = buildFullQueryWrapper(param); + List records = super.listAs(queryWrapper, ProductDTO.class); + buildProductExtInfo(records); + + // 2. 分别处理普通商品和套餐商品 + SheetData normalSheet = buildNormalProductSheet(records); + SheetData packageSheet = buildPackageProductSheet(records); + + // 3. 导出 + List dataList = List.of(normalSheet, packageSheet); + ExcelExportUtil.exportMultipleSheetsToResponse(dataList, "商品列表", response); + } + + // ----------------------------- + // 普通商品处理 + // ----------------------------- + private SheetData buildNormalProductSheet(List records) { + List handlers = new ArrayList<>(); + List dataList = new ArrayList<>(); + + for (ProductDTO dto : records) { + if ("package".equals(dto.getType())) continue; // 跳过套餐 + + int firstRow = dataList.size() + 1; + + if (dto.getSkuList() != null && !dto.getSkuList().isEmpty()) { + for (ProdSkuDTO sku : dto.getSkuList()) { + ProductExportDTO exportDto = new ProductExportDTO(); + BeanUtil.copyProperties(dto, exportDto); + exportDto.setSpecFullName(sku.getSpecInfo()); + exportDto.setPrice(sku.getSalePrice()); + exportDto.setMemberPrice(sku.getMemberPrice()); + exportDto.setIsSale(sku.getIsGrounding()); + exportDto.setBarCode(sku.getBarCode()); + exportDto.setCostPrice(sku.getCostPrice()); + dataList.add(exportDto); + } + + int skuCount = dto.getSkuList().size(); + if (skuCount > 1) { + mergeColumns(handlers, firstRow, firstRow + skuCount - 1, + 0, 1, 7, 8, 9, 10, 11); // 多列合并 + } + } else { + dataList.add(BeanUtil.copyProperties(dto, ProductExportDTO.class)); + } + } + + return new SheetData() + .setSheetName("普通商品") + .setData(dataList) + .setClazz(ProductExportDTO.class) + .setHandlers(handlers); + } + + // ----------------------------- + // 套餐商品处理 + // ----------------------------- + private SheetData buildPackageProductSheet(List records) { + List handlers = new ArrayList<>(); + List dataList = new ArrayList<>(); + + for (ProductDTO exportDTO : records) { + if (!"package".equals(exportDTO.getType())) continue; + + if (exportDTO.getProGroupVo() == null || exportDTO.getProGroupVo().isEmpty()) { + dataList.add(BeanUtil.copyProperties(exportDTO, ProductPackageExportDTO.class)); + continue; + } + + int sheetFirstRow = dataList.size() + 1; + boolean needOuterMerge = exportDTO.getProGroupVo().size() > 1; + + for (ProductGroupVo proGroupDTO : exportDTO.getProGroupVo()) { + int groupFirstRow = dataList.size() + 1; + List goods = proGroupDTO.getGoods(); + int groupSize = goods.size(); + + // 添加每条商品记录 + for (ProductGroupVo.Food good : goods) { + ProductPackageExportDTO pkgDto = new ProductPackageExportDTO() + .setName(exportDTO.getName()) + .setCategoryName(exportDTO.getCategoryName()) + .setUnitName(exportDTO.getUnitName()) + .setPrice(getMainSkuPrice(exportDTO)) + .setMemberPrice(getMainSkuMemberPrice(exportDTO)) + .setType(exportDTO.getType()) + .setGroupType(exportDTO.getGroupType()) + .setStockNumber(exportDTO.getStockNumber()) + .setIsSale(getMainSkuIsSale(exportDTO)) + .setGroupTitleName(proGroupDTO.getTitle()) + .setGroupProductNumber(Optional.ofNullable(proGroupDTO.getNumber()).map(String::valueOf).orElse("")) + .setGroupProductName(good.getProName() + " " + good.getSkuName()); + dataList.add(pkgDto); + } + + // 组内合并:如果该组有多个商品 + if (groupSize > 1) { + needOuterMerge = true; + mergeColumns(handlers, groupFirstRow, groupFirstRow + groupSize - 1, 5, 8); + } + } + + // 外层合并:整个套餐的信息(名称、分类等) + if (needOuterMerge) { + int lastRow = dataList.size(); + mergeColumns(handlers, sheetFirstRow, lastRow, 0, 1, 2, 3, 4); + } + } + + return new SheetData() + .setSheetName("套餐商品") + .setData(dataList) + .setClazz(ProductPackageExportDTO.class) + .setHandlers(handlers); + } + + // ----------------------------- + // 辅助方法:提取主 SKU 信息(避免重复 getFirst()) + // ----------------------------- + private BigDecimal getMainSkuPrice(ProductDTO dto) { + return dto.getSkuList().isEmpty() ? null : dto.getSkuList().getFirst().getSalePrice(); + } + + private BigDecimal getMainSkuMemberPrice(ProductDTO dto) { + return dto.getSkuList().isEmpty() ? null : dto.getSkuList().getFirst().getMemberPrice(); + } + + private Integer getMainSkuIsSale(ProductDTO dto) { + return dto.getSkuList().isEmpty() ? null : dto.getSkuList().getFirst().getIsSale(); + } + + // ----------------------------- + // 合并工具方法:支持多列合并 + // ----------------------------- + private void mergeColumns(List handlers, int firstRow, int lastRow, int... columns) { + for (int col : columns) { + addMergeHandler(handlers, firstRow, lastRow, col, col); + } + } + + private void addMergeHandler(List handlers, int firstRow, int lastRow, int firstCol, int lastCol) { + OnceAbsoluteMergeStrategy strategy = new OnceAbsoluteMergeStrategy(firstRow, lastRow, firstCol, lastCol); + handlers.add(strategy); + } + @Override public List getProductCacheList(ProductDTO param) { Long shopId = param.getShopId(); @@ -555,7 +711,7 @@ public class ProductServiceImpl extends ServiceImpl impl String type = param.getType(); Long id = param.getId(); Integer isSale = param.getIsSale(); - String sensitiveOperation = ""; + String sensitiveOperation; if (isSale == 1) { sensitiveOperation = "上架"; } else { @@ -668,7 +824,7 @@ public class ProductServiceImpl extends ServiceImpl impl @Override public void stockWarning(Integer warnLine) { - Long shopId = StpKit.USER.getShopId(0L); + Long shopId = StpKit.USER.getShopId(); UpdateChain.of(Product.class) .set(Product::getWarnLine, warnLine) .eq(Product::getShopId, shopId) @@ -678,7 +834,7 @@ public class ProductServiceImpl extends ServiceImpl impl @Override @Transactional(rollbackFor = Exception.class) public void reportDamage(ProductReportDamageParam param) { - Long shopId = StpKit.USER.getShopId(0L); + Long shopId = StpKit.USER.getShopId(); Long createUserId = StpKit.USER.getLoginIdAsLong(); String createUserName = StpKit.USER.getAccount(); Product product = mapper.selectOneById(param.getProductId()); diff --git a/cash-service/system-service/src/main/java/com/czg/service/system/service/impl/MiniAppPagesServiceImpl.java b/cash-service/system-service/src/main/java/com/czg/service/system/service/impl/MiniAppPagesServiceImpl.java index eaa892387..673969d60 100644 --- a/cash-service/system-service/src/main/java/com/czg/service/system/service/impl/MiniAppPagesServiceImpl.java +++ b/cash-service/system-service/src/main/java/com/czg/service/system/service/impl/MiniAppPagesServiceImpl.java @@ -12,7 +12,7 @@ import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.spring.service.impl.ServiceImpl; import com.czg.service.system.mapper.MiniAppPagesMapper; -import org.springframework.stereotype.Service; +import org.apache.dubbo.config.annotation.DubboService; /** * 小程序页面路径 服务层实现。 @@ -20,7 +20,7 @@ import org.springframework.stereotype.Service; * @author mac * @since 2025-02-12 */ -@Service +@DubboService public class MiniAppPagesServiceImpl extends ServiceImpl implements MiniAppPageService { @Override @@ -46,6 +46,7 @@ public class MiniAppPagesServiceImpl extends ServiceImpl