cashApply.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. <template>
  2. <div class="cash-apply-page">
  3. <!-- 头部 -->
  4. <div class="header">
  5. <el-button class="back-btn" @click="goBack"> 返回 </el-button>
  6. <h2 class="title">提现申请</h2>
  7. </div>
  8. <!-- 内容区域 -->
  9. <div class="content">
  10. <!-- 可提现金额 -->
  11. <div class="section">
  12. <div class="section-title">可提现金额</div>
  13. <div class="available-amount">¥{{ formatCurrency(availableAmount) }}</div>
  14. </div>
  15. <!-- 提现金额输入 -->
  16. <div class="section">
  17. <div class="section-title">提现金额</div>
  18. <div class="amount-input-wrapper">
  19. <el-input
  20. v-model="withdrawAmount"
  21. placeholder="请输入提现金额"
  22. class="amount-input"
  23. type="number"
  24. :min="0.01"
  25. :max="availableAmount"
  26. @input="handleAmountInput"
  27. />
  28. <el-button type="primary" class="withdraw-all-btn" @click="handleWithdrawAll"> 全部提现 </el-button>
  29. </div>
  30. <div class="min-amount-tip">最低提现金额为0.1元</div>
  31. </div>
  32. <!-- 提现账户 -->
  33. <div class="section">
  34. <div class="section-title">提现账户</div>
  35. <div class="account-list">
  36. <div class="account-item">
  37. <div class="account-left">
  38. <img :src="zfbIcon" alt="" class="account-icon" />
  39. <div class="account-info">
  40. <div class="account-name">
  41. {{ userInfo.name }}
  42. </div>
  43. <div class="account-number">
  44. {{ userInfo.alipayAccount }}
  45. </div>
  46. </div>
  47. </div>
  48. <div class="account-right">
  49. <div class="selected-indicator" />
  50. </div>
  51. </div>
  52. </div>
  53. </div>
  54. <!-- 底部按钮 -->
  55. <div class="footer">
  56. <el-button type="primary" class="submit-btn" @click="handleSubmit"> 提交申请 </el-button>
  57. </div>
  58. </div>
  59. <!-- 确认对话框 -->
  60. <el-dialog
  61. v-model="cashDialogVisible"
  62. title="提现金额域账户确认"
  63. width="500px"
  64. :close-on-click-modal="false"
  65. class="confirm-dialog"
  66. >
  67. <div class="confirm-content">
  68. <div class="confirm-item">
  69. <span class="confirm-label">提现金额:</span>
  70. <span class="confirm-value">¥ {{ withdrawAmount || "0" }}</span>
  71. </div>
  72. <div class="confirm-item">
  73. <span class="confirm-label">提现账户:</span>
  74. <span class="confirm-value">支付宝账户 ({{ userInfo.alipayAccount }})</span>
  75. </div>
  76. <div class="password-section">
  77. <div class="password-label">请输入提现密码</div>
  78. <el-input
  79. v-model="withdrawPassword"
  80. type="password"
  81. placeholder="请输入6位提现密码"
  82. maxlength="6"
  83. show-password
  84. class="password-input"
  85. @input="handlePasswordInput"
  86. />
  87. </div>
  88. </div>
  89. <template #footer>
  90. <div class="dialog-footer">
  91. <el-button class="dialog-cancel-btn" @click="handleCancelConfirm"> 取消 </el-button>
  92. <el-button type="primary" class="dialog-confirm-btn" @click="handleConfirmSubmit"> 确认 </el-button>
  93. </div>
  94. </template>
  95. </el-dialog>
  96. </div>
  97. </template>
  98. <script setup lang="ts">
  99. import { ref, onMounted } from "vue";
  100. import { useRouter } from "vue-router";
  101. import { ElMessage } from "element-plus";
  102. import { getAccountBalance, cashOut } from "@/api/modules/homeEntry";
  103. import zfbIcon from "@/assets/financial/zfb-icon.png";
  104. import { localGet } from "@/utils";
  105. const userInfo = localGet("geeker-user").userInfo;
  106. const router = useRouter();
  107. const cashDialogVisible = ref(false);
  108. const withdrawPassword = ref("");
  109. // 提现金额
  110. const withdrawAmount = ref();
  111. // 密码输入处理(只允许数字)
  112. const handlePasswordInput = (value: string) => {
  113. withdrawPassword.value = value.replace(/\D/g, "");
  114. };
  115. // 取消确认
  116. const handleCancelConfirm = () => {
  117. cashDialogVisible.value = false;
  118. withdrawPassword.value = "";
  119. };
  120. const handleConfirmSubmit = async () => {
  121. const res: any = await cashOut({
  122. storeId: userInfo.storeId,
  123. payPassword: withdrawPassword.value,
  124. withdrawalMoney: withdrawAmount.value * 100
  125. });
  126. if (res.code == 200) {
  127. router.go(-1);
  128. ElMessage.success("提现申请已发起成功,请耐心等待");
  129. cashDialogVisible.value = false;
  130. fetchAccountBalance();
  131. } else {
  132. ElMessage.error(res.message);
  133. }
  134. };
  135. // 可提现金额
  136. const availableAmount = ref<number>(0);
  137. // 选中的账户ID
  138. const selectedAccountId = ref<number>(1);
  139. // 返回
  140. const goBack = () => {
  141. router.back();
  142. };
  143. // 格式化金额
  144. const formatCurrency = (value: number) => {
  145. return value.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 });
  146. };
  147. // 全部提现
  148. const handleWithdrawAll = () => {
  149. withdrawAmount.value = availableAmount.value.toString();
  150. };
  151. // 金额输入处理
  152. const handleAmountInput = (value: string) => {
  153. const numValue = parseFloat(value);
  154. if (isNaN(numValue) || numValue < 0) {
  155. withdrawAmount.value = "";
  156. return;
  157. }
  158. if (numValue > availableAmount.value) {
  159. withdrawAmount.value = availableAmount.value.toString();
  160. ElMessage.warning("提现金额不能超过可提现金额");
  161. }
  162. };
  163. // 选择账户
  164. const selectAccount = (id: number) => {
  165. selectedAccountId.value = id;
  166. };
  167. // 提交申请
  168. const handleSubmit = () => {
  169. const amount = parseFloat(withdrawAmount.value);
  170. // 验证提现金额
  171. if (!withdrawAmount.value || isNaN(amount) || amount <= 0) {
  172. ElMessage.warning("请输入提现金额");
  173. return;
  174. }
  175. if (amount < 0.01) {
  176. ElMessage.warning("最低提现金额为0.01元");
  177. return;
  178. }
  179. if (amount > availableAmount.value) {
  180. ElMessage.warning("提现金额不能超过可提现金额");
  181. return;
  182. }
  183. // 验证账户
  184. if (!selectedAccountId.value) {
  185. ElMessage.warning("请选择提现账户");
  186. return;
  187. }
  188. cashDialogVisible.value = true;
  189. };
  190. // 获取可提现金额
  191. const fetchAccountBalance = async () => {
  192. let param = {
  193. storeId: userInfo.storeId
  194. };
  195. const res: any = await getAccountBalance(param as any);
  196. if (res.code == 200 && res.data) {
  197. availableAmount.value = res.data.cashOutMoney;
  198. // 根据实际API返回的数据结构更新
  199. // availableAmount.value = res.data.availableAmount || res.data.amount || 586;
  200. }
  201. };
  202. onMounted(() => {
  203. fetchAccountBalance();
  204. });
  205. </script>
  206. <style scoped lang="scss">
  207. .cash-apply-page {
  208. display: flex;
  209. flex-direction: column;
  210. width: 100%;
  211. min-height: 100vh;
  212. background-color: #ffffff;
  213. }
  214. .header {
  215. position: relative;
  216. display: flex;
  217. align-items: center;
  218. padding: 20px;
  219. border-bottom: 1px solid #e4e7ed;
  220. .back-btn {
  221. padding: 8px 16px;
  222. font-size: 14px;
  223. color: #606266;
  224. background-color: #f5f7fa;
  225. border: 1px solid #dcdfe6;
  226. border-radius: 4px;
  227. &:hover {
  228. color: #409eff;
  229. background-color: #ecf5ff;
  230. border-color: #b3d8ff;
  231. }
  232. }
  233. .title {
  234. position: absolute;
  235. left: 50%;
  236. margin: 0;
  237. font-size: 18px;
  238. font-weight: bold;
  239. color: #333333;
  240. transform: translateX(-50%);
  241. }
  242. }
  243. .content {
  244. display: flex;
  245. flex: 1;
  246. flex-direction: column;
  247. gap: 32px;
  248. padding: 24px 20px;
  249. }
  250. .section {
  251. display: flex;
  252. flex-direction: column;
  253. gap: 12px;
  254. .section-title {
  255. font-size: 16px;
  256. font-weight: 500;
  257. color: #333333;
  258. }
  259. }
  260. .available-amount {
  261. margin-top: 8px;
  262. font-size: 36px;
  263. font-weight: 600;
  264. color: #333333;
  265. }
  266. .amount-input-wrapper {
  267. display: flex;
  268. gap: 12px;
  269. align-items: center;
  270. .amount-input {
  271. flex: 1;
  272. :deep(.el-input__wrapper) {
  273. padding: 12px 16px;
  274. border-radius: 4px;
  275. }
  276. }
  277. .withdraw-all-btn {
  278. padding: 12px 20px;
  279. white-space: nowrap;
  280. background-color: #7f9dff;
  281. border: none;
  282. border-radius: 4px;
  283. }
  284. }
  285. .min-amount-tip {
  286. margin-top: 4px;
  287. font-size: 12px;
  288. color: #909399;
  289. }
  290. .account-list {
  291. display: flex;
  292. flex-direction: column;
  293. gap: 12px;
  294. margin-top: 8px;
  295. }
  296. .account-item {
  297. display: flex;
  298. align-items: center;
  299. justify-content: space-between;
  300. padding: 16px;
  301. cursor: pointer;
  302. background-color: #ffffff;
  303. border: 1px solid #dcdfe6;
  304. border-radius: 8px;
  305. transition: all 0.3s;
  306. &.active {
  307. background-color: #ecf5ff;
  308. border-color: #7f9dff;
  309. }
  310. .account-left {
  311. display: flex;
  312. flex: 1;
  313. gap: 12px;
  314. align-items: center;
  315. .account-icon {
  316. width: 40px;
  317. height: 40px;
  318. object-fit: contain;
  319. }
  320. .account-info {
  321. display: flex;
  322. flex-direction: column;
  323. gap: 4px;
  324. .account-name {
  325. font-size: 16px;
  326. font-weight: 500;
  327. color: #333333;
  328. }
  329. .account-number {
  330. font-size: 14px;
  331. color: #909399;
  332. }
  333. }
  334. }
  335. .account-right {
  336. display: flex;
  337. align-items: center;
  338. justify-content: center;
  339. width: 24px;
  340. height: 24px;
  341. .selected-indicator {
  342. width: 16px;
  343. height: 16px;
  344. background-color: #7f9dff;
  345. border: 3px solid #ffffff;
  346. border-radius: 50%;
  347. box-shadow: 0 0 0 2px #7f9dff;
  348. }
  349. }
  350. }
  351. .footer {
  352. display: flex;
  353. justify-content: center;
  354. margin-top: 100px;
  355. .cancel-btn {
  356. padding: 20px;
  357. font-size: 16px;
  358. color: #606266;
  359. background-color: #f5f7fa;
  360. border: 1px solid #dcdfe6;
  361. border-radius: 4px;
  362. }
  363. .submit-btn {
  364. padding: 20px;
  365. font-size: 16px;
  366. color: #ffffff;
  367. background-color: #7f9dff;
  368. border: none;
  369. border-radius: 4px;
  370. }
  371. }
  372. :deep(.confirm-dialog) {
  373. .el-dialog__header {
  374. padding: 20px 24px;
  375. border-bottom: 1px solid #e4e7ed;
  376. }
  377. .el-dialog__title {
  378. font-size: 18px;
  379. font-weight: 600;
  380. color: #333333;
  381. }
  382. .el-dialog__body {
  383. padding: 24px;
  384. }
  385. }
  386. .confirm-content {
  387. display: flex;
  388. flex-direction: column;
  389. gap: 20px;
  390. .confirm-item {
  391. display: flex;
  392. gap: 12px;
  393. align-items: center;
  394. font-size: 14px;
  395. .confirm-label {
  396. min-width: 80px;
  397. font-weight: 500;
  398. color: #606266;
  399. }
  400. .confirm-value {
  401. font-weight: 500;
  402. color: #333333;
  403. }
  404. }
  405. .password-section {
  406. display: flex;
  407. flex-direction: column;
  408. gap: 12px;
  409. margin-top: 8px;
  410. .password-label {
  411. font-size: 14px;
  412. font-weight: 500;
  413. color: #606266;
  414. }
  415. .password-input {
  416. :deep(.el-input__wrapper) {
  417. padding: 12px 16px;
  418. border-radius: 4px;
  419. }
  420. }
  421. }
  422. }
  423. </style>