目录
1-用户首页列表开发
1.1-需求原型分析
1.2-封装请求和数据类型
1.3-数据页面渲染和展示
1.4-点击搜索按钮搜索用户
1.5-点击重置按钮
2-新增编辑用户
2.1-原型需求分析
2.2-表单页面数据收集
2.3-页面校验规则的定义
2.4-添加用户按钮编辑按钮逻辑
2.5-保存和取消用户信息逻辑
3-删除和批量删除用户
4-分配角色
1-用户首页列表开发
1.1-需求原型分析
基本结构跟之前的商品管理模块的结构差不多,只不过这里多了一个按照用户名搜索用户,点击搜索就向服务器发送查询,点击重置,清空输入框内容,重新拉取用户列表。在页面加载的过程中,我们需要发送请求获取数据。
列表页面需要使用到el-card组件;搜索输入那边需要使用到el-form组件并且使用行内form,属性:inline="true";
1.2-封装请求和数据类型
该模块所有的接口和数据类型全部定义在此章节,文章下面的模块不在单独定义接口和数据类型。文件src\api\acl\user\type.ts定义数据类型:
//账号信息的ts类型
export interface ResponseData {
code: number
message: string
ok: boolean
}
//代表一个账号信息的ts类型
export interface User {
id?: number
createTime?: string
updateTime?: string
username?: string
password?: string
name?: string
phone?: null
roleName?: string
}
//数组包含全部的用户信息
export type Records = User[]
//获取全部用户信息接口返回的数据ts类型
export interface UserResponseData extends ResponseData {
data: {
records: Records
total: number
size: number
current: number
pages: number
}
}
//代表一个职位的ts类型
export interface RoleData {
id?: number
createTime?: string
updateTime?: string
roleName: string
remark: null
}
//全部职位的列表
export type AllRole = RoleData[]
//获取全部职位的接口返回的数据ts类型
export interface AllRoleResponseData extends ResponseData {
data: {
assignRoles: AllRole
allRolesList: AllRole
}
}
//给用户分配职位接口携带参数的ts类型
export interface SetRoleData {
roleIdList: number[]
userId: number
}
文件src\api\acl\user\index.ts定义请求服务端相关接口:
//用户管理模块的接口
import request from '@/utils/request'
import type {
UserResponseData,
User,
AllRoleResponseData,
SetRoleData,
} from './type'
//枚举地址
enum API {
ALLUSER_URL = '/admin/acl/user/', //获取全部已有用户账号信息
ADDUSER_URL = '/admin/acl/user/save', //添加一个新的用户账号
UPDATEUSER_URL = '/admin/acl/user/update',//更新已有的用户账号
ALLROLEURL = '/admin/acl/user/toAssign/',//获取全部角色,当前账号拥有的角色接口
SETROLE_URL = '/admin/acl/user/doAssignRole',//给已有的用户分配角色接口
DELETEUSER_URL = '/admin/acl/user/remove/', //删除某一个账号
DELETEALLUSER_URL = '/admin/acl/user/batchRemove',//批量删除的接口
}
//获取用户账号信息的接口
export const reqUserInfo = (page: number, limit: number, username: string) =>
request.get<any, UserResponseData>(
API.ALLUSER_URL + `${page}/${limit}/?username=${username}`,
)
//添加用户与更新已有用户的接口
export const reqAddOrUpdateUser = (data: User) => {
//携带参数有ID更新
if (data.id) {
return request.put<any, any>(API.UPDATEUSER_URL, data)
} else {
return request.post<any, any>(API.ADDUSER_URL, data)
}
}
//获取全部角色以及包含当前用户的已有的角色
export const reqAllRole = (userId: number) =>
request.get<any, AllRoleResponseData>(API.ALLROLEURL + userId)
//分配角色
export const reqSetUserRole = (data: SetRoleData) =>
request.post<any, any>(API.SETROLE_URL, data)
//删除某一个账号的信息
export const reqRemoveUser = (userId: number) =>
request.delete<any, any>(API.DELETEUSER_URL + userId)
//批量删除的接口
export const reqSelectUser = (idList: number[]) =>
request.delete(API.DELETEALLUSER_URL, { data: idList })
1.3-数据页面渲染和展示
定义请求和接受服务器端返回的相关数据类型:
import useLayOutSettingStore from '@/store/modules/setting'
import { ref, onMounted, reactive, nextTick } from 'vue';
import { reqSelectUser, reqRemoveUser, reqUserInfo, reqAddOrUpdateUser, reqAllRole, reqSetUserRole } from '@/api/acl/user'
import type { SetRoleData, UserResponseData, Records, User, AllRoleResponseData, AllRole } from '@/api/acl/user/type';
import { ElMessage } from 'element-plus';
let pageNo = ref<number>(1);//默认页码
let pageSize = ref<number>(5);//一页展示几条数据
let total = ref<number>(0);//用户总个数
let userArr = ref<Records>([]);//存储全部用户的数组
//组件挂载完毕
onMounted(() => {
getHasUser();
});
//获取全部已有的用户信息
const getHasUser = async (pager = 1) => {
//收集当前页码
pageNo.value = pager;
let result: UserResponseData = await reqUserInfo(pageNo.value, pageSize.value, keyword.value);
if (result.code == 200) {
total.value = result.data.total;
userArr.value = result.data.records;
}
}
//分页器下拉菜单的自定义事件的回调
const handler = () => {
getHasUser();
}
动态渲染数据类型:
1.4-点击搜索按钮搜索用户
填写关键字信息,点击搜索按钮,调用用户列表接口获取用户属性;完成后,关键字置空。
ps:这里可以建议不置空(方便用户查看自己输入的关键字),点击重置的时候,置空再获取用户信息。
let keyword = ref<string>('');//定义响应式数据:收集用户输入进来的关键字
//搜索按钮的回调
const search = () => {
getHasUser();//根据关键字获取相应的用户数据
//清空关键字
keyword.value = '';
}
1.5-点击重置按钮
点击重置按钮,我们改变当前的系统配置的仓库里面的refsh属性,因为我们之前监听了属性变化,dom重新加载。所以会自动调用接口。
文件src\views\acl\user\index.vue中获取配置以及方法回调
import useLayOutSettingStore from '@/store/modules/setting'
//重置按钮
const reset = () => {
settingStore.refsh = !settingStore.refsh;
}
2-新增编辑用户
2.1-原型需求分析
点击添加用户的时候,需要有个抽屉效果,需要使用到el-drawer组件,里面对用户名-用户昵称-用户密码进行相关的校验。点击保存就调用服务端接口保存用户,取消就需要关闭抽屉和清除相关数据。
2.2-表单页面数据收集
定义收集表单的数据类型对象:
//收集用户信息的响应式数据
let userParams = reactive<User>({
username: '',
name: '',
password: ''
});
页面结构的开发:
2.3-页面校验规则的定义
我们需要对页面的输入参数进行简单校验,在实际项目中,可以根据自己的实际项目要求制定规则,复杂的可以采用正则表达式来实现。
//表单校验的规则对象
const rules = {
//用户名字
username: [{ required: true, trigger: 'blur', validator: validatorUsername }],
//用户昵称
name: [{ required: true, trigger: 'blur', validator: validatorname }],
//用户的密码
password: [{ required: true, trigger: 'blur', validator: validatorPassword }],
}
//校验用户名字回调函数
const validatorUsername = (rule: any, value: any, callBack: any) => {
//用户名字|昵称,长度至少五位
if (value.trim().length >= 5) {
callBack();
} else {
callBack(new Error('用户名字至少五位'))
}
}
//校验用户名字回调函数
const validatorname = (rule: any, value: any, callBack: any) => {
//用户名字|昵称,长度至少五位
if (value.trim().length >= 5) {
callBack();
} else {
callBack(new Error('用户昵称至少五位'))
}
}
const validatorPassword = (rule: any, value: any, callBack: any) => {
//用户名字|昵称,长度至少五位
if (value.trim().length >= 6) {
callBack();
} else {
callBack(new Error('用户密码至少六位'))
}
}
2.4-添加用户按钮编辑按钮逻辑
//添加用户按钮的回调
const addUser = () => {
drawer.value = true;//抽屉显示出来
Object.assign(userParams, {id: 0,username: '',name: '',password: ''}); //清空数据
//清除上一次的错误的提示信息
nextTick(() => {
formRef.value.clearValidate('username');
formRef.value.clearValidate('name');
formRef.value.clearValidate('password');
});
}
点击编辑用户按钮,需要回显用户信息:
//更新已有的用户按钮的回调
//row:即为已有用户的账号信息
const updateUser = (row: User) => {
drawer.value = true;//抽屉显示出来
Object.assign(userParams, row);//存储收集已有的账号信息
//清除上一次的错误的提示信息
nextTick(() => {
formRef.value.clearValidate('username');
formRef.value.clearValidate('name');
});
}
2.5-保存和取消用户信息逻辑
点击保存和取消按钮的时候,需要开发相关的业务逻辑,先需要通过之前的表单校验规则校验相关的字段,当校验通过后,在向服务器发送请求,保存用户信息。
3-删除和批量删除用户
点击列表操作按钮中的删除和上面的批量删除按钮,需要弹框提示用户确认删除信息,然后调用服务端接口,不管成功还是失败提示用户,删除完成后,需要重新获取列表页面的数据。
//删除某一个用户
const deleteUser = async (userId: number) => {
let result: any = await reqRemoveUser(userId);
if (result.code == 200) {
ElMessage({ type: 'success', message: '删除成功' });
getHasUser(userArr.value.length > 1 ? pageNo.value : pageNo.value - 1);
}
}
批量删除用户信息:
let selectIdArr = ref<User[]>([]);//准备一个数组存储批量删除的用户的ID
//table复选框勾选的时候会触发的事件
const selectChange = (value: any) => {
selectIdArr.value = value;
}
//批量删除按钮的回调
const deleteSelectUser = async () => {
//整理批量删除的参数
let idsList: any = selectIdArr.value.map(item => {
return item.id;
});
//批量删除的请求
let result: any = await reqSelectUser(idsList);
if (result.code == 200) {
ElMessage({ type: 'success', message: '删除成功' });
getHasUser(userArr.value.length > 1 ? pageNo.value : pageNo.value - 1);
}
}
4-分配角色
点击列表页面的分配角色,抽屉弹出用户有的角色信息,已经全部的角色信息。点击单个角色的时候,进行勾选或者取消。当我们单个全部选中的时候,上面的全选就勾选上。
ps:这里的重难点在于,角色列表展示的时候,全选和半选状态的切换以及判断等。
let drawer1 = ref<boolean>(false);//控制分配角色抽屉显示与隐藏
let allRole = ref<AllRole>([]);//存储全部角色的数据
let userRole = ref<AllRole>([]);//当前用户已有的角色
//分配角色按钮的回调
const setRole = async (row: User) => {
Object.assign(userParams, row);//存储已有的用户信息
//获取全部的角色的数据与当前用户已有的角色的数据
let result: AllRoleResponseData = await reqAllRole((userParams.id as number));
if (result.code == 200) {
allRole.value = result.data.allRolesList;//存储全部的角色
userRole.value = result.data.assignRoles;//存储当前用户已有的角色
drawer1.value = true;//抽屉显示出来
}
}
const checkAll = ref<boolean>(false);//收集顶部复选框全选数据
const isIndeterminate = ref<boolean>(true);//控制顶部全选复选框不确定的样式
//顶部的全部复选框的change事件
const handleCheckAllChange = (val: boolean) => {
//val:true(全选)|false(没有全选)
userRole.value = val ? allRole.value : [];
//不确定的样式(确定样式)
isIndeterminate.value = false
}
//顶部全部的复选框的change事件
const handleCheckedCitiesChange = (value: string[]) => {
//顶部复选框的勾选数据
//代表:勾选上的项目个数与全部的职位个数相等,顶部的复选框勾选上
checkAll.value = value.length === allRole.value.length;
//不确定的样式
isIndeterminate.value = value.length !== allRole.value.length
}
点击保存按钮,需要将收集到的数据组装成一个对象提交给服务器,这里我们需要提交用户的id和角色的id集合。
//确定按钮的回调(分配角色)
const confirmClick = async () => {
//收集参数
let data: SetRoleData = {
userId: (userParams.id as number),
roleIdList: userRole.value.map(item => {
return (item.id as number)
})
}
//分配用户的角色
let result: any = await reqSetUserRole(data);
if (result.code == 200) {
ElMessage({ type: 'success', message: '分配职务成功' });//提示信息
drawer1.value = false;//关闭抽屉
getHasUser(pageNo.value);//获取更新完毕用户的信息,更新完毕留在当前页
}
}