'text:测试react-dnd'
This commit is contained in:
parent
0415665bc5
commit
62fae1dffe
|
|
@ -0,0 +1,14 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<link rel="stylesheet" href="//at.alicdn.com/t/font_2570680_2fgczr3435f.css">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
{
|
||||
"name": "example",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"start": "vite",
|
||||
"lint:less": "stylelint **/*.{css,sass,less} --fix --allow-empty-input",
|
||||
"build": "vite build --mode=production",
|
||||
"build:stag": "vite build --mode=staging",
|
||||
"serve": "vite preview",
|
||||
"releash": "sh releash.sh",
|
||||
"log": "standard-changelog -f && git add CHANGELOG.md"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@jest/types": "28.0.2",
|
||||
"@testing-library/dom": "7.21.4",
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/react": "12.1.5",
|
||||
"@testing-library/user-event": "12.8.3",
|
||||
"@types/node": "^16.18.3",
|
||||
"@types/react-dom": "^16.9.19",
|
||||
"js-cookie": "^2.2.1",
|
||||
"jszip": "^3.4.0",
|
||||
"less": "^3.9.0",
|
||||
"less-loader": "^5.0.0",
|
||||
"lodash": "^4.17.21",
|
||||
"qs": "^6.11.0",
|
||||
"react": "^16.14.0",
|
||||
"react-beautiful-dnd": "^13.0.0",
|
||||
"react-countup": "^4.3.3",
|
||||
"react-custom-scrollbars": "^4.2.1",
|
||||
"react-dnd": "^16.0.1",
|
||||
"react-dnd-html5-backend": "^16.0.1",
|
||||
"react-document-title": "^2.0.3",
|
||||
"react-dom": "^16.14.0",
|
||||
"react-draft-wysiwyg": "^1.14.5",
|
||||
"react-loadable": "^5.5.0",
|
||||
"react-redux": "^7.2.0",
|
||||
"react-router-dom": "^5.1.2",
|
||||
"react-scripts": "3.4.1",
|
||||
"react-transition-group": "^4.4.1",
|
||||
"redux": "^4.0.5",
|
||||
"redux-thunk": "^2.3.0",
|
||||
"typescript": "~4.2.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^16.14.43",
|
||||
"@vitejs/plugin-react": "3.1.0",
|
||||
"vite": "3.2.5",
|
||||
"vite-plugin-svg-icons": "^1.0.5"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
.box{
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
import React, {Component, useState} from "react";
|
||||
import "./App.css"
|
||||
import CustDrag from "./component/CustDrag"
|
||||
import CustDrop from "./component/CustDrop"
|
||||
import {DndProvider} from "react-dnd";
|
||||
import {HTML5Backend} from "react-dnd-html5-backend";
|
||||
const dndList = [
|
||||
{ label: "组件1", value: "组件1" },
|
||||
{ label: "组件2", value: "组件2" },
|
||||
{ label: "组件3", value: "组件3" },
|
||||
];
|
||||
|
||||
const DndPage = () => {
|
||||
const [list, setList] = useState(dndList);
|
||||
const dropChange = (res: any[]) => {
|
||||
// const valList = (res || []).map((item) => item?.value);
|
||||
// const filterList = dndList.filter((item) => !valList.includes(item.value));
|
||||
// setList(filterList);
|
||||
};
|
||||
return (
|
||||
<DndProvider backend={HTML5Backend}>
|
||||
<div >
|
||||
<div>组件:</div>
|
||||
<div>
|
||||
<div style={{ border: "1px solid #000" }}>
|
||||
{list.map((item,index) => {
|
||||
return <span style={{margin:"0 10px"}} key={index}>
|
||||
<CustDrag key={item.value} data={item} />
|
||||
</span>;
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ marginTop: "10px" }}>用例列表:</div>
|
||||
<CustDrop onChange={dropChange} />
|
||||
</div>
|
||||
</DndProvider>
|
||||
);
|
||||
};
|
||||
class App extends Component {
|
||||
eventLogger = (e: MouseEvent, data: Object) => {
|
||||
console.log('Event: ', e);
|
||||
console.log('Data: ', data);
|
||||
};
|
||||
handleStart = ()=>{
|
||||
console.log(1)
|
||||
}
|
||||
handleDrag = (e: MouseEvent)=>{
|
||||
console.log(e)
|
||||
}
|
||||
handleStop = (e: MouseEvent)=>{
|
||||
console.log(e)
|
||||
}
|
||||
render() {
|
||||
const dragHandlers = {onStart: this.handleStart, onStop: this.handleStop};
|
||||
return (
|
||||
<div className="box" style={{height: '500px', width: '500px', position: 'relative', overflow: 'auto', padding: '0'}}>
|
||||
<DndPage />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
import { useDrag } from "react-dnd";
|
||||
|
||||
// @ts-ignore
|
||||
const CustDrag = ({ data }) => {
|
||||
const [{ opacity }, dragRef] = useDrag({
|
||||
type: "Field",
|
||||
item: { ...data },
|
||||
collect: (monitor) => ({
|
||||
opacity: monitor.isDragging() ? 0.5 : 1,
|
||||
}),
|
||||
});
|
||||
|
||||
return (
|
||||
<span ref={dragRef} style={{ opacity, cursor: "move" }}>
|
||||
{data?.label}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
export default CustDrag
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
import { useDrop } from "react-dnd";
|
||||
import React, {useRef, useState} from "react";
|
||||
import CustDrag from "@/component/CustDrag";
|
||||
// 同级为排序
|
||||
// 跨级为插入
|
||||
import DragSortItemComponent from "@/component/DragSortItemComponent"
|
||||
const dndList = [
|
||||
{id:1, label: "组件1", value: "组件1" },
|
||||
{id:2,label: "组件2", value: "组件2" },
|
||||
{id:3, label: "组件3", value: "组件3" },
|
||||
];
|
||||
// @ts-ignore
|
||||
const CustDrop = ({ onChange }) => {
|
||||
const [itemClass, setItemClass] = useState<{ key: number | null; value: string }>({
|
||||
key: null,
|
||||
value: '',
|
||||
})
|
||||
const sortItems = useRef<{ dragRow: any; placeRow: any; posi: string }>({
|
||||
dragRow: {},
|
||||
placeRow: {},
|
||||
posi: '',
|
||||
})
|
||||
const [value, setValue] = useState<any[]>(dndList);
|
||||
const [{ canDrop, isOver }, drop] = useDrop({
|
||||
accept: 'Field',
|
||||
drop: (item) => {
|
||||
|
||||
// const { dragRow, placeRow, posi } = sortItems.current
|
||||
// let _map: any[] = JSON.parse(JSON.stringify(dndList))
|
||||
// let index1 = _map.findIndex(v => v.id === dragRow.id) // 拖拽的itemIndex
|
||||
// _map.splice(index1, 1) // 先删掉拖拽的,在获取放置的
|
||||
const targetValue = [...value];
|
||||
targetValue.push(item);
|
||||
setValue(targetValue);
|
||||
console.log(item,value)
|
||||
onChange(targetValue);
|
||||
// let index = _map.findIndex(v => v.id === placeRow.id) // 放置的itemIndex
|
||||
// if (index !== -1 && index1 !== -1) {
|
||||
// _map.splice(posi === 'bottom' ? index + 1 : index, 0, dragRow)
|
||||
// setValue(() => _map)
|
||||
// }
|
||||
},
|
||||
collect: (monitor) => ({
|
||||
// 是否放置在目标上
|
||||
isOver: monitor.isOver(),
|
||||
// 是否开始拖拽
|
||||
canDrop: monitor.canDrop(),
|
||||
}),
|
||||
});
|
||||
|
||||
// 展示拖动时的界面效果
|
||||
const showCanDrop = () => {
|
||||
if (canDrop && !isOver && !value.length) return <div>请拖拽到此处</div>;
|
||||
};
|
||||
|
||||
const delItem = (ind: number) => {
|
||||
const newValue = [...value];
|
||||
newValue.splice(ind, 1);
|
||||
setValue(newValue);
|
||||
onChange(newValue);
|
||||
};
|
||||
const onItemDragClass = (key:number,value:string) => {
|
||||
console.log(key,value,itemClass.value)
|
||||
if (itemClass.value !== value) {
|
||||
setItemClass(() => {
|
||||
let data = { key, value }
|
||||
return data
|
||||
})
|
||||
}
|
||||
}
|
||||
const onSortItemChange = (dragRow: any, placeRow: any, posi: string) => {
|
||||
console.log(dragRow,placeRow,posi)
|
||||
sortItems.current = { dragRow, placeRow, posi }
|
||||
}
|
||||
// 内容展示
|
||||
const showValue = () => {
|
||||
return value.map((item, index: number) => {
|
||||
return (
|
||||
<div key={index} >
|
||||
<CustDrag data={item} />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={drop}
|
||||
style={{ border: '1px solid #000', marginTop: '10px', minHeight: '200px', background: '#fff' }}
|
||||
>
|
||||
{showCanDrop()}
|
||||
{showValue()}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
export default CustDrop
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
/**
|
||||
* 通用拖拽排序的容器
|
||||
* @param row 当前行
|
||||
* @param onItemDragClass 拖拽过程的样式 top | bottom
|
||||
* @param onSortItemChange 拖拽结束后返回的值 dragRow 当前拖拽 placeRow 放置的,posi 位置 top | bottom
|
||||
* @param keyName 键名
|
||||
*/
|
||||
import {useDrag, useDrop, XYCoord} from "react-dnd";
|
||||
import {useRef} from "react";
|
||||
|
||||
type IProps = {
|
||||
row: any,
|
||||
onItemDragClass: (key:number,value:string) => void,
|
||||
onSortItemChange: (dragRow: any, placeRow: any, posi: string) => void // 排序后
|
||||
keyName: string
|
||||
}
|
||||
const DragSortItemComponent:React.FC<IProps> = props => {
|
||||
const { row,onItemDragClass,onSortItemChange,keyName } = props
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
/**
|
||||
* 拖拽容器
|
||||
*/
|
||||
const [, drop] = useDrop({
|
||||
// 定义拖拽的类型
|
||||
accept: 'sort',
|
||||
drop: (item, monitor) => {
|
||||
const didDrop = monitor.didDrop()
|
||||
if (didDrop) {
|
||||
return
|
||||
}
|
||||
},
|
||||
canDrop: (item, mointor) => {
|
||||
// 阻止默认拖拽释放
|
||||
onItemDragClass(row[keyName], '')
|
||||
return false
|
||||
},
|
||||
hover: (item: any, monitor) => {
|
||||
const didHover = monitor.isOver({ shallow: true })
|
||||
if (didHover) {
|
||||
// 拖拽目标的id
|
||||
const dragIndex = item[keyName]
|
||||
// 放置目标id 可以用index | id 只要是number,数据里唯一的就可以
|
||||
const hoverIndex = row[keyName]
|
||||
// 如果一样不处理
|
||||
if (dragIndex === hoverIndex) {
|
||||
onItemDragClass(row[keyName], '')
|
||||
return
|
||||
}
|
||||
// 获取放置的位置
|
||||
const hoverBoundingRect = ref.current?.getBoundingClientRect() as DOMRect
|
||||
// 获取放置的Y轴中点
|
||||
const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2
|
||||
// 获取拖拽目标偏移量
|
||||
const clientOffset = monitor.getClientOffset() as XYCoord
|
||||
const hoverClientY = clientOffset.y - hoverBoundingRect.top
|
||||
if (dragIndex !== hoverIndex) {
|
||||
if (hoverMiddleY < hoverClientY) {
|
||||
onItemDragClass(row[keyName], 'bottom')
|
||||
} else {
|
||||
onItemDragClass(row[keyName], 'top')
|
||||
}
|
||||
// 如果不做成通用拖拽容器,把参数存起来,把这个放在useDrag的end方法里,
|
||||
onSortItemChange(item, row, hoverMiddleY < hoverClientY ? 'bottom' : 'top')
|
||||
}
|
||||
}
|
||||
},
|
||||
collect: monitor => ({
|
||||
isOver: monitor.isOver({ shallow: true }),
|
||||
canDrop: monitor.canDrop(),
|
||||
}),
|
||||
})
|
||||
/**
|
||||
* 定义拖拽
|
||||
* isDragging 是否拖拽
|
||||
*/
|
||||
// const [{ isDragging }, drag] = useDrag({
|
||||
// item: { ...row, type: 'sort'},
|
||||
// end: () => {
|
||||
// // onSortItemChange(item, row, hoverMiddleY < hoverClientY ? 'bottom' : 'top')
|
||||
// },
|
||||
// collect: monitor => ({
|
||||
// isDragging: monitor.isDragging(),
|
||||
// didDrop: monitor.isDragging(),
|
||||
// }),
|
||||
// })
|
||||
// drop(drag(ref))
|
||||
return (
|
||||
<div ref={ref} >
|
||||
{props.children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default DragSortItemComponent
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import App from './App';
|
||||
import {DndProvider} from "react-dnd"
|
||||
import {HTML5Backend} from "react-dnd-html5-backend"
|
||||
|
||||
ReactDOM.render(
|
||||
<App />
|
||||
|
||||
,document.getElementById('root'));
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"strict": true,
|
||||
"jsx": "preserve",
|
||||
"importHelpers": true,
|
||||
"moduleResolution": "node",
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"sourceMap": true,
|
||||
"baseUrl": ".",
|
||||
"types": ["webpack-env", "vite/client", "vite-plugin-pages/client"],
|
||||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
},
|
||||
"lib": ["esnext", "dom", "dom.iterable", "scripthost"]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"platform/**/*.ts",
|
||||
"src/**/*.tsx",
|
||||
"src/**/*.vue",
|
||||
"tests/**/*.ts",
|
||||
"tests/**/*.tsx"
|
||||
],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
import {ConfigEnv, UserConfigExport} from 'vite'
|
||||
// @ts-ignore
|
||||
import viteSvgIcons from "vite-plugin-svg-icons";
|
||||
import React from '@vitejs/plugin-react'
|
||||
// @ts-ignore
|
||||
import qiankun from "vite-plugin-qiankun"
|
||||
// @ts-ignore
|
||||
import path, {resolve} from 'path'
|
||||
|
||||
const pathResolve = (dir: string): any => {
|
||||
return resolve(__dirname, '.', dir)
|
||||
}
|
||||
console.log(__dirname);
|
||||
|
||||
const alias: Record<string, string> = {
|
||||
'@': pathResolve('src'),
|
||||
'api': pathResolve('src/api'),
|
||||
'compoents': pathResolve('src/compoents'),
|
||||
}
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default ({command}: ConfigEnv): UserConfigExport => {
|
||||
const prodMock = true
|
||||
return {
|
||||
base: "/workbench",
|
||||
css:{
|
||||
devSourcemap:true
|
||||
},
|
||||
resolve: {
|
||||
alias
|
||||
},
|
||||
server: {
|
||||
port: 3001,
|
||||
host: '0.0.0.0',
|
||||
open: true,
|
||||
proxy: {
|
||||
// 代理配置
|
||||
'/api': {
|
||||
target: 'http://192.168.31.150:8080/',
|
||||
changeOrigin: true,
|
||||
rewrite: path => path.replace(/^\/api/, '')
|
||||
}
|
||||
}
|
||||
},
|
||||
build: {
|
||||
rollupOptions: {
|
||||
output: {
|
||||
manualChunks: {
|
||||
echarts: ['echarts']
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
React(),
|
||||
viteSvgIcons({
|
||||
// 指定需要缓存的图标文件夹
|
||||
iconDirs: [path.resolve(process.cwd(), 'src/assets/svg')],
|
||||
// 指定symbolId格式
|
||||
symbolId: 'icon-[dir]-[name]',
|
||||
}),
|
||||
qiankun("workbench", {
|
||||
useDevMode: true
|
||||
})
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -7,13 +7,13 @@ import { ElMessage } from "element-plus";
|
|||
import App from './App.vue'
|
||||
import store from './store'
|
||||
import {renderWithQiankun,qiankunWindow,QiankunProps} from "vite-plugin-qiankun/dist/helper"
|
||||
let instance = null
|
||||
let instance:any = null
|
||||
const render = (props:QiankunProps={})=>{
|
||||
const {container} = props
|
||||
const appEle:string |Element = container?.querySelector("#app")||"#app"
|
||||
const app = createApp(App)
|
||||
instance = app
|
||||
app.use(ElementPlus, { size: store.state.app.elementSize })
|
||||
app.use(ElementPlus, { size: "small" })
|
||||
app.use(store)
|
||||
app.config.globalProperties.$message = ElMessage
|
||||
// app.config.performance = true
|
||||
|
|
@ -37,7 +37,7 @@ const initQianKun = ()=>{
|
|||
},
|
||||
})
|
||||
}
|
||||
export async function mount(props){
|
||||
export async function mount(props:any){
|
||||
console.log('基座下发的能力:', props);
|
||||
render(props)
|
||||
// return new Promise(((resolve, reject) => {
|
||||
|
|
|
|||
33592
pnpm-lock.yaml
33592
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue