feat(admin): 新增题库模块并优化比赛管理功能

新增题库模块,包含题目管理页面和Excel导入导出功能
优化比赛管理功能,包括分组管理、硬件绑定和题目配置
重构比赛添加流程,增加重置功能和数据校验
添加Excel工具函数,支持读取和导出Excel文件
更新依赖,添加xlsx库支持
This commit is contained in:
2026-01-21 16:29:38 +08:00
parent 3270e24c25
commit 89773bd49b
33 changed files with 1988 additions and 496 deletions

View File

@ -0,0 +1,107 @@
import type { UploadCustomRequestOptions } from 'naive-ui'
import { debounce } from '@sa/utils'
import { ref, watch } from 'vue'
export interface BasicInfoModel {
name: string
startTime: number | null
endTime: number | null
groupCount: number
teamCount: number
poster: string
}
export function useBasicInfo(props: any, emit: any) {
const formData = ref<BasicInfoModel>({ ...props.modelValue })
// 修复死循环:添加值对比逻辑
watch(() => props.modelValue, (val) => {
if (JSON.stringify(val) !== JSON.stringify(formData.value)) {
formData.value = { ...val }
}
}, { deep: true })
// 添加防抖300ms 延迟,避免频繁触发父组件更新
const handleUpdate = debounce((val: typeof formData.value) => {
emit('update:modelValue', { ...val })
}, 300)
watch(formData, (val) => {
handleUpdate(val)
}, { deep: true })
function updateCount(type: 'group' | 'team', delta: number) {
if (type === 'group') {
const newVal = (formData.value.groupCount || 0) + delta
if (newVal >= 1 && newVal <= 999) {
formData.value.groupCount = newVal
}
}
else {
const newVal = (formData.value.teamCount || 0) + delta
if (newVal >= 1 && newVal <= 999) {
formData.value.teamCount = newVal
}
}
}
// 模拟上传处理
function handleUpload({ file, onFinish }: UploadCustomRequestOptions) {
const reader = new FileReader()
reader.readAsDataURL(file.file as File)
reader.onload = () => {
// 模拟上传成功,直接使用 base64 作为图片地址
formData.value.poster = reader.result as string
onFinish()
}
}
// 校验方法
function validate() {
if (!formData.value.name) {
window.$message?.error('请输入比赛项目名称')
return false
}
if (!formData.value.startTime) {
window.$message?.error('请选择开始时间')
return false
}
if (!formData.value.endTime) {
window.$message?.error('请选择结束时间')
return false
}
if (formData.value.startTime >= formData.value.endTime) {
window.$message?.error('结束时间必须晚于开始时间')
return false
}
if (!formData.value.groupCount || formData.value.groupCount < 1) {
window.$message?.error('参赛小组数量必须为正整数')
return false
}
if (!formData.value.teamCount || formData.value.teamCount < 1) {
window.$message?.error('每组队伍数量必须为正整数')
return false
}
return true
}
// 重置方法
function reset() {
formData.value = {
name: '阅读之星年度总决赛',
startTime: null,
endTime: null,
groupCount: 10,
teamCount: 4,
poster: '',
}
}
return {
formData,
updateCount,
handleUpload,
validate,
reset,
}
}