简单 现代化销售管理系统 - HTML/CSS/JS 实现

22 阅读14分钟

图:

image.png

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>现代销售管理系统</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <style>
        :root {
            --primary: #4361ee;
            --secondary: #3f37c9;
            --accent: #4895ef;
            --dark: #1a1a2e;
            --darker: #0d0d1a;
            --light: #f8f9fa;
            --success: #4cc9f0;
            --danger: #f72585;
            --warning: #f8961e;
            --card-bg: rgba(255, 255, 255, 0.05);
            --border: rgba(255, 255, 255, 0.1);
            --text: #e0e0e0;
            --text-muted: #a0a0a0;
            --transition: all 0.3s ease;
            --shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
            --glass: rgba(255, 255, 255, 0.05);
            --glass-border: rgba(255, 255, 255, 0.1);
        }

        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }

        body {
            background: linear-gradient(135deg, var(--darker) 0%, var(--dark) 100%);
            color: var(--text);
            min-height: 100vh;
            overflow-x: hidden;
            -webkit-font-smoothing: antialiased;
            -moz-osx-font-smoothing: grayscale;
        }

        /* 登录界面样式 */
        .login-container {
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            padding: 20px;
            background: linear-gradient(135deg, #0f0c29, #302b63, #24243e);
        }

        .login-card {
            background: var(--glass);
            backdrop-filter: blur(10px);
            border: 1px solid var(--glass-border);
            border-radius: 16px;
            padding: 30px;
            width: 100%;
            max-width: 420px;
            box-shadow: var(--shadow);
            transform: translateY(0);
            transition: var(--transition);
        }

        .login-card:hover {
            transform: translateY(-5px);
            box-shadow: 0 12px 24px rgba(0, 0, 0, 0.4);
        }

        .login-header {
            text-align: center;
            margin-bottom: 25px;
        }

        .login-header h1 {
            font-size: 24px;
            margin-bottom: 8px;
            background: linear-gradient(90deg, var(--accent), var(--success));
            -webkit-background-clip: text;
            background-clip: text;
            color: transparent;
        }

        .login-header p {
            color: var(--text-muted);
            font-size: 13px;
        }

        .form-group {
            margin-bottom: 18px;
        }

        .form-group label {
            display: block;
            margin-bottom: 6px;
            font-size: 13px;
            color: var(--text);
            font-weight: 500;
        }

        .form-control {
            width: 100%;
            padding: 12px 16px;
            background: rgba(255, 255, 255, 0.07);
            border: 1px solid var(--border);
            border-radius: 8px;
            color: var(--text);
            font-size: 15px;
            transition: var(--transition);
            -webkit-appearance: none;
        }

        .form-control:focus {
            outline: none;
            border-color: var(--accent);
            background: rgba(255, 255, 255, 0.1);
            box-shadow: 0 0 0 3px rgba(72, 149, 239, 0.2);
        }

        .btn {
            padding: 12px 24px;
            border: none;
            border-radius: 8px;
            font-size: 15px;
            font-weight: 600;
            cursor: pointer;
            transition: var(--transition);
            display: inline-flex;
            align-items: center;
            justify-content: center;
            gap: 8px;
            -webkit-tap-highlight-color: transparent;
        }

        .btn:active {
            transform: scale(0.98);
        }

        .btn-primary {
            background: linear-gradient(90deg, var(--primary), var(--secondary));
            color: white;
            width: 100%;
            padding: 14px;
        }

        .btn-primary:hover {
            transform: translateY(-2px);
            box-shadow: 0 6px 12px rgba(67, 97, 238, 0.4);
        }

        .btn-success {
            background: linear-gradient(90deg, #10b981, #059669);
            color: white;
        }

        .btn-danger {
            background: linear-gradient(90deg, var(--danger), #d9046d);
            color: white;
        }

        .btn-warning {
            background: linear-gradient(90deg, var(--warning), #e67e22);
            color: white;
        }

        /* 主界面样式 */
        .app-container {
            display: none;
            min-height: 100vh;
        }

        /* 顶部导航栏 - 修复移动端显示 */
        .topbar {
            background: var(--glass);
            backdrop-filter: blur(10px);
            border-bottom: 1px solid var(--glass-border);
            padding: 12px 16px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            position: sticky;
            top: 0;
            z-index: 100;
            height: 60px;
        }

        .logo {
            font-size: 18px;
            font-weight: 700;
            display: flex;
            align-items: center;
            gap: 10px;
            background: linear-gradient(90deg, var(--accent), var(--success));
            -webkit-background-clip: text;
            background-clip: text;
            color: transparent;
            white-space: nowrap;
        }

        .menu-toggle {
            display: none;
            background: transparent;
            border: none;
            color: var(--text);
            font-size: 20px;
            cursor: pointer;
            padding: 8px;
            width: 40px;
            height: 40px;
            border-radius: 8px;
            transition: var(--transition);
            -webkit-tap-highlight-color: transparent;
        }

        .menu-toggle:active {
            background: rgba(255, 255, 255, 0.1);
            transform: scale(0.95);
        }

        .user-info {
            display: flex;
            align-items: center;
            gap: 12px;
            font-size: 14px;
        }

        .logout-btn {
            background: transparent;
            border: 1px solid var(--border);
            color: var(--text);
            padding: 6px 12px;
            border-radius: 6px;
            cursor: pointer;
            transition: var(--transition);
            font-size: 13px;
            -webkit-tap-highlight-color: transparent;
        }

        .logout-btn:hover {
            background: rgba(255, 255, 255, 0.1);
            border-color: var(--danger);
            color: var(--danger);
        }

        /* 侧边栏导航 - 移动端优化 */
        .sidebar {
            position: fixed;
            top: 60px;
            left: 0;
            width: 240px;
            height: calc(100vh - 60px);
            background: var(--glass);
            backdrop-filter: blur(10px);
            border-right: 1px solid var(--glass-border);
            padding: 12px 0;
            transition: var(--transition);
            z-index: 90;
            overflow-y: auto;
            transform: translateX(0);
        }

        .nav-item {
            padding: 12px 20px;
            display: flex;
            align-items: center;
            gap: 12px;
            color: var(--text-muted);
            cursor: pointer;
            transition: var(--transition);
            border-left: 3px solid transparent;
            margin: 4px 8px;
            border-radius: 8px;
            font-size: 14px;
            -webkit-tap-highlight-color: transparent;
        }

        .nav-item:hover, .nav-item.active {
            background: rgba(255, 255, 255, 0.08);
            color: var(--text);
            border-left-color: var(--accent);
        }

        .nav-item:active {
            background: rgba(255, 255, 255, 0.12);
            transform: scale(0.98);
        }

        .nav-item i {
            width: 20px;
            text-align: center;
            font-size: 16px;
        }

        /* 主内容区 */
        .main-content {
            margin-left: 240px;
            padding: 16px;
            transition: var(--transition);
        }

        .page {
            display: none;
            animation: fadeIn 0.4s ease;
        }

        .page.active {
            display: block;
        }

        @keyframes fadeIn {
            from { opacity: 0; transform: translateY(10px); }
            to { opacity: 1; transform: translateY(0); }
        }

        .page-header {
            margin-bottom: 16px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            flex-wrap: wrap;
            gap: 12px;
        }

        .page-title {
            font-size: 20px;
            font-weight: 600;
            background: linear-gradient(90deg, var(--text), var(--text-muted));
            -webkit-background-clip: text;
            background-clip: text;
            color: transparent;
        }

        /* 卡片和仪表盘 */
        .dashboard-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
            gap: 12px;
            margin-bottom: 16px;
        }

        .card {
            background: var(--card-bg);
            border: 1px solid var(--border);
            border-radius: 10px;
            padding: 16px;
            transition: var(--transition);
            box-shadow: var(--shadow);
            backdrop-filter: blur(5px);
        }

        .card:hover {
            transform: translateY(-3px);
            box-shadow: 0 8px 16px rgba(0, 0, 0, 0.35);
            border-color: var(--accent);
        }

        .card-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 8px;
        }

        .card-title {
            font-size: 13px;
            color: var(--text-muted);
            font-weight: 500;
        }

        .card-value {
            font-size: 22px;
            font-weight: 700;
            margin-bottom: 6px;
            word-break: break-all;
        }

        .card-footer {
            font-size: 11px;
            color: var(--text-muted);
            display: flex;
            align-items: center;
            gap: 4px;
        }

        .trend-up {
            color: #10b981;
        }

        .trend-down {
            color: var(--danger);
        }

        /* 图表容器 */
        .chart-container {
            background: var(--card-bg);
            border: 1px solid var(--border);
            border-radius: 10px;
            padding: 16px;
            margin-bottom: 16px;
            height: 280px;
            box-shadow: var(--shadow);
            backdrop-filter: blur(5px);
        }

        .chart-title {
            margin-bottom: 12px;
            font-size: 16px;
            font-weight: 600;
            color: var(--text);
        }

        /* 表格样式 */
        .table-container {
            background: var(--card-bg);
            border: 1px solid var(--border);
            border-radius: 10px;
            padding: 12px;
            overflow-x: auto;
            box-shadow: var(--shadow);
            backdrop-filter: blur(5px);
            margin-bottom: 16px;
        }

        .table-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 12px;
            padding: 0 4px;
        }

        .table-header h3 {
            font-size: 16px;
            font-weight: 600;
        }

        table {
            width: 100%;
            border-collapse: collapse;
            font-size: 13px;
        }

        th, td {
            padding: 10px 8px;
            text-align: left;
            border-bottom: 1px solid var(--border);
            white-space: nowrap;
        }

        th {
            color: var(--text-muted);
            font-weight: 500;
            font-size: 12px;
            background: rgba(255, 255, 255, 0.03);
        }

        tr:hover {
            background: rgba(255, 255, 255, 0.05);
        }

        .status {
            padding: 4px 8px;
            border-radius: 12px;
            font-size: 11px;
            font-weight: 600;
            display: inline-block;
        }

        .status-completed {
            background: rgba(16, 185, 129, 0.15);
            color: #10b981;
        }

        .status-pending {
            background: rgba(248, 150, 30, 0.15);
            color: #f8961e;
        }

        .status-cancelled {
            background: rgba(247, 37, 133, 0.15);
            color: var(--danger);
        }

        /* 表单样式 */
        .form-grid {
            display: grid;
            grid-template-columns: 1fr;
            gap: 12px;
            margin-bottom: 16px;
        }

        .form-row {
            display: flex;
            gap: 10px;
            margin-top: 16px;
            flex-wrap: wrap;
        }

        .form-row .btn {
            flex: 1;
            min-width: 120px;
        }

        /* 模态框 */
        .modal {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.7);
            backdrop-filter: blur(5px);
            z-index: 1000;
            align-items: center;
            justify-content: center;
            padding: 16px;
        }

        .modal.active {
            display: flex;
            animation: fadeIn 0.3s ease;
        }

        .modal-content {
            background: var(--dark);
            border: 1px solid var(--border);
            border-radius: 12px;
            width: 100%;
            max-width: 500px;
            padding: 20px;
            max-height: 90vh;
            overflow-y: auto;
            box-shadow: var(--shadow);
        }

        .modal-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 16px;
            padding-bottom: 12px;
            border-bottom: 1px solid var(--border);
        }

        .modal-title {
            font-size: 18px;
            font-weight: 600;
        }

        .close-modal {
            background: transparent;
            border: none;
            color: var(--text);
            font-size: 20px;
            cursor: pointer;
            width: 32px;
            height: 32px;
            border-radius: 6px;
            transition: var(--transition);
            -webkit-tap-highlight-color: transparent;
        }

        .close-modal:hover {
            background: rgba(255, 255, 255, 0.1);
            color: var(--danger);
            transform: rotate(90deg);
        }

        .close-modal:active {
            transform: scale(0.9);
        }

        /* 响应式调整 - 修复移动端 */
        @media (max-width: 992px) {
            .sidebar {
                transform: translateX(-105%);
                width: 260px;
                background: var(--darker);
                border-right: 1px solid var(--glass-border);
            }

            .sidebar.open {
                transform: translateX(0);
                box-shadow: 8px 0 24px rgba(0, 0, 0, 0.5);
            }

            .main-content {
                margin-left: 0;
                padding: 12px;
            }

            .menu-toggle {
                display: block;
            }

            .logo span {
                font-size: 16px;
            }

            .user-info span {
                display: none;
            }

            .logout-btn {
                padding: 6px 10px;
                font-size: 12px;
            }

            .topbar {
                padding: 10px 12px;
            }

            .dashboard-grid {
                grid-template-columns: repeat(2, 1fr);
            }

            .card-value {
                font-size: 18px;
            }

            .chart-container {
                height: 240px;
            }

            .table-container {
                padding: 8px;
            }

            table {
                font-size: 12px;
            }

            th, td {
                padding: 8px 6px;
            }

            .page-title {
                font-size: 18px;
            }

            .btn {
                padding: 10px 16px;
                font-size: 14px;
            }

            .action-btn {
                padding: 4px 8px;
                font-size: 11px;
                margin-right: 2px;
            }

            .modal-content {
                padding: 16px;
                max-width: 95%;
            }

            .modal-title {
                font-size: 16px;
            }
        }

        @media (max-width: 576px) {
            .dashboard-grid {
                grid-template-columns: 1fr;
            }

            .form-grid {
                grid-template-columns: 1fr;
            }

            .form-row {
                flex-direction: column;
            }

            .form-row .btn {
                width: 100%;
            }

            .table-container {
                overflow-x: scroll;
                -webkit-overflow-scrolling: touch;
            }

            table {
                min-width: 600px;
            }

            .user-info {
                gap: 8px;
            }

            .logout-btn {
                padding: 6px 8px;
            }

            .login-card {
                padding: 20px;
            }

            .login-header h1 {
                font-size: 20px;
            }
        }

        /* 遮罩层 - 点击关闭侧边栏 */
        .sidebar-overlay {
            display: none;
            position: fixed;
            top: 60px;
            left: 0;
            width: 100%;
            height: calc(100vh - 60px);
            background: rgba(0, 0, 0, 0.5);
            z-index: 85;
            backdrop-filter: blur(2px);
        }

        .sidebar-overlay.active {
            display: block;
            animation: fadeIn 0.3s ease;
        }

        /* 空状态 */
        .empty-state {
            text-align: center;
            padding: 40px 20px;
            color: var(--text-muted);
        }

        .empty-state i {
            font-size: 48px;
            margin-bottom: 15px;
            opacity: 0.5;
        }

        /* 通知提示 */
        .notification {
            position: fixed;
            top: 70px;
            right: 16px;
            background: var(--glass);
            backdrop-filter: blur(10px);
            border: 1px solid var(--glass-border);
            border-left: 4px solid var(--success);
            border-radius: 8px;
            padding: 12px 16px;
            box-shadow: var(--shadow);
            transform: translateX(150%);
            transition: var(--transition);
            z-index: 1001;
            min-width: 280px;
            max-width: 90vw;
        }

        .notification.show {
            transform: translateX(0);
        }

        .notification.error {
            border-left-color: var(--danger);
        }

        .notification.warning {
            border-left-color: var(--warning);
        }

        /* 滚动条样式 */
        ::-webkit-scrollbar {
            width: 6px;
            height: 6px;
        }

        ::-webkit-scrollbar-track {
            background: rgba(255, 255, 255, 0.05);
        }

        ::-webkit-scrollbar-thumb {
            background: rgba(255, 255, 255, 0.2);
            border-radius: 3px;
        }

        ::-webkit-scrollbar-thumb:hover {
            background: rgba(255, 255, 255, 0.3);
        }

        /* 移动端触摸优化 */
        @media (hover: none) {
            .nav-item:active {
                background: rgba(255, 255, 255, 0.15);
            }

            .btn:active {
                transform: scale(0.96);
            }
        }

        /* 防止 iOS 缩放 */
        @media screen and (-webkit-min-device-pixel-ratio: 0) {
            select, textarea, input {
                font-size: 16px !important;
            }
        }
    </style>
