feat: Architecture initialization
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
// src/hooks/usePagination.ts
|
||||
import { computed, ref, watch, Ref, triggerRef } from 'vue';
|
||||
|
||||
/**
|
||||
* 分页配置项
|
||||
*/
|
||||
export interface UsePaginationOptions {
|
||||
/** 当前页码 (支持 v-model 双向绑定) */
|
||||
current?: number;
|
||||
/** 每页条数 (支持 v-model 双向绑定) */
|
||||
pageSize?: number;
|
||||
/** 数据总条数 (支持 v-model 双向绑定) */
|
||||
total?: number;
|
||||
/** 默认页码 (非受控模式下使用) */
|
||||
defaultCurrent?: number;
|
||||
/** 默认每页条数 (非受控模式下使用) */
|
||||
defaultPageSize?: number;
|
||||
/** 每页条数切换选项 (用于生成下拉菜单) */
|
||||
pageSizeOptions?: number[];
|
||||
/** 是否显示快速跳转 (可选功能) */
|
||||
showQuickJumper?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页操作 API
|
||||
*/
|
||||
export interface UsePaginationActions {
|
||||
/** 设置当前页 */
|
||||
setCurrent: (current: number) => void;
|
||||
/** 设置每页条数 (会自动重置页码为 1) */
|
||||
setPageSize: (size: number) => void;
|
||||
/** 设置总条数 */
|
||||
setTotal: (total: number) => void;
|
||||
/** 下一页 */
|
||||
next: () => void;
|
||||
/** 上一页 */
|
||||
prev: () => void;
|
||||
/** 跳转到指定页 */
|
||||
jump: (page: number) => void;
|
||||
/** 重置到初始状态 */
|
||||
reset: () => void;
|
||||
/** 强制刷新 (用于某些极端响应式场景) */
|
||||
refresh: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页计算属性
|
||||
*/
|
||||
export interface UsePaginationComputed {
|
||||
/** 响应式请求参数对象 (给 API 用的) */
|
||||
params: Ref<{ page: number; pageSize: number }>;
|
||||
/** 总页数 */
|
||||
totalPages: Ref<number>;
|
||||
/** 是否有上一页 */
|
||||
hasPrev: Ref<boolean>;
|
||||
/** 是否有下一页 */
|
||||
hasNext: Ref<boolean>;
|
||||
/** 当前页起始索引 (用于显示 "显示 1-10 条") */
|
||||
startIndex: Ref<number>;
|
||||
/** 当前页结束索引 */
|
||||
endIndex: Ref<number>;
|
||||
/** 是否为第一页 */
|
||||
isFirstPage: Ref<boolean>;
|
||||
/** 是否为最后一页 */
|
||||
isLastPage: Ref<boolean>;
|
||||
}
|
||||
|
||||
export type UsePaginationReturn = UsePaginationOptions &
|
||||
UsePaginationActions &
|
||||
UsePaginationComputed;
|
||||
|
||||
export function usePagination(options: UsePaginationOptions = {}): UsePaginationReturn {
|
||||
const { defaultCurrent = 1, defaultPageSize = 10, pageSizeOptions = [10, 20, 50, 100] } = options;
|
||||
|
||||
const currentRef = ref(options.current ?? defaultCurrent);
|
||||
const pageSizeRef = ref(options.pageSize ?? defaultPageSize);
|
||||
const totalRef = ref(options.total ?? 0);
|
||||
|
||||
watch(
|
||||
() => options.current,
|
||||
(val) => {
|
||||
if (val !== undefined) currentRef.value = val;
|
||||
},
|
||||
);
|
||||
watch(
|
||||
() => options.pageSize,
|
||||
(val) => {
|
||||
if (val !== undefined) pageSizeRef.value = val;
|
||||
},
|
||||
);
|
||||
watch(
|
||||
() => options.total,
|
||||
(val) => {
|
||||
if (val !== undefined) totalRef.value = val;
|
||||
},
|
||||
);
|
||||
|
||||
const totalPages = computed(() => {
|
||||
const total = totalRef.value;
|
||||
const size = pageSizeRef.value;
|
||||
return size === 0 ? 0 : Math.ceil(total / size);
|
||||
});
|
||||
|
||||
const hasPrev = computed(() => currentRef.value > 1);
|
||||
const hasNext = computed(() => currentRef.value < totalPages.value);
|
||||
const isFirstPage = computed(() => currentRef.value === 1);
|
||||
const isLastPage = computed(() => currentRef.value === totalPages.value);
|
||||
|
||||
const startIndex = computed(() =>
|
||||
totalPages.value === 0 ? 0 : (currentRef.value - 1) * pageSizeRef.value + 1,
|
||||
);
|
||||
|
||||
const endIndex = computed(() => Math.min(currentRef.value * pageSizeRef.value, totalRef.value));
|
||||
|
||||
const params = computed(() => ({
|
||||
page: currentRef.value,
|
||||
pageSize: pageSizeRef.value,
|
||||
}));
|
||||
|
||||
const setCurrent = (page: number) => {
|
||||
const safePage = Math.max(1, Math.min(page, totalPages.value || 1));
|
||||
if (currentRef.value !== safePage) {
|
||||
currentRef.value = safePage;
|
||||
}
|
||||
};
|
||||
|
||||
const setPageSize = (size: number) => {
|
||||
if (pageSizeRef.value !== size) {
|
||||
pageSizeRef.value = size;
|
||||
currentRef.value = 1;
|
||||
}
|
||||
};
|
||||
|
||||
const setTotal = (total: number) => {
|
||||
totalRef.value = total;
|
||||
const maxPage = Math.max(1, Math.ceil(total / pageSizeRef.value));
|
||||
if (currentRef.value > maxPage) {
|
||||
currentRef.value = maxPage;
|
||||
}
|
||||
};
|
||||
|
||||
const next = () => setCurrent(currentRef.value + 1);
|
||||
const prev = () => setCurrent(currentRef.value - 1);
|
||||
|
||||
const jump = (page: number) => {
|
||||
if (!Number.isInteger(page) || page < 1) return;
|
||||
setCurrent(page);
|
||||
};
|
||||
|
||||
const reset = () => {
|
||||
currentRef.value = defaultCurrent;
|
||||
pageSizeRef.value = defaultPageSize;
|
||||
};
|
||||
|
||||
const refresh = () => {
|
||||
triggerRef(currentRef);
|
||||
};
|
||||
|
||||
return {
|
||||
// @ts-ignore
|
||||
current: currentRef,
|
||||
// @ts-ignore
|
||||
pageSize: pageSizeRef,
|
||||
// @ts-ignore
|
||||
total: totalRef,
|
||||
pageSizeOptions,
|
||||
params,
|
||||
totalPages,
|
||||
hasPrev,
|
||||
hasNext,
|
||||
isFirstPage,
|
||||
isLastPage,
|
||||
startIndex,
|
||||
endIndex,
|
||||
setCurrent,
|
||||
setPageSize,
|
||||
setTotal,
|
||||
next,
|
||||
prev,
|
||||
jump,
|
||||
reset,
|
||||
refresh,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user