element-ui table 實現表格嵌套多層表格


項目需求:要求點擊行中的“其他”單元格中的字段展開相應的子表

1.點擊“擴展屬性”出現"擴展屬性"子表,點擊“國家/地區”出現國家/地區子表

2.在國家/地區子表中還有個“生命周期字段”,點擊“生命周期”出現“生命周期”的子表

 實現方案:使用table 中的type="expand" 同時把展開圖標隱藏,給表格文字“擴展屬性”、“國家/地區”添加點擊事件,通過點擊事件實現不同子表的切換

 當時做的時候是用v-if來實現對各級子表的顯示和隱藏但是出現了問題就是,當點擊順序是 擴展屬性-->國家/地區-->生命周期時會出現生命周期子表沒有展示出來,如圖:

當時使用$nextTick()/$forceUpdate()都沒有用,把v-if換成v-show就沒有問題了。看來頻繁切換的顯示和隱藏就要使用v-show

js代碼:

 

 css:對type=expand屬性的箭頭展開樣式隱藏

 同時要讓width=1 的那一列的邊框去掉

 這時當縮放瀏覽器時會出現表頭錯位的情況,需要再加一個樣式

 下面是完整代碼,搜索條件和表格字段有點多,大家可以忽略。若有不對的地方,歡迎指出,謝謝!

<template>
  <div>
    <el-form size="mini" :model="searchData" class="searchBox">
      <el-row :gutter="24">
        <el-col :xs="24" :sm="24" :md="12" :lg="6" :xl="4">
          <el-form-item label="skuId" class="textArea">
            <el-input
              v-model="searchData.skuIds"
              type="textarea"
              autosize
              placeholder="請輸入"
            ></el-input>
          </el-form-item>
        </el-col>
        <el-col :xs="24" :sm="24" :md="12" :lg="6" :xl="4">
          <el-form-item label="sku編碼" class="textArea">
            <el-input
              v-model="searchData.skuCodes"
              type="textarea"
              autosize
              placeholder="請輸入"
            ></el-input>
          </el-form-item>
        </el-col>
        <el-col :xs="24" :sm="24" :md="12" :lg="6" :xl="4">
          <el-form-item label="sku名稱(中文)">
            <el-input v-model="searchData.skuNameCn" placeholder="請輸入"></el-input>
          </el-form-item>
        </el-col>
        <el-col :xs="24" :sm="24" :md="12" :lg="6" :xl="4">
          <el-form-item label="Sku名稱(英文)">
            <el-input v-model="searchData.skuNameEn" placeholder="請輸入"></el-input>
          </el-form-item>
        </el-col>
        
        <el-col :xs="24" :sm="24" :md="12" :lg="6" :xl="4">
          <el-form-item>
            <el-button type="primary" @click="getTableData('init')">查詢</el-button>
            <el-button @click="reset">重置</el-button>
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
    <el-table
      v-loading="loading"
      row-key="skuId"
      size="mini"
      class="tableBox"
      :data="tableList"
      style="width:100%;"
      border
      :header-cell-style="{ background: '#fafafa' }"
      :expand-row-keys="expands"
    >
      <el-table-column type="expand" width="1">
        <template slot-scope="scopeOut">
          <el-table
            v-show="scopeOut.row.countryShow"
            ref="countryArea"
            :data="scopeOut.row.nations"
            border
            size="mini"
            row-key="id"
            :expand-row-keys="expandsInner"
            :header-cell-style="{ background: '#fafafa' }"
          >
            <el-table-column type="expand" width="1">
              <template slot-scope="scopeInner">
                <el-table
                  v-show="scopeInner.row.lifeShow"
                  :data="scopeInner.row.lifecycles"
                  border
                  size="mini"
                  :header-cell-style="{ background: '#fafafa' }"
                >
                  </el-table-column>
                  <el-table-column
                    prop="lifecycleNameCn"
                    label="生命周期中文名"
                    :show-overflow-tooltip="true"
                  >
                  </el-table-column>
                  <el-table-column
                    prop="lifecycleTime"
                    label="生命周期時間"
                    :show-overflow-tooltip="true"
                  >
                  </el-table-column>
                  <el-table-column prop="skuLifecycleStatus" label="生命周期狀態">
                    <template slot-scope="scopes">
                      <el-tag v-if="scopes.row.skuLifecycleStatus === 0" type="danger">失效</el-tag>
                      <el-tag v-if="scopes.row.skuLifecycleStatus === 1" type="info">有效</el-tag>
                    </template>
                  </el-table-column>
                </el-table>
              </template>
            </el-table-column>
            <el-table-column
              prop="nationTwoAbbr"
              label="國家地區二位碼"
              :show-overflow-tooltip="true"
            >
            </el-table-column>
            <el-table-column
              prop="nationNameCn"
              label="國家地區中文名"
              :show-overflow-tooltip="true"
            >
            </el-table-column>
            <el-table-column label="其他" :show-overflow-tooltip="true">
              <template slot-scope="scopeInner">
                <span style="color:#09F;cursor: pointer;" @click="expandTable(scopeInner.row)"
                  >生命周期</span
                >
              </template>
            </el-table-column>
          </el-table>
          <el-table
            v-show="scopeOut.row.extenShow"
            :data="scopeOut.row.extendAttributes"
            row-key="id"
            border
            size="mini"
            :header-cell-style="{ background: '#fafafa' }"
          >
            <el-table-column
              prop="attrValueCn"
              label="擴展屬性值(中文)"
              :show-overflow-tooltip="true"
            >
            </el-table-column>
            <el-table-column
              prop="attrValueEn"
              label="擴展屬性值(英文)"
              :show-overflow-tooltip="true"
            >
            </el-table-column>
            <el-table-column prop="valueDataType" label="數據類型">
              <template slot-scope="scopes">
                <el-tag v-if="scopes.row.valueDataType === 1" size="mini">字符串</el-tag>
                <el-tag v-if="scopes.row.valueDataType === 2" type="info" size="mini"
                  >帶單位實數等</el-tag
                >
              </template>
            </el-table-column>
          </el-table>
        </template>
      </el-table-column>
      <el-table-column
        property="createTime"
        label="創建時間"
        :show-overflow-tooltip="true"
        :render-header="renderHeader"
      ></el-table-column>
      <el-table-column
        property="updateTime"
        label="更新時間"
        :show-overflow-tooltip="true"
        :render-header="renderHeader"
      ></el-table-column>
      <el-table-column label="其他" :show-overflow-tooltip="true" width="140">
        <template slot-scope="scopeOut">
          <span style="color:#09F;cursor: pointer;" @click="expandExTable(scopeOut.row)"
            >擴展屬性</span
          >
          <span>|</span>
          <span style="color:#09F;cursor: pointer;" @click="expandCounTable(scopeOut.row)"
            >國家/地區</span
          >
        </template>
      </el-table-column>
    </el-table>
    <el-pagination
      class="pagination"
      :current-page="pageNum"
      :page-sizes="[10, 20, 30, 50]"
      :page-size="pageSize"
      layout="total, sizes, prev, pager, next, jumper"
      :total="total"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    >
    </el-pagination>
  </div>
