Browse Source

fleat: order

igb 3 weeks ago
parent
commit
dcba8d32a9
7 changed files with 1903 additions and 0 deletions
  1. 21 0
      get_customer_contacts.php
  2. 23 0
      get_product_info.php
  3. 417 0
      order.php
  4. 467 0
      order_add.php
  5. 273 0
      order_details.php
  6. 525 0
      order_edit.php
  7. 177 0
      order_save.php

+ 21 - 0
get_customer_contacts.php

@@ -0,0 +1,21 @@
+<?php
+require_once 'conn.php';
+checkLogin();
+
+header('Content-Type: application/json');
+$customer_id = isset($_GET['customer_id']) ? (int)$_GET['customer_id'] : 0;
+
+$sql = "SELECT id, contact_name FROM customer_contact WHERE customer_id = $customer_id";
+
+$result = mysqli_query($conn, $sql);
+
+$contacts = [];
+while ($row = mysqli_fetch_assoc($result)) {
+    $contacts[] = [
+        'id' => $row['id'],
+        'contact_name' => textUncode($row['contact_name'])
+    ];
+}
+
+echo json_encode($contacts);
+?>

+ 23 - 0
get_product_info.php

@@ -0,0 +1,23 @@
+<?php
+require_once 'conn.php';
+checkLogin();
+
+header('Content-Type: application/json');
+$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
+
+$sql = "SELECT p.unit, pr.price 
+        FROM products p 
+        LEFT JOIN price pr ON p.id = pr.productId AND pr.AreaId = 0 
+        WHERE p.id = $id ORDER BY pr.num ASC LIMIT 1";
+
+$result = mysqli_query($conn, $sql);
+
+if ($row = mysqli_fetch_assoc($result)) {
+    echo json_encode([
+        'unit' => $row['unit'],
+        'price' => $row['price'] ?? '0.00'
+    ]);
+} else {
+    echo json_encode(['error' => 'Product not found']);
+}
+?>

+ 417 - 0
order.php

