173 lines
6.2 KiB
TypeScript
173 lines
6.2 KiB
TypeScript
import React, { useState } from 'react'
|
||
import { View, Text } from '@tarojs/components'
|
||
|
||
import Taro from '@tarojs/taro'
|
||
import { ImageUpload, Range, TimeSelector, TextareaTag, SelectStadium, NumberInterval, TitleInput, FormBasicInfo, FormSwitch } from '../../components'
|
||
import { type Stadium, type CoverImage } from '../../components/index.types'
|
||
import { FormFieldConfig, FieldType } from '../../config/formSchema/publishBallFormSchema'
|
||
import { PublishBallFormData } from '../../../types/publishBall';
|
||
|
||
import styles from './index.module.scss'
|
||
|
||
// 组件映射器
|
||
const componentMap = {
|
||
[FieldType.TEXT]: TitleInput,
|
||
[FieldType.TIMEINTERVAL]: TimeSelector,
|
||
[FieldType.RANGE]: Range,
|
||
[FieldType.TEXTAREATAG]: TextareaTag,
|
||
[FieldType.NUMBERINTERVAL]: NumberInterval,
|
||
[FieldType.UPLOADIMAGE]: ImageUpload,
|
||
[FieldType.ACTIVITYINFO]: FormBasicInfo,
|
||
[FieldType.CHECKBOX]: FormSwitch,
|
||
}
|
||
|
||
const PublishForm: React.FC<{
|
||
formData: PublishBallFormData,
|
||
onChange: (key: keyof PublishBallFormData, value: any, index?: number) => void,
|
||
optionsConfig: FormFieldConfig[] }> = ({ formData, onChange, optionsConfig }) => {
|
||
const [coverImages, setCoverImages] = useState<CoverImage[]>([])
|
||
const [showStadiumSelector, setShowStadiumSelector] = useState(false)
|
||
const [selectedStadium, setSelectedStadium] = useState<Stadium | null>(null)
|
||
|
||
// 处理封面图片变化
|
||
const handleCoverImagesChange = (images: CoverImage[]) => {
|
||
setCoverImages(images)
|
||
}
|
||
|
||
// 更新表单数据
|
||
const updateFormData = (key: keyof PublishBallFormData, value: any) => {
|
||
onChange(key, value)
|
||
}
|
||
|
||
|
||
|
||
// 处理场馆选择
|
||
const handleStadiumSelect = (stadium: Stadium | null) => {
|
||
setSelectedStadium(stadium)
|
||
if (stadium) {
|
||
updateFormData('location', stadium.name)
|
||
}
|
||
setShowStadiumSelector(false)
|
||
}
|
||
|
||
const renderSummary = (item: FormFieldConfig) => {
|
||
if (item.props?.showSummary) {
|
||
return <Text className={styles['section-summary']}>{item.props?.summary}</Text>
|
||
}
|
||
return null
|
||
}
|
||
|
||
|
||
|
||
// 提交表单
|
||
const handleSubmit = async () => {
|
||
// 基础验证
|
||
if (!formData.title.trim()) {
|
||
Taro.showToast({
|
||
title: '请输入活动标题',
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
|
||
if (coverImages.length === 0) {
|
||
Taro.showToast({
|
||
title: '请至少上传一张活动封面',
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
|
||
// TODO: 实现提交逻辑
|
||
console.log('提交数据:', { coverImages, formData })
|
||
|
||
Taro.showToast({
|
||
title: '发布成功',
|
||
icon: 'success'
|
||
})
|
||
}
|
||
|
||
return (
|
||
<View className={styles['publish-form']}>
|
||
<View className={styles['publish-ball__content']}>
|
||
{
|
||
optionsConfig.map((item) => {
|
||
const Component = componentMap[item.type]
|
||
const optionProps = {
|
||
...item.props,
|
||
...(item.key === 'additionalRequirements' ? { options: item.options } : {}),
|
||
...(item.props?.className ? { className: styles[item.props.className] } : {})
|
||
}
|
||
console.log(item.props?.className)
|
||
console.log(optionProps, item.label, formData[item.key]);
|
||
if (item.type === FieldType.UPLOADIMAGE) {
|
||
/* 活动封面 */
|
||
return <ImageUpload
|
||
images={coverImages}
|
||
onChange={handleCoverImagesChange}
|
||
{...item.props}
|
||
/>
|
||
}
|
||
if (item.type === FieldType.ACTIVITYINFO) {
|
||
return <>
|
||
<View className={styles['activity-description']}>
|
||
<Text className={styles['description-text']}>
|
||
活动开始前2小时未达到最低人数,活动自动取消;活动
|
||
结束后,报名者累计到达最低人数时,一旦到达期即有序。
|
||
</Text>
|
||
</View>
|
||
|
||
{/* 费用地点玩法区域 - 合并白色块 */}
|
||
<View className={styles['bg-section']}>
|
||
<FormBasicInfo
|
||
fee={formData.fee}
|
||
location={formData.location}
|
||
gameplay={formData.gameplay}
|
||
selectedStadium={selectedStadium}
|
||
children={item.children || []}
|
||
onFeeChange={(value) => updateFormData('fee', value)}
|
||
onLocationChange={(value) => updateFormData('location', value)}
|
||
onGameplayChange={(value) => updateFormData('gameplay', value)}
|
||
onStadiumSelect={() => setShowStadiumSelector(true)}
|
||
/>
|
||
</View>
|
||
</>
|
||
}
|
||
return (
|
||
<View className={styles['section-wrapper']}>
|
||
{
|
||
item.label && <View className={styles['section-title-wrapper']} >
|
||
<Text className={styles['section-title']}>{item.label}</Text>
|
||
{
|
||
item.props?.showSummary && <Text className={styles['section-summary']}>{renderSummary(item)}</Text>
|
||
}
|
||
</View>
|
||
}
|
||
<View className={styles['bg-section']}>
|
||
<Component
|
||
label={item.label}
|
||
value={formData[item.key]}
|
||
onChange={(value) => updateFormData(item.key as keyof PublishBallFormData, value)}
|
||
{...optionProps}
|
||
placeholder={item.placeholder}
|
||
/>
|
||
</View>
|
||
</View>
|
||
)
|
||
})
|
||
}
|
||
</View>
|
||
|
||
{/* 场馆选择弹窗 */}
|
||
<SelectStadium
|
||
visible={showStadiumSelector}
|
||
onClose={() => setShowStadiumSelector(false)}
|
||
onConfirm={handleStadiumSelect}
|
||
/>
|
||
|
||
</View>
|
||
)
|
||
}
|
||
|
||
export default PublishForm
|