Initial clean project import

This commit is contained in:
cat-shark
2026-06-19 18:41:41 +08:00
commit a13b804c7a
1306 changed files with 220568 additions and 0 deletions
+237
View File
@@ -0,0 +1,237 @@
/**
* 资源路径工具模块
* 统一管理开发环境和生产环境的资源路径
* ⚠️ 确保所有依赖都能在不同环境下正确识别
*/
import * as fs from 'fs';
import * as path from 'path';
import { app } from 'electron';
import { AppEnv } from '../mapi/env';
/**
* 判断是否为开发环境
*/
export function isDevelopment(): boolean {
const appRoot = process.env.APP_ROOT || process.env.ELECTRON_RESOURCES_PATH || process.cwd();
// 修复:dist-release目录不是开发环境
if (appRoot.includes('dist-release') || appRoot.includes('dist-electron')) {
return false;
}
// 🔧 修复:不硬编码项目文件夹名,改用检查开发目录结构是否存在
// 开发环境特征:项目根目录有 electron/resources/extra 目录
const devResourcePath = path.join(appRoot, 'electron', 'resources', 'extra');
if (fs.existsSync(devResourcePath)) {
return true;
}
// 回退:检查旧的文件夹名(兼容)
return appRoot.includes('aigcpanel-main');
}
/**
* 获取资源根目录
*/
export function getResourceRoot(): string {
const isDev = isDevelopment();
if (isDev) {
// 开发环境:项目根目录/electron/resources/extra
const appRoot = process.env.APP_ROOT || process.cwd();
return path.join(appRoot, 'electron', 'resources', 'extra');
} else {
// 生产环境:使用 process.resourcesPath 获取 resources 目录
// process.resourcesPath 指向 E:\xxx\resources
// 资源文件在 E:\xxx\resources\extra
// 关键修复:直接使用 process.resourcesPath 而不是 APP_ROOT
// 因为 APP_ROOT 被设置为 resources 的父目录,会导致路径错误
const resourcesPath = process.resourcesPath || process.env.ELECTRON_RESOURCES_PATH;
if (resourcesPath) {
return path.join(resourcesPath, 'extra');
}
// 回退:使用 APP_ROOT + resources/extra(仅当 process.resourcesPath 不可用时)
const appRoot = process.env.APP_ROOT || process.cwd();
return path.join(appRoot, 'resources', 'extra');
}
}
/**
* 获取通用资源路径(common 目录下的资源)
* @param subPath 子路径(相对于 extra/common
*/
export function getCommonResourcePath(subPath: string): string {
const resourceRoot = getResourceRoot();
return path.join(resourceRoot, 'common', subPath);
}
export function getRuntimeRoot(...segments: string[]): string {
const baseRoot = AppEnv.installRoot || process.env.APP_ROOT || process.cwd();
return path.join(baseRoot, ...segments);
}
export function getRuntimeDataPath(...segments: string[]): string {
const dataRoot = AppEnv.dataRoot || getRuntimeRoot('data');
return path.join(dataRoot, ...segments);
}
export function getRuntimeBundleRoot(): string {
return AppEnv.resourceBundleRoot || getRuntimeRoot('resources-bundles');
}
export function getRuntimeBundlePath(bundleName: string, ...segments: string[]): string {
return path.join(getRuntimeBundleRoot(), bundleName, ...segments);
}
export function getResourceStatePath(...segments: string[]): string {
const root = AppEnv.resourceStateRoot || getRuntimeDataPath('resource-state');
return path.join(root, ...segments);
}
/**
* 获取平台特定资源路径
* @param subPath 子路径(相对于 extra/{platform}
*/
export function getPlatformResourcePath(subPath: string): string {
const resourceRoot = getResourceRoot();
const platform = getPlatformDir();
return path.join(resourceRoot, platform, subPath);
}
/**
* 获取平台目录名
*/
export function getPlatformDir(): string {
const isWin = process.platform === 'win32';
const isMac = process.platform === 'darwin';
if (isWin) return 'win-x86';
if (isMac) return 'osx';
return 'linux';
}
/**
* 检查资源文件是否存在
* @param resourcePath 资源路径
* @returns 文件是否存在
*/
export function resourceExists(resourcePath: string): boolean {
return fs.existsSync(resourcePath);
}
/**
* 获取并验证资源路径
* @param resourcePath 资源路径
* @param errorMessage 文件不存在时的错误消息
* @returns 验证后的资源路径
* @throws 如果资源不存在则抛出错误
*/
export function getAndVerifyResource(resourcePath: string, errorMessage?: string): string {
if (!fs.existsSync(resourcePath)) {
const error = errorMessage || `资源文件不存在: ${resourcePath}`;
throw new Error(error);
}
return resourcePath;
}
/**
* 快捷方法:获取 Python 可执行文件路径
*/
export function getPythonExecutablePath(): string {
const isWin = process.platform === 'win32';
const pythonFileName = isWin ? 'python.exe' : 'python3';
const runtimePath = getRuntimeBundlePath('python-runtime', pythonFileName);
if (fs.existsSync(runtimePath)) {
return runtimePath;
}
return getCommonResourcePath(path.join('python', pythonFileName));
}
/**
* 快捷方法:获取 FFmpeg 可执行文件路径
*/
export function getFFmpegExecutablePath(): string {
const isWin = process.platform === 'win32';
const isMac = process.platform === 'darwin';
let ffmpegFileName = 'ffmpeg';
if (isWin) ffmpegFileName = 'ffmpeg.exe';
const runtimePath = getRuntimeBundlePath('ffmpeg', ffmpegFileName);
if (fs.existsSync(runtimePath)) {
return runtimePath;
}
return getPlatformResourcePath(ffmpegFileName);
}
/**
* 快捷方法:获取 FFprobe 可执行文件路径
*/
export function getFFprobeExecutablePath(): string {
const isWin = process.platform === 'win32';
const isMac = process.platform === 'darwin';
let ffprobeFileName = 'ffprobe';
if (isWin) ffprobeFileName = 'ffprobe.exe';
const runtimePath = getRuntimeBundlePath('ffmpeg', ffprobeFileName);
if (fs.existsSync(runtimePath)) {
return runtimePath;
}
return getPlatformResourcePath(ffprobeFileName);
}
/**
* 快捷方法:获取模型文件路径
* @param modelFileName 模型文件名(如 'u2net.onnx'
*/
export function getModelPath(modelFileName: string): string {
const runtimePath = getRuntimeBundlePath('models', modelFileName);
if (fs.existsSync(runtimePath)) {
return runtimePath;
}
return getCommonResourcePath(path.join('models', modelFileName));
}
/**
* 快捷方法:获取 Python 脚本路径
* @param scriptFileName Python 脚本文件名
*/
export function getPythonScriptPath(scriptFileName: string): string {
const runtimePath = getRuntimeBundlePath('python-runtime', scriptFileName);
if (fs.existsSync(runtimePath)) {
return runtimePath;
}
const appRoot = process.env.APP_ROOT || process.env.ELECTRON_RESOURCES_PATH || process.cwd();
const isDev = isDevelopment();
if (isDev) {
return path.join(appRoot, 'python', scriptFileName);
} else {
const asarUnpackedPath = path.join(appRoot, 'app.asar.unpacked', 'python', scriptFileName);
if (fs.existsSync(asarUnpackedPath)) {
return asarUnpackedPath;
}
return path.join(appRoot, 'python', scriptFileName);
}
}
/**
* 诊断信息:打印所有资源路径
*/
export function printResourceDiagnostics(): void {
const isDev = isDevelopment();
const resourceRoot = getResourceRoot();
console.log('\n========== 资源路径诊断 ==========');
console.log('环境模式:', isDev ? '开发环境' : '生产环境');
console.log('App Root:', process.env.APP_ROOT || process.cwd());
console.log('资源根目录:', resourceRoot);
console.log('\n关键资源路径:');
console.log(' Python:', getPythonExecutablePath(), '存在:', resourceExists(getPythonExecutablePath()));
console.log(' FFmpeg:', getFFmpegExecutablePath(), '存在:', resourceExists(getFFmpegExecutablePath()));
console.log(' FFprobe:', getFFprobeExecutablePath(), '存在:', resourceExists(getFFprobeExecutablePath()));
console.log(' U2Net模型:', getModelPath('u2net.onnx'), '存在:', resourceExists(getModelPath('u2net.onnx')));
console.log('=====================================\n');
}