123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495 |
- import { Steps, Button, Space, Form, Drawer, message } from 'antd'
- import StepOne from './StepOne'
- import StepTwo from './StepTwo'
- import StepThree from './StepThree'
- import StepFour from './StepFour'
- import React, { useState, useEffect, useRef } from 'react'
- import DataTableStruct from './DataTableStruct'
- import styled from 'styled-components'
- import { MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons'
- import {
- getDataSourceList,
- getTableSchema,
- buildJsonData,
- createJob,
- } from '../services'
- import { useNavigate } from 'react-router'
- import moment from 'moment'
- const { Step } = Steps
- const SyncTask = styled.div`
- padding: 20px;
- .check__btn {
- position: absolute;
- right: 0;
- top: 20%;
- border-radius: 0;
- }
- `
- export default function SyncTaskAdd() {
- // 路由导航
- const navigate = useNavigate()
- // 步骤三ref
- const stepThreeRef = React.createRef()
- // jsonValue
- const jsonValue = React.createRef()
- const cronRef = useRef()
- // 步骤数
- const [currentStep, setCurrentStep] = useState(0)
- // 初始化数据源列表数据 constructor
- const [dataSourceList, setDataSourceList] = useState([])
- // 构建loading状态
- const [building, setBuilding] = useState(false)
- // 提交loading状态
- const [submiting, setSubmiting] = useState(false)
- // 完成状态
- const [isfinishBuild, setIsFinishBuild] = useState(false)
- const [dataxJson, setDataxJson] = useState(null)
- const [partitionNum, setPartitionNum] = useState(0)
- const [cron_data, setCronData] = useState(null)
- // 提取源表单表结构
- const [drawDataStruct, setDrawDataStruct] = useState([])
- const updateDrawDataStruct = async (ds_id, table_name) => {
- await updateTableStruct(ds_id, table_name, setDrawDataStruct)
- }
- // 加载源表单表结构
- const [loadDataStruct, setLoadDataStruct] = useState([])
- const updateLoadDataStruct = async (id, table_name) => {
- await updateTableStruct(id, table_name, setLoadDataStruct)
- }
- // 更新表结构
- const updateTableStruct = async (id, table_name, setFunc) => {
- const { data } = await getTableSchema({ id, table_name })
- if (data.code === 200) {
- const tableList = data.data.map(item => {
- const splitData = item.split(':')
- return {
- key: splitData[0],
- id: splitData[0],
- field: splitData[1],
- type: splitData[2],
- }
- })
- setFunc(tableList)
- } else {
- message.error('表结构数据加载失败')
- }
- }
- // 配置提取源表单
- const [drawDataForm] = Form.useForm()
- // 配置加载源表单
- const [loadDataForm] = Form.useForm()
- // 同步参数表单
- const [syncDataForm] = Form.useForm()
- // 当前表单
- const [currentForm, setCurrentForm] = useState(drawDataForm)
- // 上一步/下一步
- const changeStep = num => {
- if (num === -1) {
- setIsFinishBuild(false)
- }
- setCurrentStep(currentStep + num)
- }
- // 暂存cron表达式
- const saveCron = () => {
- if (Object.keys(cronRef.current.getCronData).length !== 0) {
- setCronData(cronRef.current.getCronData)
- }
- }
- // 监听步骤设置当前表单
- useEffect(() => {
- switch (currentStep) {
- case 0:
- setCurrentForm(drawDataForm)
- break
- case 1:
- setCurrentForm(loadDataForm)
- break
- case 3:
- setCurrentForm(syncDataForm)
- break
- default:
- break
- }
- }, [currentStep])
- // 右侧表结构可视
- const [visible, setVisible] = useState(false)
- // 展示
- const showDrawer = () => {
- setVisible(true)
- }
- // 关闭
- const onClose = () => {
- if (currentStep === 3) {
- saveCron()
- if (jsonValue.current) {
- setDataxJson(JSON.parse(jsonValue.current.jsonValue.editor.getValue()))
- }
- }
- setVisible(false)
- }
- // 获取列表数据
- const fetchDataSourceList = async () => {
- const { data } = await getDataSourceList()
- if (data.code === 200) {
- const list = data.data.items.map(item => {
- return {
- key: item.id,
- datasource_name: item.datasource_name,
- datasource: item.datasource,
- }
- })
- setDataSourceList(list)
- }
- }
- // 挂载的时候获取SourceList
- useEffect(() => {
- fetchDataSourceList()
- }, [])
- const [syncMapSaving, setSyncMapSaving] = useState([])
- // reader_columns
- const [reader_columns, setReaderColumns] = useState([])
- // writer_columns
- const [writer_columns, setWriterColumns] = useState([])
- // 下一步
- const nextStep = () => {
- if (currentStep === 2) {
- setSyncMapSaving(stepThreeRef.current.syncMappings)
- setReaderColumns(
- stepThreeRef.current.syncMappings.map(item => {
- return item.key.drawData
- })
- )
- setWriterColumns(
- stepThreeRef.current.syncMappings.map(item => {
- return item.key.loadData
- })
- )
- }
- currentForm
- .validateFields()
- .then(() => {
- changeStep(1)
- })
- .catch(err => {
- message.error('请检查表单数据是否完整')
- })
- }
- // 格式化构建请求参数数据
- const formatBuildData = () => {
- // 获取表单数据
- const reader_form = drawDataForm.getFieldValue()
- const writer_form = loadDataForm.getFieldValue()
- // 获取id tables
- const reader_datasource_id = reader_form['datasource_name']
- const reader_tables = [reader_form['datasource_table']]
- const writer_datasource_id = writer_form['datasource_name']
- const writer_tables = [writer_form['datasource_table']]
- const writer_filename = writer_form['writer_filename']
- // 基础固定参数
- const base_params = {
- reader_datasource_id,
- reader_tables,
- reader_columns,
- writer_datasource_id,
- writer_tables,
- writer_columns,
- }
- // 获取表类型
- const reader_type = dataSourceList.find(
- item => item.key === reader_datasource_id
- ).datasource
- const writer_type = dataSourceList.find(
- item => item.key === writer_datasource_id
- ).datasource
- // 结构表单参数
- const {
- reader_split_pk,
- where_param,
- query_sql,
- reader_default_fs,
- reader_file_type,
- reader_path,
- reader_field_delimiter,
- } = reader_form
- const {
- pre_sql,
- post_sql,
- writer_default_fs,
- writer_file_type,
- writer_path,
- writer_mode,
- writer_field_delimiter,
- } = writer_form
- // 根据类型区分参数
- switch (`${reader_type}2${writer_type}`) {
- case 'mysql2mysql':
- return {
- ...base_params,
- rdbms_reader: { reader_split_pk, where_param, query_sql },
- rdbms_writer: { pre_sql, post_sql },
- }
- case 'mysql2hive':
- return {
- ...base_params,
- rdbms_reader: { reader_split_pk, where_param, query_sql },
- hive_writer: {
- writer_default_fs,
- writer_file_type,
- writer_path,
- writer_mode,
- writer_field_delimiter,
- writer_filename,
- },
- }
- case 'hive2mysql':
- return {
- ...base_params,
- hive_reader: {
- reader_default_fs,
- reader_file_type,
- reader_path,
- reader_field_delimiter,
- },
- rdbms_writer: { pre_sql, post_sql },
- }
- case 'hive2hive':
- return {
- ...base_params,
- hive_reader: {
- reader_default_fs,
- reader_file_type,
- reader_path,
- reader_field_delimiter,
- },
- hive_writer: {
- writer_default_fs,
- writer_file_type,
- writer_path,
- writer_mode,
- writer_field_delimiter,
- writer_filename,
- },
- }
- default:
- break
- }
- return null
- }
- // 构建表单
- const build = async () => {
- saveCron()
- const buildParams = formatBuildData()
- if (!buildParams) {
- message.error('获取表单参数失败')
- return
- }
- setBuilding(true)
- const { data } = await buildJsonData(buildParams)
- if (data.code === 200) {
- message.success('构建成功')
- const json = data.data.json
- setDataxJson(json)
- showDrawer()
- setIsFinishBuild(true)
- } else {
- message.error('构建失败,请检查表单数据')
- }
- setBuilding(false)
- }
- // 完成提交
- const finishSubmit = async job_json => {
- // setSubmiting(true)
- const fields = currentForm.getFieldValue()
- const params = {
- ...fields,
- job_json,
- inc_start_time: moment(fields.inc_start_time).unix(),
- user_id: 'test',
- }
- params['partition_num'] = partitionNum
- const { data } = await createJob(params)
- if (data.code === 200) {
- message.success('提交成功')
- navigate(-1)
- } else {
- message.error('提交失败')
- }
- setSubmiting(false)
- }
- // 提交表单
- const submit = () => {
- if (jsonValue.current) {
- setDataxJson(JSON.parse(jsonValue.current.jsonValue.editor.getValue()))
- }
- try {
- let job_json = JSON.stringify(dataxJson)
- if (jsonValue.current) {
- job_json = JSON.stringify(
- JSON.parse(jsonValue.current.jsonValue.editor.getValue())
- )
- }
- if (Object.keys(cronRef.current.getCronData).length !== 0) {
- currentForm.setFieldValue(
- 'cron_expression',
- cronRef.current.getCronData
- )
- }
- currentForm
- .validateFields()
- .then(() => {
- finishSubmit(job_json)
- })
- .catch(err => {
- message.error('请检查表单数据是否完整')
- })
- } catch (error) {
- message.error('转换JSON字符串失败,请检查json数据', error)
- }
- }
- return (
- <SyncTask>
- {/* 步骤条 */}
- <Steps current={currentStep} labelPlacement="vertical" size="small">
- <Step title="步骤1: 配置提取源" />
- <Step title="步骤2: 配置加载源" />
- <Step title="步骤3: 配置转换规则" />
- <Step title="步骤4: 设置同步参数" />
- </Steps>
- {/* 表单项 */}
- {/* 配置提取源 */}
- {currentStep === 0 && (
- <StepOne
- drawDataForm={drawDataForm}
- dataSourceList={dataSourceList}
- updateTableStruct={updateDrawDataStruct}
- />
- )}
- {/* 配置加载源 */}
- {currentStep === 1 && (
- <StepTwo
- loadDataForm={loadDataForm}
- dataSourceList={dataSourceList}
- updateTableStruct={updateLoadDataStruct}
- />
- )}
- {/* 配置转换规则 */}
- {currentStep === 2 && (
- <StepThree
- onRef={stepThreeRef}
- drawDataForm={drawDataForm}
- loadDataForm={loadDataForm}
- syncMapSaving={syncMapSaving}
- />
- )}
- {/* 设置同步参数 */}
- {currentStep === 3 && (
- <StepFour
- onRef={cronRef}
- syncDataForm={syncDataForm}
- cron_data={cron_data}
- partitionNumHandle={{
- num: partitionNum,
- func: val => setPartitionNum(val),
- }}
- />
- )}
- {/* 按扭操作 */}
- {/* 表结构预览 */}
- {(currentStep === 0 || currentStep === 1 || currentStep === 3) && (
- <>
- {dataxJson !== null && (
- <Button
- type="primary"
- onClick={showDrawer}
- className="check__btn"
- size="large"
- icon={<MenuFoldOutlined />}>
- {currentStep !== 3 ? '表结构预览' : '构建'}
- </Button>
- )}
- <Drawer
- title={currentStep === 3 ? '构建' : '表结构预览'}
- placement="right"
- onClose={onClose}
- visible={visible}
- width={600}
- mask={false}
- destroyOnClose={true}
- closeIcon={<MenuUnfoldOutlined style={{ color: '#1881DA' }} />}>
- <DataTableStruct
- currentStep={currentStep}
- tableData={currentStep === 0 ? drawDataStruct : loadDataStruct}
- datax={dataxJson}
- onRef={jsonValue}
- />
- </Drawer>
- </>
- )}
- {/* 按扭操作 */}
- <Space style={{ margin: '20px' }}>
- <Button
- onClick={() => {
- changeStep(-1)
- }}
- disabled={currentStep === 0 || building}>
- 上一步
- </Button>
- {currentStep === 3 ? (
- <Button
- type="primary"
- onClick={isfinishBuild ? submit : build}
- loading={isfinishBuild ? submiting : building}>
- {isfinishBuild ? '提交' : '构建'}
- </Button>
- ) : (
- <Button type="primary" onClick={nextStep}>
- 下一步
- </Button>
- )}
- </Space>
- </SyncTask>
- )
- }
|