package com.xiaopeng.operation.controller;
|
|
|
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
import cn.afterturn.easypoi.excel.ExcelImportUtil;
|
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
import cn.afterturn.easypoi.excel.entity.ImportParams;
|
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
|
import cn.hutool.core.util.PhoneUtil;
|
import cn.hutool.core.io.resource.ClassPathResource;
|
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
import com.xiaopeng.api.model.operation.XpInvitationCode;
|
import com.xiaopeng.api.model.operation.XpWhitelist;
|
import com.xiaopeng.common.core.domain.R;
|
import com.xiaopeng.common.core.exception.ServiceException;
|
import com.xiaopeng.common.core.utils.DateUtils;
|
import com.xiaopeng.common.core.utils.WebUtils;
|
import com.xiaopeng.common.core.web.page.PageInfo;
|
import com.xiaopeng.operation.constant.I18nKeyConstant;
|
import com.xiaopeng.operation.dto.InvitationAddDto;
|
import com.xiaopeng.operation.exportExcle.XpInvitationCodeExportExcel;
|
import com.xiaopeng.operation.importExcel.InvitationCodeImportExcel;
|
import com.xiaopeng.operation.query.InvitationPageListQuery;
|
import com.xiaopeng.operation.service.IXpInvitationCodeService;
|
import com.xiaopeng.operation.service.IXpWhitelistService;
|
import io.swagger.annotations.*;
|
import lombok.extern.slf4j.Slf4j;
|
import org.apache.poi.ss.usermodel.Workbook;
|
import org.springframework.context.MessageSource;
|
import org.springframework.context.i18n.LocaleContextHolder;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.StringUtils;
|
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.multipart.MultipartFile;
|
|
import javax.annotation.Resource;
|
import javax.servlet.ServletOutputStream;
|
import javax.servlet.http.HttpServletResponse;
|
import java.io.IOException;
|
import java.io.InputStream;
|
import java.net.URLEncoder;
|
import java.time.LocalDateTime;
|
import java.time.format.DateTimeFormatter;
|
import java.util.*;
|
import java.util.stream.Collectors;
|
import java.util.regex.Pattern;
|
|
/**
|
* <p>
|
* 邀请码管理 前端控制器
|
* </p>
|
*
|
* @author mitao
|
* @since 2026-02-03
|
*/
|
@RestController
|
@Api(tags = "邀请码管理")
|
@Slf4j
|
@RequestMapping("")
|
public class XpInvitationCodeController {
|
@Resource
|
private IXpInvitationCodeService xpInvitationCodeService;
|
@Resource
|
private IXpWhitelistService xpWhitelistService;
|
@Resource
|
private MessageSource messageSource;
|
|
private static final Pattern CHINESE_PATTERN = Pattern.compile("\\p{IsHan}");
|
|
@ApiOperation(value = "邀请码管理分页列表",response = XpInvitationCode.class)
|
@PostMapping("/api/v1/invitation/pageList")
|
public R<PageInfo<XpInvitationCode>> pageList(@RequestBody InvitationPageListQuery query) {
|
PageInfo<XpInvitationCode> pageList = xpInvitationCodeService.pageList(query);
|
return R.ok(pageList);
|
}
|
/**
|
* 生成邀请码
|
*/
|
@PostMapping("/api/v1/invitation/add")
|
@ResponseBody
|
@ApiOperation(value = "生成邀请码")
|
@Transactional
|
public R add(@RequestBody InvitationAddDto dto){
|
return xpInvitationCodeService.add(dto.getPhones());
|
}
|
/**
|
* 解绑
|
*/
|
@PutMapping("/api/v1/invitation/unbind")
|
@ResponseBody
|
@ApiOperation(value = "解绑")
|
@ApiImplicitParams({
|
@ApiImplicitParam(value = "id", name = "id", dataType = "Long", required = true)
|
})
|
public R unbind(@RequestParam("id") Long id){
|
UpdateWrapper<XpInvitationCode> xpInvitationCodeUpdateWrapper = new UpdateWrapper<>();
|
xpInvitationCodeUpdateWrapper.eq("id",id);
|
xpInvitationCodeUpdateWrapper.set("status",3);
|
xpInvitationCodeUpdateWrapper.set("bind_account", null);
|
xpInvitationCodeService.update(xpInvitationCodeUpdateWrapper);
|
return R.ok();
|
}
|
@ApiOperation(value = "邀请码导入模板下载")
|
@GetMapping("/api/v1/invitation/import-template")
|
public void importTemplate() {
|
List<InvitationCodeImportExcel> invitationCodeImportExcels = new ArrayList<>();
|
InvitationCodeImportExcel invitationCodeImportExcel = new InvitationCodeImportExcel();
|
invitationCodeImportExcels.add(invitationCodeImportExcel);
|
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), InvitationCodeImportExcel.class, invitationCodeImportExcels);
|
HttpServletResponse response = WebUtils.response();
|
ServletOutputStream outputStream = null;
|
//1.获取excel模板
|
ClassPathResource classPathResource = new ClassPathResource("template/邀请码导入模板.xlsx");
|
TemplateExportParams params = new TemplateExportParams(classPathResource.getPath());
|
response.setContentType("application/vnd.ms-excel");
|
response.setCharacterEncoding("utf-8");
|
try {
|
String fileName = URLEncoder.encode("邀请码导入模板.xlsx", "utf-8");
|
response.setHeader("Content-dispodition", "attachment;filename=" + fileName);
|
outputStream = response.getOutputStream();
|
workbook.write(outputStream);
|
|
} catch (IOException e) {
|
e.printStackTrace();
|
System.out.println("邀请码导入模板下载失败!");
|
} finally {
|
try {
|
outputStream.close();
|
} catch (IOException e) {
|
e.printStackTrace();
|
}
|
}
|
}
|
@ApiOperation(value = "邀请码导入")
|
@PostMapping("/base/v1/invitation/importExcel")
|
public R<String> importExcel(@RequestPart("file") MultipartFile file) {
|
ImportParams params = new ImportParams();
|
params.setHeadRows(1); //表头行数
|
InputStream inputStream = null;
|
List<InvitationCodeImportExcel> invitationCodeImportExcels;
|
try {
|
inputStream = file.getInputStream();
|
invitationCodeImportExcels = ExcelImportUtil.importExcel(inputStream,
|
InvitationCodeImportExcel.class, params);
|
} catch (Exception e) {
|
e.printStackTrace();
|
log.error("邀请码导入失败:{}", e.getMessage());
|
throw new ServiceException("邀请码导入失败!");
|
} finally {
|
try {
|
if (inputStream != null) {
|
inputStream.close();
|
}
|
} catch (IOException e) {
|
throw new ServiceException(e.getMessage());
|
}
|
}
|
if (CollectionUtils.isEmpty(invitationCodeImportExcels)) {
|
return R.fail(messageSource.getMessage(I18nKeyConstant.INVITATION_IMPORT_DATA_EMPTY, null, I18nKeyConstant.INVITATION_IMPORT_DATA_EMPTY, LocaleContextHolder.getLocale()));
|
}
|
|
// 批量校验:账号必须为手机号;邀请码不能为空且不能包含中文;同时校验文件内重复/数据库已存在
|
List<String> errors = new ArrayList<>();
|
Set<String> importCodes = new HashSet<>();
|
for (int i = 0; i < invitationCodeImportExcels.size(); i++) {
|
InvitationCodeImportExcel row = invitationCodeImportExcels.get(i);
|
int rowNum = i + 2;
|
|
String invitationCode = trimToNull(row.getInvitationCode());
|
String bindAccount = trimToNull(row.getBindAccount());
|
row.setInvitationCode(invitationCode);
|
row.setBindAccount(bindAccount);
|
|
if (!StringUtils.hasLength(invitationCode)) {
|
errors.add(messageSource.getMessage(I18nKeyConstant.INVITATION_IMPORT_CODE_EMPTY, new Object[]{rowNum}, I18nKeyConstant.INVITATION_IMPORT_CODE_EMPTY, LocaleContextHolder.getLocale()));
|
} else {
|
if (containsChinese(invitationCode)) {
|
errors.add(messageSource.getMessage(I18nKeyConstant.INVITATION_IMPORT_CODE_CONTAINS_CHINESE, new Object[]{rowNum, bindAccount}, I18nKeyConstant.INVITATION_IMPORT_CODE_CONTAINS_CHINESE, LocaleContextHolder.getLocale()));
|
}
|
importCodes.add(invitationCode);
|
}
|
|
if (!StringUtils.hasLength(bindAccount)) {
|
errors.add(messageSource.getMessage(I18nKeyConstant.INVITATION_IMPORT_ACCOUNT_EMPTY, new Object[]{rowNum}, I18nKeyConstant.INVITATION_IMPORT_ACCOUNT_EMPTY, LocaleContextHolder.getLocale()));
|
} else if (!PhoneUtil.isPhone(bindAccount)) {
|
errors.add(messageSource.getMessage(I18nKeyConstant.INVITATION_IMPORT_ACCOUNT_INVALID, new Object[]{rowNum, bindAccount}, I18nKeyConstant.INVITATION_IMPORT_ACCOUNT_INVALID, LocaleContextHolder.getLocale()));
|
}
|
|
if (StringUtils.hasLength(row.getBindTime())) {
|
row.setBindTime(row.getBindTime().trim());
|
}
|
}
|
|
Map<String, Long> codeCountMap = invitationCodeImportExcels.stream()
|
.map(InvitationCodeImportExcel::getInvitationCode)
|
.filter(StringUtils::hasLength)
|
.collect(Collectors.groupingBy(code -> code, Collectors.counting()));
|
List<String> duplicatedCodes = codeCountMap.entrySet().stream()
|
.filter(entry -> entry.getValue() != null && entry.getValue() > 1)
|
.map(Map.Entry::getKey)
|
.sorted()
|
.collect(Collectors.toList());
|
if (!duplicatedCodes.isEmpty()) {
|
errors.add(messageSource.getMessage(I18nKeyConstant.INVITATION_IMPORT_CODE_DUPLICATE, new Object[]{String.join(",", duplicatedCodes)}, I18nKeyConstant.INVITATION_IMPORT_CODE_DUPLICATE, LocaleContextHolder.getLocale()));
|
}
|
|
if (!importCodes.isEmpty()) {
|
List<XpInvitationCode> existsList = xpInvitationCodeService.lambdaQuery()
|
.in(XpInvitationCode::getInvitationCode, importCodes)
|
.list();
|
if (!CollectionUtils.isEmpty(existsList)) {
|
List<String> existsCodes = existsList.stream()
|
.map(XpInvitationCode::getInvitationCode)
|
.filter(StringUtils::hasLength)
|
.distinct()
|
.sorted()
|
.collect(Collectors.toList());
|
if (!existsCodes.isEmpty()) {
|
errors.add(messageSource.getMessage(I18nKeyConstant.INVITATION_IMPORT_CODE_EXISTS, new Object[]{String.join(",", existsCodes)}, I18nKeyConstant.INVITATION_IMPORT_CODE_EXISTS, LocaleContextHolder.getLocale()));
|
}
|
}
|
}
|
|
if (!errors.isEmpty()) {
|
return R.fail(messageSource.getMessage(I18nKeyConstant.INVITATION_IMPORT_VALIDATE_FAIL, new Object[]{String.join("\n", errors)},I18nKeyConstant.INVITATION_IMPORT_VALIDATE_FAIL, LocaleContextHolder.getLocale()));
|
}
|
|
List<XpInvitationCode> addList = new ArrayList<>();
|
List<XpWhitelist> addWhitelistList = new ArrayList<>();
|
|
for (InvitationCodeImportExcel locationExcel : invitationCodeImportExcels) {
|
locationExcel.setBindTime(locationExcel.getBindTime());
|
XpInvitationCode xpInvitationCode = new XpInvitationCode();
|
xpInvitationCode.setInvitationCode(locationExcel.getInvitationCode());
|
xpInvitationCode.setBindAccount(locationExcel.getBindAccount());
|
if (StringUtils.hasLength(locationExcel.getBindTime())){
|
String replace = locationExcel.getBindTime().replace(".", "-");
|
String res = replace.replace("/", "-");
|
locationExcel.setBindTime(res);
|
}
|
|
xpInvitationCode.setBindTime(DateUtils.stringToLocalDateTime(locationExcel.getBindTime()));
|
xpInvitationCode.setStatus(2);
|
XpWhitelist xpWhitelist = new XpWhitelist();
|
xpWhitelist.setAccount(locationExcel.getBindAccount());
|
xpWhitelist.setStatus(true);
|
xpWhitelist.setIsPriorityDispatch(false);
|
xpWhitelist.setWhitelistSource(2);
|
addWhitelistList.add(xpWhitelist);
|
addList.add(xpInvitationCode);
|
}
|
xpInvitationCodeService.saveBatch(addList);
|
xpWhitelistService.saveBatch(addWhitelistList);
|
return R.ok();
|
}
|
|
private static String trimToNull(String value) {
|
if (!StringUtils.hasLength(value)) {
|
return null;
|
}
|
String trimmed = value.trim();
|
return StringUtils.hasLength(trimmed) ? trimmed : null;
|
}
|
|
private static boolean containsChinese(String value) {
|
if (!StringUtils.hasLength(value)) {
|
return false;
|
}
|
return CHINESE_PATTERN.matcher(value).find();
|
}
|
@ApiOperation(value = "邀请码导出")
|
@PostMapping(value = "/api/v1/invitation/exportExcel")
|
public void exportExcel(@RequestBody InvitationPageListQuery query) {
|
List<XpInvitationCode> list = xpInvitationCodeService.exportList(query);
|
List<XpInvitationCodeExportExcel> xpWhitelistExportExcels = new ArrayList<>();
|
for (XpInvitationCode xpInvitationCode : list) {
|
XpInvitationCodeExportExcel xpWhitelistExportExcel = new XpInvitationCodeExportExcel();
|
// xpWhitelistExportExcel.setId(xpInvitationCode.getId());
|
xpWhitelistExportExcel.setBind_account(xpInvitationCode.getBindAccount());
|
xpWhitelistExportExcel.setInvitationCode(xpInvitationCode.getInvitationCode());
|
LocalDateTime createTime = xpInvitationCode.getCreateTime();
|
LocalDateTime bindTime = xpInvitationCode.getBindTime();
|
// 将LocalDateTime转化为yyyy-MM-dd HH:mm:ss格式字符串
|
xpWhitelistExportExcel.setCreateTime(createTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
xpWhitelistExportExcel.setBindTime(bindTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
xpWhitelistExportExcels.add(xpWhitelistExportExcel);
|
}
|
//1.获取excel模板
|
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), XpInvitationCodeExportExcel.class, xpWhitelistExportExcels);
|
HttpServletResponse response = WebUtils.response();
|
response.setContentType("application/vnd.ms-excel");
|
response.setCharacterEncoding("utf-8");
|
ServletOutputStream outputStream = null;
|
try {
|
String fileName = URLEncoder.encode("邀请码列表.xls", "utf-8");
|
response.setHeader("Content-dispodition", "attachment;filename=" + fileName);
|
outputStream = response.getOutputStream();
|
workbook.write(outputStream);
|
} catch (IOException e) {
|
e.printStackTrace();
|
} finally {
|
try {
|
outputStream.close();
|
} catch (IOException e) {
|
e.printStackTrace();
|
}
|
}
|
|
}
|
/**
|
* 批量删除
|
*/
|
@GetMapping("/api/v1/invitation/deleteByIds")
|
@ResponseBody
|
@ApiOperation(value = "批量删除")
|
public R deleteByIds(String ids){
|
// 再转化为Long类型
|
List<Long> longs = Arrays.stream(ids.split(",")).map(Long::parseLong).collect(Collectors.toList());
|
xpInvitationCodeService.removeBatchByIds(longs);
|
return R.ok();
|
}
|
|
}
|