spring
2025-02-20 037a7112a2bc9e38bb2f398ff5ca740ac01a8fb2
src/components/Table/lims-table.vue
@@ -12,6 +12,7 @@
      :row-class-name="rowClassName"
      :row-style="rowStyle"
      :row-key="rowKey"
      :span-method="spanMethod"
      stripe
      style="width: 100%"
      tooltip-effect="dark"
@@ -19,164 +20,182 @@
      @current-change="currentChange"
      @selection-change="handleSelectionChange"
    >
      <template v-if="isSelection">
        <el-table-column type="selection" width="55" />
      </template>
      <template>
        <el-table-column
          align="center"
          label="序号"
          type="index"
          width="60"
          :index="indexMethod"
        />
      </template>
      <el-table-column
        align="center"
        type="selection"
        width="55"
        v-if="isSelection"
      />
      <el-table-column
        align="center"
        label="序号"
        type="index"
        width="60"
        :index="indexMethod"
      />
      <template v-for="(item, index) in column">
        <el-table-column
          :column-key="item.columnKey"
          :filter-method="item.filterHandler"
          :filter-multiple="item.filterMultiple"
          :filtered-value="item.filteredValue"
          :filters="item.filters"
          :fixed="item.fixed"
          :label="item.label"
          :min-width="item.minWidth"
          :prop="item.prop"
          show-overflow-tooltip
          :sortable="item.sortable ? true : false"
          :type="item.type"
          :width="item.width"
          align="center"
      <el-table-column
        v-for="(item, index) in column"
        :key="index"
        :column-key="item.columnKey"
        :filter-method="item.filterHandler"
        :filter-multiple="item.filterMultiple"
        :filtered-value="item.filteredValue"
        :filters="item.filters"
        :fixed="item.fixed"
        :label="item.label"
        :min-width="item.minWidth"
        :prop="item.prop"
        show-overflow-tooltip
        :sortable="item.sortable ? true : false"
        :type="item.type"
        :width="
          item.dataType === 'action' ? getWidth(item.operation) : item.width
        "
        align="center"
      >
        <!-- <div class="123" v-if="item.type == ''"> -->
        <template
          v-if="item.hasOwnProperty('colunmTemplate')"
          :slot="item.colunmTemplate"
          slot-scope="scope"
        >
          <!-- <div class="123" v-if="item.type == ''"> -->
          <template
            v-if="item.hasOwnProperty('colunmTemplate')"
            :slot="item.colunmTemplate"
            slot-scope="scope"
          >
          <slot
            v-if="item.theadSlot"
            :index="index"
            :name="item.theadSlot"
            :row="scope.row"
          />
        </template>
        <template slot-scope="scope">
          <!-- 插槽 -->
          <div v-if="item.dataType == 'slot'">
            <slot
              v-if="item.theadSlot"
              :index="index"
              :name="item.theadSlot"
              v-if="item.slot"
              :index="scope.$index"
              :name="item.slot"
              :row="scope.row"
            />
          </template>
          </div>
          <!-- 进度条 -->
          <div v-else-if="item.dataType == 'progress'">
            <el-progress :percentage="Number(scope.row[item.prop])" />
          </div>
          <!-- 图片 -->
          <div v-else-if="item.dataType == 'image'">
            <img
              :src="javaApi + '/img/' + item.prop"
              alt=""
              style="width: 40px; height: 40px; margin-top: 10px"
            />
          </div>
          <template slot-scope="scope">
            <!-- 插槽 -->
            <div v-if="item.dataType == 'slot'">
              <slot
                v-if="item.slot"
                :index="scope.$index"
                :name="item.slot"
                :row="scope.row"
              />
            </div>
            <!-- 进度条 -->
            <div v-else-if="item.dataType == 'progress'">
              <el-progress :percentage="Number(scope.row[item.prop])" />
            </div>
            <!-- tag -->
            <div v-else-if="item.dataType == 'tag'">
              <el-tag
                v-if="
                  typeof dataTypeFn(scope.row[item.prop], item.formatData) ==
                  'string'
                "
                :title="scope.row[item.prop] | formatters(item.formatData)"
                :type="formatType(scope.row[item.prop], item.formatType)"
                >{{
                  scope.row[item.prop] | formatters(item.formatData)
                }}</el-tag
              >
              <el-tag
                v-for="(tag, index) in dataTypeFn(
                  scope.row[item.prop],
                  item.formatData
                )"
                v-else-if="
                  typeof dataTypeFn(scope.row[item.prop], item.formatData) ==
                  'object'
                "
                :key="index"
                :title="scope.row[item.prop] | formatters(item.formatData)"
                :type="formatType(tag, item.formatType)"
                >{{
                  item.tagGroup
          <!-- tag -->
          <div v-else-if="item.dataType == 'tag'">
            <el-tag
              v-if="
                typeof dataTypeFn(scope.row[item.prop], item.formatData) ==
                'string'
              "
              :title="scope.row[item.prop] | formatters(item.formatData)"
              :type="formatType(scope.row[item.prop], item.formatType)"
              >{{ scope.row[item.prop] | formatters(item.formatData) }}</el-tag
            >
            <el-tag
              v-for="(tag, index) in dataTypeFn(
                scope.row[item.prop],
                item.formatData
              )"
              v-else-if="
                typeof dataTypeFn(scope.row[item.prop], item.formatData) ==
                'object'
              "
              :key="index"
              :title="scope.row[item.prop] | formatters(item.formatData)"
              :type="formatType(tag, item.formatType)"
              >{{
                item.tagGroup
                  ? tag[item.tagGroup.label]
                    ? tag[item.tagGroup.label]
                      ? tag[item.tagGroup.label]
                      : tag
                    : tag
                }}</el-tag
              >
              <el-tag
                v-else
                :title="scope.row[item.prop] | formatters(item.formatData)"
                :type="formatType(scope.row[item.prop], item.formatType)"
                >{{
                  scope.row[item.prop] | formatters(item.formatData)
                }}</el-tag
              >
            </div>
                  : tag
              }}</el-tag
            >
            <el-tag
              v-else
              :title="scope.row[item.prop] | formatters(item.formatData)"
              :type="formatType(scope.row[item.prop], item.formatType)"
              >{{ scope.row[item.prop] | formatters(item.formatData) }}</el-tag
            >
          </div>
            <!-- 按钮 -->
            <div v-else-if="item.dataType == 'action'">
              <template v-for="(o, key) in item.operation">
          <!-- 按钮 -->
          <div v-else-if="item.dataType == 'action'">
            <template v-for="(o, key) in item.operation">
              <el-button
                v-if="o.type != 'upload'"
                size="mini"
                v-show="o.showHide ? o.showHide(scope.row) : true"
                :disabled="o.disabled ? o.disabled(scope.row) : false"
                :icon="iconFn(o)"
                :plain="o.plain"
                :style="{ color: o.name === '删除' ? '#f56c6c' : o.color }"
                :type="o.type | typeFn(scope.row)"
                @click="o.clickFun(scope.row)"
                :key="key"
              >
                {{ o.name }}
              </el-button>
              <el-upload
                action="#"
                size="mini"
                :on-change="
                  (file, fileList) => o.clickFun(scope.row, file, fileList)
                "
                :multiple="o.multiple ? o.multiple : false"
                :limit="o.limit ? o.limit : 1"
                :disabled="o.disabled ? o.disabled(scope.row) : false"
                :accept="
                  o.accept
                    ? o.accept
                    : '.jpg,.jpeg,.png,.gif,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf,.zip,.rar'
                "
                v-if="o.type == 'upload'"
                style="display: inline-block; width: 50px"
                v-show="o.showHide ? o.showHide(scope.row) : true"
                :auto-upload="false"
                :on-exceed="onExceed"
                :show-file-list="false"
                :key="key"
              >
                <el-button
                  v-if="o.type != 'upload'"
                  size="mini"
                  v-show="o.showHide ? o.showHide(scope.row) : true"
                  :size="o.size ? o.size : 'small'"
                  type="text"
                  :disabled="o.disabled ? o.disabled(scope.row) : false"
                  :icon="iconFn(o)"
                  :plain="o.plain"
                  :style="{ color: o.name === '删除' ? '#f56c6c' : o.color }"
                  :type="o.type | typeFn(scope.row)"
                  @click="o.clickFun(scope.row)"
                  >{{ o.name }}</el-button
                >
                  {{ o.name }}
                </el-button>
                <el-upload
                  action="#"
                  size="mini"
                  :on-change="
                    (file, fileList) => o.clickFun(scope.row, file, fileList)
                  "
                  :multiple="o.multiple ? o.multiple : false"
                  :limit="o.limit ? o.limit : 1"
                  :disabled="o.disabled ? o.disabled(scope.row) : false"
                  :accept="
                    o.accept
                      ? o.accept
                      : '.jpg,.jpeg,.png,.gif,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf,.zip,.rar'
                  "
                  v-if="o.type == 'upload'"
                  style="display: inline-block; width: 50px"
                  v-show="o.showHide ? o.showHide(scope.row) : true"
                  :auto-upload="false"
                  :on-exceed="onExceed"
                  :show-file-list="false"
                >
                  <el-button
                    :size="o.size ? o.size : 'small'"
                    type="text"
                    :disabled="o.disabled ? o.disabled(scope.row) : false"
                    >{{ o.name }}</el-button
                  >
                </el-upload>
              </template>
            </div>
            <!-- 默认纯展示数据 -->
            <div v-else>
              <span v-if="!item.formatData">{{ scope.row[item.prop] }}</span>
              <span v-else>{{
                scope.row[item.prop] | formatters(item.formatData)
              }}</span>
            </div>
          </template>
        </el-table-column>
      </template>
              </el-upload>
            </template>
          </div>
          <!-- 可点击的文字 -->
          <div
            v-else-if="item.dataType == 'link'"
            class="cell link"
            style="width: 100%"
            @click="goLink(scope.row, item.linkMethod)"
          >
            <span v-if="!item.formatData">{{ scope.row[item.prop] }}</span>
          </div>
          <!-- 默认纯展示数据 -->
          <div v-else class="cell" style="width: 100%">
            <span v-if="!item.formatData">{{ scope.row[item.prop] }}</span>
            <span v-else>{{
              scope.row[item.prop] | formatters(item.formatData)
            }}</span>
          </div>
        </template>
      </el-table-column>
    </el-table>
    <pagination
      v-show="page.total > 0"
