Kaynağa Gözat

feat: 暂存

leo 2 yıl önce
ebeveyn
işleme
986060b2d4

+ 5 - 0
package-lock.json

@@ -11791,6 +11791,11 @@
         "websocket-driver": "^0.7.4"
       }
     },
+    "sortablejs": {
+      "version": "1.15.0",
+      "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz",
+      "integrity": "sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w=="
+    },
     "source-list-map": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz",

+ 1 - 0
package.json

@@ -18,6 +18,7 @@
     "react-router": "^6.3.0",
     "react-router-dom": "^6.3.0",
     "react-scripts": "5.0.1",
+    "sortablejs": "^1.15.0",
     "styled-components": "^5.3.5",
     "web-vitals": "^2.1.4",
     "yarn": "^1.22.19"

+ 0 - 111
src/module/datasource/component/LoadFormConfig.jsx

@@ -1,111 +0,0 @@
-import React, { useState, useEffect } from "react";
-import { Form, Select, Input } from "antd";
-
-const DATASOURCE_TYPE_MYSQL = 'mysql'
-
-export default function LoadFormConfig ({loadDataForm}) {
-  const [datasourceType, setDatasourceType] = useState(DATASOURCE_TYPE_MYSQL)
-    
-  useEffect(() => {
-    if (loadDataForm.getFieldValue('datasource_name')) {
-      setDatasourceType(loadDataForm.getFieldValue('datasource_name'))
-    }
-  }, [])
-  return (
-    <>
-    <p style={{fontWeight: 600, borderLeft: '3px solid #1881DA', paddingLeft: '12px'}}>配置加载源源</p>
-    <Form
-      name="drawForm"
-      form={loadDataForm}
-      labelCol={{
-        span: 2,
-      }}
-      wrapperCol={{
-        span: 6,
-      }}
-      initialValues={{
-        datasource_name: DATASOURCE_TYPE_MYSQL
-      }}
-    >
-      <Form.Item
-        label="选择数据源"
-        name="datasource_name"
-        rules={[
-          {
-            required: true,
-            message: '请选择数据源!',
-          },
-        ]}
-      >
-        <Select
-          options={[
-            {label: 'My SQL', value: 'mysql'},
-            {label: 'hive', value: 'hive'}
-          ]}
-          onSelect={(val) => {setDatasourceType(val)}}
-          allowClear
-        />
-      </Form.Item>
-      <Form.Item
-        label="选择表"
-        name="datasource_form"
-        rules={[
-          {
-            required: true,
-            message: '请选择表',
-          },
-        ]}
-      >
-        <Select options={[]} allowClear />
-      </Form.Item>
-      { datasourceType === 'mysql' ? 
-        <>
-          <Form.Item label="preSql" name="preSql" wrapperCol={{span: 10}}>
-            <Input.TextArea rows={5}/>
-          </Form.Item>
-        </> : <>
-          <Form.Item
-            label="选择路径"
-            name="dataRoute"
-            wrapperCol={{span: 10}}
-            rules={[
-              {
-                required: true,
-                message: '请选择路径!',
-              },
-            ]}>
-            <Input.TextArea rows={5}/>
-          </Form.Item>
-          <Form.Item
-            label="HDFS"
-            name="datasource_hdfs"
-            rules={[
-              {
-                required: true,
-                message: '请输入HDFS',
-              },
-            ]}
-          >
-            <Input placeholder="hdfs namenode节点地址" />
-          </Form.Item>
-          <Form.Item
-            label="选择表"
-            name="file_type"
-            rules={[
-              {
-                required: true,
-                message: '请选择文件类型',
-              },
-            ]}
-          >
-            <Select options={[]} allowClear placeholder="文件的类型" />
-          </Form.Item>
-          <Form.Item label="分隔符" name="datasource_partition">
-            <Input placeholder="读取字段的分隔符" />
-          </Form.Item>
-        </>
-      }
-    </Form>
-    </>
-  )
-}

+ 1 - 1
src/module/datasource/component/DrawFormConfig.jsx → src/module/datasource/component/StepOne.jsx

@@ -1,7 +1,7 @@
 import React, { useState, useMemo } from 'react'
 import { Form, Select, Input } from 'antd'
 
