|
@@ -1,434 +0,0 @@
|
|
-<template>
|
|
|
|
- <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 position-relative element" ref="chatBox" v-loading="loading">
|
|
|
|
- <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 flex-grow-1 flex-shrink-1' : 'mr-3 box-length-70']">
|
|
|
|
- <div
|
|
|
|
- :class="['d-flex align-center', `justify-${item.type === 1 ? 'start' : 'end'}`]"
|
|
|
|
- >
|
|
|
|
- {{ item.type === 1 ? 'AI助手' : '游客' }}
|
|
|
|
- <template v-if="item.type === 1">
|
|
|
|
- <v-btn
|
|
|
|
- v-if="item.content?.sql"
|
|
|
|
- class="ml-3"
|
|
|
|
- small
|
|
|
|
- elevation="0"
|
|
|
|
- depressed
|
|
|
|
- @click="item.showSnackbar = !item.showSnackbar"
|
|
|
|
- >
|
|
|
|
- {{ !item.showSnackbar ? '查看SQL' : '收起SQL'}}
|
|
|
|
- </v-btn>
|
|
|
|
- </template>
|
|
|
|
- </div>
|
|
|
|
- <div class="mt-2" :class="{ 'indigo lighten-5 pa-3 rounded': item.type === 2 }">
|
|
|
|
- <template v-if="typeof item.content === 'string'">
|
|
|
|
- <div>
|
|
|
|
- <span v-if="item.welcome" class="mdi mdi-hand-wave"></span>
|
|
|
|
- {{item.content}}
|
|
|
|
- </div>
|
|
|
|
- <div v-if="item.welcome">
|
|
|
|
- <div class="mt-1" v-for="_item in item.items" :key="_item">
|
|
|
|
- <span class="defaultLink" @click="onSend(_item)">{{_item}}</span>
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
- </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.summary }}
|
|
|
|
- </div>
|
|
|
|
- <div v-if="item.showSnackbar" class="pa-3 blue-grey lighten-3 mt-3">
|
|
|
|
- {{ item.content.sql }}
|
|
|
|
- </div>
|
|
|
|
- <div class="mt-3" v-if="item.content.columns.length">
|
|
|
|
- <div>
|
|
|
|
- <v-menu
|
|
|
|
- v-model="item.showMenu"
|
|
|
|
- :close-on-content-click="false"
|
|
|
|
- :close-on-click="false"
|
|
|
|
- max-width="300"
|
|
|
|
- attach=".chart-content-chat-box"
|
|
|
|
- >
|
|
|
|
- <template v-slot:activator>
|
|
|
|
- <v-btn
|
|
|
|
- @click="item.showMenu = true"
|
|
|
|
- text
|
|
|
|
- color="primary"
|
|
|
|
- >我要画图</v-btn>
|
|
|
|
- </template>
|
|
|
|
- <div class="white">
|
|
|
|
- <v-banner>画图配置</v-banner>
|
|
|
|
- <div class="pa-3">
|
|
|
|
- <v-autocomplete
|
|
|
|
- v-model="item.model.typeAxis"
|
|
|
|
- :items="item.content.columns"
|
|
|
|
- class="mb-3"
|
|
|
|
- outlined
|
|
|
|
- dense
|
|
|
|
- hide-details
|
|
|
|
- label="类型轴"
|
|
|
|
- ></v-autocomplete>
|
|
|
|
-
|
|
|
|
- <v-autocomplete
|
|
|
|
- v-model="item.model.dataAxis"
|
|
|
|
- :items="item.content.columns"
|
|
|
|
- class="mb-3"
|
|
|
|
- outlined
|
|
|
|
- dense
|
|
|
|
- hide-details
|
|
|
|
- label="数据轴"
|
|
|
|
- multiple
|
|
|
|
- chips
|
|
|
|
- small-chips
|
|
|
|
- ></v-autocomplete>
|
|
|
|
- <div class="text-right">
|
|
|
|
- <v-btn small class="mr-3" @click="item.showMenu = false">关闭</v-btn>
|
|
|
|
- <v-btn small color="primary" @click="onRender(item)">图表预览</v-btn>
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
- </v-menu>
|
|
|
|
- </div>
|
|
|
|
- <v-card flat outlined height="324">
|
|
|
|
- <div class="pa-3">
|
|
|
|
- <v-simple-table
|
|
|
|
- fixed-header
|
|
|
|
- dense
|
|
|
|
- height="300px"
|
|
|
|
- >
|
|
|
|
- <template v-slot:default>
|
|
|
|
- <thead>
|
|
|
|
- <tr>
|
|
|
|
- <th
|
|
|
|
- v-for="header in item.content.columns"
|
|
|
|
- :key="header"
|
|
|
|
- class="text-left"
|
|
|
|
- >{{ header }}</th>
|
|
|
|
- </tr>
|
|
|
|
- </thead>
|
|
|
|
- <tbody>
|
|
|
|
- <tr
|
|
|
|
- v-for="(row, index) in item.content.rows"
|
|
|
|
- :key="index"
|
|
|
|
- >
|
|
|
|
- <td
|
|
|
|
- v-for="header in item.content.columns"
|
|
|
|
- :key="header"
|
|
|
|
- class="text-left"
|
|
|
|
- >{{ row[header] }}</td>
|
|
|
|
- </tr>
|
|
|
|
- </tbody>
|
|
|
|
- </template>
|
|
|
|
- </v-simple-table>
|
|
|
|
- </div>
|
|
|
|
- </v-card>
|
|
|
|
- </div>
|
|
|
|
- <div class="d-flex align-center" v-if="!item.dataValidation">
|
|
|
|
- 您认为结果是否正确
|
|
|
|
- <v-btn
|
|
|
|
- class="ma-2"
|
|
|
|
- text
|
|
|
|
- icon
|
|
|
|
- small
|
|
|
|
- color="blue lighten-2"
|
|
|
|
- @click="onAddTrain(item, true)"
|
|
|
|
- >
|
|
|
|
- <v-icon>mdi-thumb-up</v-icon>
|
|
|
|
- </v-btn>
|
|
|
|
-
|
|
|
|
- <v-btn
|
|
|
|
- class="ma-2"
|
|
|
|
- text
|
|
|
|
- icon
|
|
|
|
- small
|
|
|
|
- color="red lighten-2"
|
|
|
|
- @click="onAddTrain(item, false)"
|
|
|
|
- >
|
|
|
|
- <v-icon>mdi-thumb-down</v-icon>
|
|
|
|
- </v-btn>
|
|
|
|
- </div>
|
|
|
|
- </template>
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
- <div class="pa-3 chart-content-chat-btn">
|
|
|
|
- <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 || disabled" @click="handleSendMsg">
|
|
|
|
- <v-icon>mdi-send</v-icon>
|
|
|
|
- </v-btn>
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
- </div>
|
|
|
|
- <!-- <v-dialog
|
|
|
|
- v-model="show"
|
|
|
|
- persistent
|
|
|
|
- max-width="290"
|
|
|
|
- >
|
|
|
|
- <v-card>
|
|
|
|
- <v-card-title class="text-h5">
|
|
|
|
- 提示
|
|
|
|
- </v-card-title>
|
|
|
|
- <v-card-text>是否添加到训练集</v-card-text>
|
|
|
|
- <v-card-actions>
|
|
|
|
- <v-spacer></v-spacer>
|
|
|
|
- <v-btn
|
|
|
|
- text
|
|
|
|
- @click="show = false"
|
|
|
|
- >
|
|
|
|
- 取消
|
|
|
|
- </v-btn>
|
|
|
|
- <v-btn
|
|
|
|
- color="error darken-1"
|
|
|
|
- text
|
|
|
|
- @click="onSure(false)"
|
|
|
|
- >
|
|
|
|
- 不添加
|
|
|
|
- </v-btn>
|
|
|
|
- <v-btn
|
|
|
|
- color="green darken-1"
|
|
|
|
- text
|
|
|
|
- @click="onSure(true)"
|
|
|
|
- >
|
|
|
|
- 添加
|
|
|
|
- </v-btn>
|
|
|
|
- </v-card-actions>
|
|
|
|
- </v-card>
|
|
|
|
- </v-dialog> -->
|
|
|
|
- </div>
|
|
|
|
-</template>
|
|
|
|
-
|
|
|
|
-<script>
|
|
|
|
-import {
|
|
|
|
- getAsk,
|
|
|
|
- submitTrainingCorrect,
|
|
|
|
- submitTrainingError
|
|
|
|
-} from '@/api/dataChart'
|
|
|
|
-export default {
|
|
|
|
- name: 'dataChartEditChat',
|
|
|
|
- data () {
|
|
|
|
- return {
|
|
|
|
- loading: false,
|
|
|
|
- disabled: false,
|
|
|
|
- question: '',
|
|
|
|
- items: [
|
|
|
|
- {
|
|
|
|
- type: 1,
|
|
|
|
- welcome: true,
|
|
|
|
- content: '你好,我是您的数据查询小助手,支持查询“高速公路服务区”的相关信息。您可以这样提问: ',
|
|
|
|
- items: [
|
|
|
|
- '现在一共有多少个服务区?分别归属于哪些管理公司?',
|
|
|
|
- '哪个服务区的档口数量最多?',
|
|
|
|
- '赣州分公司下,餐饮类档口的日均订单量是多少?'
|
|
|
|
- ]
|
|
|
|
- }
|
|
|
|
- ]
|
|
|
|
- // trueData: false
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
- methods: {
|
|
|
|
- handleKeyCode (event) {
|
|
|
|
- if (event.keyCode === 13) {
|
|
|
|
- if (!event.ctrlKey) {
|
|
|
|
- event.preventDefault()
|
|
|
|
- this.handleSendMsg()
|
|
|
|
- } else {
|
|
|
|
- this.question += '\n'
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
- onSend (str) {
|
|
|
|
- if (this.disabled) {
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- this.question = str
|
|
|
|
- this.handleSendMsg()
|
|
|
|
- },
|
|
|
|
- async handleSendMsg () {
|
|
|
|
- if (!this.question || this.disabled) {
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- this.disabled = true
|
|
|
|
-
|
|
|
|
- const question = this.question
|
|
|
|
- this.items.push({
|
|
|
|
- type: 2,
|
|
|
|
- user: '游客',
|
|
|
|
- content: question
|
|
|
|
- })
|
|
|
|
- this.scrollToBottom()
|
|
|
|
- const ask = {
|
|
|
|
- type: 1,
|
|
|
|
- content: {},
|
|
|
|
- showSnackbar: false,
|
|
|
|
- dataValidation: false,
|
|
|
|
- question, // 记录当前问题
|
|
|
|
- showMenu: false,
|
|
|
|
- model: {
|
|
|
|
- dataAxis: null,
|
|
|
|
- typeAxis: null
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- this.items.push(ask)
|
|
|
|
- this.question = ''
|
|
|
|
- try {
|
|
|
|
- const { data } = await getAsk({ question })
|
|
|
|
- ask.content = data
|
|
|
|
- this.scrollToBottom()
|
|
|
|
- } catch (error) {
|
|
|
|
- ask.content = error.message
|
|
|
|
- } finally {
|
|
|
|
- this.disabled = false
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
- scrollToBottom () {
|
|
|
|
- this.$nextTick(() => {
|
|
|
|
- const box = this.$refs.chatBox
|
|
|
|
- if (!box) {
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- box.scrollTop = box.scrollHeight
|
|
|
|
- })
|
|
|
|
- },
|
|
|
|
- async onAddTrain (item, bool) {
|
|
|
|
- this.loading = true
|
|
|
|
- const subApi = bool ? submitTrainingCorrect : submitTrainingError
|
|
|
|
- try {
|
|
|
|
- await subApi({
|
|
|
|
- question: item.question,
|
|
|
|
- sql: item.content.sql
|
|
|
|
- })
|
|
|
|
- item.dataValidation = true
|
|
|
|
- // this.$snackbar.success('操作成功')
|
|
|
|
- } catch (error) {
|
|
|
|
- this.$snackbar.error(error)
|
|
|
|
- } finally {
|
|
|
|
- this.loading = false
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
- onRender ({ model, content }) {
|
|
|
|
- if (!model.dataAxis || !model.typeAxis) {
|
|
|
|
- this.$snackbar.error('请选择数据轴和类型轴')
|
|
|
|
- return
|
|
|
|
- }
|
|
|
|
- const { typeAxis, dataAxis } = model
|
|
|
|
- const data = {
|
|
|
|
- type: typeAxis ? content.rows.map(e => e[typeAxis]) : [],
|
|
|
|
- data: dataAxis ? dataAxis.map(e => content.rows.map(r => r[e])) : []
|
|
|
|
- }
|
|
|
|
- this.$emit('render', data)
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-</script>
|
|
|
|
-
|
|
|
|
-<style lang="scss" scoped>
|
|
|
|
-.heightFull {
|
|
|
|
- height: 100%;
|
|
|
|
-}
|
|
|
|
-.widthFull {
|
|
|
|
- width: 100%;
|
|
|
|
-}
|
|
|
|
-.chart-content {
|
|
|
|
- &-chat {
|
|
|
|
- border: 1px solid #ccc;
|
|
|
|
- &-box {
|
|
|
|
- height: 0;
|
|
|
|
- flex: 1;
|
|
|
|
- max-width: 800px;
|
|
|
|
- width: 100%;
|
|
|
|
- margin: 0 auto;
|
|
|
|
- }
|
|
|
|
- &-btn {
|
|
|
|
- .send {
|
|
|
|
- margin: 0 auto;
|
|
|
|
- max-width: 800px;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-}
|
|
|
|
-.box-length-70 {
|
|
|
|
- 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 {
|
|
|
|
- position: relative;
|
|
|
|
- bottom: 0;
|
|
|
|
- ::v-deep textarea {
|
|
|
|
- padding: 15px 70px 15px 0 !important;
|
|
|
|
- max-height: 300px;
|
|
|
|
- min-height: 60px;
|
|
|
|
- overflow: auto;
|
|
|
|
- margin: 0 !important;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-.position {
|
|
|
|
- &-relative {
|
|
|
|
- position: relative;
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-.element {
|
|
|
|
- overflow: auto;
|
|
|
|
- scrollbar-width: none; /* Firefox */
|
|
|
|
- -ms-overflow-style: none; /* IE/Edge */
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-.element::-webkit-scrollbar {
|
|
|
|
- display: none; /* Chrome/Safari/Opera */
|
|
|
|
-}
|
|
|
|
-</style>
|
|
|