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 |