feat: 修复发布时图片未上传完成导致详情图片丢失的问题,修复详情球局日期展示问题,修复球局管理取消活动无响应的问题
This commit is contained in:
@@ -52,7 +52,7 @@ module.exports = {
|
||||
'nutui-react',
|
||||
],
|
||||
|
||||
['transform-remove-console', { exclude: ['error', 'warn'] }],
|
||||
// ['transform-remove-console', { exclude: ['error', 'warn'] }],
|
||||
['@babel/plugin-transform-runtime', { corejs: false }]
|
||||
],
|
||||
}
|
||||
|
||||
@@ -43,12 +43,12 @@ const CancelPopup = forwardRef((props, ref) => {
|
||||
}
|
||||
|
||||
async function handleConfirm() {
|
||||
if (!cancelReason) {
|
||||
if (!cancelReason && hasOtherJoin) {
|
||||
Taro.showToast({ title: "请输入取消原因", icon: "none" });
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await onFinish.current(cancelReason);
|
||||
await onFinish.current(hasOtherJoin ? cancelReason : "无责取消");
|
||||
onClose();
|
||||
} catch (e) {
|
||||
console.log(e, 1221);
|
||||
|
||||
@@ -1,95 +1,123 @@
|
||||
import React, { useCallback, useRef, useState } from 'react'
|
||||
import { Image, View, Text } from '@tarojs/components'
|
||||
import img from '../../config/images'
|
||||
import UploadSourcePopup, { sourceMap } from './upload-source-popup'
|
||||
import UploadFromWx from './upload-from-wx'
|
||||
import { CommonPopup } from '../'
|
||||
import React, { useCallback, useRef, useState } from "react";
|
||||
import Taro from "@tarojs/taro";
|
||||
import { Image, View, Text } from "@tarojs/components";
|
||||
import img from "../../config/images";
|
||||
import UploadSourcePopup, { sourceMap } from "./upload-source-popup";
|
||||
import UploadFromWx from "./upload-from-wx";
|
||||
import { CommonPopup } from "../";
|
||||
|
||||
import './index.scss'
|
||||
import { uploadFileResponseData } from '@/services/uploadFiles'
|
||||
import "./index.scss";
|
||||
// import { uploadFileResponseData } from "@/services/uploadFiles";
|
||||
|
||||
export type sourceType = 'album' | 'history' | 'preset'
|
||||
export type sourceType = "album" | "history" | "preset";
|
||||
|
||||
export type source = sourceType[]
|
||||
export type source = sourceType[];
|
||||
|
||||
export type CoverImageValue = {
|
||||
id: string
|
||||
url: string
|
||||
tempFilePath?: string
|
||||
}
|
||||
id: string;
|
||||
url: string;
|
||||
tempFilePath?: string;
|
||||
};
|
||||
|
||||
export interface UploadCoverProps {
|
||||
value: CoverImageValue[]
|
||||
changePicker?: (value: boolean) => void
|
||||
onChange: (value: CoverImageValue[] | ((prev: CoverImageValue[]) => CoverImageValue[])
|
||||
) => void
|
||||
source?: source
|
||||
maxCount?: number
|
||||
align?: 'center' | 'left'
|
||||
tag?: 'cover' | 'screenshot'
|
||||
value: CoverImageValue[];
|
||||
changePicker?: (value: boolean) => void;
|
||||
onChange: (
|
||||
value: CoverImageValue[] | ((prev: CoverImageValue[]) => CoverImageValue[])
|
||||
) => void;
|
||||
source?: source;
|
||||
maxCount?: number;
|
||||
align?: "center" | "left";
|
||||
tag?: "cover" | "screenshot";
|
||||
}
|
||||
|
||||
// const values = [
|
||||
// 'http://bimwe.oss-cn-shanghai.aliyuncs.com/front/ball/images/1a35ebbf-2361-44da-b338-7608561d0b31.png',
|
||||
// 'http://bimwe.oss-cn-shanghai.aliyuncs.com/front/ball/images/cf5a82ba-90af-4138-a1b3-9119adcde9e0.png',
|
||||
// 'http://bimwe.oss-cn-shanghai.aliyuncs.com/front/ball/images/49d7cdf0-b03c-4a0f-91c6-e7778080cfcd.png'
|
||||
// ]
|
||||
|
||||
const mergeCoverImages = (value: CoverImageValue[], images: CoverImageValue[]) => {
|
||||
const mergeCoverImages = (
|
||||
value: CoverImageValue[], // prev value
|
||||
images: CoverImageValue[] // new value
|
||||
) => {
|
||||
// 根据id来更新url, 如果id不存在,则添加到value中
|
||||
const newImages = images
|
||||
const updatedValue = value.map(item => {
|
||||
const index = images.findIndex(image => image.id === item.id)
|
||||
if (index !== -1) {
|
||||
newImages.splice(index, 1)
|
||||
return { ...item, url: images[index].url }
|
||||
}
|
||||
return item
|
||||
})
|
||||
return [...updatedValue, ...newImages]
|
||||
}
|
||||
const newImages = images;
|
||||
const failedIdList = images
|
||||
.filter((item) => !item.url)
|
||||
.map((item) => item.id);
|
||||
const failedIndexList: number[] = [];
|
||||
const updatedValue = value
|
||||
.map((item, i) => {
|
||||
const index = newImages.findIndex((image) => image.id === item.id);
|
||||
if (index !== -1) {
|
||||
const newUrl = newImages[index].url;
|
||||
newImages.splice(index, 1);
|
||||
if (failedIdList.includes(item.id)) {
|
||||
failedIndexList.push(i + 1);
|
||||
return null;
|
||||
}
|
||||
return { ...item, url: newUrl };
|
||||
}
|
||||
return item;
|
||||
})
|
||||
.filter((item) => item);
|
||||
if (failedIndexList.length > 0) {
|
||||
Taro.showToast({
|
||||
title: `第${failedIndexList.join("、")}张图片上传失败,请检查重试`,
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
return [...updatedValue, ...newImages];
|
||||
};
|
||||
|
||||
export default function UploadCover(props: UploadCoverProps) {
|
||||
const {
|
||||
value = [],
|
||||
onChange = () => void 0,
|
||||
source = ['album', 'history', 'preset'] as source,
|
||||
source = ["album", "history", "preset"] as source,
|
||||
maxCount = 9,
|
||||
align = 'center',
|
||||
tag = 'cover',
|
||||
changePicker
|
||||
} = props
|
||||
align = "center",
|
||||
tag = "cover",
|
||||
changePicker,
|
||||
} = props;
|
||||
|
||||
const [visible, setVisible] = useState(false)
|
||||
const [visible, setVisible] = useState(false);
|
||||
const uploadSourcePopupRef = useRef<{
|
||||
show: (sourceType: sourceType, maxCount: number) => void
|
||||
}>(null)
|
||||
show: (sourceType: sourceType, maxCount: number) => void;
|
||||
}>(null);
|
||||
|
||||
const onAdd = useCallback((images: CoverImageValue[]) => {
|
||||
// FIXME: prev is not latest value
|
||||
onChange(prev => mergeCoverImages(prev, images))
|
||||
setVisible(false)
|
||||
}, [value])
|
||||
const onAdd = useCallback(
|
||||
(images: CoverImageValue[]) => {
|
||||
// FIXME: prev is not latest value
|
||||
onChange((prev) => mergeCoverImages(prev, images));
|
||||
setVisible(false);
|
||||
},
|
||||
[value]
|
||||
);
|
||||
|
||||
const onWxAdd = useCallback((images: CoverImageValue[], onFileUpdate: Promise<{ id: string, url: string }[]>) => {
|
||||
onAdd(images)
|
||||
onFileUpdate.then(res => {
|
||||
onAdd(res.map(item => ({
|
||||
id: item.id,
|
||||
url: item.url,
|
||||
})))
|
||||
})
|
||||
}, [onAdd])
|
||||
const onWxAdd = useCallback(
|
||||
async (
|
||||
images: CoverImageValue[],
|
||||
onFileUpdate: Promise<{ id: string; url: string }[]>
|
||||
) => {
|
||||
onAdd(images);
|
||||
onFileUpdate.then((res) => {
|
||||
console.log("onWxAdd update");
|
||||
onAdd(
|
||||
res.map((item) => ({
|
||||
id: item.id,
|
||||
url: item.url,
|
||||
}))
|
||||
);
|
||||
});
|
||||
},
|
||||
[onAdd]
|
||||
);
|
||||
const onDelete = (image: CoverImageValue) => {
|
||||
onChange(value.filter(item => item.id !== image.id))
|
||||
}
|
||||
onChange(value.filter((item) => item.id !== image.id));
|
||||
};
|
||||
|
||||
const openPicker = (value: boolean) => {
|
||||
setVisible(value)
|
||||
setVisible(value);
|
||||
if (changePicker) {
|
||||
changePicker(value)
|
||||
changePicker(value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -101,50 +129,75 @@ export default function UploadCover(props: UploadCoverProps) {
|
||||
hideFooter
|
||||
zIndex={1000}
|
||||
>
|
||||
<View className="upload-source-popup-container" style={{ height: source.length * 56 + 52 + 'px' }}>
|
||||
{
|
||||
source.map((item) => {
|
||||
return (
|
||||
<View className="upload-source-popup-item" key={item}>
|
||||
{
|
||||
item === 'album' ? (
|
||||
<UploadFromWx onAdd={onWxAdd} maxCount={maxCount - value.length} />
|
||||
) : (
|
||||
<View className="upload-source-popup-item-text" onClick={() => uploadSourcePopupRef.current?.show(item, maxCount - value.length)}>
|
||||
<Text>{sourceMap.get(item)}</Text>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
</View>
|
||||
)
|
||||
})
|
||||
}
|
||||
<View
|
||||
className="upload-source-popup-container"
|
||||
style={{ height: source.length * 56 + 52 + "px" }}
|
||||
>
|
||||
{source.map((item) => {
|
||||
return (
|
||||
<View className="upload-source-popup-item" key={item}>
|
||||
{item === "album" ? (
|
||||
<UploadFromWx
|
||||
onAdd={onWxAdd}
|
||||
maxCount={maxCount - value.length}
|
||||
/>
|
||||
) : (
|
||||
<View
|
||||
className="upload-source-popup-item-text"
|
||||
onClick={() =>
|
||||
uploadSourcePopupRef.current?.show(
|
||||
item,
|
||||
maxCount - value.length
|
||||
)
|
||||
}
|
||||
>
|
||||
<Text>{sourceMap.get(item)}</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
</CommonPopup>
|
||||
<UploadSourcePopup tag={tag} ref={uploadSourcePopupRef} onAdd={onAdd} />
|
||||
<div className={`upload-cover-root ${value.length === 0 && align === 'center' ? 'upload-cover-act-center' : ''}`}>
|
||||
<div
|
||||
className={`upload-cover-root ${
|
||||
value.length === 0 && align === "center"
|
||||
? "upload-cover-act-center"
|
||||
: ""
|
||||
}`}
|
||||
>
|
||||
{value.length < maxCount && (
|
||||
<div className="upload-cover-act" onClick={() => openPicker(true)}>
|
||||
<Image className='upload-cover-act-icon' src={img.ICON_ADD} />
|
||||
<Image className="upload-cover-act-icon" src={img.ICON_ADD} />
|
||||
<div className="upload-cover-text">添加活动封面</div>
|
||||
</div>
|
||||
)}
|
||||
<div className={`cover-image-list-container ${value.length === maxCount ? 'full' : ''}`}>
|
||||
<div
|
||||
className={`cover-image-list-container ${
|
||||
value.length === maxCount ? "full" : ""
|
||||
}`}
|
||||
>
|
||||
<div className="cover-image-list">
|
||||
{
|
||||
value.map((item) => {
|
||||
return (
|
||||
<View className="cover-image-item" key={item.id}>
|
||||
<Image className="cover-image-item-image" src={item.url} mode="aspectFill" />
|
||||
<Image className="cover-image-item-delete" src={img.ICON_REMOVE} onClick={() => onDelete(item)} />
|
||||
</View>
|
||||
)
|
||||
})
|
||||
}
|
||||
{value.map((item) => {
|
||||
return (
|
||||
<View className="cover-image-item" key={item.id}>
|
||||
<Image
|
||||
className="cover-image-item-image"
|
||||
src={item.url}
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<Image
|
||||
className="cover-image-item-delete"
|
||||
src={img.ICON_REMOVE}
|
||||
onClick={() => onDelete(item)}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,123 +1,153 @@
|
||||
import React from 'react'
|
||||
import { View, Text } from '@tarojs/components'
|
||||
import Taro from '@tarojs/taro'
|
||||
import uploadApi from '@/services/uploadFiles'
|
||||
import './upload-from-wx.scss'
|
||||
import { CoverImageValue } from '.'
|
||||
import React from "react";
|
||||
import { View, Text } from "@tarojs/components";
|
||||
import Taro from "@tarojs/taro";
|
||||
import uploadApi from "@/services/uploadFiles";
|
||||
import "./upload-from-wx.scss";
|
||||
import { CoverImageValue } from ".";
|
||||
|
||||
export interface UploadFromWxProps {
|
||||
onAdd: (images: CoverImageValue[], onFileUploaded: Promise<{ id: string, url: string }[]>) => void
|
||||
maxCount: number
|
||||
onAdd: (
|
||||
images: CoverImageValue[],
|
||||
onFileUploaded: Promise<{ id: string; url: string }[]>
|
||||
) => void;
|
||||
maxCount: number;
|
||||
}
|
||||
|
||||
async function convert_to_jpg_and_compress (src: string, { width, height }): Promise<string> {
|
||||
const canvas = Taro.createOffscreenCanvas({ type: '2d', width, height })
|
||||
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D
|
||||
async function convert_to_jpg_and_compress(
|
||||
src: string,
|
||||
{ width, height }
|
||||
): Promise<string> {
|
||||
const canvas = Taro.createOffscreenCanvas({ type: "2d", width, height });
|
||||
const ctx = canvas.getContext("2d") as CanvasRenderingContext2D;
|
||||
|
||||
const image = canvas.createImage()
|
||||
await new Promise(resolve => {
|
||||
image.onload = resolve
|
||||
image.src = src
|
||||
})
|
||||
ctx.clearRect(0, 0, width, height)
|
||||
ctx.drawImage(image as unknown as CanvasImageSource, 0, 0, width, height)
|
||||
const image = canvas.createImage();
|
||||
await new Promise((resolve) => {
|
||||
image.onload = resolve;
|
||||
image.src = src;
|
||||
});
|
||||
ctx.clearRect(0, 0, width, height);
|
||||
ctx.drawImage(image as unknown as CanvasImageSource, 0, 0, width, height);
|
||||
|
||||
// const imageData = ctx.getImageData(0, 0, width, height)
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
Taro.canvasToTempFilePath({
|
||||
canvas: canvas as unknown as Taro.Canvas,
|
||||
fileType: 'jpg',
|
||||
fileType: "jpg",
|
||||
quality: 0.7,
|
||||
success: res => resolve(res.tempFilePath),
|
||||
fail: reject
|
||||
})
|
||||
})
|
||||
success: (res) => resolve(res.tempFilePath),
|
||||
fail: reject,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
async function compressImage(files) {
|
||||
const res: string[] = []
|
||||
const res: string[] = [];
|
||||
for (const file of files) {
|
||||
const compressed_image = await convert_to_jpg_and_compress(file.path, { width: file.width, height: file.height })
|
||||
res.push(compressed_image)
|
||||
const compressed_image = await convert_to_jpg_and_compress(file.path, {
|
||||
width: file.width,
|
||||
height: file.height,
|
||||
});
|
||||
res.push(compressed_image);
|
||||
}
|
||||
return res
|
||||
return res;
|
||||
}
|
||||
// 图片标准容器为 360 * 240 3:2
|
||||
// 压缩后图片最大宽高
|
||||
const IMAGE_MAX_SIZE = {
|
||||
width: 1080,
|
||||
height: 720,
|
||||
}
|
||||
};
|
||||
|
||||
// 标准长宽比,判断标准
|
||||
const STANDARD_ASPECT_RATIO = IMAGE_MAX_SIZE.width / IMAGE_MAX_SIZE.height
|
||||
const STANDARD_ASPECT_RATIO = IMAGE_MAX_SIZE.width / IMAGE_MAX_SIZE.height;
|
||||
|
||||
type ChoosenImageRes = { path: string, size: number, width: number, height: number }
|
||||
type ChoosenImageRes = {
|
||||
path: string;
|
||||
size: number;
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
// 根据图片标准重新设置图片尺寸
|
||||
async function onChooseImageSuccess(tempFiles) {
|
||||
const result: ChoosenImageRes[] = []
|
||||
const result: ChoosenImageRes[] = [];
|
||||
for (const tempFile of tempFiles) {
|
||||
const { width, height } = await Taro.getImageInfo({ src: tempFile.path })
|
||||
const image_aspect_ratio = width / height
|
||||
let fileRes: ChoosenImageRes = { path: tempFile.path, size: tempFile.size, width: 0, height: 0 }
|
||||
const { width, height } = await Taro.getImageInfo({ src: tempFile.path });
|
||||
const image_aspect_ratio = width / height;
|
||||
let fileRes: ChoosenImageRes = {
|
||||
path: tempFile.path,
|
||||
size: tempFile.size,
|
||||
width: 0,
|
||||
height: 0,
|
||||
};
|
||||
// 如果图片长宽比小于标准长宽比,则依照图片高度以及图片最大高度来重新设置图片尺寸
|
||||
if (image_aspect_ratio < STANDARD_ASPECT_RATIO) {
|
||||
fileRes = {
|
||||
...fileRes,
|
||||
...(height > IMAGE_MAX_SIZE.height ? { width: Math.floor(IMAGE_MAX_SIZE.height * image_aspect_ratio), height: IMAGE_MAX_SIZE.height } : { width: Math.floor(height * image_aspect_ratio), height }),
|
||||
}
|
||||
...(height > IMAGE_MAX_SIZE.height
|
||||
? {
|
||||
width: Math.floor(IMAGE_MAX_SIZE.height * image_aspect_ratio),
|
||||
height: IMAGE_MAX_SIZE.height,
|
||||
}
|
||||
: { width: Math.floor(height * image_aspect_ratio), height }),
|
||||
};
|
||||
} else {
|
||||
fileRes = {
|
||||
...fileRes,
|
||||
...(width > IMAGE_MAX_SIZE.width ? { width: IMAGE_MAX_SIZE.width, height: Math.floor(IMAGE_MAX_SIZE.width / image_aspect_ratio) } : { width, height: Math.floor(width / image_aspect_ratio) }),
|
||||
}
|
||||
...(width > IMAGE_MAX_SIZE.width
|
||||
? {
|
||||
width: IMAGE_MAX_SIZE.width,
|
||||
height: Math.floor(IMAGE_MAX_SIZE.width / image_aspect_ratio),
|
||||
}
|
||||
: { width, height: Math.floor(width / image_aspect_ratio) }),
|
||||
};
|
||||
}
|
||||
result.push(fileRes)
|
||||
result.push(fileRes);
|
||||
}
|
||||
return result
|
||||
return result;
|
||||
}
|
||||
|
||||
export default function UploadFromWx(props: UploadFromWxProps) {
|
||||
const {
|
||||
onAdd = () => void 0,
|
||||
maxCount = 9, // calc from parent
|
||||
} = props
|
||||
} = props;
|
||||
const handleImportFromWx = () => {
|
||||
Taro.chooseImage({
|
||||
count: maxCount,
|
||||
sizeType: ['original', 'compressed'],
|
||||
sourceType: ['album', 'camera'],
|
||||
sizeType: ["original", "compressed"],
|
||||
sourceType: ["album", "camera"],
|
||||
}).then(async (res) => {
|
||||
const analyzedFiles = await onChooseImageSuccess(res.tempFiles)
|
||||
// compress image
|
||||
const analyzedFiles = await onChooseImageSuccess(res.tempFiles);
|
||||
// cropping image to standard size
|
||||
const compressedTempFiles = await compressImage(analyzedFiles)
|
||||
const compressedTempFiles = await compressImage(analyzedFiles);
|
||||
|
||||
let start = Date.now()
|
||||
const files = compressedTempFiles.map(path => ({
|
||||
let start = Date.now();
|
||||
const files = compressedTempFiles.map((path) => ({
|
||||
filePath: path,
|
||||
description: '封面图',
|
||||
tags: 'cover',
|
||||
description: "封面图",
|
||||
tags: "cover",
|
||||
is_public: 1 as unknown as 0 | 1,
|
||||
id: (start++).toString(),
|
||||
}))
|
||||
const onFileUpdate = uploadApi.batchUpload(files).then(res => {
|
||||
return res.map(item => ({
|
||||
}));
|
||||
const onFileUpdate = uploadApi.batchUpload(files).then((res) => {
|
||||
return res.map((item) => ({
|
||||
id: item.id,
|
||||
url: item.data.file_url
|
||||
}))
|
||||
})
|
||||
onAdd(files.map(item => ({
|
||||
id: item.id,
|
||||
url: item.filePath,
|
||||
})), onFileUpdate)
|
||||
})
|
||||
}
|
||||
url: item ? item.data.file_url : "",
|
||||
}));
|
||||
});
|
||||
onAdd(
|
||||
files.map((item) => ({
|
||||
id: item.id,
|
||||
url: item.filePath,
|
||||
})),
|
||||
onFileUpdate
|
||||
);
|
||||
});
|
||||
};
|
||||
return (
|
||||
<View onClick={handleImportFromWx}>
|
||||
<Text className="upload-from-wx-text">从相册添加</Text>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,8 +13,11 @@ function genGameLength(startTime: Dayjs, endTime: Dayjs) {
|
||||
return "";
|
||||
}
|
||||
const hours = endTime.diff(startTime, "hour");
|
||||
if (Math.floor(hours / 24) > 1) {
|
||||
return `${Math.floor(hours / 24)}天${hours % 24}小时`;
|
||||
if (Math.floor(hours / 24) >= 1) {
|
||||
const leftHours = Math.floor(hours % 24);
|
||||
return `${Math.floor(hours / 24)}天${
|
||||
leftHours !== 0 ? `${leftHours}小时` : ""
|
||||
}`;
|
||||
}
|
||||
return `${hours}小时`;
|
||||
}
|
||||
|
||||
@@ -105,6 +105,12 @@ export default function StickyButton(props) {
|
||||
available: false,
|
||||
// action: () => toast("活动已取消"),
|
||||
};
|
||||
} else if (MATCH_STATUS.FINISHED === match_status) {
|
||||
return {
|
||||
text: "活动已结束",
|
||||
available: false,
|
||||
// action: () => toast("活动已取消"),
|
||||
};
|
||||
} else if (dayjs(end_time).isBefore(dayjs())) {
|
||||
return {
|
||||
text: "活动已结束",
|
||||
|
||||
@@ -57,7 +57,7 @@ const defaultFormData: PublishBallFormData = {
|
||||
wechat_contact: '',
|
||||
default_wechat_contact: ''
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
const PublishBall: React.FC = () => {
|
||||
@@ -66,7 +66,7 @@ const PublishBall: React.FC = () => {
|
||||
const userInfo = useUserInfo();
|
||||
const publishAiData = usePublishBallData()
|
||||
const { statusNavbarHeightInfo } = useGlobalState();
|
||||
|
||||
|
||||
// 使用全局键盘状态
|
||||
const { keyboardHeight, isKeyboardVisible, addListener, initializeKeyboardListener } = useKeyboardHeight()
|
||||
// 获取页面参数并设置导航标题
|
||||
@@ -181,7 +181,7 @@ const PublishBall: React.FC = () => {
|
||||
const validateFormData = (formData: PublishBallFormData, isOnSubmit: boolean = false) => {
|
||||
const { activityInfo, title, timeRange, image_list, players, current_players } = formData;
|
||||
const { play_type, price, location_name } = activityInfo;
|
||||
|
||||
|
||||
const { max } = players;
|
||||
if (!image_list?.length && activityType === 'group') {
|
||||
if (!isOnSubmit) {
|
||||
@@ -192,6 +192,19 @@ const PublishBall: React.FC = () => {
|
||||
}
|
||||
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({
|
||||
@@ -268,7 +281,7 @@ const PublishBall: React.FC = () => {
|
||||
})
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
if (current_players && (current_players > max)) {
|
||||
if (!isOnSubmit) {
|
||||
@@ -464,7 +477,7 @@ const PublishBall: React.FC = () => {
|
||||
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 } : {}),
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -487,7 +500,7 @@ const PublishBall: React.FC = () => {
|
||||
return acc
|
||||
}, [] as FormFieldConfig[])
|
||||
setOptionsConfig(newFormSchema)
|
||||
}
|
||||
}
|
||||
const initFormData = () => {
|
||||
const params = getParams()
|
||||
const userPhone = (userInfo as any)?.phone || ''
|
||||
@@ -532,7 +545,7 @@ const PublishBall: React.FC = () => {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
const getGameDetail = async (gameId) => {
|
||||
if (!gameId) return;
|
||||
@@ -577,7 +590,7 @@ const PublishBall: React.FC = () => {
|
||||
useEffect(() => {
|
||||
// 初始化全局键盘监听器
|
||||
initializeKeyboardListener()
|
||||
|
||||
|
||||
// 添加本地监听器
|
||||
const removeListener = addListener((height, visible) => {
|
||||
console.log('PublishBall 收到键盘变化:', height, visible)
|
||||
|
||||
@@ -48,26 +48,36 @@ class UploadApi {
|
||||
|
||||
const authHeader = tokenManager.getAuthHeader()
|
||||
const { id, ...rest } = req
|
||||
return Taro.uploadFile({
|
||||
url: fullUrl,
|
||||
filePath: rest.filePath,
|
||||
name: 'file',
|
||||
formData: {
|
||||
description: rest.description,
|
||||
tags: rest.tags,
|
||||
is_public: rest.is_public,
|
||||
},
|
||||
header: authHeader,
|
||||
}).then(res => {
|
||||
try {
|
||||
const res = await Taro.uploadFile({
|
||||
url: fullUrl,
|
||||
filePath: rest.filePath,
|
||||
name: 'file',
|
||||
formData: {
|
||||
description: rest.description,
|
||||
tags: rest.tags,
|
||||
is_public: rest.is_public,
|
||||
},
|
||||
header: authHeader,
|
||||
});
|
||||
return {
|
||||
id,
|
||||
data: JSON.parse(res.data).data,
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
throw { id, error }
|
||||
}
|
||||
}
|
||||
|
||||
async batchUpload(req: UploadFilesData[]): Promise<{ id: string, data: uploadFileResponseData }[]> {
|
||||
return Promise.all(req.map(item => this.upload(item)))
|
||||
async batchUpload(req: UploadFilesData[]): Promise<{ id: string, data: uploadFileResponseData | null }[]> {
|
||||
return Promise.all(req.map(async (item) => {
|
||||
try {
|
||||
const res = await this.upload(item);
|
||||
return res;
|
||||
} catch (error) {
|
||||
return { id: item.id, data: null }
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
// 上传单张图片到OSS
|
||||
@@ -84,7 +94,7 @@ class UploadApi {
|
||||
header: authHeader,
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
const result = JSON.parse(response.data);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user