chore(分包): 拆分pages_tooll子包

This commit is contained in:
2026-01-04 16:02:31 +08:00
parent db8fb25da8
commit 311efe1ecd
32 changed files with 489 additions and 357 deletions

View File

@@ -0,0 +1,430 @@
<template>
<view class="container" :style="themeColor">
<view class="bank-account-wrap" @click="goAccount()">
<view class="tx-wrap" v-if="bankAccountInfo.withdraw_type">
<text class="tx-to">提现到</text>
<view class="tx-bank" v-if="bankAccountInfo.withdraw_type == 'wechatpay'">微信默认钱包</view>
<view class="tx-bank" v-else>{{ bankAccountInfo.bank_account }}</view>
<view class="tx-img" v-if="bankAccountInfo.withdraw_type == 'alipay'">
<image :src="$util.img('public/uniapp/member/apply_withdrawal/alipay.png')" mode="widthFix"></image>
</view>
<view class="tx-img" v-else-if="bankAccountInfo.withdraw_type == 'bank'">
<image :src="$util.img('public/uniapp/member/apply_withdrawal/bank.png')" mode="widthFix"></image>
</view>
<view class="tx-img" v-else-if="bankAccountInfo.withdraw_type == 'wechatpay'">
<image :src="$util.img('public/uniapp/member/apply_withdrawal/wechatpay.png')" mode="widthFix">
</image>
</view>
</view>
<text class="tx-to" v-else>请添加提现方式</text>
<view class="iconfont icon-right"></view>
</view>
<view class="empty-box"></view>
<view class="withdraw-wrap">
<view class="withdraw-wrap-title">提现金额</view>
<view class="money-wrap">
<text class="unit">{{ $lang('common.currencySymbol') }}</text>
<input type="digit" class="withdraw-money" v-model="withdrawMoney" />
<view class="delete" @click="remove" v-if="withdrawMoney">
<image :src="$util.img('public/uniapp/member/apply_withdrawal/close.png')" mode="widthFix"></image>
</view>
</view>
<view class="bootom">
<view>
<text class="color-tip">可提现余额{{ $lang('common.currencySymbol') }}{{
withdrawInfo.member_info.balance_money | moneyFormat }}</text>
<text class="all-tx color-base-text" @click="allTx">全部提现</text>
</view>
</view>
<view class="desc">
<text>最小提现金额为{{ $lang('common.currencySymbol') }}{{ withdrawInfo.config.min | moneyFormat }}</text>
<text>手续费为{{ withdrawInfo.config.rate + '%' }}</text>
</view>
</view>
<view class="btn color-base-border ns-gradient-otherpages-member-widthdrawal-withdrawal"
:class="{ disabled: withdrawMoney == '' || withdrawMoney == 0 }" @click="withdraw">
提现
</view>
<view class="recoend" @click="toWithdrawal">
<view class="recoend-con">提现记录</view>
</view>
<loading-cover ref="loadingCover"></loading-cover>
</view>
</template>
<script>
export default {
components: {
loadingCover: () => import('@/components/loading-cover/loading-cover.vue'),
},
data() {
return {
withdrawInfo: {
config: {
is_use: 0,
min: 1,
rate: 0
},
member_info: {
balance_money: 0,
balance_withdraw: 0,
balance_withdraw_apply: 0
}
},
bankAccountInfo: {},
withdrawMoney: '',
isSub: false
};
},
onShow() {
if (this.storeToken) {
this.getWithdrawInfo();
this.getBankAccountInfo();
} else {
this.$util.redirectTo('/pages_tool/login/login', {
back: '/pages_tool/member/apply_withdrawal'
});
}
},
methods: {
toWithdrawal() {
this.$util.redirectTo('/pages_tool/member/withdrawal');
},
//全部提现
allTx() {
this.withdrawMoney = this.withdrawInfo.member_info.balance_money;
},
// 删除提现金额
remove() {
this.withdrawMoney = '';
},
/**
* 获取提现信息
*/
getWithdrawInfo() {
this.$api.sendRequest({
url: '/api/memberwithdraw/info',
success: res => {
if (res.code >= 0 && res.data) {
this.withdrawInfo = res.data;
if (this.withdrawInfo.config.is_use == 0) {
this.$util.showToast({
title: '未开启提现'
});
setTimeout(() => {
this.$util.redirectTo('/pages/member/index');
}, 1500);
}
}
if (this.$refs.loadingCover) this.$refs.loadingCover.hide();
},
fail: res => {
if (this.$refs.loadingCover) this.$refs.loadingCover.hide();
}
});
},
/**
* 银行账号信息
*/
getBankAccountInfo() {
this.$api.sendRequest({
url: '/api/memberbankaccount/defaultinfo',
success: res => {
if (res.code >= 0 && res.data) {
this.bankAccountInfo = res.data;
}
}
});
},
verify() {
if (this.withdrawMoney == '' || this.withdrawMoney == 0 || isNaN(parseFloat(this.withdrawMoney))) {
this.$util.showToast({
title: '请输入提现金额'
});
return false;
}
if (parseFloat(this.withdrawMoney) > parseFloat(this.withdrawInfo.member_info.balance_money)) {
this.$util.showToast({
title: '提现金额超出可提现金额'
});
return false;
}
if (parseFloat(this.withdrawMoney) < parseFloat(this.withdrawInfo.config.min)) {
this.$util.showToast({
title: '提现金额小于最低提现金额'
});
return false;
}
return true;
},
withdraw() {
if (!this.bankAccountInfo.withdraw_type) {
this.$util.showToast({
title: '请先添加提现方式'
});
return;
}
if (this.verify()) {
if (this.isSub) return;
this.isSub = true;
var applet_type = 0;
if (this.bankAccountInfo.withdraw_type == 'wechatpay') {
// #ifdef MP
applet_type = 1;
// #endif
}
// #ifdef MP
this.subscribeMessage(() => {
this.$api.sendRequest({
url: '/api/memberwithdraw/apply',
data: {
apply_money: this.withdrawMoney,
transfer_type: this.bankAccountInfo.withdraw_type, //转账提现类型
realname: this.bankAccountInfo.realname,
mobile: this.bankAccountInfo.mobile,
bank_name: this.bankAccountInfo.branch_bank_name,
account_number: this.bankAccountInfo.bank_account,
applet_type: applet_type
},
success: res => {
if (res.code >= 0) {
this.$util.showToast({
title: '提现申请成功'
});
setTimeout(() => {
this.$util.redirectTo(
'/pages_tool/member/withdrawal', {},
'redirectTo');
}, 1500);
} else {
this.isSub = false;
this.$util.showToast({
title: res.message
});
}
},
fail: res => {
this.isSub = false;
}
});
});
// #endif
// #ifndef MP-WEIXIN
this.$api.sendRequest({
url: '/api/memberwithdraw/apply',
data: {
apply_money: this.withdrawMoney,
transfer_type: this.bankAccountInfo.withdraw_type, //转账提现类型
realname: this.bankAccountInfo.realname,
mobile: this.bankAccountInfo.mobile,
bank_name: this.bankAccountInfo.branch_bank_name,
account_number: this.bankAccountInfo.bank_account,
applet_type: applet_type
},
success: res => {
if (res.code >= 0) {
this.$util.showToast({
title: '提现申请成功'
});
setTimeout(() => {
this.$util.redirectTo('/pages_tool/member/withdrawal', {},
'redirectTo');
}, 1500);
} else {
this.isSub = false;
this.$util.showToast({
title: res.message
});
}
},
fail: res => {
this.isSub = false;
}
});
// #endif
}
},
goAccount() {
this.$util.redirectTo(
'/pages_tool/member/account', {
back: '/pages_tool/member/apply_withdrawal'
},
'redirectTo'
);
},
/**
* 微信订阅消息
*/
subscribeMessage(callback) {
this.$api.sendRequest({
url: '/weapp/api/weapp/messagetmplids',
data: {
keywords: 'USER_WITHDRAWAL_SUCCESS'
},
success: res => {
if (res.code == 0 && res.data.length) {
uni.requestSubscribeMessage({
tmplIds: res.data,
fail: res => {
console.log('fail', res);
},
complete: () => {
callback();
}
});
} else {
callback();
}
},
fail: res => {
callback();
}
});
}
},
};
</script>
<style lang="scss">
.container {
width: 100vw;
height: 100vh;
background: #fff;
}
.empty-box {
height: 20rpx;
}
.bank-account-wrap {
margin: 0 20rpx;
padding: 20rpx 30rpx;
border-bottom: 2rpx solid #f7f7f7;
position: relative;
.tx-wrap {
display: flex;
justify-content: space-between;
margin-right: 60rpx;
.tx-bank {
margin-right: 60rpx;
flex: 1;
margin-left: 10rpx;
text-align: right;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.tx-img {
position: absolute;
right: 100rpx;
top: 50%;
transform: translateY(-50%);
width: 40rpx;
height: 40rpx;
image {
width: 100%;
height: 100%;
}
}
}
.iconfont {
position: absolute;
right: 40rpx;
top: 50%;
transform: translateY(-50%);
}
}
.withdraw-wrap {
margin: 0 20rpx;
padding: 30rpx;
border-radius: 16rpx;
box-shadow: rgba(110, 110, 110, 0.09) 0 0 20rpx 0;
.money-wrap {
padding: 20rpx 0;
border-bottom: 2rpx solid #eee;
display: flex;
align-items: baseline;
.unit {
font-size: 60rpx;
line-height: 1.3;
}
.withdraw-money {
height: 70rpx;
line-height: 70rpx;
min-height: 70rpx;
padding-left: 20rpx;
font-size: 60rpx;
flex: 1;
font-weight: bolder;
}
.delete {
width: 40rpx;
height: 40rpx;
image {
width: 100%;
height: 100%;
}
}
}
.bootom {
display: flex;
padding-top: 20rpx;
text {
line-height: 1;
flex: 2;
}
.all-tx {
padding-left: 10rpx;
}
}
}
.btn {
margin: 0 30rpx;
margin-top: 60rpx;
height: 80rpx;
line-height: 80rpx;
border-radius: $border-radius;
color: #fff;
text-align: center;
background-color: var(--main-color);
&.disabled {
background: #ccc;
border-color: #ccc;
color: #fff;
}
}
.recoend {
margin-top: 40rpx;
.recoend-con {
text-align: center;
}
}
.desc {
font-size: $font-size-tag;
color: #999;
}
</style>

View File

@@ -0,0 +1,194 @@
<template>
<view class="balance" :style="themeColor">
<!-- #ifdef MP-WEIXIN -->
<view class="custom-navbar" :style="{
'padding-top': menuButtonBounding.top + 'px',
'height': menuButtonBounding.height + 'px'
}">
<view class="navbar-wrap">
<text class="iconfont icon-back_light back" @click="$util.redirectTo('/pages/member/index')"></text>
<view class="navbar-title">
账户余额
</view>
</view>
</view>
<!-- #endif -->
<view class="head-wrap"
:style="{ background: 'url(' + $util.img('public/uniapp/balance/balance-bg.png') + ')', backgroundSize: '100% 100%' }">
<!-- <view class="head-wrap" :style="{ background: 'url(' + $util.img('public/uniapp/balance/balance-bg.png') + ') no-repeat right bottom/ auto 380rpx, linear-gradient(314deg, #FE7849 0%, #FF1959 100%)' }"> -->
<view class="title">账户余额</view>
<view class="balance price-font">{{ (parseFloat(balanceInfo.balance) +
parseFloat(balanceInfo.balance_money)).toFixed(2) }}</view>
<!-- <view class="flex-box">
<view class="flex-item">
<view class="num price-font">{{ balanceInfo.balance_money|moneyFormat }}</view>
<view class="font-size-tag">现金余额</view>
</view>
<view class="flex-item">
<view class="num price-font">{{ balanceInfo.balance|moneyFormat }}</view>
<view class="font-size-tag">储值余额</view>
</view>
</view> -->
<view class="btns">
<view class="cash btn" @click="toWithdrawal">提现</view>
<view class="recharge btn" @click="toList">充值</view>
</view>
</view>
<view class="menu-wrap">
<view class="menu-item" @click="toApply" style="border-bottom: 0.5px solid #f2f2f2;">
<view class="icon">
<text class="iconfont icon-yuemingxi"></text>
</view>
<text class="title">提现记录</text>
<text class="iconfont icon-right"></text>
</view>
<view class="menu-item" @click="toBalanceDetail" style="border-bottom: 0.5px solid #f2f2f2;">
<view class="icon">
<text class="iconfont icon-yuemingxi"></text>
</view>
<text class="title">余额明细</text>
<text class="iconfont icon-right"></text>
</view>
<!-- <view class="menu-item" @click="toOrderList">
<view class="icon">
<text class="iconfont icon-chongzhijilu"></text>
</view>
<text class="title">充值记录</text>
<text class="iconfont icon-right"></text>
</view> -->
</view>
<!-- <view class="action">
<view @click="toList" class="recharge-withdraw" v-if="addonIsExist.memberrecharge && memberrechargeConfig && memberrechargeConfig.is_use">
{{ $lang('recharge') }}
</view>
<view class="withdraw" v-if="addonIsExist.memberwithdraw && withdrawConfig && withdrawConfig.is_use" @click="toWithdrawal">
{{ $lang('withdrawal') }}
</view>
</view> -->
<ns-login ref="login"></ns-login>
<loading-cover ref="loadingCover"></loading-cover>
</view>
</template>
<script>
export default {
components: {
nsLogin: () => import('@/components/ns-login/ns-login.vue'),
loadingCover: () => import('@/components/loading-cover/loading-cover.vue')
},
data() {
return {
balanceInfo: {
balance: 0,
balance_money: 0
},
withdrawConfig: null,
memberrechargeConfig: null,
menuButtonBounding: {} // 小程序胶囊属性
};
},
async onShow() {
this.getWithdrawConfig();
this.getMemberrechargeConfig();
if (!this.storeToken) {
this.$nextTick(() => {
this.$refs.login.open('/pages_tool/member/balance');
});
} else {
this.getUserInfo();
}
},
onLoad() {
// #ifdef MP
this.menuButtonBounding = uni.getMenuButtonBoundingClientRect();
// #endif
},
methods: {
toWithdrawal() {
this.$util.redirectTo('/pages_tool/member/apply_withdrawal');
},
toOrderList() {
this.$util.redirectTo('/pages_tool/recharge/order_list');
},
toBalanceDetail() {
this.$util.redirectTo('/pages_tool/member/balance_detail');
},
toApply() {
this.$util.redirectTo('/pages_tool/member/withdrawal');
},
toList() {
this.$util.redirectTo('/pages_tool/recharge/list');
},
//获取余额信息
getUserInfo() {
this.$api.sendRequest({
url: '/api/memberaccount/info',
data: {
account_type: 'balance,balance_money'
},
success: res => {
if (res.data) {
this.balanceInfo = res.data;
} else {
this.$util.showToast({
title: res.message
});
}
if (this.$refs.loadingCover) this.$refs.loadingCover.hide();
},
fail: res => {
mescroll.endErr();
if (this.$refs.loadingCover) this.$refs.loadingCover.hide();
}
});
},
/**
* 获取余额提现配置
*/
getWithdrawConfig() {
this.$api.sendRequest({
url: '/api/memberwithdraw/config',
success: res => {
if (res.code >= 0 && res.data) {
this.withdrawConfig = res.data;
}
}
});
},
/**
* 获取充值提现配置
*/
getMemberrechargeConfig() {
this.$api.sendRequest({
url: '/memberrecharge/api/memberrecharge/config',
success: res => {
if (res.code >= 0 && res.data) {
this.memberrechargeConfig = res.data;
}
}
});
}
},
onBackPress(options) {
if (options.from === 'navigateBack') {
return false;
}
this.$util.redirectTo('/pages/member/index', {}, 'reLaunch');
return true;
},
watch: {
storeToken: function (nVal, oVal) {
if (nVal) {
this.getUserInfo();
}
}
}
};
</script>
<style lang="scss">
@import '../public/css/balance.scss';
</style>

