提交学生管理权限设置的代码

This commit is contained in:
zlwu committed 2025-07-25 14:51:19 +08:00
1 parent 0917c7f156
commit 517a0052bc
28 files changed
+2506 -161

No files matched your search

@@ -2,17 +2,35 @@
<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="type === 'custom'">
<el-checkbox-group v-model="form.selectedScopes">
<el-checkbox v-for="item in scopeOptions.custom" :key="item.id" :label="item.id">
{{ item.name }}
</el-checkbox>
</el-checkbox-group>
<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.name }}
{{ item.label }}
</el-checkbox>
</el-checkbox-group>
</div>
@@ -21,15 +39,18 @@
<template #footer>
<div class="dialog-footer">
<el-button @click="cancel">取 消</el-button>
<el-button type="primary" @click="submitForm">确 定</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 } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
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: {
@@ -54,35 +75,107 @@ const visible = computed({
set: (value) => emit('update:modelValue', value)
});
// 范围选项(模拟数据)
const scopeOptions = {
custom: [
{ id: 1, name: '高一年级' },
{ id: 2, name: '高二年级' },
{ id: 3, name: '高三年级' },
{ id: 4, name: '初一年级' },
{ id: 5, name: '初二年级' },
{ id: 6, name: '初三年级' }
],
teacher: [
{ id: 101, name: '高一(1)班' },
{ id: 102, name: '高一(2)班' },
{ id: 103, name: '高一(3)班' },
{ id: 104, name: '高二(1)班' },
{ id: 105, name: '高二(2)班' },
{ id: 106, name: '高三(1)班' },
{ id: 107, name: '高三(2)班' }
]
};
// 范围选项(从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?.name || '';
const name = props.admin?.managerName || '';
switch (type) {
case 'custom':
return `为【${name}】分配管理范围`;
@@ -106,32 +199,33 @@ function getScopeName(type: string) {
}
// 提交表单
function submitForm() {
async function submitForm() {
// 组装要提交的数据
const selectedIds = form.selectedScopes;
let scopeName = '';
// 根据类型获取选中的名称
if (type.value === 'custom') {
scopeName = scopeOptions.custom
.filter((item) => selectedIds.includes(item.id))
.map((item) => item.name)
.join(', ');
} else if (type.value === 'teacher') {
scopeName = scopeOptions.teacher
.filter((item) => selectedIds.includes(item.id))
.map((item) => item.name)
.join(', ');
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;
}
// 提交
emit('submit', {
sourceIds: selectedIds,
scopeName: scopeName
});
ElMessage.success('分配成功');
visible.value = false;
}
// 取消
@@ -145,7 +239,8 @@ const type = computed(() => props.type);
// 暴露组件以修复导出问题
defineExpose({
submitForm,
cancel
cancel,
fetchDeptTree
});
</script>
@@ -162,4 +257,15 @@ defineExpose({
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>