Explorar el Código

Merge remote-tracking branch 'origin/feature/wxPay' into feature/temp

# Conflicts:
#	pages.json
#	pages/personal/personal.vue
qzy hace 1 mes
padre
commit
ee23cef6bc

+ 46 - 3
pages.json

@@ -435,7 +435,7 @@
 				}
 			}
 
-		}, 
+		},
 		{
 			"path": "pages/personal/my",
 			"style": {
@@ -450,7 +450,7 @@
 				"navigationBarTitleText": "互助组信息",
 				"enablePullDownRefresh": false
 			}
-		
+
 		},
 		{
 			"path": "pages/market/group/gourpIndex",
@@ -458,7 +458,7 @@
 				"navigationBarTitleText": "组内边民",
 				"enablePullDownRefresh": false
 			}
-		
+
 		},
 		{
 			"path": "pages/personal/setting",
@@ -665,6 +665,49 @@
 				"enablePullDownRefresh": true
 			}
 
+
+		},
+		{
+		    "path" : "pages/wallet/wallet",
+		    "style" :{
+		        "navigationBarTitleText": "服务点数",
+		        "enablePullDownRefresh": true
+		    }
+		},
+		{
+			"path": "pages/wallet/topup/edit",
+			"style": {
+				"navigationBarTitleText": "服务点充值",
+				"enablePullDownRefresh": false
+			}
+		},
+		{
+			"path": "pages/wallet/topdown/edit",
+			"style": {
+				"navigationBarTitleText": "服务点充提现",
+				"enablePullDownRefresh": false
+			}
+		},
+		{
+			"path": "pages/wallet/detail",
+			"style": {
+				"navigationBarTitleText": "服务点扣除详细",
+				"enablePullDownRefresh": false
+			}
+		},
+		{
+			"path": "pages/wallet/topup/detail",
+			"style": {
+				"navigationBarTitleText": "服务点充值详细",
+				"enablePullDownRefresh": false
+			}
+		},
+		{
+			"path": "pages/wallet/topdown/detail",
+			"style": {
+				"navigationBarTitleText": "服务点提现详细",
+				"enablePullDownRefresh": false
+			}
 		}
 	],
 	"tabBar": {

+ 12 - 0
pages/index/index.vue

@@ -362,6 +362,18 @@
 					}
 				});
 			},
+			getUserWallet() {
+				if(this.user.userType===1){
+					this.http.request({
+						url: '/level-one-server/app/TbPeople/getById',
+						data: { id: this.user.fkId },
+						success: res => {
+							this.user.wallet = res.data.data.wallet;
+							uni.setStorageSync('info', this.user);
+						}
+					});
+				}
+			},
 			//点击轮播图
 			click(index) {
 				let item = this.bannerList[index];

+ 76 - 1
pages/personal/personal.vue

@@ -40,6 +40,7 @@
 					<view class="tag" v-if="user.userType == 4">司机</view>
 					<view class="tag" v-if="user.userType == 5">商户</view>
 					<view class="tag" v-if="user.userType == 6">合作社</view>
+					<view class="tag" style="margin-left: 0.5rem;" v-if="user.userType == 1" @click="go('/pages/wallet/wallet')">服务点数: {{ user.wallet }}</view>
 				</view>
 				<view class="clear"></view>
 			</view>
@@ -82,7 +83,7 @@
 				<view class="s_item ">
 					<text class="icon ic">&#xe622;</text>
 					<text class="title">APP版本 {{version}}</text>
-					
+
 				</view>
 			</view>
 			<button class="btn exit" @click="exitLogin()">退出登录</button>
@@ -137,6 +138,16 @@
 					uni.setStorageSync('info', this.user);
 				}
 			});
+		};
+		if(this.user.userType===1){
+			this.http.request({
+				url: '/level-one-server/app/TbPeople/getById',
+				data: { id: this.user.fkId },
+				success: res => {
+					this.user.wallet = res.data.data.wallet;
+					uni.setStorageSync('info', this.user);
+				}
+			});
 		},
 		methods: {
 			makePhoneCall(phone) {
@@ -239,6 +250,70 @@
 			}
 		}
 	};
+		}
+	},
+	methods: {
+		order() {
+			if (!this.hasAuth()) {
+				uni.navigateTo({ url: '/pages/authentication/index' });
+				return;
+			}
+			//组长
+			if (this.user.userType == 2) {
+				uni.navigateTo({ url: 'user' });
+			}
+			//外籍商户
+			if (this.user.userType == 5) {
+				uni.navigateTo({ url: '/pages/market/one/merchant/order/list' });
+			}
+			//收购商
+			if (this.user.userType == 3) {
+				uni.navigateTo({ url: '/pages/market/two/purchaser/order/list' });
+			}
+		},
+		wallet() {
+			if (!this.hasAuth() && this.user.userType == 1) {
+				uni.navigateTo({ url: '/pages/wallet/wallet' });
+				return;
+			}
+		},
+		go(url) {
+			if (!this.hasAuth() && this.user.userType == 5) {
+				uni.navigateTo({ url: '/pages/authentication/index' });
+				return;
+			}
+			if (!this.hasAuth() && this.user.userType == 3) {
+				uni.navigateTo({ url: '/pages/authentication/purchaser/index' });
+				return;
+			}
+			uni.navigateTo({ url: url });
+		},
+		exitLogin() {
+			let param = {
+				appUserId: this.getUser().id
+			};
+			uni.showModal({
+				title: '提示',
+				content: '确定注销登录?',
+				success: res => {
+					if (res.confirm) {
+						uni.removeStorageSync('token');
+						uni.removeStorageSync('info');
+						uni.removeStorageSync('menu');
+						uni.redirectTo({ url: '/pages/login/login' });
+						this.http.request({
+							url: '/sp-admin/app/AppUser/logout',
+							data: param,
+							success: res => {
+
+							}
+						});
+					}
+				}
+			});
+		}
+	}
+};
 </script>
 
 <style lang="scss">

+ 74 - 0
pages/wallet/detail.vue

