Merge branch 'dev' into test

This commit is contained in:
chenbowen
2025-10-27 10:01:35 +08:00
15 changed files with 109 additions and 23 deletions

View File

@@ -43,6 +43,11 @@ public interface FileApi {
CommonResult<FileRespDTO> getFile(@Parameter(description = "文件编号", required = true, example = "1024")
@RequestParam("fileId") @NotNull(message = "文件编号不能为空") Long fileId);
@GetMapping(PREFIX + "/info")
@Operation(summary = "根据文件编号获取文件信息")
CommonResult<FileRespDTO> getFileInfo(@Parameter(description = "文件编号", required = true, example = "1024")
@RequestParam("fileId") @NotNull(message = "文件编号不能为空") Long fileId);
/**
* 删除文件
*

View File

@@ -16,6 +16,15 @@ public class FileRespDTO {
@Schema(description = "文件目录", example = "xxx")
private String directory;
@Schema(description = "文件访问地址", example = "https://www.iocoder.cn/xxx.png")
private String url;
@Schema(description = "文件预览地址", example = "https://www.iocoder.cn/preview/xxx")
private String previewUrl;
@Schema(description = "是否加密", example = "false")
private Boolean encrypted;
@Schema(description = "文件的 MIME 类型", example = "image/png")
private String type;

View File

@@ -1,6 +1,7 @@
package com.zt.plat.module.infra.api.file;
import com.zt.plat.framework.common.pojo.CommonResult;
import com.zt.plat.framework.common.util.object.BeanUtils;
import com.zt.plat.module.infra.api.file.dto.FileCreateReqDTO;
import com.zt.plat.module.infra.api.file.dto.FileRespDTO;
import com.zt.plat.module.infra.controller.admin.file.vo.file.FileRespVO;
@@ -76,6 +77,20 @@ public class FileApiImpl implements FileApi {
}
}
@Override
public CommonResult<FileRespDTO> getFileInfo(Long fileId) {
try {
FileDO fileDO = fileService.getActiveFileById(fileId);
if (fileDO == null) {
return CommonResult.error(404, "文件不存在");
}
FileRespDTO respDTO = convertToRespDTO(fileDO);
return success(respDTO);
} catch (Exception e) {
return CommonResult.error(500, "获取文件信息失败:" + e.getMessage());
}
}
@Override
public CommonResult<Boolean> deleteFile(Long fileId) {
try {
@@ -97,19 +112,23 @@ public class FileApiImpl implements FileApi {
* 将 FileDO 转换为 FileRespDTO
*/
private FileRespDTO convertToRespDTO(FileDO fileDO) {
FileRespVO fileRespVO = BeanUtils.toBean(fileDO, FileRespVO.class);
FileRespDTO respDTO = new FileRespDTO();
respDTO.setId(fileDO.getId());
respDTO.setName(fileDO.getName());
respDTO.setType(fileDO.getType());
respDTO.setSize(fileDO.getSize());
respDTO.setUrl(fileRespVO.getUrl());
respDTO.setPreviewUrl(fileRespVO.getPreviewUrl());
respDTO.setEncrypted(Boolean.TRUE.equals(fileRespVO.getIsEncrypted()));
// 从文件路径中提取目录信息
String path = fileDO.getPath();
if (path != null && path.contains("/")) {
String directory = path.substring(0, path.lastIndexOf("/"));
respDTO.setDirectory(directory);
}
return respDTO;
}
@@ -122,6 +141,9 @@ public class FileApiImpl implements FileApi {
respDTO.setName(fileRespVO.getName());
respDTO.setType(fileRespVO.getType());
respDTO.setSize(fileRespVO.getSize());
respDTO.setUrl(fileRespVO.getUrl());
respDTO.setPreviewUrl(fileRespVO.getPreviewUrl());
respDTO.setEncrypted(Boolean.TRUE.equals(fileRespVO.getIsEncrypted()));
// 从文件路径中提取目录信息
String path = fileRespVO.getPath();

View File

@@ -106,10 +106,15 @@ public class CodegenController {
@Operation(summary = "基于数据库的表结构,同步数据库的表和字段定义")
@PutMapping("/sync-from-db")
@Parameter(name = "tableId", description = "表编号", required = true, example = "1024")
@Parameters({
@Parameter(name = "tableId", description = "表编号", required = true, example = "1024"),
@Parameter(name = "isStandardized", description = "是否标准化缩写字段名", example = "false")
})
@PreAuthorize("@ss.hasPermission('infra:codegen:update')")
public CommonResult<Boolean> syncCodegenFromDB(@RequestParam("tableId") Long tableId) {
codegenService.syncCodegenFromDB(tableId);
public CommonResult<Boolean> syncCodegenFromDB(
@RequestParam("tableId") Long tableId,
@RequestParam(value = "isStandardized", required = false, defaultValue = "false") Boolean isStandardized) {
codegenService.syncCodegenFromDB(tableId, isStandardized);
return success(true);
}

View File

@@ -39,7 +39,7 @@ public interface CodegenService {
*
* @param tableId 表编号
*/
void syncCodegenFromDB(Long tableId);
void syncCodegenFromDB(Long tableId, Boolean isStandardized);
/**
* 删除数据库的表和字段定义

View File

@@ -148,14 +148,14 @@ public class CodegenServiceImpl implements CodegenService {
@Override
@Transactional(rollbackFor = Exception.class)
public void syncCodegenFromDB(Long tableId) {
public void syncCodegenFromDB(Long tableId, Boolean isStandardized) {
// 校验是否已经存在
CodegenTableDO table = codegenTableMapper.selectById(tableId);
if (table == null) {
throw exception(CODEGEN_TABLE_NOT_EXISTS);
}
// 从数据库中,获得数据库表结构
TableInfo tableInfo = databaseTableService.getTable(table.getDataSourceConfigId(), table.getTableName(),false);
TableInfo tableInfo = databaseTableService.getTable(table.getDataSourceConfigId(), table.getTableName(), Boolean.TRUE.equals(isStandardized));
// 执行同步
syncCodegen0(tableId, tableInfo);
}

View File

@@ -261,7 +261,7 @@ public class CodegenServiceImplTest extends BaseDbUnitTest {
}))).thenReturn(newColumns);
// 调用
codegenService.syncCodegenFromDB(tableId);
codegenService.syncCodegenFromDB(tableId, false);
// 断言
List<CodegenColumnDO> dbColumns = codegenColumnMapper.selectList();
assertEquals(newColumns.size(), dbColumns.size());

View File

@@ -41,7 +41,7 @@ public class AuthPermissionInfoRespVO {
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码")
private String nickname;
@Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.jpg")
@Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
private String avatar;
@Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")

View File

@@ -34,7 +34,7 @@ public class UserProfileRespVO {
@Schema(description = "用户性别,参见 SexEnum 枚举类", example = "1")
private Integer sex;
@Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png")
@Schema(description = "用户头像", example = "123456" )
private String avatar;
@Schema(description = "最后登录 IP", requiredMode = Schema.RequiredMode.REQUIRED, example = "192.168.1.1")

View File

@@ -1,5 +1,7 @@
package com.zt.plat.module.system.controller.admin.user.vo.profile;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonSetter;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Size;
@@ -28,8 +30,16 @@ public class UserProfileUpdateReqVO {
@Schema(description = "用户性别,参见 SexEnum 枚举类", example = "1")
private Integer sex;
@Schema(description = "角色头像", example = "https://www.iocoder.cn/1.png")
@URL(message = "头像地址格式不正确")
@Schema(description = "用户头像", example = "123456" )
private String avatar;
@JsonIgnore
private boolean avatarPresent;
@JsonSetter("avatar")
public void setAvatarValue(String avatar) {
this.avatar = avatar;
this.avatarPresent = true;
}
}

View File

@@ -54,7 +54,7 @@ public class UserRespVO{
@DictFormat(DictTypeConstants.USER_SEX)
private Integer sex;
@Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png")
@Schema(description = "用户头像", example = "123456789")
private String avatar;
@Schema(description = "状态,参见 CommonStatusEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")

View File

@@ -2,6 +2,7 @@ package com.zt.plat.module.system.controller.admin.user.vo.user;
import cn.hutool.core.util.ObjectUtil;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonSetter;
import com.mzt.logapi.starter.annotation.DiffLogField;
import com.zt.plat.framework.common.validation.Mobile;
import com.zt.plat.framework.common.validation.Password;
@@ -67,10 +68,19 @@ public class UserSaveReqVO {
@Schema(description = "用户状态", example = "1")
private Integer status;
@Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png")
@Schema(description = "用户头像", example = "123456789")
@DiffLogField(name = "用户头像")
private String avatar;
@JsonIgnore
private boolean avatarPresent;
@JsonSetter("avatar")
public void setAvatarValue(String avatar) {
this.avatar = avatar;
this.avatarPresent = true;
}
@Schema(description = "用户来源类型", example = "1")
private Integer userSource;

View File

@@ -29,7 +29,7 @@ public interface AuthConvert {
AuthLoginRespVO convert(OAuth2AccessTokenDO bean);
default AuthPermissionInfoRespVO convert(AdminUserDO user, List<RoleDO> roleList, List<MenuDO> menuList) {
return AuthPermissionInfoRespVO.builder()
AuthPermissionInfoRespVO respVO = AuthPermissionInfoRespVO.builder()
.user(BeanUtils.toBean(user, AuthPermissionInfoRespVO.UserVO.class))
.roles(convertSet(roleList, RoleDO::getCode))
// 权限标识信息
@@ -37,6 +37,10 @@ public interface AuthConvert {
// 菜单树
.menus(buildMenuTree(menuList))
.build();
if (respVO.getUser() != null) {
respVO.getUser().setAvatar(user.getAvatar());
}
return respVO;
}
AuthPermissionInfoRespVO.MenuVO convertTreeNode(MenuDO menu);

View File

@@ -31,6 +31,7 @@ public interface UserConvert {
default UserRespVO convert(AdminUserDO user) {
UserRespVO vo = BeanUtils.toBean(user, UserRespVO.class);
vo.setAvatar(user.getAvatar());
if (user.getDeptIds() != null) {
vo.setDeptIds(CollectionUtils.convertList(user.getDeptIds(), Long::longValue));
}
@@ -47,6 +48,7 @@ public interface UserConvert {
default UserProfileRespVO convert(AdminUserDO user, List<RoleDO> userRoles,
List<DeptDO> depts, List<PostDO> posts) {
UserProfileRespVO userVO = BeanUtils.toBean(user, UserProfileRespVO.class);
userVO.setAvatar(user.getAvatar());
userVO.setRoles(BeanUtils.toBean(userRoles, RoleSimpleRespVO.class));
userVO.setDepts(BeanUtils.toBean(depts, DeptSimpleRespVO.class));
userVO.setPosts(BeanUtils.toBean(posts, PostSimpleRespVO.class));

View File

@@ -119,6 +119,7 @@ public class AdminUserServiceImpl implements AdminUserService {
if (user.getUserSource() == null) {
user.setUserSource(UserSourceEnum.EXTERNAL.getSource());
}
user.setAvatar(normalizeAvatarValue(createReqVO.getAvatar()));
user.setPassword(encodePassword(createReqVO.getPassword()));
userMapper.insert(user);
// 2.2 插入关联部门
@@ -202,6 +203,9 @@ public class AdminUserServiceImpl implements AdminUserService {
if (StrUtil.isNotBlank(updateReqVO.getRemark())) {
updateObj.setRemark(updateReqVO.getRemark());
}
if (updateReqVO.isAvatarPresent()) {
updateObj.setAvatar(normalizeAvatarValue(updateReqVO.getAvatar()));
}
userMapper.updateById(updateObj);
// 2.2 更新部门
@@ -250,7 +254,12 @@ public class AdminUserServiceImpl implements AdminUserService {
validateEmailUnique(id, reqVO.getEmail());
validateMobileUnique(id, reqVO.getMobile());
// 执行更新
userMapper.updateById(BeanUtils.toBean(reqVO, AdminUserDO.class).setId(id));
AdminUserDO updateObj = BeanUtils.toBean(reqVO, AdminUserDO.class);
updateObj.setId(id);
if (reqVO.isAvatarPresent()) {
updateObj.setAvatar(normalizeAvatarValue(reqVO.getAvatar()));
}
userMapper.updateById(updateObj);
}
@Override
@@ -313,12 +322,14 @@ public class AdminUserServiceImpl implements AdminUserService {
@Override
public AdminUserDO getUserByUsername(String username) {
return userMapper.selectByUsername(username);
AdminUserDO user = userMapper.selectByUsername(username);
return user;
}
@Override
public AdminUserDO getUserByMobile(String mobile) {
return userMapper.selectByMobile(mobile);
AdminUserDO user = userMapper.selectByMobile(mobile);
return user;
}
@Override
@@ -375,7 +386,8 @@ public class AdminUserServiceImpl implements AdminUserService {
if (CollUtil.isEmpty(userIds)) {
return Collections.emptyList();
}
return userMapper.selectBatchIds(userIds);
List<AdminUserDO> users = userMapper.selectBatchIds(userIds);
return users;
}
@Override
@@ -383,7 +395,8 @@ public class AdminUserServiceImpl implements AdminUserService {
if (CollUtil.isEmpty(ids)) {
return Collections.emptyList();
}
return userMapper.selectListByIds(ids);
List<AdminUserDO> users = userMapper.selectListByIds(ids);
return users;
}
@Override
@@ -408,7 +421,8 @@ public class AdminUserServiceImpl implements AdminUserService {
@Override
public List<AdminUserDO> getUserListByNickname(String nickname) {
return userMapper.selectListByNickname(nickname);
List<AdminUserDO> users = userMapper.selectListByNickname(nickname);
return users;
}
/**
@@ -468,6 +482,10 @@ public class AdminUserServiceImpl implements AdminUserService {
});
}
private String normalizeAvatarValue(String avatarValue) {
return StrUtil.isBlank(avatarValue) ? null : avatarValue.trim();
}
private AdminUserDO validateUserForCreateOrUpdate(Long id, String username, String mobile, String email,
Set<Long> deptIds, Set<Long> postIds) {
// 关闭数据权限,避免因为没有数据权限,查询不到数据,进而导致唯一校验不正确
@@ -572,7 +590,8 @@ public class AdminUserServiceImpl implements AdminUserService {
@Override
public List<AdminUserDO> getUserListByStatus(Integer status) {
return userMapper.selectListByStatus(status);
List<AdminUserDO> users = userMapper.selectListByStatus(status);
return users;
}
@Override