From 825a575deb96cce822468bb9d9ac3e4eea0f91d1 Mon Sep 17 00:00:00 2001
From: liujie <1793218484@qq.com>
Date: 星期四, 17 九月 2026 08:58:14 +0800
Subject: [PATCH] update

---
 backend/src/main/java/com/tourguide/modules/user/service/GuideApplicationService.java     |    6 ++
 backend/src/test/java/com/tourguide/modules/user/service/GuideUserServiceProfileTest.java |   28 ++++++++++++++
 frontend/src/views/DashboardView.vue                                                      |    4 +-
 backend/src/main/java/com/tourguide/modules/user/mapper/GuideUserMapper.java              |   12 +++++
 backend/src/main/java/com/tourguide/modules/user/service/GuideUserService.java            |   14 ++++++
 5 files changed, 59 insertions(+), 5 deletions(-)

diff --git a/backend/src/main/java/com/tourguide/modules/user/mapper/GuideUserMapper.java b/backend/src/main/java/com/tourguide/modules/user/mapper/GuideUserMapper.java
index 7950712..e3f2cb2 100644
--- a/backend/src/main/java/com/tourguide/modules/user/mapper/GuideUserMapper.java
+++ b/backend/src/main/java/com/tourguide/modules/user/mapper/GuideUserMapper.java
@@ -21,10 +21,20 @@
     int anonymizeCancelledGuide(@Param("guideId") Long guideId, @Param("username") String username);
 
     @Update("UPDATE guide_user SET id_card_no = NULL, id_card_front_url = NULL, " +
-            "id_card_back_url = NULL, updated_at = NOW() " +
+            "id_card_back_url = NULL, certificate_no = NULL, updated_at = NOW() " +
             "WHERE id_card_no = #{idCardNo} AND status = 3 AND deleted = 0")
     int clearCancelledIdentityByIdCard(@Param("idCardNo") String idCardNo);
 
+    @Update("UPDATE guide_user SET id_card_no = NULL, id_card_front_url = NULL, " +
+            "id_card_back_url = NULL, certificate_no = NULL, updated_at = NOW() " +
+            "WHERE id = #{guideId} AND status = 2 AND deleted = 0")
+    int releasePendingIdentity(@Param("guideId") Long guideId);
+
+    @Update("UPDATE guide_user SET id_card_no = NULL, id_card_front_url = NULL, " +
+            "id_card_back_url = NULL, certificate_no = NULL, updated_at = NOW() " +
+            "WHERE id_card_no = #{idCardNo} AND status = 2 AND deleted = 0")
+    int clearPendingIdentityByIdCard(@Param("idCardNo") String idCardNo);
+
     @Select("SELECT * FROM guide_user WHERE id = #{guideId} AND deleted = 0 FOR UPDATE")
     GuideUser selectForUpdate(@Param("guideId") Long guideId);
 
diff --git a/backend/src/main/java/com/tourguide/modules/user/service/GuideApplicationService.java b/backend/src/main/java/com/tourguide/modules/user/service/GuideApplicationService.java
index 7e6a06d..b1035ed 100644
--- a/backend/src/main/java/com/tourguide/modules/user/service/GuideApplicationService.java
+++ b/backend/src/main/java/com/tourguide/modules/user/service/GuideApplicationService.java
@@ -86,7 +86,11 @@
         if (application.getAuditStatus() == null || application.getAuditStatus() != PENDING) {
             throw new BusinessException(409, "该申请已审核,请勿重复操作");
         }
-        if (auditStatus == APPROVED) guideUserService.createFromApprovedApplication(application);
+        if (auditStatus == APPROVED) {
+            guideUserService.createFromApprovedApplication(application);
+        } else if (auditStatus == REJECTED) {
+            guideUserService.releaseIdentityForRejectedApplication(application.getMobile());
+        }
         LambdaUpdateWrapper<GuideApplication> update = new LambdaUpdateWrapper<GuideApplication>()
                 .eq(GuideApplication::getId, id)
                 .eq(GuideApplication::getAuditStatus, PENDING)
