vue 自定义的通用的表格组件(使用div)

发布时间:2023年12月21日

vue 自定义的通用的表格组件(使用div)

做项目的时候由于传统的table及elementUI的el-table的tr和td没办法设置间距,满足不了UI提供的设计稿,为了还原,自己封装了该组件

该表格组件的特点

  1. 表头排序功能:支持点击表头进行升序、降序排序,并显示相应的排序图标。
  2. 复选框功能:可以在表格中为每一行数据添加复选框,并支持全选和取消全选操作。
  3. 图表展示:支持在表格中展示图表数据,提供相应的图表显示和交互功能。
  4. 文件上传功能:对于特定的列,支持文件上传和编辑操作,并可以显示上传进度和状态。
  5. 按钮操作:支持在表格中添加按钮并绑定相应的点击事件,实现自定义的操作功能(可以动态控制按钮的显示和禁用状态)。
  6. 支持单元格内容的格式化显示
  7. 行点击事件:支持点击表格某一行触发相应的事件处理。
  8. 包含了滚动条联动的功能,右侧侧固定列和表格内容的联动滚动

该表格组件的介绍

封装组件具体用了vue哪些指令

  1. 条件渲染

    • 使用了 v-if 指令来根据条件判断是否渲染整个表格容器。
      样式类绑定:
  2. 样式类绑定

    • 使用了 :class 绑定动态的样式类。。
  3. 表头渲染:

    • 使用了 v-for 指令循环渲染表头的每一列。
    • 对每一列进行了样式设定,并且设置了点击事件处理函数。
  4. 表格内容渲染:

    • 使用了 v-for 指令循环渲染表格的每一行和每一列。
    • 对每个单元格进行了样式设定,并且设置了点击事件处理函数。
  5. 固定列:

    • 在表格右侧实现了固定列的功能,并根据条件判断是否渲染固定列的内容。
  6. 事件处理:

    • 使用了 @click 绑定点击事件处理函数。
    • 使用了 @change 监听复选框的变化事件。
  7. 插槽:

    • 使用了 slot 标签定义插槽,用于插入其他组件或内容。

表头部分

这部分代码负责渲染表格的表头结构,包括表头的各个列以及相关的操作按钮、排序功能等

<div class="common-table-header">
   ......
</div>

表格内容

这部分代码负责根据数据 data 动态渲染表格的行和列内容,包括每一行中的单元格内容、操作按钮、上传编辑功能等。

<div v-for="(row, index) in data">
   ......
</div>
类名介绍
  • common-table-body — 表格内容的盒子(除表头外)高度需固定(固定原因:表格滚动条)
  • common-table-body-wrapper — 表格内容的盒子(除表头外)高度自适应
  • common-table-row — 每一行的类名

固定列部分

<div class="common-table-box-fixed">
    ......
</div>

传参介绍

  • data — 表格显示的数据
  • columns — 表格列字段
    • 传参格式
      1. label对应value
      2. label2对应value1 — 这块后加的,value2被占用所以没对上可自行更改
      3. label3对应value3
[{
    label: '表头名称',
    value: "对应列内容的字段名",
    width: '表格列的宽度 --- 此处都是转化为vw以便自适应',
    paddingLeft: '每一列的左内边距默认都为20',
    paddingRight: '每一列的右内边距默认都为20',
    isSort: '是否是索引',
    position: "文字是位置-- center:居中;center-left:居左",
    valueFormatter: "单元格内容的格式化显示---方法 --- 解析value",
    valueFormatter1: "单元格内容的格式化显示---方法--- 解析value1",
    valueFormatter3: "单元格内容的格式化显示---方法 --- 解析value3 ",
    isHidden: '隐藏列',
    isDate: '日期格式 --- 日期有特殊样式显示',
    label2: '表头名称 --- 表格显示过多时一列支持显示1-3个字段,举例:表头名为姓名/性别/电话',
    value1: '对应列内容的字段名 --- 表格显示过多时一列支持显示1-3个字段,举例:姓名/性别/电话竖着展示',
    label3: '表头名称 --- 表格显示过多时一列支持显示1-3个字段,举例:表头名为姓名/性别/电话',
    value3: '对应列内容的字段名 --- 表格显示过多时一列支持显示1-3个字段,举例:姓名/性别/电话竖着展示',
    isTooltip: 是否超出显示提示框 --- value内容,
    isTooltip1: 是否超出显示提示框 --- value1内容,
    isTooltip2: 是否超出显示提示框 --- value3内容,
    value2: '表格值显示。一般显示名称后value2用来拼接到value后的',
    wordColor: '表格内容样色,默认为黑色,当该值为true则为灰色',
    isCommonProgress: '显示进度条',
    wrap: '通常用在操作列,按钮是否可以换行',
    isButton: '代表渲染按钮',
    buttonList: '按钮集合',
    fontColorIsBlue: '文字颜色变为蓝色',
    isbadge: '内容右上角显示的标记此处为数量',
    isProgressVal: '进度,这块显示两行,上边为具体值,下册为百分比进度',
    unit: '表格内容如果需要单位且不用valueFormatter,可直接使用该值进行传递',
    isEcharts: '需要绘制echarts',
    isImg: '代表需要展示图片',
    question: '表头显示提示框解释该字段表格含义',
    isClick: '表格可以点击需结合callback进行使用,只有点击每一列生效',
    callback: '方法,点击表格某行后执行',
    bgFormatter: '方法,根据某个值给表格行添加背景'


}]
  • 举例
tableColumns = [
          {
            label: "序号",
            value: "sort",
            width: this.windowWidth <= 1024 ? 70 * 2 : 78 * 2,
            paddingLeft: this.windowWidth <= 1024 ? 10 * 2 : 20 * 2,
            paddingRight: this.windowWidth <= 1024 ? 10 * 2 : 20 * 2,
            isSort: true,
            position: "center"
          },
          {
            label: "创建日期",
            value: "createTime",
            isDate: true,
            width: this.windowWidth <= 1024 ? 140 * 2 : 148 * 2,
            position1: "center-left",
            valueFormatter: this.valueDateFormat,
            paddingLeft: 0,
            paddingRight: 0,
            isHidden: this.windowWidth <= 1024
          },
          {
            label: "类型",
            value: "type",
            width: this.windowWidth <= 1024 ? 85 * 2 : 107 * 2,
            position: "center",
            valueFormatter: this.valueSourceFormat,
            paddingLeft: this.windowWidth <= 1024 ? 10 * 2 : 20 * 2,
            paddingRight: this.windowWidth <= 1024 ? 10 * 2 : 20 * 2
          },
        ];
  • isJump
    • 点击表格任意行及任意位置都能触发
  • isChoose
    • 支持选中某一行
  • needJudgeChooseStatus
    • false-任意选;true-需要满足某些条件才能被选
  • buttonList
    • 固定操作列按钮集合
  • fixedWidth
    • 固定操作列宽
  • fixedLabel
    • 固定操作表头的label
  • rowId
    • 选中某一行时判断是否重复选择的属性key
  • isScroll
    • 是否支持滚动表格后才加载某些内容
  • checkDisabledLabel
    • 表格多选框是否禁用要判断的属性key
  • titleCheck
    • 表格表头多选框的绑定值
  • titleChekcDisabled
    • 表格表头多选框是否禁用
  • chooseNumber
    • 选中表格行最多支持的数量
  • chooseTooltip
    • 选中表格行等于支持的数量后再选的提示

方法介绍

  • handleClickSort(handleSortDown,handleSortUp)
    • 表格的列头点击时触发排序操作,调用 $emit 方法来触发排序事件,并将排序方式和排序字段作为参数传递给父组件,供其进行相应的处理。
  • handleChangeCheck
    • 调用 $emit 方法触发勾选事件,将当前行的row作为参数传递给父组件
  • handleChangeCheckAll
    • 代表全选当前页 - 调用 $emit 方法触发勾选事件传递给父组件
  • progressoFormat
    • 用于格式化进度条的显示文本。该方法接收两个参数:percentage 表示进度百分比,status 表示进度状态
  • handleAvatarSuccess

    上传文件调用的方法

    • res-表示上传成功的响应对象
    • index-表示索引值
    • row 表示行信息。
  • beforeAvatarUpload

    上传文件判断文件类型和大小,根据条件决定是否压缩文件,并将结果返回给上传组件。同时,也会触发上传事件,并将索引值传递给父组件。

  • getFontColorIsBlue(getFontColorIsBlue1,getFontColorIsBlue2)
    • 判断是否给表格某列的添加类名,对文字颜色进行改变
  • getColumnValue(getColumnValue1,getColumnValue3)
    • 用来格式化内容
  • getColumnBg
    • 判断是否给该行添加背景类名
  • getColumnClass(getColumnClass1,getColumnClass2)
    • 判断是否给该行添加文字类名
  • getWidth
    • 设置每一列宽度
  • getPadding
    • 设置每一列内间距
  • getButtonDisabled
    • 判断按钮是否禁用
  • getButtonDisplay
    • 判断按钮是否隐藏显示
  • handleJudgeOperate
    • 判断该列是否隐藏显示
  • handleListenerScroll
    • 表格滚动事件
  • combinedScroll
    • 右侧侧固定列和表格内容的联动滚动
  • handleClickRow
    • 点击某一行
  • clearChooseData
    • 清除选中的内容

