108 lines
2.8 KiB
TypeScript
108 lines
2.8 KiB
TypeScript
|
|
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,
|
|||
|
|
}
|
|||
|
|
}
|