feat(用户管理): 新增汇邦云用户信息管理功能

新增汇邦云用户信息管理模块,包括用户实体、Mapper、Service、DTO、查询条件、命令对象、模型工厂、应用服务及控制器。支持用户列表查询、新增、修改、删除等操作,并提供了相应的数据校验和异常处理。
This commit is contained in:
dzq 2025-05-10 16:13:52 +08:00
parent 4655eb4df0
commit a53ed61457
15 changed files with 550 additions and 1 deletions

View File

@ -0,0 +1,68 @@
package com.agileboot.admin.controller.ab98;
import com.agileboot.admin.customize.aop.accessLog.AccessLog;
import com.agileboot.common.core.base.BaseController;
import com.agileboot.common.core.dto.ResponseDTO;
import com.agileboot.common.core.page.PageDTO;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import com.agileboot.domain.common.command.BulkOperationCommand;
import com.agileboot.domain.ab98.user.Ab98UserApplicationService;
import com.agileboot.domain.ab98.user.command.AddAb98UserCommand;
import com.agileboot.domain.ab98.user.command.UpdateAb98UserCommand;
import com.agileboot.domain.ab98.user.db.Ab98UserEntity;
import com.agileboot.domain.ab98.user.dto.Ab98UserDTO;
import com.agileboot.domain.ab98.user.query.SearchAb98UserQuery;
import io.swagger.v3.oas.annotations.Operation;
import java.util.List;
import javax.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/ab98/users")
@RequiredArgsConstructor
@Validated
public class Ab98UserController extends BaseController {
private final Ab98UserApplicationService userApplicationService;
@Operation(summary = "用户列表")
@GetMapping
public ResponseDTO<PageDTO<Ab98UserDTO>> list(SearchAb98UserQuery<Ab98UserEntity> query) {
PageDTO<Ab98UserDTO> page = userApplicationService.getUserList(query);
return ResponseDTO.ok(page);
}
@Operation(summary = "新增用户")
@AccessLog(title = "用户管理", businessType = BusinessTypeEnum.ADD)
@PostMapping
public ResponseDTO<Void> add(@Validated @RequestBody AddAb98UserCommand command) {
userApplicationService.addUser(command);
return ResponseDTO.ok();
}
@Operation(summary = "修改用户")
@AccessLog(title = "用户管理", businessType = BusinessTypeEnum.MODIFY)
@PutMapping("/{id}")
public ResponseDTO<Void> edit(@PathVariable Long id, @Validated @RequestBody UpdateAb98UserCommand command) {
command.setAb98UserId(id);
userApplicationService.updateUser(command);
return ResponseDTO.ok();
}
@Operation(summary = "删除用户")
@AccessLog(title = "用户管理", businessType = BusinessTypeEnum.DELETE)
@DeleteMapping("/{ids}")
public ResponseDTO<Void> remove(@PathVariable @NotNull List<Long> ids) {
userApplicationService.deleteUser(new BulkOperationCommand<>(ids));
return ResponseDTO.ok();
}
}

View File

@ -0,0 +1,61 @@
package com.agileboot.domain.ab98.user;
import com.agileboot.common.core.page.PageDTO;
import com.agileboot.domain.common.command.BulkOperationCommand;
import com.agileboot.domain.ab98.user.command.AddAb98UserCommand;
import com.agileboot.domain.ab98.user.command.UpdateAb98UserCommand;
import com.agileboot.domain.ab98.user.db.Ab98UserEntity;
import com.agileboot.domain.ab98.user.db.Ab98UserService;
import com.agileboot.domain.ab98.user.dto.Ab98UserDTO;
import com.agileboot.domain.ab98.user.model.Ab98UserModel;
import com.agileboot.domain.ab98.user.model.Ab98UserModelFactory;
import com.agileboot.domain.ab98.user.query.SearchAb98UserQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Service
@Slf4j
@RequiredArgsConstructor
public class Ab98UserApplicationService {
private final Ab98UserService userService;
private final Ab98UserModelFactory userModelFactory;
public PageDTO<Ab98UserDTO> getUserList(SearchAb98UserQuery<Ab98UserEntity> query) {
Page<Ab98UserEntity> page = userService.getUserList(query);
List<Ab98UserDTO> dtoList = page.getRecords().stream()
.map(Ab98UserDTO::new)
.collect(Collectors.toList());
return new PageDTO<>(dtoList, page.getTotal());
}
public void addUser(AddAb98UserCommand command) {
Ab98UserModel model = userModelFactory.create();
model.loadAddCommand(command);
model.insert();
}
public void updateUser(UpdateAb98UserCommand command) {
Ab98UserModel model = userModelFactory.loadById(command.getAb98UserId());
model.loadUpdateCommand(command);
model.updateById();
}
public void deleteUser(BulkOperationCommand<Long> command) {
for (Long id : command.getIds()) {
Ab98UserModel model = userModelFactory.loadById(id);
model.deleteById();
}
}
public Ab98UserEntity getByUserId(Long userId) {
return userService.getById(userId);
}
public Ab98UserEntity getByOpenid(String openid) {
return userService.getByOpenid(openid);
}
}

