Browse Source

新增错误处理

yuanmingze 3 months ago
parent
commit
13d84539d6

+ 2 - 0
components.d.ts

@@ -11,6 +11,7 @@ export {}
 /* prettier-ignore */
 declare module 'vue' {
   export interface GlobalComponents {
+    ModernDialog: typeof import('./src/components/ModernDialog.vue')['default']
     RouterLink: typeof import('vue-router')['RouterLink']
     RouterView: typeof import('vue-router')['RouterView']
     StepProgress: typeof import('./src/components/StepProgress.vue')['default']
@@ -21,6 +22,7 @@ declare module 'vue' {
     VanField: typeof import('vant/es')['Field']
     VanIcon: typeof import('vant/es')['Icon']
     VanNavBar: typeof import('vant/es')['NavBar']
+    VanOverlay: typeof import('vant/es')['Overlay']
     VanUploader: typeof import('vant/es')['Uploader']
   }
 }

BIN
dist.zip


+ 1 - 1
index.html

@@ -7,7 +7,7 @@
       name="viewport"
       content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no"
     />
-    <title>Vite App</title>
+    <title>自然人开票</title>
   </head>
   <body>
     <div id="app"></div>

+ 128 - 0
src/components/ModernDialog.vue

@@ -0,0 +1,128 @@
+<template>
+  <van-overlay :show="show" class="custom-overlay" @click="handleClose" />
+
+  <transition name="dialog-pop">
+    <div v-if="show" class="modern-dialog">
+      <div class="dialog-content">
+        <div class="dialog-title">{{ title }}</div>
+        <div class="dialog-message">{{ message }}</div>
+
+        <van-button
+          type="primary"
+          block
+          round
+          class="dialog-btn"
+          color="linear-gradient(90deg, #ff7a00, #ffa94d)"
+          @click="handleConfirm"
+        >
+          {{ confirmText }}
+        </van-button>
+      </div>
+    </div>
+  </transition>
+</template>
+
+<script setup lang="ts">
+import { defineProps, defineEmits } from 'vue'
+
+const props = defineProps({
+  show: { type: Boolean, required: true },
+  title: { type: String, default: '提示' },
+  message: { type: String, default: '' },
+  confirmText: { type: String, default: '确定' },
+  closeOnClickOverlay: { type: Boolean, default: true },
+})
+
+const emit = defineEmits(['update:show', 'confirm', 'close'])
+
+const handleConfirm = () => {
+  emit('confirm') // 让父组件自己处理逻辑
+}
+
+const handleClose = () => {
+  if (props.closeOnClickOverlay) emit('update:show', false)
+  emit('close')
+}
+</script>
+
+<style scoped lang="scss">
+.custom-overlay {
+  backdrop-filter: blur(8px);
+  background: rgba(0, 0, 0, 0.25);
+  z-index: 9998;
+  animation: fadeIn 0.3s ease;
+}
+
+.modern-dialog {
+  position: fixed;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  z-index: 9999;
+  width: 80vw;
+  border-radius: 5vw;
+  background: #fff;
+  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.15);
+  text-align: center;
+  animation: dialogPop 0.28s ease-out;
+  box-sizing: border-box;
+
+  .dialog-content {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    padding: 6vw 5vw 5vw;
+    gap: 5vw;
+  }
+
+  .dialog-title {
+    font-size: 4.4vw;
+    font-weight: 700;
+    color: #222;
+  }
+
+  .dialog-message {
+    font-size: 3.6vw;
+    line-height: 1.7;
+    color: #555;
+    word-break: break-word;
+  }
+
+  .dialog-btn {
+    width: calc(100% - 10vw);
+    margin: 0 auto 2.5vw;
+    height: 12vw;
+    border-radius: 3vw;
+    font-size: 4vw;
+    font-weight: 600;
+    display: inline-flex;
+    align-items: center;
+    justify-content: center;
+    border: none;
+    box-shadow: 0 4px 12px rgba(255, 128, 54, 0.25);
+    letter-spacing: 0.2vw;
+  }
+}
+
+/* 动画 */
+.dialog-pop-enter-active,
+.dialog-pop-leave-active {
+  transition: all 0.25s ease;
+}
+.dialog-pop-enter-from,
+.dialog-pop-leave-to {
+  opacity: 0;
+  transform: translate(-50%, -45%) scale(0.9);
+}
+
+@keyframes dialogPop {
+  from {
+    transform: translate(-50%, -45%) scale(0.9);
+    opacity: 0;
+  }
+  to {
+    transform: translate(-50%, -50%) scale(1);
+    opacity: 1;
+  }
+}
+</style>

+ 1 - 1
src/views/invoice-information/detail.vue

