Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
CI / CI OK (push) Has been cancelled
Deploy Website on push / Rerun on failure (push) Has been cancelled
Lock Threads / action (push) Has been cancelled
Issue Close Require / close-issues (push) Has been cancelled
Close stale issues / stale (push) Has been cancelled
251 lines
8.0 KiB
Vue
251 lines
8.0 KiB
Vue
<script lang="ts" setup>
|
|
import { ref, onMounted, computed } from 'vue';
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
import { Page } from '@vben/common-ui';
|
|
import { Card, Form, Input, Button, message, Select, Radio } from 'ant-design-vue';
|
|
import {
|
|
getClassDetailApi,
|
|
saveClassApi,
|
|
getTeachersApi,
|
|
getClassroomsApi,
|
|
type ClassApi
|
|
} from '#/api';
|
|
|
|
defineOptions({ name: 'ClassDetail' });
|
|
|
|
const route = useRoute();
|
|
const router = useRouter();
|
|
const formRef = ref();
|
|
const loading = ref(false);
|
|
const teacherList = ref<any[]>([]);
|
|
const classroomList = ref<any[]>([]);
|
|
const teacherListLoading = ref(false);
|
|
const classroomListLoading = ref(false);
|
|
|
|
const formData = ref<Partial<ClassApi.SaveParams>>({
|
|
name: '',
|
|
grade: '',
|
|
teacher_id: undefined,
|
|
class_room_id: undefined,
|
|
description: '',
|
|
status: 1,
|
|
});
|
|
|
|
const isEdit = computed(() => !!route.params.id);
|
|
|
|
const handleSubmit = async () => {
|
|
try {
|
|
await formRef.value.validate();
|
|
loading.value = true;
|
|
const data = { ...formData.value };
|
|
if (isEdit.value) {
|
|
data.id = Number(route.params.id);
|
|
}
|
|
await saveClassApi(data);
|
|
message.success(isEdit.value ? '更新成功' : '创建成功');
|
|
router.back();
|
|
} catch (error: any) {
|
|
console.error('保存失败:', error);
|
|
message.error(error?.response?.data?.message || error?.response?.data?.msg || '保存失败');
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
};
|
|
|
|
const fetchDetail = async () => {
|
|
if (!isEdit.value) return;
|
|
loading.value = true;
|
|
try {
|
|
const res = await getClassDetailApi({ id: Number(route.params.id) });
|
|
// 支持 code 为 0 或 200 的成功响应
|
|
if (res && (res.code === 0 || res.code === 200)) {
|
|
// 根据实际返回格式,数据在 res.data 中
|
|
const data = res.data;
|
|
if (data) {
|
|
formData.value = {
|
|
name: data.name || '',
|
|
grade: data.grade || '',
|
|
teacher_id: data.teacher_id || undefined,
|
|
class_room_id: data.class_room_id || undefined,
|
|
description: data.description || '',
|
|
status: data.status !== undefined ? data.status : 1,
|
|
};
|
|
} else {
|
|
message.error('获取班级详情失败:数据为空');
|
|
}
|
|
} else {
|
|
message.error(res?.message || res?.msg || '获取班级详情失败');
|
|
}
|
|
} catch (error: any) {
|
|
console.error('获取详情失败:', error);
|
|
message.error(error?.response?.data?.message || error?.response?.data?.msg || '获取班级详情失败');
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
};
|
|
|
|
// 获取班主任列表
|
|
const fetchTeacherList = async () => {
|
|
teacherListLoading.value = true;
|
|
try {
|
|
const res: any = await getTeachersApi();
|
|
if (Array.isArray(res)) {
|
|
teacherList.value = res;
|
|
} else if (res && (res.code === 0 || res.code === 200)) {
|
|
teacherList.value = Array.isArray(res.data) ? res.data : [];
|
|
} else {
|
|
teacherList.value = [];
|
|
}
|
|
} catch (error) {
|
|
console.error('获取班主任列表失败:', error);
|
|
teacherList.value = [];
|
|
} finally {
|
|
teacherListLoading.value = false;
|
|
}
|
|
};
|
|
|
|
// 获取教室列表
|
|
const fetchClassroomList = async () => {
|
|
classroomListLoading.value = true;
|
|
try {
|
|
const res = await getClassroomsApi();
|
|
if (res && (res.code === 0 || res.code === 200)) {
|
|
// 根据实际返回格式,教室列表在 res.data.all_classrooms 中
|
|
if (res.data && res.data.all_classrooms) {
|
|
classroomList.value = Array.isArray(res.data.all_classrooms) ? res.data.all_classrooms : [];
|
|
} else if (Array.isArray(res.data)) {
|
|
// 兼容直接返回数组的情况
|
|
classroomList.value = res.data;
|
|
} else {
|
|
classroomList.value = [];
|
|
}
|
|
} else if (Array.isArray(res)) {
|
|
// 兼容直接返回数组的情况
|
|
classroomList.value = res;
|
|
} else {
|
|
classroomList.value = [];
|
|
}
|
|
} catch (error) {
|
|
console.error('获取教室列表失败:', error);
|
|
classroomList.value = [];
|
|
} finally {
|
|
classroomListLoading.value = false;
|
|
}
|
|
};
|
|
|
|
onMounted(async () => {
|
|
// 先加载下拉列表数据,确保在填充表单时选项已存在
|
|
await Promise.all([fetchTeacherList(), fetchClassroomList()]);
|
|
// 然后再加载详情数据
|
|
if (isEdit.value) {
|
|
fetchDetail();
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<Page :title="isEdit ? '编辑班级' : '新增班级'">
|
|
<Card>
|
|
<Form
|
|
ref="formRef"
|
|
:model="formData"
|
|
:label-col="{ span: 4 }"
|
|
:wrapper-col="{ span: 20 }"
|
|
>
|
|
<Form.Item
|
|
label="班级名称"
|
|
name="name"
|
|
:rules="[{ required: true, message: '请输入班级名称' }]"
|
|
>
|
|
<Input v-model:value="formData.name" placeholder="请输入班级名称" />
|
|
</Form.Item>
|
|
<Form.Item
|
|
label="年级"
|
|
name="grade"
|
|
:rules="[{ required: true, message: '请输入年级' }]"
|
|
>
|
|
<Input v-model:value="formData.grade" placeholder="请输入年级" />
|
|
</Form.Item>
|
|
<Form.Item
|
|
label="班主任"
|
|
name="teacher_id"
|
|
:rules="[{ required: true, message: '请选择班主任' }]"
|
|
>
|
|
<Select
|
|
v-model:value="formData.teacher_id"
|
|
placeholder="请选择班主任"
|
|
:loading="teacherListLoading"
|
|
allow-clear
|
|
show-search
|
|
:filter-option="(input, option) => {
|
|
const label = option?.label || '';
|
|
return label.toLowerCase().includes(input.toLowerCase());
|
|
}"
|
|
>
|
|
<template v-if="teacherList.length === 0 && !teacherListLoading">
|
|
<Select.Option disabled value="">暂无班主任数据</Select.Option>
|
|
</template>
|
|
<Select.Option
|
|
v-for="item in teacherList"
|
|
:key="item.id"
|
|
:value="item.id"
|
|
:label="item.name || ''"
|
|
>
|
|
{{ item.name || `班主任 ${item.id}` }}
|
|
</Select.Option>
|
|
</Select>
|
|
<div v-if="teacherList.length > 0" style="margin-top: 4px; font-size: 12px; color: #999;">
|
|
共 {{ teacherList.length }} 个班主任可选
|
|
</div>
|
|
</Form.Item>
|
|
<Form.Item
|
|
label="教室"
|
|
name="class_room_id"
|
|
:rules="[{ required: true, message: '请选择教室' }]"
|
|
>
|
|
<Select
|
|
v-model:value="formData.class_room_id"
|
|
placeholder="请选择教室"
|
|
:loading="classroomListLoading"
|
|
allow-clear
|
|
show-search
|
|
:filter-option="(input, option) => {
|
|
const label = option?.label || '';
|
|
return label.toLowerCase().includes(input.toLowerCase());
|
|
}"
|
|
>
|
|
<template v-if="classroomList.length === 0 && !classroomListLoading">
|
|
<Select.Option disabled value="">暂无教室数据</Select.Option>
|
|
</template>
|
|
<Select.Option
|
|
v-for="item in classroomList"
|
|
:key="item.id"
|
|
:value="item.id"
|
|
:label="item.name || ''"
|
|
>
|
|
{{ item.name || `教室 ${item.id}` }}
|
|
</Select.Option>
|
|
</Select>
|
|
<div v-if="classroomList.length > 0" style="margin-top: 4px; font-size: 12px; color: #999;">
|
|
共 {{ classroomList.length }} 个教室可选
|
|
</div>
|
|
</Form.Item>
|
|
<Form.Item label="描述" name="description">
|
|
<Input.TextArea v-model:value="formData.description" placeholder="请输入描述" :rows="3" />
|
|
</Form.Item>
|
|
<Form.Item label="状态" name="status">
|
|
<Radio.Group v-model:value="formData.status">
|
|
<Radio :value="1">启用</Radio>
|
|
<Radio :value="0">禁用</Radio>
|
|
</Radio.Group>
|
|
</Form.Item>
|
|
<Form.Item :wrapper-col="{ offset: 4, span: 20 }">
|
|
<Button type="primary" :loading="loading" @click="handleSubmit">保存</Button>
|
|
<Button class="ml-2" @click="router.back()">取消</Button>
|
|
</Form.Item>
|
|
</Form>
|
|
</Card>
|
|
</Page>
|
|
</template>
|
|
|