| import { | 
|   useInfiniteQuery, | 
|   QueryKey, | 
|   useMutation, | 
|   useQueryClient, | 
|   InfiniteData, | 
|   RefetchOptions, | 
|   RefetchQueryFilters, | 
| } from '@tanstack/vue-query'; | 
| import { UnwrapNestedRefs, Ref, ref, reactive, computed } from 'vue'; | 
| import Taro from '@tarojs/taro'; | 
|   | 
| export type BaseData<T = any> = { | 
|   data?: T[]; | 
|   objectData?: any; | 
|   pageModel?: { | 
|     rows?: number; | 
|     page?: number; | 
|     totalCount?: number; | 
|     totalPage?: number; | 
|   }; | 
| }; | 
|   | 
| export interface OrderInput { | 
|   property?: string; | 
|   order?: number; | 
| } | 
|   | 
| export type ExtraParams = { | 
|   [key: string]: any; | 
|   orderByProperty?: string; | 
| }; | 
|   | 
| export type ServiceContext = { | 
|   pageParam?: any; | 
|   signal?: AbortSignal; | 
| }; | 
|   | 
| export type InfiniteGroupOptions = { | 
|   groupIndex?: number; | 
|   itemIndex?: number; | 
| }; | 
|   | 
| type Service<TData, TExtraParams extends ExtraParams> = ( | 
|   context: ServiceContext, | 
|   extraParamsState: UnwrapNestedRefs<TExtraParams> | 
| ) => Promise<TData>; | 
|   | 
| type UseInfiniteLoadingOptions<T, TExtraParams extends ExtraParams> = { | 
|   /** | 
|    * @deprecated | 
|    */ | 
|   defaultExtraParams?: TExtraParams; | 
|   enabled?: Ref<boolean> | boolean; | 
|   queryKey?: QueryKey; | 
|   onSuccess?: (data: InfiniteData<BaseData<T>>) => void; | 
|   onRefetch?: () => any; | 
|   useLocalData?: boolean; | 
|   refeshDidShow?: boolean; | 
|   select?: (data: InfiniteData<BaseData<T>>) => InfiniteData<BaseData<T>>; | 
| }; | 
| // QueryFunction<BaseData<T>, (string | DeepUnwrapRef<UnwrapNestedRefs<TExtraParams>>)[], any> | 
| export function useInfiniteLoading<T, TExtraParams extends ExtraParams>( | 
|   service: Service<BaseData<T>, TExtraParams>, | 
|   options: UseInfiniteLoadingOptions<T, TExtraParams> = {} | 
| ) { | 
|   const { | 
|     defaultExtraParams = {} as TExtraParams, | 
|     enabled = ref(true), | 
|     queryKey, | 
|     onSuccess, | 
|     onRefetch: _onRefetch, | 
|     useLocalData = false, | 
|     refeshDidShow = true, | 
|     select, | 
|   } = options; | 
|   | 
|   const extraParamState = reactive({ | 
|     ...defaultExtraParams, | 
|   }); | 
|   | 
|   const localData = ref({ | 
|     pageParams: [], | 
|     pages: [], | 
|   }); | 
|   | 
|   const { | 
|     data, | 
|     error, | 
|     fetchNextPage, | 
|     hasNextPage, | 
|     isFetching, | 
|     isFetchingNextPage, | 
|     isLoading, | 
|     isError, | 
|     refetch, | 
|     isInitialLoading, | 
|     fetchPreviousPage, | 
|     hasPreviousPage, | 
|   } = useInfiniteQuery({ | 
|     queryKey: queryKey, | 
|     queryFn: ({ pageParam = 1, signal }) => { | 
|       return service({ pageParam, signal }, extraParamState); | 
|     }, | 
|     // initialPageParam: 1, | 
|     getNextPageParam: (lastPage, pages) => { | 
|       if (!lastPage) return 1; | 
|       if ( | 
|         (lastPage.pageModel.page - 1) * lastPage.pageModel.rows + lastPage.data.length < | 
|           lastPage.pageModel.totalCount && | 
|         lastPage.pageModel.totalCount > 0 | 
|       ) { | 
|         return lastPage.pageModel.page + 1; | 
|       } | 
|     }, | 
|     getPreviousPageParam: (firstPage, pages) => { | 
|       if (!firstPage) return 1; | 
|       if ( | 
|         (firstPage.pageModel.page - 1) * firstPage.pageModel.rows + firstPage.data.length < | 
|           firstPage.pageModel.totalCount && | 
|         firstPage.pageModel.totalCount > 0 | 
|       ) { | 
|         return firstPage.pageModel.page + 1; | 
|       } | 
|     }, | 
|     enabled: enabled, | 
|     onSuccess(data) { | 
|       // console.log('data2: ', data); | 
|       localData.value.pageParams = data.pageParams; | 
|       //@ts-ignore | 
|       localData.value.pages = data.pages; | 
|       onSuccess?.(data); | 
|     }, | 
|     select(data) { | 
|       return select ? select(data) : data; | 
|     }, | 
|   }); | 
|   | 
|   const _data = computed<InfiniteData<BaseData<T>>>(() => | 
|     useLocalData ? (localData.value as any) : data.value | 
|   ); | 
|   | 
|   const queryClient = useQueryClient(); | 
|   | 
|   const { mutateAsync } = useMutation({ | 
|     mutationFn: ({ pageParam }: ServiceContext) => fetchNextPage(pageParam), | 
|   | 
|     // onSettled: async () => { | 
|     //   return await queryClient.invalidateQueries({ queryKey: queryKey }); | 
|     // }, | 
|   }); | 
|   | 
|   const { mutate: setListItem } = useMutation({ | 
|     mutationFn: (data: { dataKey?: string; data: Partial<T> }) => { | 
|       return Promise.resolve(data); | 
|     }, | 
|     onSuccess: ({ dataKey = 'id', data }) => { | 
|       console.log('dataKey: ', data); | 
|       const pagesArray: InfiniteData<BaseData<T>> = useLocalData | 
|         ? localData.value | 
|         : queryClient.getQueryData(queryKey); | 
|       console.log('pagesArray: ', pagesArray); | 
|       const newPagesArray = | 
|         pagesArray?.pages.map((page) => { | 
|           return { | 
|             ...page, | 
|             data: page.data.map((item) => { | 
|               if (item[dataKey] === data[dataKey]) { | 
|                 return { | 
|                   ...item, | 
|                   ...data, | 
|                 }; | 
|               } else { | 
|                 return item; | 
|               } | 
|             }), | 
|           }; | 
|         }) ?? []; | 
|       if (useLocalData) { | 
|         console.log('newPagesArray: ', newPagesArray); | 
|         localData.value.pageParams = pagesArray.pageParams; | 
|         localData.value.pages = newPagesArray; | 
|       } else { | 
|         queryClient.setQueryData(queryKey, () => ({ | 
|           pages: newPagesArray, | 
|           pageParams: pagesArray.pageParams, | 
|         })); | 
|       } | 
|     }, | 
|   }); | 
|   | 
|   function onRefetch(options?: RefetchOptions & RefetchQueryFilters<unknown>) { | 
|     _onRefetch?.(); | 
|     return refetch(options); | 
|   } | 
|   | 
|   const infiniteLoadingProps = computed(() => ({ | 
|     fetchNextPage, | 
|     listData: _data.value, | 
|     flattenListData: flattenListData.value, | 
|     // error: error.value, | 
|     hasMore: hasNextPage.value, | 
|     isFetching: isFetching.value, | 
|     isFetchingNextPage: isFetchingNextPage.value, | 
|     isLoading: isLoading.value, | 
|     isError: !!isError.value, | 
|     refetch: onRefetch, | 
|   })); | 
|   | 
|   const flattenListData = computed(() => { | 
|     let list: BaseData<T>['data'] = []; | 
|     if (data && _data.value) { | 
|       _data.value?.pages.forEach((group) => { | 
|         group.data.forEach((item) => { | 
|           list.push(item); | 
|         }); | 
|       }); | 
|     } | 
|     return list; | 
|   }); | 
|   | 
|   if (refeshDidShow) { | 
|     useRefeshDidShow({ queryKey: queryKey }); | 
|   } | 
|   | 
|   const infiniteLoadingRef = ref<{ backToTop(): void; scrollToBottom(dis?: number): void }>(); | 
|   | 
|   function setByIndex(options: InfiniteGroupOptions = {}) { | 
|     refetch({ refetchPage: (page, index) => index === options.groupIndex, type: 'inactive' }); | 
|   } | 
|   | 
|   function updatePageByIndex(options: InfiniteGroupOptions = {}) { | 
|     refetch({ refetchPage: (page, index) => index === options.groupIndex, type: 'inactive' }); | 
|   } | 
|   | 
|   function remove() { | 
|     queryClient.invalidateQueries({ queryKey: queryKey }); | 
|   } | 
|   | 
|   function invalidateQueries() { | 
|     return queryClient.invalidateQueries({ queryKey: queryKey }); | 
|   } | 
|   | 
|   const listActions = { | 
|     setByIndex, | 
|     updatePageByIndex, | 
|     remove, | 
|   }; | 
|   | 
|   return { | 
|     infiniteLoadingProps, | 
|     flattenListData, | 
|     extraParamState, | 
|     mutateAsync, | 
|     setListItem, | 
|     cancel: () => queryClient.cancelQueries(queryKey), | 
|     infiniteLoadingRef, | 
|     listActions, | 
|     invalidateQueries, | 
|     fetchPreviousPage, | 
|     hasPreviousPage, | 
|   }; | 
| } | 
|   | 
| export type ListActionsType = { | 
|   setByIndex: (options?: InfiniteGroupOptions) => void; | 
|   updatePageByIndex: (options?: InfiniteGroupOptions) => void; | 
|   remove: () => void; | 
| }; | 
|   | 
| type UseRefeshDidShowOptions = { | 
|   queryKey: QueryKey; | 
| }; | 
|   | 
| export function useRefeshDidShow({ queryKey }: UseRefeshDidShowOptions) { | 
|   const queryClient = useQueryClient(); | 
|   const showUpdate = ref(false); | 
|   | 
|   Taro.useDidShow(() => { | 
|     if (showUpdate.value) { | 
|       queryClient.invalidateQueries({ | 
|         queryKey: queryKey, | 
|       }); | 
|     } | 
|   }); | 
|   | 
|   Taro.useDidHide(() => { | 
|     showUpdate.value = true; | 
|   }); | 
|   | 
|   Taro.useUnload(() => { | 
|     showUpdate.value = false; | 
|   }); | 
| } |