/* 文件路径: data/DataManager.js */
/**
* DataManager - 数据管理主类
* 整合所有功能模块并保持原有API不变
*/
import { DataManagerCore } from './core/dataManagerCore.js';
import { createEntityAccessors } from './utils/entityAccessors.js';
import { checkDuplicate } from './utils/dataUtils.js';
/**
* 数据管理器类
* 提供统一的数据访问、操作和同步接口
*/
export class DataManager {
constructor() {
// 初始化核心管理器
this.core = new DataManagerCore();
// 混入实体访问器方法
const accessors = createEntityAccessors(this.core);
Object.assign(this, accessors);
// 绑定方法到当前实例
this.bindMethods();
}
/**
* 绑定方法到当前实例
*/
bindMethods() {
// 绑定核心方法
const coreMethods = [
'initialize',
'createEmptyData',
'registerCallback',
'unregisterCallback',
'triggerCallbacks',
'crudOperation',
'updateLocalData',
'loadDataFromStorage',
'saveDataToStorage',
'startAutoSync',
'stopAutoSync',
'initNetwork',
'syncData',
'fetchAll',
'fetchEntityData',
'initWebSocket',
'handleWebSocketUpdate',
'refreshEntityData',
'updateWechatUser',
'transactionalOperation'
];
coreMethods.forEach(methodName => {
if (typeof this.core[methodName] === 'function') {
this[methodName] = this.core[methodName].bind(this.core);
}
});
// 绑定存储方法
const storageMethods = [
'getEntityById',
'addEntity',
'updateEntity',
'deleteEntity',
'addEntities',
'clearEntities'
];
storageMethods.forEach(methodName => {
if (typeof this.core.storage[methodName] === 'function') {
this[methodName] = this.core.storage[methodName].bind(this.core.storage);
}
});
}
/**
* 获取数据访问器
*/
get data() {
return this.core.data;
}
/**
* 从本地存储加载数据
* @returns {boolean} 加载是否成功
*/
loadDataFromStorage() {
return this.core.storage.loadDataFromStorage();
}
/**
* 保存数据到本地存储
* @returns {boolean} 保存是否成功
*/
saveDataToStorage() {
return this.core.storage.saveDataToStorage();
}
/**
* 初始化网络状态监听
*/
initNetwork() {
// 此方法已在DataSync初始化时调用
console.log('Network initialized');
}
/**
* 检查实体是否重复
* @param {string} entityType - 实体类型
* @param {Object} newEntity - 新实体
* @returns {boolean} 是否重复
*/
checkDuplicate(entityType, newEntity) {
const entities = this.core.storage.getEntities(entityType);
return checkDuplicate(entities, newEntity);
}
// ===== 以下是为了保持向后兼容的额外方法 =====
/**
* 获取特定类型的所有实体
* @param {string} entityType - 实体类型
* @returns {Array} 实体数组
*/
getAllEntities(entityType) {
return this.core.storage.getEntities(entityType);
}
/**
* 批量更新实体
* @param {string} entityType - 实体类型
* @param {Array} entities - 实体数组
* @returns {Array} 更新结果数组
*/
bulkUpdateEntities(entityType, entities) {
return entities.map(entity => this.core.storage.updateEntity(entityType, entity));
}
/**
* 批量删除实体
* @param {string} entityType - 实体类型
* @param {Array} ids - 实体ID数组
* @returns {Array} 删除结果数组
*/
bulkDeleteEntities(entityType, ids) {
return ids.map(id => this.core.storage.deleteEntity(entityType, id));
}
/**
* 清空所有数据
*/
clearAllData() {
return this.core.storage.clearAllData();
}
}
// 创建默认实例
export const dataManager = new DataManager();
================================================================================
/* 文件路径: data/core/dataManagerCore.js */
/**
* DataManager核心类
* 整合所有组件并提供统一的数据管理接口
*/
import { DataStorage } from './dataStorage.js';
import { DataSync } from './dataSync.js';
import { LazyLoader } from '../components/LazyLoader.js';
import { TransactionApi } from '../components/TransactionApi.js';
import { WebSocketClient } from '../components/WebSocketClient.js';
import { resolveDataReferences } from '../utils/dataUtils.js';
export class DataManagerCore {
constructor() {
// 初始化各个组件
this.storage = new DataStorage();
this.sync = new DataSync(this);
this.lazyLoader = new LazyLoader(this);
this.transactionApi = new TransactionApi(this);
this.webSocketClient = new WebSocketClient(this);
// 初始化回调管理
this.callbacks = {};
// 初始化数据
this.initialize();
}
/**
* 初始化数据管理器
*/
initialize() {
// 从本地存储加载数据
this.storage.loadDataFromStorage();
// 初始化WebSocket连接
this.initWebSocket();
}
/**
* 创建空数据对象
* @returns {Object} 空数据对象
*/
createEmptyData() {
return {
dingdans: [],
chanpins: [],
zujians: [],
bancais: [],
cailiaos: [],
xiaoshous: [],
shengchans: [],
xiaohaos: [],
wechatUsers: []
};
}
/**
* 获取数据访问器
*/
get data() {
return this.storage.data;
}
// ===== 回调管理 =====
/**
* 注册回调函数
* @param {string} eventType - 事件类型
* @param {Function} callback - 回调函数
* @returns {Function} 取消注册的函数
*/
registerCallback(eventType, callback) {
if (!this.callbacks[eventType]) {
this.callbacks[eventType] = [];
}
this.callbacks[eventType].push(callback);
// 返回取消注册的函数
return () => this.unregisterCallback(eventType, callback);
}
/**
* 取消注册回调函数
* @param {string} eventType - 事件类型
* @param {Function} callback - 回调函数
*/
unregisterCallback(eventType, callback) {
if (!this.callbacks[eventType]) {
return;
}
this.callbacks[eventType] = this.callbacks[eventType].filter(cb => cb !== callback);
}
/**
* 触发回调函数
* @param {string} eventType - 事件类型
* @param {*} data - 回调数据
*/
triggerCallbacks(eventType, data) {
if (!this.callbacks[eventType]) {
return;
}
this.callbacks[eventType].forEach(callback => {
try {
callback(data);
} catch (error) {
console.error(`Error in callback for ${eventType}:`, error);
}
});
}
// ===== WebSocket相关 =====
/**
* 初始化WebSocket连接
*/
initWebSocket() {
this.webSocketClient.connect();
}
/**
* 处理WebSocket更新
* @param {Object} updateData - 更新数据
*/
handleWebSocketUpdate(updateData) {
if (!updateData || !updateData.type) {
return;
}
switch (updateData.type) {
case 'entity_update':
this.handleEntityUpdate(updateData);
break;
case 'entity_delete':
this.handleEntityDelete(updateData);
break;
case 'sync_complete':
this.triggerCallbacks('syncComplete', updateData);
break;
default:
this.triggerCallbacks('ws_update', updateData);
break;
}
}
/**
* 处理实体更新
* @param {Object} updateData - 更新数据
*/
handleEntityUpdate(updateData) {
const { entityType, entity } = updateData;
if (entityType && entity) {
this.updateEntity(entityType, entity);
this.triggerCallbacks(`${entityType}_updated`, entity);
}
}
/**
* 处理实体删除
* @param {Object} updateData - 更新数据
*/
handleEntityDelete(updateData) {
const { entityType, entityId } = updateData;
if (entityType && entityId) {
this.deleteEntity(entityType, entityId);
this.triggerCallbacks(`${entityType}_deleted`, { id: entityId });
}
}
// ===== 实体操作方法 =====
/**
* 执行CRUD操作
* @param {string} operation - 操作类型
* @param {string} entityType - 实体类型
* @param {Object|Array} data - 操作数据
* @returns {Promise} 操作结果Promise
*/
async crudOperation(operation, entityType, data) {
try {
let result;
switch (operation.toLowerCase()) {
case 'create':
case 'add':
result = Array.isArray(data)
? this.storage.addEntities(entityType, data)
: this.storage.addEntity(entityType, data);
break;
case 'read':
case 'get':
result = data
? this.storage.getEntityById(entityType, data)
: this.storage.getEntities(entityType);
break;
case 'update':
result = Array.isArray(data)
? data.map(item => this.storage.updateEntity(entityType, item))
: this.storage.updateEntity(entityType, data);
break;
case 'delete':
case 'remove':
result = Array.isArray(data)
? data.map(id => this.storage.deleteEntity(entityType, id))
: this.storage.deleteEntity(entityType, data);
break;
default:
throw new Error(`Unknown operation: ${operation}`);
}
// 保存到本地存储
this.storage.saveDataToStorage();
// 触发回调
this.triggerCallbacks(`${entityType}_${operation}d`, result);
return result;
} catch (error) {
console.error(`Error performing ${operation} on ${entityType}:`, error);
throw error;
}
}
/**
* 更新本地数据
* @param {Object} newData - 新数据
*/
updateLocalData(newData) {
for (const entityType in newData) {
if (Object.prototype.hasOwnProperty.call(newData, entityType)) {
const entities = newData[entityType];
if (Array.isArray(entities)) {
this.storage.addEntities(entityType, entities);
}
}
}
// 保存到本地存储
this.storage.saveDataToStorage();
}
/**
* 刷新实体数据
* @param {string} entityType - 实体类型
* @returns {Promise} 刷新结果Promise
*/
async refreshEntityData(entityType) {
const data = await this.sync.fetchEntityData(entityType);
this.triggerCallbacks(`${entityType}_refreshed`, data);
return data;
}
/**
* 执行事务操作
* @param {Function} operation - 操作函数
* @returns {Promise} 操作结果Promise
*/
transactionalOperation(operation) {
return this.transactionApi.executeTransaction(operation);
}
/**
* 更新微信用户信息
* @param {Object} userInfo - 用户信息
* @returns {Promise} 更新结果Promise
*/
async updateWechatUser(userInfo) {
return this.crudOperation('update', 'wechatUsers', userInfo);
}
}
================================================================================
/* 文件路径: data/core/dataStorage.js */
/**
* 数据存储核心类
* 提供数据的基本CRUD操作和本地存储功能
*/
import { removeCircularReferences } from '../utils/dataUtils.js';
const STORAGE_KEY = 'inventory_data';
export class DataStorage {
constructor() {
this.data = {
dingdans: [],
chanpins: [],
zujians: [],
bancais: [],
cailiaos: [],
xiaoshous: [],
shengchans: [],
xiaohaos: [],
wechatUsers: []
};
this.entityTypes = Object.keys(this.data);
}
/**
* 获取特定类型的所有实体
* @param {string} entityType - 实体类型
* @returns {Array} 实体数组
*/
getEntities(entityType) {
if (!this.entityTypes.includes(entityType)) {
console.warn(`Unknown entity type: ${entityType}`);
return [];
}
return this.data[entityType] || [];
}
/**
* 根据ID获取特定实体
* @param {string} entityType - 实体类型
* @param {string|number} id - 实体ID
* @returns {Object|null} 实体对象或null
*/
getEntityById(entityType, id) {
const entities = this.getEntities(entityType);
return entities.find(entity => entity.id === id) || null;
}
/**
* 添加实体
* @param {string} entityType - 实体类型
* @param {Object} entity - 实体对象
* @returns {Object} 添加后的实体对象
*/
addEntity(entityType, entity) {
if (!this.entityTypes.includes(entityType)) {
console.warn(`Cannot add to unknown entity type: ${entityType}`);
return entity;
}
if (!this.data[entityType]) {
this.data[entityType] = [];
}
// 检查是否已存在相同ID的实体
const existingIndex = this.data[entityType].findIndex(e => e.id === entity.id);
if (existingIndex >= 0) {
// 如果已存在,更新它
this.data[entityType][existingIndex] = entity;
} else {
// 否则添加新实体
this.data[entityType].push(entity);
}
return entity;
}
/**
* 更新实体
* @param {string} entityType - 实体类型
* @param {Object} entity - 实体对象
* @returns {boolean} 更新是否成功
*/
updateEntity(entityType, entity) {
if (!this.entityTypes.includes(entityType)) {
console.warn(`Cannot update unknown entity type: ${entityType}`);
return false;
}
if (!entity.id) {
console.warn('Cannot update entity without ID');
return false;
}
const entities = this.data[entityType];
const index = entities.findIndex(e => e.id === entity.id);
if (index === -1) {
console.warn(`Entity not found: ${entityType} with ID ${entity.id}`);
return false;
}
entities[index] = entity;
return true;
}
/**
* 删除实体
* @param {string} entityType - 实体类型
* @param {string|number} id - 实体ID
* @returns {boolean} 删除是否成功
*/
deleteEntity(entityType, id) {
if (!this.entityTypes.includes(entityType)) {
console.warn(`Cannot delete from unknown entity type: ${entityType}`);
return false;
}
const entities = this.data[entityType];
const index = entities.findIndex(e => e.id === id);
if (index === -1) {
console.warn(`Entity not found: ${entityType} with ID ${id}`);
return false;
}
entities.splice(index, 1);
return true;
}
/**
* 批量添加实体
* @param {string} entityType - 实体类型
* @param {Array} entities - 实体数组
* @returns {Array} 添加后的实体数组
*/
addEntities(entityType, entities) {
if (!Array.isArray(entities)) {
console.warn('Entities must be an array');
return [];
}
return entities.map(entity => this.addEntity(entityType, entity));
}
/**
* 清空特定类型的所有实体
* @param {string} entityType - 实体类型
*/
clearEntities(entityType) {
if (!this.entityTypes.includes(entityType)) {
console.warn(`Cannot clear unknown entity type: ${entityType}`);
return;
}
this.data[entityType] = [];
}
/**
* 从本地存储加载数据
* @returns {boolean} 加载是否成功
*/
loadDataFromStorage() {
try {
const storedData = localStorage.getItem(STORAGE_KEY);
if (storedData) {
const parsedData = JSON.parse(storedData);
// 合并存储的数据到当前数据对象
for (const entityType in parsedData) {
if (Object.prototype.hasOwnProperty.call(parsedData, entityType) &&
this.entityTypes.includes(entityType)) {
this.data[entityType] = parsedData[entityType];
}
}
return true;
}
} catch (error) {
console.error('Failed to load data from storage:', error);
}
return false;
}
/**
* 保存数据到本地存储
* @returns {boolean} 保存是否成功
*/
saveDataToStorage() {
try {
// 移除循环引用
const dataToSave = removeCircularReferences(this.data);
localStorage.setItem(STORAGE_KEY, JSON.stringify(dataToSave));
return true;
} catch (error) {
console.error('Failed to save data to storage:', error);
}
return false;
}
/**
* 清空所有数据
*/
clearAllData() {
for (const entityType of this.entityTypes) {
this.data[entityType] = [];
}
localStorage.removeItem(STORAGE_KEY);
}
}
================================================================================
/* 文件路径: data/core/dataSync.js */
/**
* 数据同步核心类
* 负责处理数据与服务器的同步、自动同步和网络状态监听
*/
export class DataSync {
constructor(dataManager, autoSyncInterval = 30000) {
this.dataManager = dataManager;
this.autoSyncInterval = autoSyncInterval; // 默认30秒
this.syncTimer = null;
this.isAutoSyncEnabled = false;
this.isOnline = true;
this.pendingOperations = [];
// 初始化网络状态监听
this.initNetworkStatus();
}
/**
* 初始化网络状态监听
*/
initNetworkStatus() {
// 监听在线状态变化
window.addEventListener('online', () => this.handleNetworkChange(true));
window.addEventListener('offline', () => this.handleNetworkChange(false));
// 初始状态
this.isOnline = window.navigator.onLine;
}
/**
* 处理网络状态变化
* @param {boolean} isOnline - 是否在线
*/
handleNetworkChange(isOnline) {
this.isOnline = isOnline;
if (isOnline) {
console.log('Network connection restored, syncing pending operations...');
// 当网络恢复时,同步待处理的操作
this.syncPendingOperations();
} else {
console.log('Network connection lost');
}
// 触发回调通知网络状态变化
this.dataManager.triggerCallbacks('networkStatusChange', { isOnline });
}
/**
* 同步待处理的操作
*/
async syncPendingOperations() {
while (this.pendingOperations.length > 0) {
const operation = this.pendingOperations.shift();
try {
await operation();
} catch (error) {
console.error('Failed to sync pending operation:', error);
// 如果同步失败,将操作重新添加到队列末尾
this.pendingOperations.push(operation);
break;
}
}
}
/**
* 开始自动同步
*/
startAutoSync() {
if (this.isAutoSyncEnabled) {
return;
}
this.isAutoSyncEnabled = true;
this.syncTimer = setInterval(() => {
if (this.isOnline) {
this.syncData();
}
}, this.autoSyncInterval);
console.log('Auto-sync started with interval:', this.autoSyncInterval);
}
/**
* 停止自动同步
*/
stopAutoSync() {
if (this.syncTimer) {
clearInterval(this.syncTimer);
this.syncTimer = null;
}
this.isAutoSyncEnabled = false;
console.log('Auto-sync stopped');
}
/**
* 同步数据到服务器
* @returns {Promise} 同步结果Promise
*/
async syncData() {
if (!this.isOnline) {
console.warn('Cannot sync data while offline');
return false;
}
try {
// 收集所有需要同步的数据
const syncData = this.collectSyncData();
if (Object.keys(syncData).length === 0) {
console.log('No data to sync');
return true;
}
const response = await fetch('/api/sync', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(syncData)
});
if (!response.ok) {
throw new Error(`Sync failed with status: ${response.status}`);
}
const result = await response.json();
// 处理同步结果
this.handleSyncResult(result);
console.log('Data synced successfully');
return true;
} catch (error) {
console.error('Error syncing data:', error);
// 如果同步失败,将操作添加到待处理队列
this.pendingOperations.push(() => this.syncData());
return false;
}
}
/**
* 收集需要同步的数据
* @returns {Object} 同步数据对象
*/
collectSyncData() {
const syncData = {};
// 在实际应用中,这里应该只收集需要同步的变更数据
// 为简化实现,我们收集所有数据
for (const entityType of this.dataManager.storage.entityTypes) {
const entities = this.dataManager.storage.getEntities(entityType);
if (entities.length > 0) {
syncData[entityType] = entities;
}
}
return syncData;
}
/**
* 处理同步结果
* @param {Object} result - 同步结果
*/
handleSyncResult(result) {
// 在实际应用中,这里应该根据服务器返回的结果更新本地数据
// 例如,处理冲突、应用服务器端的变更等
if (result.success && result.updatedEntities) {
// 应用服务器端的更新
for (const entityType in result.updatedEntities) {
const updatedEntities = result.updatedEntities[entityType];
updatedEntities.forEach(entity => {
this.dataManager.storage.updateEntity(entityType, entity);
});
}
}
}
/**
* 从服务器获取数据
* @param {Array} entityTypes - 要获取的实体类型数组
* @returns {Promise} 获取结果Promise
*/
async fetchData(entityTypes) {
if (!this.isOnline) {
console.warn('Cannot fetch data while offline');
return false;
}
try {
const response = await fetch('/api/data', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ entityTypes })
});
if (!response.ok) {
throw new Error(`Fetch data failed with status: ${response.status}`);
}
const data = await response.json();
// 处理获取的数据
this.handleFetchedData(data);
return true;
} catch (error) {
console.error('Error fetching data:', error);
return false;
}
}
/**
* 处理获取的数据
* @param {Object} data - 获取的数据
*/
handleFetchedData(data) {
// 将获取的数据保存到存储中
for (const entityType in data) {
if (Object.prototype.hasOwnProperty.call(data, entityType)) {
const entities = data[entityType];
if (Array.isArray(entities)) {
this.dataManager.storage.clearEntities(entityType);
this.dataManager.storage.addEntities(entityType, entities);
}
}
}
}
/**
* 获取所有实体数据
* @returns {Promise} 获取结果Promise
*/
fetchAll() {
return this.fetchData(this.dataManager.storage.entityTypes);
}
/**
* 获取特定实体类型的数据
* @param {string} entityType - 实体类型
* @param {Object} filters - 过滤条件
* @returns {Promise} 获取结果Promise
*/
async fetchEntityData(entityType, filters = {}) {
if (!this.isOnline) {
console.warn('Cannot fetch entity data while offline');
return [];
}
try {
const response = await fetch(`/api/data/${entityType}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(filters)
});
if (!response.ok) {
throw new Error(`Fetch ${entityType} data failed with status: ${response.status}`);
}
const data = await response.json();
// 将获取的数据保存到存储中
if (Array.isArray(data)) {
this.dataManager.storage.clearEntities(entityType);
this.dataManager.storage.addEntities(entityType, data);
return data;
}
return [];
} catch (error) {
console.error(`Error fetching ${entityType} data:`, error);
return [];
}
}
}
================================================================================
/* 文件路径: data/utils/dataUtils.js */
/**
* 数据工具函数
* 提供数据引用解析、循环引用处理等功能
*/
/**
* 解析数据对象中的所有引用
* @param {Object} data - 要解析的数据对象
* @param {Object} entitiesMap - 实体映射表
* @returns {Object} 解析后的对象
*/
export function resolveDataReferences(data, entitiesMap) {
if (!data || typeof data !== 'object') {
return data;
}
if (Array.isArray(data)) {
return data.map(item => resolveDataReferences(item, entitiesMap));
}
const result = {};
for (const key in data) {
if (Object.prototype.hasOwnProperty.call(data, key)) {
result[key] = resolveDataReference(data[key], entitiesMap);
}
}
return result;
}
/**
* 解析单个数据引用
* @param {*} value - 要解析的值
* @param {Object} entitiesMap - 实体映射表
* @returns {*} 解析后的值
*/
export function resolveDataReference(value, entitiesMap) {
if (!value || typeof value !== 'object') {
return value;
}
if (Array.isArray(value)) {
return value.map(item => resolveDataReference(item, entitiesMap));
}
// 检查是否是引用对象
if (value.__ref && value.entityType && entitiesMap[value.entityType]) {
const entity = entitiesMap[value.entityType].find(e => e.id === value.__ref);
return entity || value;
}
// 递归处理嵌套对象
const result = {};
for (const key in value) {
if (Object.prototype.hasOwnProperty.call(value, key)) {
result[key] = resolveDataReference(value[key], entitiesMap);
}
}
return result;
}
/**
* 移除对象中的循环引用
* @param {Object} obj - 要处理的对象
* @returns {Object} 处理后的对象
*/
export function removeCircularReferences(obj) {
const seen = new WeakSet();
const replacer = (key, value) => {
if (typeof value === 'object' && value !== null) {
if (seen.has(value)) {
return undefined;
}
seen.add(value);
}
return value;
};
return JSON.parse(JSON.stringify(obj, replacer));
}
/**
* 检查实体是否重复
* @param {Array} entities - 实体数组
* @param {Object} newEntity - 新实体
* @returns {boolean} 是否重复
*/
export function checkDuplicate(entities, newEntity) {
if (!entities || !Array.isArray(entities)) {
return false;
}
return entities.some(entity => entity.id === newEntity.id);
}
================================================================================
/* 文件路径: data/utils/entityAccessors.js */
/**
* 实体访问器函数
* 提供各种实体数据的访问方法
*/
import { resolveDataReferences } from './dataUtils.js';
/**
* 创建实体访问器方法
* @param {DataManagerCore} dataManager - 数据管理器实例
* @returns {Object} 访问器方法对象
*/
export function createEntityAccessors(dataManager) {
const accessors = {};
// 创建实体访问方法
const entityTypes = [
'dingdans',
'chanpins',
'zujians',
'bancais',
'cailiaos',
'xiaoshous',
'shengchans',
'xiaohaos',
'wechatUsers'
];
// 创建同步访问方法
entityTypes.forEach(entityType => {
const methodName = `get${capitalize(entityType)}`;
accessors[methodName] = function() {
const entities = dataManager.storage.getEntities(entityType);
return dataManager.lazyLoader.proxyEntities(entities, entityType);
};
});
// 创建异步访问方法
entityTypes.forEach(entityType => {
const methodName = `get${capitalize(entityType)}Async`;
accessors[methodName] = async function(filters = {}) {
// 先尝试从缓存获取
let entities = dataManager.storage.getEntities(entityType);
// 如果没有数据或强制刷新,则从服务器获取
if (entities.length === 0 || filters.forceRefresh) {
entities = await dataManager.sync.fetchEntityData(entityType, filters);
}
// 应用过滤器
if (filters) {
entities = applyFilters(entities, filters);
}
return dataManager.lazyLoader.proxyEntities(entities, entityType);
};
});
// 创建关联数据查询方法
accessors.getChanpinsForDingdan = function(dingdanId) {
const chanpins = dataManager.storage.getEntities('chanpins');
return chanpins.filter(chanpin => chanpin.dingdanId === dingdanId);
};
accessors.getZujiansForChanpin = function(chanpinId) {
const zujians = dataManager.storage.getEntities('zujians');
return zujians.filter(zujian => zujian.chanpinId === chanpinId);
};
accessors.getShengchanXiaohaoRecords = function(params = {}) {
const { startDate, endDate, chanpinId } = params;
const shengchans = dataManager.storage.getEntities('shengchans');
const xiaohaos = dataManager.storage.getEntities('xiaohaos');
// 合并生产和消耗记录
let records = [...shengchans, ...xiaohaos];
// 应用日期过滤
if (startDate) {
records = records.filter(record => new Date(record.date) >= new Date(startDate));
}
if (endDate) {
records = records.filter(record => new Date(record.date) <= new Date(endDate));
}
// 应用产品过滤
if (chanpinId) {
records = records.filter(record => record.chanpinId === chanpinId);
}
// 按日期排序
records.sort((a, b) => new Date(a.date) - new Date(b.date));
return records;
};
accessors.getShengchanStatistics = function(params = {}) {
const { startDate, endDate } = params;
const shengchans = dataManager.storage.getEntities('shengchans');
// 应用日期过滤
let filteredShengchans = shengchans;
if (startDate) {
filteredShengchans = filteredShengchans.filter(record => new Date(record.date) >= new Date(startDate));
}
if (endDate) {
filteredShengchans = filteredShengchans.filter(record => new Date(record.date) <= new Date(endDate));
}
// 计算统计数据
const statistics = {};
filteredShengchans.forEach(record => {
if (!statistics[record.chanpinId]) {
statistics[record.chanpinId] = {
chanpinId: record.chanpinId,
totalQuantity: 0,
records: []
};
}
statistics[record.chanpinId].totalQuantity += record.quantity;
statistics[record.chanpinId].records.push(record);
});
// 转换为数组并添加产品名称
const chanpinsMap = createEntityMap(dataManager.storage.getEntities('chanpins'));
return Object.values(statistics).map(stat => {
const chanpin = chanpinsMap[stat.chanpinId];
return {
...stat,
chanpinName: chanpin ? chanpin.name : 'Unknown'
};
});
};
return accessors;
}
/**
* 首字母大写
* @param {string} str - 字符串
* @returns {string} 首字母大写的字符串
*/
function capitalize(str) {
return str.charAt(0).toUpperCase() + str.slice(1);
}
/**
* 应用过滤器
* @param {Array} entities - 实体数组
* @param {Object} filters - 过滤条件
* @returns {Array} 过滤后的实体数组
*/
function applyFilters(entities, filters) {
return entities.filter(entity => {
for (const key in filters) {
if (key !== 'forceRefresh' && filters[key] !== undefined) {
if (entity[key] !== filters[key]) {
return false;
}
}
}
return true;
});
}
/**
* 创建实体映射
* @param {Array} entities - 实体数组
* @returns {Object} 实体ID到实体的映射
*/
function createEntityMap(entities) {
const map = {};
entities.forEach(entity => {
map[entity.id] = entity;
});
return map;
}
================================================================================
/* 文件路径: data/index.js */
/**
* 数据管理模块入口
* 导出所有公共API,保持向后兼容
*/
import { DataManager, dataManager } from './DataManager.js';
import { DataStorage } from './core/dataStorage.js';
import { DataSync } from './core/dataSync.js';
import { LazyLoader } from './components/LazyLoader.js';
import { TransactionApi } from './components/TransactionApi.js';
import { WebSocketClient } from './components/WebSocketClient.js';
import { resolveDataReferences, resolveDataReference, removeCircularReferences, checkDuplicate } from './utils/dataUtils.js';
// 导出所有公共API
export {
DataManager,
dataManager,
DataStorage,
DataSync,
LazyLoader,
TransactionApi,
WebSocketClient,
resolveDataReferences,
resolveDataReference,
removeCircularReferences,
checkDuplicate
};
// 导出默认模块
export default dataManager;
================================================================================
/* 文件路径: data/LazyLoader.js */
/**
* 懒加载器 - Web版 (优化版)
* 修复了缓存键设计、集合名解析和数组处理问题
* 负责为数据对象创建代理,实现关联数据的延迟加载
* 支持按需加载机制
*/
class LazyLoader {
/**
* 构造函数
* @param {DataManager} dataManager - 数据管理器实例
*/
constructor(dataManager) {
this.dataManager = dataManager; // 数据管理器引用
// 使用WeakMap避免内存泄漏
this.proxyCache = new WeakMap(); // 代理对象缓存,避免重复创建代理
// 实体名到集合名的映射表
this.entityToCollectionMap = {
bancai: 'bancais',
dingdan: 'dingdans',
mupi: 'mupis',
chanpin: 'chanpins',
kucun: 'kucuns',
chanpin_zujian: 'chanpin_zujians',
dingdan_bancai: 'dingdan_bancais',
zujian: 'zujians',
caizhi: 'caizhis',
dingdan_chanpin: 'dingdan_chanpins',
user: 'users',
jinhuo: 'jinhuos'
};
// 集合名到实体名的映射表(反向映射)
this.collectionToEntityMap = {};
for (const [entity, collection] of Object.entries(this.entityToCollectionMap)) {
this.collectionToEntityMap[collection] = entity;
}
}
/**
* 清除所有缓存
* 用于数据刷新后重置所有缓存状态
*/
clearCache() {
this.proxyCache = new WeakMap(); // 重新创建WeakMap以清空缓存
}
/**
* 创建数据代理
* 为对象添加延迟加载关联数据的能力
* @param {Object} item - 原始数据项
* @param {string} entityType - 实体类型
* @returns {Proxy} 具有延迟加载能力的代理对象
*/
createProxy(item, entityType) {
// 非对象直接返回
if (!item || typeof item !== 'object') return item;
// 检查是否已有代理
if (this.proxyCache.has(item)) {
return this.proxyCache.get(item);
}
const proxy = new Proxy(item, {
get: (target, prop) => {
// 直接返回基本属性、符号属性或以下划线开头的属性
if (typeof prop === 'symbol' ||
prop.startsWith('_') ||
typeof target[prop] !== 'object') {
return target[prop];
}
const value = target[prop];
// 处理null值
if (value === null) return null;
// 处理数组关联 - 对数组中的每个元素进行关系解析
if (Array.isArray(value)) {
return value.map(relatedItem =>
this.resolveRelation(relatedItem, prop)
);
}
// 处理对象关联 - 对单个对象进行关系解析
else if (typeof value === 'object') {
return this.resolveRelation(value, prop);
}
return value;
},
set: (target, prop, value) => {
// 允许设置属性值
target[prop] = value;
return true;
}
});
// 缓存代理对象,避免重复创建
this.proxyCache.set(item, proxy);
return proxy;
}
/**
* 解析关联对象
* 根据属性名和关联项获取完整的关联对象
* 支持按需加载关联数据
* @param {Object|string|number} relatedItem - 关联项
* @param {string} propName - 属性名
* @returns {Object} 解析后的关联对象
*/
resolveRelation(relatedItem, propName) {
// 如果关联项是简单的ID值
if (typeof relatedItem === 'string' || typeof relatedItem === 'number') {
// 从属性名推断关联的实体类型
const entityType = this.getEntityTypeFromPropName(propName);
if (!entityType) return relatedItem;
// 查找对应的实体
const collectionName = this.entityToCollectionMap[entityType.replace(/s$/, '')] || entityType;
const collection = this.dataManager._rawData[collectionName];
// 如果集合不存在或为空,但存在关联ID,则返回原始ID(按需加载时可能发生)
if (!collection || !Array.isArray(collection) || collection.length === 0) {
return relatedItem;
}
// 查找匹配的实体
const matchedEntity = collection.find(item => item.id === relatedItem);
return matchedEntity ? this.createProxy(matchedEntity, entityType.replace(/s$/, '')) : relatedItem;
}
// 如果关联项是对象,创建代理
if (typeof relatedItem === 'object' && relatedItem !== null) {
// 从属性名推断实体类型
const entityType = this.getEntityTypeFromPropName(propName);
if (entityType) {
return this.createProxy(relatedItem, entityType.replace(/s$/, ''));
}
return this.createProxy(relatedItem, null);
}
return relatedItem;
}
/**
* 从集合名获取实体类型
* @param {string} collectionName - 集合名称
* @returns {string|null} 实体类型名称
*/
getEntityTypeFromCollection(collectionName) {
return this.collectionToEntityMap[collectionName] || null;
}
/**
* 从属性名获取实体类型
* @param {string} propName - 属性名称
* @returns {string|null} 实体类型名称
*/
getEntityTypeFromPropName(propName) {
// 处理常见的关联属性命名模式
if (propName.endsWith('Id') || propName.endsWith('_id')) {
// 例如: userId -> user, dingdan_id -> dingdan
const baseName = propName.replace(/Id$/, '').replace(/_id$/, '');
return this.entityToCollectionMap[baseName.toLowerCase()] || null;
}
// 直接查找属性名对应的实体类型
const entityType = this.collectionToEntityMap[propName];
if (entityType) {
return this.entityToCollectionMap[entityType];
}
// 尝试单复数转换
if (propName.endsWith('s')) {
const singular = propName.slice(0, -1);
return this.entityToCollectionMap[singular] || null;
}
return null;
}
}
export { LazyLoader };
================================================================================
/* 文件路径: data/components/LazyLoader.js */
/**
* 延迟加载器组件
* 为数据对象创建代理,实现关联数据的延迟加载
*/
export class LazyLoader {
constructor(dataManager) {
this.dataManager = dataManager;
}
/**
* 为对象创建延迟加载代理
* @param {Object} obj - 要代理的对象
* @param {string} entityType - 实体类型
* @returns {Proxy} 代理对象
*/
createProxy(obj, entityType) {
const self = this;
return new Proxy(obj, {
get(target, property) {
// 正常属性访问
if (property in target) {
return target[property];
}
// 处理延迟加载属性
if (property.startsWith('get') && property.endsWith('Async')) {
const methodName = property;
return function() {
return self.dataManager[methodName].apply(self.dataManager, arguments);
};
}
// 尝试加载关联数据
return self.loadRelatedData(target, property, entityType);
},
set(target, property, value) {
target[property] = value;
return true;
}
});
}
/**
* 加载关联数据
* @param {Object} entity - 实体对象
* @param {string} relationName - 关联名称
* @param {string} entityType - 实体类型
* @returns {Promise|undefined} 关联数据或undefined
*/
loadRelatedData(entity, relationName, entityType) {
// 检查是否有对应的关联数据加载方法
const relationMethodMap = {
'chanpins': 'getChanpinsForDingdan',
'zujians': 'getZujiansForChanpin',
'dingdan': 'getDingdanForChanpin',
'bancai': 'getBancaiForZuJian'
// 可以添加更多的关联映射
};
const methodName = relationMethodMap[relationName];
if (methodName && this.dataManager[methodName]) {
// 返回一个Promise,用于异步加载数据
return this.dataManager[methodName](entity.id);
}
return undefined;
}
/**
* 批量为实体数组创建代理
* @param {Array} entities - 实体数组
* @param {string} entityType - 实体类型
* @returns {Array} 代理对象数组
*/
proxyEntities(entities, entityType) {
if (!Array.isArray(entities)) {
return entities;
}
return entities.map(entity => this.createProxy(entity, entityType));
}
}
================================================================================
/* 文件路径: data/TransactionApi.js */
// @ts-nocheck
/**
* 事务API类
* 提供复合数据操作的事务支持
* 处理需要原子性执行的多个相关操作
* 支持按需加载机制
*/
class TransactionApi {
/**
* 构造函数
* @param {DataManager} dataManager - 数据管理器实例
*/
constructor(dataManager) {
this.dataManager = dataManager; // 数据管理器引用,用于访问数据和基本操作
this.baseUrl = dataManager.baseUrl;
}
/**
* 执行事务操作
* 根据端点名称调用对应的事务接口
* @param {string} endpoint - 事务端点名称
* @param {Object} data - 事务数据
* @returns {Promise<Object>} 事务执行结果
*/
async execute(endpoint, data) {
try {
// 调用API执行事务
const response = await fetch(`${this.baseUrl}/app/transactional/${endpoint}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
// 检查响应状态
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
// 解析响应结果
const result = await response.json();
if (result.status !== 200) {
throw new Error(result.text || 'Transaction failed');
}
// 事务成功后,根据端点类型决定是否需要刷新特定实体数据
// 不再同步所有数据,而是只刷新受影响的数据
await this.refreshRelatedData(endpoint, result.data);
// 触发事务成功回调
this.dataManager.triggerCallbacks('transaction_success', endpoint, result.data);
return result.data;
} catch (error) {
console.error(`Transaction ${endpoint} failed:`, error);
// 触发事务失败回调
this.dataManager.triggerCallbacks('transaction_error', endpoint, {
data,
error: error.message
});
throw error;
}
}
/**
* 根据事务端点和结果刷新相关数据
* 按需刷新,而不是刷新所有数据
* @param {string} endpoint - 事务端点名称
* @param {Object} resultData - 事务结果数据
* @returns {Promise<void>}
*/
async refreshRelatedData(endpoint, resultData) {
try {
// 根据端点名称确定需要刷新的实体类型
const entitiesToRefresh = this.getEntitiesToRefresh(endpoint);
// 刷新受影响的实体数据
for (const entityType of entitiesToRefresh) {
// 标记实体类型为未加载,下次访问时会重新获取
if (this.dataManager.loadedEntities) {
this.dataManager.loadedEntities.delete(entityType);
}
}
// 清除懒加载缓存
if (this.dataManager.lazyLoader) {
this.dataManager.lazyLoader.clearCache();
}
} catch (error) {
console.error('Failed to refresh related data:', error);
// 失败时不抛出异常,避免影响事务整体结果
}
}
/**
* 根据事务端点确定需要刷新的实体类型
* @param {string} endpoint - 事务端点名称
* @returns {Array<string>} 需要刷新的实体类型列表
*/
getEntitiesToRefresh(endpoint) {
// 定义事务端点与影响实体类型的映射关系
const endpointToEntitiesMap = {
'kucunbianji': ['kucun', 'jinhuo'], // 库存编辑影响库存和进货记录
'shengchanXiaohao': ['kucun', 'jinhuo', 'dingdan_bancai'], // 生产消耗影响库存、进货记录和订单板材
'batchUpdateDingdan_bancai': ['dingdan_bancai'], // 批量更新订单板材
'submitDingdan_bancai': ['dingdan_bancai', 'kucun'], // 提交订单板材影响订单板材和库存
'consumeDingdan_bancai': ['dingdan_bancai', 'kucun', 'jinhuo'], // 消耗订单板材影响订单板材、库存和进货记录
'采购Dingdan_bancai': ['dingdan_bancai', 'kucun', 'jinhuo'] // 采购订单板材影响订单板材、库存和进货记录
};
// 返回与端点相关的实体类型列表,如果没有匹配项则返回空数组
return endpointToEntitiesMap[endpoint] || [];
}
/**
* 库存编辑事务
* 更新指定材料的库存数量
* @param {Object} params - 事务参数
* @param {Number} params.kucunId - 库存ID
* @param {Number} params.newStock - 新的库存数量
* @param {Number} params.oldStock - 原库存数量
* @param {String} params.note - 备注信息
* @param {Number} params.userId - 用户ID
* @returns {Promise<Object>} 操作结果
*/
async updateStock(params) {
return this.execute('kucunbianji', params);
}
/**
* 生产消耗事务
* 记录生产过程中消耗的材料
* @param {Object} params - 生产消耗参数
* @returns {Promise<Object>} 操作结果
*/
async shengchanXiaohao(params) {
return this.execute('shengchanXiaohao', params);
}
/**
* 批量更新订单板材事务
* 同时更新多个订单中的板材信息
* @param {Object} params - 批量更新参数
* @returns {Promise<Object>} 操作结果
*/
async batchUpdateDingdan_bancai(params) {
return this.execute('batchUpdateDingdan_bancai', params);
}
/**
* 提交订单板材采购事务
* 将订单板材提交到采购流程
* @param {Object} params - 提交参数
* @returns {Promise<Object>} 操作结果
*/
async submitDingdan_bancai(params) {
return this.execute('submitDingdan_bancai', params);
}
/**
* 消耗订单板材事务
* 标记订单中的板材已被消耗
* @param {Object} params - 消耗参数
* @returns {Promise<Object>} 操作结果
*/
async consumeDingdan_bancai(params) {
return this.execute('consumeDingdan_bancai', params);
}
/**
* 采购订单板材事务
* 执行订单板材的采购操作
* @param {Object} params - 采购参数
* @returns {Promise<Object>} 操作结果
*/
async 采购Dingdan_bancai(params) {
return this.execute('采购Dingdan_bancai', params);
}
/**
* 保存所有数据事务
* 批量保存多种类型的数据到服务器
* @param {Object} params - 包含所有需要保存数据的对象
* @returns {Promise<Object>} 事务执行结果
*/
async saveAll(params) {
try {
// 调用API执行批量保存
const response = await fetch(`${this.baseUrl}/app/save-all`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(params)
});
// 检查响应状态
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
// 解析响应结果
const result = await response.json();
if (result.status !== 200) {
throw new Error(result.text || 'Save all failed');
}
// 保存成功后刷新数据
await this.dataManager.syncData();
return result.data;
} catch (error) {
console.error('Save all failed:', error);
throw error;
}
}
}
export { TransactionApi };
================================================================================
/* 文件路径: data/components/TransactionApi.js */
/**
* 事务API组件
* 提供复合数据操作的事务支持
*/
export class TransactionApi {
constructor(dataManager) {
this.dataManager = dataManager;
}
/**
* 执行事务操作
* @param {Function} operation - 要执行的操作函数
* @returns {Promise} 事务结果Promise
*/
async executeTransaction(operation) {
try {
// 标记事务开始
this.beginTransaction();
// 执行操作
const result = await operation();
// 提交事务
this.commitTransaction();
return result;
} catch (error) {
// 回滚事务
this.rollbackTransaction();
throw error;
}
}
/**
* 开始事务
*/
beginTransaction() {
// 在实际应用中,这里可能需要保存当前状态以便回滚
// 对于这个简单实现,我们只是记录事务开始
this.isInTransaction = true;
this.transactionOperations = [];
}
/**
* 提交事务
*/
commitTransaction() {
// 执行所有事务操作
this.transactionOperations.forEach(op => {
if (typeof op === 'function') {
try {
op();
} catch (error) {
console.error('Transaction operation failed:', error);
}
}
});
// 清空事务状态
this.isInTransaction = false;
this.transactionOperations = [];
}
/**
* 回滚事务
*/
rollbackTransaction() {
// 在实际应用中,这里需要恢复到事务开始前的状态
// 对于这个简单实现,我们只是清空事务状态
this.isInTransaction = false;
this.transactionOperations = [];
}
/**
* 向事务中添加操作
* @param {Function} operation - 要添加的操作函数
*/
addOperation(operation) {
if (this.isInTransaction) {
this.transactionOperations.push(operation);
}
}
/**
* 执行复合数据更新
* @param {Object} updateData - 更新数据对象
* @returns {Promise} 更新结果Promise
*/
async updateMultipleEntities(updateData) {
return this.executeTransaction(async () => {
const results = {};
// 处理不同类型的实体更新
for (const entityType in updateData) {
if (Object.prototype.hasOwnProperty.call(updateData, entityType)) {
const entities = updateData[entityType];
if (Array.isArray(entities)) {
results[entityType] = await this.updateEntitiesOfType(entityType, entities);
}
}
}
return results;
});
}
/**
* 更新特定类型的实体
* @param {string} entityType - 实体类型
* @param {Array} entities - 要更新的实体数组
* @returns {Promise} 更新结果Promise
*/
async updateEntitiesOfType(entityType, entities) {
const results = [];
for (const entity of entities) {
if (entity.id) {
// 已存在的实体,执行更新
const result = await this.dataManager.updateEntity(entityType, entity);
results.push(result);
} else {
// 新实体,执行添加
const result = await this.dataManager.addEntity(entityType, entity);
results.push(result);
}
}
return results;
}
}
================================================================================
/* 文件路径: data/WebSocketClient.js */
/**
* WebSocket客户端类
* 负责连接WebSocket服务器并处理实体更新通知
* 注意:使用前需要在HTML页面中引入SockJS和Stomp客户端库
* <script src="https://cdn.jsdelivr.net/npm/sockjs-client@1/dist/sockjs.min.js"></script>
* <script src="https://cdn.jsdelivr.net/npm/stompjs@2.3.3/lib/stomp.min.js"></script>
*/
export class WebSocketClient {
constructor() {
// WebSocket连接实例
this.socket = null;
this.stompClient = null;
// 消息处理回调函数
this.onEntityUpdate = null;
this.onConnectionStatusChange = null;
// 连接状态标志
this.isConnected = false;
// 检查SockJS和Stomp客户端库是否已加载
if (typeof window.SockJS === 'undefined') {
console.warn('SockJS客户端库未加载,请在HTML页面中引入SockJS库');
}
if (typeof window.Stomp === 'undefined') {
console.warn('Stomp客户端库未加载,请在HTML页面中引入Stomp库');
}
}
/**
* 连接WebSocket服务器
*/
connect() {
// 构建WebSocket服务器URL
const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsUrl = `${wsProtocol}//${window.location.host}${window.location.pathname}ws`;
// 使用SockJS客户端连接
this.socket = new SockJS(wsUrl);
const stompClient = Stomp.over(this.socket);
// 设置调试标志
stompClient.debug = null; // 禁用调试输出
// 连接回调
stompClient.connect({},
// 连接成功回调
() => {
console.log('WebSocket连接成功,开始接收实时数据更新');
this.isConnected = true;
// 触发连接状态变化回调
if (this.onConnectionStatusChange) {
this.onConnectionStatusChange(true);
}
// 订阅实体更新频道
stompClient.subscribe('/topic/entity-updates', (message) => {
this.handleEntityUpdate(message);
});
},
// 连接错误/断开回调
(error) => {
console.error('WebSocket连接失败:', error);
this.isConnected = false;
// 触发连接状态变化回调
if (this.onConnectionStatusChange) {
this.onConnectionStatusChange(false);
}
// 尝试重新连接
setTimeout(() => {
console.log('尝试重新连接WebSocket...');
this.connect();
}, 5000); // 5秒后重试
}
);
// 保存Stomp客户端引用
this.stompClient = stompClient;
}
/**
* 断开WebSocket连接
*/
disconnect() {
if (this.stompClient) {
this.stompClient.disconnect(() => {
console.log('WebSocket连接已断开');
this.isConnected = false;
if (this.onConnectionStatusChange) {
this.onConnectionStatusChange(false);
}
});
}
}
/**
* 处理接收到的实体更新消息
*/
handleEntityUpdate(message) {
try {
// 解析消息内容
const updateData = JSON.parse(message.body);
// 触发实体更新回调
if (this.onEntityUpdate) {
this.onEntityUpdate(updateData);
}
} catch (error) {
console.error('解析实体更新消息失败:', error);
}
}
/**
* 获取当前连接状态
*/
getConnectionStatus() {
return this.isConnected;
}
}
================================================================================
/* 文件路径: data/components/WebSocketClient.js */
/**
* WebSocket客户端组件
* 负责连接WebSocket服务器并处理实体更新通知
*/
export class WebSocketClient {
constructor(dataManager, url = '/ws') {
this.dataManager = dataManager;
this.url = url;
this.socket = null;
this.reconnectAttempts = 0;
this.maxReconnectAttempts = 5;
this.reconnectInterval = 1000;
this.isConnecting = false;
}
/**
* 连接到WebSocket服务器
*/
connect() {
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
return;
}
if (this.isConnecting) {
return;
}
this.isConnecting = true;
try {
// 创建WebSocket连接
this.socket = new WebSocket(this.url);
// 设置事件处理器
this.socket.onopen = this.handleOpen.bind(this);
this.socket.onmessage = this.handleMessage.bind(this);
this.socket.onclose = this.handleClose.bind(this);
this.socket.onerror = this.handleError.bind(this);
} catch (error) {
console.error('Failed to create WebSocket connection:', error);
this.isConnecting = false;
this.attemptReconnect();
}
}
/**
* 断开WebSocket连接
*/
disconnect() {
if (this.socket) {
this.socket.close();
this.socket = null;
}
this.reconnectAttempts = 0;
this.isConnecting = false;
}
/**
* 处理WebSocket连接打开事件
* @param {Event} event - 连接事件
*/
handleOpen(event) {
console.log('WebSocket connection established');
this.isConnecting = false;
this.reconnectAttempts = 0;
// 发送连接确认消息
this.send({
type: 'connect',
timestamp: new Date().getTime()
});
}
/**
* 处理WebSocket消息
* @param {MessageEvent} event - 消息事件
*/
handleMessage(event) {
try {
const data = JSON.parse(event.data);
this.dataManager.handleWebSocketUpdate(data);
} catch (error) {
console.error('Failed to parse WebSocket message:', error);
}
}
/**
* 处理WebSocket连接关闭事件
* @param {CloseEvent} event - 关闭事件
*/
handleClose(event) {
console.log('WebSocket connection closed:', event.code, event.reason);
this.socket = null;
this.isConnecting = false;
// 尝试重新连接
this.attemptReconnect();
}
/**
* 处理WebSocket错误事件
* @param {Event} event - 错误事件
*/
handleError(event) {
console.error('WebSocket error:', event);
}
/**
* 发送消息到服务器
* @param {Object} message - 要发送的消息对象
*/
send(message) {
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
this.socket.send(JSON.stringify(message));
} else {
console.warn('WebSocket is not connected, cannot send message');
}
}
/**
* 尝试重新连接
*/
attemptReconnect() {
if (this.reconnectAttempts < this.maxReconnectAttempts) {
this.reconnectAttempts++;
const delay = this.reconnectInterval * Math.pow(2, this.reconnectAttempts - 1);
console.log(`Attempting to reconnect in ${delay}ms (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts})`);
setTimeout(() => {
this.connect();
}, delay);
} else {
console.error('Max reconnection attempts reached, giving up');
}
}
/**
* 订阅特定实体类型的更新
* @param {string} entityType - 实体类型
*/
subscribe(entityType) {
this.send({
type: 'subscribe',
entityType: entityType
});
}
/**
* 取消订阅特定实体类型的更新
* @param {string} entityType - 实体类型
*/
unsubscribe(entityType) {
this.send({
type: 'unsubscribe',
entityType: entityType
});
}
}
最新发布