mirror of
https://github.com/fastapiadmin/FastapiAdmin.git
synced 2026-10-16 13:50:28 +00:00
refactor(frontend): 优化列表页缓存与数据刷新逻辑
1. 为详情、评论接口添加禁用缓存配置,获取实时数据 2. 重构useListPage,新增refreshData和reload方法统一数据刷新逻辑 3. 替换原有loadData调用,统一列表页数据更新流程 4. 移除冗余的force缓存配置,通过method.config自定义缓存策略
This commit is contained in:
@@ -11,8 +11,10 @@ export const NoticeAPI = {
|
||||
getPage(params?: Record<string, any>) {
|
||||
return http.Get<PageResult<NoticeItem>>(`${SYSTEM_BASE}/notice/list`, params)
|
||||
},
|
||||
getDetail(id: number): Promise<NoticeItem> {
|
||||
return http.Get(`${SYSTEM_BASE}/notice/detail/${id}`)
|
||||
getDetail(id: number) {
|
||||
const method = http.Get<NoticeItem>(`${SYSTEM_BASE}/notice/detail/${id}`)
|
||||
method.config.cacheFor = 0
|
||||
return method
|
||||
},
|
||||
create(data: NoticeForm): Promise<NoticeItem> {
|
||||
return http.Post(`${SYSTEM_BASE}/notice/create`, data)
|
||||
|
||||
@@ -10,8 +10,10 @@ export const TicketAPI = {
|
||||
getPage(params?: Record<string, any>) {
|
||||
return http.Get<PageResult<TicketItem>>(`${SYSTEM_BASE}/ticket/list`, params)
|
||||
},
|
||||
getDetail(id: number): Promise<TicketItem> {
|
||||
return http.Get(`${SYSTEM_BASE}/ticket/detail/${id}`)
|
||||
getDetail(id: number) {
|
||||
const method = http.Get<TicketItem>(`${SYSTEM_BASE}/ticket/detail/${id}`)
|
||||
method.config.cacheFor = 0
|
||||
return method
|
||||
},
|
||||
create(data: TicketForm): Promise<TicketItem> {
|
||||
return http.Post(`${SYSTEM_BASE}/ticket/create`, data)
|
||||
@@ -28,8 +30,10 @@ export const TicketAPI = {
|
||||
exportTickets(params?: Record<string, any>): Promise<unknown> {
|
||||
return http.Post(`${SYSTEM_BASE}/ticket/export`, params)
|
||||
},
|
||||
getComments(ticketId: number, params?: Record<string, any>): Promise<PageResult<TicketComment>> {
|
||||
return http.Get(`${SYSTEM_BASE}/ticket/${ticketId}/comments`, params)
|
||||
getComments(ticketId: number, params?: Record<string, any>) {
|
||||
const method = http.Get<PageResult<TicketComment>>(`${SYSTEM_BASE}/ticket/${ticketId}/comments`, params)
|
||||
method.config.cacheFor = 0
|
||||
return method
|
||||
},
|
||||
createComment(ticketId: number, data: { content: string }): Promise<TicketComment> {
|
||||
return http.Post(`${SYSTEM_BASE}/ticket/${ticketId}/comments`, data)
|
||||
|
||||
@@ -30,9 +30,16 @@ export function useListPage<T, AG extends AlovaGenerics = AlovaGenerics>(options
|
||||
loading,
|
||||
error,
|
||||
send,
|
||||
refresh,
|
||||
reload: reloadPagination,
|
||||
onError: onPageError,
|
||||
} = usePagination<AG, T[], any[]>(
|
||||
(pageNo: number, pageSizeNo: number) => fetcher({ page_no: pageNo, page_size: pageSizeNo }),
|
||||
(pageNo: number, pageSizeNo: number) => {
|
||||
const method = fetcher({ page_no: pageNo, page_size: pageSizeNo })
|
||||
// 列表页要求实时数据,禁用 alova GET 默认 5 分钟请求缓存
|
||||
method.config.cacheFor = 0
|
||||
return method
|
||||
},
|
||||
{
|
||||
initialPage: 1,
|
||||
initialPageSize: pageSize,
|
||||
@@ -41,8 +48,6 @@ export function useListPage<T, AG extends AlovaGenerics = AlovaGenerics>(options
|
||||
watchingStates: [],
|
||||
preloadNextPage: false,
|
||||
preloadPreviousPage: false,
|
||||
// 列表页总是请求最新数据,禁用 alova 响应缓存
|
||||
force: true,
|
||||
// 响应已由 http 层 responded 解包为业务结构 { list, total }
|
||||
data: res => (res as PageResult<T>).list ?? [],
|
||||
total: res => (res as PageResult<T>).total ?? 0,
|
||||
@@ -53,7 +58,7 @@ export function useListPage<T, AG extends AlovaGenerics = AlovaGenerics>(options
|
||||
onError?.(e)
|
||||
})
|
||||
|
||||
/** 加载当前页数据 */
|
||||
/** 加载当前页数据(翻页用,命中 usePagination 分页缓存时不重复请求) */
|
||||
async function loadData() {
|
||||
try {
|
||||
await send(pageParams.value.page_no, pageParams.value.page_size)
|
||||
@@ -67,6 +72,29 @@ export function useListPage<T, AG extends AlovaGenerics = AlovaGenerics>(options
|
||||
}
|
||||
}
|
||||
|
||||
/** 强制刷新当前页(忽略缓存重新请求,下拉刷新场景) */
|
||||
async function refreshData() {
|
||||
try {
|
||||
await refresh(pageParams.value.page_no)
|
||||
}
|
||||
catch {}
|
||||
finally {
|
||||
uni.stopPullDownRefresh()
|
||||
}
|
||||
}
|
||||
|
||||
/** 从第 1 页重新加载并清除分页缓存(创建/更新/删除后调用,确保看到最新数据) */
|
||||
async function reload() {
|
||||
pageParams.value.page_no = 1
|
||||
try {
|
||||
await reloadPagination()
|
||||
}
|
||||
catch {}
|
||||
finally {
|
||||
uni.stopPullDownRefresh()
|
||||
}
|
||||
}
|
||||
|
||||
/** 上一页 */
|
||||
async function loadPrev() {
|
||||
if (pageParams.value.page_no <= 1)
|
||||
@@ -94,6 +122,8 @@ export function useListPage<T, AG extends AlovaGenerics = AlovaGenerics>(options
|
||||
error,
|
||||
pageParams,
|
||||
loadData,
|
||||
refreshData,
|
||||
reload,
|
||||
loadPrev,
|
||||
loadNext,
|
||||
toFirst,
|
||||
|
||||
@@ -30,7 +30,7 @@ const STATUS_OPTIONS = [
|
||||
/** 公告状态:数字 → StatusBadge 内置 key,由 StatusBadge 的 map prop 一次性映射 */
|
||||
const NOTICE_STATUS_MAP: Record<string, string> = { 0: 'draft', 1: 'published', 2: 'archived' }
|
||||
|
||||
const { list, total, loading, loadData, toFirst, loadNext } = useListPage<NoticeItem>({
|
||||
const { list, total, loading, loadData, reload, refreshData, toFirst, loadNext } = useListPage<NoticeItem>({
|
||||
fetcher: p => NoticeAPI.getPage({ ...p, notice_title: searchTitle.value || undefined }),
|
||||
onError: () => toast.error(t('common.loadFailed')),
|
||||
})
|
||||
@@ -73,13 +73,15 @@ async function handleSubmit() {
|
||||
if (currentId.value) {
|
||||
await NoticeAPI.update(currentId.value, formData)
|
||||
toast.success(t('common.updateSuccess'))
|
||||
showForm.value = false
|
||||
refreshData()
|
||||
}
|
||||
else {
|
||||
await NoticeAPI.create(formData)
|
||||
toast.success(t('common.createSuccess'))
|
||||
showForm.value = false
|
||||
reload()
|
||||
}
|
||||
showForm.value = false
|
||||
loadData()
|
||||
}
|
||||
catch { toast.error(t('common.operationFailed')) }
|
||||
finally { loading.value = false }
|
||||
@@ -94,7 +96,7 @@ function handleDelete(id: number) {
|
||||
try {
|
||||
await NoticeAPI.remove([id])
|
||||
toast.success(t('common.deleteSuccess'))
|
||||
loadData()
|
||||
refreshData()
|
||||
}
|
||||
catch { toast.error(t('common.deleteFailed')) }
|
||||
}
|
||||
@@ -108,7 +110,7 @@ onReachBottom(() => {
|
||||
})
|
||||
onPullDownRefresh(async () => {
|
||||
try {
|
||||
await loadData()
|
||||
await refreshData()
|
||||
}
|
||||
finally {
|
||||
uni.stopPullDownRefresh()
|
||||
|
||||
@@ -79,7 +79,7 @@ function statusLabel(status: number | string | undefined) {
|
||||
const typePickerColumns = computed(() => [TYPE_OPTIONS.map(o => ({ value: o.value, label: t(o.labelKey) }))])
|
||||
const statusPickerColumns = computed(() => [STATUS_OPTIONS.map(o => ({ value: o.value, label: t(o.labelKey) }))])
|
||||
|
||||
const { list, total, loading, loadData, toFirst, loadNext } = useListPage<TicketItem>({
|
||||
const { list, total, loading, loadData, reload, refreshData, toFirst, loadNext } = useListPage<TicketItem>({
|
||||
fetcher: p => TicketAPI.getPage({
|
||||
...p,
|
||||
title: searchTitle.value || undefined,
|
||||
@@ -137,13 +137,15 @@ async function handleSubmit() {
|
||||
if (currentId.value) {
|
||||
await TicketAPI.update(currentId.value, { ...formData })
|
||||
toast.success(t('common.updateSuccess'))
|
||||
showForm.value = false
|
||||
refreshData()
|
||||
}
|
||||
else {
|
||||
await TicketAPI.create({ ...formData })
|
||||
toast.success(t('common.createSuccess'))
|
||||
showForm.value = false
|
||||
reload()
|
||||
}
|
||||
showForm.value = false
|
||||
loadData()
|
||||
}
|
||||
catch { toast.error(t('common.operationFailed')) }
|
||||
finally { loading.value = false }
|
||||
@@ -157,7 +159,7 @@ function handleDelete(id: number) {
|
||||
try {
|
||||
await TicketAPI.remove([id])
|
||||
toast.success(t('common.deleteSuccess'))
|
||||
loadData()
|
||||
refreshData()
|
||||
}
|
||||
catch { toast.error(t('common.deleteFailed')) }
|
||||
}
|
||||
@@ -171,7 +173,7 @@ onReachBottom(() => {
|
||||
})
|
||||
onPullDownRefresh(async () => {
|
||||
try {
|
||||
await loadData()
|
||||
await refreshData()
|
||||
}
|
||||
finally {
|
||||
uni.stopPullDownRefresh()
|
||||
|
||||
Reference in New Issue
Block a user