diff --git a/node_api/src/modules/meeting/meeting.controller.ts b/node_api/src/modules/meeting/meeting.controller.ts index 47fde9c..ab4c8f6 100644 --- a/node_api/src/modules/meeting/meeting.controller.ts +++ b/node_api/src/modules/meeting/meeting.controller.ts @@ -1,25 +1,14 @@ import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, ParseIntPipe, Post, Query } from '@nestjs/common'; -import { ApiParam, ApiProperty, ApiQuery, ApiTags } from '@nestjs/swagger'; +import { ApiParam, ApiQuery, ApiTags } from '@nestjs/swagger'; import { FailResult, OkResult } from '../../common/dto/result.dto'; import { MeetingService } from './meeting.service'; import { NonEmptyStringPipe } from '@/common/pipes/non-empty-string.pipe'; import { Uint32Pipe } from '@/common/pipes/uint32.pipe'; import { ApiCustomOkResponse } from '@/common/decorators/swagger.decorator'; -import { SaveStudentOrderDto, StudentDetailResponseDto, TokenResponseDto } from './meeting.dto'; +import { BlacklistUserDto, SaveStudentOrderDto, StudentDetailResponseDto, TokenResponseDto } from './meeting.dto'; import { MeetingRedisService } from '../websocket/meeting-redis.service'; import { MeetingWebSocketGateway } from '../websocket/meeting.websocket'; -/** - * 黑名单用户 DTO - */ -class BlacklistUserDto { - @ApiProperty({ description: '短 UID', example: 1001 }) - shortUid?: number; - - @ApiProperty({ description: '用户名称', example: '张三' }) - userName?: string; -} - /** * 会议控制器 * 处理会议相关的 API 请求 diff --git a/node_api/src/modules/meeting/meeting.dto.ts b/node_api/src/modules/meeting/meeting.dto.ts index 6dbc7d1..0e4a93e 100644 --- a/node_api/src/modules/meeting/meeting.dto.ts +++ b/node_api/src/modules/meeting/meeting.dto.ts @@ -1,5 +1,16 @@ import { ApiProperty } from '@nestjs/swagger'; +import { IsArray, IsNotEmpty, IsString } from 'class-validator'; +/** + * 黑名单用户 DTO + */ +export class BlacklistUserDto { + @ApiProperty({ description: '短 UID', example: 1001 }) + shortUid?: number; + + @ApiProperty({ description: '用户名称', example: '张三' }) + userName?: string; +} /** * Token 响应数据 DTO */ @@ -33,8 +44,12 @@ export class StudentDetailResponseDto { */ export class SaveStudentOrderDto { @ApiProperty({ description: '房间 ID', example: 'room_123' }) + @IsNotEmpty({ message: 'roomId 不能为空' }) + @IsString({ message: 'roomId 必须是字符串' }) roomId!: string; @ApiProperty({ description: '学生长 ID 数组 (按排序顺序)', example: [1234567890, 1234567891, 1234567892] }) + @IsNotEmpty({ message: 'studentLongIds 不能为空' }) + @IsArray({ message: 'studentLongIds 必须是数组' }) studentLongIds!: number[]; } diff --git a/src/api/meeting.ts b/src/api/meeting.ts index 322d874..4c62092 100644 --- a/src/api/meeting.ts +++ b/src/api/meeting.ts @@ -49,6 +49,18 @@ export function getStudentDetailsAxios(homeworkId: number, roomId: string): Prom }); } +/** + * 保存学生排序顺序 + * @param roomId - 房间 ID + * @param studentLongIds - 学生长 ID 数组 (按排序顺序) + */ +export function saveStudentOrderAxios(roomId: string, studentLongIds: number[]): Promise> { + return axios.post>(`${import.meta.env.VITE_MEETING_BASE_URL}/meeting/student-order`, { + roomId, + studentLongIds, + }); +} + /** * 黑名单用户项 (包含短 UID 和名称) */ diff --git a/src/views/meeting/meeting-room/meeting-room-teacher.vue b/src/views/meeting/meeting-room/meeting-room-teacher.vue index edea6fc..b107c51 100644 --- a/src/views/meeting/meeting-room/meeting-room-teacher.vue +++ b/src/views/meeting/meeting-room/meeting-room-teacher.vue @@ -627,7 +627,8 @@ } try { const result = await getStudentDetailsAxios(homeworkId.value, roomId.value); - if (result.data) { + // 现在后端直接返回数组,不再包装在 data.students 中 + if (result.data && Array.isArray(result.data)) { studentListForSort.value = result.data; studentSortDialogVisible.value = true; } diff --git a/src/views/meeting/meeting-room/student-sort-dialog.vue b/src/views/meeting/meeting-room/student-sort-dialog.vue index 83cb3be..802ecb0 100644 --- a/src/views/meeting/meeting-room/student-sort-dialog.vue +++ b/src/views/meeting/meeting-room/student-sort-dialog.vue @@ -1,22 +1,15 @@