324 lines
12 KiB
Vue
324 lines
12 KiB
Vue
<template>
|
|
<div class="role-manage p-16-24">
|
|
<h2 class="mb-16">{{ $t('views.role.title') }}</h2>
|
|
<el-card style="--el-card-padding: 0">
|
|
<div class="flex h-full">
|
|
<div class="role-left border-r">
|
|
<div class="p-24 pb-0">
|
|
<el-input
|
|
v-model="filterText"
|
|
:placeholder="$t('common.search')"
|
|
prefix-icon="Search"
|
|
clearable
|
|
/>
|
|
</div>
|
|
<div class="list-height-left">
|
|
<el-scrollbar v-loading="loading">
|
|
<div class="p-16">
|
|
<div class="color-secondary lighter ml-8 mb-8">
|
|
<span>{{ $t('views.role.internalRole') }}</span>
|
|
</div>
|
|
<common-list
|
|
:data="filterInternalRole"
|
|
@click="clickRole"
|
|
:default-active="currentRole?.id"
|
|
@mouseenter="mouseenter"
|
|
@mouseleave="mouseId = ''"
|
|
>
|
|
<template #default="{ row }">
|
|
<div class="flex-between">
|
|
<span class="mr-8">{{ row.role_name }}</span>
|
|
<div @click.stop v-show="mouseId === row.id">
|
|
<el-dropdown :teleported="false">
|
|
<el-button text>
|
|
<el-icon class="color-secondary">
|
|
<MoreFilled />
|
|
</el-icon>
|
|
</el-button>
|
|
<template #dropdown>
|
|
<el-dropdown-menu style="min-width: 80px">
|
|
<el-dropdown-item @click.stop="createOrUpdateRole(row)" class="p-8"
|
|
v-if="hasPermission(
|
|
new ComplexPermission(
|
|
[RoleConst.ADMIN],
|
|
[PermissionConst.ROLE_EDIT],
|
|
[],'OR'
|
|
),'OR'
|
|
)"
|
|
>
|
|
<el-icon><EditPen /></el-icon>
|
|
{{ $t('common.rename') }}
|
|
</el-dropdown-item>
|
|
<el-dropdown-item @click.stop="deleteRole(row)" class="border-t p-8"
|
|
v-if="hasPermission(
|
|
new ComplexPermission(
|
|
[RoleConst.ADMIN],
|
|
[PermissionConst.ROLE_DELETE],
|
|
[],'OR'
|
|
),'OR'
|
|
)"
|
|
>
|
|
<el-icon><Delete /></el-icon>
|
|
{{ $t('common.delete') }}
|
|
</el-dropdown-item>
|
|
</el-dropdown-menu>
|
|
</template>
|
|
</el-dropdown>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<template #empty>
|
|
<span></span>
|
|
</template>
|
|
</common-list>
|
|
|
|
<div class="ml-8 border-t flex-between mb-8" style="padding-top: 12px">
|
|
<span class="color-secondary lighter">{{ $t('views.role.customRole') }}</span>
|
|
<el-tooltip
|
|
effect="dark"
|
|
:content="`${$t('common.create')}${$t('views.role.customRole')}`"
|
|
placement="top"
|
|
>
|
|
<el-button
|
|
type="primary"
|
|
text
|
|
@click="createOrUpdateRole()"
|
|
v-hasPermission="
|
|
new ComplexPermission(
|
|
[RoleConst.ADMIN],
|
|
[PermissionConst.ROLE_CREATE],
|
|
[],
|
|
'OR',)"
|
|
>
|
|
<el-icon :size="18"><Plus /></el-icon>
|
|
</el-button>
|
|
</el-tooltip>
|
|
</div>
|
|
<common-list
|
|
:data="filterCustomRole"
|
|
@click="clickRole"
|
|
:default-active="currentRole?.id"
|
|
@mouseenter="mouseenter"
|
|
@mouseleave="mouseId = ''"
|
|
>
|
|
<template #default="{ row }">
|
|
<div class="flex-between">
|
|
<span>
|
|
{{ row.role_name }}
|
|
<span class="color-input-placeholder ml-4"
|
|
>({{ roleTypeMap[row.type as RoleTypeEnum] }})</span
|
|
>
|
|
</span>
|
|
<div @click.stop v-show="mouseId === row.id">
|
|
<el-dropdown :teleported="false">
|
|
<el-button text>
|
|
<el-icon class="color-secondary">
|
|
<MoreFilled />
|
|
</el-icon>
|
|
</el-button>
|
|
<template #dropdown>
|
|
<el-dropdown-menu style="min-width: 80px">
|
|
<el-dropdown-item @click.stop="createOrUpdateRole(row)" class="p-8"
|
|
v-if="hasPermission(
|
|
new ComplexPermission(
|
|
[RoleConst.ADMIN],
|
|
[PermissionConst.ROLE_EDIT],
|
|
[],'OR'
|
|
),'OR'
|
|
)"
|
|
>
|
|
<el-icon><EditPen /></el-icon>
|
|
{{ $t('common.rename') }}
|
|
</el-dropdown-item>
|
|
<el-dropdown-item @click.stop="deleteRole(row)" class="border-t p-8"
|
|
v-if="hasPermission(
|
|
new ComplexPermission(
|
|
[RoleConst.ADMIN],
|
|
[PermissionConst.ROLE_DELETE],
|
|
[],'OR'
|
|
),'OR'
|
|
)"
|
|
>
|
|
<el-icon><Delete /></el-icon>
|
|
{{ $t('common.delete') }}
|
|
</el-dropdown-item>
|
|
</el-dropdown-menu>
|
|
</template>
|
|
</el-dropdown>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<template #empty>
|
|
<span></span>
|
|
</template>
|
|
</common-list>
|
|
</div>
|
|
</el-scrollbar>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 右边 -->
|
|
<div class="role-right p-24" v-loading="loading">
|
|
<div class="flex-between mb-16">
|
|
<div class="flex align-center">
|
|
<h4>
|
|
{{ currentRole?.role_name }}
|
|
</h4>
|
|
<span
|
|
v-if="currentRole?.type && !currentRole.internal"
|
|
class="color-input-placeholder ml-4"
|
|
>({{ roleTypeMap[currentRole?.type as RoleTypeEnum] }})
|
|
</span>
|
|
|
|
<el-divider direction="vertical" />
|
|
<el-icon class="color-input-placeholder"><UserFilled /></el-icon>
|
|
<span class="color-input-placeholder ml-4">
|
|
{{ currentRole?.user_count }}
|
|
</span>
|
|
</div>
|
|
<el-radio-group v-model="currentTab" class="app-radio-button-group">
|
|
<el-radio-button
|
|
v-for="item in tabList"
|
|
:key="item.value"
|
|
:label="item.label"
|
|
:value="item.value"
|
|
/>
|
|
</el-radio-group>
|
|
</div>
|
|
<PermissionConfiguration v-if="currentTab === 'permission'" :currentRole="currentRole" />
|
|
<Member v-else :currentRole="currentRole" />
|
|
</div>
|
|
</div>
|
|
</el-card>
|
|
|
|
<CreateOrUpdateRoleDialog ref="createOrUpdateRoleDialogRef" @refresh="refresh" />
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { onMounted, ref, watch } from 'vue'
|
|
import { t } from '@/locales'
|
|
import PermissionConfiguration from './component/PermissionConfiguration.vue'
|
|
import Member from './component/Member.vue'
|
|
import CreateOrUpdateRoleDialog from './component/CreateOrUpdateRoleDialog.vue'
|
|
import type { RoleItem } from '@/api/type/role'
|
|
import { RoleTypeEnum } from '@/enums/system'
|
|
import { roleTypeMap } from './index'
|
|
import { MsgSuccess, MsgConfirm } from '@/utils/message'
|
|
import { loadPermissionApi } from '@/utils/dynamics-api/permission-api'
|
|
import { PermissionConst, RoleConst } from '@/utils/permission/data'
|
|
import { ComplexPermission } from '@/utils/permission/type'
|
|
import { hasPermission } from '@/utils/permission/index'
|
|
|
|
const filterText = ref('')
|
|
const loading = ref(false)
|
|
const internalRoleList = ref<RoleItem[]>([])
|
|
const filterInternalRole = ref<RoleItem[]>([]) // 搜索过滤后列表
|
|
const customRoleList = ref<RoleItem[]>([])
|
|
const filterCustomRole = ref<RoleItem[]>([]) // 搜索过滤后列表
|
|
const currentRole = ref<RoleItem>()
|
|
|
|
async function getRole() {
|
|
try {
|
|
const res = await loadPermissionApi('role').getRoleList(loading)
|
|
internalRoleList.value = res.data.internal_role
|
|
customRoleList.value = res.data.custom_role
|
|
filterInternalRole.value = filter(internalRoleList.value, filterText.value)
|
|
filterCustomRole.value = filter(customRoleList.value, filterText.value)
|
|
} catch (error) {
|
|
console.error(error)
|
|
}
|
|
}
|
|
|
|
onMounted(async () => {
|
|
await getRole()
|
|
currentRole.value = internalRoleList.value[0]
|
|
})
|
|
|
|
async function refresh(role?: RoleItem) {
|
|
await getRole()
|
|
// 创建角色后选中新建的角色
|
|
currentRole.value = role ? role : currentRole.value
|
|
}
|
|
|
|
function filter(list: RoleItem[], filterText: string) {
|
|
if (!filterText.length) {
|
|
return list
|
|
}
|
|
return list.filter((v: RoleItem) => v.role_name.toLowerCase().includes(filterText.toLowerCase()))
|
|
}
|
|
|
|
watch(filterText, (val: string) => {
|
|
filterInternalRole.value = filter(internalRoleList.value, val)
|
|
filterCustomRole.value = filter(customRoleList.value, val)
|
|
})
|
|
|
|
function clickRole(item: RoleItem) {
|
|
currentRole.value = item
|
|
}
|
|
|
|
const createOrUpdateRoleDialogRef = ref<InstanceType<typeof CreateOrUpdateRoleDialog>>()
|
|
|
|
function createOrUpdateRole(item?: RoleItem) {
|
|
createOrUpdateRoleDialogRef.value?.open(item)
|
|
}
|
|
|
|
function deleteRole(item: RoleItem) {
|
|
MsgConfirm(
|
|
`${t('views.role.delete.confirmTitle')}${item.role_name} ?`,
|
|
t('views.role.delete.confirmMessage'),
|
|
{
|
|
confirmButtonText: t('common.confirm'),
|
|
confirmButtonClass: 'color-danger',
|
|
},
|
|
)
|
|
.then(() => {
|
|
loadPermissionApi('role').deleteRole(item.id, loading).then(async () => {
|
|
MsgSuccess(t('common.deleteSuccess'))
|
|
await getRole()
|
|
currentRole.value =
|
|
item.id === currentRole.value?.id ? internalRoleList.value[0] : currentRole.value
|
|
})
|
|
})
|
|
.catch(() => {})
|
|
}
|
|
|
|
const currentTab = ref('permission')
|
|
const tabList = [
|
|
{
|
|
value: 'permission',
|
|
label: t('views.role.permission.title'),
|
|
},
|
|
{
|
|
value: 'member',
|
|
label: t('views.role.member.title'),
|
|
},
|
|
]
|
|
const mouseId = ref('')
|
|
|
|
function mouseenter(row: any) {
|
|
mouseId.value = row.id
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.role-manage {
|
|
.role-left {
|
|
box-sizing: border-box;
|
|
width: var(--setting-left-width);
|
|
min-width: var(--setting-left-width);
|
|
|
|
.list-height-left {
|
|
height: calc(100vh - 213px);
|
|
}
|
|
}
|
|
.role-right {
|
|
flex: 1;
|
|
overflow: hidden;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
}
|
|
</style>
|
|
|