Reference Card
配置来自三个地方,而且会互相覆盖。搞不清哪个值最终生效, 就会出现「我改了配置但没生效」和「我以为连的是测试服」。
gameboxclient 工作区快照。 统计口径:.env* 侧用
grep -E '^\s*VITE_[A-Z0-9_]+\s*='(注意等号前有空格, 写成
^VITE_[A-Z_]*= 会大量漏匹配);源码侧用
grep -rhoE 'VITE_[A-Z0-9_]+' src/ electron/。
一句话版本
.env 里已经有一整套能跑的配置(42 个键,
含 GM 地址、pcode、渠道、SVN 仓库地址、Jenkins 地址凭据和 11 个 job
名)。 登录做的是覆盖,不是填充 ——
initEnv() 覆盖的 14 个键,在
.env 里全都已有条目。
真正的差别在值是不是空的: SVN 账号密码在
.env 里是空的,必须靠登录; Jenkins 和 GM 有真值,不登录也能连上,只是连的是 .env 里那一套。
① 构建期 · .env* —— Vite 打进包里。
主进程在 ready.ts:11-13 把它们灌进
process.env。
② 启动期 · 主进程算路径 ——
ready.ts:14-19 算出 DIST /
DIST_EXTEND 等,追加到 process.env。
随后 App.vue:40 的
gameEnv.init(process.env) 把整个
process.env 收进 Pinia。
③ 登录期 · initEnv() 覆盖 ——
utils/extend/envOption.ts:8 用
/user/info 返回的 userInfo.game
覆盖其中 14 个键。
落盘 —— GameEvn.ts:44-49 的深度 watch 把
ENV 整体写进 localStorage 的 GameENV。
下次启动 gameEnv.init() 优先读它, 而不是
process.env。
⚠️ 这条最容易踩
改了 .env 却不生效,多半是被 localStorage 的旧
GameENV 挡住了。
GameEvn.init()(store/modules/GameEvn.ts:17-22) 只要发现 localStorage
里有 GameENV,就整个用它,
根本不看传进来的 process.env。
怎么办:改完 .env 后在控制台
localStorage.removeItem('GameENV') 再刷新。
.env 里三个 pcode 键的值都是
'boxTestLS'。名字里有
Test,看起来是测试环境。
但
getBaseURL()(src/config/axios/service.ts:79-84)是这样判的:
function getBaseURL(pcode: string): string {
if (pcode.includes('_dev')) {
return 'http://common-gm-460qntest.3975app.com/n1000y-api/' // 测试
}
return 'http://common-gm-460qnprod.3975app.com/n1000y-api/' // 正式
}
'boxTestLS' 不含 _dev → 落到
return 那一行 → 打正式 GM。
❌ 别学
用子串匹配判环境,而且默认分支是生产。
这里叠了两个问题:判定依据是 _dev 这个后缀, 而兜底值
boxTestLS 的命名暗示的却是「测试」——
命名和实际路由是矛盾的。
后果:登录失败、或登录成功但服务端没下发 pcode 时, 请求会安静地打到正式 GM,而配置文件看起来一切正常。
规范做法:用显式的环境字段(env: 'test' | 'prod'),
不要靠子串;不确定时默认落最安全的环境;地址走配置下发而不是硬编码。
动手前必查:控制台敲
localStorage.getItem('pCode') 和
JSON.parse(localStorage.getItem('GameENV')).VITE_API_PCODE, 看里面有没有 _dev。没有就是在打正式服。
.env 的 42 个键(真正的配置在这)
35 个有值,7 个是空的。下表按用途分组,
「登录覆盖」列标出 initEnv() 会不会改写它。
| 用途 | 键 | .env 有值? |
登录覆盖? |
|---|---|---|---|
| GM 接口 |
VITE_API_PCODE · VITE_API_BASE_PCODE ·
VITE_API_GM_PCODE
|
✅ 均为 boxTestLS |
✅ 前两个会(GM_PCODE 由选服页另算) |
VITE_API_BASEPATH ·
VITE_API_BASEPATH_DEV ·
VITE_API_PATH
|
✅ | ✅ | |
VITE_BASEPATH |
✅ axios 的 baseURL 初始值 | ❌ | |
| 渠道 |
VITE_API_CHANNEL · VITE_API_CHANNEL_SVN
|
✅ | ✅ |
| SVN | VITE_SVN_URL · VITE_SVN_EXCEL_URL |
✅ | ✅ |
VITE_SVN_USER · VITE_SVN_PASSWORD |
❌ 空 | ✅ 只能靠登录 | |
VITE_SVN_ASSETSURL |
❌ 空 | ❌ 源码里零引用,疑似遗留 | |
| Jenkins |
VITE_JENKINS_URL · VITE_JENKINS_USER ·
VITE_JENKINS_TOKEN
|
✅ 有真值 | ✅ |
11 个 job 名(RES / DEV /
ALPHA / PROD / APP /
PUBLISH_*)
|
✅ |
❌ 不覆盖值,但 initEnv() 会把里面的
channel 字样替换成实际渠道
|
|
| 腾讯云 COS |
VITE_COS_ACCESSKEYID ·
VITE_COS_ACCESSKEYSECRET
|
❌ 空 | ❌ 见下方红框 |
VITE_COS_BUCKET · VITE_COS_REGION ·
VITE_ENDPOINT
|
✅ | ❌ | |
| 阿里云 OSS |
VITE_OSS_ACCESSKEYID · SECRET ·
BUCKET · REGION
|
两个密钥空,其余有值 | ❌ |
| 网页版地址 |
VITE_DEV_WEB · VITE_ALPHA_WEB ·
VITE_PROD_WEB · VITE_STORE
|
✅ | ❌ |
| 其他 | VITE_DEBUG |
✅ | ❌ |
❌ COS 密钥在当前代码里没有任何写入路径
三条事实叠在一起:
.env 里 VITE_COS_ACCESSKEYID /
SECRET 是空字符串;
loginSuccess() 确实把 userInfo.cos 传了进去
(api/login/index.ts:74),但
initEnv() 函数体里从头到尾没有读这个参数
(utils/extend/envOption.ts:8);
App.vue:42-43、api/shop/index.ts:171,232)。
所以
COS_Handler.init() 拿到的必然是两个空字符串。
而它内部是 try/catch +
return false,没人检查返回值,
所以这件事在界面上完全不可见。
需要实测确认的是:带空密钥的 COS 请求在服务端是直接 401, 还是某些只读操作仍可用。这是「必须问人 / 必须实测」清单里的一条。
.env.base / .env.dev /
.env.pro:只有构建开关
这三个文件不含任何业务配置,加起来只有 9 个不同的键, 全是构建期开关:
| 键 | 作用 |
|---|---|
NODE_ENV |
决定主进程要不要初始化
electron-log(ready.ts:24-26)
|
VITE_APP_TITLE |
窗口标题,经 EJS 插件注入 index.html |
VITE_BASE_PATH |
Vite 的 base,资源路径前缀。
注意和 .env 里的
VITE_BASEPATH 只差一个下划线,含义完全不同
|
VITE_BASEPATH |
接口 baseURL(只有 .env.pro 覆盖它) |
VITE_OUT_DIR · VITE_SOURCEMAP |
构建输出目录、要不要出 sourcemap |
VITE_DROP_CONSOLE · VITE_DROP_DEBUGGER
|
terser 压缩时去不去掉 console / debugger |
VITE_DEBUG |
主进程在 onAppReady.ts 里打日志用 |
VITE_SHOW_UI |
⚠️ 在 .env.base / .env.dev 里定义了,但
src/ 与
electron/ 里零引用,疑似遗留
|
❌ 别学
VITE_BASE_PATH(资源前缀)和
VITE_BASEPATH(接口 baseURL)只差一个下划线。
改配置时看漏一个,症状会是「资源 404」或「所有接口打到根路径」——
两个症状都跟你以为的原因无关。
规范做法:命名要拉开距离,比如
VITE_ASSET_BASE 和 VITE_API_BASE_URL。
| 键 | 算法 | 谁用 |
|---|---|---|
DIST_ELECTRON |
join(__dirname, '..') |
下面几个的基准 |
DIST |
DIST_ELECTRON/../dist |
打包后加载 index.html 的位置 |
DIST_EXTEND |
DIST_ELECTRON/../extend |
所有外挂工具的根目录 |
PUBLIC |
打包后 = DIST,开发时 = ../public |
图标等静态资源 |
VITE_DIST_EXTEND |
utils/extend/electron.ts:4 把
DIST_EXTEND 里的 app.asar 替换成
app.asar.unpacked
|
SVN / Python / 7-Zip 全靠它拼路径 |
VITE_DEV_SERVER_URL |
由 vite-plugin-electron 注入 |
开发时窗口加载哪个地址;打包后为空 |
app.asar
归档,归档内的文件不能被当作可执行程序运行。
electron-builder.json5 用 asarUnpack 把
extend 解出来放在
app.asar.unpacked,代码再把路径替换过去。 这是打包后「找不到
svn / python」类问题的根源所在。
.env* 里没有的 8 个| 键 | 从哪来 |
|---|---|
VITE_DIST_EXTEND · VITE_DEV_SERVER_URL
|
主进程 / 构建插件注入(见上一节) |
VITE_API_SCRIPT_PCODE |
脚本管理页按当前版本现算
(views/GameEditor/NewScript/index.vue:1092-1101)
|
VITE_API_SECTCONFIG_PCODE ·
VITE_API_SECTCONFIG_PATH
|
全局数据页现算(views/GameEditor/GlobalData/index.vue:143-154)
|
VITE_JENKINS_STOP · VITE_JENKINS_AUTO ·
VITE_JENKINS_CHECK
|
不是真配置键。它们是
jenkins/config.ts 的
JOB_TYPES 里的动作标记, 值写死为
'STOP' / 'ATUO' /
'CHECK' (ATUO 是
AUTO 的拼写错误)
|
VITE_BASE_PATH · VITE_DROP_CONSOLE ·
VITE_DROP_DEBUGGER · VITE_OUT_DIR ·
VITE_SOURCEMAP —— 这五个是给
vite.config.ts 用的,不出现在 src/ 里,属正常。
VITE_SHOW_UI 和 VITE_SVN_ASSETSURL 则是
连 vite.config.ts 也不用的真遗留键。
①
JSON.parse(localStorage.getItem('GameENV'))
—— 看整个包,以及目标键的当前值
② 值不对 → 是不是被旧的 localStorage 挡住了? localStorage.removeItem('GameENV') 再刷新试试
③ 值是空的 → 看它属于哪一类:
SVN 账号密码空 = 登录没下发,去问后端
/user/info 返回了什么;COS 密钥空 =
当前代码本来就没有写入路径(见上文红框)
④ pcode 类问题额外查
localStorage.getItem('pCode') ——
getPcode() 会优先用它,
优先级高于选服时写进 GameEvn 的值
⑤ 确认最终打到哪台服:看 Network 里 Request URL
的域名是 qntest 还是 qnprod,并和 pcode
里有没有 _dev 对上
站点版本 319ca82 · 2026-08-13
内容基线 gameboxclient @ 2026-08-12