@@ -0,0 +1,74 @@
+<template>
+	<view>
+		<view class="cmain">
+			<view class="box order_detail" style="margin-top: 0px">
+				<u-divider text="服务点扣除信息"></u-divider>
+				<view class="item" style="padding-top: 0px">
+					<text class="label">扣除用途</text>
+					<text class="desc">商品上架</text>
+				</view>
+				<view class="item">
+					<text class="label">订单号</text>
+					<text class="desc omit">{{ item.tradeNo }}</text>
+				</view>
+				<view class="item">
+					<text class="label">商品名称</text>
+					<text class="desc">{{ item.goodsNames }}</text>
+				</view>
+				<view class="item">
+					<text class="label">商铺名称</text>
+					<text class="desc">{{ item.shopName }}</text>
+				</view>			
+				<view class="item">
+					<text class="label">车牌号</text>
+					<text class="desc">{{ item.veNo }}</text>
+				</view>
+				<view class="item">
+					<text class="label">交易扣除点数</text>
+					<text class="desc">-{{ item.amount }}</text>
+				</view>
+				<view class="item">
+					<text class="label">扣除时间</text>
+					<text class="desc">{{ item.recordTime }}</text>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			item: {},
+			param: {},
+		};
+	},
+	onLoad(e) {
+		if (e.id) {
+			this.param.id = e.id
+			this.http.request({
+				url: '/level-one-server/app/WalletManage/getWalletRecordById',
+				data: this.param,
+				success: res => {
+					this.item = res.data.data;
+				}
+			});
+		}
+	},
+	methods: {
+		//查看边民
+		members(id) {
+			uni.navigateTo({
+				url: '/pages/market/one/leader/members?id=' + id
+			});
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+page {
+	background-color: $pg;
+}
+</style>

+ 65 - 0
pages/wallet/topdown/detail.vue

@@ -0,0 +1,65 @@
+<template>
+	<view>
+		<view class="cmain">
+			<view class="box order_detail" style="margin-top: 0px">
+				<u-divider text="服务点提现信息"></u-divider>
+				<view class="item" style="padding-top: 0px">
+					<text class="label">提现方式</text>
+					<text class="desc">电子银联</text>
+				</view>
+				<view class="item">
+					<text class="label">商户号</text>
+					<text class="desc omit">{{ item.mchid }}</text>
+				</view>
+				<view class="item">
+					<text class="label">商户系统内部订单号</text>
+					<text class="desc omit">{{ item.outTradeNo }}</text>
+				</view>
+				<view class="item">
+					<text class="label">平台系统生成的订单号</text>
+					<text class="desc omit">{{ item.transactionId }}</text>
+				</view>
+				<view class="item">
+					<text class="label">服务点数量(金额)</text>
+					<text class="desc">-{{ item.amount }}</text>
+				</view>
+				<view class="item">
+					<text class="label">提现时间</text>
+					<text class="desc">{{ item.topdownTime }}</text>
+				</view>	
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			item: {},
+			param: {},
+		};
+	},
+	onLoad(e) {
+		if (e.id) {
+			this.param.id = e.id
+			this.http.request({
+				url: '/level-one-server/app/WalletManage/getTopDownById',
+				data: this.param,
+				success: res => {
+					this.item = res.data.data;
+				}
+			});
+		}
+	},
+	methods: {
+		
+	}
+};
+</script>
+
+<style lang="scss">
+page {
+	background-color: $pg;
+}
+</style>

+ 451 - 0
pages/wallet/topdown/edit.vue

