From e1d1b5e5a2248381bc4faa2ac0e629676d17ff3c Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Wed, 01 Jul 2026 10:59:05 +0800
Subject: [PATCH] feat(mall): 支持优惠券多选绑定功能

---
 src/main/resources/templates/febs/views/modules/mallMember/couponSelect.html   |   52 +++++++++----
 src/main/java/cc/mrbird/febs/mall/entity/MallMember.java                       |    5 +
 src/main/java/cc/mrbird/febs/mall/mapper/SalemanCouponMapper.java              |    4 
 src/main/java/cc/mrbird/febs/mall/vo/AdminCouponSelectVo.java                  |    4 
 src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallMemberServiceImpl.java |   32 ++++---
 src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallMemberServiceImpl.java   |  103 ++++++++++++-------------
 6 files changed, 115 insertions(+), 85 deletions(-)

diff --git a/src/main/java/cc/mrbird/febs/mall/entity/MallMember.java b/src/main/java/cc/mrbird/febs/mall/entity/MallMember.java
index 9641bde..61c6398 100644
--- a/src/main/java/cc/mrbird/febs/mall/entity/MallMember.java
+++ b/src/main/java/cc/mrbird/febs/mall/entity/MallMember.java
@@ -9,6 +9,7 @@
 
 import java.math.BigDecimal;
 import java.util.Date;
