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


    写在最前

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

    源码地址(后端):https://gitee.com/csps/mingyue-springcloud-learning

    源码地址(前端):https://gitee.com/csps/mingyue-springcloud-ui

    文档地址:https://gitee.com/csps/mingyue-springcloud-learning/wikis

    本节概要

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

    分页查询用户

    分页查询通用类

    @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;
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83

    接口层

    @GetMapping("list")
    @SaCheckPermission("system:user:list")
    @Operation(summary = "获取所有用户信息")
    public R<IPage<SysUserVo>> getSysUsers(PageCommon page, UserQueryDto dto) {
      return R.ok(sysUserService.getSysUsers(page, dto));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    逻辑层

    @Override
    public IPage<SysUserVo> getSysUsers(PageCommon page, UserQueryDto dto) {
      return sysUserMapper.getUserVosPage(page.build(), dto);
    }
    
    • 1
    • 2
    • 3
    • 4

    数据层

    <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    接口测试

    非排序入参

    curl -X 'GET' \
      'http://mingyue-gateway:9100/system/sysUser/list?pageSize=10&pageNum=1&username=' \
      -H 'accept: */*' \
      -H 'Authorization: vhiqUYS3NtT5zpvyzwudffAhyu3vswAV'
    
    • 1
    • 2
    • 3
    • 4

    排序入参

    curl -X 'GET' \
      'http://mingyue-gateway:9100/system/sysUser/list?pageSize=10&pageNum=2&orderByColumn=userId&isAsc=desc&username=' \
      -H 'accept: */*' \
      -H 'Authorization: vhiqUYS3NtT5zpvyzwudffAhyu3vswAV'
    
    • 1
    • 2
    • 3
    • 4

    添加或编辑用户

    接口层

    @PostMapping("addOrEdit")
    @Operation(summary = "添加或编辑用户")
    public R<Boolean> addOrEdit(@Valid @RequestBody UserAddOrEditDto dto) {
      return R.ok(sysUserService.addOrEdit(dto));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    逻辑层

    @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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    删除用户

    接口层

    @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));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    逻辑层

    @Override
    public boolean delUser(Long userId) {
      return sysUserMapper.deleteByIdLogic(userId) > 0;
    }
    
    • 1
    • 2
    • 3
    • 4

    数据层

    <delete id="deleteByIdLogic">
        UPDATE sys_user su SET su.is_deleted = '1' WHERE su.user_id = #{userId}
    delete>
    
    • 1
    • 2
    • 3

    mingyue-ui 接口交互

    接口定义

    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'
        });
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    分页查询

    src/views/system/user/index.vue

    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;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    添加或编辑用户

    src/views/system/user/dialog.vue

    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('修改失败');
        }
      })
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    删除用户

    src/views/system/user/index.vue

    const onRowDel = (row: RowUserType) => {
    	ElMessageBox.confirm(`此操作将永久删除账户名称:“${row.username}”,是否继续?`, '提示', {
    		confirmButtonText: '确认',
    		cancelButtonText: '取消',
    		type: 'warning',
    	})
    		.then(() => {
          userApi().del(row.userId).then(() => {
            getTableData();
            ElMessage.success('删除成功');
          });
    		})
    		.catch(() => {});
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    小结

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

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

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

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

  • 相关阅读:
    第一章:最新版零基础学习 PYTHON 教程(第十三节 - Python 语句中的 –Python While 循环)
    11. [containerd] content服务解析
    Verilog HDL中的数据类型
    VirtualBox安装CentOS 7教程
    windows uvc
    SpringBoot 常用注解汇总
    使用sysctl调优Linux内核
    webpack优化系列五:vue项目配置 webpack-obfuscator 进行代码加密混淆
    05.智慧商城——路由前置守卫、首页动态渲染
    重构学习(四):代码的坏味道
  • 原文地址:https://blog.csdn.net/csp732171109/article/details/132740339