zoujiajian před 2 roky
rodič
revize
bc74854200
20 změnil soubory, kde provedl 958 přidání a 223 odebrání
  1. 5 0
      netflix-common/src/main/java/com/cyksj/common/constant/Constant.java
  2. 17 0
      netflix-dao/src/main/java/com/cyksj/mapper/AccountBlockedReplaceRecordMapper.java
  3. 23 1
      netflix-dao/src/main/java/com/cyksj/model/entity/Account.java
  4. 50 0
      netflix-dao/src/main/java/com/cyksj/model/entity/AccountBlockedReplaceRecord.java
  5. 25 0
      netflix-dao/src/main/java/com/cyksj/model/excel/ExcelBannedAccountData.java
  6. 3 0
      netflix-dao/src/main/java/com/cyksj/model/excel/ExcelImportAccountData.java
  7. 27 0
      netflix-dao/src/main/java/com/cyksj/model/excel/ExcelPrepareAccountData.java
  8. 28 1
      netflix-dao/src/main/java/com/cyksj/model/manage/views/AccountView.java
  9. 0 2
      netflix-dao/src/main/java/com/cyksj/model/request/RenewTimeUpReq.java
  10. 116 0
      netflix-dao/src/main/java/com/cyksj/model/views/AccountDisableView.java
  11. 13 0
      netflix-dao/src/main/resources/mapper/AccountBlockedReplaceRecordMapper.xml
  12. 11 0
      netflix-service/src/main/java/com/cyksj/service/mange/AccountCommonService.java
  13. 2 0
      netflix-service/src/main/java/com/cyksj/service/mange/CmsAccountService.java
  14. 2 0
      netflix-service/src/main/java/com/cyksj/service/mange/CmsGroupService.java
  15. 37 0
      netflix-service/src/main/java/com/cyksj/service/mange/account/AccountCommonServiceImpl.java
  16. 33 0
      netflix-service/src/main/java/com/cyksj/service/mange/account/CmsAccountServiceImpl.java
  17. 33 0
      netflix-service/src/main/java/com/cyksj/service/mange/group/CmsGroupServiceImpl.java
  18. 11 8
      netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupsRelationNetflixServiceImpl.java
  19. 521 210
      netflix-web/src/main/java/com/cyksj/web/controller/manage/account/CmsAccountController.java
  20. 1 1
      pom.xml

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

@@ -139,4 +139,9 @@ public interface Constant {
 	 * 电影域名
 	 */
 	String ZHAOJU_MOVIES = "https://zhaoju666.com";
+
+	/**
+	 * GPT 平台账号重复
+	 */
+	List<Long> GPT_GOODS_IDS = List.of(18l, 29l, 30l);
 }

+ 17 - 0
netflix-dao/src/main/java/com/cyksj/mapper/AccountBlockedReplaceRecordMapper.java

@@ -0,0 +1,17 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.AccountBlockedReplaceRecord;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 项目名: netflix-job
+ * 文件名: AccountBlockedReplaceRecordMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/1/16 16:39
+ */
+public interface AccountBlockedReplaceRecordMapper extends BaseMapper<AccountBlockedReplaceRecord> {
+	void batchInsert(@Param("list") List<AccountBlockedReplaceRecord> list);
+}

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

