Skip to content

Commit de447e0

Browse files
committed
merge export_ddl
2 parents e076f3a + edc94e5 commit de447e0

37 files changed

Lines changed: 1775 additions & 112 deletions

File tree

README.md

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,8 @@ To facilitate users' quick use of AI capabilities, you can scan the QR code belo
116116

117117
### CONFIGURE CUSTOM AI
118118

119-
- Customized AI can be any LLM that you deployed, such as ChatGLM、ChatGPT、ERNIE Bot、Tongyi Qianwen, and so on. However, the customized interface need to conform to the protocol definition. Otherwise, secondary development may be required. Two DEMOs are provided in the code, the configuration is as shown below. In specific use, you can refer to the DEMO interface to write a custom interface, or directly perform secondary development in the DEMO interface.
120-
- DEMO for configuring customized stream output interface.
121-
- DEMO for configuring customized non-stream output interface.
122-
<img width="1722" alt="5" src="https://github.com/chat2db/Chat2DB/assets/22975773/aff8497e-3edb-449d-a7d4-bb0429abc67c">
123-
119+
* [Refer here to deploy your ChatGLM-6B model](https://github.com/chat2db/chat2db-chatglm-6b-deploy)
120+
* [Refer here to deploy your sqlcoder model](https://github.com/chat2db/chat2db-sqlcoder-deploy)
124121

125122
## 📦 Docker installation
126123

README_CN.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ Redis and MongoDB are partially supported , Hbase、Elasticsearch、openGauss、
111111

112112
<a><img src="https://alidocs.oss-cn-zhangjiakou.aliyuncs.com/res/KM7qezzyAVX2Opj8/img/5ee43d26-05bb-4b12-b705-2b263f167975.png?x-oss-process=image/resize,w_1280,m_lfit,limit_1"/></a>
113113

114+
### 使用自定义大模型
115+
- [参考这里部署本地ChatGLM-6B模型](https://github.com/chat2db/chat2db-chatglm-6b-deploy/blob/main/README_CN.md)
116+
- [参考这里部署本地sqlcoder模型](https://github.com/chat2db/chat2db-sqlcoder-deploy/blob/main/README_CN.md)
117+
114118
## 📦 Docker 部署
115119

116120
```bash

chat2db-client/src/i18n/en-us/common.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ export default {
4646
'common.button.copy': 'Copy',
4747
'common.button.copySuccessfully': 'Copy Successfully',
4848
'common.button.createConsole': 'Create Console',
49+
'common.button.exportWord': 'Export to Word',
50+
'common.button.exportExcel': 'Export to Excel',
51+
'common.button.exportHtml': 'Export to Html',
52+
'common.button.exportMarkdown': 'Export to Markdown',
53+
'common.button.exportPdf': 'Export to Pdf',
4954
'common.text.successfulExecution': 'Successful Execution',
5055
'common.text.result': 'Result',
5156
'common.text.timeConsuming': 'Time Consuming',

chat2db-client/src/i18n/zh-cn/common.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ export default {
4646
'common.button.copy': '复制',
4747
'common.button.copySuccessfully': '复制成功',
4848
'common.button.createConsole': '新建控制台',
49+
'common.button.exportWord': '导出到Word',
50+
'common.button.exportExcel': '导出到Excel',
51+
'common.button.exportHtml': '导出到Html',
52+
'common.button.exportMarkdown': '导出到Markdown',
53+
'common.button.exportPdf': '导出到Pdf',
4954
'common.text.successfulExecution': '执行成功',
5055
'common.text.result': '结果',
5156
'common.text.timeConsuming': '耗时',

chat2db-client/src/pages/main/workspace/components/TableList/index.tsx

Lines changed: 136 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
1-
import React, { memo, useState, useEffect, useRef, useContext, useMemo } from 'react';
1+
import React, { useState, useEffect, useRef, useMemo } from 'react';
22
import classnames from 'classnames';
33
import i18n from '@/i18n';
44
import { connect } from 'umi';
5-
import { Input, Cascader } from 'antd';
5+
import { Input, Cascader, Button, Space, Dropdown, MenuProps } from 'antd';
66
import Iconfont from '@/components/Iconfont';
77
import LoadingContent from '@/components/Loading/LoadingContent';
88
import { IConnectionModelType } from '@/models/connection';
99
import { IWorkspaceModelType } from '@/models/workspace';
1010
import Tree from '../Tree';
1111
import { treeConfig } from '../Tree/treeConfig';
12-
import { ITreeNode } from '@/typings';
13-
import { TreeNodeType, CreateTabIntroType, WorkspaceTabType } from '@/constants';
14-
import styles from './index.less';
12+
import { TreeNodeType, WorkspaceTabType } from '@/constants';
1513
import { approximateTreeNode } from '@/utils';
1614
import { useUpdateEffect } from '@/hooks/useUpdateEffect';
1715
import { v4 as uuidV4 } from 'uuid';
16+
import { ITreeNode } from '@/typings';
17+
import styles from './index.less';
18+
import { DownOutlined } from '@ant-design/icons';
19+
import { ExportTypeEnum } from '@/typings/resultTable';
1820

1921
interface IOption {
2022
value: TreeNodeType;
@@ -24,13 +26,13 @@ interface IOption {
2426
const optionsList: IOption[] = [
2527
{
2628
value: TreeNodeType.TABLES,
27-
label: i18n('common.text.table')
29+
label: i18n('common.text.table'),
2830
},
2931
{ value: TreeNodeType.VIEWS, label: i18n('workspace.tree.view') },
3032
{ value: TreeNodeType.FUNCTIONS, label: i18n('workspace.tree.function') },
3133
{ value: TreeNodeType.PROCEDURES, label: i18n('workspace.tree.procedure') },
3234
{ value: TreeNodeType.TRIGGERS, label: i18n('workspace.tree.trigger') },
33-
]
35+
];
3436

3537
const dvaModel = connect(
3638
({ connection, workspace }: { connection: IConnectionModelType; workspace: IWorkspaceModelType }) => ({
@@ -39,23 +41,72 @@ const dvaModel = connect(
3941
}),
4042
);
4143

42-
interface Option {
43-
value: string;
44-
label: string;
45-
children?: Option[];
46-
}
47-
48-
const TableList = dvaModel(function (props: any) {
44+
const TableList = dvaModel((props: any) => {
4945
const { workspaceModel, dispatch } = props;
5046
const { curWorkspaceParams } = workspaceModel;
5147
const [searching, setSearching] = useState<boolean>(false);
5248
const inputRef = useRef<any>();
5349
const [searchedTableList, setSearchedTableList] = useState<ITreeNode[] | undefined>();
54-
const isReady = curWorkspaceParams?.dataSourceId && ((curWorkspaceParams?.databaseName || curWorkspaceParams?.schemaName) || (curWorkspaceParams?.databaseName === null && curWorkspaceParams?.schemaName == null))
50+
const isReady =
51+
curWorkspaceParams?.dataSourceId &&
52+
(curWorkspaceParams?.databaseName ||
53+
curWorkspaceParams?.schemaName ||
54+
(curWorkspaceParams?.databaseName === null && curWorkspaceParams?.schemaName == null));
5555
const [curType, setCurType] = useState<IOption>(optionsList[0]);
5656
const [curList, setCurList] = useState<ITreeNode[]>([]);
5757
const [tableLoading, setTableLoading] = useState<boolean>(false);
5858

59+
// 导出表结构
60+
const handleExport = (exportType: ExportTypeEnum) => {
61+
props.onExport && props.onExport(exportType);
62+
};
63+
64+
const items: MenuProps['items'] = useMemo(
65+
() => [
66+
{
67+
label: i18n('common.button.exportWord'),
68+
key: '1',
69+
// icon: <UserOutlined />,
70+
onClick: () => {
71+
handleExport(ExportTypeEnum.WORD);
72+
},
73+
},
74+
{
75+
label: i18n('common.button.exportExcel'),
76+
key: '2',
77+
// icon: <UserOutlined />,
78+
onClick: () => {
79+
handleExport(ExportTypeEnum.EXCEL);
80+
},
81+
},
82+
{
83+
label: i18n('common.button.exportHtml'),
84+
key: '3',
85+
// icon: <UserOutlined />,
86+
onClick: () => {
87+
handleExport(ExportTypeEnum.HTML);
88+
},
89+
},
90+
{
91+
label: i18n('common.button.exportMarkdown'),
92+
key: '4',
93+
// icon: <UserOutlined />,
94+
onClick: () => {
95+
handleExport(ExportTypeEnum.MARKDOWN);
96+
},
97+
},
98+
{
99+
label: i18n('common.button.exportPdf'),
100+
key: '5',
101+
// icon: <UserOutlined />,
102+
onClick: () => {
103+
handleExport(ExportTypeEnum.PDF);
104+
},
105+
},
106+
],
107+
[curWorkspaceParams],
108+
);
109+
59110
useUpdateEffect(() => {
60111
setCurList([]);
61112
getList();
@@ -74,26 +125,28 @@ const TableList = dvaModel(function (props: any) {
74125
cursor: 'start',
75126
});
76127
}
77-
}, [searching])
128+
}, [searching]);
78129

79130
function getList(refresh: boolean = false) {
80131
setTableLoading(true);
81132
treeConfig[curType.value].getChildren!({
82133
refresh,
83134
...curWorkspaceParams,
84135
extraParams: curWorkspaceParams,
85-
}).then(res => {
86-
setCurList(res);
87-
setTableLoading(false);
88-
if (curType.value === TreeNodeType.TABLES) {
89-
dispatch({
90-
type: 'workspace/setCurTableList',
91-
payload: res,
92-
})
93-
}
94-
}).catch(() => {
95-
setTableLoading(false);
96136
})
137+
.then((res) => {
138+
setCurList(res);
139+
setTableLoading(false);
140+
if (curType.value === TreeNodeType.TABLES) {
141+
dispatch({
142+
type: 'workspace/setCurTableList',
143+
payload: res,
144+
});
145+
}
146+
})
147+
.catch(() => {
148+
setTableLoading(false);
149+
});
97150
}
98151

99152
function openSearch() {
@@ -108,7 +161,7 @@ const TableList = dvaModel(function (props: any) {
108161
}
109162

110163
function onChange(value: string) {
111-
setSearchedTableList(approximateTreeNode(curList, value))
164+
setSearchedTableList(approximateTreeNode(curList, value));
112165
}
113166

114167
function refreshTableList() {
@@ -122,79 +175,83 @@ const TableList = dvaModel(function (props: any) {
122175
setCurType(selectedOptions[0]);
123176
}
124177

125-
const cascaderOnChange: any = (_: string[], selectedOptions: Option[]) => {
178+
const cascaderOnChange: any = () => {
126179
dispatch({
127180
type: 'workspace/setCreateConsoleIntro',
128181
payload: {
129182
id: uuidV4(),
130183
type: WorkspaceTabType.EditTable,
131184
title: 'create-table',
132-
uniqueData: {
133-
134-
}
185+
uniqueData: {},
135186
},
136-
})
187+
});
137188
};
138189

139190
const options = [
140191
{
141192
value: 'createTable',
142193
label: i18n('editTable.button.createTable'),
143-
}
144-
]
194+
},
195+
];
145196

146197
return (
147198
<div className={styles.tableModule}>
148199
<div className={styles.leftModuleTitle}>
149-
{
150-
searching ?
151-
<div className={styles.leftModuleTitleSearch}>
152-
<Input
153-
ref={inputRef}
154-
size="small"
155-
placeholder={i18n('common.text.search')}
156-
prefix={<Iconfont code="&#xe600;" />}
157-
onBlur={onBlur}
158-
onChange={(e) => onChange(e.target.value)}
159-
allowClear
160-
/>
161-
</div>
162-
:
163-
<div className={styles.leftModuleTitleText}>
164-
<Cascader
165-
defaultValue={[curType.value]}
166-
popupClassName={styles.cascaderPopup}
167-
options={optionsList}
168-
onChange={cascaderChange as any}
169-
>
170-
<div className={styles.modelName}>
171-
{curType.label}
172-
<Iconfont code='&#xe88e;' />
173-
</div>
174-
</Cascader>
175-
<div className={styles.iconBox} >
176-
<div className={classnames(styles.refreshIcon, styles.itemIcon)} onClick={() => refreshTableList()}>
177-
<Iconfont code="&#xec08;" />
178-
</div>
179-
<div className={classnames(styles.searchIcon, styles.itemIcon)} onClick={() => openSearch()}>
180-
<Iconfont code="&#xe600;" />
181-
</div>
182-
{
183-
curType.value === TreeNodeType.TABLES &&
184-
<Cascader options={options} onChange={cascaderOnChange}>
185-
<div className={classnames(styles.moreIcon, styles.itemIcon)}>
186-
<Iconfont code="&#xe601;" />
187-
</div>
188-
</Cascader>
189-
}
200+
{searching ? (
201+
<div className={styles.leftModuleTitleSearch}>
202+
<Input
203+
ref={inputRef}
204+
size="small"
205+
placeholder={i18n('common.text.search')}
206+
prefix={<Iconfont code="&#xe600;" />}
207+
onBlur={onBlur}
208+
onChange={(e) => onChange(e.target.value)}
209+
allowClear
210+
/>
211+
</div>
212+
) : (
213+
<div className={styles.leftModuleTitleText}>
214+
<Cascader
215+
defaultValue={[curType.value]}
216+
popupClassName={styles.cascaderPopup}
217+
options={optionsList}
218+
onChange={cascaderChange as any}
219+
>
220+
<div className={styles.modelName}>
221+
{curType.label}
222+
<Iconfont code="&#xe88e;" />
190223
</div>
224+
</Cascader>
225+
<div className={styles.iconBox}>
226+
<Dropdown menu={{ items }}>
227+
<Button>
228+
<Space>
229+
{i18n('common.text.export')}
230+
<DownOutlined />
231+
</Space>
232+
</Button>
233+
</Dropdown>
234+
<div className={classnames(styles.refreshIcon, styles.itemIcon)} onClick={() => refreshTableList()}>
235+
<Iconfont code="&#xec08;" />
236+
</div>
237+
<div className={classnames(styles.searchIcon, styles.itemIcon)} onClick={() => openSearch()}>
238+
<Iconfont code="&#xe600;" />
239+
</div>
240+
{curType.value === TreeNodeType.TABLES && (
241+
<Cascader options={options} onChange={cascaderOnChange}>
242+
<div className={classnames(styles.moreIcon, styles.itemIcon)}>
243+
<Iconfont code="&#xe601;" />
244+
</div>
245+
</Cascader>
246+
)}
191247
</div>
192-
}
248+
</div>
249+
)}
193250
</div>
194251
<LoadingContent className={styles.treeBox} isLoading={tableLoading}>
195-
<Tree className={styles.tree} initialData={searchedTableList || curList}></Tree>
252+
<Tree className={styles.tree} initialData={searchedTableList || curList} />
196253
</LoadingContent>
197-
</div >
254+
</div>
198255
);
199256
});
200257

0 commit comments

Comments
 (0)