From 39ab910fe59480a35ebca316cd66e3995e70d4ed Mon Sep 17 00:00:00 2001 From: wujingjing <gersonwu@qq.com> Date: 星期五, 13 九月 2024 11:58:49 +0800 Subject: [PATCH] 支持刷新低代码, --- src/views/project/yw/lowCode/sqlAmis/edit/SqlAmisEdit.vue | 410 +++++++++++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 335 insertions(+), 75 deletions(-) diff --git a/src/views/project/yw/lowCode/sqlAmis/edit/SqlAmisEdit.vue b/src/views/project/yw/lowCode/sqlAmis/edit/SqlAmisEdit.vue index d4a697b..21e09d6 100644 --- a/src/views/project/yw/lowCode/sqlAmis/edit/SqlAmisEdit.vue +++ b/src/views/project/yw/lowCode/sqlAmis/edit/SqlAmisEdit.vue @@ -1,61 +1,104 @@ <template> <div class="h-full flex flex-col"> - <div class="grid grid-cols-2 gap-2 h-full flex-0"> - <div class="h-full overflow-auto"> + <titleBox class="flex-0" style="background-color: #fff" :title="supervisor?.title"> + <template v-slot:left> + <el-button + icon="ele-ArrowLeft" + link + style="margin-right: 10px; margin-left: 10px; width: 40px" + size="small" + @click="backLastPage" + > + </el-button> + </template> + </titleBox> + + <Splitpanes class="default-theme flex-auto" :horizontal="false"> + <Pane :size="40" class="flex-column"> + <div class="flex-0 flex justify-between items-center mb-1 ml-1 h-[36px]"> + <span class="font-bold">閰嶇疆椤�</span> + </div> <el-table + ref="rsTableRef" :data="configList" row-class-name="cursor-pointer" - class="h-full" + class="flex-auto" highlight-current-row @current-change="dockRowChange" > + <el-table-column prop="asyncId" label="鏌ヨ id" /> <el-table-column prop="path" label="閰嶇疆璺緞" /> - <el-table-column prop="recordId" label="SQL璁板綍id" /> - <el-table-column prop="queryId" label="鏌ヨid" /> - <el-table-column prop="url" label="璇锋眰鍦板潃" /> - </el-table> - <!-- <codemirror - v-model="dockCode" - :style="{ height: '100%' }" - :autofocus="true" - :indent-with-tab="true" - :tab-size="2" - :extensions="dockEditorExtensions" - @change="log('change', $event)" - @focus="log('focus', $event)" - @blur="log('blur', $event)" - /> --> - </div> - <div class="h-full overflow-auto"> - <codemirror - class="h-full overflow-auto" - v-model="sqlCode" - :style="{ height: '100%' }" - :autofocus="true" - :indent-with-tab="true" - :tab-size="2" - :extensions="sqlEditorExtensions" - @change="log('change', $event)" - @focus="log('focus', $event)" - @blur="log('blur', $event)" - /> - </div> - </div> - <!-- <div class="flex-auto overflow-auto mt-3"> - <codemirror - disabled - class="h-full overflow-auto" - v-model="jsonCode" - :style="{ height: '100%' }" - :autofocus="true" - :indent-with-tab="true" - :tab-size="2" - :extensions="jsonEditorExtensions" - @change="log('change', $event)" - @focus="log('focus', $event)" - @blur="log('blur', $event)" - /> - </div> --> + <el-table-column prop="recordId" label="SQL id" /> + <!-- <el-table-column prop="url" label="璇锋眰鍦板潃" /> --> + </el-table></Pane + > + <Pane :size="60"> + <Splitpanes class="default-theme h100" :horizontal="true"> + <Pane :size="35" class="flex-col flex"> + <div class="flex-0 flex justify-between items-center mb-1 ml-1 h-[36px]"> + <span class="font-bold">鍙傛暟</span> + <el-button type="primary" @click="addArg">娣诲姞</el-button> + </div> + <el-table class="flex-auto" :data="args" border> + <el-table-column prop="name" label="鍚嶇О" show-overflow-tooltip> + <template #default="scope"> + <el-input v-model="scope.row.name" @input="argsInput"></el-input> + </template> + </el-table-column> + <el-table-column prop="prompt" label="鎻愮ず璇�" show-overflow-tooltip> + <template #default="scope"> + <el-input v-model="scope.row.prompt" @input="argsInput"></el-input> + </template> + </el-table-column> + <el-table-column prop="check" label="缂虹渷鍊�" show-overflow-tooltip> + <template #default="scope"> + <el-input v-model="scope.row.check" @input="argsInput"></el-input> + </template> + </el-table-column> + <el-table-column label="" width="55" fixed="right" show-overflow-tooltip> + <template #default="scope"> + <el-tooltip effect="dark" content="鍒犻櫎" placement="top"> + <i class="ywifont ywicon-shanchu !text-[17px] text-red-400 cursor-pointer" @click="deleteArg(scope.$index)"></i> + </el-tooltip> + </template> + </el-table-column> + </el-table> + </Pane> + <Pane :size="65"> + <div class="h-full"> + <template v-if="currentDockConfig"> + <div class="flex justify-between items-center my-1 ml-1 h-[36px]"> + <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="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="currentDockConfig.sql" + :autofocus="true" + :indent-with-tab="true" + :tab-size="2" + :extensions="sqlEditorExtensions" + @change="sqlCodeChange" + @focus="log('focus', $event)" + @blur="log('blur', $event)" + /> + </template> + </div> + </Pane> + </Splitpanes> + </Pane> + </Splitpanes> </div> </template> @@ -64,11 +107,24 @@ import { sql } from '@codemirror/lang-sql'; import { xml } from '@codemirror/lang-xml'; import { vscodeDark } from '@uiw/codemirror-theme-vscode'; -import { ref } from 'vue'; +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 _, { uniqueId } from 'lodash'; -import {v4 as uuid} from 'uuid' +import * as supervisorApi from '/@/api/supervisorAdmin'; +import { updateSqlApi } from '/@/api/supervisorAdmin'; +import titleBox from '/@/components/titleBox.vue'; +import { useCompRef } from '/@/utils/types'; +import { amisDockTypeMap } from './types'; + +const props = defineProps(['supervisor']); +const emit = defineEmits(['backLastPage', 'updatePublished']); const log = console.log; const jsonCode = ref(codeExample.jsonCode); const dockCode = ref(codeExample.dockCode); @@ -77,8 +133,37 @@ const jsonEditorExtensions = [json(), vscodeDark]; const sqlEditorExtensions = [sql(), vscodeDark]; const dockEditorExtensions = [xml(), vscodeDark]; +const sqlCodeEditorRef = useCompRef(Codemirror); +const resetStatus = () => { + configList.value = []; + sqlCode.value = ''; +}; -const dockRowChange = (row) => {}; +let defaultSelectDatabase = null; +const databaseSelectChange = (val) => { + defaultSelectDatabase = val; + if (currentDockConfig.value) { + currentDockConfig.value.database = val; + } + updateSqlAndRs(currentDockConfig.value.id, currentDockConfig.value); +}; +const backLastPage = () => { + // setTimeout(() => { + // resetStatus(); + // }, 300); + emit('backLastPage'); +}; +const currentRs = ref<AmisDockConfig>(null); +const dockRowChange = (row) => { + currentRs.value = row; + 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 currentDockConfig = ref(null); /** @description 璺緞鍒嗛殧绗� */ const PATH_SEPARATOR = '/'; /** @description 1 閫�鍑烘墍鏈夊惊鐜� -1閫�鍑哄綋娆″惊鐜� 0鎴栧叾浠栧�肩户缁� */ @@ -118,43 +203,218 @@ }; const enum AmisDockType { - Api, + Sql = 'SQL', } type AmisDockApi = string; type AmisDockValue = AmisDockApi; type AmisDockConfig = { - type: AmisDockType; + type?: AmisDockType; path: string; - value: AmisDockValue; + asyncId: string; + recordId: string; }; -type AmisDockSQLConfig = AmisDockConfig&{ - queryId:string; - recordId:string; -} - const configList = ref<AmisDockConfig[]>([]); -const parseJSONData = (json: string) => { - if (!json) return; - const obj = JSON.parse(json); +const parseJSONData = (obj: any, apiDataList) => { + // 鍏堟竻绌� + + const jsonConfigList = []; travelObj(obj, (key, value, path) => { if (key === 'api') { - const url = value.url; + // const url = value.url; const urlPath = path + PATH_SEPARATOR + 'url'; - const queryId ='query_'+uuid().slice(0,12); - + const randomStr = 'q_' + value.url + '_' + uuid().slice(0, 12); + const foundItem = apiDataList.find((item) => item.path === urlPath); + const asyncId = foundItem?.asyncId ?? randomStr; + const recordId = foundItem?.recordId ?? randomStr; // const recordId = uniqueId() - configList.value.push({ - queryId:queryId, - recordId:queryId, - type: AmisDockType.Api, + jsonConfigList.push({ + asyncId: asyncId, + recordId: recordId, + type: AmisDockType.Sql, path: urlPath, - value: url, - url:url, - } as any); + }); } + }); + + return jsonConfigList; +}; + +const checkValid = (showTip: boolean, tip?: string) => { + if(!dockConfigList.value || dockConfigList.value.length===0) return true; + const foundWithNoDatabase = dockConfigList.value?.find((item) => !item.database); + if (foundWithNoDatabase && showTip) { + ElMessage.warning(tip ?? `銆�${foundWithNoDatabase.id}銆戞湭閫夋嫨鏁版嵁搴揱); + } + return !foundWithNoDatabase; +}; + +const updateSqlAndRs = (id?, sqlValue?: { database?: string; sql?: string; type?: AmisDockType }) => { + const apiConfig = configList.value.filter((item) => item.type === AmisDockType.Sql); + + if (!checkValid(true)) { + return; + } + + const recordIds = apiConfig?.map(item=>item.recordId)??[]; + // 杩囨护鍑� apiConfig 涓湁鐨剅ecord; + dockConfigList.value = dockConfigList.value?.filter(item=>recordIds.includes(item.id))??[] + const asyncRsList = apiConfig.map((item) => ({ + amis_path: item.path, + async_id: item.asyncId, + rec_id: item.recordId, + })); + + if (id && sqlValue) { + const foundIndex = dockConfigList.value?.findIndex((item) => item.id === id); + if (foundIndex > -1) { + dockConfigList.value[foundIndex] = { + ...dockConfigList.value[foundIndex], + ...sqlValue, + }; + } else { + if (!sqlValue.database) { + ElMessage.warning('璇峰厛閫夋嫨鏁版嵁搴�'); + return; + } + const newSqlValue = { + id: id, + database: sqlValue.database ?? null, + sql: sqlValue.sql ?? null, + type: sqlValue.type ?? AmisDockType.Sql, + }; + if (!dockConfigList.value || dockConfigList.value.length === 0) { + dockConfigList.value = [newSqlValue]; + } else { + dockConfigList.value.push(newSqlValue); + } + } + } + + updateSqlApi( + { + id: props.supervisor.id, + def_rs_json: dockConfigList.value.length === 0 ? null : JSON.stringify(dockConfigList.value), + async_rs_json: asyncRsList.length === 0 ? null : JSON.stringify(asyncRsList), + args: args.value.length === 0 ? null : JSON.stringify(args.value), + }, + { + loading: false, + } + ).then(() => { + emit('updatePublished', props.supervisor.id, SupervisorPublished.N); }); }; -parseJSONData(codeExample.jsonCode); +const sqlCodeChange = debounce((val) => { + if (!currentRs.value.recordId) return; + if (currentDockConfig.value) { + if (!currentDockConfig.value.database) { + ElMessage.warning('璇峰厛閫夋嫨鏁版嵁搴�'); + return; + } + } + updateSqlAndRs(currentDockConfig.value.id, currentDockConfig.value); +}, 1000); +const dockConfigList = ref([]); +const rsTableRef = ref<TableInstance>(null); +let xmlJson = null; + +// 妫�鏌ユ槸鍚﹂渶瑕佹洿鏂� rs +const checkRsUpdate = (originData: AmisDockConfig[], currentData: AmisDockConfig[]) => { + + // 閮戒负绌猴紝涓嶉渶瑕佹洿鏂� + if ((!originData || originData.length === 0) && (!currentData || currentData.length === 0)) { + return false; + } + + // 瀛樺湪涓�鏂逛负绌猴紝闇�瑕佹洿鏂� + if (!originData || !currentData) { + return true; + } + + // 闀垮害涓嶄竴鑷达紝闇�瑕佹洿鏂� + if (originData.length !== currentData.length) { + return true; + } + + return originData.some((originItem) => { + const id = originItem.asyncId; + const currentItem = currentData.find((item) => item.asyncId === id); + // 娌℃壘鍒板搴旈」锛岄渶瑕佹洿鏂� + if (!currentItem) { + return true; + } + + // 瀵硅薄椤瑰�间笉鐩哥瓑锛岄渶瑕佹洿鏂� + return Object.keys(currentItem).some((item) => originItem[item] !== currentItem[item]); + }); +}; + +//#region ====================== 鍙紪杈戣〃鏍� ====================== +const args = ref([]); +const debounceUpdateInput = debounce(() => { + updateSqlAndRs(); +}, 400); +const argsInput = (val) => { + debounceUpdateInput(); +}; +const addArg = () => { + const initData = { + name: '', + prompt: '', + check: '', + }; + if (!args.value || args.value.length === 0) { + args.value = [initData]; + } else { + args.value.push(initData); + } + + updateSqlAndRs(); +}; + +const deleteArg = (index) => { + args.value.splice(index, 1); + updateSqlAndRs(); +}; + +const databaseList = ref([]); +//#endregion +onMounted(async () => { + xmlJson = await supervisorApi.getLowCodeJson({ + id: props.supervisor.id, + }); + + + const originConfig = + xmlJson.async_rs?.map( + (item) => + ({ + type: AmisDockType.Sql, + asyncId: item.async_id, + recordId: item.rec_id, + path: item.amis_path, + } as AmisDockConfig) + ) ?? []; + dockConfigList.value = xmlJson.def_rs_json ?? null; + args.value = xmlJson.args ?? []; + + configList.value = parseJSONData(xmlJson.amis_json, originConfig); + const res = await supervisorApi.getAmisDatabaseList(); + databaseList.value = res.values ?? []; + if (configList.value.length > 0) { + rsTableRef.value.setCurrentRow(configList.value[0]); + } + + if(!configList || configList.value.length===0 ){ + ElMessage.warning('鏆傛棤瀵规帴閰嶇疆'); + } + + const isRsUpdate = checkRsUpdate(originConfig, configList.value) + if (isRsUpdate) { + // 鑷姩鏇存柊Rs + updateSqlAndRs(); + } +}); </script> -- Gitblit v1.9.3