Преглед изворни кода

Merge branch 'master' into dev

# Conflicts:
#	netflix-service/src/main/java/com/cyksj/redis/RedisService.java
zoujiajian пре 2 година
родитељ
комит
2055ffbe8e
100 измењених фајлова са 2196 додато и 180 уклоњено
  1. 1 1
      netflix-common/src/main/java/com/cyksj/common/constant/Constant.java
  2. 16 0
      netflix-common/src/main/java/com/cyksj/common/util/StringUtil.java
  3. 313 0
      netflix-common/src/main/java/com/cyksj/common/util/Times.java
  4. 5 0
      netflix-common/src/main/java/com/cyksj/dto/RedisKey.java
  5. 2 0
      netflix-dao/src/main/java/com/cyksj/mapper/GroupsMapper.java
  6. 1 1
      netflix-dao/src/main/java/com/cyksj/mapper/GroupsRelationMapper.java
  7. 2 0
      netflix-dao/src/main/java/com/cyksj/mapper/OrderDonMapper.java
  8. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/UserActivityMapper.java
  9. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/UserStudentCertRecordMapper.java
  10. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/corp/CorpUserPayIntentionMapper.java
  11. 3 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/coupon/CouponUserMapper.java
  12. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/shop/YhShopGoodsSkuMapper.java
  13. 4 0
      netflix-dao/src/main/java/com/cyksj/mapper/shop/YhShopMapper.java
  14. 19 0
      netflix-dao/src/main/java/com/cyksj/mapper/shop/YhShopSkuSysTakeDownRecordMapper.java
  15. 44 0
      netflix-dao/src/main/java/com/cyksj/model/dto/CuiQiuEmailDetailDto.java
  16. 38 0
      netflix-dao/src/main/java/com/cyksj/model/dto/CuiQiuEmailDto.java
  17. 31 0
      netflix-dao/src/main/java/com/cyksj/model/dto/CuiQiuEmailResultDto.java
  18. 5 0
      netflix-dao/src/main/java/com/cyksj/model/dto/YhShopInfo.java
  19. 18 0
      netflix-dao/src/main/java/com/cyksj/model/dto/YhShopSkuDownInfo.java
  20. 21 0
      netflix-dao/src/main/java/com/cyksj/model/entity/CorpUserPayIntention.java
  21. 2 1
      netflix-dao/src/main/java/com/cyksj/model/entity/CouponUser.java
  22. 5 0
      netflix-dao/src/main/java/com/cyksj/model/entity/HomeManagementConfig.java
  23. 1 1
      netflix-dao/src/main/java/com/cyksj/model/entity/OrderDonSubsidyRelate.java
  24. 66 0
      netflix-dao/src/main/java/com/cyksj/model/entity/UserActivity.java
  25. 1 1
      netflix-dao/src/main/java/com/cyksj/model/entity/UserCertRecord.java
  26. 18 0
      netflix-dao/src/main/java/com/cyksj/model/entity/UserStudentCertRecord.java
  27. 5 0
      netflix-dao/src/main/java/com/cyksj/model/entity/YhShop.java
  28. 0 6
      netflix-dao/src/main/java/com/cyksj/model/entity/YhShopDistributeWaitingSendPoints.java
  29. 36 0
      netflix-dao/src/main/java/com/cyksj/model/entity/YhShopSkuSysTakeDownRecord.java
  30. 1 1
      netflix-dao/src/main/java/com/cyksj/model/manage/views/CorpMsgAuditUserView.java
  31. 5 0
      netflix-dao/src/main/java/com/cyksj/model/request/HomeManageConfigReq.java
  32. 18 0
      netflix-dao/src/main/java/com/cyksj/model/request/MiniSchemaReq.java
  33. 76 0
      netflix-dao/src/main/java/com/cyksj/model/request/TargetAppletSchemeReq.java
  34. 27 0
      netflix-dao/src/main/java/com/cyksj/model/views/ChatgptConversionLimitView.java
  35. 1 1
      netflix-dao/src/main/java/com/cyksj/model/views/CorpUserIntentionView.java
  36. 45 0
      netflix-dao/src/main/java/com/cyksj/model/views/CouponReceiptDetailView.java
  37. 59 0
      netflix-dao/src/main/java/com/cyksj/model/views/CouponUsedDetailView.java
  38. 3 0
      netflix-dao/src/main/java/com/cyksj/model/views/CouponView.java
  39. 3 0
      netflix-dao/src/main/java/com/cyksj/model/views/HomeManagementConfigView.java
  40. 3 0
      netflix-dao/src/main/java/com/cyksj/model/views/HomeManagementFrontView.java
  41. 53 0
      netflix-dao/src/main/java/com/cyksj/model/views/UserActivityView.java
  42. 3 0
      netflix-dao/src/main/java/com/cyksj/model/views/YhShopDetailView.java
  43. 7 1
      netflix-dao/src/main/java/com/cyksj/model/views/YhShopGoodsFrontCategoryView.java
  44. 1 1
      netflix-dao/src/main/java/com/cyksj/model/views/YhShopUserDistributeOrdersDetailView.java
  45. 6 0
      netflix-dao/src/main/resources/mapper/CouponUserMapper.xml
  46. 17 11
      netflix-dao/src/main/resources/mapper/GroupRelationMapper.xml
  47. 20 0
      netflix-dao/src/main/resources/mapper/GroupsMapper.xml
  48. 12 0
      netflix-dao/src/main/resources/mapper/OrderDonMapper.xml
  49. 11 0
      netflix-dao/src/main/resources/mapper/YhShopMapper.xml
  50. 14 0
      netflix-dao/src/main/resources/mapper/YhShopSkuSysTakeDownRecordMapper.xml
  51. 22 0
      netflix-service/src/main/java/com/cyksj/config/YhCertMiniConfig.java
  52. 7 0
      netflix-service/src/main/java/com/cyksj/redis/RedisService.java
  53. 5 3
      netflix-service/src/main/java/com/cyksj/service/chatgpt/impl/ChatGptAccountServiceImpl.java
  54. 6 0
      netflix-service/src/main/java/com/cyksj/service/corp/CorpService.java
  55. 16 58
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpEventActionServiceImpl.java
  56. 12 1
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpMsgBulkTaskServiceImpl.java
  57. 18 4
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpServiceImpl.java
  58. 1 0
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpUserServiceImpl.java
  59. 1 1
      netflix-service/src/main/java/com/cyksj/service/corp/impl/WxCorpOpsImpl.java
  60. 1 1
      netflix-service/src/main/java/com/cyksj/service/exchange/impl/ExchangeCodeServiceImpl.java
  61. 15 0
      netflix-service/src/main/java/com/cyksj/service/mail/CuiQiuMailService.java
  62. 108 0
      netflix-service/src/main/java/com/cyksj/service/mail/impl/CuiQiuMailServiceImpl.java
  63. 3 0
      netflix-service/src/main/java/com/cyksj/service/mange/CmsGoodsDonSkuService.java
  64. 8 0
      netflix-service/src/main/java/com/cyksj/service/mange/RefreshCacheService.java
  65. 29 0
      netflix-service/src/main/java/com/cyksj/service/mange/goods/CmsGoodsDonSkuServiceImpl.java
  66. 2 2
      netflix-service/src/main/java/com/cyksj/service/mange/group/CmsGroupServiceImpl.java
  67. 16 1
      netflix-service/src/main/java/com/cyksj/service/mange/impl/RefreshCacheServiceImpl.java
  68. 4 0
      netflix-service/src/main/java/com/cyksj/service/mange/statistics/impl/StatisticsDataServiceImpl.java
  69. 10 0
      netflix-service/src/main/java/com/cyksj/service/mini/MiniService.java
  70. 45 2
      netflix-service/src/main/java/com/cyksj/service/mini/impl/MiniServiceImpl.java
  71. 7 1
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java
  72. 2 2
      netflix-service/src/main/java/com/cyksj/service/relation/GroupRelationFrontService.java
  73. 17 31
      netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationFrontServiceImpl.java
  74. 4 0
      netflix-service/src/main/java/com/cyksj/service/shop/YhShopGoodsSkuService.java
  75. 10 0
      netflix-service/src/main/java/com/cyksj/service/shop/impl/YhShopDistributeServiceImpl.java
  76. 24 0
      netflix-service/src/main/java/com/cyksj/service/shop/impl/YhShopGoodsSkuServiceImpl.java
  77. 1 1
      netflix-service/src/main/java/com/cyksj/service/template/impl/TemplateCommonServiceImpl.java
  78. 17 0
      netflix-service/src/main/java/com/cyksj/service/user/UserActivityService.java
  79. 3 0
      netflix-service/src/main/java/com/cyksj/service/user/UserIdentCertService.java
  80. 81 0
      netflix-service/src/main/java/com/cyksj/service/user/impl/UserActivityServiceImpl.java
  81. 1 1
      netflix-service/src/main/java/com/cyksj/service/user/impl/UserBindRelationServiceImpl.java
  82. 17 0
      netflix-service/src/main/java/com/cyksj/service/user/impl/UserIdentCertServiceImpl.java
  83. 7 0
      netflix-service/src/main/java/com/cyksj/service/wechat/WeChatService.java
  84. 69 0
      netflix-service/src/main/java/com/cyksj/service/wechat/impl/WeChatServiceImpl.java
  85. 83 0
      netflix-service/src/main/java/com/cyksj/task/CorpChatScheduler.java
  86. 31 0
      netflix-web/src/main/java/com/cyksj/web/controller/goods/GoodsDonController.java
  87. 5 2
      netflix-web/src/main/java/com/cyksj/web/controller/group/GroupRelationController.java
  88. 7 1
      netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsOrderController.java
  89. 2 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/account/CmsAccountController.java
  90. 74 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/active/UserActivityController.java
  91. 4 2
      netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/CorpMsgAuditController.java
  92. 33 4
      netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/WxCorpController.java
  93. 27 2
      netflix-web/src/main/java/com/cyksj/web/controller/manage/coupon/CouponController.java
  94. 11 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/CmsGoodsDonSkuController.java
  95. 23 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/shop/CmsYhShopGoodsController.java
  96. 37 11
      netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/shop/YhShopGoodsController.java
  97. 19 2
      netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/shop/YhShopUserController.java
  98. 40 0
      netflix-web/src/main/java/com/cyksj/web/controller/mini/MiniController.java
  99. 92 0
      netflix-web/src/main/java/com/cyksj/web/controller/mini/UserStudentCertController.java
  100. 25 21
      netflix-web/src/main/java/com/cyksj/web/controller/mirror/MirrorController.java

+ 1 - 1
netflix-common/src/main/java/com/cyksj/common/constant/Constant.java

@@ -111,7 +111,7 @@ public interface Constant {
 	 */
 	String QR_CODE_WX_APP_ID = "qr_code_wx_app_id";
 
-	String CHANGE_GROUPS_TRIPS_ACCOUNT = "您好,您购买的%s,密码已更换【银河录像局】";
+	String CHANGE_GROUPS_TRIPS_ACCOUNT = "您好,您购买的%s,车票账号:%s密码已更换【银河录像局】";
 
 	String ACCOUNT_EXPIRY_MSG_TEMPLATE = "您好,您购买的%s,还有%s到期,请登陆网站https://nf.video/及时续费。【银河录像局】";
 

+ 16 - 0
netflix-common/src/main/java/com/cyksj/common/util/StringUtil.java

@@ -11,6 +11,8 @@ import java.net.http.HttpResponse;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Random;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * @author  chan 字符串操作辅助类
@@ -555,4 +557,18 @@ public final class StringUtil {
 
 		return "unknown";
 	}
+
+	/**
+	 * 获取账号登录验证码
+	 */
+	public static String getVerifyCodePattern(String code) {
+		if (StrUtil.isNotEmpty(code)) {
+			Pattern pattern = Pattern.compile("\\d{4,}");
+			Matcher matcher = pattern.matcher(code);
+			while (matcher.find()) {
+				return matcher.group();
+			}
+		}
+		return StrUtil.EMPTY;
+	}
 }

+ 313 - 0
netflix-common/src/main/java/com/cyksj/common/util/Times.java

@@ -0,0 +1,313 @@
+package com.cyksj.common.util;
+
+import cn.hutool.core.date.DateUtil;
+
+import java.time.Duration;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
+import java.time.temporal.TemporalAdjusters;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+
+/**
+ * @author valor
+ * @date 2018/9/22 14:17
+ */
+public class Times {
+
+    /**
+     * 一天的秒数
+     */
+    public static final int second_per_day = 86400;
+    /**
+     * 一小时的毫秒数
+     */
+    public static final int millisecond_per_hour = 3600000;
+
+    /**
+     * 一个月的秒数
+     */
+    public static final int second_per_month = 259200;
+
+    /**
+     * 一分钟的毫秒数
+     */
+    public static final int millisecond_per_minute = 60000;
+
+    /**
+     * 默认时区
+     */
+//    private static final ZoneId zoneId;
+//    static {
+//        zoneId = ZoneId.of("Asia/Shanghai");
+//    }
+
+    /**
+     * 默认时区的时间偏移量
+     */
+    private static final ZoneOffset zoneOffSet;
+    static {
+        // 8小时的秒数 8 * 60 * 60
+        zoneOffSet = ZoneOffset.ofTotalSeconds(28800);
+    }
+
+    /**
+     * 时间格式化 枚举类
+     */
+    public enum Formatter {
+        DateTime(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.US)),
+        ISO_8601(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US)),
+        RFC_1123(DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US)),
+        DATAS(DateTimeFormatter.ofPattern("yyyy-MM-dd",Locale.US)),
+        DATA_YM(DateTimeFormatter.ofPattern("yyyy-MM",Locale.US)),
+        DATAS_ST(DateTimeFormatter.ofPattern("yyyy-MM-10",Locale.US)),
+        MSEC(DateTimeFormatter.ofPattern("yyyy-MM-dd HHmmssSSS",Locale.US)),
+        HOUR_MIN_SEC(DateTimeFormatter.ofPattern("HH:mm:ss",Locale.US)),
+        HOUR_MIN_SEC_MSEC(DateTimeFormatter.ofPattern("HH:mm:ss:SSS",Locale.US)),
+        YEAR_MONTH_DAY(DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss",Locale.US)),
+        DATE_YMD(DateTimeFormatter.ofPattern("yyyyMMdd",Locale.US)),
+        DATA_10H(DateTimeFormatter.ofPattern("yyyy-MM-dd 10:00:00", Locale.US)),
+        MONTH_DAY(DateTimeFormatter.ofPattern("MM/dd",Locale.US));
+
+
+        private DateTimeFormatter formatter;
+
+        Formatter(DateTimeFormatter formatter) {
+            this.formatter = formatter;
+        }
+
+        public DateTimeFormatter getFormatter() {
+            return this.formatter;
+        }
+    }
+
+    /**
+     * 不允许外部实例化
+     */
+    private Times() { }
+
+    /**
+     * 指定日期字符串 按指定格式转换成timestamp
+     */
+    public static long toTimestamp(String str, Formatter formatter) {
+        return toTimestamp(str, formatter, zoneOffSet);
+    }
+
+    /**
+     * 指定日期字符串 按指定格式转换成timestamp
+     */
+    public static long toTimestamp(String str, Formatter formatter, ZoneOffset offset) {
+        return toDateTime(str, formatter).toEpochSecond(offset) * 1000L;
+    }
+
+    /**
+     * 指定timestamp 按指定格式 格式化时间
+     */
+    public static String format(long time, Formatter formatter) {
+        return format(time, formatter, zoneOffSet);
+    }
+
+    /**
+     * 指定timestamp 按指定格式 格式化时间
+     */
+    public static String format(long time, Formatter formatter, ZoneOffset offset) {
+        return format(toDateTime(time, offset), formatter);
+    }
+
+    /**
+     * 指定LocalDateTime 按指定格式 格式化时间
+     */
+    public static String format(LocalDateTime time, Formatter formatter) {
+        return time.format(formatter.getFormatter());
+    }
+
+    /**
+     * 指定日期字符串 按指定格式转换成localDateTime
+     */
+    public static LocalDateTime toDateTime(String str, Formatter formatter) {
+        return LocalDateTime.parse(str, formatter.getFormatter());
+    }
+
+    /**
+     * 指定timestamp 转换成localDateTime
+     */
+    public static LocalDateTime toDateTime(long timestamp) {
+        return toDateTime(timestamp, zoneOffSet);
+    }
+
+    /**
+     * 指定timestamp 转换成localDateTime
+     */
+    public static LocalDateTime toDateTime(long timestamp, ZoneOffset offset) {
+        long secs = timestamp / 1000L;
+        return LocalDateTime.ofEpochSecond(secs, 0, offset);
+    }
+
+    /**
+     * 判断指定timestamp 是否是过去的时间
+     */
+    public static boolean isPast(long time) {
+        return System.currentTimeMillis() > time;
+    }
+
+    /**
+     * 判断指定timestamp 是否是未来的时间
+     */
+    public static boolean isFuture(long time) {
+        return System.currentTimeMillis() < time;
+    }
+
+    /**
+     * 判断当前timestamp 是否在某个时间段内
+     */
+    public static boolean isInTime(long start, long end) {
+        return isInTime(System.currentTimeMillis(), start, end);
+    }
+
+    /**
+     * 判断指定timestamp 是否在某个时间段内
+     */
+    public static boolean isInTime(long time, long start, long end) {
+        return start <= time && time <= end;
+    }
+
+    /**
+     * 计算两个日期相差的 毫秒数
+     */
+    public static long between(LocalDateTime one, LocalDateTime another) {
+        return Duration.between(one, another).toMillis();
+    }
+
+    /**
+     * 获取今日零时timestamp
+     */
+    public static long getZeroPoint() {
+        return getZeroPoint(0);
+    }
+
+    /**
+     * 获取今日日期 格式 yyyy-MM-dd
+     */
+    public static String getTodayStr(){
+        return format(getZeroPoint(0),Formatter.DATAS);
+    }
+
+    /**
+     * 指定与今日相差的天数 获取零时timestamp
+     */
+    public static long getZeroPoint(int days) {
+        return getZeroPoint(days, zoneOffSet);
+    }
+
+    /**
+     * 指定与今日相差的天数 获取零时timestamp
+     */
+    public static long getZeroPoint(int days, ZoneOffset zoneOffSet) {
+        return getZeroPoint(System.currentTimeMillis(), days, zoneOffSet);
+    }
+
+    /**
+     * 指定时间戳 获取零时timestamp
+     */
+    public static long getZeroPoint(long timestamp) {
+        return getZeroPoint(timestamp, 0);
+    }
+
+    /**
+     * 指定时间戳 获取零时timestamp
+     */
+    public static long getZeroPoint(long timestamp, int days) {
+        return getZeroPoint(timestamp, days, zoneOffSet);
+    }
+
+    /**
+     * 指定时间戳 获取零时timestamp
+     */
+    public static long getZeroPoint(long timestamp, int days, ZoneOffset zoneOffSet) {
+        int offset = zoneOffSet.getTotalSeconds();
+
+        long time = timestamp / 1000L + offset;
+        long point = time - time % second_per_day;
+
+        if (0 != days) {
+            point += days * second_per_day;
+        }
+
+        // 计算时 传入的时区为标准
+        return (point - offset) * 1000L;
+    }
+
+    /**
+     * 获取当前时间的10号时间戳
+     */
+    public static long getStartTime(long startTime){
+        Calendar c = Calendar.getInstance();
+        c.setTimeInMillis(startTime);
+        long l = Times.toTimestamp(Times.format(c.getTimeInMillis(),Times.Formatter.DATAS_ST) + " 00:00:00", Times.Formatter.DateTime);
+        if (c.getTimeInMillis() < l){
+            c.add(Calendar.MONTH, -1);
+            l = Times.toTimestamp(Times.format(c.getTimeInMillis(),Times.Formatter.DATAS_ST) + " 00:00:00", Times.Formatter.DateTime);
+        }
+        return l;
+    }
+    /**
+     * 获取当前时间的次月10号时间戳
+     */
+    public static long getEndTime(){
+        Calendar c = Calendar.getInstance();
+        long l = Times.toTimestamp(Times.format(c.getTimeInMillis(), Times.Formatter.DATAS_ST) + " 00:00:00", Times.Formatter.DateTime);
+        if (c.getTimeInMillis() >= l){
+            c.add(Calendar.MONTH, 1);
+            l = Times.toTimestamp(Times.format(c.getTimeInMillis(), Times.Formatter.DATAS_ST) + " 00:00:00", Times.Formatter.DateTime);
+        }
+        return l;
+    }
+
+    /**
+     * 判断选择的日期是否是本周
+     */
+    public static boolean isThisWeek(long time) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setFirstDayOfWeek(Calendar.MONDAY);
+        int currentWeek = calendar.get(Calendar.WEEK_OF_YEAR);
+        calendar.setTime(new Date(time));
+        int paramWeek = calendar.get(Calendar.WEEK_OF_YEAR);
+        return paramWeek == currentWeek;
+    }
+
+
+    /**
+     * 传入一个日期返回距今几年几天
+     * @param date
+     * @return 1年223天
+     */
+    public static String getDaysOfYear(String date) {
+        String time = "";
+        LocalDate startDate = LocalDate.parse(date);
+        startDate = startDate.plusDays(-1L);
+        LocalDate endDate = LocalDate.parse(DateUtil.format(new Date(), "yyyy-MM-dd"));
+        LocalDate startDateOfYear = startDate.with(TemporalAdjusters.firstDayOfYear());
+        LocalDate endDateOfYear = endDate.with(TemporalAdjusters.firstDayOfYear());
+        long day1 = ChronoUnit.DAYS.between(startDate, endDate);
+        long year = ChronoUnit.YEARS.between(startDate, endDate);
+        long day2 = ChronoUnit.DAYS.between(startDateOfYear, endDateOfYear);
+        if (day2 > day1) {
+            endDateOfYear = endDateOfYear.minusYears(1);
+            day2 = ChronoUnit.DAYS.between(startDateOfYear, endDateOfYear);
+        }
+        long sub = day1 - day2;
+        if (year > 0) {
+            time = year + "年";
+            if (sub > 0) {
+                time = time + sub + "天";
+            }
+        } else if (sub > 0) {
+            time = sub + "天";
+        }
+        return time;
+    }
+}

