当前位置: 首页 > article >正文

Vue3.5 企业级管理系统实战(十七):角色管理

本篇主要探讨角色管理功能,其中菜单权限这里先不实现,后续在菜单管理中再进行实现。接口部分依然是使用 Apifox mock 的。

1 角色 api

在 src/api/role.ts 中添加角色相关 api,代码如下:

//src/api/role.ts
import service from "./config/request";
import type { ApiResponse } from "./type";export interface IRole {id: number;name: string;description: string;is_default: number;
}//定义state类型
export interface IRoleState {roles: IRole[];count: number;
}export interface IRoleParams {pageNum: number;pageSize: number;
}// 获取角色
export const getRoles = (params = { pageNum: 0, pageSize: 10 }
): Promise<ApiResponse<IRoleState>> => {return service.get("/role", {params});
};// 新增角色
export const addRole = (data: IRole): Promise<ApiResponse> => {return service.post("/role", data);
};// 更新角色
export const updateRole = (id: number,data: Partial<IRole>
): Promise<ApiResponse> => {return service.put("/role/" + id, data);
};// 删除角色
export const removeRole = (id: number): Promise<ApiResponse> => {return service.delete("/role/" + id);
};

2 角色 store

在 src/stores/role.ts 中添加角色相关方法,代码如下:

//src/stores/role.ts
import type { IRole, IRoleParams, IRoleState } from "@/api/role";
import {getRoles as getRolesApi,addRole as addRoleApi,updateRole as updateRoleApi,removeRole as removeRoleApi
} from "@/api/role";
type WithRoleParmas = IRole & IRoleParams;export const useRoleStore = defineStore("role", () => {//状态const state = reactive<IRoleState>({roles: [],count: 0});//获取角色const getRoles = async (params: IRoleParams) => {const res = await getRolesApi(params);const { data } = res;state.roles = data.roles;state.count = data.count;};//添加角色const addRole = async (data: WithRoleParmas) => {const { pageNum, pageSize, ...obj } = data;const res = await addRoleApi(obj);if (res.code == 0) {getRoles({ pageNum, pageSize });}};//修改角色const updateRole = async (data: WithRoleParmas) => {const { pageNum, pageSize, ...obj } = data;const res = await updateRoleApi(obj.id, obj);if (res.code == 0) {getRoles({ pageNum, pageSize });}};//删除角色const removeRole = async (data: WithRoleParmas) => {const { pageNum, pageSize, id } = data;const res = await removeRoleApi(id);if (res.code == 0) {getRoles({ pageNum, pageSize });}};return { getRoles, addRole, updateRole, removeRole, state };
});

3 角色管理页面开发

角色管理页面文件结构如下图所示:

3.1 角色处理函数封装

在 src/views/system/role/roleHelpers.ts 中封装角色处理的相关操作函数(增删改查),代码如下:

