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 已经包含了 统一网关服务统一认证服务统一系统服务统一推送服务,距离目标还差

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

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

相关推荐
干到60岁退休的码农10 分钟前
SpringBoot整合Mybatis-plus
spring boot·后端·mybatis
掘金者阿豪12 分钟前
从Oracle迁到金仓,第一个月踩的最大的坑就是它
前端·后端
aramae16 分钟前
C++11:现代C++的里程碑
c语言·开发语言·c++·windows·git·后端
无相求码40 分钟前
为什么你的第二个 scanf 还没输入就直接跳过了?C语言输入缓冲区陷阱
c语言·后端
叼馒女友郭芙蓉41 分钟前
Function Calling理解
后端
玉宇夕落42 分钟前
LangChain RAG Retriever 的学习
后端
用户298698530141 小时前
Python 一键导出 Excel 中的图表和形状为图片
后端·python·excel
用户8130077816371 小时前
PageHelper分页查询步骤
后端
是小李呀1 小时前
MyBatis、MyBatis-Plus 与全自动 ORM 的本质区别
后端
小堂子这厢有礼了1 小时前
Chet.Admin 权限模型:菜单级 + 按钮级 + 行级三层防护
前端·后端·信息可视化·前端框架·.net