From 22a6de40ac6693463cdbbe9ed1e3ef05fc301afc Mon Sep 17 00:00:00 2001
From: wupengfei <834520024@qq.com>
Date: 星期二, 23 九月 2025 14:50:34 +0800
Subject: [PATCH] feat: 绑定银行卡

---
 apps/cMiniApp/src/subpackages/wallet/bindBankCard/InnerPage.vue    |   56 ++++++++
 apps/cMiniApp/src/subpackages/wallet/unboundBankCard/InnerPage.vue |   93 +++++++--------
 packages/utils/common.ts                                           |    5 
 packages/services/apiV2/enterpriseWallet.ts                        |   12 ++
 apps/cMiniApp/src/hooks/user.ts                                    |   11 +
 apps/cMiniApp/src/subpackages/wallet/incomeDetail/InnerPage.vue    |   34 +++--
 packages/services/apiV2/typings.d.ts                               |   65 +++++++++-
 apps/cMiniApp/src/subpackages/wallet/mineWallet/InnerPage.vue      |   13 +
 packages/utils/validator.ts                                        |    7 +
 packages/constants/apiEnum.ts                                      |   12 ++
 apps/cMiniApp/src/pages/mine/index.vue                             |    2 
 packages/services/apiV2/user.ts                                    |   32 +++++
 12 files changed, 256 insertions(+), 86 deletions(-)

diff --git a/apps/cMiniApp/src/hooks/user.ts b/apps/cMiniApp/src/hooks/user.ts
index 980d82f..d6a9ac3 100644
--- a/apps/cMiniApp/src/hooks/user.ts
+++ b/apps/cMiniApp/src/hooks/user.ts
@@ -1,7 +1,11 @@
 import { useUserStore } from '@/stores/modules/user';
 import Taro from '@tarojs/taro';
 import { object2query, LocationUtils } from '@12333/utils';
-import { ParkOrHRStatus, UserCertificationFrontStatus } from '@12333/constants';
+import {
+  EnumUserBankCardAccess,
+  ParkOrHRStatus,
+  UserCertificationFrontStatus,
+} from '@12333/constants';
 import { useQuery, useQueryClient } from '@tanstack/vue-query';
 import { MaybeRef } from 'vue';
 import { useRefeshDidShow } from '@12333/hooks/infiniteLoading';
@@ -21,6 +25,10 @@
     return userDetail.value?.isReal;
   });
 
+  const isBindBank = computed(() => {
+    return userDetail.value?.bankCardAAccesses?.find(() => EnumUserBankCardAccess.Bank);
+  });
+
   return {
     user: userInfo,
     userDetail: userDetail,
@@ -28,6 +36,7 @@
     isCertified,
     locationCity,
     userId,
+    isBindBank,
   };
 }
 
diff --git a/apps/cMiniApp/src/pages/mine/index.vue b/apps/cMiniApp/src/pages/mine/index.vue
index 5c2b0e4..9609903 100644
--- a/apps/cMiniApp/src/pages/mine/index.vue
+++ b/apps/cMiniApp/src/pages/mine/index.vue
@@ -58,7 +58,7 @@
     <ContentScrollView v-if="isLogin" class="mine-content-scroll-view">
       <List class="mine-list-wrapper mine-balance">
         <div class="mine-balance-title">鎴戠殑浣欓</div>
-        <div class="mine-balance-money">锟{ toThousand(userDetail?.balance) }}</div>
+        <div class="mine-balance-money">锟{ toThousand(userDetail?.balance ?? 0) }}</div>
         <div class="mine-balance-btn" @click="goMineWallet">
           杩涘叆鎴戠殑閽卞寘
           <img :src="IconArrow" class="mine-balance-btn-icon" />
diff --git a/apps/cMiniApp/src/subpackages/wallet/bindBankCard/InnerPage.vue b/apps/cMiniApp/src/subpackages/wallet/bindBankCard/InnerPage.vue
index 0ac88a1..d68026e 100644
--- a/apps/cMiniApp/src/subpackages/wallet/bindBankCard/InnerPage.vue
+++ b/apps/cMiniApp/src/subpackages/wallet/bindBankCard/InnerPage.vue
@@ -3,8 +3,10 @@
     <div class="bind-bank-card-wrapper">
       <div class="bg-left-top"></div>
       <div class="bind-bank-card-content">
