withdraw.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. <!-- 提现 -->
  2. <template>
  3. <s-layout title="提现">
  4. <view class="bg-white ss-modal-box ss-flex-col">
  5. <!-- 提现方式 -->
  6. <view class="modal-content">
  7. <view class="out-title ss-p-l-30 ss-m-y-30">选择提现方式</view>
  8. <radio-group @change="onTapOut">
  9. <label class="out-type-item" v-for="item in state.outMethods" :key="item.title">
  10. <view class="out-item ss-flex ss-col-center ss-row-between ss-p-x-30 border-bottom"
  11. :class="{ 'disabled-out-item': item.disabled }">
  12. <view class="ss-flex ss-col-center">
  13. <view class="check-box ss-flex ss-col-center ss-p-l-10">
  14. <radio
  15. :value="item.value"
  16. color="var(--ui-BG-Main)"
  17. style="transform: scale(0.8)"
  18. :disabled="item.disabled"
  19. :checked="state.payment === item.value"
  20. />
  21. </view>
  22. <text class="out-title">{{ item.title }}</text>
  23. </view>
  24. <text style="float: right;" v-if="item.account">{{item.account}}</text>
  25. <text style="float: right;" v-else @click="handleBind(item.value)">暂未绑定,点击绑定&nbsp;></text>
  26. </view>
  27. </label>
  28. </radio-group>
  29. </view>
  30. <!-- 提现金额 -->
  31. <view class="modal-content ss-m-t-30">
  32. <uni-forms :model="state.model" :rules="state.rules" validateTrigger="bind" labelPosition="left" border
  33. class="form-box" labelWidth='200' ref="FormRef">
  34. <view class="bg-white ss-p-x-30">
  35. <uni-forms-item name="quota" label="提现金额" :required="true">
  36. <uni-easyinput v-model="state.outMoney" type="number"
  37. placeholder="请输入金额" :inputBorder="false" :clearable="false" />
  38. </uni-forms-item>
  39. <uni-forms-item name="quota" label="实到金额">
  40. <view class="ss-flex ss-h-100">
  41. {{commission}}
  42. </view>
  43. </uni-forms-item>
  44. <uni-forms-item name="quota" label="消费分">
  45. <view class="ss-flex ss-h-100">
  46. {{consumption}}
  47. </view>
  48. </uni-forms-item>
  49. </view>
  50. </uni-forms>
  51. <!-- <view class="out-title ss-p-l-30 ss-m-y-30">提现金额</view>
  52. <view class="ss-flex ss-row-left ss-col-center input-money ss-m-y-30" >
  53. <input v-model.number="state.outMoney" class="uni-input " type="number"
  54. placeholder="请输入金额" />
  55. </view> -->
  56. <view class="ss-flex ss-row-center ss-col-center ss-m-t-30">
  57. 您当前可兑换金额:¥<text class="text-red">{{canUseMoney}}</text>
  58. <button class="ss-m-l-10 all-btn " @click="useAllPonints">全部</button>
  59. </view>
  60. <view class="ss-flex ss-row-center ss-col-center ss-m-t-30 text-red text-center">备注:实际到账金额{{withdrawCommission}},消费分{{withdrawConsumption}}。<br>免提现手续费</view>
  61. </view>
  62. <!-- 工具 -->
  63. <view class="modal-footer ss-flex ss-row-center ss-col-center ss-m-t-80 ss-m-b-40 ss-flex-5">
  64. <button class="ss-reset-button save-btn" @tap="submit" :disabled="state.disabled" :class="{ 'disabled-btn': state.disabled }"
  65. >
  66. 确定
  67. </button>
  68. </view>
  69. </view>
  70. </s-layout>
  71. </template>
  72. <script setup>
  73. import {
  74. computed,
  75. reactive,
  76. watchEffect,
  77. nextTick,
  78. onUnmounted
  79. } from 'vue';
  80. import {
  81. onLoad
  82. } from '@dcloudio/uni-app';
  83. import sheep from '@/sheep';
  84. import { clone } from 'lodash';
  85. import {
  86. fen2yuan,
  87. points2point
  88. } from '@/sheep/hooks/useGoods';
  89. import md5 from 'blueimp-md5';
  90. import PayWalletApi from '@/sheep/api/pay/wallet';
  91. import WithdrawalApi from '@/sheep/api/distri/withdrawal';
  92. import { showAuthModal, showShareModal } from '@/sheep/hooks/useModal';
  93. const userWallet = computed(() => sheep.$store('user').userWallet);
  94. const userInfo = computed(() => sheep.$store('user').userInfo);
  95. const canUseMoney = computed(() => points2point(userWallet.value.integralDO.currentQuota));
  96. const alipayAccount = (account) => {
  97. // let account = state.model.alipayAccount;
  98. if (!account) {
  99. return false
  100. }
  101. // 手机号脱敏
  102. if (/^\d{11}$/.test(account)) { // 检查是否是11位数字的手机号
  103. return `${account.substring(0, 3)}****${account.substring(7)}`;
  104. } else if (/^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/.test(account)) {
  105. const atIndex = account.indexOf('@');
  106. // 邮箱用户名长度小于等于3位时,不脱敏
  107. if (atIndex <= 3) {
  108. return account;
  109. }
  110. const username = account.substring(0, Math.ceil(atIndex / 2)); // 取邮箱用户名的一半
  111. const domain = account.substring(atIndex); // 邮箱域名部分
  112. return `${username}***${domain}`;
  113. }
  114. }
  115. const bankAccount = (account) => {
  116. if (!account) {
  117. return false
  118. }
  119. if (account.length === 8) {
  120. return account.substring(0, 2) + '********' + account.substr(-2);
  121. } else {
  122. return account.substring(0, 4) + '******' + account.substr(-4);
  123. }
  124. }
  125. const state = reactive({
  126. model: {},
  127. orderType: 'goods', // 订单类型; goods - 商品订单, recharge - 充值订单
  128. outMent: '',
  129. outMoney:undefined,
  130. disabled:true,
  131. withdrawalPercentage:{
  132. withdrawCommission:0,
  133. withdrawConsumption:0
  134. },
  135. outMethods: [
  136. // {
  137. // title: "提现到微信",
  138. // value: '1'
  139. // },
  140. {
  141. title: "提现到支付宝",
  142. value: '2',
  143. account:''
  144. },
  145. {
  146. title: "提现到银行卡",
  147. value: '3',
  148. account:''
  149. }
  150. ]
  151. });
  152. const withdrawCommission = computed(() => {
  153. return state.withdrawalPercentage.withdrawCommission * 100 + '%';
  154. });
  155. const withdrawConsumption = computed(() => {
  156. return state.withdrawalPercentage.withdrawConsumption * 100 + '%';
  157. });
  158. const commission = computed(() => {
  159. if(!state.outMoney){
  160. return 0;
  161. }
  162. let result = parseFloat(state.withdrawalPercentage.withdrawCommission) * state.outMoney;
  163. // 地板除到小数点后两位
  164. result = Math.floor(result * 100) / 100;
  165. return result;
  166. });
  167. const consumption = computed(() => {
  168. if(!state.outMoney){
  169. return 0;
  170. }
  171. let result = parseFloat(state.withdrawalPercentage.withdrawConsumption) * state.outMoney;
  172. // 地板除到小数点后两位
  173. result = Math.floor(result * 100) / 100;
  174. return result;
  175. });
  176. const handleBind = async (type) => {
  177. // console.log(type)
  178. if(type === '2'){
  179. showAuthModal('alipayAccount');
  180. }else if(type === '3'){
  181. showAuthModal('bankAccount');
  182. }
  183. }
  184. const submit = async () => {
  185. if (state.outMent === '') {
  186. sheep.$helper.toast('请选择提现方式');
  187. return;
  188. }
  189. if (!state.outMoney) {
  190. sheep.$helper.toast('请输入提现金额');
  191. return;
  192. }
  193. if (state.outMent === '2' && !userInfo.value.alipayAccount){
  194. // 没绑定支付宝
  195. uni.showModal({
  196. title: '提示',
  197. content: '未绑定支付宝账号',
  198. confirmText:'去绑定',
  199. success: async function(res) {
  200. if (!res.confirm) {
  201. return;
  202. }
  203. showAuthModal('alipayAccount');
  204. },
  205. });
  206. return;
  207. }
  208. if (state.outMent === '3' && !userInfo.value.bankAccount){
  209. // 没绑定银行卡
  210. uni.showModal({
  211. title: '提示',
  212. content: '未绑定银行卡',
  213. confirmText:'去绑定',
  214. success: async function(res) {
  215. if (!res.confirm) {
  216. return;
  217. }
  218. showAuthModal('bankAccount');
  219. },
  220. });
  221. return;
  222. }
  223. let {
  224. code,
  225. data
  226. } = await PayWalletApi.createWithdrawal({
  227. amountTotal:state.outMoney,
  228. withdrawalType:state.outMent
  229. });
  230. if(code === 0){
  231. uni.showToast({
  232. icon: 'success',
  233. title: "申请成功",
  234. });
  235. sheep.$router.redirect('/pages/user/wallet/withdrawalLog')
  236. uni.$emit('createWithDrawComplete');
  237. }
  238. };
  239. // 切换提现方式
  240. function onTapOut(e) {
  241. state.outMent = e.detail.value;
  242. }
  243. // 提现全部佣金
  244. async function useAllPonints(){
  245. const {code,data} = await PayWalletApi.getDuserInfo();
  246. const userCanUsePoints = parseFloat(points2point(data.integralDO.currentQuota));
  247. state.outMoney = parseInt(userCanUsePoints);
  248. state.disable = false;
  249. }
  250. watchEffect(() => {
  251. // 提现金额不能大于可用佣金
  252. if (parseFloat(state.outMoney) > parseFloat(canUseMoney.value)) {
  253. // 使用 nextTick 确保 DOM 更新
  254. nextTick(() => {
  255. state.outMoney = parseInt(canUseMoney.value);
  256. });
  257. }
  258. // 如果计算出来的当前可以使用的最大佣金等于小于0 则不给输入
  259. if(canUseMoney.value == 0 || canUseMoney.value < 0){
  260. state.disabled = true
  261. }
  262. if(canUseMoney.value > 0){
  263. state.disabled = false
  264. }
  265. })
  266. // 获得用户信息
  267. const getUserInfo = async () => {
  268. // 个人信息
  269. const userInfo = await sheep.$store('user').getInfo();
  270. state.model = clone(userInfo);
  271. state.outMethods.forEach(item=>{
  272. if(item.value === '2'){
  273. item.account = alipayAccount(state.model.alipayAccount);
  274. }else if(item.value === '3'){
  275. item.account = bankAccount(state.model.bankAccount);
  276. }
  277. })
  278. };
  279. const getWithdrawalPercentage = async () => {
  280. const {code,data} = await WithdrawalApi.getWithdrawalPercentage();
  281. if(code === 0){
  282. state.withdrawalPercentage = data;
  283. }
  284. }
  285. onLoad(async(options) => {
  286. await getUserInfo();
  287. await getWithdrawalPercentage();
  288. // refresh()
  289. uni.$on('alipayAccountChangeComplete', getUserInfo);
  290. uni.$on('bankAccountChangeComplete', getUserInfo);
  291. });
  292. </script>
  293. <style lang="scss" scoped>
  294. .all-btn{
  295. height: 60rpx;
  296. line-height: 60rpx;
  297. min-width: 80rpx;
  298. padding: 0 30rpx;
  299. border-radius: 30rpx;
  300. font-size: 26rpx;
  301. margin-right: 10rpx;
  302. border: 2rpx solid var(--ui-BG-Main);
  303. color: var(--ui-BG-Main);
  304. }
  305. .out-icon {
  306. width: 36rpx;
  307. height: 36rpx;
  308. margin-right: 26rpx;
  309. }
  310. .ss-modal-box {
  311. height: calc(100vh - 88rpx);
  312. // max-height: 1000rpx;
  313. .input-money {
  314. width:90% ;
  315. padding:0 10rpx;
  316. // text-indent: 20rpx;
  317. height: 80rpx;
  318. border: 1px solid #bbbbbb;
  319. border-radius: 10rpx;
  320. margin: 15rpx auto;
  321. font-size: 28rpx;
  322. input{
  323. width: 100%;
  324. height: 100%;
  325. font-size: 28rpx;
  326. }
  327. }
  328. .modal-header {
  329. position: relative;
  330. padding: 60rpx 20rpx 40rpx;
  331. .money-text {
  332. color: $red;
  333. font-size: 46rpx;
  334. font-weight: bold;
  335. font-family: OPPOSANS;
  336. &::before {
  337. content: '¥';
  338. font-size: 30rpx;
  339. }
  340. }
  341. .time-text {
  342. font-size: 26rpx;
  343. color: $gray-b;
  344. }
  345. .close-icon {
  346. position: absolute;
  347. top: 10rpx;
  348. right: 20rpx;
  349. font-size: 46rpx;
  350. opacity: 0.2;
  351. }
  352. }
  353. .modal-content {
  354. overflow-y: auto;
  355. .out-title {
  356. font-size: 26rpx;
  357. font-weight: 500;
  358. color: #333333;
  359. }
  360. .out-tip {
  361. font-size: 26rpx;
  362. color: #bbbbbb;
  363. }
  364. .out-item {
  365. height: 86rpx;
  366. }
  367. .disabled-out-item {
  368. .out-title {
  369. color: #999999;
  370. }
  371. }
  372. .userInfo-money {
  373. font-size: 26rpx;
  374. color: #bbbbbb;
  375. line-height: normal;
  376. }
  377. }
  378. .save-btn {
  379. width: 710rpx;
  380. height: 80rpx;
  381. border-radius: 40rpx;
  382. background: linear-gradient(90deg, var(--ui-BG-Main), var(--ui-BG-Main-gradient));
  383. color: $white;
  384. }
  385. .disabled-btn {
  386. background: #e5e5e5;
  387. color: #999999;
  388. }
  389. .past-due-btn {
  390. width: 710rpx;
  391. height: 80rpx;
  392. border-radius: 40rpx;
  393. background-color: #999;
  394. color: #fff;
  395. }
  396. }
  397. </style>