Commit 35381dc1 authored by 张烨's avatar 张烨

feat: baseTable

parent ca30c991
......@@ -98,7 +98,7 @@ module.exports = {
'require-yield': 0,
'no-param-reassign': 0,
'prefer-const': 0,
'button-has-type': 1,
'button-has-type': 0,
},
settings: {
'import/resolver': {
......
......@@ -3,4 +3,49 @@ title: 基础组件
nav:
title: 组件
order: 1
---
\ No newline at end of file
---
```jsx
import React from 'react'
import BaseTable from '../../src/components/BaseTable'
const searchBar = {}
const BaseTableDemo = () => {
const dataSource = [...Array(50).keys()].map(i => ({
key: i,
name: `name${i}`,
age: (Math.random() * 20 + 18).toFixed(0),
height: (Math.random() * 20 + 160).toFixed(0)
}))
const columns = [{
title: '序号',
dataIndex: 'key',
render: (text, record, index) => {
return <span> {Number(text) + 1} </span>
}
}, {
title: '姓名',
dataIndex: 'name',
}, {
title: '年龄',
dataIndex: 'age',
},{
title: '身高',
dataIndex: 'height',
}]
return (
<BaseTable
// searchBar={searchBar}
// operation={operation}
dataSource={dataSource}
columns={columns}
resizable={true}
// components={components}
// onRequest={onRequest}
// onFilter={onFilter}
/>)
}
export default BaseTableDemo
```
\ No newline at end of file
......@@ -91,6 +91,7 @@
"history": "4.9.0",
"hoist-non-react-statics": "3.3.0",
"immer": "3.0.0",
"immutable": "^4.0.0-rc.12",
"intl": "1.2.5",
"invariant": "2.2.4",
"ip": "1.1.5",
......@@ -102,14 +103,14 @@
"react-helmet": "6.0.0-beta",
"react-intl": "2.8.0",
"react-redux": "7.0.2",
"react-resizable": "^1.11.0",
"react-router-dom": "5.0.0",
"redux": "4.0.1",
"redux-saga": "1.0.2",
"reselect": "4.0.0",
"sanitize.css": "8.0.0",
"styled-components": "4.2.0",
"use-merge-value": "^1.0.2",
"immutable": "^4.0.0-rc.12"
"use-merge-value": "^1.0.2"
},
"devDependencies": {
"@ant-design/icons": "^4.0.0",
......@@ -163,6 +164,7 @@
"file-loader": "3.0.1",
"html-loader": "0.5.5",
"html-webpack-plugin": "3.2.0",
"http-proxy-middleware": "^1.0.6",
"husky": "^2.3.0",
"image-webpack-loader": "4.6.0",
"imports-loader": "0.8.0",
......@@ -216,7 +218,6 @@
"webpack-hot-middleware": "2.24.3",
"webpack-pwa-manifest": "4.0.0",
"whatwg-fetch": "3.0.0",
"yorkie": "^2.0.0",
"http-proxy-middleware": "^1.0.6"
"yorkie": "^2.0.0"
}
}
import React from 'react';
import { Form, Button, Select, Input } from 'antd';
import { useForm, useEffect } from 'antd/lib/form/Form';
export const BaseButtonGroup = props => {
const { buttons, wrapper = false } = props;
const bts = buttons.map(bt => {
const { text, ...rest } = bt;
return <Button {...rest}>{text}</Button>;
});
if (wrapper) {
const { Comp, props: wrapperProps } = wrapper;
return <Comp {...wrapperProps}>{bts}</Comp>;
}
return bts;
};
export const BaseFormItem = itemOption => {
const { type, ...rest } = itemOption;
switch (type) {
case 'input':
// eslint-disable-next-line no-undef
return <Input allowClear {...rest} />;
case 'select':
// eslint-disable-next-line no-undef
return <Select {...rest} />;
default:
return null;
}
};
/**
* 基本表单
* @param {*} props
* items: 每个表单项
* buttons: 表单按钮
*/
const BaseForm = props => {
const {
items,
buttons = [],
buttonGroupProps = {},
getForm, // 用来获取表单实例
formProps,
} = props;
const [form] = useForm();
useEffect(() => {
// 执行回调让外部组件拿到表单实例
// eslint-disable-next-line no-unused-expressions
getForm && getForm(form);
}, []);
return (
<Form layout="horizontal" size="small" form={form} {...formProps}>
{items.map(item => {
const {
label,
dataIndex,
initialValue = '',
rules = [],
formItemProps = {},
...rest
} = item;
return (
<Form.Item
label={label}
name={dataIndex}
key={`formItem_${dataIndex}`}
rules={rules}
initialValue={initialValue}
{...formItemProps}
>
<BaseFormItem {...rest} />
</Form.Item>
);
})}
<BaseButtonGroup
buttons={buttons}
wrapper={{ Comp: Form.Item, props: buttonGroupProps }}
/>
</Form>
);
};
export default BaseForm;
// eslint-disable-next-line button-has-type
import React, { useState, useEffect } from 'react';
import BaseForm from '../../BaseForm';
const SearchBar = props => {
const { items, buttons, onCommit } = props;
const [form, setForm] = useState(null);
const getForm = f => {
setForm(f);
};
useEffect(() => {
if (form) {
form.onFinish = values => {
onCommit(values);
};
}
}, []);
return (
<BaseForm
items={items}
buttons={buttons}
layout="horizontal"
getForm={getForm}
/>
);
};
export default SearchBar;
.base-table{
width: 100%;
height: 100%;
}
\ No newline at end of file
import React, { useEffect, useState } from 'react';
// import OperationBar from './OperationBar'
import { Table } from 'antd';
import { Resizable } from 'react-resizable';
import SearchBar from './SearchBar'
import styles from './baseTable.less';
const ResizableTitle = props => {
const { onResize, width, ...restProps } = props;
if (!width) {
return <th {...restProps} />;
}
return (
<Resizable
width={width}
height={0}
handle={
<span
className="react-resizable-handle"
onClick={e => {
e.stopPropagation();
}}
/>
}
onResize={onResize}
draggableOpts={{ enableUserSelectHack: false }}
>
<th {...restProps} />
</Resizable>
);
};
// 表格头变形的hook
const useResizableClumns = (clumns) => {
if (!clumns) return null;
const [clmns, setClmns] = useState(clumns)
const handleResize = (index) => (e, { size }) => {
const nextClmns = [...clmns]
nextClmns[index] = {
...nextClmns[index],
width: size.width
}
setClmns(nextClmns)
}
return clmns.map((col, index) => ({
...col,
onHeaderCell: column => ({
width: column.width,
onResize: handleResize(index),
}),
}));
}
// 渲染列表组件
const renderComponents = (componentOption = {}) => {
const defaultComponents = {
header: {
cell: ResizableTitle,
}
}
return {
...defaultComponents,
...componentOption,
}
}
// 过滤列表数据
const filterData = (datas, searches, searchVal) => {
return datas.filter(data => {
return searches.some(s => s.filter(data[s.dataIndex], searchVal[s.dataIndex]))
})
}
const BaseTable = (props) => {
const { searchBar, // 筛选栏属性{list: [{filter: () => boolean, key, dataIndex, label, type, initialValue?, options?}]}
operation, // 操作栏属性,可选
dataSource, // 数据源,可选
columns, // 列,必填
resizable, // 列宽是否可调整,可选
components, // 自定义table渲染,同antd/table, 可选
onRequest, // 请求数据接口,非必须,需返回Promise<{data, pagenation}>,可选,与dataSource冲突,优先onRequest
onSearchCommit, // 筛选回调, 可选
// onPageChange, // 翻页时回调
...restProps } = props
const resizableClumns = resizable ? useResizableClumns(columns) : columns
const [dataList, setDataList] = useState(dataSource || [])
const [pagenation, setPageNation] = useState({})
const [loading, setLoading] = useState(false)
const [seachVal, setSearchVal] = useState({})
const fetch = (page, search) => {
search = search || seachVal
if (onRequest) {
setLoading(true)
onRequest(page || pagenation, search).then(res => {
console.log(res)
setDataList(searchBar ? filterData(res.data, searchBar.list, search) : res.data)
setPageNation(res.pagenation)
setLoading(false)
})
} else {
setDataList(searchBar ? filterData(dataSource, searchBar.list, search) : dataSource)
setPageNation(page)
}
}
const handleChange = (page) => {
fetch(page)
}
const handleSearchCommit = (value) => {
console.log(value)
}
useEffect(() => {
fetch(pagenation)
}, [dataSource])
return <div className={styles.BaseTable}>
{searchBar?.list?.length > 0 && <SearchBar {...searchBar} onCommit={handleSearchCommit} />}
<Table dataSource={dataList}
loading={loading}
components={renderComponents(components)}
columns={resizableClumns}
onChange={handleChange}
{...restProps}
/>
</div>
}
export default BaseTable
\ No newline at end of file
......@@ -12,7 +12,7 @@ import {
} from 'antd';
import { PageContainer } from '@ant-design/pro-layout';
import { connect } from 'react-redux';
import { get, post } from 'services';
import { get, post } from '../../services';
const { Option } = Select;
const formLables = {
......
import React, { useEffect, useState } from 'react';
import { Card, Button, Table, Space, Modal } from 'antd';
import { PageContainer } from '@ant-design/pro-layout';
import { get } from 'services';
import { get } from '../../services';
const ManagementDataBase = () => {
const [autoCheckList, setAutoCheckList] = useState([]);
......@@ -9,9 +9,9 @@ const ManagementDataBase = () => {
const [logList, setLogList] = useState([]);
const [checkLoading, setCheckLoading] = useState(false);
const [logLoading, setLogLoading] = useState(false);
const [modalVisible, setModalVisible] = useState(false); //弹窗
const [modalVisible, setModalVisible] = useState(false); // 弹窗
const [content, setContent] = useState(null);
//检查数据库表
// 检查数据库表
useEffect(() => {
setCheckLoading(true);
get(`/Cityinterface/rest/services/OMS.svc/TableCheck`, {
......
import React, { useState } from 'react';
import { Form, Input, Button, Space, Select, Col } from 'antd';
import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
import { get, post } from 'services';
import { get, post } from '../../services';
const methods = [
{ label: 'get', value: 'get' },
......
......@@ -18,6 +18,10 @@ export default {
},
],
},
{
path: '/test/request',
component: RequestTest,
},
{
path: '/',
component: BasicLayout,
......
declare module '*.css';
declare module '*.less';
declare module '*.scss';
declare module '*.sass';
declare module '*.svg';
declare module '*.png';
declare module '*.jpg';
declare module '*.jpeg';
declare module '*.gif';
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment