import React, { useState, useEffect, useRef } from 'react'; import { Modal, Spin, Table, Button, Divider, Input, notification } from 'antd'; import classnames from 'classnames' import { LoadFieldsByGroup, LoadGroup } from '@/services/tablemanager/tablemanager' import { PlusOutlined, DeleteOutlined } from '@ant-design/icons'; import Sortable from 'sortablejs'; import styles from './index.less' import { ChangeOrder } from '@/services/tablemanager/tablemanager' import { DataRegion } from 'bizcharts/lib/components/Annotation'; import { Number } from 'core-js'; let list = {} const AddModal = props => { let ref = useRef(); const { callBackSubmit = () => { }, type, formObj, visible } = props; const [loading, setLoading] = useState(false); const [treeLoading, setTreeLoading] = useState(true) const [isModalVisible, setIsModalVisible] = useState(false) const [allData, setAllData] = useState({}) const [leftData, setLeftData] = useState([]) const [flag, setFlag] = useState(0); // 弹窗类型 const [pickIndex, setPickIndex] = useState('') const [selectData, setSelectData] = useState('') const [createName, setCreateName] = useState('') // 提交 const onSubmit = () => { setLoading(true); let arr = [] leftData.map((item) => { allData[item].map(allItem => { arr.push({ groupName: item, ID: Number(allItem.ID) }) }) }) ChangeOrder(arr).then(res => { setLoading(false); if (res.msg === 'Ok' || res.msg === '') { notification.success({ message: '提示', duration: 3, description: '编辑成功', }); callBackSubmit(); } else { notification.error({ message: '提示', duration: 3, description: res.msg, }); } }) }; useEffect(() => { if (type != '') { setTreeLoading(true) LoadGroup({ tableName: formObj.tableName }).then( res => { setTreeLoading(false) if (res.msg === 'Ok') { let arr = [] res.data.root.map(item => { arr.push(item.text) }) LoadFieldsByGroup({ tableName: formObj.tableName, groupName: arr.join(",") }).then(respone => { if (respone.msg === 'Ok') { let data = formateArrDataA(respone.data.root, 'Group') list = data setLeftData(arr || []) setSelectData(arr[0] || {}) setAllData(data) draftSort() } }) } } ) } }, [visible, flag]); const add = () => { setCreateName('') setIsModalVisible(true) } const formateArrDataA = (initialArr, name) => { // 判定传参是否符合规则 if (!(initialArr instanceof Array)) { return '请传入正确格式的数组' } if (!name) { return '请传入对象属性' } //先获取一下这个数组中有多少个"name" let nameArr = [] for (let i in initialArr) { if (nameArr.indexOf(initialArr[i][`${name}`]) === -1) { nameArr.push(initialArr[i][`${name}`]) } } //新建一个包含多个list的结果对象 let tempObj = {} // 根据不同的"name"生成多个数组 for (let k in nameArr) { for (let j in initialArr) { if (initialArr[j][`${name}`] == nameArr[k]) { // 每次外循环时新建一个对应"name"的数组, 内循环时当前数组不变 tempObj[nameArr[k]] = tempObj[nameArr[k]] || [] tempObj[nameArr[k]].push(initialArr[j]) } } } for (let key in tempObj) { let arr = [] tempObj[key].map(item => { tempObj[key] = arr; arr.push(item) }) } return tempObj } const handlerDatas = (arr) => { let obj = {}; arr.forEach((item, index) => { let { Group } = item; if (!obj[Group]) { obj[Group] = { Group, children: [] } } obj[Group].children.push(item); }); return Object.values(obj); // 最终输出 } //拖拽初始化及逻辑 const draftSort = () => { let el = document.getElementById('doctor-drag-items'); if (el) { let sortable = Sortable.create(el, { animation: 100, //动画参数 group: { name: 'shared', pull: true,// To clone: set pull to 'clone' put: false // 不允许拖拽进这个列表 }, onEnd: function (evt) { //拖拽完毕之后发生,只需关注该事件 let maxLegth = 0 let leftNewest = [] let flagData = '' setLeftData(data => { maxLegth = 225 + data.length * 45; leftNewest = data return data }) setSelectData(data => { flagData = data return data }) if (evt.originalEvent.clientX < 983 && evt.originalEvent.clientY > 225 && evt.originalEvent.clientY < maxLegth) { let index = Math.ceil((evt.originalEvent.clientY - 225) / 40) let name = evt.from.children[0].getAttribute('group') setAllData((data) => { let obj = { ...data } if (obj[name][evt.oldIndex]) { obj[leftNewest[index - 1]].push(obj[name][evt.oldIndex]) } obj[flagData].splice(evt.oldIndex, 1) return obj }) } else { let arr = []; let len = evt.from.children.length; for (let i = 0; i < len; i++) { let child = evt.from.children[i] arr.push({ ID: child.getAttribute('drag-id'), Name: child.getAttribute('drag-name'), Shape: child.getAttribute('drag-shape'), Group: child.getAttribute('group') }) } setAllData((data) => { let obj = { ...data } obj[flagData] = arr return obj }) } }, animation: 1000, direction: 'vertical', forceFallback: true, }); } } //完成拖拽 const onDrop = (info) => { const dropKey = info.node.props.eventKey; const dragKey = info.dragNode.props.eventKey; const dropPos = info.node.props.pos.split('-'); const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]); const loop = (data, key, callback) => { for (let i = 0; i < data.length; i++) { if (data[i].key === key) { return callback(data[i], i, data); } if (data[i].children) { loop(data[i].children, key, callback); } } }; const changeData = [...data]; // Find dragObject let dragObj; if (info.dragNode.top) { return } else { loop(changeData, dragKey, (item, index, arr) => { arr.splice(index, 1); dragObj = item; }); } if (!info.dropToGap) { // Drop on the content loop(data, dropKey, item => { item.children = item.children || []; // where to insert 示例添加到尾部,可以是随意位置 item.children.push(dragObj); }); } else if ( !info.dragNode.top && info.node.children && dropPosition === 1 // On the bottom gap ) { loop(data, dropKey, item => { item.children = item.children || []; // where to insert 示例添加到头部,可以是随意位置 item.children.unshift(dragObj); }); } else { let ar; let i; info.dragNode.top ? '' : loop(data, dropKey, (item, index, arr) => { ar = arr; i = index; }); if (dropPosition === -1) { info.dragNode.top ? '' : ar.splice(i, 0, dragObj); } else { info.dragNode.top ? '' : ar.splice(i + 1, 0, dragObj); } } //changeData就是拖拽结束后改变的数据格式, 需要在这里重新赋值 即可显示最新拖拽之后的结果 setData(changeData) }; /** * * @param {Array} selectedKeys 选中的key 数组存放,单多选 * @param {Node} e 被选择中的node信息,可以拿到 数据源, 层级关系等... */ // //完成选择 // const onSelect = (selectedKeys, e) => { // if (e.node.top) { // const index = data.findIndex(item => item.key === e.node.key) // setPickIndex(index) // } // else { // setPickIndex('') // } // } const del = () => { if (pickIndex !== '') { let arr = [...leftData] let newArr = { ...allData } let index = arr.findIndex(item => { return pickIndex == item }) arr.splice(index, 1) if(newArr["(未分组)"]){ newArr["(未分组)"]=newArr["(未分组)"].concat(newArr[pickIndex]) } delete newArr[pickIndex] setLeftData(arr) setAllData(newArr) } } const handleOk = () => { let arr = [...leftData] let newArr = { ...allData } if (createName !== '') { arr.push(createName) newArr[createName] = [] } setLeftData(arr) setAllData(newArr) setIsModalVisible(false) } const handleCancel = () => { setIsModalVisible(false) } const change = (e) => { setCreateName(e.target.value) } const pickData = (e, item) => { e.stopPropagation(); setSelectData(item); setPickIndex(item) } return ( <> <Modal title='字段配置' bodyStyle={{ width: '100%', minHeight: '100px', height: '40rem' }} style={{ top: '50px', left: '50px' }} width='42%' destroyOnClose maskClosable={false} cancelText="取消" okText="确认" {...props} onOk={() => onSubmit()} confirmLoading={loading} forceRender={true} getContainer={false} > {visible && ( <Spin tip="loading..." spinning={treeLoading}> <div className={styles.cardList}> {/* <Card bordered={true} extra={<div style={{ display: 'flex' }}><Button onClick={add} style={{ display: 'flex', alignItems: 'center', marginRight: '1rem' }}>添加分组<PlusOutlined /></Button><Button danger onClick={del} style={{ display: 'flex', alignItems: 'center' }}>删除分组<DeleteOutlined /></Button> </div>} style={{ width: '100%' }}> <Tree draggable //是否可以拖拽 blockNode //是否节点占据一行 showLine // 是否展示连接线 treeData={data} //数据源 格式 Array 每项的数据格式Object { key:..., title:...,... } onDrop={onDrop} //拖拽结束后触发的回调函数 onSelect={onSelect} // 选中某一级的回调函数 /> </Card> */} <div style={{ display: 'flex', width: '96.4%', justifyContent: 'flex-end' }}><Button onClick={add} style={{ display: 'flex', alignItems: 'center', marginRight: '1rem' }}>添加分组<PlusOutlined /></Button><Button danger onClick={del} style={{ display: 'flex', alignItems: 'center' }}>删除分组<DeleteOutlined /></Button> </div> <div className={styles.listCard}> <div className={styles.cardItem} style={{ borderRight: '1px solid #99bbe8' }}> <div className={styles.doctorTable}> <table> <thead> <tr> <td>组名称</td> </tr> </thead> <tbody id='doctor-drag-items1'> {leftData && leftData.length > 0 ? leftData.map((item, index) => { return <tr className={classnames({ [styles.defaultTile]: true, [styles.activeTile]: pickIndex==item, })} onClick={e => pickData(e, item)} drag-id={item} key={index} style={{ cursor: 'pointer' }}> <td><span title={item}>{item}</span></td> </tr> }) : <tr><td colSpan='12' style={{ textAlign: 'center' }}>暂无数据</td></tr> } </tbody> </table> </div> </div> <div className={styles.cardItem}> <div className={styles.cardContent}> <div className={styles.doctorTable}> <table> <thead> <tr> <td>字段名</td> <td>形态</td> </tr> </thead> <tbody id='doctor-drag-items'> {allData[selectData] && allData[selectData].length > 0 ? allData[selectData].map((item, index) => { return <tr drag-id={item.ID} drag-name={item.Name} drag-shape={item.Shape} key={index} group={item.Group} style={{ cursor: 'move' }}> <td><span title={item.Name}>{item.Name}</span></td> <td><span title={item.Shape}>{item.Shape}</span></td> </tr> }) : <tr><td colSpan='12' style={{ textAlign: 'center' }}>暂无数据</td></tr> } </tbody> </table> </div> </div> </div> </div> </div> </Spin>)} </Modal> <Modal title="添加分组" style={{ top: '200px', left: '50px' }} visible={isModalVisible} onOk={handleOk} onCancel={handleCancel}> <Input value={createName} className="site-input-right" onChange={change} style={{ width: 400, }} placeholder="请输入分组名称" /> </Modal> </> ); }; export default AddModal;