-export default function DrawFormConfig({ drawDataForm, dataSourceList }) {
+export default function StepOne({ drawDataForm, dataSourceList }) {
   const [datasourceType, setDatasourceType] = useState(null)
 
   const datasources = useMemo(() => {

+ 235 - 0
src/module/datasource/component/StepThree.jsx

@@ -0,0 +1,235 @@
+import React, { useState } from 'react'
+import styled from 'styled-components'
+import arrowImgUrl from '../style/img/arrow.png'
+import syncImgUrl from '../style/img/sync.png'
+import warningImgUrl from '../style/img/warning.png'
+import deleteImgUrl from '../style/img/delete.png'
+
+const StepThreeDiv = styled.div`
+  .title {
+    font-weight: 600;
+    border-left: 3px solid #1881da;
+    padding-left: 12px;
+  }
+  .tip {
+    font-size: 12px;
+    font-weight: 400;
+    color: #bbbbbb;
+    line-height: 17px;
+    padding-left: 52px;
+    margin: 30px 0 30px;
+  }
+  .table__wrapper {
+    padding-left: 52px;
+    display: flex;
+  }
+  .table__source {
+    border-radius: 2px;
+    border: 1px solid #c8d3e9;
+    width: 400px;
+  }
+  .table__title {
+    border-bottom: 1px solid #c8d3e9;
+    height: 50px;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    padding: 0 20px;
+  }
+  .table__content {
+    height: 500px;
+    display: felx;
+    justify-content: space-between;
+    padding: 10px 20px;
+    overflow-y: scroll;
+  }
+  .field__wrapper {
+    background: #ebeff3;
+    padding: 8px 10px;
+    width: 140px;
+    font-size: 12px;
+    font-weight: 400;
+    line-height: 17px;
+  }
+  .field__sync {
+    background: #eef5fe;
+  }
+  .arrow {
+    padding: 0 20px;
+    display: flex;
+    align-items: center;
+  }
+  .sync__img {
+    display: flex;
+    align-items: center;
+    height: 33px;
+    margin-bottom: 1em;
+  }
+  .mapping__content {
+    height: 500px;
+    padding: 10px 20px;
+    overflow-y: scroll;
+  }
+  .mapping__item {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 1em;
+  }
+`
+
+const datasourceFields = [
+  {
+    key: '1',
+    value: '字段',
+    type: 'string',
+  },
+  {
+    key: '2',
+    value: '字段2',
+    type: 'boolean',
+  },
+  {
+    key: '3',
+    value: '字段3',
+    type: 'boolean',
+  },
+]
+
+const syncFields = [
+  {
+    key: '1',
+    value: '字段',
+    type: 'boolean',
+  },
+  {
+    key: '2',
+    value: '字段2',
+    type: 'boolean',
+  },
+  {
+    key: '3',
+    value: '字段3',
+    type: 'boolean',
+  },
+]
+
+const StepThree = () => {
+  // 映射管理
+  const [syncMappings, setSyncMappings] = useState([])
+
+  const syncFieldData = index => {
+    setSyncMappings([
+      ...syncMappings,
+      {
+        datasourceField: datasourceFields[index].value,
+        syncField: syncFields[index].value,
+      },
+    ])
+  }
+  const deleteMapping = mapping => {
+    setSyncMappings(syncMappings.filter(item => item !== mapping))
+  }
+  return (
+    <StepThreeDiv>
+      <p className="title">配置转换规则</p>
+      <p className="tip">拖拽提取源数据表中的字段,与加载源数据表</p>
+      <div className="table__wrapper">
+        <div className="table__source">
+          <div className="table__title">
+            <span>提取源:{'表1'}</span>
+            <span>加载源:{'表2'}</span>
+          </div>
+          <div className="table__content">
+            <div>
+              {datasourceFields.map(item => {
+                return (
+                  <p className="field__wrapper field__sync" key={item.key}>
+                    {item.value}
+                  </p>
+                )
+              })}
+            </div>
+            <div>
+              {datasourceFields.map((item, index) => {
+                const sameType =
+                  datasourceFields[index].type === syncFields[index].type
+                return (
+                  <div className="sync__img" key={item.key}>
+                    <img
+                      src={sameType ? syncImgUrl : warningImgUrl}
+                      alt=""
+                      onClick={() => {
+                        if (sameType) syncFieldData(index)
+                      }}
+                      style={{
+                        width: '20px',
+                        height: '20px',
+                        cursor: sameType ? 'pointer' : 'no-drop',
+                      }}
+                    />
+                  </div>
+                )
+              })}
+            </div>
+            <div>
+              {syncFields.map(item => {
+                return (
+                  <p className="field__wrapper" key={item.key}>
+                    {item.value}
+                  </p>
+                )
+              })}
+            </div>
+          </div>
+        </div>
+        <div className="arrow">
+          <img
+            src={arrowImgUrl}
+            alt=""
+            style={{ width: '20px', height: '20px' }}
+          />
+        </div>
+        <div className="table__source">
+          <div className="table__title">
+            <span>映射管理</span>
+            <span
+              onClick={() => {
+                setSyncMappings([])
+              }}
+              style={{
+                color: '#7D7D7D',
+                cursor: 'pointer',
+              }}>
+              清空
+            </span>
+          </div>
+          <div className="mapping__content">
+            {syncMappings.map((item, index) => {
+              return (
+                <div className="mapping__item" key={index}>
+                  <span style={{ width: '30px' }}>{index + 1}</span>
+                  <span className="field__wrapper">{item.datasourceField}</span>
+                  <img
+                    src={syncImgUrl}
+                    alt=""
+                    style={{ width: '20px', height: '20px' }}
+                  />
+                  <span className="field__wrapper">{item.syncField}</span>
+                  <img
+                    src={deleteImgUrl}
+                    alt=""
+                    onClick={() => deleteMapping(item)}
+                    style={{ width: '15px', height: '15px', cursor: 'pointer' }}
+                  />
+                </div>
+              )
+            })}
+          </div>
+        </div>
+      </div>
+    </StepThreeDiv>
+  )
+}
+
+export default StepThree

+ 117 - 0
src/module/datasource/component/StepTwo.jsx

@@ -0,0 +1,117 @@
+import React, { useState, useEffect } from 'react'
+import { Form, Select, Input } from 'antd'
+
+const DATASOURCE_TYPE_MYSQL = 'mysql'
+
+export default function StepTwo({ loadDataForm }) {
+  const [datasourceType, setDatasourceType] = useState(DATASOURCE_TYPE_MYSQL)
+
+  useEffect(() => {
+    if (loadDataForm.getFieldValue('datasource_name')) {
+      setDatasourceType(loadDataForm.getFieldValue('datasource_name'))
+    }
+  }, [])
+  return (
+    <>
+      <p
+        style={{
+          fontWeight: 600,
+          borderLeft: '3px solid #1881DA',
+          paddingLeft: '12px',
+        }}>
+        配置加载源源
+      </p>
+      <Form
+        name="drawForm"
+        form={loadDataForm}
+        labelCol={{
+          span: 2,
+        }}
+        wrapperCol={{
+          span: 6,
+        }}
+        initialValues={{
+          datasource_name: DATASOURCE_TYPE_MYSQL,
+        }}>
+        <Form.Item
+          label="选择数据源"
+          name="datasource_name"
+          rules={[
+            {
+              required: true,
+              message: '请选择数据源!',
+            },
+          ]}>
+          <Select
+            options={[
+              { label: 'My SQL', value: 'mysql' },
+              { label: 'hive', value: 'hive' },
+            ]}
+            onSelect={val => {
+              setDatasourceType(val)
+            }}
+            allowClear
+          />
+        </Form.Item>
+        <Form.Item
+          label="选择表"
+          name="datasource_form"
+          rules={[
+            {
+              required: true,
+              message: '请选择表',
+            },
+          ]}>
+          <Select options={[]} allowClear />
+        </Form.Item>
+        {datasourceType === 'mysql' ? (
+          <>
+            <Form.Item label="preSql" name="preSql" wrapperCol={{ span: 10 }}>
+              <Input.TextArea rows={5} />
+            </Form.Item>
+          </>
+        ) : (
+          <>
+            <Form.Item
+              label="选择路径"
+              name="dataRoute"
+              wrapperCol={{ span: 10 }}
+              rules={[
+                {
+                  required: true,
+                  message: '请选择路径!',
+                },
+              ]}>
+              <Input.TextArea rows={5} />
+            </Form.Item>
+            <Form.Item
+              label="HDFS"
+              name="datasource_hdfs"
+              rules={[
+                {
+                  required: true,
+                  message: '请输入HDFS',
+                },
+              ]}>
+              <Input placeholder="hdfs namenode节点地址" />
+            </Form.Item>
+            <Form.Item
+              label="选择表"
+              name="file_type"
+              rules={[
+                {
+                  required: true,
+                  message: '请选择文件类型',
+                },
+              ]}>
+              <Select options={[]} allowClear placeholder="文件的类型" />
+            </Form.Item>
+            <Form.Item label="分隔符" name="datasource_partition">
+              <Input placeholder="读取字段的分隔符" />
+            </Form.Item>
+          </>
+        )}
+      </Form>
+    </>
+  )
+}

+ 51 - 51
src/module/datasource/component/SyncTaskAdd.jsx

@@ -1,10 +1,11 @@
-import { Steps, Button, Space, Form, Card, Drawer } from 'antd'
-import DrawFormConfig from './DrawFormConfig'
-import LoadFormConfig from './LoadFormConfig'
+import { Steps, Button, Space, Form, Drawer } from 'antd'
+import StepOne from './StepOne'
+import StepTwo from './StepTwo'
+import StepThree from './StepThree'
 import React, { useState, useEffect } from 'react'
 import DataTableStruct from './DataTableStruct'
 import styled from 'styled-components'
-import { MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons';
+import { MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons'
 import { getDataSourceList } from '../services'
 
 const { Step } = Steps
@@ -20,7 +21,6 @@ const SyncTask = styled.div`
 `
 
 export default function SyncTaskAdd() {
-
   // 步骤数
   const [currentStep, setCurrentStep] = useState(0)
 
@@ -48,13 +48,13 @@ export default function SyncTaskAdd() {
 
   // 展示
   const showDrawer = () => {
-    setVisible(true);
-  };
+    setVisible(true)
+  }
 
   // 关闭
   const onClose = () => {
-    setVisible(false);
-  };
+    setVisible(false)
+  }
 
   // 获取列表数据
   const fetchDataSourceList = async () => {
@@ -85,49 +85,49 @@ export default function SyncTaskAdd() {
         <Step title="步骤4: 设置同步参数" />
       </Steps>
 
-        {/* 表单项 */}
-        {/* 配置提取源 */}
-        {currentStep === 0 ? (
-          <DrawFormConfig
-            drawDataForm={drawDataForm}
-            dataSourceList={dataSourceList}
-          />
-        ) : (
-          ''
-        )}
-        {/* 配置加载源 */}
-        {currentStep === 1 ? (
-          <LoadFormConfig
-            loadDataForm={loadDataForm}
-            dataSourceList={dataSourceList}
-          />
-        ) : (
-          ''
-        )}
+      {/* 表单项 */}
+      {/* 配置提取源 */}
+      {currentStep === 0 ? (
+        <StepOne drawDataForm={drawDataForm} dataSourceList={dataSourceList} />
+      ) : (
+        ''
+      )}
+      {/* 配置加载源 */}
+      {currentStep === 1 ? (
+        <StepTwo loadDataForm={loadDataForm} dataSourceList={dataSourceList} />
+      ) : (
+        ''
+      )}
+
+      {/* 配置转换规则 */}
+      {currentStep === 2 ? <StepThree /> : ''}
 
-        {/* 按扭操作 */}
-        {/* 表结构预览 */}
-      {currentStep === 0 || currentStep === 1 ? <>
-        <Button type="primary"
-          onClick={showDrawer}
-          className="check__btn"
-          size='large'
-          icon={<MenuFoldOutlined />}
-        >
-          表结构预览
-        </Button>
-        <Drawer
-          title="表结构预览"
-          placement="right"
-          onClose={onClose}
-          visible={visible}
-          width={700}
-          mask={false}
-          closeIcon={<MenuUnfoldOutlined style={{color: '#1881DA'}}/> }
-        >
-          <DataTableStruct />
-        </Drawer>
-      </> : ''}
+      {/* 按扭操作 */}
+      {/* 表结构预览 */}
+      {currentStep === 0 || currentStep === 1 ? (
+        <>
+          <Button
+            type="primary"
+            onClick={showDrawer}
+            className="check__btn"
+            size="large"
+            icon={<MenuFoldOutlined />}>
+            表结构预览
+          </Button>
+          <Drawer
+            title="表结构预览"
+            placement="right"
+            onClose={onClose}
+            visible={visible}
+            width={700}
+            mask={false}
+            closeIcon={<MenuUnfoldOutlined style={{ color: '#1881DA' }} />}>
+            <DataTableStruct />
+          </Drawer>
+        </>
+      ) : (
+        ''
+      )}
 
       {/* 按扭操作 */}
       <Space style={{ margin: '20px' }}>

BIN
src/module/datasource/style/img/arrow.png


BIN
src/module/datasource/style/img/delete.png


BIN
src/module/datasource/style/img/sync.png


BIN
src/module/datasource/style/img/warning.png