自动更新传出一个时间参数,获取最新数据并更新贝蒂数据 /**
数据管理器类,负责与后端API通信并管理数据
*/
class DataManager {
constructor(baseUrl) {
this.baseUrl = baseUrl;
this.data = {
bancais: [],
dingdans: [],
mupis: [],
chanpins: [],
kucuns: [],
dingdan_bancais:[],
chanpin_zujians: [],
zujians: [],
caizhis: [],
dingdan_chanpins: [],
users: [],
jinhuos: []
};
this.isSyncing = false;
this.lastSync = null;
this.callbacks = {
all: [],
bancais: [],
dingdan: [],
mupi: [],
chanpin: [],
kucun: [],
chanpin_zujian: [],
dingdan_bancai:[],
zujian: [],
caizhi: [],
dingdan_chanpin: [],
user: [],
jinhuo: []
};
this.syncQueue = Promise.resolve();
this.syncInterval = 5 * 60 * 1000; // 5分钟 this.startAutoSync(); this.registerCallback('dingdan_bancai', async (operation, data) => { if (operation === 'add' || operation === 'update') { try { // 构造进货记录数据 const jinhuoData = { dingdan_bancai:{id:data?.id}, shuliang: data.shuliang, date: new Date().toISOString(), user: { id: localStorage.getItem("userId") } }; // 创建进货记录 await this.addEntity('jinhuo', jinhuoData); } catch (error) { console.error('进货记录创建失败:', error); } } });
}
// 启动自动同步
startAutoSync() {
if (this.autoSyncTimer) clearInterval(this.autoSyncTimer);
this.autoSyncTimer = setInterval(() => {
if (!this.isSyncing) this.syncData();
}, this.syncInterval);
}
// 停止自动同步
stopAutoSync() {
clearInterval(this.autoSyncTimer);
}
/**
获取所有数据
@returns {Promise} 是否成功
*/
async fetchAll() {
console.log(this)
try {
const response = await fetch(${this.baseUrl}/app/all);
if (!response.ok) throw new Error(‘Network response was not ok’);
const result = await response.json();
if (result.status !== 200) throw new Error(result.text || ‘API error’);
console.log(result.data)
const resolvedData = resolveDataReferences(result.data);
// 更新本地数据
Object.keys(this.data).forEach(key => {
if (resolvedData[key]) {
this.data[key] = resolvedData[key];
}
});
this.lastSync = new Date();
// 关键改进:数据更新后触发刷新回调
this.triggerCallbacks(‘refresh’, ‘all’, this.data);
return true;
} catch (error) {
console.error(‘Fetch error:’, error);
// 触发错误回调
this.triggerCallbacks(‘fetch_error’, ‘all’, { error });
return false;
}
}
/**
注册回调函数
@param {string} entity - 实体类型(如’bancai’)或’all’表示全局回调
@param {Function} callback - 回调函数,参数为(operation, data)
*/
registerCallback(entity, callback) {
if (!this.callbacks[entity]) {
this.callbacks[entity] = [];
}
this.callbacks[entity].push(callback);
}
/**
移除回调函数
@param {string} entity - 实体类型单数性质
@param {Function} callback - 要移除的回调函数
*/
unregisterCallback(entity, callback) {
if (!this.callbacks[entity]) return;
const index = this.callbacks[entity].indexOf(callback); if (index !== -1) { this.callbacks[entity].splice(index, 1); }
}
/**
触发回调
@param {string} operation - 操作类型(‘add’, ‘update’, ‘delete’)
@param {string} entity - 实体类型单数性质
@param {Object} data - 相关数据
*/
triggerCallbacks(operation, entity, data) {
// 触发全局回调
this.callbacks.all.forEach(cb => cb(operation, entity, data));
// 触发特定实体回调 if (this.callbacks[entity]) { this.callbacks[entity].forEach(cb => cb(operation, data)); }
}
checkDuplicate(entity, data) {
switch (entity) {
case ‘bancai’:
return this.data.bancais.some(b =>
b.houdu === data.houdu &&
b.caizhi?.id === data.caizhi?.id &&
b.mupi1?.id === data.mupi1?.id &&
b.mupi2?.id === data.mupi2?.id
);
case ‘caizhi’:
return this.data.caizhis.some(c => c.name === data.name);
case ‘mupi’:
return this.data.mupis.some(m => m.name === data.name);
case ‘chanpin’:
return this.data.chanpins.some(c => c.bianhao === data.bianhao);
case ‘zujian’:
return this.data.zujians.some(z => z.name === data.name);
case ‘dingdan’:
return this.data.dingdans.some(d => d.number === data.number);
case ‘chanpin_zujian’:
return this.data.chanpin_zujians.some(cz =>
cz.chanpin?.id === data.chanpin?.id &&
cz.zujian?.id === data.zujian?.id
);
case ‘dingdan_chanpin’:
return this.data.dingdan_chanpins.some(dc =>
dc.dingdan?.id === data.dingdan?.id &&
dc.chanpin?.id === data.chanpin?.id
);
case ‘dingdan_bancai’:
return this.data.dingdan_bancais.some(db =>
db.dingdan?.id === data.dingdan?.id &&
db.chanpin?.id === data.chanpin?.id &&
db.zujian?.id === data.zujian?.id &&
db.bancai?.id === data.bancai?.id
);
case ‘user’:
return this.data.users.some(u => u.name === data.name);
default:
return false; // 其他实体类型不检查重复
}
}
/**
执行CRUD操作
@param {string} operation - ‘add’, ‘delete’, ‘update’
@param {string} entity - 实体名称单数性质(小写)
@param {Object} data - 要发送的数据 后端要求数据格式为{属性: “值”, 关联对象: {id:0}, 关联对象集: [{id:0}]}
@returns {Promise} 响应结果
*/
async crudOperation(operation, entity, data) {
try {
const response = await fetch(${this.baseUrl}/app/${operation}/${entity}, {
method: ‘POST’,
headers: {‘Content-Type’: ‘application/json’},
body: JSON.stringify(data)
});
if (!response.ok) throw new Error('Network response was not ok'); const result = await response.json(); if (result.status !== 200) throw new Error(result.text || 'API error'); console.log(data)//这了就没有id了 this. updateLocalData(operation, entity, result.data||data) // 自动同步数据 // 同步完成后触发操作回调 this.triggerCallbacks(operation, entity, result.data||data); return result;
} catch (error) {
console.error(‘CRUD error:’, error);
// 触发操作失败的回调
this.triggerCallbacks(${operation}_error, entity, {
data,
error: error.message
});
throw error;
}
}
updateLocalData(operation, entity, newData) {
var key=entity+“s”;
var entitys= this.data[key]
switch (operation) {
case ‘add’:
entitys.push(resolveDataReference(newData,this.data))
break;
case ‘update’:
const index = entitys.findIndex(item => item.id === newData.id);
if (index !== -1) {
if(entitys[index].id==newData.id){ for(var an in entitys[index]){ entitys[index][an]=newData[an] } } /*报错DataManager.js:312 CRUD error: ReferenceError: collection is not defined
at DataManager.updateLocalData (DataManager.js:335:32) at DataManager.crudOperation (DataManager.js:303:13) at async HTMLButtonElement.<anonymous> (tianjia.js:325:21)*/ } else { entitys.push(resolveDataReference(newData,this.data)); } break; case 'delete': const deleteIndex = entitys.findIndex(item => item.id === newData.id); if (deleteIndex !== -1) { entitys.splice(deleteIndex, 1); } break; default: break;
}
}
/**
自动同步数据(防止频繁请求)
*/
async syncData() {
if (this.isSyncing) {
this.pendingSync = true;
return;
}
this.isSyncing = true;
try {
await this.fetchAll();
} catch (error) {
console.error(‘Sync failed:’, error);
} finally {
this.isSyncing = false;
// 处理等待中的同步请求 if (this.pendingSync) { this.pendingSync = false; setTimeout(() => this.syncData(), 1000); }
}
}
/**
添加实体
@param {string} entity - 实体名称单数性质
@param {Object} data - 实体数据
/
async addEntity(entity, data) {
// 检查重复数据
if (this.checkDuplicate(entity, data)) {
const errorMsg = ${entity}数据重复;
this.triggerCallbacks(‘duplicate_error’, entity, { data, error: errorMsg });
throw new Error(errorMsg);
}
return this.crudOperation(‘add’, entity, data);
}
/*
更新实体
@param {string} entity - 实体名称单数性质
@param {Object} data - 实体数据(必须包含id)
*/
async updateEntity(entity, data) {
return this.crudOperation(‘update’, entity, data);
}
/**
删除实体
@param {string} entity - 实体名称单数性质
@param {number} id - 实体ID
*/
async deleteEntity(entity, id) {
return this.crudOperation(‘delete’, entity, {id});
}
/**
新增方法:手动触发数据刷新
*/
async refreshData() {
return this.syncQueue = this.syncQueue.then(() => this.syncData());
}
/**
获取订单的可用板材信息
@param {number} dingdanId - 订单ID
@returns {Object} 可用板材信息
*/
getAvailableBancaisForOrder(dingdanId) {
const dingdan = this.data.dingdans.find(d => d?.id == dingdanId);
if (!dingdan) return {};
return dingdan.availableBancais || {};
}
/**
获取产品的组件列表
@param {number} chanpinId - 产品ID
@returns {Array} 组件列表
*/
getZujiansForChanpin(chanpinId) {
const chanpin = this.data.chanpins.find(c => c?.id == chanpinId);
if (!chanpin) return [];
return (chanpin.chanpin_zujian_list || [])
.map(cz => cz.zujian)
.filter(z => z);
}
/**
获取组件的板材信息
@param {number} zujianId - 组件ID
@returns {Array} 板材列表
*/
getBancaisForZujian(zujianId) {
return (this.data.chanpin_zujians || [])
.filter(cz => cz.zujian && cz.zujian?.id == zujianId)
.map(cz => cz.bancai)
.filter(b => b);
}
/**
创建进货记录
@param {Object} jinhuoData - 进货数据
@returns {Promise} 操作结果
*/
async createJinhuo(jinhuoData) {
return this.addEntity(‘jinhuo’, jinhuoData);
}
/**
获取订单列表
@returns {Array} 订单列表
*/
getDingdans() {
return this.data.dingdans || [];
}
/**
获取订单的产品列表
@param {number} dingdanId - 订单ID
@returns {Array} 产品列表
*/
getChanpinsForDingdan(dingdanId) {
const dingdan = this.data.dingdans.find(d => d?.id == dingdanId);
if (!dingdan) return [];
return (dingdan.dingdan_chanpin_list || [])
.map(dc => dc.chanpin)
.filter(c => c);
}
}
export { DataManager };