cash.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. <template>
  2. <div class="cash">
  3. <inner-header title="资金提现"></inner-header>
  4. <section class="content">
  5. <h2 v-if="isIdCard">提现到银行卡(
  6. <span v-if="userInfo.bankAccount">{{userInfo.bankAccount}}</span>
  7. <span v-else><a href="/wo/account_manage">去绑定银行卡</a></span>
  8. )</h2>
  9. <h2 v-else>提现到支付宝({{userInfo.alipay}})</h2>
  10. <div class="input-box">
  11. <el-input class="cash-input" placeholder="最少提现10元,每日上限3万元" v-model="coins"></el-input>
  12. <span class="input-icon">¥</span>
  13. <el-button type="text" class="get-all" @click="doGetAll">全部提现</el-button>
  14. </div>
  15. <div class="balance">
  16. 可用余额
  17. <span>¥{{(+userCanWithdrawAmount) || 0}}</span>元
  18. </div>
  19. <el-button @click="doGet" class="get-btn" type="primary">提现</el-button>
  20. <p class="remind-time">预计3~5个工作日到账</p>
  21. <p>提现说明</p>
  22. <!--银行卡-->
  23. <div class="reminds" v-if="isIdCard">
  24. <div>1.只有整包项目、云端工作项目薪酬,才支持提现到银行卡</div>
  25. <div>
  26. 2.请确认银行卡账号和实名认证信息保持一致,如需修改银 行卡账号,请前往
  27. <a href="/setting/user">实名个人信息</a>
  28. </div>
  29. <div>3.提现成功后,会在3-5个工作日内到账,节假日可能会稍有延时,请耐心等待,如长时间未到账( 超过5个工作日),可联系在线客服
  30. <!--<a href="/setting/user">在线客服</a>-->
  31. </div>
  32. </div>
  33. <!--支付宝-->
  34. <div class="reminds" v-else>
  35. <div>1.提现非客栈转入的资金需要收取{{rate}}的手续费</div>
  36. <div>2.提现成功后,会在3-5个工作日内到账,节假日可能会稍有延时,请耐心等待</div>
  37. <div>
  38. 3.请确认支付宝账号和实名认证信息保持一致,如需修改支付宝账号,请前往
  39. <a href="/setting/user">实名个人信息</a>
  40. </div>
  41. <div>4.如提现失败,或长时间未到账( 超过5个工作日),可联系在线客服</div>
  42. <div>5.为防止非法套现,充值的金额30个工作日后方可提现。</div>
  43. </div>
  44. </section>
  45. <el-dialog title="手机验证码确认" :visible.sync="dialogShow">
  46. <h1 class="dialog-h1">已向您的手机{{userinfo.mobile}}发送验证码</h1>
  47. <div class="ver-input">
  48. 请输入验证码
  49. <el-input v-model="ver"></el-input>
  50. </div>
  51. <div slot="footer" class="dialog-footer">
  52. <el-button @click="dialogShow = false">取 消</el-button>
  53. <el-button type="primary" @click="doDialogConfirm">确 定</el-button>
  54. </div>
  55. </el-dialog>
  56. <SuccessToast :isShowToast="isShowToastSuccess" @close="isShowToastSuccess=false"/>
  57. <el-dialog @close="qrcodeClose" title="温馨提示" :visible.sync="centerDialogVisible" width="350px" center>
  58. <p class="qrcode-tips">请打开支付宝扫码以下二维码</p>
  59. <div class="qrcode-img">
  60. <img :src="qrcodeBase64" />
  61. </div>
  62. </el-dialog>
  63. </div>
  64. </template>
  65. <script>
  66. import InputVer from "@/components/input/ver";
  67. import InnerHeader from "@/components/inner_header";
  68. import SuccessToast from "@/components/wo/successToast";
  69. const Max_Money = 30000
  70. const Min_Money = 10
  71. import QRCode from "qrcode";
  72. export default {
  73. components: {
  74. InputVer,
  75. InnerHeader,
  76. SuccessToast
  77. },
  78. data() {
  79. return {
  80. alipayInfo: {},
  81. dialogShow: false,
  82. // 提现金额
  83. coins: "",
  84. // 验证码
  85. ver: "",
  86. // 费率
  87. rate: "",
  88. isIdCard: false, //是否是提现到银行卡
  89. isShowToastSuccess: false, //是否展示成功后的提示
  90. qrcodeBase64: "",
  91. centerDialogVisible:false,
  92. timer:null,
  93. };
  94. },
  95. computed: {
  96. coinInfo() {
  97. return this.alipayInfo && this.alipayInfo.coinInfo || {};
  98. },
  99. userCanWithdrawAmount() {
  100. const {balance=0, incomeTaxBalance=0} = this.alipayInfo && this.alipayInfo.coinInfo || {}
  101. return this.isIdCard ? incomeTaxBalance : balance
  102. },
  103. userInfo() {
  104. return this.alipayInfo && this.alipayInfo.userInfo || {};
  105. }
  106. },
  107. created() {
  108. console.log('this.$route.query', this.$route.query)
  109. //type 1-支付宝 2-银行卡 默认是1
  110. const {type=1} = this.$route.query || {}
  111. this.isIdCard = Number(type) === 2
  112. },
  113. mounted() {
  114. this.getAlipayInfo();
  115. this.getRate();
  116. },
  117. methods: {
  118. /**
  119. * 全部提现
  120. */
  121. doGetAll() {
  122. this.coins = this.userCanWithdrawAmount;
  123. if (this.coins > Max_Money) {
  124. this.$message.info("每日最多可提现3万元")
  125. this.coins = Max_Money
  126. }
  127. },
  128. /**
  129. * 获取支付宝信息
  130. */
  131. async getAlipayInfo() {
  132. let res = await this.$axios.$post("/api/user/get_cash_info");
  133. console.log(res);
  134. if (res) {
  135. this.alipayInfo = res.data;
  136. const {alipay, bankAccount} = res.data.alipayInfo || {}
  137. //银行卡提现,但没绑定时 提示
  138. if (!bankAccount && this.isIdCard === 2) {
  139. this.$message.info("请前往程序员客栈APP绑定银行卡!")
  140. }
  141. }
  142. },
  143. /**
  144. * 获取费率
  145. */
  146. async getRate() {
  147. let res = await this.$axios.$post(`/api/pay/get_withdraw_rate`);
  148. console.log(res);
  149. if (res) {
  150. this.rate = res.data.withdraw_rate;
  151. }
  152. },
  153. /**
  154. * 点击提现
  155. */
  156. async doGet() {
  157. if (!(this.coins + "").replace(/[^\d\.]/g, "")) {
  158. this.$message("请输入提现金额");
  159. return;
  160. }
  161. //最少
  162. if (Min_Money > this.coins) {
  163. this.$message(`单次最少提现${Min_Money}元`);
  164. return;
  165. }
  166. //最多
  167. if (this.coins > Max_Money) {
  168. this.$message.info("每日最多可提现3万元")
  169. this.coins = Max_Money
  170. }
  171. //最多允许提现2位小数
  172. let docRight = (this.coins + "").split(".")[1]
  173. console.log("docRight", docRight)
  174. if (docRight && docRight.length > 2) {
  175. this.$message(`最多允许输入2位小数`);
  176. return;
  177. }
  178. // 错误处理
  179. let coinsNum = +(this.coins + "").replace(/[^\d\.]/g, "");
  180. if (
  181. !coinsNum ||
  182. !(this.coins + "").match(/^\d+(\.\d{1,2}){0,1}$/) ||
  183. coinsNum <= 1
  184. ) {
  185. this.$message("请输入正确的提现金额");
  186. return;
  187. }
  188. //余额不足
  189. if (coinsNum > this.userCanWithdrawAmount) {
  190. this.$message("可提现余额不足");
  191. return;
  192. }
  193. // 判断是否已过人脸
  194. let resutCheckUserCertInfo = await this.$axios.$post("/uapi/user/realName/check");
  195. if(resutCheckUserCertInfo.status != 1){
  196. this.$message.error(resutCheckUserCertInfo.info)
  197. return
  198. }
  199. let isFace = resutCheckUserCertInfo.data.is_face === 1
  200. let isNameCert = resutCheckUserCertInfo.data.type === 1
  201. if(!isNameCert){
  202. // 如果没有实名,跳到实名认证页,并需要过人脸
  203. location.href = '/frontend/name_cert?is_face_check=1'
  204. return
  205. }
  206. if(!isFace) {
  207. // 询问是否是否人脸认证
  208. let res = await this.isFaceComfirmByAsync()
  209. if(!res){
  210. return
  211. }
  212. // 请求二维码
  213. await this.callFaceQrcode()
  214. // 启动定时器
  215. let resutByTimer = await this.startCheckIsFaceTimer()
  216. if(resutByTimer){
  217. // 关闭二维码框
  218. this.centerDialogVisible = false
  219. }
  220. }
  221. this.dialogShow = true;
  222. let res = await this.$axios.$post("/api/user/send_mobile_auth_code", {
  223. mobile: this.userinfo.mobile,
  224. type: 3
  225. });
  226. },
  227. // 提示框async 包装
  228. async isFaceComfirmByAsync(){
  229. let that = this;
  230. return new Promise(function(resolve) {
  231. that.$confirm('为了您的资金安全,本次操作需要进行人脸认证。', '提示', {
  232. confirmButtonText: '确定',
  233. cancelButtonText: '取消',
  234. type: 'warning'
  235. })
  236. .then(() => {
  237. resolve(true)
  238. })
  239. .catch(() => {
  240. resolve(false)
  241. })
  242. })
  243. },
  244. /**
  245. * 检查是否完成人脸认证
  246. */
  247. async checkIsFace(){
  248. try{
  249. let res = await this.$axios.$post("/uapi/user/realName/check");
  250. if(res.status == 1 && res.data.is_face === 1){
  251. return true
  252. }else{
  253. return false
  254. }
  255. }catch(e){
  256. return false
  257. }
  258. },
  259. /**
  260. * 关闭二维码回调
  261. */
  262. qrcodeClose(){
  263. clearInterval(this.timer)
  264. this.timer = null
  265. },
  266. /**
  267. * 检查是否过人脸定时器
  268. */
  269. startCheckIsFaceTimer(){
  270. let that = this
  271. return new Promise(function(resolve){
  272. that.timer = setInterval(async () => {
  273. let isFace = await that.checkIsFace()
  274. // console.log("请求验证")
  275. if(isFace){
  276. clearInterval(that.timer)
  277. that.timer = null
  278. resolve(true)
  279. }
  280. },3000)
  281. })
  282. },
  283. /**
  284. * 获取人脸二维码
  285. */
  286. async callFaceQrcode(){
  287. try{
  288. let res = await this.$axios.$post("/uapi/user/realName/face");
  289. let qrcode = res.data.kezhan_url;
  290. // let qrcode = "http://baidu.com"
  291. let that = this;
  292. QRCode.toDataURL(
  293. qrcode, {
  294. errorCorrectionLevel: "H",
  295. margin: 1,
  296. width: 300
  297. },
  298. function (err, url) {
  299. that.qrcodeBase64 = url;
  300. that.centerDialogVisible = true
  301. }
  302. );
  303. }catch(e){
  304. return false
  305. }
  306. },
  307. /**
  308. * 点击验证码
  309. */
  310. doDialogConfirm() {
  311. if (!this.ver.trim()) {
  312. this.$message("请输入验证码");
  313. return;
  314. }
  315. this.$confirm("确定要进行取现操作吗?", "提示", {
  316. confirmButtonText: "确定",
  317. cancelButtonText: "取消",
  318. type: "warning"
  319. }).then(async () => {
  320. this.withdrawFn()
  321. });
  322. },
  323. /** 提现到支付宝 **/
  324. async withdrawFn() {
  325. let res = null
  326. if (this.isIdCard) {
  327. res = await this.$axios.$post("/api/account/takeSalary", {
  328. coins: +this.coins,
  329. auth_code: this.ver
  330. });
  331. } else {
  332. res = await this.$axios.$post("/api/account/take_coins_to_alipay", {
  333. coins: +this.coins,
  334. payee_real_name: this.userinfo.realname,
  335. alipay_account: this.userInfo.alipay,
  336. auth_code: this.ver
  337. });
  338. }
  339. if (res && Number(res.status) === 1) {
  340. this.$message({
  341. type: "success",
  342. message: res.info || "提现成功"
  343. });
  344. this.dialogShow = false
  345. setTimeout(() => {
  346. this.isShowToastSuccess = true
  347. this.getAlipayInfo()
  348. this.coins = 0
  349. }, 1000);
  350. }
  351. }
  352. }
  353. };
  354. </script>
  355. <style scoped>
  356. .cash {
  357. display: flex;
  358. flex-direction: column;
  359. align-items: center;
  360. /* height: 590px; */
  361. background: white;
  362. padding-bottom: 20px;
  363. }
  364. h2 {
  365. margin: 64px 0 8px;
  366. font-size: 14px;
  367. }
  368. .input-box {
  369. position: relative;
  370. width: 396px;
  371. }
  372. .cash-input {
  373. width: 396px;
  374. }
  375. .input-icon,
  376. .get-all {
  377. position: absolute;
  378. }
  379. .input-icon {
  380. top: 10px;
  381. left: 16px;
  382. font-size: 20px;
  383. }
  384. .get-all {
  385. top: 0;
  386. right: 20px;
  387. }
  388. .balance {
  389. color: #999;
  390. font-size: 13px;
  391. margin: 6px 0 24px;
  392. }
  393. .balance span {
  394. color: #ffa81a;
  395. }
  396. .get-btn {
  397. width: 244px;
  398. }
  399. .remind-time {
  400. color: #999;
  401. font-size: 12px;
  402. margin: 8px 0 28px;
  403. }
  404. .reminds {
  405. width: 396px;
  406. color: #919aa7;
  407. margin-top: 6px;
  408. line-height: 32px;
  409. }
  410. .ver-input {
  411. display: flex;
  412. align-items: center;
  413. justify-content: center;
  414. }
  415. .ver-input .el-input {
  416. margin-left: 10px;
  417. width: 280px;
  418. }
  419. .dialog-h1 {
  420. margin: 10px 0;
  421. text-align: center;
  422. }
  423. .qrcode-tips{
  424. text-align: center;
  425. }
  426. </style>