mirror of
https://github.com/CodePhiliaX/Chat2DB.git
synced 2025-08-02 04:43:35 +08:00
Merge remote-tracking branch 'origin/developing' into developing
This commit is contained in:
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -11,6 +11,7 @@
|
|||||||
"ahooks",
|
"ahooks",
|
||||||
"antd",
|
"antd",
|
||||||
"asar",
|
"asar",
|
||||||
|
"bgcolor",
|
||||||
"cascader",
|
"cascader",
|
||||||
"datasource",
|
"datasource",
|
||||||
"echart",
|
"echart",
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ant-spin-container {
|
.ant-spin-container {
|
||||||
height: 100%;
|
height: calc(100% - 48px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ import { IAIState } from '@/models/ai';
|
|||||||
import Popularize from '@/components/Popularize';
|
import Popularize from '@/components/Popularize';
|
||||||
import { handleLocalStorageSavedConsole, readLocalStorageSavedConsoleText } from '@/utils';
|
import { handleLocalStorageSavedConsole, readLocalStorageSavedConsoleText } from '@/utils';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
|
import { chatErrorCodeArr } from '@/constants/chat';
|
||||||
|
|
||||||
enum IPromptType {
|
enum IPromptType {
|
||||||
NL_2_SQL = 'NL_2_SQL',
|
NL_2_SQL = 'NL_2_SQL',
|
||||||
@ -195,6 +196,14 @@ function Console(props: IProps) {
|
|||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const hasError = chatErrorCodeArr.includes(message);
|
||||||
|
//TODO:
|
||||||
|
if (hasError) {
|
||||||
|
closeEventSource();
|
||||||
|
setIsLoading(false);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const isEOF = message === '[DONE]';
|
const isEOF = message === '[DONE]';
|
||||||
if (isEOF) {
|
if (isEOF) {
|
||||||
closeEventSource();
|
closeEventSource();
|
||||||
@ -306,7 +315,7 @@ function Console(props: IProps) {
|
|||||||
onPressEnter={onPressChatInput}
|
onPressEnter={onPressChatInput}
|
||||||
selectedTables={selectedTables}
|
selectedTables={selectedTables}
|
||||||
onSelectTables={(tables: string[]) => {
|
onSelectTables={(tables: string[]) => {
|
||||||
if(tables.length > 8){
|
if (tables.length > 8) {
|
||||||
message.warning({
|
message.warning({
|
||||||
content: i18n('chat.input.tableSelect.error.TooManyTable')
|
content: i18n('chat.input.tableSelect.error.TooManyTable')
|
||||||
})
|
})
|
||||||
@ -332,7 +341,7 @@ function Console(props: IProps) {
|
|||||||
onExecute={executeSQL}
|
onExecute={executeSQL}
|
||||||
options={props.editorOptions}
|
options={props.editorOptions}
|
||||||
tables={props.tables}
|
tables={props.tables}
|
||||||
// onChange={}
|
// onChange={}
|
||||||
/>
|
/>
|
||||||
{/* <Modal open={modelConfig.open}>{modelConfig.content}</Modal> */}
|
{/* <Modal open={modelConfig.open}>{modelConfig.content}</Modal> */}
|
||||||
<Drawer open={isAiDrawerOpen} getContainer={false} mask={false} onClose={() => setIsAiDrawerOpen(false)}>
|
<Drawer open={isAiDrawerOpen} getContainer={false} mask={false} onClose={() => setIsAiDrawerOpen(false)}>
|
||||||
|
@ -96,23 +96,6 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [
|
|||||||
name: 'url',
|
name: 'url',
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
defaultValue: '8.0',
|
|
||||||
inputType: InputType.SELECT,
|
|
||||||
labelNameCN: 'JDBC驱动',
|
|
||||||
labelNameEN: 'JDBC Driver',
|
|
||||||
name: 'jdbc',
|
|
||||||
required: true,
|
|
||||||
selects: [
|
|
||||||
{
|
|
||||||
value: '8.0',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: '5.0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
pattern: /jdbc:mysql:\/\/(.*):(\d+)(\/(\w+))?/,
|
pattern: /jdbc:mysql:\/\/(.*):(\d+)(\/(\w+))?/,
|
||||||
template: 'jdbc:mysql://{host}:{port}/{database}',
|
template: 'jdbc:mysql://{host}:{port}/{database}',
|
||||||
@ -3061,3 +3044,34 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [
|
|||||||
type: DatabaseTypeCode.MONGODB
|
type: DatabaseTypeCode.MONGODB
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const driveConfig: IConnectionConfig['drive'] = {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
defaultValue: '',
|
||||||
|
inputType: InputType.SELECT,
|
||||||
|
labelNameCN: 'jdbcDriver',
|
||||||
|
labelNameEN: 'jdbcDriver',
|
||||||
|
name: 'jdbcDriver',
|
||||||
|
required: false,
|
||||||
|
selects: [
|
||||||
|
{
|
||||||
|
value: '1',
|
||||||
|
label: '/Users/wangjiaqi/Desktop/Chat2DB/chat2db-client/src/components/CreateConnection/config/dataSource.ts'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '2',
|
||||||
|
label: '/222222Users/wangjiaqi/Desktop/Chat2DB/chat2db-client/src/components/CreateConnection/config/dataSource.ts'
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// defaultValue: '',
|
||||||
|
// inputType: InputType.INPUT,
|
||||||
|
// labelNameCN: 'jdbcDriverClass',
|
||||||
|
// labelNameEN: 'jdbcDriverClass',
|
||||||
|
// name: 'jdbcDriverClass',
|
||||||
|
// required: false,
|
||||||
|
// },
|
||||||
|
]
|
||||||
|
};
|
||||||
|
@ -4,6 +4,9 @@ import { DatabaseTypeCode, OperationColumn } from '@/constants';
|
|||||||
export type ISelect = {
|
export type ISelect = {
|
||||||
value?: AuthenticationType | SSHAuthenticationType | string;
|
value?: AuthenticationType | SSHAuthenticationType | string;
|
||||||
label?: string;
|
label?: string;
|
||||||
|
rest?: {
|
||||||
|
[key in string]: any
|
||||||
|
}
|
||||||
items?: IFormItem[];
|
items?: IFormItem[];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -34,6 +37,9 @@ export type IConnectionConfig = {
|
|||||||
template: string;
|
template: string;
|
||||||
excludes?: OperationColumn[];
|
excludes?: OperationColumn[];
|
||||||
},
|
},
|
||||||
|
drive?: {
|
||||||
|
items: IFormItem[];
|
||||||
|
}
|
||||||
ssh: {
|
ssh: {
|
||||||
items: IFormItem[];
|
items: IFormItem[];
|
||||||
},
|
},
|
||||||
|
@ -13,7 +13,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.connectionBox {
|
.connectionBox {
|
||||||
width: 100%;
|
width: 65%;
|
||||||
|
flex-shrink: 0;
|
||||||
padding: 20px 20%;
|
padding: 20px 20%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,6 +111,34 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.downloadDriveFooter{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.downloadDrive{
|
||||||
|
display: flex;
|
||||||
|
.downloadText{
|
||||||
|
margin-right: 4px;
|
||||||
|
color: var(--color-primary);
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover{
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.downloadTextError{
|
||||||
|
color: var(--color-error-text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.uploadCustomDrive{
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover{
|
||||||
|
color: var(--color-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.extendTable {
|
.extendTable {
|
||||||
max-height: 300px;
|
max-height: 300px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
@ -3,21 +3,22 @@ import { i18n, isEn } from '@/i18n';
|
|||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
|
||||||
import connectionService from '@/service/connection';
|
import connectionService, { IDriverResponse } from '@/service/connection';
|
||||||
|
|
||||||
import { DatabaseTypeCode, ConnectionEnvType, databaseMap } from '@/constants';
|
import { DatabaseTypeCode, ConnectionEnvType, databaseMap } from '@/constants';
|
||||||
import { dataSourceFormConfigs } from './config/dataSource';
|
import { dataSourceFormConfigs, driveConfig } from './config/dataSource';
|
||||||
import { IConnectionConfig, IFormItem, ISelect } from './config/types';
|
import { IConnectionConfig, IFormItem, ISelect } from './config/types';
|
||||||
import { IConnectionDetails } from '@/typings';
|
import { IConnectionDetails } from '@/typings';
|
||||||
import { InputType } from './config/enum';
|
import { InputType } from './config/enum';
|
||||||
import { deepClone } from '@/utils';
|
import { deepClone } from '@/utils';
|
||||||
import { Select, Form, Input, message, Table, Button, Collapse } from 'antd';
|
import { Select, Form, Input, message, Table, Button, Collapse, Modal } from 'antd';
|
||||||
import Iconfont from '@/components/Iconfont';
|
import Iconfont from '@/components/Iconfont';
|
||||||
import LoadingContent from '@/components/Loading/LoadingContent';
|
import LoadingContent from '@/components/Loading/LoadingContent';
|
||||||
|
import UploadDriver from '@/components/UploadDriver';
|
||||||
|
|
||||||
const { Option } = Select;
|
const { Option } = Select;
|
||||||
|
|
||||||
type ITabsType = 'ssh' | 'baseInfo';
|
type ITabsType = 'ssh' | 'baseInfo' | 'drive';
|
||||||
|
|
||||||
export enum submitType {
|
export enum submitType {
|
||||||
UPDATE = 'update',
|
UPDATE = 'update',
|
||||||
@ -32,18 +33,44 @@ interface IProps {
|
|||||||
submitCallback?: Function;
|
submitCallback?: Function;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum DownloadStatus {
|
||||||
|
Default,
|
||||||
|
Loading,
|
||||||
|
Error,
|
||||||
|
Success
|
||||||
|
}
|
||||||
|
|
||||||
export default function CreateConnection(props: IProps) {
|
export default function CreateConnection(props: IProps) {
|
||||||
const { className, closeCreateConnection, submitCallback } = props;
|
const { className, closeCreateConnection, submitCallback, connectionData } = props;
|
||||||
const [baseInfoForm] = Form.useForm();
|
const [baseInfoForm] = Form.useForm();
|
||||||
const [sshForm] = Form.useForm();
|
const [sshForm] = Form.useForm();
|
||||||
const [backfillData, setBackfillData] = useState<IConnectionDetails>(props.connectionData);
|
const [driveForm] = Form.useForm();
|
||||||
|
const [backfillData, setBackfillData] = useState<IConnectionDetails>(connectionData);
|
||||||
const [loadings, setLoading] = useState({
|
const [loadings, setLoading] = useState({
|
||||||
confirmButton: false,
|
confirmButton: false,
|
||||||
testButton: false,
|
testButton: false,
|
||||||
backfillDataLoading: false
|
backfillDataLoading: false
|
||||||
});
|
});
|
||||||
// const [connectionData, setConnectionData] = useState<IConnectionDetails>(props.connectionData);
|
const [downloadStatus, setDownloadStatus] = useState<DownloadStatus>(DownloadStatus.Default);
|
||||||
// const [currentType, setCurrentType] = useState<DatabaseTypeCode>(createType || DatabaseTypeCode.MYSQL);
|
const [uploadDriverModal, setUploadDriverModal] = useState(false);
|
||||||
|
const [driverObj, setDriverObj] = useState<IDriverResponse>();
|
||||||
|
const [driverSaved, setDriverSaved] = useState<any>({});
|
||||||
|
const dataSourceFormConfigPropsMemo = useMemo<IConnectionConfig>(() => {
|
||||||
|
const deepCloneDataSourceFormConfigs = deepClone(dataSourceFormConfigs)
|
||||||
|
return deepCloneDataSourceFormConfigs.find((t: IConnectionConfig) => {
|
||||||
|
const flag = t.type === backfillData.type;
|
||||||
|
if (flag) {
|
||||||
|
t.drive = driveConfig;
|
||||||
|
}
|
||||||
|
return flag
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getDriverList()
|
||||||
|
}, [backfillData.type])
|
||||||
|
|
||||||
|
const [dataSourceFormConfigProps, setDataSourceFormConfigProps] = useState(dataSourceFormConfigPropsMemo);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setBackfillData(props.connectionData);
|
setBackfillData(props.connectionData);
|
||||||
@ -55,6 +82,26 @@ export default function CreateConnection(props: IProps) {
|
|||||||
}
|
}
|
||||||
}, [backfillData.id]);
|
}, [backfillData.id]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (driverObj?.driverConfigList?.length) {
|
||||||
|
const deepCloneDataSourceFormConfigs = deepClone(dataSourceFormConfigs)
|
||||||
|
const newDataSourceFormConfigProps = deepCloneDataSourceFormConfigs.find((t: IConnectionConfig) => {
|
||||||
|
const flag = t.type === backfillData.type;
|
||||||
|
if (flag) {
|
||||||
|
t.drive = driveConfig;
|
||||||
|
}
|
||||||
|
return flag
|
||||||
|
});
|
||||||
|
newDataSourceFormConfigProps.drive!.items[0].selects = driverObj?.driverConfigList.map(t => {
|
||||||
|
return {
|
||||||
|
value: t.jdbcDriver,
|
||||||
|
label: t.jdbcDriver
|
||||||
|
}
|
||||||
|
})
|
||||||
|
setDataSourceFormConfigProps(newDataSourceFormConfigProps)
|
||||||
|
}
|
||||||
|
}, [driverObj])
|
||||||
|
|
||||||
function getConnectionDetails(id: number) {
|
function getConnectionDetails(id: number) {
|
||||||
setLoading({
|
setLoading({
|
||||||
...loadings,
|
...loadings,
|
||||||
@ -81,12 +128,54 @@ export default function CreateConnection(props: IProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const getItems = () => [
|
const getItems = () => [
|
||||||
|
{
|
||||||
|
key: 'drive',
|
||||||
|
label: 'Drive',
|
||||||
|
children: (
|
||||||
|
<div className={styles.sshBox}>
|
||||||
|
<RenderForm
|
||||||
|
dataSourceFormConfigProps={dataSourceFormConfigProps}
|
||||||
|
backfillData={backfillData!}
|
||||||
|
form={driveForm}
|
||||||
|
tab="drive"
|
||||||
|
/>
|
||||||
|
<div className={styles.downloadDriveFooter}>
|
||||||
|
{
|
||||||
|
!!driverObj?.driverConfigList?.length ? <div></div> : <div onClick={downloadDrive} className={styles.downloadDrive}>
|
||||||
|
{
|
||||||
|
(downloadStatus === DownloadStatus.Default) && <div className={styles.downloadText}>Download</div>
|
||||||
|
}
|
||||||
|
{
|
||||||
|
(downloadStatus === DownloadStatus.Loading) && <div className={styles.downloadText}>Downloading</div>
|
||||||
|
}
|
||||||
|
{
|
||||||
|
(downloadStatus === DownloadStatus.Error) && <div className={classnames(styles.downloadText, styles.downloadTextError)}>Try again download</div>
|
||||||
|
}
|
||||||
|
{i18n('connection.title.driver')}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<div
|
||||||
|
className={styles.uploadCustomDrive}
|
||||||
|
onClick={() => { setUploadDriverModal(true) }}
|
||||||
|
>
|
||||||
|
{i18n('connection.tips.customUpload')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'ssh',
|
key: 'ssh',
|
||||||
label: 'SSH Configuration',
|
label: 'SSH Configuration',
|
||||||
children: (
|
children: (
|
||||||
<div className={styles.sshBox}>
|
<div className={styles.sshBox}>
|
||||||
<RenderForm backfillData={backfillData!} form={sshForm} tab="ssh" />
|
<RenderForm
|
||||||
|
dataSourceFormConfigProps={dataSourceFormConfigProps}
|
||||||
|
backfillData={backfillData!}
|
||||||
|
form={sshForm}
|
||||||
|
tab="ssh"
|
||||||
|
/>
|
||||||
<div className={styles.testSSHConnect}>
|
<div className={styles.testSSHConnect}>
|
||||||
<div onClick={testSSH} className={styles.testSSHConnectText}>
|
<div onClick={testSSH} className={styles.testSSHConnectText}>
|
||||||
{i18n('connection.message.testSshConnection')}
|
{i18n('connection.message.testSshConnection')}
|
||||||
@ -109,6 +198,7 @@ export default function CreateConnection(props: IProps) {
|
|||||||
// 测试、保存、修改连接
|
// 测试、保存、修改连接
|
||||||
function saveConnection(type: submitType) {
|
function saveConnection(type: submitType) {
|
||||||
const ssh = sshForm.getFieldsValue();
|
const ssh = sshForm.getFieldsValue();
|
||||||
|
const driverConfig = driveForm.getFieldsValue()
|
||||||
const baseInfo = baseInfoForm.getFieldsValue();
|
const baseInfo = baseInfoForm.getFieldsValue();
|
||||||
const extendInfo: any = [];
|
const extendInfo: any = [];
|
||||||
const loadingsButton = type === submitType.TEST ? 'testButton' : 'confirmButton';
|
const loadingsButton = type === submitType.TEST ? 'testButton' : 'confirmButton';
|
||||||
@ -123,10 +213,10 @@ export default function CreateConnection(props: IProps) {
|
|||||||
|
|
||||||
let p: any = {
|
let p: any = {
|
||||||
ssh,
|
ssh,
|
||||||
|
driverConfig,
|
||||||
...baseInfo,
|
...baseInfo,
|
||||||
extendInfo,
|
extendInfo,
|
||||||
// ...values,
|
connectionEnvType: ConnectionEnvType.DAILY,
|
||||||
ConnectionEnvType: ConnectionEnvType.DAILY,
|
|
||||||
type: backfillData.type,
|
type: backfillData.type,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -185,6 +275,32 @@ export default function CreateConnection(props: IProps) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function downloadDrive() {
|
||||||
|
setDownloadStatus(DownloadStatus.Loading)
|
||||||
|
connectionService.downloadDriver({ dbType: backfillData.type }).then(res => {
|
||||||
|
setDownloadStatus(DownloadStatus.Success)
|
||||||
|
}).catch(() => {
|
||||||
|
setDownloadStatus(DownloadStatus.Error)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDriverList() {
|
||||||
|
connectionService.getDriverList({ dbType: backfillData.type }).then(res => {
|
||||||
|
setDriverObj(res)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function formChange(data: any) {
|
||||||
|
setDriverSaved(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveDriver() {
|
||||||
|
connectionService.saveDriver(driverSaved).then(res => {
|
||||||
|
setUploadDriverModal(false)
|
||||||
|
getDriverList()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classnames(styles.box, className)}>
|
<div className={classnames(styles.box, className)}>
|
||||||
<LoadingContent className={styles.loadingContent} data={!loadings.backfillDataLoading}>
|
<LoadingContent className={styles.loadingContent} data={!loadings.backfillDataLoading}>
|
||||||
@ -194,9 +310,9 @@ export default function CreateConnection(props: IProps) {
|
|||||||
<div>{databaseMap[backfillData.type]?.name}</div>
|
<div>{databaseMap[backfillData.type]?.name}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.baseInfoBox}>
|
<div className={styles.baseInfoBox}>
|
||||||
<RenderForm backfillData={backfillData!} form={baseInfoForm} tab="baseInfo" />
|
<RenderForm dataSourceFormConfigProps={dataSourceFormConfigProps} backfillData={backfillData!} form={baseInfoForm} tab="baseInfo" />
|
||||||
</div>
|
</div>
|
||||||
<Collapse items={getItems()} />
|
<Collapse defaultActiveKey={['drive']} items={getItems()} />
|
||||||
<div className={styles.formFooter}>
|
<div className={styles.formFooter}>
|
||||||
<div className={styles.test}>
|
<div className={styles.test}>
|
||||||
{
|
{
|
||||||
@ -225,6 +341,19 @@ export default function CreateConnection(props: IProps) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</LoadingContent>
|
</LoadingContent>
|
||||||
|
<Modal
|
||||||
|
destroyOnClose={true}
|
||||||
|
title={i18n('connection.title.uploadDriver')}
|
||||||
|
open={uploadDriverModal}
|
||||||
|
onOk={() => { saveDriver() }}
|
||||||
|
onCancel={() => { setUploadDriverModal(false) }}
|
||||||
|
>
|
||||||
|
<UploadDriver
|
||||||
|
jdbcDriverClass={driverObj?.defaultDriverConfig?.jdbcDriverClass}
|
||||||
|
formChange={formChange}
|
||||||
|
databaseType={backfillData.type}
|
||||||
|
></UploadDriver>
|
||||||
|
</Modal>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -233,29 +362,25 @@ interface IRenderFormProps {
|
|||||||
tab: ITabsType;
|
tab: ITabsType;
|
||||||
form: any;
|
form: any;
|
||||||
backfillData: IConnectionDetails;
|
backfillData: IConnectionDetails;
|
||||||
|
dataSourceFormConfigProps: IConnectionConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
function RenderForm(props: IRenderFormProps) {
|
function RenderForm(props: IRenderFormProps) {
|
||||||
const { tab, form, backfillData } = props;
|
const { tab, form, backfillData, dataSourceFormConfigProps } = props;
|
||||||
const editId = backfillData.id;
|
useEffect(() => {
|
||||||
const databaseType = backfillData.type;
|
form.resetFields()
|
||||||
|
}, [backfillData.id, backfillData.type])
|
||||||
|
|
||||||
let aliasChanged = false;
|
let aliasChanged = false;
|
||||||
|
|
||||||
const dataSourceFormConfigMemo = useMemo<IConnectionConfig>(() => {
|
const [dataSourceFormConfig, setDataSourceFormConfig] = useState<IConnectionConfig>(dataSourceFormConfigProps);
|
||||||
return deepClone(dataSourceFormConfigs).find((t: IConnectionConfig) => {
|
|
||||||
return t.type === databaseType;
|
|
||||||
});
|
|
||||||
}, [databaseType]);
|
|
||||||
|
|
||||||
const [dataSourceFormConfig, setDataSourceFormConfig] = useState<IConnectionConfig>(dataSourceFormConfigMemo);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setDataSourceFormConfig(dataSourceFormConfigMemo);
|
setDataSourceFormConfig(dataSourceFormConfigProps)
|
||||||
}, [databaseType]);
|
}, [dataSourceFormConfigProps])
|
||||||
|
|
||||||
const initialValuesMemo = useMemo(() => {
|
const initialValuesMemo = useMemo(() => {
|
||||||
return initialFormData(dataSourceFormConfigMemo[tab].items);
|
return initialFormData(dataSourceFormConfigProps[tab]?.items);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const [initialValues] = useState(initialValuesMemo);
|
const [initialValues] = useState(initialValuesMemo);
|
||||||
@ -273,6 +398,9 @@ function RenderForm(props: IRenderFormProps) {
|
|||||||
if (tab === 'ssh') {
|
if (tab === 'ssh') {
|
||||||
regEXFormatting({}, backfillData.ssh || {});
|
regEXFormatting({}, backfillData.ssh || {});
|
||||||
}
|
}
|
||||||
|
if (tab === 'drive') {
|
||||||
|
regEXFormatting({}, backfillData.driverConfig || {});
|
||||||
|
}
|
||||||
}, [backfillData]);
|
}, [backfillData]);
|
||||||
|
|
||||||
function initialFormData(dataSourceFormConfig: IFormItem[] | undefined) {
|
function initialFormData(dataSourceFormConfig: IFormItem[] | undefined) {
|
||||||
@ -294,7 +422,7 @@ function RenderForm(props: IRenderFormProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function selectChange(t: { name: string; value: any }) {
|
function selectChange(t: { name: string; value: any }) {
|
||||||
dataSourceFormConfig[tab].items.map((j, i) => {
|
dataSourceFormConfig[tab]?.items.map((j, i) => {
|
||||||
if (j.name === t.name) {
|
if (j.name === t.name) {
|
||||||
j.defaultValue = t.value;
|
j.defaultValue = t.value;
|
||||||
}
|
}
|
||||||
@ -366,6 +494,7 @@ function RenderForm(props: IRenderFormProps) {
|
|||||||
if (keyName === 'host' && !aliasChanged) {
|
if (keyName === 'host' && !aliasChanged) {
|
||||||
newData.alias = '@' + keyValue;
|
newData.alias = '@' + keyValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
form.setFieldsValue({
|
form.setFieldsValue({
|
||||||
...dataObj,
|
...dataObj,
|
||||||
...newData,
|
...newData,
|
||||||
@ -458,23 +587,33 @@ function RenderForm(props: IRenderFormProps) {
|
|||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IRenderExtendTableProps {
|
interface IRenderExtendTableProps {
|
||||||
backfillData: IConnectionDetails;
|
backfillData: IConnectionDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
let extendTableData: any = [];
|
let extendTableData: any = [];
|
||||||
|
|
||||||
|
interface IExtendTable {
|
||||||
|
key: number,
|
||||||
|
label: string,
|
||||||
|
value: string
|
||||||
|
}
|
||||||
|
|
||||||
function RenderExtendTable(props: IRenderExtendTableProps) {
|
function RenderExtendTable(props: IRenderExtendTableProps) {
|
||||||
const { backfillData } = props;
|
const { backfillData } = props;
|
||||||
const databaseType = backfillData.type;
|
const databaseType = backfillData.type;
|
||||||
|
const [data, setData] = useState<IExtendTable[]>([{ key: 0, label: '', value: '' }]);
|
||||||
const dataSourceFormConfigMemo = useMemo<IConnectionConfig>(() => {
|
const dataSourceFormConfigMemo = useMemo<IConnectionConfig>(() => {
|
||||||
return deepClone(dataSourceFormConfigs).find((t: IConnectionConfig) => {
|
return deepClone(dataSourceFormConfigs).find((t: IConnectionConfig) => {
|
||||||
return t.type === databaseType;
|
return t.type === databaseType;
|
||||||
});
|
});
|
||||||
}, [backfillData.type]);
|
}, [backfillData.type]);
|
||||||
|
|
||||||
const extendInfo =
|
useEffect(() => {
|
||||||
dataSourceFormConfigMemo.extendInfo?.map((t, i) => {
|
const extendInfoList = backfillData?.extendInfo?.length ? backfillData?.extendInfo : dataSourceFormConfigMemo.extendInfo;
|
||||||
|
|
||||||
|
const extendInfo = extendInfoList?.map((t, i) => {
|
||||||
return {
|
return {
|
||||||
key: i,
|
key: i,
|
||||||
label: t.key,
|
label: t.key,
|
||||||
@ -482,19 +621,8 @@ function RenderExtendTable(props: IRenderExtendTableProps) {
|
|||||||
};
|
};
|
||||||
}) || [];
|
}) || [];
|
||||||
|
|
||||||
const [data, setData] = useState([...extendInfo, { key: extendInfo.length, label: '', value: '' }]);
|
setData([...extendInfo, { key: extendInfo.length, label: '', value: '' }])
|
||||||
|
}, [dataSourceFormConfigMemo, backfillData])
|
||||||
useEffect(() => {
|
|
||||||
const backfillDataExtendInfo =
|
|
||||||
(backfillData?.extendInfo || []).map((t, i) => {
|
|
||||||
return {
|
|
||||||
key: i,
|
|
||||||
label: t.key,
|
|
||||||
value: t.value,
|
|
||||||
};
|
|
||||||
}) || [];
|
|
||||||
setData([...backfillDataExtendInfo, { key: extendInfo.length, label: '', value: '' }]);
|
|
||||||
}, [backfillData]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
extendTableData = data;
|
extendTableData = data;
|
||||||
|
@ -1,7 +1,38 @@
|
|||||||
@import '../../styles/var.less';
|
@import '../../styles/var.less';
|
||||||
|
|
||||||
.notification{
|
|
||||||
padding: 10px 16px;
|
:global {
|
||||||
|
.ant-notification-notice {
|
||||||
|
background-color: var(--color-bg-elevated) !important;
|
||||||
|
padding: 8px 16px !important;
|
||||||
|
width: 280px !important;
|
||||||
|
|
||||||
|
.ant-notification-notice-icon {
|
||||||
|
font-size: 16px !important;
|
||||||
|
top: 12px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-notification-notice-message {
|
||||||
|
color: var(--color-text) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-notification-notice-close {
|
||||||
|
color: var(--color-text) !important
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-modal-content {
|
||||||
|
background-color: var(--color-bg-elevated) !important;
|
||||||
|
|
||||||
|
.ant-modal-confirm-title {
|
||||||
|
color: var(--color-text) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-modal-confirm-content {
|
||||||
|
color: var(--color-text) !important;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.message {
|
.message {
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { Button, Modal, notification, } from 'antd';
|
import { Button, ConfigProvider, Modal, notification, } from 'antd';
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styles from './index.less'
|
import styles from './index.less'
|
||||||
import i18n from '@/i18n';
|
import i18n from '@/i18n';
|
||||||
|
import { IconType } from 'antd/es/notification/interface';
|
||||||
// import { staticNotification } from '@/layouts'
|
// import { staticNotification } from '@/layouts'
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
@ -22,14 +23,12 @@ function MyNotification(props: IProps) {
|
|||||||
|
|
||||||
const type = props.type || 'warning';
|
const type = props.type || 'warning';
|
||||||
const title = `${errorCode}:${errorMessage}`;
|
const title = `${errorCode}:${errorMessage}`;
|
||||||
const message = props.message || <div className={styles.message}>{errorCode}:{errorMessage}</div>
|
const message = props.message || <div className={styles.message}>{errorCode}:{errorMessage || 'Error'}</div>
|
||||||
|
|
||||||
const description = <div className={styles.description}>
|
const description = <div className={styles.description}>
|
||||||
<Button style={{ 'marginRight': '8px' }} type='link' onClick={() => {
|
<Button style={{ 'marginRight': '8px' }} type='link' onClick={() => {
|
||||||
Modal.info({
|
Modal.info({
|
||||||
bodyStyle: {
|
width: 620,
|
||||||
width: '320px'
|
|
||||||
},
|
|
||||||
title,
|
title,
|
||||||
content: errorDetail
|
content: errorDetail
|
||||||
})
|
})
|
||||||
@ -40,7 +39,6 @@ function MyNotification(props: IProps) {
|
|||||||
|
|
||||||
return notification.open({
|
return notification.open({
|
||||||
...props,
|
...props,
|
||||||
className: styles.notification,
|
|
||||||
type,
|
type,
|
||||||
message,
|
message,
|
||||||
description,
|
description,
|
||||||
|
4
chat2db-client/src/components/UploadDriver/index.less
Normal file
4
chat2db-client/src/components/UploadDriver/index.less
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
@import '../../styles/var.less';
|
||||||
|
|
||||||
|
.box {
|
||||||
|
}
|
68
chat2db-client/src/components/UploadDriver/index.tsx
Normal file
68
chat2db-client/src/components/UploadDriver/index.tsx
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import React, { memo, useEffect, useState, useRef } from 'react';
|
||||||
|
import i18n from '@/i18n'
|
||||||
|
import styles from './index.less';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
import { Button, message, Upload, Form, Input } from 'antd';
|
||||||
|
import type { UploadProps } from 'antd';
|
||||||
|
import connectionService from '@/service/connection';
|
||||||
|
import { DatabaseTypeCode } from '@/constants'
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
className?: string;
|
||||||
|
databaseType: DatabaseTypeCode;
|
||||||
|
formChange: Function;
|
||||||
|
jdbcDriverClass: string | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo<IProps>(function UploadDriver(props) {
|
||||||
|
const { className, databaseType = DatabaseTypeCode.MYSQL, formChange, jdbcDriverClass } = props;
|
||||||
|
const [formData, setFormData] = useState<any>({
|
||||||
|
dbType: databaseType,
|
||||||
|
jdbcDriverClass: jdbcDriverClass,
|
||||||
|
jdbcDriver: []
|
||||||
|
});
|
||||||
|
|
||||||
|
const uploadProps: UploadProps = {
|
||||||
|
name: 'multipartFiles',
|
||||||
|
action: `${window._BaseURL}/api/jdbc/driver/upload`,
|
||||||
|
multiple: true,
|
||||||
|
onChange(info) {
|
||||||
|
if (info.file.percent === 100 && info.file?.response?.data?.[0]) {
|
||||||
|
setFormData({
|
||||||
|
...formData,
|
||||||
|
jdbcDriver: [...(formData.jdbcDriver), info.file?.response?.data?.[0]]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
formChange(formData)
|
||||||
|
}, [formData])
|
||||||
|
|
||||||
|
function onChange(e: any) {
|
||||||
|
setFormData({
|
||||||
|
...formData,
|
||||||
|
jdbcDriverClass: e.target.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className={classnames(styles.box, className)}>
|
||||||
|
<div>
|
||||||
|
<Form
|
||||||
|
name="basic"
|
||||||
|
labelCol={{ span: 5 }}
|
||||||
|
wrapperCol={{ span: 16 }}
|
||||||
|
>
|
||||||
|
<Form.Item label="jdbcDriverClass">
|
||||||
|
<Input value={formData.jdbcDriverClass} onChange={onChange} />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label={i18n('connection.title.uploadDriver')}>
|
||||||
|
<Upload {...uploadProps}>
|
||||||
|
<Button>{i18n('connection.button.clickUpload')}</Button>
|
||||||
|
</Upload>
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
</div >
|
||||||
|
})
|
15
chat2db-client/src/constants/chat.ts
Normal file
15
chat2db-client/src/constants/chat.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
|
||||||
|
export const chatError = {
|
||||||
|
"CHAT2DB_KEY_INVALID": "apikey 不在我们的数据库中需要扫码登录",
|
||||||
|
"CHAT2DB_KEY_LIMIT": "次数用完了,需要发起推广",
|
||||||
|
"CHAT2DB_KEY_EXPIRED": "到过期时间了",
|
||||||
|
"CHAT2DB_SERVICE_BUSY": "这个异常就稍后重试就行了",
|
||||||
|
"CHAT2DB_AUTH_HEADER_MISSING": "这个是 http 请求 header 没传 Authorization 字段,这个你看要怎么处理",
|
||||||
|
"CHAT2DB_AUTH_TOKEN_MISSING": "这个是 http 请求 header 中 Authorization 后面没有以 Bearer 开头,也是传的认证信息有问题,你看要怎么处理",
|
||||||
|
"CHAT2DB_SERVICE_ERROR": "这个是出了意料之外的异常要联系管理员",
|
||||||
|
"CHAT2DB_BAD_JSON_FORMAT": "这个是传的请求不是 json 格式",
|
||||||
|
"CHAT2DB_HTTP_METHOD_INVALID": "这个是传的请求不是 post 请求,目前给 openai 的请求必须是 post"
|
||||||
|
}
|
||||||
|
|
||||||
|
export const chatErrorCodeArr = Object.keys(chatError);
|
@ -58,6 +58,6 @@ export default {
|
|||||||
'common.text.wechatPopularizeAi': 'Follow the wechat public account and send "AI" to get free experiences.',
|
'common.text.wechatPopularizeAi': 'Follow the wechat public account and send "AI" to get free experiences.',
|
||||||
'common.text.wechatPopularizeAi2': 'Follow the wechat public account and send "AI" to get the ApiKey for free, and give away the number of experiences.',
|
'common.text.wechatPopularizeAi2': 'Follow the wechat public account and send "AI" to get the ApiKey for free, and give away the number of experiences.',
|
||||||
'common.text.wechatPopularize': 'You can also send "promotion" to get more experiences for free.',
|
'common.text.wechatPopularize': 'You can also send "promotion" to get more experiences for free.',
|
||||||
'common.notification.detial': 'More Detial',
|
'common.notification.detial': 'More details',
|
||||||
'common.notification.solution': 'Solution',
|
'common.notification.solution': 'Solution',
|
||||||
};
|
};
|
||||||
|
@ -17,4 +17,9 @@ export default {
|
|||||||
'connection.message.testSshConnection': 'Test the ssh connection',
|
'connection.message.testSshConnection': 'Test the ssh connection',
|
||||||
'connection.tableHeader.name': 'Name',
|
'connection.tableHeader.name': 'Name',
|
||||||
'connection.tableHeader.value': 'Value',
|
'connection.tableHeader.value': 'Value',
|
||||||
|
'connection.title.uploadDriver': 'Upload Driver',
|
||||||
|
'connection.tips.customUpload': "I don't have the drive I want",
|
||||||
|
'connection.title.driver': 'Driver',
|
||||||
|
'connection.button.clickUpload': 'Click to Upload',
|
||||||
|
|
||||||
};
|
};
|
@ -17,4 +17,8 @@ export default {
|
|||||||
'connection.message.testSshConnection': '测试ssh连接',
|
'connection.message.testSshConnection': '测试ssh连接',
|
||||||
'connection.tableHeader.name': '名称',
|
'connection.tableHeader.name': '名称',
|
||||||
'connection.tableHeader.value': '值',
|
'connection.tableHeader.value': '值',
|
||||||
|
'connection.title.uploadDriver': '上传驱动',
|
||||||
|
'connection.tips.customUpload': '没有我想要的驱动',
|
||||||
|
'connection.title.driver': '驱动',
|
||||||
|
'connection.button.clickUpload': '点击上传',
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useEffect, useLayoutEffect } from 'react';
|
import React, { useEffect, useLayoutEffect } from 'react';
|
||||||
import i18n from '@/i18n';
|
import i18n from '@/i18n';
|
||||||
import { Outlet } from 'umi';
|
import { Outlet } from 'umi';
|
||||||
import { ConfigProvider, theme, notification } from 'antd';
|
import { ConfigProvider, theme, App, Button } from 'antd';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
import { getAntdThemeConfig } from '@/theme';
|
import { getAntdThemeConfig } from '@/theme';
|
||||||
@ -22,7 +22,9 @@ import { getLang, getPrimaryColor, getTheme, setLang } from '@/utils/localStorag
|
|||||||
import { clearOlderLocalStorage } from '@/utils';
|
import { clearOlderLocalStorage } from '@/utils';
|
||||||
import registerMessage from './init/registerMessage';
|
import registerMessage from './init/registerMessage';
|
||||||
import registerNotification from './init/registerNotification';
|
import registerNotification from './init/registerNotification';
|
||||||
|
import { NotificationInstance } from 'antd/es/notification/interface';
|
||||||
|
import { ModalStaticFunctions } from 'antd/es/modal/confirm';
|
||||||
|
import Sub from './sub'
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
_Lang: string;
|
_Lang: string;
|
||||||
@ -69,6 +71,7 @@ export default function Layout() {
|
|||||||
return (
|
return (
|
||||||
<ConfigProvider locale={isEn ? antdEnUS : antdZhCN} theme={antdTheme}>
|
<ConfigProvider locale={isEn ? antdEnUS : antdZhCN} theme={antdTheme}>
|
||||||
<AppContainer></AppContainer>
|
<AppContainer></AppContainer>
|
||||||
|
{/* <Sub /> */}
|
||||||
</ConfigProvider>
|
</ConfigProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -76,12 +79,19 @@ export default function Layout() {
|
|||||||
/** 重启次数 */
|
/** 重启次数 */
|
||||||
const restartCount = 200;
|
const restartCount = 200;
|
||||||
|
|
||||||
|
let staticNotification: NotificationInstance;
|
||||||
|
|
||||||
|
|
||||||
function AppContainer() {
|
function AppContainer() {
|
||||||
const { token } = useToken();
|
const { token } = useToken();
|
||||||
const [initEnd, setInitEnd] = useState(false);
|
const [initEnd, setInitEnd] = useState(false);
|
||||||
const [appTheme, setAppTheme] = useTheme();
|
const [appTheme, setAppTheme] = useTheme();
|
||||||
const [startSchedule, setStartSchedule] = useState(0); // 0 初始状态 1 服务启动中 2 启动成功
|
const [startSchedule, setStartSchedule] = useState(0); // 0 初始状态 1 服务启动中 2 启动成功
|
||||||
const [serviceFail, setServiceFail] = useState(false);
|
const [serviceFail, setServiceFail] = useState(false);
|
||||||
|
const { notification } = App.useApp();
|
||||||
|
|
||||||
|
// staticNotification = staticFunction.notification
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let date = new Date('2030-12-30 12:30:00').toUTCString();
|
let date = new Date('2030-12-30 12:30:00').toUTCString();
|
||||||
@ -210,4 +220,4 @@ function AppContainer() {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
@ -53,7 +53,7 @@ function Connections(props: IProps) {
|
|||||||
() =>
|
() =>
|
||||||
(connectionList || []).map((t) => ({
|
(connectionList || []).map((t) => ({
|
||||||
key: t.id,
|
key: t.id,
|
||||||
icon: <Iconfont className={styles.menuItemIcon} code={databaseMap[t.type].icon} />,
|
icon: <Iconfont className={styles.menuItemIcon} code={databaseMap[t.type]?.icon} />,
|
||||||
label: t.alias,
|
label: t.alias,
|
||||||
meta: t,
|
meta: t,
|
||||||
})),
|
})),
|
||||||
|
@ -227,7 +227,7 @@ function TreeNodeRightClick(props: IProps) {
|
|||||||
return {
|
return {
|
||||||
key: i,
|
key: i,
|
||||||
label: <div className={styles.operationItem}>
|
label: <div className={styles.operationItem}>
|
||||||
<Iconfont className={styles.operationIcon} code={concrete.icon} />
|
<Iconfont className={styles.operationIcon} code={concrete?.icon} />
|
||||||
<div className={styles.operationTitle}>
|
<div className={styles.operationTitle}>
|
||||||
{concrete.text}
|
{concrete.text}
|
||||||
</div>
|
</div>
|
||||||
|
@ -51,7 +51,6 @@ export enum OperationColumn {
|
|||||||
ExportDDL = 'exportDDL',
|
ExportDDL = 'exportDDL',
|
||||||
EditSource = 'editSource',
|
EditSource = 'editSource',
|
||||||
Top = 'top'
|
Top = 'top'
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ITreeConfigItem {
|
export interface ITreeConfigItem {
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
import React, { memo, useEffect, useRef, useState, useReducer, useContext } from 'react';
|
import React, { memo, useRef, } from 'react';
|
||||||
import { connect } from 'umi';
|
import { connect } from 'umi';
|
||||||
import { Spin } from 'antd'
|
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
import DraggableContainer from '@/components/DraggableContainer';
|
import DraggableContainer from '@/components/DraggableContainer';
|
||||||
import WorkspaceLeft from './components/WorkspaceLeft';
|
import WorkspaceLeft from './components/WorkspaceLeft';
|
||||||
import WorkspaceRight from './components/WorkspaceRight';
|
import WorkspaceRight from './components/WorkspaceRight';
|
||||||
import { IConnectionModelType } from '@/models/connection';
|
import { IConnectionModelType } from '@/models/connection';
|
||||||
import { IWorkspaceModelType } from '@/models/workspace';
|
import { IWorkspaceModelType } from '@/models/workspace';
|
||||||
import LoadingContent from '@/components/Loading/LoadingContent'
|
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
@ -23,14 +21,11 @@ const dvaModel = connect(
|
|||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
const workspace = memo<IProps>((props) =>{
|
const workspace = memo<IProps>((props) => {
|
||||||
const draggableRef = useRef<any>();
|
const draggableRef = useRef<any>();
|
||||||
const {workspaceModel,connectionModel} = props;
|
const { workspaceModel, connectionModel } = props;
|
||||||
const { curWorkspaceParams } = workspaceModel;
|
|
||||||
const { curConnection } = connectionModel;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
// <LoadingContent data={curWorkspaceParams}>
|
|
||||||
<DraggableContainer className={styles.box}>
|
<DraggableContainer className={styles.box}>
|
||||||
<div ref={draggableRef} className={styles.boxLeft}>
|
<div ref={draggableRef} className={styles.boxLeft}>
|
||||||
<WorkspaceLeft />
|
<WorkspaceLeft />
|
||||||
@ -39,7 +34,6 @@ const workspace = memo<IProps>((props) =>{
|
|||||||
<WorkspaceRight />
|
<WorkspaceRight />
|
||||||
</div>
|
</div>
|
||||||
</DraggableContainer>
|
</DraggableContainer>
|
||||||
// </LoadingContent>
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { IPageResponse, IConnectionDetails } from '@/typings';
|
import { IPageResponse, IConnectionDetails } from '@/typings';
|
||||||
|
import { DatabaseTypeCode } from '@/constants';
|
||||||
import createRequest from './base';
|
import createRequest from './base';
|
||||||
// import { IPageResponse, IConnectionDetails, IDB } from '@/types';
|
|
||||||
|
|
||||||
export interface IGetConnectionParams {
|
export interface IGetConnectionParams {
|
||||||
searchKey?: string;
|
searchKey?: string;
|
||||||
@ -60,6 +60,32 @@ const getDBList = createRequest<{ id: number }, IDB[]>(
|
|||||||
{ method: 'get' },
|
{ method: 'get' },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export interface IDriverResponse {
|
||||||
|
driverConfigList: {
|
||||||
|
jdbcDriver: string;
|
||||||
|
jdbcDriverClass: string;
|
||||||
|
}[],
|
||||||
|
defaultDriverConfig: {
|
||||||
|
jdbcDriverClass: string
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IDriverParams {
|
||||||
|
dbType: DatabaseTypeCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IUploadDriver {
|
||||||
|
multipartFiles: any;
|
||||||
|
jdbcDriverClass: string;
|
||||||
|
dbType: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const getDriverList = createRequest<IDriverParams, IDriverResponse>('/api/jdbc/driver/list', { errorLevel: false, method: 'get' });
|
||||||
|
const downloadDriver = createRequest<{ dbType: string }, void>('/api/jdbc/driver/download', { errorLevel: false, method: 'get' });
|
||||||
|
const saveDriver = createRequest<IUploadDriver, void>('/api/jdbc/driver/save', { errorLevel: false, method: 'post' });
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getList,
|
getList,
|
||||||
getDetails,
|
getDetails,
|
||||||
@ -71,4 +97,7 @@ export default {
|
|||||||
getDBList,
|
getDBList,
|
||||||
close,
|
close,
|
||||||
testSSH,
|
testSSH,
|
||||||
|
getDriverList,
|
||||||
|
downloadDriver,
|
||||||
|
saveDriver,
|
||||||
};
|
};
|
||||||
|
@ -6,5 +6,5 @@ const testApiSmooth = createRequest<void, void>('/api/system/get-version-a', { e
|
|||||||
export default {
|
export default {
|
||||||
testService,
|
testService,
|
||||||
systemStop,
|
systemStop,
|
||||||
testApiSmooth
|
testApiSmooth,
|
||||||
}
|
}
|
@ -48,7 +48,7 @@ export interface IUniversalTableParams {
|
|||||||
* 版本返回
|
* 版本返回
|
||||||
* VersionResponse
|
* VersionResponse
|
||||||
*/
|
*/
|
||||||
export interface IVersionResponse {
|
export interface IVersionResponse {
|
||||||
/**
|
/**
|
||||||
* 基础链接
|
* 基础链接
|
||||||
* 类似于:http://test.sqlgpt.cn/gateway
|
* 类似于:http://test.sqlgpt.cn/gateway
|
||||||
@ -67,3 +67,5 @@ export interface IUniversalTableParams {
|
|||||||
*/
|
*/
|
||||||
wechatMpName?: string;
|
wechatMpName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,6 +16,10 @@ export interface IConnectionDetails {
|
|||||||
EnvType: ConnectionEnv;
|
EnvType: ConnectionEnv;
|
||||||
extendInfo: IConnectionExtendInfoItem[];
|
extendInfo: IConnectionExtendInfoItem[];
|
||||||
ssh: any;
|
ssh: any;
|
||||||
|
driverConfig: {
|
||||||
|
jdbcDriver: string;
|
||||||
|
jdbcDriverClass: string;
|
||||||
|
};
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,10 +505,11 @@ public class ChatController {
|
|||||||
: queryRequest.getPromptType();
|
: queryRequest.getPromptType();
|
||||||
PromptType pType = EasyEnumUtils.getEnum(PromptType.class, promptType);
|
PromptType pType = EasyEnumUtils.getEnum(PromptType.class, promptType);
|
||||||
String ext = StringUtils.isNotBlank(queryRequest.getExt()) ? queryRequest.getExt() : "";
|
String ext = StringUtils.isNotBlank(queryRequest.getExt()) ? queryRequest.getExt() : "";
|
||||||
|
String result = "假设你是个SQL编辑器,接下来你返回的SQL代码要和其他内容分隔,非SQL代码内容的每一行前面追加-- \n";
|
||||||
String schemaProperty = CollectionUtils.isNotEmpty(tableSchemas) ? String.format(
|
String schemaProperty = CollectionUtils.isNotEmpty(tableSchemas) ? String.format(
|
||||||
"### 请根据以下table properties和SQL input%s. %s\n#\n### %s SQL tables, with their properties:\n#\n# "
|
"%s### 请根据以下table properties和SQL input%s. %s\n#\n### %s SQL tables, with their properties:\n#\n# "
|
||||||
+ "%s\n#\n#\n### SQL input: %s", pType.getDescription(), ext, dataSourceType,
|
+ "%s\n#\n#\n### SQL input: %s", result, pType.getDescription(), ext, dataSourceType,
|
||||||
properties, prompt) : String.format("### 请根据以下SQL input%s. %s\n#\n### SQL input: %s",
|
properties, prompt) : String.format("%s### 请根据以下SQL input%s. %s\n#\n### SQL input: %s", result,
|
||||||
pType.getDescription(), ext, prompt);
|
pType.getDescription(), ext, prompt);
|
||||||
switch (pType) {
|
switch (pType) {
|
||||||
case SQL_2_SQL:
|
case SQL_2_SQL:
|
||||||
@ -521,7 +522,6 @@ public class ChatController {
|
|||||||
//if (I18nUtils.isEn()) {
|
//if (I18nUtils.isEn()) {
|
||||||
// schemaProperty = String.format("%s\n#\n### 返回结果要求为英文", schemaProperty);
|
// schemaProperty = String.format("%s\n#\n### 返回结果要求为英文", schemaProperty);
|
||||||
//}
|
//}
|
||||||
String result = String.format("%s. \n要求返回Markdown格式", schemaProperty);
|
return schemaProperty;
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user