riku
2025-03-12 42f42dc88214f283b43c422f37e10ab45c5c5578
src/components/monitor/DataTable.vue
@@ -1,61 +1,146 @@
<!-- eslint-disable no-unused-vars -->
<template>
  <BaseCard>
  <BaseCard size="medium" direction="right">
    <template #content>
      <el-table
        :data="tableData"
        ref="tableRef"
        :data="showData"
        v-loading="loading"
        table-layout="fixed"
        :row-class-name="tableRowClassName"
        :height="tableHeight"
        height="calc(94vh - var(--bevel-length-2))"
        size="small"
        :show-overflow-tooltip="true"
        border
        row-class-name="t-row"
        cell-class-name="t-cell"
        header-row-class-name="t-header-row"
        header-cell-class-name="t-header-cell"
        :show-summary="false"
        :highlight-current-row="true"
        @row-click="handleRowClick"
        @sort-change="handleSort"
      >
        <el-table-column prop="TIME" label="时间" />
        <el-table-column
          v-for="(item, index) in tableColumn"
          :key="index"
          :prop="item.name"
          :label="item.label"
        />
          :fixed="true"
          prop="TIME"
          label="时间"
          :formatter="timeFormatter"
          align="center"
          width="66"
          sortable="custom"
        >
        </el-table-column>
        <template v-for="item in tableColumn" :key="item.name">
          <el-table-column
            v-if="selectFactorType.includes(item.value)"
            :prop="item.name"
            :label="item.label"
            :formatter="factorFormatter"
            align="center"
            width="79"
            sortable="custom"
          />
        </template>
      </el-table>
      <el-pagination
        v-if="pagination"
        ref="paginationRef"
        class="el-pagination"
        small
        v-model:current-page="currentPage"
        v-model:page-size="pageSize"
        :page-sizes="[10, 20, 50, 100]"
        :background="true"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
        :page-sizes="[200, 500]"
        :hide-on-single-page="false"
        layout="prev, pager, next"
        :total="tableData.length"
      />
    </template>
    <template #footer> </template>
    <template #footer>
      <el-row justify="space-between" class="p-b-2 one-row">
        <el-button
          :loading="downloadLoading"
          type="primary"
          class="el-button-custom"
          size="small"
          @click="handleDownload"
          :disabled="downloadLoading"
          :icon="downloadLoading ? '' : 'download'"
        >
          导出数据
        </el-button>
        <el-text size="small" type="warning"
          >共 {{ tableData.length }} 条,{{ pageSize }}条/页</el-text
        >
      </el-row>
    </template>
  </BaseCard>
