移动端定制化table实现

989 阅读2分钟

背景:公司移动端报表重构,需要定制化一个移动端表格

主要功能有:排序,加粗,标红,标绿,前三行排名展示icon,斑马纹,横向拖动等。 上图

image.png

image.png

一开始想用table做,个人能力有限,改样式不太方便,不满足需求,改用div+span实现

表头后端给,动态表头+表数据

表头数据示例--headerList

[
  {
    "needrank": false,
    "is_percent": false,
    "default_rank": false,
    "name": " ",
    "width": " ",
    "col_name": "ORG_NA"
  },
  {
    "needrank": true,
    "is_percent": true,
    "default_rank": true,
    "name": "毛利额完成率",
    "width": " ",
    "col_name": "GROS_COMP_EVAL"
  },
  {
    "needrank": true,
    "is_percent": true,
    "default_rank": false,
    "name": "销售额完成率",
    "width": "",
    "col_name": "SALE_COMP_EVAL"
  },
  {
    "needrank": true,
    "is_percent": true,
    "default_rank": false,
    "name": "毛利率较任务",
    "width": "",
    "col_name": "MLV_COMP_EVAL"
  },
  {
    "needrank": true,
    "is_percent": true,
    "default_rank": false,
    "name": "较日清日高",
    "width": "",
    "col_name": "COMP"
  },
  {
    "needrank": true,
    "is_percent": true,
    "default_rank": false,
    "name": "日清日高任务",
    "width": "",
    "col_name": "RQRG"
  },
  {
    "needrank": true,
    "is_percent": false,
    "default_rank": false,
    "name": "客单价",
    "width": "",
    "col_name": "xxx"
  },

表格模块

  <div class="pages-tables" id="pages-tables">
    <div class="table-box">
      <div class="rank-header">
        <div
          v-for="(item, index) in headerList"
          :key="index"
          @click="SetRankType(item)"
          class="header-style"
        >
          <div
            class="back"
            @click="Reback"
            v-show="index == 0"
          >
            <div class="text">返回上级</div>
            <img src="../../assets/report/back.png" alt="" />
          </div>
          <span class="head-name" v-show="index > 0">{{ item.name }}</span>
          <img
            class="rank_icon"
            v-show="item.needrank"
            :src="GetRankIconUrl(item.col_name)"
            alt=""
          />
        </div>
      </div>
      <div
        :class="`rank-list${CheckNumType(index) ? '' : ' blue'}`"
        v-for="(item, index) in tableList"
        :key="index"
      >
        <!-- <div v-for="(items, indexs) in item"> -->
        <div
          class="header-style"
          :style="`${
            rankType === items.col_name
              ? 'font-weight: bold'
              : 'font-weight: 500'
          };color: #333333`"
          v-for="(items, indexs) in headerList"
        >
          <div class="tabs" v-if="indexs === 0">
            <span
              :class="`header-name${(lev === 'hbmd') && !item.ORG_NA.includes('(合)') ? '' : ' link'}`"
              @click="headerClick(item)"
            >
              {{ item[`ORG_NA`] }}
            </span>
          </div>
          <div class="tabs" v-if="indexs >= 1">
            {{ item[`${items.col_name}`] }}
          </div>
        </div>
      </div>
    </div>
  </div>

表格数据通过表头的key去寻找渲染

   // 通过奇偶显示表格斑马纹
   CheckNumType(num) {
      if (num % 2 == 0) {
        return true //偶数
      } else {
        return false // 技奇数
      }
    },
    // 判断当前排序规则,选择当前排序字段表头icon
    GetRankIconUrl(name) {
      return this.rankType === name ? rankIcon2 : rankIcon1
    },

表格样式可以根据需求传入表格宽高等等,因为我这边报表宽度基本上固定,就写固定宽 样式了

.pages-tables {
  -webkit-overflow-scrolling: touch; // ios滑动顺畅
  position: relative;
  // width: 100%;
  background-color: #fff;
  border-radius: 0.08rem;
  margin-top: -0.08rem;
  padding: 0.28rem 0.04rem;
  box-sizing: border-box;
  position: relative;
  flex-shrink: 0;
  overflow-x: scroll;
  display: flex;
  overflow: auto;
  .rolling-table {
    height: 100%;
    // width: 100%;
    -webkit-overflow-scrolling: touch;
    position: relative;
    top: 0;
    // overflow: hidden;
    // overflow-x: scroll;
  }
  .table-box {
    // width: 100%;
    position: relative;
  }
  .rank-header {
    width: auto;
    // min-width: 100%;
    height: 0.8rem;
    background: #f5f7fa;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 0.08rem;
    box-sizing: border-box;
    margin-bottom: 0.08rem;
    // overflow-x: scroll;
    .header-style {
      width: 1.3rem;
      line-height: 0.24rem;
      font-size: 0.2rem;
      color: #333333;
      margin-bottom: 0.08rem;
      display: flex;
      align-items: center;
      overflow: hidden;
      margin-right: 0.1rem;
      // &.name {
      //   width: 1.2rem;
      // }
      .back {
        margin-left: 0.22rem;
        display: flex;
        align-items: center;
        justify-content: center;
        .text {
          width: 0.48rem;
          height: 0.48rem;
          font-size: 0.2rem;
          font-family: PingFangSC-Regular, PingFang SC;
          font-weight: 400;
          color: #197bff;
          line-height: 0.24rem;
        }
        img {
          display: block;
          width: 0.32rem;
          height: 0.32rem;
          margin-left: 0.04rem;
        }
      }
      .head-name {
        display: block;
        width: 0.7rem;
        // transform: scale(0.9);
      }
      .rank_icon {
        display: block;
        width: 0.24rem;
        height: 0.24rem;
      }
    }
  }
  .rank-list {
    width: auto;
    min-height: 0.64rem;
    height: auto;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: space-between;
    color: #333333;
    line-height: 0.64rem;
    padding: 0 0.08rem;
    box-sizing: border-box;
    &.blue {
      background: #f5f7fa;
    }
    .header-style {
      width: 1.3rem;
      height: 100%;
      font-size: 0.2rem;
      font-family: PingFangSC-Regular, PingFang SC;
      font-weight: 400;
      height: 100%;
      line-height: 0.28rem;
      overflow: hidden;
      margin-right: 0.1rem;
      .tabs {
        width: 100%;
        height: 100%;
        overflow: hidden;
        > div {
          width: 100%;
          height: 100%;
        }
        .header-name {
          color: #333333;
          &.link {
            color: #197bff;
            text-decoration: underline;
            text-decoration-color: #197bff;
          }
        }
      }
      &.rank {
        width: 0.58rem;
        display: block;
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
      }
      &.charger {
        width: 0.7rem;
      }
      &.name {
        width: 1.2rem;
      }
      img {
        display: block;
        width: 0.4rem;
        height: 0.4rem;
      }
    }
  }
}