View File

@ -0,0 +1,11 @@
package com.agileboot.domain.ab98.user.command;
import com.agileboot.domain.ab98.user.db.Ab98UserEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class AddAb98UserCommand extends Ab98UserEntity {
}

View File

@ -0,0 +1,15 @@
package com.agileboot.domain.ab98.user.command;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.PositiveOrZero;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class UpdateAb98UserCommand extends AddAb98UserCommand {
@NotNull
@PositiveOrZero
private Long ab98UserId;
}

View File

@ -0,0 +1,84 @@
package com.agileboot.domain.ab98.user.db;
import com.agileboot.common.core.base.BaseEntity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* 汇邦云用户信息表
* </p>
*
* @author valarchie
* @since 2025-05-10
*/
@Getter
@Setter
@TableName("ab98_user")
@ApiModel(value = "Ab98UserEntity对象", description = "汇邦云用户信息表")
public class Ab98UserEntity extends BaseEntity<Ab98UserEntity> {
private static final long serialVersionUID = 1L;
@ApiModelProperty("主键ID")
@TableId(value = "ab98_user_id", type = IdType.AUTO)
private Long ab98UserId;
@ApiModelProperty("openid")
@TableField("openid")
private String openid;
@ApiModelProperty("汇邦云用户唯一ID")
@TableField("userid")
private String userid;
@ApiModelProperty("真实姓名")
@TableField("`name`")
private String name;
@ApiModelProperty("手机号码")
@TableField("tel")
private String tel;
@ApiModelProperty("身份证号码")
@TableField("idnum")
private String idnum;
@ApiModelProperty("性别(男 女)")
@TableField("sex")
private String sex;
@ApiModelProperty("人脸照片地址")
@TableField("face_img")
private String faceImg;
@ApiModelProperty("身份证正面地址")
@TableField("idcard_front")
private String idcardFront;
@ApiModelProperty("身份证背面地址")
@TableField("idcard_back")
private String idcardBack;
@ApiModelProperty("身份证登记地址")
@TableField("address")
private String address;
@ApiModelProperty("是否已注册0未注册 1已注册")
@TableField("registered")
private Boolean registered;
@Override
public Serializable pkVal() {
return this.ab98UserId;
}
}

View File

@ -0,0 +1,46 @@
package com.agileboot.domain.ab98.user.db;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
/**
* <p>
* 汇邦云用户信息表 Mapper 接口
* </p>
*
* @author valarchie
* @since 2025-05-10
*/
public interface Ab98UserMapper extends BaseMapper<Ab98UserEntity> {
@Select("SELECT ab98_user_id, openid, userid, name, tel, idnum, sex, face_img, idcard_front, idcard_back, address, registered " +
"FROM ab98_user " +
"${ew.customSqlSegment}")
Page<Ab98UserEntity> getUserList(
Page<Ab98UserEntity> page,
@Param(Constants.WRAPPER) Wrapper<Ab98UserEntity> queryWrapper
);
@Select("SELECT * " +
"FROM ab98_user " +
"WHERE registered = '1' " +
"ORDER BY create_time DESC " +
"LIMIT 1")
Ab98UserEntity selectFirstRegisteredUser();
@Select("SELECT * " +
"FROM ab98_user " +
"WHERE registered = '1' " +
"ORDER BY create_time DESC")
List<Ab98UserEntity> selectAllRegistered();
@Select("SELECT * FROM ab98_user WHERE userid = #{userid} LIMIT 1")
Ab98UserEntity selectByUserid(String userid);
@Select("SELECT * FROM ab98_user WHERE openid = #{openid} LIMIT 1")
Ab98UserEntity selectByOpenid(String openid);
}

