@nstc-business/imes 1.0.11 → 1.0.13

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/README.md CHANGED
@@ -27,15 +27,29 @@ export default {
27
27
  :code="modelCode"
28
28
  :log-id="logId"
29
29
  :model-data="modelData"
30
+ :readonly="isReadonly"
30
31
  :show-measure-cond="true"
31
32
  :cond-param="condParam"
32
33
  @calcResult="handleCalcResult"
33
34
  @getLogId="handleLogId"
35
+ @modelLoaded="handleModelLoaded"
36
+ @calcComplete="handleCalcComplete"
34
37
  />
35
38
  ```
36
39
 
37
40
  `modelData` 和 `id/code/logId` 二选一;传入 `modelData` 时优先使用完整模型数据。执行测算时必须提供 `condParam.cltNo`,或开启 `showMeasureCond` 由用户填写单位编号。
38
41
 
42
+ `readonly` 会隐藏整体和子模型测算按钮,并禁用所有录入项,展开、收起和锚点查看仍然可用。`modelLoaded` 返回组件归一化后的模型值,`calcComplete` 返回完整测算结果;原有的 `calcResult` 和 `getLogId` 事件继续兼容。
43
+
44
+ 宿主保存或提交前可通过公开方法完成校验和取值:
45
+
46
+ ```js
47
+ const validation = this.$refs.measureCalc.validate({ silent: true })
48
+ const value = this.$refs.measureCalc.getValue()
49
+ ```
50
+
51
+ `getValue()` 包含模型编号、版本、日志 ID、结果、测算入参以及兼容旧评级申报书的 `qualitativeData` 字符串。
52
+
39
53
  宿主项目需要先安装 Element UI 和 n20-common-lib。`Vue.use(n20)` 会注入组件使用的 `$axios`:
40
54
 
41
55
  ```js
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nstc-business/imes",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "private": false,
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -63,6 +63,7 @@
63
63
  <el-select
64
64
  class="full-w"
65
65
  :value="resolveRow(row).scoreMapID"
66
+ :disabled="ctx.readonly"
66
67
  size="small"
67
68
  placeholder="请选择"
68
69
  @change="val => onQualChange(row, val)"
@@ -86,6 +87,7 @@
86
87
  size="small"
87
88
  :type="row.displayStyle === 1 ? 'rate' : 'money'"
88
89
  :d-num="digitsFn(row)"
90
+ :disabled="ctx.readonly"
89
91
  v-model="resolveRow(row).value"
90
92
  />
91
93
  <InputNumber
@@ -98,6 +100,7 @@
98
100
  size="small"
99
101
  :type="row.displayStyle === 1 ? 'rate' : 'money'"
100
102
  :d-num="digitsFn(row)"
103
+ :disabled="ctx.readonly"
101
104
  v-model="resolveRow(row).value"
102
105
  />
103
106
  <el-tooltip
@@ -128,6 +131,7 @@
128
131
  class="full-w"
129
132
  :d-num="ctx.modelWrap.digits"
130
133
  :max="row.fullScore"
134
+ :disabled="ctx.readonly"
131
135
  v-model="row.modifiedResult"
132
136
  placeholder="修改指标得分"
133
137
  />
@@ -173,6 +177,7 @@
173
177
  :class="{ reasonRequireRed: manualReasonRed(row) }"
174
178
  :show-overflow-tooltip="true"
175
179
  :maxlength="1000"
180
+ :disabled="ctx.readonly"
176
181
  show-word-limit
177
182
  v-model="resolveRow(row).modifiedReason"
178
183
  :placeholder="reasonPlaceholder(row, 'manual')"
@@ -183,6 +188,7 @@
183
188
  v-title
184
189
  :show-overflow-tooltip="true"
185
190
  :maxlength="2000"
191
+ :disabled="ctx.readonly"
186
192
  show-word-limit
187
193
  v-model="resolveRow(row).reason"
188
194
  placeholder="请输入具体评价依据,不超过2000字"
@@ -195,6 +201,7 @@
195
201
  :class="{ reasonRequireRed: adjustReasonRed(row) }"
196
202
  :show-overflow-tooltip="true"
197
203
  :maxlength="1000"
204
+ :disabled="ctx.readonly"
198
205
  show-word-limit
199
206
  v-model="resolveRow(row).modifiedReason"
200
207
  :placeholder="reasonPlaceholder(row, 'adjust')"
@@ -37,6 +37,7 @@
37
37
  <el-select
38
38
  class="qual-select"
39
39
  :value="node.scoreMapID"
40
+ :disabled="readonly"
40
41
  size="small"
41
42
  placeholder="请选择"
42
43
  @change="val => onSelectChange(node, val)"
@@ -72,6 +73,7 @@
72
73
  :maxlength="2000"
73
74
  show-word-limit
74
75
  v-model="node.reason"
76
+ :disabled="readonly"
75
77
  placeholder="请输入具体评价依据,不超过2000字"
76
78
  @input="onReasonInput(node)"
77
79
  />
@@ -93,6 +95,7 @@
93
95
  type="number"
94
96
  size="small"
95
97
  v-model="node.scoreValue"
98
+ :disabled="readonly"
96
99
  placeholder="请输入评分"
97
100
  />
98
101
  </div>
@@ -119,6 +122,9 @@ export default {
119
122
  modelWrap() {
120
123
  return this.measureCtx().modelWrap || {}
121
124
  },
125
+ readonly() {
126
+ return !!this.measureCtx().readonly
127
+ },
122
128
  showSerial() {
123
129
  return showLevelSerial(this.modelWrap)
124
130
  },
@@ -3,7 +3,7 @@
3
3
  <template v-if="!cell">—</template>
4
4
  <!-- 手工填报 -->
5
5
  <template v-else-if="cell.sourceType === 3">
6
- <span v-if="column.disabled">{{ displayValue(cell) }}</span>
6
+ <span v-if="column.disabled || readonly">{{ displayValue(cell) }}</span>
7
7
  <InputNumber
8
8
  v-else
9
9
  class="full-w"
@@ -15,7 +15,7 @@
15
15
  </template>
16
16
  <!-- 不可量化下拉 -->
17
17
  <template v-else-if="cell.sourceType === 0">
18
- <span v-if="column.disabled">{{ displayValue(cell) }}</span>
18
+ <span v-if="column.disabled || readonly">{{ displayValue(cell) }}</span>
19
19
 
20
20
  <el-select
21
21
  v-else
@@ -45,6 +45,7 @@
45
45
  cell.value !== '' &&
46
46
  cell.value !== null &&
47
47
  !column.disabled
48
+ && !readonly
48
49
  "
49
50
  class="full-w"
50
51
  size="small"
@@ -64,11 +65,17 @@ import { toFixedTrunc, addThousands } from '../common'
64
65
  export default {
65
66
  name: 'MeasureStatCell',
66
67
  components: { InputNumber },
68
+ inject: ['measureCtx'],
67
69
  props: {
68
70
  cell: { type: Object, default: null },
69
71
  column: { type: Object, default: () => ({}) },
70
72
  digits: { type: Number, default: 2 }
71
73
  },
74
+ computed: {
75
+ readonly() {
76
+ return !!this.measureCtx().readonly
77
+ }
78
+ },
72
79
  methods: {
73
80
  displayValue(cell) {
74
81
  if (this.column.disabled) {
@@ -33,6 +33,7 @@
33
33
  <el-select
34
34
  class="full-w"
35
35
  v-model="row.value"
36
+ :disabled="ctx.readonly"
36
37
  size="small"
37
38
  placeholder="请选择"
38
39
  value-key="scoreMapID"
@@ -65,6 +66,7 @@
65
66
  size="small"
66
67
  :type="row.displayStyle === 1 ? 'rate' : 'money'"
67
68
  :d-num="digitsFn(row)"
69
+ :disabled="ctx.readonly"
68
70
  v-model="row.value"
69
71
  placeholder="请输入"
70
72
  />
@@ -78,6 +80,7 @@
78
80
  size="small"
79
81
  :type="row.displayStyle === 1 ? 'rate' : 'money'"
80
82
  :d-num="digitsFn(row)"
83
+ :disabled="ctx.readonly"
81
84
  v-model="row.value"
82
85
  placeholder="请输入"
83
86
  />
@@ -97,6 +100,7 @@
97
100
  class="full-w"
98
101
  :d-num="ctx.modelWrap.digits"
99
102
  :max="row.fullScore"
103
+ :disabled="ctx.readonly"
100
104
  v-model="row.modifiedResult"
101
105
  placeholder="修改指标得分"
102
106
  />
@@ -15,6 +15,7 @@
15
15
  <div v-if="isSubModelFn(row)" class="sub-toolbar">
16
16
  <div>
17
17
  <el-button
18
+ v-if="!ctx.readonly"
18
19
  type="primary"
19
20
  size="small"
20
21
  :loading="row._calcing"
@@ -134,6 +135,7 @@
134
135
  size="small"
135
136
  :type="row.displayStyle === 1 ? 'rate' : 'money'"
136
137
  :d-num="digitsFn(row)"
138
+ :disabled="ctx.readonly"
137
139
  v-model="row.value"
138
140
  placeholder="请输入"
139
141
  />
@@ -147,6 +149,7 @@
147
149
  size="small"
148
150
  :type="row.displayStyle === 1 ? 'rate' : 'money'"
149
151
  :d-num="digitsFn(row)"
152
+ :disabled="ctx.readonly"
150
153
  v-model="row.value"
151
154
  placeholder="请输入"
152
155
  />
@@ -173,6 +176,7 @@
173
176
  "
174
177
  class="full-w"
175
178
  :d-num="digitsFn(row)"
179
+ :disabled="ctx.readonly"
176
180
  v-model="row.modifiedResult"
177
181
  placeholder="请输入"
178
182
  />
@@ -204,6 +208,7 @@
204
208
  :class="{ reasonRequireRed: manualReasonRequireRedFn(row) }"
205
209
  :show-overflow-tooltip="true"
206
210
  :maxlength="1000"
211
+ :disabled="ctx.readonly"
207
212
  show-word-limit
208
213
  v-model="row.modifiedReason"
209
214
  :placeholder="manualReasonPlaceholderFn(row)"
@@ -215,6 +220,7 @@
215
220
  :class="{ reasonRequireRed: adjustReasonRequireRedFn(row) }"
216
221
  :show-overflow-tooltip="true"
217
222
  :maxlength="1000"
223
+ :disabled="ctx.readonly"
218
224
  show-word-limit
219
225
  v-model="row.modifiedReason"
220
226
  :placeholder="adjustReasonPlaceholderFn(row)"
@@ -242,6 +248,7 @@
242
248
  size="small"
243
249
  :type="row.displayStyle === 1 ? 'rate' : 'money'"
244
250
  :d-num="digitsFn(row)"
251
+ :disabled="ctx.readonly"
245
252
  v-model="row.value"
246
253
  />
247
254
 
@@ -256,6 +263,7 @@
256
263
  size="small"
257
264
  :type="row.displayStyle === 1 ? 'rate' : 'money'"
258
265
  :d-num="digitsFn(row)"
266
+ :disabled="ctx.readonly"
259
267
  v-model="row.value"
260
268
  />
261
269
 
@@ -300,6 +308,7 @@
300
308
  class="full-w"
301
309
  :d-num="ctx.modelWrap.digits"
302
310
  :max="row.fullScore"
311
+ :disabled="ctx.readonly"
303
312
  v-model="row.modifiedResult"
304
313
  placeholder="修改指标得分"
305
314
  />
@@ -351,6 +360,7 @@
351
360
  :class="{ reasonRequireRed: manualReasonRequireRedFn(row) }"
352
361
  :show-overflow-tooltip="true"
353
362
  :maxlength="1000"
363
+ :disabled="ctx.readonly"
354
364
  show-word-limit
355
365
  v-model="row.modifiedReason"
356
366
  :placeholder="manualReasonPlaceholderFn(row)"
@@ -362,6 +372,7 @@
362
372
  :class="{ reasonRequireRed: adjustReasonRequireRedFn(row) }"
363
373
  :show-overflow-tooltip="true"
364
374
  :maxlength="1000"
375
+ :disabled="ctx.readonly"
365
376
  show-word-limit
366
377
  v-model="row.modifiedReason"
367
378
  :placeholder="adjustReasonPlaceholderFn(row)"
@@ -13,6 +13,7 @@
13
13
  </div>
14
14
  <div class="header-actions">
15
15
  <el-button
16
+ v-if="!readonly"
16
17
  type="primary"
17
18
  size="small"
18
19
  :loading="calcLoading"
@@ -87,6 +88,7 @@
87
88
  <div class="cond-row">
88
89
  <el-form-item label="单位编号" label-width="80px">
89
90
  <el-select
91
+ :disabled="readonly"
90
92
  v-model="param.cltNo"
91
93
  filterable
92
94
  remote
@@ -107,6 +109,7 @@
107
109
  </el-form-item>
108
110
  <el-form-item label="报表年份" label-width="80px">
109
111
  <el-date-picker
112
+ :disabled="readonly"
110
113
  class="input-w"
111
114
  v-model="param.reportYear"
112
115
  type="year"
@@ -116,7 +119,7 @@
116
119
  />
117
120
  </el-form-item>
118
121
  <el-form-item label="报表月份" label-width="80px">
119
- <el-select v-model="param.reportMonth" placeholder="请选择">
122
+ <el-select v-model="param.reportMonth" placeholder="请选择" :disabled="readonly">
120
123
  <el-option
121
124
  v-for="item in options"
122
125
  :key="item.value"
@@ -145,7 +148,7 @@
145
148
  <div class="section-header">
146
149
  <div>
147
150
  <el-button
148
- v-if="section.container && isSubModel(section.container)"
151
+ v-if="!readonly && section.container && isSubModel(section.container)"
149
152
  type="primary"
150
153
  size="small"
151
154
  :loading="section.container._calcing"
@@ -263,6 +266,7 @@ export default {
263
266
  calcSubModel: this.calcSubModel,
264
267
  calcMode: this.calcRootModel,
265
268
  parentCalced: this.parentCalced,
269
+ readonly: this.readonly,
266
270
  resolveLeafNode: this.resolveLeafNode,
267
271
  syncQualSelection: this.syncQualSelection,
268
272
  getQualSelection: this.getQualSelection
@@ -290,6 +294,11 @@ export default {
290
294
  type: Object,
291
295
  default: null
292
296
  },
297
+ /** 禁止编辑和测算,但保留查看、展开和锚点操作 */
298
+ readonly: {
299
+ type: Boolean,
300
+ default: false
301
+ },
293
302
  /** 是否展示内部测算条件表单,默认不展示 */
294
303
  showMeasureCond: {
295
304
  type: Boolean,
@@ -332,6 +341,7 @@ export default {
332
341
  cltOptions: [],
333
342
  cltLoading: false,
334
343
  cltSearchTimer: null,
344
+ initSeq: 0,
335
345
  messageStr: '',
336
346
  options: [
337
347
  { value: '13', label: '13月(已审计报表)' },
@@ -401,6 +411,7 @@ export default {
401
411
  },
402
412
  /** 仍有必填项未完善时显示黄字提示 */
403
413
  showIncompleteTip() {
414
+ if (this.readonly) return false
404
415
  if (!this.param.cltNo) return true
405
416
  // 依赖 draft,保证定性选择变更后提示即时刷新
406
417
  const draftMap = this.qualSelectionDraft
@@ -414,6 +425,20 @@ export default {
414
425
  },
415
426
  immediate: true,
416
427
  deep: true
428
+ },
429
+ id() {
430
+ this.init()
431
+ },
432
+ code() {
433
+ this.init()
434
+ },
435
+ logId() {
436
+ this.init()
437
+ },
438
+ modelData: {
439
+ handler() {
440
+ this.init()
441
+ }
417
442
  }
418
443
  },
419
444
  mounted() {
@@ -580,6 +605,7 @@ export default {
580
605
  return node
581
606
  },
582
607
  async init() {
608
+ const seq = ++this.initSeq
583
609
  let data = this.modelData
584
610
  if (!data) {
585
611
  const id = this.id
@@ -592,12 +618,13 @@ export default {
592
618
  '/imes/v1/indicatorModel/getModelTree',
593
619
  { code, id, logId }
594
620
  )
621
+ if (seq !== this.initSeq) return
595
622
  if (res.code === 0) data = res.data
596
623
  } finally {
597
624
  this.loading = false
598
625
  }
599
626
  }
600
- if (data) this.setModel(data)
627
+ if (data && seq === this.initSeq) this.setModel(data)
601
628
  },
602
629
 
603
630
  setModel(data) {
@@ -616,19 +643,44 @@ export default {
616
643
  this.leafList = leafList
617
644
  this.qualList = qualList
618
645
  this.subModelList = subModelList
619
- this.parentCalced = false
646
+ this.parentCalced = !!(
647
+ this.logId ||
648
+ this.model.logId ||
649
+ (this.model.result !== '' && this.model.result != null) ||
650
+ (root.result !== '' && root.result != null)
651
+ )
620
652
  this.qualSelectionDraft = {}
621
- this.resultText = ''
622
- this.calcResult = null
623
- this.scoreFormulaText = ''
624
- this.relFormula = ''
625
- this.displayFormula = ''
653
+ this.resultText = this.model.resultText || root.resultText || ''
654
+ this.calcResult =
655
+ this.model.result !== '' && this.model.result != null
656
+ ? this.model.result
657
+ : root.result !== '' && root.result != null
658
+ ? root.result
659
+ : null
660
+ this.scoreFormulaText =
661
+ this.model.scoreFormulaText ||
662
+ root.scoreFormulaText ||
663
+ (this.parentCalced && this.evalRootModel
664
+ ? this.buildEvalScoreText(this.model)
665
+ : '')
666
+ this.relFormula = this.model.relFormula || root.relFormula || ''
667
+ this.displayFormula =
668
+ this.model.displayFormula || root.displayFormula || ''
669
+ this.businessModuleRemark =
670
+ this.model.businessModuleRemark || root.businessModuleRemark || ''
671
+ this.applyCondParam({
672
+ reportYear: this.model.reportYear,
673
+ reportMonth: this.model.reportMonth,
674
+ cltNo: this.model.cltNo
675
+ })
626
676
  this.sections = this.buildSections(root, children)
627
677
  this.anchorTabs = this.sections.map((s, i) => ({ key: i, name: s.name }))
628
678
  this.activeAnchorName = this.anchorTabs.length
629
679
  ? this.anchorTabs[0].name
630
680
  : ''
631
- this.fetchQualOptions()
681
+ this.fetchQualOptions().then(() => {
682
+ this.$emit('modelLoaded', this.getValue({ silent: true }))
683
+ })
632
684
  },
633
685
 
634
686
  /**
@@ -906,7 +958,7 @@ export default {
906
958
  },
907
959
 
908
960
  /** 收集某节点子树下的所有叶子指标(不含其内层子模型自身行) */
909
- buildCalcParams(leaves) {
961
+ buildCalcParams(leaves, options = {}) {
910
962
  let scoreMapList = []
911
963
  let indicatorCalcList = []
912
964
  let state = true
@@ -922,12 +974,52 @@ export default {
922
974
  scoreMapList.push(...r.scoreMapList)
923
975
  indicatorCalcList.push(...r.indicatorCalcList)
924
976
  })
925
- if (this.messageStr) this.$message.warning(this.messageStr)
977
+ if (this.messageStr && !options.silent) this.$message.warning(this.messageStr)
926
978
  return { scoreMapList, indicatorCalcList, state }
927
979
  },
928
980
 
981
+ validate(options = {}) {
982
+ const result = this.buildCalcParams(this.leafList, options)
983
+ return {
984
+ valid: result.state,
985
+ state: result.state,
986
+ scoreMapList: result.scoreMapList,
987
+ indicatorCalcList: result.indicatorCalcList
988
+ }
989
+ },
990
+
991
+ getQualitativeData() {
992
+ return this.qualList
993
+ .filter(item => item && item.code)
994
+ .map(item => `${item.code}:${item.scoreText || '0'};`)
995
+ .join('')
996
+ },
997
+
998
+ getValue(options = {}) {
999
+ const validation = this.validate({ silent: options.silent !== false })
1000
+ return {
1001
+ valid: validation.valid,
1002
+ modelID: this.model.modelID || this.model.id || this.id || '',
1003
+ code: this.model.code || this.code || '',
1004
+ version: this.model.version,
1005
+ logId: this.model.logId || this.logId || '',
1006
+ result: this.calcResult,
1007
+ resultText: this.resultText,
1008
+ maxReportTem: this.model.maxReportTem || '',
1009
+ scoreMapList: validation.scoreMapList,
1010
+ indicatorCalcList: validation.indicatorCalcList,
1011
+ qualitativeData: this.getQualitativeData(),
1012
+ relFormula: this.relFormula,
1013
+ displayFormula: this.displayFormula,
1014
+ businessModuleRemark: this.businessModuleRemark,
1015
+ reportYear: this.param.reportYear,
1016
+ reportMonth: this.param.reportMonth
1017
+ }
1018
+ },
1019
+
929
1020
  /** 外层模型整体测算 */
930
1021
  async calc() {
1022
+ if (this.readonly) return
931
1023
  if (!this.param.cltNo) {
932
1024
  this.$message.warning('请先输入单位编号')
933
1025
  return
@@ -972,8 +1064,19 @@ export default {
972
1064
  ? this.buildEvalScoreText(resData)
973
1065
  : ''
974
1066
  this.businessModuleRemark =resData.businessModuleRemark
1067
+ this.$set(this.model, 'logId', resData.logId || '')
1068
+ this.$set(this.model, 'maxReportTem', resData.maxReportTem || '')
975
1069
  this.$emit('calcResult', resData.resultText)
976
1070
  this.$emit('getLogId', resData.logId)
1071
+ this.$emit('calcComplete', {
1072
+ ...resData,
1073
+ modelID: resData.modelID || this.model.modelID,
1074
+ code: resData.code || this.model.code,
1075
+ version: resData.version != null ? resData.version : this.model.version,
1076
+ relFormula: this.relFormula,
1077
+ displayFormula: this.displayFormula,
1078
+ qualitativeData: this.getQualitativeData()
1079
+ })
977
1080
  this.$message.success('测算完成')
978
1081
  } else {
979
1082
  this.$message.error(res.msg || '测算失败')
@@ -990,6 +1093,7 @@ export default {
990
1093
  * 复用 calcWithChildren 单独算出该子模型的值并回填到子模型节点
991
1094
  */
992
1095
  async calcSubModel(subModel) {
1096
+ if (this.readonly) return
993
1097
  if (!this.param.cltNo) {
994
1098
  this.$message.warning('请先输入单位编号')
995
1099
  return
package/src/index.js CHANGED
@@ -19,7 +19,7 @@ if (typeof window !== 'undefined' && window.Vue) {
19
19
  }
20
20
 
21
21
  export default {
22
- version: '1.0.11',
22
+ version: '1.0.13',
23
23
  install,
24
24
  ModelCalculate,
25
25
  MeasureCalc,