BUGFIX:1、教育通过上传文件批量创建子账号没有任何校验

2、下载子账号所有信息接口缺失(原下载模板接口保留)
3、保存个人模特到collection时类型设置为System
4、创建子账号时设置积分无效
This commit is contained in:
2025-08-15 17:44:45 +08:00
parent c28db81893
commit 45d6af92e8
11 changed files with 138 additions and 30 deletions

View File

@@ -233,6 +233,8 @@ public interface AccountService extends IService<Account> {
void subAccountImportExcelDownload(HttpServletResponse response);
void exportAccountsToExcel(HttpServletResponse response);
Boolean subAccountImport(MultipartFile file);
Set<String> organizationNameSearch(String type, String name);

View File

@@ -39,6 +39,8 @@ import com.zaxxer.hikari.HikariDataSource;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
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.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
@@ -2162,7 +2164,7 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
int subUserRole = getSubUserRole(account.getSystemUser());
if (addSubAccountDTO.getId() == null) {
return createSubAccount(addSubAccountDTO, account, subUserRole, null, null);
return createSubAccount(addSubAccountDTO, account, subUserRole, addSubAccountDTO.getCreditsUsageLimit(), null);
} else {
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
public Boolean subAccountImport(MultipartFile file) {
AuthPrincipalVo vo = UserContext.getUserHolder();
@@ -3069,29 +3153,24 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
// 示例:打印或保存
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();
account.setUserName(dto.getName());
account.setUserEmail(dto.getEmail());
account.setUserPassword(md5(dto.getPassword() + "abc"));
account.setCreditsUsageLimit(BigDecimal.valueOf(dto.getCredisUsageLimit()));
account.setParentId(vo.getId());
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);
AddSubAccountDTO addSubAccountDTO = new AddSubAccountDTO();
addSubAccountDTO.setUserEmail(dto.getEmail());
addSubAccountDTO.setUserName(dto.getEmail().substring(0, dto.getEmail().indexOf("@")));
addSubAccountDTO.setUserPassword(md5(parent.getOrganizationName().toLowerCase() + "abc"));
// 添加用户
addSubAccount(addSubAccountDTO);
}
return true;
@@ -3104,7 +3183,7 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
public static String md5(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] messageDigest = md.digest(input.getBytes());
byte[] messageDigest = md.digest(input.getBytes(StandardCharsets.UTF_8));
// 转为16进制字符串
StringBuilder sb = new StringBuilder();
@@ -3113,7 +3192,7 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
if (hex.length() == 1) sb.append('0'); // 补0
sb.append(hex);
}
return sb.append("abc").toString();
return sb.toString();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("MD5算法不可用", e);

View File

@@ -625,6 +625,10 @@ public class CollectionElementServiceImpl extends ServiceImpl<CollectionElementM
for (MannequinDTO mannequin : designDTO.getMannequins()) {
if (mannequin.getType().equals("System")) {
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")) {
// elementVO.setStyle(byId.getLevel3Type());
// }
@@ -645,7 +649,7 @@ public class CollectionElementServiceImpl extends ServiceImpl<CollectionElementM
elementVO.setDesignLibraryModelPoint(calculateTemplatePointTemplate(modelPoint, byId.getHigh(), byId.getWidth(), byId.getUrl()));
} else if (designDTO.getModelType().equals(ModelType.SYSTEM.getValue())) {
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());
}
LibraryModelPoint modelPoint = libraryModelPointService.getByRelationId(byId.getId(), designDTO.getModelType());

View File

@@ -178,7 +178,11 @@ public class DesignItemServiceImpl extends ServiceImpl<DesignItemMapper, DesignI
}
}
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

View File

@@ -1846,11 +1846,17 @@ public class GenerateServiceImpl extends ServiceImpl<GenerateMapper, Generate> i
// 所有修改的图片都另存为,不覆盖原图
if (proportionDTO.getType().equals("Library")) {
model = libraryService.getById(proportionDTO.getId());
if (Objects.isNull(model)){
throw new BusinessException("model.not.found");
}
String url = model.getUrl();
name = url.substring(url.indexOf("/") + 1, url.lastIndexOf("/")) + "/" + uuid;
// gender = model.getLevel2Type();
} else {
SysFileVO sysModel = sysFileService.getById(proportionDTO.getId());
if (Objects.isNull(sysModel)){
throw new BusinessException("model.not.found");
}
gender = sysModel.getLevel2Type();
name = accountId + "/models/" + gender.toLowerCase() + "/" + uuid;
}

View File

@@ -214,9 +214,12 @@ public class SysFileServiceImpl extends ServiceImpl<SysFileMapper, SysFile> impl
SysFileVO sysFile = LocalCacheUtils.getSysFileCache(id);
if (Objects.isNull(sysFile) || Objects.isNull(sysFile.getId())) {
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

View File

@@ -2642,7 +2642,7 @@ public class UserLikeGroupServiceImpl extends ServiceImpl<UserLikeGroupMapper, U
CollectionElementRelModel collectionElementRelModel = new CollectionElementRelModel();
collectionElementRelModel.setCollectionElementId(collectionElement.getId());
collectionElementRelModel.setRelationId(dto.getId());
collectionElementRelModel.setRelationType("System");
collectionElementRelModel.setRelationType("Library");
collectionElementRelModelMapper.insert(collectionElementRelModel);
}