32-实现分配角色弹框(更新用户角色功能)

下面来实现点击确定的时候,更新用户分配角色
在这里插入图片描述

interface AdminObjItf {
    id?: number
    username?: string
    nickName?: string
    email?: string
    password?: string
    note?: string
    status?: number
}

interface AdminRoleFormData {
    userRoles?: RoleObjItf[]
    roleLists?: RoleObjItf[]
    adminId: number
}

添加给用户分配角色接口

import request from './request'

interface ManageResponse<T = null> {
    code: number
    message: string
    data: T
}

type PromiseResponse<T = {}> = Promise<ManageResponse<T>>

interface AdminListParams {
    keyword: string
    pageNum: number
    pageSize: number
}

interface AdminListResponse {
    list: {}[]
    pageNum: number
    pageSize: number
    total: number
    totalPage: number
}

// 获取用户数据列表
export const getAdminListApi = (data: AdminListParams):PromiseResponse<AdminListResponse> => {
    return request.get('/admin/list', {
        params: data
    })
}
// 修改指定用户信息
export const updateAdmin = (id: number, data: AdminObjItf):PromiseResponse => {
    return request.post('/admin/update/' + id, data)
}
// 获取所有角色
export const getRoleListAll = ():PromiseResponse<RoleObjItf[]> => {
    return request.get('/role/listAll')
}
// 根据用户id获取角色
export const getAdminRoleById = (id: number):PromiseResponse<RoleObjItf[]> => {
    return request.get('/admin/role/' + id)
}
// 给用户分配角色
export const updateAdminRole = (data: {
    adminId: number
    roleIds: number[]
}):PromiseResponse<RoleObjItf[]> => {
    return request.post('/admin/role/update', data)
}
import { type MockMethod } from 'vite-plugin-mock'
import fs from 'fs'
import path from 'path'

import { validateToken } from '../utils'

const adminDataFile = path.join(process.cwd(), 'src/mock/data/admin-list.json')
const roleListDataFile = path.join(process.cwd(), 'src/mock/data/role-list.json')
const roleDataFile = path.join(process.cwd(), 'src/mock/data/role.json')

const readAdmins = () => {
    try {
        const raw = fs.readFileSync(adminDataFile, 'utf-8')
        return JSON.parse(raw) as Array<Record<string, any>>
    } catch (e) {
        console.error('读取用户数据失败', e)
        return []
    }
}

const writeAdmins = (list: Array<Record<string, any>>) => {
    fs.writeFileSync(adminDataFile, JSON.stringify(list, null, 2), 'utf-8')
}

const readRoleLists = () => {
    try {
        const raw = fs.readFileSync(roleListDataFile, 'utf-8')
        return JSON.parse(raw) as Array<Record<string, any>>
    } catch (e) {
        console.error('读取角色列表数据失败', e)
        return []
    }
}

const readRole = () => {
    try {
        const raw = fs.readFileSync(roleDataFile, 'utf-8')
        return JSON.parse(raw) as Array<Record<string, any>>
    } catch (e) {
        console.error('读取角色数据失败', e)
        return []
    }
}

const writeRole = (list: Array<Record<string, any>>) => {
    fs.writeFileSync(roleDataFile, JSON.stringify(list, null, 2), 'utf-8')
}

