@@ -0,0 +1,186 @@
|
||||
import { Method } from "alova";
|
||||
import { alovaInstance } from "@/utils/alova/alova-iview";
|
||||
import conf from "@/assets/config/host.config";
|
||||
import type {
|
||||
ClassTreeNode,
|
||||
EffectiveSettingVo,
|
||||
ModNode,
|
||||
MyClassVo,
|
||||
MyTimetableVo,
|
||||
NowYearTermVo,
|
||||
SettingGetVo,
|
||||
SubjectVo,
|
||||
TemplateSaveRequest,
|
||||
TimeSettingVo,
|
||||
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 接口(表单提交)。
|
||||
* - postForm 同时把参数拼到 URL query:后端 @RequestParam 都收得到,且本地
|
||||
* vite-plugin-mock 不解析 urlencoded body,靠 query 才能拿到参数(不影响线上)。
|
||||
*/
|
||||
|
||||
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("&");
|
||||
// B1 修复:mock 只解析 query,故仅 mock 模式把参数拼进 URL;真后端只发 body,
|
||||
// 否则 Spring @RequestParam 会把 query 与 body 同名值以逗号合并(单值变 "X,X"、数字变 "1,1" 直接 500)。
|
||||
const fullUrl = conf.isMock && form ? `${url}${url.includes("?") ? "&" : "?"}${form}` : url;
|
||||
return new Method<T>(
|
||||
"POST",
|
||||
alovaInstance,
|
||||
fullUrl,
|
||||
{ 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`;
|
||||
}
|
||||
|
||||
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`);
|
||||
}
|
||||
|
||||
// ========== 我的课表(按角色过滤的只读视图) ==========
|
||||
/** 可查看班级列表(管理员/校领导=全部;班主任=所带;任教=任教班级) */
|
||||
myClasses() {
|
||||
return get<MyClassVo[]>(`${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 });
|
||||
}
|
||||
/** 课表编辑页生效设置:时间边界 + 当前学期下指定年级启用模板的行(term 1=上学期 2=下学期) */
|
||||
effectiveForGrade(gradeName: string, term?: number) {
|
||||
return get<EffectiveSettingVo>(`${SETTING}/ForGrade`, { gradeName, term });
|
||||
}
|
||||
|
||||
// ========== 附件 ==========
|
||||
fileDownUrl = fileDownUrl;
|
||||
}
|
||||
|
||||
export const baseApi = new BaseApi();
|
||||
export const syllabusApi = new SyllabusApi();
|
||||
export type { UpFileResultVo };
|
||||
export default syllabusApi;
|
||||
Reference in New Issue
Block a user