修改bug

This commit is contained in:
筱野
2025-09-13 10:55:06 +08:00
parent aef84e76cb
commit 52bee95505
9 changed files with 317 additions and 349 deletions

View File

@@ -1,65 +1,60 @@
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";
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: "",
title: '',
image_list: [],
timeRange: {
start_time: getNextHourTime(),
end_time: getEndTime(getNextHourTime()),
end_time: getEndTime(getNextHourTime())
},
activityInfo: {
play_type: "不限",
price: "",
play_type: '不限',
price: '',
venue_id: null,
location_name: "",
location: "",
latitude: "",
longitude: "",
court_type: "",
court_surface: "",
location_name: '',
location: '',
latitude: '',
longitude: '',
court_type: '',
court_surface: '',
venue_description_tag: [],
venue_description: "",
venue_description: '',
venue_image_list: [],
},
players: [1, 1],
skill_level: [1.0, 5.0],
descriptionInfo: {
description: "",
description: '',
description_tag: [],
},
is_substitute_supported: true,
is_wechat_contact: true,
wechat_contact: "14223332214",
};
wechat_contact: '14223332214'
}
const PublishBall: React.FC = () => {
const [activityType, setActivityType] = useState<ActivityType>("individual");
const [isSubmitDisabled, setIsSubmitDisabled] = useState(false);
const [activityType, setActivityType] = useState<ActivityType>('individual')
const [isSubmitDisabled, setIsSubmitDisabled] = useState(false)
// 获取页面参数并设置导航标题
const [optionsConfig, setOptionsConfig] = useState<FormFieldConfig[]>(
publishBallFormSchema,
);
const [optionsConfig, setOptionsConfig] = useState<FormFieldConfig[]>(publishBallFormSchema)
const [formData, setFormData] = useState<PublishBallFormData[]>([
defaultFormData,
]);
const [checked, setChecked] = useState(true);
defaultFormData
])
const [checked, setChecked] = useState(true)
// 删除确认弹窗状态
const [deleteConfirm, setDeleteConfirm] = useState<{
@@ -67,225 +62,200 @@ const PublishBall: React.FC = () => {
index: number;
}>({
visible: false,
index: -1,
});
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 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]);
if (type === 'group') {
setFormData([defaultFormData])
} else {
setFormData([defaultFormData]);
setFormData([defaultFormData])
}
};
}
// 检查相邻两组数据是否相同
const checkAdjacentDataSame = (formDataArray: PublishBallFormData[]) => {
if (formDataArray.length < 2) return false;
if (formDataArray.length < 2) return false
const lastIndex = formDataArray.length - 1;
const secondLastIndex = formDataArray.length - 2;
const lastIndex = formDataArray.length - 1
const secondLastIndex = formDataArray.length - 2
const lastData = formDataArray[lastIndex];
const secondLastData = formDataArray[secondLastIndex];
const lastData = formDataArray[lastIndex]
const secondLastData = formDataArray[secondLastIndex]
// 比较关键字段是否相同
return JSON.stringify(lastData) === JSON.stringify(secondLastData);
};
return (JSON.stringify(lastData) === JSON.stringify(secondLastData))
}
const handleAdd = () => {
// 检查最后两组数据是否相同
if (checkAdjacentDataSame(formData)) {
Taro.showToast({
title: "信息不可与前序场完全一致",
icon: "none",
});
return;
title: '信息不可与前序场完全一致',
icon: 'none'
})
return
}
const newStartTime = getNextHourTime();
setFormData((prev) => [
...prev,
{
...defaultFormData,
title: "",
timeRange: {
start_time: newStartTime,
end_time: getEndTime(newStartTime),
},
},
]);
};
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;
});
setFormData(prev => {
const newData = [...prev]
newData[index] = { ...newData[index - 1] }
return newData
})
Taro.showToast({
title: "复制上一场填入",
icon: "success",
});
title: '复制上一场填入',
icon: 'success'
})
}
};
}
// 删除确认弹窗
const showDeleteConfirm = (index: number) => {
setDeleteConfirm({
visible: true,
index,
});
};
index
})
}
// 关闭删除确认弹窗
const closeDeleteConfirm = () => {
setDeleteConfirm({
visible: false,
index: -1,
});
};
index: -1
})
}
// 确认删除
const confirmDelete = () => {
if (deleteConfirm.index >= 0) {
setFormData((prev) =>
prev.filter((_, index) => index !== deleteConfirm.index),
);
closeDeleteConfirm();
setFormData(prev => prev.filter((_, index) => index !== deleteConfirm.index))
closeDeleteConfirm()
Taro.showToast({
title: "已删除该场次",
icon: "success",
});
title: '已删除该场次',
icon: 'success'
})
}
};
}
const validateFormData = (
formData: PublishBallFormData,
isOnSubmit: boolean = false,
) => {
const validateFormData = (formData: PublishBallFormData, isOnSubmit: boolean = false) => {
const { activityInfo, image_list, title, timeRange } = formData;
const { play_type, price, location_name } = activityInfo;
const { play_type, price, location_name } = activityInfo;
if (!image_list?.length) {
if (!isOnSubmit) {
Taro.showToast({
title: `请上传活动封面`,
icon: "none",
});
icon: 'none'
})
}
return false;
return false
}
if (!title) {
if (!isOnSubmit) {
Taro.showToast({
title: `请输入活动标题`,
icon: "none",
});
icon: 'none'
})
}
return false;
return false
}
if (
!price ||
(typeof price === "number" && price <= 0) ||
(typeof price === "string" && !price.trim())
) {
if (!price || (typeof price === 'number' && price <= 0) || (typeof price === 'string' && !price.trim())) {
if (!isOnSubmit) {
Taro.showToast({
title: `请输入费用`,
icon: "none",
});
icon: 'none'
})
}
return false;
return false
}
if (!play_type || !play_type.trim()) {
if (!isOnSubmit) {
Taro.showToast({
title: `请选择玩法类型`,
icon: "none",
});
icon: 'none'
})
}
return false;
return false
}
if (!location_name || !location_name.trim()) {
if (!isOnSubmit) {
Taro.showToast({
title: `请选择场地`,
icon: "none",
});
icon: 'none'
})
}
return false;
return false
}
// 时间范围校验结束时间需晚于开始时间且至少间隔30分钟支持跨天
if (timeRange?.start_time && timeRange?.end_time) {
const start = dayjs(timeRange.start_time);
const end = dayjs(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",
});
icon: 'none'
})
}
return false;
return false
}
if (end.isBefore(start.add(30, "minute"))) {
if (end.isBefore(start.add(30, 'minute'))) {
if (!isOnSubmit) {
Taro.showToast({
title: `时间间隔至少30分钟`,
icon: "none",
});
icon: 'none'
})
}
return false;
return false
}
}
return true;
};
return true
}
const validateOnSubmit = () => {
const isValid =
activityType === "individual"
? validateFormData(formData[0], true)
: formData.every((item) => validateFormData(item, true));
const isValid = activityType === 'individual' ? validateFormData(formData[0], true) : formData.every(item => validateFormData(item, true))
if (!isValid) {
return false;
return false
}
return true;
};
return true
}
// 提交表单
const handleSubmit = async () => {
// 基础验证
console.log(formData, "formData");
if (activityType === "individual") {
const isValid = validateFormData(formData[0]);
console.log(formData, 'formData');
if (activityType === 'individual') {
const isValid = validateFormData(formData[0])
if (!isValid) {
return;
return
}
const {
activityInfo,
descriptionInfo,
timeRange,
players,
skill_level,
image_list,
...rest
} = formData[0];
const { activityInfo, descriptionInfo, timeRange, players, skill_level,image_list, ...rest } = formData[0];
const options = {
...rest,
...activityInfo,
@@ -295,50 +265,43 @@ const PublishBall: React.FC = () => {
current_players: players[0],
skill_level_min: skill_level[0],
skill_level_max: skill_level[1],
image_list: image_list.map((item) => item.url),
};
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);
title: '发布成功',
icon: 'success'
})
delay(1000)
// 如果是个人球局,则跳转到详情页,并自动分享
// 如果是畅打,则跳转第一个球局详情页,并自动分享 @刘杰
Taro.navigateTo({
// @ts-expect-error: id
url: `/game_pages/detail/index?id=${res.data.id || 1}&from=publish`,
});
url: `/pages/detail/index?id=${res.data.id || 1}&from=publish&autoShare=1`
})
} else {
Taro.showToast({
title: res.message,
icon: "none",
});
icon: 'none'
})
}
}
if (activityType === "group") {
const isValid = formData.every((item) => validateFormData(item));
if (activityType === 'group') {
const isValid = formData.every(item => validateFormData(item))
if (!isValid) {
return;
return
}
if (checkAdjacentDataSame(formData)) {
Taro.showToast({
title: "信息不可与前序场完全一致",
icon: "none",
});
return;
title: '信息不可与前序场完全一致',
icon: 'none'
})
return
}
const options = formData.map((item) => {
const {
activityInfo,
descriptionInfo,
timeRange,
players,
skill_level,
...rest
} = item;
return {
const { activityInfo, descriptionInfo, timeRange, players, skill_level, ...rest } = item;
return {
...rest,
...activityInfo,
...descriptionInfo,
@@ -347,146 +310,146 @@ const PublishBall: React.FC = () => {
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 });
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);
title: '发布成功',
icon: 'success'
})
delay(1000)
// 如果是个人球局,则跳转到详情页,并自动分享
// 如果是畅打,则跳转第一个球局详情页,并自动分享 @刘杰
Taro.navigateTo({
// @ts-expect-error: id
url: `/game_pages/detail/index?id=${res.data?.[0].id || 1}&from=publish`,
});
url: `/pages/detail/index?id=${res.data?.[0].id || 1}&from=publish&autoShare=1`
})
} else {
Taro.showToast({
title: res.message,
icon: "none",
});
icon: 'none'
})
}
}
};
}
const initFormData = () => {
const currentInstance = Taro.getCurrentInstance();
const params = currentInstance.router?.params;
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 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 === 'is_wechat_contact') {
return acc
}
if (item.prop === "image_list") {
if (item.prop === 'image_list') {
if (item.props) {
item.props.source = ["album", "history"];
item.props.source = ['album', 'history']
}
}
if (item.prop === "players") {
if (item.prop === 'players') {
if (item.props) {
item.props.max = 100;
item.props.max = 100
}
}
acc.push(item);
return acc;
}, [] as FormFieldConfig[]);
setOptionsConfig(newFormSchema);
setFormData([defaultFormData]);
acc.push(item)
return acc
}, [] as FormFieldConfig[])
setOptionsConfig(newFormSchema)
setFormData([defaultFormData])
}
// 根据type设置导航标题
if (type === "group") {
if (type === 'group') {
Taro.setNavigationBarTitle({
title: "发布畅打活动",
});
title: '发布畅打活动'
})
} else {
Taro.setNavigationBarTitle({
title: "发布",
});
title: '发布'
})
}
}
handleActivityTypeChange(type);
handleActivityTypeChange(type)
}
};
}
const onCheckedChange = (checked: boolean) => {
setChecked(checked);
};
setChecked(checked)
}
useEffect(() => {
const isValid = validateOnSubmit();
const isValid = validateOnSubmit()
if (!isValid) {
setIsSubmitDisabled(true);
setIsSubmitDisabled(true)
} else {
setIsSubmitDisabled(false);
setIsSubmitDisabled(false)
}
console.log(formData, "formData");
}, [formData]);
console.log(formData, 'formData');
}, [formData])
useEffect(() => {
initFormData();
}, []);
initFormData()
}, [])
return (
<View className={styles["publish-ball"]}>
<View className={styles['publish-ball']}>
{/* 活动类型切换 */}
<View className={styles["activity-type-switch"]}>
<View className={styles['activity-type-switch']}>
{/* <ActivityTypeSwitch
value={activityType}
onChange={handleActivityTypeChange}
/> */}
</View>
<View className={styles["publish-ball__scroll"]}>
{formData.map((item, index) => (
<View key={index}>
{/* 场次标题行 */}
{activityType === "group" && index > 0 && (
<View className={styles["session-header"]}>
<View className={styles["session-title"]}>
<View className={styles['publish-ball__scroll']}>
{
formData.map((item, index) => (
<View key={index}>
{/* 场次标题行 */}
{activityType === 'group' && index > 0 && (
<View className={styles['session-header']}>
<View className={styles['session-title']}>
{index + 1}
<View
className={styles["session-delete"]}
onClick={() => showDeleteConfirm(index)}
>
<Image
src={images.ICON_DELETE}
className={styles["session-delete-icon"]}
/>
className={styles['session-delete']}
onClick={() => showDeleteConfirm(index)}
>
<Image src={images.ICON_DELETE} className={styles['session-delete-icon']} />
</View>
</View>
<View className={styles['session-actions']}>
{index > 0 && (
<View
className={styles['session-action-btn']}
onClick={() => handleCopyPrevious(index)}
>
</View>
)}
</View>
</View>
<View className={styles["session-actions"]}>
{index > 0 && (
<View
className={styles["session-action-btn"]}
onClick={() => handleCopyPrevious(index)}
>
</View>
)}
</View>
</View>
)}
<PublishForm
formData={item}
onChange={(key, value) => updateFormData(key, value, index)}
optionsConfig={optionsConfig}
/>
</View>
))}
{activityType === "group" && (
<View className={styles["publish-ball__add"]} onClick={handleAdd}>
<Image
src={images.ICON_ADD}
className={styles["publish-ball__add-icon"]}
/>
</View>
)}
)}
<PublishForm
formData={item}
onChange={(key, value) => updateFormData(key, value, index)}
optionsConfig={optionsConfig}
/>
</View>
))
}
{
activityType === 'group' && (
<View className={styles['publish-ball__add']} onClick={handleAdd}>
<Image src={images.ICON_ADD} className={styles['publish-ball__add-icon']} />
</View>
)
}
</View>
{/* 删除确认弹窗 */}
@@ -500,32 +463,33 @@ const PublishBall: React.FC = () => {
contentDesc="该操作不可恢复"
/>
{/* 完成按钮 */}
<View className={styles["submit-section"]}>
<Button
className={`${styles["submit-btn"]} ${isSubmitDisabled ? styles["submit-btn-disabled"] : ""}`}
onClick={handleSubmit}
>
<View className={styles['submit-section']}>
<Button className={`${styles['submit-btn']} ${isSubmitDisabled ? styles['submit-btn-disabled'] : ''}`} onClick={handleSubmit}>
</Button>
{activityType === "individual" && (
<Text className={styles["submit-tip"]}>
<Text className={styles["link"]}></Text>
</Text>
)}
{activityType === "group" && (
<View className={styles["submit-tip"]}>
<Checkbox
className={styles["submit-checkbox"]}
checked={checked}
onChange={onCheckedChange}
/>
</View>
)}
{
activityType === 'individual' && (
<Text className={styles['submit-tip']}>
<Text className={styles['link']}></Text>
</Text>
)
}
{
activityType === 'group' && (
<View className={styles['submit-tip']}>
<Checkbox
className={styles['submit-checkbox']}
checked={checked}
onChange={onCheckedChange}
/>
</View>
)
}
</View>
</View>
);
};
)
}
export default withAuth(PublishBall);
export default withAuth(PublishBall)