element-plus table合并列、合计行、表格填报添加验证

发布于:2025-07-01 ⋅ 阅读:(21) ⋅ 点赞:(0)

1 说明

1、table 合并列:el-table 添加 span-method 方法,方法(mergeCells )内可以写死指定的合并列

2、table 添加合计行:el-table 添加 :summary-method 方法,方法(getSummaries )内可以写死求和列
,这里更推荐修改方法:使用  "decimal.js" 计算,因为js 小数计算不精准

3、表格填报添加验证:
1)添加el-from 包裹表格,并且添加model、rules,注意 el-from、table 绑定的数据要有关系;
2)el-form-item 绑定 :prop="`itemList.${scope.$index}.planAmount`" :rules="rulesTab.planAmount">
3)添加 style 美化样式,见模板 ,美化后的样式如下图

在这里插入图片描述

2 方法模板

<template>
<el-row>
	<el-col :span="24" class="blocker contenter">
	  <div class="d-flex" style="margin-bottom: 10px;">
		<div style="font-weight: bold;">列表</div>
		<div style="margin-left: auto;">
		  <el-button class="tool-btn" type="primary" icon="Edit" @click="submitForm">保存</el-button>
		</div>
	  </div>
	  <el-form ref="tableDataFromRef" :model="formData" :rules="rulesTab" class="tableDataFrom">
		<el-table
			:data="formData.itemList"
			:span-method="mergeCells"
			:summary-method="getSummaries"
			border
			height="66vh"
			style="width: 100%; margin-top: 20px"
			:row-style="{'height':'40px','font-size':'14px'}"
			:cell-style="{'padding':'0 5px'}"
		>
		  <el-table-column type="index" label="序号" width="70" align="center"/>
		  <el-table-column prop="feeLv2Name" label="费用项目" width="170" align="center"/>
		  <el-table-column :label="`${queryParamFormData.planMonth?.substring(5,8)}月`" align="center">
			<el-table-column prop="planAmount" label="计划金额" width="130" align="right">
			  <template #default="scope">
				<el-form-item :prop="`itemList.${scope.$index}.planAmount`" :rules="rulesTab.planAmount">
				  <el-input-number v-model="scope.row.planAmount" precision="2" :controls="false"
								   :disabled="!isEditing"
								   style="width: 115px"/>
				</el-form-item>
			  </template>
			</el-table-column>
		  </el-table-column>
		</el-table>
	  </el-form>
	</el-col>
</el-row>

</template>
<script setup>
import {ref, onMounted, watch} from 'vue'
import {ElMessage, ElMessageBox} from "element-plus";

......

const tableDataFromRef = ref()
const loading = ref(false)

// 是否正在编辑
const isEditing = ref(false)

// 表单信息
const formData = ref({id: null, itemList: [], status: null})

// 表单的验证规则
const rulesTab = ref({
  planAmount: [
    {required: true, message: "计划金额不能为空", trigger: "blur"}
  ]
})

// 合并单元格
const mergeCells = ({row, column, rowIndex}) => {
  const mergeKeys = ['feeLv1Name', 'feeLv2Name', 'feeLv3Name']
  const prop = column.property
  const data = formData.value.itemList

  if (!mergeKeys.includes(prop)) {
    return {rowspan: 1, colspan: 1}
  }

  // 不是第0行且和上一行值一样,则隐藏
  if (rowIndex > 0 && data[rowIndex][prop] === data[rowIndex - 1][prop]) {
    return {rowspan: 0, colspan: 0}
  }

  // 统计与当前行值相同的后续行数(仅限相邻)
  let rowspan = 1
  for (let i = rowIndex + 1; i < data.length; i++) {
    if (data[i][prop] === row[prop]) {
      rowspan++
    } else {
      break
    }
  }

  return {rowspan, colspan: 1}
}

// 添加合计行
const getSummaries = ({columns, data}) => {
  const sums = []
  const sumKeys = ['planAmount']  // 指定需要求和的字段

  columns.forEach((column, index) => {
    if (index === 0) {
      sums[index] = h('div', {}, ['合计'])
      return
    }

    const property = column.property
    if (!sumKeys.includes(property)) {
      sums[index] = ''  // 非指定列不显示或写 'N/A'
      return
    }

    const values = data.map(item => Number(item[property]))
    if (!values.every(value => Number.isNaN(value))) {
      const total = values.reduce((sum, val) => {
        return Number.isNaN(val) ? sum : sum + val
      }, 0)
      sums[index] = `${total.toFixed(2)}`
    } else {
      sums[index] = 'N/A'
    }
  })
  return sums
}

// 保存行信息
const submitForm = async () => {
  await tableDataFromRef.value.validate().then(() => {
    ...保存方法
  }).catch(error => {
    ElMessage.warning("请不要填写空值!");
  })
}

</script>
<style lang="scss" scoped>
// 调整表格中的样式,让提示美观
.tableDataFrom {
  .el-form-item {
    margin-bottom: 0;

    :deep(.el-input__wrapper) {
      background: transparent;
      padding: 0 5px;
    }

    :deep(.el-form-item__error) {
      z-index: -1;
      top: 0;
    }
  }
}
</style>

网站公告

今日签到

点亮在社区的每一天
去签到