//src/views/system/role/roleHelpers.ts
// 从 @/api/role 模块中导入 IRole 类型
import type { IRole } from "@/api/role";
// 从 @/stores/role 模块中导入 useRoleStore 函数
import { useRoleStore } from "@/stores/role";/*** 自定义组合式函数,用于处理角色相关的操作* @param pageSize - 每页显示的记录数,使用 Ref 类型* @param pageNum - 当前页码,使用 Ref 类型* @returns 包含角色操作方法和状态的对象*/
export const useRoleHelpers = ({pageSize,pageNum
}: {pageSize: Ref<number>;pageNum: Ref<number>;
}) => {// 获取当前组件实例的代理对象const { proxy } = getCurrentInstance()!;// 定义编辑类型,-1 表示初始状态,0 表示编辑,1 表示新增const editType = ref(-1);// 定义模态框的可见状态const visible = ref(false);// 定义要编辑的数据,初始值为 undefinedconst editData = ref<IRole | undefined>(undefined);// 获取角色状态管理仓库的实例const store = useRoleStore();// 计算面板的标题,根据编辑类型决定显示“增加角色”还是“修改角色”const panelTitle = computed(() =>editType.value == 1 ? "增加角色" : "修改角色");/*** 处理编辑角色的操作* @param role - 要编辑的角色对象*/const handleEditRole = (role: IRole) => {// 设置编辑类型为 0,表示编辑editType.value = 0;// 复制要编辑的角色数据editData.value = { ...role };// 显示模态框visible.value = true;};/*** 处理添加新角色的操作*/const hanleAddRole = () => {// 设置编辑类型为 1,表示新增editType.value = 1;// 初始化要编辑的数据为空的角色对象editData.value = {} as IRole;// 显示模态框visible.value = true;};/*** 添加新角色的异步方法* @param data - 要添加的角色数据*/const addNewRole = async (data: IRole) => {// 调用仓库的 addRole 方法添加角色,并传递分页信息await store.addRole({...data,pageNum: pageNum.value,pageSize: pageSize.value});// 显示成功提示信息proxy?.$message.success("角色添加成功");// 隐藏模态框visible.value = false;};/*** 编辑角色的异步方法* @param data - 要编辑的角色数据*/const editRow = async (data: IRole) => {// 调用仓库的 updateRole 方法更新角色,并传递分页信息await store.updateRole({...data,pageNum: pageNum.value,pageSize: pageSize.value});// 显示成功提示信息proxy?.$message.success("角色编辑成功");// 隐藏模态框visible.value = false;};/*** 处理提交表单的异步方法,根据编辑类型调用不同的处理方法* @param data - 表单提交的角色数据*/const handleSubmit = async (data: IRole) => {if (editType.value === 1) {// 如果是新增类型,调用 addNewRole 方法await addNewRole(data);} else {// 如果是编辑类型,调用 editRow 方法await editRow(data);}};/*** 处理删除角色的异步方法* @param data - 要删除的角色数据*/const handleRemove = async (data: IRole) => {try {// 弹出确认对话框,确认是否删除角色await proxy?.$confirm("你确定删除" + data.name + "角色吗?", {type: "warning"});// 调用仓库的 removeRole 方法删除角色,并传递分页信息await store.removeRole({...data,pageNum: pageNum.value,pageSize: pageSize.value});// 显示成功提示信息proxy?.$message.success("角色删除成功");} catch {// 如果用户取消删除,显示取消提示信息proxy?.$message.info("取消删除");}};// 返回包含角色操作方法和状态的对象return {handleSubmit,handleRemove,handleEditRole,hanleAddRole,panelTitle,editType,visible,editData};
};

3.2 editorRole 组件封装

在 src/views/system/role/components/editorRole.vue 中,对角色的新增编辑页面进行封装,代码如下:

