Files
YG_FT/frontend/src/components/AclDialog.vue
2026-07-27 09:12:47 +08:00

80 lines
2.4 KiB
Vue

<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>