@@ -292,7 +311,7 @@
    },
    border: {
      type: Boolean,
      default: false,
      default: true,
    },
    highlightCurrentRow: {
      type: Boolean,
@@ -340,8 +359,23 @@
      },
    },
  },
  data() {
    return {
      spanList: [],
    };
  },
  mounted() {
    this.calculateSpanInfo();
  },
  methods: {
    getWidth(row) {
      let count = 0;
      console.log("row---", row);
      row.forEach((a) => {
        count += a.name.length;
      });
      return count * 15 + 40 + "px";
    },
    iconFn(row) {
      if (row.name === "编辑" || row.name === "修改") {
        return "el-icon-edit";
@@ -379,6 +413,95 @@
      // return index * 2;
      return (this.page.current - 1) * this.page.size + index + 1;
    },
    // 点击单元格link事件
    goLink(row, linkMethod) {
      if (!linkMethod) {
        return this.$message.warning("请配置lingk事件");
      }
      this.$parent[linkMethod](row);
    },
    // 合并单元格
    calculateSpanInfo() {
      // 初始化每列的合并信息
      this.spanList = [];
      this.column.forEach((m, i) => {
        if (m.mergeCol) {
          this.spanList.push({
            arr: [],
            position: 0,
            name: m.prop,
            index: i + 1,
          });
        }
      });
      this.spanList.forEach((item, i) => {
        this.rowspan(
          this.spanList[i].arr,
          this.spanList[i].position,
          item.name
        );
      });
    },
    rowspan(spanArr, position, spanName) {
      this.tableData.forEach((item, index) => {
        if (index === 0) {
          spanArr.push(1);
          position = 0;
        } else {
          if (
            this.tableData[index][spanName] ===
            this.tableData[index - 1][spanName]
          ) {
            spanArr[position] += 1;
            spanArr.push(0);
          } else {
            spanArr.push(1);
            position = index;
          }
        }
      });
    },
    // 合并单元格
    spanMethod({ row, column, rowIndex, columnIndex }) {
      // 一般的合并行
      if (this.column.find((m) => m.mergeCol)) {
        let i = null;
        let obj = this.spanList.find((item, index) => {
          i = index;
          return item.index == columnIndex;
        });
        if (obj) {
          const _row = this.spanList[i].arr[rowIndex];
          const _col = _row > 0 ? 1 : 0;
          return {
            rowspan: _row,
            colspan: _col,
          };
        }
      }
      // // 特殊的合并行
      // if (
      //   this.data.spanConfig != undefined &&
      //   this.data.spanConfig.special &&
      //   this.data.spanConfig.special.main &&
      //   this.data.spanConfig.special.rows &&
      //   this.data.spanConfig.special.rows.length > 0
      // ) {
      //   let i = null;
      //   let obj = this.data.spanConfig.special.rows.find((item, index) => {
      //     i = index;
      //     return item.index == columnIndex;
      //   });
      //   if (obj) {
      //     const _row = this.specialSpanList[i].arr[rowIndex];
      //     const _col = _row > 0 ? 1 : 0;
      //     return {
      //       rowspan: _row,
      //       colspan: _col,
      //     };
      //   }
      // }
    },
  },
};
</script>
@@ -387,4 +510,22 @@
.el-table >>> .el-table__empty-text {
  text-align: center;
}
>>> .cell {
  padding: 0 !important;
}
.cell {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-right: 4px !important;
  padding-left: 10px !important;
}
.link {
  color: rgb(64, 158, 255);
  cursor: pointer;
}
>>> .el-table__body-wrapper::-webkit-scrollbar {
  height: 14px; /* 设置滚动条宽度 */
}
</style>