@nstc-business/imes 1.0.20 → 1.0.22

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.
@@ -32,14 +32,14 @@
32
32
  <el-table-column
33
33
  prop="name"
34
34
  label="指标项名称"
35
- width="250"
35
+ min-width="160"
36
36
  align="center"
37
37
  />
38
38
  <el-table-column
39
39
  v-for="col in dynamicColumns(block)"
40
40
  :key="col.prop"
41
41
  :label="col.label"
42
- :width="col.width || 250"
42
+ :min-width="col.minWidth || 140"
43
43
  align="center"
44
44
  >
45
45
  <template slot-scope="{ row }">
@@ -114,6 +114,30 @@ export default {
114
114
  return []
115
115
  }
116
116
  },
117
+ /** 嵌套统计模型时父模没有 modelStatsSetupVOS,按子模型 ID 拉取统计项配置 */
118
+ async ensureModelStatsSetup(modelWrap) {
119
+ const existing =
120
+ (modelWrap && modelWrap.modelStatsSetupVOS) ||
121
+ (this.subModel && this.subModel.modelStatsSetupVOS)
122
+ if (Array.isArray(existing) && existing.length) return existing
123
+ const id =
124
+ (this.subModel && (this.subModel.itemID || this.subModel.modelID)) ||
125
+ (modelWrap && modelWrap.modelID)
126
+ if (!id) return null
127
+ try {
128
+ const { code, data } = await this.$axios.post(
129
+ withRequestTimestamp('/imes/v1/indicatorModel/getModelById'),
130
+ { id }
131
+ )
132
+ if (code === 0 && data && Array.isArray(data.modelStatsSetupVOS)) {
133
+ this.$set(this.subModel, 'modelStatsSetupVOS', data.modelStatsSetupVOS)
134
+ return data.modelStatsSetupVOS
135
+ }
136
+ } catch (e) {
137
+ /* ignore */
138
+ }
139
+ return null
140
+ },
117
141
  async loadTables() {
118
142
  if (!this.subModel || !hasStatPivotNodes(this.subModel)) {
119
143
  this.tableData = []
@@ -121,10 +145,16 @@ export default {
121
145
  }
122
146
  this.loading = true
123
147
  try {
148
+ const modelWrap = this.ctx.modelWrap || {}
149
+ await this.ensureModelStatsSetup(modelWrap)
124
150
  this.tableData = await buildStatModelTables(
125
151
  this.subModel,
126
152
  id => this.fetchScoreMap(id),
127
- this.ctx.modelWrap
153
+ {
154
+ ...modelWrap,
155
+ modelStatsSetupVOS:
156
+ this.subModel.modelStatsSetupVOS || modelWrap.modelStatsSetupVOS
157
+ }
128
158
  )
129
159
  } finally {
130
160
  this.loading = false
@@ -1,9 +1,10 @@
1
1
  <template>
2
2
  <div class="measure-sub-model-panel">
3
- <!-- 计算模型:树形表格 + 定性分组描述列表 -->
4
- <measure-tree-table
3
+ <!-- 计算模型:分组外提为区块标题,指标用树表 -->
4
+ <measure-group-blocks
5
5
  v-if="isCalc"
6
6
  :nodes="subModel.children || []"
7
+ :group-node="subModel"
7
8
  :level="level"
8
9
  :number-prefix="numberPrefix"
9
10
  calc-mode
@@ -38,7 +39,7 @@ export default {
38
39
  components: {
39
40
  MeasureEvalFlatTable,
40
41
  MeasureStatPanel,
41
- MeasureTreeTable: () => import('./MeasureTreeTable.vue')
42
+ MeasureGroupBlocks: () => import('./MeasureGroupBlocks.vue')
42
43
  },
43
44
  props: {
44
45
  subModel: {
@@ -229,7 +229,7 @@
229
229
  </vxe-column>
230
230
  </template>
231
231
 
232
- <!-- 默认列:指标满分值 / 指标值 / 指标得分 / 理由 -->
232
+ <!-- 默认列:满分值 / 计算公式 / 评价标准 / 指标值 / 指标得分 / 模型指标得分 / 理由 -->
233
233
  <template v-else>
234
234
  <vxe-column title="指标满分值" width="110" align="center">
235
235
  <template #default="{ row }">
@@ -238,6 +238,25 @@
238
238
  </template>
239
239
  </vxe-column>
240
240
 
241
+ <vxe-column
242
+ v-if="showFormulaCol"
243
+ field="displayFormula"
244
+ title="计算公式"
245
+ width="130"
246
+ align="center"
247
+ >
248
+ <template #default="{ row }">{{ row.displayFormula || '—' }}</template>
249
+ </vxe-column>
250
+ <vxe-column
251
+ v-if="showRemarkCol"
252
+ field="indicatorRemark"
253
+ title="评价标准"
254
+ width="130"
255
+ align="center"
256
+ >
257
+ <template #default="{ row }">{{ row.indicatorRemark || '—' }}</template>
258
+ </vxe-column>
259
+
241
260
  <vxe-column title="指标值" min-width="260" align="center">
242
261
  <template #default="{ row }">
243
262
  <template v-if="isQuantIndicatorFn(row)">
@@ -298,6 +317,17 @@
298
317
  </vxe-column>
299
318
 
300
319
  <vxe-column title="指标得分" width="140" align="center">
320
+ <template #default="{ row }">
321
+ <template v-if="isQuantIndicatorFn(row)">
322
+ <div>{{ indicatorScoreFn(row) }}</div>
323
+ </template>
324
+ <template v-else-if="isSubModelFn(row) && ctx.parentCalced">
325
+ <div>{{ indicatorScoreFn(row) }}</div>
326
+ </template>
327
+ <span v-else class="color-placeholder">—</span>
328
+ </template>
329
+ </vxe-column>
330
+ <vxe-column title="模型指标得分" width="140" align="center">
301
331
  <template #default="{ row }">
302
332
  <template v-if="isQuantIndicatorFn(row)">
303
333
  <div>{{ resultFn(row) }}</div>
@@ -310,7 +340,7 @@
310
340
  :max="row.fullScore"
311
341
  :disabled="ctx.readonly"
312
342
  v-model="row.modifiedResult"
313
- placeholder="修改指标得分"
343
+ placeholder="修改模型指标得分"
314
344
  />
315
345
  </template>
316
346
  <template v-else-if="isSubModelFn(row) && ctx.parentCalced">
@@ -319,24 +349,6 @@
319
349
  <span v-else class="color-placeholder">—</span>
320
350
  </template>
321
351
  </vxe-column>
322
- <vxe-column
323
- v-if="showFormulaCol"
324
- field="displayFormula"
325
- title="计算公式"
326
- width="130"
327
- align="center"
328
- >
329
- <template #default="{ row }">{{ row.displayFormula || '—' }}</template>
330
- </vxe-column>
331
- <vxe-column
332
- v-if="showRemarkCol"
333
- field="indicatorRemark"
334
- title="评价标准"
335
- width="130"
336
- align="center"
337
- >
338
- <template #default="{ row }">{{ row.indicatorRemark || '—' }}</template>
339
- </vxe-column>
340
352
 
341
353
  <vxe-column
342
354
  v-if="showModifyReasonCol"
@@ -404,6 +416,7 @@ import {
404
416
  typeMeta,
405
417
  digitsCalc,
406
418
  resultByShowStyle,
419
+ indicatorScoreText,
407
420
  indicatorResultText,
408
421
  fullScoreText,
409
422
  hierarchySerial,
@@ -567,6 +580,9 @@ export default {
567
580
  resultFn(row) {
568
581
  return resultByShowStyle(row, this.ctx.modelWrap)
569
582
  },
583
+ indicatorScoreFn(row) {
584
+ return indicatorScoreText(row, this.ctx.modelWrap)
585
+ },
570
586
  indicatorTextFn(row) {
571
587
  return indicatorResultText(row, this.ctx.modelWrap)
572
588
  },
@@ -8,6 +8,7 @@
8
8
  * sourceType:0 系统自定义 1 报表取数 2 指标取数 3 手工填报 4 标准值取数 5 系统取值 6 系统取数
9
9
  * modifyRank:0 不调整 1 调整指标得分 2 调整指标值
10
10
  */
11
+ import { N } from 'n20-common-lib'
11
12
  import { toFixedTrunc, addThousands } from '../common'
12
13
  import { resolveManualFillValue, statItemChildren } from './statModelHelper'
13
14
 
@@ -83,15 +84,79 @@ export function isSubModel(row) {
83
84
  return t === 'calcModel' || t === 'evalModel' || t === 'statModel'
84
85
  }
85
86
 
87
+ /** 普通分组(非子模型容器) */
88
+ export function isGroup(row) {
89
+ return isContainer(row) && !isSubModel(row)
90
+ }
91
+
92
+ /** 当前层拆成普通分组 vs 其余(指标/子模型),分组抬到表格外展示 */
93
+ export function splitGroupNodes(nodes) {
94
+ const groups = []
95
+ const loose = []
96
+ if (!Array.isArray(nodes)) return { groups, loose }
97
+ nodes.forEach(node => {
98
+ if (isGroup(node)) groups.push(node)
99
+ else loose.push(node)
100
+ })
101
+ return { groups, loose }
102
+ }
103
+
104
+ /** 节点用于汇总的得分(优先调整后得分) */
105
+ export function nodeScoreValue(node) {
106
+ if (!node) return null
107
+ if (
108
+ node.modifyRank === 1 &&
109
+ node.modifiedResult !== '' &&
110
+ node.modifiedResult != null
111
+ ) {
112
+ return node.modifiedResult
113
+ }
114
+ if (node.result === '' || node.result == null) return null
115
+ return node.result
116
+ }
117
+
118
+ /** 收集分组下叶子指标(子模型不计入得分小计) */
119
+ export function collectIndicatorScoreNodes(nodes, bucket = []) {
120
+ if (!Array.isArray(nodes)) return bucket
121
+ nodes.forEach(n => {
122
+ if (!n) return
123
+ if (isIndicator(n)) {
124
+ bucket.push(n)
125
+ return
126
+ }
127
+ if (isSubModel(n)) return
128
+ if (n.children && n.children.length) {
129
+ collectIndicatorScoreNodes(n.children, bucket)
130
+ }
131
+ })
132
+ return bucket
133
+ }
134
+
135
+ /** 分组得分小计:加总下属指标得分,无有效得分返回 null */
136
+ export function sumIndicatorScores(nodes) {
137
+ const items = collectIndicatorScoreNodes(nodes)
138
+ let has = false
139
+ let total = 0
140
+ items.forEach(n => {
141
+ const val = nodeScoreValue(n)
142
+ if (val === null) return
143
+ const num = Number(val)
144
+ if (Number.isNaN(num)) return
145
+ has = true
146
+ total += num
147
+ })
148
+ return has ? total : null
149
+ }
150
+
86
151
  /** 测算场景下子模型的统一展示名称 */
87
152
  export const SUB_MODEL_LABEL = '测算子模型'
88
153
 
89
154
  /** 子模型独立测算按钮文案 */
90
155
  export const SUB_MODEL_CALC_BTN = '子模型测算'
91
156
 
92
- /** 子模型测算结果展示(优先 resultText,否则格式化 result) 统计模型没有测算结果*/
157
+ /** 子模型测算结果展示(优先 resultText,否则格式化 result) */
93
158
  export function subModelResultText(row, modelWrap) {
94
- if (!row || row.itemType ===13) return ''
159
+ if (!row) return ''
95
160
  if (row.resultText != null && row.resultText !== '') {
96
161
  return row.resultText
97
162
  }
@@ -152,7 +217,7 @@ export function digitsCalc(row, modelWrap) {
152
217
  return modelWrap ? modelWrap.digits : 2
153
218
  }
154
219
 
155
- /** 指标得分 / 模型指标系数数值展示(始终用 result,字段值只在「指标值」列展示) */
220
+ /** 模型指标得分 / 模型指标系数数值(权重之后的 result) */
156
221
  export function resultByShowStyle(row, modelWrap) {
157
222
  let val = ''
158
223
  const digits = digitsCalc(row, modelWrap)
@@ -168,6 +233,21 @@ export function resultByShowStyle(row, modelWrap) {
168
233
  return val
169
234
  }
170
235
 
236
+ /**
237
+ * 指标得分(权重之前):result * 100 / weight
238
+ * 与旧测算详情 valueScore 算法一致;无权重时不展示
239
+ */
240
+ export function indicatorScoreText(row, modelWrap) {
241
+ if (!row || (row.result !== 0 && (row.result === '' || row.result == null))) {
242
+ return ''
243
+ }
244
+ if (!row.weight) {
245
+ return resultByShowStyle(row, modelWrap)
246
+ }
247
+ const digits = digitsCalc(row, modelWrap)
248
+ return N.div(N.mul(row.result, 100, digits + 2), row.weight, digits)
249
+ }
250
+
171
251
  /** 指标满分值展示 */
172
252
  export function fullScoreText(row, modelWrap) {
173
253
  if (!row || (row.fullScore !== 0 && !row.fullScore)) return ''