feat:添加前端页面
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
/* 班级管理:新增 / 修改 / 逻辑删除
|
||||
班级表只有「编号 + 开课时间」两列,没有班级名,所以界面上一律显示成 "编号1 · 2026-09-01 开班" */
|
||||
|
||||
window.PAGES.push({
|
||||
key: 'classes',
|
||||
title: '班级管理',
|
||||
sub: '班级开课时间,班主任与任课老师来自老师模块',
|
||||
group: '数据管理',
|
||||
icon: 'class',
|
||||
|
||||
component: {
|
||||
name: 'ClassesPage',
|
||||
template: `
|
||||
<div>
|
||||
<div class="card">
|
||||
<div class="card-head">
|
||||
<div>
|
||||
<div class="card-title">班级列表</div>
|
||||
<div class="card-hint">
|
||||
共 {{ rows.length }} 个班级;班主任和任课老师由老师模块反查得到
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-tools">
|
||||
<el-button @click="load">刷新</el-button>
|
||||
<el-button type="primary" @click="openCreate">+ 新增班级</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-table :data="rows" v-loading="loading" border stripe row-key="class_id">
|
||||
<el-table-column prop="class_id" label="班级编号" width="100" />
|
||||
<el-table-column label="开课时间" width="140">
|
||||
<template #default="{ row }">{{ dash(fmtDate(row.start_time)) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="班主任" width="130">
|
||||
<template #default="{ row }">
|
||||
<span :class="{ muted: !row.head_teacher_name || row.head_teacher_name === '暂无' }">
|
||||
{{ row.head_teacher_name || '暂无' }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="任课老师">
|
||||
<template #default="{ row }">
|
||||
<span :class="{ muted: !row.course_teacher_names || row.course_teacher_names === '暂无' }">
|
||||
{{ row.course_teacher_names || '暂无' }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="140" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" @click="openEdit(row)">编辑</el-button>
|
||||
<el-button link type="danger" @click="remove(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-alert class="mt12" type="info" :closable="false" show-icon
|
||||
title="删除保护:班里还有学生或老师时不允许删除,后端会返回中文提示" />
|
||||
</div>
|
||||
|
||||
<el-dialog v-model="dialog" :title="editing ? '编辑班级' : '新增班级'" width="480px" destroy-on-close>
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="88px">
|
||||
<el-form-item label="开课时间" prop="start_time">
|
||||
<el-date-picker v-model="form.start_time" type="date" value-format="YYYY-MM-DD"
|
||||
placeholder="选择开课日期" style="width:100%" />
|
||||
</el-form-item>
|
||||
<el-alert type="info" :closable="false" show-icon
|
||||
title="开课时间会用来生成学生学号的前八位,请认真填写" />
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="dialog = false">取消</el-button>
|
||||
<el-button type="primary" :loading="saving" @click="submit">保存</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
`,
|
||||
|
||||
setup() {
|
||||
const loading = ref(false);
|
||||
const saving = ref(false);
|
||||
const rows = ref([]);
|
||||
const dialog = ref(false);
|
||||
const editing = ref(null);
|
||||
const formRef = ref(null);
|
||||
const form = ref({ start_time: null });
|
||||
|
||||
const rules = {
|
||||
start_time: [{ required: true, message: '请选择开课时间', trigger: 'change' }],
|
||||
};
|
||||
|
||||
// 一定要重新拉列表:新增/修改接口返回的班主任和任课老师永远是"暂无",
|
||||
// 那两个字段是 DAO 在列表查询里才挂上去的。
|
||||
// 顺便把结果写回共享缓存,别的页面的班级下拉/名称映射也就跟着更新了。
|
||||
const load = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
rows.value = await ClassApi.list({ limit: 1000 });
|
||||
Cache.classes = rows.value;
|
||||
Cache.loaded.classes = true;
|
||||
} catch (e) { toastErr(e); }
|
||||
finally { loading.value = false; }
|
||||
};
|
||||
|
||||
const openCreate = () => {
|
||||
editing.value = null;
|
||||
form.value = { start_time: null };
|
||||
dialog.value = true;
|
||||
};
|
||||
|
||||
const openEdit = (row) => {
|
||||
editing.value = row.class_id;
|
||||
// 回参是 "2026-09-01T00:00:00",日期选择器只认前半段
|
||||
form.value = { start_time: fmtDate(row.start_time) || null };
|
||||
dialog.value = true;
|
||||
};
|
||||
|
||||
const submit = async () => {
|
||||
if (!formRef.value) return;
|
||||
try { await formRef.value.validate(); } catch (e) { return; }
|
||||
saving.value = true;
|
||||
try {
|
||||
if (editing.value) {
|
||||
await ClassApi.update(editing.value, form.value);
|
||||
toastOk('修改成功');
|
||||
} else {
|
||||
await ClassApi.create(form.value);
|
||||
toastOk('新增成功');
|
||||
}
|
||||
dialog.value = false;
|
||||
await load();
|
||||
} catch (e) { toastErr(e); }
|
||||
finally { saving.value = false; }
|
||||
};
|
||||
|
||||
const remove = async (row) => {
|
||||
try {
|
||||
await ElementPlus.ElMessageBox.confirm(
|
||||
`确定删除班级「编号${row.class_id}」吗?`,
|
||||
'删除确认', { type: 'warning', confirmButtonText: '确定删除', cancelButtonText: '取消' });
|
||||
} catch (e) { return; }
|
||||
try {
|
||||
await ClassApi.remove(row.class_id);
|
||||
toastOk('删除成功');
|
||||
await load();
|
||||
} catch (e) { toastErr(e); }
|
||||
};
|
||||
|
||||
onMounted(load);
|
||||
|
||||
return { loading, saving, rows, dialog, editing, formRef, form, rules,
|
||||
load, openCreate, openEdit, submit, remove, dash, fmtDate };
|
||||
},
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user