@nstc-business/imes 1.1.7 → 1.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nstc-business/imes",
3
- "version": "1.1.7",
3
+ "version": "1.1.9",
4
4
  "private": false,
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -0,0 +1,84 @@
1
+ /**
2
+ * story=2206036 首次测算调整项假 0 不应覆盖指标计算结果
3
+ */
4
+ const fs = require('fs')
5
+ const path = require('path')
6
+
7
+ const helpersSrc = fs.readFileSync(path.join(__dirname, 'helpers.js'), 'utf8')
8
+ // 仅抽取假 0 / 调整值回显相关纯函数,避免拉起 Vue/N 依赖
9
+ const start = helpersSrc.indexOf('function hasEchoValue')
10
+ const end = helpersSrc.indexOf('export function shouldApplyModifiedVal')
11
+ if (start < 0 || end < 0) {
12
+ throw new Error('无法定位假 0 相关函数片段')
13
+ }
14
+ const snippet = helpersSrc
15
+ .slice(start, end)
16
+ .replace(/export function resolveAdjustInputValue/g, 'function resolveAdjustInputValue')
17
+ .replace(/export function resolveCalcEchoValue/g, 'function resolveCalcEchoValue')
18
+ // resolveCalcEchoValue 依赖 isQualIndicator,测试中用桩
19
+ .replace(
20
+ /if \(target\.sourceType === 3 && !isQualIndicator\(target\)\)/,
21
+ 'if (target.sourceType === 3 && !false)'
22
+ )
23
+
24
+ const exported = {}
25
+ new Function(
26
+ 'exports',
27
+ 'function isQualIndicator(){return false}\n' +
28
+ snippet +
29
+ '\nexports.resolveAdjustInputValue = resolveAdjustInputValue' +
30
+ '\nexports.resolveCalcEchoValue = resolveCalcEchoValue'
31
+ )(exported)
32
+
33
+ const { resolveAdjustInputValue, resolveCalcEchoValue } = exported
34
+
35
+ function assert(cond, msg) {
36
+ if (!cond) throw new Error(msg)
37
+ }
38
+
39
+ // 首次测算:后端 modifiedVal=0、result=0、有指标原值 → 假 0,不采用
40
+ assert(
41
+ resolveAdjustInputValue({
42
+ modifyRank: 2,
43
+ modifiedVal: 0,
44
+ indicatorResult: 2120912863.01,
45
+ result: 0,
46
+ calcVal: null
47
+ }) === undefined,
48
+ '有原值+result=0 的 modifiedVal=0 应视为假 0'
49
+ )
50
+
51
+ // 尚无原值时的占位 0 → 假 0
52
+ assert(
53
+ resolveAdjustInputValue({
54
+ modifyRank: 2,
55
+ modifiedVal: 0,
56
+ indicatorResult: null,
57
+ result: null,
58
+ calcVal: null
59
+ }) === undefined,
60
+ '无原值时的 modifiedVal=0 应视为假 0'
61
+ )
62
+
63
+ // 用户真实调成 0:calcVal 落库为 0
64
+ assert(
65
+ resolveAdjustInputValue({
66
+ modifyRank: 2,
67
+ modifiedVal: 0,
68
+ indicatorResult: 2120912863.01,
69
+ result: 0,
70
+ calcVal: 0
71
+ }) === 0,
72
+ 'calcVal=0 时应认定真实调整为 0'
73
+ )
74
+
75
+ // 测算回写:假 0 应回退到 indicatorResult
76
+ assert(
77
+ resolveCalcEchoValue(
78
+ { sourceType: 1, itemType: 21, modifyRank: 2 },
79
+ { modifiedVal: 0, indicatorResult: 353098.98, result: 0, calcVal: null }
80
+ ) === 353098.98,
81
+ '假 0 回写应回退 indicatorResult'
82
+ )
83
+
84
+ console.log('helpers.fakeZero.test.js passed')
@@ -680,14 +680,19 @@ function hasEchoValue(val) {
680
680
 
681
681
  /**
682
682
  * 是否为后端「未调整」时写入的假 0(null 被格式化成 0)。
683
- * 真实「调整为 0」时 result/calcVal 会为 0,且与 indicatorResult 原值不同,不能当成假 0。
684
- * 时间:2026-09-11;人员:AI && 徐红飞;入参:modifiedVal/indicatorResult/result/calcVal;出参:boolean;方法内容:区分假 0 与真实调整为 0
683
+ * 仅用于「调整指标值」(modifyRank=2):得分 result 在授信金额类模型中常为 0,不能当作真实调成 0 的证据。
684
+ * 时间:2026-10-26 16:26:37
685
+ * 人员:AI && 徐红飞
686
+ * 入参:modifiedVal/indicatorResult/result/calcVal
687
+ * 出参:boolean
688
+ * 方法内容:无原值时的 0、或有原值但 calcVal 未按 0 落库的 0,均视为未调整假 0(story 2206036)
685
689
  */
686
690
  function isFakeUnadjustedZero(modifiedVal, indicatorResult, result, calcVal) {
687
691
  if (Number(modifiedVal) !== 0) return false
688
- if (!hasEchoValue(indicatorResult) || Number(indicatorResult) === 0) return false
689
- // 测算结果或 calcVal 已按 0 落库 → 用户真实把指标值调成 0
690
- if (hasEchoValue(result) && Number(result) === 0) return false
692
+ // 尚无指标原值:后端未调整占位 0,不能回显到输入框
693
+ if (!hasEchoValue(indicatorResult)) return true
694
+ if (Number(indicatorResult) === 0) return false
695
+ // 真实把指标值调成 0 后重算,calcVal 会按 0 落库;得分 result 对调整指标值场景不可靠(常为 0)
691
696
  if (hasEchoValue(calcVal) && Number(calcVal) === 0) return false
692
697
  return true
693
698
  }
@@ -727,13 +732,17 @@ export function resolveCalcEchoValue(target, source) {
727
732
  return undefined
728
733
  }
729
734
  if (target.itemType !== 22 && Number(target.modifyRank) === 2) {
730
- return resolveAdjustInputValue({
735
+ const adjustVal = resolveAdjustInputValue({
731
736
  modifyRank: 2,
732
737
  modifiedVal: source.modifiedVal,
733
738
  indicatorResult: source.indicatorResult,
734
739
  result: source.result,
735
740
  calcVal: source.calcVal
736
741
  })
742
+ if (adjustVal !== undefined) return adjustVal
743
+ // 假 0 / 未调整:回退最新测算指标值,避免首次测算后输入框停在 0(story 2206036)
744
+ if (hasEchoValue(source.indicatorResult)) return source.indicatorResult
745
+ return undefined
737
746
  }
738
747
  return undefined
739
748
  }
@@ -368,6 +368,14 @@ export default {
368
368
  type: Object,
369
369
  default: () => ({})
370
370
  },
371
+ /**
372
+ * 打印/另存为文件名(可不含 .pdf)
373
+ * 业务侧传入如「XX公司授信测算详情」;未传时回退 model.code / 测算结果
374
+ */
375
+ downloadFileName: {
376
+ type: String,
377
+ default: ''
378
+ },
371
379
  /**
372
380
  * 是否默认收起分组/分区
373
381
  * false(默认):模型加载后全部展开
@@ -1186,11 +1194,27 @@ export default {
1186
1194
  return
1187
1195
  }
1188
1196
  if (action === 'print') {
1189
- printJS({
1190
- printable: res.data,
1191
- type: 'pdf',
1192
- base64: true
1193
- })
1197
+ // PDF blob 打印时 printJS 的 documentTitle 不生效,临时改 document.title
1198
+ // 供浏览器「另存为 PDF」预填文件名(Edge/Chrome 部分场景)
1199
+ const printTitle = this.resolvePrintFileBaseName()
1200
+ const prevTitle = document.title
1201
+ if (printTitle) {
1202
+ document.title = printTitle
1203
+ }
1204
+ try {
1205
+ printJS({
1206
+ printable: res.data,
1207
+ type: 'pdf',
1208
+ base64: true,
1209
+ documentTitle: printTitle
1210
+ })
1211
+ } finally {
1212
+ if (printTitle) {
1213
+ setTimeout(() => {
1214
+ document.title = prevTitle
1215
+ }, 1000)
1216
+ }
1217
+ }
1194
1218
  } else {
1195
1219
  this.downloadPdfBase64(res.data)
1196
1220
  }
@@ -1201,6 +1225,18 @@ export default {
1201
1225
  this.printLoading = false
1202
1226
  }
1203
1227
  },
1228
+ /**
1229
+ * 解析打印/下载文件名(不含 .pdf)
1230
+ * 时间:2026-10-29 17:27:04
1231
+ * 人员:AI && 徐红飞
1232
+ * 入参:无
1233
+ * 出参:文件名基名
1234
+ * 方法内容:优先 downloadFileName,否则 model.code,再否则「测算结果」
1235
+ */
1236
+ resolvePrintFileBaseName() {
1237
+ const raw = this.downloadFileName || (this.model && this.model.code) || '测算结果'
1238
+ return String(raw).replace(/\.pdf$/i, '')
1239
+ },
1204
1240
  downloadPdfBase64(base64) {
1205
1241
  const pure = String(base64 || '').replace(/^data:application\/pdf;base64,/, '')
1206
1242
  const binary = atob(pure)
@@ -1213,7 +1249,7 @@ export default {
1213
1249
  const url = URL.createObjectURL(blob)
1214
1250
  const a = document.createElement('a')
1215
1251
  a.href = url
1216
- a.download = `${(this.model && this.model.code) || '测算结果'}.pdf`
1252
+ a.download = `${this.resolvePrintFileBaseName()}.pdf`
1217
1253
  document.body.appendChild(a)
1218
1254
  a.click()
1219
1255
  document.body.removeChild(a)