-        <div class="bank-card-name">{{ '鎷涘晢閾惰' }}</div>
-        <div class="bank-card-number">{{ '**** **** **** 1234' }}</div>
+        <div class="bank-card-name">{{ detail?.bank ?? '' }}</div>
+        <div class="bank-card-number">
+          <div class="bank-card-number-text">{{ showBankCodeForEnd4(detail?.code ?? '') }}</div>
+        </div>
         <div class="bank-card-type">{{ '鍌ㄨ搫鍗�' }}</div>
       </div>
       <div class="bg-right-bottom"></div>
@@ -18,15 +20,59 @@
 
 <script setup lang="ts">
 import { useUserStore } from '@/stores/modules/user';
+import { useQuery } from '@tanstack/vue-query';
+import { Message, showBankCodeForEnd4 } from '@12333/utils';
+import * as userServices from '@12333/services/apiV2/user';
 import Taro from '@tarojs/taro';
+import { EnumUserBankCardAccess } from '@12333/constants';
 
 defineOptions({
   name: 'InnerPage',
 });
 
-const userStore = useUserStore();
+const {} = useUser();
+const switchTab = useSwitchTab();
+function goUserCenter() {
+  switchTab({
+    url: RouterPath.mine,
+  });
+}
 
-function handleUnbind() {}
+const {
+  isLoading,
+  isError,
+  data: detail,
+  refetch,
+} = useQuery({
+  queryKey: ['userServices/getPersonalUserBankCard'],
+  queryFn: async () => {
+    return await userServices.getPersonalUserBankCard(
+      { access: EnumUserBankCardAccess.Bank },
+      {
+        showLoading: false,
+      }
+    );
+  },
+  placeholderData: () => ({} as API.GetPersonalUserBankCardQueryResult),
+  onSuccess(data) {},
+});
+
+async function handleUnbind() {
+  try {
+    await Message.confirm({ message: '纭畾瑕佽В缁戦摱琛屽崱鍚楋紵' });
+    let params: API.DeletePersonalUserBankCardCommand = {
+      access: EnumUserBankCardAccess.Bank,
+    };
+    let res = await userServices.deletePersonalUserBankCard(params);
+    if (res) {
+      Message.success('瑙g粦鎴愬姛', {
+        onClosed() {
+          goUserCenter();
+        },
+      });
+    }
+  } catch (error) {}
+}
 </script>
 
 <style lang="scss">
@@ -34,7 +80,7 @@
 
 .bindBankCard-page-wrapper {
   .bind-bank-card-wrapper {
-    margin: 20px auto 0;
+    margin: 0 auto;
     width: 660px;
     height: 360px;
     padding: 60px 72px;
diff --git a/apps/cMiniApp/src/subpackages/wallet/incomeDetail/InnerPage.vue b/apps/cMiniApp/src/subpackages/wallet/incomeDetail/InnerPage.vue
index 68bd0c0..e6666dc 100644
--- a/apps/cMiniApp/src/subpackages/wallet/incomeDetail/InnerPage.vue
+++ b/apps/cMiniApp/src/subpackages/wallet/incomeDetail/InnerPage.vue
@@ -1,5 +1,5 @@
 <template>
-  <ProTabs
+  <!-- <ProTabs
     v-model="queryState.type"
     name="home-tab"
     :showPaneContent="false"
@@ -11,7 +11,7 @@
     <ProTabPane :title="`鍏ㄩ儴`" :pane-key="0"></ProTabPane>
     <ProTabPane :title="`鏀跺叆`" :pane-key="EnumUserWalletTransactionType.Income"></ProTabPane>
     <ProTabPane :title="`鎻愮幇`" :pane-key="EnumUserWalletTransactionType.Withdraw"></ProTabPane>
-  </ProTabs>
+  </ProTabs> -->
   <List>
     <IncomeDetailListItem :item="`鏀跺叆锛氾骏${toThousand(sumIncome)} `">
       <template #title>
@@ -87,10 +87,11 @@
         page: pageParam,
         orderInput: [{ property: 'id', order: EnumPagedListOrder.Desc }],
       },
+      type: EnumUserWalletTransactionType.Income,
     };
