From a0ee08bf85cccb79a7eb4f581b6746bcaef655e3 Mon Sep 17 00:00:00 2001
From: zmj <1493694146@qq.com>
Date: Sat, 27 Apr 2024 11:47:31 +0800
Subject: [PATCH] =?UTF-8?q?=E4=B8=80=E9=94=AE=E7=99=BB=E5=BD=95=E5=AE=8C?=
 =?UTF-8?q?=E6=88=90?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 api/user.js                                   |   19 +-
 components/orderGoods/index.vue               |   73 +-
 manifest.json                                 |  703 +++++------
 pages/users/login/login_copy.vue              | 1045 ++++++++++-------
 pages/users/login/oneClickStyle.js            |   69 ++
 pages/users/refund/detail.vue                 |  577 +++++----
 .../cloudfunctions/oneClickLoginFn/index.js   |   35 +
 .../oneClickLoginFn/package.json              |    8 +
 uniCloud-aliyun/database/JQL查询.jql          |   12 +
 uni_modules/uni-config-center/changelog.md    |    6 +
 uni_modules/uni-config-center/package.json    |   81 ++
 uni_modules/uni-config-center/readme.md       |   93 ++
 .../common/uni-config-center/index.js         |    1 +
 .../common/uni-config-center/package.json     |    1 +
 uni_modules/uni-id-common/changelog.md        |   34 +
 uni_modules/uni-id-common/package.json        |   85 ++
 uni_modules/uni-id-common/readme.md           |    3 +
 .../common/uni-id-common/index.js             |    1 +
 .../common/uni-id-common/package.json         |    1 +
 .../uni-open-bridge-common/bridge-error.js    |   26 +
 .../common/uni-open-bridge-common/config.js   |  124 ++
 .../common/uni-open-bridge-common/consts.js   |   30 +
 .../common/uni-open-bridge-common/index.js    |  317 +++++
 .../uni-open-bridge-common/package.json       |   15 +
 .../common/uni-open-bridge-common/storage.js  |  111 ++
 .../uni-open-bridge-common/uni-cloud-cache.js |  324 +++++
 .../uni-open-bridge-common/validator.js       |   31 +
 .../uni-open-bridge-common/weixin-server.js   |  203 ++++
 28 files changed, 2979 insertions(+), 1049 deletions(-)
 create mode 100644 pages/users/login/oneClickStyle.js
 create mode 100644 uniCloud-aliyun/cloudfunctions/oneClickLoginFn/index.js
 create mode 100644 uniCloud-aliyun/cloudfunctions/oneClickLoginFn/package.json
 create mode 100644 uniCloud-aliyun/database/JQL查询.jql
 create mode 100644 uni_modules/uni-config-center/changelog.md
 create mode 100644 uni_modules/uni-config-center/package.json
 create mode 100644 uni_modules/uni-config-center/readme.md
 create mode 100644 uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/index.js
 create mode 100644 uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/package.json
 create mode 100644 uni_modules/uni-id-common/changelog.md
 create mode 100644 uni_modules/uni-id-common/package.json
 create mode 100644 uni_modules/uni-id-common/readme.md
 create mode 100644 uni_modules/uni-id-common/uniCloud/cloudfunctions/common/uni-id-common/index.js
 create mode 100644 uni_modules/uni-id-common/uniCloud/cloudfunctions/common/uni-id-common/package.json
 create mode 100644 uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/bridge-error.js
 create mode 100644 uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/config.js
 create mode 100644 uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/consts.js
 create mode 100644 uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/index.js
 create mode 100644 uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/package.json
 create mode 100644 uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/storage.js
 create mode 100644 uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/uni-cloud-cache.js
 create mode 100644 uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/validator.js
 create mode 100644 uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/weixin-server.js

diff --git a/api/user.js b/api/user.js
index 41cb19c..585f6b6 100644
--- a/api/user.js
+++ b/api/user.js
@@ -13,9 +13,9 @@ import Cache from '@/utils/cache';
  * 获取版本信息
  */
 export function Appversion(data) {
-  return request.get(`app/version`, data, {
-    noAuth: true
-  });
+	return request.get(`app/version`, data, {
+		noAuth: true
+	});
 }
 /**
  * 获取用户信息
@@ -117,6 +117,17 @@ export function registerForget(data) {
 		noAuth: true
 	});
 }
+
+
+/**
+ * 一键登录
+ */
+export function phonelogin(data) {
+	return request.post("auth/phonelogin", data, {
+		noAuth: true
+	});
+}
+
 /**
  * 获取用户中心菜单
  *
@@ -257,7 +268,7 @@ export function extractCash(data) {
  * 申请提现
  */
 export function getAdminApplyAPI(merId, data) {
-  return request.get(`admin/${merId}/apply`, data);
+	return request.get(`admin/${merId}/apply`, data);
 }
 /**
  * 提现银行/提现最低金额
diff --git a/components/orderGoods/index.vue b/components/orderGoods/index.vue
index 2beaad7..164d4d3 100644
--- a/components/orderGoods/index.vue
+++ b/components/orderGoods/index.vue
@@ -39,7 +39,7 @@
 								<view class="right-btn-box event_box">
 									<view class="btn-item"
 										v-if="evaluate != 2 && item.is_refund ==0 && pay_type!= 10 && status==0 && (evaluate != 10 && evaluate != 11) && orderData.refund_status || item.refund_num > 0"
-										@click.stop="refund(item)">申请退款</view>
+										@click.stop="showTips=true,refundItem=item">申请退款</view>
 									<view class="btn-item err" v-if="item.is_refund ==1">退款中 x
 										{{item.product_num - item.refund_num}}
 									</view>
@@ -113,7 +113,7 @@
 						</view>
 						<view class="btn-item"
 							v-if="evaluate != 2 && item.refund_switch==1 && pay_type!= 10 && status==0 && (item.is_refund == 0 && evaluate != 9 && orderData.refund_status || item.refund_num > 0)"
-							@click.stop="refund(item)">申请退款</view>
+							@click.stop="showTips=true,refundItem=item">申请退款</view>
 						<view class='btn-item' v-if='item.is_reply==0 && evaluate==2 && item.refund_num > 0'
 							@click.stop="evaluateTap(item.order_product_id,orderId)">去评价</view>
 						<view class='btn-item on' v-else-if="item.is_reply==1 && evaluate==2">已评价</view>
@@ -121,6 +121,22 @@
 				</view>
 			</view>
 		</view>
+
+		<u-overlay :show="showTips">
+			<view class="tips">
+				<view class="" style="font-size: 32rpx;">
+					温馨提示
+				</view>
+				<view class="">
+					下单后1小时内申请退款可极速退款
+				</view>
+				<u-button color="#61D137" text="我知道了" @tap="refund(refundItem)"></u-button>
+			</view>
+		</u-overlay>
+
+
+
+
 	</view>
 </template>
 
@@ -169,14 +185,14 @@
 				type: String,
 				default: '',
 			},
-      pay_type:{
-        type: [Number, String],
-        default: 0,
-      },
-      status:{
-        type: [Number, String],
-        default: 0,
-      },
+			pay_type: {
+				type: [Number, String],
+				default: 0,
+			},
+			status: {
+				type: [Number, String],
+				default: 0,
+			},
 			jump: {
 				type: Boolean,
 				default: false,
@@ -187,14 +203,16 @@
 					return {};
 				}
 			},
-      sale_type: {
-        type: [Number, String],
-        default: 1,
-      },
+			sale_type: {
+				type: [Number, String],
+				default: 1,
+			},
 		},
 		computed: mapGetters(['viewColor']),
 		data() {
 			return {
+				showTips: false, //退款提示弹窗
+				refundItem: null,
 				domain: HTTP_REQUEST_URL,
 				totalNmu: '',
 				isTimePay: false, //是否到支付时间
@@ -245,7 +263,8 @@
 						let id = res.data.product_assist_set_id;
 						uni.hideLoading();
 						uni.navigateTo({
-							url: '/pages/activity/assist_detail/index?id=' + id + '&sale_type=' + this.sale_type
+							url: '/pages/activity/assist_detail/index?id=' + id +
+								'&sale_type=' + this.sale_type
 						});
 					}).catch((err) => {
 						uni.showToast({
@@ -257,6 +276,7 @@
 			},
 			// 退款
 			refund(item) {
+				if (this.showTips) this.showTips = false;
 				// #ifdef MP
 				openOrderRefundSubscribe().then(() => {
 					uni.hideLoading();
@@ -281,12 +301,14 @@
 				if (this.evaluate == 0 || this.evaluate == 9 || this.orderData.is_virtual != 0) {
 					uni.navigateTo({
 						url: '/pages/users/refund/confirm?order_id=' + this.orderId + '&type=1' + '&ids=' + item
-							.order_product_id + '&refund_type=1&order_type=' + this.orderData.order_type + '&sale_type=' + this.sale_type
+							.order_product_id + '&refund_type=1&order_type=' + this.orderData.order_type +
+							'&sale_type=' + this.sale_type
 					})
 				} else {
 					uni.navigateTo({
 						url: '/pages/users/refund/select?order_id=' + this.orderId + '&type=1&order_type=' + this
-							.orderData.order_type + '&ids=' + item.order_product_id + '&sale_type=' + this.sale_type
+							.orderData.order_type + '&ids=' + item.order_product_id + '&sale_type=' + this
+							.sale_type
 					})
 				}
 				// #endif
@@ -459,4 +481,21 @@
 			background: #F0F0F0;
 		}
 	}
+
+	.tips {
+		width: 590rpx;
+		height: 354rpx;
+		background-color: white;
+		border-radius: 16rpx;
+		position: absolute;
+		top: 50%;
+		left: 50%;
+		transform: translate(-50%, -50%);
+		box-sizing: border-box;
+		padding: 50rpx 40rpx;
+		display: flex;
+		flex-direction: column;
+		justify-content: space-between;
+		align-items: center;
+	}
 </style>
\ No newline at end of file
diff --git a/manifest.json b/manifest.json
index 1753aac..858ea67 100644
--- a/manifest.json
+++ b/manifest.json
@@ -1,352 +1,353 @@
 {
-	"name": "惠农生活",
-	"appid": "__UNI__3A527D1",
-	"description": "",
-	"versionName": "2.0.37",
-	"versionCode": 2037,
-	"transformPx": false,
-	/* 5+App特有相关 */
-	"app-plus": {
-		"titleNView": true,
-		"usingComponents": true,
-		"nvueCompiler": "uni-app",
-		"nvueStyleCompiler": "uni-app",
-		"compilerVersion": 3,
-		"compatible": {
-			"ignoreVersion": true //true表示忽略版本检查提示框,HBuilderX1.9.0及以上版本支持 
-		},
-		"splashscreen": {
-			"alwaysShowBeforeRender": false,
-			"waiting": false,
-			"autoclose": true,
-			"delay": 0
-		},
-		/* 模块配置 */
-		"modules": {
-			"VideoPlayer": {},
-			"OAuth": {},
-			"Payment": {},
-			"Share": {},
-			"iBeacon": {},
-			"Maps": {},
-			"Geolocation": {},
-			"UniMP": {
-				"description": "uni小程序"
-			},
-			"Push": {},
-			"Barcode": {},
-			"Camera": {}
-		},
-		"safearea": {
-			"bottom": {
-				"offset": "none"
-			}
-		},
-		/* 应用发布信息 */
-		"distribute": {
-			/* android打包配置 */
-			"android": {
-				"permissions": [
-					"<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
-					"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
-					"<uses-permission android:name=\"android.permission.ACCESS_LOCATION_EXTRA_COMMANDS\"/>",
-					"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
-					"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
-					"<uses-permission android:name=\"android.permission.BATTERY_STATS\"/>",
-					"<uses-permission android:name=\"android.permission.BLUETOOTH\"/>",
-					"<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
-					"<uses-permission android:name=\"android.permission.CAMERA\"/>",
-					"<uses-permission android:name=\"android.permission.CHANGE_CONFIGURATION\"/>",
-					"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
-					"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
-					"<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
-					"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
-					"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
-					"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
-					"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
-					"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
-					"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>",
-					"<uses-permission android:name=\"android.permission.BLUETOOTH_ADMIN\"/>"
-				],
-				"abiFilters": ["armeabi-v7a", "arm64-v8a", "x86"],
-				"permissionExternalStorage": {
-					"request": "none",
-					"prompt": "应用保存运行状态等信息,需要获取读写手机存储(系统提示为访问设备上的照片、媒体内容和文件)权限,请允许。"
-				},
-				"permissionPhoneState": {
-					"request": "none" //拨打电话权限关闭
-				},
-				"minSdkVersion": 23,
-				"targetSdkVersion": 30
-			},
-			/* ios打包配置 */
-			"ios": {
-				"privacyDescription": {
-					"NSPhotoLibraryUsageDescription": "上传用户头像保存分享海报",
-					"NSPhotoLibraryAddUsageDescription": "上传用户头像保存分享海报",
-					"NSCameraUsageDescription": "上传用户头像保存分享海报",
-					"NSLocationWhenInUseUsageDescription": "根据客户地理位置推荐最近门店",
-					"NSLocationAlwaysUsageDescription": "根据客户地理位置推荐最近门店"
-				},
-				"idfa": false,
-				"dSYMs": false
-			},
-			/* SDK配置 */
-			"sdkConfigs": {
-				"maps": {
-					"amap": {
-						"appkey_ios": "0a3202688624938fd5d2f37b52c30d5d",
-						"appkey_android": "0354f5ddc11e2ea76c5aac647f44d945",
-						"name": "amapIvoVHpJR"
-					}
-				},
-				"payment": {
-					"weixin": {
-						"__platform__": ["ios", "android"],
-						"appid": "wx2e8f79ff281284f5",
-						"UniversalLinks": "https://shop.lihaink.cn/"
-					}
-				},
-				"share": {
-					"weixin": {
-						"appid": "wx2e8f79ff281284f5",
-						"UniversalLinks": "https://shop.lihaink.cn/"
-					}
-				},
-				"geolocation": {
-					"amap": {
-						"name": "amapIvoVHpJR",
-						"__platform__": ["ios", "android"],
-						"appkey_ios": "0a3202688624938fd5d2f37b52c30d5d",
-						"appkey_android": "0354f5ddc11e2ea76c5aac647f44d945"
-					}
-				},
-				"push": {},
-				"oauth": {
-					"weixin": {
-						"appid": "wx2e8f79ff281284f5",
-						"UniversalLinks": "https://shop.lihaink.cn/"
-					}
-				},
-				"ad": {}
-			},
-			"icons": {
-				"android": {
-					"hdpi": "unpackage/res/icons/72x72.png",
-					"xhdpi": "unpackage/res/icons/96x96.png",
-					"xxhdpi": "unpackage/res/icons/144x144.png",
-					"xxxhdpi": "unpackage/res/icons/192x192.png"
-				},
-				"ios": {
-					"appstore": "unpackage/res/icons/1024x1024.png",
-					"ipad": {
-						"app": "unpackage/res/icons/76x76.png",
-						"app@2x": "unpackage/res/icons/152x152.png",
-						"notification": "unpackage/res/icons/20x20.png",
-						"notification@2x": "unpackage/res/icons/40x40.png",
-						"proapp@2x": "unpackage/res/icons/167x167.png",
-						"settings": "unpackage/res/icons/29x29.png",
-						"settings@2x": "unpackage/res/icons/58x58.png",
-						"spotlight": "unpackage/res/icons/40x40.png",
-						"spotlight@2x": "unpackage/res/icons/80x80.png"
-					},
-					"iphone": {
-						"app@2x": "unpackage/res/icons/120x120.png",
-						"app@3x": "unpackage/res/icons/180x180.png",
-						"notification@2x": "unpackage/res/icons/40x40.png",
-						"notification@3x": "unpackage/res/icons/60x60.png",
-						"settings@2x": "unpackage/res/icons/58x58.png",
-						"settings@3x": "unpackage/res/icons/87x87.png",
-						"spotlight@2x": "unpackage/res/icons/80x80.png",
-						"spotlight@3x": "unpackage/res/icons/120x120.png"
-					}
-				}
-			},
-			"splashscreen": {
-				"useOriginalMsgbox": true,
-				"androidStyle": "common"
-			}
-		},
-		"nativePlugins": {
-			"JG-JCore": {
-				"JPUSH_APPKEY_IOS": "8a5efd65cda14fafa6e64ad3",
-				"JPUSH_CHANNEL_IOS": "8a5efd65cda14fafa6e64ad3",
-				"JPUSH_APPKEY_ANDROID": "b5f679f4357018605ea6fd2e",
-				"JPUSH_CHANNEL_ANDROID": "",
-				"__plugin_info__": {
-					"name": "JG-JCore",
-					"description": "极光推送JCore插件",
-					"platforms": "Android,iOS",
-					"url": "",
-					"android_package_name": "uni.UNI3A527D1",
-					"ios_bundle_id": "",
-					"isCloud": false,
-					"bought": -1,
-					"pid": "",
-					"parameters": {
-						"JPUSH_APPKEY_IOS": {
-							"des": "[iOS]极光portal配置应用信息时分配的AppKey",
-							"key": "JCore:APP_KEY",
-							"value": "daebe19b547c43128796a078"
-						},
-						"JPUSH_CHANNEL_IOS": {
-							"des": "[iOS]用于统计分发渠道,不需要可填默认值developer-default",
-							"key": "JCore:CHANNEL",
-							"value": ""
-						},
-						"JPUSH_APPKEY_ANDROID": {
-							"des": "[Android]极光portal配置应用信息时分配的AppKey",
-							"key": "JPUSH_APPKEY",
-							"value": ""
-						},
-						"JPUSH_CHANNEL_ANDROID": {
-							"des": "[Android]用于统计分发渠道,不需要可填默认值developer-default",
-							"key": "JPUSH_CHANNEL",
-							"value": ""
-						}
-					}
-				}
-			},
-			"JG-JPush": {
-				"JPUSH_ISPRODUCTION_IOS": "true",
-				"JPUSH_ADVERTISINGID_IOS": "",
-				"JPUSH_DEFAULTINITJPUSH_IOS": "true",
-				"JPUSH_OPPO_APPKEY": "",
-				"JPUSH_OPPO_APPID": "",
-				"JPUSH_OPPO_APPSECRET": "",
-				"JPUSH_VIVO_APPKEY": "",
-				"JPUSH_VIVO_APPID": "",
-				"JPUSH_MEIZU_APPKEY": "",
-				"JPUSH_MEIZU_APPID": "",
-				"JPUSH_XIAOMI_APPKEY": "",
-				"JPUSH_XIAOMI_APPID": "",
-				"__plugin_info__": {
-					"name": "JG-JPush",
-					"description": "极光推送Hbuilder插件",
-					"platforms": "Android,iOS",
-					"url": "",
-					"android_package_name": "uni.UNI3A527D1",
-					"ios_bundle_id": "",
-					"isCloud": false,
-					"bought": -1,
-					"pid": "",
-					"parameters": {
-						"JPUSH_ISPRODUCTION_IOS": {
-							"des": "[iOS]是否是生产环境,是填true,不是填false或者不填",
-							"key": "JPush:ISPRODUCTION",
-							"value": ""
-						},
-						"JPUSH_ADVERTISINGID_IOS": {
-							"des": "[iOS]广告标识符(IDFA)如果不需要使用IDFA,可不填",
-							"key": "JPush:ADVERTISINGID",
-							"value": ""
-						},
-						"JPUSH_DEFAULTINITJPUSH_IOS": {
-							"des": "[iOS]是否默认初始化,是填true,不是填false或者不填",
-							"key": "JPush:DEFAULTINITJPUSH",
-							"value": ""
-						},
-						"JPUSH_OPPO_APPKEY": {
-							"des": "厂商OPPO-appkey,示例:OP-12345678",
-							"key": "OPPO_APPKEY",
-							"value": ""
-						},
-						"JPUSH_OPPO_APPID": {
-							"des": "厂商OPPO-appId,示例:OP-12345678",
-							"key": "OPPO_APPID",
-							"value": ""
-						},
-						"JPUSH_OPPO_APPSECRET": {
-							"des": "厂商OPPO-appSecret,示例:OP-12345678",
-							"key": "OPPO_APPSECRET",
-							"value": ""
-						},
-						"JPUSH_VIVO_APPKEY": {
-							"des": "厂商VIVO-appkey,示例:12345678",
-							"key": "com.vivo.push.api_key",
-							"value": ""
-						},
-						"JPUSH_VIVO_APPID": {
-							"des": "厂商VIVO-appId,示例:12345678",
-							"key": "com.vivo.push.app_id",
-							"value": ""
-						},
-						"JPUSH_MEIZU_APPKEY": {
-							"des": "厂商MEIZU-appKey,示例:MZ-12345678",
-							"key": "MEIZU_APPKEY",
-							"value": ""
-						},
-						"JPUSH_MEIZU_APPID": {
-							"des": "厂商MEIZU-appId,示例:MZ-12345678",
-							"key": "MEIZU_APPID",
-							"value": ""
-						},
-						"JPUSH_XIAOMI_APPKEY": {
-							"des": "厂商XIAOMI-appKey,示例:MI-12345678",
-							"key": "XIAOMI_APPKEY",
-							"value": ""
-						},
-						"JPUSH_XIAOMI_APPID": {
-							"des": "厂商XIAOMI-appId,示例:MI-12345678",
-							"key": "XIAOMI_APPID",
-							"value": ""
-						}
-					}
-				}
-			}
-		}
-	},
-	/* 快应用特有相关 */
-	"quickapp": {},
-	/* 小程序特有相关 */
-	"mp-weixin": {
-		"appid": "wx5fb1cc8edb3f8baa",
-		"setting": {
-			"urlCheck": false,
-			"minified": true,
-			"postcss": true,
-			"es6": true
-		},
-		"permission": {
-			"scope.userLocation": {
-				"desc": "获取您的位置"
-			}
-		},
-		"requiredPrivateInfos": ["getLocation", "chooseAddress"],
-		"usingComponents": true,
-		"__usePrivacyCheck__": true
-	},
-	"mp-alipay": {
-		"usingComponents": true
-	},
-	"mp-baidu": {
-		"usingComponents": true
-	},
-	"mp-toutiao": {
-		"usingComponents": true
-	},
-	"h5": {
-		"devServer": {
-			"https": false
-		},
-		"router": {
-			"mode": "history",
-			"base": ""
-		},
-		"domain": "",
-		"sdkConfigs": {
-			"maps": {
-				"qqmap": {
-					"key": "SMJBZ-WCHK4-ZPZUA-DSIXI-XDDVQ-XWFX7"
-				}
-			}
-		},
-		"title": "加载中...",
-		"template": "template.h5.html",
-		"optimization": {
-			"treeShaking": {
-				"enable": true
-			}
-		}
-	}
-}
\ No newline at end of file
+    "name" : "惠农生活",
+    "appid" : "__UNI__3A527D1",
+    "description" : "",
+    "versionName" : "2.0.37",
+    "versionCode" : 2037,
+    "transformPx" : false,
+    /* 5+App特有相关 */
+    "app-plus" : {
+        "titleNView" : true,
+        "usingComponents" : true,
+        "nvueCompiler" : "uni-app",
+        "nvueStyleCompiler" : "uni-app",
+        "compilerVersion" : 3,
+        "compatible" : {
+            "ignoreVersion" : true //true表示忽略版本检查提示框,HBuilderX1.9.0及以上版本支持 
+        },
+        "splashscreen" : {
+            "alwaysShowBeforeRender" : false,
+            "waiting" : false,
+            "autoclose" : true,
+            "delay" : 0
+        },
+        /* 模块配置 */
+        "modules" : {
+            "VideoPlayer" : {},
+            "OAuth" : {},
+            "Payment" : {},
+            "Share" : {},
+            "iBeacon" : {},
+            "Maps" : {},
+            "Geolocation" : {},
+            "UniMP" : {
+                "description" : "uni小程序"
+            },
+            "Push" : {},
+            "Barcode" : {},
+            "Camera" : {}
+        },
+        "safearea" : {
+            "bottom" : {
+                "offset" : "none"
+            }
+        },
+        /* 应用发布信息 */
+        "distribute" : {
+            /* android打包配置 */
+            "android" : {
+                "permissions" : [
+                    "<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_LOCATION_EXTRA_COMMANDS\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.BATTERY_STATS\"/>",
+                    "<uses-permission android:name=\"android.permission.BLUETOOTH\"/>",
+                    "<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
+                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_CONFIGURATION\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
+                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>",
+                    "<uses-permission android:name=\"android.permission.BLUETOOTH_ADMIN\"/>"
+                ],
+                "abiFilters" : [ "armeabi-v7a", "arm64-v8a", "x86" ],
+                "permissionExternalStorage" : {
+                    "request" : "none",
+                    "prompt" : "应用保存运行状态等信息,需要获取读写手机存储(系统提示为访问设备上的照片、媒体内容和文件)权限,请允许。"
+                },
+                "permissionPhoneState" : {
+                    "request" : "none" //拨打电话权限关闭
+                },
+                "minSdkVersion" : 23,
+                "targetSdkVersion" : 30
+            },
+            /* ios打包配置 */
+            "ios" : {
+                "privacyDescription" : {
+                    "NSPhotoLibraryUsageDescription" : "上传用户头像保存分享海报",
+                    "NSPhotoLibraryAddUsageDescription" : "上传用户头像保存分享海报",
+                    "NSCameraUsageDescription" : "上传用户头像保存分享海报",
+                    "NSLocationWhenInUseUsageDescription" : "根据客户地理位置推荐最近门店",
+                    "NSLocationAlwaysUsageDescription" : "根据客户地理位置推荐最近门店"
+                },
+                "idfa" : false,
+                "dSYMs" : false
+            },
+            /* SDK配置 */
+            "sdkConfigs" : {
+                "maps" : {
+                    "amap" : {
+                        "appkey_ios" : "0a3202688624938fd5d2f37b52c30d5d",
+                        "appkey_android" : "0354f5ddc11e2ea76c5aac647f44d945",
+                        "name" : "amapIvoVHpJR"
+                    }
+                },
+                "payment" : {
+                    "weixin" : {
+                        "__platform__" : [ "ios", "android" ],
+                        "appid" : "wx2e8f79ff281284f5",
+                        "UniversalLinks" : "https://shop.lihaink.cn/"
+                    }
+                },
+                "share" : {
+                    "weixin" : {
+                        "appid" : "wx2e8f79ff281284f5",
+                        "UniversalLinks" : "https://shop.lihaink.cn/"
+                    }
+                },
+                "geolocation" : {
+                    "amap" : {
+                        "name" : "amapIvoVHpJR",
+                        "__platform__" : [ "ios", "android" ],
+                        "appkey_ios" : "0a3202688624938fd5d2f37b52c30d5d",
+                        "appkey_android" : "0354f5ddc11e2ea76c5aac647f44d945"
+                    }
+                },
+                "push" : {},
+                "oauth" : {
+                    "weixin" : {
+                        "appid" : "wx2e8f79ff281284f5",
+                        "UniversalLinks" : "https://shop.lihaink.cn/"
+                    },
+                    "univerify" : {}
+                },
+                "ad" : {}
+            },
+            "icons" : {
+                "android" : {
+                    "hdpi" : "unpackage/res/icons/72x72.png",
+                    "xhdpi" : "unpackage/res/icons/96x96.png",
+                    "xxhdpi" : "unpackage/res/icons/144x144.png",
+                    "xxxhdpi" : "unpackage/res/icons/192x192.png"
+                },
+                "ios" : {
+                    "appstore" : "unpackage/res/icons/1024x1024.png",
+                    "ipad" : {
+                        "app" : "unpackage/res/icons/76x76.png",
+                        "app@2x" : "unpackage/res/icons/152x152.png",
+                        "notification" : "unpackage/res/icons/20x20.png",
+                        "notification@2x" : "unpackage/res/icons/40x40.png",
+                        "proapp@2x" : "unpackage/res/icons/167x167.png",
+                        "settings" : "unpackage/res/icons/29x29.png",
+                        "settings@2x" : "unpackage/res/icons/58x58.png",
+                        "spotlight" : "unpackage/res/icons/40x40.png",
+                        "spotlight@2x" : "unpackage/res/icons/80x80.png"
+                    },
+                    "iphone" : {
+                        "app@2x" : "unpackage/res/icons/120x120.png",
+                        "app@3x" : "unpackage/res/icons/180x180.png",
+                        "notification@2x" : "unpackage/res/icons/40x40.png",
+                        "notification@3x" : "unpackage/res/icons/60x60.png",
+                        "settings@2x" : "unpackage/res/icons/58x58.png",
+                        "settings@3x" : "unpackage/res/icons/87x87.png",
+                        "spotlight@2x" : "unpackage/res/icons/80x80.png",
+                        "spotlight@3x" : "unpackage/res/icons/120x120.png"
+                    }
+                }
+            },
+            "splashscreen" : {
+                "useOriginalMsgbox" : true,
+                "androidStyle" : "common"
+            }
+        },
+        "nativePlugins" : {
+            "JG-JCore" : {
+                "JPUSH_APPKEY_IOS" : "8a5efd65cda14fafa6e64ad3",
+                "JPUSH_CHANNEL_IOS" : "8a5efd65cda14fafa6e64ad3",
+                "JPUSH_APPKEY_ANDROID" : "b5f679f4357018605ea6fd2e",
+                "JPUSH_CHANNEL_ANDROID" : "",
+                "__plugin_info__" : {
+                    "name" : "JG-JCore",
+                    "description" : "极光推送JCore插件",
+                    "platforms" : "Android,iOS",
+                    "url" : "",
+                    "android_package_name" : "uni.UNI3A527D1",
+                    "ios_bundle_id" : "",
+                    "isCloud" : false,
+                    "bought" : -1,
+                    "pid" : "",
+                    "parameters" : {
+                        "JPUSH_APPKEY_IOS" : {
+                            "des" : "[iOS]极光portal配置应用信息时分配的AppKey",
+                            "key" : "JCore:APP_KEY",
+                            "value" : "daebe19b547c43128796a078"
+                        },
+                        "JPUSH_CHANNEL_IOS" : {
+                            "des" : "[iOS]用于统计分发渠道,不需要可填默认值developer-default",
+                            "key" : "JCore:CHANNEL",
+                            "value" : ""
+                        },
+                        "JPUSH_APPKEY_ANDROID" : {
+                            "des" : "[Android]极光portal配置应用信息时分配的AppKey",
+                            "key" : "JPUSH_APPKEY",
+                            "value" : ""
+                        },
+                        "JPUSH_CHANNEL_ANDROID" : {
+                            "des" : "[Android]用于统计分发渠道,不需要可填默认值developer-default",
+                            "key" : "JPUSH_CHANNEL",
+                            "value" : ""
+                        }
+                    }
+                }
+            },
+            "JG-JPush" : {
+                "JPUSH_ISPRODUCTION_IOS" : "true",
+                "JPUSH_ADVERTISINGID_IOS" : "",
+                "JPUSH_DEFAULTINITJPUSH_IOS" : "true",
+                "JPUSH_OPPO_APPKEY" : "",
+                "JPUSH_OPPO_APPID" : "",
+                "JPUSH_OPPO_APPSECRET" : "",
+                "JPUSH_VIVO_APPKEY" : "",
+                "JPUSH_VIVO_APPID" : "",
+                "JPUSH_MEIZU_APPKEY" : "",
+                "JPUSH_MEIZU_APPID" : "",
+                "JPUSH_XIAOMI_APPKEY" : "",
+                "JPUSH_XIAOMI_APPID" : "",
+                "__plugin_info__" : {
+                    "name" : "JG-JPush",
+                    "description" : "极光推送Hbuilder插件",
+                    "platforms" : "Android,iOS",
+                    "url" : "",
+                    "android_package_name" : "uni.UNI3A527D1",
+                    "ios_bundle_id" : "",
+                    "isCloud" : false,
+                    "bought" : -1,
+                    "pid" : "",
+                    "parameters" : {
+                        "JPUSH_ISPRODUCTION_IOS" : {
+                            "des" : "[iOS]是否是生产环境,是填true,不是填false或者不填",
+                            "key" : "JPush:ISPRODUCTION",
+                            "value" : ""
+                        },
+                        "JPUSH_ADVERTISINGID_IOS" : {
+                            "des" : "[iOS]广告标识符(IDFA)如果不需要使用IDFA,可不填",
+                            "key" : "JPush:ADVERTISINGID",
+                            "value" : ""
+                        },
+                        "JPUSH_DEFAULTINITJPUSH_IOS" : {
+                            "des" : "[iOS]是否默认初始化,是填true,不是填false或者不填",
+                            "key" : "JPush:DEFAULTINITJPUSH",
+                            "value" : ""
+                        },
+                        "JPUSH_OPPO_APPKEY" : {
+                            "des" : "厂商OPPO-appkey,示例:OP-12345678",
+                            "key" : "OPPO_APPKEY",
+                            "value" : ""
+                        },
+                        "JPUSH_OPPO_APPID" : {
+                            "des" : "厂商OPPO-appId,示例:OP-12345678",
+                            "key" : "OPPO_APPID",
+                            "value" : ""
+                        },
+                        "JPUSH_OPPO_APPSECRET" : {
+                            "des" : "厂商OPPO-appSecret,示例:OP-12345678",
+                            "key" : "OPPO_APPSECRET",
+                            "value" : ""
+                        },
+                        "JPUSH_VIVO_APPKEY" : {
+                            "des" : "厂商VIVO-appkey,示例:12345678",
+                            "key" : "com.vivo.push.api_key",
+                            "value" : ""
+                        },
+                        "JPUSH_VIVO_APPID" : {
+                            "des" : "厂商VIVO-appId,示例:12345678",
+                            "key" : "com.vivo.push.app_id",
+                            "value" : ""
+                        },
+                        "JPUSH_MEIZU_APPKEY" : {
+                            "des" : "厂商MEIZU-appKey,示例:MZ-12345678",
+                            "key" : "MEIZU_APPKEY",
+                            "value" : ""
+                        },
+                        "JPUSH_MEIZU_APPID" : {
+                            "des" : "厂商MEIZU-appId,示例:MZ-12345678",
+                            "key" : "MEIZU_APPID",
+                            "value" : ""
+                        },
+                        "JPUSH_XIAOMI_APPKEY" : {
+                            "des" : "厂商XIAOMI-appKey,示例:MI-12345678",
+                            "key" : "XIAOMI_APPKEY",
+                            "value" : ""
+                        },
+                        "JPUSH_XIAOMI_APPID" : {
+                            "des" : "厂商XIAOMI-appId,示例:MI-12345678",
+                            "key" : "XIAOMI_APPID",
+                            "value" : ""
+                        }
+                    }
+                }
+            }
+        }
+    },
+    /* 快应用特有相关 */
+    "quickapp" : {},
+    /* 小程序特有相关 */
+    "mp-weixin" : {
+        "appid" : "wx5fb1cc8edb3f8baa",
+        "setting" : {
+            "urlCheck" : false,
+            "minified" : true,
+            "postcss" : true,
+            "es6" : true
+        },
+        "permission" : {
+            "scope.userLocation" : {
+                "desc" : "获取您的位置"
+            }
+        },
+        "requiredPrivateInfos" : [ "getLocation", "chooseAddress" ],
+        "usingComponents" : true,
+        "__usePrivacyCheck__" : true
+    },
+    "mp-alipay" : {
+        "usingComponents" : true
+    },
+    "mp-baidu" : {
+        "usingComponents" : true
+    },
+    "mp-toutiao" : {
+        "usingComponents" : true
+    },
+    "h5" : {
+        "devServer" : {
+            "https" : false
+        },
+        "router" : {
+            "mode" : "history",
+            "base" : ""
+        },
+        "domain" : "",
+        "sdkConfigs" : {
+            "maps" : {
+                "qqmap" : {
+                    "key" : "SMJBZ-WCHK4-ZPZUA-DSIXI-XDDVQ-XWFX7"
+                }
+            }
+        },
+        "title" : "加载中...",
+        "template" : "template.h5.html",
+        "optimization" : {
+            "treeShaking" : {
+                "enable" : true
+            }
+        }
+    }
+}
diff --git a/pages/users/login/login_copy.vue b/pages/users/login/login_copy.vue
index 7e74e0f..ef72f4d 100644
--- a/pages/users/login/login_copy.vue
+++ b/pages/users/login/login_copy.vue
@@ -1,203 +1,214 @@
 <template>
