发布页开发
This commit is contained in:
198
src/pages/publishBall/publishForm.tsx
Normal file
198
src/pages/publishBall/publishForm.tsx
Normal file
@@ -0,0 +1,198 @@
|
||||
import React, { useState } from 'react'
|
||||
import { View, Text } from '@tarojs/components'
|
||||
|
||||
import Taro from '@tarojs/taro'
|
||||
import { CoverImageUpload, NTRPSlider, TimeSelector, TextareaTag, SelectStadium, ParticipantsControl, TitleInput, FormBasicInfo, AutoDegradeSwitch } from '../../components'
|
||||
import { type NTRPRange, type TimeRange, type Stadium, type ActivityType, type CoverImage } from '../../components/index.types'
|
||||
import { FormFieldConfig, FieldType } from '../../config/formSchema/publishBallFormSchema'
|
||||
import './index.scss'
|
||||
|
||||
interface FormData {
|
||||
activityType: ActivityType
|
||||
title: string
|
||||
timeRange: TimeRange
|
||||
fee: string
|
||||
location: string
|
||||
gameplay: string
|
||||
minParticipants: number
|
||||
maxParticipants: number
|
||||
ntpLevel: NTRPRange
|
||||
TextareaTag: string
|
||||
autoDegrade: boolean
|
||||
}
|
||||
|
||||
// 组件映射器
|
||||
const componentMap = {
|
||||
[FieldType.TEXT]: TitleInput,
|
||||
[FieldType.TIMEINTERVAL]: TimeSelector,
|
||||
[FieldType.RANGE]: NTRPSlider,
|
||||
[FieldType.TEXTAREATAG]: TextareaTag,
|
||||
[FieldType.NUMBERINTERVAL]: ParticipantsControl,
|
||||
[FieldType.UPLOADIMAGE]: CoverImageUpload,
|
||||
[FieldType.ACTIVITYINFO]: FormBasicInfo,
|
||||
[FieldType.CHECKBOX]: AutoDegradeSwitch,
|
||||
}
|
||||
|
||||
const PublishForm: React.FC<{
|
||||
formData: FormData,
|
||||
onChange: (key: keyof FormData, value: any) => 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 FormData, value: any) => {
|
||||
onChange(key, value)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 获取人数要求显示文本
|
||||
const getParticipantsText = () => {
|
||||
return `最少${formData.minParticipants}人,最多${formData.maxParticipants}人`
|
||||
}
|
||||
|
||||
// 处理NTRP范围变化
|
||||
const handleNTRPChange = (range: NTRPRange) => {
|
||||
updateFormData('ntpLevel', range)
|
||||
}
|
||||
|
||||
// 处理时间范围变化
|
||||
const handleTimeRangeChange = (timeRange: TimeRange) => {
|
||||
updateFormData('timeRange', timeRange)
|
||||
}
|
||||
|
||||
// 处理补充要求变化
|
||||
const handleAdditionalRequirementsChange = (value: string) => {
|
||||
updateFormData('additionalRequirements', value)
|
||||
}
|
||||
|
||||
// 处理场馆选择
|
||||
const handleStadiumSelect = (stadium: Stadium | null) => {
|
||||
setSelectedStadium(stadium)
|
||||
if (stadium) {
|
||||
updateFormData('location', stadium.name)
|
||||
}
|
||||
setShowStadiumSelector(false)
|
||||
}
|
||||
|
||||
// 处理活动类型变化
|
||||
const handleActivityTypeChange = (type: ActivityType) => {
|
||||
updateFormData('activityType', type)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// 提交表单
|
||||
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='publish-form'>
|
||||
<View className='publish-ball__content'>
|
||||
{
|
||||
optionsConfig.map((item) => {
|
||||
const Component = componentMap[item.type]
|
||||
const optionProps = {
|
||||
...item.props,
|
||||
...(item.key === 'additionalRequirements' ? { options: item.options } : {})
|
||||
}
|
||||
console.log(optionProps, item.label);
|
||||
if (item.type === FieldType.UPLOADIMAGE) {
|
||||
/* 活动封面 */
|
||||
return <CoverImageUpload
|
||||
images={coverImages}
|
||||
onChange={handleCoverImagesChange}
|
||||
{...item.props}
|
||||
/>
|
||||
}
|
||||
if (item.type === FieldType.ACTIVITYINFO) {
|
||||
return <>
|
||||
<View className='activity-description'>
|
||||
<Text className='description-text'>
|
||||
活动开始前2小时未达到最低人数,活动自动取消;活动
|
||||
结束后,报名者累计到达最低人数时,一旦到达期即有序。
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{/* 费用地点玩法区域 - 合并白色块 */}
|
||||
<View className='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='section-wrapper'>
|
||||
{
|
||||
item.label && <View className='section-title-wrapper' >
|
||||
<Text className='section-title'>{item.label}</Text>
|
||||
<Text className='section-summary'>最少1人,最多4人</Text>
|
||||
</View>
|
||||
}
|
||||
<View className='bg-section'>
|
||||
<Component
|
||||
value={formData[item.key]}
|
||||
onChange={(value) => updateFormData(item.key as keyof FormData, value)}
|
||||
{...optionProps}
|
||||
placeholder={item.placeholder}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
})
|
||||
}
|
||||
</View>
|
||||
|
||||
{/* 场馆选择弹窗 */}
|
||||
<SelectStadium
|
||||
visible={showStadiumSelector}
|
||||
onClose={() => setShowStadiumSelector(false)}
|
||||
onConfirm={handleStadiumSelect}
|
||||
/>
|
||||
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default PublishForm
|
||||
Reference in New Issue
Block a user