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

273 lines
10 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<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 class="mobile-form__footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="submitForm" :loading="formLoading"> </el-button>
</div>
</div>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else v-model="dialogVisible" :title="dialogTitle" width="600px">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading">
<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>
<el-divider content-position="left">评分标准满分10分</el-divider>
<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>
<el-form-item label="综合评分" prop="totalScore"><div class="total-score"><span class="score-value">{{ totalScore.toFixed(1) }}</span><span class="score-level">{{ getScoreLevel(totalScore) }}</span></div></el-form-item>
<el-form-item label="评价备注" prop="remark"><el-input v-model="formData.remark" type="textarea" :rows="3" placeholder="请输入评价备注(可选)" maxlength="500" show-word-limit /></el-form-item>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitForm" :loading="formLoading">确定</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { SupplierEvaluationApi, SupplierEvaluationVO } from '@/api/erp/purchase/supplierEvaluation'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
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 {
position: sticky;
bottom: 0;
background: #fff;
padding: 12px 16px;
padding-bottom: calc(12px + env(safe-area-inset-bottom));
border-top: 1px solid #eee;
display: flex;
justify-content: flex-end;
gap: 12px;
z-index: 10;
margin: 0 -4px -12px;
.el-button { flex: 1; height: 40px; font-size: 15px; }
}
.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>