调整评分量化表

This commit is contained in:
2026-08-25 03:25:56 +08:00
parent e5992a0c63
commit 9405c51de8
2 changed files with 638 additions and 276 deletions
+126 -28
View File
@@ -1210,20 +1210,32 @@
<el-table-column label="评分标准" min-width="430">
<template #default="{ row: detail }">
<div class="score-standard-cell">
<div class="score-standard-cell__label">请选择:</div>
<el-select
v-model="detail.selectedOption"
filterable
:disabled="readonly"
@change="scoreOptionChange(detail, $event)"
>
<el-option
v-for="item in parseScoreOptions(detail.optionsJson)"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<template v-if="isScoreTypeDetail(detail)">
<el-input
:model-value="detail.scoreInput"
inputmode="decimal"
:disabled="readonly"
@input="value => handleScoreValueInput(detail, value)"
>
<template #append>{{ getScoreRule(detail)?.changeUnit || '' }}</template>
</el-input>
</template>
<template v-else>
<div class="score-standard-cell__label">请选择:</div>
<el-select
v-model="detail.selectedOption"
filterable
:disabled="readonly"
@change="scoreOptionChange(detail, $event)"
>
<el-option
v-for="item in parseScoreOptions(detail.optionsJson)"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
</div>
</template>
</el-table-column>
@@ -2154,8 +2166,8 @@ export default {
const scoreDetails = this.normalizeChangeFieldValue(score.details);
const details = (Array.isArray(scoreDetails) ? scoreDetails : [])
.map(detail => {
const category =
detail.categoryName || categoryNames[this.getScoreDetailCategoryCode(detail)] || '';
const categoryCode = this.getScoreDetailCategoryCode(detail);
const category = categoryNames[categoryCode] || detail.categoryName || '';
const itemName = detail.itemName || '评分项目';
const option = detail.selectedOption || detail.scoreDescription || '';
const points = [
@@ -3537,7 +3549,10 @@ export default {
quantificationId: score.quantificationId ? String(score.quantificationId) : '',
tempApplyCreditLimit: this.normalizeOptionalAmount(score.tempApplyCreditLimit),
attachments: score.attachments || this.parseAttachments(score.proofAttachments),
details: score.details || [],
details: (score.details || []).map(detail => ({
...detail,
scoreInput: this.normalizeScoreInputValue(detail.scoreInput),
})),
};
},
normalizeOptionalAmount(value) {
@@ -3836,6 +3851,7 @@ export default {
...item,
categoryCode: category.categoryCode,
categoryName: category.categoryName,
scoreInput: this.normalizeScoreInputValue(item.scoreInput),
optionsJson:
item.optionsJson ||
JSON.stringify(
@@ -3843,6 +3859,10 @@ export default {
label: option.label || option.optionName || option.value,
value: option.value || option.optionName || option.label,
score: option.score,
changeType: option.changeType,
changeValue: option.changeValue,
changeUnit: option.changeUnit,
scoreType: option.scoreType,
}))
),
}))
@@ -3862,9 +3882,16 @@ export default {
...detail,
categoryCode: detail.categoryCode || category?.categoryCode || '',
categoryName: detail.categoryName || category?.categoryName || '',
scoreInput: this.normalizeScoreInputValue(detail.scoreInput),
};
});
},
normalizeScoreInputValue(value) {
if (value === undefined || value === null || value === '' || value === -1 || value === '-1') {
return '';
}
return String(value);
},
getScoreDetailCategoryCode(detail = {}) {
const rawCode = String(
detail.categoryCode ||
@@ -3916,12 +3943,24 @@ export default {
parseScoreOptions(value) {
if (!value) return [];
const normalize = list =>
list.map(item => ({
...item,
label: item.label || item.optionName || item.value,
value: item.value || item.optionName || item.label,
score: item.score,
}));
list.map(item => {
const isScoreOption = item.changeType || item.changeValue || item.changeUnit;
const changeLabel = item.changeType === 'decrease' ? '每减少' : '每增加';
const scoreLabel = item.scoreType === 'subtract' ? '减' : '加';
const generatedLabel = isScoreOption
? `${changeLabel}${item.changeValue || ''}${item.changeUnit || ''}${scoreLabel}${item.score || ''}分`
: '';
const label = item.label || item.optionName || item.value || generatedLabel;
return {
...item,
label,
value: item.value || item.optionName || item.label || generatedLabel,
score:
item.scoreType === 'subtract' && item.score !== undefined
? -Math.abs(Number(item.score))
: item.score,
};
});
if (Array.isArray(value)) return normalize(value);
try {
const options = JSON.parse(value);
@@ -3930,6 +3969,50 @@ export default {
return [];
}
},
isScoreTypeDetail(detail = {}) {
return String(detail.optionType || '').toLowerCase() === 'score';
},
getScoreRule(detail = {}) {
return this.parseScoreOptions(detail.optionsJson)[0] || null;
},
handleScoreValueInput(detail, value) {
const raw = String(value ?? '')
.replace(/[^\d.-]/g, '')
.replace(/(?!^)-/g, '')
.replace(/(\..*)\./g, '$1');
const sign = raw.startsWith('-') ? '-' : '';
const unsigned = raw.replace(/^-/, '');
const hasDecimal = unsigned.includes('.');
const [integerPart, decimalPart = ''] = unsigned.split('.');
const normalized = `${sign}${integerPart}${hasDecimal ? `.${decimalPart.slice(0, 2)}` : ''}`;
detail.scoreInput = normalized;
const rule = this.getScoreRule(detail);
if (!normalized || normalized === '-' || normalized === '.') {
detail.selfScore = '';
this.calculateScore(this.currentScore);
return;
}
const base = Number(detail.baseValue);
const input = Number(normalized);
if (!rule || !Number.isFinite(base) || !Number.isFinite(input)) {
detail.selfScore = '';
this.calculateScore(this.currentScore);
return;
}
const increase = rule.changeType !== 'decrease';
const valid = increase ? input >= base : input <= base;
if (!valid) {
detail.selfScore = '';
this.$message.warning(`输入值${increase ? '不能小于' : '不能大于'}基准数值${base}`);
this.calculateScore(this.currentScore);
return;
}
const distance = increase ? input - base : base - input;
const stepScore = Math.abs(Number(rule.score || 0));
const signedStep = rule.scoreType === 'subtract' ? -stepScore : stepScore;
detail.selfScore = Number((Number(detail.score || 0) + distance * signedStep).toFixed(2));
this.calculateScore(this.currentScore);
},
scoreOptionChange(detail, optionValue) {
const option = this.parseScoreOptions(detail.optionsJson).find(
item => item.value === optionValue
@@ -4076,9 +4159,13 @@ export default {
return score;
},
hasIncompleteBasicScoreDetail(details = []) {
return this.getScoreCategoryDetailsByList(details, 'basic').some(
item => !item.selectedOption
);
return this.getScoreCategoryDetailsByList(details, 'basic').some(item => {
if (this.isScoreTypeDetail(item)) {
const input = String(item.scoreInput ?? '').trim();
return !input || !Number.isFinite(Number(input)) || item.selfScore === '';
}
return !item.selectedOption;
});
},
finishScore(score) {
if (!score.details || !score.details.length) {
@@ -4086,7 +4173,7 @@ export default {
return;
}
if (this.hasIncompleteBasicScoreDetail(score.details)) {
this.$message.warning('请完整选择基础得分项评分明细选项');
this.$message.warning('请完整填写基础得分项评分明细');
return;
}
this.calculateScore(score);
@@ -4148,6 +4235,17 @@ export default {
this.$message.warning('当前评分量化表未配置评分项目');
return false;
}
const invalidScoreInput = this.currentScore.details.find(item => {
if (!this.isScoreTypeDetail(item)) return false;
const input = String(item.scoreInput ?? '').trim();
return input !== '' && item.selfScore === '';
});
if (invalidScoreInput) {
this.$message.warning(
`${invalidScoreInput.itemName || '评分项目'}的输入值不符合基准数值限制,请重新填写`
);
return false;
}
const overMaxReviewScore = this.currentScore.details.find(item => {
if (
item.reviewScore === undefined ||
@@ -4169,7 +4267,7 @@ export default {
return false;
}
if (requireComplete && this.hasIncompleteBasicScoreDetail(this.currentScore.details)) {
this.$message.warning('请完整选择基础得分项评分明细选项');
this.$message.warning('请完整填写基础得分项评分明细');
return false;
}
return true;