Jelajahi Sumber

热水表功能已基本完成,充值有待完成

程志平 5 tahun lalu
induk
melakukan
3f4e6af277

+ 11 - 0
.hbuilderx/launch.json

@@ -0,0 +1,11 @@
+{ // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
+  // launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数
+    "version": "0.0",
+    "configurations": [{
+            "type": "uniCloud",
+            "default": {
+                "launchtype": "remote"
+            }
+        }
+    ]
+}

+ 87 - 0
App.vue

@@ -0,0 +1,87 @@
+<script>
+	export default {
+		onLaunch: function() {
+			// console.log('App Launch')
+		},
+		onShow: function() {
+			// console.log('App Show')
+		},
+		onHide: function() {
+			// console.log('App Hide')
+		}
+	}
+</script>
+
+<style>
+	/*每个页面公共css */
+	@font-face {
+	  font-family: "iconfont"; /* Project id 2649342 */
+	  src: url('//at.alicdn.com/t/font_2649342_4vjqgtg661.woff2?t=1625907458371') format('woff2'),
+	       url('//at.alicdn.com/t/font_2649342_4vjqgtg661.woff?t=1625907458371') format('woff'),
+	       url('//at.alicdn.com/t/font_2649342_4vjqgtg661.ttf?t=1625907458371') format('truetype');
+	}
+	
+	.iconfont {
+	  font-family: "iconfont" !important;
+	  font-size: 16px;
+	  font-style: normal;
+	  -webkit-font-smoothing: antialiased;
+	  -moz-osx-font-smoothing: grayscale;
+	}
+	
+	.icon-zhongzhi:before {
+	  content: "\e60a";
+	}
+	
+	.icon-dayuhao:before {
+	  content: "\e60c";
+	}
+	
+	.icon-shuibiao:before {
+	  content: "\e65c";
+	}
+	
+	.icon-shuidi:before {
+	  content: "\ea2b";
+	}
+	
+	.icon-shijian:before {
+	  content: "\e61b";
+	}
+	
+	.icon-goux:before {
+	  content: "\e60b";
+	}
+	
+	.icon-shuzi4:before {
+	  content: "\e6fc";
+	}
+	
+	.icon-shuzi1:before {
+	  content: "\e603";
+	}
+	
+	.icon-shuzi3:before {
+	  content: "\e604";
+	}
+	
+	.icon-shuzi2:before {
+	  content: "\e605";
+	}
+	
+	.icon-saoma:before {
+	  content: "\e74c";
+	}
+	
+	.icon-zhuye:before {
+	  content: "\e62f";
+	}
+	
+	.icon-arrow-down:before {
+	  content: "\e602";
+	}
+	
+	.icon-qian:before {
+	  content: "\e7a9";
+	}
+</style>

+ 100 - 0
components/instructions.vue

