系统概述

1. 项目目标

开发一个基于 Web 的离线订单管理系统,主要服务于外贸公司,该系统旨在帮助业务员录入、管理、跟踪和导出来自邮件、展会、客户拜访等线下渠道获取的订单信息,实现订单处理的数字化和流程化,提高工作效率。

网页外贸离线订单管理系统 php
(图片来源网络,侵删)

2. 技术栈

  • 后端: PHP (推荐 PHP 7.4+)
  • 前端: HTML5, CSS3, JavaScript (原生或使用 Bootstrap/Tailwind CSS 快速构建响应式界面)
  • 数据库: MySQL 5.7+
  • Web 服务器: Apache 或 Nginx

3. 核心功能模块

  1. 用户管理: 用户登录、注册、权限控制(管理员、业务员、财务等)。
  2. 客户管理: 添加、编辑、查看客户信息(公司名、联系人、邮箱、电话、地址等)。
  3. 产品管理: 添加、编辑、查看产品信息(SKU、名称、描述、成本价、销售价等)。
  4. 订单管理:
    • 创建订单: 手动录入订单信息,包括客户、产品、数量、价格、币种、付款方式、交货期等。
    • 订单列表: 分页、搜索、排序(按订单号、客户、日期、状态)。
    • 订单详情: 查看和编辑订单的完整信息。
    • 订单状态管理: 标记订单状态(如:草稿、已确认、生产中、已发货、已完成、已取消)。
  5. 报表与统计:
    • 销售额统计(按时间段、客户、产品)。
    • 订单数量统计。
    • 可导出为 Excel 或 PDF。

数据库设计

这是系统的核心,良好的数据库设计至关重要,以下是几个核心表的设计。

1. 用户表 (users)

CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL COMMENT '用户名',
  `password` varchar(255) NOT NULL COMMENT '密码 (存储哈希值)',
  `full_name` varchar(100) NOT NULL COMMENT '真实姓名',
  `email` varchar(100) DEFAULT NULL COMMENT '邮箱',
  `role` enum('admin', 'sales', 'finance') NOT NULL DEFAULT 'sales' COMMENT '角色',
  `created_at` timestamp NOT NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

2. 客户表 (customers)

CREATE TABLE `customers` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `customer_code` varchar(20) NOT NULL COMMENT '客户编码',
  `company_name` varchar(255) NOT NULL COMMENT '公司名',
  `contact_person` varchar(100) DEFAULT NULL COMMENT '联系人',
  `email` varchar(100) DEFAULT NULL COMMENT '邮箱',
  `phone` varchar(20) DEFAULT NULL COMMENT '电话',
  `address` text COMMENT '地址',
  `country` varchar(50) DEFAULT NULL COMMENT '国家',
  `created_by` int(11) NOT NULL COMMENT '创建人ID (关联users.id)',
  `created_at` timestamp NOT NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `customer_code` (`customer_code`),
  KEY `created_by` (`created_by`),
  CONSTRAINT `customers_ibfk_1` FOREIGN KEY (`created_by`) REFERENCES `users` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

3. 产品表 (products)

CREATE TABLE `products` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `sku` varchar(50) NOT NULL COMMENT 'SKU/产品编码',
  `product_name` varchar(255) NOT NULL COMMENT '产品名称',
  `description` text COMMENT '产品描述',
  `cost_price` decimal(10, 2) DEFAULT NULL COMMENT '成本价',
  `sale_price` decimal(10, 2) NOT NULL COMMENT '销售价',
  `currency` char(3) NOT NULL DEFAULT 'USD' COMMENT '币种',
  `created_by` int(11) NOT NULL COMMENT '创建人ID',
  `created_at` timestamp NOT NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `sku` (`sku`),
  KEY `created_by` (`created_by`),
  CONSTRAINT `products_ibfk_1` FOREIGN KEY (`created_by`) REFERENCES `users` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

4. 订单主表 (orders)

