[improvement][project] global refactor , code format , support llm , support fuzzy detect ,support query filter and so on.

This commit is contained in:
lexluo
2023-07-08 15:00:03 +08:00
parent 5ffd617431
commit 404163f391
329 changed files with 21050 additions and 5036 deletions

View File

@@ -1,19 +1,102 @@
import React from 'react';
import { Form, Input, Spin } from 'antd';
import React, { useEffect, useState } from 'react';
import { Form, Input, Spin, Select, message } from 'antd';
import type { FormInstance } from 'antd/lib/form';
import { getDbNames, getTables } from '../../service';
const FormItem = Form.Item;
const { TextArea } = Input;
type Props = {
isEdit?: boolean;
dataBaseConfig: any;
form: FormInstance<any>;
tableLoading?: boolean;
mode?: 'normal' | 'fast';
};
const DataSourceBasicForm: React.FC<Props> = ({ isEdit, tableLoading = false }) => {
const DataSourceBasicForm: React.FC<Props> = ({
isEdit,
dataBaseConfig,
tableLoading = false,
mode = 'normal',
}) => {
const [dbNameList, setDbNameList] = useState<any[]>([]);
const [tableNameList, setTableNameList] = useState<any[]>([]);
const [currentDbName, setCurrentDbName] = useState<string>('');
const [currentTableName, setCurrentTableName] = useState<string>('');
const queryDbNameList = async (databaseId: number) => {
const { code, data, msg } = await getDbNames(databaseId);
if (code === 200) {
const list = data?.resultList || [];
setDbNameList(list);
} else {
message.error(msg);
}
};
const queryTableNameList = async (databaseName: string) => {
const { code, data, msg } = await getTables(dataBaseConfig.id, databaseName);
if (code === 200) {
const list = data?.resultList || [];
setTableNameList(list);
} else {
message.error(msg);
}
};
useEffect(() => {
if (dataBaseConfig?.id) {
queryDbNameList(dataBaseConfig.id);
}
}, [dataBaseConfig]);
return (
<Spin spinning={tableLoading}>
{mode === 'fast' && (
<>
<FormItem
name="dbName"
label="数据库名"
rules={[{ required: true, message: '请选择数据库/表' }]}
>
<Select
showSearch
placeholder="请选择数据库/表"
disabled={isEdit}
onChange={(dbName: string) => {
queryTableNameList(dbName);
setCurrentDbName(dbName);
}}
>
{dbNameList.map((item) => (
<Select.Option key={item.name} value={item.name}>
{item.name}
</Select.Option>
))}
</Select>
</FormItem>
<FormItem
name="tableName"
label="数据表名"
rules={[{ required: true, message: '请选择数据库/表' }]}
>
<Select
placeholder="请选择数据库/表"
disabled={isEdit}
showSearch
onChange={(tableName: string) => {
// queryTableNameList(tableName);
setCurrentTableName(tableName);
}}
>
{tableNameList.map((item) => (
<Select.Option key={item.name} value={item.name}>
{item.name}
</Select.Option>
))}
</Select>
</FormItem>
</>
)}
<FormItem
name="name"
label="数据源中文名"

View File

@@ -4,18 +4,25 @@ import BasicInfoForm from './DataSourceBasicForm';
import FieldForm from './DataSourceFieldForm';
import { formLayout } from '@/components/FormHelper/utils';
import { EnumDataSourceType } from '../constants';
import type { DataInstanceItem, FieldItem, SaveDataSetForm } from '../data';
import type { DataInstanceItem } from '../data';
import styles from '../style.less';
import { createDatasource, updateDatasource } from '../../service';
import { createDatasource, updateDatasource, getColumns } from '../../service';
import type { Dispatch } from 'umi';
import type { StateType } from '../../model';
import { connect } from 'umi';
export type CreateFormProps = {
domainManger: StateType;
dispatch: Dispatch;
createModalVisible: boolean;
sql: string;
sql?: string;
domainId: number;
dataSourceItem: DataInstanceItem | any;
onCancel?: () => void;
onSubmit?: (dataSourceInfo: any) => void;
scriptColumns: any[];
scriptColumns?: any[] | undefined;
basicInfoFormMode?: 'normal' | 'fast';
onDataBaseTableChange?: (tableName: string) => void;
};
const { Step } = Steps;
@@ -26,30 +33,40 @@ const initFormVal = {
};
const DataSourceCreateForm: React.FC<CreateFormProps> = ({
domainManger,
onCancel,
createModalVisible,
domainId,
scriptColumns,
sql,
sql = '',
onSubmit,
dataSourceItem,
basicInfoFormMode,
}) => {
const isEdit = !!dataSourceItem?.id;
const [fields, setFields] = useState<FieldItem[]>([]);
const [fields, setFields] = useState<any[]>([]);
const [currentStep, setCurrentStep] = useState(0);
const [saveLoading, setSaveLoading] = useState(false);
const formValRef = useRef(initFormVal as any);
const [form] = Form.useForm();
const updateFormVal = (val: SaveDataSetForm) => {
const { dataBaseConfig } = domainManger;
const updateFormVal = (val: any) => {
formValRef.current = val;
};
const [fieldColumns, setFieldColumns] = useState(scriptColumns || []);
useEffect(() => {
if (scriptColumns) {
setFieldColumns(scriptColumns);
}
}, [scriptColumns]);
const forward = () => setCurrentStep(currentStep + 1);
const backward = () => setCurrentStep(currentStep - 1);
const getFieldsClassify = (fieldsList: FieldItem[]) => {
const getFieldsClassify = (fieldsList: any[]) => {
const classify = fieldsList.reduce(
(fieldsClassify, item: FieldItem) => {
(fieldsClassify, item: any) => {
const {
type,
bizName,
@@ -126,11 +143,13 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
forward();
} else {
setSaveLoading(true);
const { dbName, tableName } = submitForm;
const queryParams = {
...submitForm,
sqlQuery: sql,
databaseId: dataSourceItem.databaseId,
queryType: 'sql_query',
databaseId: dataSourceItem?.databaseId || dataBaseConfig.id,
queryType: basicInfoFormMode === 'fast' ? 'table_query' : 'sql_query',
tableQuery: dbName && tableName ? `${dbName}.${tableName}` : '',
domainId,
};
const queryDatasource = isEdit ? updateDatasource : createDatasource;
@@ -149,8 +168,8 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
}
};
const initFields = (fieldsClassifyList: any[]) => {
const columnFields: any[] = scriptColumns.map((item: any) => {
const initFields = (fieldsClassifyList: any[], columns: any[]) => {
const columnFields: any[] = columns.map((item: any) => {
const { type, nameEn } = item;
const oldItem = fieldsClassifyList.find((oItem) => oItem.bizName === item.nameEn) || {};
return {
@@ -181,13 +200,32 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
});
};
const initData = () => {
const initData = async () => {
const { queryType, tableQuery } = dataSourceItem.datasourceDetail;
let tableQueryInitValue = {};
let columns = fieldColumns;
if (queryType === 'table_query') {
const tableQueryString = tableQuery || '';
const [dbName, tableName] = tableQueryString.split('.');
columns = await queryTableColumnList(dbName, tableName);
tableQueryInitValue = {
dbName,
tableName,
};
}
formatterInitData(columns, tableQueryInitValue);
};
const formatterInitData = (columns: any[], extendParams: Record<string, any> = {}) => {
const { id, name, bizName, description, datasourceDetail } = dataSourceItem as any;
const { dimensions, identifiers, measures } = datasourceDetail;
const initValue = {
id,
name,
bizName,
description,
...extendParams,
// ...tableQueryInitValue,
};
const editInitFormVal = {
...formValRef.current,
@@ -195,20 +233,19 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
};
updateFormVal(editInitFormVal);
form.setFieldsValue(initValue);
const { dimensions, identifiers, measures } = datasourceDetail;
const formatFields = [
...formatterDimensions(dimensions || []),
...(identifiers || []),
...formatterMeasures(measures || []),
];
initFields(formatFields);
initFields(formatFields, columns);
};
useEffect(() => {
if (isEdit) {
initData();
} else {
initFields([]);
initFields([], fieldColumns);
}
}, [dataSourceItem]);
@@ -227,11 +264,42 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
setFields(result);
};
const queryTableColumnList = async (dbName: string, tableName: string) => {
if (!dataBaseConfig?.id) {
return;
}
const { code, data, msg } = await getColumns(dataBaseConfig.id, dbName, tableName);
if (code === 200) {
const list = data?.resultList || [];
// setTableNameList(list);
const columns = list.map((item: any) => {
const { dataType, name } = item;
return {
nameEn: name,
type: dataType,
};
});
// setFields(columns);
initFields([], columns);
setFieldColumns(columns);
return columns;
} else {
message.error(msg);
}
};
const renderContent = () => {
if (currentStep === 1) {
return <FieldForm fields={fields} onFieldChange={handleFieldChange} />;
}
return <BasicInfoForm form={form} isEdit={isEdit} />;
return (
<BasicInfoForm
form={form}
isEdit={isEdit}
mode={basicInfoFormMode}
dataBaseConfig={dataBaseConfig}
/>
);
};
const renderFooter = () => {
@@ -280,6 +348,13 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
initialValues={{
...formValRef.current,
}}
onValuesChange={(value, values) => {
const { tableName } = value;
const { dbName } = values;
if (tableName) {
queryTableColumnList(dbName, tableName);
}
}}
className={styles.form}
>
{renderContent()}
@@ -288,4 +363,6 @@ const DataSourceCreateForm: React.FC<CreateFormProps> = ({
);
};
export default DataSourceCreateForm;
export default connect(({ domainManger }: { domainManger: StateType }) => ({
domainManger,
}))(DataSourceCreateForm);

View File

@@ -2,6 +2,7 @@ import React, { useState, useEffect, useRef } from 'react';
import { Button, Table, message, Tooltip, Space, Dropdown } from 'antd';
import SplitPane from 'react-split-pane';
import Pane from 'react-split-pane/lib/Pane';
import { connect } from 'umi';
import sqlFormatter from 'sql-formatter';
import {
FullscreenOutlined,
@@ -15,10 +16,12 @@ import {
import { isFunction } from 'lodash';
import FullScreen from '@/components/FullScreen';
import SqlEditor from '@/components/SqlEditor';
import type { TaskResultParams, TaskResultItem, DataInstanceItem, TaskResultColumn } from '../data';
import { excuteSql } from '../service';
import { getDatabaseByDomainId } from '../../service';
import type { TaskResultItem, DataInstanceItem, TaskResultColumn } from '../data';
import { excuteSql } from '@/pages/SemanticModel/service';
// import { getDatabaseByDomainId } from '../../service';
import DataSourceCreateForm from './DataSourceCreateForm';
import type { Dispatch } from 'umi';
import type { StateType } from '../../model';
import styles from '../style.less';
import 'ace-builds/src-min-noconflict/ext-searchbox';
@@ -27,7 +30,8 @@ import 'ace-builds/src-min-noconflict/theme-monokai';
import 'ace-builds/src-min-noconflict/mode-sql';
type IProps = {
oprType: 'add' | 'edit';
domainManger: StateType;
dispatch: Dispatch;
dataSourceItem: DataInstanceItem;
domainId: number;
onUpdateSql?: (sql: string) => void;
@@ -52,6 +56,7 @@ type JdbcSourceItems = {
};
const SqlDetail: React.FC<IProps> = ({
domainManger,
dataSourceItem,
onSubmitSuccess,
domainId,
@@ -59,6 +64,7 @@ const SqlDetail: React.FC<IProps> = ({
onUpdateSql,
onJdbcSourceChange,
}) => {
const { dataBaseConfig } = domainManger;
const [resultTable, setResultTable] = useState<ResultTableItem[]>([]);
const [resultTableLoading, setResultTableLoading] = useState(false);
const [resultCols, setResultCols] = useState<ResultColItem[]>([]);
@@ -111,20 +117,30 @@ const SqlDetail: React.FC<IProps> = ({
// return 'ClickHouse';
// });
const queryDatabaseConfig = async () => {
const { code, data } = await getDatabaseByDomainId(domainId);
if (code === 200) {
setJdbcSourceItems([
{
label: data?.name,
key: data?.id,
},
]);
onJdbcSourceChange?.(data?.id && Number(data?.id));
return;
}
message.error('数据库配置获取错误');
};
useEffect(() => {
setJdbcSourceItems([
{
label: dataBaseConfig?.name,
key: dataBaseConfig?.id,
},
]);
onJdbcSourceChange?.(dataBaseConfig?.id && Number(dataBaseConfig?.id));
}, [dataBaseConfig]);
// const queryDatabaseConfig = async () => {
// const { code, data } = await getDatabaseByDomainId(domainId);
// if (code === 200) {
// setJdbcSourceItems([
// {
// label: data?.name,
// key: data?.id,
// },
// ]);
// onJdbcSourceChange?.(data?.id && Number(data?.id));
// return;
// }
// message.error('数据库配置获取错误');
// };
function creatCalcItem(key: string, data: string) {
const line = document.createElement('div'); // 需要每条数据一行,这样避免数据换行的时候获得的宽度不准确
@@ -185,7 +201,7 @@ const SqlDetail: React.FC<IProps> = ({
}
};
const fetchTaskResult = (params: TaskResultParams) => {
const fetchTaskResult = (params) => {
setResultTable(
params.resultList.map((item, index) => {
return {
@@ -367,7 +383,7 @@ const SqlDetail: React.FC<IProps> = ({
}, [resultTable, isSqlResFullScreen]);
useEffect(() => {
queryDatabaseConfig();
// queryDatabaseConfig();
const windowHeight = window.innerHeight;
let size: ScreenSize = 'small';
if (windowHeight > 1100) {
@@ -527,4 +543,6 @@ const SqlDetail: React.FC<IProps> = ({
);
};
export default SqlDetail;
export default connect(({ domainManger }: { domainManger: StateType }) => ({
domainManger,
}))(SqlDetail);

View File

@@ -1,7 +1,6 @@
import React, { useState, useRef, useEffect } from 'react';
import { Tabs } from 'antd';
import SqlDetail from './SqlDetail';
import type { SqlItem } from '../data';
import styles from '../style.less';
@@ -11,7 +10,6 @@ type Panes = {
type: 'add' | 'edit';
scriptId?: number;
sql?: string;
sqlInfo?: SqlItem;
isSave?: boolean; // 暂存提示保存
};

View File

@@ -0,0 +1,16 @@
// 数据类型
export type DataInstanceItem = {
sourceInstanceId: number; // 数据实例id
sourceInstanceName: string; // 数据实例名
defaultSourceId: number; // 查询表需要的默认datasource id
bindSourceId: number;
};
// 任务查询结果列
export type TaskResultColumn = {
name: string;
type: string;
};
// 任务查询结果
export type TaskResultItem = Record<string, string | number>;

View File

@@ -1,12 +0,0 @@
import request from 'umi-request';
type ExcuteSqlParams = {
sql: string;
domainId: number;
};
// 执行脚本
export async function excuteSql(params: ExcuteSqlParams) {
const data = { ...params };
return request.post(`${process.env.API_BASE_URL}database/executeSql`, { data });
}