View File

@ -0,0 +1,25 @@
package com.agileboot.domain.ab98.user.db;
import com.agileboot.common.core.page.AbstractPageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* <p>
* 汇邦云用户信息表 服务类
* </p>
*
* @author valarchie
* @since 2025-05-10
*/
public interface Ab98UserService extends IService<Ab98UserEntity> {
Page<Ab98UserEntity> getUserList(AbstractPageQuery<Ab98UserEntity> query);
List<Ab98UserEntity> selectAll();
Ab98UserEntity getByOpenid(String openid);
Ab98UserEntity getByUserid(String userid);
}

View File

@ -0,0 +1,42 @@
package com.agileboot.domain.ab98.user.db;
import com.agileboot.common.core.page.AbstractPageQuery;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* <p>
* 汇邦云用户信息表 服务实现类
* </p>
*
* @author valarchie
* @since 2025-05-10
*/
@Service
public class Ab98UserServiceImpl extends ServiceImpl<Ab98UserMapper, Ab98UserEntity> implements Ab98UserService {
@Override
public Page<Ab98UserEntity> getUserList(AbstractPageQuery<Ab98UserEntity> query) {
return this.page(query.toPage(), query.toQueryWrapper());
}
@Override
public List<Ab98UserEntity> selectAll() {
LambdaQueryWrapper<Ab98UserEntity> wrapper = new LambdaQueryWrapper<>();
return this.list(wrapper);
}
@Override
public Ab98UserEntity getByOpenid(String openid) {
return baseMapper.selectByOpenid(openid);
}
@Override
public Ab98UserEntity getByUserid(String userid) {
return baseMapper.selectByUserid(userid);
}
}

View File

@ -0,0 +1,59 @@
package com.agileboot.domain.ab98.user.dto;
import cn.hutool.core.bean.BeanUtil;
import com.agileboot.common.annotation.ExcelColumn;
import com.agileboot.common.annotation.ExcelSheet;
import com.agileboot.domain.common.cache.CacheCenter;
import com.agileboot.domain.ab98.user.db.Ab98UserEntity;
import com.agileboot.domain.system.user.db.SysUserEntity;
import lombok.Data;
@ExcelSheet(name = "汇邦云用户列表")
@Data
public class Ab98UserDTO {
public Ab98UserDTO(Ab98UserEntity entity) {
if (entity != null) {
BeanUtil.copyProperties(entity, this);
this.registeredStatus = entity.getRegistered() ? "已注册" : "未注册";
}
}
@ExcelColumn(name = "主键ID")
private Long ab98UserId;
@ExcelColumn(name = "openid")
private String openid;
@ExcelColumn(name = "用户唯一ID")
private String userid;
@ExcelColumn(name = "真实姓名")
private String name;
@ExcelColumn(name = "手机号码")
private String tel;
@ExcelColumn(name = "身份证号码")
private String idnum;
@ExcelColumn(name = "性别")
private String sex;
@ExcelColumn(name = "人脸照片地址")
private String faceImg;
@ExcelColumn(name = "身份证正面地址")
private String idcardFront;
@ExcelColumn(name = "身份证背面地址")
private String idcardBack;
@ExcelColumn(name = "身份证登记地址")
private String address;
@ExcelColumn(name = "注册状态")
private String registeredStatus;
}

View File

@ -0,0 +1,37 @@
package com.agileboot.domain.ab98.user.model;
import cn.hutool.core.bean.BeanUtil;
import com.agileboot.domain.ab98.user.db.Ab98UserEntity;
import com.agileboot.domain.ab98.user.db.Ab98UserService;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class Ab98UserModel extends Ab98UserEntity {
private Ab98UserService userService;
public Ab98UserModel(Ab98UserEntity entity, Ab98UserService userService) {
this(userService);
if (entity != null) {
BeanUtil.copyProperties(entity, this);
}
}
public Ab98UserModel(Ab98UserService userService) {
this.userService = userService;
}
public void loadAddCommand(Object command) {
if (command != null) {
BeanUtil.copyProperties(command, this, "id");
}
}
public void loadUpdateCommand(Object command) {
if (command != null) {
loadAddCommand(command);
}
}
}

