From e9f786bb928e12ddaec9782ed1573d6ba7f1b78d Mon Sep 17 00:00:00 2001 From: weizong song Date: Thu, 8 Jan 2026 10:35:30 +0800 Subject: [PATCH] up --- rebuild.sh | 6 + src/components/BudgetSourcePickerField.vue | 160 ++- src/components/ContractSignField.vue | 553 ++++++++-- src/utils/formBuilder.js | 88 +- src/utils/request.js | 6 +- src/views/flow/create.vue | 3 +- 自定义字段渲染整理.md | 1159 ++++++++++++++++++++ 错误诊断和解决方案.md | 6 + 8 files changed, 1856 insertions(+), 125 deletions(-) create mode 100644 自定义字段渲染整理.md diff --git a/rebuild.sh b/rebuild.sh index 957041b..16b2131 100644 --- a/rebuild.sh +++ b/rebuild.sh @@ -117,3 +117,9 @@ echo "" + + + + + + diff --git a/src/components/BudgetSourcePickerField.vue b/src/components/BudgetSourcePickerField.vue index e53858a..87e9fab 100644 --- a/src/components/BudgetSourcePickerField.vue +++ b/src/components/BudgetSourcePickerField.vue @@ -494,8 +494,17 @@ export default { onDialogOpen() { this.selectionError = ""; this.selectedBudgetIds = []; - // 读取“本次付款金额” - this.totalAmount = this.extractPaymentAmountFromForm(); + // 读取“本次付款金额”(延迟查找,确保 DOM 已渲染) + this.$nextTick(() => { + // 第一次尝试 + this.totalAmount = this.extractPaymentAmountFromForm(); + // 如果没找到,再延迟一次尝试(可能 DOM 还在渲染中) + if (this.totalAmount === 0) { + setTimeout(() => { + this.totalAmount = this.extractPaymentAmountFromForm(); + }, 100); + } + }); this.ensureInit(); }, onDialogClose() { @@ -658,20 +667,145 @@ export default { }, extractPaymentAmountFromForm() { // 从页面 DOM 中模糊匹配 label “本次付款金额”,解析金额(兼容单位后缀) + // 支持多种查找方式:label、placeholder、字段名等 try { + // 方法1:通过 label 查找 const labels = Array.from(document.querySelectorAll(".el-form-item__label")); - const labelEl = labels.find((el) => (el.innerText || "").includes("本次付款金额")); - if (!labelEl) return 0; - const formItem = labelEl.closest(".el-form-item"); - const content = formItem ? formItem.querySelector(".el-form-item__content") : null; - const input = - (content && content.querySelector("input")) || - (content && content.querySelector("textarea")) || - null; - const raw = input ? String(input.value || "") : ""; - const num = parseFloat(raw.replace(/,/g, "").replace(/[^\d.-]/g, "")); - return isNaN(num) ? 0 : num; + let labelEl = labels.find((el) => { + const text = (el.innerText || el.textContent || "").trim(); + return text.includes("本次付款金额") || text.includes("付款金额"); + }); + + if (labelEl) { + const formItem = labelEl.closest(".el-form-item"); + if (formItem) { + const content = formItem.querySelector(".el-form-item__content"); + if (content) { + // 优先查找各种类型的输入框(可编辑状态) + let input = content.querySelector("input") || + content.querySelector("textarea") || + content.querySelector(".el-input__inner") || + content.querySelector("input[type='text']") || + content.querySelector("input[type='number']"); + + if (input) { + const raw = String(input.value || input.getAttribute("value") || ""); + const num = parseFloat(raw.replace(/,/g, "").replace(/[^\d.-]/g, "")); + if (!isNaN(num) && num > 0) { + return num; + } + } + + // 如果没找到输入框,查找展示元素(只读/view 状态) + // 只读字段通常渲染为 span 或其他展示元素 + const displayEl = content.querySelector("span") || + content.querySelector("div") || + content; + + if (displayEl) { + // 获取元素的文本内容(可能是直接文本或子元素的文本) + const raw = displayEl.innerText || displayEl.textContent || displayEl.getAttribute("value") || ""; + const num = parseFloat(raw.replace(/,/g, "").replace(/[^\d.-]/g, "")); + if (!isNaN(num) && num > 0) { + return num; + } + } + } + } + } + + // 方法2:通过 data-field-name 属性查找(如果字段名包含"付款金额"相关关键词) + const formItems = Array.from(document.querySelectorAll(".el-form-item[data-field-name]")); + for (const formItem of formItems) { + const fieldName = formItem.getAttribute("data-field-name") || ""; + const label = formItem.querySelector(".el-form-item__label"); + const labelText = label ? (label.innerText || label.textContent || "").trim() : ""; + + if (fieldName.includes("付款金额") || fieldName.includes("payment_amount") || + labelText.includes("本次付款金额") || labelText.includes("付款金额")) { + const content = formItem.querySelector(".el-form-item__content"); + if (content) { + // 优先查找输入框(可编辑状态) + let input = content.querySelector("input") || + content.querySelector("textarea") || + content.querySelector(".el-input__inner") || + content.querySelector("input[type='text']") || + content.querySelector("input[type='number']"); + + if (input) { + const raw = String(input.value || input.getAttribute("value") || ""); + const num = parseFloat(raw.replace(/,/g, "").replace(/[^\d.-]/g, "")); + if (!isNaN(num) && num > 0) { + return num; + } + } + + // 如果没找到输入框,查找展示元素(只读/view 状态) + const displayEl = content.querySelector("span") || + content.querySelector("div") || + content; + + if (displayEl) { + const raw = displayEl.innerText || displayEl.textContent || displayEl.getAttribute("value") || ""; + const num = parseFloat(raw.replace(/,/g, "").replace(/[^\d.-]/g, "")); + if (!isNaN(num) && num > 0) { + return num; + } + } + } + } + } + + // 方法3:通过 placeholder 查找(可编辑字段) + const inputs = Array.from(document.querySelectorAll("input, textarea, .el-input__inner")); + for (const input of inputs) { + const placeholder = input.getAttribute("placeholder") || ""; + if (placeholder.includes("本次付款金额") || placeholder.includes("付款金额")) { + const raw = String(input.value || input.getAttribute("value") || ""); + const num = parseFloat(raw.replace(/,/g, "").replace(/[^\d.-]/g, "")); + if (!isNaN(num) && num > 0) { + return num; + } + } + } + + // 方法4:直接查找所有包含金额数字的 span/div(只读展示字段) + // 查找所有 form-item,检查 label 是否包含"付款金额",然后提取内容 + const allFormItems = Array.from(document.querySelectorAll(".el-form-item")); + for (const formItem of allFormItems) { + const label = formItem.querySelector(".el-form-item__label"); + const labelText = label ? (label.innerText || label.textContent || "").trim() : ""; + + if (labelText.includes("本次付款金额") || labelText.includes("付款金额")) { + const content = formItem.querySelector(".el-form-item__content"); + if (content) { + // 查找所有可能的展示元素 + const displayEls = content.querySelectorAll("span, div, p"); + for (const el of displayEls) { + const text = (el.innerText || el.textContent || "").trim(); + // 如果文本包含数字(可能是金额) + if (text && /[\d.,]+/.test(text)) { + const num = parseFloat(text.replace(/,/g, "").replace(/[^\d.-]/g, "")); + if (!isNaN(num) && num > 0) { + return num; + } + } + } + // 如果子元素没找到,直接取 content 的文本 + const contentText = (content.innerText || content.textContent || "").trim(); + if (contentText && /[\d.,]+/.test(contentText)) { + const num = parseFloat(contentText.replace(/,/g, "").replace(/[^\d.-]/g, "")); + if (!isNaN(num) && num > 0) { + return num; + } + } + } + } + } + + return 0; } catch (e) { + console.warn("[BudgetSourcePickerField] 提取本次付款金额失败:", e); return 0; } }, diff --git a/src/components/ContractSignField.vue b/src/components/ContractSignField.vue index fc9b37f..1977b80 100644 --- a/src/components/ContractSignField.vue +++ b/src/components/ContractSignField.vue @@ -38,55 +38,52 @@ - + + + - + - + - + - + - + - + - + @@ -94,23 +91,26 @@ - + - - - - - - - + + + + + - + - + - - - - + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + @@ -152,13 +188,14 @@ - - - - - - - + + + @@ -170,39 +207,41 @@ - + - - - - - - + + + - + - + - + - + @@ -231,10 +270,11 @@ 付款计划 -
- 新增计划 -
- + +
+ 新增计划 +
+ - +
+