@nstc-business/imes 1.0.31 → 1.0.33

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.31",
3
+ "version": "1.0.33",
4
4
  "private": false,
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -2,6 +2,7 @@
2
2
  <div class="measure-eval-flat">
3
3
  <vxe-table
4
4
  border
5
+ class="v3-n20-table-pro"
5
6
  :data="rows"
6
7
  :row-config="{ keyField: '_rowKey' }"
7
8
  :scroll-y="{ enabled: false }"
@@ -29,7 +29,7 @@
29
29
  <vxe-table
30
30
  v-show="isExpanded(index)"
31
31
  border
32
- class="qual-table"
32
+ class="qual-table v3-n20-table-pro"
33
33
  :data="group.children"
34
34
  :row-config="{ keyField: '_rowKey' }"
35
35
  :scroll-y="{ enabled: false }"
@@ -4,6 +4,7 @@
4
4
  <vxe-table
5
5
  v-else
6
6
  border
7
+ class="v3-n20-table-pro"
7
8
  :data="rows"
8
9
  :merge-cells="mergeCells"
9
10
  :row-config="{ keyField: '_rowKey' }"
@@ -2,7 +2,7 @@
2
2
  <vxe-table
3
3
  border
4
4
  ref="xTable"
5
- :class="['measure-tree-table', 'level-' + level]"
5
+ :class="['measure-tree-table', 'v3-n20-table-pro', 'level-' + level]"
6
6
  :row-config="{ keyField: '_rowKey' }"
7
7
  :data="nodes"
8
8
  :expand-config="{ lazy: false, visibleMethod: canExpand }"
@@ -154,16 +154,14 @@ export const SUB_MODEL_LABEL = '测算子模型'
154
154
  /** 子模型独立测算按钮文案 */
155
155
  export const SUB_MODEL_CALC_BTN = '子模型测算'
156
156
 
157
- /** 子模型测算结果展示(优先 resultText,否则格式化 result) */
157
+ /** 子模型测算结果展示(计算/统计读 digits,评价分数+等级固定2位) */
158
158
  export function subModelResultText(row, modelWrap) {
159
159
  if (!row) return ''
160
- if (row.resultText != null && row.resultText !== '') {
161
- return row.resultText
162
- }
163
- if (row.result !== '' && row.result != null) {
164
- return resultByShowStyle(row, modelWrap)
165
- }
166
- return ''
160
+ return formatDisplayModelResult(
161
+ { result: row.result, resultText: row.resultText },
162
+ modelWrap,
163
+ { modelType: row.itemType, thousands: row.showStyle === 2 }
164
+ )
167
165
  }
168
166
 
