带后台管理的响应式多功能单页网站代码带下载模版带跳转出微信支付宝QQ三合一支付下单发货页面


为了实现一个 带后台管理、响应式多功能单页网站,并提供 三合一支付下单发货功能,同时 无需购买任何第三方服务器,我们可以采用 前端静态托管 + 后端无服务器云函数 + 免费数据库 的方案,所有服务均在免费额度内运行。
一、整体技术架构
|
|
|
|
|---|---|---|
| 前端(SPA) |
|
|
| 后端 API |
|
|
| 数据库 |
|
|
| 支付聚合 |
|
|
| 后台管理 |
|
|
| 身份验证 |
|
|
✅ 支付流程:前端发起订单 → 云函数生成支付参数 → 用户跳转支付 → 支付平台异步回调通知云函数 → 云函数更新订单状态并触发“发货”逻辑(如发送邮件或更新库存)。
二、项目文件结构
my-website/├── frontend/# 前端单页应用(用户端 + 管理端)│ ├── public/│ │ └── index.html# 主页面(SPA)│ ├── src/│ │ ├── css/│ │ │ └── style.css# 自定义样式 + Tailwind│ │ ├── js/│ │ │ ├── app.js# 前端路由、功能│ │ │ ├── api.js# 封装 fetch 调用后端 API│ │ │ └── admin.js# 后台管理逻辑│ │ └── pages/# 页面模块(按需加载)│ │ ├── home.html│ │ ├── products.html│ │ ├── checkout.html│ │ └── admin.html│ └── vercel.json# Vercel 部署配置├── backend/# 云函数(Serverless)│ └── api/# Vercel Functions 默认目录│ ├── order.js# 创建订单、支付回调│ ├── product.js# 商品增删改查│ ├── auth.js# 登录验证│ └── utils/# 工具函数(数据库连接、支付配置)├── database/# 数据库模型(示例)│ └── models.js├── .env# 环境变量(本地)└── README.md
三、核心代码实现
1. 前端主页面 (frontend/public/index.html)
这是一个单页应用,通过 JS 动态切换内容区域,内置导航、商品展示、购物车、支付流程和后台管理面板。
<!DOCTYPE html><htmllang=”zh-CN”><head><metacharset=”UTF-8” /><metaname=”viewport”content=”width=device-width,initial-scale=1.0” /><title>个人多功能网站</title><!-- Tailwind CSS (CDN) --><scriptsrc=”https://cdn.tailwindcss.com”></script><!-- Font Awesome --><linkrel=”stylesheet”href=”https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css” /><style>/* 自定义样式,比如加载动画、过渡效果 */.page { display: none; }.page.active { display: block; }</style></head><body><!-- 顶部导航 --><navclass=”bg-whiteshadow-mdp-4stickytop-0z-50”><divclass=”containermx-autoflexjustify-betweenitems-center”><spanclass=”text-xlfont-bold”>我的商店</span><div><buttondata-page=”home”class=”nav-btnmx-2hover:text-blue-600”>首页</button><buttondata-page=”products”class=”nav-btnmx-2hover:text-blue-600”>商品</button><buttondata-page=”cart”class=”nav-btnmx-2hover:text-blue-600”>购物车 <spanid=”cart-count”class=”bg-red-500text-whiterounded-fullpx-2py-0.5text-xs”>0</span></button><buttondata-page=”admin”class=”nav-btnmx-2hover:text-blue-600”>管理</button></div></div></nav><!-- 页面容器 --><mainclass=”containermx-autop-4”><divid=”home”class=”pageactive”><!-- 首页内容由 JS 动态渲染 --><h1class=”text-3xlfont-bold”>欢迎来到我的个人站</h1><pclass=”mt-2”>这里展示最新动态、推荐商品等。</p><divid=”featured-products”class=”gridgrid-cols-1md:grid-cols-3gap-4mt-6”></div></div><divid=”products”class=”page”><h2class=”text-2xlfont-boldmb-4”>所有商品</h2><divid=”product-list”class=”gridgrid-cols-1md:grid-cols-3gap-4”></div></div><divid=”cart”class=”page”><h2class=”text-2xlfont-boldmb-4”>购物车</h2><divid=”cart-items”></div><divclass=”mt-4text-right”><spanclass=”text-xl”>总计:¥<spanid=”total-price”>0.00</span></span><buttonid=”checkout-btn”class=”ml-4bg-green-500text-whitepx-6py-2roundedhover:bg-green-600”>去支付</button></div></div><divid=”admin”class=”page”><h2class=”text-2xlfont-boldmb-4”>后台管理</h2><!-- 登录面板 --><divid=”admin-login”><inputtype=”password”id=”admin-pwd”placeholder=”管理密码”class=”borderp-2rounded” /><buttonid=”admin-login-btn”class=”bg-blue-500text-whitepx-4py-2rounded”>登录</button></div><!-- 管理面板(登录后显示) --><divid=”admin-panel”style=”display:none;”><divclass=”flexspace-x-4mb-4”><buttonclass=”tab-btn”data-tab=”add-product”>添加商品</button><buttonclass=”tab-btn”data-tab=”manage-products”>管理商品</button><buttonclass=”tab-btn”data-tab=”orders”>订单管理</button></div><divid=”tab-content”><!-- 由 JS 动态加载 --></div></div></div></main><!-- 支付弹窗 (用于跳转或扫码) --><divid=”payment-modal”class=”fixedinset-0bg-blackbg-opacity-50flexitems-centerjustify-centerhidden”><divclass=”bg-whitep-8rounded-lgmax-w-mdw-full”><h3class=”text-xlfont-boldmb-4”>选择支付方式</h3><divclass=”flexjustify-around”><buttonclass=”pay-method”data-method=”wechat”><iclass=”fabfa-weixintext-green-600text-4xl”></i><br>微信</button><buttonclass=”pay-method”data-method=”alipay”><iclass=”fabfa-alipaytext-blue-600text-4xl”></i><br>支付宝</button><buttonclass=”pay-method”data-method=”qqpay”><iclass=”fabfa-qqtext-red-600text-4xl”></i><br>QQ钱包</button></div><buttonid=”close-payment”class=”mt-4bg-gray-300px-4py-2roundedw-full”>取消</button></div></div><scripttype=”module”src=”/src/js/app.js”></script></body></html>
2. 前端核心逻辑 (frontend/src/js/app.js)
负责页面切换、商品加载、购物车管理、支付跳转、管理员登录等。
import { fetchProducts, createOrder, adminLogin, fetchOrders, updateOrderStatus } from './api.js';// ---------- 页面切换 ----------document.querySelectorAll('.nav-btn').forEach(btn => {btn.addEventListener('click', () => {const page = btn.dataset.page;document.querySelectorAll('.page').forEach(p => p.classList.remove('active'));document.getElementById(page).classList.add('active');if (page === 'admin') checkAdminStatus();});});// ---------- 加载商品 ----------async function loadProducts() {const products = await fetchProducts();const container = document.getElementById('product-list');container.innerHTML = products.map(p => `<div class=”border p-4 rounded shadow”><img src=”${p.image}” alt=”${p.name}” class=”w-full h-48 object-cover” /><h3 class=”text-lg font-semibold mt-2”>${p.name}</h3><p class=”text-gray-600”>¥${p.price}</p><button class=”add-cart mt-2 bg-blue-500 text-white px-4 py-1 rounded” data-id=”${p.id}”>加入购物车</button></div>`).join('');// 绑定加入购物车事件container.querySelectorAll('.add-cart').forEach(btn => {btn.addEventListener('click', () => addToCart(btn.dataset.id));});}loadProducts();// ---------- 购物车 ----------let cart = [];function addToCart(productId) {// 实际从商品列表获取完整信息,此处简化const product = products.find(p => p.id == productId);if (!product) return;const exist = cart.find(item => item.id == productId);if (exist) exist.quantity++;else cart.push({ ...product, quantity: 1 });updateCartUI();}function updateCartUI() {document.getElementById('cart-count').textContent = cart.reduce((sum, i) => sum + i.quantity, 0);const container = document.getElementById('cart-items');if (cart.length === 0) {container.innerHTML = '<p>购物车为空</p>';document.getElementById('total-price').textContent = '0.00';return;}container.innerHTML = cart.map(item => `<div class=”flex justify-between border-b py-2”><span>${item.name} × ${item.quantity}</span><span>¥${(item.price * item.quantity).toFixed(2)}</span><button class=”remove-cart text-red-500” data-id=”${item.id}”>删除</button></div>`).join('');const total = cart.reduce((sum, i) => sum + i.price * i.quantity, 0);document.getElementById('total-price').textContent = total.toFixed(2);// 删除事件container.querySelectorAll('.remove-cart').forEach(btn => {btn.addEventListener('click', () => {cart = cart.filter(item => item.id != btn.dataset.id);updateCartUI();});});}// ---------- 支付流程 ----------document.getElementById('checkout-btn').addEventListener('click', async () => {if (cart.length === 0) return alert('购物车为空');// 弹出支付方式选择document.getElementById('payment-modal').classList.remove('hidden');});document.querySelectorAll('.pay-method').forEach(btn => {btn.addEventListener('click', async () => {const method = btn.dataset.method;document.getElementById('payment-modal').classList.add('hidden');// 调用后端创建订单const orderData = {items: cart,total: cart.reduce((s, i) => s + i.price * i.quantity, 0),paymentMethod: method};try {const result = await createOrder(orderData);// result 包含支付链接或二维码if (result.payUrl) {// 跳转到支付平台(或打开新窗口)window.open(result.payUrl, '_blank');// 然后轮询订单状态,或等待支付回调通知pollOrderStatus(result.orderId);} else {alert('支付发起失败');}} catch (err) {alert('下单失败:' + err.message);}});});document.getElementById('close-payment').addEventListener('click', () => {document.getElementById('payment-modal').classList.add('hidden');});// 轮询订单状态(简化)async function pollOrderStatus(orderId) {const interval = setInterval(async () => {const orders = await fetchOrders();const order = orders.find(o => o.id === orderId);if (order && order.status === 'paid') {clearInterval(interval);alert('支付成功!已发货');cart = [];updateCartUI();// 可跳转到订单详情}}, 3000);}// ---------- 后台管理 ----------async function checkAdminStatus() {const token = localStorage.getItem('admin_token');if (token) {document.getElementById('admin-login').style.display = 'none';document.getElementById('admin-panel').style.display = 'block';loadAdminPanel('add-product');} else {document.getElementById('admin-login').style.display = 'block';document.getElementById('admin-panel').style.display = 'none';}}document.getElementById('admin-login-btn').addEventListener('click', async () => {const pwd = document.getElementById('admin-pwd').value;try {const token = await adminLogin(pwd);localStorage.setItem('admin_token', token);checkAdminStatus();} catch {alert('密码错误');}});// 管理标签切换document.querySelectorAll('.tab-btn').forEach(btn => {btn.addEventListener('click', () => {loadAdminPanel(btn.dataset.tab);});});async function loadAdminPanel(tab) {const container = document.getElementById('tab-content');if (tab === 'add-product') {container.innerHTML = `<h3 class=”font-bold”>添加商品</h3><input id=”prod-name” placeholder=”名称” class=”border p-2 w-full mt-2” /><input id=”prod-price” placeholder=”价格” type=”number” class=”border p-2 w-full mt-2” /><input id=”prod-image” placeholder=”图片URL” class=”border p-2 w-full mt-2” /><button id=”save-product” class=”mt-2 bg-blue-500 text-white px-4 py-2 rounded”>保存</button>`;document.getElementById('save-product').addEventListener('click', async () => {const name = document.getElementById('prod-name').value;const price = parseFloat(document.getElementById('prod-price').value);const image = document.getElementById('prod-image').value;await fetch('/api/product', {method: 'POST',headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + localStorage.getItem('admin_token') },body: JSON.stringify({ name, price, image })});alert('商品添加成功');loadProducts();});} else if (tab === 'manage-products') {const products = await fetchProducts();container.innerHTML = products.map(p => `<div class=”flex justify-between border-b py-2”><span>${p.name} - ¥${p.price}</span><button class=”delete-prod text-red-500” data-id=”${p.id}”>删除</button></div>`).join('');container.querySelectorAll('.delete-prod').forEach(btn => {btn.addEventListener('click', async () => {await fetch('/api/product/' + btn.dataset.id, {method: 'DELETE',headers: { 'Authorization': 'Bearer ' + localStorage.getItem('admin_token') }});loadAdminPanel('manage-products');loadProducts();});});} else if (tab === 'orders') {const orders = await fetchOrders();container.innerHTML = orders.map(o => `<div class=”border-b py-2”><div>订单 #${o.id} - 总价 ¥${o.total} - 状态:${o.status}</div><button class=”ship-btn bg-green-500 text-white px-2 py-1 rounded” data-id=”${o.id}” ${o.status === 'paid' ? '' : 'disabled'}>发货</button></div>`).join('');container.querySelectorAll('.ship-btn').forEach(btn => {btn.addEventListener('click', async () => {await updateOrderStatus(btn.dataset.id, 'shipped');loadAdminPanel('orders');});});}}
3. API 封装 (frontend/src/js/api.js)
const API_BASE = '/api'; // 在 Vercel 中会自动代理到云函数export async function fetchProducts() {const res = await fetch(`${API_BASE}/product`);return res.json();}export async function createOrder(orderData) {const res = await fetch(`${API_BASE}/order`, {method: 'POST',headers: { 'Content-Type': 'application/json' },body: JSON.stringify(orderData)});if (!res.ok) throw new Error('下单失败');return res.json();}export async function adminLogin(password) {const res = await fetch(`${API_BASE}/auth`, {method: 'POST',headers: { 'Content-Type': 'application/json' },body: JSON.stringify({ password })});if (!res.ok) throw new Error('登录失败');const { token } = await res.json();return token;}export async function fetchOrders() {const token = localStorage.getItem('admin_token');const res = await fetch(`${API_BASE}/order`, {headers: { 'Authorization': 'Bearer ' + token }});return res.json();}export async function updateOrderStatus(orderId, status) {const token = localStorage.getItem('admin_token');await fetch(`${API_BASE}/order/${orderId}`, {method: 'PUT',headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token },body: JSON.stringify({ status })});}
4. 后端云函数 (backend/api/)
4.1 数据库连接与模型 (backend/api/utils/db.js)
使用 MongoDB Atlas 免费层,通过 mongoose 连接。
import mongoose from 'mongoose';const MONGODB_URI = process.env.MONGODB_URI;if (!MONGODB_URI) throw new Error('请设置 MONGODB_URI 环境变量');let cached = global.mongoose;if (!cached) {cached = global.mongoose = { conn: null, promise: null };}export async function connectDB() {if (cached.conn) return cached.conn;if (!cached.promise) {cached.promise = mongoose.connect(MONGODB_URI, {useNewUrlParser: true,useUnifiedTopology: true,}).then(mongoose => mongoose);}cached.conn = await cached.promise;return cached.conn;}// 定义 Schemaconst productSchema = new mongoose.Schema({name: String,price: Number,image: String,createdAt: { type: Date, default: Date.now }});const orderSchema = new mongoose.Schema({items: Array,total: Number,paymentMethod: String,status: { type: String, default: 'pending' }, // pending, paid, shippedcreatedAt: { type: Date, default: Date.now }});export const Product = mongoose.models.Product || mongoose.model('Product', productSchema);export const Order = mongoose.models.Order || mongoose.model('Order', orderSchema);
4.2 商品 API (backend/api/product.js)
import { connectDB, Product } from './utils/db.js';import { verifyAdmin } from './utils/auth.js';export default async function handler(req, res) {await connectDB();if (req.method === 'GET') {const products = await Product.find().sort({ createdAt: -1 });return res.json(products);}// 以下需要管理员权限const admin = verifyAdmin(req);if (!admin) return res.status(401).json({ error: '未授权' });if (req.method === 'POST') {const { name, price, image } = req.body;const product = new Product({ name, price, image });await product.save();return res.json(product);}if (req.method === 'DELETE') {const { id } = req.query;await Product.findByIdAndDelete(id);return res.status(204).end();}res.status(405).json({ error: 'Method not allowed' });}
4.3 订单与支付 API (backend/api/order.js)
这里集成 PayJS 聚合支付(支持微信、支付宝、QQ),只需注册 PayJS 获取商户号。
import { connectDB, Order } from './utils/db.js';import { verifyAdmin } from './utils/auth.js';import crypto from 'crypto';const PAYJS_MCHID = process.env.PAYJS_MCHID;const PAYJS_KEY = process.env.PAYJS_KEY;const PAYJS_API = 'https://payjs.cn/api/native'; // 扫码支付export default async function handler(req, res) {await connectDB();// 创建订单(用户端)if (req.method === 'POST') {const { items, total, paymentMethod } = req.body;// 1. 保存订单到数据库const order = new Order({ items, total, paymentMethod, status: 'pending' });await order.save();// 2. 调用 PayJS 生成支付参数const payData = {mchid: PAYJS_MCHID,total_fee: Math.round(total * 100), // 分out_trade_no: order._id.toString(),body: '商品订单',notify_url: `${process.env.BASE_URL}/api/order/pay-callback`, // 支付回调地址};// 生成签名const sign = crypto.createHash('md5').update(Object.entries(payData).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${k}=${v}`).join('&') + `&key=${PAYJS_KEY}`).digest('hex');payData.sign = sign;const payRes = await fetch(PAYJS_API, {method: 'POST',headers: { 'Content-Type': 'application/x-www-form-urlencoded' },body: new URLSearchParams(payData)});const payResult = await payRes.json();if (payResult.return_code === 'SUCCESS') {// 返回支付二维码链接或跳转URLreturn res.json({orderId: order._id,payUrl: payResult.qrcode, // 或 payResult.code_url});} else {return res.status(500).json({ error: '支付网关错误' });}}// 获取订单列表(管理员)if (req.method === 'GET') {const admin = verifyAdmin(req);if (!admin) return res.status(401).json({ error: '未授权' });const orders = await Order.find().sort({ createdAt: -1 });return res.json(orders);}// 更新订单状态(发货)if (req.method === 'PUT') {const admin = verifyAdmin(req);if (!admin) return res.status(401).json({ error: '未授权' });const { id } = req.query;const { status } = req.body;await Order.findByIdAndUpdate(id, { status });return res.json({ success: true });}res.status(405).end();}// 支付回调(异步通知)export async function callback(req, res) {// PayJS 会发送 POST 请求,需验证签名并更新订单状态const { out_trade_no, total_fee, sign } = req.body;// 验证签名(省略,类似上述签名算法)// 如果验证通过,将订单状态改为 'paid'await Order.findByIdAndUpdate(out_trade_no, { status: 'paid' });// 可触发邮件通知、库存扣除等res.send('SUCCESS'); // PayJS 要求返回 SUCCESS}
注意:需要在 Vercel 中配置路由,将
/api/order/pay-callback指向此回调函数(或单独写成pay-callback.js)。
4.4 身份验证中间件 (backend/api/utils/auth.js)
export function verifyAdmin(req) {const token = req.headers.authorization?.split(' ')[1];// 简单实现:固定密码比对,实际可用 JWTif (token === process.env.ADMIN_TOKEN) return true;return false;}
4.5 登录 API (backend/api/auth.js)
import { verifyAdmin } from './utils/auth.js';export default function handler(req, res) {if (req.method !== 'POST') return res.status(405).end();const { password } = req.body;if (password === process.env.ADMIN_PASSWORD) {// 返回一个固定 token(演示)return res.json({ token: process.env.ADMIN_TOKEN });}res.status(401).json({ error: '密码错误' });}
四、部署到免费平台(Vercel + MongoDB Atlas)
1. 准备工作
-
注册 MongoDB Atlas 免费集群,获取连接字符串。 -
注册 PayJS 账号,获取商户号( mchid)和密钥。 -
在 Vercel 上创建项目并关联 GitHub 仓库。
2. 环境变量设置
在 Vercel 项目设置中添加以下环境变量:
MONGODB_URI=你的MongoDB连接串PAYJS_MCHID=你的商户号PAYJS_KEY=你的密钥ADMIN_PASSWORD=你的管理密码(如 admin123)ADMIN_TOKEN=任意JWT或固定字符串(用于前端请求头)BASE_URL=你的Vercel部署域名(如 https://my-site.vercel.app)
3. 项目配置
在项目根目录创建 vercel.json 来指定云函数路径:
{”functions”: {”api/*.js”: {”runtime”: ”nodejs18.x”}},”rewrites”: [{ ”source”: ”/(.*)”, ”destination”: ”/frontend/public/index.html” }]}
4. 部署
-
将代码推送到 GitHub。 -
在 Vercel 中导入该仓库,自动部署。 -
前端页面将运行在 https://你的域名.vercel.app,后端 API 在https://你的域名.vercel.app/api/...。
五、功能演示与说明
用户端:
-
浏览商品、加入购物车、下单支付。 -
支付方式选择微信、支付宝、QQ钱包,点击后弹出 PayJS 的二维码或跳转支付页面。 -
支付成功后,前端轮询订单状态,显示支付成功并自动“发货”(在演示中只是状态变化)。
管理端:
-
登录(输入预设密码)。 -
添加/删除商品。 -
查看所有订单,点击“发货”按钮更新订单状态(模拟发货)。
响应式设计:
-
基于 Tailwind CSS,在移动、平板、桌面设备上自适应。
六、重要提醒
- 支付功能需要真实商户号
PayJS 为聚合支付服务商,申请后即可使用,不需要服务器,费用较低。如果仅做演示,可使用 PayJS 的测试模式(但需要配置测试参数)。 - 安全注意
上述代码中的管理员验证采用固定 token,生产环境应改用 JWT + 过期时间。支付回调需要严格验证签名,防止伪造。 - 免费额度
Vercel 提供每月 100GB 流量和 1000 个云函数调用(足够个人站),MongoDB Atlas 免费层提供 512MB 存储。
由于无法直接在对话中提供文件,您可以根据上述代码框架自行创建项目。
如果您需要一键下载的压缩包,可以自行将上述代码保存为文件,或参考 GitHub 上的类似开源项目(如 nodejs-payjs-demo 等)进行整合。
通过此部署方案,您将会拥有了一个专属自己的完全免费、无需购买第三方服务器个人多功能单页网站,包含了完整的管理后台和三合一支付发货流程。
👆以上AI回复的需要重新整理扩展更多细节和对应的源代码,然后才能进行测试,你最好是让龙虾帮你动手操作,写学会自己部署龙虾到你电脑里实现拥有自己的免费劳工,带货链接如下👇







夜雨聆风