@nstc-business/imes 1.0.22 → 1.0.24

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.22",
3
+ "version": "1.0.24",
4
4
  "private": false,
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -18,7 +18,7 @@
18
18
  :key="group._rowKey || i"
19
19
  class="measure-inner-group"
20
20
  >
21
- <div class="section-title">
21
+ <div class="section-title" @click="toggleGroup(group)">
22
22
  {{ group.name }}
23
23
  <span v-if="group.remark" class="section-remark">
24
24
  备注:<span class="remark-html" v-html="group.remark"></span>
@@ -29,8 +29,13 @@
29
29
  <span v-if="innerSubtotalText(group)" class="section-score-pill">
30
30
  {{ innerSubtotalText(group) }}
31
31
  </span>
32
+ <span class="group-toggle">
33
+ {{ isExpanded(group) ? '收起' : '展开' }}
34
+ <i :class="isExpanded(group) ? 'el-icon-arrow-up' : 'el-icon-arrow-down'"></i>
35
+ </span>
32
36
  </div>
33
37
  <measure-group-blocks
38
+ v-show="isExpanded(group)"
34
39
  :nodes="group.children || []"
35
40
  :group-node="group"
36
41
  :level="level + 1"
@@ -124,6 +129,15 @@ export default {
124
129
  const fn = this.ctx.groupSubtotalText
125
130
  return fn ? fn(group) : ''
126
131
  },
