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,159 @@
/**
* Nacos 配置模块
* 从 Nacos 配置中心加载和管理配置
*/
import { Injectable } from '@nestjs/common';
import * as nacos from 'nacos';
import * as yaml from 'js-yaml';
import { ConfigService } from '@nestjs/config';
import { LoggerService } from '../logger/logger.service';
/** 声网应用配置接口 */
export interface AgoraAppConfig {
appId: string;
appCertificate: string;
}
/** 声网配置接口 */
export interface AgoraConfig {
apps: Record<string, AgoraAppConfig>;
defaultAppId: string;
}
/**
* Nacos 配置服务
* 提供配置的读取和缓存功能
*/
@Injectable()
export class NacosConfigService {
private readonly logger = new LoggerService();
private agoraConfig: AgoraConfig | null = null;
private configClient!: nacos.NacosConfigClient;
constructor(private readonly configService: ConfigService) {
this.initNacosClient();
this.loadAgoraConfig();
}
/**
* 初始化 Nacos 客户端
*/
private initNacosClient(): void {
const serverAddr = this.configService.get<string>('NACOS_SERVER_ADDR');
const username = this.configService.get<string>('NACOS_USERNAME');
const password = this.configService.get<string>('NACOS_PASSWORD');
const namespace = this.configService.get<string>('NACOS_NAMESPACE_ID');
if (!serverAddr) {
throw new Error('NACOS_SERVER_ADDR 环境变量未配置');
}
try {
// 创建 Nacos 配置客户端
this.configClient = new nacos.NacosConfigClient({
serverAddr,
username: username || undefined,
password: password || undefined,
namespace: namespace || undefined,
});
this.logger.info(`Nacos 客户端初始化成功,服务器地址:${serverAddr}`);
} catch (error) {
this.logger.error('Nacos 客户端初始化失败:', error);
throw new Error(`Nacos 客户端初始化失败:${error.message}`, { cause: error });
}
}
/**
* 从 Nacos 加载声网配置文件
*/
private async loadAgoraConfig(): Promise<void> {
try {
const dataId = this.configService.get<string>('NACOS_DATA_ID');
const group = this.configService.get<string>('NACOS_GROUP') || 'DEFAULT_GROUP';
// 从 Nacos 获取配置内容
const configContent = await this.configClient.getConfig(
this.configService.get<string>('NACOS_DATA_ID')!,
this.configService.get<string>('NACOS_GROUP') || 'DEFAULT_GROUP'
);
if (!configContent) {
throw new Error(`Nacos 中未找到配置dataId=${dataId}, group=${group}`);
}
// 解析 YAML 配置
const config = yaml.load(configContent) as AgoraConfig;
if (!config.apps || !config.defaultAppId) {
throw new Error('Nacos 配置格式错误:必须包含 apps 和 defaultAppId 字段');
}
if (!config.apps[config.defaultAppId]) {
throw new Error(`Nacos 配置错误defaultAppId '${config.defaultAppId}' 在 apps 中不存在`);
}
this.agoraConfig = config;
this.logger.info(`声网配置从 Nacos 加载成功,默认应用:${config.defaultAppId}`);
// 监听配置变化(可选,实现热更新)
try {
// 使用已解析的 dataId 和 group传入对象格式
this.configClient.subscribe({ dataId, group }, (content: string) => {
this.logger.info('检测到 Nacos 配置变更,重新加载...');
try {
const newConfig = yaml.load(content) as AgoraConfig;
this.agoraConfig = newConfig;
this.logger.info(`声网配置已更新,默认应用:${newConfig.defaultAppId}`);
} catch (error) {
this.logger.error('配置更新失败', error);
}
});
} catch {
// 配置监听失败不影响主流程,记录警告日志
this.logger.warn('Nacos 配置监听器设置失败,但配置已成功加载');
}
} catch (error) {
this.logger.error('从 Nacos 加载声网配置失败', error);
throw new Error(`从 Nacos 加载声网配置失败:${error.message}`, { cause: error });
}
}
/**
* 获取声网配置
* @returns {AgoraConfig} 声网配置对象
*/
getAgoraConfig(): AgoraConfig {
if (!this.agoraConfig) {
throw new Error('声网配置未加载,请检查 Nacos 配置是否正确且格式有效');
}
return this.agoraConfig;
}
/**
* 获取指定的声网应用配置
* @param {string} appId - 应用 ID可选默认使用 defaultAppId
* @returns {AgoraAppConfig} 声网应用配置
*/
getAgoraAppConfig(appId?: string): AgoraAppConfig {
const agoraConfig = this.getAgoraConfig();
const targetAppId = appId || agoraConfig.defaultAppId;
const appConfig = agoraConfig.apps[targetAppId];
if (!appConfig) {
const errorMsg = `未找到声网应用配置:${targetAppId}。可用的应用 ID: ${Object.keys(agoraConfig.apps).join(', ')}`;
this.logger.error(errorMsg);
throw new Error(errorMsg);
}
return appConfig;
}
/**
* 获取默认的声网应用配置
* @returns {AgoraAppConfig} 默认声网应用配置
*/
getDefaultAgoraAppConfig(): AgoraAppConfig {
return this.getAgoraAppConfig();
}
}

View File

@ -0,0 +1,14 @@
/**
* Nacos 配置模块
*/
import { Global, Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { NacosConfigService } from './nacos-config.service';
@Global()
@Module({
imports: [ConfigModule],
providers: [NacosConfigService],
exports: [NacosConfigService],
})
export class NacosConfigModule {}