CatPtain commited on
Commit
10b14be
·
verified ·
1 Parent(s): b4fad0c

Update frontend/src/services/dataSyncService.ts

Browse files
Files changed (1) hide show
  1. frontend/src/services/dataSyncService.ts +257 -254
frontend/src/services/dataSyncService.ts CHANGED
@@ -1,255 +1,258 @@
1
- import api from '@/services'
2
- import { debounce } from 'lodash'
3
-
4
- class DataSyncService {
5
- private currentPPTId: string | null = null
6
- private saveTimeout: number | null = null
7
- private isOnline = true
8
- private autoSaveDelay = 300000 // 默认5分钟,可配置
9
- private isInitialized = false
10
- private debouncedSave: any = null
11
-
12
- constructor() {
13
- this.setupNetworkMonitoring()
14
- }
15
-
16
- // 延迟初始化,在 Pinia 可用后调用
17
- async initialize() {
18
- if (this.isInitialized) return
19
- await this.setupAutoSave()
20
- this.isInitialized = true
21
- }
22
-
23
- // 设置自动保存延迟时间(毫秒)
24
- setAutoSaveDelay(delay: number) {
25
- this.autoSaveDelay = Math.max(500, delay) // 最小500ms
26
- if (this.isInitialized) {
27
- this.setupAutoSave() // 重新设置自动保存
28
- }
29
- }
30
-
31
- // 获取当前自动保存延迟时间
32
- getAutoSaveDelay(): number {
33
- return this.autoSaveDelay
34
- }
35
-
36
- // 设置当前PPT ID
37
- setCurrentPPTId(pptId: string) {
38
- this.currentPPTId = pptId
39
- }
40
-
41
- // 自动保存功能
42
- private async setupAutoSave() {
43
- if (this.debouncedSave) {
44
- this.debouncedSave.cancel()
45
- }
46
-
47
- this.debouncedSave = debounce(async () => {
48
- await this.savePPT()
49
- }, this.autoSaveDelay) // 使用可配置的延迟时间
50
-
51
- // 监听slides变化
52
- try {
53
- const { useSlidesStore } = await import('@/store')
54
- const slidesStore = useSlidesStore()
55
- slidesStore.$subscribe(() => {
56
- if (this.isOnline && this.currentPPTId) {
57
- this.debouncedSave()
58
- }
59
- })
60
- }
61
- catch (error) {
62
- // console.warn('无法设置自动保存,store 未就绪:', error)
63
- }
64
- }
65
-
66
- // 网络状态监控
67
- private setupNetworkMonitoring() {
68
- window.addEventListener('online', () => {
69
- this.isOnline = true
70
- // console.log('网络已连接,恢复自动保存')
71
- })
72
-
73
- window.addEventListener('offline', () => {
74
- this.isOnline = false
75
- // console.log('网络已断开,暂停自动保存')
76
- })
77
- }
78
-
79
- // 保存PPT到后端
80
- async savePPT(force = false): Promise<boolean> {
81
- // 动态导入 store,避免初始化时的依赖问题
82
- const { useAuthStore, useSlidesStore } = await import('@/store')
83
-
84
- try {
85
- const authStore = useAuthStore()
86
- const slidesStore = useSlidesStore()
87
-
88
- if (!authStore.isLoggedIn) {
89
- // console.warn('用户未登录,无法保存')
90
- return false
91
- }
92
-
93
- // 如果没有当前PPT ID且是强制保存,创建新PPT
94
- if (!this.currentPPTId && force) {
95
- try {
96
- const response = await api.createPPT(slidesStore.title || '未命名演示文稿')
97
- this.currentPPTId = response.pptId
98
-
99
- // 更新slides store中的数据以匹配新创建的PPT
100
- if (response.ppt) {
101
- slidesStore.setSlides(response.ppt.slides)
102
- slidesStore.setTitle(response.ppt.title)
103
- slidesStore.setTheme(response.ppt.theme)
104
- }
105
-
106
- // console.log('创建新PPT并保存成功')
107
- return true
108
- }
109
- catch (createError) {
110
- // console.error('创建新PPT失败:', createError)
111
- return false
112
- }
113
- }
114
-
115
- if (!this.currentPPTId && !force) {
116
- // console.warn('没有当前PPT ID')
117
- return false
118
- }
119
-
120
- const pptData = {
121
- pptId: this.currentPPTId,
122
- title: slidesStore.title,
123
- slides: slidesStore.slides,
124
- theme: slidesStore.theme
125
- }
126
-
127
- await api.savePPT(pptData)
128
- // console.log('PPT保存成功')
129
- return true
130
- }
131
- catch (error) {
132
- // console.error('PPT保存失败:', error)
133
- return false
134
- }
135
- }
136
-
137
- // 创建新PPT
138
- async createNewPPT(title: string): Promise<string | null> {
139
- const { useAuthStore } = await import('@/store')
140
- const authStore = useAuthStore()
141
-
142
- if (!authStore.isLoggedIn) {
143
- throw new Error('用户未登录')
144
- }
145
-
146
- try {
147
- const response = await api.createPPT(title)
148
- this.setCurrentPPTId(response.pptId)
149
- return response.pptId
150
- }
151
- catch (error) {
152
- // console.error('创建PPT失败:', error)
153
- throw error
154
- }
155
- }
156
-
157
- // 加载PPT
158
- async loadPPT(pptId: string): Promise<boolean> {
159
- const { useAuthStore, useSlidesStore } = await import('@/store')
160
- const authStore = useAuthStore()
161
- const slidesStore = useSlidesStore()
162
-
163
- if (!authStore.isLoggedIn) {
164
- throw new Error('用户未登录')
165
- }
166
-
167
- try {
168
- const pptData = await api.getPPT(pptId)
169
-
170
- slidesStore.setSlides(pptData.slides)
171
- slidesStore.setTitle(pptData.title)
172
- if (pptData.theme) {
173
- slidesStore.setTheme(pptData.theme)
174
- }
175
-
176
- this.setCurrentPPTId(pptId)
177
- // console.log('PPT加载成功')
178
- return true
179
- }
180
- catch (error) {
181
- // console.error('PPT加载失败:', error)
182
- throw error
183
- }
184
- }
185
-
186
- // 获取PPT列表
187
- async getPPTList() {
188
- const { useAuthStore } = await import('@/store')
189
- const authStore = useAuthStore()
190
-
191
- if (!authStore.isLoggedIn) {
192
- throw new Error('用户未登录')
193
- }
194
-
195
- return await api.getPPTList()
196
- }
197
-
198
- // 删除PPT
199
- async deletePPT(pptId: string): Promise<boolean> {
200
- const { useAuthStore } = await import('@/store')
201
- const authStore = useAuthStore()
202
-
203
- if (!authStore.isLoggedIn) {
204
- throw new Error('用户未登录')
205
- }
206
-
207
- try {
208
- await api.deletePPT(pptId)
209
-
210
- // 如果删除的是当前PPT,清除当前PPT ID
211
- if (this.currentPPTId === pptId) {
212
- this.currentPPTId = null
213
- }
214
-
215
- // console.log('PPT删除成功')
216
- return true
217
- }
218
- catch (error) {
219
- // console.error('PPT删除失败:', error)
220
- throw error
221
- }
222
- }
223
-
224
- // 生成分享链接
225
- async generateShareLink(slideIndex = 0) {
226
- const { useAuthStore } = await import('@/store')
227
- const authStore = useAuthStore()
228
-
229
- if (!authStore.isLoggedIn || !this.currentPPTId) {
230
- throw new Error('用户未登录或没有当前PPT')
231
- }
232
-
233
- try {
234
- const response = await api.generateShareLink(
235
- authStore.currentUser!.id,
236
- this.currentPPTId,
237
- slideIndex
238
- )
239
- return response
240
- }
241
- catch (error) {
242
- // console.error('生成分享链接失败:', error)
243
- throw error
244
- }
245
- }
246
-
247
- // 手动保存
248
- async manualSave(): Promise<boolean> {
249
- return await this.savePPT(true)
250
- }
251
- }
252
-
253
- // 创建单例实例
254
- export const dataSyncService = new DataSyncService()
 
 
 
