99 */
1010
1111import { useMutation , useQueryClient } from "@tanstack/react-query" ;
12- import { useTranslation } from "react-i18next" ;
13- import { snackbar } from "@/components/Snackbar" ;
1412import { gameService } from "@/services" ;
15- import { useStore } from "@/store" ;
1613import type { GameData } from "@/types" ;
1714import type { PlayStatus } from "@/types/collection" ;
1815import { getDisplayGameData } from "@/utils/dataTransform" ;
@@ -30,13 +27,30 @@ export const playStatusKeys = {
3027// Mutations - 数据操作 hooks
3128// ============================================================================
3229
33- interface UpdatePlayStatusParams {
30+ export interface UpdatePlayStatusParams {
3431 gameId : number ;
3532 newStatus : PlayStatus ;
33+ invalidateScope ?: "game" | "all" ;
3634}
3735
38- interface UpdatePlayStatusContext {
39- previousGame ?: GameData ;
36+ async function updatePlayStatus ( {
37+ gameId,
38+ newStatus,
39+ } : UpdatePlayStatusParams ) : Promise < GameData > {
40+ const fullGame = await gameService . getGameById ( gameId ) ;
41+ if ( ! fullGame ) {
42+ throw new Error ( "游戏数据未找到" ) ;
43+ }
44+
45+ await gameService . updateGame ( gameId , {
46+ clear : newStatus ,
47+ } ) ;
48+
49+ const game = getDisplayGameData ( fullGame ) ;
50+ return {
51+ ...game ,
52+ clear : newStatus ,
53+ } ;
4054}
4155
4256/**
@@ -53,121 +67,18 @@ interface UpdatePlayStatusContext {
5367 */
5468export function useUpdatePlayStatus ( ) {
5569 const queryClient = useQueryClient ( ) ;
56- const { t } = useTranslation ( ) ;
57- const { updateGamePlayStatusInStore, setSelectedGame, selectedGame } =
58- useStore ( ) ;
59-
60- return useMutation <
61- GameData ,
62- Error ,
63- UpdatePlayStatusParams ,
64- UpdatePlayStatusContext
65- > ( {
66- mutationFn : async ( { gameId, newStatus } ) => {
67- // 获取完整游戏数据
68- const fullGame = await gameService . getGameById ( gameId ) ;
69- if ( ! fullGame ) {
70- throw new Error ( t ( "errors.gameNotFound" , "游戏数据未找到" ) ) ;
71- }
72-
73- // 更新数据库
74- await gameService . updateGame ( gameId , {
75- clear : newStatus ,
76- } ) ;
77-
78- // 返回更新后的游戏数据
79- const game = getDisplayGameData ( fullGame ) ;
80- return {
81- ...game ,
82- clear : newStatus ,
83- } ;
84- } ,
85- onMutate : async ( { gameId, newStatus } ) => {
86- // 乐观更新:立即更新 store 中的数据
87- const previousGame =
88- selectedGame ?. id === gameId ? { ...selectedGame } : undefined ;
89-
90- // 更新 store 中的游戏列表
91- updateGamePlayStatusInStore ( gameId , newStatus , true ) ;
92-
93- return { previousGame } ;
94- } ,
95- onSuccess : ( updatedGame , { gameId } ) => {
96- // 如果当前选中的游戏就是被更新的游戏,更新 selectedGame
97- if ( selectedGame ?. id === gameId ) {
98- setSelectedGame ( updatedGame ) ;
99- }
100-
101- // 使相关的查询失效,触发重新获取
102- queryClient . invalidateQueries ( {
103- queryKey : playStatusKeys . game ( gameId ) ,
104- } ) ;
105- } ,
106- onError : ( error , { gameId } , context ) => {
107- // 发生错误时回滚到之前的状态
108- if ( context ?. previousGame ) {
109- updateGamePlayStatusInStore (
110- gameId ,
111- context . previousGame . clear ?? 1 ,
112- true ,
113- ) ;
114- if ( selectedGame ?. id === gameId ) {
115- setSelectedGame ( context . previousGame ) ;
116- }
117- }
118-
119- snackbar . error (
120- `${ t ( "errors.updatePlayStatusFailed" , "更新游戏状态失败" ) } : ${ error . message } ` ,
121- ) ;
122- } ,
123- } ) ;
124- }
125-
126- /**
127- * 更新游戏状态(用于右键菜单,需要刷新游戏列表)
128- *
129- * 与 useUpdatePlayStatus 的区别:
130- * - 成功后会刷新游戏列表(skipRefresh = false)
131- * - 适用于库列表页面的右键菜单
132- */
133- export function useUpdatePlayStatusWithRefresh ( ) {
134- const queryClient = useQueryClient ( ) ;
135- const { t } = useTranslation ( ) ;
136- const { updateGamePlayStatusInStore } = useStore ( ) ;
13770
13871 return useMutation < GameData , Error , UpdatePlayStatusParams > ( {
139- mutationFn : async ( { gameId, newStatus } ) => {
140- // 获取完整游戏数据
141- const fullGame = await gameService . getGameById ( gameId ) ;
142- if ( ! fullGame ) {
143- throw new Error ( t ( "errors.gameNotFound" , "游戏数据未找到" ) ) ;
72+ mutationFn : updatePlayStatus ,
73+ onSuccess : ( _ , { gameId, invalidateScope = "game" } ) => {
74+ if ( invalidateScope === "all" ) {
75+ queryClient . invalidateQueries ( {
76+ queryKey : playStatusKeys . all ,
77+ } ) ;
14478 }
145-
146- // 更新数据库
147- await gameService . updateGame ( gameId , {
148- clear : newStatus ,
149- } ) ;
150-
151- // 返回更新后的游戏数据
152- const game = getDisplayGameData ( fullGame ) ;
153- return {
154- ...game ,
155- clear : newStatus ,
156- } ;
157- } ,
158- onSuccess : ( _ , { gameId, newStatus } ) => {
159- // 更新 store 并刷新游戏列表
160- updateGamePlayStatusInStore ( gameId , newStatus , false ) ;
161-
162- // 使相关的查询失效
16379 queryClient . invalidateQueries ( {
16480 queryKey : playStatusKeys . game ( gameId ) ,
16581 } ) ;
16682 } ,
167- onError : ( error ) => {
168- snackbar . error (
169- `${ t ( "errors.updatePlayStatusFailed" , "更新游戏状态失败" ) } : ${ error . message } ` ,
170- ) ;
171- } ,
17283 } ) ;
17384}
0 commit comments