File size: 4,230 Bytes
89ce340
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
<template>
  <div id="app">
    <!-- 未登录状态显示登录页面 -->
    <Login v-if="!authStore.isLoggedIn" />
    
    <!-- 已登录但数据加载中 -->
    <FullscreenSpin v-else-if="!dataLoaded" tip="数据加载中,请稍等..." loading :mask="false" />
    
    <!-- 已登录且数据已加载 -->
    <template v-else>
      <Screen v-if="screening" />
      <Editor v-else-if="_isPC" />
      <Mobile v-else />
    </template>
  </div>
</template>

<script lang="ts" setup>
import { onMounted, ref } from 'vue'
import { storeToRefs } from 'pinia'
import { useScreenStore, useMainStore, useSnapshotStore, useSlidesStore, useAuthStore } from '@/store'
import { LOCALSTORAGE_KEY_DISCARDED_DB } from '@/configs/storage'
import { deleteDiscardedDB } from '@/utils/database'
import { isPC } from '@/utils/common'
import api from '@/services'
import dataSyncService from '@/services/dataSyncService'

import Editor from './views/Editor/index.vue'
import Screen from './views/Screen/index.vue'
import Mobile from './views/Mobile/index.vue'
import Login from './views/Login.vue'
import FullscreenSpin from '@/components/FullscreenSpin.vue'

const _isPC = isPC()
const dataLoaded = ref(false)

const mainStore = useMainStore()
const slidesStore = useSlidesStore()
const snapshotStore = useSnapshotStore()
const authStore = useAuthStore()
const { databaseId } = storeToRefs(mainStore)
const { screening } = storeToRefs(useScreenStore())

if (import.meta.env.MODE !== 'development') {
  window.onbeforeunload = () => false
}

// 初始化应用数据
const initializeApp = async () => {
  try {
    // 初始化 DataSyncService(在 Pinia 可用后)
    await dataSyncService.initialize()
    
    // 如果用户已登录,加载用户的PPT数据
    if (authStore.isLoggedIn) {
      const pptList = await api.getPPTList()
      
      // 如果用户有PPT,加载第一个PPT;否则创建默认PPT
      if (pptList.length > 0) {
        const firstPPT = await api.getPPT(pptList[0].name)
        slidesStore.setSlides(firstPPT.slides)
        slidesStore.setTitle(firstPPT.title)
        if (firstPPT.theme) {
          slidesStore.setTheme(firstPPT.theme)
        }
        // 设置当前PPT ID以便自动保存
        dataSyncService.setCurrentPPTId(pptList[0].name)
      } 
      else {
        // 创建默认演示文稿
        const defaultPPT = await api.createPPT('我的第一个演示文稿')
        slidesStore.setSlides(defaultPPT.ppt.slides)
        slidesStore.setTitle(defaultPPT.ppt.title)
        slidesStore.setTheme(defaultPPT.ppt.theme)
        dataSyncService.setCurrentPPTId(defaultPPT.pptId)
      }
    } 
    else {
      // 未登录状态,加载默认示例数据
      const slides = await api.getFileData('slides')
      slidesStore.setSlides(slides)
    }

    await deleteDiscardedDB()
    snapshotStore.initSnapshotDatabase()
    dataLoaded.value = true
  } 
  catch (error) {
    // 如果是认证错误,清除登录状态
    if (error === 'Authentication failed') {
      authStore.logout()
    } 
    else {
      // 其他错误,加载默认数据
      try {
        const slides = await api.getFileData('slides')
        slidesStore.setSlides(slides)
        dataLoaded.value = true
      } 
      catch (fallbackError) {
        // 创建一个空的默认幻灯片
        slidesStore.setSlides([{
          id: 'default-slide',
          elements: [],
          background: { type: 'solid', color: '#ffffff' }
        }])
        dataLoaded.value = true
      }
    }
  }
}

onMounted(async () => {
  // 初始化认证状态
  await authStore.initAuth()
  
  // 初始化应用数据
  await initializeApp()
})

// 应用注销时向 localStorage 中记录下本次 indexedDB 的数据库ID,用于之后清除数据库
window.addEventListener('unload', () => {
  const discardedDB = localStorage.getItem(LOCALSTORAGE_KEY_DISCARDED_DB)
  const discardedDBList: string[] = discardedDB ? JSON.parse(discardedDB) : []

  discardedDBList.push(databaseId.value)

  const newDiscardedDB = JSON.stringify(discardedDBList)
  localStorage.setItem(LOCALSTORAGE_KEY_DISCARDED_DB, newDiscardedDB)
})
</script>

<style lang="scss">
#app {
  height: 100%;
}
</style>