<template>
|
<div class="rating-form">
|
<el-card>
|
<template #header>
|
<div class="card-header">
|
<span>{{ isEdit ? '编辑评分模板' : '新增评分模板' }}</span>
|
<el-button @click="goBack">返回</el-button>
|
</div>
|
</template>
|
|
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px" @submit.prevent v-loading="loading">
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="模板名称" prop="name">
|
<el-input v-model="form.name" placeholder="请输入模板名称" maxlength="30" />
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="模板总分">
|
<span>{{ totalScore }}</span>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
|
<el-form-item label="模板描述">
|
<el-input v-model="form.description" type="textarea" :rows="3" placeholder="请输入模板描述" />
|
</el-form-item>
|
|
<el-divider content-position="left">评分条目</el-divider>
|
<div class="items-toolbar">
|
<el-button type="primary" size="small" @click="openItemDialog()">新增条目</el-button>
|
</div>
|
<el-table :data="form.items" style="width: 100%" border>
|
<el-table-column prop="name" label="条目名称" min-width="200" />
|
<el-table-column prop="maxScore" label="分值" width="120" align="center" />
|
<el-table-column prop="orderNo" label="排序号" width="120" align="center" />
|
<el-table-column label="操作" width="180" align="center">
|
<template #default="{ row, $index }">
|
<el-button size="small" @click="openItemDialog(row, $index)">编辑</el-button>
|
<el-button size="small" type="danger" @click="removeItem($index)">删除</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
<el-empty v-if="!form.items || form.items.length === 0" description="暂无评分条目" />
|
|
<el-form-item style="margin-top: 16px;">
|
<el-button type="primary" @click="handleSubmit" :loading="submitting" :disabled="submitting">
|
{{ isEdit ? '更新' : '创建' }}
|
</el-button>
|
<el-button @click="goBack">取消</el-button>
|
</el-form-item>
|
</el-form>
|
</el-card>
|
|
<!-- 条目编辑弹窗 -->
|
<el-dialog v-model="itemDialogVisible" :title="currentItemIndex === -1 ? '新增条目' : '编辑条目'" width="500px">
|
<el-form ref="itemFormRef" :model="currentItem" :rules="itemRules" label-width="120px">
|
<el-form-item label="条目名称" prop="name">
|
<el-input v-model="currentItem.name" placeholder="请输入条目名称" maxlength="30" />
|
</el-form-item>
|
<el-form-item label="分值" prop="maxScore">
|
<el-input-number v-model="currentItem.maxScore" :min="1" :max="1000" />
|
</el-form-item>
|
<el-form-item label="排序号" prop="orderNo">
|
<el-input-number v-model="currentItem.orderNo" :min="1" :max="9999" />
|
</el-form-item>
|
</el-form>
|
<template #footer>
|
<span class="dialog-footer">
|
<el-button @click="itemDialogVisible = false">取消</el-button>
|
<el-button type="primary" @click="saveItem">确定</el-button>
|
</span>
|
</template>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script setup lang="js">
|
import { ref, computed, onMounted } from 'vue'
|
import { useRoute, useRouter } from 'vue-router'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { getRatingScheme, saveRatingScheme } from '@/api/rating.js'
|
|
const route = useRoute()
|
const router = useRouter()
|
|
const loading = ref(false)
|
const submitting = ref(false)
|
const formRef = ref()
|
|
const isEdit = computed(() => !!route.params.id)
|
|
const form = ref({
|
id: null,
|
name: '',
|
description: '',
|
totalScore: 100,
|
items: []
|
})
|
|
// 总分 = 条目分值汇总(只读展示)
|
const totalScore = computed(() => {
|
try {
|
return (form.value.items || []).reduce((sum, it) => {
|
const n = Number(it?.maxScore) || 0
|
return sum + n
|
}, 0)
|
} catch {
|
return 0
|
}
|
})
|
|
const rules = {
|
name: [
|
{ required: true, message: '请输入模板名称', trigger: 'blur' },
|
{ max: 30, message: '模板名称不能超过30个字符', trigger: 'blur' }
|
],
|
// totalScore 由条目汇总得出,不再进行手动录入与校验
|
}
|
|
// 条目弹窗
|
const itemDialogVisible = ref(false)
|
const itemFormRef = ref()
|
const currentItemIndex = ref(-1)
|
const currentItem = ref({
|
id: null,
|
name: '',
|
maxScore: 10,
|
orderNo: 1
|
})
|
|
const itemRules = {
|
name: [{ required: true, message: '请输入条目名称', trigger: 'blur' }],
|
maxScore: [{ required: true, message: '请输入分值', trigger: 'change' }],
|
orderNo: [{ required: true, message: '请输入排序号', trigger: 'change' }]
|
}
|
|
const openItemDialog = (row = null, index = -1) => {
|
currentItemIndex.value = index
|
if (row) {
|
currentItem.value = { id: row.id || null, name: row.name || '', maxScore: row.maxScore || 10, orderNo: row.orderNo || 1 }
|
if (itemFormRef.value) itemFormRef.value.clearValidate()
|
} else {
|
currentItem.value = { id: null, name: '', maxScore: 10, orderNo: 1 }
|
if (itemFormRef.value) itemFormRef.value.clearValidate()
|
}
|
itemDialogVisible.value = true
|
}
|
|
const saveItem = async () => {
|
try {
|
await itemFormRef.value.validate()
|
const item = { ...currentItem.value }
|
if (currentItemIndex.value === -1) {
|
form.value.items.push(item)
|
} else {
|
form.value.items[currentItemIndex.value] = item
|
}
|
itemDialogVisible.value = false
|
ElMessage.success(currentItemIndex.value === -1 ? '添加成功' : '更新成功')
|
} catch (e) {
|
// 验证失败
|
}
|
}
|
|
const removeItem = async (index) => {
|
try {
|
await ElMessageBox.confirm('确定要删除该条目吗?', '提示', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning'
|
})
|
form.value.items.splice(index, 1)
|
ElMessage.success('删除成功')
|
} catch {
|
// 取消
|
}
|
}
|
|
const loadData = async () => {
|
if (!isEdit.value) return
|
try {
|
loading.value = true
|
const data = await getRatingScheme(parseInt(route.params.id))
|
if (data) {
|
form.value.id = data.id
|
form.value.name = data.name || ''
|
form.value.description = data.description || ''
|
form.value.totalScore = data.totalScore || 100
|
form.value.items = Array.isArray(data.items) ? data.items.map(i => ({
|
id: i.id || null,
|
name: i.name || '',
|
maxScore: i.maxScore || 0,
|
orderNo: i.orderNo || 1
|
})) : []
|
}
|
} catch (e) {
|
ElMessage.error(e?.message || '加载模板失败')
|
} finally {
|
loading.value = false
|
}
|
}
|
|
const handleSubmit = async () => {
|
if (submitting.value) return
|
try {
|
await formRef.value.validate()
|
submitting.value = true
|
const input = {
|
id: form.value.id,
|
name: form.value.name,
|
description: form.value.description,
|
items: form.value.items.map(i => ({
|
id: i.id || null,
|
name: i.name,
|
maxScore: i.maxScore,
|
orderNo: i.orderNo
|
}))
|
}
|
const result = await saveRatingScheme(input)
|
if (!isEdit.value && result?.id) {
|
form.value.id = result.id
|
}
|
ElMessage.success(isEdit.value ? '更新成功' : '创建成功')
|
goBack()
|
} catch (e) {
|
ElMessage.error(e?.message || '保存失败')
|
} finally {
|
submitting.value = false
|
}
|
}
|
|
const goBack = () => {
|
router.push('/rating-scheme')
|
}
|
|
onMounted(() => {
|
loadData()
|
})
|
</script>
|
|
<style scoped>
|
.rating-form { padding: 20px; }
|
.card-header { display: flex; justify-content: space-between; align-items: center; }
|
.items-toolbar { margin-bottom: 10px; }
|
</style>
|