From 109a9fe35bae09f7efa6d90df1171f4cd4ac238e Mon Sep 17 00:00:00 2001 From: memorylkf <312904636@qq.com> Date: Wed, 7 Jan 2026 13:53:33 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20[=E8=90=BD=E7=AC=94=E7=95=99=E7=97=95]?= =?UTF-8?q?=20=E6=B5=8B=E8=AF=95=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/business/template/list.vue | 10 +- src/views/lblh/components/AutoSaveManager.js | 357 +++++++++++---------- src/views/lblh/components/storage/ServerStorage.js | 204 ++++++------ src/views/lblh/index.vue | 8 +- 4 files changed, 298 insertions(+), 281 deletions(-) diff --git a/src/views/business/template/list.vue b/src/views/business/template/list.vue index 7d10034..dbc3768 100644 --- a/src/views/business/template/list.vue +++ b/src/views/business/template/list.vue @@ -47,8 +47,8 @@ @@ -100,8 +100,8 @@ - - + + @@ -131,7 +131,7 @@ const EmptyDialogData = { deptId: '', status:10, needPre: 10, - type: 1, + type: 10, } export default { name: "Template", diff --git a/src/views/lblh/components/AutoSaveManager.js b/src/views/lblh/components/AutoSaveManager.js index 0abcfa7..840274c 100644 --- a/src/views/lblh/components/AutoSaveManager.js +++ b/src/views/lblh/components/AutoSaveManager.js @@ -1,50 +1,53 @@ // import MemoryStorage from './storage/MemoryStorage.js'; -import LocalStorage from './storage/LocalStorage.js'; +import LocalStorage from './storage/LocalStorage.js' // import SessionStorage from './storage/SessionStorage.js'; -import IndexedDBStorage from './storage/IndexedDBStorage.js'; -import ServerStorage from './storage/ServerStorage.js'; +import IndexedDBStorage from './storage/IndexedDBStorage.js' +import ServerStorage from './storage/ServerStorage.js' /** * 自动保存管理器 * 协调各种存储方式,处理冲突合并 */ class AutoSaveManager { - constructor(key, serverOptions = { - endpoint:process.env.VUE_APP_BASE_API, - syncEndpoint:process.env.VUE_APP_BASE_API, - historyEndpoint:process.env.VUE_APP_BASE_API, - }) { - this.key = key; - + constructor( + key, + serverOptions = { + endpoint: process.env.VUE_APP_BASE_API, + syncEndpoint: process.env.VUE_APP_BASE_API, + historyEndpoint: process.env.VUE_APP_BASE_API + } + ) { + this.key = key + try { this.storages = { // memory: new MemoryStorage(key), - // localStorage: new LocalStorage(key), + localStorage: new LocalStorage(key), // sessionStorage: new SessionStorage(key), - indexedDB: new IndexedDBStorage(key), + // indexedDB: new IndexedDBStorage(key), server: new ServerStorage(key, serverOptions) - }; + } } catch (error) { - console.error('初始化存储失败:', error); + console.error('初始化存储失败:', error) // 如果某个存储初始化失败,只使用可用的存储 this.storages = { // memory: new MemoryStorage(key), - localStorage: new LocalStorage(key), + localStorage: new LocalStorage(key) // sessionStorage: new SessionStorage(key) - }; + } } - this.states = {}; - this.initStates(); - - this.isSaving = false; - this.saveTimer = null; - this.debounceDelay = 1000;// 防抖延迟 - this.currentContent = ''; - this.lastSavedContent = ''; - + this.states = {} + this.initStates() + + this.isSaving = false + this.saveTimer = null + this.debounceDelay = 1000 // 防抖延迟 + this.currentContent = '' + this.lastSavedContent = '' + // 异步初始化 - this.initPromise = this.init(); + this.initPromise = this.init() } /** @@ -52,12 +55,12 @@ class AutoSaveManager { */ initStates() { for (const type in this.storages) { - this.states[type] = { - status: 'idle', - lastSaved: null, + this.states[type] = { + status: 'idle', + lastSaved: null, error: null, initialized: false - }; + } } } @@ -65,7 +68,7 @@ class AutoSaveManager { * 等待初始化完成 */ async waitForInit() { - await this.initPromise; + await this.initPromise } /** @@ -74,17 +77,17 @@ class AutoSaveManager { async init() { try { // 加载所有存储的数据 - await this.loadFromAllStorages(); - + await this.loadFromAllStorages() + // 设置页面关闭前保存 - this.setupBeforeUnload(); - + this.setupBeforeUnload() + // 设置页面崩溃检测 - this.setupCrashDetection(); - - console.log(`AutoSaveManager 初始化完成,key: ${this.key}`); + this.setupCrashDetection() + + console.log(`AutoSaveManager 初始化完成,key: ${this.key}`) } catch (error) { - console.error('AutoSaveManager 初始化失败:', error); + console.error('AutoSaveManager 初始化失败:', error) } } @@ -92,41 +95,43 @@ class AutoSaveManager { * 从所有存储加载数据并合并 */ async loadFromAllStorages() { - const results = {}; - + const results = {} + // 并行加载所有存储 - const promises = Object.entries(this.storages).map(async ([type, storage]) => { - try { - // 确保存储已初始化 - if (storage.waitForInit) { - await storage.waitForInit(); + const promises = Object.entries(this.storages).map( + async ([type, storage]) => { + try { + // 确保存储已初始化 + if (storage.waitForInit) { + await storage.waitForInit() + } + + const result = await storage.load() + results[type] = result + this.updateState(type, 'loaded', { + ...result, + initialized: true + }) + + return result + } catch (error) { + console.error(`加载${type}存储失败:`, error) + this.updateState(type, 'error', { + error: error.message, + initialized: false + }) + return null } - - const result = await storage.load(); - results[type] = result; - this.updateState(type, 'loaded', { - ...result, - initialized: true - }); - - return result; - } catch (error) { - console.error(`加载${type}存储失败:`, error); - this.updateState(type, 'error', { - error: error.message, - initialized: false - }); - return null; } - }); - - await Promise.allSettled(promises); - + ) + + await Promise.allSettled(promises) + // 选择最新版本的内容 // this.currentContent = this.resolveConflicts(results); - this.lastSavedContent = this.currentContent; - - return this.currentContent; + this.lastSavedContent = this.currentContent + + return this.currentContent } /** @@ -135,31 +140,31 @@ class AutoSaveManager { * @returns {string} 合并后的内容 */ resolveConflicts(results) { - let latestContent = ''; - let latestTimestamp = 0; + let latestContent = '' + let latestTimestamp = 0 Object.entries(results).forEach(([type, result]) => { if (result && result.success && result.data) { - let data = result.data; - let timestamp = 0; - let content = ''; - + let data = result.data + let timestamp = 0 + let content = '' + if (typeof data === 'object' && data !== null) { - timestamp = data.timestamp || data.lastModified || 0; - content = data.content || ''; + timestamp = data.timestamp || data.lastModified || 0 + content = data.content || '' } else if (typeof data === 'string') { - content = data; - timestamp = Date.now(); // 字符串数据给一个默认时间戳 + content = data + timestamp = Date.now() // 字符串数据给一个默认时间戳 } - + if (timestamp > latestTimestamp) { - latestTimestamp = timestamp; - latestContent = content; + latestTimestamp = timestamp + latestContent = content } } - }); + }) - return latestContent || ''; + return latestContent || '' } /** @@ -167,22 +172,22 @@ class AutoSaveManager { * @param {string} content - 要保存的内容 */ save(content) { - this.currentContent = content; - + this.currentContent = content + // 如果内容没有变化,不保存 if (content === this.lastSavedContent) { - return; + return } // 清除之前的定时器 if (this.saveTimer) { - clearTimeout(this.saveTimer); + clearTimeout(this.saveTimer) } // 设置新的定时器 this.saveTimer = setTimeout(() => { - this.doSave(content); - }, this.debounceDelay); + this.doSave(content) + }, this.debounceDelay) } /** @@ -191,51 +196,53 @@ class AutoSaveManager { */ async doSave(content) { if (this.isSaving) { - return; + return } - this.isSaving = true; - this.lastSavedContent = content; + this.isSaving = true + this.lastSavedContent = content try { // 并行保存到所有存储 - const promises = Object.entries(this.storages).map(async ([type, storage]) => { - try { - // 检查存储是否可用 - if (!storage || this.states[type]?.error) { - this.updateState(type, 'error', { - error: '存储不可用', - retry: true - }); - return null; - } - - this.updateState(type, 'saving'); - const result = await storage.save(content); - - if (result && result.success) { - this.updateState(type, 'saved', result); - } else { + const promises = Object.entries(this.storages).map( + async ([type, storage]) => { + try { + // 检查存储是否可用 + if (!storage || this.states[type]?.error) { + this.updateState(type, 'error', { + error: '存储不可用', + retry: true + }) + return null + } + + this.updateState(type, 'saving') + const result = await storage.save(content) + + if (result && result.success) { + this.updateState(type, 'saved', result) + } else { + this.updateState(type, 'error', { + error: result?.error || '保存失败', + retry: true + }) + } + + return result + } catch (error) { + console.error(`保存到${type}失败:`, error) this.updateState(type, 'error', { - error: result?.error || '保存失败', + error: error.message, retry: true - }); + }) + return null } - - return result; - } catch (error) { - console.error(`保存到${type}失败:`, error); - this.updateState(type, 'error', { - error: error.message, - retry: true - }); - return null; } - }); + ) - await Promise.allSettled(promises); + await Promise.allSettled(promises) } finally { - this.isSaving = false; + this.isSaving = false } } @@ -251,10 +258,10 @@ class AutoSaveManager { status, ...data, lastUpdated: Date.now() - }; - + } + if (status === 'saved' && data.timestamp) { - this.states[type].lastSaved = data.timestamp; + this.states[type].lastSaved = data.timestamp } } @@ -263,7 +270,7 @@ class AutoSaveManager { * @returns {object} 状态对象 */ getAllStates() { - return { ...this.states }; + return { ...this.states } } /** @@ -273,9 +280,9 @@ class AutoSaveManager { */ async getHistory(storageType) { if (this.storages[storageType]) { - return await this.storages[storageType].getHistory(); + return await this.storages[storageType].getHistory() } - return { success: false, error: '存储类型不存在' }; + return { success: false, error: '存储类型不存在' } } /** @@ -285,12 +292,12 @@ class AutoSaveManager { */ async restoreFromHistory(storageType, versionData) { if (this.storages[storageType]) { - const content = versionData.content || versionData; - await this.doSave(content); - this.currentContent = content; - return { success: true, content }; + const content = versionData.content || versionData + await this.doSave(content) + this.currentContent = content + return { success: true, content } } - return { success: false, error: '存储类型不存在' }; + return { success: false, error: '存储类型不存在' } } /** @@ -300,9 +307,9 @@ class AutoSaveManager { window.addEventListener('beforeunload', (event) => { if (this.currentContent !== this.lastSavedContent) { // 同步保存(不防抖) - this.doSaveSync(this.currentContent); + this.doSaveSync(this.currentContent) } - }); + }) } /** @@ -311,15 +318,15 @@ class AutoSaveManager { */ async doSaveSync(content) { // 只保存到本地存储,确保数据不丢失 - const localStorages = ['memory', 'localStorage', 'sessionStorage']; - + const localStorages = ['memory', 'localStorage', 'sessionStorage'] + localStorages.forEach(async (type) => { try { - await this.storages[type].save(content); + await this.storages[type].save(content) } catch (error) { - console.error(`页面关闭前保存到${type}失败:`, error); + console.error(`页面关闭前保存到${type}失败:`, error) } - }); + }) } /** @@ -330,23 +337,23 @@ class AutoSaveManager { document.addEventListener('visibilitychange', () => { if (document.visibilityState === 'visible') { // 页面恢复显示,检查是否需要同步 - this.checkAndSync(); + this.checkAndSync() } - }); + }) // 监听页面冻结和恢复 document.addEventListener('freeze', () => { - localStorage.setItem(`pageFrozen_${this.key}`, Date.now()); - }); + localStorage.setItem(`pageFrozen_${this.key}`, Date.now()) + }) document.addEventListener('resume', () => { - const frozenTime = localStorage.getItem(`pageFrozen_${this.key}`); + const frozenTime = localStorage.getItem(`pageFrozen_${this.key}`) if (frozenTime && Date.now() - frozenTime > 5000) { // 页面被冻结超过5秒,可能是崩溃恢复 - this.showCrashNotification(); + this.showCrashNotification() } - localStorage.removeItem(`pageFrozen_${this.key}`); - }); + localStorage.removeItem(`pageFrozen_${this.key}`) + }) } /** @@ -354,11 +361,11 @@ class AutoSaveManager { */ async checkAndSync() { // 重新加载所有数据并合并 - await this.loadFromAllStorages(); - + await this.loadFromAllStorages() + // 如果有服务器存储,尝试同步离线队列 if (this.storages.server) { - this.storages.server.processQueue(); + this.storages.server.processQueue() } } @@ -366,7 +373,7 @@ class AutoSaveManager { * 显示崩溃通知 */ showCrashNotification() { - const notification = document.createElement('div'); + const notification = document.createElement('div') notification.style.cssText = ` position: fixed; top: 20px; @@ -377,16 +384,16 @@ class AutoSaveManager { border-radius: 5px; z-index: 10000; box-shadow: 0 2px 10px rgba(0,0,0,0.2); - `; + ` notification.innerHTML = ` 页面恢复
检测到页面可能发生了异常,已自动恢复您的数据。 - `; - document.body.appendChild(notification); - + ` + document.body.appendChild(notification) + setTimeout(() => { - notification.remove(); - }, 5000); + notification.remove() + }, 5000) } /** @@ -394,20 +401,22 @@ class AutoSaveManager { * @returns {Promise} 备份文件列表 */ async getBackupFiles() { - const backupPromises = Object.entries(this.storages).map(async ([type, storage]) => { - if (typeof storage.getBackupFiles === 'function') { - try { - const result = await storage.getBackupFiles(); - return { type, ...result }; - } catch (error) { - return { type, success: false, error: error.message }; + const backupPromises = Object.entries(this.storages).map( + async ([type, storage]) => { + if (typeof storage.getBackupFiles === 'function') { + try { + const result = await storage.getBackupFiles() + return { type, ...result } + } catch (error) { + return { type, success: false, error: error.message } + } } + return { type, success: false, error: '不支持备份管理' } } - return { type, success: false, error: '不支持备份管理' }; - }); + ) - const results = await Promise.all(backupPromises); - return results; + const results = await Promise.all(backupPromises) + return results } /** @@ -415,10 +424,10 @@ class AutoSaveManager { */ async saveImmediately(currentContent) { if (this.saveTimer) { - clearTimeout(this.saveTimer); + clearTimeout(this.saveTimer) } - await this.doSave(currentContent); + await this.doSave(currentContent) } } -export default AutoSaveManager; \ No newline at end of file +export default AutoSaveManager diff --git a/src/views/lblh/components/storage/ServerStorage.js b/src/views/lblh/components/storage/ServerStorage.js index 0756bf1..9b70c5d 100644 --- a/src/views/lblh/components/storage/ServerStorage.js +++ b/src/views/lblh/components/storage/ServerStorage.js @@ -6,33 +6,35 @@ import { getToken } from '@/utils/auth' */ class ServerStorage { constructor(key, options = {}) { - this.key = key; + this.key = key this.options = { endpoint: options.endpoint || '/system/business/test/testLblh', - syncEndpoint: options.syncEndpoint || '/system/business/test/testLblhHistory', - historyEndpoint: options.historyEndpoint || '/system/business/test/testLblhHistory', + syncEndpoint: + options.syncEndpoint || '/system/business/test/testLblhHistory', + historyEndpoint: + options.historyEndpoint || '/system/business/test/testLblhHistory', retryCount: options.retryCount || 3, //最多重试次数 - retryDelay: options.retryDelay || 1000,//重试等待 毫秒 + retryDelay: options.retryDelay || 1000, //重试等待 毫秒 ...options - }; + } - this.queue = []; - this.isOnline = navigator.onLine; - this.isSyncing = false; - this.initOfflineQueue(); - this.setupNetworkListeners(); + this.queue = [] + this.isOnline = navigator.onLine + this.isSyncing = false + this.initOfflineQueue() + this.setupNetworkListeners() } /** * 初始化离线队列 */ initOfflineQueue() { - const queueStr = localStorage.getItem(`hxhq_serverQueue_${this.key}`); + const queueStr = localStorage.getItem(`hxhq_serverQueue_${this.key}`) if (queueStr) { try { - this.queue = JSON.parse(queueStr); + this.queue = JSON.parse(queueStr) } catch (error) { - this.queue = []; + this.queue = [] } } } @@ -42,20 +44,23 @@ class ServerStorage { */ setupNetworkListeners() { window.addEventListener('online', () => { - this.isOnline = true; - this.processQueue(); - }); - + this.isOnline = true + this.processQueue() + }) + window.addEventListener('offline', () => { - this.isOnline = false; - }); + this.isOnline = false + }) } /** * 保存队列到本地存储 */ saveQueue() { - localStorage.setItem(`hxhq_serverQueue_${this.key}`, JSON.stringify(this.queue)); + localStorage.setItem( + `hxhq_serverQueue_${this.key}`, + JSON.stringify(this.queue) + ) } /** @@ -63,34 +68,34 @@ class ServerStorage { */ async processQueue() { if (this.isSyncing || !this.isOnline || this.queue.length === 0) { - return; + return } - this.isSyncing = true; - + this.isSyncing = true + while (this.queue.length > 0 && this.isOnline) { - const item = this.queue[0]; + const item = this.queue[0] try { - await this.sendToServer(item.content, item.timestamp, item.version); - this.queue.shift(); // 发送成功,从队列移除 - this.saveQueue(); + await this.sendToServer(item.content, item.timestamp, item.version) + this.queue.shift() // 发送成功,从队列移除 + this.saveQueue() } catch (error) { - console.error('同步失败:', error); - item.retryCount = (item.retryCount || 0) + 1; - + console.error('同步失败:', error) + item.retryCount = (item.retryCount || 0) + 1 + if (item.retryCount >= this.options.retryCount) { - this.queue.shift(); // 超过重试次数,移除 - this.saveQueue(); + this.queue.shift() // 超过重试次数,移除 + this.saveQueue() } else { // 重试等待 - await new Promise(resolve => + await new Promise((resolve) => setTimeout(resolve, this.options.retryDelay * item.retryCount) - ); + ) } } } - - this.isSyncing = false; + + this.isSyncing = false } /** @@ -101,30 +106,32 @@ class ServerStorage { */ async sendToServer(content, timestamp, version) { return new Promise((resolve, reject) => { - const xhr = new XMLHttpRequest(); - xhr.open('POST', this.options.endpoint); - xhr.setRequestHeader('Content-Type', 'application/json'); - xhr.setRequestHeader('Authorization', 'Bearer ' + getToken()); // 让每个请求携带自定义token 请根据实际情况自行修改 - + const xhr = new XMLHttpRequest() + xhr.open('POST', this.options.endpoint) + xhr.setRequestHeader('Content-Type', 'application/json') + xhr.setRequestHeader('Authorization', 'Bearer ' + getToken()) // 让每个请求携带自定义token 请根据实际情况自行修改 + xhr.onload = () => { if (xhr.status === 200 || xhr.status === 201) { - resolve(JSON.parse(xhr.responseText)); + resolve(JSON.parse(xhr.responseText)) } else { - reject(new Error(`服务器错误: ${xhr.status}`)); + reject(new Error(`服务器错误: ${xhr.status}`)) } - }; - - xhr.onerror = () => reject(new Error('网络请求失败')); - xhr.ontimeout = () => reject(new Error('请求超时')); - - xhr.send(JSON.stringify({ - key: this.key, - content, - timestamp, - version, - syncedAt: Date.now() - })); - }); + } + + xhr.onerror = () => reject(new Error('网络请求失败')) + xhr.ontimeout = () => reject(new Error('请求超时')) + + xhr.send( + JSON.stringify({ + key: this.key, + content, + timestamp, + version, + syncedAt: Date.now() + }) + ) + }) } /** @@ -134,22 +141,22 @@ class ServerStorage { */ async save(content) { try { - const timestamp = Date.now(); - const version = await this.getNextVersion(); + const timestamp = Date.now() + const version = await this.getNextVersion() if (this.isOnline) { try { - const result = await this.sendToServer(content, timestamp, version); + const result = await this.sendToServer(content, timestamp, version) return { success: true, timestamp, version, storage: 'server', synced: true - }; + } } catch (error) { // 服务器保存失败,加入离线队列 - console.warn('服务器保存失败,加入离线队列:', error); + console.warn('服务器保存失败,加入离线队列:', error) } } @@ -159,8 +166,8 @@ class ServerStorage { timestamp, version, addedAt: Date.now() - }); - this.saveQueue(); + }) + this.saveQueue() return { success: true, @@ -169,13 +176,13 @@ class ServerStorage { storage: 'server', synced: false, queued: true - }; + } } catch (error) { return { success: false, error: error.message, storage: 'server' - }; + } } } @@ -185,40 +192,39 @@ class ServerStorage { */ async load() { try { - if (this.isOnline) { - try { - const response = await fetch(`${this.options.syncEndpoint}?key=${this.key}`); - if (response.ok) { - const data = await response.json(); - return { - success: true, - data, - storage: 'server', - fromServer: true - }; - } - } catch (error) { - console.warn('从服务器加载失败:', error); - } - } + // if (this.isOnline) { + // try { + // const response = await fetch(`${this.options.syncEndpoint}?key=${this.key}`); + // if (response.ok) { + // const data = await response.json(); + // return { + // success: true, + // data, + // storage: 'server', + // fromServer: true + // }; + // } + // } catch (error) { + // console.warn('从服务器加载失败:', error); + // } + // } // 返回队列中的最新数据 - const latestQueued = this.queue.length > 0 - ? this.queue[this.queue.length - 1] - : null; + const latestQueued = + this.queue.length > 0 ? this.queue[this.queue.length - 1] : null return { success: true, data: latestQueued, storage: 'server', fromServer: false - }; + } } catch (error) { return { success: false, error: error.message, storage: 'server' - }; + } } } @@ -233,26 +239,28 @@ class ServerStorage { success: false, error: '网络未连接', storage: 'server' - }; + } } - const response = await fetch(`${this.options.historyEndpoint}?key=${this.key}`); + const response = await fetch( + `${this.options.historyEndpoint}?key=${this.key}` + ) if (!response.ok) { - throw new Error(`服务器错误: ${response.status}`); + throw new Error(`服务器错误: ${response.status}`) } - const data = await response.json(); + const data = await response.json() return { success: true, data, storage: 'server' - }; + } } catch (error) { return { success: false, error: error.message, storage: 'server' - }; + } } } @@ -262,13 +270,13 @@ class ServerStorage { */ async getNextVersion() { try { - const result = await this.load(); + const result = await this.load() if (result.success && result.data) { - return result.data.version + 1; + return result.data.version + 1 } - return 1; + return 1 } catch (error) { - return 1; + return 1 } } @@ -282,8 +290,8 @@ class ServerStorage { isOnline: this.isOnline, isSyncing: this.isSyncing, nextRetry: this.queue.length > 0 ? this.queue[0].retryCount || 0 : 0 - }; + } } } -export default ServerStorage; \ No newline at end of file +export default ServerStorage diff --git a/src/views/lblh/index.vue b/src/views/lblh/index.vue index 88160a3..1749672 100644 --- a/src/views/lblh/index.vue +++ b/src/views/lblh/index.vue @@ -35,8 +35,8 @@

通过多层存储,确保在各种异常情况下(网络中断、浏览器崩溃、存储限制等)用户内容都能得到妥善保存。

分层存储(数据流向:用户输入 → 本地持久化 → 云端)

1.服务器存储:云端同步,跨设备访问

-

2.IndexedDB存储:浏览器内置 NoSQL 数据库,所有pc浏览器都支持,移动端浏览器也支持(存储数据可达50%的磁盘容量,并且支持事务,索引)(关闭标签页/窗口 → 数据保留;刷新页面 → 数据保留)

-

3.LocalStorage:本地存储, 持久化,跨会话保存(关闭标签页/窗口 → 数据保留;刷新页面 → 数据保留)如果IndexedDB初始化失败则启用

+ +

2.LocalStorage:本地存储, 持久化,跨会话保存(关闭标签页/窗口 → 数据保留;刷新页面 → 数据保留)

实时保存

3.输入结束,失去焦点后触发多存储并行保存

4.页面关闭前强制同步保存

@@ -75,8 +75,8 @@ export default { content8: '', dataSelect: [{ value: '迈瑞', label: '迈瑞' },{ value: '大疆', label: '大疆' }], serverConfig: { - endpoint: '/api/save-text', - syncEndpoint: '/api/sync-text', + endpoint: '/dev-api/system/business/test/testLblh', + syncEndpoint: '/dev-api/system/business/test/testLblh2', historyEndpoint: '/api/text-history', retryCount: 3, retryDelay: 1000