项目背景 : react + ant
需求 : 点击表头设置弹窗 , 拖拽可控制外部表格列的排序 , 开关可控制外部表格列的显示和隐藏
实现效果如下 :
注意 : 1. 拖拽效果参考了ant-table中的拖拽效果(这块代码放最后)
2. 后台反了json格式(用is_show控制显示和隐藏 , 我给他传递sort值来控制排序 , 后台返回格式如下~)
3. 将拖拽和显示隐藏后的内容存到了localStorage
实现 :
const [biaotouData, setBiaotouData] = useState([{key: 'orderNumber',orderNumber: '工单编号'},{key: 'placeName',orderNumber: '地点'},
.....])const biaotouColumns = [{render: () => <DragHandle /> // 让拖拽图标在第一列}, {title: (<span style={{ color: dropdownOpen1 ? ' var(--main-bg)' : '#333' }}>{t('HeaderColumn')}</span>),dataIndex: 'orderNumber',align: 'center',key: 'orderNumber'},{title: (<span style={{ color: dropdownOpen2 ? ' var(--main-bg)' : '#333' }}>{t('WhetherDisplayed')}</span>),align: 'center',dataIndex: 'placeName',key: 'placeName',render: (data, record) => (<div><Switchchecked={getIsShowForColumn(record.key)} // 使用getIsShowForColumn函数获取当前列的is_show状态onChange={data => handleSwitchChange(record, data)}/></div>)}]const sortedColumns = sortColumnsBySort(tableColumns) // 排序后的列,传递给外部的tableconst [biaotouModal, setBiaotouModal] = useState(false) // 控制表头设置的显示隐藏const [sortData, setSortData] = useState() //拿到表头列的显示状态// 打开表头设置弹窗const biaotouHandle = async () => {setBiaotouModal(true)const res = await getList7({ type: 3 })console.log('res.titleSetContent', res.titleSetContent)setSortData(JSON.parse(res.titleSetContent))}// 排序function sortColumnsBySort (columns) {return columns.sort((a, b) => a.sort - b.sort)}// 在渲染Switch的地方,查找当前列对应的is_show值const getIsShowForColumn = columnName => {return sortData?.find(item => item.name === columnName)?.is_show ?? true // 如果找不到,默认为true}// 当拖拽和显示和隐藏后外部表格更新useEffect(() => {if (sortData) {const updateAndHandleResponse = async () => {const res = await getEditMethod3({titleSetContent: JSON.stringify(sortData),type: 3})localStorage.setItem('hiddenColumns1', JSON.stringify(sortData))const updatedColumns = tableColumns.map(column => {if (sortData.find(item => item.name === column.key && item.is_show === false)) {return { ...column, hidden: true }} else if (sortData.find(item => item.name === column.key && item.is_show === true)) {return { ...column, hidden: false }}return column})setTableColumns(updatedColumns)}updateAndHandleResponse()}}, [sortData, biaotouModal])// 当拖拽和显示和隐藏后外部表格更新useEffect(() => {const storedHiddenColumns = localStorage.getItem('hiddenColumns1')if (storedHiddenColumns) {const hiddenColumns = JSON.parse(storedHiddenColumns)const updatedTableColumns = tableColumns.map(column => {if (hiddenColumns.find(item => item.name === column.key && item.is_show === false)) {return { ...column, hidden: true }} else if (hiddenColumns.find(item => item.name === column.key && item.is_show === true)) {return { ...column, hidden: false }}return column})setTableColumns(updatedTableColumns)}return () => {}}, [])
------------------------------------------------这是表头设置的table 和 外部的table 和 拖拽代码--------------
// 表头设置里的table <DndContextmodifiers={[restrictToVerticalAxis]}onDragEnd={onDragEnd}><SortableContextitems={biaotouData.map(i => i?.key)}strategy={verticalListSortingStrategy}><SimpleBarstyle={{maxHeight: '600px',overflowY: 'auto',display: 'block'}}className='SimpleBar'><Tablecolumns={biaotouColumns}dataSource={biaotouData}loading={loading}pagination={false}components={{body: {row: Row1}}}rowKey='key'></Table></SimpleBar></SortableContext></DndContext>// 外部的table{TableCom2({ loading, data, columns: sortedColumns })}//被拖拽后const onDragEnd = ({ active, over }) => {console.log('active', active)if (active.id !== over?.id) {setBiaotouData(biaotouData => {const activeIndex = biaotouData.findIndex(item => item?.key === active.id)const overIndex = biaotouData.findIndex(item => item?.key === over?.id)const newData = arrayMove(biaotouData, activeIndex, overIndex).map((item, index) => ({...item,sort: index + 1}))// 创建一个新的映射以方便查找const keyToSortMap = newData.reduce((map, item) => {map[item.key] = item.sortreturn map}, {})console.log('keyToSortMap', keyToSortMap)// 遍历sortData,根据name查找对应的新Data中的sort值并赋值sortData.forEach(item => {if (item.name in keyToSortMap) {item.sort = keyToSortMap[item.name]}})// 遍历sortData,根据name查找对应的新Data中的sort值并赋值tableColumns.forEach(item => {if (item.key in keyToSortMap) {item.sort = keyToSortMap[item.key]}})setTableColumns(tableColumns)localStorage.setItem('hiddenColumns1', JSON.stringify(sortData))console.log('Updated sortData:', sortData)console.log('sortData', sortData)console.log('newData', newData)console.log('tableColumns', tableColumns)getEditMethod3({titleSetContent: JSON.stringify(sortData),type: 3})return arrayMove(biaotouData, activeIndex, overIndex)})}}//控制是否可以选中表格里的文字
const Row1 = props => {const {attributes,listeners,setNodeRef,setActivatorNodeRef,transform,transition,isDragging} = useSortable({id: props['data-row-key']})const style = {...props.style,transform: CSS.Translate.toString(transform),transition,...(isDragging? {position: 'relative',zIndex: 9999}: {})}const contextValue = useMemo(() => ({setActivatorNodeRef,listeners}),[setActivatorNodeRef, listeners])return (<RowContext.Provider value={contextValue}><tr {...props} ref={setNodeRef} style={style} {...attributes} /></RowContext.Provider>)
}//拖拽图标
const DragHandle = () => {const { setActivatorNodeRef, listeners } = useContext(RowContext)return (<Buttontype='text'size='small'icon={<HolderOutlined />}style={{cursor: 'move'}}ref={setActivatorNodeRef}{...listeners}/>)
}