mirror of
https://gitee.com/devlive-community/datacap.git
synced 2024-12-02 20:17:45 +08:00
[Core] [AI] Support chatgpt for query
This commit is contained in:
parent
1315fa0da4
commit
5e97bc0ae9
@ -30,6 +30,7 @@
|
||||
"vue-clipboard3": "^2.0.0",
|
||||
"vue-i18n": "^9.2.2",
|
||||
"vue-router": "^4.0.3",
|
||||
"vue3-markdown": "^1.1.7",
|
||||
"watermark-dom": "^2.3.0",
|
||||
"webpack-bundle-analyzer": "^4.6.1"
|
||||
},
|
||||
|
6
core/datacap-web/console-fe/src/i18n/langs/en/ai.ts
Normal file
6
core/datacap-web/console-fe/src/i18n/langs/en/ai.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export default {
|
||||
optimizeSQL: 'Optimize SQL',
|
||||
optimizeSQLContent: 'Help me optimize the following SQL, the format is markdown',
|
||||
analysisSQL: 'Analysis SQL',
|
||||
analysisSQLContent: 'Help me analyze the following SQL, the format is markdown',
|
||||
}
|
@ -8,6 +8,7 @@ import grid from "@/i18n/langs/en/grid";
|
||||
import signup from "@/i18n/langs/en/signup";
|
||||
import alert from "@/i18n/langs/en/alert";
|
||||
import monitor from "@/i18n/langs/en/monitor";
|
||||
import ai from "@/i18n/langs/en/ai";
|
||||
|
||||
export default {
|
||||
...en,
|
||||
@ -19,5 +20,6 @@ export default {
|
||||
grid: grid,
|
||||
signup: signup,
|
||||
alert: alert,
|
||||
monitor: monitor
|
||||
monitor: monitor,
|
||||
ai: ai
|
||||
}
|
||||
|
6
core/datacap-web/console-fe/src/i18n/langs/zhCn/ai.ts
Normal file
6
core/datacap-web/console-fe/src/i18n/langs/zhCn/ai.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export default {
|
||||
optimizeSQL: '优化 SQL',
|
||||
optimizeSQLContent: '帮我优化以下SQL,格式为markdown',
|
||||
analysisSQL: '解析 SQL',
|
||||
analysisSQLContent: '帮我解析以下SQL,格式为markdown',
|
||||
}
|
@ -8,6 +8,7 @@ import grid from "@/i18n/langs/zhCn/grid";
|
||||
import signup from "@/i18n/langs/zhCn/signup";
|
||||
import alert from "@/i18n/langs/zhCn/alert";
|
||||
import monitor from "@/i18n/langs/zhCn/monitor";
|
||||
import ai from "@/i18n/langs/zhCn/ai";
|
||||
|
||||
export default {
|
||||
...zh,
|
||||
@ -19,5 +20,6 @@ export default {
|
||||
grid: grid,
|
||||
signup: signup,
|
||||
alert: alert,
|
||||
monitor: monitor
|
||||
monitor: monitor,
|
||||
ai: ai
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import router from "./router";
|
||||
import ViewUIPlus from 'view-ui-plus';
|
||||
import 'view-ui-plus/dist/styles/viewuiplus.css';
|
||||
|
||||
import VMdEditor from '@kangc/v-md-editor';
|
||||
import VMdPreview from '@kangc/v-md-editor/lib/preview';
|
||||
import '@kangc/v-md-editor/lib/style/preview.css';
|
||||
import githubTheme from '@kangc/v-md-editor/lib/theme/github';
|
||||
@ -18,5 +19,6 @@ const app = createApp(App);
|
||||
app.use(router);
|
||||
app.use(ViewUIPlus);
|
||||
app.use(i18n);
|
||||
app.use(VMdEditor);
|
||||
app.use(VMdPreview);
|
||||
app.mount("#app");
|
||||
|
@ -0,0 +1,146 @@
|
||||
<template>
|
||||
<div>
|
||||
<Modal title="AI" width="80%" :closable="false" v-model="visible" :maskClosable="false" :z-index="9">
|
||||
<div style="height: 350px; max-height: 350px;">
|
||||
<Tabs v-if="!loading" :animated="false" @on-click="handlerTab($event)">
|
||||
<TabPane :label="$t('ai.optimizeSQL')" name="OPTIMIZE" :disabled="actionLoading">
|
||||
<div style="height: 300px; max-height: 350px; overflow: auto;">
|
||||
<Skeleton v-if="actionLoading" loading :title="false" :animated="true"
|
||||
:paragraph="{ rows: 5, width: [100, 200, '300px', '50%', '62%'] }"/>
|
||||
<VMarkdownView v-else :mode="'light'" :content="finalContent"></VMarkdownView>
|
||||
</div>
|
||||
</TabPane>
|
||||
<TabPane :label="$t('ai.analysisSQL')" name="ANALYSIS" :disabled="actionLoading">
|
||||
<div style="height: 300px; max-height: 350px; overflow: auto;">
|
||||
<Skeleton v-if="actionLoading" loading :title="false" :animated="true"
|
||||
:paragraph="{ rows: 5, width: [100, 200, '300px', '50%', '62%'] }"/>
|
||||
<VMarkdownView v-else :mode="'light'" :content="finalContent"></VMarkdownView>
|
||||
</div>
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
</div>
|
||||
<div class="datacap-drawer-footer">
|
||||
<Button type="error" :disabled="actionLoading" @click="handlerCancel()">{{ $t('common.cancel') }}</Button>
|
||||
</div>
|
||||
<Spin size="large" fix :show="loading"></Spin>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import {defineComponent} from 'vue';
|
||||
import UserService from "@/services/UserService";
|
||||
import {User, UserQuestion} from "@/model/User";
|
||||
import {VMarkdownView} from 'vue3-markdown'
|
||||
import 'vue3-markdown/dist/style.css'
|
||||
import {Skeleton} from "view-ui-plus";
|
||||
|
||||
export enum TabType
|
||||
{
|
||||
OPTIMIZE = ('OPTIMIZE'),
|
||||
ANALYSIS = ('ANALYSIS')
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'QueryAiHelp',
|
||||
props: {
|
||||
isVisible: {
|
||||
type: Boolean,
|
||||
default: () => false
|
||||
},
|
||||
content: {
|
||||
type: String,
|
||||
default: () => ''
|
||||
}
|
||||
},
|
||||
components: {Skeleton, VMarkdownView},
|
||||
data()
|
||||
{
|
||||
return {
|
||||
loading: false,
|
||||
actionLoading: false,
|
||||
userInfo: null as User,
|
||||
finalContent: null
|
||||
}
|
||||
},
|
||||
created()
|
||||
{
|
||||
this.handlerInitialize();
|
||||
},
|
||||
methods: {
|
||||
handlerInitialize()
|
||||
{
|
||||
this.loading = true;
|
||||
UserService.getInfo()
|
||||
.then(response => {
|
||||
if (response.status) {
|
||||
this.userInfo = response.data;
|
||||
this.handlerTab(TabType.OPTIMIZE);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
handlerTab(value: TabType)
|
||||
{
|
||||
this.finalContent = null;
|
||||
let message = '';
|
||||
if (value === TabType.OPTIMIZE) {
|
||||
message += this.$t('ai.optimizeSQLContent');
|
||||
message += '\n';
|
||||
message += this.content;
|
||||
}
|
||||
else if (value === TabType.ANALYSIS) {
|
||||
message += this.$t('ai.analysisSQLContent');
|
||||
message += '\n';
|
||||
message += this.content;
|
||||
}
|
||||
|
||||
this.actionLoading = true;
|
||||
const userQuestion = new UserQuestion();
|
||||
userQuestion.type = 'ChatGPT';
|
||||
userQuestion.question = message;
|
||||
UserService.startChat(userQuestion)
|
||||
.then(response => {
|
||||
if (response.status) {
|
||||
this.finalContent = response.data.toString();
|
||||
}
|
||||
else {
|
||||
this.$Message.error(response.message);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.actionLoading = false;
|
||||
});
|
||||
},
|
||||
handlerCancel()
|
||||
{
|
||||
this.visible = false;
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
visible: {
|
||||
get(): boolean
|
||||
{
|
||||
return this.isVisible
|
||||
},
|
||||
set(value: boolean)
|
||||
{
|
||||
this.$emit('close', value)
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style scoped>
|
||||
.datacap-drawer-footer {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
border-top: 0px solid #e8e8e8;
|
||||
padding: 10px 16px;
|
||||
text-align: right;
|
||||
background: #fff;
|
||||
}
|
||||
</style>
|
@ -14,11 +14,11 @@
|
||||
<Card style="width:100%">
|
||||
<template #title>
|
||||
<Space>
|
||||
<Button type="primary" size="small" :loading="tableLoading" :disabled="!applySource"
|
||||
<Button type="primary" size="small" :loading="tableLoading" :disabled="!applySource || !activeEditorValue"
|
||||
icon="md-arrow-dropright-circle" @click="handlerRun()">
|
||||
{{ $t('common.run') }}
|
||||
</Button>
|
||||
<Button type="dashed" size="small" :disabled="!applySource" icon="md-code" @click="handlerFormat()">
|
||||
<Button type="dashed" size="small" :disabled="!applySource || !activeEditorValue" icon="md-code" @click="handlerFormat()">
|
||||
{{ $t('common.format') }}
|
||||
</Button>
|
||||
<Button type="error" size="small" :disabled="!applySource || !tableLoading"
|
||||
@ -54,6 +54,12 @@
|
||||
</Space>
|
||||
</template>
|
||||
</Poptip>
|
||||
<Badge v-if="applySource && activeEditorValue">
|
||||
<Button type="primary" size="small" icon="md-ionitron" @click="handlerVisibleHelp(true)"></Button>
|
||||
<template #count>
|
||||
<Icon type="md-help-circle" color="#ed4014" size="16"/>
|
||||
</template>
|
||||
</Badge>
|
||||
</Space>
|
||||
</template>
|
||||
<div ref="editorContainer">
|
||||
@ -64,8 +70,8 @@
|
||||
<TabPane v-for="editor in editors" :key="editor.key" :name="editor.key" :label="editor.title" :closable="editor.closable">
|
||||
</TabPane>
|
||||
<MonacoEditor theme="vs" :options="{theme: 'vs-dark', fontSize: 15}" language="sql" :height="300"
|
||||
:key="activeKey.value" @change="handlerChangeEditorValue" :width="'100%'"
|
||||
v-model:value="activeEditorValue" @editorDidMount="handlerEditorDidMount($event, 'mysql')">
|
||||
:key="activeKey.value" @change="handlerChangeEditorValue" :width="'100%'"
|
||||
v-model:value="activeEditorValue" @editorDidMount="handlerEditorDidMount($event, 'mysql')">
|
||||
</MonacoEditor>
|
||||
</Tabs>
|
||||
</div>
|
||||
@ -79,6 +85,7 @@
|
||||
<SnippetDetails v-if="snippetDetails" :isVisible="snippetDetails"
|
||||
:codeSnippet="activeEditorValue" @close="handlerCloseSnippetDetails($event)">
|
||||
</SnippetDetails>
|
||||
<QueryAiHelp v-if="visibleAiHelp" :isVisible="visibleAiHelp" :content="activeEditorValue" @close="handlerVisibleHelp($event)"></QueryAiHelp>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -100,6 +107,7 @@ import {AuditService} from "@/services/AuditService";
|
||||
import FunctionsService from "@/services/settings/functions/FunctionsService";
|
||||
import {useI18n} from "vue-i18n";
|
||||
import DataLazyTree from "@/components/common/DataLazyTree.vue";
|
||||
import QueryAiHelp from "@/views/pages/query/QueryAiHelp.vue";
|
||||
|
||||
const editors = ref<{ title: string; key: string; closable?: boolean }[]>([
|
||||
{title: 'Editor', key: '1', closable: false}
|
||||
@ -110,7 +118,7 @@ const editorValueMap = new Map<string, string>();
|
||||
|
||||
export default defineComponent({
|
||||
name: "QueryHome",
|
||||
components: {DataLazyTree, BasicTableComponent, SnippetDetails, SourceSelect, MonacoEditor},
|
||||
components: {QueryAiHelp, DataLazyTree, BasicTableComponent, SnippetDetails, SourceSelect, MonacoEditor},
|
||||
unmounted()
|
||||
{
|
||||
if (this.editorCompletionProvider) {
|
||||
@ -140,17 +148,19 @@ export default defineComponent({
|
||||
activeEditorValue: '',
|
||||
editors,
|
||||
activeKey,
|
||||
editorValueMap
|
||||
editorValueMap,
|
||||
visibleAiHelp: false
|
||||
}
|
||||
},
|
||||
created()
|
||||
{
|
||||
this.handlerInitialize();
|
||||
},
|
||||
mounted(){
|
||||
window.onresize=()=>{
|
||||
if(editorMap.values().next().value){
|
||||
editorMap.values().next().value.layout({width: this.$refs.editorContainer.offsetWidth,height:300})
|
||||
mounted()
|
||||
{
|
||||
window.onresize = () => {
|
||||
if (editorMap.values().next().value) {
|
||||
editorMap.values().next().value.layout({width: this.$refs.editorContainer.offsetWidth, height: 300})
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -236,9 +246,9 @@ export default defineComponent({
|
||||
});
|
||||
}
|
||||
});
|
||||
setTimeout(()=>{
|
||||
editorMap.values().next().value?.layout({width: this.$refs.editorContainer.offsetWidth,height:300})
|
||||
},200)
|
||||
setTimeout(() => {
|
||||
editorMap.values().next().value?.layout({width: this.$refs.editorContainer.offsetWidth, height: 300})
|
||||
}, 200)
|
||||
},
|
||||
handlerRun()
|
||||
{
|
||||
@ -348,6 +358,11 @@ export default defineComponent({
|
||||
handlerChangeEditorValue(value: string)
|
||||
{
|
||||
editorValueMap.set(activeKey.value, value);
|
||||
},
|
||||
handlerVisibleHelp(value: boolean)
|
||||
{
|
||||
this.visibleAiHelp = value;
|
||||
console.log(1)
|
||||
}
|
||||
},
|
||||
// Prevents errors from affecting other components
|
||||
|
Loading…
Reference in New Issue
Block a user