39 个文件按 .prettierrc.json (printWidth 100 / no semi / singleQuote) 统一格式, 纯空白与换行调整, 无逻辑变更。为接入代码门禁做准备, 让 npm run check (format:check + lint:strict + typecheck) 干净通过。
109 lines
2.7 KiB
Vue
109 lines
2.7 KiB
Vue
<script setup lang="ts">
|
|
import { readError } from '@/shared/utils/error'
|
|
import { ElMessage } from 'element-plus'
|
|
import { ref, watch } from 'vue'
|
|
|
|
import { fetchRoles, type Role } from '@/features/admin/api/adminRoles'
|
|
import { assignAdminRoles, type AdminMgrUser } from '@/features/admin/api/adminMgr'
|
|
|
|
const props = defineProps<{
|
|
modelValue: boolean
|
|
admin: AdminMgrUser | null
|
|
}>()
|
|
|
|
const emit = defineEmits<{
|
|
(e: 'update:modelValue', val: boolean): void
|
|
(e: 'saved'): void
|
|
}>()
|
|
|
|
const submitting = ref(false)
|
|
const loading = ref(false)
|
|
const allRoles = ref<Role[]>([])
|
|
const selectedRoleIds = ref<number[]>([])
|
|
|
|
watch(
|
|
() => props.modelValue,
|
|
async val => {
|
|
if (val && props.admin) {
|
|
loading.value = true
|
|
try {
|
|
allRoles.value = await fetchRoles()
|
|
selectedRoleIds.value = props.admin.roles.map(r => r.id)
|
|
} catch {
|
|
ElMessage.error('加载角色列表失败')
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
}
|
|
)
|
|
|
|
async function handleSave() {
|
|
if (!props.admin) return
|
|
submitting.value = true
|
|
try {
|
|
await assignAdminRoles(props.admin.id, selectedRoleIds.value)
|
|
ElMessage.success('角色已分配')
|
|
emit('saved')
|
|
emit('update:modelValue', false)
|
|
} catch (error) {
|
|
ElMessage.error(readError(error, '分配失败'))
|
|
} finally {
|
|
submitting.value = false
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<el-dialog
|
|
:model-value="modelValue"
|
|
:title="`分配角色 - ${admin?.username || ''}`"
|
|
width="500px"
|
|
@update:model-value="emit('update:modelValue', $event)"
|
|
>
|
|
<div v-loading="loading" class="dialog-body">
|
|
<p v-if="admin" class="admin-info">
|
|
<strong>{{ admin.username }}</strong> · {{ admin.nickname }}
|
|
</p>
|
|
<el-checkbox-group v-model="selectedRoleIds">
|
|
<div v-for="role in allRoles" :key="role.id" class="role-option">
|
|
<el-checkbox :value="role.id" :label="role.id">
|
|
<span class="role-name">{{ role.name }}</span>
|
|
<span class="role-desc">{{ role.description }}</span>
|
|
</el-checkbox>
|
|
</div>
|
|
</el-checkbox-group>
|
|
</div>
|
|
<template #footer>
|
|
<el-button @click="emit('update:modelValue', false)">取消</el-button>
|
|
<el-button type="primary" :loading="submitting" @click="handleSave">保存</el-button>
|
|
</template>
|
|
</el-dialog>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.dialog-body {
|
|
display: grid;
|
|
gap: 16px;
|
|
}
|
|
.admin-info {
|
|
margin: 0;
|
|
color: #374151;
|
|
}
|
|
.role-option {
|
|
padding: 8px 0;
|
|
border-bottom: 1px solid #f0f0f0;
|
|
}
|
|
.role-option:last-child {
|
|
border-bottom: none;
|
|
}
|
|
.role-name {
|
|
font-weight: 500;
|
|
margin-right: 8px;
|
|
}
|
|
.role-desc {
|
|
color: #8f9bba;
|
|
font-size: 13px;
|
|
}
|
|
</style>
|