-    if (Number(queryState.type)) {
-      params.type = queryState.type;
-    }
+    // if (Number(queryState.type)) {
+    //   params.type = queryState.type;
+    // }
     if (queryState.month) {
       params.createdTimeStart = dayjs(queryState.month).startOf('month').format('YYYY-MM-DD');
       params.createdTimeEnd = dayjs(queryState.month).endOf('month').format('YYYY-MM-DD');
@@ -105,16 +106,19 @@
 );
 
 function goIncomeDetailInfo(row: API.GetPersonalUserTransactionsQueryResultItem) {
-  if (row.type === EnumUserWalletTransactionType.Income) {
-    Taro.navigateTo({
-      url: `${RouterPath.incomeDetailInfo}?id=${row.id}`,
-    });
-  }
-  if (row.type === EnumUserWalletTransactionType.Withdraw) {
-    Taro.navigateTo({
-      url: `${RouterPath.withdrawDetailInfo}?id=${row.id}`,
-    });
-  }
+  Taro.navigateTo({
+    url: `${RouterPath.incomeDetailInfo}?id=${row.id}`,
+  });
+  // if (row.type === EnumUserWalletTransactionType.Income) {
+  //   Taro.navigateTo({
+  //     url: `${RouterPath.incomeDetailInfo}?id=${row.id}`,
+  //   });
+  // }
+  // if (row.type === EnumUserWalletTransactionType.Withdraw) {
+  //   Taro.navigateTo({
+  //     url: `${RouterPath.withdrawDetailInfo}?id=${row.id}`,
+  //   });
+  // }
 }
 </script>
 
diff --git a/apps/cMiniApp/src/subpackages/wallet/mineWallet/InnerPage.vue b/apps/cMiniApp/src/subpackages/wallet/mineWallet/InnerPage.vue
index b8a68cf..2e85da4 100644
--- a/apps/cMiniApp/src/subpackages/wallet/mineWallet/InnerPage.vue
+++ b/apps/cMiniApp/src/subpackages/wallet/mineWallet/InnerPage.vue
@@ -1,14 +1,14 @@
 <template>
-  <div class="mine-wallet-balance">
+  <!-- <div class="mine-wallet-balance">
     <WithdrawMoneyCard :money="userDetail.balance" title="璐︽埛浣欓(鍏�)"></WithdrawMoneyCard>
     <nut-button type="primary" class="mine-wallet-balance-btn" @click="goWithdraw">鎻愮幇</nut-button>
-  </div>
+  </div> -->
   <List>
     <ListItem title="鏀跺叆鏄庣粏" @click="goIncomeDetail"> </ListItem>
     <ListItem title="閾惰鍗�" @click="goBankBind">
       <template #extra>
         <div class="bind-bank-card">
-          {{ isBinding ? '宸茬粦瀹�' : '鏈粦瀹氥�佺珛鍗崇粦瀹�' }}
+          {{ isBindBank ? '宸茬粦瀹�' : '鏈粦瀹氥�佺珛鍗崇粦瀹�' }}
         </div>
       </template>
     </ListItem>
@@ -17,6 +17,7 @@
 
 <script setup lang="ts">
 import { List, ListItem, WithdrawMoneyCard } from '@12333/components';
