魔坊APP项目-19-种植园,我的背包、道具购买

种植园

一、我的背包

打开背包,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 = "余额不足!"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值