FengChaoYu 2 週間 前
コミット
3332982909
35 ファイル変更1888 行追加46 行削除
  1. 22 0
      src/main/java/com/gree/mall/contest/bean/goods/GoodsNewBean.java
  2. 58 0
      src/main/java/com/gree/mall/contest/bean/order/BuyGood.java
  3. 19 0
      src/main/java/com/gree/mall/contest/bean/order/OrderStatusBean.java
  4. 16 0
      src/main/java/com/gree/mall/contest/bean/order/ShoppingCartBean.java
  5. 19 0
      src/main/java/com/gree/mall/contest/bean/order/ShoppingCartDetail.java
  6. 25 0
      src/main/java/com/gree/mall/contest/bean/order/ShoppingCartList.java
  7. 26 0
      src/main/java/com/gree/mall/contest/bean/user/CurrentCompanyWechat.java
  8. 18 0
      src/main/java/com/gree/mall/contest/bean/user/MyProfitBean.java
  9. 23 0
      src/main/java/com/gree/mall/contest/bean/user/RankBean.java
  10. 24 0
      src/main/java/com/gree/mall/contest/bean/user/RankItemBean.java
  11. 22 0
      src/main/java/com/gree/mall/contest/bean/user/ServiceWorkerBean.java
  12. 31 0
      src/main/java/com/gree/mall/contest/bean/user/UserAddressBean.java
  13. 9 0
      src/main/java/com/gree/mall/contest/bean/user/UserWxBean.java
  14. 0 2
      src/main/java/com/gree/mall/contest/commonmapper/AdminMapper.java
  15. 43 0
      src/main/java/com/gree/mall/contest/commonmapper/AppMapper.java
  16. 3 1
      src/main/java/com/gree/mall/contest/commonmapper/CustomMemberMapper.java
  17. 24 0
      src/main/java/com/gree/mall/contest/commonmapper/OrderShareRankMapper.java
  18. 22 0
      src/main/java/com/gree/mall/contest/config/MulitpartConfig.java
  19. 21 0
      src/main/java/com/gree/mall/contest/config/ScheduleConfig.java
  20. 3 21
      src/main/java/com/gree/mall/contest/config/aop/ApiAspect.java
  21. 2 0
      src/main/java/com/gree/mall/contest/constant/Constant.java
  22. 78 0
      src/main/java/com/gree/mall/contest/controller/mini/user/AddressController.java
  23. 182 0
      src/main/java/com/gree/mall/contest/controller/mini/user/UserController.java
  24. 52 0
      src/main/java/com/gree/mall/contest/controller/mini/user/WorkerController.java
  25. 16 0
      src/main/java/com/gree/mall/contest/enums/QrCodeEnum.java
  26. 42 0
      src/main/java/com/gree/mall/contest/logic/activity/PromotionGroupLogic.java
  27. 35 6
      src/main/java/com/gree/mall/contest/logic/common/CommonLogic.java
  28. 240 0
      src/main/java/com/gree/mall/contest/logic/order/ShoppingCartLogic.java
  29. 109 0
      src/main/java/com/gree/mall/contest/logic/user/AddressLogic.java
  30. 494 14
      src/main/java/com/gree/mall/contest/logic/user/UserLogic.java
  31. 98 0
      src/main/java/com/gree/mall/contest/logic/user/WorkerLogic.java
  32. 2 2
      src/main/java/com/gree/mall/contest/utils/JwtUtils.java
  33. 62 0
      src/main/resources/mapper/AppMapper.xml
  34. 9 0
      src/main/resources/mapper/CustomMemberMapper.xml
  35. 39 0
      src/main/resources/mapper/OrderShareRankMapper.xml

+ 22 - 0
src/main/java/com/gree/mall/contest/bean/goods/GoodsNewBean.java

@@ -0,0 +1,22 @@
+package com.gree.mall.contest.bean.goods;
+
+import com.gree.mall.contest.plus.entity.Goods;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.List;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class GoodsNewBean extends Goods {
+
+    @Schema(description = "objId")
+    private String objId;
+    @Schema(description = "上标签")
+    private List<String> tags1;
+    @Schema(description = "下标签")
+    private List<String> tags2;
+
+
+}

+ 58 - 0
src/main/java/com/gree/mall/contest/bean/order/BuyGood.java

@@ -0,0 +1,58 @@
+package com.gree.mall.contest.bean.order;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.gree.mall.contest.plus.entity.Goods;
+import com.gree.mall.contest.plus.entity.GoodsSpec;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class BuyGood {
+
+    @Schema(description = "商品id")
+    private String goodsId;
+    @Schema(description = "商品规格id")
+    private String GoodsSpecId;
+    @Schema(description = "购买数量")
+    private Integer num;
+    @Schema(description = "套购商品-框几")
+    private Integer popType;
+    @Schema(description = "购物车id(购物车提交订单才传)")
+    private String shoppingCartId;
+    @Schema(description = "团购活动id")
+    private String promotionGroupId;
+    @Schema(description = "秒杀活动id")
+    private String secKillId;
+    @Schema(description = "wxSceneId")
+    private String wxSceneId;
+
+    @JsonIgnore
+    private Goods goods;
+    @JsonIgnore
+    private GoodsSpec goodsSpec;
+    @JsonIgnore
+    @Schema(description = "单价")
+    private BigDecimal price;
+    @JsonIgnore
+    @Schema(description = "单个商品佣金")
+    private BigDecimal shareAmount;
+    //套购商品
+    @JsonIgnore
+    private Boolean isGoodsPackage = false;
+    //秒杀商品
+    @JsonIgnore
+    private Boolean isSecKill = false;
+    //团购商品
+    @JsonIgnore
+    private Boolean isPromotionGroup = false;
+    //原价
+    @JsonIgnore
+    private BigDecimal orgPrice;
+    //活动的商品图
+    @JsonIgnore
+    private String promotionImgUrl;
+
+
+}

+ 19 - 0
src/main/java/com/gree/mall/contest/bean/order/OrderStatusBean.java

@@ -0,0 +1,19 @@
+package com.gree.mall.contest.bean.order;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Data
+public class OrderStatusBean {
+
+    @Schema(description = "待付款数量")
+    private Integer noPay;
+    @Schema(description = "待发货数量")
+    private Integer dfh;
+    @Schema(description = "已发货数量")
+    private Integer yfh;
+    @Schema(description = "已完成数量")
+    private Integer ywc;
+    @Schema(description = "售后服务数量")
+    private Integer sh;
+}

+ 16 - 0
src/main/java/com/gree/mall/contest/bean/order/ShoppingCartBean.java

@@ -0,0 +1,16 @@
+package com.gree.mall.contest.bean.order;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class ShoppingCartBean {
+
+    @Schema(description = "用户id")
+    private String userId;
+    @Schema(description = "购物清单")
+    private List<BuyGood> buyGoods;
+
+}

+ 19 - 0
src/main/java/com/gree/mall/contest/bean/order/ShoppingCartDetail.java

@@ -0,0 +1,19 @@
+package com.gree.mall.contest.bean.order;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+public class ShoppingCartDetail {
+
+    @Schema(description = "购物车总数量")
+    private Integer totalNum;
+    @Schema(description = "购物车总金额(不含运费)")
+    private BigDecimal totalAmount;
+    @Schema(description = "购物车商品数组")
+    private List<ShoppingCartList> shoppingCartLists;
+
+}

+ 25 - 0
src/main/java/com/gree/mall/contest/bean/order/ShoppingCartList.java

@@ -0,0 +1,25 @@
+package com.gree.mall.contest.bean.order;
+
+import com.gree.mall.contest.plus.entity.ShoppingCart;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class ShoppingCartList extends ShoppingCart {
+
+    @Schema(description = "单价")
+    private BigDecimal price;
+    @Schema(description = "商品名称")
+    private String goodsName;
+    @Schema(description = "划线价格")
+    private BigDecimal orgPrice;
+    @Schema(description = "规格值")
+    private String specValue;
+    @Schema(description = "当前商品总价(单价*数量)")
+    private BigDecimal totalPrice;
+    @Schema(description = "商品图")
+    private String goodsImg;
+
+}

+ 26 - 0
src/main/java/com/gree/mall/contest/bean/user/CurrentCompanyWechat.java

@@ -0,0 +1,26 @@
+package com.gree.mall.contest.bean.user;
+
+import com.gree.mall.contest.plus.entity.AdminCompanyWechat;
+import com.gree.mall.contest.plus.entity.AdminCompanyWechatOther;
+import com.gree.mall.contest.plus.entity.User;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class CurrentCompanyWechat extends AdminCompanyWechat {
+
+    @Schema(description = "用户id")
+    private String userId;
+    @Schema(description = "当前企业id")
+    private String currentCompanyWechatId;
+    @Schema(description = "当前企业名称")
+    private String currentCompanyName;
+    @Schema(description = "企业其他配置")
+    private AdminCompanyWechatOther adminCompanyWechatOther;
+    @Schema(description = "师傅昵称")
+    private User user;
+
+
+}

+ 18 - 0
src/main/java/com/gree/mall/contest/bean/user/MyProfitBean.java

@@ -0,0 +1,18 @@
+package com.gree.mall.contest.bean.user;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class MyProfitBean {
+    @Schema(description = "总收益")
+    private BigDecimal totalAmount;
+    @Schema(description = "已结算收益")
+    private BigDecimal paidAmount;
+    @Schema(description = "结算中收益")
+    private BigDecimal waitingAmount;
+
+
+}

+ 23 - 0
src/main/java/com/gree/mall/contest/bean/user/RankBean.java

@@ -0,0 +1,23 @@
+package com.gree.mall.contest.bean.user;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+public class RankBean {
+    @Schema(description = "排行榜")
+    private List<RankItemBean> rankList;
+    @Schema(description = "我的排名")
+    private RankItemBean myRank;
+    @Schema(description = "开始时间")
+    private String startPeriod;
+    @Schema(description = "结束时间")
+    private String endPeriod;
+    @Schema(description = "业绩是否上涨,true:上涨,false:下降")
+    private Boolean upOrDown;
+    @Schema(description = "上月业绩")
+    private BigDecimal income;
+}

+ 24 - 0
src/main/java/com/gree/mall/contest/bean/user/RankItemBean.java

@@ -0,0 +1,24 @@
+package com.gree.mall.contest.bean.user;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class RankItemBean {
+    @Schema(description = "业务员id")
+    private String workUserId;
+    @Schema(description = "业务员名称")
+    private String workUserName;
+    @Schema(description = "总销售额")
+    private BigDecimal total;
+    @Schema(description = "排名")
+    private Integer ranking;
+    @Schema(description = "网点")
+    private String websitName;
+    @Schema(description = "头像")
+    private String avatar;
+
+
+}

+ 22 - 0
src/main/java/com/gree/mall/contest/bean/user/ServiceWorkerBean.java

@@ -0,0 +1,22 @@
+package com.gree.mall.contest.bean.user;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+@Data
+@Accessors(chain = true)
+public class ServiceWorkerBean {
+    @Schema(description =  "业务员真实姓名")
+    private String workerRealName;
+    @Schema(description =  "业务员网点名称")
+    private String websit;
+    @Schema(description =  "业务员职位")
+    private String position;
+    @Schema(description = "网点主键id")
+    private String adminWebsitId;
+    @Schema(description = "网点id")
+    private Long websitId;
+    private String orderId;
+
+}