export default [
    {
        url: '/api/admin/list',
        method: 'get',
        response: ({ headers }: { headers: Record<string, string> }) => {
            const tokenCheck = validateToken(headers)
            if (!tokenCheck.valid) {
                return tokenCheck.response
            }

            const adminList = readAdmins()
            const pageSize = 10
            const pageNum = 1
            const total = adminList.length
            const totalPage = Math.max(1, Math.ceil(total / pageSize))

            return {
                code: 200,
                message: '获取用户数据列表',
                data: {
                    list: adminList,
                    pageNum,
                    pageSize,
                    total,
                    totalPage
                }
            }
        }
    },
    {
        url: '/api/admin/update/:id',
        method: 'post',
        response: (options: {
            headers: Record<string, string>
            body: Record<string, unknown>
            url: string
        }) => {
            const { headers, body, url } = options
            const tokenCheck = validateToken(headers)
            if (!tokenCheck.valid) {
                return tokenCheck.response
            }

            const adminList = readAdmins()
            const id = Number((url.match(/\/api\/admin\/update\/(\d+)/) || [])[1])
            const target = adminList.find(item => item.id === id)

            if (!target) {
                return {
                    code: 404,
                    message: '未找到对应的用户',
                    data: null
                }
            }

            // 合并更新,同时保留原有的 id
            Object.assign(target, body, { id: target.id })
            writeAdmins(adminList)

            return {
                code: 200,
                message: '修改用户信息成功',
                data: target
            }
        }
    },
    {
        url: '/api/role/listAll',
        method: 'get',
        response: ({ headers }: { headers: Record<string, string> }) => {
            const tokenCheck = validateToken(headers)
            if (!tokenCheck.valid) {
                return tokenCheck.response
            }

            const roleList = readRoleLists()
            return {
                code: 200,
                message: '获取角色列表成功',
                data: roleList
            }
        }
    },
    {
        url: '/api/admin/role/:id',
        method: 'get',
        response: ({ headers }: { headers: Record<string, string> }) => {
            const tokenCheck = validateToken(headers)
            if (!tokenCheck.valid) {
                return tokenCheck.response
            }

            const roleList = readRole()
            return {
                code: 200,
                message: '获取角色成功',
                data: roleList
            }
        }
    },
    {
        url: '/api/admin/role/update',
        method: 'post',
        response: (options: {
            headers: Record<string, string>
            body: { adminId: number; roleIds: number[] }
        }) => {
            const { headers, body } = options
            const tokenCheck = validateToken(headers)
            if (!tokenCheck.valid) {
                return tokenCheck.response
            }

            const { roleIds } = body || {}
            const roleList = readRoleLists()
            const selectedRoles = Array.isArray(roleIds)
                ? roleList.filter(item => roleIds.includes(item.id))
                : []

            writeRole(selectedRoles)

            return {
                code: 200,
                message: '分配角色成功',
                data: selectedRoles
            }
        }
    }
] as MockMethod[]

页面实现

<template>
    <div class=''>
        <el-table :data="tableData" style="width: 100%">
            <el-table-column prop="id" label="编号"/>
            <el-table-column prop="username" label="账号"/>
            <el-table-column prop="nickName" label="姓名"/>
            <el-table-column prop="email" label="邮箱"/>
            <el-table-column label="添加时间">
                <template v-slot:default="scope">
                    {{ formateDate(scope.row.createTime) }}
                </template>
            </el-table-column>
            <el-table-column label="最后登录">
                <template v-slot:default="scope">
                    {{ formateDate(scope.row.loginTime) }}
                </template>
            </el-table-column>
            <el-table-column label="是否启用">
                <template v-slot:default="scope">
                    <el-switch v-model="scope.row.status" :active-value="1" :inactive-value="0"></el-switch>
                </template>
            </el-table-column>
            <el-table-column label="操作">
                <template #default="{row}">
                    <el-button type="text" @click="allocRole(row.id)">分配角色</el-button>
                    <el-button type="text" @click="editAdmin(row)">编辑</el-button>
                </template>
            </el-table-column>
        </el-table>
        <!-- 编辑 -->
        <EditAdmin v-model:visible="visible" :form="rowData" @sure="getTableData"></EditAdmin>
        <!-- 分配权限 -->
        <EditRole v-model:visible="roleVisible" :form="roleData" @sure="getTableData"></EditRole>
    </div>
</template>

<script lang='ts' setup>
import { reactive, toRefs } from 'vue'
import { getAdminListApi, getRoleListAll, getAdminRoleById } from '@/api/ums'
import { ElMessage } from 'element-plus'
import EditAdmin from './components/EditAdmin.vue'
import EditRole from './components/EditRole.vue'

const state = reactive<{
    tableData: {}[]
    visible: boolean,
    rowData: AdminObjItf
    roleVisible: boolean
    roleData: AdminRoleFormData
}>({
    tableData: [],
    visible: false,
    rowData: {},
    roleVisible: false,
    roleData: {
        userRoles: [],
        roleLists: [],
        adminId: 0
    }
})

let { tableData, visible, rowData, roleVisible, roleData } = toRefs(state)
const getTableData = () => {
    getAdminListApi({
        keyword: '',
        pageNum: 1,
        pageSize: 10
    }).then((res) => {
        if(res.code === 200) {
            tableData.value = res.data.list
        } else {
            ElMessage.error('获取用户数据列表失败')
        }
    })
}
getTableData();

// 获取所有角色
getRoleListAll().then((res) => {
    if(res.code === 200) {
        roleData.value.roleLists = res.data
    } else {
        ElMessage.error('获取所有角色失败')
    }
})

const addZero = (num: number) => {
    return num > 9 ? num : '0' + num
}