+import { EnumUserBankCardAccess } from '@12333/constants';
 import Taro from '@tarojs/taro';
 
 defineOptions({
@@ -25,7 +26,9 @@
 
 const { userDetail } = useUser();
 
-const isBinding = ref(false);
+const isBindBank = computed(() =>
+  userDetail.value?.bankCardAAccesses?.find(() => EnumUserBankCardAccess.Bank)
+);
 
 function goIncomeDetail() {
   Taro.navigateTo({
@@ -44,7 +47,7 @@
 const goBankBind = useAccessReal(
   () => {
     Taro.navigateTo({
-      url: `${isBinding.value ? RouterPath.bindBankCard : RouterPath.unboundBankCard}`,
+      url: `${isBindBank.value ? RouterPath.bindBankCard : RouterPath.unboundBankCard}`,
     });
   },
   { message: '瀹屾垚瀹炲悕璁よ瘉鍚庢墠鍙繘琛岄摱琛屽崱缁戝畾' }
diff --git a/apps/cMiniApp/src/subpackages/wallet/unboundBankCard/InnerPage.vue b/apps/cMiniApp/src/subpackages/wallet/unboundBankCard/InnerPage.vue
index f458fa7..b1be1c9 100644
--- a/apps/cMiniApp/src/subpackages/wallet/unboundBankCard/InnerPage.vue
+++ b/apps/cMiniApp/src/subpackages/wallet/unboundBankCard/InnerPage.vue
@@ -2,22 +2,22 @@
   <ContentScrollView :paddingH="false">
     <nut-form :model-value="form" ref="formRef" :rules="rules">
       <nut-form-item label="鎸佸崱浜�:" class="bole-form-item" prop="name">
-        <nut-input v-model.trim="form.name" placeholder="璇疯緭鍏ユ寔鍗′汉" />
+        <nut-input v-model.trim="form.name" placeholder="璇疯緭鍏ユ寔鍗′汉" readonly />
       </nut-form-item>
-      <nut-form-item label="韬唤璇佸彿:" class="bole-form-item" prop="name">
-        <nut-input v-model.trim="form.name" placeholder="璇疯緭鍏ヨ韩浠借瘉鍙�" />
+      <nut-form-item label="韬唤璇佸彿:" class="bole-form-item" prop="identity">
+        <nut-input v-model.trim="form.identity" placeholder="璇疯緭鍏ヨ韩浠借瘉鍙�" readonly />
       </nut-form-item>
-      <nut-form-item label="閾惰鍗″彿:" class="bole-form-item" prop="name">
-        <nut-input v-model.trim="form.name" placeholder="璇疯緭鍏ラ摱琛屽崱鍙�" />
+      <nut-form-item label="閾惰鍗″彿:" class="bole-form-item" prop="code">
+        <nut-input v-model.trim="form.code" placeholder="璇疯緭鍏ラ摱琛屽崱鍙�" />
       </nut-form-item>
-      <nut-form-item label="寮�鎴疯:" class="bole-form-item" prop="name">
-        <nut-input v-model.trim="form.name" placeholder="璇疯緭鍏ュ紑鎴疯" />
+      <nut-form-item label="寮�鎴疯:" class="bole-form-item" prop="bank">
+        <nut-input v-model.trim="form.bank" placeholder="璇疯緭鍏ュ紑鎴疯" />
       </nut-form-item>
       <nut-form-item label="鎵嬫満鍙�:" class="bole-form-item" prop="phoneNumber" required>
         <nut-input
           v-model.trim="form.phoneNumber"
           class="nut-input-text bole-input-text"
-          placeholder="璇峰~鍐欑粡鍔炰汉鐨勬墜鏈哄彿鐮�"
+          placeholder="璇峰~鍐欓摱琛岄鐣欐墜鏈哄彿"
           type="text"
         >
           <template #right>
@@ -29,9 +29,9 @@
           </template>
         </nut-input>
       </nut-form-item>
-      <nut-form-item label="鐭俊楠岃瘉鐮�:" class="bole-form-item" prop="verificationCode" required>
+      <nut-form-item label="鐭俊楠岃瘉鐮�:" class="bole-form-item" prop="verifyCode" required>
         <nut-input
-          v-model.trim="form.verificationCode"
+          v-model.trim="form.verifyCode"
           class="nut-input-text bole-input-text"
           placeholder="璇疯緭鍏ラ獙璇佺爜"
           type="number"
@@ -47,55 +47,45 @@
 <script setup lang="ts">
 import { FormRules } from '@nutui/nutui-taro/dist/types/__VUE/form/types';
 import { ProFormCaptcha } from 'senin-mini/components';
-import { Message } from '@12333/utils';
-import { VerificationCodeBusinessType } from '@12333/constants';
-import * as commonServices from '@12333/services/api/Common';
+import { FormValidator, Message } from '@12333/utils';
+import * as userServices from '@12333/services/apiV2/user';
 import Taro from '@tarojs/taro';
-import { useQuery, useQueryClient } from '@tanstack/vue-query';
+import { useQueryClient } from '@tanstack/vue-query';
+import { EnumUserBankCardAccess } from '@12333/constants';
 
-const userResumeServices = {};
+const { userDetail } = useUser();
 const queryClient = useQueryClient();
 defineOptions({
   name: 'InnerPage',
 });
 
 const form = reactive({
-  name: '',
+  name: userDetail.value?.name ?? '',
+  identity: userDetail.value?.identity ?? '',
   phoneNumber: '',
-  verificationCode: '',
-});
-
-const {
-  isLoading,
-  isError,
-  data: detail,
-  refetch,
-} = useQuery({
-  queryKey: ['userResumeServices/getUserResumeBaseInfo'],
-  queryFn: async () => {
-    return await userResumeServices.getUserResumeBaseInfo({
-      showLoading: false,
-    });
-  },
-  placeholderData: () => ({} as API.UserResumeBaseInfoOutput),
-  onSuccess(data) {
-    form.name = data.name;
-    form.phoneNumber = data.phoneNumber;
-  },
+  code: '',
+  bank: '',
+  bankBranch: '',
+  verifyCode: '',
 });
 
 const rules = reactive<FormRules>({
-  name: [{ required: true, message: '璇疯緭鍏ユ寔鍗′汉' }],
-  phoneNumber: [{ required: true, message: '璇疯緭鍏ユ墜鏈哄彿' }],
+  code: [
+    { required: true, message: '璇疯緭鍏ラ摱琛屽崱鍙�' },
+    { message: '璇疯緭鍏ユ纭殑閾惰鍗″彿', validator: FormValidator.validatorBankCard },
+  ],
+  bank: [{ required: true, message: '璇疯緭鍏ュ紑鎴疯' }],
+  phoneNumber: [
+    { required: true, message: '璇峰~鍐欐墜鏈哄彿鐮�' },
+    { message: '璇疯緭鍏ユ纭殑鎵嬫満鍙风爜', validator: FormValidator.validatorPhoneNumber },
+  ],
+  verifyCode: [{ required: true, message: '璇疯緭鍏ラ獙璇佺爜' }],
 });
 
 async function onGetCaptcha(phoneNumber: string) {
-  await commonServices.sendPhoneCertificationVerificationCode(
+  await userServices.sendSavePersonalUserBankCardVerifyCode(
     {
-      name: form.name,
-      identity: form.name,
-      mobile: form.phoneNumber,
-      businessType: VerificationCodeBusinessType.UserCertificationPhoneCertification,
+      phoneNumber: form.phoneNumber,
     },
     { showLoading: false }
   );
@@ -113,20 +103,21 @@
 
 async function confirm() {
   try {
-    let params: API.SaveUserResumeBaseInfoInput = {
-      name: form.name,
+    let params: API.SavePersonalUserBankCardCommand = {
+      code: form.code,
+      bank: form.bank,
       phoneNumber: form.phoneNumber,
+      verifyCode: form.verifyCode,
+      access: EnumUserBankCardAccess.Bank,
     };
-    let res = await userResumeServices.saveUserResumeBaseInfo(params);
+    let res = await userServices.savePersonalUserBankCard(params);
     if (res) {
-      Message.success('淇濆瓨鎴愬姛', {
+      Message.success('缁戝畾鎴愬姛', {
         onClosed() {
           Taro.navigateTo({
-            url: `${RouterPath.mineCurriculumVitae}`,
+            url: `${RouterPath.bindBankCard}`,
           });
-          queryClient.invalidateQueries([
-            'taskCheckReceiveServices/getCheckReceiveTaskUserSubmits',
-          ]);
+          queryClient.invalidateQueries(['authServices/getPersonalLoginInfo']);
         },
       });
     }
diff --git a/packages/constants/apiEnum.ts b/packages/constants/apiEnum.ts
index df166c7..448f703 100644
--- a/packages/constants/apiEnum.ts
+++ b/packages/constants/apiEnum.ts
@@ -107,6 +107,8 @@
 export enum EnumEnterpriseWalletAccess {
   /**鏀粯瀹� */
   Alipay = 10,
+  /**骞冲畨閾惰 */
+  PingAnPay = 20,
 }
 
 /** 浼佷笟閽卞寘浠h繘浠跺崟闄勪欢绫诲瀷 */
@@ -473,6 +475,16 @@
   Fail = 40,
 }
 
+/** 鐢ㄦ埛閾惰鍗¢�氶亾 */
+export enum EnumUserBankCardAccess {
+  /**閾惰鍗� */
+  Bank = 1,
+  /**鏀粯瀹� */
+  AliPay = 10,
+  /**寰俊 */
+  WeChatPay = 20,
+}
+
 /** 鐢ㄦ埛鎬у埆 */
 export enum EnumUserGender {
   /**鐢� */
diff --git a/packages/services/apiV2/enterpriseWallet.ts b/packages/services/apiV2/enterpriseWallet.ts
index f47a980..a71c0c5 100644
--- a/packages/services/apiV2/enterpriseWallet.ts
+++ b/packages/services/apiV2/enterpriseWallet.ts
@@ -310,3 +310,15 @@
     }
   );
 }
+
+/** 娴嬭瘯闃块噷鏀粯 POST /api/user/enterpriseWallet/testAliPay */
+export async function testAliPay(body: API.TestAliPayCommand, options?: API.RequestConfig) {
+  return request<string>('/api/user/enterpriseWallet/testAliPay', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json-patch+json',
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
diff --git a/packages/services/apiV2/typings.d.ts b/packages/services/apiV2/typings.d.ts
index 46326ce..bc18054 100644
--- a/packages/services/apiV2/typings.d.ts
+++ b/packages/services/apiV2/typings.d.ts
@@ -156,8 +156,8 @@
   }
 
   interface APIgetPersonalUserBankCardParams {
-    /** 鏌ヨ涓汉鐢ㄦ埛閾惰鍗′俊鎭� */
-    request?: GetPersonalUserBankCardQuery;
+    /** 閫氶亾 */
+    access?: EnumUserBankCardAccess;
   }
 
   interface APIgetPersonalUserElectronSignParams {
@@ -209,6 +209,8 @@
   interface APIgetSettlementTaskUsersParams {
     /** 缁撶畻璁㈠崟Id */
     id?: string;
+    /** 浠诲姟Id */
+    taskInfoId?: string;
   }
 
   interface APIgetTaskEnterpriseParams {
@@ -408,6 +410,10 @@
 
   interface DeleteMenuCommand {
     ids: string[];
+  }
+
+  interface DeletePersonalUserBankCardCommand {
+    access?: EnumUserBankCardAccess;
   }
 
   interface DeleteRoleCommand {
@@ -616,6 +622,8 @@
   enum EnumEnterpriseWalletAccess {
     /**鏀粯瀹� */
     Alipay = 10,
+    /**骞冲畨閾惰 */
+    PingAnPay = 20,
   }
 
   enum EnumEnterpriseWalletExpandindirectOrderFileType {
@@ -949,6 +957,15 @@
     Success = 30,
     /**楠屾敹鏈�氳繃 */
     Fail = 40,
+  }
+
+  enum EnumUserBankCardAccess {
+    /**閾惰鍗� */
+    Bank = 1,
+    /**鏀粯瀹� */
+    AliPay = 10,
+    /**寰俊 */
+    WeChatPay = 20,
   }
 
   enum EnumUserGender {
@@ -3451,6 +3468,10 @@
     /** 鍗忚澶辨晥鏃堕棿 */
     invalidTime?: string;
     signStatus?: EnumEnterpriseWalletSignStatus;
+    /** 鎵�灞為摱琛� */
+    bank?: string;
+    /** 鎵�灞炴敮琛� */
+    bankBranch?: string;
     /** 鏀粯瀹濆鍚� */
     name?: string;
     /** 鏀粯瀹濈櫥褰曡处鍙� */
@@ -3467,6 +3488,8 @@
     /** 闄勪欢 */
     files?: GetEnterpriseWalletExpandindirectOrderQueryResultFile[];
     expandindirectOrderStatus?: EnumEnterpriseWalletExpandindirectOrderStatus;
+    /** 浣欓 */
+    balance?: number;
   }
 
   interface GetEnterpriseWalletTransactionQueryResult {
@@ -3870,6 +3893,8 @@
     avatar?: string;
     /** 濮撳悕 */
     name?: string;
+    /** 韬唤璇佸彿 */
+    identity?: string;
     /** 鎵嬫満鍙� */
     contactPhoneNumber?: string;
     /** 鏄惁瀹炲悕 */
@@ -3886,12 +3911,12 @@
     hireRefuseTaskCount?: number;
     /** 浣欓 */
     balance?: number;
+    /** 宸茬粦瀹氱殑閾惰鍗¢�氶亾 */
+    bankCardAAccesses?: EnumUserBankCardAccess[];
   }
 
-  type GetPersonalUserBankCardQuery = Record<string, any>;
-
   interface GetPersonalUserBankCardQueryResult {
-    access?: EnumEnterpriseWalletAccess;
+    access?: EnumUserBankCardAccess;
     /** 閾惰鍗″彿 */
     code?: string;
     /** 鎵�灞為摱琛� */
@@ -4497,6 +4522,12 @@
     settlementStatus?: EnumTaskSettlementStatus;
     /** 缁撶畻鏃堕棿 */
     settlementTime?: string;
+    /** 缁撶畻娴佹按鍙� */
+    orderCode?: string;
+    /** 鍒涘缓鏃堕棿 */
+    createdTime?: string;
+    /** 鐢靛瓙鏀舵嵁涓嬭浇閾炬帴 */
+    ereceiptDownloadOssUrl?: string;
   }
 
   interface GetTaskEnterpriseQueryResult {
@@ -4701,6 +4732,7 @@
     /** 鎺ㄨ崘鏃堕棿 */
     recommendTime?: string;
     hireStatus?: EnumTaskUserHireStatus;
+    settlementStatus?: EnumTaskSettlementStatus;
     /** 鍙戝竷鏃堕棿 */
     createdTime?: string;
   }
@@ -5163,6 +5195,14 @@
     /** 浼佷笟Id */
     enterpriseId?: string;
     access?: EnumEnterpriseWalletAccess;
+    /** 鎵�灞為摱琛� */
+    bank?: string;
+    /** 鎵�灞炴敮琛� */
+    bankBranch?: string;
+    /** 濮撳悕 */
+    name?: string;
+    /** 璐﹀彿 */
+    identity?: string;
   }
 
   interface OpenEnterpriseWalletCommandResult {
@@ -5578,7 +5618,7 @@
   }
 
   interface SavePersonalUserBankCardCommand {
-    access?: EnumEnterpriseWalletAccess;
+    access?: EnumUserBankCardAccess;
     /** 閾惰鍗″彿 */
     code?: string;
     /** 鎵�灞為摱琛� */
@@ -5587,6 +5627,8 @@
     bankBranch?: string;
     /** 閾惰棰勭暀鎵嬫満鍙� */
     phoneNumber?: string;
+    /** 楠岃瘉鐮� */
+    verifyCode?: string;
   }
 
   interface SaveRoleCommand {
@@ -5759,6 +5801,11 @@
     identity: string;
   }
 
+  interface SendSavePersonalUserBankCardVerifyCodeCommand {
+    /** 鎵嬫満鍙风爜 */
+    phoneNumber: string;
+  }
+
   interface SetDictionaryDataIsDisabledCommand {
     ids?: string[];
     /** 鏄惁宸茬鐢� */
@@ -5879,6 +5926,7 @@
   interface SureTaskSettlementCommand {
     /** 浠诲姟Id */
     taskInfoId?: string;
+    settlementAccess?: EnumEnterpriseWalletAccess;
   }
 
   type SyncDatabaseCommand = Record<string, any>;
@@ -6006,6 +6054,11 @@
     remark?: string;
   }
 
+  interface TestAliPayCommand {
+    code?: string;
+    freezeNo?: string;
+  }
+
   interface UpdatePhoneNumberVerifyCodeCommand {
     /** 鎵嬫満鍙风爜 */
     phoneNumber: string;
diff --git a/packages/services/apiV2/user.ts b/packages/services/apiV2/user.ts
index d06c228..10561c9 100644
--- a/packages/services/apiV2/user.ts
+++ b/packages/services/apiV2/user.ts
@@ -2,6 +2,21 @@
 // @ts-ignore
 import { request } from '@/utils/request';
 
+/** 鍒犻櫎鐢ㄦ埛閾惰鍗′俊鎭� DELETE /api/user/user/deletePersonalUserBankCard */
+export async function deletePersonalUserBankCard(
+  body: API.DeletePersonalUserBankCardCommand,
+  options?: API.RequestConfig
+) {
+  return request<number>('/api/user/user/deletePersonalUserBankCard', {
+    method: 'DELETE',
+    headers: {
+      'Content-Type': 'application/json-patch+json',
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
+
 /** 鏌ヨ杩愯惀绔敤鎴峰垎椤靛垪琛ㄦ暟鎹� POST /api/user/user/getOperationUserInfos */
 export async function getOperationUserInfos(
   body: API.GetOperationUserInfosQuery,
@@ -30,8 +45,6 @@
     method: 'GET',
     params: {
       ...params,
-      request: undefined,
-      ...params['request'],
     },
     ...(options || {}),
   });
@@ -154,6 +167,21 @@
   });
 }
 
+/** 鍙戦�佺粦瀹氶摱琛屽崱鐭俊 POST /api/user/user/sendSavePersonalUserBankCardVerifyCode */
+export async function sendSavePersonalUserBankCardVerifyCode(
+  body: API.SendSavePersonalUserBankCardVerifyCodeCommand,
+  options?: API.RequestConfig
+) {
+  return request<string>('/api/user/user/sendSavePersonalUserBankCardVerifyCode', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json-patch+json',
+    },
+    data: body,
+    ...(options || {}),
+  });
+}
+
 /** 璁剧疆鐢ㄦ埛淇℃伅瑙掕壊 PUT /api/user/user/setUserInfoRoles */
 export async function setUserInfoRoles(
   body: API.SetUserInfoRolesCommand,
diff --git a/packages/utils/common.ts b/packages/utils/common.ts
index a420b99..a02170f 100644
--- a/packages/utils/common.ts
+++ b/packages/utils/common.ts
@@ -136,6 +136,11 @@
   return realIDNumber.replace(/^(\d+)(.{6})$/, '$1******');
 };
 
+export const showBankCodeForEnd4 = (bankCode: string) => {
+  if (!bankCode) return '';
+  return '*'.repeat(Math.max(0, bankCode.length - 4)) + bankCode.slice(-4);
+};
+
 export const hiddenPhone = (phone: string) => {
   if (!phone) return '';
   return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
diff --git a/packages/utils/validator.ts b/packages/utils/validator.ts
index f4ba102..4e7864e 100644
--- a/packages/utils/validator.ts
+++ b/packages/utils/validator.ts
@@ -98,6 +98,13 @@
     }
     return Promise.reject(ruleCfg.message);
   }
+  static validatorBankCard(value: string, ruleCfg: FormItemRuleWithoutValidator) {
+    if (!ruleCfg.required && !value) return Promise.resolve(true);
+    if (BoleRegExp.RegBankCard.test(value)) {
+      return Promise.resolve(true);
+    }
+    return Promise.reject(ruleCfg.message);
+  }
 }
 
 export class BoleRegExp {

--
Gitblit v1.9.1