diff --git a/backend/src/main/java/com/tourguide/modules/user/service/GuideUserService.java b/backend/src/main/java/com/tourguide/modules/user/service/GuideUserService.java
index 6fb2478..205c7d4 100644
--- a/backend/src/main/java/com/tourguide/modules/user/service/GuideUserService.java
+++ b/backend/src/main/java/com/tourguide/modules/user/service/GuideUserService.java
@@ -338,8 +338,11 @@
 
     private void ensureUniqueGuideIdentity(GuideApplication application, GuideUser existingUser) {
         if (StringUtils.hasText(application.getIdCardNo())) {
+            String idCardNo = application.getIdCardNo().trim().toUpperCase();
             // 兼容旧注销数据:释放已注销账号占用的身份证唯一索引。
-            userMapper.clearCancelledIdentityByIdCard(application.getIdCardNo().trim().toUpperCase());
+            userMapper.clearCancelledIdentityByIdCard(idCardNo);
+            // 兼容旧驳回数据:释放待审核账号占用的身份证唯一索引,避免其阻塞重新注册。
+            userMapper.clearPendingIdentityByIdCard(idCardNo);
         }
         if (StringUtils.hasText(application.getCertificateNo())
                 && userMapper.selectCount(new LambdaQueryWrapper<GuideUser>()
@@ -359,6 +362,15 @@
         }
     }
 
+    /** 申请被驳回后释放待审核账号占用的身份证/导游证唯一索引,避免其阻塞重新注册。 */
+    public void releaseIdentityForRejectedApplication(String mobile) {
+        if (!StringUtils.hasText(mobile)) return;
+        GuideUser user = findByPhone(mobile);
+        if (user != null && Integer.valueOf(STATUS_PENDING).equals(user.getStatus())) {
+            userMapper.releasePendingIdentity(user.getId());
+        }
+    }
+
     private void copyApplicationProfile(GuideUser user, GuideApplication application) {
         user.setRealName(application.getRealName());
         user.setMobile(application.getMobile());
diff --git a/backend/src/test/java/com/tourguide/modules/user/service/GuideUserServiceProfileTest.java b/backend/src/test/java/com/tourguide/modules/user/service/GuideUserServiceProfileTest.java
index e494fef..a185f79 100644
--- a/backend/src/test/java/com/tourguide/modules/user/service/GuideUserServiceProfileTest.java
+++ b/backend/src/test/java/com/tourguide/modules/user/service/GuideUserServiceProfileTest.java
@@ -144,6 +144,34 @@
     }
 
     @Test
+    void shouldReleaseIdentityFromStalePendingGuideBeforeNewRegistration() {
+        GuideApplication application = new GuideApplication();
+        application.setMobile("13900139000");
+        application.setRealName("新导游");
+        application.setIdCardNo("11010519491231002X");
+        when(userMapper.selectOne(any())).thenReturn(null);
+
+        service.createPendingFromApplication(application);
+
+        verify(userMapper).clearCancelledIdentityByIdCard("11010519491231002X");
+        verify(userMapper).clearPendingIdentityByIdCard("11010519491231002X");
+        verify(userMapper).insert(any(GuideUser.class));
+    }
+
+    @Test
+    void shouldReleasePendingIdentityWhenRejectingApplication() {
+        GuideUser pendingGuide = new GuideUser();
+        pendingGuide.setId(12L);
+        pendingGuide.setStatus(GuideUserService.STATUS_PENDING);
+        pendingGuide.setMobile("13800138000");
+        when(userMapper.selectOne(any())).thenReturn(pendingGuide);
+
+        service.releaseIdentityForRejectedApplication("13800138000");
+
+        verify(userMapper).releasePendingIdentity(12L);
+    }
+
+    @Test
     void shouldTreatOneYearOrLessAsZeroWorkYears() {
         GuideApplication application = new GuideApplication();
         application.setMobile("13800138000");
diff --git a/frontend/src/views/DashboardView.vue b/frontend/src/views/DashboardView.vue
index f5d1ec7..0f55022 100644
--- a/frontend/src/views/DashboardView.vue
+++ b/frontend/src/views/DashboardView.vue
@@ -115,7 +115,7 @@
           <el-button link type="primary" @click="router.push('/finance/details')">查看更多</el-button>
         </div>
         <div class="line-chart">
-          <svg viewBox="0 0 680 225" preserveAspectRatio="none" role="img" aria-label="近7日平台收益趋势">
+          <svg viewBox="0 0 680 225" preserveAspectRatio="xMidYMid meet" role="img" aria-label="近7日平台收益趋势">
             <defs>
               <linearGradient id="revenueArea" x1="0" y1="0" x2="0" y2="1">
                 <stop offset="0%" stop-color="#5eb8ff" stop-opacity=".38" />
@@ -222,7 +222,7 @@
 .chart-heading div { display: flex; align-items: center; gap: 8px; }
 .chart-heading strong, .section-heading h2, .quick-panel h2 { margin: 0; color: #232932; font-size: 14px; }
 .chart-heading span { color: #8491a3; font-size: 11px; }
-.line-chart { height: 190px; }
+.line-chart { aspect-ratio: 680 / 225; }
 .line-chart svg { display: block; width: 100%; height: 100%; overflow: visible; }
 .grid-line { stroke: #e8eef5; stroke-width: 1; stroke-dasharray: 3 3; }
 .axis-label { fill: #8491a3; font-size: 10px; }

--
Gitblit v1.7.1