Files
mom-web/src/views/erp/purchase/evaluation/SupplierEvaluationForm.vue

274 lines
7.6 KiB
Vue
Raw Normal View History

2026-03-05 16:52:12 +08:00
<template>
<Dialog v-model="dialogVisible" :title="dialogTitle" width="100%" fullscreen class="mobile-eval-form-dialog">
<div class="mobile-form-wrapper" v-loading="formLoading">
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top">
<div class="mobile-form-section">
<div class="mobile-form-section__title">基本信息</div>
<el-form-item label="供应商" prop="supplierName">
<el-input v-model="formData.supplierName" disabled />
</el-form-item>
<el-form-item label="订单单号" prop="orderNo">
<el-input v-model="formData.orderNo" disabled />
</el-form-item>
</div>
<div class="mobile-form-section">
<div class="mobile-form-section__title">评分标准满分10分</div>
<el-form-item label="质量评分" prop="qualityScore">
<div class="rating-container">
<el-rate v-model="formData.qualityScore" :max="10" show-score score-template="{value}分" allow-half />
<div class="rating-desc">产品质量规格符合度缺陷率等</div>
</div>
</el-form-item>
<el-form-item label="服务评分" prop="serviceScore">
<div class="rating-container">
<el-rate v-model="formData.serviceScore" :max="10" show-score score-template="{value}分" allow-half />
<div class="rating-desc">售前售后服务响应速度专业程度等</div>
</div>
</el-form-item>
<el-form-item label="价格评分" prop="priceScore">
<div class="rating-container">
<el-rate v-model="formData.priceScore" :max="10" show-score score-template="{value}分" allow-half />
<div class="rating-desc">价格合理性性价比优惠政策等</div>
</div>
</el-form-item>
<el-form-item label="交付评分" prop="deliveryScore">
<div class="rating-container">
<el-rate v-model="formData.deliveryScore" :max="10" show-score score-template="{value}分" allow-half />
<div class="rating-desc">交付及时性包装质量物流配送等</div>
</div>
</el-form-item>
</div>
<div class="mobile-form-section">
<div class="mobile-form-section__title">综合评分</div>
<div class="total-score">
<span class="score-value">{{ totalScore.toFixed(1) }}</span>
<span class="score-level">{{ getScoreLevel(totalScore) }}</span>
</div>
</div>
<div class="mobile-form-section">
<div class="mobile-form-section__title">评价备注</div>
<el-form-item prop="remark">
<el-input v-model="formData.remark" type="textarea" :rows="3" placeholder="请输入评价备注(可选)" maxlength="500" show-word-limit />
</el-form-item>
</div>
</el-form>
</div>
<template #footer>
<div class="mobile-form-footer">
<el-button @click="dialogVisible = false" style="flex:1">取消</el-button>
<el-button type="primary" @click="submitForm" :loading="formLoading" style="flex:1">确定</el-button>
</div>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { SupplierEvaluationApi, SupplierEvaluationVO } from '@/api/erp/purchase/supplierEvaluation'
interface SupplierEvaluationForm {
id?: number
supplierId: number
supplierName: string
purchaseOrderId: number
orderNo: string
qualityScore: number
serviceScore: number
priceScore: number
deliveryScore: number
remark: string
}
const { t } = useI18n()
const message = useMessage()
const dialogVisible = ref(false)
const dialogTitle = ref('')
const formLoading = ref(false)
const formType = ref('')
const formRef = ref()
const formData = ref<SupplierEvaluationForm>({
supplierId: 0,
supplierName: '',
purchaseOrderId: 0,
orderNo: '',
qualityScore: 5,
serviceScore: 5,
priceScore: 5,
deliveryScore: 5,
remark: ''
})
const formRules = reactive({
qualityScore: [{ required: true, message: '请评价质量分数', trigger: 'change' }],
serviceScore: [{ required: true, message: '请评价服务分数', trigger: 'change' }],
priceScore: [{ required: true, message: '请评价价格分数', trigger: 'change' }],
deliveryScore: [{ required: true, message: '请评价交付分数', trigger: 'change' }]
})
// 计算综合评分
const totalScore = computed(() => {
return (formData.value.qualityScore + formData.value.serviceScore +
formData.value.priceScore + formData.value.deliveryScore) / 4
})
// 获取评分等级
const getScoreLevel = (score: number) => {
if (score >= 9) return '优秀'
if (score >= 8) return '良好'
if (score >= 7) return '一般'
if (score >= 6) return '及格'
return '不及格'
}
// 打开弹窗
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = type === 'create' ? '新增供应商评价' : '修改供应商评价'
formType.value = type
resetForm()
// 修改时,设置数据
if (id) {
formLoading.value = true
try {
const data = await SupplierEvaluationApi.getSupplierEvaluation(id)
formData.value = {
...data,
supplierName: data.supplierName || '',
orderNo: data.orderNo || ''
}
} finally {
formLoading.value = false
}
}
}
// 重置表单
const resetForm = () => {
formData.value = {
supplierId: 0,
supplierName: '',
purchaseOrderId: 0,
orderNo: '',
qualityScore: 5,
serviceScore: 5,
priceScore: 5,
deliveryScore: 5,
remark: ''
}
}
// 提交表单
const submitForm = async () => {
if (!formRef.value) return
const valid = await formRef.value.validate()
if (!valid) return
try {
formLoading.value = true
const data = {
...formData.value,
totalScore: totalScore.value
}
if (formType.value === 'create') {
await SupplierEvaluationApi.createSupplierEvaluation(data)
message.success('新增成功')
} else {
await SupplierEvaluationApi.updateSupplierEvaluation(data)
message.success('修改成功')
}
dialogVisible.value = false
emit('success')
} catch (error) {
console.error('操作失败', error)
} finally {
formLoading.value = false
}
}
// 定义事件
const emit = defineEmits<{
success: []
}>()
// 暴露方法
defineExpose({ open })
</script>
<style lang="scss" scoped>
.mobile-form-wrapper {
padding: 0 4px;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
.mobile-form-section {
background: #fff;
border-radius: 10px;
padding: 14px;
margin-bottom: 12px;
box-shadow: 0 1px 4px rgba(0,0,0,0.06);
&__title {
font-size: 15px;
font-weight: 600;
color: #303133;
margin-bottom: 12px;
padding-bottom: 8px;
border-bottom: 1px solid #f0f0f0;
}
}
.mobile-form-footer {
display: flex;
gap: 12px;
padding: 0 4px;
}
.rating-container {
display: flex;
flex-direction: column;
gap: 8px;
}
.rating-desc {
font-size: 12px;
color: #909399;
}
.total-score {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 0;
}
.score-value {
font-size: 24px;
font-weight: bold;
color: #409eff;
}
.score-level {
padding: 4px 12px;
border-radius: 4px;
font-size: 12px;
background-color: #f0f9ff;
color: #409eff;
border: 1px solid #b3d8ff;
}
:deep(.el-rate) {
height: auto;
flex-wrap: wrap;
}
:deep(.el-rate__text) {
color: #409eff;
font-weight: 500;
}
:deep(.mobile-eval-form-dialog .el-dialog__body) {
padding: 12px;
background: #f5f5f5;
}
:deep(.el-form-item) {
margin-bottom: 14px;
}
</style>