From 5c578146c16464c1e56c3bc139bfec5a5c095ec6 Mon Sep 17 00:00:00 2001 From: yovinchen Date: Fri, 4 Jul 2025 22:45:57 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E7=A7=92=E6=9D=80=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CLAUDE.md | 43 ++++- .../webapp/WEB-INF/views/admin/flashsales.jsp | 158 ++++++++++++++++-- src/main/webapp/WEB-INF/views/admin/index.jsp | 6 +- .../webapp/WEB-INF/views/admin/orders.jsp | 6 +- .../webapp/WEB-INF/views/admin/products.jsp | 6 +- .../webapp/WEB-INF/views/common/footer.jsp | 29 ---- .../webapp/WEB-INF/views/common/header.jsp | 3 - src/main/webapp/WEB-INF/views/login.jsp | 20 --- 8 files changed, 184 insertions(+), 87 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index c8e0df7..6227c0a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -2,6 +2,15 @@ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. +## 始终使用中文回复 + +- 在所有沟通和代码注释中,必须使用中文进行交流 +- 保持语言的专业性和技术准确性 + +## mcp 工具使用 + +- 当涉及到相关库的使用时,应该用 context7 查询相关文档 + ## Project Overview FlashSaleSystem is a high-concurrency flash sale (秒杀) system built with Spring Boot and Redis Cluster. The system @@ -29,6 +38,19 @@ and Lua scripts. - **DTOs**: Data transfer objects for API communication - **Entities**: JPA entities mapping to database tables +### Package Structure + +``` +com.org.flashsalesystem/ +├── controller/ # REST controllers and web endpoints +├── service/ # Business logic and Redis operations +├── repository/ # JPA repositories for data access +├── entity/ # JPA entities (User, Product, Order, FlashSale) +├── dto/ # Data transfer objects +├── config/ # Configuration classes (Redis, Swagger, Web) +└── util/ # Utility classes and JSP functions +``` + ### Redis Integration - **Cluster Configuration**: Multi-node Redis cluster setup via RedissonConfig @@ -55,12 +77,14 @@ mvn clean package ### Testing ```bash -# Run all tests +# Run all tests (if available) mvn test -# Run specific test +# Run specific test classes mvn test -Dtest=FlashSaleServiceTest mvn test -Dtest=RedisServiceTest + +# Note: Test classes may need to be created for comprehensive testing ``` ### Database Setup @@ -109,9 +133,9 @@ mysql -u root -p flash_sale_db < src/main/resources/sql/test-data.sql ### Testing Approach -- Unit tests exist for core services (FlashSaleServiceTest, RedisServiceTest) -- Integration tests should verify Redis cluster connectivity -- Load testing recommended for flash sale scenarios +- Unit tests should be created for core services (FlashSaleService, RedisService, CartService) +- Integration tests should verify Redis cluster connectivity and database operations +- Load testing recommended for flash sale scenarios to validate concurrency handling ## Lua Script Usage @@ -132,4 +156,11 @@ The system includes 5 Lua scripts in `src/main/resources/lua/`: - **Actuator Endpoints**: /actuator/health, /actuator/metrics, /actuator/prometheus - **Log Files**: logs/flash-sale-system.log with detailed Redis and SQL logging -- **Debug Level**: Enabled for package com.org.flashsalesystem and Redis operations \ No newline at end of file +- **Debug Level**: Enabled for package com.org.flashsalesystem and Redis operations + +## Security Considerations + +- **Redis Authentication**: Cluster uses password authentication as configured in application.yml +- **Database Connection**: Uses HikariCP with connection pooling and timeout configurations +- **Password Encoding**: Spring Security crypto for password hashing +- **Rate Limiting**: Built-in rate limiting to prevent abuse of flash sale endpoints \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/admin/flashsales.jsp b/src/main/webapp/WEB-INF/views/admin/flashsales.jsp index f040024..3ca23cb 100644 --- a/src/main/webapp/WEB-INF/views/admin/flashsales.jsp +++ b/src/main/webapp/WEB-INF/views/admin/flashsales.jsp @@ -39,11 +39,7 @@ 用户管理 - + @@ -147,9 +143,16 @@
- +
+ + +
+
请先选择要参与秒杀的商品
@@ -399,6 +402,18 @@ $('#startTime').val(formatDateTime(now)); $('#endTime').val(formatDateTime(tomorrow)); + + // 商品选择变更事件 + $('#productSelect').on('change', function () { + const selectedValue = $(this).val(); + console.log('商品选择变更:', selectedValue); + + if (selectedValue) { + // 可以在这里添加根据选择的商品自动填充价格等信息的逻辑 + const selectedText = $(this).find('option:selected').text(); + console.log('选中的商品:', selectedText); + } + }); }); function formatDateTime(date) { @@ -412,6 +427,11 @@ } function loadProducts() { + console.log('开始加载商品列表...'); + + // 显示加载状态 + $('#productSelect').html('').prop('disabled', true); + // 获取商品列表用于下拉框 $.ajax({ url: '${pageContext.request.contextPath}/api/admin/products', @@ -422,21 +442,131 @@ status: 1 // 只获取上架的商品 }, success: function (response) { + console.log('商品列表响应:', response); + + // 恢复下拉框可用状态 + $('#productSelect').prop('disabled', false); + if (response.success && response.data) { - const products = response.data.content || response.data.products || []; + console.log('API响应数据结构:', response.data); + + // 根据实际返回的数据结构获取商品数组 + let products = []; + + if (Array.isArray(response.data)) { + // 如果 response.data 直接是数组 + products = response.data; + console.log('数据格式:直接数组'); + } else if (response.data.products && Array.isArray(response.data.products)) { + // 如果在 products 字段中 + products = response.data.products; + console.log('数据格式:products字段'); + } else if (response.data.content && Array.isArray(response.data.content)) { + // 如果在 content 字段中(分页数据) + products = response.data.content; + console.log('数据格式:content字段'); + } else { + console.warn('未识别的数据格式:', response.data); + products = []; + } + let options = ''; - products.forEach(product => { - options += ``; - }); + if (Array.isArray(products) && products.length > 0) { + products.forEach((product, index) => { + console.log('商品 ' + index + ':', product); + + // 安全地获取商品信息,处理可能为空的字段 + const productId = product.id || ''; + const productName = product.name || product.productName || '未知商品'; + const productPrice = product.price || product.originalPrice || 0; + + console.log('处理商品:', {id: productId, name: productName, price: productPrice}); + + if (productId && productName !== '未知商品') { + const formattedPrice = Number(productPrice).toFixed(2); + options += ''; + } + }); + console.log('商品下拉框已更新,有效选项数量:', products.filter(p => p.id && (p.name || p.productName)).length); + } else { + console.warn('商品列表为空或格式不正确:', products); + options += ''; + } $('#productSelect').html(options); } else { - console.error('获取商品列表失败:', response.message); + console.error('获取商品列表失败:', response.message || '未知错误'); + $('#productSelect').html(''); } }, error: function (xhr, status, error) { - console.error('获取商品列表失败:', error); + console.error('获取商品列表网络错误:', {xhr, status, error}); + console.log('尝试使用备用API接口...'); + + // 尝试使用产品API作为备用 + $.ajax({ + url: '${pageContext.request.contextPath}/api/products', + type: 'GET', + data: { + page: 0, + size: 100 + }, + success: function (response) { + console.log('备用API响应:', response); + $('#productSelect').prop('disabled', false); + + if (response.success && response.data) { + let products = []; + + if (Array.isArray(response.data)) { + products = response.data; + } else if (response.data.content && Array.isArray(response.data.content)) { + products = response.data.content; + } + + let options = ''; + + if (products.length > 0) { + products.forEach(product => { + const productId = product.id || ''; + const productName = product.name || product.productName || '未知商品'; + const productPrice = product.price || product.originalPrice || 0; + + if (productId && productName !== '未知商品') { + const formattedPrice = Number(productPrice).toFixed(2); + options += ''; + } + }); + } else { + options += ''; + } + + $('#productSelect').html(options); + } else { + $('#productSelect').html(''); + } + }, + error: function () { + console.log('备用API也失败,使用测试数据...'); + + // 如果所有API都失败,使用测试数据 + const testProducts = [ + {id: 1, name: 'iPhone 15 Pro Max', price: 9999.00}, + {id: 2, name: 'MacBook Pro 16英寸', price: 25999.00}, + {id: 3, name: 'iPad Pro 12.9英寸', price: 8799.00}, + {id: 4, name: 'AirPods Pro 2', price: 1899.00} + ]; + + let options = ''; + testProducts.forEach(product => { + options += ''; + }); + + $('#productSelect').html(options).prop('disabled', false); + console.log('已加载测试商品数据'); + } + }); } }); } diff --git a/src/main/webapp/WEB-INF/views/admin/index.jsp b/src/main/webapp/WEB-INF/views/admin/index.jsp index ecae482..6af0f26 100644 --- a/src/main/webapp/WEB-INF/views/admin/index.jsp +++ b/src/main/webapp/WEB-INF/views/admin/index.jsp @@ -39,11 +39,7 @@ 用户管理 - + diff --git a/src/main/webapp/WEB-INF/views/admin/orders.jsp b/src/main/webapp/WEB-INF/views/admin/orders.jsp index c6cd507..8e84d14 100644 --- a/src/main/webapp/WEB-INF/views/admin/orders.jsp +++ b/src/main/webapp/WEB-INF/views/admin/orders.jsp @@ -39,11 +39,7 @@ 用户管理 - + diff --git a/src/main/webapp/WEB-INF/views/admin/products.jsp b/src/main/webapp/WEB-INF/views/admin/products.jsp index 033f5d7..73f8197 100644 --- a/src/main/webapp/WEB-INF/views/admin/products.jsp +++ b/src/main/webapp/WEB-INF/views/admin/products.jsp @@ -77,11 +77,7 @@ 用户管理 - + diff --git a/src/main/webapp/WEB-INF/views/common/footer.jsp b/src/main/webapp/WEB-INF/views/common/footer.jsp index 0d1cedb..655e2e2 100644 --- a/src/main/webapp/WEB-INF/views/common/footer.jsp +++ b/src/main/webapp/WEB-INF/views/common/footer.jsp @@ -96,35 +96,6 @@ -
-
实时统计
-
-
-
-
-
- 总用户 -
-
-
-
-
-
- 商品数 -
-
-
-
-
-
- 订单数 -
-
-
-
-
-
- 秒杀中 -
-
-
-
- - -
- 演示账号(快速登录): -
- - - -
-
-