169
167
  export function isCalcModel(row) {
@@ -223,6 +221,31 @@ export function digitsCalc(row, modelWrap) {
223
221
  */
224
222
  export const SCORE_DIGITS = 2
225
223
 
224
+ /**
225
+ * 模型结果小数位:读模型返回的 digits,缺省回退 2
226
+ * (计算模型用;对应后台全局计算位数配置)
227
+ */
228
+ export function modelResultDigits(modelWrap) {
229
+ return modelWrap && modelWrap.digits != null ? modelWrap.digits : 2
230
+ }
231
+
232
+ /**
233
+ * 模型结果数值格式化:按模型 digits 四舍五入保留小数位(仅计算模型)
234
+ * @param {*} val
235
+ * @param {*} modelWrap
236
+ * @param {{ thousands?: boolean }} [options]
237
+ */
238
+ export function formatModelResultText(val, modelWrap, options = {}) {
239
+ if (val === '' || val == null) return ''
240
+ const num = Number(val)
241
+ if (Number.isNaN(num)) return String(val)
242
+ let text = num.toFixed(modelResultDigits(modelWrap))
243
+ if (options.thousands) {
244
+ text = addThousands(text)
245
+ }
246
+ return text
247
+ }
248
+
226
249
  /**
227
250
  * 得分数值格式化:四舍五入,固定保留 SCORE_DIGITS 位
228
251
  * @param {*} val
@@ -239,6 +262,61 @@ export function formatScoreText(val, options = {}) {
239
262
  return text
240
263
  }
241
264
 
265
+ /**
266
+ * 解析模型种类:顶层 type(1/2/3) 或节点 itemType(12/11/13)
267
+ * @returns {'eval'|'calc'|'stat'|'other'}
268
+ */
269
+ export function resolveModelKind(type) {
270
+ const t = Number(type)
271
+ if (t === 1 || t === ITEM_TYPE.EVAL_MODEL) return 'eval'
272
+ if (t === 2 || t === ITEM_TYPE.CALC_MODEL) return 'calc'
273
+ if (t === 3 || t === ITEM_TYPE.STAT_MODEL) return 'stat'
274
+ return 'other'
275
+ }
276
+
277
+ /**
278
+ * 测算结果展示:
279
+ * - 计算/统计模型:按模型 digits(后台全局计算位数)
280
+ * - 评价模型:分数固定 2 位;有等级则「分数(等级)」,等级为空只显示分数
281
+ * @param {{ result?: *, resultText?: * }} payload
282
+ * @param {*} modelWrap
283
+ * @param {{ modelType?: number|string, thousands?: boolean }} [options]
284
+ */
285
+ export function formatDisplayModelResult(payload, modelWrap, options = {}) {
286
+ const result = payload && payload.result
287
+ const resultText = payload && payload.resultText
288
+ const modelType = options.modelType != null ? options.modelType : modelWrap && modelWrap.type
289
+ const kind = resolveModelKind(modelType)
290
+ const hasScore = result !== '' && result != null
291
+ const grade =
292
+ resultText !== '' && resultText != null ? String(resultText).trim() : ''
293
+
294
+ if (kind === 'eval') {
295
+ if (!hasScore && !grade) return ''
296
+ const parts = []
297
+ if (hasScore) {
298
+ parts.push(formatScoreText(result, { thousands: options.thousands }))
299
+ }
300
+ // 等级为空不展示;「未知」等非空等级文案仍展示
301
+ if (grade) {
302
+ parts.push(`(${grade})`)
303
+ }
304
+ return parts.join('')
305
+ }
306
+
307
+ const raw = hasScore ? result : grade
308
+ if (raw === '' || raw == null) return ''
309
+ const text = String(raw).trim()
310
+ if (!/^-?\d+(\.\d+)?$/.test(text)) {
311
+ return String(raw)
312
+ }
313
+ // 计算/统计模型读 digits;其他固定 2 位
314
+ if (kind === 'calc' || kind === 'stat') {
315
+ return formatModelResultText(text, modelWrap, { thousands: options.thousands })
316
+ }
317
+ return formatScoreText(text, { thousands: options.thousands })
318
+ }
319
+
242
320
  /** 模型指标得分 / 模型指标系数数值(权重之后的 result);得分不读模型 digits */
243
321
  export function resultByShowStyle(row, modelWrap) {
244
322
  if (!row || (row.result !== 0 && (row.result === '' || row.result == null))) {
@@ -319,15 +397,13 @@ export function indicatorResultText(row, modelWrap) {
319
397
  /** 从子模型节点解析指标值展示文案 */
320
398
  export function resolveSubModelValueText(row, modelWrap) {
321
399
  if (!row) return ''
322
- if (row.resultText != null && row.resultText !== '') {
323
- return row.resultText
324
- }
325
- const text = indicatorResultText(row, modelWrap)
326
- if (text) return text
327
- if (row.result !== '' && row.result != null) {
328
- return resultByShowStyle(row, modelWrap)
329
- }
330
- return ''
400
+ const modelResult = formatDisplayModelResult(
401
+ { result: row.result, resultText: row.resultText },
402
+ modelWrap,
403
+ { modelType: row.itemType, thousands: row.showStyle === 2 }
404
+ )
405
+ if (modelResult) return modelResult
406
+ return indicatorResultText(row, modelWrap)
331
407
  }
332
408
 
333
409
  /** 子模型指标值:子模型测算后展示计算结果(固化,避免父模型测算覆盖 result 后丢失) */
@@ -191,6 +191,42 @@
191
191
  </div>
192
192
  </div>
193
193
  <calculate-detail-dialog ref="calculateDetailDialog" />
194
+ <el-dialog
195
+ title="选择打印"
196
+ :visible.sync="printDialogVisible"
197
+ width="480px"
198
+ append-to-body
199
+ @closed="onPrintDialogClosed"
200
+ >
201
+ <el-form label-width="90px">
202
+ <el-form-item label="打印选项" required>
203
+ <el-select
204
+ v-model="selectedTemplateName"
205
+ placeholder="请选择"
206
+ clearable
207
+ filterable
208
+ :loading="printTemplateLoading"
209
+ style="width: 100%"
210
+ >
211
+ <el-option
212
+ v-for="item in printTemplateList"
213
+ :key="item.ptId || item.ptNo || item.ptName"
214
+ :label="item.ptName"
215
+ :value="item.ptName"
216
+ />
217
+ </el-select>
218
+ </el-form-item>
219
+ </el-form>
220
+ <div slot="footer" class="dialog-footer">
221
+ <el-button type="primary" size="small" :loading="printLoading" @click="confirmPrintDownload('download')">
222
+ 下载
223
+ </el-button>
224
+ <el-button type="primary" size="small" :loading="printLoading" @click="confirmPrintDownload('print')">
225
+ 打印
226
+ </el-button>
227
+ <el-button size="small" @click="printDialogVisible = false">取消</el-button>
228
+ </div>
229
+ </el-dialog>
194
230
  </div>
195
231
  </template>
196
232
 
@@ -216,6 +252,7 @@ import {
216
252
  subModelResultText as formatSubModelResult,
217
253
  saveSubModelValueText,
218
254
  formatScoreText,
255
+ formatDisplayModelResult,
219
256
  resolveCalcEchoValue,
220
257
  shouldApplyModifiedVal
221
258
  } from './helpers'
@@ -341,6 +378,10 @@ export default {
341
378
  loading: false,
342
379
  calcLoading: false,
343
380
  printLoading: false,
381
+ printDialogVisible: false,
382
+ printTemplateList: [],
383
+ selectedTemplateName: '',
384
+ printTemplateLoading: false,
344
385
  model: { type: 1, name: '', code: '', digits: 2, modelTreeVO: {} },
345
386
  sections: [],
346
387
  anchorTabs: [],
@@ -419,21 +460,14 @@ export default {
419
460
  if (this.model.version === '' || this.model.version == null) return '--'
420
461
  return `版本${this.model.version}`
421
462
  },
422
- /** 测算结果展示:优先 resultText,统计模型计算模式可回退到 result;得分固定 2 位四舍五入 */
463
+ /** 测算结果:计算/统计读 digits;评价固定2位且有等级则「分数(等级)」 */
423
464
  displayResultText() {
424
- const raw =
425
- this.resultText !== '' && this.resultText != null
426
- ? this.resultText
427
- : this.calcResult !== '' && this.calcResult != null
428
- ? this.calcResult
429
- : null
430
- if (raw === null || raw === '') return '--'
431
- const text = String(raw).trim()
432
- // 纯数字得分:固定 2 位;非数字文案原样展示
433
- if (/^-?\d+(\.\d+)?$/.test(text)) {
434
- return formatScoreText(text)
435
- }
436
- return String(raw)
465
+ const text = formatDisplayModelResult(
466
+ { result: this.calcResult, resultText: this.resultText },
467
+ this.model,
468
+ { modelType: this.model && this.model.type }
469
+ )
470
+ return text || '--'
437
471
  },
438
472
  /** 评价模型展示「模型得分」,计算模型展示「模型公式」 */
439
473
  formulaRowLabel() {
@@ -1082,6 +1116,42 @@ export default {
1082
1116
  }
1083
1117
  },
1084
1118
  async printFn() {
1119
+ const logId = this.currentLogId()
1120
+ const modelId = this.currentModelId()
1121
+ if (!logId || !modelId) {
1122
+ this.$message.warning('请先完成测算后再打印')
1123
+ return
1124
+ }
1125
+ this.selectedTemplateName = ''
1126
+ this.printDialogVisible = true
1127
+ await this.loadPrintTemplates()
1128
+ },
1129
+ onPrintDialogClosed() {
1130
+ this.selectedTemplateName = ''
1131
+ },
1132
+ async loadPrintTemplates() {
1133
+ this.printTemplateLoading = true
1134
+ try {
1135
+ const ptType =
1136
+ this.model && this.model.type != null && this.model.type !== '' ? String(this.model.type) : undefined
1137
+ const res = await this.$axios.get(
1138
+ '/imes/print-template/list',
1139
+ ptType ? { ptType } : {},
1140
+ { loading: false }
1141
+ )
1142
+ const list = Array.isArray(res) ? res : (res && res.data) || []
1143
+ this.printTemplateList = Array.isArray(list) ? list : []
1144
+ } catch (e) {
1145
+ this.printTemplateList = []
1146
+ } finally {
1147
+ this.printTemplateLoading = false
1148
+ }
1149
+ },
1150
+ async confirmPrintDownload(action) {
1151
+ if (!this.selectedTemplateName) {
1152
+ this.$message.warning('请选择打印选项')
1153
+ return
1154
+ }
1085
1155
  const logId = this.currentLogId()
1086
1156
  const modelId = this.currentModelId()
1087
1157
  if (!logId || !modelId) {
@@ -1095,24 +1165,47 @@ export default {
1095
1165
  {
1096
1166
  ...extra,
1097
1167
  logId,
1098
- modelId
1168
+ modelId,
1169
+ templateName: this.selectedTemplateName
1099
1170
  }
1100
1171
  ])
1101
1172
  if (res.code !== 0) {
1102
- // this.$message.error(res.msg || '打印失败')
1103
1173
  return
1104
1174
  }
1105
- printJS({
1106
- printable: res.data,
1107
- type: 'pdf',
1108
- base64: true
1109
- })
1175
+ if (action === 'print') {
1176
+ printJS({
1177
+ printable: res.data,
1178
+ type: 'pdf',
1179
+ base64: true
1180
+ })
1181
+ } else {
1182
+ this.downloadPdfBase64(res.data)
1183
+ }
1184
+ this.printDialogVisible = false
1110
1185
  } catch (e) {
1111
- // this.$message.error('打印异常')
1186
+ // keep quiet consistent with previous print catch
1112
1187
  } finally {
1113
1188
  this.printLoading = false
1114
1189
  }
1115
1190
  },
1191
+ downloadPdfBase64(base64) {
1192
+ const pure = String(base64 || '').replace(/^data:application\/pdf;base64,/, '')
1193
+ const binary = atob(pure)
1194
+ const len = binary.length
1195
+ const bytes = new Uint8Array(len)
1196
+ for (let i = 0; i < len; i++) {
1197
+ bytes[i] = binary.charCodeAt(i)
1198
+ }
1199
+ const blob = new Blob([bytes], { type: 'application/pdf' })
1200
+ const url = URL.createObjectURL(blob)
1201
+ const a = document.createElement('a')
1202
+ a.href = url
1203
+ a.download = `${(this.model && this.model.code) || '测算结果'}.pdf`
1204
+ document.body.appendChild(a)
1205
+ a.click()
1206
+ document.body.removeChild(a)
1207
+ URL.revokeObjectURL(url)
1208
+ },
1116
1209
  hasPrintObj(val) {
1117
1210
  return val && typeof val === 'object' && Object.keys(val).length > 0
1118
1211
  },
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.24',
22
+ version: '1.0.33',
23
23
  install,
24
24
  ModelCalculate,
25
25
  MeasureCalc,