024-从零搭建微服务-系统服务(六)

写在最前

如果这个项目让你有所收获,记得 Star 关注哦,这对我是非常不错的鼓励与支持。

源码地址(后端):gitee.com/csps/mingyu...

源码地址(前端):gitee.com/csps/mingyu...

文档地址:gitee.com/csps/mingyu...

本节概要

mingyue-ui 目前与后端交互只有登录登出接口,本节从用户入手,完成用户前后端交互增删改查

分页查询用户

分页查询通用类

ini 复制代码
@Data
@Schema(description = "分页查询通用类")
public class PageCommon implements Serializable {
​
  private static final long serialVersionUID = 1L;
​
  @Schema(description = "分页大小")
  private Integer pageSize;
​
  @Schema(description = "当前页数")
  private Integer pageNum;
​
  @Schema(description = "排序列")
  private String orderByColumn;
​
  @Schema(description = "排序的方向 desc 或者 asc")
  private String isAsc;
​
  /**
   * 当前记录起始索引 默认值
   */
  public static final int DEFAULT_PAGE_NUM = 1;
​
  /**
   * 每页显示记录数 默认值 默认查全部
   */
  public static final int DEFAULT_PAGE_SIZE = Integer.MAX_VALUE;
​
  public <T> Page<T> build() {
    Integer pageNum = ObjectUtil.defaultIfNull(getPageNum(), DEFAULT_PAGE_NUM);
    Integer pageSize = ObjectUtil.defaultIfNull(getPageSize(), DEFAULT_PAGE_SIZE);
    if (pageNum <= 0) {
      pageNum = DEFAULT_PAGE_NUM;
    }
    Page<T> page = new Page<>(pageNum, pageSize);
    List<OrderItem> orderItems = buildOrderItem();
    if (CollUtil.isNotEmpty(orderItems)) {
      page.addOrder(orderItems);
    }
    return page;
  }
​
  /**
   * 构建排序
   *
   * 支持的用法如下: {isAsc:"asc",orderByColumn:"id"} order by id asc
   * {isAsc:"asc",orderByColumn:"id,createTime"} order by id asc,create_time asc
   * {isAsc:"desc",orderByColumn:"id,createTime"} order by id desc,create_time desc
   * {isAsc:"asc,desc",orderByColumn:"id,createTime"} order by id asc,create_time desc
   */
  private List<OrderItem> buildOrderItem() {
    if (StrUtil.isBlank(orderByColumn) || StrUtil.isBlank(isAsc)) {
      return null;
    }
    String orderBy = SqlUtil.escapeOrderBySql(orderByColumn);
    orderBy = StrUtil.toUnderlineCase(orderBy);
​
    String[] orderByArr = orderBy.split(StrUtil.COMMA);
    String[] isAscArr = isAsc.split(StrUtil.COMMA);
    if (isAscArr.length != 1 && isAscArr.length != orderByArr.length) {
      throw new ServiceException("排序参数有误");
    }
​
    List<OrderItem> list = new ArrayList<>();
    // 每个字段各自排序
    for (int i = 0; i < orderByArr.length; i++) {
      String orderByStr = orderByArr[i];
      String isAscStr = isAscArr.length == 1 ? isAscArr[0] : isAscArr[i];
      if ("asc".equals(isAscStr)) {
        list.add(OrderItem.asc(orderByStr));
      }
      else if ("desc".equals(isAscStr)) {
        list.add(OrderItem.desc(orderByStr));
      }
      else {
        throw new ServiceException("排序参数有误");
      }
    }
​
    return list;
  }
​
}

接口层

less 复制代码
@GetMapping("list")
@SaCheckPermission("system:user:list")
@Operation(summary = "获取所有用户信息")
public R<IPage<SysUserVo>> getSysUsers(PageCommon page, UserQueryDto dto) {
  return R.ok(sysUserService.getSysUsers(page, dto));
}

逻辑层

typescript 复制代码
@Override
public IPage<SysUserVo> getSysUsers(PageCommon page, UserQueryDto dto) {
  return sysUserMapper.getUserVosPage(page.build(), dto);
}

数据层

ini 复制代码
<select id="getUserVosPage" resultType="com.csp.mingyue.system.api.vo.SysUserVo">
      SELECT su.*,sr.role_name, sr.role_code
      FROM sys_user su
      LEFT JOIN sys_user_role sur ON sur.user_id = su.user_id
      LEFT JOIN sys_role sr ON sur.role_id = sr.role_id
      <where>
          su.is_deleted = '0'
          <if test="query.username != null and query.username != ''">
              <bind name="usernameLike" value="'%' + query.username + '%'" />
              and su.username LIKE #{usernameLike}
          </if>
      </where>
      ORDER BY su.create_time DESC
  </select>

接口测试

非排序入参

arduino 复制代码
curl -X 'GET' \
  'http://mingyue-gateway:9100/system/sysUser/list?pageSize=10&pageNum=1&username=' \
  -H 'accept: */*' \
  -H 'Authorization: vhiqUYS3NtT5zpvyzwudffAhyu3vswAV'

排序入参

arduino 复制代码
curl -X 'GET' \
  'http://mingyue-gateway:9100/system/sysUser/list?pageSize=10&pageNum=2&orderByColumn=userId&isAsc=desc&username=' \
  -H 'accept: */*' \
  -H 'Authorization: vhiqUYS3NtT5zpvyzwudffAhyu3vswAV'

