227 lines
9.0 KiB
TypeScript
227 lines
9.0 KiB
TypeScript
import { Method } from "alova";
|
||
import { alovaInstance } from "@/utils/alova/alova-iview";
|
||
import conf from "@/assets/config/host.config";
|
||
import type {
|
||
ClassTreeNode,
|
||
EffectiveSettingVo,
|
||
GradeSettingVo,
|
||
ModNode,
|
||
MyClassesVo,
|
||
MyTimetableVo,
|
||
NowYearTermVo,
|
||
SettingGetVo,
|
||
SubjectVo,
|
||
TemplateSaveRequest,
|
||
TimeSettingVo,
|
||
TimetableOverviewVo,
|
||
TimetableSaveRequest,
|
||
TimetableVo,
|
||
UpFileResultVo,
|
||
UserInfoVo,
|
||
} from "@/types/syllabus";
|
||
|
||
/**
|
||
* 课程表(AcaSyllabu)接口封装。
|
||
*
|
||
* 前缀说明:conf.serviceHost 本地为空(走 vite 同源代理),线上为基础平台域名;
|
||
* platform 固定使用 "api",与后端 Config.API_PATH 中的 api 匹配。
|
||
* 统一响应 {code,msg,data} 由 alova-iview 解包为 data(code==0),页面直接使用返回值。
|
||
*
|
||
* 约定:
|
||
* - postJSON 用于 @RequestBody 接口;postForm 用于 @RequestParam 接口(表单提交)。
|
||
*/
|
||
|
||
const BASE = "/api/base";
|
||
const FILE = "/api/file";
|
||
const TIMETABLE = "/api/timetable";
|
||
const SETTING = "/api/setting";
|
||
|
||
/** GET 请求,T 为返回数据类型 */
|
||
function get<T = any>(url: string, params?: Record<string, any>): Method<T> {
|
||
return new Method<T>("GET", alovaInstance, url, { params });
|
||
}
|
||
|
||
/** POST JSON body(与后端 @RequestBody 对齐),T 为返回数据类型 */
|
||
function postJSON<T = any>(url: string, data?: Record<string, any> | any[]): Method<T> {
|
||
return new Method<T>(
|
||
"POST",
|
||
alovaInstance,
|
||
url,
|
||
{ headers: { "Content-Type": "application/json;charset=UTF-8" } },
|
||
data ? JSON.stringify(data) : undefined
|
||
);
|
||
}
|
||
|
||
/** POST 表单(与后端 @RequestParam 对齐,application/x-www-form-urlencoded),T 为返回数据类型 */
|
||
function postForm<T = any>(url: string, data?: Record<string, any>): Method<T> {
|
||
const pairs = data ? Object.entries(data).filter(([, v]) => v !== undefined && v !== null) : [];
|
||
const form = pairs.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`).join("&");
|
||
// 只发 body,不拼 URL query:Spring @RequestParam 会把 query 与 body 同名值以逗号合并(单值变 "X,X" 直接 500)
|
||
return new Method<T>(
|
||
"POST",
|
||
alovaInstance,
|
||
url,
|
||
{ headers: { "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8" } },
|
||
form || undefined
|
||
);
|
||
}
|
||
|
||
/** 附件下载直链(浏览器 location.href 跳转) */
|
||
function fileDownUrl(fileId: number): string {
|
||
return `${conf.serviceHost}${FILE}/Down?id=${fileId}`;
|
||
}
|
||
|
||
/** 附件在线预览直链(照片课表展示用) */
|
||
export function filePreviewUrl(fileId: number): string {
|
||
return `${conf.serviceHost}${FILE}/Preview?id=${fileId}`;
|
||
}
|
||
|
||
/** 照片课表上传地址(FormData 字段名 file) */
|
||
export function fileUploadUrl(): string {
|
||
return `${conf.serviceHost}${FILE}/Upload`;
|
||
}
|
||
|
||
/** 年级照片课表打包下载地址(ZIP,条目按年级+班级名命名;前端 fetch 取 Blob 后落盘) */
|
||
export function gradePhotoZipUrl(gradeName: string): string {
|
||
return `${conf.serviceHost}${TIMETABLE}/DownloadGradePhotos?gradeName=${encodeURIComponent(gradeName)}`;
|
||
}
|
||
|
||
/** 课表导入模板下载地址(按班级年级生效节次模板生成 xlsx) */
|
||
export function timetableImportTemplateUrl(classId: number): string {
|
||
return `${conf.serviceHost}${TIMETABLE}/ImportTemplate?classId=${classId}`;
|
||
}
|
||
|
||
/** 班级电子课表导出地址(xlsx,当前学年学期) */
|
||
export function timetableExportUrl(classId: number): string {
|
||
return `${conf.serviceHost}${TIMETABLE}/Export?classId=${classId}`;
|
||
}
|
||
|
||
/** 课表导入上传地址(FormData:classId + file,整表替换该班当前课表) */
|
||
export function timetableImportUrl(): string {
|
||
return `${conf.serviceHost}${TIMETABLE}/Import`;
|
||
}
|
||
|
||
class BaseApi {
|
||
// ========== 用户信息 & 模块权限 ==========
|
||
/** 获取当前登录用户信息 */
|
||
getUserInfo() {
|
||
return get<UserInfoVo>(`${BASE}/GetUserInfo`);
|
||
}
|
||
/** 获取当前用户已授权的模块列表 */
|
||
getUserMod() {
|
||
return get<ModNode[]>(`${BASE}/GetUserMod`);
|
||
}
|
||
/** 当前学校组织树(部门→教师) */
|
||
getSchoolAll() {
|
||
return get<any[]>(`${BASE}/GetSchoolAll`);
|
||
}
|
||
/** 年级→班级树(叶子=班级,附学生数;课程表按班级维护) */
|
||
getClassTree() {
|
||
return get<ClassTreeNode[]>(`${BASE}/GetClassTree`);
|
||
}
|
||
/** 端分离入口:切换当前视角(teacher / parent) */
|
||
setRole(as: "teacher" | "parent") {
|
||
return postJSON<{ role: string }>(`${BASE}/SetRole`, { as });
|
||
}
|
||
}
|
||
|
||
class SyllabusApi {
|
||
// ========== 电子课程表 ==========
|
||
/** 查询班级课程表(无数据时返回空节次,前端补默认 10 节) */
|
||
get(classId: number) {
|
||
return get<TimetableVo>(`${TIMETABLE}/Get`, { classId });
|
||
}
|
||
/** 整表保存电子课程表(全量替换节次),返回课表ID */
|
||
save(data: TimetableSaveRequest) {
|
||
return postJSON<number>(`${TIMETABLE}/Save`, data);
|
||
}
|
||
|
||
// ========== 照片课程表 ==========
|
||
/** 绑定/替换照片课表(fileId 为已上传附件ID) */
|
||
savePhoto(classId: number, fileId: number) {
|
||
return postForm<void>(`${TIMETABLE}/SavePhoto`, { classId, fileId });
|
||
}
|
||
/** 移除照片课表 */
|
||
removePhoto(classId: number) {
|
||
return postForm<void>(`${TIMETABLE}/RemovePhoto`, { classId });
|
||
}
|
||
|
||
// ========== 学科 ==========
|
||
/** 本校学科列表(学科下拉数据源;不可达时返回空列表) */
|
||
subjects() {
|
||
return get<SubjectVo[]>(`${TIMETABLE}/Subjects`);
|
||
}
|
||
|
||
// ========== 学年学期 ==========
|
||
/** 当前学年学期(课表按学年学期维护,页头展示用;班级服务不可达时报错) */
|
||
nowYearTerm() {
|
||
return get<NowYearTermVo>(`${TIMETABLE}/NowYearTerm`);
|
||
}
|
||
|
||
// ========== 排课情况 ==========
|
||
/** 全校排课情况汇总(每班电子版 / 照片版编排状态,按年级→班级排序) */
|
||
overview() {
|
||
return get<TimetableOverviewVo[]>(`${TIMETABLE}/Overview`);
|
||
}
|
||
|
||
// ========== 我的课表(按角色过滤的只读视图) ==========
|
||
/** 可查看班级列表 + 身份标识(管理员/班主任/任教老师,前端按身份切换视图) */
|
||
myClasses() {
|
||
return get<MyClassesVo>(`${TIMETABLE}/MyClasses`);
|
||
}
|
||
/** 班级课表(权限校验;任教老师只返回任教科目格) */
|
||
myGet(classId: number) {
|
||
return get<MyTimetableVo>(`${TIMETABLE}/MyGet`, { classId });
|
||
}
|
||
|
||
// ========== 应用设置(时段判定 + 节次模板) ==========
|
||
/** 查询本校应用设置(时间设置 + 全部节次模板含行) */
|
||
getSetting() {
|
||
return get<SettingGetVo>(`${SETTING}/Get`);
|
||
}
|
||
/**
|
||
* 保存时段判定时间设置(四边界 HH:mm 依次递增)。
|
||
* 页面已无调用:启用时段与节次/课间时长自 2026-10-12 起随模板保存(见 saveTemplate),
|
||
* 界面也不再维护四个边界;保留此方法仅为后端接口仍然可用。
|
||
*/
|
||
saveTimeSetting(data: TimeSettingVo) {
|
||
return postJSON<void>(`${SETTING}/SaveTime`, data);
|
||
}
|
||
/** 新建/更新节次模板(全量替换行),返回模板ID */
|
||
saveTemplate(data: TemplateSaveRequest) {
|
||
return postJSON<number>(`${SETTING}/SaveTemplate`, data);
|
||
}
|
||
/** 删除节次模板(连带行) */
|
||
deleteTemplate(id: number) {
|
||
return postForm<void>(`${SETTING}/DeleteTemplate`, { id });
|
||
}
|
||
/** 保存节次模板的「显示全部/只显示节次」偏好(绑定模板记忆,预览课表/我的课表同随此值) */
|
||
saveTemplateShowBreakRows(id: number, showBreakRows: boolean) {
|
||
return postForm<void>(`${SETTING}/SaveTemplateShowBreakRows`, { id, showBreakRows });
|
||
}
|
||
/** 保存节次模板的「节次名称 显示/隐藏」偏好(绑定模板记忆,预览课表/我的课表同随此值) */
|
||
saveTemplateShowPeriodName(id: number, showPeriodName: boolean) {
|
||
return postForm<void>(`${SETTING}/SaveTemplateShowPeriodName`, { id, showPeriodName });
|
||
}
|
||
/** 课表编辑页生效设置:时间边界 + 当前学期下指定年级启用模板的行(term 1=上学期 2=下学期) */
|
||
effectiveForGrade(gradeName: string, term?: number) {
|
||
return get<EffectiveSettingVo>(`${SETTING}/ForGrade`, { gradeName, term });
|
||
}
|
||
/** 年级设置列表(启用 + 使用电子版/照片版;未配置的年级默认全启用) */
|
||
gradeSettings() {
|
||
return get<GradeSettingVo[]>(`${SETTING}/Grades`);
|
||
}
|
||
/** 批量保存年级设置(按年级名 upsert;作用于「我的课表」电子/照片视图切换) */
|
||
saveGradeSettings(data: GradeSettingVo[]) {
|
||
return postJSON<void>(`${SETTING}/SaveGrades`, data);
|
||
}
|
||
|
||
// ========== 附件 ==========
|
||
fileDownUrl = fileDownUrl;
|
||
}
|
||
|
||
export const baseApi = new BaseApi();
|
||
export const syllabusApi = new SyllabusApi();
|
||
export type { UpFileResultVo };
|
||
export default syllabusApi;
|