} 备份文件列表
*/
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