|
|
@@ -1364,7 +1364,11 @@
|
|
|
:before-close="handleDialogClose"
|
|
|
>
|
|
|
<!-- 单选按钮组:切换“当前指标项”/“其他模板指标项” -->
|
|
|
- <el-radio-group v-model="radioType">
|
|
|
+ <el-radio-group
|
|
|
+ v-model="radioType"
|
|
|
+ class="mb20"
|
|
|
+ @change="handleRadioChange"
|
|
|
+ >
|
|
|
<el-radio label="current">当前指标项</el-radio>
|
|
|
<el-radio label="other">其他模板指标项</el-radio>
|
|
|
</el-radio-group>
|
|
|
@@ -1381,15 +1385,16 @@
|
|
|
|
|
|
<!-- 「其他模板指标项」内容区域 -->
|
|
|
<div v-else class="other-panel">
|
|
|
+ <span>版本号:</span>
|
|
|
<el-select
|
|
|
v-model="selectedTemplateId"
|
|
|
- placeholder="请选择模板"
|
|
|
+ placeholder="请选择版本号"
|
|
|
@change="handleTemplateChange"
|
|
|
>
|
|
|
<el-option
|
|
|
v-for="(item, index) in templateList"
|
|
|
:key="index"
|
|
|
- :label="item.surveyTemplateName"
|
|
|
+ :label="item.versionNo"
|
|
|
:value="item.pkVal"
|
|
|
></el-option>
|
|
|
</el-select>
|
|
|
@@ -1411,8 +1416,25 @@
|
|
|
></el-checkbox>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column prop="code" label="指标编号"></el-table-column>
|
|
|
- <el-table-column prop="name" label="项目名称"></el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ label="指标编号"
|
|
|
+ prop="cellCode"
|
|
|
+ align="center"
|
|
|
+ ></el-table-column>
|
|
|
+ <!--循环表头 -->
|
|
|
+ <el-table-column
|
|
|
+ v-for="(item, index) in indicatorTableHeaders"
|
|
|
+ :key="index"
|
|
|
+ :label="item.rkey"
|
|
|
+ align="center"
|
|
|
+ show-overflow-tooltip
|
|
|
+ >
|
|
|
+ <template slot-scope="scope">
|
|
|
+ {{
|
|
|
+ scope.row.fixedValues ? scope.row.fixedValues[item.rkey] : ''
|
|
|
+ }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
</el-table>
|
|
|
<el-input
|
|
|
v-model="formulaText"
|
|
|
@@ -1455,6 +1477,7 @@
|
|
|
import {
|
|
|
listByTemplateIdAndVersion,
|
|
|
getCellCodesByTemplateId,
|
|
|
+ listByCurrentTemplateId,
|
|
|
} from '@/api/costSurveyFdTemplateItems'
|
|
|
import {
|
|
|
addSurveyFdTemplateVersion,
|
|
|
@@ -1766,6 +1789,7 @@
|
|
|
// pageNum: this.pagination.currentPage,
|
|
|
// pageSize: this.pagination.pageSize,
|
|
|
}
|
|
|
+ console.log('params', params)
|
|
|
|
|
|
// 根据财务数据表ID获取所有版本数据
|
|
|
getSurveyFdVersionsByTemplateId(params)
|
|
|
@@ -1791,7 +1815,12 @@
|
|
|
|
|
|
handleRowClick(row, column, event) {
|
|
|
if (column && column.property !== 'checked') {
|
|
|
- this.toggleRowSelection(row)
|
|
|
+ if (row.cellCode == '') {
|
|
|
+ this.$set(row, 'checked', faslse)
|
|
|
+ return
|
|
|
+ } else if (row.cellCode) {
|
|
|
+ this.toggleRowSelection(row)
|
|
|
+ }
|
|
|
}
|
|
|
},
|
|
|
toggleRowSelection(row) {
|
|
|
@@ -1807,15 +1836,20 @@
|
|
|
this.$forceUpdate()
|
|
|
},
|
|
|
handleCheckboxChange(row) {
|
|
|
- this.$set(row, 'checked', !row.checked)
|
|
|
+ if (row.cellCode == '') {
|
|
|
+ this.$set(row, 'checked', faslse)
|
|
|
+ return
|
|
|
+ } else if (row.cellCode) {
|
|
|
+ this.$set(row, 'checked', !row.checked)
|
|
|
|
|
|
- if (row.checked) {
|
|
|
- this.formatRowCode(row)
|
|
|
- }
|
|
|
+ if (row.checked) {
|
|
|
+ this.formatRowCode(row)
|
|
|
+ }
|
|
|
|
|
|
- this.updateSelectedIndicatorCodes()
|
|
|
+ this.updateSelectedIndicatorCodes()
|
|
|
|
|
|
- this.$forceUpdate()
|
|
|
+ this.$forceUpdate()
|
|
|
+ }
|
|
|
},
|
|
|
updateSelectedIndicatorCodes() {
|
|
|
// 获取当前选中的行
|
|
|
@@ -1888,9 +1922,22 @@
|
|
|
},
|
|
|
|
|
|
getListFixedEnabled() {
|
|
|
- getListFixedEnabled().then((res) => {
|
|
|
- this.templateList = res.value
|
|
|
- })
|
|
|
+ const params = {
|
|
|
+ surveyTemplateId: this.surveyTemplateId,
|
|
|
+ status: '0',
|
|
|
+ // pageNum: this.pagination.currentPage,
|
|
|
+ // pageSize: this.pagination.pageSize,
|
|
|
+ }
|
|
|
+ getSurveyFdVersionsByTemplateId(params)
|
|
|
+ .then((response) => {
|
|
|
+ this.templateList = response.value || []
|
|
|
+ })
|
|
|
+ .catch((error) => {
|
|
|
+ console.error('查询失败:', error)
|
|
|
+ })
|
|
|
+ // getListFixedEnabled().then((res) => {
|
|
|
+ // this.templateList = res.value
|
|
|
+ // })
|
|
|
},
|
|
|
// 处理模板选择变化
|
|
|
handleTemplateChange(templateId) {
|
|
|
@@ -1901,7 +1948,33 @@
|
|
|
)
|
|
|
|
|
|
if (selectedTemplate && selectedTemplate.surveyTemplateId) {
|
|
|
- this.getCellCodesByTemplateId(selectedTemplate.surveyTemplateId)
|
|
|
+ // this.getCellCodesByTemplateId(selectedTemplate.surveyTemplateId)
|
|
|
+ listByCurrentTemplateId({
|
|
|
+ surveyTemplateId: selectedTemplate.surveyTemplateId,
|
|
|
+ }).then((responseData) => {
|
|
|
+ //解析并显示数据
|
|
|
+ if (responseData.value && responseData.value.itemlist) {
|
|
|
+ const itemList = responseData.value.itemlist
|
|
|
+ let fixedTablesTitle = this.stringToObjects(
|
|
|
+ responseData.value.fixedFields || ''
|
|
|
+ )
|
|
|
+ this.indicatorTableHeaders = fixedTablesTitle
|
|
|
+ // 遍历itemList,为每个项目创建一行数据
|
|
|
+ itemList.forEach((item, index) => {
|
|
|
+ const newRow = {
|
|
|
+ ...item,
|
|
|
+ checked: false,
|
|
|
+ cellCode: item.cellCode || '',
|
|
|
+ fixedValues: {},
|
|
|
+ }
|
|
|
+ // 初始化fixedValues并填充实际值
|
|
|
+ fixedTablesTitle.forEach((title) => {
|
|
|
+ newRow.fixedValues[title.rkey] = item[title.rkey] || ''
|
|
|
+ })
|
|
|
+ this.indicatorTableData.push(newRow)
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
} else {
|
|
|
this.indicatorTableData = []
|
|
|
}
|
|
|
@@ -1933,6 +2006,9 @@
|
|
|
this.selectedIndicatorsPerTemplate = {}
|
|
|
done()
|
|
|
},
|
|
|
+ handleRadioChange(value) {
|
|
|
+ this.formulaText = ''
|
|
|
+ },
|
|
|
handleConfirm() {
|
|
|
const result = {
|
|
|
type: this.radioType,
|
|
|
@@ -1940,6 +2016,22 @@
|
|
|
selectedTemplate: this.selectedTemplateId,
|
|
|
selectedItems: this.indicatorTableData.filter((item) => item.checked),
|
|
|
}
|
|
|
+ let _data = []
|
|
|
+ if (this.radioType == 'current') {
|
|
|
+ _data = this.contentEditForm.fixedTable.fixedTables
|
|
|
+ .filter((item) => item.cellCode)
|
|
|
+ .map((item) => item.cellCode)
|
|
|
+ } else if (this.radioType == 'other') {
|
|
|
+ _data = this.indicatorTableData
|
|
|
+ .filter((item) => item.cellCode)
|
|
|
+ .map((item) => item.cellCode)
|
|
|
+ }
|
|
|
+ if (!this.validateFormula(this.formulaText, _data).valid) {
|
|
|
+ this.$message.error(
|
|
|
+ this.validateFormula(this.formulaText, _data).errorMsg
|
|
|
+ )
|
|
|
+ return
|
|
|
+ }
|
|
|
|
|
|
const jsonStrArray = this.indicatorTableData
|
|
|
.filter((item) => item.checked)
|
|
|
@@ -1958,6 +2050,12 @@
|
|
|
|
|
|
const jsonstr = JSON.stringify(jsonStrArray)
|
|
|
|
|
|
+ // 检查是否有选中的有效行,如果没有则禁止下一步操作
|
|
|
+ if (jsonStrArray.length === 0) {
|
|
|
+ this.$message.error('请至少选择一个有指标编号的数据行!')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
// 更新当前编辑行的计算公式值
|
|
|
if (this.currentEditingRow) {
|
|
|
this.$set(
|
|
|
@@ -1984,6 +2082,129 @@
|
|
|
this.indicatorTableData = []
|
|
|
this.selectedIndicatorsPerTemplate = {} // 清空模板选中记录
|
|
|
},
|
|
|
+ // 公式验证函数
|
|
|
+ validateFormula(formula, data) {
|
|
|
+ if (!formula || typeof formula !== 'string') {
|
|
|
+ return { valid: false, errorMsg: '公式不能为空' }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 定义有效的操作符
|
|
|
+ const operators = ['+', '-', '*', '/', '(', ')']
|
|
|
+
|
|
|
+ // 检查是否包含至少一个操作符
|
|
|
+ const hasOperator = operators.some((operator) =>
|
|
|
+ formula.includes(operator)
|
|
|
+ )
|
|
|
+ if (!hasOperator) {
|
|
|
+ return { valid: false, errorMsg: '公式必须包含操作符' }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查值是否在data中存在
|
|
|
+ function checkValueInData(value, data) {
|
|
|
+ if (!data) return false
|
|
|
+
|
|
|
+ if (Array.isArray(data)) {
|
|
|
+ return data.includes(value)
|
|
|
+ } else if (typeof data === 'object') {
|
|
|
+ return Object.values(data).includes(value)
|
|
|
+ }
|
|
|
+ return data === value
|
|
|
+ }
|
|
|
+
|
|
|
+ // 提取公式中的变量/值
|
|
|
+ function extractValues(formulaStr) {
|
|
|
+ // 改进实现:支持形如"CeShi3.C2"的格式,提取点后面的部分作为变量,同时保留普通变量
|
|
|
+ const result = new Set()
|
|
|
+
|
|
|
+ // 1. 首先提取带点格式中的变量部分(如CeShi3.C2中的C2)
|
|
|
+ const dotRegex = /[A-Za-z0-9]+\.([A-Za-z0-9]+)/g
|
|
|
+ let dotMatch
|
|
|
+ while ((dotMatch = dotRegex.exec(formulaStr)) !== null) {
|
|
|
+ result.add(dotMatch[1]) // 提取点后面的部分作为变量
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 然后提取普通变量(C3等),但排除已经从带点格式中提取的部分
|
|
|
+ // 移除所有带点的部分,然后提取剩余的变量
|
|
|
+ const remainingFormula = formulaStr.replace(
|
|
|
+ /[A-Za-z0-9]+\.[A-Za-z0-9]+/g,
|
|
|
+ ''
|
|
|
+ )
|
|
|
+ const normalRegex = /[A-Za-z0-9]+/g
|
|
|
+ let normalMatch
|
|
|
+ while ((normalMatch = normalRegex.exec(remainingFormula)) !== null) {
|
|
|
+ // 跳过纯数字
|
|
|
+ if (
|
|
|
+ !isNaN(Number(normalMatch[0])) &&
|
|
|
+ Number(normalMatch[0]).toString() === normalMatch[0]
|
|
|
+ ) {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ result.add(normalMatch[0])
|
|
|
+ }
|
|
|
+
|
|
|
+ return Array.from(result)
|
|
|
+ }
|
|
|
+
|
|
|
+ function checkOperatorContext(formulaStr, data) {
|
|
|
+ for (let i = 0; i < formulaStr.length; i++) {
|
|
|
+ const char = formulaStr[i]
|
|
|
+ // 跳过括号
|
|
|
+ if (char === '(' || char === ')') continue
|
|
|
+
|
|
|
+ // 检查操作符
|
|
|
+ if (operators.includes(char)) {
|
|
|
+ // 检查操作符前是否有值(开头或不是操作符和左括号)
|
|
|
+ if (
|
|
|
+ i === 0 ||
|
|
|
+ (operators.includes(formulaStr[i - 1]) &&
|
|
|
+ formulaStr[i - 1] !== ')') ||
|
|
|
+ formulaStr[i - 1] === '('
|
|
|
+ ) {
|
|
|
+ return {
|
|
|
+ valid: false,
|
|
|
+ errorMsg: `位置 ${i + 1} 的操作符 '${char}' 前缺少值`,
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查操作符后是否有值(结尾或不是操作符和右括号)
|
|
|
+ if (
|
|
|
+ i === formulaStr.length - 1 ||
|
|
|
+ (operators.includes(formulaStr[i + 1]) &&
|
|
|
+ formulaStr[i + 1] !== '(') ||
|
|
|
+ formulaStr[i + 1] === ')'
|
|
|
+ ) {
|
|
|
+ return {
|
|
|
+ valid: false,
|
|
|
+ errorMsg: `位置 ${i + 1} 的操作符 '${char}' 后缺少值`,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证通过后,检查公式中的值是否都在data中存在
|
|
|
+ if (data) {
|
|
|
+ const values = extractValues(formulaStr)
|
|
|
+ for (const value of values) {
|
|
|
+ // 跳过纯数字(假设有值不在data中)
|
|
|
+ if (!isNaN(Number(value)) && Number(value).toString() === value) {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!checkValueInData(value, data)) {
|
|
|
+ return {
|
|
|
+ valid: false,
|
|
|
+ errorMsg: `变量 '${value}' 在数据中不存在`,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return { valid: true }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 执行验证
|
|
|
+ return checkOperatorContext(formula, data)
|
|
|
+ },
|
|
|
// 获取单元格代码
|
|
|
getCellCodesByTemplateId(surveyTemplateId) {
|
|
|
getCellCodesByTemplateId(surveyTemplateId)
|
|
|
@@ -2607,7 +2828,7 @@
|
|
|
row.status = '-1'
|
|
|
putSurveyFdTemplatePublishVersion(row).then((res) => {
|
|
|
if (res.code === 200) {
|
|
|
- this.$message.success(`停用成功`)
|
|
|
+ this.$message.success(`${action}成功`)
|
|
|
this.handleSearch()
|
|
|
}
|
|
|
})
|