kui-vue
Version:
A lightweight desktop UI component library suitable for Vue.js 2.
360 lines (351 loc) • 9.97 kB
JSX
import { Select } from "../select";
import { Input } from "../input";
import Icon from "../icon";
import {
ChevronUp,
ChevronDoubleBack,
Ellipsis,
ChevronDoubleForward,
} from "kui-icons";
import { ref, defineComponent, watch, inject, nextTick, computed } from "vue";
import { withInstall } from "../utils/vue";
import zhCN from "../locale/zh-CN";
const Page = defineComponent({
name: "Page",
props: {
disabled: Boolean,
showSizer: Boolean,
showTotal: { type: Boolean, default: true },
showElevator: Boolean,
theme: String,
sizeData: { type: Array, default: () => [10, 15, 20, 30, 40] },
size: {
default: "default",
validator(value) {
return ["small", "large", "default"].indexOf(value) >= 0;
},
},
total: { default: 0, type: Number },
pageSize: { default: 10, type: Number },
current: { default: 1, type: Number },
},
setup(ps, { emit }) {
const nextPageGroup = ref(false);
const prevPageGroup = ref(false);
const pageCount = ref(Math.ceil(ps.total / ps.pageSize) || 1);
const defaultPage = ref(ps.current);
const defaultPageSize = ref(ps.pageSize);
const injectedLocale = inject("locale", zhCN);
const locale = computed(() => {
return injectedLocale instanceof Object && "value" in injectedLocale
? injectedLocale.value
: injectedLocale;
});
watch(
() => ps.pageSize,
(v) => {
defaultPageSize.value = v;
resetPage();
}
);
watch(
() => ps.total,
(v) => {
resetPage();
}
);
watch(
() => ps.current,
(v) => {
defaultPage.value = v;
resetPage();
}
);
const resetPage = () => {
pageCount.value = Math.ceil(ps.total / defaultPageSize.value) || 1;
if (defaultPage.value > pageCount.value) {
defaultPage.value = pageCount.value;
}
};
const renderPage = () => {
const groupCount = 7,
page = Number(defaultPage.value),
pCount = Number(pageCount.value);
let showPrevMore = false;
let showNextMore = false;
if (pCount > groupCount) {
if (page > groupCount - 3) {
showPrevMore = true;
}
if (page < pCount - 3) {
showNextMore = true;
}
}
const array = [];
if (showPrevMore && !showNextMore) {
const startPage = pCount - (groupCount - 2);
for (let i = startPage; i < pCount; i++) {
array.push(i);
}
} else if (!showPrevMore && showNextMore) {
for (let i = 2; i < groupCount; i++) {
array.push(i);
}
} else if (showPrevMore && showNextMore) {
const offset = Math.floor(groupCount / 2) - 1;
for (let i = page - offset; i <= page + offset; i++) {
array.push(i);
}
} else {
for (let i = 2; i < pCount; i++) {
array.push(i);
}
}
let child = array.map((p, i) => {
let prop = {
class: ["k-pager-item", { "k-pager-item-active": page == p }],
key: i,
on: {
click: () => toPage(p),
},
};
return (
<li {...prop}>
<span>{p}</span>
</li>
);
});
if (showPrevMore) {
let p = {
class: "k-pager-item k-pager-more",
on: {
mouseenter: () => (prevPageGroup.value = true),
mouseleave: () => (prevPageGroup.value = false),
click: () => toPage(defaultPage.value - 5),
},
};
const moreNode = (
<li {...p}>
<Icon
strokeWidth={30}
type={prevPageGroup.value ? ChevronDoubleBack : Ellipsis}
/>
</li>
);
child.unshift(moreNode);
}
if (showNextMore) {
let p = {
class: "k-pager-item k-pager-more",
on: {
mouseenter: () => (nextPageGroup.value = true),
mouseleave: () => (nextPageGroup.value = false),
click: () => toPage(defaultPage.value + 5),
},
};
const moreNode = (
<li {...p}>
<Icon
strokeWidth={30}
type={nextPageGroup.value ? ChevronDoubleForward : Ellipsis}
/>
</li>
);
child.push(moreNode);
}
return child;
};
const prePage = () => {
if (ps.disabled) return;
if (defaultPage.value > 1) {
defaultPage.value--;
emit("update:current", defaultPage.value);
emit("change", defaultPage.value, defaultPageSize.value);
}
};
const nextPage = () => {
if (ps.disabled) return;
if (defaultPage.value < pageCount.value) {
defaultPage.value++;
emit("update:current", defaultPage.value);
emit("change", defaultPage.value, defaultPageSize.value);
}
};
const toPage = (page) => {
if (ps.disabled) return;
if (page == defaultPage.value) return;
if (page <= 1) {
page = 1;
prevPageGroup.value = false;
}
if (page >= pageCount.value) {
nextPageGroup.value = false;
page = pageCount.value;
}
defaultPage.value = page;
emit("update:current", page);
emit("change", defaultPage.value, defaultPageSize.value);
};
const changeSize = (value) => {
defaultPageSize.value = value;
pageCount.value = Math.ceil(ps.total / defaultPageSize.value) || 1;
if (defaultPage.value > pageCount.value) {
defaultPage.value = pageCount.value;
emit("update:current", defaultPage.value);
}
emit("change", defaultPage.value, defaultPageSize.value);
};
const renderFirst = () => {
if (pageCount.value > 0) {
return (
<li
class={[
"k-pager-item",
{ "k-pager-item-active": defaultPage.value == 1 },
]}
onClick={() => toPage(1)}
>
<span>1</span>
</li>
);
}
return null;
};
const renderLast = () => {
let pCount = pageCount.value;
if (pCount > 1) {
return (
<li
class={[
"k-pager-item",
{ "k-pager-item-active": defaultPage.value == pCount },
]}
onClick={(e) => toPage(pCount)}
>
<span>{pCount}</span>
</li>
);
}
return null;
};
const renderSize = () => {
let prop = {
props: {
value: defaultPageSize.value,
size: ps.size,
clearable: false,
theme: ps.theme,
options: ps.sizeData.map((s) => {
return { value: s, label: `${s}${locale?.value.k.page.pageSize}` };
}),
disabled: ps.disabled,
},
on: {
change: changeSize,
},
};
return ps.showSizer ? (
<div class="k-page-sizer">{<Select {...prop} />}</div>
) : null;
};
const renderElevator = () => {
let { size } = ps;
let prop = {
class: "k-page-options-elevator",
props: {
size,
theme: ps.theme,
disabled: ps.disabled,
},
// value: defaultPage.value,
on: {
change: (e) => {
let page = e.target.value;
if (Number(page) == NaN) {
e.target.value = "";
return;
}
page = Number(page);
let pCount = pageCount.value;
if (page > pCount) page = pCount;
if (page < 1) page = 1;
if ((page >= 1 || page <= pCount) && defaultPage.value != page) {
defaultPage.value = page;
emit("update:current", page);
emit("change", page, defaultPageSize.value);
}
nextTick(() => {
e.target.value = "";
});
e.stopPropagation();
},
},
// onChange: (e) => {
// // e.stopPropagation();
// },
};
return ps.showElevator ? (
<div class="k-page-options">
<span>{locale?.value.k.page.goto}</span>
<Input {...prop} />
<span>{locale?.value.k.page.page}</span>
</div>
) : null;
};
return () => {
const classes = [
"k-page",
{
["k-page-sm"]: ps.size == "small",
"k-page-light": ps.theme == "light",
"k-page-disabled": ps.disabled,
},
],
preNode = (
<li
class={[
"k-pager-item k-pager-prev",
{ "k-pager-item-disabled": defaultPage.value == 1 },
]}
onClick={prePage}
>
<Icon type={ChevronUp} />
</li>
),
nextNode = (
<li
class={[
"k-pager-item k-pager-next",
{ "k-pager-item-disabled": defaultPage.value == pageCount.value },
]}
onClick={nextPage}
>
<Icon type={ChevronUp} />
</li>
),
totalNode = ps.showTotal ? (
<div class="k-page-number">
<span>
{locale?.value.k.page.total} {ps.total}{" "}
{locale?.value.k.page.items}
</span>
</div>
) : null,
pagerNode = renderPage(),
sizeNode = renderSize(),
elevatorNode = renderElevator(),
firstNode = renderFirst(),
lastNode = renderLast();
return (
<div class={classes}>
{totalNode}
<ul class="k-pager">
{[preNode, firstNode, pagerNode, lastNode, nextNode]}
</ul>
{[sizeNode, elevatorNode]}
</div>
);
};
},
});
export default withInstall(Page);