refactor(frontend): 优化列表页缓存与数据刷新逻辑

1. 为详情、评论接口添加禁用缓存配置,获取实时数据
2. 重构useListPage,新增refreshData和reload方法统一数据刷新逻辑
3. 替换原有loadData调用,统一列表页数据更新流程
4. 移除冗余的force缓存配置,通过method.config自定义缓存策略
This commit is contained in:
zhangtao
2026-09-13 14:40:14 +08:00
parent f15fdb86c0
commit 8291c1a494
5 changed files with 60 additions and 20 deletions
+4 -2
View File
@@ -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)
+8 -4
View File
@@ -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)
+34 -4
View File
@@ -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()