View File

@@ -0,0 +1,371 @@
<template>
<view :style="themeColor">
<!-- <scroll-view id="tab-bar" class="order-nav" :scroll-x="true" :show-scrollbar="false" :scroll-into-view="scrollInto">
<view v-for="(statusItem, statusIndex) in statusList" :key="statusIndex" class="uni-tab-item" :id="statusItem.id" :data-current="statusIndex" @click="ontabtap">
<text class="uni-tab-item-title" :class="statusIndex == orderStatus ? 'uni-tab-item-title-active' : ''">{{ statusItem.name }}</text>
</view>
</scroll-view> -->
<!-- <view class="tab color-bg">
<view class="tab-left">
<picker mode="date" :value="searchType.date" @change="bindDateChange" fields="month">
<view class="uni-input">
{{ date }}
<text class="iconfont icon-iconangledown"></text>
</view>
</picker>
</view>
<view class="tab-right">
<picker @change="bindPickerChange" :value="balanceIndex" :range="balanceType" class="picker" range-key="label">
<text class="desc uni-input">{{ balanceType[balanceIndex].label }}</text>
<text class="iconfont icon-iconangledown"></text>
</picker>
</view>
</view> -->
<mescroll-uni @getData="getData" ref="mescroll">
<block slot="list">
<!-- 明细列表 -->
<block v-if="dataList.length > 0">
<view class="detailed-wrap">
<view class="balances" v-for="(item, index) in dataList" :key="index">
<image :src="$util.img('public/uniapp/balance/recharge.png')" class="balances-img"
v-if="item.account_data > 0"></image>
<image v-else :src="$util.img('public/uniapp/balance/shopping.png')" mode="widthFix">
</image>
<view class="balances-info" @click="toFromDetail(item)">
<text class="title">{{ item.remark }}</text>
<!-- <text>{{ item.remark }}</text> -->
<text>{{ $util.timeStampTurnTime(item.create_time) }}</text>
</view>
<view class="balances-num">
<text :class="item.account_data > 0 ? 'color-base-text' : ''">{{ item.account_data > 0 ?
'+' + item.account_data : item.account_data }}</text>
</view>
</view>
</view>
</block>
<block v-else><ns-empty :isIndex="false" text="暂无余额明细"></ns-empty></block>
<!-- 无明细列表 -->
</block>
</mescroll-uni>
<ns-login ref="login"></ns-login>
<loading-cover ref="loadingCover"></loading-cover>
</view>
</template>
<script>
export default {
components: {
nsEmpty: () => import('@/components/ns-empty/ns-empty.vue'),
nsLogin: () => import('@/components/ns-login/ns-login.vue'),
loadingCover: () => import('@/components/loading-cover/loading-cover.vue'),
MescrollUni: () => import('@/components/mescroll/my-list-mescroll.vue'),
// #ifdef MP-WEIXIN
privacyPopup: () => import('@/components/wx-privacy-popup/privacy-popup.vue'),
// #endif
},
data() {
const currentDate = this.getDate({
format: true
});
return {
dataList: [],
statusList: [{
name: '全部',
id: '0'
}, {
name: '收入',
id: '1'
}, {
name: '支出',
id: '2'
}],
scrollInto: '',
orderStatus: '0',
date: currentDate,
searchType: {
from_type: 0,
date: ''
},
balanceType: [{
label: '全部',
value: '0'
}], //积分类型
balanceIndex: 0,
related_id: 0
};
},
onLoad(option) {
if (option.group_id) this.related_id = option.group_id ? option.group_id : 0;
if (option.from_type) this.searchType.from_type = option.from_type;
if (option.related_id) this.related_id = option.related_id ? option.related_id : 0;
if (option.status) this.orderStatus = option.status;
this.getbalanceType();
},
onShow() {
if (!this.storeToken) {
this.$nextTick(() => {
this.$refs.login.open('/pages_tool/member/balance');
});
}
},
methods: {
bindDateChange: function (e) {
var temp = e.target.value;
var tempArr = temp.split('-');
this.date = tempArr[0] + '年' + tempArr[1] + '月';
this.searchType.date = e.target.value;
this.$refs.mescroll.refresh();
},
getDate(type) {
const date = new Date();
let year = date.getFullYear();
let month = date.getMonth() + 1;
let day = date.getDate();
if (type === 'start') {
year = year - 60;
} else if (type === 'end') {
year = year + 2;
}
month = month > 9 ? month : '0' + month;
day = day > 9 ? day : '0' + day;
return `${year}${month}`;
},
bindPickerChange(e) {
this.balanceIndex = e.detail.value;
this.searchType.from_type = this.balanceType[this.balanceIndex].value;
this.$refs.mescroll.refresh();
},
//获取分类类型
getbalanceType() {
this.$api.sendRequest({
url: '/api/memberaccount/fromType',
success: res => {
let balanceType = Object.assign(res.balance, res.balance_money),
typeArr = [{
label: '全部',
value: '0'
}];
for (var index in balanceType) {
typeArr.push({
label: balanceType[index].type_name,
value: index
})
}
this.balanceType = typeArr;
}
});
},
ontabtap(e) {
let index = e.currentTarget.dataset.current;
this.orderStatus = this.statusList[index].id;
this.$refs.mescroll.refresh();
},
getData(mescroll) {
this.$api.sendRequest({
url: '/api/memberaccount/page',
data: {
page_size: mescroll.size,
page: mescroll.num,
account_type: 'balance,balance_money',
from_type: this.searchType.from_type,
date: this.searchType.date,
related_id: this.related_id
},
success: res => {
let newArr = [];
let msg = res.message;
if (res.code == 0 && res.data) {
newArr = res.data.list;
} else {
this.$util.showToast({
title: msg
});
}
mescroll.endSuccess(newArr.length);
//设置列表数据
if (mescroll.num == 1) {
this.dataList = []; //如果是第一页需手动制空列表
this.related_id = 0;
}
this.dataList = this.dataList.concat(newArr); //追加新数据
if (this.$refs.loadingCover) this.$refs.loadingCover.hide();
},
fail: res => {
mescroll.endErr();
if (this.$refs.loadingCover) this.$refs.loadingCover.hide();
}
});
},
toFromDetail(item) {
if (item.from_type == 'order' && !isNaN(parseInt(item.type_tag))) {
this.$util.redirectTo('/pages_order/detail', {
order_id: item.type_tag
});
} else if (item.from_type == 'refund' && parseInt(item.type_tag) != 0) {
this.$util.redirectTo('/pages_order/detail', {
order_id: item.type_tag
});
}
}
}
};
</script>
<style lang="scss">
.detailed-wrap {
padding-top: 20rpx;
margin: 24rpx;
}
.tab {
position: fixed;
top: 0;
width: 100%;
z-index: 10;
display: flex;
justify-content: space-between;
height: 80rpx;
background-color: $color-bg;
view {
flex: 1;
text-align: center;
line-height: 80rpx;
text {
margin-left: 10rpx;
font-size: $font-size-base;
}
}
.tab-left {
display: flex;
padding-left: 46rpx;
}
.tab-right {
display: flex;
justify-content: flex-end;
padding-right: 26rpx;
}
}
.order-nav {
width: 100vw;
height: 70rpx;
display: flex;
flex-direction: row;
/* #ifndef APP-PLUS */
white-space: nowrap;
/* #endif */
background: #fff;
border-bottom-left-radius: 24rpx;
border-bottom-right-radius: 24rpx;
padding-bottom: 30rpx;
position: fixed;
left: 0;
z-index: 998;
.uni-tab-item {
width: 33.33%;
text-align: center;
/* #ifndef APP-PLUS */
display: inline-block;
/* #endif */
flex-wrap: nowrap;
}
.uni-tab-item-title {
color: #555;
font-size: $font-size-base;
display: block;
height: 64rpx;
line-height: 64rpx;
border-bottom: 4rpx solid #fff;
padding: 0 10rpx;
flex-wrap: nowrap;
/* #ifndef APP-PLUS */
white-space: nowrap;
/* #endif */
}
.uni-tab-item-title-active {
display: block;
height: 64rpx;
padding: 0 10rpx;
}
::-webkit-scrollbar {
width: 0;
height: 0;
color: transparent;
}
}
.balances {
padding: $margin-both 24rpx;
// margin: 0 $margin-both;
box-sizing: border-box;
display: flex;
align-items: flex-start;
border-bottom: 2rpx solid $color-line;
background: #fff;
margin-bottom: 20rpx;
border-radius: 24rpx;
image {
width: 54rpx;
height: 54rpx;
border-radius: 50%;
padding-top: 10rpx;
}
.balances-info {
flex: 1;
margin-left: 16rpx;
display: flex;
flex-direction: column;
text {
font-size: $font-size-toolbar;
line-height: 1;
&:last-child {}
&:nth-child(2) {
margin-top: $margin-updown;
font-size: $font-size-activity-tag;
color: $color-tip;
}
&:nth-child(3) {
font-size: $font-size-activity-tag;
margin-top: $margin-updown;
color: $color-tip;
}
}
}
.balances-num {
text {
line-height: 1;
font-size: $font-size-toolbar;
font-weight: 500;
color: #09c15f;
font-weight: 700;
}
}
}
.empty {
width: 100%;
height: 500rpx;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
}
</style>