@@ -0,0 +1,451 @@
+<template>
+	<view class="app">
+		<view style="padding-bottom: 0.5rem;">
+			<view class="label">可用服务点数:{{user.wallet}}</view>
+		</view>
+		<view>
+			<view class="label">提现单号:</view>
+			<view><input v-model="out_trade_no" /></view>
+		</view>
+		<view>
+			<view class="label">提现金额(单位分,100=1元):</view>
+			<view><input v-model.number="total_fee" type="number" /></view>
+		</view>
+		
+		<!-- #endif -->
+		<!-- #ifdef MP-WEIXIN || H5 || APP -->
+		<button type="primary" @click="createOrder('wxpay')">发起提现</button>
+		<!-- #endif -->		
+
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				total_fee: 1000, // 支付金额,单位分 100 = 1元
+				order_no: "", // 业务系统订单号(即你自己业务系统的订单表的订单号)
+				out_trade_no: "", // 插件支付单号
+				description: "测试订单", // 支付描述
+				type: "test", // 支付回调类型 如 recharge 代表余额充值 goods 代表商品订单(可自定义,任意英文单词都可以,只要你在 uni-pay-co/notify/目录下创建对应的 xxx.js文件进行编写对应的回调逻辑即可)
+				//qr_code: true, // 是否强制使用扫码支付
+				openid:"", // 微信公众号需要
+				custom:{
+					a: "a",
+					b: 1
+				},
+				adpid: "1000000001", // uni-ad的广告位id
+				
+				transaction_id:"", // 查询订单接口的查询条件
+				getOrderRes:{}, // 查询订单支付成功后的返回值
+			}
+		},
+		onLoad(options={}) {
+			// #ifdef H5
+			// 微信公众号特殊逻辑开始-----------------------------------------------------------
+			// 以下代码仅为获取openid,正常你自己项目应该是登录后才能支付,登录后已经拿到openid,无需编写下面的代码
+			if (this.h5Env === 'h5-weixin') {
+				let openid = uni.getStorageSync("uni-pay-weixin-h5-openid");
+				let code = uni.getStorageSync("uni-pay-weixin-h5-code");
+				if (openid) {
+					this.openid = openid;
+				}
+				// 如果code和state有值,且此code没有被使用过,则执行获取微信公众号的openid
+				if (options.code && options.state && code !== options.code) {
+					// 获取微信公众号的openid
+					setTimeout(() => {
+						this.getOpenid({
+							provider: "wxpay",
+							code: options.code
+						});
+					}, 300);
+				} else if (!openid){
+					// 如果openid为空,则执行微信公众号的网页授权登录逻辑
+					setTimeout(() => {
+						this.getWeiXinJsCode('snsapi_base');
+					}, 300);
+				}
+			}
+			this.order_no = `test`+Date.now();
+			this.out_trade_no = `${this.order_no}-1`;
+			this.user = this.getUser();
+			// 微信公众号特殊逻辑结束-----------------------------------------------------------
+			// #endif
+		},
+		methods: {
+			/**
+			 * 发起支付(唤起收银台,如果只有一种支付方式,则收银台不会弹出来,会直接使用此支付方式)
+			 * 在调用此api前,你应该先创建自己的业务系统订单,并获得订单号 order_no,把order_no当参数传给此api,而示例中为了简化跟支付插件无关的代码,这里直接已时间戳生成了order_no
+			 */
+			open() {
+				this.order_no = `test`+Date.now();
+				this.out_trade_no = `${this.order_no}-1`;
+				// 打开支付收银台
+				this.$refs.pay.open({
+					total_fee: this.total_fee, // 支付金额,单位分 100 = 1元
+					order_no: this.order_no, // 业务系统订单号(即你自己业务系统的订单表的订单号)
+					out_trade_no: this.out_trade_no, // 插件支付单号
+					description: this.description, // 支付描述
+					type: this.type, // 支付回调类型
+					qr_code: this.qr_code, // 是否强制使用扫码支付
+					openid: this.openid, // 微信公众号需要
+					custom: this.custom, // 自定义数据
+				});
+			},
+			/**
+			 * 发起支付(不唤起收银台,手动指定支付方式)
+			 * 在调用此api前,你应该先创建自己的业务系统订单,并获得订单号 order_no,把order_no当参数传给此api,而示例中为了简化跟支付插件无关的代码,这里直接已时间戳生成了order_no
+			 */
+			createOrder(provider){
+
+				/*
+				// 发起支付
+				this.$refs.pay.createOrder({
+					provider: provider, // 支付供应商
+					total_fee: this.total_fee, // 支付金额,单位分 100 = 1元
+					order_no: this.order_no, // 业务系统订单号(即你自己业务系统的订单表的订单号)
+					out_trade_no: this.out_trade_no, // 插件支付单号
+					description: this.description, // 支付描述
+					type: this.type, // 支付回调类型
+					qr_code: this.qr_code, // 是否强制使用扫码支付
+					openid: this.openid, // 微信公众号需要
+					custom: this.custom, // 自定义数据
+				});
+				*/
+			   this.http.request({
+			   	url: '/level-one-server/app/WalletManage/topdownSave',
+			   	data: {
+					amount: this.total_fee, // 支付金额,单位分 100 = 1元
+					transactionId: this.order_no, // 业务系统订单号(即你自己业务系统的订单表的订单号)
+					outTradeNo: this.out_trade_no, // 插件支付单号
+			   	},
+			   	success: res => {
+					this.user.wallet = this.user.wallet - this.total_fee/100;
+					console.log("this.user",this.user)
+					uni.setStorageSync('info', this.user);
+			   		uni.showToast({
+			   			title: '提现成功!'
+			   		});
+					uni.navigateBack({
+						data:1
+					});
+			   	}
+			   });
+				
+			},
+			/**
+			 * 生成支付独立二维码(只返回支付二维码)
+			 * 在调用此api前,你应该先创建自己的业务系统订单,并获得订单号 order_no,把order_no当参数传给此api,而示例中为了简化跟支付插件无关的代码,这里直接已时间戳生成了order_no
+			 */
+			createQRcode(provider){
+				this.order_no = `test`+Date.now();
+				this.out_trade_no = `${this.order_no}-1`;
+				// 发起支付
+				this.$refs.pay.createOrder({
+					provider: provider, // 支付供应商
+					total_fee: this.total_fee, // 支付金额,单位分 100 = 1元
+					order_no: this.order_no, // 业务系统订单号(即你自己业务系统的订单表的订单号)
+					out_trade_no: this.out_trade_no, // 插件支付单号
+					description: this.description, // 支付描述
+					type: this.type, // 支付回调类型
+					qr_code: true, // 是否强制使用扫码支付
+					cancel_popup: true, // 配合qr_code:true使用,是否只生成支付二维码,没有二维码弹窗
+					openid: this.openid, // 微信公众号需要
+					custom: this.custom, // 自定义数据
+				});
+			},
+			/**
+			 * 前往自定义收银台页面
+			 * 在调用此api前,你应该先创建自己的业务系统订单,并获得订单号 order_no,把order_no当参数传给此api,而示例中为了简化跟支付插件无关的代码,这里直接已时间戳生成了order_no
+			 */
+			toPayDesk(){
+				this.order_no = `test`+Date.now();
+				this.out_trade_no = `${this.order_no}-1`;
+				let options = {
+					total_fee: this.total_fee, // 支付金额,单位分 100 = 1元
+					order_no: this.order_no, // 业务系统订单号(即你自己业务系统的订单表的订单号)
+					out_trade_no: this.out_trade_no, // 插件支付单号
+					description: this.description, // 支付描述
+					type: this.type, // 支付回调类型
+					qr_code: this.qr_code, // 是否强制使用扫码支付
+					openid: this.openid, // 微信公众号需要
+					custom: this.custom, // 自定义数据
+				};
+				let optionsStr = encodeURI(JSON.stringify(options));
+				uni.navigateTo({
+					url:`/uni_modules/uni-pay/pages/pay-desk/pay-desk?options=${optionsStr}`
+				});
+			},
+			// 打开查询订单的弹窗
+			getOrderPopup(key){
+				if (key) {
+					this.$refs.getOrderPopup.open();
+				} else {
+					this.$refs.getOrderPopup.close();
+				}
+			},
+			// 查询支付状态
+			async getOrder() {
+				this.getOrderRes = {};
+				let res = await this.$refs.pay.getOrder({
+					//out_trade_no: this.out_trade_no, // 插件支付单号 两者传1个即可
+					transaction_id: this.transaction_id, // 第三方单号 两者传1个即可
+					await_notify: true
+				});
+				if (res) {
+					this.getOrderRes = res.pay_order;
+					let obj = {
+						"-1": "已关闭",
+						"1": "已支付",
+						"0": "未支付",
+						"2": "已部分退款",
+						"3": "已全额退款"
+					};
+					uni.showToast({
+						title: obj[res.status] || res.errMsg,
+						icon: "none"
+					});
+				}
+			},
+			// 发起退款
+			async refund() {
+				let res = await this.$refs.pay.refund({
+					out_trade_no: this.out_trade_no, // 插件支付单号
+				});
+				if (res) {
+					uni.showToast({
+						title: res.errMsg,
+						icon: "none"
+					});
+				}
+			},
+			// 查询退款状态
+			async getRefund() {
+				let res = await this.$refs.pay.getRefund({
+					out_trade_no: this.out_trade_no, // 插件支付单号
+				});
+				if (res) {
+					uni.showModal({
+						content: res.errMsg,
+						showCancel: false
+					});
+				}
+			},
+			// 关闭订单
+			async closeOrder() {
+				let res = await this.$refs.pay.closeOrder({
+					out_trade_no: this.out_trade_no, // 插件支付单号
+				});
+				if (res) {
+					uni.showModal({
+						content: res.errMsg,
+						showCancel: false
+					});
+				}
+			},
+			// 获取公众号code
+			async getWeiXinJsCode(scope="snsapi_base") {
+				let res = await this.$refs.pay.getProviderAppId({
+					provider: "wxpay",
+					provider_pay_type: "jsapi"
+				});
+				if (res.appid) {
+					let appid = res.appid;
+					let redirect_uri = window.location.href.split("?")[0];
+					let url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${redirect_uri}&response_type=code&scope=${scope}&state=STATE#wechat_redirect`;
+					window.location.href = url;
+				}
+			},
+			// 获取公众号openid
+			async getOpenid(data={}) {
+				let res = await this.$refs.pay.getOpenid(data);
+				if (res) {
+					this.openid = res.openid;
+					// 将openid缓存到本地
+					uni.setStorageSync("uni-pay-weixin-h5-openid", this.openid);
+					uni.setStorageSync("uni-pay-weixin-h5-code", data.code);
+					uni.showToast({
+						title: "已获取到openid,可以开始支付",
+						icon: "none"
+					});
+				}
+			},
+			// 监听事件 - 支付订单创建成功(此时用户还未支付)
+			onCreate(res){
+				console.log('create: ', res);
+				// 如果只是想生成支付二维码,不需要组件自带的弹窗,则在这里可以获取到支付二维码 qr_code_image
+			},
+			// 监听事件 - 支付成功
+			onSuccess(res){
+				console.log('success: ', res);
+				if (res.user_order_success) {
+					// 代表用户已付款,且你自己写的回调成功并正确执行了
+					
+				} else {
+					// 代表用户已付款,但你自己写的回调执行失败(通常是因为你的回调代码有问题)
+	
+				}
+			},
+			onFail(err){
+				console.log('err: ', err)
+				
+			},
+			pageTo(url){
+				uni.navigateTo({
+					url
+				});
+			},
+			providerFormat(provider){
+				let providerObj = {
+					"wxpay":"微信支付",
+					"alipay":"支付宝支付",
+					"appleiap":"ios内购"
+				};
+				let providerStr = providerObj[provider] || "未知";
+				return providerStr;
+			},
+			/**
+			 * 日期格式化
+			 * @params {Date || Number} date 需要格式化的时间
+			 * timeFormat(new Date(),"yyyy-MM-dd hh:mm:ss");
+			 */
+			timeFormat(time, fmt = 'yyyy-MM-dd hh:mm:ss', targetTimezone = 8){
+				try {
+					if (!time) {
+						return "";
+					}
+					if (typeof time === "string" && !isNaN(time)) time = Number(time);
+					// 其他更多是格式化有如下:
+					// yyyy-MM-dd hh:mm:ss|yyyy年MM月dd日 hh时MM分等,可自定义组合
+					let date;
+					if (typeof time === "number") {
+						if (time.toString().length == 10) time *= 1000;
+						date = new Date(time);
+					} else {
+						date = time;
+					}
+							
+					const dif = date.getTimezoneOffset();
+					const timeDif = dif * 60 * 1000 + (targetTimezone * 60 * 60 * 1000);
+					const east8time = date.getTime() + timeDif;
+							
+					date = new Date(east8time);
+					let opt = {
+						"M+": date.getMonth() + 1, //月份
+						"d+": date.getDate(), //日
+						"h+": date.getHours(), //小时
+						"m+": date.getMinutes(), //分
+						"s+": date.getSeconds(), //秒
+						"q+": Math.floor((date.getMonth() + 3) / 3), //季度
+						"S": date.getMilliseconds() //毫秒
+					};
+					if (/(y+)/.test(fmt)) {
+						fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
+					}
+					for (let k in opt) {
+						if (new RegExp("(" + k + ")").test(fmt)) {
+							fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (opt[k]) : (("00" + opt[k]).substr(("" + opt[k]).length)));
+						}
+					}
+					return fmt;
+				} catch (err) {
+					// 若格式错误,则原值显示
+					return time;
+				}
+			},
+		}, 
+		computed: {
+			h5Env(){
+				// #ifdef H5
+				let ua = window.navigator.userAgent.toLowerCase();
+				if (ua.match(/MicroMessenger/i) == 'micromessenger' && (ua.match(/miniprogram/i) == 'miniprogram')) {
+					// 微信小程序
+					return "mp-weixin";
+				}
+				if (ua.match(/MicroMessenger/i) == 'micromessenger') {
+					// 微信公众号
+					return "h5-weixin";
+				}
+				if (ua.match(/alipay/i) == 'alipay' && ua.match(/miniprogram/i) == 'miniprogram') {
+					return "mp-alipay";
+				}
+				if (ua.match(/alipay/i) == 'alipay') {
+					return "h5-alipay";
+				}
+				// 外部 H5
+				return "h5";
+				// #endif
+			},
+			// 计算当前是否是ios app
+			isIosAppCom(){
+				let info = uni.getSystemInfoSync();
+				return info.uniPlatform === 'app' && info.osName === 'ios' ? true : false;
+			},
+			// 计算当前是否是PC环境
+			isPcCom(){
+				// #ifdef H5
+				let info = uni.getSystemInfoSync();
+				return info.deviceType === 'pc' ? true : false;
+				// #endif
+				return false;
+			}
+		},
+	}
+</script>
+
+<style lang="scss" scoped>
+	.app{
+		padding: 30rpx;
+	}
+	input {
+		border: 1px solid #f3f3f3;
+		padding: 10rpx;
+		width: 100%;
+		box-sizing: border-box;
+		height: 80rpx;
+	}
+
+	button {
+		margin-top: 20rpx;
+	}
+	
+	.label{
+		margin: 10rpx 0;
+	}
+	
+	.tips{
+		margin-top: 20rpx;
+		font-size: 24rpx;
+		color: #565656;
+	}
+	
+	.get-order-popup{
+		background-color: #ffffff;
+		padding: 30rpx;
+		height: 60vh;
+		border-radius: 30rpx 30rpx 0 0;
+		overflow: hidden;
+	}
+	.mt20{
+		margin-top: 20rpx;
+	}
+	
+	.pd2030{
+		padding: 20rpx 30rpx;
+	}
+	
+	.table{
+		font-size: 24rpx;
+	}
+	.align-left{
+		text-align: left;
+		width: 50%;
+	}
+	.align-right{
+		text-align: right;
+		width: 50%;
+	}
+	
+	
+</style>

