CmsAccountServiceImpl.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. package com.cyksj.service.mange.account;
  2. import cn.hutool.core.collection.CollUtil;
  3. import cn.hutool.core.util.RandomUtil;
  4. import cn.hutool.core.util.StrUtil;
  5. import com.baomidou.mybatisplus.core.metadata.IPage;
  6. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  7. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  8. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  9. import com.cyksj.common.constant.Constant;
  10. import com.cyksj.common.exception.BusinessRuntimeException;
  11. import com.cyksj.common.util.Jsons;
  12. import com.cyksj.common.util.StringUtil;
  13. import com.cyksj.mapper.AccountMapper;
  14. import com.cyksj.mapper.AccountUpdatePasswordRecordMapper;
  15. import com.cyksj.mapper.sys.SysEmailMapper;
  16. import com.cyksj.mapper.manage.AutoUpdateAccountPwdLogMapper;
  17. import com.cyksj.mapper.manage.cms.CmsUserMapper;
  18. import com.cyksj.model.entity.*;
  19. import com.cyksj.model.excel.ExcelAccountData;
  20. import com.cyksj.model.manage.views.AccountView;
  21. import com.cyksj.model.views.CmsUserVO;
  22. import com.cyksj.model.views.ExpiredAccountDataView;
  23. import com.cyksj.redis.RedisService;
  24. import com.cyksj.service.mange.AccountCommonService;
  25. import com.cyksj.service.mange.CmsAccountService;
  26. import com.cyksj.service.mange.CmsGroupService;
  27. import com.cyksj.service.sys.SysConfigService;
  28. import com.ejlchina.searcher.BeanSearcher;
  29. import com.ejlchina.searcher.param.Operator;
  30. import com.ejlchina.searcher.util.MapUtils;
  31. import com.google.common.collect.Lists;
  32. import lombok.RequiredArgsConstructor;
  33. import lombok.extern.slf4j.Slf4j;
  34. import org.springframework.stereotype.Service;
  35. import org.springframework.transaction.annotation.Transactional;
  36. import org.springframework.web.multipart.MultipartFile;
  37. import java.io.BufferedReader;
  38. import java.io.InputStream;
  39. import java.io.InputStreamReader;
  40. import java.util.*;
  41. /**
  42. * @author chan
  43. * @date 2022/9/27 6:23 PM
  44. */
  45. @Slf4j
  46. @Service("cms")
  47. @RequiredArgsConstructor
  48. public class CmsAccountServiceImpl extends ServiceImpl<AccountMapper, Account> implements CmsAccountService {
  49. private final AccountMapper accountMapper;
  50. private final AccountUpdatePasswordRecordMapper accountUpdatePasswordRecordMapper;
  51. private final CmsUserMapper cmsUserMapper;
  52. private final AutoUpdateAccountPwdLogMapper autoUpdateAccountPwdLogMapper;
  53. private final BeanSearcher beanSearcher;
  54. private final CmsGroupService cmsGroupService;
  55. private final RedisService redisService;
  56. private final AccountCommonService accountCommonService;
  57. private final SysConfigService sysConfigService;
  58. private final SysEmailMapper sysEmailMapper;
  59. @Override
  60. 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) {
  61. return accountMapper.getExpiredAccountView(isCorpWx, customerService, goodsId, skuId, account, renewStatus, handleStatus, cnAccount, usAccount, userId, startTime, endTime, now, new Page<>(offset, limit));
  62. }
  63. @Override
  64. public List<ExcelAccountData> getExpiredAccountViewNoPage(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) {
  65. return accountMapper.getExpiredAccountViewNoPage(isCorpWx, customerService, goodsId, skuId, account, renewStatus, handleStatus, cnAccount, usAccount, userId, startTime, endTime, now);
  66. }
  67. @Override
  68. public List<OrderDon> getNoAppleOneOrderDon(List<Long> skuIds, Date yesZeroDate, Date thisZeroDate, List<String> noOrderStatus) {
  69. return accountMapper.getNoAppleOneOrderDon(skuIds, yesZeroDate, thisZeroDate, noOrderStatus);
  70. }
  71. @Override
  72. public List<AccountView> getExpiredAllAccount() {
  73. return accountMapper.getExpiredAllAccount();
  74. }
  75. @Override
  76. public void saveRecord(Long operateUserId, Long accountId, String oldPassword, String newPassword, String type) {
  77. AccountUpdatePasswordRecord record = new AccountUpdatePasswordRecord();
  78. record.setAccountId(accountId);
  79. record.setOperateUserId(operateUserId);
  80. Optional.ofNullable(cmsUserMapper.selectById(operateUserId))
  81. .ifPresent(admin -> record.setOperator(admin.getNickname()));
  82. record.setOldPassword(oldPassword);
  83. record.setNewPassword(newPassword);
  84. record.setType(type);
  85. accountUpdatePasswordRecordMapper.insert(record);
  86. }
  87. @Override
  88. public void recordAutoUpdatePwd(Long accountId, String account, String oldPwd, String newPwd, String operateIp) {
  89. AutoUpdateAccountPwdLog log = new AutoUpdateAccountPwdLog();
  90. log.setAccountId(accountId);
  91. log.setAccount(account);
  92. log.setOldPwd(oldPwd);
  93. log.setNewPwd(newPwd);
  94. log.setOperateLocation(StringUtil.getRealAddressByIP(operateIp));
  95. log.setOperateIp(operateIp);
  96. autoUpdateAccountPwdLogMapper.insert(log);
  97. }
  98. @Override
  99. public void assignDeleteCustomerAccount(Long customerServiceId) {
  100. List<AccountView> accountViews = beanSearcher.searchAll(AccountView.class, MapUtils.builder()
  101. .field(AccountView::getCustomerServiceId, customerServiceId)
  102. .build());
  103. if (accountViews.size() > 0) {
  104. List<CmsUserVO> customers = beanSearcher.searchAll(CmsUserVO.class, MapUtils.builder()
  105. .field(CmsUserVO::getId, customerServiceId).op(Operator.NotEqual)
  106. .field(CmsUserVO::getRoleNames, "客服").op(Operator.Contain)
  107. .build());
  108. if (customers.size() > 0) {
  109. log.info("删除客服id:{},分配其未修改的过期账号,账号数量:{}", customerServiceId, accountViews.size());
  110. assignCustomerAccount(customers, accountViews);
  111. }
  112. }
  113. }
  114. @Override
  115. public void assignCustomerAccount(List<CmsUserVO> customers, List<AccountView> accountViews) {
  116. int customerSize = customers.size();
  117. int accountSize = accountViews.size();
  118. if (accountSize < customerSize) {
  119. accountViews.forEach(account -> {
  120. int randomIndex = RandomUtil.randomInt(customerSize);
  121. CmsUserVO customer = customers.get(randomIndex);
  122. accountMapper.update(null, Wrappers.lambdaUpdate(Account.class)
  123. .set(Account::getCustomerServiceId, customer.getId())
  124. .eq(Account::getId, account.getId()));
  125. });
  126. return;
  127. }
  128. int num = accountSize / customerSize;
  129. int remain = accountSize % customerSize;
  130. List<List<AccountView>> partition = Lists.partition(accountViews, num);
  131. for (int i = 0; i < customerSize; i++) {
  132. List<AccountView> expiredAccounts = partition.get(i);
  133. CmsUserVO customer = customers.get(i);
  134. expiredAccounts.forEach(ea -> {
  135. Long accountId = ea.getId();
  136. accountMapper.update(null, Wrappers.lambdaUpdate(Account.class)
  137. .set(Account::getCustomerServiceId, customer.getId())
  138. .eq(Account::getId, accountId));
  139. });
  140. }
  141. if (remain > 0) {
  142. log.info("分配多余的过期账号给客服");
  143. List<AccountView> remainExpiredAccount = partition.get(customerSize);
  144. remainExpiredAccount.forEach(remainAccount -> {
  145. int randomIndex = RandomUtil.randomInt(customerSize);
  146. log.info("获取的随机下标:{}", randomIndex);
  147. CmsUserVO customer = customers.get(randomIndex);
  148. log.info("随机分配的客服是:{}", customer.getNickname());
  149. Long accountId = remainAccount.getId();
  150. accountMapper.update(null, Wrappers.lambdaUpdate(Account.class)
  151. .set(Account::getCustomerServiceId, customer.getId())
  152. .eq(Account::getId, accountId));
  153. });
  154. }
  155. }
  156. @Override
  157. @Transactional(rollbackFor = Throwable.class)
  158. public void analysisChatGPTAccount(Long goodsId, Long skuId, List<Object> accountList) {
  159. insertAccount(goodsId, skuId, accountList);
  160. }
  161. @Override
  162. public void analysisAmericaAppidAccount(Long goodsId, Long skuId, List<Object> accountList) {
  163. insertAccount(goodsId, skuId, accountList);
  164. }
  165. @Override
  166. public void readFileAndImportEmail(MultipartFile file) throws Exception {
  167. InputStream in = null;
  168. BufferedReader br = null;
  169. String regex = "----";
  170. List<SysEmail> sysEmails = new ArrayList<>();
  171. List<String> error = new ArrayList<>();
  172. try {
  173. in = file.getInputStream();
  174. br = new BufferedReader(new InputStreamReader(file.getInputStream()));
  175. String content = null;
  176. while ((content = br.readLine()) != null) {
  177. String[] split = content.split(regex);
  178. if (split.length > 1) {
  179. String email = split[0];
  180. String password = split[1];
  181. if (!StrUtil.hasEmpty(email, password)) {
  182. SysEmail sysEmail = new SysEmail();
  183. sysEmail.setEmail(email);
  184. sysEmail.setPassword(password);
  185. sysEmails.add(sysEmail);
  186. }
  187. }else {
  188. error.add(split[0]);
  189. }
  190. }
  191. if (CollUtil.isNotEmpty(sysEmails)) {
  192. Lists.partition(sysEmails, 1000).forEach(data -> {
  193. sysEmailMapper.batchInsert(data);
  194. });
  195. }
  196. } finally {
  197. if (br != null) {
  198. br.close();
  199. }
  200. if (in != null) {
  201. in.close();
  202. }
  203. }
  204. System.out.println(Jsons.toJson(error));
  205. }
  206. /**
  207. *
  208. * @param goodsId
  209. * @param skuId
  210. * @param accountList
  211. */
  212. public void insertAccount(Long goodsId, Long skuId, List<Object> accountList) {
  213. if (CollUtil.isEmpty(accountList)) {
  214. throw BusinessRuntimeException.getInstance("文件数据为空");
  215. }
  216. String cache = RedisService.key.IMPORT_ACCOUNT_CACHE_KEY.getNameFormat(goodsId);
  217. if (!redisService.setNx(cache, goodsId, RedisService.key.IMPORT_ACCOUNT_CACHE_KEY.getTimeout())) {
  218. throw BusinessRuntimeException.getInstance("后台程序正在导入账号中...");
  219. }
  220. List<Long> special_email_goods_ids = new ArrayList<>();
  221. SysConfig sysConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
  222. .eq(SysConfig::getSysKey, Constant.SPECIAL_GOODS_ACCOUNT_IMPORT_KEY).last("limit 1"));
  223. if (sysConfig != null) {
  224. try {
  225. special_email_goods_ids.addAll(Jsons.parseList(sysConfig.getSysValue(), Long.class));
  226. } catch (Exception e) {
  227. }
  228. }
  229. String regex;
  230. if (goodsId == 29l) {
  231. regex = "\\|";
  232. } else {
  233. regex = "----";
  234. }
  235. try {
  236. accountList.forEach(accountData -> {
  237. Map<String, Object> map = Jsons.toMap(accountData);
  238. Account insert = new Account();
  239. insert.setGoodsId(goodsId);
  240. if (map.keySet().size() >= 5) {
  241. String account = map.get("0").toString();
  242. String password = map.get("1").toString();
  243. String friend = map.get("2").toString();
  244. String work = map.get("3").toString();
  245. String parents = map.get("4").toString();
  246. String secret;
  247. if (map.keySet().size() == 6) {
  248. String country = map.get("5").toString();
  249. secret = String.format(Constant.NEW_APPID_SECRET, friend, work, parents, country);
  250. } else {
  251. secret = String.format(Constant.NEW_APPID_NO_COUNTRY_SECRET, friend, work, parents);
  252. }
  253. insert.setAccount(account);
  254. insert.setPassword(password);
  255. insert.setSecret(secret);
  256. } else {
  257. String[] part = map.get("0").toString().split(regex);
  258. if (part.length >= 2) {
  259. String account = part[0];
  260. String password = part[1];
  261. insert.setAccount(account);
  262. insert.setPassword(password);
  263. if (part.length > 2 && part.length < 9) {
  264. //google36、辅助邮箱
  265. //46 Google Bard
  266. if (special_email_goods_ids.contains(goodsId)) {
  267. String email = part[2];
  268. insert.setEmail(email);
  269. } else {
  270. //chatGPT 邮箱密码
  271. String gptEmailPwd = part[2];
  272. insert.setGptEmailPwd(gptEmailPwd);
  273. }
  274. }
  275. if (goodsId.equals(31l)) {
  276. if (part.length >= 9) {
  277. StringBuilder sb = new StringBuilder();
  278. String country = part[part.length - 1];
  279. if (country.contains("国")) {
  280. sb.append(part[part.length - 1]);
  281. sb.append(Constant.ONE_EMPTY);
  282. sb.append(part[part.length - 2]);
  283. sb.append(Constant.ONE_EMPTY);
  284. }
  285. for (int i = 2; i < part.length; i++) {
  286. if (part[i].contains("朋友")) {
  287. sb.append("朋友");
  288. sb.append(Constant.ONE_EMPTY);
  289. sb.append(part[i + 1]);
  290. i++;
  291. }
  292. if (part[i].contains("工作")) {
  293. sb.append("工作");
  294. sb.append(Constant.ONE_EMPTY);
  295. sb.append(part[i + 1]);
  296. i++;
  297. }
  298. if (part[i].contains("父母")) {
  299. sb.append("父母");
  300. sb.append(Constant.ONE_EMPTY);
  301. sb.append(part[i + 1]);
  302. i++;
  303. }
  304. }
  305. insert.setSecret(sb.toString());
  306. } else {
  307. insert.setSecret(Constant.AMERICA_APPID_SECRET);
  308. }
  309. }
  310. }
  311. }
  312. String account = insert.getAccount();
  313. if (StrUtil.isEmpty(account)) {
  314. return;
  315. }
  316. //重复不再重新插入
  317. if (accountCommonService.checkIsDupAccount(goodsId, account)) {
  318. return;
  319. }
  320. this.save(insert);
  321. //是否存在未发车的车队
  322. GroupsTrips waiting = cmsGroupService.getOne(Wrappers.lambdaQuery(GroupsTrips.class)
  323. .eq(GroupsTrips::getSkuId, skuId)
  324. .eq(GroupsTrips::getStatus, GroupsTrips.Status.waiting).last("limit 1"));
  325. if (waiting != null) {
  326. waiting.setAccountId(insert.getId());
  327. try {
  328. cmsGroupService.setAccount(waiting);
  329. } catch (Exception e) {
  330. //自动配置车队
  331. setGroupsTrips(skuId, insert.getId());
  332. }
  333. } else {
  334. //自动配置车队
  335. setGroupsTrips(skuId, insert.getId());
  336. }
  337. });
  338. } catch (Exception e) {
  339. log.error(StringUtil.getErrorText(e));
  340. }
  341. redisService.del(cache);
  342. }
  343. public void setGroupsTrips(Long skuId, Long accountId) {
  344. //自动配置车队
  345. GroupsTrips groupsTrips = new GroupsTrips();
  346. groupsTrips.setSkuId(skuId);
  347. groupsTrips.setAccountId(accountId);
  348. cmsGroupService.issuance(groupsTrips, null);
  349. }
  350. }