index.vue 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977
  1. <template>
  2. <div class="bind-page">
  3. <s-header title="绑定银行卡" :noback="false" :isBorder="false"></s-header>
  4. <div class="main-content">
  5. <!-- 步骤条 -->
  6. <div class="step-container">
  7. <van-steps :active="currentStep" active-color="#4d6add">
  8. <van-step>证件信息</van-step>
  9. <van-step>结算信息</van-step>
  10. <van-step>信息审核</van-step>
  11. <van-step>签约</van-step>
  12. </van-steps>
  13. </div>
  14. <!-- 证件信息 -->
  15. <div v-if="currentStep === 0" class="card-section">
  16. <van-tabs v-model:active="merchantType" title-active-color="#4d6add">
  17. <!-- 个人商户 -->
  18. <van-tab
  19. title="个人商户"
  20. :disabled="joinPayMchNo != null && merchantType === 1"
  21. >
  22. <div class="upload-card">
  23. <h3 class="upload-title">
  24. <span class="title-decoration"></span>
  25. 收款人证件(大陆)
  26. </h3>
  27. <div class="upload-group">
  28. <van-uploader
  29. v-model="idCardFront"
  30. :max-count="1"
  31. class="custom-uploader"
  32. name="idCardFront"
  33. :after-read="afterRead"
  34. >
  35. <template #default>
  36. <div class="upload-item">
  37. <van-icon name="photo" size="32" color="#4d6add" />
  38. <p>上传人像面</p>
  39. </div>
  40. </template>
  41. </van-uploader>
  42. <van-uploader
  43. v-model="idCardBack"
  44. :max-count="1"
  45. class="custom-uploader"
  46. name="idCardBack"
  47. :after-read="afterRead"
  48. >
  49. <template #default>
  50. <div class="upload-item">
  51. <van-icon name="photo" size="32" color="#4d6add" />
  52. <p>上传国徽面</p>
  53. </div>
  54. </template>
  55. </van-uploader>
  56. </div>
  57. </div>
  58. </van-tab>
  59. <!-- 企业商户 -->
  60. <van-tab
  61. title="企业商户"
  62. :disabled="joinPayMchNo != null && merchantType === 0"
  63. >
  64. <div class="upload-card">
  65. <h3 class="upload-title">
  66. <span class="title-decoration"></span>
  67. 法人证件信息(大陆)
  68. </h3>
  69. <div class="upload-group">
  70. <van-uploader
  71. v-model="idCardFront"
  72. :max-count="1"
  73. class="custom-uploader"
  74. name="idCardFront"
  75. :after-read="afterRead"
  76. >
  77. <template #default>
  78. <div class="upload-item">
  79. <van-icon name="photo" size="32" color="#4d6add" />
  80. <p>上传人像面</p>
  81. </div>
  82. </template>
  83. </van-uploader>
  84. <van-uploader
  85. v-model="idCardBack"
  86. :max-count="1"
  87. class="custom-uploader"
  88. name="idCardBack"
  89. :after-read="afterRead"
  90. >
  91. <template #default>
  92. <div class="upload-item">
  93. <van-icon name="photo" size="32" color="#4d6add" />
  94. <p>上传国徽面</p>
  95. </div>
  96. </template>
  97. </van-uploader>
  98. </div>
  99. <h3 class="upload-title" style="margin-top: 20px">
  100. <span class="title-decoration"></span>
  101. 营业执照
  102. </h3>
  103. <van-uploader
  104. v-model="businessLicense"
  105. :max-count="1"
  106. class="custom-uploader"
  107. name="businessLicense"
  108. :after-read="afterRead"
  109. >
  110. <template #default>
  111. <div class="upload-item single">
  112. <van-icon name="description" size="32" color="#4d6add" />
  113. <p>上传营业执照</p>
  114. </div>
  115. </template>
  116. </van-uploader>
  117. </div>
  118. </van-tab>
  119. </van-tabs>
  120. </div>
  121. <!-- 结算信息 -->
  122. <div v-if="currentStep === 1" class="card-section">
  123. <van-tabs v-model:active="merchantType" title-active-color="#4d6add">
  124. <!-- 个人商户 -->
  125. <van-tab title="个人商户" :disabled="merchantType === 1">
  126. <div class="upload-card">
  127. <h3 class="upload-title">
  128. <span class="title-decoration"></span>
  129. 银行卡正面
  130. </h3>
  131. <van-uploader
  132. v-model="bankCard"
  133. :max-count="1"
  134. class="custom-uploader"
  135. name="bankCard"
  136. :after-read="afterRead"
  137. >
  138. <template #default>
  139. <div class="upload-item single">
  140. <van-icon name="card" size="32" color="#4d6add" />
  141. <p>上传银行卡正面</p>
  142. </div>
  143. </template>
  144. </van-uploader>
  145. </div>
  146. </van-tab>
  147. <!-- 企业商户 -->
  148. <van-tab title="企业商户" :disabled="merchantType === 0">
  149. <div class="upload-card">
  150. <h3 class="upload-title">
  151. <span class="title-decoration"></span>
  152. 开户许可证
  153. </h3>
  154. <van-uploader
  155. v-model="accountLicense"
  156. :max-count="1"
  157. class="custom-uploader"
  158. name="accountLicense"
  159. :after-read="afterRead"
  160. >
  161. <template #default>
  162. <div class="upload-item single">
  163. <van-icon name="description" size="32" color="#4d6add" />
  164. <p>上传开户许可证</p>
  165. </div>
  166. </template>
  167. </van-uploader>
  168. </div>
  169. </van-tab>
  170. </van-tabs>
  171. </div>
  172. <!-- 信息审核步骤 -->
  173. <div v-if="currentStep === 2" class="review-section">
  174. <van-collapse v-model="activeCollapse">
  175. <!-- 基础信息 -->
  176. <van-collapse-item title="主体信息" name="1">
  177. <van-cell
  178. title="商户类型"
  179. :value="merchantType === 0 ? '个人商户' : '企业商户'"
  180. />
  181. <template v-if="merchantType === 0">
  182. <van-cell title="姓名" :value="formData.name" />
  183. <van-cell title="身份证号" :value="formData.idNumber" />
  184. <van-cell title="有效期" :value="formData.validDate" />
  185. <van-cell title="手机号" :value="formData.phone" />
  186. <van-cell title="联系人" :value="formData.contactName" />
  187. <van-cell title="手机号" :value="formData.contactPhone" />
  188. </template>
  189. <template v-else>
  190. <van-cell title="企业名称" :value="formData.companyName" />
  191. <van-cell title="营业执照号" :value="formData.licenseNo" />
  192. <van-cell title="注册日期" :value="formData.companyDate" />
  193. <van-cell title="法人姓名" :value="formData.name" />
  194. <van-cell title="法人身份证" :value="formData.idNumber" />
  195. <van-cell title="法人手机号" :value="formData.phone" />
  196. <van-cell title="有效期" :value="formData.validDate" />
  197. <van-cell title="联系人" :value="formData.contactName" />
  198. <van-cell title="联系人手机号" :value="formData.contactPhone" />
  199. </template>
  200. </van-collapse-item>
  201. <!-- 银行信息 -->
  202. <van-collapse-item title="结算信息" name="2">
  203. <van-cell
  204. title="账户类型"
  205. :value="merchantType === 0 ? '个人账户' : '企业账户'"
  206. />
  207. <van-cell
  208. :title="merchantType === 0 ? '银行卡号' : '对公账号'"
  209. :value="formData.bankCardNo"
  210. />
  211. <van-cell
  212. v-if="merchantType === 1"
  213. title="联行号"
  214. :value="formData.bankChannelNo"
  215. />
  216. <van-cell
  217. title="结算方式"
  218. :value="formData.settMode === '1' ? '自动结算' : '手动提现'"
  219. />
  220. <van-cell title="到账时效" value="D1" />
  221. </van-collapse-item>
  222. </van-collapse>
  223. </div>
  224. <!-- 签约确认步骤 -->
  225. <div v-if="currentStep === 3" class="sign-section">
  226. <div class="upload-card">
  227. <h3 class="upload-title">
  228. <span class="title-decoration"></span>
  229. 信息认证状态
  230. </h3>
  231. <!-- 信息认证状态 -->
  232. <div class="audit-status-bar" :class="infoStatusClass">
  233. <div class="status-content">
  234. <van-icon :name="infoStatusIcon" class="status-icon" />
  235. <div class="status-text">
  236. <p class="main-text">{{ infoStatusMainText }}</p>
  237. <p class="sub-text">{{ infoStatusSubText }}</p>
  238. </div>
  239. </div>
  240. <van-button
  241. v-if="infoStatus == 2"
  242. size="small"
  243. type="primary"
  244. plain
  245. @click="handleInfoReupload"
  246. >
  247. 修改信息
  248. </van-button>
  249. </div>
  250. <h3 class="upload-title">
  251. <span class="title-decoration"></span>
  252. 证件审核状态
  253. </h3>
  254. <!-- 审核状态栏 -->
  255. <div class="audit-status-bar" :class="statusClass">
  256. <div class="status-content">
  257. <van-icon :name="statusIcon" class="status-icon" />
  258. <div class="status-text">
  259. <p class="main-text">{{ statusMainText }}</p>
  260. <p class="sub-text">{{ statusSubText }}</p>
  261. </div>
  262. </div>
  263. <van-button
  264. v-if="auditStatus == 2"
  265. size="small"
  266. type="primary"
  267. plain
  268. @click="handleInfoReupload"
  269. >
  270. 上传
  271. </van-button>
  272. </div>
  273. <!-- 签约说明 -->
  274. <div class="sign-notice" v-if="signStatus != 1">
  275. <van-icon name="warning" color="#FF9500" />
  276. <span>请确认所有状态通过后,点击下方按钮完成签约</span>
  277. </div>
  278. <h3 class="upload-title">
  279. <span class="title-decoration"></span>
  280. 签约状态
  281. </h3>
  282. <!-- 签约状态栏 -->
  283. <div class="audit-status-bar" :class="signStatusClass">
  284. <div class="status-content">
  285. <van-icon :name="signStatusIcon" class="status-icon" />
  286. <div class="status-text">
  287. <p class="main-text">{{ signStatusMainText }}</p>
  288. <p class="sub-text">{{ signStatusSubText }}</p>
  289. </div>
  290. </div>
  291. </div>
  292. </div>
  293. </div>
  294. </div>
  295. <!-- 其他步骤内容 -->
  296. <!-- 操作按钮 -->
  297. <div class="action-section">
  298. <!-- 条件显示提示语 -->
  299. <div v-if="currentStep === 0 && merchantType === 1" class="action-notice">
  300. <van-icon name="warning" class="notice-icon" />
  301. <span>请确认上传法人证件信息与营业执照主体一致</span>
  302. </div>
  303. <div class="action-buttons">
  304. <van-button
  305. v-if="currentStep > 0 && currentStep < 3 && auditStatus != 1"
  306. round
  307. class="prev-btn"
  308. @click="currentStep--"
  309. >
  310. 上一步
  311. </van-button>
  312. <van-button
  313. v-if="currentStep == 2 && auditStatus == 1"
  314. round
  315. class="prev-btn"
  316. @click="currentStep--"
  317. >
  318. 上一步
  319. </van-button>
  320. <van-button
  321. v-if="currentStep < 3"
  322. round
  323. type="primary"
  324. class="next-btn"
  325. @click="handleNextStep"
  326. >
  327. 下一步
  328. </van-button>
  329. <van-button
  330. v-if="currentStep == 3 && signStatus != 1"
  331. round
  332. type="primary"
  333. class="next-btn"
  334. @click="handleNextStep"
  335. >
  336. 立即签约
  337. </van-button>
  338. <van-button
  339. v-if="
  340. currentStep == 3 &&
  341. auditStatus == 1 &&
  342. infoStatus == 1 &&
  343. signStatus == 1
  344. "
  345. round
  346. type="primary"
  347. class="next-btn"
  348. @click="updateBankCard"
  349. >
  350. 修改银行卡
  351. </van-button>
  352. </div>
  353. </div>
  354. <!-- 信息确认 ActionSheet -->
  355. <van-action-sheet
  356. v-model:show="showConfirmSheet"
  357. title="信息确认"
  358. :round="false"
  359. class="custom-actionsheet"
  360. >
  361. <!-- 证件信息 -->
  362. <div class="sheet-content" v-if="currentStep === 0">
  363. <van-form @submit="confirmInfo(0)">
  364. <!-- 个人商户表单 -->
  365. <template v-if="merchantType === 0">
  366. <!-- 收款人证件信息-->
  367. <van-cell>
  368. <template #title>
  369. <div class="custom-title">
  370. <span class="blue-line"></span>
  371. <span style="font-size: 16px; color: #333"
  372. >收款人证件信息</span
  373. >
  374. </div>
  375. </template>
  376. </van-cell>
  377. <van-field
  378. v-model="formData.name"
  379. label="姓名"
  380. placeholder="请输入姓名"
  381. required
  382. :rules="[{ required: true, message: '请输入姓名' }]"
  383. />
  384. <van-field
  385. v-model="formData.idNumber"
  386. label="身份证号"
  387. placeholder="请输入身份证号"
  388. :formatter="formatIdCard"
  389. required
  390. :rules="[{ required: true, message: '请输入身份证号' }]"
  391. />
  392. <van-field
  393. v-model="formData.validDate"
  394. label="有效期限"
  395. placeholder="请选择有效期"
  396. readonly
  397. clickable
  398. required
  399. @click="showDatePicker = true"
  400. :rules="[{ required: true, message: '请选择有效期' }]"
  401. />
  402. <van-field
  403. v-model="formData.phone"
  404. label="收款人手机号"
  405. placeholder="收款人手机号"
  406. :formatter="formatPhone"
  407. required
  408. :rules="[
  409. {
  410. required: true,
  411. message: '请输入11位手机号',
  412. validator: (val) =>
  413. /^1[3-9]\d{9}$/.test(val.replace(/\s/g, '')),
  414. },
  415. ]"
  416. />
  417. <!-- 联系人信息 -->
  418. <van-cell>
  419. <template #title>
  420. <div class="custom-title">
  421. <span class="blue-line"></span>
  422. <span style="font-size: 16px; color: #333">联系人信息</span>
  423. </div>
  424. </template>
  425. </van-cell>
  426. <van-field
  427. v-model="formData.contactName"
  428. label="联系人姓名"
  429. placeholder="请输入联系人姓名"
  430. :disabled="joinPayMchNo != null"
  431. :rules="[{ required: true, message: '请输入联系人姓名' }]"
  432. required
  433. />
  434. <van-field
  435. v-model="formData.contactPhone"
  436. label="联系人手机号"
  437. placeholder="请输入联系人手机号"
  438. :formatter="formatPhone"
  439. :disabled="joinPayMchNo != null"
  440. required
  441. :rules="[
  442. {
  443. required: true,
  444. message: '请输入11位手机号',
  445. validator: (val) =>
  446. /^1[3-9]\d{9}$/.test(val.replace(/\s/g, '')),
  447. },
  448. ]"
  449. />
  450. </template>
  451. <!-- 企业商户表单 -->
  452. <template v-else>
  453. <!-- 法人信息 -->
  454. <van-cell>
  455. <template #title>
  456. <div class="custom-title">
  457. <span class="blue-line"></span>
  458. <span style="font-size: 0.45rem; color: #333"
  459. >法人证件信息</span
  460. >
  461. </div>
  462. </template>
  463. </van-cell>
  464. <van-field
  465. v-model="formData.name"
  466. label="法人姓名"
  467. placeholder="请输入法人姓名"
  468. required
  469. :rules="[{ required: true, message: '请输入法人姓名' }]"
  470. />
  471. <van-field
  472. v-model="formData.idNumber"
  473. label="法人身份证"
  474. placeholder="请输入法人身份证"
  475. :rules="[{ required: true, message: '请输入法人身份证' }]"
  476. :formatter="formatIdCard"
  477. required
  478. />
  479. <van-field
  480. v-model="formData.validDate"
  481. label="有效期限"
  482. placeholder="请选择有效期"
  483. :rules="[{ required: true, message: '请选择有效期' }]"
  484. readonly
  485. clickable
  486. required
  487. @click="showDatePicker = true"
  488. />
  489. <van-field
  490. v-model="formData.phone"
  491. label="法人手机号"
  492. placeholder="请输入法人手机号"
  493. :formatter="formatPhone"
  494. required
  495. :rules="[
  496. {
  497. required: true,
  498. message: '请输入11位手机号',
  499. validator: (val) =>
  500. /^1[3-9]\d{9}$/.test(val.replace(/\s/g, '')),
  501. },
  502. ]"
  503. />
  504. <!-- 联系人信息 -->
  505. <van-cell>
  506. <template #title>
  507. <div class="custom-title">
  508. <span class="blue-line"></span>
  509. <span style="font-size: 0.45rem; color: #333"
  510. >联系人信息</span
  511. >
  512. </div>
  513. </template>
  514. </van-cell>
  515. <van-field
  516. v-model="formData.contactName"
  517. label="联系人姓名"
  518. placeholder="请输入联系人姓名"
  519. :rules="[{ required: true, message: '请输入联系人姓名' }]"
  520. required
  521. />
  522. <van-field
  523. v-model="formData.contactPhone"
  524. label="联系人手机号"
  525. placeholder="请输入联系人手机号"
  526. :formatter="formatPhone"
  527. required
  528. :rules="[
  529. {
  530. required: true,
  531. message: '请输入11位手机号',
  532. validator: (val) =>
  533. /^1[3-9]\d{9}$/.test(val.replace(/\s/g, '')),
  534. },
  535. ]"
  536. />
  537. <!-- 营业执照信息 -->
  538. <van-cell>
  539. <template #title>
  540. <div class="custom-title">
  541. <span class="blue-line"></span>
  542. <span style="font-size: 0.45rem; color: #333"
  543. >营业执照信息</span
  544. >
  545. </div>
  546. </template>
  547. </van-cell>
  548. <van-field
  549. v-model="formData.licenseNo"
  550. label="执照编号"
  551. placeholder="请输入营业执照编号"
  552. :rules="[{ required: true, message: '请输入营业执照编号' }]"
  553. required
  554. />
  555. <van-field
  556. v-model="formData.companyName"
  557. label="企业名称"
  558. placeholder="请输入企业全称"
  559. :rules="[{ required: true, message: '请输入企业全称' }]"
  560. required
  561. />
  562. <van-field
  563. v-model="formData.companyDate"
  564. label="注册日期"
  565. placeholder="请选择注册日期"
  566. :rules="[{ required: true, message: '请选择注册日期' }]"
  567. readonly
  568. clickable
  569. required
  570. @click="showCompanyDatePicker = true"
  571. />
  572. </template>
  573. <div class="confirm-buttons">
  574. <van-button
  575. round
  576. block
  577. type="primary"
  578. class="confirm-btn"
  579. native-type="submit"
  580. >
  581. 确认信息
  582. </van-button>
  583. </div>
  584. </van-form>
  585. </div>
  586. <!-- 银行卡信息 -->
  587. <div class="sheet-content" v-if="currentStep === 1">
  588. <van-form @submit="confirmInfo(1)">
  589. <!-- 个人商户表单 -->
  590. <template v-if="merchantType === 0">
  591. <!-- 银行卡信息-->
  592. <van-cell>
  593. <template #title>
  594. <div class="custom-title">
  595. <span class="blue-line"></span>
  596. <span style="font-size: 0.45rem; color: #333"
  597. >银行卡信息</span
  598. >
  599. </div>
  600. </template>
  601. </van-cell>
  602. <van-field
  603. v-model="formData.bankCardNo"
  604. label="银行账号"
  605. placeholder="请输入银行账号"
  606. required
  607. :rules="[{ required: true, message: '请输入银行账号' }]"
  608. />
  609. <van-field label="结算方式" required>
  610. <template #input>
  611. <div class="settlement-container">
  612. <van-radio-group
  613. v-model="formData.settMode"
  614. direction="horizontal"
  615. >
  616. <van-radio name="1" checked-color="#4d6add" icon-size="18px"
  617. >自动结算</van-radio
  618. >
  619. <van-radio name="2" checked-color="#4d6add" icon-size="18px"
  620. >手动提现</van-radio
  621. >
  622. </van-radio-group>
  623. <!-- 新增提示语 -->
  624. <div class="settlement-tip">
  625. <van-icon name="info" color="#999" size="14px" />
  626. <span>24小时内到账</span>
  627. </div>
  628. </div>
  629. </template>
  630. </van-field>
  631. </template>
  632. <!-- 企业商户表单 -->
  633. <template v-else>
  634. <!-- 法人信息 -->
  635. <van-cell>
  636. <template #title>
  637. <div class="custom-title">
  638. <span class="blue-line"></span>
  639. <span style="font-size: 0.45rem; color: #333"
  640. >开户许可证信息</span
  641. >
  642. </div>
  643. </template>
  644. </van-cell>
  645. <van-field
  646. v-model="formData.bankCardNo"
  647. label="对公账号"
  648. placeholder="请输入对公账号"
  649. required
  650. :rules="[{ required: true, message: '请输入对公账号' }]"
  651. />
  652. <van-field
  653. v-model="formData.bankChannelNo"
  654. label="联行号"
  655. placeholder="请输入联行号"
  656. required
  657. :rules="[{ required: true, message: '请输入联行号' }]"
  658. />
  659. <van-field label="结算方式" required>
  660. <template #input>
  661. <div class="settlement-container">
  662. <van-radio-group
  663. v-model="formData.settMode"
  664. direction="horizontal"
  665. >
  666. <van-radio name="1" checked-color="#4d6add" icon-size="18px"
  667. >自动结算</van-radio
  668. >
  669. <van-radio name="2" checked-color="#4d6add" icon-size="18px"
  670. >手动提现</van-radio
  671. >
  672. </van-radio-group>
  673. <!-- 新增提示语 -->
  674. <div class="settlement-tip">
  675. <van-icon name="info" color="#999" size="14px" />
  676. <span>自动结算和手工提现均为次日到账</span>
  677. </div>
  678. </div>
  679. </template>
  680. </van-field>
  681. </template>
  682. <div class="confirm-buttons">
  683. <van-button
  684. round
  685. block
  686. type="primary"
  687. class="confirm-btn"
  688. native-type="submit"
  689. >
  690. 确认信息
  691. </van-button>
  692. </div>
  693. </van-form>
  694. </div>
  695. </van-action-sheet>
  696. <!-- 组合选择器弹窗 -->
  697. <van-popup
  698. v-model:show="showDatePicker"
  699. round
  700. position="bottom"
  701. class="custom-date-picker"
  702. >
  703. <van-date-picker
  704. v-model="validDate"
  705. title="选择日期"
  706. :min-date="minDate"
  707. :max-date="maxDate"
  708. @confirm="idDateConfirm"
  709. />
  710. </van-popup>
  711. <!-- 公司注册日期选择器弹窗 -->
  712. <van-popup
  713. v-model:show="showCompanyDatePicker"
  714. round
  715. position="bottom"
  716. class="custom-date-picker"
  717. >
  718. <van-date-picker
  719. v-model="companyDate"
  720. title="选择日期"
  721. :min-date="minDate"
  722. :max-date="maxDate"
  723. @confirm="companyDateConfirm"
  724. @cancel="showCompanyDatePicker = false"
  725. />
  726. </van-popup>
  727. </div>
  728. </template>
  729. <script>
  730. import {
  731. showConfirmDialog,
  732. showToast,
  733. showFailToast,
  734. showSuccessToast,
  735. } from "vant";
  736. import { getLoginUser } from "../../common/js/utils";
  737. import sHeader from "../../components/SimpleHeader";
  738. import {
  739. idCardRecognition,
  740. createMch,
  741. getJoinPayMch,
  742. uploadPhotos,
  743. updateApproveStatus,
  744. updateMchApproveStatus,
  745. updateMchSignStatus,
  746. altMchSign,
  747. getPhotos,
  748. } from "../../service/purse/index.js";
  749. import { ref, computed, onMounted } from "vue";
  750. import dateUtil from "../../utils/dateUtil";
  751. import router from "../../router";
  752. export default {
  753. components: { sHeader },
  754. setup() {
  755. const user = getLoginUser();
  756. const currentStep = ref(0);
  757. const merchantType = ref(0);
  758. //
  759. const activeCollapse = ref(["1", "2"]);
  760. // 图片信息
  761. const idCardFront = ref([]);
  762. const idCardBack = ref([]);
  763. const businessLicense = ref([]);
  764. const bankCard = ref([]);
  765. const accountLicense = ref([]);
  766. // 企业法人确认
  767. const legalPersonName = ref('');
  768. // 确认信息弹窗
  769. const showConfirmSheet = ref(false);
  770. // 日期选择
  771. const showDatePicker = ref(false);
  772. const showCompanyDatePicker = ref(false);
  773. const minDate = ref(new Date(2000, 0, 1));
  774. const maxDate = ref(new Date(2099, 11, 31));
  775. const companyDate = ref(["2022", "06", "01"]);
  776. // 身份证有效期限
  777. const validDate = ref(["2022", "06", "01"]);
  778. // 信息认证状态(0: 未认证 1: 已认证 2: 认证失败)
  779. const infoStatus = ref(0);
  780. // 信息认证计算属性
  781. const infoStatusClass = computed(() => ({
  782. "audit-status-bar--warning": infoStatus.value === 0,
  783. "audit-status-bar--success": infoStatus.value === 1,
  784. "audit-status-bar--error": infoStatus.value === 2,
  785. }));
  786. const infoStatusIcon = computed(
  787. () =>
  788. ({
  789. 0: "clock",
  790. 1: "passed",
  791. 2: "warning",
  792. }[infoStatus.value])
  793. );
  794. const infoStatusMainText = computed(
  795. () =>
  796. ({
  797. 0: "信息认证中",
  798. 1: "认证成功",
  799. 2: "认证失败",
  800. }[infoStatus.value])
  801. );
  802. const infoStatusSubText = ref("");
  803. // 证照审核状态(0: 审核中 1: 通过 2: 未通过)
  804. const auditStatus = ref(0);
  805. // 计算属性
  806. const statusClass = computed(() => {
  807. return {
  808. "audit-status-bar--success": auditStatus.value === 1,
  809. "audit-status-bar--warning": auditStatus.value === 0,
  810. "audit-status-bar--error": auditStatus.value === 2,
  811. };
  812. });
  813. const statusIcon = computed(() => {
  814. return {
  815. 0: "clock",
  816. 1: "passed",
  817. 2: "warning",
  818. }[auditStatus.value];
  819. });
  820. const statusMainText = computed(() => {
  821. return {
  822. 0: "资料审核中",
  823. 1: "所有资料已通过审核",
  824. 2: "审核未通过",
  825. }[auditStatus.value];
  826. });
  827. const statusSubText = ref("");
  828. // 签约状态(0: 未签约 1: 已签约 2: 签约失败)
  829. const signStatus = ref(0);
  830. const signStatusIcon = computed(() => {
  831. return {
  832. 0: "clock",
  833. 1: "passed",
  834. 2: "warning",
  835. }[signStatus.value];
  836. });
  837. const signStatusClass = computed(() => {
  838. return {
  839. "audit-status-bar--success": signStatus.value === 1,
  840. "audit-status-bar--warning": signStatus.value === 0,
  841. "audit-status-bar--error": signStatus.value === 2,
  842. };
  843. });
  844. const signStatusMainText = computed(() => {
  845. return {
  846. 0: "未签约",
  847. 1: "签约成功",
  848. 2: "签约失败",
  849. }[signStatus.value];
  850. });
  851. const signStatusSubText = computed(() => {
  852. return {
  853. 0: "请完成签约流程",
  854. 1: "签约成功,可前往绑定机器",
  855. 2: "请重新上传符合要求的证件",
  856. }[signStatus.value];
  857. });
  858. // 证照上传状态
  859. const uploadStatus = ref(0);
  860. // 汇聚ID
  861. const joinPayMchID = ref(null);
  862. // 汇聚商户编号
  863. const joinPayMchNo = ref(null);
  864. // 信息
  865. const formData = ref({
  866. // 收款人/法人信息
  867. merchantType: 10, // 商户类型,“0”为个人,“1”为企业
  868. name: "", // 身份证名称
  869. idNumber: "", // 身份证
  870. validDate: "", // 身份证有效期限
  871. phone: "", // 手机号
  872. // 联系人信息
  873. contactName: "", // 联系人姓名
  874. contactPhone: "", // 联系人手机号
  875. // 营业执照信息
  876. licenseNo: "", // 营业执照编号
  877. companyName: "", // 企业名称
  878. companyDate: "", // 企业注册日期
  879. // 银行卡信息
  880. bankName: "", // 银行名称
  881. bankCardNo: "", // 银行卡号
  882. bankCardType: "0", // 银行卡类型,“0”为对公卡,“1”为对私卡
  883. settMode: "1", // 结算方式,“1”为自动结算,“2”为手动提现
  884. // 开户许可证信息
  885. bankChannelNo: "", // 联行号
  886. });
  887. // 提交参数
  888. const submitParam = ref({
  889. adminId: user.id, // 用户ID
  890. altMchName: "", // 收账方名称
  891. altMchNo: "", // 收账方账号
  892. altMerchantType: 10, // 收账方商户类型,10:个人,11:个体工商户,12:企业
  893. // 收款人/法人信息
  894. legalPerson: "", // 法人名称
  895. idCardNo: "", // 身份证
  896. idCardExpiry: "", // 身份证有效期
  897. phoneNo: "", // 法人手机号
  898. // 联系人信息
  899. busiContactName: "", // 业务联系人姓名
  900. busiContactMobileNo: "", // 业务联系人手机
  901. // 银行卡信息
  902. bankAccountType: 1, // 银行卡类型, 4:对公,1:对私
  903. bankAccountName: "", // 银行账户名称
  904. bankAccountNo: "", // 银行账号
  905. bankChannelNo: "", // 联行号
  906. settMode: 1, // 结算方式,“1”为自动结算,“2”为手动提现
  907. settDateType: 1, // 结算周期类型 * 1 工作日,2 自然日,3 月结日; integer(int32) 默认填1
  908. riskDay: 1, // 结算周期; integer(int32) 默认填1
  909. // 营业执照信息
  910. licenseNo: "", // 营业执照编号
  911. licenseExpiry: "", // 营业执照有效期
  912. bindingSteps: 0, // 绑定步骤
  913. });
  914. // 上传证照
  915. const afterRead = async (file, type) => {
  916. try {
  917. const fileData = new FormData();
  918. fileData.append("file", file.file);
  919. fileData.append("adminId", user.id);
  920. fileData.append("imageType", type.name);
  921. const { data } = await idCardRecognition(fileData);
  922. if (data.code === "00000") {
  923. console.log(data.data);
  924. switch (type.name) {
  925. // 身份证人像面
  926. case "idCardFront":
  927. console.log(idCardFront.value);
  928. formData.value.name = data.data.name;
  929. formData.value.idNumber = data.data.idCard;
  930. break;
  931. // 身份证国徽面
  932. case "idCardBack":
  933. if (data.data.idCardEndDate) {
  934. validDate.value = data.data.idCardEndDate.split(".");
  935. formData.value.validDate = validDate.value.join("-");
  936. } else {
  937. // 长期身份证
  938. validDate.value = data.data.idCardStartDate.split(".");
  939. formData.value.validDate = validDate.value.join("-");
  940. }
  941. break;
  942. // 营业执照
  943. case "businessLicense":
  944. formData.value.licenseNo = data.data.businessLicenseNo;
  945. formData.value.companyName = data.data.businessLicenseName;
  946. formData.value.companyDate = dateUtil.formatDate(
  947. data.data.businessLicenseValidDate
  948. );
  949. companyDate.value = formData.value.companyDate.split("-");
  950. legalPersonName.value = data.data.legalPerson;
  951. break;
  952. // 银行卡正面
  953. case "bankCard":
  954. formData.value.bankCardNo = data.data.bankCardNo;
  955. break;
  956. // 开户许可证
  957. case "accountLicense":
  958. formData.value.bankCardNo = data.data.accountNo;
  959. break;
  960. }
  961. }
  962. } catch (error) {
  963. console.log(error);
  964. }
  965. };
  966. // 确认日期选择
  967. const idDateConfirm = () => {
  968. formData.value.validDate = validDate.value.join("-");
  969. showDatePicker.value = false;
  970. };
  971. const companyDateConfirm = () => {
  972. formData.value.companyDate = companyDate.value.join("-");
  973. showCompanyDatePicker.value = false;
  974. };
  975. // 确认信息
  976. const confirmInfo = (value) => {
  977. console.log(formData.value);
  978. showConfirmDialog({
  979. message: "确认信息无误?",
  980. })
  981. .then(async () => {
  982. if (value === 0) {
  983. // 证件信息
  984. if (merchantType.value === 0) {
  985. // 个人
  986. submitParam.value.altMchName = formData.value.name;
  987. submitParam.value.altMerchantType = 10;
  988. submitParam.value.legalPerson = formData.value.name;
  989. submitParam.value.idCardNo = formData.value.idNumber.replace(
  990. /\s/g,
  991. ""
  992. );
  993. submitParam.value.idCardExpiry = formData.value.validDate;
  994. submitParam.value.phoneNo = formData.value.phone.replace(
  995. /\s/g,
  996. ""
  997. );
  998. submitParam.value.busiContactName = formData.value.contactName;
  999. submitParam.value.busiContactMobileNo =
  1000. formData.value.contactPhone.replace(/\s/g, "");
  1001. } else {
  1002. // 企业
  1003. submitParam.value.altMerchantType = 12;
  1004. if (legalPersonName.value != formData.value.name) {
  1005. showToast("法人姓名与营业执照主体不一致!");
  1006. return;
  1007. }
  1008. submitParam.value.legalPerson = formData.value.name;
  1009. submitParam.value.idCardNo = formData.value.idNumber.replace(
  1010. /\s/g,
  1011. ""
  1012. );
  1013. submitParam.value.idCardExpiry = formData.value.validDate;
  1014. submitParam.value.phoneNo = formData.value.phone.replace(
  1015. /\s/g,
  1016. ""
  1017. );
  1018. submitParam.value.busiContactName = formData.value.contactName;
  1019. submitParam.value.busiContactMobileNo =
  1020. formData.value.contactPhone.replace(/\s/g, "");
  1021. submitParam.value.altMchName = formData.value.companyName;
  1022. submitParam.value.licenseNo = formData.value.licenseNo;
  1023. submitParam.value.licenseExpiry = formData.value.companyDate;
  1024. }
  1025. submitParam.value.bindingSteps = 0;
  1026. }
  1027. if (value === 1) {
  1028. // 结算信息
  1029. if (merchantType.value === 0) {
  1030. // 个人
  1031. submitParam.value.bankAccountType = 1;
  1032. submitParam.value.bankAccountName = formData.value.name;
  1033. submitParam.value.bankAccountNo = formData.value.bankCardNo;
  1034. } else {
  1035. // 企业
  1036. submitParam.value.bankAccountType = 4;
  1037. submitParam.value.bankAccountName = formData.value.companyName;
  1038. submitParam.value.bankAccountNo = formData.value.bankCardNo;
  1039. submitParam.value.bankChannelNo = formData.value.bankChannelNo;
  1040. }
  1041. submitParam.value.settMode = formData.value.settMode == "1" ? 1 : 2;
  1042. submitParam.value.bindingSteps = 1;
  1043. }
  1044. try {
  1045. const { data } = await createMch(submitParam.value);
  1046. if (data.code === "00000") {
  1047. currentStep.value++;
  1048. } else {
  1049. showToast(data.message);
  1050. }
  1051. } catch (error) {
  1052. console.log(error);
  1053. }
  1054. console.log("提交参数", submitParam.value);
  1055. showConfirmSheet.value = false;
  1056. })
  1057. .catch(() => {
  1058. return;
  1059. });
  1060. };
  1061. // 回显数据
  1062. const getMchInfo = async () => {
  1063. try {
  1064. const { data } = await getJoinPayMch({ adminId: user.id });
  1065. if (data.code === "00000") {
  1066. joinPayMchID.value = data.data.id;
  1067. if (data.data.altMchNo != null && data.data.altMchNo != "") {
  1068. joinPayMchNo.value = data.data.altMchNo;
  1069. }
  1070. formData.value.merchantType = data.data.altMerchantType;
  1071. if (formData.value.merchantType === 12) {
  1072. merchantType.value = 1;
  1073. }
  1074. formData.value.name = data.data.legalPerson;
  1075. formData.value.idNumber = data.data.idCardNo;
  1076. formData.value.validDate = data.data.idCardExpiry;
  1077. formData.value.phone = data.data.phoneNo;
  1078. formData.value.contactName = data.data.busiContactName;
  1079. formData.value.contactPhone = data.data.busiContactMobileNo;
  1080. formData.value.licenseNo = data.data.licenseNo;
  1081. formData.value.companyName = data.data.bankAccountName;
  1082. formData.value.companyDate = data.data.licenseExpiry;
  1083. formData.value.bankName = data.data.bankAccountName;
  1084. formData.value.bankCardNo = data.data.bankAccountNo;
  1085. formData.value.bankChannelNo = data.data.bankChannelNo;
  1086. formData.value.settMode = data.data.settMode == 1 ? "1" : "2";
  1087. // 步骤
  1088. currentStep.value = data.data.bindingSteps;
  1089. // 认证状态
  1090. switch (data.data.status) {
  1091. case "0":
  1092. // 认证中
  1093. infoStatus.value = 0;
  1094. infoStatusSubText.value = "预计3分钟内完成认证";
  1095. break;
  1096. case "1":
  1097. // 认证成功
  1098. infoStatus.value = 1;
  1099. infoStatusSubText.value = "认证信息已验证通过";
  1100. break;
  1101. case "2":
  1102. // 认证失败
  1103. infoStatus.value = 2;
  1104. infoStatusSubText.value = data.data.bizMsg;
  1105. break;
  1106. }
  1107. // 图片上传状态
  1108. switch (data.data.step) {
  1109. case "0":
  1110. // 未上传
  1111. uploadStatus.value = 0;
  1112. break;
  1113. case "1":
  1114. // 已上传
  1115. uploadStatus.value = 1;
  1116. break;
  1117. }
  1118. // 图片审核状态
  1119. switch (data.data.approveStatus) {
  1120. case "审核中":
  1121. auditStatus.value = 0;
  1122. statusSubText.value = "预计3分钟内完成审核";
  1123. changeApproveStatus();
  1124. break;
  1125. case "审核通过":
  1126. auditStatus.value = 1;
  1127. statusSubText.value = "审核通过";
  1128. break;
  1129. case "审核不通过":
  1130. auditStatus.value = 2;
  1131. statusSubText.value = data.data.approveNote;
  1132. changeApproveStatus();
  1133. break;
  1134. }
  1135. // 签约状态
  1136. switch (data.data.signStatus) {
  1137. case "签约成功":
  1138. // 未签约
  1139. signStatus.value = 1;
  1140. break;
  1141. default:
  1142. // 已签约
  1143. break;
  1144. }
  1145. console.log("回显数据", formData.value);
  1146. }
  1147. } catch (error) {
  1148. console.log(error);
  1149. }
  1150. };
  1151. // 获取图片
  1152. const getUserLicense = async () => {
  1153. try {
  1154. const { data } = await getPhotos({
  1155. adminId: user.id,
  1156. });
  1157. if (data.code === "00000") {
  1158. console.log("图片", data.data);
  1159. if (data.data.idCardFront) {
  1160. idCardFront.value = [
  1161. {
  1162. url: "data:image/jpeg;base64," + data.data.idCardFront,
  1163. isImage: true,
  1164. },
  1165. ];
  1166. }
  1167. if (data.data.idCardBack) {
  1168. idCardBack.value = [
  1169. {
  1170. url: "data:image/jpeg;base64," + data.data.idCardBack,
  1171. isImage: true,
  1172. },
  1173. ];
  1174. }
  1175. if (data.data.bankCard) {
  1176. bankCard.value = [
  1177. {
  1178. url: "data:image/jpeg;base64," + data.data.bankCard,
  1179. isImage: true,
  1180. },
  1181. ];
  1182. }
  1183. if (data.data.businessLicense) {
  1184. businessLicense.value = [
  1185. {
  1186. url: "data:image/jpeg;base64," + data.data.businessLicense,
  1187. isImage: true,
  1188. },
  1189. ];
  1190. }
  1191. if (data.data.accountLicense) {
  1192. accountLicense.value = [
  1193. {
  1194. url: "data:image/jpeg;base64," + data.data.accountLicense,
  1195. isImage: true,
  1196. },
  1197. ];
  1198. }
  1199. }
  1200. } catch (error) {
  1201. console.log(error);
  1202. }
  1203. };
  1204. onMounted(async () => {
  1205. await getMchInfo();
  1206. await getUserLicense();
  1207. if (currentStep.value === 3) {
  1208. changeApproveStatus();
  1209. changeMchApproveStatus();
  1210. changeSignStatus();
  1211. }
  1212. });
  1213. const handleNextStep = () => {
  1214. if (currentStep.value === 0) {
  1215. // 先检查是否上传证件照
  1216. if (merchantType.value === 0) {
  1217. if (idCardFront.value.length === 0 || idCardBack.value.length === 0) {
  1218. showToast("请先上传相关证照");
  1219. return;
  1220. }
  1221. } else {
  1222. if (businessLicense.value.length === 0) {
  1223. showToast("请先上传相关证照");
  1224. return;
  1225. }
  1226. }
  1227. showConfirmSheet.value = true;
  1228. }
  1229. if (currentStep.value === 1) {
  1230. // 先检查是否银行卡或者开户开户许可证
  1231. if (merchantType.value === 0) {
  1232. if (bankCard.value.length === 0) {
  1233. showToast("请先上传银行卡");
  1234. return;
  1235. }
  1236. } else {
  1237. if (accountLicense.value.length === 0) {
  1238. showToast("请先上传开户许可证");
  1239. return;
  1240. }
  1241. }
  1242. showConfirmSheet.value = true;
  1243. }
  1244. if (currentStep.value === 2) {
  1245. showConfirmDialog({
  1246. message: "请再次确认信息无误?",
  1247. })
  1248. .then(async () => {
  1249. // 初次提交
  1250. submitParam.value.bindingSteps = 2;
  1251. try {
  1252. const { data } = await createMch(submitParam.value);
  1253. if (data.code === "00000") {
  1254. // 提交成功,看图片是否上传
  1255. const params = {
  1256. id: joinPayMchID.value,
  1257. adminId: user.id,
  1258. altMerchantType: formData.value.merchantType,
  1259. status: "0",
  1260. };
  1261. if (uploadStatus.value === 1 && auditStatus.value === 1) {
  1262. // 上传了,调用修改接口
  1263. params.status = "1";
  1264. }
  1265. try {
  1266. const { data } = await uploadPhotos(params);
  1267. if (data.code === "00000") {
  1268. // 上传成功
  1269. uploadStatus.value = 1;
  1270. auditStatus.value = 0;
  1271. statusSubText.value = "预计3分钟内完成审核";
  1272. } else {
  1273. showToast(data.message);
  1274. }
  1275. } catch (error) {
  1276. console.log(error);
  1277. }
  1278. infoStatus.value = 0;
  1279. infoStatusSubText.value = "预计3分钟内完成认证";
  1280. currentStep.value++;
  1281. } else {
  1282. showToast(data.message);
  1283. }
  1284. } catch (error) {
  1285. console.log(error);
  1286. }
  1287. })
  1288. .catch(() => {
  1289. return;
  1290. });
  1291. }
  1292. if (currentStep.value === 3) {
  1293. if (infoStatus.value != 1) {
  1294. showToast("请确认认证通过");
  1295. return;
  1296. }
  1297. if (auditStatus.value != 1) {
  1298. showToast("请确认证件审核通过");
  1299. return;
  1300. }
  1301. showConfirmDialog({
  1302. message: "确认签约?",
  1303. })
  1304. .then(async () => {
  1305. // 签约
  1306. try {
  1307. const { data } = await altMchSign({ id: joinPayMchID.value });
  1308. if (data.code === "00000") {
  1309. showSuccessToast("签约成功");
  1310. setTimeout(() => {
  1311. router.go(0);
  1312. }, 1000);
  1313. } else {
  1314. showFailToast(data.message);
  1315. }
  1316. } catch (error) {
  1317. console.error("请求发生错误:", error);
  1318. }
  1319. })
  1320. .catch(() => {
  1321. return;
  1322. });
  1323. }
  1324. };
  1325. // 更新图片审核情况
  1326. const changeApproveStatus = async () => {
  1327. const { data } = await updateApproveStatus({ id: joinPayMchID.value });
  1328. if (data.code === "00000") {
  1329. if (data.data === "P1000") {
  1330. auditStatus.value = 1;
  1331. statusSubText.value = "审核通过";
  1332. }
  1333. }
  1334. };
  1335. // 更新商户认证状态
  1336. const changeMchApproveStatus = async () => {
  1337. const { data } = await updateMchApproveStatus({ id: joinPayMchID.value });
  1338. if (data.code === "00000") {
  1339. if (data.data === "P1000") {
  1340. auditStatus.value = 1;
  1341. statusSubText.value = "审核通过";
  1342. }
  1343. }
  1344. };
  1345. // 更新签约状态
  1346. const changeSignStatus = async () => {
  1347. const { data } = await updateMchSignStatus({ id: joinPayMchID.value });
  1348. if (data.code === "00000") {
  1349. if (data.data === "P1000") {
  1350. auditStatus.value = 1;
  1351. statusSubText.value = "审核通过";
  1352. }
  1353. }
  1354. };
  1355. // 跳转修改认证信息
  1356. const handleInfoReupload = () => {
  1357. currentStep.value = 0;
  1358. };
  1359. // 修改银行卡
  1360. const updateBankCard = () => {
  1361. currentStep.value = 1;
  1362. };
  1363. const handlePrevStep = () => {
  1364. if (currentStep.value > 0) currentStep.value--;
  1365. };
  1366. // 格式化身份证号码
  1367. const formatIdCard = (value) => {
  1368. // 步骤1:过滤非法字符(保留数字和X)
  1369. let val = value.replace(/[^\dXx]/g, "");
  1370. // 步骤2:自动大写转换
  1371. val = val.toUpperCase();
  1372. // 步骤3:智能分段(前6位+8位+4位)
  1373. const parts = [];
  1374. if (val.length > 6) {
  1375. parts.push(val.substr(0, 6));
  1376. val = val.substr(6);
  1377. }
  1378. if (val.length > 8) {
  1379. parts.push(val.substr(0, 8));
  1380. val = val.substr(8);
  1381. }
  1382. parts.push(val);
  1383. // 步骤4:组合分段并限制最大长度
  1384. return parts.join(" ").substr(0, 21);
  1385. };
  1386. // 格式化手机
  1387. const formatPhone = (value) => {
  1388. // 1. 去除非数字字符并截取前11位
  1389. const phone = value.replace(/\D/g, "").slice(0, 11);
  1390. // 2. 按 3-4-4 格式添加空格
  1391. return phone.replace(/(\d{3})(\d{0,4})(\d{0,4})/, (_, $1, $2, $3) => {
  1392. let formatted = $1;
  1393. if ($2) formatted += ` ${$2}`;
  1394. if ($3) formatted += ` ${$3}`;
  1395. return formatted;
  1396. });
  1397. };
  1398. return {
  1399. // 响应式数据
  1400. currentStep,
  1401. merchantType,
  1402. idCardFront,
  1403. idCardBack,
  1404. businessLicense,
  1405. bankCard,
  1406. accountLicense,
  1407. formData,
  1408. minDate,
  1409. maxDate,
  1410. companyDate,
  1411. validDate,
  1412. activeCollapse,
  1413. auditStatus,
  1414. statusClass,
  1415. statusIcon,
  1416. statusMainText,
  1417. statusSubText,
  1418. infoStatusClass,
  1419. infoStatusIcon,
  1420. infoStatusMainText,
  1421. infoStatusSubText,
  1422. infoStatus,
  1423. signStatus,
  1424. signStatusClass,
  1425. signStatusIcon,
  1426. signStatusMainText,
  1427. signStatusSubText,
  1428. joinPayMchNo,
  1429. // 方法
  1430. handleNextStep,
  1431. handlePrevStep,
  1432. afterRead,
  1433. formatIdCard,
  1434. formatPhone,
  1435. idDateConfirm,
  1436. confirmInfo,
  1437. companyDateConfirm,
  1438. handleInfoReupload,
  1439. updateBankCard,
  1440. // 弹窗
  1441. showConfirmSheet,
  1442. showDatePicker,
  1443. showCompanyDatePicker,
  1444. };
  1445. },
  1446. };
  1447. </script>
  1448. <style lang="less" scoped>
  1449. .bind-page {
  1450. background: #f8f9ff;
  1451. min-height: 100vh;
  1452. display: flex;
  1453. flex-direction: column;
  1454. }
  1455. .main-content {
  1456. flex: 1;
  1457. overflow-y: auto;
  1458. }
  1459. .main-content::-webkit-scrollbar {
  1460. width: 6px;
  1461. background: #f1f1f1;
  1462. }
  1463. .main-content::-webkit-scrollbar-thumb {
  1464. background: #c1c1c1;
  1465. border-radius: 3px;
  1466. }
  1467. .step-container {
  1468. background: white;
  1469. padding: 15px;
  1470. margin: 10px;
  1471. border-radius: 12px;
  1472. box-shadow: 0 2px 8px rgba(77, 106, 221, 0.05);
  1473. :deep(.van-step__title) {
  1474. font-size: 0.35rem;
  1475. }
  1476. }
  1477. .card-section {
  1478. margin: 10px;
  1479. }
  1480. .upload-card {
  1481. background: white;
  1482. border-radius: 0 0 12px 12px;
  1483. padding: 20px;
  1484. box-shadow: 0 4px 12px rgba(77, 106, 221, 0.08);
  1485. .upload-title {
  1486. // color: #4d6add;
  1487. font-size: 16px;
  1488. // margin-bottom: 15px;
  1489. position: relative;
  1490. padding-left: 12px;
  1491. /* 留出装饰条位置 */
  1492. .title-decoration {
  1493. position: absolute;
  1494. left: 0;
  1495. top: 55%;
  1496. transform: translateY(-50%);
  1497. width: 3px;
  1498. height: 16px;
  1499. background: #4d6add;
  1500. border-radius: 2px;
  1501. }
  1502. }
  1503. }
  1504. .upload-group {
  1505. display: grid;
  1506. grid-template-columns: 1.2fr 1fr;
  1507. gap: 10px;
  1508. margin-bottom: 15px;
  1509. }
  1510. .upload-item {
  1511. border: 2px dashed #e0e3ff;
  1512. border-radius: 10px;
  1513. padding: 20px;
  1514. text-align: center;
  1515. transition: all 0.3s;
  1516. width: 3rem;
  1517. p {
  1518. color: #666;
  1519. margin-top: 8px;
  1520. font-size: 12px;
  1521. }
  1522. &.single {
  1523. grid-column: span 2;
  1524. }
  1525. &:active {
  1526. border-color: #4d6add;
  1527. background: rgba(77, 106, 221, 0.05);
  1528. }
  1529. }
  1530. .custom-uploader :deep(.van-uploader__preview-image) {
  1531. width: 4rem !important;
  1532. height: 2.8rem !important;
  1533. border-radius: 6px;
  1534. }
  1535. .custom-uploader :deep(.van-uploader__preview) {
  1536. width: 4rem !important;
  1537. height: 100% !important;
  1538. margin: 0 !important;
  1539. }
  1540. /* 信息审核样式 */
  1541. .review-section {
  1542. padding: 12px;
  1543. .van-collapse-item__content {
  1544. padding: 0;
  1545. }
  1546. .van-cell {
  1547. background: #f8f9ff;
  1548. margin: 4px 0;
  1549. border-radius: 6px;
  1550. }
  1551. }
  1552. .sign-section {
  1553. margin: 10px;
  1554. .audit-status-bar {
  1555. background: #f8f9ff;
  1556. border-radius: 8px;
  1557. padding: 16px;
  1558. margin: 20px 10px;
  1559. display: flex;
  1560. justify-content: space-between;
  1561. align-items: center;
  1562. border: 1px solid transparent;
  1563. .status-content {
  1564. display: flex;
  1565. align-items: center;
  1566. gap: 12px;
  1567. .status-icon {
  1568. font-size: 22px;
  1569. }
  1570. .status-text {
  1571. line-height: 1.4;
  1572. .main-text {
  1573. color: #333;
  1574. font-weight: 500;
  1575. font-size: 14px;
  1576. }
  1577. .sub-text {
  1578. color: #666;
  1579. font-size: 12px;
  1580. }
  1581. }
  1582. }
  1583. // 不同状态样式
  1584. &--success {
  1585. border-color: #38b48d;
  1586. background: #e8faf0;
  1587. .status-icon {
  1588. color: #38b48d;
  1589. }
  1590. }
  1591. &--warning {
  1592. border-color: #ff9500;
  1593. background: #fff4e8;
  1594. .status-icon {
  1595. color: #ff9500;
  1596. }
  1597. }
  1598. &--error {
  1599. border-color: #ff4d4f;
  1600. background: #ffecec;
  1601. .status-icon {
  1602. color: #ff4d4f;
  1603. }
  1604. }
  1605. }
  1606. .sign-notice {
  1607. margin-top: 20px;
  1608. padding: 12px;
  1609. background: #fffbe8;
  1610. border-radius: 6px;
  1611. color: #ff9500;
  1612. font-size: 13px;
  1613. display: flex;
  1614. align-items: center;
  1615. gap: 8px;
  1616. .van-icon {
  1617. flex-shrink: 0;
  1618. }
  1619. }
  1620. }
  1621. .preview-grid {
  1622. display: grid;
  1623. grid-template-columns: repeat(2, 1fr);
  1624. gap: 10px;
  1625. padding: 8px;
  1626. .preview-item {
  1627. position: relative;
  1628. border-radius: 8px;
  1629. overflow: hidden;
  1630. box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
  1631. .van-image {
  1632. width: 100%;
  1633. height: 120px;
  1634. }
  1635. .file-name {
  1636. position: absolute;
  1637. bottom: 0;
  1638. width: 100%;
  1639. padding: 4px;
  1640. background: rgba(0, 0, 0, 0.6);
  1641. color: white;
  1642. font-size: 12px;
  1643. text-align: center;
  1644. }
  1645. }
  1646. }
  1647. /* 固定底部容器 */
  1648. .action-section {
  1649. position: sticky;
  1650. bottom: 0;
  1651. left: 0;
  1652. right: 0;
  1653. background: #ffffff;
  1654. padding: 12px 16px;
  1655. box-shadow: 0 -4px 12px rgba(0, 0, 0, 0.05);
  1656. z-index: 100;
  1657. }
  1658. /* 提示语样式 */
  1659. .action-notice {
  1660. display: flex;
  1661. align-items: center;
  1662. margin-bottom: 12px;
  1663. padding: 8px 12px;
  1664. background: #fffbe8;
  1665. border-radius: 6px;
  1666. color: #ed6a0c;
  1667. font-size: 13px;
  1668. line-height: 1.5;
  1669. animation: slideUp 0.3s ease;
  1670. }
  1671. .notice-icon {
  1672. margin-right: 6px;
  1673. font-size: 16px;
  1674. flex-shrink: 0;
  1675. }
  1676. /* 按钮容器 */
  1677. .action-buttons {
  1678. display: flex;
  1679. gap: 10px;
  1680. .prev-btn {
  1681. flex: 2;
  1682. border-color: #4d6add;
  1683. color: #4d6add;
  1684. margin: 0 10px;
  1685. }
  1686. .next-btn {
  1687. flex: 2;
  1688. background: #4d6add;
  1689. margin: 0 10px;
  1690. }
  1691. :deep(.van-button__text) {
  1692. font-size: 16px;
  1693. }
  1694. }
  1695. /* 主要内容区域需要添加底部padding防遮挡 */
  1696. // .main-content {
  1697. // // padding-bottom: 10px;
  1698. // /* 根据实际高度调整 */
  1699. // }
  1700. /* 动画效果 */
  1701. @keyframes slideUp {
  1702. from {
  1703. transform: translateY(20px);
  1704. opacity: 0;
  1705. }
  1706. to {
  1707. transform: translateY(0);
  1708. opacity: 1;
  1709. }
  1710. }
  1711. /* 自定义 ActionSheet 样式 */
  1712. :deep(.van-action-sheet) {
  1713. border-radius: 16px 16px 0 0;
  1714. overflow: visible;
  1715. .van-action-sheet__header {
  1716. font-size: 18px;
  1717. color: #4d6add;
  1718. font-weight: 500;
  1719. padding: 18px 16px;
  1720. background: linear-gradient(to bottom, #f8f9ff, white 60%);
  1721. }
  1722. }
  1723. .sheet-content {
  1724. padding: 0 16px 20px;
  1725. max-height: 70vh;
  1726. // overflow-y: auto;
  1727. .van-cell {
  1728. background: #f8f9ff;
  1729. margin: 8px 0;
  1730. border-radius: 8px;
  1731. &::after {
  1732. display: none;
  1733. }
  1734. &__title {
  1735. flex: none;
  1736. width: 80px;
  1737. }
  1738. }
  1739. /* 自定义标题样式 */
  1740. .custom-title {
  1741. display: flex;
  1742. align-items: center;
  1743. padding: 5px 0;
  1744. }
  1745. .blue-line {
  1746. display: inline-block;
  1747. width: 4px;
  1748. height: 16px;
  1749. background: #4d6add;
  1750. margin-right: 8px;
  1751. border-radius: 2px;
  1752. }
  1753. .van-field {
  1754. margin: 12px 0;
  1755. background: #f8f9ff;
  1756. border-radius: 8px;
  1757. padding: 8px 16px;
  1758. :deep(.van-field__label) {
  1759. width: 80px;
  1760. color: #666;
  1761. }
  1762. :deep(.van-field__control) {
  1763. color: #333;
  1764. font-weight: 500;
  1765. }
  1766. }
  1767. /* 结算方式容器 */
  1768. .settlement-container {
  1769. display: flex;
  1770. flex-direction: column;
  1771. gap: 8px;
  1772. width: 100%;
  1773. }
  1774. /* 提示语样式 */
  1775. .settlement-tip {
  1776. display: flex;
  1777. align-items: center;
  1778. color: #999;
  1779. font-size: 12px;
  1780. /* 对齐单选按钮 */
  1781. line-height: 1.4;
  1782. .van-icon {
  1783. margin-right: 4px;
  1784. }
  1785. }
  1786. }
  1787. .confirm-buttons {
  1788. padding: 15px 0;
  1789. .confirm-btn {
  1790. background: #4d6add;
  1791. border: none;
  1792. font-size: 16px;
  1793. &:active {
  1794. opacity: 0.9;
  1795. }
  1796. }
  1797. }
  1798. .custom-date-picker {
  1799. width: 100%;
  1800. }
  1801. /* 调整列宽 */
  1802. .year-column {
  1803. width: 35% !important;
  1804. }
  1805. .month-column {
  1806. width: 30% !important;
  1807. }
  1808. .day-column {
  1809. width: 35% !important;
  1810. }
  1811. /* 长期选项样式 */
  1812. .van-picker-column__item--longterm {
  1813. color: #1989fa;
  1814. font-weight: bold;
  1815. }
  1816. /* 适配移动端 */
  1817. @media (max-width: 480px) {
  1818. .upload-item {
  1819. padding: 15px;
  1820. }
  1821. .upload-group {
  1822. gap: 8px;
  1823. }
  1824. .sheet-content {
  1825. padding: 0 12px 20px;
  1826. .van-cell,
  1827. .van-field {
  1828. margin: 6px 0;
  1829. }
  1830. }
  1831. .settlement-tip {
  1832. font-size: 11px;
  1833. }
  1834. :deep(.van-action-sheet__header) {
  1835. padding: 14px 12px;
  1836. font-size: 16px;
  1837. }
  1838. }
  1839. </style>