<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>电商小程序管理后台</title> <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@300;400;500;600;700&display=swap" rel="stylesheet"> <script src="https://cdn.tailwindcss.com"></script> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script> <style> * { font-family: 'Noto Sans SC', sans-serif; } .gradient-bg { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); } .card-hover { transition: all 0.3s ease; } .card-hover:hover { transform: translateY(-4px); box-shadow: 0 20px 40px rgba(0, 0, 0, 0.12); } .sidebar-item { transition: all 0.2s ease; cursor: pointer; } .sidebar-item:hover { background: rgba(255, 255, 255, 0.1); } .sidebar-item.active { background: rgba(255, 255, 255, 0.15); border-left: 3px solid #fff; } @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .fade-in { animation: fadeIn 0.4s ease forwards; } .metric-number { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } .btn-primary { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); } .btn-primary:hover { opacity: 0.9; } .page { display: block; } .page.hidden { display: none; } .login-page { min-height: 100vh; } .login-card { width: 100%; max-width: 420px; } .input-focus-ring:focus { outline: none; ring: 2px; ring-color: #667eea; } </style> </head> <body class="bg-gray-50"> <!-- 登录页面 --> <div id="loginPage" class="login-page gradient-bg flex items-center justify-center p-4"> <div class="login-card bg-white rounded-2xl shadow-2xl p-8 fade-in"> <div class="text-center mb-8"> <div class="w-20 h-20 gradient-bg rounded-full mx-auto flex items-center justify-center mb-4"> <svg class="w-10 h-10 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z"></path> </svg> </div> <h1 class="text-2xl font-bold text-gray-800">电商管理后台</h1> <p class="text-gray-500 mt-2">请登录您的账户</p> </div> <form id="loginForm" class="space-y-6"> <div> <label class="block text-sm font-medium text-gray-700 mb-2">用户名</label> <input id="login-username" type="text" required class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent" placeholder="请输入用户名"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-2">密码</label> <input id="login-password" type="password" required class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent" placeholder="请输入密码"> </div> <button type="submit" class="w-full btn-primary text-white py-3 rounded-lg font-medium hover:opacity-90 transition-opacity"> 登录 </button> </form> <p class="text-center text-gray-400 text-sm mt-6">默认管理员账号: admin / admin123</p> </div> </div> <!-- 主应用界面 --> <div id="mainApp" class="flex min-h-screen hidden"> <!-- 侧边栏 --> <aside class="w-64 gradient-bg text-white flex-shrink-0"> <div class="p-6"> <h1 class="text-2xl font-bold flex items-center gap-2"> <svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z"></path> </svg> 电商管理后台 </h1> </div> <nav class="mt-4"> <div class="sidebar-item active w-full text-left px-6 py-3 flex items-center gap-3" data-page="dashboard"> <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2 2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h2a2 2 0 01-2 2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2 2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h2a2 2 0 01-2 2v-2z"></path> </svg> 首页仪表盘 </div> <div class="sidebar-item w-full text-left px-6 py-3 flex items-center gap-3" data-page="product"> <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4"></path> </svg> 商品管理 </div> <div class="sidebar-item w-full text-left px-6 py-3 flex items-center gap-3" data-page="order"> <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01"></path> </svg> 订单管理 </div> <div class="sidebar-item w-full text-left px-6 py-3 flex items-center gap-3" data-page="user"> <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z"></path> </svg> 用户管理 </div> <div class="sidebar-item w-full text-left px-6 py-3 flex items-center gap-3" data-page="category"> <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2 2V6zM10 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H12a2 2 0 01-2 2V6zM16 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H18a2 2 0 01-2 2v-2zM10 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h2a2 2 0 01-2 2v-2z"></path> </svg> 分类管理 </div> <div class="sidebar-item w-full text-left px-6 py-3 flex items-center gap-3" data-page="stats"> <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2 2z"></path> </svg> 数据统计 </div> <div class="sidebar-item w-full text-left px-6 py-3 flex items-center gap-3" data-page="settings"> <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426-1.756-2.924-1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.9240-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37a1.724 1.724 0 002.572-1.065z"></path> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path> </svg> 系统设置 </div> <div class="sidebar-item w-full text-left px-6 py-3 flex items-center gap-3" data-page="admin"> <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z"></path> </svg> 管理员管理 </div> </nav> </aside> <!-- 主内容区 --> <main class="flex-1 overflow-auto"> <header class="bg-white shadow-sm px-8 py-4 flex justify-between items-center"> <div> <h2 id="pageTitle" class="text-2xl font-semibold text-gray-800">首页仪表盘</h2> <p class="text-gray-500 text-sm mt-1">欢迎回到电商管理后台</p> </div> <div class="flex items-center gap-4"> <div class="w-10 h-10 rounded-full gradient-bg flex items-center justify-center text-white font-semibold"> 管 </div> <div> <p id="currentAdminName" class="font-medium text-gray-800">管理员</p> <p class="text-sm text-gray-500">欢迎回来</p> </div> <button id="logoutBtn" class="ml-4 px-4 py-2 border border-gray-300 rounded-lg text-gray-600 hover:bg-gray-50 transition-colors"> 退出登录 </button> </div> </header> <div class="p-8"> <!-- 首页仪表盘 --> <div id="dashboardPage" class="page fade-in"> <div id="dashboard-container"></div> </div> <!-- 商品管理 --> <div id="productPage" class="page hidden"> <div class="bg-white rounded-xl shadow-sm"> <div class="p-6 border-b flex flex-wrap justify-between items-center gap-4"> <h3 class="text-xl font-semibold text-gray-800">商品管理</h3> <button id="add-product-btn" class="btn-primary text-white px-4 py-2 rounded-lg">添加商品</button> </div> <div class="p-6"> <div id="product-list" class="space-y-4"></div> </div> </div> </div> <!-- 订单管理 --> <div id="orderPage" class="page hidden"> <div class="bg-white rounded-xl shadow-sm"> <div class="p-6 border-b"> <h3 class="text-xl font-semibold text-gray-800 mb-4">订单管理</h3> <div class="flex flex-wrap gap-2"> <button class="order-filter-btn px-4 py-2 rounded-lg bg-purple-600 text-white" data-status="">全部</button> <button class="order-filter-btn px-4 py-2 rounded-lg bg-gray-100 text-gray-700 hover:bg-gray-200" data-status="pending">待付款</button> <button class="order-filter-btn px-4 py-2 rounded-lg bg-gray-100 text-gray-700 hover:bg-gray-200" data-status="paid">已付款</button> <button class="order-filter-btn px-4 py-2 rounded-lg bg-gray-100 text-gray-700 hover:bg-gray-200" data-status="shipped">已发货</button> <button class="order-filter-btn px-4 py-2 rounded-lg bg-gray-100 text-gray-700 hover:bg-gray-200" data-status="completed">已完成</button> </div> </div> <div class="p-6"> <div id="order-list" class="space-y-4"></div> </div> </div> </div> <!-- 用户管理 --> <div id="userPage" class="page hidden"> <div class="bg-white rounded-xl shadow-sm"> <div class="p-6 border-b"> <h3 class="text-xl font-semibold text-gray-800">用户管理</h3> </div> <div class="p-6"> <div id="user-list"></div> </div> </div> </div> <!-- 分类管理 --> <div id="categoryPage" class="page hidden"> <div class="bg-white rounded-xl shadow-sm"> <div class="p-6 border-b flex flex-wrap justify-between items-center gap-4"> <h3 class="text-xl font-semibold text-gray-800">分类管理</h3> <button id="add-category-btn" class="btn-primary text-white px-4 py-2 rounded-lg">添加分类</button> </div> <div class="p-6"> <div id="category-list"></div> </div> </div> </div> <!-- 数据统计 --> <div id="statsPage" class="page hidden"> <div id="stats-container"></div> </div> <!-- 系统设置 --> <div id="settingsPage" class="page hidden"> <div class="max-w-2xl space-y-6"> <div class="bg-white rounded-xl shadow-sm p-6"> <h3 class="text-xl font-semibold text-gray-800 mb-4">基本设置</h3> <div class="space-y-4"> <div> <label class="block text-sm font-medium text-gray-700 mb-1">店铺名称</label> <input id="shop-name" type="text" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-1">联系电话</label> <input id="shop-phone" type="text" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-1">联系邮箱</label> <input id="shop-email" type="email" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-1">店铺地址</label> <input id="shop-address" type="text" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500"> </div> </div> </div> <button id="save-settings-btn" class="btn-primary text-white px-6 py-3 rounded-lg">保存设置</button> </div> </div> <!-- 管理员管理 --> <div id="adminPage" class="page hidden"> <div class="bg-white rounded-xl shadow-sm"> <div class="p-6 border-b flex flex-wrap justify-between items-center gap-4"> <h3 class="text-xl font-semibold text-gray-800">管理员管理</h3> <button id="add-admin-btn" class="btn-primary text-white px-4 py-2 rounded-lg">添加管理员</button> </div> <div class="p-6"> <div id="admin-list" class="space-y-4"></div> </div> </div> </div> </div> </main> </div> <!-- 商品编辑弹窗 --> <div id="product-modal" class="fixed inset-0 bg-black/50 hidden items-center justify-center z-50"> <div class="bg-white rounded-xl p-6 w-full max-w-lg mx-4 max-h-[90vh] overflow-y-auto"> <div class="flex justify-between items-center mb-4"> <h3 id="product-modal-title" class="text-xl font-semibold">添加商品</h3> <button onclick="ProductPage.closeModal()" class="text-gray-400 hover:text-gray-600 text-2xl">&times;</button> </div> <div class="space-y-4"> <div> <label class="block text-sm font-medium text-gray-700 mb-1">商品名称 *</label> <input id="product-name" type="text" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-1">商品描述</label> <textarea id="product-description" rows="3" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500"></textarea> </div> <div class="grid grid-cols-2 gap-4"> <div> <label class="block text-sm font-medium text-gray-700 mb-1">售价 *</label> <input id="product-price" type="number" step="0.01" min="0" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-1">原价</label> <input id="product-original-price" type="number" step="0.01" min="0" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500"> </div> </div> <div class="grid grid-cols-2 gap-4"> <div> <label class="block text-sm font-medium text-gray-700 mb-1">库存</label> <input id="product-stock" type="number" min="0" value="0" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-1">分类</label> <select id="product-category" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500"> <option value="">请选择分类</option> </select> </div> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-1">商品图片URL</label> <input id="product-images" type="text" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500" placeholder="https://..."> </div> </div> <div class="flex gap-3 mt-6"> <button onclick="ProductPage.closeModal()" class="border border-gray-300 text-gray-700 px-4 py-2 rounded-lg flex-1 hover:bg-gray-50">取消</button> <button onclick="ProductPage.saveProduct()" class="btn-primary text-white px-4 py-2 rounded-lg flex-1">保存</button> </div> </div> </div> <!-- 分类编辑弹窗 --> <div id="category-modal" class="fixed inset-0 bg-black/50 hidden items-center justify-center z-50"> <div class="bg-white rounded-xl p-6 w-full max-w-md mx-4"> <div class="flex justify-between items-center mb-4"> <h3 id="category-modal-title" class="text-xl font-semibold">添加分类</h3> <button onclick="CategoryPage.closeModal()" class="text-gray-400 hover:text-gray-600 text-2xl">&times;</button> </div> <div class="space-y-4"> <div> <label class="block text-sm font-medium text-gray-700 mb-1">分类名称 *</label> <input id="category-name" type="text" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-1">排序</label> <input id="category-sort" type="number" min="0" value="0" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500"> </div> </div> <div class="flex gap-3 mt-6"> <button onclick="CategoryPage.closeModal()" class="border border-gray-300 text-gray-700 px-4 py-2 rounded-lg flex-1 hover:bg-gray-50">取消</button> <button onclick="CategoryPage.saveCategory()" class="btn-primary text-white px-4 py-2 rounded-lg flex-1">保存</button> </div> </div> </div> <!-- 管理员编辑弹窗 --> <div id="admin-modal" class="fixed inset-0 bg-black/50 hidden items-center justify-center z-50"> <div class="bg-white rounded-xl p-6 w-full max-w-lg mx-4"> <div class="flex justify-between items-center mb-4"> <h3 id="admin-modal-title" class="text-xl font-semibold">添加管理员</h3> <button onclick="AdminPage.closeModal()" class="text-gray-400 hover:text-gray-600 text-2xl">&times;</button> </div> <form id="admin-form" class="space-y-4"> <div> <label class="block text-sm font-medium text-gray-700 mb-1">用户名 *</label> <input id="admin-username" type="text" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-1">密码 *</label> <input id="admin-password" type="password" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500" placeholder="至少6位"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-1">确认密码 *</label> <input id="admin-password-confirm" type="password" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500" placeholder="再次输入密码"> </div> <div> <label class="block text-sm font-medium text-gray-700 mb-1">显示名称</label> <input id="admin-display-name" type="text" class="w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500"> </div> </div> <div class="flex gap-3 mt-6"> <button onclick="AdminPage.closeModal()" class="border border-gray-300 text-gray-700 px-4 py-2 rounded-lg flex-1 hover:bg-gray-50">取消</button> <button onclick="AdminPage.saveAdmin()" class="btn-primary text-white px-4 py-2 rounded-lg flex-1">保存</button> </div> </div> </div> <!-- 工具脚本 --> <script src="utils/storage.js"></script> <script src="utils/format.js"></script> <script src="utils/validate.js"></script> <script src="utils/crypto.js"></script> <!-- 组件脚本 --> <script src="components/toast.js"></script> <script src="components/modal.js"></script> <!-- API脚本 --> <script src="api/config.js"></script> <script src="api/product.js"></script> <script src="api/order.js"></script> <script src="api/user.js"></script> <script src="api/category.js"></script> <script src="api/stats.js"></script> <script src="api/admin.js"></script> <!-- 页面脚本 --> <script src="pages/dashboard/index.js"></script> <script src="pages/product/index.js"></script> <script src="pages/order/index.js"></script> <script src="pages/user/index.js"></script> <script src="pages/category/index.js"></script> <script src="pages/stats/index.js"></script> <script src="pages/settings/index.js"></script> <script src="pages/admin/index.js"></script> <!-- 主应用脚本 --> <script src="app.js"></script> </body> </html>