import { defineStore } from 'pinia' import { computed, ref } from 'vue' import { moduleStepMap } from '@/config/moduleStepMap' export const INTERVIEW_LESSON_ID = 'fangtan_rwqjk' export const INTERVIEW_KEY = 3 interface InterviewSavePayload { viewed?: Record isGuideInterviewTask?: boolean isGuideInterviewReturn?: boolean isGuideInterviewStage2?: boolean isGuideInterviewStage3?: boolean isInterviewUnlock?: boolean InterviewUnlockProgress?: number interviewMenuVisible?: boolean guideShown?: Record practiceScrollPage?: number } async function getYibanApi(): Promise { try { return await import('@/utils/yiban') } catch (error) { console.error('Failed to load Yiban API', error) return null } } /** * I store - manages Interview information */ export const useInterviewStore = defineStore( 'Interview', () => { //State /** * 已查看(停留≥阈值)记录 * key 推荐用 route.name */ const viewed = ref>({}) //Interview-任务取景框引导 const isGuideInterviewTask = ref(true) //Interview-思路提点完成回到首页的一次性引导 const isGuideInterviewReturn = ref(true) //Interview-中期拍摄阶段菜单一次性引导 const isGuideInterviewStage2 = ref(true) //Interview-后期剪辑阶段菜单一次性引导 const isGuideInterviewStage3 = ref(true) //Interview-是否解锁完成前置(观看视频) const isInterviewUnlock = ref(false) //Interview-发现与记录解锁进度 const InterviewUnlockProgress = ref(0) //Interview-菜单 Overlay 是否可见 const interviewMenuVisible = ref(false) const guideShown = ref>({}) const practiceScrollPage = ref(0) //Actions function saveInterviewStore(): void { const payload: InterviewSavePayload = { viewed: viewed.value, isGuideInterviewTask: isGuideInterviewTask.value, isGuideInterviewReturn: isGuideInterviewReturn.value, isGuideInterviewStage2: isGuideInterviewStage2.value, isGuideInterviewStage3: isGuideInterviewStage3.value, isInterviewUnlock: isInterviewUnlock.value, InterviewUnlockProgress: InterviewUnlockProgress.value, interviewMenuVisible: interviewMenuVisible.value, guideShown: guideShown.value, practiceScrollPage: practiceScrollPage.value, } getYibanApi() .then((api) => api?.setUserDefine( INTERVIEW_LESSON_ID, INTERVIEW_KEY, JSON.stringify(payload), ), ) .catch((error) => console.error('Failed to save Interview store', error), ) } async function loadInterviewStore(): Promise { try { const api = await getYibanApi() if (!api) return const raw = await api.getUserDefine(INTERVIEW_LESSON_ID, INTERVIEW_KEY) if (!raw) return const data = JSON.parse(raw) as InterviewSavePayload viewed.value = data.viewed ?? {} isGuideInterviewTask.value = data.isGuideInterviewTask ?? true isGuideInterviewReturn.value = data.isGuideInterviewReturn ?? true isGuideInterviewStage2.value = data.isGuideInterviewStage2 ?? true isGuideInterviewStage3.value = data.isGuideInterviewStage3 ?? true isInterviewUnlock.value = data.isInterviewUnlock ?? false InterviewUnlockProgress.value = data.InterviewUnlockProgress ?? 0 interviewMenuVisible.value = data.interviewMenuVisible ?? false guideShown.value = data.guideShown ?? {} practiceScrollPage.value = data.practiceScrollPage ?? 0 } catch (error) { console.error('Failed to load Interview store', error) } } function markViewed(key: string): void { if (!key) return viewed.value[key] = true InterviewUnlockProgress.value = Math.max( InterviewUnlockProgress.value, Math.min(completedStep.value + 1, 4), ) saveInterviewStore() } // 基于“子页面是否已查看”的大步骤完成度(1..3) // disabled 子项不计入(在这里直接不放进列表) const stepRouteNames = moduleStepMap.interview const completedStep = computed(() => { const isDone = (step: 1 | 2 | 3) => stepRouteNames[step].every((name) => viewed.value[name] === true) if (isDone(1) && isDone(2) && isDone(3)) return 3 if (isDone(1) && isDone(2)) return 2 if (isDone(1)) return 1 return 0 }) const progressPercent = computed(() => { const allRoutes = (Object.values(stepRouteNames) as string[][]).flat() if (allRoutes.length === 0) return 0 const viewedCount = allRoutes.filter((name) => viewed.value[name]).length return Math.round((viewedCount / allRoutes.length) * 100) }) function setIsGuideInterviewTask(value: boolean): void { isGuideInterviewTask.value = value saveInterviewStore() } function setIsGuideInterviewReturn(value: boolean): void { isGuideInterviewReturn.value = value saveInterviewStore() } function setIsGuideInterviewStage2(value: boolean): void { isGuideInterviewStage2.value = value saveInterviewStore() } function setIsGuideInterviewStage3(value: boolean): void { isGuideInterviewStage3.value = value saveInterviewStore() } function setIsInterviewUnlock(value: boolean): void { isInterviewUnlock.value = value saveInterviewStore() } function setInterviewUnlockProgress(value: number): void { const maxUnlockedStep = Math.min(completedStep.value + 1, 4) InterviewUnlockProgress.value = Math.min(value, maxUnlockedStep) saveInterviewStore() } function setInterviewMenuVisible(value: boolean): void { interviewMenuVisible.value = value saveInterviewStore() } function markGuideShown(key: string): void { if (!key) return guideShown.value[key] = true saveInterviewStore() } function setPracticeScrollPage(value: number): void { practiceScrollPage.value = value saveInterviewStore() } function resetInterviewState(): void { viewed.value = {} isGuideInterviewTask.value = true isGuideInterviewReturn.value = true isGuideInterviewStage2.value = true isGuideInterviewStage3.value = true isInterviewUnlock.value = false InterviewUnlockProgress.value = 0 interviewMenuVisible.value = false guideShown.value = {} practiceScrollPage.value = 0 saveInterviewStore() } return { //State markViewed, setIsGuideInterviewTask, setIsGuideInterviewReturn, setIsGuideInterviewStage2, setIsGuideInterviewStage3, setIsInterviewUnlock, setInterviewUnlockProgress, setInterviewMenuVisible, markGuideShown, setPracticeScrollPage, resetInterviewState, loadInterviewStore, saveInterviewStore, //Actions completedStep, progressPercent, viewed, isGuideInterviewTask, isGuideInterviewReturn, isGuideInterviewStage2, isGuideInterviewStage3, isInterviewUnlock, InterviewUnlockProgress, interviewMenuVisible, guideShown, practiceScrollPage, } }, { persist: true, }, )