View File

@@ -0,0 +1,232 @@
<template>
<view class="member-level" :style="themeColor">
<view class="level-top">
<image :src="$util.img('public/uniapp/level/card-top-bg.png')"></image>
</view>
<view class="banner-container">
<view class="memberInfo">
<image :src="$util.img(memberInfo.headimg)" v-if="memberInfo.headimg" @error="headimgError"
mode="aspectFill" />
<image :src="$util.getDefaultImage().head" v-else mode="aspectFill" />
<view class="member-desc">
<view class="font-size-toolbar">{{ memberInfo.nickname }}</view>
<view class="font-size-tag expire-time" v-if="memberInfo.level_expire_time > 0">
有效期至{{ $util.timeStampTurnTime(memberInfo.level_expire_time, true) }}</view>
</view>
</view>
<view class="image-container item-center">
<view class="slide-image">
<view class="bg-border"></view>
<image :src="$util.img('public/uniapp/level/card-bg.png')"></image>
<view class="info">
<view class="level-detail">{{ levelInfo.level_name }}</view>
<view class="growr-name">{{ levelInfo.level_name }}可享受消费折扣和</view>
<view class="growr-value">会员大礼包等权益</view>
<view class="growth-rules font-size-tag" @click="openExplainPopup"
v-if="levelInfo.remark != ''">
<text class="iconfont icon-wenhao font-size-tag"></text>
</view>
<button type="default" class="renew-btn"
@click="$util.redirectTo('/pages_tool/member/card_buy')">立即续费</button>
</view>
</view>
</view>
<view class="card-content"
v-if="levelInfo.is_free_shipping || levelInfo.consume_discount < 100 || levelInfo.point_feedback > 0">
<view class="card-content-head">
<view class="line-box">
<view class="line right"></view>
</view>
<view class="card-content-title">会员权益</view>
<view class="line-box">
<view class="line"></view>
</view>
<view class="clear"></view>
</view>
<view class="card-privilege-list">
<view class="card-privilege-item" v-if="levelInfo.is_free_shipping">
<view class="card-privilege-icon"><text class="iconfont icon-tedianquanchangbaoyou"></text>
</view>
<view class="card-privilege-name">全场包邮</view>
<view class="card-privilege-text">享受商品包邮服务</view>
</view>
<view class="card-privilege-item" v-if="levelInfo.consume_discount < 100">
<view class="card-privilege-icon"><text class="iconfont icon-zhekou"></text></view>
<view class="card-privilege-name">消费折扣</view>
<view class="card-privilege-text">部分商品下单可享{{ levelInfo.consume_discount / 10 }}折优惠</view>
</view>
<view class="card-privilege-item" v-if="levelInfo.point_feedback > 0">
<view class="card-privilege-icon"><text class="iconfont icon-jifen2 f32"></text></view>
<view class="card-privilege-name">积分回馈</view>
<view class="card-privilege-text">下单享{{ parseFloat(levelInfo.point_feedback) }}倍积分回馈</view>
</view>
</view>
<view v-if="levelInfo.send_coupon != '' || levelInfo.send_point > 0 || levelInfo.send_balance > 0">
<view class="card-content-head">
<view class="line-box">
<view class="line right"></view>
</view>
<view class="card-content-title">开卡礼包</view>
<view class="line-box">
<view class="line"></view>
</view>
<view class="clear"></view>
</view>
<view class="card-privilege-list">
<view class="card-privilege-item" v-if="levelInfo.send_point > 0">
<view class="card-privilege-icon"><text class="iconfont icon-jifen3"></text></view>
<view class="card-privilege-name">积分礼包</view>
<view class="card-privilege-text">赠送{{ levelInfo.send_point }}积分</view>
</view>
<view class="card-privilege-item" v-if="levelInfo.send_balance > 0">
<view class="card-privilege-icon"><text class="iconfont icon-hongbao"></text></view>
<view class="card-privilege-name">红包礼包</view>
<view class="card-privilege-text">赠送{{ parseFloat(levelInfo.send_balance) }}元红包</view>
</view>
<view class="card-privilege-item" v-if="levelInfo.send_coupon != ''">
<view class="card-privilege-icon"><text class="iconfont icon-youhuiquan1"></text></view>
<view class="card-privilege-name">优惠券礼包</view>
<view class="card-privilege-text">赠送{{ levelInfo.send_coupon.split(',').length }}张优惠券</view>
</view>
</view>
</view>
</view>
</view>
<!-- 弹出规则 -->
<view @touchmove.prevent.stop>
<uni-popup ref="explainPopup" type="bottom">
<view class="tips-layer">
<view class="head" @click="closeExplainPopup()">
<view class="title">会员卡说明</view>
<text class="iconfont icon-close"></text>
</view>
<view class="body">
<view class="detail margin-bottom">
<block v-if="levelInfo.remark != ''">
<view class="tip">会员卡说明</view>
<view class="font-size-base">{{ levelInfo.remark }}</view>
</block>
</view>
</view>
</view>
</uni-popup>
</view>
<ns-goods-recommend ref="goodrecommend" route="super_member"></ns-goods-recommend>
<ns-login ref="login"></ns-login>
</view>
</template>
<script>
import scroll from '@/common/js/scroll-view.js';
export default {
components: {
uniPopup: () => import('@/components/uni-popup/uni-popup.vue'),
nsGoodsRecommend: () => import('@/components/ns-goods-recommend/ns-goods-recommend.vue'),
nsLogin: () => import('@/components/ns-login/ns-login.vue')
},
mixins: [scroll],
data() {
return {
isSub: false, // 是否已提交
isIphoneX: false,
levelId: 0,
levelInfo: {
bg_color: '#333'
}
};
},
onLoad() {
//会员卡
if (!this.storeToken) {
this.$nextTick(() => {
this.$refs.login.open('/pages_tool/member/card');
});
return;
}
this.isIphoneX = this.$util.uniappIsIPhoneX();
this.levelId = this.memberInfo.member_level;
let levelInfo = this.memberInfo.member_level_info;
let charge_rule = levelInfo.charge_rule ? JSON.parse(levelInfo.charge_rule) : {};
levelInfo.charge_rule_arr = [];
Object.keys(charge_rule).forEach(key => {
levelInfo.charge_rule_arr.push({
key: key,
value: charge_rule[key]
});
});
this.levelInfo = levelInfo;
},
onShow() { },
methods: {
headimgError() {
this.memberInfo.headimg = this.$util.getDefaultImage().head;
},
/**
* 打开说明弹出层
*/
openExplainPopup() {
this.$refs.explainPopup.open();
},
/**
* 打开说明弹出层
*/
closeExplainPopup() {
this.$refs.explainPopup.close();
}
},
onBackPress(options) {
if (options.from === 'navigateBack') {
return false;
}
this.$util.redirectTo('/pages/member/index');
return true;
}
};
</script>
<style lang="scss">
@import '../public/css/card.scss';
.banner-container .image-container .slide-image {
width: calc(100% - 60rpx);
height: 360rpx;
background-size: 100% 100%;
background-repeat: no-repeat;
}
.banner-container .image-container image {
background-color: #e3b66b;
}
.banner-container .slide-image .renew-btn {
text-align: center;
line-height: 56rpx;
height: 56rpx;
border-radius: $border-radius;
width: 160rpx;
font-size: $font-size-tag;
color: #e3b66b !important;
background: #fff;
position: absolute;
right: 10rpx;
bottom: 40rpx;
border: none;
z-index: 10;
}
</style>
<style lang="scss" scoped>
/deep/ .sku-layer .uni-popup__wrapper.uni-custom .uni-popup__wrapper-box {
max-height: unset !important;
}
</style>

