import React, { useState, useEffect } from 'react'; import { Modal, Spin, Table, Button, notification, Form, Input } from 'antd'; import { PlusOutlined, DeleteOutlined, EditOutlined } from '@ant-design/icons'; import { HTML5Backend } from 'react-dnd-html5-backend'; import { DndProvider } from 'react-dnd'; import { LoadFieldsByGroup, LoadGroup, ChangeOrder } from '@/services/tablemanager/tablemanager'; import DraggableBodyRow from './DraggableBodyRow'; import styles from './index.less'; const LoadGroupNew = props => { const { onCancel, visible, formObj, callBackSubmit } = props; const [groupData, setGroupData] = useState(null); // 分组后的数组 const [pickIndex, setPickIndex] = useState(0); // 当前选中的索引 const [loading, setLoading] = useState(false); // 数据是否加载完毕 const [isModalVisible, setIsModalVisible] = useState(false); // 添加分组弹窗是否显示 const [dragType, setDragType] = useState(); // 拖拽的是分组还是字段 const [modalType, setModalType] = useState(); // 模态类型 const [form] = Form.useForm(); useEffect(() => { if (visible) { // 获取分组名称 let p1 = new Promise((resolve, reject) => { setLoading(true); LoadGroup({ tableName: formObj.tableName }) .then(res => { setLoading(false); if (res.code === 0) { resolve(res); } else { reject(res); } }) .catch(err => { reject(err); setLoading(false); }); }); p1.then(res => { // 获取字段数据 let arr = res.data.root.map(item => item.text); LoadFieldsByGroup({ tableName: formObj.tableName, groupName: arr.join(','), }).then(response => { setLoading(false); if (response.code === 0) { res.data.root.forEach(item => { item.fieldData = []; response.data.root.forEach(element => { if (element.Group === item.text) { item.fieldData.push(element); } }); }); setGroupData(res.data.root); } }); }); } }, [visible]); const columns = [ { title: '字段名', dataIndex: 'Name', width: 250, key: 'Name', }, { title: '形态', dataIndex: 'Shape', width: 120, key: 'Shape', }, ]; const columnsGroup = [ { title: '组名称', dataIndex: 'text', key: 'text', render: (text, record) => ( <div> {text} <span>({record.fieldData.length})</span> </div> ), }, ]; const components = { body: { row: DraggableBodyRow, }, style: { backgroundColor: 'red', }, }; // 提交 const onSubumit = () => { setLoading(true); let arr = []; groupData.forEach(item => { item.fieldData.forEach(ele => { arr.push({ groupName: item.text, ID: ele.ID }); }); }); ChangeOrder(arr).then(res => { setLoading(false); if (res.code === 0) { notification.success({ message: '提示', duration: 3, description: '编辑成功', }); callBackSubmit(); } else { notification.error({ message: '提示', duration: 3, description: res.msg, }); } }); }; // 移动数组元素到指定位置 const moveInArray = (arr, from, to) => { // 确保是有效数组 if (Object.prototype.toString.call(arr) !== '[object Array]') { throw new Error('Please provide a valid array'); } // 删除当前的位置 let item = arr.splice(from, 1); // 确保还剩有元素移动 if (!item.length) { throw new Error(`There is no item in the array at index ${from}`); } // 移动元素到指定位置 arr.splice(to, 0, item[0]); return arr; }; // 拖拽表格 const moveRow = (dragIndex, hoverIndex, tableType, dragTypes) => { // console.log(dragIndex, hoverIndex, tableType, dragTypes); if (dragTypes === 'field') { // 拖拽体为字段 if (tableType === 'field') { // 字段换位 setGroupData(val => { let newData = JSON.parse(JSON.stringify(val)); newData[pickIndex].fieldData = moveInArray( newData[pickIndex].fieldData, dragIndex, hoverIndex, ); return newData; }); } else { // 字段拖拽到组 if (hoverIndex === pickIndex) { return; } setGroupData(val => { let newData = JSON.parse(JSON.stringify(val)); newData[hoverIndex].fieldData.push(newData[pickIndex].fieldData[dragIndex]); newData[pickIndex].fieldData.splice(dragIndex, 1); return newData; }); } } else { // 组拖拽 setGroupData(val => { let newData = JSON.parse(JSON.stringify(val)); newData = moveInArray(newData, dragIndex, hoverIndex); return newData; }); setPickIndex(hoverIndex); } }; // 点击行添加样式 const setRowClassName = (record, index) => (index === pickIndex ? styles.clickRowStyle : ''); // 新增分组 const addGroup = type => { setModalType(type); if (type === 'add') { form.resetFields(); } else { form.setFieldsValue({ groupName: groupData[pickIndex].text }); } setIsModalVisible(true); }; // 删除分组 const delGroup = () => { if (groupData[pickIndex].text === '(未分组)') { notification.error({ message: '提示', duration: 3, description: '默认分组不能删除', }); return; } setGroupData(val => { let newData = JSON.parse(JSON.stringify(val)); let defaultGroupIndex = newData.findIndex(item => item.text === '(未分组)'); newData[defaultGroupIndex].fieldData = [ ...newData[defaultGroupIndex].fieldData, ...newData[pickIndex].fieldData, ]; newData.splice(pickIndex, 1); // 删除后指向未分组 setPickIndex(defaultGroupIndex); return newData; }); }; // 保存新建分组 const handleOk = () => { if (!form.getFieldsValue().groupName) { notification.error({ message: '提示', duration: 3, description: '请填写组名', }); return; } // 判断是否有重复的组名 let isRepeat = groupData.some(item => item.text === form.getFieldsValue().groupName); if (isRepeat) { notification.error({ message: '提示', duration: 3, description: '该组名已存在', }); return; } if (modalType === 'add') { let obj = { text: form.getFieldsValue().groupName, fieldData: [], }; setGroupData(val => { let newData = JSON.parse(JSON.stringify(val)); newData.push(obj); return newData; }); } else { setGroupData(val => { let newData = JSON.parse(JSON.stringify(val)); newData[pickIndex].text = form.getFieldsValue().groupName; return newData; }); } setIsModalVisible(false); }; return ( <div> <Modal title="字段配置" visible={visible} onOk={onSubumit} onCancel={onCancel} maskClosable={false} destroyOnClose width="680px" > <div className="button_content" style={{ display: 'flex', justifyContent: 'flex-end', marginBottom: '10px', marginRight: '11px', }} > <Button onClick={() => addGroup('add')} style={{ display: 'flex', alignItems: 'center', marginRight: '1rem', }} > 添加分组 <PlusOutlined /> </Button> <Button disabled={pickIndex === 0} type="primary" ghost onClick={() => addGroup('edit')} style={{ display: 'flex', alignItems: 'center', marginRight: '1rem', }} > 编辑分组 <EditOutlined /> </Button> <Button danger disabled={pickIndex === 0} onClick={delGroup} style={{ display: 'flex', alignItems: 'center' }} > 删除分组 <DeleteOutlined /> </Button>{' '} </div> <Spin spinning={loading}> <DndProvider backend={HTML5Backend}> {groupData && ( <div className="table_box" style={{ display: 'flex', justifyContent: 'center', height: '550px', marginBottom: '20px', }} > {/* 组名称表 */} <Table bordered rowKey={record => record.text} style={{ width: '200px' }} columns={columnsGroup} dataSource={groupData} components={components} size="small" scroll={{ y: 510 }} pagination={false} rowClassName={(record, index) => setRowClassName(record, index)} onRow={(record, index) => ({ tableType: 'group', index, pickIndex, dragType, onMouseEnter: event => { setDragType('group'); }, // 点击行 moveRow, onClick: event => { event.stopPropagation(); setPickIndex(index); }, // 点击行 })} /> <div className="line" style={{ width: '1px', backgroundColor: 'rgb(153, 187, 232)', margin: '0 15px', }} /> {/* 字段名表 */} <Table bordered columns={columns} style={{ width: '400px' }} rowKey={record => record.Name} dataSource={groupData[pickIndex].fieldData} components={components} size="small" pagination={false} scroll={{ y: 510 }} onRow={(record, index) => ({ tableType: 'field', pickIndex, dragType, index, onMouseEnter: event => { setDragType('field'); }, // 点击行 moveRow, })} /> </div> )} </DndProvider> </Spin> {/* 添加分组弹窗 */} <Modal title={modalType === 'add' ? '添加分组' : '编辑分组'} style={{ top: '200px' }} visible={isModalVisible} maskClosable={false} onOk={() => handleOk()} onCancel={() => { setIsModalVisible(false); form.resetFields(); }} > <Form form={form} labelCol={{ span: 5 }} wrapperCol={{ span: 18 }} initialValues={{ remember: true }} > <Form.Item label="添加分组" name="groupName"> <Input placeholder="请输入分组名称" /> </Form.Item> </Form> </Modal> </Modal> </div> ); }; export default LoadGroupNew;