Newer
Older
sensorHubPlusFront / src / components / NormalTable / index.vue
liyaguang 8 days ago 6 KB 系统基础修改
<script lang="ts" setup name="NormalTable">
import type { Ref } from 'vue'
import { ElTable } from 'element-plus'
import { defineExpose, ref } from 'vue'
import type { TableColumn } from './table_interface'

// ------------------定义props、 emit-------------------
const props = defineProps({
  // 是否显示多选表格
  isShowmultiSelect: {
    type: Boolean,
    default: false,
  },
  // 是否允许多选
  isMulti: {
    type: Boolean,
    default: true,
  },
  // 查询条件,此处主要需要分页的条件
  query: {
    type: Object,
    default() {
      return {
        offset: 1,
        limit: 20,
      }
    },
  },
  // loading状态
  listLoading: {
    type: Boolean,
    default: false,
  },
  // 数据
  data: {
    type: Array,
    default() {
      return []
    },
  },
  // 表格高度
  height: {
    type: Number,
    default() {
      return null
    },
  },
  // 数据总数
  total: {
    type: Number,
    default: 0,
  },
  // 数据列配置
  columns: {
    type: Array<TableColumn>,
    default() {
      return []
    },
  },
  // 是否需要分页控件
  pagination: {
    type: Boolean,
    default: true,
  },
  // 配置项
  options: {
    type: Object,
    default() {
      return {
        needIndex: true, // 是否需要序号列
        border: true, // 是否需要上方边框
      }
    },
  },
  // 可选单页显示条数
  pageSizes: {
    type: Array,
    default() {
      return [10, 20, 30]
    },
  },
  // 表格大小
  size: {
    type: String,
    default: 'default',
  }, // 表格大小,默认,small,mini等,与el-table条件相同
})
const emit = defineEmits(['change', 'selectionChange', 'rowClick', 'multiSelect'])
// -------定义数据--------------
interface columnsCheckInfo {
  text: string
  show: boolean
}
const columnsChecked: Ref<columnsCheckInfo[]> = ref([])
const table = ref<InstanceType<typeof ElTable>>()
const singleChecked = ref('') // 单选选中id
// 初始化列显示状态
function initColumnsState() {
  columnsChecked.value = []
  for (const column of props.columns) {
    columnsChecked.value.push({ text: column.text, show: !!column.show })
  }
}

// 最终展示列
const columnsFiltered: Ref<TableColumn[]> = ref([])
// 切换列
function changeColumns() {
  columnsFiltered.value = []
  for (const i in props.columns) {
    if (columnsChecked.value[i].show === true) {
      columnsFiltered.value.push(props.columns[i])
    }
  }
}
// 计算索引值方法
function indexMethod(index: number) {
  return props.query.limit * (props.query.offset - 1) + index + 1
}
// 刷新
function refresh() {
  emit('change')
}
// 改变页容量
function handleSizeChange(val: number) {
  emit('change', { size: val })
}
// 改变当前页
function handleCurrentChange(val: number) {
  emit('change', { page: val })
}
// 多选选中结果
function selectionChange(selection: []) {
  emit('selectionChange', selection)
}
// 点击行
function rowClick(row: object, column?: any, event?: any) {
  emit('rowClick', row)
}
// 监听columns
watch(props.columns, (val) => {
  initColumnsState()
  changeColumns()
})
// 多选
const handleSelectionChange = (val: any) => {
  emit('multiSelect', val)
}
// 单选选中
const radioChange = () => {
  console.log('---------')

  console.log(singleChecked.value)
  console.log(props.data)

  const checkValue = props.data.find((item: any) => item.id == singleChecked.value)
  emit('multiSelect', [checkValue])
}
// 清除多选选中
const clearMulti = () => {
  console.log('清理选中')
  table.value!.clearSelection()
}
defineExpose({
  clearMulti, initColumnsState,
})
onBeforeMount(() => {
  initColumnsState()
  changeColumns()
})
// 多选框单选功能
const selectClick = (selection: any, row: any) => {
  if (!props.isMulti) {
    console.log('selectClick')
    if (selection.length > 1) {
      const del_row = selection.shift()
      table.value?.toggleRowSelection(del_row, false) // 用于多选表格,切换某一行的选中状态,如果使用了第二个参数,则是设置这一行选中与否(selected 为 true 则选中)
    }
  }
}
</script>

<template>
  <div class="normal-table">
    <el-table
      id="print"
      ref="table"
      v-loading="listLoading"
      :data="data"
      :height="height"
      border
      stripe
      :size="size"
      style="width: 100%;"
      @selection-change="handleSelectionChange"
      @select="selectClick"
      @row-click="rowClick"
    >
      <slot name="preColumns" />

      <el-table-column v-if="!isMulti" label="" width="60" align="center" fixed>
        <template #default="scope">
          <el-radio v-model="singleChecked" :label="scope.row.id" class="radio" @change="radioChange" />
        </template>
      </el-table-column>
      <el-table-column v-if="isShowmultiSelect && isMulti" type="selection" width="38" fixed="left" />
      <el-table-column v-for="column of columns" :key="column.value" :label="column.text" :prop="column.value" :width="column.width" :align="column.align" :show-overflow-tooltip="column.showOverflow ? column.showOverflow : true" :fixed="column.fixed">
        <template #default="scope">
          <span v-if="!column.filter" :style="column.styleFilter ? column.styleFilter(scope.row) : ''">{{ scope.row[column.value] }}</span>
          <span v-else :style="column.styleFilter ? column.styleFilter(scope.row) : ''">{{ column.filter(scope.row) }}</span>
        </template>
      </el-table-column>
      <slot name="columns" />
    </el-table>
    <div v-if="props.pagination" style="width: 100%;margin-top: 10px;">
      <el-pagination
        :current-page="props.query.offset"
        :page-sizes="props.pageSizes as number[]"
        :page-size="props.query.limit"
        :total="props.total"
        layout="total, sizes, prev, pager, next"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </div>
  </div>
</template>

<style lang="scss" scoped>
.normal-table {
  width: 100%;
  // 隐藏全选按钮

  :deep(.el-radio__label) {
    display: none;
  }
}

.single-table {
  width: 100%;

  :deep(.el-table th.el-table__cell:nth-child(1) .cell) {
    visibility: hidden;
  }
}

.follow-link {
  color: #0d76d4;
  cursor: pointer;

  &:hover {
    color: #04395e;
  }
}
</style>

<style lang="scss">
.normal-table {
  .el-radio__label {
    display: none !important;
  }
}
</style>