完整代码

commonTable.vue

<template>
  <div
    class="h-common-table-container"
    v-if="data.length > 0"
  >
    <div
      class="common-table-box"
    >
      <div class="common-table-box-wrapper">
        <div class="common-table-header">
          <div
            v-for="(column, index) in columns"
            :key="index"
            :style="[
              { width: getWidth(column.width, column) },
              { textAlign: column.position || 'left' },
              {
                paddingLeft:
                  column.position != 'center' && getPadding(column.paddingLeft)
              },
              {
                paddingRight:
                  column.position == 'right' && getPadding(column.paddingRight)
              },
              {
                display: column.isCheckBox ? 'flex' : '',
                justifyContent: column.isCheckBox ? 'center' : '',
                alignItems: column.isCheckBox ? 'center' : ''
              }
            ]"
            :class="[
              { 'no-padding': column.position == 'center' },
              {
                'padding-right': column.isButton && column.position == 'right'
              },
              { 'column-flex': column.sort },
              { 'column-date': column.isDate }
            ]"
            v-show="handelJudgeFixed(column) && !column.isHidden"
            @click.stop="handleClickSort(column)"
          >
            <el-checkbox
              v-if="column.isCheckBox"
              :disabled="titleChekcDisabled"
              v-model="titleCheck"
              @change="handleChangeCheckAll($event, columns)"
            ></el-checkbox>
            <span class="column-label" v-if="!column.isCheckBox">{{
              column.label
            }}</span>
            <span class="column-label-another" v-if="column.label2">{{
              column.label2
            }}</span>
            <div class="sort-box" v-if="column.sort">
              <span @click.stop="handleSortUp(column)"
                ><img
                  src="@/assets/img/up.png"
                  alt=""
                  v-if="sortValue != 1"/><img
                  src="@/assets/img/upChoose.png"
                  alt=""
                  v-if="sortValue == 1"
              /></span>
              <span @click.stop="handleSortDown(column)"
                ><img
                  src="@/assets/img/down.png"
                  alt=""
                  v-if="sortValue != 2"/><img
                  src="@/assets/img/downChoose.png"
                  alt=""
                  v-if="sortValue == 2"
              /></span>
            </div>
            <el-popover
              placement="right"
              style="display: inline-block"
              v-if="column.question"
              :popper-class="
                $store.getters.windowWidth <= 1024
                  ? 'popover-toolip popover-toolip-wdith'
                  : 'popover-toolip'
              "
              ref="popover"
              trigger="hover"
            >
              <slot name="content"></slot>
              <i class="el-icon-question mgl10 pointer" slot="reference"></i>
            </el-popover>
          </div>
        </div>
        <div
          class="common-table-body common-scroll"
        >
          <div
            class="common-table-body-wrapper"
           
          >
            <div
              v-for="(row, index) in data"
              :key="index + 'row'"
              class="common-table-row"
              @click="handleClickRow(row)"
              :class="[
                chooseList.some(val => val[rowId] === row[rowId])
                  ? 'row-is-active'
                  : '',

                isChoose || isJump ? 'common-table-row-choose' : '',
                
                row.isRequire ? 'row-border-red' : ''
              ]"
            >
              <div
                v-for="(column, indexColumns) in columns"
                :key="indexColumns + 'column'"
                :style="[
                  { width: getWidth(column.width, column, row) },
                  { paddingLeft: getPadding(column.paddingLeft) },
                  { paddingRight: getPadding(column.paddingRight) }
                ]"
                class="cell-box"
                :class="[
                  { 'has-border': column.hasBorder },
                  {
                    'word-center':
                      (column.position == 'center' && !column.isButton) ||
                      (column.position1 == 'center' && column.isButton)
                  },

                  { 'word-center-left': column.position1 == 'center-left' },
                  { 'word-center-right': column.position1 == 'center-right' },
                  { 'button-center-right': column.position1 == 'right' },
                  { 'chart-padding': column.isEcharts },
                  { 'cell-padding': $store.getters.isNormal },
                  { 'cell-padding-no-top': column.noPaddingTop },
                  {
                    'cell-padding-no':
                      $store.getters.windowWidth <= 1024 && column.isButton
                  },
                  { 'cell-padding-min': column.wrap }
                ]"
                v-show="handleJudgeOperate(column, row) && !column.isHidden"
              >
                <div
                  v-if="column.isEcharts"
                  style="width: 100%; position: relative; height: 100%"
                >
                  <div
                    v-myLoading="JSON.stringify(row.echarts) == '{}'"
                    class="echarts-top"
                    v-if="JSON.stringify(row.echarts) == '{}'"
                  ></div>
                  <chart
                    :chart-data="row.echarts"
                    :className="'table-chart'"
                    v-else
                  />
                </div>
                <div v-else-if="column.isOpera" class="row-label">
                  <div>操作</div>
                </div>
                <div
                  v-else-if="column.isSort"
                  class="row-label"
                  :style="[
                    {
                      textAlign: column.position1 || column.position || 'left'
                    }
                  ]"
                >
                  <div>{{ index + 1 }}</div>
                </div>
                <div
                  v-else-if="column.isCheckBox"
                  class="row-label"
                  style="height: 100%; display: flex; justify-content: center"
                >
                  <el-checkbox
                    :disabled="row[checkDisabledLabel] == 1"
                    v-model="row.isCheckd"
                    @change="handleChangeCheck($event, row)"
                  ></el-checkbox>
                </div>
                <div
                  v-else-if="column.isProgress"
                  class="row-label"
                  style="position: relative"
                >
                  <el-progress
                    :text-inside="true"
                    :stroke-width="26"
                    :percentage="row.percentage"
                    :status="row.status"
                    :format="
                      () => {
                        return progressoFormat(row.percentage, row.status);
                      }
                    "
                    :class="
                      $store.getters.windowWidth <= 1024
                        ? 'el-progress-width'
                        : ''
                    "
                  ></el-progress>
                  <span
                    class="progress-label"
                    :class="
                      $store.getters.windowWidth <= 1024
                        ? 'progress-label-width'
                        : ''
                    "
                    v-if="row.percentage == 0"
                    >未上传</span
                  >
                </div>
                <div
                  v-else-if="column.isProgressVal"
                  class="row-label"
                  style="position: relative"
                >
                  <div class="progress-box">
                    <div class="device-num">
                      {{ row.shipmentNum }}/{{ row.totalShipmentNum }}台
                    </div>
                    <div class="progress" v-if="row.percent != '-'">
                      <div
                        :style="[
                          {
                            width: row.percent
                          }
                        ]"
                        class="progress-color"
                      ></div>
                      <div class="val">{{ row.percent }}</div>
                    </div>
                    <div
                      class="progress"
                      style="background: transparent;"
                      v-else
                    >
                      {{ row.percent }}
                    </div>
                  </div>
                </div>
                <div
                    v-else-if="column.isCommonProgress"
                    class="row-label"
                    style="position: relative"
                >
                  <div class="common-progress-box">
                    <div
                        :style="[
                          {
                            width: row[column.value] +'%'
                          }
                        ]"
                        class="progress-bg-color"
                    ></div>
                    <div class="val">{{ row[column.value]+'%' }}</div>
                  </div>
                </div>
                <div
                  v-else-if="column.isUpload"
                  class="row-label row-label-upload"
                >
                  <el-upload
                    v-if="row.key != 'monitor-info' && !row.isHas"
                    action="#"
                    :before-upload="
                      e => {
                        beforeAvatarUpload(e, index, row.key);
                      }
                    "
                    :show-file-list="false"
                    :http-request="
                      e => {
                        handleAvatarSuccess(e, index, row);
                      }
                    "
                    :on-progress="uploadProcess"
                    :disabled="column.disabled"
                  >
                    <el-button
                      class="table-button-upload"
                      type="info"
                      :disabled="column.disabled"
                      :class="buttonClass.tableButton"
                    >
                      <span>上传编辑</span></el-button
                    >
                  </el-upload>
                  <el-button
                    v-else
                    class="table-button-upload"
                    type="info"
                    :disabled="column.disabled"
                    :class="buttonClass.tableButton"
                    @click="$emit('special', row)"
                  >
                    <span>查看编辑</span></el-button
                  >
                </div>
                <div v-else-if="column.isImg" class="row-label">
                  <div
                    style="
                      display: flex;
                      align-items: center;
                      justify-content: center;
                    "
                    v-if="getColumnValue(column, row)"
                  >
                    <img :src="getColumnValue(column, row)" alt="" />
                  </div>
                </div>
                <div
                  v-else-if="column.isButton"
                  class="button-flex-box"
                  :class="[
                    column.position1 == 'center'
                      ? 'button-flex-box-padding'
                      : '',
                    column.nowrap ? 'button-flex-box-nowarp' : '',
                    column.wrap ? 'button-flex-box-wrap' : '',
                    column.isSmall ? 'button-flex-box-small' : '',
                    column.marginR?'button-flex-box-mr':''
                  ]"
                >
                  <!-- <div>
                    <el-button
                      type="success"
                      :disabled="getButtonDisabled(column.disabled,row)"
                      :class="buttonClass.tableButton"
                      class="table-button"
                      @click="column.callback(row)"
                      v-if="getButtonDisplay(column.display, row)"
                      ><span> {{ column.caption }} </span></el-button
                    >
                  </div> -->
