fix: 新增考试批次
This commit is contained in:
parent
58c0a36f3e
commit
e78dc1963c
@ -4,7 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { http } from '@/utils/request'
|
import { http } from '@/utils/request'
|
||||||
import type { ScoreResult, ApiResponse } from '@/types'
|
import type { ScoreResult, ApiResponse, ExamBatch, PaginatedData } from '@/types'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 后端返回的原始数据结构接口
|
* 后端返回的原始数据结构接口
|
||||||
@ -19,27 +19,6 @@ interface RawScoreData {
|
|||||||
extraDataJson: string
|
extraDataJson: string
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 考试批次接口
|
|
||||||
*/
|
|
||||||
interface ExamBatch {
|
|
||||||
id: string
|
|
||||||
name: string
|
|
||||||
status: number
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 分页数据接口
|
|
||||||
*/
|
|
||||||
interface PaginatedData<T> {
|
|
||||||
current: number
|
|
||||||
size: number
|
|
||||||
totalPage: number
|
|
||||||
totalRows: number
|
|
||||||
rows: T[]
|
|
||||||
rainbow: number[]
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取考试批次列表
|
* 获取考试批次列表
|
||||||
* @param status - 状态过滤,0表示启用
|
* @param status - 状态过滤,0表示启用
|
||||||
|
|||||||
@ -96,3 +96,33 @@ export interface ErrorInfo {
|
|||||||
/** 错误消息 */
|
/** 错误消息 */
|
||||||
message: string
|
message: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 考试批次接口
|
||||||
|
*/
|
||||||
|
export interface ExamBatch {
|
||||||
|
/** 批次ID */
|
||||||
|
id: string
|
||||||
|
/** 批次名称 */
|
||||||
|
name: string
|
||||||
|
/** 状态:0-启用 */
|
||||||
|
status: number
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页数据接口
|
||||||
|
*/
|
||||||
|
export interface PaginatedData<T> {
|
||||||
|
/** 当前页 */
|
||||||
|
current: number
|
||||||
|
/** 每页大小 */
|
||||||
|
size: number
|
||||||
|
/** 总页数 */
|
||||||
|
totalPage: number
|
||||||
|
/** 总行数 */
|
||||||
|
totalRows: number
|
||||||
|
/** 数据列表 */
|
||||||
|
rows: T[]
|
||||||
|
/** 页码彩虹 */
|
||||||
|
rainbow: number[]
|
||||||
|
}
|
||||||
|
|||||||
@ -3,16 +3,25 @@
|
|||||||
* 首页组件
|
* 首页组件
|
||||||
* 成绩查询入口页面,包含身份证输入和查询功能
|
* 成绩查询入口页面,包含身份证输入和查询功能
|
||||||
*/
|
*/
|
||||||
import { ref, computed } from 'vue'
|
import { ref, computed, onMounted } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { queryScoreByIdCard, getExamBatchList } from '@/api/score'
|
import { queryScoreByIdCard, getExamBatchList } from '@/api/score'
|
||||||
import Toast from '@/components/common/Toast.vue'
|
import Toast from '@/components/common/Toast.vue'
|
||||||
import PuzzleCaptcha from '@/components/common/PuzzleCaptcha.vue'
|
import PuzzleCaptcha from '@/components/common/PuzzleCaptcha.vue'
|
||||||
|
import type { ExamBatch } from '@/types'
|
||||||
|
|
||||||
// 路由实例
|
// 路由实例
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
// 响应式状态
|
// 响应式状态
|
||||||
|
/** 考试批次列表 */
|
||||||
|
const examBatchList = ref<ExamBatch[]>([])
|
||||||
|
/** 选中的考试批次ID */
|
||||||
|
const selectedBatchId = ref('')
|
||||||
|
/** 是否正在加载批次列表 */
|
||||||
|
const isBatchLoading = ref(false)
|
||||||
|
/** 下拉框是否展开 */
|
||||||
|
const isDropdownOpen = ref(false)
|
||||||
/** 身份证号输入值 */
|
/** 身份证号输入值 */
|
||||||
const idCard = ref('')
|
const idCard = ref('')
|
||||||
/** 学生姓名输入值 */
|
/** 学生姓名输入值 */
|
||||||
@ -33,11 +42,75 @@ const toastType = ref<'info' | 'success' | 'warning' | 'error'>('error')
|
|||||||
/** 是否显示验证码 */
|
/** 是否显示验证码 */
|
||||||
const showCaptcha = ref(false)
|
const showCaptcha = ref(false)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取选中的批次名称
|
||||||
|
*/
|
||||||
|
const selectedBatchName = computed(() => {
|
||||||
|
const batch = examBatchList.value.find(b => b.id === selectedBatchId.value)
|
||||||
|
return batch?.name || '请选择考试批次'
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 页面加载时获取考试批次列表
|
||||||
|
*/
|
||||||
|
onMounted(async () => {
|
||||||
|
await loadExamBatchList()
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载考试批次列表
|
||||||
|
*/
|
||||||
|
const loadExamBatchList = async () => {
|
||||||
|
isBatchLoading.value = true
|
||||||
|
try {
|
||||||
|
const response = await getExamBatchList()
|
||||||
|
if (response.code === 200 && response.data?.rows) {
|
||||||
|
examBatchList.value = response.data.rows
|
||||||
|
// 默认选中第一个批次
|
||||||
|
if (response.data.rows.length > 0) {
|
||||||
|
selectedBatchId.value = response.data.rows[0].id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to load exam batch list:', error)
|
||||||
|
showMessage('加载考试批次失败', 'error')
|
||||||
|
} finally {
|
||||||
|
isBatchLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 选择考试批次
|
||||||
|
*/
|
||||||
|
const selectBatch = (batch: ExamBatch) => {
|
||||||
|
selectedBatchId.value = batch.id
|
||||||
|
isDropdownOpen.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切换下拉框展开状态
|
||||||
|
*/
|
||||||
|
const toggleDropdown = () => {
|
||||||
|
if (!isBatchLoading.value && examBatchList.value.length > 0) {
|
||||||
|
isDropdownOpen.value = !isDropdownOpen.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 点击外部关闭下拉框
|
||||||
|
*/
|
||||||
|
const closeDropdown = () => {
|
||||||
|
isDropdownOpen.value = false
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按钮是否可点击
|
* 按钮是否可点击
|
||||||
*/
|
*/
|
||||||
const isButtonDisabled = computed(() => {
|
const isButtonDisabled = computed(() => {
|
||||||
return isLoading.value || idCard.value.trim().length === 0 || studentName.value.trim().length === 0
|
return isLoading.value ||
|
||||||
|
idCard.value.trim().length === 0 ||
|
||||||
|
studentName.value.trim().length === 0 ||
|
||||||
|
!selectedBatchId.value
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -97,6 +170,13 @@ const showMessage = (message: string, type: 'info' | 'success' | 'warning' | 'er
|
|||||||
* 处理查询点击
|
* 处理查询点击
|
||||||
*/
|
*/
|
||||||
const handleQueryClick = () => {
|
const handleQueryClick = () => {
|
||||||
|
// 检查考试批次
|
||||||
|
if (!selectedBatchId.value) {
|
||||||
|
errorMessage.value = '请选择考试批次'
|
||||||
|
showMessage(errorMessage.value, 'warning')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 简单非空检查
|
// 简单非空检查
|
||||||
if (!studentName.value.trim()) {
|
if (!studentName.value.trim()) {
|
||||||
errorMessage.value = '请输入学生姓名'
|
errorMessage.value = '请输入学生姓名'
|
||||||
@ -123,20 +203,8 @@ const handleCaptchaSuccess = async () => {
|
|||||||
errorMessage.value = ''
|
errorMessage.value = ''
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 1. 先获取考试批次列表
|
// 使用选中的考试批次ID进行查询
|
||||||
const batchResponse = await getExamBatchList()
|
const response = await queryScoreByIdCard(idCard.value, studentName.value, selectedBatchId.value)
|
||||||
|
|
||||||
if (batchResponse.code !== 200 || !batchResponse.data || !batchResponse.data.rows || batchResponse.data.rows.length === 0) {
|
|
||||||
errorMessage.value = '暂无考试数据'
|
|
||||||
showMessage(errorMessage.value, 'warning')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 默认取第一个批次的ID
|
|
||||||
const examBatchId = batchResponse.data.rows[0].id
|
|
||||||
|
|
||||||
// 2. 调用查询接口
|
|
||||||
const response = await queryScoreByIdCard(idCard.value, studentName.value, examBatchId)
|
|
||||||
|
|
||||||
if (response.code === 200 && response.data) {
|
if (response.code === 200 && response.data) {
|
||||||
// 查询成功,存储数据并跳转
|
// 查询成功,存储数据并跳转
|
||||||
@ -202,6 +270,92 @@ const handleKeyPress = (event: KeyboardEvent) => {
|
|||||||
|
|
||||||
<!-- 查询表单卡片 -->
|
<!-- 查询表单卡片 -->
|
||||||
<div class="card">
|
<div class="card">
|
||||||
|
<!-- 考试批次选择 -->
|
||||||
|
<div class="mb-5">
|
||||||
|
<label class="block text-sm font-medium text-slate-700 mb-2">
|
||||||
|
考试批次
|
||||||
|
</label>
|
||||||
|
<div class="relative" @click.stop>
|
||||||
|
<!-- 下拉按钮 -->
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="input-field w-full flex items-center justify-between cursor-pointer"
|
||||||
|
:class="{ 'border-primary-400 ring-2 ring-primary-100': isDropdownOpen }"
|
||||||
|
@click="toggleDropdown"
|
||||||
|
>
|
||||||
|
<span :class="selectedBatchId ? 'text-slate-800' : 'text-slate-400'">
|
||||||
|
<template v-if="isBatchLoading">
|
||||||
|
<span class="flex items-center gap-2">
|
||||||
|
<svg class="w-4 h-4 animate-spin" fill="none" viewBox="0 0 24 24">
|
||||||
|
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" />
|
||||||
|
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" />
|
||||||
|
</svg>
|
||||||
|
加载中...
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="examBatchList.length === 0">
|
||||||
|
暂无考试批次
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
{{ selectedBatchName }}
|
||||||
|
</template>
|
||||||
|
</span>
|
||||||
|
<!-- 下拉箭头 -->
|
||||||
|
<svg
|
||||||
|
class="w-5 h-5 text-slate-400 transition-transform duration-200"
|
||||||
|
:class="{ 'rotate-180': isDropdownOpen }"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- 下拉列表 -->
|
||||||
|
<Transition name="dropdown">
|
||||||
|
<div
|
||||||
|
v-if="isDropdownOpen"
|
||||||
|
class="absolute z-20 mt-1 w-full bg-white border border-slate-200 rounded-xl shadow-lg overflow-hidden"
|
||||||
|
>
|
||||||
|
<div class="max-h-60 overflow-y-auto scrollbar-thin">
|
||||||
|
<button
|
||||||
|
v-for="batch in examBatchList"
|
||||||
|
:key="batch.id"
|
||||||
|
type="button"
|
||||||
|
class="w-full px-4 py-3 text-left text-sm transition-colors cursor-pointer
|
||||||
|
hover:bg-primary-50 active:bg-primary-100"
|
||||||
|
:class="batch.id === selectedBatchId
|
||||||
|
? 'bg-primary-50 text-primary-600 font-medium'
|
||||||
|
: 'text-slate-700'"
|
||||||
|
@click="selectBatch(batch)"
|
||||||
|
>
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<span class="line-clamp-2">{{ batch.name }}</span>
|
||||||
|
<!-- 选中标记 -->
|
||||||
|
<svg
|
||||||
|
v-if="batch.id === selectedBatchId"
|
||||||
|
class="w-5 h-5 text-primary-500 flex-shrink-0 ml-2"
|
||||||
|
fill="currentColor"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
>
|
||||||
|
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
|
|
||||||
|
<!-- 点击外部关闭遮罩 -->
|
||||||
|
<div
|
||||||
|
v-if="isDropdownOpen"
|
||||||
|
class="fixed inset-0 z-10"
|
||||||
|
@click="closeDropdown"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="mb-5">
|
<div class="mb-5">
|
||||||
<label class="block text-sm font-medium text-slate-700 mb-2">
|
<label class="block text-sm font-medium text-slate-700 mb-2">
|
||||||
学生姓名
|
学生姓名
|
||||||
@ -332,3 +486,48 @@ const handleKeyPress = (event: KeyboardEvent) => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* 下拉动画 */
|
||||||
|
.dropdown-enter-active,
|
||||||
|
.dropdown-leave-active {
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-enter-from,
|
||||||
|
.dropdown-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-8px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 多行文本截断 */
|
||||||
|
.line-clamp-2 {
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 自定义滚动条样式 */
|
||||||
|
.scrollbar-thin {
|
||||||
|
scrollbar-width: thin;
|
||||||
|
scrollbar-color: #cbd5e1 transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollbar-thin::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollbar-thin::-webkit-scrollbar-track {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollbar-thin::-webkit-scrollbar-thumb {
|
||||||
|
background-color: #cbd5e1;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollbar-thin::-webkit-scrollbar-thumb:hover {
|
||||||
|
background-color: #94a3b8;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user