</template>
<script>
import moment from 'moment';
import { FactorDatas } from '@/model/FactorDatas';
import { checkboxOptions } from '@/constant/checkbox-options';
import { TYPE0 } from '@/constant/device-type';
import { windDir } from '@/constant/wind-dir';
import fileUtil from '@/utils/file';
export default {
  props: {
    loading: Boolean,
    factorDatas: FactorDatas,
    deviceType: {
      type: String,
      // type0: 车载或无人机; type1:无人船
      default: TYPE0
    }
    },
    deviceCode: String,
    selectFactorType: {
      type: Array,
      default: () => []
    },
    // 当前选中高亮的数据点索引
    locateIndex: Number
  },
  data() {
    return {
      tableHeight: '500',
      total: 0,
      currentPage: 1,
      pageSize: 20,
      loading: false
      pageSize: 200,
      rowHeight: undefined,
      // tableData:[],
      showData: [],
      downloadLoading: false
    };
  },
  emits: ['tableClick'],
  watch: {
    locateIndex(nV, oV) {
      if (nV == oV) return;
      const _index = this.tableData.findIndex((v) => v.index == nV);
      this.$refs.tableRef.setCurrentRow(this.tableData[_index]);
      // 计算分页
      this.currentPage = parseInt(_index / this.pageSize) + 1;
      // 计算对应分页中的索引
      const index = _index % this.pageSize;
      const h = this.getRowHeight();
      setTimeout(() => {
        this.$refs.tableRef.setScrollTop(h * index - 350);
      }, 200);
    },
    currentPage(nV, oV) {
      if (nV == oV) return;
      this.getShowData();
    },
    pageSize(nV, oV) {
      if (nV == oV) return;
      this.getShowData();
    },
    tableData(nV, oV) {
      if (nV == oV) return;
      this.getShowData();
    }
  },
  computed: {
    tableData() {
@@ -64,19 +149,157 @@
        if (Object.hasOwnProperty.call(this.factorDatas.factor, key)) {
          const f = this.factorDatas.factor[key];
          f.datas.forEach((v, i) => {
            const name = f.factorName;
            let value = v.factorData;
            if (list.length <= i) {
              list.push({ [f.factorName]: v });
              list.push({
                index: i,
                [name]: value
              });
            } else {
              list[i][f.factorName] = v;
              list[i][name] = value;
            }
          });
        }
      }
      return list;
    },
    // showData: {
    //   get() {
    //     // const sIndex = (this.currentPage - 1) * this.pageSize;
    //     // const eIndex = sIndex + this.pageSize;
    //     // return this.tableData.slice(sIndex, eIndex);
    //     this.pageData = this.getShowData();
    //     return this.pageData
    //   },
    //   set(newValue) {
    //     this.pageData = newValue
    //   }
    // },
    tableColumn() {
      return checkboxOptions(this.deviceType);
      return checkboxOptions(this.deviceType, true);
    }
  },
  methods: {
    getShowData() {
      const sIndex = (this.currentPage - 1) * this.pageSize;
      const eIndex = sIndex + this.pageSize;
      this.showData = this.tableData.slice(sIndex, eIndex);
    },
    // 获取表格第一行高度
    getRowHeight() {
      if (!this.rowHeight) {
        const rowList = document.getElementsByClassName('t-row');
        if (rowList.length != 0) {
          const row = rowList[0];
          this.rowHeight = row.getBoundingClientRect().height;
        } else {
          this.rowHeight = 0;
        }
      }
      return this.rowHeight;
    },
    timeFormatter(row, col, cellValue, index) {
      return moment(cellValue).format('HH:mm:ss');
    },
    factorFormatter(row, col, cellValue, index) {
      if (col.property == 'WIND_DIRECTION') {
        return windDir(cellValue);
      } else {
        return cellValue;
      }
    },
    handleRowClick(row, col, event) {
      this.$emit('tableClick', row.index);
      // console.log(row);
      // console.log(col);
      // console.log(event.target.getBoundingClientRect().height);
    },
    handleSort({ column, prop, order }) {
      // console.log(column);
      // console.log(prop);
      // console.log(order);
      this.tableData.sort((a, b) => {
        if (order == 'ascending') {
          if (a[prop] != b[prop]) {
            return a[prop] - b[prop];
          } else {
            return a.TIME - b.TIME;
          }
        } else if (order == 'descending') {
          if (a[prop] != b[prop]) {
            return b[prop] - a[prop];
          } else {
            return a.TIME - b.TIME;
          }
        } else {
          return a.TIME - b.TIME;
        }
      });
      this.getShowData();
    },
    handleDownload() {
      this.downloadLoading = true;
      setTimeout(() => {
        this.downloadLoading = false;
      }, 2000);
      const excelData = this.tableData.map((v) => {
        const res = {
          编号: ++v.index,
          时间: moment(v.TIME).format('YYYY-MM-DD HH:mm:ss')
        };
        this.tableColumn.forEach((c) => {
          res[c.label] = v[c.name];
        });
        return res;
      });
      fileUtil.exportToExcel(excelData, this.deviceCode, '走航监测数据.xlsx');
      this.downloadLoading = false;
    }
  }
};
</script>
<style scoped>
.one-row {
  /* background-color: red; */
  flex-wrap: nowrap;
}
</style>
<style>
.el-table {
  --el-table-bg-color: transparent;
  --el-table-row-hover-bg-color: var(--select_color);
  --el-table-current-row-bg-color: var(--select_color);
  /* --el-table-current-row-bg-color: #7dff5d96; */
  --el-table-text-color: var(--font-color);
}
.t-row {
  cursor: pointer;
  background-color: transparent !important;
}
.t-cell {
  /* background: red !important; */
  /* height: 40px;
  border: 1px solid black; */
}
.t-header-row {
}
.t-header-cell {
  background-color: var(--bg-color-2) !important;
  /* text-align: center !important; */
  color: white !important;
}
.el-pagination {
  --el-pagination-bg-color: transparent;
  --el-pagination-button-bg-color: transparent;
  --el-pagination-button-color: transparent;
  --el-pagination-button-disabled-color: white;
  --el-pagination-button-disabled-bg-color: transparent;
  --el-pagination-text-color: white;
  --el-pagination-button-color: white;
}
</style>