908 lines
25 KiB
TypeScript
908 lines
25 KiB
TypeScript
import React, { useState, useEffect, useRef } from "react";
|
||
import { View, Text, Button, Image } from "@tarojs/components";
|
||
import { Checkbox } from "@nutui/nutui-react-taro";
|
||
import dayjs from "dayjs";
|
||
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 { useGlobalState } from "@/store/global";
|
||
import GeneralNavbar from "@/components/GeneralNavbar";
|
||
import images from "@/config/images";
|
||
import { useUserInfo } from "@/store/userStore";
|
||
import styles from "./index.module.scss";
|
||
import { usePublishBallData } from "@/store/publishBallStore";
|
||
import { useKeyboardHeight } from "@/store/keyboardStore";
|
||
import DetailService from "@/services/detailService";
|
||
|
||
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: {
|
||
min: 1,
|
||
max: 1,
|
||
organizer_joined: true,
|
||
},
|
||
skill_level: [1.0, 5.0],
|
||
descriptionInfo: {
|
||
description: "",
|
||
description_tag: [],
|
||
},
|
||
is_substitute_supported: true,
|
||
wechat: {
|
||
is_wechat_contact: true,
|
||
wechat_contact: "",
|
||
default_wechat_contact: "",
|
||
},
|
||
};
|
||
|
||
const PublishBall: React.FC = () => {
|
||
const [activityType, setActivityType] = useState<ActivityType>("individual");
|
||
const [isSubmitDisabled, setIsSubmitDisabled] = useState(false);
|
||
const userInfo = useUserInfo();
|
||
const publishAiData = usePublishBallData();
|
||
const { statusNavbarHeightInfo } = useGlobalState();
|
||
|
||
// 使用全局键盘状态
|
||
const {
|
||
keyboardHeight,
|
||
isKeyboardVisible,
|
||
addListener,
|
||
initializeKeyboardListener,
|
||
} = useKeyboardHeight();
|
||
// 获取页面参数并设置导航标题
|
||
const [optionsConfig, setOptionsConfig] = useState<FormFieldConfig[]>(
|
||
publishBallFormSchema,
|
||
);
|
||
const [formData, setFormData] = useState<PublishBallFormData[]>([
|
||
defaultFormData,
|
||
]);
|
||
const [checked, setChecked] = useState(true);
|
||
const [publishLoading, setPublishLoading] = useState(false);
|
||
const [titleBar, setTitleBar] = useState("发布球局");
|
||
// 控制是否响应全局键盘(由具体输入框 focus/blur 控制)
|
||
const [shouldReactToKeyboard, setShouldReactToKeyboard] = useState(false);
|
||
|
||
// 删除确认弹窗状态
|
||
const [deleteConfirm, setDeleteConfirm] = useState<{
|
||
visible: boolean;
|
||
index: number;
|
||
}>({
|
||
visible: false,
|
||
index: -1,
|
||
});
|
||
|
||
// 更新表单数据
|
||
const updateFormData = (
|
||
key: keyof PublishBallFormData,
|
||
value: any,
|
||
index: number,
|
||
) => {
|
||
setFormData((prev) => {
|
||
const newData = [...prev];
|
||
newData[index] = { ...newData[index], [key]: value };
|
||
return newData;
|
||
});
|
||
};
|
||
|
||
// 检查相邻两组数据是否相同
|
||
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,
|
||
title,
|
||
timeRange,
|
||
image_list,
|
||
players,
|
||
current_players,
|
||
descriptionInfo,
|
||
} = formData;
|
||
const { play_type, price, location_name } = activityInfo;
|
||
const { description } = descriptionInfo;
|
||
|
||
const { max } = players;
|
||
if (!image_list?.length && activityType === "group") {
|
||
if (!isOnSubmit) {
|
||
Taro.showToast({
|
||
title: `请上传活动封面`,
|
||
icon: "none",
|
||
});
|
||
}
|
||
return false;
|
||
}
|
||
// 判断图片是否上传完成
|
||
if (image_list?.length > 0) {
|
||
const uploadInProgress = image_list.some((item) =>
|
||
item?.url?.startsWith?.("http://tmp/"),
|
||
);
|
||
if (uploadInProgress) {
|
||
Taro.showToast({
|
||
title: `封面图片上传中...`,
|
||
icon: "none",
|
||
});
|
||
return;
|
||
}
|
||
}
|
||
if (!title) {
|
||
if (!isOnSubmit) {
|
||
Taro.showToast({
|
||
title: `请输入活动标题`,
|
||
icon: "none",
|
||
});
|
||
}
|
||
return false;
|
||
}
|
||
if (title.length > 20) {
|
||
if (!isOnSubmit) {
|
||
Taro.showToast({
|
||
title: `标题最多可输入20个字`,
|
||
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);
|
||
const currentTime = dayjs();
|
||
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;
|
||
}
|
||
if (start.isBefore(currentTime)) {
|
||
if (!isOnSubmit) {
|
||
Taro.showToast({
|
||
title: `开始时间需晚于当前时间`,
|
||
icon: "none",
|
||
});
|
||
}
|
||
return false;
|
||
}
|
||
if (end.isBefore(currentTime)) {
|
||
if (!isOnSubmit) {
|
||
Taro.showToast({
|
||
title: `结束时间需晚于当前时间`,
|
||
icon: "none",
|
||
});
|
||
}
|
||
return false;
|
||
}
|
||
}
|
||
if (current_players && current_players > max) {
|
||
if (!isOnSubmit) {
|
||
Taro.showToast({
|
||
title: `最大人数不能小于当前参与人数${current_players}`,
|
||
icon: "none",
|
||
});
|
||
}
|
||
return false;
|
||
}
|
||
|
||
if (description?.length > 200) {
|
||
if (!isOnSubmit) {
|
||
Taro.showToast({
|
||
title: `补充要求最多可输入200个字`,
|
||
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 getParams = () => {
|
||
const currentInstance = Taro.getCurrentInstance();
|
||
const params = currentInstance.router?.params;
|
||
return params;
|
||
};
|
||
// 提交表单
|
||
const handleSubmit = async () => {
|
||
// 基础验证
|
||
const params = getParams();
|
||
const { republish } = params || {};
|
||
if (activityType === "individual") {
|
||
const isValid = validateFormData(formData[0]);
|
||
if (!isValid || publishLoading) {
|
||
return;
|
||
}
|
||
setPublishLoading(true);
|
||
const {
|
||
activityInfo,
|
||
descriptionInfo,
|
||
is_substitute_supported,
|
||
timeRange,
|
||
players,
|
||
skill_level,
|
||
image_list,
|
||
wechat,
|
||
id,
|
||
...rest
|
||
} = formData[0];
|
||
const { min, max, organizer_joined } = players;
|
||
const options = {
|
||
...rest,
|
||
...activityInfo,
|
||
...descriptionInfo,
|
||
...timeRange,
|
||
max_players: max,
|
||
min_players: min,
|
||
organizer_joined: organizer_joined === true ? 1 : 0,
|
||
skill_level_min: skill_level[0],
|
||
skill_level_max: skill_level[1],
|
||
image_list: image_list.map((item) => item.url),
|
||
is_wechat_contact: wechat.is_wechat_contact ? 1 : 0,
|
||
wechat_contact: wechat.wechat_contact || wechat.default_wechat_contact,
|
||
is_substitute_supported: is_substitute_supported ? "1" : "0",
|
||
...(republish === "0" ? { id } : {}),
|
||
};
|
||
const res =
|
||
republish === "0"
|
||
? await PublishService.gamesUpdate(options)
|
||
: await PublishService.createPersonal(options);
|
||
const successText = republish === "0" ? "更新成功" : "发布成功";
|
||
if (res.code === 0 && res.data) {
|
||
Taro.showToast({
|
||
title: successText,
|
||
icon: "success",
|
||
});
|
||
delay(1000);
|
||
// 如果是个人球局,则跳转到详情页,并自动分享
|
||
// 如果是畅打,则跳转第一个球局详情页,并自动分享 @刘杰
|
||
const id = (res as any).data?.id;
|
||
// 如果是编辑,就返回,否则就是新发布
|
||
if (republish === "0") {
|
||
Taro.navigateBack();
|
||
} else {
|
||
// 使用 redirectTo 替换当前页面,避免返回时回到发布页面
|
||
Taro.redirectTo({
|
||
// @ts-expect-error: id
|
||
url: `/game_pages/detail/index?id=${
|
||
id || 1
|
||
}&from=publish&autoShare=1`,
|
||
});
|
||
}
|
||
} else {
|
||
Taro.showToast({
|
||
title: res.message,
|
||
icon: "none",
|
||
});
|
||
setPublishLoading(false);
|
||
}
|
||
}
|
||
if (activityType === "group") {
|
||
const isValid = formData.every((item) => validateFormData(item));
|
||
if (!isValid || publishLoading) {
|
||
return;
|
||
}
|
||
setPublishLoading(true);
|
||
if (checkAdjacentDataSame(formData)) {
|
||
Taro.showToast({
|
||
title: "信息不可与前序场完全一致",
|
||
icon: "none",
|
||
});
|
||
return;
|
||
}
|
||
const options = formData.map((item) => {
|
||
const {
|
||
activityInfo,
|
||
descriptionInfo,
|
||
timeRange,
|
||
players,
|
||
skill_level,
|
||
is_substitute_supported,
|
||
id,
|
||
...rest
|
||
} = item;
|
||
const { min, max, organizer_joined } = players;
|
||
return {
|
||
...rest,
|
||
...activityInfo,
|
||
...descriptionInfo,
|
||
...timeRange,
|
||
max_players: max,
|
||
min_players: min,
|
||
organizer_joined: organizer_joined === true ? 1 : 0,
|
||
skill_level_min: skill_level[0],
|
||
skill_level_max: skill_level[1],
|
||
is_substitute_supported: is_substitute_supported ? "1" : "0",
|
||
image_list: item.image_list.map((img) => img.url),
|
||
...(republish === "0" ? { id } : {}),
|
||
};
|
||
});
|
||
const successText = republish === "0" ? "更新成功" : "发布成功";
|
||
const res =
|
||
republish === "0"
|
||
? await PublishService.gamesUpdate(options[0])
|
||
: await PublishService.create_play_pmoothlys({ rows: options });
|
||
if (res.code === 0 && res.data) {
|
||
Taro.showToast({
|
||
title: successText,
|
||
icon: "success",
|
||
});
|
||
delay(1000);
|
||
// 如果是个人球局,则跳转到详情页,并自动分享
|
||
// 如果是畅打,则跳转第一个球局详情页,并自动分享 @刘杰
|
||
const id =
|
||
republish === "0"
|
||
? (res as any).data?.id
|
||
: (res as any).data?.[0]?.id;
|
||
// 使用 redirectTo 替换当前页面,避免返回时回到发布页面
|
||
Taro.redirectTo({
|
||
// @ts-expect-error: id
|
||
url: `/game_pages/detail/index?id=${
|
||
id || 1
|
||
}&from=publish&autoShare=1`,
|
||
});
|
||
} else {
|
||
Taro.showToast({
|
||
title: res.message,
|
||
icon: "none",
|
||
});
|
||
setPublishLoading(false);
|
||
}
|
||
}
|
||
};
|
||
|
||
const mergeWithDefault = (
|
||
data: any,
|
||
isDetail: boolean = false,
|
||
): PublishBallFormData => {
|
||
// ai导入与详情数据处理
|
||
const {
|
||
start_time,
|
||
end_time,
|
||
play_type,
|
||
price,
|
||
venue_id,
|
||
location_name,
|
||
location,
|
||
latitude,
|
||
longitude,
|
||
court_type,
|
||
court_surface,
|
||
venue_description_tag,
|
||
venue_description,
|
||
venue_image_list,
|
||
description,
|
||
description_tag,
|
||
max_players,
|
||
min_players,
|
||
skill_level_max,
|
||
skill_level_min,
|
||
venueDtl,
|
||
wechat_contact,
|
||
image_list,
|
||
id: publish_id,
|
||
is_wechat_contact,
|
||
is_substitute_supported,
|
||
title,
|
||
current_players,
|
||
organizer_joined,
|
||
} = data;
|
||
const level_max = skill_level_max ? Number(skill_level_max) : 5.0;
|
||
const level_min = skill_level_min ? Number(skill_level_min) : 1.0;
|
||
const userPhone = wechat_contact || (userInfo as any)?.phone || "";
|
||
let activityInfo = {};
|
||
if (venueDtl) {
|
||
const {
|
||
latitude,
|
||
longitude,
|
||
venue_type,
|
||
surface_type,
|
||
facilities,
|
||
name,
|
||
id,
|
||
} = venueDtl;
|
||
activityInfo = {
|
||
latitude,
|
||
longitude,
|
||
court_type: venue_type,
|
||
court_surface: surface_type,
|
||
venue_description: facilities,
|
||
location_name: name,
|
||
venue_id: id,
|
||
};
|
||
}
|
||
if (isDetail) {
|
||
activityInfo = {
|
||
venue_id,
|
||
location_name,
|
||
location,
|
||
latitude,
|
||
longitude,
|
||
court_type,
|
||
court_surface,
|
||
venue_description_tag,
|
||
venue_description,
|
||
venue_image_list,
|
||
};
|
||
}
|
||
return {
|
||
...defaultFormData,
|
||
title,
|
||
...(is_substitute_supported === "0"
|
||
? { is_substitute_supported: false }
|
||
: {}),
|
||
...(publish_id ? { id: publish_id } : {}),
|
||
timeRange: {
|
||
...defaultFormData.timeRange,
|
||
start_time,
|
||
end_time,
|
||
},
|
||
activityInfo: {
|
||
...defaultFormData.activityInfo,
|
||
...(play_type ? { play_type } : {}),
|
||
...(price ? { price } : {}),
|
||
...activityInfo,
|
||
},
|
||
descriptionInfo: {
|
||
...defaultFormData.descriptionInfo,
|
||
...(description ? { description } : {}),
|
||
...(description_tag ? { description_tag } : {}),
|
||
},
|
||
...(level_max && level_min
|
||
? { skill_level: [level_min, level_max] }
|
||
: {}),
|
||
...(max_players && min_players
|
||
? {
|
||
players: {
|
||
min: min_players,
|
||
max: max_players,
|
||
organizer_joined: organizer_joined === 0 ? false : true,
|
||
},
|
||
}
|
||
: {}),
|
||
wechat: {
|
||
...defaultFormData.wechat,
|
||
default_wechat_contact: userPhone,
|
||
is_wechat_contact: is_wechat_contact === 0 ? false : true,
|
||
},
|
||
image_list: image_list?.map((item) => ({ url: item, id: item })) || [],
|
||
...(current_players ? { current_players } : {}),
|
||
};
|
||
};
|
||
|
||
const formatConfig = () => {
|
||
const newFormSchema = publishBallFormSchema.reduce((acc, item) => {
|
||
if (item.prop === "wechat") {
|
||
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);
|
||
};
|
||
const initFormData = () => {
|
||
const params = getParams();
|
||
const userPhone = (userInfo as any)?.phone || "";
|
||
if (params?.type) {
|
||
const type = params.type as ActivityType;
|
||
if (type === "individual" || type === "group") {
|
||
setActivityType(type);
|
||
if (type === "group") {
|
||
formatConfig();
|
||
setFormData([defaultFormData]);
|
||
setTitleBar("发布畅打活动");
|
||
} else {
|
||
setTitleBar("发布球局");
|
||
setFormData([
|
||
{
|
||
...defaultFormData,
|
||
wechat: {
|
||
...defaultFormData.wechat,
|
||
default_wechat_contact: userPhone,
|
||
},
|
||
},
|
||
]);
|
||
}
|
||
} else if (type === "ai") {
|
||
// 从 Store 注入 AI 生成的表单 JSON
|
||
if (
|
||
publishAiData &&
|
||
Array.isArray(publishAiData) &&
|
||
publishAiData.length > 0
|
||
) {
|
||
Taro.showToast({
|
||
title: "智能识别成功,请完善剩余信息",
|
||
icon: "none",
|
||
});
|
||
const merged = publishAiData.map((item) => mergeWithDefault(item));
|
||
setFormData(merged.length ? merged : [defaultFormData]);
|
||
if (merged.length === 1) {
|
||
setTitleBar("发布球局");
|
||
setActivityType("individual");
|
||
} else {
|
||
formatConfig();
|
||
setTitleBar("发布畅打活动");
|
||
setActivityType("group");
|
||
}
|
||
} else {
|
||
setFormData([defaultFormData]);
|
||
setTitleBar("发布球局");
|
||
setActivityType("individual");
|
||
}
|
||
}
|
||
}
|
||
if (params?.gameId) {
|
||
getGameDetail(params.gameId);
|
||
}
|
||
};
|
||
|
||
const getGameDetail = async (gameId) => {
|
||
if (!gameId) return;
|
||
try {
|
||
const res = await DetailService.getDetail(Number(gameId));
|
||
if (res.code === 0) {
|
||
const merged = mergeWithDefault(res.data, true);
|
||
setFormData([merged]);
|
||
if (res.data.game_type === "个人球局") {
|
||
setTitleBar("发布球局");
|
||
setActivityType("individual");
|
||
} else {
|
||
setTitleBar("发布畅打活动");
|
||
setActivityType("group");
|
||
}
|
||
}
|
||
} catch (e) {
|
||
Taro.showToast({
|
||
title: e.message,
|
||
icon: "none",
|
||
});
|
||
}
|
||
};
|
||
const onCheckedChange = (checked: boolean) => {
|
||
setChecked(checked);
|
||
};
|
||
useEffect(() => {
|
||
const isValid = validateOnSubmit();
|
||
if (!isValid) {
|
||
setIsSubmitDisabled(true);
|
||
} else {
|
||
setIsSubmitDisabled(false);
|
||
}
|
||
}, [formData]);
|
||
|
||
useEffect(() => {
|
||
initFormData();
|
||
}, []);
|
||
|
||
// 使用全局键盘状态监听
|
||
useEffect(() => {
|
||
// 初始化全局键盘监听器
|
||
initializeKeyboardListener();
|
||
|
||
// 添加本地监听器
|
||
const removeListener = addListener(() => {
|
||
// 布局是否响应交由 shouldReactToKeyboard 决定
|
||
});
|
||
|
||
return () => {
|
||
removeListener();
|
||
};
|
||
}, [initializeKeyboardListener, addListener]);
|
||
|
||
const handleAnyInputFocus = (item: FormFieldConfig, e: any) => {
|
||
const { prop } = item;
|
||
if (prop === "descriptionInfo") {
|
||
setShouldReactToKeyboard(true);
|
||
}
|
||
};
|
||
const handleAnyInputBlur = () => {
|
||
setShouldReactToKeyboard(false);
|
||
};
|
||
return (
|
||
<View
|
||
className={`${styles["publish-ball-container"]} ${
|
||
isKeyboardVisible && shouldReactToKeyboard
|
||
? styles["publish-ball-container-keyboard"]
|
||
: ""
|
||
}`}
|
||
style={{
|
||
bottom:
|
||
isKeyboardVisible && shouldReactToKeyboard
|
||
? `${keyboardHeight - 124}px`
|
||
: 0,
|
||
}}
|
||
>
|
||
<GeneralNavbar
|
||
title={titleBar}
|
||
className={styles["publish-ball-navbar"]}
|
||
/>
|
||
<View
|
||
className={styles["publish-ball"]}
|
||
style={{ paddingTop: `${statusNavbarHeightInfo.totalHeight}px` }}
|
||
>
|
||
{/* 活动类型切换 */}
|
||
{/* <View className={styles['activity-type-switch']}>
|
||
<ActivityTypeSwitch
|
||
value={activityType}
|
||
onChange={handleActivityTypeChange}
|
||
/>
|
||
</View> */}
|
||
|
||
<View
|
||
className={styles["publish-ball__scroll"]}
|
||
style={{
|
||
height: `calc(100vh - ${
|
||
statusNavbarHeightInfo.totalHeight + 140
|
||
}px)`,
|
||
overflow: "auto",
|
||
}}
|
||
>
|
||
{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"]}
|
||
/>
|
||
</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}
|
||
onAnyInputFocus={handleAnyInputFocus}
|
||
onAnyInputBlur={handleAnyInputBlur}
|
||
/>
|
||
</View>
|
||
))}
|
||
{activityType === "group" && (
|
||
<View className={styles["publish-ball__add"]} onClick={handleAdd}>
|
||
<Image
|
||
src={images.ICON_ADD}
|
||
className={styles["publish-ball__add-icon"]}
|
||
/>
|
||
再添加一场
|
||
</View>
|
||
)}
|
||
</View>
|
||
|
||
{/* 删除确认弹窗 */}
|
||
<CommonDialog
|
||
visible={deleteConfirm.visible}
|
||
cancelText="再想想"
|
||
confirmText="确认移除"
|
||
onCancel={closeDeleteConfirm}
|
||
onConfirm={confirmDelete}
|
||
contentTitle="确认移除该场次?"
|
||
contentDesc="该操作不可恢复"
|
||
/>
|
||
{/* 完成按钮 */}
|
||
<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"]}
|
||
onClick={() =>
|
||
Taro.navigateTo({ url: "/publish_pages/footballRules/index" })
|
||
}
|
||
>
|
||
《约球规则》
|
||
</Text>
|
||
</Text>
|
||
)}
|
||
{/* {activityType === "group" && (
|
||
<View className={styles["submit-tip"]}>
|
||
<Checkbox
|
||
className={styles["submit-checkbox"]}
|
||
checked={checked}
|
||
onChange={onCheckedChange}
|
||
/>
|
||
已认证 徐汇爱打球官方球场,请严格遵守签约协议
|
||
</View>
|
||
)} */}
|
||
</View>
|
||
</View>
|
||
</View>
|
||
);
|
||
};
|
||
|
||
export default withAuth(PublishBall);
|