Files
hzdyjs/web/src/views/studentMsg/authmsg/components/ScopeDialog.vue
T

272 lines
6.6 KiB
Vue

<template>
<el-dialog :title="getScopeDialogTitle(type)" v-model="visible" width="600px" append-to-body destroy-on-close>
<el-form :model="form" label-width="100px">
<el-form-item :label="getScopeName(type)">
<div v-if="loading" class="loading-container">
<el-icon class="is-loading"><Loading /></el-icon>
<span>加载中...</span>
</div>
<div v-else-if="type === 'custom'">
<el-tree
:data="scopeOptions.custom"
show-checkbox
node-key="id"
:default-checked-keys="form.selectedScopes"
:props="{ label: 'label', children: 'children' }"
@check="onTreeCheck"
default-expand-all
style="
width: 100%;
min-width: 100%;
overflow-x: auto;
overflow-y: auto;
/* border: 1px solid #ebeef5; */
border-radius: 4px;
padding: 10px;
box-sizing: border-box;
"
/>
</div>
<div v-else-if="type === 'teacher'">
<el-checkbox-group v-model="form.selectedScopes">
<el-checkbox v-for="item in scopeOptions.teacher" :key="item.id" :label="item.id">
{{ item.label }}
</el-checkbox>
</el-checkbox-group>
</div>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="cancel">取 消</el-button>
<el-button type="primary" @click="submitForm" :loading="loading">确 定</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { ref, reactive, computed, watch, onMounted } from 'vue';
import { ElMessage } from 'element-plus';
import { Loading } from '@element-plus/icons-vue';
import axios from 'axios';
import request from '@/utils/request';
const props = defineProps({
modelValue: {
type: Boolean,
default: false
},
admin: {
type: Object,
default: () => ({})
},
type: {
type: String,
default: 'custom'
}
});
const emit = defineEmits(['update:modelValue', 'submit']);
// 计算属性:对话框可见性
const visible = computed({
get: () => props.modelValue,
set: (value) => emit('update:modelValue', value)
});
// 范围选项(从API获取)
const scopeOptions = reactive({
custom: [] as any[],
teacher: [] as any[]
});
// 加载状态
const loading = ref(false);
// 表单数据
const form = reactive({
selectedScopes: [] as number[]
});
// 获取部门树数据
async function fetchDeptTree() {
try {
loading.value = true;
const response = await request({
url: '/system/user/deptTree',
method: 'get',
params: {
belongDeptId: 101
}
});
if (response && response.code === 200) {
// custom类型直接使用树形结构
if (props.type === 'custom') {
scopeOptions.custom = response.data || [];
} else if (props.type === 'teacher') {
// teacher类型仍可用扁平化
scopeOptions.teacher = flattenTreeData(response.data || []);
}
}
} catch (error) {
console.error('获取部门树数据失败:', error);
ElMessage.error('获取范围选项失败');
} finally {
loading.value = false;
}
}
// 将树形数据扁平化
function flattenTreeData(treeData: any[]): any[] {
const result: any[] = [];
function traverse(nodes: any[]) {
nodes.forEach((node) => {
result.push({
id: node.id,
label: node.label
});
if (node.children && node.children.length > 0) {
traverse(node.children);
}
});
}
traverse(treeData);
return result;
}
// 新增:获取历史范围数据
async function fetchSelectedScopes(managerId: number | string) {
if (!managerId) return;
try {
const res = await request({
url: '/xgStudentManagerSource/studentManagerSource/list',
method: 'get',
params: { managerId }
});
if (res && res.code === 200) {
// 提取rows中的authSource字段作为已选范围ID
form.selectedScopes = (res.rows || []).map((item: any) => item.authSource);
}
} catch (e) {
form.selectedScopes = [];
}
}
// 监听对话框显示状态,自动加载数据
watch(visible, async (newVal) => {
if (newVal) {
const managerId = props.admin?.managerId || props.admin?.id;
await fetchDeptTree();
await fetchSelectedScopes(managerId);
} else {
// 对话框关闭时清空选择
form.selectedScopes = [];
}
});
// el-tree勾选事件,确保能正确获取所有勾选节点的id
function onTreeCheck(checkedNodes: any, info: { checkedKeys: any[]; halfCheckedKeys: any[] }) {
form.selectedScopes = info.checkedKeys;
}
// 获取范围对话框标题
function getScopeDialogTitle(type: string) {
const name = props.admin?.managerName || '';
switch (type) {
case 'custom':
return `为【${name}】分配管理范围`;
case 'teacher':
return `为【${name}】分配班级`;
default:
return `为【${name}】分配范围`;
}
}
// 获取范围名称
function getScopeName(type: string) {
switch (type) {
case 'custom':
return '管理范围';
case 'teacher':
return '所管理班级';
default:
return '管理范围';
}
}
// 提交表单
async function submitForm() {
// 组装要提交的数据
const selectedIds = form.selectedScopes;
console.log(selectedIds);
const managerId = props.admin?.managerId || props.admin?.id; // 兼容不同字段
if (!managerId) {
ElMessage.error('管理员ID缺失,无法提交');
return;
}
loading.value = true;
try {
await request({
url: '/xgStudentManagerSource/studentManagerSource/grantDeptAuth',
method: 'post',
params: { managerId },
data: selectedIds
});
ElMessage.success('分配成功');
visible.value = false;
emit('submit', {
sourceIds: selectedIds
});
} catch (error) {
ElMessage.error('分配失败,请重试');
} finally {
loading.value = false;
}
}
// 取消
function cancel() {
visible.value = false;
}
// 从props获取类型的响应式引用
const type = computed(() => props.type);
// 暴露组件以修复导出问题
defineExpose({
submitForm,
cancel,
fetchDeptTree
});
</script>
<style scoped>
.dialog-footer {
display: flex;
justify-content: flex-end;
}
.el-checkbox-group {
display: flex;
flex-wrap: wrap;
}
.el-checkbox {
margin-right: 15px;
margin-bottom: 10px;
}
.loading-container {
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
color: #909399;
}
.loading-container .el-icon {
margin-right: 8px;
font-size: 16px;
}
</style>