laravel中对象数据转换为数组的快捷方法$d = array_map('get_object_vars', $data);

由于给定内容为空,无法提取关键信息生成摘要。
$data = array_map('get_object_vars', $data);

 

ValueError: setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (1000209,) + inhomogeneous part.import pandas as pd import numpy as np import re import os from sklearn.model_selection import train_test_split from tensorflow.keras.preprocessing.sequence import pad_sequences from tensorflow.keras.utils import to_categorical from sklearn.metrics import mean_absolute_error, ndcg_score import tensorflow as tf from tensorflow.keras.models import Model from tensorflow.keras.layers import Input, Embedding, Dense, Dropout, Concatenate, Reshape, Multiply, Activation, GlobalAveragePooling1D, Bidirectional, LSTM, MultiHeadAttention # 更安全地提取电影名 def extract_title_year(title): pattern = re.compile(r'^(.*?)\s*$(\d+)$') match = pattern.match(title) if match: return match.group(1).strip() else: return title.strip() # 加载数据 def load_data(): # 用户数据 users = pd.read_csv('/kaggle/input/tuijian/ml-1m/users.dat', sep='::', header=None, names=['UserID', 'Gender', 'Age', 'Occupation', 'Zip-code'], engine='python', encoding='ISO-8859-1') users = users[['UserID', 'Gender', 'Age', 'Occupation']] users['UserID'] = users['UserID'].astype(int) gender_map = {'F': 0, 'M': 1} users['Gender'] = users['Gender'].map(gender_map) age_map = {var: ii for ii, var in enumerate(set(users['Age']))} users['Age'] = users['Age'].map(age_map) # 电影数据 movies = pd.read_csv('/kaggle/input/tuijian/ml-1m/movies.dat', sep='::', header=None, names=['MovieID', 'Title', 'Genres'], engine='python', encoding='ISO-8859-1') movies['MovieID'] = movies['MovieID'].astype(int) movies['TitleWithoutYear'] = movies['Title'].apply(extract_title_year) # 处理类型 genre_set = set() for var in movies['Genres'].str.split('|'): genre_set.update(var) genre_int_map = {var: ii for ii, var in enumerate(genre_set)} movies['GenresMultiHot'] = movies['Genres'].apply( lambda x: [genre_int_map[genre] for genre in x.split('|')]) movies['GenresMultiHot'] = movies['GenresMultiHot'].apply( lambda x: to_categorical(x, num_classes=len(genre_int_map))) # 处理标题 word_set = set() for var in movies['TitleWithoutYear'].str.split(): word_set.update(var) word_int_map = {var: ii + 1 for ii, var in enumerate(word_set)} movies['TitleIndex'] = movies['TitleWithoutYear'].apply( lambda x: [word_int_map[word] for word in x.split() if word in word_int_map]) movies['TitleIndex'] = movies['TitleIndex'].apply( lambda x: pad_sequences([x], maxlen=15, padding='post', value=0)[0]) # 评分数据 ratings = pd.read_csv('/kaggle/input/tuijian/ml-1m/ratings.dat', sep='::', header=None, names=['UserID', 'MovieID', 'Rating', 'Timestamp'], engine='python', encoding='ISO-8859-1') ratings['UserID'] = ratings['UserID'].astype(int) ratings['MovieID'] = ratings['MovieID'].astype(int) ratings = ratings[['UserID', 'MovieID', 'Rating']] # 合并数据 data = pd.merge(pd.merge(users, ratings), movies) features = data.drop(['Rating'], axis=1) targets = data[['Rating']] return features, targets, genre_int_map, word_int_map # 加载并预处理数据 features, targets, genre_int_map, word_int_map = load_data() # 超参数 USER_ID_COUNT = 6040 MOVIE_ID_COUNT = 3952 GENRE_COUNT = len(genre_int_map) TITLE_WORD_COUNT = len(word_int_map) + 1 EMBED_DIM = 64 LSTM_UNIT_NUM = 64 DROPOUT_RATE = 0.3 # 用户特征网络 def user_feature_network(user_id, user_gender, user_age, user_occupation): user_id_embed = Embedding(USER_ID_COUNT, EMBED_DIM)(user_id) user_gender_embed = Embedding(2, EMBED_DIM // 2)(user_gender) user_age_embed = Embedding(7, EMBED_DIM // 2)(user_age) user_occupation_embed = Embedding(21, EMBED_DIM // 2)(user_occupation) user_id_embed = Reshape((EMBED_DIM,))(user_id_embed) user_gender_embed = Reshape((EMBED_DIM // 2,))(user_gender_embed) user_age_embed = Reshape((EMBED_DIM // 2,))(user_age_embed) user_occupation_embed = Reshape((EMBED_DIM // 2,))(user_occupation_embed) user_combine = Concatenate()([user_id_embed, user_gender_embed, user_age_embed, user_occupation_embed]) user_dense = Dense(128, activation='relu')(user_combine) return user_dense # 电影特征网络 def movie_feature_network(movie_id, movie_genres, movie_titles): movie_id_embed = Embedding(MOVIE_ID_COUNT, EMBED_DIM)(movie_id) movie_genres_embed = Dense(EMBED_DIM, activation='relu')(movie_genres) movie_title_embed = Embedding(TITLE_WORD_COUNT, EMBED_DIM)(movie_titles) transformer_output = MultiHeadAttention(num_heads=2, key_dim=EMBED_DIM)(movie_title_embed, movie_title_embed) transformer_output = GlobalAveragePooling1D()(transformer_output) movie_combine = Concatenate()([movie_id_embed, movie_genres_embed, transformer_output]) movie_dense = Dense(128, activation='relu')(movie_combine) return movie_dense # 注意力交互模块 def attention_interaction(user_feat, movie_feat): attention_score = tf.keras.layers.Dot(axes=-1)([user_feat, movie_feat]) attention_score = Reshape((1,))(attention_score) attention_score = Activation('softmax')(attention_score) return attention_score # 构建模型 def build_model(): user_id = Input(shape=(1,), name='user_id') user_gender = Input(shape=(1,), name='user_gender') user_age = Input(shape=(1,), name='user_age') user_occupation = Input(shape=(1,), name='user_occupation') movie_id = Input(shape=(1,), name='movie_id') movie_genres = Input(shape=(GENRE_COUNT,), name='movie_genres') movie_titles = Input(shape=(15,), name='movie_titles') user_feat = user_feature_network(user_id, user_gender, user_age, user_occupation) movie_feat = movie_feature_network(movie_id, movie_genres, movie_titles) attention_score = attention_interaction(user_feat, movie_feat) interaction = Multiply()([user_feat, attention_score]) combined = Concatenate()([interaction, movie_feat]) output = Dense(1, activation='sigmoid', name='predicted_rating')(combined) model = Model( inputs=[user_id, user_gender, user_age, user_occupation, movie_id, movie_genres, movie_titles], outputs=output ) model.compile(optimizer='adam', loss='mse', metrics=['mae']) return model # 准备数据 user_id_arr = np.array(features['UserID']).reshape(-1, 1) user_gender_arr = np.array(features['Gender']).reshape(-1, 1) user_age_arr = np.array(features['Age']).reshape(-1, 1) user_occupation_arr = np.array(features['Occupation']).reshape(-1, 1) movie_id_arr = np.array(features['MovieID']).reshape(-1, 1) movie_genres_arr = np.array(features['GenresMultiHot'].tolist()) movie_titles_arr = np.array(features['TitleIndex'].tolist()) ratings_arr = np.array(targets['Rating']).reshape(-1, 1) # 划分训练集和测试集 X = [user_id_arr, user_gender_arr, user_age_arr, user_occupation_arr, movie_id_arr, movie_genres_arr, movie_titles_arr] y = ratings_arr X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 构建并训练模型 model = build_model() model.summary() history = model.fit(X_train, y_train, epochs=10, batch_size=256, validation_split=0.2) # 评估 loss, mae = model.evaluate(X_test, y_test) print(f'Test Loss: {loss:.4f}') print(f'Test MAE: {mae:.4f}') # 生成预测 predictions = model.predict(X_test) # Hit Rate @ K def calculate_hit_rate(predictions, actuals, top_k=10): hit_count = 0 user_dict = {} for i, (pred, act) in enumerate(zip(predictions, actuals)): user_id = X_test[0][i][0] if user_id not in user_dict: user_dict[user_id] = [] user_dict[user_id].append((pred[0], act[0])) for user in user_dict: items = sorted(user_dict[user], key=lambda x: x[0], reverse=True)[:top_k] top_k_items = [item[1] for item in items] if any([act >= 4 for act in top_k_items]): hit_count += 1 return hit_count / len(user_dict) # NDCG @ K def calculate_ndcg(predictions, actuals, top_k=10): user_dict = {} for i, (pred, act) in enumerate(zip(predictions, actuals)): user_id = X_test[0][i][0] if user_id not in user_dict: user_dict[user_id] = [] user_dict[user_id].append((pred[0], act[0])) ndcg_scores = [] for user in user_dict: preds, acts = zip(*user_dict[user]) preds = np.array(preds).reshape(1, -1) acts = np.array(acts).reshape(1, -1) idxs = np.argsort(-preds[0])[:top_k] ndcg = ndcg_score(acts[:, idxs], preds[:, idxs], k=top_k) ndcg_scores.append(ndcg) return np.mean(ndcg_scores) # 计算评估指标 hit_rate = calculate_hit_rate(predictions, y_test, top_k=10) ndcg_at_k = calculate_ndcg(predictions, y_test, top_k=10) print(f'Test HR@10: {hit_rate:.4f}') print(f'Test NDCG@10: {ndcg_at_k:.4f}')
06-13
/* 文件路径: data/DataManager.js */ // @ts-nocheck // 导入依赖 import { LazyLoader } from './LazyLoader.js'; import { TransactionApi } from './TransactionApi.js'; //这个函数不许改,也禁止废话,属性名和其他命名都哼规范不会出现意外, function resolveDataReferences(data) { console.log(data) // 获取 data 对象的所有顶层键 const keys = Object.keys(data); // 遍历每个顶层键(如 users, posts 等) for (const key of keys) { const entities = data[key]; // 遍历该顶层键下的每个实体(如每个 user 或 post) for (const entity of entities) { // 遍历实体的每个属性 for (const attribute in entity) { if (entity?.hasOwnProperty(attribute)) { var trpe=attribute?.replace(/\d/g, ''); // 确保属性属于当前实体 if (Array.isArray(entity[attribute])) { if(data[trpe]==null){ trpe+="s" } // 如果属性是一个数组,则将数组中的每个 ID 替换为对应的实际对象 entity[attribute] = entity[attribute].map(item => data[trpe ]?.find(updateItem => updateItem?.id === item?.id) || item ); } else if (typeof entity[attribute] === "object" && entity[attribute] !== null) { // 如果属性是一个对象,则将其替换为对应的实际对象 entity[attribute] = data[trpe + "s"]?.find(updateItem => updateItem?.id === entity[attribute]?.id); } } } } } return data; } function resolveDataReference(entity,data) { console.log(entity) // // 遍历实体的每个属性 for (const attribute in entity) { if (entity?.hasOwnProperty(attribute)) { var trpe=attribute?.replace(/\d/g, ''); // 确保属性属于当前实体 if (Array.isArray(entity[attribute])) { if(data[trpe]==null){ trpe+="s" } // 如果属性是一个数组,则将数组中的每个 ID 替换为对应的实际对象 entity[attribute] = entity[attribute].map(item => data[trpe ]?.find(updateItem => updateItem?.id === item?.id) || item ); } else if (typeof entity[attribute] === "object" && entity[attribute] !== null) { // 如果属性是一个对象,则将其替换为对应的实际对象 entity[attribute] = data[trpe + "s"]?.find(updateItem => updateItem?.id === entity[attribute]?.id); } } } return entity; } /** * 数据管理器类 - Web版 * 基于小程序版MiniProgramDataManager重构 */ class DataManager { constructor(baseUrl = "../php_api/index.php") { this.baseUrl = baseUrl; this.debug = true; this.networkAvailable = true; this.isSyncing = false; this.lastSync = null; this.syncInterval = 5 * 60 * 1000; this.storageKey = 'webAppData'; this._rawData = this.createEmptyData(); this.lazyLoader = new LazyLoader(this); this.callbacks = { all: [], bancais: [], dingdans: [], mupis: [], chanpins: [], kucuns: [], chanpin_zujians: [], dingdan_bancais: [], zujians: [], caizhis: [], dingdan_chanpins: [], users: [], jinhuos: [], shengchan_xiaohao: [] }; // 创建事务API实例 this.Transaction = new TransactionApi(this); this.entiyeText = { bancai: '板材已存在', dingdan: '订单已存在', mupi: '木皮已存在', chanpin: '产品已存在', kucun: '已有库存记录', chanpin_zujian: '产品已有该件', dingdan_bancai: '', zujian: '件已定义过了', caizhi: '材质已定义过了', dingdan_chanpin: '订单下已有该产品', user: '' }; this.initNetwork(); this.loadDataFromStorage(); 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); } } }); } createEmptyData() { return { bancais: [], dingdans: [], mupis: [], chanpins: [], kucuns: [], dingdan_bancais: [], chanpin_zujians: [], zujians: [], caizhis: [], dingdan_chanpins: [], users: [], jinhuos: [], _lastModified: null, _lastSync: null }; } get data() { // 创建数据访问代理,保持懒加载功能 const self = this; return new Proxy(this._rawData, { get: (target, prop) => { if (prop.startsWith('_')) { return target[prop]; } if (Array.isArray(target[prop])) { // 为数组中的每个对象创建懒加载代理 return target[prop].map(item => { if (typeof item === 'object' && item !== null) { return self.lazyLoader.createProxy(item, prop.replace(/s$/, '')); } return item; }); } return target[prop]; }, set: (target, prop, value) => { // 允许内部修改,但给出警告 console.warn(`直接修改 data.${prop} 可能会影响数据一致性,建议使用 DataManager 的方法`); target[prop] = value; return true; }, deleteProperty: (target, prop) => { console.warn(`直接删除 data.${prop} 可能会影响数据一致性,建议使用 DataManager 的方法`); delete target[prop]; return true; } }); } async initialize() { try { await this.syncData(); return true; } catch (error) { if (this._rawData._lastSync) return true; throw error; } } startAutoSync() { if (this.autoSyncTimer) clearInterval(this.autoSyncTimer); this.autoSyncTimer = setInterval(() => { if (!this.isSyncing) this.syncData(); }, this.syncInterval); } stopAutoSync() { clearInterval(this.autoSyncTimer); } async initNetwork() { // Web环境默认网络可用 this.networkAvailable = navigator.onLine; // 监听网络状态变化 window.addEventListener('online', () => { this.networkAvailable = true; }); window.addEventListener('offline', () => { this.networkAvailable = false; }); } async syncData() { if (this.isSyncing) return; this.isSyncing = true; try { const since = this._rawData._lastSync; await this.fetchAll(since); this.lazyLoader.clearCache(); this.saveDataToStorage(); this.triggerCallbacks('refresh', 'all', this.data); } catch (error) { console.error('Sync failed:', error); this.triggerCallbacks('sync_error', 'all', { error }); if (!this._rawData._lastSync) throw error; } finally { this.isSyncing = false; } } async fetchAll(since) { try { const params = since ? { since } : {}; const url = since ? `${this.baseUrl}/app/all?since=${encodeURIComponent(since)}` : `${this.baseUrl}/app/all`; const response = await fetch(url); 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'); const resolvedData = resolveDataReferences(result.data); Object.keys(this._rawData).forEach(key => { if (key.startsWith('_') || !resolvedData[key]) return; if (since) { resolvedData[key].forEach(newItem => { const index = this._rawData[key].findIndex(item => item.id === newItem.id); index >= 0 ? this._rawData[key][index] = newItem : this._rawData[key].push(newItem); }); } else { this._rawData[key] = resolvedData[key]; } }); this._rawData._lastSync = new Date().toISOString(); this.saveDataToStorage(); return true; } catch (error) { console.error('Fetch error:', error); this.triggerCallbacks('fetch_error', 'all', { error }); throw error; } } registerCallback(entity, callback) { if (!this.callbacks[entity]) { this.callbacks[entity] = []; } this.callbacks[entity].push(callback); } unregisterCallback(entity, callback) { const arr = this.callbacks[entity] || this.callbacks.all; const index = arr.indexOf(callback); if (index !== -1) arr.splice(index, 1); } triggerCallbacks(operation, entity, data) { this.callbacks.all.forEach(cb => cb(operation, entity, data)); this.callbacks[entity]?.forEach(cb => cb(operation, data)); } 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'); const resultData = result.data || data; this.updateLocalData(operation, entity, resultData); this.triggerCallbacks(operation, entity, resultData); return resultData; } catch (error) { this.triggerCallbacks(`${operation}_error`, entity, { data, error }); throw error; } } updateLocalData(operation, entity, data) { const key = `${entity}s`; const collection = this._rawData[key] || []; switch (operation) { case 'add': collection.push(resolveDataReference(data, this._rawData)); break; case 'update': const index = collection.findIndex(item => item.id === data.id); index >= 0 ? Object.assign(collection[index], data) : collection.push(resolveDataReference(data, this._rawData)); break; case 'delete': const deleteIndex = collection.findIndex(item => item.id === data.id); if (deleteIndex >= 0) collection.splice(deleteIndex, 1); break; } this._rawData._lastModified = new Date().toISOString(); this.lazyLoader.clearCache(); this.saveDataToStorage(); } loadDataFromStorage() { try { const storedData = localStorage.getItem(this.storageKey); if (storedData) { this._rawData = JSON.parse(storedData); } } catch (error) { console.error('Storage load error:', error); } } saveDataToStorage() { try { localStorage.setItem(this.storageKey, JSON.stringify(this._rawData)); } catch (error) { console.error('Storage save error:', error); alert('数据保存失败'); } } checkDuplicate(entity, data) { switch (entity) { case 'bancai': return this._rawData.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._rawData.caizhis.some(c => c.name === data.name); case 'mupi': return this._rawData.mupis.some(m => m.name === data.name && m.you === data.you); case 'chanpin': return this._rawData.chanpins.some(c => c.bianhao === data.bianhao); case 'zujian': return this._rawData.zujians.some(z => z.name === data.name); case 'dingdan': return this._rawData.dingdans.some(d => d.number === data.number); case 'chanpin_zujian': return this._rawData.chanpin_zujians.some(cz => cz.chanpin?.id === data.chanpin?.id && cz.zujian?.id === data.zujian?.id ); case 'dingdan_chanpin': return this._rawData.dingdan_chanpins.some(dc => dc.dingdan?.id === data.dingdan?.id && dc.chanpin?.id === data.chanpin?.id ); case 'dingdan_bancai': return this._rawData.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._rawData.users.some(u => u.name === data.name); default: return false; } } async addEntity(entity, data) { // 检查重复数据 if (this.checkDuplicate(entity, data)) { const errorMsg = `${this.entiyeText[entity]}`; this.triggerCallbacks('duplicate_error', entity, { data, error: errorMsg }); throw new Error(errorMsg); } return this.crudOperation('add', entity, data); } async updateEntity(entity, data) { return this.crudOperation('update', entity, data); } async deleteEntity(entity, id) { return this.crudOperation('delete', entity, { id }); } async transactionalOperation(endpoint, data) { return this.Transaction.execute(endpoint, data); } // 数据获取方法 getDingdans() { return this.data.dingdans || []; } getBancais() { return this.data.bancais || []; } getChanpins() { return this.data.chanpins || []; } getZujians() { return this.data.zujians || []; } getKucuns() { return this.data.kucuns || []; } getUsers() { return this.data.users || []; } getCaizhis() { return this.data.caizhis || []; } getMupis() { return this.data.mupis || []; } getDingdanBancais() { return this.data.dingdan_bancais || []; } getJinhuos() { return this.data.jinhuos || []; } getChanpinZujians() { return this.data.chanpin_zujians || []; } getDingdanChanpins() { return this.data.dingdan_chanpins || []; } // 业务方法 getChanpinsForDingdan(dingdanId) { const dingdan = this._rawData.dingdans.find(d => d?.id == dingdanId); if (!dingdan) return []; return (dingdan.dingdan_chanpin_list || []) .map(dc => dc.chanpin) .filter(c => c); } getZujiansForChanpin(chanpinId) { const chanpin = this._rawData.chanpins.find(c => c?.id == chanpinId); if (!chanpin) return []; return (chanpin.chanpin_zujian_list || []) .map(cz => cz.zujian) .filter(z => z); } getShengchanXiaohaoRecords() { return this._rawData.jinhuos.filter(jinhuo => jinhuo.the_type_of_operation === 2 && jinhuo.shuliang < 0 ); } getShengchanStatistics() { const today = new Date().toISOString().split('T')[0]; const thisMonth = new Date().toISOString().substring(0, 7); const consumptionRecords = this.getShengchanXiaohaoRecords(); const todayConsumption = consumptionRecords .filter(record => record.date && record.date.startsWith(today)) .reduce((sum, record) => sum + Math.abs(record.shuliang), 0); const monthConsumption = consumptionRecords .filter(record => record.date && record.date.startsWith(thisMonth)) .reduce((sum, record) => sum + Math.abs(record.shuliang), 0); const pendingOrders = this._rawData.dingdans.filter(dingdan => !dingdan.deleted && dingdan.zhuangtai !== '已完成' ).length; const lowStockCount = this._rawData.kucuns.filter(kucun => !kucun.deleted && kucun.shuliang < 10 ).length; return { today_consumption: todayConsumption, month_consumption: monthConsumption, pending_orders: pendingOrders, low_stock_count: lowStockCount, total_records: consumptionRecords.length }; } } export { DataManager }; ================================================================================ /* 文件路径: data/LazyLoader.js */ /** * 懒加载器 - Web版 * 负责处理数据的懒加载和代理 */ class LazyLoader { constructor(dataManager) { this.dataManager = dataManager; this.cache = new Map(); this.proxyCache = new Map(); } /** * 清除缓存 */ clearCache() { this.cache.clear(); // WeakMap 会自动清理,无需手动清除 } /** * 创建数据代理 * @param {Object} item - 原始数据项 * @param {string} entityType - 实体类型 * @returns {Proxy} 代理对象 */ createProxy(item, entityType) { if (!item || typeof item !== 'object') return item; // 检查是否已经创建过代理 if (this.proxyCache.has(entityType+"_"+item?.id)) { return this.proxyCache.get(entityType+"_"+item?.id); } if (Array.isArray(item)) { // 处理数组关联 return item.map(relatedItem => this.createProxy(relatedItem, entityType)); } const proxy = new Proxy(item, { get: (target, prop) => { // 直接返回基本属性 if (typeof prop === 'symbol' || prop.startsWith('_') || typeof target[prop] !== 'object') { return target[prop]; } // 处理关联对象的懒加载 if (target[prop] && typeof target[prop] === 'object') { if (Array.isArray(target[prop])) { // 处理数组关联 return target[prop].map(relatedItem => this.resolveRelation(relatedItem, prop) ); } else { // 处理单个关联对象 return this.resolveRelation(target[prop], prop); } } return target[prop]; }, set: (target, prop, value) => { target[prop] = value; return true; } }); // 缓存代理对象 this.proxyCache.set(entityType+"_"+item?.id, proxy); return proxy; } /** * 解析关联对象 * @param {Object} relatedItem - 关联对象 * @param {string} propName - 关联属性名 * @returns {Object|Array} 解析后的关联对象 */ resolveRelation(relatedItem, propName) { if (typeof relatedItem === 'undefined') return undefined; let entityType=propName; if(!this.dataManager._rawData[entityType]){ if(!this.dataManager._rawData[entityType+"s"]){ return relatedItem; }else{ entityType=entityType+"s"; } } const key_id =entityType+"_"+ relatedItem?.id; if (this.proxyCache.has(key_id)) { return this.proxyCache.get(key_id); } // 获取原始数据项的实体类型 const originalType = this.dataManager._rawData[entityType]; const cachedItem = originalType.find(x=>x.id===relatedItem?.id); if (cachedItem) { return this.createProxy(cachedItem,originalType); }else{ return relatedItem; } } } export { LazyLoader }; ================================================================================ /* 文件路径: data/TransactionApi.js */ /** * 事务API - Web版 * 负责处理所有事务相关的操作 */ class TransactionApi { constructor(dataManager) { this.dataManager = dataManager; this.baseUrl = dataManager.baseUrl; } /** * 执行事务操作 * @param {string} endpoint - 事务端点 * @param {Object} data - 事务数据 * @returns {Promise} 操作结果 */ async execute(endpoint, data) { try { 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.dataManager.syncData(); // 触发事务成功回调 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 {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} 操作结果 */ async updateStock(params) { return this.execute('kucunbianji', params); } /** * 生产消耗事务 * @param {Object} params - 生产消耗参数 * @returns {Promise} 操作结果 */ async shengchanXiaohao(params) { return this.execute('shengchanXiaohao', params); } /** * 批量更新订单板材事务 * @param {Object} params - 批量更新参数 * @returns {Promise} 操作结果 */ async batchUpdateDingdanBancai(params) { return this.execute('batchUpdateDingdanBancai', params); } /** * 保存所有数据事务 * @param {Object} params - 保存参数 * @returns {Promise} 操作结果 */ async saveAll(params) { try { 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 }; 懒加载部分有什么问题
最新发布
08-11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值