import React, { useState, useEffect } from 'react' import { View, Text, Button, Image } from '@tarojs/components' import { Checkbox } from '@nutui/nutui-react-taro' import Taro from '@tarojs/taro' import { type ActivityType } from '../../components/ActivityTypeSwitch' import CommonDialog from '../../components/CommonDialog' import { withAuth } from '@/components' import PublishForm from './publishForm' import { FormFieldConfig, publishBallFormSchema } from '../../config/formSchema/publishBallFormSchema'; import { PublishBallFormData } from '../../../types/publishBall'; import PublishService from '@/services/publishService'; import { getNextHourTime, getEndTime, delay } from '@/utils'; import images from '@/config/images' import styles from './index.module.scss' import dayjs from 'dayjs' const defaultFormData: PublishBallFormData = { title: '', image_list: [], timeRange: { start_time: getNextHourTime(), end_time: getEndTime(getNextHourTime()) }, activityInfo: { play_type: '不限', price: '', venue_id: null, location_name: '', location: '', latitude: '', longitude: '', court_type: '', court_surface: '', venue_description_tag: [], venue_description: '', venue_image_list: [], }, players: [1, 1], skill_level: [1.0, 5.0], descriptionInfo: { description: '', description_tag: [], }, is_substitute_supported: true, is_wechat_contact: true, wechat_contact: '14223332214' } const PublishBall: React.FC = () => { const [activityType, setActivityType] = useState('individual') const [isSubmitDisabled, setIsSubmitDisabled] = useState(false) // 获取页面参数并设置导航标题 const [optionsConfig, setOptionsConfig] = useState(publishBallFormSchema) const [formData, setFormData] = useState([ defaultFormData ]) const [checked, setChecked] = useState(true) // 删除确认弹窗状态 const [deleteConfirm, setDeleteConfirm] = useState<{ visible: boolean; index: number; }>({ visible: false, index: -1 }) // 更新表单数据 const updateFormData = (key: keyof PublishBallFormData, value: any, index: number) => { console.log(key, value, index, 'key, value, index'); setFormData(prev => { const newData = [...prev] newData[index] = { ...newData[index], [key]: value } console.log(newData, 'newData'); return newData }) } // 处理活动类型变化 const handleActivityTypeChange = (type: ActivityType) => { if (type === 'group') { setFormData([defaultFormData]) } else { setFormData([defaultFormData]) } } // 检查相邻两组数据是否相同 const checkAdjacentDataSame = (formDataArray: PublishBallFormData[]) => { if (formDataArray.length < 2) return false const lastIndex = formDataArray.length - 1 const secondLastIndex = formDataArray.length - 2 const lastData = formDataArray[lastIndex] const secondLastData = formDataArray[secondLastIndex] // 比较关键字段是否相同 return (JSON.stringify(lastData) === JSON.stringify(secondLastData)) } const handleAdd = () => { // 检查最后两组数据是否相同 if (checkAdjacentDataSame(formData)) { Taro.showToast({ title: '信息不可与前序场完全一致', icon: 'none' }) return } const newStartTime = getNextHourTime() setFormData(prev => [...prev, { ...defaultFormData, title: '', timeRange: { start_time: newStartTime, end_time: getEndTime(newStartTime) } }]) } // 复制上一场数据 const handleCopyPrevious = (index: number) => { if (index > 0) { setFormData(prev => { const newData = [...prev] newData[index] = { ...newData[index - 1] } return newData }) Taro.showToast({ title: '复制上一场填入', icon: 'success' }) } } // 删除确认弹窗 const showDeleteConfirm = (index: number) => { setDeleteConfirm({ visible: true, index }) } // 关闭删除确认弹窗 const closeDeleteConfirm = () => { setDeleteConfirm({ visible: false, index: -1 }) } // 确认删除 const confirmDelete = () => { if (deleteConfirm.index >= 0) { setFormData(prev => prev.filter((_, index) => index !== deleteConfirm.index)) closeDeleteConfirm() Taro.showToast({ title: '已删除该场次', icon: 'success' }) } } const validateFormData = (formData: PublishBallFormData, isOnSubmit: boolean = false) => { const { activityInfo, image_list, title, timeRange } = formData; const { play_type, price, location_name } = activityInfo; if (!image_list?.length) { if (!isOnSubmit) { Taro.showToast({ title: `请上传活动封面`, icon: 'none' }) } return false } if (!title) { if (!isOnSubmit) { Taro.showToast({ title: `请输入活动标题`, icon: 'none' }) } return false } if (!price || (typeof price === 'number' && price <= 0) || (typeof price === 'string' && !price.trim())) { if (!isOnSubmit) { Taro.showToast({ title: `请输入费用`, icon: 'none' }) } return false } if (!play_type || !play_type.trim()) { if (!isOnSubmit) { Taro.showToast({ title: `请选择玩法类型`, icon: 'none' }) } return false } if (!location_name || !location_name.trim()) { if (!isOnSubmit) { Taro.showToast({ title: `请选择场地`, icon: 'none' }) } return false } // 时间范围校验:结束时间需晚于开始时间,且至少间隔30分钟(支持跨天) if (timeRange?.start_time && timeRange?.end_time) { const start = dayjs(timeRange.start_time) const end = dayjs(timeRange.end_time) if (!end.isAfter(start)) { if (!isOnSubmit) { Taro.showToast({ title: `结束时间需晚于开始时间`, icon: 'none' }) } return false } if (end.isBefore(start.add(30, 'minute'))) { if (!isOnSubmit) { Taro.showToast({ title: `时间间隔至少30分钟`, icon: 'none' }) } return false } } return true } const validateOnSubmit = () => { const isValid = activityType === 'individual' ? validateFormData(formData[0], true) : formData.every(item => validateFormData(item, true)) if (!isValid) { return false } return true } // 提交表单 const handleSubmit = async () => { // 基础验证 console.log(formData, 'formData'); if (activityType === 'individual') { const isValid = validateFormData(formData[0]) if (!isValid) { return } const { activityInfo, descriptionInfo, timeRange, players, skill_level,image_list, ...rest } = formData[0]; const options = { ...rest, ...activityInfo, ...descriptionInfo, ...timeRange, max_players: players[1], current_players: players[0], skill_level_min: skill_level[0], skill_level_max: skill_level[1], image_list: image_list.map(item => item.url) } const res = await PublishService.createPersonal(options); if (res.code === 0 && res.data) { Taro.showToast({ title: '发布成功', icon: 'success' }) delay(1000) // 如果是个人球局,则跳转到详情页,并自动分享 // 如果是畅打,则跳转第一个球局详情页,并自动分享 @刘杰 Taro.navigateTo({ // @ts-expect-error: id url: `/game_pages/detail/index?id=${res.data.id || 1}&from=publish&autoShare=1` }) } else { Taro.showToast({ title: res.message, icon: 'none' }) } } if (activityType === 'group') { const isValid = formData.every(item => validateFormData(item)) if (!isValid) { return } if (checkAdjacentDataSame(formData)) { Taro.showToast({ title: '信息不可与前序场完全一致', icon: 'none' }) return } const options = formData.map((item) => { const { activityInfo, descriptionInfo, timeRange, players, skill_level, ...rest } = item; return { ...rest, ...activityInfo, ...descriptionInfo, ...timeRange, max_players: players[1], current_players: players[0], skill_level_min: skill_level[0], skill_level_max: skill_level[1], image_list: item.image_list.map(img => img.url) } }) const res = await PublishService.create_play_pmoothlys({rows: options}); if (res.code === 0 && res.data) { Taro.showToast({ title: '发布成功', icon: 'success' }) delay(1000) // 如果是个人球局,则跳转到详情页,并自动分享 // 如果是畅打,则跳转第一个球局详情页,并自动分享 @刘杰 Taro.navigateTo({ // @ts-expect-error: id url: `/game_pages/detail/index?id=${res.data?.[0].id || 1}&from=publish&autoShare=1` }) } else { Taro.showToast({ title: res.message, icon: 'none' }) } } } const initFormData = () => { const currentInstance = Taro.getCurrentInstance() const params = currentInstance.router?.params if (params?.type) { const type = params.type as ActivityType if (type === 'individual' || type === 'group') { setActivityType(type) if (type === 'group') { const newFormSchema = publishBallFormSchema.reduce((acc, item) => { if (item.prop === 'is_wechat_contact') { return acc } if (item.prop === 'image_list') { if (item.props) { item.props.source = ['album', 'history'] } } if (item.prop === 'players') { if (item.props) { item.props.max = 100 } } acc.push(item) return acc }, [] as FormFieldConfig[]) setOptionsConfig(newFormSchema) setFormData([defaultFormData]) } // 根据type设置导航标题 if (type === 'group') { Taro.setNavigationBarTitle({ title: '发布畅打活动' }) } else { Taro.setNavigationBarTitle({ title: '发布' }) } } handleActivityTypeChange(type) } } const onCheckedChange = (checked: boolean) => { setChecked(checked) } useEffect(() => { const isValid = validateOnSubmit() if (!isValid) { setIsSubmitDisabled(true) } else { setIsSubmitDisabled(false) } console.log(formData, 'formData'); }, [formData]) useEffect(() => { initFormData() }, []) return ( {/* 活动类型切换 */} {/* */} { formData.map((item, index) => ( {/* 场次标题行 */} {activityType === 'group' && index > 0 && ( 第{index + 1}场 showDeleteConfirm(index)} > {index > 0 && ( handleCopyPrevious(index)} > 复制上一场 )} )} updateFormData(key, value, index)} optionsConfig={optionsConfig} /> )) } { activityType === 'group' && ( 再添加一场 ) } {/* 删除确认弹窗 */} {/* 完成按钮 */} { activityType === 'individual' && ( 点击确定发布约球,即表示已经同意条款 《约球规则》 ) } { activityType === 'group' && ( 已认证 徐汇爱打球官方球场,请严格遵守签约协议 ) } ) } export default withAuth(PublishBall)