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 }) ) } if (currentStep === 2) { if (stepThreeRef.current?.syncMappings.length) { changeStep(1) } else { message.error('缺少同步字段') } } else { currentForm .validateFields() .then(() => { changeStep(1) }) .catch(err => { console.log(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(data.msg) } 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 ( {/* 步骤条 */} {/* 表单项 */} {/* 配置提取源 */} {currentStep === 0 && ( )} {/* 配置加载源 */} {currentStep === 1 && ( )} {/* 配置转换规则 */} {currentStep === 2 && ( )} {/* 设置同步参数 */} {currentStep === 3 && ( setPartitionNum(val), }} /> )} {/* 按扭操作 */} {/* 表结构预览 */} {(currentStep === 0 || currentStep === 1 || currentStep === 3) && ( <> {dataxJson !== null || (currentStep !== 3 && ( ))} }> )} {/* 按扭操作 */} {currentStep === 0 && ( )} {currentStep !== 0 && ( )} {currentStep === 3 ? ( ) : ( )} ) }