From f81a35c10e6c697982b02540c93d302e654810c1 Mon Sep 17 00:00:00 2001 From: caorui <3165079241@qq.com> Date: Fri, 4 Jul 2025 17:59:47 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9C=BA=E6=99=AF=E4=B8=AD=E5=BF=83=E5=8A=A8?= =?UTF-8?q?=E6=80=81=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/LinkUp/compoment/addDialogChunk.vue | 276 +++++++++++++----- 1 file changed, 199 insertions(+), 77 deletions(-) diff --git a/src/views/LinkUp/compoment/addDialogChunk.vue b/src/views/LinkUp/compoment/addDialogChunk.vue index e1cffdc..c4ab631 100644 --- a/src/views/LinkUp/compoment/addDialogChunk.vue +++ b/src/views/LinkUp/compoment/addDialogChunk.vue @@ -129,7 +129,10 @@ v-show="representation" >
- + @@ -551,10 +554,11 @@ label-position="top" style="margin: 0 10px" > -
+
@@ -628,6 +632,10 @@ + +
+ 点击测试 +
@@ -772,11 +780,69 @@ export default { }, currenrActiveNodeRef: "", lastSelectedTokenIndex: -1, - tokenCounter: 0, representationData: representationData, + savedRange: null, // ⬅️ 用于存储当前 range }; }, methods: { + async HitTesting() { + this.openLoading("处理"); + // 使用示例:传入你这段 HTML 所在的 DOM 根节点 + const root = document.querySelector("#editorContainer"); + const parsed = this.extractEditorItems(root); + let data = this.drawShowList[this.drawSelectIndex].options; + let params = { + detailList: parsed, + flowId: this.sceneID, + stepID: data.stepID, + stepAccountId: data.step_acc_id, + actionName: data.apiName || data.plugName, + tableName: this.outsideFormData.tableName, + }; + let res = await authApi( + "sysFlowStepConfigService", + "", + "saveOrUpdateConfig", + "", + params + ); + if (res.status == "200") { + this.$vmNews("测试成功!", "success"); + } + }, + extractEditorItems(rootElement) { + const result = []; + const items = rootElement.querySelectorAll(".editorItem"); + + items.forEach((item) => { + const fieldName = + item.querySelector(".el-form-item__label")?.innerText.trim() || ""; + const editor = item.querySelector(".content-editor"); + if (!editor) return; + + const html_label = editor.innerHTML.trim(); // 保留标签结构 + + let whereCondition = ""; + editor.childNodes.forEach((node) => { + if (node.nodeType === Node.TEXT_NODE) { + whereCondition += node.textContent; + } else if (node.nodeType === Node.ELEMENT_NODE) { + whereCondition += node.getAttribute("data-token-text") || ""; + } + }); + + // 替换中文符号为英文符号 + whereCondition = whereCondition + .replace(/,/g, ",") + .replace(/(/g, "(") + .replace(/)/g, ")"); + + result.push({ fieldName, whereCondition, html_label }); + }); + + return result; + }, + /** * 打开弹窗 * @param {string} sceneID 场景 ID @@ -1592,10 +1658,20 @@ export default { } }, // 切换表时 - outsideSelectChange(val) { + async outsideSelectChange(val) { if (val) { this.outsideColumns = []; - this.queryColumns(val); + // 更新当前步骤的步骤描述 + this.drawShowList[this.drawSelectIndex].options.description = + this.description; + let params = { + flowId: this.sceneID, + id: this.drawShowList[this.drawSelectIndex].options.stepID, + tableName: val, + }; + // 保存场景步骤数据 + await this.SaveSceneStepData(params); + await this.queryColumns(val); } }, // 获取表字段 @@ -1773,7 +1849,24 @@ export default { this.userList = []; this.representation = false; }, + representationChange() { + if (!this.currenrActiveNodeRef) return; + const editor = this.$refs[this.currenrActiveNodeRef][0]; + if (!editor) return; + // 创建 range 和 selection + const range = document.createRange(); + const selection = window.getSelection(); + // 将 range 定位到 editor 的最后一个子节点 + range.selectNodeContents(editor); + range.collapse(false); // 折叠到末尾 + // 清空现有选区并设置新 range + selection.removeAllRanges(); + selection.addRange(range); + // 确保编辑器有焦点 + editor.focus(); + this.saveRange(); + }, handleKeyDown(e, columnName, rowIndex) { const editor = this.$refs["contentEditor" + columnName + rowIndex][0]; @@ -1799,20 +1892,6 @@ export default { } } } - - // 清除token选中状态(除了特殊键) - if ( - ![ - "Backspace", - "Delete", - "ArrowLeft", - "ArrowRight", - "ArrowUp", - "ArrowDown", - ].includes(e.key) - ) { - this.clearTokenSelection(columnName, rowIndex); - } }, // 清除token选中状态 clearTokenSelection(columnName, rowIndex) { @@ -1822,29 +1901,27 @@ export default { }, // 处理输入事件 handleInput(e, columnName, rowIndex) { - // 清除token选中状态 - this.clearTokenSelection(columnName, rowIndex); - - // 强制更新computed属性 - this.$forceUpdate(); + // this.clearTokenSelection(columnName, rowIndex); + this.saveRange(); }, // 处理编辑器点击 handleEditorClick(e, columnName, rowIndex) { const editor = this.$refs["contentEditor" + columnName + rowIndex][0]; this.currenrActiveNodeRef = "contentEditor" + columnName + rowIndex; - // 如果点击的不是token,清除选中状态 - if ( - !e.target.classList.contains("content-token") && - !e.target.closest(".content-token") - ) { - this.clearTokenSelection(columnName, rowIndex); - } + // // 如果点击的不是token,清除选中状态 + // if ( + // !e.target.classList.contains("content-token") && + // !e.target.closest(".content-token") + // ) { + // this.clearTokenSelection(columnName, rowIndex); + // } - // 确保编辑器获得焦点 - if (e.target === editor || editor.contains(e.target)) { - editor.focus(); - } + // // 确保编辑器获得焦点 + // if (e.target === editor || editor.contains(e.target)) { + editor.focus(); + this.saveRange(); + // } }, // 处理粘贴事件 handlePaste(e, columnName, rowIndex) { @@ -1854,7 +1931,6 @@ export default { // 处理编辑器获得焦点 handleEditorFocus(e, columnName, rowIndex) { const editor = this.$refs["contentEditor" + columnName + rowIndex][0]; - // 如果编辑器为空,设置光标到开始位置 if (this.isEmpty(columnName, rowIndex)) { setTimeout(() => { @@ -1900,6 +1976,7 @@ export default { selection.addRange(range); // 确保编辑器有焦点 editor.focus(); + this.saveRange(); }); }, @@ -1925,13 +2002,14 @@ export default { selection.addRange(range); // 确保编辑器有焦点 editor.focus(); + this.saveRange(); }, handleNodeSelected(path) { this.selectedNode = path; this.insertToken(path, "node-reference"); }, - handleTagSelected(label){ - + handleTagSelected(label) { + this.insertToken(label, "node-edit"); }, // 插入token到编辑器 insertToken(text, type) { @@ -1942,46 +2020,64 @@ export default { // 确保编辑器有焦点 editor.focus(); + setTimeout(() => { + const token = this.createTokenElement(text, type); + const space = document.createTextNode(" "); - const token = this.createTokenElement(text, type); + // 获取当前光标位置 + const selection = window.getSelection(); + let range = this.savedRange?.cloneRange(); - // 获取当前光标位置 - const selection = window.getSelection(); - if (selection.rangeCount > 0) { - const range = selection.getRangeAt(0); + // fallback:没有保存 range,则使用当前选区 + if (!range && selection.rangeCount > 0) { + range = selection.getRangeAt(0); + } + + if (!range) { + // fallback:插入到末尾 + editor.appendChild(token); + editor.appendChild(space); + this.setCursorToEnd(); + this.$nextTick(() => { + if (!this.setCursorAfter(space)) { + this.setCursorToEnd(); + } + }); + return; + } + + // 删除选中内容(若有) range.deleteContents(); - // 插入token - range.insertNode(token); + // 插入 token + 空格 + const frag = document.createDocumentFragment(); + frag.appendChild(token); + frag.appendChild(space); + range.insertNode(frag); - // 在token后添加一个空格 - const space = document.createTextNode(" "); - range.setStartAfter(token); - range.insertNode(space); + // 设置光标到空格后 + range.setStartAfter(space); + range.collapse(true); + selection.removeAllRanges(); + selection.addRange(range); - // 使用setTimeout确保DOM更新完成后设置光标 - setTimeout(() => { - if (!this.setCursorAfter(space)) { - // 如果设置失败,则设置到编辑器末尾 - this.setCursorToEnd(); - } - }, 10); // 增加延迟时间确保DOM完全更新 - } else { - // 如果没有选中区域,直接添加到末尾 - editor.appendChild(token); - const space = document.createTextNode(" "); - editor.appendChild(space); + // 更新 savedRange + this.savedRange = range.cloneRange(); - // 使用setTimeout确保DOM更新完成后设置光标 - setTimeout(() => { + this.$nextTick(() => { if (!this.setCursorAfter(space)) { this.setCursorToEnd(); } - }, 10); + }); + + this.saveRange(); + }, 10); + }, + saveRange() { + const selection = window.getSelection(); + if (selection.rangeCount > 0) { + this.savedRange = selection.getRangeAt(0).cloneRange(); } - - // 强制更新 - this.$forceUpdate(); }, // 设置光标到末尾 setCursorToEnd() { @@ -2014,15 +2110,17 @@ export default { }, // 创建token元素 createTokenElement(text, type) { - const token = document.createElement("span"); - token.className = `content-token token-function`; - token.contentEditable = false; - token.setAttribute("data-token-id", ++this.tokenCounter); - token.setAttribute("data-token-type", type); - token.setAttribute("data-token-text", text); + let token = null; + token = document.createElement("span"); + token.contentEditable = false; + token.setAttribute("data-token-text", text); if (type === "node-reference") { + token.className = "content-token token-function"; token.innerHTML = ` ${text}`; + } else { + token.className = "content-token token-edit"; + token.innerHTML = `${text}`; } return token; }, @@ -2047,6 +2145,15 @@ export default { this.currenrActiveNodeRef = ""; }, }, + mounted() { + // 绑定事件监听器 + const editor = this.$refs[this.currenrActiveNodeRef]?.[0]; + if (editor) { + editor.addEventListener("mouseup", this.saveRange); + editor.addEventListener("keyup", this.saveRange); + editor.addEventListener("mouseleave", this.saveRange); // 鼠标移开也记录一次 + } + }, }; @@ -2874,9 +2981,9 @@ export default { user-select: none; } ::v-deep .token-function { - background: #e0e7ff; - color: #5b21b6; - border: 1px solid #8b5cf6; + background: #ecfdf5; + color: #047857; + border: 1px solid #10b981; } ::v-deep .repContainer { @@ -2915,7 +3022,7 @@ export default { cursor: pointer; } -.repItem:hover .repItemValue{ +.repItem:hover .repItemValue { color: #409eff; } @@ -2924,6 +3031,21 @@ export default { font-size: 13px; margin-left: 10px; } + +.token-editable-content { + display: inline-block; + min-width: 1em; + padding: 0 2px; + border-bottom: 1px dashed #aaa; + cursor: text; + outline: none; +} +::v-deep .content-token.token-edit { + display: inline-flex !important; + color: #5b21b6; + font-weight: bold; + padding: 0; +}