diff --git a/.gitignore b/.gitignore index a3f61f5..13243c7 100644 --- a/.gitignore +++ b/.gitignore @@ -13,5 +13,7 @@ venv/ # M9 覆盖层页面壳:构建产物,不入库。生成方式=由 apps/pbls/build.sh 在构建期调用 # python3 scripts/gen_overlay_pages.py 自动生成(已接入,并紧随其后以 --check 作为门禁), -# 本地开发调试可手动执行同一命令;README「生成产物与入库边界」有可机械核验的前提检查 +# 之后由同一脚本的「模块 wwwroot 挂载」步骤把本模块 wwwroot 软链进应用 wwwroot, +# 使页面壳在应用侧 URL /pbl_scense_ext/pbl_overlay/.ui 可达(挂载链路见 README +# 「生成产物与入库边界」)。本地开发调试可手动执行同一命令,并可跑 README 的自检清单。 wwwroot/pbl_overlay/ diff --git a/README.md b/README.md index 7643649..df495aa 100644 --- a/README.md +++ b/README.md @@ -11,15 +11,28 @@ PBL 覆盖层前端扩展模块(scense / scense_game 之上的 pbl_scense_ext `scripts/gen_overlay_pages.py` 生成页面壳,并紧随其后以 `--check` 作为门禁 (rc≠0 终止部署并打印原因)——实测 `grep -n 'gen_overlay_pages' apps/pbls/build.sh` 命中。调用位置在模块安装(`pip install -e modules/pbl_*`)之后、模块 wwwroot 软链 - 之前,因此新克隆 / 新部署环境执行 `build.sh` 即自动产出 `wwwroot/pbl_overlay/*.ui`, + 挂载之前,因此新克隆 / 新部署环境执行 `build.sh` 即自动产出 `wwwroot/pbl_overlay/*.ui`, 无需人工干预。人工执行 `python3 scripts/gen_overlay_pages.py` 仅用于本地开发调试。 反之,若该目录为空则 `/pbl_overlay/.ui` 导航全量 404——构建期的 `--check` 门禁就是为此前置拦截。 +- **应用侧可达性(模块 wwwroot 挂载,已接入)**:页面壳生成在**本模块仓**的 + `wwwroot/pbl_overlay/` 下,而 `wwwroot/overlay/pbl_overlay_play.js` 的 `pageUrl()` + 请求的是应用侧 URL `/pbl_scense_ext/pbl_overlay/.ui`;应用 `conf/config.json` + 的 `website.root=wwwroot` 只指向应用自身目录。因此 `apps/pbls/build.sh` 在生成 + + `--check` 之后还有一步**模块 wwwroot 软链挂载**(`ln -sfn + "${WS_DIR}/modules//wwwroot" "${APP_DIR}/wwwroot/"`,对所有含 `wwwroot/` + 的 `pbl_*` 模块执行),并紧随其后以应用侧路径实测页面壳数量作为门禁 + (`find -L apps/pbls/wwwroot/pbl_scense_ext/pbl_overlay -maxdepth 1 -name '*.ui'` + 必须为 12,否则终止部署)。缺了这一步,生成物虽在磁盘上、应用侧仍取不到—— + 这正是 QC 退回意见 #1 指出的「生成步骤接了、可达链路仍断」。软链(非拷贝)保证 + 与模块仓单一副本同步;该软链由构建脚本产出,在应用仓 `.gitignore` 中以 + `wwwroot/pbl_*/` 排除,不入库。 - 入库的交付物是**生成器与事实源**:`scripts/gen_overlay_pages.py`(生成器)、 `wwwroot/i18n/{zh,en}/msg.txt`(界面文案事实源)、`wwwroot/overlay/*.js|*.css` (覆盖层实现)、`scripts/load_path.py`(RBAC 路径登记)。 -- 一致性自检(四条都必须成立:前两条验「入库边界」,第三条验「生成步骤接入前提」, - 第四条验「本模块文档内不存在对 build.sh 生成步骤的编号化残留表述」): +- 一致性自检(五条都必须成立:前两条验「入库边界」,第三条验「生成步骤接入前提」, + 第四条验「本模块文档内不存在对 build.sh 生成步骤的编号化残留表述」,第五条验 + 「应用侧可达性(模块 wwwroot 已挂载进应用 wwwroot)」): ```bash git check-ignore -v wwwroot/pbl_overlay/home.ui # 命中 .gitignore 的 wwwroot/pbl_overlay/ git ls-files wwwroot/pbl_overlay # 空输出(无任何跟踪文件) @@ -29,6 +42,8 @@ PBL 覆盖层前端扩展模块(scense / scense_game 之上的 pbl_scense_ext || echo 'FAIL: 生成步骤未接入 apps/pbls/build.sh,新克隆环境 wwwroot/pbl_overlay/ 将为空' # 文档口径自检:本模块内不得残留对构建脚本生成步骤的编号化表述(期望 rc=1,零命中) grep -rnE '第 ?9 ?步' . --exclude-dir=.git ; echo "rc=$? (期望 1)" + # 可达性自检:页面壳必须经应用 wwwroot 的模块软链取到(期望 12,先执行过 apps/pbls/build.sh) + ls ../../apps/pbls/wwwroot/pbl_scense_ext/pbl_overlay/*.ui | wc -l ``` 说明三点: 1. 第四条自检**刻意**用 ERE 形式(`第`+可选空格+`9`+可选空格+`步`),一次性覆盖 diff --git a/scripts/gen_overlay_pages.py b/scripts/gen_overlay_pages.py index 05770b3..aa77896 100644 --- a/scripts/gen_overlay_pages.py +++ b/scripts/gen_overlay_pages.py @@ -10,15 +10,25 @@ wwwroot Directories Must Not Be Git-Tracked」/ QC 退回意见 #3 方案 (b)) git ls-files wwwroot/pbl_overlay # 输出为空(无跟踪文件) 本脚本(生成器)与 wwwroot/i18n/*/msg.txt(文案事实源)才是入库的交付物。 -【生成时机:已接入应用构建脚本,构建期自动生成】 +【生成时机:已接入应用构建脚本,构建期自动生成 + 自动挂载】 apps/pbls/build.sh 已调用本脚本生成页面壳,并紧随其后以 `--check` 作为门禁 (rc≠0 终止部署并打印原因)——实测 `grep -n gen_overlay_pages apps/pbls/build.sh` 命中。调用位置在模块安装(pip install -e modules/pbl_*)之后、模块 wwwroot 软链 -之前,故新克隆/新部署环境执行 build.sh 即自动产出页面壳;若该目录为空, +挂载之前,故新克隆/新部署环境执行 build.sh 即自动产出页面壳;若该目录为空, `/pbl_overlay/.ui` 导航会全量 404,构建期门禁即为此前置拦截。 + +生成物落在**本模块仓** wwwroot/pbl_overlay/ 下,而 play.js 的 pageUrl() 请求的是 +应用侧 URL `/pbl_scense_ext/pbl_overlay/.ui`,应用 conf/config.json 的 +website.root=wwwroot 只指向应用自身目录——因此 build.sh 在生成与 --check 之后还有 +一步「模块 wwwroot 挂载」:对所有含 wwwroot/ 的 pbl_* 模块执行 +`ln -sfn "${WS_DIR}/modules//wwwroot" "${APP_DIR}/wwwroot/"`,并以应用侧路径 +实测页面壳数=12 作为门禁(不符即终止部署)。只有「生成 + 挂载」两步齐备, +页面壳在应用侧才真正可达;缺挂载 = 生成物在磁盘上但 404(QC 退回意见 #1 根因)。 + 人工执行 `python3 scripts/gen_overlay_pages.py` 仅用于本地开发调试。 warn_build_integration() 作为常驻前提检查保留:`--check` 每次实测 apps/pbls/build.sh -并打印 OK(当前状态:已接入)或 WARN(接入被回退时),只告警不改变返回码。 +是否同时含生成调用与 wwwroot 挂载步骤,打印 OK(两项齐备)或 WARN(任一项被回退), +只告警不改变返回码。 为什么需要页面壳:wwwroot/overlay/pbl_overlay_core.js 的 PAGES 注册表 route 指向 `/pbl_overlay/.ui`,play.js 的 pageUrl() 会拼成 @@ -187,26 +197,39 @@ def build_page(key, in_world, zh): def warn_build_integration(): - """机械核验:页面壳生成步骤是否已接入应用构建脚本(QC #9 复审意见 #2)。 + """机械核验:构建脚本是否齐备「生成」与「模块 wwwroot 挂载」两个前提。 只告警、不改返回码——apps/pbls/build.sh 归应用侧所有,接入与否由 PM 派单跟踪; 但文档不得依赖未经核验的口头承诺,故每次校验都实测一次并如实打印结论。 + 两项检查的依据(QC 退回意见 #1/#2): + ① 生成:脚本内必须调用本脚本(否则新克隆环境页面壳目录为空); + ② 挂载:脚本内必须把模块 wwwroot 软链进应用 wwwroot(否则生成物虽在模块仓 + 磁盘上、应用侧 URL /pbl_scense_ext/pbl_overlay/.ui 仍取不到)。 """ build_sh = os.path.normpath(os.path.join(ROOT, os.pardir, os.pardir, 'apps', 'pbls', 'build.sh')) if not os.path.isfile(build_sh): - print('[gen_overlay_pages][WARN] 未找到 %s:无法核验生成步骤是否已接入构建脚本,' - '新环境请手动执行本脚本生成页面壳' % build_sh) + print('[gen_overlay_pages][WARN] 未找到 %s:无法核验生成/挂载步骤是否已接入构建脚本,' + '新环境请手动执行本脚本生成页面壳,并自行把模块 wwwroot 挂载到应用 wwwroot' + % build_sh) return with io.open(build_sh, 'r', encoding='utf-8', errors='replace') as f: body = f.read() - if 'gen_overlay_pages' in body: - print('[gen_overlay_pages] OK: 生成步骤已接入 %s' % build_sh) - else: - print('[gen_overlay_pages][WARN] 前提检查失败:apps/pbls/build.sh 内已无本脚本调用,' - '说明构建期自动生成已被回退。新克隆/新部署环境 wwwroot/pbl_overlay/ 将为空、' - '/pbl_overlay/.ui 全量 404,请恢复构建脚本中的生成步骤' - '(见 README「生成产物与入库边界」)') + has_gen = 'gen_overlay_pages' in body + # 挂载步骤的机械特征:对模块 wwwroot 建软链(ln -sfn ... modules//wwwroot -> 应用 wwwroot) + has_mount = ('ln -s' in body) and ('wwwroot' in body) + if has_gen and has_mount: + print('[gen_overlay_pages] OK: 生成步骤与模块 wwwroot 挂载步骤均已接入 %s' % build_sh) + return + missing = [] + if not has_gen: + missing.append('生成步骤(本脚本调用)——缺失则新克隆/新部署环境 wwwroot/pbl_overlay/ ' + '为空,/pbl_overlay/.ui 全量 404') + if not has_mount: + missing.append('模块 wwwroot 挂载步骤(ln -s 模块 wwwroot 到应用 wwwroot)——缺失则' + '生成物只落在模块仓,应用侧 /pbl_scense_ext/pbl_overlay/.ui 仍取不到') + print('[gen_overlay_pages][WARN] 前提检查失败:%s 内缺少 %s,请恢复构建脚本中的对应步骤' + '(见 README「生成产物与入库边界」)' % (build_sh, ';'.join(missing))) def check(zh, en):