From 2040c0a7fa055174f252aa3880a2506af70850cf Mon Sep 17 00:00:00 2001
From: peng <peng.com>
Date: 星期二, 16 九月 2025 17:07:45 +0800
Subject: [PATCH] Merge branch 'dev' into user_action

---
 framework/src/main/java/cn/lili/modules/lmk/enums/general/VirtualGoodsTypeEnum.java      |   13 
 framework/src/main/java/cn/lili/modules/lmk/domain/form/CouponVirtualForm.java           |   72 ++
 framework/src/main/java/cn/lili/modules/order/order/entity/vo/OrderSimpleVO.java         |    1 
 framework/src/main/java/cn/lili/modules/goods/entity/dos/GoodsSku.java                   |    7 
 framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsSkuServiceImpl.java       |    2 
 framework/src/main/java/cn/lili/modules/order/order/entity/enums/ModifyAddressEnums.java |   11 
 framework/src/main/java/cn/lili/modules/lmk/service/impl/CouponVirtualServiceImpl.java   |  262 ++++++++++
 framework/src/main/java/cn/lili/modules/goods/sku/GoodsSkuBuilder.java                   |    8 
 seller-api/src/main/java/cn/lili/controller/order/AfterSaleStoreController.java          |   16 
 framework/src/main/java/cn/lili/modules/order/order/mapper/OrderMapper.java              |    6 
 framework/src/main/java/cn/lili/modules/lmk/domain/entity/CouponVirtual.java             |   85 +++
 framework/src/main/java/cn/lili/modules/lmk/mapper/CouponVirtualMapper.java              |   35 +
 framework/src/main/java/cn/lili/modules/promotion/entity/dos/MemberCoupon.java           |    3 
 framework/src/main/java/cn/lili/modules/order/order/entity/enums/ClaimStatusEnum.java    |   30 +
 framework/src/main/resources/mapper/lmk/VideoMapper.xml                                  |    4 
 framework/src/main/java/cn/lili/modules/lmk/service/CouponVirtualService.java            |   74 ++
 framework/src/main/java/cn/lili/modules/order/cart/render/util/PromotionPriceUtil.java   |  154 +++--
 buyer-api/src/main/java/cn/lili/controller/order/AfterSaleBuyerController.java           |    4 
 framework/src/main/java/cn/lili/modules/lmk/domain/vo/CouponVirtualVOInfo.java           |   72 ++
 manager-api/src/main/java/cn/lili/controller/order/AfterSaleManagerController.java       |   32 +
 manager-api/src/main/java/cn/lili/controller/order/OrderComplaintManagerController.java  |   21 
 framework/src/main/java/cn/lili/modules/lmk/domain/query/CouponVirtualQuery.java         |   28 +
 framework/src/main/java/cn/lili/modules/order/order/entity/dto/OrderSearchParams.java    |    5 
 buyer-api/src/main/java/cn/lili/controller/lmk/CouponVirtualController.java              |   37 +
 buyer-api/src/main/java/cn/lili/controller/order/OrderBuyerController.java               |   37 +
 framework/src/main/java/cn/lili/modules/order/order/service/OrderService.java            |    4 
 framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java    |  134 ++++
 framework/src/main/java/cn/lili/modules/order/order/entity/dos/Order.java                |   11 
 framework/src/main/java/cn/lili/modules/order/order/entity/dos/OrderItem.java            |    6 
 framework/src/main/java/cn/lili/modules/promotion/entity/dos/Coupon.java                 |    3 
 framework/src/main/java/cn/lili/modules/goods/entity/dto/GoodsOperationDTO.java          |    8 
 framework/src/main/java/cn/lili/modules/lmk/domain/vo/CouponVirtualVO.java               |   77 ++
 seller-api/src/main/java/cn/lili/controller/goods/GoodsStoreController.java              |    1 
 manager-api/src/main/java/cn/lili/controller/lmk/CardPackController.java                 |   36 +
 framework/src/main/java/cn/lili/modules/order/order/entity/enums/CouPonFlagEnum.java     |   29 +
 framework/src/main/java/cn/lili/modules/goods/entity/dos/Goods.java                      |   12 
 framework/src/main/java/cn/lili/modules/order/cart/render/impl/CouponRender.java         |   47 +
 framework/src/main/java/cn/lili/modules/order/cart/render/impl/FullDiscountRender.java   |    2 
 framework/src/main/resources/mapper/lmk/CouponVirtualMapper.xml                          |   84 +++
 buyer-api/src/main/java/cn/lili/controller/lmk/CouponCardController.java                 |   37 +
 framework/src/main/java/cn/lili/modules/order/cart/entity/dto/SkuMapDTO.java             |   12 
 framework/src/main/java/cn/lili/modules/order/order/entity/vo/OrderSimpleXcxVO.java      |    6 
 framework/src/main/java/cn/lili/modules/order/order/entity/enums/ShareStatusEnum.java    |   29 +
 43 files changed, 1,471 insertions(+), 86 deletions(-)

diff --git a/buyer-api/src/main/java/cn/lili/controller/lmk/CouponCardController.java b/buyer-api/src/main/java/cn/lili/controller/lmk/CouponCardController.java
new file mode 100644
index 0000000..9bf841c
--- /dev/null
+++ b/buyer-api/src/main/java/cn/lili/controller/lmk/CouponCardController.java
@@ -0,0 +1,37 @@
+package cn.lili.controller.lmk;
+
+import cn.lili.base.Result;
+import cn.lili.modules.lmk.service.CouponVirtualService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@Validated
+@RequiredArgsConstructor
+@Api(value = "灏忕▼搴忚喘鐗╁崱鎺ュ彛", tags = "灏忕▼搴忚喘鐗╁崱鎺ュ彛")
+@RestController
+@RequestMapping("/buyer/lmk/coupon/card")
+public class CouponCardController {
+    private final CouponVirtualService couponVirtualService;
+
+    @PostMapping("/{cardId}")
+    @ApiOperation(value = "棰嗗彇璐墿鍗�", notes = "棰嗗彇璐墿鍗�")
+    public Result tackCardById(@PathVariable String cardId){
+        return couponVirtualService.tackCardById(cardId);
+    }
+    @PostMapping("/changShareStatus/{cardId}")
+    @ApiOperation(value = "鏇存敼鍒嗕韩鐘舵��", notes = "鏇存敼鍒嗕韩鐘舵��")
+    public Result changShareStatus(@PathVariable String cardId){
+        return couponVirtualService.changShareStatus(cardId);
+    }
+    @PostMapping("/couponCardInfo/{cardId}")
+    @ApiOperation(value = "鑾峰彇棰嗗彇淇℃伅", notes = "鑾峰彇棰嗗彇淇℃伅")
+    public Result couponCardInfo(@PathVariable String cardId){
+        return couponVirtualService.couponCardInfo(cardId);
+    }
+}
diff --git a/buyer-api/src/main/java/cn/lili/controller/lmk/CouponVirtualController.java b/buyer-api/src/main/java/cn/lili/controller/lmk/CouponVirtualController.java
new file mode 100644
index 0000000..26d7f0d
--- /dev/null
+++ b/buyer-api/src/main/java/cn/lili/controller/lmk/CouponVirtualController.java
@@ -0,0 +1,37 @@
+package cn.lili.controller.lmk;
+
+
+import cn.lili.base.Result;
+import cn.lili.modules.lmk.domain.query.CouponVirtualQuery;
+import cn.lili.modules.lmk.service.CouponVirtualService;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * lmk-shop-java
+ * 铏氭嫙浼樻儬鍗峰晢鍝�
+ *
+ * @author : zxl
+ * @date : 2025-09-12 09:41
+ **/
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/buyer/lmk/couponVirtual")
+public class CouponVirtualController {
+
+    private final CouponVirtualService couponVirtualService;
+
+    @GetMapping()
+    @ApiOperation(value = "鍒楄〃", notes = "鍒楄〃")
+    public Result getPage(CouponVirtualQuery query){
+        //鏇村叿璁㈠崟id鏌ヨ
+        return couponVirtualService.page(query);
+    }
+
+}
diff --git a/buyer-api/src/main/java/cn/lili/controller/order/AfterSaleBuyerController.java b/buyer-api/src/main/java/cn/lili/controller/order/AfterSaleBuyerController.java
index 68a8a0f..b053c7a 100644
--- a/buyer-api/src/main/java/cn/lili/controller/order/AfterSaleBuyerController.java
+++ b/buyer-api/src/main/java/cn/lili/controller/order/AfterSaleBuyerController.java
@@ -64,6 +64,10 @@
     @GetMapping(value = "/get/{sn}")
     public ResultMessage<AfterSaleVO> get(@NotNull(message = "鍞悗鍗曞彿") @PathVariable("sn") String sn) {
         AfterSaleVO afterSale = OperationalJudgment.judgment(afterSaleService.getAfterSale(sn));
+        String goodsImage = afterSale.getGoodsImage();
+        if (StringUtils.isNotBlank(goodsImage)&&!goodsImage.contains("http")) {
+            afterSale.setGoodsImage(cosUtil.getPreviewUrl(goodsImage));
+        }
         return ResultUtil.data(afterSale);
     }
 
diff --git a/buyer-api/src/main/java/cn/lili/controller/order/OrderBuyerController.java b/buyer-api/src/main/java/cn/lili/controller/order/OrderBuyerController.java
index 61888b1..23db668 100644
--- a/buyer-api/src/main/java/cn/lili/controller/order/OrderBuyerController.java
+++ b/buyer-api/src/main/java/cn/lili/controller/order/OrderBuyerController.java
@@ -10,10 +10,12 @@
 import cn.lili.common.utils.StringUtils;
 import cn.lili.common.vo.ResultMessage;
 import cn.lili.modules.lmk.enums.general.AdminRoleEnum;
+import cn.lili.modules.member.entity.dto.MemberAddressDTO;
 import cn.lili.modules.order.order.entity.dos.Order;
 import cn.lili.modules.order.order.entity.dos.OrderPackage;
 import cn.lili.modules.order.order.entity.dto.OrderSearchParams;
 import cn.lili.modules.order.order.entity.dto.OrderSearchXcxParams;
+import cn.lili.modules.order.order.entity.enums.ModifyAddressEnums;
 import cn.lili.modules.order.order.entity.enums.OrderStatusEnum;
 import cn.lili.modules.order.order.entity.vo.OrderDetailVO;
 import cn.lili.modules.order.order.entity.vo.OrderSimpleVO;
@@ -30,10 +32,12 @@
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 import springfox.documentation.annotations.ApiIgnore;
 
+import javax.validation.Valid;
 import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.NotNull;
 import java.util.ArrayList;
@@ -46,6 +50,7 @@
  * @author Chopper
  * @since 2020/11/16 10:08 涓嬪崍
  */
+@Slf4j
 @RestController
 @Api(tags = "涔板绔�,璁㈠崟鎺ュ彛")
 @RequestMapping("/buyer/order/order")
@@ -115,7 +120,37 @@
         });
         return ResultUtil.data(orderDetailVO);
     }
