diff --git a/frontend/assets/styles.css b/frontend/assets/styles.css index 160a583..3d64e62 100644 --- a/frontend/assets/styles.css +++ b/frontend/assets/styles.css @@ -43,7 +43,7 @@ body{margin:0;background:var(--bg);color:var(--text);font-family:Inter,system-ui [data-theme="light"] .content-header{background:#f5f7fa !important} #breadcrumb{color:var(--text-2)} #actions{position:relative;z-index:999;display:flex;align-items:center;gap:8px} -.view{position:relative;padding:20px;flex:1;overflow-y:auto;overflow-x:hidden;background:var(--bg);min-height:100%} +.view{position:relative;padding:20px;flex:1;overflow-y:auto;overflow-x:hidden;background:var(--bg);min-height:0} .card{background:var(--surface-2);border:1px solid var(--border);border-radius:12px;padding:16px} .grid{display:grid;gap:12px} .grid.cols-2{grid-template-columns:repeat(2,minmax(0,1fr))} diff --git a/frontend/js/components/customer-order.js b/frontend/js/components/customer-order.js index 68b85b1..664b7ef 100644 --- a/frontend/js/components/customer-order.js +++ b/frontend/js/components/customer-order.js @@ -128,6 +128,7 @@ ${order.quantity || 0} ${order.unit_price || 0} + @@ -190,22 +191,41 @@ } } + let currentEditId = null; + function openModal(order = null) { const modal = document.getElementById('order-modal'); const title = document.getElementById('modal-title'); - title.textContent = '新增订单'; - document.getElementById('order-form').reset(); - - // 设置默认日期为今天 - const today = new Date().toISOString().split('T')[0]; - document.getElementById('order-date').value = today; - - // 清空物料列表并添加一行 + // 清空物料列表 const container = document.getElementById('materials-container'); container.innerHTML = ''; materialRowIndex = 0; - addMaterialRow(); + + if (order) { + // 编辑模式 + title.textContent = '编辑订单'; + currentEditId = order.id; + + document.getElementById('order-date').value = order.order_date || ''; + document.getElementById('order-no').value = order.order_no || ''; + document.getElementById('customer-name').value = order.customer_name || ''; + + // 添加物料信息 + addMaterialRow(order.material || '', order.quantity || '', order.unit_price || ''); + } else { + // 新增模式 + title.textContent = '新增订单'; + currentEditId = null; + document.getElementById('order-form').reset(); + + // 设置默认日期为今天 + const today = new Date().toISOString().split('T')[0]; + document.getElementById('order-date').value = today; + + // 添加一行空物料 + addMaterialRow(); + } modal.style.display = 'flex'; } @@ -270,11 +290,16 @@ } try { - // 为每个物料创建一条订单记录 - let successCount = 0; - for (const mat of materials) { - const res = await fetch('/api/customer-orders', { - method: 'POST', + if (currentEditId) { + // 编辑模式:只能编辑单条记录 + if (materials.length !== 1) { + API.toast('编辑模式下只能有一个物料', 'error'); + return; + } + + const mat = materials[0]; + const res = await fetch(`/api/customer-orders/${currentEditId}`, { + method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ order_date: orderDate, @@ -289,22 +314,49 @@ const data = await res.json(); if (res.ok && data.ok) { - successCount++; + API.toast('更新成功', 'success'); + closeModal(); + await loadOrders(); } else { - console.error('保存物料失败:', mat.material, data.error); + API.toast(data.error || '更新失败', 'error'); } - } - - if (successCount === materials.length) { - API.toast(`订单保存成功,共 ${successCount} 个物料`, 'success'); - closeModal(); - await loadOrders(); - } else if (successCount > 0) { - API.toast(`部分保存成功(${successCount}/${materials.length})`, 'warning'); - closeModal(); - await loadOrders(); } else { - API.toast('保存失败', 'error'); + // 新增模式:为每个物料创建一条订单记录 + let successCount = 0; + for (const mat of materials) { + const res = await fetch('/api/customer-orders', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + order_date: orderDate, + order_no: orderNo, + customer_name: customerName, + material: mat.material, + quantity: mat.quantity, + unit_price: mat.unit_price + }) + }); + + const data = await res.json(); + + if (res.ok && data.ok) { + successCount++; + } else { + console.error('保存物料失败:', mat.material, data.error); + } + } + + if (successCount === materials.length) { + API.toast(`订单保存成功,共 ${successCount} 个物料`, 'success'); + closeModal(); + await loadOrders(); + } else if (successCount > 0) { + API.toast(`部分保存成功(${successCount}/${materials.length})`, 'warning'); + closeModal(); + await loadOrders(); + } else { + API.toast('保存失败', 'error'); + } } } catch (err) { console.error('保存订单失败:', err); @@ -336,11 +388,30 @@ } } + async function editOrder(id) { + try { + const res = await fetch('/api/customer-orders'); + const data = await res.json(); + + const order = data.list.find(o => o.id === id); + if (!order) { + API.toast('订单不存在', 'error'); + return; + } + + openModal(order); + } catch (err) { + console.error('加载订单失败:', err); + API.toast('加载失败', 'error'); + } + } + // 暴露给全局 window.CustomerOrder = { openModal, closeModal, saveOrder, + editOrder, deleteOrder, addMaterialRow, removeMaterialRow diff --git a/init_customer_orders.py b/init_customer_orders.py index cb7b94d..86829f7 100644 --- a/init_customer_orders.py +++ b/init_customer_orders.py @@ -23,14 +23,12 @@ orders_data = [ # 2025/4/28 - CGDD001695 {'order_date': '2025-04-28', 'order_no': 'CGDD001695', 'customer_name': '易泰勒', 'material': 'ETAP05\n基站-5.0\nETAP05', 'quantity': 950, 'unit_price': 315.19}, {'order_date': '2025-04-28', 'order_no': 'CGDD001695', 'customer_name': '易泰勒', 'material': 'WD1MK0SMD0551\n蓝牙模块\nPCBCOMPONENT_1_-_DUPLICATE', 'quantity': 950, 'unit_price': 1.3}, - {'order_date': '2025-04-28', 'order_no': 'CGDD001695', 'customer_name': '易泰勒', 'material': 'WA0000000040\nPCBA', 'quantity': 4750, 'unit_price': 8.05}, - {'order_date': '2025-04-28', 'order_no': 'CGDD001695', 'customer_name': '易泰勒', 'material': 'CH6121-MODULE-V14', 'quantity': 4750, 'unit_price': 8.05}, + {'order_date': '2025-04-28', 'order_no': 'CGDD001695', 'customer_name': '易泰勒', 'material': 'WA0000000040\nPCBA\nCH6121-MODULE-V14', 'quantity': 4750, 'unit_price': 8.05}, # 2025/9/4 - CGDD002429 {'order_date': '2025-09-04', 'order_no': 'CGDD002429', 'customer_name': '易泰勒', 'material': 'ETAP05\n基站-5.0\nETAP05', 'quantity': 1500, 'unit_price': 315.19}, {'order_date': '2025-09-04', 'order_no': 'CGDD002429', 'customer_name': '易泰勒', 'material': 'WD1MK0SMD0551\n蓝牙模块\nPCBCOMPONENT_1_-_DUPLICATE', 'quantity': 1500, 'unit_price': 1.3}, - {'order_date': '2025-09-04', 'order_no': 'CGDD002429', 'customer_name': '易泰勒', 'material': 'WA0000000040\nPCBA', 'quantity': 7500, 'unit_price': 8.05}, - {'order_date': '2025-09-04', 'order_no': 'CGDD002429', 'customer_name': '易泰勒', 'material': 'CH6121-MODULE-V14', 'quantity': 7500, 'unit_price': 8.05}, + {'order_date': '2025-09-04', 'order_no': 'CGDD002429', 'customer_name': '易泰勒', 'material': 'WA0000000040\nPCBA\nCH6121-MODULE-V14', 'quantity': 7500, 'unit_price': 8.05}, {'order_date': '2025-09-04', 'order_no': 'CGDD002429', 'customer_name': '易泰勒', 'material': 'AP-ET010\n基站-5.0\nETAP05', 'quantity': 500, 'unit_price': 315.19}, {'order_date': '2025-09-04', 'order_no': 'CGDD002429', 'customer_name': '易泰勒', 'material': 'WD1MK0SMD0551\n蓝牙模块\nPCBCOMPONENT_1_-_DUPLICATE', 'quantity': 500, 'unit_price': 1.3}, {'order_date': '2025-09-04', 'order_no': 'CGDD002429', 'customer_name': '易泰勒', 'material': 'WA0000000040\nPCBA\nCH6121-MODULE-V14', 'quantity': 2500, 'unit_price': 8.05}, diff --git a/server/app.py b/server/app.py index f2e9fe8..444eb17 100644 --- a/server/app.py +++ b/server/app.py @@ -3683,6 +3683,61 @@ def create_customer_order(): return jsonify({'ok': True, 'id': order_id, 'message': '订单创建成功'}) +@app.put('/api/customer-orders/') +@require_login +@require_any_role('superadmin') +def update_customer_order(order_id): + """更新客户订单""" + data = request.get_json() + + order_date = data.get('order_date', '').strip() + order_no = data.get('order_no', '').strip() + customer_name = data.get('customer_name', '').strip() + material = data.get('material', '').strip() + quantity = data.get('quantity') + unit_price = data.get('unit_price') + + if not all([order_date, order_no, customer_name, material, quantity is not None, unit_price is not None]): + return jsonify({'error': '请填写所有必填项'}), 400 + + try: + quantity = int(quantity) + unit_price = float(unit_price) + except (ValueError, TypeError): + return jsonify({'error': '数量和单价必须是有效数字'}), 400 + + if quantity <= 0: + return jsonify({'error': '数量必须大于0'}), 400 + + if unit_price < 0: + return jsonify({'error': '单价不能为负数'}), 400 + + conn = get_db() + c = conn.cursor() + + # 检查订单是否存在 + c.execute('SELECT id FROM customer_orders WHERE id=?', (order_id,)) + if not c.fetchone(): + conn.close() + return jsonify({'error': '订单不存在'}), 404 + + # 更新订单 + c.execute('''UPDATE customer_orders + SET order_date=?, order_no=?, customer_name=?, material=?, + quantity=?, unit_price=?, updated_at=?, updated_by=? + WHERE id=?''', + (order_date, order_no, customer_name, material, quantity, unit_price, + datetime.now(timezone(timedelta(hours=8))).isoformat(), + session.get('username', 'unknown'), order_id)) + + conn.commit() + conn.close() + + log('update_customer_order', f'订单ID: {order_id}, 客户: {customer_name}, 订单号: {order_no}') + + return jsonify({'ok': True, 'message': '订单更新成功'}) + + @app.delete('/api/customer-orders/') @require_login @require_any_role('superadmin')