React AntDesign中上传图片预览功能

现需求就是上传之后的图片再次进入的时候 该组件呈现可预览并且删除之后可以再次上传
图片个数限制最多传3张

效果如图:

图片上传

	return (
		<>
			<Modal visible={visible} maskClosable={false} className={classes.root} title={'添加专题图'} onCancel={() => setAddItemShow(false)}>
				<Form {...layout} form={form} initialValues={{ remember: true }} onFinish={(values) => getAnnouncementApi(values)}>
					<Form.Item
						label="图片"
						name="picture"
						rules={state == 'add' ? [{ required: true, message: '请上传图片' }] : [{ required: false, message: '请上传图片' }]}>
						<Upload
							beforeUpload={() => false}
							listType="picture-card"
							accept=".png,.jpg"
							fileList={pictureList}
							onPreview={handlePreview}
							onChange={({ fileList }) => setpictureList(fileList)}>
							{pictureList.length >= 3 ? null : uploadButton}
						</Upload>
					</Form.Item>

					<Form.Item {...tailLayout}>
						<Button loading={loadVis} type="primary" htmlType="submit" block>
							确定
						</Button>
					</Form.Item>
				</Form>
			</Modal>
			<Modal visible={previewVisible} title={previewTitle} footer={null} onCancel={handleCancel}>
				<img alt="example" style={{ width: '100%' }} src={previewImage} />
			</Modal>
		</>
	)

预览

//预览
const handlePreview = async (file) => {
		if (!file.url && !file.preview) {
			file.preview = await getFileBase64(file.originFileObj)
		}

		setPreviewImage(file.url || (file.preview as string))
		setPreviewVisible(true)
		// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
		setPreviewTitle(file.name || file.url!.substring(file.url!.lastIndexOf('/') + 1))
	}

回显


//回显
	useEffect(() => {
		if (state == 'add') { //判断当前是新增还是编辑
			setpictureList([])
		}

		if (!detailVal) return //详情信息

		// 获取数据中的图片
		if (detailVal?.pictureFiles) {
			// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
			const files = detailVal?.pictureFiles.map((url) => ({ uid: uuidv4(), name: url.filename, status: 'done', url: url.url }))

			setpictureList(files)
			// setpictureList(detailVal.pictureFiles)
		} else {
			setpictureList([])
		}
	}, [detailVal, state])

这里用到了获取文件的 base64 字符串形式

/**
 * 获取文件的 base64 字符串形式
 * @param {File} file
 * @returns {Promise<string>}
 */
export function getFileBase64(file: File): Promise<string> {
	return new Promise((resolve, reject) => {
		const reader = new FileReader()

		reader.readAsDataURL(file)
		reader.onload = () => resolve(reader.result)
		reader.onerror = (error) => reject(error)
	})
}

完成代码下:

import React, { useState, useEffect } from 'react'
import { Modal, Form, Upload, Button, DatePicker, message } from 'antd'
import { createUseStyles } from 'react-jss'
import { CameraOutlined } from '@ant-design/icons'
import { v4 as uuidv4 } from 'uuid'
import { getFileBase64 } from '../workbench-project/utils/helper'

const uploadButton = (
	<div>
		<CameraOutlined />
		<div style={{ marginTop: 8 }}>上传图片</div>
	</div>
)
const layout = {
	labelCol: { span: 3 },
	wrapperCol: { span: 20 },
}
const tailLayout = {
	wrapperCol: { offset: 1, span: 22 },
}
interface IProps {
	visible: boolean
	setAddItemShow: () => void
	loadVis:boolean
	setloadVis:boolean
	postAddThematic: () => void
	state:string
	detailVal: Record<string, string>
}
const ThematicAddModule: React.FC = (props: IProps) => {
	const { setAddItemShow, visible, loadVis, setloadVis, postAddThematic, state, detailVal } = props
	const [pictureList, setpictureList] = useState([])
	const [previewVisible, setPreviewVisible] = useState(false)
	const [previewImage, setPreviewImage] = useState('')
	const [previewTitle, setPreviewTitle] = useState('')
//预览
const handlePreview = async (file) => {
		if (!file.url && !file.preview) {
			file.preview = await getFileBase64(file.originFileObj)
		}

		setPreviewImage(file.url || (file.preview as string))
		setPreviewVisible(true)
		// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
		setPreviewTitle(file.name || file.url!.substring(file.url!.lastIndexOf('/') + 1))
	}
//关闭窗口
const handleCancel = () => setPreviewVisible(false)

//回显
	useEffect(() => {
		if (state == 'add') { //判断当前是新增还是编辑
			setpictureList([])
		}

		if (!detailVal) return //详情信息

		// 获取数据中的图片
		if (detailVal?.pictureFiles) {
			// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
			const files = detailVal?.pictureFiles.map((url) => ({ uid: uuidv4(), name: url.filename, status: 'done', url: url.url }))

			setpictureList(files)
			// setpictureList(detailVal.pictureFiles)
		} else {
			setpictureList([])
		}
	}, [detailVal, state])

	return (
		<>
			<Modal visible={visible} maskClosable={false} className={classes.root} title={'添加专题图'} onCancel={() => setAddItemShow(false)}>
				<Form {...layout} form={form} initialValues={{ remember: true }} onFinish={(values) => getAnnouncementApi(values)}>
					<Form.Item
						label="图片"
						name="picture"
						rules={state == 'add' ? [{ required: true, message: '请上传图片' }] : [{ required: false, message: '请上传图片' }]}>
						<Upload
							beforeUpload={() => false}
							listType="picture-card"
							accept=".png,.jpg"
							fileList={pictureList}
							onPreview={handlePreview}
							onChange={({ fileList }) => setpictureList(fileList)}>
							{pictureList.length >= 3 ? null : uploadButton}
						</Upload>
					</Form.Item>

					<Form.Item {...tailLayout}>
						<Button loading={loadVis} type="primary" htmlType="submit" block>
							确定
						</Button>
					</Form.Item>
				</Form>
			</Modal>
			<Modal visible={previewVisible} title={previewTitle} footer={null} onCancel={handleCancel}>
				<img alt="example" style={{ width: '100%' }} src={previewImage} />
			</Modal>
		</>
	)
	
}

没有太多文字类的描述,只能用代码表示,这里表示直接复制代码,然后根据需求在改改就大功告成啦!!!

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值