@@ -101,7 +101,7 @@ const getInvoiceTax = async () => {
       }
     } else {
       taxList.value = []
-      showToast(res?.msg || '获取税费信息失败')
+      showToast(res?.msg || '未查询到税费明细')
     }
   } catch (err) {
     console.error('请求失败', err)

+ 15 - 95
src/views/invoice-information/index.vue

@@ -62,7 +62,6 @@
             </div>
           </div>
         </div>
-
         <!-- 发票信息 -->
         <div class="card">
           <div class="card-header">
@@ -119,37 +118,21 @@
       </van-button>
     </div>
 
-    <!-- ✅ 弹窗(放在最外层,不要嵌套第二个 template) -->
-    <van-dialog
+    <!-- 通用弹窗 -->
+    <ModernDialog
       v-model:show="showDialog"
-      :show-cancel-button="false"
-      :show-confirm-button="false"
-      class="modern-dialog"
-      close-on-click-overlay
-    >
-      <div class="dialog-content">
-        <div class="dialog-title">申请成功</div>
-        <div class="dialog-message">
-          您的开票信息已提交至税务部门审核,审核通过后通知您缴纳税款,请关注缴税信息。
-        </div>
-        <van-button
-          type="primary"
-          block
-          round
-          class="dialog-btn"
-          color="linear-gradient(90deg, #ff7a00, #ffa94d)"
-          @click="onConfirm"
-        >
-          我知道了
-        </van-button>
-      </div>
-    </van-dialog>
+      title="申请成功"
+      message="您的开票信息已提交至税务部门审核,审核通过后通知您缴纳税款,请关注缴税信息。"
+      confirmText="我知道了"
+      @confirm="onConfirm"
+    />
   </div>
 </template>
 
 <script setup lang="ts">
 import { useRouter } from 'vue-router'
 import { useDebounceFn } from '@/utils/util'
+import ModernDialog from '@/components/ModernDialog.vue'
 import {
   getConfirmInvoiceInfoApi,
   getStatusApi,
@@ -178,8 +161,11 @@ const getConfirmInvoiceInfo = async () => {
     if (res.code === 0) {
       invoiceInfo.value = res.data
     }
-  } catch (err) {
-    console.error('获取发票信息失败', err)
+  } catch (err: any) {
+    const { code, message } = err
+    if (code === 1 && message) {
+      showToast(message)
+    }
   } finally {
     loading.value = false
   }
@@ -210,7 +196,8 @@ const submitInvoiceApply = async () => {
       showDialog.value = true
     }
   } catch (err) {
-    console.error('提交失败', err)
+    console.log('err', err)
+
     showToast('提交失败,请稍后重试')
   }
 }
@@ -396,71 +383,4 @@ onMounted(() => {
     }
   }
 }
-
-/* 修正版:留白 + 按钮不被挤压 */
-.modern-dialog {
-  width: 80vw;
-  border-radius: 5vw !important;
-  background: #fff;
-  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.15);
-  padding: 0; /* 外层不再加内边距,改到内容区 */
-  overflow: visible; /* 允许按钮投影外扩 */
-  text-align: center;
-  animation: dialogPop 0.28s ease-out;
-  box-sizing: border-box;
-
-  .dialog-content {
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-    padding: 6vw 5vw 5vw; /* ✅ 内容留白在这里 */
-    gap: 5vw; /* 内容与按钮的竖向间距 */
-  }
-
-  .dialog-title {
-    font-size: 4.4vw;
-    font-weight: 700;
-    color: #222;
-  }
-
-  .dialog-message {
-    font-size: 3.6vw;
-    line-height: 1.7;
-    color: #555;
-    word-break: break-word;
-  }
-
-  /* ✅ 独立按钮:有左右边距与圆角,不会被挤压 */
-  .dialog-btn {
-    width: calc(100% - 10vw); /* 等同左右各 5vw 的边距 */
-    margin: 0 auto 2.5vw; /* 底部也留点气口 */
-    height: 12vw;
-    border-radius: 3vw;
-    font-size: 4vw;
-    font-weight: 600;
-    display: inline-flex; /* 避免被拉伸成整块底边 */
-    align-items: center;
-    justify-content: center;
-    border: none;
-    box-shadow: 0 4px 12px rgba(255, 128, 54, 0.25);
-    letter-spacing: 0.2vw;
-  }
-}
-
-/* 蒙层与动画(可保留) */
-:deep(.van-overlay) {
-  backdrop-filter: blur(8px);
-  background: rgba(0, 0, 0, 0.25);
-  animation: fadeIn 0.3s ease;
-}
-@keyframes dialogPop {
-  from {
-    transform: translateY(4vw) scale(0.9);
-    opacity: 0;
-  }
-  to {
-    transform: translateY(0) scale(1);
-    opacity: 1;
-  }
-}
 </style>