+ 65 - 0
pages/wallet/topup/detail.vue

@@ -0,0 +1,65 @@
+<template>
+	<view>
+		<view class="cmain">
+			<view class="box order_detail" style="margin-top: 0px">
+				<u-divider text="服务点充值信息"></u-divider>
+				<view class="item" style="padding-top: 0px">
+					<text class="label">支付方式</text>
+					<text class="desc">微信支付</text>
+				</view>
+				<view class="item">
+					<text class="label">商户号</text>
+					<text class="desc omit">{{ item.mchid }}</text>
+				</view>
+				<view class="item">
+					<text class="label">商户系统内部订单号</text>
+					<text class="desc omit">{{ item.outTradeNo }}</text>
+				</view>
+				<view class="item">
+					<text class="label">微信支付系统生成的订单号</text>
+					<text class="desc omit">{{ item.transactionId }}</text>
+				</view>
+				<view class="item">
+					<text class="label">服务点数量(金额)</text>
+					<text class="desc">+{{ item.amount }}</text>
+				</view>
+				<view class="item">
+					<text class="label">充值时间</text>
+					<text class="desc">{{ item.topupTime }}</text>
+				</view>	
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			item: {},
+			param: {},
+		};
+	},
+	onLoad(e) {
+		if (e.id) {
+			this.param.id = e.id
+			this.http.request({
+				url: '/level-one-server/app/WalletManage/getTopUpById',
+				data: this.param,
+				success: res => {
+					this.item = res.data.data;
+				}
+			});
+		}
+	},
+	methods: {
+		
+	}
+};
+</script>
+
+<style lang="scss">
+page {
+	background-color: $pg;
+}
+</style>

