Kaynağa Gözat

add appleId自动注册;意愿客户;用户数据

add Apple ID注册数据

fix 注册账号数据统计

fix 注册账号微信支付签名

fix 微信签名

fix 用户数据

fix 用户数据统计

fix 状态修改

fix 用户统计数据

fix 空指针

fix pc端用户数据统计

fix

add 意向客户功能

fix 状态

fix 备注修改

fix 随机生成appId账号订单状态

fix 未支付不展示密码

fix

fix 注册账号用户昵称

fix

fix 展示

fix 默认不展示已购买实物意愿

fix

fix 去掉无用字段

fix 统计实物数据为0不展示

fix 去掉无用接口

fix 重复插入

fix

fix 最新时间排序在前

fix

fix id

fix 用户已购买时间

fix 购买时间字段

fix 最高规格

fix spotify模板消息

fix

fix 时间

fix 不同实物平台

fix 更新支付方式
zoujiajian 3 yıl önce
ebeveyn
işleme
364c945f7a
43 değiştirilmiş dosya ile 1402 ekleme ve 63 silme
  1. 2 0
      netflix-common/src/main/java/com/cyksj/common/constant/TemplateEnum.java
  2. 34 0
      netflix-dao/src/main/java/com/cyksj/mapper/AppleAutoRegisterDataMapper.java
  3. 7 0
      netflix-dao/src/main/java/com/cyksj/mapper/OrderDonMapper.java
  4. 20 0
      netflix-dao/src/main/java/com/cyksj/mapper/RealGoodsInterestUserMapper.java
  5. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/RegisterAccountDataMapper.java
  6. 18 0
      netflix-dao/src/main/java/com/cyksj/mapper/RegisterOrderDonMapper.java
  7. 3 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/statistics/RealGoodsDataMapper.java
  8. 34 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/statistics/StatisticsUserDataMapper.java
  9. 18 10
      netflix-dao/src/main/java/com/cyksj/model/dto/UnifiedOrder.java
  10. 43 0
      netflix-dao/src/main/java/com/cyksj/model/entity/AppleAutoRegisterData.java
  11. 58 0
      netflix-dao/src/main/java/com/cyksj/model/entity/RealGoodsInterestUser.java
  12. 32 0
      netflix-dao/src/main/java/com/cyksj/model/entity/RegisterAccountData.java
  13. 72 1
      netflix-dao/src/main/java/com/cyksj/model/entity/RegisterOrderDon.java
  14. 48 0
      netflix-dao/src/main/java/com/cyksj/model/entity/StatisticsUserData.java
  15. 19 0
      netflix-dao/src/main/java/com/cyksj/model/excel/ExcelAppleIdTemplateData.java
  16. 97 0
      netflix-dao/src/main/java/com/cyksj/model/excel/ExcelRealGoodsUserInterestData.java
  17. 87 0
      netflix-dao/src/main/java/com/cyksj/model/excel/listener/ExcelAppleDataListener.java
  18. 5 0
      netflix-dao/src/main/java/com/cyksj/model/manage/request/RegisterReq.java
  19. 23 0
      netflix-dao/src/main/java/com/cyksj/model/request/UserRealGoodsInterestReq.java
  20. 22 0
      netflix-dao/src/main/java/com/cyksj/model/views/AppleIdCountryOrAreaDataView.java
  21. 21 0
      netflix-dao/src/main/java/com/cyksj/model/views/AppleIdHeadDataView.java
  22. 41 0
      netflix-dao/src/main/java/com/cyksj/model/views/AppleIdRegisterView.java
  23. 6 0
      netflix-dao/src/main/java/com/cyksj/model/views/BackgroundDataView.java
  24. 66 0
      netflix-dao/src/main/java/com/cyksj/model/views/RealGoodsInterestUserView.java
  25. 50 0
      netflix-dao/src/main/java/com/cyksj/model/views/StatisticsUserDataView.java
  26. 40 0
      netflix-dao/src/main/resources/mapper/OrderDonMapper.xml
  27. 27 8
      netflix-dao/src/main/resources/mapper/RealGoodsDataMapper.xml
  28. 4 0
      netflix-service/src/main/java/com/cyksj/common/EnvCommonService.java
  29. 10 0
      netflix-service/src/main/java/com/cyksj/service/mange/statistics/impl/StatisticsDataServiceImpl.java
  30. 7 4
      netflix-service/src/main/java/com/cyksj/service/order/OrderDonService.java
  31. 19 0
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java
  32. 2 0
      netflix-service/src/main/java/com/cyksj/service/register/RegisterOrderDonService.java
  33. 71 7
      netflix-service/src/main/java/com/cyksj/service/register/impl/RegisterOrderDonServiceImpl.java
  34. 33 5
      netflix-service/src/main/java/com/cyksj/service/register/impl/SpotifyServiceImpl.java
  35. 4 2
      netflix-service/src/main/java/com/cyksj/service/wechat/impl/WeChatServiceImpl.java
  36. 59 2
      netflix-service/src/main/java/com/cyksj/task/Scheduler.java
  37. 50 2
      netflix-service/src/main/java/com/cyksj/task/StatisticsDataScheduler.java
  38. 72 4
      netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsOrderController.java
  39. 2 2
      netflix-web/src/main/java/com/cyksj/web/controller/manage/group/CmsGroupController.java
  40. 74 11
      netflix-web/src/main/java/com/cyksj/web/controller/manage/register/CmsRegisterController.java
  41. 38 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/statistics/StatisticsDataController.java
  42. 31 5
      netflix-web/src/main/java/com/cyksj/web/controller/register/RegisterController.java
  43. 20 0
      netflix-web/src/main/java/com/cyksj/web/util/EasyExcelUtils.java

+ 2 - 0
netflix-common/src/main/java/com/cyksj/common/constant/TemplateEnum.java

