From 7eb522243fb5dce2b7268fdf0927409d5a3b0d70 Mon Sep 17 00:00:00 2001
From: Helius <wangdoubleone@gmail.com>
Date: Tue, 30 Jan 2024 11:40:52 +0800
Subject: [PATCH] fix

---
 src/main/java/cc/mrbird/febs/vip/mapper/MallVipBenefitsDetailsMapper.java            |    7 
 src/main/resources/mapper/modules/MallVipBenefitsMapper.xml                          |   59 
 src/main/java/cc/mrbird/febs/vip/entity/MallVipConfigBenefits.java                   |   20 
 src/main/java/cc/mrbird/febs/mall/quartz/OrderSettlementJob.java                     |    8 
 src/main/java/cc/mrbird/febs/rabbit/consumer/AgentConsumer.java                      |   24 
 src/main/java/cc/mrbird/febs/mall/dto/ApiXcxSaveInfoDto.java                         |   13 
 src/main/java/cc/mrbird/febs/vip/service/impl/MallVipConfigBenefitsServiceImpl.java  |   15 
 src/main/java/cc/mrbird/febs/mall/service/IApiMallMemberService.java                 |    3 
 src/main/resources/templates/febs/views/modules/vip/vipBenefits-add.html             |  489 ++++++
 src/main/java/cc/mrbird/febs/mall/vo/OrderListVo.java                                |    6 
 src/main/java/cc/mrbird/febs/common/configure/RabbitConfigure.java                   |   32 
 src/main/java/cc/mrbird/febs/mall/entity/MallMemberCoupon.java                       |    6 
 src/main/java/cc/mrbird/febs/vip/entity/MallVipConfig.java                           |   83 +
 src/main/java/cc/mrbird/febs/vip/vo/VipSettingVo.java                                |   14 
 src/main/java/cc/mrbird/febs/vip/service/IMallVipConfigBenefitsService.java          |    7 
 src/main/java/cc/mrbird/febs/rabbit/constants/QueueConstants.java                    |    3 
 src/main/java/cc/mrbird/febs/rabbit/producter/AgentProducer.java                     |   14 
 src/main/java/cc/mrbird/febs/vip/mapper/MallVipConfigMapper.java                     |   17 
 src/main/java/cc/mrbird/febs/rabbit/enumerates/RabbitQueueEnum.java                  |    6 
 src/main/java/cc/mrbird/febs/vip/service/impl/VipCommonServiceImpl.java              |  168 ++
 src/main/java/cc/mrbird/febs/vip/service/IMallVipBenefitsService.java                |   21 
 src/main/java/cc/mrbird/febs/mall/controller/AdminMallMemberController.java          |    8 
 src/main/java/cc/mrbird/febs/mall/entity/MallGoodsCoupon.java                        |    1 
 src/main/resources/mapper/modules/MallMemberMapper.xml                               |    4 
 src/main/java/cc/mrbird/febs/mall/service/IApiMallShoppingCartService.java           |    2 
 src/main/resources/mapper/modules/MallOrderInfoMapper.xml                            |    7 
 src/main/java/cc/mrbird/febs/mall/dto/AddCartDto.java                                |    4 
 src/main/java/cc/mrbird/febs/mall/controller/ApiMallShoppingCartController.java      |    4 
 src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallMemberServiceImpl.java         |  121 +
 src/main/resources/templates/febs/views/modules/mallMember/vip-level-setting.html    |   92 +
 src/main/java/cc/mrbird/febs/vip/controller/AdminMallVipConfigController.java        |   73 
 src/main/java/cc/mrbird/febs/vip/VipSettingUnAliveSettingBo.java                     |   13 
 src/main/java/cc/mrbird/febs/vip/service/impl/MallVipConfigServiceImpl.java          |  168 ++
 src/main/resources/templates/febs/views/modules/vip/vipConfig-add.html               |  256 +++
 src/main/java/cc/mrbird/febs/vip/controller/AdminMallVipBenefitsController.java      |   59 
 src/main/java/cc/mrbird/febs/vip/service/IMallVipBenefitsDetailsService.java         |    7 
 src/main/java/cc/mrbird/febs/vip/service/impl/MallVipBenefitsServiceImpl.java        |  283 +++
 src/main/java/cc/mrbird/febs/mall/entity/MallOrderInfo.java                          |    5 
 src/main/resources/templates/febs/views/modules/vip/vipConfig-list.html              |  171 ++
 src/main/java/cc/mrbird/febs/vip/mapper/MallVipBenefitsMapper.java                   |   18 
 src/test/java/cc/mrbird/febs/ProfitTest.java                                         |    6 
 src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallOrderInfoServiceImpl.java      |   20 
 src/main/resources/templates/febs/views/modules/vip/vipBenefits-list.html            |  165 ++
 src/main/java/cc/mrbird/febs/mall/vo/MoneyFlowVo.java                                |    7 
 src/main/java/cc/mrbird/febs/vip/mapper/MallVipConfigBenefitsMapper.java             |    7 
 src/main/java/cc/mrbird/febs/vip/service/IVipCommonService.java                      |    8 
 src/main/java/cc/mrbird/febs/vip/mapper/MallVipBenefitsRecordMapper.java             |    7 
 src/main/java/cc/mrbird/febs/pay/controller/XcxPayController.java                    |    1 
 src/main/java/cc/mrbird/febs/vip/entity/MallVipBenefitsDetails.java                  |   51 
 src/main/resources/mapper/modules/MallMemberCouponMapper.xml                         |    3 
 src/main/java/cc/mrbird/febs/vip/controller/ApiMallVipConfigController.java          |   57 
 src/main/resources/mapper/modules/MallShoppingCartMapper.xml                         |    2 
 src/main/java/cc/mrbird/febs/mall/controller/ApiMallMemberController.java            |    6 
 src/main/java/cc/mrbird/febs/common/enumerates/DataDictionaryEnum.java               |   12 
 src/main/resources/mapper/modules/MallVipConfigMapper.xml                            |   58 
 src/main/java/cc/mrbird/febs/mall/mapper/MallShoppingCartMapper.java                 |    2 
 src/main/java/cc/mrbird/febs/mall/service/impl/CommonService.java                    |   14 
 src/main/java/cc/mrbird/febs/vip/entity/MallVipBenefits.java                         |   55 
 src/main/java/cc/mrbird/febs/vip/controller/ViewVipConfigController.java             |  172 ++
 src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallGoodsService.java            |   22 
 src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallShoppingCartServiceImpl.java   |   53 
 src/main/resources/templates/febs/views/modules/vip/coupon-select.html               |   91 +
 src/main/resources/templates/febs/views/modules/vip/vipBenefits-edit.html            |  513 ++++++
 src/main/java/cc/mrbird/febs/mall/entity/MallShoppingCart.java                       |    2 
 src/main/resources/templates/febs/views/modules/vip/vipConfig-edit.html              |  291 +++
 src/main/java/cc/mrbird/febs/mall/service/ICommonService.java                        |    2 
 src/main/java/cc/mrbird/febs/common/enumerates/ScoreFlowTypeEnum.java                |   34 
 src/main/resources/templates/febs/views/modules/mallMember/mallMemberList.html       |   26 
 src/main/resources/templates/febs/views/modules/vip/goods-select-list.html           |  233 ++
 src/main/java/cc/mrbird/febs/mall/vo/MallGoodsDetailsVo.java                         |    3 
 src/main/resources/mapper/modules/MallGoodsMapper.xml                                |    7 
 src/main/java/cc/mrbird/febs/mall/vo/MallMemberVo.java                               |    4 
 src/main/java/cc/mrbird/febs/mall/entity/MallMember.java                             |    9 
 src/main/java/cc/mrbird/febs/vip/service/impl/MallVipBenefitsDetailsServiceImpl.java |   15 
 src/main/java/cc/mrbird/febs/mall/controller/ViewMallMemberController.java           |   13 
 src/main/java/cc/mrbird/febs/vip/service/IMallVipConfigService.java                  |   25 
 src/main/resources/templates/febs/views/modules/vip/vip-setting.html                 |  245 +++
 src/main/java/cc/mrbird/febs/vip/entity/MallVipBenefitsRecord.java                   |   28 
 src/main/resources/templates/febs/views/modules/score/goodsAdd.html                  |   69 
 src/main/java/cc/mrbird/febs/mall/vo/OrderDetailVo.java                              |    3 
 src/main/java/cc/mrbird/febs/vip/controller/ApiMallVipBenefitsController.java        |   16 
 81 files changed, 4,597 insertions(+), 71 deletions(-)

diff --git a/src/main/java/cc/mrbird/febs/common/configure/RabbitConfigure.java b/src/main/java/cc/mrbird/febs/common/configure/RabbitConfigure.java
index 32b3b5e..5c4f242 100644
--- a/src/main/java/cc/mrbird/febs/common/configure/RabbitConfigure.java
+++ b/src/main/java/cc/mrbird/febs/common/configure/RabbitConfigure.java
@@ -138,4 +138,36 @@
         return BindingBuilder.bind(orderCouponQueue()).to(orderCouponExchange()).with(RabbitQueueEnum.ORDER_COUPON.getRoute());
     }
 
+
+    @Bean
+    public DirectExchange getScoreMsgExchange() {
+        return new DirectExchange(RabbitQueueEnum.GET_SCORE_MSG.getExchange());
+    }
+
+    @Bean
+    public Queue getScoreMsgQueue() {
+        return new Queue(QueueConstants.GET_SCORE_MSG);
+    }
+
+    @Bean
+    public Binding getScoreMsgBind() {
+        return BindingBuilder.bind(getScoreMsgQueue()).to(getScoreMsgExchange()).with(RabbitQueueEnum.GET_SCORE_MSG.getRoute());
+    }
+
+
+    @Bean
+    public DirectExchange vipLevelUp() {
+        return new DirectExchange(RabbitQueueEnum.VIP_LEVEL_UP.getExchange());
+    }
+
+    @Bean
+    public Queue vipLevelUpQueue() {
+        return new Queue(QueueConstants.VIP_LEVEL_UP);
+    }
+
+    @Bean
+    public Binding vipLevelUpBind() {
+        return BindingBuilder.bind(vipLevelUpQueue()).to(vipLevelUp()).with(RabbitQueueEnum.VIP_LEVEL_UP.getRoute());
+    }
+
 }
diff --git a/src/main/java/cc/mrbird/febs/common/enumerates/DataDictionaryEnum.java b/src/main/java/cc/mrbird/febs/common/enumerates/DataDictionaryEnum.java
index 31e3827..ba1d1cd 100644
--- a/src/main/java/cc/mrbird/febs/common/enumerates/DataDictionaryEnum.java
+++ b/src/main/java/cc/mrbird/febs/common/enumerates/DataDictionaryEnum.java
@@ -59,7 +59,17 @@
     WIN_CASH("WIN_PROBABILITY", "WIN_CASH"),
     RANK_BONUS("BONUS_TYPE", "RANK_BONUS"),
     CASHOUT_SETTING("CASHOUT_SET", "CASHOUT_SETTING"),
-    INDIRECT_BONUS_SETTING("INDIRECT_BONUS_SETTING", "");
+    INDIRECT_BONUS_SETTING("INDIRECT_BONUS_SETTING", ""),
+
+    /**
+     * 会员日
+     */
+    VIP_DATE("VIP_DATE", "VIP_DATE"),
+
+    /**
+     * 会员日
+     */
+    UNALIVE_COUPON("UNALIVE_COUPON", "UNALIVE_COUPON");
 
     private String type;
 
diff --git a/src/main/java/cc/mrbird/febs/common/enumerates/ScoreFlowTypeEnum.java b/src/main/java/cc/mrbird/febs/common/enumerates/ScoreFlowTypeEnum.java
new file mode 100644
index 0000000..a65ce85
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/common/enumerates/ScoreFlowTypeEnum.java
@@ -0,0 +1,34 @@
+package cc.mrbird.febs.common.enumerates;
+
+import lombok.Getter;
+
+@Getter
+public enum ScoreFlowTypeEnum {
+
+    /**
+     *
+     */
+    PAY(1, "积分支付"),
+
+    BUY(2, "购买商品获得积分");
+
+    private final int value;
+
+    private final String desc;
+
+    ScoreFlowTypeEnum(int value, String desc) {
+        this.value = value;
+        this.desc = desc;
+    }
+
+    public static String getDescByValue(int value) {
+        for (ScoreFlowTypeEnum scoreFlowTypeEnum : values()) {
+            if (value == scoreFlowTypeEnum.getValue()) {
+                return scoreFlowTypeEnum.getDesc();
+            }
+        }
+
+        return "";
+    }
+
+}
diff --git a/src/main/java/cc/mrbird/febs/mall/controller/AdminMallMemberController.java b/src/main/java/cc/mrbird/febs/mall/controller/AdminMallMemberController.java
index e10ec84..08eda2d 100644
--- a/src/main/java/cc/mrbird/febs/mall/controller/AdminMallMemberController.java
+++ b/src/main/java/cc/mrbird/febs/mall/controller/AdminMallMemberController.java
@@ -20,6 +20,7 @@
 
 import javax.validation.Valid;
 import javax.validation.constraints.NotNull;
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
 
@@ -606,4 +607,11 @@
         return mallMemberService.salemanCoupon(mallmember);
     }
 
+    @PostMapping("vipLevelSetUpdate")
+    public FebsResponse vipLevelSetUpdate(MallMember member) {
+        member.setVipLevelTime(new Date());
+        mallMemberService.updateById(member);
+        return new FebsResponse().success().message("操作成功");
+    }
+
 }
diff --git a/src/main/java/cc/mrbird/febs/mall/controller/ApiMallMemberController.java b/src/main/java/cc/mrbird/febs/mall/controller/ApiMallMemberController.java
index a69a704..34088f0 100644
--- a/src/main/java/cc/mrbird/febs/mall/controller/ApiMallMemberController.java
+++ b/src/main/java/cc/mrbird/febs/mall/controller/ApiMallMemberController.java
@@ -269,4 +269,10 @@
         return memberService.couponDetails(id);
     }
 
+
+    @ApiOperation(value = "登录事件", notes = "登录事件")
+    @GetMapping(value = "/loginEvent")
+    public FebsResponse loginEvent() {
+        return new FebsResponse().success().data(memberService.loginEvent());
+    }
 }
diff --git a/src/main/java/cc/mrbird/febs/mall/controller/ApiMallShoppingCartController.java b/src/main/java/cc/mrbird/febs/mall/controller/ApiMallShoppingCartController.java
index dd483e3..6d4a4ee 100644
--- a/src/main/java/cc/mrbird/febs/mall/controller/ApiMallShoppingCartController.java
+++ b/src/main/java/cc/mrbird/febs/mall/controller/ApiMallShoppingCartController.java
@@ -38,8 +38,8 @@
             @ApiResponse(code = 200, message = "success", response = ShoppingCartGoodsVo.class)
     })
     @PostMapping(value = "/findCartGoodsList")
-    public FebsResponse findCartGoodsList() {
-        return new FebsResponse().success().data(mallShoppingCartService.findCartGoodsList());
+    public FebsResponse findCartGoodsList(@RequestParam(required = false, value = "type") Integer type) {
+        return new FebsResponse().success().data(mallShoppingCartService.findCartGoodsList(type));
     }
 
     @ApiOperation(value = "添加商品到购物车", notes = "添加商品到购物车")
diff --git a/src/main/java/cc/mrbird/febs/mall/controller/ViewMallMemberController.java b/src/main/java/cc/mrbird/febs/mall/controller/ViewMallMemberController.java
index 7945eee..8c4dee9 100644
--- a/src/main/java/cc/mrbird/febs/mall/controller/ViewMallMemberController.java
+++ b/src/main/java/cc/mrbird/febs/mall/controller/ViewMallMemberController.java
@@ -18,6 +18,9 @@
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;
 
+import java.util.HashMap;
+import java.util.Map;
+
 @Controller("mallMemberView")
 @RequestMapping(FebsConstant.VIEW_PREFIX + "modules/mallMember")
 @RequiredArgsConstructor
@@ -399,5 +402,15 @@
         return FebsUtil.view("modules/mallMember/couponSelect");
     }
 
+    @GetMapping("vipLevelSetting/{id}")
+    public String vipLevelSetting(@PathVariable(value = "id") String id, Model model) {
+        MallMember mallMember = mallMemberMapper.selectById(id);
+
+        Map<String, Object> data = new HashMap<>();
+        data.put("id", mallMember.getId());
+        data.put("level", mallMember.getLevel());
+        model.addAttribute("vipLevelSet", data);
+        return FebsUtil.view("modules/mallMember/vip-level-setting");
+    }
 
 }
diff --git a/src/main/java/cc/mrbird/febs/mall/dto/AddCartDto.java b/src/main/java/cc/mrbird/febs/mall/dto/AddCartDto.java
index 4e6f6ec..985e8d4 100644
--- a/src/main/java/cc/mrbird/febs/mall/dto/AddCartDto.java
+++ b/src/main/java/cc/mrbird/febs/mall/dto/AddCartDto.java
@@ -21,4 +21,8 @@
     @NotNull(message = "参数不能为空")
     @ApiModelProperty(value = "数量")
     private Integer cnt;
+
+    @NotNull(message = "类型不能为空")
+    @ApiModelProperty(value = "1-普通商品 2-积分商品")
+    private Integer type;
 }
diff --git a/src/main/java/cc/mrbird/febs/mall/dto/ApiXcxSaveInfoDto.java b/src/main/java/cc/mrbird/febs/mall/dto/ApiXcxSaveInfoDto.java
index 7922925..5f1dc66 100644
--- a/src/main/java/cc/mrbird/febs/mall/dto/ApiXcxSaveInfoDto.java
+++ b/src/main/java/cc/mrbird/febs/mall/dto/ApiXcxSaveInfoDto.java
@@ -1,8 +1,12 @@
 package cc.mrbird.febs.mall.dto;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
 
 @Data
 @ApiModel(value = "ApiXcxSaveInfoDto", description = "小程序接收用户数据")
@@ -22,4 +26,13 @@
 
     @ApiModelProperty(value = "邀请码")
     private String inviteId;
+
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    @ApiModelProperty(value = "生日")
+    private Date birthday;
+
+    @ApiModelProperty(value = "真实姓名")
+    private String realName;
+
 }
diff --git a/src/main/java/cc/mrbird/febs/mall/entity/MallGoodsCoupon.java b/src/main/java/cc/mrbird/febs/mall/entity/MallGoodsCoupon.java
index 1cffe8d..6ba6c2b 100644
--- a/src/main/java/cc/mrbird/febs/mall/entity/MallGoodsCoupon.java
+++ b/src/main/java/cc/mrbird/febs/mall/entity/MallGoodsCoupon.java
@@ -26,5 +26,4 @@
     //减免金额
     private BigDecimal realAmount;
 
-
 }
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 2f6511b..f23b060 100644
--- a/src/main/java/cc/mrbird/febs/mall/entity/MallMember.java
+++ b/src/main/java/cc/mrbird/febs/mall/entity/MallMember.java
@@ -8,6 +8,7 @@
 import lombok.Data;
 
 import java.math.BigDecimal;
+import java.util.Date;
 
 /**
  * @author wzy
@@ -165,4 +166,12 @@
     //优惠卷名称
     @TableField(exist = false)
     private Long couponId;
+
+    private Date birthday;
+
+    private String realName;
+
+    private Date lastLoginTime;
+
+    private Date vipLevelTime;
 }
diff --git a/src/main/java/cc/mrbird/febs/mall/entity/MallMemberCoupon.java b/src/main/java/cc/mrbird/febs/mall/entity/MallMemberCoupon.java
index 3143fff..c922737 100644
--- a/src/main/java/cc/mrbird/febs/mall/entity/MallMemberCoupon.java
+++ b/src/main/java/cc/mrbird/febs/mall/entity/MallMemberCoupon.java
@@ -21,4 +21,10 @@
     private Integer state;
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private Date expireTime;
+
+    /**
+     * 来源类型 1-默认 2-积分权益 3-失活会员
+     */
+    private Integer fromType;
+
 }
diff --git a/src/main/java/cc/mrbird/febs/mall/entity/MallOrderInfo.java b/src/main/java/cc/mrbird/febs/mall/entity/MallOrderInfo.java
index 56224de..5754d1c 100644
--- a/src/main/java/cc/mrbird/febs/mall/entity/MallOrderInfo.java
+++ b/src/main/java/cc/mrbird/febs/mall/entity/MallOrderInfo.java
@@ -139,4 +139,9 @@
 
     @TableField(exist = false)
     private String orderIds;
+
+    @TableField(exist = false)
+    private String expressNo;
+
+    private Integer isFree;
 }
diff --git a/src/main/java/cc/mrbird/febs/mall/entity/MallShoppingCart.java b/src/main/java/cc/mrbird/febs/mall/entity/MallShoppingCart.java
index f23fc07..6ca894c 100644
--- a/src/main/java/cc/mrbird/febs/mall/entity/MallShoppingCart.java
+++ b/src/main/java/cc/mrbird/febs/mall/entity/MallShoppingCart.java
@@ -23,6 +23,8 @@
 
     private Integer cnt;
 
+    private Integer type;
+
     @TableField(exist = false)
     private MallGoods goods;
 
diff --git a/src/main/java/cc/mrbird/febs/mall/mapper/MallShoppingCartMapper.java b/src/main/java/cc/mrbird/febs/mall/mapper/MallShoppingCartMapper.java
index c59ee88..3a646ad 100644
--- a/src/main/java/cc/mrbird/febs/mall/mapper/MallShoppingCartMapper.java
+++ b/src/main/java/cc/mrbird/febs/mall/mapper/MallShoppingCartMapper.java
@@ -12,7 +12,7 @@
  **/
 public interface MallShoppingCartMapper extends BaseMapper<MallShoppingCart> {
 
-    List<MallShoppingCart> selectCartGoodsList(@Param("memberId") Long memberId);
+    List<MallShoppingCart> selectCartGoodsList(@Param("memberId") Long memberId,@Param("type") Integer type);
 
     MallShoppingCart selectCartGoodsBySkuId(@Param("skuId") Long skuId, @Param("memberId") Long memberId);
 
diff --git a/src/main/java/cc/mrbird/febs/mall/quartz/OrderSettlementJob.java b/src/main/java/cc/mrbird/febs/mall/quartz/OrderSettlementJob.java
index d532430..7b9b5c7 100644
--- a/src/main/java/cc/mrbird/febs/mall/quartz/OrderSettlementJob.java
+++ b/src/main/java/cc/mrbird/febs/mall/quartz/OrderSettlementJob.java
@@ -11,6 +11,7 @@
 import cc.mrbird.febs.mall.service.IMallAchieveService;
 import cc.mrbird.febs.mall.service.IMallMoneyFlowService;
 import cc.mrbird.febs.mall.service.IMemberProfitService;
+import cc.mrbird.febs.rabbit.producter.AgentProducer;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
@@ -68,6 +69,9 @@
 
     @Autowired
     private IMallAchieveService mallAchieveService;
+
+    @Autowired
+    private AgentProducer agentProducer;
 
     /**
      * 普通商品结算
@@ -144,6 +148,10 @@
 //                }
 //            }
             mallOrderInfoMapper.updateOrderConfirmStatus(DateUtil.date(),DateUtil.offsetDay(new Date(), -value));
+
+            orderInfos.forEach(item -> {
+                agentProducer.sendVipLevelUp(item.getId());
+            });
         }
     }
     /**
diff --git a/src/main/java/cc/mrbird/febs/mall/service/IApiMallMemberService.java b/src/main/java/cc/mrbird/febs/mall/service/IApiMallMemberService.java
index b5f756d..9bd68b3 100644
--- a/src/main/java/cc/mrbird/febs/mall/service/IApiMallMemberService.java
+++ b/src/main/java/cc/mrbird/febs/mall/service/IApiMallMemberService.java
@@ -14,6 +14,7 @@
 import java.io.IOException;
 import java.math.BigDecimal;
 import java.util.List;
+import java.util.Map;
 
 public interface IApiMallMemberService extends IService<MallMember> {
     FebsResponse register(RegisterDto registerDto);
@@ -94,4 +95,6 @@
     FebsResponse couponDetails(Long id);
 
     FebsResponse setInvite(ApiSetInviteDto apiSetInviteDto);
+
+    Map<String, Object> loginEvent();
 }
diff --git a/src/main/java/cc/mrbird/febs/mall/service/IApiMallShoppingCartService.java b/src/main/java/cc/mrbird/febs/mall/service/IApiMallShoppingCartService.java
index dfa0668..6a11757 100644
--- a/src/main/java/cc/mrbird/febs/mall/service/IApiMallShoppingCartService.java
+++ b/src/main/java/cc/mrbird/febs/mall/service/IApiMallShoppingCartService.java
@@ -13,7 +13,7 @@
  **/
 public interface IApiMallShoppingCartService extends IService<MallShoppingCart> {
 
-    List<ShoppingCartGoodsVo> findCartGoodsList();
+    List<ShoppingCartGoodsVo> findCartGoodsList(Integer type);
 
     void addGoodsToCart(List<AddCartDto> addCartDto);
 
diff --git a/src/main/java/cc/mrbird/febs/mall/service/ICommonService.java b/src/main/java/cc/mrbird/febs/mall/service/ICommonService.java
index 74df42d..afd64f4 100644
--- a/src/main/java/cc/mrbird/febs/mall/service/ICommonService.java
+++ b/src/main/java/cc/mrbird/febs/mall/service/ICommonService.java
@@ -19,4 +19,6 @@
 
     void addDataDic(String type, String key, Object value, String description);
 
+    void addDataDic(String type, String key, Object value, String description, boolean isJson);
+
 }
diff --git a/src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallGoodsService.java b/src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallGoodsService.java
index dcb5000..8f4e174 100644
--- a/src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallGoodsService.java
+++ b/src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallGoodsService.java
@@ -73,16 +73,18 @@
             return new FebsResponse().fail().message("商品编号不能重复");
         }
         Integer carriageType = addMallGoodsDto.getCarriageType();