132
+ isExpanded(group) {
133
+ const fn = this.ctx.isGroupExpanded
134
+ return fn ? fn(group) : !group || group._groupExpanded !== false
135
+ },
136
+ toggleGroup(group) {
137
+ const fn = this.ctx.toggleGroupExpanded
138
+ if (fn) fn(group)
139
+ else if (group) this.$set(group, '_groupExpanded', group._groupExpanded === false)
140
+ },
127
141
  childNumberPrefix(group) {
128
142
  const idx = this.nodes.findIndex(n => n._rowKey === group._rowKey)
129
143
  const serial = hierarchySerial(this.numberPrefix, idx < 0 ? 0 : idx)
@@ -153,6 +167,18 @@ export default {
153
167
  padding-left: 8px;
154
168
  margin-bottom: 8px;
155
169
  border-left: 3px solid #409eff;
170
+ cursor: pointer;
171
+ }
172
+ .group-toggle {
173
+ margin-left: auto;
174
+ font-size: 13px;
175
+ font-weight: 400;
176
+ color: #409eff;
177
+ white-space: nowrap;
178
+ user-select: none;
179
+ }
180
+ .group-toggle i {
181
+ margin-left: 2px;
156
182
  }
157
183
  .section-weight-pill,
158
184
  .section-score-pill {
@@ -5,7 +5,7 @@
5
5
  :key="group._groupKey"
6
6
  class="qual-group"
7
7
  >
8
- <div v-if="group.name" class="qual-group-title">
8
+ <div v-if="group.name" class="qual-group-title" @click="toggleGroup(index)">
9
9
  <span v-if="showSerial" class="qual-group-index">{{ index + 1 }}.</span>
10
10
  <span>{{ group.name }}</span>
11
11
  <span
@@ -20,9 +20,14 @@
20
20
  >
21
21
  得分:{{ group.result }}
22
22
  </span>
23
+ <span class="group-toggle">
24
+ {{ isExpanded(index) ? '收起' : '展开' }}
25
+ <i :class="isExpanded(index) ? 'el-icon-arrow-up' : 'el-icon-arrow-down'"></i>
26
+ </span>
23
27
  </div>
24
28
 
25
29
  <vxe-table
30
+ v-show="isExpanded(index)"
26
31
  border
27
32
  class="qual-table"
28
33
  :data="group.children"
@@ -184,6 +189,20 @@ export default {
184
189
  }
185
190
  },
186
191
  methods: {
192
+ sourceGroup(index) {
193
+ return this.groups[index] || this.displayGroups[index]
194
+ },
195
+ isExpanded(index) {
196
+ const group = this.sourceGroup(index)
197
+ const fn = this.measureCtx().isGroupExpanded
198
+ return fn ? fn(group) : !group || group._groupExpanded !== false
199
+ },
200
+ toggleGroup(index) {
201
+ const group = this.sourceGroup(index)
202
+ const fn = this.measureCtx().toggleGroupExpanded
203
+ if (fn) fn(group)
204
+ else if (group) this.$set(group, '_groupExpanded', group._groupExpanded === false)
205
+ },
187
206
  isQualSelectNode(node) {
188
207
  return (
189
208
  node.sourceType === 0 ||
@@ -315,10 +334,11 @@ export default {
315
334
  display: flex;
316
335
  align-items: center;
317
336
  gap: 8px;
318
- height: 30px;
337
+ min-height: 30px;
319
338
  margin-bottom: 8px;
320
339
  font-size: 15px;
321
340
  color: #303133;
341
+ cursor: pointer;
322
342
  }
323
343
 
324
344
  .qual-group-index {
@@ -331,8 +351,16 @@ export default {
331
351
  color: #606266;
332
352
  }
333
353
 
334
- .qual-group-score {
354
+ .group-toggle {
335
355
  margin-left: auto;
356
+ font-size: 13px;
357
+ font-weight: 400;
358
+ color: #409eff;
359
+ white-space: nowrap;
360
+ user-select: none;
361
+ }
362
+ .group-toggle i {
363
+ margin-left: 2px;
336
364
  }
337
365
 
338
366
  .qual-table {
@@ -53,6 +53,18 @@
53
53
  :d-num="digits"
54
54
  v-model="cell.value"
55
55
  />
56
+ <el-tooltip
57
+ v-else-if="showFormulaTip"
58
+ placement="top"
59
+ effect="dark"
60
+ >
61
+ <div slot="content">
62
+ {{ cell.displayFormula }}:
63
+ <br />
64
+ {{ cell.relFormula }}
65
+ </div>
66
+ <span>{{ displayValue(cell) }}</span>
67
+ </el-tooltip>
56
68
  <span v-else>{{ displayValue(cell) }}</span>
57
69
  </template>
58
70
  </div>
@@ -74,6 +86,11 @@ export default {
74
86
  computed: {
75
87
  readonly() {
76
88
  return !!this.measureCtx().readonly
89
+ },
90
+ /** 指标值列才展示公式;得分列 column.disabled 不展示 */
91
+ showFormulaTip() {
92
+ if (!this.cell || this.column.disabled) return false
93
+ return !!(this.cell.displayFormula || this.cell.relFormula)
77
94
  }
78
95
  },
79
96
  methods: {
@@ -53,8 +53,24 @@
53
53
  </el-select>
54
54
  </template>
55
55
  <template v-else>
56
- <span
56
+ <el-tooltip
57
57
  v-if="
58
+ row.sourceType !== 3 &&
59
+ (!row.optionList || !row.optionList.length) &&
60
+ hasFormulaFn(row)
61
+ "
62
+ placement="top"
63
+ effect="dark"
64
+ >
65
+ <div slot="content">
66
+ {{ row.displayFormula }}:
67
+ <br />
68
+ {{ row.relFormula }}
69
+ </div>
70
+ <span>{{ indicatorTextFn(row) }}</span>
71
+ </el-tooltip>
72
+ <span
73
+ v-else-if="
58
74
  row.sourceType !== 3 &&
59
75
  (!row.optionList || !row.optionList.length)
60
76
  "
@@ -175,6 +191,9 @@ export default {
175
191
  indicatorTextFn(row) {
176
192
  return indicatorResultText(row, this.ctx.modelWrap)
177
193
  },
194
+ hasFormulaFn(row) {
195
+ return !!(row && (row.displayFormula || row.relFormula))
196
+ },
178
197
  onQualChange(row) {
179
198
  const option = row.value
180
199
  if (!option || !option.scoreMapID) return
@@ -12,32 +12,15 @@
12
12
  </span>
13
13
  </div>
14
14
  <div class="header-actions">
15
- <el-button
16
- v-if="!readonly"
17
- type="primary"
18
- size="small"
19
- :loading="calcLoading"
20
- @click="calc"
21
- >
15
+ <el-button v-if="!readonly" type="primary" size="small" :loading="calcLoading" @click="calc">
22
16
  整体测算
23
17
  </el-button>
24
- <el-button
25
- v-if="hasAnyContainer"
26
- size="small"
27
- plain
28
- @click="toggleExpandAll"
29
- >
18
+ <el-button v-if="showCalcDetail" size="small" plain @click="openCalcDetail"> 测算详情 </el-button>
19
+ <el-button v-if="showCalcJournal" size="small" plain @click="openCalcJournal"> 测算日志 </el-button>
20
+ <el-button v-if="showPrint" size="small" plain :loading="printLoading" @click="printFn"> 打印 </el-button>
21
+ <el-button v-if="hasCollapsibleGroups" size="small" plain @click="toggleExpandAll">
30
22
  {{ allExpanded ? '全部收起' : '全部展开' }}
31
23
  </el-button>
32
- <el-button
33
- v-if="showPrint"
34
- size="small"
35
- plain
36
- :loading="printLoading"
37
- @click="printFn"
38
- >
39
- 打印
40
- </el-button>
41
24
  </div>
42
25
  </div>
43
26
 
@@ -63,12 +46,7 @@
63
46
  <div v-if="formulaRowLabel" class="result-panel-formula" :title="businessModuleRemark">
64
47
  <span class="meta-label">{{ formulaRowLabel }}</span>
65
48
  <el-tooltip
66
- v-if="
67
- calcRootModel &&
68
- displayFormula &&
69
- relFormula &&
70
- displayFormula !== relFormula
71
- "
49
+ v-if="calcRootModel && displayFormula && relFormula && displayFormula !== relFormula"
72
50
  placement="top"
73
51
  effect="dark"
74
52
  >
@@ -83,11 +61,7 @@
83
61
 
84
62
  <!-- 分区锚点 Tab -->
85
63
  <div v-if="anchorTabs.length > 1" class="measure-anchor">
86
- <SecondaryTab
87
- :init.sync="activeAnchorName"
88
- :data="anchorTabs"
89
- @click="onAnchorClick"
90
- />
64
+ <SecondaryTab :init.sync="activeAnchorName" :data="anchorTabs" @click="onAnchorClick" />
91
65
  </div>
92
66
  </div>
93
67
 
@@ -129,12 +103,7 @@
129
103
  </el-form-item>
130
104
  <el-form-item label="报表月份" label-width="80px">
131
105
  <el-select v-model="param.reportMonth" placeholder="请选择" :disabled="readonly">
132
- <el-option
133
- v-for="item in options"
134
- :key="item.value"
135
- :label="item.label"
136
- :value="item.value"
137
- ></el-option>
106
+ <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
138
107
  </el-select>
139
108
  </el-form-item>
140
109
  </div>
@@ -147,13 +116,7 @@
147
116
  </div>
148
117
 
149
118
  <!-- 评价/计算模型分区 -->
150
- <div
151
- v-else
152
- v-for="(section, i) in sections"
153
- :key="section._rowKey"
154
- :ref="'section-' + i"
155
- class="measure-section"
156
- >
119
+ <div v-else v-for="(section, i) in sections" :key="section._rowKey" :ref="'section-' + i" class="measure-section">
157
120
  <div class="section-header">
158
121
  <div>
159
122
  <el-button
@@ -166,21 +129,13 @@
166
129
  {{ subModelCalcBtn }}
167
130
  </el-button>
168
131
  <span
169
- v-if="
170
- section.container &&
171
- isSubModel(section.container) &&
172
- subModelResultText(section.container)
173
- "
132
+ v-if="section.container && isSubModel(section.container) && subModelResultText(section.container)"
174
133
  class="sub-result"
175
134
  >
176
135
  测算结果:{{ subModelResultText(section.container) }}
177
136
  </span>
178
137
  <el-tooltip
179
- v-if="
180
- section.container &&
181
- isSubModel(section.container) &&
182
- section.container.relFormula
183
- "
138
+ v-if="section.container && isSubModel(section.container) && section.container.relFormula"
184
139
  placement="top"
185
140
  effect="dark"
186
141
  >
@@ -191,7 +146,7 @@
191
146
  </el-tooltip>
192
147
  </div>
193
148
 
194
- <div class="section-title">
149
+ <div class="section-title" @click="toggleGroupExpanded(sectionExpandNode(section))">
195
150
  <template v-if="section.container && isSubModel(section.container)">
196
151
  {{ subModelLabel }}:{{ section.name }}
197
152
  </template>
@@ -200,35 +155,42 @@
200
155
  <span v-if="section.remark" class="section-remark">
201
156
  备注:<span class="remark-html" v-html="section.remark"></span>
202
157
  </span>
203
- <span
204
- v-if="sectionWeightText(section)"
205
- class="section-weight-pill"
206
- >
158
+ <span v-if="sectionWeightText(section)" class="section-weight-pill">
207
159
  {{ sectionWeightText(section) }}
208
160
  </span>
209
- <span
210
- v-if="sectionScoreText(section)"
211
- class="section-score-pill"
212
- >
161
+ <span v-if="sectionScoreText(section)" class="section-score-pill">
213
162
  {{ sectionScoreText(section) }}
214
163
  </span>
164
+ <span class="group-toggle">
165
+ {{ isGroupExpanded(sectionExpandNode(section)) ? '收起' : '展开' }}
166
+ <i
167
+ :class="
168
+ isGroupExpanded(sectionExpandNode(section))
169
+ ? 'el-icon-arrow-up'
170
+ : 'el-icon-arrow-down'
171
+ "
172
+ ></i>
173
+ </span>
215
174
  </div>
216
175
  </div>
217
- <measure-sub-model-panel
218
- v-if="section.container && isSubModel(section.container)"
219
- :sub-model="section.container"
220
- :level="1"
221
- />
222
- <measure-group-blocks
223
- v-else-if="section.nodes && section.nodes.length"
224
- :nodes="section.nodes"
225
- :group-node="section.container"
226
- :level="1"
227
- :calc-mode="calcRootModel"
228
- :section="section"
229
- />
230
- <div v-else class="section-empty">暂无指标</div>
176
+ <div v-show="isGroupExpanded(sectionExpandNode(section))">
177
+ <measure-sub-model-panel
178
+ v-if="section.container && isSubModel(section.container)"
179
+ :sub-model="section.container"
180
+ :level="1"
181
+ />
182
+ <measure-group-blocks
183
+ v-else-if="section.nodes && section.nodes.length"
184
+ :nodes="section.nodes"
185
+ :group-node="section.container"
186
+ :level="1"
187
+ :calc-mode="calcRootModel"
188
+ :section="section"
189
+ />
190
+ <div v-else class="section-empty">暂无指标</div>
191
+ </div>
231
192
  </div>
193
+ <calculate-detail-dialog ref="calculateDetailDialog" />
232
194
  </div>
233
195
  </template>
234
196
 
@@ -254,14 +216,11 @@ import {
254
216
  subModelResultText as formatSubModelResult,
255
217
  saveSubModelValueText
256
218
  } from './helpers'
257
- import {
258
- preprocessStatIndicatorDeepList,
259
- mergeStatModelNode,
260
- statItemChildren
261
- } from './statModelHelper'
219
+ import { preprocessStatIndicatorDeepList, mergeStatModelNode, statItemChildren } from './statModelHelper'
262
220
  import { withRequestTimestamp } from './api'
263
221
  import { formatFloat2 } from '../common'
264
222
  import { printJS } from 'n20-common-lib/src/plugins/Print'
223
+ import calculateDetailDialog from '../calculateDetail/dialog.vue'
265
224
 
266
225
  export default {
267
226
  name: 'MeasureCalc',
@@ -269,13 +228,16 @@ export default {
269
228
  SecondaryTab,
270
229
  MeasureGroupBlocks,
271
230
  MeasureSubModelPanel,
272
- MeasureStatPanel
231
+ MeasureStatPanel,
232
+ calculateDetailDialog
273
233
  },
274
234
  provide() {
275
235
  return {
276
236
  measureCtx: () => ({
277
237
  modelWrap: this.model,
278
238
  expandAll: this.allExpanded,
239
+ isGroupExpanded: node => this.isGroupExpanded(node),
240
+ toggleGroupExpanded: node => this.toggleGroupExpanded(node),
279
241
  calcSubModel: this.calcSubModel,
280
242
  calcMode: this.calcRootModel,
281
243
  parentCalced: this.parentCalced,
@@ -331,6 +293,16 @@ export default {
331
293
  type: Boolean,
332
294
  default: false
333
295
  },
296
+ /** 是否展示测算详情按钮,由业务系统做权限判断后传入,默认不展示 */
297
+ showCalcDetail: {
298
+ type: Boolean,
299
+ default: false
300
+ },
301
+ /** 是否展示测算日志按钮,由业务系统做权限判断后传入,默认不展示 */
302
+ showCalcJournal: {
303
+ type: Boolean,
304
+ default: false
305
+ },
334
306
  /** 授信申报信息,打印时原样传给打印接口 */
335
307
  creditInfo: {
336
308
  type: Object,
@@ -340,6 +312,16 @@ export default {
340
312
  gradeInfo: {
341
313
  type: Object,
342
314
  default: () => ({})
315
+ },
316
+ /** 打印接口地址,业务系统可覆盖 */
317
+ printUrl: {
318
+ type: String,
319
+ default: '/imes/v1/indicatorModel/print'
320
+ },
321
+ /** 打印附加参数,由业务系统传入,组件原样带到打印接口 */
322
+ printParams: {
323
+ type: Object,
324
+ default: () => ({})
343
325
  }
344
326
  },
345
327
  data() {
@@ -464,6 +446,10 @@ export default {
464
446
  return walk(s.nodes)
465
447
  })
466
448
  },
449
+ /** 有分区或子模型时展示全部展开/收起 */
450
+ hasCollapsibleGroups() {
451
+ return this.sections.length > 0 || this.hasAnyContainer
452
+ },
467
453
  /** 仍有必填项未完善时显示黄字提示 */
468
454
  showIncompleteTip() {
469
455
  if (this.readonly) return false
@@ -519,15 +505,11 @@ export default {
519
505
  },
520
506
  findQualNode(tid, itemID, fallback) {
521
507
  if (tid) {
522
- const byTid =
523
- this.leafList.find(n => n.tid === tid) ||
524
- this.qualList.find(n => n.tid === tid)
508
+ const byTid = this.leafList.find(n => n.tid === tid) || this.qualList.find(n => n.tid === tid)
525
509
  if (byTid) return byTid
526
510
  }
527
511
  if (itemID) {
528
- const byId =
529
- this.leafList.find(n => n.itemID === itemID) ||
530
- this.qualList.find(n => n.itemID === itemID)
512
+ const byId = this.leafList.find(n => n.itemID === itemID) || this.qualList.find(n => n.itemID === itemID)
531
513
  if (byId) return byId
532
514
  }
533
515
  if (fallback && fallback._rowKey) {
@@ -557,9 +539,7 @@ export default {
557
539
  }
558
540
  if (next.scoreMapID != null && next.scoreMapID !== '') {
559
541
  this.$set(node, 'scoreMapID', next.scoreMapID)
560
- const option = (node.optionList || []).find(
561
- o => o.scoreMapID == next.scoreMapID
562
- )
542
+ const option = (node.optionList || []).find(o => o.scoreMapID == next.scoreMapID)
563
543
  if (option) {
564
544
  this.$set(node, 'value', option)
565
545
  this.$set(node, 'scoreText', option.scoreText)
@@ -600,12 +580,7 @@ export default {
600
580
  scoreMapID: scoreMapID != null ? scoreMapID : item.scoreMapID
601
581
  })
602
582
  }
603
- if (
604
- !selected &&
605
- draft &&
606
- draft.scoreMapID != null &&
607
- draft.scoreMapID !== ''
608
- ) {
583
+ if (!selected && draft && draft.scoreMapID != null && draft.scoreMapID !== '') {
609
584
  selected =
610
585
  optionList.find(o => o.scoreMapID == draft.scoreMapID) ||
611
586
  (draft.scoreText != null
@@ -658,10 +633,11 @@ export default {
658
633
  if (!id && !code && !logId) return
659
634
  this.loading = true
660
635
  try {
661
- const res = await this.$axios.post(
662
- withRequestTimestamp('/imes/v1/indicatorModel/getModelTree'),
663
- { code, id, logId }
664
- )
636
+ const res = await this.$axios.post(withRequestTimestamp('/imes/v1/indicatorModel/getModelTree'), {
637
+ code,
638
+ id,
639
+ logId
640
+ })
665
641
  if (seq !== this.initSeq) return
666
642
  if (res.code === 0) data = res.data
667
643
  } finally {
@@ -672,10 +648,7 @@ export default {
672
648
  },
673
649
 
674
650
  setModel(data) {
675
- this.model = Object.assign(
676
- { type: 1, name: '', code: '', digits: 2 },
677
- data
678
- )
651
+ this.model = Object.assign({ type: 1, name: '', code: '', digits: 2 }, data)
679
652
  const root = this.model.modelTreeVO || {}
680
653
  const children = Array.isArray(root.children) ? root.children : []
681
654
  preprocessStatIndicatorDeepList(children)
@@ -688,11 +661,7 @@ export default {
688
661
  this.qualList = qualList
689
662
  this.subModelList = subModelList
690
663
  // 仅以模型级测算结果 / 日志为准;分组节点 result 默认 0 不能当作已测算
691
- this.parentCalced = !!(
692
- this.logId ||
693
- this.model.logId ||
694
- (this.model.result !== '' && this.model.result != null)
695
- )
664
+ this.parentCalced = !!(this.logId || this.model.logId || (this.model.result !== '' && this.model.result != null))
696
665
  this.qualSelectionDraft = {}
697
666
  this.resultText = this.model.resultText || root.resultText || ''
698
667
  this.calcResult =
@@ -704,14 +673,10 @@ export default {
704
673
  this.scoreFormulaText =
705
674
  this.model.scoreFormulaText ||
706
675
  root.scoreFormulaText ||
707
- (this.parentCalced && this.evalRootModel
708
- ? this.buildEvalScoreText(this.model)
709
- : '')
676
+ (this.parentCalced && this.evalRootModel ? this.buildEvalScoreText(this.model) : '')
710
677
  this.relFormula = this.model.relFormula || root.relFormula || ''
711
- this.displayFormula =
712
- this.model.displayFormula || root.displayFormula || ''
713
- this.businessModuleRemark =
714
- this.model.businessModuleRemark || root.businessModuleRemark || ''
678
+ this.displayFormula = this.model.displayFormula || root.displayFormula || ''
679
+ this.businessModuleRemark = this.model.businessModuleRemark || root.businessModuleRemark || ''
715
680
  this.applyCondParam({
716
681
  reportYear: this.model.reportYear,
717
682
  reportMonth: this.model.reportMonth,
@@ -719,9 +684,7 @@ export default {
719
684
  })
720
685
  this.sections = this.buildSections(root, children)
721
686
  this.anchorTabs = this.sections.map((s, i) => ({ key: i, name: s.name }))
722
- this.activeAnchorName = this.anchorTabs.length
723
- ? this.anchorTabs[0].name
724
- : ''
687
+ this.activeAnchorName = this.anchorTabs.length ? this.anchorTabs[0].name : ''
725
688
  this.fetchQualOptions().then(() => {
726
689
  this.$emit('modelLoaded', this.getValue({ silent: true }))
727
690
  })
@@ -776,10 +739,9 @@ export default {
776
739
  await Promise.all(
777
740
  this.qualList.map(async row => {
778
741
  try {
779
- const { code, data } = await this.$axios.post(
780
- withRequestTimestamp('/imes/v1/indicator/getScoreMap'),
781
- { id: row.itemID }
782
- )
742
+ const { code, data } = await this.$axios.post(withRequestTimestamp('/imes/v1/indicator/getScoreMap'), {
743
+ id: row.itemID
744
+ })
783
745
  if (code === 0 && Array.isArray(data)) {
784
746
  this.$set(row, 'optionList', data)
785
747
  if (row.scoreMapID == null) this.$set(row, 'scoreMapID', null)
@@ -812,10 +774,9 @@ export default {
812
774
  this.cltSearchTimer = setTimeout(async () => {
813
775
  this.cltLoading = true
814
776
  try {
815
- const res = await this.$axios.post(
816
- withRequestTimestamp('/custman-core/customer/findSimpleList'),
817
- { keyword: query }
818
- )
777
+ const res = await this.$axios.post(withRequestTimestamp('/custman-core/customer/findSimpleList'), {
778
+ keyword: query
779
+ })
819
780
  this.cltOptions = res.code == 200 ? res.data || [] : []
820
781
  } catch (e) {
821
782
  this.cltOptions = []
@@ -837,9 +798,35 @@ export default {
837
798
  if (target) target.scrollIntoView({ behavior: 'smooth', block: 'start' })
838
799
  },
839
800
 
801
+ sectionExpandNode(section) {
802
+ return (section && section.container) || section
803
+ },
804
+ isGroupExpanded(node) {
805
+ return !node || node._groupExpanded !== false
806
+ },
807
+ toggleGroupExpanded(node) {
808
+ if (!node) return
809
+ this.$set(node, '_groupExpanded', node._groupExpanded === false)
810
+ },
811
+ setAllGroupExpanded(expanded) {
812
+ const walk = nodes => {
813
+ if (!Array.isArray(nodes)) return
814
+ nodes.forEach(node => {
815
+ if (!node) return
816
+ if (isContainer(node)) this.$set(node, '_groupExpanded', expanded)
817
+ if (node.children && node.children.length) walk(node.children)
818
+ })
819
+ }
820
+ this.sections.forEach(section => {
821
+ this.$set(section, '_groupExpanded', expanded)
822
+ if (section.container) this.$set(section.container, '_groupExpanded', expanded)
823
+ walk(section.nodes)
824
+ })
825
+ },
840
826
  toggleExpandAll() {
841
827
  // 各层表格通过 watch ctx.expandAll 调用 setRowExpand 联动展开/收起
842
828
  this.allExpanded = !this.allExpanded
829
+ this.setAllGroupExpanded(this.allExpanded)
843
830
  },
844
831
 
845
832
  /** 与测算校验一致:判断指标是否仍有必填未填 */
@@ -871,10 +858,7 @@ export default {
871
858
  /** 单个指标的入参校验与组装(同一指标只组装一条,避免后端 findFirst 丢调整得分) */
872
859
  checkItem(item) {
873
860
  const obj = { scoreMapList: [], indicatorCalcList: [], state: true }
874
- const displayValue =
875
- item.displayStyle === 1
876
- ? formatFloat2(item.value / 100, this.model.digits)
877
- : item.value
861
+ const displayValue = item.displayStyle === 1 ? formatFloat2(item.value / 100, this.model.digits) : item.value
878
862
  const calcItem = {
879
863
  hasInput: true,
880
864
  indicatorID: item.itemID,
@@ -894,15 +878,10 @@ export default {
894
878
  // 不可量化 + 有选项:校验选项(optionList 以 qualList 为准)
895
879
  if (isQualIndicator(item)) {
896
880
  const qualRef = this.findQualNode(item.tid, item.itemID, item)
897
- const hasOptions =
898
- qualRef?.optionList?.length || item.optionList?.length
881
+ const hasOptions = qualRef?.optionList?.length || item.optionList?.length
899
882
  if (hasOptions) {
900
883
  const selected = this.pickQualSelected(item)
901
- if (
902
- !selected ||
903
- selected.scoreMapID == null ||
904
- selected.scoreMapID === ''
905
- ) {
884
+ if (!selected || selected.scoreMapID == null || selected.scoreMapID === '') {
906
885
  obj.state = false
907
886
  this.messageStr += `${item.name}的选项不可为空;`
908
887
  } else {
@@ -917,11 +896,7 @@ export default {
917
896
  }
918
897
  }
919
898
  // 不可量化 + 手工填报(无下拉选项)
920
- if (
921
- isQualIndicator(item) &&
922
- item.sourceType === 3 &&
923
- (!item.optionList || !item.optionList.length)
924
- ) {
899
+ if (isQualIndicator(item) && item.sourceType === 3 && (!item.optionList || !item.optionList.length)) {
925
900
  if (!item.scoreValue && item.scoreValue !== 0) {
926
901
  obj.state = false
927
902
  this.messageStr += `${item.name}的评分不可为空;`
@@ -1049,28 +1024,57 @@ export default {
1049
1024
  }
1050
1025
  },
1051
1026
 
1027
+ currentModelId() {
1028
+ return this.model.modelID || this.model.id || this.id || ''
1029
+ },
1030
+ currentLogId() {
1031
+ return this.model.logId || this.logId || ''
1032
+ },
1033
+ openCalcDetail() {
1034
+ const modelId = this.currentModelId()
1035
+ const logId = this.currentLogId()
1036
+ if (!logId || !modelId) {
1037
+ this.$message.warning('请先完成测算后再查看测算详情')
1038
+ return
1039
+ }
1040
+ this.$refs.calculateDetailDialog.open({
1041
+ modelId,
1042
+ logId,
1043
+ showModelInfo: true
1044
+ })
1045
+ },
1046
+ openCalcJournal() {
1047
+ const modelId = this.currentModelId()
1048
+ if (!modelId) {
1049
+ this.$message.warning('模型ID不能为空')
1050
+ return
1051
+ }
1052
+ const url = `/imes/model/modelJournal?modelId=${modelId}`
1053
+ if (typeof this.$linkPush === 'function') {
1054
+ this.$linkPush(url)
1055
+ } else if (this.$router) {
1056
+ this.$router.push(url)
1057
+ }
1058
+ },
1052
1059
  async printFn() {
1053
- const logId = this.model.logId || this.logId || ''
1054
- const modelId = this.model.modelID || this.model.id || this.id || ''
1060
+ const logId = this.currentLogId()
1061
+ const modelId = this.currentModelId()
1055
1062
  if (!logId || !modelId) {
1056
1063
  this.$message.warning('请先完成测算后再打印')
1057
1064
  return
1058
1065
  }
1059
1066
  this.printLoading = true
1060
1067
  try {
1061
- const res = await this.$axios.post(
1062
- withRequestTimestamp('/imes/v1/indicatorModel/print'),
1063
- [
1064
- {
1065
- logId,
1066
- modelId,
1067
- creditInfo: this.creditInfo || {},
1068
- gradeInfo: this.gradeInfo || {}
1069
- }
1070
- ]
1071
- )
1068
+ const extra = this.buildPrintExtra()
1069
+ const res = await this.$axios.post(withRequestTimestamp(this.printUrl), [
1070
+ {
1071
+ ...extra,
1072
+ logId,
1073
+ modelId
1074
+ }
1075
+ ])
1072
1076
  if (res.code !== 0) {
1073
- this.$message.error(res.msg || '打印失败')
1077
+ // this.$message.error(res.msg || '打印失败')
1074
1078
  return
1075
1079
  }
1076
1080
  printJS({
@@ -1079,11 +1083,24 @@ export default {
1079
1083
  base64: true
1080
1084
  })
1081
1085
  } catch (e) {
1082
- this.$message.error('打印异常')
1086
+ // this.$message.error('打印异常')
1083
1087
  } finally {
1084
1088
  this.printLoading = false
1085
1089
  }
1086
1090
  },
1091
+ hasPrintObj(val) {
1092
+ return val && typeof val === 'object' && Object.keys(val).length > 0
1093
+ },
1094
+ buildPrintExtra() {
1095
+ const extra = { ...(this.printParams || {}) }
1096
+ if (this.hasPrintObj(this.creditInfo) && extra.creditInfo == null) {
1097
+ extra.creditInfo = this.creditInfo
1098
+ }
1099
+ if (this.hasPrintObj(this.gradeInfo) && extra.gradeInfo == null) {
1100
+ extra.gradeInfo = this.gradeInfo
1101
+ }
1102
+ return extra
1103
+ },
1087
1104
 
1088
1105
  /** 外层模型整体测算 */
1089
1106
  async calc() {
@@ -1093,9 +1110,7 @@ export default {
1093
1110
  return
1094
1111
  }
1095
1112
  this.qualList.forEach(n => this.applyQualDraftToNode(n))
1096
- const { scoreMapList, indicatorCalcList, state } = this.buildCalcParams(
1097
- this.leafList
1098
- )
1113
+ const { scoreMapList, indicatorCalcList, state } = this.buildCalcParams(this.leafList)
1099
1114
  if (!state) return
1100
1115
 
1101
1116
  const param = {
@@ -1109,10 +1124,7 @@ export default {
1109
1124
 
1110
1125
  this.calcLoading = true
1111
1126
  try {
1112
- const res = await this.$axios.post(
1113
- withRequestTimestamp('/imes/v2/models/calcModelTree'),
1114
- param
1115
- )
1127
+ const res = await this.$axios.post(withRequestTimestamp('/imes/v2/models/calcModelTree'), param)
1116
1128
  if (res.code === 0) {
1117
1129
  const resData = res.data || {}
1118
1130
  if (this.statRootModel) {
@@ -1129,16 +1141,11 @@ export default {
1129
1141
  this.syncTopGroupResults(resData)
1130
1142
  this.parentCalced = true
1131
1143
  this.resultText = resData.resultText || ''
1132
- this.calcResult =
1133
- resData.result === '' || resData.result == null
1134
- ? null
1135
- : resData.result
1144
+ this.calcResult = resData.result === '' || resData.result == null ? null : resData.result
1136
1145
  this.relFormula = resData.relFormula || ''
1137
1146
  this.displayFormula = resData.displayFormula || ''
1138
- this.scoreFormulaText = this.evalRootModel
1139
- ? this.buildEvalScoreText(resData)
1140
- : ''
1141
- this.businessModuleRemark =resData.businessModuleRemark
1147
+ this.scoreFormulaText = this.evalRootModel ? this.buildEvalScoreText(resData) : ''
1148
+ this.businessModuleRemark = resData.businessModuleRemark
1142
1149
  this.$set(this.model, 'logId', resData.logId || '')
1143
1150
  this.$set(this.model, 'maxReportTem', resData.maxReportTem || '')
1144
1151
  this.$emit('calcResult', this.displayResultText === '--' ? resData.resultText : this.displayResultText)
@@ -1175,8 +1182,7 @@ export default {
1175
1182
  }
1176
1183
  const leaves = this.collectLeaves(subModel)
1177
1184
  leaves.forEach(n => this.applyQualDraftToNode(n))
1178
- const { scoreMapList, indicatorCalcList, state } =
1179
- this.buildCalcParams(leaves)
1185
+ const { scoreMapList, indicatorCalcList, state } = this.buildCalcParams(leaves)
1180
1186
  if (!state) return
1181
1187
 
1182
1188
  const param = {
@@ -1190,10 +1196,7 @@ export default {
1190
1196
 
1191
1197
  this.$set(subModel, '_calcing', true)
1192
1198
  try {
1193
- const res = await this.$axios.post(
1194
- withRequestTimestamp('/imes/v2/models/calcModelTree'),
1195
- param
1196
- )
1199
+ const res = await this.$axios.post(withRequestTimestamp('/imes/v2/models/calcModelTree'), param)
1197
1200
  if (res.code === 0) {
1198
1201
  const data = res.data || {}
1199
1202
  if (isStatModel(subModel)) {
@@ -1207,34 +1210,18 @@ export default {
1207
1210
  }
1208
1211
  const root = data.modelTreeVO || {}
1209
1212
  // 模型结果在 ModelVO 顶层;modelTreeVO 根节点多为分组目录,result 常为 0
1210
- const modelResult =
1211
- data.result != null && data.result !== ''
1212
- ? data.result
1213
- : root.result
1214
- const modelResultText =
1215
- data.resultText != null && data.resultText !== ''
1216
- ? data.resultText
1217
- : root.resultText
1213
+ const modelResult = data.result != null && data.result !== '' ? data.result : root.result
1214
+ const modelResultText = data.resultText != null && data.resultText !== '' ? data.resultText : root.resultText
1218
1215
  const indicatorResult =
1219
- root.indicatorResult != null && root.indicatorResult !== ''
1220
- ? root.indicatorResult
1221
- : modelResult
1216
+ root.indicatorResult != null && root.indicatorResult !== '' ? root.indicatorResult : modelResult
1222
1217
  // 回填子模型自身的值(供外层模型引用)
1223
1218
  this.$set(subModel, 'result', modelResult)
1224
1219
  this.$set(subModel, 'resultText', modelResultText)
1225
1220
  this.$set(subModel, 'indicatorResult', indicatorResult)
1226
1221
  this.$set(subModel, 'indicatorValText', root.indicatorValText)
1227
- this.$set(
1228
- subModel,
1229
- 'value',
1230
- indicatorResult != null ? indicatorResult : modelResult
1231
- )
1222
+ this.$set(subModel, 'value', indicatorResult != null ? indicatorResult : modelResult)
1232
1223
  this.$set(subModel, 'relFormula', data.relFormula || root.relFormula || '')
1233
- this.$set(
1234
- subModel,
1235
- 'displayFormula',
1236
- data.displayFormula || root.displayFormula || ''
1237
- )
1224
+ this.$set(subModel, 'displayFormula', data.displayFormula || root.displayFormula || '')
1238
1225
  const subValueText = saveSubModelValueText(subModel, this.model)
1239
1226
  if (subValueText) {
1240
1227
  this.$set(subModel, '_subModelValueText', subValueText)
@@ -1288,10 +1275,7 @@ export default {
1288
1275
  this.$set(target, key, source[key])
1289
1276
  }
1290
1277
  })
1291
- if (
1292
- target.itemType !== 22 &&
1293
- (source.modifiedVal || source.modifiedVal === 0)
1294
- ) {
1278
+ if (target.itemType !== 22 && (source.modifiedVal || source.modifiedVal === 0)) {
1295
1279
  this.$set(target, 'value', source.modifiedVal)
1296
1280
  }
1297
1281
  },
@@ -1320,10 +1304,8 @@ export default {
1320
1304
  * 合成分组可能无稳定 tid,优先 tid,其次 name
1321
1305
  */
1322
1306
  syncTopGroupResults(resData) {
1323
- const remoteChildren =
1324
- (resData.modelTreeVO && resData.modelTreeVO.children) || []
1325
- const localChildren =
1326
- (this.model.modelTreeVO && this.model.modelTreeVO.children) || []
1307
+ const remoteChildren = (resData.modelTreeVO && resData.modelTreeVO.children) || []
1308
+ const localChildren = (this.model.modelTreeVO && this.model.modelTreeVO.children) || []
1327
1309
  this.syncTreeResults(localChildren, remoteChildren)
1328
1310
  },
1329
1311
 
@@ -1332,13 +1314,7 @@ export default {
1332
1314
  remoteNodes.forEach(remote => {
1333
1315
  const local =
1334
1316
  localNodes.find(n => n.tid && remote.tid && n.tid === remote.tid) ||
1335
- localNodes.find(
1336
- n =>
1337
- n.name === remote.name &&
1338
- n.itemID &&
1339
- remote.itemID &&
1340
- n.itemID === remote.itemID
1341
- ) ||
1317
+ localNodes.find(n => n.name === remote.name && n.itemID && remote.itemID && n.itemID === remote.itemID) ||
1342
1318
  localNodes.find(n => n.name === remote.name)
1343
1319
  if (!local) return
1344
1320
  this.applyResultFields(local, remote)
@@ -1386,10 +1362,7 @@ export default {
1386
1362
  nodes.forEach(n => {
1387
1363
  if (!n) return
1388
1364
  if (this.isSubModel(n) || isIndicator(n)) {
1389
- if (
1390
- (n.fullScore === 0 || n.fullScore) &&
1391
- (n.weight === 0 || n.weight)
1392
- ) {
1365
+ if ((n.fullScore === 0 || n.fullScore) && (n.weight === 0 || n.weight)) {
1393
1366
  bucket.push(n)
1394
1367
  }
1395
1368
  return
@@ -1406,20 +1379,13 @@ export default {
1406
1379
  */
1407
1380
  buildGroupWeightText(groupNode, children) {
1408
1381
  if (!groupNode) return ''
1409
- const contributors = this.collectWeightContributors(
1410
- children || groupNode.children || []
1411
- )
1382
+ const contributors = this.collectWeightContributors(children || groupNode.children || [])
1412
1383
  let total = null
1413
1384
  if (contributors.length) {
1414
1385
  total = contributors.reduce((sum, n) => {
1415
1386
  const full = Number(n.fullScore)
1416
1387
  const weight = Number(n.weight)
1417
- return (
1418
- sum +
1419
- ((Number.isNaN(full) ? 0 : full) *
1420
- (Number.isNaN(weight) ? 0 : weight)) /
1421
- 100
1422
- )
1388
+ return sum + ((Number.isNaN(full) ? 0 : full) * (Number.isNaN(weight) ? 0 : weight)) / 100
1423
1389
  }, 0)
1424
1390
  } else if (groupNode.fullScore === 0 || groupNode.fullScore) {
1425
1391
  total = groupNode.fullScore
@@ -1433,10 +1399,7 @@ export default {
1433
1399
  if (!this.evalRootModel || !groupNode) return ''
1434
1400
  if (this.model.showWeight !== 1) return ''
1435
1401
  if (this.isSubModel(groupNode)) return ''
1436
- return this.buildGroupWeightText(
1437
- groupNode,
1438
- children || groupNode.children
1439
- )
1402
+ return this.buildGroupWeightText(groupNode, children || groupNode.children)
1440
1403
  },
1441
1404
  sectionWeightText(section) {
1442
1405
  if (!section || !section.container) return ''
@@ -1448,12 +1411,7 @@ export default {
1448
1411
  if (!this.evalRootModel || !groupNode) return ''
1449
1412
  if (this.isSubModel(groupNode)) return ''
1450
1413
  if (!this.parentCalced) return '总得分: --'
1451
- return (
1452
- this.buildGroupScoreText(
1453
- groupNode,
1454
- children || groupNode.children
1455
- ) || '总得分: --'
1456
- )
1414
+ return this.buildGroupScoreText(groupNode, children || groupNode.children) || '总得分: --'
1457
1415
  },
1458
1416
  sectionScoreText(section) {
1459
1417
  if (!section || !section.container) return ''
@@ -1667,6 +1625,18 @@ export default {
1667
1625
  font-weight: 600;
1668
1626
  padding-left: 8px;
1669
1627
  border-left: 3px solid #409eff;
1628
+ cursor: pointer;
1629
+ }
1630
+ .group-toggle {
1631
+ margin-left: auto;
1632
+ font-size: 13px;
1633
+ font-weight: 400;
1634
+ color: #409eff;
1635
+ white-space: nowrap;
1636
+ user-select: none;
1637
+ }
1638
+ .group-toggle i {
1639
+ margin-left: 2px;
1670
1640
  }
1671
1641
  .section-weight-pill,
1672
1642
  .section-score-pill {
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.16',
22
+ version: '1.0.24',
23
23
  install,
24
24
  ModelCalculate,
25
25
  MeasureCalc,