Files
mini-programs/src/components/UploadCover/index.tsx

141 lines
4.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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>
</>
);
};