141 lines
4.6 KiB
TypeScript
141 lines
4.6 KiB
TypeScript
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 './index.scss'
|
||
import { uploadFileResponseData } from '@/services/uploadFiles'
|
||
|
||
export type sourceType = 'album' | 'history' | 'preset'
|
||
|
||
export type source = sourceType[]
|
||
|
||
export type CoverImageValue = {
|
||
id: string
|
||
url: string
|
||
tempFilePath?: string
|
||
}
|
||
|
||
export interface UploadCoverProps {
|
||
value: CoverImageValue[]
|
||
onChange: (value: CoverImageValue[] | ((prev: CoverImageValue[]) => CoverImageValue[])
|
||
) => void
|
||
source?: source
|
||
maxCount?: number
|
||
align?: 'center' | 'left'
|
||
}
|
||
|
||
// 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[]) => {
|
||
console.log(value, images, 11111)
|
||
// 根据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]
|
||
}
|
||
|
||
export default function UploadCover(props: UploadCoverProps) {
|
||
const {
|
||
value = [],
|
||
onChange = () => void 0,
|
||
source = ['album', 'history', 'preset'] as source,
|
||
maxCount = 9,
|
||
align = 'center',
|
||
} = props
|
||
|
||
const [visible, setVisible] = useState(false)
|
||
const uploadSourcePopupRef = useRef<{
|
||
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 onWxAdd = useCallback((images: CoverImageValue[], onFileUploaded: Promise<{ id: string, data: uploadFileResponseData }[]>) => {
|
||
onAdd(images)
|
||
onFileUploaded.then(res => {
|
||
onAdd(res.map(item => ({
|
||
id: item.id,
|
||
url: item.data.file_path,
|
||
})))
|
||
})
|
||
}, [onAdd])
|
||
const onDelete = (image: CoverImageValue) => {
|
||
onChange(value.filter(item => item.id !== image.id))
|
||
}
|
||
|
||
return (
|
||
<>
|
||
<CommonPopup
|
||
visible={visible}
|
||
onClose={() => setVisible(false)}
|
||
round
|
||
position="bottom"
|
||
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>
|
||
</CommonPopup>
|
||
<UploadSourcePopup ref={uploadSourcePopupRef} onAdd={onAdd} />
|
||
<div className={`upload-cover-root ${value.length === 0 && align === 'center' ? 'upload-cover-act-center' : ''}`}>
|
||
{value.length < maxCount && (
|
||
<div className="upload-cover-act" onClick={() => setVisible(true)}>
|
||
<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">
|
||
{
|
||
value.map((item) => {
|
||
return (
|
||
<View className="cover-image-item" key={item.id}>
|
||
<Image className="cover-image-item-image" src={item.url} />
|
||
<Image className="cover-image-item-delete" src={img.ICON_REMOVE} onClick={() => onDelete(item)} />
|
||
</View>
|
||
)
|
||
})
|
||
}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</>
|
||
);
|
||
};
|
||
|