+ 5 - 0
netflix-common/src/main/java/com/cyksj/dto/RedisKey.java

@@ -62,4 +62,9 @@ public class RedisKey {
      * Telegram 电报机器人推送
      */
     public static String TELEGRAM_BOT_MSG ="telegram:bot:msg";
+
+    /**
+     * 客服下标
+     */
+    public static String SERVICE_INDEX_KEY ="service_index_key";
 }

+ 2 - 0
netflix-dao/src/main/java/com/cyksj/mapper/GroupsMapper.java

@@ -39,4 +39,6 @@ public interface GroupsMapper extends BaseMapper<GroupsTrips> {
 	Long selectMidJourneySameSpecItemGroups(@Param("groupsId") Long groupsId, @Param("skuId") Long skuId, @Param("expiryTime") Date expiryTime);
 
 	Integer countExpiredNum(Long accountId);
+
+	GroupsTrips selectTicketGroups(@Param("skuId") Long skuId, @Param("status") GroupsTrips.Status status, @Param("maxNum") Integer maxNum, @Param("ip") String ip);
 }

+ 1 - 1
netflix-dao/src/main/java/com/cyksj/mapper/GroupsRelationMapper.java

@@ -31,7 +31,7 @@ public interface GroupsRelationMapper extends BaseMapper<GroupsRelation> {
 	@Update("update groups_relation set customer_service = null where id = #{id}")
 	void updateCustomerService(Long id);
 
-	Long selectSimilarExpiredRelation(@Param("skuId") Long skuId, @Param("minExpiryTime") DateTime minExpiryTime, @Param("maxNum") Integer maxNum);
+	Long selectSimilarExpiredRelation(@Param("skuId") Long skuId, @Param("minExpiryTime") DateTime minExpiryTime, @Param("maxNum") Integer maxNum, @Param("ip") String ip);
 
 	List<GroupsRelationView> selectRelationByGoodsId(@Param("goodsId") Long goodsId, @Param("userId") Long userId, @Param("yhsId") Long yhsId);
 

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

@@ -87,4 +87,6 @@ public interface OrderDonMapper extends BaseMapper<OrderDon> {
 	UserOrderDetailView getFansToDayOrdersView(@Param("tagIdStr") String tagIdStr, @Param("date") String date);
 
 	List<Long> getPayGoodsIds(@Param("userIds") List<Long> relationUserIdList);
+
+	BigDecimal getTotalRefundAmountTime(@Param("startDate") Date startDate, @Param("endDate") Date endDate);
 }

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

@@ -0,0 +1,13 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.UserActivity;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserActivityMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/4/15 16:01
+ */
+public interface UserActivityMapper extends BaseMapper<UserActivity> {
+}

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

@@ -0,0 +1,13 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.UserStudentCertRecord;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserStudentCertRecordMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/4/18 11:15
+ */
+public interface UserStudentCertRecordMapper extends BaseMapper<UserStudentCertRecord> {
+}

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

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.corp;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.CorpUserPayIntention;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: CorpUserPayIntentionMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/5/7 17:04
+ */
+public interface CorpUserPayIntentionMapper extends BaseMapper<CorpUserPayIntention> {
+}

+ 3 - 0
netflix-dao/src/main/java/com/cyksj/mapper/manage/coupon/CouponUserMapper.java

@@ -10,6 +10,7 @@ import com.cyksj.model.views.CouponUserView;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
+import java.util.Map;
 
 /*
  *项目名: netflix
@@ -31,4 +32,6 @@ public interface CouponUserMapper extends BaseMapper<CouponUser> {
 	CouponUser getCouponByCouponUserId(Long couponUserId);
 
 	CouponUserView getCouponDetailById(@Param("userId") long userId, @Param("couponId") Long couponId);
+
+	Map<String, Long> selectCouponUserNumData(Long couponId);
 }

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

@@ -5,6 +5,10 @@ import com.cyksj.model.entity.GoodsDonSku;
 import com.cyksj.model.entity.YhShopGoodsSku;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+
+import java.math.BigDecimal;
+import java.util.List;
 
 /**
  * @author zwhui
@@ -15,4 +19,13 @@ public interface YhShopGoodsSkuMapper extends BaseMapper<YhShopGoodsSku> {
 	@Select("select sku.*,ygs.price as yhShopSkuPrice from (select user_id from yh_shop where id = #{yhsId} limit 1) ys inner join yh_shop_goods_sku ygs on ygs.user_id = ys.user_id and ygs.sku_id = #{skuId} and ygs.deleted is true and ygs.status is true" +
 			" inner join goods_don_sku sku on sku.id = ygs.sku_id")
 	GoodsDonSku selectGoodsDonSkuBySkuIdAndYhsId(@Param("yhsId") Long yhsId, @Param("skuId") Long skuId);
+
+	@Update("update yh_shop_goods_sku set status = 0 where sku_id = #{skuId} and price < #{minPrice}")
+	Integer setBelowPriceShopSkuDown(@Param("skuId") Long skuId, @Param("minPrice") BigDecimal minPrice);
+
+	@Select("select sku_id,price from yh_shop_goods_sku where yhs_id = #{yhsId} and goods_id = #{goodsId} and deleted is true and status is true order by price limit 1")
+	YhShopGoodsSku selectMinPriceSkuByYhsId(@Param("yhsId") Long yhsId, @Param("goodsId") Long goodsId);
+
+	@Select("select * from yh_shop_goods_sku where sku_id = #{skuId} and price < #{minPrice} and status = 1")
+	List<YhShopGoodsSku> getBelowPriceShopSku(@Param("skuId") Long skuId, @Param("minPrice") BigDecimal minPrice);
 }

+ 4 - 0
netflix-dao/src/main/java/com/cyksj/mapper/shop/YhShopMapper.java

@@ -1,6 +1,7 @@
 package com.cyksj.mapper.shop;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.dto.YhShopSkuDownInfo;
 import com.cyksj.model.entity.YhShop;
 import com.cyksj.model.entity.YhShopDistributeMoneyApply;
 import com.cyksj.model.views.YhShopDistributeView;
@@ -8,6 +9,7 @@ import org.apache.ibatis.annotations.Param;
 
 import java.math.BigDecimal;
 import java.util.Date;
+import java.util.List;
 import java.util.Map;
 
 /*
@@ -28,4 +30,6 @@ public interface YhShopMapper extends BaseMapper<YhShop> {
 	Map<String, Object> selectYhShopApplyMoney(@Param("startDate") Date startDate, @Param("endDate") Date endDate);
 
 	YhShopDistributeMoneyApply selectRelationBusiness(Long userId);
+
+	List<YhShopSkuDownInfo> getYhShopSkuSysStatusDownInfo(long userId);
 }

+ 19 - 0
netflix-dao/src/main/java/com/cyksj/mapper/shop/YhShopSkuSysTakeDownRecordMapper.java

@@ -0,0 +1,19 @@
+package com.cyksj.mapper.shop;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.YhShopGoodsSku;
+import com.cyksj.model.entity.YhShopSkuSysTakeDownRecord;
+import org.apache.ibatis.annotations.Param;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: YhShopSkuSysTakeDownRecordMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/4/26 14:29
+ */
+public interface YhShopSkuSysTakeDownRecordMapper extends BaseMapper<YhShopSkuSysTakeDownRecord> {
+	void batchInsert(@Param("list") List<YhShopGoodsSku> yhShopGoodsSkus, @Param("sysPrice") BigDecimal sysPrice);
+}

+ 44 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/CuiQiuEmailDetailDto.java

@@ -0,0 +1,44 @@
+package com.cyksj.model.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CuiQiuEmailDetailDto
+ * 创建者: JavaZou
+ * 创建时间:2024/4/25 16:52
+ */
+@Getter
+@Setter
+public class CuiQiuEmailDetailDto {
+	private Integer code;
+
+	private String msg;
+
+	private ResultData data;
+
+	@Getter
+	@Setter
+	public static class ResultData{
+		private Content content;
+	}
+
+	@Getter
+	@Setter
+	public static class Content {
+		private Integer id;
+
+		private String time;
+
+		private String subject;
+
+		private List<CuiQiuEmailDto.CuiQiuUser> from;
+
+		private List<CuiQiuEmailDto.CuiQiuUser> to;
+
+		private String body;
+	}
+}

+ 38 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/CuiQiuEmailDto.java

@@ -0,0 +1,38 @@
+package com.cyksj.model.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CuiQiuEmailDto
+ * 创建者: JavaZou
+ * 创建时间:2024/4/25 16:35
+ */
+
+@Getter
+@Setter
+public class CuiQiuEmailDto {
+
+	private Long id;
+
+	private String time;
+
+	private Long timestamp;
+
+	private String subject;
+
+	private List<CuiQiuUser> from;
+
+	private List<CuiQiuUser> to;
+
+	@Getter
+	@Setter
+	public static class CuiQiuUser{
+		private String name;
+
+		private String address;
+	}
+}

+ 31 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/CuiQiuEmailResultDto.java

@@ -0,0 +1,31 @@
+package com.cyksj.model.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CuiQiuEmailResultDto
+ * 创建者: JavaZou
+ * 创建时间:2024/4/25 16:42
+ */
+@Getter
+@Setter
+public class CuiQiuEmailResultDto {
+	private Integer code;
+
+	private String msg;
+
+	private ResultData data;
+
+	@Getter
+	@Setter
+	public static class ResultData {
+		private Integer total;
+
+		private List<CuiQiuEmailDto> list;
+	}
+
+}

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/YhShopInfo.java

@@ -34,5 +34,10 @@ public class YhShopInfo {
 
 	private String reason;
 
+	/**
+	 * 是否展示广告
+	 */
+	private Boolean isShowAd;
+
 	private Date createdTime;
 }

+ 18 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/YhShopSkuDownInfo.java

@@ -0,0 +1,18 @@
+package com.cyksj.model.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: YhShopSkuDownInfo
+ * 创建者: JavaZou
+ * 创建时间:2024/4/26 18:19
+ */
+@Getter
+@Setter
+public class YhShopSkuDownInfo {
+	private String title;
+
+	private String specVal;
+}

+ 21 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/CorpUserPayIntention.java

@@ -0,0 +1,21 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: CorpUserPayIntention
+ * 创建者: JavaZou
+ * 创建时间:2024/5/7 17:01
+ */
+@Getter
+@Setter
+public class CorpUserPayIntention extends BaseEntity {
+	private String unionId;
+
+	/**
+	 * 意向 0无回复 1无意向 2.问相关问题 3有意向 4很有意向
+	 */
+	private Integer intention;
+}

+ 2 - 1
netflix-dao/src/main/java/com/cyksj/model/entity/CouponUser.java

@@ -71,7 +71,8 @@ public class CouponUser extends BaseEntity {
 		channel_popularize("channel_popularize", "渠道推广"),
 		new_welfare("new_welfare", "新人福利"),
 		corp_active_code("corp_active_code", "企业微信活码"),
-		customer_link("customer_link", "获客链接")
+		customer_link("customer_link", "获客链接"),
+		student_cert("student_cert","大学生认证")
 		;
 		private String channel;
 		private String desc;

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/HomeManagementConfig.java

@@ -51,6 +51,11 @@ public class HomeManagementConfig extends BaseEntity{
 	@TableField(updateStrategy = FieldStrategy.IGNORED)
 	private AdType adType;
 
+	/**
+	 * 广告是否店铺展示 默认false
+	 */
+	private Boolean isShop;
+
 	@TableField(updateStrategy = FieldStrategy.IGNORED)
 	private RgType rgType;
 

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

@@ -11,7 +11,7 @@ import lombok.Setter;
  */
 @Getter
 @Setter
-public class OrderDonSubsidyRelate {
+public class OrderDonSubsidyRelate extends BaseEntity{
 	private Long subsidyId;
 
 	private Long orderId;

+ 66 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/UserActivity.java

@@ -0,0 +1,66 @@
+package com.cyksj.model.entity;
+
+import com.baomidou.mybatisplus.annotation.FieldStrategy;
+import com.baomidou.mybatisplus.annotation.TableField;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotEmpty;
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserActivity
+ * 创建者: JavaZou
+ * 创建时间:2024/4/15 15:44
+ * 官网用户活动表
+ */
+@Getter
+@Setter
+public class UserActivity extends BaseEntity{
+	/**
+	 * 活动名称
+	 */
+	@NotEmpty(message = "活动名称不能为空")
+	private String name;
+
+	/**
+	 * 开始时间
+	 */
+	@TableField(updateStrategy = FieldStrategy.IGNORED)
+	private Date startTime;
+
+	/**
+	 * 结束时间
+	 */
+	@TableField(updateStrategy = FieldStrategy.IGNORED)
+	private Date endTime;
+
+	/**
+	 * 备注
+	 */
+	private String remark;
+
+	/**
+	 * 优惠券ids
+	 */
+	@TableField(updateStrategy = FieldStrategy.IGNORED)
+	private String couponIds;
+
+	/**
+	 * 图片
+	 */
+	@TableField(updateStrategy = FieldStrategy.IGNORED)
+	private String img;
+
+	/**
+	 * 规则图片
+	 */
+	@TableField(updateStrategy = FieldStrategy.IGNORED)
+	private String rules;
+
+	/**
+	 * 是否删除
+	 */
+	private Boolean deleted;
+}

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

@@ -5,7 +5,7 @@ import lombok.Setter;
 
 /**
  * 项目名: yhlxj2
- * 文件名: UserCert
+ * 文件名: UserCertRecord
  * 创建者: JavaZou
  * 创建时间:2024/2/21 10:00
  */

+ 18 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/UserStudentCertRecord.java

@@ -0,0 +1,18 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserStudentCertRecord
+ * 创建者: JavaZou
+ * 创建时间:2024/4/18 11:14
+ */
+@Getter
+@Setter
+public class UserStudentCertRecord extends BaseEntity{
+	private Long userId;
+
+	private String school;
+}

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/YhShop.java

@@ -32,6 +32,11 @@ public class YhShop extends BaseEntity {
 	 */
 	private String customId;
 
+	/**
+	 * 用户是否展示广告位 默认false
+	 */
+	private Boolean isShowAd;
+
 	/**
 	 * 商务id
 	 */

+ 0 - 6
netflix-dao/src/main/java/com/cyksj/model/entity/YhShopDistributeWaitingSendPoints.java

@@ -49,12 +49,6 @@ public class YhShopDistributeWaitingSendPoints extends BaseEntity {
 
 	private Status sendStatus;
 
-	/**
-	 * 是否是特殊设备分销订单
-	 * false
-	 */
-	private Boolean isSpecialEp;
-
 	public enum Status{
 		close("店铺分销订单关闭,积分奖励不分发"),
 		success("积分发送成功"),

+ 36 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/YhShopSkuSysTakeDownRecord.java

@@ -0,0 +1,36 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: YhShopSkuSysTakeDownRecord
+ * 创建者: JavaZou
+ * 创建时间:2024/4/26 14:26
+ */
+@Getter
+@Setter
+public class YhShopSkuSysTakeDownRecord extends BaseEntity{
+	private Long yhsId;
+
+	private Long userId;
+
+	private Long goodsId;
+
+	private Long skuId;
+
+	/**
+	 * 店铺规格价格
+	 */
+	private BigDecimal shopPrice;
+
+	/**
+	 * 系统后台设置规格最低价格
+	 */
+	private BigDecimal sysPrice;
+
+	private Boolean deleted;
+}

+ 1 - 1
netflix-dao/src/main/java/com/cyksj/model/manage/views/CorpMsgAuditUserView.java

@@ -16,7 +16,7 @@ import java.util.Date;
         where = " c.id = cu.corp_user_id " +
                 "and cu.external_userid = cr.corp_user_id " +
                 "and f.userid = cr.follow_id " +
-                ":tag:",
+                ":tag: :intention:",
         groupBy = "c.name,cu.external_userid,c.avatar,c.type,c.gender,f.name,f.userid,cr.agree_status,cr.add_created_time"
 )
 public class CorpMsgAuditUserView {

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

@@ -35,6 +35,11 @@ public class HomeManageConfigReq {
 
 	private HomeManagementConfig.AdType adType;
 
+	/**
+	 * 广告是否店铺展示 默认false
+	 */
+	private Boolean isShop;
+
 	private HomeManagementConfig.RgType rgType;
 
 	private BigDecimal rgPrice;

+ 18 - 0
netflix-dao/src/main/java/com/cyksj/model/request/MiniSchemaReq.java

@@ -0,0 +1,18 @@
+package com.cyksj.model.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: MiniSchemaReq
+ * 创建者: JavaZou
+ * 创建时间:2024/5/6 16:12
+ */
+@Getter
+@Setter
+public class MiniSchemaReq {
+	private String dsCode;
+
+	private String path;
+}

+ 76 - 0
netflix-dao/src/main/java/com/cyksj/model/request/TargetAppletSchemeReq.java

@@ -0,0 +1,76 @@
+package com.cyksj.model.request;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/*
+ *项目名: yicang-server
+ *文件名: JiShanSchemeReq
+ *创建者: JavaZou
+ *创建时间:2022/8/22 13:56
+ */
+@Getter
+@Setter
+public class TargetAppletSchemeReq {
+	/**
+	 * 跳转到的目标小程序信息
+	 */
+	@JsonProperty("jump_wxa")
+	private JumpWxa jumpWxa;
+	/**
+	 * 到期失效的 scheme 码失效类型,失效时间:0,失效间隔天数:1
+	 */
+	@JsonProperty("expire_type")
+	private Long expireType;
+	/**
+	 * 到期失效的 scheme 码的失效时间,为 Unix 时间戳。
+	 * 生成的到期失效 scheme 码在该时间前有效。
+	 * 最长有效期为30天。expire_type 为 0 时必填
+	 */
+	@JsonProperty("expire_time")
+	private Long expireTime;
+	/**
+	 * 到期失效的 scheme 码的失效间隔天数。
+	 * 生成的到期失效 scheme 码在该间隔时间到达前有效。最长间隔天数为30天。
+	 * expire_type 为 1 时必填
+	 */
+	@JsonProperty("expire_interval")
+	private Long expireInterval;
+
+	/**
+	 * 默认值false。
+	 * 生成的 scheme 码类型,到期失效:true,永久有效:false。注意,
+	 * 永久有效 scheme 和有效时间超过180天的到期失效 scheme 的总数上限为10万个,
+	 */
+	@JsonProperty("is_expire")
+	private Boolean isExpired;
+
+	@Getter
+	@Setter
+	@AllArgsConstructor
+	@NoArgsConstructor
+	public static class JumpWxa {
+		/**
+		 * 通过 scheme 码进入的小程序页面路径,必须是已经发布的小程序存在的页面,不可携带 query。path 为空时会跳转小程序主页。
+		 */
+		private String path;
+		/**
+		 * 通过 scheme 码进入小程序时的 query,最大1024个字符,只支持数字,大小写英文以及部分特殊字符:`!#$&'()*+,/:;=?@-._~%``
+		 */
+		private String query;
+		/**
+		 * 要打开的小程序版本。
+		 * 正式版为"release",体验版为"trial",开发版为"develop",仅在微信外打开时生效。
+		 */
+		@JsonProperty("env_version")
+		private String envVersion;
+
+		public JumpWxa(String path, String query) {
+			this.path = path;
+			this.query = query;
+		}
+	}
+}

+ 27 - 0
netflix-dao/src/main/java/com/cyksj/model/views/ChatgptConversionLimitView.java

@@ -0,0 +1,27 @@
+package com.cyksj.model.views;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.Data;
+
+/**
+ * @author chan
+ * @date 2024/4/28 14:11
+ */
+@Data
+public class ChatgptConversionLimitView {
+
+    //"{\"detail\":{\"message\":\"您的账号已达到GPT-4的使用上限。您现在可以继续使用默认模型,或者重试在\",\"code\":\"model_cap_exceeded\",\"clears_in\":2687}}";
+
+    private Detail detail;
+
+    @JsonInclude(JsonInclude.Include.NON_NULL)
+    @Data
+    public static class Detail{
+
+        private String message;
+
+        private String code;
+
+        private Long clears_in;
+    }
+}

+ 1 - 1
netflix-dao/src/main/java/com/cyksj/model/views/CorpUserIntentionView.java

@@ -22,7 +22,7 @@ public class CorpUserIntentionView {
 	private String nickname;
 
 	/**
-	 * 意向 0无意向 1有意向 2很有意向
+	 * 意向 0无回复 1无意向 2.问相关问题 3有意向 4很有意向
 	 */
 	private Integer intention;
 

+ 45 - 0
netflix-dao/src/main/java/com/cyksj/model/views/CouponReceiptDetailView.java

@@ -0,0 +1,45 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.CouponUser;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: CouponReceiptDetailView
+ * 创建者: JavaZou
+ * 创建时间:2024/4/16 16:58
+ */
+@Getter
+@Setter
+@SearchBean(tables = "(select id,name from coupon where deleted is true :cid:) c inner join coupon_user cu on cu.coupon_id = c.id inner join user u on u.id = cu.user_id")
+public class CouponReceiptDetailView {
+
+	@DbField("cu.id")
+	private Long id;
+
+	@DbField("c.id")
+	private Long couponId;
+
+	@DbField("c.name")
+	private String name;
+
+	@DbField("u.id")
+	private Long userId;
+
+	@DbField("u.nickname")
+	private String nickname;
+
+	@DbField("cu.status")
+	private CouponUser.Status status;
+
+	@DbField("cu.created_time")
+	private Date receiptTime;
+
+	@DbField("cu.valid_end_time")
+	private Date expiryTime;
+}

+ 59 - 0
netflix-dao/src/main/java/com/cyksj/model/views/CouponUsedDetailView.java

@@ -0,0 +1,59 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: CouponUsedDetailView
+ * 创建者: JavaZou
+ * 创建时间:2024/4/16 17:05
+ */
+@Getter
+@Setter
+@SearchBean(tables = "(select id,name from coupon where deleted is true :cid:) c inner join coupon_user cu on cu.coupon_id = c.id inner join user u on u.id = cu.user_id" +
+		" inner join order_don o on o.coupon_user_id = cu.id and o.status not in ('close','noPayment','refund')" +
+		" left join goods_don g on g.id = o.goods_id" +
+		" left join goods_don_sku sku on sku.id = o.sku_id")
+public class CouponUsedDetailView {
+
+	@DbField("cu.id")
+	private Long id;
+
+	@DbField("c.id")
+	private Long couponId;
+
+	@DbField("c.name")
+	private String name;
+
+	@DbField("u.id")
+	private Long userId;
+
+	@DbField("u.nickname")
+	private String nickname;
+
+	@DbField("o.order_no")
+	private String orderNo;
+
+	@DbField("cu.created_time")
+	private Date receiptTime;
+
+	@DbField("sku.id")
+	private Long skuId;
+
+	@DbField("sku.spec_val")
+	private String specVal;
+
+	@DbField("g.id")
+	private Long goodsId;
+
+	@DbField("g.title")
+	private String goodsName;
+
+	@DbField("o.created_time")
+	private Date usedTime;
+}

+ 3 - 0
netflix-dao/src/main/java/com/cyksj/model/views/CouponView.java

@@ -124,6 +124,9 @@ public class CouponView {
 	@DbIgnore
 	private Integer usedNum;
 
+	@DbIgnore
+	private Integer receiptNum;
+
 	/**
 	 * 发放状态
 	 */

+ 3 - 0
netflix-dao/src/main/java/com/cyksj/model/views/HomeManagementConfigView.java

@@ -48,6 +48,9 @@ public class HomeManagementConfigView {
 	@DbField("hc.ad_type")
 	private HomeManagementConfig.AdType adType;
 
+	@DbField("hc.is_shop")
+	private Boolean isShop;
+
 	@DbField("hc.rg_type")
 	private HomeManagementConfig.AdType rgType;
 

+ 3 - 0
netflix-dao/src/main/java/com/cyksj/model/views/HomeManagementFrontView.java

@@ -54,6 +54,9 @@ public class HomeManagementFrontView {
 	@DbField("hc.ad_type")
 	private HomeManagementConfig.AdType adType;
 
+	@DbField("hc.is_shop")
+	private Boolean isShop;
+
 	@DbField("hc.rg_type")
 	private HomeManagementConfig.RgType rgType;
 

+ 53 - 0
netflix-dao/src/main/java/com/cyksj/model/views/UserActivityView.java

@@ -0,0 +1,53 @@
+package com.cyksj.model.views;
+
+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.util.Date;
+import java.util.List;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserActivityView
+ * 创建者: JavaZou
+ * 创建时间:2024/4/16 15:43
+ */
+@Getter
+@Setter
+@SearchBean(tables = "user_activity ua",
+		where = "ua.deleted is true")
+public class UserActivityView {
+
+	@DbField("ua.id")
+	private Long id;
+
+	/**
+	 * 活动名称
+	 */
+	@DbField("ua.name")
+	private String name;
+
+	@DbField("ua.start_time")
+	private Date startTime;
+
+	@DbField("ua.end_time")
+	private Date endTime;
+
+	/**
+	 * 优惠券ids
+	 */
+	@DbField("ua.coupon_ids")
+	private String couponIds;
+
+	@DbField("ua.img")
+	private String img;
+
+	@DbField("ua.rules")
+	private String rules;
+
+	@DbIgnore
+	private List<CouponView> couponViews;
+}

+ 3 - 0
netflix-dao/src/main/java/com/cyksj/model/views/YhShopDetailView.java

@@ -38,6 +38,9 @@ public class YhShopDetailView {
 	@DbField("ys.custom_id")
 	private String customId;
 
+	@DbField("ys.is_show_ad")
+	private Boolean isShowAd;
+
 	/**
 	 * 是否审核通过
 	 */

+ 7 - 1
netflix-dao/src/main/java/com/cyksj/model/views/YhShopGoodsFrontCategoryView.java

@@ -75,7 +75,13 @@ public class YhShopGoodsFrontCategoryView {
 	/**
 	 * 店铺最低规格价格
 	 */
-	@DbField("yg.price")
+	@DbIgnore
+	private Long skuId;
+
+	/**
+	 * 店铺最低规格价格
+	 */
+	@DbIgnore
 	private BigDecimal price;
 
 	/**

+ 1 - 1
netflix-dao/src/main/java/com/cyksj/model/views/YhShopUserDistributeOrdersDetailView.java

@@ -43,7 +43,7 @@ public class YhShopUserDistributeOrdersDetailView {
 	@DbField("TRUNCATE(dp.money/100,2)")
 	private BigDecimal reMoney = BigDecimal.ZERO;
 
-	@DbField("if(send_status = 'success',TRUNCATE(dp.money/100,2),0)")
+	@DbField("if(send_status = 'success',TRUNCATE(dp.refund_money/100,2),0)")
 	private BigDecimal rdMoney;
 
 	@DbField("dp.send_status")

+ 6 - 0
netflix-dao/src/main/resources/mapper/CouponUserMapper.xml

@@ -233,4 +233,10 @@
                 and coupon_id = #{couponId} limit 1) cu
                  inner join coupon c on c.id = cu.coupon_id
     </select>
+
+    <select id="selectCouponUserNumData" resultType="java.util.Map">
+        select count(if(status = 'used', 1, NULL)) usedNum, count(*) receiptNum
+        from coupon_user
+        where coupon_id = #{couponId}
+    </select>
 </mapper>

+ 17 - 11
netflix-dao/src/main/resources/mapper/GroupRelationMapper.xml

@@ -12,7 +12,6 @@
         user_id = #{entity.userId},
         account = null,
         customer_service = null,
-        verify_code = null,
         password = null,
         recharge_status = null,
         send_time = null,
@@ -49,17 +48,24 @@
     <select id="selectSimilarExpiredRelation" resultType="java.lang.Long">
         select s.id
         from (select gt.id, min(gr.expiry_time) minExpiryTime
-              from `groups_trips` gt
-                       left join `groups_relation` gr on gr.groups_id = gt.id
-              where gt.sku_id = #{skuId}
-                and (gt.available_parking_num = 0 or (select count(*) from groups_relation gr where gr.groups_id = gt.id and gr.user_id != 0 and gr.num &lt;= #{maxNum}) &lt; gt.available_parking_num)
-                and gt.available_num > 0
-                and gt.status = 'validity'
-                and gr.status = 'validity'
-                and gr.user_id != 0
-              and gr.expiry_time is not null
-              group by gr.groups_id) s
+        from `groups_trips` gt
+        left join `groups_relation` gr on gr.groups_id = gt.id
+        where gt.sku_id = #{skuId}
+        and (gt.available_parking_num = 0 or (select count(*)
+        from groups_relation gr
+        where gr.groups_id = gt.id and gr.user_id != 0 and gr.num &lt;=
+        #{maxNum}) &lt; gt.available_parking_num) and gt.available_num > 0
+        and gt.status = 'validity'
+        and gr.status = 'validity'
+        and gr.user_id != 0
+        and gr.expiry_time is not null
+        group by gr.groups_id) s
         where s.minExpiryTime >= #{minExpiryTime}
+        <if test="ip != null">
+            and not exists (select 1 from (select id, user_id from groups_relation gnr where gnr.groups_id = s.id and gnr.user_id != 0) gr inner join
+            order_don o on o.user_id = gr.user_id and o.relation_id = gr.id
+            inner join order_don_location_relate ocr on ocr.order_id = o.id where ocr.ip = #{ip} limit 1)
+        </if>
         order by minExpiryTime desc limit 1
     </select>
 

+ 20 - 0
netflix-dao/src/main/resources/mapper/GroupsMapper.xml

@@ -78,4 +78,24 @@
           and deleted is true
           and source = 'self'
     </select>
+
+    <select id="selectTicketGroups" resultType="com.cyksj.model.entity.GroupsTrips">
+        select *
+        from groups_trips gt
+        where gt.sku_id = #{skuId}
+        and gt.status = #{status}
+        and gt.available_num > 0
+        <if test="ip != null">
+            and not exists (select 1 from (select id, user_id from groups_relation gnr where gnr.groups_id = gt.id
+            and gnr.user_id != 0) gr inner join
+            order_don o on o.user_id = gr.user_id and o.relation_id = gr.id
+            inner join order_don_location_relate ocr on ocr.order_id = o.id where ocr.ip = #{ip} limit 1)
+        </if>
+        and (available_parking_num = 0 or available_parking_num > (select count(*)
+        from groups_relation gr
+        where gr.groups_id = gt.id
+        and gr.user_id != 0 and gr.num &lt;= #{maxNum}))
+        order by available_num asc
+        limit 1
+    </select>
 </mapper>

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

@@ -495,4 +495,16 @@
             #{item}
         </foreach>
     </select>
+
+    <select id="getTotalRefundAmountTime" resultType="java.math.BigDecimal">
+        select cast(ifnull(sum(refund_fee),0)/100 as decimal(11,2))
+        from refund_order_don
+        where (refund_method != 'balance' or is_clear_balance = 1)
+        <if test="startDate != null">
+            and created_time >= #{startDate}
+        </if>
+        <if test="endDate != null">
+            and created_time &lt; #{endDate}
+        </if>
+    </select>
 </mapper>

+ 11 - 0
netflix-dao/src/main/resources/mapper/YhShopMapper.xml

@@ -61,4 +61,15 @@
         from (select * from yh_shop where user_id = #{userId} limit 1) ys
                  left join cms_user cu on cu.id = ys.business_id
     </select>
+
+    <select id="getYhShopSkuSysStatusDownInfo" resultType="com.cyksj.model.dto.YhShopSkuDownInfo">
+        select any_value(g.title) as title, group_concat(distinct sku.spec_val SEPARATOR '') as specVal
+        from (select goods_id, sku_id
+              from yh_shop_sku_sys_take_down_record
+              where user_id = #{userId}
+                and deleted is true) s
+                 inner join goods_don_sku sku on sku.id = s.sku_id
+                 inner join goods_don g on g.id = s.goods_id
+        group by g.id
+    </select>
 </mapper>

+ 14 - 0
netflix-dao/src/main/resources/mapper/YhShopSkuSysTakeDownRecordMapper.xml

@@ -0,0 +1,14 @@
+<?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.cyksj.mapper.shop.YhShopSkuSysTakeDownRecordMapper">
+
+
+    <insert id="batchInsert">
+        insert into
+        yh_shop_sku_sys_take_down_record(`yhs_id`,`user_id`,`goods_id`,`sku_id`,`shop_price`,`sys_price`,`created_time`,`update_time`)
+        values
+        <foreach collection="list" item="item" separator=",">
+            (#{item.yhsId},#{item.userId},#{item.goodsId},#{item.skuId},#{item.price},#{sysPrice},now(),now())
+        </foreach>
+    </insert>
+</mapper>

+ 22 - 0
netflix-service/src/main/java/com/cyksj/config/YhCertMiniConfig.java

@@ -0,0 +1,22 @@
+package com.cyksj.config;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: CertMiniConfig
+ * 创建者: JavaZou
+ * 创建时间:2024/4/16 12:00
+ */
+@Configuration
+@ConfigurationProperties(prefix = "certmini")
+@Getter
+@Setter
+public class YhCertMiniConfig {
+	private String appId;
+
+	private String secret;
+}

+ 7 - 0
netflix-service/src/main/java/com/cyksj/redis/RedisService.java

@@ -809,6 +809,13 @@ public class RedisService {
         USER_DISTRIBUTE_ADD_KEY("user_distribute_add_key:%s", "分销用户新增key", 30l),
 
         CORP_CUSTOMER_ACQUISTION_CLICKID("corp:customer:post:%s","巨量投放,获客链接 跳转存储点击id",60*60*24),
+
+        CORP_CUSTOMER_ACQUISTION_START_CHAT("corp:customer:post:start_chat","获客链接 发起回话存储点击id",60*60*24),
+
+        CORP_CUSTOMER_ACQUISTION_START_CHAT_COUNT("corp:customer:post:start_chat:count:%s","获客链接 发起回话回传计数",60*60*24),
+
+        CORP_CUSTOMER_ACQUISTION_START_CHAT_SET("corp:customer:post:start_chat_set","获客链接 发起回话待回传set",60*60*24),
+
         //获客链接 到企业微信内将平台标识与unionId 对应
         CORP_CUSTOMER_ACQUISTION_UNIONID_CLICKID("corp:customer:unionId:%s","unionid 对应的clickId",60*60*24),
 

+ 5 - 3
netflix-service/src/main/java/com/cyksj/service/chatgpt/impl/ChatGptAccountServiceImpl.java

@@ -254,7 +254,9 @@ public class ChatGptAccountServiceImpl implements ChatGptAccountService {
     public String getCarLoginUrlWithToken(String userToken, String carId) {
         ChatgptUser chatgptUser = getCarChatGptUserWithToken(userToken);
         if (chatgptUser != null) {
-            return CAR_GPT_DOMAIN + "/auth/logintoken?carid=" + carId + "&usertoken=" + chatgptUser.getUserToken();
+            String DOMAIN = "https://chat.galaxydvd.com";
+            log.info("domain:{},渠道用户:{},在{}获取跳转GPT镜像的登录url", DOMAIN, userToken, DateTime.now());
+            return DOMAIN + "/auth/logintoken?carid=" + carId + "&usertoken=" + chatgptUser.getUserToken();
         } else {
             throw BusinessRuntimeException.getInstance("服务出了点问题");
         }
@@ -642,7 +644,7 @@ public class ChatGptAccountServiceImpl implements ChatGptAccountService {
                 .map((historyView) -> {
                     ChatgptCarInfoView chatgptCarInfoView = buildChatgptCarInfoView(historyView.getCarId(), historyView.getCarName(), historyView.getIsPLus(), redisService.zScore(RedisService.key.CHATGPT_CAR_SCORES.getName(), historyView.getCarId()));
                     chatgptCarInfoView.setIsHistory(true);
-                    chatgptCarInfoView.setScore(Math.min(redisService.zScore(RedisService.key.CHATGPT_CAR_SCORES.getName(), historyView.getCarId()), 100));
+                    chatgptCarInfoView.setScore(Math.min(redisService.zScore(RedisService.key.CHATGPT_CAR_SCORES.getName(), historyView.getCarId()), 200));
 
                     return chatgptCarInfoView;
                 }).collect(Collectors.toCollection(LinkedHashSet::new));
@@ -740,7 +742,7 @@ public class ChatGptAccountServiceImpl implements ChatGptAccountService {
         ChatgptCarInfoView view = new ChatgptCarInfoView();
         view.setCarId(carId);
         // 假设以下方法从Redis或其他服务获取数据
-        view.setScore(Math.min(score, 100));
+        view.setScore(Math.min(score, 200));
         view.setStatus(score >= 50 ? "繁忙" : "空闲"); // 或“繁忙”
 
         view.setType(isPlus == 1 ? "plus" : "3.5");

+ 6 - 0
netflix-service/src/main/java/com/cyksj/service/corp/CorpService.java

@@ -3,6 +3,7 @@ package com.cyksj.service.corp;
 import com.cyksj.dto.CorpOauth2UserInfo;
 import com.cyksj.model.entity.CorpCustomerAcquistionCallback;
 import com.cyksj.model.entity.CorpFollow;
+import com.cyksj.model.entity.CorpUserPayIntention;
 import com.cyksj.model.request.corp.Attachments;
 
 /*
@@ -50,4 +51,9 @@ public interface CorpService {
 	 */
 	void upCallbackIntention(CorpCustomerAcquistionCallback corpCustomerAcquistionCallback);
 
+	/**
+	 * 修改用户购买意愿
+	 * @param corpUserPayIntention
+	 */
+	void updateUserIntention(CorpUserPayIntention corpUserPayIntention);
 }

+ 16 - 58
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpEventActionServiceImpl.java

@@ -575,69 +575,21 @@ public class CorpEventActionServiceImpl implements CorpEventActionService {
 		//外部联系人id
 		String externalUserId = message.getExternalUserId();
 		log.info("监听微信客户:{}发起会话事件", externalUserId);
-		try {
-			//等待3s
-			Thread.sleep(3000);
-		} catch (InterruptedException e) {
-		}
+
 		//获客链接id
 		String linkId = message.getLinkId();
-		CorpUserAuth corpUserAuth = corpUserAuthMapper.selectOne(Wrappers.lambdaQuery(CorpUserAuth.class)
-				.eq(CorpUserAuth::getExternalUserid, externalUserId).last("limit 1"));
-		String unionId = null;
-		if (corpUserAuth != null) {
-			CorpUser corpUser = corpUserMapper.selectById(corpUserAuth.getCorpUserId());
-			if (corpUser != null) {
-				unionId = corpUser.getUnionid();
+		CorpCustomerAcquisitionLink corpCustomerAcquisitionLink = corpCustomerAcquisitionLinkMapper.selectOne(Wrappers.lambdaQuery(CorpCustomerAcquisitionLink.class).eq(CorpCustomerAcquisitionLink::getLinkId, linkId));
+
+		if(corpCustomerAcquisitionLink != null){
+			//记录发起对话事件
+			CorpCustomerAcquisitionLinkPopularize corpCustomerAcquisitionLinkPopularize = corpCustomerAcquisitionLinkPopularizeMapper.selectOne(Wrappers.lambdaQuery(CorpCustomerAcquisitionLinkPopularize.class)
+					.eq(CorpCustomerAcquisitionLinkPopularize::getIsChat, 1)
+					.eq(CorpCustomerAcquisitionLinkPopularize::getCustomerAcquistionLinkId, corpCustomerAcquisitionLink.getId()).last("limit 1"));
+			if (corpCustomerAcquisitionLinkPopularize != null) {
+				redisService.sSet(RedisService.key.CORP_CUSTOMER_ACQUISTION_START_CHAT_SET.getEnvName(), externalUserId);
 			}
 		}
-		if (StrUtil.isEmpty(unionId)) {
-			return null;
-		}
-		CorpCustomerAcquisitionLinkPopularize corpCustomerAcquisitionLinkPopularize = corpCustomerAcquisitionLinkPopularizeMapper.selectOne(Wrappers.lambdaQuery(CorpCustomerAcquisitionLinkPopularize.class)
-				.eq(CorpCustomerAcquisitionLinkPopularize::getIsChat, 1)
-				.eq(CorpCustomerAcquisitionLinkPopularize::getCustomerAcquistionLinkId, linkId).last("limit 1"));
-		if (corpCustomerAcquisitionLinkPopularize != null) {
-			//callback
-			String callback = null;
-			String params = redisService.getStr(String.format(RedisService.key.CORP_CUSTOMER_ACQUISTION_UNIONID_CLICKID.getName(), unionId));
-			if (StringUtils.isNotBlank(params)) {
-				JSONObject paramsObj = JSONUtil.parseObj(params);
-				callback = paramsObj.getStr("callback");
-			}
-			//如果需要延后主动回传的做持久化.
-			if (StrUtil.isNotBlank(callback)) {
-				log.info("开始回传客户:{}发起会话事件", externalUserId);
-				//如果为加粉则直接回传
-				if (corpCustomerAcquisitionLinkPopularize.getType() == 1) {
-					//如果需要延后主动回传的做持久化.
-					if (!corpCustomerAcquisitionLinkPopularize.getDelayedPost()) {
-						postData(callback, corpCustomerAcquisitionLinkPopularize.getEvent());
-					}
-				} else {
-					//深度转化 前置加粉事件回传.
-					if (StringUtils.isNotBlank(corpCustomerAcquisitionLinkPopularize.getAddEvent())) {
-						postData(callback, corpCustomerAcquisitionLinkPopularize.getAddEvent());
-					}
-				}
-				// 是否延后回传都记录,只看是否直接回传.
-				CorpCustomerAcquistionCallback corpCustomerAcquistionCallback =
-						corpCustomerAcquistionCallbackMapper.selectOne(Wrappers.lambdaQuery(CorpCustomerAcquistionCallback.class).eq(CorpCustomerAcquistionCallback::getCallback, callback).eq(CorpCustomerAcquistionCallback::getUnionId, unionId));
-				if (corpCustomerAcquistionCallback == null) {
-					corpCustomerAcquistionCallback = new CorpCustomerAcquistionCallback();
-				}
-				corpCustomerAcquistionCallback.setCallback(callback);
-				corpCustomerAcquistionCallback.setEvent(corpCustomerAcquisitionLinkPopularize.getEvent());
-				corpCustomerAcquistionCallback.setUnionId(unionId);
-				corpCustomerAcquistionCallback.setStatus(!corpCustomerAcquisitionLinkPopularize.getDelayedPost());
-				if (corpCustomerAcquistionCallback.getId() != null) {
-					corpCustomerAcquistionCallbackMapper.updateById(corpCustomerAcquistionCallback);
-				} else {
-					corpCustomerAcquistionCallbackMapper.insert(corpCustomerAcquistionCallback);
-				}
 
-			}
-		}
 		return null;
 	}
 
@@ -1229,6 +1181,12 @@ public class CorpEventActionServiceImpl implements CorpEventActionService {
 							corpCustomerAcquistionCallbackMapper.insert(corpCustomerAcquistionCallback);
 						}
 					}
+
+					//是否为对话 回传
+					if (corpCustomerAcquisitionLinkPopularize.getIsChat()) {
+						jsonObject.putOpt("event", corpCustomerAcquisitionLinkPopularize.getAddEvent());
+						redisService.hset(RedisService.key.CORP_CUSTOMER_ACQUISTION_START_CHAT.getEnvName(), unionId, jsonObject.toString(), RedisService.key.CORP_CUSTOMER_ACQUISTION_START_CHAT.getTimeout());
+					}
 				}
 			}
 		}

+ 12 - 1
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpMsgBulkTaskServiceImpl.java

@@ -93,6 +93,8 @@ public class CorpMsgBulkTaskServiceImpl extends ServiceImpl<CorpMsgBulkTaskMappe
 		if (corpMsgBulkTask.getWxCorpId() == null) corpMsgBulkTask.setWxCorpId(2l);
 		if (CollUtil.isNotEmpty(corpMsgBulkTask.getAttachments())) {
 			corpMsgBulkTask.setAttachmentsStr(Jsons.toJson(corpMsgBulkTask.getAttachments()));
+		} else {
+			corpMsgBulkTask.setAttachmentsStr(null);
 		}
 		setCorn(corpMsgBulkTask);
 		if (corpMsgBulkTask.getId() != null) {
@@ -247,7 +249,10 @@ public class CorpMsgBulkTaskServiceImpl extends ServiceImpl<CorpMsgBulkTaskMappe
 		//获取对应标签的客户
 		WxCorpApp wxCorpApp = wxCorpAppMapper.selectById(corpMsgBulkTask.getWxCorpId());
 		Assert.notNull(wxCorpApp, "企业微信未配置");
-		List<String> tagIds = Jsons.parseList(corpMsgBulkTask.getChooseTagStr(), String.class);
+		List<String> tagIds = null;
+		if (StrUtil.isNotBlank(corpMsgBulkTask.getChooseTagStr())) {
+			tagIds = Jsons.parseList(corpMsgBulkTask.getChooseTagStr(), String.class);
+		}
 		//客服集合
 		List<String> service_follow_ids = null;
 		SysConfig serviceConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
@@ -458,6 +463,12 @@ public class CorpMsgBulkTaskServiceImpl extends ServiceImpl<CorpMsgBulkTaskMappe
 		List<CorpMsgBulkTaskTagRelation> relations = corpMsgBulkTaskTagRelationMapper.selectList(Wrappers.lambdaQuery(CorpMsgBulkTaskTagRelation.class)
 				.eq(CorpMsgBulkTaskTagRelation::getTaskId, taskId));
 		String chooseTagStr = corpMsgBulkTask.getChooseTagStr();
+		if (corpMsgBulkTask.getSendScope() == 2 && StrUtil.isEmpty(chooseTagStr)) {
+			throw BusinessRuntimeException.getInstance("请选择对应的标签");
+		}
+		if (StrUtil.isEmpty(chooseTagStr)) {
+			return;
+		}
 		List<String> corpTagIds = Jsons.parseList(chooseTagStr, String.class);
 		if (CollUtil.isNotEmpty(relations)) {
 			//清除删除的关系

+ 18 - 4
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpServiceImpl.java

@@ -15,11 +15,9 @@ import com.cyksj.config.corp.YHLXWxCorpConfig;
 import com.cyksj.dto.CorpOauth2UserInfo;
 import com.cyksj.mapper.corp.CorpCustomerAcquistionCallbackMapper;
 import com.cyksj.mapper.corp.CorpFollowMapper;
+import com.cyksj.mapper.corp.CorpUserPayIntentionMapper;
 import com.cyksj.model.dto.WxCorpEncryptDto;
-import com.cyksj.model.entity.CorpCustomerAcquistionCallback;
-import com.cyksj.model.entity.CorpFollow;
-import com.cyksj.model.entity.OrderDonPost;
-import com.cyksj.model.entity.WxCorpApp;
+import com.cyksj.model.entity.*;
 import com.cyksj.model.request.corp.Attachments;
 import com.cyksj.model.request.corp.CorpXmlMessage;
 import com.cyksj.model.request.corp.CorpXmlOutMessage;
@@ -36,6 +34,7 @@ import com.cyksj.util.WxCorpUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DuplicateKeyException;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -80,6 +79,9 @@ public class CorpServiceImpl implements CorpService {
 	@Autowired
 	private CorpCustomerAcquistionCallbackMapper corpCustomerAcquistionCallbackMapper;
 
+	@Autowired
+	private CorpUserPayIntentionMapper corpUserPayIntentionMapper;
+
 	@PostConstruct
 	private void init() {
 		corpMessageRouter = new CorpMessageRouter(this)
@@ -372,4 +374,16 @@ public class CorpServiceImpl implements CorpService {
 	public void upCallbackIntention(CorpCustomerAcquistionCallback corpCustomerAcquistionCallback) {
 		corpCustomerAcquistionCallbackMapper.update(null, Wrappers.lambdaUpdate(CorpCustomerAcquistionCallback.class).eq(CorpCustomerAcquistionCallback::getId, corpCustomerAcquistionCallback.getId()).set(CorpCustomerAcquistionCallback::getIntention, corpCustomerAcquistionCallback.getIntention()));
 	}
+
+	@Override
+	public void updateUserIntention(CorpUserPayIntention corpUserPayIntention) {
+		if (corpUserPayIntention.getId() == null) {
+			try {
+				corpUserPayIntentionMapper.insert(corpUserPayIntention);
+			} catch (DuplicateKeyException e) {
+			}
+			return;
+		}
+		corpUserPayIntentionMapper.updateById(corpUserPayIntention);
+	}
 }

+ 1 - 0
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpUserServiceImpl.java

@@ -111,6 +111,7 @@ public class CorpUserServiceImpl implements CorpUserService {
 			view.setTicketViews(tkCollect);
 			List<CorpWxOrderDonView> orderDonViews = beanSearcher.searchAll(CorpWxOrderDonView.class, MapUtils.builder()
 					.field(CorpWxOrderDonView::getUserId, userIdList).op(Operator.InList)
+					.orderBy(CorpWxOrderDonView::getId).desc()
 					.build());
 			view.setOrderDonViews(orderDonViews);
 		}

+ 1 - 1
netflix-service/src/main/java/com/cyksj/service/corp/impl/WxCorpOpsImpl.java

@@ -540,7 +540,7 @@ public class WxCorpOpsImpl implements WxCorpOps {
 		String accessToken = getAccessToken(corpId);
 		String url = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/add_msg_template?access_token=" + accessToken;
 		log.info("发送的内容为: {}",Jsons.toJson(msgTemplate));
-		log.info("企业微信群发消息 corpId:{}, sender:{},userCount:{}",corpId,msgTemplate.getSender(),msgTemplate.getExternalUserid().size());
+		log.info("企业微信群发消息 corpId:{},userCount:{}", corpId, msgTemplate.getExternalUserid().size());
 		HttpResponse<String> res =
 				J11HttpC.custom()
 						.ofPost()

+ 1 - 1
netflix-service/src/main/java/com/cyksj/service/exchange/impl/ExchangeCodeServiceImpl.java

@@ -367,7 +367,7 @@ public class ExchangeCodeServiceImpl extends ServiceImpl<ExchangeCodeMapper, Exc
 
 	public GroupsRelation getFinalRelation(GoodsDonSku sku, Long userId, Integer retryNum, Long yhsId, List<Long> errorsRelationIds) {
 		//获取车票车位
-		GroupsRelation relation = groupRelationFrontService.getRelation(null, userId, sku);
+		GroupsRelation relation = groupRelationFrontService.getRelation(null, userId, sku, null);
 
 		try {
 			//锁定座位

+ 15 - 0
netflix-service/src/main/java/com/cyksj/service/mail/CuiQiuMailService.java

@@ -0,0 +1,15 @@
+package com.cyksj.service.mail;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CuiQiuMailService
+ * 创建者: JavaZou
+ * 创建时间:2024/4/25 15:55
+ */
+public interface CuiQiuMailService {
+
+	/**
+	 * 获取最新邮箱 返回验证码
+	 */
+	String getVerifyCode(String email) throws Exception;
+}

+ 108 - 0
netflix-service/src/main/java/com/cyksj/service/mail/impl/CuiQiuMailServiceImpl.java

@@ -0,0 +1,108 @@
+package com.cyksj.service.mail.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
+import cn.hutool.http.HttpUtil;
+import com.cyksj.common.util.Jsons;
+import com.cyksj.common.util.StringUtil;
+import com.cyksj.model.dto.CuiQiuEmailDetailDto;
+import com.cyksj.model.dto.CuiQiuEmailDto;
+import com.cyksj.model.dto.CuiQiuEmailResultDto;
+import com.cyksj.service.mail.CuiQiuMailService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CuiQiuMailServiceImpl
+ * 创建者: JavaZou
+ * 创建时间:2024/4/25 15:57
+ */
+@Service
+@Slf4j
+public class CuiQiuMailServiceImpl implements CuiQiuMailService {
+	private final static String CUI_QIU_TOKEN = "4ff0341ebf1747cd89a2d1a5a296b68b";
+
+	//脆球域名id
+	private final static String DOMAIN_ID = "1696913058045050661";
+
+	//代收管理员邮件id
+	private final static String ADMIN_MAIL_ID = "1696913058063659217";
+
+	//PS 验证码官方
+	private final static String PS_ADOBE = "Adobe";
+
+	@Override
+	public String getVerifyCode(String email) throws Exception {
+		//获取近二十封邮件
+		String url = "https://domain-open-api.cuiqiu.com/v1/message/list";
+
+		Map<String, Object> params = new HashMap<>();
+
+		//获取近五分钟的代收邮件
+		//维度是天
+		DateTime now = DateTime.now();
+		params.put("token", CUI_QIU_TOKEN);
+		params.put("mail_id", ADMIN_MAIL_ID);
+		params.put("start_time", DateUtil.offsetDay(now, -1).toDateStr());
+		params.put("end_time", DateUtil.offsetDay(now, 1).toDateStr());
+		params.put("limit", 20);
+
+		HttpRequest post = HttpUtil.createPost(url);
+		post.form(params);
+		HttpResponse execute = post.execute();
+		CuiQiuEmailResultDto resultDto = Jsons.parseObject(execute.body(), CuiQiuEmailResultDto.class);
+		List<CuiQiuEmailDto> list = resultDto.getData().getList();
+		//获取邮箱对应的邮件
+		list = list.stream().filter(emailInfo -> {
+			CuiQiuEmailDto.CuiQiuUser from = emailInfo.getFrom().get(0);
+			CuiQiuEmailDto.CuiQiuUser cuiQiuUser = emailInfo.getTo().get(0);
+			if (StrUtil.equals(from.getName(), PS_ADOBE) && StrUtil.equals(cuiQiuUser.getAddress(), email)) {
+				return true;
+			}
+			return false;
+		}).collect(Collectors.toList());
+
+		if (CollUtil.isNotEmpty(list)) {
+			for (CuiQiuEmailDto cuiQiuEmailDto : list) {
+				Long messageId = cuiQiuEmailDto.getId();
+				try {
+					String code = getVerifyCodeByEmail(messageId);
+					if (StrUtil.isNotBlank(code)) {
+						return code;
+					}
+				} catch (Exception e) {
+				}
+			}
+		}
+		return null;
+	}
+
+	public String getVerifyCodeByEmail(Long messageId) throws Exception {
+		String url = "https://domain-open-api.cuiqiu.com/v1/message/detail";
+		Map<String, Object> params = new HashMap<>();
+		params.put("token", CUI_QIU_TOKEN);
+		params.put("mail_id", ADMIN_MAIL_ID);
+		params.put("message_id", messageId);
+		HttpRequest post = HttpUtil.createPost(url);
+		post.form(params);
+		HttpResponse execute = post.execute();
+		String body = execute.body();
+		CuiQiuEmailDetailDto cuiQiuEmailDetailDto = Jsons.parseObject(body, CuiQiuEmailDetailDto.class);
+		CuiQiuEmailDetailDto.Content content = cuiQiuEmailDetailDto.getData().getContent();
+
+		String contentBody = content.getBody();
+
+		String code = StrUtil.subWithLength(contentBody, contentBody.indexOf("ADOBE"), 215);
+		return StringUtil.getVerifyCodePattern(code);
+	}
+}

+ 3 - 0
netflix-service/src/main/java/com/cyksj/service/mange/CmsGoodsDonSkuService.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import com.cyksj.model.entity.GoodsDiscountPlusPurchaseRelation;
 import com.cyksj.model.entity.GoodsDonSku;
 
+import java.math.BigDecimal;
 import java.util.List;
 
 /**
@@ -14,4 +15,6 @@ public interface CmsGoodsDonSkuService extends IService<GoodsDonSku> {
 	void handleDiscountPurchaseGoods(GoodsDonSku sku, List<GoodsDiscountPlusPurchaseRelation> discountPlusPurchaseGoods);
 
 	void updateMirrorCarUserNum(GoodsDonSku sku);
+
+	void setBelowPriceShopSkuDown(Long skuId, BigDecimal newPrice);
 }

+ 8 - 0
netflix-service/src/main/java/com/cyksj/service/mange/RefreshCacheService.java

@@ -22,4 +22,12 @@ public interface RefreshCacheService {
 	 * 清除补贴商品缓存
 	 */
 	void refreshGoodsSkuSubsidyPageCache();
+
+	void refreshShopUserIdCacheByYshId(Long yhsId);
+
+
+	/**
+	 * 清除用户店铺缓存
+	 */
+	void refreshUserShopMangeCache(String customId);
 }

+ 29 - 0
netflix-service/src/main/java/com/cyksj/service/mange/goods/CmsGoodsDonSkuServiceImpl.java

@@ -8,8 +8,13 @@ import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.mapper.ChatgptUserMapper;
 import com.cyksj.mapper.GoodsDiscountPlusPurchaseRelationMapper;
 import com.cyksj.mapper.GoodsDonSkuMapper;
+import com.cyksj.mapper.shop.YhShopGoodsRateMapper;
+import com.cyksj.mapper.shop.YhShopGoodsSkuMapper;
+import com.cyksj.mapper.shop.YhShopSkuSysTakeDownRecordMapper;
 import com.cyksj.model.entity.GoodsDiscountPlusPurchaseRelation;
 import com.cyksj.model.entity.GoodsDonSku;
+import com.cyksj.model.entity.YhShopGoodsRate;
+import com.cyksj.model.entity.YhShopGoodsSku;
 import com.cyksj.service.mange.CmsGoodsDonSkuService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -36,6 +41,12 @@ public class CmsGoodsDonSkuServiceImpl extends ServiceImpl<GoodsDonSkuMapper,Goo
 
 	private final ChatgptUserMapper chatgptUserMapper;
 
+	private final YhShopGoodsRateMapper yhShopGoodsRateMapper;
+
+	private final YhShopGoodsSkuMapper yhShopGoodsSkuMapper;
+
+	private final YhShopSkuSysTakeDownRecordMapper yhShopSkuSysTakeDownRecordMapper;
+
 	@Override
 	public void handleDiscountPurchaseGoods(GoodsDonSku sku, List<GoodsDiscountPlusPurchaseRelation> discountPlusPurchaseGoods) {
 		Long skuId = sku.getId();
@@ -115,6 +126,24 @@ public class CmsGoodsDonSkuServiceImpl extends ServiceImpl<GoodsDonSkuMapper,Goo
 		}
 	}
 
+	@Override
+	public void setBelowPriceShopSkuDown(Long skuId, BigDecimal newPrice) {
+		YhShopGoodsRate yhShopGoodsRate = yhShopGoodsRateMapper.selectOne(Wrappers.lambdaQuery(YhShopGoodsRate.class)
+				.eq(YhShopGoodsRate::getSkuId, skuId)
+				.last("limit 1"));
+		if (yhShopGoodsRate != null) {
+			BigDecimal oriDiscount = BigDecimal.valueOf(100).subtract(BigDecimal.valueOf(yhShopGoodsRate.getRate()));
+			BigDecimal minPrice = newPrice.multiply(oriDiscount.divide(BigDecimal.valueOf(100)));
+			//记录那些店铺规格被下架
+			List<YhShopGoodsSku> yhShopGoodsSkus = yhShopGoodsSkuMapper.getBelowPriceShopSku(skuId, minPrice);
+			if (CollUtil.isNotEmpty(yhShopGoodsSkus)) {
+				yhShopSkuSysTakeDownRecordMapper.batchInsert(yhShopGoodsSkus, minPrice);
+				Integer update = yhShopGoodsSkuMapper.setBelowPriceShopSkuDown(skuId, minPrice);
+				log.info("变更skuId:{}规格价格,店铺数量:{}低于价格:{}下架", skuId, update, minPrice);
+			}
+		}
+	}
+
 	public void checkPurchaseParamsAndSaveOrUpdate(Long goodsId, Long skuId, GoodsDiscountPlusPurchaseRelation discountGoods) {
 		Long disSid = discountGoods.getDisSid();
 		if (disSid == null) {

+ 2 - 2
netflix-service/src/main/java/com/cyksj/service/mange/group/CmsGroupServiceImpl.java

@@ -250,7 +250,7 @@ public class CmsGroupServiceImpl extends ServiceImpl<GroupsMapper,GroupsTrips> i
             }
             if (relation.getUserId() != 0 && isPrdEnv && relation.getYhsId() == 0) {
                 //发送短信
-                smsService.sendSmsToRelationUser(relation.getUserId(), Constant.CHANGE_GROUPS_TRIPS_ACCOUNT, title);
+                smsService.sendSmsToRelationUser(relation.getUserId(), Constant.CHANGE_GROUPS_TRIPS_ACCOUNT, title, account.getAccount());
             }
             if (verifyCodeList != null && verifyCodeList.size() > 0 && i < verifyCodeList.size()) {
                 relation.setVerifyCode(verifyCodeList.get(i));
@@ -462,7 +462,7 @@ public class CmsGroupServiceImpl extends ServiceImpl<GroupsMapper,GroupsTrips> i
             }
             if (relation.getUserId() != 0 && isPrd && relation.getYhsId() == 0) {
                 try {
-                    smsService.sendSmsToRelationUser(relation.getUserId(), Constant.CHANGE_GROUPS_TRIPS_ACCOUNT, title);
+                    smsService.sendSmsToRelationUser(relation.getUserId(), Constant.CHANGE_GROUPS_TRIPS_ACCOUNT, title, account);
                 } catch (Exception e) {
                 }
             }

+ 16 - 1
netflix-service/src/main/java/com/cyksj/service/mange/impl/RefreshCacheServiceImpl.java

@@ -20,14 +20,16 @@ public class RefreshCacheServiceImpl implements RefreshCacheService {
 
 	@Override
 	public void refreshYhHomePageCache() {
-		Set<String> keys = redisService.keys(RedisService.key.YH_HOME_PAGHE_CACHE.getEnvName() + "*");
+		Set<String> keys = redisService.keys(RedisService.key.YH_HOME_PAGHE_CACHE.getName() + "*");
 		redisService.del(keys.toArray(String[]::new));
 	}
 
 	@Override
 	public void refreshYhHomeCategoryPageCache() {
 		Set<String> keys = redisService.keys(RedisService.key.YH_HOME_PAGHE_CACHE.getEnvName() + "category" + "*");
+		Set<String> shoKeys = redisService.keys(RedisService.key.YH_HOME_PAGHE_CACHE_SHOP.getEnvName() + "category" + "*");
 		redisService.del(keys.toArray(String[]::new));
+		redisService.del(shoKeys.toArray(String[]::new));
 	}
 
 	@Override
@@ -35,4 +37,17 @@ public class RefreshCacheServiceImpl implements RefreshCacheService {
 		Set<String> keys = redisService.keys(RedisService.key.YH_HOME_PAGHE_CACHE.getEnvName() + "subsidy" + "*");
 		redisService.del(keys.toArray(String[]::new));
 	}
+
+	@Override
+	public void refreshShopUserIdCacheByYshId(Long yhsId) {
+		String yhShopCacheKey = RedisService.key.YH_HOME_PAGHE_CACHE_SHOP.getEnvName() + yhsId + "*";
+		Set<String> keys = redisService.keys(yhShopCacheKey);
+		redisService.del(keys.toArray(String[]::new));
+	}
+
+	@Override
+	public void refreshUserShopMangeCache(String customId) {
+		Set<String> keys = redisService.keys(RedisService.key.YH_HOME_PAGHE_CACHE_SHOP.getEnvName() + customId + "*");
+		redisService.del(keys.toArray(String[]::new));
+	}
 }

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

@@ -1013,6 +1013,10 @@ public class StatisticsDataServiceImpl implements StatisticsDataService {
 
 	private BackgroundDataView getHeaderData(Date startDate, Date endDate) {
 		BackgroundDataView backgroundDataView = orderDonMapper.getBackgroundDataView(startDate, endDate, Constant.noOrderStatus);
+		if (startDate != null || endDate != null) {
+			BigDecimal totalRefundMoney = orderDonMapper.getTotalRefundAmountTime(startDate, endDate);
+			backgroundDataView.setTotalRefundAmount(totalRefundMoney);
+		}
 		//近5天将要到期的主账号总数
 		DateTime now = DateTime.now();
 		DateTime zero = DateUtil.beginOfDay(now);

+ 10 - 0
netflix-service/src/main/java/com/cyksj/service/mini/MiniService.java

@@ -3,6 +3,7 @@ package com.cyksj.service.mini;
 import com.cyksj.dto.Result;
 import com.cyksj.model.entity.User;
 import com.cyksj.model.request.MiniArticleReq;
+import com.cyksj.model.request.MiniSchemaReq;
 import com.cyksj.model.views.ArticleDetailView;
 
 /*
@@ -19,4 +20,13 @@ public interface MiniService {
 	Result<String> markArticle(MiniArticleReq miniArticleReq);
 
 	ArticleDetailView getArticleDetailView(Long articleId, Long userId);
+
+	void getStudentIdentity(User user, String code) throws Exception;
+
+	/**
+	 * 生成小程序schema
+	 */
+	String generateSchema(MiniSchemaReq req) throws Exception;
+
+	byte[] generateCode(MiniSchemaReq req) throws Exception;
 }

+ 45 - 2
netflix-service/src/main/java/com/cyksj/service/mini/impl/MiniServiceImpl.java

@@ -1,8 +1,11 @@
 package com.cyksj.service.mini.impl;
 
 import cn.hutool.core.util.RandomUtil;
+import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.util.Times;
+import com.cyksj.config.YhCertMiniConfig;
 import com.cyksj.config.YhMiniConfig;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
@@ -14,6 +17,8 @@ import com.cyksj.model.entity.Article;
 import com.cyksj.model.entity.ArticleUserMark;
 import com.cyksj.model.entity.User;
 import com.cyksj.model.request.MiniArticleReq;
+import com.cyksj.model.request.MiniSchemaReq;
+import com.cyksj.model.request.TargetAppletSchemeReq;
 import com.cyksj.model.views.ArticleDetailView;
 import com.cyksj.model.wechat.MiniURLLink;
 import com.cyksj.redis.RedisService;
@@ -41,14 +46,16 @@ public class MiniServiceImpl implements MiniService {
 
 	private final YhMiniConfig yhMiniConfig;
 
-	private final RedisService redisService;
-
 	private final UserMapper userMapper;
 
 	private final ArticleUserMarkMapper articleUserMarkMapper;
 
 	private final ArticleMapper articleMapper;
 
+	private final YhCertMiniConfig certMiniConfig;
+
+	private final RedisService redisService;
+
 	@Override
 	public String getMiniURLLink(String path, String query) throws Exception {
 		MiniURLLink miniURLLink = new MiniURLLink();
@@ -153,6 +160,42 @@ public class MiniServiceImpl implements MiniService {
 		return detailView;
 	}
 
+	@Override
+	public void getStudentIdentity(User user, String code) throws Exception {
+		weChatService.getMiniStudentIdentity(user.getOpenId(), code);
+	}
+
+	@Override
+	public String generateSchema(MiniSchemaReq req) throws Exception {
+		//跳转路径
+		req.setPath("pages/index/index");
+		String query = StrUtil.EMPTY;
+		if (StrUtil.isNotBlank(req.getDsCode())) {
+			query = "dsCode=" + req.getDsCode();
+		}
+		//调用微信小程序接口
+		String accessToken = weChatService.getAccessToken(certMiniConfig.getAppId());
+		TargetAppletSchemeReq targetAppletSchemeReq = new TargetAppletSchemeReq();
+		targetAppletSchemeReq.setExpireType(0l);
+		targetAppletSchemeReq.setExpireTime((System.currentTimeMillis() / 1000) + Times.second_per_day);
+		targetAppletSchemeReq.setIsExpired(false);
+		TargetAppletSchemeReq.JumpWxa jumpWxa = new TargetAppletSchemeReq.JumpWxa(req.getPath(), query);
+		targetAppletSchemeReq.setJumpWxa(jumpWxa);
+		String miniSchema = weChatService.generateSchema(accessToken, targetAppletSchemeReq);
+		return miniSchema;
+	}
+
+	@Override
+	public byte[] generateCode(MiniSchemaReq req) throws Exception {
+		req.setPath("pages/index/index");
+		//调用微信小程序接口
+		if (StrUtil.isNotBlank(req.getDsCode())) {
+			req.setPath(req.getPath() + "?dsCode=" + req.getDsCode());
+		}
+		String accessToken = weChatService.getAccessToken(certMiniConfig.getAppId());
+		return weChatService.generateCode(accessToken, req.getPath());
+	}
+
 	public void updateArticleMarkNum(Integer type, Long articleId, Integer offset) {
 		Integer success = 0;
 		while (success != 1) {

+ 7 - 1
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java

@@ -2035,8 +2035,13 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 	public GroupsRelation getRelation(OrderPayRequest payRequest, GoodsDonSku sku, Long yhsId) {
 		Long payRelationId = payRequest.getRelationId();
 		Long userId = payRequest.getUserId();
+		String ip = null;
+		//MJ车票统一ip不允许上同一车次
+		if (sku.getGoodsId() == 26) {
+			ip = payRequest.getIp();
+		}
 		//获取车票车位
-		GroupsRelation relation = groupRelationFrontService.getRelation(payRelationId, userId, sku);
+		GroupsRelation relation = groupRelationFrontService.getRelation(payRelationId, userId, sku, ip);
 
 		//锁定座位
 		setRelation(relation);
@@ -2771,6 +2776,7 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		String outNo = orderRefundService.centerRefund(orderRefundReq, orderDon);
 
 		orderDon.setStatus(OrderDon.Status.refund);
+		orderDon.setRefundMoney(orderRefundReq.getRefundMoney());
 		orderDonMapper.updateById(orderDon);
 
 		clearUserLockingRelation(groupsRelationMapper.selectById(orderDon.getRelationId()), orderDon);

+ 2 - 2
netflix-service/src/main/java/com/cyksj/service/relation/GroupRelationFrontService.java

@@ -21,7 +21,7 @@ public interface GroupRelationFrontService {
 
 	Boolean isJoinCorpWx(Long userId, Boolean isJoin, Boolean noCoupon);
 
-	GroupsRelation getSimilarExpiredGroupRelation(GoodsDonSku sku, List<Long> errorsRelationIds);
+	GroupsRelation getSimilarExpiredGroupRelation(GoodsDonSku sku, List<Long> errorsRelationIds, String ip);
 
 	Page<UserRecommendGoodsFrontView> getRecommendGoodsViews(Boolean isPayNf, List<Long> filter_goods_id, Integer start, Integer limit);
 
@@ -33,7 +33,7 @@ public interface GroupRelationFrontService {
 	/**
 	 * 获取车票座位
 	 */
-	GroupsRelation getRelation(Long payRelationId, Long userId, GoodsDonSku sku);
+	GroupsRelation getRelation(Long payRelationId, Long userId, GoodsDonSku sku, String ip);
 
 	/**
 	 * 获取车票账号登录 验证码

+ 17 - 31
netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationFrontServiceImpl.java

@@ -15,6 +15,7 @@ import com.cyksj.common.constant.Constant;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
 import com.cyksj.common.util.Jsons;
+import com.cyksj.common.util.StringUtil;
 import com.cyksj.enums.GatewayApiCode;
 import com.cyksj.mapper.*;
 import com.cyksj.mapper.sys.SysEmailMapper;
@@ -24,6 +25,7 @@ import com.cyksj.model.views.*;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.chatgpt.ChatGptAuthService;
 import com.cyksj.service.groups.GroupsFuncService;
+import com.cyksj.service.mail.CuiQiuMailService;
 import com.cyksj.service.mail.MailService;
 import com.cyksj.service.mange.coupon.CouponCommonService;
 import com.cyksj.service.relation.GroupRelationFrontService;
@@ -42,8 +44,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 import javax.servlet.http.HttpServletRequest;
 import java.util.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 import static com.cyksj.enums.GatewayApiCode.GROUP_INDEX_ALREADY_BE_USER;
 import static com.cyksj.enums.GatewayApiCode.GROUP_INDEX_NOT_FIND;
@@ -98,7 +98,10 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 
 	private final UserLoginRecordService userLoginRecordService;
 
-	private final static String VERIFY_CODE_SECRET = "q1w2e3";
+	private final CuiQiuMailService cuiQiuMailService;
+
+	//脆球邮箱后缀
+	private final static String CUI_QIU_EMAIL_SUFFIX = "@kindvd.com";
 
 	@Override
 	public SearchResult<RenewalView> getMyTicket(long userId, Boolean isLoginPopularize, String customId, String account) {
@@ -265,7 +268,7 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 	}
 
 	@Override
-	public GroupsRelation getSimilarExpiredGroupRelation(GoodsDonSku sku, List<Long> errorsRelationIds) {
+	public GroupsRelation getSimilarExpiredGroupRelation(GoodsDonSku sku, List<Long> errorsRelationIds, String ip) {
 		Long skuId = sku.getId();
 		Integer days = sku.getDays();
 		Integer months = sku.getMonths();
@@ -282,7 +285,7 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 		}
 		maxNum += extraNum;
 		DateTime minExpiryTime = DateUtil.offsetDay(expiryTime, -5);
-		Long groupsId = groupsRelationMapper.selectSimilarExpiredRelation(skuId, minExpiryTime, maxNum);
+		Long groupsId = groupsRelationMapper.selectSimilarExpiredRelation(skuId, minExpiryTime, maxNum, ip);
 		if (groupsId == null) {
 			log.info("暂无相似过期时间车队");
 			return null;
@@ -343,7 +346,7 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 	}
 
 	@Override
-	public GroupsRelation getRelation(Long payRelationId, Long userId, GoodsDonSku sku) {
+	public GroupsRelation getRelation(Long payRelationId, Long userId, GoodsDonSku sku, String ip) {
 		GroupsRelation relation = null;
 		Integer maxNum = sku.getNum();
 		if (payRelationId != null && payRelationId > 0) {
@@ -394,23 +397,14 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 			}
 			if (groups == null) {
 				//寻找差不多过期时间规格的车位
-				relation = getSimilarExpiredGroupRelation(sku,null);
+				relation = getSimilarExpiredGroupRelation(sku, null, ip);
 				if (relation == null) {
 					//TODO 如果没指定座位,等待逻辑确认
-					groups = groupsMapper.selectOne(Wrappers.lambdaQuery(GroupsTrips.class)
-							.eq(GroupsTrips::getSkuId, sku.getId())
-							.gt(GroupsTrips::getAvailableNum, 0).last("limit 1")
-							.apply(String.format("(available_parking_num = 0 or available_parking_num > (select count(*) from groups_relation gr where gr.groups_id = groups_trips.id and gr.user_id != 0 and gr.num <= %s))", maxNum))
-							.eq(GroupsTrips::getStatus, GroupsTrips.Status.validity)
-							.orderByAsc(GroupsTrips::getAvailableNum));
+					groups = groupsMapper.selectTicketGroups(sku.getId(), GroupsTrips.Status.validity, maxNum, ip);
+
 					if (groups == null) {
 						//待发车
-						groups = groupsMapper.selectOne(Wrappers.lambdaQuery(GroupsTrips.class)
-								.eq(GroupsTrips::getSkuId, sku.getId())
-								.gt(GroupsTrips::getAvailableNum, 0).last("limit 1")
-								.eq(GroupsTrips::getStatus, GroupsTrips.Status.waiting)
-								.apply(String.format("(available_parking_num = 0 or available_parking_num > (select count(*) from groups_relation gr where gr.groups_id = groups_trips.id and gr.user_id != 0 and gr.num <= %s))", maxNum))
-								.orderByAsc(GroupsTrips::getAvailableNum));
+						groups = groupsMapper.selectTicketGroups(sku.getId(), GroupsTrips.Status.waiting, maxNum, ip);
 					}
 					//新增空车队
 					if (groups == null) {
@@ -454,6 +448,9 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 		if (StrUtil.hasEmpty(account, password)) {
 			throw BusinessRuntimeException.getInstance("您的车票账号密码异常,请联系客服...");
 		}
+		if (renewalView.getGoodsId() == 33l && renewalView.getAccount().contains(CUI_QIU_EMAIL_SUFFIX)) {
+			return cuiQiuMailService.getVerifyCode(renewalView.getAccount());
+		}
 		//获取邮箱密码
 		SysEmail sysEmail = sysEmailMapper.selectOne(Wrappers.lambdaQuery(SysEmail.class)
 				.eq(SysEmail::getEmail, account)
@@ -647,22 +644,11 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 		if (goodsId == 33l) {
 			code = StrUtil.subWithLength(body, body.indexOf("ADOBE"), 215);
 		}
-		code = getVerifyCode(code);
+		code = StringUtil.getVerifyCodePattern(code);
 		if (!Validator.isNumber(code)) {
 			log.error("获取账号验证码失败:{}", StrUtil.subSufByLength(code, 512));
 			throw BusinessRuntimeException.getInstance("获取验证码失败,请重新获取..");
 		}
 		return code.trim();
 	}
-
-	public String getVerifyCode(String code) {
-		if (StrUtil.isNotEmpty(code)) {
-			Pattern pattern = Pattern.compile("\\d{4,}");
-			Matcher matcher = pattern.matcher(code);
-			while (matcher.find()) {
-				return matcher.group();
-			}
-		}
-		return StrUtil.EMPTY;
-	}
 }

+ 4 - 0
netflix-service/src/main/java/com/cyksj/service/shop/YhShopGoodsSkuService.java

@@ -1,6 +1,7 @@
 package com.cyksj.service.shop;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.dto.YhShopSkuDownInfo;
 import com.cyksj.model.entity.YhShopGoodsSku;
 
 import java.util.List;
@@ -13,4 +14,7 @@ public interface YhShopGoodsSkuService extends IService<YhShopGoodsSku> {
     void saveGoods(List<Long> goodsIds, Long userId);
 
 
+	List<YhShopSkuDownInfo> yhShopSkuSysStatusDownInfo(long userId);
+
+	void deleteSkuDownInfo(long userId);
 }

+ 10 - 0
netflix-service/src/main/java/com/cyksj/service/shop/impl/YhShopDistributeServiceImpl.java

@@ -3,6 +3,7 @@ package com.cyksj.service.shop.impl;
 import cn.hutool.core.date.DateUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.mapper.GoodsDonMapper;
+import com.cyksj.mapper.manage.distribute.UserDistributeSharedMapper;
 import com.cyksj.mapper.shop.*;
 import com.cyksj.model.entity.*;
 import com.cyksj.service.distribute.UserBusinessFrontService;
@@ -38,6 +39,8 @@ public class YhShopDistributeServiceImpl implements YhShopDistributeService {
 	private final UserBenefitsService userBenefitsService;
 
 	private final GoodsDonMapper goodsDonMapper;
+
+	private final UserDistributeSharedMapper userDistributeSharedMapper;
 	@Override
 	public void distributeWaitingSendPointsRecord(OrderDon order) {
 		BigDecimal orderMoney = order.getMoney();
@@ -171,6 +174,13 @@ public class YhShopDistributeServiceImpl implements YhShopDistributeService {
 			yhShopUserDistributeShared.setShopUserId(shopUserId);
 			yhShopUserDistributeShared.setUserId(userId);
 			yhShopUserDistributeSharedMapper.insert(yhShopUserDistributeShared);
+
+			//同步用户邀请关联 待优化 TODO
+			UserDistributeShared userDistributeShared = new UserDistributeShared();
+			userDistributeShared.setUserId(userId);
+			userDistributeShared.setSharedId(shopUserId);
+			userDistributeShared.setRemark("小店同步");
+			userDistributeSharedMapper.insert(userDistributeShared);
 		} catch (DuplicateKeyException e) {
 		}
 	}

+ 24 - 0
netflix-service/src/main/java/com/cyksj/service/shop/impl/YhShopGoodsSkuServiceImpl.java

@@ -6,8 +6,11 @@ import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.mapper.GoodsDonSkuMapper;
 import com.cyksj.mapper.shop.YhShopGoodsSkuMapper;
 import com.cyksj.mapper.shop.YhShopMapper;
+import com.cyksj.mapper.shop.YhShopSkuSysTakeDownRecordMapper;
+import com.cyksj.model.dto.YhShopSkuDownInfo;
 import com.cyksj.model.entity.YhShop;
 import com.cyksj.model.entity.YhShopGoodsSku;
+import com.cyksj.model.entity.YhShopSkuSysTakeDownRecord;
 import com.cyksj.service.shop.YhShopGoodsSkuService;
 import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
@@ -25,6 +28,8 @@ public class YhShopGoodsSkuServiceImpl extends ServiceImpl<YhShopGoodsSkuMapper,
     private final GoodsDonSkuMapper goodsDonSkuMapper;
 
     private final YhShopMapper yhShopMapper;
+
+    private final YhShopSkuSysTakeDownRecordMapper yhShopSkuSysTakeDownRecordMapper;
     @Override
     public void saveGoods(List<Long> goodsIds, Long userId) {
         YhShop yhShop = yhShopMapper.selectOne(Wrappers.lambdaQuery(YhShop.class)
@@ -39,4 +44,23 @@ public class YhShopGoodsSkuServiceImpl extends ServiceImpl<YhShopGoodsSkuMapper,
         });
         this.saveOrUpdateBatch(skuShops);
     }
+
+    @Override
+    public List<YhShopSkuDownInfo> yhShopSkuSysStatusDownInfo(long userId) {
+        List<YhShopSkuDownInfo> infos = yhShopMapper.getYhShopSkuSysStatusDownInfo(userId);
+        return infos;
+    }
+
+    @Override
+    public void deleteSkuDownInfo(long userId) {
+        Integer selectCount = yhShopSkuSysTakeDownRecordMapper.selectCount(Wrappers.lambdaQuery(YhShopSkuSysTakeDownRecord.class)
+                .eq(YhShopSkuSysTakeDownRecord::getUserId, userId)
+                .eq(YhShopSkuSysTakeDownRecord::getDeleted, 1));
+        if (selectCount > 0) {
+            yhShopSkuSysTakeDownRecordMapper.update(null, Wrappers.lambdaUpdate(YhShopSkuSysTakeDownRecord.class)
+                    .set(YhShopSkuSysTakeDownRecord::getDeleted, 0)
+                    .eq(YhShopSkuSysTakeDownRecord::getUserId, userId)
+                    .eq(YhShopSkuSysTakeDownRecord::getDeleted, 1));
+        }
+    }
 }

+ 1 - 1
netflix-service/src/main/java/com/cyksj/service/template/impl/TemplateCommonServiceImpl.java

@@ -239,7 +239,7 @@ public class TemplateCommonServiceImpl implements TemplateCommonService {
 				return;
 			}
 			if (relation.getUserId() != 0 && relation.getYhsId() == 0 && isPrd) {
-				String msg = String.format(Constant.CHANGE_GROUPS_TRIPS_ACCOUNT, title);
+				String msg = String.format(Constant.CHANGE_GROUPS_TRIPS_ACCOUNT, title, account.getAccount());
 				smsService.sendSmsToRelationUser(relation.getUserId(), msg);
 			}
 		}

+ 17 - 0
netflix-service/src/main/java/com/cyksj/service/user/UserActivityService.java

@@ -0,0 +1,17 @@
+package com.cyksj.service.user;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.entity.User;
+import com.cyksj.model.entity.UserActivity;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserActivityService
+ * 创建者: JavaZou
+ * 创建时间:2024/4/16 12:16
+ */
+public interface UserActivityService extends IService<UserActivity> {
+	void sendStudentCertActivity(User user, String dsCode, String school) throws Exception;
+
+	void saveOrUpdateActivity(UserActivity userActivity) throws Exception;
+}

+ 3 - 0
netflix-service/src/main/java/com/cyksj/service/user/UserIdentCertService.java

@@ -2,6 +2,7 @@ package com.cyksj.service.user;
 
 import com.cyksj.model.dto.UserWxIndentDto;
 import com.cyksj.model.entity.UserCertRecord;
+import com.cyksj.model.entity.UserStudentCertRecord;
 import com.cyksj.model.request.UserIndentCertReq;
 import com.cyksj.model.response.WxCertAuthTokenResp;
 
@@ -21,4 +22,6 @@ public interface UserIdentCertService {
 	Boolean checkCertRecord(long userId);
 
 	UserCertRecord getUserCertRecord(long userId);
+
+	UserStudentCertRecord getUserStudentCertRecord(long userId);
 }

+ 81 - 0
netflix-service/src/main/java/com/cyksj/service/user/impl/UserActivityServiceImpl.java

@@ -0,0 +1,81 @@
+package com.cyksj.service.user.impl;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.common.util.Jsons;
+import com.cyksj.mapper.UserActivityMapper;
+import com.cyksj.mapper.UserMapper;
+import com.cyksj.mapper.UserStudentCertRecordMapper;
+import com.cyksj.model.entity.CouponUser;
+import com.cyksj.model.entity.User;
+import com.cyksj.model.entity.UserActivity;
+import com.cyksj.model.entity.UserStudentCertRecord;
+import com.cyksj.service.mange.coupon.CouponCommonService;
+import com.cyksj.service.user.UserActivityService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserActivityServiceImpl
+ * 创建者: JavaZou
+ * 创建时间:2024/4/16 12:16
+ */
+@Service
+@RequiredArgsConstructor
+@Slf4j
+public class UserActivityServiceImpl extends ServiceImpl<UserActivityMapper, UserActivity> implements UserActivityService {
+	private final CouponCommonService couponCommonService;
+
+	private final UserMapper userMapper;
+
+	private final UserStudentCertRecordMapper userStudentCertRecordMapper;
+	@Override
+	public void sendStudentCertActivity(User user, String dsCode, String school) throws Exception {
+		UserActivity activity = getById(1);
+		Long sendUserId = user.getId();
+		if (StrUtil.isNotBlank(dsCode)) {
+			log.info("用户code:{}进行大学生身份认证成功..", dsCode);
+			User toUser = userMapper.selectOne(Wrappers.lambdaQuery(User.class).eq(User::getShowId, dsCode).last("limit 1"));
+			if (toUser != null) {
+				sendUserId = toUser.getId();
+			}
+		}
+		if (StrUtil.isNotBlank(activity.getCouponIds())) {
+			//发送优惠券
+			List<Long> couponIds = Jsons.parseList(activity.getCouponIds(), Long.class);
+			log.info("uid:{}大学生认证成功,发放优惠券:{}", user.getId(), couponIds);
+			for (Long couponId : couponIds) {
+				couponCommonService.sendCouponToUser(sendUserId, couponId, 0l, 0l, 0l, CouponUser.Channel.student_cert);
+			}
+		}
+		try {
+			UserStudentCertRecord record = new UserStudentCertRecord();
+			//记录发送用户
+			record.setUserId(sendUserId);
+			record.setSchool(school);
+			userStudentCertRecordMapper.insert(record);
+		} catch (DuplicateKeyException e) {
+		}
+	}
+
+	@Override
+	public void saveOrUpdateActivity(UserActivity userActivity) throws Exception {
+		checkActivity(userActivity);
+		saveOrUpdate(userActivity);
+	}
+
+
+	public void checkActivity(UserActivity userActivity) throws Exception {
+		String couponIds = userActivity.getCouponIds();
+		if (StrUtil.isNotBlank(couponIds)) {
+			List<Long> couponidsList = Jsons.parseList(couponIds, Long.class);
+			userActivity.setCouponIds(Jsons.toJson(couponidsList));
+		}
+	}
+}

+ 1 - 1
netflix-service/src/main/java/com/cyksj/service/user/impl/UserBindRelationServiceImpl.java

@@ -38,7 +38,7 @@ public class UserBindRelationServiceImpl implements UserBindRelationService {
 
 		UserBindDetail userBindDetail;
 		//微信用户
-		if (StrUtil.isNotEmpty(user.getUnionid())) {
+		if (StrUtil.isNotBlank(user.getUnionid()) || StrUtil.isNotEmpty(user.getOpenId())) {
 			userIds.add(userId);
 			userBindDetail = userBindDetailMapper.selectOne(Wrappers.lambdaQuery(UserBindDetail.class)
 					.eq(UserBindDetail::getUserId, userId).last("limit 1"));

+ 17 - 0
netflix-service/src/main/java/com/cyksj/service/user/impl/UserIdentCertServiceImpl.java

@@ -10,9 +10,11 @@ import com.cyksj.common.util.Jsons;
 import com.cyksj.common.util.StringUtil;
 import com.cyksj.mapper.UserCertRecordMapper;
 import com.cyksj.mapper.UserMapper;
+import com.cyksj.mapper.UserStudentCertRecordMapper;
 import com.cyksj.model.dto.UserWxIndentDto;
 import com.cyksj.model.entity.User;
 import com.cyksj.model.entity.UserCertRecord;
+import com.cyksj.model.entity.UserStudentCertRecord;
 import com.cyksj.model.request.UserIndentCertReq;
 import com.cyksj.model.response.WxCertAuthTokenResp;
 import com.cyksj.redis.RedisService;
@@ -43,6 +45,8 @@ public class UserIdentCertServiceImpl implements UserIdentCertService {
 
 	private final UserCertRecordMapper userCertRecordMapper;
 
+	private final UserStudentCertRecordMapper userStudentCertRecordMapper;
+
 	private final UserMapper userMapper;
 
 	private final RedisService redisService;
@@ -81,6 +85,19 @@ public class UserIdentCertServiceImpl implements UserIdentCertService {
 		return record;
 	}
 
+	@Override
+	public UserStudentCertRecord getUserStudentCertRecord(long userId) {
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		UserStudentCertRecord record = userStudentCertRecordMapper.selectOne(Wrappers.lambdaQuery(UserStudentCertRecord.class)
+				.in(UserStudentCertRecord::getUserId, userIdList)
+				.select(UserStudentCertRecord::getSchool, UserStudentCertRecord::getCreatedTime)
+				.last("limit 1"));
+		if (record == null) {
+			return null;
+		}
+		return record;
+	}
+
 	@Override
 	public String bindWxUser(long userId) {
 		User user = userMapper.selectById(userId);

+ 7 - 0
netflix-service/src/main/java/com/cyksj/service/wechat/WeChatService.java

@@ -2,6 +2,7 @@ package com.cyksj.service.wechat;
 
 
 import com.cyksj.model.dto.*;
+import com.cyksj.model.request.TargetAppletSchemeReq;
 import com.cyksj.model.response.WxGzhQrCodeTicketRep;
 import com.cyksj.model.wechat.MiniURLLink;
 
@@ -101,4 +102,10 @@ public interface WeChatService {
     String getMiniURLLink(String accessToken, MiniURLLink miniURLLink) throws Exception;
 
     MiniProgramSession code2Session(String appId, String code) throws Exception;
+
+    void getMiniStudentIdentity(String openId, String code) throws Exception;
+
+	String generateSchema(String accessToken, TargetAppletSchemeReq targetAppletSchemeReq) throws Exception;
+
+    byte[] generateCode(String accessToken, String path) throws Exception;
 }

+ 69 - 0
netflix-service/src/main/java/com/cyksj/service/wechat/impl/WeChatServiceImpl.java

@@ -15,6 +15,7 @@ import com.cyksj.common.util.*;
 import com.cyksj.config.BaseWeChatConfig;
 import com.cyksj.config.WeChatConfig;
 import com.cyksj.config.WeChatFactory;
+import com.cyksj.config.YhCertMiniConfig;
 import com.cyksj.enums.WeChatAuthRedirectUrl;
 import com.cyksj.mapper.WxAppMapper;
 import com.cyksj.mapper.channel.ShopConfigMapper;
@@ -22,6 +23,7 @@ import com.cyksj.model.dto.*;
 import com.cyksj.model.entity.ShopConfig;
 import com.cyksj.model.entity.SysConfig;
 import com.cyksj.model.entity.WxApp;
+import com.cyksj.model.request.TargetAppletSchemeReq;
 import com.cyksj.model.response.WxGzhQrCodeTicketRep;
 import com.cyksj.model.wechat.MiniURLLink;
 import com.cyksj.redis.RedisService;
@@ -71,6 +73,8 @@ public class WeChatServiceImpl implements WeChatService {
 
     private final SysConfigService sysConfigService;
 
+    private final YhCertMiniConfig certMiniConfig;
+
     @Override
     public String createUrl(String state, String redirectUrl) {
         return createUrl(state,redirectUrl,weChatConfig.getAppid(), WeChatAuthRedirectUrl.BASE.getScope());
@@ -666,4 +670,69 @@ public class WeChatServiceImpl implements WeChatService {
         return wxMpAccountOps.miniProgramCode2Session(appId,code);
     }
 
+    @Override
+    public void getMiniStudentIdentity(String openId, String code) throws Exception {
+        String url = "https://api.weixin.qq.com/intp/quickcheckstudentidentity?access_token=" + getAccessToken(certMiniConfig.getAppId());
+
+        JSONObject params = new JSONObject();
+        params.putOpt("openid", openId);
+        params.putOpt("wx_studentcheck_code", code);
+
+        HttpResponse<String> response = J11HttpC.custom().url(url).ofPost().body(HttpRequest.BodyPublishers.ofString(params.toString())).send(HttpResponse.BodyHandlers.ofString());
+
+        JSONObject re = Jsons.parseObject(response.body(), JSONObject.class);
+        if (re.getInt("errcode") != 0) {
+            log.info("获取学生信息失败:{}", re.getStr("errmsg"));
+            throw BusinessRuntimeException.getInstance("获取认证信息失败");
+        }
+        Integer bindStatus = Optional.ofNullable(re.getInt("bind_status")).orElse(1);
+        //绑定状态:
+        //1-未绑定
+        //2-审核中
+        //3-已绑定
+        if (bindStatus == 1) {
+            throw BusinessRuntimeException.getInstance("大学生身份未绑定");
+        }
+        if (bindStatus == 2) {
+            throw BusinessRuntimeException.getInstance("大学生身份审核中");
+        }
+    }
+
+    @Override
+    public String generateSchema(String accessToken, TargetAppletSchemeReq targetAppletSchemeReq) throws Exception {
+        String url = "https://api.weixin.qq.com/wxa/generatescheme?access_token=" + accessToken;
+        HttpResponse<byte[]> res = J11HttpC.custom()
+                .ofPost()
+                .url(url)
+                .body(HttpRequest.BodyPublishers.ofString(Jsons.toJson(targetAppletSchemeReq)))
+                .send(HttpResponse.BodyHandlers.ofByteArray());
+        if (200 != res.statusCode()) {
+            throw BusinessRuntimeException.getInstance("获取用户信息失败: " + IoKit.toString(res.body()));
+        }
+
+        JSONObject jsonObject = Jsons.parseObject(res.body(), JSONObject.class);
+        if (jsonObject.getInt("errcode") != 0) {
+            throw BusinessRuntimeException.getInstance(jsonObject.getStr("errmsg"));
+        }
+        if (StrUtil.isEmpty(jsonObject.getStr("openlink"))) {
+            throw BusinessRuntimeException.getInstance("系统异常..");
+        }
+        return jsonObject.getStr("openlink");
+    }
+
+    @Override
+    public byte[] generateCode(String accessToken, String path) throws Exception {
+        String url = "https://api.weixin.qq.com/wxa/getwxacode?access_token=" + accessToken;
+        JSONObject params = new JSONObject();
+        params.putOpt("path", path);
+        HttpResponse<byte[]> res = J11HttpC.custom()
+                .ofPost()
+                .url(url)
+                .body(HttpRequest.BodyPublishers.ofString(params.toString()))
+                .send(HttpResponse.BodyHandlers.ofByteArray());
+        if (200 != res.statusCode()) {
+            throw BusinessRuntimeException.getInstance("获取用户信息失败: " + IoKit.toString(res.body()));
+        }
+        return res.body();
+    }
 }

+ 83 - 0
netflix-service/src/main/java/com/cyksj/task/CorpChatScheduler.java

@@ -0,0 +1,83 @@
+package com.cyksj.task;
+
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.util.StringUtil;
+import com.cyksj.mapper.corp.CorpUserAuthMapper;
+import com.cyksj.mapper.corp.CorpUserMapper;
+import com.cyksj.model.entity.CorpUser;
+import com.cyksj.model.entity.CorpUserAuth;
+import com.cyksj.model.entity.OrderDonPost;
+import com.cyksj.redis.RedisService;
+import com.cyksj.service.corp.WxCorpOps;
+import com.cyksj.service.corp.msg.CorpEventActionService;
+import com.cyksj.service.order.OrderDonPostService;
+import com.ejlchina.searcher.BeanSearcher;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * @author chan
+ * @date 2024-04-29 12:14
+ */
+@Component
+@Slf4j
+@RequiredArgsConstructor
+public class CorpChatScheduler {
+
+	private final CorpUserMapper corpUserMapper;
+
+	private final CorpUserAuthMapper corpUserAuthMapper;
+
+	private final RedisService redisService;
+
+	private final OrderDonPostService orderDonPostService;
+
+	/**
+	 * 客服业绩数据统计
+	 */
+    @Scheduled(cron = "5 0/2 * * * ?")
+	public void chatPost() {
+		Set<Object> chatRecord = redisService.sGet(RedisService.key.CORP_CUSTOMER_ACQUISTION_START_CHAT_SET.getEnvName());
+		log.info("发起对话回传. size: {}", chatRecord.size());
+		chatRecord.forEach((key) -> {
+			log.info("发起对话回传. key: {}", key);
+			CorpUserAuth corpUserAuth = corpUserAuthMapper.selectOne(Wrappers.lambdaQuery(CorpUserAuth.class)
+					.eq(CorpUserAuth::getExternalUserid, key).last("limit 1"));
+			String unionId = null;
+			if (corpUserAuth != null) {
+				CorpUser corpUser = corpUserMapper.selectById(corpUserAuth.getCorpUserId());
+				if (corpUser != null) {
+					unionId = corpUser.getUnionid();
+				}
+			}
+			log.info("发起对话回传. unionId: {}", unionId);
+			if (StrUtil.isNotBlank(unionId)) {
+				String json = StringUtil.getString(redisService.hget(RedisService.key.CORP_CUSTOMER_ACQUISTION_START_CHAT.getEnvName(), unionId));
+				if (StringUtil.isNotBlank(json)) {
+					JSONObject jsonObject = JSONUtil.parseObj(json);
+					String callback = jsonObject.getStr("callback");
+					try {
+						orderDonPostService.post(OrderDonPost.Type.OE.getType(), callback, Optional.ofNullable(jsonObject.getStr("event")).orElse("customer_effective"));
+						redisService.setRemove(RedisService.key.CORP_CUSTOMER_ACQUISTION_START_CHAT_SET.getEnvName(), key);
+						log.info("发起对话回传成功. {}", key);
+					} catch (Exception e) {
+						log.error("发起对话回传失败. {}", e.getMessage());
+					}
+				}
+			}else {
+				Long count = redisService.incr(RedisService.key.CORP_CUSTOMER_ACQUISTION_START_CHAT_COUNT.getNameFormat(key), 1L);
+				if(count > 3){
+					redisService.setRemove(RedisService.key.CORP_CUSTOMER_ACQUISTION_START_CHAT_SET.getEnvName(), key);
+				}
+			}
+		});
+	}
+}

+ 31 - 0
netflix-web/src/main/java/com/cyksj/web/controller/goods/GoodsDonController.java

@@ -18,6 +18,7 @@ import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.GoodsDonSkuMapper;
 import com.cyksj.mapper.OrderDonMapper;
 import com.cyksj.mapper.RegisterOrderDonMapper;
+import com.cyksj.mapper.shop.YhShopGoodsSkuMapper;
 import com.cyksj.mapper.sys.SysConfigMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.request.ClickRecordReq;
@@ -67,6 +68,8 @@ public class GoodsDonController {
 
     private final GoodsDonSkuMapper goodsDonSkuMapper;
 
+    private final YhShopGoodsSkuMapper yhShopGoodsSkuMapper;
+
     private final RedisService redisService;
 
     private final SysConfigMapper sysConfigMapper;
@@ -1045,6 +1048,10 @@ public class GoodsDonController {
 						.eq(OrderDon::getGoodsId, data.getId()).notIn(OrderDon::getStatus, Constant.noOrderStatus));
 				data.setSold(sold + data.getSold());
 				data.setNotifyMsg(getPayMsgTime(data.getId(), now, 1, yhsId));
+				//重新设置最低价格规格
+				YhShopGoodsSku sku = yhShopGoodsSkuMapper.selectMinPriceSkuByYhsId(yhsId, data.getId());
+				data.setPrice(sku.getPrice());
+				data.setSkuId(sku.getSkuId());
 			});
 			redisService.setNx(categoryGoodsKey, list, RedisService.key.YH_HOME_PAGHE_CACHE.getTimeout() + 5 * 60);
 			value = redisService.get(categoryGoodsKey);
@@ -1216,4 +1223,28 @@ public class GoodsDonController {
 		return GatewayResponse.SUCCESS.newBuilder().toResult(goodsDonSkuSubsidyAvailableViews);
 	}
 
+	/**
+	 * 获取用户店铺首页配置列表
+	 */
+	@GetMapping("/get/shop/homeManage")
+	public Result<Map<String, List<HomeManagementFrontView>>> getShopHomeManageConfig(String customId) {
+		//是否同意展示对应首页广告位
+		String key = RedisService.key.YH_HOME_PAGHE_CACHE_SHOP.getEnvName() + customId + ":homeManage";
+		Object o = redisService.get(key);
+		if (o == null) {
+			MapBuilder builder = MapUtils.builder()
+					.field(HomeManagementFrontView::getType, HomeManagementConfig.Type.ad.name())
+					.field(HomeManagementFrontView::getIsShop, 1);
+			List<HomeManagementFrontView> homeManagementFrontViews = beanSearcher.searchAll(HomeManagementFrontView.class, builder.build());
+			if (homeManagementFrontViews == null) {
+				return GatewayResponse.SUCCESS.newBuilder().toResult();
+			}
+			Map<String, List<HomeManagementFrontView>> map = new ConcurrentHashMap<>();
+			map.putIfAbsent(HomeManagementConfig.Type.ad.name(), homeManagementFrontViews);
+			redisService.setNx(key, map, 50 * 60l);
+			o = redisService.get(key);
+		}
+		Map map = Jsons.parseObject(o, Map.class);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(map);
+	}
 }

+ 5 - 2
netflix-web/src/main/java/com/cyksj/web/controller/group/GroupRelationController.java

@@ -273,8 +273,11 @@ public class GroupRelationController {
                 .between(DoubleVerifyClickRecord::getCreatedTime, DateUtil.beginOfMonth(now), DateUtil.endOfMonth(now)));
         //获取双重验证码
         Boolean isHasVerifyCode = StrUtil.isNotBlank(groupsRelationView.getVerifyCode()) ? true : false;
-        Integer num = groupRelationFrontService.getUserCodeNumBySkuId(userId, groupsRelationView.getSkuId(), isHasVerifyCode);
-        if (count >= num) throw BusinessRuntimeException.getInstance("获取双重验证码次数上限");
+        //出去亚马逊 获取限制
+        if (groupsRelationView.getGoodsId() != 6) {
+            Integer num = groupRelationFrontService.getUserCodeNumBySkuId(userId, groupsRelationView.getSkuId(), isHasVerifyCode);
+            if (count >= num) throw BusinessRuntimeException.getInstance("获取双重验证码次数上限");
+        }
         //一分钟内 只能一人获取
         boolean b = redisService.setNx(RedisService.key.DOUBLE_VERIFY_CODE_VIEW_MINUTES_KEY.getEnvName() + groupsRelationView.getTripsAccount(), relationId, RedisService.key.DOUBLE_VERIFY_CODE_VIEW_MINUTES_KEY.getTimeout());
         if (!b) {

+ 7 - 1
netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsOrderController.java

@@ -109,7 +109,7 @@ public class CmsOrderController {
 
 	@GetMapping("/get")
 	@SaCheckPermission("order:view")
-	public Result<SearchResult<OrderDonBackView>> get(Long channelId, String account, String showId, Long acId, String nickname, String register, Boolean isGoogle) {
+	public Result<SearchResult<OrderDonBackView>> get(Long channelId, String account, String showId, Long acId, String nickname, String register, Boolean isGoogle, Boolean isSubsidy) {
 		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
 		if (channelId != null) {
 			List<Long> popularizeIds = channelPopularizeMapper.getPopularizeIdByChannelId(channelId);
@@ -153,6 +153,12 @@ public class CmsOrderController {
 			}
 			conditionSql += " limit 1)";
 		}
+		if (isSubsidy != null) {
+			if (StrUtil.isNotEmpty(conditionSql)) {
+				conditionSql += " and ";
+			}
+			conditionSql += " exists (select 1 from order_don_subsidy_relate ocr where ocr.order_id = o.id limit 1)";
+		}
 		if (StrUtil.isNotBlank(conditionSql)) {
 			builder.put("condition", conditionSql);
 		}

+ 2 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/account/CmsAccountController.java

@@ -640,6 +640,7 @@ public class CmsAccountController {
 							.eq(UserTicketClearedRecord::getAccountId, account.getId()));
 					//发放模板消息
 					try {
+						account.setAccount(db.getAccount());
 						templateCommonService.sendAccountTemplateMsg(account);
 					} catch (Exception e) {
 						log.error("发送账号{}修改密码消息模板错误", account.getId());
@@ -885,6 +886,7 @@ public class CmsAccountController {
 		if (isFlag) {
 			boolean b = accountService.updateById(db);
 			if (StrUtil.isNotBlank(newPwd) && !dnPwd.equals(newPwd) && b) {
+				account.setAccount(db.getAccount());
 				templateCommonService.sendAccountTemplateMsg(account);
 			}
 		}

+ 74 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/active/UserActivityController.java

@@ -0,0 +1,74 @@
+package com.cyksj.web.controller.manage.active;
+
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.entity.UserActivity;
+import com.cyksj.service.user.UserActivityService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserActivityController
+ * 创建者: JavaZou
+ * 创建时间:2024/4/17 12:22
+ */
+@RestController
+@RequestMapping("/manage/activity")
+@Slf4j
+@RequiredArgsConstructor
+public class UserActivityController {
+	private final UserActivityService userActivityService;
+
+	private final BeanSearcher beanSearcher;
+
+	private final HttpServletRequest request;
+
+	/**
+	 * 新建活动
+	 */
+	@PostMapping("/post")
+	public Result<String> insertActivity(@RequestBody @Validated UserActivity userActivity) throws Exception {
+		userActivityService.saveOrUpdateActivity(userActivity);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 编辑活动
+	 */
+	@PutMapping("/update")
+	public Result<String> updateActivity(@RequestBody @Validated UserActivity userActivity) throws Exception {
+		userActivityService.saveOrUpdateActivity(userActivity);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 删除活动
+	 */
+	@DeleteMapping("/delete/{id}")
+	public Result<String> deleteActivity(@PathVariable Long id) {
+		UserActivity activity = userActivityService.getById(id);
+		if (activity != null && activity.getDeleted()) {
+			activity.setDeleted(false);
+			userActivityService.updateById(activity);
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 活动列表
+	 */
+	@GetMapping("/get")
+	public Result<SearchResult<UserActivity> > get() {
+		SearchResult<UserActivity> search = beanSearcher.search(UserActivity.class, MapUtils.flatBuilder(request.getParameterMap()).field(UserActivity::getDeleted, 1).build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+}

+ 4 - 2
netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/CorpMsgAuditController.java

@@ -12,7 +12,6 @@ import com.cyksj.service.corp.CorpQyMsgContentService;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
 import com.ejlchina.searcher.operator.InList;
-import com.ejlchina.searcher.param.Operator;
 import com.ejlchina.searcher.util.MapBuilder;
 import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
@@ -54,7 +53,7 @@ public class CorpMsgAuditController {
      * @return
      */
     @GetMapping
-    public Result<SearchResult<CorpMsgAuditUserView>> get(String textKey, String tagId) {
+    public Result<SearchResult<CorpMsgAuditUserView>> get(String textKey, String tagId, Integer intention) {
         Set<String> userIds = new HashSet<>();
         if(StringUtils.isNotBlank(textKey)){
             List<QyMsgContent> text = corpQyMsgContentService.list(Wrappers.lambdaQuery(QyMsgContent.class).select(QyMsgContent::getFrom, QyMsgContent::getExternalUserid,QyMsgContent::getTolist).like(QyMsgContent::getText, textKey).eq(QyMsgContent::getRoomid,"").eq(QyMsgContent::getMsgtype, "text"));
@@ -68,6 +67,9 @@ public class CorpMsgAuditController {
             builder.put("tag", String.format( "and cr.id = t.relation_id and t.tag_id = '%s'", tagId));
             builder.put("tagTable", ",corp_user_tag t");
         }
+        if (intention != null) {
+            builder.put("intention", String.format("and exists (select 1 from corp_user_pay_intention cup where cup.union_id = c.unionid and intention = %s limit 1)", intention));
+        }
         SearchResult<CorpMsgAuditUserView> search = beanSearcher.search(CorpMsgAuditUserView.class, builder.build());
         return GatewayResponse.SUCCESS.newBuilder().toResult(search);
 

+ 33 - 4
netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/WxCorpController.java

@@ -21,10 +21,7 @@ import com.cyksj.mapper.GroupsRelationExpiryRecordMapper;
 import com.cyksj.mapper.corp.CorpUserAuthMapper;
 import com.cyksj.mapper.corp.CorpUserTagMapper;
 import com.cyksj.model.dto.AuthRedirect;
-import com.cyksj.model.entity.CorpCustomerAcquistionCallback;
-import com.cyksj.model.entity.CorpFollow;
-import com.cyksj.model.entity.CorpMsgFollowAssociation;
-import com.cyksj.model.entity.QyMsgContent;
+import com.cyksj.model.entity.*;
 import com.cyksj.model.manage.views.CorpQyMsgAuditChatView;
 import com.cyksj.model.request.corp.CorpCommonReq;
 import com.cyksj.model.views.CorpUserIntentionView;
@@ -339,6 +336,38 @@ public class WxCorpController {
 		return GatewayResponse.SUCCESS.newBuilder().toResult(corpCustomerAcquistionCallback);
 	}
 
+	/**
+	 * 查询用户 购买意愿
+	 */
+	@GetMapping("/get/user/intention")
+	public Result<CorpUserPayIntention> getUserIntention(String externalUserId) {
+		if (StrUtil.isEmpty(externalUserId)) {
+			return GatewayResponse.SUCCESS.newBuilder().toResult();
+		}
+		String unionId = corpUserAuthMapper.getUnionIdByExternalUserId(externalUserId);
+		if (StrUtil.isEmpty(unionId)) {
+			return GatewayResponse.SUCCESS.newBuilder().toResult();
+		}
+		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap()).field(CorpUserPayIntention::getUnionId, unionId);
+		CorpUserPayIntention corpUserPayIntention = Optional.ofNullable(beanSearcher.searchFirst(CorpUserPayIntention.class, builder.build()))
+				.orElseGet(() -> {
+					CorpUserPayIntention corpUserPayIntention1 = new CorpUserPayIntention();
+					corpUserPayIntention1.setUnionId(unionId);
+					corpUserPayIntention1.setIntention(0);
+					return corpUserPayIntention1;
+				});
+		return GatewayResponse.SUCCESS.newBuilder().toResult(corpUserPayIntention);
+	}
+
+	@PutMapping("/update/user/intention")
+	public Result<CorpUserPayIntention> updateUserIntention(@RequestBody CorpUserPayIntention corpUserPayIntention) {
+		if (corpUserPayIntention.getUnionId() == null || corpUserPayIntention.getIntention() == null) {
+			throw BusinessRuntimeException.getInstance("缺少必填参数.");
+		}
+		corpService.updateUserIntention(corpUserPayIntention);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(corpUserPayIntention);
+	}
+
 	/**
 	 * 主动回传
 	 *

+ 27 - 2
netflix-web/src/main/java/com/cyksj/web/controller/manage/coupon/CouponController.java

@@ -39,6 +39,7 @@ import org.springframework.web.bind.annotation.*;
 import javax.servlet.http.HttpServletRequest;
 import javax.validation.constraints.Min;
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
@@ -188,9 +189,11 @@ public class CouponController {
 		search.getDataList().forEach(data -> {
 			data.setRelationNum(couponDistributePopularizeMapper.selectCount(Wrappers.lambdaQuery(CouponDistributePopularize.class).eq(CouponDistributePopularize::getCouponId, data.getId())));
 
-			Integer usedNum = couponUserMapper.selectCount(Wrappers.lambdaQuery(CouponUser.class)
-					.eq(CouponUser::getCouponId, data.getId()).eq(CouponUser::getStatus, CouponUser.Status.used));
+			Map<String, Long> couponUserNumData = couponUserMapper.selectCouponUserNumData(data.getId());
+			Integer usedNum = Integer.parseInt(couponUserNumData.get("usedNum").toString());
 			data.setUsedNum(usedNum);
+			Integer receiptNum = Integer.parseInt(couponUserNumData.get("receiptNum").toString());
+			data.setReceiptNum(receiptNum);
 
 			List<GoodsDonSkuView> skuViewList = couponSkuMapper.selectGoodsSkuViewList(data.getId());
 			data.setSkuViewList(skuViewList);
@@ -511,4 +514,26 @@ public class CouponController {
 		});
 		return GatewayResponse.SUCCESS.newBuilder().toResult();
 	}
+
+	/**
+	 * 优惠券领取详情
+	 */
+	@GetMapping("/get/receipt/detail/{couponId}")
+	public Result<SearchResult<CouponReceiptDetailView>> getReceiptDetail(@PathVariable Long couponId) {
+		SearchResult<CouponReceiptDetailView> search = beanSearcher.search(CouponReceiptDetailView.class, MapUtils.flatBuilder(request.getParameterMap())
+				.put("cid",String.format("and id = %s", couponId))
+				.build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 优惠券使用详情
+	 */
+	@GetMapping("/get/used/detail/{couponId}")
+	public Result<SearchResult<CouponUsedDetailView>> getUsedDetail(@PathVariable Long couponId) {
+		SearchResult<CouponUsedDetailView> search = beanSearcher.search(CouponUsedDetailView.class, MapUtils.flatBuilder(request.getParameterMap())
+				.put("cid",String.format("and id = %s", couponId))
+				.build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
 }

+ 11 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/CmsGoodsDonSkuController.java

@@ -107,6 +107,9 @@ public class CmsGoodsDonSkuController {
     @PutMapping(value = "/update")
     @Log(module = "平台管理/编辑规格", businessType = BusinessType.PUT, isSaveRequestData = true)
     public Result<String> skuUpdate(@RequestBody GoodsDonSku sku) throws Exception {
+        Long skuId = sku.getId();
+        GoodsDonSku dbSku = goodsDonSkuService.getById(skuId);
+        Assert.notNull(dbSku, "规格不存在");
         Long goodsId = sku.getGoodsId();
         GoodsDon goods = goodsDonService.getById(goodsId);
         if (goods.getType() == 1) {
@@ -162,6 +165,14 @@ public class CmsGoodsDonSkuController {
         goodsDonSkuService.saveOrUpdate(sku);
         //给平台更新额外属性
         goodsDonService.updateGoodsSkuPrice(sku.getGoodsId(), null);
+        //前后两次价格不同 下架店铺低于这个折扣最低价格
+        BigDecimal oldPrice = dbSku.getPrice();
+        BigDecimal newPrice = sku.getPrice();
+        //规格新价 变高
+        if (newPrice.compareTo(oldPrice) > 0) {
+            //下架店铺低于这个规格价格的品
+            goodsDonSkuService.setBelowPriceShopSkuDown(skuId, newPrice);
+        }
         refreshCacheService.refreshYhHomePageCache();
         return GatewayResponse.SUCCESS.newBuilder().toResult();
     }

+ 23 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/shop/CmsYhShopGoodsController.java

@@ -12,6 +12,7 @@ import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.StringUtil;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.GoodsDonSkuMapper;
 import com.cyksj.mapper.UserMapper;
 import com.cyksj.mapper.manage.cms.CmsUserMapper;
 import com.cyksj.mapper.shop.YhShopMapper;
@@ -21,8 +22,10 @@ import com.cyksj.model.request.GoodsDonShopRateReq;
 import com.cyksj.model.request.YhShopUserPlatDistributeRateReq;
 import com.cyksj.model.request.YhShopVerifyReq;
 import com.cyksj.model.views.*;
+import com.cyksj.service.mange.CmsGoodsDonSkuService;
 import com.cyksj.service.mange.CmsYhShopCommonService;
 import com.cyksj.service.mange.CmsYhShopGoodsRateService;
+import com.cyksj.service.mange.RefreshCacheService;
 import com.cyksj.service.mange.business.UserBusinessRateService;
 import com.cyksj.service.mange.statistics.StatisticsDataService;
 import com.ejlchina.searcher.BeanSearcher;
@@ -74,6 +77,12 @@ public class CmsYhShopGoodsController {
 
     private final StatisticsDataService statisticsDataService;
 
+    private final GoodsDonSkuMapper skuMapper;
+
+    private final CmsGoodsDonSkuService goodsDonSkuService;
+
+    private final RefreshCacheService refreshCacheService;
+
 
     /**
      * 获取店铺平台价格
@@ -110,7 +119,12 @@ public class CmsYhShopGoodsController {
                 one.setRate(e.getRate());
             }
             yhShopGoodsRateService.saveOrUpdate(one);
+
+            GoodsDonSku sku = skuMapper.selectById(one.getSkuId());
+            //下架店铺低于这个规格价格的品
+            goodsDonSkuService.setBelowPriceShopSkuDown(e.getSkuId(), sku.getPrice());
         });
+        refreshCacheService.refreshYhHomePageCache();
         return GatewayResponse.SUCCESS.newBuilder().toResult();
     }
 
@@ -118,6 +132,7 @@ public class CmsYhShopGoodsController {
      * 一键设置 店铺平台通用浮动比例
      */
     @PutMapping("/oneKey/set/goods/rate")
+    @Transactional(rollbackFor = Throwable.class)
     public Result<Void> setShopGoodsGeneralRate(@RequestBody GoodsDonShopRateReq req) {
         Integer rate = Optional.ofNullable(req.getRate()).orElse(0);
         if (rate < 0 && rate > 100) {
@@ -130,7 +145,15 @@ public class CmsYhShopGoodsController {
                 data.setRate(rate);
             });
             yhShopGoodsRateService.saveOrUpdateBatch(yhShopGoodsRates);
+
+            List<GoodsDonSku> goodsDonSkus = goodsDonSkuService.list(Wrappers.lambdaQuery(GoodsDonSku.class)
+                    .eq(GoodsDonSku::getGoodsId, goodsId));
+            goodsDonSkus.forEach(sku -> {
+                //下架店铺低于这个规格价格的品
+                goodsDonSkuService.setBelowPriceShopSkuDown(sku.getId(), sku.getPrice());
+            });
         });
+        refreshCacheService.refreshYhHomePageCache();
         return GatewayResponse.SUCCESS.newBuilder().toResult();
     }
 

+ 37 - 11
netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/shop/YhShopGoodsController.java

@@ -5,12 +5,14 @@ import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.shop.YhShopMapper;
+import com.cyksj.model.dto.YhShopSkuDownInfo;
 import com.cyksj.model.entity.YhShop;
 import com.cyksj.model.entity.YhShopGoodsSku;
 import com.cyksj.model.views.YhShopAvailableGoodsView;
 import com.cyksj.model.views.YhShopGoodsRateView;
 import com.cyksj.model.views.YhShopGoodsView;
 import com.cyksj.redis.RedisService;
+import com.cyksj.service.mange.RefreshCacheService;
 import com.cyksj.service.shop.YhShopGoodsSkuService;
 import com.cyksj.web.util.StpYhShopManageUser;
 import com.ejlchina.searcher.BeanSearcher;
@@ -22,7 +24,6 @@ import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
 import java.util.List;
-import java.util.Set;
 
 /*
  *项目名: yhlxj
@@ -45,6 +46,8 @@ public class YhShopGoodsController {
 
 	private final HttpServletRequest request;
 
+	private final RefreshCacheService refreshCacheService;
+
 	/**
 	 * 新增平台
 	 */
@@ -72,9 +75,7 @@ public class YhShopGoodsController {
 			sku.setYhsId(yhShop.getId());
 		});
 		yhShopGoodsSkuService.saveOrUpdateBatch(goodsSkus);
-		String yhShopCacheKey = RedisService.key.YH_HOME_PAGHE_CACHE_SHOP.getEnvName() + yhShop.getId() + "*";
-		Set<String> keys = redisService.keys(yhShopCacheKey);
-		redisService.del(keys.toArray(String[]::new));
+		refreshCacheService.refreshShopUserIdCacheByYshId(yhShop.getId());
 		return GatewayResponse.SUCCESS.newBuilder().toResult();
 	}
 
@@ -82,14 +83,20 @@ public class YhShopGoodsController {
 	 * 上下架
 	 */
 	@PutMapping("/put/goodsStatus/{goodsId}")
-	public Result<Void> updGoodsStatus(@PathVariable Long goodsId, Boolean status){
+	public Result<Void> updGoodsStatus(@PathVariable Long goodsId, Boolean status) {
 		long userId = StpYhShopManageUser.getLoginIdAsLong();
 		YhShop yhShop = yhShopMapper.selectOne(Wrappers.lambdaQuery(YhShop.class)
 				.eq(YhShop::getUserId, userId).last("limit 1"));
+		List<YhShopGoodsView.YhShopGoodsSkuView> list = beanSearcher.searchAll(YhShopGoodsView.YhShopGoodsSkuView.class, MapUtils.builder().put("uid", String.format("and ysgs.user_id = %s", userId))
+				.field(YhShopGoodsView.YhShopGoodsSkuView::getGoodsId, goodsId).build());
+		list.forEach(sku -> {
+			YhShopGoodsRateView.YhShopGoodsSkuRateView yhShopGoodsSkuRateView = beanSearcher.searchFirst(YhShopGoodsRateView.YhShopGoodsSkuRateView.class, MapUtils.builder().field(YhShopGoodsRateView.YhShopGoodsSkuRateView::getSkuId, sku.getSkuId()).build());
+			if (sku.getShopSkuPrice().compareTo(yhShopGoodsSkuRateView.getMaxPrice()) > 0 || sku.getShopSkuPrice().compareTo(yhShopGoodsSkuRateView.getMinPrice()) < 0) {
+				throw BusinessRuntimeException.getInstance("价格不能超出区间范围");
+			}
+		});
 		yhShopGoodsSkuService.update(Wrappers.lambdaUpdate(YhShopGoodsSku.class).eq(YhShopGoodsSku::getGoodsId, goodsId).eq(YhShopGoodsSku::getDeleted, true).eq(YhShopGoodsSku::getUserId, userId).set(YhShopGoodsSku::getStatus, status));
-		String yhShopCacheKey = RedisService.key.YH_HOME_PAGHE_CACHE_SHOP.getEnvName() + yhShop.getId() + "*";
-		Set<String> keys = redisService.keys(yhShopCacheKey);
-		redisService.del(keys.toArray(String[]::new));
+		refreshCacheService.refreshShopUserIdCacheByYshId(yhShop.getId());
 		return GatewayResponse.SUCCESS.newBuilder().toResult();
 	}
 
@@ -103,9 +110,7 @@ public class YhShopGoodsController {
 		YhShop yhShop = yhShopMapper.selectOne(Wrappers.lambdaQuery(YhShop.class)
 				.eq(YhShop::getUserId, userId).last("limit 1"));
 		yhShopGoodsSkuService.update(Wrappers.lambdaUpdate(YhShopGoodsSku.class).eq(YhShopGoodsSku::getGoodsId, goodsId).eq(YhShopGoodsSku::getUserId, userId).set(YhShopGoodsSku::getDeleted, false));
-		String yhShopCacheKey = RedisService.key.YH_HOME_PAGHE_CACHE_SHOP.getEnvName() + yhShop.getId() + "*";
-		Set<String> keys = redisService.keys(yhShopCacheKey);
-		redisService.del(keys.toArray(String[]::new));
+		refreshCacheService.refreshShopUserIdCacheByYshId(yhShop.getId());
 		return GatewayResponse.SUCCESS.newBuilder().toResult();
 	}
 
@@ -142,4 +147,25 @@ public class YhShopGoodsController {
 				.field(YhShopGoodsView.YhShopGoodsSkuView::getGoodsId, goodsId).build());
 		return GatewayResponse.SUCCESS.newBuilder().toResult(views);
 	}
+
+	/**
+	 * 小店规格被下架提示
+	 * @return
+	 */
+	@GetMapping("/get/sku/down/info")
+	public Result<List<YhShopSkuDownInfo>> yhShopSkuSysStatusDownInfo() {
+		long userId = StpYhShopManageUser.getLoginIdAsLong();
+		List<YhShopSkuDownInfo> infos = yhShopGoodsSkuService.yhShopSkuSysStatusDownInfo(userId);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(infos);
+	}
+
+	/**
+	 * 删除提示
+	 */
+	@DeleteMapping("/delete/sku/down/info")
+	public Result<String> deleteSkuDownInfo() {
+		long userId = StpYhShopManageUser.getLoginIdAsLong();
+		yhShopGoodsSkuService.deleteSkuDownInfo(userId);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
 }

+ 19 - 2
netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/shop/YhShopUserController.java

@@ -14,7 +14,7 @@ import com.cyksj.model.entity.*;
 import com.cyksj.model.request.YhShopApplyMoneyReq;
 import com.cyksj.model.views.*;
 import com.cyksj.service.cps.shop.YhShopManageService;
-import com.cyksj.service.mange.GoodsDonCategoryService;
+import com.cyksj.service.mange.RefreshCacheService;
 import com.cyksj.web.util.StpYhShopManageUser;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
@@ -54,7 +54,7 @@ public class YhShopUserController {
 
 	private final YhShopApplyRecordMapper yhShopApplyRecordMapper;
 
-	private final GoodsDonCategoryService goodsDonCategoryService;
+	private final RefreshCacheService refreshCacheService;
 
 	/**
 	 * 店铺 信息详情
@@ -85,6 +85,23 @@ public class YhShopUserController {
 		return GatewayResponse.SUCCESS.newBuilder().toResult();
 	}
 
+	/**
+	 * 设置是否展示广告位
+	 */
+	@PutMapping("/set/shop/ad")
+	public Result<String> setShopAd() {
+		long userId = StpYhShopManageUser.getLoginIdAsLong();
+		YhShop dbShop = yhShopMapper.selectOne(Wrappers.lambdaQuery(YhShop.class)
+				.eq(YhShop::getUserId, userId).last("limit 1"));
+		if (dbShop == null) {
+			throw BusinessRuntimeException.getInstance("店铺不存在");
+		}
+		dbShop.setIsShowAd(!dbShop.getIsShowAd());
+		yhShopMapper.updateById(dbShop);
+		refreshCacheService.refreshUserShopMangeCache(dbShop.getCustomId());
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
 	/**
 	 * 申请修改
 	 */

+ 40 - 0
netflix-web/src/main/java/com/cyksj/web/controller/mini/MiniController.java

@@ -1,11 +1,14 @@
 package com.cyksj.web.controller.mini;
 
 import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.util.IoKit;
+import com.cyksj.common.util.StringUtil;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
 import com.cyksj.model.entity.User;
 import com.cyksj.model.request.MiniArticleReq;
 import com.cyksj.model.request.MiniProgramLoginPost;
+import com.cyksj.model.request.MiniSchemaReq;
 import com.cyksj.model.views.ArticleDetailView;
 import com.cyksj.model.views.ArticleFrontView;
 import com.cyksj.model.views.ArticleSelfFrontView;
@@ -22,6 +25,8 @@ import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.OutputStream;
 
 /*
  *项目名: netflix
@@ -49,6 +54,41 @@ public class MiniController {
 		return GatewayResponse.SUCCESS.newBuilder().toResult(linkUrl);
 	}
 
+	/**
+	 * 生成小程序schema
+	 */
+	@GetMapping("/generate/schema")
+	public Result<String> generateSchema(String dsCode) throws Exception {
+		MiniSchemaReq req = new MiniSchemaReq();
+		req.setDsCode(dsCode);
+		String url = miniService.generateSchema(req);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(url);
+	}
+
+	/**
+	 * 生成小程序code
+	 */
+	@GetMapping("/generate/code")
+	public void generateCode(String dsCode, HttpServletResponse response) throws Exception {
+		MiniSchemaReq req = new MiniSchemaReq();
+		req.setDsCode(dsCode);
+		byte [] s = miniService.generateCode(req);
+		response.reset();
+		// 若直接在浏览器预览 需要注释下面的response header
+		//response.addHeader("Content-Disposition", "attachment;filename=share.jpeg");
+		response.setContentType("image/jpeg");
+		// 处理文件 返回流
+		OutputStream out = null;
+		try {
+			out = response.getOutputStream();
+			IoKit.write(s, out);
+		} catch (Throwable e) {
+			throw BusinessRuntimeException.getInstance(StringUtil.getErrorMsg(e));
+		} finally {
+			IoKit.close(out);
+		}
+	}
+
 	/**
 	 * 银河小程序 静默授权登录
 	 */

+ 92 - 0
netflix-web/src/main/java/com/cyksj/web/controller/mini/UserStudentCertController.java

@@ -0,0 +1,92 @@
+package com.cyksj.web.controller.mini;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.util.Jsons;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.UserMapper;
+import com.cyksj.mapper.UserStudentCertRecordMapper;
+import com.cyksj.model.entity.User;
+import com.cyksj.model.entity.UserStudentCertRecord;
+import com.cyksj.model.views.CouponView;
+import com.cyksj.model.views.UserActivityView;
+import com.cyksj.service.mini.MiniService;
+import com.cyksj.service.user.UserActivityService;
+import com.cyksj.service.user.UserBindRelationService;
+import com.cyksj.web.util.StpUserUtil;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.param.Operator;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserCertController
+ * 创建者: JavaZou
+ * 创建时间:2024/4/16 11:34
+ */
+@RestController
+@RequestMapping("/applets/mini/identity")
+@RequiredArgsConstructor
+@Slf4j
+public class UserStudentCertController {
+	private final UserMapper userMapper;
+
+	private final MiniService miniService;
+
+	private final UserActivityService userActivityService;
+
+	private final UserBindRelationService userBindRelationService;
+
+	private final BeanSearcher beanSearcher;
+
+	private final UserStudentCertRecordMapper userStudentCertRecordMapper;
+
+	/**
+	 * 获取学生身份接口
+	 */
+	@GetMapping("/get/student")
+	public Result<String> getStudentIdentity(String school, String code, String dsCode) throws Exception {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		User user = userMapper.selectById(userId);
+		if (user == null || StrUtil.isEmpty(user.getOpenId())) {
+			throw BusinessRuntimeException.getInstance("用户未授权");
+		}
+		//是否认证过
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, user);
+		Integer selectCount = userStudentCertRecordMapper.selectCount(Wrappers.lambdaQuery(UserStudentCertRecord.class)
+				.in(UserStudentCertRecord::getUserId, userIdList));
+		if (selectCount > 0) {
+			throw BusinessRuntimeException.getInstance("已认证大学生身份");
+		}
+		miniService.getStudentIdentity(user, code);
+		//大学生认证活动 若有sid则发送对应用户
+		userActivityService.sendStudentCertActivity(user, dsCode, school);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 大学生认证活动详情
+	 */
+	@GetMapping("/get/activity/info")
+	public Result<UserActivityView> getIdentityAcInfo() throws Exception {
+		UserActivityView userActivityView = beanSearcher.searchFirst(UserActivityView.class, MapUtils.builder().field(UserActivityView::getId, 1).build());
+		if (userActivityView == null) {
+			return GatewayResponse.SUCCESS.newBuilder().toResult();
+		}
+		if (StrUtil.isNotBlank(userActivityView.getCouponIds())) {
+			List<Long> couponIds = Jsons.parseList(userActivityView.getCouponIds(), Long.class);
+			userActivityView.setCouponViews(beanSearcher.searchAll(CouponView.class, MapUtils.builder().field(CouponView::getId, couponIds).op(Operator.InList).build()));
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult(userActivityView);
+	}
+
+}

+ 25 - 21
netflix-web/src/main/java/com/cyksj/web/controller/mirror/MirrorController.java

@@ -1,5 +1,6 @@
 package com.cyksj.web.controller.mirror;
 
+import cn.hutool.core.date.DateUtil;
 import cn.hutool.json.JSONObject;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
@@ -13,6 +14,7 @@ import com.cyksj.model.response.ConversationLimitResponse;
 import com.cyksj.model.views.ChatGptUserConversationRecordHistoryView;
 import com.cyksj.model.views.ChatGptUserView;
 import com.cyksj.model.views.ChatgptCarInfoView;
+import com.cyksj.model.views.ChatgptConversionLimitView;
 import com.cyksj.service.chatgpt.ChatGptAccountService;
 import com.cyksj.service.midjourney.MidjourneyAccountService;
 import com.cyksj.web.util.StpUserUtil;
@@ -29,7 +31,10 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.io.OutputStream;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.time.LocalDateTime;
+import java.util.Date;
 import java.util.Set;
 
 /**
@@ -127,7 +132,7 @@ public class MirrorController {
      * 会话限制
      */
     @RequestMapping("/gpt/conversation/limit")
-    public void conversationLimit(@RequestParam(value = "isCar", defaultValue = "false") Boolean isCar, @RequestBody ConversationRequest conversationRequest) {
+    public ChatgptConversionLimitView conversationLimit(@RequestParam(value = "isCar", defaultValue = "false") Boolean isCar, @RequestBody ConversationRequest conversationRequest) {
         //1.从request获取请求头Authorization 并取 值内 'Bearer ' 后的值为usertoken
         String authorization = request.getHeader("Authorization");
         String carid = request.getHeader("Carid");
@@ -144,34 +149,26 @@ public class MirrorController {
             //text-davinci-002-render-sha 3.5
             ConversationLimitResponse conversationLimitResponse = chatGptAccountService.conversationLimit(userToken, conversationRequest.getModel(), conversationRequest.getCarId(), user, isCar);
 
-            OutputStream out = null;
-            String messgae = "";
             if (conversationLimitResponse.isLimited()) {
-                response.setStatus(429);
-                String json = "{\"detail\":{\"message\":\"您的账号已达到GPT-4的使用上限。您现在可以继续使用默认模型,或者重试在\",\"code\":\"model_cap_exceeded\",\"clears_in\":2687}}";
-                JSONObject res = new JSONObject(json);
-                res.putOpt("clears_in", conversationLimitResponse.getNextAvailableTime() / 1000);
-                messgae = res.toString();
+                response.setStatus(400);
+                //String json = "{\"detail\":{\"message\":\"您的账号已达到GPT-4的使用上限。您现在可以继续使用默认模型,或者重试在\",\"code\":\"model_cap_exceeded\",\"clears_in\":2687}}";
+                ChatgptConversionLimitView chatgptConversionLimitView = new ChatgptConversionLimitView();
+                ChatgptConversionLimitView.Detail detail = new ChatgptConversionLimitView.Detail();
+                detail.setMessage("您目前的套餐已达到GPT-4的使用上限。您可以继续使用3.5,预计 " + DateUtil.format(new Date(conversationLimitResponse.getNextAvailableTime()), "yyyy-MM-dd HH:mm:ss") + " 恢复");
+                chatgptConversionLimitView.setDetail(detail);
+                return chatgptConversionLimitView;
             } else {
                 response.setStatus(200);
+                //记录提问时间,车次,标题和模型
+                TASK_EXECUTOR.execute(() -> {
+                    chatGptAccountService.saveConversationRecord(userToken, conversationRequest);
+                });
             }
             //5.获取 conversationRequest 中的model 字段,判断是否为 gpt-4 如果为gpt-4 执行 查看是否达到限制方法
             //6.如果达到限制,返回状态码 429 并返回文本 xxx
-            try {
-                out = response.getOutputStream();
-                IoKit.write(messgae, out);
-            } catch (Throwable e) {
-                log.error("conversationLimit write response error", e);
-            } finally {
-                IoKit.close(out);
-            }
         }
 
-        //记录提问时间,车次,标题和模型
-        TASK_EXECUTOR.execute(() -> {
-            chatGptAccountService.saveConversationRecord(userToken, conversationRequest);
-        });
-        response.setStatus(200);
+        return new ChatgptConversionLimitView();
     }
 
 
@@ -190,6 +187,13 @@ public class MirrorController {
             throw BusinessRuntimeException.getInstance("您还未购买车票");
         }
         Set<ChatgptCarInfoView> carInfoList = chatGptAccountService.getCarInfoList(carChatGptUser.getUserToken(),10, isPlus);
+        for (ChatgptCarInfoView chatgptCarInfoView : carInfoList) {
+            Double score = BigDecimal.valueOf(chatgptCarInfoView.getScore()).multiply(BigDecimal.valueOf(0.5)).setScale(0, RoundingMode.DOWN).doubleValue();
+            chatgptCarInfoView.setScore(score);
+            if (!"停运".equals(chatgptCarInfoView.getStatus())) {
+                chatgptCarInfoView.setStatus(score >= 50 ? "繁忙" : "空闲");
+            }
+        }
         return GatewayResponse.SUCCESS.newBuilder().toResult(carInfoList);
     }
 

Неке датотеке нису приказане због велике количине промена