-	<div :style="viewColor">
-    
-		<div class="register absolute" v-if="!auth_token">
-			<div class="login" style="background-size: 100% 100%;background-repeat: no-repeat;">
-				<div class="shading" >
-					<div class="pictrue acea-row row-center-wrapper" style="background-color: transparent !important;">
-						<image src="@/static/images/logo1.png"  />
-					</div>
-				</div>
-        <div class="whiteBg" v-if="formItem == 0">
-          <div class="logon" style="display: flex;align-items: center;justify-content: center;" @click="wxLogin"> 
-            <u-icon name="weixin-fill" color="#fff" size="30"></u-icon> 微信一键登录
-          </div>
-          
-          <div class="protocol acea-row row-between-wrapper">
-          	<checkbox-group class="checkgroup" @change='isAgree=!isAgree'>
-          		<checkbox class="checkbox" :checked="isAgree ? true : false" />
-          		<text class="protocol_text">我已同意<text @click="userAgree"
-          				class="font_pro">《用户协议》</text>与<text @click="userPrivacyAgree"
-          				class="font_pro">《隐私政策》</text></text>
-          	</checkbox-group>
-          </div>
-        </div>
-				<div class="whiteBg" v-else-if="formItem === 1" style="po">
-					<div class="title acea-row row-center-wrapper">
-						<div class="item" :class="current === index ? 'on' : ''" v-for="(item, index) in navList"
+	<view :style="viewColor">
+		<view class="register absolute" v-if="!auth_token">
+			<view class="login" style="background-size: 100% 100%;background-repeat: no-repeat;">
+				<view class="shading">
+					<view class="pictrue acea-row row-center-wrapper" style="background-color: transparent !important;">
+						<image src="@/static/images/logo1.png" />
+					</view>
+				</view>
+				<view class="" style="margin-top: 70rpx;" v-if='formItem==2'>
+					<view style="text-align: center;font-size: 36rpx;color: #20B128;font-weight: 700;">
+						重置密码
+					</view>
+					<view style="text-align: center;color: #BCBCBC;font-size: 24rpx;margin-top: 10rpx;">
+						请输入手机号码和验证码找回密码、重置
+					</view>
+				</view>
+				<view class="whiteBg" v-if="formItem == 0">
+					<view class="logon" style="display: flex;align-items: center;justify-content: center;"
+						@click="wxLogin">
+						<u-icon name="weixin-fill" color="#fff" size="30"></u-icon> 微信一键登录
+					</view>
+
+					<view class="protocol acea-row row-between-wrapper">
+						<checkbox-group class="checkgroup" @change='isAgree=!isAgree'>
+							<checkbox class="checkbox" :checked="isAgree ? true : false" />
+							<text class="protocol_text">我已同意<text @click="userAgree"
+									class="font_pro">《用户协议》</text>与<text @click="userPrivacyAgree"
+									class="font_pro">《隐私政策》</text></text>
+						</checkbox-group>
+					</view>
+				</view>
+				<view class="whiteBg" v-else-if="formItem === 1">
+					<view class="title acea-row row-center-wrapper">
+						<view class="item" :class="current === index ? 'on' : ''" v-for="(item, index) in navList"
 							@click="navTap(index)" :key="index">
 							{{ item }}
-						</div>
-					</div>
-					<div class="list" :hidden="current !== 1">
+						</view>
+					</view>
+					<view class="list" :hidden="current !== 1">
 						<form @submit.prevent="submit">
-							<div class="item">
-								<div class="acea-row row-middle">
+							<view class="item">
+								<view class="acea-row row-middle">
 									<image src="/static/images/phone_1.png"></image>
 									<input type="number" placeholder="输入账号" placeholder-class="placeholder"
 										v-model="account" required />
-								</div>
-							</div>
-							<div class="item">
-								<div class="acea-row row-middle">
+								</view>
+							</view>
+							<view class="item">
+								<view class="acea-row row-middle">
 									<image src="/static/images/code_2.png"></image>
 									<input type="password" placeholder="填写登录密码" placeholder-class="placeholder"
 										v-model="password" required />
-								</div>
-							</div>
+									<button class="code" @click="formItem=2">
+										忘记密码
+									</button>
+								</view>
+							</view>
 						</form>
-						<div class="tip">
-							<!-- <span @click="formItem = 2" class="font-color-red">立即注册</span> -->
-              <span> </span>
-							<navigator class="forgetPwd" hover-class="none" url="/pages/users/retrievePassword/index">
-								忘记密码
-							</navigator>
-						</div>
-
-					</div>
-					<div class="list" :hidden="current !== 0">
-						<div class="item">
-							<div class="acea-row row-middle">
+					</view>
+					<view class="list" :hidden="current !== 0">
+						<view class="item">
+							<view class="acea-row row-middle">
 								<image src="/static/images/phone_1.png"></image>
 								<input type="number" placeholder="输入手机号码" placeholder-class="placeholder"
 									v-model="account" />
-							</div>
-						</div>
-						
-						<div class="item">
-							<div class="acea-row row-middle">
+							</view>
+						</view>
+						<view class="item">
+							<view class="acea-row row-middle">
 								<image src="/static/images/code_2.png"></image>
-							
-								<input type="number" placeholder="填写验证码" placeholder-class="placeholder" class="codeIput"
-									v-model="captcha" maxlength="4" />
+								<input type="number" placeholder="填写验证码" placeholder-class="placeholder"
+									class="codeIput" v-model="captcha" maxlength="4" />
 								<button class="code" :disabled="disabled" :class="disabled === true ? 'on' : ''"
 									@click="handleVerify">
 									{{ text }}
 								</button>
-							</div>
-						</div>
-						<div class="item" v-if="isShowCode">
-							<div class="acea-row row-middle">
+							</view>
+						</view>
+						<view class="item" v-if="isShowCode">
+							<view class="acea-row row-middle">
 								<image src="/static/images/code_2.png"></image>
-								<input type="number" placeholder="填写验证码"  placeholder-class="placeholder" class="codeIput"
-									v-model="codeVal" maxlength="4" />
-								<div class="code" @click="getcaptcha">
+								<input type="number" placeholder="填写验证码" placeholder-class="placeholder"
+									class="codeIput" v-model="codeVal" maxlength="4" />
+								<view class="code" @click="getcaptcha">
 									<image class="code-img" style="width: 100%;height: 100%;" :src="codeUrl" />
-								</div>
-							</div>
-						</div>
-					</div>
+								</view>
+							</view>
+						</view>
+					</view>
 
-					<div class="logon" @click="loginMobile" :hidden="current !== 0">登录</div>
-					<div class="logon" @click="submit" :hidden="current === 0">登录</div>
-					<div class="protocol acea-row row-between-wrapper">
+					<view class="logon" @click="loginMobile" :hidden="current !== 0">登5445录</view>
+					<view class="logon" @click="submit" :hidden="current === 0">账号登录</view>
+					<view class="protocol acea-row row-between-wrapper">
 						<checkbox-group class="checkgroup" @change='isAgree=!isAgree'>
 							<checkbox class="checkbox" :checked="isAgree ? true : false" />
 							<text class="protocol_text">我已同意<text @click="userAgree"
 									class="font_pro">《用户协议》</text>与<text @click="userPrivacyAgree"
 									class="font_pro">《隐私政策》</text></text>
 						</checkbox-group>
-					</div>
-				</div>
-				<div class="whiteBg" v-else>
-					<div class="title">注册账号</div>
-					<div class="list">
-						<div class="item">
-							<div class="acea-row row-middle">
+					</view>
+				</view>
+
+				<view class="whiteBg" style="margin-top: 0;" v-else-if='formItem==2'>
+					<view class="list">
+						<view class="item">
+							<view class="acea-row row-middle">
 								<image src="/static/images/phone_1.png"></image>
 								<input type="number" placeholder="输入手机号码" placeholder-class="placeholder"
 									v-model="account" />
-							</div>
-						</div>
-						<div class="item">
-							<div class="acea-row row-middle">
+							</view>
+						</view>
+						<view class="item">
+							<view class="acea-row row-middle">
 								<image src="/static/images/code_2.png"></image>
-								<input type="number" placeholder="填写验证码"   maxLength='4'  placeholder-class="placeholder" class="codeIput"
-									v-model="captcha" />
-									
+								<input type="number" placeholder="填写验证码" maxLength='4' placeholder-class="placeholder"
+									class="codeIput" v-model="captcha" />
 								<button class="code" :disabled="disabled" :class="disabled === true ? 'on' : ''"
 									@click="handleVerify">
 									{{ text }}
 								</button>