@@ -0,0 +1,417 @@
+<?php
+require_once 'conn.php';
+checkLogin();
+
+// 辅助函数
+function textDecode($str) {
+    return htmlspecialchars_decode($str, ENT_QUOTES);
+}
+
+function htmlDecode($str) {
+    return htmlspecialchars_decode($str, ENT_QUOTES);
+}
+
+$act = $_GET['act'] ?? '';
+$urlStr = '';
+
+// 处理批量操作
+if ($act == "postchk") {
+    if (isset($_POST['chkbox']) && isset($_POST['chkact'])) {
+        $chkact = $_POST['chkact'];
+        $ids = implode(',', array_map('intval', $_POST['chkbox']));
+        $employee_id = $_SESSION['employee_id'];
+
+        switch($chkact) {
+            case "0":
+            case "1":
+            case "2":
+            case "3":
+            case "4":
+            case "5":
+                $sql = "UPDATE orders SET order_status = $chkact WHERE id IN ($ids) AND employee_id = $employee_id";
+                break;
+            case "-1":
+                // 删除订单记录和订单项记录(依靠外键级联删除)
+                $sql = "DELETE FROM orders WHERE id IN ($ids) AND employee_id = $employee_id";
+                break;
+        }
+
+        if (isset($sql)) {
+            mysqli_query($conn, $sql);
+        }
+
+        $keys = urlencode($_GET['Keys'] ?? '');
+        $page = $_GET['Page'] ?? '';
+        header("Location: ?keys=$keys&Page=$page$urlStr");
+        exit;
+    }
+}
+
+// 处理筛选条件
+$fliterStatus = $_GET['fliterStatus'] ?? '';
+$fliterPayment = $_GET['fliterPayment'] ?? '';
+$fliterCustomer = $_GET['fliterCustomer'] ?? '';
+$fliterFromDate = $_GET['fliterFromDate'] ?? '';
+$fliterToDate = $_GET['fliterToDate'] ?? '';
+
+$fliterStr = "";
+
+if (!empty($fliterStatus)) {
+    $fliterStr .= " AND o.order_status = " . intval($fliterStatus);
+    $urlStr .= "&fliterStatus=" . $fliterStatus;
+}
+
+if (!empty($fliterPayment)) {
+    $fliterStr .= " AND o.payment_status = " . intval($fliterPayment);
+    $urlStr .= "&fliterPayment=" . $fliterPayment;
+}
+
+if (!empty($fliterCustomer)) {
+    $fliterStr .= " AND o.customer_id = " . intval($fliterCustomer);
+    $urlStr .= "&fliterCustomer=" . $fliterCustomer;
+}
+
+if (!empty($fliterFromDate)) {
+    $fliterStr .= " AND o.order_date >= '" . mysqli_real_escape_string($conn, $fliterFromDate) . "'";
+    $urlStr .= "&fliterFromDate=" . urlencode($fliterFromDate);
+}
+
+if (!empty($fliterToDate)) {
+    $fliterStr .= " AND o.order_date <= '" . mysqli_real_escape_string($conn, $fliterToDate) . " 23:59:59'";
+    $urlStr .= "&fliterToDate=" . urlencode($fliterToDate);
+}
+
+// 搜索和排序
+$keys = $_GET['Keys'] ?? '';
+$keyscode = mysqli_real_escape_string($conn, $keys);
+$page = $_GET['Page'] ?? 1;
+$ord = $_GET['Ord'] ?? '';
+
+$ordStr = !empty($ord) ? "$ord," : "";
+
+// 构建查询SQL
+$employee_id = $_SESSION['employee_id'];
+$sqlStr = "SELECT o.*, c.cs_company, cc.contact_name
+           FROM orders o
+           LEFT JOIN customer c ON o.customer_id = c.id
+           LEFT JOIN customer_contact cc ON o.contact_id = cc.id
+           WHERE o.employee_id = $employee_id";
+
+if (!empty($keyscode)) {
+    $sqlStr .= " AND (o.order_code LIKE '%$keyscode%'
+           OR c.cs_company LIKE '%$keyscode%'
+           OR cc.contact_name LIKE '%$keyscode%')";
+}
+
+$sqlStr .= " $fliterStr ORDER BY {$ordStr}o.created_at DESC";
+
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <title>订单列表</title>
+    <link rel="stylesheet" href="css/common.css" type="text/css" />
+    <link rel="stylesheet" href="css/alert.css" type="text/css" />
+    <script src="js/jquery-1.7.2.min.js"></script>
+    <script src="js/js.js"></script>
+    <style>
+        body {
+            margin: 0;
+            padding: 20px;
+            background: #fff;
+        }
+        #man_zone {
+            margin-left: 0;
+        }
+        .status-badge {
+            display: inline-block;
+            padding: 3px 8px;
+            border-radius: 3px;
+            font-size: 12px;
+            color: white;
+        }
+        .status-0 { background-color: #999; }
+        .status-1 { background-color: #5bc0de; }
+        .status-2 { background-color: #337ab7; }
+        .status-3 { background-color: #f0ad4e; }
+        .status-4 { background-color: #5cb85c; }
+        .status-5 { background-color: #28a745; }
+
+        .payment-badge {
+            display: inline-block;
+            padding: 3px 8px;
+            border-radius: 3px;
+            font-size: 12px;
+            color: white;
+        }
+        .payment-0 { background-color: #d9534f; }
+        .payment-1 { background-color: #f0ad4e; }
+        .payment-2 { background-color: #5cb85c; }
+
+        /* Date picker styling */
+        .date-input {
+            padding: 5px;
+            border: 1px solid #ccc;
+            border-radius: 3px;
+        }
+    </style>
+</head>
+<body>
+<div id="man_zone">
+    <div class="fastSelect clear">
+        <H1>筛选条件</H1>
+        <div class="selectItem">
+            <label>订单状态</label>
+            <select name="fliterStatus" class="filterSearch">
+                <option value="">全部状态</option>
+                <option value="0"<?= $fliterStatus == "0" ? ' selected' : '' ?>>已取消</option>
+                <option value="1"<?= $fliterStatus == "1" ? ' selected' : '' ?>>待确认</option>
+                <option value="2"<?= $fliterStatus == "2" ? ' selected' : '' ?>>已确认</option>
+                <option value="3"<?= $fliterStatus == "3" ? ' selected' : '' ?>>生产中</option>
+                <option value="4"<?= $fliterStatus == "4" ? ' selected' : '' ?>>已发货</option>
+                <option value="5"<?= $fliterStatus == "5" ? ' selected' : '' ?>>已完成</option>
+            </select>
+        </div>
+        <div class="selectItem">
+            <label>付款状态</label>
+            <select name="fliterPayment" class="filterSearch">
+                <option value="">全部付款状态</option>
+                <option value="0"<?= $fliterPayment == "0" ? ' selected' : '' ?>>未付款</option>
+                <option value="1"<?= $fliterPayment == "1" ? ' selected' : '' ?>>部分付款</option>
+                <option value="2"<?= $fliterPayment == "2" ? ' selected' : '' ?>>已付清</option>
+            </select>
+        </div>
+        <div class="selectItem">
+            <label>客户筛选</label>
+            <select name="fliterCustomer" class="filterSearch">
+                <option value="">全部客户</option>
+                <?php
+                $employee_id = $_SESSION['employee_id'];
+                $customerSql = "SELECT id, cs_company FROM customer WHERE cs_belong = $employee_id ORDER BY cs_company";
+                $customerResult = mysqli_query($conn, $customerSql);
+                while ($customerRow = mysqli_fetch_assoc($customerResult)) {
+                    $selected = ($fliterCustomer == $customerRow['id']) ? ' selected' : '';
+                    echo "<option value=\"{$customerRow['id']}\"$selected>" . htmlspecialcharsFix($customerRow['cs_company']) . "</option>";
+                }
+                ?>
+            </select>
+        </div>
+        <div class="selectItem">
+            <label>订单日期 从</label>
+            <input type="date" name="fliterFromDate" class="date-input filterSearch" value="<?= $fliterFromDate ?>">
+            <label>到</label>
+            <input type="date" name="fliterToDate" class="date-input filterSearch" value="<?= $fliterToDate ?>">
+        </div>
+        <div class="inputSearch">
+            <input type="text" id="keys" class="inputTxt"
+                value="<?= empty($keyscode) ? '请输入搜索关键词' : $keyscode ?>"
+                onFocus="if(this.value == '<?= empty($keyscode) ? '请输入搜索关键词' : $keyscode ?>'){this.value='';}"
+                onBlur="if(this.value == ''){this.value='<?= empty($keyscode) ? '请输入搜索关键词' : $keyscode ?>';}"
+                onKeyDown="if(event.keyCode==13){location.href='?Keys='+escape(document.getElementById('keys').value)}" />
+            <input type="button" id="searchgo" class="searchgo" value="go"
+                onClick="location.href='?Keys='+escape(document.getElementById('keys').value)" />
+        </div>
+    </div>
+
+    <form id="form1" method="post" action="?act=postchk&Keys=<?= $keys ?>&Page=<?= $page ?>" onSubmit="return false">
+        <div align="right" style="margin-bottom: 10px;">
+            <input type="button" value="新增订单" class="btn1" onClick="location.href='order_add.php'" />
+        </div>
+
+        <div class="table2 em<?= $_SESSION['employee_id'] ?>">
+            <div class="theader">
+                <div class="col1"><input type="checkbox" name="chkall" id="chkall" onClick="chkboxall(this,'chkbox')" /></div>
+                <div class="col2">序号</div>
+                <div class="col3">订单编号</div>
+                <div class="col4">客户</div>
+                <div class="col5">联系人</div>
+                <div class="col6">订单日期</div>
+                <div class="col7">订单状态</div>
+                <div class="col8">付款状态</div>
+                <div class="col9">订单金额</div>
+                <div class="col10">操作</div>
+            </div>
+
+            <?php
+            // 设置每页显示记录数
+            $pageSize = 20;
+
+            // 获取总记录数
+            $employee_id = $_SESSION['employee_id'];
+            $countSql = "SELECT COUNT(*) AS total FROM orders o
+                         WHERE o.employee_id = $employee_id";
+            if (!empty($keyscode)) {
+                $countSql .= " AND (o.order_code LIKE '%$keyscode%'
+                             OR o.customer_id IN (SELECT id FROM customer WHERE cs_company LIKE '%$keyscode%'))";
+            }
+            $countSql .= $fliterStr;
+
+            $countResult = mysqli_query($conn, $countSql);
+            $countRow = mysqli_fetch_assoc($countResult);
+            $totalRecords = $countRow['total'];
+
+            // 计算总页数
+            $totalPages = ceil($totalRecords / $pageSize);
+            if ($totalPages < 1) $totalPages = 1;
+
+            // 验证当前页码
+            $page = (int)$page;
+            if ($page < 1) $page = 1;
+            if ($page > $totalPages) $page = $totalPages;
+
+            // 计算起始记录
+            $offset = ($page - 1) * $pageSize;
+
+            // 添加分页条件
+            $sqlStr .= " LIMIT $offset, $pageSize";
+
+            $result = mysqli_query($conn, $sqlStr);
+
+            if (mysqli_num_rows($result) > 0) {
+                $tempNum = ($page - 1) * $pageSize;
+                while ($row = mysqli_fetch_assoc($result)) {
+                    $tempNum++;
+                    ?>
+                    <div class="tline">
+                        <div class="col1" align="center"><input type="checkbox" name="chkbox[]" value="<?= $row['id'] ?>" /></div>
+                        <div class="col2"><?= $tempNum ?></div>
+                        <div class="col3"><?= htmlspecialcharsFix($row['order_code']) ?></div>
+                        <div class="col4"><?= htmlspecialcharsFix($row['cs_company']) ?></div>
+                        <div class="col5"><?= htmlspecialcharsFix($row['contact_name']) ?></div>
+                        <div class="col6"><?= date('Y-m-d', strtotime($row['order_date'])) ?></div>
+                        <div class="col7">
+                            <?php
+                            $statusMap = [
+                                0 => '已取消',
+                                1 => '待确认',
+                                2 => '已确认',
+                                3 => '生产中',
+                                4 => '已发货',
+                                5 => '已完成'
+                            ];
+                            echo '<span class="status-badge status-' . $row['order_status'] . '">' .
+                                 $statusMap[$row['order_status']] . '</span>';
+                            ?>
+                        </div>
+                        <div class="col8">
+                            <?php
+                            $paymentMap = [
+                                0 => '未付款',
+                                1 => '部分付款',
+                                2 => '已付清'
+                            ];
+                            echo '<span class="payment-badge payment-' . $row['payment_status'] . '">' .
+                                 $paymentMap[$row['payment_status']] . '</span>';
+                            ?>
+                        </div>
+                        <div class="col9"><?= number_format($row['total_amount'], 2) . ' ' . $row['currency'] ?></div>
+                        <div class="col10">
+                            <a href="order_edit.php?id=<?= $row['id'] ?>&keys=<?= $keys ?>&page=<?= $page ?>" class="ico_edit ico">修改</a>
+                            <a href="order_details.php?id=<?= $row['id'] ?>" class="ico_view ico">查看详情</a>
+                        </div>
+                    </div>
+                    <?php
+                }
+            } else {
+                if (empty($keys) && empty($fliterStr)) {
+                    echo '<div class="tline"><div align="center" colspan="10">当前暂无订单记录</div></div>';
+                } else {
+                    echo '<div class="tline"><div align="center" colspan="10"><a href="?">没有找到匹配的订单记录,点击返回</a></div></div>';
+                }
+            }
+            ?>
+
+            <div colspan="10">
+                <div class="showpagebox">
+                    <?php
+                    if ($totalPages > 1) {
+                        $pageName = "?Keys=$keys$urlStr&";
+                        $pageLen = 3;
+
+                        if ($page > 1) {
+                            echo "<a href=\"{$pageName}Page=1\">首页</a>";
+                            echo "<a href=\"{$pageName}Page=" . ($page - 1) . "\">上一页</a>";
+                        }
+
+                        if ($pageLen * 2 + 1 >= $totalPages) {
+                            $startPage = 1;
+                            $endPage = $totalPages;
+                        } else {
+                            if ($page <= $pageLen + 1) {
+                                $startPage = 1;
+                                $endPage = $pageLen * 2 + 1;
+                            } else {
+                                $startPage = $page - $pageLen;
+                                $endPage = $page + $pageLen;
+                            }
+                            if ($page + $pageLen > $totalPages) {
+                                $startPage = $totalPages - $pageLen * 2;
+                                $endPage = $totalPages;
+                            }
+                        }
+
+                        for ($i = $startPage; $i <= $endPage; $i++) {
+                            if ($i == $page) {
+                                echo "<a class=\"current\">$i</a>";
+                            } else {
+                                echo "<a href=\"{$pageName}Page=$i\">$i</a>";
+                            }
+                        }
+
+                        if ($page < $totalPages) {
+                            if ($totalPages - $page > $pageLen) {
+                                echo "<a href=\"{$pageName}Page=$totalPages\">...$totalPages</a>";
+                            }
+                            echo "<a href=\"{$pageName}Page=" . ($page + 1) . "\">下一页</a>";
+                            echo "<a href=\"{$pageName}Page=$totalPages\">尾页</a>";
+                        }
+                    }
+                    ?>
+                </div>
+                <div class="postchkbox">
+                    <select id="chkact" name="chkact">
+                        <option value="1">待确认</option>
+                        <option value="2">已确认</option>
+                        <option value="3">生产中</option>
+                        <option value="4">已发货</option>
+                        <option value="5">已完成</option>
+                        <option value="0">取消订单</option>
+                        <option value="-1">删除</option>
+                    </select>
+                    <input type="button" value="执行" onClick="postchk(1)" class="btn1" />
+                </div>
+            </div>
+        </div>
+    </form>
+
+    <script>
+    $(document).ready(function() {
+        // 处理筛选条件改变
+        $('.filterSearch').change(function() {
+            var url = '?';
+            var keys = $('#keys').val();
+            if (keys && keys != '请输入搜索关键词') {
+                url += 'Keys=' + encodeURIComponent(keys) + '&';
+            }
+
+            $('.filterSearch').each(function() {
+                var name = $(this).attr('name');
+                var value = $(this).val();
+                if (value) {
+                    url += name + '=' + encodeURIComponent(value) + '&';
+                }
+            });
+
+            // 移除末尾的&
+            if (url.endsWith('&')) {
+                url = url.substring(0, url.length - 1);
+            }
+
+            location.href = url;
+        });
+    });
+    </script>
+</div>
+</body>
+</html>

+ 467 - 0
order_add.php

@@ -0,0 +1,467 @@
+<?php
+require_once 'conn.php';
+checkLogin();
+
+// 生成一个新的订单编号
+$order_code = date('YmdHis') . rand(100, 999);
+
+$page = $_GET['Page'] ?? '';
+$keys = urlencode($_GET['Keys'] ?? '');
+$hrefstr = "keys=$keys&Page=$page";
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <title>新增订单</title>
+    <link rel="stylesheet" href="css/common.css" type="text/css" />
+    <link rel="stylesheet" href="css/alert.css" type="text/css" />
+    <script src="js/jquery-1.7.2.min.js"></script>
+    <script src="js/js.js"></script>
+    <style>
+        body {
+            margin: 0;
+            padding: 20px;
+            background: #fff;
+        }
+        #man_zone {
+            margin-left: 0;
+        }
+        .product-row {
+            border: 1px solid #ddd;
+            padding: 10px;
+            margin-bottom: 10px;
+            background-color: #f9f9f9;
+            position: relative;
+        }
+        .delete-product {
+            position: absolute;
+            right: 10px;
+            top: 10px;
+            color: red;
+            cursor: pointer;
+        }
+        .add-product-btn {
+            background-color: #4CAF50;
+            color: white;
+            padding: 8px 12px;
+            border: none;
+            cursor: pointer;
+            margin-bottom: 15px;
+        }
+        .total-section {
+            margin-top: 20px;
+            padding: 10px;
+            background-color: #eee;
+            font-weight: bold;
+        }
+        #product-container {
+            margin-bottom: 20px;
+        }
+    </style>
+</head>
+<body>
+<div id="man_zone">
+    <form name="form1" id="form1" method="post" action="order_save.php?<?= $hrefstr ?>" onsubmit="return validateOrderForm()">
+        <table width="100%" border="0" cellpadding="3" cellspacing="1" class="table1">
+            <tbody>
+            <tr>
+                <th width="8%">订单编号</th>
+                <td><input type="text" id="order_code" name="order_code" value="<?= $order_code ?>" class="txt1" /></td>
+            </tr>
+            <tr>
+                <th width="8%">客户选择</th>
+                <td>
+                    <select id="customer_id" name="customer_id" onchange="loadCustomerContacts(this.value)">
+                        <option value="0">请选择客户</option>
+                        <?php
+                        $customerSql = "SELECT id, cs_company FROM customer WHERE cs_belong = " . $_SESSION['employee_id'] . " ORDER BY cs_company";
+                        $customerResult = mysqli_query($conn, $customerSql);
+                        while ($customerRow = mysqli_fetch_assoc($customerResult)) {
+                            echo "<option value=\"{$customerRow['id']}\">" . htmlspecialcharsFix($customerRow['cs_company']) . "</option>";
+                        }
+                        ?>
+                    </select>
+                </td>
+            </tr>
+            <tr>
+                <th width="8%">联系人</th>
+                <td>
+                    <select id="contact_id" name="contact_id">
+                        <option value="">请选择联系人</option>
+                    </select>
+                </td>
+            </tr>
+            <tr>
+                <th width="8%">订单日期</th>
+                <td><input type="date" id="order_date" name="order_date" value="<?= date('Y-m-d') ?>" class="txt1" /></td>
+            </tr>
+            <tr>
+                <th width="8%">预计交付日期</th>
+                <td><input type="date" id="delivery_date" name="delivery_date" value="" class="txt1" /></td>
+            </tr>
+            <tr>
+                <th width="8%">实际交付日期</th>
+                <td><input type="date" id="actual_delivery_date" name="actual_delivery_date" value="" class="txt1" /></td>
+            </tr>
+            <tr>
+                <th width="8%">订单状态</th>
+                <td>
+                    <select id="order_status" name="order_status">
+                        <option value="0">已取消</option>
+                        <option value="1" selected>待确认</option>
+                        <option value="2">已确认</option>
+                        <option value="3">生产中</option>
+                        <option value="4">已发货</option>
+                        <option value="5">已完成</option>
+                    </select>
+                </td>
+            </tr>
+            <tr>
+                <th width="8%">付款状态</th>
+                <td>
+                    <select id="payment_status" name="payment_status">
+                        <option value="0" selected>未付款</option>
+                        <option value="1">部分付款</option>
+                        <option value="2">已付清</option>
+                    </select>
+                </td>
+            </tr>
+            <tr>
+                <th width="8%">币种</th>
+                <td>
+                    <select id="currency" name="currency">
+                        <option value="CNY" selected>人民币 (CNY)</option>
+                        <option value="USD">美元 (USD)</option>
+                        <option value="EUR">欧元 (EUR)</option>
+                    </select>
+                </td>
+            </tr>
+            <tr>
+                <th width="8%" valign="top">产品列表</th>
+                <td>
+                    <button type="button" id="add-product-btn" class="add-product-btn">添加产品</button>
+                    <div id="product-container">
+                        <div class="product-row" data-index="0">
+                            <span class="delete-product">×</span>
+                            <div>
+                                <label>产品:</label>
+                                <select name="items[0][product_id]" class="product-select" onchange="updateProductInfo(this)">
+                                    <option value="">请选择产品</option>
+                                    <?php
+                                    $productSql = "SELECT id, ProductName FROM products ORDER BY ProductName";
+                                    $productResult = mysqli_query($conn, $productSql);
+                                    while ($productRow = mysqli_fetch_assoc($productResult)) {
+                                        echo "<option value=\"{$productRow['id']}\">" . htmlspecialcharsFix($productRow['ProductName']) . "</option>";
+                                    }
+                                    ?>
+                                </select>
+                            </div>
+                            <div style="margin-top: 5px;">
+                                <label>数量:</label>
+                                <input type="number" name="items[0][quantity]" value="1" min="1" class="quantity-input" onchange="calculateItemTotal(this)">
+
+                                <label style="margin-left: 10px;">单位:</label>
+                                <input type="text" name="items[0][unit]" value="" class="unit-input">
+
+                                <label style="margin-left: 10px;">单价:</label>
+                                <input type="number" step="0.01" name="items[0][unit_price]" value="0.00" class="price-input" onchange="calculateItemTotal(this)">
+                            </div>
+                            <div style="margin-top: 5px;">
+                                <label>折扣金额:</label>
+                                <input type="number" step="0.01" name="items[0][discount_amount]" value="0.00" class="discount-amount-input" onchange="calculateItemTotal(this)">
+
+                                <label style="margin-left: 10px;">折扣率:</label>
+                                <input type="number" step="0.01" name="items[0][discount_percent]" value="0" class="discount-percent-input" max="100" min="0">%
+
+                                <label style="margin-left: 10px;">总价:</label>
+                                <input type="number" step="0.01" name="items[0][total_price]" value="0.00" class="total-price-input" readonly>
+                            </div>
+                            <div style="margin-top: 5px;">
+                                <label>备注:</label>
+                                <input type="text" name="items[0][notes]" value="" style="width: 80%;">
+                            </div>
+                        </div>
+                    </div>
+                    <div class="total-section">
+                        <div>
+                            <label>订单小计:</label>
+                            <span id="subtotal">0.00</span>
+                            <input type="hidden" name="subtotal" id="subtotal-input" value="0.00">
+                        </div>
+                        <div style="margin-top: 5px;">
+                            <label>运费:</label>
+                            <input type="number" step="0.01" name="shipping_fee" id="shipping-fee" value="0.00" onchange="calculateOrderTotal()">
+                        </div>
+                        <div style="margin-top: 5px;">
+                            <label>订单折扣:</label>
+                            <input type="number" step="0.01" name="discount_amount" id="order-discount" value="0.00" onchange="calculateOrderTotal()">
+                        </div>
+                        <div style="margin-top: 5px;">
+                            <label>订单总额:</label>
+                            <span id="total-amount">0.00</span>
+                            <input type="hidden" name="total_amount" id="total-amount-input" value="0.00">
+                        </div>
+                    </div>
+                </td>
+            </tr>
+            <tr>
+                <th width="8%">订单备注</th>
+                <td>
+                    <textarea name="notes" rows="3" style="width: 90%;"></textarea>
+                </td>
+            </tr>
+            <tr>
+                <th width="8%">内部备注</th>
+                <td>
+                    <textarea name="internal_notes" rows="3" style="width: 90%;"></textarea>
+                </td>
+            </tr>
+            <tr>
+                <th></th>
+                <td>
+                    <input type="submit" name="save" value="保存订单" class="btn1">
+                    <input type="button" value="返回" class="btn1" onClick="location.href='order.php?<?= $hrefstr ?>'" />
+                </td>
+            </tr>
+            </tbody>
+        </table>
+    </form>
+
+    <script>
+        var productIndex = 1;
+
+        $(document).ready(function() {
+            // 初始化计算
+            calculateOrderTotal();
+
+            // 添加产品行
+            $('#add-product-btn').click(function() {
+                addProductRow();
+            });
+
+            // 删除产品行
+            $(document).on('click', '.delete-product', function() {
+                if ($('.product-row').length > 1) {
+                    $(this).closest('.product-row').remove();
+                    reindexProductRows();
+                    calculateOrderTotal();
+                } else {
+                    alert('订单至少需要一个产品');
+                }
+            });
+
+            // 更新折扣率和折扣金额之间的关系
+            $(document).on('change', '.discount-percent-input', function() {
+                var row = $(this).closest('.product-row');
+                var percent = parseFloat($(this).val()) || 0;
+                var quantity = parseInt(row.find('.quantity-input').val()) || 0;
+                var price = parseFloat(row.find('.price-input').val()) || 0;
+                var subtotal = quantity * price;
+
+                var discountAmount = (subtotal * percent / 100).toFixed(2);
+                row.find('.discount-amount-input').val(discountAmount);
+
+                calculateItemTotal(this);
+            });
+
+            $(document).on('change', '.discount-amount-input', function() {
+                var row = $(this).closest('.product-row');
+                var amount = parseFloat($(this).val()) || 0;
+                var quantity = parseInt(row.find('.quantity-input').val()) || 0;
+                var price = parseFloat(row.find('.price-input').val()) || 0;
+                var subtotal = quantity * price;
+
+                if (subtotal > 0) {
+                    var percent = ((amount / subtotal) * 100).toFixed(2);
+                    row.find('.discount-percent-input').val(percent);
+                }
+
+                calculateItemTotal(this);
+            });
+        });
+
+        function addProductRow() {
+            var html = `
+            <div class="product-row" data-index="${productIndex}">
+                <span class="delete-product">×</span>
+                <div>
+                    <label>产品:</label>
+                    <select name="items[${productIndex}][product_id]" class="product-select" onchange="updateProductInfo(this)">
+                        <option value="">请选择产品</option>
+                        ${getProductOptions()}
+                    </select>
+                </div>
+                <div style="margin-top: 5px;">
+                    <label>数量:</label>
+                    <input type="number" name="items[${productIndex}][quantity]" value="1" min="1" class="quantity-input" onchange="calculateItemTotal(this)">
+
+                    <label style="margin-left: 10px;">单位:</label>
+                    <input type="text" name="items[${productIndex}][unit]" value="" class="unit-input">
+
+                    <label style="margin-left: 10px;">单价:</label>
+                    <input type="number" step="0.01" name="items[${productIndex}][unit_price]" value="0.00" class="price-input" onchange="calculateItemTotal(this)">
+                </div>
+                <div style="margin-top: 5px;">
+                    <label>折扣金额:</label>
+                    <input type="number" step="0.01" name="items[${productIndex}][discount_amount]" value="0.00" class="discount-amount-input" onchange="calculateItemTotal(this)">
+
+                    <label style="margin-left: 10px;">折扣率:</label>
+                    <input type="number" step="0.01" name="items[${productIndex}][discount_percent]" value="0" class="discount-percent-input" max="100" min="0">%
+
+                    <label style="margin-left: 10px;">总价:</label>
+                    <input type="number" step="0.01" name="items[${productIndex}][total_price]" value="0.00" class="total-price-input" readonly>
+                </div>
+                <div style="margin-top: 5px;">
+                    <label>备注:</label>
+                    <input type="text" name="items[${productIndex}][notes]" value="" style="width: 80%;">
+                </div>
+            </div>
+        `;
+
+            $('#product-container').append(html);
+            productIndex++;
+        }
+
+        function getProductOptions() {
+            var options = '';
+            <?php
+            $productSql = "SELECT id, ProductName FROM products ORDER BY ProductName";
+            $productResult = mysqli_query($conn, $productSql);
+            while ($productRow = mysqli_fetch_assoc($productResult)) {
+                echo "options += '<option value=\"{$productRow['id']}\">" . addslashes(htmlspecialcharsFix($productRow['ProductName'])) . "</option>';\n";
+            }
+            ?>
+            return options;
+        }
+
+        function reindexProductRows() {
+            $('.product-row').each(function(index) {
+                $(this).attr('data-index', index);
+                $(this).find('select, input').each(function() {
+                    var name = $(this).attr('name');
+                    if (name) {
+                        name = name.replace(/items\[\d+\]/, 'items[' + index + ']');
+                        $(this).attr('name', name);
+                    }
+                });
+            });
+            productIndex = $('.product-row').length;
+        }
+
+        function updateProductInfo(selectElement) {
+            var productId = $(selectElement).val();
+            var row = $(selectElement).closest('.product-row');
+
+            if (productId) {
+                // 使用AJAX获取产品信息
+                $.ajax({
+                    url: 'get_product_info.php',
+                    type: 'GET',
+                    data: {id: productId},
+                    dataType: 'json',
+                    success: function(data) {
+                        if (data) {
+                            row.find('.unit-input').val(data.unit);
+                            row.find('.price-input').val(data.price);
+                            calculateItemTotal(selectElement);
+                        }
+                    }
+                });
+            } else {
+                row.find('.unit-input').val('');
+                row.find('.price-input').val('0.00');
+                calculateItemTotal(selectElement);
+            }
+        }
+
+        function calculateItemTotal(element) {
+            var row = $(element).closest('.product-row');
+            var quantity = parseInt(row.find('.quantity-input').val()) || 0;
+            var price = parseFloat(row.find('.price-input').val()) || 0;
+            var discountAmount = parseFloat(row.find('.discount-amount-input').val()) || 0;
+
+            var subtotal = quantity * price;
+            var total = subtotal - discountAmount;
+            if (total < 0) total = 0;
+
+            row.find('.total-price-input').val(total.toFixed(2));
+
+            calculateOrderTotal();
+        }
+
+        function calculateOrderTotal() {
+            var subtotal = 0;
+            $('.total-price-input').each(function() {
+                subtotal += parseFloat($(this).val()) || 0;
+            });
+
+            var shippingFee = parseFloat($('#shipping-fee').val()) || 0;
+            var orderDiscount = parseFloat($('#order-discount').val()) || 0;
+            var total = subtotal + shippingFee - orderDiscount;
+
+            if (total < 0) total = 0;
+
+            $('#subtotal').text(subtotal.toFixed(2));
+            $('#subtotal-input').val(subtotal.toFixed(2));
+            $('#total-amount').text(total.toFixed(2));
+            $('#total-amount-input').val(total.toFixed(2));
+        }
+
+        function loadCustomerContacts(customerId) {
+            if (customerId) {
+                $.ajax({
+                    url: 'get_customer_contacts.php',
+                    type: 'GET',
+                    data: {customer_id: customerId},
+                    dataType: 'json',
+                    success: function(data) {
+                        var options = '<option value="">请选择联系人</option>';
+                        if (data && data.length > 0) {
+                            for (var i = 0; i < data.length; i++) {
+                                options += '<option value="' + data[i].id + '">' + data[i].contact_name + '</option>';
+                            }
+                        }
+                        $('#contact_id').html(options);
+                    }
+                });
+            } else {
+                $('#contact_id').html('<option value="">请选择联系人</option>');
+            }
+        }
+
+        function validateOrderForm() {
+            var orderCode = $('#order_code').val();
+            var customerId = $('#customer_id').val();
+            var hasProducts = false;
+
+            $('.product-select').each(function() {
+                if ($(this).val()) {
+                    hasProducts = true;
+                    return false; // break the loop
+                }
+            });
+
+            if (!orderCode) {
+                alert('订单编号不能为空');
+                $('#order_code').focus();
+                return false;
+            }
+
+            if (!customerId || customerId == '0') {
+                alert('请选择客户');
+                $('#customer_id').focus();
+                return false;
+            }
+
+            if (!hasProducts) {
+                alert('请至少选择一个产品');
+                return false;
+            }
+
+            return true;
+        }
+    </script>
+</div>
+</body>
+</html>

+ 273 - 0
order_details.php

@@ -0,0 +1,273 @@
+<?php
+require_once 'conn.php';
+checkLogin();
+
+$id = $_GET['id'] ?? '';
+
+// 验证并获取订单数据
+if (!empty($id) && is_numeric($id)) {
+    // 获取订单基本信息
+    $employee_id = $_SESSION['employee_id'];
+    $sql = "SELECT o.*, c.cs_company, cc.contact_name, e.employee_name 
+            FROM orders o 
+            LEFT JOIN customer c ON o.customer_id = c.id 
+            LEFT JOIN customer_contact cc ON o.contact_id = cc.id 
+            LEFT JOIN employee e ON o.employee_id = e.id
+            WHERE o.id = $id AND o.employee_id = $employee_id";
+
+    $result = mysqli_query($conn, $sql);
+
+    if ($row = mysqli_fetch_assoc($result)) {
+        $order = $row;
+    } else {
+        echo "<script>alert('订单不存在或您没有权限查看');history.back();</script>";
+        exit;
+    }
+
+    // 获取订单项信息
+    $sql = "SELECT oi.*, p.ProductName 
+            FROM order_items oi 
+            LEFT JOIN products p ON oi.product_id = p.id 
+            WHERE oi.order_id = $id";
+
+    $itemsResult = mysqli_query($conn, $sql);
+
+    $orderItems = [];
+    while ($itemRow = mysqli_fetch_assoc($itemsResult)) {
+        $orderItems[] = $itemRow;
+    }
+} else {
+    echo "<script>alert('订单不存在!');history.back();</script>";
+    exit;
+}
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <title>订单详情</title>
+    <link rel="stylesheet" href="css/common.css" type="text/css" />
+    <link rel="stylesheet" href="css/alert.css" type="text/css" />
+    <script src="js/jquery-1.7.2.min.js"></script>
+    <script src="js/js.js"></script>
+    <style>
+        body {
+            margin: 0;
+            padding: 20px;
+            background: #fff;
+        }
+        #man_zone {
+            margin-left: 0;
+        }
+        .order-info {
+            border: 1px solid #ddd;
+            padding: 15px;
+            margin-bottom: 20px;
+            background-color: #f9f9f9;
+        }
+        .order-info h2 {
+            margin-top: 0;
+            border-bottom: 1px solid #ddd;
+            padding-bottom: 10px;
+        }
+        .order-info .info-row {
+            margin-bottom: 10px;
+        }
+        .order-info .info-label {
+            font-weight: bold;
+            display: inline-block;
+            width: 120px;
+        }
+        .products-table {
+            width: 100%;
+            border-collapse: collapse;
+            margin-bottom: 20px;
+        }
+        .products-table th, .products-table td {
+            border: 1px solid #ddd;
+            padding: 8px;
+            text-align: left;
+        }
+        .products-table th {
+            background-color: #f2f2f2;
+        }
+        .status-badge {
+            display: inline-block;
+            padding: 3px 8px;
+            border-radius: 3px;
+            font-size: 12px;
+            color: white;
+        }
+        .status-0 { background-color: #999; }
+        .status-1 { background-color: #5bc0de; }
+        .status-2 { background-color: #337ab7; }
+        .status-3 { background-color: #f0ad4e; }
+        .status-4 { background-color: #5cb85c; }
+        .status-5 { background-color: #28a745; }
+
+        .payment-badge {
+            display: inline-block;
+            padding: 3px 8px;
+            border-radius: 3px;
+            font-size: 12px;
+            color: white;
+        }
+        .payment-0 { background-color: #d9534f; }
+        .payment-1 { background-color: #f0ad4e; }
+        .payment-2 { background-color: #5cb85c; }
+
+        .notes-section {
+            border: 1px solid #ddd;
+            padding: 15px;
+            margin-bottom: 20px;
+        }
+        .total-section {
+            text-align: right;
+            font-size: 1.1em;
+            margin-top: 10px;
+            border-top: 1px solid #ddd;
+            padding-top: 10px;
+        }
+    </style>
+</head>
+<body>
+<div id="man_zone">
+    <div align="right" style="margin-bottom: 10px;">
+        <input type="button" value="返回订单列表" class="btn1" onClick="location.href='order.php'" />
+        <input type="button" value="编辑此订单" class="btn1" onClick="location.href='order_edit.php?id=<?= $id ?>'" />
+    </div>
+
+    <div class="order-info">
+        <h2>订单信息</h2>
+        <div class="info-row">
+            <span class="info-label">订单编号:</span> <?= htmlspecialcharsFix($order['order_code']) ?>
+        </div>
+        <div class="info-row">
+            <span class="info-label">客户:</span> <?= htmlspecialcharsFix($order['cs_company']) ?>
+        </div>
+        <div class="info-row">
+            <span class="info-label">联系人:</span> <?= htmlspecialcharsFix($order['contact_name']) ?>
+        </div>
+        <div class="info-row">
+            <span class="info-label">订单日期:</span> <?= date('Y-m-d', strtotime($order['order_date'])) ?>
+        </div>
+        <div class="info-row">
+            <span class="info-label">预计交付日期:</span> <?= $order['delivery_date'] ? date('Y-m-d', strtotime($order['delivery_date'])) : '未设置' ?>
+        </div>
+        <div class="info-row">
+            <span class="info-label">实际交付日期:</span> <?= $order['actual_delivery_date'] ? date('Y-m-d', strtotime($order['actual_delivery_date'])) : '未完成' ?>
+        </div>
+        <div class="info-row">
+            <span class="info-label">订单状态:</span>
+            <?php
+            $statusMap = [
+                0 => '已取消',
+                1 => '待确认',
+                2 => '已确认',
+                3 => '生产中',
+                4 => '已发货',
+                5 => '已完成'
+            ];
+            echo '<span class="status-badge status-' . $order['order_status'] . '">' .
+                $statusMap[$order['order_status']] . '</span>';
+            ?>
+        </div>
+        <div class="info-row">
+            <span class="info-label">付款状态:</span>
+            <?php
+            $paymentMap = [
+                0 => '未付款',
+                1 => '部分付款',
+                2 => '已付清'
+            ];
+            echo '<span class="payment-badge payment-' . $order['payment_status'] . '">' .
+                $paymentMap[$order['payment_status']] . '</span>';
+            ?>
+        </div>
+        <div class="info-row">
+            <span class="info-label">币种:</span> <?= $order['currency'] ?>
+        </div>
+        <div class="info-row">
+            <span class="info-label">创建时间:</span> <?= $order['created_at'] ?>
+        </div>
+        <div class="info-row">
+            <span class="info-label">最后更新:</span> <?= $order['updated_at'] ?>
+        </div>
+        <div class="info-row">
+            <span class="info-label">销售员:</span> <?= htmlspecialcharsFix($order['employee_name']) ?>
+        </div>
+    </div>
+
+    <h2>订单产品</h2>
+    <table class="products-table">
+        <thead>
+        <tr>
+            <th>序号</th>
+            <th>产品名称</th>
+            <th>数量</th>
+            <th>单位</th>
+            <th>单价</th>
+            <th>折扣</th>
+            <th>总价</th>
+            <th>备注</th>
+        </tr>
+        </thead>
+        <tbody>
+        <?php foreach ($orderItems as $index => $item): ?>
+            <tr>
+                <td><?= $index + 1 ?></td>
+                <td><?= htmlspecialcharsFix($item['ProductName']) ?></td>
+                <td><?= $item['quantity'] ?></td>
+                <td><?= htmlspecialcharsFix($item['unit']) ?></td>
+                <td><?= number_format($item['unit_price'], 2) ?></td>
+                <td>
+                    <?php if ($item['discount_amount'] > 0): ?>
+                        <?= number_format($item['discount_amount'], 2) ?>
+                        (<?= number_format($item['discount_percent'], 2) ?>%)
+                    <?php else: ?>
+                        -
+                    <?php endif; ?>
+                </td>
+                <td><?= number_format($item['total_price'], 2) ?></td>
+                <td><?= htmlspecialcharsFix($item['notes']) ?></td>
+            </tr>
+        <?php endforeach; ?>
+        </tbody>
+    </table>
+
+    <div class="total-section">
+        <div>
+            <strong>订单小计:</strong> <?= number_format($order['subtotal'], 2) ?> <?= $order['currency'] ?>
+        </div>
+        <div>
+            <strong>运费:</strong> <?= number_format($order['shipping_fee'], 2) ?> <?= $order['currency'] ?>
+        </div>
+        <div>
+            <strong>订单折扣:</strong> <?= number_format($order['discount_amount'], 2) ?> <?= $order['currency'] ?>
+        </div>
+        <div style="font-size: 1.2em; margin-top: 5px;">
+            <strong>订单总额:</strong> <?= number_format($order['total_amount'], 2) ?> <?= $order['currency'] ?>
+        </div>
+    </div>
+
+    <?php if (!empty($order['notes']) || !empty($order['internal_notes'])): ?>
+        <div class="notes-section">
+            <h2>备注信息</h2>
+            <?php if (!empty($order['notes'])): ?>
+                <div>
+                    <strong>订单备注:</strong>
+                    <p><?= nl2br(htmlspecialcharsFix($order['notes'])) ?></p>
+                </div>
+            <?php endif; ?>
+
+            <?php if (!empty($order['internal_notes'])): ?>
+                <div>
+                    <strong>内部备注:</strong>
+                    <p><?= nl2br(htmlspecialcharsFix($order['internal_notes'])) ?></p>
+                </div>
+            <?php endif; ?>
+        </div>
+    <?php endif; ?>
+</div>
+</body>
+</html>

+ 525 - 0
order_edit.php

@@ -0,0 +1,525 @@
+<?php
+require_once 'conn.php';
+checkLogin();
+
+$id = $_GET['id'] ?? '';
+$page = $_GET['Page'] ?? '';
+$keys = urlencode($_GET['Keys'] ?? '');
+
+$hrefstr = "keys=$keys&Page=$page";
+
+// 验证并获取订单数据
+if (!empty($id) && is_numeric($id)) {
+    // 获取订单基本信息
+    $employee_id = $_SESSION['employee_id'];
+    $sql = "SELECT o.*, c.cs_company, cc.contact_name 
+            FROM orders o 
+            LEFT JOIN customer c ON o.customer_id = c.id 
+            LEFT JOIN customer_contact cc ON o.contact_id = cc.id 
+            WHERE o.id = $id AND o.employee_id = $employee_id";
+
+    $result = mysqli_query($conn, $sql);
+
+    if ($row = mysqli_fetch_assoc($result)) {
+        $order = $row;
+    } else {
+        echo "<script>alert('订单不存在或您没有权限查看');history.back();</script>";
+        exit;
+    }
+
+    // 获取订单项信息
+    $sql = "SELECT oi.*, p.ProductName 
+            FROM order_items oi 
+            LEFT JOIN products p ON oi.product_id = p.id 
+            WHERE oi.order_id = $id";
+
+    $itemsResult = mysqli_query($conn, $sql);
+
+    $orderItems = [];
+    while ($itemRow = mysqli_fetch_assoc($itemsResult)) {
+        $orderItems[] = $itemRow;
+    }
+} else {
+    echo "<script>alert('订单不存在!');history.back();</script>";
+    exit;
+}
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <title>编辑订单</title>
+    <link rel="stylesheet" href="css/common.css" type="text/css" />
+    <link rel="stylesheet" href="css/alert.css" type="text/css" />
+    <script src="js/jquery-1.7.2.min.js"></script>
+    <script src="js/js.js"></script>
+    <style>
+        body {
+            margin: 0;
+            padding: 20px;
+            background: #fff;
+        }
+        #man_zone {
+            margin-left: 0;
+        }
+        .product-row {
+            border: 1px solid #ddd;
+            padding: 10px;
+            margin-bottom: 10px;
+            background-color: #f9f9f9;
+            position: relative;
+        }
+        .delete-product {
+            position: absolute;
+            right: 10px;
+            top: 10px;
+            color: red;
+            cursor: pointer;
+        }
+        .add-product-btn {
+            background-color: #4CAF50;
+            color: white;
+            padding: 8px 12px;
+            border: none;
+            cursor: pointer;
+            margin-bottom: 15px;
+        }
+        .total-section {
+            margin-top: 20px;
+            padding: 10px;
+            background-color: #eee;
+            font-weight: bold;
+        }
+        #product-container {
+            margin-bottom: 20px;
+        }
+    </style>
+</head>
+<body>
+<div id="man_zone">
+    <form name="form1" id="form1" method="post" action="order_save.php?<?= $hrefstr ?>" onsubmit="return validateOrderForm()">
+        <table width="100%" border="0" cellpadding="3" cellspacing="1" class="table1">
+            <tbody>
+            <tr>
+                <th width="8%">订单编号</th>
+                <td>
+                    <input type="text" id="order_code" name="order_code" value="<?= htmlspecialcharsFix($order['order_code']) ?>" class="txt1" />
+                    <input type="hidden" name="id" value="<?= $id ?>" />
+                </td>
+            </tr>
+            <tr>
+                <th width="8%">客户选择</th>
+                <td>
+                    <select id="customer_id" name="customer_id" onchange="loadCustomerContacts(this.value)">
+                        <option value="0">请选择客户</option>
+                        <?php
+                        $customerSql = "SELECT id, cs_company FROM customer WHERE cs_belong = " . $_SESSION['employee_id'] . " ORDER BY cs_company";
+                        $customerResult = mysqli_query($conn, $customerSql);
+                        while ($customerRow = mysqli_fetch_assoc($customerResult)) {
+                            $selected = ($order['customer_id'] == $customerRow['id']) ? ' selected' : '';
+                            echo "<option value=\"{$customerRow['id']}\"$selected>" . htmlspecialcharsFix($customerRow['cs_company']) . "</option>";
+                        }
+                        ?>
+                    </select>
+                </td>
+            </tr>
+            <tr>
+                <th width="8%">联系人</th>
+                <td>
+                    <select id="contact_id" name="contact_id">
+                        <option value="">请选择联系人</option>
+                        <?php
+                        if ($order['customer_id']) {
+                            $contactSql = "SELECT id, contact_name FROM customer_contact WHERE customer_id = " . $order['customer_id'];
+                            $contactResult = mysqli_query($conn, $contactSql);
+                            while ($contactRow = mysqli_fetch_assoc($contactResult)) {
+                                $selected = ($order['contact_id'] == $contactRow['id']) ? ' selected' : '';
+                                echo "<option value=\"{$contactRow['id']}\"$selected>" . htmlspecialcharsFix($contactRow['contact_name']) . "</option>";
+                            }
+                        }
+                        ?>
+                    </select>
+                </td>
+            </tr>
+            <tr>
+                <th width="8%">订单日期</th>
+                <td>
+                    <input type="date" id="order_date" name="order_date" value="<?= substr($order['order_date'], 0, 10) ?>" class="txt1" />
+                </td>
+            </tr>
+            <tr>
+                <th width="8%">预计交付日期</th>
+                <td>
+                    <input type="date" id="delivery_date" name="delivery_date" value="<?= $order['delivery_date'] ? substr($order['delivery_date'], 0, 10) : '' ?>" class="txt1" />
+                </td>
+            </tr>
+            <tr>
+                <th width="8%">实际交付日期</th>
+                <td>
+                    <input type="date" id="actual_delivery_date" name="actual_delivery_date" value="<?= $order['actual_delivery_date'] ? substr($order['actual_delivery_date'], 0, 10) : '' ?>" class="txt1" />
+                </td>
+            </tr>
+            <tr>
+                <th width="8%">订单状态</th>
+                <td>
+                    <select id="order_status" name="order_status">
+                        <option value="0" <?= $order['order_status'] == 0 ? 'selected' : '' ?>>已取消</option>
+                        <option value="1" <?= $order['order_status'] == 1 ? 'selected' : '' ?>>待确认</option>
+                        <option value="2" <?= $order['order_status'] == 2 ? 'selected' : '' ?>>已确认</option>
+                        <option value="3" <?= $order['order_status'] == 3 ? 'selected' : '' ?>>生产中</option>
+                        <option value="4" <?= $order['order_status'] == 4 ? 'selected' : '' ?>>已发货</option>
+                        <option value="5" <?= $order['order_status'] == 5 ? 'selected' : '' ?>>已完成</option>
+                    </select>
+                </td>
+            </tr>
+            <tr>
+                <th width="8%">付款状态</th>
+                <td>
+                    <select id="payment_status" name="payment_status">
+                        <option value="0" <?= $order['payment_status'] == 0 ? 'selected' : '' ?>>未付款</option>
+                        <option value="1" <?= $order['payment_status'] == 1 ? 'selected' : '' ?>>部分付款</option>
+                        <option value="2" <?= $order['payment_status'] == 2 ? 'selected' : '' ?>>已付清</option>
+                    </select>
+                </td>
+            </tr>
+            <tr>
+                <th width="8%">币种</th>
+                <td>
+                    <select id="currency" name="currency">
+                        <option value="CNY" <?= $order['currency'] == 'CNY' ? 'selected' : '' ?>>人民币 (CNY)</option>
+                        <option value="USD" <?= $order['currency'] == 'USD' ? 'selected' : '' ?>>美元 (USD)</option>
+                        <option value="EUR" <?= $order['currency'] == 'EUR' ? 'selected' : '' ?>>欧元 (EUR)</option>
+                    </select>
+                </td>
+            </tr>
+            <tr>
+                <th width="8%" valign="top">产品列表</th>
+                <td>
+                    <button type="button" id="add-product-btn" class="add-product-btn">添加产品</button>
+                    <div id="product-container">
+                        <?php foreach ($orderItems as $index => $item): ?>
+                            <div class="product-row" data-index="<?= $index ?>">
+                                <span class="delete-product">×</span>
+                                <div>
+                                    <label>产品:</label>
+                                    <select name="items[<?= $index ?>][product_id]" class="product-select" onchange="updateProductInfo(this)">
+                                        <option value="">请选择产品</option>
+                                        <?php
+                                        $productSql = "SELECT id, ProductName FROM products ORDER BY ProductName";
+                                        $productResult = mysqli_query($conn, $productSql);
+                                        while ($productRow = mysqli_fetch_assoc($productResult)) {
+                                            $selected = ($item['product_id'] == $productRow['id']) ? ' selected' : '';
+                                            echo "<option value=\"{$productRow['id']}\"$selected>" . htmlspecialcharsFix($productRow['ProductName']) . "</option>";
+                                        }
+                                        ?>
+                                    </select>
+                                </div>
+                                <div style="margin-top: 5px;">
+                                    <label>数量:</label>
+                                    <input type="number" name="items[<?= $index ?>][quantity]" value="<?= $item['quantity'] ?>" min="1" class="quantity-input" onchange="calculateItemTotal(this)">
+
+                                    <label style="margin-left: 10px;">单位:</label>
+                                    <input type="text" name="items[<?= $index ?>][unit]" value="<?= htmlspecialcharsFix($item['unit']) ?>" class="unit-input">
+
+                                    <label style="margin-left: 10px;">单价:</label>
+                                    <input type="number" step="0.01" name="items[<?= $index ?>][unit_price]" value="<?= $item['unit_price'] ?>" class="price-input" onchange="calculateItemTotal(this)">
+                                </div>
+                                <div style="margin-top: 5px;">
+                                    <label>折扣金额:</label>
+                                    <input type="number" step="0.01" name="items[<?= $index ?>][discount_amount]" value="<?= $item['discount_amount'] ?>" class="discount-amount-input" onchange="calculateItemTotal(this)">
+
+                                    <label style="margin-left: 10px;">折扣率:</label>
+                                    <input type="number" step="0.01" name="items[<?= $index ?>][discount_percent]" value="<?= $item['discount_percent'] ?>" class="discount-percent-input" max="100" min="0">%
+
+                                    <label style="margin-left: 10px;">总价:</label>
+                                    <input type="number" step="0.01" name="items[<?= $index ?>][total_price]" value="<?= $item['total_price'] ?>" class="total-price-input" readonly>
+                                </div>
+                                <div style="margin-top: 5px;">
+                                    <label>备注:</label>
+                                    <input type="text" name="items[<?= $index ?>][notes]" value="<?= htmlspecialcharsFix($item['notes']) ?>" style="width: 80%;">
+                                </div>
+                            </div>
+                        <?php endforeach; ?>
+                    </div>
+                    <div class="total-section">
+                        <div>
+                            <label>订单小计:</label>
+                            <span id="subtotal"><?= number_format($order['subtotal'], 2) ?></span>
+                            <input type="hidden" name="subtotal" id="subtotal-input" value="<?= $order['subtotal'] ?>">
+                        </div>
+                        <div style="margin-top: 5px;">
+                            <label>运费:</label>
+                            <input type="number" step="0.01" name="shipping_fee" id="shipping-fee" value="<?= $order['shipping_fee'] ?>" onchange="calculateOrderTotal()">
+                        </div>
+                        <div style="margin-top: 5px;">
+                            <label>订单折扣:</label>
+                            <input type="number" step="0.01" name="discount_amount" id="order-discount" value="<?= $order['discount_amount'] ?>" onchange="calculateOrderTotal()">
+                        </div>
+                        <div style="margin-top: 5px;">
+                            <label>订单总额:</label>
+                            <span id="total-amount"><?= number_format($order['total_amount'], 2) ?></span>
+                            <input type="hidden" name="total_amount" id="total-amount-input" value="<?= $order['total_amount'] ?>">
+                        </div>
+                    </div>
+                </td>
+            </tr>
+            <tr>
+                <th width="8%">订单备注</th>
+                <td>
+                    <textarea name="notes" rows="3" style="width: 90%;"><?= htmlspecialcharsFix($order['notes']) ?></textarea>
+                </td>
+            </tr>
+            <tr>
+                <th width="8%">内部备注</th>
+                <td>
+                    <textarea name="internal_notes" rows="3" style="width: 90%;"><?= htmlspecialcharsFix($order['internal_notes']) ?></textarea>
+                </td>
+            </tr>
+            <tr>
+                <th></th>
+                <td>
+                    <input type="submit" name="save" value="保存订单" class="btn1">
+                    <input type="button" value="返回" class="btn1" onClick="location.href='order.php?<?= $hrefstr ?>'" />
+                </td>
+            </tr>
+            </tbody>
+        </table>
+    </form>
+
+    <script>
+        var productIndex = <?= count($orderItems) ?>;
+
+        $(document).ready(function() {
+            // 初始化计算
+            calculateOrderTotal();
+
+            // 添加产品行
+            $('#add-product-btn').click(function() {
+                addProductRow();
+            });
+
+            // 删除产品行
+            $(document).on('click', '.delete-product', function() {
+                if ($('.product-row').length > 1) {
+                    $(this).closest('.product-row').remove();
+                    reindexProductRows();
+                    calculateOrderTotal();
+                } else {
+                    alert('订单至少需要一个产品');
+                }
+            });
+
+            // 更新折扣率和折扣金额之间的关系
+            $(document).on('change', '.discount-percent-input', function() {
+                var row = $(this).closest('.product-row');
+                var percent = parseFloat($(this).val()) || 0;
+                var quantity = parseInt(row.find('.quantity-input').val()) || 0;
+                var price = parseFloat(row.find('.price-input').val()) || 0;
+                var subtotal = quantity * price;
+
+                var discountAmount = (subtotal * percent / 100).toFixed(2);
+                row.find('.discount-amount-input').val(discountAmount);
+
+                calculateItemTotal(this);
+            });
+
+            $(document).on('change', '.discount-amount-input', function() {
+                var row = $(this).closest('.product-row');
+                var amount = parseFloat($(this).val()) || 0;
+                var quantity = parseInt(row.find('.quantity-input').val()) || 0;
+                var price = parseFloat(row.find('.price-input').val()) || 0;
+                var subtotal = quantity * price;
+
+                if (subtotal > 0) {
+                    var percent = ((amount / subtotal) * 100).toFixed(2);
+                    row.find('.discount-percent-input').val(percent);
+                }
+
+                calculateItemTotal(this);
+            });
+        });
+
+        function addProductRow() {
+            var html = `
+            <div class="product-row" data-index="${productIndex}">
+                <span class="delete-product">×</span>
+                <div>
+                    <label>产品:</label>
+                    <select name="items[${productIndex}][product_id]" class="product-select" onchange="updateProductInfo(this)">
+                        <option value="">请选择产品</option>
+                        ${getProductOptions()}
+                    </select>
+                </div>
+                <div style="margin-top: 5px;">
+                    <label>数量:</label>
+                    <input type="number" name="items[${productIndex}][quantity]" value="1" min="1" class="quantity-input" onchange="calculateItemTotal(this)">
+
+                    <label style="margin-left: 10px;">单位:</label>
+                    <input type="text" name="items[${productIndex}][unit]" value="" class="unit-input">
+
+                    <label style="margin-left: 10px;">单价:</label>
+                    <input type="number" step="0.01" name="items[${productIndex}][unit_price]" value="0.00" class="price-input" onchange="calculateItemTotal(this)">
+                </div>
+                <div style="margin-top: 5px;">
+                    <label>折扣金额:</label>
+                    <input type="number" step="0.01" name="items[${productIndex}][discount_amount]" value="0.00" class="discount-amount-input" onchange="calculateItemTotal(this)">
+
+                    <label style="margin-left: 10px;">折扣率:</label>
+                    <input type="number" step="0.01" name="items[${productIndex}][discount_percent]" value="0" class="discount-percent-input" max="100" min="0">%
+
+                    <label style="margin-left: 10px;">总价:</label>
+                    <input type="number" step="0.01" name="items[${productIndex}][total_price]" value="0.00" class="total-price-input" readonly>
+                </div>
+                <div style="margin-top: 5px;">
+                    <label>备注:</label>
+                    <input type="text" name="items[${productIndex}][notes]" value="" style="width: 80%;">
+                </div>
+            </div>
+        `;
+
+            $('#product-container').append(html);
+            productIndex++;
+        }
+
+        function getProductOptions() {
+            var options = '';
+            <?php
+            $productSql = "SELECT id, ProductName FROM products ORDER BY ProductName";
+            $productResult = mysqli_query($conn, $productSql);
+            while ($productRow = mysqli_fetch_assoc($productResult)) {
+                echo "options += '<option value=\"{$productRow['id']}\">" . addslashes(htmlspecialcharsFix($productRow['ProductName'])) . "</option>';\n";
+            }
+            ?>
+            return options;
+        }
+
+        function reindexProductRows() {
+            $('.product-row').each(function(index) {
+                $(this).attr('data-index', index);
+                $(this).find('select, input').each(function() {
+                    var name = $(this).attr('name');
+                    if (name) {
+                        name = name.replace(/items\[\d+\]/, 'items[' + index + ']');
+                        $(this).attr('name', name);
+                    }
+                });
+            });
+            productIndex = $('.product-row').length;
+        }
+
+        function updateProductInfo(selectElement) {
+            var productId = $(selectElement).val();
+            var row = $(selectElement).closest('.product-row');
+
+            if (productId) {
+                // 使用AJAX获取产品信息
+                $.ajax({
+                    url: 'get_product_info.php',
+                    type: 'GET',
+                    data: {id: productId},
+                    dataType: 'json',
+                    success: function(data) {
+                        if (data) {
+                            row.find('.unit-input').val(data.unit);
+                            row.find('.price-input').val(data.price);
+                            calculateItemTotal(selectElement);
+                        }
+                    }
+                });
+            } else {
+                row.find('.unit-input').val('');
+                row.find('.price-input').val('0.00');
+                calculateItemTotal(selectElement);
+            }
+        }
+
+        function calculateItemTotal(element) {
+            var row = $(element).closest('.product-row');
+            var quantity = parseInt(row.find('.quantity-input').val()) || 0;
+            var price = parseFloat(row.find('.price-input').val()) || 0;
+            var discountAmount = parseFloat(row.find('.discount-amount-input').val()) || 0;
+
+            var subtotal = quantity * price;
+            var total = subtotal - discountAmount;
+            if (total < 0) total = 0;
+
+            row.find('.total-price-input').val(total.toFixed(2));
+
+            calculateOrderTotal();
+        }
+
+        function calculateOrderTotal() {
+            var subtotal = 0;
+            $('.total-price-input').each(function() {
+                subtotal += parseFloat($(this).val()) || 0;
+            });
+
+            var shippingFee = parseFloat($('#shipping-fee').val()) || 0;
+            var orderDiscount = parseFloat($('#order-discount').val()) || 0;
+            var total = subtotal + shippingFee - orderDiscount;
+
+            if (total < 0) total = 0;
+
+            $('#subtotal').text(subtotal.toFixed(2));
+            $('#subtotal-input').val(subtotal.toFixed(2));
+            $('#total-amount').text(total.toFixed(2));
+            $('#total-amount-input').val(total.toFixed(2));
+        }
+
+        function loadCustomerContacts(customerId) {
+            if (customerId) {
+                $.ajax({
+                    url: 'get_customer_contacts.php',
+                    type: 'GET',
+                    data: {customer_id: customerId},
+                    dataType: 'json',
+                    success: function(data) {
+                        var options = '<option value="">请选择联系人</option>';
+                        if (data && data.length > 0) {
+                            for (var i = 0; i < data.length; i++) {
+                                options += '<option value="' + data[i].id + '">' + data[i].contact_name + '</option>';
+                            }
+                        }
+                        $('#contact_id').html(options);
+                    }
+                });
+            } else {
+                $('#contact_id').html('<option value="">请选择联系人</option>');
+            }
+        }
+
+        function validateOrderForm() {
+            var orderCode = $('#order_code').val();
+            var customerId = $('#customer_id').val();
+            var hasProducts = false;
+
+            $('.product-select').each(function() {
+                if ($(this).val()) {
+                    hasProducts = true;
+                    return false; // break the loop
+                }
+            });
+
+            if (!orderCode) {
+                alert('订单编号不能为空');
+                $('#order_code').focus();
+                return false;
+            }
+
+            if (!customerId || customerId == '0') {
+                alert('请选择客户');
+                $('#customer_id').focus();
+                return false;
+            }
+
+            if (!hasProducts) {
+                alert('请至少选择一个产品');
+                return false;
+            }
+
+            return true;
+        }
+    </script>
+</div>
+</body>
+</html>

+ 177 - 0
order_save.php

@@ -0,0 +1,177 @@
+<?php
+require_once 'conn.php';
+checkLogin();
+
+// 辅助函数
+function textEncode($str) {
+    return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
+}
+
+function htmlEncode($str) {
+    return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
+}
+
+$isedit = false;
+$id = $_POST['id'] ?? '';
+if (!empty($id) && is_numeric($id)) {
+    $isedit = true;
+}
+
+// 获取表单数据 - 订单基本信息
+$order_code = mysqli_real_escape_string($conn, textEncode($_POST['order_code']));
+$customer_id = (int)$_POST['customer_id'];
+$contact_id = !empty($_POST['contact_id']) ? (int)$_POST['contact_id'] : "NULL";
+$employee_id = $_SESSION['employee_id'];
+$order_date = mysqli_real_escape_string($conn, $_POST['order_date']);
+$delivery_date = !empty($_POST['delivery_date']) ? "'" . mysqli_real_escape_string($conn, $_POST['delivery_date']) . "'" : "NULL";
+$actual_delivery_date = !empty($_POST['actual_delivery_date']) ? "'" . mysqli_real_escape_string($conn, $_POST['actual_delivery_date']) . "'" : "NULL";
+$order_status = (int)$_POST['order_status'];
+$payment_status = (int)$_POST['payment_status'];
+$currency = mysqli_real_escape_string($conn, textEncode($_POST['currency']));
+$notes = mysqli_real_escape_string($conn, htmlEncode($_POST['notes']));
+$internal_notes = mysqli_real_escape_string($conn, htmlEncode($_POST['internal_notes']));
+
+// 获取订单项信息
+$items = $_POST['items'] ?? [];
+
+// 计算订单总额
+$subtotal = 0;
+$shipping_fee = !empty($_POST['shipping_fee']) ? (float)$_POST['shipping_fee'] : 0;
+$discount_amount = !empty($_POST['discount_amount']) ? (float)$_POST['discount_amount'] : 0;
+
+foreach ($items as $item) {
+    $quantity = (int)$item['quantity'];
+    $unit_price = (float)$item['unit_price'];
+    $item_discount = (float)($item['discount_amount'] ?? 0);
+    $item_total = ($quantity * $unit_price) - $item_discount;
+    $subtotal += $item_total;
+}
+
+$total_amount = $subtotal + $shipping_fee - $discount_amount;
+
+// 验证必填字段
+if (empty($order_code)) {
+    echo "<script>alert('订单编号不能为空');history.back();</script>";
+    exit;
+}
+
+if ($customer_id <= 0) {
+    echo "<script>alert('请选择客户');history.back();</script>";
+    exit;
+}
+
+if (empty($items)) {
+    echo "<script>alert('订单必须包含至少一个产品');history.back();</script>";
+    exit;
+}
+
+// 处理保存
+if ($isedit) {
+    // 更新订单基本信息
+    $sql = "UPDATE orders SET 
+            order_code = '$order_code', 
+            customer_id = $customer_id, 
+            contact_id = $contact_id, 
+            employee_id = $employee_id, 
+            order_date = '$order_date', 
+            delivery_date = $delivery_date, 
+            actual_delivery_date = $actual_delivery_date, 
+            order_status = $order_status, 
+            payment_status = $payment_status, 
+            currency = '$currency', 
+            subtotal = $subtotal, 
+            shipping_fee = $shipping_fee, 
+            discount_amount = $discount_amount, 
+            total_amount = $total_amount, 
+            notes = '$notes', 
+            internal_notes = '$internal_notes', 
+            updated_at = NOW() 
+            WHERE id = $id";
+
+    mysqli_query($conn, $sql);
+
+    // 删除旧的订单项
+    $sql = "DELETE FROM order_items WHERE order_id = $id";
+    mysqli_query($conn, $sql);
+
+    // 添加新的订单项
+    foreach ($items as $item) {
+        if (empty($item['product_id'])) continue; // 跳过没有选择产品的行
+
+        $product_id = (int)$item['product_id'];
+        $quantity = (int)$item['quantity'];
+        $unit = mysqli_real_escape_string($conn, textEncode($item['unit']));
+        $unit_price = (float)$item['unit_price'];
+        $discount_percent = !empty($item['discount_percent']) ? (float)$item['discount_percent'] : 0;
+        $discount_amount = !empty($item['discount_amount']) ? (float)$item['discount_amount'] : 0;
+        $total_price = ($quantity * $unit_price) - $discount_amount;
+        $item_notes = mysqli_real_escape_string($conn, htmlEncode($item['notes'] ?? ''));
+
+        $sql = "INSERT INTO order_items (
+                order_id, product_id, quantity, unit, unit_price, 
+                discount_percent, discount_amount, total_price, notes, 
+                created_at, updated_at
+            ) VALUES (
+                $id, $product_id, $quantity, '$unit', $unit_price, 
+                $discount_percent, $discount_amount, $total_price, '$item_notes', 
+                NOW(), NOW()
+            )";
+
+        mysqli_query($conn, $sql);
+    }
+
+    $message = "订单更新成功!";
+} else {
+    // 创建新订单
+    $sql = "INSERT INTO orders (
+            order_code, customer_id, contact_id, employee_id, 
+            order_date, delivery_date, actual_delivery_date, 
+            order_status, payment_status, currency, 
+            subtotal, shipping_fee, discount_amount, total_amount, 
+            notes, internal_notes, created_at, updated_at
+        ) VALUES (
+            '$order_code', $customer_id, $contact_id, $employee_id, 
+            '$order_date', $delivery_date, $actual_delivery_date, 
+            $order_status, $payment_status, '$currency', 
+            $subtotal, $shipping_fee, $discount_amount, $total_amount, 
+            '$notes', '$internal_notes', NOW(), NOW()
+        )";
+
+    mysqli_query($conn, $sql);
+    $order_id = mysqli_insert_id($conn);
+
+    // 添加订单项
+    foreach ($items as $item) {
+        if (empty($item['product_id'])) continue; // 跳过没有选择产品的行
+
+        $product_id = (int)$item['product_id'];
+        $quantity = (int)$item['quantity'];
+        $unit = mysqli_real_escape_string($conn, textEncode($item['unit']));
+        $unit_price = (float)$item['unit_price'];
+        $discount_percent = !empty($item['discount_percent']) ? (float)$item['discount_percent'] : 0;
+        $discount_amount = !empty($item['discount_amount']) ? (float)$item['discount_amount'] : 0;
+        $total_price = ($quantity * $unit_price) - $discount_amount;
+        $item_notes = mysqli_real_escape_string($conn, htmlEncode($item['notes'] ?? ''));
+
+        $sql = "INSERT INTO order_items (
+                order_id, product_id, quantity, unit, unit_price, 
+                discount_percent, discount_amount, total_price, notes, 
+                created_at, updated_at
+            ) VALUES (
+                $order_id, $product_id, $quantity, '$unit', $unit_price, 
+                $discount_percent, $discount_amount, $total_price, '$item_notes', 
+                NOW(), NOW()
+            )";
+
+        mysqli_query($conn, $sql);
+    }
+
+    $message = "订单创建成功!";
+}
+
+// 重定向回订单列表页面
+$page = $_GET['Page'] ?? '';
+$keys = urlencode($_GET['Keys'] ?? '');
+echo "<script>alert('$message');location.href='order.php?keys=$keys&Page=$page';</script>";
+exit;
+?>