'text:测试react-dnd'

This commit is contained in:
zjc 2023-06-23 17:23:05 +08:00
parent 0415665bc5
commit 62fae1dffe
14 changed files with 17947 additions and 16105 deletions

View File

@ -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>

View File

@ -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"
}
}

View File

@ -0,0 +1,5 @@
.box{
height: 50px;
width: 50px;
overflow: hidden;
}

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

View File

View File

@ -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'));

View File

@ -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"]
}

View File

@ -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
})
]
}
}

View File

@ -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) => {

File diff suppressed because it is too large Load Diff