@@ -0,0 +1,100 @@
+<template>
+	<view class="content">
+		<view class="container">
+			<view class="item_warp">
+				<view class="title">
+					使用说明
+				</view>
+				<view class="item">
+					<view class="text">
+						1.点击"扫码连接",扫码水表上的二维码;
+					</view>
+					<view class="text">
+						2.水表连接成功后"开始使用"按钮;
+					</view>
+					<view class="text">
+						3.使用完成后点击"停止用水"即关闭热水;
+					</view>
+					<view class="text">
+						4.或者连接水表后直接在表上进行操作,如下图:
+					</view>
+					<view class="img">
+						<image class="img_scan" src="../static/images/qr-code.png" mode=""></image>
+					</view>
+					<view class="bot_text" @click="child_cancel">
+						我知道了
+					</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		methods: {
+			child_cancel() {
+				this.$emit('parent_cancel', false)
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.content {
+		width: 100%;
+		height: 100%;
+
+		.container {
+			width: 100%;
+			height: 100%;
+			position: fixed;
+			top: 0;
+			left: 0;
+			background: rgba(0, 0, 0, .4);
+
+			.item_warp {
+				width: 650rpx;
+				position: absolute;
+				top: 50%;
+				left: 50%;
+				transform: translate(-50%, -50%);
+				padding: 40rpx 50rpx;
+				box-sizing: border-box;
+				background: #fff;
+				border-radius: 10rpx;
+
+				.title {
+					font-size: 32rpx;
+					color: #000;
+					font-weight: bold;
+					text-align: center;
+					margin-bottom: 30rpx;
+				}
+
+				.text {
+					font-size: 32rpx;
+					color: #333;
+					line-height: 40rpx;
+					margin-bottom: 20rpx;
+				}
+
+				.img {
+					text-align: center;
+					margin: 30rpx 0;
+
+					.img_scan {
+						width: 300rpx;
+						height: 200rpx;
+					}
+				}
+
+				.bot_text {
+					color: $my-color-primary;
+					font-size: 32rpx;
+					text-align: center;
+				}
+			}
+		}
+	}
+</style>

+ 251 - 0
components/uni-steps/uni-steps.vue

@@ -0,0 +1,251 @@
+<template>
+	<view class="uni-steps">
+		<view :class="[direction==='column'?'uni-steps__column':'uni-steps__row']">
+			<view :class="[direction==='column'?'uni-steps__column-text-container':'uni-steps__row-text-container']">
+				<view v-for="(item,index) in options" :key="index" :class="[direction==='column'?'uni-steps__column-text':'uni-steps__row-text']">
+					<text :style="{color:index<=active?activeColor:deactiveColor}" :class="[direction==='column'?'uni-steps__column-title':'uni-steps__row-title']">{{item.title}}</text>
+					<text :style="{color:index<=active?activeColor:deactiveColor}" :class="[direction==='column'?'uni-steps__column-desc':'uni-steps__row-desc']">{{item.desc}}</text>
+				</view>
+			</view>
+			<view :class="[direction==='column'?'uni-steps__column-container':'uni-steps__row-container']">
+				<view :class="[direction==='column'?'uni-steps__column-line-item':'uni-steps__row-line-item']" v-for="(item,index) in options" :key="index">
+					<view :class="[direction==='column'?'uni-steps__column-line':'uni-steps__row-line',direction==='column'?'uni-steps__column-line--before':'uni-steps__row-line--before']" :style="{backgroundColor:index<=active&&index!==0?activeColor:index===0?'transparent':deactiveColor}"></view>
+					<view :class="[direction==='column'?'uni-steps__column-check':'uni-steps__row-check']" v-if="index === active">
+						<!-- <uni-icons :color="activeColor" type="checkbox-filled" size="14"></uni-icons> -->
+						<uni-icons :color="activeColor" class="iconfont icon-goux" size="14"></uni-icons>
+					</view>
+					<view :class="[direction==='column'?'uni-steps__column-circle':'uni-steps__row-circle']" v-else :style="{backgroundColor:index<active?activeColor:deactiveColor}"></view>
+					<view :class="[direction==='column'?'uni-steps__column-line':'uni-steps__row-line',direction==='column'?'uni-steps__column-line--after':'uni-steps__row-line--after']" :style="{backgroundColor:index<active&&index!==options.length-1?activeColor:index===options.length-1?'transparent':deactiveColor}"></view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	/**
+	 * Steps 步骤条
+	 * @description 评分组件
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=34
+	 * @property {Number} active 当前步骤
+	 * @property {String} direction = [row|column] 当前步骤
+	 * 	@value row 横向
+	 * 	@value column 纵向
+	 * @property {String} activeColor 选中状态的颜色
+	 * @property {Array} options 数据源,格式为:[{title:'xxx',desc:'xxx'},{title:'xxx',desc:'xxx'}]
+	 */
+
+	export default {
+		name: 'UniSteps',
+		props: {
+			direction: {
+				// 排列方向 row column
+				type: String,
+				default: 'row'
+			},
+			activeColor: {
+				// 激活状态颜色
+				type: String,
+				default: '#1aad19'
+			},
+			deactiveColor: {
+				// 未激活状态颜色
+				type: String,
+				default: '#999999'
+			},
+			active: {
+				// 当前步骤
+				type: Number,
+				default: 0
+			},
+			options: {
+				type: Array,
+				default () {
+					return []
+				}
+			} // 数据
+		},
+		data() {
+			return {}
+		}
+	}
+</script>
+
+<style scoped>
+	.uni-steps {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		width: 100%;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		flex: 1;
+		/* #endif */
+		flex-direction: column;
+	}
+
+	.uni-steps__row {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+	}
+
+	.uni-steps__column {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row-reverse;
+	}
+
+	.uni-steps__row-text-container {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: flex-end;
+		margin-bottom: 8px;
+	}
+
+	.uni-steps__column-text-container {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		flex: 1;
+	}
+
+	.uni-steps__row-text {
+		/* #ifndef APP-NVUE */
+		display: inline-flex;
+		/* #endif */
+		flex: 1;
+		flex-direction: column;
+	}
+
+	.uni-steps__column-text {
+		padding: 6px 0px;
+		border-bottom-style: solid;
+		border-bottom-width: 1px;
+		border-bottom-color: #e5e5e5;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+	}
+
+	.uni-steps__row-title {
+		font-size: 14px;
+		line-height: 16px;
+		text-align: center;
+	}
+
+	.uni-steps__column-title {
+		font-size: 14px;
+		text-align: left;
+		line-height: 18px;
+	}
+
+	.uni-steps__row-desc {
+		font-size: 12px;
+		line-height: 14px;
+		text-align: center;
+	}
+
+	.uni-steps__column-desc {
+		font-size: 12px;
+		text-align: left;
+		line-height: 18px;
+	}
+
+	.uni-steps__row-container {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+	}
+
+	.uni-steps__column-container {
+		/* #ifndef APP-NVUE */
+		display: inline-flex;
+		/* #endif */
+		width: 30px;
+		flex-direction: column;
+	}
+
+	.uni-steps__row-line-item {
+		/* #ifndef APP-NVUE */
+		display: inline-flex;
+		/* #endif */
+		flex-direction: row;
+		flex: 1;
+		height: 14px;
+		line-height: 14px;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.uni-steps__column-line-item {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		flex: 1;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.uni-steps__row-line {
+		flex: 1;
+		height: 1px;
+		background-color: #999;
+	}
+
+	.uni-steps__column-line {
+		width: 1px;
+		background-color: #999;
+	}
+
+	.uni-steps__row-line--after {
+		transform: translateX(1px);
+	}
+
+	.uni-steps__column-line--after {
+		flex: 1;
+		transform: translate(0px, 1px);
+	}
+
+	.uni-steps__row-line--before {
+		transform: translateX(-1px);
+	}
+
+	.uni-steps__column-line--before {
+		height: 6px;
+		transform: translate(0px, -1px);
+	}
+
+	.uni-steps__row-circle {
+		width: 5px;
+		height: 5px;
+		border-radius: 100px;
+		background-color: #999;
+		margin: 0px 3px;
+	}
+
+	.uni-steps__column-circle {
+		width: 5px;
+		height: 5px;
+		border-radius: 100px;
+		background-color: #999;
+		margin: 4px 0px 5px 0px;
+	}
+
+	.uni-steps__row-check {
+		margin: 0px 6px;
+	}
+
+	.uni-steps__column-check {
+		height: 14px;
+		line-height: 14px;
+		margin: 2px 0px;
+	}
+</style>

+ 17 - 0
main.js

@@ -0,0 +1,17 @@
+import Vue from 'vue'
+import App from './App'
+import {myRequest} from './static/api.js'
+
+Vue.prototype.$myRequest = myRequest
+
+// import {common} from './static/common.js'
+// Vue.prototype.$request = common.axios
+
+Vue.config.productionTip = false
+
+App.mpType = 'app'
+
+const app = new Vue({
+	...App
+})
+app.$mount()

+ 78 - 0
manifest.json

@@ -0,0 +1,78 @@
+{
+	"name": "ceshi",
+	"appid": "__UNI__D7AE6E0",
+	"description": "",
+	"versionName": "1.0.0",
+	"versionCode": "100",
+	"transformPx": false,
+	/* 5+App特有相关 */
+	"app-plus": {
+		"usingComponents": true,
+		"nvueStyleCompiler": "uni-app",
+		"compilerVersion": 3,
+		"splashscreen": {
+			"alwaysShowBeforeRender": true,
+			"waiting": true,
+			"autoclose": true,
+			"delay": 0
+		},
+		/* 模块配置 */
+		"modules": {},
+		/* 应用发布信息 */
+		"distribute": {
+			/* android打包配置 */
+			"android": {
+				"permissions": [
+					"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+					"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+					"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+					"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
+					"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+					"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
+					"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+					"<uses-permission android:name=\"android.permission.CAMERA\"/>",
+					"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
+					"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+					"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+					"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+					"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+					"<uses-feature android:name=\"android.hardware.camera\"/>",
+					"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
+				]
+			},
+			/* ios打包配置 */
+			"ios": {},
+			/* SDK配置 */
+			"sdkConfigs": {}
+		}
+	},
+	/* 快应用特有相关 */
+	"quickapp": {},
+	/* 小程序特有相关 */
+	"mp-weixin": {
+		"appid": "wx2fc3f45732fae5d3",
+		"setting": {
+			"urlCheck": false
+		},
+		"usingComponents": true,
+		"plugins": {
+			"myPlugin": {
+				"provider": "wx1549b963bbae9931",
+				"version": "4.0.0"
+			}
+		},
+		"permission": {}
+	},
+	"mp-alipay": {
+		"usingComponents": true
+	},
+	"mp-baidu": {
+		"usingComponents": true
+	},
+	"mp-toutiao": {
+		"usingComponents": true
+	},
+	"uniStatistics": {
+		"enable": false
+	}
+}

+ 35 - 0
pages.json

@@ -0,0 +1,35 @@
+{
+	"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
+		{
+			"path": "pages/index/index",
+			"style": {
+				"navigationBarTitleText": "校园",
+				"enablePullDownRefresh": false
+			}
+
+		},
+		{
+			"path": "pages/reshui/reshui",
+			"style": {
+				"navigationBarTitleText": "热水",
+				"enablePullDownRefresh": false
+			}
+		},
+		{
+			"path": "pages/recharge/recharge",
+			"style": {
+				"navigationBarTitleText": "钱包充值",
+				"enablePullDownRefresh": false
+			}
+		}
+	],
+	"globalStyle": {
+		"navigationBarTextStyle": "black",
+		"navigationBarTitleText": "uni-app",
+		"navigationBarBackgroundColor": "#fff",
+		"backgroundColor": "#fff",
+		"usingComponents": {
+			"login": "plugin://myPlugin/login"
+		}
+	}
+}

+ 355 - 0
pages/index/index.vue

@@ -0,0 +1,355 @@
+<template>
+	<view class="container">
+		<view class="banner">
+			<image src="../../static/images/banner2x.png" mode=""></image>
+		</view>
+		<view class="nav">
+			<view class="menu" v-show="my_display">
+				<navigator :url="'/pages/reshui/reshui?item=' + encodeURIComponent(JSON.stringify(this.userinfo))"
+					open-type="redirect" class="menu_item">
+					<image src="../../static/images/shower2x.png" mode=""></image>
+					<text>洗 浴</text>
+				</navigator>
+				<navigator url="" open-type="redirect" class="menu_item">
+					<image src="../../static/images/recharge2x.png" mode=""></image>
+					<text>电费充值</text>
+				</navigator>
+			</view>
+			<view class="reset">
+				<navigator url="" open-type="redirect" @click="reauthorization()" class="menu_item">
+					<text class="iconfont icon-zhongzhi"></text>
+					<text>重新授权</text>
+				</navigator>
+			</view>
+		</view>
+		<view v-if="showLogin">
+			<login :ocode="ocode" :appkey="appkey" scope="snsapi_userinfo" :visible="visible" @success="callback()"
+				@cancel="callback()" @fail="callback()" />
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				visible: false,
+				showLogin: true,
+				appkey: '5AA49F3E4CACA380',
+				sub_appid: '1015730314_1941301045',
+				appid: 'wx2fc3f45732fae5d3', // 获取用户信息
+				ocode: '1015730314', // 获取用户信息
+				app_secret: '58D34C81D82B35179ED896C4362B0FC0', // 获取用户信息
+				// 用于传给后代页面
+				appid_pass: 'wxd6f090391d410534', // 传给后代页面,用于唤起支付
+				ocode_pass: '1609853253', // 传给后代页面,用于唤起支付
+				app_secret_pass: 'eb99fffa11caa585fcf7c97c891a5e1f', // 传给后代页面,用于唤起支付
+				wxcode: '',
+				access_token: '',
+				access_token_for_amount: '', // 获取到应用有效凭证
+				refresh_token: '',
+				my_display: false,
+				userinfo: {},
+				amount: 0.00
+			}
+		},
+		onLoad() {
+			try {
+				const value = uni.getStorageSync('userinfo_storage_key');
+				if (value == '') {
+					if (JSON.stringify(this.userinfo) == '{}') {
+						this.showLogin = true
+						this.visible = true
+					} else {
+						this.showLogin = false
+						this.my_display = true
+					}
+				} else {
+					this.showLogin = false
+					this.userinfo = value
+					this.my_display = true
+				}
+
+				// 获取应用有效凭证,并查询余额
+				this.get_valid_credentials()
+
+			} catch (e) {
+				// console.log(e)
+				uni.showToast({
+					icon: 'success',
+					title: '用户获取失败',
+					duration: 2000
+				})
+			}
+		},
+		methods: {
+			/**
+			 * 重新授权
+			 */
+			reauthorization() {
+				try {
+					uni.removeStorageSync('userinfo_storage_key');
+					setTimeout(() => {
+						this.showLogin = false
+						this.userinfo = {}
+						this.my_display = false
+					}, 300)
+
+					setTimeout(() => {
+						this.showLogin = true
+						this.visible = true
+					}, 300)
+				} catch (e) {
+					console.log(e)
+				}
+			},
+
+			/**
+			 * 授权回调
+			 */
+			callback: function({
+				detail
+			}) {
+				// console.log(detail)
+				// {wxcode: "7f7Qi9rN8zQ1nifQiysTZ3WIeIWlgcGk"}
+				if (detail === undefined) {
+					this.userinfo = {};
+					uni.showToast({
+						icon: 'success',
+						title: '需要先授权'
+					});
+				} else {
+					const {
+						wxcode = ""
+					} = detail
+					
+					if (wxcode.length == 0) {
+						uni.showToast({
+							title: '未获得wxcode',
+							duration: 500
+						})
+					} else {
+						// 获取wxcode
+						this.wxcode = wxcode
+
+						// 通过wxcode换取access_token
+						this.get_access_token()
+					}
+				}
+			},
+
+			/**
+			 * 通过wxcode换取access_token
+			 */
+			async get_access_token() {
+				const res = await this.$myRequest({
+					host: 'wecard',
+					url: '/connect/oauth2/token',
+					method: 'POST',
+					header: {
+						'content-type': 'application/json'
+					},
+					data: {
+						'wxcode': this.wxcode,
+						'app_key': this.appkey,
+						'app_secret': this.app_secret,
+						'grant_type': 'authorization_code',
+						'redirect_uri': 'mnp://wx2fc3f45732fae5d3'
+					}
+				})
+
+				if (res.data.refresh_token == '' || res.data.refresh_token == 'undefined') {
+					uni.showToast({
+						title: '未获得token'
+					});
+				} else {
+					this.access_token = res.data.access_token;
+					this.refresh_token = res.data.refresh_token;
+
+					// 通过access_token换取用户信息
+					this.get_user_info();
+				}
+			},
+
+			/**
+			 * 通过access_token换取用户信息
+			 */
+			async get_user_info() {
+				const res = await this.$myRequest({
+					host: 'wecard',
+					url: '/connect/oauth/get-user-info',
+					method: 'POST',
+					header: {
+						'content-type': 'application/json'
+					},
+					data: {
+						"access_token": this.access_token
+					}
+				});
+
+				if (res.data.errcode == 0 && res.data.errmsg == 'OK') {
+					try {
+						this.userinfo = res.data
+						this.userinfo.amount = this.amount
+						// 微校参数
+						this.userinfo.appkey = this.appkey
+						this.userinfo.sub_appid = this.sub_appid
+						this.userinfo.appid = this.appid_pass
+						this.userinfo.app_secret = this.app_secret_pass
+						this.userinfo.ocode = this.ocode_pass
+						// 存储用户信息
+						uni.setStorageSync('userinfo_storage_key', this.userinfo)
+						// 提示授权成功
+						uni.showToast({
+							icon: 'success',
+							title: '授权成功',
+							duration: 800,
+							success: (res) => {
+								this.my_display = true
+							}
+						})
+					} catch (e) {
+						console.log(e)
+					}
+				} else {
+					uni.showToast({
+						title: '未获得用户信息',
+						duration: 1000
+					});
+				}
+			},
+
+			/**
+			 * 获取应用有效凭证
+			 */
+			async get_valid_credentials() {
+				const res = await this.$myRequest({
+					host: 'wecard',
+					url: '/cgi-bin/oauth2/token',
+					method: 'POST',
+					header: {
+						'content-type': 'application/json'
+					},
+					data: {
+						'app_key': this.appkey,
+						'app_secret': this.app_secret,
+						"grant_type": "client_credentials",
+						"scope": "base",
+						"ocode": this.ocode
+					}
+				});
+
+				if (typeof(res.data.access_token) != 'undefined') {
+					// 获取到应用有效凭证,保存到页面变量中
+					this.access_token_for_amount = res.data.access_token
+					// 用户充值钱包余额查询
+					this.request_user_amount()
+
+				} else {
+					uni.showToast({
+						title: '获取凭证失败',
+						duration: 2000
+					})
+				}
+			},
+
+			/**
+			 * 用户充值钱包余额查询
+			 */
+			async request_user_amount() {
+				const res = await this.$myRequest({
+					host: 'wecard',
+					url: "/cgi-bin/pay/app/wallet-recharge-balance?access_token=" + this
+						.access_token_for_amount + "&sub_appid=" + this.sub_appid + "&user_id=" + this
+						.userinfo.card_number
+				});
+
+				if (res.data.code === 0) {
+					// 用户余额保存到页面变量中
+					this.amount = res.data.data.amount;
+				} else {
+					uni.showToast({
+						icon: 'none',
+						title: '余额查询失败:\n' + res.data.message,
+						duration: 2000
+					})
+				}
+			}
+		}
+	}
+</script>
+
+<style scoped lang="scss">
+	.container {
+		display: flex;
+		flex-direction: column;
+		width: 750rpx;
+		font-family: Microsoft YaHei-3970(82674968);
+		color: #333333;
+
+		.banner {
+			width: 100%;
+			height: 360rpx;
+
+			image {
+				width: 100%;
+				height: 100%;
+			}
+		}
+
+		.nav {
+			position: relative;
+			width: 100%;
+
+			.menu,
+			.reset {
+				margin: 25rpx auto;
+				width: 640rpx;
+			}
+
+			.menu_item {
+				display: inline-flex;
+				flex-direction: column;
+				text-align: center;
+				width: 25%;
+				padding: 30rpx 0 39rpx;
+				border-radius: 20rpx;
+				font-family: Microsoft YaHei-3970(82674968);
+				color: #333333;
+
+				image {
+					width: 90rpx;
+					height: 90rpx;
+					margin: 0 auto;
+				}
+
+				text {
+					height: 29rpx;
+					line-height: 54rpx;
+					font-size: 30rpx;
+					color: #333333;
+				}
+			}
+
+			.reset {
+				position: fixed;
+				display: flex;
+				flex-direction: column;
+				align-items: flex-end;
+				right: 55rpx;
+				bottom: 55rpx;
+				font-family: Microsoft YaHei-3970(82674968);
+				color: #333333;
+
+				.icon-zhongzhi {
+					margin: 0 auto;
+					padding-top: 20rpx;
+					color: $my-color-primary;
+					width: 90rpx;
+					height: 70rpx;
+					font-size: 80rpx;
+				}
+			}
+		}
+	}
+</style>

+ 441 - 0
pages/recharge/recharge.vue

@@ -0,0 +1,441 @@
+<template>
+	<view class="content">
+		<view class="title">
+			<text class="iconfont icon-qian"></text>
+			<text>江西南昌交通学院</text>
+		</view>
+		<view class="input_amount">
+			<view class="amount_tip">充值金额(元)</view>
+			<view class="amount_inp">
+				<text></text>
+				<input type="number" maxlength="3" v-model="amount" @input="onInput" @blur="onBlur"
+					placeholder="请输入大于10,小于100元" placeholder-class="ph_class" />
+			</view>
+			<text>最多可输入金额100元</text>
+		</view>
+		<view class="amount_select">
+			<view class="amount_btn">
+				<text @tap="sel_amount(10)" :class="{selStyle:amount == 10}">充10元</text>
+				<text @tap="sel_amount(20)" :class="{selStyle:amount == 20}">充20元</text>
+				<text @tap="sel_amount(50)" :class="{selStyle:amount == 50}">充50元</text>
+				<text @tap="sel_amount(100)" :class="{selStyle:amount == 100}">充100元</text>
+			</view>
+			<view class="reminder">温馨提示:最少充值金额为10元</view>
+			<view class="payment">支付金额:<text>{{amount}}</text>元</view>
+			<button class="btn_submit" type="primary" @tap="chongzhi">确认提交</button>
+			<button class="btn_tel" type="default" @tap="callPhone">客服热线:{{phone_number}}</button>
+			<view class="tips">
+				尊敬的用户,你好!因项目提现业务配置问题导致您无法提现对此,我们深表歉意!您可致电运营商处理提现问题,运营商电话:13645689854。感谢您对我们工作的支持和理解。
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				amount: 10.0.toFixed(0), // 金额
+				phone_number: '13645689854', // 客户热线电话
+				userinfo: '', // 用户信息
+				order_id: '', // 订单号
+				pay_info: '', // 支付参数。将此参数透传给支付 SDK 发起支付
+				access_token: ''
+			};
+		},
+		onLoad(options) {
+			try {
+				// 获取存储的用户数据
+				const value = uni.getStorageSync('userinfo_storage_key')
+				let item = decodeURIComponent(options.item)
+				if (item === '{}' && value == '') { // 如果没有用户信息,返回首页
+					uni.redirectTo({
+						url: '../index/index'
+					});
+					return;
+				}
+
+				if (item != '') {
+					// 处理JSON字符串
+					// this.userinfo = item.replace(/"/g, "'");
+					this.userinfo = JSON.parse(item);
+				} else if (value != '') {
+					// 处理JSON字符串
+					// this.userinfo = value.replace(/"/g, "'");
+					this.userinfo = value;
+				}
+			} catch (e) {
+				console.log(e)
+			}
+
+			// 获取应用有效凭证
+			this.get_valid_credentials()
+		},
+		methods: {
+			/**
+			 * 获取应用有效凭证
+			 */
+			async get_valid_credentials() {
+				const res = await this.$myRequest({
+					host: 'wecard',
+					url: '/cgi-bin/oauth2/token',
+					method: 'POST',
+					header: {
+						'content-type': 'application/json'
+					},
+					data: {
+						'app_key': this.userinfo.appkey,
+						'app_secret': this.userinfo.app_secret,
+						'grant_type': 'client_credentials',
+						'scope': 'base',
+						'ocode': this.userinfo.ocode
+					}
+				});
+
+				if (typeof(res.data.access_token) != 'undefined') {
+					// 获取到应用有效凭证,保存到页面变量中
+					// this.access_token = res.data.access_token
+					this.access_token = this.userinfo.access_token
+				} else {
+					uni.showToast({
+						title: '获取凭证失败',
+						duration: 2000
+					})
+				}
+			},
+			/**
+			 * 输入充值金额
+			 */
+			onInput(e) {
+				const v = e.detail.value
+				this.amount = 10
+
+				const zero = /^(0{1,})|[^0-9]/g
+				let final = 0
+				if (!v) {
+					final = 0
+				} else {
+					final = v.toString().replace(zero, (v) => {
+						return 0
+					})
+
+					if (final.split('')[0] * 1 === 0) {
+						final = final.slice(1) - 0 || 0
+					}
+
+					if (final > 100) {
+						final = 100
+					}
+				}
+				this.$nextTick(() => {
+					this.amount = final.toString() || '0'
+				})
+				// setTimeout(() => {
+				// 	this.amount = final.toString() || '0'
+				// }, 100)
+			},
+			onBlur() {
+				if (this.amount < 10) {
+					this.amount = 10
+				}
+			},
+			/**
+			 * 选择充值金额
+			 */
+			sel_amount(m) {
+				this.amount = m
+			},
+			/**
+			 * 调用接口实现充值功能
+			 */
+			chongzhi() {
+				if (this.amount < 10 || this.amount > 100) {
+					uni.showToast({
+						icon: 'none',
+						title: '最少充值10元,最多充值100元!',
+						mask: true,
+						duration: 3000
+					})
+				} else {
+					uni.showModal({
+						title: '提示',
+						content: '您选择了充值:¥' + this.amount + ' 元',
+						cancelText: '算了',
+						confirmText: '充值',
+						success: (res) => {
+							if (res.confirm) {
+								// 组合地址,发起支付
+								this.jsapi()
+							} else if (res.cancel) {
+								console.log('用户点击取消');
+							}
+						}
+					})
+				}
+			},
+
+			/**
+			 * 组合地址,发起支付
+			 */
+			async jsapi() {
+				const res = await this.$myRequest({
+					host: 'wecard',
+					url: '/cgi-bin/pay/app/mppay',
+					method: 'POST',
+					header: {
+						'content-type': 'application/json'
+					},
+					data: {
+						'access_token': this.access_token,
+						'sub_appid': this.userinfo.sub_appid,
+						'user_id': this.userinfo.card_number,
+						'order_id': this.order_id = get_order_id(),
+						'amount': this.amount
+					}
+				})
+
+				console.log(res)
+				console.log(this.access_token)
+				console.log(this.userinfo.sub_appid)
+				console.log(this.userinfo.card_number)
+				console.log(this.order_id)
+				console.log(this.amount)
+				if (res.data.code == 0) {
+					this.pay_info = res.data.data.pay_info
+					// 发起支付
+					this.pay_amount()
+				} else {
+					uni.showToast({
+						icon: 'none',
+						title: res.data.message,
+						duration: 3000
+					})
+				}
+			},
+			// 调起支付
+			pay_amount() {
+				var OpenMidas = require("@/static/openMidas.js"); // 引入小程序目录下的SDK文件
+
+				// 设置支付配置
+				OpenMidas['OpenMidasConfig'] = {
+					apiCommonConf: {
+						version: "weixiao"
+					},
+					cgiDomain: {
+						// release: "midas.weixiao.qq.com/api", // 私有化参数联系微卡客服进行获取
+						test: "midas.weixiao.qq.com/api", // 私有化参数联系微卡客服进行获取
+					},
+					webDomain: "https://midas.weixiao.qq.com/h5", // 私有化参数联系微卡客服进行获取
+					sandboxWebDomain: "https://midas.weixiao.qq.com/h5" // 私有化参数联系微卡客服进行获取
+				}
+
+				var payInfo = this.pay_info; // 请求mppay接口返回的数据
+				var appMetaData = "app=test&version=1.1"; // 自定义回调数据
+
+				// OpenMidas.init("release");
+				OpenMidas.init("test");
+				OpenMidas.pay(
+					payInfo,
+					function(resultCode, innerCode, resultMsg, appMetaData) {
+						console.log(resultCode); // 支付响应状态码
+						console.log(innerCode); // 支付响应内部错误码
+						console.log(resultMsg); // 支付响应说明
+						console.log(appMetaData); // 自定义回调数据
+
+						// todo:处理业务逻辑
+					},
+					appMetaData
+				);
+			},
+			/**
+			 * 拨打电话
+			 */
+			callPhone() {
+				uni.makePhoneCall({
+					phoneNumber: this.phone_number
+				});
+			}
+		}
+	}
+	/**
+	 * 时间生成订单号
+	 */
+	function get_order_id() {
+		const date = new Date()
+
+		let year = date.getFullYear()
+		let month = date.getMonth() + 1
+		let day = date.getDate()
+		let hour = date.getHours()
+		let minute = date.getMinutes()
+		let second = date.getSeconds()
+		let millisecond = date.getMilliseconds()
+
+		month = month > 9 ? month : '0' + month
+		day = day > 9 ? day : '0' + day
+		second = second > 9 ? second : '0' + second
+		// 小于4位数,前补0
+		// millisecond = millisecond < 1000 ? '00' + millisecond : millisecond
+		// 小于4位数,前补随机数
+		millisecond = millisecond < 1000 ? Math.floor(Math.random() * 999 + 1000) + millisecond : millisecond
+
+		return `${year}${month}${day}${hour}${minute}${second}${millisecond}`
+	}
+</script>
+
+<style lang="scss" scoped>
+	.content {
+		display: flex;
+		flex-direction: column;
+		background-color: #F5F5F5;
+		width: 750rpx;
+		// height: 100%;
+		// align-items: stretch;
+
+		.title {
+			display: flex;
+			align-items: center;
+			padding: 40rpx;
+
+			text:nth-child(1) {
+				color: $my-color-primary;
+				font-size: 50rpx;
+			}
+
+			text:nth-child(2) {
+				font-size: 32rpx;
+				margin-left: 15rpx;
+				font-family: Microsoft YaHei-3970(82674968);
+				color: #333333;
+			}
+		}
+
+		.input_amount {
+			background-color: #FFFFFF;
+			width: 670rpx;
+			height: 210rpx;
+			padding: 40rpx 40rpx 0 40rpx;
+			border-radius: 40rpx 40rpx 0 0;
+
+			.amount_tip {
+				font-size: 32rpx;
+				font-family: Microsoft YaHei-3970(82674968);
+			}
+
+			.amount_inp {
+				display: flex;
+				flex-direction: row;
+				border-bottom: 1px solid #cccccc;
+				margin-top: 20rpx;
+				margin-bottom: 10rpx;
+
+				text {
+					width: 50rpx;
+					height: 74rpx;
+					font-size: 50rpx;
+					font-weight: bold;
+					padding-top: 6rpx;
+					font-family: Microsoft YaHei-3970(82674968);
+				}
+
+				text::before {
+					content: '¥';
+				}
+
+				input {
+					width: 620rpx;
+					height: 80rpx;
+					font-size: 50rpx;
+					font-weight: bold;
+					font-family: Microsoft YaHei-3970(82674968);
+				}
+
+				/deep/.ph_class {
+					font-size: 28rpx;
+					font-weight: normal;
+				}
+			}
+
+			text {
+				font-size: 26rpx;
+				font-family: Microsoft YaHei-3970(82674968);
+				font-weight: 500;
+			}
+		}
+
+		.amount_select {
+			padding: 40rpx;
+
+			.amount_btn {
+				display: flex;
+				justify-content: space-between;
+				margin: 30rpx 0 20rpx;
+
+				text {
+					width: 150rpx;
+					height: 120rpx;
+					line-height: 120rpx;
+					font-size: 32rpx;
+					font-family: Microsoft YaHei-3970(82674968);
+					color: #333333;
+					text-align: center;
+					background: #FFFFFF;
+					border: 3rpx solid #AAAAAA;
+				}
+
+				.selStyle {
+					border: 0rpx;
+					width: 156rpx;
+					height: 126rpx;
+					background: url(../../static/images/jinebeijing2x.png) 0rpx 0rpx no-repeat;
+					background-size: 100%;
+				}
+			}
+
+			.reminder {
+				height: 26rpx;
+				font-size: 26rpx;
+				font-family: Microsoft YaHei-3970(82674968);
+				color: $my-color-primary;
+			}
+
+
+			.payment {
+				margin-top: 65rpx;
+				font-size: 32rpx;
+				font-family: Microsoft YaHei-3970(82674968);
+				color: #333333;
+
+				text {
+					color: $my-color-primary;
+				}
+			}
+
+			button {
+				margin-top: 38rpx;
+			}
+
+			.btn_submit {
+				border-radius: 10rpx;
+				background-color: $my-color-primary;
+				font-family: Microsoft YaHei-3970(82674968);
+				color: #FFFFFF;
+			}
+
+			.btn_tel {
+				border-radius: 10rpx;
+				background: #CCCCCC;
+				font-family: Microsoft YaHei-3970(82674968);
+				color: #FFFFFF;
+			}
+
+			.tips {
+				margin-top: 20rpx;
+				font-size: 24rpx;
+				font-family: Microsoft YaHei-3970(82674968);
+				color: $my-color-primary;
+				line-height: 36rpx;
+			}
+		}
+	}
+</style>

