feat(meeting): 添加通过作业ID查询学生详细信息功能

- 在MeetingController中新增getStudentDetails方法,支持通过作业ID查询学生信息
- 添加StudentDetailResponseDto和StudentListResponseDto数据传输对象
- 实现getStudentDetailsByHomeworkId服务方法,支持长短ID映射和自动分配
- 优化SQL查询逻辑,支持批量插入缺失的短ID
- 添加相应的API文档注解和参数验证
This commit is contained in:
2026-03-14 14:52:18 +08:00
parent b04877be8d
commit ff6dde5f4d
3 changed files with 160 additions and 3 deletions

View File

@ -5,6 +5,28 @@ import { EntityManager } from '@mikro-orm/core';
import type { TokenResponseDto } from './meeting.dto';
import { MeetingUser } from '@/entities/MeetingUser';
/**
* 学生信息接口
*/
export interface StudentInfo {
/** 学生 ID */
studentId: number;
/** 学生姓名 */
studentName: string;
}
/**
* 学生详细信息接口 (包含长短 ID)
*/
export interface StudentDetailInfo {
/** 学生长 ID (数据库 ID) */
longId: number;
/** 学生短 ID (声网短 ID) */
shortId: number;
/** 学生姓名 */
studentName: string;
}
@Injectable()
export class MeetingService {
constructor(
@ -12,6 +34,96 @@ export class MeetingService {
private readonly nacosConfig: NacosConfigService
) {}
/**
* 通过作业 ID 获取学生详细信息列表 (包含长短 ID)
* @param homeworkId - 作业 ID
* @returns 学生详细信息列表,包含长 ID、短 ID 和姓名
*/
public async getStudentDetailsByHomeworkId(homeworkId: number): Promise<StudentDetailInfo[]> {
const id = Number(homeworkId);
if (!Number.isFinite(id) || id <= 0) {
return [];
}
// 查询学生信息并批量分配缺失的短 ID
const sql = `
SELECT u.Id AS longId, u.Name AS studentName, mu.id AS shortId
FROM icr_homework h
INNER JOIN scs_studentgroup sg ON h.StudentGroupId = sg.Id
INNER JOIN scs_studentgroupdetail sgd ON sg.Id = sgd.StudentGroupId
INNER JOIN scs_user u ON sgd.StudentId = u.Id
LEFT JOIN meeting_user mu ON u.Id = mu.longUserId
WHERE h.Id = ${id}
`;
const rows = await this.em.getConnection().execute(sql);
const results = rows as Array<{ longId: number | string; studentName: string; shortId: number | null }>;
// 批量插入缺失的短 ID
const missingIds = results.filter((row) => row.shortId === null).map((row) => Number(row.longId));
if (missingIds.length > 0) {
// 批量插入缺失的短 ID
await this.em.getConnection().execute(`
INSERT INTO meeting_user (longUserId, createdAt)
VALUES ${missingIds.map((longUserId) => `(${longUserId}, NOW())`).join(',')}
ON DUPLICATE KEY UPDATE longUserId = longUserId
`);
// 查询新分配的短 ID
const newUsers = await this.em.getConnection().execute(`
SELECT longUserId, id FROM meeting_user WHERE longUserId IN (${missingIds.join(',')})
`);
const shortIdMap = new Map<number, number>();
(newUsers as Array<{ longUserId: number; id: number }>).forEach((user) => {
shortIdMap.set(user.longUserId, user.id);
});
// 更新缺失的短 ID
results.forEach((row) => {
if (row.shortId === null) {
row.shortId = shortIdMap.get(Number(row.longId)) ?? null;
}
});
}
// 转换为最终结果
return results.map((row) => ({
longId: Number(row.longId),
studentName: row.studentName || '',
shortId: row.shortId ?? 0,
}));
}
/**
* 通过作业 ID 获取学生列表
* @param homeworkId - 作业 ID
* @returns 学生列表,包含学生 ID 和姓名
*/
public async getStudentsByHomeworkId(homeworkId: number): Promise<StudentInfo[]> {
const id = Number(homeworkId);
if (!Number.isFinite(id) || id <= 0) {
return [];
}
// 使用单条 SQL JOIN 查询 (性能最优)
const sql = `
SELECT
u.Id AS studentId,
u.Name AS studentName
FROM icr_homework h
INNER JOIN scs_studentgroup sg ON h.StudentGroupId = sg.Id
INNER JOIN scs_studentgroupdetail sgd ON sg.Id = sgd.StudentGroupId
INNER JOIN scs_user u ON sgd.StudentId = u.Id
WHERE h.Id = ${id}
`;
const rows = await this.em.getConnection().execute(sql);
return (rows as Array<{ studentId: number | string; studentName: string }>).map((row) => ({
studentId: Number(row.studentId),
studentName: row.studentName || '',
}));
}
/**
* 通过作业 ID 查询老师的长 ID
* @param homeworkId - 作业 IDJoinRoomData.homeworkId