310 lines
11 KiB
Vue
310 lines
11 KiB
Vue
![]() |
<template>
|
|||
|
<div
|
|||
|
class="jahat-pagination d-flex align-items-center flex-wrap border-top mt-3 p-2 rounded-0"
|
|||
|
:class="pagination.alignment['between']"
|
|||
|
>
|
|||
|
<div
|
|||
|
v-if="showTotalRecords"
|
|||
|
class="form-group d-flex align-items-center ml-3 mb-0"
|
|||
|
>
|
|||
|
<span
|
|||
|
>{{
|
|||
|
localPaginationInfo.offset + localPaginationInfo.limit
|
|||
|
}} </span
|
|||
|
>
|
|||
|
<span>-</span>
|
|||
|
<span> {{ localPaginationInfo.offset }}</span>
|
|||
|
<span> از </span>
|
|||
|
<span>{{ localPaginationInfo.total }}</span>
|
|||
|
<span> رکورد</span>
|
|||
|
|
|||
|
<label
|
|||
|
style="width: auto; font-size: inherit; color: inherit"
|
|||
|
for="exampleFormControlSelect1"
|
|||
|
class="no-wrap ml-2 mr-4 mb-0"
|
|||
|
>
|
|||
|
تعداد سطرها
|
|||
|
</label>
|
|||
|
|
|||
|
<select
|
|||
|
style="min-width: 3.5em"
|
|||
|
v-model="localPaginationInfo.limit"
|
|||
|
@change="limitChanged"
|
|||
|
class="form-control"
|
|||
|
id="exampleFormControlSelect1"
|
|||
|
>
|
|||
|
<option :value="5">5</option>
|
|||
|
<option :value="10">10</option>
|
|||
|
<option :value="15">15</option>
|
|||
|
<option :value="20">20</option>
|
|||
|
<option :value="25">25</option>
|
|||
|
<option :value="50">50</option>
|
|||
|
<option :value="75">75</option>
|
|||
|
<option :value="100">100</option>
|
|||
|
</select>
|
|||
|
</div>
|
|||
|
|
|||
|
<div v-if="showPageSelection" class="d-flex align-items-center">
|
|||
|
<input
|
|||
|
type="number"
|
|||
|
dir="ltr"
|
|||
|
v-model.number="localPaginationInfo.page"
|
|||
|
class="form-control font-weight-bold"
|
|||
|
id="page-id"
|
|||
|
placeholder="00"
|
|||
|
name="page-id"
|
|||
|
aria-label="وارد کردن شماره صفحه"
|
|||
|
size="10000"
|
|||
|
@keyup="sendQuery()"
|
|||
|
@keydown="onKeyDown()"
|
|||
|
/>
|
|||
|
|
|||
|
<UPagination
|
|||
|
:active-button="{ variant: 'outline' }"
|
|||
|
:inactive-button="{ color: 'gray' }"
|
|||
|
:total="localPaginationInfo.total"
|
|||
|
:prev-button="{
|
|||
|
icon: '',
|
|||
|
label: 'قبلی',
|
|||
|
color: 'gray',
|
|||
|
}"
|
|||
|
:next-button="{
|
|||
|
icon: '',
|
|||
|
trailing: true,
|
|||
|
label: 'بعدی',
|
|||
|
color: 'gray',
|
|||
|
}"
|
|||
|
v-model="localPaginationInfo.page"
|
|||
|
:max="3"
|
|||
|
:page-count="localPaginationInfo.pages"
|
|||
|
@click.prevent="clickCallback"
|
|||
|
>
|
|||
|
</UPagination>
|
|||
|
<!-- :first-button="{
|
|||
|
icon: 'i-heroicons-arrow-small-right-20-solid',
|
|||
|
label: 'ابتدا',
|
|||
|
color: 'gray',
|
|||
|
}"
|
|||
|
:last-button="{
|
|||
|
icon: 'i-heroicons-arrow-small-left-20-solid',
|
|||
|
trailing: true,
|
|||
|
label: 'آخر',
|
|||
|
color: 'gray',
|
|||
|
}"
|
|||
|
show-first
|
|||
|
show-last -->
|
|||
|
<!-- :prev-text="'قبلی'"
|
|||
|
:margin-pages="2"
|
|||
|
:next-text="'بعدی'"
|
|||
|
:last-button-text="'آخر'"
|
|||
|
:first-button-text="'ابتدا'"
|
|||
|
:container-class="pagination.containerClass"
|
|||
|
:page-class="pagination.pageClass"
|
|||
|
:page-link-class="pagination.linkClass"
|
|||
|
:prev-class="pagination.prevClass"
|
|||
|
:prev-link-class="pagination.prevLinkClass"
|
|||
|
:next-class="pagination.nextClass"
|
|||
|
:next-link-class="pagination.nextLinkClass" -->
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</template>
|
|||
|
|
|||
|
<script>
|
|||
|
import { mapActions } from "pinia";
|
|||
|
import { useCommonStore } from "~/stores/commonStore";
|
|||
|
// import Paginate from "vuejs-paginate-next";
|
|||
|
|
|||
|
/**
|
|||
|
* @vue-prop {Object} [paginationInfo] - اطلاعات صفحه بندی
|
|||
|
* @vue-prop {Number} [paginationInfo.pages=0] - تعداد کل صفحات
|
|||
|
* @vue-prop {Number} [paginationInfo.total=0] - تعداد کل آیتمها
|
|||
|
* @vue-prop {Number} [paginationInfo.page=1] - صفحه فعلی
|
|||
|
* @vue-prop {Number} [paginationInfo.offset=0] - آفست (صفحه * تعداد در هر صفحه)
|
|||
|
* @vue-prop {Number} [paginationInfo.limit=10] - تعداد در هر صفحه
|
|||
|
*
|
|||
|
* @vue-data {Number} [typingTimer=0] - تایمر تایپ
|
|||
|
* @vue-data {Number} [doneTypingInterval=500] - فاصله زمانی برای اتمام تایپ (به میلیثانیه)
|
|||
|
* @vue-data {Object} [pagination] - تنظیمات صفحه بندی
|
|||
|
* @vue-data {String} [pagination.containerClass="pagination"] - کلاس کانتینر صفحه بندی
|
|||
|
* @vue-data {String} [pagination.activeClass="active"] - کلاس فعال
|
|||
|
* @vue-data {String} [pagination.disabledClass="disabled"] - کلاس غیرفعال
|
|||
|
* @vue-data {String} [pagination.pageClass="page-item"] - کلاس آیتم صفحه
|
|||
|
* @vue-data {String} [pagination.linkClass="page-link"] - کلاس لینک صفحه
|
|||
|
* @vue-data {String} [pagination.prevClass="page-item"] - کلاس آیتم صفحه قبلی
|
|||
|
* @vue-data {String} [pagination.prevLinkClass="page-link"] - کلاس لینک صفحه قبلی
|
|||
|
* @vue-data {String} [pagination.nextClass="page-item"] - کلاس آیتم صفحه بعدی
|
|||
|
* @vue-data {String} [pagination.nextLinkClass="page-link"] - کلاس لینک صفحه بعدی
|
|||
|
* @vue-data {Object} [pagination.alignment] - تنظیمات تراز صفحه بندی
|
|||
|
* @vue-data {String} [pagination.alignment.start="justify-content-start"] - تراز ابتدا
|
|||
|
* @vue-data {String} [pagination.alignment.center="justify-content-center"] - تراز مرکز
|
|||
|
* @vue-data {String} [pagination.alignment.end="justify-content-end"] - تراز انتها
|
|||
|
* @vue-data {String} [pagination.alignment.between="justify-content-between"] - تراز بین
|
|||
|
* @vue-data {Object} [pagination.icons] - آیکونهای صفحه بندی
|
|||
|
* @vue-data {String} [pagination.icons.first="fas fa-angle-double-right"] - آیکون صفحه اول
|
|||
|
* @vue-data {String} [pagination.icons.prev="fas fa-angle-right"] - آیکون صفحه قبلی
|
|||
|
* @vue-data {String} [pagination.icons.next="fas fa-angle-left"] - آیکون صفحه بعدی
|
|||
|
* @vue-data {String} [pagination.icons.last="fas fa-angle-double-left"] - آیکون آخرین صفحه
|
|||
|
* @vue-data {Object} [localPaginationInfo] - اطلاعات صفحه بندی محلی
|
|||
|
* @vue-data {Number} [localPaginationInfo.pages=0] - تعداد کل صفحات
|
|||
|
* @vue-data {Number} [localPaginationInfo.total=0] - تعداد کل آیتمها
|
|||
|
* @vue-data {Number} [localPaginationInfo.page=1] - صفحه فعلی
|
|||
|
* @vue-data {Number} [localPaginationInfo.offset=0] - آفست (صفحه * تعداد در هر صفحه)
|
|||
|
* @vue-data {Number} [localPaginationInfo.limit=10] - تعداد در هر صفحه
|
|||
|
*/
|
|||
|
|
|||
|
export default {
|
|||
|
props: {
|
|||
|
showPageSelection: {
|
|||
|
default: true,
|
|||
|
},
|
|||
|
showTotalRecords: {
|
|||
|
default: true,
|
|||
|
},
|
|||
|
|
|||
|
paginationInfo: {
|
|||
|
default() {
|
|||
|
return {
|
|||
|
pages: 0,
|
|||
|
total: 0,
|
|||
|
page: 1,
|
|||
|
offset: 0,
|
|||
|
limit: 10,
|
|||
|
};
|
|||
|
},
|
|||
|
},
|
|||
|
},
|
|||
|
mounted() {
|
|||
|
// const plainPaginationInfo = JSON.parse(JSON.stringify(this.paginationInfo));
|
|||
|
// this.localPaginationInfo = structuredClone(plainPaginationInfo);
|
|||
|
// this.localPaginationInfo = structuredClone(this.paginationInfo);
|
|||
|
this.localPaginationInfo = this.paginationInfo;
|
|||
|
this.paginationSetter(this.localPaginationInfo);
|
|||
|
},
|
|||
|
|
|||
|
watch: {
|
|||
|
paginationInfo(newVal) {
|
|||
|
// this.localPaginationInfo = structuredClone(newVal);
|
|||
|
this.localPaginationInfo = newVal;
|
|||
|
this.paginationSetter(this.localPaginationInfo);
|
|||
|
},
|
|||
|
},
|
|||
|
data() {
|
|||
|
return {
|
|||
|
typingTimer: 0,
|
|||
|
doneTypingInterval: 500,
|
|||
|
|
|||
|
pagination: {
|
|||
|
containerClass: "pagination",
|
|||
|
activeClass: "active",
|
|||
|
disabledClass: "disabled",
|
|||
|
pageClass: "page-item",
|
|||
|
linkClass: "page-link",
|
|||
|
prevClass: "page-item",
|
|||
|
prevLinkClass: "page-link",
|
|||
|
nextClass: "page-item",
|
|||
|
nextLinkClass: "page-link",
|
|||
|
alignment: {
|
|||
|
start: "justify-content-start",
|
|||
|
center: "justify-content-center",
|
|||
|
end: "justify-content-end",
|
|||
|
between: "justify-content-between",
|
|||
|
},
|
|||
|
|
|||
|
icons: {
|
|||
|
first: "fas fa-angle-double-right",
|
|||
|
prev: "fas fa-angle-right",
|
|||
|
next: "fas fa-angle-left",
|
|||
|
last: "fas fa-angle-double-left",
|
|||
|
},
|
|||
|
},
|
|||
|
|
|||
|
localPaginationInfo: {
|
|||
|
pages: 0,
|
|||
|
total: 0,
|
|||
|
page: 1,
|
|||
|
offset: 0,
|
|||
|
limit: 10,
|
|||
|
},
|
|||
|
};
|
|||
|
},
|
|||
|
methods: {
|
|||
|
...mapActions(useCommonStore, ["paginationSetter"]),
|
|||
|
/**
|
|||
|
* ارسال درخواست جستجو پس از اتمام تایپ.
|
|||
|
* اگر کاربر تایپ را متوقف کند، پس از مدت زمان مشخصی (doneTypingInterval) این متد اجرا میشود.
|
|||
|
* صفحه فعلی و محدودیت نتایج را به روز میکند و آنها را به کامپوننت والد ارسال میکند.
|
|||
|
*/
|
|||
|
sendQuery() {
|
|||
|
clearTimeout(this.typingTimer);
|
|||
|
|
|||
|
this.typingTimer = setTimeout(() => {
|
|||
|
if (this.localPaginationInfo.page.length == 0)
|
|||
|
this.localPaginationInfo.page = 1;
|
|||
|
|
|||
|
this.$emit("page-changed", {
|
|||
|
pageNumber: this.localPaginationInfo.page,
|
|||
|
limit: this.localPaginationInfo.limit,
|
|||
|
});
|
|||
|
this.paginationSetter(this.localPaginationInfo);
|
|||
|
}, this.doneTypingInterval);
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* هنگامی که کلیدی فشار داده میشود، تایمر تایپ کردن را متوقف میکند.
|
|||
|
*/
|
|||
|
onKeyDown() {
|
|||
|
clearTimeout(this.typingTimer);
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* تغییر تعداد نتایج صفحه.
|
|||
|
* تعداد جدید را تنظیم کرده و آن را به کامپوننت والد ارسال میکند.
|
|||
|
*/
|
|||
|
limitChanged() {
|
|||
|
this.$emit("page-limit-changed", {
|
|||
|
pageNumber: 1,
|
|||
|
limit: this.localPaginationInfo.limit,
|
|||
|
});
|
|||
|
this.paginationSetter(this.localPaginationInfo);
|
|||
|
},
|
|||
|
|
|||
|
/**
|
|||
|
* تغییر صفحه هنگامی که کاربر روی شماره صفحه کلیک میکند.
|
|||
|
* صفحه جدید را تنظیم کرده و آدرس URL را بهروزرسانی میکند.
|
|||
|
* @param {number} pageNumber - شماره صفحه جدید.
|
|||
|
*/
|
|||
|
clickCallback(evt) {
|
|||
|
this.$emit("page-changed", {
|
|||
|
pageNumber: this.paginationInfo.page,
|
|||
|
limit: this.localPaginationInfo.limit,
|
|||
|
});
|
|||
|
this.paginationSetter(this.localPaginationInfo);
|
|||
|
|
|||
|
// this.$router.replace({
|
|||
|
// query: { ...this.$route.query, page: pageNumber },
|
|||
|
// });
|
|||
|
// this.$route.query = {...this.$route.query, page: pageNumber};
|
|||
|
|
|||
|
let path = this.$route.fullPath;
|
|||
|
|
|||
|
if (this.$route.query.page)
|
|||
|
path = path.replace(
|
|||
|
`page=${this.$route.query.page}`,
|
|||
|
`page=${this.paginationInfo.page}`
|
|||
|
);
|
|||
|
else path = path + `?page=${this.paginationInfo.page}`;
|
|||
|
|
|||
|
history.pushState({}, document.title, path);
|
|||
|
},
|
|||
|
},
|
|||
|
// components: ["Paginate"],
|
|||
|
};
|
|||
|
</script>
|
|||
|
|
|||
|
<style scoped>
|
|||
|
.form-control[type="number"] {
|
|||
|
width: 4em;
|
|||
|
text-align: center;
|
|||
|
}
|
|||
|
</style>
|