File diff ditekan karena terlalu besar
+ 1286 - 0
pages/reshui/reshui.vue


+ 46 - 0
static/api.js

@@ -0,0 +1,46 @@
+const WECARD_BASE_URL = 'https://open.wecard.qq.com' // wecard
+const MY_BASE_URL = 'http://demo.xwsyjjy.com' // my
+const CODE_BASE_URL = 'https://developdomain.chuanghai-tech.com' // code
+
+export const myRequest = (options) => {
+	
+	// 域名 或 url 为空,则不执行任何操作
+	if (options.host == '' || options.url == '') {
+		return
+	}
+
+	return new Promise((resolve, reject) => {
+		let BASE_URL = '';
+
+		if (options.host == 'wecard')
+			BASE_URL = WECARD_BASE_URL;
+		else if (options.host == 'my')
+			BASE_URL = MY_BASE_URL;
+		else if (options.host == 'code')
+			BASE_URL = CODE_BASE_URL;
+		else
+			return;
+
+		uni.request({
+			url: BASE_URL + options.url,
+			method: options.method || 'GET',
+			header: options.header || {},
+			data: options.data || {},
+			success: (res) => {
+				// console.log(res)
+				resolve(res)
+			},
+			fail: (err) => {
+				uni.showToast({
+					icon: 'none',
+					title: err.errMsg
+				})
+				reject(err)
+			}
+		})
+	}).catch(
+		err => {
+			console.log("catch " + err);
+		}
+	)
+}