View File

@@ -0,0 +1,66 @@
<template>
<view class="page" :style="themeColor">
<view class="agreement-title">{{ title }}</view>
<view class="agreement-content"><rich-text :nodes="content"></rich-text></view>
</view>
</template>
<script>
import htmlParser from '@/common/js/html-parser.js';
export default {
data() {
return {
title: '',
content: ''
};
},
onLoad() {
this.getAgreement();
},
onShow() { },
methods: {
getAgreement() {
this.$api.sendRequest({
url: '/supermember/api/membercard/agreement',
success: res => {
if (res.data && res.code == 0) {
this.title = res.data.title;
this.content = htmlParser(res.data.content);
uni.setNavigationBarTitle({
title: this.title
});
}
}
});
}
},
onBackPress(options) {
if (options.from === 'navigateBack') {
return false;
}
this.$util.redirectTo('/pages_tool/member/card_buy', {}, 'redirectTo');
return true;
}
};
</script>
<style lang="scss">
.page {
width: 100%;
height: 100%;
padding: 30rpx;
box-sizing: border-box;
background-color: #fff;
}
.agreement-title {
font-size: $font-size-toolbar;
text-align: center;
}
.agreement-content {
margin-top: $margin-updown;
word-break: break-all;
font-size: $font-size-base;
}
</style>

View File

