文案模块优化

This commit is contained in:
Jerry 2025-08-25 22:59:44 +08:00
parent e775bcdf77
commit de264b1244
4 changed files with 84 additions and 37 deletions

View File

@ -13,57 +13,65 @@ export class AutoUpdateService {
private readonly git: SimpleGit; private readonly git: SimpleGit;
private readonly repoPath: string; private readonly repoPath: string;
constructor( constructor(@Inject(PathService) private readonly pathService: PathService) {
@Inject(PathService)
private readonly pathService: PathService,
) {
this.git = simpleGit(); this.git = simpleGit();
this.repoPath = this.pathService.get('root'); this.repoPath = this.pathService.get('root');
} }
/** /**
* *
*/ */
async checkForUpdates(): Promise<boolean> { async checkForUpdates(): Promise<boolean> {
try { return this.checkRepoForUpdates(this.repoPath, 'crystelf-core');
this.logger.log('检查仓库更新中...'); }
/**
*
*/
async checkRepoForUpdates(
folderPath: string,
label = '子仓库',
): Promise<boolean> {
try {
this.logger.log(`[${label}] 检查仓库更新中...`);
const repoGit = simpleGit(folderPath);
const status = await repoGit.status();
const status = await this.git.status();
if (status.ahead > 0) { if (status.ahead > 0) {
this.logger.warn('检测到本地仓库有未提交的更改,跳过更新'); this.logger.warn(`[${label}] 检测到本地仓库有未提交的更改,跳过更新`);
return false; return false;
} }
this.logger.log('正在获取远程仓库信息...'); this.logger.log(`[${label}] 正在获取远程仓库信息...`);
await this.git.fetch(); await repoGit.fetch();
const localBranch = status.current; const localBranch = status.current;
const diffSummary = await this.git.diffSummary([ const diffSummary = await repoGit.diffSummary([
`${localBranch}..origin/${localBranch}`, `${localBranch}..origin/${localBranch}`,
]); ]);
if (diffSummary.files.length > 0) { if (diffSummary.files.length > 0) {
this.logger.log('检测到远程仓库有更新!'); this.logger.log(`[${label}] 检测到远程仓库有更新!`);
if (localBranch) { if (localBranch) {
this.logger.log('正在拉取远程代码...'); this.logger.log(`[${label}] 正在拉取远程代码...`);
await this.git.pull('origin', localBranch); await repoGit.pull('origin', localBranch);
} else { } else {
this.logger.error('当前分支名称未知,无法执行拉取操作。'); this.logger.error(`[${label}] 当前分支名称未知,无法执行拉取操作。`);
return false; return false;
} }
this.logger.log('代码更新成功,开始更新依赖...'); this.logger.log(`[${label}] 代码更新成功,开始更新依赖...`);
await this.updateDependencies(); await this.updateDependencies(folderPath, label);
this.logger.log('自动更新流程完成'); this.logger.log(`[${label}] 自动更新流程完成`);
return true; return true;
} else { } else {
this.logger.log('远程仓库没有新变化'); this.logger.log(`[${label}] 远程仓库没有新变化`);
return false; return false;
} }
} catch (error) { } catch (error) {
this.logger.error('检查仓库更新失败:', error); this.logger.error(`[${label}] 检查仓库更新失败:`, error);
return false; return false;
} }
} }
@ -71,24 +79,34 @@ export class AutoUpdateService {
/** /**
* *
*/ */
private async updateDependencies(): Promise<void> { private async updateDependencies(
folderPath: string,
label = '仓库',
): Promise<void> {
try { try {
this.logger.log('执行 pnpm install...'); this.logger.log(`[${label}] 执行 pnpm install...`);
await execAsync('pnpm install', { cwd: this.repoPath }); await execAsync('pnpm install', { cwd: folderPath });
this.logger.log('依赖安装完成'); this.logger.log(`[${label}] 依赖安装完成`);
const pkgPath = this.pathService.get('package'); const pkgPath = `${folderPath}/package.json`;
const pkgJson = JSON.parse(readFileSync(pkgPath, 'utf-8')); let pkgJson: any;
try {
pkgJson = JSON.parse(readFileSync(pkgPath, 'utf-8'));
} catch {
this.logger.warn(`[${label}] 未找到 package.json跳过依赖构建`);
return;
}
if (pkgJson.scripts?.build) { if (pkgJson.scripts?.build) {
this.logger.log('检测到 build 脚本,执行 pnpm build...'); this.logger.log(`[${label}] 检测到 build 脚本,执行 pnpm build...`);
await execAsync('pnpm build', { cwd: this.repoPath }); await execAsync('pnpm build', { cwd: folderPath });
this.logger.log('构建完成'); this.logger.log(`[${label}] 构建完成`);
} else { } else {
this.logger.log('未检测到 build 脚本,跳过构建'); this.logger.log(`[${label}] 未检测到 build 脚本,跳过构建`);
} }
} catch (error) { } catch (error) {
this.logger.error('更新依赖或构建失败:', error); this.logger.error(`[${label}] 更新依赖或构建失败:`, error);
} }
} }
} }

