diff --git a/manager/src/utils/useTable.js b/manager/src/utils/useTable.js new file mode 100644 index 000000000..69af9ba76 --- /dev/null +++ b/manager/src/utils/useTable.js @@ -0,0 +1,119 @@ +import { onMounted, reactive, ref } from "vue"; + +/** + * 分页列表通用逻辑:loading / data / total / searchForm / 查询 / 重置 / 刷新。 + * + * 用法: + * const { loading, data, total, searchForm, getDataList, handleSearch, resetSearch } = + * useTable(getXxxPage, { form: { name: "", status: "" } }); + * + * + * + * + * @param {(params: object) => Promise} fetcher 请求函数,入参为 searchForm + * @param {object} [options] + * @param {object} [options.form] 查询条件默认值(会与分页/排序默认值合并) + * @param {number} [options.pageSize=10] 默认每页条数 + * @param {string} [options.sort] 默认排序字段 + * @param {string} [options.order] 默认排序方向 + * @param {boolean} [options.immediate=true] 挂载后是否自动查询 + * @param {(res: any) => ({records: any[], total: number}|null|undefined)} [options.resolve] + * 从响应中取出 { records, total };返回空表示请求失败(保持原数据)。 + * 默认:res.success 为真时取 res.result.records / res.result.total + * @param {(params: object) => object} [options.beforeRequest] 请求前加工参数(返回新对象,不影响 searchForm) + * @param {(res: any, parsed: {records: any[], total: number}) => void} [options.onSuccess] + * 查询成功且数据已更新后回调(仅最后一次请求触发),可用于刷新状态计数等 + */ +export function useTable(fetcher, options = {}) { + const { + form = {}, + pageSize = 10, + sort, + order, + immediate = true, + resolve = defaultResolve, + beforeRequest, + onSuccess, + } = options; + + const loading = ref(false); + const data = ref([]); + const total = ref(0); + + const initialForm = { ...form }; + const searchForm = reactive({ + pageNumber: 1, + pageSize, + ...(sort ? { sort } : {}), + ...(order ? { order } : {}), + ...form, + }); + + // 只采纳最后一次请求的结果,避免快速切换页码/条件时旧响应覆盖新数据 + let requestId = 0; + + function getDataList() { + const current = ++requestId; + loading.value = true; + const params = beforeRequest ? beforeRequest({ ...searchForm }) : searchForm; + return Promise.resolve(fetcher(params)) + .then((res) => { + if (current !== requestId) return res; + const parsed = resolve(res); + if (parsed) { + data.value = parsed.records || []; + total.value = parsed.total || 0; + if (onSuccess) onSuccess(res, parsed); + } + return res; + }) + .finally(() => { + if (current === requestId) loading.value = false; + }); + } + + /** 以当前条件从第 1 页重新查询 */ + function handleSearch() { + searchForm.pageNumber = 1; + return getDataList(); + } + + /** 恢复查询条件默认值(保留当前每页条数)并从第 1 页查询 */ + function resetSearch() { + Object.assign(searchForm, initialForm); + return handleSearch(); + } + + /** 保持当前页刷新(如删除/修改后) */ + function refresh() { + return getDataList(); + } + + if (immediate) { + onMounted(getDataList); + } + + return { + loading, + data, + total, + searchForm, + getDataList, + handleSearch, + resetSearch, + refresh, + }; +} + +function defaultResolve(res) { + if (res && res.success && res.result) { + return { records: res.result.records, total: res.result.total }; + } + return null; +} diff --git a/manager/src/views/finance/refundLog.vue b/manager/src/views/finance/refundLog.vue index 175036a98..871fcc30c 100644 --- a/manager/src/views/finance/refundLog.vue +++ b/manager/src/views/finance/refundLog.vue @@ -35,35 +35,18 @@