'init_again'

Change-Id: Ib7ecdb9f5baeab1e4681152a57b936edf7475b35
diff --git a/src/pages/Tool/Gen/components/BaseInfo.tsx b/src/pages/Tool/Gen/components/BaseInfo.tsx
new file mode 100644
index 0000000..6a0466f
--- /dev/null
+++ b/src/pages/Tool/Gen/components/BaseInfo.tsx
@@ -0,0 +1,124 @@
+import { Button, Col, Form, message, Row } from 'antd';
+import React, { Fragment, useEffect } from 'react';
+import { history } from '@umijs/max';
+import styles from '../style.less';
+import { ProForm, ProFormText, ProFormTextArea } from '@ant-design/pro-components';
+
+export type BaseInfoProps = {
+  values?: any;
+  onStepSubmit?: any;
+};
+
+const BaseInfo: React.FC<BaseInfoProps> = (props) => {
+  const [form] = Form.useForm();
+  const { onStepSubmit } = props;
+
+  useEffect(() => {
+    form.resetFields();
+    form.setFieldsValue({
+      tableName: props.values.tableName,
+    });
+  });
+
+  const onValidateForm = async () => {
+    const values = await form.validateFields();
+    if (onStepSubmit) {
+      onStepSubmit('base', values);
+    }
+  };
+
+  return (
+    <Fragment>
+      <Row>
+        <Col span={24}>
+          <ProForm
+            form={form}
+            onFinish={async () => {
+              message.success('提交成功');
+            }}
+            initialValues={{
+              tableName: props.values?.tableName,
+              tableComment: props.values?.tableComment,
+              className: props.values?.className,
+              functionAuthor: props.values?.functionAuthor,
+              remark: props.values?.remark,
+            }}
+            submitter={{
+              resetButtonProps: {
+                style: { display: 'none' },
+              },
+              submitButtonProps: {
+                style: { display: 'none' },
+              },
+            }}
+          >
+            <Row>
+              <Col span={12} order={1}>
+                <ProFormText
+
+                  name="tableName"
+                  label="表名称"
+                  rules={[
+                    {
+                      required: true,
+                      message: '表名称不可为空。',
+                    },
+                  ]}
+                />
+              </Col>
+              <Col span={12} order={2}>
+                <ProFormText
+                  name="tableComment"
+                  label="表描述"
+                />
+              </Col>
+            </Row>
+            <Row>
+              <Col span={12} order={1}>
+                <ProFormText
+
+                  name="className"
+                  label="实体类名称"
+                  rules={[
+                    {
+                      required: true,
+                      message: '实体类名称不可为空。',
+                    },
+                  ]}
+                />
+              </Col>
+              <Col span={12} order={2}>
+                <ProFormText name="functionAuthor" label="作者" />
+              </Col>
+            </Row>
+            <Row>
+              <Col span={24}>
+                <ProFormTextArea name="remark" label="备注" />
+              </Col>
+            </Row>
+          </ProForm>
+        </Col>
+      </Row>
+      <Row justify="center">
+        <Col span={4}>
+          <Button
+            type="primary"
+            className={styles.step_buttons}
+            onClick={() => {
+              history.back();
+            }}
+          >
+            返回
+          </Button>
+        </Col>
+        <Col span={4}>
+          <Button type="primary" onClick={onValidateForm}>
+            下一步
+          </Button>
+        </Col>
+      </Row>
+    </Fragment>
+  );
+};
+
+export default BaseInfo;
diff --git a/src/pages/Tool/Gen/components/ColumnInfo.tsx b/src/pages/Tool/Gen/components/ColumnInfo.tsx
new file mode 100644
index 0000000..2db5de4
--- /dev/null
+++ b/src/pages/Tool/Gen/components/ColumnInfo.tsx
@@ -0,0 +1,304 @@
+import React, { Fragment, useEffect, useRef, useState } from 'react';
+import type { GenCodeType } from '../data';
+import { Button, Checkbox, Col, Row, Tag } from 'antd';
+import type { FormInstance } from 'antd';
+import { history } from '@umijs/max';
+import styles from '../style.less';
+import { EditableProTable, ProColumns } from '@ant-design/pro-components';
+
+export type ColumnInfoProps = {
+  parentType?: string;
+  data?: any[];
+  dictData?: any[];
+  onStepSubmit?: any;
+};
+
+const booleanEnum = [
+  {
+    label: 'true',
+    value: '1',
+  },
+  {
+    label: 'false',
+    value: '0',
+  },
+];
+
+const ColumnInfo: React.FC<ColumnInfoProps> = (props) => {
+  const formRef = useRef<FormInstance>();
+
+  const [dataSource, setDataSource] = useState<any[]>();
+
+  const [editableKeys, setEditableRowKeys] = useState<React.Key[]>([]);
+
+  const { data, dictData, onStepSubmit } = props;
+
+  const columns: ProColumns<GenCodeType>[] = [
+    {
+      title: '编号',
+      dataIndex: 'columnId',
+      editable: false,
+      width: 80,
+    },
+    {
+      title: '字段名',
+      dataIndex: 'columnName',
+      editable: false,
+    },
+    {
+      title: '字段描述',
+      dataIndex: 'columnComment',
+      hideInForm: true,
+      hideInSearch: true,
+      width: 200,
+    },
+    {
+      title: '字段类型',
+      dataIndex: 'columnType',
+      editable: false,
+    },
+    {
+      title: 'Java类型',
+      dataIndex: 'javaType',
+      valueType: 'select',
+      valueEnum: {
+        Long: {
+          text: 'Long',
+        },
+        String: {
+          text: 'String',
+        },
+        Integer: {
+          text: 'Integer',
+        },
+        Double: {
+          text: 'Double',
+        },
+        BigDecimal: {
+          text: 'BigDecimal',
+        },
+        Date: {
+          text: 'Date',
+        },
+      },
+    },
+    {
+      title: 'Java属性',
+      dataIndex: 'javaField',
+    },
+    {
+      title: '插入',
+      dataIndex: 'isInsert',
+      valueType: 'select',
+      fieldProps: {
+        options: booleanEnum,
+      },
+      render: (_, record) => {
+        return <Checkbox checked={record.isInsert === '1'} />;
+      },
+    },
+    {
+      title: '编辑',
+      dataIndex: 'isEdit',
+      valueType: 'select',
+      fieldProps: {
+        options: booleanEnum,
+      },
+      render: (_, record) => {
+        return <Checkbox checked={record.isEdit === '1'} />;
+      },
+    },
+    {
+      title: '列表',
+      dataIndex: 'isList',
+      valueType: 'select',
+      fieldProps: {
+        options: booleanEnum,
+      },
+      render: (_, record) => {
+        return <Checkbox checked={record.isList === '1'} />;
+      },
+    },
+    {
+      title: '查询',
+      dataIndex: 'isQuery',
+      valueType: 'select',
+      fieldProps: {
+        options: booleanEnum,
+      },
+      render: (_, record) => {
+        return <Checkbox checked={record.isQuery === '1'} />;
+      },
+    },
+    {
+      title: '查询方式',
+      dataIndex: 'queryType',
+      valueType: 'select',
+      valueEnum: {
+        EQ: {
+          text: '=',
+        },
+        NE: {
+          text: '!=',
+        },
+        GT: {
+          text: '>',
+        },
+        GTE: {
+          text: '>=',
+        },
+        LT: {
+          text: '<',
+        },
+        LTE: {
+          text: '<=',
+        },
+        LIKE: {
+          text: 'LIKE',
+        },
+        BETWEEN: {
+          text: 'BETWEEN',
+        },
+      },
+    },
+    {
+      title: '必填',
+      dataIndex: 'isRequired',
+      valueType: 'select',
+      fieldProps: {
+        options: booleanEnum,
+      },
+      render: (_, record) => {
+        return <Checkbox checked={record.isRequired === '1'} />;
+      },
+    },
+    {
+      title: '显示类型',
+      dataIndex: 'htmlType',
+      hideInSearch: true,
+      valueType: 'select',
+      valueEnum: {
+        input: {
+          text: '文本框',
+        },
+        textarea: {
+          text: '文本域',
+        },
+        select: {
+          text: '下拉框',
+        },
+        radio: {
+          text: '单选框',
+        },
+        checkbox: {
+          text: '复选框',
+        },
+        datetime: {
+          text: '日期控件',
+        },
+        imageUpload: {
+          text: '图片上传',
+        },
+        fileUpload: {
+          text: '文件上传',
+        },
+        editor: {
+          text: '富文本控件',
+        },
+      },
+    },
+    {
+      title: '字典类型',
+      dataIndex: 'dictType',
+      hideInSearch: true,
+      valueType: 'select',
+      fieldProps: {
+        options: dictData,
+      },
+      render: (text) => {
+        return <Tag color="#108ee9">{text}</Tag>;
+      },
+    },
+  ];
+
+  useEffect(() => {
+    setDataSource(data);
+    if (data) {
+      setEditableRowKeys(data.map((item) => item.columnId));
+    }
+  }, [data]);
+
+  const onSubmit = (direction: string) => {
+    if (onStepSubmit) {
+      onStepSubmit('column', dataSource, direction);
+    }
+  };
+
+  const onDataChange = (value: readonly GenCodeType[]) => {
+    setDataSource({ ...value } as []);
+  };
+
+  return (
+    <Fragment>
+      <Row>
+        <Col span={24}>
+          <EditableProTable<GenCodeType>
+            formRef={formRef}
+            rowKey="columnId"
+            search={false}
+            columns={columns}
+            value={dataSource}
+            editable={{
+              type: 'multiple',
+              editableKeys,
+              onChange: setEditableRowKeys,
+              actionRender: (row, config, defaultDoms) => {
+                return [defaultDoms.delete];
+              },
+              onValuesChange: (record, recordList) => {
+                setDataSource(recordList);
+              },
+            }}
+            onChange={onDataChange}
+            recordCreatorProps={false}
+          />
+        </Col>
+      </Row>
+      <Row justify="center">
+        <Col span={4}>
+          <Button
+            type="primary"
+            onClick={() => {
+              history.back();
+            }}
+          >
+            返回
+          </Button>
+        </Col>
+        <Col span={4}>
+          <Button
+            type="primary"
+            className={styles.step_buttons}
+            onClick={() => {
+              onSubmit('prev');
+            }}
+          >
+            上一步
+          </Button>
+        </Col>
+        <Col span={4}>
+          <Button
+            type="primary"
+            onClick={() => {
+              onSubmit('next');
+            }}
+          >
+            下一步
+          </Button>
+        </Col>
+      </Row>
+    </Fragment>
+  );
+};
+
+export default ColumnInfo;
diff --git a/src/pages/Tool/Gen/components/GenInfo.tsx b/src/pages/Tool/Gen/components/GenInfo.tsx
new file mode 100644
index 0000000..97901ec
--- /dev/null
+++ b/src/pages/Tool/Gen/components/GenInfo.tsx
@@ -0,0 +1,330 @@
+import { Button, Col, Divider, Form, Row, TreeSelect } from 'antd';
+import React, { Fragment, useEffect, useState } from 'react';
+import { history } from '@umijs/max';
+import type { TableInfo } from '../data';
+import styles from '../style.less';
+import { DataNode } from 'antd/es/tree';
+import { ProForm, ProFormRadio, ProFormSelect, ProFormText } from '@ant-design/pro-components';
+
+export type GenInfoProps = {
+  values?: any;
+  menuData?: DataNode[];
+  tableInfo?: TableInfo[];
+  onStepSubmit?: any;
+};
+
+const GenInfo: React.FC<GenInfoProps> = (props) => {
+  const [form] = Form.useForm();
+
+  const [pathType, setPathType] = useState<string>('0');
+  const [tlpType, setTlpType] = useState<string>('curd');
+
+  const [subTablesColumnOptions, setSubTablesColumnOptions] = useState<any[]>();
+
+  const { menuData, tableInfo, onStepSubmit } = props;
+
+  const tablesOptions = tableInfo?.map((item: any) => {
+    return {
+      value: item.tableName,
+      label: `${item.tableName}:${item.tableComment}`,
+    };
+  });
+
+  if (tableInfo) {
+    for (let index = 0; index < tableInfo?.length; index += 1) {
+      const tbl = tableInfo[index];
+      if (tbl.tableName === props.values.subTableName) {
+        const opts = [];
+        tbl.columns.forEach((item) => {
+          opts.push({
+            value: item.columnName,
+            label: `${item.columnName}: ${item.columnComment}`,
+          });
+        });
+        break;
+      }
+    }
+  }
+
+  const treeColumns = props.values.columns.map((item: any) => {
+    return {
+      value: item.columnName,
+      label: `${item.columnName}: ${item.columnComment}`,
+    };
+  });
+
+  const onSubmit = async (direction: string) => {
+    const values = await form.validateFields();
+    onStepSubmit('gen', values, direction);
+  };
+
+  useEffect(() => {
+    setPathType(props.values.genType);
+    setTlpType(props.values.tplCategory);
+  }, [props.values.genType, props.values.tplCategory]);
+
+  return (
+    <Fragment>
+      <Row>
+        <Col span={24}>
+          <ProForm
+            form={form}
+            onFinish={async () => {
+              const values = await form.validateFields();
+              onStepSubmit('gen', values);
+            }}
+            initialValues={{
+              curd: props.values.curd,
+              tree: props.values.tree,
+              sub: props.values.sub,
+              tplCategory: props.values.tplCategory,
+              packageName: props.values.packageName,
+              moduleName: props.values.moduleName,
+              businessName: props.values.businessName,
+              functionName: props.values.functionName,
+              parentMenuId: props.values.parentMenuId,
+              genType: props.values.genType,
+              genPath: props.values.genPath,
+              treeCode: props.values.treeCode,
+              treeParentCode: props.values.treeParentCode,
+              treeName: props.values.treeName,
+              subTableName: props.values.subTableName,
+              subTableFkName: props.values.subTableFkName,
+            }}
+            submitter={{
+              resetButtonProps: {
+                style: { display: 'none' },
+              },
+              submitButtonProps: {
+                style: { display: 'none' },
+              },
+            }}
+          >
+            <Row gutter={[16, 16]}>
+              <Col span={12} order={1}>
+                <ProFormSelect
+                  fieldProps={{
+                    onChange: (val) => {
+                      setTlpType(val);
+                    },
+                  }}
+                  valueEnum={{
+                    crud: '单表(增删改查)',
+                    tree: '树表(增删改查)',
+                    sub: '主子表(增删改查)',
+                  }}
+                  name="tplCategory"
+                  label="生成模板"
+                  rules={[
+                    {
+                      required: true,
+                      message: '选择类型',
+                    },
+                  ]}
+                />
+              </Col>
+              <Col span={12} order={2}>
+                <ProFormText name="packageName" label="生成包路径" />
+              </Col>
+            </Row>
+            <Row gutter={[16, 16]}>
+              <Col span={12} order={1}>
+                <ProFormText name="moduleName" label="生成模块名" />
+              </Col>
+              <Col span={12} order={2}>
+                <ProFormText name="businessName" label="生成业务名" />
+              </Col>
+            </Row>
+            <Row gutter={[16, 16]}>
+              <Col span={12} order={1}>
+                <ProFormText name="functionName" label="生成功能名" />
+              </Col>
+              <Col span={12} order={2}>
+                <ProForm.Item
+                  labelCol={{ span: 20 }}
+                  name="parentMenuId"
+                  label="父菜单"
+                >
+                  <TreeSelect
+                    style={{ width: '74%' }}
+                    defaultValue={props.values.parentMenuId}
+                    treeData={menuData}
+                    placeholder="请选择父菜单"
+                  />
+                </ProForm.Item>
+              </Col>
+            </Row>
+            <Row gutter={[16, 16]}>
+              <Col span={24}>
+                <ProFormRadio.Group
+                  valueEnum={{
+                    '0': 'zip压缩包',
+                    '1': '自定义路径',
+                  }}
+                  name="genType"
+                  label="生成代码方式"
+                  rules={[
+                    {
+                      required: true,
+                      message: '选择类型',
+                    },
+                  ]}
+                  fieldProps={{
+                    onChange: (e) => {
+                      setPathType(e.target.value);
+                    },
+                  }}
+                />
+              </Col>
+            </Row>
+            <Row gutter={[16, 16]}>
+              <Col span={24} order={1}>
+                <ProFormText
+                  hidden={pathType === '0'}
+                  width="md"
+                  name="genPath"
+                  label="自定义路径"
+                />
+              </Col>
+            </Row>
+            <div hidden={tlpType !== 'tree'}>
+              <Divider orientation="left">其他信息</Divider>
+              <Row gutter={[16, 16]}>
+                <Col span={12} order={1}>
+                  <ProFormSelect
+                    name="treeCode"
+                    label="树编码字段"
+                    options={treeColumns}
+                    rules={[
+                      {
+                        required: tlpType === 'tree',
+                        message: '树编码字段',
+                      },
+                    ]}
+                  />
+                </Col>
+                <Col span={12} order={2}>
+                  <ProFormSelect
+                    name="treeParentCode"
+                    label="树父编码字段"
+                    options={treeColumns}
+                    rules={[
+                      {
+                        required: tlpType === 'tree',
+                        message: '树父编码字段',
+                      },
+                    ]}
+                  />
+                </Col>
+              </Row>
+              <Row gutter={[16, 16]}>
+                <Col span={12} order={1}>
+                  <ProFormSelect
+                    name="treeName"
+                    label="树名称字段"
+                    options={treeColumns}
+                    rules={[
+                      {
+                        required: tlpType === 'tree',
+                        message: '树名称字段',
+                      },
+                    ]}
+                  />
+                </Col>
+              </Row>
+            </div>
+            <div hidden={tlpType !== 'sub'}>
+              <Divider orientation="left">关联信息</Divider>
+              <Row gutter={[16, 16]}>
+                <Col span={12} order={1}>
+                  <ProFormSelect
+                    name="subTableName"
+                    label="关联子表的表名"
+                    options={tablesOptions}
+                    rules={[
+                      {
+                        required: tlpType === 'sub',
+                        message: '关联子表的表名',
+                      },
+                    ]}
+                    fieldProps={{
+                      onChange: (val) => {
+                        form.setFieldsValue({
+                          subTableFkName: '',
+                        });
+                        if (tableInfo) {
+                          for (let index = 0; index < tableInfo?.length; index += 1) {
+                            const tbl = tableInfo[index];
+                            if (tbl.tableName === val) {
+                              const opts: any[] = [];
+                              tbl.columns.forEach((item) => {
+                                opts.push({
+                                  value: item.columnName,
+                                  label: `${item.columnName}:${item.columnComment}`,
+                                });
+                              });
+                              setSubTablesColumnOptions(opts);
+                              break;
+                            }
+                          }
+                        }
+                      },
+                    }}
+                  />
+                </Col>
+                <Col span={12} order={2}>
+                  <ProFormSelect
+                    name="subTableFkName"
+                    options={subTablesColumnOptions}
+                    label="子表关联的外键名"
+                    rules={[
+                      {
+                        required: tlpType === 'sub',
+                        message: '子表关联的外键名',
+                      },
+                    ]}
+                  />
+                </Col>
+              </Row>
+            </div>
+          </ProForm>
+        </Col>
+      </Row>
+      <Row justify="center">
+        <Col span={4}>
+          <Button
+            type="primary"
+            onClick={() => {
+              history.back();
+            }}
+          >
+            返回
+          </Button>
+        </Col>
+        <Col span={4}>
+          <Button
+            type="primary"
+            className={styles.step_buttons}
+            onClick={() => {
+              onSubmit('prev');
+            }}
+          >
+            上一步
+          </Button>
+        </Col>
+        <Col span={4}>
+          <Button
+            type="primary"
+            onClick={() => {
+              onSubmit('next');
+            }}
+          >
+            提交
+          </Button>
+        </Col>
+      </Row>
+    </Fragment>
+  );
+};
+
+export default GenInfo;
diff --git a/src/pages/Tool/Gen/components/PreviewCode.tsx b/src/pages/Tool/Gen/components/PreviewCode.tsx
new file mode 100644
index 0000000..f3611ad
--- /dev/null
+++ b/src/pages/Tool/Gen/components/PreviewCode.tsx
@@ -0,0 +1,50 @@
+import React, { useEffect } from 'react';
+import { useIntl } from '@umijs/max';
+import { Modal, Tabs } from 'antd';
+import type { TabsProps } from 'antd';
+import Highlight from 'react-highlight';
+import 'highlight.js/styles/base16/material.css';
+
+interface PreviewTableProps {
+  open: boolean;
+  data?: any;
+  onHide: () => void;
+}
+
+const PreviewTableCode: React.FC<PreviewTableProps> = (props) => {
+  const intl = useIntl();
+  const panes: any = [];
+  const keys = Object.keys(props.data);
+  keys.forEach((key) => {
+    panes.push({
+        key: key + '1',
+        label: key.substring(key.lastIndexOf('/') + 1, key.indexOf('.vm')),
+        children: <Highlight className="java">{props.data[key]}</Highlight>,
+      } as TabsProps);
+  });
+
+  useEffect(() => {}, []);
+
+  return (
+    <Modal
+      width={900}
+      title={intl.formatMessage({
+        id: 'gen.preview',
+        defaultMessage: '预览',
+      })}
+      open={props.open}
+      destroyOnClose
+      footer={false}
+      onOk={() => {
+        props.onHide();
+      }}
+      onCancel={() => {
+        props.onHide();
+      }}
+    >
+      <Tabs defaultActiveKey="1" items={panes}></Tabs>
+    </Modal>
+  );
+};
+
+export default PreviewTableCode;