// 格式化时间
const formateDate = (time: string | undefined) => {
    if (!time) return '';
    const date = new Date(time);
    const year = date.getFullYear();
    let month = addZero(date.getMonth() + 1);
    let day = addZero(date.getDate());
    let hour = addZero(date.getHours());
    let min = addZero(date.getMinutes());
    let sec = addZero(date.getSeconds());
    return  `${year}-${month}-${day} ${hour}:${min}:${sec}`
}

// 点击编辑按钮
const editAdmin = (row: AdminObjItf) => {
    visible.value = true
    rowData.value = row
}
// 点击分配权限按钮
const allocRole = (id: number) => {
    getAdminRoleById(id).then(res => {
        if(res.code === 200) {
            roleVisible.value = true
            roleData.value.adminId = id
            roleData.value.userRoles = res.data
        }
    })
}

</script>

<style lang='less' scoped>

</style>
<template>
    <el-dialog v-model="dialogVisible" title="分配角色" width="420" :before-close="close">
        <el-form :model="form" label-width="70px">
            <el-form-item label="权限">
                <el-select v-model="roles" multiple>
                    <el-option v-for="role in form.roleLists" :label="role.name" :value="role.id"></el-option>
                </el-select>
            </el-form-item>
        </el-form>
        <template #footer>
            <div class="dialog-footer">
                <el-button @click="close">取消</el-button>
                <el-button type="primary" @click="modifyRole">确定</el-button>
            </div>
        </template>
    </el-dialog>
</template>

<script lang='ts' setup>
import { computed, reactive, toRefs, watch } from 'vue'
import { updateAdminRole } from '@/api/ums'
import { ElMessage } from 'element-plus'

const props = defineProps<{
    visible: boolean,
    form: AdminRoleFormData
}>()

const state = reactive<{
    roles: number[]
}>({
    roles: []
})

const { roles } = toRefs(state)
// 拷贝form
watch(() => props.form.userRoles, () => {
    roles.value = props.form.userRoles?.map(el => el.id) || []
})

const emit = defineEmits<{
    (event: 'update:visible', value: boolean): void
    (event: 'sure'): void
}>()

// 双向绑定 dialog 显示状态(emit 更新父组件)
const dialogVisible = computed({
    get: () => props.visible,
    set: (val: boolean) => emit('update:visible', val)
})
// 点击关闭
const close = () => {
    dialogVisible.value = false
}
// 确定
const modifyRole = () => {
    updateAdminRole({
        adminId: props.form.adminId,
        roleIds: roles.value
    }).then((res) => {
        if(res.code === 200) {
            close()
            emit('sure')
            ElMessage.success('修改用户角色成功')
        } else {
            ElMessage.error('修改用户角色失败')
        }
    })
}

</script>

<style lang='less' scoped>

</style>
<!-- 添加用户--> <el-dialog :title="title" v-model="openAddUser" width="90%" append-to-body fullscreen> <el-form :model="queryEmp" ref="queryDetRef" :inline="true" label-width="150px"> <el-form-item label="用户" prop="EMP_NAME_"> <el-input v-model="queryEmp.EMP_NAME_" placeholder="请输入用户名称" clearable style="width: 240px" @keyup.enter="handleQueryEmp" /> </el-form-item> <el-form-item> <el-button type="primary" icon="Search" @click="handleQueryEmp">搜索</el-button> <el-button icon="Refresh" @click="resetQueryDet">重置</el-button> </el-form-item> </el-form> <!-- 使用 el-row 和 el-col 实现左右布局 --> <el-row :gutter="20"> <!-- 左侧表格 --> <el-col :span="12"> <el-card> <el-table v-loading="loading" :data="empListLeft"> <el-table-column type="selection" width="50" align="center"/> <el-table-column label="用户编号" align="center" key="EMP_ID_" prop="EMP_CODE_"/> <el-table-column label="用户名称" align="center" key="userName" prop="EMP_NAME_"/> <el-table-column label="机构名称" align="center" key="ORG_NAME_" prop="ORG_NAME_"/> <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <template #default="scope"> <el-button link type="primary" @click="handleAddEmp(scope.row)">添加</el-button> </template> </el-table-column> </el-table> </el-card> </el-col> <!-- 右侧表格 --> <el-col :span="12"> <el-card> <el-table v-loading="loading" :data="empListRight"> <el-table-column type="selection" width="50" align="center"/> <el-table-column label="用户编号" align="center" key="EMP_ID_" prop="EMP_CODE_"/> <el-table-column label="用户名称" align="center" key="
03-11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凯小默

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值