View File

@ -0,0 +1,27 @@
package com.agileboot.domain.ab98.user.model;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.domain.ab98.user.db.Ab98UserEntity;
import com.agileboot.domain.ab98.user.db.Ab98UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class Ab98UserModelFactory {
private final Ab98UserService userService;
public Ab98UserModel loadById(Long userId) {
Ab98UserEntity entity = userService.getById(userId);
if (entity == null) {
throw new ApiException(ErrorCode.Business.COMMON_OBJECT_NOT_FOUND, userId, "用户");
}
return new Ab98UserModel(entity, userService);
}
public Ab98UserModel create() {
return new Ab98UserModel(userService);
}
}

View File

@ -0,0 +1,44 @@
package com.agileboot.domain.ab98.user.query;
import cn.hutool.core.util.StrUtil;
import com.agileboot.common.core.page.AbstractPageQuery;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import java.util.Date;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class SearchAb98UserQuery<T> extends AbstractPageQuery<T> {
private Long ab98UserId;
private String openid;
private String userid;
private String name;
private String tel;
private String idnum;
private String sex;
private Boolean registered;
private Date startTime;
private Date endTime;
@Override
public QueryWrapper<T> addQueryCondition() {
QueryWrapper<T> queryWrapper = new QueryWrapper<>();
queryWrapper
.eq(ab98UserId != null, "ab98_user_id", ab98UserId)
.eq(StrUtil.isNotEmpty(openid), "openid", openid)
.eq(StrUtil.isNotEmpty(userid), "userid", userid)
.like(StrUtil.isNotEmpty(name), "name", name)
.like(StrUtil.isNotEmpty(tel), "tel", tel)
.like(StrUtil.isNotEmpty(idnum), "idnum", idnum)
.eq(StrUtil.isNotEmpty(sex), "sex", sex)
.eq(registered != null, "registered", registered)
.between(startTime != null && endTime != null, "create_time", startTime, endTime);
this.timeRangeColumn = "create_time";
return queryWrapper;
}
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.agileboot.domain.ab98.user.db.Ab98UserMapper">
</mapper>

View File

@ -61,7 +61,7 @@ public class CodeGenerator {
//生成的类 放在orm子模块下的/target/generated-code目录底下
.module("/agileboot-orm/target/generated-code")
.parentPackage("com.agileboot")
.tableName("shop")
.tableName("ab98_user")
// 决定是否继承基类
.isExtendsFromBaseEntity(true)
.build();

View File

@ -0,0 +1,25 @@
DROP TABLE IF EXISTS `ab98_user`;
CREATE TABLE `ab98_user` (
`ab98_user_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`openid` VARCHAR(32) NOT NULL COMMENT 'openid',
`userid` VARCHAR(100) NOT NULL COMMENT '汇邦云用户唯一ID',
`name` VARCHAR(50) NOT NULL COMMENT '真实姓名',
`tel` VARCHAR(20) NOT NULL COMMENT '手机号码',
`idnum` VARCHAR(20) NOT NULL COMMENT '身份证号码',
`sex` CHAR(8) NOT NULL COMMENT '性别(男 女)',
`face_img` VARCHAR(500) NOT NULL COMMENT '人脸照片地址',
`idcard_front` VARCHAR(500) COMMENT '身份证正面地址',
`idcard_back` VARCHAR(500) COMMENT '身份证背面地址',
`address` VARCHAR(200) COMMENT '身份证登记地址',
`registered` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否已注册0未注册 1已注册',
`creator_id` BIGINT DEFAULT 0 COMMENT '创建者ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater_id` BIGINT DEFAULT 0 COMMENT '更新者ID',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '删除标志0存在 1删除',
PRIMARY KEY (`ab98_user_id`),
KEY `idx_openid` (`openid`),
KEY `idx_tel` (`tel`),
KEY `idx_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='汇邦云用户信息表';