-
+    @ApiOperation(value = "璁㈠崟鏄庣粏")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "orderSn", value = "璁㈠崟缂栧彿", required = true, paramType = "path")
+    })
+    @GetMapping(value = "/editAddress/{orderSn}")
+    public ResultMessage<OrderDetailVO> editAddress(@NotNull(message = "璁㈠崟缂栧彿涓嶈兘涓虹┖") @PathVariable("orderSn") String orderSn) {
+        OrderDetailVO orderDetailVO = orderService.queryEditAddressDetail(orderSn);
+        Order order = orderDetailVO.getOrder();
+        if (!OrderStatusEnum.UNDELIVERED.name().equals(order.getOrderStatus())) {
+            log.error("璁㈠崟鍙蜂负{}------------------->鐘舵�佸紓甯镐负{}",orderSn,order.getOrderStatus());
+            throw new ServiceException("璁㈠崟鐘舵�佸紓甯告棤娉曢鍙�");
+        }
+        String modifyAddressFlag = order.getModifyAddressFlag();
+        if (ModifyAddressEnums.USED.name().equals(modifyAddressFlag)) {
+            throw new ServiceException("璁㈠崟宸茶棰嗗彇");
+        }
+        orderDetailVO.getOrderItems().forEach(orderItem -> {
+            String image = orderItem.getImage();
+            if (StringUtils.isNotBlank(image)&&!image.contains("http")) {
+                orderItem.setImage(cosUtil.getPreviewUrl(image));
+            }
+        });
+        return ResultUtil.data(orderDetailVO);
+    }
+    @ApiOperation(value = "淇敼鏀惰揣浜轰俊鎭�")
+    @ApiImplicitParam(name = "orderSn", value = "璁㈠崟sn", required = true, dataType = "String", paramType = "path")
+    @PostMapping(value = "/update/editAddress/{orderSn}/consignee")
+    public ResultMessage<Object> consignee(@NotNull(message = "鍙傛暟闈炴硶") @PathVariable String orderSn,
+                                           @Valid @RequestBody MemberAddressDTO memberAddressDTO) {
+        return ResultUtil.data(orderService.updateAddressConsignee(orderSn, memberAddressDTO));
+    }
     @PreventDuplicateSubmissions
     @ApiOperation(value = "纭鏀惰揣")
     @ApiImplicitParams({
diff --git a/framework/src/main/java/cn/lili/modules/goods/entity/dos/Goods.java b/framework/src/main/java/cn/lili/modules/goods/entity/dos/Goods.java
index 43d2e79..531cdd9 100644
--- a/framework/src/main/java/cn/lili/modules/goods/entity/dos/Goods.java
+++ b/framework/src/main/java/cn/lili/modules/goods/entity/dos/Goods.java
@@ -177,6 +177,10 @@
 
     @ApiModelProperty(value = "鍟嗗搧鎺掑簭")
     private Integer goodsSort;
+
+    @ApiModelProperty(value ="琛ㄧず铏氭嫙鍟嗗搧绫诲瀷 鐜版湁绫诲瀷锛欳OUPON浼樻儬鍔�")
+    private String virtualGoodsType;
+
     public Goods() {
     }
 
@@ -194,6 +198,8 @@
         this.mobileIntro = goodsOperationDTO.getMobileIntro();
         this.goodsVideo = goodsOperationDTO.getGoodsVideo();
         this.price = goodsOperationDTO.getPrice();
+        this.virtualGoodsType = goodsOperationDTO.getVirtualGoodsType();
+
         //涓嶆槸棰勫敭鍟嗗搧棰勫敭鏃堕棿缃┖
         if (!GoodsSalesModeEnum.PRESALE.name().equals(goodsOperationDTO.getSalesModel())) {
             goodsOperationDTO.setPreSaleBeginDate(null);
@@ -230,6 +236,12 @@
             if (!sku.containsKey("quantity") || StringUtil.isEmpty(sku.get("quantity").toString()) || Convert.toInt(sku.get("quantity").toString()) < 0) {
                 throw new ServiceException(ResultCode.GOODS_SKU_QUANTITY_ERROR);
             }
+            //娌℃湁浼樻儬鍗风殑鍟嗗搧闇�瑕佺Щ闄や紭鎯犲嵎淇℃伅
+            Object couponId = sku.get("couponId");
+            if (couponId == null || StringUtil.isEmpty(couponId.toString())) {
+                sku.remove("couponId");
+                sku.remove("couponName");
+            }
             sku.values().forEach(i -> {
                 if (CharSequenceUtil.isBlank(i.toString())) {
                     throw new ServiceException(ResultCode.MUST_HAVE_GOODS_SKU_VALUE);
diff --git a/framework/src/main/java/cn/lili/modules/goods/entity/dos/GoodsSku.java b/framework/src/main/java/cn/lili/modules/goods/entity/dos/GoodsSku.java
index 1b77b11..6f968a3 100644
--- a/framework/src/main/java/cn/lili/modules/goods/entity/dos/GoodsSku.java
+++ b/framework/src/main/java/cn/lili/modules/goods/entity/dos/GoodsSku.java
@@ -170,6 +170,12 @@
     @ApiModelProperty(value = "棰勮鏁伴噺")
     private Integer alertQuantity;
 
+    @ApiModelProperty(value ="浼樻儬鍔礽d")
+    private String couponId;
+
+    @ApiModelProperty(value ="浼樻儬鍔靛悕")
+    private String couponName;
+
     public Double getWeight() {
         if (weight == null) {
             return 0d;
@@ -223,6 +229,7 @@
         this.storeCategoryPath = goods.getStoreCategoryPath();
         this.freightTemplateId = goods.getTemplateId();
         this.recommend = goods.getRecommend();
+
     }
 
 }
\ No newline at end of file
diff --git a/framework/src/main/java/cn/lili/modules/goods/entity/dto/GoodsOperationDTO.java b/framework/src/main/java/cn/lili/modules/goods/entity/dto/GoodsOperationDTO.java
index b47e599..89323d9 100644
--- a/framework/src/main/java/cn/lili/modules/goods/entity/dto/GoodsOperationDTO.java
+++ b/framework/src/main/java/cn/lili/modules/goods/entity/dto/GoodsOperationDTO.java
@@ -158,6 +158,14 @@
     private BigDecimal commission;
     @ApiModelProperty(value = "鍟嗗搧鎺掑簭")
     private Integer goodsSort;
+    @ApiModelProperty(value = "浼樻儬鍔礽d")
+    private String couponId;
+    @ApiModelProperty(value = "浼樻儬鍔靛悕")
+    private String couponName;
+
+    @ApiModelProperty(value ="琛ㄧず铏氭嫙鍟嗗搧绫诲瀷 鐜版湁绫诲瀷锛欳OUPON浼樻儬鍔�")
+    private String virtualGoodsType;
+
 
     public String getGoodsName() {
         //瀵瑰晢鍝佸鍚嶇О鍋氫竴涓瀬闄愬鐞嗐�傝繖閲屾病鏈夌敤xss杩囨护鏄洜涓簒ss杩囨护涓哄叏灞�杩囨护锛屽奖鍝嶅緢澶с��
diff --git a/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsSkuServiceImpl.java b/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsSkuServiceImpl.java
index 63f3d6c..6cebe32 100644
--- a/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsSkuServiceImpl.java
+++ b/framework/src/main/java/cn/lili/modules/goods/serviceimpl/GoodsSkuServiceImpl.java
@@ -159,7 +159,7 @@
         // 妫�鏌ユ槸鍚﹂渶瑕佺敓鎴愮储寮�
         List<GoodsSku> goodsSkus = GoodsSkuBuilder.buildBatch(goods, goodsOperationDTO.getSkuList());
         renderGoodsSkuList(goodsSkus, goodsOperationDTO);
-
+        System.out.println(goodsSkus);
         if (!goodsSkus.isEmpty()) {
             this.saveOrUpdateBatch(goodsSkus);
             this.updateGoodsStock(goodsSkus);
diff --git a/framework/src/main/java/cn/lili/modules/goods/sku/GoodsSkuBuilder.java b/framework/src/main/java/cn/lili/modules/goods/sku/GoodsSkuBuilder.java
index 0df1a26..8e121d0 100644
--- a/framework/src/main/java/cn/lili/modules/goods/sku/GoodsSkuBuilder.java
+++ b/framework/src/main/java/cn/lili/modules/goods/sku/GoodsSkuBuilder.java
@@ -4,6 +4,7 @@
 import cn.hutool.core.convert.Convert;
 import cn.hutool.core.lang.Assert;
 import cn.hutool.json.JSONUtil;
+import cn.lili.common.utils.StringUtils;
 import cn.lili.modules.goods.entity.dos.Goods;
 import cn.lili.modules.goods.entity.dos.GoodsSku;
 import org.springframework.stereotype.Component;
@@ -64,7 +65,7 @@
         Map<String, Object> specMap = new LinkedHashMap<>();
 
         // 鍘熷瑙勬牸椤�
-        String[] ignoreOriginKeys = {"id", "sn", "cost", "price", "quantity", "weight", "alertQuantity"};
+        String[] ignoreOriginKeys = {"id", "sn", "cost", "price", "quantity", "weight", "alertQuantity","couponId","couponName"};
         //鑾峰彇瑙勬牸淇℃伅
         for (Map.Entry<String, Object> spec : skuInfo.entrySet()) {
             //淇濆瓨鏂板瑙勬牸淇℃伅
@@ -83,6 +84,11 @@
 
 
         //瑙勬牸淇℃伅
+        if(StringUtils.isNotBlank(Convert.toStr(skuInfo.get("couponId")))){
+            goodsSku.setCouponId(Convert.toStr(skuInfo.get("couponId"),""));
+        }
+
+        goodsSku.setCouponName(Convert.toStr(skuInfo.get("couponName"),""));
         goodsSku.setId(Convert.toStr(skuInfo.get("id"), ""));
         goodsSku.setSn(Convert.toStr(skuInfo.get("sn")));
         goodsSku.setWeight(Convert.toDouble(skuInfo.get("weight"), 0D));
diff --git a/framework/src/main/java/cn/lili/modules/lmk/domain/entity/CouponVirtual.java b/framework/src/main/java/cn/lili/modules/lmk/domain/entity/CouponVirtual.java
new file mode 100644
index 0000000..01deb89
--- /dev/null
+++ b/framework/src/main/java/cn/lili/modules/lmk/domain/entity/CouponVirtual.java
@@ -0,0 +1,85 @@
+package cn.lili.modules.lmk.domain.entity;
+
+import cn.lili.mybatis.BaseEntity;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+/**
+ * 铏氭嫙鍟嗗搧浼樻儬鍗�
+ *
+ * @author zxl
+ * @since 2025-09-10
+ */
+@Data
+@TableName("lmk_coupon_virtual")
+public class CouponVirtual extends BaseEntity {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableField("order_id")
+    /** 璁㈠崟id */
+    private String orderId;
+
+
+    @TableField("item_order_id")
+    /** 璁㈠崟id */
+    private String itemOrderId;
+
+    @TableField("goods_id")
+    /** 鍟嗗搧id */
+    private String goodsId;
+
+    @TableField("sku_id")
+    /** 鍟嗗搧id */
+    private String skuId;
+
+    @TableField("sku_name")
+    /** 鍟嗗搧鍚嶇О */
+    private String skuName;
+
+    @TableField("coupon_id")
+    /** 浼樻儬鍗穒d */
+    private String couponId;
+
+    @TableField("coupon_no")
+    /** 缂栧彿 */
+    private String couponNo;
+
+    @TableField("coupon_name")
+    /** 浼樻儬鍗峰悕绉� */
+    private String couponName;
+
+    @TableField("user_id")
+    /** 鐢ㄦ埛id */
+    private String userId;
+
+    @TableField("user_nickname")
+    /** 鐢ㄦ埛鏄电О */
+    private String userNickname;
+
+    @TableField("claim_time")
+    /** 棰嗗彇鏃堕棿 */
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date claimTime;
+
+    @TableField("name")
+    /** 鍚嶇О */
+    private String name;
+
+    @TableField("share_status")
+    /** 鏄惁鍒嗕韩 */
+    private String shareStatus;
+
+    @TableField("claim_status")
+    /** 鏄惁棰嗗彇 */
+    private String claimStatus;
+
+
+}
diff --git a/framework/src/main/java/cn/lili/modules/lmk/domain/form/CouponVirtualForm.java b/framework/src/main/java/cn/lili/modules/lmk/domain/form/CouponVirtualForm.java
new file mode 100644
index 0000000..86596c3
--- /dev/null
+++ b/framework/src/main/java/cn/lili/modules/lmk/domain/form/CouponVirtualForm.java
@@ -0,0 +1,72 @@
+package cn.lili.modules.lmk.domain.form;
+
+
+import cn.lili.base.AbsForm;
+import cn.lili.group.Add;
+import cn.lili.group.Update;
+import cn.lili.modules.lmk.domain.entity.CouponVirtual;
+import org.springframework.beans.BeanUtils;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import org.springframework.lang.NonNull;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import java.util.Date;
+
+/**
+ * 铏氭嫙鍟嗗搧浼樻儬鍗疯〃鍗�
+ *
+ * @author zxl
+ * @since 2025-09-10
+ */
+@Data
+@ApiModel(value = "CouponVirtual琛ㄥ崟", description = "铏氭嫙鍟嗗搧浼樻儬鍗疯〃鍗�")
+public class CouponVirtualForm extends AbsForm {
+
+    @NotNull(message = "璁㈠崟id涓嶈兘涓虹┖", groups = {Add.class, Update.class})
+    @ApiModelProperty("璁㈠崟id")
+    private Long orderId;
+
+    @NotNull(message = "鍟嗗搧id涓嶈兘涓虹┖", groups = {Add.class, Update.class})
+    @ApiModelProperty("鍟嗗搧id")
+    private Long goodsId;
+
+    @NotBlank(message = "鍟嗗搧鍚嶇О涓嶈兘涓虹┖", groups = {Add.class, Update.class})
+    @ApiModelProperty("鍟嗗搧鍚嶇О")
+    private String skuName;
+
+    @NotNull(message = "浼樻儬鍗穒d涓嶈兘涓虹┖", groups = {Add.class, Update.class})
+    @ApiModelProperty("浼樻儬鍗穒d")
+    private Long couponId;
+
+    @NotBlank(message = "缂栧彿涓嶈兘涓虹┖", groups = {Add.class, Update.class})
+    @ApiModelProperty("缂栧彿")
+    private String couponNo;
+
+    @NotBlank(message = "浼樻儬鍗峰悕绉颁笉鑳戒负绌�", groups = {Add.class, Update.class})
+    @ApiModelProperty("浼樻儬鍗峰悕绉�")
+    private String couponName;
+
+    @NotBlank(message = "鍚嶇О涓嶈兘涓虹┖", groups = {Add.class, Update.class})
+    @ApiModelProperty("鍚嶇О")
+    private String name;
+
+    @NotBlank(message = "鏄惁鍒嗕韩涓嶈兘涓虹┖", groups = {Add.class, Update.class})
+    @ApiModelProperty("鏄惁鍒嗕韩")
+    private String shareStatus;
+
+    @NotBlank(message = "鏄惁棰嗗彇涓嶈兘涓虹┖", groups = {Add.class, Update.class})
+    @ApiModelProperty("鏄惁棰嗗彇")
+    private String claimStatus;
+
+
+    public static CouponVirtual getEntityByForm(@NonNull CouponVirtualForm form, CouponVirtual entity) {
+        if(entity == null) {
+          entity = new CouponVirtual();
+        }
+        BeanUtils.copyProperties(form, entity);
+        return entity;
+    }
+
+}
diff --git a/framework/src/main/java/cn/lili/modules/lmk/domain/query/CouponVirtualQuery.java b/framework/src/main/java/cn/lili/modules/lmk/domain/query/CouponVirtualQuery.java
new file mode 100644
index 0000000..e86c8f9
--- /dev/null
+++ b/framework/src/main/java/cn/lili/modules/lmk/domain/query/CouponVirtualQuery.java
@@ -0,0 +1,28 @@
+package cn.lili.modules.lmk.domain.query;
+
+
+import java.util.List;
+
+import cn.lili.base.AbsQuery;
+import org.springframework.lang.NonNull;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * 铏氭嫙鍟嗗搧浼樻儬鍗锋煡璇�
+ *
+ * @author zxl
+ * @since 2025-09-10
+ */
+@Data
+@ApiModel(value = "CouponVirtual鏌ヨ鍙傛暟", description = "铏氭嫙鍟嗗搧浼樻儬鍗锋煡璇㈠弬鏁�")
+public class CouponVirtualQuery extends AbsQuery {
+    private String orderId;
+    private String userNickName;
+
+    private String skuName;
+}
+
diff --git a/framework/src/main/java/cn/lili/modules/lmk/domain/vo/CouponVirtualVO.java b/framework/src/main/java/cn/lili/modules/lmk/domain/vo/CouponVirtualVO.java
new file mode 100644
index 0000000..e526df0
--- /dev/null
+++ b/framework/src/main/java/cn/lili/modules/lmk/domain/vo/CouponVirtualVO.java
@@ -0,0 +1,77 @@
+package cn.lili.modules.lmk.domain.vo;
+
+
+import java.util.List;
+
+import cn.lili.base.AbsVo;
+import cn.lili.modules.lmk.domain.entity.CouponVirtual;
+import com.baomidou.mybatisplus.annotation.TableField;
+import org.springframework.lang.NonNull;
+import org.springframework.beans.BeanUtils;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import java.util.Date;
+
+/**
+ * 铏氭嫙鍟嗗搧浼樻儬鍗峰睍绀�
+ *
+ * @author zxl
+ * @since 2025-09-10
+ */
+@Data
+@ApiModel(value = "铏氭嫙鍟嗗搧浼樻儬鍗峰搷搴旀暟鎹�", description = "铏氭嫙鍟嗗搧浼樻儬鍗峰搷搴旀暟鎹�")
+public class CouponVirtualVO extends AbsVo {
+
+    /** 璁㈠崟id */
+    @ApiModelProperty("璁㈠崟id")
+    private String orderId;
+
+    /** 鍟嗗搧id */
+    @ApiModelProperty("鍟嗗搧id")
+    private String goodsId;
+
+    /** 鍟嗗搧鍚嶇О */
+    @ApiModelProperty("鍟嗗搧鍚嶇О")
+    private String skuName;
+
+    /** 浼樻儬鍗穒d */
+    @ApiModelProperty("浼樻儬鍗穒d")
+    private String couponId;
+
+    /** 缂栧彿 */
+    @ApiModelProperty("缂栧彿")
+    private String couponNo;
+
+    /** 浼樻儬鍗峰悕绉� */
+    @ApiModelProperty("浼樻儬鍗峰悕绉�")
+    private String couponName;
+
+    /** 鍚嶇О */
+    @ApiModelProperty("鍚嶇О")
+    private String name;
+
+    /** 鏄惁鍒嗕韩 */
+    @ApiModelProperty("鏄惁鍒嗕韩")
+    private String shareStatus;
+
+    /** 鏄惁棰嗗彇 */
+    @ApiModelProperty("鏄惁棰嗗彇")
+    private String claimStatus;
+
+
+    private Boolean deleteFlag;
+
+    private String original;
+
+    private String userNickName;
+
+    public static CouponVirtualVO getVoByEntity(@NonNull CouponVirtual entity, CouponVirtualVO vo) {
+        if(vo == null) {
+            vo = new CouponVirtualVO();
+        }
+        BeanUtils.copyProperties(entity, vo);
+        return vo;
+    }
+
+}
diff --git a/framework/src/main/java/cn/lili/modules/lmk/domain/vo/CouponVirtualVOInfo.java b/framework/src/main/java/cn/lili/modules/lmk/domain/vo/CouponVirtualVOInfo.java
new file mode 100644
index 0000000..07faf60
--- /dev/null
+++ b/framework/src/main/java/cn/lili/modules/lmk/domain/vo/CouponVirtualVOInfo.java
@@ -0,0 +1,72 @@
+package cn.lili.modules.lmk.domain.vo;
+
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+/**
+ * lmk-shop-java
+ *
+ * @author : zxl
+ * @date : 2025-09-12 15:19
+ **/
+@Data
+public class CouponVirtualVOInfo {
+    private static final long serialVersionUID = 1L;
+
+    private String id;
+
+    private String orderId;
+
+
+
+    private String itemOrderId;
+
+
+    private String goodsId;
+
+
+    private String skuId;
+
+
+    private String skuName;
+
+
+    private String couponId;
+
+
+    private String couponNo;
+
+
+    private String couponName;
+
+
+    private String userId;
+
+
+    private String userNickname;
+
+    /** 棰嗗彇鏃堕棿 */
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date claimTime;
+
+    /** 棰嗗彇鏃堕棿 */
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date createTime;
+    /** 鍚嶇О */
+    private String name;
+
+    /** 鏄惁鍒嗕韩 */
+    private String shareStatus;
+
+    /** 鏄惁棰嗗彇 */
+    private String claimStatus;
+
+    private String goodsUrl;
+}
diff --git a/framework/src/main/java/cn/lili/modules/lmk/enums/general/VirtualGoodsTypeEnum.java b/framework/src/main/java/cn/lili/modules/lmk/enums/general/VirtualGoodsTypeEnum.java
new file mode 100644
index 0000000..69d08a8
--- /dev/null
+++ b/framework/src/main/java/cn/lili/modules/lmk/enums/general/VirtualGoodsTypeEnum.java
@@ -0,0 +1,13 @@
+package cn.lili.modules.lmk.enums.general;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@AllArgsConstructor
+@Getter
+public enum VirtualGoodsTypeEnum {
+
+    COUPON("铏氭嫙浼樻儬鍔�");
+    private String description;
+
+}
diff --git a/framework/src/main/java/cn/lili/modules/lmk/mapper/CouponVirtualMapper.java b/framework/src/main/java/cn/lili/modules/lmk/mapper/CouponVirtualMapper.java
new file mode 100644
index 0000000..31fc724
--- /dev/null
+++ b/framework/src/main/java/cn/lili/modules/lmk/mapper/CouponVirtualMapper.java
@@ -0,0 +1,35 @@
+package cn.lili.modules.lmk.mapper;
+
+
+import cn.lili.modules.lmk.domain.entity.CouponVirtual;
+import cn.lili.modules.lmk.domain.query.CouponVirtualQuery;
+import cn.lili.modules.lmk.domain.vo.CouponVirtualVO;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+import java.util.List;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 铏氭嫙鍟嗗搧浼樻儬鍗� Mapper 鎺ュ彛
+ *
+ * @author zxl
+ * @since 2025-09-10
+ */
+@Mapper
+public interface CouponVirtualMapper extends BaseMapper<CouponVirtual> {
+
+    /**
+     * id鏌ユ壘铏氭嫙鍟嗗搧浼樻儬鍗�
+     * @param id
+     * @return
+     */
+    CouponVirtualVO getById(Integer id);
+
+    /**
+    *  鍒嗛〉
+    */
+    IPage getPage(IPage page, @Param("query") CouponVirtualQuery query);
+
+}
diff --git a/framework/src/main/java/cn/lili/modules/lmk/service/CouponVirtualService.java b/framework/src/main/java/cn/lili/modules/lmk/service/CouponVirtualService.java
new file mode 100644
index 0000000..6ea9f08
--- /dev/null
+++ b/framework/src/main/java/cn/lili/modules/lmk/service/CouponVirtualService.java
@@ -0,0 +1,74 @@
+package cn.lili.modules.lmk.service;
+
+
+import cn.lili.base.Result;
+import cn.lili.modules.lmk.domain.entity.CouponVirtual;
+import cn.lili.modules.lmk.domain.form.CouponVirtualForm;
+import cn.lili.modules.lmk.domain.query.CouponVirtualQuery;
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.springframework.web.bind.annotation.PathVariable;
+
+import java.util.List;
+
+/**
+ * 铏氭嫙鍟嗗搧浼樻儬鍗� 鏈嶅姟绫�
+ *
+ * @author zxl
+ * @since 2025-09-10
+ */
+public interface CouponVirtualService extends IService<CouponVirtual> {
+
+    /**
+     * 娣诲姞
+     * @param form
+     * @return
+     */
+    Result add(CouponVirtualForm form);
+
+    /**
+     * 淇敼
+     * @param form
+     * @return
+     */
+    Result update(CouponVirtualForm form);
+
+    /**
+     * 鎵归噺鍒犻櫎
+     * @param ids
+     * @return
+     */
+    Result remove(List<String> ids);
+
+    /**
+     * id鍒犻櫎
+     * @param id
+     * @return
+     */
+    Result removeById(String id);
+
+    /**
+     * 鍒嗛〉鏌ヨ
+     * @param query
+     * @return
+     */
+    Result page(CouponVirtualQuery query);
+
+    /**
+     * 鏍规嵁id鏌ユ壘
+     * @param id
+     * @return
+     */
+    Result detail(Integer id);
+
+    /**
+     * 鍒楄〃
+     * @return
+     */
+    Result all();
+
+    Result tackCardById( String cardId);
+
+    Result changShareStatus( String cardId);
+
+    Result couponCardInfo(String cardId);
+}
diff --git a/framework/src/main/java/cn/lili/modules/lmk/service/impl/CouponVirtualServiceImpl.java b/framework/src/main/java/cn/lili/modules/lmk/service/impl/CouponVirtualServiceImpl.java
new file mode 100644
index 0000000..72fb330
--- /dev/null
+++ b/framework/src/main/java/cn/lili/modules/lmk/service/impl/CouponVirtualServiceImpl.java
@@ -0,0 +1,262 @@
+package cn.lili.modules.lmk.service.impl;
+
+import cn.lili.base.Result;
+import cn.lili.common.exception.ServiceException;
+import cn.lili.common.security.AuthUser;
+import cn.lili.common.security.context.UserContext;
+import cn.lili.modules.goods.service.GoodsService;
+import cn.lili.modules.lmk.domain.entity.CouponVirtual;
+import cn.lili.modules.lmk.domain.form.CouponVirtualForm;
+import cn.lili.modules.lmk.domain.query.CouponVirtualQuery;
+import cn.lili.modules.lmk.domain.vo.CouponVirtualVO;
+import cn.lili.modules.lmk.domain.vo.CouponVirtualVOInfo;
+import cn.lili.modules.lmk.mapper.CouponVirtualMapper;
+import cn.lili.modules.lmk.service.CouponVirtualService;
+import cn.lili.modules.order.order.entity.dos.Order;
+import cn.lili.modules.order.order.entity.dos.OrderItem;
+import cn.lili.modules.order.order.entity.enums.ClaimStatusEnum;
+import cn.lili.modules.order.order.entity.enums.OrderStatusEnum;
+import cn.lili.modules.order.order.entity.enums.RefundStatusEnum;
+import cn.lili.modules.order.order.entity.enums.ShareStatusEnum;
+import cn.lili.modules.order.order.service.OrderItemService;
+import cn.lili.modules.order.order.service.OrderService;
+import cn.lili.modules.promotion.service.MemberCouponService;
+import cn.lili.utils.COSUtil;
+import cn.lili.utils.PageUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+
+import lombok.extern.slf4j.Slf4j;
+import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
+import org.springframework.stereotype.Service;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.BeanUtils;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.Assert;
+
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 铏氭嫙鍟嗗搧浼樻儬鍗� 鏈嶅姟瀹炵幇绫�
+ *
+ * @author zxl
+ * @since 2025-09-10
+ */
+@Service
+@RequiredArgsConstructor
+@Slf4j
+public class CouponVirtualServiceImpl extends ServiceImpl<CouponVirtualMapper, CouponVirtual> implements CouponVirtualService {
+
+    private final CouponVirtualMapper couponVirtualMapper;
+
+    private final RedissonClient redissonClient;
+
+    private final static String LOCK_COUPON_VIRTUAL_CARD_ID = "lock_coupon_virtual_card_id:";
+
+    private final OrderItemService orderItemService;
+
+    private final OrderService orderService;
+
+    private final MemberCouponService memberCouponService;
+
+    private final GoodsService goodsService;
+
+    private final COSUtil cosUtil;
+    /**
+     * 娣诲姞
+     *
+     * @param form
+     * @return
+     */
+    @Override
+    public Result add(CouponVirtualForm form) {
+        CouponVirtual entity = CouponVirtualForm.getEntityByForm(form, null);
+        baseMapper.insert(entity);
+        return Result.ok("娣诲姞鎴愬姛");
+    }
+
+    /**
+     * 淇敼
+     *
+     * @param form
+     * @return
+     */
+    @Override
+    public Result update(CouponVirtualForm form) {
+        CouponVirtual entity = baseMapper.selectById(form.getId());
+
+        // 涓虹┖鎶汭llegalArgumentException锛屽仛鍏ㄥ眬寮傚父澶勭悊
+        Assert.notNull(entity, "璁板綍涓嶅瓨鍦�");
+        BeanUtils.copyProperties(form, entity);
+        baseMapper.updateById(entity);
+        return Result.ok("淇敼鎴愬姛");
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎
+     *
+     * @param ids
+     * @return
+     */
+    @Override
+    public Result remove(List<String> ids) {
+        baseMapper.deleteBatchIds(ids);
+        return Result.ok("鍒犻櫎鎴愬姛");
+    }
+
+    /**
+     * id鍒犻櫎
+     *
+     * @param id
+     * @return
+     */
+    @Override
+    public Result removeById(String id) {
+        baseMapper.deleteById(id);
+        return Result.ok("鍒犻櫎鎴愬姛");
+    }
+
+    /**
+     * 鍒嗛〉鏌ヨ
+     *
+     * @param query
+     * @return
+     */
+    @Override
+    public Result page(CouponVirtualQuery query) {
+        IPage<CouponVirtualVO> page = PageUtil.getPage(query, CouponVirtualVO.class);
+        baseMapper.getPage(page, query);
+        for (CouponVirtualVO record : page.getRecords()) {
+            String original = record.getOriginal();
+            if (StringUtils.isNotBlank(original) && !original.contains("http")) {
+                record.setOriginal(cosUtil.getPreviewUrl(original));
+            }
+        }
+        return Result.ok().data(page.getRecords()).total(page.getTotal());
+    }
+
+    /**
+     * 鏍规嵁id鏌ユ壘
+     *
+     * @param id
+     * @return
+     */
+    @Override
+    public Result detail(Integer id) {
+        CouponVirtualVO vo = baseMapper.getById(id);
+        Assert.notNull(vo, "璁板綍涓嶅瓨鍦�");
+        return Result.ok().data(vo);
+    }
+
+    /**
+     * 鍒楄〃
+     *
+     * @return
+     */
+    @Override
+    public Result all() {
+        List<CouponVirtual> entities = baseMapper.selectList(null);
+        List<CouponVirtualVO> vos = entities.stream()
+                .map(entity -> CouponVirtualVO.getVoByEntity(entity, null))
+                .collect(Collectors.toList());
+        return Result.ok().data(vos);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Result tackCardById(String cardId) {
+        log.info("琚鍙栫殑绀煎搧鍗$殑id涓�--------------------------->{}",cardId);
+        AuthUser currentUser = UserContext.getCurrentUser();
+        if (currentUser == null) {
+            throw new ServiceException("褰撳墠鐢ㄦ埛娌℃湁鐧诲綍");
+        }
+        String userId = currentUser.getId();
+        String nickName = currentUser.getNickName();
+        RLock lock = null;
+        try {
+            lock = redissonClient.getLock(LOCK_COUPON_VIRTUAL_CARD_ID + cardId);
+            lock.lock();
+            LambdaQueryWrapper<CouponVirtual> forUpdate = Wrappers.<CouponVirtual>lambdaQuery().eq(CouponVirtual::getId, cardId).last("FOR UPDATE");
+            CouponVirtual cardInfo = this.getOne(forUpdate);
+            if (cardInfo == null) {
+                throw new ServiceException("褰撳墠浼樻儬鍗蜂笉瀛樺湪");
+            }
+            if (ClaimStatusEnum.CLAIM.name().equals(cardInfo.getClaimStatus())) {
+                throw new ServiceException("褰撳墠璐墿鍗″凡缁忚棰嗗彇");
+            }
+            //鏍¢獙璁㈠崟鐘舵�佹槸鍚︽甯�
+            String orderNo = cardInfo.getOrderId();
+            if (StringUtils.isBlank(orderNo)) {
+                throw new ServiceException("褰撳墠璁㈠崟涓嶅瓨鍦ㄦ棤娉曢鍙�");
+            }
+            String itemOrderId = cardInfo.getItemOrderId();
+            Order order = orderService.getBySn(orderNo);
+            if (order == null) {
+                throw new ServiceException("褰撳墠璁㈠崟涓嶅瓨鍦ㄦ棤娉曢鍙�");
+            }
+            if (!OrderStatusEnum.COMPLETED.name().equals(order.getOrderStatus())) {
+                throw new ServiceException("璁㈠崟鐘舵�佸紓甯告棤娉曢鍙�");
+            }
+            OrderItem orderItem = orderItemService.getById(itemOrderId);
+            if (orderItem == null) {
+                throw new ServiceException("褰撳墠璁㈠崟涓嶅瓨鍦�");
+            }
+            String orderSn = orderItem.getOrderSn();
+            if (!orderNo.equals(orderSn)) {
+                throw new ServiceException("璁㈠崟鏃犳硶瀵瑰簲鏃犳硶棰嗗彇");
+            }
+            if (!RefundStatusEnum.NO_REFUND.name().equals(orderItem.getIsRefund())) {
+                throw new ServiceException("褰撳墠璁㈠崟宸查��娆炬棤娉曢鍙�");
+            }
+            //棰嗗彇瀵瑰簲鐨勪紭鎯犲嵎
+            memberCouponService.receiveCoupon(cardInfo.getCouponId(),userId , nickName);
+            cardInfo.setUserNickname(nickName);
+            cardInfo.setUserId(userId);
+            cardInfo.setClaimStatus(ClaimStatusEnum.CLAIM.name());
+            cardInfo.setShareStatus(ShareStatusEnum.SHARE.name());
+            cardInfo.setClaimTime(new Date());
+            boolean b = this.updateById(cardInfo);
+            //鍘婚鍙栦紭鎯犲嵎
+            if (!b) {
+                throw new RuntimeException("棰嗗彇澶辫触");
+            }
+            return Result.ok().data(cardInfo.getCouponId());
+        } finally {
+            if ( lock != null && lock.isHeldByCurrentThread()) {
+                lock.unlock();
+            }
+        }
+    }
+
+    @Override
+    public Result changShareStatus(String cardId) {
+        CouponVirtual couponVirtual = this.getById(cardId);
+        couponVirtual.setShareStatus(ShareStatusEnum.SHARE.name());
+        this.updateById(couponVirtual);
+        return Result.ok();
+    }
+
+    @Override
+    public Result couponCardInfo(String cardId) {
+        CouponVirtual couponVirtual = this.getById(cardId);
+        if (couponVirtual == null) {
+            throw new ServiceException("褰撳墠璐墿鍗′笉瀛樺湪");
+        }
+        CouponVirtualVOInfo virtualVOInfo = new CouponVirtualVOInfo();
+        BeanUtils.copyProperties(couponVirtual, virtualVOInfo);
+
+        String goodsId = virtualVOInfo.getGoodsId();
+        String url = goodsService.getById(goodsId).getOriginal();
+        if (StringUtils.isNotBlank(url) && !url.contains("http")) {
+            virtualVOInfo.setGoodsUrl(cosUtil.getPreviewUrl(url));
+        }
+        return Result.ok().data(virtualVOInfo);
+    }
+}
diff --git a/framework/src/main/java/cn/lili/modules/order/cart/entity/dto/SkuMapDTO.java b/framework/src/main/java/cn/lili/modules/order/cart/entity/dto/SkuMapDTO.java
new file mode 100644
index 0000000..ff4d8a7
--- /dev/null
+++ b/framework/src/main/java/cn/lili/modules/order/cart/entity/dto/SkuMapDTO.java
@@ -0,0 +1,12 @@
+package cn.lili.modules.order.cart.entity.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+@Data
+@AllArgsConstructor
+
+public class SkuMapDTO {
+    private String skuId;
+    private Double price;
+}
diff --git a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CouponRender.java b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CouponRender.java
index 36d0423..24c6404 100644
--- a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CouponRender.java
+++ b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CouponRender.java
@@ -5,6 +5,7 @@
 import cn.lili.common.utils.CurrencyUtil;
 import cn.lili.common.utils.StringUtils;
 import cn.lili.modules.order.cart.entity.dto.MemberCouponDTO;
+import cn.lili.modules.order.cart.entity.dto.SkuMapDTO;
 import cn.lili.modules.order.cart.entity.dto.TradeDTO;
 import cn.lili.modules.order.cart.entity.enums.RenderStepEnums;
 import cn.lili.modules.order.cart.entity.vo.CartSkuVO;
@@ -240,8 +241,13 @@
 
         //鎺ユ敹鍏蜂綋浼樻儬鍒镐俊鎭�
         MemberCoupon coupon = memberCouponDTO.getMemberCoupon();
+
+        Integer goodsNum = tradeDTO.getSkuList().stream().map(CartSkuVO::getNum).reduce(Integer::sum).get();
+
         //澶勭悊涓�涓瀬绔儏鍐碉紝濡傛灉浼樻儬鍒告弧鍑忛噾棰濆ぇ浜庤鍗曢噾棰�
-        if (coupon.getCouponType().equals(CouponTypeEnum.PRICE.name()) && coupon.getPrice() > countPrice) {
+        if (coupon.getCouponType().equals(CouponTypeEnum.PRICE.name())
+                && coupon.getPrice() > countPrice
+                && coupon.getGoodsUseLimitNum() >= goodsNum) {
             //灏嗙鍚堜紭鎯犲埜鐨勯噾棰濆啓鍏ワ紝鍗虫渶澶ф墸鍑忛噾棰�
             coupon.setPrice(countPrice);
         }
@@ -264,21 +270,42 @@
      * @param memberCouponDTO 鐢ㄤ簬璁$畻浼樻儬鍒哥粨绠楄鎯�
      */
     private void renderCouponPrice(Map<String, Double> couponMap, TradeDTO tradeDTO, MemberCoupon coupon, MemberCouponDTO memberCouponDTO) {
+        List<SkuMapDTO> skuMapDTOList = new ArrayList<>();
+        for (String skuId : couponMap.keySet()) {
+            skuMapDTOList.add(new SkuMapDTO(skuId, couponMap.get(skuId)));
+        }
+        skuMapDTOList.sort((o1, o2) -> o2.getPrice().compareTo(o1.getPrice()));
         //鍒嗗彂浼樻儬鍒�
-        PromotionPriceUtil.recountPrice(tradeDTO, memberCouponDTO.getSkuDetail(), memberCouponDTO.getMemberCoupon().getPrice(),
-                Boolean.TRUE.equals(coupon.getPlatformFlag()) ?
-                        PromotionTypeEnum.PLATFORM_COUPON : PromotionTypeEnum.COUPON, memberCouponDTO.getMemberCoupon().getCouponId());
+        PromotionPriceUtil.recountPrice(tradeDTO, memberCouponDTO.getSkuDetail(),
+                memberCouponDTO.getMemberCoupon().getPrice(),
+                Boolean.TRUE.equals(coupon.getPlatformFlag()) ? PromotionTypeEnum.PLATFORM_COUPON : PromotionTypeEnum.COUPON,
+                memberCouponDTO.getMemberCoupon().getCouponId(),
+                memberCouponDTO.getMemberCoupon().getGoodsUseLimitNum());
         //濡傛灉鏄钩鍙板埜 鍒欓渶瑕佽绠楀晢瀹舵壙鎷呮瘮渚�
         if (Boolean.TRUE.equals(coupon.getPlatformFlag()) && coupon.getStoreCommission() > 0) {
 
+            Integer i = coupon.getGoodsUseLimitNum();
             //寰幆鎵�鏈変紭鎯犲埜
-            for (String skuId : couponMap.keySet()) {
+            for (SkuMapDTO skuMapDTO : skuMapDTOList) {
 
                 for (CartSkuVO cartSkuVO : tradeDTO.getSkuList()) {
                     //鍐欏叆骞冲彴浼樻儬鍒告壙鎷呮瘮渚�
-                    if (cartSkuVO.getGoodsSku().getId().equals(skuId)) {
-                        //鍐欏叆搴楅摵鎵挎媴姣斾緥
-                        cartSkuVO.getPriceDetailDTO().setSiteCouponPoint(coupon.getStoreCommission());
+                    if (cartSkuVO.getGoodsSku().getId().equals(skuMapDTO.getSkuId())) {
+                        if (i == null) {
+                            cartSkuVO.getPriceDetailDTO().setSiteCouponPoint(coupon.getStoreCommission());
+                        } else {
+                            if (i > 0) {
+                                //鍐欏叆搴楅摵鎵挎媴姣斾緥
+                                if (i >= cartSkuVO.getNum()) {
+                                    cartSkuVO.getPriceDetailDTO().setSiteCouponPoint(coupon.getStoreCommission());
+                                } else {
+                                    cartSkuVO.getPriceDetailDTO().setSiteCouponPoint(coupon.getStoreCommission() * i / cartSkuVO.getNum());
+                                }
+                                i = i - cartSkuVO.getNum();
+                            } else {
+                                return;
+                            }
+                        }
                     }
                 }
             }
@@ -294,6 +321,7 @@
      * @param coupon    浼樻儬鍒镐俊鎭�
      */
     private void renderCouponDiscount(Map<String, Double> couponMap, TradeDTO tradeDTO, MemberCoupon coupon) {
+
         //寰幆鎵�鏈変紭鎯犲埜
         for (String skuId : couponMap.keySet()) {
 
@@ -315,9 +343,10 @@
                     }
                     priceDetailDTO.setCouponPrice(CurrencyUtil.add(priceDetailDTO.getCouponPrice(), discountCouponPrice));
 
+                } else {
+                    return;
                 }
             }
         }
     }
-
 }
diff --git a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/FullDiscountRender.java b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/FullDiscountRender.java
index 270caba..0015269 100644
--- a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/FullDiscountRender.java
+++ b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/FullDiscountRender.java
@@ -86,7 +86,7 @@
                         if (isFull(countPrice, cart)) {
                             //濡傛灉鍑忕幇閲�
                             if (Boolean.TRUE.equals(fullDiscount.getFullMinusFlag())) {
-                                PromotionPriceUtil.recountPrice(tradeDTO, skuPriceDetail, fullDiscount.getFullMinus(), PromotionTypeEnum.FULL_DISCOUNT, fullDiscountVO.getId());
+                                PromotionPriceUtil.recountPrice(tradeDTO, skuPriceDetail, fullDiscount.getFullMinus(), PromotionTypeEnum.FULL_DISCOUNT, fullDiscountVO.getId(), 0);
                             }
                             //鎵撴姌
                             else if (Boolean.TRUE.equals(fullDiscount.getFullRateFlag())) {
diff --git a/framework/src/main/java/cn/lili/modules/order/cart/render/util/PromotionPriceUtil.java b/framework/src/main/java/cn/lili/modules/order/cart/render/util/PromotionPriceUtil.java
index f3dedc3..ad9333d 100644
--- a/framework/src/main/java/cn/lili/modules/order/cart/render/util/PromotionPriceUtil.java
+++ b/framework/src/main/java/cn/lili/modules/order/cart/render/util/PromotionPriceUtil.java
@@ -3,11 +3,13 @@
 import cn.hutool.core.map.MapUtil;
 import cn.lili.common.enums.PromotionTypeEnum;
 import cn.lili.common.utils.CurrencyUtil;
+import cn.lili.modules.order.cart.entity.dto.SkuMapDTO;
 import cn.lili.modules.order.cart.entity.dto.TradeDTO;
 import cn.lili.modules.order.cart.entity.vo.CartSkuVO;
 import cn.lili.modules.order.order.entity.dto.DiscountPriceItem;
 import lombok.extern.slf4j.Slf4j;
 
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
@@ -32,79 +34,111 @@
      * @param promotionTypeEnum  淇冮攢绫诲瀷
      */
     public static void recountPrice(TradeDTO tradeDTO, Map<String, Double> skuPromotionDetail, Double discountPrice,
-                                    PromotionTypeEnum promotionTypeEnum, String activityId) {
+                                    PromotionTypeEnum promotionTypeEnum, String activityId, Integer goodsUseLimitNum) {
 
         // sku 淇冮攢淇℃伅闈炵┖鍒ゅ畾
         if (skuPromotionDetail == null || skuPromotionDetail.isEmpty()) {
             return;
         }
-
         //璁$畻鎬婚噾棰�
         Double totalPrice = 0D;
-        for (Double value : skuPromotionDetail.values()) {
-            totalPrice = CurrencyUtil.add(totalPrice, value);
-        }
-
-        //鏋佺鎯呭喌锛屽鏋滄墸鍑忛噾棰濆皬浜庨渶瑕佹敮浠樼殑閲戦锛屽垯鎵e噺閲戦=鏀粯閲戦锛屼笉鑳芥垚涓鸿礋鏁�
-        if (discountPrice > totalPrice) {
-            discountPrice = totalPrice;
-
-            for (String skuId : skuPromotionDetail.keySet()) {
-
-                //鑾峰彇瀵瑰簲鍟嗗搧杩涜璁$畻
-                for (CartSkuVO cartSkuVO : tradeDTO.getSkuList()) {
-
-                    if (cartSkuVO.getGoodsSku().getId().equals(skuId)) {
-                        //浼樻儬鍒搁噾棰濓紝鍒欒鍏ヤ紭鎯犲埜 锛屽叾浠栧垯璁″叆鎬荤殑discount price
-                        if (promotionTypeEnum == PromotionTypeEnum.COUPON) {
-                            cartSkuVO.getPriceDetailDTO().setCouponPrice(cartSkuVO.getPriceDetailDTO().getGoodsPrice());
-                        } else {
-                            cartSkuVO.getPriceDetailDTO().setDiscountPrice(cartSkuVO.getPriceDetailDTO().getGoodsPrice());
-                        }
-                    }
-                }
-            }
-        }
-
         //鑾峰彇璐墿杞︿俊鎭�
         List<CartSkuVO> skuVOList = tradeDTO.getSkuList();
-
-        // 鑾峰彇map鍒嗛厤sku鐨勬�绘暟锛屽鏋滄槸鏈�鍚庝竴涓晢鍝佸垎閰嶉噾棰濓紝鍒欏皢閲戦浠庣櫨鍒嗘瘮鏀逛负鎬婚噾棰濇墸鍑忥紝閬垮厤鍑虹幇灏忔暟闄や笉灏�
-        AtomicInteger count = new AtomicInteger(skuPromotionDetail.size());
 
         //宸蹭紭鎯犻噾棰�
         AtomicReference<Double> deducted = new AtomicReference<>(0D);
 
-        for (String skuId : skuPromotionDetail.keySet()) {
+        if (goodsUseLimitNum > 0) {
+            // 澶勭悊闄愬埗鍟嗗搧鏁伴噺閫昏緫,鍙鐞嗕竴涓晢鍝�
+            List<SkuMapDTO> skuMapDTOList = new ArrayList<>();
+            for (String skuId : skuPromotionDetail.keySet()) {
+                skuMapDTOList.add(new SkuMapDTO(skuId, skuPromotionDetail.get(skuId)));
+            }
+            skuMapDTOList.sort((o1, o2) -> o2.getPrice().compareTo(o1.getPrice()));
 
-            //鑾峰彇瀵瑰簲鍟嗗搧杩涜璁$畻
+            final int[] i = {0};
+            for (SkuMapDTO skuMap : skuMapDTOList) {
 
-            Double finalDiscountPrice = discountPrice;
-            Double finalTotalPrice = totalPrice;
-            skuVOList.stream().filter(l -> l.getGoodsSku().getId().equals(skuId)).findFirst().ifPresent(cartSkuVO -> {
-                //sku 浼樻儬閲戦
-                Double skuDiscountPrice;
-                count.getAndDecrement();
+                //鑾峰彇瀵瑰簲鍟嗗搧杩涜璁$畻
+                Double finalDiscountPrice = discountPrice;
+                skuVOList.stream().filter(l -> l.getGoodsSku().getId().equals(skuMap.getSkuId())).findFirst().ifPresent(cartSkuVO -> {
+                    //sku 浼樻儬閲戦
+                    Double skuDiscountPrice = 0D;
+                    if (i[0] < 1) {
 
-                //闈炴渶鍚庝竴涓晢鍝侊紝鍒欐寜鐓ф瘮渚嬭绠�
-                if (count.get() > 0) {
-                    //鍟嗗搧閲戦鍗犳瘮
-                    double point = CurrencyUtil.div(cartSkuVO.getPriceDetailDTO().getGoodsPrice(), finalTotalPrice, 4);
-                    //鍟嗗搧浼樻儬閲戦
-                    skuDiscountPrice = CurrencyUtil.mul(finalDiscountPrice, point);
-                    //绱姞宸蹭紭鎯犻噾棰�
-                    deducted.set(CurrencyUtil.add(deducted.get(), skuDiscountPrice));
+                        if (cartSkuVO.getUtilPrice() > finalDiscountPrice) {
+                            skuDiscountPrice = cartSkuVO.getUtilPrice() - finalDiscountPrice;
+                        } else {
+                            skuDiscountPrice = cartSkuVO.getUtilPrice();
+                        }
+                        //绱姞宸蹭紭鎯犻噾棰�
+                        deducted.set(CurrencyUtil.add(deducted.get(), skuDiscountPrice));
+                        i[0] = i[0] + 1;
+                    }
+                    calculateCartSkuPromotionsPrice(cartSkuVO, skuDiscountPrice, promotionTypeEnum, activityId);
+                });
+                discountPrice = deducted.get();
+            }
+        } else {
+            for (Double value : skuPromotionDetail.values()) {
+                totalPrice = CurrencyUtil.add(totalPrice, value);
+            }
+
+            //鏋佺鎯呭喌锛屽鏋滄墸鍑忛噾棰濆皬浜庨渶瑕佹敮浠樼殑閲戦锛屽垯鎵e噺閲戦=鏀粯閲戦锛屼笉鑳芥垚涓鸿礋鏁�
+            if (discountPrice > totalPrice) {
+                discountPrice = totalPrice;
+
+                for (String skuId : skuPromotionDetail.keySet()) {
+
+                    //鑾峰彇瀵瑰簲鍟嗗搧杩涜璁$畻
+                    for (CartSkuVO cartSkuVO : tradeDTO.getSkuList()) {
+
+                        if (cartSkuVO.getGoodsSku().getId().equals(skuId)) {
+                            //浼樻儬鍒搁噾棰濓紝鍒欒鍏ヤ紭鎯犲埜 锛屽叾浠栧垯璁″叆鎬荤殑discount price
+                            if (promotionTypeEnum == PromotionTypeEnum.COUPON) {
+                                cartSkuVO.getPriceDetailDTO().setCouponPrice(cartSkuVO.getPriceDetailDTO().getGoodsPrice());
+                            } else {
+                                cartSkuVO.getPriceDetailDTO().setDiscountPrice(cartSkuVO.getPriceDetailDTO().getGoodsPrice());
+                            }
+                        }
+                    }
                 }
-                // 濡傛灉鏄渶鍚庝竴涓晢鍝� 鍒欏噺鍘讳箣鍓嶄紭鎯犵殑閲戦鏉ヨ繘琛岃绠�
-                else {
-                    skuDiscountPrice = CurrencyUtil.sub(finalDiscountPrice, deducted.get());
-                }
+            }
 
-                calculateCartSkuPromotionsPrice(cartSkuVO, skuDiscountPrice, promotionTypeEnum, activityId);
-            });
+            // 鑾峰彇map鍒嗛厤sku鐨勬�绘暟锛屽鏋滄槸鏈�鍚庝竴涓晢鍝佸垎閰嶉噾棰濓紝鍒欏皢閲戦浠庣櫨鍒嗘瘮鏀逛负鎬婚噾棰濇墸鍑忥紝閬垮厤鍑虹幇灏忔暟闄や笉灏�
+            AtomicInteger count = new AtomicInteger(skuPromotionDetail.size());
 
+
+            for (String skuId : skuPromotionDetail.keySet()) {
+
+                //鑾峰彇瀵瑰簲鍟嗗搧杩涜璁$畻
+
+                Double finalDiscountPrice = discountPrice;
+                Double finalTotalPrice = totalPrice;
+                skuVOList.stream().filter(l -> l.getGoodsSku().getId().equals(skuId)).findFirst().ifPresent(cartSkuVO -> {
+                    //sku 浼樻儬閲戦
+                    Double skuDiscountPrice;
+                    count.getAndDecrement();
+
+                    //闈炴渶鍚庝竴涓晢鍝侊紝鍒欐寜鐓ф瘮渚嬭绠�
+                    if (count.get() > 0) {
+                        //鍟嗗搧閲戦鍗犳瘮
+                        double point = CurrencyUtil.div(cartSkuVO.getPriceDetailDTO().getGoodsPrice(), finalTotalPrice, 4);
+                        //鍟嗗搧浼樻儬閲戦
+                        skuDiscountPrice = CurrencyUtil.mul(finalDiscountPrice, point);
+                        //绱姞宸蹭紭鎯犻噾棰�
+                        deducted.set(CurrencyUtil.add(deducted.get(), skuDiscountPrice));
+                    }
+                    // 濡傛灉鏄渶鍚庝竴涓晢鍝� 鍒欏噺鍘讳箣鍓嶄紭鎯犵殑閲戦鏉ヨ繘琛岃绠�
+                    else {
+                        skuDiscountPrice = CurrencyUtil.sub(finalDiscountPrice, deducted.get());
+                    }
+
+                    calculateCartSkuPromotionsPrice(cartSkuVO, skuDiscountPrice, promotionTypeEnum, activityId);
+                });
+
+            }
         }
-
         calculateNotEnoughPromotionsPrice(skuVOList, skuPromotionDetail, discountPrice, totalPrice, promotionTypeEnum, activityId);
 
     }
@@ -218,9 +252,11 @@
             // 濡傛灉杩樻湁鍓╀綑閲戦锛屽垯缁х画鍒嗘憡
             if (balance.get() > 0) {
                 skuPromotionDetailClone.remove(lastSkuId.toString());
-                double lastDiscountPrice = CurrencyUtil.sub(discountPrice, skuPromotionDetail.get(lastSkuId.toString()));
-                double lastTotalPrice = CurrencyUtil.sub(totalPrice, skuPromotionDetail.get(lastSkuId.toString()));
-                filterEnoughSku(skuVOList, skuPromotionDetailClone, lastDiscountPrice, lastTotalPrice, balance, lastSkuId, promotionTypeEnum, activityId);
+                if (skuPromotionDetail.containsKey(lastSkuId.toString())) {
+                    double lastDiscountPrice = CurrencyUtil.sub(discountPrice, skuPromotionDetail.get(lastSkuId.toString()));
+                    double lastTotalPrice = CurrencyUtil.sub(totalPrice, skuPromotionDetail.get(lastSkuId.toString()));
+                    filterEnoughSku(skuVOList, skuPromotionDetailClone, lastDiscountPrice, lastTotalPrice, balance, lastSkuId, promotionTypeEnum, activityId);
+                }
             } else {
                 break;
             }
@@ -235,9 +271,9 @@
 
 
     private static void filterEnoughSku(List<CartSkuVO> skuVOList, Map<String, Double> skuPromotionDetail,
-                                                   Double discountPrice, Double totalPrice,
-                                                   AtomicReference<Double> balance, StringBuilder lastSkuId,
-                                                   PromotionTypeEnum promotionTypeEnum, String activityId) {
+                                        Double discountPrice, Double totalPrice,
+                                        AtomicReference<Double> balance, StringBuilder lastSkuId,
+                                        PromotionTypeEnum promotionTypeEnum, String activityId) {
         AtomicInteger count = new AtomicInteger(skuPromotionDetail.size());
         AtomicReference<Double> countPrice = new AtomicReference<>(0D);
         for (String skuId : skuPromotionDetail.keySet()) {
diff --git a/framework/src/main/java/cn/lili/modules/order/order/entity/dos/Order.java b/framework/src/main/java/cn/lili/modules/order/order/entity/dos/Order.java
index 0ffe52a..c39556f 100644
--- a/framework/src/main/java/cn/lili/modules/order/order/entity/dos/Order.java
+++ b/framework/src/main/java/cn/lili/modules/order/order/entity/dos/Order.java
@@ -187,6 +187,17 @@
     private String orderType;
 
     /**
+     * @see CouPonFlagEnum
+     */
+    @ApiModelProperty(value = "鏄惁鏄ぜ鍝佸崱")
+    private String couponFlag;
+    /**
+     * 璁㈠崟鍦板潃淇敼鐘舵��
+     */
+    @ApiModelProperty(value = "璁㈠崟鍦板潃淇敼鐘舵��")
+    private String modifyAddressFlag;
+
+    /**
      * @see OrderPromotionTypeEnum
      */
     @ApiModelProperty(value = "璁㈠崟淇冮攢绫诲瀷")
diff --git a/framework/src/main/java/cn/lili/modules/order/order/entity/dos/OrderItem.java b/framework/src/main/java/cn/lili/modules/order/order/entity/dos/OrderItem.java
index 28e4ffe..fb2387a 100644
--- a/framework/src/main/java/cn/lili/modules/order/order/entity/dos/OrderItem.java
+++ b/framework/src/main/java/cn/lili/modules/order/order/entity/dos/OrderItem.java
@@ -85,6 +85,12 @@
     @ApiModelProperty(value = "淇冮攢id")
     private String promotionId;
 
+    @ApiModelProperty(value = "浼樻儬鍗穒d")
+    private String couponId;
+
+    @ApiModelProperty(value = "浼樻儬鍗峰悕绉�")
+    private String couponName;
+
     @ApiModelProperty(value = "閿�鍞噾棰�")
     private Double goodsPrice;
 
diff --git a/framework/src/main/java/cn/lili/modules/order/order/entity/dto/OrderSearchParams.java b/framework/src/main/java/cn/lili/modules/order/order/entity/dto/OrderSearchParams.java
index 89e1722..5075613 100644
--- a/framework/src/main/java/cn/lili/modules/order/order/entity/dto/OrderSearchParams.java
+++ b/framework/src/main/java/cn/lili/modules/order/order/entity/dto/OrderSearchParams.java
@@ -117,6 +117,9 @@
     @ApiModelProperty(value = "璁㈠崟淇冮攢绫诲瀷")
     private String orderPromotionType;
 
+    private String couponFlag;
+
+
     public <T> QueryWrapper<T> queryWrapper() {
         AuthUser currentUser = UserContext.getCurrentUser();
         QueryWrapper<T> wrapper = new QueryWrapper<>();
@@ -180,6 +183,8 @@
         //鎸夎瘎浠风姸鎬�
         wrapper.eq(CharSequenceUtil.isNotEmpty(commentStatus), "oi.comment_status", commentStatus);
 
+        wrapper.eq(CharSequenceUtil.isNotEmpty(couponFlag),"o.coupon_flag", couponFlag);
+
         //鎸夋爣绛炬煡璇�
         if (CharSequenceUtil.isNotEmpty(tag)) {
             String orderStatusColumn = "o.order_status";
diff --git a/framework/src/main/java/cn/lili/modules/order/order/entity/enums/ClaimStatusEnum.java b/framework/src/main/java/cn/lili/modules/order/order/entity/enums/ClaimStatusEnum.java
new file mode 100644
index 0000000..707420a
--- /dev/null
+++ b/framework/src/main/java/cn/lili/modules/order/order/entity/enums/ClaimStatusEnum.java
@@ -0,0 +1,30 @@
+package cn.lili.modules.order.order.entity.enums;
+
+/**
+ * 棰嗗彇鐘舵�佺姸鎬�
+ *
+
+ **/
+public enum ClaimStatusEnum {
+
+    /**
+     * 鍒嗕韩
+     */
+    CLAIM("棰嗗彇"),
+
+    /**
+     * 鏈垎浜�
+     */
+    NOT_CLAIM("鏈鍙�");
+
+    private final String description;
+
+    ClaimStatusEnum(String description) {
+        this.description = description;
+    }
+
+    public String description() {
+        return this.description;
+    }
+
+}
diff --git a/framework/src/main/java/cn/lili/modules/order/order/entity/enums/CouPonFlagEnum.java b/framework/src/main/java/cn/lili/modules/order/order/entity/enums/CouPonFlagEnum.java
new file mode 100644
index 0000000..3f8d70b
--- /dev/null
+++ b/framework/src/main/java/cn/lili/modules/order/order/entity/enums/CouPonFlagEnum.java
@@ -0,0 +1,29 @@
+package cn.lili.modules.order.order.entity.enums;
+
+/**
+ * 鍒嗕韩鐘舵��
+ *
+ **/
+public enum CouPonFlagEnum {
+
+    /**
+     * 绀煎搧鍗�
+     */
+    COUPON("绀煎搧鍗�"),
+
+    /**
+     * 涓嶆槸绀煎搧鍗�
+     */
+    NOT_COUPON("涓嶆槸绀煎搧鍗�");
+
+    private final String description;
+
+    CouPonFlagEnum(String description) {
+        this.description = description;
+    }
+
+    public String description() {
+        return this.description;
+    }
+
+}
diff --git a/framework/src/main/java/cn/lili/modules/order/order/entity/enums/ModifyAddressEnums.java b/framework/src/main/java/cn/lili/modules/order/order/entity/enums/ModifyAddressEnums.java
new file mode 100644
index 0000000..60db0f0
--- /dev/null
+++ b/framework/src/main/java/cn/lili/modules/order/order/entity/enums/ModifyAddressEnums.java
@@ -0,0 +1,11 @@
+package cn.lili.modules.order.order.entity.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@AllArgsConstructor
+@Getter
+public enum ModifyAddressEnums {
+    USED("宸茶棰嗗彇");
+    private final String des;
+}
diff --git a/framework/src/main/java/cn/lili/modules/order/order/entity/enums/ShareStatusEnum.java b/framework/src/main/java/cn/lili/modules/order/order/entity/enums/ShareStatusEnum.java
new file mode 100644
index 0000000..8857ed4
--- /dev/null
+++ b/framework/src/main/java/cn/lili/modules/order/order/entity/enums/ShareStatusEnum.java
@@ -0,0 +1,29 @@
+package cn.lili.modules.order.order.entity.enums;
+
+/**
+ * 鍒嗕韩鐘舵��
+ *
+ **/
+public enum ShareStatusEnum {
+
+    /**
+     * 鍒嗕韩
+     */
+    SHARE("鍒嗕韩"),
+
+    /**
+     * 鏈垎浜�
+     */
+    NOT_SHARE("鏈垎浜�");
+
+    private final String description;
+
+    ShareStatusEnum(String description) {
+        this.description = description;
+    }
+
+    public String description() {
+        return this.description;
+    }
+
+}
diff --git a/framework/src/main/java/cn/lili/modules/order/order/entity/vo/OrderSimpleVO.java b/framework/src/main/java/cn/lili/modules/order/order/entity/vo/OrderSimpleVO.java
index 089802f..aa439c6 100644
--- a/framework/src/main/java/cn/lili/modules/order/order/entity/vo/OrderSimpleVO.java
+++ b/framework/src/main/java/cn/lili/modules/order/order/entity/vo/OrderSimpleVO.java
@@ -159,6 +159,7 @@
 
     private String consigneeName;
     private String consigneeMobile;
+    private String modifyAddressFlag;
 
 
     private String memberId;
diff --git a/framework/src/main/java/cn/lili/modules/order/order/entity/vo/OrderSimpleXcxVO.java b/framework/src/main/java/cn/lili/modules/order/order/entity/vo/OrderSimpleXcxVO.java
index 811f3d4..440fc4b 100644
--- a/framework/src/main/java/cn/lili/modules/order/order/entity/vo/OrderSimpleXcxVO.java
+++ b/framework/src/main/java/cn/lili/modules/order/order/entity/vo/OrderSimpleXcxVO.java
@@ -27,6 +27,8 @@
 @Data
 public class OrderSimpleXcxVO {
 
+    private String id;
+
     @ApiModelProperty("sn")
     private String sn;
 
@@ -154,6 +156,10 @@
 
     @ApiModelProperty(value = "鍗栧璁㈠崟澶囨敞")
     private String sellerRemark;
+
+    @ApiModelProperty(value = "鏄惁鏄ぜ鍝佸崱")
+    private String couponFlag;
+
     private int i = 0;
     public List<OrderItemVO> initOrderItems() {
         if (CharSequenceUtil.isEmpty(groupGoodsId)) {
diff --git a/framework/src/main/java/cn/lili/modules/order/order/mapper/OrderMapper.java b/framework/src/main/java/cn/lili/modules/order/order/mapper/OrderMapper.java
index 6e851de..b300072 100644
--- a/framework/src/main/java/cn/lili/modules/order/order/mapper/OrderMapper.java
+++ b/framework/src/main/java/cn/lili/modules/order/order/mapper/OrderMapper.java
@@ -90,6 +90,7 @@
             "o.consignee_mobile AS consigneeMobile," +
             "o.member_id AS memberId," +
             "m.nick_name AS nickName," +
+            "o.modify_address_flag AS modifyAddressFlag,"+
             " GROUP_CONCAT(oi.goods_id) as group_goods_id," +
             " GROUP_CONCAT(oi.sku_id) as group_sku_id," +
             " GROUP_CONCAT(oi.num) as group_num" +
@@ -117,6 +118,7 @@
             "o.consignee_name AS consigneeName," +
             "o.consignee_mobile AS consigneeMobile," +
             "o.member_id AS memberId," +
+            "o.modify_address_flag AS modifyAddressFlag,"+
             " GROUP_CONCAT(oi.goods_id) as group_goods_id," +
             " GROUP_CONCAT(oi.sku_id) as group_sku_id," +
             " GROUP_CONCAT(oi.num) as group_num" +
@@ -139,8 +141,8 @@
      * @param queryWrapper 鏌ヨ鏉′欢
      * @return 绠�鐭鍗曞垎椤�
      */
-    @Select("select o.sn,o.flow_price,o.create_time,o.order_status,o.pay_status,o.payment_method,o.payment_time,o.member_name,o.store_name as " +
-            "store_name,o.store_id as store_id,o.client_type,o.order_type,o.deliver_status,o.order_promotion_type,o.seller_remark " +
+    @Select("select o.id,o.sn,o.flow_price,o.create_time,o.order_status,o.pay_status,o.payment_method,o.payment_time,o.member_name,o.store_name as " +
+            "store_name,o.store_id as store_id,o.client_type,o.order_type,o.deliver_status,o.order_promotion_type,o.seller_remark,o.coupon_flag " +
             ",GROUP_CONCAT(oi.goods_id) as group_goods_id," +
             " GROUP_CONCAT(oi.sku_id) as group_sku_id," +
             " GROUP_CONCAT(oi.num) as group_num" +
diff --git a/framework/src/main/java/cn/lili/modules/order/order/service/OrderService.java b/framework/src/main/java/cn/lili/modules/order/order/service/OrderService.java
index 9b8efa7..27f7281 100644
--- a/framework/src/main/java/cn/lili/modules/order/order/service/OrderService.java
+++ b/framework/src/main/java/cn/lili/modules/order/order/service/OrderService.java
@@ -127,6 +127,8 @@
      */
     OrderDetailVO queryDetail(String orderSn);
 
+    OrderDetailVO queryEditAddressDetail(String orderSn);
+
     String sendMqMessage(String  snNo);
     /**
      * 鍒涘缓璁㈠崟
@@ -175,6 +177,8 @@
      */
     Order updateConsignee(String orderSn, MemberAddressDTO memberAddressDTO);
 
+    Order updateAddressConsignee(String orderSn, MemberAddressDTO memberAddressDTO);
+
     /**
      * 璁㈠崟鍙戣揣
      *
diff --git a/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java b/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java
index dfe3ded..b775eca 100644
--- a/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java
+++ b/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java
@@ -27,8 +27,10 @@
 import cn.lili.modules.goods.entity.dos.Goods;
 import cn.lili.modules.goods.entity.dto.GoodsCompleteMessage;
 import cn.lili.modules.goods.service.GoodsService;
+import cn.lili.modules.lmk.domain.entity.CouponVirtual;
 import cn.lili.modules.lmk.domain.vo.OrderCountVO;
 import cn.lili.modules.lmk.enums.general.AdminRoleEnum;
+import cn.lili.modules.lmk.service.CouponVirtualService;
 import cn.lili.modules.member.entity.dos.Member;
 import cn.lili.modules.member.entity.dto.MemberAddressDTO;
 import cn.lili.modules.member.mapper.MemberMapper;
@@ -47,7 +49,9 @@
 import cn.lili.modules.permission.entity.dos.AdminUser;
 import cn.lili.modules.permission.service.AdminUserService;
 import cn.lili.modules.permission.service.RoleService;
+import cn.lili.modules.promotion.entity.dos.Coupon;
 import cn.lili.modules.promotion.entity.dos.Pintuan;
+import cn.lili.modules.promotion.service.CouponService;
 import cn.lili.modules.promotion.service.PintuanService;
 import cn.lili.modules.store.entity.dto.StoreDeliverGoodsAddressDTO;
 import cn.lili.modules.store.service.StoreDetailService;
@@ -87,6 +91,7 @@
 import org.apache.poi.ss.util.CellRangeAddressList;
 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.apache.rocketmq.spring.core.RocketMQTemplate;
+import org.redisson.api.RLock;
 import org.redisson.api.RedissonClient;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.ApplicationEventPublisher;
@@ -199,7 +204,18 @@
     @Resource
     private RedisTemplate<Object,Object> redisTemplate;
 
+    @Autowired
+    private CouponService couponService;
+
+    @Autowired
+    private CouponVirtualService couponVirtualService;
+
+    @Autowired
+    private RedissonClient redissonClient;
+
     private final static  String LOCK_ORDER_NO_MQ="lock_order_no_mq:";
+    private final static  String LOCK_EDIT_ORDER_ADDRESS="lock_edit_order_address:";
+    private final static  String LOCK_COUPON_CARD="lock_coupon_card:";
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void intoDB(TradeDTO tradeDTO) {
@@ -488,6 +504,18 @@
         //鏌ヨ璁㈠崟鍜岃嚜璁㈠崟锛岀劧鍚庡啓鍏o杩斿洖
         return new OrderDetailVO(order, orderItems, orderLogs, receipt);
     }
+    @Override
+    public OrderDetailVO queryEditAddressDetail(String orderSn) {
+        Order order = this.getBySn(orderSn);
+        if (order == null) {
+            throw new ServiceException(ResultCode.ORDER_NOT_EXIST);
+        }
+        //鏌ヨ璁㈠崟椤逛俊鎭�
+        List<OrderItem> orderItems = orderItemService.getByOrderSn(orderSn);
+
+        //鏌ヨ璁㈠崟鍜岃嚜璁㈠崟锛岀劧鍚庡啓鍏o杩斿洖
+        return new OrderDetailVO(order, orderItems, null, null);
+    }
 
     @Override
     @Transactional
@@ -666,7 +694,40 @@
 
         return order;
     }
+    @Override
+    @SystemLogPoint(description = "淇敼璁㈠崟", customerLog = "'璁㈠崟[' + #orderSn + ']鏀惰揣淇℃伅淇敼锛屼慨鏀逛负'+#memberAddressDTO.consigneeDetail")
+    @Transactional(rollbackFor = Exception.class)
+    public Order updateAddressConsignee(String orderSn, MemberAddressDTO memberAddressDTO) {
+        Order order = this.getBySn(orderSn);
+        if (order == null) {
+            throw new ServiceException(ResultCode.ORDER_NOT_EXIST);
+        }
+        //闄愬埗30绉掑彧鑳借姹備竴娆¢伩鍏嶅嚭鐜伴噸鏂版彁浜ら棶棰�
+        Boolean b = redisTemplate.opsForValue().setIfAbsent(LOCK_EDIT_ORDER_ADDRESS + orderSn, orderSn,30, TimeUnit.SECONDS);
+        if ( Boolean.FALSE.equals(b)){
+            throw new ServiceException("璇峰湪30绉掑悗閲嶈瘯");
+        }
+        String modifyAddressFlag = order.getModifyAddressFlag();
+        if (StringUtils.isNotBlank(modifyAddressFlag)) {
+            throw new ServiceException("褰撳墠璁㈠崟宸茬粡琚鍙�");
+        }
+        QueryWrapper<Order> wrapper = new QueryWrapper<>();
+        wrapper.eq("id", order.getId());
+        // 浣跨敤 last 鏂规硶鎷兼帴 FOR UPDATE 璇彞
+        wrapper.last("FOR UPDATE");
+        baseMapper.selectOne(wrapper);
+        //瑕佽褰曚箣鍓嶇殑鏀惰揣鍦板潃锛屾墍浠ラ渶瑕佷互浠g爜鏂瑰紡杩涜璋冪敤 涓嶉噰鐢ㄦ敞瑙�
+        String message = "璁㈠崟[" + orderSn + "]鏀惰揣淇℃伅淇敼锛岀敱[" +order.getConsigneeAddressPath()+  order.getConsigneeDetail() + "]淇敼涓篬" + memberAddressDTO.getConsigneeAddressPath()+ memberAddressDTO.getConsigneeDetail() + "]";
+        //璁板綍璁㈠崟鎿嶄綔鏃ュ織
+        BeanUtil.copyProperties(memberAddressDTO, order);
+        order.setModifyAddressFlag(ModifyAddressEnums.USED.name());
+        this.updateById(order);
+        OrderLog orderLog = new OrderLog(orderSn, UserContext.getCurrentUser().getId(), UserContext.getCurrentUser().getRole().getRole(),
+                UserContext.getCurrentUser().getUsername(), message);
+        orderLogService.save(orderLog);
 
+        return order;
+    }
     @Override
     @OrderLogPoint(description = "'璁㈠崟['+#orderSn+']鍙戣揣锛屽彂璐у崟鍙穂'+#logisticsNo+']'", orderSn = "#orderSn")
     @Transactional(rollbackFor = Exception.class)
@@ -740,17 +801,76 @@
     @OrderLogPoint(description = "'璁㈠崟['+#orderSn+']鏍搁攢锛屾牳閿�鐮乕'+#verificationCode+']'", orderSn = "#orderSn")
     @Transactional(rollbackFor = Exception.class)
     public Order take(String orderSn, String verificationCode) {
+        Order order;
+        RLock lock = redissonClient.getLock(LOCK_COUPON_CARD + orderSn);
+        try {
+             lock.lock();
+            //鑾峰彇璁㈠崟淇℃伅
+            order = this.getBySn(orderSn);
+            //璁㈠崟骞傜瓑闂
+            if (OrderStatusEnum.COMPLETED.name().equals(order.getOrderStatus())) {
+                throw new ServiceException("褰撳墠璁㈠崟宸插畬鎴愭棤娉曞啀娆℃牳楠�");
+            }
 
-        //鑾峰彇璁㈠崟淇℃伅
-        Order order = this.getBySn(orderSn);
-        //妫�娴嬭櫄鎷熻鍗曚俊鎭�
-        checkVerificationOrder(order, verificationCode);
-        order.setOrderStatus(OrderStatusEnum.COMPLETED.name());
-        //璁㈠崟瀹屾垚
-        this.complete(orderSn);
+            //妫�娴嬭櫄鎷熻鍗曚俊鎭�
+            checkVerificationOrder(order, verificationCode);
+            order.setOrderStatus(OrderStatusEnum.COMPLETED.name());
+            //璁㈠崟瀹屾垚
+            //鑾峰彇鎵�鏈夌殑璁㈠崟瀛愰」鐢ㄤ簬鐢熸垚浼樻儬鍗疯鍗曚俊鎭�
+            List<OrderItem> orderItems = orderItemService.getByOrderSn(orderSn);
+            List<CouponVirtual> couponVirtuals = new  ArrayList<>();
+            for (OrderItem orderItem : orderItems) {
+                String couponId = orderItem.getCouponId();
+                if (StringUtils.isBlank(couponId)) {
+                    continue;
+                }
+                String storeId = order.getStoreId();
+                Coupon one = couponService.getOne(Wrappers.<Coupon>lambdaQuery().eq(Coupon::getStoreId, storeId).eq(Coupon::getId, couponId));
+                if (one == null) {
+                    log.error("褰撳墠璁㈠崟璁㈠崟鍙蜂负:{}涓嶅瓨鍦ㄤ腑鐨勪紭鎯犲嵎涓嶅瓨鍦�----------------------->{}",order.getId(),orderItem.getOrderSn());
+                }else {
+                    Integer num = orderItem.getNum();
+                    //褰撹喘涔版暟閲忎笉涓虹┖鐨勬椂鍊欒繘琛�
+                    if (num != null) {
+                        for (int i = 1; i <= num; i++) {
+                            CouponVirtual couponVirtual = getCouponVirtual(orderItem);
+                            couponVirtual.setCouponNo(String.format("%08d", i));
+                            couponVirtuals.add(couponVirtual);
+                        }
+                    }
+
+                }
+            }
+            if (!couponVirtuals.isEmpty()) {
+                order.setCouponFlag(CouPonFlagEnum.COUPON.name());
+                couponVirtualService.saveBatch(couponVirtuals);
+                //鏇存柊鐘舵�佺敤浜庡悗缁皬绋嬪簭鍒ゆ柇寮瑰嚭鍗峰垪琛�
+                this.updateById(order);
+            }
+            this.complete(orderSn);
+        } finally {
+            assert lock != null;
+            if (lock.isHeldByCurrentThread()) {
+                lock.unlock();
+            }
+        }
         return order;
     }
 
+    private static CouponVirtual getCouponVirtual(OrderItem orderItem) {
+        CouponVirtual couponVirtual = new CouponVirtual();
+        couponVirtual.setOrderId(orderItem.getOrderSn());
+        couponVirtual.setCouponId(orderItem.getCouponId());
+        couponVirtual.setCouponName(orderItem.getCouponName());
+        couponVirtual.setGoodsId(orderItem.getGoodsId());
+        couponVirtual.setSkuId(orderItem.getSkuId());
+        couponVirtual.setItemOrderId(orderItem.getId());
+        couponVirtual.setSkuName(orderItem.getGoodsName());
+        couponVirtual.setName(orderItem.getCouponName());
+        couponVirtual.setShareStatus(ShareStatusEnum.NOT_SHARE.name());
+        couponVirtual.setClaimStatus(ClaimStatusEnum.NOT_CLAIM.name());
+        return couponVirtual;
+    }
     @Override
     public Order take(String verificationCode) {
         String storeId = OperationalJudgment.judgment(UserContext.getCurrentUser()).getStoreId();
diff --git a/framework/src/main/java/cn/lili/modules/promotion/entity/dos/Coupon.java b/framework/src/main/java/cn/lili/modules/promotion/entity/dos/Coupon.java
index 0a8f172..2f801d8 100644
--- a/framework/src/main/java/cn/lili/modules/promotion/entity/dos/Coupon.java
+++ b/framework/src/main/java/cn/lili/modules/promotion/entity/dos/Coupon.java
@@ -82,6 +82,9 @@
     @ApiModelProperty(value = "鏈夋晥鏈�")
     private Integer effectiveDays;
 
+    @ApiModelProperty(value = "鍟嗗搧浣跨敤闄愬埗")
+    private Integer goodsUseLimitNum;
+
     public Coupon(CouponVO couponVO) {
         BeanUtils.copyProperties(couponVO, this);
     }
diff --git a/framework/src/main/java/cn/lili/modules/promotion/entity/dos/MemberCoupon.java b/framework/src/main/java/cn/lili/modules/promotion/entity/dos/MemberCoupon.java
index 11c30b9..94d7111 100644
--- a/framework/src/main/java/cn/lili/modules/promotion/entity/dos/MemberCoupon.java
+++ b/framework/src/main/java/cn/lili/modules/promotion/entity/dos/MemberCoupon.java
@@ -107,6 +107,8 @@
     @ApiModelProperty(value = "浼氬憳浼樻儬鍒哥姸鎬�")
     private String memberCouponStatus;
 
+    @ApiModelProperty(value = "鍟嗗搧浣跨敤闄愬埗")
+    private Integer goodsUseLimitNum;
     public MemberCoupon() {
     }
 
@@ -120,6 +122,7 @@
         setScopeType(coupon.getScopeType());
         setScopeId(coupon.getScopeId());
         setCouponType(coupon.getCouponType());
+        setGoodsUseLimitNum(coupon.getGoodsUseLimitNum());
         setStartTime(coupon.getStartTime() == null ? new Date() : coupon.getStartTime());
 
         setGetType(coupon.getGetType());
diff --git a/framework/src/main/resources/mapper/lmk/CouponVirtualMapper.xml b/framework/src/main/resources/mapper/lmk/CouponVirtualMapper.xml
new file mode 100644
index 0000000..274c01d
--- /dev/null
+++ b/framework/src/main/resources/mapper/lmk/CouponVirtualMapper.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.lili.modules.lmk.mapper.CouponVirtualMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="cn.lili.modules.lmk.domain.vo.CouponVirtualVO">
+        <result column="order_id" property="orderId" />
+        <result column="goods_id" property="goodsId" />
+        <result column="sku_name" property="skuName" />
+        <result column="coupon_id" property="couponId" />
+        <result column="coupon_no" property="couponNo" />
+        <result column="coupon_name" property="couponName" />
+        <result column="name" property="name" />
+        <result column="share_status" property="shareStatus" />
+        <result column="claim_status" property="claimStatus" />
+        <result column="update_time" property="updateTime" />
+        <result column="create_by" property="createBy" />
+        <result column="create_time" property="createTime" />
+        <result column="update_by" property="updateBy" />
+        <result column="delete_flag" property="deleteFlag" />
+        <result column="original" property="original" />
+        <result column="user_nickname" property="userNickName" />
+    </resultMap>
+
+    <select id="getById" resultMap="BaseResultMap">
+        SELECT
+            LCV.order_id,
+            LCV.goods_id,
+            LCV.sku_name,
+            LCV.coupon_id,
+            LCV.coupon_no,
+            LCV.coupon_name,
+            LCV.name,
+            LCV.share_status,
+            LCV.claim_status,
+            LCV.update_time,
+            LCV.create_by,
+            LCV.create_time,
+            LCV.update_by,
+            LCV.delete_flag,
+            LCV.id
+        FROM
+            lmk_coupon_virtual LCV
+        WHERE
+            LCV.id = #{id} AND LCV.deleted = 0
+    </select>
+
+
+    <select id="getPage" resultMap="BaseResultMap">
+        SELECT
+            LCV.order_id,
+            LCV.goods_id,
+            LCV.sku_name,
+            LCV.coupon_id,
+            LCV.coupon_no,
+            LCV.coupon_name,
+            LCV.name,
+            LCV.share_status,
+            LCV.claim_status,
+            LCV.update_time,
+            LCV.create_by,
+            LCV.create_time,
+            LCV.update_by,
+            LCV.delete_flag,
+            LCV.user_nickname,
+            LCV.id,
+            LGS.original
+        FROM
+        lmk_coupon_virtual LCV JOIN li_goods_sku LGS ON LGS.id = LCV.sku_id
+        WHERE
+        LCV.delete_flag = 0 AND LGS.delete_flag = 0
+        <if test="query.orderId != null and query.orderId !=''">
+           AND LCV.order_id = #{query.orderId}
+        </if>
+        <if test="query.userNickName != null and query.userNickName !=''">
+            AND LCV.user_nickname like CONCAT('%', #{query.userNickName}, '%')
+        </if>
+        <if test="query.skuName != null and query.skuName !=''">
+            AND LCV.sku_name like CONCAT('%', #{query.skuName}, '%')
+        </if>
+    </select>
+
+
+</mapper>
diff --git a/framework/src/main/resources/mapper/lmk/VideoMapper.xml b/framework/src/main/resources/mapper/lmk/VideoMapper.xml
index 58a6600..b6dc81b 100644
--- a/framework/src/main/resources/mapper/lmk/VideoMapper.xml
+++ b/framework/src/main/resources/mapper/lmk/VideoMapper.xml
@@ -300,7 +300,7 @@
             LV.delete_flag = 0
           AND LV.STATUS = '1'
           AND LV.video_type = #{query.videoType}
-          AND lm.id IS NOT NULL
+          AND LM.id IS NOT NULL
         UNION ALL
         SELECT
             LV.author_id,
@@ -334,7 +334,7 @@
             LV.delete_flag = 0
           AND LV.STATUS = '1'
           AND LV.video_type = #{query.videoType}
-          AND lm.id IS NOT NULL
+          AND LM.id IS NOT NULL
         ORDER BY
             create_time DESC
     </select>
diff --git a/manager-api/src/main/java/cn/lili/controller/lmk/CardPackController.java b/manager-api/src/main/java/cn/lili/controller/lmk/CardPackController.java
new file mode 100644
index 0000000..0e53834
--- /dev/null
+++ b/manager-api/src/main/java/cn/lili/controller/lmk/CardPackController.java
@@ -0,0 +1,36 @@
+package cn.lili.controller.lmk;
+
+
+import cn.lili.base.Result;
+import cn.lili.modules.lmk.domain.query.CouponVirtualQuery;
+import cn.lili.modules.lmk.service.CouponVirtualService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * lmk-shop-java
+ *
+ * @author : zxl
+ * @date : 2025-09-12 18:11
+ **/
+@Validated
+@RequiredArgsConstructor
+@Api(value = "绀煎搧鍗″寘", tags = "绀煎搧鍗″寘")
+@RestController
+@RequestMapping("/manager/cardPack")
+public class CardPackController {
+    private final CouponVirtualService couponVirtualService;
+
+    @GetMapping
+    @ApiOperation(value = "鍒楄〃", notes = "鍒楄〃")
+    public Result getPage(CouponVirtualQuery query){
+        //鏇村叿璁㈠崟id鏌ヨ
+        return couponVirtualService.page(query);
+    }
+
+}
diff --git a/manager-api/src/main/java/cn/lili/controller/order/AfterSaleManagerController.java b/manager-api/src/main/java/cn/lili/controller/order/AfterSaleManagerController.java
index 2764615..e20b3b5 100644
--- a/manager-api/src/main/java/cn/lili/controller/order/AfterSaleManagerController.java
+++ b/manager-api/src/main/java/cn/lili/controller/order/AfterSaleManagerController.java
@@ -2,13 +2,16 @@
 
 import cn.lili.common.aop.annotation.PreventDuplicateSubmissions;
 import cn.lili.common.enums.ResultUtil;
+import cn.lili.common.utils.StringUtils;
 import cn.lili.common.vo.ResultMessage;
 import cn.lili.modules.order.aftersale.entity.dos.AfterSale;
 import cn.lili.modules.order.aftersale.entity.vo.AfterSaleSearchParams;
 import cn.lili.modules.order.aftersale.entity.vo.AfterSaleVO;
+import cn.lili.modules.order.aftersale.mapper.AfterSaleMapper;
 import cn.lili.modules.order.aftersale.service.AfterSaleService;
 import cn.lili.modules.store.entity.dto.StoreAfterSaleAddressDTO;
 import cn.lili.modules.system.entity.vo.Traces;
+import cn.lili.utils.COSUtil;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
@@ -18,6 +21,7 @@
 import org.springframework.web.bind.annotation.*;
 
 import javax.validation.constraints.NotNull;
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -36,11 +40,19 @@
      */
     @Autowired
     private AfterSaleService afterSaleService;
+    @Autowired
+    private COSUtil cosUtil;
 
     @ApiOperation(value = "鍒嗛〉鑾峰彇鍞悗鏈嶅姟")
     @GetMapping(value = "/page")
     public ResultMessage<IPage<AfterSaleVO>> getByPage(AfterSaleSearchParams searchParams) {
-        return ResultUtil.data(afterSaleService.getAfterSalePages(searchParams));
+        IPage<AfterSaleVO> afterSalePages = afterSaleService.getAfterSalePages(searchParams);
+        for (AfterSaleVO record : afterSalePages.getRecords()) {
+            if (StringUtils.isNotBlank(record.getGoodsImage())&&!record.getGoodsImage().contains("http")) {
+                record.setGoodsImage(cosUtil.getPreviewUrl(record.getGoodsImage()));
+            }
+        }
+        return ResultUtil.data(afterSalePages);
     }
 
     @ApiOperation(value = "鑾峰彇瀵煎嚭鍞悗鏈嶅姟鍒楄〃鍒楄〃")
@@ -53,7 +65,23 @@
     @ApiImplicitParam(name = "sn", value = "鍞悗鍗曞彿", required = true, paramType = "path")
     @GetMapping(value = "/get/{sn}")
     public ResultMessage<AfterSaleVO> get(@NotNull(message = "鍞悗鍗曞彿") @PathVariable("sn") String sn) {
-        return ResultUtil.data(afterSaleService.getAfterSale(sn));
+        AfterSaleVO afterSale = afterSaleService.getAfterSale(sn);
+        String afterSaleImage = afterSale.getAfterSaleImage();
+        if (StringUtils.isNotBlank(afterSaleImage)) {
+            String[] split = afterSaleImage.split(",");
+            List<String> asleImages = new ArrayList<>(split.length);
+            for (String s : split) {
+                if (!s.contains("http")){
+                    asleImages.add(cosUtil.getPreviewUrl(s));
+                }
+            }
+            String join = String.join(",", asleImages);
+            afterSale.setAfterSaleImage(join);
+        }
+        if (StringUtils.isNotBlank(afterSale.getGoodsImage())&&!afterSale.getGoodsImage().contains("http")) {
+            afterSale.setGoodsImage(cosUtil.getPreviewUrl(afterSale.getGoodsImage()));
+        }
+        return ResultUtil.data(afterSale);
     }
 
     @ApiOperation(value = "鏌ョ湅涔板閫�璐х墿娴佽釜杩�")
diff --git a/manager-api/src/main/java/cn/lili/controller/order/OrderComplaintManagerController.java b/manager-api/src/main/java/cn/lili/controller/order/OrderComplaintManagerController.java
index c328674..1610157 100644
--- a/manager-api/src/main/java/cn/lili/controller/order/OrderComplaintManagerController.java
+++ b/manager-api/src/main/java/cn/lili/controller/order/OrderComplaintManagerController.java
@@ -4,6 +4,7 @@
 import cn.lili.common.enums.ResultUtil;
 import cn.lili.common.security.AuthUser;
 import cn.lili.common.security.context.UserContext;
+import cn.lili.common.utils.StringUtils;
 import cn.lili.common.vo.PageVO;
 import cn.lili.common.vo.ResultMessage;
 import cn.lili.modules.order.order.entity.dos.OrderComplaint;
@@ -15,6 +16,7 @@
 import cn.lili.modules.order.order.entity.vo.OrderComplaintVO;
 import cn.lili.modules.order.order.service.OrderComplaintCommunicationService;
 import cn.lili.modules.order.order.service.OrderComplaintService;
+import cn.lili.utils.COSUtil;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
@@ -23,6 +25,8 @@
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.Arrays;
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -48,11 +52,26 @@
     @Autowired
     private OrderComplaintCommunicationService orderComplaintCommunicationService;
 
+    @Autowired
+    private COSUtil cosUtil;
     @ApiOperation(value = "閫氳繃id鑾峰彇")
     @ApiImplicitParam(name = "id", value = "鎶曡瘔鍗旾D", required = true, paramType = "path")
     @GetMapping(value = "/{id}")
     public ResultMessage<OrderComplaintVO> get(@PathVariable String id) {
-        return ResultUtil.data(orderComplaintService.getOrderComplainById(id));
+        OrderComplaintVO orderComplainById = orderComplaintService.getOrderComplainById(id);
+        String goodsImage = orderComplainById.getGoodsImage();
+        if (StringUtils.isNotBlank(goodsImage)&&!goodsImage.contains("http")) {
+            orderComplainById.setGoodsImage(cosUtil.getPreviewUrl(goodsImage));
+        }
+        String[] orderComplaintImages = orderComplainById.getOrderComplaintImages();
+        List<String> orderComplaintImagesList = Arrays.asList(orderComplaintImages);
+        for (String orderComplaintImage : orderComplaintImages) {
+            if (StringUtils.isNotBlank(orderComplaintImage)&&!orderComplaintImage.contains("http")) {
+                orderComplaintImagesList.add(cosUtil.getPreviewUrl(orderComplaintImage));
+            }
+        }
+        orderComplainById.setOrderComplaintImages(orderComplaintImagesList.toArray(new String[0]));
+        return ResultUtil.data(orderComplainById);
     }
 
     @ApiOperation(value = "鍒嗛〉鑾峰彇")
diff --git a/seller-api/src/main/java/cn/lili/controller/goods/GoodsStoreController.java b/seller-api/src/main/java/cn/lili/controller/goods/GoodsStoreController.java
index f4f46c0..ef46981 100644
--- a/seller-api/src/main/java/cn/lili/controller/goods/GoodsStoreController.java
+++ b/seller-api/src/main/java/cn/lili/controller/goods/GoodsStoreController.java
@@ -155,6 +155,7 @@
     @ApiOperation(value = "鏂板鍟嗗搧")
     @PostMapping(value = "/create", consumes = "application/json", produces = "application/json")
     public ResultMessage<GoodsOperationDTO> save(@Valid @RequestBody GoodsOperationDTO goodsOperationDTO) {
+
         System.err.println(JSONObject.toJSONString(goodsOperationDTO));
         goodsService.addGoods(goodsOperationDTO);
         return ResultUtil.success();
diff --git a/seller-api/src/main/java/cn/lili/controller/order/AfterSaleStoreController.java b/seller-api/src/main/java/cn/lili/controller/order/AfterSaleStoreController.java
index ff5fc4d..133400c 100644
--- a/seller-api/src/main/java/cn/lili/controller/order/AfterSaleStoreController.java
+++ b/seller-api/src/main/java/cn/lili/controller/order/AfterSaleStoreController.java
@@ -22,6 +22,7 @@
 import org.springframework.web.bind.annotation.*;
 
 import javax.validation.constraints.NotNull;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
 
@@ -46,6 +47,21 @@
     @GetMapping(value = "/{sn}")
     public ResultMessage<AfterSaleVO> get(@PathVariable String sn) {
         AfterSaleVO afterSale = OperationalJudgment.judgment(afterSaleService.getAfterSale(sn));
+        String afterSaleImage = afterSale.getAfterSaleImage();
+        if (StringUtils.isNotBlank(afterSaleImage)) {
+            String[] split = afterSaleImage.split(",");
+            List<String> asleImages = new ArrayList<>(split.length);
+            for (String s : split) {
+                if (!s.contains("http")){
+                    asleImages.add(cosUtil.getPreviewUrl(s));
+                }
+            }
+            String join = String.join(",", asleImages);
+            afterSale.setAfterSaleImage(join);
+        }
+        if (StringUtils.isNotBlank(afterSale.getGoodsImage())&&!afterSale.getGoodsImage().contains("http")) {
+            afterSale.setGoodsImage(cosUtil.getPreviewUrl(afterSale.getGoodsImage()));
+        }
         return ResultUtil.data(afterSale);
     }
 

--
Gitblit v1.8.0