/* 学生管理:增删改查 + 按学号/姓名/班级/顾问筛选 注意:学号是后端按班级开课时间生成的,表单里不给填,新增成功后提示出来 */ window.PAGES.push({ key: 'students', title: '学生管理', sub: '学生基本信息,学号由班级开课时间自动生成', group: '数据管理', icon: 'student', component: { name: 'StudentsPage', template: `
查询 重置
学生列表
共 {{ rows.length }} 人
+ 新增学生
`, setup() { const loading = ref(false); const saving = ref(false); const rows = ref([]); const classes = ref([]); const advisors = ref([]); const dialog = ref(false); const editing = ref(null); const formRef = ref(null); const filter = ref({ stu_no: '', stu_name: '', class_id: null, advisor_id: null }); const page = ref(1); const pageSize = ref(10); const emptyForm = () => ({ class_id: null, advisor_id: null, stu_name: '', native_place: '', graduate_school: '', major: '', in_time: null, out_time: null, edu: null, stu_age: null, stu_gender: null, }); const form = ref(emptyForm()); // 学号是后端生成的,所以班级必选;其余字段都可空 const rules = { class_id: [{ required: true, message: '请选择班级', trigger: 'change' }], stu_name: [{ required: true, message: '请填写姓名', trigger: 'blur' }], }; // 表格是客户端分页:接口本身没有分页参数,一次把命中的都取回来 const pagedRows = computed(() => { const start = (page.value - 1) * pageSize.value; return rows.value.slice(start, start + pageSize.value); }); const load = async () => { loading.value = true; try { rows.value = await StudentApi.list({ stu_no: filter.value.stu_no, stu_name: filter.value.stu_name, class_id: filter.value.class_id, advisor_id: filter.value.advisor_id, }); page.value = 1; } catch (e) { toastErr(e); } finally { loading.value = false; } }; const reset = () => { filter.value = { stu_no: '', stu_name: '', class_id: null, advisor_id: null }; load(); }; const openCreate = () => { editing.value = null; form.value = emptyForm(); dialog.value = true; }; const openEdit = (row) => { editing.value = row.stu_no; form.value = { class_id: row.class_id, advisor_id: row.advisor_id, stu_name: row.stu_name, native_place: row.native_place, graduate_school: row.graduate_school, major: row.major, in_time: fmtDate(row.in_time) || null, out_time: fmtDate(row.out_time) || null, edu: row.edu, stu_age: row.stu_age, stu_gender: row.stu_gender, }; dialog.value = true; }; const submit = async () => { if (!formRef.value) return; try { await formRef.value.validate(); } catch (e) { return; } saving.value = true; try { // pruneEmpty:没填的字段不下发,避免把可空字段写成空字符串 const payload = pruneEmpty(form.value); if (editing.value) { await StudentApi.update(editing.value, payload); toastOk('修改成功'); } else { const created = await StudentApi.create(payload); toastOk('新增成功,学号:' + created.stu_no); } Cache.invalidate('students'); dialog.value = false; await load(); } catch (e) { toastErr(e); } finally { saving.value = false; } }; const remove = async (row) => { try { await ElementPlus.ElMessageBox.confirm( `确定删除学生「${row.stu_name || row.stu_no}」吗?`, '删除确认', { type: 'warning', confirmButtonText: '确定删除', cancelButtonText: '取消' }); } catch (e) { return; } try { await StudentApi.remove(row.stu_no); toastOk('删除成功'); Cache.invalidate('students'); await load(); } catch (e) { toastErr(e); } }; // 班级/顾问下拉的数据先准备好,再拉学生列表 onMounted(async () => { try { [classes.value, advisors.value] = await Promise.all([ Cache.loadClasses(), Cache.loadAdvisors(), ]); } catch (e) { toastErr(e); } load(); }); return { loading, saving, rows, classes, advisors, dialog, editing, formRef, filter, form, rules, page, pageSize, pagedRows, load, reset, openCreate, openEdit, submit, remove, GENDER_OPTIONS, EDU_OPTIONS, dash, fmtDate, className, advisorName, classLabel, }; }, }, });