diff --git a/src/main/java/com/org/flashsalesystem/service/MessageListenerService.java b/src/main/java/com/org/flashsalesystem/service/MessageListenerService.java index 3194cec..ef2edb6 100644 --- a/src/main/java/com/org/flashsalesystem/service/MessageListenerService.java +++ b/src/main/java/com/org/flashsalesystem/service/MessageListenerService.java @@ -181,6 +181,51 @@ public class MessageListenerService { log.debug("推荐替代商品: 用户ID={}, 秒杀ID={}", userId, flashSaleId); } + /** + * 提取Long值 + */ + private Long extractLongValue(Object value) { + if (value == null) return null; + if (value instanceof Long) return (Long) value; + if (value instanceof Integer) return ((Integer) value).longValue(); + if (value instanceof String) return Long.valueOf((String) value); + return Long.valueOf(value.toString()); + } + + /** + * 提取Integer值 + */ + private Integer extractIntegerValue(Object value) { + if (value == null) return null; + if (value instanceof Integer) return (Integer) value; + if (value instanceof Long) return ((Long) value).intValue(); + if (value instanceof String) return Integer.valueOf((String) value); + return Integer.valueOf(value.toString()); + } + + /** + * 解析Redisson消息格式 + */ + private Map parseRedissonMessage(String messageBody) throws Exception { + // 处理Redisson序列化的数据格式 + if (messageBody.startsWith("[") && messageBody.contains("java.util.HashMap")) { + // 解析Redisson序列化格式: ["java.util.HashMap",{...}] + int startIndex = messageBody.indexOf('{'); + int endIndex = messageBody.lastIndexOf('}') + 1; + if (startIndex > 0 && endIndex > startIndex) { + String jsonPart = messageBody.substring(startIndex, endIndex); + // 处理Redisson的类型信息格式: ["java.lang.Long",11] -> 11 + jsonPart = jsonPart.replaceAll("\\[\"java\\.lang\\.(Long|Integer|String)\",([^\\]]+)\\]", "$2"); + return objectMapper.readValue(jsonPart, Map.class); + } else { + throw new RuntimeException("无法解析Redisson消息格式"); + } + } else { + // 标准JSON格式 + return objectMapper.readValue(messageBody, Map.class); + } + } + /** * 订单状态变更监听器 */ @@ -189,11 +234,13 @@ public class MessageListenerService { public void onMessage(Message message, byte[] pattern) { try { String messageBody = new String(message.getBody()); - Map data = objectMapper.readValue(messageBody, Map.class); + log.debug("接收到订单状态变更消息: {}", messageBody); - Long orderId = Long.valueOf(data.get("orderId").toString()); - Long userId = Long.valueOf(data.get("userId").toString()); - Integer status = Integer.valueOf(data.get("status").toString()); + Map data = parseRedissonMessage(messageBody); + + Long orderId = extractLongValue(data.get("orderId")); + Long userId = extractLongValue(data.get("userId")); + Integer status = extractIntegerValue(data.get("status")); String action = data.get("action").toString(); log.info("订单状态变更: 订单ID={}, 用户ID={}, 状态={}, 操作={}", @@ -216,10 +263,12 @@ public class MessageListenerService { public void onMessage(Message message, byte[] pattern) { try { String messageBody = new String(message.getBody()); - Map data = objectMapper.readValue(messageBody, Map.class); + log.debug("接收到库存变更消息: {}", messageBody); - Long productId = Long.valueOf(data.get("productId").toString()); - Integer quantity = Integer.valueOf(data.get("quantity").toString()); + Map data = parseRedissonMessage(messageBody); + + Long productId = extractLongValue(data.get("productId")); + Integer quantity = extractIntegerValue(data.get("quantity")); String operation = data.get("operation").toString(); log.info("库存变更: 商品ID={}, 数量={}, 操作={}", productId, quantity, operation); @@ -241,10 +290,12 @@ public class MessageListenerService { public void onMessage(Message message, byte[] pattern) { try { String messageBody = new String(message.getBody()); - Map data = objectMapper.readValue(messageBody, Map.class); + log.debug("接收到秒杀结果消息: {}", messageBody); - Long userId = Long.valueOf(data.get("userId").toString()); - Long flashSaleId = Long.valueOf(data.get("flashSaleId").toString()); + Map data = parseRedissonMessage(messageBody); + + Long userId = extractLongValue(data.get("userId")); + Long flashSaleId = extractLongValue(data.get("flashSaleId")); Boolean success = Boolean.valueOf(data.get("success").toString()); log.info("秒杀结果: 用户ID={}, 秒杀ID={}, 成功={}", userId, flashSaleId, success); @@ -266,9 +317,11 @@ public class MessageListenerService { public void onMessage(Message message, byte[] pattern) { try { String messageBody = new String(message.getBody()); - Map data = objectMapper.readValue(messageBody, Map.class); + log.debug("接收到用户行为消息: {}", messageBody); - Long userId = Long.valueOf(data.get("userId").toString()); + Map data = parseRedissonMessage(messageBody); + + Long userId = extractLongValue(data.get("userId")); String action = data.get("action").toString(); log.info("用户行为: 用户ID={}, 行为={}", userId, action); diff --git a/src/main/webapp/WEB-INF/views/order-detail.jsp b/src/main/webapp/WEB-INF/views/order-detail.jsp new file mode 100644 index 0000000..1422d7a --- /dev/null +++ b/src/main/webapp/WEB-INF/views/order-detail.jsp @@ -0,0 +1,571 @@ +<%@ 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" %> + + +<%@ include file="common/header.jsp" %> + +
+
+
+ +
+
+ + +
+
+ 加载中... +
+

正在加载订单详情...

+
+ + + + + + +
+ + + + + + + + +<%@ include file="common/footer.jsp" %> \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/orders.jsp b/src/main/webapp/WEB-INF/views/orders.jsp index 8fd45ea..1f4182b 100644 --- a/src/main/webapp/WEB-INF/views/orders.jsp +++ b/src/main/webapp/WEB-INF/views/orders.jsp @@ -494,11 +494,142 @@ // 支付订单 function payOrder(orderId) { if (confirm('确定要支付这个订单吗?')) { - // 这里可以集成真实的支付接口 - showMessage('支付功能开发中...', 'info'); + // 显示支付方式选择模态框 + showPaymentModal(orderId); } } + // 显示支付方式选择模态框 + function showPaymentModal(orderId) { + const modalHtml = ` + + `; + + // 移除现有的支付模态框 + $('#paymentModal').remove(); + + // 添加新的支付模态框 + $('body').append(modalHtml); + + // 设置订单ID到模态框数据属性中 + $('#paymentModal').attr('data-order-id', orderId); + + // 添加支付方式点击事件 + $('#paymentModal').on('click', '.form-check[data-payment-method]', function () { + const paymentMethod = $(this).attr('data-payment-method'); + const currentOrderId = $('#paymentModal').attr('data-order-id'); + selectPaymentMethod(paymentMethod, currentOrderId); + }); + + // 在模态框关闭时移除事件监听器 + $('#paymentModal').on('hidden.bs.modal', function () { + $(this).off('click'); + $(this).remove(); + }); + + // 显示模态框 + $('#paymentModal').modal('show'); + } + + // 选择支付方式并直接处理支付 + function selectPaymentMethod(paymentMethod, orderId) { + // 如果orderId未定义,从模态框数据属性中获取 + if (!orderId || orderId === 'undefined') { + orderId = $('#paymentModal').attr('data-order-id'); + } + + // 验证orderId + if (!orderId || orderId === 'undefined') { + showMessage('订单ID错误,请重新尝试', 'error'); + return; + } + + console.log('Processing payment for order:', orderId, 'with method:', paymentMethod); + + // 选中对应的单选框 + $('#paymentModal input[value="' + paymentMethod + '"]').prop('checked', true); + + // 显示支付处理中状态 + $('#paymentStatus').html(' 正在处理支付...'); + + // 禁用所有支付方式选项 + $('.payment-methods .form-check').css('pointer-events', 'none').css('opacity', '0.6'); + + // 模拟短暂延迟后调用后端支付接口 + setTimeout(function () { + $.ajax({ + url: '${pageContext.request.contextPath}/api/order/' + orderId + '/pay', + type: 'POST', + contentType: 'application/json', + data: JSON.stringify({ + paymentMethod: paymentMethod + }), + success: function (response) { + if (response.success) { + $('#paymentStatus').html(' 支付成功!'); + + // 2秒后关闭模态框并刷新订单列表 + setTimeout(function () { + $('#paymentModal').modal('hide'); + showMessage('支付成功!订单状态已更新为已支付', 'success'); + refreshOrders(); + }, 2000); + } else { + $('#paymentStatus').html(' 支付失败: ' + response.message + ''); + // 恢复支付方式选项 + $('.payment-methods .form-check').css('pointer-events', 'auto').css('opacity', '1'); + } + }, + error: function (xhr, status, error) { + let errorMessage = '支付失败,请稍后重试'; + if (xhr.responseJSON && xhr.responseJSON.message) { + errorMessage = xhr.responseJSON.message; + } + $('#paymentStatus').html(' ' + errorMessage + ''); + // 恢复支付方式选项 + $('.payment-methods .form-check').css('pointer-events', 'auto').css('opacity', '1'); + } + }); + }, 1000); // 1秒延迟模拟支付处理 + } + // 取消订单 function cancelOrder(orderId) { if (confirm('确定要取消这个订单吗?')) { @@ -626,6 +757,65 @@ font-weight: 500; width: 30%; } + + /* 支付方式样式 */ + .payment-methods .form-check { + border: 2px solid #dee2e6; + border-radius: 0.5rem; + padding: 1rem; + transition: all 0.3s ease; + cursor: pointer; + position: relative; + background: #fff; + } + + .payment-methods .form-check:hover { + border-color: #0d6efd; + box-shadow: 0 4px 12px rgba(13, 110, 253, 0.15); + transform: translateY(-2px); + } + + .payment-methods .form-check-input { + position: absolute; + top: 1rem; + right: 1rem; + transform: scale(1.2); + } + + .payment-methods .form-check-input:checked + .form-check-label { + color: #0d6efd; + font-weight: 600; + } + + .payment-methods .form-check-input:checked { + background-color: #0d6efd; + border-color: #0d6efd; + } + + .payment-methods .form-check:has(.form-check-input:checked) { + border-color: #0d6efd; + background-color: rgba(13, 110, 253, 0.05); + } + + .payment-methods .form-check-label { + cursor: pointer; + font-size: 1.1rem; + display: block; + margin-bottom: 0; + padding-right: 2.5rem; + } + + .payment-methods .form-check-label i { + font-size: 1.3rem; + margin-right: 0.5rem; + vertical-align: middle; + } + + #paymentStatus { + display: flex; + align-items: center; + gap: 0.5rem; + } <%@ include file="common/footer.jsp" %> \ No newline at end of file