@@ -0,0 +1,435 @@
<template>
<view class="member-level" :style="themeColor">
<block v-if="levelList.length">
<view class="level-top">
<image :src="$util.img('public/uniapp/level/card-top-bg.png')"></image>
</view>
<view class="banner-container">
<view class="memberInfo">
<image :src="$util.img(memberInfo.headimg)" v-if="memberInfo.headimg" @error="headimgError"
mode="aspectFill" />
<image :src="$util.getDefaultImage().head" v-else mode="aspectFill"></image>
<view class="member-desc">
<view class="font-size-toolbar">{{ memberInfo.nickname }}</view>
<view class="font-size-tag expire-time" v-if="memberInfo.level_expire_time > 0">
有效期至{{ $util.timeStampTurnTime(memberInfo.level_expire_time, true) }}
</view>
</view>
</view>
<swiper :style="{ width: '100vw', height: '390rpx' }" class="margin-bottom"
:indicator-dots="swiperConfig.indicatorDots" :indicator-color="swiperConfig.indicatorColor"
:indicator-active-color="swiperConfig.indicatorActiveColor" :autoplay="false"
:interval="swiperConfig.interval" :duration="swiperConfig.duration"
:circular="swiperConfig.circular" :previous-margin="swiperConfig.previousMargin"
:next-margin="swiperConfig.nextMargin" @change="swiperChange" @animationfinish="animationfinish"
:current="curIndex">
<swiper-item :class="levelList.length == 1 ? 'image-container-box' : ''"
v-for="(item, i) in levelList" :key="i">
<view class="image-container" :class="[
curIndex === 0
? i === listLen - 1
? 'item-left'
: i === 1
? 'item-right'
: 'item-center'
: curIndex === listLen - 1
? i === 0
? 'item-right'
: i === listLen - 2
? 'item-left'
: 'item-center'
: i === curIndex - 1
? 'item-left'
: i === curIndex + 1
? 'item-right'
: 'item-center'
]">
<view class="slide-image" style="background-size: 100% 100%;background-repeat:no-repeat"
:style="{
transform: curIndex === i ? 'scale(' + scaleX + ',' + scaleY + ')' : 'scale(1,1)',
transitionDuration: '.3s',
transitionTimingFunction: 'ease'
}">
<view class="bg-border"></view>
<image v-if="levelList[curIndex] && levelList[curIndex]['level_picture']"
:src="$util.img(levelList[curIndex]['level_picture'])" />
<image v-else :style="{ backgroundColor: levelList[curIndex]['bg_color'] }" />
<view class="info">
<view class="level-detail" :style="{ color: levelList[curIndex]['level_text_color'] }">
{{ levelList[curIndex].level_name }}</view>
<view class="growr-name" :style="{ color: levelList[curIndex]['level_text_color'] }">{{
levelList[curIndex].level_name }}可享受消费折扣和</view>
<view class="growr-value" :style="{ color: levelList[curIndex]['level_text_color'] }">
会员大礼包等权益</view>
<view class="growth-rules font-size-tag" @click="openExplainPopup"
v-if="levelList[curIndex].remark != ''">
<text class="iconfont icon-wenhao font-size-tag"></text>
</view>
</view>
</view>
</view>
</swiper-item>
</swiper>
<view class="card-content">
<view class="card-content-head">
<view class="line-box">
<view class="line right"></view>
</view>
<view class="card-content-title">卡种选择</view>
<view class="line-box">
<view class="line"></view>
</view>
<view class="clear"></view>
</view>
<view class="card-time-list">
<view class="card-item-box" :class="{ small: currCard.charge_rule_arr.length == 4 }"
v-for="(item, index) in currCard.charge_rule_arr" :key="index">
<view class="card-time-item" :class="{ active: choiceIndex == index }"
@click="choice(index)">
<image :src="$util.img('public/uniapp/level/card-icon.png')" mode="widthFix"></image>
<view class="time-name">{{ cardType[item.key].name }}</view>
<view class="time-price">
{{ $lang('common.currencySymbol') }}
<text class="price">{{ item.value }}</text>
/{{ cardType[item.key].unit }}
</view>
</view>
</view>
</view>
</view>
<view class="card-content"
v-if="currCard.is_free_shipping || currCard.consume_discount < 100 || currCard.point_feedback > 0">
<view class="card-content-head">
<view class="line-box">
<view class="line right"></view>
</view>
<view class="card-content-title">会员权益</view>
<view class="line-box">
<view class="line"></view>
</view>
<view class="clear"></view>
</view>
<view class="card-privilege-list">
<view class="card-privilege-item" v-if="currCard.is_free_shipping">
<view class="card-privilege-icon">
<text class="iconfont icon-tedianquanchangbaoyou"></text>
</view>
<view class="card-privilege-name">全场包邮</view>
<view class="card-privilege-text">享受商品包邮服务</view>
</view>
<view class="card-privilege-item" v-if="currCard.consume_discount < 100">
<view class="card-privilege-icon"><text class="iconfont icon-zhekou"></text></view>
<view class="card-privilege-name">消费折扣</view>
<view class="card-privilege-text">部分商品下单可享{{ currCard.consume_discount / 10 }}折优惠</view>
</view>
<view class="card-privilege-item" v-if="currCard.point_feedback > 0">
<view class="card-privilege-icon"><text class="iconfont icon-jifen2 f32"></text></view>
<view class="card-privilege-name">积分回馈</view>
<view class="card-privilege-text">下单享{{ parseFloat(currCard.point_feedback) }}倍积分回馈</view>
</view>
</view>
<view v-if="currCard.send_coupon != '' || currCard.send_point > 0 || currCard.send_balance > 0">
<view class="card-content-head">
<view class="line-box">
<view class="line right"></view>
</view>
<view class="card-content-title">开卡礼包</view>
<view class="line-box">
<view class="line"></view>
</view>
<view class="clear"></view>
</view>
<view class="card-privilege-list">
<view class="card-privilege-item" v-if="currCard.send_point > 0">
<view class="card-privilege-icon"><text class="iconfont icon-jifen3"></text></view>
<view class="card-privilege-name">积分礼包</view>
<view class="card-privilege-text">赠送{{ currCard.send_point }}积分</view>
</view>
<view class="card-privilege-item" v-if="currCard.send_balance > 0">
<view class="card-privilege-icon"><text class="iconfont icon-hongbao"></text></view>
<view class="card-privilege-name">红包礼包</view>
<view class="card-privilege-text">赠送{{ parseFloat(currCard.send_balance) }}元红包</view>
</view>
<view class="card-privilege-item" v-if="currCard.send_coupon != ''">
<view class="card-privilege-icon"><text class="iconfont icon-youhuiquan1"></text></view>
<view class="card-privilege-name">优惠券礼包</view>
<view class="card-privilege-text">赠送{{ currCard.send_coupon.split(',').length }}张优惠券
</view>
</view>
</view>
</view>
</view>
<block v-if="currCard.charge_rule_arr.length">
<view class="action-wrap" :class="{ 'bottom-safe-area': isIphoneX, 'have-agreement': agreement }">
</view>
<view class="action" :class="{ 'bottom-safe-area': isIphoneX, 'have-agreement': agreement }">
<view class="action-btn" @click="create">
<block v-if="currCard.level_id == levelId"><text class="bold title">立即续费</text></block>
<block v-else>
<text class="bold title" v-if="currCard.charge_type == 1">充值开通</text>
<text class="bold title" v-else>立即开通</text>
</block>
<text class="font-size-tag">{{ $lang('common.currencySymbol') }}</text>
<text class="bold">{{ currCard.charge_rule_arr[choiceIndex].value }}</text>
<text>/{{ cardType[currCard.charge_rule_arr[choiceIndex].key].unit }}</text>
</view>
<view class="agreement" v-if="agreement">
购买既视为同意
<text @click="$util.redirectTo('/pages_tool/member/card_agreement')">{{ agreement.title
}}</text>
</view>
</view>
</block>
</view>
<!-- 弹出规则 -->
<view @touchmove.prevent.stop>
<uni-popup ref="explainPopup" type="bottom">
<view class="tips-layer">
<view class="head" @click="closeExplainPopup()">
<view class="title">会员卡说明</view>
<text class="iconfont icon-close"></text>
</view>
<view class="body">
<view class="detail margin-bottom">
<block v-if="currCard.remark != ''">
<view class="tip">会员卡说明</view>
<view class="font-size-base">{{ currCard.remark }}</view>
</block>
</view>
</view>
</view>
</uni-popup>
</view>
<ns-payment ref="choosePaymentPopup" :payMoney="currCard.charge_rule_arr[choiceIndex].value"
@confirm="toPay" v-if="currCard.charge_rule_arr.length"></ns-payment>
</block>
<block v-else><ns-empty text="暂无可开会员卡" :isIndex="false"></ns-empty></block>
<ns-login ref="login"></ns-login>
<loading-cover ref="loadingCover"></loading-cover>
<!-- 选择支付方式弹窗 -->
</view>
</template>
<script>
import scroll from '@/common/js/scroll-view.js';
export default {
components: {
uniPopup: () => import('@/components/uni-popup/uni-popup.vue'),
nsEmpty: () => import('@/components/ns-empty/ns-empty.vue'),
nsLogin: () => import('@/components/ns-login/ns-login.vue'),
loadingCover: () => import('@/components/loading-cover/loading-cover.vue'),
nsPayment: () => import('@/components/ns-payment/ns-payment.vue')
},
mixins: [scroll],
data() {
return {
isSub: false, // 是否已提交
isIphoneX: false,
couponPopList: [],
curIndex: 0,
isDescAnimating: false,
scaleX: (634 / 540).toFixed(4),
scaleY: (378 / 330).toFixed(4),
swiperConfig: {
indicatorDots: false,
indicatorColor: 'rgba(255, 255, 255, .4)',
indicatorActiveColor: 'rgba(255, 255, 255, 1)',
interval: 3000,
duration: 300,
circular: false,
previousMargin: '58rpx',
nextMargin: '58rpx'
},
levelList: [],
levelId: 0,
cardType: {
week: {
name: '周卡',
unit: '周'
},
month: {
name: '月卡',
unit: '月'
},
quarter: {
name: '季卡',
unit: '季'
},
year: {
name: '年卡',
unit: '年'
}
},
choiceIndex: 0,
outTradeNo: '',
agreement: null
};
},
computed: {
listLen() {
return this.levelList.length;
},
currCard() {
if (this.levelList[this.curIndex]) {
let card = this.levelList[this.curIndex];
let charge_rule = card.charge_rule ? JSON.parse(card.charge_rule) : {};
card.charge_rule_arr = [];
Object.keys(charge_rule).forEach(key => {
card.charge_rule_arr.push({
key: key,
value: charge_rule[key]
});
});
return card;
}
}
},
onLoad() {
//会员卡
this.isIphoneX = this.$util.uniappIsIPhoneX();
if (this.storeToken) {
this.getCardList();
} else {
this.$nextTick(() => {
this.$refs.login.open('/pages_tool/member/card_buy');
});
}
this.getAgreement();
},
onShow() { },
watch: {
storeToken: function (nVal, oVal) {
if (nVal) {
this.getCardList();
}
}
},
methods: {
swiperChange(e) {
this.curIndex = e.detail.current;
this.choiceIndex = 0;
this.isDescAnimating = true;
},
animationfinish(e) {
this.isDescAnimating = false;
},
getCardList() {
this.$api.sendRequest({
url: '/supermember/api/membercard/lists',
success: res => {
if (res.code == 0 && res.data) {
this.levelList = res.data;
this.levelId = this.memberInfo.member_level;
for (let i = 0; i < this.levelList.length; i++) {
if (this.levelList[i].level_id == this.levelId) {
this.curIndex = i;
break;
}
}
} else {
this.$util.showToast({
title: res.message
});
}
if (this.$refs.loadingCover) this.$refs.loadingCover.hide();
}
});
},
choice(index) {
this.choiceIndex = index;
},
/**
* 创建
*/
create() {
if (this.memberInfo.member_level_type && this.memberInfo.member_level != this.currCard.level_id) {
uni.showModal({
title: '提示',
content: '您有尚未过期的会员卡,再次购卡会覆盖掉之前的卡,是否继续?',
success: res => {
if (res.confirm) {
this.$refs.choosePaymentPopup.open();
}
}
});
} else {
this.$refs.choosePaymentPopup.open();
}
},
/**
* 提交
*/
toPay() {
if (this.isSub) return;
this.isSub = true;
this.$api.sendRequest({
url: '/supermember/api/ordercreate/create',
data: {
level_id: this.currCard.level_id,
period_unit: this.currCard.charge_rule_arr[this.choiceIndex].key
},
success: res => {
if (res.data && res.code == 0) {
this.outTradeNo = res.data.out_trade_no;
uni.setStorageSync('paySource', 'membercard');
this.$refs.choosePaymentPopup.getPayInfo(this.outTradeNo);
} else {
this.isSub = false;
this.$util.showToast({
title: res.message
});
}
}
});
},
headimgError() {
this.memberInfo.headimg = this.$util.getDefaultImage().head;
},
/**
* 打开说明弹出层
*/
openExplainPopup() {
this.$refs.explainPopup.open();
},
/**
* 打开说明弹出层
*/
closeExplainPopup() {
this.$refs.explainPopup.close();
},
getAgreement() {
this.$api.sendRequest({
url: '/supermember/api/membercard/agreement',
success: res => {
if (res.code == 0 && res.data && res.data.title != '' && res.data.content != '') {
this.agreement = res.data;
}
}
});
}
},
onBackPress(options) {
if (options.from === 'navigateBack') {
return false;
}
this.$util.redirectTo('/pages/member/index');
return true;
}
};
</script>
<style lang="scss">
@import '../public/css/card.scss';
</style>