-							</div>
-						</div>
-						<div class="item">
-							<div class="acea-row row-middle">
+							</view>
+						</view>
+						<view class="item">
+							<view class="acea-row row-middle">
 								<image src="/static/images/code_1.png"></image>
-								<input type="password" placeholder="填写您的登录密码" placeholder-class="placeholder"
+								<input type="password" placeholder="请输入新密码" placeholder-class="placeholder"
 									v-model="password" />
-							</div>
-						</div>
-						
-						<div class="item" v-if="isShowCode">
-							<div class="acea-row row-middle">
+							</view>
+						</view>
+						<view class="item">
+							<view class="acea-row row-middle">
+								<image src="/static/images/code_1.png"></image>
+								<input type="password" placeholder="请再次输入密码" placeholder-class="placeholder"
+									v-model="confirm_pwd" />
+							</view>
+						</view>
+
+						<view class="item" v-if="isShowCode">
+							<view class="acea-row row-middle">
 								<image src="/static/images/code_2.png"></image>
-								<input type="number" placeholder="填写验证码" maxlength="4" placeholder-class="placeholder" class="codeIput"
-									v-model="codeVal" />
-								<div class="code" @click="getcaptcha">
+								<input type="number" placeholder="填写验证码" maxlength="4" placeholder-class="placeholder"
+									class="codeIput" v-model="codeVal" />
+								<view class="code" @click="getcaptcha">
 									<image class="code-img" style="width: 100%;height: 100%;" :src="codeUrl" />
-								</div>
-							</div>
-						</div>
-					</div>
-					<div class="tip">
-						<div>
-							已有账号?
-							<span @click="formItem = 1" class="font-color-red">去登录</span>
-						</div>
-					</div>
-					<div class="logon" @click="register">注册</div>
-					<div class="protocol acea-row row-between-wrapper">
+								</view>
+							</view>
+						</view>
+					</view>
+					<view class="logon" @click="registerReset">完成并登录</view>
+					<view class="tip">
+						<text @click="formItem=1">立即登录</text>
+					</view>
+					<view class="protocol acea-row row-between-wrapper">
 						<checkbox-group class="checkgroup" @change='isAgree=!isAgree'>
 							<checkbox class="checkbox" :checked="isAgree ? true : false" />
 							<text class="protocol_text">我已同意<text @click="userAgree"
 									class="font_pro">《用户协议》</text>与<text @click="userPrivacyAgree"
 									class="font_pro">《隐私政策》</text></text>
 						</checkbox-group>
-					</div>
-				</div>
-			</div>
-			<div class="bottom"></div>
+					</view>
+				</view>
+			</view>
+			<view class="bottom"></view>
 			<view class="settlementAgreement" v-if="showAgreement">
 				<view class="setAgCount">
 					<i class="icon iconfont icon-cha" @click="showAgreement = false"></i>
-					<div class="title">用户协议与隐私政策</div>
+					<view class="title">用户协议与隐私政策</view>
 					<view class="content">
 						<jyf-parser :html="agreement" ref="article" :tag-style="tagStyle"></jyf-parser>
 					</view>
 				</view>
 			</view>
-      
-      <!-- #ifdef APP-PLUS -->
-      <div class="protocol acea-row row-between-wrapper" style="position: fixed; bottom: 160rpx;left: 50%;transform: translate(-50%);">
-      	<text class="protocol_text" v-if="formItem==0" @click="formItem = 1 ">其他方式登录</text>
-        <text class="protocol_text" v-else @click="formItem = 0 ">微信快捷登录</text>
-      </div>
-      <!-- #endif -->
-		</div>
+
+			<!-- #ifdef APP-PLUS -->
+			<view class="footer-btns">
+				<view class="login-type-btn" :class="{actLoginType:formItem==0}" style="margin-right: 70rpx;">
+					<text v-if='formItem == 1' @click="formItem = 0">微信快捷登录</text>
+					<text v-else @click="appOneClcik">本机一键登录</text>
+				</view>
+				<view class="login-type-btn" :class="{actLoginType:formItem==1}">
+					<text v-if='formItem == 0' @click="formItem = 1">更多登录方式</text>
+					<text v-else @click="appOneClcik">本机一键登录</text>
+				</view>
+
+			</view>
+			<!-- #endif -->
+		</view>
 		<form report-submit='true' v-if="auth_token">
 			<view class="ChangePassword">
-        <view class="title">
-          <view>首次登录</view>
-          <view style="font-size: 36rpx;">需要绑定手机号码</view>
-        </view>
+				<view class="title">
+					<view>首次登录</view>
+					<view style="font-size: 36rpx;">需要绑定手机号码</view>
+				</view>
 				<view class="list">
 					<view class="item">
 						<input type='number' placeholder='填写手机号码' placeholder-class='placeholder'
 							v-model="account"></input>
 					</view>
-					
+
 					<view class="item acea-row row-between-wrapper">
-						<input type='number' placeholder='填写验证码' maxlength="4" placeholder-class='placeholder' class="codeIput"
-							v-model="captcha"></input>
-							
+						<input type='number' placeholder='填写验证码' maxlength="4" placeholder-class='placeholder'
+							class="codeIput" v-model="captcha"></input>
+
 						<button class="code" :class="disabled === true ? 'on' : ''" :disabled='disabled'
 							@click="handleVerify">
 							{{ text }}
 						</button>
 					</view>
 					<view class="item">
-						<input type='password' placeholder='填写登录密码'  placeholder-class='placeholder'
+						<input type='password' placeholder='填写登录密码' placeholder-class='placeholder'
 							v-model="password"></input>
 					</view>
 					<view class="protocol acea-row row-between-wrapper">
@@ -213,14 +224,54 @@
 				<button form-type="submit" @click="auth_token = ''" class="confirmBnt back">返回</button>
 			</view>
 		</form>
-		<!-- <view class="copyright" @click="goCopyUrl">
-			{{ copyright.status == -1 ? `${copyright.year} ${copyright.url}` : copyright.Copyright }}
-		</view> -->
-
 		<Verify @success="success" :captchaType="'blockPuzzle'" :imgSize="{ width: '330px', height: '155px' }"
 			ref="verify"></Verify>
-      
-	</div>
+		<!-- tips弹窗 -->
+		<u-overlay :show="showTips">
+			<view class="tips">
+				<view class="" style="font-size: 32rpx;">
+					{{tispTile}}
+				</view>
+				<block v-if="tispTile=='密码错误'">
+					<view class="">
+						{{tipsErr}}
+					</view>
+					<view class="" style="display: flex;">
+						<view style="width: 236rpx;height: 84rpx;margin-right:38rpx;">
+							<u-button plain text="找回密码" @tap="showTips=false,formItem=2"></u-button>
+						</view>
+						<view style="width: 236rpx;height: 84rpx;">
+							<u-button color="#46BF6F" text="重新输入" @tap="showTips=false"></u-button>
+						</view>
+					</view>
+				</block>
+				<block v-else-if="tispTile=='验证码错误'">
+					<view class="">
+						验证码错误,请重新收入
+					</view>
+					<view class="" style="display: flex;">
+						<u-button color="#46BF6F" text="确定" @tap="showTips=false"></u-button>
+					</view>
+				</block>
+				<block v-else-if="tispTile=='密码不一致'">
+					<view class="">
+						两次输入的密码不一致,请重新输入
+					</view>
+					<view class="" style="display: flex;">
+						<u-button color="#46BF6F" text="确定" @tap="showTips=false"></u-button>
+					</view>
+				</block>
+				<block v-else>
+					<view class="" style="display: flex;width: 236rpx;">
+						<u-button color="#46BF6F" text="确定" @tap="showTips=false"></u-button>
+					</view>
+				</block>
+			</view>
+		</u-overlay>
+		<!-- tips结束 -->
+
+
+	</view>
 </template>
 <script>
 	// +----------------------------------------------------------------------
@@ -244,7 +295,9 @@
 		getCaptcha,
 		getAgreementApi,
 		appleLogin,