@@ -18,6 +18,8 @@ public enum TemplateEnum {
 	NEW_ORDER_PRD_TEMPLATE("新订单通知正式环境模板", "T88yYYsfhBIKALWGmGTY2ZJGWHx91pcAtinoRGZ0krw", " "),
 	EMPTY_ENV_TEMPLATE("空车位通知测试环境模板", "ArZr9oCJYelqCfn0pU7RQqRbRIWuyRNaU7N_Oo6p2vM", " "),
 	EMPTY_PRD_TEMPLATE("正式环境空车位通知模板", "T88yYYsfhBIKALWGmGTY2ZJGWHx91pcAtinoRGZ0krw", " "),
+	SPOTIFY_ENV_TEMPLATE("Spotify注册测试环境模板", "gsGFRefPlGKfvNoqB5Vd43ZOsmCsZNsH4UDWefWG0sg", " "),
+	SPOTIFY_PRD_TEMPLATE("Spotify注册正式环境模板", "VPQ3cYd_OMYpyHzyaa1X5oOeWh9ZcgwZlrBw_cGqEIA", " "),
 
 	;
 	private String desc;

+ 34 - 0
netflix-dao/src/main/java/com/cyksj/mapper/AppleAutoRegisterDataMapper.java

@@ -0,0 +1,34 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.AppleAutoRegisterData;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.Date;
+import java.util.List;
+
+/*
+ *项目名: netflix
+ *文件名: AppleAutoRegisterDataMapper
+ *创建者: JavaZou
+ *创建时间:2022/11/22 16:15
+ */
+public interface AppleAutoRegisterDataMapper extends BaseMapper<AppleAutoRegisterData> {
+	@Select("select count(*)" +
+			" from apple_auto_register_data" +
+			" where status is false and country_or_area = #{countryOrArea}")
+	Integer selectAreaDataView(AppleAutoRegisterData.CountryOrArea countryOrArea);
+
+	@Select("select ad.id from apple_auto_register_data ad left join register_order_don rd on rd.id = ad.order_id" +
+			" where ad.user_id = #{userId} and ad.status = true" +
+			" and ad.country_or_area = #{countryOrArea}" +
+			" and rd.status = 'noPayment'")
+	Integer checkNoPayOrder(@Param("userId") long userId, @Param("countryOrArea") AppleAutoRegisterData.CountryOrArea countryOrArea);
+
+	@Select("select rd.id from apple_auto_register_data ad inner join register_order_don rd on rd.id = ad.order_id" +
+			" where ad.status = true" +
+			" and ad.user_id != 0" +
+			" and rd.status = 'noPayment' and rd.created_time <= #{newDate}")
+	List<Long> getAllNoPayOrders(Date newDate);
+}

+ 7 - 0
netflix-dao/src/main/java/com/cyksj/mapper/OrderDonMapper.java

@@ -2,6 +2,7 @@ package com.cyksj.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.cyksj.model.entity.OrderDon;
+import com.cyksj.model.entity.RealGoodsInterestUser;
 import com.cyksj.model.excel.ExcelOrderDonInfo;
 import org.apache.ibatis.annotations.Param;
 
@@ -18,4 +19,10 @@ public interface OrderDonMapper extends BaseMapper<OrderDon> {
     List<ExcelOrderDonInfo> exportOrderInfo(@Param("promotionId") Long promotionId, @Param("start") String start, @Param("end") String end);
 
     List<OrderDon> getAppleOneOrderDons(@Param("appleOne") String appleOne, @Param("skuIds") List<Long> skuIds, @Param("goodsIds") List<Long> goodsIds, @Param("noOrderStatus") List<String> noOrderStatus, @Param("yesZeroDate") Date yesZeroDate, @Param("thisZeroDate") Date thisZeroDate);
+
+	List<RealGoodsInterestUser> selectNoPaymentRealGoods();
+
+	Integer updateHasPaymentInterestRealGoods();
+
+	void updateHasPaymentInterestRealGoodsPayTime();
 }

+ 20 - 0
netflix-dao/src/main/java/com/cyksj/mapper/RealGoodsInterestUserMapper.java

@@ -0,0 +1,20 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.RealGoodsInterestUser;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Update;
+
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: RealGoodsInterestUserMapper
+ *创建者: JavaZou
+ *创建时间:2022/11/25 14:41
+ */
+public interface RealGoodsInterestUserMapper extends BaseMapper<RealGoodsInterestUser> {
+
+	@Update("update real_goods_interest_user set sku_id = #{skuId},order_id = #{orderId},order_created_time = #{orderCreatedTime} where id = #{id}")
+	void updateData(@Param("id") Long id, @Param("skuId") Long skuId, @Param("orderCreatedTime") Date orderCreatedTime, @Param("orderId") Long orderId);
+}

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/RegisterAccountDataMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.RegisterAccountData;
+
+/*
+ *项目名: netflix
+ *文件名: RegisterAccountDataMapper
+ *创建者: JavaZou
+ *创建时间:2022/11/24 13:32
+ */
+public interface RegisterAccountDataMapper extends BaseMapper<RegisterAccountData> {
+}

+ 18 - 0
netflix-dao/src/main/java/com/cyksj/mapper/RegisterOrderDonMapper.java

@@ -1,11 +1,29 @@
 package com.cyksj.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.RegisterAccountData;
 import com.cyksj.model.entity.RegisterOrderDon;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.Date;
 
 /**
  * @author chan
  * @date 2022/11/7 2:38 PM
  */
 public interface RegisterOrderDonMapper extends BaseMapper<RegisterOrderDon> {
+
+	@Select("select platform,count(distinct user_id) as numOfUser," +
+			"count(user_id) as numOfOrder,sum(money) as money" +
+			" from register_order_don" +
+			" where created_time between #{yesZeroDate} and #{thisZeroDate} and status != 'noPayment' and platform = #{platform}" +
+			" group by platform")
+	RegisterAccountData registerAccountDataEveryDay(@Param("yesZeroDate") Date yesZeroDate, @Param("thisZeroDate") Date thisZeroDate, @Param("platform") String platform);
+
+	@Select("select count(user_id) as 'numOfRefundOrder',"+
+			"sum(money) as 'refundMoney'" +
+			" from register_order_don" +
+			" where created_time between #{yesZeroDate} and #{thisZeroDate} and status = 'refund' and platform = #{platform}")
+	RegisterAccountData selectRefundOrderDetail(@Param("yesZeroDate") Date yesZeroDate, @Param("thisZeroDate") Date thisZeroDate, @Param("platform") String platform);
 }

+ 3 - 0
netflix-dao/src/main/java/com/cyksj/mapper/manage/statistics/RealGoodsDataMapper.java

@@ -2,6 +2,7 @@ package com.cyksj.mapper.manage.statistics;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.cyksj.model.entity.RealGoodsData;
+import com.cyksj.model.entity.RegisterAccountData;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.Date;
@@ -15,4 +16,6 @@ import java.util.List;
  */
 public interface RealGoodsDataMapper extends BaseMapper<RealGoodsData> {
 	List<RealGoodsData> statisticsRealGoodsData(@Param("startDate") Date startDate, @Param("endDate") Date endDate);
+
+	List<RegisterAccountData> statisticsRegisterAccountData(@Param("startDate") Date startDate, @Param("endDate") Date endDate);
 }

+ 34 - 0
netflix-dao/src/main/java/com/cyksj/mapper/manage/statistics/StatisticsUserDataMapper.java

@@ -0,0 +1,34 @@
+package com.cyksj.mapper.manage.statistics;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.StatisticsUserData;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: StatisticsUserDataMapper
+ *创建者: JavaZou
+ *创建时间:2022/11/24 16:21
+ */
+public interface StatisticsUserDataMapper extends BaseMapper<StatisticsUserData> {
+	@Select("select count(distinct unionid) from user where created_time between #{yesZeroDate} and #{thisZeroDate} and unionid != ''")
+	Integer getNumOfNewUser(@Param("yesZeroDate") Date yesZeroDate, @Param("thisZeroDate") Date thisZeroDate);
+
+	@Select("select count(distinct unionid) from user where update_time between #{yesZeroDate} and #{thisZeroDate} and unionid != ''")
+	Integer getNumOfActiveUser(@Param("yesZeroDate") Date yesZeroDate, @Param("thisZeroDate") Date thisZeroDate);
+
+	@Select("select count(distinct unionid) from user where unionid != ''")
+	Integer getWxTotalOfUser();
+
+	@Select("select count(*) from user where login_phone != ''")
+	Integer getPcTotalOfUser();
+
+	@Select("select count(*) from user where created_time between #{yesZeroDate} and #{thisZeroDate} and login_phone != ''")
+	Integer getPcNumOfNewUser(@Param("yesZeroDate") Date yesZeroDate, @Param("thisZeroDate") Date thisZeroDate);
+
+	@Select("select count(*) from user where update_time between #{yesZeroDate} and #{thisZeroDate} and login_phone != ''")
+	Integer getPcNumOfActiveUser(@Param("yesZeroDate") Date yesZeroDate, @Param("thisZeroDate") Date thisZeroDate);
+}

+ 18 - 10
netflix-dao/src/main/java/com/cyksj/model/dto/UnifiedOrder.java

@@ -117,7 +117,8 @@ public class UnifiedOrder {
     private String sceneInfo;
 
     public String println(String shopKey) {
-        return "appid=" + this.appid +
+        StringBuilder sb = new StringBuilder();
+        sb.append("appid=" + this.appid +
                 "&attach=" + this.attach +
                 "&body=" + this.body +
                 "&mch_id=" + this.mchId +
@@ -125,11 +126,14 @@ public class UnifiedOrder {
                 "&notify_url=" + this.notifyUrl +
                 "&openid=" + this.openid +
                 "&out_trade_no=" + this.outTradeNo +
-                "&spbill_create_ip=" + this.spbillCreateIp +
-                "&time_expire=" + this.timeExpire +
-                "&total_fee=" + totalFee +
+                "&spbill_create_ip=" + this.spbillCreateIp);
+        if (this.timeExpire != null) {
+            sb.append("&time_expire=" + this.timeExpire);
+        }
+        sb.append("&total_fee=" + totalFee +
                 "&trade_type=JSAPI" +
-                "&key=" + shopKey;
+                "&key=" + shopKey);
+        return sb.toString();
     }
 
     public String H5Println(String shopKey) {
@@ -148,18 +152,22 @@ public class UnifiedOrder {
     }
 
     public String nativePrintln(String shopKey) {
-        return "appid=" + this.appid +
+        StringBuilder sb = new StringBuilder();
+        sb.append("appid=" + this.appid +
                 "&attach=" + this.attach +
                 "&body=" + this.body +
                 "&mch_id=" + this.mchId +
                 "&nonce_str=" + this.nonceStr +
                 "&notify_url=" + this.notifyUrl +
                 "&out_trade_no=" + this.outTradeNo +
-                "&spbill_create_ip=" + this.spbillCreateIp +
-                "&time_expire=" + this.timeExpire +
-                "&total_fee=" + totalFee +
+                "&spbill_create_ip=" + this.spbillCreateIp);
+        if (this.timeExpire != null) {
+            sb.append("&time_expire=" + this.timeExpire);
+        }
+        sb.append("&total_fee=" + totalFee +
                 "&trade_type=NATIVE" +
-                "&key=" + shopKey;
+                "&key=" + shopKey);
+        return sb.toString();
     }
 
     public String getPrintln(String tradeType, String shopKey) {

+ 43 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/AppleAutoRegisterData.java

@@ -0,0 +1,43 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: AppleAutoRegisterData
+ *创建者: JavaZou
+ *创建时间:2022/11/22 16:16
+ */
+@Getter
+@Setter
+public class AppleAutoRegisterData extends BaseEntity{
+	private String applePwdId;
+
+	private CountryOrArea countryOrArea;
+
+	/**
+	 * 使用状态
+	 */
+	private Boolean status;
+
+	private Long userId;
+
+	private Long orderId;
+
+	private String remark;
+
+	@Getter
+	public enum CountryOrArea {
+		CN_TaiWan("中国台湾"),
+		CN_HongKong("中国香港"),
+		US("美国"),
+		JAPAN("日本"),
+		;
+		String desc;
+
+		CountryOrArea(String desc) {
+			this.desc = desc;
+		}
+	}
+}

+ 58 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/RealGoodsInterestUser.java

@@ -0,0 +1,58 @@
+package com.cyksj.model.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: RealGoodsInterestUser
+ *创建者: JavaZou
+ *创建时间:2022/11/25 13:57
+ */
+@Getter
+@Setter
+public class RealGoodsInterestUser extends BaseEntity{
+	private Long userId;
+
+	private Long orderId;
+
+	private String remark;
+
+	private Long goodsId;
+
+	private Long skuId;
+
+	@TableField(exist = false)
+	private BigDecimal money;
+
+	@TableField(exist = false)
+	private String groupBy;
+
+	/**
+	 * 意向
+	 */
+	private Status interestStatus;
+
+	/**
+	 * 订单创建时间
+	 */
+	private Date orderCreatedTime;
+
+	@Getter
+	public enum Status{
+		notContacted("未联系"),
+		interest("有意向"),
+		notInterest("无意向"),
+		hasPayment("已购买"),
+		;
+		String desc;
+
+		Status(String desc) {
+			this.desc = desc;
+		}
+	}
+}

+ 32 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/RegisterAccountData.java

@@ -0,0 +1,32 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: RegisterAccountData
+ *创建者: JavaZou
+ *创建时间:2022/11/24 12:17
+ */
+@Getter
+@Setter
+public class RegisterAccountData extends BaseEntity{
+	private String platform;
+
+	private Integer numOfUser;
+
+
+	private Integer numOfOrder;
+
+	private BigDecimal money;
+
+	private Integer numOfRefundOrder;
+
+	private BigDecimal refundMoney;
+
+	private Date statisticsDate;
+}

+ 72 - 1
netflix-dao/src/main/java/com/cyksj/model/entity/RegisterOrderDon.java

@@ -1,5 +1,10 @@
 package com.cyksj.model.entity;
 
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.ejlchina.searcher.bean.DbField;
 import com.ejlchina.searcher.bean.SearchBean;
 import lombok.Getter;
 import lombok.Setter;
@@ -13,32 +18,51 @@ import java.util.Date;
  */
 @Getter
 @Setter
-public class RegisterOrderDon extends BaseEntity{
+@SearchBean(tables = "register_order_don rd left join apple_auto_register_data ad on ad.order_id = rd.id" +
+        " left join user u on rd.user_id = u.id")
+public class RegisterOrderDon{
 
+    @TableId(value = "id",type = IdType.AUTO)
+    @DbField("rd.id")
+    private Long id;
+
+    @DbField("rd.platform")
     private String platform;
 
+    @DbField("rd.nickname")
     private String nickname;
 
+    @DbField("rd.username")
     private String username;
 
+    @DbField("rd.password")
     private String password;
 
+    @DbField("rd.email")
     private String email;
 
+    @DbField("rd.birth_year")
     private String birthYear;
 
+    @DbField("rd.birth_month")
     private String birthMonth;
 
+    @DbField("rd.birth_day")
     private String birthDay;
 
+    @DbField("rd.gender")
     private String gender;
 
+    @DbField("rd.phone")
     private String phone;
 
+    @DbField("rd.country")
     private String country;
 
+    @DbField("rd.order_no")
     private String orderNo;
 
+    @DbField("money")
     private BigDecimal money;
 
     /**
@@ -48,25 +72,72 @@ public class RegisterOrderDon extends BaseEntity{
 
 
     /** 用户id */
+    @DbField("rd.user_id")
     private Long userId ;
 
+    /**
+     * 用户昵称
+     */
+    @DbField("u.nickname")
+    @TableField(exist = false)
+    private String userNickname;
+
     /**
      * openId
      */
+    @DbField("rd.open_id")
     private String openId;
 
     /** 支付状态 */
+    @DbField("rd.status")
     private Status status ;
 
     /**
      * 支付时间
      */
+    @DbField("rd.pay_time")
     private Date payTime;
 
+    @DbField("rd.is_free")
     private Boolean isFree;
 
+    @DbField("rd.error_msg")
     private String errorMsg;
 
+    @DbField("ad.id")
+    @TableField(exist = false)
+    private Long appleAutoId;
+
+    @DbField("if(ad.id is null,false,true)")
+    @TableField(exist = false)
+    private Boolean appleIsAutoType;
+
+    @DbField("ad.apple_pwd_id")
+    @TableField(exist = false)
+    private String applePwdId;
+
+    @DbField("ad.country_or_area")
+    @TableField(exist = false)
+    private AppleAutoRegisterData.CountryOrArea countryOrArea;
+
+    @DbField("ad.remark")
+    @TableField(exist = false)
+    private String remark;
+
+    /**
+     * 创建时间
+     */
+    @DbField("rd.created_time")
+    @TableField(fill = FieldFill.INSERT)
+    private Date createdTime;
+
+    /**
+     * 修改时间
+     */
+    @DbField("rd.update_time")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Date updateTime;
+
     public enum Status {
         /**
          * 订单状态

+ 48 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/StatisticsUserData.java

@@ -0,0 +1,48 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: StatisticsUserData
+ *创建者: JavaZou
+ *创建时间:2022/11/24 16:04
+ */
+@Getter
+@Setter
+public class StatisticsUserData extends BaseEntity{
+	/**
+	 * 总用户数
+	 */
+	private Integer numOfUser;
+
+	/**
+	 * 新用户
+	 */
+	private Integer numOfNewUser;
+
+	/**
+	 * 活跃用户
+	 */
+	private Integer numOfActiveUser;
+
+	/**
+	 * pc端总用户数
+	 */
+	private Integer pcNumOfUser;
+
+	/**
+	 * pc端新用户
+	 */
+	private Integer pcNumOfNewUser;
+
+	/**
+	 * 实时pc端活跃用户
+	 */
+	private Integer pcNumOfActiveUser;
+
+	private Date statisticsDate;
+}

+ 19 - 0
netflix-dao/src/main/java/com/cyksj/model/excel/ExcelAppleIdTemplateData.java

@@ -0,0 +1,19 @@
+package com.cyksj.model.excel;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: ExcelAppleIdTempalteData
+ *创建者: JavaZou
+ *创建时间:2022/11/22 15:37
+ */
+@Getter
+@Setter
+public class ExcelAppleIdTemplateData {
+
+	@ExcelProperty(value = "Apple ID/密码",index = 0)
+	private String applePwdId;
+}

+ 97 - 0
netflix-dao/src/main/java/com/cyksj/model/excel/ExcelRealGoodsUserInterestData.java

@@ -0,0 +1,97 @@
+package com.cyksj.model.excel;
+
+import com.alibaba.excel.annotation.ExcelIgnore;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.cyksj.model.entity.RealGoodsInterestUser;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: ExcelRealGoodsUserInterestData
+ *创建者: JavaZou
+ *创建时间:2022/11/25 15:41
+ */
+@Getter
+@Setter
+@SearchBean(tables = "real_goods_interest_user ru " +
+		" left join goods_don_sku gdk on gdk.id = ru.sku_id" +
+		" left join user u on u.id = ru.user_id" +
+		" left join goods_don gd on gd.id = gdk.goods_id" +
+		" left join order_don_transport ot on ot.order_id = ru.order_id")
+public class ExcelRealGoodsUserInterestData {
+
+	@DbField("ru.id")
+	@ExcelIgnore
+	private Long id;
+
+	@DbField("ru.id")
+	@ExcelProperty("用户ID")
+	private Long userId;
+
+	@DbField("ru.goods_id")
+	@ExcelIgnore
+	private Long goodsId;
+
+	@DbField("ru.sku_id")
+	@ExcelIgnore
+	private Long skuId;
+
+	@DbField("ru.order_id")
+	@ExcelIgnore
+	private Long orderId;
+
+	@DbField("u.nickname")
+	@ExcelProperty("用户名称")
+	private String nickname;
+
+	@DbField("ru.order_created_time")
+	@ExcelProperty("创建时间")
+	private Date orderCreatedTime;
+
+	@DbField("ru.pay_time")
+	@ExcelProperty("购买时间")
+	private Date payTime;
+
+	@DbField("gd.title")
+	@ExcelProperty("意向商品")
+	private String goodsTitle;
+
+	@DbField("gdk.spec_val")
+	@ExcelProperty("规格")
+	private String specVal;
+
+	@DbField("cast(gdk.price/100 as decimal(10,0))")
+	@ExcelProperty("金额")
+	private BigDecimal money;
+
+	@DbField("ot.receiver")
+	@ExcelProperty("姓名")
+	private String receiver;
+
+	@DbField("ot.phone")
+	@ExcelProperty("手机号")
+	private String phone;
+
+	@DbField("concat(ot.province,ot.city,ot.district,ot.address)")
+	@ExcelProperty("地址")
+	private String address;
+
+	@DbField("ru.interest_status")
+	@ExcelIgnore
+	private RealGoodsInterestUser.Status interestStatus;
+
+	@DbIgnore
+	@ExcelProperty("意向")
+	private String cnInterestStatus;
+
+	public String getCnInterestStatus() {
+		return interestStatus.getDesc();
+	}
+}

+ 87 - 0
netflix-dao/src/main/java/com/cyksj/model/excel/listener/ExcelAppleDataListener.java

@@ -0,0 +1,87 @@
+package com.cyksj.model.excel.listener;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.event.AnalysisEventListener;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.mapper.AppleAutoRegisterDataMapper;
+import com.cyksj.model.entity.AppleAutoRegisterData;
+import com.cyksj.model.excel.ExcelAppleIdTemplateData;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.dao.DuplicateKeyException;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/*
+ *项目名: netflix
+ *文件名: ExcelAppleDataListener
+ *创建者: JavaZou
+ *创建时间:2022/11/22 15:48
+ */
+public class ExcelAppleDataListener extends AnalysisEventListener<ExcelAppleIdTemplateData> {
+	private static final Logger LOGGER = LoggerFactory.getLogger(ExcelAppleDataListener.class);
+
+	private AppleAutoRegisterDataMapper appleAutoRegisterDataMapper;
+
+	private String countryOrArea;
+
+	private String remark;
+
+	public ExcelAppleDataListener() {
+	}
+
+	public ExcelAppleDataListener(AppleAutoRegisterDataMapper appleAutoRegisterDataMapper, String countryOrArea, String remark) {
+		this.appleAutoRegisterDataMapper = appleAutoRegisterDataMapper;
+		this.countryOrArea = countryOrArea;
+		this.remark = remark;
+	}
+
+	private List<ExcelAppleIdTemplateData> list = new ArrayList<>();
+
+	private static final int BATCH_COUNT = 100;
+
+	@Override
+	public void invoke(ExcelAppleIdTemplateData data, AnalysisContext analysisContext) {
+		LOGGER.info("解析到一条数据:{}", data);
+		if (StrUtil.hasEmpty(data.getApplePwdId())) {
+			throw new BusinessRuntimeException("表格缺少必填参数,请重新确认");
+		}
+		list.add(data);
+		// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
+		if (list.size() >= BATCH_COUNT) {
+			saveData();
+			// 存储完成清理 list
+			list.clear();
+		}
+	}
+
+	@Override
+	public void doAfterAllAnalysed(AnalysisContext analysisContext) {
+		// 这里也要保存数据,确保最后遗留的数据也存储到数据库
+		saveData();
+		list.clear();
+		LOGGER.info("所有数据解析完成!");
+	}
+
+
+	private void saveData() {
+		for (ExcelAppleIdTemplateData data : list) {
+			AppleAutoRegisterData appleAutoRegisterData = new AppleAutoRegisterData();
+			BeanUtil.copyProperties(data, appleAutoRegisterData);
+			AppleAutoRegisterData.CountryOrArea countryOrArea = AppleAutoRegisterData.CountryOrArea.valueOf(this.countryOrArea);
+			if (countryOrArea == null) {
+				throw BusinessRuntimeException.getInstance("该国家或区域不存在");
+			}
+			appleAutoRegisterData.setCountryOrArea(countryOrArea);
+			appleAutoRegisterData.setRemark(remark);
+			try {
+				appleAutoRegisterDataMapper.insert(appleAutoRegisterData);
+			} catch (DuplicateKeyException e) {
+				LOGGER.info("重复Apple ID:{}记录!", data.getApplePwdId());
+			}
+		}
+	}
+}

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/request/RegisterReq.java

@@ -1,5 +1,6 @@
 package com.cyksj.model.manage.request;
 
+import com.cyksj.model.entity.AppleAutoRegisterData;
 import lombok.Data;
 
 /**
@@ -39,4 +40,8 @@ public class RegisterReq {
     private String phone;
 
     private String nickname;
+
+    private String appleRegisterType;
+
+    private AppleAutoRegisterData.CountryOrArea countryOrArea;
 }

+ 23 - 0
netflix-dao/src/main/java/com/cyksj/model/request/UserRealGoodsInterestReq.java

@@ -0,0 +1,23 @@
+package com.cyksj.model.request;
+
+import com.cyksj.model.entity.RealGoodsInterestUser;
+import lombok.Getter;
+import lombok.NonNull;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: UserRealGoodsInterestReq
+ *创建者: JavaZou
+ *创建时间:2022/11/25 15:33
+ */
+@Getter
+@Setter
+public class UserRealGoodsInterestReq {
+	@NonNull
+	private Long id;
+
+	private RealGoodsInterestUser.Status status;
+
+	private String remark;
+}

+ 22 - 0
netflix-dao/src/main/java/com/cyksj/model/views/AppleIdCountryOrAreaDataView.java

@@ -0,0 +1,22 @@
+package com.cyksj.model.views;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: AppleIdHeadDataView
+ *创建者: JavaZou
+ *创建时间:2022/11/22 17:02
+ */
+@Getter
+@Setter
+public class AppleIdCountryOrAreaDataView {
+	private Integer taiWanAvaNum;
+
+	private Integer hongKongAvaNum;
+
+	private Integer usAvaNum;
+
+	private Integer japanAvaNum;
+}

+ 21 - 0
netflix-dao/src/main/java/com/cyksj/model/views/AppleIdHeadDataView.java

@@ -0,0 +1,21 @@
+package com.cyksj.model.views;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: AppleIdHeadDataView
+ *创建者: JavaZou
+ *创建时间:2022/11/22 17:11
+ */
+@Getter
+@Setter
+public class AppleIdHeadDataView {
+
+	private Integer avaAppleIdNum;
+
+	private Integer usedAppleIdNum;
+
+	private AppleIdCountryOrAreaDataView areaDataView;
+}

+ 41 - 0
netflix-dao/src/main/java/com/cyksj/model/views/AppleIdRegisterView.java

@@ -0,0 +1,41 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.AppleAutoRegisterData;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: AppleIdRegisterView
+ *创建者: JavaZou
+ *创建时间:2022/11/22 16:54
+ */
+@Getter
+@Setter
+@SearchBean(tables = "apple_auto_register_data ar left join user u on u.id = ar.user_id")
+public class AppleIdRegisterView {
+	@DbField("ar.id")
+	private Long id;
+
+	@DbField("ar.apple_pwd_id")
+	private String applePwdId;
+
+	@DbField("ar.country_or_area")
+	private AppleAutoRegisterData.CountryOrArea countryOrArea;
+
+	@DbField("ar.status")
+	private Boolean status;
+
+	@DbField("u.id")
+	private Long userId;
+
+	@DbField("u.nickname")
+	private String nickname;
+
+	@DbField("ar.created_time")
+	private Date createdTime;
+}

+ 6 - 0
netflix-dao/src/main/java/com/cyksj/model/views/BackgroundDataView.java

@@ -2,6 +2,7 @@ package com.cyksj.model.views;
 
 import com.cyksj.model.entity.AppleOneData;
 import com.cyksj.model.entity.RealGoodsData;
+import com.cyksj.model.entity.RegisterAccountData;
 import com.cyksj.model.entity.StreamingAccountData;
 import lombok.Getter;
 import lombok.Setter;
@@ -79,4 +80,9 @@ public class BackgroundDataView {
 	 */
 	private List<RealGoodsData> realGoodsDataViews;
 
+	/**
+	 * 注册账号数据
+	 */
+	private List<RegisterAccountData> registerAccountDataViews;
+
 }

+ 66 - 0
netflix-dao/src/main/java/com/cyksj/model/views/RealGoodsInterestUserView.java

@@ -0,0 +1,66 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.RealGoodsInterestUser;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: RealGoodsInterestUserView
+ *创建者: JavaZou
+ *创建时间:2022/11/25 14:53
+ */
+@Getter
+@Setter
+@SearchBean(tables = "real_goods_interest_user ru " +
+		" left join goods_don_sku gdk on gdk.id = ru.sku_id" +
+		" left join user u on u.id = ru.user_id" +
+		" left join goods_don gd on gd.id = gdk.goods_id")
+public class RealGoodsInterestUserView {
+	@DbField("ru.id")
+	private Long id;
+
+	@DbField("ru.order_id")
+	private Long orderId;
+
+	@DbField("ru.goods_id")
+	private Long goodsId;
+
+	@DbField("ru.sku_id")
+	private Long skuId;
+
+	@DbField("ru.user_id")
+	private Long userId;
+
+	@DbField("u.nickname")
+	private String nickname;
+
+	@DbField("ru.order_created_time")
+	private Date orderCreatedTime;
+
+	@DbField("ru.pay_time")
+	private Date payTime;
+
+	@DbField("gd.logo")
+	private String logo;
+
+	@DbField("gd.title")
+	private String goodsTitle;
+
+	@DbField("gdk.spec_val")
+	private String specVal;
+
+	@DbField("gdk.price")
+	private BigDecimal money;
+
+	@DbField("ru.remark")
+	private String remark;
+
+	@DbField("ru.interest_status")
+	private RealGoodsInterestUser.Status interestStatus;
+}

+ 50 - 0
netflix-dao/src/main/java/com/cyksj/model/views/StatisticsUserDataView.java

@@ -0,0 +1,50 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.StatisticsUserData;
+import com.ejlchina.searcher.SearchResult;
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: StatisticsUserDataView
+ *创建者: JavaZou
+ *创建时间:2022/11/24 17:49
+ */
+@Getter
+@Setter
+public class StatisticsUserDataView {
+	private Integer totalOfUser;
+
+	/**
+	 * 公众号用户数
+	 */
+	private Integer numOfUser;
+
+	/**
+	 * pc端用户数
+	 */
+	private Integer pcNumOfUser;
+
+	/**
+	 * 实时新用户
+	 */
+	private Integer numOfNewUser;
+
+	/**
+	 * 实时活跃用户
+	 */
+	private Integer numOfActiveUser;
+
+	/**
+	 * pc端新用户
+	 */
+	private Integer pcNumOfNewUser;
+
+	/**
+	 * 实时pc端活跃用户
+	 */
+	private Integer pcNumOfActiveUser;
+
+	SearchResult<StatisticsUserData> userData;
+}

+ 40 - 0
netflix-dao/src/main/resources/mapper/OrderDonMapper.xml

@@ -2,6 +2,25 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.cyksj.mapper.OrderDonMapper">
 
+    <update id="updateHasPaymentInterestRealGoods">
+        update real_goods_interest_user
+        set interest_status = 'hasPayment'
+        where id in (select id
+                     from (select distinct ru.id
+                           from `real_goods_interest_user` ru
+                                    left join `order_don` od on od.user_id = ru.user_id and od.goods_id = ru.goods_id
+                           where od.status not in ('close', 'noPayment')
+                             and ru.interest_status != 'hasPayment') s)
+    </update>
+
+    <update id="updateHasPaymentInterestRealGoodsPayTime">
+        update real_goods_interest_user ru
+        set ru.pay_time= (select if(pay_time is null,created_time,pay_time) from `order_don` od where od.user_id = ru.user_id and od.goods_id = ru.goods_id order by money desc limit 1),
+            ru.sku_id = (select sku_id from `order_don` od where od.user_id = ru.user_id and od.goods_id = ru.goods_id order by money desc limit 1)
+        where interest_status = 'hasPayment'
+          and pay_time is null
+    </update>
+
 
     <select id="exportOrderInfo" resultType="com.cyksj.model.excel.ExcelOrderDonInfo">
         SELECT o.order_no, o.real_name ,o.price,o.phone,o.source,o.pay_time ,u1.nickname as sharedName,u2.nickname as nickName
@@ -39,4 +58,25 @@
         </foreach>
         where g.title = #{appleOne} and gr.status = 'validity'
     </select>
+
+    <select id="selectNoPaymentRealGoods" resultType="com.cyksj.model.entity.RealGoodsInterestUser">
+        select s.*
+        from (select od.id                     as orderId,
+                     od.user_id,
+                     gd.id                     as goods_id,
+                     od.sku_id,
+                     od.money,
+                     concat(od.user_id, gd.id) as groupBy,
+                     od.created_time           as orderCreatedTime
+              from `order_don` od
+                       left join `goods_don` gd on gd.id = od.goods_id
+                       left join `real_goods_interest_user` ru on ru.user_id = od.user_id
+                  and ru.goods_id = od.goods_id
+              where gd.type = 2
+                and od.status = 'close'
+                and ru.id is null
+              group by od.id, od.user_id, gd.id, od.sku_id, od.money, od.created_time) s
+        where not EXISTS(
+                select id from `order_don` where user_id = s.user_id and goods_id = s.goods_id and status !='close')
+    </select>
 </mapper>

+ 27 - 8
netflix-dao/src/main/resources/mapper/RealGoodsDataMapper.xml

@@ -4,13 +4,13 @@
 <mapper namespace="com.cyksj.mapper.manage.statistics.RealGoodsDataMapper">
 
     <select id="statisticsRealGoodsData" resultType="com.cyksj.model.entity.RealGoodsData">
-        select goods_id,
-               sku_id,
-               max(goods_title) as goods_title,
-               max(spec_val) as spec_val,
-               sum(num_of_user) as num_of_user,
-               sum(num_of_order) as num_of_order,
-               cast(sum(money)/100 as decimal(20,2)) as money
+        select * from (select goods_id,
+        sku_id,
+        max(goods_title) as goods_title,
+        max(spec_val) as spec_val,
+        sum(num_of_user) as num_of_user,
+        sum(num_of_order) as num_of_order,
+        cast(sum(money)/100 as decimal(20,2)) as money
         from real_goods_data
         <where>
             <if test="startDate != null">
@@ -20,6 +20,25 @@
                 and statistics_date &lt; #{endDate}
             </if>
         </where>
-        group by goods_id,sku_id
+        group by goods_id,sku_id)s where s.num_of_user > 0 and num_of_order > 0 and money > 0
+    </select>
+
+    <select id="statisticsRegisterAccountData" resultType="com.cyksj.model.entity.RegisterAccountData">
+        select platform,
+        sum(num_of_user) as numOfUser,
+        sum(num_of_order) as numOfOrder,
+        cast(sum(money)/100 as decimal(20,2)) as money,
+        sum(num_of_refund_order) as numOfRefundOrder,
+        cast(sum(refund_money)/100 as decimal(20,2)) as refundMoney
+        from register_account_data
+        <where>
+            <if test="startDate != null">
+                statistics_date >= #{startDate}
+            </if>
+            <if test="endDate != null">
+                and statistics_date &lt; #{endDate}
+            </if>
+        </where>
+        group by platform
     </select>
 </mapper>

+ 4 - 0
netflix-service/src/main/java/com/cyksj/common/EnvCommonService.java

@@ -27,4 +27,8 @@ public class EnvCommonService {
 		}
 		return "netflix.tw.cn";
 	}
+
+	public String getDomain() {
+		return this.getHost().substring(0, this.getHost().indexOf("8081"));
+	}
 }

+ 10 - 0
netflix-service/src/main/java/com/cyksj/service/mange/statistics/impl/StatisticsDataServiceImpl.java

@@ -85,9 +85,19 @@ public class StatisticsDataServiceImpl implements StatisticsDataService {
 		getStreamingAccountDataView(backgroundDataView, startDate, endDate);
 		//实物数据
 		getRealGoodsData(backgroundDataView, startDate, endDate);
+		//注册账号数据
+		getRegisterAccountData(backgroundDataView, startDate, endDate);
 		return GatewayResponse.SUCCESS.newBuilder().toResult(backgroundDataView);
 	}
 
+	/**
+	 * 注册账号数据
+	 */
+	private void getRegisterAccountData(BackgroundDataView backgroundDataView, Date startDate, Date endDate) {
+		List<RegisterAccountData> registerAccountData = realGoodsDataMapper.statisticsRegisterAccountData(startDate, endDate);
+		backgroundDataView.setRegisterAccountDataViews(registerAccountData);
+	}
+
 	@Override
 	public IPage<ExpiredAccountDataView> getExpiredAccountView(Integer goodsId, String account, Boolean renewStatus, Boolean handleStatus, String cnAccount, String usAccount, Integer userId, Long startTime, Long endTime, Long start, Long limit) {
 		String startDate = null;

+ 7 - 4
netflix-service/src/main/java/com/cyksj/service/order/OrderDonService.java

@@ -4,10 +4,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import com.cyksj.dto.Result;
 import com.cyksj.model.dto.AliPayParams;
 import com.cyksj.model.dto.H5JsPayParams;
-import com.cyksj.model.entity.GoodsDon;
-import com.cyksj.model.entity.GoodsDonSku;
-import com.cyksj.model.entity.OrderDon;
-import com.cyksj.model.entity.User;
+import com.cyksj.model.entity.*;
 import com.cyksj.model.manage.views.OrderDonView;
 import com.cyksj.model.request.OrderPayRequest;
 import com.cyksj.model.request.WxOrderRefundReq;
@@ -80,4 +77,10 @@ public interface OrderDonService extends IService<OrderDon> {
      * 发送新订单模板消息
      */
 	void newOderSendMsgByType(OrderDon order, GoodsDon goodsDon, GoodsDonSku sku, User user,String toPeople) throws Exception;
+
+    List<RealGoodsInterestUser> selectNoPaymentRealGoods();
+
+    Integer updateHasPaymentInterestRealGoods();
+
+    void updateHasPaymentInterestRealGoodsPayTime();
 }

+ 19 - 0
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java

@@ -354,6 +354,21 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
         weChatService.sendTemplateMessage(weChatService.getAccessToken(), Jsons.toJson(templateMessage));
     }
 
+	@Override
+	public List<RealGoodsInterestUser> selectNoPaymentRealGoods() {
+		return orderDonMapper.selectNoPaymentRealGoods();
+	}
+
+	@Override
+	public Integer updateHasPaymentInterestRealGoods() {
+		return orderDonMapper.updateHasPaymentInterestRealGoods();
+	}
+
+	@Override
+	public void updateHasPaymentInterestRealGoodsPayTime() {
+		orderDonMapper.updateHasPaymentInterestRealGoodsPayTime();
+	}
+
 	@Transactional(rollbackFor = Throwable.class)
 	@Override
 	public void closeOrder(Long orderId) {
@@ -854,6 +869,10 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		String body = Codec.DoBase64.custom()
 				.setData(Jsons.toJson(attach)).encodeAsText();
 		OrderDon orderDon = orderDonMapper.selectById(orderId);
+		if (orderDon.getType() != OrderDon.Type.ALI_PAY) {
+			orderDon.setType(OrderDon.Type.ALI_PAY);
+			orderDonMapper.updateById(orderDon);
+		}
 		GoodsDonSku goodsDonSku = goodsDonSkuMapper.selectById(orderDon.getSkuId());
 		GoodsDon goodsDon = goodsDonMapper.selectById(goodsDonSku.getGoodsId());
 		if (ZfbProductCode.MOBILE_WEB.getProductCode().equals(productCode)) {

+ 2 - 0
netflix-service/src/main/java/com/cyksj/service/register/RegisterOrderDonService.java

@@ -20,4 +20,6 @@ public interface RegisterOrderDonService extends IService<RegisterOrderDon> {
     H5JsPayParams pay(Long orderId) throws Exception;
 
     void prepayNotify(Map<String, String> map) throws Exception;
+
+    void updateAppleAutoStatus(Long orderId);
 }

+ 71 - 7
netflix-service/src/main/java/com/cyksj/service/register/impl/RegisterOrderDonServiceImpl.java

@@ -10,12 +10,11 @@ import com.cyksj.common.util.Codec;
 import com.cyksj.common.util.Jsons;
 import com.cyksj.config.WeChatConfig;
 import com.cyksj.dto.RedisKey;
+import com.cyksj.mapper.AppleAutoRegisterDataMapper;
 import com.cyksj.mapper.RegisterOrderDonMapper;
 import com.cyksj.mapper.UserMapper;
 import com.cyksj.model.dto.H5JsPayParams;
-import com.cyksj.model.entity.RegisterOrderDon;
-import com.cyksj.model.entity.SysConfig;
-import com.cyksj.model.entity.User;
+import com.cyksj.model.entity.*;
 import com.cyksj.model.manage.request.RegisterReq;
 import com.cyksj.model.request.OrderAttach;
 import com.cyksj.redis.RedisService;
@@ -23,6 +22,7 @@ import com.cyksj.service.register.RegisterOrderDonService;
 import com.cyksj.service.register.SpotifyService;
 import com.cyksj.service.sys.SysConfigService;
 import com.cyksj.service.wechat.WeChatService;
+import com.cyksj.task.JobManager;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
@@ -57,6 +57,14 @@ public class RegisterOrderDonServiceImpl extends ServiceImpl<RegisterOrderDonMap
 
     private final UserMapper userMapper;
 
+    private final AppleAutoRegisterDataMapper appleAutoRegisterDataMapper;
+
+    private final JobManager jobManager;
+
+    private final RegisterOrderDonMapper registerOrderDonMapper;
+
+    private static final Long EXPIRY_TIME = 1000 * 60 * 5L;
+
     /**
      * 判断是否免费
      * @author chan
@@ -93,7 +101,6 @@ public class RegisterOrderDonServiceImpl extends ServiceImpl<RegisterOrderDonMap
         BeanUtil.copyProperties(req,orderDon);
         SysConfig register_price = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, "register_price").last("limit 1"));
         Map<String, Integer> map = Jsons.toMap(register_price.getSysValue());
-
         orderDon.setOrderNo(SEQUENCE.nextId() + "");
         orderDon.setUserId(userId);
         orderDon.setOpenId(user.getOpenId());
@@ -101,15 +108,68 @@ public class RegisterOrderDonServiceImpl extends ServiceImpl<RegisterOrderDonMap
         orderDon.setMoney(isFree ? BigDecimal.ZERO : BigDecimal.valueOf(map.get(req.getPlatform())));
         orderDon.setStatus(isFree ? RegisterOrderDon.Status.hasPayment : RegisterOrderDon.Status.noPayment);
         save(orderDon);
-
+        //apple
+        handleAppleIdAuto(userId, req, orderDon);
         return orderDon;
     }
 
+    /**
+     *  Apple ID自动注册
+     */
+    private void handleAppleIdAuto(long userId, RegisterReq req, RegisterOrderDon orderDon) {
+        if ("apple".equals(req.getPlatform()) && "auto".equals(req.getAppleRegisterType())) {
+            //是否有未支付的国家或区域的订单
+            Integer exists = appleAutoRegisterDataMapper.checkNoPayOrder(userId, req.getCountryOrArea());
+            if (exists != null) {
+                throw BusinessRuntimeException.getInstance(String.format("您有%s随机生成Apple ID未支付的订单", req.getCountryOrArea().getDesc()));
+            }
+            if (req.getCountryOrArea() == null) {
+                throw BusinessRuntimeException.getInstance("请选择对应的国家或地区");
+            }
+            //查看是否有空余账号
+            AppleAutoRegisterData appleAutoRegisterData = appleAutoRegisterDataMapper.selectOne(Wrappers.lambdaQuery(AppleAutoRegisterData.class).eq(AppleAutoRegisterData::getCountryOrArea, req.getCountryOrArea()).eq(AppleAutoRegisterData::getStatus, false).select(AppleAutoRegisterData::getId).last("limit 1"));
+            if (appleAutoRegisterData == null) {
+                throw BusinessRuntimeException.getInstance("自动生成Apple ID库存不足");
+            }
+            appleAutoRegisterData.setUserId(userId);
+            appleAutoRegisterData.setStatus(true);
+            appleAutoRegisterData.setOrderId(orderDon.getId());
+            int update = appleAutoRegisterDataMapper.update(appleAutoRegisterData, Wrappers.lambdaUpdate(AppleAutoRegisterData.class).eq(AppleAutoRegisterData::getStatus, false).eq(AppleAutoRegisterData::getId, appleAutoRegisterData.getId()));
+            if (update != 1) {
+                throw BusinessRuntimeException.getInstance("系统异常,请重新操作");
+            }
+            jobManager.addJob(EXPIRY_TIME, () -> {
+                updateAppleAutoStatus(orderDon.getId());
+            });
+        }
+    }
+
+    @Override
+    public void updateAppleAutoStatus(Long orderId) {
+        log.info("校验appleID自动注册订单 orderId:{}", orderId);
+        RegisterOrderDon registerOrderDon = this.getById(orderId);
+        if (registerOrderDon != null && RegisterOrderDon.Status.noPayment == registerOrderDon.getStatus()) {
+            AppleAutoRegisterData appleAutoRegisterData = appleAutoRegisterDataMapper.selectOne(Wrappers.lambdaQuery(AppleAutoRegisterData.class).eq(AppleAutoRegisterData::getOrderId, orderId).last("limit 1"));
+            if (appleAutoRegisterData != null) {
+                appleAutoRegisterData.setStatus(false);
+                appleAutoRegisterData.setUserId(0l);
+                appleAutoRegisterData.setOrderId(0l);
+                appleAutoRegisterDataMapper.updateById(appleAutoRegisterData);
+                //订单关闭
+                registerOrderDon.setStatus(RegisterOrderDon.Status.close);
+                registerOrderDonMapper.updateById(registerOrderDon);
+                log.info("未支付appleID自动注册订单:{},修改appleID使用状态", orderId);
+            }
+        }
+    }
+
     @Override
     public H5JsPayParams pay(Long orderId) throws Exception {
         log.info("注册 账号调起微信支付[start] orderId:{}", orderId);
         RegisterOrderDon orderDon = this.getById(orderId);
-
+        if (orderDon.getStatus() == RegisterOrderDon.Status.close) {
+            throw BusinessRuntimeException.getInstance("订单已关闭");
+        }
         OrderAttach attach = new OrderAttach();
         attach.setO(orderDon.getId());
 
@@ -125,7 +185,7 @@ public class RegisterOrderDonServiceImpl extends ServiceImpl<RegisterOrderDonMap
                 toWechatAttach,
                 "注册服务",
                 "JSAPI",
-                orderDon.getCreatedTime()
+                null
         );
 
         log.info("微信支付成功[end]");
@@ -169,6 +229,10 @@ public class RegisterOrderDonServiceImpl extends ServiceImpl<RegisterOrderDonMap
         // 更改订单状态
         order.setTransactionId(transactionId);
         order.setStatus(RegisterOrderDon.Status.hasPayment);
+        AppleAutoRegisterData appleAutoRegisterData = appleAutoRegisterDataMapper.selectOne(Wrappers.lambdaQuery(AppleAutoRegisterData.class).eq(AppleAutoRegisterData::getOrderId, order.getId()).eq(AppleAutoRegisterData::getStatus, true));
+        if (appleAutoRegisterData != null) {
+            order.setStatus(RegisterOrderDon.Status.complete);
+        }
 
         order.setPayTime(DateUtil.parse(map.get("time_end"), "yyyyMMddHHmmss"));
 

+ 33 - 5
netflix-service/src/main/java/com/cyksj/service/register/impl/SpotifyServiceImpl.java

@@ -1,27 +1,29 @@
 package com.cyksj.service.register.impl;
 
-import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.RandomUtil;
 import cn.hutool.http.HttpRequest;
 import cn.hutool.http.HttpResponse;
 import cn.hutool.http.HttpUtil;
 import cn.hutool.http.Method;
-import cn.hutool.json.JSONArray;
 import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.cyksj.common.EnvCommonService;
+import com.cyksj.common.constant.TemplateEnum;
+import com.cyksj.common.util.Jsons;
 import com.cyksj.dto.RedisKey;
-import com.cyksj.dto.Result;
-import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.ProxysMapper;
 import com.cyksj.mapper.RegisterOrderDonMapper;
+import com.cyksj.model.dto.WxMpTemplateData;
+import com.cyksj.model.dto.WxMpTemplateMessage;
 import com.cyksj.model.entity.Proxys;
 import com.cyksj.model.entity.RegisterOrderDon;
-import com.cyksj.model.entity.SpotifyRegister;
 import com.cyksj.model.response.ProxyInfo;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.register.SpotifyService;
+import com.cyksj.service.wechat.WeChatService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
@@ -47,6 +49,10 @@ public class SpotifyServiceImpl implements SpotifyService {
 
     private final RedisService redisService;
 
+    private final EnvCommonService envCommonService;
+
+    private final WeChatService weChatService;
+
     private static final List<String> User_Agent_LIST =  List.of(
             "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
             "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)",
@@ -196,6 +202,8 @@ public class SpotifyServiceImpl implements SpotifyService {
                         registerOrderDon.setStatus(RegisterOrderDon.Status.complete);
                         registerOrderDonMapper.updateById(registerOrderDon);
                         regFlag = true;
+                        //注册成功发放模板消息
+                        spotifyTemplateMsg(registerOrderDon, String.format("%s%s", envCommonService.getDomain(), "yinhe/web/sign/list"), true);
                         break;
                     } else {
                         if (errors != null && !errors.isEmpty()) {
@@ -207,6 +215,8 @@ public class SpotifyServiceImpl implements SpotifyService {
                             registerOrderDon.setStatus(RegisterOrderDon.Status.error);
                             registerOrderDonMapper.updateById(registerOrderDon);
                             regFlag = true;
+                            //注册失败发放模板消息
+                            spotifyTemplateMsg(registerOrderDon, String.format("%s%s", envCommonService.getDomain(), "yinhe/web/sign/list"), false);
                             break;
                         }
                     }
@@ -227,5 +237,23 @@ public class SpotifyServiceImpl implements SpotifyService {
         }
     }
 
+    private void spotifyTemplateMsg(RegisterOrderDon registerOrderDon, String url, Boolean isSuccess) throws Exception {
+        TemplateEnum templateEnum = null;
+        if (EnvCommonService.active.equals(envCommonService.getEnv())) {
+            templateEnum = TemplateEnum.SPOTIFY_ENV_TEMPLATE;
+        }else {
+            templateEnum = TemplateEnum.SPOTIFY_PRD_TEMPLATE;
+        }
+        WxMpTemplateMessage templateMessage = new WxMpTemplateMessage()
+                .setToUser(registerOrderDon.getOpenId())
+                .setTemplateId(templateEnum.getTemplateId())
+                .setUrl(url);
+        WxMpTemplateMessage.TemplateData data = templateMessage.getData();
+        data.setFirst(new WxMpTemplateData(isSuccess ? "Spotify账号已注册成功" : "Spotify账号注册失败,请修改后重新提交"));
+        data.setKeyword1(new WxMpTemplateData(registerOrderDon.getPhone()));
+        data.setKeyword2(new WxMpTemplateData(DateUtil.format(registerOrderDon.getCreatedTime(), "yyyy-MM-dd HH:mm:ss")));
+        weChatService.sendTemplateMessage(weChatService.getAccessToken(), Jsons.toJson(templateMessage));
+    }
+
 
 }

+ 4 - 2
netflix-service/src/main/java/com/cyksj/service/wechat/impl/WeChatServiceImpl.java

@@ -197,11 +197,13 @@ public class WeChatServiceImpl implements WeChatService {
                 .setNonceStr("chan.123")
                 .setNotifyUrl(notifyUrl)
                 .setOutTradeNo(outTradeNo)
-                //5分钟过期
-                .setTimeExpire(DateUtil.format(DateUtil.offsetMinute(expireTime, 5), "yyyyMMddHHmmss"))
                 .setSpbillCreateIp("127.0.0.1")
                 .setTotalFee(totalFee)
                 .setTradeType(tradeType);
+        if (expireTime != null) {
+            //5分钟过期
+            order.setTimeExpire(DateUtil.format(DateUtil.offsetMinute(expireTime, 5), "yyyyMMddHHmmss"));
+        }
         if (!"NATIVE".equals(tradeType)) {
             order.setOpenid(openid);
         }

+ 59 - 2
netflix-service/src/main/java/com/cyksj/task/Scheduler.java

@@ -13,16 +13,18 @@ import com.cyksj.model.dto.WxMpTemplateMessage;
 import com.cyksj.model.entity.*;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.order.OrderDonService;
+import com.cyksj.service.register.RegisterOrderDonService;
 import com.cyksj.service.register.SpotifyService;
 import com.cyksj.service.wechat.WeChatService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.dao.DuplicateKeyException;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.util.Date;
-import java.util.List;
+import java.util.*;
+import java.util.stream.Collectors;
 
 import static com.cyksj.common.constant.WeChatTemplateConst.EXPIRY_TEMPLATE;
 
@@ -57,6 +59,12 @@ public class Scheduler {
 
         private final SysConfigMapper sysConfigMapper;
 
+        private final RegisterOrderDonService registerOrderDonService;
+
+        private final AppleAutoRegisterDataMapper appleAutoRegisterDataMapper;
+
+        private final RealGoodsInterestUserMapper realGoodsInterestUserMapper;
+
 
     /**
      * 每5分钟清理过期账号
@@ -191,4 +199,53 @@ public class Scheduler {
         redisService.set(RedisKey.SPOTIFY_FREE_NUM, Long.parseLong(register_free_num.getSysValue()));
         log.info("每日重置 spotify 免单账户数 [end] 数量:{}",register_free_num.getSysValue());
     }
+
+    /**
+     * 定时更新未支付AppleID自动注册订单
+     */
+    @Scheduled(cron = "0 0/5 * * * ?")
+    public void updateAppleAutoStatus() {
+        //获取为支付订单
+        DateTime now = new DateTime();
+        Date newDate = DateUtil.offset(now, DateField.MINUTE, -5);
+        List<Long> orderDons = appleAutoRegisterDataMapper.getAllNoPayOrders(newDate);
+        log.info("定时更新未支付AppleID自动注册订单 订单数:{}",orderDons.size());
+        orderDons.forEach((orderId)->{
+            registerOrderDonService.updateAppleAutoStatus(orderId);
+        });
+    }
+
+    /**
+     * 实物订单意愿数据
+     */
+    @Scheduled(cron = "0 0/5 * * * ?")
+    public void realGoodsInterestUser() {
+        Optional.ofNullable(orderDonService.selectNoPaymentRealGoods()).ifPresent(list -> {
+                    if (list.size() > 0) {
+                        Map<String, List<RealGoodsInterestUser>> collect = list.stream().collect(Collectors.groupingBy(RealGoodsInterestUser::getGroupBy));
+                        log.info("实物订单意愿数据同步开始");
+                        collect.forEach((k, data) -> {
+                            RealGoodsInterestUser realGoodsInterestUser = null;
+                            if (data.size() == 0) {
+                                realGoodsInterestUser = data.get(0);
+                            } else {
+                                List<RealGoodsInterestUser> high = data.stream().sorted(Comparator.comparing(RealGoodsInterestUser::getMoney).thenComparing(RealGoodsInterestUser::getOrderCreatedTime).reversed()).collect(Collectors.toList());
+                                realGoodsInterestUser = high.get(0);
+                            }
+                            try {
+                                realGoodsInterestUserMapper.insert(realGoodsInterestUser);
+                            } catch (DuplicateKeyException e) {
+                                log.info("重复插入用户相同实物商品记录");
+                            }
+                        });
+                        log.info("实物订单意愿数据同步结束");
+                    }
+                }
+        );
+        Integer update = orderDonService.updateHasPaymentInterestRealGoods();
+        orderDonService.updateHasPaymentInterestRealGoodsPayTime();
+        if (update > 0) {
+            log.info("更新用户记录:{}已购买实物意愿商品状态成功", update);
+        }
+    }
 }

+ 50 - 2
netflix-service/src/main/java/com/cyksj/task/StatisticsDataScheduler.java

@@ -6,8 +6,11 @@ import cn.hutool.core.date.DateUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
 import com.cyksj.mapper.GoodsDonMapper;
+import com.cyksj.mapper.RegisterAccountDataMapper;
+import com.cyksj.mapper.RegisterOrderDonMapper;
 import com.cyksj.mapper.manage.statistics.AppleOneDataMapper;
 import com.cyksj.mapper.manage.statistics.RealGoodsDataMapper;
+import com.cyksj.mapper.manage.statistics.StatisticsUserDataMapper;
 import com.cyksj.mapper.manage.statistics.StreamingAccountDataMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.service.mange.CmsAccountService;
@@ -51,7 +54,7 @@ public class StatisticsDataScheduler {
 
 	public static List<String> payType = List.of("月", "季", "年");
 
-	private final static List<String> APPLE_ONE_AREA = List.of("美区", "马来西亚区");
+	private final static List<String> registerAccount = List.of("apple", "spotify", "google");
 
 	private static Long DAY_MILLS = 86400000l;
 
@@ -59,6 +62,12 @@ public class StatisticsDataScheduler {
 
 	private final RealGoodsDataMapper realGoodsDataMapper;
 
+	private final RegisterOrderDonMapper registerOrderDonMapper;
+
+	private final RegisterAccountDataMapper registerAccountDataMapper;
+
+	private final StatisticsUserDataMapper statisticsUserDataMapper;
+
 	/**
 	 * 后台数据统计 定时器
 	 */
@@ -71,8 +80,47 @@ public class StatisticsDataScheduler {
 		//统计流媒体账号数据
 		TASK_POOL.execute(() -> statisticsStreamingAccountData(yesZeroDate, thisZeroDate));
 		//统计实物数据
-		statisticsRealGoodsData(yesZeroDate, thisZeroDate);
+		TASK_POOL.execute(()->statisticsRealGoodsData(yesZeroDate, thisZeroDate));
+		//注册账号数据
+		TASK_POOL.execute(() -> statisticsRegisterAccountData(yesZeroDate, thisZeroDate));
+		//用户数据统计
+		statisticsUserData(yesZeroDate, thisZeroDate);
+
+	}
+
+	/**
+	 * 用户数据统计
+	 */
+	private void statisticsUserData(Date yesZeroDate, Date thisZeroDate) {
+		StatisticsUserData yesData = statisticsUserDataMapper.selectOne(Wrappers.lambdaQuery(StatisticsUserData.class).orderByDesc(StatisticsUserData::getId).select(StatisticsUserData::getNumOfUser, StatisticsUserData::getPcNumOfUser).last("limit 1"));
+		Integer yesNumOfUser = yesData == null ? 0 : yesData.getNumOfUser();
+		Integer yesPcNumOfUser = yesData == null ? 0 : yesData.getPcNumOfUser();
+		StatisticsUserData statisticsUserData = new StatisticsUserData();
+		statisticsUserData.setNumOfNewUser(statisticsUserDataMapper.getNumOfNewUser(yesZeroDate, thisZeroDate));
+		statisticsUserData.setNumOfActiveUser(statisticsUserDataMapper.getNumOfActiveUser(yesZeroDate, thisZeroDate));
+		statisticsUserData.setNumOfUser(yesNumOfUser + statisticsUserData.getNumOfNewUser());
+
+		statisticsUserData.setPcNumOfNewUser(statisticsUserDataMapper.getPcNumOfNewUser(yesZeroDate, thisZeroDate));
+		statisticsUserData.setPcNumOfActiveUser(statisticsUserDataMapper.getPcNumOfActiveUser(yesZeroDate, thisZeroDate));
+		statisticsUserData.setPcNumOfUser(yesPcNumOfUser + statisticsUserData.getPcNumOfNewUser());
+
+		statisticsUserData.setStatisticsDate(yesZeroDate);
+		statisticsUserDataMapper.insert(statisticsUserData);
+	}
 
+	/**
+	 * 注册账号数据
+	 */
+	private void statisticsRegisterAccountData(Date yesZeroDate, Date thisZeroDate) {
+		registerAccount.forEach(platform->{
+			RegisterAccountData entity = Optional.ofNullable(registerOrderDonMapper.registerAccountDataEveryDay(yesZeroDate, thisZeroDate, platform)).orElse(new RegisterAccountData());
+			entity.setPlatform(platform);
+			RegisterAccountData dto = Optional.ofNullable(registerOrderDonMapper.selectRefundOrderDetail(yesZeroDate, thisZeroDate, platform)).orElse(new RegisterAccountData());
+			entity.setNumOfRefundOrder(dto.getNumOfRefundOrder());
+			entity.setRefundMoney(dto.getRefundMoney());
+			entity.setStatisticsDate(yesZeroDate);
+			registerAccountDataMapper.insert(entity);
+		});
 	}
 
 	/**

+ 72 - 4
netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsOrderController.java

@@ -1,29 +1,33 @@
 package com.cyksj.web.controller.manage;
 
-import cn.hutool.core.date.DateUtil;
 import com.alibaba.excel.support.ExcelTypeEnum;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.RealGoodsInterestUserMapper;
 import com.cyksj.model.entity.OrderDon;
 import com.cyksj.model.entity.OrderDonTransport;
 import com.cyksj.model.entity.OrderDonWaybill;
-import com.cyksj.model.excel.ExcelOrderDonInfo;
+import com.cyksj.model.entity.RealGoodsInterestUser;
+import com.cyksj.model.excel.ExcelRealGoodsUserInterestData;
 import com.cyksj.model.manage.request.ReqSetLogisticsPost;
 import com.cyksj.model.manage.views.OrderDonView;
+import com.cyksj.model.request.UserRealGoodsInterestReq;
+import com.cyksj.model.views.RealGoodsInterestUserView;
 import com.cyksj.service.mange.CmsOrderDonService;
 import com.cyksj.service.user.UserService;
 import com.cyksj.web.util.EasyExcelUtils;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.param.Operator;
+import com.ejlchina.searcher.util.MapBuilder;
 import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
-import org.apache.commons.lang3.StringUtils;
+import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import java.util.Date;
 import java.util.List;
 
 /**
@@ -45,6 +49,8 @@ public class CmsOrderController {
 
     private final BeanSearcher beanSearcher;
 
+    private final RealGoodsInterestUserMapper realGoodsInterestUserMapper;
+
 
     @GetMapping("/get")
     public Result<SearchResult<OrderDonView>> get(){
@@ -72,4 +78,66 @@ public class CmsOrderController {
         return GatewayResponse.SUCCESS.newBuilder().toResult(orderDonWaybill);
     }
 
+    /**
+     * 用户购买实物商品意愿列表
+     */
+    @GetMapping("/get/realGooods/interest/users")
+    public Result<SearchResult<RealGoodsInterestUserView>> getInterestUserList(RealGoodsInterestUser.Status interestStatus,HttpServletRequest request) {
+        MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
+        if (interestStatus == null) {
+            builder.field(RealGoodsInterestUserView::getInterestStatus, "hasPayment").op(Operator.NotEqual);
+        }
+        SearchResult<RealGoodsInterestUserView> search = beanSearcher.search(RealGoodsInterestUserView.class, builder.build());
+        search.getDataList().forEach(data->{
+            Long goodsId = data.getGoodsId();
+            OrderDon order = cmsOrderDonService.getOne(Wrappers.lambdaQuery(OrderDon.class).eq(OrderDon::getUserId, data.getUserId()).eq(OrderDon::getGoodsId, goodsId).ne(OrderDon::getId, data.getId()).gt(OrderDon::getMoney, data.getMoney()).eq(OrderDon::getStatus, "close").last("limit 1"));
+            if (order != null) {
+                data.setOrderId(order.getId());
+                data.setSkuId(order.getSkuId());
+                data.setMoney(order.getMoney());
+                data.setOrderCreatedTime(order.getCreatedTime());
+                realGoodsInterestUserMapper.updateData(data.getId(), data.getSkuId(), data.getOrderCreatedTime(), data.getOrderId());
+            }
+        });
+        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+    }
+
+    /**
+     * 修改购买意愿记录
+     */
+    @PutMapping("/put/interest")
+    public Result<String> updateInterest(@RequestBody @Validated UserRealGoodsInterestReq req) {
+        RealGoodsInterestUser realGoodsInterestUser = realGoodsInterestUserMapper.selectById(req.getId());
+        if (realGoodsInterestUser != null) {
+            if (req.getStatus() != null) {
+                realGoodsInterestUser.setInterestStatus(req.getStatus());
+            }
+            if (req.getRemark() != null) {
+                realGoodsInterestUser.setRemark(req.getRemark());
+            }
+            realGoodsInterestUserMapper.updateById(realGoodsInterestUser);
+        }
+        return GatewayResponse.SUCCESS.newBuilder().toResult("修改成功");
+    }
+
+    /**
+     * 导出用户意愿列表
+     */
+    @GetMapping("/export/interest")
+    public void exportInterest(HttpServletRequest request, HttpServletResponse response) {
+        List<ExcelRealGoodsUserInterestData> excelRealGoodsUserInterestData = beanSearcher.searchAll(ExcelRealGoodsUserInterestData.class, MapUtils.flatBuilder(request.getParameterMap()).build());
+        excelRealGoodsUserInterestData.forEach(data -> {
+            Long goodsId = data.getGoodsId();
+            OrderDon order = cmsOrderDonService.getOne(Wrappers.lambdaQuery(OrderDon.class).eq(OrderDon::getUserId, data.getUserId()).eq(OrderDon::getGoodsId, goodsId).ne(OrderDon::getId, data.getId()).gt(OrderDon::getMoney, data.getMoney()).eq(OrderDon::getStatus, "close").last("limit 1"));
+            if (order != null) {
+                data.setOrderId(order.getId());
+                data.setSkuId(order.getSkuId());
+                data.setMoney(order.getMoney());
+                data.setOrderCreatedTime(order.getCreatedTime());
+                realGoodsInterestUserMapper.updateData(data.getId(), data.getSkuId(), data.getOrderCreatedTime(), data.getOrderId());
+            }
+        });
+        EasyExcelUtils.createExcelStreamMutilByEasyExcel(response, ExcelRealGoodsUserInterestData.class, excelRealGoodsUserInterestData, "用户意愿列表", "用户意愿列表", ExcelTypeEnum.XLSX, null);
+    }
+
 }

+ 2 - 2
netflix-web/src/main/java/com/cyksj/web/controller/manage/group/CmsGroupController.java

@@ -1,13 +1,12 @@
 package com.cyksj.web.controller.manage.group;
 
+import com.cyksj.common.annotation.NoSubmit;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.GroupsRelationMapper;
 import com.cyksj.model.entity.Account;
-import com.cyksj.model.entity.GoodsDonSku;
 import com.cyksj.model.entity.GroupsTrips;
-import com.cyksj.model.manage.views.AccountView;
 import com.cyksj.service.mange.CmsAccountService;
 import com.cyksj.service.mange.CmsGoodsDonSkuService;
 import com.cyksj.service.mange.CmsGroupService;
@@ -67,6 +66,7 @@ public class CmsGroupController {
     }
 
     @PostMapping("/post")
+    @NoSubmit
     public Result<GroupsTrips> add(@RequestBody GroupsTrips groups){
 
         GroupsTrips groupsTrips = groupService.issuance(groups);

+ 74 - 11
netflix-web/src/main/java/com/cyksj/web/controller/manage/register/CmsRegisterController.java

@@ -1,27 +1,32 @@
 package com.cyksj.web.controller.manage.register;
 
-import com.cyksj.common.exception.BusinessRuntimeException;
-import com.cyksj.common.util.IoKit;
-import com.cyksj.common.util.Xmls;
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.support.ExcelTypeEnum;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
-import com.cyksj.model.dto.H5JsPayParams;
+import com.cyksj.mapper.AppleAutoRegisterDataMapper;
+import com.cyksj.model.entity.AppleAutoRegisterData;
 import com.cyksj.model.entity.RegisterOrderDon;
-import com.cyksj.model.manage.request.RegisterReq;
+import com.cyksj.model.excel.ExcelAppleIdTemplateData;
+import com.cyksj.model.excel.listener.ExcelAppleDataListener;
+import com.cyksj.model.views.AppleIdCountryOrAreaDataView;
+import com.cyksj.model.views.AppleIdHeadDataView;
+import com.cyksj.model.views.AppleIdRegisterView;
 import com.cyksj.service.register.RegisterOrderDonService;
-import com.cyksj.web.util.StpUserUtil;
+import com.cyksj.web.util.EasyExcelUtils;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.param.Operator;
+import com.ejlchina.searcher.util.MapBuilder;
 import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
 import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import java.io.OutputStream;
-import java.util.Map;
 
 /**
  * @author chan
@@ -39,9 +44,25 @@ public class CmsRegisterController {
 
     private final HttpServletRequest request;
 
+    private final AppleAutoRegisterDataMapper appleAutoRegisterDataMapper;
+
     @GetMapping("/get")
-    public Result<SearchResult<RegisterOrderDon>> get(){
-        SearchResult<RegisterOrderDon> search = beanSearcher.search(RegisterOrderDon.class, MapUtils.flatBuilder(request.getParameterMap()).build());
+    public Result<SearchResult<RegisterOrderDon>> get(Boolean appleIsAutoType) {
+        MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
+        if (appleIsAutoType != null) {
+            if (appleIsAutoType) {
+                builder.field(RegisterOrderDon::getAppleAutoId).op(Operator.NotNull);
+            }else {
+                builder.field(RegisterOrderDon::getAppleAutoId).op(Operator.IsNull);
+            }
+        }
+        SearchResult<RegisterOrderDon> search = beanSearcher.search(RegisterOrderDon.class, builder.build());
+        search.getDataList().forEach(data->{
+            if (data.getAppleIsAutoType()) {
+                data.setCountry(data.getCountryOrArea().getDesc());
+                data.setEmail(data.getApplePwdId());
+            }
+        });
         return GatewayResponse.SUCCESS.newBuilder().toResult(search);
     }
 
@@ -51,6 +72,48 @@ public class CmsRegisterController {
         return GatewayResponse.SUCCESS.newBuilder().toResult(registerOrderDon);
     }
 
+    /**
+     * 下载apple id 导入模板
+     */
+    @GetMapping("/get/appleId/template")
+    public void appleIdTemplate(HttpServletResponse response) {
+        EasyExcelUtils.createTemplateExcel(response, ExcelAppleIdTemplateData.class, "导入模板", "导入模板", ExcelTypeEnum.XLSX, null);
+    }
+
+    /**
+     * 导入apple Id注册数据
+     */
+    @PostMapping("/export/appleId/data")
+    public Result<String> exportRegisterAppleData(MultipartFile file, String remark, String countryOrArea) throws Exception {
+        EasyExcel.read(file.getInputStream(), ExcelAppleIdTemplateData.class, new ExcelAppleDataListener(appleAutoRegisterDataMapper, countryOrArea, remark)).sheet().doRead();
+        return GatewayResponse.SUCCESS.newBuilder().toResult("导入数据成功");
+    }
 
+    /**
+     * apple ID注册数据列表
+     */
+    @GetMapping("/get/appleId/list")
+    public Result<SearchResult<AppleIdRegisterView>> getAppleIdList(HttpServletRequest request) {
+        return GatewayResponse.SUCCESS.newBuilder().toResult(beanSearcher.search(AppleIdRegisterView.class, MapUtils.flatBuilder(request.getParameterMap()).build()));
+    }
+
+    /**
+     * apple ID头部数据
+     */
+    @GetMapping("/get/appleId/head")
+    public Result<AppleIdHeadDataView> getAppleIdHeadDataView() {
+        AppleIdCountryOrAreaDataView appleIdCountryOrAreaDataView = new AppleIdCountryOrAreaDataView();
+        appleIdCountryOrAreaDataView.setJapanAvaNum(appleAutoRegisterDataMapper.selectAreaDataView(AppleAutoRegisterData.CountryOrArea.JAPAN));
+        appleIdCountryOrAreaDataView.setHongKongAvaNum(appleAutoRegisterDataMapper.selectAreaDataView(AppleAutoRegisterData.CountryOrArea.CN_HongKong));
+        appleIdCountryOrAreaDataView.setUsAvaNum(appleAutoRegisterDataMapper.selectAreaDataView(AppleAutoRegisterData.CountryOrArea.US));
+        appleIdCountryOrAreaDataView.setTaiWanAvaNum(appleAutoRegisterDataMapper.selectAreaDataView(AppleAutoRegisterData.CountryOrArea.CN_TaiWan));
+        AppleIdHeadDataView appleIdHeadDataView = new AppleIdHeadDataView();
+        appleIdHeadDataView.setAreaDataView(appleIdCountryOrAreaDataView);
+        Integer avaAppleIdNum = appleAutoRegisterDataMapper.selectCount(Wrappers.lambdaQuery(AppleAutoRegisterData.class).eq(AppleAutoRegisterData::getStatus, false));
+        appleIdHeadDataView.setAvaAppleIdNum(avaAppleIdNum);
+        Integer usedAppleIdNum = appleAutoRegisterDataMapper.selectCount(Wrappers.lambdaQuery(AppleAutoRegisterData.class).eq(AppleAutoRegisterData::getStatus, true));
+        appleIdHeadDataView.setUsedAppleIdNum(usedAppleIdNum);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(appleIdHeadDataView);
+    }
 
 }

+ 38 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/statistics/StatisticsDataController.java

@@ -1,15 +1,25 @@
 package com.cyksj.web.controller.manage.statistics;
 
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.UserMapper;
+import com.cyksj.mapper.manage.statistics.StatisticsUserDataMapper;
+import com.cyksj.model.entity.StatisticsUserData;
 import com.cyksj.model.views.BackgroundDataView;
 import com.cyksj.model.views.ExpiredAccountDataView;
+import com.cyksj.model.views.StatisticsUserDataView;
 import com.cyksj.service.mange.statistics.StatisticsDataService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 
+import javax.servlet.http.HttpServletRequest;
+
 /*
  *项目名: netflix
  *文件名: StatisticsDataController
@@ -24,6 +34,12 @@ public class StatisticsDataController {
 
 	private final StatisticsDataService statisticsDataService;
 
+	private final UserMapper userMapper;
+
+	private final BeanSearcher beanSearcher;
+
+	private final StatisticsUserDataMapper statisticsUserDataMapper;
+
 	/**
 	 * 查询统计数据
 	 */
@@ -62,4 +78,26 @@ public class StatisticsDataController {
 		}
 		return statisticsDataService.updateHandleStatus(relationId);
 	}
+
+	/**
+	 * 总用户数列表
+	 */
+	@GetMapping("/get/user/data")
+	public Result<StatisticsUserDataView> getUserData(HttpServletRequest request) {
+		StatisticsUserDataView statisticsUserDataView = new StatisticsUserDataView();
+		DateTime now = DateTime.now();
+		DateTime thisZero = DateUtil.beginOfDay(now);
+		DateTime thisEnd = DateUtil.endOfDay(now);
+		Integer wxUserNum = statisticsUserDataMapper.getWxTotalOfUser();
+		Integer pcUserNum = statisticsUserDataMapper.getPcTotalOfUser();
+		statisticsUserDataView.setTotalOfUser(wxUserNum + pcUserNum);
+		statisticsUserDataView.setNumOfUser(wxUserNum);
+		statisticsUserDataView.setPcNumOfUser(pcUserNum);
+		statisticsUserDataView.setNumOfNewUser(statisticsUserDataMapper.getNumOfNewUser(thisZero, thisEnd));
+		statisticsUserDataView.setPcNumOfNewUser(statisticsUserDataMapper.getPcNumOfNewUser(thisZero, thisEnd));
+		statisticsUserDataView.setNumOfActiveUser(statisticsUserDataMapper.getNumOfActiveUser(thisZero, thisEnd));
+		statisticsUserDataView.setPcNumOfActiveUser(statisticsUserDataMapper.getPcNumOfActiveUser(thisZero, thisEnd));
+		statisticsUserDataView.setUserData(beanSearcher.search(StatisticsUserData.class, MapUtils.flatBuilder(request.getParameterMap()).build()));
+		return GatewayResponse.SUCCESS.newBuilder().toResult(statisticsUserDataView);
+	}
 }

+ 31 - 5
netflix-web/src/main/java/com/cyksj/web/controller/register/RegisterController.java

@@ -5,16 +5,17 @@ import com.cyksj.common.util.IoKit;
 import com.cyksj.common.util.Xmls;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.AppleAutoRegisterDataMapper;
 import com.cyksj.model.dto.H5JsPayParams;
-import com.cyksj.model.dto.H5PayParams;
+import com.cyksj.model.entity.AppleAutoRegisterData;
 import com.cyksj.model.entity.RegisterOrderDon;
 import com.cyksj.model.manage.request.RegisterReq;
-import com.cyksj.redis.RedisService;
+import com.cyksj.model.views.AppleIdCountryOrAreaDataView;
 import com.cyksj.service.register.RegisterOrderDonService;
-import com.cyksj.service.register.SpotifyService;
 import com.cyksj.web.util.StpUserUtil;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.param.Operator;
 import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -42,6 +43,8 @@ public class RegisterController {
 
     private final HttpServletRequest request;
 
+    private final AppleAutoRegisterDataMapper appleAutoRegisterDataMapper;
+
     @PostMapping
     public Result<RegisterOrderDon> register(@RequestBody RegisterReq req) throws Exception {
         long userId = StpUserUtil.getLoginIdAsLong();
@@ -110,11 +113,34 @@ public class RegisterController {
     public Result<SearchResult<RegisterOrderDon>> get(){
         long userId = StpUserUtil.getLoginIdAsLong();
         SearchResult<RegisterOrderDon> search = beanSearcher.search(RegisterOrderDon.class, MapUtils.flatBuilder(request.getParameterMap())
-                .field(RegisterOrderDon::getUserId,userId)
+                .field(RegisterOrderDon::getUserId,userId).op(Operator.Equal)
                 .build());
+        search.getDataList().forEach(data->{
+            if (data.getAppleIsAutoType() && (data.getStatus() == RegisterOrderDon.Status.noPayment || data.getStatus() == RegisterOrderDon.Status.close)) {
+                data.setApplePwdId(null);
+                data.setCountryOrArea(null);
+                data.setRemark(null);
+            }
+        });
         return GatewayResponse.SUCCESS.newBuilder().toResult(search);
     }
 
+    @GetMapping("/get/appleId/area/detail")
+    public Result<AppleIdCountryOrAreaDataView> getAppleIdCountryOrAreaData() {
+        AppleIdCountryOrAreaDataView appleIdCountryOrAreaDataView = new AppleIdCountryOrAreaDataView();
+        appleIdCountryOrAreaDataView.setJapanAvaNum(appleAutoRegisterDataMapper.selectAreaDataView(AppleAutoRegisterData.CountryOrArea.JAPAN));
+        appleIdCountryOrAreaDataView.setHongKongAvaNum(appleAutoRegisterDataMapper.selectAreaDataView(AppleAutoRegisterData.CountryOrArea.CN_HongKong));
+        appleIdCountryOrAreaDataView.setUsAvaNum(appleAutoRegisterDataMapper.selectAreaDataView(AppleAutoRegisterData.CountryOrArea.US));
+        appleIdCountryOrAreaDataView.setTaiWanAvaNum(appleAutoRegisterDataMapper.selectAreaDataView(AppleAutoRegisterData.CountryOrArea.CN_TaiWan));
+        return GatewayResponse.SUCCESS.newBuilder().toResult(appleIdCountryOrAreaDataView);
+    }
 
-
+    /**
+     * 取消appleId订单
+     */
+    @PutMapping("/cancel/order/{orderId}")
+    public Result<String> cancelOrder(@PathVariable Long orderId) {
+        registerOrderDonService.updateAppleAutoStatus(orderId);
+        return GatewayResponse.SUCCESS.newBuilder().toResult("取消订单成功");
+    }
 }

+ 20 - 0
netflix-web/src/main/java/com/cyksj/web/util/EasyExcelUtils.java

@@ -129,6 +129,26 @@ public class EasyExcelUtils {
 		}
 	}
 
+	/**
+	 * 获取模板 Excel
+	 */
+	public static void createTemplateExcel(HttpServletResponse response, Class tClass, String sheetName, String fileName, ExcelTypeEnum type, String charset) {
+		final String methodName = "createTemplateExcel";
+		LOGGER.info("{},excel导出开始[end]",methodName);
+		try {
+			response.setContentType("application/x-download");
+			response.setContentType("application/vnd.ms-excel");
+			response.setCharacterEncoding("utf-8");
+			response.setHeader("Content-disposition",
+					"attachment;filename=" + new String(fileName.getBytes("utf-8"), "ISO-8859-1")+ type.getValue());
+
+			EasyExcel.write(response.getOutputStream(), tClass).sheet(sheetName).doWrite(null);
+			LOGGER.info("{},excel导出结束[end]",methodName);
+		} catch (IOException e) {
+			LOGGER.warn("{},excel导出 异常:{}",methodName,e.getMessage());
+		}
+	}
+
 
 
 	/**