This commit is contained in:
@@ -4,7 +4,9 @@
|
||||
<ElCard shadow="never">
|
||||
<div class="detail-header">
|
||||
<ElButton @click="handleBack">
|
||||
<template #icon><ElIcon><ArrowLeft /></ElIcon></template>
|
||||
<template #icon
|
||||
><ElIcon><ArrowLeft /></ElIcon
|
||||
></template>
|
||||
返回
|
||||
</ElButton>
|
||||
<h2 class="detail-title">{{ pageTitle }}</h2>
|
||||
@@ -19,6 +21,13 @@
|
||||
@search="handleSearch"
|
||||
></ArtSearchBar>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<div style="margin: 10px 0">
|
||||
<ElButton @click="showAddAccountDialog">
|
||||
{{ isShopType ? '新增店铺账号' : '新增企业账号' }}
|
||||
</ElButton>
|
||||
</div>
|
||||
|
||||
<!-- 表格 -->
|
||||
<ArtTable
|
||||
ref="tableRef"
|
||||
@@ -28,28 +37,176 @@
|
||||
:currentPage="pagination.page"
|
||||
:pageSize="pagination.pageSize"
|
||||
:total="pagination.total"
|
||||
:marginTop="10"v
|
||||
:marginTop="10"
|
||||
v
|
||||
height="60vh"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
>
|
||||
<template #default>
|
||||
<ElTableColumn v-for="col in columns" :key="col.prop || (col as any).type" v-bind="col" />
|
||||
<ElTableColumn
|
||||
v-for="col in columns"
|
||||
:key="col.prop || (col as any).type"
|
||||
v-bind="col"
|
||||
/>
|
||||
</template>
|
||||
</ArtTable>
|
||||
|
||||
<!-- 新增账号对话框 -->
|
||||
<ElDialog
|
||||
v-model="dialogVisible"
|
||||
:title="isShopType ? '新增店铺账号' : '新增企业账号'"
|
||||
width="500px"
|
||||
>
|
||||
<ElForm ref="formRef" :model="accountForm" :rules="accountRules" label-width="100px">
|
||||
<ElFormItem label="用户名" prop="username">
|
||||
<ElInput v-model="accountForm.username" placeholder="请输入用户名" />
|
||||
</ElFormItem>
|
||||
<ElFormItem label="密码" prop="password">
|
||||
<ElInput
|
||||
v-model="accountForm.password"
|
||||
type="password"
|
||||
placeholder="请输入密码"
|
||||
show-password
|
||||
/>
|
||||
</ElFormItem>
|
||||
<ElFormItem label="手机号" prop="phone">
|
||||
<ElInput v-model="accountForm.phone" placeholder="请输入手机号" maxlength="11" />
|
||||
</ElFormItem>
|
||||
<ElFormItem label="账号类型" prop="user_type">
|
||||
<ElInput :value="isShopType ? '代理账号' : '企业账号'" disabled />
|
||||
</ElFormItem>
|
||||
</ElForm>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<ElButton @click="dialogVisible = false">取消</ElButton>
|
||||
<ElButton type="primary" @click="handleSubmit" :loading="submitLoading">
|
||||
提交
|
||||
</ElButton>
|
||||
</div>
|
||||
</template>
|
||||
</ElDialog>
|
||||
|
||||
<!-- 分配角色对话框 -->
|
||||
<ElDialog v-model="roleDialogVisible" width="900px">
|
||||
<template #header>
|
||||
<div class="dialog-header">
|
||||
<span class="dialog-title">分配角色</span>
|
||||
<div class="account-info">
|
||||
<span class="account-name">{{ currentAccountName }}</span>
|
||||
<ElTag v-if="currentAccountType === 3" type="warning" size="small" style="margin-left: 8px">
|
||||
代理账号只能分配一个客户角色
|
||||
</ElTag>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="role-transfer-container">
|
||||
<!-- 左侧:可分配角色列表 -->
|
||||
<div class="transfer-panel">
|
||||
<div class="panel-header">
|
||||
<span class="panel-title">可分配角色</span>
|
||||
<ElInput
|
||||
v-model="leftRoleFilter"
|
||||
placeholder="搜索角色"
|
||||
clearable
|
||||
size="small"
|
||||
style="width: 180px"
|
||||
/>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<ElCheckboxGroup v-model="rolesToAdd" class="role-list">
|
||||
<div v-for="role in filteredAvailableRoles" :key="role.ID" class="role-item">
|
||||
<ElCheckbox :label="role.ID" :disabled="selectedRoles.includes(role.ID)">
|
||||
<span class="role-info">
|
||||
<span>{{ role.role_name }}</span>
|
||||
<ElTag :type="role.role_type === 1 ? 'primary' : 'success'" size="small">
|
||||
{{ role.role_type === 1 ? '平台角色' : '客户角色' }}
|
||||
</ElTag>
|
||||
</span>
|
||||
</ElCheckbox>
|
||||
</div>
|
||||
</ElCheckboxGroup>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 中间:操作按钮 -->
|
||||
<div class="transfer-buttons">
|
||||
<ElButton
|
||||
type="primary"
|
||||
:icon="'ArrowRight'"
|
||||
@click="addRoles"
|
||||
:disabled="rolesToAdd.length === 0"
|
||||
>
|
||||
添加
|
||||
</ElButton>
|
||||
</div>
|
||||
|
||||
<!-- 右侧:已分配角色列表 -->
|
||||
<div class="transfer-panel">
|
||||
<div class="panel-header">
|
||||
<span class="panel-title">已分配角色</span>
|
||||
<ElInput
|
||||
v-model="rightRoleFilter"
|
||||
placeholder="搜索角色"
|
||||
clearable
|
||||
size="small"
|
||||
style="width: 180px"
|
||||
/>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="role-list">
|
||||
<div
|
||||
v-for="role in filteredAssignedRoles"
|
||||
:key="role.ID"
|
||||
class="role-item assigned-role-item"
|
||||
>
|
||||
<span class="role-info">
|
||||
<span>{{ role.role_name }}</span>
|
||||
<ElTag :type="role.role_type === 1 ? 'primary' : 'success'" size="small">
|
||||
{{ role.role_type === 1 ? '平台角色' : '客户角色' }}
|
||||
</ElTag>
|
||||
</span>
|
||||
<ElButton type="danger" size="small" link @click="removeSingleRole(role.ID)">
|
||||
移除
|
||||
</ElButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<ElButton @click="roleDialogVisible = false">关闭</ElButton>
|
||||
</div>
|
||||
</template>
|
||||
</ElDialog>
|
||||
</ElCard>
|
||||
</div>
|
||||
</ArtTableFullScreen>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { h, computed, ref, reactive, onMounted } from 'vue'
|
||||
import { h, computed, ref, reactive, onMounted, nextTick } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { ElMessage, ElTag, ElIcon, ElButton, ElCard } from 'element-plus'
|
||||
import {
|
||||
ElMessage,
|
||||
ElTag,
|
||||
ElIcon,
|
||||
ElButton,
|
||||
ElCard,
|
||||
ElDialog,
|
||||
ElForm,
|
||||
ElFormItem,
|
||||
ElInput,
|
||||
ElCheckbox,
|
||||
ElCheckboxGroup
|
||||
} from 'element-plus'
|
||||
import { ArrowLeft } from '@element-plus/icons-vue'
|
||||
import { AccountService } from '@/api/modules'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
import { AccountService, RoleService } from '@/api/modules'
|
||||
import ArtButtonTable from '@/components/core/forms/ArtButtonTable.vue'
|
||||
import type { SearchFormItem } from '@/types'
|
||||
import type { PlatformAccount } from '@/types/api'
|
||||
import type { PlatformAccount, PlatformRole } from '@/types/api'
|
||||
import { formatDateTime } from '@/utils/business/format'
|
||||
|
||||
defineOptions({ name: 'CommonAccountList' })
|
||||
@@ -86,6 +243,17 @@
|
||||
const tableRef = ref()
|
||||
const accountList = ref<PlatformAccount[]>([])
|
||||
|
||||
// 分配角色相关变量
|
||||
const roleDialogVisible = ref(false)
|
||||
const currentAccountId = ref<number>(0)
|
||||
const currentAccountName = ref<string>('')
|
||||
const currentAccountType = ref<number>(0)
|
||||
const selectedRoles = ref<number[]>([])
|
||||
const allRoles = ref<PlatformRole[]>([])
|
||||
const rolesToAdd = ref<number[]>([])
|
||||
const leftRoleFilter = ref('')
|
||||
const rightRoleFilter = ref('')
|
||||
|
||||
// 搜索表单初始值
|
||||
const initialSearchState = {
|
||||
username: '',
|
||||
@@ -124,19 +292,6 @@
|
||||
placeholder: '请输入手机号'
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '用户类型',
|
||||
prop: 'user_type',
|
||||
type: 'select',
|
||||
config: {
|
||||
clearable: true,
|
||||
placeholder: '全部'
|
||||
},
|
||||
options: () => [
|
||||
{ label: '代理账号', value: 3 },
|
||||
{ label: '企业账号', value: 4 }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '状态',
|
||||
prop: 'status',
|
||||
@@ -163,52 +318,74 @@
|
||||
}
|
||||
|
||||
// 列配置
|
||||
const columns = computed(() => [
|
||||
{
|
||||
prop: 'username',
|
||||
label: '用户名',
|
||||
minWidth: 150
|
||||
},
|
||||
{
|
||||
prop: 'phone',
|
||||
label: '手机号',
|
||||
width: 130
|
||||
},
|
||||
{
|
||||
prop: 'user_type',
|
||||
label: '用户类型',
|
||||
width: 110,
|
||||
formatter: (row: PlatformAccount) => {
|
||||
return h(ElTag, { type: getUserTypeTag(row.user_type) }, () => getUserTypeName(row.user_type))
|
||||
const columns = computed(() => {
|
||||
const baseColumns = [
|
||||
{
|
||||
prop: 'username',
|
||||
label: '用户名'
|
||||
},
|
||||
{
|
||||
prop: 'phone',
|
||||
label: '手机号'
|
||||
},
|
||||
{
|
||||
prop: 'user_type',
|
||||
label: '用户类型',
|
||||
formatter: (row: PlatformAccount) => {
|
||||
return h(ElTag, { type: getUserTypeTag(row.user_type) }, () =>
|
||||
getUserTypeName(row.user_type)
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'shop_id',
|
||||
label: '店铺ID',
|
||||
width: 100,
|
||||
formatter: (row: PlatformAccount) => row.shop_id || '-'
|
||||
},
|
||||
{
|
||||
prop: 'enterprise_id',
|
||||
label: '企业ID',
|
||||
width: 100,
|
||||
formatter: (row: PlatformAccount) => row.enterprise_id || '-'
|
||||
},
|
||||
{
|
||||
prop: 'status',
|
||||
label: '状态',
|
||||
width: 100,
|
||||
formatter: (row: PlatformAccount) => {
|
||||
return h(ElTag, { type: getStatusTag(row.status) }, () => getStatusName(row.status))
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'CreatedAt',
|
||||
label: '创建时间',
|
||||
width: 180,
|
||||
formatter: (row: PlatformAccount) => formatDateTime(row.CreatedAt)
|
||||
]
|
||||
|
||||
// 根据页面类型添加不同的列
|
||||
if (isShopType.value) {
|
||||
// 店铺类型:显示店铺名称
|
||||
baseColumns.push({
|
||||
prop: 'shop_name',
|
||||
label: '店铺名称',
|
||||
formatter: (row: PlatformAccount) => (row as any).shop_name || '-'
|
||||
})
|
||||
} else {
|
||||
// 企业类型:显示企业名称
|
||||
baseColumns.push({
|
||||
prop: 'enterprise_name',
|
||||
label: '企业名称',
|
||||
formatter: (row: PlatformAccount) => (row as any).enterprise_name || '-'
|
||||
})
|
||||
}
|
||||
])
|
||||
|
||||
// 添加状态和创建时间
|
||||
baseColumns.push(
|
||||
{
|
||||
prop: 'status',
|
||||
label: '状态',
|
||||
formatter: (row: PlatformAccount) => {
|
||||
return h(ElTag, { type: getStatusTag(row.status) }, () => getStatusName(row.status))
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'created_at',
|
||||
label: '创建时间',
|
||||
formatter: (row: PlatformAccount) => formatDateTime((row as any).created_at)
|
||||
},
|
||||
{
|
||||
prop: 'operation',
|
||||
label: '操作',
|
||||
width: 120,
|
||||
fixed: 'right',
|
||||
formatter: (row: PlatformAccount) => {
|
||||
return h(ArtButtonTable, {
|
||||
text: '分配角色',
|
||||
onClick: () => showRoleDialog(row)
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
return baseColumns
|
||||
})
|
||||
|
||||
// 获取账号列表
|
||||
const getTableData = async () => {
|
||||
@@ -220,7 +397,7 @@
|
||||
pageSize: pagination.pageSize,
|
||||
username: searchForm.username || undefined,
|
||||
phone: searchForm.phone || undefined,
|
||||
user_type: searchForm.user_type,
|
||||
user_type: isShopType.value ? 3 : 4, // 根据页面类型自动设置: 3:代理账号, 4:企业账号
|
||||
status: searchForm.status,
|
||||
[filterParamKey.value]: entityId // 动态设置 shop_id 或 enterprise_id
|
||||
}
|
||||
@@ -274,8 +451,214 @@
|
||||
router.back()
|
||||
}
|
||||
|
||||
// 对话框相关
|
||||
const dialogVisible = ref(false)
|
||||
const submitLoading = ref(false)
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
// 账号表单数据
|
||||
const accountForm = reactive({
|
||||
username: '',
|
||||
password: '',
|
||||
phone: ''
|
||||
})
|
||||
|
||||
// 表单验证规则
|
||||
const accountRules = reactive<FormRules>({
|
||||
username: [
|
||||
{ required: true, message: '请输入用户名', trigger: 'blur' },
|
||||
{ min: 2, max: 50, message: '长度在 2 到 50 个字符', trigger: 'blur' }
|
||||
],
|
||||
password: [
|
||||
{ required: true, message: '请输入密码', trigger: 'blur' },
|
||||
{ min: 6, max: 20, message: '密码长度为 6-20 个字符', trigger: 'blur' }
|
||||
],
|
||||
phone: [
|
||||
{ required: true, message: '请输入手机号', trigger: 'blur' },
|
||||
{ len: 11, message: '手机号必须为 11 位', trigger: 'blur' },
|
||||
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号格式', trigger: 'blur' }
|
||||
]
|
||||
})
|
||||
|
||||
// 显示新增账号对话框
|
||||
const showAddAccountDialog = () => {
|
||||
// 重置表单
|
||||
accountForm.username = ''
|
||||
accountForm.password = ''
|
||||
accountForm.phone = ''
|
||||
|
||||
// 重置表单验证状态
|
||||
nextTick(() => {
|
||||
formRef.value?.clearValidate()
|
||||
})
|
||||
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
const handleSubmit = async () => {
|
||||
if (!formRef.value) return
|
||||
|
||||
await formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
submitLoading.value = true
|
||||
try {
|
||||
const entityId = Number(route.params.id)
|
||||
const data: any = {
|
||||
username: accountForm.username,
|
||||
password: accountForm.password,
|
||||
phone: accountForm.phone,
|
||||
user_type: isShopType.value ? 3 : 4 // 3:代理账号, 4:企业账号
|
||||
}
|
||||
|
||||
// 根据类型添加关联ID
|
||||
if (isShopType.value) {
|
||||
data.shop_id = entityId
|
||||
} else {
|
||||
data.enterprise_id = entityId
|
||||
}
|
||||
|
||||
await AccountService.createAccount(data)
|
||||
ElMessage.success('添加账号成功')
|
||||
dialogVisible.value = false
|
||||
|
||||
// 刷新列表
|
||||
getTableData()
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
ElMessage.error('添加账号失败')
|
||||
} finally {
|
||||
submitLoading.value = false
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 加载所有角色列表
|
||||
const loadAllRoles = async () => {
|
||||
try {
|
||||
const res = await RoleService.getRoles({ page: 1, pageSize: 100 })
|
||||
if (res.code === 0) {
|
||||
allRoles.value = res.data.items || []
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取角色列表失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 计算属性:过滤后的可分配角色(根据账号类型过滤)
|
||||
const filteredAvailableRoles = computed(() => {
|
||||
let roles = allRoles.value
|
||||
|
||||
// 根据账号类型过滤角色
|
||||
if (currentAccountType.value === 3) {
|
||||
// 代理账号:只显示客户角色
|
||||
roles = roles.filter((role) => role.role_type === 2)
|
||||
} else if (currentAccountType.value === 2) {
|
||||
// 平台用户:只显示平台角色
|
||||
roles = roles.filter((role) => role.role_type === 1)
|
||||
} else if (currentAccountType.value === 4) {
|
||||
// 企业账号:只显示客户角色
|
||||
roles = roles.filter((role) => role.role_type === 2)
|
||||
}
|
||||
|
||||
// 根据搜索关键词过滤
|
||||
if (!leftRoleFilter.value) return roles
|
||||
const keyword = leftRoleFilter.value.toLowerCase()
|
||||
return roles.filter((role) => role.role_name.toLowerCase().includes(keyword))
|
||||
})
|
||||
|
||||
// 计算属性:过滤后的已分配角色
|
||||
const filteredAssignedRoles = computed(() => {
|
||||
const assignedRolesList = allRoles.value.filter((role) => selectedRoles.value.includes(role.ID))
|
||||
if (!rightRoleFilter.value) return assignedRolesList
|
||||
const keyword = rightRoleFilter.value.toLowerCase()
|
||||
return assignedRolesList.filter((role) => role.role_name.toLowerCase().includes(keyword))
|
||||
})
|
||||
|
||||
// 显示分配角色对话框
|
||||
const showRoleDialog = async (row: PlatformAccount) => {
|
||||
currentAccountId.value = (row as any).id
|
||||
currentAccountName.value = row.username
|
||||
currentAccountType.value = row.user_type
|
||||
selectedRoles.value = []
|
||||
rolesToAdd.value = []
|
||||
leftRoleFilter.value = ''
|
||||
rightRoleFilter.value = ''
|
||||
|
||||
try {
|
||||
// 每次打开对话框时重新加载最新的角色列表
|
||||
await loadAllRoles()
|
||||
|
||||
// 先加载当前账号的角色,再打开对话框
|
||||
const res = await AccountService.getAccountRoles((row as any).id)
|
||||
if (res.code === 0) {
|
||||
// 提取角色ID数组
|
||||
const roles = res.data || []
|
||||
// 兼容 ID 和 id 两种字段名
|
||||
selectedRoles.value = roles.map((role: any) => role.ID || role.id)
|
||||
// 数据加载完成后再打开对话框
|
||||
roleDialogVisible.value = true
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取账号角色失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 批量添加角色
|
||||
const addRoles = async () => {
|
||||
if (rolesToAdd.value.length === 0) return
|
||||
|
||||
try {
|
||||
let newRoles: number[]
|
||||
|
||||
// 代理账号只能分配一个角色,会覆盖之前的角色
|
||||
if (currentAccountType.value === 3) {
|
||||
if (rolesToAdd.value.length > 1) {
|
||||
ElMessage.warning('代理账号只能分配一个角色')
|
||||
return
|
||||
}
|
||||
// 只保留新选择的一个角色
|
||||
newRoles = rolesToAdd.value
|
||||
} else {
|
||||
// 其他账号类型可以分配多个角色
|
||||
newRoles = [...new Set([...selectedRoles.value, ...rolesToAdd.value])]
|
||||
}
|
||||
|
||||
await AccountService.assignRolesToAccount(currentAccountId.value, newRoles)
|
||||
|
||||
selectedRoles.value = newRoles
|
||||
rolesToAdd.value = []
|
||||
|
||||
ElMessage.success('角色分配成功')
|
||||
// 刷新列表以更新角色显示
|
||||
await getTableData()
|
||||
} catch (error) {
|
||||
console.error('分配角色失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 移除单个角色
|
||||
const removeSingleRole = async (roleId: number) => {
|
||||
try {
|
||||
// 从已分配列表中移除该角色
|
||||
const newRoles = selectedRoles.value.filter((id) => id !== roleId)
|
||||
await AccountService.assignRolesToAccount(currentAccountId.value, newRoles)
|
||||
|
||||
selectedRoles.value = newRoles
|
||||
|
||||
ElMessage.success('角色移除成功')
|
||||
// 刷新列表以更新角色显示
|
||||
await getTableData()
|
||||
} catch (error) {
|
||||
console.error('移除角色失败:', error)
|
||||
ElMessage.error('角色移除失败')
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getTableData()
|
||||
loadAllRoles()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -285,9 +668,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
margin-bottom: 24px;
|
||||
padding-bottom: 16px;
|
||||
border-bottom: 1px solid #e4e7ed;
|
||||
|
||||
.detail-title {
|
||||
margin: 0;
|
||||
@@ -297,4 +678,128 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dialog-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
|
||||
.dialog-title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.account-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
|
||||
.account-name {
|
||||
font-size: 14px;
|
||||
color: var(--el-text-color-regular);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.role-transfer-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: stretch;
|
||||
gap: 20px;
|
||||
padding: 20px 0;
|
||||
min-height: 500px;
|
||||
|
||||
.transfer-panel {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: 1px solid var(--el-border-color);
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
max-width: 380px;
|
||||
|
||||
.panel-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px 16px;
|
||||
background: var(--el-fill-color-light);
|
||||
border-bottom: 1px solid var(--el-border-color);
|
||||
|
||||
.panel-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.panel-body {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 12px;
|
||||
|
||||
.role-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
|
||||
.role-item {
|
||||
padding: 10px 12px;
|
||||
border: 1px solid var(--el-border-color-lighter);
|
||||
border-radius: 4px;
|
||||
transition: all 0.2s;
|
||||
|
||||
&:hover {
|
||||
background: var(--el-fill-color-light);
|
||||
border-color: var(--el-border-color);
|
||||
}
|
||||
|
||||
.role-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
:deep(.el-checkbox) {
|
||||
width: 100%;
|
||||
|
||||
.el-checkbox__label {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.assigned-role-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
|
||||
.role-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.el-button {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.transfer-buttons {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 0 10px;
|
||||
|
||||
.el-button {
|
||||
width: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user