<!--                  :class="$store.getters.isNormal ? 'button-Box-height' : ''"-->
                  <div
                    class="button-Box button-Box-height"
                    v-for="(item, parentIndex) in column.buttonList"
                    :key="parentIndex + 'parent'"

                  >
                    <template
                      v-for="({ display, type, callback, caption, disabled,loading },
                      childIndex) in item"
                    >
                      <el-button
                        :disabled="getButtonDisabled(disabled, row)"
                        :key="childIndex + caption + 'child'"
                        v-if="getButtonDisplay(display, row)"
                        :type="type"
                        :loading="loading===undefined?false:loading==row.id"
                        :class="[
                          buttonClass.tableButton,
                          caption.length == 4 ? 'button-four' : ''
                        ]"
                        class="table-button"
                        @click.stop="callback(row, index)"
                        >{{ caption }}
                      </el-button>
                    </template>
                  </div>
                </div>
                <div
                  v-else-if="column.isuploadButton"
                  class="button-flex-box one"
                  :class="
                    column.position == 'center' ? 'button-flex-box-padding' : ''
                  "
                >
                  <div
                    class="button-Box file-button-box"
                    v-for="(item, parentIndex) in column.buttonList"
                    :key="parentIndex + 'parent'"
                    :class="$store.getters.isNormal ? 'button-Box-height' : ''"
                  >
                    <template
                      v-for="({
                        display,
                        type,
                        callback,
                        caption,
                        isUpload,
                        disabled
                      },
                      childIndex) in item"
                    >
                      <template
                        v-if="isUpload && getButtonDisplay(display, row)"
                      >
                        <el-upload
                          :key="childIndex + caption + 'child1'"
                          v-if="row.key == 'project-info' && !row.isHas"
                          action="#"
                          :before-upload="
                            e => {
                              beforeAvatarUpload(e, index, row.key);
                            }
                          "
                          :show-file-list="false"
                          :http-request="
                            e => {
                              handleAvatarSuccess(e, index, row);
                            }
                          "
                          :on-progress="uploadProcess"
                          :disabled="column.disabled"
                        >
                          <el-button
                            class="table-button-upload"
                            type="info"
                            :disabled="column.disabled"
                            :class="buttonClass.tableButton"
                          >
                            <span>{{ caption }}</span></el-button
                          >
                        </el-upload>
                        <el-button
                          v-else
                          :key="childIndex + caption + 'child2'"
                          class="table-button-upload"
                          type="info"
                          :disabled="column.disabled"
                          :class="buttonClass.tableButton"
                          @click="$emit('special', row)"
                        >
                          <span>查看</span></el-button
                        >
                      </template>
                      <el-button
                        :disabled="getButtonDisabled(disabled, row)"
                        :key="childIndex + caption + 'child'"
                        v-else-if="!isUpload && getButtonDisplay(display, row)"
                        :type="type"
                        :class="[
                          buttonClass.tableButton,
                          caption.length == 4 ? 'button-four' : ''
                        ]"
                        class="table-button"
                        @click.stop="callback(row, index)"
                        >{{ caption }}
                      </el-button>
                    </template>
                  </div>
                </div>
                <div
                  v-else-if="column.isClick"
                  style="cursor: pointer"
                  class="row-label"
                  @click="column.callback(row, column)"
                >
                  <div
                    :style="[
                      {
                        textAlign: column.position1 || column.position || 'left'
                      }
                    ]"
                    :class="[
                      { 'word-bold': column.wordBold },
                      { 'word-font-default': column.wordFontDefault },
                      { 'word-blue': getFontColorIsBlue(column, row) },
                      column.value1 ? 'no-warp' : 'one-line',
                      getColumnBg(column, row),
                      getColumnClass(column, row)
                    ]"
                  >
                    <common-tooltip
                      :twoLine="column.isTooltip && column.value1 != undefined"
                      :className="'ellipsisName' + indexColumns"
                      :refName="'toolitipName' + indexColumns"
                      :content="getColumnValue(column, row)"
                      :disabled="!column.isTooltip"
                    >
                    </common-tooltip>
                  </div>
                  <div
                    v-if="column.value1"
                    :style="[{ textAlign: column.position || 'left' }]"
                    :class="[
                      { 'word-bold': column.wordBold1 },
                      { 'row-label-color-default': column.wordColorDefault1 },
                      { 'word-blue': getFontColorIsBlue1(column, row) },
                      column.value3 ? 'two-line-mt' : '',
                      getColumnBg(column, row),
                      getColumnClass1(column, row)
                    ]"
                    class="two-line"
                  >
                    <common-tooltip
                      :twoLine="column.isTooltip1"
                      :className="'ellipsisNameTwo' + indexColumns"
                      :refName="'toolitipNameTwo' + indexColumns"
                      :content="getColumnValue1(column, row)"
                      :disabled="!column.isTooltip1"
                    >
                    </common-tooltip>
                  </div>
                  <div
                    v-if="column.value3"
                    :style="[{ textAlign: column.position || 'left' }]"
                    :class="[
                      { 'word-bold': column.wordBold2 },
                      { 'word-blue': getFontColorIsBlue2(column, row) },
                      getColumnBg(column, row),
                      getColumnClass2(column, row)
                    ]"
                    class="two-line two-line-mts"
                  >
                    <common-tooltip
                      :twoLine="column.isTooltip2"
                      :className="'ellipsisNameThree' + indexColumns"
                      :refName="'toolitipNameThree' + indexColumns"
                      :content="getColumnValue3(column, row)"
                      :disabled="!column.isTooltip2"
                    >
                    </common-tooltip>
                  </div>
                </div>
                <template v-else-if="column.isbadge">
                  <el-badge
                    :value="row.badgeNum > 99 ? 99 : row.badgeNum"
                    class="item"
                    :hidden="row.badgeNum == 0"
                  >
                    {{ getColumnValue(column, row) }}
                  </el-badge>
                </template>
                <div
                  v-else
                  class="row-label"
                  :class="column.isDate ? 'row-label-date' : ''"
                >
                  <div
                    :style="[
                      {
                        textAlign: column.position1 || column.position || 'left'
                      }
                    ]"
                    :class="[
                      { 'word-bold': column.wordBold },
                      { 'word-font-default': column.wordFontDefault },
                      { 'word-blue': getFontColorIsBlue(column, row) },
                      column.value1 ? 'no-warp' : 'one-line',
                      column.wordColor ? 'row-label-color' : '',
                      column.isDeviceNum
                        ? column.boxBg(row) == 'danger'
                          ? 'row-label-num-style row-label-num-style-bg'
                          : 'row-label-num-style'
                        : '',
                      column.isCircle ? 'row-label-circle' : '',
                      getColumnBg(column, row),
                      getColumnClass(column, row)
                    ]"
                  >
                    <common-tooltip
                      :twoLine="column.isTooltip && column.value1 != undefined"
                      :className="'ellipsisName' + indexColumns"
                      :refName="'toolitipName' + indexColumns"
                      :content="getColumnValue(column, row)"
                      :disabled="!column.isTooltip"
                    >
                    </common-tooltip>
                  </div>
                  <div
                    v-if="column.value1"
                    :style="[{ textAlign: column.position || 'left' }]"
                    :class="[
                       {'row-label-color':column.wordColor1},
                      { 'word-bold': column.wordBold1 },
                      { 'row-label-color-default': column.wordColorDefault1 },
                      { 'word-blue': getFontColorIsBlue1(column, row) },
                      column.value3 ? 'two-line-mt' : '',
                      getColumnBg(column, row),
                      getColumnClass1(column, row)
                    ]"
                    class="two-line"
                  >
                    <common-tooltip
                      :twoLine="column.isTooltip1"
                      :className="'ellipsisNameTwo' + indexColumns"
                      :refName="'toolitipNameTwo' + indexColumns"
                      :content="getColumnValue1(column, row)"
                      :disabled="!column.isTooltip1"
                    >
                    </common-tooltip>
                  </div>
                  <div
                    v-if="column.value3"
                    :style="[{ textAlign: column.position || 'left' }]"
                    :class="[
                      { 'word-bold': column.wordBold2 },
                      { 'word-blue': getFontColorIsBlue2(column, row) },
                      getColumnBg(column, row),
                      getColumnClass2(column, row)
                    ]"
                    class="two-line two-line-mts"
                  >
                    <common-tooltip
                      :twoLine="column.isTooltip2"
                      :className="'ellipsisNameThree' + indexColumns"
                      :refName="'toolitipNameThree' + indexColumns"
                      :content="getColumnValue3(column, row)"
                      :disabled="!column.isTooltip2"
                    >
                    </common-tooltip>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div
      class="common-table-box-fixed"
      v-if="buttonList.length > 0 && data.length > 0 && handelJudgeFixed()"
      :style="{ width: getWidth(fixedWidth) }"
    >
      <div class="common-table-fixed-header" style="width: 100%">
        {{ fixedLabel }}
      </div>
      <div
        class="common-table-fixed-box common-scroll"
        :class="$store.getters.windowWidth <= 1024 ? 'common-scroll-width' : ''"
      >
        <div class="common-table-fixed-wrapper">
          <div
            class="common-table-fixed-header-body"
            v-for="(row, index) in data"
            :key="index + 'fixed'"
            :class="[
              chooseList.some(val => val[rowId] === row[rowId])
                ? 'fixed-is-active'
                : '',

              isChoose || isJump ? 'common-table-fixed-row-choose' : '',
              isOne ? 'common-table-fixed-header-body-flex' : ''
            ]"
            @click.stop="handleClickRow(row)"
          >
            <div
              class="button-Box"
              v-for="(item, parentIndex) in buttonList"
              :key="parentIndex + 'parent'"
              :class="$store.getters.isNormal ? 'button-Box-height' : ''"
            >
              <template
                v-for="({ display, type, callback, caption },
                childIndex) in item"
              >
                <el-button
                  :key="childIndex + caption + 'child'"
                  v-if="getButtonDisplay(display, row)"
                  :type="type"
                  :class="[
                    buttonClass.tableButton,
                    caption.length == 4 ? 'button-four' : ''
                  ]"
                  class="table-button"
                  @click.stop="callback(row, index)"
                  >{{ caption }}
                </el-button>
              </template>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import chart from "@/components/echarts/index";