+ 463 - 0
pages/wallet/topup/edit.vue

@@ -0,0 +1,463 @@
+<template>
+	<view class="app">
+		<view>
+			<view class="label">支付单号:</view>
+			<view><input v-model="out_trade_no" /></view>
+		</view>
+		<view>
+			<view class="label">支付金额(单位分,100=1元):</view>
+			<view><input v-model.number="total_fee" type="number" /></view>
+		</view>
+		
+		<!-- #endif -->
+		<!-- #ifdef MP-WEIXIN || H5 || APP -->
+		<button type="primary" @click="createOrder('wxpay')">发起支付(微信)</button>
+		<!-- #endif -->		
+	
+		<!-- #ifdef MP-WEIXIN -->
+		<button @click="pageTo('/pages/weixin-virtual-payment/weixin-virtual-payment')">微信小程序虚拟支付示例</button>
+		<!-- #endif -->
+		
+		<!--
+		<button @click="refund">发起退款</button>
+		<view class="tips">发起退款需要admin权限,本示例未对接登录功能</view>
+		<button @click="getRefund">查询退款状态</button>
+		<button @click="closeOrder">关闭订单</button>
+		-->
+		<!-- #ifdef H5 -->
+		<button v-if="h5Env === 'h5-weixin'" @click="getWeiXinJsCode('snsapi_base')">公众号获取openid示例</button>
+		<!-- #endif -->
+		<!-- 统一支付组件,注意:vue3下ref不可以等于组件名,因此这里ref="pay" 而不能是 ref="uniPay" -->
+		<uni-pay ref="pay" :adpid="adpid" height="70vh" return-url="/pages/order-detail/order-detail" logo="/static/logo.png" @success="onSuccess" @create="onCreate" @fail="onFail"></uni-pay>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				total_fee: 1000, // 支付金额,单位分 100 = 1元
+				order_no: "", // 业务系统订单号(即你自己业务系统的订单表的订单号)
+				out_trade_no: "", // 插件支付单号
+				description: "测试订单", // 支付描述
+				type: "test", // 支付回调类型 如 recharge 代表余额充值 goods 代表商品订单(可自定义,任意英文单词都可以,只要你在 uni-pay-co/notify/目录下创建对应的 xxx.js文件进行编写对应的回调逻辑即可)
+				//qr_code: true, // 是否强制使用扫码支付
+				openid:"", // 微信公众号需要
+				custom:{
+					a: "a",
+					b: 1
+				},
+				adpid: "1000000001", // uni-ad的广告位id
+				
+				transaction_id:"", // 查询订单接口的查询条件
+				getOrderRes:{}, // 查询订单支付成功后的返回值
+			}
+		},
+		onLoad(options={}) {
+			// #ifdef H5
+			// 微信公众号特殊逻辑开始-----------------------------------------------------------
+			// 以下代码仅为获取openid,正常你自己项目应该是登录后才能支付,登录后已经拿到openid,无需编写下面的代码
+			if (this.h5Env === 'h5-weixin') {
+				let openid = uni.getStorageSync("uni-pay-weixin-h5-openid");
+				let code = uni.getStorageSync("uni-pay-weixin-h5-code");
+				if (openid) {
+					this.openid = openid;
+				}
+				// 如果code和state有值,且此code没有被使用过,则执行获取微信公众号的openid
+				if (options.code && options.state && code !== options.code) {
+					// 获取微信公众号的openid
+					setTimeout(() => {
+						this.getOpenid({
+							provider: "wxpay",
+							code: options.code
+						});
+					}, 300);
+				} else if (!openid){
+					// 如果openid为空,则执行微信公众号的网页授权登录逻辑
+					setTimeout(() => {
+						this.getWeiXinJsCode('snsapi_base');
+					}, 300);
+				}
+			}
+			this.order_no = `test`+Date.now();
+			this.out_trade_no = `${this.order_no}-1`;
+			this.user = this.getUser();
+			// 微信公众号特殊逻辑结束-----------------------------------------------------------
+			// #endif
+		},
+		methods: {
+			/**
+			 * 发起支付(唤起收银台,如果只有一种支付方式,则收银台不会弹出来,会直接使用此支付方式)
+			 * 在调用此api前,你应该先创建自己的业务系统订单,并获得订单号 order_no,把order_no当参数传给此api,而示例中为了简化跟支付插件无关的代码,这里直接已时间戳生成了order_no
+			 */
+			open() {
+				this.order_no = `test`+Date.now();
+				this.out_trade_no = `${this.order_no}-1`;
+				// 打开支付收银台
+				this.$refs.pay.open({
+					total_fee: this.total_fee, // 支付金额,单位分 100 = 1元
+					order_no: this.order_no, // 业务系统订单号(即你自己业务系统的订单表的订单号)
+					out_trade_no: this.out_trade_no, // 插件支付单号
+					description: this.description, // 支付描述
+					type: this.type, // 支付回调类型
+					qr_code: this.qr_code, // 是否强制使用扫码支付
+					openid: this.openid, // 微信公众号需要
+					custom: this.custom, // 自定义数据
+				});
+			},
+			/**
+			 * 发起支付(不唤起收银台,手动指定支付方式)
+			 * 在调用此api前,你应该先创建自己的业务系统订单,并获得订单号 order_no,把order_no当参数传给此api,而示例中为了简化跟支付插件无关的代码,这里直接已时间戳生成了order_no
+			 */
+			createOrder(provider){
+
+				/*
+				// 发起支付
+				this.$refs.pay.createOrder({
+					provider: provider, // 支付供应商
+					total_fee: this.total_fee, // 支付金额,单位分 100 = 1元
+					order_no: this.order_no, // 业务系统订单号(即你自己业务系统的订单表的订单号)
+					out_trade_no: this.out_trade_no, // 插件支付单号
+					description: this.description, // 支付描述
+					type: this.type, // 支付回调类型
+					qr_code: this.qr_code, // 是否强制使用扫码支付
+					openid: this.openid, // 微信公众号需要
+					custom: this.custom, // 自定义数据
+				});
+				*/
+			   this.http.request({
+			   	url: '/level-one-server/app/WalletManage/topupSave',
+			   	data: {
+					amount: this.total_fee, // 支付金额,单位分 100 = 1元
+					transactionId: this.order_no, // 业务系统订单号(即你自己业务系统的订单表的订单号)
+					outTradeNo: this.out_trade_no, // 插件支付单号
+			   	},
+			   	success: res => {
+					this.user.wallet = this.user.wallet + this.total_fee/100;
+					console.log("this.user",this.user)
+					uni.setStorageSync('info', this.user);
+			   		uni.showToast({
+			   			title: '充值成功!'
+			   		});
+					uni.navigateBack({
+						data:1
+					});
+			   	}
+			   });
+				
+			},
+			/**
+			 * 生成支付独立二维码(只返回支付二维码)
+			 * 在调用此api前,你应该先创建自己的业务系统订单,并获得订单号 order_no,把order_no当参数传给此api,而示例中为了简化跟支付插件无关的代码,这里直接已时间戳生成了order_no
+			 */
+			createQRcode(provider){
+				this.order_no = `test`+Date.now();
+				this.out_trade_no = `${this.order_no}-1`;
+				// 发起支付
+				this.$refs.pay.createOrder({
+					provider: provider, // 支付供应商
+					total_fee: this.total_fee, // 支付金额,单位分 100 = 1元
+					order_no: this.order_no, // 业务系统订单号(即你自己业务系统的订单表的订单号)
+					out_trade_no: this.out_trade_no, // 插件支付单号
+					description: this.description, // 支付描述
+					type: this.type, // 支付回调类型
+					qr_code: true, // 是否强制使用扫码支付
+					cancel_popup: true, // 配合qr_code:true使用,是否只生成支付二维码,没有二维码弹窗
+					openid: this.openid, // 微信公众号需要
+					custom: this.custom, // 自定义数据
+				});
+			},
+			/**
+			 * 前往自定义收银台页面
+			 * 在调用此api前,你应该先创建自己的业务系统订单,并获得订单号 order_no,把order_no当参数传给此api,而示例中为了简化跟支付插件无关的代码,这里直接已时间戳生成了order_no
+			 */
+			toPayDesk(){
+				this.order_no = `test`+Date.now();
+				this.out_trade_no = `${this.order_no}-1`;
+				let options = {
+					total_fee: this.total_fee, // 支付金额,单位分 100 = 1元
+					order_no: this.order_no, // 业务系统订单号(即你自己业务系统的订单表的订单号)
+					out_trade_no: this.out_trade_no, // 插件支付单号
+					description: this.description, // 支付描述
+					type: this.type, // 支付回调类型
+					qr_code: this.qr_code, // 是否强制使用扫码支付
+					openid: this.openid, // 微信公众号需要
+					custom: this.custom, // 自定义数据
+				};
+				let optionsStr = encodeURI(JSON.stringify(options));
+				uni.navigateTo({
+					url:`/uni_modules/uni-pay/pages/pay-desk/pay-desk?options=${optionsStr}`
+				});
+			},
+			// 打开查询订单的弹窗
+			getOrderPopup(key){
+				if (key) {
+					this.$refs.getOrderPopup.open();
+				} else {
+					this.$refs.getOrderPopup.close();
+				}
+			},
+			// 查询支付状态
+			async getOrder() {
+				this.getOrderRes = {};
+				let res = await this.$refs.pay.getOrder({
+					//out_trade_no: this.out_trade_no, // 插件支付单号 两者传1个即可
+					transaction_id: this.transaction_id, // 第三方单号 两者传1个即可
+					await_notify: true
+				});
+				if (res) {
+					this.getOrderRes = res.pay_order;
+					let obj = {
+						"-1": "已关闭",
+						"1": "已支付",
+						"0": "未支付",
+						"2": "已部分退款",
+						"3": "已全额退款"
+					};
+					uni.showToast({
+						title: obj[res.status] || res.errMsg,
+						icon: "none"
+					});
+				}
+			},
+			// 发起退款
+			async refund() {
+				let res = await this.$refs.pay.refund({
+					out_trade_no: this.out_trade_no, // 插件支付单号
+				});
+				if (res) {
+					uni.showToast({
+						title: res.errMsg,
+						icon: "none"
+					});
+				}
+			},
+			// 查询退款状态
+			async getRefund() {
+				let res = await this.$refs.pay.getRefund({
+					out_trade_no: this.out_trade_no, // 插件支付单号
+				});
+				if (res) {
+					uni.showModal({
+						content: res.errMsg,
+						showCancel: false
+					});
+				}
+			},
+			// 关闭订单
+			async closeOrder() {
+				let res = await this.$refs.pay.closeOrder({
+					out_trade_no: this.out_trade_no, // 插件支付单号
+				});
+				if (res) {
+					uni.showModal({
+						content: res.errMsg,
+						showCancel: false
+					});
+				}
+			},
+			// 获取公众号code
+			async getWeiXinJsCode(scope="snsapi_base") {
+				let res = await this.$refs.pay.getProviderAppId({
+					provider: "wxpay",
+					provider_pay_type: "jsapi"
+				});
+				if (res.appid) {
+					let appid = res.appid;
+					let redirect_uri = window.location.href.split("?")[0];
+					let url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${redirect_uri}&response_type=code&scope=${scope}&state=STATE#wechat_redirect`;
+					window.location.href = url;
+				}
+			},
+			// 获取公众号openid
+			async getOpenid(data={}) {
+				let res = await this.$refs.pay.getOpenid(data);
+				if (res) {
+					this.openid = res.openid;
+					// 将openid缓存到本地
+					uni.setStorageSync("uni-pay-weixin-h5-openid", this.openid);
+					uni.setStorageSync("uni-pay-weixin-h5-code", data.code);
+					uni.showToast({
+						title: "已获取到openid,可以开始支付",
+						icon: "none"
+					});
+				}
+			},
+			// 监听事件 - 支付订单创建成功(此时用户还未支付)
+			onCreate(res){
+				console.log('create: ', res);
+				// 如果只是想生成支付二维码,不需要组件自带的弹窗,则在这里可以获取到支付二维码 qr_code_image
+			},
+			// 监听事件 - 支付成功
+			onSuccess(res){
+				console.log('success: ', res);
+				if (res.user_order_success) {
+					// 代表用户已付款,且你自己写的回调成功并正确执行了
+					
+				} else {
+					// 代表用户已付款,但你自己写的回调执行失败(通常是因为你的回调代码有问题)
+	
+				}
+			},
+			onFail(err){
+				console.log('err: ', err)
+				
+			},
+			pageTo(url){
+				uni.navigateTo({
+					url
+				});
+			},
+			providerFormat(provider){
+				let providerObj = {
+					"wxpay":"微信支付",
+					"alipay":"支付宝支付",
+					"appleiap":"ios内购"
+				};
+				let providerStr = providerObj[provider] || "未知";
+				return providerStr;
+			},
+			/**
+			 * 日期格式化
+			 * @params {Date || Number} date 需要格式化的时间
+			 * timeFormat(new Date(),"yyyy-MM-dd hh:mm:ss");
+			 */
+			timeFormat(time, fmt = 'yyyy-MM-dd hh:mm:ss', targetTimezone = 8){
+				try {
+					if (!time) {
+						return "";
+					}
+					if (typeof time === "string" && !isNaN(time)) time = Number(time);
+					// 其他更多是格式化有如下:
+					// yyyy-MM-dd hh:mm:ss|yyyy年MM月dd日 hh时MM分等,可自定义组合
+					let date;
+					if (typeof time === "number") {
+						if (time.toString().length == 10) time *= 1000;
+						date = new Date(time);
+					} else {
+						date = time;
+					}
+							
+					const dif = date.getTimezoneOffset();
+					const timeDif = dif * 60 * 1000 + (targetTimezone * 60 * 60 * 1000);
+					const east8time = date.getTime() + timeDif;
+							
+					date = new Date(east8time);
+					let opt = {
+						"M+": date.getMonth() + 1, //月份
+						"d+": date.getDate(), //日
+						"h+": date.getHours(), //小时
+						"m+": date.getMinutes(), //分
+						"s+": date.getSeconds(), //秒
+						"q+": Math.floor((date.getMonth() + 3) / 3), //季度
+						"S": date.getMilliseconds() //毫秒
+					};
+					if (/(y+)/.test(fmt)) {
+						fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
+					}
+					for (let k in opt) {
+						if (new RegExp("(" + k + ")").test(fmt)) {
+							fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (opt[k]) : (("00" + opt[k]).substr(("" + opt[k]).length)));
+						}
+					}
+					return fmt;
+				} catch (err) {
+					// 若格式错误,则原值显示
+					return time;
+				}
+			},
+		}, 
+		computed: {
+			h5Env(){
+				// #ifdef H5
+				let ua = window.navigator.userAgent.toLowerCase();
+				if (ua.match(/MicroMessenger/i) == 'micromessenger' && (ua.match(/miniprogram/i) == 'miniprogram')) {
+					// 微信小程序
+					return "mp-weixin";
+				}
+				if (ua.match(/MicroMessenger/i) == 'micromessenger') {
+					// 微信公众号
+					return "h5-weixin";
+				}
+				if (ua.match(/alipay/i) == 'alipay' && ua.match(/miniprogram/i) == 'miniprogram') {
+					return "mp-alipay";
+				}
+				if (ua.match(/alipay/i) == 'alipay') {
+					return "h5-alipay";
+				}
+				// 外部 H5
+				return "h5";
+				// #endif
+			},
+			// 计算当前是否是ios app
+			isIosAppCom(){
+				let info = uni.getSystemInfoSync();
+				return info.uniPlatform === 'app' && info.osName === 'ios' ? true : false;
+			},
+			// 计算当前是否是PC环境
+			isPcCom(){
+				// #ifdef H5
+				let info = uni.getSystemInfoSync();
+				return info.deviceType === 'pc' ? true : false;
+				// #endif
+				return false;
+			}
+		},
+	}
+</script>
+
+<style lang="scss" scoped>
+	.app{
+		padding: 30rpx;
+	}
+	input {
+		border: 1px solid #f3f3f3;
+		padding: 10rpx;
+		width: 100%;
+		box-sizing: border-box;
+		height: 80rpx;
+	}
+
+	button {
+		margin-top: 20rpx;
+	}
+	
+	.label{
+		margin: 10rpx 0;
+	}
+	
+	.tips{
+		margin-top: 20rpx;
+		font-size: 24rpx;
+		color: #565656;
+	}
+	
+	.get-order-popup{
+		background-color: #ffffff;
+		padding: 30rpx;
+		height: 60vh;
+		border-radius: 30rpx 30rpx 0 0;
+		overflow: hidden;
+	}
+	.mt20{
+		margin-top: 20rpx;
+	}
+	
+	.pd2030{
+		padding: 20rpx 30rpx;
+	}
+	
+	.table{
+		font-size: 24rpx;
+	}
+	.align-left{
+		text-align: left;
+		width: 50%;
+	}
+	.align-right{
+		text-align: right;
+		width: 50%;
+	}
+	
+	
+</style>

