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 { // 动态导入 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 { 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 { 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 { 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 { return await this.savePPT(true) } } // 创建单例实例 export const dataSyncService = new DataSyncService() export default dataSyncService