|
@@ -1,82 +1,86 @@
|
|
|
<template>
|
|
|
- <div class="chart-content d-flex heightFull">
|
|
|
- <div class="chart-content-show heightFull mr-3"></div>
|
|
|
- <div class="chart-content-chat heightFull d-flex flex-column">
|
|
|
- <div class="chart-content-chat-title mb-3">
|
|
|
- <v-tabs>
|
|
|
- <v-tab>AI 取数</v-tab>
|
|
|
- </v-tabs>
|
|
|
- </div>
|
|
|
- <div class="chart-content-chat-box overflow-y-auto" ref="chatBox">
|
|
|
- <div class="pa-3">
|
|
|
- <div
|
|
|
- v-for="(item, index) in items"
|
|
|
- :key="index"
|
|
|
- :class="['d-flex', 'mb-3', item.type === 1 ? 'flex-row' : 'flex-row-reverse' ]"
|
|
|
- >
|
|
|
- <v-avatar color="indigo" size="36">
|
|
|
- <span class="white--text">{{ item.type === 1 ? 'AI' : 'T' }}</span>
|
|
|
- </v-avatar>
|
|
|
- <div :class="[item.type === 1 ? 'ml-3' : 'mr-3 box-length-70']">
|
|
|
- <div :class="`text-${item.type === 1 ? 'left' : 'right'}`">{{ item.type === 1 ? 'AI助手' : '游客' }}</div>
|
|
|
- <div class="mt-2" :class="{ 'indigo lighten-5 pa-3 rounded': item.type !== 1 }">
|
|
|
- <template v-if="typeof item.content === 'string'">
|
|
|
- {{ item.content }}
|
|
|
- </template>
|
|
|
- <template v-else-if="Object.keys(item.content).length === 0">
|
|
|
- <div>
|
|
|
- 正在思考中...
|
|
|
- </div>
|
|
|
- </template>
|
|
|
- <template v-else>
|
|
|
- <div>
|
|
|
- {{ item.content.sql }}
|
|
|
- </div>
|
|
|
- <div class="mt-3">
|
|
|
- <!-- <m-table
|
|
|
- clearHeader
|
|
|
- size="small"
|
|
|
- shadow="never"
|
|
|
- :headers="item.content.columns"
|
|
|
- :items="item.content.rows"
|
|
|
- ></m-table>
|
|
|
- <el-popover
|
|
|
- placement="bottom"
|
|
|
- width="200"
|
|
|
- trigger="click"
|
|
|
- >
|
|
|
- <m-form :ref="`form${i}`" label-width="60px" :items="formItems(item.content.columns)" v-model="item.model"></m-form>
|
|
|
- <div style="text-align: right; margin: 0">
|
|
|
- <m-button type="primary" size="mini" @click="onRender($refs[`form${i}`], item)">生成图表</m-button>
|
|
|
- </div>
|
|
|
- <m-button type="primary" text slot="reference">我要作图</m-button>
|
|
|
- </el-popover> -->
|
|
|
- </div>
|
|
|
- </template>
|
|
|
- </div>
|
|
|
+ <div class="chart-content-chat heightFull d-flex flex-column">
|
|
|
+ <div class="chart-content-chat-title mb-3">
|
|
|
+ <v-tabs>
|
|
|
+ <v-tab>AI 取数</v-tab>
|
|
|
+ </v-tabs>
|
|
|
+ </div>
|
|
|
+ <div class="chart-content-chat-box overflow-y-auto" ref="chatBox">
|
|
|
+ <div class="pa-3">
|
|
|
+ <div
|
|
|
+ v-for="(item, index) in items"
|
|
|
+ :key="index"
|
|
|
+ :class="['d-flex', 'mb-3', item.type === 1 ? 'flex-row' : 'flex-row-reverse' ]"
|
|
|
+ >
|
|
|
+ <v-avatar color="indigo" size="36">
|
|
|
+ <span class="white--text">{{ item.type === 1 ? 'AI' : 'T' }}</span>
|
|
|
+ </v-avatar>
|
|
|
+ <div :class="[item.type === 1 ? 'ml-3' : 'mr-3 box-length-70']">
|
|
|
+ <div :class="`text-${item.type === 1 ? 'left' : 'right'}`">{{ item.type === 1 ? 'AI助手' : '游客' }}</div>
|
|
|
+ <div class="mt-2" :class="{ 'indigo lighten-5 pa-3 rounded': item.type !== 1 }">
|
|
|
+ <template v-if="typeof item.content === 'string'">
|
|
|
+ {{ item.content }}
|
|
|
+ </template>
|
|
|
+ <template v-else-if="Object.keys(item.content).length === 0">
|
|
|
+ <span>
|
|
|
+ 正在思考中
|
|
|
+ <v-progress-circular
|
|
|
+ indeterminate
|
|
|
+ size="14"
|
|
|
+ class="ml-1"
|
|
|
+ width="2"
|
|
|
+ color="primary"
|
|
|
+ ></v-progress-circular>
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <div>
|
|
|
+ {{ item.content.sql }}
|
|
|
+ </div>
|
|
|
+ <div class="mt-3">
|
|
|
+ <!-- <m-table
|
|
|
+ clearHeader
|
|
|
+ size="small"
|
|
|
+ shadow="never"
|
|
|
+ :headers="item.content.columns"
|
|
|
+ :items="item.content.rows"
|
|
|
+ ></m-table>
|
|
|
+ <el-popover
|
|
|
+ placement="bottom"
|
|
|
+ width="200"
|
|
|
+ trigger="click"
|
|
|
+ >
|
|
|
+ <m-form :ref="`form${i}`" label-width="60px" :items="formItems(item.content.columns)" v-model="item.model"></m-form>
|
|
|
+ <div style="text-align: right; margin: 0">
|
|
|
+ <m-button type="primary" size="mini" @click="onRender($refs[`form${i}`], item)">生成图表</m-button>
|
|
|
+ </div>
|
|
|
+ <m-button type="primary" text slot="reference">我要作图</m-button>
|
|
|
+ </el-popover> -->
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="pa-3">
|
|
|
- <div class="send d-flex align-center justify-center">
|
|
|
- <div class="send-box">
|
|
|
- <v-textarea
|
|
|
- v-model="question"
|
|
|
- class="send-box-area"
|
|
|
- auto-grow
|
|
|
- placeholder="请输入您想问的内容,按 Ctrl+Enter 换行"
|
|
|
- outlined
|
|
|
- hide-details
|
|
|
- no-resize
|
|
|
- rows="1"
|
|
|
- @keydown.enter="handleKeyCode($event)"
|
|
|
- >
|
|
|
- </v-textarea>
|
|
|
- <v-btn icon color="primary" class="btn" :disabled="!question" @click="handleSendMsg">
|
|
|
- <v-icon>mdi-send</v-icon>
|
|
|
- </v-btn>
|
|
|
- </div>
|
|
|
+ </div>
|
|
|
+ <div class="pa-3">
|
|
|
+ <div class="send d-flex align-center justify-center">
|
|
|
+ <div class="send-box">
|
|
|
+ <v-textarea
|
|
|
+ v-model="question"
|
|
|
+ class="send-box-area"
|
|
|
+ auto-grow
|
|
|
+ placeholder="请输入您想问的内容,按 Ctrl+Enter 换行"
|
|
|
+ outlined
|
|
|
+ hide-details
|
|
|
+ no-resize
|
|
|
+ rows="1"
|
|
|
+ @keydown.enter="handleKeyCode($event)"
|
|
|
+ >
|
|
|
+ </v-textarea>
|
|
|
+ <v-btn icon color="primary" class="btn" :disabled="!question" @click="handleSendMsg">
|
|
|
+ <v-icon>mdi-send</v-icon>
|
|
|
+ </v-btn>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
@@ -91,6 +95,7 @@ export default {
|
|
|
name: 'dataChartEditChat',
|
|
|
data () {
|
|
|
return {
|
|
|
+ icons: 1,
|
|
|
question: '',
|
|
|
items: [
|
|
|
{
|
|
@@ -133,19 +138,23 @@ export default {
|
|
|
}
|
|
|
}
|
|
|
this.items.push(ask)
|
|
|
- const { data } = await getAsk({
|
|
|
- question: this.question
|
|
|
- })
|
|
|
- this.question = ''
|
|
|
- const { columns, ...obj } = data
|
|
|
- ask.content = {
|
|
|
- ...obj,
|
|
|
- columns: columns.map(e => ({ label: e, prop: e, value: e }))
|
|
|
+ try {
|
|
|
+ const { data } = await getAsk({
|
|
|
+ question: this.question
|
|
|
+ })
|
|
|
+ this.question = ''
|
|
|
+ const { columns, ...obj } = data
|
|
|
+ ask.content = {
|
|
|
+ ...obj,
|
|
|
+ columns: columns.map(e => ({ label: e, prop: e, value: e }))
|
|
|
+ }
|
|
|
+ this.$nextTick(() => {
|
|
|
+ const box = this.$refs.chatBox
|
|
|
+ box.scrollTop = box.scrollHeight
|
|
|
+ })
|
|
|
+ } catch (error) {
|
|
|
+ this.$snackbar.error(error)
|
|
|
}
|
|
|
- this.$nextTick(() => {
|
|
|
- const box = this.$refs.chatBox
|
|
|
- box.scrollTop = box.scrollHeight
|
|
|
- })
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -159,12 +168,6 @@ export default {
|
|
|
width: 100%;
|
|
|
}
|
|
|
.chart-content {
|
|
|
- width: 0;
|
|
|
- flex: 1;
|
|
|
- &-show {
|
|
|
- width: 50%;
|
|
|
- border: 1px solid #ccc;
|
|
|
- }
|
|
|
&-chat {
|
|
|
width: 50%;
|
|
|
border: 1px solid #ccc;
|
|
@@ -179,29 +182,29 @@ export default {
|
|
|
max-width: 70%;
|
|
|
}
|
|
|
.send {
|
|
|
-// height: 130px;
|
|
|
-// margin: 20px 0;
|
|
|
-padding: 20px;
|
|
|
-&-box {
|
|
|
- width: 100%;
|
|
|
- // max-width: 800px;
|
|
|
- position: relative;
|
|
|
- .btn {
|
|
|
- position: absolute;
|
|
|
- right: 20px;
|
|
|
- bottom: 12px;
|
|
|
- }
|
|
|
- &-area {
|
|
|
+ // height: 130px;
|
|
|
+ // margin: 20px 0;
|
|
|
+ padding: 20px;
|
|
|
+ &-box {
|
|
|
+ width: 100%;
|
|
|
+ // max-width: 800px;
|
|
|
position: relative;
|
|
|
- bottom: 0;
|
|
|
- ::v-deep textarea {
|
|
|
- padding: 15px 70px 15px 0 !important;
|
|
|
- max-height: 300px;
|
|
|
- min-height: 60px;
|
|
|
- overflow: auto;
|
|
|
- margin: 0 !important;
|
|
|
+ .btn {
|
|
|
+ position: absolute;
|
|
|
+ right: 20px;
|
|
|
+ bottom: 12px;
|
|
|
+ }
|
|
|
+ &-area {
|
|
|
+ position: relative;
|
|
|
+ bottom: 0;
|
|
|
+ ::v-deep textarea {
|
|
|
+ padding: 15px 70px 15px 0 !important;
|
|
|
+ max-height: 300px;
|
|
|
+ min-height: 60px;
|
|
|
+ overflow: auto;
|
|
|
+ margin: 0 !important;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-}
|
|
|
</style>
|