种植园
一、我的背包
打开背包,orchard.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>
<script src="../static/js/uuid.js"></script>
<script src="../static/js/settings.js"></script>
<script src="../static/js/socket.io.js"></script>
</head>
<body>
<div class="app orchard" id="app">
<img class="music" :class="music_play?'music2':''" @click="music_play=!music_play" src="../static/images/player.png">
<div class="orchard-bg">
<img src="../static/images/bg2.png">
<img class="board_bg2" src="../static/images/board_bg2.png">
</div>
<img class="back" @click="go_index" src="../static/images/user_back.png" alt="">
<div class="header">
<div class="info" @click='go_home'>
<div class="avatar">
<img class="avatar_bf" src="../static/images/avatar_bf.png" alt="">
<img class="user_avatar" src="../static/images/avatar.png" alt="">
<img class="avatar_border" src="../static/images/avatar_border.png" alt="">
</div>
<p class="user_name">好听的昵称</p>
</div>
<div class="wallet">
<div class="balance" @click='user_recharge'>
<p class="title"><img src="../static/images/money.png" alt="">钱包</p>
<p class="num">{{money}}</p>
</div>
<div class="balance">
<p class="title"><img src="../static/images/integral.png" alt="">果子</p>
<p class="num">99,999.00</p>
</div>
</div>
<div class="menu-list">
<div class="menu">
<img src="../static/images/menu1.png" alt="">
排行榜
</div>
<div class="menu">
<img src="../static/images/menu2.png" alt="">
签到有礼
</div>
<div class="menu" @click='go_orchard_shop'>
<img src="../static/images/menu3.png" alt="">
道具商城
</div>
<div class="menu">
<img src="../static/images/menu4.png" alt="">
邮件中心
</div>
</div>
</div>
<div class="footer">
<ul class="menu-list">
<li class="menu">新手</li>
<li class="menu" @click='go_my_package'>背包</li>
<li class="menu-center" @click='go_orchard_shop'>商店</li>
<li class="menu">消息</li>
<li class="menu" @click='go_friends'>好友</li>
</ul>
</div>
</div>
<script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
music_play:true,
namespace: '/mofang',
token:"",
money:"",
socket: null,
recharge_list: ['10','20','50','100','200','500','1000'],
timeout: 0,
prev:{name:"",url:"",params:{}},
current:{name:"orchard",url:"orchard.html",params:{}},
}
},
created(){
this.game.goFrame('orchard', 'my_orchard.html', this.current, {
x: 0,
y: 180,
w: 'auto',
h: 410,
}, null);
this.checkout();
this.money = this.game.fget("money")
},
methods:{
user_recharge(){
// 发起充值请求
api.actionSheet({
title: '余额充值',
cancelTitle: '取消',
buttons: this.recharge_list
}, (ret, err)=>{
if( ret ){
if(ret.buttonIndex <= this.recharge_list.length){
// 充值金额
money = this.recharge_list[ret.buttonIndex-1];
// 调用支付宝充值
this.create_recharge(money);
}
}else{
}
});
},
create_recharge(money){
// 获取历史信息记录
var token = this.game.get('access_token') || this.game.fget('access_token');
this.game.checkout(this, token, (new_access_token)=>{
this.axios.post('', {
'jsonrpc': '2.0',
'id': this.uuid(),
'method': 'Recharge.create',
'params': {
'money': money,
}
},{
headers:{
Authorization: "jwt " + token,
}
}).then(response=>{
// this.game.print(response.data);
if(parseInt(response.data.result.errno)==1000){
// 前往支付宝
var aliPayPlus = api.require("aliPayPlus");
aliPayPlus.payOrder({
orderInfo: response.data.result.order_string,
sandbox: response.data.result.sandbox, // 将来APP上线需要修改成false
}, (ret, err)=>{
pay_result = {
9000:'支付成功',
8000:"正在处理中",
4000:"订单支付失败",
5000:"重复请求",
6001:"取消支付",
6002:"网络连接出错",
6004:"支付结果未知",
}
api.alert({
title: '支付结果',
msg: pay_result[ret.code],
buttons: ['确定']
});
// 通知服务端, 修改充值结果
this.return_recharge(response.data.result.order_number, token);
});
}else {
this.game.print(response.data);
}
}).catch(error=>{
// 网络等异常
this.game.print(error);
});
})
},
return_recharge(out_trade_number, token){
this.axios.post("", {
'jsonrpc':"2.0",
'id':this.uuid(),
'method':'Recharge.return',
'params': {
'out_trade_number':out_trade_number,
}
},{
headers:{
Authorization: "jwt " + token,
}
}).then(response=>{
if(parseInt(response.data.result.errno)==1000){
this.money = response.data.result.money.toFixed(2);
}
})
},
checkout(){
var token = this.game.get("access_token") || this.game.fget("access_token");
this.game.checkout(this,token,(new_access_token)=>{
this.connect();
});
},
connect(){
// socket连接
this.socket = io.connect(this.settings.socket_server + this.namespace, {transports: ['websocket']});
this.socket.on('connect', ()=>{
this.game.print("开始连接服务端");
});
},
go_index(){
this.game.outWin("orchard");
},
go_friends(){
this.game.goFrame('friends', 'friends.html', this.current);
this.game.goFrame('friend_list', 'friend_list.html', this.current, {
x: 0,
y: 190,
w: 'auto',
h: 'auto',
}, null, true);
},
go_home(){
this.game.goWin('user', 'user.html', this.current);
},
go_orchard_shop(){
// 种植园商店
this.game.goFrame('orchard_shop', 'shop.html', this.current, null, {
type: 'push',
subType: 'from_top',
duration: 300
});
},
go_my_package(){
// 我的背包
this.game.goFrame('package', 'package.html', this.current, null, {
type: 'push',
subType: 'from_top',
duration: 300
});
},
}
});
}
</script>
</body>
</html>
package.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>
<script src="../static/js/uuid.js"></script>
<script src="../static/js/settings.js"></script>
</head>
<body>
<div class="app frame avatar add_friend package" id="app">
<div class="box">
<p class="title">我的背包</p>
<img class="close" @click="close_frame" src="../static/images/close_btn1.png" alt="">
<div class="prop_list">
<div class="item">
<img src="../static/images/fruit_tree.png" alt="">
<span>10</span>
</div>
<div class="item">
<img src="../static/images/prop1.png" alt="">
<span>10</span>
</div>
<div class="item"></div>
<div class="item"></div>
<div class="item lock"></div>
<div class="item lock"></div>
<div class="item lock"></div>
<div class="item lock"></div>
<div class="item lock"></div>
<div class="item lock"></div>
<div class="item lock"></div>
<div class="item lock"></div>
<div class="item lock"></div>
<div class="item lock"></div>
<div class="item lock"></div>
<div class="item lock"></div>
<div class="item lock"></div>
<div class="item lock"></div>
<div class="item lock"></div>
<div class="item lock"></div>
<div class="item lock"></div>
<div class="item lock"></div>
<div class="item lock"></div>
<div class="item lock"></div>
<div class="item lock"></div>
<div class="item lock"></div>
<div class="item lock"></div>
<div class="item lock"></div>
<div class="item lock"></div>
<div class="item lock"></div>
<div class="item lock"></div>
<div class="item lock"></div>
</div>
</div>
</div>
<script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
user_id: "", // 当前登陆用户Id
prev:{name:"",url:"",params:{}},
current:{name:"package",url:"package.html",params:{}},
}
},
created(){
this.user_id = this.game.get("id") || this.game.fget("id");
},
methods:{
close_frame(){
this.game.outFrame("package");
},
}
});
}
</script>
</body>
</html>
main.css
,代码:
.package .prop_list{
position: absolute;
left: 4.2rem;
top: 10rem;
width: 21rem;
height: 39.8rem;
overflow: scroll;
}
.package .prop_list .item{
background: #a63600;
border: 3px solid #ff9900;
width: 4rem;
height: 4rem;
margin: .2rem;
float: left;
border-radius: 5px;
position: relative;
}
.package .prop_list .item img{
position: absolute;
margin: auto;
width: 3rem;
height: 3rem;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.package .prop_list .item span{
font-size: 1.5rem;
color: #fff;
position: absolute;
bottom: 0;
right: 0;
}
.package .prop_list .lock:after{
display: block;
content:"x";
font-size: 4rem;
color: #ff9900;
text-align: center;
line-height: 100%;
height: 4rem;
width: 4rem;
}
种植园的参数信息:
商店的商品:
1. 种子
果树
标题
价格
描述
图片
使用流程相关
状态: 种子期, 成长期, 成熟期, 树桩
种子期: 3 x 60 x 60
成长期: 6 x 60 x 60
成熟期: 12 x 60 x 60
树桩 : -1
2. 宠物
小狗1,小狗2,小狗3,小狗4
标题
价格
描述
图片
使用流程相关:
饱食度: <20%(饥饿) <50%(正常) <100%(饱腹)
生命期: -1(永久)
保护命中率 : 10% 0-1 <10%
3. 狗粮
狗粮1,狗粮2,狗粮3
标题
价格
描述
图片
使用流程相关:
饱食度: 20%
有效期:
4. 道具
化肥,....
标题
价格
描述
图片
使用流程相关:
缩短时间: 1小时
经过了充值以后, 用户就可以有对应的余额进行购买商品, 而对于商品中的果树, 道具等使用用户信息, 我们可以理解为 配置参数, 这些配置参数与以往的dev.py里面填写的项目配置信息不也一样, 这些参数是业务相关的, 在运营过程中随时可能发生变化, 而dev.py中的配置信息, 则在项目上线以后基本不会发生变化.
所以需要在实现商品购买以后, 还需要把参数保存到数据库中.
修改商店中商品购买的货币信息, 模型代码:
orchard/models.py
, 代码:
from application.utils.models import BaseModel, db
class Goods(BaseModel):
"""商品基本信息"""
__tablename__ = 'mf_goods'
remark = db.Column(db.String(255), comment="商品描述")
price = db.Column(db.Numeric(7, 2), comment="商品价格[余额]")
credit = db.Column(db.Integer, comment="商品价格[果子]")
image = db.Column(db.String(255), comment="商品图片")
数据迁移, 终端执行:
python manage.py db migrate -m "add goods column"
python manage.py db upgrade
修复用户在进入种植园页面和返回首页时, socket的回话ID持续刷新的问题.此处我们需要在窗口切换的时候, 不能关闭窗口和刷新页面.因此修改代码如下.
index.html
,修改go_orchard方法的代码:
...
go_orchard(){
if(this.game.get('access_token') || this.game.fget('access_token')){
this.game.goWin('orchard','orchard.html', this.current, reload=false);
}else {
this.game.goWin('user','login.html', this.current);
}
}
...
修改orchard.html
的go_index方法代码:
...
go_index(){
this.game.goWin("root");
},
...
修改main.js
代码:
...
goWin(name,url,pageParam,reload=true){
// 新建窗口
api.openWin({
name: name, // 自定义窗口名称
bounces: false, // 窗口是否上下拉动
reload: reload, // 如果页面已经在之前被打开了,是否要重新加载当前窗口中的页面
useWKWebView:true,
historyGestureEnabled:true,
url: url, // 窗口创建时展示的html页面的本地路径[相对于当前代码所在文件的路径]
animation:{ // 打开新建窗口时的过渡动画效果
type: "push", //动画类型(详见动画类型常量)
subType: "from_right", //动画子类型(详见动画子类型常量)
duration:300 //动画过渡时间,默认300毫秒
},
pageParam: pageParam // 传递给下一个窗口使用的参数.将来可以在新窗口中通过 api.pageParam.name 获取
});
}
...
二、道具购买
在shop.html
中发起购买通知, 获取购买的道具ID和数量,代码:
<!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>
<script src="../static/js/uuid.js"></script>
<script src="../static/js/settings.js"></script>
</head>
<body>
<div class="app frame avatar update_nickname add_friend shop" id="app">
<div class="box">
<p class="title">商店</p>
<img class="close" @click="close_frame" src="../static/images/close_btn1.png" alt="">
<div class="friends_list shop_list">
<div class="item" @click='buy_prop(goods.id)' v-for='goods in goods_list'>
<div class="avatar shop_item">
<img :src="settings.static_url + goods.image" alt="">
</div>
<div class="info">
<p class="username">{{goods.name}}</p>
<p class="time">{{goods.remark}}</p>
</div>
<div class="status">{{goods.price}}</div>
</div>
</div>
</div>
</div>
<script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
user_id: "", // 当前登陆用户Id
goods_list: [], // 商品列表
page: 1,
limit: 10,
is_send_ajax: false,
prev:{name:"",url:"",params:{}},
current:{name:"orchard",url:"shop.html",params:{}},
}
},
created(){
this.user_id = this.game.get("id") || this.game.fget("id");
this.get_goods_list();
},
methods:{
close_frame(){
this.game.outFrame("orchard_shop");
},
get_goods_list(){
if(this.is_send_ajax){
return;
}
// 通过请求获取当前用户的好友列表
var token = this.game.get('access_token') || this.game.fget('access_token');
this.game.checkout(this, token, (new_access_token)=>{
this.is_send_ajax = true;
this.axios.post("", {
'jsonrpc': '2.0',
"id": this.uuid(),
'method': 'Orchard.goods.list',
'params': {
'page': this.page,
'limit': this.limit,
}
},{
headers:{
Authorization: "jwt " + token,
}
}).then(response=>{
if(parseInt(response.data.result.errno) == 1000){
if(this.page+1 == response.data.result.pages){
this.is_send_ajax = true;
}else{
this.is_send_ajax = false;
this.page+=1;
}
if(this.page>1){
api.refreshHeaderLoadDone();
}
this.goods_list = response.data.result.goods_list.concat(this.goods_list);
}else if (parseInt(response.data.result.errno) == 1008) {
this.friends = [];
}else {
this.game.print(response.data);
}
}).catch(error=>{
// 网络等异常
this.game.print(error);
});
})
},
buy_prop(prop_id){
// 购买商品道具
// 让用户选择购买的数量
api.prompt({
text: 1,
title: '请输入购买数量',
type: 'number',
buttons: ['确定', '取消']
}, (ret, err)=>{
if( ret.buttonIndex == 1 ){
// 通过通知告知socket进行商品购买
api.sendEvent({
name: 'buy_prop',
extra: {
'pid': prop_id,
'num': ret.text
}
});
}
});
}
}
});
}
</script>
</body>
</html>
在种植园主页面orchard.html
中通过监听获取购买道具的通知, 并通过socket发起请求服务端进行购买, 代码:
<!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>
<script src="../static/js/uuid.js"></script>
<script src="../static/js/settings.js"></script>
<script src="../static/js/socket.io.js"></script>
</head>
<body>
<div class="app orchard" id="app">
<img class="music" :class="music_play?'music2':''" @click="music_play=!music_play" src="../static/images/player.png">
<div class="orchard-bg">
<img src="../static/images/bg2.png">
<img class="board_bg2" src="../static/images/board_bg2.png">
</div>
<img class="back" @click="go_index" src="../static/images/user_back.png" alt="">
<div class="header">
<div class="info" @click='go_home'>
<div class="avatar">
<img class="avatar_bf" src="../static/images/avatar_bf.png" alt="">
<img class="user_avatar" src="../static/images/avatar.png" alt="">
<img class="avatar_border" src="../static/images/avatar_border.png" alt="">
</div>
<p class="user_name">好听的昵称</p>
</div>
<div class="wallet">
<div class="balance" @click='user_recharge'>
<p class="title"><img src="../static/images/money.png" alt="">钱包</p>
<p class="num">{{money}}</p>
</div>
<div class="balance">
<p class="title"><img src="../static/images/integral.png" alt="">果子</p>
<p class="num">99,999.00</p>
</div>
</div>
<div class="menu-list">
<div class="menu">
<img src="../static/images/menu1.png" alt="">
排行榜
</div>
<div class="menu">
<img src="../static/images/menu2.png" alt="">
签到有礼
</div>
<div class="menu" @click='go_orchard_shop'>
<img src="../static/images/menu3.png" alt="">
道具商城
</div>
<div class="menu">
<img src="../static/images/menu4.png" alt="">
邮件中心
</div>
</div>
</div>
<div class="footer">
<ul class="menu-list">
<li class="menu">新手</li>
<li class="menu" @click='go_my_package'>背包</li>
<li class="menu-center" @click='go_orchard_shop'>商店</li>
<li class="menu">消息</li>
<li class="menu" @click='go_friends'>好友</li>
</ul>
</div>
</div>
<script>
apiready = function(){
init();
new Vue({
el:"#app",
data(){
return {
music_play:true,
namespace: '/mofang',
token:"",
money:"",
socket: null,
recharge_list: ['10','20','50','100','200','500','1000'],
timeout: 0,
prev:{name:"",url:"",params:{}},
current:{name:"orchard",url:"orchard.html",params:{}},
}
},
created(){
this.game.goFrame('orchard', 'my_orchard.html', this.current, {
x: 0,
y: 180,
w: 'auto',
h: 410,
}, null);
this.checkout();
this.money = this.game.fget("money");
this.buy_prop();
},
methods:{
user_recharge(){
// 发起充值请求
api.actionSheet({
title: '余额充值',
cancelTitle: '取消',
buttons: this.recharge_list
}, (ret, err)=>{
if( ret ){
if(ret.buttonIndex <= this.recharge_list.length){
// 充值金额
money = this.recharge_list[ret.buttonIndex-1];
// 调用支付宝充值
this.create_recharge(money);
}
}else{
}
});
},
create_recharge(money){
// 获取历史信息记录
var token = this.game.get('access_token') || this.game.fget('access_token');
this.game.checkout(this, token, (new_access_token)=>{
this.axios.post('', {
'jsonrpc': '2.0',
'id': this.uuid(),
'method': 'Recharge.create',
'params': {
'money': money,
}
},{
headers:{
Authorization: "jwt " + token,
}
}).then(response=>{
// this.game.print(response.data);
if(parseInt(response.data.result.errno)==1000){
// 前往支付宝
var aliPayPlus = api.require("aliPayPlus");
aliPayPlus.payOrder({
orderInfo: response.data.result.order_string,
sandbox: response.data.result.sandbox, // 将来APP上线需要修改成false
}, (ret, err)=>{
pay_result = {
9000:'支付成功',
8000:"正在处理中",
4000:"订单支付失败",
5000:"重复请求",
6001:"取消支付",
6002:"网络连接出错",
6004:"支付结果未知",
}
api.alert({
title: '支付结果',
msg: pay_result[ret.code],
buttons: ['确定']
});
// 通知服务端, 修改充值结果
this.return_recharge(response.data.result.order_number, token);
});
}else {
this.game.print(response.data);
}
}).catch(error=>{
// 网络等异常
this.game.print(error);
});
})
},
return_recharge(out_trade_number, token){
this.axios.post("", {
'jsonrpc':"2.0",
'id':this.uuid(),
'method':'Recharge.return',
'params': {
'out_trade_number':out_trade_number,
}
},{
headers:{
Authorization: "jwt " + token,
}
}).then(response=>{
if(parseInt(response.data.result.errno)==1000){
this.money = response.data.result.money.toFixed(2);
}
})
},
checkout(){
var token = this.game.get("access_token") || this.game.fget("access_token");
this.game.checkout(this,token,(new_access_token)=>{
this.connect();
});
},
connect(){
// socket连接
this.socket = io.connect(this.settings.socket_server + this.namespace, {transports: ['websocket']});
this.socket.on('connect', ()=>{
this.game.print("开始连接服务端");
var id = this.game.fget('id');
this.socket.emit('login', {'uid': id});
});
},
go_index(){
this.game.goWin("root");
},
go_friends(){
this.game.goFrame('friends', 'friends.html', this.current);
this.game.goFrame('friend_list', 'friend_list.html', this.current, {
x: 0,
y: 190,
w: 'auto',
h: 'auto',
}, null, true);
},
go_home(){
this.game.goWin('user', 'user.html', this.current);
},
go_orchard_shop(){
// 种植园商店
this.game.goFrame('orchard_shop', 'shop.html', this.current, null, {
type: 'push',
subType: 'from_top',
duration: 300
});
},
go_my_package(){
// 我的背包
this.game.goFrame('package', 'package.html', this.current, null, {
type: 'push',
subType: 'from_top',
duration: 300
});
},
buy_prop(){
api.addEventListener({
name: 'buy_prop'
}, (ret, err)=>{
if( ret ){
// 用户购买道具
this.socket.emit('user_buy_prop', ret.value);
}
});
}
}
});
}
</script>
</body>
</html>
服务端socket监听购买道具事件, orchard/socket.py
, 代码:
from application import socketio
from flask import request
from application.apps.users.models import User
from flask_socketio import join_room, leave_room
from application import mongo
from .models import Goods
from status import APIStatus as status
from message import ErrorMessage as errmsg
# 建立socket通信
# @socketio.on('connect', namespace='/mofang')
# def user_connect():
# """用户连接"""
# print('用户%s连接过来了!' % request.sid)
# # 主动响应数据给客户端
# socketio.emit('server_response', 'hello', namespace='/mofang')
# 断开socket通信
@socketio.on('disconnect', namespace='/mofang')
def user_disconnect():
print('用户%s退出了种植园' % request.sid)
@socketio.on('login', namespace='/mofang')
def user_login(data):
# 分配房间
room = data['uid']
join_room(room)
# 保存当前用户和sid的绑定关系
# 判断当前用户是否在mongo中有记录
query = {
'_id': data['uid']
}
ret = mongo.db.user_info_list.find_one(query)
if ret:
mongo.db.user_info_list.update_one(query, {'$set': {'sid': request.sid}})
else:
mongo.db.user_info_list.insert_one({
'_id': data['uid'],
'sid': request.sid,
})
socketio.emit('login_response', {'errno': status.CODE_OK, 'errmsg': errmsg.ok}, namespace='/mofang', room=room)
@socketio.on('user_buy_prop', namespace='/mofang')
def user_buy_prop(data):
"""用户购买道具"""
room = request.sid
# 从mongo中获取当前用户信息
user_info = mongo.db.user_info_list.find_one({'sid': request.sid})
user = User.query.get(user_info.get('_id'))
if user is None:
socketio.emit('user_buy_prop_response', {'errno': status.CODE_NO_USER, 'errmsg': errmsg.user_not_exists}, namespace='/mofang', room=room)
return
# 从mysql中获取商品价格
prop = Goods.query.get(data['pid'])
if float(user.money) < float(prop.price) * int(data['num']):
socketio.emit('user_buy_prop_response', {'errno': status.CODE_NO_MONEY, 'errmsg': errmsg.money_no_enough}, namespace='/mofang', room=room)
return
# 从mongo中获取用户列表信息,提取购买的商品数量进行累加和余额
query = {'sid': request.sid}
if user_info.get('prop_list') is None:
"""此前没有购买任何道具"""
message = {'$set': {'prop_list': {'prop_%s' % prop.id: int(data['num'])}}}
mongo.db.user_info_list.update_one(query, message)
else:
"""此前有购买了道具"""
prop_list = user_info.get('prop_list') # 道具列表
if('prop_%s' % prop.id) in prop_list:
"""如果再次同一款道具"""
prop_list[('prop_%s' % prop.id)] = prop_list[('prop_%s' % prop.id)] + int(data['num'])
else:
"""此前没有购买过这种道具"""
prop_list[('prop_%s' % prop.id)] = int(data['num'])
mongo.db.user_info_list.update_one(query, {'$set': {'prop_list': prop_list}})
socketio.emit('user_buy_prop_response', {'errno': status.CODE_OK, 'errmsg': errmsg.ok}, namespace='/mofang', room=room)
status.py
,代码:
CODE_NO_MONEY = 1014 # 余额不足
message.py
,代码:
money_no_enough = "余额不足!"