diff --git a/web-react/public/seed/form-tabs/index.jsx b/web-react/public/seed/form-tabs/index.jsx
new file mode 100644
index 0000000..eb0a9c4
--- /dev/null
+++ b/web-react/public/seed/form-tabs/index.jsx
@@ -0,0 +1,141 @@
+import React, { Component } from 'react'
+import { Button, Tabs } from 'antd'
+import { ComponentDynamic, Container } from 'components'
+import { isEqual } from 'lodash'
+
+const tabs = [
+ {
+ title: '标题',
+ component: () => import('./tab'),
+ show: true,
+ },
+]
+
+export default class index extends Component {
+ state = {
+ actived: '0',
+ loading: true,
+ record: null,
+ saving: false,
+ }
+
+ // 子表单实例集合
+ children = []
+
+ // 整合提交数据
+ formData = {}
+
+ /**
+ * 阻止外部组件引发的渲染,提升性能
+ * 可自行添加渲染条件
+ * [必要]
+ * @param {*} props
+ * @param {*} state
+ * @returns
+ */
+ shouldComponentUpdate(props, state) {
+ return !isEqual(this.state, state)
+ }
+
+ /**
+ * DOM加载完成钩子,可在此获取详细数据赋值到record
+ */
+ componentDidMount() {}
+
+ async onSubmit() {
+ for (const child of this.children) {
+ try {
+ const data = await child.getData()
+ this.formData = {
+ ...this.formData,
+ ...data,
+ }
+ } catch (e) {
+ return e
+ }
+ }
+
+ //#region 提交数据
+ this.setState({ saving: true })
+ this.setState({ saving: false })
+ //#endregion
+ }
+
+ render() {
+ const { actived, loading, record, saving } = this.state
+
+ return (
+
+
+ {/* 底部工具栏(需放在前面) */}
+
+
+
+
+
+
+
+
+
+
+
+ {/* 顶部信息栏,不需要时刻删除 */}
+
+
+
{
+ this.setState({ actived: activeKey })
+ }}
+ >
+ {tabs.map(
+ (tab, i) =>
+ tab.show && (
+
+ )
+ )}
+
+
+ {tabs.map((tab, i) => {
+ if (tab.show) {
+ return (
+
+ this.children.push(c)}
+ />
+
+ )
+ }
+ return <>>
+ })}
+
+
+
+
+ )
+ }
+}
diff --git a/web-react/public/seed/form-tabs/tab/index.jsx b/web-react/public/seed/form-tabs/tab/index.jsx
new file mode 100644
index 0000000..ee18b7a
--- /dev/null
+++ b/web-react/public/seed/form-tabs/tab/index.jsx
@@ -0,0 +1,124 @@
+import React, { Component } from 'react'
+import ReactDOM from 'react-dom'
+import { Anchor, Card, Col, Row, Spin } from 'antd'
+import { AntIcon, ComponentDynamic, Container } from 'components'
+import { isEqual } from 'lodash'
+
+const parts = [
+ {
+ // title: '标题',
+ component: () => import('./part'),
+ },
+]
+
+export default class index extends Component {
+ // 子表单实例集合
+ children = []
+
+ // 整合提交数据
+ formData = {}
+
+ // 锚点挂载DOM
+ container = window
+
+ /**
+ * 阻止外部组件引发的渲染,提升性能
+ * 可自行添加渲染条件
+ * [必要]
+ * @param {*} props
+ * @param {*} state
+ * @returns
+ */
+ shouldComponentUpdate(props, state) {
+ return !isEqual(this.state, state) || this.props.loading !== props.loading
+ }
+
+ /**
+ * DDOM加载完成钩子,在此将自身传递给父级
+ */
+ componentDidMount() {
+ if (this.props.onRef) {
+ this.props.onRef(this)
+ }
+ }
+
+ /**
+ * 从下级组件获取表单数据,并传递给更上级组件
+ * [异步,必要]
+ * @returns
+ */
+ async getData() {
+ for (const child of this.children) {
+ const data = await child.getData()
+ this.formData = {
+ ...this.formData,
+ ...data,
+ }
+ }
+ return this.formData
+ }
+
+ /**
+ * 设置锚点容器
+ * [非必要]
+ * @param {*} container
+ */
+ setContainer(container) {
+ this.container = (ReactDOM.findDOMNode(container) || {}).parentNode
+ }
+
+ /**
+ * 渲染
+ * 当前渲染结构已完善,非必要可以不用修改
+ * [必要]
+ * @returns
+ */
+ render() {
+ const { id, loading } = this.props
+
+ return (
+ this.setContainer(e)}>
+
+
+
+
+
+ {parts.map((item, i) => (
+
+ ))}
+
+
+ {/* 锚点,如果不需要可以删除以下节点 */}
+
+ this.container}
+ offsetTop={24}
+ targetOffset={100}
+ wrapperStyle={{ backgroundColor: 'transparent' }}
+ onClick={e => e.preventDefault()}
+ >
+ {parts.map((part, i) => (
+
+ ))}
+
+
+
+
+ )
+ }
+}
diff --git a/web-react/public/seed/form-tabs/tab/parts.jsx b/web-react/public/seed/form-tabs/tab/parts.jsx
new file mode 100644
index 0000000..0785128
--- /dev/null
+++ b/web-react/public/seed/form-tabs/tab/parts.jsx
@@ -0,0 +1,111 @@
+import React, { Component } from 'react'
+import { Form, Spin } from 'antd'
+import { AntIcon } from 'components'
+import { cloneDeep, isEqual } from 'lodash'
+
+const initialValues = {}
+
+const layout = {
+ labelCol: { flex: '150px' },
+ wrapperCol: { flex: '1' },
+}
+
+export default class part extends Component {
+ state = {
+ loading: true,
+ codes: {},
+ options: {},
+ }
+
+ // 表单实例
+ form = React.createRef()
+
+ // 初始化数据
+ record = {}
+
+ /**
+ * 阻止外部组件引发的渲染,提升性能
+ * 可自行添加渲染条件
+ * [必要]
+ * @param {*} props
+ * @param {*} state
+ * @returns
+ */
+ shouldComponentUpdate(props, state) {
+ return !isEqual(this.state, state)
+ }
+
+ /**
+ * DOM加载完成钩子,在此将自身传递给父级,并且绑定数据
+ */
+ componentDidMount() {
+ if (this.props.onRef) {
+ this.props.onRef(this)
+ }
+ this.fillData({
+ record: this.props.record,
+ })
+ }
+
+ /**
+ * 填充数据
+ * 可以在设置this.record之后对其作出数据结构调整
+ * [异步,必要]
+ * @param {*} params
+ */
+ async fillData(params) {
+ this.record = cloneDeep(params.record)
+ //#region 从后端转换成前段所需格式
+ //#endregion
+ this.form.current.setFieldsValue(this.record)
+
+ this.setState({
+ loading: false,
+ })
+ }
+
+ /**
+ * 获取数据
+ * 可以对postData进行数据结构调整
+ * [异步,必要]
+ * @returns
+ */
+ async getData() {
+ const form = this.form.current
+
+ const valid = await form.validateFields()
+ if (valid) {
+ const postData = form.getFieldsValue()
+ //#region 从前段转换后端所需格式
+ //#endregion
+ return postData
+ }
+ }
+
+ //#region 自定义方法
+ /**
+ * 表单change事件处理,包括了所有字段的change
+ * [异步,非必要]
+ * @param {*} changedValues
+ * @param {*} allValues
+ */
+ async onValuesChange(changedValues, allValues) {}
+ //#endregion
+
+ render() {
+ const { loading } = this.state
+
+ return (
+ }>
+
+
+ )
+ }
+}
diff --git a/web-react/public/seed/form/index.jsx b/web-react/public/seed/form/index.jsx
new file mode 100644
index 0000000..c2d80e4
--- /dev/null
+++ b/web-react/public/seed/form/index.jsx
@@ -0,0 +1,159 @@
+import React, { Component } from 'react'
+import ReactDOM from 'react-dom'
+import { Anchor, Button, Card, Col, Row, Spin } from 'antd'
+import { AntIcon, ComponentDynamic, Container } from 'components'
+import { isEqual } from 'lodash'
+
+const parts = [
+ {
+ // title: '标题',
+ component: () => import('./part'),
+ },
+]
+
+export default class index extends Component {
+ state = {
+ loading: true,
+ record: null,
+ saving: false,
+ }
+
+ // 子表单实例集合
+ children = []
+
+ // 整合提交数据
+ formData = {}
+
+ // 锚点挂载DOM
+ container = window
+
+ /**
+ * 阻止外部组件引发的渲染,提升性能
+ * 可自行添加渲染条件
+ * [必要]
+ * @param {*} props
+ * @param {*} state
+ * @returns
+ */
+ shouldComponentUpdate(props, state) {
+ return !isEqual(this.state, state)
+ }
+
+ /**
+ * DOM加载完成钩子,可在此获取详细数据赋值到record
+ */
+ componentDidMount() {}
+
+ /**
+ * 提交
+ * [异步,必要]
+ * @returns
+ */
+ async onSubmit() {
+ for (const child of this.children) {
+ try {
+ const data = await child.getData()
+ this.formData = {
+ ...this.formData,
+ ...data,
+ }
+ } catch (e) {
+ return e
+ }
+ }
+
+ //#region 提交数据
+ this.setState({ saving: true })
+ this.setState({ saving: false })
+ //#endregion
+ }
+
+ /**
+ * 设置锚点容器
+ * [非必要]
+ * @param {*} container
+ */
+ setContainer(container) {
+ this.container = (ReactDOM.findDOMNode(container) || {}).parentNode
+ }
+
+ /**
+ * 渲染
+ * 当前渲染结构已完善,非必要可以不用修改
+ * [必要]
+ * @returns
+ */
+ render() {
+ const { id } = this.props
+
+ const { loading, record, saving } = this.state
+
+ return (
+
+
this.setContainer(e)}>
+
+
+
+
+
+ {parts.map((item, i) => (
+
+ ))}
+
+
+ {/* 锚点,如果不需要可以删除以下节点 */}
+
+ this.container}
+ offsetTop={24}
+ targetOffset={100}
+ wrapperStyle={{ backgroundColor: 'transparent' }}
+ onClick={e => e.preventDefault()}
+ >
+ {parts.map((part, i) => (
+
+ ))}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+ }
+}
diff --git a/web-react/public/seed/form/part.jsx b/web-react/public/seed/form/part.jsx
new file mode 100644
index 0000000..0785128
--- /dev/null
+++ b/web-react/public/seed/form/part.jsx
@@ -0,0 +1,111 @@
+import React, { Component } from 'react'
+import { Form, Spin } from 'antd'
+import { AntIcon } from 'components'
+import { cloneDeep, isEqual } from 'lodash'
+
+const initialValues = {}
+
+const layout = {
+ labelCol: { flex: '150px' },
+ wrapperCol: { flex: '1' },
+}
+
+export default class part extends Component {
+ state = {
+ loading: true,
+ codes: {},
+ options: {},
+ }
+
+ // 表单实例
+ form = React.createRef()
+
+ // 初始化数据
+ record = {}
+
+ /**
+ * 阻止外部组件引发的渲染,提升性能
+ * 可自行添加渲染条件
+ * [必要]
+ * @param {*} props
+ * @param {*} state
+ * @returns
+ */
+ shouldComponentUpdate(props, state) {
+ return !isEqual(this.state, state)
+ }
+
+ /**
+ * DOM加载完成钩子,在此将自身传递给父级,并且绑定数据
+ */
+ componentDidMount() {
+ if (this.props.onRef) {
+ this.props.onRef(this)
+ }
+ this.fillData({
+ record: this.props.record,
+ })
+ }
+
+ /**
+ * 填充数据
+ * 可以在设置this.record之后对其作出数据结构调整
+ * [异步,必要]
+ * @param {*} params
+ */
+ async fillData(params) {
+ this.record = cloneDeep(params.record)
+ //#region 从后端转换成前段所需格式
+ //#endregion
+ this.form.current.setFieldsValue(this.record)
+
+ this.setState({
+ loading: false,
+ })
+ }
+
+ /**
+ * 获取数据
+ * 可以对postData进行数据结构调整
+ * [异步,必要]
+ * @returns
+ */
+ async getData() {
+ const form = this.form.current
+
+ const valid = await form.validateFields()
+ if (valid) {
+ const postData = form.getFieldsValue()
+ //#region 从前段转换后端所需格式
+ //#endregion
+ return postData
+ }
+ }
+
+ //#region 自定义方法
+ /**
+ * 表单change事件处理,包括了所有字段的change
+ * [异步,非必要]
+ * @param {*} changedValues
+ * @param {*} allValues
+ */
+ async onValuesChange(changedValues, allValues) {}
+ //#endregion
+
+ render() {
+ const { loading } = this.state
+
+ return (
+ }>
+
+
+ )
+ }
+}