feat: 完善访谈与vlog模块页面,重组设备与图片公共资源,新增音频管理与一班对接工具
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
c4c9be9d35
commit
fc9633f371
159 files changed
+4823
-2535
No files matched your search
@@ -1,5 +1,25 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
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<string, boolean>
|
||||
isGuideInterviewTask?: boolean
|
||||
isInterviewUnlock?: boolean
|
||||
InterviewUnlockProgress?: number
|
||||
}
|
||||
|
||||
async function getYibanApi(): Promise<typeof import('@/utils/yiban') | null> {
|
||||
try {
|
||||
return await import('@/utils/yiban')
|
||||
} catch (error) {
|
||||
console.error('Failed to load Yiban API', error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* I store - manages Interview information
|
||||
@@ -9,6 +29,12 @@ export const useInterviewStore = defineStore(
|
||||
() => {
|
||||
//State
|
||||
|
||||
/**
|
||||
* 已查看(停留≥阈值)记录
|
||||
* key 推荐用 route.name
|
||||
*/
|
||||
const viewed = ref<Record<string, boolean>>({})
|
||||
|
||||
//Interview-任务取景框引导
|
||||
const isGuideInterviewTask = ref<boolean>(true)
|
||||
//Interview-是否解锁完成前置(观看视频)
|
||||
@@ -17,24 +43,107 @@ export const useInterviewStore = defineStore(
|
||||
const InterviewUnlockProgress = ref<number>(0)
|
||||
|
||||
//Actions
|
||||
function saveInterviewStore(): void {
|
||||
const payload: InterviewSavePayload = {
|
||||
viewed: viewed.value,
|
||||
isGuideInterviewTask: isGuideInterviewTask.value,
|
||||
isInterviewUnlock: isInterviewUnlock.value,
|
||||
InterviewUnlockProgress: InterviewUnlockProgress.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<void> {
|
||||
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
|
||||
isInterviewUnlock.value = data.isInterviewUnlock ?? false
|
||||
InterviewUnlockProgress.value = data.InterviewUnlockProgress ?? 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<number>(() => {
|
||||
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<number>(() => {
|
||||
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 setIsInterviewUnlock(value: boolean): void {
|
||||
isInterviewUnlock.value = value
|
||||
saveInterviewStore()
|
||||
}
|
||||
|
||||
function setInterviewUnlockProgress(value: number): void {
|
||||
InterviewUnlockProgress.value = value
|
||||
const maxUnlockedStep = Math.min(completedStep.value + 1, 4)
|
||||
InterviewUnlockProgress.value = Math.min(value, maxUnlockedStep)
|
||||
saveInterviewStore()
|
||||
}
|
||||
|
||||
function resetInterviewState(): void {
|
||||
viewed.value = {}
|
||||
isGuideInterviewTask.value = true
|
||||
isInterviewUnlock.value = false
|
||||
InterviewUnlockProgress.value = 0
|
||||
saveInterviewStore()
|
||||
}
|
||||
|
||||
return {
|
||||
//State
|
||||
markViewed,
|
||||
setIsGuideInterviewTask,
|
||||
setIsInterviewUnlock,
|
||||
setInterviewUnlockProgress,
|
||||
resetInterviewState,
|
||||
loadInterviewStore,
|
||||
saveInterviewStore,
|
||||
//Actions
|
||||
completedStep,
|
||||
progressPercent,
|
||||
viewed,
|
||||
isGuideInterviewTask,
|
||||
isInterviewUnlock,
|
||||
InterviewUnlockProgress
|
||||
|
||||
Reference in new issue
Block a user