index.vue 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388
  1. <template>
  2. <div v-loading="pageLoading" class="app-container" :element-loading-text="loadingText">
  3. <el-tabs v-model="activeTab" class="account-tabs" type="card">
  4. <el-tab-pane label="账户概览" name="overview">
  5. <AccountOverview ref="overviewRef" :enterprise-id="currentEnterpriseId" @refresh="handleOverviewRefresh"
  6. @goTab="handleGoTab" />
  7. </el-tab-pane>
  8. <!-- <el-tab-pane label="转账授权签约" name="authorize">
  9. <div class="tab-content">
  10. <el-card>
  11. <template #header>
  12. <div class="card-header">
  13. <span>转账授权签约</span>
  14. </div>
  15. </template>
  16. <el-form ref="authorizeFormRef" :model="authorizeForm" :rules="authorizeRules" label-width="120px">
  17. <el-form-item label="企业ID" prop="enterprise_id" v-show="!currentEnterpriseId">
  18. <el-input v-model="authorizeForm.enterprise_id" placeholder="请输入企业ID" :disabled="!!currentEnterpriseId" />
  19. </el-form-item>
  20. <el-form-item>
  21. <el-button v-hasPerm="['module_payment:account:authorize']" type="primary" :loading="authorizeLoading"
  22. @click="handleAuthorize">
  23. 申请签约
  24. </el-button>
  25. <el-button @click="handleAuthorizeReset">重置</el-button>
  26. </el-form-item>
  27. </el-form>
  28. <div v-if="authorizeResult.sign_url" class="authorize-result">
  29. <el-alert title="签约链接已生成,请在支付宝中完成签约" type="success" :closable="false">
  30. <template #default>
  31. <el-link :href="authorizeResult.sign_url" target="_blank" type="primary">
  32. 点击前往签约 →
  33. </el-link>
  34. </template>
  35. </el-alert>
  36. </div>
  37. </el-card>
  38. </div>
  39. </el-tab-pane> -->
  40. <!-- <el-tab-pane label="开通资金专户" name="create">
  41. <div class="tab-content">
  42. <el-card>
  43. <template #header>
  44. <div class="card-header">
  45. <span>开通资金专户</span>
  46. <el-tag v-if="authorizeStatus !== 'AUTHORIZED'" type="danger">
  47. 请先完成转账授权签约
  48. </el-tag>
  49. </div>
  50. </template>
  51. <el-form
  52. ref="createFormRef"
  53. :model="createForm"
  54. :rules="createRules"
  55. label-width="140px"
  56. >
  57. <el-form-item label="企业ID" prop="enterprise_id">
  58. <el-input
  59. v-model="createForm.enterprise_id"
  60. placeholder="请输入企业ID"
  61. :disabled="!!currentEnterpriseId"
  62. />
  63. </el-form-item>
  64. <el-form-item label="账户类型" prop="account_type">
  65. <el-select v-model="createForm.account_type" placeholder="请选择账户类型">
  66. <el-option label="收支全能户" value="ALL" />
  67. <el-option label="收入户" value="INCOME" />
  68. <el-option label="支出户" value="DISBURSE" />
  69. </el-select>
  70. </el-form-item>
  71. <el-form-item label="场景类型" prop="scene">
  72. <el-select v-model="createForm.scene" placeholder="请选择场景类型">
  73. <el-option label="ToB转账" value="B2B_TRANS" />
  74. <el-option label="企业信用" value="ENT_CREDIT" />
  75. </el-select>
  76. </el-form-item>
  77. <el-form-item label="备注" prop="remark">
  78. <el-input v-model="createForm.remark" type="textarea" placeholder="请输入备注" />
  79. </el-form-item>
  80. <el-form-item>
  81. <el-button
  82. v-hasPerm="['module_payment:account:create']"
  83. type="primary"
  84. :loading="createLoading"
  85. :disabled="authorizeStatus !== 'AUTHORIZED'"
  86. @click="handleCreate"
  87. >
  88. 开通专户
  89. </el-button>
  90. <el-button @click="handleCreateReset">重置</el-button>
  91. </el-form-item>
  92. </el-form>
  93. <div v-if="createResult.account_book_id" class="create-result">
  94. <el-alert title="资金专户开通成功" type="success" :closable="false">
  95. <template #default>
  96. <div>专户ID: {{ createResult.account_book_id }}</div>
  97. </template>
  98. </el-alert>
  99. </div>
  100. </el-card>
  101. </div>
  102. </el-tab-pane> -->
  103. <el-tab-pane label="账户充值" name="deposit">
  104. <div class="tab-content">
  105. <el-card>
  106. <template #header>
  107. <div class="card-header">
  108. <span>资金专户充值</span>
  109. <el-tag v-if="!accountInfo.account_book_id" type="danger">
  110. 请先开通资金专户
  111. </el-tag>
  112. <!-- <el-tag v-else-if="accountInfo.status !== 'AUTHORIZED'" type="warning">
  113. 资金专户状态异常
  114. </el-tag> -->
  115. </div>
  116. </template>
  117. <el-form ref="depositFormRef" :model="depositForm" :rules="depositRules" label-width="140px">
  118. <!-- <el-form-item label="企业ID" prop="enterprise_id">
  119. <el-input v-model="currentEnterpriseId" placeholder="请输入企业ID" :disabled="!!currentEnterpriseId" />
  120. </el-form-item> -->
  121. <!-- <el-form-item label="资金账户" prop="account_book_id">
  122. <el-input v-model="depositForm.account_book_id" :placeholder="accountInfo.account_book_id || '请先开通资金账户'"
  123. :disabled="!!accountInfo.account_book_id" />
  124. </el-form-item> -->
  125. <el-form-item label="充值金额" prop="amount">
  126. <el-input-number v-model="depositForm.amount" :min="0.00" :precision="2" :controls="false"
  127. placeholder="请输入充值金额" style="width: 300px" />
  128. <span class="ml-2">元</span>
  129. </el-form-item>
  130. <!-- <el-form-item label="备注" prop="remark">
  131. <el-input v-model="depositForm.remark" type="textarea" placeholder="请输入备注" />
  132. </el-form-item> -->
  133. <el-form-item>
  134. <el-button v-hasPerm="['module_payment:account:deposit']" type="primary" :loading="depositLoading"
  135. :disabled="!accountInfo.account_book_id || accountInfo.status === 'AUTHORIZED'" @click="handleDeposit">
  136. 发起充值
  137. </el-button>
  138. <el-button @click="handleDepositReset">重置</el-button>
  139. </el-form-item>
  140. </el-form>
  141. <div v-if="depositResult.url" class="deposit-result">
  142. <el-alert title="充值页面已生成,请在支付宝中完成支付" type="success" :closable="false">
  143. <template #default>
  144. <el-link :href="depositResult.url" target="_blank" type="primary">
  145. 点击前往充值 →
  146. </el-link>
  147. </template>
  148. </el-alert>
  149. </div>
  150. </el-card>
  151. <!-- <el-card class="mt-4">
  152. <template #header>
  153. <span>充值记录</span>
  154. </template>
  155. <el-table :data="depositList" border stripe>
  156. <el-table-column prop="out_biz_no" label="订单号" min-width="180" />
  157. <el-table-column prop="amount" label="充值金额" min-width="100">
  158. <template #default="{ row }">
  159. ¥{{ row.amount }}
  160. </template>
  161. </el-table-column>
  162. <el-table-column prop="status" label="状态" min-width="100">
  163. <template #default="{ row }">
  164. <el-tag :type="getDepositStatusType(row.status)">
  165. {{ row.status }}
  166. </el-tag>
  167. </template>
  168. </el-table-column>
  169. <el-table-column prop="created_time" label="创建时间" min-width="160" />
  170. </el-table>
  171. </el-card> -->
  172. </div>
  173. </el-tab-pane>
  174. <el-tab-pane label="转账管理" name="transfer">
  175. <div class="tab-content">
  176. <el-card>
  177. <template #header>
  178. <div class="card-header">
  179. <span>发起转账</span>
  180. <div>
  181. <el-tag v-if="!accountInfo.account_book_id" type="danger" class="ml-2">
  182. 请先开通资金专户
  183. </el-tag>
  184. <el-tag v-else-if="accountInfo.balance <= 0" type="warning" class="ml-2">
  185. 账户余额不足,请先充值
  186. </el-tag>
  187. </div>
  188. </div>
  189. </template>
  190. <el-form ref="transferFormRef" :model="transferForm" :rules="transferRules" label-width="140px">
  191. <!-- <el-form-item label="企业ID" prop="enterprise_id">
  192. <el-input v-model="currentEnterpriseId" placeholder="请输入企业ID"
  193. :disabled="!!currentEnterpriseId" />
  194. </el-form-item>
  195. <el-form-item label="付款资金账户" prop="account_book_id">
  196. <el-input v-model="transferForm.account_book_id"
  197. :placeholder="accountInfo.account_book_id || '请先开通资金账户'" :disabled="!!accountInfo.account_book_id" />
  198. </el-form-item> -->
  199. <el-form-item label="转账金额" prop="amount">
  200. <el-input-number v-model="transferForm.amount" :min="0.00" :precision="2" :controls="false"
  201. placeholder="请输入转账金额" style="width: 300px" />
  202. <span class="ml-2">元</span>
  203. </el-form-item>
  204. <el-form-item label="转账标题" prop="order_title">
  205. <el-input v-model="transferForm.order_title" placeholder="请输入转账标题" />
  206. </el-form-item>
  207. <el-form-item label="收款方类型" prop="payee_info.identity_type">
  208. <el-select v-model="transferForm.payee_info.identity_type" placeholder="请选择收款方类型">
  209. <el-option label="支付宝账户" value="alipay" />
  210. <el-option label="银行卡" value="bank" />
  211. <!-- <el-option label="资金专户" value="book" /> -->
  212. </el-select>
  213. </el-form-item>
  214. <el-form-item label="收款方真实姓名" prop="payee_info.name">
  215. <el-input v-model="transferForm.payee_info.name" placeholder="请输入收款方姓名" />
  216. </el-form-item>
  217. <el-form-item :label="transferForm.payee_info.identity_type === 'alipay' ? '收款方支付宝账号' : '收款方银行卡号'" prop="payee_info.identity">
  218. <el-input v-model="transferForm.payee_info.identity" :placeholder="transferForm.payee_info.identity_type === 'alipay' ? '请输入收款方支付宝账号' : '请输入收款方银行卡号'" />
  219. </el-form-item>
  220. <template v-if="transferForm.payee_info.identity_type === 'bank'">
  221. <el-form-item label="账户类型" prop="payee_info.bankcard_ext_info.account_type">
  222. <el-select v-model="transferForm.payee_info.bankcard_ext_info!.account_type" placeholder="请选择账户类型">
  223. <el-option label="公司账户" value="1" />
  224. <el-option label="个人账户" value="2" />
  225. </el-select>
  226. </el-form-item>
  227. <el-form-item label="银行名称" prop="payee_info.bankcard_ext_info.inst_name">
  228. <el-input v-model="transferForm.payee_info.bankcard_ext_info!.inst_name" placeholder="请输入银行名称" />
  229. </el-form-item>
  230. <el-form-item label="开户省份" prop="payee_info.bankcard_ext_info.inst_province">
  231. <el-input v-model="transferForm.payee_info.bankcard_ext_info!.inst_province" placeholder="请输入开户省份" />
  232. </el-form-item>
  233. <el-form-item label="开户城市" prop="payee_info.bankcard_ext_info.inst_city">
  234. <el-input v-model="transferForm.payee_info.bankcard_ext_info!.inst_city" placeholder="请输入开户城市" />
  235. </el-form-item>
  236. <el-form-item label="支行名称" prop="payee_info.bankcard_ext_info.inst_branch_name">
  237. <el-input v-model="transferForm.payee_info.bankcard_ext_info!.inst_branch_name"
  238. placeholder="请输入支行名称" />
  239. </el-form-item>
  240. <el-form-item label="联行号" prop="payee_info.bankcard_ext_info.bank_code">
  241. <el-input v-model="transferForm.payee_info.bankcard_ext_info!.bank_code" placeholder="请输入联行号" />
  242. </el-form-item>
  243. </template>
  244. <el-form-item label="备注" prop="remark">
  245. <el-input v-model="transferForm.remark" type="textarea" placeholder="请输入备注" />
  246. </el-form-item>
  247. <el-form-item>
  248. <el-button v-hasPerm="['module_payment:account:transfer']" type="primary" :loading="transferLoading"
  249. :disabled="!accountInfo.account_book_id || accountInfo.balance <= 0" @click="handleTransfer">
  250. 发起转账
  251. </el-button>
  252. <el-button @click="handleTransferReset">重置</el-button>
  253. <el-button v-hasPerm="['module_payment:account:transfer']" type="primary" @click="openBatchTransferDialog">
  254. 批量转账
  255. </el-button>
  256. </el-form-item>
  257. </el-form>
  258. </el-card>
  259. <el-card class="mt-4">
  260. <template #header>
  261. <div class="card-header">
  262. <span>转账记录</span>
  263. </div>
  264. </template>
  265. <div class="mb-4">
  266. <el-form :inline="true" :model="transferSearchForm">
  267. <el-form-item label="订单号">
  268. <el-input v-model="transferSearchForm.out_biz_no" placeholder="请输入订单号" clearable />
  269. </el-form-item>
  270. <el-form-item label="状态">
  271. <el-select v-model="transferSearchForm.status" placeholder="请选择状态" clearable>
  272. <el-option label="处理中" value="DEALING" />
  273. <el-option label="成功" value="SUCCESS" />
  274. <el-option label="失败" value="FAIL" />
  275. <el-option label="退票" value="REFUND" />
  276. </el-select>
  277. </el-form-item>
  278. <el-form-item>
  279. <el-button type="primary" @click="handleTransferSearch">查询</el-button>
  280. <el-button @click="handleTransferSearchReset">重置</el-button>
  281. <el-button icon="Refresh" @click="handleTransferSearchReset">刷新</el-button>
  282. </el-form-item>
  283. </el-form>
  284. </div>
  285. <el-table :data="transferList" border stripe v-loading="transferListLoading">
  286. <template #empty>
  287. <el-empty description="暂无数据" />
  288. </template>
  289. <el-table-column prop="out_biz_no" label="订单号" min-width="180" />
  290. <el-table-column prop="amount" label="转账金额" min-width="100">
  291. <template #default="{ row }">
  292. ¥{{ row.amount }}
  293. </template>
  294. </el-table-column>
  295. <el-table-column prop="payee_info.name" label="收款方姓名" min-width="120" />
  296. <el-table-column prop="payee_info.identity_type" label="收款方类型" min-width="100">
  297. <template #default="{ row }">
  298. {{ getPayeeTypeLabel(row.payee_info?.identity_type) }}
  299. </template>
  300. </el-table-column>
  301. <el-table-column prop="status" label="状态" min-width="100">
  302. <template #default="{ row }">
  303. <el-tag :type="getTransferStatusType(row.status)">
  304. {{ getStatusLabel(row.status) }}
  305. </el-tag>
  306. </template>
  307. </el-table-column>
  308. <el-table-column prop="order_title" label="转账标题" min-width="150" />
  309. <el-table-column prop="created_time" label="创建时间" min-width="160" />
  310. <el-table-column label="操作" width="100" fixed="right">
  311. <template #default="{ row }">
  312. <el-button type="primary" link @click="handleViewTransferDetail(row.out_biz_no)">
  313. 详情
  314. </el-button>
  315. </template>
  316. </el-table-column>
  317. </el-table>
  318. <div class="mt-4 flex justify-end">
  319. <el-pagination v-model:current-page="transferPage.page_no" v-model:page-size="transferPage.page_size"
  320. :total="transferPage.total" :page-sizes="[10, 20, 50, 100]"
  321. layout="total, sizes, prev, pager, next, jumper" @size-change="handleTransferListChange"
  322. @current-change="handleTransferListChange" />
  323. </div>
  324. </el-card>
  325. </div>
  326. </el-tab-pane>
  327. <!-- <el-tab-pane label="账单查询" name="consume">
  328. <div class="tab-content">
  329. <el-card>
  330. <template #header>
  331. <span>账单详情查询</span>
  332. </template>
  333. <el-form ref="consumeFormRef" :model="consumeForm" :rules="consumeRules" label-width="140px">
  334. <el-form-item label="支付宝账单号" prop="pay_no">
  335. <el-input v-model="consumeForm.pay_no" placeholder="请输入支付宝账单号" />
  336. </el-form-item>
  337. <el-form-item label="企业ID" prop="enterprise_id">
  338. <el-input
  339. v-model="consumeForm.enterprise_id"
  340. placeholder="请输入企业ID(2.0接口签约企业必填)"
  341. :disabled="!!currentEnterpriseId"
  342. />
  343. </el-form-item>
  344. <el-form-item label="蚂蚁门店ID" prop="ant_shop_id">
  345. <el-input v-model="consumeForm.ant_shop_id" placeholder="请输入蚂蚁门店ID(商户服务商必填)" />
  346. </el-form-item>
  347. <el-form-item label="查询选项">
  348. <el-checkbox-group v-model="consumeForm.query_options">
  349. <el-checkbox label="Refund">退款信息</el-checkbox>
  350. <el-checkbox label="Order">订单信息</el-checkbox>
  351. <el-checkbox label="Ticket">票据信息</el-checkbox>
  352. </el-checkbox-group>
  353. </el-form-item>
  354. <el-form-item>
  355. <el-button
  356. v-hasPerm="['module_payment:account:consume:detail']"
  357. type="primary"
  358. :loading="consumeLoading"
  359. @click="handleConsumeQuery"
  360. >
  361. 查询
  362. </el-button>
  363. <el-button @click="handleConsumeReset">重置</el-button>
  364. </el-form-item>
  365. </el-form>
  366. </el-card>
  367. <el-card v-if="consumeDetail" class="mt-4">
  368. <template #header>
  369. <span>账单详情</span>
  370. </template>
  371. <ConsumeDetail :data="consumeDetail" />
  372. </el-card>
  373. </div>
  374. </el-tab-pane> -->
  375. </el-tabs>
  376. <TransferDetail v-model="transferDetailVisible" :out-biz-no="currentTransferOutBizNo"
  377. @refresh="handleTransferDetailRefresh" />
  378. <!-- 批量转账对话框 -->
  379. <el-dialog v-model="batchTransferVisible" title="批量转账" width="1000px" :close-on-click-modal="false" :close-on-press-escape="false">
  380. <div class="batch-transfer-container" :class="{ 'has-overlay': showBatchTransferOverlay }">
  381. <el-card class="mb-4">
  382. <template #header>
  383. <span>Excel模板下载</span>
  384. </template>
  385. <el-button type="primary" @click="downloadTemplate">下载模板</el-button>
  386. <el-alert
  387. title="模板说明"
  388. type="info"
  389. :closable="false"
  390. class="mt-4"
  391. >
  392. <ul>
  393. <li>请按照模板格式填写转账数据</li>
  394. <li>支持支付宝账户和银行卡转账</li>
  395. <li>银行卡转账需要填写完整的银行信息</li>
  396. </ul>
  397. </el-alert>
  398. </el-card>
  399. <el-card class="mb-4">
  400. <template #header>
  401. <span>上传Excel文件</span>
  402. </template>
  403. <el-upload
  404. class="upload-demo"
  405. action=""
  406. :auto-upload="false"
  407. :on-change="handleFileChange"
  408. accept=".xlsx, .xls"
  409. :file-list="fileList"
  410. :limit="1"
  411. >
  412. <el-button type="primary">选择文件</el-button>
  413. <template #tip>
  414. <div class="el-upload__tip">
  415. 请上传Excel文件,支持.xlsx和.xls格式
  416. </div>
  417. </template>
  418. </el-upload>
  419. </el-card>
  420. <el-card v-if="batchTransferData.length > 0">
  421. <template #header>
  422. <span>数据预览</span>
  423. </template>
  424. <el-table :data="batchTransferData" border stripe>
  425. <el-table-column prop="amount" label="转账金额(元)" min-width="100" />
  426. <el-table-column prop="order_title" label="转账标题" min-width="150" />
  427. <el-table-column prop="payee_name" label="收款方姓名" min-width="120" />
  428. <el-table-column prop="payee_type" label="收款方类型" min-width="100" />
  429. <el-table-column prop="payee_account" label="收款方账号" min-width="180" />
  430. <el-table-column prop="bank_name" label="银行名称" min-width="120" v-if="hasBankTransfer" />
  431. <el-table-column prop="status" label="状态" min-width="100">
  432. <template #default="{ row }">
  433. <el-tag :type="row.status === 'valid' ? 'success' : 'danger'">
  434. {{ row.status === 'valid' ? '有效' : '无效' }}
  435. </el-tag>
  436. </template>
  437. </el-table-column>
  438. <el-table-column prop="error_msg" label="错误信息" min-width="150" v-if="hasInvalidData" />
  439. </el-table>
  440. </el-card>
  441. <!-- 遮罩层 -->
  442. <div v-if="showBatchTransferOverlay" class="batch-transfer-overlay">
  443. <div class="overlay-content">
  444. <el-icon class="is-loading" size="40"><Loading /></el-icon>
  445. <h3>正在处理批量转账,请勿关闭对话框</h3>
  446. <el-progress :percentage="Math.round((batchCurrentIndex / batchTotalCount) * 100)" :stroke-width="20" />
  447. <p>正在向 {{ batchCurrentPayee }} 转账 ¥{{ batchCurrentAmount }}</p>
  448. <div class="result-summary">
  449. <el-tag type="success">成功: {{ batchTransferSuccessCount }}</el-tag>
  450. <el-tag type="danger">失败: {{ batchTransferFailCount }}</el-tag>
  451. <el-tag type="warning">进行中: {{ batchCurrentIndex }}/{{ batchTotalCount }}</el-tag>
  452. </div>
  453. </div>
  454. </div>
  455. </div>
  456. <template #footer>
  457. <span class="dialog-footer">
  458. <el-button @click="batchTransferVisible = false" :disabled="batchTransferLoading">取消</el-button>
  459. <el-button type="primary" :loading="batchTransferLoading" @click="handleBatchTransfer" :disabled="batchTransferData.length === 0 || hasInvalidData || showBatchTransferOverlay">
  460. 开始批量转账
  461. </el-button>
  462. </span>
  463. </template>
  464. </el-dialog>
  465. <!-- 批量转账结果对话框 -->
  466. <el-dialog v-model="batchTransferResultVisible" title="批量转账结果" width="800px">
  467. <el-card>
  468. <template #header>
  469. <div class="card-header">
  470. <span>处理结果</span>
  471. <div>
  472. <el-tag type="success" class="ml-2">{{ batchTransferSuccessCount }} 成功</el-tag>
  473. <el-tag type="danger" class="ml-2">{{ batchTransferFailCount }} 失败</el-tag>
  474. </div>
  475. </div>
  476. </template>
  477. <el-table :data="batchTransferResults" border stripe>
  478. <el-table-column prop="amount" label="转账金额(元)" min-width="100" />
  479. <el-table-column prop="payee_name" label="收款方姓名" min-width="120" />
  480. <el-table-column prop="status" label="状态" min-width="100">
  481. <template #default="{ row }">
  482. <el-tag :type="row.status === 'success' ? 'success' : 'danger'">
  483. {{ row.status === 'success' ? '成功' : '失败' }}
  484. </el-tag>
  485. </template>
  486. </el-table-column>
  487. <el-table-column prop="message" label="消息" min-width="200" />
  488. </el-table>
  489. </el-card>
  490. <template #footer>
  491. <span class="dialog-footer">
  492. <el-button @click="batchTransferResultVisible = false">关闭</el-button>
  493. </span>
  494. </template>
  495. </el-dialog>
  496. </div>
  497. </template>
  498. <script setup lang="ts">
  499. defineOptions({
  500. name: "Account",
  501. inheritAttrs: false,
  502. });
  503. import { useEnterpriseStore } from "@/store/modules/enterprise.store";
  504. import AccountAPI from "@/api/module_payment/account";
  505. import AccountOverview from "./components/AccountOverview.vue";
  506. import TransferDetail from "./components/TransferDetail.vue";
  507. import ConsumeDetail from "./components/ConsumeDetail.vue";
  508. import { ref, reactive, computed, onMounted, watch } from "vue";
  509. import { Refresh, Loading } from "@element-plus/icons-vue";
  510. import { ElMessage, ElMessageBox } from "element-plus";
  511. import type { FormInstance, FormRules } from "element-plus";
  512. import * as ExcelJS from "exceljs";
  513. const enterpriseStore = useEnterpriseStore();
  514. const activeTab = ref("overview");
  515. const pageLoading = ref(false);
  516. const loadingText = ref("加载中...");
  517. const authorizeLoading = ref(false);
  518. const createLoading = ref(false);
  519. const depositLoading = ref(false);
  520. const transferLoading = ref(false);
  521. const consumeLoading = ref(false);
  522. const transferListLoading = ref(false);
  523. const authorizeFormRef = ref<FormInstance>();
  524. const createFormRef = ref<FormInstance>();
  525. const depositFormRef = ref<FormInstance>();
  526. const transferFormRef = ref<FormInstance>();
  527. const consumeFormRef = ref<FormInstance>();
  528. const overviewRef = ref<InstanceType<typeof AccountOverview>>();
  529. const currentEnterpriseId = computed(() => enterpriseStore.getCurrentEnterprise?.enterprise_id);
  530. const cureentEnterprise = computed(() => enterpriseStore.getCurrentEnterprise);
  531. const accountInfo = ref<{
  532. account_book_id: string;
  533. status: string;
  534. balance: number;
  535. }>({
  536. account_book_id: "",
  537. status: "",
  538. balance: 0,
  539. });
  540. const authorizeStatus = ref("PENDING");
  541. const authorizeForm = reactive({
  542. enterprise_id: "",
  543. });
  544. const authorizeRules: FormRules = {
  545. enterprise_id: [{ required: true, message: "请输入企业ID", trigger: "blur" }],
  546. };
  547. const authorizeResult = reactive({
  548. sign_url: "",
  549. });
  550. const createForm = reactive({
  551. enterprise_id: "",
  552. account_type: "ALL",
  553. scene: "B2B_TRANS",
  554. remark: "",
  555. });
  556. const createRules: FormRules = {
  557. enterprise_id: [{ required: true, message: "请输入企业ID", trigger: "blur" }],
  558. account_type: [{ required: true, message: "请选择账户类型", trigger: "change" }],
  559. scene: [{ required: true, message: "请选择场景类型", trigger: "change" }],
  560. };
  561. const createResult = reactive({
  562. enterprise_id: "",
  563. account_book_id: "",
  564. });
  565. const depositForm = reactive({
  566. enterprise_id: "",
  567. account_book_id: "",
  568. amount: 0,
  569. remark: "",
  570. });
  571. const depositRules: FormRules = {
  572. enterprise_id: [{ required: true, message: "请输入企业ID", trigger: "blur" }],
  573. account_book_id: [{ required: true, message: "请输入资金专户号", trigger: "blur" }],
  574. amount: [{ required: true, message: "请输入充值金额", trigger: "blur" }],
  575. };
  576. const depositResult = reactive({
  577. url: "",
  578. });
  579. const depositList = ref<any[]>([]);
  580. const transferForm = reactive({
  581. enterprise_id: "",
  582. account_book_id: "",
  583. amount: 0,
  584. order_title: "",
  585. remark: "",
  586. payee_info: {
  587. identity_type: "alipay",
  588. name: "",
  589. identity: "",
  590. bankcard_ext_info: {
  591. account_type: "2",
  592. inst_name: "",
  593. inst_province: "",
  594. inst_city: "",
  595. inst_branch_name: "",
  596. bank_code: "",
  597. },
  598. },
  599. });
  600. const transferRules: FormRules = {
  601. enterprise_id: [{ required: true, message: "请输入企业ID", trigger: "blur" }],
  602. account_book_id: [{ required: true, message: "请输入付款资金账户", trigger: "blur" }],
  603. amount: [{ required: true, message: "请输入转账金额", trigger: "blur" }],
  604. "payee_info.identity_type": [{ required: true, message: "请选择收款方类型", trigger: "change" }],
  605. "payee_info.name": [{ required: true, message: "请输入收款方姓名", trigger: "blur" }],
  606. "payee_info.identity": [{ required: true, message: "请输入收款方账号", trigger: "blur" }],
  607. };
  608. const transferList = ref<any[]>([]);
  609. const transferPage = reactive({
  610. page_no: 1,
  611. page_size: 10,
  612. total: 0,
  613. });
  614. const transferSearchForm = reactive({
  615. out_biz_no: "",
  616. status: "",
  617. });
  618. const transferDetailVisible = ref(false);
  619. const currentTransferOutBizNo = ref("");
  620. // 批量转账相关
  621. const batchTransferVisible = ref(false);
  622. const batchTransferResultVisible = ref(false);
  623. const batchTransferLoading = ref(false);
  624. const showBatchTransferOverlay = ref(false);
  625. const batchCurrentIndex = ref(0);
  626. const batchTotalCount = ref(0);
  627. const batchCurrentPayee = ref("");
  628. const batchCurrentAmount = ref(0);
  629. const fileList = ref<any[]>([]);
  630. const batchTransferData = ref<any[]>([]);
  631. const batchTransferResults = ref<any[]>([]);
  632. const batchTransferSuccessCount = ref(0);
  633. const batchTransferFailCount = ref(0);
  634. const consumeForm = reactive({
  635. pay_no: "",
  636. enterprise_id: "",
  637. ant_shop_id: "",
  638. query_options: [] as string[],
  639. });
  640. const consumeRules: FormRules = {
  641. pay_no: [{ required: true, message: "请输入支付宝账单号", trigger: "blur" }],
  642. };
  643. const consumeDetail = ref<any>(null);
  644. function getDepositStatusType(status: string) {
  645. const map: Record<string, any> = {
  646. DEALING: "warning",
  647. SUCCESS: "success",
  648. FAIL: "danger",
  649. };
  650. return map[status] || "info";
  651. }
  652. function getTransferStatusType(status: string) {
  653. const map: Record<string, any> = {
  654. DEALING: "warning",
  655. SUCCESS: "success",
  656. FAIL: "danger",
  657. REFUND: "warning",
  658. };
  659. return map[status] || "info";
  660. }
  661. function getPayeeTypeLabel(type: string) {
  662. const map: Record<string, string> = {
  663. ALIPAY_ACCOUNT: "支付宝",
  664. BANK_CARD: "银行卡",
  665. BOOK: "资金专户",
  666. };
  667. return map[type] || type;
  668. }
  669. function getStatusLabel(status: string) {
  670. const map: Record<string, string> = {
  671. DEALING: "处理中",
  672. SUCCESS: "成功",
  673. FAIL: "失败",
  674. REFUND: "退票",
  675. };
  676. return map[status] || status;
  677. }
  678. // 批量转账相关计算属性
  679. const hasBankTransfer = computed(() => {
  680. return batchTransferData.value.some(item => item.payee_type === "bank");
  681. });
  682. const hasInvalidData = computed(() => {
  683. return batchTransferData.value.some(item => item.status === "invalid");
  684. });
  685. // 下载模板
  686. function downloadTemplate() {
  687. const workbook = new ExcelJS.Workbook();
  688. const worksheet = workbook.addWorksheet("批量转账模板");
  689. // 设置表头
  690. worksheet.columns = [
  691. { header: "转账金额", key: "amount", width: 15 },
  692. { header: "转账标题", key: "order_title", width: 20 },
  693. { header: "收款方姓名", key: "payee_name", width: 15 },
  694. { header: "收款方账号类型", key: "payee_type", width: 15 },
  695. { header: "收款方账号", key: "payee_account", width: 30 },
  696. { header: "银行账户类型(1:公司账户,2:个人账户)", key: "bank_type", width: 30 },
  697. { header: "银行名称(公司账户必填)", key: "bank_name", width: 20 },
  698. { header: "开户省份(非必填)", key: "bank_province", width: 15 },
  699. { header: "开户城市(非必填)", key: "bank_city", width: 15 },
  700. { header: "支行名称(非必填)", key: "bank_branch", width: 20 },
  701. { header: "联行号(非必填)", key: "bank_code", width: 15 },
  702. { header: "备注(非必填)", key: "remark", width: 20 },
  703. ];
  704. // 添加示例数据
  705. worksheet.addRow({
  706. amount: 100.00,
  707. order_title: "测试转账",
  708. payee_name: "张三",
  709. payee_type: "alipay",
  710. payee_account: "zhangsan@example.com",
  711. remark: "测试"
  712. });
  713. worksheet.addRow({
  714. amount: 200.00,
  715. order_title: "测试转账",
  716. payee_name: "李四",
  717. payee_type: "bank",
  718. payee_account: "6222021234567890123",
  719. bank_type: "1",
  720. bank_name: "中国工商银行",
  721. bank_province: "北京市",
  722. bank_city: "北京市",
  723. bank_branch: "中关村支行",
  724. bank_code: "102100004534",
  725. remark: "测试"
  726. });
  727. // 生成并下载文件
  728. workbook.xlsx.writeBuffer().then(buffer => {
  729. const blob = new Blob([buffer], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
  730. const url = URL.createObjectURL(blob);
  731. const a = document.createElement("a");
  732. a.href = url;
  733. a.download = "批量转账模板.xlsx";
  734. a.click();
  735. URL.revokeObjectURL(url);
  736. });
  737. }
  738. // 处理文件上传
  739. async function handleFileChange(file: any) {
  740. fileList.value = [file.raw];
  741. await parseExcelFile(file.raw);
  742. }
  743. // 解析Excel文件
  744. async function parseExcelFile(file: File) {
  745. try {
  746. const workbook = new ExcelJS.Workbook();
  747. await workbook.xlsx.load(await file.arrayBuffer());
  748. const worksheet = workbook.worksheets[0];
  749. const data: any[] = [];
  750. worksheet.eachRow((row, rowNumber) => {
  751. if (rowNumber > 1) { // 跳过表头
  752. const rowData = {
  753. amount: row.getCell(1).value,
  754. order_title: row.getCell(2).value,
  755. payee_name: row.getCell(3).value,
  756. payee_type: row.getCell(4).value,
  757. payee_account: row.getCell(5).value,
  758. bank_type: row.getCell(6).value,
  759. bank_name: row.getCell(7).value,
  760. bank_province: row.getCell(8).value,
  761. bank_city: row.getCell(9).value,
  762. bank_branch: row.getCell(10).value,
  763. bank_code: row.getCell(11).value,
  764. remark: row.getCell(12).value,
  765. };
  766. data.push(rowData);
  767. }
  768. });
  769. // 验证数据
  770. batchTransferData.value = data.map(item => validateTransferData(item));
  771. } catch (error) {
  772. ElMessage.error("文件解析失败,请检查文件格式");
  773. console.error(error);
  774. }
  775. }
  776. // 验证转账数据
  777. function validateTransferData(data: any) {
  778. const result = {
  779. ...data,
  780. status: "valid",
  781. error_msg: "",
  782. };
  783. // 验证金额
  784. if (!data.amount || typeof data.amount !== "number" || data.amount < 0.02) {
  785. result.status = "invalid";
  786. result.error_msg = "转账金额必须大于等于0.02元";
  787. return result;
  788. }
  789. // 验证转账标题
  790. if (!data.order_title || data.order_title.toString().trim() === "") {
  791. result.status = "invalid";
  792. result.error_msg = "转账标题不能为空";
  793. return result;
  794. }
  795. // 验证收款方姓名
  796. if (!data.payee_name || data.payee_name.toString().trim() === "") {
  797. result.status = "invalid";
  798. result.error_msg = "收款方姓名不能为空";
  799. return result;
  800. }
  801. // 验证收款方类型
  802. if (!data.payee_type || !["alipay", "bank"].includes(data.payee_type)) {
  803. result.status = "invalid";
  804. result.error_msg = "收款方类型必须是alipay或bank";
  805. return result;
  806. }
  807. // 验证收款方账号
  808. if (!data.payee_account || data.payee_account.toString().trim() === "") {
  809. result.status = "invalid";
  810. result.error_msg = "收款方账号不能为空";
  811. return result;
  812. }
  813. // 验证银行卡信息
  814. if (data.payee_type === "bank") {
  815. if (!data.bank_type || ![1, 2].includes(data.bank_type)) {
  816. result.status = "invalid";
  817. result.error_msg = "银行账户类型必须是1或2";
  818. return result;
  819. }
  820. if (data.bank_type === "1" && (!data.bank_name || data.bank_name.toString().trim() === "")) {
  821. result.status = "invalid";
  822. result.error_msg = "银行名称不能为空";
  823. return result;
  824. }
  825. }
  826. return result;
  827. }
  828. // 处理批量转账
  829. async function handleBatchTransfer() {
  830. const validData = batchTransferData.value.filter(item => item.status === "valid");
  831. if (validData.length === 0) {
  832. ElMessage.warning("没有有效的转账数据");
  833. return;
  834. }
  835. ElMessageBox.confirm(
  836. `确定要批量转账 ${validData.length} 笔交易吗?`,
  837. "确认操作",
  838. {
  839. confirmButtonText: "确定",
  840. cancelButtonText: "取消",
  841. type: "warning",
  842. }
  843. ).then(async () => {
  844. // 开启遮罩
  845. showBatchTransferOverlay.value = true;
  846. batchTransferLoading.value = true;
  847. batchTotalCount.value = validData.length;
  848. batchCurrentIndex.value = 0;
  849. batchTransferResults.value = [];
  850. batchTransferSuccessCount.value = 0;
  851. batchTransferFailCount.value = 0;
  852. try {
  853. for (let i = 0; i < validData.length; i++) {
  854. const item = validData[i];
  855. batchCurrentIndex.value = i + 1;
  856. batchCurrentPayee.value = item.payee_name;
  857. batchCurrentAmount.value = item.amount;
  858. try {
  859. await AccountAPI.transfer({
  860. enterprise_id: currentEnterpriseId.value!,
  861. account_book_id: accountInfo.value.account_book_id,
  862. amount: item.amount,
  863. order_title: item.order_title.toString(),
  864. remark: item.remark?.toString() || "",
  865. payee_info: {
  866. identity_type: item.payee_type,
  867. name: item.payee_name.toString(),
  868. identity: item.payee_account.toString(),
  869. bankcard_ext_info:
  870. item.payee_type === "bank"
  871. ? {
  872. account_type: item.bank_type?.toString(),
  873. inst_name: item.bank_name?.toString(),
  874. inst_province: item.bank_province?.toString(),
  875. inst_city: item.bank_city?.toString(),
  876. inst_branch_name: item.bank_branch?.toString(),
  877. bank_code: item.bank_code?.toString(),
  878. }
  879. : undefined,
  880. },
  881. });
  882. batchTransferResults.value.push({
  883. amount: item.amount,
  884. payee_name: item.payee_name,
  885. status: "success",
  886. message: "转账成功",
  887. });
  888. batchTransferSuccessCount.value++;
  889. } catch (error: any) {
  890. batchTransferResults.value.push({
  891. amount: item.amount,
  892. payee_name: item.payee_name,
  893. status: "fail",
  894. message: error.message || "转账失败",
  895. });
  896. batchTransferFailCount.value++;
  897. }
  898. }
  899. // 完成后隐藏遮罩
  900. showBatchTransferOverlay.value = false;
  901. // 刷新转账记录
  902. await handleTransferSearch();
  903. // 关闭批量转账对话框,显示结果
  904. batchTransferResultVisible.value = true;
  905. batchTransferVisible.value = false;
  906. } catch (error) {
  907. showBatchTransferOverlay.value = false;
  908. ElMessage.error("批量转账过程出错");
  909. } finally {
  910. batchTransferLoading.value = false;
  911. }
  912. });
  913. }
  914. // 打开批量转账对话框
  915. function openBatchTransferDialog() {
  916. // 重置数据
  917. resetBatchTransfer();
  918. // 打开对话框
  919. batchTransferVisible.value = true;
  920. }
  921. // 重置批量转账
  922. function resetBatchTransfer() {
  923. batchTransferVisible.value = false;
  924. batchTransferResultVisible.value = false;
  925. showBatchTransferOverlay.value = false;
  926. batchCurrentIndex.value = 0;
  927. batchTotalCount.value = 0;
  928. batchCurrentPayee.value = "";
  929. batchCurrentAmount.value = 0;
  930. fileList.value = [];
  931. batchTransferData.value = [];
  932. batchTransferResults.value = [];
  933. batchTransferSuccessCount.value = 0;
  934. batchTransferFailCount.value = 0;
  935. }
  936. async function handleAuthorize() {
  937. // if (!authorizeFormRef.value) return;
  938. // await authorizeFormRef.value.validate(async (valid) => {
  939. // if (valid) {
  940. // authorizeLoading.value = true;
  941. // try {
  942. // const res = await AccountAPI.authorizeApply({
  943. // enterprise_id: authorizeForm.enterprise_id || currentEnterpriseId.value!,
  944. // });
  945. // authorizeResult.sign_url = res.data.sign_url || "";
  946. // } finally {
  947. // authorizeLoading.value = false;
  948. // }
  949. // }
  950. // });
  951. try {
  952. const res = await AccountAPI.authorizeApply({
  953. enterprise_id: currentEnterpriseId.value!,
  954. });
  955. authorizeResult.sign_url = res.data.data?.sign_url || "";
  956. // 直接打开新窗口跳转
  957. window.open(authorizeResult.sign_url, "_blank");
  958. } finally {
  959. authorizeLoading.value = false;
  960. }
  961. }
  962. function handleAuthorizeReset() {
  963. authorizeFormRef.value?.resetFields();
  964. authorizeResult.sign_url = "";
  965. }
  966. async function handleCreate() {
  967. // if (!createFormRef.value) return;
  968. // await createFormRef.value.validate(async (valid) => {
  969. // if (valid) {
  970. // if (authorizeStatus.value !== "AUTHORIZED") {
  971. // ElMessage.warning("请先完成转账授权签约");
  972. // return;
  973. // }
  974. // createLoading.value = true;
  975. // try {
  976. // const res = await AccountAPI.create({
  977. // enterprise_id: createForm.enterprise_id || currentEnterpriseId.value!,
  978. // account_type: createForm.account_type,
  979. // scene: createForm.scene,
  980. // remark: createForm.remark,
  981. // });
  982. // createResult.enterprise_id = res.data.enterprise_id || "";
  983. // createResult.account_book_id = res.data.account_book_id || "";
  984. // accountInfo.value.account_book_id = createResult.account_book_id;
  985. // accountInfo.value.status = "ACTIVE";
  986. // overviewRef.value?.refresh();
  987. // } finally {
  988. // createLoading.value = false;
  989. // }
  990. // }
  991. // });
  992. try {
  993. const res = await AccountAPI.create({
  994. enterprise_id: currentEnterpriseId.value!,
  995. account_type: "ALL",
  996. scene: "B2B_TRANS",
  997. remark: "",
  998. });
  999. createResult.enterprise_id = res.data.data.enterprise_id || "";
  1000. createResult.account_book_id = res.data.data.account_book_id || "";
  1001. accountInfo.value.account_book_id = createResult.account_book_id;
  1002. accountInfo.value.status = "AUTHORIZED";
  1003. overviewRef.value?.refresh();
  1004. } finally {
  1005. createLoading.value = false;
  1006. }
  1007. }
  1008. function handleCreateReset() {
  1009. createFormRef.value?.resetFields();
  1010. createResult.enterprise_id = "";
  1011. createResult.account_book_id = "";
  1012. }
  1013. async function handleDeposit() {
  1014. if (!depositFormRef.value) return;
  1015. await depositFormRef.value.validate(async (valid) => {
  1016. if (valid) {
  1017. if (!accountInfo.value.account_book_id) {
  1018. ElMessage.warning("请先开通资金专户");
  1019. return;
  1020. }
  1021. depositLoading.value = true;
  1022. try {
  1023. const res = await AccountAPI.deposit({
  1024. enterprise_id: currentEnterpriseId.value!,
  1025. account_book_id: accountInfo.value.account_book_id,
  1026. amount: depositForm.amount,
  1027. remark: depositForm.remark,
  1028. });
  1029. depositResult.url = res.data.data?.url || "";
  1030. // 直接打开新窗口跳转
  1031. window.open(depositResult.url, "_blank");
  1032. } finally {
  1033. depositLoading.value = false;
  1034. }
  1035. }
  1036. });
  1037. }
  1038. function handleDepositReset() {
  1039. depositFormRef.value?.resetFields();
  1040. depositResult.url = "";
  1041. }
  1042. async function handleTransfer() {
  1043. if (!transferFormRef.value) return;
  1044. await transferFormRef.value.validate(async (valid) => {
  1045. if (valid) {
  1046. if (accountInfo.value.balance <= 0) {
  1047. ElMessage.warning("账户余额不足,请先充值");
  1048. return;
  1049. }
  1050. transferLoading.value = true;
  1051. try {
  1052. await AccountAPI.transfer({
  1053. enterprise_id: currentEnterpriseId.value!,
  1054. account_book_id: accountInfo.value.account_book_id,
  1055. amount: transferForm.amount,
  1056. order_title: transferForm.order_title,
  1057. remark: transferForm.remark,
  1058. payee_info: {
  1059. identity_type: transferForm.payee_info.identity_type,
  1060. name: transferForm.payee_info.name,
  1061. identity: transferForm.payee_info.identity,
  1062. bankcard_ext_info:
  1063. transferForm.payee_info.identity_type === "bank"
  1064. ? transferForm.payee_info.bankcard_ext_info
  1065. : undefined,
  1066. },
  1067. });
  1068. // ElMessage.success("转账申请已提交");
  1069. handleTransferListChange();
  1070. handleTransferReset();
  1071. } finally {
  1072. transferLoading.value = false;
  1073. }
  1074. }
  1075. });
  1076. }
  1077. function handleTransferReset() {
  1078. transferFormRef.value?.resetFields();
  1079. transferForm.payee_info = {
  1080. identity_type: "alipay",
  1081. name: "",
  1082. identity: "",
  1083. bankcard_ext_info: {
  1084. account_type: "2",
  1085. inst_name: "",
  1086. inst_province: "",
  1087. inst_city: "",
  1088. inst_branch_name: "",
  1089. bank_code: "",
  1090. },
  1091. };
  1092. }
  1093. async function handleTransferSearch() {
  1094. transferPage.page_no = 1;
  1095. await fetchTransferList();
  1096. }
  1097. function handleTransferSearchReset() {
  1098. transferSearchForm.out_biz_no = "";
  1099. transferSearchForm.status = "";
  1100. handleTransferSearch();
  1101. }
  1102. async function fetchTransferList() {
  1103. transferListLoading.value = true;
  1104. try {
  1105. const res = await AccountAPI.transferList({
  1106. page_no: transferPage.page_no,
  1107. page_size: transferPage.page_size,
  1108. out_biz_no: transferSearchForm.out_biz_no || undefined,
  1109. status: transferSearchForm.status || undefined,
  1110. });
  1111. transferList.value = res.data.data.items || [];
  1112. transferPage.total = res.data.data.total || 0;
  1113. } finally {
  1114. transferListLoading.value = false;
  1115. }
  1116. }
  1117. function handleTransferListChange() {
  1118. fetchTransferList();
  1119. }
  1120. function handleViewTransferDetail(outBizNo: string) {
  1121. currentTransferOutBizNo.value = outBizNo;
  1122. transferDetailVisible.value = true;
  1123. }
  1124. function handleTransferDetailRefresh() {
  1125. fetchTransferList();
  1126. }
  1127. async function handleConsumeQuery() {
  1128. if (!consumeFormRef.value) return;
  1129. await consumeFormRef.value.validate(async (valid) => {
  1130. if (valid) {
  1131. consumeLoading.value = true;
  1132. try {
  1133. const res = await AccountAPI.consumeDetail({
  1134. pay_no: consumeForm.pay_no,
  1135. enterprise_id: consumeForm.enterprise_id || currentEnterpriseId.value || undefined,
  1136. ant_shop_id: consumeForm.ant_shop_id || undefined,
  1137. query_options: consumeForm.query_options.length > 0 ? consumeForm.query_options : undefined,
  1138. });
  1139. consumeDetail.value = res.data;
  1140. } finally {
  1141. consumeLoading.value = false;
  1142. }
  1143. }
  1144. });
  1145. }
  1146. function handleConsumeReset() {
  1147. consumeFormRef.value?.resetFields();
  1148. consumeDetail.value = null;
  1149. }
  1150. function handleOverviewRefresh(data: any) {
  1151. if (data) {
  1152. accountInfo.value = {
  1153. account_book_id: data.account_book_id || "",
  1154. status: data.status || "",
  1155. balance: data.balance || 0,
  1156. };
  1157. authorizeStatus.value = data.authorize_status || "PENDING";
  1158. }
  1159. }
  1160. async function handleGoTab(tab: string) {
  1161. console.log("goTab => ", tab);
  1162. if (tab === "authorize") {
  1163. await handleAuthorize();
  1164. } else if (tab === "create") {
  1165. await handleCreate();
  1166. } else if (tab === "deposit") {
  1167. activeTab.value = tab;
  1168. } else if (tab === "transfer") {
  1169. activeTab.value = tab;
  1170. }
  1171. }
  1172. onMounted(() => {
  1173. if (currentEnterpriseId.value) {
  1174. authorizeForm.enterprise_id = currentEnterpriseId.value;
  1175. createForm.enterprise_id = currentEnterpriseId.value;
  1176. depositForm.enterprise_id = currentEnterpriseId.value;
  1177. transferForm.enterprise_id = currentEnterpriseId.value;
  1178. consumeForm.enterprise_id = currentEnterpriseId.value;
  1179. }
  1180. });
  1181. watch(activeTab, async (newValue) => {
  1182. if (newValue === "transfer") {
  1183. await handleTransferSearch();
  1184. }
  1185. })
  1186. // watch(batchTransferVisible, (newValue) => {
  1187. // if (!newValue) {
  1188. // resetBatchTransfer();
  1189. // }
  1190. // })
  1191. onMounted(async() => {
  1192. pageLoading.value = true;
  1193. try {
  1194. await overviewRef.value?.refresh();
  1195. } finally {
  1196. pageLoading.value = false;
  1197. }
  1198. });
  1199. </script>
  1200. <style lang="scss" scoped>
  1201. .account-tabs {
  1202. height: 100%;
  1203. :deep(.el-tabs__content) {
  1204. height: calc(100% - 40px);
  1205. overflow-y: auto;
  1206. }
  1207. }
  1208. .tab-content {
  1209. padding: 0;
  1210. }
  1211. .card-header {
  1212. display: flex;
  1213. justify-content: space-between;
  1214. align-items: center;
  1215. }
  1216. .mt-4 {
  1217. margin-top: 16px;
  1218. }
  1219. .ml-2 {
  1220. margin-left: 8px;
  1221. }
  1222. .mb-4 {
  1223. margin-bottom: 16px;
  1224. }
  1225. .flex {
  1226. display: flex;
  1227. }
  1228. .justify-end {
  1229. justify-content: flex-end;
  1230. }
  1231. .authorize-result,
  1232. .create-result,
  1233. .deposit-result {
  1234. margin-top: 20px;
  1235. }
  1236. .batch-transfer-container {
  1237. position: relative;
  1238. &.has-overlay {
  1239. pointer-events: none;
  1240. }
  1241. }
  1242. .batch-transfer-overlay {
  1243. position: absolute;
  1244. top: 0;
  1245. left: 0;
  1246. right: 0;
  1247. bottom: 0;
  1248. background: rgba(255, 255, 255, 0.95);
  1249. display: flex;
  1250. align-items: center;
  1251. justify-content: center;
  1252. z-index: 10;
  1253. border-radius: 8px;
  1254. .overlay-content {
  1255. text-align: center;
  1256. padding: 40px;
  1257. h3 {
  1258. margin: 20px 0;
  1259. color: #303133;
  1260. }
  1261. p {
  1262. margin: 15px 0;
  1263. color: #606266;
  1264. }
  1265. .result-summary {
  1266. display: flex;
  1267. gap: 15px;
  1268. justify-content: center;
  1269. margin-top: 20px;
  1270. }
  1271. }
  1272. }
  1273. </style>