

添加、编辑
用的是同一个编辑面板
1-1 user.vue
添加用户就等于注册用户,目前密码默认都是6个1
src/views/system/user/index.vue
<template><div class="user-container"><h2>用户管理</h2><el-form :inline="true" :model="formQuery" ref="queryFormRef"><el-form-item label="用户名" prop="username"><el-input v-model="formQuery.username" placeholder="请输入用户名"></el-input></el-form-item><el-form-item label="手机号" prop="mobile"><el-input v-model="formQuery.mobile" placeholder="请输入手机号"></el-input></el-form-item><el-form-item label="状态" prop="status"><el-select v-model="formQuery.status" placeholder="状态"><el-option label="全部" value="all"></el-option><el-option label="禁用" :value="0"></el-option><el-option label="正常" :value="1"></el-option></el-select></el-form-item><el-form-item><el-button type="primary" @click="handleSubmitQuery">查询</el-button><el-button type="default" @click="handleResetFeilds">重置</el-button></el-form-item></el-form><div class="role-list"><el-buttontype="primary"plainicon="el-icon-plus"@click="handleAddUser">添加用户</el-button><el-table:data="users"max-height="400"><el-table-columnprop="username"label="用户名"></el-table-column><el-table-columnprop="mobile"label="手机"></el-table-column><el-table-columnprop="email"label="邮箱"></el-table-column><el-table-columnprop="status"label="状态":formatter="formatter"></el-table-column><el-table-columnprop="createdAt"label="创建时间"></el-table-column><el-table-columnlabel="操作"fixed="right"width="150px"><template #default="scope"><el-buttontype="text"size="mini"@click="handleEditUser(scope.$index, scope.row)">编辑</el-button><el-buttontype="text"size="mini"@click="handleDeleteUser(scope.$index, scope.row)">删除</el-button></template></el-table-column></el-table><div class="user-pagination"><el-pagination@size-change="handleSizeChange"@current-change="handleCurrentChange"background:total="total":page-sizes="[1, 5, 10, 20]":page-size="pageSize"layout="total, prev, pager, next, sizes,jumper"></el-pagination></div></div><!-- 新增角色 编辑角色面板 --><right-panel v-model="panelVisible" :title="panelTitle" :size="330"><editor-user:type="editType":data="editData"@submit="handleSubmitUser"/></right-panel></div></template><script lang="ts">import { computed, defineComponent, onMounted, reactive, ref, getCurrentInstance } from 'vue'import { ElForm } from 'element-plus'import { Profile } from '@/store/modules/user'import { useStore } from '@/store'import RightPanel from '@/components/RightPanel/index.vue'import EditorUser from './components/editorUser.vue'type ElFormInstance = InstanceType<typeof ElForm>export default defineComponent({name: 'User',components: {EditorUser,RightPanel},setup() {const { proxy } = getCurrentInstance()!const store = useStore()// 查询表单refconst queryFormRef = ref<ElFormInstance | null>(null)// 查询条件const formQuery = reactive({username: '',status: 'all',mobile: ''})// 用户列表const users = computed(() => store.state.user.users)// 用户总条数const total = computed(() => store.state.user.count)// 分页相关状态const pageNum = ref(0)const pageSize = ref(1)// 获取用户列表 支持分页const getUserList = () => {store.dispatch('user/getAllUsers', {pageNum: pageNum.value,pageSize: pageSize.value,...formQuery})}onMounted(() => { // 初始加载数据getUserList()})// 查询const handleSubmitQuery = () => {getUserList()}// 重置const handleResetFeilds = () => {(queryFormRef.value as ElFormInstance).resetFields()getUserList()}// 分页const handleSizeChange = (val: number) => {pageSize.value = valgetUserList()}const handleCurrentChange = (val: number) => {pageNum.value = val - 1 // 页码后端是从0开始的getUserList()}// 格式化statusconst formatter = (row: Profile) => {return row.status ? '正常' : '禁用'}// 用户新增const editData = ref<Profile | undefined>(undefined)// 控制面板显示const panelVisible = ref(false)// 操作类型 0编辑 1新增const editType = ref(1)// panel titleconst panelTitle = computed(() => editType.value === 1 ? '新增用户' : '编辑用户')// 获取角色 添加和编辑用户都需要分配角色 这里是必选store.dispatch('role/getRoles')const roles = computed(() => store.state.role.roles)// 添加用户const handleAddUser = () => {editType.value = 1editData.value = {} as ProfileeditData.value.roles = roles.value // 所有角色列表editData.value.roleIds = [] // 所选角色id列表panelVisible.value = true}// 编辑用户const handleEditUser = (index: number, row: Profile) => {editType.value = 0editData.value = { ...row }// 获取当前编辑用户 现有角色列表editData.value.roleIds = row.roles.map(item => item.id)editData.value.roles = roles.value // 所有角色列表panelVisible.value = true}// 新增编辑 统一派发方法const dispatchAction = async (action: string, data: Partial<Profile>, message: string) => {await store.dispatch(action, {...data,pageSize: pageSize.value,pageNum: pageNum.value}).then(() => {(queryFormRef.value as ElFormInstance).resetFields()proxy?.$message.success(message)panelVisible.value = false})}// 新增用户const addNewUser = (data: Profile) => {dispatchAction('user/addUser', data, '用户添加成功')}// 编辑用户const editUser = (data: Profile) => {dispatchAction('user/editUser', data, '用户编辑成功')}// 删除用户const handleDeleteUser = (index: number, row: Profile) => {proxy?.$confirm(`您确认要删除用户${row.username}吗?`, '删除确认', {type: 'warning'}).then(async () => {await dispatchAction('user/removeUser', {id: row.id}, '用户删除成功')}).catch((err: Error) => {console.log('err', err)proxy?.$message({type: 'info',message: '已取消删除'})})}// 提交用户信息const handleSubmitUser = (data: Profile) => {if (editType.value === 1) { // 新增addNewUser(data)} else if (editType.value === 0) { // 编辑editUser(data)}}return {users,total,pageSize,formQuery,queryFormRef,formatter,editData,panelVisible,editType,panelTitle,handleSubmitUser,handleAddUser,handleEditUser,handleDeleteUser,handleSizeChange,handleCurrentChange,handleSubmitQuery,handleResetFeilds}}})</script><style lang="scss" scoped>.user-container {padding: 30px;.user-pagination {margin-top: 10px;text-align: right;}}</style>
创建editorUser组件
/src/views/system/user/components/editorUser.vue
<template><div class="editor-container"><el-formref="editFormRef":model="editData":rules="menuFormRules"label-width="80px"><el-form-item label="用户名" prop="username"><el-input v-model="editData.username" placeholder="请输入用户名" /></el-form-item><el-form-item label="手机" prop="mobile"><el-inputv-model="editData.mobile"placeholder="请输入手机"maxlength="11"/></el-form-item><el-form-item label="邮箱" prop="email"><el-input v-model="editData.email" placeholder="请输入邮箱" /></el-form-item><el-form-item label="状态" prop="status"><el-switch v-model="editData.status" /></el-form-item><el-form-item label="角色分配" prop="roleIds"><el-select multiple v-model="editData.roleIds" placeholder="请选择角色"><el-optionv-for="item in editData.roles":key="item.id":label="item.name":value="item.id"></el-option></el-select></el-form-item><el-form-item label="说明" prop="description"><el-inputtype="textarea":rows="3"v-model="editData.description"placeholder="请输入说明"/></el-form-item><el-form-item><el-button type="primary" @click="submitMenuForm" :loading="loading">提交</el-button></el-form-item></el-form></div></template><script lang="ts">import { defineComponent, PropType, ref, watchEffect } from 'vue'import { ElForm } from 'element-plus'import { Profile } from '@/store/modules/user'type FormInstance = InstanceType<typeof ElForm>export default defineComponent({name: 'EditorMenu',props: {type: { // 操作类型 0编辑 1新增type: Number,required: true},data: {type: Object as PropType<Profile>}},emits: ['submit'],setup(props, { emit }) {const loading = ref(false)const editFormRef = ref<FormInstance | null>(null)const editData = ref<Partial<Profile>>({username: '',email: '',mobile: '',description: '',status: true})// 验证规则const validateMobile = (rule: unknown,value: string,callback: (arg?: Error) => void) => {if (!isNaN(Number(value)) && value.length === 11) {callback()}callback(new Error('请输入正确格式手机号!'))}const validateRoles = (rule: unknown,value: number[],callback: (arg?: Error) => void) => {if (value.length <= 0) {callback(new Error('请至少选择一个角色!'))}callback()}const menuFormRules = {username: {required: true,message: '请输入用户名',trigger: 'blur'},email: [{required: true,message: '请输入邮箱',trigger: 'blur'},{type: 'email',message: '请输入正确的邮箱地址',trigger: ['blur', 'change']}],mobile: [{required: true,message: '请输入手机',trigger: 'blur'},{message: '请输入正确11位手机号',trigger: 'blur',validator: validateMobile}],roleIds: {required: true,message: '请至少选择一个角色!',// validator: validateRoles,trigger: 'blur'}}const defaultProps = {username: '',email: '',mobile: '',description: '',status: true}watchEffect(() => {if (props.data) {// 移除之前表单效验结果editFormRef.value?.clearValidate()editData.value = { ...defaultProps, ...props.data }}})// 提交编辑菜单const submitMenuForm = () => {(editFormRef.value as FormInstance).validate(valid => {if (valid) {emit('submit', editData.value)}})}return {editData,submitMenuForm,editFormRef,menuFormRules,loading}}})</script><style>.editor-container {padding: 20px;}</style>
1-2 相关store
至于上面页面中 需要依赖角色数据,至于角色的sotre放在角色那一章节
src/store/modules/user.ts
import { Module, MutationTree, ActionTree } from 'vuex'import { IRootState } from '@/store'import { getUserInfo, getUsers, login, addUser, updateUser, removeUser } from '@/api/user'import { setToken, removeToken, getToken } from '@/utils/auth'// login paramsexport interface IUserInfo {username: string;password: string;}interface Role {id: number;name: string;description: string;}export interface Profile {avatar: string;email: string;id: number;isSuper: boolean;mobile: string;status: boolean;username: string;description: string;roles: Role[];roleIds?: number[]}// 定义state类型export interface IUserState {token: string | null;userInfo: Profile | null;users: Profile[];count: number;roles: Role[] | null}// 查询user参数类型export interface IUserQuery {pageNum?: number;pageSize?: number;mobile?: string;status?: boolean;username?: string;}// 用户编辑/添加查询类型export type IProfileQuery = Profile & {pageNum?: number;pageSize?: number;}// mutations类型type IMutations = MutationTree<IUserState>// actions类型type IActions = ActionTree<IUserState, IRootState>// 定义stateconst state: IUserState = {token: getToken(),userInfo: null,users: [],count: 0,roles: null}// 定义mutationconst mutations: IMutations = {SET_TOKEN(state, token: string) {state.token = token},SET_USER_INFO(state, data: Profile) {state.userInfo = data},SET_USERS(state, data: Profile[]) {state.users = data},SET_COUNT(state, data: number) {state.count = data},SET_ROLES(state, data: Role[]) {state.roles = data}}// 定义actionconst actions: IActions = {login({ commit }, userInfo: IUserInfo) {const { username, password } = userInforeturn new Promise((resolve, reject) => {login({ username: username.trim(), password }).then(response => {const { data } = responsecommit('SET_TOKEN', data.token)setToken(data.token) // localStorage中保存tokenresolve(data)}).catch(error => {reject(error)})})},logout({ commit, dispatch }) {// 退出登录接口我这里就不写了return new Promise<void>((resolve) => {// 清空store里tokencommit('SET_TOKEN', '')// 清空localStorage里的tokenremoveToken()// 清除所有tag viewsdispatch('tagsView/delAllViews', null, { root: true })resolve()})},resetToken({ commit }) {return new Promise<void>((resolve) => {// 清空store里tokencommit('SET_TOKEN', '')// 清空localStorage里的tokenremoveToken()resolve()})},getAllUsers({ commit }, params: IUserQuery = {}) {return new Promise<void>((resolve, reject) => {getUsers(params).then(res => {const { data } = rescommit('SET_USERS', data.users)commit('SET_COUNT', data.count)resolve()}).catch(reject)})},addUser({ dispatch }, data: IProfileQuery) {return new Promise<void>((resolve, reject) => {const { pageSize, pageNum, ...params } = dataaddUser(params).then(res => {if (res.code === 0) {dispatch('getAllUsers', {pageSize,pageNum})}resolve()}).catch(reject)})},editUser({ dispatch }, data: IProfileQuery) {return new Promise<void>((resolve, reject) => {const { pageSize, pageNum, ...params } = dataupdateUser(params.id, params).then(res => {if (res.code === 0) {dispatch('getAllUsers', {pageSize,pageNum})}resolve()}).catch(reject)})},removeUser({ dispatch }, data: IProfileQuery) {return new Promise<void>((resolve, reject) => {const { pageSize, pageNum, id } = dataremoveUser(id).then(res => {if (res.code === 0) {dispatch('getAllUsers', {pageSize,pageNum})}resolve()}).catch(reject)})},getUserInfo({ commit }) {return new Promise((resolve, reject) => {getUserInfo().then(response => {const { data } = responseconst { roles, ...info } = datacommit('SET_USER_INFO', info)commit('SET_ROLES', roles)resolve(roles)}).catch(reject)})}}// 定义user moduleconst user: Module<IUserState, IRootState> = {namespaced: true,state,mutations,actions}export default user
1-3 用户相关api
src/api/user.ts
import request from '@/api/config/request'import { IUserQuery, Profile } from '@/store/modules/user'import { ApiResponse } from './type'interface UserLoginData {username: string;password: string;}interface LoginResponseData {token: string;}export const login = (data: UserLoginData): Promise<ApiResponse<LoginResponseData>> => {return request.post('/auth/login',data)}// 获取用户信息interface UserBody {token: string;}export const getUserInfo = (data?: UserBody): Promise<ApiResponse<Profile>> => {return request.post('/auth/info', data)}// 获取用户列表interface IUsers {users: Profile[];count: number;}export const getUsers = (params: IUserQuery): Promise<ApiResponse<IUsers>> => {const { pageNum = 0, pageSize = 10, username = '', status, mobile = '' } = paramsreturn request.get('/user', {params: {pageNum,pageSize,username,status,mobile}})}// 删除用户export const removeUser = (id: number): Promise<ApiResponse> => {return request.delete(`/user/${id}`)}// 添加用户export const addUser = (data: Profile): Promise<ApiResponse> => {return request.post('/auth/register', data)}// 编辑用户export const updateUser = (id: number, data: Profile): Promise<ApiResponse> => {return request.put(`/user/${id}`, data)}

