功能说明
做项目使用React Antd4.x Upload上传图片,实现批量上传。
后期项目迭代更新,要求拖拽图片调整图片顺序。
框架不支持,自己借助包写了一个上传且可以拖拽图片换位置的功能。
下面是思路具体步骤:
1、框架Upload实现批量上传,预览,删除。
2、Upload旁边增加拖拽换位置的按钮。
3、点击按钮弹窗,弹窗中实现拖拽。
设计原因:上传与拖拽互不影响。
功能实现
安装“array-move”
$ npm i array-move
安装“react-sortable-hoc"
$ npm install react-sortable-hoc --save
封装拖拽弹窗组件
/* eslint-disable react-hooks/exhaustive-deps */
import React, { useEffect, useState, } from "react";
import { Modal, } from 'antd';
import { SortableContainer, SortableElement, } from 'react-sortable-hoc';
import { arrayMoveImmutable } from 'array-move';
import './style.less';
import CTSTooltip from '@/components/CTSTooltip';
const handlePreview = (value,) => {
if (value) {
const image = new Image();
image.src = value;
const imageWindow = window.open(value);
imageWindow.document.write(image.outerHTML);
}
}
const handleOver = (value) => {
document.getElementById(`img-operate-wrap${value}`).style.display = 'block';
}
const handleOut = (value) => {
document.getElementById(`img-operate-wrap${value}`).style.display = 'none';
}
const SortableItem = SortableElement(({ value, onDelete }) => <div onMouseOut={() => handleOut(value)} onMouseOver={() => handleOver(value)} className='img-box-wrap'>
<img alt='' className='img-box' src={value}></img>
<div className='img-operate-default' id={`img-operate-wrap${value}`}>
<div className='img-icon-wrap'>
<CTSTooltip title="预览" iconName="icon-yulan" onTooltipIcon={() => handlePreview(value)} />
<CTSTooltip className="del" title="删除" iconName="icon-lajitong" onTooltipIcon={() => onDelete(value)} />
</div>
</div>
</div>
);
const SortableList = SortableContainer(({ items, onDelete }) => {
return <div style={{ display: 'flex', flexWrap: 'wrap' }}>{
items && items.map((value, index) => (
<SortableItem key={`item-${value.url}`} index={index} onDelete={onDelete} value={value.url} />
))}
</div>
});
const CTSChangePosition = ({
visible,
fileListAll,
onConfirm,
onCancel,
loading = false,
}) => {
const [fileTempList, setFileTempList] = useState(fileListAll);
useEffect(() => {
setFileTempList(fileListAll);
}, []);
const handleOk = () => {
// console.log("final ----", fileTempList);
onConfirm(fileTempList);
}
const onSortEnd = ({ oldIndex, newIndex }) => {
let finalList = arrayMoveImmutable(fileTempList, oldIndex, newIndex);
setFileTempList(finalList);
};
const handleDelete = (value) => {
// console.log("value - value", value, fileTempList);
if (value) {
let dealFileList = fileTempList.filter(item => item.url !== value);
// console.log("dealFileList", dealFileList,);
setFileTempList(dealFileList);
}
}
return (<Modal width="70%" loading={loading} title={'拖拽调整图片顺序'} onOk={handleOk} maskClosable={false} onCancel={onCancel} visible={visible} >
<SortableList distance={10} axis="xy" items={fileTempList} onSortEnd={onSortEnd} onDelete={(value) => handleDelete(value)} />
</Modal>)
}
export default CTSChangePosition;
.img-box-wrap {
position: relative;
z-index: 9999;
.img-box {
width: 104px;
height: 104px;
margin-right: 8px;
margin-bottom: 8px;
border: 1px dashed #d9d9d9;
background: white;
}
.img-operate-default {
width: 104px;
height: 104px;
margin-right: 8px;
margin-bottom: 8px;
display: none;
position: absolute;
top: 0;
left: 0;
opacity: 0.5;
background-color: black;
.iconfont {
color: white;
font-size: 20px;
}
.icon-lajitong {
margin-left: 6px;
}
.icon-yulan {
margin-right: 6px;
}
.img-icon-wrap {
width: 104px;
height: 104px;
display: flex;
justify-content: center;
align-items: center;
color: white;
}
}
}
组件的引用:
<Button className='btn' onClick={() => handleChangeImagePosition()}>调整图片顺序</Button>
{visible && <CTSChangePosition visible={visible} fileListAll={fileListAll} onConfirm={(fileListDeal) => handleModalConfirm(fileListDeal)} onCancel={() => handleModalClose()} />}
const handleChangeImagePosition = () => {
setVisible(true);
}
const handleModalClose = () => {
setVisible(false);
}
const handleModalConfirm = (fileListDeal) => {
setFileListAll(fileListDeal);
if (form) {
form.setFieldsValue({
[`${name[0]}`]: {
[name[1]]: fileListDeal
}
})
}
handleModalClose();
}