File size: 6,803 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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
import api from '@/services'
import { debounce } from 'lodash'

class DataSyncService {
  private currentPPTId: string | null = null
  private saveTimeout: number | null = null
  private isOnline = true
  private autoSaveDelay = 300000 // 默认5分钟,可配置
  private isInitialized = false
  private debouncedSave: any = null

  constructor() {
    this.setupNetworkMonitoring()
  }

  // 延迟初始化,在 Pinia 可用后调用
  async initialize() {
    if (this.isInitialized) return
    await this.setupAutoSave()
    this.isInitialized = true
  }

  // 设置自动保存延迟时间(毫秒)
  setAutoSaveDelay(delay: number) {
    this.autoSaveDelay = Math.max(500, delay) // 最小500ms
    if (this.isInitialized) {
      this.setupAutoSave() // 重新设置自动保存
    }
  }

  // 获取当前自动保存延迟时间
  getAutoSaveDelay(): number {
    return this.autoSaveDelay
  }

  // 设置当前PPT ID
  setCurrentPPTId(pptId: string) {
    this.currentPPTId = pptId
  }

  // 自动保存功能
  private async setupAutoSave() {
    if (this.debouncedSave) {
      this.debouncedSave.cancel()
    }

    this.debouncedSave = debounce(async () => {
      await this.savePPT()
    }, this.autoSaveDelay) // 使用可配置的延迟时间

    // 监听slides变化
    try {
      const { useSlidesStore } = await import('@/store')
      const slidesStore = useSlidesStore()
      slidesStore.$subscribe(() => {
        if (this.isOnline && this.currentPPTId) {
          this.debouncedSave()
        }
      })
    } 
    catch (error) {
      // console.warn('无法设置自动保存,store 未就绪:', error)
    }
  }

  // 网络状态监控
  private setupNetworkMonitoring() {
    window.addEventListener('online', () => {
      this.isOnline = true
      // console.log('网络已连接,恢复自动保存')
    })

    window.addEventListener('offline', () => {
      this.isOnline = false
      // console.log('网络已断开,暂停自动保存')
    })
  }

  // 保存PPT到后端
  async savePPT(force = false): Promise<boolean> {
    // 动态导入 store,避免初始化时的依赖问题
    const { useAuthStore, useSlidesStore } = await import('@/store')
    
    try {
      const authStore = useAuthStore()
      const slidesStore = useSlidesStore()

      if (!authStore.isLoggedIn) {
        // console.warn('用户未登录,无法保存')
        return false
      }

      // 如果没有当前PPT ID且是强制保存,创建新PPT
      if (!this.currentPPTId && force) {
        try {
          const response = await api.createPPT(slidesStore.title || '未命名演示文稿')
          this.currentPPTId = response.pptId
          
          // 更新slides store中的数据以匹配新创建的PPT
          if (response.ppt) {
            slidesStore.setSlides(response.ppt.slides)
            slidesStore.setTitle(response.ppt.title)
            slidesStore.setTheme(response.ppt.theme)
          }
          
          // console.log('创建新PPT并保存成功')
          return true
        } 
        catch (createError) {
          // console.error('创建新PPT失败:', createError)
          return false
        }
      }

      if (!this.currentPPTId && !force) {
        // console.warn('没有当前PPT ID')
        return false
      }

      const pptData = {
        pptId: this.currentPPTId,
        title: slidesStore.title,
        slides: slidesStore.slides,
        theme: slidesStore.theme
      }

      await api.savePPT(pptData)
      // console.log('PPT保存成功')
      return true
    } 
    catch (error) {
      // console.error('PPT保存失败:', error)
      return false
    }
  }

  // 创建新PPT
  async createNewPPT(title: string): Promise<string | null> {
    const { useAuthStore } = await import('@/store')
    const authStore = useAuthStore()

    if (!authStore.isLoggedIn) {
      throw new Error('用户未登录')
    }

    try {
      const response = await api.createPPT(title)
      this.setCurrentPPTId(response.pptId)
      return response.pptId
    } 
    catch (error) {
      // console.error('创建PPT失败:', error)
      throw error
    }
  }

  // 加载PPT
  async loadPPT(pptId: string): Promise<boolean> {
    const { useAuthStore, useSlidesStore } = await import('@/store')
    const authStore = useAuthStore()
    const slidesStore = useSlidesStore()

    if (!authStore.isLoggedIn) {
      throw new Error('用户未登录')
    }

    try {
      const pptData = await api.getPPT(pptId)
      
      slidesStore.setSlides(pptData.slides)
      slidesStore.setTitle(pptData.title)
      if (pptData.theme) {
        slidesStore.setTheme(pptData.theme)
      }
      
      this.setCurrentPPTId(pptId)
      // console.log('PPT加载成功')
      return true
    } 
    catch (error) {
      // console.error('PPT加载失败:', error)
      throw error
    }
  }

  // 获取PPT列表
  async getPPTList() {
    const { useAuthStore } = await import('@/store')
    const authStore = useAuthStore()

    if (!authStore.isLoggedIn) {
      throw new Error('用户未登录')
    }

    return await api.getPPTList()
  }

  // 删除PPT
  async deletePPT(pptId: string): Promise<boolean> {
    const { useAuthStore } = await import('@/store')
    const authStore = useAuthStore()

    if (!authStore.isLoggedIn) {
      throw new Error('用户未登录')
    }

    try {
      await api.deletePPT(pptId)
      
      // 如果删除的是当前PPT,清除当前PPT ID
      if (this.currentPPTId === pptId) {
        this.currentPPTId = null
      }
      
      // console.log('PPT删除成功')
      return true
    } 
    catch (error) {
      // console.error('PPT删除失败:', error)
      throw error
    }
  }

  // 生成分享链接
  async generateShareLink(slideIndex = 0) {
    const { useAuthStore } = await import('@/store')
    const authStore = useAuthStore()

    if (!authStore.isLoggedIn || !this.currentPPTId) {
      throw new Error('用户未登录或没有当前PPT')
    }

    try {
      const response = await api.generateShareLink(
        authStore.currentUser!.id,
        this.currentPPTId,
        slideIndex
      )
      return response
    } 
    catch (error) {
      // console.error('生成分享链接失败:', error)
      throw error
    }
  }

  // 手动保存
  async manualSave(): Promise<boolean> {
    return await this.savePPT(true)
  }
}

// 创建单例实例
export const dataSyncService = new DataSyncService()
export default dataSyncService