316 lines
11 KiB
Vue
316 lines
11 KiB
Vue
<template>
|
|
<div class="p-6 max-w-4xl mx-auto">
|
|
<h1 class="text-2xl font-bold mb-6">高校专业志愿填报</h1>
|
|
|
|
<div class="space-y-6">
|
|
<!-- 基本信息 -->
|
|
<div class="bg-white p-6 rounded-lg shadow">
|
|
<h2 class="text-xl font-semibold mb-4">基本信息</h2>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">省份 *</label>
|
|
<select
|
|
v-model="formData.province"
|
|
class="w-full border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
required
|
|
>
|
|
<option value="">请选择省份</option>
|
|
<option
|
|
v-for="item in dictStore.getDictItems('provinces')"
|
|
:key="item.value"
|
|
:value="item.value"
|
|
>
|
|
{{ item.label }}
|
|
</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">学历层次 *</label>
|
|
<select
|
|
v-model="formData.educationalLevel"
|
|
class="w-full border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
required
|
|
>
|
|
<option value="">请选择学历层次</option>
|
|
<option
|
|
v-for="item in dictStore.getDictItems('educationalLevel')"
|
|
:key="item.value"
|
|
:value="item.value"
|
|
>
|
|
{{ item.label }}
|
|
</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 专业选择 -->
|
|
<div class="bg-white p-6 rounded-lg shadow">
|
|
<h2 class="text-xl font-semibold mb-4">专业选择</h2>
|
|
|
|
<div class="space-y-4">
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">专业类别 *</label>
|
|
<select
|
|
v-model="formData.professionalCategory"
|
|
class="w-full border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
required
|
|
>
|
|
<option value="">请选择专业类别</option>
|
|
<option
|
|
v-for="item in dictStore.getDictItems('professionalCategory')"
|
|
:key="item.value"
|
|
:value="item.value"
|
|
>
|
|
{{ item.label }}
|
|
</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">选考科目 (最多3门) *</label>
|
|
<div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-2">
|
|
<label
|
|
v-for="item in dictStore.getDictItems('subjectList')"
|
|
:key="item.value"
|
|
class="flex items-center space-x-2 p-2 border rounded cursor-pointer hover:bg-gray-50"
|
|
:class="{ 'bg-blue-50 border-blue-300': formData.subjectList.includes(item.value) }"
|
|
>
|
|
<input
|
|
type="checkbox"
|
|
:value="item.value"
|
|
v-model="formData.subjectList"
|
|
:disabled="formData.subjectList.length >= 3 && !formData.subjectList.includes(item.value)"
|
|
class="h-4 w-4 text-blue-600 rounded focus:ring-blue-500"
|
|
/>
|
|
<span>{{ item.label }}</span>
|
|
</label>
|
|
</div>
|
|
<div class="text-sm text-gray-500 mt-1">
|
|
已选择 {{ formData.subjectList.length }}/3 门科目
|
|
<span v-if="formData.subjectList.length >= 3" class="text-red-500">已达到上限</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 成绩信息 -->
|
|
<div class="bg-white p-6 rounded-lg shadow">
|
|
<h2 class="text-xl font-semibold mb-4">成绩信息</h2>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">专业成绩</label>
|
|
<input
|
|
v-model.number="formData.professionalScore"
|
|
type="number"
|
|
step="0.01"
|
|
min="0"
|
|
max="300"
|
|
class="w-full border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
placeholder="请输入专业成绩 (0-300)"
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">文化成绩</label>
|
|
<input
|
|
v-model.number="formData.culturalScore"
|
|
type="number"
|
|
step="0.01"
|
|
min="0"
|
|
max="750"
|
|
class="w-full border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
placeholder="请输入文化成绩 (0-750)"
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">语文成绩</label>
|
|
<input
|
|
v-model.number="formData.chineseScore"
|
|
type="number"
|
|
step="0.01"
|
|
min="0"
|
|
max="150"
|
|
class="w-full border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
placeholder="请输入语文成绩 (0-150)"
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-1">英语成绩</label>
|
|
<input
|
|
v-model.number="formData.englishScore"
|
|
type="number"
|
|
step="0.01"
|
|
min="0"
|
|
max="150"
|
|
class="w-full border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
placeholder="请输入英语成绩 (0-150)"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 操作按钮 -->
|
|
<div class="flex justify-end space-x-4 pt-4">
|
|
<button
|
|
type="button"
|
|
@click="resetForm"
|
|
class="px-6 py-2 border border-gray-300 rounded-md text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
|
|
>
|
|
重置
|
|
</button>
|
|
<button
|
|
type="submit"
|
|
@click="submitForm"
|
|
class="px-6 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
|
|
:disabled="!isFormValid"
|
|
>
|
|
{{ isSubmitting ? '提交中...' : '提交' }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 表单验证错误提示 -->
|
|
<div v-if="errors.length > 0" class="mt-4 p-4 bg-red-50 border border-red-200 rounded-md">
|
|
<h3 class="text-red-800 font-medium mb-2">请修正以下错误:</h3>
|
|
<ul class="list-disc list-inside text-red-700 space-y-1">
|
|
<li v-for="(error, index) in errors" :key="index">{{ error }}</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, reactive, computed, onMounted } from 'vue'
|
|
import { useDictStore } from '~/stores/dict'
|
|
import { useScoreStore } from '~/stores/score'
|
|
import { SaveScoreRequest } from '~/service/api/score'
|
|
import message from '~/utils/message'
|
|
|
|
// 使用字典Store和成绩Store
|
|
const dictStore = useDictStore()
|
|
const scoreStore = useScoreStore()
|
|
|
|
// 表单数据
|
|
const formData = reactive<SaveScoreRequest>({
|
|
cognitioPolyclinic: '',
|
|
subjectList: [],
|
|
professionalCategory: '',
|
|
professionalCategoryChildren: [],
|
|
professionalCategoryChildrenScore: {},
|
|
professionalScore: 0,
|
|
culturalScore: 0,
|
|
englishScore: 0,
|
|
chineseScore: 0,
|
|
province: '',
|
|
})
|
|
|
|
// 状态
|
|
const isSubmitting = ref(false)
|
|
|
|
// 错误信息
|
|
const errors = ref<string[]>([])
|
|
|
|
// 计算属性
|
|
const isFormValid = computed(() => {
|
|
return formData.province &&
|
|
formData.professionalCategory &&
|
|
formData.subjectList.length > 0
|
|
})
|
|
|
|
// 提交表单
|
|
const submitForm = async () => {
|
|
errors.value = []
|
|
|
|
// 基本验证
|
|
if (!formData.province) {
|
|
errors.value.push('请选择省份')
|
|
}
|
|
if (!formData.professionalCategory) {
|
|
errors.value.push('请选择专业类别')
|
|
}
|
|
if (formData.subjectList.length === 0) {
|
|
errors.value.push('请至少选择一门选考科目')
|
|
}
|
|
|
|
if (errors.value.length > 0) {
|
|
return
|
|
}
|
|
|
|
isSubmitting.value = true
|
|
try {
|
|
// 更新认知门诊字段 - 根据省份和专业类别推断
|
|
formData.cognitioPolyclinic = formData.province.includes('beijing') || formData.province.includes('shanghai')
|
|
? '综合改革'
|
|
: formData.subjectList.includes('physics') || formData.subjectList.includes('chemistry')
|
|
? '理科'
|
|
: '文科'
|
|
|
|
// 保存数据
|
|
await scoreStore.saveScore(formData)
|
|
message.success('志愿信息保存成功!', 2000)
|
|
|
|
// 可以在这里添加导航到其他页面的逻辑
|
|
} catch (error) {
|
|
console.error('提交失败:', error)
|
|
message.error('提交失败,请检查网络连接或稍后重试', 3000)
|
|
} finally {
|
|
isSubmitting.value = false
|
|
}
|
|
}
|
|
|
|
// 重置表单
|
|
const resetForm = () => {
|
|
formData.cognitioPolyclinic = ''
|
|
formData.subjectList = []
|
|
formData.professionalCategory = ''
|
|
formData.professionalCategoryChildren = []
|
|
formData.professionalCategoryChildrenScore = {}
|
|
formData.professionalScore = 0
|
|
formData.culturalScore = 0
|
|
formData.englishScore = 0
|
|
formData.chineseScore = 0
|
|
formData.province = ''
|
|
errors.value = []
|
|
}
|
|
|
|
// 页面加载时初始化
|
|
onMounted(async () => {
|
|
// 尝试加载字典数据
|
|
if (Object.keys(dictStore.allDicts).length === 0) {
|
|
try {
|
|
await dictStore.loadDynamicDicts()
|
|
} catch (error) {
|
|
console.warn('加载字典数据失败,使用默认值:', error)
|
|
}
|
|
}
|
|
|
|
// 尝试加载已保存的成绩数据
|
|
try {
|
|
const scoreInfo = await scoreStore.fetchScore()
|
|
if (scoreInfo) {
|
|
// 使用解构赋值更新表单数据
|
|
Object.assign(formData, {
|
|
cognitioPolyclinic: scoreInfo.cognitioPolyclinic || '',
|
|
subjectList: scoreInfo.subjectList || [],
|
|
professionalCategory: scoreInfo.professionalCategory || '',
|
|
professionalCategoryChildren: scoreInfo.professionalCategoryChildren || [],
|
|
professionalCategoryChildrenScore: scoreInfo.professionalCategoryChildrenScore || {},
|
|
professionalScore: scoreInfo.professionalScore || 0,
|
|
culturalScore: scoreInfo.culturalScore || 0,
|
|
englishScore: scoreInfo.englishScore || 0,
|
|
chineseScore: scoreInfo.chineseScore || 0,
|
|
province: scoreInfo.province || '',
|
|
})
|
|
}
|
|
} catch (error) {
|
|
console.warn('加载成绩数据失败:', error)
|
|
// 忽略错误,用户可能没有保存过数据
|
|
}
|
|
})
|
|
</script> |