后台完成修复,初始化项目

This commit is contained in:
2025-07-01 17:18:04 +08:00
commit 5916f076b7
74 changed files with 17444 additions and 0 deletions

View File

@@ -0,0 +1,472 @@
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://flashsale.org/functions" %>
<c:set var="pageTitle" value="首页" />
<%@ include file="common/header.jsp" %>
<!-- 轮播图 -->
<div id="heroCarousel" class="carousel slide" data-bs-ride="carousel">
<div class="carousel-indicators">
<button type="button" data-bs-target="#heroCarousel" data-bs-slide-to="0" class="active"></button>
<button type="button" data-bs-target="#heroCarousel" data-bs-slide-to="1"></button>
<button type="button" data-bs-target="#heroCarousel" data-bs-slide-to="2"></button>
</div>
<div class="carousel-inner">
<div class="carousel-item active">
<div class="bg-gradient-danger text-white py-5" style="min-height: 400px;">
<div class="container d-flex align-items-center h-100">
<div class="row w-100">
<div class="col-md-6">
<h1 class="display-4 fw-bold mb-4">
<i class="fas fa-bolt"></i> 秒杀系统
</h1>
<p class="lead mb-4">基于Redis集群构建的高并发秒杀系统支持分布式锁、接口限流、库存预热等核心功能。</p>
<div class="d-flex gap-3">
<a href="${pageContext.request.contextPath}/flashsales" class="btn btn-light btn-lg">
<i class="fas fa-fire"></i> 立即抢购
</a>
<a href="${pageContext.request.contextPath}/products" class="btn btn-outline-light btn-lg">
<i class="fas fa-shopping-bag"></i> 浏览商品
</a>
</div>
</div>
<div class="col-md-6 text-center">
<i class="fas fa-rocket fa-10x opacity-50"></i>
</div>
</div>
</div>
</div>
</div>
<div class="carousel-item">
<div class="bg-gradient-primary text-white py-5" style="min-height: 400px;">
<div class="container d-flex align-items-center h-100">
<div class="row w-100">
<div class="col-md-6">
<h1 class="display-4 fw-bold mb-4">
<i class="fas fa-shield-alt"></i> 防超卖机制
</h1>
<p class="lead mb-4">采用Redis分布式锁和Lua脚本确保高并发场景下的数据一致性彻底解决超卖问题。</p>
<a href="#features" class="btn btn-light btn-lg">
<i class="fas fa-info-circle"></i> 了解更多
</a>
</div>
<div class="col-md-6 text-center">
<i class="fas fa-lock fa-10x opacity-50"></i>
</div>
</div>
</div>
</div>
</div>
<div class="carousel-item">
<div class="bg-gradient-success text-white py-5" style="min-height: 400px;">
<div class="container d-flex align-items-center h-100">
<div class="row w-100">
<div class="col-md-6">
<h1 class="display-4 fw-bold mb-4">
<i class="fas fa-tachometer-alt"></i> 高性能缓存
</h1>
<p class="lead mb-4">Redis集群架构支持五种数据类型应用实现毫秒级响应轻松应对高并发访问。</p>
<a href="#performance" class="btn btn-light btn-lg">
<i class="fas fa-chart-line"></i> 性能指标
</a>
</div>
<div class="col-md-6 text-center">
<i class="fas fa-database fa-10x opacity-50"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<button class="carousel-control-prev" type="button" data-bs-target="#heroCarousel" data-bs-slide="prev">
<span class="carousel-control-prev-icon"></span>
</button>
<button class="carousel-control-next" type="button" data-bs-target="#heroCarousel" data-bs-slide="next">
<span class="carousel-control-next-icon"></span>
</button>
</div>
<div class="container my-5">
<!-- 正在进行的秒杀活动 -->
<section class="mb-5">
<div class="d-flex justify-content-between align-items-center mb-4">
<h2 class="fw-bold">
<i class="fas fa-fire text-danger"></i> 正在秒杀
</h2>
<a href="${pageContext.request.contextPath}/flashsales" class="btn btn-outline-danger">
查看全部 <i class="fas fa-arrow-right"></i>
</a>
</div>
<div id="activeFlashSales" class="row">
<!-- 动态加载秒杀活动 -->
<div class="col-12 text-center py-5">
<i class="fas fa-spinner fa-spin fa-2x text-muted"></i>
<p class="text-muted mt-2">加载中...</p>
</div>
</div>
</section>
<!-- 热门商品 -->
<section class="mb-5">
<div class="d-flex justify-content-between align-items-center mb-4">
<h2 class="fw-bold">
<i class="fas fa-star text-warning"></i> 热门商品
</h2>
<a href="${pageContext.request.contextPath}/products" class="btn btn-outline-primary">
查看全部 <i class="fas fa-arrow-right"></i>
</a>
</div>
<div id="hotProducts" class="row">
<!-- 动态加载热门商品 -->
<div class="col-12 text-center py-5">
<i class="fas fa-spinner fa-spin fa-2x text-muted"></i>
<p class="text-muted mt-2">加载中...</p>
</div>
</div>
</section>
<!-- 系统特性 -->
<section id="features" class="mb-5">
<h2 class="text-center fw-bold mb-5">
<i class="fas fa-cogs"></i> 系统特性
</h2>
<div class="row g-4">
<div class="col-md-3 col-sm-6">
<div class="card h-100 text-center border-0 shadow-sm">
<div class="card-body">
<i class="fas fa-bolt fa-3x text-danger mb-3"></i>
<h5 class="card-title">秒杀抢购</h5>
<p class="card-text text-muted">高并发秒杀系统,支持大量用户同时抢购</p>
</div>
</div>
</div>
<div class="col-md-3 col-sm-6">
<div class="card h-100 text-center border-0 shadow-sm">
<div class="card-body">
<i class="fas fa-shield-alt fa-3x text-success mb-3"></i>
<h5 class="card-title">防超卖</h5>
<p class="card-text text-muted">分布式锁机制,确保库存数据一致性</p>
</div>
</div>
</div>
<div class="col-md-3 col-sm-6">
<div class="card h-100 text-center border-0 shadow-sm">
<div class="card-body">
<i class="fas fa-database fa-3x text-info mb-3"></i>
<h5 class="card-title">Redis缓存</h5>
<p class="card-text text-muted">五种数据类型应用,毫秒级响应</p>
</div>
</div>
</div>
<div class="col-md-3 col-sm-6">
<div class="card h-100 text-center border-0 shadow-sm">
<div class="card-body">
<i class="fas fa-tachometer-alt fa-3x text-warning mb-3"></i>
<h5 class="card-title">接口限流</h5>
<p class="card-text text-muted">多种限流策略,防止恶意刷单</p>
</div>
</div>
</div>
</div>
</section>
<!-- 性能指标 -->
<section id="performance" class="mb-5">
<h2 class="text-center fw-bold mb-5">
<i class="fas fa-chart-line"></i> 性能指标
</h2>
<div class="row g-4">
<div class="col-md-3 col-sm-6">
<div class="card border-primary">
<div class="card-body text-center">
<h3 class="text-primary fw-bold" id="qpsCounter">10000+</h3>
<p class="card-text">QPS并发处理</p>
</div>
</div>
</div>
<div class="col-md-3 col-sm-6">
<div class="card border-success">
<div class="card-body text-center">
<h3 class="text-success fw-bold" id="responseTime">&lt;100ms</h3>
<p class="card-text">平均响应时间</p>
</div>
</div>
</div>
<div class="col-md-3 col-sm-6">
<div class="card border-warning">
<div class="card-body text-center">
<h3 class="text-warning fw-bold" id="successRate">99.9%</h3>
<p class="card-text">系统可用性</p>
</div>
</div>
</div>
<div class="col-md-3 col-sm-6">
<div class="card border-info">
<div class="card-body text-center">
<h3 class="text-info fw-bold" id="concurrentUsers">50000+</h3>
<p class="card-text">并发用户支持</p>
</div>
</div>
</div>
</div>
</section>
</div>
<script>
$(document).ready(function() {
// 加载正在进行的秒杀活动
loadActiveFlashSales();
// 加载热门商品
loadHotProducts();
// 启动性能指标动画
animateCounters();
});
// 加载正在进行的秒杀活动
function loadActiveFlashSales() {
$.get('${pageContext.request.contextPath}/api/flashsale/active')
.done(function(response) {
if (response.success && response.data.length > 0) {
renderFlashSales(response.data.slice(0, 4)); // 只显示前4个
} else {
$('#activeFlashSales').html(`
<div class="col-12 text-center py-5">
<i class="fas fa-info-circle fa-2x text-muted"></i>
<p class="text-muted mt-2">暂无进行中的秒杀活动</p>
</div>
`);
}
})
.fail(function() {
$('#activeFlashSales').html(`
<div class="col-12 text-center py-5">
<i class="fas fa-exclamation-triangle fa-2x text-warning"></i>
<p class="text-muted mt-2">加载失败,请刷新页面重试</p>
</div>
`);
});
}
// 渲染秒杀活动
function renderFlashSales(flashSales) {
let html = '';
flashSales.forEach(function(flashSale) {
const discountPercent = Math.round((1 - flashSale.flashPrice / flashSale.originalPrice) * 100);
html += `
<div class="col-lg-3 col-md-6 mb-4">
<div class="card h-100 border-danger">
<div class="position-relative">
<img src="` + (flashSale.productImageUrl || '${pageContext.request.contextPath}/images/default-product.svg') + `"
class="card-img-top" alt="` + flashSale.productName + `" style="height: 200px; object-fit: cover;"
onerror="this.src='${pageContext.request.contextPath}/images/default-product.svg'; this.onerror=null;">
<div class="position-absolute top-0 start-0 bg-danger text-white px-2 py-1 rounded-end">
<small><i class="fas fa-fire"></i> 秒杀中</small>
</div>
<div class="position-absolute top-0 end-0 bg-warning text-dark px-2 py-1 rounded-start">
<small>${discountPercent}% OFF</small>
</div>
</div>
<div class="card-body">
<h6 class="card-title text-truncate">` + flashSale.productName + `</h6>
<div class="d-flex justify-content-between align-items-center mb-2">
<div>
<span class="text-danger fw-bold fs-5">¥` + (flashSale.flashPrice ? flashSale.flashPrice.toFixed(2) : '0.00') + `</span>
<small class="text-muted text-decoration-line-through ms-2">¥` + (flashSale.originalPrice ? flashSale.originalPrice.toFixed(2) : '0.00') + `</small>
</div>
</div>
<div class="mb-2">
<small class="text-muted">剩余: ` + (flashSale.remainingStock || 0) + `件</small>
<div class="progress" style="height: 4px;">
<div class="progress-bar bg-danger" style="width: ` + ((flashSale.remainingStock || 0) / (flashSale.flashStock || 1) * 100) + `%"></div>
</div>
</div>
<div class="text-center">
<div class="text-danger fw-bold mb-2" id="countdown_${flashSale.id}">
计算中...
</div>
<button class="btn btn-danger btn-sm w-100" onclick="participateFlashSale(${flashSale.id})">
<i class="fas fa-bolt"></i> 立即抢购
</button>
</div>
</div>
</div>
</div>
`;
// 启动倒计时
setTimeout(() => {
if (flashSale.timeToEnd > 0) {
countdown(Date.now() + flashSale.timeToEnd, 'countdown_' + flashSale.id);
}
}, 100);
});
$('#activeFlashSales').html(html);
}
// 加载热门商品
function loadHotProducts() {
$.get('${pageContext.request.contextPath}/api/product/hot?limit=8')
.done(function(response) {
if (response.success && response.data.length > 0) {
renderHotProducts(response.data);
} else {
$('#hotProducts').html(`
<div class="col-12 text-center py-5">
<i class="fas fa-info-circle fa-2x text-muted"></i>
<p class="text-muted mt-2">暂无热门商品</p>
</div>
`);
}
})
.fail(function() {
$('#hotProducts').html(`
<div class="col-12 text-center py-5">
<i class="fas fa-exclamation-triangle fa-2x text-warning"></i>
<p class="text-muted mt-2">加载失败,请刷新页面重试</p>
</div>
`);
});
}
// 渲染热门商品
function renderHotProducts(products) {
let html = '';
products.forEach(function(product) {
html += `
<div class="col-lg-3 col-md-6 mb-4">
<div class="card h-100">
<img src="${product.imageUrl || '${pageContext.request.contextPath}/images/default-product.svg'}"
class="card-img-top" alt="${product.name}" style="height: 200px; object-fit: cover;"
onerror="this.src='${pageContext.request.contextPath}/images/default-product.svg'; this.onerror=null;">
<div class="card-body">
<h6 class="card-title text-truncate">` + product.name + `</h6>
<p class="card-text text-muted small text-truncate">` + (product.description || '暂无描述') + `</p>
<div class="d-flex justify-content-between align-items-center">
<span class="text-primary fw-bold">¥` + (product.price ? product.price.toFixed(2) : '0.00') + `</span>
<small class="text-muted">库存: ` + (product.stock || 0) + `</small>
</div>
<div class="mt-2">
<button class="btn btn-primary btn-sm w-100" onclick="addToCart(` + product.id + `)">
<i class="fas fa-cart-plus"></i> 加入购物车
</button>
</div>
</div>
</div>
</div>
`;
});
$('#hotProducts').html(html);
}
// 参与秒杀
function participateFlashSale(flashSaleId) {
<c:choose>
<c:when test="${not empty sessionScope.user}">
if (confirm('确定要参与这个秒杀活动吗?')) {
$.ajax({
url: '${pageContext.request.contextPath}/api/flashsale/participate',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({
flashSaleId: flashSaleId,
quantity: 1
}),
success: function(response) {
if (response.success) {
showMessage('秒杀成功!订单已生成', 'success');
setTimeout(() => {
window.location.href = '${pageContext.request.contextPath}/orders';
}, 2000);
} else {
showMessage(response.message, 'error');
}
},
error: function() {
showMessage('秒杀失败,请重试', 'error');
}
});
}
</c:when>
<c:otherwise>
showMessage('请先登录', 'warning');
setTimeout(() => {
window.location.href = '${pageContext.request.contextPath}/login';
}, 1000);
</c:otherwise>
</c:choose>
}
// 添加到购物车
function addToCart(productId) {
<c:choose>
<c:when test="${not empty sessionScope.user}">
$.ajax({
url: '${pageContext.request.contextPath}/api/cart/add',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({
productId: productId,
quantity: 1
}),
success: function(response) {
if (response.success) {
showMessage('商品已添加到购物车', 'success');
updateCartCount();
} else {
showMessage(response.message, 'error');
}
},
error: function() {
showMessage('添加失败,请重试', 'error');
}
});
</c:when>
<c:otherwise>
showMessage('请先登录', 'warning');
setTimeout(() => {
window.location.href = '${pageContext.request.contextPath}/login';
}, 1000);
</c:otherwise>
</c:choose>
}
// 性能指标动画
function animateCounters() {
const counters = [
{ id: 'qpsCounter', target: 10000, suffix: '+' },
{ id: 'concurrentUsers', target: 50000, suffix: '+' }
];
counters.forEach(counter => {
animateCounter(counter.id, counter.target, counter.suffix);
});
}
function animateCounter(elementId, target, suffix = '') {
const element = document.getElementById(elementId);
let current = 0;
const increment = target / 100;
const timer = setInterval(() => {
current += increment;
if (current >= target) {
current = target;
clearInterval(timer);
}
element.textContent = Math.floor(current).toLocaleString() + suffix;
}, 20);
}
</script>
<%@ include file="common/footer.jsp" %>