学生端-导师测评

parent be3831af
...@@ -45,12 +45,17 @@ export async function initialAssignStudents(param: any) { ...@@ -45,12 +45,17 @@ export async function initialAssignStudents(param: any) {
// 如果原匹配未完成的任务,新导师需要重新完成 // 如果原匹配未完成的任务,新导师需要重新完成
} }
// 获取学生班级ID
let studentProfile = await selectOneDataByParam(TABLENAME.用户扩展信息表, { user_id: studentId }, ["class_id"]);
let class_id = studentProfile.data?.class_id || null;
// 创建新的匹配 // 创建新的匹配
await addData(TABLENAME.师生匹配表, { await addData(TABLENAME.师生匹配表, {
id: randomId(TABLEID.师生匹配表), id: randomId(TABLEID.师生匹配表),
student_id: studentId, student_id: studentId,
teacher_id: teacher_id, teacher_id: teacher_id,
semester_id: semester.id, semester_id: semester.id,
class_id: class_id,
match_type: MATCHTYPE.主动选择, match_type: MATCHTYPE.主动选择,
match_time: getMySqlMs(), match_time: getMySqlMs(),
is_active: true is_active: true
......
...@@ -287,6 +287,254 @@ export async function getInteractionDynamic(studentId: string) { ...@@ -287,6 +287,254 @@ export async function getInteractionDynamic(studentId: string) {
} }
/**
* 获取导师评价列表
* @param studentId 学生ID
* @param surveyName 测评标题(可选,模糊搜索)
* @param status 测评状态(可选,0=待测评 1=已测评)
*/
export async function getTeacherSurvey(studentId: string, surveyName?: string, status?: number) {
/**获取当前学期 */
let semester = await getCurrentSemester();
if (!semester) {
return [];
}
/**查当前学生的导师 */
let match = await selectOneDataByParam(TABLENAME.师生匹配表, {
student_id: studentId,
semester_id: semester.id,
is_active: true
});
if (!match.data) {
return [];
}
/**查测评活动列表 */
let surveyParam: any = {
semester_id: semester.id,
is_open: 1
};
let surveyList = await selectDataListByParam(TABLENAME.测评活动表, surveyParam);
if (!surveyList.data || surveyList.data.length === 0) {
return [];
}
let resultList = [];
for (let survey of surveyList.data) {
// 模糊搜索测评标题
if (surveyName && !survey.name.includes(surveyName)) {
continue;
}
// 查是否已提交
let submission = await selectOneDataByParam(TABLENAME.测评提交表, {
survey_id: survey.id,
student_id: studentId
});
let surveyStatus = submission.data && (submission.data as any).id ? 1 : 0;
// 按状态筛选
if (status !== undefined && status !== null && surveyStatus !== status) {
continue;
}
resultList.push({
survey_id: survey.id,
name: survey.name,
start_time: survey.start_time,
end_time: survey.end_time,
status: surveyStatus
});
}
return resultList;
}
/**
* 获取测评详情
* @param studentId 学生ID
* @param surveyId 测评活动ID
*/
export async function surveyInfo(studentId: string, surveyId: number) {
/**查测评活动 */
let survey = await selectOneDataByParam(TABLENAME.测评活动表, { id: surveyId });
if (!survey.data || !(survey.data as any).id) {
throw new BizError(ERRORENUM.未找到数据, '测评不存在');
}
/**查题目列表(按排序号升序) */
let questions = await selectDataListByParam(TABLENAME.测评题目表, {
survey_id: surveyId,
"%orderAsc%": "sort_order"
});
/**查是否已提交 */
let submission = await selectOneDataByParam(TABLENAME.测评提交表, {
survey_id: surveyId,
student_id: studentId
});
let isSubmitted = !!(submission.data && (submission.data as any).id);
/**如果已提交,查答案 */
let answerMap: Map<number, any> = new Map();
if (isSubmitted) {
let answers = await selectDataListByParam(TABLENAME.测评答案表, {
submission_id: (submission.data as any).id
});
for (let ans of answers.data) {
answerMap.set(ans.question_id, ans);
}
}
/**组装题目列表 */
let questionList = (questions.data || []).map((q: any) => {
let answer = null;
let ansRecord = answerMap.get(q.id);
if (ansRecord) {
if (q.question_type === 'text') {
answer = ansRecord.answer_text;
} else {
answer = ansRecord.answer_option_keys;
}
}
return {
question_id: q.id,
question_code: q.question_code,
question_text: q.question_text,
question_type: q.question_type,
options: q.options,
is_required: q.is_required,
sort_order: q.sort_order,
answer: answer
};
});
return {
surveyInfo: {
survey_id: survey.data.id,
name: (survey.data as any).name,
description: (survey.data as any).description,
start_time: (survey.data as any).start_time,
end_time: (survey.data as any).end_time,
is_submitted: isSubmitted
},
questions: questionList
};
}
/**
* 提交导师测评
* @param studentId 学生ID(测评人)
* @param surveyId 测评活动ID
* @param answers 答案数组,格式:[{"1":"[\"A\",\"B\"]"},{"2":"无"}]
*/
export async function surveyTeacher(studentId: string, surveyId: number, answers: object[]) {
/**获取当前学期 */
let semester = await getCurrentSemester();
if (!semester) {
throw new BizError(ERRORENUM.操作失败, '当前没有进行中的学期');
}
/**校验测评存在且开放 */
let survey = await selectOneDataByParam(TABLENAME.测评活动表, { id: surveyId });
if (!survey.data || !(survey.data as any).id) {
throw new BizError(ERRORENUM.未找到数据, '测评不存在');
}
let surveyData = survey.data as any;
if (!surveyData.is_open) {
throw new BizError(ERRORENUM.操作不允许, '测评未开放');
}
/**校验答题时间 */
let now = getMySqlMs();
if (surveyData.start_time && now < surveyData.start_time) {
throw new BizError(ERRORENUM.操作不允许, '测评尚未开始');
}
if (surveyData.end_time && now > surveyData.end_time) {
throw new BizError(ERRORENUM.操作不允许, '测评已结束');
}
/**防重复提交 */
let existSubmission = await selectOneDataByParam(TABLENAME.测评提交表, {
survey_id: surveyId,
student_id: studentId
});
if (existSubmission.data && (existSubmission.data as any).id) {
throw new BizError(ERRORENUM.重复操作, '您已提交过该测评,不可重复提交');
}
/**获取当前导师 */
let match = await selectOneDataByParam(TABLENAME.师生匹配表, {
student_id: studentId,
semester_id: semester.id,
is_active: true
});
if (!match.data) {
throw new BizError(ERRORENUM.未找到数据, '您当前没有导师');
}
let teacherId = (match.data as any).teacher_id;
/**创建提交记录 */
let submission = await addData(TABLENAME.测评提交表, {
survey_id: surveyId,
student_id: studentId,
teacher_id: teacherId,
submit_time: getMySqlMs()
});
let submissionId = (submission as any).data?.id;
if (!submissionId) {
// 自增ID需要重新查
let newSub = await selectOneDataByParam(TABLENAME.测评提交表, {
survey_id: surveyId,
student_id: studentId
});
submissionId = (newSub.data as any).id;
}
/**遍历答案并保存 */
for (let answerItem of answers) {
for (let key in answerItem) {
let questionId = parseInt(key);
let rawValue = (answerItem as any)[key];
// 解析答案值(JSON字符串)
let parsedValue: any;
try {
parsedValue = JSON.parse(rawValue);
} catch (e) {
parsedValue = rawValue;
}
// 查题目类型
let question = await selectOneDataByParam(TABLENAME.测评题目表, { id: questionId });
if (!question.data || !(question.data as any).id) {
continue; // 题目不存在则跳过
}
let questionType = (question.data as any).question_type;
// 根据题目类型保存答案
let answerData: any = {
submission_id: submissionId,
question_id: questionId
};
if (questionType === 'text') {
answerData.answer_text = typeof parsedValue === 'string' ? parsedValue : JSON.stringify(parsedValue);
} else {
answerData.answer_option_keys = Array.isArray(parsedValue) ? parsedValue : [parsedValue];
}
await addData(TABLENAME.测评答案表, answerData);
}
}
return { isSuccess: true };
}
......
...@@ -207,11 +207,16 @@ export async function selectTeacher(studentId: string, teacherId: string) { ...@@ -207,11 +207,16 @@ export async function selectTeacher(studentId: string, teacherId: string) {
throw new BizError(ERRORENUM.操作失败, '该导师名额已满'); throw new BizError(ERRORENUM.操作失败, '该导师名额已满');
} }
/**获取学生班级ID */
let studentProfile = await selectOneDataByParam(TABLENAME.用户扩展信息表, { user_id: studentId }, ["class_id"]);
let class_id = studentProfile.data?.class_id || null;
/**创建匹配 */ /**创建匹配 */
await addData(TABLENAME.师生匹配表, { await addData(TABLENAME.师生匹配表, {
student_id: studentId, student_id: studentId,
teacher_id: teacherId, teacher_id: teacherId,
semester_id: semester.id, semester_id: semester.id,
class_id: class_id,
match_type: MATCHTYPE.主动选择, match_type: MATCHTYPE.主动选择,
match_time: getMySqlMs(), match_time: getMySqlMs(),
is_active: true is_active: true
......
...@@ -150,6 +150,296 @@ export async function teacherUpdate(teacherId: string, param: any) { ...@@ -150,6 +150,296 @@ export async function teacherUpdate(teacherId: string, param: any) {
} }
/**
* 查询学生历年导师(基于师生匹配表的历史记录)
* 场景:班主任查看本班学生历史上匹配过的所有导师
*
* @param classId 班级ID(由班主任中间件注入)
* @param studentId 学生ID(可选,查单个学生;不传则查全班学生)
* @param semesterId 学期ID(可选,筛选特定学期)
* @param page 页码
* @param pageSize 每页大小
*/
export async function getHistoryTeacher(classId: number, params: {
studentId?: string;
semesterId?: number;
page?: number;
pageSize?: number;
}) {
let { studentId, semesterId, page = 1, pageSize = 10 } = params;
/**1. 查本班所有学生 */
let studentQueryParam: any = {
class_id: classId,
roles: { "%like%": "3" }
};
if (studentId) {
studentQueryParam.user_id = studentId;
}
let students = await selectDataListByParam(TABLENAME.用户扩展信息表, studentQueryParam);
if (!students.data || students.data.length === 0) {
return { count: 0, totalPages: 0, dataList: [] };
}
let studentIds = students.data.map((s: any) => s.user_id);
/**2. 查询这些学生在所有学期的匹配记录(包括 is_active=true 和 false) */
let matchParam: any = {
student_id: { "%in%": studentIds }
};
if (semesterId) {
matchParam.semester_id = semesterId;
}
let allMatches = await selectDataListByParam(TABLENAME.师生匹配表, matchParam);
if (!allMatches.data || allMatches.data.length === 0) {
return { count: 0, totalPages: 0, dataList: [] };
}
/**3. 收集去重的 semester_id 和 teacher_id */
let semesterIdSet = new Set<number>();
let teacherIdSet = new Set<string>();
for (let m of allMatches.data) {
semesterIdSet.add(m.semester_id);
teacherIdSet.add(m.teacher_id);
}
/**4. 批量查学期信息 */
let semesterMap = new Map<number, string>();
if (semesterIdSet.size > 0) {
let semesterList = await selectDataListByParam(TABLENAME.学期表, {
id: { "%in%": [...semesterIdSet] }
});
for (let s of semesterList.data) {
semesterMap.set(s.id, s.name);
}
}
/**5. 批量查导师基础信息(姓名、性别) */
let teacherMap = new Map<string, { teacherName: string; gender: string }>();
if (teacherIdSet.size > 0) {
let teacherList = await selectDataListByParam(TABLENAME.统一用户表, {
user_id: { "%in%": [...teacherIdSet] }
});
for (let t of teacherList.data) {
teacherMap.set(t.user_id, { teacherName: t.user_name, gender: t.gender || "" });
}
}
/**6. 批量查导师扩展信息(政治面貌) */
let teacherProfileMap = new Map<string, string>();
if (teacherIdSet.size > 0) {
let teacherProfileList = await selectDataListByParam(TABLENAME.用户扩展信息表, {
user_id: { "%in%": [...teacherIdSet] }
});
for (let p of teacherProfileList.data) {
teacherProfileMap.set(p.user_id, p.political_status || "");
}
}
/**7. 批量查导师任教科目(按学期,所有相关学期) */
let teacherSubjectMap = new Map<string, string>(); // key: "teacherId_semesterId"
if (teacherIdSet.size > 0 && semesterIdSet.size > 0) {
let subjectList = await selectDataListByParam(TABLENAME.教师任教科目表, {
teacher_id: { "%in%": [...teacherIdSet] },
semester_id: { "%in%": [...semesterIdSet] }
});
for (let s of subjectList.data) {
let key = `${s.teacher_id}_${s.semester_id}`;
let existing = teacherSubjectMap.get(key) || "";
teacherSubjectMap.set(key, existing ? existing + "、" + s.subject : s.subject);
}
}
/**8. 批量查学生姓名 */
let studentNameMap = new Map<string, string>();
if (studentIds.length > 0) {
let studentList = await selectDataListByParam(TABLENAME.统一用户表, {
user_id: { "%in%": studentIds }
});
for (let s of studentList.data) {
studentNameMap.set(s.user_id, s.user_name);
}
}
/**9. 组装返回数据,按学期+学生+导师分组 */
let dataList: any[] = [];
for (let m of allMatches.data) {
let teacherInfo = teacherMap.get(m.teacher_id);
let subjectKey = `${m.teacher_id}_${m.semester_id}`;
dataList.push({
match_id: m.id,
student_id: m.student_id,
student_name: studentNameMap.get(m.student_id) || "",
teacher_id: m.teacher_id,
teacher_name: teacherInfo ? teacherInfo.teacherName : "",
gender: teacherInfo ? teacherInfo.gender : "",
political_status: teacherProfileMap.get(m.teacher_id) || "",
subjects: teacherSubjectMap.get(subjectKey) || "",
semester_id: m.semester_id,
semester_name: semesterMap.get(m.semester_id) || "",
match_type: m.match_type,
match_time: m.match_time,
is_active: m.is_active
});
}
/**10. 排序(按学期倒序 + 匹配时间倒序) */
dataList.sort((a, b) => {
if (a.semester_id !== b.semester_id) return b.semester_id - a.semester_id;
return new Date(b.match_time).getTime() - new Date(a.match_time).getTime();
});
/**11. 分页 */
let total = dataList.length;
let totalPages = Math.ceil(total / pageSize);
let start = (page - 1) * pageSize;
let pagedList = dataList.slice(start, start + pageSize);
return {
count: total,
totalPages,
page,
pageSize,
dataList: pagedList
};
}
/**
* 查询单个学生历年导师(导师端使用)
* 导师查看自己名下某个学生历史上匹配过的所有导师
*
* @param studentId 学生ID
* @param params.semesterId 学期ID(可选)
* @param params.page 页码
* @param params.pageSize 每页大小
*/
export async function getHistoryTeacherForStudent(studentId: string, params: {
semesterId?: number;
page?: number;
pageSize?: number;
}) {
let { semesterId, page = 1, pageSize = 10 } = params;
/**1. 查询该学生在所有学期的匹配记录 */
let matchParam: any = { student_id: studentId };
if (semesterId) {
matchParam.semester_id = semesterId;
}
let allMatches = await selectDataListByParam(TABLENAME.师生匹配表, matchParam);
if (!allMatches.data || allMatches.data.length === 0) {
return { count: 0, totalPages: 0, dataList: [] };
}
/**2. 收集去重的 semester_id 和 teacher_id */
let semesterIdSet = new Set<number>();
let teacherIdSet = new Set<string>();
for (let m of allMatches.data) {
semesterIdSet.add(m.semester_id);
teacherIdSet.add(m.teacher_id);
}
/**3. 批量查学期信息 */
let semesterMap = new Map<number, string>();
if (semesterIdSet.size > 0) {
let semesterList = await selectDataListByParam(TABLENAME.学期表, {
id: { "%in%": [...semesterIdSet] }
});
for (let s of semesterList.data) {
semesterMap.set(s.id, s.name);
}
}
/**4. 批量查导师基础信息(姓名、性别) */
let teacherMap = new Map<string, { teacherName: string; gender: string }>();
if (teacherIdSet.size > 0) {
let teacherList = await selectDataListByParam(TABLENAME.统一用户表, {
user_id: { "%in%": [...teacherIdSet] }
});
for (let t of teacherList.data) {
teacherMap.set(t.user_id, { teacherName: t.user_name, gender: t.gender || "" });
}
}
/**5. 批量查导师扩展信息(政治面貌) */
let teacherProfileMap = new Map<string, string>();
if (teacherIdSet.size > 0) {
let teacherProfileList = await selectDataListByParam(TABLENAME.用户扩展信息表, {
user_id: { "%in%": [...teacherIdSet] }
});
for (let p of teacherProfileList.data) {
teacherProfileMap.set(p.user_id, p.political_status || "");
}
}
/**6. 批量查导师任教科目(按学期) */
let teacherSubjectMap = new Map<string, string>(); // key: "teacherId_semesterId"
if (teacherIdSet.size > 0 && semesterIdSet.size > 0) {
let subjectList = await selectDataListByParam(TABLENAME.教师任教科目表, {
teacher_id: { "%in%": [...teacherIdSet] },
semester_id: { "%in%": [...semesterIdSet] }
});
for (let s of subjectList.data) {
let key = `${s.teacher_id}_${s.semester_id}`;
let existing = teacherSubjectMap.get(key) || "";
teacherSubjectMap.set(key, existing ? existing + "、" + s.subject : s.subject);
}
}
/**7. 查学生姓名 */
let studentInfo = await selectOneDataByParam(TABLENAME.统一用户表, { user_id: studentId });
let studentName = studentInfo.data ? studentInfo.data.user_name : "";
/**8. 组装返回数据 */
let dataList: any[] = [];
for (let m of allMatches.data) {
let teacherInfo = teacherMap.get(m.teacher_id);
let subjectKey = `${m.teacher_id}_${m.semester_id}`;
dataList.push({
match_id: m.id,
student_id: m.student_id,
student_name: studentName,
teacher_id: m.teacher_id,
teacher_name: teacherInfo ? teacherInfo.teacherName : "",
gender: teacherInfo ? teacherInfo.gender : "",
political_status: teacherProfileMap.get(m.teacher_id) || "",
subjects: teacherSubjectMap.get(subjectKey) || "",
semester_id: m.semester_id,
semester_name: semesterMap.get(m.semester_id) || "",
match_type: m.match_type,
match_time: m.match_time,
is_active: m.is_active
});
}
/**9. 排序(按学期倒序 + 匹配时间倒序) */
dataList.sort((a, b) => {
if (a.semester_id !== b.semester_id) return b.semester_id - a.semester_id;
return new Date(b.match_time).getTime() - new Date(a.match_time).getTime();
});
/**10. 分页 */
let total = dataList.length;
let totalPages = Math.ceil(total / pageSize);
let start = (page - 1) * pageSize;
let pagedList = dataList.slice(start, start + pageSize);
return {
count: total,
totalPages,
page,
pageSize,
dataList: pagedList
};
}
......
...@@ -35,6 +35,12 @@ export enum TABLENAME { ...@@ -35,6 +35,12 @@ export enum TABLENAME {
消息已读表 = 'notification_read', 消息已读表 = 'notification_read',
用户登录日志表 = 'user_login_log', 用户登录日志表 = 'user_login_log',
角色切换日志表 = 'role_switch_log', 角色切换日志表 = 'role_switch_log',
// 测评相关
测评活动表 = 'survey',
测评题目表 = 'survey_question',
测评提交表 = 'survey_submission',
测评答案表 = 'survey_answer',
}; };
/** /**
...@@ -57,6 +63,12 @@ export enum TABLEID { ...@@ -57,6 +63,12 @@ export enum TABLEID {
消息已读表 = "NR", 消息已读表 = "NR",
用户登录日志表 = 'LOG', 用户登录日志表 = 'LOG',
角色切换日志表 = 'RSL', 角色切换日志表 = 'RSL',
// 测评相关
测评活动表 = 'SV',
测评题目表 = 'SQ',
测评提交表 = 'SS',
测评答案表 = 'SA',
}; };
...@@ -169,6 +169,7 @@ export const TablesConfig = [ ...@@ -169,6 +169,7 @@ export const TablesConfig = [
student_id: { type: DataTypes.STRING(20), allowNull: false, comment: '学生user_id' }, student_id: { type: DataTypes.STRING(20), allowNull: false, comment: '学生user_id' },
teacher_id: { type: DataTypes.STRING(20), allowNull: false, comment: '导师user_id' }, teacher_id: { type: DataTypes.STRING(20), allowNull: false, comment: '导师user_id' },
semester_id: { type: DataTypes.INTEGER, allowNull: false, comment: '学期ID,关联semester.id' }, semester_id: { type: DataTypes.INTEGER, allowNull: false, comment: '学期ID,关联semester.id' },
class_id: { type: DataTypes.INTEGER, comment: '班级ID,关联class.id' },
match_type: { type: DataTypes.ENUM('主动选择', '抢课分配'), allowNull: false, comment: '选择方式' }, match_type: { type: DataTypes.ENUM('主动选择', '抢课分配'), allowNull: false, comment: '选择方式' },
match_time: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW, comment: '匹配时间' }, match_time: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW, comment: '匹配时间' },
is_active: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: true, comment: '是否当前有效匹配' }, is_active: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: true, comment: '是否当前有效匹配' },
...@@ -480,7 +481,7 @@ export const TablesConfig = [ ...@@ -480,7 +481,7 @@ export const TablesConfig = [
submission_id: { type: DataTypes.INTEGER, allowNull: false, comment: '关联survey_submission.id' }, submission_id: { type: DataTypes.INTEGER, allowNull: false, comment: '关联survey_submission.id' },
question_id: { type: DataTypes.INTEGER, allowNull: false, comment: '关联survey_question.id' }, question_id: { type: DataTypes.INTEGER, allowNull: false, comment: '关联survey_question.id' },
answer_text: { type: DataTypes.TEXT, allowNull: true, comment: '文本答案,用于文本题(如建议)' }, answer_text: { type: DataTypes.TEXT, allowNull: true, comment: '文本答案,用于文本题(如建议)' },
answer_option_keys: { type: DataTypes.JSON, allowNull: true, comment: '选择题答案,单选存字符串如"A",多选存数组如["A","C","E"]' }, answer_option_keys: { type: DataTypes.JSON, allowNull: true, comment: '选择题答案,单选存字符串如["A"],多选存数组如["A","C","E"]' },
created_at: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW }, created_at: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW },
updated_at: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW } updated_at: { type: DataTypes.DATE, allowNull: false, defaultValue: DataTypes.NOW }
}, },
......
...@@ -8,6 +8,7 @@ import * as studentMatchBiz from '../biz/headteacher/studentMatch'; ...@@ -8,6 +8,7 @@ import * as studentMatchBiz from '../biz/headteacher/studentMatch';
import * as growthMessageSummaryBiz from '../biz/headteacher/growthMessageSummary'; import * as growthMessageSummaryBiz from '../biz/headteacher/growthMessageSummary';
import * as notificationBiz from '../biz/headteacher/notification'; import * as notificationBiz from '../biz/headteacher/notification';
import * as dashboardBiz from '../biz/headteacher/dashboard'; import * as dashboardBiz from '../biz/headteacher/dashboard';
import * as teacherInfoBiz from '../biz/teacher/teacherInfo';
import { checkUser, checkRole, checkClassTeacher } from '../middleware/user'; import { checkUser, checkRole, checkClassTeacher } from '../middleware/user';
import { USERROLE } from '../config/enum'; import { USERROLE } from '../config/enum';
import { eccReqParamater } from '../util/verificationParam'; import { eccReqParamater } from '../util/verificationParam';
...@@ -46,6 +47,10 @@ export function setRouter(httpServer) { ...@@ -46,6 +47,10 @@ export function setRouter(httpServer) {
/** 获取未读消息通知数量 - notification.ts */ /** 获取未读消息通知数量 - notification.ts */
httpServer.post('/api/headteacher/notification/unread/count', checkUser, checkClassTeacher(), asyncHandler(getUnreadNotificationCount)); httpServer.post('/api/headteacher/notification/unread/count', checkUser, checkClassTeacher(), asyncHandler(getUnreadNotificationCount));
// ===== 历史导师 =====
/** 查看本班学生历年导师 - teacherInfo.ts */
httpServer.post('/api/headteacher/history/teacher', checkUser, checkClassTeacher(), asyncHandler(getHistoryTeacherForClass));
// ===== 数据看板 ===== // ===== 数据看板 =====
/** 班主任首页数据 - dashboard.ts */ /** 班主任首页数据 - dashboard.ts */
httpServer.post('/api/headteacher/dashboard', checkUser, checkClassTeacher(), asyncHandler(headteacherDashboard)); httpServer.post('/api/headteacher/dashboard', checkUser, checkClassTeacher(), asyncHandler(headteacherDashboard));
...@@ -260,5 +265,31 @@ async function headteacherDashboard(req, res) { ...@@ -260,5 +265,31 @@ async function headteacherDashboard(req, res) {
res.success(result); res.success(result);
} }
/**
* 查看本班学生历年导师(班主任端)
* 班主任查看本班所有学生在各个学期匹配过的导师
*
* @param studentId 学生ID(可选,查单个学生;不传则查全班)
* @param semesterId 学期ID(可选,筛选特定学期)
* @param page 页码
* @param pageSize 每页大小
*/
async function getHistoryTeacherForClass(req, res) {
const userInfo = req.userInfo;
const classInfo = req.classInfo; // checkClassTeacher 中间件注入的班级信息
let reqConf = { studentId: 'String', semesterId: 'Number', page: 'Number', pageSize: 'Number' };
const NotMustHaveKeys = ['studentId', 'semesterId', 'page', 'pageSize'];
let { studentId, semesterId, page, pageSize } = eccReqParamater(reqConf, req.body, NotMustHaveKeys);
let result = await teacherInfoBiz.getHistoryTeacher(classInfo.classId, {
studentId: studentId || undefined,
semesterId: semesterId || undefined,
page: page || 1,
pageSize: pageSize || 10
});
res.success(result);
}
...@@ -37,6 +37,11 @@ export function setRouter(httpServer) { ...@@ -37,6 +37,11 @@ export function setRouter(httpServer) {
/** 获取互动动态列表 - myTeacher.ts */ /** 获取互动动态列表 - myTeacher.ts */
httpServer.post('/api/student/interaction/dynamic', checkUser, checkRole(USERROLE.学生), asyncHandler(getInteractionDynamic)); httpServer.post('/api/student/interaction/dynamic', checkUser, checkRole(USERROLE.学生), asyncHandler(getInteractionDynamic));
/** 导师评价&测评 - myTeacher.ts */
httpServer.post('/api/student/teacher/survey', checkUser, checkRole(USERROLE.学生), asyncHandler(getTeacherSurvey));
httpServer.post('/api/student/survey/info', checkUser, checkRole(USERROLE.学生), asyncHandler(surveyInfo));
httpServer.post('/api/student/survey/teacher', checkUser, checkRole(USERROLE.学生), asyncHandler(surveyTeacher));
// ===== 预约管理 ===== // ===== 预约管理 =====
/** 未读预约数量 - appointment.ts */ /** 未读预约数量 - appointment.ts */
...@@ -171,6 +176,48 @@ async function getInteractionDynamic(req, res) { ...@@ -171,6 +176,48 @@ async function getInteractionDynamic(req, res) {
} }
/** /**
* 获取导师评价列表
*/
async function getTeacherSurvey(req, res) {
const userInfo = req.userInfo;
let reqConf = {surveyName:'String', status: "Number"};
const NotMustHaveKeys = ['surveyName', 'status'];
let { surveyName, status } = eccReqParamater(reqConf, req.body, NotMustHaveKeys);
let result = await myTeacherBiz.getTeacherSurvey(userInfo.userId, surveyName, status);
res.success({ dataList: result });
}
/**
* 测评详情
* @param req
* @param res
*/
async function surveyInfo(req, res) {
const userInfo = req.userInfo;
let reqConf = {surveyId:'Number'};
const NotMustHaveKeys = [];
let { surveyId } = eccReqParamater(reqConf, req.body, NotMustHaveKeys);
let result = await myTeacherBiz.surveyInfo(userInfo.userId, surveyId);
res.success(result);
}
/**
* 导师测评
*/
async function surveyTeacher(req, res) {
const userInfo = req.userInfo;
let reqConf = {surveyId:'Number', answers: '[Object]'};
const NotMustHaveKeys = [];
let { surveyId, answers } = eccReqParamater(reqConf, req.body, NotMustHaveKeys);
let result = await myTeacherBiz.surveyTeacher(userInfo.userId, surveyId, answers);
res.success(result);
}
/**
* 未读预约数量 * 未读预约数量
*/ */
async function getUnreadAppointmentCount(req, res) { async function getUnreadAppointmentCount(req, res) {
......
...@@ -923,12 +923,25 @@ async function teacherUpdate(req, res) { ...@@ -923,12 +923,25 @@ async function teacherUpdate(req, res) {
} }
/** /**
* 学生历年导师列表 * 学生历年导师列表(导师端查看单个学生的历史导师)
* @param req * @param studentId 学生ID
* @param res * @param semesterId 学期ID(可选)
* @param page 页码
* @param pageSize 每页大小
*/ */
async function getHistoryTeacher(req, res) { async function getHistoryTeacher(req, res) {
const userInfo = req.userInfo;
let reqConf = { studentId: 'String', semesterId: 'Number', page: 'Number', pageSize: 'Number' };
const NotMustHaveKeys = ['semesterId', 'page', 'pageSize'];
let { studentId, semesterId, page, pageSize } = eccReqParamater(reqConf, req.body, NotMustHaveKeys);
let result = await teacherInfoBiz.getHistoryTeacherForStudent(studentId, {
semesterId: semesterId || undefined,
page: page || 1,
pageSize: pageSize || 10
});
res.success(result);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment