index.vue 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. <template>
  2. <div class="loading-page" role="status" aria-live="polite" aria-label="页面加载中">
  3. <!-- 顶部导航 -->
  4. <van-nav-bar title="加载中" fixed :border="false" safe-area-inset-top class="nav" />
  5. <!-- 中心区域(带淡淡的高光背景,不是卡片) -->
  6. <div class="loading-body">
  7. <div>
  8. <van-loading type="circular" vertical :size="loadingSize" :color="loadingColor">
  9. 加载中…
  10. </van-loading>
  11. </div>
  12. </div>
  13. <!-- 低证等级弹窗 -->
  14. <van-dialog
  15. v-model:show="lowCertLevelDialog"
  16. title="税局账号安全等级升级提醒"
  17. confirmButtonText="我知道啦"
  18. @confirm="lowCertLevelConfirm"
  19. >
  20. <div class="dialog-content">
  21. <div class="dialog-text">
  22. 抱歉,您在电子税务局的账号安全等级较低,无法确认开票申请,请登录至电子税务局提升账号安全等级。
  23. </div>
  24. <div class="dialog-btn" @click="handleSecurityLevelGuideClick">
  25. 点击了解提升安全等级操作指引
  26. </div>
  27. </div>
  28. </van-dialog>
  29. <!-- 安全等级操作指引 -->
  30. <van-dialog
  31. v-model:show="securityLevelGuideDialog"
  32. width="90%"
  33. :closeOnClickOverlay="true"
  34. className="security-level-guide-dialog"
  35. @confirm="securityLevelGuideDialog = false"
  36. >
  37. <div class="security-level-guide-body">
  38. <img
  39. src="@/assets/images/securityLevelGuide.png"
  40. alt="安全等级升级指引"
  41. class="guide-image"
  42. />
  43. </div>
  44. </van-dialog>
  45. </div>
  46. </template>
  47. <script setup lang="ts">
  48. import { getFaceAuthResultApi } from '@/services/modules/faceRecognition'
  49. import type { PushRecordIdRequest } from '@/services/modules/invoiceInformation/type.d.ts'
  50. import { ref, reactive, onMounted } from 'vue'
  51. import { useUserStore } from '@/stores/modules/user'
  52. import { showToast } from 'vant'
  53. import { useInvoice } from '@/hooks/useInvoice'
  54. import { useRouter } from 'vue-router'
  55. const userStore = useUserStore()
  56. const router = useRouter()
  57. // --- 初始化 Hooks ---
  58. const { submitInvoiceApply } = useInvoice()
  59. const loadingSize = '10vw'
  60. const loadingColor = '#1677ff'
  61. const params = reactive<PushRecordIdRequest>({
  62. pushRecordId: userStore.pushRecordId,
  63. })
  64. const lowCertLevelDialog = ref(false)
  65. // 获取认证结果
  66. const getFaceAuthResult = async () => {
  67. try {
  68. const res = await getFaceAuthResultApi(params)
  69. if (res.code === 0 && res.data.lowCertLevel) {
  70. lowCertLevelDialog.value = true
  71. return
  72. }
  73. if (res.code === 0 && res.data?.success) {
  74. const rzzt = res.data.rzzt
  75. // 已认证或无需认证提交跳转
  76. if (rzzt === 'NO_REQUIRED_AUTHENTICATION') {
  77. submitInvoiceApply()
  78. return
  79. }
  80. } else {
  81. showToast('扫脸认证失败,请重试')
  82. }
  83. } catch (err) {
  84. console.error('获取认证结果失败', err)
  85. showToast('网络错误,请稍后重试')
  86. }
  87. setTimeout(() => {
  88. router.replace({
  89. path: '/invoice-information',
  90. })
  91. }, 1800)
  92. }
  93. const lowCertLevelConfirm = () => {
  94. router.back()
  95. }
  96. const securityLevelGuideDialog = ref(false)
  97. const handleSecurityLevelGuideClick = () => {
  98. securityLevelGuideDialog.value = true
  99. }
  100. onMounted(() => {
  101. getFaceAuthResult()
  102. })
  103. </script>
  104. <style scoped>
  105. /* 基于 375 设计稿的 vw 适配 */
  106. html {
  107. font-size: calc(100vw / 3.75);
  108. }
  109. .loading-page {
  110. width: 100vw;
  111. height: 100vh;
  112. background: #f6f7fb; /* 整页浅灰底,非卡片 */
  113. display: flex;
  114. flex-direction: column;
  115. overflow: hidden;
  116. }
  117. /* 顶部导航固定 */
  118. .nav {
  119. position: fixed;
  120. top: 0;
  121. width: 100vw;
  122. }
  123. /* 居中容器 */
  124. .loading-body {
  125. flex: 1;
  126. display: flex;
  127. align-items: center;
  128. justify-content: center;
  129. padding-top: 14vw; /* 预留固定导航空间 */
  130. }
  131. .dialog-content {
  132. padding: 12px;
  133. .dialog-text {
  134. font-size: 14px;
  135. line-height: 22px;
  136. color: #333;
  137. font-weight: 400;
  138. }
  139. .dialog-btn {
  140. text-align: center;
  141. font-weight: 600;
  142. margin: 18px 0;
  143. color: #0072f8;
  144. }
  145. }
  146. :deep(.security-level-guide-dialog) {
  147. top: 50%;
  148. height: 90vh;
  149. .security-level-guide-body {
  150. height: 80vh;
  151. overflow-y: auto;
  152. -webkit-overflow-scrolling: touch;
  153. padding: 12px;
  154. .guide-image {
  155. width: 100%;
  156. height: auto;
  157. display: block;
  158. }
  159. }
  160. }
  161. </style>