-        if(1 == carriageType){
-            if(ObjectUtil.isEmpty(addMallGoodsDto.getCarriageAmount())
-                    || BigDecimal.ZERO.compareTo(addMallGoodsDto.getCarriageAmount()) > 0){
-                return new FebsResponse().fail().message("固定邮费不能小于零");
-            }
-        }else{
-            Long carriageRuleId = addMallGoodsDto.getCarriageRuleId();
-            MallCarriageRule mallCarriageRule = mallCarriageRuleMapper.selectById(carriageRuleId);
-            if(ObjectUtil.isEmpty(mallCarriageRule)){
-                return new FebsResponse().fail().message("邮费模板不能为空");
+        if (addMallGoodsDto.getGoodsType() == 1) {
+            if (1 == carriageType) {
+                if (ObjectUtil.isEmpty(addMallGoodsDto.getCarriageAmount())
+                        || BigDecimal.ZERO.compareTo(addMallGoodsDto.getCarriageAmount()) > 0) {
+                    return new FebsResponse().fail().message("固定邮费不能小于零");
+                }
+            } else {
+                Long carriageRuleId = addMallGoodsDto.getCarriageRuleId();
+                MallCarriageRule mallCarriageRule = mallCarriageRuleMapper.selectById(carriageRuleId);
+                if (ObjectUtil.isEmpty(mallCarriageRule)) {
+                    return new FebsResponse().fail().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 89b97fe..059ea38 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
@@ -1,10 +1,7 @@
 package cc.mrbird.febs.mall.service.impl;
 
 import cc.mrbird.febs.common.entity.FebsResponse;
-import cc.mrbird.febs.common.enumerates.AgentLevelEnum;
-import cc.mrbird.febs.common.enumerates.DataDictionaryEnum;
-import cc.mrbird.febs.common.enumerates.FlowTypeEnum;
-import cc.mrbird.febs.common.enumerates.MoneyFlowTypeEnum;
+import cc.mrbird.febs.common.enumerates.*;
 import cc.mrbird.febs.common.exception.FebsException;
 import cc.mrbird.febs.common.properties.XcxProperties;
 import cc.mrbird.febs.common.utils.*;
@@ -17,8 +14,12 @@
 import cc.mrbird.febs.mall.vo.*;
 import cc.mrbird.febs.pay.model.BrandWCPayRequestData;
 import cc.mrbird.febs.pay.service.IXcxPayService;
+import cc.mrbird.febs.vip.VipSettingUnAliveSettingBo;
+import cc.mrbird.febs.vip.entity.MallVipConfig;
+import cc.mrbird.febs.vip.mapper.MallVipConfigMapper;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DateUnit;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.IdUtil;
 import cn.hutool.core.util.ObjectUtil;
@@ -44,6 +45,7 @@
 import java.io.IOException;
 import java.math.BigDecimal;
 import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * @author wzy
@@ -76,6 +78,8 @@
     private final MallGoodsCouponMapper mallGoodsCouponMapper;
     private final MallMemberCouponMapper mallMemberCouponMapper;
     private final MallGoodsMapper mallGoodsMapper;
+
+    private final MallVipConfigMapper mallVipConfigMapper;
 
 
     @Value("${spring.profiles.active}")
@@ -129,7 +133,6 @@
         mallMember.setName(registerDto.getName());
         mallMember.setAccountStatus(MallMember.ACCOUNT_STATUS_ENABLE);
         mallMember.setAccountType(MallMember.ACCOUNT_TYPE_NORMAL);
-        mallMember.setLevel(AgentLevelEnum.ZERO_LEVEL.name());
         mallMember.setSex("男");
         mallMember.setBindPhone(registerDto.getAccount());
 
@@ -285,9 +288,13 @@
         mallMemberVo.setChildCnt(CollUtil.isNotEmpty(mallMembers) ? mallMembers.size() : 0);
 
         MallMemberWallet wallet = mallMemberWalletMapper.selectWalletByMemberId(mallMemberVo.getId());
+
+        MallVipConfig mallVipConfig = mallVipConfigMapper.selectVipConfigByCode(mallMember.getLevel());
+
+        mallMemberVo.setVipInfo(mallVipConfig);
         mallMemberVo.setBalance(wallet.getBalance());
 //        mallMemberVo.setScore(wallet.getScore());
-//        mallMemberVo.setPrizeScore(wallet.getPrizeScore());
+        mallMemberVo.setPrizeScore(wallet.getPrizeScore());
 //        mallMemberVo.setTotalCost(mallOrderInfoMapper.selectTotalAmount(id));
         return new FebsResponse().success().data(mallMemberVo);
     }
@@ -304,7 +311,7 @@
             }
         }
 
-        List<MallShoppingCart> carts = mallShoppingCartMapper.selectCartGoodsList(id);
+        List<MallShoppingCart> carts = mallShoppingCartMapper.selectCartGoodsList(id, 1);
         Map<String, Object> result = new HashMap<>();
         result.put("order", orderCnt);
         result.put("carts", carts.size());
@@ -377,6 +384,12 @@
         Long id = LoginUserUtil.getLoginUser().getId();
         moneyFlowDto.setMemberId(id);
         IPage<MoneyFlowVo> pages = mallMoneyFlowMapper.selectApiMoneyFlowInPage(page, moneyFlowDto);
+
+        if (moneyFlowDto.getFlowType() == 3) {
+            pages.getRecords().forEach(item -> {
+                item.setDescription(ScoreFlowTypeEnum.getDescByValue(item.getType()));
+            });
+        }
         return new FebsResponse().success().data(pages);
     }
 
@@ -609,7 +622,6 @@
                     mallMember = new MallMember();
                     mallMember.setAccountStatus(MallMember.ACCOUNT_STATUS_ENABLE);
                     mallMember.setAccountType(MallMember.ACCOUNT_TYPE_NORMAL);
-                    mallMember.setLevel(AgentLevelEnum.ZERO_LEVEL.name());
                     mallMember.setOpenId(openId);
                     mallMember.setSessionKey(sessionKey);
 
@@ -703,7 +715,22 @@
         if(StrUtil.isNotEmpty(avatarUrl)){
             mallMember.setAvatar(avatarUrl);
         }
-//        mallMember.setSex(1 == apiXcxSaveInfoDto.getGender() ? "女" : "男");
+
+        if (StrUtil.isNotBlank(apiXcxSaveInfoDto.getRealName())) {
+            mallMember.setRealName(apiXcxSaveInfoDto.getRealName());
+        }
+
+        if (apiXcxSaveInfoDto.getBirthday() != null) {
+            mallMember.setBirthday(apiXcxSaveInfoDto.getBirthday());
+        }
+
+        List<MallVipConfig> configs = mallVipConfigMapper.selectVipConfigList();
+        if (StrUtil.isBlank(mallMember.getLevel()) && CollUtil.isNotEmpty(configs)) {
+            MallVipConfig mallVipConfig = configs.get(0);
+            mallMember.setLevel(mallVipConfig.getCode());
+        }
+
+        mallMember.setSex(1 == apiXcxSaveInfoDto.getGender() ? "女" : "男");
         this.baseMapper.updateById(mallMember);
         return new FebsResponse().success();
     }
@@ -723,7 +750,6 @@
                     mallMember.setPhone(phone);
                     mallMember.setAccountStatus(MallMember.ACCOUNT_STATUS_ENABLE);
                     mallMember.setAccountType(MallMember.ACCOUNT_TYPE_NORMAL);
-                    mallMember.setLevel(AgentLevelEnum.ZERO_LEVEL.name());
                     this.baseMapper.insert(mallMember);
 
                     String inviteId = ShareCodeUtil.toSerialCode(mallMember.getId());
@@ -1052,4 +1078,79 @@
         String wechatLoginUrl =xcxProperties.getWecharLoginUrl();
         return String.format(wechatLoginUrl, xcxProperties.getXcxAppid(), xcxProperties.getXcxSecret(), code);
     }
+
+    @Override
+    public Map<String, Object>  loginEvent() {
+        MallMember loginUser = LoginUserUtil.getLoginUser();
+
+        MallMember member = this.baseMapper.selectById(loginUser.getId());
+
+        MallMember mallMember = new MallMember();
+        mallMember.setId(member.getId());
+        mallMember.setLastLoginTime(new Date());
+        this.baseMapper.updateById(mallMember);
+
+        DataDictionaryCustom dic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(DataDictionaryEnum.UNALIVE_COUPON.getType(), DataDictionaryEnum.UNALIVE_COUPON.getCode());
+        if (dic == null || StrUtil.isBlank(dic.getValue())) {
+            return new HashMap<>();
+        }
+
+        Date today = new Date();
+        Date lastLoginTime = member.getLastLoginTime();
+        if (lastLoginTime == null) {
+            lastLoginTime = new Date();
+        }
+
+        long days = DateUtil.between(DateUtil.endOfDay(lastLoginTime), DateUtil.endOfDay(today), DateUnit.DAY);
+
+        List<VipSettingUnAliveSettingBo> list = JSONObject.parseArray(dic.getValue(), VipSettingUnAliveSettingBo.class);
+        List<Long> couponIds = list.stream().filter(item -> {
+            return item.getDay() <= days && item.getCouponId() != null;
+        }).map(VipSettingUnAliveSettingBo::getCouponId).collect(Collectors.toList());
+        if (CollUtil.isEmpty(couponIds)) {
+            return new HashMap<>();
+        }
+
+        LambdaQueryWrapper<MallGoodsCoupon> query = new LambdaQueryWrapper<>();
+        query.in(MallGoodsCoupon::getId, couponIds)
+                .eq(MallGoodsCoupon::getState, 2);
+        List<MallGoodsCoupon> coupons = mallGoodsCouponMapper.selectList(query);
+
+        LambdaQueryWrapper<MallMemberCoupon> memberCouponQuery = new LambdaQueryWrapper<>();
+        memberCouponQuery.in(MallMemberCoupon::getCouponId, couponIds)
+                        .eq(MallMemberCoupon::getMemberId, member.getId())
+                        .eq(MallMemberCoupon::getFromType, 3)
+                        .ge(MallMemberCoupon::getCreatedTime, DateUtil.beginOfDay(new Date()))
+                        .le(MallMemberCoupon::getCreatedTime, DateUtil.endOfDay(new Date()));
+        List<MallMemberCoupon> mallMemberCoupons = mallMemberCouponMapper.selectList(memberCouponQuery);
+        if (CollUtil.isNotEmpty(mallMemberCoupons)) {
+            Map<Long, MallMemberCoupon> map = mallMemberCoupons.stream().collect(Collectors.toMap(MallMemberCoupon::getCouponId, MallMemberCoupon -> MallMemberCoupon));
+            coupons = coupons.stream().filter(item -> {
+                return map.get(item.getId()) == null;
+            }).collect(Collectors.toList());
+        }
+
+        if (CollUtil.isEmpty(coupons)) {
+            return new HashMap<>();
+        }
+
+        coupons.forEach(item -> {
+            MallMemberCoupon memberCoupon = new MallMemberCoupon();
+            memberCoupon.setCouponId(item.getId());
+            memberCoupon.setCouponName(item.getName());
+            memberCoupon.setInviteId(member.getInviteId());
+            memberCoupon.setCouponUuid(IdUtil.simpleUUID());
+            memberCoupon.setState(1);
+            memberCoupon.setFromType(3);
+            memberCoupon.setExpireTime(DateUtil.offsetDay(DateUtil.date(), item.getExpireDay()));
+            memberCoupon.setMemberId(member.getId());
+            mallMemberCouponMapper.insert(memberCoupon);
+        });
+
+        Map<String, Object> result = new HashMap<>();
+        result.put("coupon", coupons);
+        return result;
+    }
+
+
 }
diff --git a/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallOrderInfoServiceImpl.java b/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallOrderInfoServiceImpl.java
index 7b70a02..e7aa9be 100644
--- a/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallOrderInfoServiceImpl.java
+++ b/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallOrderInfoServiceImpl.java
@@ -23,6 +23,8 @@
 import cc.mrbird.febs.pay.service.IXcxPayService;
 import cc.mrbird.febs.pay.util.WeixinServiceUtil;
 import cc.mrbird.febs.rabbit.producter.AgentProducer;
+import cc.mrbird.febs.vip.service.IMallVipConfigBenefitsService;
+import cc.mrbird.febs.vip.service.IMallVipConfigService;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.date.DateUnit;
 import cn.hutool.core.date.DateUtil;
@@ -32,6 +34,7 @@
 import cn.hutool.json.JSONArray;
 import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -86,6 +89,8 @@
     private final MallMemberCouponMapper mallMemberCouponMapper;
     private final MallGoodsCouponMapper mallGoodsCouponMapper;
     private final CouponGoodsMapper couponGoodsMapper;
+
+    private final IMallVipConfigService mallVipConfigService;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -145,6 +150,12 @@
                     orderItem.setSkuImage(mallGoods.getThumb());
                     orderItem.setState(1);
 