View File

@@ -0,0 +1,280 @@
<template>
<view :style="themeColor" class="container">
<view class="tips" v-if="step != 0">请输入6位支付密码建议不要使用重复或连续数字</view>
<view class="tips" v-else>验证码已发送至{{ memberInfo.mobile | mobile }}请在下方输入4位数字验证码</view>
<view class="password-wrap">
<myp-one :maxlength="step == 0 ? 4 : 6" :is-pwd="step != 0" @input="input" ref="input"
:auto-focus="true"></myp-one>
<view v-show="step == 0" class="dynacode"
:class="dynacodeData.seconds == 120 ? 'color-base-text' : 'color-tip'" @click="sendMobileCode">
{{ dynacodeData.codeText }}
</view>
<view class="action-tips" v-show="step == 0">输入短信验证码</view>
<view class="action-tips" v-show="step == 1">请设置支付密码</view>
<view class="action-tips" v-show="step == 2">请再次输入</view>
<view class="btn color-base-bg color-base-border" :class="{ disabled: !isClick }" @click="confirm">确认</view>
</view>
</view>
</template>
<script>
export default {
components: {
mypOne: () => import('@/pages_tool/components/myp-one/myp-one.vue'),
},
data() {
return {
isClick: false,
step: 1,
key: '', // 短信key
code: '', // 动态码
password: '', // 密码
repassword: '', // 重复密码
isSub: false, // 防重复提交
back: '', // 返回页
dynacodeData: {
seconds: 120,
timer: null,
codeText: '获取验证码',
isSend: false
}
};
},
onLoad(option) {
if (option.back) this.back = option.back;
// 判断登录
if (!this.storeToken) {
this.$util.redirectTo('/pages_tool/login/login');
} else {
if (this.memberInfo.mobile == '') {
uni.showModal({
title: '提示',
content: '设置支付密码需要先绑定手机号,是否立即绑定?',
success: res => {
if (res.confirm) {
this.$util.redirectTo('/pages_tool/member/info', {
action: 'mobile',
back: this.back
}, 'redirectTo');
} else {
if (this.back) this.$util.redirectTo(this.back);
else this.$util.redirectTo('/pages/member/index');
}
}
});
} else {
this.step = 0;
this.sendMobileCode();
}
}
},
methods: {
input(val) {
if (this.step == 0) {
if (val.length == 4) {
this.isClick = true;
this.code = val;
} else {
this.isClick = false;
}
} else if (this.step == 1) {
if (val.length == 6) {
this.isClick = true;
this.password = val;
} else {
this.isClick = false;
}
} else {
if (val.length == 6) {
this.isClick = true;
this.repassword = val;
} else {
this.isClick = false;
}
}
},
confirm() {
if (this.isClick) {
if (this.step == 0) {
this.$api.sendRequest({
url: '/api/member/verifypaypwdcode',
data: {
code: this.code,
key: this.key
},
success: res => {
if (res.code == 0) {
this.$refs.input.clear();
this.isClick = false;
this.step = 1;
} else {
this.$util.showToast({
title: res.message
});
}
}
});
} else if (this.step == 1) {
this.$refs.input.clear();
this.isClick = false;
this.step = 2;
} else {
if (this.password == this.repassword) {
if (this.isSub) return;
this.isSub = true;
this.$api.sendRequest({
url: '/api/member/modifypaypassword',
data: {
key: this.key,
code: this.code,
password: this.password
},
success: res => {
if (res.code >= 0) {
this.$util.showToast({
title: '修改成功'
});
setTimeout(() => {
if (this.back) this.$util.redirectTo(this.back, {},
'redirectTo');
else this.$util.redirectTo('/pages/member/index');
}, 2000);
} else {
this.initInfo();
this.$util.showToast({
title: res.message
});
}
}
});
} else {
this.$util.showToast({
title: '两次输入的密码不一致',
success: res => {
this.initInfo();
}
});
}
}
}
},
initInfo() {
this.isClick = false;
this.step = 1;
this.password = '';
this.repassword = '';
this.oldpassword = '';
this.isSub = false;
this.$refs.input.clear();
},
/**
* 发送手机动态码
*/
sendMobileCode() {
if (this.dynacodeData.seconds != 120) return;
if (this.dynacodeData.isSend) return;
this.dynacodeData.isSend = true;
this.$api.sendRequest({
url: '/api/member/paypwdcode',
success: res => {
this.dynacodeData.isSend = false;
if (res.code >= 0) {
this.key = res.data.key;
if (this.dynacodeData.seconds == 120 && this.dynacodeData.timer == null) {
this.dynacodeData.timer = setInterval(() => {
this.dynacodeData.seconds--;
this.dynacodeData.codeText = this.dynacodeData.seconds + 's后可重新获取';
}, 1000);
}
} else {
this.$util.showToast({
title: res.message
});
}
},
fail: () => {
this.$util.showToast({
title: 'request:fail'
});
this.dynacodeData.isSend = false;
}
});
}
},
filters: {
mobile(mobile) {
return mobile.substring(0, 4 - 1) + '****' + mobile.substring(6 + 1);
}
},
watch: {
'dynacodeData.seconds': {
handler(newValue, oldValue) {
if (newValue == 0) {
clearInterval(this.dynacodeData.timer);
this.dynacodeData = {
seconds: 120,
timer: null,
codeText: '获取动态码',
isSend: false
};
}
},
immediate: true,
deep: true
}
}
};
</script>
<style lang="scss">
.container {
width: 100vw;
height: 100vh;
background: #fff;
.tips {
width: 60%;
margin: 0 auto;
text-align: center;
padding-top: 100rpx;
}
.password-wrap {
width: 80%;
margin: 0 auto;
margin-top: 40rpx;
.action-tips {
text-align: center;
font-weight: 600;
margin-top: 80rpx;
}
.dynacode {
line-height: 1;
margin-top: 20rpx;
font-size: $font-size-tag;
}
.btn {
margin: 0 auto;
margin-top: 30rpx;
height: 80rpx;
line-height: 80rpx;
border-radius: $border-radius;
color: #fff;
text-align: center;
&.disabled {
background: #ccc !important;
border-color: #ccc !important;
color: #fff;
}
}
}
}
</style>

View File

