From 4f2d13e6de729a08bf96a391fdd21f1cc8f48453 Mon Sep 17 00:00:00 2001 From: wujingjing <gersonwu@qq.com> Date: 星期五, 20 九月 2024 13:03:28 +0800 Subject: [PATCH] 自动加注释 --- src/views/project/yw/lowCode/sqlAmis/edit/SqlAmisEdit.vue | 395 ++++++++++++++++++++++++++++++++++++++++++++------------ 1 files changed, 309 insertions(+), 86 deletions(-) diff --git a/src/views/project/yw/lowCode/sqlAmis/edit/SqlAmisEdit.vue b/src/views/project/yw/lowCode/sqlAmis/edit/SqlAmisEdit.vue index e36ebba..08b1351 100644 --- a/src/views/project/yw/lowCode/sqlAmis/edit/SqlAmisEdit.vue +++ b/src/views/project/yw/lowCode/sqlAmis/edit/SqlAmisEdit.vue @@ -13,50 +13,92 @@ </template> </titleBox> - <div class="grid grid-cols-2 gap-2 h-full flex-auto"> - <div class="h-full overflow-auto"> + <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="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" v-if="currentSql"> - <codemirror - class="h-full overflow-auto" - v-model="currentSql.sql" - :style="{ height: '100%' }" - :autofocus="true" - :indent-with-tab="true" - :tab-size="2" - :extensions="sqlEditorExtensions" - @change="sqlCodeChange" - @focus="log('focus', $event)" - @blur="log('blur', $event)" - /> - </div> - </div> + <!-- <el-table-column label="璇锋眰鍦板潃" ></el-table-column> --> + </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" width="150" 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" width="450" label="鎻愮ず璇�" show-overflow-tooltip> + <template #default="scope"> + <el-input type="textarea" :rows="2" 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> @@ -65,21 +107,24 @@ 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 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, watch } from 'vue'; +import { Codemirror } from 'vue-codemirror'; +import { SupervisorPublished } from '../types'; +import * as codeExample from './testData'; +import { amisDockTypeMap } from './types'; import * as supervisorApi from '/@/api/supervisorAdmin'; import { updateSqlApi } from '/@/api/supervisorAdmin'; +import titleBox from '/@/components/titleBox.vue'; import { useCompRef } from '/@/utils/types'; const props = defineProps(['supervisor']); -const emit = defineEmits(['backLastPage']); +const emit = defineEmits(['backLastPage', 'updatePublished']); const log = console.log; const jsonCode = ref(codeExample.jsonCode); const dockCode = ref(codeExample.dockCode); @@ -93,6 +138,15 @@ configList.value = []; sqlCode.value = ''; }; + +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(); @@ -100,18 +154,60 @@ emit('backLastPage'); }; const currentRs = ref<AmisDockConfig>(null); + +const getWithTemplateDataCommentSql = (sql: string, data: any) => { + if (!Array.isArray(data)) { + return sql; + } + const first = data[0]; + if (!_.isObjectLike(first)) { + return sql; + } + const firstKeyList = Object.keys(first); + // 鍊间负瀵硅薄 + if (_.isObjectLike(first[firstKeyList[0]])) { + return sql; + } + + + + let comment = ''; + firstKeyList.map((key, index, array) => { + const value = JSON.stringify(first[key]); + comment += `-- "${key}": ${value}\n`; + }); + + const reg = new RegExp(`^\\s*(\\s*--\\s*".*"\\s*:.*\\n)+`) + // 宸茬粡瀛樺湪锛屼竴瀹氳鏇挎崲鎴愭渶鏂扮殑 + if (reg.test(sql)) { + const replaceStr = sql.replace(reg,comment); + return replaceStr; + } + + const result = comment+sql; + return result; +}; const dockRowChange = (row) => { currentRs.value = row; - currentSql.value = sqlList.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 templateData = extraInfoMap.value.get(row.recordId).templateData; + + currentDockConfig.value.sql = getWithTemplateDataCommentSql(currentDockConfig.value.sql,templateData) }; -const currentSql = ref(null); +const currentDockConfig = ref(null); /** @description 璺緞鍒嗛殧绗� */ const PATH_SEPARATOR = '/'; /** @description 1 閫�鍑烘墍鏈夊惊鐜� -1閫�鍑哄綋娆″惊鐜� 0鎴栧叾浠栧�肩户缁� */ -const travelObj = (obj, callBack?: (key?: string, value?: any, path?: string) => 1 | -1 | undefined | void | 0, path = '') => { +const travelObj = ( + obj, + callBack?: (key?: string, value?: any, path?: string, item?: any) => 1 | -1 | undefined | void | 0, + path = '' +) => { let entry = Object.entries(obj); let res; @@ -119,7 +215,7 @@ iterate: for (const item of entry) { const [key, value] = item; const currentPath = path ? path + PATH_SEPARATOR + key : key; - res = callBack?.(key, value, currentPath); + res = callBack?.(key, value, currentPath, obj); switch (res) { case 1: break iterate; @@ -147,7 +243,7 @@ }; const enum AmisDockType { - Api, + Sql = 'SQL', } type AmisDockApi = string; type AmisDockValue = AmisDockApi; @@ -156,58 +252,105 @@ path: string; asyncId: string; recordId: string; + // url: string; }; const configList = ref<AmisDockConfig[]>([]); -const parseJSONData = (obj: any) => { - const apiDataList = configList.value; + +type ExtraInfo = { + url: string; + templateData: Array<any>; +}; +const extraInfoMap = ref(new Map<string, ExtraInfo>()); + +const getAmisData = (data) => { + if (!data) return null; + + const dataKeyList = Object.keys(data); + if (dataKeyList.length === 0) return null; + if (dataKeyList.length === 1) return data.items ?? data.rows ?? data; + + return data; +}; +const parseJSONData = (obj: any, apiDataList) => { // 鍏堟竻绌� - configList.value = []; - travelObj(obj, (key, value, path) => { + + const jsonConfigList = []; + extraInfoMap.value.clear(); + travelObj(obj, (key, value, path, item) => { if (key === 'api') { // const url = value.url; const urlPath = path + PATH_SEPARATOR + 'url'; - const randomStr = '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; + + extraInfoMap.value.set(recordId, { + url: value.url, + templateData: getAmisData(item.data), + }); // const recordId = uniqueId() - configList.value.push({ + jsonConfigList.push({ asyncId: asyncId, recordId: recordId, - type: AmisDockType.Api, + type: AmisDockType.Sql, path: urlPath, }); } }); + + return jsonConfigList; }; -const updateSqlAndRs = (id?, sqlValue?: string) => { - const apiConfig = configList.value.filter((item) => item.type === AmisDockType.Api); - if (apiConfig.length === 0) return; +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) { - const found = sqlList.value?.find((item) => item.id === id); - if (found) { - found.sql = sqlValue; + if (id && sqlValue) { + const foundIndex = dockConfigList.value?.findIndex((item) => item.id === id); + if (foundIndex > -1) { + dockConfigList.value[foundIndex] = { + ...dockConfigList.value[foundIndex], + ...sqlValue, + }; } else { - if (!sqlList.value || sqlList.value.length === 0) { - sqlList.value = [ - { - id: id, - sql: sqlValue, - }, - ]; + 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 { - sqlList.value.push({ - id: id, - sql: sqlValue, - }); + dockConfigList.value.push(newSqlValue); } } } @@ -215,49 +358,129 @@ updateSqlApi( { id: props.supervisor.id, - sql_json: sqlList.value.length === 0 ? null : JSON.stringify(sqlList.value), + 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); + }); }; const sqlCodeChange = debounce((val) => { if (!currentRs.value.recordId) return; - updateSqlAndRs(currentRs.value.recordId, val); + if (currentDockConfig.value) { + if (!currentDockConfig.value.database) { + ElMessage.warning('璇峰厛閫夋嫨鏁版嵁搴�'); + return; + } + } + updateSqlAndRs(currentDockConfig.value.id, currentDockConfig.value); }, 1000); -const sqlList = ref([]); +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, }); - if (!xmlJson?.amis_json) { - ElMessage.warning('鏆傛棤SQL閰嶇疆'); - return; - } - configList.value = + + const originConfig = xmlJson.async_rs?.map( (item) => ({ - type: AmisDockType.Api, + type: AmisDockType.Sql, asyncId: item.async_id, recordId: item.rec_id, path: item.amis_path, } as AmisDockConfig) ) ?? []; - sqlList.value = xmlJson.sql ?? null; + dockConfigList.value = xmlJson.def_rs_json ?? null; + args.value = xmlJson.args ?? []; - parseJSONData(xmlJson.amis_json); + 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]); - // dockRowChange(configList.value[0]); } - // 鑷姩鏇存柊Rs - updateSqlAndRs(); + if (!configList || configList.value.length === 0) { + ElMessage.warning('鏆傛棤瀵规帴閰嶇疆'); + } + + const isRsUpdate = checkRsUpdate(originConfig, configList.value); + if (isRsUpdate) { + // 鑷姩鏇存柊Rs + updateSqlAndRs(); + } }); + +// watch(() => sqlCodemirrorRef.value, (codeMirrorRef) => { +// codeMirrorRef. +// }) </script> -- Gitblit v1.9.3