+                    if (addOrderDto.getType() == 1) {
+                        LambdaQueryWrapper<MallShoppingCart> delQuery = new LambdaQueryWrapper<>();
+                        delQuery.eq(MallShoppingCart::getGoodsId, item.getSkuId())
+                                .eq(MallShoppingCart::getMemberId, member.getId());
+                        mallShoppingCartMapper.delete(delQuery);
+                    }
                     total = total.add(amount);
                 } else {
                     MallGoodsSku sku = mallGoodsSkuMapper.selectSkuInfoById(item.getSkuId());
@@ -314,7 +325,11 @@
         orderInfo.setCancelType(MallOrderInfo.CANCEL_BY_SELF);
         this.baseMapper.updateById(orderInfo);
 
-
+        if (orderInfo.getOrderType() == 2) {
+//            mallMoneyFlowService.addMoneyFlow(member.getId(), orderInfo.getAmount(), MoneyFlowTypeEnum.REFUND.getValue(), orderInfo.getOrderNo(),  FlowTypeEnum.PRIZE_SCORE.getValue());
+//            memberWalletService.add(orderInfo.getAmount(), member.getId(), "prizeScore");
+            return;
+        }
 
         List<MallOrderItem> mallOrderItemList = mallOrderItemMapper.selectListByOrderId(orderInfo.getId());
         if(CollUtil.isNotEmpty(mallOrderItemList)){
@@ -451,7 +466,7 @@
                 orderInfo.setPayTime(new Date());
                 orderInfo.setPayResult("1");
 
-                mallMoneyFlowService.addMoneyFlow(member.getId(), orderInfo.getAmount().negate(), MoneyFlowTypeEnum.PAY.getValue(), orderInfo.getOrderNo(),  FlowTypeEnum.PRIZE_SCORE.getValue());
+                mallMoneyFlowService.addMoneyFlow(member.getId(), orderInfo.getAmount().negate(), ScoreFlowTypeEnum.PAY.getValue(), orderInfo.getOrderNo(),  FlowTypeEnum.PRIZE_SCORE.getValue(), null, 2);
                 break;
             default:
 
@@ -567,6 +582,7 @@
         orderInfo.setReceivingTime(new Date());
         this.baseMapper.updateById(orderInfo);
 
+        agentProducer.sendGetScoreMsg(orderInfo.getId());
         //生成一条团长提成记录
 //        Long orderInfoId = orderInfo.getId();
 //        List<MallOrderItem> mallOrderItemList = mallOrderItemMapper.selectListByOrderId(orderInfoId);
diff --git a/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallShoppingCartServiceImpl.java b/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallShoppingCartServiceImpl.java
index 73f3c5a..2629f7b 100644
--- a/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallShoppingCartServiceImpl.java
+++ b/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallShoppingCartServiceImpl.java
@@ -1,15 +1,19 @@
 package cc.mrbird.febs.mall.service.impl;
 
 import cc.mrbird.febs.common.exception.FebsException;
+import cc.mrbird.febs.common.exception.GeneratorException;
 import cc.mrbird.febs.common.utils.LoginUserUtil;
 import cc.mrbird.febs.mall.conversion.MallShoppingCartConversion;
 import cc.mrbird.febs.mall.dto.AddCartDto;
+import cc.mrbird.febs.mall.entity.MallGoods;
 import cc.mrbird.febs.mall.entity.MallGoodsSku;
 import cc.mrbird.febs.mall.entity.MallShoppingCart;
+import cc.mrbird.febs.mall.mapper.MallGoodsMapper;
 import cc.mrbird.febs.mall.mapper.MallGoodsSkuMapper;
 import cc.mrbird.febs.mall.mapper.MallShoppingCartMapper;
 import cc.mrbird.febs.mall.service.IApiMallShoppingCartService;
 import cc.mrbird.febs.mall.vo.ShoppingCartGoodsVo;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -28,11 +32,15 @@
 public class ApiMallShoppingCartServiceImpl extends ServiceImpl<MallShoppingCartMapper, MallShoppingCart> implements IApiMallShoppingCartService {
 
     private final MallGoodsSkuMapper mallGoodsSkuMapper;
+    private final MallGoodsMapper mallGoodsMapper;
 
     @Override
-    public List<ShoppingCartGoodsVo> findCartGoodsList() {
+    public List<ShoppingCartGoodsVo> findCartGoodsList(Integer type) {
+        if (type == null) {
+            type = 1;
+        }
         Long memberId = LoginUserUtil.getLoginUser().getId();
-        List<MallShoppingCart> carts = this.baseMapper.selectCartGoodsList(memberId);
+        List<MallShoppingCart> carts = this.baseMapper.selectCartGoodsList(memberId, type);
 
         return MallShoppingCartConversion.INSTANCE.entityListToVoList(carts);
     }
@@ -40,22 +48,47 @@
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void addGoodsToCart(List<AddCartDto> addCartDtoList) {
+        Long memberId = LoginUserUtil.getLoginUser().getId();
         for (AddCartDto addCartDto : addCartDtoList) {
-            MallGoodsSku sku = mallGoodsSkuMapper.selectById(addCartDto.getSkuId());
+            Long goodsId = null;
+            Long skuId = null;
+            Long styleId = null;
+            MallShoppingCart cartGoods = null;
+            if (addCartDto.getType() == 1) {
+                MallGoodsSku sku = mallGoodsSkuMapper.selectById(addCartDto.getSkuId());
 
-            if (sku == null) {
-                throw new FebsException("sku不存在");
+                if (sku == null) {
+                    throw new FebsException("sku不存在");
+                }
+
+                goodsId = sku.getGoodsId();
+                skuId = sku.getId();
+                styleId = sku.getStyleId();
+
+                cartGoods = this.baseMapper.selectCartGoodsBySkuId(addCartDto.getSkuId(), memberId);
+            } else {
+                MallGoods mallGoods = mallGoodsMapper.selectById(addCartDto.getSkuId());
+                if (mallGoods == null) {
+                    throw new FebsException("积分商品不存在");
+                }
+
+                goodsId = mallGoods.getId();
+
+                LambdaQueryWrapper<MallShoppingCart> cartQuery = new LambdaQueryWrapper<>();
+                cartQuery.eq(MallShoppingCart::getGoodsId, goodsId)
+                        .eq(MallShoppingCart::getMemberId, memberId)
+                        .last("limit 1");
+                cartGoods = this.baseMapper.selectOne(cartQuery);
             }
-            Long memberId = LoginUserUtil.getLoginUser().getId();
 
-            MallShoppingCart cartGoods = this.baseMapper.selectCartGoodsBySkuId(sku.getId(), memberId);
             if (cartGoods == null) {
                 cartGoods = new MallShoppingCart();
-                cartGoods.setGoodsId(sku.getGoodsId());
-                cartGoods.setSkuId(sku.getId());
-                cartGoods.setStyleId(sku.getStyleId());
+                cartGoods.setGoodsId(goodsId);
+                cartGoods.setSkuId(skuId);
+                cartGoods.setStyleId(styleId);
                 cartGoods.setCnt(addCartDto.getCnt());
                 cartGoods.setMemberId(memberId);
+                cartGoods.setType(addCartDto.getType());
 
                 this.baseMapper.insert(cartGoods);
             } else {
diff --git a/src/main/java/cc/mrbird/febs/mall/service/impl/CommonService.java b/src/main/java/cc/mrbird/febs/mall/service/impl/CommonService.java
index 6f2fe47..4f4cd2f 100644
--- a/src/main/java/cc/mrbird/febs/mall/service/impl/CommonService.java
+++ b/src/main/java/cc/mrbird/febs/mall/service/impl/CommonService.java
@@ -57,9 +57,19 @@
 
     @Override
     public void addDataDic(String type, String code, Object value, String description) {
-        DataDictionaryCustom dic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(type, code);
+        addDataDic(type, code, value, description, true);
+    }
 
-        String data = JSONObject.toJSONString(value);
+    @Override
+    public void addDataDic(String type, String code, Object value, String description, boolean isJson) {
+        DataDictionaryCustom dic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(type, code);
+        String data = null;
+        if (isJson) {
+            data = JSONObject.toJSONString(value);
+        } else {
+            data = (String) value;
+        }
+
         if (dic != null) {
             dic.setValue(data);
             dataDictionaryCustomMapper.updateById(dic);
diff --git a/src/main/java/cc/mrbird/febs/mall/vo/MallGoodsDetailsVo.java b/src/main/java/cc/mrbird/febs/mall/vo/MallGoodsDetailsVo.java
index 3566603..378526e 100644
--- a/src/main/java/cc/mrbird/febs/mall/vo/MallGoodsDetailsVo.java
+++ b/src/main/java/cc/mrbird/febs/mall/vo/MallGoodsDetailsVo.java
@@ -18,6 +18,9 @@
     @ApiModelProperty(value = "id")
     private Long id;
 
+    @ApiModelProperty(value = "商品主图")
+    private String thumb;
+
     @ApiModelProperty(value = "商品编号")
     private String goodsNo;
 
diff --git a/src/main/java/cc/mrbird/febs/mall/vo/MallMemberVo.java b/src/main/java/cc/mrbird/febs/mall/vo/MallMemberVo.java
index 6665c0a..59c4080 100644
--- a/src/main/java/cc/mrbird/febs/mall/vo/MallMemberVo.java
+++ b/src/main/java/cc/mrbird/febs/mall/vo/MallMemberVo.java
@@ -1,5 +1,6 @@
 package cc.mrbird.febs.mall.vo;
 
+import cc.mrbird.febs.vip.entity.MallVipConfig;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
@@ -95,4 +96,7 @@
 
     @ApiModelProperty(value = "是否是推销员")
     private Integer isSale;
+
+    @ApiModelProperty(value = "会员信息")
+    private MallVipConfig vipInfo;
 }
diff --git a/src/main/java/cc/mrbird/febs/mall/vo/MoneyFlowVo.java b/src/main/java/cc/mrbird/febs/mall/vo/MoneyFlowVo.java
index 178599f..1e8b998 100644
--- a/src/main/java/cc/mrbird/febs/mall/vo/MoneyFlowVo.java
+++ b/src/main/java/cc/mrbird/febs/mall/vo/MoneyFlowVo.java
@@ -37,4 +37,11 @@
     @ApiModelProperty(value = "时间")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private Date createdTime;
+
+
+    @ApiModelProperty(value = "描述")
+    private String description;
+
+    @ApiModelProperty(value = "备注")
+    private String remark;
 }
diff --git a/src/main/java/cc/mrbird/febs/mall/vo/OrderDetailVo.java b/src/main/java/cc/mrbird/febs/mall/vo/OrderDetailVo.java
index 012f7be..538eb5d 100644
--- a/src/main/java/cc/mrbird/febs/mall/vo/OrderDetailVo.java
+++ b/src/main/java/cc/mrbird/febs/mall/vo/OrderDetailVo.java
@@ -124,5 +124,8 @@
     private Integer deliveryState;
     @ApiModelProperty(value = "是否送货上门  1:是 2:否")
     private Integer isHome;
+
+    @ApiModelProperty(value = "是否赠送 1-是 2-否")
+    private Integer isFree;
 }
 
diff --git a/src/main/java/cc/mrbird/febs/mall/vo/OrderListVo.java b/src/main/java/cc/mrbird/febs/mall/vo/OrderListVo.java
index 335a4be..a1a4923 100644
--- a/src/main/java/cc/mrbird/febs/mall/vo/OrderListVo.java
+++ b/src/main/java/cc/mrbird/febs/mall/vo/OrderListVo.java
@@ -57,4 +57,10 @@
 
     @ApiModelProperty(value = "是否送货上门  1:是 2:否")
     private Integer isHome;
+
+    @ApiModelProperty(value = "快递单号")
+    private String expressNo;
+
+    @ApiModelProperty(value = "是否赠送 1-是 2-否")
+    private Integer isFree;
 }
diff --git a/src/main/java/cc/mrbird/febs/pay/controller/XcxPayController.java b/src/main/java/cc/mrbird/febs/pay/controller/XcxPayController.java
index 0d95241..5629e7b 100644
--- a/src/main/java/cc/mrbird/febs/pay/controller/XcxPayController.java
+++ b/src/main/java/cc/mrbird/febs/pay/controller/XcxPayController.java
@@ -327,6 +327,7 @@
                             mallOrderInfoMapper.updateById(order);
 
                             agentProducer.sendOrderCoupon(order.getId());
+//                            agentProducer.sendGetScoreMsg(order.getId());
 
                             mallMoneyFlowService.addMoneyFlow(
                                     order.getMemberId(),
diff --git a/src/main/java/cc/mrbird/febs/rabbit/constants/QueueConstants.java b/src/main/java/cc/mrbird/febs/rabbit/constants/QueueConstants.java
index a473a08..1de63b7 100644
--- a/src/main/java/cc/mrbird/febs/rabbit/constants/QueueConstants.java
+++ b/src/main/java/cc/mrbird/febs/rabbit/constants/QueueConstants.java
@@ -12,4 +12,7 @@
     public static final String ORDER_RETURN_MONEY = "queue_order_return_money_qay";
 
     public static final String ORDER_COUPON = "queue_order_coupon";
+
+    public static final String GET_SCORE_MSG = "queue_get_score_msg";
+    public static final String VIP_LEVEL_UP = "queue_vip_level_up";
 }
diff --git a/src/main/java/cc/mrbird/febs/rabbit/consumer/AgentConsumer.java b/src/main/java/cc/mrbird/febs/rabbit/consumer/AgentConsumer.java
index 9fe3dea..366ac20 100644
--- a/src/main/java/cc/mrbird/febs/rabbit/consumer/AgentConsumer.java
+++ b/src/main/java/cc/mrbird/febs/rabbit/consumer/AgentConsumer.java
@@ -5,6 +5,7 @@
 import cc.mrbird.febs.mall.service.IMemberProfitService;
 import cc.mrbird.febs.rabbit.constants.QueueConstants;
 import cc.mrbird.febs.rabbit.enumerates.RabbitQueueEnum;
+import cc.mrbird.febs.vip.service.IVipCommonService;
 import com.rabbitmq.client.Channel;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.amqp.core.Message;
@@ -82,4 +83,27 @@
             log.error("使用优惠卷异常:", e);
         }
     }
+
+    @Autowired
+    private IVipCommonService vipCommonService;
+
+    @RabbitListener(queues = QueueConstants.GET_SCORE_MSG)
+    public void getScoreMsg(Long orderId) {
+        log.info("收到积分消息:{}", orderId);
+        try {
+            vipCommonService.getScore(orderId);
+        } catch (Exception e) {
+            log.error("获取积分消息异常", e);
+        }
+    }
+
+    @RabbitListener(queues = QueueConstants.VIP_LEVEL_UP)
+    public void vipLevelUp(Long orderId) {
+        log.info("收到会员升级消息:{}", orderId);
+        try {
+            vipCommonService.levelUp(orderId);
+        } catch (Exception e) {
+            log.error("会员升级消息异常", e);
+        }
+    }
 }
diff --git a/src/main/java/cc/mrbird/febs/rabbit/enumerates/RabbitQueueEnum.java b/src/main/java/cc/mrbird/febs/rabbit/enumerates/RabbitQueueEnum.java
index 87376dd..f567b9c 100644
--- a/src/main/java/cc/mrbird/febs/rabbit/enumerates/RabbitQueueEnum.java
+++ b/src/main/java/cc/mrbird/febs/rabbit/enumerates/RabbitQueueEnum.java
@@ -15,7 +15,11 @@
 
     ORDER_RETURN_MONEY("exchange_order_return_money_qay", "route_key_order_return_money_qay", "queue_order_return_money_qay"),
 
-    ORDER_COUPON("exchange_order_coupon", "route_key_order_coupon", QueueConstants.ORDER_COUPON);
+    ORDER_COUPON("exchange_order_coupon", "route_key_order_coupon", QueueConstants.ORDER_COUPON),
+
+    GET_SCORE_MSG("exchange_get_score_msg", "route_key_get_score_msg", QueueConstants.GET_SCORE_MSG),
+
+    VIP_LEVEL_UP("exchange_vip_level_up", "route_key_vip_level_up", QueueConstants.VIP_LEVEL_UP);
 
     private String exchange;
 
diff --git a/src/main/java/cc/mrbird/febs/rabbit/producter/AgentProducer.java b/src/main/java/cc/mrbird/febs/rabbit/producter/AgentProducer.java
index 281c171..501fdbb 100644
--- a/src/main/java/cc/mrbird/febs/rabbit/producter/AgentProducer.java
+++ b/src/main/java/cc/mrbird/febs/rabbit/producter/AgentProducer.java
@@ -83,4 +83,18 @@
         CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
         rabbitTemplate.convertAndSend(RabbitQueueEnum.ORDER_COUPON.getExchange(), RabbitQueueEnum.ORDER_COUPON.getRoute(), id, correlationData);
     }
+
+    public void sendGetScoreMsg(Long orderId) {
+        log.info("发送获得积分消息:{}", orderId);
+
+        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
+        rabbitTemplate.convertAndSend(RabbitQueueEnum.GET_SCORE_MSG.getExchange(), RabbitQueueEnum.GET_SCORE_MSG.getRoute(), orderId, correlationData);
+    }
+
+    public void sendVipLevelUp(Long orderId) {
+        log.info("发送会员升级消息:{}", orderId);
+
+        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
+        rabbitTemplate.convertAndSend(RabbitQueueEnum.VIP_LEVEL_UP.getExchange(), RabbitQueueEnum.VIP_LEVEL_UP.getRoute(), orderId, correlationData);
+    }
 }
diff --git a/src/main/java/cc/mrbird/febs/vip/VipSettingUnAliveSettingBo.java b/src/main/java/cc/mrbird/febs/vip/VipSettingUnAliveSettingBo.java
new file mode 100644
index 0000000..cbe93bf
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/vip/VipSettingUnAliveSettingBo.java
@@ -0,0 +1,13 @@
+package cc.mrbird.febs.vip;
+
+import lombok.Data;
+
+@Data
+public class VipSettingUnAliveSettingBo {
+
+    private int day;
+
+    private Long couponId;
+
+    private String couponName;
+}
diff --git a/src/main/java/cc/mrbird/febs/vip/controller/AdminMallVipBenefitsController.java b/src/main/java/cc/mrbird/febs/vip/controller/AdminMallVipBenefitsController.java
new file mode 100644
index 0000000..42e8107
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/vip/controller/AdminMallVipBenefitsController.java
@@ -0,0 +1,59 @@
+package cc.mrbird.febs.vip.controller;
+
+
+import cc.mrbird.febs.common.controller.BaseController;
+import cc.mrbird.febs.common.entity.FebsResponse;
+import cc.mrbird.febs.common.entity.QueryRequest;
+import cc.mrbird.febs.vip.entity.MallVipBenefits;
+import cc.mrbird.febs.vip.service.IMallVipBenefitsService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Map;
+
+/**
+ * 会员权益接口类
+ */
+@Slf4j
+@Validated
+@RestController
+@RequiredArgsConstructor
+@RequestMapping(value = "/admin/vip/benefits")
+public class AdminMallVipBenefitsController extends BaseController {
+
+    private final IMallVipBenefitsService mallVipBenefitsService;
+
+    @GetMapping("/list")
+    public FebsResponse list(QueryRequest request) {
+        Map<String, Object> data = getDataTable(mallVipBenefitsService.vipBenefitsListInPage(request));
+        return new FebsResponse().success().data(data);
+    }
+
+    @GetMapping("/getById/{id}")
+    public FebsResponse getById(@PathVariable("id") Long id) {
+        return new FebsResponse().success().data(mallVipBenefitsService.findVipBenefitsById(id));
+    }
+
+    @PostMapping("/addOrEditBenefits")
+    public FebsResponse addOrEditBenefits(@RequestBody MallVipBenefits mallVipBenefits) {
+        if (mallVipBenefits.getId() == null) {
+            this.mallVipBenefitsService.addVipBenefits(mallVipBenefits);
+        } else {
+            this.mallVipBenefitsService.editVipBenefits(mallVipBenefits);
+        }
+        return new FebsResponse().success();
+    }
+
+    @GetMapping("/delBenefits/{id}")
+    public FebsResponse delBenefits(@PathVariable("id") Long id) {
+        this.mallVipBenefitsService.delVipBenefits(id);
+        return new FebsResponse().success();
+    }
+
+    @GetMapping("/findAllBenefits")
+    public FebsResponse findAllBenefits() {
+        return new FebsResponse().success().data(mallVipBenefitsService.list());
+    }
+}
diff --git a/src/main/java/cc/mrbird/febs/vip/controller/AdminMallVipConfigController.java b/src/main/java/cc/mrbird/febs/vip/controller/AdminMallVipConfigController.java
new file mode 100644
index 0000000..407ee95
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/vip/controller/AdminMallVipConfigController.java
@@ -0,0 +1,73 @@
+package cc.mrbird.febs.vip.controller;
+
+import cc.mrbird.febs.common.controller.BaseController;
+import cc.mrbird.febs.common.entity.FebsResponse;
+import cc.mrbird.febs.common.entity.QueryRequest;
+import cc.mrbird.febs.common.enumerates.DataDictionaryEnum;
+import cc.mrbird.febs.mall.service.impl.CommonService;
+import cc.mrbird.febs.vip.entity.MallVipConfig;
+import cc.mrbird.febs.vip.service.IMallVipConfigService;
+import cc.mrbird.febs.vip.vo.VipSettingVo;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 会员配置接口类
+ */
+@Slf4j
+@Validated
+@RestController
+@RequiredArgsConstructor
+@RequestMapping(value = "/admin/vip/config")
+public class AdminMallVipConfigController extends BaseController {
+
+    private final IMallVipConfigService mallVipConfigService;
+    private final CommonService commonService;
+
+    @GetMapping(value = "/list")
+    public FebsResponse list(QueryRequest request) {
+        return new FebsResponse().success().data(getDataTable(mallVipConfigService.vipConfigList(request)));
+    }
+
+
+    @PostMapping(value = "/addOrEdit")
+    public FebsResponse addOrEdit(@RequestBody MallVipConfig config) {
+        if (config.getType() == 1) {
+            config.setTimes(null);
+            config.setAmount(null);
+        } else {
+            config.setTargetId(null);
+        }
+
+        if (config.getId() == null) {
+            mallVipConfigService.addVipConfig(config);
+        } else {
+            mallVipConfigService.editVipConfig(config);
+        }
+        return new FebsResponse().success().message("操作成功");
+    }
+
+    @GetMapping(value = "/del/{id}")
+    public FebsResponse del(@PathVariable("id") Long id) {
+        mallVipConfigService.delVipConfig(id);
+        return new FebsResponse().success().message("操作成功");
+    }
+
+    @PostMapping(value = "/vipSetting")
+    public FebsResponse vipSetting(@RequestBody VipSettingVo vipSettingVo) {
+        commonService.addDataDic(DataDictionaryEnum.VIP_DATE.getType(), DataDictionaryEnum.VIP_DATE.getCode(), vipSettingVo.getVipDate(), null, false);
+
+        commonService.addDataDic(DataDictionaryEnum.UNALIVE_COUPON.getType(), DataDictionaryEnum.UNALIVE_COUPON.getCode(), vipSettingVo.getItems(), "失活会员优惠券配置", true);
+        return new FebsResponse().success();
+    }
+
+    @GetMapping(value = "/allList")
+    public FebsResponse allList() {
+        return new FebsResponse().success().data(mallVipConfigService.list());
+    }
+}
diff --git a/src/main/java/cc/mrbird/febs/vip/controller/ApiMallVipBenefitsController.java b/src/main/java/cc/mrbird/febs/vip/controller/ApiMallVipBenefitsController.java
new file mode 100644
index 0000000..1b1f87b
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/vip/controller/ApiMallVipBenefitsController.java
@@ -0,0 +1,16 @@
+package cc.mrbird.febs.vip.controller;
+
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@Slf4j
+@Validated
+@RestController
+@RequiredArgsConstructor
+@RequestMapping(value = "/api/vip/benefits")
+public class ApiMallVipBenefitsController {
+}
diff --git a/src/main/java/cc/mrbird/febs/vip/controller/ApiMallVipConfigController.java b/src/main/java/cc/mrbird/febs/vip/controller/ApiMallVipConfigController.java
new file mode 100644
index 0000000..60a38ac
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/vip/controller/ApiMallVipConfigController.java
@@ -0,0 +1,57 @@
+package cc.mrbird.febs.vip.controller;
+
+
+import cc.mrbird.febs.common.controller.BaseController;
+import cc.mrbird.febs.common.entity.FebsResponse;
+import cc.mrbird.febs.vip.entity.MallVipBenefits;
+import cc.mrbird.febs.vip.entity.MallVipConfig;
+import cc.mrbird.febs.vip.service.IMallVipBenefitsService;
+import cc.mrbird.febs.vip.service.IMallVipConfigService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+
+@Slf4j
+@Validated
+@RestController
+@RequiredArgsConstructor
+@RequestMapping(value = "/api/vip/config")
+@Api(value = "ApiMallVipConfigController", tags = "会员等级接口类")
+public class ApiMallVipConfigController extends BaseController {
+
+    private final IMallVipConfigService mallVipConfigService;
+    private final IMallVipBenefitsService mallVipBenefitsService;
+
+
+    @ApiOperation(value = "获取会员等级列表")
+    @ApiResponses({
+            @ApiResponse(code = 200, message = "success", response = MallVipConfig.class)
+    })
+    @GetMapping(value = "/findVipList")
+    public FebsResponse findVipList() {
+        return new FebsResponse().success().data(mallVipConfigService.findConfigList());
+    }
+
+    @ApiOperation(value = "获取权益详情")
+    @ApiResponses({
+            @ApiResponse(code = 200, message = "success", response = MallVipBenefits.class)
+    })
+    @GetMapping(value = "/findBenefitsDetailList/{id}")
+    public FebsResponse findVipDetailList(@PathVariable("id") Long id) {
+        MallVipBenefits vipBenefits = mallVipBenefitsService.findVipBenefitsById(id);
+        return new FebsResponse().success().data(vipBenefits);
+    }
+
+    @ApiOperation(value = "领取权益")
+    @PostMapping(value = "/getBenefitsData/{id}")
+    public FebsResponse getBenefitsData(@PathVariable("id") Long id) {
+        mallVipBenefitsService.getBenefits(id);
+        return new FebsResponse().success().message("领取成功");
+    }
+}
diff --git a/src/main/java/cc/mrbird/febs/vip/controller/ViewVipConfigController.java b/src/main/java/cc/mrbird/febs/vip/controller/ViewVipConfigController.java
new file mode 100644
index 0000000..793ded0
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/vip/controller/ViewVipConfigController.java
@@ -0,0 +1,172 @@
+package cc.mrbird.febs.vip.controller;
+
+import cc.mrbird.febs.common.entity.FebsConstant;
+import cc.mrbird.febs.common.enumerates.DataDictionaryEnum;
+import cc.mrbird.febs.common.utils.FebsUtil;
+import cc.mrbird.febs.mall.entity.DataDictionaryCustom;
+import cc.mrbird.febs.mall.entity.MallGoods;
+import cc.mrbird.febs.mall.entity.MallGoodsCoupon;
+import cc.mrbird.febs.mall.mapper.DataDictionaryCustomMapper;
+import cc.mrbird.febs.mall.mapper.MallGoodsCouponMapper;
+import cc.mrbird.febs.mall.service.IApiMallGoodsService;
+import cc.mrbird.febs.vip.VipSettingUnAliveSettingBo;
+import cc.mrbird.febs.vip.entity.MallVipBenefits;
+import cc.mrbird.febs.vip.entity.MallVipConfig;
+import cc.mrbird.febs.vip.entity.MallVipConfigBenefits;
+import cc.mrbird.febs.vip.service.IMallVipBenefitsService;
+import cc.mrbird.febs.vip.service.IMallVipConfigBenefitsService;
+import cc.mrbird.febs.vip.service.IMallVipConfigService;
+import cc.mrbird.febs.vip.vo.VipSettingVo;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Controller("mallVipConfig")
+@RequestMapping(FebsConstant.VIEW_PREFIX + "modules/vip/config")
+@RequiredArgsConstructor
+public class ViewVipConfigController {
+
+    private final IMallVipBenefitsService mallVipBenefitsService;
+    private final IApiMallGoodsService apiMallGoodsService;
+    private final MallGoodsCouponMapper mallGoodsCouponMapper;
+    private final IMallVipConfigService mallVipConfigService;
+    private final IMallVipConfigBenefitsService mallVipConfigBenefitsService;
+    private final DataDictionaryCustomMapper dataDictionaryCustomMapper;
+
+    @GetMapping(value = "/benefitsList")
+    public String benefitsList() {
+        return FebsUtil.view("modules/vip/vipBenefits-list");
+    }
+
+    @GetMapping(value = "/vipBenefitsAdd")
+    public String vipBenefitsAdd() {
+        return FebsUtil.view("modules/vip/vipBenefits-add");
+    }
+
+
+    @GetMapping(value = "/goodsSelect/{index}")
+    public String goodsSelect(@PathVariable("index") String index, Model model) {
+        model.addAttribute("tableIndex", index);
+        return FebsUtil.view("modules/vip/goods-select-list");
+    }
+
+
+    @GetMapping(value = "/couponSelect/{index}")
+    public String couponSelect(@PathVariable("index") String index, Model model) {
+        model.addAttribute("tableIndex", index);
+        return FebsUtil.view("modules/vip/coupon-select");
+    }
+
+    @GetMapping("/editBenefits/{id}")
+    public String editBenefits(@PathVariable("id") Long id, Model model) {
+        MallVipBenefits vipBenefits = mallVipBenefitsService.findVipBenefitsById(id);
+
+        List<Long> goodsIds = new ArrayList<>();
+        List<Long> couponIds = new ArrayList<>();
+        vipBenefits.getDetails().forEach(item -> {
+            if (item.getIsClick() == 2) {
+                return;
+            }
+
+            if (item.getLinkType() == 2) {
+                goodsIds.add(Long.parseLong(item.getContent()));
+            }
+
+            if (item.getLinkType() == 3) {
+                couponIds.add(Long.parseLong(item.getContent()));
+            }
+        });
+
+        List<MallGoods> goodsList = new ArrayList<>();
+        if (CollUtil.isNotEmpty(goodsIds)) {
+            goodsList = apiMallGoodsService.listByIds(goodsIds);
+        }
+
+        List<MallGoodsCoupon> coupons = new ArrayList<>();
+        if (CollUtil.isNotEmpty(couponIds)) {
+            coupons = mallGoodsCouponMapper.selectBatchIds(couponIds);
+        }
+
+        Map<Long, MallGoods> goodsMap = goodsList.stream().collect(Collectors.toMap(MallGoods::getId, MallGoods -> MallGoods));
+        Map<Long, MallGoodsCoupon> couponMap = coupons.stream().collect(Collectors.toMap(MallGoodsCoupon::getId, MallGoodsCoupon -> MallGoodsCoupon));
+
+        vipBenefits.getDetails().forEach(item -> {
+            if (item.getIsClick() == 2) {
+                return;
+            }
+
+            if (item.getLinkType() == 2) {
+                MallGoods mallGoods = goodsMap.get(Long.parseLong(item.getContent()));
+                if (mallGoods != null) {
+                    item.setContentName(mallGoods.getGoodsName());
+                }
+            }
+
+            if (item.getLinkType() == 3) {
+                MallGoodsCoupon coupon = couponMap.get(Long.parseLong(item.getContent()));
+                if (coupon != null) {
+                    item.setContentName(coupon.getName());
+                }
+            }
+        });
+        model.addAttribute("benefitsData", vipBenefits);
+        return FebsUtil.view("modules/vip/vipBenefits-edit");
+    }
+
+    @GetMapping(value = "/levelList")
+    public String levelList() {
+        return FebsUtil.view("modules/vip/vipConfig-list");
+    }
+
+    @GetMapping(value = "/levelAdd")
+    public String levelAdd() {
+        return FebsUtil.view("modules/vip/vipConfig-add");
+    }
+
+    @GetMapping(value = "/levelEdit/{id}")
+    public String levelEdit(@PathVariable("id") Long id, Model model) {
+        MallVipConfig vipConfig = mallVipConfigService.getById(id);
+        if (vipConfig.getType() == 1) {
+            MallGoods goods = apiMallGoodsService.getById(vipConfig.getTargetId());
+            vipConfig.setTargetId(goods.getId());
+            vipConfig.setTargetName(goods.getGoodsName());
+        }
+
+        LambdaQueryWrapper<MallVipConfigBenefits> configBenefitsQuery = new LambdaQueryWrapper<>();
+        configBenefitsQuery.eq(MallVipConfigBenefits::getConfigId, vipConfig.getId());
+        List<MallVipConfigBenefits> list = mallVipConfigBenefitsService.list(configBenefitsQuery);
+
+        List<Long> benefitsIds = list.stream().map(MallVipConfigBenefits::getBenefitsId).collect(Collectors.toList());
+        vipConfig.setBenefitsIdList(benefitsIds);
+
+        model.addAttribute("configData", vipConfig);
+        return FebsUtil.view("modules/vip/vipConfig-edit");
+    }
+
+    @GetMapping(value = "/vipSetting")
+    public String vipSetting(Model model) {
+        DataDictionaryCustom data = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(DataDictionaryEnum.VIP_DATE.getType(), DataDictionaryEnum.VIP_DATE.getCode());
+        VipSettingVo setting = new VipSettingVo();
+        setting.setVipDate(data.getValue());
+
+        DataDictionaryCustom couponData = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(DataDictionaryEnum.UNALIVE_COUPON.getType(), DataDictionaryEnum.UNALIVE_COUPON.getCode());
+        if (couponData != null && StrUtil.isNotBlank(couponData.getValue())) {
+            List<VipSettingUnAliveSettingBo> items = JSONObject.parseArray(couponData.getValue(), VipSettingUnAliveSettingBo.class);
+            setting.setItems(items);
+        }
+        model.addAttribute("vipSetting", setting);
+        return FebsUtil.view("modules/vip/vip-setting");
+    }
+}
diff --git a/src/main/java/cc/mrbird/febs/vip/entity/MallVipBenefits.java b/src/main/java/cc/mrbird/febs/vip/entity/MallVipBenefits.java
new file mode 100644
index 0000000..a6f65fd
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/vip/entity/MallVipBenefits.java
@@ -0,0 +1,55 @@
+package cc.mrbird.febs.vip.entity;
+
+import cc.mrbird.febs.common.entity.BaseEntity;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+@TableName("mall_vip_benefits")
+@ApiModel(value = "MallVipBenefits")
+public class MallVipBenefits extends BaseEntity {
+
+    /**
+     * 权益名称
+     */
+    @ApiModelProperty(value = "权益名称")
+    private String name;
+
+    /**
+     * 权益类型;1-积分 2-指定商品 3-暂无
+     */
+    private Integer type;
+
+    /**
+     * 权益图标
+     */
+    @ApiModelProperty(value = "权益图标")
+    private String icon;
+
+    /**
+     * 积分倍数
+     */
+    private BigDecimal scoreMultiple;
+
+    /**
+     * 获取途径 1-会员日 2-生日
+     */
+    private Integer gainType;
+
+    /**
+     * 权益备注
+     */
+    private String remark;
+
+    @TableField(exist = false)
+    private Integer isJump;
+
+    @TableField(exist = false)
+    private List<MallVipBenefitsDetails> details;
+}
diff --git a/src/main/java/cc/mrbird/febs/vip/entity/MallVipBenefitsDetails.java b/src/main/java/cc/mrbird/febs/vip/entity/MallVipBenefitsDetails.java
new file mode 100644
index 0000000..9d55849
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/vip/entity/MallVipBenefitsDetails.java
@@ -0,0 +1,51 @@
+package cc.mrbird.febs.vip.entity;
+
+import cc.mrbird.febs.common.entity.BaseEntity;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+@TableName("mall_vip_benefits_details")
+@ApiModel(value = "MallVipBenefitsDetails")
+public class MallVipBenefitsDetails extends BaseEntity {
+
+    /**
+     * 图片链接
+     */
+    @ApiModelProperty(value = "图片")
+    private String image;
+
+    /**
+     * 是否可点击;1-是 2-否
+     */
+    @ApiModelProperty(value = "是否可点击")
+    private Integer isClick;
+
+    /**
+     * 链接类型;1-链接 2-领取商品 3-优惠券
+     */
+    @ApiModelProperty(value = "1-链接 2-领取商品 3-优惠券")
+    private Integer linkType;
+
+    /**
+     * 内容;根据linkType来的
+     */
+    @ApiModelProperty(value = "跳转的链接或者商品/优惠券的ID")
+    private String content;
+
+    /**
+     * 排序
+     */
+    private String seq;
+
+    /**
+     * 权益ID
+     */
+    private Long benefitsId;
+
+    @TableField(exist = false)
+    private String contentName;
+}
diff --git a/src/main/java/cc/mrbird/febs/vip/entity/MallVipBenefitsRecord.java b/src/main/java/cc/mrbird/febs/vip/entity/MallVipBenefitsRecord.java
new file mode 100644
index 0000000..7f3f1ff
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/vip/entity/MallVipBenefitsRecord.java
@@ -0,0 +1,28 @@
+package cc.mrbird.febs.vip.entity;
+
+import cc.mrbird.febs.common.entity.BaseEntity;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+@TableName(value = "mall_vip_benefits_record")
+public class MallVipBenefitsRecord extends BaseEntity {
+
+    private Long memberId ;
+    /** 权益名称 */
+    private String benefitsName ;
+    /** 权益类型; 1-会员日 2-生日 */
+    private Integer benefitsType ;
+    /** 领取名称 */
+    private String receiveName ;
+    /** 领取数量 */
+    private Integer receiveCnt ;
+    /** 领取时间 */
+    private Date receiveTime ;
+    /** 领取类型;2-商品 3-优惠券 */
+    private Integer receiveType ;
+    /** 领取ID */
+    private Long receiveId ;
+}
diff --git a/src/main/java/cc/mrbird/febs/vip/entity/MallVipConfig.java b/src/main/java/cc/mrbird/febs/vip/entity/MallVipConfig.java
new file mode 100644
index 0000000..c9670a3
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/vip/entity/MallVipConfig.java
@@ -0,0 +1,83 @@
+package cc.mrbird.febs.vip.entity;
+
+import cc.mrbird.febs.common.entity.BaseEntity;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+@ApiModel(value = "MallVipConfig")
+@TableName("mall_vip_config")
+public class MallVipConfig extends BaseEntity {
+
+
+    /**
+     * 会员名称
+     */
+    @ApiModelProperty(value = "名称")
+    private String name;
+
+    /**
+     * 主图
+     */
+    @ApiModelProperty(value = "主图")
+    private String thumb;
+
+    /**
+     * 会员编码
+     */
+    private String code;
+
+    /**
+     * 等级
+     */
+    @ApiModelProperty(value = "会员等级")
+    private Integer level;
+
+    /**
+     * 有效期
+     */
+    private Integer validTime;
+
+    /**
+     * 有效期类型;day/month/year
+     */
+    private String validType;
+
+    /**
+     * 成为会员条件类型;1-指定商品 2-时间区间内消费金额
+     */
+    private Integer type;
+
+    /**
+     * 消费金额
+     */
+    private BigDecimal amount;
+
+    /**
+     * 指定月数
+     */
+    private Integer times;
+
+    /**
+     * 指定商品ID
+     */
+    private Long targetId;
+
+    @TableField(exist = false)
+    private String targetName;
+
+    @TableField(exist = false)
+    private List<MallVipBenefits> benefits;
+
+    @TableField(exist = false)
+    private String benefitsIds;
+
+    @TableField(exist = false)
+    private List<Long> benefitsIdList;
+}
diff --git a/src/main/java/cc/mrbird/febs/vip/entity/MallVipConfigBenefits.java b/src/main/java/cc/mrbird/febs/vip/entity/MallVipConfigBenefits.java
new file mode 100644
index 0000000..8cfd973
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/vip/entity/MallVipConfigBenefits.java
@@ -0,0 +1,20 @@
+package cc.mrbird.febs.vip.entity;
+
+import cc.mrbird.febs.common.entity.BaseEntity;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+@Data
+@TableName("mall_vip_config_benefits")
+public class MallVipConfigBenefits extends BaseEntity {
+
+    /**
+     * 会员配置ID
+     */
+    private Long configId;
+
+    /**
+     * 会员权益ID
+     */
+    private Long benefitsId;
+}
diff --git a/src/main/java/cc/mrbird/febs/vip/mapper/MallVipBenefitsDetailsMapper.java b/src/main/java/cc/mrbird/febs/vip/mapper/MallVipBenefitsDetailsMapper.java
new file mode 100644
index 0000000..8d37907
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/vip/mapper/MallVipBenefitsDetailsMapper.java
@@ -0,0 +1,7 @@
+package cc.mrbird.febs.vip.mapper;
+
+import cc.mrbird.febs.vip.entity.MallVipBenefitsDetails;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+public interface MallVipBenefitsDetailsMapper extends BaseMapper<MallVipBenefitsDetails> {
+}
diff --git a/src/main/java/cc/mrbird/febs/vip/mapper/MallVipBenefitsMapper.java b/src/main/java/cc/mrbird/febs/vip/mapper/MallVipBenefitsMapper.java
new file mode 100644
index 0000000..89319c5
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/vip/mapper/MallVipBenefitsMapper.java
@@ -0,0 +1,18 @@
+package cc.mrbird.febs.vip.mapper;
+
+import cc.mrbird.febs.vip.entity.MallVipBenefits;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface MallVipBenefitsMapper extends BaseMapper<MallVipBenefits> {
+
+    IPage<MallVipBenefits> selectVipBenefitsListInPage(Page<MallVipBenefits> page);
+
+    MallVipBenefits selectVipBenefitsById(@Param("id") Long id);
+
+    List<MallVipBenefits> selectVipBenefitsByIds(@Param("list") List<Long> ids);
+}
diff --git a/src/main/java/cc/mrbird/febs/vip/mapper/MallVipBenefitsRecordMapper.java b/src/main/java/cc/mrbird/febs/vip/mapper/MallVipBenefitsRecordMapper.java
new file mode 100644
index 0000000..149aea4
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/vip/mapper/MallVipBenefitsRecordMapper.java
@@ -0,0 +1,7 @@
+package cc.mrbird.febs.vip.mapper;
+
+import cc.mrbird.febs.vip.entity.MallVipBenefitsRecord;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+public interface MallVipBenefitsRecordMapper extends BaseMapper<MallVipBenefitsRecord> {
+}
diff --git a/src/main/java/cc/mrbird/febs/vip/mapper/MallVipConfigBenefitsMapper.java b/src/main/java/cc/mrbird/febs/vip/mapper/MallVipConfigBenefitsMapper.java
new file mode 100644
index 0000000..dc72f52
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/vip/mapper/MallVipConfigBenefitsMapper.java
@@ -0,0 +1,7 @@
+package cc.mrbird.febs.vip.mapper;
+
+import cc.mrbird.febs.vip.entity.MallVipConfigBenefits;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+public interface MallVipConfigBenefitsMapper extends BaseMapper<MallVipConfigBenefits> {
+}
diff --git a/src/main/java/cc/mrbird/febs/vip/mapper/MallVipConfigMapper.java b/src/main/java/cc/mrbird/febs/vip/mapper/MallVipConfigMapper.java
new file mode 100644
index 0000000..0a856a4
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/vip/mapper/MallVipConfigMapper.java
@@ -0,0 +1,17 @@
+package cc.mrbird.febs.vip.mapper;
+
+import cc.mrbird.febs.vip.entity.MallVipConfig;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface MallVipConfigMapper extends BaseMapper<MallVipConfig> {
+
+    IPage<MallVipConfig> findVipConfigListInPage(IPage<MallVipConfig> page);
+
+    List<MallVipConfig> selectVipConfigList();
+
+    MallVipConfig selectVipConfigByCode(@Param("code") String code);
+}
diff --git a/src/main/java/cc/mrbird/febs/vip/service/IMallVipBenefitsDetailsService.java b/src/main/java/cc/mrbird/febs/vip/service/IMallVipBenefitsDetailsService.java
new file mode 100644
index 0000000..60c5624
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/vip/service/IMallVipBenefitsDetailsService.java
@@ -0,0 +1,7 @@
+package cc.mrbird.febs.vip.service;
+
+import cc.mrbird.febs.vip.entity.MallVipBenefitsDetails;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+public interface IMallVipBenefitsDetailsService extends IService<MallVipBenefitsDetails> {
+}
diff --git a/src/main/java/cc/mrbird/febs/vip/service/IMallVipBenefitsService.java b/src/main/java/cc/mrbird/febs/vip/service/IMallVipBenefitsService.java
new file mode 100644
index 0000000..df60c35
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/vip/service/IMallVipBenefitsService.java
@@ -0,0 +1,21 @@
+package cc.mrbird.febs.vip.service;
+
+import cc.mrbird.febs.common.entity.QueryRequest;
+import cc.mrbird.febs.vip.entity.MallVipBenefits;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+public interface IMallVipBenefitsService extends IService<MallVipBenefits> {
+
+    IPage<MallVipBenefits> vipBenefitsListInPage(QueryRequest request);
+
+    MallVipBenefits findVipBenefitsById(Long id);
+
+    void addVipBenefits(MallVipBenefits mallVipBenefits);
+
+    void delVipBenefits(Long id);
+
+    void editVipBenefits(MallVipBenefits mallVipBenefits);
+
+    void getBenefits(Long id);
+}
diff --git a/src/main/java/cc/mrbird/febs/vip/service/IMallVipConfigBenefitsService.java b/src/main/java/cc/mrbird/febs/vip/service/IMallVipConfigBenefitsService.java
new file mode 100644
index 0000000..98634de
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/vip/service/IMallVipConfigBenefitsService.java
@@ -0,0 +1,7 @@
+package cc.mrbird.febs.vip.service;
+
+import cc.mrbird.febs.vip.entity.MallVipConfigBenefits;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+public interface IMallVipConfigBenefitsService extends IService<MallVipConfigBenefits> {
+}
diff --git a/src/main/java/cc/mrbird/febs/vip/service/IMallVipConfigService.java b/src/main/java/cc/mrbird/febs/vip/service/IMallVipConfigService.java
new file mode 100644
index 0000000..8137f8b
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/vip/service/IMallVipConfigService.java
@@ -0,0 +1,25 @@
+package cc.mrbird.febs.vip.service;
+
+import cc.mrbird.febs.common.entity.QueryRequest;
+import cc.mrbird.febs.vip.entity.MallVipBenefits;
+import cc.mrbird.febs.vip.entity.MallVipBenefitsDetails;
+import cc.mrbird.febs.vip.entity.MallVipConfig;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.util.List;
+
+public interface IMallVipConfigService extends IService<MallVipConfig> {
+
+    IPage<MallVipConfig> vipConfigList(QueryRequest request);
+
+    List<MallVipConfig> findConfigList();
+
+    void addVipConfig(MallVipConfig config);
+
+    void editVipConfig(MallVipConfig config);
+
+    void delVipConfig(Long id);
+
+    MallVipBenefits hasVipBenefits(Long memberId);
+}
diff --git a/src/main/java/cc/mrbird/febs/vip/service/IVipCommonService.java b/src/main/java/cc/mrbird/febs/vip/service/IVipCommonService.java
new file mode 100644
index 0000000..e07a285
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/vip/service/IVipCommonService.java
@@ -0,0 +1,8 @@
+package cc.mrbird.febs.vip.service;
+
+public interface IVipCommonService {
+
+    void getScore(Long orderId);
+
+    void levelUp(Long orderId);
+}
diff --git a/src/main/java/cc/mrbird/febs/vip/service/impl/MallVipBenefitsDetailsServiceImpl.java b/src/main/java/cc/mrbird/febs/vip/service/impl/MallVipBenefitsDetailsServiceImpl.java
new file mode 100644
index 0000000..1be3f3d
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/vip/service/impl/MallVipBenefitsDetailsServiceImpl.java
@@ -0,0 +1,15 @@
+package cc.mrbird.febs.vip.service.impl;
+
+import cc.mrbird.febs.vip.entity.MallVipBenefitsDetails;
+import cc.mrbird.febs.vip.mapper.MallVipBenefitsDetailsMapper;
+import cc.mrbird.febs.vip.service.IMallVipBenefitsDetailsService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class MallVipBenefitsDetailsServiceImpl extends ServiceImpl<MallVipBenefitsDetailsMapper, MallVipBenefitsDetails> implements IMallVipBenefitsDetailsService {
+}
diff --git a/src/main/java/cc/mrbird/febs/vip/service/impl/MallVipBenefitsServiceImpl.java b/src/main/java/cc/mrbird/febs/vip/service/impl/MallVipBenefitsServiceImpl.java
new file mode 100644
index 0000000..5f91d71
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/vip/service/impl/MallVipBenefitsServiceImpl.java
@@ -0,0 +1,283 @@
+package cc.mrbird.febs.vip.service.impl;
+
+import cc.mrbird.febs.common.entity.QueryRequest;
+import cc.mrbird.febs.common.enumerates.DataDictionaryEnum;
+import cc.mrbird.febs.common.enumerates.OrderStatusEnum;
+import cc.mrbird.febs.common.exception.FebsException;
+import cc.mrbird.febs.common.utils.LoginUserUtil;
+import cc.mrbird.febs.common.utils.MallUtils;
+import cc.mrbird.febs.mall.entity.*;
+import cc.mrbird.febs.mall.mapper.*;
+import cc.mrbird.febs.mall.vo.AdminMailGoodsDetailVo;
+import cc.mrbird.febs.mall.vo.AdminMallNewsInfoVo;
+import cc.mrbird.febs.vip.entity.MallVipBenefits;
+import cc.mrbird.febs.vip.entity.MallVipBenefitsDetails;
+import cc.mrbird.febs.vip.entity.MallVipBenefitsRecord;
+import cc.mrbird.febs.vip.entity.MallVipConfig;
+import cc.mrbird.febs.vip.mapper.MallVipBenefitsDetailsMapper;
+import cc.mrbird.febs.vip.mapper.MallVipBenefitsMapper;
+import cc.mrbird.febs.vip.mapper.MallVipBenefitsRecordMapper;
+import cc.mrbird.febs.vip.mapper.MallVipConfigMapper;
+import cc.mrbird.febs.vip.service.IMallVipBenefitsDetailsService;
+import cc.mrbird.febs.vip.service.IMallVipBenefitsService;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DatePattern;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.metadata.OrderItem;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+import java.util.Objects;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class MallVipBenefitsServiceImpl extends ServiceImpl<MallVipBenefitsMapper, MallVipBenefits> implements IMallVipBenefitsService {
+
+    private final IMallVipBenefitsDetailsService mallVipBenefitsDetailsService;
+    private final MallMemberCouponMapper mallMemberCouponMapper;
+    private final MallGoodsCouponMapper mallGoodsCouponMapper;
+    private final MallGoodsMapper mallGoodsMapper;
+    private final MallAddressInfoMapper mallAddressInfoMapper;
+    private final MallOrderInfoMapper mallOrderInfoMapper;
+    private final MallOrderItemMapper mallOrderItemMapper;
+    private final MallVipBenefitsRecordMapper mallVipBenefitsRecordMapper;
+    private final DataDictionaryCustomMapper dataDictionaryCustomMapper;
+    private final MallMemberMapper mallMemberMapper;
+    private final MallVipConfigMapper mallVipConfigMapper;
+
+    @Override
+    public IPage<MallVipBenefits> vipBenefitsListInPage(QueryRequest request) {
+        Page<MallVipBenefits> page = new Page<>(request.getPageNum(), request.getPageSize());
+        return this.baseMapper.selectVipBenefitsListInPage(page);
+    }
+
+    @Override
+    public MallVipBenefits findVipBenefitsById(Long id) {
+        return this.baseMapper.selectVipBenefitsById(id);
+    }
+
+    @Override
+    @Transactional
+    public void addVipBenefits(MallVipBenefits mallVipBenefits) {
+        if (mallVipBenefits == null) {
+            return;
+        }
+
+        if (CollUtil.isEmpty(mallVipBenefits.getDetails())) {
+            throw new FebsException("权益明细不能为空");
+        }
+
+        this.baseMapper.insert(mallVipBenefits);
+
+        mallVipBenefits.getDetails().forEach(item -> {
+            item.setBenefitsId(mallVipBenefits.getId());
+        });
+        this.mallVipBenefitsDetailsService.saveBatch(mallVipBenefits.getDetails());
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void delVipBenefits(Long id) {
+        this.baseMapper.deleteById(id);
+
+        LambdaQueryWrapper<MallVipBenefitsDetails> delQuery = new LambdaQueryWrapper<>();
+        delQuery.eq(MallVipBenefitsDetails::getBenefitsId, id);
+        this.mallVipBenefitsDetailsService.remove(delQuery);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void editVipBenefits(MallVipBenefits mallVipBenefits) {
+        if (mallVipBenefits.getId() == null) {
+            throw new FebsException("缺少重要参数");
+        }
+
+        this.baseMapper.updateById(mallVipBenefits);
+
+        LambdaQueryWrapper<MallVipBenefitsDetails> delQuery = new LambdaQueryWrapper<>();
+        delQuery.eq(MallVipBenefitsDetails::getBenefitsId, mallVipBenefits.getId());
+        this.mallVipBenefitsDetailsService.remove(delQuery);
+
+        mallVipBenefits.getDetails().forEach(item -> {
+            item.setBenefitsId(mallVipBenefits.getId());
+        });
+        this.mallVipBenefitsDetailsService.saveBatch(mallVipBenefits.getDetails());
+
+    }
+
+
+    @Override
+    public void getBenefits(Long id) {
+        MallMember loginUser = LoginUserUtil.getLoginUser();
+        MallMember member = mallMemberMapper.selectById(loginUser.getId());
+
+        MallVipBenefitsDetails benefits = mallVipBenefitsDetailsService.getById(id);
+        if (benefits == null) {
+            throw new FebsException("权益不存在");
+        }
+
+        if (benefits.getIsClick() == 2) {
+            throw new FebsException("请联系客服,检查权益设置");
+        }
+
+        MallVipBenefits vipBenefits = this.baseMapper.selectById(benefits.getBenefitsId());
+        if (vipBenefits == null) {
+            throw new FebsException("权益不存在");
+        }
+
+
+        MallVipConfig config = mallVipConfigMapper.selectVipConfigByCode(member.getLevel());
+        boolean b = config.getBenefits().stream().anyMatch(item -> {
+            return Objects.equals(item.getId(), benefits.getBenefitsId());
+        });
+        if (!b) {
+            throw new FebsException("未达到等级不能领取该权益");
+        }
+
+        Integer linkType = benefits.getLinkType();
+
+        if (vipBenefits.getGainType() == 2) {
+            String today = DateUtil.format(new Date(), DatePattern.NORM_DATE_PATTERN);
+            boolean isBirthday = member.getBirthday().compareTo(DateUtil.parseDate(today)) == 0;
+            if (!isBirthday) {
+                throw new FebsException("未达到权益领取条件:未到生日");
+            }
+        }
+
+        if (vipBenefits.getGainType() == 3) {
+            DataDictionaryCustom data = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(DataDictionaryEnum.VIP_DATE.getType(), DataDictionaryEnum.VIP_DATE.getCode());
+
+            String today = DateUtil.format(new Date(), "MM-dd");
+            if (!StrUtil.equals(data.getValue(), today)) {
+                throw new FebsException("未达到权益领取条件:未到会员日");
+            }
+        }
+
+        LambdaQueryWrapper<MallVipBenefitsRecord> recordQuery = new LambdaQueryWrapper<>();
+        recordQuery.ge(MallVipBenefitsRecord::getReceiveTime, DateUtil.beginOfDay(new Date()))
+                .le(MallVipBenefitsRecord::getReceiveTime, DateUtil.endOfDay(new Date()))
+                .eq(MallVipBenefitsRecord::getMemberId, member.getId())
+                .eq(MallVipBenefitsRecord::getBenefitsType, vipBenefits.getGainType())
+                .eq(MallVipBenefitsRecord::getReceiveId, Long.parseLong(benefits.getContent()));
+        List<MallVipBenefitsRecord> mallVipBenefitsRecords = mallVipBenefitsRecordMapper.selectList(recordQuery);
+        if (CollUtil.isNotEmpty(mallVipBenefitsRecords)) {
+            throw new FebsException("已领取过权益");
+        }
+
+        MallVipBenefitsRecord record = new MallVipBenefitsRecord();
+        record.setBenefitsType(vipBenefits.getGainType());
+        record.setBenefitsName(vipBenefits.getName());
+        record.setReceiveTime(new Date());
+        record.setReceiveType(linkType);
+        record.setReceiveId(Long.parseLong(benefits.getContent()));
+        record.setMemberId(member.getId());
+        record.setReceiveCnt(1);
+
+        // 商品
+        if (linkType == 2) {
+            MallGoods goods = mallGoodsMapper.selectGoodsDetailById(Long.parseLong(benefits.getContent()));
+            if (goods == null) {
+                throw new FebsException("商品不存在");
+            }
+
+            LambdaQueryWrapper<MallAddressInfo> query = new LambdaQueryWrapper<>();
+            query.eq(MallAddressInfo::getMemberId, member.getId())
+                    .eq(MallAddressInfo::getIsDefault, 1)
+                    .last("limit 1");
+            MallAddressInfo address = mallAddressInfoMapper.selectOne(query);
+            if (address == null) {
+                throw new FebsException("请设置默认地址");
+            }
+
+            String orderNo = MallUtils.getOrderNum();
+            MallOrderInfo orderInfo = new MallOrderInfo();
+            orderInfo.setOrderNo(orderNo);
+            orderInfo.setOrderTime(new Date());
+            orderInfo.setMemberId(member.getId());
+            orderInfo.setPayTime(new Date());
+            orderInfo.setStatus(OrderStatusEnum.WAIT_SHIPPING.getValue());
+            orderInfo.setOrderType(goods.getGoodsType());
+            orderInfo.setDeliveryType(2);
+            orderInfo.setIsFree(1);
+            orderInfo.setCarriage(BigDecimal.ZERO);
+            orderInfo.setAmount(BigDecimal.ZERO);
+            orderInfo.setAddressId(address.getId());
+            orderInfo.setName(address.getName());
+            orderInfo.setPhone(address.getPhone());
+            orderInfo.setIsHome(2);
+            orderInfo.setAddress(address.getProvince()+address.getCity()+address.getArea() + address.getAddress());
+            orderInfo.setLatitude(address.getLatitude());
+            orderInfo.setLongitude(address.getLongitude());
+            mallOrderInfoMapper.insert(orderInfo);
+
+            MallOrderItem orderItem = new MallOrderItem();
+            if (goods.getGoodsType() == 2) {
+                orderItem.setAmount(BigDecimal.ZERO);
+                orderItem.setCnt(1);
+                orderItem.setOrderId(orderInfo.getId());
+                orderItem.setPrice(goods.getScore());
+                orderItem.setGoodsId(goods.getId());
+                orderItem.setGoodsName(goods.getGoodsName());
+                orderItem.setStyleName(goods.getGoodsName());
+                orderItem.setSkuName(goods.getGoodsName());
+                orderItem.setSkuImage(goods.getThumb());
+                orderItem.setState(1);
+            } else {
+                MallGoodsSku sku = goods.getStyles().get(0).getSkus().get(0);
+
+                orderItem.setAmount(BigDecimal.ZERO);
+                orderItem.setCnt(1);
+                orderItem.setOrderId(orderInfo.getId());
+                orderItem.setPrice(sku.getPresentPrice());
+                orderItem.setGoodsId(sku.getGoodsId());
+                orderItem.setGoodsName(goods.getGoodsName());
+                orderItem.setSkuId(sku.getId());
+                orderItem.setState(1);
+                orderItem.setStyleName(goods.getStyles().get(0).getName());
+                orderItem.setSkuName(sku.getSkuName());
+                orderItem.setSkuImage(sku.getSkuImage());
+                orderItem.setIsNormal(goods.getIsNormal());
+                orderItem.setCostPrice(sku.getCostPrice());
+            }
+
+            record.setReceiveName(goods.getGoodsName());
+            mallOrderItemMapper.insert(orderItem);
+        }
+
+        // 优惠券
+        if (linkType == 3) {
+            MallGoodsCoupon coupon = mallGoodsCouponMapper.selectById(Long.parseLong(benefits.getContent()));
+            if (coupon == null) {
+                throw new FebsException("优惠券");
+            }
+            MallMemberCoupon memberCoupon = new MallMemberCoupon();
+            memberCoupon.setCouponId(coupon.getId());
+            memberCoupon.setCouponName(coupon.getName());
+            memberCoupon.setInviteId(member.getInviteId());
+            memberCoupon.setCouponUuid(IdUtil.simpleUUID());
+            memberCoupon.setState(1);
+            memberCoupon.setFromType(2);
+            memberCoupon.setExpireTime(DateUtil.offsetDay(DateUtil.date(), coupon.getExpireDay()));
+            memberCoupon.setMemberId(member.getId());
+            mallMemberCouponMapper.insert(memberCoupon);
+
+            record.setReceiveName(coupon.getName());
+        }
+
+        mallVipBenefitsRecordMapper.insert(record);
+    }
+
+}
diff --git a/src/main/java/cc/mrbird/febs/vip/service/impl/MallVipConfigBenefitsServiceImpl.java b/src/main/java/cc/mrbird/febs/vip/service/impl/MallVipConfigBenefitsServiceImpl.java
new file mode 100644
index 0000000..b992145
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/vip/service/impl/MallVipConfigBenefitsServiceImpl.java
@@ -0,0 +1,15 @@
+package cc.mrbird.febs.vip.service.impl;
+
+import cc.mrbird.febs.vip.entity.MallVipConfigBenefits;
+import cc.mrbird.febs.vip.mapper.MallVipConfigBenefitsMapper;
+import cc.mrbird.febs.vip.service.IMallVipConfigBenefitsService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class MallVipConfigBenefitsServiceImpl extends ServiceImpl<MallVipConfigBenefitsMapper, MallVipConfigBenefits> implements IMallVipConfigBenefitsService {
+}
diff --git a/src/main/java/cc/mrbird/febs/vip/service/impl/MallVipConfigServiceImpl.java b/src/main/java/cc/mrbird/febs/vip/service/impl/MallVipConfigServiceImpl.java
new file mode 100644
index 0000000..1972463
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/vip/service/impl/MallVipConfigServiceImpl.java
@@ -0,0 +1,168 @@
+package cc.mrbird.febs.vip.service.impl;
+
+import cc.mrbird.febs.common.entity.QueryRequest;
+import cc.mrbird.febs.common.enumerates.DataDictionaryEnum;
+import cc.mrbird.febs.common.exception.FebsException;
+import cc.mrbird.febs.mall.entity.DataDictionaryCustom;
+import cc.mrbird.febs.mall.entity.MallMember;
+import cc.mrbird.febs.mall.mapper.DataDictionaryCustomMapper;
+import cc.mrbird.febs.mall.mapper.MallMemberMapper;
+import cc.mrbird.febs.vip.entity.MallVipBenefits;
+import cc.mrbird.febs.vip.entity.MallVipConfig;
+import cc.mrbird.febs.vip.entity.MallVipConfigBenefits;
+import cc.mrbird.febs.vip.mapper.MallVipConfigBenefitsMapper;
+import cc.mrbird.febs.vip.mapper.MallVipConfigMapper;
+import cc.mrbird.febs.vip.service.IMallVipConfigBenefitsService;
+import cc.mrbird.febs.vip.service.IMallVipConfigService;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DatePattern;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class MallVipConfigServiceImpl extends ServiceImpl<MallVipConfigMapper, MallVipConfig> implements IMallVipConfigService {
+
+    private final IMallVipConfigBenefitsService mallVipConfigBenefitsService;
+    private final MallMemberMapper mallMemberMapper;
+    private final DataDictionaryCustomMapper dataDictionaryCustomMapper;
+
+    @Override
+    public IPage<MallVipConfig> vipConfigList(QueryRequest request) {
+        Page<MallVipConfig> page = new Page<>(request.getPageNum(), request.getPageSize());
+        return this.baseMapper.findVipConfigListInPage(page);
+    }
+
+    @Override
+    public List<MallVipConfig> findConfigList() {
+        List<MallVipConfig> configs = this.baseMapper.selectVipConfigList();
+        configs.forEach(item -> {
+            item.getBenefits().forEach(benefits -> {
+                benefits.setIsJump(CollUtil.isEmpty(benefits.getDetails()) ? 2 : 1);
+            });
+        });
+        return configs;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void addVipConfig(MallVipConfig config) {
+        List<MallVipConfig> configs = this.baseMapper.selectVipConfigList();
+        boolean b = configs.stream().anyMatch(item -> {
+            return (item.getLevel().equals(config.getLevel()) || config.getCode().equals(item.getCode()));
+        });
+
+        if (b) {
+            throw new FebsException("会员等级或编码已存在");
+        }
+        this.baseMapper.insert(config);
+
+        List<MallVipConfigBenefits> configBenefitsList = new ArrayList<>();
+        List<String> benefitsIds = StrUtil.split(config.getBenefitsIds(), ',');
+        benefitsIds.forEach(item -> {
+            MallVipConfigBenefits configBenefits = new MallVipConfigBenefits();
+            configBenefits.setConfigId(config.getId());
+            configBenefits.setBenefitsId(Long.parseLong(item));
+            configBenefitsList.add(configBenefits);
+        });
+
+        mallVipConfigBenefitsService.saveBatch(configBenefitsList);
+    }
+
+    @Override
+    public void editVipConfig(MallVipConfig config) {
+        MallVipConfig oldConfig = this.baseMapper.selectById(config.getId());
+
+        List<MallVipConfig> configs = this.baseMapper.selectVipConfigList();
+        boolean b = configs.stream().anyMatch(item -> {
+            return !item.getId().equals(config.getId()) && (item.getLevel().equals(config.getLevel()) || config.getCode().equals(item.getCode()));
+        });
+
+        if (b) {
+            throw new FebsException("会员等级或编码已存在");
+        }
+
+        if (!config.getCode().equals(oldConfig.getCode())) {
+            LambdaQueryWrapper<MallMember> memberQuery = new LambdaQueryWrapper<>();
+            memberQuery.eq(MallMember::getLevel, oldConfig.getCode());
+            List<MallMember> mallMembers = mallMemberMapper.selectList(memberQuery);
+            if (CollUtil.isNotEmpty(mallMembers)) {
+                throw new FebsException("会员编码绑定了客户,请调整后修改");
+            }
+        }
+
+
+        this.baseMapper.updateById(config);
+
+        LambdaQueryWrapper<MallVipConfigBenefits> delQuery = new LambdaQueryWrapper<>();
+        delQuery.eq(MallVipConfigBenefits::getConfigId, config.getId());
+        mallVipConfigBenefitsService.remove(delQuery);
+
+        List<MallVipConfigBenefits> configBenefitsList = new ArrayList<>();
+        List<String> benefitsIds = StrUtil.split(config.getBenefitsIds(), ',');
+        benefitsIds.forEach(item -> {
+            MallVipConfigBenefits configBenefits = new MallVipConfigBenefits();
+            configBenefits.setConfigId(config.getId());
+            configBenefits.setBenefitsId(Long.parseLong(item));
+            configBenefitsList.add(configBenefits);
+        });
+
+        mallVipConfigBenefitsService.saveBatch(configBenefitsList);
+    }
+
+    @Override
+    @Transactional
+    public void delVipConfig(Long id) {
+        this.baseMapper.deleteById(id);
+
+        LambdaQueryWrapper<MallVipConfigBenefits> delQuery = new LambdaQueryWrapper<>();
+        delQuery.eq(MallVipConfigBenefits::getConfigId, id);
+        this.mallVipConfigBenefitsService.remove(delQuery);
+    }
+
+    @Override
+    public MallVipBenefits hasVipBenefits(Long memberId) {
+        MallMember member = mallMemberMapper.selectById(memberId);
+        if (member == null) {
+            throw new FebsException("会员不存在");
+        }
+
+        MallVipConfig vipConfig = this.baseMapper.selectVipConfigByCode(member.getLevel());
+        if (vipConfig == null) {
+            throw new FebsException("会员配置不存在");
+        }
+
+        String today = DateUtil.format(new Date(), DatePattern.NORM_DATE_PATTERN);
+        boolean isBirthday = member.getBirthday().compareTo(DateUtil.parseDate(today)) == 0;
+        List<MallVipBenefits> benefits = vipConfig.getBenefits();
+        Optional<MallVipBenefits> max = benefits.stream().filter(item -> {
+            if (item.getScoreMultiple() == null) {
+                return false;
+            }
+
+            // 生日权益
+            if (item.getGainType() == 2 && isBirthday) {
+                return true;
+            }
+
+            DataDictionaryCustom data = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(DataDictionaryEnum.VIP_DATE.getType(), DataDictionaryEnum.VIP_DATE.getCode());
+
+            String todayTime = DateUtil.format(new Date(), "MM-dd");
+            // 会员日
+            return item.getGainType() == 1 && StrUtil.equals(data.getValue(), todayTime);
+        }).max(Comparator.comparing(MallVipBenefits::getScoreMultiple));
+
+        return max.orElse(null);
+    }
+}
diff --git a/src/main/java/cc/mrbird/febs/vip/service/impl/VipCommonServiceImpl.java b/src/main/java/cc/mrbird/febs/vip/service/impl/VipCommonServiceImpl.java
new file mode 100644
index 0000000..fa1618c
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/vip/service/impl/VipCommonServiceImpl.java
@@ -0,0 +1,168 @@
+package cc.mrbird.febs.vip.service.impl;
+
+import cc.mrbird.febs.common.enumerates.FlowTypeEnum;
+import cc.mrbird.febs.common.enumerates.MoneyFlowTypeEnum;
+import cc.mrbird.febs.common.enumerates.ScoreFlowTypeEnum;
+import cc.mrbird.febs.mall.entity.MallMember;
+import cc.mrbird.febs.mall.entity.MallOrderInfo;
+import cc.mrbird.febs.mall.entity.MallOrderItem;
+import cc.mrbird.febs.mall.mapper.MallMemberMapper;
+import cc.mrbird.febs.mall.mapper.MallOrderInfoMapper;
+import cc.mrbird.febs.mall.service.IApiMallMemberWalletService;
+import cc.mrbird.febs.mall.service.IApiMallOrderInfoService;
+import cc.mrbird.febs.mall.service.IMallMoneyFlowService;
+import cc.mrbird.febs.rabbit.producter.AgentProducer;
+import cc.mrbird.febs.vip.entity.MallVipBenefits;
+import cc.mrbird.febs.vip.entity.MallVipConfig;
+import cc.mrbird.febs.vip.mapper.MallVipConfigMapper;
+import cc.mrbird.febs.vip.service.IMallVipConfigService;
+import cc.mrbird.febs.vip.service.IVipCommonService;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class VipCommonServiceImpl implements IVipCommonService {
+
+    private final MallOrderInfoMapper mallOrderInfoMapper;
+    private final IMallVipConfigService mallVipConfigService;
+    private final IMallMoneyFlowService mallMoneyFlowService;
+    private final IApiMallMemberWalletService mallMemberWalletService;
+    private final MallMemberMapper mallMemberMapper;
+    private final MallVipConfigMapper mallVipConfigMapper;
+    private final AgentProducer agentProducer;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void getScore(Long orderId) {
+        MallOrderInfo mallOrderInfo = mallOrderInfoMapper.selectOrderDetailsById(orderId);
+        if (mallOrderInfo == null) {
+            return;
+        }
+
+        Long memberId = mallOrderInfo.getMemberId();
+        MallVipBenefits mallVipBenefits = mallVipConfigService.hasVipBenefits(memberId);
+
+        BigDecimal multiple = BigDecimal.ONE;
+        String name = "";
+        if (mallVipBenefits != null) {
+            multiple = mallVipBenefits.getScoreMultiple();
+            name = mallVipBenefits.getName();
+        }
+
+        List<String> skuNames = mallOrderInfo.getItems().stream().map(MallOrderItem::getSkuName).collect(Collectors.toList());
+        double sum = mallOrderInfo.getItems().stream().map(MallOrderItem::getAmount).mapToDouble(BigDecimal::doubleValue).sum();
+
+        int score = multiple.multiply(BigDecimal.valueOf(sum)).intValue();
+
+        mallMoneyFlowService.addMoneyFlow(memberId, new BigDecimal(score), ScoreFlowTypeEnum.BUY.getValue(), mallOrderInfo.getOrderNo(), FlowTypeEnum.PRIZE_SCORE.getValue(), CollUtil.join(skuNames, ","), 2);
+        mallMemberWalletService.add(new BigDecimal(score), memberId, "prizeScore");
+
+        agentProducer.sendVipLevelUp(orderId);
+    }
+
+    @Override
+    public void levelUp(Long orderId) {
+        MallOrderInfo mallOrderInfo = mallOrderInfoMapper.selectOrderDetailsById(orderId);
+        if (mallOrderInfo == null) {
+            return;
+        }
+
+        MallMember member = mallMemberMapper.selectById(mallOrderInfo.getMemberId());
+        if (member == null) {
+            log.info("会员不存在");
+            return;
+        }
+
+        MallVipConfig config = mallVipConfigMapper.selectVipConfigByCode(member.getLevel());
+        if (config == null) {
+            log.info("会员等级配置不存在");
+            return;
+        }
+
+//        LambdaQueryWrapper<MallVipConfig> configQuery = new LambdaQueryWrapper<>();
+//        configQuery.gt(MallVipConfig::getLevel, config.getLevel())
+//                .orderByAsc(MallVipConfig::getLevel)
+//                .last("limit 1");
+//        MallVipConfig nextLevel = mallVipConfigMapper.selectOne(configQuery);
+
+        List<MallVipConfig> configs = mallVipConfigMapper.selectVipConfigList();
+
+        String nextLevelCode = "";
+        for (MallVipConfig nextLevel : configs) {
+            if (config.getLevel() >= nextLevel.getLevel()) {
+                continue;
+            }
+
+            // 指定商品
+            if (nextLevel.getType() == 1) {
+                boolean hasMatch = mallOrderInfo.getItems().stream().anyMatch(item -> {
+                    return item.getGoodsId().equals(nextLevel.getTargetId());
+                });
+
+                if (hasMatch) {
+                    nextLevelCode = nextLevel.getCode();
+                    continue;
+                }
+            }
+
+            // 时间区间内金额
+            if (nextLevel.getType() == 2) {
+                Date endTime = DateUtil.endOfDay(new Date());
+                Date startTime = getStartTime(nextLevel.getValidType());
+
+                LambdaQueryWrapper<MallOrderInfo> query = new LambdaQueryWrapper<>();
+                query.ge(MallOrderInfo::getReceivingTime, startTime)
+                        .le(MallOrderInfo::getReceivingTime, endTime)
+                        .eq(MallOrderInfo::getStatus, 4)
+                        .eq(MallOrderInfo::getMemberId, member.getId());
+                List<MallOrderInfo> orderList = mallOrderInfoMapper.selectList(query);
+                if (CollUtil.isEmpty(orderList)) {
+                    continue;
+                }
+
+                double totalAmount = orderList.stream().mapToDouble(item -> {
+                    return item.getAmount().doubleValue();
+                }).sum();
+
+                if (nextLevel.getAmount().compareTo(BigDecimal.valueOf(totalAmount)) <= 0) {
+                    nextLevelCode = nextLevel.getCode();
+                }
+            }
+        }
+
+        if (StrUtil.isNotBlank(nextLevelCode)) {
+            MallMember update = new MallMember();
+            update.setId(member.getId());
+            update.setLevel(nextLevelCode);
+            update.setVipLevelTime(new Date());
+            mallMemberMapper.updateById(update);
+        }
+    }
+
+    private Date getStartTime(String type) {
+        Date date = new Date();
+        switch (type) {
+            case "day" :
+                return DateUtil.beginOfDay(date);
+            case "month":
+                return DateUtil.beginOfMonth(date);
+            case "year":
+                return DateUtil.beginOfYear(date);
+            default:
+                return date;
+        }
+    }
+}
diff --git a/src/main/java/cc/mrbird/febs/vip/vo/VipSettingVo.java b/src/main/java/cc/mrbird/febs/vip/vo/VipSettingVo.java
new file mode 100644
index 0000000..caed7c4
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/vip/vo/VipSettingVo.java
@@ -0,0 +1,14 @@
+package cc.mrbird.febs.vip.vo;
+
+import cc.mrbird.febs.vip.VipSettingUnAliveSettingBo;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class VipSettingVo {
+
+    private String vipDate;
+
+    private List<VipSettingUnAliveSettingBo> items;
+}
diff --git a/src/main/resources/mapper/modules/MallGoodsMapper.xml b/src/main/resources/mapper/modules/MallGoodsMapper.xml
index 20c4977..3162fc5 100644
--- a/src/main/resources/mapper/modules/MallGoodsMapper.xml
+++ b/src/main/resources/mapper/modules/MallGoodsMapper.xml
@@ -106,7 +106,7 @@
                 </if>
                 min(b.id) skuId,
                 min(b.present_price) price,
-                sum(b.stock) stock,
+                ifnull(sum(b.stock), a.stock) stock,
                 sum(b.sku_volume) saleVolume
             from mall_goods a
                  left join mall_goods_sku b on a.id=b.goods_id
@@ -123,9 +123,12 @@
                     <if test="record.isNormal != null and record.isNormal != ''">
                         and a.is_normal = #{record.isNormal}
                     </if>
-                    <if test="record.goodsType != null and record.goodsType != '' and record.goodsType != 3">
+                    <if test="record.goodsType != null and record.goodsType != '' and record.goodsType == 1">
                         and a.goods_type = #{record.goodsType} and a.present_price != 0
                     </if>
+                    <if test="record.goodsType != null and record.goodsType != '' and record.goodsType == 2">
+                        and a.goods_type = #{record.goodsType}
+                    </if>
                     <if test="record.goodsType == 3">
                         and a.present_price = 0
                     </if>
diff --git a/src/main/resources/mapper/modules/MallMemberCouponMapper.xml b/src/main/resources/mapper/modules/MallMemberCouponMapper.xml
index 41b4287..ecde786 100644
--- a/src/main/resources/mapper/modules/MallMemberCouponMapper.xml
+++ b/src/main/resources/mapper/modules/MallMemberCouponMapper.xml
@@ -6,7 +6,8 @@
         select
         a.*,
         b.cost_amount costAmount,
-        b.real_amount realAmount
+        b.real_amount realAmount,
+        b.type type
         from mall_member_coupon a
         INNER join mall_goods_coupon b on b.id = a.coupon_id and b.state = 2
         <where>
diff --git a/src/main/resources/mapper/modules/MallMemberMapper.xml b/src/main/resources/mapper/modules/MallMemberMapper.xml
index 1484e3d..37a2332 100644
--- a/src/main/resources/mapper/modules/MallMemberMapper.xml
+++ b/src/main/resources/mapper/modules/MallMemberMapper.xml
@@ -4,11 +4,11 @@
 
     <select id="selectMallMemberListInPage" resultType="cc.mrbird.febs.mall.entity.MallMember">
         SELECT m.*,a.name referrerName,IFNULL(c.balance,0) balance,IFNULL(c.score,0) score,IFNULL(c.prize_score,0) prizeScore,IFNULL(c.commission,0) commission
-        ,d.description levelName
+        ,vipConfig.name levelName
         FROM mall_member m
         left join mall_member a on m.referrer_id = a.invite_id
         LEFT JOIN mall_member_wallet c on c.member_id = m.id
-        LEFT JOIN data_dictionary_custom d on d.code = m.level and type='AGENT_LEVEL'
+        left join mall_vip_config vipConfig on m.level = vipConfig.code
         <where>
             <if test="record != null" >
                 <if test="record.name!=null and record.name!=''">
diff --git a/src/main/resources/mapper/modules/MallOrderInfoMapper.xml b/src/main/resources/mapper/modules/MallOrderInfoMapper.xml
index e1f180e..9e7f9e6 100644
--- a/src/main/resources/mapper/modules/MallOrderInfoMapper.xml
+++ b/src/main/resources/mapper/modules/MallOrderInfoMapper.xml
@@ -127,6 +127,7 @@
         <result column="take_unique_code" property="takeUniqueCode" />
         <result column="delivery_state" property="deliveryState" />
         <result column="is_home" property="isHome" />
+        <result column="is_free" property="isFree" />
         <result column="del_flag" property="delFlag" />
         <result column="leader_name" property="leaderName" />
         <result column="leader_phone" property="leaderPhone" />
@@ -215,7 +216,7 @@
             a.status,
             count(1) cnt
         from mall_order_info a
-        where a.del_flag=2 and a.member_id=#{memberId}
+        where a.del_flag=2 and a.member_id=#{memberId} and order_type = 1
         group by a.status
     </select>
 
@@ -374,6 +375,7 @@
         <result column="take_unique_code" property="takeUniqueCode" />
         <result column="delivery_state" property="deliveryState" />
         <result column="is_home" property="isHome" />
+        <result column="is_free" property="isFree" />
         <result column="del_flag" property="delFlag" />
         <result column="leader_name" property="leaderName" />
         <result column="leader_phone" property="leaderPhone" />
@@ -386,12 +388,15 @@
         <result column="city" property="city" />
         <result column="township" property="township" />
         <result column="detail_address" property="detailAddress" />
+        <result column="express_no" property="expressNo" />
     </resultMap>
 
     <select id="selectNewApiOrderListInPage" resultMap="NewOrderInfoMap">
         select
         a.*
+        ,express.express_no
         from mall_order_info a
+            left join mall_express_info express on a.id=express.order_id
         <where>
             a.del_flag=2
             <if test="record.memberId != null">
diff --git a/src/main/resources/mapper/modules/MallShoppingCartMapper.xml b/src/main/resources/mapper/modules/MallShoppingCartMapper.xml
index 3acd27d..ac1796e 100644
--- a/src/main/resources/mapper/modules/MallShoppingCartMapper.xml
+++ b/src/main/resources/mapper/modules/MallShoppingCartMapper.xml
@@ -13,7 +13,7 @@
     </resultMap>
     
     <select id="selectCartGoodsList" resultMap="ShoppingCartMap">
-        select * from mall_shopping_cart where member_id=#{memberId}
+        select * from mall_shopping_cart where member_id=#{memberId} and type = #{type}
     </select>
 
     <select id="selectCartGoodsBySkuId" resultType="cc.mrbird.febs.mall.entity.MallShoppingCart">
diff --git a/src/main/resources/mapper/modules/MallVipBenefitsMapper.xml b/src/main/resources/mapper/modules/MallVipBenefitsMapper.xml
new file mode 100644
index 0000000..f04bd59
--- /dev/null
+++ b/src/main/resources/mapper/modules/MallVipBenefitsMapper.xml
@@ -0,0 +1,59 @@
+<?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="cc.mrbird.febs.vip.mapper.MallVipBenefitsMapper">
+
+    <resultMap id="VipBenefitsMap" type="cc.mrbird.febs.vip.entity.MallVipBenefits">
+        <id property="id" column="id" />
+        <result property="name" column="name" />
+        <result property="type" column="type" />
+        <result property="gainType" column="gain_type" />
+        <result property="icon" column="icon" />
+        <result property="scoreMultiple" column="score_multiple" />
+        <result property="remark" column="remark" />
+
+        <collection property="details" ofType="cc.mrbird.febs.vip.entity.MallVipBenefitsDetails">
+            <id property="id" column="c_id" />
+            <result property="image" column="image" />
+            <result property="isClick" column="is_click" />
+            <result property="linkType" column="link_type" />
+            <result property="content" column="content" />
+            <result property="benefitsId" column="benefits_id" />
+            <result property="seq" column="seq" />
+        </collection>
+    </resultMap>
+
+    <select id="selectVipBenefitsListInPage" resultType="cc.mrbird.febs.vip.entity.MallVipBenefits">
+        select * from mall_vip_benefits
+    </select>
+
+    <select id="selectVipBenefitsById" resultMap="VipBenefitsMap">
+        select
+            benefits.*,
+            benefitsDetail.id c_id
+            ,benefitsDetail.image
+            ,benefitsDetail.is_click
+            ,benefitsDetail.link_type
+            ,benefitsDetail.content
+            ,benefitsDetail.seq
+        from mall_vip_benefits benefits
+            left join mall_vip_benefits_details benefitsDetail on benefits.id=benefitsDetail.benefits_id
+        where benefits.id=#{id}
+    </select>
+
+    <select id="selectVipBenefitsByIds" resultMap="VipBenefitsMap">
+        select
+            benefits.*,
+            benefitsDetail.id c_id
+             ,benefitsDetail.image
+             ,benefitsDetail.is_click
+             ,benefitsDetail.link_type
+             ,benefitsDetail.content
+             ,benefitsDetail.seq
+        from mall_vip_benefits benefits
+                 left join mall_vip_benefits_details benefitsDetail on benefits.id=benefitsDetail.benefits_id
+        where benefits.id in
+        <foreach collection="list" open="(" close=")" separator=",">
+            #{item}
+        </foreach>
+    </select>
+</mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/modules/MallVipConfigMapper.xml b/src/main/resources/mapper/modules/MallVipConfigMapper.xml
new file mode 100644
index 0000000..57a7c24
--- /dev/null
+++ b/src/main/resources/mapper/modules/MallVipConfigMapper.xml
@@ -0,0 +1,58 @@
+<?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="cc.mrbird.febs.vip.mapper.MallVipConfigMapper">
+
+    <resultMap id="vipConfigMap" type="cc.mrbird.febs.vip.entity.MallVipConfig">
+        <id property="id" column="id" />
+        <result property="name" column="name" />
+        <result property="thumb" column="thumb" />
+        <result property="level" column="level" />
+        <result property="validTime" column="valid_time" />
+        <result property="validType" column="valid_type" />
+        <result property="type" column="type" />
+        <result property="code" column="code" />
+        <result property="amount" column="amount" />
+        <result property="times" column="times" />
+        <result property="targetId" column="target_id" />
+
+        <collection property="benefits" ofType="cc.mrbird.febs.vip.entity.MallVipBenefits">
+            <id property="id" column="c_id" />
+            <result property="name" column="c_name" />
+            <result property="icon" column="c_icon" />
+
+            <collection property="details" ofType="cc.mrbird.febs.vip.entity.MallVipBenefitsDetails">
+                <id property="id" column="d_id" />
+            </collection>
+        </collection>
+    </resultMap>
+
+    <select id="findVipConfigListInPage" resultType="cc.mrbird.febs.vip.entity.MallVipConfig">
+        select * from mall_vip_config
+    </select>
+
+    <select id="selectVipConfigList" resultMap="vipConfigMap">
+        select
+            config.*
+            ,benefits.id c_id
+            ,benefits.name c_name
+            ,benefits.icon c_icon
+            ,details.id d_id
+        from mall_vip_config config
+            inner join mall_vip_config_benefits configBenefits on config.id=configBenefits.config_id
+            inner join mall_vip_benefits benefits on configBenefits.benefits_id=benefits.id
+            left join mall_vip_benefits_details details on benefits.id = details.benefits_id
+        order by level
+    </select>
+
+    <select id="selectVipConfigByCode" resultMap="vipConfigMap">
+        select
+            config.*
+             ,benefits.id c_id
+             ,benefits.name c_name
+             ,benefits.icon c_icon
+        from mall_vip_config config
+                 inner join mall_vip_config_benefits configBenefits on config.id=configBenefits.config_id
+                 inner join mall_vip_benefits benefits on configBenefits.benefits_id=benefits.id
+        where config.code=#{code}
+    </select>
+</mapper>
\ No newline at end of file
diff --git a/src/main/resources/templates/febs/views/modules/mallMember/mallMemberList.html b/src/main/resources/templates/febs/views/modules/mallMember/mallMemberList.html
index 21bbc81..a025887 100644
--- a/src/main/resources/templates/febs/views/modules/mallMember/mallMemberList.html
+++ b/src/main/resources/templates/febs/views/modules/mallMember/mallMemberList.html
@@ -111,6 +111,7 @@
 <script type="text/html" id="toolbar">
     <div class="layui-btn-container">
         <button class="layui-btn layui-btn-normal layui-btn-sm" type="button" lay-event="updateReferer">修改推荐人</button>
+        <button class="layui-btn layui-btn-normal layui-btn-sm" type="button" lay-event="updateVipLevel">修改会员等级</button>
 <!--        <button class="layui-btn layui-btn-normal layui-btn-sm" type="button" lay-event="registMember">添加会员</button>-->
 <!--        <button class="layui-btn layui-btn-normal layui-btn-sm" type="button" lay-event="balance">拨付余额</button>-->
 <!--        <button class="layui-btn layui-btn-normal layui-btn-sm" type="button" lay-event="score">拨付赠送积分</button>-->
@@ -294,10 +295,10 @@
                     {field: 'inviteId', title: '邀请码', minWidth: 100,align:'left'},
                     {field: 'balance', title: '余额', minWidth: 100,align:'left'},
                     // {field: 'score', title: '赠送积分', minWidth: 100,align:'left'},
-                    // {field: 'prizeScore', title: '竞猜积分', minWidth: 100,align:'left'},
+                    {field: 'prizeScore', title: '积分', minWidth: 100,align:'left'},
                     // {field: 'commission', title: '佣金', minWidth: 100,align:'left'},
                     {field: 'referrerName', title: '推荐人', minWidth: 100,align:'left'},
-                    {field: 'levelName', title: '会员类型', minWidth: 100,align:'left'},
+                    {field: 'levelName', title: '会员等级', minWidth: 100,align:'left'},
                     // {field: 'referrerName', title: '推荐人', minWidth: 100,align:'left'},
                     {field: 'isSalesman', title: '推销员设置', templet: '#isSalesmanSwitch', minWidth: 100,align:'center'},
                     // {field: 'director', title: '总监', templet:'#switchDirector', minWidth: 100},
@@ -376,6 +377,27 @@
                 });
             }
 
+            if (layEvent === 'updateVipLevel') {
+                var checkData = table.checkStatus('userTable').data;
+                if (checkData.length > 1) {
+                    febs.alert.warn('每次只能修改一个用户');
+                    return;
+                }
+                // var idList = [];
+                // for (var i = 0; i < checkData.length; i++) {
+                //     idList.push(checkData[i].id);
+                // }
+                febs.modal.open('设置会员等级', 'modules/mallMember/vipLevelSetting/' + checkData[0].id, {
+                    btn: ['确认', '取消'],
+                    yes: function (index, layero) {
+                        $('#vip-level-set').find('#submit').trigger('click');
+                    },
+                    btn2: function () {
+                        layer.closeAll();
+                    }
+                });
+            }
+
             if (layEvent === 'resetPwd') {
                 febs.modal.confirm('重置登录密码', '是否重置选中账号登录密码?', function () {
                     var ids = [];
diff --git a/src/main/resources/templates/febs/views/modules/mallMember/vip-level-setting.html b/src/main/resources/templates/febs/views/modules/mallMember/vip-level-setting.html
new file mode 100644
index 0000000..434c406
--- /dev/null
+++ b/src/main/resources/templates/febs/views/modules/mallMember/vip-level-setting.html
@@ -0,0 +1,92 @@
+<style>
+    #vip-level-set {
+        padding: 20px 25px 25px 0;
+    }
+
+    #vip-level-set .layui-treeSelect .ztree li a, .ztree li span {
+        margin: 0 0 2px 3px !important;
+    }
+    #vip-level-set #data-permission-tree-block {
+        border: 1px solid #eee;
+        border-radius: 2px;
+        padding: 3px 0;
+    }
+    #vip-level-set .layui-treeSelect .ztree li span.button.switch {
+        top: 1px;
+        left: 3px;
+    }
+
+</style>
+<div class="layui-fluid" id="vip-level-set">
+    <form class="layui-form" action="" lay-filter="vip-level-set-form">
+        <div class="layui-form-item febs-hide">
+            <label class="layui-form-label febs-form-item-require">id:</label>
+            <div class="layui-input-block">
+                <input type="text" name="id">
+            </div>
+        </div>
+        <div class="layui-form-item">
+            <div class="layui-inline">
+                <label class="layui-form-label">会员等级:</label>
+                <div class="layui-input-inline">
+                    <select lay-verify="required" name="level" class="vip-level-set-level" id="levelSet">
+                        <option value="">请选择</option>
+                    </select>
+                </div>
+            </div>
+        </div>
+        <div class="layui-form-item febs-hide">
+            <button class="layui-btn" lay-submit="" lay-filter="vip-level-set-form-submit" id="submit"></button>
+        </div>
+    </form>
+</div>
+
+<script data-th-inline="javascript">
+    layui.use(['febs', 'form', 'formSelects', 'validate', 'treeSelect', 'eleTree'], function () {
+        var $ = layui.jquery,
+            febs = layui.febs,
+            layer = layui.layer,
+            formSelects = layui.formSelects,
+            treeSelect = layui.treeSelect,
+            form = layui.form,
+            eleTree = layui.eleTree,
+            vipLevelSet = [[${vipLevelSet}]],
+            $view = $('#vip-level-set'),
+            validate = layui.validate,
+            _deptTree;
+
+        form.render();
+
+        initUserValue();
+
+        function initUserValue() {
+            form.val("vip-level-set-form", {
+                "id": vipLevelSet.id,
+                "level": vipLevelSet.level
+            });
+        }
+
+        //(下拉框)
+        $.get(ctx + 'admin/vip/config/allList', function (res) {
+            var data = res.data;
+            for (var k in data)
+            {
+                $(".vip-level-set-level").append("<option value='" + data[k].code + "'>" + data[k].name + "</option>");
+            }
+            layui.use('form', function () {
+                var form = layui.form;
+                $("#levelSet").val(vipLevelSet.level)
+                form.render();
+            });
+        });
+
+        form.on('submit(vip-level-set-form-submit)', function (data) {
+            febs.post(ctx + 'admin/mallMember/vipLevelSetUpdate', data.field, function () {
+                layer.closeAll();
+                febs.alert.success('操作成功');
+                $('#febs-member-list').find('#reset').click();
+            });
+            return false;
+        });
+    });
+</script>
\ No newline at end of file
diff --git a/src/main/resources/templates/febs/views/modules/score/goodsAdd.html b/src/main/resources/templates/febs/views/modules/score/goodsAdd.html
index 9e5facf..49b5b74 100644
--- a/src/main/resources/templates/febs/views/modules/score/goodsAdd.html
+++ b/src/main/resources/templates/febs/views/modules/score/goodsAdd.html
@@ -207,31 +207,58 @@
             }
         });
 
