<!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">×</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">×</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">×</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>