UnisKB/ui/src/views/system/role/component/PermissionConfiguration.vue

201 lines
5.7 KiB
Vue
Raw Normal View History

2025-06-10 11:25:17 +00:00
<template>
<el-scrollbar v-loading="loading">
<div class="p-24 pt-0">
2025-06-26 06:32:03 +00:00
<app-table :data="tableData" border :span-method="objectSpanMethod">
<el-table-column
prop="module"
:width="130"
:label="$t('views.role.permission.moduleName')"
/>
<el-table-column
prop="name"
:width="150"
:label="$t('views.role.permission.operationTarget')"
/>
<el-table-column
prop="permission"
:label="$t('views.model.modelForm.permissionType.label')"
>
2025-06-10 11:25:17 +00:00
<template #default="{ row }">
<el-checkbox-group v-model="row.perChecked" @change="handleCellChange($event, row)">
2025-06-26 06:32:03 +00:00
<el-checkbox
v-for="item in row.permission"
:key="item.id"
:value="item.id"
:disabled="disabled"
>
2025-06-10 11:25:17 +00:00
<div class="ellipsis" style="width: 96px">{{ item.name }}</div>
</el-checkbox>
</el-checkbox-group>
</template>
</el-table-column>
<el-table-column :width="40">
<template #header>
2025-06-26 06:32:03 +00:00
<el-checkbox
:model-value="allChecked"
:indeterminate="allIndeterminate"
:disabled="disabled"
@change="handleCheckAll"
/>
2025-06-10 11:25:17 +00:00
</template>
<template #default="{ row }">
2025-06-26 06:32:03 +00:00
<el-checkbox
v-model="row.enable"
:indeterminate="row.indeterminate"
:disabled="disabled"
@change="(value: boolean) => handleRowChange(value, row)"
/>
2025-06-10 11:25:17 +00:00
</template>
</el-table-column>
2025-06-26 06:32:03 +00:00
</app-table>
2025-06-10 11:25:17 +00:00
</div>
</el-scrollbar>
<div v-if="!disabled" class="footer border-t">
2025-06-26 06:32:03 +00:00
<el-button type="primary" style="width: 80px" :loading="loading" @click="handleSave">
2025-06-10 11:25:17 +00:00
{{ $t('common.save') }}
</el-button>
</div>
</template>
<script setup lang="ts">
import { ref, watch, computed } from 'vue'
2025-06-26 06:32:03 +00:00
import type {
RoleItem,
RolePermissionItem,
RoleTableDataItem,
ChildrenPermissionItem,
} from '@/api/type/role'
2025-06-11 08:00:35 +00:00
import RoleApi from '@/api/system/role'
2025-06-10 11:25:17 +00:00
import { MsgSuccess } from '@/utils/message'
import { t } from '@/locales'
const props = defineProps<{
currentRole?: RoleItem
}>()
const loading = ref(false)
const tableData = ref<RoleTableDataItem[]>([])
const disabled = computed(() => props.currentRole?.internal) // TODO 权限
function transformData(data: RolePermissionItem[]) {
const transformedData: RoleTableDataItem[] = []
2025-06-26 06:32:03 +00:00
data.forEach((module) => {
module.children.forEach((feature) => {
const perChecked = feature.permission.filter((p) => p.enable).map((p) => p.id)
2025-06-10 11:25:17 +00:00
transformedData.push({
module: module.name,
name: feature.name,
permission: feature.permission,
enable: feature.enable,
perChecked,
2025-06-26 06:32:03 +00:00
indeterminate: perChecked.length > 0 && perChecked.length < feature.permission.length,
2025-06-10 11:25:17 +00:00
})
})
})
2025-06-26 06:32:03 +00:00
return transformedData
}
2025-06-10 11:25:17 +00:00
async function getRolePermission() {
if (!props.currentRole?.id) return
try {
2025-06-26 06:32:03 +00:00
tableData.value = []
2025-06-10 11:25:17 +00:00
const res = await RoleApi.getRolePermissionList(props.currentRole.id, loading)
2025-06-26 06:32:03 +00:00
tableData.value = transformData(res.data)
2025-06-10 11:25:17 +00:00
} catch (error) {
console.error(error)
}
}
function handleCellChange(checkedValues: string[], row: RoleTableDataItem) {
row.enable = checkedValues.length === row.permission.length
row.indeterminate = checkedValues.length > 0 && checkedValues.length < row.permission.length
2025-06-26 06:32:03 +00:00
row.permission.forEach((p) => {
2025-06-10 11:25:17 +00:00
p.enable = checkedValues.includes(p.id)
})
}
function handleRowChange(checked: boolean, row: RoleTableDataItem) {
if (checked) {
2025-06-26 06:32:03 +00:00
row.perChecked = row.permission.map((p) => p.id)
row.permission.forEach((p) => (p.enable = true))
2025-06-10 11:25:17 +00:00
} else {
row.perChecked = []
2025-06-26 06:32:03 +00:00
row.permission.forEach((p) => (p.enable = false))
2025-06-10 11:25:17 +00:00
}
row.indeterminate = false
}
const allChecked = computed(() => {
2025-06-26 06:32:03 +00:00
return tableData.value.length > 0 && tableData.value.every((item) => item.enable)
2025-06-10 11:25:17 +00:00
})
const allIndeterminate = computed(() => {
2025-06-26 06:32:03 +00:00
return !allChecked.value && tableData.value.some((item) => item.enable)
2025-06-10 11:25:17 +00:00
})
function handleCheckAll(checked: boolean) {
2025-06-26 06:32:03 +00:00
tableData.value.forEach((item) => {
2025-06-10 11:25:17 +00:00
item.enable = checked
2025-06-26 06:32:03 +00:00
item.perChecked = checked ? item.permission.map((p) => p.id) : []
2025-06-10 11:25:17 +00:00
item.indeterminate = false
2025-06-26 06:32:03 +00:00
item.permission.forEach((p) => (p.enable = checked))
2025-06-10 11:25:17 +00:00
})
}
const objectSpanMethod = ({ row, column, rowIndex, columnIndex }: any) => {
if (columnIndex === 0) {
2025-06-26 06:32:03 +00:00
const sameModuleRows = tableData.value.filter((item) => item.module === row.module)
const firstRowIndex = tableData.value.findIndex((item) => item.module === row.module)
2025-06-10 11:25:17 +00:00
if (rowIndex === firstRowIndex) {
return {
rowspan: sameModuleRows.length,
2025-06-26 06:32:03 +00:00
colspan: 1,
2025-06-10 11:25:17 +00:00
}
} else {
return {
rowspan: 0,
2025-06-26 06:32:03 +00:00
colspan: 0,
2025-06-10 11:25:17 +00:00
}
}
}
}
watch(() => props.currentRole?.id, getRolePermission, { immediate: true })
async function handleSave() {
try {
2025-06-26 06:32:03 +00:00
const permissions: { id: string; enable: boolean }[] = []
2025-06-10 11:25:17 +00:00
tableData.value.forEach((e) => {
e.permission?.forEach((ele: ChildrenPermissionItem) => {
permissions.push({
id: ele.id,
enable: ele.enable,
2025-06-26 06:32:03 +00:00
})
})
})
await RoleApi.saveRolePermission(props.currentRole?.id as string, permissions, loading)
2025-06-10 11:25:17 +00:00
MsgSuccess(t('common.saveSuccess'))
} catch (error) {
2025-06-26 06:32:03 +00:00
console.log(error)
2025-06-10 11:25:17 +00:00
}
}
</script>
<style lang="scss" scoped>
:deep(.el-checkbox-group) {
display: flex;
flex-wrap: wrap;
gap: 4px;
}
.footer {
width: 100%;
display: flex;
justify-content: flex-end;
padding: 16px 24px;
box-sizing: border-box;
}
2025-06-26 06:32:03 +00:00
</style>