+ 209 - 0
pages/wallet/wallet.vue

@@ -0,0 +1,209 @@
+<template>
+	<view>
+		<view class="my_top">
+			<image src="../../static/images/top-bg.png" class="bg"></image>
+		</view>
+		<view class="list animated fadeInDown">
+			<view class="uni-flex uni-row center">
+				<view class="wallet">
+					<text>我的服务点数</text>
+					<text class="num">{{ user.wallet }}</text>					
+				</view>
+			</view>
+		</view>
+		<view class="uni-flex uni-row" style="padding:1rem; ">
+			<button type="primary" style="-webkit-flex: 1;flex: 1;" @click="goto('/pages/wallet/topup/edit')">充值</button>
+			<view class="text" style="width: 15rpx;"></view>
+			<button type="default" style="-webkit-flex: 1;flex: 1;" @click="goto('/pages/wallet/topdown/edit')">提现</button>
+		</view>
+		<view class="tab">
+			<u-tabs :list="tab" @click="click" :lineHeight="5"></u-tabs>
+		</view>
+		<view class="goodsList">
+			<view class="item" v-for="(item, index) in list" :key="index" @click="detail(item)">	
+				<view class="title">{{ item.tagTypeName }}
+					<view class="state" v-if="item.tagType == 1 ">
+						<text class="icon" style="color:#13ce66">&#xe830;</text>
+						<text>+{{ item.amount }}</text>
+					</view>
+					<view class="state" v-if="item.tagType == 2 ">
+						<text class="icon" style="color:#FF2222">&#xe830;</text>
+						<text>-{{ item.amount }}</text>
+					</view>
+					<view class="state" v-if="item.tagType == 3 ">
+						<text class="icon" style="color:#CC8855">&#xe830;</text>
+						<text>-{{ item.amount }}</text>
+					</view>
+				</view>
+				<view class="op">					
+					<view class="date">{{ item.recordTime }}</view>
+				</view>
+			</view>
+			<view class="loading" v-if="loadMore"><u-loadmore :status="loadMore ? 'loading' : 'nomore'" /></view>
+			<u-empty v-if="!loadMore && list.length == 0"></u-empty>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				user: {},
+				tab: [{
+						name: '全部',
+						tagType: ''
+					},
+					{
+						name: '充值',
+						tagType: '1'
+					},
+					{
+						name: '提现',
+						tagType: '2'
+					},
+					{
+						name: '扣除',
+						tagType: '3'
+					}
+				],
+				param: {
+					pageNo: 1,
+					pageSize: 10,
+					tagType:''
+				},
+				list: [],
+				loadMore: true,
+			};
+		},
+		onLoad() {
+			this.user = this.getUser()
+		},
+		onShow() {
+			this.user = this.getUser();
+			this.getData();
+		},
+		methods: {
+			getData() {
+				this.param.peopleId = this.user.fkId;
+				this.http.request({
+					url: '/level-one-server/app/WalletManage/getList',
+					loading: 'false',
+					data: this.param,
+					success: res => {
+						this.loadMore = parseInt(res.data.pageCount) > this.param.pageNo;
+						if (res.data.data) {
+							this.list = res.data.data;
+						}
+					}
+				});
+			},
+			// 点击tab切换
+			click(e) {
+				this.param.tagType = e.tagType;
+				this.refresh()
+			},
+			detail(item) {
+				let urlStr=''
+				if(item.tagType==1){
+					urlStr='/pages/wallet/topup/detail?id='
+				}
+				if(item.tagType==2){
+					urlStr='/pages/wallet/topdown/detail?id='
+				}
+				if(item.tagType==3){
+					urlStr='/pages/wallet/detail?id='
+				}
+				uni.navigateTo({
+					url: urlStr + item.id
+				});
+			},
+			goto(url) {
+				uni.navigateTo({ url: url });
+			},
+			// 刷新数据
+			refresh() {
+				this.loadMore = true;
+				this.param.pageNo = 1;
+				this.list = [];
+				this.getData();
+			}
+		},
+		//下拉刷新
+		onPullDownRefresh() {
+			setTimeout(() => {
+				this.refresh();
+				uni.stopPullDownRefresh();
+			}, 1000);
+		},
+		//上拉加载
+		onReachBottom() {
+			if (this.loadMore) {
+				this.param.pageNo++;
+				this.getData();
+			}
+		}
+	};
+</script>
+
+<style lang="scss">
+	page {
+		background-color: #f5f5f5;
+	}
+	.my_top {
+		position: relative;
+		overflow: hidden;
+		image {
+			width: 100%;
+		}
+	}
+	.uni-flex {
+		display: flex;
+		flex-direction: row;
+	}
+	.uni-flex-item {
+		flex: 1;
+	}
+	.uni-row {
+		flex-direction: row;
+	}
+	.list {
+		position: relative;
+		padding: 0px 20px 10px 20px;
+		margin-top: -226px;
+		.center{
+			-webkit-justify-content: center;
+			justify-content: center;
+			text-align: center;
+			.wallet {
+				display: flex;
+				flex-direction: column;
+				background-color: white;
+				width: 15rem;
+				height: 7rem;
+				border-radius: 50%;
+				.num {
+					color: #0000CC;
+					font-size: 43px;					
+				}
+			}
+			.rbtn {			
+				padding-left: 15px;
+				width: 60%;
+			}
+		}
+	}
+	.state {
+		margin-right: -70px;
+	}
+
+	.down_btn {
+		color: #f0f4f7;
+		width: 100px;
+		background: #f9ae3d;
+		text-align: center;
+		border-radius: 10px;
+		font-size: 12px;
+		padding: 2px 5px;
+	}
+</style>