-		loginMpPhone
+		loginMpPhone,
+		registerForget,
+		phonelogin
 	} from "@/api/user";
 	// #ifdef APP-PLUS
 	import {
@@ -275,15 +328,18 @@
 	import parser from "@/components/jyf-parser/jyf-parser";
 	import {
 		commonAuth,
-    userMerge
+		userMerge
 	} from '../../../api/public';
 	import {
 		mapGetters
 	} from "vuex";
 	import Verify from '@/components/verify/verify.vue';
-  import { Toast } from "../../../libs/uniApi";
+	import {
+		Toast
+	} from "../../../libs/uniApi";
 	const BACK_URL = "login_back_url";
 	// #ifdef APP-PLUS
+	import oneClickStyle from "./oneClickStyle.js"
 	var jpushModule = uni.requireNativePlugin("JG-JPush");
 	// #endif
 	export default {
@@ -295,17 +351,21 @@
 		},
 		data: function() {
 			return {
-				navList: ["快速登录","账号登录"],
+				tipsErr: "",
+				tispTile: '密码错误',
+				showTips: false,
+				navList: ["快速登录", "账号登录"],
 				current: 0,
 				account: "",
 				password: "",
+				confirm_pwd: "",
 				captcha: "",
 				// #ifdef APP-PLUS
 				formItem: 0,
 				// #endif
-        // #ifndef APP-PLUS
-        formItem: 1,
-        // #endif
+				// #ifndef APP-PLUS
+				formItem: 1,
+				// #endif
 				type: "login",
 				keyCode: "",
 				codeUrl: "",
@@ -333,6 +393,8 @@
 			formItem: function(nval, oVal) {
 				if (nval == 1) {
 					this.type = 'login'
+				} else if (nval == 2) {
+					this.type = 'change_pwd'
 				} else {
 					this.type = 'register'
 				}
@@ -350,7 +412,7 @@
 			this.getVersion();
 		},
 		mounted: function() {
-      
+
 		},
 		onReady() {
 			let that = this
@@ -367,9 +429,18 @@
 			// #endif
 		},
 		methods: {
+			showTipsFn(text, err) {
+				this.showTips = true
+				this.tispTile = text
+				this.tipsErr = err || ''
+			},
+			navgo(url) {
+				uni.navigateTo({
+					url
+				})
+			},
 			// #ifdef MP
 			getPhoneNumber(e) {
-
 				let that = this;
 				loginMpPhone({
 						iv: e.detail.iv,
@@ -379,7 +450,8 @@
 					}).then(({
 						data
 					}) => {
-						const backUrl = that.$Cache.get('login_back_url_weixin') || that.$Cache.get(BACK_URL) || "/pages/index/index";
+						const backUrl = that.$Cache.get('login_back_url_weixin') || that.$Cache.get(BACK_URL) ||
+							"/pages/index/index";
 						that.$Cache.clear(BACK_URL);
 						that.$Cache.clear('login_back_url_weixin');
 						that.$store.commit("LOGIN", {
@@ -498,7 +570,8 @@
 				}).then(res => {
 					const data = res.data;
 					if (res.data.status == 200) {
-						const backUrl = that.$Cache.get('login_back_url_weixin') || that.$Cache.get(BACK_URL) || "/pages/index/index";
+						const backUrl = that.$Cache.get('login_back_url_weixin') || that.$Cache.get(BACK_URL) ||
+							"/pages/index/index";
 						that.$Cache.clear(BACK_URL);
 						that.$Cache.clear('login_back_url_weixin');
 						that.$store.commit("LOGIN", {
@@ -555,13 +628,13 @@
 					provider: 'weixin',
 					onlyAuthorize: true,
 					success: function(loginRes) {
-            console.log(loginRes);
-            uni.hideLoading()
+						console.log(loginRes);
+						uni.hideLoading()
 						self.appUserInfo = loginRes;
 						self.weixinLoginApi()
 					},
 					fail(error) {
-            console.log(error);
+						console.log(error);
 						uni.showToast({
 							title: '登录失败',
 							icon: 'none',
@@ -582,16 +655,17 @@
 				commonAuth({
 					auth: {
 						type: 'app_wechat',
-            auth: {
-            	code: that.appUserInfo.authResult.access_token,
-            	openid: that.appUserInfo.authResult.openid,
-            	phone: this.account,
-            }
+						auth: {
+							code: that.appUserInfo.authResult.access_token,
+							openid: that.appUserInfo.authResult.openid,
+							phone: this.account,
+						}
 					}
 				}).then(res => {
 					const data = res.data;
 					if (res.data.status == 200) {
-						const backUrl = that.$Cache.get('login_back_url_weixin') || that.$Cache.get(BACK_URL) || "/pages/index/index";
+						const backUrl = that.$Cache.get('login_back_url_weixin') || that.$Cache.get(BACK_URL) ||
+							"/pages/index/index";
 						that.$Cache.clear(BACK_URL);
 						that.$Cache.clear('login_back_url_weixin');
 						that.$store.commit("LOGIN", {
@@ -620,13 +694,71 @@
 							url: backUrl
 						});
 					} else {
-            that.isAgree = false;
+						that.isAgree = false;
 						that.auth_token = res.data.result.key;
 						that.bindStatus = true;
 					}
 					uni.hideLoading();
 				}).catch(res => {
-          console.log(res);
+					console.log(res);
+					uni.hideLoading();
+					uni.showToast({
+						title: res.message || res,
+						icon: 'none',
+						duration: 2000
+					});
+				});
+			},
+			weixinLoginApi() {
+				const that = this
+				commonAuth({
+					auth: {
+						type: 'app_wechat',
+						auth: {
+							code: that.appUserInfo.code
+						}
+					}
+				}).then(res => {
+					console.log('--', res);
+					const data = res.data;
+					if (res.data.status == 200) {
+						const backUrl = that.$Cache.get('login_back_url_weixin') || that.$Cache.get(BACK_URL) ||
+							"/pages/index/index";
+						that.$Cache.clear(BACK_URL);
+						that.$Cache.clear('login_back_url_weixin');
+						that.$store.commit("LOGIN", {
+							'token': data.result.token,
+							'time': data.result.exp
+						});
+						that.$store.commit("SETUID", data.result.user.uid);
+						that.$store.commit('UPDATE_USERINFO', data.result.user);
+						let method
+						let indexPat = ['/pages/index/index', '/pages/order_addcart/order_addcart',
+							'/pages/goods_cate/goods_cate',
+							'/pages/user/index', '/pages/plant_grass/index'
+						]
+						if (indexPat.includes(this.getPath(backUrl))) {
+							method = 'switchTab'
+						} else {
+							method = 'navigateTo'
+						}
+						if (this.getPath(backUrl) === '/pages/users/login/index') {
+							uni.switchTab({
+								url: '/pages/index/index'
+							});
+							return
+						}
+						uni[method]({
+							url: backUrl
+						});
+					} else {
+						that.isAgree = false;
+						that.auth_token = res.data.result.key;
+						that.bindStatus = true;
+					}
+					uni.hideLoading();
+				}).catch(res => {
+					console.log('错误--', res);
 					uni.hideLoading();
 					uni.showToast({
 						title: res.message || res,
@@ -635,63 +767,6 @@
 					});
 				});
 			},
-      weixinLoginApi() {
-      	const that = this
-      	commonAuth({
-      		auth: {
-      			type: 'app_wechat',
-            auth: {
-            	code: that.appUserInfo.code
-            }
-      		}
-      	}).then(res => {
-          console.log('--', res);
-      		const data = res.data;
-      		if (res.data.status == 200) {
-      			const backUrl = that.$Cache.get('login_back_url_weixin') || that.$Cache.get(BACK_URL) || "/pages/index/index";
-      			that.$Cache.clear(BACK_URL);
-      			that.$Cache.clear('login_back_url_weixin');
-      			that.$store.commit("LOGIN", {
-      				'token': data.result.token,
-      				'time': data.result.exp
-      			});
-      			that.$store.commit("SETUID", data.result.user.uid);
-      			that.$store.commit('UPDATE_USERINFO', data.result.user);
-      			let method
-      			let indexPat = ['/pages/index/index', '/pages/order_addcart/order_addcart',
-      				'/pages/goods_cate/goods_cate',
-      				'/pages/user/index', '/pages/plant_grass/index'
-      			]
-      			if (indexPat.includes(this.getPath(backUrl))) {
-      				method = 'switchTab'
-      			} else {
-      				method = 'navigateTo'
-      			}
-      			if (this.getPath(backUrl) === '/pages/users/login/index') {
-      				uni.switchTab({
-      					url: '/pages/index/index'
-      				});
-      				return
-      			}
-      			uni[method]({
-      				url: backUrl
-      			});
-      		} else {
-            that.isAgree = false;
-      			that.auth_token = res.data.result.key;
-      			that.bindStatus = true;
-      		}
-      		uni.hideLoading();
-      	}).catch(res => {
-          console.log('错误--', res);
-      		uni.hideLoading();
-      		uni.showToast({
-      			title: res.message || res,
-      			icon: 'none',
-      			duration: 2000
-      		});
-      	});
-      },
 			getAgreement() {
 				let that = this
 				getAgreementApi('sys_user_agree').then(res => {
@@ -711,6 +786,7 @@
 						});
 					});
 			},
+			// 快速登录
 			async loginMobile() {
 				let that = this;
 				if (!that.account) return that.$util.Tips({
@@ -745,23 +821,24 @@
 						data
 					}) => {
 						this.checkOpenId(data.user)
-						const backUrl = that.$Cache.get('login_back_url_weixin') || that.$Cache.get(BACK_URL) || "/pages/index/index";
+						const backUrl = that.$Cache.get('login_back_url_weixin') || that.$Cache.get(BACK_URL) ||
+							"/pages/index/index";
 						that.$store.commit("LOGIN", {
 							'token': data.token,
 							'time': data.exp
 						});
 						that.$store.commit("SETUID", data.user.uid);
 						that.$store.commit('UPDATE_USERINFO', data.user);
-              
-            if(data.is_new_user && !that.$Cache.get('login_back_url_weixin')){
-              return uni.navigateTo({
-                url: '/pages/helpPeople/helpPeople'
-              })
-            }
-            
-            that.$Cache.clear(BACK_URL);
-            that.$Cache.clear('login_back_url_weixin');
-            
+
+						if (data.is_new_user && !that.$Cache.get('login_back_url_weixin')) {
+							return uni.navigateTo({
+								url: '/pages/helpPeople/helpPeople'
+							})
+						}
+
+						that.$Cache.clear(BACK_URL);
+						that.$Cache.clear('login_back_url_weixin');
+
 						let method
 						let indexPat = ['/pages/index/index', '/pages/order_addcart/order_addcart',
 							'/pages/goods_cate/goods_cate',
@@ -783,9 +860,7 @@
 						});
 					})
 					.catch(res => {
-						that.$util.Tips({
-							title: res
-						});
+						that.showTipsFn(res)
 					});
 			},
 			async register() {
@@ -831,116 +906,117 @@
 						});
 						that.$store.commit("SETUID", res.data.user.uid);
 						that.$store.commit('UPDATE_USERINFO', res.data.user);
-						const backUrl = that.$Cache.get('login_back_url_weixin') || that.$Cache.get(BACK_URL) || "/pages/index/index";
+						const backUrl = that.$Cache.get('login_back_url_weixin') || that.$Cache.get(BACK_URL) ||
+							"/pages/index/index";
 						that.$Cache.clear(BACK_URL);
 						that.$Cache.clear('login_back_url_weixin');
-            let method
-            let indexPat = ['/pages/index/index', '/pages/order_addcart/order_addcart',
-            	'/pages/goods_cate/goods_cate',
-            	'/pages/user/index'
-            ]
-            if (indexPat.includes(this.getPath(backUrl))) {
-            	method = 'switchTab'
-            } else {
-            	method = 'navigateTo'
-            }
-            uni[method]({
-            	url: backUrl,
-              success:()=>{
-                this.auth_token = ''
-              }
-            });
+						let method
+						let indexPat = ['/pages/index/index', '/pages/order_addcart/order_addcart',
+							'/pages/goods_cate/goods_cate',
+							'/pages/user/index'
+						]
+						if (indexPat.includes(this.getPath(backUrl))) {
+							method = 'switchTab'
+						} else {
+							method = 'navigateTo'
+						}
+						uni[method]({
+							url: backUrl,
+							success: () => {
+								this.auth_token = ''
+							}
+						});
 					})
 					.catch(res => {
+						console.log(res, 'res')
+						that.showTipsFn('密码错误', res)
+					});
+			},
+			async weixinMerge() {
+				let that = this;
+				if (!that.account) return that.$util.Tips({
+					title: '请输入手机号码'
+				});
+				if (!/^1(3|4|5|7|8|9|6)\d{9}$/i.test(that.account)) return that.$util.Tips({
+					title: '请输入正确的手机号码'
+				});
+				if (!that.captcha) return that.$util.Tips({
+					title: '请输入验证码'
+				});
+				if (!/^[\w\d]+$/i.test(that.captcha)) return that.$util.Tips({
+					title: '请输入正确的验证码'
+				});
+				if (!that.password) return that.$util.Tips({
+					title: '请输入密码'
+				});
+				if (!/^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,16}$/i.test(that.password)) return that.$util.Tips({
+					title: '请输入6-16位字母加数字组合'
+				});
+				if (!that.isAgree) return that.$util.Tips({
+					title: '请勾选用户协议与隐私政策'
+				});
+				console.log('绑定前', {
+					auth_token: this.auth_token || uni.getStorageSync('auth_token'),
+					phone: that.account,
+					sms_code: that.captcha,
+					pwd: that.password,
+					spread: that.$Cache.get("spread"),
+					// #ifdef APP-PLUS
+					user_type: 'app',
+					// #endif
+					// #ifdef H5
+					user_type: 'h5',
+					// #endif
+				});
+				userMerge({
+						auth_token: this.auth_token || uni.getStorageSync('auth_token'),
+						phone: that.account,
+						sms_code: that.captcha,
+						pwd: that.password,
+						spread: that.$Cache.get("spread"),
+						// #ifdef APP-PLUS
+						user_type: 'app',
+						// #endif
+						// #ifdef H5
+						user_type: 'h5',
+						// #endif
+					})
+					.then(res => {
+						console.log(res);
+						that.$store.commit("LOGIN", {
+							'token': res.data.token,
+							'time': res.data.exp
+						});
+						that.$store.commit("SETUID", res.data.user.uid);
+						that.$store.commit('UPDATE_USERINFO', res.data.user);
+						const backUrl = that.$Cache.get('login_back_url_weixin') || that.$Cache.get(BACK_URL) ||
+							"/pages/index/index";
+						that.$Cache.clear(BACK_URL);
+						that.$Cache.clear('login_back_url_weixin');
+						let method
+						let indexPat = ['/pages/index/index', '/pages/order_addcart/order_addcart',
+							'/pages/goods_cate/goods_cate',
+							'/pages/user/index'
+						]
+						if (indexPat.includes(this.getPath(backUrl))) {
+							method = 'switchTab'
+						} else {
+							method = 'navigateTo'
+						}
+						uni[method]({
+							url: backUrl,
+							success: () => {
+								this.auth_token = ''
+							}
+						});
+					})
+					.catch(res => {
+						console.log('error', err);
 						that.$util.Tips({
 							title: res
 						});
 					});
 			},
-      async weixinMerge() {
-      	let that = this;
-      	if (!that.account) return that.$util.Tips({
-      		title: '请输入手机号码'
-      	});
-      	if (!/^1(3|4|5|7|8|9|6)\d{9}$/i.test(that.account)) return that.$util.Tips({
-      		title: '请输入正确的手机号码'
-      	});
-      	if (!that.captcha) return that.$util.Tips({
-      		title: '请输入验证码'
-      	});
-      	if (!/^[\w\d]+$/i.test(that.captcha)) return that.$util.Tips({
-      		title: '请输入正确的验证码'
-      	});
-      	if (!that.password) return that.$util.Tips({
-      		title: '请输入密码'
-      	});
-      	if (!/^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,16}$/i.test(that.password)) return that.$util.Tips({
-      		title: '请输入6-16位字母加数字组合'
-      	});
-      	if (!that.isAgree) return that.$util.Tips({
-      		title: '请勾选用户协议与隐私政策'
-      	});
-        console.log('绑定前', {
-      			auth_token: this.auth_token || uni.getStorageSync('auth_token'),
-      			phone: that.account,
-      			sms_code: that.captcha,
-      			pwd: that.password,
-      			spread: that.$Cache.get("spread"),
-      			// #ifdef APP-PLUS
-      			user_type: 'app',
-      			// #endif
-      			// #ifdef H5
-      			user_type: 'h5',
-      			// #endif
-      		});
-      	userMerge({
-      			auth_token: this.auth_token || uni.getStorageSync('auth_token'),
-      			phone: that.account,
-      			sms_code: that.captcha,
-      			pwd: that.password,
-      			spread: that.$Cache.get("spread"),
-      			// #ifdef APP-PLUS
-      			user_type: 'app',
-      			// #endif
-      			// #ifdef H5
-      			user_type: 'h5',
-      			// #endif
-      		})
-      		.then(res => {
-            console.log(res);
-      			that.$store.commit("LOGIN", {
-      				'token': res.data.token,
-      				'time': res.data.exp
-      			});
-      			that.$store.commit("SETUID", res.data.user.uid);
-      			that.$store.commit('UPDATE_USERINFO', res.data.user);
-      			const backUrl = that.$Cache.get('login_back_url_weixin') || that.$Cache.get(BACK_URL) || "/pages/index/index";
-      			that.$Cache.clear(BACK_URL);
-      			that.$Cache.clear('login_back_url_weixin');
-            let method
-            let indexPat = ['/pages/index/index', '/pages/order_addcart/order_addcart',
-            	'/pages/goods_cate/goods_cate',
-            	'/pages/user/index'
-            ]
-            if (indexPat.includes(this.getPath(backUrl))) {
-            	method = 'switchTab'
-            } else {
-            	method = 'navigateTo'
-            }
-            uni[method]({
-            	url: backUrl,
-              success:()=>{
-                this.auth_token = ''
-              }
-            });
-      		})
-      		.catch(res => {
-            console.log('error', err);
-      			that.$util.Tips({
-      				title: res
-      			});
-      		});
-      },
 			async code(data) {
 				let that = this;
 				if (!that.account) return that.$util.Tips({
@@ -952,7 +1028,7 @@
 				// if (that.formItem == 2) that.type = "register";
 				await registerVerify({
 						phone: that.account,
-						type: 'login',
+						type: that.type,
 						key: that.keyCode,
 						// code: that.codeVal,
 						toke: data.token,
@@ -971,6 +1047,38 @@
 						});
 					});
 			},
+			async registerReset() {
+				var that = this;
+				if (!that.account) return that.$util.Tips({
+					title: '请填写手机号码'
+				});
+				if (!/^1(3|4|5|7|8|9|6)\d{9}$/i.test(that.account)) return that.$util.Tips({
+					title: '请输入正确的手机号码'
+				});
+				if (that.password == '123456') return that.$util.Tips({
+					title: '您输入的密码过于简单'
+				});
+				if (that.password != that.confirm_pwd) return that.$util.Tips({
+					title: '两次密码不一致'
+				});
+				if (!that.captcha) return that.$util.Tips({
+					title: '请填写验证码'
+				});
+				registerForget({
+						phone: that.account,
+						sms_code: that.captcha,
+						pwd: that.password,
+						confirm_pwd: that.confirm_pwd
+					})
+					.then(res => {
+						that.submitSuccess(res.data)
+					})
+					.catch(res => {
+						that.$util.Tips({
+							title: res
+						})
+					});
+			},
 			getcaptcha() {
 				let that = this
 				getCaptcha().then(data => {
@@ -989,6 +1097,8 @@
 				}
 				return url
 			},
+
+			// 账号登录
 			async submit() {
 				let that = this;
 				if (!that.account) return that.$util.Tips({
@@ -1012,51 +1122,58 @@
 					.then(({
 						data
 					}) => {
-						this.checkOpenId(data.user)
-						const backUrl = that.$Cache.get('login_back_url_weixin') || that.$Cache.get(BACK_URL) || "/pages/index/index";
-						that.$store.commit("LOGIN", {
-							'token': data.token,
-							'time': data.exp
-						});
-						that.$store.commit("SETUID", data.user.uid);
-						that.$store.commit('UPDATE_USERINFO', data.user);
-
-            if(data.is_new_user && !that.$Cache.get('login_back_url_weixin')){
-              return uni.navigateTo({
-                url: '/pages/helpPeople/helpPeople'
-              })
-            }
-            
-            that.$Cache.clear(BACK_URL);
-            that.$Cache.clear('login_back_url_weixin');
-            
-						let method
-						let indexPat = ['/pages/index/index', '/pages/order_addcart/order_addcart',
-							'/pages/goods_cate/goods_cate',
-							'/pages/user/index'
-						]
-						if (indexPat.includes(this.getPath(backUrl))) {
-							method = 'switchTab'
-						} else {
-							method = 'navigateTo'
-						}
-            
-						if (this.getPath(backUrl) === '/pages/users/login/index') {
-							uni.switchTab({
-								url: '/pages/index/index'
-							});
-							return
-						}
-						uni[method]({
-							url: backUrl
-						});
+						this.submitSuccess(data)
 					})
 					.catch(e => {
-						that.$util.Tips({
-							title: e
-						});
+						that.showTipsFn("密码错误", e)
 					});
 			},
+
+			// 账号密码验证通过后的逻辑
+			submitSuccess(data) {
+				console.log(data, 'hanshu')
+				let that = this
+				this.checkOpenId(data.user)
+				const backUrl = that.$Cache.get('login_back_url_weixin') || that.$Cache.get(BACK_URL) ||
+					"/pages/index/index";
+				that.$store.commit("LOGIN", {
+					'token': data.token,
+					'time': data.exp
+				});
+				that.$store.commit("SETUID", data.user.uid);
+				that.$store.commit('UPDATE_USERINFO', data.user);
+
+				if (data.is_new_user && !that.$Cache.get('login_back_url_weixin')) {
+					return uni.navigateTo({
+						url: '/pages/helpPeople/helpPeople'
+					})
+				}
+
+				that.$Cache.clear(BACK_URL);
+				that.$Cache.clear('login_back_url_weixin');
+
+				let method
+				let indexPat = ['/pages/index/index', '/pages/order_addcart/order_addcart',
+					'/pages/goods_cate/goods_cate',
+					'/pages/user/index'
+				]
+				if (indexPat.includes(this.getPath(backUrl))) {
+					method = 'switchTab'
+				} else {
+					method = 'navigateTo'
+				}
+
+				if (this.getPath(backUrl) === '/pages/users/login/index') {
+					uni.switchTab({
+						url: '/pages/index/index'
+					});
+					return
+				}
+				uni[method]({
+					url: backUrl
+				});
+			},
+
 			getVersion() {
 				getVersion().then(data => {
 					this.copyright = data.data;
@@ -1082,34 +1199,34 @@
 			checkOpenId(user) {
 				if (user.wechat_user_id === 0) {
 					let that = this
-					try{
-					  wx.getUserInfo({
-					  	success: function(res) {
-					  		const encryptedData = res.encryptedData
-					  		const iv = res.iv
-					  		wx.login({
-					  			success(res) {
-					  				if (res.code) {
-					  					bindMp({
-					  						code: res.code,
-					  						iv: iv,
-					  						encryptedData: encryptedData,
-					  						phone: that.account
-					  					}).then(res => {
-					  						// console.log(res);
-					  					})
-					  				} else {
-					  					// console.log('登录失败!' + res.errMsg)
-					  				}
-					  			}
-					  		})
-					  	},
-					  	fail(e) {
-					  		// console.log('登录失败!' + res.errMsg)
-					  	}
-					  })
-					}catch(e){
-					  console.log(e);
+					try {
+						wx.getUserInfo({
+							success: function(res) {
+								const encryptedData = res.encryptedData
+								const iv = res.iv
+								wx.login({
+									success(res) {
+										if (res.code) {
+											bindMp({
+												code: res.code,
+												iv: iv,
+												encryptedData: encryptedData,
+												phone: that.account
+											}).then(res => {
+												// console.log(res);
+											})
+										} else {
+											// console.log('登录失败!' + res.errMsg)
+										}
+									}
+								})
+							},
+							fail(e) {
+								// console.log('登录失败!' + res.errMsg)
+							}
+						})
+					} catch (e) {
+						console.log(e);
 					}
 				}
 				// #ifdef APP-PLUS
@@ -1119,16 +1236,69 @@
 						bindJG({
 							phone: this.account,
 							jg_register_id: result.registerID
-						}).then(res=>{
-              console.log("绑定成功", res);
-            }).catch(err=>{
-              console.log("绑定失败", err);
-            })
+						}).then(res => {
+							console.log("绑定成功", res);
+						}).catch(err => {
+							console.log("绑定失败", err);
+						})
 					}
 				})
 				// #endif
 
+			},
+			// app手机号一键登录
+			appOneClcik() {
+				let that = this
+				uni.preLogin({
+					provider: 'univerify',
+					success() {
+						console.log("当前环境支持一键登录")
+						uni.login({
+							provider: 'univerify',
+							univerifyStyle: oneClickStyle,
+							success(res) {
+								console.log(res, 'res')
+								phonelogin({
+									access_token: res.authResult.access_token,
+									openid: res.authResult.openid,
+									auth_token: that.auth_token,
+									user_type: 'app'
+								}).then(res => {
+									uni.closeAuthView()
+									that.submitSuccess(res.data)
+								}).catch(err => {
+									uni.closeAuthView()
+									that.$util.Tips({
+										title: '登录失败,请稍后再试'
+									});
+								})
+								// uniCloud.callFunction({
+								// 	name: 'oneClickLoginFn', 
+								// 	data: {
+								// 		'access_token': res.authResult
+								// 			.access_token, 
+								// 		'openid': res.authResult.openid 
+								// 	}
+								// }).then(res => {
+								// 	console.log(res, '登录成功后的res')
+								// }).catch(err => {
+								// 	console.log(err, 'ererre')
+								// })
+							},
+							fail(res) { // 登录失败
+								console.log(res.errCode)
+								console.log(res.errMsg)
+							}
+						})
+					},
+					fail(res) {
+						that.$util.Tips({
+							title: '当前环境不支持一键登录'
+						});
+					}
+				})
 			}
+
 		}
 	};
 </script>
@@ -1140,15 +1310,15 @@
 	/deep/uni-checkbox .uni-checkbox-input {
 		border-radius: 100%;
 	}
-  
-  .ChangePassword{
-    .title{
-      width: 580rpx;
-      margin: 180rpx auto 0 auto;
-      font-size: 46rpx;
-      color: #7f7f7f;
-    }
-  }
+
+	.ChangePassword {
+		.title {
+			width: 580rpx;
+			margin: 180rpx auto 0 auto;
+			font-size: 46rpx;
+			color: #7f7f7f;
+		}
+	}
 
 	.ChangePassword .phone {
 		font-size: 32rpx;
@@ -1450,8 +1620,8 @@
 
 		.whiteBg {
 			margin-top: 100rpx;
-      transition: 300ms;
-      
+			transition: 300ms;
+
 			.list {
 				border-radius: 16rpx;
 				overflow: hidden;
@@ -1515,4 +1685,43 @@
 			font-size: 20rpx;
 		}
 	}
+
+	.footer-btns {
+		position: absolute;
+		bottom: 160rpx;
+		left: 50%;
+		transform: translate(-50%);
+		display: flex;
+		justify-content: space-between;
+		width: 750rpx !important;
+		padding: 0 112rpx;
+
+		.login-type-btn {
+			padding: 12rpx 30rpx;
+			border-radius: 32rpx;
+			background-color: #F6F6F6
+		}
+
+		.actLoginType {
+			color: #20B128;
+			background-color: #E8F7E9;
+		}
+	}
+
+	.tips {
+		width: 590rpx;
+		height: 354rpx;
+		background-color: white;
+		border-radius: 16rpx;
+		position: absolute;
+		top: 50%;
+		left: 50%;
+		transform: translate(-50%, -50%);
+		box-sizing: border-box;
+		padding: 50rpx 40rpx;
+		display: flex;
+		flex-direction: column;
+		justify-content: space-between;
+		align-items: center;
+	}
 </style>
\ No newline at end of file
diff --git a/pages/users/login/oneClickStyle.js b/pages/users/login/oneClickStyle.js
new file mode 100644
index 0000000..4807592
--- /dev/null
+++ b/pages/users/login/oneClickStyle.js
@@ -0,0 +1,69 @@
+let customStyle = {
+	"fullScreen": true, // 是否全屏显示,默认值: false
+	"backgroundColor": "#ffffff", // 授权页面背景颜色,默认值:#ffffff
+	"backgroundImage": "", // 全屏显示的背景图片,默认值:"" (仅支持本地图片,只有全屏显示时支持)
+	"icon": {
+		"path": "static/xxx.png", // 自定义显示在授权框中的logo,仅支持本地图片 默认显示App logo
+		"width": "60px", //图标宽度 默认值:60px
+		"height": "60px" //图标高度 默认值:60px
+	},
+	"closeIcon": {
+		"path": "static/xxx.png", // 自定义显示在授权框中的logo,仅支持本地图片 默认显示App logo
+		"width": "60px", //图标宽度 默认值:60px (HBuilderX 4.0支持)
+		"height": "60px" //图标高度 默认值:60px (HBuilderX 4.0支持)
+	},
+	"phoneNum": {
+		"color": "#202020" // 手机号文字颜色 默认值:#202020
+	},
+	"slogan": {
+		"color": "#BBBBBB" //  slogan 字体颜色 默认值:#BBBBBB
+	},
+	"authButton": {
+		"normalColor": "#3CB625", // 授权按钮正常状态背景颜色 默认值:#3479f5
+		"highlightColor": "#2861c5", // 授权按钮按下状态背景颜色 默认值:#2861c5(仅ios支持)
+		"disabledColor": "#73aaf5", // 授权按钮不可点击时背景颜色 默认值:#73aaf5(仅ios支持)
+		"textColor": "#ffffff", // 授权按钮文字颜色 默认值:#ffffff
+		"title": "本机号码一键登录", // 授权按钮文案 默认值:“本机号码一键登录”
+		"borderRadius": "24px" // 授权按钮圆角 默认值:"24px" (按钮高度的一半)
+	},
+	"otherLoginButton": {
+		"visible": true, // 是否显示其他登录按钮,默认值:true
+		"normalColor": "", // 其他登录按钮正常状态背景颜色 默认值:透明
+		"highlightColor": "", // 其他登录按钮按下状态背景颜色 默认值:透明
+		"textColor": "#656565", // 其他登录按钮文字颜色 默认值:#656565
+		"title": "其他登录方式", // 其他登录方式按钮文字 默认值:“其他登录方式”
+		"borderColor": "", //边框颜色 默认值:透明(仅iOS支持)
+		"borderRadius": "0px" // 其他登录按钮圆角 默认值:"24px" (按钮高度的一半)
+	},
+	"privacyTerms": {
+		"defaultCheckBoxState": true, // 条款勾选框初始状态 默认值: true
+		"isCenterHint": false, //未勾选服务条款时点击登录按钮的提示是否居中显示 默认值: false (3.7.13+ 版本支持)
+		"uncheckedImage": "", // 可选 条款勾选框未选中状态图片(仅支持本地图片 建议尺寸 24x24px)(3.2.0+ 版本支持)
+		"checkedImage": "", // 可选 条款勾选框选中状态图片(仅支持本地图片 建议尺寸24x24px)(3.2.0+ 版本支持)
+		"checkBoxSize": 12, // 可选 条款勾选框大小
+		"textColor": "#BBBBBB", // 文字颜色 默认值:#BBBBBB
+		"termsColor": "#5496E3", //  协议文字颜色 默认值: #5496E3
+		"prefix": "我已阅读并同意", // 条款前的文案 默认值:“我已阅读并同意”
+		"suffix": "并使用本机号码登录", // 条款后的文案 默认值:“并使用本机号码登录”
+		"privacyItems": [ // 自定义协议条款,最大支持2个,需要同时设置url和title. 否则不生效
+			{
+				"url": "https://", // 点击跳转的协议详情页面
+				"title": "用户服务协议" // 协议名称
+			}
+		]
+	},
+	"buttons": { // 自定义页面下方按钮仅全屏模式生效(3.1.14+ 版本支持)
+		"iconWidth": "45px", // 图标宽度(高度等比例缩放) 默认值:45px
+		"list": [{
+				"provider": "apple",
+				"iconPath": "/static/apple.png" // 图标路径仅支持本地图片
+			},
+			{
+				"provider": "weixin",
+				"iconPath": "/static/wechat.png" // 图标路径仅支持本地图片
+			}
+		]
+	}
+}
+
+export default customStyle
\ No newline at end of file
diff --git a/pages/users/refund/detail.vue b/pages/users/refund/detail.vue
index 7ca85e0..2b99825 100644
--- a/pages/users/refund/detail.vue
+++ b/pages/users/refund/detail.vue
@@ -15,9 +15,9 @@
 			</block>
 			<block v-if="type == 2">
 				<view class="txt">请等待商家收货并退款</view>
-				<view class="time">还剩:				
-				<countDown :is-day="true" :tip-text="' '" :day-text="'天'" :hour-text="':'" :minute-text="':'" :second-text="' '"
-				 :datatime="datatime"></countDown>
+				<view class="time">还剩:
+					<countDown :is-day="true" :tip-text="' '" :day-text="'天'" :hour-text="':'" :minute-text="':'"
+						:second-text="' '" :datatime="datatime"></countDown>
 				</view>
 			</block>
 			<block v-if="type == 3">
@@ -59,12 +59,17 @@
 			<view class="title">退款信息</view>
 			<view class="product-box">
 				<view class="product-item" v-for="(item,index) in detail.refundProduct" :key="index">
-					<image class="img-box" :src="item.product.cart_info.productAttr.image" mode="" v-if="item.product.cart_info.productAttr.image"></image>
+					<image class="img-box" :src="item.product.cart_info.productAttr.image" mode=""
+						v-if="item.product.cart_info.productAttr.image"></image>
 					<image class="img-box" :src="item.product.cart_info.product.image" mode="" v-else></image>
 					<view class="msg">
-						<view class="name line1"><text v-if="item.product.cart_info.product_type === 2" class="event_name event_bg">预售</text>{{item.product.cart_info.product.store_name}}</view>
+						<view class="name line1"><text v-if="item.product.cart_info.product_type === 2"
+								class="event_name event_bg">预售</text>{{item.product.cart_info.product.store_name}}
+						</view>
 						<view class="des">{{item.product.cart_info.productAttr.sku}}</view>
-						<view class="price">¥{{item.product.product_type == 3 ? item.product.cart_info.productAssistAttr.assist_price : item.product.product_type == 4 ? item.product.cart_info.activeSku.active_price : item.product.cart_info.productAttr.price}}</view>
+						<view class="price">
+							¥{{item.product.product_type == 3 ? item.product.cart_info.productAssistAttr.assist_price : item.product.product_type == 4 ? item.product.cart_info.activeSku.active_price : item.product.cart_info.productAttr.price}}
+						</view>
 						<view class="num">x {{item.refund_num}}</view>
 					</view>
 				</view>
@@ -76,10 +81,10 @@
 				<view class="txt flex">
 					<text>{{detail.refund_order_sn}}</text>
 					<!-- #ifdef H5 -->
-						<text class='copy copy-data' :data-clipboard-text="detail.refund_order_sn">复制</text>
+					<text class='copy copy-data' :data-clipboard-text="detail.refund_order_sn">复制</text>
 					<!-- #endif -->
 					<!-- #ifdef MP -->
-						<text class='copy' @tap='copy'>复制</text>
+					<text class='copy' @tap='copy'>复制</text>
 					<!-- #endif -->
 				</view>
 			</view>
@@ -95,6 +100,13 @@
 					<text>{{detail.refund_num}}</text>
 				</view>
 			</view>
+
+			<view class="item">
+				<view class="label">退款原因:</view>
+				<view class="txt flex">
+					<text>{{ getRightText(detail.refund_message)   }}</text>
+				</view>
+			</view>
 			<view class="item">
 				<view class="label">申请时间:</view>
 				<view class="txt flex">
@@ -116,7 +128,7 @@
 				</view>
 			</view>
 			<view class="btn-wrapper">
-				<block v-if="type==-1">	
+				<block v-if="type==-1">
 					<view class="btn" @click="applyAgain(detail)">再次申请</view>
 				</block>
 				<block v-else-if="type==1">
@@ -148,35 +160,40 @@
 	// +----------------------------------------------------------------------
 	// | Author: CRMEB Team <admin@crmeb.com>
 	// +----------------------------------------------------------------------
-	import { refundDetail, refundCancelApi } from '@/api/order.js'
+	import {
+		refundDetail,
+		refundCancelApi
+	} from '@/api/order.js'
 	import ClipboardJS from "@/plugin/clipboard/clipboard.js";
 	import countDown from '@/components/countDown'
-	import { mapGetters } from "vuex";
-	export default{
+	import {
+		mapGetters
+	} from "vuex";
+	export default {
 		components: {
-			countDown,	
+			countDown,
 		},
-		computed:{
+		computed: {
 			...mapGetters(['viewColor']),
 		},
-		data(){
-			return{
-				type:0,
-				refund_order_id:0,
-				detail:'',
+		data() {
+			return {
+				type: 0,
+				refund_order_id: 0,
+				detail: '',
 				datatime: 0
 			}
 		},
 		onLoad(options) {
 			uni.setNavigationBarTitle({
-			  title:'退款详情'
+				title: '退款详情'
 			})
 			this.refund_order_id = options.id
 			this.getDetail()
 		},
 		onReady: function() {
 			// #ifdef H5
-			this.$nextTick(function() {				
+			this.$nextTick(function() {
 				const clipboard = new ClipboardJS(".copy-data");
 				clipboard.on("success", () => {
 					this.$util.Tips({
@@ -186,57 +203,65 @@
 			});
 			// #endif
 		},
-		methods:{
+		methods: {
+			getRightText(str) {
+				const index = str.indexOf("@");
+				if (index !== -1) {
+					return str.substring(0, index);
+				} else {
+					return str
+				}
+			},
 			//联系客服拨打电话
-			call: function(service){
+			call: function(service) {
 				let that = this;
-				if(service){
+				if (service) {
 					uni.showModal({
 						title: '提示',
-						content: '暂无在线客服,确定拨打客服电话:'+that.detail.merchant.service_phone+'吗?',
+						content: '暂无在线客服,确定拨打客服电话:' + that.detail.merchant.service_phone + '吗?',
 						success: function(res) {
 							if (res.confirm) {
 								uni.makePhoneCall({
-								  phoneNumber: that.detail.merchant.service_phone,
+									phoneNumber: that.detail.merchant.service_phone,
 								});
 							}
 						}
 					})
-				}else{
+				} else {
 					return that.$util.Tips({
 						title: '暂无可用客服'
 					})
 				}
 			},
 			//查看大图
-			loookImg(item,index){
+			loookImg(item, index) {
 				uni.previewImage({
 					urls: this.detail.pics,
 					current: this.detail.pics[index]
 				});
 			},
-			getDetail(){
-				refundDetail(this.refund_order_id).then(res=>{
+			getDetail() {
+				refundDetail(this.refund_order_id).then(res => {
 					// status 0审核中 1待发货 2待收货 3已退款 -1已拒绝 
 					this.type = res.data.status
 					this.detail = res.data
 					this.datatime = res.data.auto_refund_time;
-					
+
 				})
 			},
-			goPage(){
+			goPage() {
 				uni.navigateTo({
-					url:'/pages/users/refund/goods/index?id='+this.detail.refund_order_id
+					url: '/pages/users/refund/goods/index?id=' + this.detail.refund_order_id
 				})
 			},
-			applyAgain(item){
+			applyAgain(item) {
 				uni.navigateTo({
-					url:`/pages/order_details/index?order_id=${item.refundProduct[0].product.order_id}`
+					url: `/pages/order_details/index?order_id=${item.refundProduct[0].product.order_id}`
 				})
 			},
-			go(){
+			go() {
 				uni.navigateTo({
-					url:`/pages/users/refund/logistics?orderId=${this.detail.refund_order_id}`
+					url: `/pages/users/refund/logistics?orderId=${this.detail.refund_order_id}`
 				})
 			},
 			/**
@@ -252,30 +277,30 @@
 			},
 			// #endif
 			// 客服
-			goService(){
+			goService() {
 				uni.navigateTo({
-					url:`/pages/chat/customer_list/chat?mer_id=${this.detail.mer_id}&uid=${this.detail.uid}&refund_order_id=${this.detail.refund_order_id}`
+					url: `/pages/chat/customer_list/chat?mer_id=${this.detail.mer_id}&uid=${this.detail.uid}&refund_order_id=${this.detail.refund_order_id}`
 				})
 			},
 			// 取消售后
-			cancelSales(){
+			cancelSales() {
 				let that = this;
 				uni.showModal({
-				  content: '确定要取消售后?',
-				  success: function(res) {
-				    if(res.confirm) {
-				      refundCancelApi(that.detail.refund_order_id).then(res => {
-				      	if (res.status === 200) {
-				      		that.$util.Tips({
-				      			title: res.message
-				      		});
+					content: '确定要取消售后?',
+					success: function(res) {
+						if (res.confirm) {
+							refundCancelApi(that.detail.refund_order_id).then(res => {
+								if (res.status === 200) {
+									that.$util.Tips({
+										title: res.message
+									});
 									that.getDetail();
 								}
-				      })
-				    } else if(res.cancel) {
-				      console.log('用户点击取消');
-				    }
-				  }
+							})
+						} else if (res.cancel) {
+							console.log('用户点击取消');
+						}
+					}
 				});
 			},
 		}
@@ -283,217 +308,251 @@
 </script>
 
 <style lang="scss">
-.refund-detail{
-	.head{
-		display: flex;
-		flex-direction: column;
-		justify-content: center;
-		height: 150rpx;
-		padding: 0 30rpx;
-		color: #fff;
-		background-color: #666666;
-		font-size: 30rpx;
-		.txt{
-			font-weight: bold;
+	.refund-detail {
+		.head {
+			display: flex;
+			flex-direction: column;
+			justify-content: center;
+			height: 150rpx;
+			padding: 0 30rpx;
+			color: #fff;
+			background-color: #666666;
+			font-size: 30rpx;
+
+			.txt {
+				font-weight: bold;
+			}
+
+			.time {
+				margin-top: 10rpx;
+				font-size: 24rpx;
+				opacity: .8;
+
+				.time {
+					display: inline-block;
+					width: 600rpx;
+
+					/deep/ .red {
+						color: #fff;
+					}
+				}
+			}
 		}
-		.time{
-			margin-top: 10rpx;
-			font-size: 24rpx;
-			opacity: .8;
-			.time{
-				display: inline-block;
-				width: 600rpx;
-				/deep/ .red{
+
+		.info-box {
+			margin-top: 12rpx;
+			background-color: #fff;
+
+			.title {
+				padding: 0 32rpx;
+				line-height: 86rpx;
+				border-bottom: 1px solid #F0F0F0;
+				color: #282828;
+			}
+
+			.product-box {
+				.product-item {
+					display: flex;
+					padding: 25rpx 30rpx;
+
+					.img-box {
+						width: 130rpx;
+						height: 130rpx;
+						border-radius: 16rpx;
+					}
+
+					.msg {
+						position: relative;
+						display: flex;
+						flex-direction: column;
+						justify-content: space-between;
+						width: 440rpx;
+						margin-left: 26rpx;
+
+						.name {
+							font-size: 28rpx;
+							color: #282828;
+						}
+
+						.des {
+							font-size: 20rpx;
+							color: #868686;
+						}
+
+						.price {
+							font-size: 26rpx;
+							color: var(--view-priceColor);
+						}
+
+						.num {
+							position: absolute;
+							right: -80rpx;
+							top: 4rpx;
+							color: #868686;
+							font-size: 26rpx;
+						}
+					}
+				}
+
+				.event_name {
+					display: inline-block;
+					margin-right: 9rpx;
+					color: #fff;
+					font-size: 20rpx;
+					padding: 0 8rpx;
+					line-height: 30rpx;
+					text-align: center;
+					border-radius: 6rpx;
+				}
+			}
+
+			.event_bg {
+				background: #FF7F00;
+			}
+
+			.store-info {
+				padding: 30rpx;
+
+				.des {
+					margin-top: 10rpx;
+					font-size: 26rpx;
+					color: #868686;
+				}
+
+				.red-txt {
+					display: flex;
+					align-items: center;
+					margin-top: 10rpx;
+					color: $theme-color;
+					font-size: 24rpx;
+
+					.iconfont {
+						font-size: 30rpx;
+						margin-right: 5rpx;
+						margin-top: 6rpx;
+					}
+				}
+			}
+		}
+
+		.content {
+			margin-top: 12rpx;
+			padding: 30rpx 30rpx 0;
+			background-color: #FFFFFF;
+
+			.item {
+				display: flex;
+				justify-content: space-between;
+				margin-bottom: 30rpx;
+
+				.txt {
+					justify-content: flex-end;
+					align-items: center;
+					width: 450rpx;
+					color: #868686;
+					text-align: right;
+
+					.copy {
+						display: flex;
+						align-items: center;
+						justify-content: center;
+						width: 80rpx;
+						height: 34rpx;
+						margin-left: 20rpx;
+						border: 1px solid #666666;
+						border-radius: 17rpx;
+						font-size: 20rpx;
+						color: #333;
+					}
+				}
+
+				&:last-child {
+					margin-bottom: 0;
+				}
+
+				.upload-img {
+					display: flex;
+					flex-wrap: wrap;
+					margin-top: 20rpx;
+
+					.img-item {
+						position: relative;
+						width: 156rpx;
+						height: 156rpx;
+						margin-right: 23rpx;
+						margin-top: 20rpx;
+
+						&:nth-child(4n) {
+							margin-right: 0;
+						}
+
+						image {
+							width: 156rpx;
+							height: 156rpx;
+							border-radius: 8rpx;
+						}
+					}
+				}
+			}
+
+			.btn-wrapper {
+				position: relative;
+				display: flex;
+				justify-content: flex-end;
+				align-items: center;
+				height: 100rpx;
+
+				button {
+					font-size: 28rpx;
+				}
+
+				.btn {
+					width: 176rpx;
+					height: 60rpx;
+					display: flex;
+					align-items: center;
+					justify-content: center;
+					margin-left: 20rpx;
+					background: var(--view-theme);
+					border-radius: 30rpx;
 					color: #fff;
 				}
+
+				.gray {
+					background: transparent;
+					border: 1px solid #eee;
+					color: #AAAAAA;
+				}
+
+				&:after {
+					content: ' ';
+					position: absolute;
+					top: 0;
+					left: 50%;
+					width: 690rpx;
+					height: 1px;
+					margin-left: -345rpx;
+					background-color: #f0f0f0;
+				}
+			}
+		}
+
+		.box {
+			margin-top: 12rpx;
+			padding: 25rpx 30rpx;
+			background-color: #fff;
+			font-size: 30rpx;
+			color: #282828;
+
+			.des {
+				margin-top: 5rpx;
+				font-size: 26rpx;
+				color: #868686;
 			}
 		}
 	}
 
-	.info-box{
-		margin-top: 12rpx;
-		background-color: #fff;
-		.title{
-			padding: 0 32rpx;
-			line-height: 86rpx;
-			border-bottom: 1px solid #F0F0F0;
-			color: #282828;
-		}
-		.product-box{
-			.product-item{
-				display: flex;
-				padding: 25rpx 30rpx;
-				.img-box{
-					width:130rpx;
-					height:130rpx;
-					border-radius:16rpx;
-				}
-				.msg{
-					position: relative;
-					display: flex;
-					flex-direction: column;
-					justify-content: space-between;
-					width: 440rpx;
-					margin-left: 26rpx;
-					.name{
-						font-size: 28rpx;
-						color: #282828;
-					}
-					.des{
-						font-size: 20rpx;
-						color: #868686;
-					}
-					.price{
-						font-size: 26rpx;
-						color: var(--view-priceColor);
-					}
-					.num{
-						position: absolute;
-						right: -80rpx;
-						top: 4rpx;
-						color: #868686;
-						font-size: 26rpx;
-					}
-				}
-			}			
-			.event_name{
-				display: inline-block;
-				margin-right: 9rpx;
-				color: #fff;
-				font-size: 20rpx;
-				padding: 0 8rpx;
-				line-height: 30rpx;	
-				text-align: center;
-				border-radius: 6rpx;						
-			}
-		}
-		
-		.event_bg{
-			background: #FF7F00;
-		}
-		.store-info{
-			padding: 30rpx;
-			.des{
-				margin-top: 10rpx;
-				font-size: 26rpx;
-				color: #868686;
-			}
-			.red-txt{
-				display: flex;
-				align-items: center;
-				margin-top: 10rpx;
-				color: $theme-color;
-				font-size: 24rpx;
-				.iconfont{
-					font-size: 30rpx;
-					margin-right: 5rpx;
-					margin-top: 6rpx;
-				}
-			}
-		}
+	/deep/.styleAll {
+		color: #fff;
 	}
-	.content{
-		margin-top: 12rpx;
-		padding: 30rpx 30rpx 0;
-		background-color: #FFFFFF;
-		.item{
-			display: flex;
-			justify-content: space-between;
-			margin-bottom: 30rpx;
-			.txt{
-				justify-content: flex-end;
-				align-items: center;
-				width: 450rpx;
-				color: #868686;
-				text-align: right;
-				.copy{
-					display: flex;
-					align-items: center;
-					justify-content: center;
-					width:80rpx;
-					height:34rpx;
-					margin-left: 20rpx;
-					border:1px solid #666666;
-					border-radius:17rpx;
-					font-size: 20rpx;
-					color: #333;
-				}
-			}
-			&:last-child{
-				margin-bottom: 0;
-			}
-			.upload-img{
-				display: flex;
-				flex-wrap: wrap;
-				margin-top: 20rpx;
-				.img-item{
-					position: relative;
-					width: 156rpx;
-					height: 156rpx;
-					margin-right: 23rpx;
-					margin-top: 20rpx;
-					&:nth-child(4n){
-						margin-right: 0;
-					}
-					image{
-						width: 156rpx;
-						height: 156rpx;
-						border-radius: 8rpx;
-					}
-				}
-			}
-		}	
-		.btn-wrapper{
-			position: relative;
-			display: flex;
-			justify-content: flex-end;
-			align-items: center;
-			height: 100rpx;
-			button{
-				font-size: 28rpx;
-			}
-			.btn{
-				width:176rpx;
-				height:60rpx;
-				display: flex;
-				align-items: center;
-				justify-content: center;
-				margin-left: 20rpx;
-				background: var(--view-theme);
-				border-radius:30rpx;
-				color: #fff;
-			}
-			.gray{
-				background: transparent;
-				border: 1px solid #eee;
-				color: #AAAAAA;
-			}
-			&:after{
-				content:' ';
-				position: absolute;
-				top: 0;
-				left: 50%;
-				width: 690rpx;
-				height:1px;
-				margin-left: -345rpx;
-				background-color: #f0f0f0;
-			}
-		}
-	}
-	.box{
-		margin-top: 12rpx;
-		padding:25rpx 30rpx;
-		background-color: #fff;
-		font-size: 30rpx;
-		color: #282828;
-		.des{
-			margin-top: 5rpx;
-			font-size: 26rpx;
-			color: #868686;
-		}
-	}
-}
-/deep/.styleAll{
-	color: #fff;
-}
-</style>
+</style>
\ No newline at end of file
diff --git a/uniCloud-aliyun/cloudfunctions/oneClickLoginFn/index.js b/uniCloud-aliyun/cloudfunctions/oneClickLoginFn/index.js
new file mode 100644
index 0000000..51899fb
--- /dev/null
+++ b/uniCloud-aliyun/cloudfunctions/oneClickLoginFn/index.js
@@ -0,0 +1,35 @@
+// 下面仅展示客户端使用post方式发送content-type为application/json请求的场景
+exports.main = async (event) => {
+	let body = event.body
+	if (event.isBase64Encoded) {
+		body = Buffer.from(body, 'base64')
+	}
+	const {
+		access_token,
+		openid
+	} = JSON.parse(body)
+	if (!access_token || !openid) {
+		return { // 不建议把完整手机号返回给前端
+			success: false,
+			error: {
+				code: 'params is not fund',
+				message: '参数错误',
+			}
+		}
+	}
+	const res = await uniCloud.getPhoneNumber({
+		provider: 'univerify',
+		appid: '__UNI__3A527D1', // DCloud appid,不同于callFunction方式调用,使用云函数Url化需要传递DCloud appid参数!!!
+		access_token: access_token,
+		openid: openid
+	})
+	console.log(res); // res里包含手机号
+	return { // 不建议把完整手机号返回给前端
+		success: true,
+		info: {
+			code: 0,
+			message: '获取手机号成功',
+			data: res,
+		}
+	}
+}
\ No newline at end of file
diff --git a/uniCloud-aliyun/cloudfunctions/oneClickLoginFn/package.json b/uniCloud-aliyun/cloudfunctions/oneClickLoginFn/package.json
new file mode 100644
index 0000000..7f4ea72
--- /dev/null
+++ b/uniCloud-aliyun/cloudfunctions/oneClickLoginFn/package.json
@@ -0,0 +1,8 @@
+{
+	"name": "oneClickLoginFn",
+	"dependencies": {},
+	"extensions": {
+		"uni-cloud-jql": {},
+		"uni-cloud-verify": {}
+	}
+}
\ No newline at end of file
diff --git a/uniCloud-aliyun/database/JQL查询.jql b/uniCloud-aliyun/database/JQL查询.jql
new file mode 100644
index 0000000..35d21de
--- /dev/null
+++ b/uniCloud-aliyun/database/JQL查询.jql
@@ -0,0 +1,12 @@
+// 本文件用于,使用JQL语法操作项目关联的uniCloud空间的数据库,方便开发调试和远程数据库管理
+// 编写clientDB的js API(也支持常规js语法,比如var),可以对云数据库进行增删改查操作。不支持uniCloud-db组件写法
+// 可以全部运行,也可以选中部分代码运行。点击工具栏上的运行按钮或者按下【F5】键运行代码
+// 如果文档中存在多条JQL语句,只有最后一条语句生效
+// 如果混写了普通js,最后一条语句需是数据库操作语句
+// 此处代码运行不受DB Schema的权限控制,移植代码到实际业务中注意在schema中配好permission
+// 不支持clientDB的action
+// 数据库查询有最大返回条数限制,详见:https://uniapp.dcloud.net.cn/uniCloud/cf-database.html#limit
+// 详细JQL语法,请参考:https://uniapp.dcloud.net.cn/uniCloud/jql.html
+
+// 下面示例查询uni-id-users表的所有数据
+db.collection('uni-id-users').get();
diff --git a/uni_modules/uni-config-center/changelog.md b/uni_modules/uni-config-center/changelog.md
new file mode 100644
index 0000000..57dbcb5
--- /dev/null
+++ b/uni_modules/uni-config-center/changelog.md
@@ -0,0 +1,6 @@
+## 0.0.3(2022-11-11)
+- 修复 config 方法获取根节点为数组格式配置时错误的转化为了对象的Bug
+## 0.0.2(2021-04-16)
+- 修改插件package信息
+## 0.0.1(2021-03-15)
+- 初始化项目
diff --git a/uni_modules/uni-config-center/package.json b/uni_modules/uni-config-center/package.json
new file mode 100644
index 0000000..bace866
--- /dev/null
+++ b/uni_modules/uni-config-center/package.json
@@ -0,0 +1,81 @@
+{
+  "id": "uni-config-center",
+  "displayName": "uni-config-center",
+  "version": "0.0.3",
+  "description": "uniCloud 配置中心",
+  "keywords": [
+    "配置",
+    "配置中心"
+],
+  "repository": "",
+  "engines": {
+    "HBuilderX": "^3.1.0"
+  },
+"dcloudext": {
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "",
+    "type": "unicloud-template-function"
+  },
+  "directories": {
+    "example": "../../../scripts/dist"
+  },
+  "uni_modules": {
+    "dependencies": [],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "u",
+          "app-nvue": "u"
+        },
+        "H5-mobile": {
+          "Safari": "u",
+          "Android Browser": "u",
+          "微信浏览器(Android)": "u",
+          "QQ浏览器(Android)": "u"
+        },
+        "H5-pc": {
+          "Chrome": "u",
+          "IE": "u",
+          "Edge": "u",
+          "Firefox": "u",
+          "Safari": "u"
+        },
+        "小程序": {
+          "微信": "u",
+          "阿里": "u",
+          "百度": "u",
+          "字节跳动": "u",
+          "QQ": "u"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "u"
+        }
+      }
+    }
+  }
+}
diff --git a/uni_modules/uni-config-center/readme.md b/uni_modules/uni-config-center/readme.md
new file mode 100644
index 0000000..03f7fc2
--- /dev/null
+++ b/uni_modules/uni-config-center/readme.md
@@ -0,0 +1,93 @@
+# 为什么使用uni-config-center
+
+实际开发中很多插件需要配置文件才可以正常运行,如果每个插件都单独进行配置的话就会产生下面这样的目录结构
+
+```bash
+cloudfunctions
+└─────common 公共模块
+        ├─plugin-a // 插件A对应的目录
+        │  ├─index.js
+        │  ├─config.json // plugin-a对应的配置文件
+        │  └─other-file.cert  // plugin-a依赖的其他文件
+        └─plugin-b // plugin-b对应的目录
+           ├─index.js
+           └─config.json // plugin-b对应的配置文件
+```
+
+假设插件作者要发布一个项目模板,里面使用了很多需要配置的插件,无论是作者发布还是用户使用都是一个大麻烦。
+
+uni-config-center就是用了统一管理这些配置文件的,使用uni-config-center后的目录结构如下
+
+```bash
+cloudfunctions
+└─────common 公共模块
+        ├─plugin-a // 插件A对应的目录
+        │  └─index.js
+        ├─plugin-b // plugin-b对应的目录
+        │  └─index.js
+        └─uni-config-center
+           ├─index.js // config-center入口文件
+           ├─plugin-a
+           │  ├─config.json  // plugin-a对应的配置文件
+           │  └─other-file.cert  // plugin-a依赖的其他文件
+           └─plugin-b
+              └─config.json  // plugin-b对应的配置文件
+```
+
+使用uni-config-center后的优势
+
+- 配置文件统一管理,分离插件主体和配置信息,更新插件更方便
+- 支持对config.json设置schema,插件使用者在HBuilderX内编写config.json文件时会有更好的提示(后续HBuilderX会提供支持)
+
+# 用法
+
+在要使用uni-config-center的公共模块或云函数内引入uni-config-center依赖,请参考:[使用公共模块](https://uniapp.dcloud.net.cn/uniCloud/cf-common)
+
+```js
+const createConfig = require('uni-config-center')
+
+const uniIdConfig = createConfig({
+    pluginId: 'uni-id', // 插件id
+    defaultConfig: { // 默认配置
+        tokenExpiresIn: 7200,
+        tokenExpiresThreshold: 600,
+    },
+    customMerge: function(defaultConfig, userConfig) { // 自定义默认配置和用户配置的合并规则,不设置的情况侠会对默认配置和用户配置进行深度合并
+        // defaudltConfig 默认配置
+        // userConfig 用户配置
+        return Object.assign(defaultConfig, userConfig)
+    }
+})
+
+
+// 以如下配置为例
+// {
+//   "tokenExpiresIn": 7200,
+//   "passwordErrorLimit": 6,
+//   "bindTokenToDevice": false,
+//   "passwordErrorRetryTime": 3600,
+//   "app-plus": {
+//     "tokenExpiresIn": 2592000
+//   },
+//   "service": {
+//     "sms": {
+//       "codeExpiresIn": 300
+//     }
+//   }
+// }
+
+// 获取配置
+uniIdConfig.config() // 获取全部配置,注意:uni-config-center内不存在对应插件目录时会返回空对象
+uniIdConfig.config('tokenExpiresIn') // 指定键值获取配置,返回:7200
+uniIdConfig.config('service.sms.codeExpiresIn') // 指定键值获取配置,返回:300
+uniIdConfig.config('tokenExpiresThreshold', 600) // 指定键值获取配置,如果不存在则取传入的默认值,返回:600
+
+// 获取文件绝对路径
+uniIdConfig.resolve('custom-token.js') // 获取uni-config-center/uni-id/custom-token.js文件的路径
+
+// 引用文件(require)
+uniIDConfig.requireFile('custom-token.js') // 使用require方式引用uni-config-center/uni-id/custom-token.js文件。文件不存在时返回undefined,文件内有其他错误导致require失败时会抛出错误。
+
+// 判断是否包含某文件
+uniIDConfig.hasFile('custom-token.js') // 配置目录是否包含某文件,true: 文件存在,false: 文件不存在
+```
\ No newline at end of file
diff --git a/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/index.js b/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/index.js
new file mode 100644
index 0000000..00ba62f
--- /dev/null
+++ b/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/index.js
@@ -0,0 +1 @@
+"use strict";var t=require("fs"),r=require("path");function e(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var n=e(t),o=e(r),i="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};var u=function(t){var r={exports:{}};return t(r,r.exports),r.exports}((function(t,r){var e="__lodash_hash_undefined__",n=9007199254740991,o="[object Arguments]",u="[object Function]",c="[object Object]",a=/^\[object .+?Constructor\]$/,f=/^(?:0|[1-9]\d*)$/,s={};s["[object Float32Array]"]=s["[object Float64Array]"]=s["[object Int8Array]"]=s["[object Int16Array]"]=s["[object Int32Array]"]=s["[object Uint8Array]"]=s["[object Uint8ClampedArray]"]=s["[object Uint16Array]"]=s["[object Uint32Array]"]=!0,s[o]=s["[object Array]"]=s["[object ArrayBuffer]"]=s["[object Boolean]"]=s["[object DataView]"]=s["[object Date]"]=s["[object Error]"]=s[u]=s["[object Map]"]=s["[object Number]"]=s[c]=s["[object RegExp]"]=s["[object Set]"]=s["[object String]"]=s["[object WeakMap]"]=!1;var l="object"==typeof i&&i&&i.Object===Object&&i,h="object"==typeof self&&self&&self.Object===Object&&self,p=l||h||Function("return this")(),_=r&&!r.nodeType&&r,v=_&&t&&!t.nodeType&&t,d=v&&v.exports===_,y=d&&l.process,g=function(){try{var t=v&&v.require&&v.require("util").types;return t||y&&y.binding&&y.binding("util")}catch(t){}}(),b=g&&g.isTypedArray;function j(t,r,e){switch(e.length){case 0:return t.call(r);case 1:return t.call(r,e[0]);case 2:return t.call(r,e[0],e[1]);case 3:return t.call(r,e[0],e[1],e[2])}return t.apply(r,e)}var w,O,m,A=Array.prototype,z=Function.prototype,M=Object.prototype,x=p["__core-js_shared__"],C=z.toString,F=M.hasOwnProperty,U=(w=/[^.]+$/.exec(x&&x.keys&&x.keys.IE_PROTO||""))?"Symbol(src)_1."+w:"",S=M.toString,I=C.call(Object),P=RegExp("^"+C.call(F).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),T=d?p.Buffer:void 0,q=p.Symbol,E=p.Uint8Array,$=T?T.allocUnsafe:void 0,D=(O=Object.getPrototypeOf,m=Object,function(t){return O(m(t))}),k=Object.create,B=M.propertyIsEnumerable,N=A.splice,L=q?q.toStringTag:void 0,R=function(){try{var t=vt(Object,"defineProperty");return t({},"",{}),t}catch(t){}}(),G=T?T.isBuffer:void 0,V=Math.max,W=Date.now,H=vt(p,"Map"),J=vt(Object,"create"),K=function(){function t(){}return function(r){if(!xt(r))return{};if(k)return k(r);t.prototype=r;var e=new t;return t.prototype=void 0,e}}();function Q(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r<e;){var n=t[r];this.set(n[0],n[1])}}function X(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r<e;){var n=t[r];this.set(n[0],n[1])}}function Y(t){var r=-1,e=null==t?0:t.length;for(this.clear();++r<e;){var n=t[r];this.set(n[0],n[1])}}function Z(t){var r=this.__data__=new X(t);this.size=r.size}function tt(t,r){var e=Ot(t),n=!e&&wt(t),o=!e&&!n&&At(t),i=!e&&!n&&!o&&Ft(t),u=e||n||o||i,c=u?function(t,r){for(var e=-1,n=Array(t);++e<t;)n[e]=r(e);return n}(t.length,String):[],a=c.length;for(var f in t)!r&&!F.call(t,f)||u&&("length"==f||o&&("offset"==f||"parent"==f)||i&&("buffer"==f||"byteLength"==f||"byteOffset"==f)||dt(f,a))||c.push(f);return c}function rt(t,r,e){(void 0!==e&&!jt(t[r],e)||void 0===e&&!(r in t))&&ot(t,r,e)}function et(t,r,e){var n=t[r];F.call(t,r)&&jt(n,e)&&(void 0!==e||r in t)||ot(t,r,e)}function nt(t,r){for(var e=t.length;e--;)if(jt(t[e][0],r))return e;return-1}function ot(t,r,e){"__proto__"==r&&R?R(t,r,{configurable:!0,enumerable:!0,value:e,writable:!0}):t[r]=e}Q.prototype.clear=function(){this.__data__=J?J(null):{},this.size=0},Q.prototype.delete=function(t){var r=this.has(t)&&delete this.__data__[t];return this.size-=r?1:0,r},Q.prototype.get=function(t){var r=this.__data__;if(J){var n=r[t];return n===e?void 0:n}return F.call(r,t)?r[t]:void 0},Q.prototype.has=function(t){var r=this.__data__;return J?void 0!==r[t]:F.call(r,t)},Q.prototype.set=function(t,r){var n=this.__data__;return this.size+=this.has(t)?0:1,n[t]=J&&void 0===r?e:r,this},X.prototype.clear=function(){this.__data__=[],this.size=0},X.prototype.delete=function(t){var r=this.__data__,e=nt(r,t);return!(e<0)&&(e==r.length-1?r.pop():N.call(r,e,1),--this.size,!0)},X.prototype.get=function(t){var r=this.__data__,e=nt(r,t);return e<0?void 0:r[e][1]},X.prototype.has=function(t){return nt(this.__data__,t)>-1},X.prototype.set=function(t,r){var e=this.__data__,n=nt(e,t);return n<0?(++this.size,e.push([t,r])):e[n][1]=r,this},Y.prototype.clear=function(){this.size=0,this.__data__={hash:new Q,map:new(H||X),string:new Q}},Y.prototype.delete=function(t){var r=_t(this,t).delete(t);return this.size-=r?1:0,r},Y.prototype.get=function(t){return _t(this,t).get(t)},Y.prototype.has=function(t){return _t(this,t).has(t)},Y.prototype.set=function(t,r){var e=_t(this,t),n=e.size;return e.set(t,r),this.size+=e.size==n?0:1,this},Z.prototype.clear=function(){this.__data__=new X,this.size=0},Z.prototype.delete=function(t){var r=this.__data__,e=r.delete(t);return this.size=r.size,e},Z.prototype.get=function(t){return this.__data__.get(t)},Z.prototype.has=function(t){return this.__data__.has(t)},Z.prototype.set=function(t,r){var e=this.__data__;if(e instanceof X){var n=e.__data__;if(!H||n.length<199)return n.push([t,r]),this.size=++e.size,this;e=this.__data__=new Y(n)}return e.set(t,r),this.size=e.size,this};var it,ut=function(t,r,e){for(var n=-1,o=Object(t),i=e(t),u=i.length;u--;){var c=i[it?u:++n];if(!1===r(o[c],c,o))break}return t};function ct(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":L&&L in Object(t)?function(t){var r=F.call(t,L),e=t[L];try{t[L]=void 0;var n=!0}catch(t){}var o=S.call(t);n&&(r?t[L]=e:delete t[L]);return o}(t):function(t){return S.call(t)}(t)}function at(t){return Ct(t)&&ct(t)==o}function ft(t){return!(!xt(t)||function(t){return!!U&&U in t}(t))&&(zt(t)?P:a).test(function(t){if(null!=t){try{return C.call(t)}catch(t){}try{return t+""}catch(t){}}return""}(t))}function st(t){if(!xt(t))return function(t){var r=[];if(null!=t)for(var e in Object(t))r.push(e);return r}(t);var r=yt(t),e=[];for(var n in t)("constructor"!=n||!r&&F.call(t,n))&&e.push(n);return e}function lt(t,r,e,n,o){t!==r&&ut(r,(function(i,u){if(o||(o=new Z),xt(i))!function(t,r,e,n,o,i,u){var a=gt(t,e),f=gt(r,e),s=u.get(f);if(s)return void rt(t,e,s);var l=i?i(a,f,e+"",t,r,u):void 0,h=void 0===l;if(h){var p=Ot(f),_=!p&&At(f),v=!p&&!_&&Ft(f);l=f,p||_||v?Ot(a)?l=a:Ct(j=a)&&mt(j)?l=function(t,r){var e=-1,n=t.length;r||(r=Array(n));for(;++e<n;)r[e]=t[e];return r}(a):_?(h=!1,l=function(t,r){if(r)return t.slice();var e=t.length,n=$?$(e):new t.constructor(e);return t.copy(n),n}(f,!0)):v?(h=!1,d=f,y=!0?(g=d.buffer,b=new g.constructor(g.byteLength),new E(b).set(new E(g)),b):d.buffer,l=new d.constructor(y,d.byteOffset,d.length)):l=[]:function(t){if(!Ct(t)||ct(t)!=c)return!1;var r=D(t);if(null===r)return!0;var e=F.call(r,"constructor")&&r.constructor;return"function"==typeof e&&e instanceof e&&C.call(e)==I}(f)||wt(f)?(l=a,wt(a)?l=function(t){return function(t,r,e,n){var o=!e;e||(e={});var i=-1,u=r.length;for(;++i<u;){var c=r[i],a=n?n(e[c],t[c],c,e,t):void 0;void 0===a&&(a=t[c]),o?ot(e,c,a):et(e,c,a)}return e}(t,Ut(t))}(a):xt(a)&&!zt(a)||(l=function(t){return"function"!=typeof t.constructor||yt(t)?{}:K(D(t))}(f))):h=!1}var d,y,g,b;var j;h&&(u.set(f,l),o(l,f,n,i,u),u.delete(f));rt(t,e,l)}(t,r,u,e,lt,n,o);else{var a=n?n(gt(t,u),i,u+"",t,r,o):void 0;void 0===a&&(a=i),rt(t,u,a)}}),Ut)}function ht(t,r){return bt(function(t,r,e){return r=V(void 0===r?t.length-1:r,0),function(){for(var n=arguments,o=-1,i=V(n.length-r,0),u=Array(i);++o<i;)u[o]=n[r+o];o=-1;for(var c=Array(r+1);++o<r;)c[o]=n[o];return c[r]=e(u),j(t,this,c)}}(t,r,Pt),t+"")}var pt=R?function(t,r){return R(t,"toString",{configurable:!0,enumerable:!1,value:(e=r,function(){return e}),writable:!0});var e}:Pt;function _t(t,r){var e,n,o=t.__data__;return("string"==(n=typeof(e=r))||"number"==n||"symbol"==n||"boolean"==n?"__proto__"!==e:null===e)?o["string"==typeof r?"string":"hash"]:o.map}function vt(t,r){var e=function(t,r){return null==t?void 0:t[r]}(t,r);return ft(e)?e:void 0}function dt(t,r){var e=typeof t;return!!(r=null==r?n:r)&&("number"==e||"symbol"!=e&&f.test(t))&&t>-1&&t%1==0&&t<r}function yt(t){var r=t&&t.constructor;return t===("function"==typeof r&&r.prototype||M)}function gt(t,r){if(("constructor"!==r||"function"!=typeof t[r])&&"__proto__"!=r)return t[r]}var bt=function(t){var r=0,e=0;return function(){var n=W(),o=16-(n-e);if(e=n,o>0){if(++r>=800)return arguments[0]}else r=0;return t.apply(void 0,arguments)}}(pt);function jt(t,r){return t===r||t!=t&&r!=r}var wt=at(function(){return arguments}())?at:function(t){return Ct(t)&&F.call(t,"callee")&&!B.call(t,"callee")},Ot=Array.isArray;function mt(t){return null!=t&&Mt(t.length)&&!zt(t)}var At=G||function(){return!1};function zt(t){if(!xt(t))return!1;var r=ct(t);return r==u||"[object GeneratorFunction]"==r||"[object AsyncFunction]"==r||"[object Proxy]"==r}function Mt(t){return"number"==typeof t&&t>-1&&t%1==0&&t<=n}function xt(t){var r=typeof t;return null!=t&&("object"==r||"function"==r)}function Ct(t){return null!=t&&"object"==typeof t}var Ft=b?function(t){return function(r){return t(r)}}(b):function(t){return Ct(t)&&Mt(t.length)&&!!s[ct(t)]};function Ut(t){return mt(t)?tt(t,!0):st(t)}var St,It=(St=function(t,r,e){lt(t,r,e)},ht((function(t,r){var e=-1,n=r.length,o=n>1?r[n-1]:void 0,i=n>2?r[2]:void 0;for(o=St.length>3&&"function"==typeof o?(n--,o):void 0,i&&function(t,r,e){if(!xt(e))return!1;var n=typeof r;return!!("number"==n?mt(e)&&dt(r,e.length):"string"==n&&r in e)&&jt(e[r],t)}(r[0],r[1],i)&&(o=n<3?void 0:o,n=1),t=Object(t);++e<n;){var u=r[e];u&&St(t,u,e,o)}return t})));function Pt(t){return t}t.exports=It}));const c=Object.prototype.hasOwnProperty,a=(t,r)=>c.call(t,r);class f{constructor({pluginId:t,defaultConfig:r={},customMerge:e,root:n}){this.pluginId=t,this.defaultConfig=r,this.pluginConfigPath=o.default.resolve(n||__dirname,t),this.customMerge=e,this._config=void 0}resolve(t){return o.default.resolve(this.pluginConfigPath,t)}hasFile(t){return n.default.existsSync(this.resolve(t))}requireFile(t){try{return require(this.resolve(t))}catch(t){if("MODULE_NOT_FOUND"===t.code)return;throw t}}_getUserConfig(){return this.requireFile("config.json")}config(t,r){if(!this._config){const t=this._getUserConfig();this._config=Array.isArray(t)?t:(this.customMerge||u)(this.defaultConfig,t)}let e=this._config;return t?function(t,r,e){if("number"==typeof r)return t[r];if("symbol"==typeof r)return a(t,r)?t[r]:e;const n="string"!=typeof(o=r)?o:o.split(".").reduce(((t,r)=>(r.split(/\[([^}]+)\]/g).forEach((r=>r&&t.push(r))),t)),[]);var o;let i=t;for(let t=0;t<n.length;t++){const r=n[t];if(!a(i,r))return e;i=i[r]}return i}(e,t,r):e}}const s=new class{constructor(){this._configMap=new Map}plugin({pluginId:t,defaultConfig:r,customMerge:e,root:n=__dirname,cache:o=!0}){if(this._configMap.has(t)&&o)return this._configMap.get(t);const i=new f({pluginId:t,defaultConfig:r,customMerge:e,root:n});return o&&this._configMap.set(t,i),i}};var l=s.plugin.bind(s);module.exports=l;
diff --git a/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/package.json b/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/package.json
new file mode 100644
index 0000000..9a6dd0d
--- /dev/null
+++ b/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/package.json
@@ -0,0 +1 @@
+{"name":"uni-config-center","version":"0.0.3","description":"配置中心","main":"index.js","keywords":[],"author":"DCloud","license":"Apache-2.0"}
diff --git a/uni_modules/uni-id-common/changelog.md b/uni_modules/uni-id-common/changelog.md
new file mode 100644
index 0000000..e76f197
--- /dev/null
+++ b/uni_modules/uni-id-common/changelog.md
@@ -0,0 +1,34 @@
+## 1.0.17(2024-04-26)
+- 兼容uni-app-x对客户端uniPlatform的调整(uni-app-x内uniPlatform区分app-android、app-ios)
+## 1.0.16(2023-04-25)
+- 新增maxTokenLength配置,用于限制数据库用户记录token数组的最大长度
+## 1.0.15(2023-04-06)
+- 修复部分语言国际化出错的Bug
+## 1.0.14(2023-03-07)
+- 修复 admin用户包含其他角色时未包含在token的Bug
+## 1.0.13(2022-07-21)
+- 修复 创建token时未传角色权限信息生成的token不正确的bug
+## 1.0.12(2022-07-15)
+- 提升与旧版本uni-id的兼容性(补充读取配置文件时回退平台app-plus、h5),但是仍推荐使用新平台名进行配置(app、web)
+## 1.0.11(2022-07-14)
+- 修复 部分情况下报`read property 'reduce' of undefined`的错误
+## 1.0.10(2022-07-11)
+- 将token存储在用户表的token字段内,与旧版本uni-id保持一致
+## 1.0.9(2022-07-01)
+- checkToken兼容token内未缓存角色权限的情况,此时将查库获取角色权限
+## 1.0.8(2022-07-01)
+- 修复clientDB默认依赖时部分情况下获取不到uni-id配置的Bug
+## 1.0.7(2022-06-30)
+- 修复config文件不合法时未抛出具体错误的Bug
+## 1.0.6(2022-06-28)
+- 移除插件内的数据表schema
+## 1.0.5(2022-06-27)
+- 修复使用多应用配置时报`Cannot read property 'appId' of undefined`的Bug
+## 1.0.4(2022-06-27)
+- 修复使用自定义token内容功能报错的Bug [详情](https://ask.dcloud.net.cn/question/147945)
+## 1.0.2(2022-06-23)
+- 对齐旧版本uni-id默认配置
+## 1.0.1(2022-06-22)
+- 补充对uni-config-center的依赖
+## 1.0.0(2022-06-21)
+- 提供uni-id token创建、校验、刷新接口,简化旧版uni-id公共模块
diff --git a/uni_modules/uni-id-common/package.json b/uni_modules/uni-id-common/package.json
new file mode 100644
index 0000000..5a4f900
--- /dev/null
+++ b/uni_modules/uni-id-common/package.json
@@ -0,0 +1,85 @@
+{
+	"id": "uni-id-common",
+	"displayName": "uni-id-common",
+	"version": "1.0.17",
+	"description": "包含uni-id token生成、校验、刷新功能的云函数公共模块",
+	"keywords": [
+        "uni-id-common",
+        "uniCloud",
+        "token",
+        "权限"
+    ],
+	"repository": "https://gitcode.net/dcloud/uni-id-common",
+	"engines": {
+		"HBuilderX": "^3.1.0"
+	},
+    "dcloudext": {
+        "sale": {
+			"regular": {
+				"price": "0.00"
+			},
+			"sourcecode": {
+				"price": "0.00"
+			}
+		},
+		"contact": {
+			"qq": ""
+		},
+		"declaration": {
+			"ads": "无",
+			"data": "无",
+			"permissions": "无"
+		},
+        "npmurl": "",
+        "type": "unicloud-template-function"
+	},
+	"uni_modules": {
+		"dependencies": ["uni-config-center"],
+		"encrypt": [],
+		"platforms": {
+			"cloud": {
+				"tcb": "y",
+                "aliyun": "y",
+                "alipay": "n"
+			},
+			"client": {
+				"Vue": {
+					"vue2": "u",
+					"vue3": "u"
+				},
+				"App": {
+					"app-vue": "u",
+					"app-nvue": "u"
+				},
+				"H5-mobile": {
+					"Safari": "u",
+					"Android Browser": "u",
+					"微信浏览器(Android)": "u",
+					"QQ浏览器(Android)": "u"
+				},
+				"H5-pc": {
+					"Chrome": "u",
+					"IE": "u",
+					"Edge": "u",
+					"Firefox": "u",
+					"Safari": "u"
+				},
+				"小程序": {
+					"微信": "u",
+					"阿里": "u",
+					"百度": "u",
+					"字节跳动": "u",
+					"QQ": "u",
+					"钉钉": "u",
+					"快手": "u",
+					"飞书": "u",
+                    "京东": "u"
+				},
+				"快应用": {
+					"华为": "u",
+					"联盟": "u"
+				}
+			}
+		}
+	}
+}
diff --git a/uni_modules/uni-id-common/readme.md b/uni_modules/uni-id-common/readme.md
new file mode 100644
index 0000000..5f6a37a
--- /dev/null
+++ b/uni_modules/uni-id-common/readme.md
@@ -0,0 +1,3 @@
+# uni-id-common
+
+文档请参考:[uni-id-common](https://uniapp.dcloud.net.cn/uniCloud/uni-id-common.html)
\ No newline at end of file
diff --git a/uni_modules/uni-id-common/uniCloud/cloudfunctions/common/uni-id-common/index.js b/uni_modules/uni-id-common/uniCloud/cloudfunctions/common/uni-id-common/index.js
new file mode 100644
index 0000000..2078958
--- /dev/null
+++ b/uni_modules/uni-id-common/uniCloud/cloudfunctions/common/uni-id-common/index.js
@@ -0,0 +1 @@
+"use strict";var e,t=(e=require("crypto"))&&"object"==typeof e&&"default"in e?e.default:e;const n={TOKEN_EXPIRED:"uni-id-token-expired",CHECK_TOKEN_FAILED:"uni-id-check-token-failed",PARAM_REQUIRED:"uni-id-param-required",ACCOUNT_EXISTS:"uni-id-account-exists",ACCOUNT_NOT_EXISTS:"uni-id-account-not-exists",ACCOUNT_CONFLICT:"uni-id-account-conflict",ACCOUNT_BANNED:"uni-id-account-banned",ACCOUNT_AUDITING:"uni-id-account-auditing",ACCOUNT_AUDIT_FAILED:"uni-id-account-audit-failed",ACCOUNT_CLOSED:"uni-id-account-closed"};function i(e){return!!e&&("object"==typeof e||"function"==typeof e)&&"function"==typeof e.then}function r(e){if(!e)return;const t=e.match(/^(\d+).(\d+).(\d+)/);return t?t.slice(1,4).map(e=>parseInt(e)):void 0}function o(e,t){const n=r(e),i=r(t);return n?i?function(e,t){const n=Math.max(e.length,t.length);for(let i=0;i<n;i++){const n=e[i],r=t[i];if(n>r)return 1;if(n<r)return-1}return 0}(n,i):1:i?-1:0}const s={"uni-id-token-expired":30203,"uni-id-check-token-failed":30202};function c(e){const{errCode:t,errMsgValue:n}=e;e.errMsg=this._t(t,n),t in s&&(e.code=s[t]),delete e.errMsgValue}function a(e){return"object"===(i=e,Object.prototype.toString.call(i).slice(8,-1).toLowerCase())&&e.errCode&&(t=e.errCode,Object.values(n).includes(t))&&!!e.errCode;var t,i}let u={"zh-Hans":{"uni-id-token-expired":"登录状态失效,token已过期","uni-id-check-token-failed":"token校验未通过","uni-id-param-required":"缺少参数: {param}","uni-id-account-exists":"此账号已注册","uni-id-account-not-exists":"此账号未注册","uni-id-account-conflict":"用户账号冲突","uni-id-account-banned":"从账号已封禁","uni-id-account-auditing":"此账号正在审核中","uni-id-account-audit-failed":"此账号审核失败","uni-id-account-closed":"此账号已注销"},en:{"uni-id-token-expired":"The login status is invalid, token has expired","uni-id-check-token-failed":"Check token failed","uni-id-param-required":"Parameter required: {param}","uni-id-account-exists":"Account exists","uni-id-account-not-exists":"Account does not exists","uni-id-account-conflict":"User account conflict","uni-id-account-banned":"Account has been banned","uni-id-account-auditing":"Account audit in progress","uni-id-account-audit-failed":"Account audit failed","uni-id-account-closed":"Account has been closed"}};try{const e=require.resolve("uni-config-center/uni-id/lang/index.js");u=function(e,t){const n=Object.keys(e);n.push(...Object.keys(t));const i={};for(let r=0;r<n.length;r++){const o=n[r];i[o]=Object.assign({},e[o],t[o])}return i}(u,require(e))}catch(e){}var d=u;function l(e){return e.replace(/=/g,"").replace(/\+/g,"-").replace(/\//g,"_")}function h(e){return JSON.parse((t=function(e){var t=4-(e=e.toString()).length%4;if(4!==t)for(var n=0;n<t;++n)e+="=";return e.replace(/-/g,"+").replace(/_/g,"/")}(e),Buffer.from(t,"base64").toString("utf-8")));var t}function f(e){return l((t=JSON.stringify(e),Buffer.from(t,"utf-8").toString("base64")));var t}function p(e,n){return l(t.createHmac("sha256",n).update(e).digest("base64"))}const k=function(e,t){if("string"!=typeof e)throw new Error("Invalid token");const n=e.split(".");if(3!==n.length)throw new Error("Invalid token");const[i,r,o]=n;if(p(i+"."+r,t)!==o)throw new Error("Invalid token");const s=h(i);if("HS256"!==s.alg||"JWT"!==s.typ)throw new Error("Invalid token");const c=h(r);if(1e3*c.exp<Date.now()){const e=new Error("Token expired");throw e.name="TokenExpiredError",e}return c},g=function(e,t,n={}){const{expiresIn:i}=n;if(!i)throw new Error("expiresIn is required");const r=parseInt(Date.now()/1e3),o={...e,iat:r,exp:r+n.expiresIn},s=f({alg:"HS256",typ:"JWT"})+"."+f(o);return s+"."+p(s,t)},I=uniCloud.database(),_=I.command,C=I.collection("uni-id-users"),T=I.collection("uni-id-roles");class m{constructor({uniId:e}={}){this.uid=null,this.userRecord=null,this.userPermission=null,this.oldToken=null,this.oldTokenPayload=null,this.uniId=e,this.config=this.uniId._getConfig(),this.clientInfo=this.uniId._clientInfo,this.checkConfig()}checkConfig(){const{tokenExpiresIn:e,tokenExpiresThreshold:t}=this.config;if(t>=e)throw new Error("Config error, tokenExpiresThreshold should be less than tokenExpiresIn");t>e/2&&console.warn(`Please check whether the tokenExpiresThreshold configuration is set too large, tokenExpiresThreshold: ${t}, tokenExpiresIn: ${e}`)}get customToken(){return this.uniId.interceptorMap.get("customToken")}isTokenInDb(e){return o(e,"1.0.10")>=0}async getUserRecord(){if(this.userRecord)return this.userRecord;const e=await C.doc(this.uid).get();if(this.userRecord=e.data[0],!this.userRecord)throw{errCode:n.ACCOUNT_NOT_EXISTS};switch(this.userRecord.status){case void 0:case 0:break;case 1:throw{errCode:n.ACCOUNT_BANNED};case 2:throw{errCode:n.ACCOUNT_AUDITING};case 3:throw{errCode:n.ACCOUNT_AUDIT_FAILED};case 4:throw{errCode:n.ACCOUNT_CLOSED}}if(this.oldTokenPayload){if(this.isTokenInDb(this.oldTokenPayload.uniIdVersion)){if(-1===(this.userRecord.token||[]).indexOf(this.oldToken))throw{errCode:n.CHECK_TOKEN_FAILED}}if(this.userRecord.valid_token_date&&this.userRecord.valid_token_date>1e3*this.oldTokenPayload.iat)throw{errCode:n.TOKEN_EXPIRED}}return this.userRecord}async updateUserRecord(e){await C.doc(this.uid).update(e)}async getUserPermission(){if(this.userPermission)return this.userPermission;const e=(await this.getUserRecord()).role||[];if(0===e.length)return this.userPermission={role:[],permission:[]},this.userPermission;if(e.includes("admin"))return this.userPermission={role:e,permission:[]},this.userPermission;const t=await T.where({role_id:_.in(e)}).get(),n=(i=t.data.reduce((e,t)=>(t.permission&&e.push(...t.permission),e),[]),Array.from(new Set(i)));var i;return this.userPermission={role:e,permission:n},this.userPermission}async _createToken({uid:e,role:t,permission:i}={}){if(!t||!i){const e=await this.getUserPermission();t=e.role,i=e.permission}let r={uid:e,role:t,permission:i};if(this.uniId.interceptorMap.has("customToken")){const n=this.uniId.interceptorMap.get("customToken");if("function"!=typeof n)throw new Error("Invalid custom token file");r=await n({uid:e,role:t,permission:i})}const o=Date.now(),{tokenSecret:s,tokenExpiresIn:c,maxTokenLength:a=10}=this.config,u=g({...r,uniIdVersion:"1.0.17"},s,{expiresIn:c}),d=await this.getUserRecord(),l=(d.token||[]).filter(e=>{try{const t=this._checkToken(e);if(d.valid_token_date&&d.valid_token_date>1e3*t.iat)return!1}catch(e){if(e.errCode===n.TOKEN_EXPIRED)return!1}return!0});return l.push(u),l.length>a&&l.splice(0,l.length-a),await this.updateUserRecord({last_login_ip:this.clientInfo.clientIP,last_login_date:o,token:l}),{token:u,tokenExpired:o+1e3*c}}async createToken({uid:e,role:t,permission:i}={}){if(!e)throw{errCode:n.PARAM_REQUIRED,errMsgValue:{param:"uid"}};this.uid=e;const{token:r,tokenExpired:o}=await this._createToken({uid:e,role:t,permission:i});return{errCode:0,token:r,tokenExpired:o}}async refreshToken({token:e}={}){if(!e)throw{errCode:n.PARAM_REQUIRED,errMsgValue:{param:"token"}};this.oldToken=e;const t=this._checkToken(e);this.uid=t.uid,this.oldTokenPayload=t;const{uid:i}=t,{role:r,permission:o}=await this.getUserPermission(),{token:s,tokenExpired:c}=await this._createToken({uid:i,role:r,permission:o});return{errCode:0,token:s,tokenExpired:c}}_checkToken(e){const{tokenSecret:t}=this.config;let i;try{i=k(e,t)}catch(e){if("TokenExpiredError"===e.name)throw{errCode:n.TOKEN_EXPIRED};throw{errCode:n.CHECK_TOKEN_FAILED}}return i}async checkToken(e,{autoRefresh:t=!0}={}){if(!e)throw{errCode:n.PARAM_REQUIRED,errMsgValue:{param:"token"}};this.oldToken=e;const i=this._checkToken(e);this.uid=i.uid,this.oldTokenPayload=i;const{tokenExpiresThreshold:r}=this.config,{uid:o,role:s,permission:c}=i,a={role:s,permission:c};if(!s&&!c){const{role:e,permission:t}=await this.getUserPermission();a.role=e,a.permission=t}if(!r||!t){const e={code:0,errCode:0,...i,...a};return delete e.uniIdVersion,e}const u=Date.now();let d={};1e3*i.exp-u<1e3*r&&(d=await this._createToken({uid:o}));const l={code:0,errCode:0,...i,...a,...d};return delete l.uniIdVersion,l}}var E=Object.freeze({__proto__:null,checkToken:async function(e,{autoRefresh:t=!0}={}){return new m({uniId:this}).checkToken(e,{autoRefresh:t})},createToken:async function({uid:e,role:t,permission:n}={}){return new m({uniId:this}).createToken({uid:e,role:t,permission:n})},refreshToken:async function({token:e}={}){return new m({uniId:this}).refreshToken({token:e})}});const w=require("uni-config-center")({pluginId:"uni-id"});class x{constructor({context:e,clientInfo:t,config:n}={}){this._clientInfo=e?function(e){return{appId:e.APPID,platform:e.PLATFORM,locale:e.LOCALE,clientIP:e.CLIENTIP,deviceId:e.DEVICEID}}(e):t,this._config=n,this.config=this._getOriginConfig(),this.interceptorMap=new Map,w.hasFile("custom-token.js")&&this.setInterceptor("customToken",require(w.resolve("custom-token.js")));this._i18n=uniCloud.initI18n({locale:this._clientInfo.locale,fallbackLocale:"zh-Hans",messages:JSON.parse(JSON.stringify(d))}),d[this._i18n.locale]||this._i18n.setLocale("zh-Hans")}setInterceptor(e,t){this.interceptorMap.set(e,t)}_t(...e){return this._i18n.t(...e)}_parseOriginConfig(e){return Array.isArray(e)?e:e[0]?Object.values(e):e}_getOriginConfig(){if(this._config)return this._config;if(w.hasFile("config.json")){let e;try{e=w.config()}catch(e){throw new Error("Invalid uni-id config file\n"+e.message)}return this._parseOriginConfig(e)}try{return this._parseOriginConfig(require("uni-id/config.json"))}catch(e){throw new Error("Invalid uni-id config file")}}_getAppConfig(){const e=this._getOriginConfig();return Array.isArray(e)?e.find(e=>e.dcloudAppid===this._clientInfo.appId)||e.find(e=>e.isDefaultConfig):e}_getPlatformConfig(){const e=this._getAppConfig();if(!e)throw new Error(`Config for current app (${this._clientInfo.appId}) was not found, please check your config file or client appId`);let t;switch(["app-plus","app-android","app-ios"].indexOf(this._clientInfo.platform)>-1&&(this._clientInfo.platform="app"),"h5"===this._clientInfo.platform&&(this._clientInfo.platform="web"),this._clientInfo.platform){case"web":t="h5";break;case"app":t="app-plus"}const n=[{tokenExpiresIn:7200,tokenExpiresThreshold:1200,passwordErrorLimit:6,passwordErrorRetryTime:3600},e];t&&e[t]&&n.push(e[t]),n.push(e[this._clientInfo.platform]);const i=Object.assign(...n);return["tokenSecret","tokenExpiresIn"].forEach(e=>{if(!i||!i[e])throw new Error(`Config parameter missing, ${e} is required`)}),i}_getConfig(){return this._getPlatformConfig()}}for(const e in E)x.prototype[e]=E[e];function y(e){const t=new x(e);return new Proxy(t,{get(e,t){if(t in e&&0!==t.indexOf("_")){if("function"==typeof e[t])return(n=e[t],function(){let e;try{e=n.apply(this,arguments)}catch(e){if(a(e))return c.call(this,e),e;throw e}return i(e)?e.then(e=>(a(e)&&c.call(this,e),e),e=>{if(a(e))return c.call(this,e),e;throw e}):(a(e)&&c.call(this,e),e)}).bind(e);if("context"!==t&&"config"!==t)return e[t]}var n}})}x.prototype.createInstance=y;const A={createInstance:y};module.exports=A;
diff --git a/uni_modules/uni-id-common/uniCloud/cloudfunctions/common/uni-id-common/package.json b/uni_modules/uni-id-common/uniCloud/cloudfunctions/common/uni-id-common/package.json
new file mode 100644
index 0000000..4986a12
--- /dev/null
+++ b/uni_modules/uni-id-common/uniCloud/cloudfunctions/common/uni-id-common/package.json
@@ -0,0 +1 @@
+{"name":"uni-id-common","version":"1.0.17","description":"uni-id token生成、校验、刷新","main":"index.js","homepage":"https://uniapp.dcloud.io/uniCloud/uni-id-common.html","repository":{"type":"git","url":"git+https://gitee.com/dcloud/uni-id-common.git"},"author":"DCloud","license":"Apache-2.0","dependencies":{"uni-config-center":"file:../../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center"}}
diff --git a/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/bridge-error.js b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/bridge-error.js
new file mode 100644
index 0000000..95160a4
--- /dev/null
+++ b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/bridge-error.js
@@ -0,0 +1,26 @@
+'use strict';
+
+class BridgeError extends Error {
+
+  constructor(code, message) {
+    super(message)
+
+    this._code = code
+  }
+
+  get code() {
+    return this._code
+  }
+
+  get errCode() {
+    return this._code
+  }
+
+  get errMsg() {
+    return this.message
+  }
+}
+
+module.exports = {
+  BridgeError
+}
diff --git a/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/config.js b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/config.js
new file mode 100644
index 0000000..d083f00
--- /dev/null
+++ b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/config.js
@@ -0,0 +1,124 @@
+'use strict';
+
+const {
+  ProviderType
+} = require('./consts.js')
+
+const configCenter = require('uni-config-center')
+
+// 多维数据为兼容uni-id以前版本配置
+const OauthConfig = {
+  'weixin-app': [
+    ['app', 'oauth', 'weixin'],
+    ['app-plus', 'oauth', 'weixin']
+  ],
+  'weixin-mp': [
+    ['mp-weixin', 'oauth', 'weixin']
+  ],
+  'weixin-h5': [
+    ['web', 'oauth', 'weixin-h5'],
+    ['h5-weixin', 'oauth', 'weixin'],
+    ['h5', 'oauth', 'weixin']
+  ],
+  'weixin-web': [
+    ['web', 'oauth', 'weixin-web']
+  ],
+  'qq-app': [
+    ['app', 'oauth', 'qq'],
+    ['app-plus', 'oauth', 'qq']
+  ],
+  'qq-mp': [
+    ['mp-qq', 'oauth', 'qq']
+  ]
+}
+
+const Support_Platforms = [
+  ProviderType.WEIXIN_MP,
+  ProviderType.WEIXIN_H5,
+  ProviderType.WEIXIN_APP,
+  ProviderType.WEIXIN_WEB,
+  ProviderType.QQ_MP,
+  ProviderType.QQ_APP
+]
+
+class ConfigBase {
+
+  constructor() {
+    const uniIdConfigCenter = configCenter({
+      pluginId: 'uni-id'
+    })
+
+    this._uniIdConfig = uniIdConfigCenter.config()
+  }
+
+  getAppConfig(appid) {
+    if (Array.isArray(this._uniIdConfig)) {
+      return this._uniIdConfig.find((item) => {
+        return (item.dcloudAppid === appid)
+      })
+    }
+    return this._uniIdConfig
+  }
+}
+
+class AppConfig extends ConfigBase {
+
+  constructor() {
+    super()
+  }
+
+  get(appid, platform) {
+    if (!this.isSupport(platform)) {
+      return null
+    }
+
+    let appConfig = this.getAppConfig(appid)
+    if (!appConfig) {
+      return null
+    }
+
+    return this.getOauthConfig(appConfig, platform)
+  }
+
+  isSupport(platformName) {
+    return (Support_Platforms.indexOf(platformName) >= 0)
+  }
+
+  getOauthConfig(appConfig, platformName) {
+    let treePath = OauthConfig[platformName]
+    let node = this.findNode(appConfig, treePath)
+    if (node && node.appid && node.appsecret) {
+      return {
+        appid: node.appid,
+        secret: node.appsecret
+      }
+    }
+    return null
+  }
+
+  findNode(treeNode, arrayPath) {
+    let node = treeNode
+    for (let treePath of arrayPath) {
+      for (let name of treePath) {
+        const currentNode = node[name]
+        if (currentNode) {
+          node = currentNode
+        } else {
+          node = null
+          break
+        }
+      }
+      if (node === null) {
+        node = treeNode
+      } else {
+        break
+      }
+    }
+    return node
+  }
+}
+
+
+module.exports = {
+  AppConfig
+};
\ No newline at end of file
diff --git a/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/consts.js b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/consts.js
new file mode 100644
index 0000000..4c666e9
--- /dev/null
+++ b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/consts.js
@@ -0,0 +1,30 @@
+'use strict';
+
+const TAG = "UNI_OPEN_BRIDGE"
+
+const HTTP_STATUS = {
+  SUCCESS: 200
+}
+
+const ProviderType = {
+  WEIXIN_MP: 'weixin-mp',
+  WEIXIN_H5: 'weixin-h5',
+  WEIXIN_APP: 'weixin-app',
+  WEIXIN_WEB: 'weixin-web',
+  QQ_MP: 'qq-mp',
+  QQ_APP: 'qq-app'
+}
+
+// old
+const PlatformType = ProviderType
+
+const ErrorCodeType = {
+  SYSTEM_ERROR: TAG + "_SYSTEM_ERROR"
+}
+
+module.exports = {
+  HTTP_STATUS,
+  ProviderType,
+  PlatformType,
+  ErrorCodeType
+}
diff --git a/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/index.js b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/index.js
new file mode 100644
index 0000000..fc23cd9
--- /dev/null
+++ b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/index.js
@@ -0,0 +1,317 @@
+'use strict';
+
+const {
+  PlatformType,
+  ProviderType,
+  ErrorCodeType
+} = require('./consts.js')
+
+const {
+  AppConfig
+} = require('./config.js')
+
+const {
+  Storage
+} = require('./storage.js')
+
+const {
+  BridgeError
+} = require('./bridge-error.js')
+
+const {
+  WeixinServer
+} = require('./weixin-server.js')
+
+const appConfig = new AppConfig()
+
+class AccessToken extends Storage {
+
+  constructor() {
+    super('access-token', ['provider', 'appid'])
+  }
+
+  async update(key) {
+    super.update(key)
+
+    const result = await this.getByWeixinServer(key)
+
+    return this.set(key, result.value, result.duration)
+  }
+
+  async fallback(key) {
+    return this.getByWeixinServer(key)
+  }
+
+  async getByWeixinServer(key) {
+    const oauthConfig = appConfig.get(key.dcloudAppid, key.provider)
+    let methodName
+    if (key.provider === ProviderType.WEIXIN_MP) {
+      methodName = 'GetMPAccessTokenData'
+    } else if (key.provider === ProviderType.WEIXIN_H5) {
+      methodName = 'GetH5AccessTokenData'
+    } else {
+      throw new BridgeError(ErrorCodeType.SYSTEM_ERROR, "provider invalid")
+    }
+
+    const responseData = await WeixinServer[methodName](oauthConfig)
+
+    const duration = responseData.expires_in || (60 * 60 * 2)
+    delete responseData.expires_in
+
+    return {
+      value: responseData,
+      duration
+    }
+  }
+}
+
+class UserAccessToken extends Storage {
+
+  constructor() {
+    super('user-access-token', ['provider', 'appid', 'openid'])
+  }
+}
+
+class SessionKey extends Storage {
+
+  constructor() {
+    super('session-key', ['provider', 'appid', 'openid'])
+  }
+}
+
+class Encryptkey extends Storage {
+
+  constructor() {
+    super('encrypt-key', ['provider', 'appid', 'openid'])
+  }
+
+  async update(key) {
+    super.update(key)
+
+    const result = await this.getByWeixinServer(key)
+
+    return this.set(key, result.value, result.duration)
+  }
+
+  getKeyString(key) {
+    return `${super.getKeyString(key)}-${key.version}`
+  }
+
+  getExpiresIn(value) {
+    if (value <= 0) {
+      return 60
+    }
+    return value
+  }
+
+  async fallback(key) {
+    return this.getByWeixinServer(key)
+  }
+
+  async getByWeixinServer(key) {
+    const accessToken = await Factory.Get(AccessToken, key)
+    const userSession = await Factory.Get(SessionKey, key)
+
+    const responseData = await WeixinServer.GetUserEncryptKeyData({
+      openid: key.openid,
+      access_token: accessToken.access_token,
+      session_key: userSession.session_key
+    })
+
+    const keyInfo = responseData.key_info_list.find((item) => {
+      return item.version === key.version
+    })
+
+    if (!keyInfo) {
+      throw new BridgeError(ErrorCodeType.SYSTEM_ERROR, 'key version invalid')
+    }
+
+    const value = {
+      encrypt_key: keyInfo.encrypt_key,
+      iv: keyInfo.iv
+    }
+
+    return {
+      value,
+      duration: keyInfo.expire_in
+    }
+  }
+}
+
+class Ticket extends Storage {
+
+  constructor() {
+    super('ticket', ['provider', 'appid'])
+  }
+
+  async update(key) {
+    super.update(key)
+
+    const result = await this.getByWeixinServer(key)
+
+    return this.set(key, result.value, result.duration)
+  }
+
+  async fallback(key) {
+    return this.getByWeixinServer(key)
+  }
+
+  async getByWeixinServer(key) {
+    const accessToken = await Factory.Get(AccessToken, {
+      dcloudAppid: key.dcloudAppid,
+      provider: ProviderType.WEIXIN_H5
+    })
+
+    const responseData = await WeixinServer.GetH5TicketData(accessToken)
+
+    const duration = responseData.expires_in || (60 * 60 * 2)
+    delete responseData.expires_in
+    delete responseData.errcode
+    delete responseData.errmsg
+
+    return {
+      value: responseData,
+      duration
+    }
+  }
+}
+
+
+const Factory = {
+
+  async Get(T, key, fallback) {
+    Factory.FixOldKey(key)
+    return Factory.MakeUnique(T).get(key, fallback)
+  },
+
+  async Set(T, key, value, expiresIn) {
+    Factory.FixOldKey(key)
+    return Factory.MakeUnique(T).set(key, value, expiresIn)
+  },
+
+  async Remove(T, key) {
+    Factory.FixOldKey(key)
+    return Factory.MakeUnique(T).remove(key)
+  },
+
+  async Update(T, key) {
+    Factory.FixOldKey(key)
+    return Factory.MakeUnique(T).update(key)
+  },
+
+  FixOldKey(key) {
+    if (!key.provider) {
+      key.provider = key.platform
+    }
+
+    const configData = appConfig.get(key.dcloudAppid, key.provider)
+    if (!configData) {
+      throw new BridgeError(ErrorCodeType.SYSTEM_ERROR, 'appid or provider invalid')
+    }
+    key.appid = configData.appid
+  },
+
+  MakeUnique(T) {
+    return new T()
+  }
+}
+
+
+// exports
+
+async function getAccessToken(key, fallback) {
+  return Factory.Get(AccessToken, key, fallback)
+}
+
+async function setAccessToken(key, value, expiresIn) {
+  return Factory.Set(AccessToken, key, value, expiresIn)
+}
+
+async function removeAccessToken(key) {
+  return Factory.Remove(AccessToken, key)
+}
+
+async function updateAccessToken(key) {
+  return Factory.Update(AccessToken, key)
+}
+
+async function getUserAccessToken(key, fallback) {
+  return Factory.Get(UserAccessToken, key, fallback)
+}
+
+async function setUserAccessToken(key, value, expiresIn) {
+  return Factory.Set(UserAccessToken, key, value, expiresIn)
+}
+
+async function removeUserAccessToken(key) {
+  return Factory.Remove(UserAccessToken, key)
+}
+
+async function getSessionKey(key, fallback) {
+  return Factory.Get(SessionKey, key, fallback)
+}
+
+async function setSessionKey(key, value, expiresIn) {
+  return Factory.Set(SessionKey, key, value, expiresIn)
+}
+
+async function removeSessionKey(key) {
+  return Factory.Remove(SessionKey, key)
+}
+
+async function getEncryptKey(key, fallback) {
+  return Factory.Get(Encryptkey, key, fallback)
+}
+
+async function setEncryptKey(key, value, expiresIn) {
+  return Factory.Set(Encryptkey, key, value, expiresIn)
+}
+
+async function removeEncryptKey(key) {
+  return Factory.Remove(Encryptkey, key)
+}
+
+async function updateEncryptKey(key) {
+  return Factory.Update(Encryptkey, key)
+}
+
+async function getTicket(key, fallback) {
+  return Factory.Get(Ticket, key, fallback)
+}
+
+async function setTicket(key, value, expiresIn) {
+  return Factory.Set(Ticket, key, value, expiresIn)
+}
+
+async function removeTicket(key) {
+  return Factory.Remove(Ticket, key)
+}
+
+async function updateTicket(key) {
+  return Factory.Update(Ticket, key)
+}
+
+module.exports = {
+  getAccessToken,
+  setAccessToken,
+  removeAccessToken,
+  updateAccessToken,
+  getUserAccessToken,
+  setUserAccessToken,
+  removeUserAccessToken,
+  getSessionKey,
+  setSessionKey,
+  removeSessionKey,
+  getEncryptKey,
+  setEncryptKey,
+  removeEncryptKey,
+  updateEncryptKey,
+  getTicket,
+  setTicket,
+  removeTicket,
+  updateTicket,
+  ProviderType,
+  PlatformType,
+  WeixinServer,
+  ErrorCodeType
+}
diff --git a/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/package.json b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/package.json
new file mode 100644
index 0000000..a017b49
--- /dev/null
+++ b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/package.json
@@ -0,0 +1,15 @@
+{
+  "name": "uni-open-bridge-common",
+  "version": "1.0.0",
+  "description": "",
+  "main": "index.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "keywords": [],
+  "author": "",
+  "license": "ISC",
+  "dependencies": {
+    "uni-config-center": "file:../../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center"
+  }
+}
\ No newline at end of file
diff --git a/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/storage.js b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/storage.js
new file mode 100644
index 0000000..bfb13a1
--- /dev/null
+++ b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/storage.js
@@ -0,0 +1,111 @@
+'use strict';
+
+const {
+  Validator
+} = require('./validator.js')
+
+const {
+  CacheKeyCascade
+} = require('./uni-cloud-cache.js')
+
+const {
+  BridgeError
+} = require('./bridge-error.js')
+
+class Storage {
+
+  constructor(type, keys) {
+    this._type = type || null
+    this._keys = keys || []
+  }
+
+  async get(key, fallback) {
+    this.validateKey(key)
+    const result = await this.create(key, fallback).get()
+    return result.value
+  }
+
+  async set(key, value, expiresIn) {
+    this.validateKey(key)
+    this.validateValue(value)
+    const expires_in = this.getExpiresIn(expiresIn)
+    if (expires_in !== 0) {
+      await this.create(key).set(this.getValue(value), expires_in)
+    }
+  }
+
+  async remove(key) {
+    this.validateKey(key)
+    await this.create(key).remove()
+  }
+
+  // virtual
+  async update(key) {
+    this.validateKey(key)
+  }
+
+  async ttl(key) {
+    this.validateKey(key)
+    // 后续考虑支持
+  }
+
+  async fallback(key) {}
+
+  getKeyString(key) {
+    const keyArray = [Storage.Prefix]
+    this._keys.forEach((name) => {
+      keyArray.push(key[name])
+    })
+    keyArray.push(this._type)
+    return keyArray.join(':')
+  }
+
+  getValue(value) {
+    return value
+  }
+
+  getExpiresIn(value) {
+    if (value !== undefined) {
+      return value
+    }
+    return -1
+  }
+
+  validateKey(key) {
+    Validator.Key(this._keys, key)
+  }
+
+  validateValue(value) {
+    Validator.Value(value)
+  }
+
+  create(key, fallback) {
+    const keyString = this.getKeyString(key)
+    const options = {
+      layers: [{
+        type: 'database',
+        key: keyString
+      }, {
+        type: 'redis',
+        key: keyString
+      }]
+    }
+
+    const _this = this
+    return new CacheKeyCascade({
+      ...options,
+      fallback: async function() {
+        if (fallback) {
+          return fallback(key)
+        } else if (_this.fallback) {
+          return _this.fallback(key)
+        }
+      }
+    })
+  }
+}
+Storage.Prefix = "uni-id"
+
+module.exports = {
+  Storage
+};
diff --git a/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/uni-cloud-cache.js b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/uni-cloud-cache.js
new file mode 100644
index 0000000..2e4286b
--- /dev/null
+++ b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/uni-cloud-cache.js
@@ -0,0 +1,324 @@
+const db = uniCloud.database()
+
+function getType(value) {
+  return Object.prototype.toString.call(value).slice(8, -1).toLowerCase()
+}
+
+const validator = {
+  key: function(value) {
+    const err = new Error('Invalid key')
+    if (typeof value !== 'string') {
+      throw err
+    }
+    const valueTrim = value.trim()
+    if (!valueTrim || valueTrim !== value) {
+      throw err
+    }
+  },
+  value: function(value) {
+    // 仅作简单校验
+    const type = getType(value)
+    const validValueType = ['null', 'number', 'string', 'array', 'object']
+    if (validValueType.indexOf(type) === -1) {
+      throw new Error('Invalid value type')
+    }
+  },
+  duration: function(value) {
+    const err = new Error('Invalid duration')
+    if (value === undefined) {
+      return
+    }
+    if (typeof value !== 'number' || value === 0) {
+      throw err
+    }
+  }
+}
+
+/**
+ * 入库时 expired 为过期时间对应的时间戳,永不过期用-1表示
+ * 返回结果时 与redis对齐,-1表示永不过期,-2表示已过期或不存在
+ */
+class DatabaseCache {
+  constructor({
+    collection = 'opendb-open-data'
+  } = {}) {
+    this.type = 'db'
+    this.collection = db.collection(collection)
+  }
+
+  _serializeValue(value) {
+    return value === undefined ? null : JSON.stringify(value)
+  }
+
+  _deserializeValue(value) {
+    return value ? JSON.parse(value) : value
+  }
+
+  async set(key, value, duration) {
+    validator.key(key)
+    validator.value(value)
+    validator.duration(duration)
+    value = this._serializeValue(value)
+    await this.collection.doc(key).set({
+      value,
+      expired: duration && duration !== -1 ? Date.now() + (duration * 1000) : -1
+    })
+  }
+
+  async _getWithDuration(key) {
+    const getKeyRes = await this.collection.doc(key).get()
+    const record = getKeyRes.data[0]
+    if (!record) {
+      return {
+        value: null,
+        duration: -2
+      }
+    }
+    const value = this._deserializeValue(record.value)
+    const expired = record.expired
+    if (expired === -1) {
+      return {
+        value,
+        duration: -1
+      }
+    }
+    const duration = expired - Date.now()
+    if (duration <= 0) {
+      await this.remove(key)
+      return {
+        value: null,
+        duration: -2
+      }
+    }
+    return {
+      value,
+      duration: Math.floor(duration / 1000)
+    }
+  }
+
+  async get(key, {
+    withDuration = true
+  } = {}) {
+    const result = await this._getWithDuration(key)
+    if (!withDuration) {
+      delete result.duration
+    }
+    return result
+  }
+
+  async remove(key) {
+    await this.collection.doc(key).remove()
+  }
+}
+
+class RedisCache {
+  constructor() {
+    this.type = 'redis'
+    this.redis = uniCloud.redis()
+  }
+
+  _serializeValue(value) {
+    return value === undefined ? null : JSON.stringify(value)
+  }
+
+  _deserializeValue(value) {
+    return value ? JSON.parse(value) : value
+  }
+
+  async set(key, value, duration) {
+    validator.key(key)
+    validator.value(value)
+    validator.duration(duration)
+    value = this._serializeValue(value)
+    if (!duration || duration === -1) {
+      await this.redis.set(key, value)
+    } else {
+      await this.redis.set(key, value, 'EX', duration)
+    }
+  }
+
+  async get(key, {
+    withDuration = false
+  } = {}) {
+    let value = await this.redis.get(key)
+    value = this._deserializeValue(value)
+    if (!withDuration) {
+      return {
+        value
+      }
+    }
+    const durationSecond = await this.redis.ttl(key)
+    let duration
+    switch (durationSecond) {
+      case -1:
+        duration = -1
+        break
+      case -2:
+        duration = -2
+        break
+      default:
+        duration = durationSecond
+        break
+    }
+    return {
+      value,
+      duration
+    }
+  }
+
+  async remove(key) {
+    await this.redis.del(key)
+  }
+}
+
+class Cache {
+  constructor({
+    type,
+    collection
+  } = {}) {
+    if (type === 'database') {
+      return new DatabaseCache({
+        collection
+      })
+    } else if (type === 'redis') {
+      return new RedisCache()
+    } else {
+      throw new Error('Invalid cache type')
+    }
+  }
+}
+
+class CacheKey {
+  constructor({
+    type,
+    collection,
+    cache,
+    key,
+    fallback
+  } = {}) {
+    this.cache = cache || new Cache({
+      type,
+      collection
+    })
+    this.key = key
+    this.fallback = fallback
+  }
+
+  async set(value, duration) {
+    await this.cache.set(this.key, value, duration)
+  }
+
+  async setWithSync(value, duration, syncMethod) {
+    await Promise.all([
+      this.set(this.key, value, duration),
+      syncMethod(value, duration)
+    ])
+  }
+
+  async get() {
+    let {
+      value,
+      duration
+    } = await this.cache.get(this.key)
+    if (value !== null && value !== undefined) {
+      return {
+        value,
+        duration
+      }
+    }
+    if (!this.fallback) {
+      return {
+        value: null,
+        duration: -2
+      }
+    }
+    const fallbackResult = await this.fallback()
+    value = fallbackResult.value
+    duration = fallbackResult.duration
+    if (value !== null && duration !== undefined) {
+      await this.cache.set(this.key, value, duration)
+    }
+    return {
+      value,
+      duration
+    }
+  }
+
+  async remove() {
+    await this.cache.remove(this.key)
+  }
+}
+
+class CacheKeyCascade {
+  constructor({
+    layers, // [{cache, type, collection, key}] 从低级到高级排序,[DbCacheKey, RedisCacheKey]
+    fallback
+  } = {}) {
+    this.layers = layers
+    this.cacheLayers = []
+    let lastCacheKey
+    for (let i = 0; i < layers.length; i++) {
+      const {
+        type,
+        cache,
+        collection,
+        key
+      } = layers[i]
+      const lastCacheKeyTemp = lastCacheKey
+      try {
+        const currentCacheKey = new CacheKey({
+          type,
+          collection,
+          cache,
+          key,
+          fallback: i === 0 ? fallback : function() {
+            return lastCacheKeyTemp.get()
+          }
+        })
+        this.cacheLayers.push(currentCacheKey)
+        lastCacheKey = currentCacheKey
+      } catch (e) {}
+    }
+    this.highLevelCache = lastCacheKey
+  }
+
+  async set(value, duration) {
+    return Promise.all(
+      this.cacheLayers.map(item => {
+        return item.set(value, duration)
+      })
+    )
+  }
+
+  async setWithSync(value, duration, syncMethod) {
+    const setPromise = this.cacheLayers.map(item => {
+      return item.set(value, duration)
+    })
+    return Promise.all(
+      [
+        ...setPromise,
+        syncMethod(value, duration)
+      ]
+    )
+  }
+
+  async get() {
+    return this.highLevelCache.get()
+  }
+
+  async remove() {
+    await Promise.all(
+      this.cacheLayers.map(cacheKeyItem => {
+        return cacheKeyItem.remove()
+      })
+    )
+  }
+}
+
+module.exports = {
+  Cache,
+  DatabaseCache,
+  RedisCache,
+  CacheKey,
+  CacheKeyCascade
+}
diff --git a/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/validator.js b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/validator.js
new file mode 100644
index 0000000..47a455b
--- /dev/null
+++ b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/validator.js
@@ -0,0 +1,31 @@
+const Validator = {
+
+  Key(keyArray, parameters) {
+    for (let i = 0; i < keyArray.length; i++) {
+      const keyName = keyArray[i]
+      if (typeof parameters[keyName] !== 'string') {
+        Validator.ThrowNewError(`Invalid ${keyName}`)
+      }
+      if (parameters[keyName].length < 1) {
+        Validator.ThrowNewError(`Invalid ${keyName}`)
+      }
+    }
+  },
+
+  Value(value) {
+    if (value === undefined) {
+      Validator.ThrowNewError('Invalid Value')
+    }
+    if (typeof value !== 'object') {
+      Validator.ThrowNewError('Invalid Value Type')
+    }
+  },
+
+  ThrowNewError(message) {
+    throw new Error(message)
+  }
+}
+
+module.exports = {
+  Validator
+}
diff --git a/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/weixin-server.js b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/weixin-server.js
new file mode 100644
index 0000000..ef476f1
--- /dev/null
+++ b/uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/weixin-server.js
@@ -0,0 +1,203 @@
+'use strict';
+
+const crypto = require('crypto')
+
+const {
+  HTTP_STATUS
+} = require('./consts.js')
+
+const {
+  BridgeError
+} = require('./bridge-error.js')
+
+class WeixinServer {
+
+  constructor(options = {}) {
+    this._appid = options.appid
+    this._secret = options.secret
+  }
+
+  getAccessToken() {
+    return uniCloud.httpclient.request(WeixinServer.AccessToken_Url, {
+      dataType: 'json',
+      method: 'POST',
+      contentType: 'json',
+      data: {
+        appid: this._appid,
+        secret: this._secret,
+        grant_type: "client_credential"
+      }
+    })
+  }
+
+  // 使用客户端获取的 code 从微信服务器换取 openid,code 仅可使用一次
+  codeToSession(code) {
+    return uniCloud.httpclient.request(WeixinServer.Code2Session_Url, {
+      dataType: 'json',
+      data: {
+        appid: this._appid,
+        secret: this._secret,
+        js_code: code,
+        grant_type: 'authorization_code'
+      }
+    })
+  }
+
+  getUserEncryptKey({
+    access_token,
+    openid,
+    session_key
+  }) {
+    console.log(access_token, openid, session_key);
+    const signature = crypto.createHmac('sha256', session_key).update('').digest('hex')
+    return uniCloud.httpclient.request(WeixinServer.User_Encrypt_Key_Url, {
+      dataType: 'json',
+      method: 'POST',
+      dataAsQueryString: true,
+      data: {
+        access_token,
+        openid: openid,
+        signature: signature,
+        sig_method: 'hmac_sha256'
+      }
+    })
+  }
+
+  getH5AccessToken() {
+    return uniCloud.httpclient.request(WeixinServer.AccessToken_H5_Url, {
+      dataType: 'json',
+      method: 'GET',
+      data: {
+        appid: this._appid,
+        secret: this._secret,
+        grant_type: "client_credential"
+      }
+    })
+  }
+
+  getH5Ticket(access_token) {
+    return uniCloud.httpclient.request(WeixinServer.Ticket_Url, {
+      dataType: 'json',
+      dataAsQueryString: true,
+      method: 'POST',
+      data: {
+        access_token
+      }
+    })
+  }
+
+  getH5AccessTokenForEip() {
+    return uniCloud.httpProxyForEip.postForm(WeixinServer.AccessToken_H5_Url, {
+      appid: this._appid,
+      secret: this._secret,
+      grant_type: "client_credential"
+    }, {
+      dataType: 'json'
+    })
+  }
+
+  getH5TicketForEip(access_token) {
+    return uniCloud.httpProxyForEip.postForm(WeixinServer.Ticket_Url, {
+      access_token
+    }, {
+      dataType: 'json',
+      dataAsQueryString: true
+    })
+  }
+}
+
+WeixinServer.AccessToken_Url = 'https://api.weixin.qq.com/cgi-bin/stable_token'
+WeixinServer.Code2Session_Url = 'https://api.weixin.qq.com/sns/jscode2session'
+WeixinServer.User_Encrypt_Key_Url = 'https://api.weixin.qq.com/wxa/business/getuserencryptkey'
+WeixinServer.AccessToken_H5_Url = 'https://api.weixin.qq.com/cgi-bin/token'
+WeixinServer.Ticket_Url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi'
+
+WeixinServer.GetMPAccessToken = function(options) {
+  return new WeixinServer(options).getAccessToken()
+}
+
+WeixinServer.GetCodeToSession = function(options) {
+  return new WeixinServer(options).codeToSession(options.code)
+}
+
+WeixinServer.GetUserEncryptKey = function(options) {
+  return new WeixinServer(options).getUserEncryptKey(options)
+}
+
+WeixinServer.GetH5AccessToken = function(options) {
+  return new WeixinServer(options).getH5AccessToken()
+}
+
+WeixinServer.GetH5Ticket = function(options) {
+  return new WeixinServer(options).getH5Ticket(options.access_token)
+}
+
+////////////////////////////////////////////////////////////////
+
+function isAliyun() {
+  return (uniCloud.getCloudInfos()[0].provider === 'aliyun')
+}
+
+WeixinServer.GetResponseData = function(response) {
+  console.log("WeixinServer::response", response)
+
+  if (!(response.status === HTTP_STATUS.SUCCESS || response.statusCodeValue === HTTP_STATUS.SUCCESS)) {
+    throw new BridgeError(response.status || response.statusCodeValue, response.status || response.statusCodeValue)
+  }
+
+  const responseData = response.data || response.body
+
+  if (responseData.errcode !== undefined && responseData.errcode !== 0) {
+    throw new BridgeError(responseData.errcode, responseData.errmsg)
+  }
+
+  return responseData
+}
+
+WeixinServer.GetMPAccessTokenData = async function(options) {
+  const response = await new WeixinServer(options).getAccessToken()
+  return WeixinServer.GetResponseData(response)
+}
+
+WeixinServer.GetCodeToSessionData = async function(options) {
+  const response = await new WeixinServer(options).codeToSession(options.code)
+  return WeixinServer.GetResponseData(response)
+}
+
+WeixinServer.GetUserEncryptKeyData = async function(options) {
+  const response = await new WeixinServer(options).getUserEncryptKey(options)
+  return WeixinServer.GetResponseData(response)
+}
+
+WeixinServer.GetH5AccessTokenData = async function(options) {
+  const ws = new WeixinServer(options)
+  let response
+  if (isAliyun()) {
+    response = await ws.getH5AccessTokenForEip()
+    if (typeof response === 'string') {
+      response = JSON.parse(response)
+    }
+  } else {
+    response = await ws.getH5AccessToken()
+  }
+  return WeixinServer.GetResponseData(response)
+}
+
+WeixinServer.GetH5TicketData = async function(options) {
+  const ws = new WeixinServer(options)
+  let response
+  if (isAliyun()) {
+    response = await ws.getH5TicketForEip(options.access_token)
+    if (typeof response === 'string') {
+      response = JSON.parse(response)
+    }
+  } else {
+    response = await ws.getH5Ticket(options.access_token)
+  }
+  return WeixinServer.GetResponseData(response)
+}
+
+
+module.exports = {
+  WeixinServer
+}