CREATE TABLE `orders` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `order_number` varchar(50) NOT NULL COMMENT '订单号',
  `customer_id` int(11) NOT NULL COMMENT '客户ID (关联customers.id)',
  `order_date` date NOT NULL COMMENT '下单日期',
  `delivery_date` date DEFAULT NULL COMMENT '要求交货日期',
  `total_amount` decimal(15, 2) NOT NULL COMMENT '订单总金额',
  `currency` char(3) NOT NULL DEFAULT 'USD' COMMENT '币种',
  `payment_terms` varchar(100) DEFAULT NULL COMMENT '付款方式 (如: T/T, L/C)',
  `shipping_address` text COMMENT '收货地址',
  `status` enum('draft', 'confirmed', 'in_production', 'shipped', 'completed', 'cancelled') NOT NULL DEFAULT 'draft' COMMENT '订单状态',
  `notes` text COMMENT '备注',
  `created_by` int(11) NOT NULL COMMENT '创建人ID',
  `created_at` timestamp NOT NULL DEFAULT current_timestamp(),
  `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `order_number` (`order_number`),
  KEY `customer_id` (`customer_id`),
  KEY `created_by` (`created_by`),
  CONSTRAINT `orders_ibfk_1` FOREIGN KEY (`customer_id`) REFERENCES `customers` (`id`),
  CONSTRAINT `orders_ibfk_2` FOREIGN KEY (`created_by`) REFERENCES `users` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

5. 订单明细表 (order_items)

CREATE TABLE `order_items` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `order_id` int(11) NOT NULL COMMENT '订单ID (关联orders.id)',
  `product_id` int(11) NOT NULL COMMENT '产品ID (关联products.id)',
  `quantity` int(11) NOT NULL COMMENT '数量',
  `unit_price` decimal(10, 2) NOT NULL COMMENT '单价',
  `total_price` decimal(10, 2) NOT NULL COMMENT '小计',
  PRIMARY KEY (`id`),
  KEY `order_id` (`order_id`),
  KEY `product_id` (`product_id`),
  CONSTRAINT `order_items_ibfk_1` FOREIGN KEY (`order_id`) REFERENCES `orders` (`id`),
  CONSTRAINT `order_items_ibfk_2` FOREIGN KEY (`product_id`) REFERENCES `products` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

核心功能实现

我们将以 订单创建订单列表 为例,展示核心的 PHP 代码。

1. 项目结构

/your-project-root
|-- /assets
|   |-- /css
|   |-- /js
|-- /includes
|   |-- db.php          # 数据库连接
|   |-- header.php      # 公共头部
|   |-- footer.php      # 公共底部
|   |-- auth_check.php  # 权限检查
|-- index.php           # 首页/仪表盘
|-- login.php           # 登录页面
|-- orders.php          # 订单列表页面
|-- create_order.php    # 创建订单页面
|-- order_details.php   # 订单详情页面
|-- ...

2. 数据库连接 (includes/db.php)

<?php
// includes/db.php
$host = 'localhost';
$dbname = 'your_database_name';
$username = 'your_db_username';
$password = 'your_db_password';
try {
    $pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $username, $password);
    // 设置 PDO 错误模式为异常
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
    die("数据库连接失败: " . $e->getMessage());
}
?>

3. 订单列表页面 (orders.php)

这个页面将展示所有订单,并提供搜索和分页功能。

<?php
session_start();
if (!isset($_SESSION['user_id'])) {
    header('Location: login.php');
    exit;
}
require_once 'includes/db.php';
require_once 'includes/header.php';
// --- 分页逻辑 ---
$records_per_page = 10;
$page = isset($_GET['page']) && is_numeric($_GET['page']) ? (int)$_GET['page'] : 1;
$offset = ($page - 1) * $records_per_page;
// --- 搜索逻辑 ---
$search_query = "WHERE 1=1";
if (!empty($_GET['search'])) {
    $search_term = '%' . $_GET['search'] . '%';
    $search_query .= " AND (o.order_number LIKE :search OR c.company_name LIKE :search)";
}
// --- 获取订单总数 (用于分页) ---
$total_stmt = $pdo->prepare("SELECT COUNT(*) FROM orders o JOIN customers c ON o.customer_id = c.id $search_query");
if (!empty($_GET['search'])) {
    $total_stmt->bindParam(':search', $search_term);
}
$total_stmt->execute();
$total_records = $total_stmt->fetchColumn();
$total_pages = ceil($total_records / $records_per_page);
// --- 获取当前页的订单数据 ---
$stmt = $pdo->prepare("
    SELECT o.*, c.company_name 
    FROM orders o 
    JOIN customers c ON o.customer_id = c.id 
    $search_query 
    ORDER BY o.created_at DESC 
    LIMIT :offset, :limit
");
if (!empty($_GET['search'])) {
    $stmt->bindParam(':search', $search_term);
}
$stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
$stmt->bindValue(':limit', $records_per_page, PDO::PARAM_INT);
$stmt->execute();
$orders = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<h1 class="mb-4">订单列表</h1>
<!-- 搜索表单 -->
<form action="orders.php" method="get" class="mb-4">
    <div class="input-group">
        <input type="text" name="search" class="form-control" placeholder="搜索订单号或客户名..." value="<?= htmlspecialchars($_GET['search'] ?? '') ?>">
        <button class="btn btn-primary" type="submit">搜索</button>
        <a href="orders.php" class="btn btn-secondary">重置</a>
    </div>
</form>
<!-- 订单列表表格 -->
<div class="table-responsive">
    <table class="table table-striped table-hover">
        <thead>
            <tr>
                <th>订单号</th>
                <th>客户</th>
                <th>下单日期</th>
                <th>总金额</th>
                <th>状态</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
            <?php if ($orders): ?>
                <?php foreach ($orders as $order): ?>
                    <tr>
                        <td><?= htmlspecialchars($order['order_number']) ?></td>
                        <td><?= htmlspecialchars($order['company_name']) ?></td>
                        <td><?= $order['order_date'] ?></td>
                        <td><?= htmlspecialchars($order['currency']) ?> <?= number_format($order['total_amount'], 2) ?></td>
                        <td><span class="badge bg-info"><?= htmlspecialchars($order['status']) ?></span></td>
                        <td>
                            <a href="order_details.php?id=<?= $order['id'] ?>" class="btn btn-sm btn-info">查看</a>
                            <a href="create_order.php?id=<?= $order['id'] ?>" class="btn btn-sm btn-warning">编辑</a>
                        </td>
                    </tr>
                <?php endforeach; ?>
            <?php else: ?>
                <tr>
                    <td colspan="6" class="text-center">没有找到订单。</td>
                </tr>
            <?php endif; ?>
        </tbody>
    </table>
</div>
<!-- 分页链接 -->
<nav aria-label="Page navigation">
    <ul class="pagination justify-content-center">
        <?php for ($i = 1; $i <= $total_pages; $i++): ?>
            <li class="page-item <?= $i == $page ? 'active' : '' ?>">
                <a class="page-link" href="orders.php?page=<?= $i ?>&search=<?= htmlspecialchars($_GET['search'] ?? '') ?>"><?= $i ?></a>
            </li>
        <?php endfor; ?>
    </ul>
</nav>
<?php require_once 'includes/footer.php'; ?>

4. 创建/编辑订单页面 (create_order.php)

这个页面比较复杂,需要一个表单来输入订单信息,并且需要动态地添加产品行。

网页外贸离线订单管理系统 php
(图片来源网络,侵删)
<?php
session_start();
if (!isset($_SESSION['user_id'])) {
    header('Location: login.php');
    exit;
}
require_once 'includes/db.php';
require_once 'includes/header.php';
// 获取所有客户和产品用于下拉列表
$stmt_customers = $pdo->query("SELECT id, company_name FROM customers ORDER BY company_name");
$customers = $stmt_customers->fetchAll(PDO::FETCH_ASSOC);
$stmt_products = $pdo->query("SELECT id, sku, product_name, sale_price, currency FROM products ORDER BY product_name");
$products = $stmt_products->fetchAll(PDO::FETCH_ASSOC);
$is_edit = isset($_GET['id']);
$order_data = null;
$order_items = [];
if ($is_edit) {
    $order_id = $_GET['id'];
    // 获取订单主信息
    $stmt = $pdo->prepare("SELECT * FROM orders WHERE id = ?");
    $stmt->execute([$order_id]);
    $order_data = $stmt->fetch(PDO::FETCH_ASSOC);
    // 获取订单明细
    $stmt_items = $pdo->prepare("
        SELECT oi.*, p.sku, p.product_name 
        FROM order_items oi 
        JOIN products p ON oi.product_id = p.id 
        WHERE oi.order_id = ?
    ");
    $stmt_items->execute([$order_id]);
    $order_items = $stmt_items->fetchAll(PDO::FETCH_ASSOC);
}
?>
<h1 class="mb-4"><?= $is_edit ? '编辑订单' : '创建新订单' ?></h1>
<form action="process_order.php" method="post">
    <input type="hidden" name="order_id" value="<?= $is_edit ? $order_data['id'] : '' ?>">
    <div class="row mb-3">
        <div class="col-md-6">
            <label for="order_number" class="form-label">订单号</label>
            <input type="text" class="form-control" id="order_number" name="order_number" value="<?= $is_edit ? htmlspecialchars($order_data['order_number']) : '' ?>" required>
        </div>
        <div class="col-md-6">
            <label for="customer_id" class="form-label">客户</label>
            <select class="form-select" id="customer_id" name="customer_id" required>
                <option value="">请选择客户</option>
                <?php foreach ($customers as $customer): ?>
                    <option value="<?= $customer['id'] ?>" <?= ($is_edit && $order_data['customer_id'] == $customer['id']) ? 'selected' : '' ?>><?= htmlspecialchars($customer['company_name']) ?></option>
                <?php endforeach; ?>
            </select>
        </div>
    </div>
    <div class="row mb-3">
        <div class="col-md-6">
            <label for="order_date" class="form-label">下单日期</label>
            <input type="date" class="form-control" id="order_date" name="order_date" value="<?= $is_edit ? $order_data['order_date'] : date('Y-m-d') ?>" required>
        </div>
        <div class="col-md-6">
            <label for="currency" class="form-label">币种</label>
            <select class="form-select" id="currency" name="currency">
                <option value="USD" <?= ($is_edit && $order_data['currency'] == 'USD') ? 'selected' : '' ?>>USD</option>
                <option value="EUR" <?= ($is_edit && $order_data['currency'] == 'EUR') ? 'selected' : '' ?>>EUR</option>
                <option value="CNY" <?= ($is_edit && $order_data['currency'] == 'CNY') ? 'selected' : '' ?>>CNY</option>
            </select>
        </div>
    </div>
    <!-- 订单明细表格 -->
    <h3 class="mt-4 mb-3">订单明细</h3>
    <div class="table-responsive">
        <table class="table table-bordered" id="itemsTable">
            <thead>
                <tr>
                    <th>产品</th>
                    <th>SKU</th>
                    <th>单价</th>
                    <th>数量</th>
                    <th>小计</th>
                    <th>操作</th>
                </tr>
            </thead>
            <tbody>
                <?php if ($is_edit && $order_items): ?>
                    <?php foreach ($order_items as $item): ?>
                    <tr>
                        <input type="hidden" name="product_id[]" value="<?= $item['product_id'] ?>">
                        <td><?= htmlspecialchars($item['product_name']) ?></td>
                        <td><?= htmlspecialchars($item['sku']) ?></td>
                        <td><input type="number" class="form-control form-control-sm item-price" value="<?= $item['unit_price'] ?>" data-price="<?= $item['unit_price'] ?>" readonly></td>
                        <td><input type="number" class="form-control form-control-sm item-quantity" name="quantity[]" value="<?= $item['quantity'] min="1" onchange="calculateRow(this)"></td>
                        <td><input type="text" class="form-control form-control-sm item-total" value="<?= $item['total_price'] ?>" readonly></td>
                        <td><button type="button" class="btn btn-sm btn-danger remove-row">删除</button></td>
                    </tr>
                    <?php endforeach; ?>
                <?php else: ?>
                    <!-- 默认空行 -->
                    <tr>
                        <td colspan="6" class="text-center">请添加产品</td>
                    </tr>
                <?php endif; ?>
            </tbody>
            <tfoot>
                <tr>
                    <td colspan="4"><strong>订单总金额:</strong></td>
                    <td><strong id="grandTotal">0.00</strong></td>
                    <td></td>
                </tr>
            </tfoot>
        </table>
    </div>
    <button type="button" class="btn btn-secondary mb-3" onclick="addRow()">+ 添加产品</button>
    <div class="mb-3">
        <label for="notes" class="form-label">备注</label>
        <textarea class="form-control" id="notes" name="notes" rows="3"><?= $is_edit ? htmlspecialchars($order_data['notes']) : '' ?></textarea>
    </div>
    <button type="submit" class="btn btn-primary">保存订单</button>
    <a href="orders.php" class="btn btn-secondary">取消</a>
</form>
<?php require_once 'includes/footer.php'; ?>
<!-- JavaScript 用于动态添加行和计算金额 -->
<script>
function addRow() {
    const tbody = document.querySelector('#itemsTable tbody');
    const rowCount = tbody.rows.length;
    const newRow = tbody.insertRow();
    newRow.innerHTML = `
        <td>
            <select name="product_id[]" class="form-select product-select" onchange="updateProductInfo(this)">
                <option value="">请选择产品</option>
                <?php foreach ($products as $product): ?>
                    <option value="<?= $product['id'] ?>" data-price="<?= $product['sale_price'] ?>" data-currency="<?= $product['currency'] ?>"><?= htmlspecialchars($product['product_name']) ?> (<?= htmlspecialchars($product['sku']) ?>)</option>
                <?php endforeach; ?>
            </select>
        </td>
        <td><input type="text" class="form-control sku-input" readonly></td>
        <td><input type="number" class="form-control form-control-sm item-price" readonly></td>
        <td><input type="number" class="form-control form-control-sm item-quantity" min="1" value="1" onchange="calculateRow(this)"></td>
        <td><input type="text" class="form-control form-control-sm item-total" readonly></td>
        <td><button type="button" class="btn btn-sm btn-danger remove-row">删除</button></td>
    `;
    attachRemoveListener(newRow.querySelector('.remove-row'));
}
function updateProductInfo(selectElement) {
    const option = selectElement.options[selectElement.selectedIndex];
    const price = option.getAttribute('data-price');
    const sku = option.text.split('(')[1].replace(')', '');
    const row = selectElement.closest('tr');
    row.querySelector('.sku-input').value = sku;
    row.querySelector('.item-price').value = price;
    calculateRow(row.querySelector('.item-quantity'));
}
function calculateRow(quantityInput) {
    const row = quantityInput.closest('tr');
    const price = parseFloat(row.querySelector('.item-price').value) || 0;
    const quantity = parseInt(quantityInput.value) || 0;
    const total = price * quantity;
    row.querySelector('.item-total').value = total.toFixed(2);
    updateGrandTotal();
}
function updateGrandTotal() {
    let total = 0;
    document.querySelectorAll('.item-total').forEach(input => {
        total += parseFloat(input.value) || 0;
    });
    document.getElementById('grandTotal').textContent = total.toFixed(2);
}
function attachRemoveListener(button) {
    button.addEventListener('click', function() {
        this.closest('tr').remove();
        updateGrandTotal();
    });
}
// 为初始的删除按钮添加监听器
document.querySelectorAll('.remove-row').forEach(button => {
    attachRemoveListener(button);
});
</script>

5. 处理订单数据 (process_order.php)

这个脚本接收来自 create_order.php 表单的数据,并将其保存到数据库中,这里需要使用事务来确保数据的一致性。

<?php
session_start();
require_once 'includes/db.php';
// 验证用户登录
if (!isset($_SESSION['user_id'])) {
    die('未授权访问');
}
// 验证并获取POST数据
$order_number = $_POST['order_number'] ?? '';
$customer_id = $_POST['customer_id'] ?? 0;
$order_date = $_POST['order_date'] ?? '';
$currency = $_POST['currency'] ?? 'USD';
$notes = $_POST['notes'] ?? '';
$order_id = $_POST['order_id'] ?? 0;
$product_ids = $_POST['product_id'] ?? [];
$quantities = $_POST['quantity'] ?? [];
// 基本数据验证
if (empty($order_number) || !$customer_id || empty($order_date) || empty($product_ids)) {
    die('请填写所有必填项。');
}
try {
    $pdo->beginTransaction();
    // 1. 计算订单总金额
    $grand_total = 0;
    $item_details = [];
    for ($i = 0; $i < count($product_ids); $i++) {
        if (empty($product_ids[$i]) || $quantities[$i] <= 0) continue;
        $stmt = $pdo->prepare("SELECT sale_price FROM products WHERE id = ?");
        $stmt->execute([$product_ids[$i]]);
        $product = $stmt->fetch(PDO::FETCH_ASSOC);
        if (!$product) {
            throw new Exception("产品ID {$product_ids[$i]} 不存在。");
        }
        $unit_price = $product['sale_price'];
        $total_price = $unit_price * $quantities[$i];
        $grand_total += $total_price;
        $item_details[] = [
            'product_id' => $product_ids[$i],
            'quantity' => $quantities[$i],
            'unit_price' => $unit_price,
            'total_price' => $total_price
        ];
    }
    if ($grand_total <= 0) {
        throw new Exception('订单总金额必须大于零。');
    }
    // 2. 更新或插入订单主表
    if ($order_id) {
        // 编辑模式
        $stmt = $pdo->prepare("
            UPDATE orders 
            SET customer_id = ?, order_date = ?, currency = ?, total_amount = ?, notes = ? 
            WHERE id = ? AND created_by = ?
        ");
        $stmt->execute([$customer_id, $order_date, $currency, $grand_total, $notes, $order_id, $_SESSION['user_id']]);
    } else {
        // 创建模式
        $stmt = $pdo->prepare("
            INSERT INTO orders (order_number, customer_id, order_date, currency, total_amount, notes, created_by) 
            VALUES (?, ?, ?, ?, ?, ?, ?)
        ");
        $stmt->execute([$order_number, $customer_id, $order_date, $currency, $grand_total, $notes, $_SESSION['user_id']]);
        $order_id = $pdo->lastInsertId();
    }
    // 3. 删除旧的订单明细 (如果是编辑模式)
    if ($order_id) {
        $stmt = $pdo->prepare("DELETE FROM order_items WHERE order_id = ?");
        $stmt->execute([$order_id]);
    }
    // 4. 插入新的订单明细
    $stmt = $pdo->prepare("INSERT INTO order_items (order_id, product_id, quantity, unit_price, total_price) VALUES (?, ?, ?, ?, ?)");
    foreach ($item_details as $item) {
        $stmt->execute([$order_id, $item['product_id'], $item['quantity'], $item['unit_price'], $item['total_price']]);
    }
    $pdo->commit();
    header('Location: order_details.php?id=' . $order_id);
} catch (Exception $e) {
    $pdo->rollBack();
    die("保存订单时发生错误: " . $e->getMessage());
}
?>

后续开发建议

  1. 用户认证与授权:

    • 实现一个完整的登录/注册系统。
    • 使用 $_SESSION 来管理用户登录状态。
    • 创建一个权限检查函数(如 is_admin(), is_sales()),在每个需要权限的页面顶部调用它。
  2. 安全加固:

    • 密码哈希: 在存储用户密码时,永远不要存明文,使用 password_hash()password_verify()
    • 防止SQL注入: 代码中已使用 PDO 的预处理语句,这是最好的实践。
    • 防止XSS攻击: 在输出用户到HTML页面的数据前,使用 htmlspecialchars() 函数进行转义。
    • 输入验证: 对所有用户输入(无论是GET还是POST)进行严格的验证和过滤。
  3. 报表功能:

    网页外贸离线订单管理系统 php
    (图片来源网络,侵删)
    • 使用 PHPExcel 或 PhpSpreadsheet 库来生成 Excel 报表。
    • 使用 TCPDF 或 DomPDF 库来生成 PDF 报表。
    • 编写 SQL 查询,按时间、客户等维度聚合销售数据。
  4. 用户体验优化:

    • 使用 AJAX 来实现无刷新加载、搜索等功能,提升交互体验。
    • 引入 Bootstrap 或 Tailwind CSS 等现代前端框架,让界面更美观、响应式。
    • 添加加载动画、操作成功/失败的提示信息。
  5. 部署与维护:

    • 使用 Composer 来管理 PHP 依赖。
    • 将配置信息(如数据库凭证)放在单独的 .env 文件中,而不是代码里。
    • 定期备份数据库。

这份指南为您提供了一个坚实的基础,您可以根据这个框架继续扩展和完善功能,例如添加邮件通知、文件上传(如合同附件)等高级功能。