chore: 初始化项目基础结构和资源文件

- 添加项目图标文件(app-icon.png、各平台图标)
- 配置开发环境文件(.env、.nvmrc、.npmrc)
- 添加静态资源文件(背景图片、字体、音频)
- 初始化Tauri后端结构(build.rs、main.rs、模块文件)
- 配置前端项目结构(TypeScript、Vue组件、样式)
- 添加Node.js API服务基础结构
- 配置构建和开发工具(vite、prettier、gitignore)
This commit is contained in:
2026-03-13 10:03:05 +08:00
commit 78af453fe1
357 changed files with 70605 additions and 0 deletions

View File

@ -0,0 +1,92 @@
import { Controller, Delete, Get, HttpCode, HttpStatus, Param } from '@nestjs/common';
import { ApiParam, ApiProperty, 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 { TokenResponseDto } from './meeting.dto';
import { MeetingRedisService } from '../websocket/meeting-redis.service';
/**
* 黑名单用户 DTO
*/
class BlacklistUserDto {
@ApiProperty({ description: '短 UID', example: 1001 })
shortUid?: number;
@ApiProperty({ description: '用户名称', example: '张三' })
userName?: string;
}
/**
* 会议控制器
* 处理会议相关的 API 请求
*/
@ApiTags('Meeting')
@Controller('meeting')
export class MeetingController {
public constructor(
private readonly meetingService: MeetingService,
private readonly redis: MeetingRedisService
) {}
/**
* 生成声网 RTC Token
*/
@Get('get-token/:channelName/:uid')
@HttpCode(HttpStatus.OK)
@ApiCustomOkResponse({
summary: '声网 RTC Token',
model: TokenResponseDto,
apiDescription: '声网 RTC Token 信息',
resDescription: '声网 RTC Token 信息包含appid',
})
@ApiParam({ name: 'channelName', description: '需要加入的频道名(格式: `n_课程名称`)', example: 'n_1234567890' })
@ApiParam({ name: 'uid', description: '用户的短 UID(0~4294967295)', example: '1001' })
public async getToken(@Param('channelName', new NonEmptyStringPipe('channelName')) channelName: string, @Param('uid', new Uint32Pipe('uid')) uid: number) {
const result = this.meetingService.generateToken(channelName, uid);
if (!result) {
return new FailResult('生成 Token 失败');
}
return new OkResult(result);
}
/**
* 查询房间黑名单(包含短 UID 和名称的数组)
*/
@Get('blacklist/:roomId')
@HttpCode(HttpStatus.OK)
@ApiParam({ name: 'roomId', description: '服务端房间 IDSocket.IO 房间名)' })
@ApiCustomOkResponse({
summary: '房间黑名单',
model: [BlacklistUserDto],
apiDescription: '房间黑名单(包含短 UID 和名称的数组)',
resDescription: '房间黑名单(包含短 UID 和名称的数组)',
})
public async getBlacklist(@Param('roomId', new NonEmptyStringPipe('roomId')) roomId: string) {
const list = await this.redis.getBlacklist(roomId);
return new OkResult(list);
}
/**
* 从房间黑名单移除指定用户(短 UID
*/
@Delete('blacklist/:roomId/:shortUid')
@HttpCode(HttpStatus.OK)
@ApiParam({ name: 'roomId', description: '服务端房间 IDSocket.IO 房间名)' })
@ApiParam({ name: 'shortUid', description: '用户短 UID', example: '1001' })
@ApiCustomOkResponse({
summary: '从房间黑名单移除用户',
model: Boolean,
apiDescription: '从房间黑名单移除指定用户(短 UID',
resDescription: '是否成功移除用户',
})
public async removeFromBlacklist(
@Param('roomId', new NonEmptyStringPipe('roomId')) roomId: string,
@Param('shortUid', new Uint32Pipe('shortUid')) shortUid: number
) {
await this.redis.removeFromBlacklist(roomId, shortUid);
return new OkResult(true);
}
}