Bläddra i källkod

Merge branch 'v1.1.0' into test

0es 1 månad sedan
förälder
incheckning
bc7d0b4328
3 ändrade filer med 96 tillägg och 55 borttagningar
  1. 2 2
      app/pages/wallet/withdraw/apply.vue
  2. 92 51
      app/pages/wallet/withdraw/auth.vue
  3. 2 2
      app/types/api/wallet.ts

+ 2 - 2
app/pages/wallet/withdraw/apply.vue

@@ -680,8 +680,8 @@ const onSubmit = async () => {
   /* Keep font-family/font-size consistent between input and measure node */
   font-family: var(--font-title, 'Poppins', sans-serif);
   font-weight: 600;
-  font-size: 16px;
-  line-height: 17px;
+  font-size: 18px;
+  line-height: 22px;
   color: #1d2129;
 }
 

+ 92 - 51
app/pages/wallet/withdraw/auth.vue

@@ -171,16 +171,26 @@ onMounted(() => {
 })
 
 const isFormValid = computed(() => {
-  // Check if ID card images are available (either uploaded or existing)
+  // Only validate fields that will be submitted.
+  // Rule:
+  // - If any part is not applied (state=0), submit both.
+  // - Otherwise submit only the rejected part(s) (state=3).
+  const shouldSubmitBoth = idCardState.value === 0 || bankCardState.value === 0
+    || (idCardState.value === 3 && bankCardState.value === 3)
+  const shouldSubmitIdCard = shouldSubmitBoth || idCardState.value === 3
+  const shouldSubmitBankCard = shouldSubmitBoth || bankCardState.value === 3
+
+  if (!shouldSubmitIdCard && !shouldSubmitBankCard) {
+    return false
+  }
+
   const hasIdCardImages = (frontIdFile.value || frontIdImageUrl.value)
     && (backIdFile.value || backIdImageUrl.value)
 
   return (
     realName.value.trim()
-    && idNo.value.trim()
-    && hasIdCardImages
-    && bankNo.value.trim()
-    && bankName.value.trim()
+    && (!shouldSubmitIdCard || (idNo.value.trim() && hasIdCardImages))
+    && (!shouldSubmitBankCard || (bankNo.value.trim() && bankName.value.trim()))
     && !submitting.value
     && !uploadingFront.value
     && !uploadingBack.value
@@ -188,78 +198,106 @@ const isFormValid = computed(() => {
 })
 
 const handleSubmit = async () => {
-  // Validate all fields
-  if (!realName.value.trim()) {
-    showToast(t('wallet.withdraw.auth.validation.realNameRequired'))
+  // Decide which parts to submit.
+  // - If any part is not applied (state=0), submit both.
+  // - Otherwise submit only the rejected part(s) (state=3).
+  const shouldSubmitBoth = idCardState.value === 0 || bankCardState.value === 0
+    || (idCardState.value === 3 && bankCardState.value === 3)
+  const shouldSubmitIdCard = shouldSubmitBoth || idCardState.value === 3
+  const shouldSubmitBankCard = shouldSubmitBoth || bankCardState.value === 3
+
+  if (!shouldSubmitIdCard && !shouldSubmitBankCard) {
+    showToast(t('wallet.withdraw.auth.failed'))
     return
   }
 
-  if (!idNo.value.trim()) {
-    showToast(t('wallet.withdraw.auth.validation.idNoRequired'))
+  // Validate common field
+  if (!realName.value.trim()) {
+    showToast(t('wallet.withdraw.auth.validation.realNameRequired'))
     return
   }
 
-  // Check if ID card images are available (either new files or existing URLs)
-  if (!frontIdFile.value && !frontIdImageUrl.value) {
-    showToast(t('wallet.withdraw.auth.validation.frontImageRequired'))
-    return
-  }
+  // Validate only the parts being submitted
+  if (shouldSubmitIdCard) {
+    if (!idNo.value.trim()) {
+      showToast(t('wallet.withdraw.auth.validation.idNoRequired'))
+      return
+    }
 
-  if (!backIdFile.value && !backIdImageUrl.value) {
-    showToast(t('wallet.withdraw.auth.validation.backImageRequired'))
-    return
-  }
+    // Check if ID card images are available (either new files or existing URLs)
+    if (!frontIdFile.value && !frontIdImageUrl.value) {
+      showToast(t('wallet.withdraw.auth.validation.frontImageRequired'))
+      return
+    }
 
-  if (!bankNo.value.trim()) {
-    showToast(t('wallet.withdraw.auth.validation.bankNoRequired'))
-    return
+    if (!backIdFile.value && !backIdImageUrl.value) {
+      showToast(t('wallet.withdraw.auth.validation.backImageRequired'))
+      return
+    }
   }
 
-  if (!bankName.value.trim()) {
-    showToast(t('wallet.withdraw.auth.validation.bankNameRequired'))
-    return
+  if (shouldSubmitBankCard) {
+    if (!bankNo.value.trim()) {
+      showToast(t('wallet.withdraw.auth.validation.bankNoRequired'))
+      return
+    }
+
+    if (!bankName.value.trim()) {
+      showToast(t('wallet.withdraw.auth.validation.bankNameRequired'))
+      return
+    }
   }
 
   try {
     submitting.value = true
 
-    // Upload front ID card image (only if new file selected)
+    // Upload ID card images only when needed.
     let frontImageUrl = frontIdImageUrl.value
-    if (frontIdFile.value) {
-      const uploadedUrl = await uploadFrontFile(frontIdFile.value)
-      if (!uploadedUrl) {
-        return
+    let backImageUrl = backIdImageUrl.value
+    if (shouldSubmitIdCard) {
+      // Upload front ID card image (only if new file selected)
+      if (frontIdFile.value) {
+        const uploadedUrl = await uploadFrontFile(frontIdFile.value)
+        if (!uploadedUrl) {
+          return
+        }
+        frontImageUrl = uploadedUrl
       }
-      frontImageUrl = uploadedUrl
-    }
 
-    // Upload back ID card image (only if new file selected)
-    let backImageUrl = backIdImageUrl.value
-    if (backIdFile.value) {
-      const uploadedUrl = await uploadBackFile(backIdFile.value)
-      if (!uploadedUrl) {
-        return
+      // Upload back ID card image (only if new file selected)
+      if (backIdFile.value) {
+        const uploadedUrl = await uploadBackFile(backIdFile.value)
+        if (!uploadedUrl) {
+          return
+        }
+        backImageUrl = uploadedUrl
       }
-      backImageUrl = uploadedUrl
     }
 
-    // Submit to backend (use same realName for both idCard and bankCard)
-    const result = await walletApi.submitWithdrawRealNameAuth({
-      idCard: {
+    // Build payload: submit only rejected part(s), unless any part is not applied.
+    const payload: Parameters<typeof walletApi.submitWithdrawRealNameAuth>[0] = {}
+    if (shouldSubmitIdCard) {
+      payload.idCard = {
         idNo: idNo.value.trim(),
         realName: realName.value.trim(),
         idCardFrontImage: frontImageUrl,
         idCardBackImage: backImageUrl,
-      },
-      bankCard: {
+      }
+    }
+    if (shouldSubmitBankCard) {
+      payload.bankCard = {
         bankNo: bankNo.value.trim(),
         realName: realName.value.trim(),
         bankName: bankName.value.trim(),
-      },
-    })
+      }
+    }
+
+    const result = await walletApi.submitWithdrawRealNameAuth(payload)
 
     // Check result
-    if (result?.idCardApply && result?.idBankCardApply) {
+    const idOk = !payload.idCard || !!result?.idCardApply
+    const bankOk = !payload.bankCard || !!result?.idBankCardApply
+    if (idOk && bankOk) {
       showToast(t('wallet.withdraw.auth.success'))
       // Reload status to show updated state
       await loadAuthStatus()
@@ -518,7 +556,7 @@ const onBack = () => {
           <!-- Tip -->
           <div class="withdraw-auth-card__section withdraw-auth-card__section--tip">
             <div class="withdraw-auth-tip">
-              <TipIcon />
+              <TipIcon class="withdraw-auth-tip__icon" />
               <p class="withdraw-auth-tip__text">
                 {{ t('wallet.withdraw.auth.tip') }}
               </p>
@@ -663,8 +701,7 @@ const onBack = () => {
 .withdraw-auth-upload {
   margin-top: 10px;
   display: flex;
-  gap: 8px;
-  justify-content: center;
+  justify-content: space-between;
 }
 
 .withdraw-auth-upload-item {
@@ -812,8 +849,12 @@ const onBack = () => {
 
 .withdraw-auth-tip {
   display: flex;
-  align-items: center;
+  align-items: flex-start;
   gap: 3px;
+
+  &__icon {
+    flex-shrink: 0;
+  }
 }
 
 .withdraw-auth-tip__text {

+ 2 - 2
app/types/api/wallet.ts

@@ -122,9 +122,9 @@ export interface BankCardInfoSub {
  */
 export interface WalletWithdrawRealNameAuthDTO {
   /** 身份证信息 */
-  idCard: IdCardInfoSub
+  idCard?: IdCardInfoSub
   /** 银行卡信息 */
-  bankCard: BankCardInfoSub
+  bankCard?: BankCardInfoSub
 }
 
 /**