//{ 实体类的关联和属性列表
// "entities": {
// "Dingdan": {
// "properties": {
// "id": "Integer",
// "number": "String",
// "xiadan": "Date",
// "jiaohuo": "Date",
// "dingdan_chanpins": "List<Dingdan_chanpin> (OneToMany)",
// "dingdan_chanpins_zujians": "List<Dingdan_chanpin_zujian> (OneToMany)"
// },
// "relations": [
// "关联订单产品(Dingdan_chanpin)",
// "关联订单组件(Dingdan_chanpin_zujian)"
// ]
// },
// "Dingdan_chanpin": {
// "properties": {
// "id": "Integer",
// "shuliang": "Integer"
// },
// "relations": [
// "多对一关联订单(Dingdan)",
// "多对一关联产品(Chanpin)"
// ]
// },
// "Dingdan_chanpin_zujian": {
// "properties": {
// "id": "Integer",
// "shuliang": "Integer"
// },
// "relations": [
// "多对一关联订单(Dingdan)",
// "多对一关联组件(Chanpin_zujian)",
// "多对一关联板材(Bancai)"
// ]
// },
// "Jinhuo": {
// "properties": {
// "id": "Integer",
// "shuliang": "Integer",
// "date": "Date"
// },
// "relations": [
// "多对一关联订单(Dingdan)",
// "多对一关联产品(Chanpin)",
// "多对一关联组件(Zujian)",
// "多对一关联板材(Bancai)",
// "多对一关联用户(User)"
// ]
// },
// "Kucun": {
// "properties": {
// "id": "Integer",
// "shuliang": "Long"
// },
// "relations": [
// "一对一关联板材(Bancai)"
// ]
// },
// "Mupi": {
// "properties": {
// "id": "Integer",
// "name": "String",
// "you": "Boolean"
// },
// "relations": [
// "被板材关联(Bancai - mupi1/mupi2)"
// ]
// },
// "User": {
// "properties": {
// "id": "Integer",
// "name": "String",
// "andy": "String",
// "pass": "String",
// "role": "int"
// }
// },
// "Zujian": {
// "properties": {
// "id": "Integer",
// "name": "String"
// },
// "relations": [
// "一对多关联产品组件(Chanpin_zujian)"
// ]
// },
// "Bancai": {
// "properties": {
// "id": "Integer",
// "houdu": "Double"
// },
// "relations": [
// "多对一关联材质(Caizhi)",
// "多对一关联木皮(Mupi - mupi1/mupi2)",
// "一对一关联库存(Kucun)"
// ]
// },
// "Caizhi": {
// "properties": {
// "id": "Integer",
// "name": "String"
// },
// "relations": [
// "一对多关联板材(Bancai)"
// ]
// },
// "Chanpin": {
// "properties": {
// "id": "Integer",
// "bianhao": "String"
// },
// "relations": [
// "一对多关联订单产品(Dingdan_chanpin)",
// "一对多关联产品组件(Chanpin_zujian)"
// ]
// },
// "Chanpin_zujian": {
// "properties": {
// "id": "Integer",
// "one_howmany": "Double"
// },
// "relations": [
// "多对一关联产品(Chanpin)",
// "多对一关联组件(Zujian)",
// "多对一关联板材(Bancai)"
// ]
// }
// },
// "relationsSummary": [
// "订单(Dingdan) 1:N 订单产品(Dingdan_chanpin)",
// "订单(Dingdan) 1:N 订单组件(Dingdan_chanpin_zujian)",
// "产品(Chanpin) 1:N 产品组件(Chanpin_zujian)",
// "组件(Zujian) 1:N 产品组件(Chanpin_zujian)",
// "板材(Bancai) 1:1 库存(Kucun)",
// "材质(Caizhi) 1:N 板材(Bancai)"
// ]
//}
/**
* 优化后的关联解析函数(解决空值问题)
* @param {Object} data - 后端原始数据
* @returns {Object} 处理后的完整关联数据
*/
function __resolveDataReferences(data) {
// 创建ID映射表(带空值保护)
const idMaps = {};
Object.keys(data).forEach(key => {
if (Array.isArray(data[key])) {
idMaps[key] = new Map();
data[key].forEach(item => item.id && idMaps[key].set(item.id, item));
}
});
// 通用关联解析方法(带安全检测)
const resolveRef = (sourceArray, sourceKey, targetKey, refProperty) => {
if (!Array.isArray(sourceArray)) return;
sourceArray.forEach(item => {
const refObj = item[refProperty];
if (refObj && refObj.id && idMaps[targetKey]) {
const target = idMaps[targetKey].get(refObj.id);
if (target) {
// 建立正向引用
item[refProperty] = target;
// 建立反向引用(自动创建关联数组)
const reverseProp = sourceKey.endsWith('s') ?
sourceKey.slice(0, -1) + '_list' :
sourceKey + '_list';
if (!target[reverseProp]) target[reverseProp] = [];
if (!target[reverseProp].includes(item)) {
target[reverseProp].push(item);
}
}
}
});
};
// 处理特定关联(使用新安全方法)
// 订单 ↔ 订单产品
if (data.dingdans && data.dingdan_chanpins) {
resolveRef(data.dingdan_chanpins, 'dingdans', 'dingdans', 'dingdan');
}
// 订单 ↔ 订单组件
if (data.dingdans && data.dingdan_chanpin_zujians) {
resolveRef(data.dingdan_chanpin_zujians, 'dingdans', 'dingdans', 'dingdan');
}
// 产品 ↔ 产品组件
if (data.chanpins && data.chanpin_zujians) {
resolveRef(data.chanpin_zujians, 'chanpins', 'chanpins', 'chanpin');
}
// 组件 ↔ 产品组件
if (data.zujians && data.chanpin_zujians) {
resolveRef(data.chanpin_zujians, 'zujians', 'zujians', 'zujian');
}
// 材质 ↔ 板材
if (data.caizhis && data.bancais) {
resolveRef(data.bancais, 'caizhis', 'caizhis', 'caizhi');
}
// 板材 ↔ 库存(一对一)
if (data.bancais && data.kucuns) {
resolveRef(data.bancais, 'kucuns', 'kucuns', 'kucun');
resolveRef(data.kucuns, 'bancais', 'bancais', 'bancai'); // 反向引用
}
// 板材 ↔ 木皮(mupi1/mupi2)
if (data.bancais && data.mupis) {
resolveRef(data.bancais, 'mupis', 'mupis', 'mupi1');
resolveRef(data.bancais, 'mupis', 'mupis', 'mupi2');
}
// 订单产品 ↔ 产品
if (data.dingdan_chanpins && data.chanpins) {
resolveRef(data.dingdan_chanpins, 'chanpins', 'chanpins', 'chanpin');
}
// 订单组件 ↔ 产品组件
if (data.dingdan_chanpin_zujians && data.chanpin_zujians) {
resolveRef(data.dingdan_chanpin_zujians, 'chanpin_zujians', 'chanpin_zujians', 'chanpin_zujian');
}
// 订单组件 ↔ 板材
if (data.dingdan_chanpin_zujians && data.bancais) {
resolveRef(data.dingdan_chanpin_zujians, 'bancais', 'bancais', 'bancai');
}
// 进货 ↔ 相关实体
if (data.jinhuos) {
['dingdan', 'chanpin', 'zujian', 'bancai', 'user'].forEach(entity => {
const plural = entity + 's';
if (data[plural]) {
resolveRef(data.jinhuos, plural, plural, entity);
}
});
}
return data;
}
function resolveDataReferences(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);
}
}
}
}
}
console.log(data)
return data;
}
/**
* 数据管理器类,负责与后端API通信并管理数据
*/
class DataManager {
constructor(baseUrl) {
this.baseUrl = baseUrl;
this.data = {
bancais: [],
dingdans: [],
mupis: [],
chanpins: [],
kucuns: [],
dingdan_chanpin_zujians: [],
chanpin_zujians: [],
zujians: [],
caizhis: [],
dingdan_chanpins: [],
users: []
};
this.isSyncing = false;
this.lastSync = null;
// 回调注册表
this.callbacks = {
// 全局回调
all: [],
// 按实体类型分类的回调
bancais: [],
dingdan: [],
mupi: [],
chanpin: [],
kucun: [],
dingdan_chanpin_zujian: [],
chanpin_zujian: [],
zujian: [],
caizhi: [],
dingdan_chanpin: [],
user: [],
// ...其他实体
};
this.syncQueue = Promise.resolve();
}
/**
* 获取所有数据
* @returns {Promise<boolean>} 是否成功
*/
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');
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));
}
}
/**
* 执行CRUD操作并触发回调
*/
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');
// 自动同步数据
this.syncData();
// 触发操作成功的回调
this.triggerCallbacks(operation, entity, data);
return result;
} catch (error) {
console.error('CRUD error:', error);
// 触发操作失败的回调
this.triggerCallbacks(`${operation}_error`, entity, {
data,
error: error.message
});
throw error;
}
}
/**
* 执行CRUD操作
* @param {string} operation - 'add', 'delete', 'update'
* @param {string} entity - 实体名称单数性质(小写)
* @param {Object} data - 要发送的数据 后端要求数据格式为{属性: "值", 关联对象: {id:0}, 关联对象集: [{id:0}]}
* @returns {Promise<Object>} 响应结果
*/
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');
// 自动同步数据
this.syncQueue = this.syncQueue.then(async () => {
await this.syncData();
// 同步完成后触发操作回调
this.triggerCallbacks(operation, entity, data);
});
return result;
} catch (error) {
console.error('CRUD error:', error);
// 触发操作失败的回调
this.triggerCallbacks(`${operation}_error`, entity, {
data,
error: error.message
});
throw error;
}
}
/**
* 自动同步数据(防止频繁请求)
*/
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) {
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());
}
}
export { DataManager };
// 创建单例实例
//const dataManager = new DataManager('http://127.0.0.1:8080/KuCun2');
//// 初始化时获取所有数据
//dataManager.fetchAll().then(() => {
// console.log('Initial data loaded');
//});
// 导出数据对象,外部可以直接访问 data.bancais, data.dingdans 等
//export const data = dataManager.data;
//// 导出操作方法
//export const addEntity = dataManager.addEntity.bind(dataManager);
//export const updateEntity = dataManager.updateEntity.bind(dataManager);
//export const deleteEntity = dataManager.deleteEntity.bind(dataManager);
//export const fetchAll = dataManager.fetchAll.bind(dataManager);$(document).ready(function() {
// 获取全局的DataManager实例
const dataManager = window.parent.dataManager;
// 初始化页面元素
const $dingdanSelect = $('#dingdanSelect');
const $chanpinSelect = $('#chanpinSelect');
const $zujianSelect = $('#zujianSelect');
const $bancaiInfo = $('#bancaiInfo');
const $orderQuantityInput = $('#orderQuantityInput');
const $submitOrderBtn = $('#submitOrderBtn');
// 定义实体类型常量
const ENTITY_DINGDAN = 'dingdan';
const ENTITY_CHANPIN = 'chanpin';
const ENTITY_ZUJIAN = 'zujian';
const ENTITY_BANCAI = 'bancai';
const ENTITY_CAIZHI = 'caizhi';
const ENTITY_MUPI = 'mupi';
// 存储当前选中的实体ID
let currentDingdanId = null;
let currentChanpinId = null;
let currentZujianId = null;
// 初始化页面
initPage();
// 初始化页面函数
async function initPage() {
// 注册数据更新回调
dataManager.registerCallback('all', (operation, entity, data) => {
if (operation === 'refresh' || operation === 'add' || operation === 'update' || operation === 'delete') {
// 只刷新需要更新的部分
if (entity === ENTITY_DINGDAN) {
refreshDingdanList();
} else if (entity === 'dingdan_chanpin') {
if (currentDingdanId) {
refreshChanpinList(currentDingdanId);
}
} else if (entity === 'chanpin_zujian') {
if (currentChanpinId) {
refreshZujianList(currentChanpinId);
}
}
}
});
// 填充订单下拉框
await refreshDingdanList();
// 绑定事件
bindEvents();
}
// 绑定事件处理函数
function bindEvents() {
// 订单选择变化
$dingdanSelect.on('change', async function() {
currentDingdanId = $(this).val();
if (currentDingdanId) {
await refreshChanpinList(currentDingdanId);
$('#chanpinSelect').prop('disabled', false);
$('#addChanpinBtn').prop('disabled', false);
// 重置下级选择
$zujianSelect.prop('disabled', true).empty();
$bancaiInfo.text('');
$orderQuantityInput.val('').prop('disabled', true);
$submitOrderBtn.prop('disabled', true);
$('#addZujianBtn').prop('disabled', true);
currentChanpinId = null;
currentZujianId = null;
} else {
$chanpinSelect.prop('disabled', true).empty();
$zujianSelect.prop('disabled', true).empty();
$bancaiInfo.text('');
$orderQuantityInput.val('').prop('disabled', true);
$submitOrderBtn.prop('disabled', true);
$('#addChanpinBtn').prop('disabled', true);
$('#addZujianBtn').prop('disabled', true);
currentChanpinId = null;
currentZujianId = null;
}
});
// 产品选择变化
$chanpinSelect.on('change', async function() {
currentChanpinId = $(this).val();
if (currentChanpinId) {
await refreshZujianList(currentChanpinId);
$zujianSelect.prop('disabled', false);
$('#addZujianBtn').prop('disabled', false);
// 重置下级选择
$bancaiInfo.text('');
$orderQuantityInput.val('').prop('disabled', true);
$submitOrderBtn.prop('disabled', true);
currentZujianId = null;
} else {
$zujianSelect.prop('disabled', true).empty();
$bancaiInfo.text('');
$orderQuantityInput.val('').prop('disabled', true);
$submitOrderBtn.prop('disabled', true);
$('#addZujianBtn').prop('disabled', true);
currentZujianId = null;
}
});
// 组件选择变化
$zujianSelect.on('change', function() {
currentZujianId = $(this).val();
if (currentZujianId) {
displayBancaiInfo(currentZujianId);
$orderQuantityInput.prop('disabled', false);
$submitOrderBtn.prop('disabled', false);
} else {
$bancaiInfo.text('');
$orderQuantityInput.val('').prop('disabled', true);
$submitOrderBtn.prop('disabled', true);
}
});
// 新增订单按钮
$('#addDingdanBtn').on('click', function() {
showEntityModal('新增订单', ENTITY_DINGDAN, null, {
number: '',
xiadan: new Date().toISOString().split('T')[0],
jiaohuo: ''
});
});
// 添加产品按钮
$('#addChanpinBtn').on('click', function() {
if (!currentDingdanId) {
alert('请先选择订单');
return;
}
// 确保产品数据已加载
if (!dataManager.data.chanpins || dataManager.data.chanpins.length === 0) {
alert('产品数据未加载,请稍后再试');
return;
}
showEntityModal('添加产品', 'dingdan_chanpin', null, {
dingdan: { id: parseInt(currentDingdanId) },
chanpin: { id: '' },
shuliang: 1
});
});
// 添加组件按钮
$('#addZujianBtn').on('click', function() {
if (!currentChanpinId) {
alert('请先选择产品');
return;
}
// 确保组件数据已加载
if (!dataManager.data.zujians || dataManager.data.zujians.length === 0) {
alert('组件数据未加载,请稍后再试');
return;
}
// 确保板材数据已加载
if (!dataManager.data.bancais || dataManager.data.bancais.length === 0) {
alert('板材数据未加载,请稍后再试');
return;
}
showEntityModal('添加组件', 'chanpin_zujian', null, {
chanpin: { id: parseInt(currentChanpinId) },
zujian: { id: '' },
bancai: { id: '' },
one_howmany: 1
});
});
// 提交订单按钮
$submitOrderBtn.on('click', async function() {
const quantity = parseInt($orderQuantityInput.val());
if (!quantity || quantity <= 0) {
alert('请输入有效的订购数量');
return;
}
if (!currentDingdanId || !currentZujianId) {
alert('请完整选择订单、产品和组件');
return;
}
try {
// 获取当前选中的产品组件关联
const chanpinZujian = dataManager.data.chanpin_zujians.find(
cz => cz.id == currentZujianId
);
if (!chanpinZujian) {
throw new Error('未找到选中的产品组件关联');
}
// 检查是否已存在相同的订单组件订购记录
var existingOrder
if(dataManager.data.dingdan_chanpin_zujians.length>0){
existingOrder= dataManager.data.dingdan_chanpin_zujians.find(
dcz => dcz.dingdan&& dcz.dingdan.id == currentDingdanId &&
dcz.chanpin_zujian.id == currentZujianId
);
}
if (existingOrder) {
// 更新现有记录
await dataManager.updateEntity('dingdan_chanpin_zujian', {
id: existingOrder.id,
shuliang: quantity
});
} else {
// 创建新记录 - 直接关联chanpin_zujian
await dataManager.addEntity('dingdan_chanpin_zujian', {
dingdan: { id: parseInt(currentDingdanId) },
chanpin_zujian: { id: parseInt(currentZujianId) },
bancai:{id:parseInt(chanpinZujian.bancai.id)},// 直接关联
shuliang: quantity
});
}
// 创建进货记录
await createJinhuo(chanpinZujian, quantity);
alert('订购成功!');
resetForm();
} catch (error) {
console.error('订购失败:', error);
alert(`订购失败: ${error.message}`);
}
});
// 模态框保存按钮
$('#saveEntityBtn').on('click', saveEntity);
// 新建实体按钮(在创建实体模态框中)
$('#saveNewEntityBtn').on('click', saveNewEntity);
}
// 修改createJinhuo函数
async function createJinhuo(chanpinZujian, quantity) {
// 获取当前用户
// 确保获取正确的产品ID和组件ID
const chanpinId = chanpinZujian.chanpin?.id;
const zujianId = chanpinZujian.zujian?.id;
const bancaiId = chanpinZujian.bancai?.id;
if (!chanpinId || !zujianId || !bancaiId) {
throw new Error('产品组件关联数据不完整');
}
const jinhuoData = {
dingdan: { id: parseInt(currentDingdanId) },
chanpin: { id: chanpinId }, // 使用实际产品ID
zujian: { id: zujianId }, // 使用实际组件ID
bancai: { id: bancaiId }, // 使用实际板材ID
shuliang: quantity,
date: new Date().toISOString(),
user: { id: localStorage.getItem("userId") }
};
await dataManager.addEntity('jinhuo', jinhuoData);
}
// 重置表单
function resetForm() {
$orderQuantityInput.val('');
$submitOrderBtn.prop('disabled', true);
}
// 刷新订单列表
async function refreshDingdanList() {
const currentValue = $dingdanSelect.val();
$dingdanSelect.empty().append('<option value="">请选择订单</option>');
// 获取所有订单
const dingdans = dataManager.data.dingdans || [];
// 按下单日期降序排序
dingdans.sort((a, b) => new Date(b.xiadan) - new Date(a.xiadan));
// 填充下拉框
dingdans.forEach(dingdan => {
const option = $('<option>')
.val(dingdan.id)
.text(`${dingdan.number} (${formatDate(dingdan.xiadan)})`);
$dingdanSelect.append(option);
});
// 恢复之前的选择
if (currentValue) {
$dingdanSelect.val(currentValue);
}
}
// 刷新产品列表(基于订单)
async function refreshChanpinList(dingdanId) {
const currentValue = $chanpinSelect.val();
$chanpinSelect.empty().append('<option value="">请选择产品</option>');
// 获取订单对应的产品
const dingdan = dataManager.data.dingdans.find(d => d.id == dingdanId);
if (!dingdan || !dingdan.dingdan_chanpin) return;
// 填充下拉框
dingdan.dingdan_chanpin.forEach(dc => {
if (dc.chanpin) {
const option = $('<option>')
.val(dc.id)
.text(`${dc.chanpin.bianhao} (数量: ${dc.shuliang})`);
$chanpinSelect.append(option);
}
});
// 恢复之前的选择
if (currentValue) {
$chanpinSelect.val(currentValue);
}
}
// 刷新组件列表(基于产品)
async function refreshZujianList(dingdanChanpinId) {
const currentValue = $zujianSelect.val();
$zujianSelect.empty().append('<option value="">请选择组件</option>');
// 获取产品对应的组件
const chanpin = dataManager.data.chanpins.find(
cp => cp.dingdan_chanpin?.some(dc => dc.id == dingdanChanpinId)
);
if (!chanpin || !chanpin.chanpin_zujian) return;
// 填充下拉框
chanpin.chanpin_zujian.forEach(cz => {
if (cz.zujian) {
const option = $('<option>')
.val(cz.id)
.text(`${cz.zujian.name} (产量: ${cz.one_howmany})`);
$zujianSelect.append(option);
}
});
// 恢复之前的选择
if (currentValue) {
$zujianSelect.val(currentValue);
}
}
// 显示板材信息
function displayBancaiInfo(chanpinZujianId) {
// 获取产品组件
const chanpinZujian = dataManager.data.chanpin_zujians.find(
cz => cz.id == chanpinZujianId
);
if (!chanpinZujian || !chanpinZujian.bancai) {
$bancaiInfo.text('未找到板材信息');
return;
}
const bancai = chanpinZujian.bancai;
let info = `厚度: ${bancai.houdu}mm, 材质: `;
if (bancai.caizhi) {
info += bancai.caizhi.name;
}
if (bancai.mupi1) {
info += `, 木皮1: ${bancai.mupi1.name}${bancai.mupi1.you ? ' (油)' : ''}`;
}
if (bancai.mupi2) {
info += `, 木皮2: ${bancai.mupi2.name}${bancai.mupi2.you ? ' (油)' : ''}`;
}
$bancaiInfo.text(info);
}
// 显示实体模态框(添加产品/组件)
function showEntityModal(title, entityType, entityId, initialData) {
$('#modalTitle').text(title);
const $formFields = $('#formFields');
$formFields.empty();
// 根据实体类型生成表单字段
switch (entityType) {
case ENTITY_DINGDAN:
$formFields.append(`
<div class="form-group">
<label>订单编号</label>
<input type="text" class="form-control" name="number" value="${initialData.number || ''}" required>
</div>
<div class="form-group">
<label>下单日期</label>
<input type="date" class="form-control" name="xiadan" value="${initialData.xiadan || ''}" required>
</div>
<div class="form-group">
<label>交货日期</label>
<input type="date" class="form-control" name="jiaohuo" value="${initialData.jiaohuo || ''}">
</div>
`);
break;
case 'dingdan_chanpin': // 订单产品
const chanpins = dataManager.data.chanpins || [];
let chanpinOptions = '<option value="">选择产品</option>';
chanpinOptions += '<option value="new">+ 创建新产品</option>';
if (chanpins.length > 0) {
chanpins.forEach(cp => {
chanpinOptions += `
<option value="${cp.id}" ${initialData.chanpin.id == cp.id ? 'selected' : ''}>
${cp.bianhao}
</option>
`;
});
}
$formFields.append(`
<div class="form-group">
<label>产品</label>
<div class="input-group">
<select class="form-control" name="chanpin" id="chanpinSelectModal" required>
${chanpinOptions}
</select>
<span class="input-group-btn">
<button class="btn btn-info" id="createChanpinBtn">新建</button>
</span>
</div>
</div>
<div class="form-group">
<label>数量</label>
<input type="number" class="form-control" name="shuliang" value="${initialData.shuliang || 1}" min="1" required>
</div>
<input type="hidden" name="dingdan" value="${initialData.dingdan.id}">
`);
// 添加新建产品按钮事件
$('#createChanpinBtn').on('click', function() {
showCreateEntityModal('创建新产品', ENTITY_CHANPIN, null, {
bianhao: '',
name: ''
});
});
// 产品选择变化
$('#chanpinSelectModal').on('change', function() {
if ($(this).val() === 'new') {
showCreateEntityModal('创建新产品', ENTITY_CHANPIN, null, {
bianhao: '',
name: ''
});
$(this).val(''); // 重置选择
}
});
break;
case 'chanpin_zujian': // 产品组件
const zujians = dataManager.data.zujians || [];
const bancais = dataManager.data.bancais || [];
let zujianOptions = '<option value="">选择组件</option>';
zujianOptions += '<option value="new">+ 创建新组件</option>';
let bancaiOptions = '<option value="">选择板材</option>';
bancaiOptions += '<option value="new">+ 创建新板材</option>';
if (zujians.length > 0) {
zujians.forEach(zj => {
zujianOptions += `
<option value="${zj.id}" ${initialData.zujian.id == zj.id ? 'selected' : ''}>
${zj.name}
</option>
`;
});
}
if (bancais.length > 0) {
bancais.forEach(bc => {
let bcInfo = `厚度: ${bc.houdu}mm`;
if (bc.caizhi) bcInfo += `, 材质: ${bc.caizhi.name}`;
if (bc.mupi1) bcInfo += `, 木皮1: ${bc.mupi1.name}`;
if (bc.mupi2) bcInfo += `, 木皮2: ${bc.mupi2.name}`;
bancaiOptions += `
<option value="${bc.id}" ${initialData.bancai.id == bc.id ? 'selected' : ''}>
${bcInfo}
</option>
`;
});
}
$formFields.append(`
<div class="form-group">
<label>组件</label>
<div class="input-group">
<select class="form-control" name="zujian" id="zujianSelectModal" required>
${zujianOptions}
</select>
<span class="input-group-btn">
<button class="btn btn-info" id="createZujianBtn">新建</button>
</span>
</div>
</div>
<div class="form-group">
<label>板材</label>
<div class="input-group">
<select class="form-control" name="bancai" id="bancaiSelectModal" required>
${bancaiOptions}
</select>
<span class="input-group-btn">
<button class="btn btn-info" id="createBancaiBtn">新建</button>
</span>
</div>
</div>
<div class="form-group">
<label>一张板出多少组件</label>
<input type="number" class="form-control" name="one_howmany" value="${initialData.one_howmany || 1}" min="0.01" step="0.01" required>
</div>
<input type="hidden" name="chanpin" value="${initialData.chanpin.id}">
`);
// 添加新建按钮事件
$('#createZujianBtn').on('click', function() {
showCreateEntityModal('创建新组件', ENTITY_ZUJIAN, null, {
name: ''
});
});
$('#createBancaiBtn').on('click', function() {
showCreateEntityModal('创建新板材', ENTITY_BANCAI, null, {
houdu: 0.0
});
});
// 组件选择变化
$('#zujianSelectModal').on('change', function() {
if ($(this).val() === 'new') {
showCreateEntityModal('创建新组件', ENTITY_ZUJIAN, null, {
name: ''
});
$(this).val(''); // 重置选择
}
});
// 板材选择变化
$('#bancaiSelectModal').on('change', function() {
if ($(this).val() === 'new') {
showCreateEntityModal('创建新板材', ENTITY_BANCAI, null, {
houdu: 0.0
});
$(this).val(''); // 重置选择
}
});
break;
}
// 显示模态框
$('#entityModal').modal('show');
// 存储当前操作的实体信息
$('#entityModal').data('entity', {
type: entityType,
id: entityId
});
}
// 显示创建实体模态框(新产品/新组件/新板材)
function showCreateEntityModal(title, entityType, entityId, initialData) {
$('#createEntityModalTitle').text(title);
const $formFields = $('#createEntityFields');
$formFields.empty();
// 根据实体类型生成表单字段
switch (entityType) {
case ENTITY_CHANPIN: // 新产品
$formFields.append(`
<div class="form-group">
<label>产品编号</label>
<input type="text" class="form-control" name="bianhao" value="${initialData.bianhao || ''}" required>
</div>
`);
break;
case ENTITY_ZUJIAN: // 新组件
$formFields.append(`
<div class="form-group">
<label>组件名称</label>
<input type="text" class="form-control" name="name" value="${initialData.name || ''}" required>
</div>
`);
break;
case ENTITY_BANCAI: // 新板材
const caizhis = dataManager.data.caizhis || [];
const mupis = dataManager.data.mupis || [];
let caizhiOptions = '<option value="">选择材质</option>';
let mupi1Options = '<option value="">选择木皮1</option>';
let mupi2Options = '<option value="">选择木皮2</option>';
if (caizhis.length > 0) {
caizhis.forEach(cz => {
caizhiOptions += `<option value="${cz.id}">${cz.name}</option>`;
});
}
if (mupis.length > 0) {
mupis.forEach(mp => {
mupi1Options += `<option value="${mp.id}">${mp.name}${mp.you ? ' (油)' : ''}</option>`;
mupi2Options += `<option value="${mp.id}">${mp.name}${mp.you ? ' (油)' : ''}</option>`;
});
}
$formFields.append(`
<div class="form-group">
<label>厚度(mm)</label>
<input type="number" class="form-control" name="houdu" value="${initialData.houdu || 0.0}" step="0.1" min="0.1" required>
</div>
<div class="form-group">
<label>材质</label>
<div class="input-group">
<select class="form-control" name="caizhi" required>
${caizhiOptions}
</select>
<span class="input-group-btn">
<button class="btn btn-default" id="createCaizhiBtn">新建</button>
</span>
</div>
</div>
<div class="form-group">
<label>木皮1</label>
<div class="input-group">
<select class="form-control" name="mupi1">
${mupi1Options}
</select>
<span class="input-group-btn">
<button class="btn btn-default" id="createMupiBtn">新建</button>
</span>
</div>
</div>
<div class="form-group">
<label>木皮2</label>
<div class="input-group">
<select class="form-control" name="mupi2">
${mupi2Options}
</select>
<span class="input-group-btn">
<button class="btn btn-default" id="createMupiBtn2">新建</button>
</span>
</div>
</div>
`);
// 添加新建材质按钮事件
$('#createCaizhiBtn').on('click', function() {
showCreateEntityModal('创建新材质', ENTITY_CAIZHI, null, {
name: ''
});
});
// 添加新建木皮按钮事件
$('#createMupiBtn, #createMupiBtn2').on('click', function() {
showCreateEntityModal('创建新木皮', ENTITY_MUPI, null, {
name: '',
you: false
});
});
break;
case ENTITY_CAIZHI: // 新材质
$formFields.append(`
<div class="form-group">
<label>材质名称</label>
<input type="text" class="form-control" name="name" value="${initialData.name || ''}" required>
</div>
`);
break;
case ENTITY_MUPI: // 新木皮
$formFields.append(`
<div class="form-group">
<label>木皮名称</label>
<input type="text" class="form-control" name="name" value="${initialData.name || ''}" required>
</div>
<div class="form-group">
<label>
<input type="checkbox" name="you" ${initialData.you ? 'checked' : ''}>
是否有油漆
</label>
</div>
`);
break;
}
// 显示模态框
$('#createEntityModal').modal('show');
// 存储当前操作的实体信息
$('#createEntityModal').data('entity', {
type: entityType,
id: entityId
});
}
// 保存实体(在添加产品/组件模态框中)
async function saveEntity() {
const $saveBtn = $('#saveEntityBtn');
const originalText = $saveBtn.text();
try {
// 显示加载状态
$saveBtn.prop('disabled', true).html('<i class="fa fa-spinner fa-spin"></i> 保存中...');
const entityInfo = $('#entityModal').data('entity');
const formData = getFormData('#entityForm');
let result;
if (entityInfo.id) {
// 更新实体
result = await dataManager.updateEntity(entityInfo.type, {
id: entityInfo.id,
...formData
});
} else {
// 新增实体
result = await dataManager.addEntity(entityInfo.type, formData);
}
if (result.status === 200) {
$('#entityModal').modal('hide');
// 根据操作类型刷新对应的下拉列表
switch (entityInfo.type) {
case ENTITY_DINGDAN:
await refreshDingdanList();
break;
case 'dingdan_chanpin':
if (formData.dingdan && formData.dingdan.id) {
await refreshChanpinList(formData.dingdan.id);
}
break;
case 'chanpin_zujian':
if (formData.chanpin && formData.chanpin.id) {
await refreshZujianList(formData.chanpin.id);
}
break;
}
} else {
alert(`保存失败: ${result.text}`);
}
} catch (error) {
console.error('保存实体时出错:', error);
alert(`保存失败: ${error.message}`);
} finally {
// 恢复按钮状态
$saveBtn.prop('disabled', false).text(originalText);
}
}
// 保存新实体(在创建实体模态框中)
async function saveNewEntity() {
const $saveBtn = $('#saveNewEntityBtn');
const originalText = $saveBtn.text();
try {
// 显示加载状态
$saveBtn.prop('disabled', true).html('<i class="fa fa-spinner fa-spin"></i> 保存中...');
const entityInfo = $('#createEntityModal').data('entity');
const formData = getFormData('#createEntityForm');
// 新增实体
const result = await dataManager.addEntity(entityInfo.type, formData);
if (result.status === 200) {
$('#createEntityModal').modal('hide');
// 刷新父模态框中的下拉框
refreshParentDropdown(entityInfo.type, result.data.id);
} else {
alert(`创建失败: ${result.text}`);
}
} catch (error) {
console.error('创建实体时出错:', error);
alert(`创建失败: ${error.message}`);
} finally {
// 恢复按钮状态
$saveBtn.prop('disabled', false).text(originalText);
}
}
// 刷新父模态框中的下拉框
function refreshParentDropdown(entityType, newEntityId) {
// 获取父模态框中的相关下拉框
const $parentModal = $('#entityModal');
if (!$parentModal.is(':visible')) return;
const parentEntityType = $parentModal.data('entity').type;
// 根据实体类型刷新对应的下拉框
if (parentEntityType === 'dingdan_chanpin' && entityType === ENTITY_CHANPIN) {
// 刷新产品下拉框
const $select = $('#chanpinSelectModal');
$select.append(`<option value="${newEntityId}" selected>新建产品</option>`);
}
else if (parentEntityType === 'chanpin_zujian') {
if (entityType === ENTITY_ZUJIAN) {
// 刷新组件下拉框
const $select = $('#zujianSelectModal');
$select.append(`<option value="${newEntityId}" selected>新建组件</option>`);
}
else if (entityType === ENTITY_BANCAI) {
// 刷新板材下拉框
const $select = $('#bancaiSelectModal');
$select.append(`<option value="${newEntityId}" selected>新建板材</option>`);
}
else if (entityType === ENTITY_CAIZHI) {
// 刷新材质下拉框(在板材创建中)
const $select = $parentModal.find('select[name="caizhi"]');
$select.append(`<option value="${newEntityId}" selected>新建材质</option>`);
}
else if (entityType === ENTITY_MUPI) {
// 刷新木皮下拉框(在板材创建中)
const $select = $parentModal.find('select[name="mupi1"], select[name="mupi2"]');
$select.append(`<option value="${newEntityId}" selected>新建木皮</option>`);
}
}
}
// 获取表单数据
function getFormData(selector) {
const formData = {};
$(`${selector} :input`).each(function() {
const $input = $(this);
const name = $input.attr('name');
const type = $input.attr('type');
if (name) {
if (type === 'checkbox') {
formData[name] = $input.prop('checked');
} else if (type === 'radio') {
if ($input.prop('checked')) {
formData[name] = $input.val();
}
} else {
// 处理关联对象
if (name === 'chanpin' || name === 'zujian' ||
name === 'bancai' || name === 'dingdan' ||
name === 'caizhi' || name === 'mupi1' || name === 'mupi2') {
formData[name] = { id: parseInt($input.val()) };
} else if (name === 'one_howmany' || name === 'houdu') {
formData[name] = parseFloat($input.val());
} else if (name === 'shuliang') {
formData[name] = parseInt($input.val());
} else {
formData[name] = $input.val();
}
}
}
});
return formData;
}
// 日期格式化辅助函数
function formatDate(dateString) {
if (!dateString) return '';
const date = new Date(dateString);
return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`;
}
}); 创建进货记录时,产品.id 搞错了