@@ -0,0 +1,165 @@
<template>
<view :style="themeColor" class="point">
<!-- #ifdef MP-WEIXIN -->
<view class="custom-navbar" :style="{
'padding-top': menuButtonBounding.top + 'px',
'height': menuButtonBounding.height + 'px'
}">
<view class="navbar-wrap">
<text class="iconfont icon-back_light back" @click="$util.redirectTo('/pages/member/index')"></text>
<view class="navbar-title">
我的积分
</view>
</view>
</view>
<!-- #endif -->
<view class="head-wrap"
:style="{ background: 'url(' + $util.img('public/uniapp/point/point_bg.png') + ') no-repeat right bottom/ auto 340rpx, linear-gradient(314deg, #F16914 0%, #FEAA4C 100%)' }">
<view class="point price-font">{{ pointInfo.point }}</view>
<view class="title">当前积分</view>
<view class="flex-box">
<view class="flex-item">
<view class="num price-font">{{ pointInfo.totalPoint }}</view>
<view class="font-size-tag">累计积分</view>
</view>
<view class="flex-item">
<view class="num price-font">{{ pointInfo.totalConsumePoint }}</view>
<view class="font-size-tag">累计消费</view>
</view>
<view class="flex-item">
<view class="num price-font">{{ pointInfo.todayPoint }}</view>
<view class="font-size-tag">今日获得</view>
</view>
</view>
</view>
<view class="menu-wrap">
<view class="menu-item" @click="$util.redirectTo('/pages_tool/member/point_detail')">
<view class="icon">
<image :src="$util.img('public/uniapp/point/point_detail_icon.png')" mode="widthFix"></image>
</view>
<text class="title">积分明细</text>
</view>
<view class="menu-item" @click="$util.redirectTo('/pages_promotion/point/list')">
<view class="icon">
<image :src="$util.img('public/uniapp/point/point_shop.png')" mode="widthFix"></image>
</view>
<text class="title">积分商城</text>
</view>
</view>
<!--
<view class="task-wrap">
<view class="title">做任务赚积分</view>
<view class="task-item" @click="toSign">
<view class="icon"><text class="iconfont icon-qiandao1"></text></view>
<view class="wrap">
<view class="title">每日签到</view>
<view class="desc color-tip font-size-tag">连续签到可获得更多积分</view>
</view>
<view class="btn">去签到</view>
</view>
<view class="task-item" @click="$util.redirectTo('/pages/index/index')">
<view class="icon"><text class="iconfont icon-shangpin"></text></view>
<view class="wrap">
<view class="title">购买商品</view>
<view class="desc color-tip font-size-tag">购买商品可获得积分</view>
</view>
<view class="btn">去下单</view>
</view>
</view> -->
<ns-login ref="login"></ns-login>
<loading-cover ref="loadingCover"></loading-cover>
</view>
</template>
<script>
export default {
components: {
nsLogin: () => import('@/components/ns-login/ns-login.vue'),
loadingCover: () => import('@/components/loading-cover/loading-cover.vue'),
},
data() {
return {
pointInfo: {
point: 0,
totalPoint: 0,
totalConsumePoint: 0,
todayPoint: 0
},
menuButtonBounding: {} // 小程序胶囊属性
};
},
onShow() {
if (!this.storeToken) {
this.$nextTick(() => {
this.$refs.login.open('/pages_tool/member/point');
});
} else {
this.getMemberPoint();
}
},
onLoad() {
// #ifdef MP
this.menuButtonBounding = uni.getMenuButtonBoundingClientRect();
// #endif
},
methods: {
toSign() {
this.$util.redirectTo('/pages_tool/member/signin');
},
getMemberPoint() {
this.$api.sendRequest({
url: '/api/memberaccount/point',
data: {
},
success: res => {
if (res.code == 0) {
this.pointInfo.point = parseInt(res.data.point);
this.pointInfo.totalPoint = parseInt(res.data.point_all);
this.pointInfo.totalConsumePoint = parseInt(res.data.point_use);
this.pointInfo.todayPoint = parseInt(res.data.point_today);
}
if (this.$refs.loadingCover) this.$refs.loadingCover.hide();
},
fail: res => {
if (this.$refs.loadingCover) this.$refs.loadingCover.hide();
}
});
},
/**
* 获取充值提现配置
*/
getMemberrechargeConfig() {
this.$api.sendRequest({
url: '/memberrecharge/api/memberrecharge/config',
success: res => {
if (res.code >= 0 && res.data) {
this.memberrechargeConfig = res.data;
}
}
});
}
},
onBackPress(options) {
if (options.from === 'navigateBack') {
return false;
}
this.$util.redirectTo('/pages/member/index', {}, 'reLaunch');
return true;
},
watch: {
storeToken: function (nVal, oVal) {
if (nVal) {
this.getMemberPoint();
}
}
}
};
</script>
<style lang="scss">
@import '../public/css/point.scss';
</style>

View File

@@ -0,0 +1,355 @@
<template>
<view :style="themeColor">
<!-- <view class="tab color-bg">
<view class="tab-left">
<picker mode="date" :value="searchType.date" @change="bindDateChange" fields="month">
<view class="uni-input">
{{ date }}
<text class="iconfont icon-iconangledown"></text>
</view>
</picker>
</view>
<view class="tab-right">
<picker @change="bindPickerChange" :value="pointIndex" :range="pointType" class="picker" range-key="label">
<text class="desc uni-input">{{ pointType[pointIndex].label }}</text>
<text class="iconfont icon-iconangledown"></text>
</picker>
</view>
</view> -->
<mescroll-uni @getData="getData" class="member-point" ref="mescroll">
<view slot="list">
<block v-if="dataList.length">
<view class="detailed-wrap">
<view class="cont">
<view class="detailed-item" v-for="(item, index) in dataList" :key="index">
<view class="info" @click="toFromDetail(item)">
<view class="event">{{ item.type_name }}</view>
<view class="time-box">
<text class="time color-tip">{{ $util.timeStampTurnTime(item.create_time)
}}</text>
</view>
</view>
<view class="num color-base-text" v-if="item.account_data > 0">+{{
parseInt(item.account_data) }}</view>
<view class="num " v-else>{{ parseInt(item.account_data) }}</view>
</view>
</view>
</view>
</block>
<block v-else>
<view class="cart-empty"><ns-empty></ns-empty></view>
</block>
</view>
</mescroll-uni>
<loading-cover ref="loadingCover"></loading-cover>
</view>
</template>
<script>
export default {
components: {
nsEmpty: () => import('@/components/ns-empty/ns-empty.vue'),
nsLogin: () => import('@/components/ns-login/ns-login.vue'),
loadingCover: () => import('@/components/loading-cover/loading-cover.vue'),
MescrollUni: () => import('@/components/mescroll/my-list-mescroll.vue'),
// #ifdef MP-WEIXIN
privacyPopup: () => import('@/components/wx-privacy-popup/privacy-popup.vue'),
// #endif
},
data() {
const currentDate = this.getDate({
format: true
});
return {
memberAccount: {
point: 0
},
dataList: [],
date: currentDate,
searchType: {
from_type: 0,
date: ''
},
pointType: [
{
label: '全部',
value: '0'
}
], //积分类型
pointIndex: 0,
related_id: 0
};
},
onShow() {
if (!this.storeToken) {
this.$util.redirectTo(
'/pages_tool/login/login',
{
back: '/pages_tool/member/point'
},
'redirectTo'
);
}
},
onLoad(option) {
if (option.related_id) this.related_id = option.related_id ? option.related_id : 0;
if (option.from_type) this.searchType.from_type = option.from_type;
this.getPointType();
},
methods: {
bindDateChange: function (e) {
var temp = e.target.value;
var tempArr = temp.split('-');
this.date = tempArr[0] + '年' + tempArr[1] + '月';
this.searchType.date = e.target.value;
this.$refs.mescroll.refresh();
},
getDate(type) {
const date = new Date();
let year = date.getFullYear();
let month = date.getMonth() + 1;
let day = date.getDate();
if (type === 'start') {
year = year - 60;
} else if (type === 'end') {
year = year + 2;
}
month = month > 9 ? month : '0' + month;
day = day > 9 ? day : '0' + day;
return `${year}${month}`;
},
bindPickerChange(e) {
this.pointIndex = e.detail.value;
this.searchType.from_type = this.pointType[this.pointIndex].value;
this.$refs.mescroll.refresh();
},
//获取分类类型
getPointType() {
var temp = [],
that = this;
this.$api.sendRequest({
url: '/api/memberaccount/fromType',
success: res => {
for (var index in res.point) {
var obg = {};
obg.label = res.point[index].type_name;
obg.value = index;
that.pointType.push(obg);
}
}
});
},
toList() {
this.$util.redirectTo('/pages_promotion/point/list');
},
toOrderList() {
this.$util.redirectTo('/pages_promotion/point/order_list');
},
toFromDetail(item) {
if (item.from_type == 'pointexchange') {
this.$api.sendRequest({
url: '/pointexchange/api/order/info',
data: {
order_id: item.type_tag
},
success: res => {
if (res.code >= 0) {
var data = res.data;
if (data.type == 1 && data.relate_order_id) {
switch (data.delivery_type) {
case 'store':
this.$util.redirectTo('/pages_order/detail_pickup', {
order_id: data.relate_order_id
});
break;
case 'local':
this.$util.redirectTo('/pages_order/detail_local_delivery', {
order_id: data.relate_order_id
});
break;
default:
this.$util.redirectTo('/pages_order/detail', {
order_id: data.relate_order_id
});
}
} else {
this.$util.redirectTo('/pages_order/detail_point', {
order_id: data.order_id
});
}
}
}
});
} else if (item.from_type == 'pointcash') {
this.$util.redirectTo('/pages_order/detail', {
order_id: item.type_tag
});
} else if (item.from_type == 'memberconsume') {
// this.$util.redirectTo('/pages_order/detail', {
// order_id: item.type_tag
// });
} else if (item.from_type == 'pointexchangerefund' && parseInt(item.type_tag) != 0) {
this.$util.redirectTo('/pages_order/detail_point', {
order_id: item.type_tag
});
} else if (item.from_type == 'refund' && parseInt(item.type_tag) != 0) {
this.$util.redirectTo('/pages_order/detail', {
order_id: item.type_tag
});
}
},
//获得列表数据
getData(mescroll) {
this.$api.sendRequest({
url: '/api/memberaccount/page',
data: {
page_size: mescroll.size,
page: mescroll.num,
account_type: 'point',
from_type: this.searchType.from_type,
date: this.searchType.date,
related_id: this.related_id
},
success: res => {
let newArr = [];
let msg = res.message;
if (res.code == 0 && res.data) {
newArr = res.data.list;
} else {
this.$util.showToast({
title: msg
});
}
mescroll.endSuccess(newArr.length);
//设置列表数据
if (mescroll.num == 1) {
this.dataList = []; //如果是第一页需手动制空列表
this.related_id = 0;
}
this.dataList = this.dataList.concat(newArr); //追加新数据
if (this.$refs.loadingCover) this.$refs.loadingCover.hide();
},
fail: res => {
mescroll.endErr();
if (this.$refs.loadingCover) this.$refs.loadingCover.hide();
}
});
}
}
};
</script>
<style lang="scss">
/deep/ .fixed {
position: relative;
top: 0;
}
.tab {
position: fixed;
top: 0;
width: 100%;
z-index: 10;
display: flex;
justify-content: space-between;
height: 80rpx;
background-color: $color-bg;
view {
flex: 1;
text-align: center;
line-height: 80rpx;
text {
margin-left: 10rpx;
font-size: $font-size-base;
}
}
.tab-left {
display: flex;
padding-left: 30rpx;
}
.tab-right {
display: flex;
justify-content: flex-end;
padding-right: 40rpx;
}
}
.cart-empty {
margin-top: 208rpx !important;
}
.detailed-wrap {
background: #fff;
position: relative;
z-index: 9;
padding-top: 20rpx;
.head {
display: flex;
height: 90rpx;
&>view {
flex: 1;
text-align: left;
padding: 0 $padding;
line-height: 90rpx;
}
}
.cont {
background: #fff;
width: 100%;
margin: 0 auto;
.detailed-item {
padding: 30rpx 0 32rpx;
margin: 0 32rpx;
border-bottom: 2rpx solid $color-line;
position: relative;
box-sizing: border-box;
&:last-of-type {
border-bottom: none;
}
.info {
padding-right: 180rpx;
.event {
font-size: $font-size-base;
line-height: 1.3;
font-weight: 500;
}
.time-box {
line-height: 1;
margin-top: 24rpx;
}
.time {
font-size: $font-size-activity-tag;
color: $color-tip;
}
}
.num {
width: 160rpx;
position: absolute;
right: 17rpx;
top: 50%;
transform: translateY(-50%);
text-align: right;
font-size: $font-size-toolbar;
font-weight: 500;
}
}
}
}
</style>

