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')