@nstc-business/imes 1.0.39 → 1.0.40

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.0.39",
3
+ "version": "1.0.40",
4
4
  "private": false,
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -245,6 +245,7 @@ import {
245
245
  showLevelSerial,
246
246
  isShowFullScore
247
247
  } from './helpers'
248
+ import { fillQualReasonFromOption } from './qualReason'
248
249
 
249
250
  export default {
250
251
  name: 'MeasureEvalFlatTable',
@@ -337,6 +338,8 @@ export default {
337
338
  this.$set(target, 'scoreText', option.scoreText)
338
339
  this.$set(target, 'scoreValue', option.scoreValue)
339
340
  target.picker = option
341
+ fillQualReasonFromOption(target, option, true)
342
+ this.$set(target, 'reason', target.reason)
340
343
  this.syncQual(target, {
341
344
  itemID: target.itemID,
342
345
  scoreMapID: option.scoreMapID,
@@ -154,6 +154,7 @@ import {
154
154
  fullScoreText,
155
155
  isShowFullScore
156
156
  } from './helpers'
157
+ import { fillQualReasonFromOption } from './qualReason'
157
158
 
158
159
  export default {
159
160
  name: 'MeasureQualAnalysis',
@@ -251,13 +252,15 @@ export default {
251
252
  const resolve = this.measureCtx().resolveLeafNode
252
253
  return resolve ? resolve(node) || node : node
253
254
  },
254
- applyNodeSelection(node, option) {
255
+ applyNodeSelection(node, option, forceReason = false) {
255
256
  if (!node || !option) return
256
257
  this.$set(node, 'value', option)
257
258
  this.$set(node, 'scoreMapID', option.scoreMapID)
258
259
  this.$set(node, 'scoreText', option.scoreText)
259
260
  this.$set(node, 'scoreValue', option.scoreValue)
260
261
  this.$set(node, 'picker', option)
262
+ fillQualReasonFromOption(node, option, forceReason)
263
+ this.$set(node, 'reason', node.reason)
261
264
  },
262
265
  pushQualDraft(node, patch) {
263
266
  const sync = this.measureCtx().syncQualSelection
@@ -280,7 +283,7 @@ export default {
280
283
  item => item.scoreMapID == scoreMapID
281
284
  )
282
285
  if (!option) return
283
- this.applyNodeSelection(target, option)
286
+ this.applyNodeSelection(target, option, true)
284
287
  this.$set(target, 'result', null)
285
288
  this.pushQualDraft(target, {
286
289
  itemID: target.itemID,
@@ -313,7 +316,7 @@ export default {
313
316
  const option = (node.optionList || []).find(
314
317
  o => o.scoreMapID == draft.scoreMapID
315
318
  )
316
- if (option) this.applyNodeSelection(node, option)
319
+ if (option) this.applyNodeSelection(node, option, false)
317
320
  }
318
321
  if (draft.reason != null && draft.reason !== node.reason) {
319
322
  this.$set(node, 'reason', draft.reason)
@@ -0,0 +1,58 @@
1
+ /**
2
+ * 定性指标评价理由回填:选选项带到节点 reason;测算结果非空 reason 才覆盖
3
+ */
4
+ const fs = require('fs')
5
+ const path = require('path')
6
+
7
+ const src = fs
8
+ .readFileSync(path.join(__dirname, 'qualReason.js'), 'utf8')
9
+ .replace(/export /g, '')
10
+ const exported = {}
11
+ new Function(
12
+ 'exports',
13
+ src +
14
+ '\nexports.hasFilledReason = hasFilledReason' +
15
+ '\nexports.fillQualReasonFromOption = fillQualReasonFromOption' +
16
+ '\nexports.mergeCalcResultReason = mergeCalcResultReason'
17
+ )(exported)
18
+
19
+ const { hasFilledReason, fillQualReasonFromOption, mergeCalcResultReason } = exported
20
+
21
+ function assert(cond, msg) {
22
+ if (!cond) throw new Error(msg)
23
+ }
24
+
25
+ assert(hasFilledReason('有内容') === true, '非空理由应为 true')
26
+ assert(hasFilledReason('') === false, '空字符串应为 false')
27
+ assert(hasFilledReason(' ') === false, '空白应为 false')
28
+ assert(hasFilledReason(null) === false, 'null 应为 false')
29
+
30
+ const option = { scoreMapID: 1, scoreText: '否', reason: '至少下调1级,最低调至CC级' }
31
+
32
+ const emptyNode = { reason: '' }
33
+ fillQualReasonFromOption(emptyNode, option, false)
34
+ assert(emptyNode.reason === option.reason, '节点理由为空时应从选项带回,实际: ' + emptyNode.reason)
35
+
36
+ const savedNode = { reason: '用户已保存的理由' }
37
+ fillQualReasonFromOption(savedNode, option, false)
38
+ assert(savedNode.reason === '用户已保存的理由', '回显时不应覆盖已有理由')
39
+
40
+ const selectNode = { reason: '旧选项理由' }
41
+ fillQualReasonFromOption(selectNode, option, true)
42
+ assert(selectNode.reason === option.reason, '用户新选选项时应覆盖为当前选项理由')
43
+
44
+ const noOptionReason = { reason: '' }
45
+ fillQualReasonFromOption(noOptionReason, { reason: '' }, true)
46
+ assert(noOptionReason.reason === '', '选项没有理由时不应写脏值')
47
+
48
+ const target = { reason: '界面上已填' }
49
+ mergeCalcResultReason(target, { reason: '测算日志理由' })
50
+ assert(target.reason === '测算日志理由', '测算回写非空理由应覆盖')
51
+
52
+ mergeCalcResultReason(target, { reason: '' })
53
+ assert(target.reason === '测算日志理由', '测算回写空理由不应把界面理由冲掉')
54
+
55
+ mergeCalcResultReason(target, {})
56
+ assert(target.reason === '测算日志理由', '测算结果无 reason 字段时保持原值')
57
+
58
+ console.log('helpers.qualReason.test.js ok')
@@ -258,6 +258,7 @@ import {
258
258
  } from './helpers'
259
259
  import { preprocessStatIndicatorDeepList, mergeStatModelNode, statItemChildren } from './statModelHelper'
260
260
  import { withRequestTimestamp } from './api'
261
+ import { fillQualReasonFromOption, mergeCalcResultReason } from './qualReason'
261
262
  import { formatFloat2 } from '../common'
262
263
  import { printJS } from 'n20-common-lib/src/plugins/Print'
263
264
  import calculateDetailDialog from '../calculateDetail/dialog.vue'
@@ -653,6 +654,8 @@ export default {
653
654
  this.$set(target, 'scoreText', selected.scoreText)
654
655
  this.$set(target, 'scoreValue', selected.scoreValue)
655
656
  this.$set(target, 'picker', selected)
657
+ fillQualReasonFromOption(target, selected, false)
658
+ this.$set(target, 'reason', target.reason)
656
659
  })
657
660
  }
658
661
  return selected || null
@@ -808,6 +811,7 @@ export default {
808
811
  const matched =
809
812
  data.find(o => o.scoreMapID == row.scoreMapID) ||
810
813
  data.find(o => o.scoreText == row.scoreText) ||
814
+ data.find(o => o.scoreText == row.indicatorValText) ||
811
815
  data.find(o => o.scoreValue == row.indicatorResult)
812
816
  if (matched) {
813
817
  this.$set(row, 'value', matched)
@@ -815,6 +819,8 @@ export default {
815
819
  this.$set(row, 'scoreText', matched.scoreText)
816
820
  this.$set(row, 'scoreValue', matched.scoreValue)
817
821
  this.$set(row, 'picker', matched)
822
+ fillQualReasonFromOption(row, matched, false)
823
+ this.$set(row, 'reason', row.reason)
818
824
  }
819
825
  }
820
826
  } catch (e) {
@@ -1392,6 +1398,9 @@ export default {
1392
1398
  this.$set(target, key, source[key])
1393
1399
  }
1394
1400
  })
1401
+ if (mergeCalcResultReason(target, source)) {
1402
+ this.$set(target, 'reason', target.reason)
1403
+ }
1395
1404
  // 未调整时后端 modifiedVal 常为 0,不能覆盖手工填报的指标值
1396
1405
  if (shouldApplyModifiedVal(target, source)) {
1397
1406
  this.$set(target, 'modifiedVal', source.modifiedVal)
@@ -0,0 +1,29 @@
1
+ /**
2
+ * 定性指标评价理由回填
3
+ * 时间:2026-09-21;人员:AI && 徐红飞;入参:节点/选项/测算结果;出参:是否写回;方法内容:选项理由带到评价理由,测算空值不覆盖
4
+ */
5
+
6
+ export function hasFilledReason(val) {
7
+ return val != null && String(val).trim() !== ''
8
+ }
9
+
10
+ /**
11
+ * 把评分选项上的评价说明写到节点评价理由。
12
+ * force=true:用户刚选选项,用当前选项 reason 覆盖。
13
+ * force=false:回显/拉选项,仅当节点 reason 为空时补齐,避免冲掉日志里已保存的理由。
14
+ */
15
+ export function fillQualReasonFromOption(row, option, force = false) {
16
+ if (!row || !option) return false
17
+ if (!hasFilledReason(option.reason)) return false
18
+ if (!force && hasFilledReason(row.reason)) return false
19
+ row.reason = option.reason
20
+ return true
21
+ }
22
+
23
+ /** 测算结果回写:仅非空 reason 覆盖,避免空串冲掉界面已填理由 */
24
+ export function mergeCalcResultReason(target, source) {
25
+ if (!target || !source) return false
26
+ if (!hasFilledReason(source.reason)) return false
27
+ target.reason = source.reason
28
+ return true
29
+ }