View File

@ -27,7 +27,7 @@ export class PathService {
userData: path.join(this.baseDir, 'private/data'), userData: path.join(this.baseDir, 'private/data'),
package: path.join(this.baseDir, 'package.json'), package: path.join(this.baseDir, 'package.json'),
modules: path.join(this.baseDir, 'src/modules'), modules: path.join(this.baseDir, 'src/modules'),
words: path.join(this.baseDir, 'private/data/word'), words: path.join(this.baseDir, 'private/word'),
}; };
return type ? mappings[type] : this.baseDir; return type ? mappings[type] : this.baseDir;

View File

@ -51,7 +51,7 @@ export class WordsController {
); );
} }
const randomIndex = Math.floor(Math.random() * texts.length); const randomIndex = Math.floor(Math.random() * texts.length);
return { success: true, data: texts[randomIndex] }; return texts[randomIndex];
} catch (e) { } catch (e) {
this.logger.error(`getText 失败: ${e?.message}`); this.logger.error(`getText 失败: ${e?.message}`);
throw new HttpException('服务器错误', HttpStatus.INTERNAL_SERVER_ERROR); throw new HttpException('服务器错误', HttpStatus.INTERNAL_SERVER_ERROR);

View File

@ -2,19 +2,28 @@ import { Inject, Injectable, Logger } from '@nestjs/common';
import * as path from 'path'; import * as path from 'path';
import * as fs from 'fs/promises'; import * as fs from 'fs/promises';
import { PathService } from '../../core/path/path.service'; import { PathService } from '../../core/path/path.service';
import { AutoUpdateService } from '../../core/auto-update/auto-update.service';
@Injectable() @Injectable()
export class WordsService { export class WordsService {
private readonly logger = new Logger(WordsService.name); private readonly logger = new Logger(WordsService.name);
private wordCache: Record<string, string[]> = {}; private wordCache: Record<string, string[]> = {};
private readonly clearIntervalMs = 30 * 60 * 1000; // 30min private readonly clearIntervalMs = 30 * 60 * 1000; // 30min
@Inject(PathService) @Inject(PathService)
private readonly paths: PathService; private readonly paths: PathService;
@Inject(AutoUpdateService)
private readonly autoUpdateService: AutoUpdateService;
constructor() { constructor() {
this.startAutoClear(); this.startAutoClear();
this.startAutoUpdate();
} }
/**
*
*/
private startAutoClear() { private startAutoClear() {
setInterval(() => { setInterval(() => {
this.logger.log('清理文案缓存..'); this.logger.log('清理文案缓存..');
@ -23,10 +32,30 @@ export class WordsService {
} }
/** /**
* json & * words
*/
private startAutoUpdate() {
const wordsPath = this.paths.get('words');
setInterval(async () => {
this.logger.log('定时检查文案仓库更新..');
const updated = await this.autoUpdateService.checkRepoForUpdates(
wordsPath,
'words 仓库',
);
if (updated) {
this.logger.log('文案仓库已更新,清理缓存..');
this.wordCache = {};
}
}, this.clearIntervalMs);
}
/**
*
*/ */
async loadWordById(id: string): Promise<string[] | null> { async loadWordById(id: string): Promise<string[] | null> {
this.logger.log(`Loading words ${id}..`); this.logger.log(`加载文案 ${id}..`);
if (this.wordCache[id]) return this.wordCache[id]; if (this.wordCache[id]) return this.wordCache[id];
const filePath = path.join(this.paths.get('words'), `${id}.json`); const filePath = path.join(this.paths.get('words'), `${id}.json`);
try { try {