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