调整评分量化表
This commit is contained in:
@@ -85,67 +85,73 @@
|
||||
>
|
||||
<div class="score-config">
|
||||
<section-card title="评分量化表">
|
||||
<el-form
|
||||
:model="configForm"
|
||||
label-position="right"
|
||||
label-width="auto"
|
||||
class="archive-form"
|
||||
:disabled="readonly"
|
||||
>
|
||||
<el-form-item label="评定表名称" required>
|
||||
<el-input
|
||||
v-model="configForm.name"
|
||||
class="score-config__name-input"
|
||||
maxlength="30"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input
|
||||
v-model="configForm.remark"
|
||||
type="textarea"
|
||||
:rows="1"
|
||||
maxlength="500"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-form
|
||||
:model="configForm"
|
||||
label-position="right"
|
||||
label-width="auto"
|
||||
class="archive-form"
|
||||
:disabled="readonly"
|
||||
>
|
||||
<el-form-item label="评定表名称" required>
|
||||
<el-input
|
||||
v-model="configForm.name"
|
||||
class="score-config__name-input"
|
||||
maxlength="30"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input
|
||||
v-model="configForm.remark"
|
||||
type="textarea"
|
||||
:rows="1"
|
||||
maxlength="500"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</section-card>
|
||||
|
||||
<section-card title="评分表">
|
||||
<el-table :data="configForm.categories" border class="config-table">
|
||||
<el-table-column label="序号" type="index" width="90" align="center" />
|
||||
<el-table-column label="评分类目" prop="categoryName" min-width="180" />
|
||||
<el-table-column label="评分项目数" width="140" align="center">
|
||||
<template #default="{ row }">{{ row.items.length }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="160" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-link type="primary" @click="openCategory(row)">编辑</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-table :data="configForm.categories" border class="config-table">
|
||||
<el-table-column label="序号" type="index" width="90" align="center" />
|
||||
<el-table-column label="评分类目" prop="categoryName" min-width="180" />
|
||||
<el-table-column label="评分项目数" width="140" align="center">
|
||||
<template #default="{ row }">{{ row.items.length }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="160" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-link type="primary" @click="openCategory(row)">编辑</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</section-card>
|
||||
|
||||
<section-card title="评估标准">
|
||||
<template #extra>
|
||||
<el-button type="primary" plain icon="el-icon-plus" v-if="!readonly" @click="openStandard()">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
icon="el-icon-plus"
|
||||
v-if="!readonly"
|
||||
@click="openStandard()"
|
||||
>
|
||||
添加评估标准
|
||||
</el-button>
|
||||
</template>
|
||||
<el-table :data="configForm.standards" border class="config-table">
|
||||
<el-table-column label="序号" type="index" width="90" align="center" />
|
||||
<el-table-column label="信用等级" prop="creditLevel" width="120" align="center" />
|
||||
<el-table-column label="标准说明" prop="standardDescription" min-width="320" />
|
||||
<el-table-column label="操作" width="160" align="center">
|
||||
<template #default="{ row, $index }">
|
||||
<el-link type="primary" @click="openStandard(row, $index)">编辑</el-link>
|
||||
<el-link type="danger" v-if="!readonly" @click="removeStandard($index)"
|
||||
>删除</el-link
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-table :data="configForm.standards" border class="config-table">
|
||||
<el-table-column label="序号" type="index" width="90" align="center" />
|
||||
<el-table-column label="信用等级" prop="creditLevel" width="120" align="center" />
|
||||
<el-table-column label="标准说明" prop="standardDescription" min-width="320" />
|
||||
<el-table-column label="操作" width="160" align="center">
|
||||
<template #default="{ row, $index }">
|
||||
<el-link type="primary" @click="openStandard(row, $index)">编辑</el-link>
|
||||
<el-link type="danger" v-if="!readonly" @click="removeStandard($index)"
|
||||
>删除</el-link
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</section-card>
|
||||
</div>
|
||||
<template #footer>
|
||||
@@ -166,31 +172,37 @@
|
||||
<div class="category-line">评分类目:{{ currentCategory.categoryName }}</div>
|
||||
<section-card title="评分项目">
|
||||
<template #extra>
|
||||
<el-button type="primary" plain icon="el-icon-plus" v-if="!readonly" @click="openItem()">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
icon="el-icon-plus"
|
||||
v-if="!readonly"
|
||||
@click="openItem()"
|
||||
>
|
||||
添加评分项目
|
||||
</el-button>
|
||||
</template>
|
||||
<el-table :data="currentCategory.items" border class="config-table">
|
||||
<el-table-column label="序号" type="index" width="90" align="center" />
|
||||
<el-table-column label="评分项目" prop="itemName" width="180" />
|
||||
<el-table-column label="得分说明" prop="scoreDescription" min-width="260" />
|
||||
<el-table-column label="选项数" width="100" align="center">
|
||||
<template #default="{ row }">{{ row.options.length }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="160" align="center">
|
||||
<template #default="{ row, $index }">
|
||||
<el-link type="primary" @click="openItem(row, $index)">编辑</el-link>
|
||||
<el-link
|
||||
type="danger"
|
||||
v-if="!readonly"
|
||||
:disabled="currentCategory.items.length <= 1"
|
||||
@click="removeItem($index)"
|
||||
>
|
||||
删除
|
||||
</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-table :data="currentCategory.items" border class="config-table">
|
||||
<el-table-column label="序号" type="index" width="90" align="center" />
|
||||
<el-table-column label="评分项目" prop="itemName" width="180" />
|
||||
<el-table-column label="得分说明" prop="scoreDescription" min-width="260" />
|
||||
<el-table-column label="选项数" width="100" align="center">
|
||||
<template #default="{ row }">{{ row.options.length }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="160" align="center">
|
||||
<template #default="{ row, $index }">
|
||||
<el-link type="primary" @click="openItem(row, $index)">编辑</el-link>
|
||||
<el-link
|
||||
type="danger"
|
||||
v-if="!readonly"
|
||||
:disabled="currentCategory.items.length <= 1"
|
||||
@click="removeItem($index)"
|
||||
>
|
||||
删除
|
||||
</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</section-card>
|
||||
</div>
|
||||
<template #footer>
|
||||
@@ -206,51 +218,119 @@
|
||||
class="score-item-dialog"
|
||||
>
|
||||
<section-card title="评分项目详情">
|
||||
<el-form
|
||||
:model="itemForm"
|
||||
label-position="right"
|
||||
label-width="112px"
|
||||
:disabled="readonly"
|
||||
class="score-item-form"
|
||||
>
|
||||
<div class="score-item-form__top">
|
||||
<el-form-item label="评分项目" required>
|
||||
<el-input v-model="itemForm.itemName" maxlength="20" />
|
||||
</el-form-item>
|
||||
<el-form-item label="分值" required>
|
||||
<el-input-number v-model="itemForm.score" :min="1" :precision="0" :step="1" :controls="false" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
<el-form-item label="得分说明">
|
||||
<el-input v-model="itemForm.scoreDescription" maxlength="300" class="score-description-input" />
|
||||
</el-form-item>
|
||||
<el-form-item label="选项描述">
|
||||
<el-input v-model="itemForm.optionDescription" maxlength="100" />
|
||||
</el-form-item>
|
||||
<el-form-item label="选项" required>
|
||||
<div class="option-editor">
|
||||
<div class="option-row" v-for="(option, index) in itemForm.options" :key="index">
|
||||
<el-input v-model="option.optionName" maxlength="100" />
|
||||
<div class="option-score">
|
||||
<el-input-number v-model="option.score" :min="1" :precision="0" :step="1" :controls="false" />
|
||||
<span class="score-unit">分</span>
|
||||
</div>
|
||||
<el-link
|
||||
type="danger"
|
||||
class="option-delete"
|
||||
v-if="!readonly && itemForm.options.length > 1"
|
||||
@click="removeOption(index)"
|
||||
>
|
||||
删除
|
||||
</el-link>
|
||||
</div>
|
||||
<div class="option-add">
|
||||
<el-link type="primary" v-if="!readonly" @click="addOption">
|
||||
+添加选项
|
||||
</el-link>
|
||||
</div>
|
||||
<el-form
|
||||
:model="itemForm"
|
||||
label-position="right"
|
||||
label-width="112px"
|
||||
:disabled="readonly"
|
||||
class="score-item-form"
|
||||
>
|
||||
<div class="score-item-form__top">
|
||||
<el-form-item label="评分项目" required>
|
||||
<el-input v-model="itemForm.itemName" maxlength="20" />
|
||||
</el-form-item>
|
||||
<el-form-item label="分值" required>
|
||||
<el-input-number
|
||||
v-model="itemForm.score"
|
||||
:min="0.01"
|
||||
:precision="2"
|
||||
:step="0.01"
|
||||
:controls="false"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="得分说明">
|
||||
<el-input
|
||||
v-model="itemForm.scoreDescription"
|
||||
maxlength="300"
|
||||
class="score-description-input"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="选项描述">
|
||||
<el-input v-model="itemForm.optionDescription" maxlength="100" />
|
||||
</el-form-item>
|
||||
<el-form-item label="选项类型" required>
|
||||
<el-radio-group v-model="itemForm.optionType" @change="handleOptionTypeChange">
|
||||
<el-radio value="option">选项</el-radio>
|
||||
<el-radio value="score">分值</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="itemForm.optionType === 'score'" label="基准数值" required>
|
||||
<el-input
|
||||
:model-value="itemForm.baseValue"
|
||||
inputmode="decimal"
|
||||
@input="handleBaseValueInput"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="itemForm.optionType === 'score' ? '阶梯配置' : '选项'" required>
|
||||
<div class="option-editor">
|
||||
<div
|
||||
class="option-row"
|
||||
:class="{ 'option-row--score': itemForm.optionType === 'score' }"
|
||||
v-for="(option, index) in itemForm.options"
|
||||
:key="index"
|
||||
>
|
||||
<template v-if="itemForm.optionType === 'score'">
|
||||
<el-select v-model="option.changeType" class="option-change-type">
|
||||
<el-option label="每增加" value="increase" />
|
||||
<el-option label="每减少" value="decrease" />
|
||||
</el-select>
|
||||
<el-input
|
||||
:model-value="option.changeValue"
|
||||
inputmode="decimal"
|
||||
@input="value => handleOptionDecimalInput(option, 'changeValue', value)"
|
||||
>
|
||||
<template #append>
|
||||
<el-select v-model="option.changeUnit" class="option-unit-select">
|
||||
<el-option
|
||||
v-for="unit in scoreUnitOptions"
|
||||
:key="unit"
|
||||
:label="unit"
|
||||
:value="unit"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-input>
|
||||
<el-select v-model="option.scoreType" class="option-score-type">
|
||||
<el-option label="加" value="add" />
|
||||
<el-option label="减" value="subtract" />
|
||||
</el-select>
|
||||
<div class="option-score">
|
||||
<el-input
|
||||
:model-value="option.score"
|
||||
inputmode="decimal"
|
||||
@input="value => handleOptionDecimalInput(option, 'score', value)"
|
||||
>
|
||||
<template #append>分</template>
|
||||
</el-input>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-input v-model="option.optionName" maxlength="100" />
|
||||
<div class="option-score">
|
||||
<el-input
|
||||
:model-value="option.score"
|
||||
inputmode="decimal"
|
||||
@input="value => handleOptionDecimalInput(option, 'score', value)"
|
||||
>
|
||||
<template #append>分</template>
|
||||
</el-input>
|
||||
</div>
|
||||
</template>
|
||||
<el-link
|
||||
type="danger"
|
||||
class="option-delete"
|
||||
v-if="!readonly && itemForm.options.length > 1"
|
||||
@click="removeOption(index)"
|
||||
>
|
||||
删除
|
||||
</el-link>
|
||||
</div>
|
||||
<div class="option-add" v-if="itemForm.optionType !== 'score'">
|
||||
<el-link type="primary" v-if="!readonly" @click="addOption"> +添加选项 </el-link>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</section-card>
|
||||
<template #footer>
|
||||
@@ -267,93 +347,99 @@
|
||||
:close-on-press-escape="false"
|
||||
>
|
||||
<section-card title="评估标准设置">
|
||||
<el-form :model="standardForm" label-position="right" label-width="auto" :disabled="readonly" class="standard-form archive-form">
|
||||
<el-form
|
||||
:model="standardForm"
|
||||
label-position="right"
|
||||
label-width="auto"
|
||||
:disabled="readonly"
|
||||
class="standard-form archive-form"
|
||||
>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="信用等级" required>
|
||||
<el-select
|
||||
v-model="standardForm.creditLevel"
|
||||
placeholder="请选择信用等级"
|
||||
clearable
|
||||
@change="handleStandardCreditLevelChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in creditLevelOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="得分率(%)" required>
|
||||
<div class="range-input standard-range-input score-rate-range">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="信用等级" required>
|
||||
<el-select
|
||||
v-model="standardForm.creditLevel"
|
||||
placeholder="请选择信用等级"
|
||||
clearable
|
||||
@change="handleStandardCreditLevelChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in creditLevelOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="得分率(%)" required>
|
||||
<div class="range-input standard-range-input score-rate-range">
|
||||
<el-input
|
||||
v-model="standardForm.scoreRateLower"
|
||||
inputmode="numeric"
|
||||
@input="value => handleStandardNumberInput('scoreRateLower', value, 0, 100)"
|
||||
/>
|
||||
<span>至</span>
|
||||
<el-input
|
||||
v-model="standardForm.scoreRateUpper"
|
||||
inputmode="numeric"
|
||||
@input="value => handleStandardNumberInput('scoreRateUpper', value, 0, 100)"
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="得分率每增加" required>
|
||||
<el-input
|
||||
v-model="standardForm.scoreRateLower"
|
||||
v-model="standardForm.scoreRateIncrease"
|
||||
inputmode="numeric"
|
||||
@input="value => handleStandardNumberInput('scoreRateLower', value, 0, 100)"
|
||||
/>
|
||||
<span>至</span>
|
||||
@input="value => handleStandardNumberInput('scoreRateIncrease', value)"
|
||||
>
|
||||
<template #suffix>%</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="额度增加(万元)" required>
|
||||
<el-input
|
||||
v-model="standardForm.scoreRateUpper"
|
||||
inputmode="numeric"
|
||||
@input="value => handleStandardNumberInput('scoreRateUpper', value, 0, 100)"
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="得分率每增加" required>
|
||||
<el-input
|
||||
v-model="standardForm.scoreRateIncrease"
|
||||
inputmode="numeric"
|
||||
@input="value => handleStandardNumberInput('scoreRateIncrease', value)"
|
||||
>
|
||||
<template #suffix>%</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="额度增加(万元)" required>
|
||||
<el-input
|
||||
v-model="standardForm.creditLimitIncrease"
|
||||
inputmode="decimal"
|
||||
@input="value => handleStandardNumberInput('creditLimitIncrease', value, 2)"
|
||||
class="credit-increase-input"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="最大资金使用额度(万元)" required>
|
||||
<div class="range-input standard-range-input credit-limit-range">
|
||||
<el-input
|
||||
v-model="standardForm.creditLimitLower"
|
||||
v-model="standardForm.creditLimitIncrease"
|
||||
inputmode="decimal"
|
||||
@input="value => handleStandardNumberInput('creditLimitLower', value, 2)"
|
||||
@input="value => handleStandardNumberInput('creditLimitIncrease', value, 2)"
|
||||
class="credit-increase-input"
|
||||
/>
|
||||
<span>至</span>
|
||||
<el-input
|
||||
v-model="standardForm.creditLimitUpper"
|
||||
inputmode="decimal"
|
||||
@input="value => handleStandardNumberInput('creditLimitUpper', value, 2)"
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="标准说明">
|
||||
<el-input
|
||||
v-model="standardForm.standardDescription"
|
||||
type="textarea"
|
||||
maxlength="500"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="最大资金使用额度(万元)" required>
|
||||
<div class="range-input standard-range-input credit-limit-range">
|
||||
<el-input
|
||||
v-model="standardForm.creditLimitLower"
|
||||
inputmode="decimal"
|
||||
@input="value => handleStandardNumberInput('creditLimitLower', value, 2)"
|
||||
/>
|
||||
<span>至</span>
|
||||
<el-input
|
||||
v-model="standardForm.creditLimitUpper"
|
||||
inputmode="decimal"
|
||||
@input="value => handleStandardNumberInput('creditLimitUpper', value, 2)"
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="标准说明">
|
||||
<el-input
|
||||
v-model="standardForm.standardDescription"
|
||||
type="textarea"
|
||||
maxlength="500"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</section-card>
|
||||
<template #footer>
|
||||
@@ -413,6 +499,7 @@ export default {
|
||||
label: item,
|
||||
value: item,
|
||||
})),
|
||||
scoreUnitOptions: ['%', '件', '次', '项', '天'],
|
||||
option: {
|
||||
height: 'auto',
|
||||
calcHeight: 32,
|
||||
@@ -536,7 +623,19 @@ export default {
|
||||
score: 1,
|
||||
scoreDescription: '',
|
||||
optionDescription: '',
|
||||
options: [{ optionName: '', score: 1 }],
|
||||
optionType: 'option',
|
||||
baseValue: '',
|
||||
options: [this.emptyOption()],
|
||||
};
|
||||
},
|
||||
emptyOption() {
|
||||
return {
|
||||
optionName: '',
|
||||
score: 1,
|
||||
changeType: 'increase',
|
||||
changeValue: '',
|
||||
changeUnit: '%',
|
||||
scoreType: 'add',
|
||||
};
|
||||
},
|
||||
emptyStandard() {
|
||||
@@ -559,14 +658,20 @@ export default {
|
||||
...category,
|
||||
items: (category.items || []).map(item => ({
|
||||
...item,
|
||||
optionType: this.normalizeOptionType(item.optionType),
|
||||
options:
|
||||
item.options && item.options.length ? item.options : [{ optionName: '', score: 1 }],
|
||||
item.options && item.options.length
|
||||
? item.options.map(option => this.normalizeOption(option))
|
||||
: [this.emptyOption()],
|
||||
})),
|
||||
};
|
||||
});
|
||||
return {
|
||||
...detail,
|
||||
categories: categories.map(category => map[category.categoryCode] || category),
|
||||
categories: categories.map(category => ({
|
||||
...(map[category.categoryCode] || category),
|
||||
categoryName: category.categoryName,
|
||||
})),
|
||||
standards: detail.standards || [],
|
||||
};
|
||||
},
|
||||
@@ -596,10 +701,84 @@ export default {
|
||||
openItem(row, index = -1) {
|
||||
this.currentItemIndex = index;
|
||||
this.itemForm = row
|
||||
? { ...this.emptyItem(), ...JSON.parse(JSON.stringify(row)) }
|
||||
? this.normalizeItem({ ...this.emptyItem(), ...JSON.parse(JSON.stringify(row)) })
|
||||
: this.emptyItem();
|
||||
this.itemBox = true;
|
||||
},
|
||||
normalizeOptionType(value) {
|
||||
return value === 'score' || value === 2 || String(value) === 'score' ? 'score' : 'option';
|
||||
},
|
||||
normalizeItem(item = {}) {
|
||||
return {
|
||||
...this.emptyItem(),
|
||||
...item,
|
||||
optionType: this.normalizeOptionType(item.optionType),
|
||||
options:
|
||||
item.options && item.options.length
|
||||
? item.options.map(option => this.normalizeOption(option))
|
||||
: [this.emptyOption()],
|
||||
};
|
||||
},
|
||||
normalizeOption(option = {}) {
|
||||
const normalized = { ...this.emptyOption(), ...option };
|
||||
return {
|
||||
...normalized,
|
||||
changeType:
|
||||
normalized.changeType === 'decrease' ||
|
||||
normalized.changeType === '每减少' ||
|
||||
normalized.changeType === 2
|
||||
? 'decrease'
|
||||
: 'increase',
|
||||
scoreType:
|
||||
normalized.scoreType === 'subtract' ||
|
||||
normalized.scoreType === '减' ||
|
||||
normalized.scoreType === 2
|
||||
? 'subtract'
|
||||
: 'add',
|
||||
};
|
||||
},
|
||||
handleOptionTypeChange(value) {
|
||||
this.itemForm.optionType = this.normalizeOptionType(value);
|
||||
this.itemForm.options = (this.itemForm.options || []).map(option =>
|
||||
this.normalizeOption(option)
|
||||
);
|
||||
},
|
||||
handleBaseValueInput(value) {
|
||||
const source = String(value ?? '').replace(/[^\d.-]/g, '');
|
||||
const negative = source.startsWith('-');
|
||||
const unsigned = source.replace(/-/g, '');
|
||||
const [integer = '', ...decimalParts] = unsigned.split('.');
|
||||
const decimal = decimalParts.join('').slice(0, 10);
|
||||
this.itemForm.baseValue = `${negative ? '-' : ''}${integer}${decimalParts.length ? `.${decimal}` : ''}`;
|
||||
},
|
||||
handleOptionDecimalInput(option, field, value) {
|
||||
option[field] = this.normalizeDecimalInput(value);
|
||||
},
|
||||
normalizeDecimalInput(value) {
|
||||
const source = String(value ?? '').replace(/[^\d.]/g, '');
|
||||
const [integer = '', ...decimalParts] = source.split('.');
|
||||
const decimal = decimalParts.join('').slice(0, 2);
|
||||
return decimalParts.length ? `${integer}.${decimal}` : integer;
|
||||
},
|
||||
toScoreValue(value) {
|
||||
const number = Number(value);
|
||||
return Number.isFinite(number) ? number.toFixed(2) : value;
|
||||
},
|
||||
prepareSubmitConfig(config) {
|
||||
const payload = JSON.parse(JSON.stringify(config || {}));
|
||||
(payload.categories || []).forEach(category => {
|
||||
(category.items || []).forEach(item => {
|
||||
item.score = this.toScoreValue(item.score);
|
||||
(item.options || []).forEach(option => {
|
||||
option.score = this.toScoreValue(option.score);
|
||||
if (this.normalizeOptionType(item.optionType) === 'score') {
|
||||
option.changeValue = this.toScoreValue(option.changeValue);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
return payload;
|
||||
},
|
||||
hasDuplicateItemName(itemName, currentIndex = -1) {
|
||||
const name = String(itemName || '').trim();
|
||||
return this.currentCategory.items.some(
|
||||
@@ -623,37 +802,55 @@ export default {
|
||||
this.$message.warning('请输入分值');
|
||||
return;
|
||||
}
|
||||
if (!this.isPositiveInteger(this.itemForm.score)) {
|
||||
this.$message.warning('分值只能输入正整数');
|
||||
return;
|
||||
}
|
||||
if (!this.itemForm.options.length) {
|
||||
this.$message.warning('至少添加1条档位选项');
|
||||
return;
|
||||
}
|
||||
const invalidOption = this.itemForm.options.some(
|
||||
option =>
|
||||
!String(option.optionName || '').trim() ||
|
||||
option.score === undefined ||
|
||||
option.score === null ||
|
||||
option.score === ''
|
||||
);
|
||||
if (invalidOption) {
|
||||
this.$message.warning('请完整填写档位选项');
|
||||
return;
|
||||
}
|
||||
if (this.itemForm.options.some(option => !this.isPositiveInteger(option.score))) {
|
||||
this.$message.warning('选项分数只能输入正整数');
|
||||
return;
|
||||
if (this.itemForm.optionType === 'score') {
|
||||
if (this.itemForm.options.length !== 1) {
|
||||
this.$message.warning('分值类型只能配置1条阶梯配置');
|
||||
return;
|
||||
}
|
||||
if (!this.isAnyNumber(this.itemForm.baseValue)) {
|
||||
this.$message.warning('请输入基准数值');
|
||||
return;
|
||||
}
|
||||
const invalidScoreOption = this.itemForm.options.some(
|
||||
option =>
|
||||
!option.changeType ||
|
||||
!this.isPositiveDecimal(option.changeValue) ||
|
||||
!option.changeUnit ||
|
||||
!option.scoreType ||
|
||||
!this.isPositiveDecimal(option.score)
|
||||
);
|
||||
if (invalidScoreOption) {
|
||||
this.$message.warning('请完整填写基础分值,并确保数值为正数且最多两位小数');
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
const invalidOption = this.itemForm.options.some(
|
||||
option =>
|
||||
!String(option.optionName || '').trim() ||
|
||||
option.score === undefined ||
|
||||
option.score === null ||
|
||||
option.score === ''
|
||||
);
|
||||
if (invalidOption) {
|
||||
this.$message.warning('请完整填写档位选项');
|
||||
return;
|
||||
}
|
||||
}
|
||||
const item = JSON.parse(JSON.stringify(this.itemForm));
|
||||
item.itemName = String(item.itemName || '').trim();
|
||||
item.optionType = this.normalizeOptionType(item.optionType);
|
||||
item.baseValue = item.optionType === 'score' ? String(item.baseValue).trim() : null;
|
||||
item.options = item.options.map(option => ({
|
||||
...option,
|
||||
optionName: String(option.optionName || '').trim(),
|
||||
score: Number(option.score),
|
||||
score: this.toScoreValue(option.score),
|
||||
...(item.optionType === 'score' ? { changeValue: this.toScoreValue(option.changeValue) } : {}),
|
||||
}));
|
||||
item.score = Number(item.score);
|
||||
item.score = this.toScoreValue(item.score);
|
||||
if (this.currentItemIndex >= 0) {
|
||||
this.currentCategory.items.splice(this.currentItemIndex, 1, item);
|
||||
} else {
|
||||
@@ -669,7 +866,7 @@ export default {
|
||||
this.currentCategory.items.splice(index, 1);
|
||||
},
|
||||
addOption() {
|
||||
this.itemForm.options.push({ optionName: '', score: 1 });
|
||||
this.itemForm.options.push(this.emptyOption());
|
||||
},
|
||||
removeOption(index) {
|
||||
this.itemForm.options.splice(index, 1);
|
||||
@@ -788,8 +985,20 @@ export default {
|
||||
isBlankValue(value) {
|
||||
return value === undefined || value === null || value === '';
|
||||
},
|
||||
isPositiveInteger(value) {
|
||||
return /^\d+$/.test(String(value)) && Number(value) > 0;
|
||||
isPositiveDecimal(value) {
|
||||
const number = Number(value);
|
||||
console.log(
|
||||
value,
|
||||
Number.isFinite(number),
|
||||
number,
|
||||
Math.abs(number * 100 - Math.round(number * 100))
|
||||
);
|
||||
if (!Number.isFinite(number) || number <= 0) return false;
|
||||
return Math.abs(number * 100 - Math.round(number * 100)) < 1e-8;
|
||||
},
|
||||
isAnyNumber(value) {
|
||||
const text = String(value ?? '').trim();
|
||||
return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)$/.test(text) && Number.isFinite(Number(text));
|
||||
},
|
||||
hasRangeOverlap(list, lowerProp, upperProp) {
|
||||
const ranges = list
|
||||
@@ -822,17 +1031,32 @@ export default {
|
||||
return false;
|
||||
}
|
||||
for (const item of category.items) {
|
||||
if (!this.isPositiveInteger(item.score)) {
|
||||
this.$message.warning(`${item.itemName || '评分项目'}的分值只能为正整数`);
|
||||
return false;
|
||||
}
|
||||
if (!item.options || item.options.length === 0) {
|
||||
this.$message.warning(`${item.itemName}至少存在1条档位选项`);
|
||||
return false;
|
||||
}
|
||||
if (item.options.some(option => !this.isPositiveInteger(option.score))) {
|
||||
this.$message.warning(`${item.itemName || '评分项目'}的选项分数只能为正整数`);
|
||||
return false;
|
||||
if (this.normalizeOptionType(item.optionType) === 'score') {
|
||||
if (item.options.length !== 1) {
|
||||
this.$message.warning(`${item.itemName || '评分项目'}的分值类型只能配置1条阶梯配置`);
|
||||
return false;
|
||||
}
|
||||
if (!this.isAnyNumber(item.baseValue)) {
|
||||
this.$message.warning(`${item.itemName || '评分项目'}的基准数值不能为空且必须为数字`);
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
item.options.some(
|
||||
option =>
|
||||
!option.changeType ||
|
||||
!this.isPositiveDecimal(option.changeValue) ||
|
||||
!this.scoreUnitOptions.includes(option.changeUnit) ||
|
||||
!option.scoreType ||
|
||||
!this.isPositiveDecimal(option.score)
|
||||
)
|
||||
) {
|
||||
this.$message.warning(`${item.itemName || '评分项目'}的基础分值配置不完整`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -862,24 +1086,40 @@ export default {
|
||||
this.$message.warning('发布前请完整填写评分项目名称');
|
||||
return false;
|
||||
}
|
||||
if (!this.isPositiveInteger(item.score)) {
|
||||
this.$message.warning(`${item.itemName || '评分项目'}的分值只能为正整数`);
|
||||
return false;
|
||||
}
|
||||
if (!item.options || item.options.length === 0) {
|
||||
this.$message.warning(`${item.itemName || '评分项目'}至少配置1个档位选项`);
|
||||
return false;
|
||||
}
|
||||
const invalidOption = item.options.some(
|
||||
option => !String(option.optionName || '').trim() || this.isBlankValue(option.score)
|
||||
);
|
||||
if (invalidOption) {
|
||||
this.$message.warning(`${item.itemName || '评分项目'}的档位选项未填写完整`);
|
||||
return false;
|
||||
}
|
||||
if (item.options.some(option => !this.isPositiveInteger(option.score))) {
|
||||
this.$message.warning(`${item.itemName || '评分项目'}的选项分数只能为正整数`);
|
||||
return false;
|
||||
if (this.normalizeOptionType(item.optionType) === 'score') {
|
||||
if (item.options.length !== 1) {
|
||||
this.$message.warning(`${item.itemName || '评分项目'}的分值类型只能配置1条阶梯配置`);
|
||||
return false;
|
||||
}
|
||||
if (!this.isAnyNumber(item.baseValue)) {
|
||||
this.$message.warning(`${item.itemName || '评分项目'}的基准数值不能为空且必须为数字`);
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
item.options.some(
|
||||
option =>
|
||||
!option.changeType ||
|
||||
!this.isPositiveDecimal(option.changeValue) ||
|
||||
!this.scoreUnitOptions.includes(option.changeUnit) ||
|
||||
!option.scoreType ||
|
||||
!this.isPositiveDecimal(option.score)
|
||||
)
|
||||
) {
|
||||
this.$message.warning(`${item.itemName || '评分项目'}的基础分值配置不完整`);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
const invalidOption = item.options.some(
|
||||
option => !String(option.optionName || '').trim() || this.isBlankValue(option.score)
|
||||
);
|
||||
if (invalidOption) {
|
||||
this.$message.warning(`${item.itemName || '评分项目'}的档位选项未填写完整`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -938,7 +1178,7 @@ export default {
|
||||
saveConfig() {
|
||||
if (!this.validateConfig()) return;
|
||||
submit({
|
||||
...this.configForm,
|
||||
...this.prepareSubmitConfig(this.configForm),
|
||||
status: 3,
|
||||
}).then(() => {
|
||||
this.configBox = false;
|
||||
@@ -1157,6 +1397,31 @@ export default {
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.option-row--score {
|
||||
grid-template-columns: 150px minmax(220px, 1fr) 110px 180px 74px;
|
||||
gap: 16px;
|
||||
|
||||
.option-score {
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.option-change-type,
|
||||
.option-score-type {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.option-unit-select {
|
||||
width: 78px;
|
||||
|
||||
:deep(.el-input__wrapper) {
|
||||
border: 0;
|
||||
border-left: 1px solid #dcdfe6;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.option-score {
|
||||
position: relative;
|
||||
|
||||
@@ -1278,5 +1543,4 @@ export default {
|
||||
margin-left: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user