update
This commit is contained in:
79
frontend/src/components/AclDialog.vue
Normal file
79
frontend/src/components/AclDialog.vue
Normal file
@@ -0,0 +1,79 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { getAcl, setAcl, type AclEntry } from '@/api/modules/acl'
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: boolean
|
||||
resourceType: string
|
||||
resourceId: string
|
||||
}>()
|
||||
const emit = defineEmits<{ 'update:modelValue': [boolean] }>()
|
||||
|
||||
const visible = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (v) => emit('update:modelValue', v),
|
||||
})
|
||||
const entries = ref<AclEntry[]>([])
|
||||
const loading = ref(false)
|
||||
const ALL_PERMS = ['read', 'write', 'execute', 'download', 'delete', 'share']
|
||||
|
||||
async function load() {
|
||||
loading.value = true
|
||||
try {
|
||||
entries.value = await getAcl(props.resourceType, props.resourceId)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
watch(visible, (v) => { if (v) load() })
|
||||
|
||||
function addEntry() {
|
||||
entries.value.push({ subject_type: 'user', subject_id: '', permissions: [] })
|
||||
}
|
||||
|
||||
function removeEntry(idx: number) {
|
||||
entries.value.splice(idx, 1)
|
||||
}
|
||||
|
||||
async function save() {
|
||||
await setAcl(props.resourceType, props.resourceId, entries.value)
|
||||
ElMessage.success('ACL 已保存')
|
||||
visible.value = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-dialog v-model="visible" title="资源授权 (ACL)" width="640px">
|
||||
<div v-loading="loading">
|
||||
<el-button type="primary" size="small" @click="addEntry">添加授权项</el-button>
|
||||
<div v-for="(entry, idx) in entries" :key="idx" class="acl-row">
|
||||
<el-select v-model="entry.subject_type" style="width: 140px">
|
||||
<el-option label="用户" value="user" />
|
||||
<el-option label="项目角色" value="project_role" />
|
||||
</el-select>
|
||||
<el-input v-model="entry.subject_id" placeholder="subject ID" style="width: 200px" />
|
||||
<el-checkbox-group v-model="entry.permissions">
|
||||
<el-checkbox v-for="p in ALL_PERMS" :key="p" :value="p">{{ p }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
<el-button link type="danger" @click="removeEntry(idx)">删除</el-button>
|
||||
</div>
|
||||
<el-empty v-if="entries.length === 0" description="暂无授权" />
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="visible = false">取消</el-button>
|
||||
<el-button type="primary" @click="save">保存</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.acl-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-top: 12px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
</style>
|
||||
@@ -74,6 +74,16 @@ const menuGroups: MenuGroup[] = [
|
||||
{ key: 'compute', label: '算力节点', icon: 'fa-microchip', to: '/compute', permission: 'compute' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '平台治理',
|
||||
items: [
|
||||
{ key: 'tenants', label: '租户管理', icon: 'fa-building', to: '/tenants', permission: 'user-settings' },
|
||||
{ key: 'projects', label: '项目空间', icon: 'fa-folder', to: '/projects', permission: 'user-settings' },
|
||||
{ key: 'audit-logs', label: '审计日志', icon: 'fa-history', to: '/audit-logs', permission: 'user-settings' },
|
||||
{ key: 'approval-templates', label: '审批模板', icon: 'fa-list-alt', to: '/approval-templates', permission: 'user-settings' },
|
||||
{ key: 'approval-instances', label: '审批中心', icon: 'fa-check-square', to: '/approval-instances', permission: 'user-settings' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '系统设置',
|
||||
items: [
|
||||
|
||||
Reference in New Issue
Block a user