package com.cyksj.service.mange.account; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.RandomUtil; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 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.AccountMapper; import com.cyksj.mapper.AccountUpdatePasswordRecordMapper; import com.cyksj.mapper.manage.AutoUpdateAccountPwdLogMapper; import com.cyksj.mapper.manage.cms.CmsUserMapper; import com.cyksj.model.entity.*; import com.cyksj.model.excel.ExcelAccountData; import com.cyksj.model.manage.views.AccountView; import com.cyksj.model.views.CmsUserVO; import com.cyksj.model.views.ExpiredAccountDataView; 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.sys.SysConfigService; import com.ejlchina.searcher.BeanSearcher; import com.ejlchina.searcher.param.Operator; import com.ejlchina.searcher.util.MapUtils; import com.google.common.collect.Lists; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.*; /** * @author chan * @date 2022/9/27 6:23 PM */ @Slf4j @Service("cms") @RequiredArgsConstructor public class CmsAccountServiceImpl extends ServiceImpl implements CmsAccountService { private final AccountMapper accountMapper; private final AccountUpdatePasswordRecordMapper accountUpdatePasswordRecordMapper; private final CmsUserMapper cmsUserMapper; private final AutoUpdateAccountPwdLogMapper autoUpdateAccountPwdLogMapper; private final BeanSearcher beanSearcher; private final CmsGroupService cmsGroupService; private final RedisService redisService; private final AccountCommonService accountCommonService; private final SysConfigService sysConfigService; @Override public IPage 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)); } @Override public List 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) { return accountMapper.getExpiredAccountViewNoPage(isCorpWx, customerService, goodsId, skuId, account, renewStatus, handleStatus, cnAccount, usAccount, userId, startTime, endTime, now); } @Override public List getNoAppleOneOrderDon(List skuIds, Date yesZeroDate, Date thisZeroDate, List noOrderStatus) { return accountMapper.getNoAppleOneOrderDon(skuIds, yesZeroDate, thisZeroDate, noOrderStatus); } @Override public List getExpiredAllAccount() { return accountMapper.getExpiredAllAccount(); } @Override public void saveRecord(Long operateUserId, Long accountId, String oldPassword, String newPassword, String type) { AccountUpdatePasswordRecord record = new AccountUpdatePasswordRecord(); record.setAccountId(accountId); record.setOperateUserId(operateUserId); Optional.ofNullable(cmsUserMapper.selectById(operateUserId)) .ifPresent(admin -> record.setOperator(admin.getNickname())); record.setOldPassword(oldPassword); record.setNewPassword(newPassword); record.setType(type); accountUpdatePasswordRecordMapper.insert(record); } @Override public void recordAutoUpdatePwd(Long accountId, String account, String oldPwd, String newPwd, String operateIp) { AutoUpdateAccountPwdLog log = new AutoUpdateAccountPwdLog(); log.setAccountId(accountId); log.setAccount(account); log.setOldPwd(oldPwd); log.setNewPwd(newPwd); log.setOperateLocation(StringUtil.getRealAddressByIP(operateIp)); log.setOperateIp(operateIp); autoUpdateAccountPwdLogMapper.insert(log); } @Override public void assignDeleteCustomerAccount(Long customerServiceId) { List accountViews = beanSearcher.searchAll(AccountView.class, MapUtils.builder() .field(AccountView::getCustomerServiceId, customerServiceId) .build()); if (accountViews.size() > 0) { List customers = beanSearcher.searchAll(CmsUserVO.class, MapUtils.builder() .field(CmsUserVO::getId, customerServiceId).op(Operator.NotEqual) .field(CmsUserVO::getRoleNames, "客服").op(Operator.Contain) .build()); if (customers.size() > 0) { log.info("删除客服id:{},分配其未修改的过期账号,账号数量:{}", customerServiceId, accountViews.size()); assignCustomerAccount(customers, accountViews); } } } @Override public void assignCustomerAccount(List customers, List accountViews) { int customerSize = customers.size(); int accountSize = accountViews.size(); if (accountSize < customerSize) { accountViews.forEach(account -> { int randomIndex = RandomUtil.randomInt(customerSize); CmsUserVO customer = customers.get(randomIndex); accountMapper.update(null, Wrappers.lambdaUpdate(Account.class) .set(Account::getCustomerServiceId, customer.getId()) .eq(Account::getId, account.getId())); }); return; } int num = accountSize / customerSize; int remain = accountSize % customerSize; List> partition = Lists.partition(accountViews, num); for (int i = 0; i < customerSize; i++) { List expiredAccounts = partition.get(i); CmsUserVO customer = customers.get(i); expiredAccounts.forEach(ea -> { Long accountId = ea.getId(); accountMapper.update(null, Wrappers.lambdaUpdate(Account.class) .set(Account::getCustomerServiceId, customer.getId()) .eq(Account::getId, accountId)); }); } if (remain > 0) { log.info("分配多余的过期账号给客服"); List remainExpiredAccount = partition.get(customerSize); remainExpiredAccount.forEach(remainAccount -> { int randomIndex = RandomUtil.randomInt(customerSize); log.info("获取的随机下标:{}", randomIndex); CmsUserVO customer = customers.get(randomIndex); log.info("随机分配的客服是:{}", customer.getNickname()); Long accountId = remainAccount.getId(); accountMapper.update(null, Wrappers.lambdaUpdate(Account.class) .set(Account::getCustomerServiceId, customer.getId()) .eq(Account::getId, accountId)); }); } } @Override @Transactional(rollbackFor = Throwable.class) public void analysisChatGPTAccount(Long goodsId, Long skuId, List accountList) { insertAccount(goodsId, skuId, accountList); } @Override public void analysisAmericaAppidAccount(Long goodsId, Long skuId, List accountList) { insertAccount(goodsId, skuId, accountList); } /** * * @param goodsId * @param skuId * @param accountList */ public void insertAccount(Long goodsId, Long skuId, List accountList) { if (CollUtil.isEmpty(accountList)) { throw BusinessRuntimeException.getInstance("文件数据为空"); } String cache = RedisService.key.IMPORT_ACCOUNT_CACHE_KEY.getNameFormat(goodsId); if (!redisService.setNx(cache, goodsId, RedisService.key.IMPORT_ACCOUNT_CACHE_KEY.getTimeout())) { throw BusinessRuntimeException.getInstance("后台程序正在导入账号中..."); } List special_email_goods_ids = new ArrayList<>(); SysConfig sysConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class) .eq(SysConfig::getSysKey, Constant.SPECIAL_GOODS_ACCOUNT_IMPORT_KEY).last("limit 1")); if (sysConfig != null) { try { special_email_goods_ids.addAll(Jsons.parseList(sysConfig.getSysValue(), Long.class)); } catch (Exception e) { } } String regex; if (goodsId == 29l) { regex = "\\|"; } else { regex = "----"; } try { accountList.forEach(accountData -> { Map map = Jsons.toMap(accountData); String[] part = map.get("0").toString().split(regex); if (part.length >= 2) { String account = part[0]; String password = part[1]; //重复不再重新插入 if (accountCommonService.checkIsDupAccount(goodsId, account)) { return; } Account insert = new Account(); insert.setAccount(account); insert.setPassword(password); if (part.length > 2 && part.length < 9) { //google36、辅助邮箱 //46 Google Bard if (special_email_goods_ids.contains(goodsId)) { String email = part[2]; insert.setEmail(email); } else { String apiKey = part[2]; insert.setApiKey(apiKey); } } insert.setGoodsId(goodsId); if (goodsId.equals(31l)) { if (part.length >= 9) { StringBuilder sb = new StringBuilder(); String country = part[part.length - 1]; if (country.contains("国")) { sb.append(part[part.length - 1]); sb.append(Constant.ONE_EMPTY); sb.append(part[part.length - 2]); sb.append(Constant.ONE_EMPTY); } for (int i = 2; i < part.length; i++) { if (part[i].contains("朋友")) { sb.append("朋友"); sb.append(Constant.ONE_EMPTY); sb.append(part[i + 1]); i++; } if (part[i].contains("工作")) { sb.append("工作"); sb.append(Constant.ONE_EMPTY); sb.append(part[i + 1]); i++; } if (part[i].contains("父母")) { sb.append("父母"); sb.append(Constant.ONE_EMPTY); sb.append(part[i + 1]); i++; } } insert.setSecret(sb.toString()); } else { insert.setSecret(Constant.AMERICA_APPID_SECRET); } } this.save(insert); //是否存在未发车的车队 GroupsTrips waiting = cmsGroupService.getOne(Wrappers.lambdaQuery(GroupsTrips.class) .eq(GroupsTrips::getSkuId, skuId) .eq(GroupsTrips::getStatus, GroupsTrips.Status.waiting).last("limit 1")); if (waiting != null) { waiting.setAccountId(insert.getId()); try { cmsGroupService.setAccount(waiting); } catch (Exception e) { //自动配置车队 setGroupsTrips(skuId, insert.getId()); } } else { //自动配置车队 setGroupsTrips(skuId, insert.getId()); } } }); } catch (Exception e) { log.error(StringUtil.getErrorText(e)); } redisService.del(cache); } public void setGroupsTrips(Long skuId, Long accountId) { //自动配置车队 GroupsTrips groupsTrips = new GroupsTrips(); groupsTrips.setSkuId(skuId); groupsTrips.setAccountId(accountId); cmsGroupService.issuance(groupsTrips, null); } }