+ 28 - 0
static/common.js

@@ -0,0 +1,28 @@
+export default {
+	axios({
+		url = '',
+		method = 'GET',
+		header = {},
+		data = {}
+	}) {
+		return new Promise((resovle, reject) => {
+			uni.showLoading({
+				title: '加载中',
+				mask: true
+			})
+			uni.request({
+				url: url,
+				method: method,
+				data: data,
+				header: header,
+				success(res) {
+					uni.hideLoading();
+					resovle(res)
+				},
+				fail(err) {
+					reject(err)
+				}
+			})
+		})
+	}
+}

TEMPAT SAMPAH
static/images/banner2x.png


TEMPAT SAMPAH
static/images/jinebeijing2x.png


TEMPAT SAMPAH
static/images/qr-code.png


TEMPAT SAMPAH
static/images/recharge2x.png


TEMPAT SAMPAH
static/images/shower2x.png


File diff ditekan karena terlalu besar
+ 2 - 0
static/openMidas.js


+ 77 - 0
uni.scss

@@ -0,0 +1,77 @@
+/**
+ * 这里是uni-app内置的常用样式变量
+ *
+ * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
+ * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
+ *
+ */
+
+/**
+ * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
+ *
+ * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
+ */
+
+/* 颜色变量 */
+$my-color-primary: #1296db;
+
+/* 行为相关颜色 */
+$uni-color-primary: #007aff;
+$uni-color-success: #4cd964;
+$uni-color-warning: #f0ad4e;
+$uni-color-error: #dd524d;
+
+/* 文字基本颜色 */
+$uni-text-color:#333;//基本色
+$uni-text-color-inverse:#fff;//反色
+$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
+$uni-text-color-placeholder: #808080;
+$uni-text-color-disable:#c0c0c0;
+
+/* 背景颜色 */
+$uni-bg-color:#ffffff;
+$uni-bg-color-grey:#f8f8f8;
+$uni-bg-color-hover:#f1f1f1;//点击状态颜色
+$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
+
+/* 边框颜色 */
+$uni-border-color:#c8c7cc;
+
+/* 尺寸变量 */
+
+/* 文字尺寸 */
+$uni-font-size-sm:24rpx;
+$uni-font-size-base:28rpx;
+$uni-font-size-lg:32rpx;
+
+/* 图片尺寸 */
+$uni-img-size-sm:40rpx;
+$uni-img-size-base:52rpx;
+$uni-img-size-lg:80rpx;
+
+/* Border Radius */
+$uni-border-radius-sm: 4rpx;
+$uni-border-radius-base: 6rpx;
+$uni-border-radius-lg: 12rpx;
+$uni-border-radius-circle: 50%;
+
+/* 水平间距 */
+$uni-spacing-row-sm: 10px;
+$uni-spacing-row-base: 20rpx;
+$uni-spacing-row-lg: 30rpx;
+
+/* 垂直间距 */
+$uni-spacing-col-sm: 8rpx;
+$uni-spacing-col-base: 16rpx;
+$uni-spacing-col-lg: 24rpx;
+
+/* 透明度 */
+$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
+
+/* 文章场景相关 */
+$uni-color-title: #2C405A; // 文章标题颜色
+$uni-font-size-title:40rpx;
+$uni-color-subtitle: #555555; // 二级标题颜色
+$uni-font-size-subtitle:36rpx;
+$uni-color-paragraph: #3F536E; // 文章段落颜色
+$uni-font-size-paragraph:30rpx;