@@ -21,6 +21,8 @@ public class Account extends BaseEntity {
 
     private String password;
 
+    private Boolean isMonth;
+
     private Long goodsId;
 
     private String bankCard;
@@ -54,6 +56,11 @@ public class Account extends BaseEntity {
      */
     private String apiKey;
 
+    /**
+     * chatGpt 邮箱密码
+     */
+    private String gptEmailPwd;
+
     /**
      * 辅助邮箱
      */
@@ -85,4 +92,19 @@ public class Account extends BaseEntity {
      * gpt accesToken
      */
     private String gptRefreshToken;
-}
+
+    /**
+     * 备用账号类型sku_ids
+     */
+    private String preSkuIds;
+
+    /**
+     * 类型 1通用 2备用
+     */
+    private Integer type;
+
+    /**
+     * 账号是否禁用
+     */
+    private Boolean isDisable;
+}

+ 50 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/AccountBlockedReplaceRecord.java

@@ -0,0 +1,50 @@
+package com.cyksj.model.entity;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * 项目名: netflix-job
+ * 文件名: AccountBlockedReplaceRecord
+ * 创建者: JavaZou
+ * 创建时间:2024/1/16 16:37
+ */
+@Getter
+@Setter
+@SearchBean(tables = "account_blocked_replace_record ar left join goods_don g on g.id = ar.goods_id")
+public class AccountBlockedReplaceRecord {
+
+
+	@DbField("ar.id")
+	private Long id;
+
+	@DbField("ar.account")
+	private String account;
+
+	@DbField("ar.goods_id")
+	private Long goodsId;
+
+	@DbField("a.title")
+	@TableField(exist = false)
+	private String title;
+
+	/**
+	 * 创建时间
+	 */
+	@TableField(fill = FieldFill.INSERT)
+	@DbField("ar.created_time")
+	private Date createdTime;
+
+	/**
+	 * 修改时间
+	 */
+	@TableField(fill = FieldFill.INSERT_UPDATE)
+	@DbField("ar.update_time")
+	private Date updateTime;
+}

+ 25 - 0
netflix-dao/src/main/java/com/cyksj/model/excel/ExcelBannedAccountData.java

@@ -0,0 +1,25 @@
+package com.cyksj.model.excel;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: ExcelBannedAccountData
+ * 创建者: JavaZou
+ * 创建时间:2023/10/7 15:35
+ */
+@Getter
+@Setter
+public class ExcelBannedAccountData {
+
+	@ExcelProperty("原账号")
+	private String oldAccount;
+
+	@ExcelProperty("新账号")
+	private String account;
+
+	@ExcelProperty("新账号密码")
+	private String password;
+}

+ 3 - 0
netflix-dao/src/main/java/com/cyksj/model/excel/ExcelImportAccountData.java

@@ -27,4 +27,7 @@ public class ExcelImportAccountData {
 
 	@ExcelProperty("到期时间")
 	private String expiryTime;
+
+	@ExcelProperty("是否月抛")
+	private String isMonth;
 }

+ 27 - 0
netflix-dao/src/main/java/com/cyksj/model/excel/ExcelPrepareAccountData.java

@@ -0,0 +1,27 @@
+package com.cyksj.model.excel;
+
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class ExcelPrepareAccountData {
+
+    @ExcelProperty("账号")
+    private String account;
+
+    /**
+     * 省份
+     */
+    @ExcelProperty("密码")
+    private String password;
+
+
+    /**
+     * 银行卡号
+     */
+    @ExcelProperty("银行卡号")
+    private String bankCard;
+}

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

@@ -40,12 +40,21 @@ public class AccountView {
     @DbField("a.account")
     private String account;
 
+    @DbIgnore
+    private String emailPassword;
+
     @DbField("a.password")
     private String password;
 
+    @DbField("a.is_month")
+    private Boolean isMonth;
+
     @DbField("a.api_key")
     private String apiKey;
 
+    @DbField("a.gpt_email_pwd")
+    private String gptEmailPwd;
+
     @DbField("a.verify_codes")
     private String verifyCodes;
 
@@ -109,6 +118,9 @@ public class AccountView {
     @DbField("gdk.id")
     private Long skuId;
 
+    @DbField("gdk.is_mirror")
+    private Boolean isMirror;
+
     @DbField("a.gpt_refresh_token")
     private String gptRefreshToken;
 
@@ -118,6 +130,9 @@ public class AccountView {
     @DbField("gdk.spec_val")
     private String specVal;
 
+    @DbField("a.created_time")
+    private Date createdTime;
+
     //@DbField("select count(ur.id) from user_ticket_cleared_record ur where ur.account_id = a.id and deleted is true and source = 'self' :yesTime:")
     @DbIgnore
     private Integer expiryCount;
@@ -137,4 +152,16 @@ public class AccountView {
 
     @DbIgnore
     private Date lastUpdatePwdDate;
-}
+
+    @DbField("a.pre_sku_ids")
+    private String preSkuIds;
+
+    @DbField("a.type")
+    private Integer accountType;
+
+    @DbIgnore
+    private Boolean isMjMirror;
+
+    @DbField("a.is_disable")
+    private Boolean isDisable;
+}

+ 0 - 2
netflix-dao/src/main/java/com/cyksj/model/request/RenewTimeUpReq.java

@@ -3,7 +3,6 @@ package com.cyksj.model.request;
 import lombok.Getter;
 import lombok.Setter;
 
-import javax.validation.constraints.Min;
 import javax.validation.constraints.NotNull;
 
 /*
@@ -25,7 +24,6 @@ public class RenewTimeUpReq {
 	 * 增加天数
 	 */
 	@NotNull(message = "天数不为空")
-	@Min(value = 1)
 	private Integer days;
 
 	/**

+ 116 - 0
netflix-dao/src/main/java/com/cyksj/model/views/AccountDisableView.java

@@ -0,0 +1,116 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.GroupsTrips;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: AccountDisableView
+ * 创建者: JavaZou
+ * 创建时间:2024/7/1 16:29
+ */
+@Getter
+@Setter
+@SearchBean(tables = "account a left join goods_don g on a.goods_id = g.id " +
+		"left join groups_trips gt on gt.account_id = a.id " +
+		"left join goods_don_sku gdk on gdk.id = gt.sku_id")
+public class AccountDisableView {
+	@DbField("a.id")
+	private Long id;
+
+	@DbField("g.id")
+	private Long goodsId;
+
+	@DbField("g.title")
+	private String title;
+
+	@DbField("g.second_type")
+	private Integer goodsSecondType;
+
+	@DbField("a.bank_card")
+	private String bankCard;
+
+	@DbField("a.account")
+	private String account;
+
+	@DbField("a.password")
+	private String password;
+
+	@DbField("a.is_month")
+	private Boolean isMonth;
+
+	@DbField("a.api_key")
+	private String apiKey;
+
+	@DbField("a.gpt_email_pwd")
+	private String gptEmailPwd;
+
+	@DbField("a.verify_codes")
+	private String verifyCodes;
+
+	@DbField("a.api_secret")
+	private String apiSecret;
+
+	@DbField("a.start_time")
+	private Date startTime;
+
+	@DbField("a.expiry_time")
+	private Date expiryTime;
+
+	@DbField("a.amount")
+	private BigDecimal amount;
+
+	/**
+	 * 国区id
+	 */
+	@DbField("a.cn_account")
+	private String cnAccount;
+
+	/**
+	 * 美区id
+	 */
+	@DbField("a.us_account")
+	private String usAccount;
+
+	@DbField("a.customer_service_id")
+	private Long customerServiceId;
+
+	@DbField("a.secret")
+	private String secret;
+
+	@DbField("gt.id")
+	private Long groupsId;
+
+	@DbField("gt.status")
+	private GroupsTrips.Status gtStatus;
+
+	/**
+	 * 账号备注
+	 */
+	@DbField("a.remark")
+	private String remark;
+
+	@DbField("a.email")
+	private String email;
+
+	@DbField("gdk.id")
+	private Long skuId;
+
+	/**
+	 * 规格
+	 */
+	@DbField("gdk.spec_val")
+	private String specVal;
+
+	@DbField("a.created_time")
+	private Date createdTime;
+
+	@DbField("a.is_disable")
+	private Boolean isDisable;
+}

+ 13 - 0
netflix-dao/src/main/resources/mapper/AccountBlockedReplaceRecordMapper.xml

@@ -0,0 +1,13 @@
+<?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.AccountBlockedReplaceRecordMapper">
+
+    <insert id="batchInsert">
+        insert ignore into
+        account_blocked_replace_record(`account`,`goods_id`,`created_time`,`update_time`)
+        values
+        <foreach collection="list" item="item" separator=",">
+            (#{item.account},#{item.goodsId},now(),now())
+        </foreach>
+    </insert>
+</mapper>

+ 11 - 0
netflix-service/src/main/java/com/cyksj/service/mange/AccountCommonService.java

@@ -0,0 +1,11 @@
+package com.cyksj.service.mange;
+
+/*
+ *项目名: netflix
+ *文件名: AccountCommonService
+ *创建者: JavaZou
+ *创建时间:2023/8/16 17:12
+ */
+public interface AccountCommonService {
+	Boolean checkIsDupAccount(Long goodsId, String account);
+}

+ 2 - 0
netflix-service/src/main/java/com/cyksj/service/mange/CmsAccountService.java

@@ -51,4 +51,6 @@ public interface CmsAccountService extends IService<Account> {
 	void analysisAmericaAppidAccount(Long goodsId, Long skuId, List<Object> accountList);
 
 	void readFileAndImportEmail(MultipartFile file) throws Exception;
+
+	void batchImportBlockedAccount(Long goodsId, List<Object> accountBlockedList);
 }

+ 2 - 0
netflix-service/src/main/java/com/cyksj/service/mange/CmsGroupService.java

@@ -17,4 +17,6 @@ public interface CmsGroupService extends IService<GroupsTrips> {
     void setAccount(GroupsTrips groupsTrips) throws Exception;
 
     void replaceTripsAccount(ReplaceTripsAccountReq req);
+
+	void sendChangeAccountMsg(Long groupsId, Long goodsId, String account);
 }

+ 37 - 0
netflix-service/src/main/java/com/cyksj/service/mange/account/AccountCommonServiceImpl.java

@@ -0,0 +1,37 @@
+package com.cyksj.service.mange.account;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.constant.Constant;
+import com.cyksj.mapper.AccountMapper;
+import com.cyksj.model.entity.Account;
+import com.cyksj.service.mange.AccountCommonService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+/*
+ *项目名: netflix
+ *文件名: AccountCommonServiceImpl
+ *创建者: JavaZou
+ *创建时间:2023/8/16 17:12
+ */
+@Service
+@RequiredArgsConstructor
+public class AccountCommonServiceImpl implements AccountCommonService {
+
+	private final AccountMapper accountMapper;
+
+	@Override
+	public Boolean checkIsDupAccount(Long goodsId, String account) {
+		LambdaQueryWrapper<Account> wrapper = Wrappers.lambdaQuery(Account.class)
+				.eq(Account::getAccount, account);
+		if (Constant.GPT_GOODS_IDS.contains(goodsId)) {
+			wrapper.in(Account::getGoodsId, Constant.GPT_GOODS_IDS);
+		} else {
+			wrapper.eq(Account::getGoodsId, goodsId);
+		}
+		int count = accountMapper.selectCount(wrapper);
+		if (count > 0) return true;
+		return false;
+	}
+}

+ 33 - 0
netflix-service/src/main/java/com/cyksj/service/mange/account/CmsAccountServiceImpl.java

@@ -1,9 +1,11 @@
 package com.cyksj.service.mange.account;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.lang.Validator;
 import cn.hutool.core.util.RandomUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Assert;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -11,8 +13,10 @@ import com.cyksj.common.constant.Constant;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.Jsons;
 import com.cyksj.common.util.StringUtil;
+import com.cyksj.mapper.AccountBlockedReplaceRecordMapper;
 import com.cyksj.mapper.AccountMapper;
 import com.cyksj.mapper.AccountUpdatePasswordRecordMapper;
+import com.cyksj.mapper.GoodsDonMapper;
 import com.cyksj.mapper.manage.AutoUpdateAccountPwdLogMapper;
 import com.cyksj.mapper.manage.cms.CmsUserMapper;
 import com.cyksj.mapper.sys.SysEmailMapper;
@@ -66,6 +70,10 @@ public class CmsAccountServiceImpl extends ServiceImpl<AccountMapper, Account> i
 
 	private final SysConfigService sysConfigService;
 
+	private final GoodsDonMapper goodsDonMapper;
+
+	private final AccountBlockedReplaceRecordMapper accountBlockedReplaceRecordMapper;
+
 	@Override
 	public IPage<ExpiredAccountDataView> getExpiredAccountView(Boolean isCorpWx, String customerService, Long goodsId, Long skuId, String account, Boolean renewStatus, Boolean handleStatus, String cnAccount, String usAccount, Integer userId, String startTime, String endTime, String now, Long offset, Long limit) {
 		return accountMapper.getExpiredAccountView(isCorpWx, customerService, goodsId, skuId, account, renewStatus, handleStatus, cnAccount, usAccount, userId, startTime, endTime, now, new Page<>(offset, limit));
@@ -231,6 +239,31 @@ public class CmsAccountServiceImpl extends ServiceImpl<AccountMapper, Account> i
 		System.out.println(Jsons.toJson(error));
 	}
 
+	@Override
+	public void batchImportBlockedAccount(Long goodsId, List<Object> accountBlockedList) {
+		GoodsDon goodsDon = goodsDonMapper.selectById(goodsId);
+		Assert.notNull(goodsDon, "平台不存在");
+		List<AccountBlockedReplaceRecord> list = new ArrayList<>();
+		accountBlockedList.forEach(accountBlocked->{
+			Map<String, Object> map = Jsons.toMap(accountBlocked);
+			String blockedAccount = map.get("0").toString();
+			if (!Validator.isEmail(blockedAccount)) {
+				return;
+			}
+			AccountBlockedReplaceRecord accountBlockedReplaceRecord = new AccountBlockedReplaceRecord();
+			accountBlockedReplaceRecord.setGoodsId(goodsId);
+			accountBlockedReplaceRecord.setAccount(blockedAccount);
+			list.add(accountBlockedReplaceRecord);
+			if (list.size() == 400) {
+				accountBlockedReplaceRecordMapper.batchInsert(list);
+				list.clear();
+			}
+		});
+		if (list.size() > 0) {
+			accountBlockedReplaceRecordMapper.batchInsert(list);
+		}
+	}
+
 	/**
 	 *
 	 * @param goodsId

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

@@ -1,5 +1,6 @@
 package com.cyksj.service.mange.group;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.date.DateField;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
@@ -16,6 +17,7 @@ import com.cyksj.mapper.manage.DelGroupsTripsRecordMapper;
 import com.cyksj.mapper.manage.GroupsTripsAccountReplaceRecordMapper;
 import com.cyksj.mapper.manage.cms.CmsUserMapper;
 import com.cyksj.model.entity.*;
+import com.cyksj.model.manage.views.GroupsRelationView;
 import com.cyksj.model.request.ReplaceTripsAccountReq;
 import com.cyksj.model.views.GroupsAccountView;
 import com.cyksj.redis.RedisService;
@@ -341,4 +343,35 @@ public class CmsGroupServiceImpl extends ServiceImpl<GroupsMapper,GroupsTrips> i
             }
         });
     }
+
+    @Override
+    public void sendChangeAccountMsg(Long groupsId, Long goodsId, String account) {
+        GoodsDon goodsDon = goodsDonMapper.selectById(goodsId);
+        String title = goodsDon != null ? goodsDon.getTitle() : "车票";
+        DateTime now = DateTime.now();
+        Boolean isPrd = envCommonService.isPrdEnv();
+        List<GroupsRelationView> groupsRelations = beanSearcher.searchAll(GroupsRelationView.class, MapUtils.builder().field(GroupsRelationView::getGroupsId, groupsId).build());
+        if (CollUtil.isEmpty(groupsRelations)) {
+            return;
+        }
+        groupsRelations.forEach(relation -> {
+            if (relation.getExpiryTime() == null) {
+                return;
+            }
+            //账号有效期小于5天的人,不发账号替换/改密码短信提醒
+            if (now.after(DateUtil.offsetDay(relation.getExpiryTime(), -5))) {
+                return;
+            }
+            //去掉GPT过滤平台
+            if (Constant.CHANGE_ACCOUNT_PWD_FILTER_GIDS.get(1) == goodsId) {
+                return;
+            }
+            if (relation.getUserId() != 0 && isPrd) {
+                try {
+                    smsService.sendSmsToRelationUser(relation.getUserId(), String.format(Constant.CHANGE_GROUPS_TRIPS_ACCOUNT, title, envCommonService.getDomain()));
+                } catch (Exception e) {
+                }
+            }
+        });
+    }
 }

+ 11 - 8
netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupsRelationNetflixServiceImpl.java

@@ -155,14 +155,17 @@ public class GroupsRelationNetflixServiceImpl implements GroupsRelationNetflixSe
 	 */
 	@Override
 	public void timingSetNetflix(Integer num, String nickname, String account, String password, Date expiryTime) {
-		String key = RedisService.key.NETFLIX_SET_LIMIT_TIME.getName();
-		if (!redisService.setNx(key, 1L, 30L)) {
-			jobManager.addJob(30001, () -> {
-				timingSetNetflix(num, nickname, account, password, expiryTime);
-			});
-		} else {
-			setNetflixSeatNum(num, nickname, account, password, expiryTime, null);
-			log.info("当前时间:{}开始调用设置奈飞座位信息接口", DateTime.now());
+		try {
+			String key = RedisService.key.NETFLIX_SET_LIMIT_TIME.getName();
+			if (!redisService.setNx(key, 1L, 30L)) {
+				jobManager.addJob(30001, () -> {
+					timingSetNetflix(num, nickname, account, password, expiryTime);
+				});
+			} else {
+				setNetflixSeatNum(num, nickname, account, password, expiryTime, null);
+				log.info("当前时间:{}开始调用设置奈飞座位信息接口", DateTime.now());
+			}
+		} catch (Exception e) {
 		}
 	}
 }

+ 521 - 210
netflix-web/src/main/java/com/cyksj/web/controller/manage/account/CmsAccountController.java

@@ -9,11 +9,15 @@ import com.alibaba.excel.EasyExcel;
 import com.alibaba.excel.context.AnalysisContext;
 import com.alibaba.excel.event.AnalysisEventListener;
 import com.alibaba.excel.support.ExcelTypeEnum;
+import com.baomidou.mybatisplus.core.toolkit.Assert;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.annotation.Log;
 import com.cyksj.common.annotation.NoSubmit;
 import com.cyksj.common.constant.Constant;
 import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
+import com.cyksj.common.util.J11HttpC;
+import com.cyksj.common.util.Jsons;
 import com.cyksj.dto.RedisKey;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.BusinessType;
@@ -22,10 +26,7 @@ import com.cyksj.mapper.*;
 import com.cyksj.mapper.manage.cms.CmsUserMapper;
 import com.cyksj.mapper.sys.SysEmailMapper;
 import com.cyksj.model.entity.*;
-import com.cyksj.model.excel.ExcelDoubleVerifyAccountData;
-import com.cyksj.model.excel.ExcelImportAccountData;
-import com.cyksj.model.excel.ExcelImportDoubleVerifyAccountData;
-import com.cyksj.model.excel.ExcelManageAccountData;
+import com.cyksj.model.excel.*;
 import com.cyksj.model.manage.request.ReqAccountIncrExpiryTime;
 import com.cyksj.model.manage.views.AccountView;
 import com.cyksj.model.manage.views.GroupsRelationView;
@@ -33,6 +34,7 @@ import com.cyksj.model.response.ExpiredAccountRep;
 import com.cyksj.model.response.OrderDonAccountRep;
 import com.cyksj.model.views.*;
 import com.cyksj.redis.RedisService;
+import com.cyksj.service.mange.AccountCommonService;
 import com.cyksj.service.mange.CmsAccountService;
 import com.cyksj.service.mange.CmsGroupService;
 import com.cyksj.service.mange.cms.CmsUserManager;
@@ -57,6 +59,7 @@ import org.springframework.web.multipart.MultipartFile;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
+import java.net.http.HttpResponse;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -98,14 +101,20 @@ public class CmsAccountController {
 
 	private final AccountUpdatePasswordRecordMapper accountUpdatePasswordRecordMapper;
 
+	private final AccountCommonService accountCommonService;
+
 	private final RedisService redisService;
 
+	private final GoodsDonSkuMapper goodsDonSkuMapper;
+
 	private final SysEmailMapper sysEmailMapper;
 
-	private final GoodsDonSkuMapper goodsDonSkuMapper;
+	private final AccountBlockedReplaceRecordMapper accountBlockedReplaceRecordMapper;
+
+	private static final GlobalThreadPoolTaskExecutor TASK_EXECUTOR = GlobalThreadPoolTaskExecutor.getInstance();
 
 	@GetMapping("/get")
-	public Result<SearchResult<AccountView>> get(Long userId, String showId, String nickName, String submitAccount, String expiryStartTime, String expiryEndTime, Boolean expiredAll, Boolean existsExpired, Boolean existsExpiredToday, Integer noChangeMonths) {
+	public Result<SearchResult<AccountView>> get(Long userId, String showId, String nickName, String submitAccount, String expiryStartTime, String expiryEndTime, Boolean expiredAll, Boolean existsExpired, Boolean existsExpiredToday, Integer noChangeMonths, Boolean isMjMirror) {
 		MapBuilder mapBuilder = MapUtils.flatBuilder(request.getParameterMap());
 		if (StrUtil.isNotEmpty(expiryStartTime) || StrUtil.isNotEmpty(expiryEndTime)) {
 			mapBuilder.field(AccountView::getExpiryTime, expiryStartTime, expiryEndTime)
@@ -151,6 +160,12 @@ public class CmsAccountController {
 				extra_sql += String.format(" (select min(expiry_time) from (select gt.id from groups_trips where account_id = a.id) gt inner join groups_relation gr on gr.groups_id = gt.id) > '%s'", endOfDay);
 			}
 		}
+		if (isMjMirror != null) {
+			if (StrUtil.isNotEmpty(extra_sql)) {
+				extra_sql += " and";
+			}
+			extra_sql += String.format(" %s (select 1 from midjourney_account ma where ma.account_id = a.id limit 1)", isMjMirror ? "EXISTS" : "NOT EXISTS");
+		}
 		if (StrUtil.isNotEmpty(extra_sql)) {
 			mapBuilder.put("extra_sql", extra_sql);
 		}
@@ -179,76 +194,83 @@ public class CmsAccountController {
 			}
 			Integer expiryCount = groupsMapper.countExpiredNum(accountView.getId());
 			accountView.setExpiryCount(expiryCount);
+
+			if (StrUtil.isNotEmpty(accountView.getAccount())) {
+				Optional.ofNullable(sysEmailMapper.selectOne(Wrappers.lambdaQuery(SysEmail.class)
+								.eq(SysEmail::getEmail, accountView.getAccount()).select(SysEmail::getPassword)
+								.last("limit 1")))
+						.ifPresent(email -> accountView.setEmailPassword(email.getPassword()));
+			}
 		});
 		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
 	}
 
-    /**
-     * 导出账号
-     */
-    @GetMapping("/export/account")
-    @Log(module = "平台管理/导出账号", businessType = BusinessType.EXPORT, isSaveRequestData = true)
-    public void exportAccount(Long userId, String showId, String nickName, String submitAccount, String expiryStartTime, String expiryEndTime, Boolean expiredAll, Boolean existsExpired, Boolean existsExpiredToday, Integer noChangeMonths, HttpServletResponse response) {
-        MapBuilder mapBuilder = MapUtils.flatBuilder(request.getParameterMap());
-        if (StrUtil.isNotEmpty(expiryStartTime) || StrUtil.isNotEmpty(expiryEndTime)) {
-            mapBuilder.field(ExcelManageAccountData::getExpiryTime, expiryStartTime, expiryEndTime)
-                    .op(Operator.Between);
-        }
-	    if (StrUtil.isNotEmpty(showId)) {
-		    userId = userMapper.getUserIdByShowId(showId);
-	    }
-
-        if (userId != null || StringUtils.isNotBlank(nickName) || StringUtils.isNotBlank(submitAccount)) {
-            List<Long> accountIds = homeGroupMapper.getAccountIdsByUserIdOrNickNameOrSubmitAccount(userId, nickName, submitAccount);
-            if (accountIds.isEmpty()) {
-                throw BusinessRuntimeException.getInstance("暂无数据!");
-            }
-
-            mapBuilder.field(ExcelManageAccountData::getId, accountIds).op(Operator.InList);
-        }
-	    String extra_sql = StrUtil.EMPTY;
-	    if (expiredAll != null && expiredAll) {
-		    extra_sql += "(if((select count(ur.id) from user_ticket_cleared_record ur where ur.account_id = a.id and deleted is true and source = 'self')>=3,true,false)) = 1";
-	    }
-
-	    if (noChangeMonths != null) {
-		    DateTime pastMonth = DateUtil.offsetMonth(DateTime.now(), -noChangeMonths);
-		    List<Long> accountIds = accountUpdatePasswordRecordMapper.selectPasswordNotChangedThePastMonthAccountId(pastMonth);
-		    mapBuilder.field(AccountView::getId, accountIds).op(Operator.InList);
-	    }
-
-	    if (existsExpired != null && existsExpired) {
-		    if (StrUtil.isNotEmpty(extra_sql)) {
-			    extra_sql += " and";
-		    }
-		    extra_sql += "(select count(ur.id) from user_ticket_cleared_record ur where ur.account_id = a.id and deleted is true and source = 'self') > 0";
-	    }
-	    if (existsExpiredToday != null) {
-		    DateTime endOfDay = DateUtil.endOfDay(DateTime.now());
-		    if (StrUtil.isNotEmpty(extra_sql)) {
-			    extra_sql += " and";
-		    }
-		    if (existsExpiredToday) {
-			    extra_sql += String.format(" (select min(expiry_time) from (select gt.id from groups_trips where account_id = a.id) gt inner join groups_relation gr on gr.groups_id = gt.id) <= '%s'", endOfDay);
-		    } else {
-			    extra_sql += String.format(" (select min(expiry_time) from (select gt.id from groups_trips where account_id = a.id) gt inner join groups_relation gr on gr.groups_id = gt.id) > '%s'", endOfDay);
-		    }
-	    }
-	    if (StrUtil.isNotEmpty(extra_sql)) {
-		    mapBuilder.put("extra_sql", extra_sql);
-	    }
-	    List<ExcelManageAccountData> list = beanSearcher.searchAll(ExcelManageAccountData.class, mapBuilder.build());
-
-	    EasyExcelUtils.createExcelStreamMutilByEasyExcel(response, ExcelManageAccountData.class, list, "账号列表", "账号列表", ExcelTypeEnum.XLSX, null);
-    }
-
-    /**
-     * 下载批量修改密码模板
-     */
-    @GetMapping("/get/account/template")
-    public void getAccountTemplate(HttpServletResponse response) {
-        EasyExcelUtils.createTemplateExcel(response, ExcelImportAccountData.class, "账号批量修改密码模板", "账号批量修改密码模板", ExcelTypeEnum.XLSX, null);
-    }
+	/**
+	 * 导出账号
+	 */
+	@GetMapping("/export/account")
+	@Log(module = "平台管理/导出账号", businessType = BusinessType.EXPORT, isSaveRequestData = true)
+	public void exportAccount(Long userId, String showId, String nickName, String submitAccount, String expiryStartTime, String expiryEndTime, Boolean expiredAll, Boolean existsExpired, Boolean existsExpiredToday, Integer noChangeMonths, HttpServletResponse response) {
+		MapBuilder mapBuilder = MapUtils.flatBuilder(request.getParameterMap());
+		if (StrUtil.isNotEmpty(expiryStartTime) || StrUtil.isNotEmpty(expiryEndTime)) {
+			mapBuilder.field(ExcelManageAccountData::getExpiryTime, expiryStartTime, expiryEndTime)
+					.op(Operator.Between);
+		}
+		if (StrUtil.isNotEmpty(showId)) {
+			userId = userMapper.getUserIdByShowId(showId);
+		}
+
+		if (userId != null || StringUtils.isNotBlank(nickName) || StringUtils.isNotBlank(submitAccount)) {
+			List<Long> accountIds = homeGroupMapper.getAccountIdsByUserIdOrNickNameOrSubmitAccount(userId, nickName, submitAccount);
+			if (accountIds.isEmpty()) {
+				throw BusinessRuntimeException.getInstance("暂无数据!");
+			}
+
+			mapBuilder.field(ExcelManageAccountData::getId, accountIds).op(Operator.InList);
+		}
+		String extra_sql = StrUtil.EMPTY;
+		if (expiredAll != null && expiredAll) {
+			extra_sql += "(if((select count(ur.id) from user_ticket_cleared_record ur where ur.account_id = a.id and deleted is true and source = 'self')>=3,true,false)) = 1";
+		}
+
+		if (noChangeMonths != null) {
+			DateTime pastMonth = DateUtil.offsetMonth(DateTime.now(), -noChangeMonths);
+			List<Long> accountIds = accountUpdatePasswordRecordMapper.selectPasswordNotChangedThePastMonthAccountId(pastMonth);
+			mapBuilder.field(AccountView::getId, accountIds).op(Operator.InList);
+		}
+
+		if (existsExpired != null && existsExpired) {
+			if (StrUtil.isNotEmpty(extra_sql)) {
+				extra_sql += " and";
+			}
+			extra_sql += "(select count(ur.id) from user_ticket_cleared_record ur where ur.account_id = a.id and deleted is true and source = 'self') > 0";
+		}
+		if (existsExpiredToday != null) {
+			DateTime endOfDay = DateUtil.endOfDay(DateTime.now());
+			if (StrUtil.isNotEmpty(extra_sql)) {
+				extra_sql += " and";
+			}
+			if (existsExpiredToday) {
+				extra_sql += String.format(" (select min(expiry_time) from (select gt.id from groups_trips where account_id = a.id) gt inner join groups_relation gr on gr.groups_id = gt.id) <= '%s'", endOfDay);
+			} else {
+				extra_sql += String.format(" (select min(expiry_time) from (select gt.id from groups_trips where account_id = a.id) gt inner join groups_relation gr on gr.groups_id = gt.id) > '%s'", endOfDay);
+			}
+		}
+		if (StrUtil.isNotEmpty(extra_sql)) {
+			mapBuilder.put("extra_sql", extra_sql);
+		}
+		List<ExcelManageAccountData> list = beanSearcher.searchAll(ExcelManageAccountData.class, mapBuilder.build());
+
+		EasyExcelUtils.createExcelStreamMutilByEasyExcel(response, ExcelManageAccountData.class, list, "账号列表", "账号列表", ExcelTypeEnum.XLSX, null);
+	}
+
+	/**
+	 * 下载批量修改密码模板
+	 */
+	@GetMapping("/get/account/template")
+	public void getAccountTemplate(HttpServletResponse response) {
+		EasyExcelUtils.createTemplateExcel(response, ExcelImportAccountData.class, "账号批量修改密码模板", "账号批量修改密码模板", ExcelTypeEnum.XLSX, null);
+	}
 
 	/**
 	 * 导入文件,修改密码
@@ -273,7 +295,7 @@ public class CmsAccountController {
 						}
 						String oldPwd = account.getPassword();
 						if (StrUtil.isNotBlank(data.getExpiryTime())) {
-							account.setExpiryTime(DateUtil.parse(data.getExpiryTime(), "yyyy-MM-dd HH:mm:ss"));
+							account.setExpiryTime(DateUtil.parse(data.getExpiryTime()));
 							flag = true;
 						}
 						String new_pass = data.getPassword();
@@ -338,30 +360,79 @@ public class CmsAccountController {
 		return GatewayResponse.SUCCESS.newBuilder().toResult();
 	}
 
-    @PostMapping("/post")
-    @NoSubmit
-    @Transactional(rollbackFor = Throwable.class)
-    @Log(module = "平台管理/新增账号", businessType = BusinessType.POST, isSaveRequestData = true)
-    public Result<String> add(@RequestBody Account account){
+	@GetMapping("/test")
+	public Result<String> stest(MultipartFile file) throws IOException {
+		List<Object> objects = EasyExcel.read(file.getInputStream()).sheet().headRowNumber(0).doReadSync();
+
+		String url = "https://plus1.caifree.com/api?email=%s";
+		objects.forEach(e->{
+			Map<String, Object> map = Jsons.toMap(e);
+			String account = String.valueOf(map.get("0"));
+			if (StrUtil.isNotEmpty(account)) {
+				String formatUrl = String.format(url, account);
+				try {
+					HttpResponse<String> send = J11HttpC.custom()
+							.ofGet()
+							.url(formatUrl)
+							.send(HttpResponse.BodyHandlers.ofString());
+					System.out.println(send.body());
+				} catch (Exception exception) {
+
+				}
+			}
+
+		});
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	public static void main(String[] args) {
+		String url = "https://plus1.caifree.com/api?email=sentzb99@gmail.com";
+		try {
+			HttpResponse<String> send = J11HttpC.custom()
+					.ofGet()
+					.url(url)
+					.send(HttpResponse.BodyHandlers.ofString());
+			System.out.println(send.body());
+		} catch (Exception exception) {
+
+		}
+	}
+
+	@PostMapping("/post")
+	@NoSubmit
+	@Transactional(rollbackFor = Throwable.class)
+	@Log(module = "平台管理/新增账号", businessType = BusinessType.POST, isSaveRequestData = true)
+	public Result<String> add(@RequestBody Account account){
 		account.setAccount(account.getAccount().trim());
 		account.setPassword(account.getPassword().trim());
-	    //账号是否已经添加过
-	    if (!account.getAccount().contains("客服")) {
-		    int count = accountService.count(Wrappers.lambdaQuery(Account.class)
-				    .eq(Account::getAccount, account.getAccount())
-				    .eq(Account::getGoodsId, account.getGoodsId()));
-		    if (count > 0) {
-			    throw BusinessRuntimeException.getInstance("该平台下已生成该账号");
-		    }
-	    }
-        accountService.save(account);
-	    //自动配置车队
-	    GroupsTrips groupsTrips = new GroupsTrips();
-	    groupsTrips.setSkuId(account.getSkuId());
-	    groupsTrips.setAccountId(account.getId());
-	    cmsGroupService.issuance(groupsTrips, account.getVerifyCodes());
-        return GatewayResponse.SUCCESS.newBuilder().toResult();
-    }
+		//账号是否已经添加过
+		if (!account.getAccount().contains("客服")) {
+			if (accountCommonService.checkIsDupAccount(account.getGoodsId(), account.getAccount())) {
+				throw BusinessRuntimeException.getInstance("该平台下已生成该账号");
+			}
+		}
+		accountService.save(account);
+		if (account.getSkuId() != null) {
+			//自动配置车队
+			GroupsTrips groupsTrips = new GroupsTrips();
+
+			//限制每天新车队前3天 停车数量
+			Integer availableParkingNum = 0;
+			if (account.getSkuId() == 161l) {
+				availableParkingNum = 10;
+			}
+			if (account.getSkuId() == 178l) {
+				availableParkingNum = 4;
+			}
+			groupsTrips.setAvailableParkingNum(availableParkingNum);
+
+			groupsTrips.setSkuId(account.getSkuId());
+			groupsTrips.setAccountId(account.getId());
+			cmsGroupService.issuance(groupsTrips, account.getVerifyCodes());
+		}
+
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
 
 	/**
 	 * 获取导入账号模板
@@ -388,10 +459,7 @@ public class CmsAccountController {
 				if (StrUtil.isNotBlank(data.getAccount())) {
 					//账号是否已经添加过
 					if (!account.contains("客服")) {
-						int count = accountService.count(Wrappers.lambdaQuery(Account.class)
-								.eq(Account::getAccount, account)
-								.eq(Account::getGoodsId, goodsId));
-						if (count > 0) {
+						if (accountCommonService.checkIsDupAccount(goodsId, account)) {
 							log.info("该平台下:{}已生成该账号:{}", goodsId, account);
 							return;
 						}
@@ -402,18 +470,37 @@ public class CmsAccountController {
 					at.setGoodsId(goodsId);
 					at.setSkuId(skuId);
 					at.setBankCard(bankCard);
+					String isMonth = data.getIsMonth();
+					if (StrUtil.isNotBlank(isMonth)) {
+						at.setIsMonth(true);
+					}
 					if (StrUtil.isNotBlank(startTime)) {
-						at.setStartTime(DateUtil.parse(startTime, "yyyy-MM-dd HH:mm:ss"));
+						at.setStartTime(DateUtil.parse(startTime));
+					} else {
+						at.setStartTime(DateTime.now());
 					}
 					if (StrUtil.isNotBlank(expiryTime)) {
-						at.setExpiryTime(DateUtil.parse(expiryTime, "yyyy-MM-dd HH:mm:ss"));
+						at.setExpiryTime(DateUtil.parse(expiryTime));
+					} else {
+						at.setExpiryTime(DateUtil.offsetMonth(at.getStartTime(), 1));
 					}
 					accountService.save(at);
-					//自动配置车队
-					GroupsTrips groupsTrips = new GroupsTrips();
-					groupsTrips.setSkuId(at.getSkuId());
-					groupsTrips.setAccountId(at.getId());
-					cmsGroupService.issuance(groupsTrips, null);
+					if (at.getSkuId() != null) {
+						//自动配置车队
+						GroupsTrips groupsTrips = new GroupsTrips();
+						//限制每天新车队前3天 停车数量
+						Integer availableParkingNum = 0;
+						if (at.getSkuId() == 161l) {
+							availableParkingNum = 10;
+						}
+						if (at.getSkuId() == 178l) {
+							availableParkingNum = 4;
+						}
+						groupsTrips.setAvailableParkingNum(availableParkingNum);
+						groupsTrips.setSkuId(at.getSkuId());
+						groupsTrips.setAccountId(at.getId());
+						cmsGroupService.issuance(groupsTrips, null);
+					}
 				}
 			}
 
@@ -425,89 +512,86 @@ public class CmsAccountController {
 		return GatewayResponse.SUCCESS.newBuilder().toResult("导入账号成功");
 	}
 
-    @PutMapping("/update")
-    @Log(module = "平台管理/编辑账号", businessType = BusinessType.PUT, isSaveRequestData = true)
-    public Result<String> update(@RequestBody Account account){
-	    Account db = accountService.getById(account.getId());
-	    if (db == null) {
-		    throw BusinessRuntimeException.getInstance("该账号不存在");
-	    }
-	    Boolean isClear = false;
-	    String dbAccount = db.getAccount();
-	    long userId = StpAbroadUtil.getLoginIdAsLong();
-	    if (!db.getPassword().equals(account.getPassword())) {
-		    account.setCustomerServiceId(0l);
-		    accountService.saveRecord(userId, account.getId(), db.getPassword(), account.getPassword(), "操作编辑");
-		    
-		    //清空过期账号 逻辑删除
-		    userTicketClearedRecordMapper.update(null, Wrappers.lambdaUpdate(UserTicketClearedRecord.class)
-				    .set(UserTicketClearedRecord::getDeleted, false)
-				    .eq(UserTicketClearedRecord::getAccountId, account.getId()));
-		    isClear = true;
-	    }
-	    if (StrUtil.isNotBlank(account.getAccount())){
+	@PutMapping("/update")
+	@Log(module = "平台管理/编辑账号", businessType = BusinessType.PUT, isSaveRequestData = true)
+	public Result<String> update(@RequestBody Account account) throws Exception {
+		Account db = accountService.getById(account.getId());
+		if (db == null) {
+			throw BusinessRuntimeException.getInstance("该账号不存在");
+		}
+		Boolean isClear = false;
+		String dbAccount = db.getAccount();
+		long userId = StpAbroadUtil.getLoginIdAsLong();
+		if (!db.getPassword().equals(account.getPassword())) {
+			account.setCustomerServiceId(0l);
+			accountService.saveRecord(userId, account.getId(), db.getPassword(), account.getPassword(), "操作编辑");
+
+			//清空过期账号 逻辑删除
+			userTicketClearedRecordMapper.update(null, Wrappers.lambdaUpdate(UserTicketClearedRecord.class)
+					.set(UserTicketClearedRecord::getDeleted, false)
+					.eq(UserTicketClearedRecord::getAccountId, account.getId()));
+			isClear = true;
+		}
+		if (!db.getAccount().equals(account.getAccount())){
 			account.setAccount(account.getAccount().trim());
 			//账号是否已经添加过
 			if (!account.getAccount().contains("客服")) {
-				int count = accountService.count(Wrappers.lambdaQuery(Account.class)
-						.ne(Account::getId, account.getId())
-						.eq(Account::getAccount, account.getAccount())
-						.eq(Account::getGoodsId, account.getGoodsId()));
-				if (count > 0) {
+				if (accountCommonService.checkIsDupAccount(account.getGoodsId(), account.getAccount())) {
 					throw BusinessRuntimeException.getInstance("该平台下已生成该账号");
 				}
 			}
-		    if (!dbAccount.equals(account.getAccount())) {
-			    isClear = true;
-		    }
-		}
-	    if (StrUtil.isNotBlank(account.getPassword())){
-		    account.setPassword(account.getPassword().trim());
-	    }
-	    String verifyCodes = account.getVerifyCodes();
-	    if (StrUtil.isNotBlank(verifyCodes) && !StrUtil.equals(verifyCodes, db.getVerifyCodes())) {
-		    verifyCodes = verifyCodes.replaceAll("\n", "");
-		    String[] verifyCodesArray = verifyCodes.split("\\*");
-		    List<String> verifyCodeList = Arrays.stream(verifyCodesArray).filter(str -> StrUtil.isNotBlank(str)).map(str -> str.trim()).collect(Collectors.toList());
-		    List<GroupsRelationView> relationViews = beanSearcher.searchAll(GroupsRelationView.class, MapUtils.builder()
-				    .field(GroupsRelationView::getAccountId, account.getId())
-				    .onlySelect(GroupsRelationView::getId)
-				    .build());
-		    if (CollUtil.isNotEmpty(relationViews)) {
-			    for (int i = 0; i < verifyCodeList.size(); i++) {
-				    if (i < relationViews.size()) {
-					    GroupsRelationView groupsRelationView = relationViews.get(i);
-					    groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
-							    .set(GroupsRelation::getVerifyCode, verifyCodeList.get(i))
-							    .eq(GroupsRelation::getId, groupsRelationView.getId()));
-				    }
-			    }
-		    }
-	    }
-	    String apiSecret = account.getApiSecret();
-	    if (StrUtil.isNotBlank(apiSecret)) {
-		    doubleVerifyRecordMapper.update(null, Wrappers.lambdaUpdate(AccountDoubleVerifyRecord.class)
-				    .set(AccountDoubleVerifyRecord::getDeleted, false)
-				    .set(AccountDoubleVerifyRecord::getApiSecret, apiSecret)
-				    .eq(AccountDoubleVerifyRecord::getAccountId, account.getId()));
-	    }
-	    account.setStartTime(null);
-	    if (isClear){
-		    account.setGptRefreshToken(StrUtil.EMPTY);
-		    //清除gpt token
-		    redisService.del(RedisKey.CHATGPT_ACCESS_TOKEN + dbAccount);
-		    redisService.del(RedisService.key.CHAT_GPT_TOKEN_EXCEPTION_KEY.getName() + dbAccount);
-	    }
-	    //时间有效
-	    if (account.getExpiryTime() != null && account.getExpiryTime().after(DateTime.now())) {
-		    groupsMapper.update(null, Wrappers.lambdaUpdate(GroupsTrips.class)
-				    .set(GroupsTrips::getStatus, GroupsTrips.Status.validity)
-				    .eq(GroupsTrips::getAccountId, account.getId())
-				    .eq(GroupsTrips::getStatus, GroupsTrips.Status.down));
-	    }
-	    accountService.updateById(account);
-        return GatewayResponse.SUCCESS.newBuilder().toResult();
-    }
+			if (!dbAccount.equals(account.getAccount())) {
+				isClear = true;
+			}
+		}
+		if (StrUtil.isNotBlank(account.getPassword())){
+			account.setPassword(account.getPassword().trim());
+		}
+		String verifyCodes = account.getVerifyCodes();
+		if (StrUtil.isNotBlank(verifyCodes) && !StrUtil.equals(verifyCodes, db.getVerifyCodes())) {
+			verifyCodes = verifyCodes.replaceAll("\n", "");
+			String[] verifyCodesArray = verifyCodes.split("\\*");
+			List<String> verifyCodeList = Arrays.stream(verifyCodesArray).filter(str -> StrUtil.isNotBlank(str)).map(str -> str.trim()).collect(Collectors.toList());
+			List<GroupsRelationView> relationViews = beanSearcher.searchAll(GroupsRelationView.class, MapUtils.builder()
+					.field(GroupsRelationView::getAccountId, account.getId())
+					.onlySelect(GroupsRelationView::getId)
+					.build());
+			if (CollUtil.isNotEmpty(relationViews)) {
+				for (int i = 0; i < verifyCodeList.size(); i++) {
+					if (i < relationViews.size()) {
+						GroupsRelationView groupsRelationView = relationViews.get(i);
+						groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
+								.set(GroupsRelation::getVerifyCode, verifyCodeList.get(i))
+								.eq(GroupsRelation::getId, groupsRelationView.getId()));
+					}
+				}
+			}
+		}
+		String apiSecret = account.getApiSecret();
+		if (StrUtil.isNotBlank(apiSecret)) {
+			doubleVerifyRecordMapper.update(null, Wrappers.lambdaUpdate(AccountDoubleVerifyRecord.class)
+					.set(AccountDoubleVerifyRecord::getDeleted, false)
+					.set(AccountDoubleVerifyRecord::getApiSecret, apiSecret)
+					.eq(AccountDoubleVerifyRecord::getAccountId, account.getId()));
+		}
+		account.setStartTime(null);
+		if (isClear){
+			account.setGptRefreshToken(StrUtil.EMPTY);
+			//清除gpt token
+			redisService.del(RedisKey.CHATGPT_ACCESS_TOKEN + dbAccount);
+			redisService.del(RedisService.key.CHAT_GPT_TOKEN_EXCEPTION_KEY.getName() + dbAccount);
+			templateCommonService.sendAccountTemplateMsg(account);
+		}
+		//时间有效
+		if (account.getExpiryTime() != null && account.getExpiryTime().after(DateTime.now())) {
+			groupsMapper.update(null, Wrappers.lambdaUpdate(GroupsTrips.class)
+					.set(GroupsTrips::getStatus, GroupsTrips.Status.validity)
+					.eq(GroupsTrips::getAccountId, account.getId())
+					.eq(GroupsTrips::getStatus, GroupsTrips.Status.down));
+		}
+		accountService.updateById(account);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
 
 	/**
 	 * 修改密码并发送模板消息
@@ -540,6 +624,7 @@ public class CmsAccountController {
 							.eq(UserTicketClearedRecord::getAccountId, account.getId()));
 					//发放模板消息
 					try {
+						account.setAccount(db.getAccount());
 						templateCommonService.sendAccountTemplateMsg(account);
 					} catch (Exception e) {
 						log.error("发送账号{}修改密码消息模板错误", account.getId());
@@ -587,24 +672,24 @@ public class CmsAccountController {
 	@DeleteMapping("/delete/{id}")
 	@Log(module = "平台管理/删除账号", businessType = BusinessType.DELETE, isSaveRequestData = true)
 	public Result<String> update(@PathVariable Long id){
-	    //是否关联了车队
-	    Integer count = groupsMapper.selectCount(Wrappers.lambdaQuery(GroupsTrips.class).eq(GroupsTrips::getAccountId, id));
-	    if (count > 0) {
-		    throw BusinessRuntimeException.getInstance("已经发布账号,必须先删除车队才可删除账号");
-	    }
-        accountService.removeById(id);
-        return GatewayResponse.SUCCESS.newBuilder().toResult();
-    }
-
-    @PutMapping("/update/expiryTime")
-    public Result<String> updateExpiryTime(@RequestBody ReqAccountIncrExpiryTime incrExpiryTime){
-        incrExpiryTime.getAccounts().forEach((accountId)->{
-            Account account = accountService.getById(accountId);
-            DateTime time = DateUtil.offsetDay(account.getExpiryTime(), incrExpiryTime.getDays());
-            accountService.update(Wrappers.lambdaUpdate(Account.class).eq(Account::getId,accountId).set(Account::getExpiryTime,time));
-        });
-        return GatewayResponse.SUCCESS.newBuilder().toResult();
-    }
+		//是否关联了车队
+		Integer count = groupsMapper.selectCount(Wrappers.lambdaQuery(GroupsTrips.class).eq(GroupsTrips::getAccountId, id));
+		if (count > 0) {
+			throw BusinessRuntimeException.getInstance("已经发布账号,必须先删除车队才可删除账号");
+		}
+		accountService.removeById(id);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	@PutMapping("/update/expiryTime")
+	public Result<String> updateExpiryTime(@RequestBody ReqAccountIncrExpiryTime incrExpiryTime){
+		incrExpiryTime.getAccounts().forEach((accountId)->{
+			Account account = accountService.getById(accountId);
+			DateTime time = DateUtil.offsetDay(account.getExpiryTime(), incrExpiryTime.getDays());
+			accountService.update(Wrappers.lambdaUpdate(Account.class).eq(Account::getId,accountId).set(Account::getExpiryTime,time));
+		});
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
 
 	/**
 	 * 需要修改主账号密码的平台
@@ -677,15 +762,6 @@ public class CmsAccountController {
 		if (account.getGoodsId() != 1l) {
 			return GatewayResponse.SUCCESS.newBuilder().toResult();
 		}
-		//账号是否已经添加过
-		if (!account.getAccount().contains("客服")) {
-			int count = accountService.count(Wrappers.lambdaQuery(Account.class)
-					.eq(Account::getAccount, account.getAccount())
-					.eq(Account::getGoodsId, account.getGoodsId()));
-			if (count > 0) {
-				throw BusinessRuntimeException.getInstance("该平台下已生成该账号");
-			}
-		}
 		Boolean flag = false;
 		String oldPwd = account.getPassword();
 		if (account != null) {
@@ -792,6 +868,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);
 			}
 		}
@@ -904,6 +981,185 @@ public class CmsAccountController {
 		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
 	}
 
+	/**
+	 * 编辑 未续费的账号
+	 */
+	@PutMapping("/update/renew/account")
+	public Result<String> updateRenewAccount(@RequestBody Account account) {
+		Long id = account.getId();
+		Date startTime = account.getStartTime();
+		Date expiryTime = account.getExpiryTime();
+		String remark = account.getRemark();
+		Account byId = accountService.getById(id);
+		Assert.notNull(byId, "账号不存在");
+		byId.setStartTime(startTime);
+		byId.setExpiryTime(expiryTime);
+		byId.setRemark(remark);
+		accountService.updateById(byId);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 下载 替换错误账号模板
+	 */
+	@GetMapping("/get/replace/banned/template")
+	public void getReplaceBannedTemplate(HttpServletResponse response) {
+		EasyExcelUtils.createTemplateExcel(response, ExcelBannedAccountData.class, "封禁账号替换模板", "封禁账号替换模板", ExcelTypeEnum.XLSX, null);
+	}
+
+	/**
+	 * 替换封禁账号
+	 */
+	@PostMapping("/replace/banned")
+	public Result<List<String>> replaceBannedAccount(Long goodsId, MultipartFile file) throws IOException {
+		List<String> repeat = new ArrayList<>();
+		List<Long> sendMsgList = new ArrayList<>();
+		EasyExcel.read(file.getInputStream(), ExcelBannedAccountData.class, new AnalysisEventListener<ExcelBannedAccountData>() {
+			@Override
+			public void invoke(ExcelBannedAccountData data, AnalysisContext analysisContext) {
+				String oldAccount = data.getOldAccount();
+				String account = data.getAccount();
+				String password = data.getPassword();
+				if (StrUtil.isEmpty(oldAccount) || StrUtil.isEmpty(account) || StrUtil.isEmpty(password)) {
+					return;
+				}
+				Account dbAccount = accountService.getOne(Wrappers.lambdaQuery(Account.class)
+						.eq(Account::getGoodsId, goodsId)
+						.eq(Account::getAccount, oldAccount.trim())
+						.last("limit 1"));
+				if (dbAccount == null) {
+					return;
+				}
+				account = account.trim();
+				password = password.trim();
+				if (accountCommonService.checkIsDupAccount(goodsId, account)) {
+					repeat.add(oldAccount);
+					return;
+				}
+				dbAccount.setAccount(account);
+				dbAccount.setPassword(password);
+				dbAccount.setStartTime(DateTime.now());
+				dbAccount.setExpiryTime(DateUtil.offsetMonth(DateTime.now(), 1));
+				accountService.updateById(dbAccount);
+
+				GroupsTrips groupsTrips = groupsMapper.selectOne(Wrappers.lambdaQuery(GroupsTrips.class)
+						.eq(GroupsTrips::getAccountId, dbAccount.getId())
+						.eq(GroupsTrips::getStatus, GroupsTrips.Status.down)
+						.last("limit 1"));
+				if (groupsTrips != null) {
+					groupsTrips.setStatus(GroupsTrips.Status.validity);
+					groupsMapper.updateById(groupsTrips);
+				}
+				sendMsgList.add(dbAccount.getId());
+			}
+
+			@Override
+			public void doAfterAllAnalysed(AnalysisContext analysisContext) {
+
+			}
+		}).sheet().doRead();
+
+		if (CollUtil.isNotEmpty(sendMsgList)) {
+			TASK_EXECUTOR.execute(() -> {
+				sendMsgList.forEach(accountId -> {
+					GroupsTrips groupsTrips = groupsMapper.selectOne(Wrappers.lambdaQuery(GroupsTrips.class)
+							.eq(GroupsTrips::getAccountId, accountId).last("limit 1"));
+					if (groupsTrips != null) {
+						Account byId = accountService.getById(accountId);
+						cmsGroupService.sendChangeAccountMsg(groupsTrips.getId(), goodsId, byId.getAccount());
+					}
+				});
+			});
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult(repeat);
+	}
+
+	/**
+	 * 导入备用账号模板
+	 */
+	@GetMapping("/export/prepare/template")
+	public void getPrepareTemplate(HttpServletResponse response) {
+		EasyExcelUtils.createTemplateExcel(response, ExcelPrepareAccountData.class, "导入备用账号模板", "导入备用账号模板", ExcelTypeEnum.XLSX, null);
+	}
+
+	/**
+	 * 批量导入备用账号
+	 */
+	@PostMapping("/batch/import/prepare")
+	public Result<String> batchImportPrepare(Long goodsId, String preSkuIds, MultipartFile file) throws IOException {
+		if (goodsId == null) {
+			throw BusinessRuntimeException.getInstance("请选择对应平台");
+		}
+		if (goodsId == 26) {
+			if (StrUtil.isEmpty(preSkuIds)) {
+				throw BusinessRuntimeException.getInstance("请选择对应规格id");
+			}
+			String[] split = preSkuIds.split(",");
+			preSkuIds = Arrays.stream(split).distinct().collect(Collectors.joining(","));
+		}
+		final String f_skuIds = preSkuIds;
+		EasyExcel.read(file.getInputStream(), ExcelPrepareAccountData.class, new AnalysisEventListener<ExcelPrepareAccountData>() {
+			@Override
+			public void invoke(ExcelPrepareAccountData data, AnalysisContext analysisContext) {
+				String account = data.getAccount();
+				String password = data.getPassword();
+				if (StrUtil.isEmpty(account) || StrUtil.isEmpty(password)) {
+					return;
+				}
+				Account insert = new Account();
+				insert.setAccount(account.trim());
+				insert.setPassword(password.trim());
+				insert.setGoodsId(goodsId);
+				insert.setPreSkuIds(f_skuIds);
+				insert.setType(2);
+				insert.setStartTime(DateTime.now());
+				insert.setExpiryTime(DateUtil.offsetMonth(DateTime.now(), 1));
+				insert.setBankCard(data.getBankCard());
+				//账号是否已经添加过
+				if (!insert.getAccount().contains("客服")) {
+					if (accountCommonService.checkIsDupAccount(insert.getGoodsId(), insert.getAccount())) {
+						return;
+					}
+				}
+				insert.setType(2);
+				accountService.save(insert);
+			}
+
+			@Override
+			public void doAfterAllAnalysed(AnalysisContext analysisContext) {
+
+			}
+		}).sheet().doRead();
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 新增预备账号
+	 */
+	@PostMapping("/post/prepare")
+	public Result<String> postPrepare(@RequestBody Account account) {
+		account.setAccount(account.getAccount().trim());
+		account.setPassword(account.getPassword().trim());
+		//账号是否已经添加过
+		if (!account.getAccount().contains("客服")) {
+			if (accountCommonService.checkIsDupAccount(account.getGoodsId(), account.getAccount())) {
+				throw BusinessRuntimeException.getInstance("该平台下已生成该账号");
+			}
+		}
+		account.setType(2);
+		if (account.getGoodsId() == 26) {
+			String preSkuIds = account.getPreSkuIds();
+			if (StrUtil.isEmpty(preSkuIds)) {
+				throw BusinessRuntimeException.getInstance("请选择对应规格id");
+			}
+			String[] split = preSkuIds.split(",");
+			String skuSetStr = Arrays.stream(split).distinct().collect(Collectors.joining(","));
+			account.setPreSkuIds(skuSetStr);
+		}
+		accountService.save(account);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
 	/**
 	 * 批量导入系统邮箱
 	 */
@@ -953,4 +1209,59 @@ public class CmsAccountController {
 		sysEmailMapper.deleteById(id);
 		return GatewayResponse.SUCCESS.newBuilder().toResult();
 	}
+
+	/**
+	 * 批量导入被封禁平台账号
+	 */
+	@PostMapping("/batch/import/blocked")
+	public Result<String> batchImportBlockedAccount(MultipartFile file, Long goodsId) throws IOException {
+		Assert.notNull(goodsId, "请选择对应平台");
+		List<Object> accountBlockedList = EasyExcel.read(file.getInputStream()).sheet().headRowNumber(0).doReadSync();
+		accountService.batchImportBlockedAccount(goodsId, accountBlockedList);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 删除封禁平台账号
+	 */
+	@DeleteMapping("/delete/blocked/{id}")
+	public Result<String> deleteBlockedAccount(@PathVariable Long id) throws IOException {
+		accountBlockedReplaceRecordMapper.deleteById(id);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 被封禁账号列表
+	 */
+	@GetMapping("/get/blocked")
+	public Result<SearchResult<AccountBlockedReplaceRecord>> getBlockedAccount() {
+		SearchResult<AccountBlockedReplaceRecord> search = beanSearcher.search(AccountBlockedReplaceRecord.class, MapUtils.flatBuilder(request.getParameterMap())
+				.orderBy(AccountBlockedReplaceRecord::getId).desc()
+				.build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 禁用账号
+	 */
+	@PutMapping("/update/disable/{accountId}")
+	@Log(module = "平台管理/禁用账号", businessType = BusinessType.PUT, isSaveRequestData = true)
+	public Result<String> updateDisableAccount(@PathVariable Long accountId) {
+		Optional.ofNullable(accountService.getById(accountId))
+				.ifPresent(e -> {
+					e.setIsDisable(!e.getIsDisable());
+					accountService.updateById(e);
+				});
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 账号禁用列表
+	 */
+	@GetMapping("/get/disable/acount")
+	public Result<SearchResult<AccountDisableView>> getDisableAccount() {
+		SearchResult<AccountDisableView> search = beanSearcher.search(AccountDisableView.class, MapUtils.flatBuilder(request.getParameterMap())
+				.field(AccountDisableView::getIsDisable, 1).build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
 }

+ 1 - 1
pom.xml

@@ -201,7 +201,7 @@
         </resources>
 
 
-        <finalName>netflix-pre</finalName>
+        <finalName>netflix-abroad</finalName>
     </build>
 
     <!-- profiles配置 -->