From 2fbe14b811f40ad5d48ef94e5513f933e175853f Mon Sep 17 00:00:00 2001 From: hzjcd <3357883100@qq.com> Date: Tue, 2 Dec 2025 17:35:49 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E9=80=9A=E7=9F=A5=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=EF=BC=9A=201.=20=E6=95=B0=E6=8D=AE=E5=BA=93=E5=B1=82?= =?UTF-8?q?=E9=9D=A2=EF=BC=9A=E5=9C=A8Users=E8=A1=A8=E5=92=8CSupplyUsers?= =?UTF-8?q?=E8=A1=A8=E4=B8=AD=E6=B7=BB=E5=8A=A0notice=E5=AD=97=E6=AE=B5=20?= =?UTF-8?q?2.=20Mapper=E5=B1=82=EF=BC=9A=E4=BF=AE=E6=94=B9UsersMapper.xml?= =?UTF-8?q?=E5=92=8CSupplyUsersMapper.xml=EF=BC=8C=E6=B7=BB=E5=8A=A0notice?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=203.=20=E5=89=8D=E7=AB=AF=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=EF=BC=9A=E5=AE=9E=E7=8E=B0=E9=80=9A=E7=9F=A5=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=8C=E5=8C=85=E6=8B=AC=E9=80=9A=E7=9F=A5=E6=95=B0=E9=87=8F?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E3=80=81=E9=80=9A=E7=9F=A5=E5=BC=B9=E7=AA=97?= =?UTF-8?q?=E3=80=81=E5=AE=A2=E6=88=B7=E8=AF=A6=E6=83=85=E6=9F=A5=E7=9C=8B?= =?UTF-8?q?=204.=20=E4=BF=AE=E5=A4=8D=E8=AF=AD=E6=B3=95=E9=94=99=E8=AF=AF?= =?UTF-8?q?=EF=BC=9A=E5=B0=86=E6=A0=B7=E5=BC=8F=E4=BB=A3=E7=A0=81=E4=BB=8E?= =?UTF-8?q?=E7=B1=BB=E5=86=85=E9=83=A8=E7=A7=BB=E8=87=B3=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E6=9C=AB=E5=B0=BEscript=E6=A0=87=E7=AD=BE=E5=86=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/controller/CustomerController.java | 26 + .../web/controller/EnterpriseController.java | 2 + .../controller/SupplyCustomerController.java | 28 ++ .../SupplyEnterpriseController.java | 2 + .../example/web/dto/UnifiedCustomerDTO.java | 14 +- .../example/web/dto/UserProductCartDTO.java | 9 + .../java/com/example/web/entity/Users.java | 12 +- .../example/web/mapper/SupplyUsersMapper.java | 4 + .../com/example/web/mapper/UsersMapper.java | 11 +- .../web/service/PoolCustomerService.java | 17 +- .../service/SupplyPoolCustomerService.java | 17 + .../resources/mapper/SupplyUsersMapper.xml | 21 +- src/main/resources/mapper/UsersMapper.xml | 15 +- src/main/resources/static/loginmm.html | 2 +- src/main/resources/static/mainapp-sells.html | 453 ++++++++++++++++- .../resources/static/mainapp-supplys.html | 454 +++++++++++++++++- 16 files changed, 1064 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/example/web/controller/CustomerController.java b/src/main/java/com/example/web/controller/CustomerController.java index aa6b5e2..3e6ab30 100644 --- a/src/main/java/com/example/web/controller/CustomerController.java +++ b/src/main/java/com/example/web/controller/CustomerController.java @@ -40,6 +40,8 @@ public class CustomerController { @Autowired private UsersManagementsMapper usersManagementsMapper; + @Autowired + private com.example.web.mapper.UsersMapper usersMapper; @Autowired private InformationTraService informationTraService; @@ -49,6 +51,28 @@ public class CustomerController { * 根据公司ID查询客户详情 - 优先处理wechat数据源 * GET /pool/customers/{id} */ + // 更新客户通知状态 + @PutMapping("/customers/{id}/notice") + public ResponseEntity> updateCustomerNotice(@PathVariable String id) { + try { + // 直接调用mapper更新通知状态 + System.out.println("🔄 手动更新通知状态, userId: " + id + ", 从banold改为old"); + usersMapper.updateNotice(id, "old"); + // 返回成功响应 + Map response = new HashMap<>(); + response.put("success", true); + response.put("message", "通知状态更新成功"); + return ResponseEntity.ok(response); + } catch (Exception e) { + System.err.println("❌ 更新通知状态失败: " + e.getMessage()); + // 返回失败响应 + Map response = new HashMap<>(); + response.put("success", false); + response.put("message", "通知状态更新失败: " + e.getMessage()); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response); + } + } + @GetMapping("/customers/{id}") public ResponseEntity> getById(@PathVariable String id, HttpServletRequest request) { System.out.println("===================================================="); @@ -350,6 +374,8 @@ public class CustomerController { dto.setLevel(userInfo.getLevel() != null ? userInfo.getLevel() : "公海池"); dto.setCreated_at(userInfo.getCreated_at()); dto.setUpdated_at(userInfo.getUpdated_at()); + // 添加通知信息转换 + dto.setNotice(userInfo.getNotice() != null ? userInfo.getNotice() : ""); // 关键:设置数据源标识为wechat dto.setDataSource("wechat"); diff --git a/src/main/java/com/example/web/controller/EnterpriseController.java b/src/main/java/com/example/web/controller/EnterpriseController.java index 3974e24..e4c3989 100644 --- a/src/main/java/com/example/web/controller/EnterpriseController.java +++ b/src/main/java/com/example/web/controller/EnterpriseController.java @@ -631,6 +631,8 @@ public class EnterpriseController { dto.setLevel(userInfo.getLevel() != null ? userInfo.getLevel() : "公海池"); dto.setCreated_at(userInfo.getCreated_at()); dto.setUpdated_at(userInfo.getUpdated_at()); + // 添加通知信息转换 + dto.setNotice(userInfo.getNotice() != null ? userInfo.getNotice() : ""); // 关键:设置数据源标识为wechat dto.setDataSource("wechat"); diff --git a/src/main/java/com/example/web/controller/SupplyCustomerController.java b/src/main/java/com/example/web/controller/SupplyCustomerController.java index 87f618b..f8e8501 100644 --- a/src/main/java/com/example/web/controller/SupplyCustomerController.java +++ b/src/main/java/com/example/web/controller/SupplyCustomerController.java @@ -35,10 +35,36 @@ public class SupplyCustomerController { @Autowired private SupplyUsersManagementsMapper supplyUsersManagementsMapper; + @Autowired + private com.example.web.mapper.SupplyUsersMapper supplyUsersMapper; @Autowired private InformationTraService informationTraService; + /** + * 采购端 - 更新客户通知状态 + */ + @PutMapping("/customers/{id}/notice") + public ResponseEntity> updateCustomerNotice(@PathVariable String id) { + try { + // 直接调用mapper更新通知状态 + System.out.println("🔄 采购端手动更新通知状态, userId: " + id + ", 从banold改为old"); + supplyUsersMapper.updateNotice(id, "old"); + // 返回成功响应 + Map response = new HashMap<>(); + response.put("success", true); + response.put("message", "通知状态更新成功"); + return ResponseEntity.ok(response); + } catch (Exception e) { + System.err.println("❌ 采购端更新通知状态失败: " + e.getMessage()); + // 返回失败响应 + Map response = new HashMap<>(); + response.put("success", false); + response.put("message", "通知状态更新失败: " + e.getMessage()); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response); + } + } + /** * 根据公司ID查询客户详情 - 优先处理wechat数据源 * GET /supply/pool/customers/{id} @@ -340,6 +366,8 @@ public class SupplyCustomerController { dto.setLevel(userInfo.getLevel() != null ? userInfo.getLevel() : "公海池"); dto.setCreated_at(userInfo.getCreated_at()); dto.setUpdated_at(userInfo.getUpdated_at()); + // 添加通知信息转换 + dto.setNotice(userInfo.getNotice() != null ? userInfo.getNotice() : ""); // 关键:设置数据源标识为wechat dto.setDataSource("wechat"); diff --git a/src/main/java/com/example/web/controller/SupplyEnterpriseController.java b/src/main/java/com/example/web/controller/SupplyEnterpriseController.java index 00d8f58..e15d03d 100644 --- a/src/main/java/com/example/web/controller/SupplyEnterpriseController.java +++ b/src/main/java/com/example/web/controller/SupplyEnterpriseController.java @@ -608,6 +608,8 @@ public class SupplyEnterpriseController { dto.setLevel(userInfo.getLevel() != null ? userInfo.getLevel() : "公海池"); dto.setCreated_at(userInfo.getCreated_at()); dto.setUpdated_at(userInfo.getUpdated_at()); + // 添加通知信息转换 + dto.setNotice(userInfo.getNotice() != null ? userInfo.getNotice() : ""); // 关键:设置数据源标识为wechat dto.setDataSource("wechat"); diff --git a/src/main/java/com/example/web/dto/UnifiedCustomerDTO.java b/src/main/java/com/example/web/dto/UnifiedCustomerDTO.java index e795ae2..fca85ee 100644 --- a/src/main/java/com/example/web/dto/UnifiedCustomerDTO.java +++ b/src/main/java/com/example/web/dto/UnifiedCustomerDTO.java @@ -45,7 +45,7 @@ public class UnifiedCustomerDTO { private String role = ""; // 负责人角色 private String userName = ""; // 负责人用户名 private String assistant = ""; // 协助人 - + private String notice = ""; // 通知信息 // 时间信息 private LocalDateTime created_at; @@ -305,7 +305,17 @@ public class UnifiedCustomerDTO { public void setUserName(String userName) { this.userName = userName; } public String getAssistant() { return assistant; } - public void setAssistant(String assistant) { this.assistant = assistant; } + public void setAssistant(String assistant) { + this.assistant = assistant; + } + + public String getNotice() { + return notice; + } + + public void setNotice(String notice) { + this.notice = notice; + } public LocalDateTime getCreated_at() { return created_at; } public void setCreated_at(LocalDateTime created_at) { this.created_at = created_at; } diff --git a/src/main/java/com/example/web/dto/UserProductCartDTO.java b/src/main/java/com/example/web/dto/UserProductCartDTO.java index baab599..7d3c195 100644 --- a/src/main/java/com/example/web/dto/UserProductCartDTO.java +++ b/src/main/java/com/example/web/dto/UserProductCartDTO.java @@ -22,6 +22,7 @@ public class UserProductCartDTO { private String spec;//规格 private LocalDateTime created_at;//创建时间 private LocalDateTime updated_at;//更新时间 + private String notice;//通知状态 private List products= new ArrayList<>();;//产品信息 private List cartItems= new ArrayList<>();;//购物车信息 private List usersContacts= new ArrayList<>();;//联系人信息 @@ -98,6 +99,14 @@ public class UserProductCartDTO { this.spec = spec; } + public String getNotice() { + return notice; + } + + public void setNotice(String notice) { + this.notice = notice; + } + public LocalDateTime getCreated_at() { return created_at; } diff --git a/src/main/java/com/example/web/entity/Users.java b/src/main/java/com/example/web/entity/Users.java index 7b66187..bfe9b9a 100644 --- a/src/main/java/com/example/web/entity/Users.java +++ b/src/main/java/com/example/web/entity/Users.java @@ -33,8 +33,9 @@ public class Users { private String demand;//客户需求 private String spec;//规格 private String followup;//跟进信息 + private String notice;//通知状态 - public Users(Integer id, String openid, String userId, String nickName, String avatarUrl, String phoneNumber, String type, Integer gender, String country, String province, String city, String language, String session_key, LocalDateTime created_at, LocalDateTime updated_at, String company, String region, String level, String demand, String spec, String followup) { + public Users(Integer id, String openid, String userId, String nickName, String avatarUrl, String phoneNumber, String type, Integer gender, String country, String province, String city, String language, String session_key, LocalDateTime created_at, LocalDateTime updated_at, String company, String region, String level, String demand, String spec, String followup, String notice) { this.id = id; this.openid = openid; this.userId = userId; @@ -56,6 +57,7 @@ public class Users { this.demand = demand; this.spec = spec; this.followup = followup; + this.notice = notice; } public Integer getId() { @@ -225,4 +227,12 @@ public class Users { public void setFollowup(String followup) { this.followup = followup; } + + public String getNotice() { + return notice; + } + + public void setNotice(String notice) { + this.notice = notice; + } } diff --git a/src/main/java/com/example/web/mapper/SupplyUsersMapper.java b/src/main/java/com/example/web/mapper/SupplyUsersMapper.java index 3289a22..2680b61 100644 --- a/src/main/java/com/example/web/mapper/SupplyUsersMapper.java +++ b/src/main/java/com/example/web/mapper/SupplyUsersMapper.java @@ -263,4 +263,8 @@ public interface SupplyUsersMapper { // 更新跟进信息 @Update("UPDATE users SET followup = #{followup} WHERE phoneNumber = #{phoneNumber}") int updateFollowUpByPhone(@Param("phoneNumber") String phoneNumber, @Param("followup") String followup); + + // 🔥 新增:更新用户通知状态 + @Update("UPDATE users SET notice = #{notice} WHERE user_id = #{userId}") + int updateNotice(@Param("userId") String userId, @Param("notice") String notice); } \ No newline at end of file diff --git a/src/main/java/com/example/web/mapper/UsersMapper.java b/src/main/java/com/example/web/mapper/UsersMapper.java index 7bf4f74..6924f2f 100644 --- a/src/main/java/com/example/web/mapper/UsersMapper.java +++ b/src/main/java/com/example/web/mapper/UsersMapper.java @@ -259,11 +259,18 @@ public interface UsersMapper { @Param("authInfo") ManagerAuthInfo authInfo); // 🔥 新增:批量查询用户联系人信息 - List getUserContactsByUserIds(@Param("userIds") List userIds); + List getUserContactsByUserIds(@Param("userIds") List userIds); // 🔥 新增:批量查询用户购物车信息 - List getCartItemsByUserIds(@Param("userIds") List userIds); + List getBuyerCartItemsByUserIds(@Param("userIds") List userIds); + + // 🔥 新增:批量查询用户购物车信息(兼容旧方法名) + List getCartItemsByUserIds(@Param("userIds") List userIds); // 🔥 新增:批量查询用户基本信息 List getUserBasicInfoByUserIds(@Param("userIds") List userIds); + + // 🔥 新增:更新用户通知状态 + @Update("UPDATE users SET notice = #{notice} WHERE user_id = #{userId}") + int updateNotice(@Param("userId") String userId, @Param("notice") String notice); } \ No newline at end of file diff --git a/src/main/java/com/example/web/service/PoolCustomerService.java b/src/main/java/com/example/web/service/PoolCustomerService.java index 441cbf7..6e43d52 100644 --- a/src/main/java/com/example/web/service/PoolCustomerService.java +++ b/src/main/java/com/example/web/service/PoolCustomerService.java @@ -172,7 +172,10 @@ public class PoolCustomerService { List authorizedUsers = usersMapper.getAuthorizedCustomers(authInfo, limit, offset); System.out.println("✅ 授权客户数据查询完成"); - System.out.println("📊 当前页获取到授权客户数据条数: " + (authorizedUsers != null ? authorizedUsers.size() : "null")); + System.out.println("📊 当前页获取到授权客户数据条数: " + (authorizedUsers != null ? authorizedUsers.size() : "null")); + // 统计通知状态为banold的用户数量 + long banoldCount = authorizedUsers != null ? authorizedUsers.stream().filter(user -> "banold".equals(user.getNotice())).count() : 0; + System.out.println("📊 通知状态为banold的用户数量: " + banoldCount); List result = new ArrayList<>(); @@ -441,6 +444,13 @@ public class PoolCustomerService { return null; } + // 2. 如果通知状态为banold,则更新为old + if ("banold".equals(userInfo.getNotice())) { + System.out.println("🔄 更新通知状态, userId: " + userId + ", 从banold改为old"); + usersMapper.updateNotice(userId, "old"); + userInfo.setNotice("old"); + } + // 销售端权限校验 if (!"buyer".equals(userInfo.getType()) && !"both".equals(userInfo.getType())) { System.out.println("🚫 过滤掉非客户端客户: " + userId + " (类型: " + userInfo.getType() + ")"); @@ -549,7 +559,10 @@ public class PoolCustomerService { List allUsers = usersMapper.getAllUserBasicInfo(); System.out.println("✅ 基础用户数据查询完成"); - System.out.println("📊 获取到基础用户数据条数: " + (allUsers != null ? allUsers.size() : "null")); + System.out.println("📊 获取到基础用户数据条数: " + (allUsers != null ? allUsers.size() : "null")); + // 统计通知状态为banold的用户数量 + long banoldCount = allUsers != null ? allUsers.stream().filter(user -> "banold".equals(user.getNotice())).count() : 0; + System.out.println("📊 通知状态为banold的用户数量: " + banoldCount); List result = new ArrayList<>(); diff --git a/src/main/java/com/example/web/service/SupplyPoolCustomerService.java b/src/main/java/com/example/web/service/SupplyPoolCustomerService.java index 0778ac4..5e66d37 100644 --- a/src/main/java/com/example/web/service/SupplyPoolCustomerService.java +++ b/src/main/java/com/example/web/service/SupplyPoolCustomerService.java @@ -173,6 +173,11 @@ public class SupplyPoolCustomerService { System.out.println("✅ 授权客户数据查询完成"); System.out.println("📊 当前页获取到授权客户数据条数: " + (authorizedUsers != null ? authorizedUsers.size() : "null")); + // 统计通知状态为banold的授权客户数量 + if (authorizedUsers != null) { + long banoldCount = authorizedUsers.stream().filter(user -> "banold".equals(user.getNotice())).count(); + System.out.println("📊 通知状态为banold的授权客户数量: " + banoldCount); + } List result = new ArrayList<>(); @@ -457,6 +462,13 @@ public class SupplyPoolCustomerService { System.out.println("🚫 过滤掉非供应端客户: " + userId + " (类型: " + userInfo.getType() + ")"); return null; // 返回null而不是抛出异常 } + + // 如果通知状态为banold,则更新为old + if ("banold".equals(userInfo.getNotice())) { + System.out.println("🔄 更新通知状态: " + userId + " 从banold改为old"); + supplyusersMapper.updateNotice(userId, "old"); + userInfo.setNotice("old"); + } // 🔥 新增:查询负责人信息 try { UsersManagements userManager = supplyUsersManagementsMapper.findByUserId(userId); @@ -563,6 +575,11 @@ public class SupplyPoolCustomerService { System.out.println("✅ 基础用户数据查询完成"); System.out.println("📊 获取到基础用户数据条数: " + (allUsers != null ? allUsers.size() : "null")); + // 统计通知状态为banold的用户数量 + if (allUsers != null) { + long banoldCount = allUsers.stream().filter(user -> "banold".equals(user.getNotice())).count(); + System.out.println("📊 通知状态为banold的用户数量: " + banoldCount); + } List result = new ArrayList<>(); diff --git a/src/main/resources/mapper/SupplyUsersMapper.xml b/src/main/resources/mapper/SupplyUsersMapper.xml index e84f58f..bee7220 100644 --- a/src/main/resources/mapper/SupplyUsersMapper.xml +++ b/src/main/resources/mapper/SupplyUsersMapper.xml @@ -25,6 +25,7 @@ + @@ -40,6 +41,7 @@ + @@ -82,7 +84,8 @@ u.demand, u.spec, u.created_at, - u.updated_at + u.updated_at, + u.notice FROM users u LEFT JOIN usermanagements um ON u.userId = um.userId WHERE u.phoneNumber IS NOT NULL @@ -190,7 +193,8 @@ u.demand, u.spec, u.created_at, - u.updated_at + u.updated_at, + u.notice FROM users u LEFT JOIN usermanagements um ON u.userId = um.userId WHERE u.phoneNumber = #{phoneNumber} @@ -230,7 +234,8 @@ demand, spec, created_at, - updated_at + updated_at, + notice FROM users WHERE userId = #{userId} @@ -267,6 +272,7 @@ level, demand, spec, + notice, created_at, updated_at FROM users @@ -289,7 +295,8 @@ demand, spec, created_at, - updated_at + updated_at, + notice FROM users WHERE phoneNumber = #{phoneNumber} AND (type = 'seller' OR type = 'both') @@ -308,7 +315,8 @@ demand, spec, created_at, - updated_at + updated_at, + notice FROM users WHERE userId = #{userId} AND (type = 'seller' OR type = 'both') @@ -612,7 +620,8 @@ demand, spec, created_at, - updated_at + updated_at, + notice FROM users WHERE userId IN diff --git a/src/main/resources/mapper/UsersMapper.xml b/src/main/resources/mapper/UsersMapper.xml index 0e567be..ec196e9 100644 --- a/src/main/resources/mapper/UsersMapper.xml +++ b/src/main/resources/mapper/UsersMapper.xml @@ -31,6 +31,7 @@ + @@ -46,6 +47,7 @@ + @@ -88,7 +90,8 @@ u.demand, u.spec, u.created_at, - u.updated_at + u.updated_at, + u.notice FROM users u LEFT JOIN usermanagements um ON u.userId = um.userId WHERE u.phoneNumber IS NOT NULL @@ -178,7 +181,8 @@ demand, spec, created_at, - updated_at + updated_at, + notice FROM users WHERE userId = #{userId} @@ -219,6 +223,7 @@ level, demand, spec, + notice, created_at, updated_at FROM users @@ -259,7 +264,8 @@ demand, spec, created_at, - updated_at + updated_at, + notice FROM users WHERE userId = #{userId} @@ -625,7 +631,8 @@ demand, spec, created_at, - updated_at + updated_at, + notice FROM users WHERE userId IN diff --git a/src/main/resources/static/loginmm.html b/src/main/resources/static/loginmm.html index 5a72bbd..1027581 100644 --- a/src/main/resources/static/loginmm.html +++ b/src/main/resources/static/loginmm.html @@ -520,7 +520,7 @@ errorElement.classList.remove('show'); } - const API_BASE_URL = 'http://8.137.125.67:8080/DL'; // 服务器API地址 + const API_BASE_URL = 'http://localhost:8081/DL'; // 服务器API地址 async function sendLoginRequest(projectName, userName, password) { try { // 使用URL编码的表单数据 diff --git a/src/main/resources/static/mainapp-sells.html b/src/main/resources/static/mainapp-sells.html index 86db328..53588f9 100644 --- a/src/main/resources/static/mainapp-sells.html +++ b/src/main/resources/static/mainapp-sells.html @@ -604,6 +604,7 @@ transition: all 0.3s ease; margin-right: 10px; color: #666; + position: relative; } .notification-btn:hover { @@ -615,6 +616,47 @@ .notification-btn i { font-size: 18px; + transition: all 0.3s ease; + } + + /* 通知铃铛激活状态样式 */ + .notification-btn.notification-active { + background-color: #fee2e2; + border-color: #fecaca; + color: #ef4444; + } + + /* 通知数量徽章样式 */ + .notification-count { + position: absolute; + top: -5px; + right: -5px; + background: #ef4444; + color: white; + font-size: 12px; + font-weight: bold; + border-radius: 50%; + min-width: 18px; + height: 18px; + display: flex; + align-items: center; + justify-content: center; + padding: 0 6px; + } + + /* 铃铛摇晃动画 */ + @keyframes ring { + 0% { transform: rotate(0deg); } + 10% { transform: rotate(15deg); } + 20% { transform: rotate(-15deg); } + 30% { transform: rotate(10deg); } + 40% { transform: rotate(-10deg); } + 50% { transform: rotate(5deg); } + 60% { transform: rotate(-5deg); } + 70% { transform: rotate(2deg); } + 80% { transform: rotate(-2deg); } + 90% { transform: rotate(1deg); } + 100% { transform: rotate(0deg); } } /* 头部操作容器样式 */ @@ -2733,6 +2775,21 @@ + + + @@ -4097,6 +4154,12 @@ const data = result.data || {}; const allPublicSeaCustomers = Array.isArray(data) ? data : Object.values(data); + // 统计notice为banold的客户数量并更新通知铃铛 + this.updateNotificationStatus(allPublicSeaCustomers); + + // 保存所有公海客户数据到缓存中,用于通知弹窗 + this.allPublicSeaCustomers = allPublicSeaCustomers; + // 对每个等级分别过滤和缓存 for (const level of levels) { const filteredCustomers = this.filterPublicSeaCustomersByLoginInfo( @@ -4326,6 +4389,50 @@ } } + // 更新通知铃铛状态 + updateNotificationStatus(customers) { + // 统计notice为banold的客户数量 + console.log('📊 更新通知状态 - 客户列表:', customers.length, '个客户'); + const banoldCount = customers.filter(customer => customer.notice === 'banold').length; + console.log('🔔 待处理通知数量:', banoldCount); + + // 更新通知铃铛样式 + const notificationButton = document.getElementById('notificationButton'); + console.log('🔘 通知按钮存在:', !!notificationButton); + if (notificationButton) { + const bellIcon = notificationButton.querySelector('i'); + if (bellIcon) { + if (banoldCount > 0) { + notificationButton.classList.add('notification-active'); + bellIcon.style.animation = 'ring 1s ease-in-out'; + + // 添加或更新通知数量显示 + let countBadge = notificationButton.querySelector('.notification-count'); + if (!countBadge) { + countBadge = document.createElement('span'); + countBadge.className = 'notification-count'; + notificationButton.appendChild(countBadge); + } + countBadge.textContent = banoldCount; + } else { + notificationButton.classList.remove('notification-active'); + bellIcon.style.animation = 'none'; + + // 移除通知数量显示 + const countBadge = notificationButton.querySelector('.notification-count'); + if (countBadge) { + countBadge.remove(); + } + } + } + + // 绑定通知点击事件 + this.bindNotificationEvents(); + } + + return banoldCount; + } + // 获取公海池数据的辅助方法 async fetchPublicSeaData(loginInfo, level) { const url = appendAuthParams(`${API_BASE_URL}/pool/all-customers`); @@ -4344,10 +4451,148 @@ const data = result.data || {}; const customersArray = Array.isArray(data) ? data : Object.values(data); + // 统计notice为banold的客户数量并更新通知铃铛 + this.updateNotificationStatus(customersArray); + // 根据登录信息过滤公海池数据 return this.filterPublicSeaCustomersByLoginInfo(customersArray, loginInfo, level); } + // 绑定通知事件 + bindNotificationEvents() { + const notificationButton = document.getElementById('notificationButton'); + const notificationModal = document.getElementById('notificationModal'); + const closeNotificationModal = document.getElementById('closeNotificationModal'); + + if (notificationButton && notificationModal && closeNotificationModal) { + // 移除现有的点击事件监听器,避免重复绑定 + notificationButton.onclick = null; + closeNotificationModal.onclick = null; + + // 点击通知按钮显示弹窗 + notificationButton.addEventListener('click', () => { + this.showNotificationModal(); + }); + + // 点击关闭按钮关闭弹窗 + closeNotificationModal.addEventListener('click', () => { + this.hideNotificationModal(); + }); + + // 点击弹窗外部关闭弹窗 + notificationModal.addEventListener('click', (e) => { + if (e.target === notificationModal) { + this.hideNotificationModal(); + } + }); + } + } + + // 显示通知弹窗 + async showNotificationModal() { + console.log('🎯 显示通知弹窗'); + const notificationModal = document.getElementById('notificationModal'); + const notificationContent = document.getElementById('notificationContent'); + + // 显示加载状态 + notificationContent.innerHTML = '

加载中...

'; + notificationModal.classList.add('active'); + + // 阻止背景滚动和操作 + document.body.style.overflow = 'hidden'; + notificationModal.style.zIndex = '1000'; // 确保弹窗在最上层 + + try { + // 先尝试从缓存获取数据 + let allCustomers = []; + if (this.allPublicSeaCustomers) { + allCustomers = this.allPublicSeaCustomers; + console.log('📋 从缓存获取客户数据:', allCustomers.length, '条'); + console.log('📋 缓存完整数据:', JSON.stringify(this.allPublicSeaCustomers)); + } else { + // 如果缓存中没有数据,直接从API获取 + const url = appendAuthParams(`${API_BASE_URL}/pool/all-customers`); + console.log('🌐 请求API地址:', url); + const response = await fetch(url); + if (!response.ok) throw new Error(`HTTP错误: ${response.status}`); + + const result = await response.json(); + console.log('📥 API完整响应:', JSON.stringify(result)); + + if (!result.success) throw new Error(result.message); + + const data = result.data || {}; + allCustomers = Array.isArray(data) ? data : Object.values(data); + console.log('🔄 转换后客户数组:', allCustomers.length, '条'); + console.log('🔄 转换后完整数据:', JSON.stringify(allCustomers)); + + // 更新缓存 + this.allPublicSeaCustomers = allCustomers; + } + + // 获取notice为banold的客户 + const banoldCustomers = allCustomers.filter(customer => customer.notice === 'banold'); + console.log('🔔 符合条件的banold客户:', banoldCustomers.length, '条'); + console.log('🔔 banold客户详情:', JSON.stringify(banoldCustomers)); + + if (banoldCustomers.length === 0) { + notificationContent.innerHTML = '

暂无通知

'; + } else { + // 生成通知内容 + let contentHTML = '
'; + banoldCustomers.forEach(customer => { + const customerName = customer.company || customer.companyName || '未知'; + contentHTML += ` +
+
+
+ +
+
+
+ ${customerName} +
+
+ 客户ID: ${customer.id} + ${customer.phoneNumber || '无电话'} +
+
+ + 该客户已满足过期条件 +
+ +
+
+
+ `; + }); + contentHTML += '
'; + notificationContent.innerHTML = contentHTML; + } + } catch (error) { + console.error('❌ 获取通知数据失败:', error); + console.error('❌ 错误详情:', error.stack); + notificationContent.innerHTML = '

加载通知失败,请稍后重试

'; + } + } + + // 隐藏通知弹窗 + hideNotificationModal() { + const notificationModal = document.getElementById('notificationModal'); + notificationModal.classList.remove('active'); + } + + + + // 恢复背景滚动 + document.body.style.overflow = 'auto'; + } + // 获取普通等级数据的辅助方法 async fetchNormalLevelData(loginInfo, level) { const url = appendAuthParams(`${API_BASE_URL}/pool/customers`); @@ -4365,6 +4610,9 @@ const dataMap = result.data || {}; let allCustomers = Object.values(dataMap); + + // 统计notice为banold的客户数量并更新通知铃铛 + this.updateNotificationStatus(allCustomers); // 根据登录信息和等级过滤数据 allCustomers = this.filterCustomersByLoginInfo(allCustomers, loginInfo, level); @@ -11418,7 +11666,7 @@ // 移除未定义变量的console日志 // console.log('查看客户详情参数:', { customerId, phoneNumber, isCompanyId }); // 优化的客户详情查看功能 - async function viewCustomerDetails(customerId, phoneNumber, targetCartItemId = null) { + async function viewCustomerDetails(customerId, phoneNumber, targetCartItemId = null, fromNotification = false) { // 重置客户数据状态 resetCustomerDataState(); @@ -11440,6 +11688,40 @@ showNotification('未找到客户信息,请检查客户是否存在或数据是否加载完成', 'error'); return; } + + // 如果是从通知弹窗点击进入,更新notice状态为old + if (fromNotification) { + console.log('📋 从通知弹窗查看客户详情,更新notice状态为old'); + // 发送请求更新notice状态 + fetch(`/pool/customers/${customerId}/notice`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ notice: 'old' }) + }) + .then(response => response.json()) + .then(data => { + console.log('✅ 更新客户通知状态成功,响应:', data); + // 从通知列表中移除对应的通知项 + const notificationItems = document.querySelectorAll('.notification-item'); + notificationItems.forEach(item => { + const customerIdElement = item.querySelector('.customer-id'); + if (customerIdElement && customerIdElement.textContent.includes(customerId)) { + item.remove(); + } + }); + // 检查是否还有通知项 + const remainingItems = document.querySelectorAll('.notification-item'); + if (remainingItems.length === 0) { + const notificationContent = document.getElementById('notificationContent'); + notificationContent.innerHTML = '

暂无通知

'; + } + }) + .catch(error => { + console.error('❌ 更新客户通知状态失败:', error); + }); + } // 处理客户数据 const { customer, dataSource, apiUsed } = customerData; @@ -13942,6 +14224,45 @@ } } }); + // 更新客户通知状态的全局函数 + function updateCustomerNotice(customerId, notificationItem) { + console.log('⚙️ 处理客户通知状态更新,客户ID:', customerId); + // 发送请求到后端更新客户的notice状态 + fetch(`/pool/customers/${customerId}/notice`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ notice: 'old' }) + }) + .then(response => response.json()) + .then(data => { + console.log('✅ 更新客户通知状态成功,响应:', data); + if (data.success) { + // 从通知列表中移除该项 + if (notificationItem && notificationItem.parentNode) { + notificationItem.remove(); + } + + // 更新通知铃铛状态 + const notificationContent = document.getElementById('notificationContent'); + const remainingNotifications = notificationContent.querySelectorAll('.notification-item').length; + + if (remainingNotifications === 0) { + notificationContent.innerHTML = '

暂无通知

'; + } + + // 重新获取数据并更新通知铃铛 + if (typeof CustomerDataCache !== 'undefined') { + CustomerDataCache.refreshPublicSeaLevels(); + } + } + }) + .catch(error => { + console.error('❌ 更新客户通知状态失败:', error); + }); + } + // 确保数据缓存系统在页面加载时正确初始化 document.addEventListener('DOMContentLoaded', async function() { console.log('🚀 初始化客户数据系统'); @@ -14047,7 +14368,135 @@ }); // 绑定行点击事件的功能已在setupEnhancedEventDelegation中实现 - + + // 添加通知弹窗样式 + const style = document.createElement('style'); + style.textContent = ` + /* 通知弹窗样式 */ + .notification-list { + display: flex; + flex-direction: column; + gap: 16px; + padding: 16px; + } + + .notification-item { + background: #ffffff; + border: 1px solid #e8e8e8; + border-radius: 8px; + padding: 16px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + transition: all 0.3s ease; + } + + .notification-item:hover { + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15); + transform: translateY(-2px); + } + + .notification-header { + display: flex; + align-items: flex-start; + gap: 12px; + } + + .notification-icon { + display: flex; + align-items: center; + justify-content: center; + width: 40px; + height: 40px; + background: #fff7e6; + border-radius: 50%; + flex-shrink: 0; + } + + .notification-content { + flex: 1; + } + + .notification-title { + font-size: 16px; + font-weight: 600; + margin-bottom: 8px; + transition: color 0.3s ease; + } + + .notification-title:hover { + color: #40a9ff !important; + text-decoration: underline; + } + + .notification-meta { + display: flex; + gap: 16px; + margin-bottom: 8px; + font-size: 14px; + color: #666666; + } + + .notification-message { + font-size: 14px; + color: #ff7875; + margin-bottom: 12px; + display: flex; + align-items: center; + } + + .notification-footer { + display: flex; + justify-content: space-between; + align-items: center; + font-size: 12px; + color: #999999; + } + + .notification-time { + white-space: nowrap; + } + + .notification-action-btn { + padding: 6px 16px; + background: #1890ff; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; + font-size: 12px; + transition: all 0.3s ease; + } + + .notification-action-btn:hover { + background: #40a9ff; + transform: translateY(-1px); + } + + .notification-empty { + display: flex; + align-items: center; + justify-content: center; + padding: 48px 24px; + color: #999999; + background: #fafafa; + border-radius: 8px; + font-size: 14px; + } + + /* 适配不同屏幕尺寸 */ + @media (max-width: 768px) { + .notification-meta { + flex-direction: column; + gap: 4px; + } + + .notification-footer { + flex-direction: column; + gap: 8px; + align-items: flex-start; + } + } + `; + document.head.appendChild(style); diff --git a/src/main/resources/static/mainapp-supplys.html b/src/main/resources/static/mainapp-supplys.html index 9f3d38c..8289f84 100644 --- a/src/main/resources/static/mainapp-supplys.html +++ b/src/main/resources/static/mainapp-supplys.html @@ -604,6 +604,7 @@ transition: all 0.3s ease; margin-right: 10px; color: #666; + position: relative; } .notification-btn:hover { @@ -615,6 +616,47 @@ .notification-btn i { font-size: 18px; + transition: all 0.3s ease; + } + + /* 通知铃铛激活状态样式 */ + .notification-btn.notification-active { + background-color: #fee2e2; + border-color: #fecaca; + color: #ef4444; + } + + /* 通知数量徽章样式 */ + .notification-count { + position: absolute; + top: -5px; + right: -5px; + background: #ef4444; + color: white; + font-size: 12px; + font-weight: bold; + border-radius: 50%; + min-width: 18px; + height: 18px; + display: flex; + align-items: center; + justify-content: center; + padding: 0 6px; + } + + /* 铃铛摇晃动画 */ + @keyframes ring { + 0% { transform: rotate(0deg); } + 10% { transform: rotate(15deg); } + 20% { transform: rotate(-15deg); } + 30% { transform: rotate(10deg); } + 40% { transform: rotate(-10deg); } + 50% { transform: rotate(5deg); } + 60% { transform: rotate(-5deg); } + 70% { transform: rotate(2deg); } + 80% { transform: rotate(-2deg); } + 90% { transform: rotate(1deg); } + 100% { transform: rotate(0deg); } } /* 头部操作容器样式 */ @@ -2733,6 +2775,21 @@ + + + @@ -4097,6 +4154,12 @@ const data = result.data || {}; const allPublicSeaCustomers = Array.isArray(data) ? data : Object.values(data); + // 统计notice为banold的客户数量并更新通知铃铛 + this.updateNotificationStatus(allPublicSeaCustomers); + + // 保存所有公海客户数据到缓存中,用于通知弹窗 + this.allPublicSeaCustomers = allPublicSeaCustomers; + // 对每个等级分别过滤和缓存 for (const level of levels) { const filteredCustomers = this.filterPublicSeaCustomersByLoginInfo( @@ -4315,8 +4378,52 @@ } // 获取公海池数据的辅助方法 + // 更新通知铃铛状态 + updateNotificationStatus(customers) { + // 统计notice为banold的客户数量 + console.log('📊 更新通知状态 - 客户列表:', customers.length, '个客户'); + const banoldCount = customers.filter(customer => customer.notice === 'banold').length; + console.log('🔔 待处理通知数量:', banoldCount); + + // 更新通知铃铛样式 + const notificationButton = document.getElementById('notificationButton'); + console.log('🔘 通知按钮存在:', !!notificationButton); + if (notificationButton) { + const bellIcon = notificationButton.querySelector('i'); + if (bellIcon) { + if (banoldCount > 0) { + notificationButton.classList.add('notification-active'); + bellIcon.style.animation = 'ring 1s ease-in-out'; + + // 添加或更新通知数量显示 + let countBadge = notificationButton.querySelector('.notification-count'); + if (!countBadge) { + countBadge = document.createElement('span'); + countBadge.className = 'notification-count'; + notificationButton.appendChild(countBadge); + } + countBadge.textContent = banoldCount; + } else { + notificationButton.classList.remove('notification-active'); + bellIcon.style.animation = 'none'; + + // 移除通知数量显示 + const countBadge = notificationButton.querySelector('.notification-count'); + if (countBadge) { + countBadge.remove(); + } + } + } + + // 绑定通知点击事件 + this.bindNotificationEvents(); + } + + return banoldCount; + } + async fetchPublicSeaData(loginInfo, level) { - const url = appendAuthParams(`${API_BASE_URL}/pool/all-customers`); + const url = appendAuthParams(`${API_BASE_URL}/supply/pool/all-customers`); const response = await fetch(url, { headers: { 'Content-Type': 'application/json', @@ -4332,10 +4439,147 @@ const data = result.data || {}; const customersArray = Array.isArray(data) ? data : Object.values(data); + // 统计notice为banold的客户数量并更新通知铃铛 + this.updateNotificationStatus(customersArray); + // 根据登录信息过滤公海池数据 return this.filterPublicSeaCustomersByLoginInfo(customersArray, loginInfo, level); } + // 绑定通知事件 + bindNotificationEvents() { + const notificationButton = document.getElementById('notificationButton'); + const notificationModal = document.getElementById('notificationModal'); + const closeNotificationModal = document.getElementById('closeNotificationModal'); + + if (notificationButton && notificationModal && closeNotificationModal) { + // 移除现有的点击事件监听器,避免重复绑定 + notificationButton.onclick = null; + closeNotificationModal.onclick = null; + + // 点击通知按钮显示弹窗 + notificationButton.addEventListener('click', () => { + this.showNotificationModal(); + }); + + // 点击关闭按钮关闭弹窗 + closeNotificationModal.addEventListener('click', () => { + this.hideNotificationModal(); + }); + + // 点击弹窗外部关闭弹窗 + notificationModal.addEventListener('click', (e) => { + if (e.target === notificationModal) { + this.hideNotificationModal(); + } + }); + } + } + + // 显示通知弹窗 + async showNotificationModal() { + console.log('🎯 显示通知弹窗'); + const notificationModal = document.getElementById('notificationModal'); + const notificationContent = document.getElementById('notificationContent'); + + // 显示加载状态 + notificationContent.innerHTML = '

加载中...

'; + notificationModal.classList.add('active'); + + // 阻止背景滚动和操作 + document.body.style.overflow = 'hidden'; + notificationModal.style.zIndex = '1000'; // 确保弹窗在最上层 + + try { + // 先尝试从缓存获取数据 + let allCustomers = []; + if (this.allPublicSeaCustomers) { + allCustomers = this.allPublicSeaCustomers; + console.log('📋 从缓存获取客户数据:', allCustomers.length, '条'); + console.log('📋 缓存完整数据:', JSON.stringify(this.allPublicSeaCustomers)); + } else { + // 如果缓存中没有数据,直接从API获取 + const url = appendAuthParams(`${API_BASE_URL}/supply/pool/all-customers`); + console.log('🌐 请求API地址:', url); + const response = await fetch(url); + if (!response.ok) throw new Error(`HTTP错误: ${response.status}`); + + const result = await response.json(); + console.log('📥 API完整响应:', JSON.stringify(result)); + + if (!result.success) throw new Error(result.message); + + const data = result.data || {}; + allCustomers = Array.isArray(data) ? data : Object.values(data); + console.log('🔄 转换后客户数组:', allCustomers.length, '条'); + console.log('🔄 转换后完整数据:', JSON.stringify(allCustomers)); + + // 更新缓存 + this.allPublicSeaCustomers = allCustomers; + } + + // 获取notice为banold的客户 + const banoldCustomers = allCustomers.filter(customer => customer.notice === 'banold'); + console.log('🔔 符合条件的banold客户:', banoldCustomers.length, '条'); + console.log('🔔 banold客户详情:', JSON.stringify(banoldCustomers)); + + if (banoldCustomers.length === 0) { + notificationContent.innerHTML = '

暂无通知

'; + } else { + // 生成通知内容 + let contentHTML = '
'; + banoldCustomers.forEach(customer => { + const customerName = customer.company || customer.companyName || '未知'; + contentHTML += ` +
+
+
+ +
+
+
+ ${customerName} +
+
+ 客户ID: ${customer.id} + ${customer.phoneNumber || '无电话'} +
+
+ + 该客户已满足过期条件 +
+ +
+
+
+ `; + }); + contentHTML += '
'; + notificationContent.innerHTML = contentHTML; + } + } catch (error) { + console.error('❌ 获取通知数据失败:', error); + console.error('❌ 错误详情:', error.stack); + notificationContent.innerHTML = '

加载通知失败,请稍后重试

'; + } + } + + // 隐藏通知弹窗 + hideNotificationModal() { + const notificationModal = document.getElementById('notificationModal'); + notificationModal.classList.remove('active'); + + // 恢复背景滚动 + document.body.style.overflow = 'auto'; + } + + + // 获取普通等级数据的辅助方法 async fetchNormalLevelData(loginInfo, level) { const url = appendAuthParams(`${API_BASE_URL}/pool/customers`); @@ -4354,6 +4598,9 @@ const dataMap = result.data || {}; let allCustomers = Object.values(dataMap); + // 统计notice为banold的客户数量并更新通知铃铛 + this.updateNotificationStatus(allCustomers); + // 根据登录信息和等级过滤数据 allCustomers = this.filterCustomersByLoginInfo(allCustomers, loginInfo, level); @@ -11247,7 +11494,7 @@ // 移除未定义变量的console日志 // console.log('查看客户详情参数:', { customerId, phoneNumber, isCompanyId }); // 优化的客户详情查看功能 - async function viewCustomerDetails(customerId, phoneNumber, targetProductItemId = null) { + async function viewCustomerDetails(customerId, phoneNumber, targetProductItemId = null, fromNotification = false) { // 重置客户数据状态 resetCustomerDataState(); @@ -11269,6 +11516,40 @@ showNotification('未找到客户信息,请检查客户是否存在或数据是否加载完成', 'error'); return; } + + // 如果是从通知弹窗点击进入,更新notice状态为old + if (fromNotification) { + console.log('📋 从通知弹窗查看客户详情,更新notice状态为old'); + // 发送请求更新notice状态 + fetch(`/pool/customers/${customerId}/notice`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ notice: 'old' }) + }) + .then(response => response.json()) + .then(data => { + console.log('✅ 更新客户通知状态成功,响应:', data); + // 从通知列表中移除对应的通知项 + const notificationItems = document.querySelectorAll('.notification-item'); + notificationItems.forEach(item => { + const customerIdElement = item.querySelector('.customer-id'); + if (customerIdElement && customerIdElement.textContent.includes(customerId)) { + item.remove(); + } + }); + // 检查是否还有通知项 + const remainingItems = document.querySelectorAll('.notification-item'); + if (remainingItems.length === 0) { + const notificationContent = document.getElementById('notificationContent'); + notificationContent.innerHTML = '

暂无通知

'; + } + }) + .catch(error => { + console.error('❌ 更新客户通知状态失败:', error); + }); + } // 处理客户数据 const { customer, dataSource, apiUsed } = customerData; @@ -13905,7 +14186,174 @@ }); // 绑定行点击事件的功能已在setupEnhancedEventDelegation中实现 - + + // 更新客户通知状态的全局函数 + function updateCustomerNotice(customerId, notificationItem) { + console.log('⚙️ 处理客户通知状态更新,客户ID:', customerId); + // 发送请求到后端更新客户的notice状态 + fetch(`/supply/pool/customers/${customerId}/notice`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ notice: 'old' }) + }) + .then(response => response.json()) + .then(data => { + console.log('✅ 更新客户通知状态成功,响应:', data); + if (data.success) { + // 从通知列表中移除该项 + if (notificationItem && notificationItem.parentNode) { + notificationItem.remove(); + } + + // 更新通知铃铛状态 + const notificationContent = document.getElementById('notificationContent'); + const remainingNotifications = notificationContent.querySelectorAll('.notification-item').length; + + if (remainingNotifications === 0) { + notificationContent.innerHTML = '

暂无通知

'; + } + + // 重新获取数据并更新通知铃铛 + if (typeof CustomerDataCache !== 'undefined') { + CustomerDataCache.refreshPublicSeaLevels(); + } + } + }) + .catch(error => { + console.error('❌ 更新客户通知状态失败:', error); + }); + } + + // 添加通知弹窗样式 + const style = document.createElement('style'); + style.textContent = ` + /* 通知弹窗样式 */ + .notification-list { + display: flex; + flex-direction: column; + gap: 16px; + padding: 16px; + } + + .notification-item { + background: #ffffff; + border: 1px solid #e8e8e8; + border-radius: 8px; + padding: 16px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + transition: all 0.3s ease; + } + + .notification-item:hover { + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15); + transform: translateY(-2px); + } + + .notification-header { + display: flex; + align-items: flex-start; + gap: 12px; + } + + .notification-icon { + display: flex; + align-items: center; + justify-content: center; + width: 40px; + height: 40px; + background: #fff7e6; + border-radius: 50%; + flex-shrink: 0; + } + + .notification-content { + flex: 1; + } + + .notification-title { + font-size: 16px; + font-weight: 600; + margin-bottom: 8px; + transition: color 0.3s ease; + } + + .notification-title:hover { + color: #40a9ff !important; + text-decoration: underline; + } + + .notification-meta { + display: flex; + gap: 16px; + margin-bottom: 8px; + font-size: 14px; + color: #666666; + } + + .notification-message { + font-size: 14px; + color: #ff7875; + margin-bottom: 12px; + display: flex; + align-items: center; + } + + .notification-footer { + display: flex; + justify-content: space-between; + align-items: center; + font-size: 12px; + color: #999999; + } + + .notification-time { + white-space: nowrap; + } + + .notification-action-btn { + padding: 6px 16px; + background: #1890ff; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; + font-size: 12px; + transition: all 0.3s ease; + } + + .notification-action-btn:hover { + background: #40a9ff; + transform: translateY(-1px); + } + + .notification-empty { + display: flex; + align-items: center; + justify-content: center; + padding: 48px 24px; + color: #999999; + background: #fafafa; + border-radius: 8px; + font-size: 14px; + } + + /* 适配不同屏幕尺寸 */ + @media (max-width: 768px) { + .notification-meta { + flex-direction: column; + gap: 4px; + } + + .notification-footer { + flex-direction: column; + gap: 8px; + align-items: flex-start; + } + } + `; + document.head.appendChild(style);