BUGFIX:1、教育通过上传文件批量创建子账号没有任何校验
2、下载子账号所有信息接口缺失(原下载模板接口保留) 3、保存个人模特到collection时类型设置为System 4、创建子账号时设置积分无效
This commit is contained in:
@@ -369,6 +369,12 @@ public class AccountController {
|
|||||||
accountService.subAccountImportExcelDownload(response);
|
accountService.subAccountImportExcelDownload(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/exportAccountsToExcel")
|
||||||
|
@ApiOperation(value = "下载子账号信息")
|
||||||
|
public void exportAccountsToExcel(HttpServletResponse response) {
|
||||||
|
accountService.exportAccountsToExcel(response);
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping("/subAccountImport")
|
@PostMapping("/subAccountImport")
|
||||||
@ApiOperation(value = "模板导入")
|
@ApiOperation(value = "模板导入")
|
||||||
public Response<Boolean> subAccountImport(@RequestParam("file") MultipartFile file) {
|
public Response<Boolean> subAccountImport(@RequestParam("file") MultipartFile file) {
|
||||||
|
|||||||
@@ -19,4 +19,6 @@ public class GetNextSysElementVO {
|
|||||||
@ApiModelProperty("对应的图片的绝对路径")
|
@ApiModelProperty("对应的图片的绝对路径")
|
||||||
private String path;
|
private String path;
|
||||||
|
|
||||||
|
public GetNextSysElementVO() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -233,6 +233,8 @@ public interface AccountService extends IService<Account> {
|
|||||||
|
|
||||||
void subAccountImportExcelDownload(HttpServletResponse response);
|
void subAccountImportExcelDownload(HttpServletResponse response);
|
||||||
|
|
||||||
|
void exportAccountsToExcel(HttpServletResponse response);
|
||||||
|
|
||||||
Boolean subAccountImport(MultipartFile file);
|
Boolean subAccountImport(MultipartFile file);
|
||||||
|
|
||||||
Set<String> organizationNameSearch(String type, String name);
|
Set<String> organizationNameSearch(String type, String name);
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ import com.zaxxer.hikari.HikariDataSource;
|
|||||||
import io.netty.util.internal.StringUtil;
|
import io.netty.util.internal.StringUtil;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.poi.ss.usermodel.*;
|
||||||
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -2162,7 +2164,7 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
|||||||
int subUserRole = getSubUserRole(account.getSystemUser());
|
int subUserRole = getSubUserRole(account.getSystemUser());
|
||||||
|
|
||||||
if (addSubAccountDTO.getId() == null) {
|
if (addSubAccountDTO.getId() == null) {
|
||||||
return createSubAccount(addSubAccountDTO, account, subUserRole, null, null);
|
return createSubAccount(addSubAccountDTO, account, subUserRole, addSubAccountDTO.getCreditsUsageLimit(), null);
|
||||||
} else {
|
} else {
|
||||||
return updateSubAccount(addSubAccountDTO, account, subUserRole);
|
return updateSubAccount(addSubAccountDTO, account, subUserRole);
|
||||||
}
|
}
|
||||||
@@ -3056,6 +3058,88 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exportAccountsToExcel(HttpServletResponse response) {
|
||||||
|
Workbook workbook = null;
|
||||||
|
try {
|
||||||
|
// 1. 查询数据
|
||||||
|
Account adminAcc = baseMapper.selectById(UserContext.getUserHolder().getId());
|
||||||
|
List<Account> accounts = accountMapper.selectList(new QueryWrapper<Account>()
|
||||||
|
.eq("organization_name", adminAcc.getOrganizationName())
|
||||||
|
.eq("system_user", 8)
|
||||||
|
.select("user_name", "user_email", "user_password", "credits_usage_limit"));
|
||||||
|
|
||||||
|
// 2. 创建Excel工作簿
|
||||||
|
workbook = new XSSFWorkbook();
|
||||||
|
Sheet sheet = workbook.createSheet("subAccounts");
|
||||||
|
|
||||||
|
// 3. 创建标题行
|
||||||
|
Row headerRow = sheet.createRow(0);
|
||||||
|
String[] headers = {"name", "email", "password", "creditsUsageLimit"};
|
||||||
|
|
||||||
|
// 设置标题样式
|
||||||
|
CellStyle headerStyle = workbook.createCellStyle();
|
||||||
|
Font headerFont = workbook.createFont();
|
||||||
|
headerFont.setBold(true);
|
||||||
|
headerStyle.setFont(headerFont);
|
||||||
|
|
||||||
|
// 写入标题
|
||||||
|
for (int i = 0; i < headers.length; i++) {
|
||||||
|
Cell cell = headerRow.createCell(i);
|
||||||
|
cell.setCellValue(headers[i]);
|
||||||
|
cell.setCellStyle(headerStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 写入数据
|
||||||
|
int rowNum = 1;
|
||||||
|
for (Account account : accounts) {
|
||||||
|
Row row = sheet.createRow(rowNum++);
|
||||||
|
row.createCell(0).setCellValue(account.getUserName() != null ? account.getUserName() : "");
|
||||||
|
row.createCell(1).setCellValue(account.getUserEmail() != null ? account.getUserEmail() : "");
|
||||||
|
row.createCell(2).setCellValue(account.getUserPassword() != null ? account.getUserPassword() : "");
|
||||||
|
|
||||||
|
// 更安全的数据类型处理
|
||||||
|
if (account.getCreditsUsageLimit() != null) {
|
||||||
|
row.createCell(3).setCellValue(String.valueOf(account.getCreditsUsageLimit()));
|
||||||
|
} else {
|
||||||
|
row.createCell(3).setCellValue(""); // 空字符串
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 自动调整列宽
|
||||||
|
for (int i = 0; i < headers.length; i++) {
|
||||||
|
sheet.autoSizeColumn(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. 重置响应(重要!)
|
||||||
|
response.reset();
|
||||||
|
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||||
|
response.setCharacterEncoding("UTF-8");
|
||||||
|
|
||||||
|
// 设置文件名(处理特殊字符)
|
||||||
|
String fileName = "subAccount_export.xlsx";
|
||||||
|
String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replace("+", "%20");
|
||||||
|
response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encodedFileName);
|
||||||
|
|
||||||
|
// 7. 写入响应流
|
||||||
|
OutputStream outputStream = response.getOutputStream();
|
||||||
|
workbook.write(outputStream);
|
||||||
|
outputStream.flush();
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error(e.getMessage()); // 记录异常信息
|
||||||
|
throw new BusinessException("导出文件失败");
|
||||||
|
} finally {
|
||||||
|
// 确保资源关闭
|
||||||
|
if (workbook != null) {
|
||||||
|
try {
|
||||||
|
workbook.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error(e.getMessage()); // 记录异常信息
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Boolean subAccountImport(MultipartFile file) {
|
public Boolean subAccountImport(MultipartFile file) {
|
||||||
AuthPrincipalVo vo = UserContext.getUserHolder();
|
AuthPrincipalVo vo = UserContext.getUserHolder();
|
||||||
@@ -3069,29 +3153,24 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
|||||||
|
|
||||||
// 示例:打印或保存
|
// 示例:打印或保存
|
||||||
for (SubAccountImportDTO dto : importList) {
|
for (SubAccountImportDTO dto : importList) {
|
||||||
|
// 只有当前子账号数量为0时允许批量上传
|
||||||
|
QueryWrapper<Account> qw = new QueryWrapper<>();
|
||||||
|
qw.lambda().eq(Account::getSystemUser, 8)
|
||||||
|
.eq(Account::getOrganizationName, parent.getOrganizationName());
|
||||||
|
List<Account> accounts = accountMapper.selectList(qw);
|
||||||
|
if (!accounts.isEmpty()){
|
||||||
|
throw new BusinessException("permit.bulk.creation", ResultEnum.PROMPT.getCode());
|
||||||
|
}
|
||||||
|
if (importList.size() > parent.getSubAccountNum() - 1){
|
||||||
|
throw new BusinessException("Action required: You cannot create [" +importList.size() + "] sub-accounts (Current quota: [" + (parent.getSubAccountNum() - 1) + "]).");
|
||||||
|
}
|
||||||
|
|
||||||
Account account = new Account();
|
AddSubAccountDTO addSubAccountDTO = new AddSubAccountDTO();
|
||||||
account.setUserName(dto.getName());
|
addSubAccountDTO.setUserEmail(dto.getEmail());
|
||||||
account.setUserEmail(dto.getEmail());
|
addSubAccountDTO.setUserName(dto.getEmail().substring(0, dto.getEmail().indexOf("@")));
|
||||||
account.setUserPassword(md5(dto.getPassword() + "abc"));
|
addSubAccountDTO.setUserPassword(md5(parent.getOrganizationName().toLowerCase() + "abc"));
|
||||||
account.setCreditsUsageLimit(BigDecimal.valueOf(dto.getCredisUsageLimit()));
|
// 添加用户
|
||||||
account.setParentId(vo.getId());
|
addSubAccount(addSubAccountDTO);
|
||||||
account.setValidStartTime(parent.getValidStartTime());
|
|
||||||
account.setValidEndTime(parent.getValidEndTime());
|
|
||||||
account.setCreateDate(new Date());
|
|
||||||
account.setIsTrial(0);
|
|
||||||
account.setIsBeginner(1);
|
|
||||||
account.setCredits(BigDecimal.valueOf(0));
|
|
||||||
account.setLanguage(Language.ENGLISH.name());
|
|
||||||
if (parent.getSystemUser() == 5) {
|
|
||||||
account.setSystemUser(6);
|
|
||||||
}
|
|
||||||
if (parent.getSystemUser() == 7) {
|
|
||||||
account.setSystemUser(8);
|
|
||||||
}
|
|
||||||
account.setOrganizationName(parent.getOrganizationName());
|
|
||||||
account.setParentId(parent.getId());
|
|
||||||
accountMapper.insert(account);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -3104,7 +3183,7 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
|||||||
public static String md5(String input) {
|
public static String md5(String input) {
|
||||||
try {
|
try {
|
||||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||||
byte[] messageDigest = md.digest(input.getBytes());
|
byte[] messageDigest = md.digest(input.getBytes(StandardCharsets.UTF_8));
|
||||||
|
|
||||||
// 转为16进制字符串
|
// 转为16进制字符串
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
@@ -3113,7 +3192,7 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
|||||||
if (hex.length() == 1) sb.append('0'); // 补0
|
if (hex.length() == 1) sb.append('0'); // 补0
|
||||||
sb.append(hex);
|
sb.append(hex);
|
||||||
}
|
}
|
||||||
return sb.append("abc").toString();
|
return sb.toString();
|
||||||
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
throw new RuntimeException("MD5算法不可用", e);
|
throw new RuntimeException("MD5算法不可用", e);
|
||||||
|
|||||||
@@ -625,6 +625,10 @@ public class CollectionElementServiceImpl extends ServiceImpl<CollectionElementM
|
|||||||
for (MannequinDTO mannequin : designDTO.getMannequins()) {
|
for (MannequinDTO mannequin : designDTO.getMannequins()) {
|
||||||
if (mannequin.getType().equals("System")) {
|
if (mannequin.getType().equals("System")) {
|
||||||
SysFileVO byId = sysFileService.getById(mannequin.getId());
|
SysFileVO byId = sysFileService.getById(mannequin.getId());
|
||||||
|
if (Objects.isNull(byId)){
|
||||||
|
log.info("未知模特:{}:{}", mannequin.getId(), "System");
|
||||||
|
throw new BusinessException("model.not.found");
|
||||||
|
}
|
||||||
// if (!StringUtils.isEmpty(byId.getLevel3Type()) && byId.getLevel2Type().equals("Female")) {
|
// if (!StringUtils.isEmpty(byId.getLevel3Type()) && byId.getLevel2Type().equals("Female")) {
|
||||||
// elementVO.setStyle(byId.getLevel3Type());
|
// elementVO.setStyle(byId.getLevel3Type());
|
||||||
// }
|
// }
|
||||||
@@ -645,7 +649,7 @@ public class CollectionElementServiceImpl extends ServiceImpl<CollectionElementM
|
|||||||
elementVO.setDesignLibraryModelPoint(calculateTemplatePointTemplate(modelPoint, byId.getHigh(), byId.getWidth(), byId.getUrl()));
|
elementVO.setDesignLibraryModelPoint(calculateTemplatePointTemplate(modelPoint, byId.getHigh(), byId.getWidth(), byId.getUrl()));
|
||||||
} else if (designDTO.getModelType().equals(ModelType.SYSTEM.getValue())) {
|
} else if (designDTO.getModelType().equals(ModelType.SYSTEM.getValue())) {
|
||||||
SysFileVO byId = sysFileService.getById(designDTO.getTemplateId());
|
SysFileVO byId = sysFileService.getById(designDTO.getTemplateId());
|
||||||
if (!StringUtils.isEmpty(byId.getLevel3Type()) && byId.getLevel2Type().equals("Female")) {
|
if (Objects.nonNull(byId) && !StringUtils.isEmpty(byId.getLevel3Type()) && byId.getLevel2Type().equals("Female")) {
|
||||||
elementVO.setStyle(byId.getLevel3Type());
|
elementVO.setStyle(byId.getLevel3Type());
|
||||||
}
|
}
|
||||||
LibraryModelPoint modelPoint = libraryModelPointService.getByRelationId(byId.getId(), designDTO.getModelType());
|
LibraryModelPoint modelPoint = libraryModelPointService.getByRelationId(byId.getId(), designDTO.getModelType());
|
||||||
|
|||||||
@@ -178,7 +178,11 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
SysFileVO sysFileVO = sysFileService.getById(idValue);
|
SysFileVO sysFileVO = sysFileService.getById(idValue);
|
||||||
return new GetNextSysElementVO(sysFileVO.getId(), level2Type, sysFileVO.getUrl());
|
if (Objects.nonNull(sysFileVO)){
|
||||||
|
return new GetNextSysElementVO(sysFileVO.getId(), level2Type, sysFileVO.getUrl());
|
||||||
|
}else {
|
||||||
|
return new GetNextSysElementVO();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1846,11 +1846,17 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
|
|||||||
// 所有修改的图片都另存为,不覆盖原图
|
// 所有修改的图片都另存为,不覆盖原图
|
||||||
if (proportionDTO.getType().equals("Library")) {
|
if (proportionDTO.getType().equals("Library")) {
|
||||||
model = libraryService.getById(proportionDTO.getId());
|
model = libraryService.getById(proportionDTO.getId());
|
||||||
|
if (Objects.isNull(model)){
|
||||||
|
throw new BusinessException("model.not.found");
|
||||||
|
}
|
||||||
String url = model.getUrl();
|
String url = model.getUrl();
|
||||||
name = url.substring(url.indexOf("/") + 1, url.lastIndexOf("/")) + "/" + uuid;
|
name = url.substring(url.indexOf("/") + 1, url.lastIndexOf("/")) + "/" + uuid;
|
||||||
// gender = model.getLevel2Type();
|
// gender = model.getLevel2Type();
|
||||||
} else {
|
} else {
|
||||||
SysFileVO sysModel = sysFileService.getById(proportionDTO.getId());
|
SysFileVO sysModel = sysFileService.getById(proportionDTO.getId());
|
||||||
|
if (Objects.isNull(sysModel)){
|
||||||
|
throw new BusinessException("model.not.found");
|
||||||
|
}
|
||||||
gender = sysModel.getLevel2Type();
|
gender = sysModel.getLevel2Type();
|
||||||
name = accountId + "/models/" + gender.toLowerCase() + "/" + uuid;
|
name = accountId + "/models/" + gender.toLowerCase() + "/" + uuid;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -214,9 +214,12 @@ public class SysFileServiceImpl extends ServiceImpl<SysFileMapper, SysFile> impl
|
|||||||
SysFileVO sysFile = LocalCacheUtils.getSysFileCache(id);
|
SysFileVO sysFile = LocalCacheUtils.getSysFileCache(id);
|
||||||
if (Objects.isNull(sysFile) || Objects.isNull(sysFile.getId())) {
|
if (Objects.isNull(sysFile) || Objects.isNull(sysFile.getId())) {
|
||||||
sysFile = CopyUtil.copyObject(sysFileMapper.selectById(id), SysFileVO.class);
|
sysFile = CopyUtil.copyObject(sysFileMapper.selectById(id), SysFileVO.class);
|
||||||
LocalCacheUtils.setSysFileCache(id, sysFile);
|
if (Objects.nonNull(sysFile)){
|
||||||
|
LocalCacheUtils.setSysFileCache(id, sysFile);
|
||||||
|
return sysFile;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return sysFile;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -2642,7 +2642,7 @@ public class UserLikeGroupServiceImpl extends ServiceImpl<UserLikeGroupMapper, U
|
|||||||
CollectionElementRelModel collectionElementRelModel = new CollectionElementRelModel();
|
CollectionElementRelModel collectionElementRelModel = new CollectionElementRelModel();
|
||||||
collectionElementRelModel.setCollectionElementId(collectionElement.getId());
|
collectionElementRelModel.setCollectionElementId(collectionElement.getId());
|
||||||
collectionElementRelModel.setRelationId(dto.getId());
|
collectionElementRelModel.setRelationId(dto.getId());
|
||||||
collectionElementRelModel.setRelationType("System");
|
collectionElementRelModel.setRelationType("Library");
|
||||||
collectionElementRelModelMapper.insert(collectionElementRelModel);
|
collectionElementRelModelMapper.insert(collectionElementRelModel);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,6 +158,7 @@ this.promotion.code.is.invalid=This promotion code is invalid.
|
|||||||
one.time.limit.per.customer=This code has already been redeemed. Promo codes are limited to one-time use per customer.
|
one.time.limit.per.customer=This code has already been redeemed. Promo codes are limited to one-time use per customer.
|
||||||
element.already.exists=This element already exists in the public library
|
element.already.exists=This element already exists in the public library
|
||||||
have.no.permission=Sorry, you don't have permission
|
have.no.permission=Sorry, you don't have permission
|
||||||
|
permit.bulk.creation=The system permits bulk account creation exclusively when no sub-accounts exist.
|
||||||
|
|
||||||
# 可能会报异常
|
# 可能会报异常
|
||||||
# Informative:
|
# Informative:
|
||||||
|
|||||||
@@ -154,6 +154,7 @@ this.promotion.code.is.invalid=该促销码无效。
|
|||||||
one.time.limit.per.customer=该码已兑换。每个促销码每位用户仅限使用一次。
|
one.time.limit.per.customer=该码已兑换。每个促销码每位用户仅限使用一次。
|
||||||
element.already.exists=元素已存在于公共库中
|
element.already.exists=元素已存在于公共库中
|
||||||
have.no.permission=您没有权限
|
have.no.permission=您没有权限
|
||||||
|
permit.bulk.creation=系统仅当不存在任何子账号时,才允许批量创建账号。
|
||||||
|
|
||||||
# 可能会报异常
|
# 可能会报异常
|
||||||
# Informative:
|
# Informative:
|
||||||
|
|||||||
Reference in New Issue
Block a user