Init project

This commit is contained in:
lifizer
2023-09-20 21:49:33 +08:00
parent 85a5989c96
commit c9ceac9f37
710 changed files with 125705 additions and 0 deletions
+209
View File
@@ -0,0 +1,209 @@
<template>
<view class="user-addBankCard">
<view class="acea-row row-column">
<view class="input-box acea-row row-column">
<view class="input-item acea-row row-middle">
<view class="input-title">持卡人</view>
<view class="input">
<input
placeholder="请输入持卡人姓名"
placeholder-style="color:#DADCE0"
v-model="name"
/>
</view>
</view>
<view class="input-item acea-row row-middle">
<view class="input-title">卡号</view>
<view class="input">
<input
placeholder="请输入卡号"
placeholder-style="color:#DADCE0"
type="number"
v-model="cardNo"
@input='inputCardChange'
/>
</view>
</view>
<view class="input-item acea-row row-middle">
<view class="input-title">银行</view>
<view class="input acea-row row-middle" style="position: relative;">
<picker style="width: 100%;z-index: 1;" @change="bindPickerChange" :value="index" :range="banks">
<view class="" style="font-size: 28rpx;">{{ banks[index] }}</view>
</picker>
<uni-icons class="bankArrow" type="arrowright" size="13"></uni-icons>
</view>
</view>
</view>
<view class="acea-row row-center row-middle">
<button class="confirm-btn" @click="confirmAdd">确认添加</button>
</view>
</view>
</view>
</template>
<script>
import {bankList, addBankCard} from "@/api/user";
export default {
components: {},
data: function () {
return {
name: "",
cardNo: "",
bankName: "",
bankSub: "",
bankList: [],
banks: [],
index: 0,
showPicker: false
};
},
watch: {},
mounted: function () {
this.getBankList();
},
methods: {
inputCardChange: function (event) {
var value = event.target.value;
console.log('value:' + value);
this.cardNo = value.replace(/[^\d]/g, ""); // 不允许输入非数字字符
},
bindPickerChange: function (e) {
console.log('picker发送选择改变,携带值为', e.target.value);
this.index = e.target.value;
this.bankName = this.bankList[this.index].name;
},
bankSelectClick: function () {
this.showPicker = true;
},
onConfirmBank: function (value, index) {
this.bankName = value;
this.showPicker = false;
},
onBackClick: function () {
this.$router.back();
},
getBankList: function () {
let that = this;
bankList({
page: 1,
limit: 999
})
.then(res => {
that.bankList = res.data;
that.banks = [];
that.bankList.forEach(function (bank, idx) {
that.banks.push(bank.name);
if (idx == 0) {
that.bankName = bank.name;
}
});
})
.catch(err => {
that.$dialog.error(err.msg || "获取银行列表失败");
});
},
//提交
confirmAdd: function () {
let that = this;
//参数检查
if (that.name.length == 0) {
that.$dialog.error("请输入持卡人姓名");
return;
}
if (that.cardNo.length == 0) {
that.$dialog.error("请输入银行卡号");
return;
}
if (that.bankName.length == 0) {
that.$dialog.error("请选择银行");
return;
}
that.$dialog.loading.open();
addBankCard({
bankName: that.bankName,
// bankSub: that.bankSub,
cardNo: that.cardNo,
name: that.name
})
.then(res => {
that.$dialog.loading.close();
that.$dialog.toast({mes: "添加成功"});
setTimeout(function () {
that.$yrouter.back();
}, 1000);
})
.catch(err => {
that.$dialog.loading.close();
that.$dialog.error(err.msg || "添加失败");
});
}
}
};
</script>
<style scoped lang="less">
.user-addBankCard {
min-height: 100vh;
padding: 60rpx 32rpx;
background: #F9F9F9;
color: #333333;
font-size: 24rpx;
line-height: 34rpx;
.input-box {
.input-item {
margin-bottom: 24rpx;
.input-title {
width: 96rpx;
margin-right: 10rpx;
font-weight: bold;
flex-shrink: 0;
}
.input {
position: relative;
height: 80rpx;
box-sizing: border-box;
padding: 8rpx 24rpx;
border-radius: 12rpx;
background: #FFFFFF;
flex-grow: 1;
input {
width: 100%;
height: 100%;
}
}
.bankArrow {
position: absolute;
right: 24rpx;
top: 0;
line-height: 80rpx;
}
}
}
.confirm-btn {
width: 686rpx;
height: 80rpx;
margin-top: 56rpx;
border-radius: 8rpx;
background: #FD574B;
color: #FFFFFF;
font-size: 28rpx;
}
}
</style>
+274
View File
@@ -0,0 +1,274 @@
<template>
<view class="container">
<mescroll-body ref="mescrollRef" top="0" bottom="0" class='cotent-scroll' :up="upOption" :down="downOption"
@up="upCallback" @down="downCallback" @init="mescrollInit" @emptyclick="emptyClick">
<view id="dataList" class="data-list acea-row row-column">
<view class="item acea-row row-column" :style="{'background':card.bgColor}" :key="index"
v-for="(card, index) in list" @click="cardClick(card)">
<view class="acea-row row-column">
<view class="acea-row row-between">
<view class="txt-bankname">{{ card.bankName }}</view>
<view class="unbind-btn" @click="unbindCard(index)">解除绑定</view>
</view>
<view class="acea-row row-middle" style="margin-top: 58rpx;flex-wrap: nowrap;">
<view class="acea-row row-left" style="flex: 1;margin-right: 18rpx;">
<view class="dot"></view>
<view class="dot"></view>
<view class="dot"></view>
<view class="dot"></view>
</view>
<view class="acea-row row-left" style="flex: 1;margin-right: 18rpx;">
<view class="dot"></view>
<view class="dot"></view>
<view class="dot"></view>
<view class="dot"></view>
</view>
<view class="acea-row row-left" style="flex: 1;margin-right: 18rpx;">
<view class="dot"></view>
<view class="dot"></view>
<view class="dot"></view>
<view class="dot"></view>
</view>
<view class="" style="flex-shrink: 0;">
<text class="txt-cardno">{{ last4CardNo(card.cardNo) }}</text>
</view>
</view>
<view class="txt-name" style="margin-top: 38rpx;">{{ card.name }}</view>
</view>
</view>
</view>
<view class="bottom-buttons-wrap acea-row row-middle row-between" @click="addBtnClick">
<view class="" style="color: #999999;font-size: 28rpx;">添加银行卡</view>
<view class="acea-row row-middle">
<image style="width: 82rpx;height: 82rpx;" :src="webUrl+'/20220922225634717078.png'" mode=""></image>
</view>
</view>
<view id="loading-more"></view>
</mescroll-body>
</view>
</template>
<script>
import MescrollMixins from "@/mixins/mescroll-mixins.js";
import MescrollBody from "@/components/mescroll-uni/mescroll-body.vue";
import {getBank, postCashInfo, bankCardList, deleteBankCard} from "@/api/user";
export default {
data() {
return {
list: [],
upOption: {
noMoreSize: 10, //如果列表已无数据,可设置列表的总数量要大于半页才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看; 默认5
auto: true,
empty: {
tip: '暂无银行卡' // 提示
// btnText:'点击刷新'
}
},
downOption: {
auto: false
},
isSelectMode: false,
webUrl: this.$VUE_APP_RESOURCES_URL,
bgColor: ["#FD574B", "#0DC5C5", "#3F57DA", "#FF4F48"]
}
},
components: {
MescrollBody
},
mixins: [
MescrollMixins({
getPageData(mescroll) {
var _this = this;
// 此时mescroll会携带page的参数:
let pageNum = mescroll.num; // 页码, 默认从1开始
let pageSize = mescroll.size; // 页长, 默认每页10条
var params = {
limit: pageNum,
page: pageSize
}
bankCardList(params)
.then(res => {
if (mescroll.num == 1) {
_this.list = []; //如果是第一页需手动制空列表
}
_this.list = _this.list.concat(res.data);//追加新数据
_this.handleColor();
//mescroll.endByPage(res.data, res.data.total);
mescroll.endSuccess(res.data.length);
})
.catch(err => {
mescroll.endErr();
uni.showToast({
title: err + '',
icon: 'none',
mask: false,
duration: 1500
});
})
}
})
],
onLoad: function (e) {
//从query里取模式
this.isSelectMode = this.$yroute.query.isSelected;
},
onShow: function () {
//静默刷新
this.mescroll && this.mescroll.resetUpScroll(false);
},
methods: {
last4CardNo: function (cardNo) {
var str = cardNo;
var reg = /^\d+(\d{4})$/;
str = str.replace(reg, "$1");
return str;
},
formartCard: function (cardNo) {
var str = cardNo;
var reg = /^(\d{4})\d+(\d{4})$/;
str = str.replace(reg, "$1 **** **** $2");
return str;
//return cardNo.replace(/(\d{4})(?=\d)/g, '$1 ');
},
cardClick: function (card) {
//判断是否选择模式
if (this.isSelectMode) {
//把数据放入本地存储里,返回上一页时再取出来
//localStorage.setItem("selectedBankCard", JSON.stringify(card));
// uni.setStorage({
// "selectedBankCard":JSON.stringify(card)
// });
uni.setStorageSync("selectedBankCard", JSON.stringify(card));
this.$yrouter.back();
} else {
}
},
addBtnClick: function () {
uni.navigateTo({
url:"addBankCard"
})
},
unbindCard: function (index) {
let that = this;
let card = that.list[index];
let id = card.id;
uni.showModal({
title: '是否解绑此银行卡?',
content: '',
showCancel: true,
cancelText: '否',
confirmText: '是',
success: res1 => {
if (res1.confirm) {
deleteBankCard({
id: id
}).then(res => {
uni.showToast({
title: res.msg,
icon: "success",
duration: 2000
});
//刷新界面数据
that.mescroll && that.mescroll.resetUpScroll(false);
});
} else {
}
},
fail: () => {
},
complete: () => {
}
});
},
handleColor() {
if (this.list.length > 0) {
this.list.forEach((item, index) => {
item.bgColor = this.bgColor[index % 4];
})
}
}
}
}
</script>
<style>
.data-list {
padding: 40rpx 32rpx 0;
}
.item {
flex-wrap: nowrap;
margin-bottom: 40rpx;
padding: 32rpx 40rpx;
/*background: linear-gradient(*/
/* 221deg,*/
/* rgba(255, 187, 140, 1) 0%,*/
/* rgba(250, 134, 135, 1) 100%*/
/*);*/
opacity: 1;
border-radius: 20rpx;
}
.txt-bankname {
font-size: 30rpx;
color: #fff;
font-weight: bold;
}
.txt-cardno {
font-size: 40rpx;
color: #fff;
font-weight: bold;
}
.txt-name {
font-size: 26rpx;
color: #fff;
font-weight: bold;
}
.unbind-btn {
font-size: 22rpx;
color: rgba(255, 255, 255, 0.6);
}
.bottom-buttons-wrap {
height: 106rpx;
margin: 0 32rpx;
padding: 0 26rpx 0 48rpx;
box-shadow: 0px 6px 20px rgba(0, 0, 0, 0.16);
background-color: #fff;
}
.add-btn {
font-size: 36rpx;
background: linear-gradient(90deg, rgba(255, 149, 141, 1) 0%, rgba(255, 94, 138, 1) 100%);
border-radius: 44rpx;
color: rgba(255, 255, 255, 1);
padding: 20rpx 70rpx;
flex-wrap: nowrap;
}
.dot {
width: 18rpx;
height: 18rpx;
background: #fff;
border-radius: 50%;
opacity: 0.3;
margin-right: 18rpx;
}
</style>
+222
View File
@@ -0,0 +1,222 @@
<template>
<view class="user-bindPhone">
<view class="input-box flex ai-center" style="margin-bottom: 32rpx">
<image class="icon-phone flex-0" :src="webUrl+'/20220925102913233030.png'"/>
<input v-model="phone" type="number" placeholder="请填写手机号码" placeholder-style="color:#E2E2E2"/>
</view>
<view class="flex jc-between ai-center">
<view class="input-box flex ai-center">
<input v-model="captcha" type="text" placeholder="请填写验证码" placeholder-style="color:#E2E2E2"/>
</view>
<button class="btn-code" :class="disabled === true ? 'on' : ''"
:disabled="disabled" @click="code">{{ text }}
</button>
</view>
<button class="btn-save" @click="confirm">确认绑定</button>
</view>
</template>
<script>
import {mapGetters} from "vuex";
import sendVerifyCode from "@/mixins/SendVerifyCode";
import {required, alpha_num, chs_phone} from "@/utils/validate";
import {validatorDefaultCatch} from "@/utils/dialog";
import {registerVerify, bindingPhoneByInput} from "@/api/user";
export default {
name: "BindingPhone",
components: {},
props: {},
data: function () {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
captcha: "",
phone: "" //手机号
};
},
mixins: [sendVerifyCode],
computed: mapGetters(["userInfo"]),
mounted: function () {
},
methods: {
async confirm() {
let that = this;
const {phone, captcha} = that;
try {
await that
.$validator({
phone: [
chs_phone(chs_phone.message("手机号码")),
alpha_num(alpha_num.message())
],
captcha: [
required(required.message("验证码")),
alpha_num(alpha_num.message("验证码"))
]
})
.validate({phone, captcha});
} catch (e) {
return validatorDefaultCatch(e);
}
bindingPhoneByInput({
phone: this.phone,
captcha: this.captcha
})
.then(res => {
if (res.data !== undefined && res.data.is_bind) {
uni.showModal({
title: "提示",
content: "确认绑定?",
success: function (res) {
if (res.confirm) {
bindingPhoneByInput({
phone: this.phone,
captcha: this.captcha,
step: 1
})
.then(res => {
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
that.$yrouter.replace({
path: "/pkg_user/views/personalData"
});
})
.catch(res => {
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
that.$yrouter.replace({
path: "/pkg_user/views/personalData"
});
});
} else if (res.cancel) {
uni.showToast({
title: "已取消绑定",
icon: "none",
duration: 2000
});
that.$yrouter.replace({
path: "/pkg_user/views/personalData"
});
}
}
});
} else {
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
that.$yrouter.replace({
path: "/pkg_user/views/personalData"
});
}
})
.catch(res => {
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
});
},
async code() {
let that = this;
const {phone} = that;
try {
await that
.$validator({
phone: [
required(required.message("手机号码")),
chs_phone(chs_phone.message())
]
})
.validate({phone});
} catch (e) {
return validatorDefaultCatch(e);
}
registerVerify({phone: phone})
.then(res => {
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
that.sendCode();
})
.catch(res => {
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
});
}
}
};
</script>
<style scoped lang="less">
.user-bindPhone {
min-height: 100vh;
padding: 60rpx 32rpx;
background: #F9F9F9;
font-size: 28rpx;
line-height: 40rpx;
button {
border-radius: 8rpx;
color: #FFFFFF;
font-size: 28rpx;
font-weight: bold;
}
button:after {
display: none;
}
.input-box {
height: 100rpx;
padding: 0 36rpx;
border-radius: 8rpx;
background: #FFFFFF;
color: #999999;
.icon-phone {
width: 48rpx;
height: 48rpx;
vertical-align: middle;
margin-right: 20rpx;
}
input {
font-size: 28rpx;
line-height: 40rpx;
}
}
.btn-code {
width: 200rpx;
height: 72rpx;
margin: 0 0 0 32rpx;
background: #28AAF4;
line-height: 72rpx;
}
.btn-save {
height: 80rpx;
margin-top: 80rpx;
background: #FD574B;
line-height: 80rpx;
}
}
</style>
+285
View File
@@ -0,0 +1,285 @@
<template>
<view class="user-payPassword">
<!-- <view class="content acea-row row-column">-->
<!-- <input class="phone-input" type="text" :value="phone" disabled/>-->
<!-- <view class="acea-row row-middle" style="flex-wrap: nowrap;">-->
<!-- <input type="text" placeholder="填写验证码" placeholder-style="color:#DADCE0;font-size:28rpx;" class="codeIput" v-model="captcha" />-->
<!-- <button-->
<!-- class="code acea-row row-middle"-->
<!-- :disabled="disabled"-->
<!-- :class="disabled === true ? 'on' : ''"-->
<!-- @click="code"-->
<!-- >{{ text }}</button>-->
<!-- </view>-->
<!-- <input type="number" maxlength="6" password placeholder="请输新6位数字支付密码" placeholder-style="color:#DADCE0;font-size:28rpx" class="payPwdInput" v-model="payPwd" @input='inputPaypwdChange' />-->
<!-- </view>-->
<!-- <view class="confirmBnt bg-color-red" @click="confirm()">保存</view>-->
<view class="input-box flex ai-center" style="margin-bottom: 32rpx">
<image class="icon-phone flex-0" :src="webUrl+'/20220925102913233030.png'"/>
<input :value="phone" disabled/>
</view>
<view class="flex jc-between ai-center">
<view class="input-box flex ai-center">
<input v-model="captcha" type="text" placeholder="请填写验证码" placeholder-style="color:#E2E2E2"/>
</view>
<button class="btn-code" :class="disabled === true ? 'on' : ''"
:disabled="disabled" @click="code">{{ text }}
</button>
</view>
<view class="input-box flex ai-center" style="margin-top: 32rpx">
<input style="width: 100%" v-model="payPwd" type="number" maxlength="6" placeholder="请重新输入6位数字支付密码" placeholder-style="color:#E2E2E2" @input="inputPaypwdChange"/>
</view>
<button class="btn-save" @click="confirm">保存</button>
</view>
</template>
<script>
import { mapGetters } from "vuex";
import sendVerifyCode from "@/mixins/SendVerifyCode";
import { required, alpha_num, chs_phone } from "@/utils/validate";
import { validatorDefaultCatch } from "@/utils/dialog";
import { getUserInfo, registerVerify, bindingPhone,modifyUserPayPwd } from "@/api/user";
export default {
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
captcha: "",
phone:'',
payPwd:''
}
},
mixins: [sendVerifyCode],
watch:{
userInfo(){
this.phone = this.userInfo.phone;
}
},
computed:{
...mapGetters(["userInfo"]),
},
onLoad:function(e){
if (e.isSetMode) {
uni.setNavigationBarTitle({
title: '设置支付密码'
});
} else{
uni.setNavigationBarTitle({
title: '修改支付密码'
});
}
//获取用户信息
if (this.$store.getters.token) {
this.$store.dispatch("getUser", true);
}
},
methods: {
inputPaypwdChange:function(event){
var value = event.target.value;
var filterValue = value.replace(/\D/g,"");
//console.log('value:'+filterValue);
this.payPwd = filterValue; // 不允许输入非数字字符
},
async code() {
let that = this;
const { phone } = that;
try {
await that
.$validator({
phone: [
required(required.message("手机号码")),
chs_phone(chs_phone.message())
]
})
.validate({ phone });
} catch (e) {
return validatorDefaultCatch(e);
}
registerVerify({ phone: phone })
.then(res => {
uni.showToast({
title: res.data,
icon: "none",
duration: 2000
});
that.sendCode();
})
.catch(res => {
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
});
},
async confirm() {
let that = this;
const { phone, captcha, payPwd } = that;
try {
await that
.$validator({
phone: [
chs_phone(chs_phone.message("手机号码")),
alpha_num(alpha_num.message())
],
captcha: [
required(required.message("验证码")),
alpha_num(alpha_num.message("验证码"))
],
payPwd: [
required(required.message("支付密码")),
alpha_num(alpha_num.message("支付密码"))
]
})
.validate({ phone, captcha,payPwd });
} catch (e) {
return validatorDefaultCatch(e);
}
//网络请求
uni.showLoading();
modifyUserPayPwd({
passwordPay:that.payPwd,
code:that.captcha,
phone:that.phone
}).then((res)=>{
//提示成功并返回
uni.hideLoading();
that.$dialog.toast({ mes: "保存成功" });
setTimeout(function(){
that.$yrouter.back();
},1000);
}).catch((err)=>{
uni.hideLoading();
that.$dialog.error(err.msg || "修改失败");
})
}
}
}
</script>
<style scoped lang="less">
.user-payPassword{
min-height: 100vh;
padding: 60rpx 32rpx;
background: #F9F9F9;
font-size: 28rpx;
line-height: 40rpx;
button {
border-radius: 8rpx;
color: #FFFFFF;
font-size: 28rpx;
font-weight: bold;
}
button:after {
display: none;
}
.input-box {
height: 100rpx;
padding: 0 36rpx;
border-radius: 8rpx;
background: #FFFFFF;
color: #999999;
.icon-phone {
width: 48rpx;
height: 48rpx;
vertical-align: middle;
margin-right: 20rpx;
}
input {
font-size: 28rpx;
line-height: 40rpx;
}
}
.btn-code {
width: 200rpx;
height: 72rpx;
margin: 0 0 0 32rpx;
background: #28AAF4;
line-height: 72rpx;
}
.btn-save {
height: 80rpx;
margin-top: 80rpx;
background: #FD574B;
line-height: 80rpx;
}
}
/*page{*/
/* background: #fff;*/
/*}*/
/*.container{*/
/* background: #fff;*/
/*}*/
/*.confirmBnt {*/
/* font-size: 32rpx;*/
/* width: 580rpx;*/
/* height: 90rpx;*/
/* border-radius: 45rpx;*/
/* color: #fff;*/
/* margin: 92rpx auto 0 auto;*/
/* text-align: center;*/
/* line-height: 90rpx;*/
/*}*/
/*.content{*/
/* margin: 114rpx;*/
/*}*/
/*.phone-input{*/
/* color: #8B8F99;*/
/* font-size: 36rpx;*/
/* height:88rpx;*/
/* background:rgba(247,247,249,1);*/
/* opacity:1;*/
/* border-radius:12rpx;*/
/* margin-bottom: 32rpx;*/
/*}*/
/*.codeIput{*/
/* font-size: 28rpx;*/
/* height:88rpx;*/
/* border:1px solid rgba(218,220,224,1);*/
/* opacity:1;*/
/* border-radius:12rpx;*/
/* flex-grow: 1;*/
/*}*/
/*.code{*/
/* !* width:224rpx; *!*/
/* height:88rpx;*/
/* background:rgba(121,129,253,1);*/
/* opacity:1;*/
/* color: #fff;*/
/* font-size: 28rpx;*/
/* border-radius:12rpxpx;*/
/* flex-shrink: 0;*/
/* margin-left: 16rpx;*/
/* text-align: center;*/
/* padding-left: 24rpx;*/
/* padding-right: 24rpx;*/
/*}*/
/*.payPwdInput{*/
/* font-size: 28rpx;*/
/* height:88rpx;*/
/* border:1px solid rgba(218,220,224,1);*/
/* opacity:1;*/
/* border-radius:12rpx;*/
/* margin-top: 32rpx;*/
/*}*/
</style>
+366
View File
@@ -0,0 +1,366 @@
<template>
<view class="user-personalData">
<view class="top-box" :style="{'backgroundImage':`url(${webUrl}/20220925102928757633.png)`}">
<view class="flex ai-center">
<image-cropper :src="tempFilePath" @confirm="confirm" @cancel="cancel"></image-cropper>
<view style="position: relative" @tap="chooseImage">
<image class="cover" :src="avatar"/>
<image class="btn-change" :src="webUrl+'/20220925111121285647.png'"/>
</view>
<view>
<view class="name">{{ userInfo.nickname }}</view>
<view class="phone">绑定手机号{{ userInfo.phone || '未绑定' }}</view>
</view>
</view>
</view>
<view class="cell-box">
<view class="cell flex jc-between ai-center">
<view class="flex ai-center">
<view class="title">昵称</view>
<view class="value">
<input type="text" v-model="userInfo.nickname"/>
</view>
</view>
<view class="icon">
<image :src="webUrl+'/20220903145836941399.png'"/>
</view>
</view>
<view class="cell flex jc-between ai-center">
<view class="flex ai-center">
<view class="title">ID号</view>
<view class="value">{{ userInfo.uid }}</view>
</view>
<view class="icon">
<image :src="webUrl+'/20220925102920713727.png'" style="width: 40rpx;height: 40rpx"/>
</view>
</view>
<view class="cell flex jc-between ai-center" @click="bindPhone">
<view class="flex ai-center">
<view class="title">手机号</view>
<view class="value">{{ userInfo.phone || '未绑定' }}</view>
</view>
<view class="icon">
<image :src="webUrl+'/20220903145836941399.png'"/>
</view>
</view>
<view class="cell flex jc-between ai-center" @click="payPwdClick">
<view class="flex ai-center">
<view class="title">支付密码</view>
<view class="value"></view>
</view>
<view class="icon">
<image :src="webUrl+'/20220903145836941399.png'"/>
</view>
</view>
</view>
<button class="btn-save" @click="submit">保存修改</button>
<!-- <view class="list">-->
<!-- <view class="item acea-row row-between-wrapper">-->
<!-- <view>昵称</view>-->
<!-- <view class="input">-->
<!-- <input type="text" v-model="userInfo.nickname"/>-->
<!-- </view>-->
<!-- </view>-->
<!-- <view class="item acea-row row-between-wrapper">-->
<!-- <view>ID号</view>-->
<!-- <view class="input acea-row row-between-wrapper">-->
<!-- <input type="text" :value="userInfo.uid" disabled class="id"/>-->
<!-- <text class="iconfont icon-suozi"></text>-->
<!-- </view>-->
<!-- </view>-->
<!-- <view class="item acea-row row-between-wrapper" @click="bindPhone">-->
<!-- <view>手机号</view>-->
<!-- <view class="input acea-row row-between-wrapper">-->
<!-- <input type="text" disabled v-if="userInfo.phone" v-model="userInfo.phone" class="id"/>-->
<!-- <input type="text" v-else value="未绑定" disabled class="id"/>-->
<!-- <text class="iconfont icon-jiantou"></text>-->
<!-- </view>-->
<!-- </view>-->
<!-- <view class="item acea-row row-between-wrapper" @click="payPwdClick">-->
<!-- <view>支付密码</view>-->
<!-- <view class="input acea-row row-right">-->
<!-- <text class="iconfont icon-jiantou"></text>-->
<!-- </view>-->
<!-- </view>-->
<!-- </view>-->
<!-- <view class="modifyBnt bg-color-lightred" @click="submit">保存修改</view>-->
<view
class="logOut cart-color acea-row row-center-wrapper"
@click="logout"
v-if="$deviceType=='app'"
>退出登录
</view>
</view>
</template>
<script>
import {mapGetters} from "vuex";
import {trim, isWeixin, chooseImage, uploadImage} from "@/utils";
import {
postUserEdit,
getLogout,
switchH5Login
} from "@/api/user";
import cookie from "@/utils/store/cookie";
import store from "@//store";
import dayjs from "dayjs";
import ImageCropper from "@/pkg_user/components/invinbg-image-cropper/invinbg-image-cropper.vue";
export default {
name: "PersonalData",
components: {
ImageCropper
},
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
avatar: "",
isWeixin: false,
currentAccounts: 0,
switchUserInfo: [],
userIndex: 0,
tempFilePath: '',
cropFilePath: '',
};
},
computed: mapGetters(["userInfo"]),
mounted: function () {
this.avatar = this.userInfo.avatar;
this.isWeixin = isWeixin();
},
onShow: function () {
//获取用户信息
this.$store.dispatch("getUser", true);
},
methods: {
confirm(e) {
this.tempFilePath = '';
this.cropFilePath = e.detail.tempFilePath;
uploadImage(this.cropFilePath, img => {
console.log(img)
this.avatar = img;
this.cropFilePath = '';
})
},
cancel() {
console.log('canceled')
},
bindPhone: function () {
this.$yrouter.push("/pkg_user/views/bindPhone");
},
payPwdClick: function () {
//先判断用户是否绑定过手机
if (this.userInfo.phone) {
//再判断用户是否设置过支付密码
if (this.userInfo.hasPwdPay) {
//修改支付密码
this.$yrouter.push("/pkg_user/views/payPassword");
} else {
//设置支付密码
this.$yrouter.push("/pkg_user/views/payPassword?isSetMode=true");
}
} else {
//跳转到绑定手机
this.$yrouter.push("/pkg_user/views/bindPhone");
}
},
switchAccounts: function (index) {
let that = this;
this.userIndex = index;
let userInfo = this.switchUserInfo[this.userIndex];
if (this.switchUserInfo.length <= 1) return true;
if (userInfo === undefined) {
uni.showToast({
title: "切换的账号不存在",
icon: "none",
duration: 2000
});
return;
}
if (userInfo.user_type === "h5") {
switchH5Login()
.then(({data}) => {
uni.hideLoading();
const expires_time = dayjs(data.expires_time);
store.commit("login", data.token, expires_time);
that.$emit("changeswitch", false);
location.reload();
})
.catch(err => {
uni.hideLoading();
uni.showToast({
title:
err.msg || err.response.data.msg || err.response.data.message,
icon: "none",
duration: 2000
});
});
} else {
cookie.set("loginType", "wechat", 60);
uni.hideLoading();
this.$store.commit("logout");
this.$emit("changeswitch", false);
}
},
chooseImage() {
uni.chooseImage({
count: 1, //默认9
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
sourceType: ['album'], //从相册选择
success: (res) => {
this.tempFilePath = res.tempFilePaths.shift()
}
});
},
submit: function () {
let userInfo = this.userInfo;
let that = this;
postUserEdit({
nickname: trim(this.userInfo.nickname),
avatar: this.avatar
}).then(
res => {
that.$store.dispatch("userInfo", true);
uni.showToast({
title: res.msg,
icon: "none",
duration: 2000
});
setTimeout(function () {
that.$yrouter.back();
}, 2000)
},
err => {
uni.showToast({
title:
err.msg || err.response.data.msg || err.response.data.message,
icon: "none",
duration: 2000
});
}
);
},
logout: function () {
uni.showModal({
title: "提示",
content: "确认退出登录?",
success: function (res) {
if (res.confirm) {
getLogout()
.then(res => {
this.$store.commit("logout");
this.$yrouter.replace({
path: "/pages/user/Login/index",
query: {}
});
})
.catch(err => {
});
} else if (res.cancel) {
// console.log("用户点击取消");
}
}
});
}
}
};
</script>
<style scoped lang="less">
.user-personalData {
min-height: 100vh;
background: #F9F9F9;
view {
box-sizing: border-box;
}
.top-box {
width: 100vw;
height: 332.5rpx;
padding: 94rpx 0 0 104rpx;
background-size: 750rpx 332.5rpx;
color: #FFFFFF;
.cover {
width: 136rpx;
height: 136rpx;
border-radius: 50%;
margin-right: 42rpx;
}
.btn-change {
position: absolute;
top: 100rpx;
left: 13rpx;
width: 110rpx;
height: 44rpx;
}
.name {
font-size: 32rpx;
line-height: 48rpx;
font-weight: bold;
}
.phone {
margin-top: 22rpx;
font-size: 28rpx;
line-height: 40rpx;
}
}
.cell-box {
margin: 54rpx 32rpx;
padding: 0 25rpx;
border-radius: 12rpx;
background: #FFFFFF;
.cell:last-child {
border-bottom: none;
}
.cell {
padding: 32rpx 0 20rpx;
border-bottom: 1rpx solid #E8E9E9;
font-size: 28rpx;
line-height: 40rpx;
.title {
width: 112rpx;
margin-right: 40rpx;
color: #333333;
font-weight: bold;
}
.value {
color: #999999;
}
.icon {
image {
width: 26rpx;
height: 26rpx;
}
}
}
}
.btn-save {
margin: 0 32rpx;
background: #FE5261;
color: #FFFFFF;
font-size: 32rpx;
}
}
</style>
+467
View File
@@ -0,0 +1,467 @@
<template>
<view class="user-withdrawal">
<view class="bold">提现到</view>
<view class="bank-box acea-row row-between row-middle" @click="bankSelect">
<view class="acea-row row-middle" v-if="selectedBank">
<image class="icon-card" :src="webUrl+'/20220924105211695252.png'"/>
<view class="acea-row row-column">
<span class="bold">{{ selectedBank.bankName }}</span>
<span class="bold">{{ selectedBank.cardNo }}/{{ selectedBank.name }}</span>
</view>
</view>
<view class="flex ai-center bold" v-else>
<image class="icon-card" :src="webUrl+'/20220924105211695252.png'"/>
请选择银行卡
</view>
</view>
<view class="amount-box">
<view class="title bold">提现金额</view>
<view class="item acea-row row-middle">
<view class="dollar bold"></view>
<view class="input">
<input
:placeholder="'最低提现金额' + minPrice"
placeholder-style="font-size:28rpx"
v-model="amout"
:maxlength='maxlength'
@blur="balanceInputBlur"
@input="balanceInputChange"
type="digit"
autofocus
/>
</view>
<button class="withdraw-all-btn" @click="withdrawalAll">全部提现</button>
</view>
<view class="vline"></view>
<view class="acea-row row-between row-middle" style="margin-top: 22rpx;">
<view class="bold">可提现金额{{ commissionCount }}</view>
<view class="bold">手续费
<text class="red">{{ totalFee }}</text>
</view>
</view>
</view>
<view class="acea-row row-column row-middle">
<button class="confirm-btn" @click="confrimBtnClick">提现</button>
<view class="record-btn" style="" @click="goCashRecord">提现记录</view>
</view>
<uni-popup ref="popup" type="bottom">
<blPaymentPasswordInput hideTopBorder ref="secrity" @input="onInput" @confirm="onConfirm">
<block slot='header' style='width: 100%;'>
<view style="font-size: 36rpx;color: #8B8F99;margin-top: 10rpx;">请输入支付密码</view>
</block>
<block slot='middle'>
<view class="" style="background-color: #fff;"></view>
</block>
</blPaymentPasswordInput>
</uni-popup>
</view>
</template>
<script>
import {mapGetters} from "vuex";
import {getUserInfo, getMenuUser, bindingPhone, getBank, bankCardList, postCashInfo} from "@/api/user";
import NP from "number-precision";
import uniPopup from '@/components/uni-popup/uni-popup.vue';
import blPaymentPasswordInput from '@/components/blPaymentPasswordInput.vue';
export default {
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
payPwd: "",
selectedBank: null,
amout: "",
minPrice: 0,
banks: [],
maxlength: -1,
commissionCount: 0, //可提现金额
fee: 0, //手续费
gdAmount: 0, //固定手续费
gdLimit: 0, //最低固定费率额度
feeRate: 0, //手续费费率
remark: "" //提现说明
}
},
components: {
uniPopup,
blPaymentPasswordInput
},
computed: {
...mapGetters(["userInfo"]),
//计算手续费
totalFee() {
/*
if( 提现金额 < gdLimit ) sxf = gdAmount
if( 提现金额 >= gdLimit ) sxf = 提现金额*fl
*/
return this.calculateSxf(this.amout);
}
},
onLoad: function (e) {
this.getBank();
this.getDefaultBankCards();
},
onShow() {
if (this.$store.getters.token) {
this.$store.dispatch("getUser", true);
}
//获取选择的银行卡
let card = uni.getStorageSync('selectedBankCard');
if (card) {
console.log("card:" + JSON.parse(card));
this.selectedBank = JSON.parse(card);
//清空存储
uni.removeStorageSync('selectedBankCard');
}
},
methods: {
calculateSxf: function (amout) {
var sxf = 0;
if (amout == 0) {
return sxf;
}
if (parseFloat(this.gdLimit) > 0 && amout < parseFloat(this.gdLimit)) {
sxf = parseFloat(this.gdAmount);
console.log("fixed");
} else {
if (parseFloat(this.feeRate) > 0) {
sxf = NP.times(amout, NP.divide(parseFloat(this.feeRate), 100));
}
console.log("variable");
}
console.log("sxf:" + sxf);
return this.$force2Decimal(sxf);
},
goCashRecord() {
this.$yrouter.push("/pages/user/promotion/CashRecord/index");
},
clearNoNum: function (value) {
var str = value;
var len1 = str.substr(0, 1);
var len2 = str.substr(1, 1);
//如果第一位是0,第二位不是点,就用数字把点替换掉
if (str.length > 1 && len1 == 0 && len2 != ".") {
str = str.substr(1, 1);
}
//第一位不能是.
if (len1 == ".") {
str = "";
}
//限制只能输入一个小数点
if (str.indexOf(".") != -1) {
var str_ = str.substr(str.indexOf(".") + 1);
if (str_.indexOf(".") != -1) {
str = str.substr(0, str.indexOf(".") + str_.indexOf(".") + 1);
}
}
value = str
var index = String(value).indexOf('.');
value = value.replace(/[^\d.]/g, ""); //清除“数字”和“.”以外的字符
// value = value.replace(/\.{2,}/g,"."); //只保留第一个. 清除多余的
// value = value.replace(".","$#$").replace(/\./g,"").replace("$#$",".");
value = value.replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3');//只能输入两个小数
//修复可输入3位小数的bug
if (index != -1) {
var arrStr = [];
arrStr = String(value).split('.');
//当小数位数达两位的时候,设备最大输入长度为当前长度
if (arrStr[1] && arrStr[1].length == 2) {
this.maxlength = String(value).length
} else {
this.maxlength = -1//恢复
}
} else {
this.maxlength = -1//恢复
}
return value
},
balanceInputChange: function (e) {
var value = e.target.value;
this.amout = value
var v = this.clearNoNum(value)
setTimeout(() => {
this.amout = v
}, 0)
},
balanceInputBlur: function (e) {
var value = e.target.value;
if (String(value).length == 0) {
this.amout = 0
}
},
openPwdInput() {
this.$refs.popup.open();
},
//支付密码输入监听
onInput(e) {
},
// 支付密码输入确认
onConfirm(e) {
let password = e.value;
this.payPwd = password;
if (this.payPwd.length == 0 || this.payPwd.length < 6) {
uni.showToast({
title: '请输入正确的支付密码'
});
return;
}
//网络请求
//网络请求
/*
extractType 填 'bank'
realName 持卡人姓名
bankAddress 支行地址
bankCode 卡号
money 提现金额
*/
var that = this;
this.$dialog.loading.open();
postCashInfo({
extractType: 'bank',
realName: this.selectedBank.name,
bankCode: this.selectedBank.cardNo,
bankAddress: this.selectedBank.bankSub,
money: this.amout,
passwordPay: this.payPwd
}).then(
res => {
that.$dialog.loading.close();
that.$dialog.message(res.msg);
that.$refs.popup.close();
that.$refs.secrity.clear();
setTimeout(function () {
that.$yrouter.replace("/pages/user/promotion/CashAudit/index");
}, 1000);
},
error => {
that.$dialog.loading.close();
that.$dialog.message(error.msg);
that.$refs.popup.close();
that.$refs.secrity.clear();
}
);
},
getDefaultBankCards() {
let that = this;
bankCardList({
limit: 1,
page: 1
})
.then(response => {
// 请求的列表数据
let arr = response.data.records;
//取第一张银行卡做为默认
if (arr != undefined && arr.length > 0) {
that.selectedBank = arr[0];
}
})
.catch(err => {
});
},
confrimBtnClick: function () {
let that = this;
if (!this.selectedBank) {
this.$dialog.error("请选择提现银行卡");
return;
}
if (this.amout.length == 0) {
this.$dialog.error("请输入提现金额");
return;
} else if (
parseFloat(this.amout) > parseFloat(this.commissionCount) ||
parseFloat(this.commissionCount) == 0
) {
this.$dialog.error("可提现金额不足");
return;
} else if (parseFloat(this.amout) < parseFloat(this.minPrice)) {
this.$dialog.error("金额不能小于最低提现金额" + this.minPrice);
return;
}
//先判断用户是否绑定过手机
if (this.userInfo.phone) {
//再判断用户是否设置过支付密码
if (this.userInfo.hasPwdPay) {
//显示支付密码输入框
this.openPwdInput();
} else {
//设置支付密码
this.$yrouter.push({path: "/pkg_user/views/payPassword?isSetMode=true"});
}
} else {
//跳转到绑定手机
this.$yrouter.push({path: "/pkg_user/views/bindPhone"});
}
},
onBackClick: function () {
console.log("back");
this.$yrouter.back();
},
//选择银行卡
bankSelect: function () {
console.log("bankSelect");
this.$yrouter.push({
path: "/pkg_user/views/bankCardList",
query: {
isSelected: true
}
});
},
withdrawalAll: function () {
if (this.commissionCount) {
this.amout = this.commissionCount + "";
}
},
getBank: function () {
let that = this;
getBank().then(
res => {
that.banks = res.data.extractBank;
that.minPrice = res.data.minPrice;
that.commissionCount = this.$force2Decimal(res.data.commissionCount);
that.gdAmount = parseFloat(res.data.gdAmount);
that.gdLimit = parseFloat(res.data.gdLimit);
that.feeRate = parseFloat(res.data.fl);
//可提现金额去除手续费
if (that.commissionCount > 0) {
var sxf = that.calculateSxf(that.commissionCount);
console.log('手续费:' + sxf);
that.commissionCount = this.$force2Decimal(Math.max(0, (that.commissionCount - sxf)));
;
}
},
function (err) {
}
);
}
}
}
</script>
<style lang="less">
.user-withdrawal {
min-height: 100vh;
box-sizing: border-box;
padding: 42rpx 32rpx;
background: #F9F9F9;
color: #333333;
font-size: 24rpx;
line-height: 34rpx;
.icon-card {
width: 36rpx;
height: 36rpx;
margin-right: 8rpx;
}
}
.bank-box {
margin: 10rpx 0 40rpx;
padding: 24rpx;
border-radius: 12rpx;
background: #FFFFFF;
box-sizing: border-box;
}
.amount-box {
padding: 32rpx 24rpx 54rpx;
border-radius: 12rpx;
background: rgba(255, 255, 255, 1);
box-sizing: border-box;
.title {
margin-bottom: 30rpx;
font-size: 28rpx;
line-height: 40rpx;
}
}
.amount-box .item {
margin-bottom: 12rpx;
}
.red {
color: #E91717;
}
.dollar {
font-size: 32rpx;
line-height: 48rpx;
flex-shrink: 0;
}
.withdraw-all-btn {
width: 148rpx;
height: 56rpx;
padding: 0;
border-radius: 4rpx;
background: #28AAF4;
color: #FFFFFF;
font-size: 24rpx;
font-weight: bold;
flex-shrink: 0;
}
.vline {
height: 0;
border: 1rpx solid #E8E9E9;
}
.input {
padding: 0 20rpx;
font-size: 28rpx;
line-height: 40rpx;
flex-grow: 1;
}
.confirm-btn {
width: 686rpx;
height: 80rpx;
margin: 54rpx 0 40rpx;
border-radius: 8rpx;
background: #FD574B;
color: #FFFFFF;
font-size: 28rpx;
font-weight: bold;
line-height: 80rpx;
}
.record-btn {
color: #776A89;
font-size: 28rpx;
line-height: 40rpx;
text-decoration: underline;
}
</style>