import commonSearchMixin from "@/mixins/search";
import commonTooltip from "@/components/commonTooltip/index";
import { uploadImgProgress } from "@/api/district";

export default {
  name: "HTable",
  mixins: [commonSearchMixin],
  props: {
    data: Array,
    columns: Array,
    isJump: {
      type: Boolean,
      default: false
    },
    isChoose: {
      type: Boolean,
      default: false
    },
    needJudgeChooseStatus: {
      type: Function,
      default: () => {
        return false;
      }
    },
    buttonList: {
      type: Array,
      default: () => {
        return [];
      }
    },
    fixedWidth: {
      type: Number,
      default: 85 * 2
    },
    fixedLabel: {
      type: String,
      default: "操作"
    },
    rowId: {
      type: String,
      default: "id"
    },
    isScroll: {
      type: Boolean,
      default: false
    },
    isOne: {
      type: Boolean,
      default: false
    },
   
    checkDisabledLabel: {
      type: String,
      default: "needAttest"
    },
    titleCheck: {
      type: Boolean,
      default: false
    },
    titleChekcDisabled: {
      type: Boolean,
      default: false
    },
    chooseNumber: {
      type: [Number, String],
      default: 5
    },
    chooseTooltip: {
      type: String,
      default: "最多支持选择5条数据进行数据对比!"
    }
  },
  data() {
    return {
      chooseList: [],
      isFlag: false,
      sortUp: false,
      sortdown: false,
      sortValue: 0
      // isFlag: false,
    };
  },
  watch: {
    data: {
      handler(val) {
        if (val.length > 0) {
          if (!this.isFlag) {
            this.isFlag = true;
            this.$nextTick(() => {
              var bodyBox = document.querySelector(".common-table-body");
              if (bodyBox) {
                this.handleListenerScroll();
              }
            });
          }
        } else {
          this.isFlag = false;
        }
      },
      immediate: true,
      deep: true
    },
    windowWidth: {
      handler(val) {
        this.$nextTick(() => {
          var bodyBox = document.querySelector(".common-table-body");
          if (bodyBox) {
            this.handleListenerScroll();
          }
        });
      },
      immediate: true
    }
  },
  components: { chart, commonTooltip },
  computed: {
    windowWidth() {
      return this.$store.getters.windowWidth;
    }
  },
  methods: {
    handleClickSort(column) {
      if (column.sort) {
        if (this.sortValue == 2) {
          this.sortValue = 0;
          this.$emit("sort", "none", "");
        } else if (this.sortValue == 1) {
          this.$emit("sort", "down", column.value);
          this.sortValue = 2;
        } else {
          this.$emit("sort", "up", column.value);
          this.sortValue = 1;
        }
      }
    },
    handleSortDown(column) {
      this.$emit("sort", "down", column.value);
      this.sortValue = 2;
    },
    handleSortUp(column) {
      this.$emit("sort", "up", column.value);
      this.sortValue = 1;
    },
    handleChangeCheck(val, row) {
      this.$emit("checked", row);
    },
    handleChangeCheckAll() {
      this.$emit("checkedAll");
    },
    progressoFormat(percentage, status) {
      if (percentage === 100) {
        if (status == "success") {
          return "已完成";
        } else if (status == "exception") {
          return "上传失败";
        } else if (status == "exception") {
          return `${percentage}%`;
        }
      } else if (percentage === 0) {
        return ``;
      } else {
        return `${percentage}%`;
      }
    },
    uploadProcess(event, file, fileList) {},
    handleAvatarSuccess(res, index, row) {
      const isJPG =
        res.file.type === "image/jpeg" || res.file.type === "image/png";
      if (row.key == "project-info" && !isJPG) {
        this.$commonMessage.message({
          type: "warning",
          message: "请上传PNG或JPG格式的图片!"
        });
        return false;
      }
      // 以下是向后端识别图片接口传递file文件
      var formData = new FormData();
      formData.append("file", res.file); // 注意是传file.raw
      const uploadProgressEvent = progressEvent => {
        let percent = ((progressEvent.loaded / progressEvent.total) * 100) | 0;
        res.onProgress({ percent: percent, status: "" });
        this.$emit("progress", { percent: percent, status: "warning" }, index);
      };
      uploadImgProgress(formData, uploadProgressEvent)
        .then(response => {
          this.$emit(
            "success",
            {
              percent: 100,
              status: "success",
              data: response,
              row: row
            },
            index
          );
          res.onProgress({ percent: 100, status: "success" }, index);
        })
        .catch(() => {
          res.onProgress({ percent: 100, status: "exception" });
          this.$emit(
            "fail",
            { percent: 100, status: "exception", row: row },
            index
          );
        });
    },
    beforeAvatarUpload(file, index, key) {
      const isJPG = file.type === "image/jpeg" || file.type === "image/png";

      if (key == "project-info" && !isJPG) {
        return false;
      }
      this.$emit("upload", index);
      const isLtM = file.size / 1024 / 1024 >= 1;
      if (isJPG) {
        return new Promise(resolve => {
          // 小于1M 不压缩
          if (!isLtM) {
            resolve(file);
          }
          // 压缩到400KB,这里的400就是要压缩的大小,可自定义
          this.imageConversion.compressAccurately(file, 400).then(res => {
            resolve(res);
          });
          //compressAccurately有多个参数时传入对象
          //imageConversion.compressAccurately(file, {
          // size: 1024, //图片大小压缩到1024kb
          // width:1280 //宽度压缩到1280
          //}).then(res => {
          //resolve(res)
          //})
        });
      } else {
        return true;
      }
    },
    getFontColorIsBlue(column, row) {
      let { fontColorIsBlue } = column;
      if (row) {
        if (fontColorIsBlue && typeof fontColorIsBlue === "function") {
          return fontColorIsBlue(row);
        } else {
          return fontColorIsBlue;
        }
      }
    },
    getFontColorIsBlue1(column, row) {
      let { fontColorIsBlue1 } = column;
      if (row) {
        if (fontColorIsBlue1 && typeof fontColorIsBlue1 === "function") {
          return fontColorIsBlue1(row);
        } else {
          return fontColorIsBlue1;
        }
      }
    },
    getFontColorIsBlue2(column, row) {
      let { fontColorIsBlue2 } = column;
      if (row) {
        if (fontColorIsBlue2 && typeof fontColorIsBlue2 === "function") {
          return fontColorIsBlue2(row);
        } else {
          return fontColorIsBlue2;
        }
      }
    },
    getProgressSuccess(column, row) {
      if (row.percentage == 100) {
        return "success";
      }
    },
    getColumnValue(column, row) {
      let { value, valueFormatter, unit, value2 } = column;
      if (row) {
        if (valueFormatter && typeof valueFormatter === "function") {
          return valueFormatter(row, value);
        } else {
          if (value2) {
            return (
              row[value] +
              (row[value] !== undefined && row[value] !== null && unit
                ? unit
                : "") +
              "-" +
              row[value2]
            );
          } else {
            return (
              (row[value] !== undefined && row[value] !== null
                ? row[value]
                : "-") + (row[value] && unit ? unit : "")
            );
          }
        }
      }
    },
    getColumnBg(column, row) {
      let { bgFormatter } = column;
      if (row) {
        if (bgFormatter && typeof bgFormatter === "function") {
          return bgFormatter(row);
        }
        return "";
      }
    },
    getColumnClass(column, row) {
      let { fontColorIsRed } = column;
      if (row) {
        if (fontColorIsRed && typeof fontColorIsRed === "function") {
          return fontColorIsRed(row);
        }
        return "";
      }
    },
    getColumnClass1(column, row) {
      let { fontColorIsRed1 } = column;
      if (row) {
        if (fontColorIsRed1 && typeof fontColorIsRed1 === "function") {
          return fontColorIsRed1(row);
        }
        return "";
      }
    },
    getColumnClass2(column, row) {
      let { fontColorIsRed1 } = column;
      if (row) {
        if (fontColorIsRed1 && typeof fontColorIsRed1 === "function") {
          return fontColorIsRed1(row);
        }
        return "";
      }
    },
    getColumnValue1(column, row) {
      let { value1, valueFormatter1, unit1 } = column;
      if (row) {
        if (valueFormatter1 && typeof valueFormatter1 === "function") {
          return valueFormatter1(row, value1);
        } else {
          return (
            (row[value1] ? row[value1] : "") +
            (row[value1] && unit1 ? unit1 : "")
          );
        }
      }
    },
    getColumnValue3(column, row) {
      let { value3, valueFormatter3, unit2 } = column;
      if (row) {
        if (valueFormatter3 && typeof valueFormatter3 === "function") {
          return valueFormatter3(row, value3);
        } else {
          return (
            (row[value3] ? row[value3] : "") +
            (row[value3] && unit2 ? unit2 : "")
          );
        }
      }
    },
    getWidth(val, column, row) {
      if (!this.handelJudgeFixed()) {
        if (column && column.addWidth) {
          if (this.$store.getters.windowWidth <= 1024) {
            return (((column.addWidth / 1024) * 1920) / 3840) * 2 * 100 + "vw";
          } else {
            return (column.addWidth / 3840) * 2 * 100 + "vw";
          }
        }
      }
      if (this.$store.getters.windowWidth <= 1024) {
        return (((val / 1024) * 1920) / 3840) * 2 * 100 + "vw";
      } else {
        return (val / 3840) * 2 * 100 + "vw";
      }
    },
    
    
    getPadding(val = 40) {
      if (this.$store.getters.windowWidth <= 1024) {
        return (((val / 1024) * 1920) / 3840) * 2 * 100 + "vw";
      } else {
        return (val / 3840) * 2 * 100 + "vw";
      }
    },
    getButtonDisabled(display, row) {
      let result = false;
      if (typeof display === "boolean") {
        result = display;
      } else if (typeof display === "function") {
        result = display(row);
      }
      return result;
    },
    getButtonDisplay(display, row) {
      let result = true;
      if (typeof display === "boolean") {
        result = display;
      } else if (typeof display === "function") {
        result = display(row);
      }
      return result;
    },
    handleJudgeOperate(column, row) {
      if (column.isOpera) {
        return this.handelJudgeFixed();
      } else {
        return true;
      }
    },
    handelJudgeFixed(column) {
      if (column && !column.isOpera) {
        return true;
      }
      let result = false;
      for (let k = 0; k < this.buttonList.length; k++) {
        if (this.buttonList[k].some(row => row.display !== undefined)) {
          result = this.buttonList[k].some(row => row.display !== undefined);
        }
      }
      if (result) {
        let flag = false;
        for (let i = 0; i < this.buttonList.length; i++) {
          for (let j = 0; j < this.buttonList[i].length; j++) {
            if (typeof this.buttonList[i][j].display === "boolean") {
              if (this.buttonList[i][j].display) {
                flag = this.buttonList[i][j].display;
              }
            } else if (typeof this.buttonList[i][j].display === "function") {
              if (
                !flag &&
                this.data.some(el => {
                  return this.buttonList[i][j].display(el);
                })
              ) {
                flag = true;
              }
            }
          }
        }
        return flag;
      } else {
        return true;
      }
    },
    handleListenerScroll() {
      let that = this;
      var bodyBox = document.querySelector(".common-table-body");

      function bindEventLeft() {
        bodyBox.addEventListener("scroll", leftScroll);
      }

      function removeEventLeft() {
        bodyBox.removeEventListener("scroll", leftScroll);
      }

      function leftScroll() {
        var a = bodyBox.scrollTop;
        if (that.isScroll) {
          that.$emit("scroll", a);
        }
      }

      bodyBox.addEventListener("mouseover", bindEventLeft);
      bodyBox.addEventListener("mouseLeave", removeEventLeft);
    },
    combinedScroll() {
      let that = this;
      // 获取元素
      var bodyBox = document.querySelector(".common-table-body");
      var fixedBox = document.querySelector(".common-table-fixed-box");

      // 绑定body的滚动事件
      function bindEventLeft() {
        removeEventRight(); //关键点-先解绑右边
        bodyBox.addEventListener("scroll", leftScroll);
      }

      // 绑定fixed的滚动事件
      function bindEventRight() {
        removeEventLeft(); //关键点-先解绑左边
        fixedBox.addEventListener("scroll", rightScroll);
      }

      //   解绑body的滚动事件
      function removeEventLeft() {
        bodyBox.removeEventListener("scroll", leftScroll);
      }

      //   解绑fixed的滚动事件

      function removeEventRight() {
        fixedBox.removeEventListener("scroll", rightScroll);
      }

      // body滚动时候,fixed同步
      function leftScroll() {
        var a = bodyBox.scrollTop;
        fixedBox.scrollTop = a;
        if (that.isScroll) {
          that.$emit("scroll", a);
        }
      }

      // fixed滚动时候,body同步
      function rightScroll() {
        var a = fixedBox.scrollTop;
        bodyBox.scrollTop = a;
        if (that.isScroll) {
          that.$emit("scroll", a);
        }
      }

      bodyBox.addEventListener("mouseover", bindEventLeft);
      fixedBox.addEventListener("mouseover", bindEventRight);
    },
    handleClickRow(value) {
      if (!this.isChoose && !this.isJump) {
        return;
      }
      if (this.isChoose) {
        if (this.needJudgeChooseStatus(value)) {
          this.$commonMessage.message({
            type: "info",
            message: this.needJudgeChooseStatus(value)
          });
          return;
        }
        let type = 'add'
        // 增加
        if (
          !this.chooseList.some(row => row[this.rowId] === value[this.rowId])
        ) {
          if(this.chooseNumber != 'unlimited') {
            if (this.chooseList.length == this.chooseNumber) {
              this.$commonMessage.message({
                type: "info",
                message: this.chooseTooltip
              });
              return;
            }
          }
          type = 'add'
          this.chooseList.push(value);
        } else {
          type = 'delete'
          this.chooseList.splice(
            this.chooseList.findIndex(
              row => row[this.rowId] === value[this.rowId]
            ),
            1
          );
        }
        this.$emit("getChooseData", this.chooseList,type, value[this.rowId]);
      } else {
        this.$emit("jump", value);
      }
    },
    clearChooseData() {
      this.chooseList = [];
      this.$emit("getChooseData", this.chooseList);
    }
  },
  mounted() {
    this.$nextTick(() => {
      var bodyBox = document.querySelector(".common-table-body");
      if (bodyBox) {
        this.handleListenerScroll();
      }
    });
  }
};
</script>

