diff --git a/apps/desktop-client/build/afterPack.cjs b/apps/desktop-client/build/afterPack.cjs new file mode 100644 index 0000000..d87198a --- /dev/null +++ b/apps/desktop-client/build/afterPack.cjs @@ -0,0 +1,46 @@ +// electron-builder afterPack hook — 在签名前裁掉不要的本地化文件 +// 解决 electron-builder 25 + Electron 41 不识别 *_NEUTER / *_MASCULINE / *_FEMININE 变体的 bug +// 220 个 .lproj → 仅保留 en* 和 zh_CN*,签名时间从 ~10 分钟降到 ~30 秒 +const fs = require('fs'); +const path = require('path'); + +// 只保留 en 和 zh_CN(性别变体 *_NEUTER/_MASCULINE/_FEMININE 在调用方已剥离) +const KEEP = new Set(['en', 'zh_CN']); +function shouldKeepLocale(base) { + return KEEP.has(base); +} + +exports.default = async function afterPack(context) { + const { appOutDir, packager } = context; + const productFilename = packager.appInfo.productFilename; + const appPath = path.join(appOutDir, `${productFilename}.app`); + + // 两处都要清理:app 自己的 Resources + Electron Framework 的 Resources + const dirs = [ + path.join(appPath, 'Contents/Resources'), + path.join(appPath, 'Contents/Frameworks/Electron Framework.framework/Versions/A/Resources'), + ]; + + let removed = 0; + let kept = 0; + + for (const dir of dirs) { + if (!fs.existsSync(dir)) continue; + for (const entry of fs.readdirSync(dir)) { + if (!entry.endsWith('.lproj')) continue; + // 去掉 .lproj 后缀和性别变体后缀,得到基础语言代码 + const base = entry + .replace(/\.lproj$/, '') + .replace(/_(NEUTER|MASCULINE|FEMININE)$/, ''); + + if (shouldKeepLocale(base)) { + kept++; + } else { + fs.rmSync(path.join(dir, entry), { recursive: true, force: true }); + removed++; + } + } + } + + console.log(`[afterPack] 本地化清理:保留 ${kept} 个,删除 ${removed} 个 .lproj`); +}; diff --git a/apps/desktop-client/build/mac/CertificateSigningRequest.certSigningRequest b/apps/desktop-client/build/mac/CertificateSigningRequest.certSigningRequest new file mode 100644 index 0000000..7d2949d --- /dev/null +++ b/apps/desktop-client/build/mac/CertificateSigningRequest.certSigningRequest @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIChTCCAW0CAQAwQDEgMB4GCSqGSIb3DQEJARYRMjQ2NjU4OTgwOEBxcS5jb20x +DzANBgNVBAMMBuaigeaXrTELMAkGA1UEBhMCQ04wggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQDTFpNTzOEjh0KnvpRBOE37Et96ELFbm2L5mpkBpUSwXxWH +Z9Bla02CkUZUivwfD/+YISVQfu/pQ/S9jzCkYCYbYykSNz5MYP2S/t8wAGJarys8 +RdmVUt/2AnIBaWzKngqKgFr9uyZEsr+c0/6zuGvQrxY3YHm2Qe2jyYpcW4zJQ3+M +AIDQw8yZgQu1ybi4Y7RP3wDeUWSFunxcoQozvtWycmZDHbzigOeiiYdIxfwl1naX +IRLNFxagcZheLRoHLNjZbnsjtAxAKtM6V6bgF8lQxom+evXaSkbaeiKZUFO4FQ+j +8KJorgySauVLzec/1WKyfKNlj0+0FV388M7mqUbvAgMBAAGgADANBgkqhkiG9w0B +AQsFAAOCAQEAJgasLwwyvvciKv4fvhS1lQHKvRUSURQmrWmiQIZ0rzdD8f+tXa7/ +7yS1p+h8IRx9LNNzYVA2T/triD44DDg7MmpXKxHIvhXFZbxj0gP73DJPtXoOIwUq +OCHjAZWIvFfDGGmFNpcIPT0iq/++8b15IuLrgh2fB+pL+k2b/k88ZAAZR4fZXwFe +CFOxcfJG+wCnV7yEmIMWlHtd6Sd61pz9VtGzeryhyL1YL9JAC5+VJWxzj57gs80R +2tRLbEEETGH2LMqk6FVeKnEO9CioswrIRqrfcQuyt9DCxXCDYOPYNE1f8QzSs/qH +SsQOkCged041feSDfmAUvR3ZbuUg6rUS2w== +-----END CERTIFICATE REQUEST----- diff --git a/apps/desktop-client/build/mac/developerID_application.cer b/apps/desktop-client/build/mac/developerID_application.cer new file mode 100644 index 0000000..2d3f486 Binary files /dev/null and b/apps/desktop-client/build/mac/developerID_application.cer differ diff --git a/apps/desktop-client/build/mac/证书-liang0920.p12 b/apps/desktop-client/build/mac/证书-liang0920.p12 new file mode 100644 index 0000000..f9ef45f Binary files /dev/null and b/apps/desktop-client/build/mac/证书-liang0920.p12 differ diff --git a/apps/desktop-client/electron-builder.yml b/apps/desktop-client/electron-builder.yml index 709bec2..1f18c0c 100644 --- a/apps/desktop-client/electron-builder.yml +++ b/apps/desktop-client/electron-builder.yml @@ -8,6 +8,7 @@ compression: maximum removePackageScripts: true removePackageKeywords: true asar: true +afterPack: build/afterPack.cjs # 签名前裁掉非 en/zh_CN 的本地化文件 asarUnpack: - "**/node_modules/better-sqlite3/build/Release/**" - "**/node_modules/better-sqlite3/lib/**" diff --git a/deploy/.env.example b/deploy/.env.example index 5cdc835..11a339e 100644 --- a/deploy/.env.example +++ b/deploy/.env.example @@ -7,12 +7,6 @@ IMAGE_REGISTRY=ghcr.io/your-org/geo-rankly IMAGE_TAG=latest -# ─── Required: API Keys ──────────────────────────────────────────────────────── -# LLM provider API key (Ark / Doubao / OpenAI-compatible) -LLM_API_KEY=your-llm-api-key-here -# Embedding + reranker API key (SiliconFlow) -SILICONFLOW_API_KEY=your-siliconflow-api-key-here - # ─── Required: Security ─────────────────────────────────────────────────────── # JWT signing secret — use a strong random string in production # Generate: openssl rand -hex 32