</head>
<body>
    <!-- 登录界面 -->
    <div class="login-container" id="loginScreen">
        <div class="login-card">
            <div class="login-header">
                <h1><i class="fas fa-chart-line"></i> 销售管理系统</h1>
                <p>现代化的销售数据管理平台</p>
            </div>
            <form id="loginForm">
                <div class="form-group">
                    <label for="username">用户名</label>
                    <input type="text" id="username" class="form-control" placeholder="输入用户名" required autocomplete="username">
                </div>
                <div class="form-group">
                    <label for="password">密码</label>
                    <input type="password" id="password" class="form-control" placeholder="输入密码" required autocomplete="current-password">
                </div>
                <button type="submit" class="btn btn-primary">
                    <i class="fas fa-sign-in-alt"></i> 登录系统
                </button>
            </form>
            <div style="margin-top: 16px; text-align: center; font-size: 12px; color: var(--text-muted);">
                提示:用户名: admin, 密码: 123456
            </div>
        </div>
    </div>

    <!-- 主应用界面 -->
    <div class="app-container" id="appContainer">
        <!-- 顶部导航 -->
        <div class="topbar">
            <div class="logo">
                <button class="menu-toggle" id="menuToggle" aria-label="切换菜单">
                    <i class="fas fa-bars"></i>
                </button>
                <span>销售管理系统</span>
            </div>
            <div class="user-info">
                <span id="welcomeUser">欢迎, 管理员</span>
                <button class="logout-btn" id="logoutBtn">
                    <i class="fas fa-sign-out-alt"></i> 退出
                </button>
            </div>
        </div>

        <!-- 侧边栏导航 -->
        <div class="sidebar" id="sidebar">
            <div class="nav-item active" data-page="dashboard">
                <i class="fas fa-home"></i> 仪表盘
            </div>
            <div class="nav-item" data-page="products">
                <i class="fas fa-box"></i> 产品管理
            </div>
            <div class="nav-item" data-page="orders">
                <i class="fas fa-shopping-cart"></i> 订单管理
            </div>
            <div class="nav-item" data-page="customers">
                <i class="fas fa-users"></i> 客户管理
            </div>
        </div>

        <!-- 遮罩层 -->
        <div class="sidebar-overlay" id="sidebarOverlay"></div>

        <!-- 主内容区 -->
        <div class="main-content">
            <!-- 仪表盘页面 -->
            <div class="page active" id="dashboardPage">
                <div class="page-header">
                    <h2 class="page-title">仪表盘概览</h2>
                </div>

                <div class="dashboard-grid">
                    <div class="card">
                        <div class="card-header">
                            <div class="card-title">总销售额</div>
                            <i class="fas fa-dollar-sign" style="color: var(--success);"></i>
                        </div>
                        <div class="card-value" id="totalSales">¥0</div>
                        <div class="card-footer">
                            <i class="fas fa-arrow-up trend-up"></i> <span class="trend-up">12.5%</span> 较上月
                        </div>
                    </div>

                    <div class="card">
                        <div class="card-header">
                            <div class="card-title">订单数量</div>
                            <i class="fas fa-shopping-cart" style="color: var(--accent);"></i>
                        </div>
                        <div class="card-value" id="totalOrders">0</div>
                        <div class="card-footer">
                            <i class="fas fa-arrow-up trend-up"></i> <span class="trend-up">8.2%</span> 较上月
                        </div>
                    </div>

                    <div class="card">
                        <div class="card-header">
                            <div class="card-title">客户总数</div>
                            <i class="fas fa-users" style="color: var(--warning);"></i>
                        </div>
                        <div class="card-value" id="totalCustomers">0</div>
                        <div class="card-footer">
                            <i class="fas fa-arrow-up trend-up"></i> <span class="trend-up">5.7%</span> 较上月
                        </div>
                    </div>

                    <div class="card">
                        <div class="card-header">
                            <div class="card-title">产品库存</div>
                            <i class="fas fa-box-open" style="color: var(--danger);"></i>
                        </div>
                        <div class="card-value" id="totalProducts">0</div>
                        <div class="card-footer">
                            <i class="fas fa-arrow-down trend-down"></i> <span class="trend-down">3.1%</span> 较上月
                        </div>
                    </div>
                </div>

                <div class="chart-container">
                    <div class="chart-title">销售趋势 (最近7天)</div>
                    <canvas id="salesChart"></canvas>
                </div>
            </div>

            <!-- 产品管理页面 -->
            <div class="page" id="productsPage">
                <div class="page-header">
                    <h2 class="page-title">产品管理</h2>
                    <button class="btn btn-primary" id="addProductBtn"><i class="fas fa-plus"></i> 添加产品</button>
                </div>

                <div class="table-container">
                    <div class="table-header">
                        <h3>产品列表</h3>
                    </div>
                    <table id="productsTable">
                        <thead>
                            <tr>
                                <th>ID</th>
                                <th>产品名称</th>
                                <th>类别</th>
                                <th>价格</th>
                                <th>库存</th>
                                <th>操作</th>
                            </tr>
                        </thead>
                        <tbody id="productsTableBody">
                            <!-- 动态生成 -->
                        </tbody>
                    </table>
                    <div id="emptyProducts" class="empty-state" style="display: none;">
                        <i class="fas fa-box-open"></i>
                        <p>暂无产品数据,请添加</p>
                    </div>
                </div>
            </div>

            <!-- 订单管理页面 -->
            <div class="page" id="ordersPage">
                <div class="page-header">
                    <h2 class="page-title">订单管理</h2>
                    <button class="btn btn-primary" id="addOrderBtn"><i class="fas fa-plus"></i> 新增订单</button>
                </div>

                <div class="table-container">
                    <div class="table-header">
                        <h3>订单列表</h3>
                    </div>
                    <table id="ordersTable">
                        <thead>
                            <tr>
                                <th>订单ID</th>
                                <th>客户名称</th>
                                <th>产品</th>
                                <th>数量</th>
                                <th>金额</th>
                                <th>日期</th>
                                <th>状态</th>
                                <th>操作</th>
                            </tr>
                        </thead>
                        <tbody id="ordersTableBody">
                            <!-- 动态生成 -->
                        </tbody>
                    </table>
                    <div id="emptyOrders" class="empty-state" style="display: none;">
                        <i class="fas fa-shopping-cart"></i>
                        <p>暂无订单数据,请添加</p>
                    </div>
                </div>
            </div>

            <!-- 客户管理页面 -->
            <div class="page" id="customersPage">
                <div class="page-header">
                    <h2 class="page-title">客户管理</h2>
                    <button class="btn btn-primary" id="addCustomerBtn"><i class="fas fa-plus"></i> 添加客户</button>
                </div>

                <div class="table-container">
                    <div class="table-header">
                        <h3>客户列表</h3>
                    </div>
                    <table id="customersTable">
                        <thead>
                            <tr>
                                <th>ID</th>
                                <th>姓名</th>
                                <th>电话</th>
                                <th>邮箱</th>
                                <th>消费金额</th>
                                <th>操作</th>
                            </tr>
                        </thead>
                        <tbody id="customersTableBody">
                            <!-- 动态生成 -->
                        </tbody>
                    </table>
                    <div id="emptyCustomers" class="empty-state" style="display: none;">
                        <i class="fas fa-users"></i>
                        <p>暂无客户数据,请添加</p>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- 模态框 - 产品 -->
    <div class="modal" id="productModal">
        <div class="modal-content">
            <div class="modal-header">
                <h3 class="modal-title" id="productModalTitle">添加产品</h3>
                <button class="close-modal" data-modal="productModal">&times;</button>
            </div>
            <form id="productForm">
                <input type="hidden" id="productId">
                <div class="form-grid">
                    <div class="form-group">
                        <label for="productName">产品名称</label>
                        <input type="text" id="productName" class="form-control" required>
                    </div>
                    <div class="form-group">
                        <label for="productCategory">类别</label>
                        <input type="text" id="productCategory" class="form-control" required>
                    </div>
                    <div class="form-group">
                        <label for="productPrice">价格 (¥)</label>
                        <input type="number" id="productPrice" class="form-control" min="0" step="0.01" required>
                    </div>
                    <div class="form-group">
                        <label for="productStock">库存</label>
                        <input type="number" id="productStock" class="form-control" min="0" required>
                    </div>
                </div>
                <div class="form-row">
                    <button type="submit" class="btn btn-primary">保存产品</button>
                    <button type="button" class="btn btn-warning close-modal-btn" data-modal="productModal">取消</button>
                </div>
            </form>
        </div>
    </div>

    <!-- 模态框 - 订单 -->
    <div class="modal" id="orderModal">
        <div class="modal-content">
            <div class="modal-header">
                <h3 class="modal-title">新增订单</h3>
                <button class="close-modal" data-modal="orderModal">&times;</button>
            </div>
            <form id="orderForm">
                <div class="form-grid">
                    <div class="form-group">
                        <label for="orderCustomer">客户</label>
                        <select id="orderCustomer" class="form-control" required>
                            <option value="">选择客户</option>
                        </select>
                    </div>
                    <div class="form-group">
                        <label for="orderProduct">产品</label>
                        <select id="orderProduct" class="form-control" required>
                            <option value="">选择产品</option>
                        </select>
                    </div>
                    <div class="form-group">
                        <label for="orderQuantity">数量</label>
                        <input type="number" id="orderQuantity" class="form-control" min="1" required>
                    </div>
                    <div class="form-group">
                        <label for="orderDate">日期</label>
                        <input type="date" id="orderDate" class="form-control" required>
                    </div>
                </div>
                <div class="form-row">
                    <button type="submit" class="btn btn-primary">创建订单</button>
                    <button type="button" class="btn btn-warning close-modal-btn" data-modal="orderModal">取消</button>
                </div>
            </form>
        </div>
    </div>

    <!-- 模态框 - 客户 -->
    <div class="modal" id="customerModal">
        <div class="modal-content">
            <div class="modal-header">
                <h3 class="modal-title" id="customerModalTitle">添加客户</h3>
                <button class="close-modal" data-modal="customerModal">&times;</button>
            </div>
            <form id="customerForm">
                <input type="hidden" id="customerId">
                <div class="form-grid">
                    <div class="form-group">
                        <label for="customerName">姓名</label>
                        <input type="text" id="customerName" class="form-control" required>
                    </div>
                    <div class="form-group">
                        <label for="customerPhone">电话</label>
                        <input type="tel" id="customerPhone" class="form-control" required>
                    </div>
                    <div class="form-group">
                        <label for="customerEmail">邮箱</label>
                        <input type="email" id="customerEmail" class="form-control" required>
                    </div>
                    <div class="form-group">
                        <label for="customerSpent">消费金额 (¥)</label>
                        <input type="number" id="customerSpent" class="form-control" min="0" step="0.01" value="0">
                    </div>
                </div>
                <div class="form-row">
                    <button type="submit" class="btn btn-primary">保存客户</button>
                    <button type="button" class="btn btn-warning close-modal-btn" data-modal="customerModal">取消</button>
                </div>
            </form>
        </div>
    </div>

    <!-- 通知提示 -->
    <div class="notification" id="notification">
        <div id="notificationMessage"></div>
    </div>

    <script>
        // 全局状态
        const state = {
            currentUser: null,
            products: [],
            orders: [],
            customers: [],
            currentEditId: null
        };

        // 模拟数据初始化
        function initializeData() {
            const storedProducts = localStorage.getItem('sales_products');
            const storedOrders = localStorage.getItem('sales_orders');
            const storedCustomers = localStorage.getItem('sales_customers');

            if (!storedProducts) {
                state.products = [
                    { id: 1, name: '笔记本电脑', category: '电子产品', price: 5999, stock: 25 },
                    { id: 2, name: '智能手机', category: '电子产品', price: 2999, stock: 40 },
                    { id: 3, name: '办公椅', category: '家具', price: 899, stock: 15 },
                    { id: 4, name: '显示器', category: '电子产品', price: 1299, stock: 30 }
                ];
                localStorage.setItem('sales_products', JSON.stringify(state.products));
            } else {
                state.products = JSON.parse(storedProducts);
            }

            if (!storedOrders) {
                const today = new Date().toISOString().split('T')[0];
                state.orders = [
                    { id: 1, customerId: 1, productId: 1, quantity: 1, amount: 5999, date: today, status: 'completed' },
                    { id: 2, customerId: 2, productId: 2, quantity: 2, amount: 5998, date: today, status: 'pending' },
                    { id: 3, customerId: 3, productId: 3, quantity: 1, amount: 899, date: today, status: 'completed' }
                ];
                localStorage.setItem('sales_orders', JSON.stringify(state.orders));
            } else {
                state.orders = JSON.parse(storedOrders);
            }

            if (!storedCustomers) {
                state.customers = [
                    { id: 1, name: '张三', phone: '13800138000', email: 'zhangsan@example.com', spent: 5999 },
                    { id: 2, name: '李四', phone: '13900139000', email: 'lisi@example.com', spent: 5998 },
                    { id: 3, name: '王五', phone: '13700137000', email: 'wangwu@example.com', spent: 899 }
                ];
                localStorage.setItem('sales_customers', JSON.stringify(state.customers));
            } else {
                state.customers = JSON.parse(storedCustomers);
            }
        }

        // 登录功能
        document.getElementById('loginForm').addEventListener('submit', function(e) {
            e.preventDefault();
            const username = document.getElementById('username').value;
            const password = document.getElementById('password').value;

            if (username === 'admin' && password === '123456') {
                state.currentUser = username;
                document.getElementById('loginScreen').style.display = 'none';
                document.getElementById('appContainer').style.display = 'block';
                document.getElementById('welcomeUser').textContent = `欢迎, ${username}`;

                initializeData();
                updateDashboard();
                renderProducts();
                renderOrders();
                renderCustomers();

                showNotification('登录成功!', 'success');
            } else {
                showNotification('用户名或密码错误!', 'error');
            }
        });

        // 退出登录
        document.getElementById('logoutBtn').addEventListener('click', function() {
            state.currentUser = null;
            document.getElementById('appContainer').style.display = 'none';
            document.getElementById('loginScreen').style.display = 'flex';
            document.getElementById('loginForm').reset();
            showNotification('已安全退出', 'success');
        });

        // 页面导航
        document.querySelectorAll('.nav-item').forEach(item => {
            item.addEventListener('click', function() {
                // 更新导航状态
                document.querySelectorAll('.nav-item').forEach(nav => nav.classList.remove('active'));
                this.classList.add('active');

                // 显示对应页面
                const pageId = this.getAttribute('data-page') + 'Page';
                document.querySelectorAll('.page').forEach(page => page.classList.remove('active'));
                document.getElementById(pageId).classList.add('active');

                // 移动端:点击后关闭侧边栏
                if (window.innerWidth <= 992) {
                    closeSidebar();
                }
            });
        });

        // 移动端菜单切换 - 修复版本
        function openSidebar() {
            document.getElementById('sidebar').classList.add('open');
            document.getElementById('sidebarOverlay').classList.add('active');
            document.body.style.overflow = 'hidden'; // 防止背景滚动
        }

        function closeSidebar() {
            document.getElementById('sidebar').classList.remove('open');
            document.getElementById('sidebarOverlay').classList.remove('active');
            document.body.style.overflow = ''; // 恢复滚动
        }

        document.getElementById('menuToggle').addEventListener('click', function(e) {
            e.stopPropagation();
            const sidebar = document.getElementById('sidebar');
            if (sidebar.classList.contains('open')) {
                closeSidebar();
            } else {
                openSidebar();
            }
        });

        // 点击遮罩层关闭侧边栏
        document.getElementById('sidebarOverlay').addEventListener('click', function() {
            closeSidebar();
        });

        // 点击侧边栏外部关闭(移动端)
        document.addEventListener('click', function(e) {
            const sidebar = document.getElementById('sidebar');
            const menuToggle = document.getElementById('menuToggle');

            if (window.innerWidth <= 992 && sidebar.classList.contains('open')) {
                if (!sidebar.contains(e.target) && !menuToggle.contains(e.target)) {
                    closeSidebar();
                }
            }
        });

        // 模态框控制
        function openModal(modalId) {
            document.getElementById(modalId).classList.add('active');
            document.body.style.overflow = 'hidden'; // 防止背景滚动
        }

        function closeModal(modalId) {
            document.getElementById(modalId).classList.remove('active');
            document.body.style.overflow = ''; // 恢复滚动
        }

        // 关闭模态框事件
        document.querySelectorAll('.close-modal, .close-modal-btn').forEach(btn => {
            btn.addEventListener('click', function() {
                const modalId = this.getAttribute('data-modal');
                closeModal(modalId);
            });
        });

        // 点击模态框外部关闭
        document.querySelectorAll('.modal').forEach(modal => {
            modal.addEventListener('click', function(e) {
                if (e.target === this) {
                    this.classList.remove('active');
                    document.body.style.overflow = '';
                }
            });
        });

        // 产品管理
        document.getElementById('addProductBtn').addEventListener('click', function() {
            state.currentEditId = null;
            document.getElementById('productModalTitle').textContent = '添加产品';
            document.getElementById('productForm').reset();
            openModal('productModal');
        });

        document.getElementById('productForm').addEventListener('submit', function(e) {
            e.preventDefault();

            const product = {
                id: state.currentEditId || (state.products.length > 0 ? Math.max(...state.products.map(p => p.id)) + 1 : 1),
                name: document.getElementById('productName').value,
                category: document.getElementById('productCategory').value,
                price: parseFloat(document.getElementById('productPrice').value),
                stock: parseInt(document.getElementById('productStock').value)
            };

            if (state.currentEditId) {
                const index = state.products.findIndex(p => p.id === state.currentEditId);
                if (index !== -1) {
                    state.products[index] = product;
                    showNotification('产品更新成功', 'success');
                }
            } else {
                state.products.push(product);
                showNotification('产品添加成功', 'success');
            }

            localStorage.setItem('sales_products', JSON.stringify(state.products));
            renderProducts();
            updateDashboard();
            closeModal('productModal');
        });

        function renderProducts() {
            const tbody = document.getElementById('productsTableBody');
            const emptyState = document.getElementById('emptyProducts');

            tbody.innerHTML = '';

            if (state.products.length === 0) {
                emptyState.style.display = 'block';
                return;
            }

            emptyState.style.display = 'none';

            state.products.forEach(product => {
                const row = document.createElement('tr');
                row.innerHTML = `
                    <td>${product.id}</td>
                    <td>${product.name}</td>
                    <td>${product.category}</td>
                    <td>¥${product.price.toFixed(2)}</td>
                    <td>${product.stock}</td>
                    <td>
                        <button class="action-btn action-edit" onclick="editProduct(${product.id})">编辑</button>
                        <button class="action-btn action-delete" onclick="deleteProduct(${product.id})">删除</button>
                    </td>
                `;
                tbody.appendChild(row);
            });
        }

        function editProduct(id) {
            const product = state.products.find(p => p.id === id);
            if (product) {
                state.currentEditId = id;
                document.getElementById('productModalTitle').textContent = '编辑产品';
                document.getElementById('productId').value = product.id;
                document.getElementById('productName').value = product.name;
                document.getElementById('productCategory').value = product.category;
                document.getElementById('productPrice').value = product.price;
                document.getElementById('productStock').value = product.stock;
                openModal('productModal');
            }
        }

        function deleteProduct(id) {
            if (confirm('确定要删除这个产品吗?')) {
                state.products = state.products.filter(p => p.id !== id);
                localStorage.setItem('sales_products', JSON.stringify(state.products));
                renderProducts();
                updateDashboard();
                showNotification('产品已删除', 'success');
            }
        }

        // 订单管理
        document.getElementById('addOrderBtn').addEventListener('click', function() {
            const customerSelect = document.getElementById('orderCustomer');
            const productSelect = document.getElementById('orderProduct');

            customerSelect.innerHTML = '<option value="">选择客户</option>';
            productSelect.innerHTML = '<option value="">选择产品</option>';

            state.customers.forEach(customer => {
                const option = document.createElement('option');
                option.value = customer.id;
                option.textContent = customer.name;
                customerSelect.appendChild(option);
            });

            state.products.forEach(product => {
                const option = document.createElement('option');
                option.value = product.id;
                option.textContent = `${product.name} (库存: ${product.stock})`;
                productSelect.appendChild(option);
            });

            document.getElementById('orderDate').valueAsDate = new Date();
            openModal('orderModal');
        });

        document.getElementById('orderForm').addEventListener('submit', function(e) {
            e.preventDefault();

            const customerId = parseInt(document.getElementById('orderCustomer').value);
            const productId = parseInt(document.getElementById('orderProduct').value);
            const quantity = parseInt(document.getElementById('orderQuantity').value);
            const date = document.getElementById('orderDate').value;

            const product = state.products.find(p => p.id === productId);
            if (product.stock < quantity) {
                showNotification(`库存不足!可用库存: ${product.stock}`, 'error');
                return;
            }

            const amount = product.price * quantity;

            const order = {
                id: state.orders.length > 0 ? Math.max(...state.orders.map(o => o.id)) + 1 : 1,
                customerId,
                productId,
                quantity,
                amount,
                date,
                status: 'pending'
            };

            state.orders.push(order);

            product.stock -= quantity;
            const productIndex = state.products.findIndex(p => p.id === productId);
            state.products[productIndex] = product;

            const customer = state.customers.find(c => c.id === customerId);
            customer.spent += amount;
            const customerIndex = state.customers.findIndex(c => c.id === customerId);
            state.customers[customerIndex] = customer;

            localStorage.setItem('sales_orders', JSON.stringify(state.orders));
            localStorage.setItem('sales_products', JSON.stringify(state.products));
            localStorage.setItem('sales_customers', JSON.stringify(state.customers));

            renderOrders();
            renderProducts();
            renderCustomers();
            updateDashboard();

            closeModal('orderModal');
            showNotification('订单创建成功', 'success');
        });

        function renderOrders() {
            const tbody = document.getElementById('ordersTableBody');
            const emptyState = document.getElementById('emptyOrders');

            tbody.innerHTML = '';

            if (state.orders.length === 0) {
                emptyState.style.display = 'block';
                return;
            }

            emptyState.style.display = 'none';

            state.orders.forEach(order => {
                const customer = state.customers.find(c => c.id === order.customerId);
                const product = state.products.find(p => p.id === order.productId);

                const row = document.createElement('tr');
                row.innerHTML = `
                    <td>#${order.id}</td>
                    <td>${customer ? customer.name : '未知'}</td>
                    <td>${product ? product.name : '未知'}</td>
                    <td>${order.quantity}</td>
                    <td>¥${order.amount.toFixed(2)}</td>
                    <td>${order.date}</td>
                    <td><span class="status status-${order.status}">${order.status === 'completed' ? '已完成' : '处理中'}</span></td>
                    <td>
                        <button class="action-btn action-view" onclick="completeOrder(${order.id})">完成</button>
                        <button class="action-btn action-delete" onclick="deleteOrder(${order.id})">删除</button>
                    </td>
                `;
                tbody.appendChild(row);
            });
        }

        function completeOrder(id) {
            const orderIndex = state.orders.findIndex(o => o.id === id);
            if (orderIndex !== -1) {
                state.orders[orderIndex].status = 'completed';
                localStorage.setItem('sales_orders', JSON.stringify(state.orders));
                renderOrders();
                showNotification('订单已完成', 'success');
            }
        }

        function deleteOrder(id) {
            if (confirm('确定要删除这个订单吗?')) {
                state.orders = state.orders.filter(o => o.id !== id);
                localStorage.setItem('sales_orders', JSON.stringify(state.orders));
                renderOrders();
                updateDashboard();
                showNotification('订单已删除', 'success');
            }
        }

        // 客户管理
        document.getElementById('addCustomerBtn').addEventListener('click', function() {
            state.currentEditId = null;
            document.getElementById('customerModalTitle').textContent = '添加客户';
            document.getElementById('customerForm').reset();
            openModal('customerModal');
        });

        document.getElementById('customerForm').addEventListener('submit', function(e) {
            e.preventDefault();

            const customer = {
                id: state.currentEditId || (state.customers.length > 0 ? Math.max(...state.customers.map(c => c.id)) + 1 : 1),
                name: document.getElementById('customerName').value,
                phone: document.getElementById('customerPhone').value,
                email: document.getElementById('customerEmail').value,
                spent: parseFloat(document.getElementById('customerSpent').value)
            };

            if (state.currentEditId) {
                const index = state.customers.findIndex(c => c.id === state.currentEditId);
                if (index !== -1) {
                    state.customers[index] = customer;
                    showNotification('客户信息更新成功', 'success');
                }
            } else {
                state.customers.push(customer);
                showNotification('客户添加成功', 'success');
            }

            localStorage.setItem('sales_customers', JSON.stringify(state.customers));
            renderCustomers();
            updateDashboard();
            closeModal('customerModal');
        });

        function renderCustomers() {
            const tbody = document.getElementById('customersTableBody');
            const emptyState = document.getElementById('emptyCustomers');

            tbody.innerHTML = '';

            if (state.customers.length === 0) {
                emptyState.style.display = 'block';
                return;
            }

            emptyState.style.display = 'none';

            state.customers.forEach(customer => {
                const row = document.createElement('tr');
                row.innerHTML = `
                    <td>${customer.id}</td>
                    <td>${customer.name}</td>
                    <td>${customer.phone}</td>
                    <td>${customer.email}</td>
                    <td>¥${customer.spent.toFixed(2)}</td>
                    <td>
                        <button class="action-btn action-edit" onclick="editCustomer(${customer.id})">编辑</button>
                        <button class="action-btn action-delete" onclick="deleteCustomer(${customer.id})">删除</button>
                    </td>
                `;
                tbody.appendChild(row);
            });
        }

        function editCustomer(id) {
            const customer = state.customers.find(c => c.id === id);
            if (customer) {
                state.currentEditId = id;
                document.getElementById('customerModalTitle').textContent = '编辑客户';
                document.getElementById('customerId').value = customer.id;
                document.getElementById('customerName').value = customer.name;
                document.getElementById('customerPhone').value = customer.phone;
                document.getElementById('customerEmail').value = customer.email;
                document.getElementById('customerSpent').value = customer.spent;
                openModal('customerModal');
            }
        }

        function deleteCustomer(id) {
            if (confirm('确定要删除这个客户吗?')) {
                state.customers = state.customers.filter(c => c.id !== id);
                localStorage.setItem('sales_customers', JSON.stringify(state.customers));
                renderCustomers();
                updateDashboard();
                showNotification('客户已删除', 'success');
            }
        }

        // 仪表盘更新
        function updateDashboard() {
            const totalSales = state.orders.reduce((sum, order) => sum + order.amount, 0);
            document.getElementById('totalSales').textContent = ${totalSales.toFixed(2)}`;
            document.getElementById('totalOrders').textContent = state.orders.length;
            document.getElementById('totalCustomers').textContent = state.customers.length;
            document.getElementById('totalProducts').textContent = state.products.reduce((sum, p) => sum + p.stock, 0);

            updateSalesChart();
        }

        // 图表初始化
        let salesChart = null;

        function updateSalesChart() {
            const ctx = document.getElementById('salesChart').getContext('2d');

            const labels = [];
            const data = [];
            const today = new Date();

            for (let i = 6; i >= 0; i--) {
                const date = new Date(today);
                date.setDate(date.getDate() - i);
                const dateStr = date.toLocaleDateString('zh-CN', { month: 'short', day: 'numeric' });
                labels.push(dateStr);

                const dailySales = Math.floor(Math.random() * 10000) + 2000;
                data.push(dailySales);
            }

            if (salesChart) {
                salesChart.destroy();
            }

            salesChart = new Chart(ctx, {
                type: 'line',
                data: {
                    labels: labels,
                    datasets: [{
                        label: '销售额 (¥)',
                        data: data,
                        borderColor: '#4895ef',
                        backgroundColor: 'rgba(72, 149, 239, 0.1)',
                        borderWidth: 3,
                        pointBackgroundColor: '#4895ef',
                        pointRadius: 4,
                        pointHoverRadius: 6,
                        fill: true,
                        tension: 0.4
                    }]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    plugins: {
                        legend: {
                            display: false
                        },
                        tooltip: {
                            backgroundColor: 'rgba(0, 0, 0, 0.7)',
                            titleColor: '#fff',
                            bodyColor: '#fff',
                            borderColor: '#4895ef',
                            borderWidth: 1,
                            padding: 12,
                            displayColors: false,
                            callbacks: {
                                label: function(context) {
                                    return '¥' + context.parsed.y.toLocaleString();
                                }
                            }
                        }
                    },
                    scales: {
                        y: {
                            beginAtZero: true,
                            grid: {
                                color: 'rgba(255, 255, 255, 0.1)'
                            },
                            ticks: {
                                color: 'rgba(255, 255, 255, 0.6)',
                                callback: function(value) {
                                    return '¥' + value.toLocaleString();
                                }
                            }
                        },
                        x: {
                            grid: {
                                display: false
                            },
                            ticks: {
                                color: 'rgba(255, 255, 255, 0.6)'
                            }
                        }
                    }
                }
            });
        }

        // 通知系统
        function showNotification(message, type = 'success') {
            const notification = document.getElementById('notification');
            const messageEl = document.getElementById('notificationMessage');

            messageEl.textContent = message;
            notification.className = 'notification show';

            if (type === 'error') {
                notification.classList.add('error');
            } else if (type === 'warning') {
                notification.classList.add('warning');
            }

            setTimeout(() => {
                notification.classList.remove('show');
            }, 3000);
        }

        // 页面加载完成后执行
        document.addEventListener('DOMContentLoaded', function() {
            const today = new Date().toISOString().split('T')[0];
            if (document.getElementById('orderDate')) {
                document.getElementById('orderDate').value = today;
            }

            // 防止iOS双击缩放
            document.addEventListener('touchstart', function() {}, {passive: true});
        });

        // 暴露全局函数供HTML事件调用
        window.editProduct = editProduct;
        window.deleteProduct = deleteProduct;
        window.deleteOrder = deleteOrder;
        window.completeOrder = completeOrder;
        window.editCustomer = editCustomer;
        window.deleteCustomer = deleteCustomer;
    </script>
</body>
</html>

系统功能说明

这个销售管理系统包含以下核心功能:

    登录系统

    • 用户名: admin
    • 密码: 123456
    • 简单认证(实际应用中应使用后端验证)

    仪表盘

    • 显示关键指标:总销售额、订单数量、客户总数、产品库存
    • 销售趋势图表(使用Chart.js)
    • 数据可视化展示

    产品管理

    • 添加新产品
    • 编辑现有产品
    • 删除产品
    • 产品列表展示(名称、类别、价格、库存)

    订单管理

    • 创建新订单(选择客户和产品)
    • 完成订单(更新状态)
    • 删除订单
    • 订单列表(包含客户、产品、数量、金额、日期、状态)

    客户管理

    • 添加新客户
    • 编辑客户信息
    • 删除客户
    • 客户列表(包含姓名、电话、邮箱、消费金额)

    数据持久化

    • 使用浏览器localStorage存储所有数据
    • 刷新页面数据不会丢失

    响应式设计

    • 适配桌面和移动设备
    • 移动端侧边栏菜单

设计亮点

    现代化UI

    • 深色主题,减少视觉疲劳
    • 玻璃态设计(glassmorphism)
    • 平滑过渡动画
    • 卡片式布局

    用户体验

    • 直观的导航
    • 即时反馈(通知系统)
    • 表单验证
    • 操作确认(删除操作)

    数据可视化

    • 关键指标卡片
    • 销售趋势图表
    • 状态标签(已完成、处理中)

    代码结构

    • 模块化JavaScript
    • 状态管理
    • 清晰的HTML结构
    • 响应式CSS

这个系统可以直接在浏览器中运行,无需任何后端支持。所有数据都存储在浏览器的localStorage中,刷新页面后数据仍然保留