+ 31 - 0
src/main/java/com/gree/mall/contest/bean/user/UserAddressBean.java

@@ -0,0 +1,31 @@
+package com.gree.mall.contest.bean.user;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Data
+public class UserAddressBean {
+    @Schema(description =  "地址id")
+    private String userAddressId;
+
+    @Schema(description =  "用户id")
+    private String userId;
+    @Schema(description =  "收货人姓名")
+    private String name;
+    @Schema(description =  "收货电话")
+    private String phone;
+    @Schema(description =  "省")
+    private String province;
+    @Schema(description =  "市")
+    private String city;
+    @Schema(description =  "区")
+    private String area;
+    @Schema(description = "街道")
+    private String street;
+    @Schema(description =  "收货地址")
+    private String address;
+    @Schema(description =  "门牌号")
+    private String houseNo;
+    @Schema(description =  "是否默认地址")
+    private Boolean defaultAddr;
+}

+ 9 - 0
src/main/java/com/gree/mall/contest/bean/user/UserWxBean.java

@@ -23,4 +23,13 @@ public class UserWxBean extends User {
     private String workerName;
     @Schema(description = "业务员自己电话")
     private String workerPhone;
+
+    @Schema(description = "token")
+    private String token;
+    @Schema(description = "购物车商品数量")
+    private Integer shoppingCartNums = 0;
+    @Schema(description = "网点编号")
+    private String websitNumber;
+    @Schema(description = "业务员信息")
+    private ServiceWorkerBean serviceWorkerBean;
 }

+ 0 - 2
src/main/java/com/gree/mall/contest/commonmapper/AdminMapper.java

@@ -5,11 +5,9 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.gree.mall.contest.bean.admin.AdminFastEntryVO;
 import com.gree.mall.contest.bean.zfire.ZfireParamBean;
-import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Update;
 
-@Mapper
 public interface AdminMapper {
     
     @Update("update mp_ma_rela a \n" +

+ 43 - 0
src/main/java/com/gree/mall/contest/commonmapper/AppMapper.java

@@ -0,0 +1,43 @@
+package com.gree.mall.contest.commonmapper;
+
+
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.gree.mall.contest.bean.goods.GoodsNewBean;
+import com.gree.mall.contest.bean.order.OrderStatusBean;
+import com.gree.mall.contest.bean.order.ShoppingCartList;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface AppMapper {
+
+    /**
+     * 查询购物车的商品清单
+     * @param userId
+     * @return
+     */
+    @InterceptorIgnore(tenantLine = "true")
+    public List<ShoppingCartList> queryShoppingCartList(@Param("userId") String userId);
+
+
+    /**
+     * 查询各订单状态数量
+     */
+    @InterceptorIgnore(tenantLine = "true")
+    public OrderStatusBean orderStatusCount(@Param("userId") String userId);
+
+    /**
+     * 精选分类商品
+     */
+    @InterceptorIgnore(tenantLine = "true")
+    public IPage<GoodsNewBean> queryNewGoods(
+            IPage ipage,
+            @Param("objId") String objId,
+            @Param("type") String type,
+            @Param("companyWechatId") String companyWechatId,
+            @Param("sort") Integer sort
+    );
+
+
+}

+ 3 - 1
src/main/java/com/gree/mall/contest/commonmapper/CustomMemberMapper.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.gree.mall.contest.bean.member.MemberBean;
+import com.gree.mall.contest.bean.user.MyProfitBean;
 import com.gree.mall.contest.bean.user.UserApplyBean;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
@@ -22,5 +23,6 @@ public interface CustomMemberMapper {
                                                @Param("companyWechatIds") List<String> companyWechatIds,
                                                @Param("keyword") String keyword,
                                                @Param("status") String status);
-
+    @InterceptorIgnore(tenantLine = "true")
+    MyProfitBean queryProfitSum(@Param("workUserId") String workUserId, @Param("userId") String userId);
 }

+ 24 - 0
src/main/java/com/gree/mall/contest/commonmapper/OrderShareRankMapper.java

@@ -0,0 +1,24 @@
+package com.gree.mall.contest.commonmapper;
+
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
+import com.gree.mall.contest.bean.user.RankItemBean;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.Date;
+import java.util.List;
+
+@Mapper
+public interface OrderShareRankMapper {
+
+    @InterceptorIgnore(tenantLine = "true")
+    List<RankItemBean> queryRankList(@Param("userId") String userId,
+                                     @Param("startTime") Date startTime,
+                                     @Param("endTime") Date endTime,
+                                     @Param("companyWechatId") String companyWechatId);
+
+    @InterceptorIgnore(tenantLine = "true")
+    RankItemBean queryWorkerInfo(@Param("userId") String userId,@Param("companyWechatId") String companyWechatId);
+
+
+}

+ 22 - 0
src/main/java/com/gree/mall/contest/config/MulitpartConfig.java

@@ -0,0 +1,22 @@
+package com.gree.mall.contest.config;
+
+import org.springframework.boot.web.servlet.MultipartConfigFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.servlet.MultipartConfigElement;
+
+@Configuration
+public class MulitpartConfig {
+
+    /**
+     * 文件上传临时路径
+     */
+    @Bean
+    MultipartConfigElement multipartConfigElement() {
+        MultipartConfigFactory factory = new MultipartConfigFactory();
+        factory.setLocation("/app");
+        return factory.createMultipartConfig();
+    }
+
+}

+ 21 - 0
src/main/java/com/gree/mall/contest/config/ScheduleConfig.java

@@ -0,0 +1,21 @@
+package com.gree.mall.contest.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.SchedulingConfigurer;
+import org.springframework.scheduling.config.ScheduledTaskRegistrar;
+
+import java.util.concurrent.Executors;
+
+/**
+ * schedule定时任务多线程
+ * 2019-02-21
+ */
+
+@Configuration
+public class ScheduleConfig implements SchedulingConfigurer {
+
+    @Override
+    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
+        scheduledTaskRegistrar.setScheduler(Executors.newScheduledThreadPool(10));
+    }
+}

+ 3 - 21
src/main/java/com/gree/mall/contest/config/aop/ApiAspect.java

@@ -21,6 +21,7 @@ import org.springframework.web.context.request.ServletRequestAttributes;
 
 import javax.servlet.http.HttpServletRequest;
 import java.lang.reflect.Method;
+import java.util.Objects;
 
 @Aspect
 @Slf4j
