wujingjing
2024-09-10 68994735dddb8d2be65149aa605ec0ac12e8775a
未滑动到底部 bug;多次点开对话测试 bug;数据对接SQL为选项之一
已修改10个文件
已添加1个文件
539 ■■■■ 文件已修改
src/components/amis/AMISRenderer.vue 412 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/Chat.vue 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/chatComponents/summaryCom/components/amisPage/AmisPage.vue 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/hooks/useScrollToBottom.ts 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/types/mitt.d.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/mitt.ts 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/request.ts 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/project/yw/dataManage/knowledge/Knowledge.vue 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/project/yw/lowCode/sqlAmis/SqlAmis.vue 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/project/yw/lowCode/sqlAmis/edit/SqlAmisEdit.vue 44 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/project/yw/lowCode/sqlAmis/edit/types.ts 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/amis/AMISRenderer.vue
@@ -1,16 +1,40 @@
<template><div class="my-amis-scope">加载中...</div></template>
<template><div ref="amisRootRef" class="my-amis-scope">加载中...</div></template>
<script lang="ts">
import { accessSessionKey, handleNoAuth } from '/@/utils/request';
<script setup lang="ts">
import { MAIN_URL } from '/@/constants';
import router from '/@/router/index';
import { Local } from '/@/utils/storage';
import { accessSessionKey, handleNoAuth } from '/@/utils/request';
// å¯ä»¥ä¸å¼•用, å¦‚果你不想要任何辅助类样式的话 (比如 `m-t-xs` è¿™ç§)
// https://aisuda.bce.baidu.com/amis/zh-CN/style/index
// import 'amis/sdk/helper.css';
import qs from 'qs';
import { onMounted, onUnmounted, reactive, ref, shallowRef, watch } from 'vue';
const amisRootRef = ref<HTMLDivElement>(null);
import { Local } from '/@/utils/storage';
const props = defineProps({
    schema: {
        type: Object,
        default: () => ({
            type: 'page',
            body: 'Hello World!',
        }),
    },
    locals: {
        type: Object,
        default: () => ({}),
    },
    props: {
        type: Object,
        default: () => ({}),
    },
    env: {
        type: Object,
        default: () => ({}),
    },
});
const emit = defineEmits(['ready']);
function loadScript(callback) {
    window.eventList.amisSdkJsPromise
@@ -20,16 +44,6 @@
        .catch((error) => {
            callback(error);
        });
}
function loadStyles(styles) {
    for (const path of styles) {
        const style = document.createElement('link');
        style.setAttribute('rel', 'stylesheet');
        style.setAttribute('type', 'text/css');
        style.setAttribute('href', path);
        document.head.appendChild(style);
    }
}
function loadSDK() {
@@ -51,204 +65,174 @@
    });
}
export default {
    name: 'AMISRenderer',
    components: {},
    props: {
        schema: {
            type: Object,
            default: () => ({
                type: 'page',
                body: 'Hello World!',
            }),
        },
        locals: {
            type: Object,
            default: () => ({}),
        },
        props: {
            type: Object,
            default: () => ({}),
        },
        env: {
            type: Object,
            default: () => ({}),
        },
    },
    data() {
        return {
            // è¿™é‡Œé¢çš„æ•°æ®æ‰€æœ‰ amis é¡µé¢éƒ½å¯ä»¥èŽ·å–åˆ°
            // å¯ä»¥ç”¨æ¥æ”¾ä¸€ä¸‹å…¬å…±æ•°æ®ï¼Œæ¯”如用户信息等
            // ä¸è¦æ”¾å—控数据,受控数据应该通过 data ä¸‹å‘
            context: {
                siteName: 'AMIS DEMO',
            },
            get location() {
                const current = router.currentRoute.value;
                return {
                    pathname: current?.path,
                    hash: current?.hash,
                    query: current?.query,
                    search: `?${qs.stringify(current.query)}`,
                };
                // return 'localtion'
            },
            loading: false,
            amisInstance: null,
            unmounted: false,
        };
    },
const context = reactive({
    siteName: 'AMIS DEMO',
});
const current = router.currentRoute.value;
    watch: {
        locals: function () {
            this.updateProps();
        },
        props: function () {
            this.updateProps();
        },
        $route: function () {
            this.updateProps();
        },
    },
    async mounted() {
        try {
            this.loading = true;
            await loadSDK();
        } finally {
            this.loading = false;
        }
        if (this.unmounted) {
            return;
        }
        const scoped = amisRequire('amis/embed');
        const { normalizeLink } = amisRequire('amis');
        const instance = scoped.embed(
            this.$el,
            this.schema,
            {
                data: {
                    ...this.locals,
                },
                context: this.context,
                location: this.location,
                // todo ä¸‹å‘ location å¯¹è±¡
                ...this.props,
            },
            {
                requestAdaptor(api) {
                    const accessSession = Local.get(accessSessionKey);
                    if (accessSession) {
                        // å°† token æ·»åŠ åˆ°è¯·æ±‚æŠ¥æ–‡å¤´ä¸­
                        api.headers['hswatersession'] = accessSession;
                    } else {
                        handleNoAuth();
                    }
                    api.url = `${MAIN_URL}${api.url}`;
                    return api;
                },
                // å…¨å±€ api é€‚配器。
                // å¦å¤–在 amis é…ç½®é¡¹ä¸­çš„ api ä¹Ÿå¯ä»¥é…ç½®é€‚配器,针对某个特定接口单独处理。
                responseAdaptor(api, payload, query, request, response) {
                    //                     {
                    //   "json_ok": true,
                    //   "sections": [
                    //     {
                    //       "section_id": "knowledge_base",
                    //       "section_name": "水务知识库",
                    //       "section_title": "拥有水务行业相关的通用知识,包括:法律法规、设计规范、给排水相关知识等等"
                    //     },
                    //     {
                    //       "section_id": "office_assistant",
                    //       "section_name": "办公助手",
                    //       "section_title": "办公助手能够辅助写会议通知、请假条、工作总结、PPT等工作。"
                    //     },
                    //     {
                    //       "section_id": "customer_service",
                    //       "section_name": "客户服务",
                    //       "section_title": "针对水务企业对外客户服务相关的内容,包括:抄表、开账、收费,以及热线相关"
                    //     },
                    //     {
                    //       "section_id": "network_operation",
                    //       "section_name": "管网运行",
                    //       "section_title": "针对水务企业管网运行与维护管理、水质管理等相关"
                    //     },
                    //     {
                    //       "section_id": "waterworks_operation",
                    //       "section_name": "水厂运行",
                    //       "section_title": "针对水务企业水厂运日常运营管理服务,包括:水厂工艺流程、水泵运行调度"
                    //     }
                    //   ]
                    // }
                    return payload;
                },
                // è¦†ç›– amis env
                // å‚考 https://aisuda.bce.baidu.com/amis/zh-CN/docs/start/getting-started#sdk
                jumpTo: (to, action) => {
                    return;
                    if (to === 'goBack') {
                        return router.go(-1);
                    }
                    to = normalizeLink(to, this.location);
                    if (action?.actionType === 'url') {
                        action.blank === false ? router.push(to) : window.open(to);
                        return;
                    }
                    // ä¸»è¦æ˜¯æ”¯æŒ nav ä¸­çš„跳转
                    if (action && to && action.target) {
                        window.open(to, action.target);
                        return;
                    }
                    if (/^https?:\/\//.test(to)) {
                        window.location.replace(to);
                    } else {
                        router.push(to);
                    }
                },
                updateLocation: (location, replace) => {
                    // ç¦æ­¢è·³è½¬
                    return;
                    if (location === 'goBack') {
                        return router.go(-1);
                    }
                    location = normalizeLink(location, this.location);
                    replace ? router.replace(location) : router.replace(location);
                },
                ...this.env,
            },
            () => {
                this.$emit('ready', {
                    instance,
                });
            }
        );
        this.amisInstance = instance;
    },
    methods: {
        updateProps() {
            this.amisInstance?.updateProps({
                data: {
                    ...this.locals,
                },
                context: this.context,
                ...this.props,
            });
        },
    },
    unmounted() {
        this.unmounted = true;
        this.amisInstance?.unmount();
    },
const location = {
    pathname: current?.path,
    hash: current?.hash,
    query: current?.query,
    search: `?${qs.stringify(current.query)}`,
};
const loading = ref(false);
const amisInstance = shallowRef(null);
const unmounted = ref(false);
const updateProps = () => {
    amisInstance.value?.updateProps({
        data: {
            ...props.locals,
        },
        context: context,
        ...props.props,
    });
};
watch(
    () => props.locals,
    (val) => {
        updateProps();
    }
);
watch(
    () => props.props,
    (val) => {
        updateProps();
    }
);
// watch(() => router.value, (val) => {
// })
onMounted(async () => {
    try {
        loading.value = true;
        await loadSDK();
    } finally {
        loading.value = false;
    }
    if (unmounted.value) {
        return;
    }
    const scoped = amisRequire('amis/embed');
    const { normalizeLink } = amisRequire('amis');
    const instance = scoped.embed(
        amisRootRef.value,
        props.schema,
        {
            data: {
                ...props.locals,
            },
            context: context,
            location: location,
            // todo ä¸‹å‘ location å¯¹è±¡
            ...props.props,
        },
        {
            requestAdaptor(api) {
                const accessSession = Local.get(accessSessionKey);
                if (accessSession) {
                    // å°† token æ·»åŠ åˆ°è¯·æ±‚æŠ¥æ–‡å¤´ä¸­
                    api.headers['hswatersession'] = accessSession;
                } else {
                    handleNoAuth();
                }
                api.url = `${MAIN_URL}${api.url}`;
                return api;
            },
            // å…¨å±€ api é€‚配器。
            // å¦å¤–在 amis é…ç½®é¡¹ä¸­çš„ api ä¹Ÿå¯ä»¥é…ç½®é€‚配器,针对某个特定接口单独处理。
            responseAdaptor(api, payload, query, request, response) {
                //                     {
                //   "json_ok": true,
                //   "sections": [
                //     {
                //       "section_id": "knowledge_base",
                //       "section_name": "水务知识库",
                //       "section_title": "拥有水务行业相关的通用知识,包括:法律法规、设计规范、给排水相关知识等等"
                //     },
                //     {
                //       "section_id": "office_assistant",
                //       "section_name": "办公助手",
                //       "section_title": "办公助手能够辅助写会议通知、请假条、工作总结、PPT等工作。"
                //     },
                //     {
                //       "section_id": "customer_service",
                //       "section_name": "客户服务",
                //       "section_title": "针对水务企业对外客户服务相关的内容,包括:抄表、开账、收费,以及热线相关"
                //     },
                //     {
                //       "section_id": "network_operation",
                //       "section_name": "管网运行",
                //       "section_title": "针对水务企业管网运行与维护管理、水质管理等相关"
                //     },
                //     {
                //       "section_id": "waterworks_operation",
                //       "section_name": "水厂运行",
                //       "section_title": "针对水务企业水厂运日常运营管理服务,包括:水厂工艺流程、水泵运行调度"
                //     }
                //   ]
                // }
                return payload;
            },
            // è¦†ç›– amis env
            // å‚考 https://aisuda.bce.baidu.com/amis/zh-CN/docs/start/getting-started#sdk
            jumpTo: (to, action) => {
                return;
                if (to === 'goBack') {
                    return router.go(-1);
                }
                to = normalizeLink(to, this.location);
                if (action?.actionType === 'url') {
                    action.blank === false ? router.push(to) : window.open(to);
                    return;
                }
                // ä¸»è¦æ˜¯æ”¯æŒ nav ä¸­çš„跳转
                if (action && to && action.target) {
                    window.open(to, action.target);
                    return;
                }
                if (/^https?:\/\//.test(to)) {
                    window.location.replace(to);
                } else {
                    router.push(to);
                }
            },
            updateLocation: (location, replace) => {
                // ç¦æ­¢è·³è½¬
                return;
                if (location === 'goBack') {
                    return router.go(-1);
                }
                location = normalizeLink(location, this.location);
                replace ? router.replace(location) : router.replace(location);
            },
            ...props.env,
        },
        () => {
            emit('ready', {
                instance,
            });
        }
    );
    amisInstance.value = instance;
});
onUnmounted(() => {
    unmounted.value = true;
    amisInstance.value?.unmount();
});
</script>
src/components/chat/Chat.vue
@@ -119,7 +119,7 @@
                                    </div>
                                </div>
                                <Loading v-if="isTalking && index === messageList.length - 1" class="w-fit" />
                                <Loading v-if="isTalking && index === messageList.length - 1" class="w-fit my-auto" />
                            </div>
                        </div>
                    </div>
@@ -139,7 +139,7 @@
                </div>
            </div>
            <div class="sticky bottom-0 w-full pb-3 flex justify-center">
            <div class="sticky bottom-0 w-full py-6 flex justify-center">
                <PlayBar
                    v-model:voicePageIsShow="voicePageIsShow"
                    :isTalking="isTalking"
@@ -167,11 +167,10 @@
import { GetHistoryAnswer, extCallQuery } from '/@/api/ai/chat';
import PlayBar from '/@/components/chat/components/playBar/PlayBar.vue';
import { ErrorCode } from '/@/utils/request';
import { CancelTokenSource } from 'axios';
const props = defineProps({
    questionApi: Function as PropType<(...params: any[]) => any>,
    questionApi: Function as PropType<(text: string, sourceObj: { source: CancelTokenSource }) => any>,
});
const chatWidth = '100%';
@@ -194,7 +193,6 @@
        type: AnswerType.Text,
        values: '解析失败!',
    };
    switch (res.answer_type) {
        case AnswerType.RecordSet:
            content = {
@@ -249,8 +247,13 @@
};
let questionRes = null;
// ä½œä¸ºå‚数传进去,携带参数出来
let lastSourceObj: { source: CancelTokenSource } = {
    source:null
};
const questionAi = async (text) => {
    const res = await props.questionApi(text);
    const res = await props.questionApi(text, lastSourceObj);
    questionRes = res?.values;
    const content = parseContent(res?.values);
    return content;
@@ -267,7 +270,6 @@
        history_id: historyId,
    });
};
const sendChatMessage = async (content: ChatContent = messageContent.value, cb?: any, isCallExtParams?: any) => {
    if (!content?.values || isTalking.value) return;
    const isNewChat = messageList.value.length === 0;
@@ -326,6 +328,7 @@
};
const clearContent = () => {
    lastSourceObj.source?.cancel();
    messageList.value = [];
    // æ¸…空输入框
    clearMessageContent();
@@ -333,7 +336,7 @@
defineExpose({
    autoSend,
    clear:clearContent
    clear: clearContent,
});
//#region ====================== å…³è”查询 ======================
src/components/chat/chatComponents/summaryCom/components/amisPage/AmisPage.vue
@@ -1,13 +1,14 @@
<template>
    <div>
        <span v-if="data?.title" class="text-base font-bold flex-center">{{ data?.title }}</span>
        <AMISRenderer :schema="data?.amis_json" :locals="data?.amis_data" />
        <AMISRenderer :schema="data?.amis_json" :locals="data?.amis_data" @ready="amisReady"/>
    </div>
</template>
<script setup lang="ts">
import type { PropType } from 'vue';
import AMISRenderer from '/@/components/amis/AMISRenderer.vue';
import emitter from '/@/utils/mitt';
// import  å‘¨ç¤¾ä¼šå­˜é”€æ¯” from './testData/周社会存销比.json'
// import  å®¢æˆ·æƒ…况 from './testData/客户情况.json'
@@ -23,6 +24,10 @@
    },
});
const amisReady = (val) => {
    emitter.emit('amis.page.ready',val);
};
</script>
<style scoped lang="scss"></style>
src/components/chat/hooks/useScrollToBottom.ts
@@ -1,6 +1,7 @@
import type { ComputedRef, Ref } from 'vue';
import { nextTick, onActivated, ref, watch } from 'vue';
import { nextTick, onActivated, onUnmounted, ref, watch } from 'vue';
import type { ChatMessage } from '../model/types';
import emitter from '/@/utils/mitt';
export type UseScrollToBottomOption = {
    chatListDom: Ref<HTMLDivElement>;
@@ -12,8 +13,18 @@
    const scrollToBottom = () => {
        if (!chatListDom.value) return;
        chatListDom.value.lastElementChild?.scrollIntoView();
        const parent = chatListDom.value.parentElement;
        if(!parent)return;
        if(parent.scrollHeight>parent.clientHeight){
            parent.scrollTop = parent.scrollHeight - parent.clientHeight;
        }
    };
    emitter.on('amis.page.ready',({instance})=>{
        nextTick(()=>{
            scrollToBottom();
        })
    })
    const forbidScroll = ref(false);
    watch(
        displayMessageList,
@@ -25,6 +36,9 @@
            deep: true,
        }
    );
    onUnmounted(()=>{
        emitter.off('amis.page.ready');
    })
    onActivated(() => {
        if (forbidScroll.value) return;
src/types/mitt.d.ts
@@ -80,6 +80,10 @@
    };
    //#endregion
    'amis.page.ready':{
        instance
    }
};
// mitt å‚数类型定义
src/utils/mitt.ts
@@ -1,6 +1,7 @@
// https://www.npmjs.com/package/mitt
import type { Emitter } from 'mitt';
import mitt from 'mitt';
import { MittType } from '../types/mitt';
// ç±»åž‹
const emitter: Emitter<MittType> = mitt<MittType>();
src/utils/request.ts
@@ -1,4 +1,4 @@
import type { AxiosInstance, AxiosRequestConfig } from 'axios';
import type { AxiosInstance, AxiosRequestConfig, CancelToken } from 'axios';
import axios from 'axios';
import { ElLoadingService, ElMessage } from 'element-plus';
import router from '../router';
@@ -10,6 +10,7 @@
    loading?: boolean;
    noAuth?: boolean;
    handleFail?: boolean;
    cancelToken?: CancelToken | undefined;
};
export const checkAuth = () => {
    const session = Local.get(accessSessionKey);
src/views/project/yw/dataManage/knowledge/Knowledge.vue
@@ -88,6 +88,7 @@
import { useCompRef } from '/@/utils/types';
import { SupervisorPublished, supervisorPublishedMap } from '/@/views/project/yw/lowCode/sqlAmis/types';
import knowledgeLeft from '/static/images/knowledge/data_type_1.png';
import axios, { CancelTokenSource } from 'axios';
const router = useRouter();
//#region ====================== èŽ·å–çŸ¥è¯†åº“sheet列表 ======================
const knowledgeBaseList = ref([]);
@@ -168,7 +169,9 @@
    chatTestIsShow.value = true;
    nextTick(() => {
        chatRef.value.clear();
        chatRef.value.autoSend(row.prompt);
        setTimeout(() => {
            chatRef.value.autoSend(row.prompt);
        }, 30);
    });
};
@@ -190,7 +193,9 @@
    },
});
const questionAi = async (text) => {
const questionAi = async (text, sourceObj: { source: CancelTokenSource }) => {
    const currentSource = axios.CancelToken.source();
    sourceObj.source = currentSource;
    const res = await check_docvector_validate(
        {
            knowlg_id: chatTestMapRow.value.id,
@@ -198,6 +203,7 @@
        },
        {
            loading: false,
            cancelToken: currentSource.token,
        }
    );
    return res;
src/views/project/yw/lowCode/sqlAmis/SqlAmis.vue
@@ -213,9 +213,10 @@
import { useCompRef } from '/@/utils/types';
import { convertListToTree } from '/@/utils/util';
import axios, { CancelTokenSource } from 'axios';
import * as supervisorGroupApi from '/@/api/supervisorAdmin/supervisorGroup';
import LeftTreeByMgr from '/@/components/tree/leftTreeByMgr.vue';
import AHMContainer from '/@/components/layout/AHMContainer.vue';
import LeftTreeByMgr from '/@/components/tree/leftTreeByMgr.vue';
import { useUpdateData } from '/@/hooks/useUpdateData';
//#region ====================== å·¦ä¾§æ ‘数据,tree init ======================
@@ -493,7 +494,9 @@
    nextTick(() => {
        chatRef.value.clear();
        chatRef.value.autoSend(row.prompt);
        setTimeout(() => {
            chatRef.value.autoSend(row.prompt);
        }, 30);
    });
};
@@ -515,7 +518,9 @@
    },
});
const questionAi = async (text) => {
const questionAi = async (text, sourceObj: { source: CancelTokenSource }) => {
    const currentSource = axios.CancelToken.source();
    sourceObj.source = currentSource;
    const res = await checkSupervisorValidate(
        {
            id: chatTestMapRow.value.id,
@@ -523,6 +528,7 @@
        },
        {
            loading: false,
            cancelToken: currentSource.token,
        }
    );
    return res;
src/views/project/yw/lowCode/sqlAmis/edit/SqlAmisEdit.vue
@@ -66,18 +66,21 @@
                    </Pane>
                    <Pane :size="65">
                        <div class=" h-full">
                            <template v-if="currentSql">
                            <template v-if="currentDockConfig">
                                <div class=" flex justify-between items-center my-1 ml-1 h-[36px]">
                                    <span class="font-bold">SQL</span>
                                    <el-select class="w-52 font-bold" v-model="currentDockConfig.type">
                                        <el-option v-for="item in Object.keys(amisDockTypeMap)" :key="item" :value="(item)" :label="amisDockTypeMap[item]"></el-option>
                                    </el-select>
                                    <el-select class="w-40" v-model="currentSql.database" @change="databaseSelectChange">
                                    <el-select class="w-40" v-model="currentDockConfig.database" @change="databaseSelectChange">
                                        <el-option v-for="item in databaseList" :key="item.id" :value="item.id" :label="item.title"></el-option>
                                    </el-select>
                                </div>
                                <codemirror
                                    class="overflow-auto"
                                    style="height: calc(100% - 36px);"
                                    v-model="currentSql.sql"
                                    v-model="currentDockConfig.sql"
                                    :autofocus="true"
                                    :indent-with-tab="true"
                                    :tab-size="2"
@@ -100,20 +103,21 @@
import { sql } from '@codemirror/lang-sql';
import { xml } from '@codemirror/lang-xml';
import { vscodeDark } from '@uiw/codemirror-theme-vscode';
import _, { debounce } from 'lodash';
import { onMounted, ref } from 'vue';
import { Codemirror } from 'vue-codemirror';
import * as codeExample from './testData';
import titleBox from '/@/components/titleBox.vue';
import { Pane, Splitpanes } from 'splitpanes';
import 'splitpanes/dist/splitpanes.css';
import type { TableInstance } from 'element-plus';
import { ElMessage } from 'element-plus';
import _, { debounce } from 'lodash';
import { Pane, Splitpanes } from 'splitpanes';
import 'splitpanes/dist/splitpanes.css';
import { v4 as uuid } from 'uuid';
import { onMounted, ref } from 'vue';
import { Codemirror } from 'vue-codemirror';
import { SupervisorPublished } from '../types';
import * as codeExample from './testData';
import * as supervisorApi from '/@/api/supervisorAdmin';
import { updateSqlApi } from '/@/api/supervisorAdmin';
import titleBox from '/@/components/titleBox.vue';
import { useCompRef } from '/@/utils/types';
import { SupervisorPublished } from '../types';
import { amisDockTypeMap } from './types';
const props = defineProps(['supervisor']);
const emit = defineEmits(['backLastPage', 'updatePublished']);
@@ -134,10 +138,10 @@
let defaultSelectDatabase = null;
const databaseSelectChange = (val) => {
    defaultSelectDatabase = val;
    if(currentSql.value){
        currentSql.value.database = val;
    if(currentDockConfig.value){
        currentDockConfig.value.database = val;
    }
    updateSqlAndRs(currentSql.value.id,currentSql.value)
    updateSqlAndRs(currentDockConfig.value.id,currentDockConfig.value)
};
const backLastPage = () => {
    // setTimeout(() => {
@@ -148,14 +152,14 @@
const currentRs = ref<AmisDockConfig>(null);
const dockRowChange = (row) => {
    currentRs.value = row;
    currentSql.value = dockConfigList.value.find((item) => item.id === currentRs.value.recordId) ?? {
    currentDockConfig.value = dockConfigList.value.find((item) => item.id === currentRs.value.recordId) ?? {
        id: row.recordId,
        type: AmisDockType.Sql,
        sql: '',
        database: defaultSelectDatabase ?? databaseList.value[0]?.id ?? null,
    };
};
const currentSql = ref(null);
const currentDockConfig = ref(null);
/** @description è·¯å¾„分隔符 */
const PATH_SEPARATOR = '/';
/** @description 1 é€€å‡ºæ‰€æœ‰å¾ªçޝ -1退出当次循环 0或其他值继续 */
@@ -295,13 +299,13 @@
const sqlCodeChange = debounce((val) => {
    if (!currentRs.value.recordId) return;
    if (currentSql.value) {
        if (!currentSql.value.database) {
    if (currentDockConfig.value) {
        if (!currentDockConfig.value.database) {
            ElMessage.warning('请先选择数据库');
            return;
        }
    }
    updateSqlAndRs(currentSql.value.id, currentSql.value);
    updateSqlAndRs(currentDockConfig.value.id, currentDockConfig.value);
}, 1000);
const dockConfigList = ref([]);
const rsTableRef = ref<TableInstance>(null);
src/views/project/yw/lowCode/sqlAmis/edit/types.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,7 @@
export const enum AmisDockType {
    Sql = 'SQL',
}
export const amisDockTypeMap = {
    [AmisDockType.Sql]: 'SQL',
};