精华内容
下载资源
问答
  • vue移动端复杂表格表头,固定表头与固定第

    万次阅读 热门讨论 2018-07-28 11:45:09
    最近做移动端的h5项目,要做一个可配置表头的复杂表格,网上找了很久也没什么好方法,结合网上的一些例子,此做一了一个完整的vue版的例子。 效果 无图无真相,先上最终效果图再说 。 方法一:iscroll ...

    复杂表格表头
    #前言
    最近做移动端的h5项目,要做一个可配置表头的复杂表格,网上找了很久也没什么好方法,结合网上的一些例子,在此做一了一个完整的vue版的例子。
    #效果
    无图无真相,先上最终效果图再说 。
    table.gif
    #方法一:iscroll 插件版
    ###第一步:npm install
    引入 iscroll

    npm i iscroll --save 
    

    ###第二步:封装
    对插件再做一层封装,封装成 iscrollTable.js 方便调用,代码如下:

    // 统一使用
    const iScollProbe = require('iscroll/build/iscroll-probe');
    let scroller = null;
    let Selector = "";
    export function createIScroller(selector) {
      Selector = selector;
      scroller = new iScollProbe(Selector, {
        preventDefault: false,  // 阻止浏览器滑动默认行为
        probeType: 3, //需要使用 iscroll-probe.js 才能生效 probeType : 1 滚动不繁忙的时候触发 probeType : 2 滚动时每隔一定时间触发 probeType : 3   每滚动一像素触发一次
        mouseWheel: true, //是否监听鼠标滚轮事件。
        scrollX: true,  // 启动x轴滑动
        scrollY: true,  // 启动y轴滑动
        // momentum: false,
        lockDirection: false,
        snap: false, //自动分割容器,用于制作走马灯效果等。Options.snap:true// 根据容器尺寸自动分割
        //snapSpeed: 400,
        scrollbars: false, //是否显示默认滚动条
        freeScroll: true, //主要在上下左右滚动都生效时使用,可以向任意方向滚动。
        deceleration: 0.0001, //滚动动量减速越大越快,建议不大于 0.01,默认:0.0006
        disableMouse: true, //是否关闭鼠标事件探测。如知道运行在哪个平台,可以开启它来加速。
        disablePointer: true, //是否关闭指针事件探测。如知道运行在哪个平台,可以开启它来加速。
        disableTouch: false, //是否关闭触摸事件探测。如知道运行在哪个平台,可以开启它来加速。
        eventPassthrough: false, //使用 IScroll 的横轴滚动时,如想使用系统立轴滚动并在横轴上生效,请开启。
        bounce: false //是否启用弹力动画效果,关掉可以加速
      });
      scroller.on('scroll', updatePosition);
      scroller.on('scrollEnd', updatePosition);
      scroller.on('beforeScrollStart', function () {
        scroller.refresh();
      });
    
      function updatePosition() {
        let frozenCols = document.querySelectorAll(selector + ' table tr td.cols');
        let frozenRows = document.querySelectorAll(selector + ' table tr th.rows');
        let frozenCrosses = document.querySelectorAll(selector + ' table tr th.cross');
        for (let i = 0; i < frozenCols.length; i++) {
          frozenCols[i].style.transform = 'translate(' + -1 * this.x + 'px, 0px) translateZ(0px)';
        }
        for (let i = 0; i < frozenRows.length; i++) {
          frozenRows[i].style.transform = 'translate(0px, ' + -1 * this.y + 'px) translateZ(0px)';
        }
        for (let i = 0; i < frozenCrosses.length; i++) {
          frozenCrosses[i].style.transform = 'translate(' + -1 * this.x + 'px,' + -1 * this.y + 'px) translateZ(0px)';
        }
      }
    
      return scroller;
    }
    
    export function refreshScroller() {
      if (scroller === null) {
        console.error("先初始化scroller");
        return;
      }
      setTimeout(() => {
        scroller.refresh();
        scroller.scrollTo(0, 0);
        let frozenCols = document.querySelectorAll(Selector + ' table tr td.cols');
        let frozenRows = document.querySelectorAll(Selector + ' table tr th.rows');
        let frozenCrosses = document.querySelectorAll(Selector + ' table tr th.cross');
        for (let i = 0; i < frozenCols.length; i++) {
          frozenCols[i].style.transform = 'translate(0px, 0px) translateZ(0px)';
        }
        for (let i = 0; i < frozenRows.length; i++) {
          frozenRows[i].style.transform = 'translate(0px, 0px) translateZ(0px)';
        }
        for (let i = 0; i < frozenCrosses.length; i++) {
          frozenCrosses[i].style.transform = 'translate(0px, 0px) translateZ(0px)';
        }
      }, 0);
    }
    

    ###第三步:使用
    引用前面的自己封装的iscrollTable.js,用到的table.vue的具体代码如下:

    <template>
        <div class="pages-tables " id="pages-tables">
            <div class="waterMask" id="watermark"></div>
            <div class="rolling-table meal-table" ref="tableBox" :style="{height: maxHeight + 'px'}">
                <table class="table" id="table" cellpadding="0" cellspacing="0" ref="rollingTable">
                    <tr v-for="(x,i) in xList" :key="i">
                        <th class="rows " :class="{'cross': index == 0 && i == 0}" v-for="(l,index) in x" :key="index" :colspan="l.colspan" :rowspan="l.rowspan">{{l.name}}</th>
                    </tr>
                    <tr v-for="(l,i) in yList" :key="i + 'a'">
                        <template v-for="(x, xKey) in xField">
                            <td v-for="(ll,yKey) in l" :key="yKey" v-if="x === yKey" :class="{'cols': yKey == xField[0]}">
                                {{ yList[i][yKey]}}
                            </td>
                        </template>
                    </tr>
                    <tr></tr>
                </table>
            </div>
        </div>
    </template>
    <script>
    import { createIScroller, refreshScroller } from "libs/iscrollTable";
    import { addWaterMarker } from "libs/common/common";
    export default {
        data() {
            return {
                maxHeight:'100%',
                scroll: {
                    scroller: null
                },
                xList: [
                    [
                        {
                            field_name: "statis_date",
                            name: "第一行合并3行1列",
                            colspan: 1, //指定单元格 横向 跨越的 列数
                            rowspan: 3, //指定单元格 纵向 跨越的 行数
                        },
                        {
                            field_name: "custom_field",
                            name: "第一行合并2列",
                            colspan: 2,
                            rowspan: 1,
                        },
                        {
                            field_name: "custom_field",
                            name: "第一行合并2列",
                            colspan: 2,
                            rowspan: 1,
                        },
                        {
                            field_name: "custom_field",
                            name: "第一行合并3列",
                            colspan: 3,
                            rowspan: 1,
                        },
                    ],
                    [
                        {
                            field_name: "custom_field",
                            name: "第二行日期",
                            colspan: 1, //指定单元格 横向 跨越的 列数
                            rowspan: 1, //指定单元格 纵向 跨越的 行数
                        },
                        {
                            field_name: "custom_field",
                            name: "第二行日期合并2列",
                            colspan: 2,
                            rowspan: 1,
                        },
                        {
                            field_name: "custom_field",
                            name: "第二行日期合并2列",
                            colspan: 2,
                            rowspan: 1,
                        },
                        {
                            field_name: "custom_field",
                            name: "第二行日期合并3列",
                            colspan: 3,
                            rowspan: 1,
                        },
                    ],
                    [
                        {
                            field_name: "area_name",
                            name: "第三行当月新增",
                            colspan: 1,  //指定单元格 横向 跨越的 列数
                            rowspan: 1, //指定单元格 纵向 跨越的 行数
                        },
                        {
                            field_name: "area_name1",
                            name: "第三行当月新增1",
                            colspan: 1,
                            rowspan: 1,
                        },
                        {
                            field_name: "area_name2",
                            name: "第三行当月新增2",
                            colspan: 1,
                            rowspan: 1,
                        },
                        {
                            field_name: "area_name3",
                            name: "第三行当月新增3",
                            colspan: 1,
                            rowspan: 1,
                        },
                        {
                            field_name: "area_name4",
                            name: "第三行当月新增4",
                            colspan: 1,
                            rowspan: 1,
                        },
                        {
                            field_name: "area_name5",
                            name: "第三行当月新增5",
                            colspan: 1,
                            rowspan: 1,
                        },
                        {
                            field_name: "area_name6",
                            name: "第三行当月新增6",
                            colspan: 1,
                            rowspan: 1,
                        },
                    ],
                ],
                xField: ['statis_date', 'area_name', "area_name1", "area_name2", "area_name3", "area_name4", "area_name5", "area_name6",],
                yList: [
                    {
                        area_name: "新增数据开始",
                        area_name1: "新增数据开始1",
                        area_name2: "新增数据开始2",
                        area_name3: "新增数据开始3",
                        area_name4: "新增数据开始4",
                        area_name5: "新增数据开始5",
                        area_name6: "新增数据开始6",
                        statis_date: 100007,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据最后",
                        area_name1: "新增数据最后1",
                        area_name2: "新增数据最后2",
                        area_name3: "新增数据最后3",
                        area_name4: "新增数据最后4",
                        area_name5: "新增数据最后5",
                        area_name6: "新增数据最后6",
                        statis_date: 222222,
                    }
                ]
            }
        },
        mounted() {
            this.maxHeight = window.screen.height
            this.scroll.scroller = createIScroller(".meal-table");
            // addWaterMarker(document.getElementById('watermark'))
        }
    }
    
    </script>
    <style lang="less" scoped>
    .pages-tables {
      -webkit-overflow-scrolling: touch; // ios滑动顺畅
      position: relative;
    }
    .rolling-table {
        height: 100%;
        font-size: 0.28rem;
        color: #86939a;
        background-color: #fff;
        width: 100%;
        -webkit-overflow-scrolling: touch;
        position: relative;
        top: 0;
        overflow: hidden;
      }
    .rows {
        position: relative;
        z-index: 3;
    }
    .cross {
        position: relative;
        z-index: 5;
    }
    table td {
      border: 0px solid #000;
      font-size: 0.32rem;
      background: #fff;
    }
    ::-webkit-scrollbar {
        display: none;
    }
    .table {
    //   border-collapse: collapse; //去掉重复的border
      color: #86939e;
      font-size: 0.32rem;
      border: 0px solid #000;
      min-height: 100%;
      text-align: center;
      td {
        border-bottom: 0.02rem solid #eee;
        white-space: nowrap;
        height: 0.86rem;
        line-height: 0.86rem;
        padding: 0 0.2rem;
      }
      th {
        color: #43484d;
        white-space: nowrap;
        height: 0.74rem;
        line-height: 0.74rem;
        padding: 0rem 0.3rem;
        background-color: #f3f4f6;
        font-weight: normal;
        padding-bottom: 0;
        padding-top: 0;
        border: 0.02rem solid red;
      }
    }
    tr{
        position: relative;
        background-color: #fff;
        &:nth-of-type(odd){
            td{
                // background-color: pink;
            }
        }
    }
    </style>
    

    注意点:

    1. table 外的盒子 .rolling-table 要设置高度,不然向上滚动失效
      2.固定和行与列,即:rows、cross 的position要设为relative

    最终效果就如上图。
    #方法二: 结合css,自定义封装版
    ###原理
    因为除了表头和第一列,其他都可以滚动所以需要:
    1.一个展示的table表格
    2.一个用来覆盖上表头的 thead,一个用来覆盖左上角的 div,一个固定在第一列的 tbody。
    3. 展示的table表格放在最底层,覆盖上表头的 thead固定定位在最上面,固定在第一列的 tbody固定定位在最左边,左上角的 div固定是左上角且z-index最大,在最上层。
    4. 固定的表格头部与第一列的宽、高、行高都是通过获取真实的表格的宽高来设定的。
    5. 通过展示的table表格的上下滚动从而带动固定在第一列的 tbody向上滚动,向左右滚动带动覆盖上表头的 thead的左右滚动。

    完整代码如下:

    <template>
        <div class="pages" id="pages" :style="{height: maxHeight + 'px'}">
            <table id="table" class="table" cellpadding="0" cellspacing="0">
                <thead v-show="showFixedHeaderCloFirst" class="fixedThead" id="fixedThead" :style="{left: fixedTheadLeft}">
                    <tr v-for="(x,i) in xList"   :key="i+'a'">
                        <th v-for="(l,i) in x" :key="i" :colspan="l.colspan" :rowspan="l.rowspan">{{l.name}}</th>
                    </tr>
                </thead>
                <div v-show="showFixedHeaderCloFirst" class="fixedHeaderCenter" id="fixedHeaderCenter" :style="{'line-height': firstCloHeight + 'px',width: firstCloWidth-1 + 'px'}">{{xList[0][0].name}}</div>
    
                <tbody v-show="showFixedHeaderCloFirst" class="fixedHeaderCloFirst" id="fixedHeaderCloFirst" :style="{'top': fixedHeaderCloFirstTop ,'height': fixedHeaderCloFirstHeight}">
                    <tr v-for="(l,i) in yList" :key="i" :style="{width: firstCloWidth + 'px',height: cloFirstLineHeight + 'px'}">
                        <td :style="{width: firstCloWidth + 'px',height: cloFirstLineHeight -1 + 'px' }">{{l.statis_date }} </td>
                    </tr>
                </tbody>
                
                <thead >
                    <tr v-for="(x,index) in xList"   :key="index+'b'">
                        <th :class="{firstCol: index == 0 && i == 0}" v-for="(l,i) in x" :key="i" :colspan="l.colspan" :rowspan="l.rowspan">{{l.name}}</th>
                    </tr>
                </thead>
                <tbody id="tbody">
                    <tr  v-for="(l,i) in yList" :key="i">
                        <td v-for="(x,xKey) in xField" :key="xKey">
                            <div v-for="(ll,yKey) in l" v-if="x === yKey" :key="yKey" :class="{'tables-content-item-yellow':yList[i][yKey] > 0 && validateVal(x),'tables-content-item-green':yList[i][yKey] <= 0 && validateVal(x),}">
                                {{ yList[i][yKey]}}
                            </div>
                        </td>
                    </tr>
                </tbody>
            </table>
        </div>
    </template>
    <script>
    export default {
        data() {
            return {
                maxHeight: '100%',
                fixedTheadLeft: 0,
                fixedHeaderCloFirstTop: 0,
                fixedHeaderCloFirstHeight: '100%',
                th: [],
                tl: [],
                temp: [],
                firstCloWidth: 0,
                firstCloHeight: 0,
                showFixedHeaderCloFirst: false,
                cloFirstLineHeight: '0',
                fixedCol: false,
                fixedHeader: false,
                fixedA1: false,
                hLeft: 0,
                hHeight: 0,
                xList: [
                    [
                        {
                            field_name: "statis_date",
                            name: "第一行合并3行1列",
                            colspan: 1, //指定单元格 横向 跨越的 列数
                            rowspan: 3, //指定单元格 纵向 跨越的 行数
                        },
                        {
                            field_name: "custom_field",
                            name: "第一行合并2列",
                            colspan: 2,
                            rowspan: 1,
                        },
                        {
                            field_name: "custom_field",
                            name: "第一行合并2列",
                            colspan: 2,
                            rowspan: 1,
                        },
                        {
                            field_name: "custom_field",
                            name: "第一行合并3列",
                            colspan: 3,
                            rowspan: 1,
                        },
                    ],
                    [
                        {
                            field_name: "custom_field",
                            name: "第二行日期",
                            colspan: 1, //指定单元格 横向 跨越的 列数
                            rowspan: 1, //指定单元格 纵向 跨越的 行数
                        },
                        {
                            field_name: "custom_field",
                            name: "第二行日期合并2列",
                            colspan: 2,
                            rowspan: 1,
                        },
                        {
                            field_name: "custom_field",
                            name: "第二行日期合并2列",
                            colspan: 2,
                            rowspan: 1,
                        },
                        {
                            field_name: "custom_field",
                            name: "第二行日期合并3列",
                            colspan: 3,
                            rowspan: 1,
                        },
                    ],
                    [
                        {
                            field_name: "area_name",
                            name: "第三行当月新增",
                            colspan: 1,  //指定单元格 横向 跨越的 列数
                            rowspan: 1, //指定单元格 纵向 跨越的 行数
                        },
                        {
                            field_name: "area_name1",
                            name: "第三行当月新增1",
                            colspan: 1,
                            rowspan: 1,
                        },
                        {
                            field_name: "area_name2",
                            name: "第三行当月新增2",
                            colspan: 1,
                            rowspan: 1,
                        },
                        {
                            field_name: "area_name3",
                            name: "第三行当月新增3",
                            colspan: 1,
                            rowspan: 1,
                        },
                        {
                            field_name: "area_name4",
                            name: "第三行当月新增4",
                            colspan: 1,
                            rowspan: 1,
                        },
                        {
                            field_name: "area_name5",
                            name: "第三行当月新增5",
                            colspan: 1,
                            rowspan: 1,
                        },
                        {
                            field_name: "area_name6",
                            name: "第三行当月新增6",
                            colspan: 1,
                            rowspan: 1,
                        },
                    ],
                ],
                xField: ['statis_date', 'area_name', "area_name1", "area_name2", "area_name3", "area_name4", "area_name5", "area_name6",],
                yList: [
                    {
                        area_name: "新增数据开始",
                        area_name1: "新增数据开始1",
                        area_name2: "新增数据开始2",
                        area_name3: "新增数据开始3",
                        area_name4: "新增数据开始4",
                        area_name5: "新增数据开始5",
                        area_name6: "新增数据开始6",
                        statis_date: 100007,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据",
                        area_name1: "新增数据1",
                        area_name2: "新增数据2",
                        area_name3: "新增数据3",
                        area_name4: "新增数据4",
                        area_name5: "新增数据5",
                        area_name6: "新增数据6",
                        statis_date: 201807,
                    },
                    {
                        area_name: "新增数据最后",
                        area_name1: "新增数据最后1",
                        area_name2: "新增数据最后2",
                        area_name3: "新增数据最后3",
                        area_name4: "新增数据最后4",
                        area_name5: "新增数据最后5",
                        area_name6: "新增数据最后6",
                        statis_date: 222222,
                    }
                ]
            }
        },
        filters: {
            dateFromt: function (value) {
                if (!value) return ''
                value = value.toString()
                return value.slice(4)
            },
        },
        methods: {
            // 返回
            vdVal(val, value) {
                return value
            },
            // 是否包含 % 标志,有就要颜色控制
            validateVal(value) {
                let flag = false
                this.xList.forEach((e, i) => {
                    if (e.zd_name == value) {
                        if (e.zx_name.includes('%')) {
                            flag = true
                        }
                    }
                })
                return flag
            },
            $$(dom){
                return document.getElementById(dom)
            },
            savePosition(){
                this.maxHeight = window.screen.height
                this.$$("pages").onscroll = (()=> {
                    let offsetHeight = this.$$("fixedHeaderCenter").offsetHeight
                    let scrollTop = offsetHeight + 1 - this.$$("pages").scrollTop
                    this.fixedTheadLeft =  - this.$$("pages").scrollLeft + 'px'
                    this.fixedHeaderCloFirstTop = scrollTop + 'px'
                    console.log("scrollTop:",scrollTop)
                    console.log("this.fixedHeaderCloFirstTop:",this.fixedHeaderCloFirstTop)
                });
                // this.$$("fixedHeaderCloFirst").onscroll = (()=> {
                //     let offsetHeight = this.$$("fixedHeaderCenter").offsetHeight
                //     let scrollTop = - this.$$("fixedHeaderCloFirst").scrollTop
                //     this.$$("pages").style.left =  - this.$$("fixedHeaderCloFirst").scrollLeft + 'px'
                //     this.$$("table").style.top =  scrollTop + 'px'
                // });
            }
        },
        mounted() {
            setTimeout(()=>{
                this.firstCloWidth = document.getElementsByClassName("firstCol")[0].offsetWidth 
                this.firstCloHeight = document.getElementsByClassName("firstCol")[0].offsetHeight-1
                this.fixedHeaderCloFirstHeight = this.$$("tbody").offsetHeight + 'px'
                this.cloFirstLineHeight = this.$$("tbody").children[0].offsetHeight  + 'px'
                this.fixedHeaderCloFirstTop = this.firstCloHeight + 3 + 'px'
                this.showFixedHeaderCloFirst = true
                this.savePosition()
            },1000)
            
        },
    }
    
    </script>
    <style lang="less" scoped>
    ::-webkit-scrollbar {
        display: none;
    }
    .pages{
        overflow: scroll;
        height: 100%;
    
    }
    .fixedHeaderCenter{
        border: 1px solid red;
        background-color: #f3f4f6;
        color: #43484d;
        text-align: center;
        // padding: 0 0.3rem;
        position: fixed;
        left: 0;
        top: 0;
        z-index: 9999;
    }
    .fixedHeaderCloFirst{
        // border-bottom: 1px solid #eee;
        height: 100%;
        line-height: 0.86rem;
        background: #fff;
        white-space: nowrap;
        text-align: center;
        position: fixed;
        left: 0;
        top: 0;
        th,td{
            padding: 0;
        }
        // overflow: scroll;
        div{
            background-color: #fff;
            border-bottom: 1px solid #eee;
        }
    }
    @main-color-green: #269513;
    @main-color-yellow: #fc9d2e;
    table {
      position: relative;
      color: #86939e;
      font-size: 0.32rem;
      border: 0px solid #000;
      min-height: 100%;
      text-align: center;
      white-space:nowrap;
      td {
        border-bottom: 1px solid #eee;
        white-space: nowrap;
        height: 0.86rem;
        line-height: 0.86rem;
        padding: 0 0.2rem;
        white-space:nowrap;
      }
      th {
          white-space:nowrap;
        color: #43484d;
        white-space: nowrap;
        height: 0.74rem;
        line-height: 0.74rem;
        padding: 0rem 0.3rem;
        background-color: #f3f4f6;
        font-weight: normal;
        padding-bottom: 0;
        padding-top: 0;
        border: 1px solid red;
      }
    }
    .tables-content-item-green {
      color: @main-color-green;
    }
    
    .tables-content-item-yellow {
      color: @main-color-yellow;
    }
    table {
        font-size: 0.3rem;
        // margin: 300px;
        border-collapse:collapse
    }
    .fixedThead{
        background: lightblue;
        position: fixed;
        top: 0 ;
        z-index: 2;
    }
    /*固定表头的样式*/
    .fixedHeader {
        background: lightblue;
        position: fixed;
        top: 0 ;
        z-index: 2;
    }
    
    </style>
    

    最终效果图如下:
    table.gif
    不过这个版本的上下滚动时的精准计算有点误差。
    ####推荐第一种方式。

    #最后
    希望文章内容对你有一点帮助!

    欢迎关注以下公众号,学到不一样的 武功秘籍

    关注公众号并回复 福利 可领取免费学习资料,福利详情请猛戳: 免费资源获取–Python、Java、Linux、Go、node、vue、react、javaScript

    BiaoChenXuYing.png

    展开全文
  • elementUI表格表头居中对齐

    elementUI表格表头居中对齐

    是的,你没看错:

       <el-table-column
              label="居中介绍"
              align="center"
              min-width="570"
              show-overflow-tooltip
              prop="introduction"
            ></el-table-column>
    
    展开全文
  • table表格一个表头斜线样式

    万次阅读 2018-08-24 23:56:09
    具体代码实现如下: &amp;lt;!doctype html&amp;gt; &amp;lt;html lang=&quot;en&quot;&amp;gt; &amp;lt;head&amp;gt; &amp;...带表头斜线的表格&amp;lt

    具体代码实现如下:

    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>带表头斜线的表格</title>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
    
            table {
                border: 1px solid #fff;
                /*去掉表格之间的空隙*/
                border-collapse:collapse;
                margin: 100px auto;
            }
    
            caption {
                font-size: 20px;
                font-weight: bold;
            }
    
            th,td{
                border: 1px solid #ccc;
                width: 80px;
                font-size: 14px;
                line-height: 40px;
                text-align: center;
            }
    
            /*模拟对角线*/
            .out{
                border-top:40px #D6D3D6 solid;/*上边框宽度等于表格第一行行高*/
                width:0px;/*让容器宽度为0*/
                height:0px;/*让容器高度为0*/
                border-left:80px #BDBABD solid;/*左边框宽度等于表格第一行第一格宽度*/
                position:relative;/*让里面的两个子容器绝对定位*/
            }
    
            b{
                font-style:normal;
                display:block;
                position:absolute;
                top:-40px;
                left:-40px;
                width:50px;
            }
    
            em{
                font-style:normal;
                display:block;
                position:absolute;
                top:-25px;
                left:-70px;
                width:55px;
            }
    
        </style>
    </head>
    <body>
    
    <table>
        <caption>我是标题</caption>
        <thead>
            <tr>
                <!-- 模拟表头分割线的部分 -->
                <th>
                    <div class="out">
                        <b>类别</b>
                        <em>姓名</em>
                    </div>
                </th>
                <th>年龄</th>
                <th>班级</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>张三</td>
                <td>18</td>
                <td>大一</td>
            </tr><tr>
                <td>李四</td>
                <td>19</td>
                <td>大二</td>
            </tr><tr>
                <td>王五</td>
                <td>20</td>
                <td>大三</td>
            </tr><tr>
                <td>赵六</td>
                <td>21</td>
                <td>大四</td>
            </tr>
        </tbody>
    </table>
    
    </body>
    </html>
    

    结果:
    这里写图片描述

    展开全文
  • 一、分析需求 这里先上一张图说明 需求: ...渲染出一个这样子的 表格 : res数据: res的每一个元素的直接属性name (即为邮费模板名称,比如成都运费模板), res的ext属性下的三个数组 defa...

    一、分析需求

    • 这里先上一张图说明 需求

    根据后端返回的数据 (res 是一个数组,它的元素是一个对象,对象里面的ext属性是一个对象,它又包含了,defaultfreepay三个属性,且这三个都是数组格式。):
    在这里插入图片描述

    • 渲染出一个这样子的 表格

    res数据:

    1. res的每一个元素的直接属性name (即为邮费模板名称,比如成都运费模板),
    2. resext属性下的三个数组 defaultfreepay,每一个数组要大的一行(这一行中,第一列是运送到的地址的名字,这里定义的是area属性,但后端是未给到这个字段的,可自己处理数据添加该字段 ,这里就不细说了。) 这个area属性占据的这一列,在页面的展示效果 应该是多行合并的效果。在这里插入图片描述

    二、代码实现:

    <template>
        <div class="layout">
          <el-table :data="res" >
            <el-table-column prop="name">
              <template slot-scope="scope">
                <div class="tab_header">
                  <span style="font-weight:600;">{{scope.row.name}}</span>
                  <div class="operate">
                    <span @click="handleEdit(scope.$index, scope.row)">修改</span>
                    <span @click="handleDelete(scope.$index, scope.row)">删除</span>
                  </div>
                </div>
    
                <!-- 这里要实现 多个表格共用一个表头,故需做判断,当表格要渲染的数据为default这个数组的时候,才显示表头的label值 -->
                <!-- 注意:当label无值的时候,还是会占用空间,故当前表格在页面上会出现一个代表表头的空行,需要手动更改(重写)Element表格的 thead样式 -->
    
                <div v-for="item in (scope.row.ext)" :key="item.id">
                  <el-table :data="item" border :class="item!==scope.row.ext.default?'tab-thead-style':''"  style="box-sizing: border-box;border-top:none;" :span-method="objectSpanMethod">
                    <el-table-column :label="item===scope.row.ext.default?'运送到':''" prop="area"></el-table-column>
                    <el-table-column :label="item===scope.row.ext.default?'首重':''" prop="weight"></el-table-column>
                    <el-table-column :label="item===scope.row.ext.default?'运费':''"   prop="first_price"></el-table-column>
                    <el-table-column :label="item===scope.row.ext.default?'续重':''"  prop="weight_incre"></el-table-column>
                    <el-table-column :label="item===scope.row.ext.default?'最终运费':''"  prop="extend_price"></el-table-column>
                  </el-table>
                </div>
    
              </template>
            </el-table-column>
          </el-table>
        </div>
    </template>
    <script>
    export default {
      data () {
        return {
          // res 参考的是后端返回的数据格式,
          res: [
            {
              id: 1,
              dealer_id: 0,
              name: '成都运费模板',
              type: 1,
              ext: {
                default: [{ area: '默认', type: 1, region: '1', weight: '首重d', weight_incre: '续重d', first_price: '运费d', extend_price: '最终运费d' }],
                free: [{ area: 'free', type: 1, region: '1', weight: '首重f', weight_incre: '续重f', first_price: '运费f', extend_price: '最终运费f' }, { area: 'free', type: 1, region: '1', weight: '首重f', weight_incre: '续重f', first_price: '运费f', extend_price: '最终运费f' }],
                pay: [{ area: 'pay', type: 1, region: '1', weight: '首重p', weight_incre: '续重p', first_price: '运费p', extend_price: '最终运费p' }, { area: 'pay', type: 1, region: '1', weight: '首重p', weight_incre: '续重p', first_price: '运费p', extend_price: '最终运费p' }, { area: 'pay', type: 1, region: '1', weight: '首重p', weight_incre: '续重p', first_price: '运费p', extend_price: '最终运费p' }]
              }
            },
            {
              id: 2,
              dealer_id: 0,
              name: '重庆运费模板',
              type: 2,
              ext: {
                default: [{ area: '默认1', type: 1, region: '1', weight: '首重d', weight_incre: '续重d', first_price: '运费d', extend_price: '最终运费d' }],
                free: [{ area: 'free1', type: 1, region: '1', weight: '首重f', weight_incre: '续重f', first_price: '运费f', extend_price: '最终运费f' }, { area: 'free', type: 1, region: '1', weight: '首重f', weight_incre: '续重f', first_price: '运费f', extend_price: '最终运费f' }],
                pay: [{ area: 'pay1', type: 1, region: '1', weight: '首重p', weight_incre: '续重p', first_price: '运费p', extend_price: '最终运费p' }, { area: 'pay', type: 1, region: '1', weight: '首重p', weight_incre: '续重p', first_price: '运费p', extend_price: '最终运费p' }, { area: 'pay', type: 1, region: '1', weight: '首重p', weight_incre: '续重p', first_price: '运费p', extend_price: '最终运费p' }, { area: 'pay1', type: 1, region: '1', weight: '首重p', weight_incre: '续重p', first_price: '运费p', extend_price: '最终运费p' }, { area: 'pay', type: 1, region: '1', weight: '首重p', weight_incre: '续重p', first_price: '运费p', extend_price: '最终运费p' }, { area: 'pay', type: 1, region: '1', weight: '首重p', weight_incre: '续重p', first_price: '运费p', extend_price: '最终运费p' }]
              }
            }
    
          ]
        }
      },
      methods: {
        handleEdit (index, row) {
          console.log(index, row)
        },
        handleDelete (index, row) {
          console.log(index, row)
        },
        objectSpanMethod ({ row, column, rowIndex, columnIndex }) {
          if (columnIndex === 0) {
            if (rowIndex === 0) {
              let maxLen
              this.res.forEach(val => {
                const arr = [val.ext.default.length, val.ext.free.length, val.ext.pay.length]
                arr.sort((a, b) => a - b)// arr数组  按数字大小从小到大排序
                maxLen = arr.pop()// 取出排序后的数组arr中的最后一个元素
              })
              return {
                // 这个rowspan应该据 ext的default,pay,free的长度不同来定,取最大长度
                rowspan: maxLen,
                colspan: 1
              }
            } else {
              return {
                rowspan: 0,
                colspan: 0
              }
            }
          }
        }
      }
    }
    </script>
    <style lang="scss">
    .layout{
    
      .tab_header{
       color:#333;
       padding:0 5px 0 5px;
       height:45px;
       line-height:45px;
       border:1px solid #eee;display:flex;
       justify-content: space-between;
       background:rgb(233, 225, 225);
      }
      .operate{
        span{
          font-size: 14px;
          margin-right: 20px;
          margin-right:20px;
          color:#409EFF;
          cursor: pointer;
        }
      }
      /* 处理多个表格共用一个表头时,表头处出现多余空行的问题 (label置空后还是占据空间问题) */
      .tab-thead-style{
          thead{
              display: none;
          }
      }
    
    }
    </style>
    
    
    

    在这里插入图片描述

    三、知识点总结:

    • 为什么要采用这种方式解决(渲染)?

      ① . 项目用的UI组件是Element,它的Table表格组件,没有直接处理行的操作。

      ② . el-table,它是通过注入data对象数组,并在el-table-column 中用prop属性来对应对象中的键名来填入数据,从而渲染出渲染表格。其中el-table-column表示一个列,label属性来定义表格的列名,即对象的一个键名代表一列;

      ③ . 没想到更优的解决办法,O(∩_∩)O哈哈~

    • 多个表格共用一个表头时,注意:

      ①. 需做判断,同时注意label的值。

      ②.el-table-column 的属性label无值的时候,还是会占用空间,故当前表格在页面上会出现一个代表表头的空行,需要手动更改(重写)Element表格的 thead样式

    • table表格嵌套的时候,注意:

      ① . ElementTable组件可 自定义列模板,主要是利用它实现表格嵌套部分,通过 Scoped slot 可以获取到 row, column, $indexstore(table 内部的状态管理)的数据,更多用法参考官网

      ②. ElementTable组件可 合并行或列 ,多行或多列共用一个数据时,可以合并行或列;通过给table传入span-method方法可以实现合并行或列,参考上述代码的 **objectSpanMethod**方法(该表格的第一列需要合并多行——合并渲染表格的data数组的长度那么多行) 或者官网。

    展开全文
  • layui 数据表格表头动态修改

    万次阅读 2019-06-20 10:21:48
    一般情况下,数据表格表头是固定的,不会轻易改变,但是由于业务的需要,表格的表头需要动态修改,有很多方法: 1.html页面分别设置成不同的数据表格,根据点击事件来show或者hide,这样可以达到我们的目的,但是,这样违法...
  • bootstrap 表格表头固定

    万次阅读 2017-07-17 22:49:08
    效果效果是pc端和移动端能够使表格表头固定,并且顶部,支持缩放时布局不乱。核心技术利用css的position:fixed 属性来脱离文档流,达到表头固定的效果。代码说明都代码里面,代码也不多这里就不多说了。 ...
  • 次遇到这问题: 每次加载时候第次会出现重复重叠问题,刷新一下页面就正常了. ...onPostBodyonPostHeader事件表加载后 刷新表内容和表头 刷新方法 $("#id").bootstrapTable('resetView'); ...
  • 解决表格表头与表格数据体的对齐问题 最近项目遇到了表格的表头与表格数据体无法对齐的问题,找了很多办法,都没实际的作用,研究了一下,这里记录一下: (所有样式代码均只贴关键部分) 首先表格样式 table{ ...
  • 前端表格表头固定

    千次阅读 2018-07-20 10:08:01
    最后,也是最重要的,表头固定,需要使用到div的id,这里面,我有三个表格在页面上,需要重复写三次。 window.onload = function(){ var tableCont = document.querySelector('#xxzl'); var tableCont1 =...
  • 对话框中弹出查看信息,打开时表格,要求是表头在左侧
  • html 表格表头条斜线

    万次阅读 2016-09-02 15:04:18
    网上利用border宽度来设置斜线的方法有局限线,...最简单直接的方法就真正意义上画一条线,指定要画斜线的隔离增加一个宽高与格子一样大的canvas.  html如下:   增加一个line()的js脚本: function line(){
  • bootstrapTable表格表头换行

    万次阅读 2017-11-29 14:49:23
    使用bootstrapTable组件,达到表头中有格显示两行,其他表头均为行,效果图如下: 代码: { field : 'pay_date', title : '已还款完成时间', valign:'middle', align:'center' },{
  • antd表格表头固定,含有纵向下拉,表头和表格内容信息错位问题解决复现解决方法 复现 固定表头,设定百分比宽还是 会出现这样的情况 解决方法 .ant-table-fixed-header>.ant-table-content>.ant-table-...
  • java 写一个接口,利用json动态数据生成表格表头 求解
  • //控制表格滑动   table tbody {  display:block;  height:450px;  overflow-y:scroll;  }  //固定表头  table thead, tbody tr {  display:table;  ...
  • .el-table__header tr, .el-table__header th { padding: 0; height: 40px; } .el-table__body tr, .el-table__body td { padding: 0; height: 40px; }
  • 使用bootstrap创建一个表格表头固定,身体部分自动滚动,页面显示3行数据,共有10行数据。怎么实现?
  • jquery实现表格复杂表头

    千次阅读 2018-05-16 10:29:48
    目前一个表格插件,表格表头是根据一个数组生成,如果只是普通的单层表头很容易实现,但是如果是复杂的表头,就要挺麻烦的,主要是我的数组结构是树形数组,实现需要递归,递归过程要考虑到&amp;amp;amp;...
  • layui的数据表格可以你查出数据之后直接解析展示数据,非常的方便。 但是获取数据的时候数据的type不同,或者数据对应的属性不同,设置表头的时候就会有点难受 我们可以这样设置弹出表之前可以先去判断数据...
  • 因为最近项目的特殊性 最近有这样一个需求 在表格中需要按照客户需要 生成不固定的日期 并获取到 这些日期里的数据 一开始因为不太懂客户的需求 已经对页面逻辑的错误理解 算是走了不少弯路 话不多说直接 上实现效果...
  • HTML多表头表格

    万次阅读 2014-02-19 21:54:14
    1、多表头表格代码 多表头表格 body{ width:98%; height:100%; font-size:12px; background-color:#FCF; text-align:center; } #tab{ width:100%; height:100%; font-size:12px;
  • jquery,插件固定表格表头

    千次阅读 2018-09-25 19:57:20
    表格数据较多时,会导致表头随内容滚动,影响使用,因此使用jQuery做一个插件,目前比较粗糙,不过可以达到相同效果 效果图 使用方式: 引入jquery文件 &lt;script type="text/javascript" ...
  • 只保留表格表头,其他内容清空

    千次阅读 2018-02-07 11:12:37
    使用jquery只保留表格表头一行,其他的内容代码清空的代码。 $("table tr:not(:first)").remove();
  • vue、element实现表格表头纵向显示

    万次阅读 2019-07-28 00:13:08
    大多数情况,我们的管理端都有表格展示数据,然而表格的展示基本都是表头横向展示,然后相应的数据行排列下方,我们先看一下element官网的el-table的样子: 那么我们如果想要让表头纵向展示该如何实现呢...
  • 从数据库中取出数据对应的集合,JSP页面中遍历出一个注册项的列表,每一项都是从数据库中的表中取出的,比如,第一行为用户名,后面是个文本框,第二行是密码,后面还是个文本框,但是有的type是text,有的是...
  • 常规表格表头查询

    千次阅读 2014-02-20 23:51:13
    常规表格表头查询
  • JSP页面中,由于表格数据较多,滚动条下滑则看不到表头, 想将表头固定(冻结)住,滚动条滑动只改变数据,有什么 好的办法来实现吗? 注:在一个表格里面,不分两个表格来实现

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 71,870
精华内容 28,748
关键字:

一个表格的表头在哪