@nstc-business/imes 1.0.19 → 1.0.21
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 +1 -1
- package/src/components/calculateDetail/index.vue +14 -2
- package/src/components/measureCalc/MeasureStatCell.vue +2 -1
- package/src/components/measureCalc/MeasureStatModelTable.vue +32 -1
- package/src/components/measureCalc/helpers.js +2 -2
- package/src/components/measureCalc/index.vue +24 -6
- package/src/components/measureCalc/statModelHelper.js +150 -19
package/package.json
CHANGED
|
@@ -101,8 +101,20 @@
|
|
|
101
101
|
label-width="10em"
|
|
102
102
|
v-if="modelData.sataMode !== 1"
|
|
103
103
|
>
|
|
104
|
-
<el-form-item
|
|
105
|
-
|
|
104
|
+
<el-form-item
|
|
105
|
+
label="模型得分:"
|
|
106
|
+
v-if="
|
|
107
|
+
modelData.type === 1 ||
|
|
108
|
+
(modelData.type === 3 && modelData.sataMode === 2)
|
|
109
|
+
"
|
|
110
|
+
>
|
|
111
|
+
<span>
|
|
112
|
+
{{
|
|
113
|
+
modelData.result || modelData.result === 0
|
|
114
|
+
? Number(modelData.result).toFixed(modelData.digits)
|
|
115
|
+
: '--'
|
|
116
|
+
}}
|
|
117
|
+
</span>
|
|
106
118
|
</el-form-item>
|
|
107
119
|
<el-form-item label="模型结果:" v-if="modelData.type !== 3">
|
|
108
120
|
<span>{{ modelData.resultText }}</span>
|
|
@@ -79,7 +79,8 @@ export default {
|
|
|
79
79
|
methods: {
|
|
80
80
|
displayValue(cell) {
|
|
81
81
|
if (this.column.disabled) {
|
|
82
|
-
const val =
|
|
82
|
+
const val =
|
|
83
|
+
cell.result !== '' && cell.result != null ? cell.result : cell.value
|
|
83
84
|
if (val === '' || val == null) return ''
|
|
84
85
|
let text = Number(val).toFixed(this.digits)
|
|
85
86
|
if (cell.showStyle === 2) {
|
|
@@ -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,9 +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
|
-
id => this.fetchScoreMap(id)
|
|
152
|
+
id => this.fetchScoreMap(id),
|
|
153
|
+
{
|
|
154
|
+
...modelWrap,
|
|
155
|
+
modelStatsSetupVOS:
|
|
156
|
+
this.subModel.modelStatsSetupVOS || modelWrap.modelStatsSetupVOS
|
|
157
|
+
}
|
|
127
158
|
)
|
|
128
159
|
} finally {
|
|
129
160
|
this.loading = false
|
|
@@ -89,9 +89,9 @@ export const SUB_MODEL_LABEL = '测算子模型'
|
|
|
89
89
|
/** 子模型独立测算按钮文案 */
|
|
90
90
|
export const SUB_MODEL_CALC_BTN = '子模型测算'
|
|
91
91
|
|
|
92
|
-
/** 子模型测算结果展示(优先 resultText,否则格式化 result)
|
|
92
|
+
/** 子模型测算结果展示(优先 resultText,否则格式化 result) */
|
|
93
93
|
export function subModelResultText(row, modelWrap) {
|
|
94
|
-
if (!row
|
|
94
|
+
if (!row) return ''
|
|
95
95
|
if (row.resultText != null && row.resultText !== '') {
|
|
96
96
|
return row.resultText
|
|
97
97
|
}
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
</span>
|
|
48
48
|
<span class="meta-item">
|
|
49
49
|
<span class="meta-label">测算结果</span>
|
|
50
|
-
<span class="meta-value meta-result">{{
|
|
50
|
+
<span class="meta-value meta-result">{{ displayResultText }}</span>
|
|
51
51
|
</span>
|
|
52
52
|
</div>
|
|
53
53
|
|
|
@@ -386,18 +386,29 @@ export default {
|
|
|
386
386
|
statRootModel() {
|
|
387
387
|
return checkStatRootModel(this.model)
|
|
388
388
|
},
|
|
389
|
-
/**
|
|
389
|
+
/** 顶层统计模型的根节点(必须返回原引用,保证 _statTableVersion 能触发子表刷新) */
|
|
390
390
|
statRootNode() {
|
|
391
391
|
const root = this.model.modelTreeVO || {}
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
itemID
|
|
392
|
+
const itemID = root.itemID || root.modelID || this.model.modelID
|
|
393
|
+
if (itemID && root.itemID !== itemID) {
|
|
394
|
+
this.$set(root, 'itemID', itemID)
|
|
395
395
|
}
|
|
396
|
+
return root
|
|
396
397
|
},
|
|
397
398
|
modelVersionText() {
|
|
398
399
|
if (this.model.version === '' || this.model.version == null) return '--'
|
|
399
400
|
return `版本${this.model.version}`
|
|
400
401
|
},
|
|
402
|
+
/** 测算结果展示:优先 resultText,统计模型计算模式可回退到 result */
|
|
403
|
+
displayResultText() {
|
|
404
|
+
if (this.resultText !== '' && this.resultText != null) {
|
|
405
|
+
return this.resultText
|
|
406
|
+
}
|
|
407
|
+
if (this.calcResult !== '' && this.calcResult != null) {
|
|
408
|
+
return this.calcResult
|
|
409
|
+
}
|
|
410
|
+
return '--'
|
|
411
|
+
},
|
|
401
412
|
/** 评价模型展示「模型得分」,计算模型展示「模型公式」 */
|
|
402
413
|
formulaRowLabel() {
|
|
403
414
|
if (this.evalRootModel) return '模型得分:'
|
|
@@ -1054,6 +1065,10 @@ export default {
|
|
|
1054
1065
|
if (this.statRootModel) {
|
|
1055
1066
|
const treeRoot = resData.modelTreeVO || {}
|
|
1056
1067
|
preprocessStatIndicatorDeepList(treeRoot.children || [])
|
|
1068
|
+
if (resData.modelStatsSetupVOS) {
|
|
1069
|
+
treeRoot.modelStatsSetupVOS = resData.modelStatsSetupVOS
|
|
1070
|
+
this.$set(this.model, 'modelStatsSetupVOS', resData.modelStatsSetupVOS)
|
|
1071
|
+
}
|
|
1057
1072
|
mergeStatModelNode(this.model.modelTreeVO || {}, treeRoot)
|
|
1058
1073
|
this.bumpStatTableVersion(this.model.modelTreeVO)
|
|
1059
1074
|
}
|
|
@@ -1073,7 +1088,7 @@ export default {
|
|
|
1073
1088
|
this.businessModuleRemark =resData.businessModuleRemark
|
|
1074
1089
|
this.$set(this.model, 'logId', resData.logId || '')
|
|
1075
1090
|
this.$set(this.model, 'maxReportTem', resData.maxReportTem || '')
|
|
1076
|
-
this.$emit('calcResult', resData.resultText)
|
|
1091
|
+
this.$emit('calcResult', this.displayResultText === '--' ? resData.resultText : this.displayResultText)
|
|
1077
1092
|
this.$emit('getLogId', resData.logId)
|
|
1078
1093
|
this.$emit('calcComplete', {
|
|
1079
1094
|
...resData,
|
|
@@ -1131,6 +1146,9 @@ export default {
|
|
|
1131
1146
|
if (isStatModel(subModel)) {
|
|
1132
1147
|
const treeRoot = data.modelTreeVO || {}
|
|
1133
1148
|
preprocessStatIndicatorDeepList(treeRoot.children || [])
|
|
1149
|
+
if (data.modelStatsSetupVOS) {
|
|
1150
|
+
treeRoot.modelStatsSetupVOS = data.modelStatsSetupVOS
|
|
1151
|
+
}
|
|
1134
1152
|
mergeStatModelNode(subModel, treeRoot)
|
|
1135
1153
|
this.bumpStatTableVersion(subModel)
|
|
1136
1154
|
}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 统计模型行转列:以 isLeaf=2 为横向展开边界
|
|
3
3
|
* 逻辑参考 EvaOfCreditConditionsRewrite.initColumnsRewrite
|
|
4
|
-
* statCalResult
|
|
4
|
+
* statCalResult / modelStatsSetupVOS 作辅助元数据(列配置/标题/合计),
|
|
5
|
+
* 不作为是否行转列的判断条件。
|
|
6
|
+
*
|
|
7
|
+
* 注意:getModelTree 对统计模型通常不下发 statCalResult(挂在评价模型的
|
|
8
|
+
* 定量分析/定性分析节点上),标题需按 pid 反查分组目录,列配置优先用
|
|
9
|
+
* modelStatsSetupVOS,避免回退到第一个指标名 / 默认 calType=0 导致错列。
|
|
5
10
|
*/
|
|
6
11
|
|
|
7
12
|
function hasFilledValue(val) {
|
|
@@ -105,14 +110,45 @@ export function hasStatPivotData(statNode) {
|
|
|
105
110
|
return hasStatPivotNodes(statNode)
|
|
106
111
|
}
|
|
107
112
|
|
|
113
|
+
/**
|
|
114
|
+
* calType:0=指标取数(展示「xxx指标值/指标得分」),非 0(如 9=统计项运算)只展示统计项名。
|
|
115
|
+
*
|
|
116
|
+
* 注意:指标取数节点落库时 rankType 常是「指标自身打分规则」,不是统计项 calType
|
|
117
|
+
*(见 statisticModel createIndicatorWithData: rankType = deepItem.rankType || calType)。
|
|
118
|
+
* 因此不能把 rankType 直接当 calType;有指标类型/itemID 时应视为指标取数(0)。
|
|
119
|
+
*/
|
|
120
|
+
function resolveStatCalType(statLike) {
|
|
121
|
+
if (!statLike) return 0
|
|
122
|
+
if (statLike.calType !== '' && statLike.calType != null) {
|
|
123
|
+
return Number(statLike.calType)
|
|
124
|
+
}
|
|
125
|
+
const itemType = Number(statLike.itemType)
|
|
126
|
+
if (itemType === 21 || itemType === 22) return 0
|
|
127
|
+
// 无关联指标:保存时 rankType === 统计项 calType(如 9=统计项运算)
|
|
128
|
+
if (!statLike.itemID) {
|
|
129
|
+
if (statLike.rankType !== '' && statLike.rankType != null) {
|
|
130
|
+
return Number(statLike.rankType)
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// 有 itemID 的统计项按指标取数处理
|
|
134
|
+
if (statLike.itemID) return 0
|
|
135
|
+
return 0
|
|
136
|
+
}
|
|
137
|
+
|
|
108
138
|
function resolveStatMeta(statsResultList, statChild) {
|
|
109
139
|
const fromList = (statsResultList || []).find(
|
|
110
140
|
s => s.name == statChild.statsName
|
|
111
141
|
)
|
|
112
|
-
if (fromList)
|
|
142
|
+
if (fromList) {
|
|
143
|
+
return {
|
|
144
|
+
...fromList,
|
|
145
|
+
name: fromList.name || statChild.statsName,
|
|
146
|
+
calType: resolveStatCalType(fromList)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
113
149
|
return {
|
|
114
150
|
name: statChild.statsName,
|
|
115
|
-
calType: statChild
|
|
151
|
+
calType: resolveStatCalType(statChild),
|
|
116
152
|
statShow: statChild.statShow ?? 1,
|
|
117
153
|
statCalMethod: statChild.statCalMethod,
|
|
118
154
|
statResult: statChild.statResult
|
|
@@ -120,25 +156,104 @@ function resolveStatMeta(statsResultList, statChild) {
|
|
|
120
156
|
}
|
|
121
157
|
|
|
122
158
|
function buildStatsResultListFromChildren(statChildren) {
|
|
123
|
-
return statChildren.map(c => ({
|
|
159
|
+
return (statChildren || []).map(c => ({
|
|
124
160
|
name: c.statsName,
|
|
125
|
-
calType: c
|
|
161
|
+
calType: resolveStatCalType(c),
|
|
126
162
|
statShow: c.statShow ?? 1,
|
|
127
163
|
statCalMethod: c.statCalMethod,
|
|
128
164
|
statResult: c.statResult
|
|
129
165
|
}))
|
|
130
166
|
}
|
|
131
167
|
|
|
132
|
-
function
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
168
|
+
function normalizeStatsResultList(list) {
|
|
169
|
+
if (!Array.isArray(list) || !list.length) return null
|
|
170
|
+
return list.map(s => ({
|
|
171
|
+
name: s.name || s.statsName,
|
|
172
|
+
calType: resolveStatCalType(s),
|
|
173
|
+
statShow: s.statShow ?? 1,
|
|
174
|
+
statCalMethod: s.statCalMethod,
|
|
175
|
+
statResult: s.statResult
|
|
176
|
+
}))
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** 在节点树中按 tid 查找节点(含根) */
|
|
180
|
+
function findNodeByTid(root, tid) {
|
|
181
|
+
if (!root || tid == null || tid === '') return null
|
|
182
|
+
if (root.tid === tid || root.TID === tid) return root
|
|
183
|
+
const stack = Array.isArray(root.children) ? [...root.children] : []
|
|
184
|
+
while (stack.length) {
|
|
185
|
+
const node = stack.shift()
|
|
186
|
+
if (!node) continue
|
|
187
|
+
if (node.tid === tid || node.TID === tid) return node
|
|
188
|
+
if (Array.isArray(node.children) && node.children.length) {
|
|
189
|
+
stack.push(...node.children)
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return null
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/** 收集整棵树上所有 statCalResult(挂在定量分析/定性分析等祖先节点上) */
|
|
196
|
+
function collectAllStatCalResults(root, bucket = []) {
|
|
197
|
+
if (!root) return bucket
|
|
198
|
+
if (Array.isArray(root.statCalResult) && root.statCalResult.length) {
|
|
199
|
+
bucket.push(...root.statCalResult)
|
|
200
|
+
}
|
|
201
|
+
;(root.children || []).forEach(child => collectAllStatCalResults(child, bucket))
|
|
202
|
+
return bucket
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function findStatCalBlock(treeData, pid, modelWrap) {
|
|
206
|
+
const local = (treeData && treeData.statCalResult) || []
|
|
207
|
+
let block = local.find(r => r.pid === pid)
|
|
208
|
+
if (block) return block
|
|
209
|
+
const modelRoot = modelWrap && modelWrap.modelTreeVO
|
|
210
|
+
if (!modelRoot) return null
|
|
211
|
+
return collectAllStatCalResults(modelRoot).find(r => r.pid === pid) || null
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* 分组标题优先用 statCalResult.statIndicatorName(分组目录名),
|
|
216
|
+
* 否则按 pid 反查树节点 name;禁止回退到第一个指标 name(缺陷现象)。
|
|
217
|
+
*/
|
|
218
|
+
function resolveStatIndicatorName(calBlock, treeData, pid, indicatorItems, modelWrap) {
|
|
219
|
+
if (calBlock && calBlock.statIndicatorName) return calBlock.statIndicatorName
|
|
220
|
+
const fromTree =
|
|
221
|
+
findNodeByTid(treeData, pid) ||
|
|
222
|
+
findNodeByTid(modelWrap && modelWrap.modelTreeVO, pid)
|
|
223
|
+
if (fromTree && fromTree.name) return fromTree.name
|
|
224
|
+
const first = indicatorItems && indicatorItems[0]
|
|
225
|
+
if (first && first.folderName) return first.folderName
|
|
226
|
+
return ''
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function resolveStatsResultList(calBlock, treeData, indicatorItems, modelWrap) {
|
|
230
|
+
const fromBlock = normalizeStatsResultList(calBlock && calBlock.statsResultList)
|
|
231
|
+
if (fromBlock) return fromBlock
|
|
232
|
+
const fromModel = normalizeStatsResultList(
|
|
233
|
+
(modelWrap && modelWrap.modelStatsSetupVOS) ||
|
|
234
|
+
(treeData && treeData.modelStatsSetupVOS)
|
|
235
|
+
)
|
|
236
|
+
if (fromModel) return fromModel
|
|
237
|
+
const first = indicatorItems && indicatorItems[0]
|
|
238
|
+
return buildStatsResultListFromChildren(statItemChildren(first))
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function resolveTableBlockMeta(treeData, pid, indicatorItems, modelWrap) {
|
|
242
|
+
const calBlock = findStatCalBlock(treeData, pid, modelWrap)
|
|
136
243
|
return {
|
|
137
|
-
statIndicatorName:
|
|
138
|
-
calBlock
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
244
|
+
statIndicatorName: resolveStatIndicatorName(
|
|
245
|
+
calBlock,
|
|
246
|
+
treeData,
|
|
247
|
+
pid,
|
|
248
|
+
indicatorItems,
|
|
249
|
+
modelWrap
|
|
250
|
+
),
|
|
251
|
+
statsResultList: resolveStatsResultList(
|
|
252
|
+
calBlock,
|
|
253
|
+
treeData,
|
|
254
|
+
indicatorItems,
|
|
255
|
+
modelWrap
|
|
256
|
+
)
|
|
142
257
|
}
|
|
143
258
|
}
|
|
144
259
|
|
|
@@ -155,8 +270,9 @@ function groupIsLeaf2ByPid(nodes) {
|
|
|
155
270
|
/**
|
|
156
271
|
* @param {Object} treeData 统计模型节点
|
|
157
272
|
* @param {Function} fetchScoreMap async (itemID) => optionList
|
|
273
|
+
* @param {Object} [modelWrap] 整模 ModelVO(含 modelTreeVO / modelStatsSetupVOS)
|
|
158
274
|
*/
|
|
159
|
-
export async function buildStatModelTables(treeData, fetchScoreMap) {
|
|
275
|
+
export async function buildStatModelTables(treeData, fetchScoreMap, modelWrap) {
|
|
160
276
|
const isLeaf2Nodes = collectIsLeaf2Nodes(treeData.children || [])
|
|
161
277
|
if (!isLeaf2Nodes.length) return []
|
|
162
278
|
|
|
@@ -168,7 +284,8 @@ export async function buildStatModelTables(treeData, fetchScoreMap) {
|
|
|
168
284
|
const { statIndicatorName, statsResultList } = resolveTableBlockMeta(
|
|
169
285
|
treeData,
|
|
170
286
|
pid,
|
|
171
|
-
indicatorItems
|
|
287
|
+
indicatorItems,
|
|
288
|
+
modelWrap
|
|
172
289
|
)
|
|
173
290
|
|
|
174
291
|
const columns = [
|
|
@@ -189,7 +306,8 @@ export async function buildStatModelTables(treeData, fetchScoreMap) {
|
|
|
189
306
|
align: 'center',
|
|
190
307
|
slotName: label
|
|
191
308
|
})
|
|
192
|
-
|
|
309
|
+
// 测算页始终展示指标得分列;statShow 仅约束业务端(授信等)是否展示
|
|
310
|
+
if (statMeta.calType == 0) {
|
|
193
311
|
columns.push({
|
|
194
312
|
label: item.statsName + '指标得分',
|
|
195
313
|
prop: item.statsName + '指标得分',
|
|
@@ -223,12 +341,22 @@ export async function buildStatModelTables(treeData, fetchScoreMap) {
|
|
|
223
341
|
statMeta.calType == 0
|
|
224
342
|
? item.statsName + '指标值'
|
|
225
343
|
: item.statsName
|
|
226
|
-
|
|
344
|
+
// 非手工填报:每次重建表格都取最新测算值;手工填报保留用户已输入
|
|
345
|
+
if (item.sourceType === 3) {
|
|
346
|
+
applyCellValue(item, optionList)
|
|
347
|
+
} else {
|
|
348
|
+
item.value = resolveCellValue(item, optionList)
|
|
349
|
+
}
|
|
227
350
|
listItem[label] = item
|
|
228
351
|
if (statMeta.calType == 0) {
|
|
352
|
+
const scoreVal =
|
|
353
|
+
item.result !== '' && item.result != null
|
|
354
|
+
? item.result
|
|
355
|
+
: item.modifiedResult
|
|
229
356
|
listItem[item.statsName + '指标得分'] = {
|
|
230
357
|
...item,
|
|
231
|
-
|
|
358
|
+
result: scoreVal,
|
|
359
|
+
value: scoreVal,
|
|
232
360
|
sourceType: '',
|
|
233
361
|
displayStyle: 0,
|
|
234
362
|
calcState: false
|
|
@@ -342,6 +470,9 @@ export function mergeStatModelNode(target, source) {
|
|
|
342
470
|
if (source.statsResultList) {
|
|
343
471
|
target.statsResultList = source.statsResultList
|
|
344
472
|
}
|
|
473
|
+
if (source.modelStatsSetupVOS) {
|
|
474
|
+
target.modelStatsSetupVOS = source.modelStatsSetupVOS
|
|
475
|
+
}
|
|
345
476
|
const fields = [
|
|
346
477
|
'result',
|
|
347
478
|
'resultText',
|