255
  export default dataSyncService
 
1
+ import api from '@/services'
2
+ import { debounce } from 'lodash'
3
+
4
+ class DataSyncService {
5
+ private currentPPTId: string | null = null
6
+ private saveTimeout: number | null = null
7
+ private isOnline = true
8
+ private autoSaveDelay = 300000 // 默认5分钟,可配置
9
+ private isInitialized = false
10
+ private debouncedSave: any = null
11
+
12
+ constructor() {
13
+ this.setupNetworkMonitoring()
14
+ }
15
+
16
+ // 延迟初始化,在 Pinia 可用后调用
17
+ async initialize() {
18
+ if (this.isInitialized) return
19
+ await this.setupAutoSave()
20
+ this.isInitialized = true
21
+ }
22
+
23
+ // 设置自动保存延迟时间(毫秒)
24
+ setAutoSaveDelay(delay: number) {
25
+ this.autoSaveDelay = Math.max(500, delay) // 最小500ms
26
+ if (this.isInitialized) {
27
+ this.setupAutoSave() // 重新设置自动保存
28
+ }
29
+ }
30
+
31
+ // 获取当前自动保存延迟时间
32
+ getAutoSaveDelay(): number {
33
+ return this.autoSaveDelay
34
+ }
35
+
36
+ // 设置当前PPT ID
37
+ setCurrentPPTId(pptId: string) {
38
+ this.currentPPTId = pptId
39
+ }
40
+
41
+ // 自动保存功能
42
+ private async setupAutoSave() {
43
+ if (this.debouncedSave) {
44
+ this.debouncedSave.cancel()
45
+ }
46
+
47
+ this.debouncedSave = debounce(async () => {
48
+ await this.savePPT()
49
+ }, this.autoSaveDelay) // 使用可配置的延迟时间
50
+
51
+ // 监听slides变化
52
+ try {
53
+ const { useSlidesStore } = await import('@/store')
54
+ const slidesStore = useSlidesStore()
55
+ slidesStore.$subscribe(() => {
56
+ if (this.isOnline && this.currentPPTId) {
57
+ this.debouncedSave()
58
+ }
59
+ })
60
+ }
61
+ catch (error) {
62
+ // console.warn('无法设置自动保存,store 未就绪:', error)
63
+ }
64
+ }
65
+
66
+ // 网络状态监控
67
+ private setupNetworkMonitoring() {
68
+ window.addEventListener('online', () => {
69
+ this.isOnline = true
70
+ // console.log('网络已连接,恢复自动保存')
71
+ })
72
+
73
+ window.addEventListener('offline', () => {
74
+ this.isOnline = false
75
+ // console.log('网络已断开,暂停自动保存')
76
+ })
77
+ }
78
+
79
+ // 保存PPT到后端
80
+ async savePPT(force = false): Promise<boolean> {
81
+ // 动态导入 store,避免初始化时的依赖问题
82
+ const { useAuthStore, useSlidesStore } = await import('@/store')
83
+
84
+ try {
85
+ const authStore = useAuthStore()
86
+ const slidesStore = useSlidesStore()
87
+
88
+ if (!authStore.isLoggedIn) {
89
+ // console.warn('用户未登录,无法保存')
90
+ return false
91
+ }
92
+
93
+ // 如果没有当前PPT ID且是强制保存,创建新PPT
94
+ if (!this.currentPPTId && force) {
95
+ try {
96
+ const response = await api.createPPT(slidesStore.title || '未命名演示文稿')
97
+ this.currentPPTId = response.pptId
98
+
99
+ // 更新slides store中的数据以匹配新创建的PPT
100
+ if (response.ppt) {
101
+ slidesStore.setSlides(response.ppt.slides)
102
+ slidesStore.setTitle(response.ppt.title)
103
+ slidesStore.setTheme(response.ppt.theme)
104
+ }
105
+
106
+ // console.log('创建新PPT并保存成功')
107
+ return true
108
+ }
109
+ catch (createError) {
110
+ // console.error('创建新PPT失败:', createError)
111
+ return false
112
+ }
113
+ }
114
+
115
+ if (!this.currentPPTId && !force) {
116
+ // console.warn('没有当前PPT ID')
117
+ return false
118
+ }
119
+
120
+ const pptData = {
121
+ pptId: this.currentPPTId,
122
+ title: slidesStore.title,
123
+ slides: slidesStore.slides,
124
+ theme: slidesStore.theme,
125
+ // 添加关键的尺寸信息
126
+ viewportSize: slidesStore.viewportSize,
127
+ viewportRatio: slidesStore.viewportRatio
128
+ }
129
+
130
+ await api.savePPT(pptData)
131
+ // console.log('PPT保存成功')
132
+ return true
133
+ }
134
+ catch (error) {
135
+ // console.error('PPT保存失败:', error)
136
+ return false
137
+ }
138
+ }
139
+
140
+ // 创建新PPT
141
+ async createNewPPT(title: string): Promise<string | null> {
142
+ const { useAuthStore } = await import('@/store')
143
+ const authStore = useAuthStore()
144
+
145
+ if (!authStore.isLoggedIn) {
146
+ throw new Error('用户未登录')
147
+ }
148
+
149
+ try {
150
+ const response = await api.createPPT(title)
151
+ this.setCurrentPPTId(response.pptId)
152
+ return response.pptId
153
+ }
154
+ catch (error) {
155
+ // console.error('创建PPT失败:', error)
156
+ throw error
157
+ }
158
+ }
159
+
160
+ // 加载PPT
161
+ async loadPPT(pptId: string): Promise<boolean> {
162
+ const { useAuthStore, useSlidesStore } = await import('@/store')
163
+ const authStore = useAuthStore()
164
+ const slidesStore = useSlidesStore()
165
+
166
+ if (!authStore.isLoggedIn) {
167
+ throw new Error('用户未登录')
168
+ }
169
+
170
+ try {
171
+ const pptData = await api.getPPT(pptId)
172
+
173
+ slidesStore.setSlides(pptData.slides)
174
+ slidesStore.setTitle(pptData.title)
175
+ if (pptData.theme) {
176
+ slidesStore.setTheme(pptData.theme)
177
+ }
178
+
179
+ this.setCurrentPPTId(pptId)
180
+ // console.log('PPT加载成功')
181
+ return true
182
+ }
183
+ catch (error) {
184
+ // console.error('PPT加载失败:', error)
185
+ throw error
186
+ }
187
+ }
188
+
189
+ // 获取PPT列表
190
+ async getPPTList() {
191
+ const { useAuthStore } = await import('@/store')
192
+ const authStore = useAuthStore()
193
+
194
+ if (!authStore.isLoggedIn) {
195
+ throw new Error('用户未登录')
196
+ }
197
+
198
+ return await api.getPPTList()
199
+ }
200
+
201
+ // 删除PPT
202
+ async deletePPT(pptId: string): Promise<boolean> {
203
+ const { useAuthStore } = await import('@/store')
204
+ const authStore = useAuthStore()
205
+
206
+ if (!authStore.isLoggedIn) {
207
+ throw new Error('用户未登录')
208
+ }
209
+
210
+ try {
211
+ await api.deletePPT(pptId)
212
+
213
+ // 如果删除的是当前PPT,清除当前PPT ID
214
+ if (this.currentPPTId === pptId) {
215
+ this.currentPPTId = null
216
+ }
217
+
218
+ // console.log('PPT删除成功')
219
+ return true
220
+ }
221
+ catch (error) {
222
+ // console.error('PPT删除失败:', error)
223
+ throw error
224
+ }
225
+ }
226
+
227
+ // 生成分享链接
228
+ async generateShareLink(slideIndex = 0) {
229
+ const { useAuthStore } = await import('@/store')
230
+ const authStore = useAuthStore()
231
+
232
+ if (!authStore.isLoggedIn || !this.currentPPTId) {
233
+ throw new Error('用户未登录或没有当前PPT')
234
+ }
235
+
236
+ try {
237
+ const response = await api.generateShareLink(
238
+ authStore.currentUser!.id,
239
+ this.currentPPTId,
240
+ slideIndex
241
+ )
242
+ return response
243
+ }
244
+ catch (error) {
245
+ // console.error('生成分享链接失败:', error)
246
+ throw error
247
+ }
248
+ }
249
+
250
+ // 手动保存
251
+ async manualSave(): Promise<boolean> {
252
+ return await this.savePPT(true)
253
+ }
254
+ }
255
+
256
+ // 创建单例实例
257
+ export const dataSyncService = new DataSyncService()
258
  export default dataSyncService