</template>
<script>
import Crypto from '@/utils/crypto.js';
import diySelect from '@/components/Select/diySelect.vue';

export default {
  components: {
    diySelect,
  },
  data() {
    return {
      searchData: {},
      tableList: [],
      pageNum: 1,
      pageSize: 10,
      total: 0,
      loading: false,
      secretKey: '',
      pickerOptions: {
        shortcuts: [
          {
            text: '最近一周',
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
              picker.$emit('pick', [start, end]);
            },
          },
          {
            text: '最近一個月',
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
              picker.$emit('pick', [start, end]);
            },
          },
          {
            text: '最近三個月',
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
              picker.$emit('pick', [start, end]);
            },
          },
          {
            text: '最近六個月',
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 180);
              picker.$emit('pick', [start, end]);
            },
          },
        ],
      },
      dataList: [],
      expands: [],
      expandsCoun: [],
      lifeShow: false,
      countryShow: false,
      expandsInner: [], // 生命周期展開數組
      counFlag: true,
      colorCnsList: [],
      colorEnsList: [],
      colorLocalsList: [],
      carrierNameCnsList: [],
      carrierNameEnsList: [],
      certifiedModelsList: [],
    };
  },
  created() {
    this.getTableData('init');
    this.getSkuItem();
  },
  methods: {
    renderHeader(h, data) {
      return h('span', [
        h(
          'el-tooltip',
          {
            attrs: {
              class: 'item',
              effect: 'dark',
              content: data.column.label,
              placement: 'top',
            },
          },
          [h('span', data.column.label)]
        ),
      ]);
    },
    expandTable(row) {
      row.lifeShow = !row.lifeShow;
      if (row.lifeShow) {
        this.expandsInner.push(row.id);
      } else {
        this.expandsInner = this.expandsInner.filter(item => item !== row.id);
      }
      console.log(this.expandsInner, '生命周期');
    },
    expandCounTable(row) {
      row.countryShow = !row.countryShow;
      if (row.countryShow) {
        this.expands.push(row.skuId);
      } else {
        this.expands = this.expands.filter(item => item !== row.skuId);
      }
      row.extenShow = false;
      console.log(this.expands, '國家/地區');
    },
    expandExTable(row) {
      row.extenShow = !row.extenShow;
      if (row.extenShow) {
        this.expands.push(row.skuId);
      } else {
        this.expands = this.expands.filter(item => item !== row.skuId);
      }
      row.countryShow = false;
      console.log(this.expands, '擴展屬性');
    },
    reset() {
      this.searchData = {};
      this.getTableData('init');
    },
    getTableData(init) {
      this.expandsInner = [];
      this.expands = [];
      let creatObj = {};
      if (this.searchData.createDate !== undefined && this.searchData.createDate !== null) {
        creatObj = {
          startCreateTime: this.searchData.createDate[0],
          endCreateTime: this.searchData.createDate[1],
        };
      } else {
        delete this.searchData.createDate;
        creatObj = {};
      }
      let updateObj = {};
      if (this.searchData.updateDate !== undefined && this.searchData.updateDate !== null) {
        updateObj = {
          startUpdateTime: this.searchData.updateDate[0],
          endUpdateTime: this.searchData.updateDate[1],
        };
      } else {
        delete this.searchData.updateDate;
        updateObj = {};
      }
      const obj = {
        skuIds: this.searchData.skuIds ? this.searchData.skuIds.split(/[(\r\n)\r\n]+/) : [],
        skuCodes: this.searchData.skuCodes ? this.searchData.skuCodes.split(/[(\r\n)\r\n]+/) : [],
        carrierIds: this.searchData.carrierIds
          ? this.searchData.carrierIds.split(/[(\r\n)\r\n]+/)
          : [],
        carrierCodes: this.searchData.carrierCodes
          ? this.searchData.carrierCodes.split(/[(\r\n)\r\n]+/)
          : [],
        normalizationIds: this.searchData.normalizationIds
          ? this.searchData.normalizationIds.split(/[(\r\n)\r\n]+/)
          : [],
        normalizationCodes: this.searchData.normalizationCodes
          ? this.searchData.normalizationCodes.split(/[(\r\n)\r\n]+/)
          : [],
        skuNameCn: this.searchData.skuNameCn,
        skuNameEn: this.searchData.skuNameEn,
        colorCns: this.searchData.colorCns,
        colorEns: this.searchData.colorEns,
        colorLocals: this.searchData.colorLocals,
        carrierNameCns: this.searchData.carrierNameCns,
        carrierNameEns: this.searchData.carrierNameEns,
        certifiedModels: this.searchData.certifiedModels,
        ...updateObj,
        ...creatObj,
      };
      if (init) {
        this.pageNum = 1;
        this.pageSize = 10;
      }
      this.loading = true;
      const param = {
        pageNum: this.pageNum,
        pageSize: this.pageSize,
        ...obj,
      };
      this.$api.productTree.skuList({ ...param }).then(res => {
        if (res.data) {
          this.tableList = res.data.content;
          this.tableList.forEach(item => {
            this.$set(item, 'countryShow', false);
            this.$set(item, 'extenShow', false);
          });
          this.total = res.data.total;
        }
        this.loading = false;
      });
    },
    handleCurrentChange(page) {
      this.pageNum = page;
      this.getTableData();
    },
    handleSizeChange(pageSize) {
      this.pageSize = pageSize;
      this.getTableData();
    },
    getSkuItem() {
      this.$api.productTree.skuItem().then(res => {
        if (res.data) {
          this.colorCnsList = [];
          this.colorEnsList = [];
          this.colorLocalsList = [];
          this.carrierNameCnsList = [];
          this.carrierNameEnsList = [];
          this.certifiedModelsList = [];
          for (const key in res.data) {
            const itemArr = [];
            res.data[key].forEach(item => {
              const obj = {
                name: item,
              };
              itemArr.push(obj);
            });
            if (key === 'colorCns') {
              this.colorCnsList = itemArr;
            } else if (key === 'colorEns') {
              this.colorEnsList = itemArr;
            } else if (key === 'colorLocals') {
              this.colorLocalsList = itemArr;
            } else if (key === 'carrierNameCns') {
              this.carrierNameCnsList = itemArr;
            } else if (key === 'carrierNameEns') {
              this.carrierNameEnsList = itemArr;
            } else if (key === 'certifiedModels') {
              this.certifiedModelsList = itemArr;
            }
          }
        }
      });
    },
  },
};
</script>
<style lang="scss" scoped>
.mainContent {
  margin: 20px;
}
.form-content {
  font-weight: 600;
}
.pagination {
  float: right;
  margin-top: 10px;
}
.import {
  margin: 0 0 20px 0;
}
.el-dialog .el-dialog__body {
  padding-top: 0 !important;
}
.el-form-item {
  margin-bottom: 15px !important;
}
.el-select,
.el-cascader,
.el-date-editor.el-input {
  width: 100%;
}
.searchBox >>> .el-form-item {
  display: flex;
  width: 100%;
  height: 30px;
  .el-form-item__label {
    white-space: nowrap;
  }
  .el-range-editor--mini.el-input__inner {
    height: 30px;
  }
  .el-form-item__content {
    flex: 1;
    .el-date-editor--daterange.el-input,
    .el-date-editor--daterange.el-input__inner,
    .el-date-editor--timerange.el-input,
    .el-date-editor--timerange.el-input__inner {
      width: 100% !important;
    }
  }
}
.tableBox >>> .el-table__expand-icon:after {
  content: '';
}
.tableBox >>> .el-table__expand-icon > i {
  display: none;
}
.tableBox >>> .el-table__expand-column {
  border-right: none;
}
</style>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM