场景中心动态配置

This commit is contained in:
caorui 2025-07-04 17:59:47 +08:00
parent 66427493fc
commit f81a35c10e
1 changed files with 199 additions and 77 deletions

View File

@ -129,7 +129,10 @@
v-show="representation" v-show="representation"
> >
<div class="repContainer"> <div class="repContainer">
<el-tabs v-model="representationActiveName"> <el-tabs
v-model="representationActiveName"
@tab-click="representationChange"
>
<el-tab-pane label="动态内容" name="first"></el-tab-pane> <el-tab-pane label="动态内容" name="first"></el-tab-pane>
<el-tab-pane label="表达式" name="second"></el-tab-pane> <el-tab-pane label="表达式" name="second"></el-tab-pane>
</el-tabs> </el-tabs>
@ -551,10 +554,11 @@
label-position="top" label-position="top"
style="margin: 0 10px" style="margin: 0 10px"
> >
<div ref="editorContainer"> <div id="editorContainer">
<div <div
v-for="(row, rowIndex) in outsideColumns" v-for="(row, rowIndex) in outsideColumns"
:key="rowIndex" :key="rowIndex"
class="editorItem"
> >
<el-form-item :label="row.column_name"> <el-form-item :label="row.column_name">
<div class="editor-container"> <div class="editor-container">
@ -628,6 +632,10 @@
</el-form> </el-form>
</el-collapse-item> </el-collapse-item>
</el-collapse> </el-collapse>
<div>
<el-button @click="HitTesting">点击测试</el-button>
</div>
</div> </div>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
@ -772,11 +780,69 @@ export default {
}, },
currenrActiveNodeRef: "", currenrActiveNodeRef: "",
lastSelectedTokenIndex: -1, lastSelectedTokenIndex: -1,
tokenCounter: 0,
representationData: representationData, representationData: representationData,
savedRange: null, // range
}; };
}, },
methods: { 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 * @param {string} sceneID 场景 ID
@ -1592,10 +1658,20 @@ export default {
} }
}, },
// //
outsideSelectChange(val) { async outsideSelectChange(val) {
if (val) { if (val) {
this.outsideColumns = []; 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.userList = [];
this.representation = false; 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) { handleKeyDown(e, columnName, rowIndex) {
const editor = this.$refs["contentEditor" + columnName + rowIndex][0]; 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 // token
clearTokenSelection(columnName, rowIndex) { clearTokenSelection(columnName, rowIndex) {
@ -1822,29 +1901,27 @@ export default {
}, },
// //
handleInput(e, columnName, rowIndex) { handleInput(e, columnName, rowIndex) {
// token // this.clearTokenSelection(columnName, rowIndex);
this.clearTokenSelection(columnName, rowIndex); this.saveRange();
// computed
this.$forceUpdate();
}, },
// //
handleEditorClick(e, columnName, rowIndex) { handleEditorClick(e, columnName, rowIndex) {
const editor = this.$refs["contentEditor" + columnName + rowIndex][0]; const editor = this.$refs["contentEditor" + columnName + rowIndex][0];
this.currenrActiveNodeRef = "contentEditor" + columnName + rowIndex; this.currenrActiveNodeRef = "contentEditor" + columnName + rowIndex;
// token // // token
if ( // if (
!e.target.classList.contains("content-token") && // !e.target.classList.contains("content-token") &&
!e.target.closest(".content-token") // !e.target.closest(".content-token")
) { // ) {
this.clearTokenSelection(columnName, rowIndex); // this.clearTokenSelection(columnName, rowIndex);
} // }
// // //
if (e.target === editor || editor.contains(e.target)) { // if (e.target === editor || editor.contains(e.target)) {
editor.focus(); editor.focus();
} this.saveRange();
// }
}, },
// //
handlePaste(e, columnName, rowIndex) { handlePaste(e, columnName, rowIndex) {
@ -1854,7 +1931,6 @@ export default {
// //
handleEditorFocus(e, columnName, rowIndex) { handleEditorFocus(e, columnName, rowIndex) {
const editor = this.$refs["contentEditor" + columnName + rowIndex][0]; const editor = this.$refs["contentEditor" + columnName + rowIndex][0];
// //
if (this.isEmpty(columnName, rowIndex)) { if (this.isEmpty(columnName, rowIndex)) {
setTimeout(() => { setTimeout(() => {
@ -1900,6 +1976,7 @@ export default {
selection.addRange(range); selection.addRange(range);
// //
editor.focus(); editor.focus();
this.saveRange();
}); });
}, },
@ -1925,13 +2002,14 @@ export default {
selection.addRange(range); selection.addRange(range);
// //
editor.focus(); editor.focus();
this.saveRange();
}, },
handleNodeSelected(path) { handleNodeSelected(path) {
this.selectedNode = path; this.selectedNode = path;
this.insertToken(path, "node-reference"); this.insertToken(path, "node-reference");
}, },
handleTagSelected(label) { handleTagSelected(label) {
this.insertToken(label, "node-edit");
}, },
// token // token
insertToken(text, type) { insertToken(text, type) {
@ -1942,46 +2020,64 @@ export default {
// //
editor.focus(); editor.focus();
setTimeout(() => {
const token = this.createTokenElement(text, type); const token = this.createTokenElement(text, type);
const space = document.createTextNode(" ");
// //
const selection = window.getSelection(); const selection = window.getSelection();
if (selection.rangeCount > 0) { let range = this.savedRange?.cloneRange();
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(); range.deleteContents();
// token // token +
range.insertNode(token); const frag = document.createDocumentFragment();
frag.appendChild(token);
frag.appendChild(space);
range.insertNode(frag);
// token //
const space = document.createTextNode(" "); range.setStartAfter(space);
range.setStartAfter(token); range.collapse(true);
range.insertNode(space); selection.removeAllRanges();
selection.addRange(range);
// 使setTimeoutDOM // savedRange
setTimeout(() => { this.savedRange = range.cloneRange();
if (!this.setCursorAfter(space)) {
//
this.setCursorToEnd();
}
}, 10); // DOM
} else {
//
editor.appendChild(token);
const space = document.createTextNode(" ");
editor.appendChild(space);
// 使setTimeoutDOM this.$nextTick(() => {
setTimeout(() => {
if (!this.setCursorAfter(space)) { if (!this.setCursorAfter(space)) {
this.setCursorToEnd(); this.setCursorToEnd();
} }
});
this.saveRange();
}, 10); }, 10);
},
saveRange() {
const selection = window.getSelection();
if (selection.rangeCount > 0) {
this.savedRange = selection.getRangeAt(0).cloneRange();
} }
//
this.$forceUpdate();
}, },
// //
setCursorToEnd() { setCursorToEnd() {
@ -2014,15 +2110,17 @@ export default {
}, },
// token // token
createTokenElement(text, type) { createTokenElement(text, type) {
const token = document.createElement("span"); let token = null;
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);
token = document.createElement("span");
token.contentEditable = false;
token.setAttribute("data-token-text", text);
if (type === "node-reference") { if (type === "node-reference") {
token.className = "content-token token-function";
token.innerHTML = `<i class="el-icon-connection"></i> ${text}`; token.innerHTML = `<i class="el-icon-connection"></i> ${text}`;
} else {
token.className = "content-token token-edit";
token.innerHTML = `${text}`;
} }
return token; return token;
}, },
@ -2047,6 +2145,15 @@ export default {
this.currenrActiveNodeRef = ""; 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); //
}
},
}; };
</script> </script>
@ -2874,9 +2981,9 @@ export default {
user-select: none; user-select: none;
} }
::v-deep .token-function { ::v-deep .token-function {
background: #e0e7ff; background: #ecfdf5;
color: #5b21b6; color: #047857;
border: 1px solid #8b5cf6; border: 1px solid #10b981;
} }
::v-deep .repContainer { ::v-deep .repContainer {
@ -2924,6 +3031,21 @@ export default {
font-size: 13px; font-size: 13px;
margin-left: 10px; 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;
}
</style> </style>