<template>
|
<div class="rating-form">
|
<div class="form-header">
|
<h3>{{ ratingForm.schemeName || '评分表单' }}</h3>
|
<div class="total-score">
|
总分:{{ totalScore }} / {{ ratingForm.totalMaxScore }}
|
</div>
|
</div>
|
|
<el-form
|
ref="formRef"
|
:model="formData"
|
:rules="rules"
|
label-width="120px"
|
class="rating-form-content"
|
>
|
<!-- 评分项目 -->
|
<div v-if="ratingForm.items && ratingForm.items.length > 0" class="rating-items">
|
<div
|
v-for="item in ratingForm.items"
|
:key="item.id"
|
class="rating-item"
|
>
|
<el-form-item
|
:label="item.name"
|
:prop="`scores.${item.id}`"
|
class="score-item"
|
>
|
<div class="score-input-group">
|
<el-input-number
|
v-model="formData.scores[item.id]"
|
:min="0"
|
:max="item.maxScore"
|
:precision="1"
|
:step="0.5"
|
placeholder="请输入分数"
|
class="score-input"
|
/>
|
<span class="max-score">/ {{ item.maxScore }}</span>
|
</div>
|
<div v-if="item.description" class="item-description">
|
{{ item.description }}
|
</div>
|
</el-form-item>
|
</div>
|
</div>
|
|
<!-- 评语 -->
|
<el-form-item label="评语" prop="comment" class="comment-item">
|
<el-input
|
v-model="formData.comment"
|
type="textarea"
|
:rows="4"
|
placeholder="请输入评语(选填)"
|
maxlength="500"
|
show-word-limit
|
/>
|
</el-form-item>
|
|
<!-- 提交按钮 -->
|
<el-form-item class="submit-item">
|
<el-button
|
type="primary"
|
size="large"
|
@click="handleSubmit"
|
:loading="submitting"
|
class="submit-btn"
|
>
|
提交评分
|
</el-button>
|
<el-button
|
size="large"
|
@click="handleReset"
|
class="reset-btn"
|
>
|
重置
|
</el-button>
|
</el-form-item>
|
</el-form>
|
</div>
|
</template>
|
|
<script setup>
|
import { ref, reactive, computed, watch } from 'vue'
|
import { ElForm, ElFormItem, ElInputNumber, ElInput, ElButton, ElMessage } from 'element-plus'
|
|
const props = defineProps({
|
ratingForm: {
|
type: Object,
|
required: true
|
},
|
activityPlayerId: {
|
type: [String, Number],
|
required: true
|
}
|
})
|
|
const emit = defineEmits(['submit'])
|
|
const formRef = ref()
|
const submitting = ref(false)
|
|
// 表单数据
|
const formData = reactive({
|
scores: {},
|
comment: ''
|
})
|
|
// 初始化分数对象
|
const initScores = () => {
|
if (props.ratingForm.items) {
|
props.ratingForm.items.forEach(item => {
|
formData.scores[item.id] = null
|
})
|
}
|
}
|
|
// 表单验证规则
|
const rules = computed(() => {
|
const scoreRules = {}
|
if (props.ratingForm.items) {
|
props.ratingForm.items.forEach(item => {
|
scoreRules[`scores.${item.id}`] = [
|
{
|
required: true,
|
message: `请输入${item.name}的分数`,
|
trigger: 'blur'
|
},
|
{
|
type: 'number',
|
min: 0,
|
max: item.maxScore,
|
message: `分数应在0-${item.maxScore}之间`,
|
trigger: 'blur'
|
}
|
]
|
})
|
}
|
|
return scoreRules
|
})
|
|
// 计算总分
|
const totalScore = computed(() => {
|
let total = 0
|
Object.values(formData.scores).forEach(score => {
|
if (typeof score === 'number' && !isNaN(score)) {
|
total += score
|
}
|
})
|
return Math.round(total * 10) / 10 // 保留一位小数
|
})
|
|
// 提交评分
|
const handleSubmit = async () => {
|
try {
|
await formRef.value.validate()
|
|
submitting.value = true
|
|
const ratingData = {
|
activityPlayerId: props.activityPlayerId,
|
scores: formData.scores,
|
comment: formData.comment,
|
totalScore: totalScore.value
|
}
|
|
emit('submit', ratingData)
|
|
} catch (error) {
|
console.error('表单验证失败:', error)
|
ElMessage.error('请检查表单填写是否完整')
|
} finally {
|
submitting.value = false
|
}
|
}
|
|
// 重置表单
|
const handleReset = () => {
|
formRef.value.resetFields()
|
initScores()
|
}
|
|
// 监听评分表单变化,重新初始化
|
watch(() => props.ratingForm, () => {
|
initScores()
|
}, { immediate: true })
|
</script>
|
|
<style scoped>
|
.rating-form {
|
background: white;
|
border-radius: 8px;
|
padding: 20px;
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
}
|
|
.form-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
margin-bottom: 20px;
|
padding-bottom: 16px;
|
border-bottom: 1px solid #EBEEF5;
|
}
|
|
.form-header h3 {
|
margin: 0;
|
color: #303133;
|
font-size: 18px;
|
font-weight: 600;
|
}
|
|
.total-score {
|
font-size: 16px;
|
font-weight: 600;
|
color: #409EFF;
|
background: #ECF5FF;
|
padding: 8px 16px;
|
border-radius: 20px;
|
}
|
|
.rating-items {
|
margin-bottom: 20px;
|
}
|
|
.rating-item {
|
margin-bottom: 20px;
|
padding: 16px;
|
background: #FAFAFA;
|
border-radius: 8px;
|
border-left: 4px solid #409EFF;
|
}
|
|
.score-item :deep(.el-form-item__label) {
|
font-weight: 600;
|
color: #303133;
|
}
|
|
.score-input-group {
|
display: flex;
|
align-items: center;
|
gap: 8px;
|
}
|
|
.score-input {
|
width: 120px;
|
}
|
|
.max-score {
|
color: #909399;
|
font-size: 14px;
|
}
|
|
.item-description {
|
margin-top: 8px;
|
color: #606266;
|
font-size: 13px;
|
line-height: 1.4;
|
}
|
|
.comment-item {
|
margin-bottom: 30px;
|
}
|
|
.submit-item {
|
text-align: center;
|
margin-bottom: 0;
|
}
|
|
.submit-btn {
|
width: 120px;
|
margin-right: 16px;
|
}
|
|
.reset-btn {
|
width: 80px;
|
}
|
|
:deep(.el-form-item__label) {
|
font-weight: 500;
|
}
|
|
:deep(.el-textarea__inner) {
|
resize: vertical;
|
}
|
</style>
|