From 2661277bd2c14804b6c026a57a5b770e0b3b65c2 Mon Sep 17 00:00:00 2001 From: Jack <46790855@qq.com> Date: Fri, 7 Nov 2025 12:42:01 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A0=8D=E4=BB=B7=E5=AD=97=E6=AE=B5=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/store/ShopStoreActivityBase.java | 6 +- .../mobile/UserActivityController.java | 4 +- .../impl/ShopActivityCutpriceServiceImpl.java | 119 ++++++++--- .../impl/ShopOrderInfoServiceImpl.java | 202 ++++++++++-------- .../ShopStoreActivityBaseController.java | 2 +- .../ShopStoreActivityBaseServiceImpl.java | 39 +++- 6 files changed, 235 insertions(+), 137 deletions(-) diff --git a/mall-common/src/main/java/com/suisung/mall/common/modules/store/ShopStoreActivityBase.java b/mall-common/src/main/java/com/suisung/mall/common/modules/store/ShopStoreActivityBase.java index 03baa06c..47838d78 100644 --- a/mall-common/src/main/java/com/suisung/mall/common/modules/store/ShopStoreActivityBase.java +++ b/mall-common/src/main/java/com/suisung/mall/common/modules/store/ShopStoreActivityBase.java @@ -129,10 +129,10 @@ public class ShopStoreActivityBase implements Serializable { @TableField(updateStrategy = NOT_EMPTY) private String flow_no; - @ApiModelProperty(value = "在活动时间范围内,用户砍价允许的天数") - private Integer cut_days; + @ApiModelProperty(value = "在活动时间范围内,用户砍价有效期(小时)") + private Integer cut_hour; - @ApiModelProperty(value = "参与活动商品的总数量") + @ApiModelProperty(value = "参与活动商品的总数量(个)") private Integer product_count; } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/activity/controller/mobile/UserActivityController.java b/mall-shop/src/main/java/com/suisung/mall/shop/activity/controller/mobile/UserActivityController.java index 5315b485..0b2255c0 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/activity/controller/mobile/UserActivityController.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/activity/controller/mobile/UserActivityController.java @@ -118,8 +118,8 @@ public class UserActivityController extends BaseControllerImpl { return CommonResult.success(shopActivityCutpriceService.getCutPriceActivity()); } - @ApiOperation(value = "立即砍价", notes = "自己砍价、要求朋友过来也能砍价") - @RequestMapping(value = "/doCutPrice", method = RequestMethod.GET) + @ApiOperation(value = "立即砍价", notes = "自己砍价、邀请朋友过来也能砍价") + @RequestMapping(value = "/doCutPrice", method = {RequestMethod.GET, RequestMethod.POST}) public CommonResult doCutPrice(@RequestParam(name = "ac_id", defaultValue = "0") Integer ac_id) { UserDto user = getCurrentUser(); if (user == null || CheckUtil.isEmpty(user.getId())) { diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/activity/service/impl/ShopActivityCutpriceServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/activity/service/impl/ShopActivityCutpriceServiceImpl.java index 6c97c0f4..7f5faf68 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/activity/service/impl/ShopActivityCutpriceServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/activity/service/impl/ShopActivityCutpriceServiceImpl.java @@ -260,37 +260,58 @@ public class ShopActivityCutpriceServiceImpl extends BaseServiceImpl queryWrapper = new QueryWrapper<>(); queryWrapper.eq("activity_id", activity_id).eq("user_id", user_id); ShopActivityCutprice cutprice_row = findOne(queryWrapper); + + // 如果用户未参与该砍价活动,则创建新的砍价记录 if (cutprice_row == null) { cutprice_row = new ShopActivityCutprice(); + + // 从活动规则中获取商品原价和砍价底价 JSONObject activity_rule = JSONUtil.parseObj(activityBase.getActivity_rule()); + if (activity_rule == null) { + throw new ApiException(I18nUtil._("活动规则数据异常!")); + } + BigDecimal item_unit_price = Convert.toBigDecimal(activity_rule.get("item_unit_price")); BigDecimal cut_down_min_limit_price = Convert.toBigDecimal(activity_rule.get("cut_down_min_limit_price")); + // 初始化砍价记录信息 cutprice_row.setActivity_id(activity_id); cutprice_row.setUser_id(user_id); cutprice_row.setAc_sale_price(item_unit_price); @@ -298,32 +319,29 @@ public class ShopActivityCutpriceServiceImpl extends BaseServiceImpl historyQueryWrapper = new QueryWrapper<>(); historyQueryWrapper.eq("ac_id", ac_id).eq("user_id", participant_id); ShopActivityCutpriceHistory cutpriceHistory = cutpriceHistoryService.findOne(historyQueryWrapper); + // 设置用户砍价历史信息 activity_row.put("cut_row", cutpriceHistory); activity_row.put("is_cut", cutpriceHistory != null); + // 设置活动规则信息 activity_row.put("activity_rule", JSONUtil.parseObj(activity_row.get("activity_rule"))); -// // 砍价订单有效期时长 -// if (cutprice_row != null && cutprice_row.getAc_datetime() != null) { -// Float order_cutprice_time = accountBaseConfigService.getConfig("order_cutprice_time", 3f); -// int second = NumberUtil.mul(order_cutprice_time, 24, 60, 60).intValue(); -// long time = DateUtil.offsetSecond(cutprice_row.getAc_datetime(), +second).getTime(); -// activity_row.put("activity_endtime", Convert.toDate(time)); -// } - - // 界面做一个简单的底价验证: + // 判断是否可以立即购买 boolean canBuyNow = cutprice_row != null && CheckUtil.isNotEmpty(cutprice_row.getAc_sale_price()) && CheckUtil.isNotEmpty(cutprice_row.getAc_mix_limit_price()) @@ -331,7 +349,7 @@ public class ShopActivityCutpriceServiceImpl extends BaseServiceImpl 0 && cut_num >= num) { throw new ApiException(I18nUtil._("今日帮砍次数已用完!")); } @@ -362,34 +396,54 @@ public class ShopActivityCutpriceServiceImpl extends BaseServiceImpl queryWrapper = new QueryWrapper<>(); queryWrapper.eq("user_id", user_id).eq("ac_id", ac_id); long ach_num = shopActivityCutpriceHistoryService.count(queryWrapper); - - if (CheckUtil.isNotEmpty(ach_num)) { - throw new ApiException(I18nUtil._("已经帮助好友进行砍价!")); + if (ach_num > 0) { + throw new ApiException(I18nUtil._("已经帮过好友砍了价!")); } + // 计算砍价金额 BigDecimal cut_price = shopStoreActivityBaseService.getCutDownPrice(storeActivityBase, cutprice_row); - if (CheckUtil.isEmpty(cut_price)) { + if (cut_price == null || cut_price.compareTo(BigDecimal.ZERO) <= 0) { throw new ApiException(I18nUtil._("砍价失败!")); } + // 获取商品ID String str_activity_rule = storeActivityBase.getActivity_rule(); - com.alibaba.fastjson.JSONObject activity_rule = com.alibaba.fastjson.JSONObject.parseObject(str_activity_rule); - Long item_id = activity_rule.getObject("item_id", Long.class); + if (StrUtil.isBlank(str_activity_rule)) { + throw new ApiException(I18nUtil._("活动规则数据异常!")); + } + JSONObject activity_rule = JSONUtil.parseObj(str_activity_rule); + Long item_id = activity_rule.get("item_id", Long.class); + if (item_id == null) { + throw new ApiException(I18nUtil._("未找到商品信息!")); + } + + // 创建砍价历史记录 ShopActivityCutpriceHistory ach_data = new ShopActivityCutpriceHistory(); ach_data.setActivity_id(activity_id); ach_data.setUser_id(user_id); @@ -398,17 +452,22 @@ public class ShopActivityCutpriceServiceImpl extends BaseServiceImpl items = new ArrayList<>(); // 参数校验 - if (StrUtil.isNotBlank(dateStr) && StrUtil.isNotBlank(startTimeStr) && StrUtil.isNotBlank(endTimeStr)) { - try { - // 解析营业时间 - Date openTime = DateUtil.parse(dateStr + " " + startTimeStr + ":00", "yyyy-MM-dd HH:mm:ss"); - Date closeTime = DateUtil.parse(dateStr + " " + endTimeStr + ":00", "yyyy-MM-dd HH:mm:ss"); + if (StrUtil.isBlank(dateStr) || StrUtil.isBlank(startTimeStr) || StrUtil.isBlank(endTimeStr)) { + bookingArgDTO.setItems(items); + bookingArgList.add(bookingArgDTO); + continue; + } - // 验证营业时间有效性 - if (!openTime.after(closeTime)) { - // 在营业时间段内,且是今天,添加"立即送出"选项 - if (i == 0 && isTodayAvailable && inRangeVal == 0) { - BookingArgDTO.BookingArgItem immediateItem = new BookingArgDTO.BookingArgItem(); - immediateItem.setTime_title("立即送出"); - immediateItem.setBooking_at(0L); - immediateItem.setBooking_state(1); - immediateItem.setBooking_begin_time(""); - immediateItem.setBooking_end_time(""); - items.add(immediateItem); - } + try { + // 解析营业时间 + Date openTime = DateUtil.parse(dateStr + " " + startTimeStr + ":00", "yyyy-MM-dd HH:mm:ss"); + Date closeTime = DateUtil.parse(dateStr + " " + endTimeStr + ":00", "yyyy-MM-dd HH:mm:ss"); - // 确定时间槽开始时间 - Date startTime = openTime; - if (i == 0 && isTodayAvailable && inRangeVal <= 0) { - // 当前时间+50分钟作为时间槽的开始时间 - Date nowPlusFifty = DateUtil.offsetMinute(new Date(), CommonConstant.MIN_DELAY_MINUTES_FOR_BOOKING_ORDER); - - // 确保开始时间在营业时间范围内 - if (nowPlusFifty.after(openTime)) { - if (nowPlusFifty.before(closeTime)) { - // 如果当前时间+50分钟在营业时间范围内,则从该时间开始 - startTime = nowPlusFifty; - logger.debug("[生成时间槽] 当前时间+50分钟在营业时间范围内,则从该时间开始"); - } else { - // 如果当前时间+50分钟已经超过营业结束时间,则不生成后续时间槽 - logger.debug("[生成时间槽] 当前时间+50分钟已超过营业结束时间,不生成后续时间槽"); - startTime = null; // 标记为不生成时间槽 - } - } - } - - // 生成时间槽 - if (startTime != null) { - Date currentTimeSlot = startTime; - int slotCount = 0; - final int MAX_SLOTS = 96; // 最多生成96个时间段,防止异常循环 - - while (currentTimeSlot.before(closeTime) && slotCount < MAX_SLOTS) { - Date endTimeSlot = DateUtil.offsetMinute(currentTimeSlot, 15); - - // 如果结束时间超过了营业结束时间,则使用营业结束时间 - if (endTimeSlot.after(closeTime)) { - endTimeSlot = closeTime; - } - - // 创建时间段项 - BookingArgDTO.BookingArgItem timeItem = new BookingArgDTO.BookingArgItem(); - String beginTimeStr = DateUtil.format(currentTimeSlot, "HH:mm"); - String endTimeStrItem = DateUtil.format(endTimeSlot, "HH:mm"); - - timeItem.setTime_title(beginTimeStr + "-" + endTimeStrItem); - - // 时间戳计算(秒) - long bookingAt = currentTimeSlot.getTime() / 1000; - timeItem.setBooking_at(bookingAt); - - timeItem.setBooking_state(2); - timeItem.setBooking_begin_time(DateUtil.format(currentTimeSlot, "yyyy-MM-dd HH:mm:ss")); - timeItem.setBooking_end_time(DateUtil.format(endTimeSlot, "yyyy-MM-dd HH:mm:ss")); - - items.add(timeItem); - - // 移动到下一个时间段 - currentTimeSlot = endTimeSlot; - slotCount++; - - // 防止时间相同导致的死循环 - if (currentTimeSlot.equals(startTime)) { - logger.warn("[生成时间槽] 检测到时间循环,跳出循环"); - break; - } - } - - if (slotCount >= MAX_SLOTS) { - logger.warn("[生成时间槽] 时间段数量超过最大限制,date: {}", dateStr); - } - } - } else { - logger.warn("[生成时间槽] 营业时间无效,openTime: {}, closeTime: {}", openTime, closeTime); - } - } catch (Exception e) { - logger.error("[生成时间槽] 生成时间槽异常,date: {}, openingHours: {}, closeHours: {}", dateStr, startTimeStr, endTimeStr, e); + // 验证营业时间有效性 + if (openTime.after(closeTime)) { + logger.warn("[生成时间槽] 营业时间无效,openTime: {}, closeTime: {}", openTime, closeTime); + bookingArgDTO.setItems(items); + bookingArgList.add(bookingArgDTO); + continue; } + + // 在营业时间段内,且是今天,添加"立即送出"选项 + if (i == 0 && isTodayAvailable && inRangeVal == 0) { + BookingArgDTO.BookingArgItem immediateItem = new BookingArgDTO.BookingArgItem(); + immediateItem.setTime_title("立即送出"); + immediateItem.setBooking_at(0L); + immediateItem.setBooking_state(1); + immediateItem.setBooking_begin_time(""); + immediateItem.setBooking_end_time(""); + items.add(immediateItem); + } + + // 确定时间槽开始时间 + Date startTime = openTime; + if (i == 0 && isTodayAvailable && inRangeVal <= 0) { + // 当前时间+50分钟作为时间槽的开始时间 + Date nowPlusFifty = DateUtil.offsetMinute(new Date(), CommonConstant.MIN_DELAY_MINUTES_FOR_BOOKING_ORDER); + + // 确保开始时间在营业时间范围内 + if (nowPlusFifty.after(openTime)) { + if (nowPlusFifty.before(closeTime)) { + // 如果当前时间+50分钟在营业时间范围内,则从该时间开始 + startTime = nowPlusFifty; + logger.debug("[生成时间槽] 当前时间+50分钟在营业时间范围内,则从该时间开始"); + } else { + // 如果当前时间+50分钟已经超过营业结束时间,则不生成后续时间槽 + logger.debug("[生成时间槽] 当前时间+50分钟已超过营业结束时间,不生成后续时间槽"); + startTime = null; // 标记为不生成时间槽 + } + } + } + + // 生成时间槽 + if (startTime != null) { + Date currentTimeSlot = startTime; + int slotCount = 0; + final int MAX_SLOTS = 96; // 最多生成96个时间段,防止异常循环 + + while (currentTimeSlot.before(closeTime) && slotCount < MAX_SLOTS) { + Date endTimeSlot = DateUtil.offsetMinute(currentTimeSlot, 15); + + // 如果结束时间超过了营业结束时间,则使用营业结束时间 + if (endTimeSlot.after(closeTime)) { + endTimeSlot = closeTime; + } + + // 创建时间段项 + BookingArgDTO.BookingArgItem timeItem = new BookingArgDTO.BookingArgItem(); + String beginTimeStr = DateUtil.format(currentTimeSlot, "HH:mm"); + String endTimeStrItem = DateUtil.format(endTimeSlot, "HH:mm"); + + timeItem.setTime_title(beginTimeStr + "-" + endTimeStrItem); + + // 时间戳计算(秒) + long bookingAt = currentTimeSlot.getTime() / 1000; + timeItem.setBooking_at(bookingAt); + + timeItem.setBooking_state(CommonConstant.Order_Booking_State_YY); + timeItem.setBooking_begin_time(DateUtil.format(currentTimeSlot, "yyyy-MM-dd HH:mm:ss")); + timeItem.setBooking_end_time(DateUtil.format(endTimeSlot, "yyyy-MM-dd HH:mm:ss")); + + items.add(timeItem); + + // 移动到下一个时间段 + currentTimeSlot = endTimeSlot; + slotCount++; + + // 防止时间相同导致的死循环 + if (currentTimeSlot.equals(startTime)) { + logger.warn("[生成时间槽] 检测到时间循环,跳出循环"); + break; + } + } + + if (slotCount >= MAX_SLOTS) { + logger.warn("[生成时间槽] 时间段数量超过最大限制,date: {}", dateStr); + } + } + } catch (Exception e) { + logger.error("[生成时间槽] 生成时间槽异常,date: {}, openingHours: {}, closeHours: {}", dateStr, startTimeStr, endTimeStr, e); } bookingArgDTO.setItems(items); diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/admin/ShopStoreActivityBaseController.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/admin/ShopStoreActivityBaseController.java index e34cf7f9..9dadbde4 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/admin/ShopStoreActivityBaseController.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/admin/ShopStoreActivityBaseController.java @@ -65,7 +65,7 @@ public class ShopStoreActivityBaseController { return CommonResult.success(shopStoreActivityBaseService.listBarginItem()); } - @ApiOperation(value = "活动表-编辑", notes = "活动表-编辑") + @ApiOperation(value = "活动表-新增", notes = "活动表-新增") @RequestMapping(value = "/edit", method = RequestMethod.POST) public CommonResult edit() { return shopStoreActivityBaseService.saveActivityBase(); diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreActivityBaseServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreActivityBaseServiceImpl.java index c4746cc6..967dd236 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreActivityBaseServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreActivityBaseServiceImpl.java @@ -3653,7 +3653,7 @@ public class ShopStoreActivityBaseServiceImpl extends BaseServiceImpl 0) { + activity_rule.put("cut_hour", cut_hour); + } + // product_count - 参与活动商品总数(个) + Integer product_count = getParameter("product_count", 0); + if (product_count > 0) { + activity_rule.put("product_count", product_count); + } + shopStoreActivityBase.setActivity_rule(Convert.toStr(activity_rule)); } else if (base.getActivity_type_id().equals(StateCode.ACTIVITY_TYPE_GIFTBAG)) { //a+b组合套餐 @@ -5315,6 +5328,7 @@ public class ShopStoreActivityBaseServiceImpl extends BaseServiceImpl