element ui 表格動態(tài)列,單行合并同時可行內(nèi)編輯

效果如下:


image.png

image.png

版本信息如下:

"vue": "^2.5.2", "element-ui": "^2.7.2",

代碼如下:

<!--表格行合并-->
<template>
  <div style="margin: 20px">
    <div style="margin: 20px 0;text-align: right;">
      <el-button type="primary" @click="logTableData">打印表格數(shù)據(jù)</el-button>
    </div>
    <el-table
      v-loading="tableLoading"
      :data="tableData"
      :span-method="spanMethod"
      :header-row-style="headerRowStyle"
      style="width: 100%">

      <el-table-column
        align="center"
        v-for="(col,colIndex) in tableHeader"
        :key="`col-${colIndex}`"
        :prop="col.prop"
        :min-width="col.width || 80"
        :label="col.label">
        <template slot-scope="{row, $index}">
          <el-input v-if="!col.noEdit && row._edit" class="inputNumber" :placeholder="`請輸入${col.label}`"
                    v-model="row[col.prop]"/>
          <span v-else>{{ row[col.prop] }}</span>
        </template>
      </el-table-column>

      <el-table-column align="center" label="配比">
        <el-table-column label="" align="center" v-for="rateColIndex in maxTableColLength" :key="`rate-${rateColIndex}`"
                         :min-width="80">
          <template slot-scope="{row, $index}">


            <!--                第一行-->
            <template v-if="row.rowSpan">
              <span v-if="rateColIndex <= row.list.length">{{ row.list[rateColIndex - 1].name }}</span>
            </template>

            <!--                第二行,操作的也是上一行的數(shù)據(jù)-->
            <!--              有這項的才可編輯-->
            <template v-else-if="rateColIndex <= tableData[$index-1].list.length">

              <el-input class="inputNumber" type="number" v-if="tableData[$index-1]._edit" placeholder="請輸入"
                        v-model="tableData[$index-1].list[rateColIndex-1].rate"/>
              <span v-else>{{ valFixed(tableData[$index-1].list[rateColIndex - 1].rate, 2) }}</span>

            </template>

          </template>
        </el-table-column>
      </el-table-column>

      <el-table-column
        fixed="right"
        align="center"
        label="操作"
        width="120">
        <template slot-scope="{row,$index}">
          <template v-if="!row._edit">
            <el-button @click="rowEdit(row, $index)" type="text">修改</el-button>
          </template>
          <template v-else>
            <el-button @click="rowSave(row, $index)" type="text">保存</el-button>
            <el-button @click="rowCancel(row, $index)" type="text">取消</el-button>
          </template>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
