修复打包问题

This commit is contained in:
ACT丶流星雨 2026-04-04 18:54:17 +08:00
parent ee37450176
commit 2881055c3f
10 changed files with 55 additions and 96 deletions

View File

@ -31,6 +31,11 @@ jobs:
- name: Build application
run: yarn build
- name: Install sharp platform binaries
run: |
npm install --os=win32 --cpu=x64 sharp
npm install --os=win32 --cpu=arm64 sharp
- name: Build Windows installer
run: yarn dist:win
env:
@ -63,6 +68,11 @@ jobs:
- name: Build application
run: yarn build
- name: Install sharp platform binaries
run: |
npm install --os=darwin --cpu=x64 sharp
npm install --os=darwin --cpu=arm64 sharp
- name: Build macOS installer
run: yarn dist:mac
env:
@ -95,6 +105,11 @@ jobs:
- name: Build application
run: yarn build
- name: Install sharp platform binaries
run: |
npm install --os=linux --cpu=x64 sharp
npm install --os=linux --cpu=arm64 sharp
- name: Build Linux installer
run: yarn dist:linux
env:

View File

@ -21,6 +21,9 @@ files:
- "!scripts/*.ts"
asar: true
asarUnpack:
- "**/node_modules/sharp/**"
- "**/node_modules/@img/**"
extraResources:
- from: data

4
env/.env.dev vendored
View File

@ -1,4 +0,0 @@
NODE_ENV=dev
PORT=10588
OSSURL=http://127.0.0.1:10588/

4
env/.env.prod vendored
View File

@ -1,4 +0,0 @@
NODE_ENV=prod
PORT=10588
OSSURL=http://127.0.0.1:10588/

View File

