[EQD-6838] 补充踩坑注释:main.post 业务错误走 reject、本文件独立 script 部署、bundle 大小写敏感+非致命

- base/main.js __post/main.post:标注业务错误(success=false/errcode)与网络异常均走 deferred.reject,
  调用方只挂 .done 会静默跳过失败分支(约定2补充曾因此长期不生效)。
- app/swaptrade/swapTradeEdit.js calcBondForItem:标注本文件为独立 <script>(不在 bundle.js)、须 dotnet publish
  刷新 JsVersion 缓存键才生效;并展开 .fail 注释记录约定2补充一度不生效的历史根因。
- rebuild-bundles.py:标注 bundleconfig 输入路径在 Linux 大小写敏感(曾 MISSING 打挂 publish)、
  缺失输入必须非致命(否则 exit 1 连带打挂 dotnet publish)。纯注释,无逻辑改动。
This commit is contained in:
hjhan
2026-07-29 19:51:42 +08:00
parent ce4ef62950
commit 56256cad0b
3 changed files with 39 additions and 7 deletions
+12 -2
View File
@@ -86,6 +86,10 @@ def build_all():
for f in b['inputFiles']:
p = os.path.join(ROOT, f)
if not os.path.exists(p):
# ⚠️【CI 踩坑必读 / 大小写敏感】Windows 大小写不敏感,本地能找到 MyJs.js / isoWeek.js
# 但 Jenkins 是 Linux,大小写敏感,bundleconfig.json 里写的输入路径必须与 git 实际跟踪的
# 文件名【大小写完全一致】,否则这里判 missing。曾经因此报 MISSING INPUT 并把整个 dotnet publish 打挂。
# 改 bundleconfig 的输入文件名时,务必先 `git ls-files` 确认真实大小写。
missing.append(f)
continue
content = normalize(open(p, 'rb').read())
@@ -149,6 +153,10 @@ def main():
for f in b['inputFiles']:
p = os.path.join(ROOT, f)
if not os.path.exists(p):
# ⚠️【CI 踩坑必读 / 大小写敏感】Windows 大小写不敏感,本地能找到 MyJs.js / isoWeek.js
# 但 Jenkins 是 Linux,大小写敏感,bundleconfig.json 里写的输入路径必须与 git 实际跟踪的
# 文件名【大小写完全一致】,否则这里判 missing。曾经因此报 MISSING INPUT 并把整个 dotnet publish 打挂。
# 改 bundleconfig 的输入文件名时,务必先 `git ls-files` 确认真实大小写。
missing.append(f)
continue
content = normalize(open(p, 'rb').read())
@@ -162,8 +170,10 @@ def main():
for out, joined, missing in results:
dest = os.path.join(ROOT, out)
if missing:
# 缺失输入文件:警告但不 fail,避免阻塞 CI 主构建
# 重建模式下跳过此 bundle(保留已提交的产物);Verify 模式下报错
# ⚠️【CI 踩坑必读 / 非致命】缺失输入文件不 fail:早期实现把 MISSING 当致命错误 exit 1
# 会连带打挂整个 dotnet publishyml 报错 "命令已退出,代码为 1")。
# 现改为:重建模式跳过该 bundle(保留已提交的产物即可,CI 仍能出包);只有 --verify 校验模式才 exit 1。
# 重建模式下警告但不 fail,避免阻塞 CI 主构建
if verify:
ok = False
print(f" [MISSING INPUT] {out}: {missing}")
@@ -410,6 +410,13 @@ const vue = new Vue({
// - 业务/参数错误(success=false 或 errCode!=0,如债券不存在/信息不全/参数非法)
// 以非阻塞 toast(main.message) 反馈真实原因,绝不回写、不弹模态框、不阻止手工输入;
// - 网络/服务异常:框架 main.post 已弹"请求失败",此处不再二次提示。
// ⚠️【部署 / 踩坑必读】本文件 swapTradeEdit.js 是【独立 <script> 引用】,并不在 bundle.js 里拼接!
// 页面用 ?v=JsVersion 缓存键引用(JsVersion = bin/YLErp* DLL 最大 mtime)。
// 因此:改了本文件后必须 dotnet publish(重编 DLL 才会刷新 JsVersion 缓存键),
// 否则浏览器仍读旧缓存 —— 表现为"本地/某次提交明明改了却没生效"。
// ⚠️【接线 / 踩坑必读】计算器成败路由见 base/main.js __post 注释:业务错误走 reject。
// 本函数曾把"约定2补充(算不出→清另两字段+清标识)"只写在 .done 内,
// 而 .done 在 reject 时不触发 → 那段是死代码、长期静默失效;现已改到 .fail(见下)。
calcBondForItem(item, explicitDriver) {
var driver = explicitDriver || item.bondDriverType;
if (!item.isBond || !driver) return;
@@ -448,7 +455,7 @@ const vue = new Vue({
price: SwapCalc.bondPriceToCalc(price),
priceType: priceType,
targetDate: targetDate
}, { alertFn: main.message }).done(function (resp) {
}, { alertFn: main.message }).done(function (resp) { // ⚠️ .done 仅在 success(=resolve) 时触发;业务失败/网络异常请走下方 .fail,此处写失败处理是死代码
if (!resp || !resp.obj) {
// 网络错误/响应异常:框架已弹"请求失败",按交互约定2补充清另两字段+标识
SwapCalc.applyBondCalcFailure(item, driver);
@@ -488,11 +495,14 @@ const vue = new Vue({
// 直接赋值不会触发组件 input 事件,需在此显式重算,保持名义本金与全价一致。
if (self.calcNotional) self.calcNotional();
}).fail(function (resp) {
// 交互约定2补充:main.post 在 success:false(业务错误=计算器算不出来)或网络异常时
// 走 reject.done 不会触发;故"计算器算不出来"统一在此落地:
// 保留源字段值、另两字段清空为空白、三个数值旁标识(源/AUTO/REV)全清。
// ⚠️【踩坑记录 / 约定2补充 为何一度不生效】main.post(__post) 在 resp.success===false
// (业务错误=计算器算不出来)或网络异常时调用 deferred.reject()Promise 进入 rejected 态;
// 而 .done() 只在 resolved 态触发 —— 历史上把 applyBondCalcFailure(清另两字段+清标识)
// 写在 .done 内的「业务错误分支」里,业务失败时那段根本不执行,表现就是
// "约定2补充静默失效、auto/源标识纹丝不动"。正确做法就是像现在这样统一在 .fail 里落地。
// 交互约定2补充:计算器算不出来 → 保留源字段值、另两字段清空为空白、三个数值旁标识(源/AUTO/REV)全清。
// 错误文案已由 __post 的 alertFn(main.message) 非阻塞提示,此处不重复弹,仅清数值+清标识
// (与 .done 内 !resp.obj / getBondCalcErrorMessage 两个失败分支行为一致)。
// (与 .done 内 !resp.obj 分支行为一致;左侧 .done 的 getBondCalcErrorMessage 分支为兼容冗余,主路径在此)。
SwapCalc.applyBondCalcFailure(item, driver);
self.syncBondFlags(item);
});
+12
View File
@@ -350,6 +350,17 @@ function __getWaitMeFunc(options) {
return waitMeFunc;
}
/**
* ⚠️【全局陷阱 / 接手必读】__post 的成败路由:
* - 成功(resp.success 为真 且 非 errcode) -> deferred.resolve(resp) .done 触发)
* - 业务错误(resp.success===false / errcode) -> deferred.reject(resp) .fail 触发,.done 不触发!)
* - 网络异常(ajax error) -> deferred.reject(resp) .fail 触发)
* 即:业务错误走的是 reject,不是 resolve。调用方若只在 .done(...) 里写「业务失败/算不出来」的处理,
* 业务失败时那段代码根本不会执行 —— 这是 bug 静默失效的高发地。
* 典型实例:swapTradeEdit.js 的 calcBondForItem「约定2补充(计算器算不出→清另两字段+清标识)」曾因
* applyBondCalcFailure 只写在 .done 内、长期不生效;后改到 .fail 才修复(见该文件注释)。
* 凡要区分「成功 / 业务失败 / 网络异常」的逻辑,务必在 .done 之外再挂 .fail。
*/
function __post(url, data, deferred, options) {
if (!url) throw "post url 不能为空";
@@ -454,6 +465,7 @@ main.ajax = function (options) {
* @param {boolean} options.suppressError -- 禁止出错时提示
* @returns {jQuery} -- jquery延迟对象Deferred
*/
// ⚠️ 见上方 __post 说明:本方法业务错误/网络异常走 reject,调用方需 .fail 才能捕获(只 .done 会漏掉失败分支)。
main.post = function (url, data, options) {
var d = $.Deferred();
__post(url, data, d, options);