@@ -63,30 +64,11 @@ public class ApiAspect {
         if (StringUtils.isBlank(userId)) {
             throw new RemoteServiceException(ResponseHelper.ResponseCode_AUTH_ERROR, "请求不合法");
         }
-        //taijpcapi=pc  zfminiapp = 小程序接口
+        // pcapi=pc  miniapp = 小程序接口
         String issuer = CommonUtils.getIssuer(request);
-        if(!servletPath.contains(issuer)){
+        if(Objects.isNull(issuer) || !servletPath.contains(issuer)){
             throw new RemoteServiceException("暂无权限访问,请联系相关人员");
         }
-        //如果是师傅,状态无效,无法访问
-//        String appid = CommonUtils.getAPPID();
-//        if(StringUtils.isNotBlank(appid)) {
-//            AdminCompanyWechat adminCompanyWechat = (AdminCompanyWechat) redisUtil.get(Constant.RedisPrefix.CLIENT + appid);
-//            if (adminCompanyWechat == null) {
-//                throw new RemoteServiceException("非法请求");
-//            }
-//            if (adminCompanyWechat.getFlag() == 2) {
-//                User user = userService.getById(userId);
-//                //还未授权手机号的不用检查
-//                if (StringUtils.isBlank(user.getMobile())) {
-//                    return;
-//                }
-//                Integer count = workerService.lambdaQuery().eq(Worker::getUserId, userId).eq(Worker::getStatus, true).count();
-//                if (count == 0) {
-//                    throw new RemoteServiceException("您暂未入驻任何网点");
-//                }
-//            }
-//        }
 
     }
 

+ 2 - 0
src/main/java/com/gree/mall/contest/constant/Constant.java

@@ -55,6 +55,8 @@ public class Constant {
         public final static String SERVICE2_PAY_BILL = "mall:contest:service2:pay:bill:";
         public final static String COUPON_STOCK_LOCK = "mall:contest:COUPON_STOCK_LOCK";
         public final static String LOCK_ORDER = "mall:contest:lock:order:";
+        public final static String LOCK_AUTH = "mall:contest:lock:auth:";
+        public final static String LOCK_ORDER_STOCK = "mall:contest:lock:stock";
 
         public final static String CLIENT = "mall:contest:client:";
     }

+ 78 - 0
src/main/java/com/gree/mall/contest/controller/mini/user/AddressController.java

@@ -0,0 +1,78 @@
+package com.gree.mall.contest.controller.mini.user;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.gree.mall.contest.bean.user.UserAddressBean;
+import com.gree.mall.contest.helper.ResponseHelper;
+import com.gree.mall.contest.logic.user.AddressLogic;
+import com.gree.mall.contest.plus.entity.UserAddress;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+
+@Slf4j
+@RestController
+@Tag(name = "小程序用户地址", description = "小程序用户地址")
+@RequestMapping(value = "/miniapp/user/address", produces = "application/json; charset=utf-8")
+@RequiredArgsConstructor
+public class AddressController {
+
+    private final AddressLogic addressLogic;
+
+    @PostMapping("/save")
+    @Operation(summary = "添加地址")
+    public ResponseHelper<UserAddress> saveAddress(
+            HttpServletRequest request,
+            @Parameter(description = "object",required = true) @RequestBody UserAddressBean userAddressBean
+    ) throws Exception{
+        UserAddress userAddress = addressLogic.saveAddress(request , userAddressBean);
+        return ResponseHelper.success(userAddress);
+    }
+
+    @PostMapping("/update")
+    @Operation(summary = "修改地址")
+    public ResponseHelper<UserAddress> updateAddress(
+            HttpServletRequest request,
+            @Parameter(description = "object",required = true) @RequestBody UserAddressBean  userAddressBean
+    ) throws Exception{
+        addressLogic.updateAddress(request, userAddressBean);
+        return ResponseHelper.success();
+    }
+
+    @PostMapping("/del")
+    @Operation(summary = "删除地址")
+    public ResponseHelper<String> delAddress(
+            @Parameter(description = "用户地址id", required = true) @RequestParam(required = true) String userAddressId
+    ) throws Exception{
+        String addressId = addressLogic.delAddress(userAddressId);
+        return ResponseHelper.success(addressId);
+    }
+    @GetMapping("/detail")
+    @Operation(summary = "获取地址详情")
+    public ResponseHelper<UserAddress> addressDetail(
+            @Parameter(description = "用户地址id", required = true) @RequestParam(required = true) String userAddressId
+    ) throws Exception{
+        UserAddress userAddress = addressLogic.addressDetail(userAddressId);
+        return ResponseHelper.success(userAddress);
+    }
+
+
+    @GetMapping("/list")
+    @Operation(summary = "地址列表")
+    public ResponseHelper<Page<UserAddress>> pageAddress(
+            @Parameter(description = "用户id", required = true) @RequestParam(required = true) String userId,
+            @Parameter(description = "页号",required = true) @RequestParam Integer pageNum,
+            @Parameter(description = "页大小",required = true) @RequestParam Integer pageSize
+    ) throws Exception{
+
+        IPage<UserAddress> page = addressLogic.page(userId,pageNum,pageSize);
+        return ResponseHelper.success(page);
+    }
+
+
+}

+ 182 - 0
src/main/java/com/gree/mall/contest/controller/mini/user/UserController.java

@@ -0,0 +1,182 @@
+package com.gree.mall.contest.controller.mini.user;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.aliyuncs.utils.StringUtils;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.gree.mall.contest.annotation.ApiNotAuth;
+import com.gree.mall.contest.bean.user.MyProfitBean;
+import com.gree.mall.contest.bean.user.RankBean;
+import com.gree.mall.contest.bean.user.RankItemBean;
+import com.gree.mall.contest.bean.user.UserWxBean;
+import com.gree.mall.contest.exception.RemoteServiceException;
+import com.gree.mall.contest.helper.ResponseHelper;
+import com.gree.mall.contest.logic.user.UserLogic;
+import com.gree.mall.contest.plus.entity.OrderShare;
+import com.gree.mall.contest.plus.entity.User;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.math.BigDecimal;
+
+@Slf4j
+@RestController
+@Tag(name = "小程序用户", description = "小程序用户")
+@RequestMapping(value = "/miniapp/user", produces = "application/json; charset=utf-8")
+@RequiredArgsConstructor
+public class UserController {
+
+
+    private final UserLogic userLogic;
+
+    @PostMapping("/bind")
+    @Operation(summary = "绑定业务员")
+    public ResponseHelper grantMobile(
+            @Parameter(description = "用户id", required = true) @RequestParam String userId,
+            @Parameter(description = "业务员用户id", required = true) @RequestParam String serviceId
+    ) throws Exception {
+        userLogic.bind(userId, serviceId);
+        return ResponseHelper.success();
+    }
+
+    @GetMapping("/qrcode/bind")
+    @Operation(summary = "获取业务员绑定小程序码")
+    public ResponseHelper bindQrCode(HttpServletRequest request) throws Exception {
+        return ResponseHelper.success(userLogic.bindQrCode(request));
+    }
+
+    @GetMapping("/rank")
+    @Operation(summary = "上月业绩排行榜")
+    public ResponseHelper rank(HttpServletRequest request) throws Exception {
+        RankBean rank = userLogic.rank(request);
+        if (rank != null && CollectionUtil.isNotEmpty(rank.getRankList())) {
+            for (RankItemBean bean : rank.getRankList()) {
+                if (StringUtils.isNotEmpty(bean.getWorkUserName())) {
+                    bean.setWorkUserName(bean.getWorkUserName().charAt(0) + "**");
+                }
+            }
+        }
+        return ResponseHelper.success(rank);
+    }
+
+
+    @ApiNotAuth
+    @PostMapping("/auth")
+    @Operation(summary = "微信授权")
+    public ResponseHelper<UserWxBean> auth(
+            @Parameter(description = "业务员用户id", required = false) @RequestParam(required = false) String serviceId,
+            @Parameter(description = "code", required = true) @RequestParam String code,
+            HttpServletRequest request
+    ) throws Exception {
+        UserWxBean userWxBean;
+        log.info("微信授权 code:{} serviceId:{} ", code, serviceId);
+        userWxBean = userLogic.addUser(code, serviceId, request);
+        userLogic.addVisit(request, userWxBean.getUserId());
+        log.info(userWxBean.toString());
+        return ResponseHelper.success(userWxBean);
+    }
+
+    @ApiNotAuth
+    @PostMapping("/mobile/grant")
+    @Operation(summary = "授权手机号")
+    public ResponseHelper<UserWxBean> grantMobile(
+            @Parameter(description = "code", required = true) @RequestParam String code,
+            @Parameter(description = "用户id", required = true) @RequestParam String userId,
+            HttpServletRequest request
+    ) throws Exception {
+        UserWxBean wxMobile = userLogic.getWxMobile(code, userId, request);
+        return ResponseHelper.success(wxMobile);
+    }
+
+    @GetMapping("/user/detail")
+    @Operation(summary = "个人信息")
+    public ResponseHelper<UserWxBean> detail(
+            @Parameter(description = "code", required = true) @RequestParam(required = true) String userId,
+            HttpServletRequest request
+    ) throws RemoteServiceException {
+        UserWxBean userWxBean = userLogic.userDetail(userId, request);
+        return ResponseHelper.success(userWxBean);
+    }
+
+    @PostMapping("/userinfo/save")
+    @Operation(summary = "保存微信账号的用户信息")
+    public ResponseHelper<User> saveUserInfo(
+            @Parameter(description = "用户id", required = true) @RequestParam String userId,
+            @Parameter(description = "用户昵称") @RequestParam(required = false) String nickName,
+            @Parameter(description = "性别( 未知 男 女)") @RequestParam(required = false) String sex,
+            @Parameter(description = "头像") @RequestParam(required = false) String avatarUrl,
+            @Parameter(description = "国家") @RequestParam(required = false) String country,
+            @Parameter(description = "省") @RequestParam(required = false) String province,
+            @Parameter(description = "城市") @RequestParam(required = false) String city
+    ) throws Exception {
+        User user = userLogic.saveUserInfo(userId, nickName, sex, avatarUrl, country, province, city);
+        return ResponseHelper.success(user);
+    }
+
+
+    @GetMapping("/profit")
+    @Operation(summary = "我的收益统计")
+    public ResponseHelper<MyProfitBean> userProfit(
+            @Parameter(description = "用户id", required = true) @RequestParam(required = true) String userId
+    ) throws RemoteServiceException {
+        MyProfitBean myProfitBean = userLogic.myProfit(userId);
+        return ResponseHelper.success(myProfitBean);
+    }
+
+    @GetMapping("/profit/list")
+    @Operation(summary = "我的收益明细列表")
+    public ResponseHelper<IPage<OrderShare>> userProfitList(
+            @Parameter(description = "用户id", required = true) @RequestParam String userId,
+            @Parameter(description = "ING=结算中  OVER=已结算  CANCEL=已取消  EXCEPTION=异常结算") @RequestParam(required = false) String status,
+            @Parameter(description = "页号", required = true) @RequestParam Integer pageNum,
+            @Parameter(description = "页大小", required = true) @RequestParam Integer pageSize
+    ) throws RemoteServiceException {
+        IPage<OrderShare> myProfit = userLogic.myProfitList(userId, status, pageNum, pageSize);
+        return ResponseHelper.success(myProfit);
+    }
+
+
+    @GetMapping("/profit/total")
+    @Operation(summary = "总计收益")
+    public ResponseHelper<BigDecimal> totalProfit(
+            @Parameter(description = "用户id", required = true) @RequestParam(required = true) String userId
+    ) throws RemoteServiceException {
+        BigDecimal bigDecimal = userLogic.totalProfit(userId);
+        return ResponseHelper.success(bigDecimal);
+    }
+
+    @GetMapping("/customer")
+    @Operation(summary = "我的客户列表")
+    public ResponseHelper<Page<User>> customerList(
+            @Parameter(description = "用户id", required = true) @RequestParam String userId,
+            @Parameter(description = "pageNum", required = true) @RequestParam Integer pageNum,
+            @Parameter(description = "pageSize", required = true) @RequestParam Integer pageSize
+    ) throws RemoteServiceException {
+        IPage<User> userIPage = userLogic.customerList(userId, pageNum, pageSize);
+        return ResponseHelper.success(userIPage);
+    }
+
+
+    @GetMapping("/parent")
+    @Operation(summary = "我的客户经理")
+    public ResponseHelper<User> parentList(
+            @Parameter(description = "用户id", required = true) @RequestParam String userId
+    ) throws RemoteServiceException {
+        User user = userLogic.parentUser(userId);
+        return ResponseHelper.success(user);
+    }
+
+    @Operation(summary = "续期token")
+    @PostMapping("/renewal")
+    public ResponseHelper<String> renewal(
+            @RequestParam String token
+    ) throws RemoteServiceException {
+        String newToken = userLogic.renewal(token);
+        return ResponseHelper.success(newToken);
+    }
+}

+ 52 - 0
src/main/java/com/gree/mall/contest/controller/mini/user/WorkerController.java

@@ -0,0 +1,52 @@
+package com.gree.mall.contest.controller.mini.user;
+
+import com.gree.mall.contest.exception.RemoteServiceException;
+import com.gree.mall.contest.helper.ResponseHelper;
+import com.gree.mall.contest.logic.user.WorkerLogic;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+
+@Slf4j
+@RestController
+@Tag(name = "申请成为业务员", description = "申请成为业务员")
+@RequestMapping(value = "/miniapp/worker", produces = "application/json; charset=utf-8")
+@RequiredArgsConstructor
+public class WorkerController {
+    private final WorkerLogic workerLogic;
+
+    @PostMapping("/sms/send")
+    @Operation(summary = "发送验证码")
+    public ResponseHelper sendSms(
+            HttpServletRequest request,
+            @Parameter(description = "手机号码",required = true) @RequestParam String phone,
+            @Parameter(description = "滑动验证key",required = false) @RequestParam(required = false) String key,
+            @Parameter(description = "滑动验证数值",required = false) @RequestParam(required = false) String vrifyCode
+    ) throws Exception {
+        workerLogic.sendSms(phone, key, vrifyCode, request);
+        return ResponseHelper.success();
+    }
+
+    @PostMapping("/bind")
+    @Operation(summary = "绑定业务员")
+    public ResponseHelper<String> bind(
+            HttpServletRequest request,
+            @Parameter(description = "手机号码",required = true) @RequestParam String phone,
+            @Parameter(description = "短信验证码",required = true) @RequestParam String code
+    ) throws RemoteServiceException {
+
+        workerLogic.bind(request, phone, code);
+        return ResponseHelper.success("成功提交申请记录");
+    }
+
+
+
+}

+ 16 - 0
src/main/java/com/gree/mall/contest/enums/QrCodeEnum.java

@@ -0,0 +1,16 @@
+package com.gree.mall.contest.enums;
+
+public enum QrCodeEnum {
+    //商品详情
+    GOODS(),
+    //付费订单码
+    ORDER(),
+    //绑定业务员小程序码
+    BIND(),
+    //优惠券码
+    COUPON(),
+    //团购活动码
+    PROMOTION_GROUP,
+    //降价分享码
+    CUT
+}

+ 42 - 0
src/main/java/com/gree/mall/contest/logic/activity/PromotionGroupLogic.java

@@ -11,6 +11,7 @@ import com.gree.mall.contest.bean.activity.PromotionGroupDetail;
 import com.gree.mall.contest.bean.activity.PromotionGroupList;
 import com.gree.mall.contest.bean.admin.AdminUserCom;
 import com.gree.mall.contest.commonmapper.PromotionMapper;
+import com.gree.mall.contest.constant.Constant;
 import com.gree.mall.contest.enums.OrderShareStatusEnum;
 import com.gree.mall.contest.enums.OrderStatusEnum;
 import com.gree.mall.contest.exception.RemoteServiceException;
@@ -20,6 +21,7 @@ import com.gree.mall.contest.plus.service.*;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
+import org.springframework.integration.redis.util.RedisLockRegistry;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -27,6 +29,8 @@ import javax.servlet.http.HttpServletRequest;
 import java.math.BigDecimal;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
 import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
@@ -49,6 +53,7 @@ public class PromotionGroupLogic {
     private final GoodsVisitService goodsVisitService;
     private final GoodsService goodsService;
     private final UserVisitService userVisitService;
+    private final RedisLockRegistry redisLockRegistry;
 
     /**
      * 团购分类统计
@@ -520,5 +525,42 @@ public class PromotionGroupLogic {
         return page;
     }
 
+    public PromotionGroupSpecUser getStock(String userId,String goodsSpecId,int num) throws InterruptedException {
+        PromotionGroupSpecUser promotionGroupSpecUser = promotionGroupSpecUserService.lambdaQuery()
+                .eq(PromotionGroupSpecUser::getUserId, userId)
+                .eq(PromotionGroupSpecUser::getGoodsSpecId, goodsSpecId).one();
+        if (promotionGroupSpecUser == null) {
+            throw new RemoteServiceException("存在商品所属活动已结束");
+        }
+        boolean b = this.checkPromotionGroup(promotionGroupSpecUser.getPromotionGroupId());
+        if(!b){
+            throw new RemoteServiceException("存在商品所属活动已结束");
+        }
+        //处理库存
+        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.LOCK_ORDER_STOCK + ":" + promotionGroupSpecUser.getPromotionGroupSpecId());
+        try {
+            if (obtain.tryLock(5, TimeUnit.SECONDS)) {
+                PromotionGroupSpec promotionGroupSpec = promotionGroupSpecService.getById(promotionGroupSpecUser.getPromotionGroupSpecId());
+                if(promotionGroupSpec.getStock() < num){
+                    throw new RemoteServiceException("下单失败,商品库存不足");
+                }
+                promotionGroupSpec.setStock(promotionGroupSpec.getStock() - num);
+                //promotionGroupSpec.setSalesNum(promotionGroupSpec.getSalesNum() + num);
+                promotionGroupSpec.updateById();
+            }
+        }finally {
+            obtain.unlock();
+        }
 
+        return promotionGroupSpecUser;
+    }
+
+    public boolean checkPromotionGroup(String promotionGroupId){
+        PromotionGroup promotionGroup = promotionGroupService.lambdaQuery()
+                .eq(PromotionGroup::getPromotionGroupId,promotionGroupId)
+                .eq(PromotionGroup::getStatus, true)
+                .le(PromotionGroup::getStartTime, new Date())
+                .ge(PromotionGroup::getEndTime, new Date()).one();
+        return promotionGroup != null;
+    }
 }

+ 35 - 6
src/main/java/com/gree/mall/contest/logic/common/CommonLogic.java

@@ -3,6 +3,7 @@ package com.gree.mall.contest.logic.common;
 import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.collection.ListUtil;
 import com.gree.mall.contest.bean.admin.AdminUserCom;
+import com.gree.mall.contest.bean.user.CurrentCompanyWechat;
 import com.gree.mall.contest.commonmapper.AdminMapper;
 import com.gree.mall.contest.enums.StateEnum;
 import com.gree.mall.contest.enums.admin.RoleTypeEnum;
@@ -325,21 +326,49 @@ public class CommonLogic {
     /**
      * 附件归属绑定
      */
-    public void bindFile(String objId,String objType,List<String> fileIds){
+    public void bindFile(String objId, String objType, List<String> fileIds) {
         //先删除后绑定
         commonFileService.lambdaUpdate()
-                .eq(CommonFile::getObjId,objId)
-                .eq(CommonFile::getObjType,objType)
-                .notIn(CommonFile::getId,fileIds).remove();
+                .eq(CommonFile::getObjId, objId)
+                .eq(CommonFile::getObjType, objType)
+                .notIn(CommonFile::getId, fileIds).remove();
 
-        for(int i =0;i< fileIds.size();i++) {
+        for (int i = 0; i < fileIds.size(); i++) {
             //这里分开每次存储的时候,每个图片创建时间加1秒,方便图片排序用
             commonFileService.lambdaUpdate()
                     .set(CommonFile::getObjId, objId)
                     .set(CommonFile::getObjType, objType)
-                    .set(CommonFile::getCreateTime, DateUtils.addSeconds(new Date(),i))
+                    .set(CommonFile::getCreateTime, DateUtils.addSeconds(new Date(), i))
                     .eq(CommonFile::getId, fileIds.get(i))
                     .update();
         }
     }
+
+    /**
+     * 获取当前用户
+     */
+    public CurrentCompanyWechat getCurrentCompanyWechat(HttpServletRequest request) {
+        String appid = CommonUtils.getAPPID();
+        String userId = CommonUtils.getUserId(request);
+
+        if (com.aliyuncs.utils.StringUtils.isEmpty(appid)) {
+            throw new RemoteServiceException("非法请求,缺少必须的参数");
+        }
+        AdminCompanyWechat adminCompanyWechat = adminCompanyWechatService.lambdaQuery()
+                .eq(AdminCompanyWechat::getSubAppId, appid).one();
+        if (adminCompanyWechat == null) {
+            throw new RemoteServiceException("非法请求,请联系管理员配置必要的参数:" + appid);
+        }
+
+        User user = userService.getById(userId);
+
+        CurrentCompanyWechat currentCompanyWechat = new CurrentCompanyWechat();
+        BeanUtils.copyProperties(adminCompanyWechat, currentCompanyWechat);
+        currentCompanyWechat.setCurrentCompanyWechatId(adminCompanyWechat.getCompanyWechatId());
+        currentCompanyWechat.setCurrentCompanyName(adminCompanyWechat.getCompanyName());
+        currentCompanyWechat.setUserId(CommonUtils.getUserId(request));
+        currentCompanyWechat.setUser(user);
+        return currentCompanyWechat;
+
+    }
 }

+ 240 - 0
src/main/java/com/gree/mall/contest/logic/order/ShoppingCartLogic.java

@@ -0,0 +1,240 @@
+package com.gree.mall.contest.logic.order;
+
+import com.aliyuncs.utils.StringUtils;
+import com.gree.mall.contest.bean.order.BuyGood;
+import com.gree.mall.contest.bean.order.ShoppingCartBean;
+import com.gree.mall.contest.bean.order.ShoppingCartDetail;
+import com.gree.mall.contest.bean.order.ShoppingCartList;
+import com.gree.mall.contest.bean.user.CurrentCompanyWechat;
+import com.gree.mall.contest.commonmapper.AppMapper;
+import com.gree.mall.contest.enums.UserTypeEnum;
+import com.gree.mall.contest.exception.RemoteServiceException;
+import com.gree.mall.contest.logic.activity.PromotionGroupLogic;
+import com.gree.mall.contest.logic.common.CommonLogic;
+import com.gree.mall.contest.plus.entity.MiniNotice;
+import com.gree.mall.contest.plus.entity.PromotionGroupSpecUser;
+import com.gree.mall.contest.plus.entity.ShoppingCart;
+import com.gree.mall.contest.plus.entity.User;
+import com.gree.mall.contest.plus.service.MiniNoticeService;
+import com.gree.mall.contest.plus.service.ShoppingCartService;
+import com.gree.mall.contest.plus.service.UserService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import javax.servlet.http.HttpServletRequest;
+import java.math.BigDecimal;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class ShoppingCartLogic {
+
+    private final PromotionGroupLogic promotionGroupLogic;
+    private final AppMapper appMapper;
+    private final ShoppingCartService shoppingCartService;
+    private final MiniNoticeService miniNoticeService;
+    private final UserService userService;
+    private final CommonLogic commonLogic;
+
+    /**
+     * 查询购物车商品数量
+     */
+    public Integer total(String userId){
+        try {
+            List<ShoppingCartList> shoppingCartLists = this.queryShoppingCart(userId).getShoppingCartLists();
+            if (shoppingCartLists.size() == 0) {
+                return 0;
+            }
+            Integer sum = shoppingCartLists.stream().collect(Collectors.summingInt(x -> x.getNum()));
+            return sum;
+        }catch(Exception e){
+            log.error("【查询购物车商品数量失败】",e);
+            return 0;
+        }
+    }
+
+    /**
+     * 查询购物车
+     */
+    public ShoppingCartDetail queryShoppingCart(String userId) throws InterruptedException {
+
+        List<ShoppingCartList> list = appMapper.queryShoppingCartList(userId);
+        User user = userService.getById(userId);
+        String promotionGroupUserId = user.getPromotionGroupUserId();
+        if(user.getPromotionGroupLeader()){
+            promotionGroupUserId = user.getUserId();
+        }
+        int totalNum = 0;
+        BigDecimal totalAmount = new BigDecimal(0);
+        for(ShoppingCartList shoppingCart : list){
+            String promotionGroupId = shoppingCart.getPromotionGroupId();
+            String secKillId = shoppingCart.getSecKillId();
+            String goodsSpecId = shoppingCart.getGoodsSpecId();
+            //团购活动商品
+            if(StringUtils.isNotEmpty(promotionGroupId)){
+                PromotionGroupSpecUser promotionGroupSpecUser = null;
+                try {
+                    promotionGroupSpecUser = promotionGroupLogic.getStock(promotionGroupUserId, goodsSpecId, 0);
+                }catch(Exception e){}
+                if(promotionGroupSpecUser != null) {
+                    shoppingCart.setPrice(promotionGroupSpecUser.getGroupPrice());
+                    shoppingCart.setOrgPrice(promotionGroupSpecUser.getOrgGoodsPrice());
+                }
+            }
+
+            totalNum += shoppingCart.getNum();
+            totalAmount = totalAmount.add(shoppingCart.getPrice());
+        }
+
+        ShoppingCartDetail shoppingCartDetail = new ShoppingCartDetail();
+        shoppingCartDetail.setTotalAmount(totalAmount);
+        shoppingCartDetail.setTotalNum(totalNum);
+        shoppingCartDetail.setShoppingCartLists(list);
+        return shoppingCartDetail;
+    }
+
+    /**
+     * 添加商品到购物车
+     */
+    public ShoppingCartDetail addShoppingCart(HttpServletRequest request , ShoppingCartBean shoppingCartBean) throws RemoteServiceException, InterruptedException {
+        String userId = shoppingCartBean.getUserId();
+        //先清空
+        this.clearShoppingCart(userId);
+        User user = userService.getById(userId);
+        List<BuyGood> buyGoods = shoppingCartBean.getBuyGoods();
+        if(buyGoods == null || buyGoods.size() == 0){
+           return null;
+        }
+        long count = buyGoods.stream().filter(v -> v.getNum() <= 0).count();
+        if(count > 0){
+            throw new RemoteServiceException("请求失败存在数量小于0的请求数据");
+        }
+        if(!this.checkDist(buyGoods)){
+            throw new RemoteServiceException("有重复数据请重新请求");
+        }
+        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat(request);
+
+        //增加
+        List<ShoppingCart> shoppingCarts = new ArrayList<>();
+        for(BuyGood buyGood : buyGoods){
+            ShoppingCart shoppingCart = new ShoppingCart();
+            shoppingCart.setCreateTime(new Date());
+            shoppingCart.setGoodsId(buyGood.getGoodsId());
+            shoppingCart.setGoodsSpecId(buyGood.getGoodsSpecId());
+            shoppingCart.setNum(buyGood.getNum());
+            shoppingCart.setUserId(userId);
+            shoppingCart.setPromotionGroupId(buyGood.getPromotionGroupId());
+            shoppingCart.setSecKillId(buyGood.getSecKillId());
+            if(user.getType().equals(UserTypeEnum.GENERAL.toString())) {
+                shoppingCart.setWxSceneId(buyGood.getWxSceneId());
+            }
+            shoppingCart.setCompanyWechatId(currentCompanyWechat.getCurrentCompanyWechatId());
+            shoppingCart.setCompanyName(currentCompanyWechat.getCurrentCompanyName());
+            shoppingCarts.add(shoppingCart);
+        }
+        shoppingCartService.saveBatch(shoppingCarts);
+
+        return this.queryShoppingCart(userId);
+    }
+
+
+    /**
+     * 添加一条商品到购物车
+     * @param shoppingCartBean
+     * @return
+     * @throws RemoteServiceException
+     */
+    public ShoppingCartDetail addOne(HttpServletRequest request,ShoppingCartBean shoppingCartBean) throws RemoteServiceException, InterruptedException {
+        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat(request);
+
+        String userId = shoppingCartBean.getUserId();
+        User user = userService.getById(userId);
+
+        List<BuyGood> buyGoods = shoppingCartBean.getBuyGoods();
+        if(buyGoods == null || buyGoods.size() == 0 || buyGoods .size() > 1){
+            return null;
+        }
+        BuyGood buyGood = buyGoods.get(0);
+        if(buyGood.getNum() == 0){
+            throw new RemoteServiceException("请求失败存在数量小于0的请求数据");
+        }
+        String goodsId = buyGood.getGoodsId();
+        String goodsSpecId = buyGood.getGoodsSpecId();
+        ShoppingCart shoppingCart = shoppingCartService.lambdaQuery()
+                .eq(ShoppingCart::getGoodsId, goodsId)
+                .eq(ShoppingCart::getGoodsSpecId, goodsSpecId)
+                .eq(ShoppingCart::getUserId, userId)
+                .one();
+        if(shoppingCart == null){
+            ShoppingCart bean = new ShoppingCart();
+            bean.setCreateTime(new Date());
+            bean.setGoodsId(buyGood.getGoodsId());
+            bean.setGoodsSpecId(buyGood.getGoodsSpecId());
+            bean.setNum(buyGood.getNum());
+            bean.setUserId(userId);
+            bean.setPromotionGroupId(buyGood.getPromotionGroupId());
+            bean.setSecKillId(buyGood.getSecKillId());
+            if(user.getType().equals(UserTypeEnum.GENERAL.toString())) {
+                bean.setWxSceneId(buyGood.getWxSceneId());
+            }
+            bean.setCompanyWechatId(currentCompanyWechat.getCurrentCompanyWechatId());
+            bean.setCompanyName(currentCompanyWechat.getCurrentCompanyName());
+            bean.insert();
+        }else{
+            shoppingCart.setNum(shoppingCart.getNum()+buyGood.getNum());
+            shoppingCart.updateById();
+        }
+        return this.queryShoppingCart(userId);
+    }
+
+    /**
+     * 清空购物车
+     */
+    public void clearShoppingCart(String userId){
+        shoppingCartService.lambdaUpdate().eq(ShoppingCart::getUserId,userId).remove();
+    }
+
+    /**
+     * 判断是否重复
+     */
+    public Boolean checkDist(List<BuyGood> buyGoods){
+
+        Set<String> set = new HashSet<>();
+        for(BuyGood buyGood : buyGoods){
+            set.add(buyGood.getGoodsId()+""+buyGood.getGoodsSpecId());
+        }
+        if(set.size() != buyGoods.size()){
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 删除选中的商品
+     */
+    public ShoppingCartDetail remove(String userId,List<String> shoppingCartIds) throws InterruptedException {
+        shoppingCartService.lambdaUpdate().in(ShoppingCart::getShoppingCartId,shoppingCartIds).remove();
+        return this.queryShoppingCart(userId);
+    }
+
+    /**
+     * 消息通知
+     */
+    public String miniNotice(HttpServletRequest request){
+        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat(request);
+
+        List<MiniNotice> list = miniNoticeService.lambdaQuery()
+                .eq(MiniNotice::getStatus, true)
+                .eq(MiniNotice::getCompanyWechatId , currentCompanyWechat.getCurrentCompanyWechatId())
+                .list();
+        if(list.size() > 0){
+            return list.get(0).getNoticeContent();
+        }
+        return "";
+    }
+
+
+}

+ 109 - 0
src/main/java/com/gree/mall/contest/logic/user/AddressLogic.java

@@ -0,0 +1,109 @@
+package com.gree.mall.contest.logic.user;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.gree.mall.contest.bean.user.CurrentCompanyWechat;
+import com.gree.mall.contest.bean.user.UserAddressBean;
+import com.gree.mall.contest.logic.common.CommonLogic;
+import com.gree.mall.contest.plus.entity.FreightTemplateDetail;
+import com.gree.mall.contest.plus.entity.UserAddress;
+import com.gree.mall.contest.plus.service.FreightTemplateDetailService;
+import com.gree.mall.contest.plus.service.UserAddressService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Date;
+import java.util.Objects;
+
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class AddressLogic {
+
+    private final FreightTemplateDetailService freightTemplateDetailService;
+    private final UserAddressService userAddressService;
+    private final CommonLogic commonLogic;
+
+    public UserAddress saveAddress(HttpServletRequest request, UserAddressBean userAddressBean) {
+        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat(request);
+
+        UserAddress userAddress = new UserAddress();
+        BeanUtils.copyProperties(userAddressBean, userAddress);
+        userAddress.setUserAddressId(null);
+        Long count = freightTemplateDetailService.lambdaQuery()
+                .eq(StringUtils.isNotBlank(userAddressBean.getProvince()), FreightTemplateDetail::getProvince, userAddressBean.getProvince())
+                .eq(StringUtils.isNotBlank(userAddressBean.getCity()), FreightTemplateDetail::getCity, userAddressBean.getCity())
+                .eq(FreightTemplateDetail::getCompanyWechatId , currentCompanyWechat.getCurrentCompanyWechatId())
+                .count();
+        userAddress.setStatus(count > 0);
+        userAddress.setCreateTime(new Date());
+        if (userAddressBean.getDefaultAddr() != null && userAddressBean.getDefaultAddr()) {
+            userAddressService.lambdaUpdate().eq(UserAddress::getUserId, userAddressBean.getUserId())
+                    .set(UserAddress::getDefaultAddr, false)
+                    .update();
+        }
+        userAddress.setCompanyWechatId(currentCompanyWechat.getCurrentCompanyWechatId());
+        userAddress.setCompanyName(currentCompanyWechat.getCurrentCompanyName());
+        userAddressService.save(userAddress);
+        return userAddress;
+    }
+
+    public void updateAddress(HttpServletRequest request , UserAddressBean userAddressBean) {
+        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat(request);
+
+        BeanUtils.copyProperties(userAddressBean, userAddressBean);
+        Long count = freightTemplateDetailService.lambdaQuery()
+                .eq(StringUtils.isNotBlank(userAddressBean.getProvince()), FreightTemplateDetail::getProvince, userAddressBean.getProvince())
+                .eq(StringUtils.isNotBlank(userAddressBean.getCity()), FreightTemplateDetail::getCity, userAddressBean.getCity())
+                .eq(FreightTemplateDetail::getCompanyWechatId , currentCompanyWechat.getCurrentCompanyWechatId())
+                .count();
+        boolean status = count > 0;
+        if (userAddressBean.getDefaultAddr() != null && userAddressBean.getDefaultAddr()) {
+            userAddressService.lambdaUpdate().eq(UserAddress::getUserId, userAddressBean.getUserId())
+                    .set(UserAddress::getDefaultAddr, false)
+                    .update();
+        }
+        userAddressService.lambdaUpdate().eq(UserAddress::getUserAddressId, userAddressBean.getUserAddressId())
+                .set(StringUtils.isNotBlank(userAddressBean.getAddress()), UserAddress::getAddress, userAddressBean.getAddress())
+                .set(StringUtils.isNotBlank(userAddressBean.getProvince()), UserAddress::getProvince, userAddressBean.getProvince())
+                .set(StringUtils.isNotBlank(userAddressBean.getCity()), UserAddress::getCity, userAddressBean.getCity())
+                .set(StringUtils.isNotBlank(userAddressBean.getArea()), UserAddress::getArea, userAddressBean.getArea())
+                .set(StringUtils.isNotBlank(userAddressBean.getHouseNo()), UserAddress::getHouseNo, userAddressBean.getHouseNo())
+                .set(StringUtils.isNotBlank(userAddressBean.getName()), UserAddress::getName, userAddressBean.getName())
+                .set(StringUtils.isNotBlank(userAddressBean.getPhone()), UserAddress::getPhone, userAddressBean.getPhone())
+                .set(UserAddress::getStatus, status)
+                .set(StringUtils.isNotEmpty(userAddressBean.getStreet()), UserAddress::getStreet, userAddressBean.getStreet())
+                .set(!Objects.isNull(userAddressBean.getDefaultAddr()), UserAddress::getDefaultAddr, userAddressBean.getDefaultAddr())
+                .update();
+    }
+
+
+    public String delAddress(String userAddressId) {
+
+        userAddressService.lambdaUpdate().eq(UserAddress::getUserAddressId, userAddressId).remove();
+        return userAddressId;
+    }
+
+
+    public UserAddress addressDetail(String userAddressId) {
+
+        UserAddress userAddress = userAddressService.lambdaQuery().eq(UserAddress::getUserAddressId, userAddressId).one();
+        return userAddress;
+    }
+
+    public IPage<UserAddress> page(String userId, Integer pageNum, Integer pageSize) {
+        return userAddressService.lambdaQuery()
+                .eq(StringUtils.isNotBlank(userId), UserAddress::getUserId, userId)
+                .orderByDesc(UserAddress::getCreateTime)
+                .page(new Page(pageNum, pageSize));
+
+    }
+
+
+}
+
+

+ 494 - 14
src/main/java/com/gree/mall/contest/logic/user/UserLogic.java

@@ -1,8 +1,11 @@
 package com.gree.mall.contest.logic.user;
 
+import cn.binarywang.wx.miniapp.api.WxMaService;
+import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
 import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.IdUtil;
 import cn.hutool.json.JSONArray;
 import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -10,23 +13,29 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.gree.mall.contest.bean.ExcelData;
 import com.gree.mall.contest.bean.admin.AdminUserCom;
+import com.gree.mall.contest.bean.common.WechatOpenBean;
 import com.gree.mall.contest.bean.member.MemberBean;
 import com.gree.mall.contest.bean.member.MemberSortBean;
-import com.gree.mall.contest.bean.user.UserApplyBean;
-import com.gree.mall.contest.bean.user.UserWxBean;
+import com.gree.mall.contest.bean.user.*;
 import com.gree.mall.contest.commonmapper.CustomGoodsMapper;
 import com.gree.mall.contest.commonmapper.CustomMemberMapper;
-import com.gree.mall.contest.commonmapper.CustomWebsitMapper;
+import com.gree.mall.contest.commonmapper.OrderShareRankMapper;
+import com.gree.mall.contest.constant.Constant;
+import com.gree.mall.contest.enums.OrderShareStatusEnum;
+import com.gree.mall.contest.enums.QrCodeEnum;
 import com.gree.mall.contest.enums.UserTypeEnum;
 import com.gree.mall.contest.exception.RemoteServiceException;
+import com.gree.mall.contest.helper.ResponseHelper;
 import com.gree.mall.contest.logic.activity.PromotionGroupLogic;
 import com.gree.mall.contest.logic.common.CommonLogic;
 import com.gree.mall.contest.logic.common.WechatLogic;
 import com.gree.mall.contest.logic.coupon.CouponLogic;
 import com.gree.mall.contest.logic.order.OrderShareLogic;
+import com.gree.mall.contest.logic.order.ShoppingCartLogic;
 import com.gree.mall.contest.plus.entity.*;
 import com.gree.mall.contest.plus.service.*;
 import com.gree.mall.contest.utils.CommonUtils;
+import com.gree.mall.contest.utils.JwtUtils;
 import com.gree.mall.contest.utils.RedisUtil;
 import com.gree.mall.contest.utils.excel.ExcelUtils;
 import lombok.RequiredArgsConstructor;
@@ -35,6 +44,7 @@ import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringEscapeUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.BeanUtils;
+import org.springframework.integration.redis.util.RedisLockRegistry;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
@@ -42,8 +52,11 @@ import org.springframework.web.multipart.MultipartFile;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
+import java.math.BigDecimal;
 import java.text.SimpleDateFormat;
 import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
@@ -57,20 +70,22 @@ public class UserLogic {
 
     private final UserService userService;
     private final UserAddressService userAddressService;
-    private final GoodsFavoriteService goodsFavoriteService;
     private final GoodsVisitService goodsVisitService;
     private final CustomGoodsMapper customGoodsMapper;
-    private final CustomWebsitMapper customWebsitMapper;
     private final CustomMemberMapper customMemberMapper;
     private final CouponLogic couponLogic;
     private final OrderShareLogic orderShareLogic;
-    private final RedisUtil redisUtil;
     private final WechatLogic wechatLogic;
     private final PromotionGroupLogic promotionGroupLogic;
     private final CommonLogic commonLogic;
     private final UserServiceApplyService userServiceApplyService;
     private final UserServiceWaitService userServiceWaitService;
     private final AdminWebsitService adminWebsitService;
+    private final OrderShareRankMapper orderShareRankMapper;
+    private final RedisLockRegistry redisLockRegistry;
+    private final ShoppingCartLogic shoppingCartLogic;
+    private final OrderShareService orderShareService;
+    private final RedisUtil redisUtil;
 
     /**
      * 会员列表
@@ -269,17 +284,17 @@ public class UserLogic {
 
             AdminWebsit adminWebsit;
 
+            adminWebsit = adminWebsitService.lambdaQuery()
+                    .eq(AdminWebsit::getCompanyWechatId, companyWechat.getCompanyWechatId())
+                    .eq(AdminWebsit::getWebsitNumber, user.getWebsitId())
+                    .one();
+            if (Objects.isNull(adminWebsit)) {
                 adminWebsit = adminWebsitService.lambdaQuery()
                         .eq(AdminWebsit::getCompanyWechatId, companyWechat.getCompanyWechatId())
-                        .eq(AdminWebsit::getWebsitNumber, user.getWebsitId())
+                        .orderByAsc(AdminWebsit::getCreateTime)
+                        .last("limit 1")
                         .one();
-                if (Objects.isNull(adminWebsit)) {
-                    adminWebsit = adminWebsitService.lambdaQuery()
-                            .eq(AdminWebsit::getCompanyWechatId, companyWechat.getCompanyWechatId())
-                            .orderByAsc(AdminWebsit::getCreateTime)
-                            .last("limit 1")
-                            .one();
-                }
+            }
 
             user.setWebsitId(adminWebsit.getWebsitId() + "");
             user.setWebsitName(adminWebsit.getName());
@@ -627,4 +642,469 @@ public class UserLogic {
         IPage<UserApplyBean> page = customMemberMapper.queryServiceApplyList(new Page<>(pageNum, pageSize), companyWechatIds, keyword, status);
         return page;
     }
+
+    /**
+     * 绑定业务员
+     */
+    public void bind(String userId, String serviceId) {
+        User user = userService.getById(userId);
+        User service = userService.getById(serviceId);
+        //绑定业务员
+        if (user.getType().equals(UserTypeEnum.GENERAL.toString()) && service.getType().equals(UserTypeEnum.SERVICE.toString())) {
+            user.setServiceId(serviceId);
+            user.setServiceTime(new Date());
+        }
+
+        //判断是否为团长
+        if (!user.getPromotionGroupLeader()) {
+            if (service.getPromotionGroupLeader()) {
+                user.setPromotionGroupUserId(serviceId);
+            } else {
+                String promotionGroupUserId = service.getPromotionGroupUserId();
+                user.setPromotionGroupUserId(promotionGroupUserId);
+            }
+        }
+
+        user.updateById();
+    }
+
+    /**
+     * 获取绑定业务员小程序码
+     */
+    public String bindQrCode(HttpServletRequest request) throws RemoteServiceException {
+        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat(request);
+        String userId = CommonUtils.getUserId(request);
+        User user = userService.lambdaQuery()
+                .eq(User::getUserId, userId)
+                .eq(User::getStatus, true)
+                .one();
+        if (user == null) {
+            throw new RemoteServiceException("用户不存在");
+        }
+        if (StringUtils.isNotEmpty(user.getBindQrcode())) {
+            return user.getBindQrcode();
+        }
+        String qrcode = null;
+        try {
+            qrcode = wechatLogic.getQrcode(QrCodeEnum.BIND.toString().toLowerCase(Locale.ROOT),
+                    user.getWorkUserId(), user.getUserId(), currentCompanyWechat.getCompanyWechatId());
+            if (StringUtils.isNotEmpty(qrcode)) {
+                user.setBindQrcode(qrcode);
+                userService.updateById(user);
+            }
+        } catch (Exception e) {
+            log.error("获取绑定业务员小程序码失败", e);
+        }
+        return qrcode;
+
+    }
+
+    public RankBean rank(HttpServletRequest request) throws RemoteServiceException {
+        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat(request);
+        String userId = CommonUtils.getUserId(request);
+        User user = userService.lambdaQuery()
+                .eq(User::getUserId, userId)
+                .eq(User::getStatus, true)
+                .one();
+        if (user == null || StringUtils.isEmpty(user.getWorkUserId())) {
+            throw new RemoteServiceException("业务员不存在");
+        }
+
+        Date now = new Date();
+        Date endTime = DateUtil.beginOfMonth(now);
+        Date startTime = DateUtil.beginOfMonth(DateUtil.lastMonth());
+        Date endTimeDay = DateUtil.offsetDay(now, -1);
+        RankBean rankBean = new RankBean();
+        List<RankItemBean> rankItemBeans = orderShareRankMapper.queryRankList(null, endTime, endTimeDay, currentCompanyWechat.getCompanyWechatId());
+        List<RankItemBean> myRanks = null;
+        if (rankItemBeans != null && rankItemBeans.size() > 0) {
+            rankBean.setRankList(rankItemBeans.size() > 10 ? rankItemBeans.subList(0, 10) : rankItemBeans);
+            //此处的workUserId就是userId
+            myRanks = rankItemBeans.stream()
+                    .filter(o -> o.getWorkUserId() != null && o.getWorkUserId().equals(user.getUserId()))
+                    .limit(1)
+                    .collect(Collectors.toList());
+        }
+        RankItemBean myrank = myRanks != null && myRanks.size() > 0 ? myRanks.get(0) : orderShareRankMapper.queryWorkerInfo(user.getUserId(), currentCompanyWechat.getCompanyWechatId());
+        rankBean.setMyRank(myrank);
+
+        BigDecimal previousIncome = new BigDecimal("0.00");
+        BigDecimal currentIncome = new BigDecimal("0.00");
+        List<RankItemBean> previous = orderShareRankMapper.queryRankList(user.getUserId(), startTime, endTime, currentCompanyWechat.getCompanyWechatId());
+        List<RankItemBean> current = orderShareRankMapper.queryRankList(user.getUserId(), endTime, endTimeDay, currentCompanyWechat.getCompanyWechatId());
+        if (previous != null && previous.size() > 0) {
+            previousIncome = previous.get(0).getTotal();
+        }
+        if (current != null && current.size() > 0) {
+            currentIncome = current.get(0).getTotal();
+        }
+
+        rankBean.setUpOrDown(currentIncome.compareTo(previousIncome) > 0 ? true : false);
+        rankBean.setIncome(currentIncome);
+        Calendar date = Calendar.getInstance();
+        date.setTime(endTimeDay);
+        //date.add(Calendar.SECOND, -1);
+
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
+        rankBean.setStartPeriod(simpleDateFormat.format(endTime));
+        rankBean.setEndPeriod(simpleDateFormat.format(date.getTime()));
+        return rankBean;
+    }
+
+    /**
+     * 微信授权
+     *
+     * @param code
+     * @param serviceId
+     * @return
+     * @throws RemoteServiceException
+     * @throws InterruptedException
+     */
+    @Transactional
+    public UserWxBean addUser(String code, String serviceId, HttpServletRequest request) throws RemoteServiceException, InterruptedException {
+        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat(request);
+        final WechatOpenBean wechatOpenBean = wechatLogic.authToken(code, currentCompanyWechat.getSubAppId());
+
+        log.info("【微信授权】:{}", JSONUtil.toJsonStr(wechatOpenBean));
+
+        String key = Constant.RedisPrefix.LOCK_AUTH + ":" + wechatOpenBean.getOpenid();
+        Lock obtain = redisLockRegistry.obtain(key);
+        if (!obtain.tryLock(2, TimeUnit.SECONDS)) {
+            log.error("请勿重复授权");
+            return null;
+        }
+        try {
+            //如果用户不存在则新注册
+            User user = userService.lambdaQuery()
+                    .eq(User::getOpenId, wechatOpenBean.getOpenid())
+                    .eq(User::getCompanyWechatId, currentCompanyWechat.getCompanyWechatId())
+                    .one();
+            if (user == null) {
+                user = new User();
+                user.setLastLoginTime(new Date());
+                user.setNickName("微信用户_" + IdUtil.objectId().substring(16, 24));
+                user.setOpenId(wechatOpenBean.getOpenid());
+                user.setSessionKey(wechatOpenBean.getSessionKey());
+                user.setServiceId(serviceId);
+                user.setServiceTime(new Date());
+                user.setLastLoginTime(new Date());
+                user.setCreateTime(new Date());
+                user.setCompanyWechatId(currentCompanyWechat.getCompanyWechatId());
+                user.setCompanyName(currentCompanyWechat.getCompanyName());
+                userService.save(user);
+                log.info("【注册成为会员】:{}", user);
+                return this.supplyUser(user);
+            }
+
+            //如果用户存在,则判断是否为业务员,并更新相关信息
+            if (!user.getStatus()) {
+                throw new RemoteServiceException("用户已被冻结");
+            }
+            //判断该手机号是否为业务员
+            user = userToService(user, currentCompanyWechat);
+
+            user.setUnionId(wechatOpenBean.getUnionid());
+            user.setSessionKey(wechatOpenBean.getSessionKey());
+            user.setLastLoginTime(new Date());
+            if (StringUtils.isEmpty(user.getServiceId()) && StringUtils.isNotEmpty(serviceId)) {
+                user.setServiceId(serviceId);
+                user.setServiceTime(new Date());
+            }
+            user.setOpenId(wechatOpenBean.getOpenid());
+            user.updateById();
+            return this.supplyUser(user);
+        } finally {
+            obtain.unlock();
+        }
+
+    }
+
+    /**
+     * 返回小程序用户登录需要的信息
+     *
+     * @param user
+     * @return
+     */
+    private UserWxBean supplyUser(User user) {
+        UserWxBean userWxBean = new UserWxBean();
+        String token = JwtUtils.generateToken(user.getUserId(), user.getOpenId(), user.getNickName(), null, Constant.MINIAPP_API);
+        BeanUtils.copyProperties(user, userWxBean);
+        userWxBean.setToken(token);
+        userWxBean.setShoppingCartNums(shoppingCartLogic.total(userWxBean.getUserId()));
+        //存放到redis
+        redisUtil.set(Constant.RedisPrefix.TOKEN_MP_WX + userWxBean.getToken(), user, 2 * 60 * 60 * 1000);
+        AdminWebsit adminWebsit = adminWebsitService.lambdaQuery()
+                .eq(AdminWebsit::getCompanyWechatId, user.getCompanyWechatId())
+                .eq(AdminWebsit::getWebsitId, user.getWebsitId())
+                .one();
+        if (adminWebsit != null) {
+            userWxBean.setWebsitNumber(adminWebsit.getWebsitNumber());
+            userWxBean.setWebsitName(adminWebsit.getName());
+        }
+        if (StringUtils.isNotBlank(user.getServiceId())) {
+            final User serviceUser = userService.getById(user.getServiceId());
+            ServiceWorkerBean bean = new ServiceWorkerBean();
+            if (StringUtils.isNotBlank(serviceUser.getWebsitId())) {
+                bean.setWebsitId(Long.parseLong(serviceUser.getWebsitId()));
+            }
+            bean.setWebsit(serviceUser.getWebsitName());
+            userWxBean.setServiceWorkerBean(bean);
+        }
+        return userWxBean;
+    }
+
+    public User userToService(User user, CurrentCompanyWechat currentCompanyWechat) {
+        //判断该手机号是否为业务员
+        if (StringUtils.isNotEmpty(user.getMobile())) {
+            UserServiceWait waitUser = userServiceWaitService.lambdaQuery()
+                    .eq(UserServiceWait::getMobile, user.getMobile())
+                    .eq(UserServiceWait::getCompanyWechatId, user.getCompanyWechatId())
+                    .one();
+
+            if (Objects.nonNull(waitUser)) {
+                Long count = userService.lambdaQuery()
+                        .eq(User::getMobile, user.getMobile())
+                        .eq(User::getType, UserTypeEnum.SERVICE.toString())
+                        .eq(User::getCompanyWechatId, user.getCompanyWechatId())
+                        .count();
+                if (count < 1) {
+                    user.setType(UserTypeEnum.SERVICE.toString());
+                    user.setWorkName(waitUser.getName());
+                    user.setWorkUserId(waitUser.getWorkerId());
+                    user.setPosition(waitUser.getPosition());
+                    user.setWorkPhone(waitUser.getMobile());
+                    user.setWebsitId(waitUser.getWebsitId());
+                    user.setWebsitName(waitUser.getWebsitName());
+                    user.setCompanyWechatId(currentCompanyWechat.getCompanyWechatId());
+                    user.setCompanyName(currentCompanyWechat.getCompanyName());
+
+                    waitUser.setUserId(user.getUserId())
+                            .setIsBind(true)
+                            .setUpdateTime(new Date())
+                            .updateById();
+                }
+            }
+        }
+        return user;
+    }
+
+    /**
+     * 新增用户访问记录
+     */
+    public void addVisit(HttpServletRequest request, String userId) {
+        try {
+            CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat(request);
+            UserVisit userVisit = new UserVisit();
+            userVisit.setUserId(userId);
+            userVisit.setVisitTime(new Date());
+            userVisit.setCompanyWechatId(currentCompanyWechat.getCurrentCompanyWechatId());
+            userVisit.setCompanyName(currentCompanyWechat.getCurrentCompanyName());
+            userVisit.insert();
+        } catch (Exception e) {
+            log.error("新增用户访问记录失败", e);
+        }
+    }
+
+    //手机号码授权
+    @Transactional
+    public UserWxBean getWxMobile(String code, String userId, HttpServletRequest request) throws Exception {
+        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat(request);
+        UserWxBean userWxBean = new UserWxBean();
+        User user = this.userService.getById(userId);
+        if (null == user) {
+            throw new RemoteServiceException("用户信息为空" + userId);
+        }
+        WxMaService maService = wechatLogic.getMaService(currentCompanyWechat.getCompanyWechatId());
+        WxMaPhoneNumberInfo phoneNoInfo = maService.getUserService().getPhoneNoInfo(code);
+        String mobile = phoneNoInfo.getPhoneNumber();
+        if (StringUtils.isEmpty(mobile)) {
+            throw new RemoteServiceException("手机号授权失败");
+        }
+
+        List<UserServiceWait> waitList = userServiceWaitService.lambdaQuery()
+                .eq(UserServiceWait::getCompanyWechatId, currentCompanyWechat.getCompanyWechatId())
+                .eq(UserServiceWait::getMobile, mobile)
+                .list();
+
+        //根据手机号查询是否存在企业微信用户
+        User workUser = userService.lambdaQuery()
+                .eq(User::getMobile, mobile)
+                .eq(User::getStatus, true)
+                .eq(User::getCompanyWechatId, currentCompanyWechat.getCompanyWechatId())
+                .one();
+        if (workUser == null) {
+            //企业微信用户为空,则直接授权手机号。并根据手机号判断是否存在于微信成员表如果存在则为业务员
+            user.setMobile(mobile);
+            if (waitList.size() > 0) {
+                UserServiceWait wait = waitList.get(0);
+                String workUserId = wait.getWorkerId();
+                Long count = userService.lambdaQuery()
+                        .eq(User::getWorkUserId, workUserId)
+                        .eq(User::getType, UserTypeEnum.SERVICE.toString())
+                        .eq(User::getCompanyWechatId, currentCompanyWechat.getCompanyWechatId())
+                        .count();
+                if (count < 1) {
+                    user.setType(UserTypeEnum.SERVICE.toString());
+                    user.setWorkName(wait.getName());
+                    user.setWorkUserId(workUserId);
+                    user.setWorkPhone(wait.getMobile());
+//                    user.setWorkQrcode(list.get(0).getQrCode());
+                    user.setPosition(wait.getPosition());
+                    user.setWebsitId(wait.getWebsitId());
+                    user.setWebsitName(wait.getWebsitName());
+                    user.setWorkCreateTime(new Date());
+
+                    wait.setUserId(user.getUserId())
+                            .setIsBind(true)
+                            .setUpdateTime(new Date())
+                            .updateById();
+                }
+            }
+            user.updateById();
+
+            String token = JwtUtils.generateToken(user.getUserId(), user.getOpenId(), user.getNickName(), null, Constant.MINIAPP_API);
+            BeanUtils.copyProperties(user, userWxBean);
+            userWxBean.setToken(token);
+
+        } else {
+            //企业微信不为空,则将数据绑定到企业微信,并删除授权openid的用户数据
+            workUser.setOpenId(user.getOpenId());
+            workUser.updateById();
+            user.deleteById();
+
+            String token = JwtUtils.generateToken(user.getUserId(), user.getOpenId(), user.getNickName(), null, Constant.MINIAPP_API);
+            BeanUtils.copyProperties(workUser, userWxBean);
+            userWxBean.setToken(token);
+        }
+        return userWxBean;
+    }
+
+    /**
+     * 个人信息
+     */
+    public UserWxBean userDetail(String userId, HttpServletRequest request) throws RemoteServiceException {
+        User user = userService.getById(userId);
+        if (user == null) {
+            throw new RemoteServiceException(ResponseHelper.ResponseCode_AUTH_ERROR, "请求不合法");
+        }
+        UserWxBean userWxBean = new UserWxBean();
+        BeanUtils.copyProperties(user, userWxBean);
+        userWxBean.setShoppingCartNums(shoppingCartLogic.total(userWxBean.getUserId()));
+        if (StringUtils.isNotBlank(user.getServiceId())) {
+            final User serviceUser = userService.getById(user.getServiceId());
+            ServiceWorkerBean bean = new ServiceWorkerBean();
+            if (StringUtils.isNotBlank(serviceUser.getWebsitId())) {
+                bean.setWebsitId(Long.parseLong(serviceUser.getWebsitId()));
+            }
+            bean.setWebsit(serviceUser.getWebsitName());
+            userWxBean.setServiceWorkerBean(bean);
+        }
+        return userWxBean;
+    }
+
+    //保存用户信息
+    public User saveUserInfo(String userId, String nickName, String sex, String avatarUrl, String country, String province, String city) {
+        User user = new User();
+        user.setUserId(userId);
+        user.setNickName(nickName);
+        user.setSex(sex);
+        user.setAvatar(avatarUrl);
+        user.setCountry(country);
+        user.setProvince(province);
+        user.setCity(city);
+        user.updateById();
+        return user;
+    }
+
+    /**
+     * 我的收益
+     */
+    public MyProfitBean myProfit(String userId) {
+        User user = userService.getById(userId);
+        if (user == null) {
+            return null;
+        }
+        MyProfitBean myProfitBean = customMemberMapper.queryProfitSum(user.getWorkUserId(), user.getUserId());
+        if (myProfitBean != null) {
+            myProfitBean.setTotalAmount(myProfitBean.getPaidAmount().add(myProfitBean.getWaitingAmount()));
+        } else {
+            myProfitBean = new MyProfitBean();
+            BigDecimal zero = new BigDecimal("0.00");
+            myProfitBean.setPaidAmount(zero);
+            myProfitBean.setWaitingAmount(zero);
+            myProfitBean.setTotalAmount(zero);
+        }
+        return myProfitBean;
+    }
+
+
+    public IPage<OrderShare> myProfitList(String userId, String status, Integer pageNum, Integer pageSize) {
+        User user = userService.getById(userId);
+        if (user == null) {
+            return null;
+        }
+        return orderShareService.lambdaQuery()
+                .eq(OrderShare::getOpenId, user.getOpenId())
+                .ne(OrderShare::getWorkUserId, "")
+                .eq(StringUtils.isNotEmpty(status), OrderShare::getStatus, status)
+                .eq(OrderShare::getCompanyWechatId, user.getCompanyWechatId())
+                .orderByDesc(OrderShare::getCreateTime)
+                .page(new Page<>(pageNum, pageSize));
+    }
+
+    /**
+     * 总收益
+     */
+    public BigDecimal totalProfit(String userId) {
+        User user = userService.getById(userId);
+        if (user == null || StringUtils.isEmpty(user.getWorkUserId())) {
+            return null;
+        }
+        List<OrderShare> list = orderShareService.lambdaQuery()
+                .eq(OrderShare::getOpenId, user.getOpenId())
+                .eq(OrderShare::getCompanyWechatId, user.getCompanyWechatId())
+                .and(v -> v.like(OrderShare::getWorkUserId, user.getWorkUserId()).or().like(OrderShare::getWorkUserId, user.getUserId()))
+                .eq(OrderShare::getStatus, OrderShareStatusEnum.OVER.toString())
+                .list();
+        if (list.size() == 0) {
+            return new BigDecimal(0);
+        }
+        return list.stream().map(OrderShare::getAmount).reduce(BigDecimal::add).orElse(new BigDecimal(0));
+    }
+
+    /**
+     * 我的客户
+     */
+    public IPage<User> customerList(String userId, Integer pageNum, Integer pageSize) {
+        IPage<User> page = userService.lambdaQuery().eq(User::getServiceId, userId).page(new Page<>(pageNum, pageSize));
+        return page;
+    }
+
+    /**
+     * 我的经理
+     */
+    public User parentUser(String userId) {
+        User user = userService.getById(userId);
+        if (StringUtils.isNotEmpty(user.getServiceId())) {
+            User parentUser = userService.getById(user.getServiceId());
+            return parentUser;
+        }
+        return null;
+    }
+
+    public String renewal(String token) {
+        final Object o = redisUtil.get(Constant.RedisPrefix.TOKEN_MP_WX + token);
+        if (Objects.isNull(o)) {
+            throw new RemoteServiceException(ResponseHelper.ResponseCode_AUTH_ERROR, "登录过期");
+        }
+
+        User user = (User) o;
+        final User user1 = userService.getById(user.getUserId());
+
+        String newToken = JwtUtils.refreshToken(token, Constant.MINIAPP_API);
+
+        //存放到redis
+        redisUtil.set(Constant.RedisPrefix.TOKEN_MP_WX + newToken, user1, 2 * 60 * 60 * 1000);
+        return newToken;
+    }
 }

+ 98 - 0
src/main/java/com/gree/mall/contest/logic/user/WorkerLogic.java

@@ -0,0 +1,98 @@
+package com.gree.mall.contest.logic.user;
+
+import cn.hutool.core.date.DateUtil;
+import com.gree.mall.contest.bean.user.CurrentCompanyWechat;
+import com.gree.mall.contest.enums.UserTypeEnum;
+import com.gree.mall.contest.exception.RemoteServiceException;
+import com.gree.mall.contest.logic.SMSLogic;
+import com.gree.mall.contest.logic.common.CommonLogic;
+import com.gree.mall.contest.plus.entity.AdminWebsit;
+import com.gree.mall.contest.plus.entity.User;
+import com.gree.mall.contest.plus.entity.UserServiceApply;
+import com.gree.mall.contest.plus.service.AdminWebsitService;
+import com.gree.mall.contest.plus.service.UserService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class WorkerLogic {
+
+    private final SMSLogic smsLogic;
+    private final CommonLogic commonLogic;
+    private final UserService userService;
+    private final AdminWebsitService adminWebsitService;
+
+    public void sendSms(String phone, String key, String vrifyCode, HttpServletRequest request) throws Exception {
+        if (!this.isPhoneLegal(phone)) {
+            throw new RemoteServiceException("手机号不正确");
+        }
+
+        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat(request);
+
+        final Long count = userService.lambdaQuery()
+                .eq(User::getCompanyWechatId, currentCompanyWechat.getCompanyWechatId())
+                .eq(User::getType, UserTypeEnum.SERVICE.toString())
+                .eq(User::getMobile, phone)
+                .count();
+
+        if (count > 0) {
+            throw new RemoteServiceException("手机号已被绑定");
+        }
+        smsLogic.sendSms(phone, key, vrifyCode, "APPLY_WORKER");
+    }
+
+    private boolean isPhoneLegal(String phone) {
+        Pattern CHINA_PATTERN = Pattern.compile("^((13[0-9])|(14[0,1,4-9])|(15[0-3,5-9])|(16[2,5,6,7])|(17[0-8])|(18[0-9])|(19[0-3,5-9]))\\d{8}$");
+        Matcher m = CHINA_PATTERN.matcher(phone);
+        return m.matches();
+    }
+
+
+    public void bind(HttpServletRequest request, String phone, String code) throws RemoteServiceException {
+        smsLogic.checkSmsCode(phone, code, "APPLY_WORKER");
+        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat(request);
+
+        final Long count = userService.lambdaQuery()
+                .eq(User::getCompanyWechatId, currentCompanyWechat.getCompanyWechatId())
+                .eq(User::getType, UserTypeEnum.SERVICE.toString())
+                .eq(User::getMobile, phone)
+                .count();
+
+        if (count > 0) {
+            throw new RemoteServiceException("手机号已被绑定");
+        }
+
+        final User user = userService.getById(currentCompanyWechat.getUserId());
+
+        if (!user.getType().equals(UserTypeEnum.GENERAL.toString())) {
+            throw new RemoteServiceException("当前用户已成为”业务员“");
+        }
+
+        UserServiceApply apply = new UserServiceApply();
+        apply.setUserId(user.getUserId())
+                .setMobile(phone)
+                .setCreateTime(DateUtil.date())
+                .setCompanyWechatId(user.getCompanyWechatId())
+                .setCompanyName(user.getCompanyName())
+                .insert();
+
+    }
+
+    public List<AdminWebsit> websitList(HttpServletRequest request) {
+        CurrentCompanyWechat currentCompanyWechat = commonLogic.getCurrentCompanyWechat(request);
+        final List<AdminWebsit> websitList = adminWebsitService.lambdaQuery()
+                .eq(AdminWebsit::getCompanyWechatId, currentCompanyWechat.getCompanyWechatId())
+                .orderByAsc(AdminWebsit::getCreateTime)
+                .list();
+
+        return websitList;
+    }
+}

+ 2 - 2
src/main/java/com/gree/mall/contest/utils/JwtUtils.java

@@ -39,8 +39,8 @@ public class JwtUtils {
      * @param userId    用户ID
      * @param username  用户名
      * @param realName  真实姓名
-     * @param userType 用户类型
-     * @param issuer 用户角色
+     * @param userType  用户类型
+     * @param issuer
      * @return JWT令牌
      */
     public static String generateToken(String userId, String username, String realName, String userType, String issuer) {

+ 62 - 0
src/main/resources/mapper/AppMapper.xml

@@ -0,0 +1,62 @@
+<?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="com.gree.mall.contest.commonmapper.AppMapper">
+
+    <select id="queryShoppingCartList" resultType="com.gree.mall.contest.bean.order.ShoppingCartList">
+        select a.*,
+               b.price,
+               c.goods_name,
+               b.spec_value,
+               b.org_price,
+               b.price * num as 'totalPrice', c.img_url 'goodsImg'
+
+        from shopping_cart a
+                 join goods_spec b on a.goods_spec_id = b.goods_spec_id
+                 join goods c on c.goods_id = a.goods_id
+        where a.user_id = #{userId}
+    </select>
+
+
+    <select id="orderStatusCount" resultType="com.gree.mall.contest.bean.order.OrderStatusBean">
+
+        select sum(if(order_status = 'NOPAY', 1, 0))  noPay,
+               sum(if(order_status = 'YFH', 1, 0))    yfh,
+               sum(if(order_status = 'DFH', 1, 0))    dfh,
+               sum(if(order_status = 'REFUND', 1, 0)) sh,
+               sum(if(order_status = 'OVER', 1, 0))   ywc
+        from order_info
+        where user_id = #{userId}
+    </select>
+
+
+    <select id="queryNewGoods" resultType="com.gree.mall.contest.bean.goods.GoodsNewBean">
+        select
+            a.*,
+            b.obj_id
+        from goods a
+        join goods_news_category_goods b on a.goods_id = b.goods_id
+        where b.company_wechat_id = #{companyWechatId} and a.del=0 and a.status=1 and a.promotion_group=false
+        <if test="objId != null and objId != ''">
+            and b.obj_id = #{objId}
+        </if>
+        <if test="type != null and type != ''">
+            and b.type = #{type}
+        </if>
+        <if test="sort != null and sort==0">
+            order by a.sort_num asc
+        </if>
+        <if test="sort != null and sort==1">
+            order by a.sold_num desc
+        </if>
+        <if test="sort != null and sort==2">
+            order by goods_price asc
+        </if>
+        <if test="sort != null and sort==3">
+            order by goods_price desc
+        </if>
+        <if test="sort != null and sort==4">
+            order by a.create_time desc
+        </if>
+
+    </select>
+</mapper>

+ 9 - 0
src/main/resources/mapper/CustomMemberMapper.xml

@@ -53,6 +53,15 @@
             AND a.status = #{status}
         </if>
     </select>
+    <select id="queryProfitSum" resultType="com.gree.mall.contest.bean.user.MyProfitBean">
+        SELECT
+            sum( IF ( STATUS = 'ING', amount, 0.00 ) ) AS waitingAmount,
+            sum( IF ( STATUS = 'OVER', amount, 0.00 ) ) AS paidAmount
+        from order_share
+        where (work_user_id = #{workUserId} or work_user_id = #{userId})
+          and status != 'CANCEL'
+          and work_user_id !=''
+    </select>
 
 
 </mapper>

+ 39 - 0
src/main/resources/mapper/OrderShareRankMapper.xml

@@ -0,0 +1,39 @@
+<?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="com.gree.mall.contest.commonmapper.OrderShareRankMapper">
+    <select id="queryRankList" resultType="com.gree.mall.contest.bean.user.RankItemBean">
+        select
+                ur.user_id as workUserId,
+                ifnull(ur.work_name,ur.nick_name) as work_user_name,
+                ur.avatar,
+                ifnull(aw.name,'') as websitName,
+                sum(od.pay_amount) as 'total',
+                row_number() over(order by sum(od.pay_amount) desc) as 'ranking'
+            from order_info os join order_detail od on os.order_id = od.order_id
+            join user ur on ur.user_id = od.share_user_id
+            join admin_company_wechat d on d.company_wechat_id = os.company_wechat_id
+            left join admin_websit aw on d.company_wechat_id = aw.company_wechat_id AND aw.websit_id = ur.websit_id
+        where od.share_user_id !='' and os.order_status in('DFH','YFH','OVER')
+          and os.create_time between #{startTime} and #{endTime} and os.company_wechat_id=#{companyWechatId}
+          <if test="userId != null and userId !=''">
+              and od.share_user_id = #{userId}
+          </if>
+        group by od.share_user_id limit 50
+    </select>
+
+
+    <select id="queryWorkerInfo" resultType="com.gree.mall.contest.bean.user.RankItemBean">
+         select
+					 ur.work_user_id,
+					 ur.work_name as work_user_name,
+					 ur.avatar,
+					 aw.name      as websitName
+        from user ur
+		  join admin_company_wechat d on ur.company_wechat_id = d.company_wechat_id
+          join admin_websit aw on d.company_wechat_id = aw.company_wechat_id AND ur.websit_id = aw.websit_id
+        where ur.user_id = #{userId}
+    </select>
+
+
+
+</mapper>