+import java.util.List;
 
 /**
  * @author wzy
@@ -162,10 +163,12 @@
     //优惠卷名称
     @TableField(exist = false)
     private String couponName;
-
     //优惠卷名称
     @TableField(exist = false)
     private Long couponId;
+    //优惠卷ID列表(支持多选)
+    @TableField(exist = false)
+    private List<Long> couponIds;
 
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
diff --git a/src/main/java/cc/mrbird/febs/mall/mapper/SalemanCouponMapper.java b/src/main/java/cc/mrbird/febs/mall/mapper/SalemanCouponMapper.java
index 5909232..cc9e4ab 100644
--- a/src/main/java/cc/mrbird/febs/mall/mapper/SalemanCouponMapper.java
+++ b/src/main/java/cc/mrbird/febs/mall/mapper/SalemanCouponMapper.java
@@ -4,8 +4,10 @@
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import org.apache.ibatis.annotations.Param;
 
+import java.util.List;
+
 public interface SalemanCouponMapper extends BaseMapper<SalemanCoupon> {
 
-    SalemanCoupon selectByMemberId(@Param("memberId")Long memberId);
+    List<SalemanCoupon> selectByMemberId(@Param("memberId")Long memberId);
 
 }
diff --git a/src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallMemberServiceImpl.java b/src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallMemberServiceImpl.java
index 5ad9ccb..b1c3142 100644
--- a/src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallMemberServiceImpl.java
+++ b/src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallMemberServiceImpl.java
@@ -391,21 +391,25 @@
         if(ObjectUtil.isEmpty(member)){
             throw new FebsException("请刷新页面");
         }
-        Long couponId = mallmember.getCouponId();
-
-        QueryWrapper<SalemanCoupon> objectQueryWrapper = new QueryWrapper<>();
-        objectQueryWrapper.eq("member_id",member.getId());
-        List<SalemanCoupon> salemanCouponList = salemanCouponMapper.selectList(objectQueryWrapper);
-        if(CollUtil.isNotEmpty(salemanCouponList)){
-            SalemanCoupon salemanCoupon = salemanCouponList.get(0);
-            salemanCoupon.setCouponId(couponId);
-            salemanCouponMapper.updateById(salemanCoupon);
-            return new FebsResponse().success().message("操作成功");
+        List<Long> couponIds = mallmember.getCouponIds();
+        if(CollUtil.isEmpty(couponIds)){
+            return new FebsResponse().fail().message("请选择优惠券");
         }
-        SalemanCoupon salemanCoupon = new SalemanCoupon();
-        salemanCoupon.setMemberId(member.getId());
-        salemanCoupon.setCouponId(couponId);
-        salemanCouponMapper.insert(salemanCoupon);
+
+        for(Long couponId : couponIds){
+            // 检查是否已绑定,已绑定则跳过
+            QueryWrapper<SalemanCoupon> queryWrapper = new QueryWrapper<>();
+            queryWrapper.eq("member_id", member.getId());
+            queryWrapper.eq("coupon_id", couponId);
+            SalemanCoupon exist = salemanCouponMapper.selectOne(queryWrapper);
+            if(ObjectUtil.isNotEmpty(exist)){
+                continue;
+            }
+            SalemanCoupon salemanCoupon = new SalemanCoupon();
+            salemanCoupon.setMemberId(member.getId());
+            salemanCoupon.setCouponId(couponId);
+            salemanCouponMapper.insert(salemanCoupon);
+        }
         return new FebsResponse().success().message("操作成功");
     }
 
diff --git a/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallMemberServiceImpl.java b/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallMemberServiceImpl.java
index 0a695fc..1831857 100644
--- a/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallMemberServiceImpl.java
+++ b/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallMemberServiceImpl.java
@@ -24,6 +24,7 @@
 import cc.mrbird.febs.vip.mapper.MallVipConfigMapper;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
+import java.util.List;
 import cn.hutool.core.date.DateUnit;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.IdUtil;
@@ -923,45 +924,40 @@
     @Override
     public FebsResponse getCoupon(GetCouponDto getCouponDto) {
         Long memberId = LoginUserUtil.getLoginUser().getId();
+        Long goodsId = getCouponDto.getGoodsId();
 
-        String couponUUID = IdUtil.simpleUUID();
-//        String couponUUID = getCouponDto.getCouponUUID();
-//        QueryWrapper<MallMemberCoupon> objectQueryWrapper = new QueryWrapper<>();
-//        objectQueryWrapper.eq("coupon_uuid",couponUUID);
-//        List<MallMemberCoupon> mallMemberCouponDone = mallMemberCouponMapper.selectList(objectQueryWrapper);
-//        if(CollUtil.isNotEmpty(mallMemberCouponDone)){
-//            return new FebsResponse().success();
-//        }
+        //验证商品存不存在,且上没上架
+        MallGoods mallGoods = mallGoodsMapper.selectById(goodsId);
+        if(ObjectUtil.isEmpty(mallGoods) || MallGoods.ISSALE_STATUS_ENABLE != mallGoods.getIsSale()){
+            return new FebsResponse().success();
+        }
+
         //通过邀请人信息,获取能领取的优惠卷信息
         MallMember mallMember = this.baseMapper.selectInfoByInviteId(getCouponDto.getInviteId());
         if(ObjectUtil.isNotEmpty(mallMember)){
-            SalemanCoupon salemanCoupon = salemanCouponMapper.selectByMemberId(mallMember.getId());
-            if(ObjectUtil.isNotEmpty(salemanCoupon)){
-                Long couponId = salemanCoupon.getCouponId();
-                Long goodsId = getCouponDto.getGoodsId();
-                MallGoods mallGoods = mallGoodsMapper.selectById(goodsId);
-                //验证商品存不存在,且上没上架
-                if(ObjectUtil.isNotEmpty(mallGoods)
-                    && MallGoods.ISSALE_STATUS_ENABLE == mallGoods.getIsSale()){
-//                List<MallMemberCoupon> mallMemberCoupons = mallMemberCouponMapper.selectListByMemberIdAndGoodsIdAndCouponId(memberId, goodsId, couponId,mallMember.getInviteId());
-//                List<MallMemberCoupon> mallMemberCoupons = mallMemberCouponMapper.selectListByMemberIdAndGoodsIdAndCouponIdWithOutInviteId(memberId, goodsId, couponId);
-                    List<MallMemberCoupon> mallMemberCoupons = mallMemberCouponMapper.selectListByMemberIdAndGoodsIdAndCouponIdWithOutInviteId(memberId, goodsId);
-                    if(CollUtil.isEmpty(mallMemberCoupons)){
-                        //商品优惠卷如果绑定了,那么当前登陆者获取一张卷
-                        List<CouponGoods> couponGoodsList = couponGoodsMapper.selectByGoodIdAndCouponId(goodsId,couponId);
-                        MallGoodsCoupon mallGoodsCoupon = mallGoodsCouponMapper.selectById(couponId);
-                        if(CollUtil.isNotEmpty(couponGoodsList)){
-                            MallMemberCoupon mallMemberCoupon = new MallMemberCoupon();
-                            mallMemberCoupon.setCouponId(couponId);
-                            mallMemberCoupon.setCouponName(mallGoodsCoupon.getName());
-                            mallMemberCoupon.setMemberId(memberId);
-                            mallMemberCoupon.setGoodsId(goodsId);
-                            mallMemberCoupon.setCouponUuid(couponUUID);
-                            mallMemberCoupon.setInviteId(mallMember.getInviteId());
-                            mallMemberCoupon.setState(1);
-                            mallMemberCoupon.setExpireTime(DateUtil.offsetDay(DateUtil.date(),mallGoodsCoupon.getExpireDay()));
-                            mallMemberCouponMapper.insert(mallMemberCoupon);
-                        }
+            List<SalemanCoupon> salemanCouponList = salemanCouponMapper.selectByMemberId(mallMember.getId());
+            if(CollUtil.isNotEmpty(salemanCouponList)){
+                for(SalemanCoupon salemanCoupon : salemanCouponList){
+                    Long couponId = salemanCoupon.getCouponId();
+                    //验证是否已经领取过该优惠券
+                    List<MallMemberCoupon> mallMemberCoupons = mallMemberCouponMapper.selectListByMemberIdCouponIdWithOutInviteId(memberId, couponId);
+                    if(CollUtil.isNotEmpty(mallMemberCoupons)){
+                        continue;
+                    }
+                    //商品优惠卷如果绑定了该商品,那么当前登陆者获取一张卷
+                    List<CouponGoods> couponGoodsList = couponGoodsMapper.selectByGoodIdAndCouponId(goodsId, couponId);
+                    MallGoodsCoupon mallGoodsCoupon = mallGoodsCouponMapper.selectById(couponId);
+                    if(CollUtil.isNotEmpty(couponGoodsList) && ObjectUtil.isNotEmpty(mallGoodsCoupon)){
+                        MallMemberCoupon mallMemberCoupon = new MallMemberCoupon();
+                        mallMemberCoupon.setCouponId(couponId);
+                        mallMemberCoupon.setCouponName(mallGoodsCoupon.getName());
+                        mallMemberCoupon.setMemberId(memberId);
+                        mallMemberCoupon.setGoodsId(goodsId);
+                        mallMemberCoupon.setCouponUuid(IdUtil.simpleUUID());
+                        mallMemberCoupon.setInviteId(mallMember.getInviteId());
+                        mallMemberCoupon.setState(1);
+                        mallMemberCoupon.setExpireTime(DateUtil.offsetDay(DateUtil.date(), mallGoodsCoupon.getExpireDay()));
+                        mallMemberCouponMapper.insert(mallMemberCoupon);
                     }
                 }
             }
@@ -972,26 +968,29 @@
     @Override
     public FebsResponse scanCoupon(GetCouponDto getCouponDto) {
         Long memberId = LoginUserUtil.getLoginUser().getId();
-        String couponUUID = IdUtil.simpleUUID();
         //通过邀请人信息,获取能领取的优惠卷信息
         MallMember mallMember = this.baseMapper.selectInfoByInviteId(getCouponDto.getInviteId());
         if(ObjectUtil.isNotEmpty(mallMember)){
-            SalemanCoupon salemanCoupon = salemanCouponMapper.selectByMemberId(mallMember.getId());
-            if(ObjectUtil.isNotEmpty(salemanCoupon)){
-                Long couponId = salemanCoupon.getCouponId();
-                List<MallMemberCoupon> mallMemberCoupons = mallMemberCouponMapper.selectListByMemberIdCouponIdWithOutInviteId(memberId, couponId);
-                if(CollUtil.isEmpty(mallMemberCoupons)){
-                    //商品优惠卷如果绑定了,那么当前登陆者获取一张卷
-                    MallGoodsCoupon mallGoodsCoupon = mallGoodsCouponMapper.selectById(couponId);
-                    MallMemberCoupon mallMemberCoupon = new MallMemberCoupon();
-                    mallMemberCoupon.setCouponId(couponId);
-                    mallMemberCoupon.setCouponName(mallGoodsCoupon.getName());
-                    mallMemberCoupon.setMemberId(memberId);
-                    mallMemberCoupon.setCouponUuid(couponUUID);
-                    mallMemberCoupon.setInviteId(mallMember.getInviteId());
-                    mallMemberCoupon.setState(1);
-                    mallMemberCoupon.setExpireTime(DateUtil.offsetDay(DateUtil.date(),mallGoodsCoupon.getExpireDay()));
-                    mallMemberCouponMapper.insert(mallMemberCoupon);
+            List<SalemanCoupon> salemanCouponList = salemanCouponMapper.selectByMemberId(mallMember.getId());
+            if(CollUtil.isNotEmpty(salemanCouponList)){
+                for(SalemanCoupon salemanCoupon : salemanCouponList){
+                    Long couponId = salemanCoupon.getCouponId();
+                    List<MallMemberCoupon> mallMemberCoupons = mallMemberCouponMapper.selectListByMemberIdCouponIdWithOutInviteId(memberId, couponId);
+                    if(CollUtil.isEmpty(mallMemberCoupons)){
+                        //商品优惠卷如果绑定了,那么当前登陆者获取一张卷
+                        MallGoodsCoupon mallGoodsCoupon = mallGoodsCouponMapper.selectById(couponId);
+                        if(ObjectUtil.isNotEmpty(mallGoodsCoupon)){
+                            MallMemberCoupon mallMemberCoupon = new MallMemberCoupon();
+                            mallMemberCoupon.setCouponId(couponId);
+                            mallMemberCoupon.setCouponName(mallGoodsCoupon.getName());
+                            mallMemberCoupon.setMemberId(memberId);
+                            mallMemberCoupon.setCouponUuid(IdUtil.simpleUUID());
+                            mallMemberCoupon.setInviteId(mallMember.getInviteId());
+                            mallMemberCoupon.setState(1);
+                            mallMemberCoupon.setExpireTime(DateUtil.offsetDay(DateUtil.date(),mallGoodsCoupon.getExpireDay()));
+                            mallMemberCouponMapper.insert(mallMemberCoupon);
+                        }
+                    }
                 }
             }
         }
diff --git a/src/main/java/cc/mrbird/febs/mall/vo/AdminCouponSelectVo.java b/src/main/java/cc/mrbird/febs/mall/vo/AdminCouponSelectVo.java
index 4e84aba..14dcb0f 100644
--- a/src/main/java/cc/mrbird/febs/mall/vo/AdminCouponSelectVo.java
+++ b/src/main/java/cc/mrbird/febs/mall/vo/AdminCouponSelectVo.java
@@ -3,12 +3,14 @@
 import io.swagger.annotations.ApiModel;
 import lombok.Data;
 
+import java.util.List;
+
 @Data
 @ApiModel(value = "AdminCouponSelectVo", description = "信息返回类")
 public class AdminCouponSelectVo {
     private Long id;
 
-    private Long couponId;
+    private List<Long> couponIds;
 
     private String couponName;
 }
diff --git a/src/main/resources/templates/febs/views/modules/mallMember/couponSelect.html b/src/main/resources/templates/febs/views/modules/mallMember/couponSelect.html
index 0b7995f..156b28e 100644
--- a/src/main/resources/templates/febs/views/modules/mallMember/couponSelect.html
+++ b/src/main/resources/templates/febs/views/modules/mallMember/couponSelect.html
@@ -31,10 +31,8 @@
 
         <div class="layui-form-item">
             <label class="layui-form-label">优惠卷:</label>
-            <div class="layui-input-inline">
-                <select name="couponId" class="coupon-select-category" id="couponCategarySelect">
-                    <option value="">请选择</option>
-                </select>
+            <div class="layui-input-block">
+                <div id="coupon-select-multi"></div>
             </div>
         </div>
 
@@ -45,7 +43,7 @@
 </div>
 
 <script data-th-inline="javascript">
-    layui.use(['febs', 'form', 'formSelects', 'validate', 'treeSelect', 'eleTree', 'laydate','upload'], function () {
+    layui.use(['febs', 'form', 'formSelects', 'validate', 'treeSelect', 'eleTree', 'laydate','upload', 'xmSelect'], function () {
         var $ = layui.$,
             febs = layui.febs,
             layer = layui.layer,
@@ -57,6 +55,7 @@
             adminCouponSelectVo = [[${adminCouponSelectVo}]],
             $view = $('#coupon-select'),
             upload = layui.upload,
+            xmSelect = layui.xmSelect,
             validate = layui.validate;
 
         form.render();
@@ -66,27 +65,48 @@
 
         formSelects.render();
 
-        //(下拉框)
-        $.get(ctx + 'admin/goods/coupon/tree', function (data) {
-            for (var k in data)
-            {
-                $(".coupon-select-category").append("<option value='" + data[k].couponId + "'>" + data[k].couponName + "</option>");
+        // 多选优惠券
+        var couponMultiSelect = xmSelect.render({
+            el: '#coupon-select-multi',
+            language: 'zn',
+            tips: '请选择优惠券',
+            filterable: true,
+            data: []
+        });
+
+        febs.get(ctx + 'admin/goods/coupon/tree', null, function(data) {
+            var options = [];
+            for (var k in data) {
+                options.push({
+                    name: data[k].couponName,
+                    value: data[k].couponId
+                });
             }
-            layui.use('form', function () {
-                var form = layui.form;
-                $("#couponCategarySelect").val('')
-                form.render();
+            couponMultiSelect.update({
+                data: options,
+                autoRow: true
             });
         });
+
         initUserValue();
 
         function initUserValue() {
             form.val("coupon-select-form", {
-                "id": adminCouponSelectVo.id,
+                "id": adminCouponSelectVo.id
             });
         }
 
         form.on('submit(coupon-select-form-submit)', function (data) {
+            var selected = couponMultiSelect.getValue();
+            if (!selected || selected.length === 0) {
+                febs.alert.warn('请选择优惠券');
+                return false;
+            }
+            var couponIds = [];
+            for (var i = 0; i < selected.length; i++) {
+                couponIds.push(selected[i].value);
+            }
+            data.field.couponIds = couponIds;
             febs.post(ctx + 'admin/mallMember/salemanCoupon', data.field, function () {
                 layer.closeAll();
                 febs.alert.success('操作成功');
@@ -95,4 +115,4 @@
             return false;
         });
     });
-</script>
\ No newline at end of file
+</script>

--
Gitblit v1.9.1