<style lang="scss" scoped>
.h-common-table-container {
  flex-direction: column;
}
</style>

<style lang="scss"></style>

index.scss

.h-common-table-container {
  position: relative;
  height: calc(100% - 3.125vw);
  display: flex;
  flex-direction: column;

 
  .common-table-box {
    background-color: transparent;
    border-radius: 0;
    border: none;
    @include font_color("themeColor");
    font-size: vw(14 * 2);
    margin-bottom: vh(40 * 2);
    height: 100%;
    width: 100%;
    overflow-y: hidden;
    overflow-x: auto;
    padding-bottom: vh(6 * 2);

    &.common-table-box-min {
      height: vh(288 * 2);
      padding-bottom: 0;
      margin-bottom: 0;
    }

    &.common-table-box-min-height {
      height: vh(322 * 2);
      padding-bottom: 0;
      margin-bottom: 0;
    }

    &::-webkit-scrollbar {
      width: vw(6 * 2);
      height: vw(6 * 2);
    }

    /*定义滑块 内阴影+圆角*/
    &::-webkit-scrollbar-thumb {
      background-color: #dfdfdf;
      border-radius: vw(3 * 2);
    }

    &::-webkit-scrollbar-track {
      background: #fff;
      border-radius: vw(3 * 2);
    }

    .common-table-box-wrapper {
      width: 100%;
      height: 100%;
      display: flex;
      flex-direction: column;
    }

    .common-table-header {
      height: vh(25 * 2);
      display: flex;
      margin-bottom: vh(20 * 2);
      font-size: vw(18 * 2);
      color: #000;
      font-weight: 500;

      div {
        height: 100%;
        text-align: center;
        flex-shrink: 0;
        padding-left: vw(20 * 2);

        &.no-padding {
          padding-left: 0;
        }

        &.padding-right {
          padding-right: vw(50 * 2) !important;
        }

        &.column-flex {
          display: inline-flex;
          align-items: center;
          justify-content: center;
          cursor: pointer;
        }

        &.column-date {
          padding-left: vw(35 * 2) !important;
        }

        .sort-box {
          display: inline-flex;
          flex-direction: column;
          padding-left: 0;
          align-items: center;
          justify-content: center;

          span {
            width: vw(12 * 2);
            margin-bottom: vh(1 * 2);
            cursor: pointer;
            // height: vw(8*2);
            display: flex;
            align-items: center;
            justify-content: center;

            &:last-child {
              margin-bottom: 0;
            }

            img {
              width: 100%;
              height: 100%;
            }
          }
        }

        .el-checkbox {
          width: fit-content;
          padding: 0 vw(20 * 2);
          display: inline-flex;
          align-items: center;
          height: 100%;
          font-size: vw(12 * 2);
          margin-right: 0;

          .el-checkbox__label {
            font-size: vw(12 * 2);
            padding-left: vw(13 * 2);
            @include font_color("themeColor");
            display: flex;
            align-items: center;
            height: 100%;
          }

          .el-checkbox__input {
            display: inline-flex;
            align-items: center;
            justify-content: center;

            &.is-checked {
              .el-checkbox__inner {
                background: url("~@/assets/img/checkedImg.png");
                @include checkBox-style(vw(16 * 2));
                border: vh(1 * 2) solid #007cdb;
              }

              + .el-checkbox__label {
                @include font_color("themeColor");
              }
            }

            &.is-indeterminate {
              .el-checkbox__inner {
                background: url("~@/assets/img/checkedImg.png");
                @include checkBox-style(vw(16 * 2));
                border: vh(1 * 2) solid #007cdb;
              }
            }

            &.is-disabled {
              .el-checkbox__inner {
                background: none;
                background-color: rgba(192, 196, 204, 0.5);
                @include checkBox-style(vw(16 * 2));
                border: vh(1 * 2) solid #c0c4cc;
                box-sizing: border-box;
              }
            }

            .el-checkbox__inner {
              background: url("~@/assets/img/noCheckImg.png");
              @include checkBox-same-style(vw(16 * 2));
            }
          }
        }

        .column-label-another {
          color: #797979;
        }
      }
    }

    .common-table-body {
      flex: 1;
      width: 100%;

      &.common-table-body-min {
        height: vh(262 * 2);
      }

      &.common-table-body-min-height {
        height: min_vh(262 * 2) !important;
      }

      .common-table-body-wrapper {
        height: fit-content;
        padding-right: vw(36 * 2);

        &.common-table-body-wrapper-no-padding {
          padding-right: 0;
        }

        &.common-table-body-wrapper-min-padding {
          padding-right: vw(20 * 2);
        }
      }

      .common-table-row {
        display: flex;
        background: #fff;
        margin-bottom: vh(20 * 2);
        height: vh(100 * 2);
        border-radius: vw(10 * 2);
        position: relative;
        box-sizing: border-box;
        font-size: vw(18 * 2);

        &.common-table-row-choose {
          cursor: pointer;
        }

        &.row-border-green {
          &:before {
            width: vw(10 * 2);
            height: 100%;
            content: "";
            @include background_color("alarmGreenBgColor");
            border-radius: vw(10 * 2) 0 0 vw(10 * 2);
            position: absolute;
            left: 0;
          }
        }

        &.row-border-yellow {
          &:before {
            width: vw(10 * 2);
            height: 100%;
            content: "";
            @include background_color("alarmYellowBgColor");
            border-radius: vw(10 * 2) 0 0 vw(10 * 2);
            position: absolute;
            left: 0;
          }
        }

        &.row-border-orange {
          &:before {
            width: vw(10 * 2);
            height: 100%;
            content: "";
            @include background_color("alarmHappenBgColor");
            border-radius: vw(10 * 2) 0 0 vw(10 * 2);
            position: absolute;
            left: 0;
          }
        }

        &.row-border-red {
          border-color: #ff4949 !important;
        }

        &.row-border-warning-red {
          border: vh(2 * 2) solid #ff452f !important;
        }

        &.row-is-active {
          border: vh(2 * 2) solid #71807b;

          &:before {
            width: vw(10 * 2);
            height: 100%;
            content: "";
            background: #808c87;
            border-radius: vw(10 * 2) 0 0 vw(10 * 2);
            position: absolute;
            left: 0;
          }
        }

        &.common-table-row-min-height {
          height: vh(50 * 2);
        }

        .button-flex-box {
          height: 100%;
          position: relative;
          width: 100%;
          border-left: none !important;
          display: flex;
          align-items: center;
          box-sizing: border-box;
          justify-content: flex-end;

          &.button-flex-box-padding {
            padding-right: 0;

            &.button-flex-box-wrap {
              // flex-wrap: wrap;
              flex-direction: column;
              align-items: flex-end;
            }
          }

          &.button-flex-box-wrap {
            // flex-wrap: wrap;
            flex-direction: column;
            align-items: flex-end;

            .button-Box-height {
              height: vh(32 * 2);

              + .button-Box-height {
                margin-left: 0;
              }

              &:first-child {
                margin-bottom: vh(10 * 2);
              }

              &:last-child {
                margin-bottom: vh(0 * 2);
              }

              .el-button {
                width: vw(82 * 2);
                height: vh(32 * 2);

                + .el-button {
                  margin-left: vw(10 * 2);
                }
              }
            }
          }

          &.button-flex-box-small {
            align-items: center;

            .button-Box-height {
              height: vh(32 * 2);

              + .button-Box-height {
                margin-left: 0;
              }

              .el-button {
                width: vw(82 * 2);
                height: vh(32 * 2);

                + .el-button {
                  margin-left: vw(10 * 2);
                }
              }
            }
          }

          &.one {
            .button-Box-height {
              min-width: min_vw(112 * 2);

              .el-upload {
                margin: 0;
              }
            }
          }

          .el-button {
            width: vw(112 * 2);
            height: vh(42 * 2);
            border-radius: vw(21 * 2);
            font-size: vw(20 * 2);
            border: none;
            outline: none;

            span {
              height: vh(24 * 2);
              display: inline-flex;
              align-items: center;
            }

            &.el-button--primary {
              @include background_color("confirmButtonBgColor");
            }

            &.el-button--info {
              @include background_color("infobtnBgColor");
            }

            &.el-button--success {
              @include background_color("confirmButtonBgColor");
            }

            &.el-button--danger {
              @include background_color("dangerbtnBgColor");
            }

            + .el-button {
              margin-left: vw(20 * 2);
            }
          }
        }

        .button-Box {
          height: vh(42 * 2);

          display: flex;
          justify-content: flex-end;
          margin-bottom: 0;

          + .button-Box {
            margin-left: vw(20 * 2);

            &.file-button-box {
              margin-left: vw(20 * 2);

              .el-button {
                margin-left: 0;
              }
            }

            // .el-button {
            //   margin-left: vw(20 * 2);
            // }

            margin-bottom: 0;
          }

          &.button-Box-height {
            height: vh(42 * 2);

            .el-button {
              height: vh(42 * 2);
              width: vw(112 * 2);
              padding: 0;

              &.button-four {
                width: vw(112 * 2);
              }
            }
          }

          .el-button {
            flex-shrink: 0;
            border: none;
          }
        }

        .cell-box {
          padding: vh(10 * 2) vw(20 * 2);
          flex-shrink: 0;

          &.cell-padding {
            padding: vh(20 * 2) vw(20 * 2);
          }

          &.cell-padding-min {
            padding-top: vh(13 * 2);
            padding-bottom: vh(13 * 2);
          }

          &.cell-padding-no-top {
            padding: vw(8 * 2) vw(20 * 2);
          }

          &.has-border {
            position: relative;

            &:before {
              content: "";
              width: vw(1 * 2);
              height: vh(21 * 2);
              position: absolute;
              right: 0;
              top: 0;
              bottom: 0;
              margin: auto;
              @include background_color("borderColor");
            }
          }

          &.word-center {
            display: flex;
            align-items: center;
            justify-content: center;
          }

          &.word-center-left {
            display: flex;
            align-items: center;
          }

          &.word-center-right {
            display: flex;
            align-items: center;

            span {
              text-align: right;
            }
          }

          &.button-center-right {
            justify-content: flex-end;
          }

          &.chart-padding {
            padding: vw(6 * 2) vw(20 * 2);
          }

          .row-label {
            width: 100%;

            div {
              &.one-line {
                font-size: vw(18 * 2);
                @include text-overflow-two;

                .none-label {
                  width: fit-content;
                  white-space: nowrap;
                }

                span {
                  @include text-overflow-two;
                }
              }

              &.no-warp {
                font-size: vw(16 * 2);
                @include text-overflow;

                span {
                  @include text-overflow;
                  width: 100%;
                  display: inline-block;
                }
              }

              &.two-line {
                font-size: vw(18 * 2);
                margin-top: vh(10 * 2);
                color: #797979;
                height: vh(25*2);
                @include text-overflow;

                &.two-line-mt {
                  margin-top: vh(7 * 2);
                }

                &.two-line-mts {
                  margin-top: vh(5 * 2);
                }

                .none-label {
                  width: fit-content;
                  white-space: nowrap;
                }

                span {
                  width: 100%;
                  display: inline-block;
                  @include text-overflow;
                }
              }

              &.word-bold {
                font-family: "PingFangSC-Semibold";
              }

              &.word-red {
                color: #ff452f;
              }

              &.word-blue {
                color: #2b5ae8;
              }

              &.row-label-bg {
                width: vw(45 * 2);
                height: vh(20 * 2);
                display: flex;
                align-items: center;
                justify-content: center;
                color: #fff;
                border-radius: vw(10 * 2);

                &.row-label-green {
                  @include background_color("alarmMsgBgColor");
                }

                &.row-label-yellow {
                  @include background_color("alarmYellowBgColor");
                }

                &.row-label-orange {
                  @include background_color("alarmRedBgColor");
                }

                &.row-label-gray {
                  @include background_color("pageBoxBgColor");
                }
              }

              &.word-bold {
                font-family: "PingFangSC-Semibold";
              }

              &.progress-box {
                width: 100%;
                display: flex;
                flex-direction: column;
                display: flex;
                flex-direction: column;
                align-items: center;

                .device-num {
                  width: 100%;
                  color: #000;
                  text-align: center;
                  font-size: vw(16 * 2);
                  margin-bottom: vh(6 * 2);
                }

                .progress {
                  width: vw(82 * 2);
                  height: vh(32 * 2);
                  position: relative;
                  border-radius: vw(21 * 2);

                  background: #b5c0bc;
                  overflow: hidden;
                  display: flex;
                  align-items: center;
                  justify-content: center;

                  .progress-color {
                    position: absolute;
                    left: 0;
                    height: 100%;
                    top: 0;
                    background: #2b5ae8;
                  }

                  .val {
                    font-size: vw(18 * 2);
                    color: #ffffff;
                    position: absolute;
                    left: 0;
                    right: 0;
                    top: 0;
                    bottom: 0;
                    margin: auto;
                    width: fit-content;
                    height: fit-content;
                  }
                }
              }
              &.common-progress-box {
                display: flex;
                align-items: center;
                justify-content: center;
                height: vh(50*2);
                background: #EEF0EF;
                border-radius: vw(5*2);
                position: relative;
                overflow: hidden;
                .progress-bg-color {
                  position: absolute;
                  left: 0;
                  height: 100%;
                  top: 0;
                  background: #B5C0BC;
                }
                .val {
                  font-size: vw(18 * 2);
                  color: #000;
                  position: absolute;
                  left: 0;
                  right: 0;
                  top: 0;
                  bottom: 0;
                  margin: auto;
                  width: fit-content;
                  height: fit-content;
                }
              }
              img {
                width: vw(22 * 2);
                height: vw(22 * 2);
                object-fit: contain;
                display: block;
              }
            }

            .el-checkbox {
              width: fit-content;
              padding: 0 vw(20 * 2);
              display: inline-flex;
              align-items: center;
              height: 100%;
              font-size: vw(12 * 2);
              margin-right: 0;

              .el-checkbox__label {
                font-size: vw(12 * 2);
                padding-left: vw(13 * 2);
                @include font_color("themeColor");
                display: flex;
                align-items: center;
                height: 100%;
              }

              .el-checkbox__input {
                display: inline-flex;
                align-items: center;
                justify-content: center;

                &.is-checked {
                  .el-checkbox__inner {
                    background: url("~@/assets/img/checkedImg.png");
                    @include checkBox-style(vw(16 * 2));
                    border: vh(1 * 2) solid #007cdb;
                  }

                  + .el-checkbox__label {
                    @include font_color("themeColor");
                  }
                }

                &.is-indeterminate {
                  .el-checkbox__inner {
                    background: url("~@/assets/img/checkedImg.png");
                    @include checkBox-style(vw(16 * 2));
                    border: vh(1 * 2) solid #007cdb;
                  }
                }

                &.is-disabled {
                  .el-checkbox__inner {
                    background: none;
                    background-color: rgba(192, 196, 204, 0.5);
                    @include checkBox-style(vw(16 * 2));
                    border: vh(1 * 2) solid #c0c4cc;
                  }
                }

                .el-checkbox__inner {
                  background: url("~@/assets/img/noCheckImg.png");
                  @include checkBox-same-style(vw(16 * 2));
                }
              }
            }

            &.row-label-date {
              width: 100%;
              height: vh(36 * 2);
              border-radius: vw(21 * 2);
              border: vh(1 * 2) solid #797979;
              display: inline-flex;
              align-items: center;
              justify-content: center;
              font-size: vw(18 * 2);
              color: #797979;
            }

            .row-label-color {
              color: #797979;
            }

            .row-label-color-default {
              color: #000000 !important;
            }

            .word-font-default {
              font-size: vw(18*2) !important;
            }

            .row-label-num-style {
              width: vw(80 * 2);
              height: vh(36 * 2);
              background: #808c87;
              border-radius: vw(21 * 2);
              display: inline-flex !important;
              align-items: center;
              justify-content: center;
              font-size: vw(24 * 2) !important;
              color: #fff;

              &-bg {
                background: #ff452f;
              }
            }

            .row-label-circle {
              width: vw(60 * 2);
              height: vw(60 * 2);
              background: #808c87;
              border-radius: 50%;
              color: #fff;
              display: inline-flex !important;
              align-items: center;
              justify-content: center;
              font-size: vw(16 * 2) !important;
            }
          }

          .table-chart {
            @include background_color("pageBoxBgColor");
            width: 100% !important;
            height: vh(40 * 2) !important;
            padding: 0 vw(15 * 2);
            border-radius: vw(10 * 2);

            section {
              position: absolute !important;

              .loading {
                display: flex;
                align-items: center;
                justify-content: center;
              }

              .desc {
                display: none;
              }
            }
          }

          .echarts-top {
            position: absolute !important;
            @include background_color("pageBoxBgColor");
            width: 100% !important;
            height: vh(40 * 2) !important;
            padding: 0 vw(15 * 2);
            border-radius: vw(10 * 2);
            z-index: 99;

            section {
              position: absolute !important;

              .loading {
                display: flex;
                align-items: center;
                justify-content: center;
              }

              .desc {
                display: none;
              }
            }
          }

          .el-badge {
            width: 100%;
            position: relative;

            .el-badge__content {
              position: absolute;
              width: vw(17 * 2);
              height: vw(17 * 2);
              border-radius: 50%;
              background-color: #ff452f;
              top: vw(-17 * 2);
              right: 0;
              transform: none;
              font-size: vw(12 * 2);
              display: flex;
              align-items: center;
              justify-content: center;
            }
          }
        }
      }
    }
  }

  .common-table-box-fixed {
    position: absolute;
    right: vw(36 * 2);
    top: 0;
    z-index: 100;
    height: vh(830 * 2);
    padding-bottom: vh(6 * 2);

    .common-table-fixed-header {
      height: vh(17 * 2);
      display: flex;
      margin-bottom: vh(10 * 2);
      align-items: center;
      justify-content: flex-end;
      padding-right: vw(50 * 2);
      @include background_color("pageBoxBgColor");
      font-family: "PingFangSC-Semibold";
    }

    .common-table-fixed-box {
      height: vh(800 * 2);
      overflow-x: hidden;
      overflow-y: auto;
      border-radius: 0 vw(10 * 2) vw(10 * 2) 0;

      // @include background_color('bottomBoxBgColor');
      &::-webkit-scrollbar {
        display: none;
      }
    }

    .common-table-fixed-wrapper {
      height: fit-content;

      .common-table-fixed-header-body {
        padding-top: 0;
        height: vh(55 * 2);
        position: relative;
        padding-right: vw(40 * 2);
        margin-bottom: vh(10 * 2);
        @include background_color("bottomBoxBgColor");
        @include border_style("borderColor");
        border-left: none !important;
        border-radius: 0 vw(10 * 2) vw(10 * 2) 0;
        display: flex;
        align-items: center;
        box-sizing: border-box;
        justify-content: flex-end;

        &.common-table-fixed-row-choose {
          cursor: pointer;
        }

        &.fixed-is-active {
          @include background-color("confirmButtonBgColor");
          @include border_style("confirmButtonBgColor");

          .button-Box {
            .el-button {
              @include border_style("borderColor");
              border-color: #fff !important;
            }
          }
        }

        // .spance-bg {
        //   width: 100%;
        //   height: vh(10*2);
        //   // @include background_color('pageBoxBgColor');
        // }

        .button-Box {
          height: vh(20 * 2);

          display: flex;
          justify-content: flex-end;
          margin-bottom: 0;

          + .button-Box {
            &.file-button-box {
              margin-left: vw(10 * 2);

              .el-button {
                margin-left: 0;
              }
            }

            .el-button {
              margin-left: vw(10 * 2);
            }

            margin-bottom: 0;
          }

          &.button-Box-height {
            height: vh(24 * 2);

            .el-button {
              height: vh(24 * 2);
              width: vw(45 * 2);
              padding: 0;

              &.button-four {
                width: vw(70 * 2);
              }
            }
          }

          .el-button {
            border: none;
          }
        }

        &:before {
          display: none;
          content: "";
          width: vw(1 * 2);
          height: vh(21 * 2);
          position: absolute;
          left: 0;
          top: 0;
          bottom: 0;
          margin: auto;
          @include background_color("borderColor");
        }
      }
    }
  }
}
  • 上述样式单位如果想改为px
    • 可以将vw(162) 、vh(162)这种的改为16px;
    • 如果觉得改vw vh很麻烦可以使用下列函数放入你的文件中