//src/views/system/role/components/editorRole.vue 
<template><el-form :model="editData" label-width="auto" style="max-width: 600px"><el-form-item label="角色名称"><el-input v-model="editData.name" /></el-form-item><el-form-item label="描述"><el-input v-model="editData.description" /></el-form-item><el-form-item label="是否是默认角色 "><el-switchv-model="editData.is_default":active-value="1":inactive-value="0"></el-switch></el-form-item><el-form-item><el-button type="primary" @click="submitForm">提交</el-button><el-button @click="handleReset">重置</el-button></el-form-item></el-form>
</template><script lang="ts" setup>
import type { IRole } from "@/api/role";
import type { PropType } from "vue";
import { ref, defineProps, watchEffect, defineEmits } from "vue";// 定义 editData 响应式变量,用于存储表单数据,初始值为空对象
const editData = ref({name: "",description: "",is_default: 0
});// 定义组件接收的 props
const { data, type } = defineProps({data: {// 指定 data 的类型为 IRole 对象type: Object as PropType<IRole>,// 如果未传入 data,默认返回空对象default: () => ({})},type: {// 指定 type 的类型为数字type: Number,// type 为必填项required: true}
});// 定义默认表单数据,用于重置表单
const defaultProps = {name: "",description: "",is_default: 0
};// 重置表单数据的函数,将默认数据和传入的 data 合并
const resetForm = () => {editData.value = { ...defaultProps, ...data };
};// 监听 data 的变化,当 data 改变时重置表单
watchEffect(() => {if (data) {resetForm();}
});// 定义自定义事件,用于向父组件发送表单数据
const emit = defineEmits(["submit"]);// 提交表单的函数,触发 submit 事件并传递表单数据
const submitForm = () => {emit("submit", editData.value);
};// 处理重置操作的函数,调用 resetForm 重置表单
const handleReset = () => {resetForm();
};
</script>

3.3 角色管理页面

修改 src/views/system/role/index.vue,编写角色管理静态页面,代码如下:

//src/views/system/role/index.vue
<template><div p-30px><h2>角色管理</h2><el-button @click="hanleAddRole">角色添加</el-button><el-table :data="roles" style="width: 100%"><el-table-column prop="id" label="角色id" width="180" /><el-table-column prop="name" label="角色名称" width="180" /><el-table-column prop="description" label="描述" /><el-table-columnprop="is_default"label=" 默认角色":formatter="formatter"/><el-table-column label="操作" fixed="right"><template #default="scope"><el-button link @click="handleEditRole(scope.row)">编辑</el-button><el-button link @click="handleRemove(scope.row)">删除</el-button></template></el-table-column></el-table><el-pagination:page-sizes="[1, 5, 10, 20]"layout="prev, pager, next, sizes, total":total="count":page-size="pageSize"@size-change="handleSizeChange"@current-change="handleCurrentChange"/><!-- 右侧面板组件,使用 v-model 绑定 visible 控制显示隐藏,设置标题 --><right-panel v-model="visible" :title="panelTitle"><!-- 角色编辑组件,传递编辑类型和编辑数据,监听 submit 事件 --><editor-role:type="editType":data="editData"@submit="handleSubmit"></editor-role></right-panel></div>
</template><script lang="ts" setup>
import type { IRole } from "@/api/role";
import { useRoleStore } from "@/stores/role";
import { useRoleHelpers } from "./roleHelpers";
import { ref, toRefs, watchEffect } from "vue";// 获取角色状态管理仓库实例
const store = useRoleStore();
// 当前页码,初始为 0
const pageNum = ref(0);
// 每页显示的记录数,初始为 10
const pageSize = ref(10);// 从 useRoleHelpers 组合式函数中解构出所需的方法和状态
const {handleSubmit,handleRemove,handleEditRole,hanleAddRole,panelTitle,editType,visible,editData
} = useRoleHelpers({ pageNum, pageSize });// 将仓库状态中的 count 和 roles 转换为响应式引用
const { count, roles } = toRefs(store.state);// 监听 pageNum 和 pageSize 的变化,当变化时重新获取角色数据
watchEffect(() => {store.getRoles({ pageNum: pageNum.value, pageSize: pageSize.value });
});// 处理每页显示记录数改变的方法
const handleSizeChange = (val: number) => {pageSize.value = val;
};// 处理当前页码改变的方法
const handleCurrentChange = (val: number) => {pageNum.value = val - 1;
};// 格式化是否为默认角色的显示内容
const formatter = (row: IRole) => {return row.is_default ? "是" : "否";
};
</script>

npm run dev 启动项目后,页面效果如下:

以上,就是角色管理的全部内容。

下一篇将继续探讨 用户管理,敬请期待~

相关文章:

Vue3.5 企业级管理系统实战(十七):角色管理

本篇主要探讨角色管理功能&#xff0c;其中菜单权限这里先不实现&#xff0c;后续在菜单管理中再进行实现。接口部分依然是使用 Apifox mock 的。 1 角色 api 在 src/api/role.ts 中添加角色相关 api&#xff0c;代码如下&#xff1a; //src/api/role.ts import service fro…...

QTableWidget实现多级表头、表头冻结效果

最终效果&#xff1a; 实现思路&#xff1a;如果只用一个表格的话写起来比较麻烦&#xff0c;可以考虑使用两个QTableWidget组合&#xff0c;把复杂的表头一个用QTableWidget显示&#xff0c;其他内容用另一个QTableWidget。 #include "mainwindow.h" #include &qu…...

A2A大模型协议及Java示例

A2A大模型协议概述 1. 协议作用 A2A协议旨在解决以下问题&#xff1a; 数据交换&#xff1a;不同应用程序之间的数据格式可能不一致&#xff0c;A2A协议通过定义统一的接口和数据格式解决这一问题。模型调用&#xff1a;提供标准化的接口&#xff0c;使得外部应用可以轻松调…...

单脉冲前视成像多目标分辨算法——论文阅读

单脉冲前视成像多目标分辨算法 1. 论文的研究目标及实际意义1.1 研究目标1.2 实际问题与产业意义2. 论文的创新方法及公式解析2.1 核心思路2.2 关键公式与模型2.2.1 单脉冲雷达信号模型2.2.2 匹配滤波输出模型2.2.3 多目标联合观测模型2.2.4 对数似然函数与优化2.2.5 MDL准则目…...

CMake 入门实践

CMake 入门实践 第一章 概念与基础项目1.1 CMake 基础认知1.2 最小 CMake 项目1.3 构建流程验证 第二章 多文件项目管理2.1 项目结构2.2 源码示例2.3 CMake 配置 第三章 库文件管理实战3.1 项目结构3.2 核心配置3.3 接口设计 第四章 构建类型与编译优化4.1 构建类型配置4.2 构建…...

异地多活单元化架构下的微服务体系

治理服务间的跨IDC调用&#xff0c;而数据库层面还是要跨IDC 服务注册中心拆开、 金融要求&#xff0c;距离太远&#xff0c;异地备库&#xff0c;如果延迟没读到数据就可能有资损&#xff0c;IDC3平时不能用&#xff0c;IDC1挂了还是有数据同步问题&#xff0c;IDC3日常维护…...

HarmonyOS NEXT——DevEco Studio的使用(还没写完)

一、IDE环境的搭建 Windows环境 运行环境要求 为保证DevEco Studio正常运行&#xff0c;建议电脑配置满足如下要求&#xff1a; 操作系统&#xff1a;Windows10 64位、Windows11 64位 内存&#xff1a;16GB及以上 硬盘&#xff1a;100GB及以上 分辨率&#xff1a;1280*8…...

《Python星球日记》 第46天:决策树与随机森林

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏:《Python星球日记》,限时特价订阅中ing 目录 一、前言二、决策树算法原理1. 决策树简介2. 决策树的分裂准则(1) 信息熵与信息增益(2) 基尼不纯…...

Windows系统Jenkins企业级实战

目标 在Windows操作系统上使用Jenkins完成代码的自动拉取、编译、打包、发布工作。 实施 1.安装Java开发工具包&#xff08;JDK&#xff09; Jenkins是基于Java的应用程序&#xff0c;因此需要先安装JDK。可以从Oracle官网或OpenJDK下载适合的JDK版本。推荐java17版本&#x…...

C# 方法(ref局部变量和ref返回)

>本章内容: 方法的结构 方法体内部的代码执行 局部变量 局部常量 控制流 方法调用 返回值 返回语句和void方法 局部函数 参数 值参数 引用参数 引用类型作为值参数和引用参数 输出参数 参数数组 参数类型总结 方法重载 命名参数 可选参数 栈帧 递归 ref局部变量和ref返回 …...

C# 引用类型作为值参数与引用参数的区别

在编程中&#xff0c;我们常常需要处理引用类型对象&#xff0c;而将引用类型对象作为参数传递给方法时&#xff0c;有值参数和引用参数这两种方式&#xff0c;它们在方法内部操作时会产生不同的结果。下面就来详细分析这两种情况。 引用类型对象作为值参数传递 当我们把引用…...

滑动窗口,438找出字符串中所有字母的异位词

1.题目 2.解析 这道题我们用滑动窗口来实现&#xff0c;加上哈希表和vector容器的使用来实现这道题目&#xff0c;每次滑动之后我们都对其和答案进行比较&#xff0c;如果全部相等我们返回left&#xff0c;不相等继续滑动即可。 本质就是我们把p中相同数量的字母框起来&#…...

「国产嵌入式仿真平台:高精度虚实融合如何终结Proteus时代?」——从教学实验到低空经济,揭秘新一代AI赋能的产业级教学工具

引言&#xff1a;从Proteus到国产平台的范式革新 在高校嵌入式实验教学中&#xff0c;仿真工具的选择直接影响学生的工程能力培养与创新思维发展。长期以来&#xff0c;Proteus作为经典工具占据主导地位&#xff0c;但其设计理念已难以满足现代复杂系统教学与国产化技术需求。…...

《Python星球日记》 第52天:反向传播与优化器

名人说&#xff1a;路漫漫其修远兮&#xff0c;吾将上下而求索。—— 屈原《离骚》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 一、引言二、反向传播算法原理简述1. 什么是反向传播&#xff1f;2. 从数学角度…...

Java常用类概述

Java常用类概述 一、字符串三剑客1. String&#xff08;不可变字符串&#xff09;2. StringBuilder&#xff08;可变&#xff0c;线程不安全&#xff09;3. StringBuffer&#xff08;可变&#xff0c;线程安全&#xff09; 二、日期时间类&#xff08;重点掌握新版API&#xff…...

在现代Web应用中集成 PDF.js (pdfjs-dist 5.2 ESM): 通过 jsdelivr 实现动态加载与批注功能的思考

PDF 文档在现代 Web 应用中越来越常见&#xff0c;无论是作为文档预览、报告展示还是在线编辑的载体。Mozilla 的 PDF.js 是一个功能强大的 JavaScript 库&#xff0c;它使得在浏览器端渲染和显示 PDF 文件成为可能&#xff0c;无需依赖原生插件。 本文将深入探讨如何在你的项…...

C++STL——priority_queue

优先队列 前言优先队列仿函数头文件 前言 本篇主要讲解优先队列及其底层实现。 优先队列 优先队列的本质就是个堆&#xff0c;其与queue一样&#xff0c;都是容器适配器&#xff0c;不过优先队列是默认为vector实现的。priority_queue的接口优先队列默认为大根堆。 仿函数 …...

没有 Mac,如何把 iOS App 成功上架?

开发者的 iOS 上架折腾记&#xff1a;没有 Mac&#xff0c;也能搞定&#xff1f; 最近在帮朋友把一个跨平台 Flutter 项目上架到 App Store&#xff0c;结果被 iOS 上架的那套流程卡得头都大了。其实这也不是第一次碰壁了——每次到“申请证书 打包 上传”的时候&#xff0c…...

C++ Vector深度易错点指南(临时抱佛脚)(基础用法;进阶;高级;实战)

Vector 1. Vector 基础概念1.1 内存结构1.2 初始化方法2.1 访问方式对比2.2 遍历流程3.1 扩容流程3.2 迭代器失效3.2.1 插入操作导致迭代器失效3.2.2 删除操作导致迭代器失效3.2.3 避免迭代器失效的建议4.1 排序与去重排序去重性能分析4.2 查找与条件删除查找条件删除性能分析5…...

深入解析WPF中的3D图形编程:材质与光照

引言 在Windows Presentation Foundation (WPF) 中创建三维(3D)图形是一项既有趣又具有挑战性的任务。为了帮助开发者更好地理解如何使用WPF进行3D图形的渲染&#xff0c;本文将深入探讨GeometryModel3D类及其相关的材质和光源设置。 1、GeometryModel3D类简介 GeometryMode…...

SolidWork-2023 鼠標工程

地址 https://github.com/MartinxMax/SW2023-Project/tree/main/mouse 鼠標...

vscode预览模式(点击文件时默认覆盖当前标签,标签名称显示为斜体,可通过双击该标签取消)覆盖标签、新窗打开

文章目录 VS Code 预览模式如何取消预览模式&#xff08;即“固定”标签页&#xff09;&#xff1f;预览模式有什么用&#xff1f; VS Code 预览模式 在 VS Code 中&#xff0c;当你单击文件浏览器&#xff08;例如&#xff0c;资源管理器侧边栏&#xff09;中的某个文件时&am…...

记录踩过的坑-金蝶云苍穹平台-轻分析和轻报表(慢慢更新)

未发现AppIdName(qing rpt)服务或访问服务网络异常 前提是有许可和权限。 去console&#xff08;云基础平台控制台&#xff09;&#xff0c;点击服务管理&#xff0c;编辑mservice-更新升级-环境变量&#xff0c;在appIds里增加qing_rpt 查看数据库 如果是采用公共数据源连接…...

每日一题洛谷T534125 合数c++

字符串输入&#xff0c;看所有位数加起来的数是不是3的倍数 是&#xff0c;直接输出&#xff0c;不是&#xff0c;删除1或2 特判全是1和全是2的情况 直接检测末尾数字可以特判2 特判1时&#xff0c;还要特判11和111&#xff0c;其他数字&#xff0c;k是奇数时是质数&#x…...

数据链共享:从印巴空战到工业控制的跨越性应用

摘要 本文通过对印巴空战中数据链共享发挥关键作用的分析&#xff0c;引出数据链共享在工业控制领域同样具有重大价值的观点。深入阐述 DIOS 工业控制操作系统作为工业数据链共享基础技术的特点、架构及应用优势&#xff0c;对比空战场景与工业控制场景下数据链共享的相…...

Go多服务项目结构优化:为何每个服务单独设置internal目录?

文章目录 Go多服务项目结构优化&#xff1a;为何每个服务单独设置internal目录&#xff1f;背景什么是 Go 的 internal 机制&#xff1f;传统根 internal 目录的局限为什么要每个服务单独设置 internal &#xff1f;推荐结构示例 总结 Go多服务项目结构优化&#xff1a;为何每个…...

图解gpt之Seq2Seq架构与序列到序列模型

今天深入探讨如何构建更强大的序列到序列模型&#xff0c;特别是Seq2Seq架构。序列到序列模型&#xff0c;顾名思义&#xff0c;它的核心任务就是将一个序列映射到另一个序列。这个序列可以是文本&#xff0c;也可以是其他符号序列。最早&#xff0c;人们尝试用一个单一的RNN来…...

Linux--JsonCpp

1.JsonCpp 简介 JsonCpp 是一个用于 C 的 JSON 解析和生成库&#xff0c;支持 JSON 数据的读写、解析和序列化。它提供了简单的 API 来操作 JSON 对象、数组、字符串、数字等类型&#xff0c;是 C 开发中处理 JSON 数据的常用工具。 核心功能与类 JsonCpp 主要包含以下核心类…...

程序代码篇---Python视频流

文章目录 前言一、OpenCV 视频流处理1. 视频捕获基础2. 视频流属性设置与获取3. 视频写入 二、高级视频流操作1. 多摄像头处理2. 视频流帧处理3. 视频流分析与统计 三、其他视频处理库1. PyAV (FFmpeg 的 Python 绑定)2. imageio 四、视频流处理优化技巧1. 多线程视频处理2. 视…...

如何利用 QuickAPI 生成 PostgreSQL 样本测试数据:全面解析与实用指南

目录 一、什么是 QuickAPI&#xff1f; 二、为什么需要生成样本测试数据&#xff1f; 三、如何在 QuickAPI 中生成 PostgreSQL 样本测试数据&#xff1f; 1. 登录 QuickAPI 平台 2. 选择 PostgreSQL 数据库和目标表 3. 配置样本数据生成规则 4. 导出或直接插入数据 四、…...