feat(fsgx): 完成全部24项开发任务 Phase1-7
Phase1 后端核心:
- 新增 fsgx_v1.sql 迁移脚本(is_queue_goods/frozen_points/available_points/no_assess)
- SystemConfigServices 返佣设置扩展(周期人数/分档比例/范围/时机)
- StoreOrderCreateServices 周期循环佣金计算
- StoreOrderTakeServices 佣金发放后同步冻结积分
- StoreProductServices/StoreProduct 保存 is_queue_goods
Phase2 后端接口:
- GET /api/hjf/brokerage/progress 佣金周期进度
- GET /api/hjf/assets/overview 资产总览
- HjfPointsServices 每日 frozen_points 0.4‰ 释放定时任务
- PUT /adminapi/hjf/member/{uid}/no_assess 不考核接口
- GET /adminapi/hjf/points/release_log 积分日志接口
Phase3 前端清理:
- hjfCustom.js 路由精简(仅保留 points/log)
- hjfQueue.js/hjfMember.js API 清理/重定向至 CRMEB 原生接口
- pages.json 公排→推荐佣金/佣金记录/佣金规则
Phase4-5 前端改造:
- queue/status.vue 推荐佣金进度页整体重写
- 商品详情/订单确认/支付结果页文案与逻辑改造
- 个人中心/资产页/引导页/规则页文案改造
- HjfQueueProgress/HjfRefundNotice/HjfAssetCard 组件改造
- 推广中心嵌入佣金进度摘要
- hjfMockData.js 全量更新(公排字段→佣金字段)
Phase6 Admin 增强:
- 用户列表新增 frozen_points/available_points 列及不考核操作按钮
- hjfPoints.js USE_MOCK=false 对接真实积分日志接口
Phase7 配置文档:
- docs/fsgx-phase7-config-checklist.md 后台配置与全链路验收清单
Made-with: Cursor
This commit is contained in:
529
pro_v3.5.1_副本/view/uniapp/pages/users/binding_phone/index.vue
Normal file
529
pro_v3.5.1_副本/view/uniapp/pages/users/binding_phone/index.vue
Normal file
@@ -0,0 +1,529 @@
|
||||
<template>
|
||||
<view class="wrapper" :style="colorStyle">
|
||||
<view class="bag">
|
||||
<img :src="imgHost+'/statics/images/users/login-bg.jpg'" alt="" srcset="">
|
||||
</view>
|
||||
<view class="system-height" :style="{ height: statusBarHeight }"></view>
|
||||
<!-- #ifdef MP -->
|
||||
<view class="title-bar" style="height: 43px;">
|
||||
<view class="icon" @click="back" v-if="!isHome">
|
||||
<image src="../static/left.png"></image>
|
||||
</view>
|
||||
<view class="icon" @click="home" v-else>
|
||||
<image src="../static/home.png"></image>
|
||||
</view>
|
||||
{{pageTitle}}
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<view class="page-msg">
|
||||
<view class="title">
|
||||
{{pageType == 1?'绑定手机号':'手机号登录'}}
|
||||
</view>
|
||||
<view class="tip">
|
||||
{{pageType == 1?'登录注册需绑定手机号':'首次登录会自动注册'}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="page-form">
|
||||
<view class="item">
|
||||
<input type='number' placeholder='填写手机号码' placeholder-class='placeholder' v-model="phone"
|
||||
:maxlength="11"></input>
|
||||
</view>
|
||||
<view class="item acea-row row-between-wrapper">
|
||||
<input type='number' placeholder='填写验证码' placeholder-class='placeholder' :maxlength="6"
|
||||
class="codeIput" v-model="captcha"></input>
|
||||
<view class="line">
|
||||
|
||||
</view>
|
||||
<button class="code font-num" :class="disabled === true ? 'on' : ''" :disabled='disabled' @click="code">
|
||||
{{ text }}
|
||||
</button>
|
||||
</view>
|
||||
<view class="btn" @click="submitData">
|
||||
{{pageType == 1 ? '绑定手机号' : '立即登录'}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="protocol" >
|
||||
<checkbox-group @click.stop='ChangeIsDefault'>
|
||||
<checkbox :class="inAnimation?'trembling':''" @animationend='inAnimation=false'
|
||||
color="#ffffff" backgroundColor="#ffffff"
|
||||
activeBackgroundColor="var(--view-theme)" activeBorderColor="var(--view-theme)"
|
||||
:checked="protocol ? true : false" /> <text @click.stop='ChangeIsDefault'>已阅读并同意</text>
|
||||
<text class="main-color" @click.stop="privacy('user')">《用户协议》</text>
|
||||
与<text class="main-color" @click.stop="privacy('privacy')">《隐私协议》</text>
|
||||
</checkbox-group>
|
||||
</view>
|
||||
<Verify @success="success" :captchaType="captchaType" :imgSize="{ width: '330px', height: '155px' }"
|
||||
ref="verify"></Verify>
|
||||
<!-- #ifdef MP -->
|
||||
<editUserModal :isShow="isShow" @closeEdit="closeEdit" @editSuccess="editSuccess">
|
||||
</editUserModal>
|
||||
<!-- <privacyAgreementPopup v-if="canGetPrivacySetting" @onReject="onReject" @onAgree="onAgree">
|
||||
</privacyAgreementPopup> -->
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const app = getApp();
|
||||
let statusBarHeight = uni.getWindowInfo().statusBarHeight + 'px';
|
||||
import { HTTP_REQUEST_URL, CAPTCHA_TYPE } from '@/config/app';
|
||||
import sendVerifyCode from "@/mixins/SendVerifyCode";
|
||||
import colors from '@/mixins/color.js';
|
||||
import editUserModal from '@/components/eidtUserModal/index.vue'
|
||||
import privacyAgreementPopup from '@/components/privacyAgreementPopup/index.vue'
|
||||
import {
|
||||
bindingUserPhone,
|
||||
verifyCode,
|
||||
registerVerify,
|
||||
updatePhone
|
||||
} from '@/api/api.js';
|
||||
import {
|
||||
getCodeApi,
|
||||
getUserInfo,
|
||||
phoneSilenceAuth
|
||||
} from "@/api/user.js";
|
||||
import {
|
||||
phoneLogin,
|
||||
wechatBindingPhone
|
||||
} from '@/api/public.js'
|
||||
import Routine from '@/libs/routine';
|
||||
import Verify from '../components/verify/verify.vue';
|
||||
import Cache from '@/utils/cache';
|
||||
export default {
|
||||
mixins: [sendVerifyCode, colors],
|
||||
components: {
|
||||
Verify,
|
||||
editUserModal,
|
||||
privacyAgreementPopup
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
captchaType: CAPTCHA_TYPE,
|
||||
imgHost: HTTP_REQUEST_URL,
|
||||
statusBarHeight: statusBarHeight,
|
||||
pageType: 1, // 0 登录 1 绑定手机
|
||||
phone: '',
|
||||
captcha: '',
|
||||
text: '获取验证码',
|
||||
isShow: false,
|
||||
protocol: false,
|
||||
inAnimation: false,
|
||||
authKey: "",
|
||||
backUrl: "",
|
||||
pageTitle: '绑定手机号',
|
||||
configData: Cache.get('BASIC_CONFIG'),
|
||||
canGetPrivacySetting: false,
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
// #ifdef MP
|
||||
if (wx.getPrivacySetting) {
|
||||
this.canGetPrivacySetting = true
|
||||
}
|
||||
// #endif
|
||||
if (options.authKey) {
|
||||
this.authKey = options.authKey
|
||||
}
|
||||
this.backUrl = options.backUrl || ''
|
||||
if (options.pageType) {
|
||||
this.pageType = options.pageType || 1
|
||||
this.pageTitle = options.pageType == 1 ? '绑定手机号' : '手机号登录'
|
||||
}
|
||||
let pages = getCurrentPages();
|
||||
let prePage = pages[pages.length - 2];
|
||||
if (prePage && prePage.route == 'pages/order_addcart/order_addcart') {
|
||||
this.isHome = true;
|
||||
} else {
|
||||
this.isHome = false;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// onAgree() {
|
||||
// this.protocol = true
|
||||
// },
|
||||
submitData() {
|
||||
let that = this;
|
||||
if (this.pageType == 0) {
|
||||
this.isLogin()
|
||||
return
|
||||
}
|
||||
if (!this.rules()) return
|
||||
if (!this.authKey) {
|
||||
let key = this.$Cache.get('snsapiKey');
|
||||
this.phoneAuth(key)
|
||||
} else {
|
||||
this.phoneAuth(this.authKey)
|
||||
}
|
||||
},
|
||||
rules() {
|
||||
let that = this;
|
||||
if (!this.protocol && this.pageType == 0) {
|
||||
this.$util.Tips({
|
||||
title: '请先阅读并同意协议'
|
||||
});
|
||||
return false
|
||||
}
|
||||
if (!that.phone) {
|
||||
this.$util.Tips({
|
||||
title: '请填写手机号码'
|
||||
});
|
||||
return false
|
||||
}
|
||||
if (!(/^1(3|4|5|7|8|9|6)\d{9}$/i.test(that.phone))) {
|
||||
this.$util.Tips({
|
||||
title: '请输入正确的手机号码'
|
||||
});
|
||||
return false
|
||||
}
|
||||
if (!that.captcha) {
|
||||
this.$util.Tips({
|
||||
title: '请填写验证码'
|
||||
});
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
isLogin() {
|
||||
if (!this.rules()) return
|
||||
|
||||
uni.showLoading({
|
||||
title: '正在登录中'
|
||||
});
|
||||
Routine.getCode()
|
||||
.then(code => {
|
||||
phoneLogin({
|
||||
code,
|
||||
spread_spid: app.globalData.spid,
|
||||
spread_code: app.globalData.code,
|
||||
phone: this.phone,
|
||||
captcha: this.captcha,
|
||||
}).then(res => {
|
||||
uni.hideLoading();
|
||||
let time = res.data.expires_time - this.$Cache.time();
|
||||
this.$store.commit('LOGIN', {
|
||||
token: res.data.token,
|
||||
time: time
|
||||
});
|
||||
this.getUserInfo(res.data.store_user_avatar);
|
||||
})
|
||||
.catch(err => {
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: err,
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err)
|
||||
});
|
||||
},
|
||||
phoneAuth(key) {
|
||||
uni.showLoading({
|
||||
title: '正在登录中'
|
||||
});
|
||||
let met
|
||||
// #ifdef MP
|
||||
met = phoneLogin
|
||||
// #endif
|
||||
// #ifndef MP
|
||||
met = wechatBindingPhone
|
||||
// #endif
|
||||
met({
|
||||
phone: this.phone,
|
||||
captcha: this.captcha,
|
||||
key
|
||||
}).then(res => {
|
||||
let time = res.data.expires_time - this.$Cache.time();
|
||||
this.$store.commit('LOGIN', {
|
||||
token: res.data.token,
|
||||
time: time
|
||||
});
|
||||
this.getUserInfo(res.data.store_user_avatar);
|
||||
}).catch(error => {
|
||||
uni.hideLoading()
|
||||
this.$util.Tips({
|
||||
title: error
|
||||
})
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 获取个人用户信息
|
||||
*/
|
||||
getUserInfo(new_user) {
|
||||
let that = this;
|
||||
getUserInfo().then(res => {
|
||||
uni.hideLoading();
|
||||
that.userInfo = res.data;
|
||||
that.$store.commit('SETUID', res.data.uid);
|
||||
that.$store.commit('UPDATE_USERINFO', res.data);
|
||||
if (new_user) {
|
||||
this.isShow = true
|
||||
} else {
|
||||
// #ifdef MP
|
||||
that.$util.Tips({
|
||||
title: '登录成功',
|
||||
icon: 'success'
|
||||
}, {
|
||||
tab: 3,
|
||||
url: this.configData.wechat_auth_switch ? 2 : 1
|
||||
});
|
||||
// #endif
|
||||
// #ifndef MP
|
||||
// that.$util.Tips({
|
||||
// title: '登录成功',
|
||||
// icon: 'success'
|
||||
// }, {
|
||||
// tab: 4,
|
||||
// url: this.backUrl || '/pages/user/index'
|
||||
// });
|
||||
that.wechatPhone();
|
||||
// #endif
|
||||
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
wechatPhone() {
|
||||
this.$Cache.clear('snsapiKey');
|
||||
uni.reLaunch({
|
||||
url: '/pages/user/index'
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
|
||||
success(data) {
|
||||
this.$refs.verify.hide()
|
||||
let that = this;
|
||||
verifyCode().then(res => {
|
||||
let obj ={
|
||||
phone: that.phone,
|
||||
type: 'reset',
|
||||
key: res.data.key,
|
||||
captchaType: CAPTCHA_TYPE,
|
||||
captchaVerification: data.captchaVerification
|
||||
}
|
||||
registerVerify(obj)
|
||||
.then(res => {
|
||||
that.$util.Tips({
|
||||
title: res.msg
|
||||
});
|
||||
that.sendCode();
|
||||
}).catch(err => {
|
||||
this.$refs.verify.refresh()
|
||||
return that.$util.Tips({
|
||||
title: err
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
* 发送验证码
|
||||
*
|
||||
*/
|
||||
async code() {
|
||||
let that = this;
|
||||
if (!that.phone) return that.$util.Tips({
|
||||
title: '请填写手机号码'
|
||||
});
|
||||
if (!(/^1(3|4|5|7|8|9|6)\d{9}$/i.test(that.phone))) return that.$util.Tips({
|
||||
title: '请输入正确的手机号码'
|
||||
});
|
||||
this.$refs.verify.show();
|
||||
return;
|
||||
},
|
||||
ChangeIsDefault() {
|
||||
this.$set(this, 'protocol', !this.protocol);
|
||||
},
|
||||
closeEdit() {
|
||||
this.isShow = false
|
||||
this.$util.Tips({
|
||||
title: '登录成功',
|
||||
icon: 'success'
|
||||
}, {
|
||||
tab: 3,
|
||||
url: 2
|
||||
});
|
||||
},
|
||||
editSuccess() {
|
||||
this.isShow = false
|
||||
},
|
||||
back() {
|
||||
uni.navigateBack({
|
||||
delta: this.configData.wechat_auth_switch ? 2 : 1
|
||||
})
|
||||
},
|
||||
privacy(type) {
|
||||
uni.navigateTo({
|
||||
url: "/pages/users/privacy/index?type=" + type
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/deep/ checkbox .wx-checkbox-input.wx-checkbox-input-checked {
|
||||
border: 1px solid var(--view-theme) !important;
|
||||
background-color: var(--view-theme) !important;
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
font-size: 24rpx;
|
||||
color: #fff !important;
|
||||
}
|
||||
.wrapper {
|
||||
background-color: #fff;
|
||||
min-height: 100vh;
|
||||
position: relative;
|
||||
|
||||
.bag {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 0;
|
||||
/* #ifdef H5 */
|
||||
z-index: 0;
|
||||
|
||||
/* #endif */
|
||||
img {
|
||||
width: 100%;
|
||||
height: 544rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.page-msg {
|
||||
padding-top: 160rpx;
|
||||
margin-left: 72rpx;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
.title {
|
||||
font-size: 48rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
line-height: 68rpx;
|
||||
}
|
||||
|
||||
.tip {
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.page-form {
|
||||
width: 606rpx;
|
||||
margin: 100rpx auto 0 auto;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
.item {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
background: #F5F5F5;
|
||||
border-radius: 45rpx;
|
||||
padding: 24rpx 48rpx;
|
||||
margin-bottom: 32rpx;
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
color: #BBBBBB;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
input.codeIput {
|
||||
width: 300rpx;
|
||||
}
|
||||
|
||||
.line {
|
||||
width: 2rpx;
|
||||
height: 28rpx;
|
||||
background: #CCCCCC;
|
||||
}
|
||||
|
||||
.code {
|
||||
font-size: 28rpx;
|
||||
color: var(--view-theme);
|
||||
background-color: rgba(255, 255, 255, 0);
|
||||
}
|
||||
|
||||
.code.on {
|
||||
color: #BBBBBB !important;
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 606rpx;
|
||||
height: 88rpx;
|
||||
background: var(--view-theme);
|
||||
border-radius: 200rpx 200rpx 200rpx 200rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 32rpx;
|
||||
font-family: PingFang SC-Regular, PingFang SC;
|
||||
font-weight: 400;
|
||||
color: #FFFFFF;
|
||||
line-height: 44rpx;
|
||||
margin-top: 48rpx;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.title-bar {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 34rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
line-height: 48rpx;
|
||||
}
|
||||
|
||||
.icon {
|
||||
position: absolute;
|
||||
left: 30rpx;
|
||||
top: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 86rpx;
|
||||
height: 86rpx;
|
||||
|
||||
image {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.protocol {
|
||||
position: fixed;
|
||||
bottom: 52rpx;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
color: #999999;
|
||||
font-size: 24rpx;
|
||||
line-height: 22rpx;
|
||||
text-align: center;
|
||||
bottom: calc(52rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
|
||||
bottom: calc(52rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
|
||||
|
||||
.main-color {
|
||||
color: var(--view-theme);
|
||||
}
|
||||
|
||||
.trembling {
|
||||
animation: shake 0.6s;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user