Files
RCZN-bs-program/rc_autoplc_front/src/views/user-role/index.vue
2025-12-23 14:02:53 +08:00

528 lines
14 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="user-role-page">
<el-card class="search-card" shadow="never">
<div class="search-bar">
<el-form :inline="true" :model="queryForm" label-width="80px">
<el-form-item label="用户">
<el-select
v-model="queryForm.userId"
filterable
clearable
placeholder="请选择用户"
style="width: 200px"
>
<el-option
v-for="item in userOptions"
:key="item.id"
:label="item.userName || item.nicke || item.nickName"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="角色">
<el-select
v-model="queryForm.roleId"
filterable
clearable
placeholder="请选择角色"
style="width: 200px"
>
<el-option
v-for="item in roleOptions"
:key="item.id"
:label="item.roleName || item.roleCode"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch">查询</el-button>
<el-button @click="resetSearch">重置</el-button>
</el-form-item>
</el-form>
<div class="toolbar">
<el-button type="primary" @click="openDrawer('create')">新增用户角色关联</el-button>
</div>
</div>
</el-card>
<el-card shadow="never">
<el-table
:data="tableData"
stripe
border
style="width: 100%"
v-loading="loading"
>
<el-table-column type="index" label="序号" width="70" />
<el-table-column
prop="userId"
label="用户名"
min-width="150"
>
<template #default="scope">
{{ getUserName(scope.row.userId) }}
</template>
</el-table-column>
<el-table-column
prop="roleId"
label="角色名"
min-width="150"
>
<template #default="scope">
{{ getRoleName(scope.row.roleId) }}
</template>
</el-table-column>
<el-table-column
prop="remark"
label="备注"
min-width="200"
:formatter="formatCell"
/>
<el-table-column label="操作" width="120" fixed="right">
<template #default="scope">
<el-button type="danger" link @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination
v-model:current-page="pagination.pageNum"
v-model:page-size="pagination.pageSize"
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
background
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
/>
</div>
</el-card>
<el-drawer
v-model="drawerVisible"
title="新增用户角色关联"
direction="rtl"
:size="500"
>
<el-form
ref="formRef"
:model="form"
:rules="rules"
label-width="100px"
class="drawer-form"
>
<el-form-item label="用户" prop="userId">
<el-select
v-model="form.userId"
filterable
clearable
placeholder="请选择用户"
style="width: 100%"
>
<el-option
v-for="item in userOptions"
:key="item.id"
:label="item.userName || item.nicke || item.nickName"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="角色" prop="roleId">
<el-select
v-model="form.roleId"
filterable
clearable
placeholder="请选择角色"
style="width: 100%"
>
<el-option
v-for="item in roleOptions"
:key="item.id"
:label="item.roleName || item.roleCode"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="备注">
<el-input
v-model="form.remark"
type="textarea"
placeholder="请输入备注"
:rows="3"
maxlength="200"
show-word-limit
/>
</el-form-item>
</el-form>
<template #footer>
<div class="drawer-footer">
<el-button @click="drawerVisible = false">取消</el-button>
<el-button type="primary" :loading="submitLoading" @click="submitForm">
保存
</el-button>
</div>
</template>
</el-drawer>
</div>
</template>
<script setup lang="ts">
import { onMounted, reactive, ref } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus'
import { userRoleAdd, userRoleDel, userRoleList, userRoleByUserId } from '@/api/system/user-role'
import { userselect } from '@/api/system/user'
import { rleselect } from '@/api/system/role'
interface UserRoleItem {
id?: number | string
userId: number | string
roleId: number | string
remark?: string
}
interface UserItem {
id: number | string
userName?: string
nicke?: string
nickName?: string
}
interface RoleItem {
id: number | string
roleName?: string
roleCode?: string
}
const loading = ref(false)
const submitLoading = ref(false)
const tableData = ref<UserRoleItem[]>([])
const total = ref(0)
const userOptions = ref<UserItem[]>([])
const roleOptions = ref<RoleItem[]>([])
const userMap = ref<Map<number | string, string>>(new Map())
const roleMap = ref<Map<number | string, string>>(new Map())
const queryForm = reactive({
userId: null as number | string | null,
roleId: null as number | string | null,
})
const pagination = reactive({
pageNum: 1,
pageSize: 10,
})
const drawerVisible = ref(false)
const formRef = ref<FormInstance>()
const form = reactive<UserRoleItem>({
userId: '',
roleId: '',
remark: '',
})
const rules: FormRules = {
userId: [{ required: true, message: '请选择用户', trigger: 'change' }],
roleId: [{ required: true, message: '请选择角色', trigger: 'change' }],
}
const resetForm = () => {
form.userId = ''
form.roleId = ''
form.remark = ''
formRef.value?.clearValidate()
}
const formatCell = (_row: any, _column: any, value: any) => {
if (value === 0) return 0
return value === undefined || value === null || value === '' ? '暂无' : value
}
// 获取用户名
const getUserName = (userId: number | string | null | undefined) => {
if (!userId) return '暂无'
return userMap.value.get(userId) || '暂无'
}
// 获取角色名
const getRoleName = (roleId: number | string | null | undefined) => {
if (!roleId) return '暂无'
return roleMap.value.get(roleId) || '暂无'
}
// 加载用户列表
const loadUsers = async () => {
try {
const res: any = await userselect({})
const data = Array.isArray(res?.data) ? res.data : Array.isArray(res) ? res : []
userOptions.value = data
userMap.value.clear()
data.forEach((user: UserItem) => {
if (user.id) {
const userName = user.userName || user.nicke || user.nickName || ''
userMap.value.set(user.id, userName)
}
})
} catch (error) {
console.error('load user list error', error)
ElMessage.error('加载用户列表失败')
userOptions.value = []
}
}
// 加载角色列表
const loadRoles = async () => {
try {
const res: any = await rleselect({})
const data = Array.isArray(res?.data) ? res.data : Array.isArray(res) ? res : []
roleOptions.value = data
roleMap.value.clear()
data.forEach((role: RoleItem) => {
if (role.id) {
const roleName = role.roleName || role.roleCode || ''
roleMap.value.set(role.id, roleName)
}
})
} catch (error) {
console.error('load role list error', error)
ElMessage.error('加载角色列表失败')
roleOptions.value = []
}
}
// 加载用户角色关联列表
const loadList = async () => {
loading.value = true
try {
// 确保用户和角色列表已加载
if (userOptions.value.length === 0) {
await loadUsers()
}
if (roleOptions.value.length === 0) {
await loadRoles()
}
const params: any = {
pageNum: pagination.pageNum,
pageSize: pagination.pageSize,
}
if (queryForm.userId) {
params.userId = queryForm.userId
}
if (queryForm.roleId) {
params.roleId = queryForm.roleId
}
const res: any = await userRoleList(params)
console.log('用户角色关联列表API返回数据:', res)
let pageData = res?.data
if (!pageData && (res?.records || res?.total !== undefined)) {
pageData = res
}
const recordsFromData =
pageData?.records ||
pageData?.list ||
pageData?.rows ||
pageData?.items ||
(Array.isArray(pageData?.data) ? pageData.data : undefined)
const records = Array.isArray(recordsFromData)
? recordsFromData
: Array.isArray(pageData)
? pageData
: Array.isArray(res?.data)
? res.data
: []
const totalValue =
pageData?.total ??
pageData?.count ??
pageData?.totalCount ??
res?.total ??
(Array.isArray(records) ? records.length : 0)
tableData.value = records
total.value = Number(totalValue) || 0
console.log('解析后的数据:', {
records: records.length,
total: total.value,
firstRecord: records[0],
})
} catch (error: any) {
console.error('load user role list error', error)
const errorMsg = error?.message || error?.msg || '加载用户角色关联列表失败'
ElMessage.error(errorMsg)
tableData.value = []
total.value = 0
} finally {
loading.value = false
}
}
const handleSearch = () => {
pagination.pageNum = 1
loadList()
}
const resetSearch = () => {
queryForm.userId = null
queryForm.roleId = null
handleSearch()
}
const handleSizeChange = (size: number) => {
pagination.pageSize = size
loadList()
}
const handleCurrentChange = (page: number) => {
pagination.pageNum = page
loadList()
}
const openDrawer = async (mode: 'create') => {
resetForm()
drawerVisible.value = true
// 加载用户和角色数据
await Promise.all([loadUsers(), loadRoles()])
}
const submitForm = () => {
formRef.value?.validate(async (valid) => {
if (!valid) return
// 检查用户是否已拥有该角色
try {
const res: any = await userRoleByUserId(form.userId)
const data = res?.data ?? res ?? {}
// 兼容多种返回格式
const userRoles = Array.isArray(data)
? data
: Array.isArray(data.data)
? data.data
: Array.isArray(data.records)
? data.records
: Array.isArray(data.list)
? data.list
: []
// 检查是否已存在该角色关联
const existingRole = userRoles.find((item: any) => item.roleId === form.roleId)
if (existingRole) {
// 获取用户名和角色名
const userName = getUserName(form.userId)
const roleName = getRoleName(form.roleId)
ElMessage.warning(`用户【${userName}】已拥有【${roleName}】角色,无需重复分配`)
return
}
} catch (error: any) {
console.error('check user role error', error)
// 如果检查失败,继续执行新增操作,让后端处理重复情况
}
submitLoading.value = true
try {
const payload: any = {
userId: form.userId,
roleId: form.roleId,
remark: form.remark || '',
}
await userRoleAdd(payload)
ElMessage.success('新增成功')
drawerVisible.value = false
loadList()
} catch (error: any) {
console.error('submit user role error', error)
const errorMsg = error?.message || error?.msg || '新增失败'
ElMessage.error(errorMsg)
} finally {
submitLoading.value = false
}
})
}
const handleDelete = (row: UserRoleItem) => {
if (!row.id) {
ElMessage.warning('缺少关联ID')
return
}
const userName = getUserName(row.userId)
const roleName = getRoleName(row.roleId)
ElMessageBox.confirm(`确认删除用户「${userName}」与角色「${roleName}」的关联吗?`, '提示', {
type: 'warning',
})
.then(async () => {
if (row.id == null) {
ElMessage.warning('缺少关联ID无法删除')
return
}
try {
await userRoleDel(row.id)
ElMessage.success('删除成功')
loadList()
} catch (error: any) {
console.error('delete user role error', error)
const errorMsg = error?.message || error?.msg || '删除失败'
ElMessage.error(errorMsg)
}
})
.catch(() => {})
}
onMounted(() => {
loadUsers()
loadRoles()
loadList()
})
</script>
<style scoped>
.user-role-page {
display: flex;
flex-direction: column;
gap: 12px;
}
.search-card {
padding-bottom: 4px;
}
.search-bar {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 8px;
}
.toolbar {
display: flex;
align-items: center;
gap: 8px;
}
.pagination {
margin-top: 16px;
display: flex;
justify-content: flex-end;
}
.drawer-footer {
display: flex;
justify-content: flex-end;
gap: 10px;
}
</style>