-        var E = window.wangEditor;
-        const editorConfig = { MENU_CONF: {} };
-        editorConfig.MENU_CONF['uploadImage'] = {
-            server: '/admin/goods/uploadFileBase64',
-            fieldName : "file",
-            customInsert(res, insertFn) {
-                insertFn(res.data.src, res.data.title, '')
-            },
-        }
+        // var E = window.wangEditor;
+        // const editorConfig = { MENU_CONF: {} };
+        // editorConfig.MENU_CONF['uploadImage'] = {
+        //     server: '/admin/goods/uploadFileBase64',
+        //     fieldName : "file",
+        //     customInsert(res, insertFn) {
+        //         insertFn(res.data.src, res.data.title, '')
+        //     },
+        // }
+        //
+        // const editor = E.createEditor({
+        //     selector: '#editor-container',
+        //     config : editorConfig,
+        //     mode: 'default'
+        // });
+        //
+        // const toolbar = E.createToolbar({
+        //     editor,
+        //     selector: '#toolbar-container',
+        //     mode: 'default'
+        // });
 
-        const editor = E.createEditor({
-            selector: '#editor-container',
-            config : editorConfig,
-            mode: 'default'
-        });
-
-        const toolbar = E.createToolbar({
-            editor,
-            selector: '#toolbar-container',
-            mode: 'default'
-        });
+        const E = window.wangEditor;
+        const editor = new E('#toolbar-container', '#editor-container'); // 传入两个元素
+        editor.config.showLinkImg = false;
+        editor.config.uploadFileName = 'file';
+        editor.config.customUploadImg = function (files, insertImgFn) {
+            // files 是 input 中选中的文件列表
+            // insertImgFn 是获取图片 url 后,插入到编辑器的方法
+            // 上传图片,返回结果,将图片插入到编辑器中
+            for (let i = 0; i < files.length; i++){
+                var form = new FormData();
+                form.append("file", files[0]);
+                $.ajax({
+                    url:'/admin/goods/uploadFileBase64',
+                    type: "post",
+                    processData: false,
+                    contentType: false,
+                    data: form,
+                    dataType: 'json',
+                    success(res) {
+                        // 上传代码返回结果之后,将图片插入到编辑器中
+                        insertImgFn(res.data.src, res.data.title, '')
+                    }
+                })
+            }
+        };
+        editor.create();
 
         form.on('submit(score-goods-add-form-submit)', function (data) {
             data.field.goodsType = 2;
-            data.field.goodsDetails = editor.getHtml();
+            data.field.goodsDetails = editor.txt.html();
             $.ajax({
                 'url':ctx + 'admin/goods/addMallGoods',
                 'type':'post',
diff --git a/src/main/resources/templates/febs/views/modules/vip/coupon-select.html b/src/main/resources/templates/febs/views/modules/vip/coupon-select.html
new file mode 100644
index 0000000..31e1429
--- /dev/null
+++ b/src/main/resources/templates/febs/views/modules/vip/coupon-select.html
@@ -0,0 +1,91 @@
+<style>
+    #vip-coupon-select {
+        padding: 20px 25px 25px 0;
+    }
+
+    #vip-coupon-select .layui-treeSelect .ztree li a, .ztree li span {
+        margin: 0 0 2px 3px !important;
+    }
+    #vip-coupon-select #data-permission-tree-block {
+        border: 1px solid #eee;
+        border-radius: 2px;
+        padding: 3px 0;
+    }
+    #vip-coupon-select .layui-treeSelect .ztree li span.button.switch {
+        top: 1px;
+        left: 3px;
+    }
+    #vip-coupon-select img{
+        max-width:100px
+    }
+
+</style>
+<div class="layui-fluid" id="vip-coupon-select">
+    <form class="layui-form" action="" lay-filter="vip-coupon-select-form">
+
+        <div class="layui-form-item">
+            <label class="layui-form-label">优惠卷:</label>
+            <div class="layui-input-inline">
+                <select name="couponId" class="vip-coupon-select-category" id="couponCategarySelect" lay-filter="coupon-select">
+                    <option value="">请选择</option>
+                </select>
+            </div>
+        </div>
+
+        <div class="layui-form-item febs-hide">
+            <button class="layui-btn" lay-submit="" lay-filter="vip-coupon-select-form-submit" id="submit"></button>
+        </div>
+    </form>
+</div>
+
+<script data-th-inline="javascript">
+    layui.use(['febs', 'form', 'formSelects', 'validate', 'treeSelect', 'eleTree', 'laydate','upload'], function () {
+        var $ = layui.$,
+            febs = layui.febs,
+            layer = layui.layer,
+            formSelects = layui.formSelects,
+            treeSelect = layui.treeSelect,
+            form = layui.form,
+            laydate = layui.laydate,
+            eleTree = layui.eleTree,
+            tableIndex = [[${tableIndex}]],
+            $view = $('#vip-coupon-select'),
+            upload = layui.upload,
+            selectData,
+            couponList,
+            validate = layui.validate;
+
+        form.render();
+        laydate.render({
+            elem: '#febs-form-group-date'
+        });
+
+        formSelects.render();
+
+        //(下拉框)
+        $.get(ctx + 'admin/goods/coupon/tree', function (data) {
+            couponList = data;
+            for (var k in data)
+            {
+                $(".vip-coupon-select-category").append("<option value='" + data[k].couponId + "'>" + data[k].couponName + "</option>");
+            }
+            layui.use('form', function () {
+                var form = layui.form;
+                $("#couponCategarySelect").val('')
+                form.render();
+            });
+        });
+
+        form.on('select(coupon-select)', function(data) {
+            for(var i = 0; i<couponList.length; i++) {
+                if (data.value == couponList[i].couponId) {
+                    selectData = couponList[i];
+                }
+            }
+        });
+
+        form.on('submit(vip-coupon-select-form-submit)', function (data) {
+            parent.setCouponSelect(tableIndex, selectData)
+        });
+    });
+</script>
\ No newline at end of file
diff --git a/src/main/resources/templates/febs/views/modules/vip/goods-select-list.html b/src/main/resources/templates/febs/views/modules/vip/goods-select-list.html
new file mode 100644
index 0000000..1b33eab
--- /dev/null
+++ b/src/main/resources/templates/febs/views/modules/vip/goods-select-list.html
@@ -0,0 +1,233 @@
+<div class="layui-fluid layui-anim febs-anim" id="febs-select-goods" lay-title="商品列表">
+    <div class="layui-row febs-container">
+        <div class="layui-col-md12">
+            <div class="layui-tab layui-tab-brief" lay-filter="goods-select-tab">
+                <ul class="layui-tab-title">
+                    <li class="layui-this">付费商品</li>
+                    <li>积分商品</li>
+                </ul>
+                <div class="layui-tab-content">
+                    <div class="layui-tab-item layui-show">
+                        <div class="layui-card">
+                            <div class="layui-card-body febs-table-full">
+                                <form class="layui-form layui-table-form" lay-filter="goods-select-table-form" id="form">
+                                    <div class="layui-row">
+                                        <div class="layui-col-md10">
+                                            <div class="layui-form-item">
+                                                <div class="layui-inline">
+                                                    <label class="layui-form-label layui-form-label-sm">商品名称</label>
+                                                    <div class="layui-input-inline">
+                                                        <input type="text" placeholder="商品名称" name="goodsName" autocomplete="off" class="layui-input">
+                                                    </div>
+                                                </div>
+                                            </div>
+                                        </div>
+                                        <div class="layui-col-md2 layui-col-sm12 layui-col-xs12 table-action-area">
+                                            <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-blue-plain table-action" id="query">
+                                                <i class="layui-icon">&#xe848;</i>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </form>
+                                <table lay-filter="goodsListTable" id="goodsListTable" lay-data="{id: 'goodsListTable'}"></table>
+                            </div>
+                        </div>
+                    </div>
+
+                    <div class="layui-tab-item">
+                        <div class="layui-card">
+                            <div class="layui-card-body febs-table-full" id="scoreForm">
+                                <form class="layui-form layui-table-form" lay-filter="goods-select-table-form">
+                                    <div class="layui-row">
+                                        <div class="layui-col-md10">
+                                            <div class="layui-form-item">
+                                                <div class="layui-inline">
+                                                    <label class="layui-form-label layui-form-label-sm">商品名称</label>
+                                                    <div class="layui-input-inline">
+                                                        <input type="text" placeholder="商品名称" name="goodsName" autocomplete="off" class="layui-input">
+                                                    </div>
+                                                </div>
+                                            </div>
+                                        </div>
+                                        <div class="layui-col-md2 layui-col-sm12 layui-col-xs12 table-action-area">
+                                            <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-blue-plain table-action" id="scoreQuery">
+                                                <i class="layui-icon">&#xe848;</i>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </form>
+                                <table lay-filter="scoreGoodsListTable" id="scoreGoodsListTable" lay-data="{id: 'scoreGoodsListTable'}"></table>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <div class="layui-form-item febs-hide">
+            <button class="layui-btn" id="goods-select-form-submit"></button>
+            <button class="layui-btn" id="goods-select-close"></button>
+        </div>
+    </div>
+</div>
+<style type="text/css">
+    .layui-table-cell{
+        text-align:center;
+        height: auto;
+        white-space: nowrap; /*文本不会换行,在同一行显示*/
+        overflow: hidden; /*超出隐藏*/
+        text-overflow: ellipsis; /*省略号显示*/
+    }
+    .layui-table img{
+        max-width:100px
+    }
+    ::-webkit-scrollbar {
+        height: 20px !important;
+        background-color: #f4f4f4;
+    }
+</style>
+<script type="text/html" id="isSkuFormat">
+    {{# if(d.isSku === 1) { }}
+        <span>是</span>
+    {{# } else { }}
+        <span>否</span>
+    {{# } }}
+</script>
+<script type="text/html" id="goodsTypeFormat">
+    {{# if(d.isNormal == 1) { }}
+        <span>普通商品</span>
+    {{# } else { }}
+        <span>套餐</span>
+    {{# } }}
+</script>
+<style>
+    .layui-form-onswitch {
+        background-color: #5FB878 !important;
+    }
+</style>
+<!-- 表格操作栏 end -->
+<script data-th-inline="javascript" type="text/javascript">
+    // 引入组件并初始化
+    layui.use([ 'jquery', 'form', 'table', 'febs'], function () {
+        var $ = layui.jquery,
+            febs = layui.febs,
+            form = layui.form,
+            table = layui.table,
+            element = layui.element,
+            $view = $('#febs-select-goods'),
+            $query = $view.find('#query'),
+            $searchForm = $view.find('#form'),
+            $scoreSearchForm = $view.find('#scoreForm'),
+            $scoreQuery = $view.find('#scoreQuery'),
+            sortObject = {field: 'isSale', type: 'asc'},
+            tableIns,
+            tableIndex = [[${tableIndex}]],
+            tableSelect = 'goodsListTable',
+            scoreTableIns;
+
+        form.render();
+        let currPageGoods = 1;//首先默认值为1,防止出错
+        //获取当前页
+        currPageGoods = $view.find(".layui-laypage-em").next().html();
+        // 表格初始化
+        initTable();
+        initScoreTable();
+
+        // 查询按钮
+        $query.on('click', function () {
+            var params = $.extend(getQueryParams($searchForm), {field: sortObject.field, order: sortObject.type});
+            tableIns.reload({where: params, page: {curr: 1}});
+        });
+
+        // 查询按钮
+        $scoreQuery.on('click', function () {
+            var params = $.extend(getQueryParams($scoreSearchForm), {field: sortObject.field, order: sortObject.type});
+            scoreTableIns.reload({where: params, page: {curr: 1}});
+        });
+
+        function initTable() {
+            var tableFeilds = [
+                {type: 'radio', title: ''},
+                {field: 'goodsName', title: '商品名称', minWidth: 140,align:'left'},
+                {field: 'thumb', title: '缩略图',
+                    templet: function (d) {
+                        return '<a lay-event="seeImgThumb"><img id="seeImgThumb'+d.id+'" src="'+d.thumb+'" alt=""></a>';
+                    }, minWidth: 150,align:'center'},
+                {field: 'categaryName', title: '分类', minWidth: 140,align:'left'},
+                {templet:"#goodsTypeFormat",  title: '商品类型', minWidth: 140,align:'left'},
+                {field: 'presentPrice', title: '现价', minWidth: 100,align:'left'},
+                {field: 'originalPrice', title: '原价', minWidth: 100,align:'left'},
+                {field: 'stock', title: '商品库存', minWidth: 100,align:'left'},
+                {field: 'skuVolume', title: '商品销量', minWidth: 100,align:'left'},
+            ];
+
+            tableIns = febs.table.init({
+                elem: $("#goodsListTable"),
+                id: 'goodsListTable',
+                url: ctx + 'admin/goods/goodsList?goodsType=1&isSale=1',
+                cols: [tableFeilds]
+            });
+        }
+
+        // table.on('row(goodsListTable)', function(obj){
+        //     var data = obj.data; // 获取当前行数据
+        //
+        //     console.log(obj)
+        //     // obj.setRowChecked({
+        //     //     type: 'radio'
+        //     // });
+        // });
+
+        function initScoreTable() {
+            var scoreFields = [
+                {type: 'radio', title: ''},
+                {field: 'goodsName', title: '商品名称', minWidth: 140,align:'left'},
+                {field: 'thumb', title: '缩略图',
+                    templet: function (d) {
+                        return '<a lay-event="seeImgThumb"><img id="seeImgThumb'+d.id+'" src="'+d.thumb+'" alt=""></a>';
+                    }, minWidth: 150,align:'center'},
+                {field: 'categaryName', title: '分类', minWidth: 140,align:'left'},
+                {field: 'presentPrice', title: '现价', minWidth: 100,align:'left'},
+                {field: 'originalPrice', title: '原价', minWidth: 100,align:'left'},
+                {field: 'stock', title: '商品库存', minWidth: 100,align:'left'},
+                {field: 'skuVolume', title: '商品销量', minWidth: 100,align:'left'},
+            ]
+
+            scoreTableIns = febs.table.init({
+                elem: $("#scoreGoodsListTable"),
+                id: 'scoreGoodsListTable',
+                url: ctx + 'admin/goods/goodsList?goodsType=2&isSale=1',
+                cols: [scoreFields]
+            });
+        }
+
+        // 获取查询参数
+        function getQueryParams(elem) {
+            return {
+                goodsName: elem.find('input[name="goodsName"]').val().trim(),
+            };
+        }
+
+        $("#goods-select-form-submit").on('click', function() {
+            var checkData = table.checkStatus(tableSelect).data;
+            if (checkData.length > 0) {
+                if (tableIndex != -1) {
+                    parent.setGoodsSelect(tableIndex, checkData[0]);
+                } else {
+                    parent.setConfigGoodsSelect(tableIndex, checkData[0]);
+                }
+            }
+        })
+
+        element.on('tab(goods-select-tab)', function(data) {
+            if (data.index == 0) {
+                tableSelect = 'goodsListTable';
+            }
+
+            if (data.index == 1) {
+                tableSelect = 'scoreGoodsListTable';
+            }
+        });
+
+    })
+</script>
\ No newline at end of file
diff --git a/src/main/resources/templates/febs/views/modules/vip/vip-setting.html b/src/main/resources/templates/febs/views/modules/vip/vip-setting.html
new file mode 100644
index 0000000..171c0b3
--- /dev/null
+++ b/src/main/resources/templates/febs/views/modules/vip/vip-setting.html
@@ -0,0 +1,245 @@
+<div class="layui-fluid layui-anim febs-anim" id="vip-setting" lay-title="会员设置">
+    <div class="layui-row layui-col-space8 febs-container">
+        <form class="layui-form" action="" lay-filter="vip-setting-form">
+            <div class="layui-card">
+                <div class="layui-card-body">
+                    <blockquote class="layui-elem-quote blue-border">会员日设置</blockquote>
+                    <div class="layui-form-item">
+                        <div class="layui-col-lg6">
+                            <label class="layui-form-label ">会员日:</label>
+                            <div class="layui-input-block">
+                                <input type="text" name="vipDate" id="vipDate" autocomplete="off" class="layui-input" >
+                            </div>
+                        </div>
+                    </div>
+
+
+                    <blockquote class="layui-elem-quote blue-border">失活客户优惠券</blockquote>
+
+                    <div class="layui-form-item">
+                        <div class="layui-col-lg6">
+                            <table id="unAliveCouponItem" lay-filter="unAliveCouponItem"></table>
+                        </div>
+                    </div>
+                </div>
+
+                <div class="layui-card-footer">
+                    <button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="vip-setting-form-submit" id="submit">保存</button>
+                </div>
+            </div>
+        </form>
+    </div>
+</div>
+<style>
+    .layui-form-label {
+        width: 120px;
+    }
+
+    .layui-form-item .layui-input-block {
+        margin-left: 150px;
+    }
+
+    .layui-table-form .layui-form-item {
+        margin-bottom: 20px !important;
+    }
+
+    .layui-table-cell {
+        height:auto;
+    }
+</style>
+
+<script type="text/html" id="toolbar">
+    <div class="layui-btn-container">
+        <button class="layui-btn layui-btn-sm" type="button" lay-event="addCoupon">新增</button>
+        <button class="layui-btn layui-btn-danger layui-btn-sm" type="button" lay-event="delCoupon">删除</button>
+    </div>
+</script>
+
+<script type="text/html" id="detailsEvent">
+    <input type="text" name="couponName" autocomplete="off" data-index="{{d.index}}" value="{{d.couponName}}" class="layui-input couponSelect" readonly>
+    <input type="text" name="couponId" autocomplete="off" value="{{d.couponId}}" class="layui-input couponId febs-hide" readonly>
+</script>
+<script data-th-inline="javascript" type="text/javascript">
+    layui.use(['dropdown', 'jquery', 'validate', 'febs', 'form', 'eleTree', 'laydate', 'table'], function () {
+        var $ = layui.jquery,
+            febs = layui.febs,
+            form = layui.form,
+            table = layui.table,
+            laydate = layui.laydate,
+            unAliveCouponItemsData = [],
+            vipSetting = [[${vipSetting}]],
+            validate = layui.validate,
+            $view = $('#vip-setting');
+
+        form.verify(validate);
+
+
+        form.render();
+
+        laydate.render({
+            elem: '#vipDate'
+            ,format: 'MM-dd'
+        });
+
+        table.render({
+            elem: '#unAliveCouponItem'
+            ,toolbar:"#toolbar"
+            ,cols: [[ //表头
+                {type: 'checkbox'}
+                , {field: 'day', title: '失活天数', edit:'text', width:250}
+                ,{templet: '#detailsEvent', title: '优惠券', width:350}
+            ]]
+            ,data: []
+        });
+
+        table.on('toolbar(unAliveCouponItem)', function(obj){
+            var data = obj.data;
+
+            if(obj.event === 'delCoupon'){
+                var hasData = table.cache['unAliveCouponItem'];
+                var checkData = table.checkStatus('unAliveCouponItem').data;
+
+                if (checkData.length <= 0) {
+                    febs.alert.warn('请选择删除数据');
+                    return;
+                }
+
+                for (let i = 0; i < checkData.length; i++) {
+                    var delData = checkData[i];
+                    for (let j = 0; j < hasData.length; j++) {
+                        if (hasData[j].index == delData.index) {
+                            hasData.splice(j, 1);
+                            break;
+                        }
+                    }
+                }
+
+                for (let i = 0; i < hasData.length; i++) {
+                    hasData[i].index = i + 1;
+                }
+
+                unAliveCouponItemsData=hasData;
+                reloadTable(hasData);
+            }
+
+            if(obj.event === 'addCoupon'){
+                var addData = {};
+                addTableDate(addData);
+            }
+        });
+
+        form.on('submit(vip-setting-form-submit)', function (data) {
+            data.field.items = unAliveCouponItemsData;
+            $.ajax({
+                'url':ctx + 'admin/vip/config/vipSetting',
+                'type':'post',
+                'dataType':'json',
+                'headers' : {'Content-Type' : 'application/json;charset=utf-8'}, //接口json格式
+                'traditional': true,//ajax传递数组必须添加属性
+                'data':JSON.stringify(data.field),
+                'success':function (data) {
+                    if(data.code==200){
+                        febs.alert.success("设置成功");
+                    }else{
+                        febs.alert.warn(data.message);
+                    }
+                },
+                'error':function () {
+                    febs.alert.warn('服务器繁忙');
+                }
+            })
+            window.location.reload();
+            return false;
+        });
+
+        table.on('edit(unAliveCouponItem)', function(obj){
+            var value = obj.value //得到修改后的值
+                ,data = obj.data //得到所在行所有键值
+                ,field = obj.field; //得到字段
+
+            for (let i = 0; i < unAliveCouponItemsData.length; i++) {
+                if (unAliveCouponItemsData[i].index == data.index) {
+                    unAliveCouponItemsData[i] = data;
+                }
+            }
+        });
+
+        function addTableDate(data) {
+            var hasData = table.cache['unAliveCouponItem'];
+
+            data.index = hasData.length + 1;
+            data.couponName = ''
+            data.couponId = ''
+            data.day = ''
+            unAliveCouponItemsData.push(data);
+
+            reloadTable(unAliveCouponItemsData);
+            return data.index;
+        }
+
+        function reloadTable(data) {
+            table.reload('unAliveCouponItem', {
+                data : data
+            });
+
+            listenerCouponSelect();
+        }
+
+        function listenerCouponSelect() {
+            $(".couponSelect").each(function(index, elem) {
+                var dataIndex = $(this).attr('data-index');
+
+                $(this).off('click')
+                $(this).on('click', function() {
+                    febs.modal.open('选择优惠券', 'modules/vip/config/couponSelect/' + dataIndex, {
+                        btn: ['提交', '取消'],
+                        yes: function (index, layero) {
+                            $('#vip-coupon-select').find('#submit').trigger('click');
+                            layer.close(index);
+                        },
+                        btn2: function () {
+                        }
+                    });
+                })
+            });
+        }
+
+        window.setCouponSelect = function(tableIndex, data) {
+            var hasData = table.cache['unAliveCouponItem'];
+
+            for(var i = 0; i<hasData.length; i++) {
+                if (tableIndex == hasData[i].index) {
+                    hasData[i].couponId = data.couponId;
+                    hasData[i].couponName = data.couponName
+                }
+            }
+
+            unAliveCouponItemsData = hasData;
+            $(".couponSelect").each(function(index, elem) {
+                var dataIndex = $(this).attr('data-index');
+                if (dataIndex == tableIndex) {
+                    $(this).val(data.couponName);
+                    $(this).next().val(data.couponId);
+                }
+            });
+        }
+
+
+        initVipSettingValue();
+        function initVipSettingValue() {
+            form.val("vip-setting-form", {
+                "vipDate": vipSetting.vipDate,
+            });
+
+            var details = vipSetting.items;
+            if (details) {
+                for(var i = 0; i < details.length; i++) {
+                    details[i].index = i + 1;
+                }
+
+                unAliveCouponItemsData = details;
+                reloadTable(details);
+            }
+        }
+    });
+</script>
\ No newline at end of file
diff --git a/src/main/resources/templates/febs/views/modules/vip/vipBenefits-add.html b/src/main/resources/templates/febs/views/modules/vip/vipBenefits-add.html
new file mode 100644
index 0000000..b1cb41b
--- /dev/null
+++ b/src/main/resources/templates/febs/views/modules/vip/vipBenefits-add.html
@@ -0,0 +1,489 @@
+<div class="layui-fluid layui-anim febs-anim" id="febs-vipBenefits-add" lay-title="新增会员权益">
+    <div class="layui-row febs-container">
+        <div class="layui-col-md12">
+            <div class="layui-fluid" id="act-add">
+                <form class="layui-form" action="" lay-filter="vipBenefits-add-form">
+                    <div class="layui-tab-item layui-show">
+                        <blockquote class="layui-elem-quote blue-border">基本信息设置</blockquote>
+                        <div class="layui-row layui-col-space10 layui-form-item">
+                            <div class="layui-col-lg6">
+                                <label class="layui-form-label febs-form-item-require">权益名称:</label>
+                                <div class="layui-input-block">
+                                    <input type="text" name="name" lay-verify="required"
+                                           placeholder="" autocomplete="off" class="layui-input">
+                                </div>
+                            </div>
+                        </div>
+
+                        <div class="layui-form-item">
+                            <div class="layui-col-lg6">
+                                <label class="layui-form-label febs-form-item-require">权益生效类型</label>
+                                <div class="layui-input-block">
+                                    <select name="gainType" class="gain-type" lay-filter="gain-type-select">
+                                        <option value="1">会员日</option>
+                                        <option value="2">会员生日</option>
+                                    </select>
+                                </div>
+                            </div>
+                        </div>
+
+                        <div class="layui-form-item">
+                            <div class="layui-col-lg6">
+                                <label class="layui-form-label febs-form-item-require">权益类型</label>
+                                <div class="layui-input-block">
+                                    <select name="type" class="benefits-type" lay-filter="benefits-type-select">
+                                        <option value="1">积分</option>
+                                        <option value="2">其他</option>
+                                    </select>
+                                </div>
+                            </div>
+
+                            <div class="layui-col-lg6" id="scoreMultiple">
+                                <label class="layui-form-label febs-form-item-require">积分倍数:</label>
+                                <div class="layui-input-block">
+                                    <input type="text" name="scoreMultiple" placeholder="" autocomplete="off" class="layui-input">
+                                </div>
+                            </div>
+                        </div>
+
+                        <div class="layui-form-item">
+                            <label class="layui-form-label febs-form-item-require">权益ICON</label>
+                            <div class="layui-input-block">
+                                <div class="layui-upload">
+                                    <button type="button" class="layui-btn layui-btn-normal layui-btn" id="test2">上传</button>
+                                    <blockquote class="layui-elem-quote layui-quote-nm" style="margin-top: 10px;">
+                                        <div class="layui-upload-list">
+                                            <img class="layui-upload-img" id="demo2" style="width: 100px" >
+                                        </div>
+                                    </blockquote>
+                                </div>
+                            </div>
+                        </div>
+
+                        <div class="layui-form-item febs-hide">
+                            <label class="layui-form-label">缩略图链接:</label>
+                            <div class="layui-input-block">
+                                <input type="text" id="benefitsIcon" lay-verify="required" name="icon" autocomplete="off" class="layui-input" readonly>
+                            </div>
+                        </div>
+
+                        <div class="layui-form-item">
+                            <label class="layui-form-label">备注:</label>
+                            <div class="layui-input-block">
+                                <label>
+                                    <textarea name="remark" rows="5" autocomplete="off" class="layui-textarea" ></textarea>
+                                </label>
+                            </div>
+                        </div>
+
+                        <blockquote class="layui-elem-quote blue-border">权益详情页面设置</blockquote>
+                        <div class="layui-row layui-col-space10 layui-form-item">
+                            <div class="layui-col-lg3">
+                                <label class="layui-form-label">是否可点击</label>
+                                <div class="layui-input-block">
+                                    <input type="radio" name="isClick" value="1" title="是" lay-filter="isClick"/>
+                                    <input type="radio" name="isClick" value="2" title="否" lay-filter="isClick" checked />
+                                </div>
+                            </div>
+                            <div class="layui-col-lg3 febs-hide" id="linkTypeDiv">
+                                <label class="layui-form-label febs-form-item-require">点击类型</label>
+                                <div class="layui-input-block">
+                                    <select name="linkType" class="linkType" lay-filter="link-type-select">
+                                        <option value="">请选择</option>
+                                        <option value="1">链接</option>
+                                        <option value="2">领取商品</option>
+                                        <option value="3">优惠券</option>
+                                    </select>
+                                </div>
+                            </div>
+                            <div class="layui-col-lg6">
+                                <button type="button" class="layui-btn layui-btn-normal layui-btn" id="addBenefits" >添加</button>
+                            </div>
+
+                            <div class="layui-form-item">
+                                <table id="benefitsDetailsItem" lay-filter="benefitsDetailsItem"></table>
+                            </div>
+                        </div>
+                    </div>
+
+                    <div class="layui-form-item febs-hide">
+                        <button class="layui-btn" lay-submit="" lay-filter="vipBenefits-add-form-submit" id="submit">保存</button>
+                    </div>
+                </form>
+            </div>
+        </div>
+    </div>
+</div>
+<style>
+    .blue-border {
+        border-left-color: #2db7f5;
+        font-size: 18px;
+    }
+    .layui-table-cell {
+        height:auto;
+    }
+</style>
+<script type="text/html" id="toolbar">
+    <div class="layui-btn-container">
+        <button class="layui-btn layui-btn-danger layui-btn-sm" type="button" lay-event="delAct">删除</button>
+    </div>
+</script>
+<script type="text/html" id="awardtableImgUpload">
+    <div class="layui-upload">
+        <button type="button" class="layui-btn layui-btn-normal layui-btn-xs sku-img" id="awardImg{{d.index}}">上传</button></br>
+        <img class="layui-upload-img" id="awardImageUrls{{d.index}}" style="width: 100px; display:none;" src="{{d.image}}" >
+        <input type="text" id="awardImage{{d.index}}" name="awardImage{{d.index}}" autocomplete="off" value="{{d.image}}" class="layui-input febs-hide">
+    </div>
+</script>
+
+<!--<script type="text/html" id="seqInput">-->
+<!--    <input type="text" name="seq" autocomplete="off" class="layui-input">-->
+<!--</script>-->
+<!-- 表格操作栏 end -->
+<script data-th-inline="javascript">
+    layui.use(['febs', 'form', 'formSelects', 'validate', 'treeSelect', 'eleTree','dropdown', 'laydate', 'layedit', 'upload', 'element', 'table', 'xmSelect'], function () {
+        var $ = layui.jquery,
+            febs = layui.febs,
+            layer = layui.layer,
+            table = layui.table,
+            formSelects = layui.formSelects,
+            treeSelect = layui.treeSelect,
+            form = layui.form,
+            laydate = layui.laydate,
+            eleTree = layui.eleTree,
+            $view = $('#febs-vip-benefits'),
+            layedit = layui.layedit,
+            upload = layui.upload,
+            validate = layui.validate,
+            element = layui.element;
+
+        form.render();
+        formSelects.render();
+
+        //图片上传
+        upload.render({
+            elem: '#test2'
+            ,url: ctx + 'admin/goods/uploadFileBase64' //改成您自己的上传接口
+            ,done: function(res){
+                $('#demo2').attr('src', res.data.src);
+                $("#benefitsIcon").val(res.data.src);
+            }
+        });
+
+        var tableBenefitsItemsData=[];
+        var tableIns = table.render({
+            elem: '#benefitsDetailsItem'
+            ,limit:999
+            ,toolbar:"#toolbar"
+            ,defaultToolbar:[]
+            ,cols: [[ //表头
+                {type: 'checkbox'}
+                ,{field: 'index', title: '序号', width:70}
+                ,{field: 'isClick', title: '是否可点击',
+                    templet: function (d) {
+                        if (d.isClick == '1') {
+                            return '<span>是</span>'
+                        } else if (d.isClick == '2') {
+                            return '<span>否</span>'
+                        }else{
+                            return ''
+                        }
+                    }, minWidth: 80,align:'center'}
+                ,{field: 'seq', title: '排序', edit:'text'}
+                ,{templet: '#awardtableImgUpload', title: '详情图片', width:150}
+                ,{templet: '#detailsEvent', title: '操作对应属性'}
+                ,{field: 'linkType', title: '类型',
+                    templet: function (d) {
+                        if (d.linkType == '1') {
+                            return '<span>链接</span>'
+                        } else if (d.linkType == '2') {
+                            return '<span>指定商品</span>'
+                        }else if (d.linkType == '3') {
+                            return '<span>优惠券</span>'
+                        }else{
+                            return ''
+                        }
+                    }, minWidth: 80,align:'center'}
+            ]]
+            ,data: []
+        });
+
+        table.on('toolbar(benefitsDetailsItem)', function(obj){
+            var data = obj.data;
+
+            var hasData = table.cache['benefitsDetailsItem'];
+            var checkData = table.checkStatus('benefitsDetailsItem').data;
+
+            if (checkData.length <= 0) {
+                febs.alert.warn('请选择删除数据');
+                return;
+            }
+            if(obj.event === 'delAct'){
+                for (let i = 0; i < checkData.length; i++) {
+                    var delData = checkData[i];
+                    for (let j = 0; j < hasData.length; j++) {
+                        if (hasData[j].index == delData.index) {
+                            hasData.splice(j, 1);
+                            break;
+                        }
+                    }
+                }
+
+                for (let i = 0; i < hasData.length; i++) {
+                    hasData[i].index = i + 1;
+                }
+
+                tableBenefitsItemsData=hasData;
+                reloadTable(hasData);
+            }
+        });
+
+        function addTableDate(data) {
+            var hasData = table.cache['benefitsDetailsItem'];
+
+            data.index = hasData.length + 1;
+            data.contentName = ''
+            data.content = ''
+            tableBenefitsItemsData.push(data);
+
+            reloadTable(tableBenefitsItemsData);
+            return data.index;
+        }
+
+        function reloadTable(data) {
+            table.reload('benefitsDetailsItem', {
+                data : data
+            });
+
+            for (let i = 0; i < data.length; i++) {
+                if (data[i].image) {
+                    $('#awardImageUrls'+ (i+1)).css('display','block');
+                }
+                // 重新绑定图片上传
+                bindUpload(i+1);
+
+                listenerLinkContent();
+                listenerGoodsSelect();
+                listenerCouponSelect();
+            }
+        }
+
+        table.on('edit(benefitsDetailsItem)', function(obj){
+            var value = obj.value //得到修改后的值
+                ,data = obj.data //得到所在行所有键值
+                ,field = obj.field; //得到字段
+
+            for (let i = 0; i < tableBenefitsItemsData.length; i++) {
+                if (tableBenefitsItemsData[i].index == data.index) {
+                    tableBenefitsItemsData[i] = data;
+                }
+            }
+        });
+
+        function listenerLinkContent() {
+            var hasData = table.cache['benefitsDetailsItem'];
+
+            $(".linkContent").each(function(index, elem) {
+                var dataIndex = $(this).attr('data-index');
+                var $this = $(this);
+                $(this).off('blur')
+                $(this).on('blur', function() {
+                    var data = $this.val();
+                    hasData[dataIndex - 1].content = data;
+
+                    tableBenefitsItemsData = hasData;
+                })
+            });
+        }
+
+        function listenerGoodsSelect() {
+            var hasData = table.cache['benefitsDetailsItem'];
+
+            $(".goodsSelect").each(function(index, elem) {
+                var dataIndex = $(this).attr('data-index');
+                $(this).off('click')
+                $(this).on('click', function() {
+                    febs.modal.open('选择商品', 'modules/vip/config/goodsSelect/' + dataIndex, {
+                        btn: ['提交', '取消'],
+                        yes: function (index, layero) {
+                            $('#febs-select-goods').find('#goods-select-form-submit').trigger('click');
+                            layer.close(index);
+                        },
+                        btn2: function () {
+                        }
+                    });
+                })
+            });
+        }
+
+        function listenerCouponSelect() {
+            $(".couponSelect").each(function(index, elem) {
+                var dataIndex = $(this).attr('data-index');
+
+                $(this).off('click')
+                $(this).on('click', function() {
+                    febs.modal.open('选择优惠券', 'modules/vip/config/couponSelect/' + dataIndex, {
+                        btn: ['提交', '取消'],
+                        yes: function (index, layero) {
+                            $('#vip-coupon-select').find('#submit').trigger('click');
+                            layer.close(index);
+                        },
+                        btn2: function () {
+                        }
+                    });
+                })
+            });
+        }
+
+        $('#addBenefits').on('click', function (){
+            var isClickVal = $("input[name='isClick']:checked").val();
+            var linkTypeVal = $("select[name='linkType']").val();
+            if(isClickVal == 1 && (linkTypeVal == null || linkTypeVal == "")) {
+                febs.alert.warn('链接类型不能为空');
+                return false;
+            }
+
+
+            var data = {};
+
+            if (isClickVal == 1) {
+                data.linkType = linkTypeVal;
+            }
+            data.isClick = isClickVal;
+            addTableDate(data);
+
+            if (linkTypeVal == 1) {
+                listenerLinkContent();
+            }
+
+            if (linkTypeVal == 2) {
+                listenerGoodsSelect();
+            }
+
+            if (linkTypeVal == 3) {
+                listenerCouponSelect();
+            }
+
+        });
+
+        function bindUpload(index) {
+            // 普通图片上传
+            upload.render({
+                elem: '#awardImg' + index
+                ,url: ctx + 'admin/goods/uploadFileBase64' //改成您自己的上传接口
+                ,done: function(res){
+                    febs.alert.success("上传成功");
+                    $('#awardImageUrls' + index).attr('src', res.data.src);
+                    $('#awardImageUrls'+ index).css('display','block');
+                    $('#awardImage'+ index).val(res.data.src);
+
+                    for (let i = 0; i < tableBenefitsItemsData.length; i++) {
+                        if(tableBenefitsItemsData[i].index == index) {
+                            tableBenefitsItemsData[i].image = res.data.src;
+                        }
+                    }
+
+                    reloadTable(tableBenefitsItemsData);
+                }
+            });
+        }
+
+        form.on('radio(isClick)', function(data) {
+            if (data.value == 2) {
+                $('#linkTypeDiv').hide();
+            } else {
+                $('#linkTypeDiv').show();
+            }
+        });
+
+        form.on('select(benefits-type-select)', function(data) {
+            if (data.value == 1) {
+                $('#scoreMultiple').show();
+            } else {
+                $('#scoreMultiple').hide();
+            }
+        });
+
+        form.on('submit(vipBenefits-add-form-submit)', function (data) {
+            data.field.details = tableBenefitsItemsData;
+            $.ajax({
+                'url':ctx + 'admin/vip/benefits/addOrEditBenefits',
+                'type':'post',
+                'dataType':'json',
+                'headers' : {'Content-Type' : 'application/json;charset=utf-8'}, //接口json格式
+                'traditional': true,//ajax传递数组必须添加属性
+                'data':JSON.stringify(data.field),
+                'success':function (data) {
+                    if(data.code==200){
+                        layer.closeAll();
+                        febs.alert.success(data.message);
+                        $('#febs-vip-benefits').find('#reset').click();
+                    }else{
+                        febs.alert.warn(data.message);
+                    }
+                },
+                'error':function () {
+                    febs.alert.warn('服务器繁忙');
+                }
+            })
+            return false;
+        });
+
+        window.setGoodsSelect = function(tableIndex, data) {
+            var hasData = table.cache['benefitsDetailsItem'];
+
+            for(var i = 0; i<hasData.length; i++) {
+                if (tableIndex == hasData[i].index) {
+                    hasData[i].content = data.id;
+                    hasData[i].contentName = data.goodsName
+                }
+            }
+
+            tableBenefitsItemsData = hasData;
+            $(".goodsSelect").each(function(index, elem) {
+                var dataIndex = $(this).attr('data-index');
+                if (dataIndex == tableIndex) {
+                    $(this).val(data.goodsName);
+                    $(this).next().val(data.id);
+                }
+            });
+        }
+
+        window.setCouponSelect = function(tableIndex, data) {
+            var hasData = table.cache['benefitsDetailsItem'];
+
+            for(var i = 0; i<hasData.length; i++) {
+                if (tableIndex == hasData[i].index) {
+                    hasData[i].content = data.couponId;
+                    hasData[i].contentName = data.couponName
+                }
+            }
+
+            tableBenefitsItemsData = hasData;
+            console.log(tableBenefitsItemsData)
+            $(".couponSelect").each(function(index, elem) {
+                var dataIndex = $(this).attr('data-index');
+                if (dataIndex == tableIndex) {
+                    $(this).val(data.couponName);
+                    $(this).next().val(data.couponId);
+                }
+            });
+        }
+
+    });
+</script>
+
+
+<script type="text/html" id="detailsEvent">
+    {{# if(d.isClick == 1 && d.linkType == 1){ }}
+    <input type="text" name="content" autocomplete="off" data-index="{{d.index}}" value="{{d.content}}" class="layui-input linkContent">
+    {{# } }}
+    {{# if( d.isClick == 1 && d.linkType == 2){ }}
+    <input type="text" autocomplete="off" name="contentName" data-index="{{d.index}}" value="{{d.contentName}}" class="layui-input goodsSelect" readonly>
+    <input type="text" name="content" autocomplete="off" value="{{d.content}}" class="layui-input goodsSelectId febs-hide" readonly>
+    {{# }  }}
+    {{# if(d.isClick == 1 && d.linkType == 3){ }}
+    <input type="text" name="contentName" autocomplete="off" data-index="{{d.index}}" value="{{d.contentName}}" class="layui-input couponSelect" readonly>
+    <input type="text" name="content" autocomplete="off" value="{{d.content}}" class="layui-input couponSelectId febs-hide" readonly>
+    {{# } }}
+</script>
\ No newline at end of file
diff --git a/src/main/resources/templates/febs/views/modules/vip/vipBenefits-edit.html b/src/main/resources/templates/febs/views/modules/vip/vipBenefits-edit.html
new file mode 100644
index 0000000..2330e99
--- /dev/null
+++ b/src/main/resources/templates/febs/views/modules/vip/vipBenefits-edit.html
@@ -0,0 +1,513 @@
+<div class="layui-fluid layui-anim febs-anim" id="febs-vipBenefits-edit" lay-title="编辑会员权益">
+    <div class="layui-row febs-container">
+        <div class="layui-col-md12">
+            <div class="layui-fluid" id="act-add">
+                <form class="layui-form" action="" lay-filter="vipBenefits-edit-form">
+                    <div class="layui-form-item febs-hide">
+                        <label class="layui-form-label febs-form-item-require">id:</label>
+                        <div class="layui-input-block">
+                            <input type="text" name="id">
+                        </div>
+                    </div>
+                    <div class="layui-tab-item layui-show">
+                        <blockquote class="layui-elem-quote blue-border">基本信息设置</blockquote>
+                        <div class="layui-row layui-col-space10 layui-form-item">
+                            <div class="layui-col-lg6">
+                                <label class="layui-form-label febs-form-item-require">权益名称:</label>
+                                <div class="layui-input-block">
+                                    <input type="text" name="name" lay-verify="required"
+                                           placeholder="" autocomplete="off" class="layui-input">
+                                </div>
+                            </div>
+                        </div>
+
+                        <div class="layui-form-item">
+                            <div class="layui-col-lg6">
+                                <label class="layui-form-label febs-form-item-require">权益生效类型</label>
+                                <div class="layui-input-block">
+                                    <select name="gainType" class="gain-type" lay-filter="gain-type-select">
+                                        <option value="1">会员日</option>
+                                        <option value="2">会员生日</option>
+                                    </select>
+                                </div>
+                            </div>
+                        </div>
+
+                        <div class="layui-form-item">
+                            <div class="layui-col-lg6">
+                                <label class="layui-form-label febs-form-item-require">权益类型</label>
+                                <div class="layui-input-block">
+                                    <select name="type" class="benefits-type" lay-filter="benefits-type-select">
+                                        <option value="1">积分</option>
+                                        <option value="2">其他</option>
+                                    </select>
+                                </div>
+                            </div>
+
+                            <div class="layui-col-lg6" id="scoreMultiple">
+                                <label class="layui-form-label febs-form-item-require">积分倍数:</label>
+                                <div class="layui-input-block">
+                                    <input type="text" name="scoreMultiple" placeholder="" autocomplete="off" class="layui-input">
+                                </div>
+                            </div>
+                        </div>
+
+                        <div class="layui-form-item">
+                            <label class="layui-form-label febs-form-item-require">权益ICON</label>
+                            <div class="layui-input-block">
+                                <div class="layui-upload">
+                                    <button type="button" class="layui-btn layui-btn-normal layui-btn" id="test2">上传</button>
+                                    <blockquote class="layui-elem-quote layui-quote-nm" style="margin-top: 10px;">
+                                        <div class="layui-upload-list">
+                                            <img class="layui-upload-img" id="demo2" style="width: 100px" >
+                                        </div>
+                                    </blockquote>
+                                </div>
+                            </div>
+                        </div>
+
+                        <div class="layui-form-item febs-hide">
+                            <label class="layui-form-label">缩略图链接:</label>
+                            <div class="layui-input-block">
+                                <input type="text" id="benefitsIcon" lay-verify="required" name="icon" autocomplete="off" class="layui-input" readonly>
+                            </div>
+                        </div>
+
+                        <div class="layui-form-item">
+                            <label class="layui-form-label">备注:</label>
+                            <div class="layui-input-block">
+                                <label>
+                                    <textarea name="remark" rows="5" autocomplete="off" class="layui-textarea" ></textarea>
+                                </label>
+                            </div>
+                        </div>
+
+                        <blockquote class="layui-elem-quote blue-border">权益详情页面设置</blockquote>
+                        <div class="layui-row layui-col-space10 layui-form-item">
+                            <div class="layui-col-lg3">
+                                <label class="layui-form-label">是否可点击</label>
+                                <div class="layui-input-block">
+                                    <input type="radio" name="isClick" value="1" title="是" lay-filter="isClick"/>
+                                    <input type="radio" name="isClick" value="2" title="否" lay-filter="isClick" checked />
+                                </div>
+                            </div>
+                            <div class="layui-col-lg3 febs-hide" id="linkTypeDiv">
+                                <label class="layui-form-label febs-form-item-require">点击类型</label>
+                                <div class="layui-input-block">
+                                    <select name="linkType" class="linkType" lay-filter="link-type-select">
+                                        <option value="">请选择</option>
+                                        <option value="1">链接</option>
+                                        <option value="2">领取商品</option>
+                                        <option value="3">优惠券</option>
+                                    </select>
+                                </div>
+                            </div>
+                            <div class="layui-col-lg6">
+                                <button type="button" class="layui-btn layui-btn-normal layui-btn" id="addBenefits" >添加</button>
+                            </div>
+
+                            <div class="layui-form-item">
+                                <table id="benefitsDetailsItem" lay-filter="benefitsDetailsItem"></table>
+                            </div>
+                        </div>
+                    </div>
+
+                    <div class="layui-form-item febs-hide">
+                        <button class="layui-btn" lay-submit="" lay-filter="vipBenefits-edit-form-submit" id="submit">保存</button>
+                    </div>
+                </form>
+            </div>
+        </div>
+    </div>
+</div>
+<style>
+    .blue-border {
+        border-left-color: #2db7f5;
+        font-size: 18px;
+    }
+    .layui-table-cell {
+        height:auto;
+    }
+</style>
+<script type="text/html" id="toolbar">
+    <div class="layui-btn-container">
+        <button class="layui-btn layui-btn-danger layui-btn-sm" type="button" lay-event="delAct">删除</button>
+    </div>
+</script>
+<script type="text/html" id="awardtableImgUpload">
+    <div class="layui-upload">
+        <button type="button" class="layui-btn layui-btn-normal layui-btn-xs sku-img" id="awardImg{{d.index}}">上传</button></br>
+        <img class="layui-upload-img" id="awardImageUrls{{d.index}}" style="width: 100px; display:none;" src="{{d.image}}" >
+        <input type="text" id="awardImage{{d.index}}" name="awardImage{{d.index}}" autocomplete="off" value="{{d.image}}" class="layui-input febs-hide">
+    </div>
+</script>
+<!-- 表格操作栏 end -->
+<script data-th-inline="javascript">
+    layui.use(['febs', 'form', 'formSelects', 'validate', 'treeSelect', 'eleTree','dropdown', 'laydate', 'layedit', 'upload', 'element', 'table', 'xmSelect'], function () {
+        var $ = layui.jquery,
+            febs = layui.febs,
+            layer = layui.layer,
+            table = layui.table,
+            formSelects = layui.formSelects,
+            treeSelect = layui.treeSelect,
+            form = layui.form,
+            laydate = layui.laydate,
+            eleTree = layui.eleTree,
+            $view = $('#febs-vip-benefits'),
+            layedit = layui.layedit,
+            upload = layui.upload,
+            validate = layui.validate,
+            benefitsData = [[${benefitsData}]],
+            element = layui.element;
+
+        var tableBenefitsItemsData=[];
+        form.render();
+        formSelects.render();
+
+        //图片上传
+        upload.render({
+            elem: '#test2'
+            ,url: ctx + 'admin/goods/uploadFileBase64' //改成您自己的上传接口
+            ,done: function(res){
+                $('#demo2').attr('src', res.data.src);
+                $("#benefitsIcon").val(res.data.src);
+            }
+        });
+
+        var tableIns = table.render({
+            elem: '#benefitsDetailsItem'
+            ,limit:999
+            ,toolbar:"#toolbar"
+            ,defaultToolbar:[]
+            ,cols: [[ //表头
+                {type: 'checkbox'}
+                ,{field: 'index', title: '序号', width:70}
+                ,{field: 'isClick', title: '是否可点击',
+                    templet: function (d) {
+                        if (d.isClick == '1') {
+                            return '<span>是</span>'
+                        } else if (d.isClick == '2') {
+                            return '<span>否</span>'
+                        }else{
+                            return ''
+                        }
+                    }, minWidth: 80,align:'center'}
+                ,{field: 'seq', title: '排序', edit:'text'}
+                ,{templet: '#awardtableImgUpload', title: '详情图片', width:150}
+                ,{templet: '#detailsEvent', title: '操作对应属性'}
+                ,{field: 'linkType', title: '类型',
+                    templet: function (d) {
+                        if (d.linkType == '1') {
+                            return '<span>链接</span>'
+                        } else if (d.linkType == '2') {
+                            return '<span>指定商品</span>'
+                        }else if (d.linkType == '3') {
+                            return '<span>优惠券</span>'
+                        }else{
+                            return ''
+                        }
+                    }, minWidth: 80,align:'center'}
+            ]]
+            ,data: []
+        });
+
+        table.on('toolbar(benefitsDetailsItem)', function(obj){
+            var data = obj.data;
+
+            var hasData = table.cache['benefitsDetailsItem'];
+            var checkData = table.checkStatus('benefitsDetailsItem').data;
+
+            if (checkData.length <= 0) {
+                febs.alert.warn('请选择删除数据');
+                return;
+            }
+            if(obj.event === 'delAct'){
+                for (let i = 0; i < checkData.length; i++) {
+                    var delData = checkData[i];
+                    for (let j = 0; j < hasData.length; j++) {
+                        if (hasData[j].index == delData.index) {
+                            hasData.splice(j, 1);
+                            break;
+                        }
+                    }
+                }
+
+                for (let i = 0; i < hasData.length; i++) {
+                    hasData[i].index = i + 1;
+                }
+
+                tableBenefitsItemsData=hasData;
+                reloadTable(hasData);
+            }
+        });
+
+        function addTableDate(data) {
+            var hasData = table.cache['benefitsDetailsItem'];
+
+            data.index = hasData.length + 1;
+            data.contentName = ''
+            data.content = ''
+            tableBenefitsItemsData.push(data);
+
+            reloadTable(tableBenefitsItemsData);
+            return data.index;
+        }
+
+        function reloadTable(data) {
+            table.reload('benefitsDetailsItem', {
+                data : data
+            });
+
+            for (let i = 0; i < data.length; i++) {
+                if (data[i].image) {
+                    $('#awardImageUrls'+ (i+1)).css('display','block');
+                }
+                // 重新绑定图片上传
+                bindUpload(i+1);
+
+                listenerLinkContent();
+                listenerGoodsSelect();
+                listenerCouponSelect();
+            }
+        }
+
+        table.on('edit(benefitsDetailsItem)', function(obj){
+            var value = obj.value //得到修改后的值
+                ,data = obj.data //得到所在行所有键值
+                ,field = obj.field; //得到字段
+
+            for (let i = 0; i < tableBenefitsItemsData.length; i++) {
+                if (tableBenefitsItemsData[i].index == data.index) {
+                    tableBenefitsItemsData[i] = data;
+                }
+            }
+        });
+
+        function listenerLinkContent() {
+            var hasData = table.cache['benefitsDetailsItem'];
+
+            $(".linkContent").each(function(index, elem) {
+                var dataIndex = $(this).attr('data-index');
+                var $this = $(this);
+                $(this).off('blur')
+                $(this).on('blur', function() {
+                    var data = $this.val();
+                    hasData[dataIndex - 1].content = data;
+
+                    tableBenefitsItemsData = hasData;
+                })
+            });
+        }
+
+        function listenerGoodsSelect() {
+            var hasData = table.cache['benefitsDetailsItem'];
+
+            $(".goodsSelect").each(function(index, elem) {
+                var dataIndex = $(this).attr('data-index');
+                $(this).off('click')
+                $(this).on('click', function() {
+                    febs.modal.open('选择商品', 'modules/vip/config/goodsSelect/' + dataIndex, {
+                        btn: ['提交', '取消'],
+                        yes: function (index, layero) {
+                            $('#febs-select-goods').find('#goods-select-form-submit').trigger('click');
+                            layer.close(index);
+                        },
+                        btn2: function () {
+                        }
+                    });
+                })
+            });
+        }
+
+        function listenerCouponSelect() {
+            $(".couponSelect").each(function(index, elem) {
+                var dataIndex = $(this).attr('data-index');
+                $(this).off('click')
+                $(this).on('click', function() {
+                    febs.modal.open('选择优惠券', 'modules/vip/config/couponSelect/' + dataIndex, {
+                        btn: ['提交', '取消'],
+                        yes: function (index, layero) {
+                            $('#vip-coupon-select').find('#submit').trigger('click');
+                            layer.close(index);
+                        },
+                        btn2: function () {
+                        }
+                    });
+                })
+            });
+        }
+
+        $('#addBenefits').on('click', function (){
+            var isClickVal = $("input[name='isClick']:checked").val();
+            var linkTypeVal = $("select[name='linkType']").val();
+            if(isClickVal == 1 && (linkTypeVal == null || linkTypeVal == "")) {
+                febs.alert.warn('链接类型不能为空');
+                return false;
+            }
+
+
+            var data = {};
+            if (isClickVal == 1) {
+                data.linkType = linkTypeVal;
+            }
+            data.isClick = isClickVal;
+            addTableDate(data);
+
+            if (linkTypeVal == 1) {
+                listenerLinkContent();
+            }
+
+            if (linkTypeVal == 2) {
+                listenerGoodsSelect();
+            }
+
+            if (linkTypeVal == 3) {
+                listenerCouponSelect();
+            }
+
+        });
+
+        function bindUpload(index) {
+            // 普通图片上传
+            upload.render({
+                elem: '#awardImg' + index
+                ,url: ctx + 'admin/goods/uploadFileBase64' //改成您自己的上传接口
+                ,done: function(res){
+                    febs.alert.success("上传成功");
+                    $('#awardImageUrls' + index).attr('src', res.data.src);
+                    $('#awardImageUrls'+ index).css('display','block');
+                    $('#awardImage'+ index).val(res.data.src);
+
+                    for (let i = 0; i < tableBenefitsItemsData.length; i++) {
+                        if(tableBenefitsItemsData[i].index == index) {
+                            tableBenefitsItemsData[i].image = res.data.src;
+                        }
+                    }
+
+                    reloadTable(tableBenefitsItemsData);
+                }
+            });
+        }
+
+        form.on('radio(isClick)', function(data) {
+            if (data.value == 2) {
+                $('#linkTypeDiv').hide();
+            } else {
+                $('#linkTypeDiv').show();
+            }
+        });
+
+        form.on('select(benefits-type-select)', function(data) {
+            if (data.value == 1) {
+                $('#scoreMultiple').show();
+            } else {
+                $('#scoreMultiple').hide();
+            }
+        });
+
+        form.on('submit(vipBenefits-edit-form-submit)', function (data) {
+            data.field.details = tableBenefitsItemsData;
+            $.ajax({
+                'url':ctx + 'admin/vip/benefits/addOrEditBenefits',
+                'type':'post',
+                'dataType':'json',
+                'headers' : {'Content-Type' : 'application/json;charset=utf-8'}, //接口json格式
+                'traditional': true,//ajax传递数组必须添加属性
+                'data':JSON.stringify(data.field),
+                'success':function (data) {
+                    if(data.code==200){
+                        layer.closeAll();
+                        febs.alert.success(data.message);
+                        $('#febs-vip-benefits').find('#reset').click();
+                    }else{
+                        febs.alert.warn(data.message);
+                    }
+                },
+                'error':function () {
+                    febs.alert.warn('服务器繁忙');
+                }
+            })
+            return false;
+        });
+
+        window.setGoodsSelect = function(tableIndex, data) {
+            var hasData = table.cache['benefitsDetailsItem'];
+
+            for(var i = 0; i<hasData.length; i++) {
+                if (tableIndex == hasData[i].index) {
+                    hasData[i].content = data.id;
+                    hasData[i].contentName = data.goodsName
+                }
+            }
+
+            tableBenefitsItemsData = hasData;
+            $(".goodsSelect").each(function(index, elem) {
+                var dataIndex = $(this).attr('data-index');
+                if (dataIndex == tableIndex) {
+                    $(this).val(data.goodsName);
+                    $(this).next().val(data.id);
+                }
+            });
+        }
+
+        window.setCouponSelect = function(tableIndex, data) {
+            var hasData = table.cache['benefitsDetailsItem'];
+
+            for(var i = 0; i<hasData.length; i++) {
+                if (tableIndex == hasData[i].index) {
+                    hasData[i].content = data.couponId;
+                    hasData[i].contentName = data.couponName
+                }
+            }
+
+            tableBenefitsItemsData = hasData;
+            $(".couponSelect").each(function(index, elem) {
+                var dataIndex = $(this).attr('data-index');
+                if (dataIndex == tableIndex) {
+                    $(this).val(data.couponName);
+                    $(this).next().val(data.couponId);
+                }
+            });
+        }
+
+        initValue();
+        function initValue() {
+            form.val("vipBenefits-edit-form", {
+                "id": benefitsData.id,
+                "name": benefitsData.name,
+                "gainType": benefitsData.gainType,
+                "type": benefitsData.type,
+                "scoreMultiple": benefitsData.scoreMultiple,
+                "remark": benefitsData.remark,
+                "icon":benefitsData.icon,
+            });
+
+            $('#demo2').attr('src', benefitsData.icon);
+
+            var details = benefitsData.details;
+            for(var i = 0; i < details.length; i++) {
+                details[i].index = i + 1;
+            }
+            reloadTable(details);
+
+
+            tableBenefitsItemsData = details;
+        }
+
+    });
+</script>
+
+
+<script type="text/html" id="detailsEvent">
+    {{# if(d.isClick == 1 && d.linkType == 1){ }}
+    <input type="text" name="content" autocomplete="off" data-index="{{d.index}}" value="{{d.content}}" class="layui-input linkContent">
+    {{# } }}
+    {{# if( d.isClick == 1 && d.linkType == 2){ }}
+    <input type="text" autocomplete="off" name="contentName" data-index="{{d.index}}" value="{{d.contentName}}" class="layui-input goodsSelect" readonly>
+    <input type="text" name="content" autocomplete="off" value="{{d.content}}" class="layui-input goodsSelectId febs-hide" readonly>
+    {{# }  }}
+    {{# if(d.isClick == 1 && d.linkType == 3){ }}
+    <input type="text" name="contentName" autocomplete="off" data-index="{{d.index}}" value="{{d.contentName}}" class="layui-input couponSelect" readonly>
+    <input type="text" name="content" autocomplete="off" value="{{d.content}}" class="layui-input couponSelectId febs-hide" readonly>
+    {{# } }}
+</script>
\ No newline at end of file
diff --git a/src/main/resources/templates/febs/views/modules/vip/vipBenefits-list.html b/src/main/resources/templates/febs/views/modules/vip/vipBenefits-list.html
new file mode 100644
index 0000000..aeec71e
--- /dev/null
+++ b/src/main/resources/templates/febs/views/modules/vip/vipBenefits-list.html
@@ -0,0 +1,165 @@
+<div class="layui-fluid layui-anim febs-anim" id="febs-vip-benefits" lay-title="会员权益">
+    <div class="layui-row febs-container">
+        <div class="layui-col-md12">
+            <div class="layui-card">
+                <div class="layui-card-body febs-table-full">
+                    <form class="layui-form layui-table-form" lay-filter="vip-benefits-table-form">
+                        <div class="layui-row">
+                            <div class="layui-col-md2 layui-col-sm12 layui-col-xs12 table-action-area">
+                                <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain table-action" id="add">
+                                    新增
+                                </div>
+                                <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-blue-plain table-action" id="query">
+                                    <i class="layui-icon">&#xe848;</i>
+                                </div>
+                                <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain table-action" id="reset">
+                                    <i class="layui-icon">&#xe79b;</i>
+                                </div>
+                            </div>
+                        </div>
+                    </form>
+                    <table lay-filter="vipBenefitsTable" lay-data="{id: 'vipBenefitsTable'}"></table>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+<style>
+    .layui-table-cell {
+        height: auto;
+    }
+    .layui-form-onswitch {
+        background-color: #5FB878 !important;
+    }
+</style>
+<!-- 表格操作栏 start -->
+<script type="text/html" id="user-option">
+    <span shiro:lacksPermission="vipBenefits:view,vipBenefits:update,vipBenefits:delete">
+        <span class="layui-badge-dot febs-bg-orange"></span> 无权限
+    </span>
+    <a lay-event="edit" shiro:hasPermission="vipBenefits:update"><i
+            class="layui-icon febs-edit-area febs-blue">&#xe7a5;</i></a>
+</script>
+<!-- 表格操作栏 end -->
+<script data-th-inline="none" type="text/javascript">
+    // 引入组件并初始化
+    layui.use([ 'jquery', 'form', 'table', 'febs'], function () {
+        var $ = layui.jquery,
+            febs = layui.febs,
+            form = layui.form,
+            table = layui.table,
+            $view = $('#febs-vip-benefits'),
+            $query = $view.find('#query'),
+            $add = $view.find('#add'),
+            $reset = $view.find('#reset'),
+            $searchForm = $view.find('form'),
+            sortObject = {field: 'phone', type: null},
+            tableIns;
+
+        form.render();
+
+        // 表格初始化
+        initTable();
+
+        // 初始化表格操作栏各个按钮功能
+        table.on('tool(vipBenefitsTable)', function (obj) {
+            var data = obj.data,
+                layEvent = obj.event;
+            if (layEvent === 'benefitsUpdate') {
+                febs.modal.open('编辑', 'modules/vip/config/editBenefits/' + data.id, {
+                    btn: ['提交', '取消'],
+                    yes: function (index, layero) {
+                        $('#febs-vipBenefits-edit').find('#submit').trigger('click');
+                    },
+                    btn2: function () {
+                        layer.closeAll();
+                    }
+                });
+            }
+            if (layEvent === 'delBenefits') {
+                febs.modal.confirm('删除', '确认删除?', function () {
+                    delBenefits(data.id);
+                });
+            }
+        });
+
+        function delBenefits(id) {
+            febs.get(ctx + 'admin/vip/benefits/delBenefits/' + id, null, function () {
+                febs.alert.success('操作成功');
+                $query.click();
+            });
+        }
+
+        // 查询按钮
+        $query.on('click', function () {
+            var params = $.extend(getQueryParams(), {field: sortObject.field, order: sortObject.type});
+            tableIns.reload({where: params, page: {curr: 1}});
+        });
+
+        // 刷新按钮
+        $reset.on('click', function () {
+            $searchForm[0].reset();
+            sortObject.type = 'null';
+            tableIns.reload({where: getQueryParams(), page: {curr: 1}, initSort: sortObject});
+        });
+
+        $add.on('click', function () {
+            febs.modal.open('新增', 'modules/vip/config/vipBenefitsAdd/', {
+                btn: ['提交', '取消'],
+                yes: function (index, layero) {
+                    $('#febs-vipBenefits-add').find('#submit').trigger('click');
+                },
+                btn2: function () {
+                    layer.closeAll();
+                }
+            });
+        });
+
+        function initTable() {
+            tableIns = febs.table.init({
+                elem: $view.find('table'),
+                id: 'vipBenefitsTable',
+                url: ctx + 'admin/vip/benefits/list',
+                cols: [[
+                    {field: 'name', title: '权益名称', minWidth: 120, align: 'center'},
+                    {
+                        field: 'icon', title: 'ICON',
+                        templet: function (d) {
+                            return '<a lay-event="seeImgThumb"><img id="seeImgThumb'+d.id+'" src="'+d.icon+'" alt=""></a>';
+                        }, minWidth: 150, align: 'center'
+                    },
+                    {field: 'remark', title: '备注', minWidth: 120, align: 'center'},
+                    {field: 'createdTime', title: '创建时间', minWidth: 120, align: 'center'},
+                    {
+                        title: '操作',
+                        templet: function (d) {
+                            return '<button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="benefitsUpdate" shiro:hasPermission="user:update">编辑</button>'
+                                + '<button class="layui-btn layui-btn-danger layui-btn-xs" lay-event="delBenefits" shiro:hasPermission="user:update">删除</button>'
+                        }, minWidth: 300, align: 'center'
+                    }
+                ]]
+            });
+        }
+
+        // 获取查询参数
+        function getQueryParams() {
+            return {
+            };
+        }
+
+        form.on('switch(isTopSwitch)', function (data) {
+            console.log(data.value);
+            if (data.elem.checked) {
+                febs.post(ctx + 'admin/news/topNews/' + data.value, null, function () {
+                    febs.alert.success('设置成功');
+                    $query.click();
+                });
+            } else {
+                febs.post(ctx + 'admin/news/unTopNews/' + data.value, null, function () {
+                    febs.alert.success('设置成功');
+                    $query.click();
+                });
+            }
+        })
+    })
+</script>
\ No newline at end of file
diff --git a/src/main/resources/templates/febs/views/modules/vip/vipConfig-add.html b/src/main/resources/templates/febs/views/modules/vip/vipConfig-add.html
new file mode 100644
index 0000000..2ce47af
--- /dev/null
+++ b/src/main/resources/templates/febs/views/modules/vip/vipConfig-add.html
@@ -0,0 +1,256 @@
+<style>
+    #vipConfig-add {
+        padding: 20px 25px 25px 0;
+    }
+
+    #vipConfig-add .layui-treeSelect .ztree li a, .ztree li span {
+        margin: 0 0 2px 3px !important;
+    }
+    #vipConfig-add #data-permission-tree-block {
+        border: 1px solid #eee;
+        border-radius: 2px;
+        padding: 3px 0;
+    }
+    #vipConfig-add .layui-treeSelect .ztree li span.button.switch {
+        top: 1px;
+        left: 3px;
+    }
+    #vipConfig-add img{
+        max-width:100px
+    }
+
+</style>
+<div class="layui-fluid" id="febs-vipConfig-add">
+    <form class="layui-form" action="" lay-filter="vipConfig-add-form">
+        <div class="layui-form-item">
+
+            <div class="layui-col-lg6">
+                <label class="layui-form-label febs-form-item-require">会员名称:</label>
+                <div class="layui-input-block">
+                    <input type="text" name="name" lay-verify="required" autocomplete="off" class="layui-input" >
+                </div>
+            </div>
+
+            <div class="layui-col-lg6">
+                <label class="layui-form-label febs-form-item-require">会员等级:</label>
+                <div class="layui-input-block">
+                    <input type="number" name="level" lay-verify="required" autocomplete="off" class="layui-input" >
+                </div>
+            </div>
+        </div>
+        <div class="layui-form-item">
+
+            <div class="layui-col-lg6">
+                <label class="layui-form-label febs-form-item-require">会员编码:</label>
+                <div class="layui-input-block">
+                    <input type="text" name="code" lay-verify="required" autocomplete="off" class="layui-input" >
+                </div>
+            </div>
+        </div>
+
+        <div class="layui-form-item">
+            <label class="layui-form-label">主图:</label>
+            <div class="layui-input-block">
+                <button type="button" class="layui-btn" id="imageUpload" style="background-color: #009688; margin-bottom: 2px">图片上传</button>
+                <blockquote class="layui-elem-quote layui-quote-nm" style="margin-top: 10px;">
+                    <div class=" layui-upload-list view-images" id="thumbImage">
+                    </div>
+                </blockquote>
+                <div class="febs-hide">
+                    <input type="text" id="thumb"  name="thumb" autocomplete="off" class="layui-input" readonly>
+                </div>
+            </div>
+        </div>
+
+        <div class="layui-form-item">
+            <div class="layui-col-lg4">
+                <label class="layui-form-label febs-form-item-require">有效期:</label>
+                <div class="layui-input-block">
+                    <input type="number" name="validTime" lay-verify="required" autocomplete="off" class="layui-input" >
+                </div>
+            </div>
+            <div class="layui-col-lg2">
+                <select name="validType" class="valid-type" lay-filter="valid-type-select">
+                    <option value="day">日</option>
+                    <option value="month">月</option>
+                    <option value="year">年</option>
+                </select>
+            </div>
+        </div>
+
+        <div id="layui-form-item">
+            <div class="layui-col-lg6">
+                <label class="layui-form-label febs-form-item-require">成为会员条件:</label>
+                <div class="layui-input-block">
+                    <select name="type" class="valid-type" lay-filter="type-select">
+                        <option value="1">指定商品</option>
+                        <option value="2">时间区间内消费金额</option>
+                    </select>
+                </div>
+            </div>
+
+            <div class="layui-col-lg6" id="targetGoods">
+                <label class="layui-form-label febs-form-item-require">指定商品:</label>
+                <div class="layui-input-block">
+                    <input type="text" id="selectGoods" name="targetName" placeholder="点击选择商品" autocomplete="off" class="layui-input" >
+                    <input type="text" id="selectGoodsId" name="targetId" placeholder="点击选择商品" autocomplete="off" class="layui-input febs-hide" >
+                </div>
+            </div>
+
+            <div class="layui-col-lg6 febs-hide" id="targetShopping">
+                <div class="layui-input-inline layui-col-lg2">
+                    <input type="text" name="times" autocomplete="off" class="layui-input" >
+                </div>
+                <div class="layui-form-mid">月内,消费</div>
+                <div class="layui-input-inline layui-col-lg2">
+                    <input type="text" name="amount" autocomplete="off" class="layui-input" >
+                </div>
+                <div class="layui-form-mid">金额</div>
+            </div>
+        </div>
+
+        <div class="layui-form-item">
+            <label class="layui-form-label febs-form-item-require">选择会员权益:</label>
+            <div class="layui-input-block">
+<!--                <select name="benefitsIds" class="vip-benefits-list" id="vip-benefits-list">-->
+<!--                </select>-->
+                <div id="vip-benefits-list"></div>
+            </div>
+        </div>
+
+        <div class="layui-form-item febs-hide">
+            <button class="layui-btn" lay-submit="" lay-filter="vipConfig-add-form-submit" id="submit"></button>
+        </div>
+    </form>
+</div>
+
+<script data-th-inline="javascript">
+    layui.use(['febs', 'form', 'formSelects', 'validate', 'treeSelect', 'eleTree','layedit', 'laydate', 'upload', 'xmSelect'], function () {
+        var $ = layui.$,
+            febs = layui.febs,
+            layer = layui.layer,
+            upload = layui.upload,
+            formSelects = layui.formSelects,
+            form = layui.form,
+            laydate = layui.laydate,
+            layedit = layui.layedit,
+            $view = $('#vipConfig-add'),
+            validate = layui.validate;
+
+        var benefitsList = xmSelect.render({
+            el: '#vip-benefits-list',
+            prop: {
+                name: 'name',
+                value: 'id',
+            },
+            data: []
+        })
+
+
+        //(下拉框)
+        $.get(ctx + 'admin/vip/benefits/findAllBenefits', function (data) {
+            benefitsList.update({
+                data : data.data,
+                autoRow: true,
+            });
+        });
+
+        form.render();
+
+        formSelects.render();
+        form.on('submit(vipConfig-add-form-submit)', function (data) {
+            data.field.benefitsIds = benefitsList.getValue('valueStr');
+            $.ajax({
+                'url':ctx + 'admin/vip/config/addOrEdit',
+                'type':'post',
+                'dataType':'json',
+                'headers' : {'Content-Type' : 'application/json;charset=utf-8'}, //接口json格式
+                'traditional': true,//ajax传递数组必须添加属性
+                'data':JSON.stringify(data.field),
+                'success':function (data) {
+                    if(data.code==200){
+                        layer.closeAll();
+                        febs.alert.success(data.message);
+                        $('#febs-vip-level').find('#reset').click();
+                    }else{
+                        febs.alert.warn(data.message);
+                    }
+                },
+                'error':function () {
+                    febs.alert.warn('服务器繁忙');
+                }
+            })
+            return false;
+            return false;
+        });
+
+        form.on('select(type-select)', function(data) {
+            if (data.value == 1) {
+                $("#targetGoods").show();
+                $("#targetShopping").hide();
+            } else {
+                $("#targetGoods").hide();
+                $("#targetShopping").show();
+            }
+        })
+
+        upload.render({
+            elem: '#imageUpload'
+            ,url: ctx + 'admin/goods/uploadFileBase64' //改成您自己的上传接口
+            ,multiple: false
+            ,before: function(obj){
+                //预读本地文件示例,不支持ie8
+                obj.preview(function(index, file, result){
+                    $('#thumbImage').html('<img src="'+ result +'" alt="'+ file.name +'" class="layui-upload-img" style="width: 100px">')
+                });
+            }
+            ,done: function(res){
+                $("#thumb").val(res.data.src);
+            }
+        });
+
+
+        bindUpload();
+        function bindUpload() {
+            upload.render({
+                elem: '.upload'
+                ,url: ctx + 'admin/goods/uploadFileBase64' //改成您自己的上传接口
+                ,accept: 'file'
+                ,before: function(obj){
+                    layer.msg('上传中', {icon: 16, time: 0});
+                }
+                ,done: function(res){
+                    var item = this.item;
+                    //如果上传失败
+                    if(res.code !== 0){
+                        return layer.msg('上传失败');
+                    }
+
+                    // $(item).parent().prev().find('input').val(res.data[0]);
+                    $("#videoUrl").val(res.data.src);
+                    layer.msg('上传完毕', {icon: 1});
+                }
+                ,error: function(err){
+                    return layer.msg('上传失败');
+                }
+            });
+        }
+
+        $("#selectGoods").on('click', function() {
+            febs.modal.open('选择商品', 'modules/vip/config/goodsSelect/' + -1, {
+                btn: ['提交', '取消'],
+                yes: function (index, layero) {
+                    $('#febs-select-goods').find('#goods-select-form-submit').trigger('click');
+                    layer.close(index);
+                },
+                btn2: function () {
+                }
+            });
+        })
+
+        window.setConfigGoodsSelect = function(tableIndex, data) {
+            $("#selectGoods").val(data.goodsName);
+            $("#selectGoodsId").val(data.id);
+        }
+    });
+</script>
\ No newline at end of file
diff --git a/src/main/resources/templates/febs/views/modules/vip/vipConfig-edit.html b/src/main/resources/templates/febs/views/modules/vip/vipConfig-edit.html
new file mode 100644
index 0000000..2c7cd52
--- /dev/null
+++ b/src/main/resources/templates/febs/views/modules/vip/vipConfig-edit.html
@@ -0,0 +1,291 @@
+<style>
+    #vipConfig-edit {
+        padding: 20px 25px 25px 0;
+    }
+
+    #vipConfig-edit .layui-treeSelect .ztree li a, .ztree li span {
+        margin: 0 0 2px 3px !important;
+    }
+    #vipConfig-edit #data-permission-tree-block {
+        border: 1px solid #eee;
+        border-radius: 2px;
+        padding: 3px 0;
+    }
+    #vipConfig-edit .layui-treeSelect .ztree li span.button.switch {
+        top: 1px;
+        left: 3px;
+    }
+    #vipConfig-edit img{
+        max-width:100px
+    }
+
+</style>
+<div class="layui-fluid" id="febs-vipConfig-edit">
+    <form class="layui-form" action="" lay-filter="vipConfig-edit-form">
+        <div class="layui-form-item">
+            <input type="text" name="id" lay-verify="required" autocomplete="off" class="layui-input febs-hide" >
+            <div class="layui-col-lg6">
+                <label class="layui-form-label febs-form-item-require">会员名称:</label>
+                <div class="layui-input-block">
+                    <input type="text" name="name" lay-verify="required" autocomplete="off" class="layui-input" >
+                </div>
+            </div>
+
+            <div class="layui-col-lg6">
+                <label class="layui-form-label febs-form-item-require">会员等级:</label>
+                <div class="layui-input-block">
+                    <input type="number" name="level" lay-verify="required" autocomplete="off" class="layui-input" >
+                </div>
+            </div>
+        </div>
+
+        <div class="layui-form-item">
+
+            <div class="layui-col-lg6">
+                <label class="layui-form-label febs-form-item-require">会员编码:</label>
+                <div class="layui-input-block">
+                    <input type="text" name="code" lay-verify="required" autocomplete="off" class="layui-input" >
+                </div>
+            </div>
+        </div>
+
+        <div class="layui-form-item">
+            <label class="layui-form-label">主图:</label>
+            <div class="layui-input-block">
+                <button type="button" class="layui-btn" id="imageUpload" style="background-color: #009688; margin-bottom: 2px">图片上传</button>
+                <blockquote class="layui-elem-quote layui-quote-nm" style="margin-top: 10px;">
+                    <div class=" layui-upload-list view-images" id="thumbImage">
+                    </div>
+                </blockquote>
+                <div class="febs-hide">
+                    <input type="text" id="thumb"  name="thumb" autocomplete="off" class="layui-input" readonly>
+                </div>
+            </div>
+        </div>
+
+        <div class="layui-form-item">
+            <div class="layui-col-lg4">
+                <label class="layui-form-label febs-form-item-require">有效期:</label>
+                <div class="layui-input-block">
+                    <input type="number" name="validTime" lay-verify="required" autocomplete="off" class="layui-input" >
+                </div>
+            </div>
+            <div class="layui-col-lg2">
+                <select name="validType" class="valid-type" lay-filter="valid-type-select">
+                    <option value="day">日</option>
+                    <option value="month">月</option>
+                    <option value="year">年</option>
+                </select>
+            </div>
+        </div>
+
+        <div id="layui-form-item">
+            <div class="layui-col-lg6">
+                <label class="layui-form-label febs-form-item-require">成为会员条件:</label>
+                <div class="layui-input-block">
+                    <select name="type" class="valid-type" lay-filter="type-select">
+                        <option value="1">指定商品</option>
+                        <option value="2">时间区间内消费金额</option>
+                    </select>
+                </div>
+            </div>
+
+            <div class="layui-col-lg6" id="targetGoods">
+                <label class="layui-form-label febs-form-item-require">指定商品:</label>
+                <div class="layui-input-block">
+                    <input type="text" id="selectGoods" name="targetName" placeholder="点击选择商品" autocomplete="off" class="layui-input" >
+                    <input type="text" id="selectGoodsId" name="targetId" placeholder="点击选择商品" autocomplete="off" class="layui-input febs-hide" >
+                </div>
+            </div>
+
+            <div class="layui-col-lg6 febs-hide" id="targetShopping">
+                <div class="layui-input-inline layui-col-lg2">
+                    <input type="text" name="times" autocomplete="off" class="layui-input" >
+                </div>
+                <div class="layui-form-mid">月内,消费</div>
+                <div class="layui-input-inline layui-col-lg2">
+                    <input type="text" name="amount" autocomplete="off" class="layui-input" >
+                </div>
+                <div class="layui-form-mid">金额</div>
+            </div>
+        </div>
+
+        <div class="layui-form-item">
+            <label class="layui-form-label febs-form-item-require">选择会员权益:</label>
+            <div class="layui-input-block">
+<!--                <select name="benefitsIds" class="vip-benefits-list" id="vip-benefits-list">-->
+<!--                </select>-->
+                <div id="vip-benefits-list"></div>
+            </div>
+        </div>
+
+        <div class="layui-form-item febs-hide">
+            <button class="layui-btn" lay-submit="" lay-filter="vipConfig-edit-form-submit" id="submit"></button>
+        </div>
+    </form>
+</div>
+
+<script data-th-inline="javascript">
+    layui.use(['febs', 'form', 'formSelects', 'validate', 'treeSelect', 'eleTree','layedit', 'laydate', 'upload', 'xmSelect'], function () {
+        var $ = layui.$,
+            febs = layui.febs,
+            layer = layui.layer,
+            upload = layui.upload,
+            formSelects = layui.formSelects,
+            form = layui.form,
+            laydate = layui.laydate,
+            layedit = layui.layedit,
+            vipConfigData = [[${configData}]]
+            $view = $('#vipConfig-edit'),
+            validate = layui.validate;
+
+        var benefitsList = xmSelect.render({
+            el: '#vip-benefits-list',
+            prop: {
+                name: 'name',
+                value: 'id',
+            },
+            data: []
+        })
+
+
+        //(下拉框)
+        $.get(ctx + 'admin/vip/benefits/findAllBenefits', function (data) {
+            benefitsList.update({
+                data : data.data,
+                autoRow: true,
+            });
+
+            initValue();
+        });
+
+        form.render();
+
+        formSelects.render();
+        form.on('submit(vipConfig-edit-form-submit)', function (data) {
+            data.field.benefitsIds = benefitsList.getValue('valueStr');
+            $.ajax({
+                'url':ctx + 'admin/vip/config/addOrEdit',
+                'type':'post',
+                'dataType':'json',
+                'headers' : {'Content-Type' : 'application/json;charset=utf-8'}, //接口json格式
+                'traditional': true,//ajax传递数组必须添加属性
+                'data':JSON.stringify(data.field),
+                'success':function (data) {
+                    if(data.code==200){
+                        layer.closeAll();
+                        febs.alert.success(data.message);
+                        $('#febs-vip-level').find('#reset').click();
+                    }else{
+                        febs.alert.warn(data.message);
+                    }
+                },
+                'error':function () {
+                    febs.alert.warn('服务器繁忙');
+                }
+            })
+            return false;
+        });
+
+        form.on('select(type-select)', function(data) {
+            if (data.value == 1) {
+                $("#targetGoods").show();
+                $("#targetShopping").hide();
+            } else {
+                $("#targetGoods").hide();
+                $("#targetShopping").show();
+            }
+        })
+
+        upload.render({
+            elem: '#imageUpload'
+            ,url: ctx + 'admin/goods/uploadFileBase64' //改成您自己的上传接口
+            ,multiple: false
+            ,before: function(obj){
+                //预读本地文件示例,不支持ie8
+                obj.preview(function(index, file, result){
+                    $('#thumbImage').html('<img src="'+ result +'" alt="'+ file.name +'" class="layui-upload-img" style="width: 100px">')
+                });
+            }
+            ,done: function(res){
+                $("#thumb").val(res.data.src);
+            }
+        });
+
+
+        bindUpload();
+        function bindUpload() {
+            upload.render({
+                elem: '.upload'
+                ,url: ctx + 'admin/goods/uploadFileBase64' //改成您自己的上传接口
+                ,accept: 'file'
+                ,before: function(obj){
+                    layer.msg('上传中', {icon: 16, time: 0});
+                }
+                ,done: function(res){
+                    var item = this.item;
+                    //如果上传失败
+                    if(res.code !== 0){
+                        return layer.msg('上传失败');
+                    }
+
+                    // $(item).parent().prev().find('input').val(res.data[0]);
+                    $("#videoUrl").val(res.data.src);
+                    layer.msg('上传完毕', {icon: 1});
+                }
+                ,error: function(err){
+                    return layer.msg('上传失败');
+                }
+            });
+        }
+
+        $("#selectGoods").on('click', function() {
+            febs.modal.open('选择商品', 'modules/vip/config/goodsSelect/' + -1, {
+                btn: ['提交', '取消'],
+                yes: function (index, layero) {
+                    $('#febs-select-goods').find('#goods-select-form-submit').trigger('click');
+                    layer.close(index);
+                },
+                btn2: function () {
+                }
+            });
+        })
+
+        window.setConfigGoodsSelect = function(tableIndex, data) {
+            $("#selectGoods").val(data.goodsName);
+            $("#selectGoodsId").val(data.id);
+        }
+
+        function initValue() {
+            form.val("vipConfig-edit-form", {
+                "id": vipConfigData.id,
+                "name": vipConfigData.name,
+                "level": vipConfigData.level,
+                "type" : vipConfigData.type,
+                "validTime": vipConfigData.validTime,
+                "validType": vipConfigData.validType,
+                "targetName":vipConfigData.targetName,
+                "targetId":vipConfigData.targetId,
+                "times" : vipConfigData.times,
+                "amount" : vipConfigData.amount,
+                "code" : vipConfigData.code,
+            });
+
+            $('#thumbImage').html('<img src="'+ vipConfigData.thumb +'" class="layui-upload-img" style="width: 100px">')
+            $("#thumb").val(vipConfigData.thumb);
+
+            if (vipConfigData.type == 1) {
+                $("#targetGoods").show();
+                $("#targetShopping").hide();
+            } else {
+                $("#targetGoods").hide();
+                $("#targetShopping").show();
+            }
+
+            var arr = []
+            arr.push(vipConfigData.benefitsIdList)
+            console.log(vipConfigData.benefitsIdList)
+            benefitsList.setValue(vipConfigData.benefitsIdList);
+        }
+    });
+</script>
\ No newline at end of file
diff --git a/src/main/resources/templates/febs/views/modules/vip/vipConfig-list.html b/src/main/resources/templates/febs/views/modules/vip/vipConfig-list.html
new file mode 100644
index 0000000..76c8edc
--- /dev/null
+++ b/src/main/resources/templates/febs/views/modules/vip/vipConfig-list.html
@@ -0,0 +1,171 @@
+<div class="layui-fluid layui-anim febs-anim" id="febs-vip-level" lay-title="会员权益">
+    <div class="layui-row febs-container">
+        <div class="layui-col-md12">
+            <div class="layui-card">
+                <div class="layui-card-body febs-table-full">
+                    <form class="layui-form layui-table-form" lay-filter="vip-benefits-level-table-form">
+                        <div class="layui-row">
+                            <div class="layui-col-md2 layui-col-sm12 layui-col-xs12 table-action-area">
+                                <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain table-action" id="add">
+                                    新增
+                                </div>
+                                <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-blue-plain table-action" id="query">
+                                    <i class="layui-icon">&#xe848;</i>
+                                </div>
+                                <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain table-action" id="reset">
+                                    <i class="layui-icon">&#xe79b;</i>
+                                </div>
+                            </div>
+                        </div>
+                    </form>
+                    <table lay-filter="vipBenefitsLevelTable" lay-data="{id: 'vipBenefitsLevelTable'}"></table>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+<style>
+    .layui-table-cell {
+        height: auto;
+    }
+    .layui-form-onswitch {
+        background-color: #5FB878 !important;
+    }
+</style>
+<!-- 表格操作栏 start -->
+<script type="text/html" id="user-option">
+    <span shiro:lacksPermission="vipConfig:view,vipConfig:update,vipConfig:delete">
+        <span class="layui-badge-dot febs-bg-orange"></span> 无权限
+    </span>
+    <a lay-event="edit" shiro:hasPermission="vipConfig:update"><i
+            class="layui-icon febs-edit-area febs-blue">&#xe7a5;</i></a>
+</script>
+
+<script type="text/html" id="validTypeFormat">
+    {{# if(d.validType == "day") { }}
+    <span>日</span>
+    {{# } else if(d.validType == "month") { }}
+    <span>月</span>
+    {{# } else { }}
+    <span>年</span>
+    {{# } }}
+</script>
+
+
+<script type="text/html" id="typeFormat">
+    {{# if(d.validType == "day") { }}
+    <span>指定商品</span>
+    {{# } else { }}
+    <span>周期内消费指定金额</span>
+    {{# } }}
+</script>
+<!-- 表格操作栏 end -->
+<script data-th-inline="none" type="text/javascript">
+    // 引入组件并初始化
+    layui.use([ 'jquery', 'form', 'table', 'febs'], function () {
+        var $ = layui.jquery,
+            febs = layui.febs,
+            form = layui.form,
+            table = layui.table,
+            $view = $('#febs-vip-level'),
+            $query = $view.find('#query'),
+            $add = $view.find('#add'),
+            $reset = $view.find('#reset'),
+            $searchForm = $view.find('form'),
+            sortObject = {field: 'phone', type: null},
+            tableIns;
+
+        form.render();
+
+        // 表格初始化
+        initTable();
+
+        // 初始化表格操作栏各个按钮功能
+        table.on('tool(vipBenefitsLevelTable)', function (obj) {
+            var data = obj.data,
+                layEvent = obj.event;
+            if (layEvent === 'benefitsUpdate') {
+                febs.modal.open('编辑', 'modules/vip/config/levelEdit/' + data.id, {
+                    btn: ['提交', '取消'],
+                    yes: function (index, layero) {
+                        $('#febs-vipConfig-edit').find('#submit').trigger('click');
+                    },
+                    btn2: function () {
+                        layer.closeAll();
+                    }
+                });
+            }
+            if (layEvent === 'delVipConfig') {
+                febs.modal.confirm('删除', '确认删除?', function () {
+                    delVipConfig(data.id);
+                });
+            }
+        });
+
+        function delVipConfig(id) {
+            febs.get(ctx + 'admin/vip/config/del/' + id, null, function () {
+                febs.alert.success('操作成功');
+                $query.click();
+            });
+        }
+
+        // 查询按钮
+        $query.on('click', function () {
+            var params = $.extend(getQueryParams(), {field: sortObject.field, order: sortObject.type});
+            tableIns.reload({where: params, page: {curr: 1}});
+        });
+
+        // 刷新按钮
+        $reset.on('click', function () {
+            $searchForm[0].reset();
+            sortObject.type = 'null';
+            tableIns.reload({where: getQueryParams(), page: {curr: 1}, initSort: sortObject});
+        });
+
+        $add.on('click', function () {
+            febs.modal.open('新增', 'modules/vip/config/levelAdd/', {
+                btn: ['提交', '取消'],
+                yes: function (index, layero) {
+                    $('#febs-vipConfig-add').find('#submit').trigger('click');
+                },
+                btn2: function () {
+                    layer.closeAll();
+                }
+            });
+        });
+
+        function initTable() {
+            tableIns = febs.table.init({
+                elem: $view.find('table'),
+                id: 'vipBenefitsLevelTable',
+                url: ctx + 'admin/vip/config/list',
+                cols: [[
+                    {field: 'name', title: '会员名称', minWidth: 120, align: 'center'},
+                    {
+                        field: 'thumb', title: '主图',
+                        templet: function (d) {
+                            return '<a lay-event="seeImgThumb"><img id="seeImgThumb'+d.id+'" src="'+d.thumb+'" alt=""></a>';
+                        }, minWidth: 150, align: 'center'
+                    },
+                    {field: 'level', title: '等级', minWidth: 120, align: 'center'},
+                    {field: 'validTime', title: '有效时长', minWidth: 120, align: 'center'},
+                    {templet:"#validTypeFormat",title: '有效类型', minWidth: 120, align: 'center'},
+                    {templet:"#typeFormat", title: '成为会员条件', minWidth: 120, align: 'center'},
+                    {
+                        title: '操作',
+                        templet: function (d) {
+                            return '<button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="benefitsUpdate" shiro:hasPermission="user:update">编辑</button>'
+                                + '<button class="layui-btn layui-btn-danger layui-btn-xs" lay-event="delVipConfig" shiro:hasPermission="user:update">删除</button>'
+                        }, minWidth: 300, align: 'center'
+                    }
+                ]]
+            });
+        }
+
+        // 获取查询参数
+        function getQueryParams() {
+            return {
+            };
+        }
+    })
+</script>
\ No newline at end of file
diff --git a/src/test/java/cc/mrbird/febs/ProfitTest.java b/src/test/java/cc/mrbird/febs/ProfitTest.java
index 8a8d677..bc26aac 100644
--- a/src/test/java/cc/mrbird/febs/ProfitTest.java
+++ b/src/test/java/cc/mrbird/febs/ProfitTest.java
@@ -967,4 +967,10 @@
         BigDecimal amount = new BigDecimal("0.15").setScale(2,BigDecimal.ROUND_DOWN);
         System.out.println(amount);
     }
+
+    @Test
+    public void aaaTest() {
+//        agentConsumer.vipLevelUp(133L);
+        agentConsumer.getScoreMsg(152L);
+    }
 }

--
Gitblit v1.9.1