|
|
@@ -1473,20 +1473,20 @@
|
|
|
|
|
|
<!-- 「其他模板指标项」内容区域 -->
|
|
|
<div v-else class="other-panel">
|
|
|
- <span>版本号:</span>
|
|
|
+ <span>模版:</span>
|
|
|
<el-select
|
|
|
v-model="selectedTemplateId"
|
|
|
multiple
|
|
|
collapse-tags
|
|
|
clearable
|
|
|
filterable
|
|
|
- placeholder="请选择版本号"
|
|
|
+ placeholder="请选择模版"
|
|
|
@change="handleTemplateChange"
|
|
|
>
|
|
|
<el-option
|
|
|
v-for="(item, index) in templateList"
|
|
|
:key="index"
|
|
|
- :label="`${item.versionNo}(${item.surveyTemplateName})`"
|
|
|
+ :label="item.surveyTemplateName"
|
|
|
:value="item.pkVal"
|
|
|
></el-option>
|
|
|
</el-select>
|
|
|
@@ -1624,6 +1624,8 @@
|
|
|
currentEditingRowIndex: -1,
|
|
|
radioType: 'current',
|
|
|
formulaText: 'C1+C2+C3',
|
|
|
+ // 是否为自动拼接的公式文本(用于避免覆盖用户手填)
|
|
|
+ isAutoGeneratedFormula: false,
|
|
|
templateName: '',
|
|
|
templateList: [],
|
|
|
selectedTemplateId: [],
|
|
|
@@ -1815,6 +1817,68 @@
|
|
|
this.isAutoGeneratedFormula = false
|
|
|
},
|
|
|
methods: {
|
|
|
+ /**
|
|
|
+ * 从公式文本中解析出 “模板名.指标编号” 的引用,用于回显勾选。
|
|
|
+ * 支持:TemplateA.C1 + (TemplateB.C2)
|
|
|
+ * 返回:Map<templateName, Set<code>>
|
|
|
+ */
|
|
|
+ parseOtherFormulaSelectionMap(formulaText) {
|
|
|
+ const map = new Map()
|
|
|
+ if (!formulaText || typeof formulaText !== 'string') return map
|
|
|
+
|
|
|
+ // 去掉空格,便于匹配
|
|
|
+ const text = String(formulaText).replace(/\s+/g, '')
|
|
|
+
|
|
|
+ // 模板名可能包含下划线/中文/数字;指标编号通常是字母数字下划线(如 C1、T_01)
|
|
|
+ // 这里尽量宽松:模板名取“非运算符、非括号、非点号”的连续字符
|
|
|
+ const reg = /([^+\-*/()\.]+)\.([A-Za-z0-9_]+)/g
|
|
|
+ let m
|
|
|
+ while ((m = reg.exec(text)) !== null) {
|
|
|
+ const templateName = m[1]
|
|
|
+ const code = m[2]
|
|
|
+ if (!templateName || !code) continue
|
|
|
+ if (!map.has(templateName)) map.set(templateName, new Set())
|
|
|
+ map.get(templateName).add(code)
|
|
|
+ }
|
|
|
+
|
|
|
+ return map
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 其他模板指标项:根据 formulaText 的引用结果,给合并表格数据打勾选回显。
|
|
|
+ * 注意:templateName 可能是中文名或英文名,这里两者都尝试匹配。
|
|
|
+ */
|
|
|
+ applyOtherFormulaSelectionToRows(rows, selectedTemplate) {
|
|
|
+ if (!Array.isArray(rows) || rows.length === 0) return
|
|
|
+ const selectionMap = this.parseOtherFormulaSelectionMap(
|
|
|
+ this.formulaText
|
|
|
+ )
|
|
|
+ if (!selectionMap || selectionMap.size === 0) return
|
|
|
+
|
|
|
+ const possibleTemplateNames = [
|
|
|
+ selectedTemplate?.surveyTemplateNameYw,
|
|
|
+ selectedTemplate?.surveyTemplateName,
|
|
|
+ ].filter(Boolean)
|
|
|
+
|
|
|
+ // 把可能的模板名映射到同一个 codeSet(只要有一个命中即可)
|
|
|
+ let codeSet = null
|
|
|
+ for (const name of possibleTemplateNames) {
|
|
|
+ if (selectionMap.has(name)) {
|
|
|
+ codeSet = selectionMap.get(name)
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!codeSet || codeSet.size === 0) return
|
|
|
+
|
|
|
+ rows.forEach((row) => {
|
|
|
+ const codeKey = String(row.cellCode || row.code || '')
|
|
|
+ const shouldCheck = codeKey ? codeSet.has(codeKey) : false
|
|
|
+ this.$set(row, 'checked', shouldCheck)
|
|
|
+ if (shouldCheck) {
|
|
|
+ this.formatRowCode(row)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
async loadDictTypeList() {
|
|
|
try {
|
|
|
const res = await getDictTypList()
|
|
|
@@ -1887,12 +1951,92 @@
|
|
|
// 切换选中状态
|
|
|
this.toggleRowSelection(row)
|
|
|
},
|
|
|
+ /**
|
|
|
+ * 往公式里追加一个 token(如 TemplateA.C1)。
|
|
|
+ * 规则:
|
|
|
+ * - 空公式:直接赋值
|
|
|
+ * - 非空:若末尾不是运算符/左括号,则用 + 连接
|
|
|
+ * - 已存在:不重复追加
|
|
|
+ */
|
|
|
+ appendFormulaToken(token) {
|
|
|
+ if (!token) return
|
|
|
+ const t = String(token).trim()
|
|
|
+ if (!t) return
|
|
|
+
|
|
|
+ const cur = String(this.formulaText || '').trim()
|
|
|
+ if (!cur) {
|
|
|
+ this.formulaText = t
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 已存在则不重复追加(简单包含判断,够用;如需更严格可再增强)
|
|
|
+ if (cur.includes(t)) return
|
|
|
+
|
|
|
+ // 如果末尾是操作符或左括号,直接拼接;否则补一个+
|
|
|
+ const lastChar = cur.slice(-1)
|
|
|
+ const needPlus = !['+', '-', '*', '/', '('].includes(lastChar)
|
|
|
+ this.formulaText = needPlus ? `${cur}+${t}` : `${cur}${t}`
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 从公式里移除一个 token(如 TemplateA.C1),并尽量处理前后连接符。
|
|
|
+ */
|
|
|
+ removeFormulaToken(token) {
|
|
|
+ if (!token) return
|
|
|
+ const t = String(token).trim()
|
|
|
+ if (!t) return
|
|
|
+
|
|
|
+ let cur = String(this.formulaText || '')
|
|
|
+ if (!cur) return
|
|
|
+
|
|
|
+ // 先去空格,统一处理
|
|
|
+ cur = cur.replace(/\s+/g, '')
|
|
|
+
|
|
|
+ // 处理多种位置:
|
|
|
+ // 1) +token 2) token+ 3) token(唯一)
|
|
|
+ const escaped = t.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
|
+ const patterns = [
|
|
|
+ new RegExp(`\\+${escaped}`, 'g'),
|
|
|
+ new RegExp(`${escaped}\\+`, 'g'),
|
|
|
+ new RegExp(`${escaped}`, 'g'),
|
|
|
+ ]
|
|
|
+
|
|
|
+ patterns.forEach((p) => {
|
|
|
+ cur = cur.replace(p, '')
|
|
|
+ })
|
|
|
+
|
|
|
+ // 清理可能出现的重复操作符,如:C1++C2、开头+、结尾+
|
|
|
+ cur = cur
|
|
|
+ .replace(/\+{2,}/g, '+')
|
|
|
+ .replace(/^\+/, '')
|
|
|
+ .replace(/\+$/, '')
|
|
|
+
|
|
|
+ this.formulaText = cur
|
|
|
+ },
|
|
|
toggleRowSelection(row) {
|
|
|
// 切换选中状态(用于行点击)
|
|
|
this.$set(row, 'checked', !row.checked)
|
|
|
|
|
|
if (row.checked) {
|
|
|
this.formatRowCode(row)
|
|
|
+ if (this.radioType === 'other') {
|
|
|
+ // 用户通过表格追加/删除时,视为手动编辑公式,不再自动覆盖
|
|
|
+ this.isAutoGeneratedFormula = false
|
|
|
+ this.appendFormulaToken(row.formattedCode)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (this.radioType === 'other') {
|
|
|
+ this.isAutoGeneratedFormula = false
|
|
|
+ // 取消勾选时,从公式中移除
|
|
|
+ const token = row.formattedCode
|
|
|
+ ? row.formattedCode
|
|
|
+ : (() => {
|
|
|
+ const templateName =
|
|
|
+ row.templateNameYw || row.templateName || ''
|
|
|
+ const code = row.code || row.cellCode || ''
|
|
|
+ return templateName ? `${templateName}.${code}` : code
|
|
|
+ })()
|
|
|
+ this.removeFormulaToken(token)
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
this.updateSelectedIndicatorCodes()
|
|
|
@@ -1908,6 +2052,24 @@
|
|
|
|
|
|
if (row.checked) {
|
|
|
this.formatRowCode(row)
|
|
|
+ if (this.radioType === 'other') {
|
|
|
+ // 用户通过表格追加/删除时,视为手动编辑公式,不再自动覆盖
|
|
|
+ this.isAutoGeneratedFormula = false
|
|
|
+ this.appendFormulaToken(row.formattedCode)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (this.radioType === 'other') {
|
|
|
+ this.isAutoGeneratedFormula = false
|
|
|
+ const token = row.formattedCode
|
|
|
+ ? row.formattedCode
|
|
|
+ : (() => {
|
|
|
+ const templateName =
|
|
|
+ row.templateNameYw || row.templateName || ''
|
|
|
+ const code = row.code || row.cellCode || ''
|
|
|
+ return templateName ? `${templateName}.${code}` : code
|
|
|
+ })()
|
|
|
+ this.removeFormulaToken(token)
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
this.updateSelectedIndicatorCodes()
|
|
|
@@ -2079,6 +2241,13 @@
|
|
|
headers = fixedTablesTitle
|
|
|
}
|
|
|
|
|
|
+ // 优先:如果当前是“其他模版指标项”,并且公式中有引用,则按公式回显
|
|
|
+ // 兜底:没有公式引用时,使用缓存 selectedIndicatorsPerTemplate 回显
|
|
|
+ const shouldUseFormulaSelection =
|
|
|
+ this.radioType === 'other' &&
|
|
|
+ typeof this.formulaText === 'string' &&
|
|
|
+ this.formulaText.trim()
|
|
|
+
|
|
|
const cachedSelectedList =
|
|
|
this.selectedIndicatorsPerTemplate[templateId] || []
|
|
|
const cachedCodeSet = new Set(
|
|
|
@@ -2090,9 +2259,15 @@
|
|
|
selectedTemplate.surveyTemplateName ||
|
|
|
''
|
|
|
|
|
|
+ // 先组装该模板的行
|
|
|
+ const currentTemplateRows = []
|
|
|
itemList.forEach((item) => {
|
|
|
const codeKey = String(item.cellCode || item.code || '')
|
|
|
- const checked = codeKey ? cachedCodeSet.has(codeKey) : false
|
|
|
+ const checked = shouldUseFormulaSelection
|
|
|
+ ? false
|
|
|
+ : codeKey
|
|
|
+ ? cachedCodeSet.has(codeKey)
|
|
|
+ : false
|
|
|
|
|
|
const row = {
|
|
|
...item,
|
|
|
@@ -2111,12 +2286,23 @@
|
|
|
row.fixedValues[title.rkey] = item[title.rkey] || ''
|
|
|
})
|
|
|
|
|
|
- if (checked) {
|
|
|
- this.formatRowCode(row)
|
|
|
- }
|
|
|
-
|
|
|
- mergedRows.push(row)
|
|
|
+ currentTemplateRows.push(row)
|
|
|
})
|
|
|
+
|
|
|
+ // 如果需要按公式回显:对该模板行集做一次勾选匹配
|
|
|
+ if (shouldUseFormulaSelection) {
|
|
|
+ this.applyOtherFormulaSelectionToRows(
|
|
|
+ currentTemplateRows,
|
|
|
+ selectedTemplate
|
|
|
+ )
|
|
|
+ } else {
|
|
|
+ // 缓存回显时:给已勾选的行补 formattedCode/jsonStr
|
|
|
+ currentTemplateRows.forEach((row) => {
|
|
|
+ if (row.checked) this.formatRowCode(row)
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ mergedRows.push(...currentTemplateRows)
|
|
|
})
|
|
|
|
|
|
this.indicatorTableHeaders = headers
|
|
|
@@ -2208,6 +2394,13 @@
|
|
|
|
|
|
const jsonstr = JSON.stringify(jsonStrArray)
|
|
|
|
|
|
+ // calculationTemplateId:选中的模版id拼接(逗号分隔)
|
|
|
+ const calculationTemplateId = Array.isArray(this.selectedTemplateId)
|
|
|
+ ? this.selectedTemplateId
|
|
|
+ .filter((x) => x !== undefined && x !== null && x !== '')
|
|
|
+ .join(',')
|
|
|
+ : ''
|
|
|
+
|
|
|
// 更新当前编辑行的计算公式值
|
|
|
if (this.currentEditingRow) {
|
|
|
this.$set(
|
|
|
@@ -2218,6 +2411,13 @@
|
|
|
|
|
|
this.$set(this.currentEditingRow, 'jsonstr', jsonstr)
|
|
|
|
|
|
+ // 新增:保存选中模版id拼接
|
|
|
+ this.$set(
|
|
|
+ this.currentEditingRow,
|
|
|
+ 'calculationTemplateId',
|
|
|
+ calculationTemplateId
|
|
|
+ )
|
|
|
+
|
|
|
// 同步缓存弹窗状态,便于下次打开回显(包含当前/其他、版本号、勾选)
|
|
|
this.$set(this.currentEditingRow, '_calcDialogState', {
|
|
|
radioType: this.radioType,
|
|
|
@@ -2233,6 +2433,7 @@
|
|
|
console.log('点击了确定,获取到的数据:', {
|
|
|
...result,
|
|
|
jsonstr: jsonstr,
|
|
|
+ calculationTemplateId,
|
|
|
})
|
|
|
|
|
|
// 清空当前操作的状态
|
|
|
@@ -2360,6 +2561,7 @@
|
|
|
orderNum: this.contentEditForm.fixedTable.fixedTables.length + 1,
|
|
|
cellCode: '',
|
|
|
calculationFormula: '',
|
|
|
+ calculationTemplateId: '',
|
|
|
unit: '',
|
|
|
tabtype: this.templateType,
|
|
|
surveyTemplateId: this.surveyTemplateId,
|
|
|
@@ -2731,6 +2933,7 @@
|
|
|
orderNum: maxFixedOrderNum + 1,
|
|
|
cellCode: '',
|
|
|
calculationFormula: '',
|
|
|
+ calculationTemplateId: '',
|
|
|
unit: '',
|
|
|
tabtype: this.templateType,
|
|
|
surveyTemplateId: this.surveyTemplateId,
|
|
|
@@ -3677,6 +3880,7 @@
|
|
|
rowid: node.rowid || null,
|
|
|
// 添加计算公式相关字段
|
|
|
calculationFormula: node.calculationFormula || null,
|
|
|
+ calculationTemplateId: node.calculationTemplateId || null,
|
|
|
jsonstr: node.jsonstr || null,
|
|
|
orderNum:
|
|
|
typeof node.orderNum === 'number'
|
|
|
@@ -3702,6 +3906,7 @@
|
|
|
key !== 'rowid' &&
|
|
|
key !== 'jsonstr' &&
|
|
|
key !== 'calculationFormula' &&
|
|
|
+ key !== 'calculationTemplateId' &&
|
|
|
key !== 'children' // 排除children字段
|
|
|
) {
|
|
|
newItem[key] = node[key]
|
|
|
@@ -3825,6 +4030,7 @@
|
|
|
rowid: node.rowid || null,
|
|
|
// 添加计算公式相关字段
|
|
|
calculationFormula: node.calculationFormula || null,
|
|
|
+ calculationTemplateId: node.calculationTemplateId || null,
|
|
|
jsonstr: node.jsonstr || null,
|
|
|
orderNum:
|
|
|
typeof node.orderNum === 'number'
|
|
|
@@ -3845,6 +4051,7 @@
|
|
|
key !== 'rowid' &&
|
|
|
key !== 'jsonstr' &&
|
|
|
key !== 'calculationFormula' &&
|
|
|
+ key !== 'calculationTemplateId' &&
|
|
|
key !== 'children' // 排除children字段
|
|
|
) {
|
|
|
newItem[key] = node[key]
|
|
|
@@ -4045,6 +4252,7 @@
|
|
|
versionId: item.versionId,
|
|
|
cellCode: item.cellCode || '',
|
|
|
calculationFormula: item.calculationFormula || '',
|
|
|
+ calculationTemplateId: item.calculationTemplateId || '',
|
|
|
unit: item.unit || '',
|
|
|
fixedValues: {},
|
|
|
itemId: item.id || null,
|
|
|
@@ -4152,6 +4360,8 @@
|
|
|
isChild: isSubItem,
|
|
|
isSubItem: isSubItem,
|
|
|
rowid: item.rowid || this.generateUUID(),
|
|
|
+ calculationFormula: item.calculationFormula || '',
|
|
|
+ calculationTemplateId: item.calculationTemplateId || '',
|
|
|
jsonstr: item.jsonstr || null,
|
|
|
children: [], // 添加children数组用于树形结构
|
|
|
}
|