index.vue 6.57 KB

import { propsToAttrMap } from '@vue/shared';
<script lang="ts" setup name="PageNav">
import { ref, computed } from "vue";
import { changeNum } from '@/utils/common'

const props = defineProps({
  pageInfo: {
    type: Object,
    default: {},
  },
});

const emits = defineEmits(["pageChange"]);

const pageNum: Ref<any> = ref(1);
const pageCurr = computed(() => {
  pageNum.value = props.pageInfo.curr
  return props.pageInfo.curr ?? 1
})

const pageLimit = computed(() => {
  return props.pageInfo.limit ?? 10
})
// 总条数
const pageTotal = computed(() => {
  return props.pageInfo.rows ?? 0
})

const pageSizes = computed(() => {
  return props.pageInfo.sizes ?? []
})

// 总页数
const pageCount = computed(() => {
  return Math.ceil(props.pageInfo.rows / props.pageInfo.limit)
})

const pageType = computed({
  get: () => {
    return props.pageInfo.type
  },
  set: (val) => {
    return val
  }
})

const pageCurrentChange = (val) => {
  if (pageTotal.value == 0) return
  const page = {
    curr: val,
    limit: pageLimit.value,
  }
  pageNum.value = val;
  emits('pageChange', page)
}

const pageJump = () => {
  const page = {
    ...props.pageInfo,
    curr: parseInt(pageNum.value)
  }
  emits('pageChange', page)
}

const pageSizesChange = (val) => {
  const page = {
    curr: 1,
    limit: val,
  }
  emits('pageChange', page)
}
/** 处理输入框只能输入>=1的整数 */
const userInput: any = ref(null);

const pageNumInput = computed(() => userInput.value ?? pageNum.value)

function handleInput(val: number | string) {
  userInput.value = val ? +val : ''
}

function inputPageJump(val) {
  let oldVal = pageNum.value;
  if (!val) {
    pageNum.value = 1;
    userInput.value = undefined;
    if (oldVal !== pageNum.value) {
      const page = {
        ...props.pageInfo,
        curr: parseInt(pageNum.value)
      }
      emits('pageChange', page)
    }
    return;
  }
  val = Math.trunc(+val)
  if (val > pageCount.value) {
    pageNum.value = pageCount.value;
  } else if (val < 1) {
    pageNum.value = 1;
  } else {
    pageNum.value = val;
  }
  userInput.value = undefined;
  if (oldVal !== pageNum.value) {
    const page = {
      ...props.pageInfo,
      curr: parseInt(pageNum.value)
    }
    emits('pageChange', page)
  }
}
</script>

<template>
  <div class="page_nav_wrap" :class="{ showCount: pageType == 'concise' && props.pageInfo.showCount }">
    <template v-if="pageType == 'simple'">
      <el-pagination small layout="total, slot" :total="pageTotal" :default-page-size="pageLimit" :page-count="pageCount">
        <span>数据</span>
      </el-pagination>
      <el-pagination small layout="prev, slot, next" :total="pageTotal" :default-page-size="pageLimit"
        :page-count="pageCount" @current-change="pageCurrentChange">
        <div class="page_code">
          <span>{{ pageNum }} / {{ pageCount }}</span>
        </div>
      </el-pagination>
    </template>
    <template v-else-if="pageType == 'concise'">
      <el-pagination v-if="props.pageInfo.showCount" background small layout="slot" :total="pageTotal" :default-page-size="pageLimit"
        :page-count="pageCount">
        <span style="font-size: 14px">共有
          <span style="color: #4fa1a4; font-size: 14px">{{
            changeNum(pageTotal)
          }}</span>
          条数据</span>
      </el-pagination>
      <el-pagination small layout="prev, slot, next" :total="pageTotal" :default-page-size="pageLimit"
        :page-count="pageCount" :current-page="parseInt(pageNum)" @current-change="pageCurrentChange">
        <div class="page_code">
          <el-input class="pagnination" type="number" :min="1" :max="pageCount" v-model.trim="pageNumInput" size="small"
            style="width: 40px" @input="handleInput" @change="inputPageJump" :disabled="pageCount <= 1" />
          <span> / {{ pageCount }}</span>
        </div>
      </el-pagination>
    </template>
    <template v-else-if="pageType == 'count'">
      <el-pagination background small layout="slot" :total="pageTotal" :default-page-size="pageLimit"
        :page-count="pageCount">
        <span style="font-size: 14px">当前表共有
          <span style="color: #4fa1a4; font-size: 14px">{{
            changeNum(pageTotal)
          }}</span>
          条数据</span>
      </el-pagination>
    </template>
    <template v-else>
      <el-pagination background small layout="slot" :total="pageTotal" :default-page-size="pageLimit"
        :page-count="pageCount">
        <span style="font-size: 14px">当前表共有
          <span style="color: #4fa1a4; font-size: 14px">{{
            changeNum(pageTotal)
          }}</span>
          条数据</span>
      </el-pagination>
      <el-pagination background small layout="prev, pager, next, slot" :total="pageTotal" :default-page-size="pageLimit"
        :page-count="pageCount" :current-page="pageCurr" @current-change="pageCurrentChange">
        <div class="page_jumper">
          <el-input class="pagnination" type="number" :min="1" :max="pageCount" v-model.trim="pageNumInput" size="small"
            style="width: 40px" @input="handleInput" @change="inputPageJump" :disabled="pageTotal <= 0" />
          <el-button plain size="small" :disabled="parseInt(pageNum) > pageCount || parseInt(pageNum) <= 0"
            @click="pageJump()" v-preReClick>GO</el-button>
        </div>
        <div class="page_sizes" v-if="props.pageInfo.pageSizeShow ?? true">
          <el-select v-model="pageLimit" placeholder="Select" size="small" style="width: 60px" @change="pageSizesChange">
            <el-option v-for="  item   in   pageSizes  " :key="item.value" :label="item.label" :value="item.value" />
          </el-select>
          <span style="margin-left: 8px">条 / 页</span>
        </div>
      </el-pagination>
    </template>
  </div>
</template>

<style lang="scss" scoped>
.page_nav_wrap {
  width: 100%;
  height: 36px;
  display: flex;
  justify-content: space-between;
  align-items: center;

  .page_jumper {
    display: flex;
    align-items: center;

    .el-button {
      height: 24px;
      line-height: 24px;
      border: 1px solid #d9d9d9;
      border-radius: 2px;
      margin-left: 4px;
    }
  }

  .page_sizes {
    display: flex;
    align-items: center;
    margin-left: 24px;
  }

  &.simple {
    :deep(.el-pagination) {
      button {
        border: none;
      }
    }

    .el-pagination:last-child {
      border: 1px solid #d9d9d9;
      border-radius: 2px;
    }
  }

  &.concise {
    justify-content: flex-end;

    &.showCount {
      justify-content: space-between;
    }

    .el-input.pagnination {
      vertical-align: baseline;
    }
  }

  .page_code {
    padding: 0 8px;
  }
}
</style>@/utils/common