feat: 管理员修改用户姓名、批量创建机构用户接口(单条失败不影响其他,返回逐条结果)
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# 前端接口文档 —— 用户管理增强 & 机构账号查询 & 按手机号查询文件记录
|
# 前端接口文档 —— 用户管理增强 & 机构账号查询 & 按手机号查询文件记录
|
||||||
|
|
||||||
> 版本:v1.0(2026-09-14)
|
> 版本:v1.2(2026-10-27,新增 1.4 修改用户姓名、1.5 批量创建机构用户)
|
||||||
> 适用后端:s-file(alita-bjy-uygur)
|
> 适用后端:s-file(alita-bjy-uygur)
|
||||||
> Swagger 分组:「用户」「用户文件」
|
> Swagger 分组:「用户」「用户文件」
|
||||||
|
|
||||||
@@ -170,6 +170,94 @@ POST /user/admin_cancel
|
|||||||
|
|
||||||
> **与既有接口的区别**:既有 `POST /user/cancel` 为机构内注销(限定当前登录机构、且要求目标账号启用中),供原「注销申请/同意」流程使用,保持不变;本接口供系统管理员在用户管理页面跨机构直接注销。
|
> **与既有接口的区别**:既有 `POST /user/cancel` 为机构内注销(限定当前登录机构、且要求目标账号启用中),供原「注销申请/同意」流程使用,保持不变;本接口供系统管理员在用户管理页面跨机构直接注销。
|
||||||
|
|
||||||
|
### 1.4 修改用户姓名
|
||||||
|
|
||||||
|
修改用户账号的真实姓名(`real_name`)。平台超管可修改全部用户;机构管理员仅可修改本机构用户(同一账号属于多个机构时,改的是账号本身,各机构下展示同步生效)。
|
||||||
|
|
||||||
|
- **URL**:`POST /user/modify_real_name`
|
||||||
|
- **权限**:平台超管(全部用户)/ 机构管理员(限本机构用户)
|
||||||
|
- **Body**(application/json)
|
||||||
|
|
||||||
|
| 字段 | 类型 | 必填 | 说明 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| userId | Long | 是 | 目标用户 id |
|
||||||
|
| realName | String | 是 | 新姓名,2-30 位,仅支持中文或英文姓名 |
|
||||||
|
|
||||||
|
- **返回**:`AlitaResult<Boolean>`,data 为 `true`
|
||||||
|
- **失败场景**:
|
||||||
|
- 用户不存在
|
||||||
|
- 目标已注销(提示「已注销账号不可修改姓名」)
|
||||||
|
- 姓名格式错误(提示「姓名格式错误!(长度2-30位,仅支持中文或英文姓名)」)
|
||||||
|
- 与原姓名一致(提示「姓名与原姓名一致,无需修改!」)
|
||||||
|
- 机构管理员操作非本机构用户(提示「只能操作本机构的用户」)
|
||||||
|
|
||||||
|
**请求示例**
|
||||||
|
|
||||||
|
```json
|
||||||
|
POST /user/modify_real_name
|
||||||
|
{ "userId": 10086, "realName": "张三" }
|
||||||
|
```
|
||||||
|
|
||||||
|
**返回示例**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "code": "200", "success": true, "data": true }
|
||||||
|
```
|
||||||
|
|
||||||
|
> **与既有接口的区别**:既有 `POST /user/modify_org_user_info` 为超管编辑企业用户完整信息(账号名/姓名/启用状态一起校验更新);本接口仅更新姓名,供用户管理页与机构账号页的「修改姓名」入口使用。
|
||||||
|
|
||||||
|
### 1.5 批量创建机构用户
|
||||||
|
|
||||||
|
一次性提交多条「手机号 + 姓名」创建机构用户。**单条失败不影响其他条目**(每条独立事务),返回与入参**顺序一一对应**的逐条结果,前端据此展示失败项。
|
||||||
|
|
||||||
|
- **URL**:`POST /user/batch_create_org_user`
|
||||||
|
- **权限**:登录用户(机构取当前登录机构,与单条创建 `POST /user/create_org_user` 一致)
|
||||||
|
- **Body**(application/json,对象数组,单次最多 **500** 条)
|
||||||
|
|
||||||
|
数组元素字段:
|
||||||
|
|
||||||
|
| 字段 | 类型 | 必填 | 说明 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| phone | String | 是 | 手机号 |
|
||||||
|
| realName | String | 否 | 姓名 |
|
||||||
|
|
||||||
|
- **返回**:`AlitaResult<List<OrgUserCreateResultDTO>>`
|
||||||
|
|
||||||
|
**OrgUserCreateResultDTO 字段**
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|---|---|---|
|
||||||
|
| phone | String | 手机号(回显入参) |
|
||||||
|
| realName | String | 姓名(回显入参) |
|
||||||
|
| success | Boolean | 是否创建成功 |
|
||||||
|
| userId | Long | 用户 id,失败时为 null |
|
||||||
|
| msg | String | 失败原因,成功时为 null |
|
||||||
|
|
||||||
|
**请求示例**
|
||||||
|
|
||||||
|
```json
|
||||||
|
POST /user/batch_create_org_user
|
||||||
|
[
|
||||||
|
{ "phone": "13800000001", "realName": "张三" },
|
||||||
|
{ "phone": "13800000002", "realName": "李四" }
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
**返回示例**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": "200",
|
||||||
|
"success": true,
|
||||||
|
"data": [
|
||||||
|
{ "phone": "13800000001", "realName": "张三", "success": true, "userId": 1001, "msg": null },
|
||||||
|
{ "phone": "13800000002", "realName": "李四", "success": false, "userId": null, "msg": "手机号已存在,不能重复添加" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- **失败场景**(整体请求失败):列表为空;超过 500 条(提示「单次批量创建不能超过500条」)。单条业务失败(手机号格式不正确、手机号已存在等)不使请求失败,体现在对应条目的 `success/msg` 中。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. 系统管理员:查看各机构下的账号信息
|
## 2. 系统管理员:查看各机构下的账号信息
|
||||||
@@ -405,3 +493,6 @@ GET /user_file/record/page_by_phone?phone=13800000001&recordType=2&pageNo=1&page
|
|||||||
| 禁用/注销超管 | 不能禁用超级管理员账号 / 不能注销超级管理员账号 |
|
| 禁用/注销超管 | 不能禁用超级管理员账号 / 不能注销超级管理员账号 |
|
||||||
| recordType 非法 | 记录类型不合法,仅支持1上传/2发送/3接收 |
|
| recordType 非法 | 记录类型不合法,仅支持1上传/2发送/3接收 |
|
||||||
| phone 为空 | 手机号不能为空 |
|
| phone 为空 | 手机号不能为空 |
|
||||||
|
| 修改姓名格式错误 | 姓名格式错误!(长度2-30位,仅支持中文或英文姓名) |
|
||||||
|
| 修改姓名与原值相同 | 姓名与原姓名一致,无需修改! |
|
||||||
|
| 机构管理员越机构操作 | 只能操作本机构的用户 |
|
||||||
|
|||||||
@@ -115,6 +115,15 @@ public class UserController {
|
|||||||
return AlitaResult.success(userService.createOrgUser(orgUserCreateDTO));
|
return AlitaResult.success(userService.createOrgUser(orgUserCreateDTO));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("user/batch_create_org_user")
|
||||||
|
@ApiOperation("批量创建机构用户(单条失败不影响其他条目,返回逐条结果)")
|
||||||
|
public AlitaResult<List<OrgUserCreateResultDTO>> batchCreateOrgUser(
|
||||||
|
@Validated @RequestBody List<OrgUserCreateDTO> orgUserCreateDTOs) {
|
||||||
|
orgUserCreateDTOs.forEach(orgUserCreateDTO ->
|
||||||
|
orgUserCreateDTO.setOrgId(UserContextHolder.getExistLoginOrgId()));
|
||||||
|
return AlitaResult.success(userService.batchCreateOrgUser(orgUserCreateDTOs));
|
||||||
|
}
|
||||||
|
|
||||||
@PutMapping("user/modify_org_user")
|
@PutMapping("user/modify_org_user")
|
||||||
@ApiOperation("修改机构用户")
|
@ApiOperation("修改机构用户")
|
||||||
public AlitaResult modifyOrgUser(@Validated @RequestBody OrgUserModifyDTO orgUserModifyDTO) {
|
public AlitaResult modifyOrgUser(@Validated @RequestBody OrgUserModifyDTO orgUserModifyDTO) {
|
||||||
@@ -301,4 +310,10 @@ public class UserController {
|
|||||||
userService.pageOrgAccount(queryDTO);
|
userService.pageOrgAccount(queryDTO);
|
||||||
return AlitaResult.success(queryDTO.getPageResult());
|
return AlitaResult.success(queryDTO.getPageResult());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("user/modify_real_name")
|
||||||
|
@ApiOperation("修改用户姓名(系统管理员)")
|
||||||
|
public AlitaResult<Boolean> modifyRealName(@Validated @RequestBody UserRealNameModifyDTO reqDTO) {
|
||||||
|
return AlitaResult.success(userService.modifyRealName(reqDTO));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package com.senmesh.usercenter.user.dto;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量创建机构用户单条结果
|
||||||
|
*
|
||||||
|
* @author liu on 2026-10-27
|
||||||
|
*/
|
||||||
|
@ApiModel(description = "批量创建机构用户结果")
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class OrgUserCreateResultDTO {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@ApiModelProperty("手机号")
|
||||||
|
private String phone;
|
||||||
|
|
||||||
|
@ApiModelProperty("姓名")
|
||||||
|
private String realName;
|
||||||
|
|
||||||
|
@ApiModelProperty("是否创建成功")
|
||||||
|
private Boolean success;
|
||||||
|
|
||||||
|
@ApiModelProperty("用户id,失败时为null")
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
@ApiModelProperty("失败原因,成功时为null")
|
||||||
|
private String msg;
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.senmesh.usercenter.user.dto;
|
||||||
|
|
||||||
|
import com.senmesh.common.dto.BaseOperateDTO;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改用户姓名操作DTO
|
||||||
|
*
|
||||||
|
* @author liu on 2026-10-27
|
||||||
|
*/
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Builder
|
||||||
|
@ApiModel(description = "修改用户姓名操作")
|
||||||
|
public class UserRealNameModifyDTO extends BaseOperateDTO {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@ApiModelProperty("用户id")
|
||||||
|
@NotNull(message = "用户id不能为空")
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
@ApiModelProperty("姓名")
|
||||||
|
@NotBlank(message = "姓名不能为空")
|
||||||
|
private String realName;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -157,6 +157,15 @@ public interface UserService {
|
|||||||
*/
|
*/
|
||||||
Long createOrgUser(OrgUserCreateDTO orgUserCreateDTO);
|
Long createOrgUser(OrgUserCreateDTO orgUserCreateDTO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量创建企业用户
|
||||||
|
* 单条失败仅回滚该条,不影响其他条目,返回逐条结果
|
||||||
|
*
|
||||||
|
* @param orgUserCreateDTOs 创建dto列表
|
||||||
|
* @return {@link List}<{@link OrgUserCreateResultDTO}> 与入参顺序一一对应
|
||||||
|
*/
|
||||||
|
List<OrgUserCreateResultDTO> batchCreateOrgUser(List<OrgUserCreateDTO> orgUserCreateDTOs);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改企业用户
|
* 修改企业用户
|
||||||
*
|
*
|
||||||
@@ -366,4 +375,13 @@ public interface UserService {
|
|||||||
*/
|
*/
|
||||||
void pageOrgAccount(OrgAccountQueryDTO queryDTO);
|
void pageOrgAccount(OrgAccountQueryDTO queryDTO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改用户姓名(系统管理员)
|
||||||
|
* 平台超管可修改全部用户,机构管理员仅可修改本机构用户
|
||||||
|
*
|
||||||
|
* @param reqDTO 操作dto
|
||||||
|
* @return {@link Boolean}
|
||||||
|
*/
|
||||||
|
Boolean modifyRealName(UserRealNameModifyDTO reqDTO);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ import com.senmesh.usercenter.user.dto.ModifyPasswordDTO;
|
|||||||
import com.senmesh.usercenter.user.dto.OrgAccountDTO;
|
import com.senmesh.usercenter.user.dto.OrgAccountDTO;
|
||||||
import com.senmesh.usercenter.user.dto.OrgAccountQueryDTO;
|
import com.senmesh.usercenter.user.dto.OrgAccountQueryDTO;
|
||||||
import com.senmesh.usercenter.user.dto.OrgUserCreateDTO;
|
import com.senmesh.usercenter.user.dto.OrgUserCreateDTO;
|
||||||
|
import com.senmesh.usercenter.user.dto.OrgUserCreateResultDTO;
|
||||||
import com.senmesh.usercenter.user.dto.OrgUserModifyDTO;
|
import com.senmesh.usercenter.user.dto.OrgUserModifyDTO;
|
||||||
import com.senmesh.usercenter.user.dto.OrgUserOperateDTO;
|
import com.senmesh.usercenter.user.dto.OrgUserOperateDTO;
|
||||||
import com.senmesh.usercenter.user.dto.PersonUserCardCreateDTO;
|
import com.senmesh.usercenter.user.dto.PersonUserCardCreateDTO;
|
||||||
@@ -81,6 +82,7 @@ import com.senmesh.usercenter.user.dto.UserExtensionOperateDTO;
|
|||||||
import com.senmesh.usercenter.user.dto.UserOperateDTO;
|
import com.senmesh.usercenter.user.dto.UserOperateDTO;
|
||||||
import com.senmesh.usercenter.user.dto.UserQueryByRoleDTO;
|
import com.senmesh.usercenter.user.dto.UserQueryByRoleDTO;
|
||||||
import com.senmesh.usercenter.user.dto.UserQueryDTO;
|
import com.senmesh.usercenter.user.dto.UserQueryDTO;
|
||||||
|
import com.senmesh.usercenter.user.dto.UserRealNameModifyDTO;
|
||||||
import com.senmesh.usercenter.user.dto.UserStatusOperateDTO;
|
import com.senmesh.usercenter.user.dto.UserStatusOperateDTO;
|
||||||
import com.senmesh.usercenter.user.entity.User;
|
import com.senmesh.usercenter.user.entity.User;
|
||||||
import com.senmesh.usercenter.user.login.dto.UserDetailDTO;
|
import com.senmesh.usercenter.user.login.dto.UserDetailDTO;
|
||||||
@@ -107,6 +109,7 @@ public class UserServiceImpl implements UserService {
|
|||||||
private static final String CARD_NO_LOCK_NAME = "user:cardno";
|
private static final String CARD_NO_LOCK_NAME = "user:cardno";
|
||||||
private static final String USERNAME_LOCK_NAME = "user:username";
|
private static final String USERNAME_LOCK_NAME = "user:username";
|
||||||
private static final String AUTH_LOCK_NAME = "user:auth";
|
private static final String AUTH_LOCK_NAME = "user:auth";
|
||||||
|
private static final int BATCH_CREATE_ORG_USER_LIMIT = 500;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private UserMapper userMapper;
|
private UserMapper userMapper;
|
||||||
@@ -208,6 +211,32 @@ public class UserServiceImpl implements UserService {
|
|||||||
return userId;
|
return userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<OrgUserCreateResultDTO> batchCreateOrgUser(List<OrgUserCreateDTO> orgUserCreateDTOs) {
|
||||||
|
Assert.isTrue(CollectionUtils.isNotEmpty(orgUserCreateDTOs), "创建列表不能为空");
|
||||||
|
Assert.isTrue(orgUserCreateDTOs.size() <= BATCH_CREATE_ORG_USER_LIMIT,
|
||||||
|
"单次批量创建不能超过" + BATCH_CREATE_ORG_USER_LIMIT + "条");
|
||||||
|
List<OrgUserCreateResultDTO> resultDTOs =
|
||||||
|
Lists.newArrayListWithExpectedSize(orgUserCreateDTOs.size());
|
||||||
|
// 不开外层事务,逐条走代理调用,单条独立事务+手机号锁,失败仅回滚该条
|
||||||
|
UserService proxy = ((UserService) AopContext.currentProxy());
|
||||||
|
for (OrgUserCreateDTO createDTO : orgUserCreateDTOs) {
|
||||||
|
OrgUserCreateResultDTO resultDTO = OrgUserCreateResultDTO.builder()
|
||||||
|
.phone(createDTO.getPhone())
|
||||||
|
.realName(createDTO.getRealName())
|
||||||
|
.build();
|
||||||
|
try {
|
||||||
|
resultDTO.setUserId(proxy.createOrgUser(createDTO));
|
||||||
|
resultDTO.setSuccess(Boolean.TRUE);
|
||||||
|
} catch (Exception e) {
|
||||||
|
resultDTO.setSuccess(Boolean.FALSE);
|
||||||
|
resultDTO.setMsg(e.getMessage());
|
||||||
|
}
|
||||||
|
resultDTOs.add(resultDTO);
|
||||||
|
}
|
||||||
|
return resultDTOs;
|
||||||
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public void modifyOrgUser(OrgUserModifyDTO orgUserModifyDTO) {
|
public void modifyOrgUser(OrgUserModifyDTO orgUserModifyDTO) {
|
||||||
@@ -1093,4 +1122,22 @@ public class UserServiceImpl implements UserService {
|
|||||||
Assert.isTrue(UserContextHolder.isSuperior(), "当前用户无操作权限");
|
Assert.isTrue(UserContextHolder.isSuperior(), "当前用户无操作权限");
|
||||||
userMapper.listOrgAccount(queryDTO);
|
userMapper.listOrgAccount(queryDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public Boolean modifyRealName(UserRealNameModifyDTO reqDTO) {
|
||||||
|
// 平台超管可修改全部用户姓名,机构管理员仅可修改本机构用户
|
||||||
|
Assert.isTrue(UserContextHolder.isSuperior() || UserContextHolder.isAdministrator(),
|
||||||
|
"当前用户无操作权限");
|
||||||
|
this.checkOrgScopeOfOperateUser(reqDTO.getUserId());
|
||||||
|
User user = userMapper.getById(reqDTO.getUserId());
|
||||||
|
Assert.notNull(user, "用户不存在");
|
||||||
|
Assert.isTrue(!UserStatusEnum.CLOSED.getStatus().equals(user.getStatus()), "已注销账号不可修改姓名");
|
||||||
|
Assert.isTrue(ValidateUtils.checkRealName(reqDTO.getRealName()),
|
||||||
|
"姓名格式错误!(长度2-30位,仅支持中文或英文姓名)");
|
||||||
|
Assert.isTrue(!StringUtils.equals(reqDTO.getRealName(), user.getRealName()),
|
||||||
|
"姓名与原姓名一致,无需修改!");
|
||||||
|
User updateInfo = User.builder().id(user.getId()).realName(reqDTO.getRealName()).build();
|
||||||
|
return userMapper.updateEntitySelective(updateInfo, UserContextHolder.getLoginUserId()) == 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user