+ 0 - 0
unpackage/dist/dev/.automator/mp-weixin/.automator.json


File diff ditekan karena terlalu besar
+ 1 - 0
unpackage/dist/dev/.sourcemap/mp-weixin/common/main.js.map


File diff ditekan karena terlalu besar
+ 1 - 0
unpackage/dist/dev/.sourcemap/mp-weixin/common/runtime.js.map


File diff ditekan karena terlalu besar
+ 1 - 0
unpackage/dist/dev/.sourcemap/mp-weixin/common/vendor.js.map


File diff ditekan karena terlalu besar
+ 1 - 0
unpackage/dist/dev/.sourcemap/mp-weixin/components/instructions.js.map


File diff ditekan karena terlalu besar
+ 1 - 0
unpackage/dist/dev/.sourcemap/mp-weixin/components/uni-steps/uni-steps.js.map


File diff ditekan karena terlalu besar
+ 1 - 0
unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/index.js.map


File diff ditekan karena terlalu besar
+ 1 - 0
unpackage/dist/dev/.sourcemap/mp-weixin/pages/recharge/recharge.js.map


+ 1 - 0
unpackage/dist/dev/.sourcemap/mp-weixin/pages/refresh/refresh.js.map

@@ -0,0 +1 @@
+{"version":3,"sources":["uni-app:///main.js"],"names":["createPage","Page"],"mappings":";;;;;;;;;;kDAAA;AACA;AACA,kN;AACAA,UAAU,CAACC,gBAAD,CAAV,C","file":"pages/refresh/refresh.js","sourcesContent":["import 'uni-pages';\nimport Vue from 'vue'\nimport Page from './pages/refresh/refresh.vue'\ncreatePage(Page)"],"sourceRoot":""}

File diff ditekan karena terlalu besar
+ 1 - 0
unpackage/dist/dev/.sourcemap/mp-weixin/pages/reshui/reshui.js.map


+ 1 - 0
unpackage/dist/dev/mp-weixin

@@ -0,0 +1 @@
+Subproject commit 11d3ea1f0d0f621b239da5bff5238e4694e34723