发布页开发

This commit is contained in:
筱野
2025-08-17 22:58:00 +08:00
parent 68a6558776
commit 2b3caf027b
76 changed files with 6173 additions and 1610 deletions

View 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'>14</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