用户模块
注册功能实现
1.手机号码唯一验证接口
在开发中,针对客户端提交的数据进行验证或提供模型数据转换格式成字典给客户端。可以使用Marshmallow模块来进行。
为了方便导包,所以我们设置当前language作为导包路径进行使用.
application.__init__.py
代码:
import sys
...
def init_app(config_path):
"""全局初始化"""
# 创建app应用对象
app = Flask(__name__)
# 项目根目录
app.BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# 加载导包路径
sys.path.insert(0, os.path.join(app.BASE_DIR, 'application/utils/language'))
...
避免Pycharm飘红:
选择 language
右键,点击 Make Directory as
→Sources Root
即可设置。
状态文件和服务端提示信息文件,
application.utils.language.message.
代码:
class ErrorMessage():
ok = 'ok'
mobile_format_error = "手机号码格式有误!"
mobile_is_use = "对不起,当前手机已经被注册!"
application.utils.language.status
代码:
class APIStatus():
CODE_OK = 1000 # 接口操作成功
CODE_VALIDATE_ERROR = 1001 # 验证有误!
application.apps.users.marshmallow
,代码:
from marshmallow import Schema, fields, validate, validates, ValidationError
from message import ErrorMessage as Message
from .models import User
class MobileSchema(Schema):
mobile = fields.String(required=True, validate=validate.Regexp('^1[3-9]\d{9}$', error=Message.mobile_format_error))
@validates('mobile')
def validates_mobile(self, data):
user = User.query.filter(User.mobile == data).first()
if user is not None:
raise ValidationError(message=Message.mobile_is_use)
return data
application.apps.users.views
,代码:
from application import jsonrpc, db
from .marshmallow import MobileSchema
from status import APIStatus as status
from message import ErrorMessage as Message
from marshmallow import ValidationError
@jsonrpc.method('User.mobile')
def mobile(mobile):
"""验证手机号码是否已经注册"""
ms = MobileSchema()
try:
ms.load({'mobile': mobile})
ret = {'errno': status.CODE_OK, 'errmsg': Message.ok}
except ValidationError as e:
ret = {'errno': status.CODE_VALIDATE_ERROR, 'errmsg': e.messages['mobile'][0]}
return ret
@jsonrpc.method('User.register')
def register():
"""用户信息注册"""
pass
postman测试接口:
2.客户端进行手机号验证
mfdemo
mfdemo/html/register.html
<!DOCTYPE html>
<html>
<head>
<title>注册</title>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta charset="utf-8">
<link rel="stylesheet" href="../static/css/main.css">
<script src="../static/js/vue.js"></script>
<script src="../static/js/axios.js"></script>
<script src="../static/js/main.js"></script>
</head>
<body>
<div class="app" id="app">
<img class="music" :class="music_play?'music2':''" @click="music_play=!music_play" src="../static/images/player.png">
<div class="bg">
<img src="../static/images/bg0.jpg">
</div>
<div class="form">
<div class="form-title">
<img src="../static/images/register.png">
<img class="back" @click="back" src="../static/images/back.png">
</div>
<div class="form-data">
<div class="form-data-bg">
<img src="../static/images/bg1.png">
</div>
<div class="form-item">
<label class="text">手机</label>
<input type="text" v-model="mobile" @change='check_mobile' placeholder="请输入手机号">
</div>
<div class="form-item">
<label class="text">验证码</label>
<input type="text" class="code" name="code" placeholder="请输入验证码">
<img class="refresh" src="../static/images/refresh.png">
</div>
<div class="form-item">
<label class="text">密码</label>
<input type="password" name="password" placeholder="请输入密码">
</div>
<div class="form-item">
<label class="text">确认密码</label>
<input type="password" name="password2" placeholder="请再次输入密码">
</div>
<div class="form-item">
<input type="checkbox" class="agree" name="agree" checked>
<label><span class="agree_text">同意磨方《用户协议》和《隐私协议》</span></label>
</div>
<div class="form-item">
<img class="commit" @click="game.play_music('../static/mp3/btn1.mp3')" src="../static/images/commit.png"/>
</div>
</div>
</div>
</div>
<script>
apiready = function(){
var game = new Game("../static/mp3/bg1.mp3");
Vue.prototype.game = game;
// 初始化axios
axios.defaults.baseURL = 'http://192.168.20.158:5000/api' // 服务端api接口网关地址
axios.defaults.timeout = 2500; // 请求超时时间
axios.defaults.withCredentials = false; // 跨域请求资源的情况下,忽略cookie的发送
Vue.prototype.axios = axios;
new Vue({
el:"#app",
data(){
return {
mobile: "",
music_play:true,
prev:{name:"",url:"",params:{}},
current:{name:"register",url:"register.html","params":{}},
}
},
watch:{
music_play(){
if(this.music_play){
this.game.play_music("../static/mp3/bg1.mp3");
}else{
this.game.stop_music();
}
}
},
methods:{
check_mobile(){
// 验证手机号码
this.axios.post("", {
'jsonrpc': '2.0',
'id': 1,
'method': 'User.mobile',
'params': {'mobile': this.mobile}
}).then(response=>{
this.game.print(response.data.result);
if(response.data.result.errno != 1000){
api.alert({
title: '错误提示',
msg: 'response.data.result.errmsg',
});
}
}).catch(error=>{
this.game.print(error.response.data.error);
});
},
back(){
// this.game.outWin();
// this.game.outFrame();
this.game.goGroup('user', 0);
}
}
})
}
</script>
</body>
</html>
在客户单请求过程中, 我们需要设置id作为唯一标识, 同时, 将来在客户端项目中多个页面都会继续使用到上面的初始化代码,所以我们一并抽取
这部分代码到另一个static/js/settings.js
文件中.
function init(){
var game = new Game("../static/mp3/bg1.mp3");
Vue.prototype.game = game;
// 初始化axios
axios.defaults.baseURL = 'http://192.168.20.158:5000/api' // 服务端api接口网关地址
axios.defaults.timeout = 2500; // 请求超时时间
axios.defaults.withCredentials = false; // 跨域请求资源的情况下,忽略cookie的发送
Vue.prototype.axios = axios;
Vue.prototype.uuid = UUID.generate;
}
注册页面调用init函数进行初始化.
mfdemo/html/register.html
<!DOCTYPE html>
<html>
<head>
<title>注册</title>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta charset="utf-8">
<link rel="stylesheet" href="../static/css/main.css">
<script src="../static/js/vue.js"></script>
<script src="../static/js/axios.js"></script>
<script src="../static/js/main.js"></script>
</head>
<body>
<div class="app" id="app">
<img class="music" :class="music_play?'music2':''" @click="music_play=!music_play" src="../static/images/player.png">
<div class="bg">
<img src="../static/images/bg0.jpg">
</div>
<div class="form">
<div class="form-title">
<img src="../static/images/register.png">
<img class="back" @click="back" src="../static/images/back.png">
</div>
<div class="form-data">
<div class="form-data-bg">
<img src="../static/images/bg1.png">
</div>
<div class="form-item">
<label class="text">手机</label>
<input type="text" v-model="mobile" @change='check_mobile' placeholder="请输入手机号">
</div>
<div class="form-item">
<label class="text">验证码</label>
<input type="text" class="code" name="code" placeholder="请输入验证码">
<img class="refresh" src="../static/images/refresh.png">
</div>
<div class="form-item">
<label class="text">密码</label>
<input type="password" name="password" placeholder="请输入密码">
</div>
<div class="form-item">
<label class="text">确认密码</label>
<input type="password" name="password2" placeholder="请再次输入密码">
</div>
<div class="form-item">
<input type="checkbox" class="agree" name="agree" checked>
<label><span class="agree_text">同意磨方《用户协议》和《隐私协议》</span></label>
</div>
<div class="form-item">
<img class="commit" @click="game.play_music('../static/mp3/btn1.mp3')" src="../static/images/commit.png"/>
</div>
</div>
</div>
</div>
<script src='../static/js/uuid.js'></script>
<script src='../static/js/settings.js'></script>
<script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
mobile: "",
music_play:true,
prev:{name:"",url:"",params:{}},
current:{name:"register",url:"register.html","params":{}},
}
},
watch:{
music_play(){
if(this.music_play){
this.game.play_music("../static/mp3/bg1.mp3");
}else{
this.game.stop_music();
}
}
},
methods:{
check_mobile(){
// 验证手机号码
this.axios.post("", {
'jsonrpc': '2.0',
'id': this.uuid(),
'method': 'User.mobile',
'params': {'mobile': this.mobile}
}).then(response=>{
this.game.print(response.data.result);
if(response.data.result.errno != 1000){
api.alert({
title: '错误提示',
msg: response.data.result.errmsg,
});
}
}).catch(error=>{
this.game.print(error.response.data.error);
});
},
back(){
// this.game.outWin();
// this.game.outFrame();
this.game.goGroup('user', 0);
}
}
})
}
</script>
</body>
</html>
3.保存用户注册信息接口
创建Marshmallow构造器[暂时不涉及到手机验证码功能]
application.utils.language.message.py
,代码:
class ErrorMessage():
ok = 'ok'
mobile_format_error = "手机号码格式有误!"
mobile_is_use = "对不起,当前手机已经被注册!"
username_is_use = "对不起,当前用户名已经被使用!"
password_not_match = "密码和验证密码不匹配!"
marshmallow.py
from marshmallow import Schema, fields, validate, validates, ValidationError
from message import ErrorMessage as Message
from .models import User, db
class MobileSchema(Schema):
mobile = fields.String(required=True, validate=validate.Regexp('^1[3-9]\d{9}$', error=Message.mobile_format_error))
@validates('mobile')
def validates_mobile(self, data):
user = User.query.filter(User.mobile == data).first()
if user is not None:
raise ValidationError(message=Message.mobile_is_use)
return data
from marshmallow_sqlalchemy import SQLAlchemyAutoSchema, auto_field
from marshmallow import post_load, pre_load, validates_schema
class UserSchema(SQLAlchemyAutoSchema):
mobile = auto_field(required=True, load_only=True)
password = fields.String(required=True, load_only=True)
password2 = fields.String(required=True, load_only=True)
sms_code = fields.String(required=True, load_only=True)
class Meta:
model = User
include_fk = True # 启用外键关系
include_relationships = True # 模型关系外部属性
fields = ['id', 'name', 'mobile', 'password', 'password2', 'sms_code'] # 如果要全换全部字段,就不要声明fields或exclude字段即可
sql_session = db.session
@post_load()
def save_object(self, data, **kwargs):
data.pop('password2')
data.pop('sms_code')
data['name'] = data['mobile']
instance = User(**data)
db.session.add(instance)
db.session.commit()
return instance
@validates_schema
def validate(self, data, **kwargs):
# 校验密码和确认密码
if data['password'] != data['password2']:
raise ValidationError(message=Message.password_not_match, field_name='password')
# todo 校验短信验证码
return data
视图代码:
application.apps.users.views.py
,代码:
from application import jsonrpc, db
from .marshmallow import MobileSchema, UserSchema
from status import APIStatus as status
from message import ErrorMessage as Message
from marshmallow import ValidationError
@jsonrpc.method('User.mobile')
def mobile(mobile):
"""验证手机号码是否已经注册"""
ms = MobileSchema()
try:
ms.load({'mobile': mobile})
ret = {'errno': status.CODE_OK, 'errmsg': Message.ok}
except ValidationError as e:
ret = {'errno': status.CODE_VALIDATE_ERROR, 'errmsg': e.messages['mobile'][0]}
return ret
@jsonrpc.method('User.register')
def register(mobile, password, password2, sms_code):
"""用户信息注册"""
try:
ms = MobileSchema()
ms.load({'mobile': mobile})
us = UserSchema()
user = us.load({
'mobile': mobile,
'password': password,
'password2': password2,
'sms_code': sms_code
})
data = {'errno': status.CODE_OK, 'errmsg': us.dump(user)}
except ValidationError as e:
data = {'errno': status.CODE_VALIDATE_ERROR, 'errmsg': e.messages}
return data
4.客户端发送用户进行注册
mfdemo.html/register.html
,代码:
<!DOCTYPE html>
<html>
<head>
<title>注册</title>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta charset="utf-8">
<link rel="stylesheet" href="../static/css/main.css">
<script src="../static/js/vue.js"></script>
<script src="../static/js/axios.js"></script>
<script src="../static/js/main.js"></script>
</head>
<body>
<div class="app" id="app">
<img class="music" :class="music_play?'music2':''" @click="music_play=!music_play" src="../static/images/player.png">
<div class="bg">
<img src="../static/images/bg0.jpg">
</div>
<div class="form">
<div class="form-title">
<img src="../static/images/register.png">
<img class="back" @click="back" src="../static/images/back.png">
</div>
<div class="form-data">
<div class="form-data-bg">
<img src="../static/images/bg1.png">
</div>
<div class="form-item">
<label class="text">手机</label>
<input type="text" v-model="mobile" @change='check_mobile' placeholder="请输入手机号">
</div>
<div class="form-item">
<label class="text">验证码</label>
<input type="text" class="code" v-model='sms_code' placeholder="请输入验证码">
<img class="refresh" src="../static/images/refresh.png">
</div>
<div class="form-item">
<label class="text">密码</label>
<input type="password" v-model='password' placeholder="请输入密码">
</div>
<div class="form-item">
<label class="text">确认密码</label>
<input type="password" v-model='password2' placeholder="请再次输入密码">
</div>
<div class="form-item">
<input type="checkbox" class="agree" v-model='agree' checked>
<label><span class="agree_text">同意磨方《用户协议》和《隐私协议》</span></label>
</div>
<div class="form-item">
<img class="commit" @click='registerHandle' src="../static/images/commit.png"/>
</div>
</div>
</div>
</div>
<script src='../static/js/uuid.js'></script>
<script src='../static/js/settings.js'></script>
<script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
mobile: "",
password: "",
password2: "",
sms_code: "",
agree: false,
music_play:true,
prev:{name:"",url:"",params:{}},
current:{name:"register",url:"register.html","params":{}},
}
},
watch:{
music_play(){
if(this.music_play){
this.game.play_music("../static/mp3/bg1.mp3");
}else{
this.game.stop_music();
}
}
},
methods:{
registerHandle(){
// 注册处理
this.game.play_music('../static/mp3/btn1.mp3');
// 验证数据[双向验证]
if (!/1[3-9]\d{9}/.test(this.mobile)) {
api.alert({
title: '警告',
msg: '手机号码格式不正确!',
});
return; // 阻止代码继续往下执行
}
if (this.password.length<3 || this.password.length>16){
api.alert({
title: '警告',
msg: '密码长度必须在3-16个字符之间!',
});
return;
}
if (this.password != this.password2) {
api.alert({
title: '警告',
msg: '密码和确认密码不匹配!',
});
return;
}
if (this.sms_code.length<1) {
api.alert({
title: '警告',
msg: '验证码不能为空!',
});
return;
}
if (this.agree === false) {
api.alert({
title: '警告',
msg: '对不起, 必须同意磨方的用户协议和隐私协议才能继续注册!',
});
return;
}
this.axios.post('',{
'jsonrpc': '2.0',
'id': this.uuid(),
'method': 'User.register',
'params': {
'mobile': this.mobile,
'sms_code': this.sms_code,
'password': this.password,
'password2': this.password2,
}
}).then(response=>{
this.game.print(response.data.result);
if (response.data.result.errno != 1000) {
api.alert({
title: '错误提示',
msg: response.data.result.errmsg,
});
}else {
// 注册成功!
api.confirm({
title: '磨方提示',
msg: '注册成功',
buttons: ['返回首页', '个人中心']
}, (ret, err)=>{
if(ret.buttonIndex == 1){
// 跳转到首页
this.game.outGroup('user');
}else{
// 跳转到个人中心
this.game.goGroup('user', 2)
}
});
}
}).catch(error=>{
this.game.print(console.error(.response.data.error);
});
},
check_mobile(){
// 验证手机号码
this.axios.post("", {
'jsonrpc': '2.0',
'id': this.uuid(),
'method': 'User.mobile',
'params': {'mobile': this.mobile}
}).then(response=>{
this.game.print(response.data.result);
if(response.data.result.errno != 1000){
api.alert({
title: '错误提示',
msg: response.data.result.errmsg,
});
}
}).catch(error=>{
this.game.print(error.response.data.error);
});
},
back(){
// this.game.outWin();
// this.game.outFrame();
this.game.goGroup('user', 0);
}
}
})
}
</script>
</body>
</html>
在html/index.html
,frames帧页面组中新增用户中心页面的user.html
,代码:
<!DOCTYPE html>
<html lang="en">
<head>
<title>首页</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta name="format-detection" content="telephone=no,email=no,date=no,address=no">
<link rel="stylesheet" href="../static/css/main.css">
<script src="../static/js/vue.js"></script>
<script src="../static/js/main.js"></script>
</head>
<body>
<div class="app" id="app">
<img class="music" :class="music_play?'music2':''" @click="music_play=!music_play" src="../static/images/player.png">
<div class="bg">
<img src="../static/images/bg0.jpg">
</div>
<ul>
<li><img class="module1" src="../static/images/image1.png"></li>
<li><img class="module2" @click="gohome" src="../static/images/image2.png"></li>
<li><img class="module3" src="../static/images/image3.png"></li>
<li><img class="module4" src="../static/images/image4.png"></li>
</ul>
</div>
<script>
apiready = function(){
var game = new Game("../static/mp3/bg1.mp3");
// 允许ajax发送请求时附带cookie,设置为不允许
Vue.prototype.game = game;
new Vue({
el:"#app",
data(){
return {
music_play:true, // 默认播放背景音乐
prev:{name:"",url:"",params:{}}, // 上一页状态
current:{name:"index",url:"index.html","params":{}}, // 下一页状态
frames: [{
name: 'login',
url: './login.html',
},{
name: 'register',
url: './register.html',
},{
name: 'user',
url: './user.html',
}]
}
},
watch:{
music_play(){
if(this.music_play){
this.game.play_music("../static/mp3/bg1.mp3");
}else{
this.game.stop_music();
}
}
},
created(){
},
methods:{
gohome(){
this.game.openGroup('user', this.frames, frames.length);
}
}
})
}
</script>
</body>
</html>
5.使用云通讯发送短信
官方文档:https://www.yuntongxun.com/member/main
在登录后的平台上面获取一下信息:
ACCOUNT SID:
AUTH TOKEN :
AppID(默认):
Rest URL(短信服务器): app.cloopen.com:8883
在开发过程中,把自己的或者同事的手机加入到测试号码中.
安装sdk
pip install ronglian_sms_sdk
①服务端实现发送短信验证码的api接口
application.settings.dev
,配置文件中填写短信接口相关配置,代码:
# 短信相关配置
SMS_ACCOUNT_ID = "8aaf0708754a3ef2017563ddb22d0773" # 接口主账号
SMS_ACCOUNT_TOKEN = "0b41612bc8a8429d84b5d37f29178743" # 认证token令牌
SMS_APP_ID = "8aaf0708754a3ef2017563ddb3110779" # 应用ID
SMS_TEMPLATE_ID = 1 # 短信模板ID
SMS_EXPIRE_TIME = 60 * 5 # 短信有效时间,单位:秒/s
SMS_INTERVAL_TIME = 60 # 短信发送冷却时间,单位:秒/s
短信属于公共业务,所以把功能接口写在Home蓝图下。
application.utils.language.message.py
,代码:
class ErrorMessage():
ok = 'ok'
mobile_format_error = "手机号码格式有误!"
mobile_is_use = "对不起,当前手机已经被注册!"
username_is_use = "对不起,当前用户名已经被使用!"
password_not_match = "密码和验证密码不匹配!"
sms_send_error = "短信发送失败!"
sms_interval_time = "短信发送冷却中!"
application.utils.language.status.py
,代码:
class APIStatus():
CODE_OK = 1000 # 接口操作成功
CODE_VALIDATE_ERROR = 1001 # 验证有误!
CODE_SMS_ERROR = 1002 # 短信功能执行失败
CODE_INTERVAL_TIME = 1003 # 短信发送冷却中
application.apps.home.views
,代码:
from application import jsonrpc
import re, random, json
from status import APIStatus as status
from message import ErrorMessage as message
from ronglian_sms_sdk import SmsSDK
from flask import current_app
from application import redis
@jsonrpc.method(name='Home.sms')
def sms(mobile):
"""发送短信验证码"""
# 验证手机
if not re.match('^1[3-9]\d{9}$', mobile):
return {'errno': status.CODE_VALIDATE_ERROR, 'errmsg': message.mobile_format_error}
# 短信发送冷却时间
ret = redis.get('int_%s' % mobile)
if ret is not None:
return {'errno': status.CODE_INTERVAL_TIME, 'errmsg': message.sms_interval_time}
# 生成验证码
sms_code = '%06d' % random.randint(0, 999999)
# 发送短信
sdk = SmsSDK(
current_app.config.get('SMS_ACCOUNT_ID'),
current_app.config.get('SMS_ACCOUNT_TOKEN'),
current_app.config.get('SMS_APP_ID')
)
ret = sdk.sendMessage(
current_app.config.get('SMS_TEMPLATE_ID'),
mobile,
(sms_code, current_app.config.get('SMS_EXPIRE_TIME') // 60)
)
result = json.loads(ret)
if result['statusCode'] == '000000':
pipe = redis.pipeline()
pipe.multi() # 开启事务
# 保存短信记录到redis中
pipe.setex('sms_%s' % mobile, current_app.config.get('SMS_EXPIRE_TIME'), sms_code)
# 进行冷却倒计时
pipe.setex('int_%s' % mobile, current_app.config.get('SMS_INTERVAL_TIME'), '_')
pipe.execute() # 提交事务
# 返回结果
return {'errno': status.CODE_OK, 'errmsg': message.ok}
else:
return {'errno': status.CODE_SMS_ERROR, 'errmsg': message.sms_send_error}
postman测试:
②客户端实现点击发送短信
mfdemo/html/register.html
<!DOCTYPE html>
<html>
<head>
<title>注册</title>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta charset="utf-8">
<link rel="stylesheet" href="../static/css/main.css">
<script src="../static/js/vue.js"></script>
<script src="../static/js/axios.js"></script>
<script src="../static/js/main.js"></script>
</head>
<body>
<div class="app" id="app">
<img class="music" :class="music_play?'music2':''" @click="music_play=!music_play" src="../static/images/player.png">
<div class="bg">
<img src="../static/images/bg0.jpg">
</div>
<div class="form">
<div class="form-title">
<img src="../static/images/register.png">
<img class="back" @click="back" src="../static/images/back.png">
</div>
<div class="form-data">
<div class="form-data-bg">
<img src="../static/images/bg1.png">
</div>
<div class="form-item">
<label class="text">手机</label>
<input type="text" v-model="mobile" @change='check_mobile' placeholder="请输入手机号">
</div>
<div class="form-item">
<label class="text">验证码</label>
<input type="text" class="code" v-model='sms_code' placeholder="请输入验证码">
<img class="refresh" @click='send' src="../static/images/refresh.png">
</div>
<div class="form-item">
<label class="text">密码</label>
<input type="password" v-model='password' placeholder="请输入密码">
</div>
<div class="form-item">
<label class="text">确认密码</label>
<input type="password" v-model='password2' placeholder="请再次输入密码">
</div>
<div class="form-item">
<input type="checkbox" class="agree" v-model='agree' checked>
<label><span class="agree_text">同意磨方《用户协议》和《隐私协议》</span></label>
</div>
<div class="form-item">
<img class="commit" @click='registerHandle' src="../static/images/commit.png"/>
</div>
</div>
</div>
</div>
<script src='../static/js/uuid.js'></script>
<script src='../static/js/settings.js'></script>
<script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
is_send: false,
send_interval: 60, // 短信发送冷却时间
mobile: "",
password: "",
password2: "",
sms_code: "",
agree: false,
music_play:true,
prev:{name:"",url:"",params:{}},
current:{name:"register",url:"register.html","params":{}},
}
},
watch:{
music_play(){
if(this.music_play){
this.game.play_music("../static/mp3/bg1.mp3");
}else{
this.game.stop_music();
}
}
},
methods:{
send(){
// 点击发送短信
if (!/1[3-9]\d{9}/,test(this.mobile)) {
api.alert({
title: '警告',
msg: '手机号码格式不正确!',
});
return; // 阻止代码继续往下执行
}
if (this.is_send) {
api.alert({
title: '警告',
msg: `短信发送冷却中,请${this.send_interval}秒之后重新点击发送!`,
});
return;
}
this.axios.post('',{
'jsonrpc': '2.0',
'id': this.uuid(),
'method': 'Home.sms',
'params': {
'mobile': this.mobile,
}
}).then(response=>{
if (response.data.result.errno != 1000) {
api.alert({
title: '错误提示',
msg: response.data.result.errmsg,
});
}else {
this.is_send = true; // 进入冷却状态
this.send_interval = 60;
var timer = setInterval(()=>{
this.send_interval--;
if (this.send_interval<1) {
clearInterval(timer);
this.is_send = false; // 退出冷却状态
}
}, 1000);
}
}).catch(error=>{
this.game.print(error.response.data.error);
});
},
registerHandle(){
// 注册处理
this.game.play_music('../static/mp3/btn1.mp3');
// 验证数据[双向验证]
if (!/1[3-9]\d{9}/.test(this.mobile)) {
api.alert({
title: '警告',
msg: '手机号码格式不正确!',
});
return; // 阻止代码继续往下执行
}
if (this.password.length<3 || this.password.length>16){
api.alert({
title: '警告',
msg: '密码长度必须在3-16个字符之间!',
});
return;
}
if (this.password != this.password2) {
api.alert({
title: '警告',
msg: '密码和确认密码不匹配!',
});
return;
}
if (this.sms_code.length<1) {
api.alert({
title: '警告',
msg: '验证码不能为空!',
});
return;
}
if (this.agree === false) {
api.alert({
title: '警告',
msg: '对不起, 必须同意磨方的用户协议和隐私协议才能继续注册!',
});
return;
}
this.axios.post('',{
'jsonrpc': '2.0',
'id': this.uuid(),
'method': 'User.register',
'params': {
'mobile': this.mobile,
'sms_code': this.sms_code,
'password': this.password,
'password2': this.password2,
}
}).then(response=>{
this.game.print(response.data.result);
if (response.data.result.errno != 1000) {
api.alert({
title: '错误提示',
msg: response.data.result.errmsg,
});
}else {
// 注册成功!
api.confirm({
title: '磨方提示',
msg: '注册成功',
buttons: ['返回首页', '个人中心']
}, (ret, err)=>{
if(ret.buttonIndex == 1){
// 跳转到首页
this.game.outGroup('user');
}else{
// 跳转到个人中心
this.game.goGroup('user', 2)
}
});
}
}).catch(error=>{
this.game.print(error.response.data.error);
});
},
check_mobile(){
// 验证手机号码
this.axios.post("", {
'jsonrpc': '2.0',
'id': this.uuid(),
'method': 'User.mobile',
'params': {'mobile': this.mobile}
}).then(response=>{
this.game.print(response.data.result);
if(response.data.result.errno != 1000){
api.alert({
title: '错误提示',
msg: response.data.result.errmsg,
});
}
}).catch(error=>{
this.game.print(error.response.data.error);
});
},
back(){
// this.game.outWin();
// this.game.outFrame();
this.game.goGroup('user', 0);
}
}
})
}
</script>
</body>
</html>