@function vw($px) {
  // 进行计算操作
  $result: ($px / 2);
  $factor: 100000;
  $roundedValue: round($result * $factor);
  $roundedResult: $roundedValue / $factor;
 
  @return #{$result}px;
 
}
@function vh($px) {
  $result: ($px / 2);
  $factor: 100000;
  $roundedValue: round($result * $factor);
  $roundedResult: $roundedValue / $factor;
  @return #{$result}px;
}
  • 使用vw和vh 我这边是统一将宽高都设备2倍,然后页面整体缩放了
//默认设计稿的宽度
$designWidth: 3840;
//默认设计稿的高度
$designHeight: 2160;


//px转为vw的函数

@function vw($px) {
  // 进行计算操作
  $result: ($px / $designWidth * 2) * 100;
  $factor: 100000;
  $roundedValue: round($result * $factor);
  $roundedResult: $roundedValue / $factor;

  @return #{$roundedResult}vw;
  
}


//px转为vh的函数

@function vh($px) {
  $result: ($px / $designHeight * 2) * 100;
  $factor: 100000;
  $roundedValue: round($result * $factor);
  $roundedResult: $roundedValue / $factor;
  @return #{$roundedResult}vh;
}

index.scss具体引用:详见该篇文章Vue项目切换主题颜色(mixin + scss)

