feat: 更新 ESLint 和 Prettier 配置,增强代码质量管理
- 在 .gitignore 中添加 public/audio/* 以忽略音频文件。 - 更新 bun.lock,添加 eslint-config-prettier 和 eslint-plugin-prettier 依赖,确保 ESLint 与 Prettier 的兼容性。 - 修改 eslint.config.ts,整合 Prettier 规则,优化代码风格一致性。 - 在 package.json 中添加 lint:fix 和 format 脚本,简化代码格式化和修复流程。 - 更新 tailwind.config.ts 和其他组件文件,统一代码风格,提升可读性。
This commit is contained in:
1 parent
5d00adc1a5
commit
76c67b492e
216 files changed
+12454
-13976
No files matched your search
+65
-47
@@ -1,67 +1,68 @@
|
||||
import { create } from "zustand";
|
||||
import { persist } from "zustand/middleware";
|
||||
import { STORE_NAMES } from "./storeNames";
|
||||
import { create } from 'zustand'
|
||||
import { persist } from 'zustand/middleware'
|
||||
import { STORE_NAMES } from './storeNames'
|
||||
import { setUserDefine } from '@/lib/utils/api-common'
|
||||
|
||||
interface ChenyunStore {
|
||||
// 存储每个场景(place)的已访问展品ID集合
|
||||
// 格式:{ place1: Set<1, 2>, place2: Set<1, 2>, ... }
|
||||
visitedExhibits: Record<string, Set<number>>;
|
||||
visitedExhibits: Record<string, Set<number>>
|
||||
|
||||
// 标记展品为已访问
|
||||
markExhibitVisited: (place: string, exhibitId: number) => void;
|
||||
markExhibitVisited: (place: string, exhibitId: number) => void
|
||||
|
||||
// 检查展品是否已访问
|
||||
isExhibitVisited: (place: string, exhibitId: number) => boolean;
|
||||
isExhibitVisited: (place: string, exhibitId: number) => boolean
|
||||
|
||||
// 获取某个场景已访问的展品ID数组
|
||||
getVisitedExhibits: (place: string) => number[];
|
||||
getVisitedExhibits: (place: string) => number[]
|
||||
|
||||
// 重置某个场景的访问记录
|
||||
resetPlace: (place: string) => void;
|
||||
resetPlace: (place: string) => void
|
||||
|
||||
// 重置所有访问记录
|
||||
resetAll: () => void;
|
||||
resetAll: () => void
|
||||
|
||||
// ========== 体悟模块状态 ==========
|
||||
// 银元之战是否已解决
|
||||
isYinyuanSolved: boolean;
|
||||
isYinyuanSolved: boolean
|
||||
// 设置银元之战解决状态
|
||||
setYinyuanSolved: (solved: boolean) => void;
|
||||
setYinyuanSolved: (solved: boolean) => void
|
||||
|
||||
// 米棉之战是否已解决
|
||||
isMimianSolved: boolean;
|
||||
isMimianSolved: boolean
|
||||
// 设置米棉之战解决状态
|
||||
setMimianSolved: (solved: boolean) => void;
|
||||
setMimianSolved: (solved: boolean) => void
|
||||
}
|
||||
|
||||
// 将 Set 转换为数组以便序列化
|
||||
const serializeVisitedExhibits = (
|
||||
visitedExhibits: Record<string, Set<number>>
|
||||
): Record<string, number[]> => {
|
||||
const serialized: Record<string, number[]> = {};
|
||||
const serialized: Record<string, number[]> = {}
|
||||
for (const [place, exhibits] of Object.entries(visitedExhibits)) {
|
||||
serialized[place] = Array.from(exhibits);
|
||||
serialized[place] = Array.from(exhibits)
|
||||
}
|
||||
return serialized;
|
||||
};
|
||||
return serialized
|
||||
}
|
||||
|
||||
// 将数组转换回 Set
|
||||
const deserializeVisitedExhibits = (
|
||||
serialized: Record<string, number[]> | undefined
|
||||
): Record<string, Set<number>> => {
|
||||
if (!serialized || typeof serialized !== "object") {
|
||||
return {};
|
||||
if (!serialized || typeof serialized !== 'object') {
|
||||
return {}
|
||||
}
|
||||
const visitedExhibits: Record<string, Set<number>> = {};
|
||||
const visitedExhibits: Record<string, Set<number>> = {}
|
||||
for (const [place, exhibits] of Object.entries(serialized)) {
|
||||
if (Array.isArray(exhibits)) {
|
||||
visitedExhibits[place] = new Set(exhibits);
|
||||
visitedExhibits[place] = new Set(exhibits)
|
||||
} else {
|
||||
visitedExhibits[place] = new Set();
|
||||
visitedExhibits[place] = new Set()
|
||||
}
|
||||
}
|
||||
return visitedExhibits;
|
||||
};
|
||||
return visitedExhibits
|
||||
}
|
||||
|
||||
export const useChenyunStore = create<ChenyunStore>()(
|
||||
persist(
|
||||
@@ -70,50 +71,49 @@ export const useChenyunStore = create<ChenyunStore>()(
|
||||
|
||||
markExhibitVisited: (place: string, exhibitId: number) => {
|
||||
set((state) => {
|
||||
const currentExhibits =
|
||||
state.visitedExhibits[place] || new Set<number>();
|
||||
const currentExhibits = state.visitedExhibits[place] || new Set<number>()
|
||||
if (!currentExhibits.has(exhibitId)) {
|
||||
const newExhibits = {
|
||||
...state.visitedExhibits,
|
||||
[place]: new Set([...currentExhibits, exhibitId]),
|
||||
};
|
||||
return { visitedExhibits: newExhibits };
|
||||
}
|
||||
return { visitedExhibits: newExhibits }
|
||||
}
|
||||
return state;
|
||||
});
|
||||
return state
|
||||
})
|
||||
},
|
||||
|
||||
isExhibitVisited: (place: string, exhibitId: number) => {
|
||||
const { visitedExhibits } = get();
|
||||
return visitedExhibits[place]?.has(exhibitId) || false;
|
||||
const { visitedExhibits } = get()
|
||||
return visitedExhibits[place]?.has(exhibitId) || false
|
||||
},
|
||||
|
||||
getVisitedExhibits: (place: string) => {
|
||||
const { visitedExhibits } = get();
|
||||
return Array.from(visitedExhibits[place] || []);
|
||||
const { visitedExhibits } = get()
|
||||
return Array.from(visitedExhibits[place] || [])
|
||||
},
|
||||
|
||||
resetPlace: (place: string) => {
|
||||
set((state) => {
|
||||
const newExhibits = { ...state.visitedExhibits };
|
||||
delete newExhibits[place];
|
||||
return { visitedExhibits: newExhibits };
|
||||
});
|
||||
const newExhibits = { ...state.visitedExhibits }
|
||||
delete newExhibits[place]
|
||||
return { visitedExhibits: newExhibits }
|
||||
})
|
||||
},
|
||||
|
||||
resetAll: () => {
|
||||
set({ visitedExhibits: {} });
|
||||
set({ visitedExhibits: {} })
|
||||
},
|
||||
|
||||
// ========== 体悟模块状态 ==========
|
||||
isYinyuanSolved: false,
|
||||
setYinyuanSolved: (solved: boolean) => {
|
||||
set({ isYinyuanSolved: solved });
|
||||
set({ isYinyuanSolved: solved })
|
||||
},
|
||||
|
||||
isMimianSolved: false,
|
||||
setMimianSolved: (solved: boolean) => {
|
||||
set({ isMimianSolved: solved });
|
||||
set({ isMimianSolved: solved })
|
||||
},
|
||||
}),
|
||||
{
|
||||
@@ -126,18 +126,36 @@ export const useChenyunStore = create<ChenyunStore>()(
|
||||
onRehydrateStorage: () => (state) => {
|
||||
if (state) {
|
||||
// 确保反序列化后的数据格式正确
|
||||
state.visitedExhibits = deserializeVisitedExhibits(
|
||||
state.visitedExhibits as any
|
||||
);
|
||||
state.visitedExhibits = deserializeVisitedExhibits(state.visitedExhibits as any)
|
||||
// 确保解决状态有默认值
|
||||
if (state.isYinyuanSolved === undefined) {
|
||||
state.isYinyuanSolved = false;
|
||||
state.isYinyuanSolved = false
|
||||
}
|
||||
if (state.isMimianSolved === undefined) {
|
||||
state.isMimianSolved = false;
|
||||
state.isMimianSolved = false
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
);
|
||||
)
|
||||
|
||||
// ========== 易班平台数据保存 ==========
|
||||
const CHENYUN_LESSON_ID = 'Cheny_duihua'
|
||||
const CHENYUN_KEY = 22
|
||||
|
||||
export const saveChenyunStore = (): void => {
|
||||
const state = useChenyunStore.getState()
|
||||
|
||||
const payload = {
|
||||
visitedExhibits: serializeVisitedExhibits(state.visitedExhibits),
|
||||
isYinyuanSolved: state.isYinyuanSolved,
|
||||
isMimianSolved: state.isMimianSolved,
|
||||
}
|
||||
|
||||
try {
|
||||
setUserDefine(CHENYUN_LESSON_ID, CHENYUN_KEY, JSON.stringify(payload))
|
||||
} catch (error) {
|
||||
console.error('Failed to save Chenyun store', error)
|
||||
}
|
||||
}
|
||||
+26
-28
@@ -1,26 +1,26 @@
|
||||
import { create } from "zustand";
|
||||
import { persist } from "zustand/middleware";
|
||||
import { STORE_NAMES } from "./storeNames";
|
||||
import { create } from 'zustand'
|
||||
import { persist } from 'zustand/middleware'
|
||||
import { STORE_NAMES } from './storeNames'
|
||||
|
||||
export interface Clue {
|
||||
id: string; // 格式: "sunzhongshan/reflection/scene1/clue1"
|
||||
name: string; // 线索名称,如 "线索1"
|
||||
collected: boolean; // 是否已收集
|
||||
collectedAt?: number; // 收集时间戳
|
||||
id: string // 格式: "sunzhongshan/reflection/scene1/clue1"
|
||||
name: string // 线索名称,如 "线索1"
|
||||
collected: boolean // 是否已收集
|
||||
collectedAt?: number // 收集时间戳
|
||||
}
|
||||
|
||||
interface ClueStore {
|
||||
clues: Clue[];
|
||||
clues: Clue[]
|
||||
// 收集线索
|
||||
collectClue: (id: string, name: string) => void;
|
||||
collectClue: (id: string, name: string) => void
|
||||
// 检查线索是否已收集
|
||||
isClueCollected: (id: string) => boolean;
|
||||
isClueCollected: (id: string) => boolean
|
||||
// 获取指定场景的所有线索
|
||||
getSceneClues: (sceneId: string) => Clue[];
|
||||
getSceneClues: (sceneId: string) => Clue[]
|
||||
// 重置指定场景的线索
|
||||
resetSceneClues: (sceneId: string) => void;
|
||||
resetSceneClues: (sceneId: string) => void
|
||||
// 重置所有线索
|
||||
resetAll: () => void;
|
||||
resetAll: () => void
|
||||
}
|
||||
|
||||
export const useClueStore = create<ClueStore>()(
|
||||
@@ -29,8 +29,8 @@ export const useClueStore = create<ClueStore>()(
|
||||
clues: [],
|
||||
|
||||
collectClue: (id: string, name: string) => {
|
||||
const { clues } = get();
|
||||
const existingClue = clues.find((c) => c.id === id);
|
||||
const { clues } = get()
|
||||
const existingClue = clues.find((c) => c.id === id)
|
||||
|
||||
if (!existingClue) {
|
||||
set({
|
||||
@@ -43,41 +43,39 @@ export const useClueStore = create<ClueStore>()(
|
||||
collectedAt: Date.now(),
|
||||
},
|
||||
],
|
||||
});
|
||||
})
|
||||
} else if (!existingClue.collected) {
|
||||
set({
|
||||
clues: clues.map((c) =>
|
||||
c.id === id
|
||||
? { ...c, collected: true, collectedAt: Date.now() }
|
||||
: c
|
||||
c.id === id ? { ...c, collected: true, collectedAt: Date.now() } : c
|
||||
),
|
||||
});
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
isClueCollected: (id: string) => {
|
||||
const { clues } = get();
|
||||
return clues.some((c) => c.id === id && c.collected);
|
||||
const { clues } = get()
|
||||
return clues.some((c) => c.id === id && c.collected)
|
||||
},
|
||||
|
||||
getSceneClues: (sceneId: string) => {
|
||||
const { clues } = get();
|
||||
return clues.filter((c) => c.id.startsWith(sceneId));
|
||||
const { clues } = get()
|
||||
return clues.filter((c) => c.id.startsWith(sceneId))
|
||||
},
|
||||
|
||||
resetSceneClues: (sceneId: string) => {
|
||||
const { clues } = get();
|
||||
const { clues } = get()
|
||||
set({
|
||||
clues: clues.filter((c) => !c.id.startsWith(sceneId)),
|
||||
});
|
||||
})
|
||||
},
|
||||
|
||||
resetAll: () => {
|
||||
set({ clues: [] });
|
||||
set({ clues: [] })
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: STORE_NAMES.CLUE, // localStorage key
|
||||
}
|
||||
)
|
||||
);
|
||||
)
|
||||
@@ -1,76 +1,76 @@
|
||||
import { create } from "zustand";
|
||||
import { persist } from "zustand/middleware";
|
||||
import { STORE_NAMES } from "./storeNames";
|
||||
import { create } from 'zustand'
|
||||
import { persist } from 'zustand/middleware'
|
||||
import { STORE_NAMES } from './storeNames'
|
||||
|
||||
interface HuangyanpeiStore {
|
||||
// 存储每个场景(place)的已访问展品ID集合
|
||||
// 格式:{ place1: Set<1, 2>, place2: Set<1, 2>, ... }
|
||||
visitedExhibits: Record<string, Set<number>>;
|
||||
visitedExhibits: Record<string, Set<number>>
|
||||
|
||||
// 标记展品为已访问
|
||||
markExhibitVisited: (place: string, exhibitId: number) => void;
|
||||
markExhibitVisited: (place: string, exhibitId: number) => void
|
||||
|
||||
// 检查展品是否已访问
|
||||
isExhibitVisited: (place: string, exhibitId: number) => boolean;
|
||||
isExhibitVisited: (place: string, exhibitId: number) => boolean
|
||||
|
||||
// 获取某个场景已访问的展品ID数组
|
||||
getVisitedExhibits: (place: string) => number[];
|
||||
getVisitedExhibits: (place: string) => number[]
|
||||
|
||||
// 重置某个场景的访问记录
|
||||
resetPlace: (place: string) => void;
|
||||
resetPlace: (place: string) => void
|
||||
|
||||
// 重置所有访问记录
|
||||
resetAll: () => void;
|
||||
resetAll: () => void
|
||||
|
||||
// ========== 体悟模块状态 ==========
|
||||
// 存储每个reflection场景的已完成cursor ID集合
|
||||
// 格式:{ scene1: Set<1, 2>, scene2: Set<1, 2>, ... }
|
||||
visitedReflectionCursors: Record<string, Set<number>>;
|
||||
visitedReflectionCursors: Record<string, Set<number>>
|
||||
|
||||
// 标记reflection cursor为已完成
|
||||
markReflectionCursorVisited: (scene: string, cursorId: number) => void;
|
||||
markReflectionCursorVisited: (scene: string, cursorId: number) => void
|
||||
|
||||
// 检查reflection cursor是否已完成
|
||||
isReflectionCursorVisited: (scene: string, cursorId: number) => boolean;
|
||||
isReflectionCursorVisited: (scene: string, cursorId: number) => boolean
|
||||
|
||||
// 获取某个reflection场景已完成的cursor ID数组
|
||||
getVisitedReflectionCursors: (scene: string) => number[];
|
||||
getVisitedReflectionCursors: (scene: string) => number[]
|
||||
|
||||
// 重置某个reflection场景的cursor记录
|
||||
resetReflectionScene: (scene: string) => void;
|
||||
resetReflectionScene: (scene: string) => void
|
||||
|
||||
// 重置所有reflection cursor记录
|
||||
resetAllReflectionCursors: () => void;
|
||||
resetAllReflectionCursors: () => void
|
||||
}
|
||||
|
||||
// 将 Set 转换为数组以便序列化
|
||||
const serializeVisitedExhibits = (
|
||||
visitedExhibits: Record<string, Set<number>>
|
||||
): Record<string, number[]> => {
|
||||
const serialized: Record<string, number[]> = {};
|
||||
const serialized: Record<string, number[]> = {}
|
||||
for (const [place, exhibits] of Object.entries(visitedExhibits)) {
|
||||
serialized[place] = Array.from(exhibits);
|
||||
serialized[place] = Array.from(exhibits)
|
||||
}
|
||||
return serialized;
|
||||
};
|
||||
return serialized
|
||||
}
|
||||
|
||||
// 将数组转换回 Set
|
||||
const deserializeVisitedExhibits = (
|
||||
serialized: Record<string, number[]> | undefined
|
||||
): Record<string, Set<number>> => {
|
||||
if (!serialized || typeof serialized !== "object") {
|
||||
return {};
|
||||
if (!serialized || typeof serialized !== 'object') {
|
||||
return {}
|
||||
}
|
||||
const visitedExhibits: Record<string, Set<number>> = {};
|
||||
const visitedExhibits: Record<string, Set<number>> = {}
|
||||
for (const [place, exhibits] of Object.entries(serialized)) {
|
||||
if (Array.isArray(exhibits)) {
|
||||
visitedExhibits[place] = new Set(exhibits);
|
||||
visitedExhibits[place] = new Set(exhibits)
|
||||
} else {
|
||||
visitedExhibits[place] = new Set();
|
||||
visitedExhibits[place] = new Set()
|
||||
}
|
||||
}
|
||||
return visitedExhibits;
|
||||
};
|
||||
return visitedExhibits
|
||||
}
|
||||
|
||||
export const useHuangyanpeiStore = create<HuangyanpeiStore>()(
|
||||
persist(
|
||||
@@ -79,39 +79,38 @@ export const useHuangyanpeiStore = create<HuangyanpeiStore>()(
|
||||
|
||||
markExhibitVisited: (place: string, exhibitId: number) => {
|
||||
set((state) => {
|
||||
const currentExhibits =
|
||||
state.visitedExhibits[place] || new Set<number>();
|
||||
const currentExhibits = state.visitedExhibits[place] || new Set<number>()
|
||||
if (!currentExhibits.has(exhibitId)) {
|
||||
const newExhibits = {
|
||||
...state.visitedExhibits,
|
||||
[place]: new Set([...currentExhibits, exhibitId]),
|
||||
};
|
||||
return { visitedExhibits: newExhibits };
|
||||
}
|
||||
return { visitedExhibits: newExhibits }
|
||||
}
|
||||
return state;
|
||||
});
|
||||
return state
|
||||
})
|
||||
},
|
||||
|
||||
isExhibitVisited: (place: string, exhibitId: number) => {
|
||||
const { visitedExhibits } = get();
|
||||
return visitedExhibits[place]?.has(exhibitId) || false;
|
||||
const { visitedExhibits } = get()
|
||||
return visitedExhibits[place]?.has(exhibitId) || false
|
||||
},
|
||||
|
||||
getVisitedExhibits: (place: string) => {
|
||||
const { visitedExhibits } = get();
|
||||
return Array.from(visitedExhibits[place] || []);
|
||||
const { visitedExhibits } = get()
|
||||
return Array.from(visitedExhibits[place] || [])
|
||||
},
|
||||
|
||||
resetPlace: (place: string) => {
|
||||
set((state) => {
|
||||
const newExhibits = { ...state.visitedExhibits };
|
||||
delete newExhibits[place];
|
||||
return { visitedExhibits: newExhibits };
|
||||
});
|
||||
const newExhibits = { ...state.visitedExhibits }
|
||||
delete newExhibits[place]
|
||||
return { visitedExhibits: newExhibits }
|
||||
})
|
||||
},
|
||||
|
||||
resetAll: () => {
|
||||
set({ visitedExhibits: {} });
|
||||
set({ visitedExhibits: {} })
|
||||
},
|
||||
|
||||
// ========== 体悟模块状态 ==========
|
||||
@@ -119,60 +118,55 @@ export const useHuangyanpeiStore = create<HuangyanpeiStore>()(
|
||||
|
||||
markReflectionCursorVisited: (scene: string, cursorId: number) => {
|
||||
set((state) => {
|
||||
const currentCursors =
|
||||
state.visitedReflectionCursors[scene] || new Set<number>();
|
||||
const currentCursors = state.visitedReflectionCursors[scene] || new Set<number>()
|
||||
if (!currentCursors.has(cursorId)) {
|
||||
const newCursors = {
|
||||
...state.visitedReflectionCursors,
|
||||
[scene]: new Set([...currentCursors, cursorId]),
|
||||
};
|
||||
return { visitedReflectionCursors: newCursors };
|
||||
}
|
||||
return { visitedReflectionCursors: newCursors }
|
||||
}
|
||||
return state;
|
||||
});
|
||||
return state
|
||||
})
|
||||
},
|
||||
|
||||
isReflectionCursorVisited: (scene: string, cursorId: number) => {
|
||||
const { visitedReflectionCursors } = get();
|
||||
return visitedReflectionCursors[scene]?.has(cursorId) || false;
|
||||
const { visitedReflectionCursors } = get()
|
||||
return visitedReflectionCursors[scene]?.has(cursorId) || false
|
||||
},
|
||||
|
||||
getVisitedReflectionCursors: (scene: string) => {
|
||||
const { visitedReflectionCursors } = get();
|
||||
return Array.from(visitedReflectionCursors[scene] || []);
|
||||
const { visitedReflectionCursors } = get()
|
||||
return Array.from(visitedReflectionCursors[scene] || [])
|
||||
},
|
||||
|
||||
resetReflectionScene: (scene: string) => {
|
||||
set((state) => {
|
||||
const newCursors = { ...state.visitedReflectionCursors };
|
||||
delete newCursors[scene];
|
||||
return { visitedReflectionCursors: newCursors };
|
||||
});
|
||||
const newCursors = { ...state.visitedReflectionCursors }
|
||||
delete newCursors[scene]
|
||||
return { visitedReflectionCursors: newCursors }
|
||||
})
|
||||
},
|
||||
|
||||
resetAllReflectionCursors: () => {
|
||||
set({ visitedReflectionCursors: {} });
|
||||
set({ visitedReflectionCursors: {} })
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: STORE_NAMES.HUANGYANPEI, // localStorage key
|
||||
partialize: (state) => ({
|
||||
visitedExhibits: serializeVisitedExhibits(state.visitedExhibits),
|
||||
visitedReflectionCursors: serializeVisitedExhibits(
|
||||
state.visitedReflectionCursors
|
||||
),
|
||||
visitedReflectionCursors: serializeVisitedExhibits(state.visitedReflectionCursors),
|
||||
}),
|
||||
onRehydrateStorage: () => (state) => {
|
||||
if (state) {
|
||||
// 确保反序列化后的数据格式正确
|
||||
state.visitedExhibits = deserializeVisitedExhibits(
|
||||
state.visitedExhibits as any
|
||||
);
|
||||
state.visitedExhibits = deserializeVisitedExhibits(state.visitedExhibits as any)
|
||||
state.visitedReflectionCursors = deserializeVisitedExhibits(
|
||||
state.visitedReflectionCursors as any
|
||||
);
|
||||
)
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
);
|
||||
)
|
||||
+8
-8
@@ -1,8 +1,8 @@
|
||||
export { useChenyunStore } from "./chenyunStore";
|
||||
export { useHuangyanpeiStore } from "./huangyanpeiStore";
|
||||
export { useLuxunStore } from "./luxunStore";
|
||||
export { useSunzhongshanStore } from "./sunzhongshanStore";
|
||||
export { useClueStore } from "./clueStore";
|
||||
export { usePuzzleStore } from "./puzzleStore";
|
||||
export { useUserStore } from "./userStore";
|
||||
export { STORE_NAMES } from "./storeNames";
|
||||
export { useChenyunStore } from './chenyunStore'
|
||||
export { useHuangyanpeiStore } from './huangyanpeiStore'
|
||||
export { useLuxunStore } from './luxunStore'
|
||||
export { useSunzhongshanStore } from './sunzhongshanStore'
|
||||
export { useClueStore } from './clueStore'
|
||||
export { usePuzzleStore } from './puzzleStore'
|
||||
export { useUserStore } from './userStore'
|
||||
export { STORE_NAMES } from './storeNames'
|
||||
+36
-41
@@ -1,56 +1,56 @@
|
||||
import { create } from "zustand";
|
||||
import { persist } from "zustand/middleware";
|
||||
import { STORE_NAMES } from "./storeNames";
|
||||
import { create } from 'zustand'
|
||||
import { persist } from 'zustand/middleware'
|
||||
import { STORE_NAMES } from './storeNames'
|
||||
|
||||
interface LuxunStore {
|
||||
// 存储每个场景(place)的已访问展品ID集合
|
||||
// 格式:{ place1: Set<1, 2>, place2: Set<1, 2>, ... }
|
||||
visitedExhibits: Record<string, Set<number>>;
|
||||
visitedExhibits: Record<string, Set<number>>
|
||||
|
||||
// 标记展品为已访问
|
||||
markExhibitVisited: (place: string, exhibitId: number) => void;
|
||||
markExhibitVisited: (place: string, exhibitId: number) => void
|
||||
|
||||
// 检查展品是否已访问
|
||||
isExhibitVisited: (place: string, exhibitId: number) => boolean;
|
||||
isExhibitVisited: (place: string, exhibitId: number) => boolean
|
||||
|
||||
// 获取某个场景已访问的展品ID数组
|
||||
getVisitedExhibits: (place: string) => number[];
|
||||
getVisitedExhibits: (place: string) => number[]
|
||||
|
||||
// 重置某个场景的访问记录
|
||||
resetPlace: (place: string) => void;
|
||||
resetPlace: (place: string) => void
|
||||
|
||||
// 重置所有访问记录
|
||||
resetAll: () => void;
|
||||
resetAll: () => void
|
||||
}
|
||||
|
||||
// 将 Set 转换为数组以便序列化
|
||||
const serializeVisitedExhibits = (
|
||||
visitedExhibits: Record<string, Set<number>>
|
||||
): Record<string, number[]> => {
|
||||
const serialized: Record<string, number[]> = {};
|
||||
const serialized: Record<string, number[]> = {}
|
||||
for (const [place, exhibits] of Object.entries(visitedExhibits)) {
|
||||
serialized[place] = Array.from(exhibits);
|
||||
serialized[place] = Array.from(exhibits)
|
||||
}
|
||||
return serialized;
|
||||
};
|
||||
return serialized
|
||||
}
|
||||
|
||||
// 将数组转换回 Set
|
||||
const deserializeVisitedExhibits = (
|
||||
serialized: Record<string, number[]> | undefined
|
||||
): Record<string, Set<number>> => {
|
||||
if (!serialized || typeof serialized !== "object") {
|
||||
return {};
|
||||
if (!serialized || typeof serialized !== 'object') {
|
||||
return {}
|
||||
}
|
||||
const visitedExhibits: Record<string, Set<number>> = {};
|
||||
const visitedExhibits: Record<string, Set<number>> = {}
|
||||
for (const [place, exhibits] of Object.entries(serialized)) {
|
||||
if (Array.isArray(exhibits)) {
|
||||
visitedExhibits[place] = new Set(exhibits);
|
||||
visitedExhibits[place] = new Set(exhibits)
|
||||
} else {
|
||||
visitedExhibits[place] = new Set();
|
||||
visitedExhibits[place] = new Set()
|
||||
}
|
||||
}
|
||||
return visitedExhibits;
|
||||
};
|
||||
return visitedExhibits
|
||||
}
|
||||
|
||||
export const useLuxunStore = create<LuxunStore>()(
|
||||
persist(
|
||||
@@ -59,39 +59,38 @@ export const useLuxunStore = create<LuxunStore>()(
|
||||
|
||||
markExhibitVisited: (place: string, exhibitId: number) => {
|
||||
set((state) => {
|
||||
const currentExhibits =
|
||||
state.visitedExhibits[place] || new Set<number>();
|
||||
const currentExhibits = state.visitedExhibits[place] || new Set<number>()
|
||||
if (!currentExhibits.has(exhibitId)) {
|
||||
const newExhibits = {
|
||||
...state.visitedExhibits,
|
||||
[place]: new Set([...currentExhibits, exhibitId]),
|
||||
};
|
||||
return { visitedExhibits: newExhibits };
|
||||
}
|
||||
return { visitedExhibits: newExhibits }
|
||||
}
|
||||
return state;
|
||||
});
|
||||
return state
|
||||
})
|
||||
},
|
||||
|
||||
isExhibitVisited: (place: string, exhibitId: number) => {
|
||||
const { visitedExhibits } = get();
|
||||
return visitedExhibits[place]?.has(exhibitId) || false;
|
||||
const { visitedExhibits } = get()
|
||||
return visitedExhibits[place]?.has(exhibitId) || false
|
||||
},
|
||||
|
||||
getVisitedExhibits: (place: string) => {
|
||||
const { visitedExhibits } = get();
|
||||
return Array.from(visitedExhibits[place] || []);
|
||||
const { visitedExhibits } = get()
|
||||
return Array.from(visitedExhibits[place] || [])
|
||||
},
|
||||
|
||||
resetPlace: (place: string) => {
|
||||
set((state) => {
|
||||
const newExhibits = { ...state.visitedExhibits };
|
||||
delete newExhibits[place];
|
||||
return { visitedExhibits: newExhibits };
|
||||
});
|
||||
const newExhibits = { ...state.visitedExhibits }
|
||||
delete newExhibits[place]
|
||||
return { visitedExhibits: newExhibits }
|
||||
})
|
||||
},
|
||||
|
||||
resetAll: () => {
|
||||
set({ visitedExhibits: {} });
|
||||
set({ visitedExhibits: {} })
|
||||
},
|
||||
}),
|
||||
{
|
||||
@@ -101,13 +100,9 @@ export const useLuxunStore = create<LuxunStore>()(
|
||||
}),
|
||||
onRehydrateStorage: () => (state) => {
|
||||
if (state) {
|
||||
state.visitedExhibits = deserializeVisitedExhibits(
|
||||
state.visitedExhibits as any
|
||||
);
|
||||
state.visitedExhibits = deserializeVisitedExhibits(state.visitedExhibits as any)
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
)
|
||||
+62
-64
@@ -1,75 +1,73 @@
|
||||
import { create } from "zustand";
|
||||
import { persist } from "zustand/middleware";
|
||||
import { STORE_NAMES } from "./storeNames";
|
||||
import { create } from 'zustand'
|
||||
import { persist } from 'zustand/middleware'
|
||||
import { STORE_NAMES } from './storeNames'
|
||||
|
||||
interface PuzzleStore {
|
||||
// 每个故居的已解锁碎片集合,格式:{ residence: Set<pieceId> }
|
||||
puzzles: Record<string, Set<number>>;
|
||||
puzzles: Record<string, Set<number>>
|
||||
|
||||
// 解锁碎片
|
||||
unlockPuzzle: (residence: string, pieceId: number) => void;
|
||||
unlockPuzzle: (residence: string, pieceId: number) => void
|
||||
|
||||
// 检查碎片是否解锁
|
||||
isPuzzleUnlocked: (residence: string, pieceId: number) => boolean;
|
||||
isPuzzleUnlocked: (residence: string, pieceId: number) => boolean
|
||||
|
||||
// 获取已解锁碎片列表
|
||||
getUnlockedPuzzles: (residence: string) => number[];
|
||||
getUnlockedPuzzles: (residence: string) => number[]
|
||||
|
||||
// 重置指定故居的所有碎片
|
||||
resetPuzzles: (residence: string) => void;
|
||||
resetPuzzles: (residence: string) => void
|
||||
|
||||
// 重置所有碎片
|
||||
resetAll: () => void;
|
||||
resetAll: () => void
|
||||
|
||||
// 获取收集进度
|
||||
getPuzzleCollectProgress: (residence: string) => number;
|
||||
getPuzzleCollectProgress: (residence: string) => number
|
||||
}
|
||||
|
||||
// 将 Set 转换为数组以便序列化
|
||||
const serializePuzzles = (puzzles: Record<string, Set<number>>) => {
|
||||
const serialized: Record<string, number[]> = {};
|
||||
const serialized: Record<string, number[]> = {}
|
||||
for (const [residence, pieces] of Object.entries(puzzles)) {
|
||||
serialized[residence] = Array.from(pieces);
|
||||
serialized[residence] = Array.from(pieces)
|
||||
}
|
||||
return serialized;
|
||||
};
|
||||
return serialized
|
||||
}
|
||||
|
||||
// 将数组转换回 Set
|
||||
const deserializePuzzles = (
|
||||
serialized: Record<string, number[]> | undefined
|
||||
) => {
|
||||
if (!serialized || typeof serialized !== "object") {
|
||||
return {};
|
||||
const deserializePuzzles = (serialized: Record<string, number[]> | undefined) => {
|
||||
if (!serialized || typeof serialized !== 'object') {
|
||||
return {}
|
||||
}
|
||||
const puzzles: Record<string, Set<number>> = {};
|
||||
const puzzles: Record<string, Set<number>> = {}
|
||||
for (const [residence, pieces] of Object.entries(serialized)) {
|
||||
// 确保 pieces 是数组
|
||||
if (Array.isArray(pieces)) {
|
||||
puzzles[residence] = new Set(pieces);
|
||||
puzzles[residence] = new Set(pieces)
|
||||
} else {
|
||||
// 如果格式不对,创建新的 Set
|
||||
puzzles[residence] = new Set();
|
||||
puzzles[residence] = new Set()
|
||||
}
|
||||
}
|
||||
return puzzles;
|
||||
};
|
||||
return puzzles
|
||||
}
|
||||
|
||||
// 辅助函数:确保 puzzles 中的值都是 Set
|
||||
const ensurePuzzlesAreSets = (puzzles: any): Record<string, Set<number>> => {
|
||||
const fixed: Record<string, Set<number>> = {};
|
||||
if (puzzles && typeof puzzles === "object") {
|
||||
const fixed: Record<string, Set<number>> = {}
|
||||
if (puzzles && typeof puzzles === 'object') {
|
||||
for (const [residence, pieces] of Object.entries(puzzles)) {
|
||||
if (pieces instanceof Set) {
|
||||
fixed[residence] = pieces;
|
||||
fixed[residence] = pieces
|
||||
} else if (Array.isArray(pieces)) {
|
||||
fixed[residence] = new Set(pieces);
|
||||
fixed[residence] = new Set(pieces)
|
||||
} else {
|
||||
fixed[residence] = new Set();
|
||||
fixed[residence] = new Set()
|
||||
}
|
||||
}
|
||||
}
|
||||
return fixed;
|
||||
};
|
||||
return fixed
|
||||
}
|
||||
|
||||
export const usePuzzleStore = create<PuzzleStore>()(
|
||||
persist(
|
||||
@@ -77,62 +75,62 @@ export const usePuzzleStore = create<PuzzleStore>()(
|
||||
puzzles: {},
|
||||
|
||||
unlockPuzzle: (residence: string, pieceId: number) => {
|
||||
const { puzzles } = get();
|
||||
const { puzzles } = get()
|
||||
// 确保 puzzles 格式正确
|
||||
const fixedPuzzles = ensurePuzzlesAreSets(puzzles);
|
||||
const residencePuzzles = fixedPuzzles[residence] || new Set<number>();
|
||||
const fixedPuzzles = ensurePuzzlesAreSets(puzzles)
|
||||
const residencePuzzles = fixedPuzzles[residence] || new Set<number>()
|
||||
|
||||
if (!residencePuzzles.has(pieceId)) {
|
||||
const newPuzzles = { ...fixedPuzzles };
|
||||
newPuzzles[residence] = new Set([...residencePuzzles, pieceId]);
|
||||
set({ puzzles: newPuzzles });
|
||||
const newPuzzles = { ...fixedPuzzles }
|
||||
newPuzzles[residence] = new Set([...residencePuzzles, pieceId])
|
||||
set({ puzzles: newPuzzles })
|
||||
}
|
||||
},
|
||||
|
||||
isPuzzleUnlocked: (residence: string, pieceId: number) => {
|
||||
const { puzzles } = get();
|
||||
const { puzzles } = get()
|
||||
// 确保 puzzles 格式正确
|
||||
const fixedPuzzles = ensurePuzzlesAreSets(puzzles);
|
||||
const residencePuzzles = fixedPuzzles[residence];
|
||||
const fixedPuzzles = ensurePuzzlesAreSets(puzzles)
|
||||
const residencePuzzles = fixedPuzzles[residence]
|
||||
if (!residencePuzzles) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
return residencePuzzles.has(pieceId);
|
||||
return residencePuzzles.has(pieceId)
|
||||
},
|
||||
|
||||
getUnlockedPuzzles: (residence: string) => {
|
||||
const { puzzles } = get();
|
||||
const { puzzles } = get()
|
||||
// 确保 puzzles 格式正确
|
||||
const fixedPuzzles = ensurePuzzlesAreSets(puzzles);
|
||||
const residencePuzzles = fixedPuzzles[residence];
|
||||
const fixedPuzzles = ensurePuzzlesAreSets(puzzles)
|
||||
const residencePuzzles = fixedPuzzles[residence]
|
||||
if (!residencePuzzles) {
|
||||
return [];
|
||||
return []
|
||||
}
|
||||
return Array.from(residencePuzzles);
|
||||
return Array.from(residencePuzzles)
|
||||
},
|
||||
|
||||
getPuzzleCollectProgress: (residence: string): number => {
|
||||
const totalPuzzles = 16;
|
||||
const { puzzles } = get();
|
||||
const fixedPuzzles = ensurePuzzlesAreSets(puzzles);
|
||||
const residencePuzzles = fixedPuzzles[residence];
|
||||
const totalPuzzles = 16
|
||||
const { puzzles } = get()
|
||||
const fixedPuzzles = ensurePuzzlesAreSets(puzzles)
|
||||
const residencePuzzles = fixedPuzzles[residence]
|
||||
if (!residencePuzzles) {
|
||||
return 0;
|
||||
return 0
|
||||
}
|
||||
return (residencePuzzles.size / totalPuzzles) * 100;
|
||||
return (residencePuzzles.size / totalPuzzles) * 100
|
||||
},
|
||||
|
||||
resetPuzzles: (residence: string) => {
|
||||
const { puzzles } = get();
|
||||
const { puzzles } = get()
|
||||
// 确保 puzzles 格式正确
|
||||
const fixedPuzzles = ensurePuzzlesAreSets(puzzles);
|
||||
const newPuzzles = { ...fixedPuzzles };
|
||||
delete newPuzzles[residence];
|
||||
set({ puzzles: newPuzzles });
|
||||
const fixedPuzzles = ensurePuzzlesAreSets(puzzles)
|
||||
const newPuzzles = { ...fixedPuzzles }
|
||||
delete newPuzzles[residence]
|
||||
set({ puzzles: newPuzzles })
|
||||
},
|
||||
|
||||
resetAll: () => {
|
||||
set({ puzzles: {} });
|
||||
set({ puzzles: {} })
|
||||
},
|
||||
}),
|
||||
{
|
||||
@@ -142,19 +140,19 @@ export const usePuzzleStore = create<PuzzleStore>()(
|
||||
}),
|
||||
merge: (persistedState, currentState) => {
|
||||
const persisted = persistedState as {
|
||||
puzzles?: Record<string, number[]>;
|
||||
};
|
||||
puzzles?: Record<string, number[]>
|
||||
}
|
||||
return {
|
||||
...currentState,
|
||||
puzzles: deserializePuzzles(persisted?.puzzles),
|
||||
};
|
||||
}
|
||||
},
|
||||
onRehydrateStorage: () => (state) => {
|
||||
// 在恢复时,确保所有 puzzles 都是 Set
|
||||
if (state) {
|
||||
state.puzzles = ensurePuzzlesAreSets(state.puzzles);
|
||||
state.puzzles = ensurePuzzlesAreSets(state.puzzles)
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
);
|
||||
)
|
||||
+10
-12
@@ -1,13 +1,13 @@
|
||||
//lessonId 课时唯一id
|
||||
export const STORE_NAMES = {
|
||||
USER: "user-storage",
|
||||
SUNZHONGSHAN: "sunzhongshan-storage",
|
||||
LUXUN: "luxun-storage",
|
||||
HUANGYANPEI: "huangyanpei-storage",
|
||||
CHENYUN: "chenyun-storage",
|
||||
PUZZLE: "puzzle-storage",
|
||||
CLUE: "clue-storage",
|
||||
} as const;
|
||||
USER: 'user-storage',
|
||||
SUNZHONGSHAN: 'sunzhongshan-storage',
|
||||
LUXUN: 'luxun-storage',
|
||||
HUANGYANPEI: 'huangyanpei-storage',
|
||||
CHENYUN: 'chenyun-storage',
|
||||
PUZZLE: 'puzzle-storage',
|
||||
CLUE: 'clue-storage',
|
||||
} as const
|
||||
|
||||
//课程的第几课时
|
||||
export const COURSE_ORDER = {
|
||||
@@ -18,8 +18,6 @@ export const COURSE_ORDER = {
|
||||
COURSE_ORDER_5: 5,
|
||||
COURSE_ORDER_6: 6,
|
||||
COURSE_ORDER_7: 7,
|
||||
} as const;
|
||||
|
||||
export type StoreNameKey = keyof typeof STORE_NAMES;
|
||||
|
||||
} as const
|
||||
|
||||
export type StoreNameKey = keyof typeof STORE_NAMES
|
||||
@@ -1,65 +1,65 @@
|
||||
import { create } from "zustand";
|
||||
import { persist } from "zustand/middleware";
|
||||
import { STORE_NAMES } from "./storeNames";
|
||||
import { create } from 'zustand'
|
||||
import { persist } from 'zustand/middleware'
|
||||
import { STORE_NAMES } from './storeNames'
|
||||
|
||||
interface SunzhongshanStore {
|
||||
// 存储每个场景(place)的已访问展品ID集合
|
||||
// 格式:{ place1: Set<1, 2>, place2: Set<1, 2>, ... }
|
||||
visitedExhibits: Record<string, Set<number>>;
|
||||
visitedExhibits: Record<string, Set<number>>
|
||||
|
||||
// 体悟模块通用布尔状态(引导是否展示、场景是否完成等)
|
||||
reflectionFlags: Record<string, boolean>;
|
||||
reflectionFlags: Record<string, boolean>
|
||||
|
||||
// 标记展品为已访问
|
||||
markExhibitVisited: (place: string, exhibitId: number) => void;
|
||||
markExhibitVisited: (place: string, exhibitId: number) => void
|
||||
|
||||
// 检查展品是否已访问
|
||||
isExhibitVisited: (place: string, exhibitId: number) => boolean;
|
||||
isExhibitVisited: (place: string, exhibitId: number) => boolean
|
||||
|
||||
// 获取某个场景已访问的展品ID数组
|
||||
getVisitedExhibits: (place: string) => number[];
|
||||
getVisitedExhibits: (place: string) => number[]
|
||||
|
||||
// 重置某个场景的访问记录
|
||||
resetPlace: (place: string) => void;
|
||||
resetPlace: (place: string) => void
|
||||
|
||||
// 重置所有访问记录
|
||||
resetAll: () => void;
|
||||
resetAll: () => void
|
||||
|
||||
// 设置体悟模块布尔状态
|
||||
setReflectionFlag: (key: string, value: boolean) => void;
|
||||
setReflectionFlag: (key: string, value: boolean) => void
|
||||
|
||||
// 获取体悟模块布尔状态
|
||||
getReflectionFlag: (key: string) => boolean;
|
||||
getReflectionFlag: (key: string) => boolean
|
||||
}
|
||||
|
||||
// 将 Set 转换为数组以便序列化
|
||||
const serializeVisitedExhibits = (
|
||||
visitedExhibits: Record<string, Set<number>>
|
||||
): Record<string, number[]> => {
|
||||
const serialized: Record<string, number[]> = {};
|
||||
const serialized: Record<string, number[]> = {}
|
||||
for (const [place, exhibits] of Object.entries(visitedExhibits)) {
|
||||
serialized[place] = Array.from(exhibits);
|
||||
serialized[place] = Array.from(exhibits)
|
||||
}
|
||||
return serialized;
|
||||
};
|
||||
return serialized
|
||||
}
|
||||
|
||||
// 将数组转换回 Set
|
||||
const deserializeVisitedExhibits = (
|
||||
serialized: Record<string, number[]> | undefined
|
||||
): Record<string, Set<number>> => {
|
||||
if (!serialized || typeof serialized !== "object") {
|
||||
return {};
|
||||
if (!serialized || typeof serialized !== 'object') {
|
||||
return {}
|
||||
}
|
||||
const visitedExhibits: Record<string, Set<number>> = {};
|
||||
const visitedExhibits: Record<string, Set<number>> = {}
|
||||
for (const [place, exhibits] of Object.entries(serialized)) {
|
||||
if (Array.isArray(exhibits)) {
|
||||
visitedExhibits[place] = new Set(exhibits);
|
||||
visitedExhibits[place] = new Set(exhibits)
|
||||
} else {
|
||||
visitedExhibits[place] = new Set();
|
||||
visitedExhibits[place] = new Set()
|
||||
}
|
||||
}
|
||||
return visitedExhibits;
|
||||
};
|
||||
return visitedExhibits
|
||||
}
|
||||
|
||||
export const useSunzhongshanStore = create<SunzhongshanStore>()(
|
||||
persist(
|
||||
@@ -69,39 +69,38 @@ export const useSunzhongshanStore = create<SunzhongshanStore>()(
|
||||
|
||||
markExhibitVisited: (place: string, exhibitId: number) => {
|
||||
set((state) => {
|
||||
const currentExhibits =
|
||||
state.visitedExhibits[place] || new Set<number>();
|
||||
const currentExhibits = state.visitedExhibits[place] || new Set<number>()
|
||||
if (!currentExhibits.has(exhibitId)) {
|
||||
const newExhibits = {
|
||||
...state.visitedExhibits,
|
||||
[place]: new Set([...currentExhibits, exhibitId]),
|
||||
};
|
||||
return { visitedExhibits: newExhibits };
|
||||
}
|
||||
return { visitedExhibits: newExhibits }
|
||||
}
|
||||
return state;
|
||||
});
|
||||
return state
|
||||
})
|
||||
},
|
||||
|
||||
isExhibitVisited: (place: string, exhibitId: number) => {
|
||||
const { visitedExhibits } = get();
|
||||
return visitedExhibits[place]?.has(exhibitId) || false;
|
||||
const { visitedExhibits } = get()
|
||||
return visitedExhibits[place]?.has(exhibitId) || false
|
||||
},
|
||||
|
||||
getVisitedExhibits: (place: string) => {
|
||||
const { visitedExhibits } = get();
|
||||
return Array.from(visitedExhibits[place] || []);
|
||||
const { visitedExhibits } = get()
|
||||
return Array.from(visitedExhibits[place] || [])
|
||||
},
|
||||
|
||||
resetPlace: (place: string) => {
|
||||
set((state) => {
|
||||
const newExhibits = { ...state.visitedExhibits };
|
||||
delete newExhibits[place];
|
||||
return { visitedExhibits: newExhibits };
|
||||
});
|
||||
const newExhibits = { ...state.visitedExhibits }
|
||||
delete newExhibits[place]
|
||||
return { visitedExhibits: newExhibits }
|
||||
})
|
||||
},
|
||||
|
||||
resetAll: () => {
|
||||
set({ visitedExhibits: {}, reflectionFlags: {} });
|
||||
set({ visitedExhibits: {}, reflectionFlags: {} })
|
||||
},
|
||||
|
||||
setReflectionFlag: (key: string, value: boolean) => {
|
||||
@@ -110,12 +109,12 @@ export const useSunzhongshanStore = create<SunzhongshanStore>()(
|
||||
...state.reflectionFlags,
|
||||
[key]: value,
|
||||
},
|
||||
}));
|
||||
}))
|
||||
},
|
||||
|
||||
getReflectionFlag: (key: string) => {
|
||||
const { reflectionFlags } = get();
|
||||
return !!reflectionFlags[key];
|
||||
const { reflectionFlags } = get()
|
||||
return !!reflectionFlags[key]
|
||||
},
|
||||
}),
|
||||
{
|
||||
@@ -126,19 +125,12 @@ export const useSunzhongshanStore = create<SunzhongshanStore>()(
|
||||
}),
|
||||
onRehydrateStorage: () => (state) => {
|
||||
if (state) {
|
||||
state.visitedExhibits = deserializeVisitedExhibits(
|
||||
state.visitedExhibits as any
|
||||
);
|
||||
if (
|
||||
!state.reflectionFlags ||
|
||||
typeof state.reflectionFlags !== "object"
|
||||
) {
|
||||
state.reflectionFlags = {};
|
||||
state.visitedExhibits = deserializeVisitedExhibits(state.visitedExhibits as any)
|
||||
if (!state.reflectionFlags || typeof state.reflectionFlags !== 'object') {
|
||||
state.reflectionFlags = {}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
)
|
||||
+10
-12
@@ -1,13 +1,13 @@
|
||||
import { create } from "zustand";
|
||||
import { persist } from "zustand/middleware";
|
||||
import { STORE_NAMES } from "./storeNames";
|
||||
import { create } from 'zustand'
|
||||
import { persist } from 'zustand/middleware'
|
||||
import { STORE_NAMES } from './storeNames'
|
||||
|
||||
interface UserStore {
|
||||
courseId: string | null;
|
||||
uid: string | null;
|
||||
courseId: string | null
|
||||
uid: string | null
|
||||
|
||||
setCourseInfo: (info: { courseId?: string | null; uid?: string | null }) => void;
|
||||
resetCourseInfo: () => void;
|
||||
setCourseInfo: (info: { courseId?: string | null; uid?: string | null }) => void
|
||||
resetCourseInfo: () => void
|
||||
}
|
||||
|
||||
export const useUserStore = create<UserStore>()(
|
||||
@@ -20,17 +20,15 @@ export const useUserStore = create<UserStore>()(
|
||||
set((state) => ({
|
||||
courseId: info.courseId ?? state.courseId,
|
||||
uid: info.uid ?? state.uid,
|
||||
}));
|
||||
}))
|
||||
},
|
||||
|
||||
resetCourseInfo: () => {
|
||||
set({ courseId: null, uid: null });
|
||||
set({ courseId: null, uid: null })
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: STORE_NAMES.USER,
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
)
|
||||
Reference in new issue
Block a user