View File

@@ -0,0 +1,180 @@
<template>
<view :style="themeColor">
<mescroll-uni @getData="getData" class="member-point">
<view slot="list">
<block v-if="dataList.length">
<view class="detailed-wrap">
<view class="cont">
<view class="detailed-item" v-for="(item, index) in dataList" :key="index" @click="toDetail(item.id)">
<view class="info">
<view class="event">{{ item.transfer_type_name }}</view>
<view>
<text class="time">{{ $util.timeStampTurnTime(item.apply_time) }}</text>
</view>
</view>
<view class="right-wrap">
<view class="num color-base-text">{{ item.apply_money }}</view>
<view class="status-name">{{ item.status_name }}</view>
</view>
</view>
</view>
</view>
</block>
<block v-else>
<ns-empty :isIndex="false" text="暂无提现记录"></ns-empty>
</block>
</view>
</mescroll-uni>
<loading-cover ref="loadingCover"></loading-cover>
</view>
</template>
<script>
export default {
components: {
nsEmpty: () => import('@/components/ns-empty/ns-empty.vue'),
nsLogin: () => import('@/components/ns-login/ns-login.vue'),
loadingCover: () => import('@/components/loading-cover/loading-cover.vue'),
MescrollUni: () => import('@/components/mescroll/my-list-mescroll.vue'),
// #ifdef MP-WEIXIN
privacyPopup: () => import('@/components/wx-privacy-popup/privacy-popup.vue')
// #endif
},
data() {
return {
dataList: []
};
},
onShow() {
if (!this.storeToken) {
this.$util.redirectTo(
'/pages_tool/login/login',
{
back: '/pages_tool/member/point'
},
'redirectTo'
);
}
},
methods: {
//获得列表数据
getData(mescroll) {
this.$api.sendRequest({
url: '/api/memberwithdraw/page',
data: {
page_size: mescroll.size,
page: mescroll.num
},
success: res => {
let newArr = [];
let msg = res.message;
if (res.code == 0 && res.data) {
newArr = res.data.list;
} else {
this.$util.showToast({
title: msg
});
}
mescroll.endSuccess(newArr.length);
//设置列表数据
if (mescroll.num == 1) this.dataList = []; //如果是第一页需手动制空列表
this.dataList = this.dataList.concat(newArr); //追加新数据
if (this.$refs.loadingCover) this.$refs.loadingCover.hide();
},
fail: res => {
mescroll.endErr();
if (this.$refs.loadingCover) this.$refs.loadingCover.hide();
}
});
},
toDetail(id) {
this.$util.redirectTo('/pages_tool/member/withdrawal_detail', {
id: id
});
}
}
};
</script>
<style lang="scss">
.account-box {
width: 100vw;
padding: 30rpx;
box-sizing: border-box;
padding-bottom: 10rpx;
display: flex;
justify-content: space-between;
align-items: center;
.tit {
color: #fff;
line-height: 1;
}
.iconmn_jifen_fill {
font-size: 60rpx;
color: #fff;
}
.point {
color: #fff;
font-size: 60rpx;
margin-left: 10rpx;
}
}
.detailed-wrap {
.head {
display: flex;
height: 90rpx;
& > view {
flex: 1;
text-align: left;
padding: 0 $padding;
line-height: 90rpx;
}
}
.cont {
background: #fff;
.detailed-item {
padding: $padding 10rpx;
margin: 0 $margin-both;
border-bottom: 2rpx solid #eee;
position: relative;
&:last-of-type {
border-bottom: none;
}
.info {
padding-right: 180rpx;
.event {
font-size: $font-size-base;
line-height: 1.3;
}
.time {
font-size: $font-size-base;
color: $color-tip;
}
}
.right-wrap {
position: absolute;
right: 0;
top: 0;
text-align: right;
.num {
font-size: $font-size-toolbar;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,134 @@
<template>
<view :style="themeColor">
<view class="money-wrap">
<text>-{{ detail.apply_money }}</text>
</view>
<!-- 状态0待审核1.待转账2已转账 -1拒绝' -->
<view class="item">
<view class="line-wrap">
<text class="label">当前状态</text>
<text class="value">{{ detail.status_name }}</text>
</view>
<view class="line-wrap">
<text class="label">交易号</text>
<text class="value">{{ detail.withdraw_no }}</text>
</view>
<view class="line-wrap">
<text class="label">手续费</text>
<text class="value">¥{{ detail.service_money }}</text>
</view>
<view class="line-wrap">
<text class="label">申请时间</text>
<text class="value">{{ $util.timeStampTurnTime(detail.apply_time) }}</text>
</view>
<view class="line-wrap" v-if="detail.status">
<text class="label">审核时间</text>
<text class="value">{{ $util.timeStampTurnTime(detail.audit_time) }}</text>
</view>
<view class="line-wrap" v-if="detail.bank_name">
<text class="label">银行名称</text>
<text class="value">{{ detail.bank_name }}</text>
</view>
<view class="line-wrap">
<text class="label">收款账号</text>
<text class="value">{{ detail.account_number }}</text>
</view>
<view class="line-wrap" v-if="detail.status == -1 && detail.refuse_reason">
<text class="label">拒绝理由</text>
<text class="value">{{ detail.refuse_reason }}</text>
</view>
<view class="line-wrap" v-if="detail.status == 2">
<text class="label">转账方式名称</text>
<text class="value">{{ detail.transfer_type_name }}</text>
</view>
<view class="line-wrap" v-if="detail.status == 2">
<text class="label">转账时间</text>
<text class="value">{{ $util.timeStampTurnTime(detail.payment_time) }}</text>
</view>
</view>
<loading-cover ref="loadingCover"></loading-cover>
</view>
</template>
<script>
export default {
components: {
loadingCover: () => import('@/components/loading-cover/loading-cover.vue'),
},
data() {
return {
id: 0,
detail: {}
};
},
onLoad(option) {
this.id = option.id || 0;
},
onShow() {
if (this.storeToken) {
this.getDetail();
} else {
this.$util.redirectTo(
'/pages_tool/login/login',
{
back: '/pages_tool/member/point'
},
'redirectTo'
);
}
},
methods: {
getDetail() {
this.$api.sendRequest({
url: '/api/memberwithdraw/detail',
data: {
id: this.id
},
success: res => {
if (res.data) {
this.detail = res.data;
}
if (this.$refs.loadingCover) this.$refs.loadingCover.hide();
},
fail: res => {
if (this.$refs.loadingCover) this.$refs.loadingCover.hide();
}
});
}
}
};
</script>
<style lang="scss">
.money-wrap {
text-align: center;
font-size: 50rpx;
font-weight: bold;
margin: 40rpx;
border-bottom: 2rpx solid $color-line;
padding: 40rpx;
}
.item {
margin: 40rpx;
.line-wrap {
margin-bottom: 20rpx;
.label {
display: inline-block;
width: 200rpx;
color: $color-tip;
font-size: $font-size-base;
}
.value {
display: inline-block;
font-size: $font-size-base;
}
}
}
</style>