添加或编辑用户

接口层

less 复制代码
@PostMapping("addOrEdit")
@Operation(summary = "添加或编辑用户")
public R<Boolean> addOrEdit(@Valid @RequestBody UserAddOrEditDto dto) {
  return R.ok(sysUserService.addOrEdit(dto));
}

逻辑层

less 复制代码
@Override
@Transactional(rollbackFor = Exception.class)
public boolean addOrEdit(UserAddOrEditDto dto) {
  SysUser sysUser = BeanUtil.copyProperties(dto, SysUser.class);
​
  // 添加用户
  if (Objects.isNull(sysUser.getUserId())) {
    // 密码加密
    sysUser.setPassword(BCrypt.hashpw(sysUser.getPassword(), userPasswordProperties.getSalt()));
  }
​
  boolean flag = this.saveOrUpdate(sysUser);
  if (!flag) {
    throw new UserException("用户信息保存异常");
  }
​
  // 保存角色关系
  flag = sysRoleService.addUserRole(sysUser.getUserId(), dto.getRoleCode());
  if (!flag) {
    throw new UserException("用户角色信息保存异常");
  }
​
  return true;
}

删除用户

接口层

less 复制代码
@DeleteMapping("{userId}")
@Operation(summary = "删除用户", parameters = { @Parameter(name = "userId", description = "用户ID", required = true) })
public R<Boolean> delUser(@PathVariable Long userId) {
  return R.ok(sysUserService.delUser(userId));
}

逻辑层

typescript 复制代码
@Override
public boolean delUser(Long userId) {
  return sysUserMapper.deleteByIdLogic(userId) > 0;
}

数据层

ini 复制代码
<delete id="deleteByIdLogic">
    UPDATE sys_user su SET su.is_deleted = '1' WHERE su.user_id = #{userId}
</delete>

mingyue-ui 接口交互

接口定义

php 复制代码
list: (page: object) => {
    return request({
        url: '/api/system/sysUser/list',
        method: 'get',
        params: page
    });
},
addOrEdit: (data: object) => {
    return request({
        url: '/api/system/sysUser/addOrEdit',
        method: 'post',
        data: data
    });
},
del: (userId: number) => {
    return request({
        url: '/api/system/sysUser/' + userId,
        method: 'delete'
    });
}

分页查询

src/views/system/user/index.vue

ini 复制代码
const getTableData = async () => {
  state.tableData.loading = true;
​
  const res = await getUserList();
  state.tableData.data = res.data.records;
  state.tableData.total = res.data.total;
​
  state.tableData.loading = false;
};

添加或编辑用户

src/views/system/user/dialog.vue

ini 复制代码
const onSubmit = () => {
  userApi().addOrEdit(state.ruleForm).then(res => {
    if (res.data) {
      closeDialog();
      emit('refresh');
      state.dialog.type === 'add' ? ElMessage.success('添加成功') : ElMessage.success('修改成功');
    } else {
      state.dialog.type === 'add' ? ElMessage.error('添加失败') : ElMessage.error('修改失败');
    }
  })
};

删除用户

src/views/system/user/index.vue

javascript 复制代码
const onRowDel = (row: RowUserType) => {
  ElMessageBox.confirm(`此操作将永久删除账户名称:"${row.username}",是否继续?`, '提示', {
    confirmButtonText: '确认',
    cancelButtonText: '取消',
    type: 'warning',
  })
    .then(() => {
      userApi().del(row.userId).then(() => {
        getTableData();
        ElMessage.success('删除成功');
      });
    })
    .catch(() => {});
};

小结

用户管理已经可以交互接口完成真实的增删改查了。

目前 mingyue 已经包含了 统一网关服务统一认证服务统一系统服务统一推送服务,距离目标还差

统一文件服务统一定时服务统一搜索服务 等等。接下来搞一搞 统一文件服务 吧!

本人后端一枚,前端粗通,等后续后端服务基本完成后,再去抽时间完善前端代码哈~~ 见谅《 - 。- 》

相关推荐
brzhang2 分钟前
Node 服务遇到血崩,汤过坑才知道,限流与熔断是你绕不过的坑
前端·后端·架构
Moment2 分钟前
NestJS 在 2025 年:对于后端开发者仍然值得吗 ❓︎❓︎❓︎
前端·javascript·后端
milanyangbo3 分钟前
从C10K到Reactor:事件驱动,如何重塑高并发服务器的网络架构
服务器·网络·后端·架构
Json____3 分钟前
最近我用springBoot开发了一个二手交易管理系统,分享一下实现方式~
java·spring boot·后端
调试人生的显微镜18 分钟前
前端一般用什么开发工具?一文看懂从入门到专业的完整工具链
后端
喜欢读源码的小白20 分钟前
SpringBoot的启动流程原理——小白的魔法引擎探秘
java·开发语言·spring boot·springboot启动原理
摇滚侠41 分钟前
Spring Boot 3零基础教程,WEB 开发 通过配置类代码方式修改静态资源配置 笔记32
java·spring boot·笔记
golang学习记1 小时前
Go 高效开发的“十诫”:写出可维护、安全、高性能的 Go 代码
后端
洛克大航海1 小时前
5-SpringCloud-服务链路追踪 Micrometer Tracing
后端·spring·spring cloud·zipkin·micrometer
小咕聊编程1 小时前
【含文档+PPT+源码】基于spring boot的固定资产管理系统
java·spring boot·后端