feat(admin): 新增题库模块并优化比赛管理功能
新增题库模块,包含题目管理页面和Excel导入导出功能 优化比赛管理功能,包括分组管理、硬件绑定和题目配置 重构比赛添加流程,增加重置功能和数据校验 添加Excel工具函数,支持读取和导出Excel文件 更新依赖,添加xlsx库支持
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { debounce } from '@sa/utils'
|
||||
import { NButton, NDatePicker, NForm, NInput, NInputNumber, NUpload, type UploadCustomRequestOptions } from 'naive-ui'
|
||||
import { ref, useTemplateRef, watch } from 'vue'
|
||||
import { NButton, NDatePicker, NForm, NInput, NInputNumber, NUpload } from 'naive-ui'
|
||||
import { useTemplateRef } from 'vue'
|
||||
import { useBasicInfo } from './useBasicInfo'
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: {
|
||||
@ -18,80 +18,9 @@ const emit = defineEmits(['update:modelValue'])
|
||||
|
||||
const formRef = useTemplateRef('formRef')
|
||||
|
||||
const formData = ref({ ...props.modelValue })
|
||||
const { formData, updateCount, handleUpload, validate, reset } = useBasicInfo(props, emit)
|
||||
|
||||
// 修复死循环:添加值对比逻辑
|
||||
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
|
||||
}
|
||||
|
||||
defineExpose({ validate })
|
||||
defineExpose({ validate, reset })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
Reference in New Issue
Block a user