vue文件引用table组件

<template>
  <div class="page-container">
    

      
        <h-common-table
          :data="tableData"
          :columns="tableColumns"
          ref="myTable"
        ></h-common-table>
       
    
  </div>
</template>

<script>
import HCommonTable from '@/components/commonTable/index'

export default {
  mixins: [commonSearchMixin, tableMixins, loadingMixins],
  components: {
    HCommonTable
  },
  data() {
    return {
      tableData: [],
      tableColumns: [],
      typeList:[{
        name:'类型11',
        id: 1
      },{
        name:'类型2',
        id: 2
      }]
    };
  },
  methods:{
    valueSourceFormat(row) {
      let item = this.typeList.find(el=>el.id==row.type)
      rerurn item ? item.name: ''
    },
    valueAddressFormat(row) {
      return row.dirct + row.address
    }
  }
  mounted() {
    this.tableColumns  = [
          {
            label: "序号",
            value: "sort",
            width: this.windowWidth <= 1024 ? 70 * 2 : 78 * 2,
            paddingLeft: this.windowWidth <= 1024 ? 10 * 2 : 20 * 2,
            paddingRight: this.windowWidth <= 1024 ? 10 * 2 : 20 * 2,
            isSort: true,
            position: "center"
          },
          {
            label: "创建日期",
            value: "createTime",
            isDate: true,
            width: this.windowWidth <= 1024 ? 140 * 2 : 148 * 2,
            position1: "center-left",
            paddingLeft: 0,
            paddingRight: 0,
            isHidden: this.windowWidth <= 1024
          },
          {
            label: "类型",
            value: "type",
            width: this.windowWidth <= 1024 ? 85 * 2 : 107 * 2,
            position: "center",
            valueFormatter: this.valueSourceFormat,
            paddingLeft: this.windowWidth <= 1024 ? 10 * 2 : 20 * 2,
            paddingRight: this.windowWidth <= 1024 ? 10 * 2 : 20 * 2
          },

          {
            label: "名称",
            value: "name",
            wordColor: true,
            isTooltip: true,
            width: this.windowWidth <= 1024 ? 150 * 2 : 340 * 2,
            position1: "center-left",
            paddingLeft: this.windowWidth <= 1024 ? 10 * 2 : 20 * 2,
            paddingRight: this.windowWidth <= 1024 ? 10 * 2 : 20 * 2
          },
          {
            label: "所在地",
            value: "companyDistrictId",
            isTooltip: true,
            width: this.windowWidth <= 1024 ? 130 * 2 : 162 * 2,
            paddingLeft: this.windowWidth <= 1024 ? 10 * 2 : 20 * 2,
            paddingRight: this.windowWidth <= 1024 ? 10 * 2 : 20 * 2,
            position1: "center-left",
            valueFormatter: this.valueAddressFormat
          },
          {
            label: "联系人/",
            label2: "电话",
            value: "contactName",
            value1: "contactPhone",
            width: this.windowWidth <= 1024 ? 145 * 2 : 190 * 2,
            position1: "center-left",
            paddingLeft: this.windowWidth <= 1024 ? 10 * 2 : 20 * 2,
            paddingRight: this.windowWidth <= 1024 ? 10 * 2 : 20 * 2
          },
          {
            label: "操作",
            isButton: true,
            position: "center",
            position1: "center",
            wrap: true,
            width: this.windowWidth <= 1024 ? 155 * 2 : 214 * 2,
            value: "",
            isSmall: this.windowWidth <= 1024 ? true : false,
            paddingLeft: this.windowWidth <= 1024 ? 0 : 18 * 2,
            buttonList: [
              [
                {
                  caption: "删除",
                  callback: this.deleteInfo,
                  type: "danger",
                  display: this.commonFunc.hasPermission("dealer-delete")
                },
                {
                  caption: "详情",
                  callback: this.lookInfo,
                  type: "success",
                  display: this.commonFunc.hasPermission("dealer-info")
                }
              ],
              [
                {
                  caption: "编辑",
                  callback: this.changeInfo,
                  type: "success",
                  display: this.commonFunc.hasPermission("dealer-update")
                }
              ]
            ]
          }
        ];
  }
  
 
  beforeDestroy() {}
};
</script>
<style lang="scss" scoped></style>
文章来源:https://blog.csdn.net/weixin_46328739/article/details/135135533
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。