export default {
  data() {
    return {
      tableLoading: false,
      tableHeader: [
        {
          prop: 'pileNo',
          label: '堆號',
          noEdit: true
        },
        {
          prop: 'tfe',
          label: '品位'
        },
        {
          prop: 'ironWeight',
          label: '鐵水產(chǎn)量'
        }
      ],
      tableData: [],
      historyRow: null, // 行編輯時存儲歷史數(shù)據(jù)
    }
  },
  computed: {
    // 表格中最大配比列長度
    maxTableColLength() {
      let arr = this.tableData.map(item => {
        return (item.list || []).length
      })
      return arr.length ? Math.max(...arr) : 0
    },
  },
  created() {
    this.initData()
  },
  methods: {
    // 判斷值是否為空
    isNull(val) {
      return val === null || val === void 0 || val === '' || (val).toString() === 'NaN'
    },
    /**
     * 值保留小數(shù)處理
     * @val: 需要保留小數(shù)的值
     * @fixed:小數(shù)位數(shù)
     * @dt:為空時的默認值
     * @unit:單位
     * */
    valFixed(val, fixed = 3, dt = '', unit = '') {
      return this.isNull(val) ? dt : (parseFloat(val).toFixed(fixed) + unit)
    },
    initData() {
      // 模擬數(shù)據(jù)
      let data = [
        {
          pileNo: '11111111',
          tfe: 56.2,
          ironWeight: 5000,
          list: [
            {
              name: '精粉1',
              rate: 10,
            },
            {
              name: '精粉2',
              rate: 5,
            },
            {
              name: '混合粉2',
              rate: 8,
            },
            {
              name: '混合粉4',
              rate: 3,
            }
          ],
        },
        {
          pileNo: '22222222',
          tfe: 50.34,
          ironWeight: 5500,
          list: [
            {
              name: '精粉5',
              rate: 10,
            },
            {
              name: '混合粉1',
              rate: 8,
            },
            {
              name: '混合粉2',
              rate: 3,
            }
          ],
        },
        {
          pileNo: '33333333',
          tfe: 49,
          ironWeight: 4900,
          list: [
            {
              name: '精粉5',
              rate: 5,
            },
            {
              name: '混合粉1',
              rate: 10,
            },
            {
              name: '混合粉2',
              rate: 20,
            },
            {
              name: '混合粉3',
              rate: 20,
            }
          ],
        }
      ]

      let tableData = []
      data.map(item => {
        let list = item.list || []
        tableData = tableData.concat([
          {
            ...item,
            // 輔助變量
            rowSpan: 2
          },
          {}
        ])
      })
      this.tableData = tableData
    },

    // 表頭隱藏
    headerRowStyle({row, rowIndex}) {
      if (rowIndex === 1) {
        return {'display': 'none'}
      }
    },
    // 表格行合并
    spanMethod({row, column, rowIndex, columnIndex}) {
      let startColIndex = this.tableHeader.length // 數(shù)的,第五列開始是配比列
      let endColIndex = startColIndex + (this.maxTableColLength - 1)
      let isRateCol = columnIndex >= startColIndex && columnIndex <= endColIndex // 配比列不進行行合并
      if (row.rowSpan) { // name行
        if (!isRateCol) {
          return [row.rowSpan, 1]
        } else {
          return [1, 1]
        }
      } else { // 配比行
        if (!isRateCol) {
          return [0, 1]
        } else {
          return [1, 1]
        }
      }

    },

    // 打印數(shù)據(jù)
    logTableData() {
      let data = this.tableData.filter(item => item.rowSpan)
      data.map((item) => {
        let str = ''
        this.tableHeader.map(sub => {
          str += `${sub.label}: ${item[sub.prop]} `
        })
        item.list.map(sub => {
          str += `${sub.name}: ${sub.rate} `
        })
        console.log(`%c${str}`, 'color: #43bb88;font-weight: bold;');
      })

      console.log('最終數(shù)據(jù)為:', data)
    },

    // 行編輯 --------------- start

    // 修改
    rowEdit(row, rowIndex) {
      // console.log(row, rowIndex)
      if (this.tableData.find(item => item._edit)) return this.$message({
        message: '請保存正在編輯的行',
        type: 'warning'
      });

      let editRow = row
      this.historyRow = JSON.parse(JSON.stringify(editRow))
      this.$set(editRow, '_edit', true)
    },
    // 保存正在編輯的
    rowSave(row, rowIndex) {
      // console.log(row, rowIndex)
      this.historyRow = {}
      row._edit = false
    },
    // 取消保存
    rowCancel(row, rowIndex) {
      // console.log(row, rowIndex)
      this.tableData.splice(rowIndex, 1, {
        ...this.historyRow,
        _edit: false
      })
      this.historyRow = {}
    }

    // 行編輯 --------------- end
  }
}
</script>

<style scoped lang="less">

.inputNumber {
  /deep/ input::-webkit-outer-spin-button,
  /deep/ input::-webkit-inner-spin-button {
    -webkit-appearance: none !important;
  }

  /deep/ input[type='number'] {
    -moz-appearance: textfield;
  }
}
</style>

大體思路

image.png

1.表頭其實有兩行,下面這行被隱藏了。
2.表格中每行數(shù)據(jù)是兩行,表格行合并了,第二行是空行,編輯時操作的是第一行的數(shù)據(jù)。
3.這里使用行合并是為了讓配比列表格寬度自適應(yīng)。

若對你有幫助,請點個贊吧,謝謝支持!
本文地址:http://m.itdecent.cn/p/0fdfbb68a73e?v=1668668903593,轉(zhuǎn)載請注明出處,謝謝。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容