@ -28,6 +28,7 @@ const external = [
"vm2",
"sqlite3",
"better-sqlite3",
"sharp",
"mysql",
"mysql2",
"pg",

View File

@ -15,20 +15,26 @@ declare const __APP_VERSION__: string | undefined;
function getVersionFromUpdateJson(filePath: string): string | null {
try {
if (fs.existsSync(filePath)) {
const data = JSON.parse(fs.readFileSync(filePath, "utf8"));
return data.version ?? null;
}
return JSON.parse(fs.readFileSync(filePath, "utf8")).version ?? null;
} catch {}
return null;
}
function copyDirForce(src: string, dest: string): void {
const SKIP_ENTRIES = new Set(["logs", "oss", "db2.sqlite"]);
function copyDir(src: string, dest: string, overwrite = false): void {
if (!fs.existsSync(src)) return;
if (fs.existsSync(dest)) {
fs.rmSync(dest, { recursive: true, force: true });
fs.mkdirSync(dest, { recursive: true });
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
if (SKIP_ENTRIES.has(entry.name)) continue;
const srcPath = path.join(src, entry.name);
const destPath = path.join(dest, entry.name);
if (entry.isDirectory()) {
copyDir(srcPath, destPath, overwrite);
} else if (overwrite || !fs.existsSync(destPath)) {
fs.copyFileSync(srcPath, destPath);
}
}
copyDirRecursive(src, dest);
}
function initializeData(): void {
@ -38,34 +44,23 @@ function initializeData(): void {
const currentVersion = typeof __APP_VERSION__ !== "undefined" ? __APP_VERSION__ : "0.0.0";
const userVersion = getVersionFromUpdateJson(updateJsonFile);
// 首次安装或无update.json直接全量拷贝
if (!fs.existsSync(destDir) || !userVersion) {
copyDirRecursive(srcDir, destDir);
if (!userVersion) {
copyDir(srcDir, destDir);
return;
}
// 版本号不同则覆盖 serve 和 web 目录
if (userVersion !== currentVersion) {
copyDirForce(path.join(srcDir, "serve"), path.join(destDir, "serve"));
copyDirForce(path.join(srcDir, "web"), path.join(destDir, "web"));
}
}
function copyDirRecursive(src: string, dest: string): void {
if (!fs.existsSync(src)) return;
if (!fs.existsSync(dest)) fs.mkdirSync(dest, { recursive: true });
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
// 跳过 oss 文件夹和 db2.sqlite 文件
if (entry.isDirectory() && entry.name === "logs") continue;
if (entry.isDirectory() && entry.name === "oss") continue;
if (!entry.isDirectory() && entry.name === "db2.sqlite") continue;
const srcPath = path.join(src, entry.name);
const destPath = path.join(dest, entry.name);
if (entry.isDirectory()) {
copyDirRecursive(srcPath, destPath);
} else if (!fs.existsSync(destPath)) {
fs.copyFileSync(srcPath, destPath);
for (const dir of ["serve", "web"]) {
const dest = path.join(destDir, dir);
if (fs.existsSync(dest)) fs.rmSync(dest, { recursive: true, force: true });
copyDir(path.join(srcDir, dir), dest);
}
copyDir(srcDir, destDir);
try {
const data = JSON.parse(fs.readFileSync(updateJsonFile, "utf8"));
data.version = currentVersion;
fs.writeFileSync(updateJsonFile, JSON.stringify(data, null, 4), "utf8");
} catch {}
}
}

View File

@ -12,7 +12,6 @@ import fs from "fs";
import u from "@/utils";
import jwt from "jsonwebtoken";
import socketInit from "@/socket/index";
import path from "path";
const app = express();
const server = http.createServer(app);
@ -52,7 +51,7 @@ export default async function startServe(randomPort: Boolean = false) {
express.static(skillsDir),
);
// assets 静态资源
// assets 静态资源
const assetsDir = u.getPath("assets");
if (!fs.existsSync(assetsDir)) {
fs.mkdirSync(assetsDir, { recursive: true });
@ -105,7 +104,7 @@ export default async function startServe(randomPort: Boolean = false) {
res.status(err.status || 500).send(err);
});
const port = randomPort ? 0 : parseInt(process.env.PORT || "10588");
const port = randomPort ? 0 : 10588;
return await new Promise((resolve) => {
server.listen(port, async () => {
const address = server.address();

View File

@ -1,12 +1,3 @@
import { readFileSync, existsSync, writeFileSync, mkdirSync } from "fs";
import path from "path";
// 默认环境变量(当 env 文件不存在时自动创建)
const defaultEnvValues: Record<string, string> = {
dev: `NODE_ENV=dev\nPORT=10588\nOSSURL=http://127.0.0.1:10588/oss/`,
prod: `NODE_ENV=prod\nPORT=10588\nOSSURL=http://127.0.0.1:10588/oss/`,
};
// 判断是否为打包后的 Electron 环境
const isElectron = typeof process.versions?.electron !== "undefined";
let isPackaged = false;
@ -16,35 +7,9 @@ if (isElectron) {
}
//加载环境变量(打包环境默认使用 prod
const env = process.env.NODE_ENV ?? (isPackaged ? "prod" : "dev");
const env = process.env.NODE_ENV;
if (!env) {
console.log("[环境变量为空]");
process.exit(1);
} else {
// Electron 打包环境使用 userData 目录,开发环境使用项目根目录
let envDir: string;
if (isElectron) {
const { app } = require("electron");
envDir = path.join(app.getPath("userData"), "env");
} else {
envDir = path.resolve("env");
}
const envFilePath = path.join(envDir, `.env.${env}`);
// 自动创建 env 目录和文件(.gitignore 可能忽略了这些文件)
if (!existsSync(envDir)) {
mkdirSync(envDir, { recursive: true });
}
if (!existsSync(envFilePath)) {
const content = defaultEnvValues[env] ?? defaultEnvValues.prod;
writeFileSync(envFilePath, content, "utf8");
console.log(`[环境变量] 自动创建 ${envFilePath}`);
}
const text = readFileSync(envFilePath, "utf8");
for (const line of text.split("\n")) {
const idx = line.indexOf("=");
if (idx > 0) process.env[line.slice(0, idx).trim()] = line.slice(idx + 1).trim();
}
console.log(`[环境变量] ${env}`);
if (isElectron) process.env.NODE_ENV = "prod";
else process.env.NODE_ENV = "dev";
console.log(`[环境变量:${process.env.NODE_ENV}]`);
}

View File

@ -33,19 +33,8 @@ export default router.post(
const absPath = path.join(getPath("oss"), item.filePath!);
zipStream.addEntry(absPath, { relativePath: `${index}.${ext}` });
});
const fileName = `分镜.zip`;
const zipFilePath = getPath(["oss", "temp", fileName]);
await new Promise<void>((resolve, reject) => {
const fs = require("fs");
fs.mkdirSync(getPath(["oss", "temp"]), { recursive: true });
const writeStream = fs.createWriteStream(zipFilePath);
zipStream.pipe(writeStream);
writeStream.on("finish", resolve);
writeStream.on("error", reject);
});
const downloadUrl = `${process.env.OSSURL || "http://127.0.0.1:10588/"}temp/${fileName}`;
res.json(success({ url: downloadUrl }));
res.setHeader("Content-Type", "application/zip");
res.setHeader("Content-Disposition", "attachment; filename=export.zip");
zipStream.pipe(res);
},
);

View File

@ -50,7 +50,7 @@ class OSS {
await this.ensureInit();
const safePath = normalizeUserPath(userRelPath);
// URL 始终使用 /,所以这里需要将系统分隔符转回 /
let url = `${process.env.OSSURL}${prefix}/` || `http://127.0.0.1:10588/${prefix}/`;
let url = `http://127.0.0.1:10588/${prefix}/`;
if (isEletron()) url = `http://localhost:${process.env.PORT}/${prefix}/`;
return `${url}${safePath.split(path.sep).join("/")}`;
}