Sfoglia il codice sorgente

对接楼栋之前

19124812874 5 anni fa
parent
commit
ba542bc3f4
95 ha cambiato i file con 7943 aggiunte e 3988 eliminazioni
  1. 33 2
      App.vue
  2. 16 0
      assets/css/app.css
  3. 55 0
      comps/mescroll-body/components/mescroll-down.css
  4. 47 0
      comps/mescroll-body/components/mescroll-down.vue
  5. 90 0
      comps/mescroll-body/components/mescroll-empty.vue
  6. 83 0
      comps/mescroll-body/components/mescroll-top.vue
  7. 47 0
      comps/mescroll-body/components/mescroll-up.css
  8. 39 0
      comps/mescroll-body/components/mescroll-up.vue
  9. 19 0
      comps/mescroll-body/mescroll-body.css
  10. 348 0
      comps/mescroll-body/mescroll-body.vue
  11. 65 0
      comps/mescroll-body/mescroll-mixins.js
  12. 36 0
      comps/mescroll-body/mescroll-uni-option.js
  13. 36 0
      comps/mescroll-body/mescroll-uni.css
  14. 799 0
      comps/mescroll-body/mescroll-uni.js
  15. 430 0
      comps/mescroll-body/mescroll-uni.vue
  16. 48 0
      comps/mescroll-body/mixins/mescroll-comp.js
  17. 59 0
      comps/mescroll-body/mixins/mescroll-more-item.js
  18. 74 0
      comps/mescroll-body/mixins/mescroll-more.js
  19. 109 0
      comps/mescroll-body/wxs/mixins.js
  20. 92 0
      comps/mescroll-body/wxs/renderjs.js
  21. 268 0
      comps/mescroll-body/wxs/wxs.wxs
  22. 35 0
      main.js
  23. 50 14
      pages.json
  24. 73 17
      pages/auth/auth.vue
  25. 163 164
      pages/authorize_record/authorize_record.vue
  26. 56 126
      pages/authorize_record/openPass/openPass.vue
  27. 160 0
      pages/choosePlot/chooseBuilding/chooseBuilding.vue
  28. 51 54
      pages/choosePlot/choosePlot.vue
  29. 43 23
      pages/choosePlot/chooseRoom/chooseRoom.vue
  30. 31 32
      pages/choosePlot/chooseUnit/chooseUnit.vue
  31. 26 30
      pages/choosePlot/householdCert/householdCert.vue
  32. 0 2
      pages/community/community.vue
  33. 1 1
      pages/community/detail/carDetail.vue
  34. 21 1
      pages/demo/demo2.vue
  35. 480 26
      pages/guest/guest_form.vue
  36. 32 13
      pages/guest/open_door.vue
  37. 212 0
      pages/healthCode/healthCode.vue
  38. 68 46
      pages/index/index.vue
  39. 1 1
      pages/my-camera/my-camera.vue
  40. 40 44
      pages/myFamily/activateFace/activateFace.vue
  41. 17 15
      pages/myFamily/add/add.vue
  42. 50 45
      pages/myFamily/addFamily/addFamily.vue
  43. 151 0
      pages/myFamily/apply-card.vue
  44. 146 0
      pages/myFamily/audit-card.vue
  45. 248 0
      pages/myFamily/audit-detail/audit-detail.vue
  46. 37 22
      pages/myFamily/editApplyFamily/editApplyFamily.vue
  47. 21 13
      pages/myFamily/editFamily/editFamily.vue
  48. 228 0
      pages/myFamily/item.vue
  49. 148 804
      pages/myFamily/myFamily.vue
  50. 847 0
      pages/myFamily/myfamily1.vue
  51. 204 0
      pages/myFamily/user-card.vue
  52. 3 3
      pages/myPassword/myPassword.vue
  53. 109 214
      pages/myhome/familyList.vue
  54. 128 134
      pages/myhome/myhome.vue
  55. 153 0
      pages/record/card.vue
  56. 171 0
      pages/record/item.vue
  57. 203 154
      pages/record/record.vue
  58. 12 5
      pages/register/register.vue
  59. 1 1
      pages/services/property/comment.vue
  60. 7 7
      pages/services/property/detail.vue
  61. 3 3
      pages/services/property/list/card.vue
  62. 4 3
      pages/services/property/list/item.vue
  63. 1 1
      pages/services/property/list/list.vue
  64. 5 10
      pages/services/property/property.vue
  65. 1 2
      pages/switchcity/switchcity.vue
  66. 48 28
      pages/tool-list/epidemic-pass/detail.vue
  67. 133 7
      pages/tool-list/epidemic-pass/epidemic-pass.vue
  68. 120 0
      pages/tool-list/epidemic-pass/list.vue
  69. 2 11
      pages/uploadFace/uploadFace.vue
  70. 9 2
      pages/webview/webview.vue
  71. 1 1
      pages/wode/direction/direction.vue
  72. 36 24
      pages/wode/wode.vue
  73. 37 18
      pagesM/comps/canvas/index.vue
  74. 2 8
      pagesM/comps/canvas/poster.vue
  75. 3 3
      pagesM/comps/dt_order_item.vue
  76. 50 36
      pagesM/pages/goods_des.vue
  77. 0 1781
      pagesM/pages/goods_des_old.vue
  78. 16 9
      pagesM/pages/mine_info.vue
  79. 1 1
      pagesM/pages/mine_order_list.vue
  80. 135 8
      pagesM/pages/mine_protocal.vue
  81. 11 10
      pagesM/pages/mine_setting.vue
  82. 6 6
      pagesM/pages/order_detail.vue
  83. 3 0
      pagesM/pages/order_pay.vue
  84. BIN
      static/call.png
  85. BIN
      static/common/unit.png
  86. BIN
      static/dialog/dialog_fail.png
  87. BIN
      static/dialog/dialog_success.png
  88. BIN
      static/dialog/dialog_warn.png
  89. BIN
      static/home/health.png
  90. BIN
      static/home/health5.png
  91. BIN
      static/noImg.png
  92. BIN
      static/wode/jiaofei1.png
  93. 26 0
      store/$u.mixin.js
  94. 67 0
      store/index.js
  95. 3 3
      utils/dialog.js

+ 33 - 2
App.vue

@@ -79,9 +79,9 @@
 			token: "j2qctr89u1xfmbjkp69hegfmqhwquycw",
 			//对接后台的api地址
 			//远程的
-			// apiurl: "http://192.168.2.200:9082/app/",
 			apiurl: "https://community.58fo.com/api/app/",
-			
+			// apiurl: "http://192.168.1.117:9082/app/",
+			// apiurl: "http://192.168.0.104:9082/app/",
 			member: null,
 			//用户信息--后台
 			userInfo: null,
@@ -136,6 +136,37 @@
 			    }
 			  });
 			},
+			postRequestAsync: function (params,operation) {
+			  let that = this; //公共参数
+			  params['org_id'] = that.org_id;
+			  params['token'] = that.token; 
+			  let jsonStr = JSON.stringify(params); //数据md5签名
+			  let dataSign = md5.hex_md5(jsonStr);
+			   return new Promise((resolve,reject)=>{
+				  uni.request({
+					  url: that.apiurl + operation,
+					  method: 'POST',
+					  header: {
+						'content-type': 'application/json',
+						'data-sign': dataSign
+					  },
+					  data: jsonStr,
+					  success: (res)=>{
+						  resolve(res)
+					  },
+					  fail: (err)=>{
+						  uni.hideLoading();
+						  uni.showModal({
+							title: '警告',
+							content: '网络异常' + res.errMsg,
+							showCancel: false,
+							confirmText: '确认'
+						  });
+					  }
+				  })
+			  })
+			},
+			
 			//上传文件
 			uploadBase64: function (base_64_str, is_need_md5, callback) {
 			  let that = this;

+ 16 - 0
assets/css/app.css

@@ -19,4 +19,20 @@
 .bg-btn{
 	color: #FFFFFF;
 	background-color: #2f7ff5;
+}
+
+.text-success{
+	color: #19be6b;
+}
+
+.text-warning{
+	color: #ff9900;
+}
+
+.text-error{
+	color: #fa3534;
+}
+
+.text-info{
+	color: #909399;
 }

+ 55 - 0
comps/mescroll-body/components/mescroll-down.css

@@ -0,0 +1,55 @@
+/* 下拉刷新区域 */
+.mescroll-downwarp {
+	position: absolute;
+	top: -100%;
+	left: 0;
+	width: 100%;
+	height: 100%;
+	text-align: center;
+}
+
+/* 下拉刷新--内容区,定位于区域底部 */
+.mescroll-downwarp .downwarp-content {
+	position: absolute;
+	left: 0;
+	bottom: 0;
+	width: 100%;
+	min-height: 60rpx;
+	padding: 20rpx 0;
+	text-align: center;
+}
+
+/* 下拉刷新--提示文本 */
+.mescroll-downwarp .downwarp-tip {
+	display: inline-block;
+	font-size: 28rpx;
+	vertical-align: middle;
+	margin-left: 16rpx;
+	/* color: gray; 已在style设置color,此处删去*/
+}
+
+/* 下拉刷新--旋转进度条 */
+.mescroll-downwarp .downwarp-progress {
+	display: inline-block;
+	width: 32rpx;
+	height: 32rpx;
+	border-radius: 50%;
+	border: 2rpx solid gray;
+	border-bottom-color: transparent !important; /*已在style设置border-color,此处需加 !important*/
+	vertical-align: middle;
+}
+
+/* 旋转动画 */
+.mescroll-downwarp .mescroll-rotate {
+	animation: mescrollDownRotate 0.6s linear infinite;
+}
+
+@keyframes mescrollDownRotate {
+	0% {
+		transform: rotate(0deg);
+	}
+
+	100% {
+		transform: rotate(360deg);
+	}
+}

+ 47 - 0
comps/mescroll-body/components/mescroll-down.vue

@@ -0,0 +1,47 @@
+<!-- 下拉刷新区域 -->
+<template>
+	<view v-if="mOption.use" class="mescroll-downwarp" :style="{'background-color':mOption.bgColor,'color':mOption.textColor}">
+		<view class="downwarp-content">
+			<view class="downwarp-progress" :class="{'mescroll-rotate': isDownLoading}" :style="{'border-color':mOption.textColor, 'transform':downRotate}"></view>
+			<view class="downwarp-tip">{{downText}}</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	props: {
+		option: Object , // down的配置项
+		type: Number, // 下拉状态(inOffset:1, outOffset:2, showLoading:3, endDownScroll:4)
+		rate: Number // 下拉比率 (inOffset: rate<1; outOffset: rate>=1)
+	},
+	computed: {
+		// 支付宝小程序需写成计算属性,prop定义default仍报错
+		mOption(){
+			return this.option || {}
+		},
+		// 是否在加载中
+		isDownLoading(){
+			return this.type === 3
+		},
+		// 旋转的角度
+		downRotate(){
+			return 'rotate(' + 360 * this.rate + 'deg)'
+		},
+		// 文本提示
+		downText(){
+			switch (this.type){
+				case 1: return this.mOption.textInOffset;
+				case 2: return this.mOption.textOutOffset;
+				case 3: return this.mOption.textLoading;
+				case 4: return this.mOption.textLoading;
+				default: return this.mOption.textInOffset;
+			}
+		}
+	}
+};
+</script>
+
+<style>
+@import "./mescroll-down.css";
+</style>

+ 90 - 0
comps/mescroll-body/components/mescroll-empty.vue

@@ -0,0 +1,90 @@
+<!--空布局
+
+可作为独立的组件, 不使用mescroll的页面也能单独引入, 以便APP全局统一管理:
+import MescrollEmpty from '@/components/mescroll-uni/components/mescroll-empty.vue';
+<mescroll-empty v-if="isShowEmpty" :option="optEmpty" @emptyclick="emptyClick"></mescroll-empty>
+
+-->
+<template>
+	<view class="mescroll-empty" :class="{ 'empty-fixed': option.fixed }" :style="{ 'z-index': option.zIndex, top: option.top }">
+		<view> <image v-if="icon" class="empty-icon" :src="icon" mode="widthFix" /> </view>
+		<view v-if="tip" class="empty-tip">{{ tip }}</view>
+		<view v-if="option.btnText" class="empty-btn" @click="emptyClick">{{ option.btnText }}</view>
+	</view>
+</template>
+
+<script>
+// 引入全局配置
+import GlobalOption from './../mescroll-uni-option.js';
+export default {
+	props: {
+		// empty的配置项: 默认为GlobalOption.up.empty
+		option: {
+			type: Object,
+			default() {
+				return {};
+			}
+		}
+	},
+	// 使用computed获取配置,用于支持option的动态配置
+	computed: {
+		// 图标
+		icon() {
+			return this.option.icon == null ? GlobalOption.up.empty.icon : this.option.icon; // 此处不使用短路求值, 用于支持传空串不显示图标
+		},
+		// 文本提示
+		tip() {
+			return this.option.tip == null ? GlobalOption.up.empty.tip : this.option.tip; // 此处不使用短路求值, 用于支持传空串不显示文本提示
+		}
+	},
+	methods: {
+		// 点击按钮
+		emptyClick() {
+			this.$emit('emptyclick');
+		}
+	}
+};
+</script>
+
+<style>	
+/* 无任何数据的空布局 */
+.mescroll-empty {
+	box-sizing: border-box;
+	width: 100%;
+	padding: 300rpx 50rpx 0;
+	text-align: center;
+}
+
+.mescroll-empty.empty-fixed {
+	z-index: 99;
+	position: absolute; /*transform会使fixed失效,最终会降级为absolute */
+	top: 100rpx;
+	left: 0;
+}
+
+.mescroll-empty .empty-icon {
+	width: 280rpx;
+	height: 280rpx;
+}
+
+.mescroll-empty .empty-tip {
+	margin-top: 20rpx;
+	font-size: 24rpx;
+	color: gray;
+}
+
+.mescroll-empty .empty-btn {
+	display: inline-block;
+	margin-top: 40rpx;
+	min-width: 200rpx;
+	padding: 18rpx;
+	font-size: 28rpx;
+	border: 1rpx solid #e04b28;
+	border-radius: 60rpx;
+	color: #e04b28;
+}
+
+.mescroll-empty .empty-btn:active {
+	opacity: 0.75;
+}
+</style>

+ 83 - 0
comps/mescroll-body/components/mescroll-top.vue

@@ -0,0 +1,83 @@
+<!-- 回到顶部的按钮 -->
+<template>
+	<image
+		v-if="mOption.src"
+		class="mescroll-totop"
+		:class="[value ? 'mescroll-totop-in' : 'mescroll-totop-out', {'mescroll-totop-safearea': mOption.safearea}]"
+		:style="{'z-index':mOption.zIndex, 'left': left, 'right': right, 'bottom':addUnit(mOption.bottom), 'width':addUnit(mOption.width), 'border-radius':addUnit(mOption.radius)}"
+		:src="mOption.src"
+		mode="widthFix"
+		@click="toTopClick"
+	/>
+</template>
+
+<script>
+export default {
+	props: {
+		// up.toTop的配置项
+		option: Object,
+		// 是否显示
+		value: false
+	},
+	computed: {
+		// 支付宝小程序需写成计算属性,prop定义default仍报错
+		mOption(){
+			return this.option || {}
+		},
+		// 优先显示左边
+		left(){
+			return this.mOption.left ? this.addUnit(this.mOption.left) : 'auto';
+		},
+		// 右边距离 (优先显示左边)
+		right() {
+			return this.mOption.left ? 'auto' : this.addUnit(this.mOption.right);
+		}
+	},
+	methods: {
+		addUnit(num){
+			if(!num) return 0;
+			if(typeof num === 'number') return num + 'rpx';
+			return num
+		},
+		toTopClick() {
+			this.$emit('input', false); // 使v-model生效
+			this.$emit('click'); // 派发点击事件
+		}
+	}
+};
+</script>
+
+<style>
+/* 回到顶部的按钮 */
+.mescroll-totop {
+	z-index: 9990;
+	position: fixed !important; /* 加上important避免编译到H5,在多mescroll中定位失效 */
+	right: 20rpx;
+	bottom: 120rpx;
+	width: 72rpx;
+	height: auto;
+	border-radius: 50%;
+	opacity: 0;
+	transition: opacity 0.5s; /* 过渡 */
+	margin-bottom: var(--window-bottom); /* css变量 */
+}
+
+/* 适配 iPhoneX */
+@supports (bottom: constant(safe-area-inset-bottom)) or (bottom: env(safe-area-inset-bottom)) {
+	.mescroll-totop-safearea {
+		margin-bottom: calc(var(--window-bottom) + constant(safe-area-inset-bottom)); /* window-bottom + 适配 iPhoneX */
+		margin-bottom: calc(var(--window-bottom) + env(safe-area-inset-bottom));
+	}
+}
+
+/* 显示 -- 淡入 */
+.mescroll-totop-in {
+	opacity: 1;
+}
+
+/* 隐藏 -- 淡出且不接收事件*/
+.mescroll-totop-out {
+	opacity: 0;
+	pointer-events: none;
+}
+</style>

+ 47 - 0
comps/mescroll-body/components/mescroll-up.css

@@ -0,0 +1,47 @@
+/* 上拉加载区域 */
+.mescroll-upwarp {
+	box-sizing: border-box;
+	min-height: 110rpx;
+	padding: 30rpx 0;
+	text-align: center;
+	clear: both;
+}
+
+/*提示文本 */
+.mescroll-upwarp .upwarp-tip,
+.mescroll-upwarp .upwarp-nodata {
+	display: inline-block;
+	font-size: 28rpx;
+	vertical-align: middle;
+	/* color: gray; 已在style设置color,此处删去*/
+}
+
+.mescroll-upwarp .upwarp-tip {
+	margin-left: 16rpx;
+}
+
+/*旋转进度条 */
+.mescroll-upwarp .upwarp-progress {
+	display: inline-block;
+	width: 32rpx;
+	height: 32rpx;
+	border-radius: 50%;
+	border: 2rpx solid gray;
+	border-bottom-color: transparent !important; /*已在style设置border-color,此处需加 !important*/
+	vertical-align: middle;
+}
+
+/* 旋转动画 */
+.mescroll-upwarp .mescroll-rotate {
+	animation: mescrollUpRotate 0.6s linear infinite;
+}
+
+@keyframes mescrollUpRotate {
+	0% {
+		transform: rotate(0deg);
+	}
+
+	100% {
+		transform: rotate(360deg);
+	}
+}

+ 39 - 0
comps/mescroll-body/components/mescroll-up.vue

@@ -0,0 +1,39 @@
+<!-- 上拉加载区域 -->
+<template>
+	<view class="mescroll-upwarp" :style="{'background-color':mOption.bgColor,'color':mOption.textColor}">
+		<!-- 加载中 (此处不能用v-if,否则android小程序快速上拉可能会不断触发上拉回调) -->
+		<view v-show="isUpLoading">
+			<view class="upwarp-progress mescroll-rotate" :style="{'border-color':mOption.textColor}"></view>
+			<view class="upwarp-tip">{{ mOption.textLoading }}</view>
+		</view>
+		<!-- 无数据 -->
+		<view v-if="isUpNoMore" class="upwarp-nodata">{{ mOption.textNoMore }}</view>
+	</view>
+</template>
+
+<script>
+export default {
+	props: {
+		option: Object, // up的配置项
+		type: Number // 上拉加载的状态:0(loading前),1(loading中),2(没有更多了)
+	},
+	computed: {
+		// 支付宝小程序需写成计算属性,prop定义default仍报错
+		mOption() {
+			return this.option || {};
+		},
+		// 加载中
+		isUpLoading() {
+			return this.type === 1;
+		},
+		// 没有更多了
+		isUpNoMore() {
+			return this.type === 2;
+		}
+	}
+};
+</script>
+
+<style>
+@import './mescroll-up.css';
+</style>

+ 19 - 0
comps/mescroll-body/mescroll-body.css

@@ -0,0 +1,19 @@
+.mescroll-body {
+	position: relative; /* 下拉刷新区域相对自身定位 */
+	height: auto; /* 不可固定高度,否则overflow:hidden导致无法滑动; 同时使设置的最小高生效,实现列表不满屏仍可下拉*/
+	overflow: hidden; /* 当有元素写在mescroll-body标签前面时,可遮住下拉刷新区域 */
+	box-sizing: border-box; /* 避免设置padding出现双滚动条的问题 */
+}
+
+/* 使sticky生效: 父元素不能overflow:hidden或者overflow:auto属性 */
+.mescroll-body.mescorll-sticky{
+	overflow: unset !important
+}
+
+/* 适配 iPhoneX */
+@supports (bottom: constant(safe-area-inset-bottom)) or (bottom: env(safe-area-inset-bottom)) {
+	.mescroll-safearea {
+		padding-bottom: constant(safe-area-inset-bottom);
+		padding-bottom: env(safe-area-inset-bottom);
+	}
+}

+ 348 - 0
comps/mescroll-body/mescroll-body.vue

@@ -0,0 +1,348 @@
+<template>
+	<view 
+	class="mescroll-body mescroll-render-touch" 
+	:class="{'mescorll-sticky': sticky}"
+	:style="{'minHeight':minHeight, 'padding-top': padTop, 'padding-bottom': padBottom,'background-color': isShowEmpty?'#FFFFFF':'#f1f1f1'}" 
+	@touchstart="wxsBiz.touchstartEvent" 
+	@touchmove="wxsBiz.touchmoveEvent" 
+	@touchend="wxsBiz.touchendEvent" 
+	@touchcancel="wxsBiz.touchendEvent"
+	:change:prop="wxsBiz.propObserver"
+	:prop="wxsProp"
+	>
+		<!-- 状态栏 -->
+		<view v-if="topbar&&statusBarHeight" class="mescroll-topbar" :style="{height: statusBarHeight+'px', background: topbar}"></view>
+		
+		<view class="mescroll-body-content mescroll-wxs-content" :style="{ transform: translateY, transition: transition }" :change:prop="wxsBiz.callObserver" :prop="callProp">
+			<!-- 下拉加载区域 (支付宝小程序子组件传参给子子组件仍报单项数据流的异常,暂时不通过mescroll-down组件实现)-->
+			<!-- <mescroll-down :option="mescroll.optDown" :type="downLoadType" :rate="downRate"></mescroll-down> -->
+			<view v-if="mescroll.optDown.use" class="mescroll-downwarp" :style="{'background':mescroll.optDown.bgColor,'color':mescroll.optDown.textColor}">
+				<view class="downwarp-content">
+					<view class="downwarp-progress mescroll-wxs-progress" :class="{'mescroll-rotate': isDownLoading}" :style="{'border-color':mescroll.optDown.textColor, 'transform': downRotate}"></view>
+					<view class="downwarp-tip">{{downText}}</view>
+				</view>
+			</view>
+	
+			<!-- 列表内容 -->
+			<slot></slot>
+
+			<!-- 空布局 -->
+			<mescroll-empty v-if="isShowEmpty" :option="mescroll.optUp.empty" @emptyclick="emptyClick"></mescroll-empty>
+
+			<!-- 上拉加载区域 (下拉刷新时不显示, 支付宝小程序子组件传参给子子组件仍报单项数据流的异常,暂时不通过mescroll-up组件实现)-->
+			<!-- <mescroll-up v-if="mescroll.optUp.use && !isDownLoading && upLoadType!==3" :option="mescroll.optUp" :type="upLoadType"></mescroll-up> -->
+			<view v-if="mescroll.optUp.use && !isDownLoading && upLoadType!==3" class="mescroll-upwarp" :style="{'background':mescroll.optUp.bgColor,'color':mescroll.optUp.textColor}">
+				<!-- 加载中 (此处不能用v-if,否则android小程序快速上拉可能会不断触发上拉回调) -->
+				<view v-show="upLoadType===1">
+					<view class="upwarp-progress mescroll-rotate" :style="{'border-color':mescroll.optUp.textColor}"></view>
+					<view class="upwarp-tip">{{ mescroll.optUp.textLoading }}</view>
+				</view>
+				<!-- 无数据 -->
+				<view v-if="upLoadType===2" class="upwarp-nodata">{{ mescroll.optUp.textNoMore }}</view>
+			</view>
+		</view>
+		
+		<!-- 底部是否偏移TabBar的高度(默认仅在H5端的tab页生效) -->
+		<!-- #ifdef H5 -->
+		<view v-if="bottombar && windowBottom>0" class="mescroll-bottombar" :style="{height: windowBottom+'px'}"></view>
+		<!-- #endif -->
+		
+		<!-- 适配iPhoneX -->
+		<view v-if="safearea" class="mescroll-safearea"></view>
+		
+		<!-- 回到顶部按钮 (fixed元素需写在transform外面,防止降级为absolute)-->
+		<mescroll-top v-model="isShowToTop" :option="mescroll.optUp.toTop" @click="toTopClick"></mescroll-top>
+		
+		<!-- #ifdef MP-WEIXIN || MP-QQ || APP-PLUS || H5 -->
+		<!-- renderjs的数据载体,不可写在mescroll-downwarp内部,避免use为false时,载体丢失,无法更新数据 -->
+		<view :change:prop="renderBiz.propObserver" :prop="wxsProp"></view>
+		<!-- #endif -->
+	</view>
+</template>
+
+<!-- 微信小程序, QQ小程序, app, h5使用wxs -->
+<!-- #ifdef MP-WEIXIN || MP-QQ || APP-PLUS || H5 -->
+<script src="./wxs/wxs.wxs" module="wxsBiz" lang="wxs"></script>
+<!-- #endif -->
+
+<!-- app, h5使用renderjs -->
+<!-- #ifdef APP-PLUS || H5 -->
+<script module="renderBiz" lang="renderjs">
+	import renderBiz from './wxs/renderjs.js';
+	export default {
+		mixins: [renderBiz]
+	}
+</script>
+<!-- #endif -->
+
+<script>
+	// 引入mescroll-uni.js,处理核心逻辑
+	import MeScroll from './mescroll-uni.js';
+	// 引入全局配置
+	import GlobalOption from './mescroll-uni-option.js';
+	// 引入空布局组件
+	import MescrollEmpty from './components/mescroll-empty.vue';
+	// 引入回到顶部组件
+	import MescrollTop from './components/mescroll-top.vue';
+	// 引入兼容wxs(含renderjs)写法的mixins
+	import WxsMixin from './wxs/mixins.js';
+	
+	export default {
+		mixins: [WxsMixin],
+		components: {
+			MescrollEmpty,
+			MescrollTop
+		},
+		data() {
+			return {
+				mescroll: {optDown:{},optUp:{}}, // mescroll实例
+				downHight: 0, //下拉刷新: 容器高度
+				downRate: 0, // 下拉比率(inOffset: rate<1; outOffset: rate>=1)
+				downLoadType: 0, // 下拉刷新状态: 0(loading前), 1(inOffset), 2(outOffset), 3(showLoading), 4(endDownScroll)
+				upLoadType: 0, // 上拉加载状态:0(loading前),1(loading中),2(没有更多了,显示END文本提示),3(没有更多了,不显示END文本提示)
+				isShowEmpty: false, // 是否显示空布局
+				isShowToTop: false, // 是否显示回到顶部按钮
+				windowHeight: 0, // 可使用窗口的高度
+				windowBottom: 0, // 可使用窗口的底部位置
+				statusBarHeight: 0 // 状态栏高度
+			};
+		},
+		props: {
+			down: Object, // 下拉刷新的参数配置
+			up: Object, // 上拉加载的参数配置
+			top: [String, Number], // 下拉布局往下的偏移量 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx, 百分比则相对于windowHeight)
+			topbar: [Boolean, String], // top的偏移量是否加上状态栏高度, 默认false (使用场景:取消原生导航栏时,配置此项可留出状态栏的占位, 支持传入字符串背景,如色值,背景图,渐变)
+			bottom: [String, Number], // 上拉布局往上的偏移量 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx, 百分比则相对于windowHeight)
+			safearea: Boolean, // bottom的偏移量是否加上底部安全区的距离, 默认false (需要适配iPhoneX时使用)
+			height: [String, Number], // 指定mescroll最小高度,默认windowHeight,使列表不满屏仍可下拉
+			bottombar:{ // 底部是否偏移TabBar的高度(默认仅在H5端的tab页生效)
+				type: Boolean,
+				default: true
+			},
+			sticky: Boolean // 是否支持sticky,默认false; 当值配置true时,需避免在mescroll-body标签前面加非定位的元素,否则下拉区域无法会隐藏
+		},
+		computed: {
+			// mescroll最小高度,默认windowHeight,使列表不满屏仍可下拉
+			minHeight(){
+				return this.toPx(this.height || '100%') + 'px'
+			},
+			// 下拉布局往下偏移的距离 (px)
+			numTop() {
+				return this.toPx(this.top)
+			},
+			padTop() {
+				return this.numTop + 'px';
+			},
+			// 上拉布局往上偏移 (px)
+			numBottom() {
+				return this.toPx(this.bottom);
+			},
+			padBottom() {
+				return this.numBottom + 'px';
+			},
+			// 是否为重置下拉的状态
+			isDownReset() {
+				return this.downLoadType === 3 || this.downLoadType === 4;
+			},
+			// 过渡
+			transition() {
+				return this.isDownReset ? 'transform 300ms' : '';
+			},
+			translateY() {
+				return this.downHight > 0 ? 'translateY(' + this.downHight + 'px)' : ''; // transform会使fixed失效,需注意把fixed元素写在mescroll之外
+			},
+			// 是否在加载中
+			isDownLoading(){
+				return this.downLoadType === 3
+			},
+			// 旋转的角度
+			downRotate(){
+				return 'rotate(' + 360 * this.downRate + 'deg)'
+			},
+			// 文本提示
+			downText(){
+				if(!this.mescroll) return ""; // 避免头条小程序初始化时报错
+				switch (this.downLoadType){
+					case 1: return this.mescroll.optDown.textInOffset;
+					case 2: return this.mescroll.optDown.textOutOffset;
+					case 3: return this.mescroll.optDown.textLoading;
+					case 4: return this.mescroll.isDownEndSuccess ? this.mescroll.optDown.textSuccess : this.mescroll.isDownEndSuccess==false ? this.mescroll.optDown.textErr : this.mescroll.optDown.textInOffset;
+					default: return this.mescroll.optDown.textInOffset;
+				}
+			}
+		},
+		methods: {
+			//number,rpx,upx,px,% --> px的数值
+			toPx(num) {
+				if (typeof num === 'string') {
+					if (num.indexOf('px') !== -1) {
+						if (num.indexOf('rpx') !== -1) {
+							// "10rpx"
+							num = num.replace('rpx', '');
+						} else if (num.indexOf('upx') !== -1) {
+							// "10upx"
+							num = num.replace('upx', '');
+						} else {
+							// "10px"
+							return Number(num.replace('px', ''));
+						}
+					} else if (num.indexOf('%') !== -1) {
+						// 传百分比,则相对于windowHeight,传"10%"则等于windowHeight的10%
+						let rate = Number(num.replace('%', '')) / 100;
+						return this.windowHeight * rate;
+					}
+				}
+				return num ? uni.upx2px(Number(num)) : 0;
+			},
+			// 点击空布局的按钮回调
+			emptyClick() {
+				this.$emit('emptyclick', this.mescroll);
+			},
+			// 点击回到顶部的按钮回调
+			toTopClick() {
+				this.mescroll.scrollTo(0, this.mescroll.optUp.toTop.duration); // 执行回到顶部
+				this.$emit('topclick', this.mescroll); // 派发点击回到顶部按钮的回调
+			}
+		},
+		// 使用created初始化mescroll对象; 如果用mounted部分css样式编译到H5会失效
+		created() {
+			let vm = this;
+
+			let diyOption = {
+				// 下拉刷新的配置
+				down: {
+					inOffset() {
+						vm.downLoadType = 1; // 下拉的距离进入offset范围内那一刻的回调 (自定义mescroll组件时,此行不可删)
+					},
+					outOffset() {
+						vm.downLoadType = 2; // 下拉的距离大于offset那一刻的回调 (自定义mescroll组件时,此行不可删)
+					},
+					onMoving(mescroll, rate, downHight) {
+						// 下拉过程中的回调,滑动过程一直在执行;
+						vm.downHight = downHight; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
+						vm.downRate = rate; //下拉比率 (inOffset: rate<1; outOffset: rate>=1)
+					},
+					showLoading(mescroll, downHight) {
+						vm.downLoadType = 3; // 显示下拉刷新进度的回调 (自定义mescroll组件时,此行不可删)
+						vm.downHight = downHight; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
+					},
+					beforeEndDownScroll(mescroll){
+						vm.downLoadType = 4; 
+						return mescroll.optDown.beforeEndDelay // 延时结束的时长
+					},
+					endDownScroll() {
+						vm.downLoadType = 4; // 结束下拉 (自定义mescroll组件时,此行不可删)
+						vm.downHight = 0; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
+						if(vm.downResetTimer) {clearTimeout(vm.downResetTimer); vm.downResetTimer = null} // 移除重置倒计时
+						vm.downResetTimer = setTimeout(()=>{ // 过渡动画执行完毕后,需重置为0的状态,避免下次inOffset不及时显示textInOffset
+							if(vm.downLoadType === 4) vm.downLoadType = 0
+						},300)
+					},
+					// 派发下拉刷新的回调
+					callback: function(mescroll) {
+						vm.$emit('down', mescroll);
+					}
+				},
+				// 上拉加载的配置
+				up: {
+					// 显示加载中的回调
+					showLoading() {
+						vm.upLoadType = 1;
+					},
+					// 显示无更多数据的回调
+					showNoMore() {
+						vm.upLoadType = 2;
+					},
+					// 隐藏上拉加载的回调
+					hideUpScroll(mescroll) {
+						vm.upLoadType = mescroll.optUp.hasNext ? 0 : 3;
+					},
+					// 空布局
+					empty: {
+						onShow(isShow) {
+							// 显示隐藏的回调
+							vm.isShowEmpty = isShow;
+						}
+					},
+					// 回到顶部
+					toTop: {
+						onShow(isShow) {
+							// 显示隐藏的回调
+							vm.isShowToTop = isShow;
+						}
+					},
+					// 派发上拉加载的回调
+					callback: function(mescroll) {
+						vm.$emit('up', mescroll);
+					}
+				}
+			};
+
+			MeScroll.extend(diyOption, GlobalOption); // 混入全局的配置
+			let myOption = JSON.parse(JSON.stringify({down: vm.down,up: vm.up})); // 深拷贝,避免对props的影响
+			MeScroll.extend(myOption, diyOption); // 混入具体界面的配置
+
+			// 初始化MeScroll对象
+			vm.mescroll = new MeScroll(myOption, true); // 传入true,标记body为滚动区域
+			// init回调mescroll对象
+			vm.$emit('init', vm.mescroll);
+
+			// 设置高度
+			const sys = uni.getSystemInfoSync();
+			if (sys.windowHeight) vm.windowHeight = sys.windowHeight;
+			if (sys.windowBottom) vm.windowBottom = sys.windowBottom;
+			if (sys.statusBarHeight) vm.statusBarHeight = sys.statusBarHeight;
+			// 使down的bottomOffset生效
+			vm.mescroll.setBodyHeight(sys.windowHeight);
+
+			// 因为使用的是page的scroll,这里需自定义scrollTo
+			vm.mescroll.resetScrollTo((y, t) => {
+				if(typeof y === 'string'){
+					// 滚动到指定view (y为css选择器)
+					setTimeout(()=>{ // 延时确保view已渲染; 不使用$nextTick
+						let selector;
+						if(y.indexOf('#')==-1 && y.indexOf('.')==-1){
+							selector = '#'+y // 不带#和. 则默认为id选择器
+						}else{
+							selector = y
+							// #ifdef APP-PLUS || H5 || MP-ALIPAY || MP-DINGTALK
+							if(y.indexOf('>>>')!=-1){ // 不支持跨自定义组件的后代选择器 (转为普通的选择器即可跨组件查询)
+								selector = y.split('>>>')[1].trim()
+							}
+							// #endif
+						}
+						uni.createSelectorQuery().select(selector).boundingClientRect(function(rect){
+							if (rect) {
+								let top = rect.top
+								top += vm.mescroll.getScrollTop()
+								uni.pageScrollTo({
+									scrollTop: top,
+									duration: t
+								})
+							} else{
+								console.error(selector + ' does not exist');
+							}
+						}).exec()
+					},30)
+				} else{
+					// 滚动到指定位置 (y必须为数字)
+					uni.pageScrollTo({
+						scrollTop: y,
+						duration: t
+					})
+				}
+			});
+
+			// 具体的界面如果不配置up.toTop.safearea,则取本vue的safearea值
+			if (vm.up && vm.up.toTop && vm.up.toTop.safearea != null) {} else {
+				vm.mescroll.optUp.toTop.safearea = vm.safearea;
+			}
+		}
+	};
+</script>
+
+<style>
+	@import "./mescroll-body.css";
+	@import "./components/mescroll-down.css";
+	@import './components/mescroll-up.css';
+</style>

+ 65 - 0
comps/mescroll-body/mescroll-mixins.js

@@ -0,0 +1,65 @@
+// mescroll-body 和 mescroll-uni 通用
+
+// import MescrollUni from "./mescroll-uni.vue";
+// import MescrollBody from "./mescroll-body.vue";
+
+const MescrollMixin = {
+	// components: { // 非H5端无法通过mixin注册组件, 只能在main.js中注册全局组件或具体界面中注册
+	// 	MescrollUni,
+	// 	MescrollBody
+	// },
+	data() {
+		return {
+			mescroll: null //mescroll实例对象
+		}
+	},
+	// 注册系统自带的下拉刷新 (配置down.native为true时生效, 还需在pages配置enablePullDownRefresh:true;详请参考mescroll-native的案例)
+	onPullDownRefresh(){
+		this.mescroll && this.mescroll.onPullDownRefresh();
+	},
+	// 注册列表滚动事件,用于判定在顶部可下拉刷新,在指定位置可显示隐藏回到顶部按钮 (此方法为页面生命周期,无法在子组件中触发, 仅在mescroll-body生效)
+	onPageScroll(e) {
+		this.mescroll && this.mescroll.onPageScroll(e);
+	},
+	// 注册滚动到底部的事件,用于上拉加载 (此方法为页面生命周期,无法在子组件中触发, 仅在mescroll-body生效)
+	onReachBottom() {
+		this.mescroll && this.mescroll.onReachBottom();
+	},
+	methods: {
+		// mescroll组件初始化的回调,可获取到mescroll对象
+		mescrollInit(mescroll) {
+			this.mescroll = mescroll;
+			this.mescrollInitByRef(); // 兼容字节跳动小程序
+		},
+		// 以ref的方式初始化mescroll对象 (兼容字节跳动小程序)
+		mescrollInitByRef() {
+			if(!this.mescroll || !this.mescroll.resetUpScroll){
+				let mescrollRef = this.$refs.mescrollRef;
+				if(mescrollRef) this.mescroll = mescrollRef.mescroll
+			}
+		},
+		// 下拉刷新的回调 (mixin默认resetUpScroll)
+		downCallback() {
+			if(this.mescroll.optUp.use){
+				this.mescroll.resetUpScroll()
+			}else{
+				setTimeout(()=>{
+					this.mescroll.endSuccess();
+				}, 500)
+			}
+		},
+		// 上拉加载的回调
+		upCallback() {
+			// mixin默认延时500自动结束加载
+			setTimeout(()=>{
+				this.mescroll.endErr();
+			}, 500)
+		}
+	},
+	mounted() {
+		this.mescrollInitByRef(); // 兼容字节跳动小程序, 避免未设置@init或@init此时未能取到ref的情况
+	}
+	
+}
+
+export default MescrollMixin;

+ 36 - 0
comps/mescroll-body/mescroll-uni-option.js

@@ -0,0 +1,36 @@
+// 全局配置
+// mescroll-body 和 mescroll-uni 通用
+const GlobalOption = {
+	down: {
+		// 其他down的配置参数也可以写,这里只展示了常用的配置:
+		textInOffset: '下拉刷新', // 下拉的距离在offset范围内的提示文本
+		textOutOffset: '释放更新', // 下拉的距离大于offset范围的提示文本
+		textLoading: '加载中 ...', // 加载中的提示文本
+		textSuccess: '加载成功', // 加载成功的文本
+		textErr: '加载失败', // 加载失败的文本
+		beforeEndDelay: 100, // 延时结束的时长 (显示加载成功/失败的时长)
+		offset: 80, // 在列表顶部,下拉大于80px,松手即可触发下拉刷新的回调
+		native: false // 是否使用系统自带的下拉刷新; 默认false; 仅在mescroll-body生效 (值为true时,还需在pages配置enablePullDownRefresh:true;详请参考mescroll-native的案例)
+	},
+	up: {
+		// 其他up的配置参数也可以写,这里只展示了常用的配置:
+		textLoading: '加载中 ...', // 加载中的提示文本
+		textNoMore: '到底啦', // 没有更多数据的提示文本
+		offset: 150, // 距底部多远时,触发upCallback,仅mescroll-uni生效 ( mescroll-body配置的是pages.json的 onReachBottomDistance )
+		toTop: {
+			// 回到顶部按钮,需配置src才显示
+			src: "https://www.mescroll.com/img/mescroll-totop.png", // 图片路径 (建议放入static目录, 如 /static/img/mescroll-totop.png )
+			offset: 1000, // 列表滚动多少距离才显示回到顶部按钮,默认1000px
+			right: 20, // 到右边的距离, 默认20 (支持"20rpx", "20px", "20%"格式的值, 纯数字则默认单位rpx)
+			bottom: 120, // 到底部的距离, 默认120 (支持"20rpx", "20px", "20%"格式的值, 纯数字则默认单位rpx)
+			width: 72 // 回到顶部图标的宽度, 默认72 (支持"20rpx", "20px", "20%"格式的值, 纯数字则默认单位rpx)
+		},
+		empty: {
+			use: true, // 是否显示空布局
+			icon: "http://139.9.103.171:1888/miniofile/xlyq/empty/empty.png", // 图标路径 (建议放入static目录, 如 /static/img/mescroll-empty.png )
+			tip: '数据为空' // 提示
+		}
+	}
+}
+
+export default GlobalOption

+ 36 - 0
comps/mescroll-body/mescroll-uni.css

@@ -0,0 +1,36 @@
+.mescroll-uni-warp{
+	height: 100%;
+}
+
+.mescroll-uni-content{
+	height: 100%;
+}
+
+.mescroll-uni {
+	position: relative;
+	width: 100%;
+	height: 100%;
+	min-height: 200rpx;
+	overflow-y: auto;
+	box-sizing: border-box; /* 避免设置padding出现双滚动条的问题 */
+}
+
+/* 定位的方式固定高度 */
+.mescroll-uni-fixed{
+	z-index: 1;
+	position: fixed;
+	top: 0;
+	left: 0;
+	right: 0;
+	bottom: 0;
+	width: auto; /* 使right生效 */
+	height: auto; /* 使bottom生效 */
+}
+
+/* 适配 iPhoneX */
+@supports (bottom: constant(safe-area-inset-bottom)) or (bottom: env(safe-area-inset-bottom)) {
+	.mescroll-safearea {
+		padding-bottom: constant(safe-area-inset-bottom);
+		padding-bottom: env(safe-area-inset-bottom);
+	}
+}

+ 799 - 0
comps/mescroll-body/mescroll-uni.js

@@ -0,0 +1,799 @@
+/* mescroll
+ * version 1.3.3
+ * 2020-09-15 wenju
+ * https://www.mescroll.com
+ */
+
+export default function MeScroll(options, isScrollBody) {
+	let me = this;
+	me.version = '1.3.3'; // mescroll版本号
+	me.options = options || {}; // 配置
+	me.isScrollBody = isScrollBody || false; // 滚动区域是否为原生页面滚动; 默认为scroll-view
+
+	me.isDownScrolling = false; // 是否在执行下拉刷新的回调
+	me.isUpScrolling = false; // 是否在执行上拉加载的回调
+	let hasDownCallback = me.options.down && me.options.down.callback; // 是否配置了down的callback
+
+	// 初始化下拉刷新
+	me.initDownScroll();
+	// 初始化上拉加载,则初始化
+	me.initUpScroll();
+
+	// 自动加载
+	setTimeout(function() { // 待主线程执行完毕再执行,避免new MeScroll未初始化,在回调获取不到mescroll的实例
+		// 自动触发下拉刷新 (只有配置了down的callback才自动触发下拉刷新)
+		if ((me.optDown.use || me.optDown.native) && me.optDown.auto && hasDownCallback) {
+			if (me.optDown.autoShowLoading) {
+				me.triggerDownScroll(); // 显示下拉进度,执行下拉回调
+			} else {
+				me.optDown.callback && me.optDown.callback(me); // 不显示下拉进度,直接执行下拉回调
+			}
+		}
+		// 自动触发上拉加载
+		if(!me.isUpAutoLoad){ // 部分小程序(头条小程序)emit是异步, 会导致isUpAutoLoad判断有误, 先延时确保先执行down的callback,再执行up的callback
+			setTimeout(function(){
+				me.optUp.use && me.optUp.auto && !me.isUpAutoLoad && me.triggerUpScroll();
+			},100)
+		}
+	}, 30); // 需让me.optDown.inited和me.optUp.inited先执行
+}
+
+/* 配置参数:下拉刷新 */
+MeScroll.prototype.extendDownScroll = function(optDown) {
+	// 下拉刷新的配置
+	MeScroll.extend(optDown, {
+		use: true, // 是否启用下拉刷新; 默认true
+		auto: true, // 是否在初始化完毕之后自动执行下拉刷新的回调; 默认true
+		native: false, // 是否使用系统自带的下拉刷新; 默认false; 仅mescroll-body生效 (值为true时,还需在pages配置enablePullDownRefresh:true;详请参考mescroll-native的案例)
+		autoShowLoading: false, // 如果设置auto=true(在初始化完毕之后自动执行下拉刷新的回调),那么是否显示下拉刷新的进度; 默认false
+		isLock: false, // 是否锁定下拉刷新,默认false;
+		offset: 80, // 在列表顶部,下拉大于80px,松手即可触发下拉刷新的回调
+		startTop: 100, // scroll-view快速滚动到顶部时,此时的scroll-top可能大于0, 此值用于控制最大的误差
+		inOffsetRate: 1, // 在列表顶部,下拉的距离小于offset时,改变下拉区域高度比例;值小于1且越接近0,高度变化越小,表现为越往下越难拉
+		outOffsetRate: 0.2, // 在列表顶部,下拉的距离大于offset时,改变下拉区域高度比例;值小于1且越接近0,高度变化越小,表现为越往下越难拉
+		bottomOffset: 20, // 当手指touchmove位置在距离body底部20px范围内的时候结束上拉刷新,避免Webview嵌套导致touchend事件不执行
+		minAngle: 45, // 向下滑动最少偏移的角度,取值区间  [0,90];默认45度,即向下滑动的角度大于45度则触发下拉;而小于45度,将不触发下拉,避免与左右滑动的轮播等组件冲突;
+		textInOffset: '下拉刷新', // 下拉的距离在offset范围内的提示文本
+		textOutOffset: '释放更新', // 下拉的距离大于offset范围的提示文本
+		textLoading: '加载中 ...', // 加载中的提示文本
+		textSuccess: '加载成功', // 加载成功的文本
+		textErr: '加载失败', // 加载失败的文本
+		beforeEndDelay: 100, // 延时结束的时长 (显示加载成功/失败的时长)
+		bgColor: "transparent", // 背景颜色 (建议在pages.json中再设置一下backgroundColorTop)
+		textColor: "gray", // 文本颜色 (当bgColor配置了颜色,而textColor未配置时,则textColor会默认为白色)
+		inited: null, // 下拉刷新初始化完毕的回调
+		inOffset: null, // 下拉的距离进入offset范围内那一刻的回调
+		outOffset: null, // 下拉的距离大于offset那一刻的回调
+		onMoving: null, // 下拉过程中的回调,滑动过程一直在执行; rate下拉区域当前高度与指定距离的比值(inOffset: rate<1; outOffset: rate>=1); downHight当前下拉区域的高度
+		beforeLoading: null, // 准备触发下拉刷新的回调: 如果return true,将不触发showLoading和callback回调; 常用来完全自定义下拉刷新, 参考案例【淘宝 v6.8.0】
+		showLoading: null, // 显示下拉刷新进度的回调
+		afterLoading: null, // 显示下拉刷新进度的回调之后,马上要执行的代码 (如: 在wxs中使用)
+		beforeEndDownScroll: null, // 准备结束下拉的回调. 返回结束下拉的延时执行时间,默认0ms; 常用于结束下拉之前再显示另外一小段动画,才去隐藏下拉刷新的场景, 参考案例【dotJump】
+		endDownScroll: null, // 结束下拉刷新的回调
+		afterEndDownScroll: null, // 结束下拉刷新的回调,马上要执行的代码 (如: 在wxs中使用)
+		callback: function(mescroll) {
+			// 下拉刷新的回调;默认重置上拉加载列表为第一页
+			mescroll.resetUpScroll();
+		}
+	})
+}
+
+/* 配置参数:上拉加载 */
+MeScroll.prototype.extendUpScroll = function(optUp) {
+	// 上拉加载的配置
+	MeScroll.extend(optUp, {
+		use: true, // 是否启用上拉加载; 默认true
+		auto: true, // 是否在初始化完毕之后自动执行上拉加载的回调; 默认true
+		isLock: false, // 是否锁定上拉加载,默认false;
+		isBoth: true, // 上拉加载时,如果滑动到列表顶部是否可以同时触发下拉刷新;默认true,两者可同时触发;
+		callback: null, // 上拉加载的回调;function(page,mescroll){ }
+		page: {
+			num: 0, // 当前页码,默认0,回调之前会加1,即callback(page)会从1开始
+			size: 10, // 每页数据的数量
+			time: null // 加载第一页数据服务器返回的时间; 防止用户翻页时,后台新增了数据从而导致下一页数据重复;
+		},
+		noMoreSize: 5, // 如果列表已无数据,可设置列表的总数量要大于等于5条才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看
+		offset: 150, // 距底部多远时,触发upCallback,仅mescroll-uni生效 ( mescroll-body配置的是pages.json的 onReachBottomDistance )
+		textLoading: '加载中 ...', // 加载中的提示文本
+		textNoMore: '-- END --', // 没有更多数据的提示文本
+		bgColor: "transparent", // 背景颜色 (建议在pages.json中再设置一下backgroundColorBottom)
+		textColor: "gray", // 文本颜色 (当bgColor配置了颜色,而textColor未配置时,则textColor会默认为白色)
+		inited: null, // 初始化完毕的回调
+		showLoading: null, // 显示加载中的回调
+		showNoMore: null, // 显示无更多数据的回调
+		hideUpScroll: null, // 隐藏上拉加载的回调
+		errDistance: 60, // endErr的时候需往上滑动一段距离,使其往下滑动时再次触发onReachBottom,仅mescroll-body生效
+		toTop: {
+			// 回到顶部按钮,需配置src才显示
+			src: null, // 图片路径,默认null (绝对路径或网络图)
+			offset: 1000, // 列表滚动多少距离才显示回到顶部按钮,默认1000
+			duration: 300, // 回到顶部的动画时长,默认300ms (当值为0或300则使用系统自带回到顶部,更流畅; 其他值则通过step模拟,部分机型可能不够流畅,所以非特殊情况不建议修改此项)
+			btnClick: null, // 点击按钮的回调
+			onShow: null, // 是否显示的回调
+			zIndex: 9990, // fixed定位z-index值
+			left: null, // 到左边的距离, 默认null. 此项有值时,right不生效. (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
+			right: 20, // 到右边的距离, 默认20 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
+			bottom: 120, // 到底部的距离, 默认120 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
+			safearea: false, // bottom的偏移量是否加上底部安全区的距离, 默认false, 需要适配iPhoneX时使用 (具体的界面如果不配置此项,则取本vue的safearea值)
+			width: 72, // 回到顶部图标的宽度, 默认72 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
+			radius: "50%" // 圆角, 默认"50%" (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
+		},
+		empty: {
+			use: true, // 是否显示空布局
+			icon: null, // 图标路径
+			tip: '~ 暂无相关数据 ~', // 提示
+			btnText: '', // 按钮
+			btnClick: null, // 点击按钮的回调
+			onShow: null, // 是否显示的回调
+			fixed: false, // 是否使用fixed定位,默认false; 配置fixed为true,以下的top和zIndex才生效 (transform会使fixed失效,最终会降级为absolute)
+			top: "100rpx", // fixed定位的top值 (完整的单位值,如 "10%"; "100rpx")
+			zIndex: 99 // fixed定位z-index值
+		},
+		onScroll: false // 是否监听滚动事件
+	})
+}
+
+/* 配置参数 */
+MeScroll.extend = function(userOption, defaultOption) {
+	if (!userOption) return defaultOption;
+	for (let key in defaultOption) {
+		if (userOption[key] == null) {
+			let def = defaultOption[key];
+			if (def != null && typeof def === 'object') {
+				userOption[key] = MeScroll.extend({}, def); // 深度匹配
+			} else {
+				userOption[key] = def;
+			}
+		} else if (typeof userOption[key] === 'object') {
+			MeScroll.extend(userOption[key], defaultOption[key]); // 深度匹配
+		}
+	}
+	return userOption;
+}
+
+/* 简单判断是否配置了颜色 (非透明,非白色) */
+MeScroll.prototype.hasColor = function(color) {
+	if(!color) return false;
+	let c = color.toLowerCase();
+	return c != "#fff" && c != "#ffffff" && c != "transparent" && c != "white"
+}
+
+/* -------初始化下拉刷新------- */
+MeScroll.prototype.initDownScroll = function() {
+	let me = this;
+	// 配置参数
+	me.optDown = me.options.down || {};
+	if(!me.optDown.textColor && me.hasColor(me.optDown.bgColor)) me.optDown.textColor = "#fff"; // 当bgColor有值且textColor未设置,则textColor默认白色
+	me.extendDownScroll(me.optDown);
+	
+	// 如果是mescroll-body且配置了native,则禁止自定义的下拉刷新
+	if(me.isScrollBody && me.optDown.native){
+		me.optDown.use = false
+	}else{
+		me.optDown.native = false // 仅mescroll-body支持,mescroll-uni不支持
+	}
+	
+	me.downHight = 0; // 下拉区域的高度
+
+	// 在页面中加入下拉布局
+	if (me.optDown.use && me.optDown.inited) {
+		// 初始化完毕的回调
+		setTimeout(function() { // 待主线程执行完毕再执行,避免new MeScroll未初始化,在回调获取不到mescroll的实例
+			me.optDown.inited(me);
+		}, 0)
+	}
+}
+
+/* 列表touchstart事件 */
+MeScroll.prototype.touchstartEvent = function(e) {
+	if (!this.optDown.use) return;
+
+	this.startPoint = this.getPoint(e); // 记录起点
+	this.startTop = this.getScrollTop(); // 记录此时的滚动条位置
+	this.startAngle = 0; // 初始角度
+	this.lastPoint = this.startPoint; // 重置上次move的点
+	this.maxTouchmoveY = this.getBodyHeight() - this.optDown.bottomOffset; // 手指触摸的最大范围(写在touchstart避免body获取高度为0的情况)
+	this.inTouchend = false; // 标记不是touchend
+}
+
+/* 列表touchmove事件 */
+MeScroll.prototype.touchmoveEvent = function(e) {
+	if (!this.optDown.use) return;
+	let me = this;
+
+	let scrollTop = me.getScrollTop(); // 当前滚动条的距离
+	let curPoint = me.getPoint(e); // 当前点
+
+	let moveY = curPoint.y - me.startPoint.y; // 和起点比,移动的距离,大于0向下拉,小于0向上拉
+
+	// 向下拉 && 在顶部
+	// mescroll-body,直接判定在顶部即可
+	// scroll-view在滚动时不会触发touchmove,当触顶/底/左/右时,才会触发touchmove
+	// scroll-view滚动到顶部时,scrollTop不一定为0,也有可能大于0; 在iOS的APP中scrollTop可能为负数,不一定和startTop相等
+	if (moveY > 0 && (
+			(me.isScrollBody && scrollTop <= 0)
+			||
+			(!me.isScrollBody && (scrollTop <= 0 || (scrollTop <= me.optDown.startTop && scrollTop === me.startTop)) )
+		)) {
+		// 可下拉的条件
+		if (!me.inTouchend && !me.isDownScrolling && !me.optDown.isLock && (!me.isUpScrolling || (me.isUpScrolling &&
+				me.optUp.isBoth))) {
+
+			// 下拉的初始角度是否在配置的范围内
+			if(!me.startAngle) me.startAngle = me.getAngle(me.lastPoint, curPoint); // 两点之间的角度,区间 [0,90]
+			if (me.startAngle < me.optDown.minAngle) return; // 如果小于配置的角度,则不往下执行下拉刷新
+
+			// 如果手指的位置超过配置的距离,则提前结束下拉,避免Webview嵌套导致touchend无法触发
+			if (me.maxTouchmoveY > 0 && curPoint.y >= me.maxTouchmoveY) {
+				me.inTouchend = true; // 标记执行touchend
+				me.touchendEvent(); // 提前触发touchend
+				return;
+			}
+			
+			me.preventDefault(e); // 阻止默认事件
+
+			let diff = curPoint.y - me.lastPoint.y; // 和上次比,移动的距离 (大于0向下,小于0向上)
+
+			// 下拉距离  < 指定距离
+			if (me.downHight < me.optDown.offset) {
+				if (me.movetype !== 1) {
+					me.movetype = 1; // 加入标记,保证只执行一次
+					me.isDownEndSuccess = null; // 重置是否加载成功的状态 (wxs执行的是wxs.wxs)
+					me.optDown.inOffset && me.optDown.inOffset(me); // 进入指定距离范围内那一刻的回调,只执行一次
+					me.isMoveDown = true; // 标记下拉区域高度改变,在touchend重置回来
+				}
+				me.downHight += diff * me.optDown.inOffsetRate; // 越往下,高度变化越小
+
+				// 指定距离  <= 下拉距离
+			} else {
+				if (me.movetype !== 2) {
+					me.movetype = 2; // 加入标记,保证只执行一次
+					me.optDown.outOffset && me.optDown.outOffset(me); // 下拉超过指定距离那一刻的回调,只执行一次
+					me.isMoveDown = true; // 标记下拉区域高度改变,在touchend重置回来
+				}
+				if (diff > 0) { // 向下拉
+					me.downHight += diff * me.optDown.outOffsetRate; // 越往下,高度变化越小
+				} else { // 向上收
+					me.downHight += diff; // 向上收回高度,则向上滑多少收多少高度
+				}
+			}
+			
+			me.downHight = Math.round(me.downHight) // 取整
+			let rate = me.downHight / me.optDown.offset; // 下拉区域当前高度与指定距离的比值
+			me.optDown.onMoving && me.optDown.onMoving(me, rate, me.downHight); // 下拉过程中的回调,一直在执行
+		}
+	}
+
+	me.lastPoint = curPoint; // 记录本次移动的点
+}
+
+/* 列表touchend事件 */
+MeScroll.prototype.touchendEvent = function(e) {
+	if (!this.optDown.use) return;
+	// 如果下拉区域高度已改变,则需重置回来
+	if (this.isMoveDown) {
+		if (this.downHight >= this.optDown.offset) {
+			// 符合触发刷新的条件
+			this.triggerDownScroll();
+		} else {
+			// 不符合的话 则重置
+			this.downHight = 0;
+			this.endDownScrollCall(this);
+		}
+		this.movetype = 0;
+		this.isMoveDown = false;
+	} else if (!this.isScrollBody && this.getScrollTop() === this.startTop) { // scroll-view到顶/左/右/底的滑动事件
+		let isScrollUp = this.getPoint(e).y - this.startPoint.y < 0; // 和起点比,移动的距离,大于0向下拉,小于0向上拉
+		// 上滑
+		if (isScrollUp) {
+			// 需检查滑动的角度
+			let angle = this.getAngle(this.getPoint(e), this.startPoint); // 两点之间的角度,区间 [0,90]
+			if (angle > 80) {
+				// 检查并触发上拉
+				this.triggerUpScroll(true);
+			}
+		}
+	}
+}
+
+/* 根据点击滑动事件获取第一个手指的坐标 */
+MeScroll.prototype.getPoint = function(e) {
+	if (!e) {
+		return {
+			x: 0,
+			y: 0
+		}
+	}
+	if (e.touches && e.touches[0]) {
+		return {
+			x: e.touches[0].pageX,
+			y: e.touches[0].pageY
+		}
+	} else if (e.changedTouches && e.changedTouches[0]) {
+		return {
+			x: e.changedTouches[0].pageX,
+			y: e.changedTouches[0].pageY
+		}
+	} else {
+		return {
+			x: e.clientX,
+			y: e.clientY
+		}
+	}
+}
+
+/* 计算两点之间的角度: 区间 [0,90]*/
+MeScroll.prototype.getAngle = function(p1, p2) {
+	let x = Math.abs(p1.x - p2.x);
+	let y = Math.abs(p1.y - p2.y);
+	let z = Math.sqrt(x * x + y * y);
+	let angle = 0;
+	if (z !== 0) {
+		angle = Math.asin(y / z) / Math.PI * 180;
+	}
+	return angle
+}
+
+/* 触发下拉刷新 */
+MeScroll.prototype.triggerDownScroll = function() {
+	if (this.optDown.beforeLoading && this.optDown.beforeLoading(this)) {
+		//return true则处于完全自定义状态
+	} else {
+		this.showDownScroll(); // 下拉刷新中...
+		!this.optDown.native && this.optDown.callback && this.optDown.callback(this); // 执行回调,联网加载数据
+	}
+}
+
+/* 显示下拉进度布局 */
+MeScroll.prototype.showDownScroll = function() {
+	this.isDownScrolling = true; // 标记下拉中
+	if (this.optDown.native) {
+		uni.startPullDownRefresh(); // 系统自带的下拉刷新
+		this.showDownLoadingCall(0); // 仍触发showLoading,因为上拉加载用到
+	} else{
+		this.downHight = this.optDown.offset; // 更新下拉区域高度
+		this.showDownLoadingCall(this.downHight); // 下拉刷新中...
+	}
+}
+
+MeScroll.prototype.showDownLoadingCall = function(downHight) {
+	this.optDown.showLoading && this.optDown.showLoading(this, downHight); // 下拉刷新中...
+	this.optDown.afterLoading && this.optDown.afterLoading(this, downHight); // 下拉刷新中...触发之后马上要执行的代码
+}
+
+/* 显示系统自带的下拉刷新时需要处理的业务 */
+MeScroll.prototype.onPullDownRefresh = function() {
+	this.isDownScrolling = true; // 标记下拉中
+	this.showDownLoadingCall(0); // 仍触发showLoading,因为上拉加载用到
+	this.optDown.callback && this.optDown.callback(this); // 执行回调,联网加载数据
+}
+
+/* 结束下拉刷新 */
+MeScroll.prototype.endDownScroll = function() {
+	if (this.optDown.native) { // 结束原生下拉刷新
+		this.isDownScrolling = false;
+		this.endDownScrollCall(this);
+		uni.stopPullDownRefresh();
+		return
+	}
+	let me = this;
+	// 结束下拉刷新的方法
+	let endScroll = function() {
+		me.downHight = 0;
+		me.isDownScrolling = false;
+		me.endDownScrollCall(me);
+		if(!me.isScrollBody){
+			me.setScrollHeight(0) // scroll-view重置滚动区域,使数据不满屏时仍可检查触发翻页
+			me.scrollTo(0,0) // scroll-view需重置滚动条到顶部,避免startTop大于0时,对下拉刷新的影响
+		}
+	}
+	// 结束下拉刷新时的回调
+	let delay = 0;
+	if (me.optDown.beforeEndDownScroll) {
+		delay = me.optDown.beforeEndDownScroll(me); // 结束下拉刷新的延时,单位ms
+		if(me.isDownEndSuccess == null) delay = 0; // 没有执行加载中,则不延时
+	}
+	if (typeof delay === 'number' && delay > 0) {
+		setTimeout(endScroll, delay);
+	} else {
+		endScroll();
+	}
+}
+
+MeScroll.prototype.endDownScrollCall = function() {
+	this.optDown.endDownScroll && this.optDown.endDownScroll(this);
+	this.optDown.afterEndDownScroll && this.optDown.afterEndDownScroll(this);
+}
+
+/* 锁定下拉刷新:isLock=ture,null锁定;isLock=false解锁 */
+MeScroll.prototype.lockDownScroll = function(isLock) {
+	if (isLock == null) isLock = true;
+	this.optDown.isLock = isLock;
+}
+
+/* 锁定上拉加载:isLock=ture,null锁定;isLock=false解锁 */
+MeScroll.prototype.lockUpScroll = function(isLock) {
+	if (isLock == null) isLock = true;
+	this.optUp.isLock = isLock;
+}
+
+/* -------初始化上拉加载------- */
+MeScroll.prototype.initUpScroll = function() {
+	let me = this;
+	// 配置参数
+	me.optUp = me.options.up || {use: false}
+	if(!me.optUp.textColor && me.hasColor(me.optUp.bgColor)) me.optUp.textColor = "#fff"; // 当bgColor有值且textColor未设置,则textColor默认白色
+	me.extendUpScroll(me.optUp);
+
+	if (me.optUp.use === false) return; // 配置不使用上拉加载时,则不初始化上拉布局
+	me.optUp.hasNext = true; // 如果使用上拉,则默认有下一页
+	me.startNum = me.optUp.page.num + 1; // 记录page开始的页码
+
+	// 初始化完毕的回调
+	if (me.optUp.inited) {
+		setTimeout(function() { // 待主线程执行完毕再执行,避免new MeScroll未初始化,在回调获取不到mescroll的实例
+			me.optUp.inited(me);
+		}, 0)
+	}
+}
+
+/*滚动到底部的事件 (仅mescroll-body生效)*/
+MeScroll.prototype.onReachBottom = function() {
+	if (this.isScrollBody && !this.isUpScrolling) { // 只能支持下拉刷新的时候同时可以触发上拉加载,否则滚动到底部就需要上滑一点才能触发onReachBottom
+		if (!this.optUp.isLock && this.optUp.hasNext) {
+			this.triggerUpScroll();
+		}
+	}
+}
+
+/*列表滚动事件 (仅mescroll-body生效)*/
+MeScroll.prototype.onPageScroll = function(e) {
+	if (!this.isScrollBody) return;
+	
+	// 更新滚动条的位置 (主要用于判断下拉刷新时,滚动条是否在顶部)
+	this.setScrollTop(e.scrollTop);
+
+	// 顶部按钮的显示隐藏
+	if (e.scrollTop >= this.optUp.toTop.offset) {
+		this.showTopBtn();
+	} else {
+		this.hideTopBtn();
+	}
+}
+
+/*列表滚动事件*/
+MeScroll.prototype.scroll = function(e, onScroll) {
+	// 更新滚动条的位置
+	this.setScrollTop(e.scrollTop);
+	// 更新滚动内容高度
+	this.setScrollHeight(e.scrollHeight);
+
+	// 向上滑还是向下滑动
+	if (this.preScrollY == null) this.preScrollY = 0;
+	this.isScrollUp = e.scrollTop - this.preScrollY > 0;
+	this.preScrollY = e.scrollTop;
+
+	// 上滑 && 检查并触发上拉
+	this.isScrollUp && this.triggerUpScroll(true);
+
+	// 顶部按钮的显示隐藏
+	if (e.scrollTop >= this.optUp.toTop.offset) {
+		this.showTopBtn();
+	} else {
+		this.hideTopBtn();
+	}
+
+	// 滑动监听
+	this.optUp.onScroll && onScroll && onScroll()
+}
+
+/* 触发上拉加载 */
+MeScroll.prototype.triggerUpScroll = function(isCheck) {
+	if (!this.isUpScrolling && this.optUp.use && this.optUp.callback) {
+		// 是否校验在底部; 默认不校验
+		if (isCheck === true) {
+			let canUp = false;
+			// 还有下一页 && 没有锁定 && 不在下拉中
+			if (this.optUp.hasNext && !this.optUp.isLock && !this.isDownScrolling) {
+				if (this.getScrollBottom() <= this.optUp.offset) { // 到底部
+					canUp = true; // 标记可上拉
+				}
+			}
+			if (canUp === false) return;
+		}
+		this.showUpScroll(); // 上拉加载中...
+		this.optUp.page.num++; // 预先加一页,如果失败则减回
+		this.isUpAutoLoad = true; // 标记上拉已经自动执行过,避免初始化时多次触发上拉回调
+		this.num = this.optUp.page.num; // 把最新的页数赋值在mescroll上,避免对page的影响
+		this.size = this.optUp.page.size; // 把最新的页码赋值在mescroll上,避免对page的影响
+		this.time = this.optUp.page.time; // 把最新的页码赋值在mescroll上,避免对page的影响
+		this.optUp.callback(this); // 执行回调,联网加载数据
+	}
+}
+
+/* 显示上拉加载中 */
+MeScroll.prototype.showUpScroll = function() {
+	this.isUpScrolling = true; // 标记上拉加载中
+	this.optUp.showLoading && this.optUp.showLoading(this); // 回调
+}
+
+/* 显示上拉无更多数据 */
+MeScroll.prototype.showNoMore = function() {
+	this.optUp.hasNext = false; // 标记无更多数据
+	this.optUp.showNoMore && this.optUp.showNoMore(this); // 回调
+}
+
+/* 隐藏上拉区域**/
+MeScroll.prototype.hideUpScroll = function() {
+	this.optUp.hideUpScroll && this.optUp.hideUpScroll(this); // 回调
+}
+
+/* 结束上拉加载 */
+MeScroll.prototype.endUpScroll = function(isShowNoMore) {
+	if (isShowNoMore != null) { // isShowNoMore=null,不处理下拉状态,下拉刷新的时候调用
+		if (isShowNoMore) {
+			this.showNoMore(); // isShowNoMore=true,显示无更多数据
+		} else {
+			this.hideUpScroll(); // isShowNoMore=false,隐藏上拉加载
+		}
+	}
+	this.isUpScrolling = false; // 标记结束上拉加载
+}
+
+/* 重置上拉加载列表为第一页
+ *isShowLoading 是否显示进度布局;
+ * 1.默认null,不传参,则显示上拉加载的进度布局
+ * 2.传参true, 则显示下拉刷新的进度布局
+ * 3.传参false,则不显示上拉和下拉的进度 (常用于静默更新列表数据)
+ */
+MeScroll.prototype.resetUpScroll = function(isShowLoading) {
+	if (this.optUp && this.optUp.use) {
+		let page = this.optUp.page;
+		this.prePageNum = page.num; // 缓存重置前的页码,加载失败可退回
+		this.prePageTime = page.time; // 缓存重置前的时间,加载失败可退回
+		page.num = this.startNum; // 重置为第一页
+		page.time = null; // 重置时间为空
+		if (!this.isDownScrolling && isShowLoading !== false) { // 如果不是下拉刷新触发的resetUpScroll并且不配置列表静默更新,则显示进度;
+			if (isShowLoading == null) {
+				this.removeEmpty(); // 移除空布局
+				this.showUpScroll(); // 不传参,默认显示上拉加载的进度布局
+			} else {
+				this.showDownScroll(); // 传true,显示下拉刷新的进度布局,不清空列表
+			}
+		}
+		this.isUpAutoLoad = true; // 标记上拉已经自动执行过,避免初始化时多次触发上拉回调
+		this.num = page.num; // 把最新的页数赋值在mescroll上,避免对page的影响
+		this.size = page.size; // 把最新的页码赋值在mescroll上,避免对page的影响
+		this.time = page.time; // 把最新的页码赋值在mescroll上,避免对page的影响
+		this.optUp.callback && this.optUp.callback(this); // 执行上拉回调
+	}
+}
+
+/* 设置page.num的值 */
+MeScroll.prototype.setPageNum = function(num) {
+	this.optUp.page.num = num - 1;
+}
+
+/* 设置page.size的值 */
+MeScroll.prototype.setPageSize = function(size) {
+	this.optUp.page.size = size;
+}
+
+/* 联网回调成功,结束下拉刷新和上拉加载
+ * dataSize: 当前页的数据量(必传)
+ * totalPage: 总页数(必传)
+ * systime: 服务器时间 (可空)
+ */
+MeScroll.prototype.endByPage = function(dataSize, totalPage, systime) {
+	let hasNext;
+	if (this.optUp.use && totalPage != null) hasNext = this.optUp.page.num < totalPage; // 是否还有下一页
+	this.endSuccess(dataSize, hasNext, systime);
+}
+
+/* 联网回调成功,结束下拉刷新和上拉加载
+ * dataSize: 当前页的数据量(必传)
+ * totalSize: 列表所有数据总数量(必传)
+ * systime: 服务器时间 (可空)
+ */
+MeScroll.prototype.endBySize = function(dataSize, totalSize, systime) {
+	let hasNext;
+	if (this.optUp.use && totalSize != null) {
+		let loadSize = (this.optUp.page.num - 1) * this.optUp.page.size + dataSize; // 已加载的数据总数
+		hasNext = loadSize < totalSize; // 是否还有下一页
+	}
+	this.endSuccess(dataSize, hasNext, systime);
+}
+
+/* 联网回调成功,结束下拉刷新和上拉加载
+ * dataSize: 当前页的数据个数(不是所有页的数据总和),用于上拉加载判断是否还有下一页.如果不传,则会判断还有下一页
+ * hasNext: 是否还有下一页,布尔类型;用来解决这个小问题:比如列表共有20条数据,每页加载10条,共2页.如果只根据dataSize判断,则需翻到第三页才会知道无更多数据,如果传了hasNext,则翻到第二页即可显示无更多数据.
+ * systime: 服务器时间(可空);用来解决这个小问题:当准备翻下一页时,数据库新增了几条记录,此时翻下一页,前面的几条数据会和上一页的重复;这里传入了systime,那么upCallback的page.time就会有值,把page.time传给服务器,让后台过滤新加入的那几条记录
+ */
+MeScroll.prototype.endSuccess = function(dataSize, hasNext, systime) {
+	let me = this;
+	// 结束下拉刷新
+	if (me.isDownScrolling) {
+		me.isDownEndSuccess = true
+		me.endDownScroll();
+	}
+
+	// 结束上拉加载
+	if (me.optUp.use) {
+		let isShowNoMore; // 是否已无更多数据
+		if (dataSize != null) {
+			let pageNum = me.optUp.page.num; // 当前页码
+			let pageSize = me.optUp.page.size; // 每页长度
+			// 如果是第一页
+			if (pageNum === 1) {
+				if (systime) me.optUp.page.time = systime; // 设置加载列表数据第一页的时间
+			}
+			if (dataSize < pageSize || hasNext === false) {
+				// 返回的数据不满一页时,则说明已无更多数据
+				me.optUp.hasNext = false;
+				if (dataSize === 0 && pageNum === 1) {
+					// 如果第一页无任何数据且配置了空布局
+					isShowNoMore = false;
+					me.showEmpty();
+				} else {
+					// 总列表数少于配置的数量,则不显示无更多数据
+					let allDataSize = (pageNum - 1) * pageSize + dataSize;
+					if (allDataSize < me.optUp.noMoreSize) {
+						isShowNoMore = false;
+					} else {
+						isShowNoMore = true;
+					}
+					me.removeEmpty(); // 移除空布局
+				}
+			} else {
+				// 还有下一页
+				isShowNoMore = false;
+				me.optUp.hasNext = true;
+				me.removeEmpty(); // 移除空布局
+			}
+		}
+
+		// 隐藏上拉
+		me.endUpScroll(isShowNoMore);
+	}
+}
+
+/* 回调失败,结束下拉刷新和上拉加载 */
+MeScroll.prototype.endErr = function(errDistance) {
+	// 结束下拉,回调失败重置回原来的页码和时间
+	if (this.isDownScrolling) {
+		this.isDownEndSuccess = false
+		let page = this.optUp.page;
+		if (page && this.prePageNum) {
+			page.num = this.prePageNum;
+			page.time = this.prePageTime;
+		}
+		this.endDownScroll();
+	}
+	// 结束上拉,回调失败重置回原来的页码
+	if (this.isUpScrolling) {
+		this.optUp.page.num--;
+		this.endUpScroll(false);
+		// 如果是mescroll-body,则需往回滚一定距离
+		if(this.isScrollBody && errDistance !== 0){ // 不处理0
+			if(!errDistance) errDistance = this.optUp.errDistance; // 不传,则取默认
+			this.scrollTo(this.getScrollTop() - errDistance, 0) // 往上回滚的距离
+		}
+	}
+}
+
+/* 显示空布局 */
+MeScroll.prototype.showEmpty = function() {
+	this.optUp.empty.use && this.optUp.empty.onShow && this.optUp.empty.onShow(true)
+}
+
+/* 移除空布局 */
+MeScroll.prototype.removeEmpty = function() {
+	this.optUp.empty.use && this.optUp.empty.onShow && this.optUp.empty.onShow(false)
+}
+
+/* 显示回到顶部的按钮 */
+MeScroll.prototype.showTopBtn = function() {
+	if (!this.topBtnShow) {
+		this.topBtnShow = true;
+		this.optUp.toTop.onShow && this.optUp.toTop.onShow(true);
+	}
+}
+
+/* 隐藏回到顶部的按钮 */
+MeScroll.prototype.hideTopBtn = function() {
+	if (this.topBtnShow) {
+		this.topBtnShow = false;
+		this.optUp.toTop.onShow && this.optUp.toTop.onShow(false);
+	}
+}
+
+/* 获取滚动条的位置 */
+MeScroll.prototype.getScrollTop = function() {
+	return this.scrollTop || 0
+}
+
+/* 记录滚动条的位置 */
+MeScroll.prototype.setScrollTop = function(y) {
+	this.scrollTop = y;
+}
+
+/* 滚动到指定位置 */
+MeScroll.prototype.scrollTo = function(y, t) {
+	this.myScrollTo && this.myScrollTo(y, t) // scrollview需自定义回到顶部方法
+}
+
+/* 自定义scrollTo */
+MeScroll.prototype.resetScrollTo = function(myScrollTo) {
+	this.myScrollTo = myScrollTo
+}
+
+/* 滚动条到底部的距离 */
+MeScroll.prototype.getScrollBottom = function() {
+	return this.getScrollHeight() - this.getClientHeight() - this.getScrollTop()
+}
+
+/* 计步器
+ star: 开始值
+ end: 结束值
+ callback(step,timer): 回调step值,计步器timer,可自行通过window.clearInterval(timer)结束计步器;
+ t: 计步时长,传0则直接回调end值;不传则默认300ms
+ rate: 周期;不传则默认30ms计步一次
+ * */
+MeScroll.prototype.getStep = function(star, end, callback, t, rate) {
+	let diff = end - star; // 差值
+	if (t === 0 || diff === 0) {
+		callback && callback(end);
+		return;
+	}
+	t = t || 300; // 时长 300ms
+	rate = rate || 30; // 周期 30ms
+	let count = t / rate; // 次数
+	let step = diff / count; // 步长
+	let i = 0; // 计数
+	let timer = setInterval(function() {
+		if (i < count - 1) {
+			star += step;
+			callback && callback(star, timer);
+			i++;
+		} else {
+			callback && callback(end, timer); // 最后一次直接设置end,避免计算误差
+			clearInterval(timer);
+		}
+	}, rate);
+}
+
+/* 滚动容器的高度 */
+MeScroll.prototype.getClientHeight = function(isReal) {
+	let h = this.clientHeight || 0
+	if (h === 0 && isReal !== true) { // 未获取到容器的高度,可临时取body的高度 (可能会有误差)
+		h = this.getBodyHeight()
+	}
+	return h
+}
+MeScroll.prototype.setClientHeight = function(h) {
+	this.clientHeight = h;
+}
+
+/* 滚动内容的高度 */
+MeScroll.prototype.getScrollHeight = function() {
+	return this.scrollHeight || 0;
+}
+MeScroll.prototype.setScrollHeight = function(h) {
+	this.scrollHeight = h;
+}
+
+/* body的高度 */
+MeScroll.prototype.getBodyHeight = function() {
+	return this.bodyHeight || 0;
+}
+MeScroll.prototype.setBodyHeight = function(h) {
+	this.bodyHeight = h;
+}
+
+/* 阻止浏览器默认滚动事件 */
+MeScroll.prototype.preventDefault = function(e) {
+	// 小程序不支持e.preventDefault, 已在wxs中禁止
+	// app的bounce只能通过配置pages.json的style.app-plus.bounce为"none"来禁止, 或使用renderjs禁止
+	// cancelable:是否可以被禁用; defaultPrevented:是否已经被禁用
+	if (e && e.cancelable && !e.defaultPrevented) e.preventDefault()
+}

+ 430 - 0
comps/mescroll-body/mescroll-uni.vue

@@ -0,0 +1,430 @@
+<template>
+	<view class="mescroll-uni-warp" :class="isShowEmpty?'page':''">
+		<scroll-view :id="viewId" class="mescroll-uni" :class="{'mescroll-uni-fixed':isFixed}" :style="{'height':scrollHeight,'padding-top':padTop,'padding-bottom':padBottom,'top':fixedTop,'bottom':fixedBottom}" :scroll-top="scrollTop" :scroll-with-animation="scrollAnim" @scroll="scroll" :scroll-y='scrollable' :enable-back-to-top="true" :throttle="false">
+			<view class="mescroll-uni-content mescroll-render-touch"
+			@touchstart="wxsBiz.touchstartEvent" 
+			@touchmove="wxsBiz.touchmoveEvent" 
+			@touchend="wxsBiz.touchendEvent" 
+			@touchcancel="wxsBiz.touchendEvent"
+			:change:prop="wxsBiz.propObserver"
+			:prop="wxsProp">
+				<!-- 状态栏 -->
+				<view v-if="topbar&&statusBarHeight" class="mescroll-topbar" :style="{height: statusBarHeight+'px', background: topbar}"></view>
+		
+				<view class="mescroll-wxs-content" :style="{'transform': translateY, 'transition': transition}" :change:prop="wxsBiz.callObserver" :prop="callProp">
+					<!-- 下拉加载区域 (支付宝小程序子组件传参给子子组件仍报单项数据流的异常,暂时不通过mescroll-down组件实现)-->
+					<!-- <mescroll-down :option="mescroll.optDown" :type="downLoadType" :rate="downRate"></mescroll-down> -->
+					<view v-if="mescroll.optDown.use" class="mescroll-downwarp" :style="{'background':mescroll.optDown.bgColor,'color':mescroll.optDown.textColor}">
+						<view class="downwarp-content">
+							<view class="downwarp-progress mescroll-wxs-progress" :class="{'mescroll-rotate': isDownLoading}" :style="{'border-color':mescroll.optDown.textColor, 'transform': downRotate}"></view>
+							<view class="downwarp-tip">{{downText}}</view>
+						</view>
+					</view>
+
+					<!-- 列表内容 -->
+					<slot></slot>
+
+					<!-- 空布局 -->
+					<mescroll-empty  v-if="isShowEmpty" :option="mescroll.optUp.empty" @emptyclick="emptyClick"></mescroll-empty>
+
+					<!-- 上拉加载区域 (下拉刷新时不显示, 支付宝小程序子组件传参给子子组件仍报单项数据流的异常,暂时不通过mescroll-up组件实现)-->
+					<!-- <mescroll-up v-if="mescroll.optUp.use && !isDownLoading && upLoadType!==3" :option="mescroll.optUp" :type="upLoadType"></mescroll-up> -->
+					<view v-if="mescroll.optUp.use && !isDownLoading && upLoadType!==3" class="mescroll-upwarp" :style="{'background':mescroll.optUp.bgColor,'color':mescroll.optUp.textColor}">
+						<!-- 加载中 (此处不能用v-if,否则android小程序快速上拉可能会不断触发上拉回调) -->
+						<view v-show="upLoadType===1">
+							<view class="upwarp-progress mescroll-rotate" :style="{'border-color':mescroll.optUp.textColor}"></view>
+							<view class="upwarp-tip">{{ mescroll.optUp.textLoading }}</view>
+						</view>
+						<!-- 无数据 -->
+						<view v-if="upLoadType===2" class="upwarp-nodata">{{ mescroll.optUp.textNoMore }}</view>
+					</view>
+				</view>
+			
+				<!-- 底部是否偏移TabBar的高度(默认仅在H5端的tab页生效) -->
+				<!-- #ifdef H5 -->
+				<view v-if="bottombar && windowBottom>0" class="mescroll-bottombar" :style="{height: windowBottom+'px'}"></view>
+				<!-- #endif -->
+				
+				<!-- 适配iPhoneX -->
+				<view v-if="safearea" class="mescroll-safearea"></view>
+			</view>
+		</scroll-view>
+
+		<!-- 回到顶部按钮 (fixed元素,需写在scroll-view外面,防止滚动的时候抖动)-->
+		<mescroll-top v-model="isShowToTop" :option="mescroll.optUp.toTop" @click="toTopClick"></mescroll-top>
+		
+		<!-- #ifdef MP-WEIXIN || MP-QQ || APP-PLUS || H5 -->
+		<!-- renderjs的数据载体,不可写在mescroll-downwarp内部,避免use为false时,载体丢失,无法更新数据 -->
+		<view :change:prop="renderBiz.propObserver" :prop="wxsProp"></view>
+		<!-- #endif -->
+	</view>
+</template>
+
+<!-- 微信小程序, QQ小程序, app, h5使用wxs -->
+<!-- #ifdef MP-WEIXIN || MP-QQ || APP-PLUS || H5 -->
+<script src="./wxs/wxs.wxs" module="wxsBiz" lang="wxs"></script>
+<!-- #endif -->
+
+<!-- app, h5使用renderjs -->
+<!-- #ifdef APP-PLUS || H5 -->
+<script module="renderBiz" lang="renderjs">
+	import renderBiz from './wxs/renderjs.js';
+	export default {
+		mixins:[renderBiz]
+	}
+</script>
+<!-- #endif -->
+
+<script>
+	// 引入mescroll-uni.js,处理核心逻辑
+	import MeScroll from './mescroll-uni.js';
+	// 引入全局配置
+	import GlobalOption from './mescroll-uni-option.js';
+	// 引入空布局组件
+	import MescrollEmpty from './components/mescroll-empty.vue';
+	// 引入回到顶部组件
+	import MescrollTop from './components/mescroll-top.vue';
+	// 引入兼容wxs(含renderjs)写法的mixins
+	import WxsMixin from './wxs/mixins.js';
+	
+	export default {
+		mixins: [WxsMixin],
+		components: {
+			MescrollEmpty,
+			MescrollTop
+		},
+		data() {
+			return {
+				mescroll: {optDown:{},optUp:{}}, // mescroll实例
+				viewId: 'id_' + Math.random().toString(36).substr(2,16), // 随机生成mescroll的id(不能数字开头,否则找不到元素)
+				downHight: 0, //下拉刷新: 容器高度
+				downRate: 0, // 下拉比率(inOffset: rate<1; outOffset: rate>=1)
+				downLoadType: 0, // 下拉刷新状态: 0(loading前), 1(inOffset), 2(outOffset), 3(showLoading), 4(endDownScroll)
+				upLoadType: 0, // 上拉加载状态: 0(loading前), 1loading中, 2没有更多了,显示END文本提示, 3(没有更多了,不显示END文本提示)
+				isShowEmpty: false, // 是否显示空布局
+				isShowToTop: false, // 是否显示回到顶部按钮
+				scrollTop: 0, // 滚动条的位置
+				scrollAnim: false, // 是否开启滚动动画
+				windowTop: 0, // 可使用窗口的顶部位置
+				windowBottom: 0, // 可使用窗口的底部位置
+				windowHeight: 0, // 可使用窗口的高度
+				statusBarHeight: 0 // 状态栏高度
+			}
+		},
+		props: {
+			down: Object, // 下拉刷新的参数配置
+			up: Object, // 上拉加载的参数配置
+			top: [String, Number], // 下拉布局往下的偏移量 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx, 百分比则相对于windowHeight)
+			topbar: [Boolean, String], // top的偏移量是否加上状态栏高度, 默认false (使用场景:取消原生导航栏时,配置此项可留出状态栏的占位, 支持传入字符串背景,如色值,背景图,渐变)
+			bottom: [String, Number], // 上拉布局往上的偏移量 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx, 百分比则相对于windowHeight)
+			safearea: Boolean, // bottom的偏移量是否加上底部安全区的距离, 默认false (需要适配iPhoneX时使用)
+			fixed: { // 是否通过fixed固定mescroll的高度, 默认true
+				type: Boolean,
+				default: true
+			},
+			height: [String, Number], // 指定mescroll的高度, 此项有值,则不使用fixed. (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx, 百分比则相对于windowHeight)
+			bottombar:{ // 底部是否偏移TabBar的高度(默认仅在H5端的tab页生效)
+				type: Boolean,
+				default: true
+			}
+		},
+		computed: {
+			// 是否使用fixed定位 (当height有值,则不使用)
+			isFixed(){
+				return !this.height && this.fixed
+			},
+			// mescroll的高度
+			scrollHeight(){
+				if (this.isFixed) {
+					return "auto"
+				} else if(this.height){
+					return this.toPx(this.height) + 'px'
+				}else{
+					return "100%"
+				}
+			},
+			// 下拉布局往下偏移的距离 (px)
+			numTop() {
+				return this.toPx(this.top)
+			},
+			fixedTop() {
+				return this.isFixed ? (this.numTop + this.windowTop) + 'px' : 0
+			},
+			padTop() {
+				return !this.isFixed ? this.numTop + 'px' : 0
+			},
+			// 上拉布局往上偏移 (px)
+			numBottom() {
+				return this.toPx(this.bottom)
+			},
+			fixedBottom() {
+				return this.isFixed ? (this.numBottom + this.windowBottom) + 'px' : 0
+			},
+			padBottom() {
+				return !this.isFixed ? this.numBottom + 'px' : 0
+			},
+			// 是否为重置下拉的状态
+			isDownReset(){
+				return this.downLoadType===3 || this.downLoadType===4
+			},
+			// 过渡
+			transition() {
+				return this.isDownReset ? 'transform 300ms' : '';
+			},
+			translateY() {
+				return this.downHight > 0 ? 'translateY(' + this.downHight + 'px)' : ''; // transform会使fixed失效,需注意把fixed元素写在mescroll之外
+			},
+			// 列表是否可滑动
+			scrollable(){
+				return this.downLoadType===0 || this.isDownReset
+			},
+			// 是否在加载中
+			isDownLoading(){
+				return this.downLoadType === 3
+			},
+			// 旋转的角度
+			downRotate(){
+				return 'rotate(' + 360 * this.downRate + 'deg)'
+			},
+			// 文本提示
+			downText(){
+				if(!this.mescroll) return ""; // 避免头条小程序初始化时报错
+				switch (this.downLoadType){
+					case 1: return this.mescroll.optDown.textInOffset;
+					case 2: return this.mescroll.optDown.textOutOffset;
+					case 3: return this.mescroll.optDown.textLoading;
+					case 4: return this.mescroll.isDownEndSuccess ? this.mescroll.optDown.textSuccess : this.mescroll.isDownEndSuccess==false ? this.mescroll.optDown.textErr : this.mescroll.optDown.textInOffset;
+					default: return this.mescroll.optDown.textInOffset;
+				}
+			}
+		},
+		methods: {
+			//number,rpx,upx,px,% --> px的数值
+			toPx(num){
+				if(typeof num === "string"){
+					if (num.indexOf('px') !== -1) {
+						if(num.indexOf('rpx') !== -1) { // "10rpx"
+							num = num.replace('rpx', '');
+						} else if(num.indexOf('upx') !== -1) { // "10upx"
+							num = num.replace('upx', '');
+						} else { // "10px"
+							return Number(num.replace('px', ''))
+						}
+					}else if (num.indexOf('%') !== -1){
+						// 传百分比,则相对于windowHeight,传"10%"则等于windowHeight的10%
+						let rate = Number(num.replace("%","")) / 100
+						return this.windowHeight * rate
+					}
+				}
+				return num ? uni.upx2px(Number(num)) : 0
+			},
+			//注册列表滚动事件,用于下拉刷新和上拉加载
+			scroll(e) {
+				this.mescroll.scroll(e.detail, () => {
+					this.$emit('scroll', this.mescroll) // 此时可直接通过 this.mescroll.scrollTop获取滚动条位置; this.mescroll.isScrollUp获取是否向上滑动
+				})
+			},
+			// 点击空布局的按钮回调
+			emptyClick() {
+				this.$emit('emptyclick', this.mescroll)
+			},
+			// 点击回到顶部的按钮回调
+			toTopClick() {
+				this.mescroll.scrollTo(0, this.mescroll.optUp.toTop.duration); // 执行回到顶部
+				this.$emit('topclick', this.mescroll); // 派发点击回到顶部按钮的回调
+			},
+			// 更新滚动区域的高度 (使内容不满屏和到底,都可继续翻页)
+			setClientHeight() {
+				if (this.mescroll.getClientHeight(true) === 0 && !this.isExec) {
+					this.isExec = true; // 避免多次获取
+					this.$nextTick(() => { // 确保dom已渲染
+						this.getClientInfo(data=>{
+							this.isExec = false;
+							if (data) {
+								this.mescroll.setClientHeight(data.height);
+							} else if (this.clientNum != 3) { // 极少部分情况,可能dom还未渲染完毕,递归获取,最多重试3次
+								this.clientNum = this.clientNum == null ? 1 : this.clientNum + 1;
+								setTimeout(() => {
+									this.setClientHeight()
+								}, this.clientNum * 100)
+							}
+						})
+					})
+				}
+			},
+			// 获取滚动区域的信息
+			getClientInfo(success){
+				let query = uni.createSelectorQuery();
+				// #ifndef MP-ALIPAY || MP-DINGTALK
+				query = query.in(this) // 支付宝小程序不支持in(this),而字节跳动小程序必须写in(this), 否则都取不到值
+				// #endif
+				let view = query.select('#' + this.viewId);
+				view.boundingClientRect(data => {
+					success(data)
+				}).exec();
+			}
+		},
+		// 使用created初始化mescroll对象; 如果用mounted部分css样式编译到H5会失效
+		created() {
+			let vm = this;
+
+			let diyOption = {
+				// 下拉刷新的配置
+				down: {
+					inOffset() {
+						vm.downLoadType = 1; // 下拉的距离进入offset范围内那一刻的回调 (自定义mescroll组件时,此行不可删)
+					},
+					outOffset() {
+						vm.downLoadType = 2; // 下拉的距离大于offset那一刻的回调 (自定义mescroll组件时,此行不可删)
+					},
+					onMoving(mescroll, rate, downHight) {
+						// 下拉过程中的回调,滑动过程一直在执行;
+						vm.downHight = downHight; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
+						vm.downRate = rate; //下拉比率 (inOffset: rate<1; outOffset: rate>=1)
+					},
+					showLoading(mescroll, downHight) {
+						vm.downLoadType = 3; // 显示下拉刷新进度的回调 (自定义mescroll组件时,此行不可删)
+						vm.downHight = downHight; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
+					},
+					beforeEndDownScroll(mescroll){
+						vm.downLoadType = 4; 
+						return mescroll.optDown.beforeEndDelay // 延时结束的时长
+					},
+					endDownScroll() {
+						vm.downLoadType = 4; // 结束下拉 (自定义mescroll组件时,此行不可删)
+						vm.downHight = 0; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
+						vm.downResetTimer && clearTimeout(vm.downResetTimer)
+						vm.downResetTimer = setTimeout(()=>{ // 过渡动画执行完毕后,需重置为0的状态,以便置空this.transition,避免iOS小程序列表渲染不完整
+							if(vm.downLoadType===4) vm.downLoadType = 0
+						},300)
+					},
+					// 派发下拉刷新的回调
+					callback: function(mescroll) {
+						vm.$emit('down', mescroll)
+					}
+				},
+				// 上拉加载的配置
+				up: {
+					// 显示加载中的回调
+					showLoading() {
+						vm.upLoadType = 1;
+					},
+					// 显示无更多数据的回调
+					showNoMore() {
+						vm.upLoadType = 2;
+					},
+					// 隐藏上拉加载的回调
+					hideUpScroll(mescroll) {
+						vm.upLoadType = mescroll.optUp.hasNext ? 0 : 3;
+					},
+					// 空布局
+					empty: {
+						onShow(isShow) { // 显示隐藏的回调
+							vm.isShowEmpty = isShow;
+						}
+					},
+					// 回到顶部
+					toTop: {
+						onShow(isShow) { // 显示隐藏的回调
+							vm.isShowToTop = isShow;
+						}
+					},
+					// 派发上拉加载的回调
+					callback: function(mescroll) {
+						vm.$emit('up', mescroll);
+						// 更新容器的高度 (多mescroll的情况)
+						vm.setClientHeight()
+					}
+				}
+			}
+
+			MeScroll.extend(diyOption, GlobalOption); // 混入全局的配置
+			let myOption = JSON.parse(JSON.stringify({'down': vm.down,'up': vm.up})) // 深拷贝,避免对props的影响
+			MeScroll.extend(myOption, diyOption); // 混入具体界面的配置
+
+			// 初始化MeScroll对象
+			vm.mescroll = new MeScroll(myOption);
+			vm.mescroll.viewId = vm.viewId; // 附带id
+			// init回调mescroll对象
+			vm.$emit('init', vm.mescroll);
+			
+			// 设置高度
+			const sys = uni.getSystemInfoSync();
+			if(sys.windowTop) vm.windowTop = sys.windowTop;
+			if(sys.windowBottom) vm.windowBottom = sys.windowBottom;
+			if(sys.windowHeight) vm.windowHeight = sys.windowHeight;
+			if(sys.statusBarHeight) vm.statusBarHeight = sys.statusBarHeight;
+			// 使down的bottomOffset生效
+			vm.mescroll.setBodyHeight(sys.windowHeight);
+
+			// 因为使用的是scrollview,这里需自定义scrollTo
+			vm.mescroll.resetScrollTo((y, t) => {
+				vm.scrollAnim = (t !== 0); // t为0,则不使用动画过渡
+				if(typeof y === 'string'){
+					// 小程序不支持slot里面的scroll-into-view, 统一使用计算的方式实现
+					vm.getClientInfo(function(rect){
+						let mescrollTop = rect.top // mescroll到顶部的距离
+						let selector;
+						if(y.indexOf('#')==-1 && y.indexOf('.')==-1){
+							selector = '#'+y // 不带#和. 则默认为id选择器
+						}else{
+							selector = y
+							// #ifdef APP-PLUS || H5 || MP-ALIPAY || MP-DINGTALK
+							if(y.indexOf('>>>')!=-1){ // 不支持跨自定义组件的后代选择器 (转为普通的选择器即可跨组件查询)
+								selector = y.split('>>>')[1].trim()
+							}
+							// #endif
+						}
+						uni.createSelectorQuery().select(selector).boundingClientRect(function(rect){
+							if (rect) {
+								let curY = vm.mescroll.getScrollTop()
+								let top = rect.top - mescrollTop
+								top += curY
+								if(!vm.isFixed) top -= vm.numTop
+								vm.scrollTop = curY;
+								vm.$nextTick(function() {
+									vm.scrollTop = top
+								})
+							} else{
+								console.error(selector + ' does not exist');
+							}
+						}).exec()
+					})
+					return;
+				}
+				let curY = vm.mescroll.getScrollTop()
+				if (t === 0 || t === 300) { // 当t使用默认配置的300时,则使用系统自带的动画过渡
+					vm.scrollTop = curY;
+					vm.$nextTick(function() {
+						vm.scrollTop = y
+					})
+				} else {
+					vm.mescroll.getStep(curY, y, step => { // 此写法可支持配置t
+						vm.scrollTop = step
+					}, t)
+				}
+			})
+			
+			// 具体的界面如果不配置up.toTop.safearea,则取本vue的safearea值
+			if (vm.up && vm.up.toTop && vm.up.toTop.safearea != null) {} else {
+				vm.mescroll.optUp.toTop.safearea = vm.safearea;
+			}
+		},
+		mounted() {
+			// 设置容器的高度
+			this.setClientHeight()
+		}
+	}
+</script>
+
+<style lang="scss">
+	
+	.page{
+		background-color: #FFFFFF;
+		min-height: calc(100vh - 90rpx);
+	}
+	
+	@import "./mescroll-uni.css";
+	@import "./components/mescroll-down.css";
+	@import './components/mescroll-up.css';
+</style>

+ 48 - 0
comps/mescroll-body/mixins/mescroll-comp.js

@@ -0,0 +1,48 @@
+/**
+ * mescroll-body写在子组件时,需通过mescroll的mixins补充子组件缺少的生命周期
+ */
+const MescrollCompMixin = {
+	// 因为子组件无onPageScroll和onReachBottom的页面生命周期,需在页面传递进到子组件 (一级)
+	onPageScroll(e) {
+		this.handlePageScroll(e)
+	},
+	onReachBottom() {
+		this.handleReachBottom()
+	},
+	// 当down的native: true时, 还需传递此方法进到子组件
+	onPullDownRefresh(){
+		this.handlePullDownRefresh()
+	},
+	// mescroll-body写在子子子...组件的情况 (多级)
+	data() {
+		return {
+			mescroll: {
+				onPageScroll: e=>{
+					this.handlePageScroll(e)
+				},
+				onReachBottom: ()=>{
+					this.handleReachBottom()
+				},
+				onPullDownRefresh: ()=>{
+					this.handlePullDownRefresh()
+				}
+			}
+		}
+	},
+	methods:{
+		handlePageScroll(e){
+			let item = this.$refs["mescrollItem"];
+			if(item && item.mescroll) item.mescroll.onPageScroll(e);
+		},
+		handleReachBottom(){
+			let item = this.$refs["mescrollItem"];
+			if(item && item.mescroll) item.mescroll.onReachBottom();
+		},
+		handlePullDownRefresh(){
+			let item = this.$refs["mescrollItem"];
+			if(item && item.mescroll) item.mescroll.onPullDownRefresh();
+		}
+	}
+}
+
+export default MescrollCompMixin;

+ 59 - 0
comps/mescroll-body/mixins/mescroll-more-item.js

@@ -0,0 +1,59 @@
+/**
+ * mescroll-more-item的mixins, 仅在多个 mescroll-body 写在子组件时使用 (参考 mescroll-more 案例)
+ */
+const MescrollMoreItemMixin = {
+	// 支付宝小程序不支持props的mixin,需写在具体的页面中
+	// #ifndef MP-ALIPAY || MP-DINGTALK
+	props:{
+		i: Number, // 每个tab页的专属下标
+		index: { // 当前tab的下标
+			type: Number,
+			default(){
+				return 0
+			}
+		}
+	},
+	// #endif
+	data() {
+		return {
+			downOption:{
+				auto:false // 不自动加载
+			},
+			upOption:{
+				auto:false // 不自动加载
+			},
+			isInit: false // 当前tab是否已初始化
+		}
+	},
+	watch:{
+		// 监听下标的变化
+		index(val){
+			if (this.i === val && !this.isInit) {
+				this.isInit = true; // 标记为true
+				this.mescroll && this.mescroll.triggerDownScroll();
+			}
+		}
+	},
+	methods: {
+		// 以ref的方式初始化mescroll对象 (兼容字节跳动小程序)
+		mescrollInitByRef() {
+			if(!this.mescroll || !this.mescroll.resetUpScroll){
+				// 字节跳动小程序编辑器不支持一个页面存在相同的ref, 多mescroll的ref需动态生成, 格式为'mescrollRef下标'
+				let mescrollRef = this.$refs.mescrollRef || this.$refs['mescrollRef'+this.i];
+				if(mescrollRef) this.mescroll = mescrollRef.mescroll
+			}
+		},
+		// mescroll组件初始化的回调,可获取到mescroll对象 (覆盖mescroll-mixins.js的mescrollInit, 为了标记isInit)
+		mescrollInit(mescroll) {
+			this.mescroll = mescroll;
+			this.mescrollInitByRef && this.mescrollInitByRef(); // 兼容字节跳动小程序
+			// 自动加载当前tab的数据
+			if(this.i === this.index){
+				this.isInit = true; // 标记为true
+				this.mescroll.triggerDownScroll();
+			}
+		},
+	}
+}
+
+export default MescrollMoreItemMixin;

+ 74 - 0
comps/mescroll-body/mixins/mescroll-more.js

@@ -0,0 +1,74 @@
+/**
+ * mescroll-body写在子组件时, 需通过mescroll的mixins补充子组件缺少的生命周期
+ */
+const MescrollMoreMixin = {
+	data() {
+		return {
+			tabIndex: 0, // 当前tab下标
+			mescroll: {
+				onPageScroll: e=>{
+					this.handlePageScroll(e)
+				},
+				onReachBottom: ()=>{
+					this.handleReachBottom()
+				},
+				onPullDownRefresh: ()=>{
+					this.handlePullDownRefresh()
+				}
+			}
+		}
+	},
+	// 因为子组件无onPageScroll和onReachBottom的页面生命周期,需在页面传递进到子组件
+	onPageScroll(e) {
+		this.handlePageScroll(e)
+	},
+	onReachBottom() {
+		this.handleReachBottom()
+	},
+	// 当down的native: true时, 还需传递此方法进到子组件
+	onPullDownRefresh(){
+		this.handlePullDownRefresh()
+	},
+	methods:{
+		handlePageScroll(e){
+			let mescroll = this.getMescroll(this.tabIndex);
+			mescroll && mescroll.onPageScroll(e);
+		},
+		handleReachBottom(){
+			let mescroll = this.getMescroll(this.tabIndex);
+			mescroll && mescroll.onReachBottom();
+		},
+		handlePullDownRefresh(){
+			let mescroll = this.getMescroll(this.tabIndex);
+			mescroll && mescroll.onPullDownRefresh();
+		},
+		// 根据下标获取对应子组件的mescroll
+		getMescroll(i){
+			if(!this.mescrollItems) this.mescrollItems = [];
+			if(!this.mescrollItems[i]) {
+				// v-for中的refs
+				let vForItem = this.$refs["mescrollItem"];
+				if(vForItem){
+					this.mescrollItems[i] = vForItem[i]
+				}else{
+					// 普通的refs,不可重复
+					this.mescrollItems[i] = this.$refs["mescrollItem"+i];
+				}
+			}
+			let item = this.mescrollItems[i]
+			return item ? item.mescroll : null
+		},
+		// 切换tab,恢复滚动条位置
+		tabChange(i){
+			let mescroll = this.getMescroll(i);
+			if(mescroll){
+				// 延时(比$nextTick靠谱一些),确保元素已渲染
+				setTimeout(()=>{
+					mescroll.scrollTo(mescroll.getScrollTop(),0)
+				},30)
+			}
+		}
+	}
+}
+
+export default MescrollMoreMixin;

+ 109 - 0
comps/mescroll-body/wxs/mixins.js

@@ -0,0 +1,109 @@
+// 定义在wxs (含renderjs) 逻辑层的数据和方法, 与视图层相互通信
+const WxsMixin = {
+	data() {
+		return {
+			// 传入wxs视图层的数据 (响应式)
+			wxsProp: {
+				optDown:{}, // 下拉刷新的配置
+				scrollTop:0, // 滚动条的距离
+				bodyHeight:0, // body的高度
+				isDownScrolling:false, // 是否正在下拉刷新中
+				isUpScrolling:false, // 是否正在上拉加载中
+				isScrollBody:true, // 是否为mescroll-body滚动
+				isUpBoth:true, // 上拉加载时,是否同时可以下拉刷新
+				t: 0 // 数据更新的标记 (只有数据更新了,才会触发wxs的Observer)
+			},
+			
+			// 标记调用wxs视图层的方法
+			callProp: {
+				callType: '', // 方法名
+				t: 0 // 数据更新的标记 (只有数据更新了,才会触发wxs的Observer)
+			},
+			
+			// 不用wxs的平台使用此处的wxsBiz对象,抹平wxs的写法 (微信小程序和APP使用的wxsBiz对象是./wxs/wxs.wxs)
+			// #ifndef MP-WEIXIN || MP-QQ || APP-PLUS || H5
+			wxsBiz: {
+				//注册列表touchstart事件,用于下拉刷新
+				touchstartEvent: e=> {
+					this.mescroll.touchstartEvent(e);
+				},
+				//注册列表touchmove事件,用于下拉刷新
+				touchmoveEvent: e=> {
+					this.mescroll.touchmoveEvent(e);
+				},
+				//注册列表touchend事件,用于下拉刷新
+				touchendEvent: e=> {
+					this.mescroll.touchendEvent(e);
+				},
+				propObserver(){}, // 抹平wxs的写法
+				callObserver(){} // 抹平wxs的写法
+			},
+			// #endif
+			
+			// 不用renderjs的平台使用此处的renderBiz对象,抹平renderjs的写法 (app 和 h5 使用的renderBiz对象是./wxs/renderjs.js)
+			// #ifndef APP-PLUS || H5
+			renderBiz: {
+				propObserver(){} // 抹平renderjs的写法
+			}
+			// #endif
+		}
+	},
+	methods: {
+		// wxs视图层调用逻辑层的回调
+		wxsCall(msg){
+			if(msg.type === 'setWxsProp'){
+				// 更新wxsProp数据 (值改变才触发更新)
+				this.wxsProp = {
+					optDown: this.mescroll.optDown,
+					scrollTop: this.mescroll.getScrollTop(),
+					bodyHeight: this.mescroll.getBodyHeight(),
+					isDownScrolling: this.mescroll.isDownScrolling,
+					isUpScrolling: this.mescroll.isUpScrolling,
+					isUpBoth: this.mescroll.optUp.isBoth,
+					isScrollBody:this.mescroll.isScrollBody,
+					t: Date.now()
+				}
+			}else if(msg.type === 'setLoadType'){
+				// 设置inOffset,outOffset的状态
+				this.downLoadType = msg.downLoadType
+				// 状态挂载到mescroll对象, 以便在其他组件中使用, 比如<me-video>中
+				this.$set(this.mescroll, 'downLoadType', this.downLoadType)
+				// 重置是否加载成功的状态
+				this.$set(this.mescroll, 'isDownEndSuccess', null)
+			}else if(msg.type === 'triggerDownScroll'){
+				// 主动触发下拉刷新
+				this.mescroll.triggerDownScroll();
+			}else if(msg.type === 'endDownScroll'){
+				// 结束下拉刷新
+				this.mescroll.endDownScroll();
+			}else if(msg.type === 'triggerUpScroll'){
+				// 主动触发上拉加载
+				this.mescroll.triggerUpScroll(true);
+			}
+		}
+	},
+	mounted() {
+		// #ifdef MP-WEIXIN || MP-QQ || APP-PLUS || H5
+		// 配置主动触发wxs显示加载进度的回调
+		this.mescroll.optDown.afterLoading = ()=>{
+			this.callProp = {callType: "showLoading", t: Date.now()} // 触发wxs的方法 (值改变才触发更新)
+		}
+		// 配置主动触发wxs隐藏加载进度的回调
+		this.mescroll.optDown.afterEndDownScroll = ()=>{
+			this.callProp = {callType: "endDownScroll", t: Date.now()} // 触发wxs的方法 (值改变才触发更新)
+			let delay = 300 + (this.mescroll.optDown.beforeEndDelay || 0)
+			setTimeout(()=>{
+				if(this.downLoadType === 4 || this.downLoadType === 0){
+					this.callProp = {callType: "clearTransform", t: Date.now()} // 触发wxs的方法 (值改变才触发更新)
+				}
+				// 状态挂载到mescroll对象, 以便在其他组件中使用, 比如<me-video>中
+				this.$set(this.mescroll, 'downLoadType', this.downLoadType)
+			}, delay)
+		}
+		// 初始化wxs的数据
+		this.wxsCall({type: 'setWxsProp'})
+		// #endif
+	}
+}
+
+export default WxsMixin;

+ 92 - 0
comps/mescroll-body/wxs/renderjs.js

@@ -0,0 +1,92 @@
+// 使用renderjs直接操作window对象,实现动态控制app和h5的bounce
+// bounce: iOS橡皮筋,Android半月弧,h5浏览器下拉背景等效果 (下拉刷新时禁止)
+// https://uniapp.dcloud.io/frame?id=renderjs
+
+// 与wxs的me实例一致
+var me = {}
+
+// 初始化window对象的touch事件 (仅初始化一次)
+if(window && !window.$mescrollRenderInit){
+	window.$mescrollRenderInit = true
+	
+	
+	window.addEventListener('touchstart', function(e){
+		if (me.disabled()) return;
+		me.startPoint = me.getPoint(e); // 记录起点
+	}, {passive: true})
+	
+	
+	window.addEventListener('touchmove', function(e){
+		if (me.disabled()) return;
+		if (me.getScrollTop() > 0) return; // 需在顶部下拉,才禁止bounce
+		
+		var curPoint = me.getPoint(e); // 当前点
+		var moveY = curPoint.y - me.startPoint.y; // 和起点比,移动的距离,大于0向下拉,小于0向上拉
+		// 向下拉
+		if (moveY > 0) {
+			// 可下拉的条件
+			if (!me.isDownScrolling && !me.optDown.isLock && (!me.isUpScrolling || (me.isUpScrolling && me.isUpBoth))) {
+				
+				// 只有touch在mescroll的view上面,才禁止bounce
+				var el = e.target;
+				var isMescrollTouch = false;
+				while (el && el.tagName && el.tagName !== 'UNI-PAGE-BODY' && el.tagName != "BODY") {
+					var cls = el.classList;
+					if (cls && cls.contains('mescroll-render-touch')) {
+						isMescrollTouch = true
+						break;
+					}
+					el = el.parentNode; // 继续检查其父元素
+				}
+				// 禁止bounce (不会对swiper和iOS侧滑返回造成影响)
+				if (isMescrollTouch && e.cancelable && !e.defaultPrevented) e.preventDefault();
+			}
+		}
+	}, {passive: false})
+}
+
+/* 获取滚动条的位置 */
+me.getScrollTop = function() {
+	return me.scrollTop || 0
+}
+
+/* 是否禁用下拉刷新 */
+me.disabled = function(){
+	return !me.optDown || !me.optDown.use || me.optDown.native
+}
+
+/* 根据点击滑动事件获取第一个手指的坐标 */
+me.getPoint = function(e) {
+	if (!e) {
+		return {x: 0,y: 0}
+	}
+	if (e.touches && e.touches[0]) {
+		return {x: e.touches[0].pageX,y: e.touches[0].pageY}
+	} else if (e.changedTouches && e.changedTouches[0]) {
+		return {x: e.changedTouches[0].pageX,y: e.changedTouches[0].pageY}
+	} else {
+		return {x: e.clientX,y: e.clientY}
+	}
+}
+
+/**
+ * 监听逻辑层数据的变化 (实时更新数据)
+ */
+function propObserver(wxsProp) {
+	me.optDown = wxsProp.optDown
+	me.scrollTop = wxsProp.scrollTop
+	me.isDownScrolling = wxsProp.isDownScrolling
+	me.isUpScrolling = wxsProp.isUpScrolling
+	me.isUpBoth = wxsProp.isUpBoth
+}
+
+/* 导出模块 */
+const renderBiz = {
+	data() {
+		return {
+			propObserver: propObserver,
+		}
+	}
+}
+
+export default renderBiz;

+ 268 - 0
comps/mescroll-body/wxs/wxs.wxs

@@ -0,0 +1,268 @@
+// 使用wxs处理交互动画, 提高性能, 同时避免小程序bounce对下拉刷新的影响
+// https://uniapp.dcloud.io/frame?id=wxs
+// https://developers.weixin.qq.com/miniprogram/dev/framework/view/interactive-animation.html 
+
+// 模拟mescroll实例, 与mescroll.js的写法尽量保持一致
+var me = {}
+
+// ------ 自定义下拉刷新动画 start ------
+
+/* 下拉过程中的回调,滑动过程一直在执行 (rate<1为inOffset; rate>1为outOffset) */
+me.onMoving = function (ins, rate, downHight){
+	ins.requestAnimationFrame(function () {
+		ins.selectComponent('.mescroll-wxs-content').setStyle({
+			'will-change': 'transform', // 可解决下拉过程中, image和swiper脱离文档流的问题
+			'transform': 'translateY(' + downHight + 'px)',
+			'transition': ''
+		})
+		// 环形进度条
+		var progress = ins.selectComponent('.mescroll-wxs-progress')
+		progress && progress.setStyle({transform: 'rotate(' + 360 * rate + 'deg)'})
+	})
+}
+
+/* 显示下拉刷新进度 */
+me.showLoading = function (ins){
+	me.downHight = me.optDown.offset
+	ins.requestAnimationFrame(function () {
+		ins.selectComponent('.mescroll-wxs-content').setStyle({
+			'will-change': 'auto',
+			'transform': 'translateY(' + me.downHight + 'px)',
+			'transition': 'transform 300ms'
+		})
+	})
+}
+
+/* 结束下拉 */
+me.endDownScroll = function (ins){
+	me.downHight = 0;
+	me.isDownScrolling = false;
+	ins.requestAnimationFrame(function () {
+		ins.selectComponent('.mescroll-wxs-content').setStyle({
+			'will-change': 'auto',
+			'transform': 'translateY(0)', // 不可以写空串,否则scroll-view渲染不完整 (延时350ms会调clearTransform置空)
+			'transition': 'transform 300ms'
+		})
+	})
+}
+
+/* 结束下拉动画执行完毕后, 清除transform和transition, 避免对列表内容样式造成影响, 如: h5的list-msg示例下拉进度条漏出来等 */
+me.clearTransform = function (ins){
+	ins.requestAnimationFrame(function () {
+		ins.selectComponent('.mescroll-wxs-content').setStyle({
+			'will-change': '',
+			'transform': '',
+			'transition': ''
+		})
+	})
+}
+
+// ------ 自定义下拉刷新动画 end ------
+
+/**
+ * 监听逻辑层数据的变化 (实时更新数据)
+ */
+function propObserver(wxsProp) {
+	me.optDown = wxsProp.optDown
+	me.scrollTop = wxsProp.scrollTop
+	me.bodyHeight = wxsProp.bodyHeight
+	me.isDownScrolling = wxsProp.isDownScrolling
+	me.isUpScrolling = wxsProp.isUpScrolling
+	me.isUpBoth = wxsProp.isUpBoth
+	me.isScrollBody = wxsProp.isScrollBody
+	me.startTop = wxsProp.scrollTop // 及时更新touchstart触发的startTop, 避免scroll-view快速惯性滚动到顶部取值不准确
+}
+
+/**
+ * 监听逻辑层数据的变化 (调用wxs的方法)
+ */
+function callObserver(callProp, oldValue, ins) {
+	if (me.disabled()) return;
+	if(callProp.callType){
+		// 逻辑层(App Service)的style已失效,需在视图层(Webview)设置style
+		if(callProp.callType === 'showLoading'){
+			me.showLoading(ins)
+		}else if(callProp.callType === 'endDownScroll'){
+			me.endDownScroll(ins)
+		}else if(callProp.callType === 'clearTransform'){
+			me.clearTransform(ins)
+		}
+	}
+}
+
+/**
+ * touch事件
+ */
+function touchstartEvent(e, ins) {
+	me.downHight = 0; // 下拉的距离
+	me.startPoint = me.getPoint(e); // 记录起点
+	me.startTop = me.getScrollTop(); // 记录此时的滚动条位置
+	me.startAngle = 0; // 初始角度
+	me.lastPoint = me.startPoint; // 重置上次move的点
+	me.maxTouchmoveY = me.getBodyHeight() - me.optDown.bottomOffset; // 手指触摸的最大范围(写在touchstart避免body获取高度为0的情况)
+	me.inTouchend = false; // 标记不是touchend
+	
+	me.callMethod(ins, {type: 'setWxsProp'}) // 同步更新wxsProp的数据 (小程序是异步的,可能touchmove先执行,才到propObserver; h5和app是同步)
+}
+
+function touchmoveEvent(e, ins) {
+	var isPrevent = true // false表示不往上冒泡,相当于调用了同时调用了stopPropagation和preventDefault (对小程序生效, h5和app无效)
+	
+	if (me.disabled()) return isPrevent;
+	
+	var scrollTop = me.getScrollTop(); // 当前滚动条的距离
+	var curPoint = me.getPoint(e); // 当前点
+	
+	var moveY = curPoint.y - me.startPoint.y; // 和起点比,移动的距离,大于0向下拉,小于0向上拉
+	
+	// 向下拉 && 在顶部
+	// mescroll-body,直接判定在顶部即可
+	// scroll-view在滚动时不会触发touchmove,当触顶/底/左/右时,才会触发touchmove
+	// scroll-view滚动到顶部时,scrollTop不一定为0,也有可能大于0; 在iOS的APP中scrollTop可能为负数,不一定和startTop相等
+	if (moveY > 0 && (
+			(me.isScrollBody && scrollTop <= 0)
+			||
+			(!me.isScrollBody && (scrollTop <= 0 || (scrollTop <= me.optDown.startTop && scrollTop === me.startTop)) )
+		)) {
+		// 可下拉的条件
+		if (!me.inTouchend && !me.isDownScrolling && !me.optDown.isLock && (!me.isUpScrolling || (me.isUpScrolling &&
+				me.isUpBoth))) {
+	
+			// 下拉的角度是否在配置的范围内
+			if(!me.startAngle) me.startAngle = me.getAngle(me.lastPoint, curPoint); // 两点之间的角度,区间 [0,90]
+			if (me.startAngle < me.optDown.minAngle) return isPrevent; // 如果小于配置的角度,则不往下执行下拉刷新
+	
+			// 如果手指的位置超过配置的距离,则提前结束下拉,避免Webview嵌套导致touchend无法触发
+			if (me.maxTouchmoveY > 0 && curPoint.y >= me.maxTouchmoveY) {
+				me.inTouchend = true; // 标记执行touchend
+				touchendEvent(e, ins); // 提前触发touchend
+				return isPrevent;
+			}
+			
+			isPrevent = false // 小程序是return false
+	
+			var diff = curPoint.y - me.lastPoint.y; // 和上次比,移动的距离 (大于0向下,小于0向上)
+	
+			// 下拉距离  < 指定距离
+			if (me.downHight < me.optDown.offset) {
+				if (me.movetype !== 1) {
+					me.movetype = 1; // 加入标记,保证只执行一次
+					// me.optDown.inOffset && me.optDown.inOffset(me); // 进入指定距离范围内那一刻的回调,只执行一次
+					me.callMethod(ins, {type: 'setLoadType', downLoadType: 1})
+					me.isMoveDown = true; // 标记下拉区域高度改变,在touchend重置回来
+				}
+				me.downHight += diff * me.optDown.inOffsetRate; // 越往下,高度变化越小
+	
+				// 指定距离  <= 下拉距离
+			} else {
+				if (me.movetype !== 2) {
+					me.movetype = 2; // 加入标记,保证只执行一次
+					// me.optDown.outOffset && me.optDown.outOffset(me); // 下拉超过指定距离那一刻的回调,只执行一次
+					me.callMethod(ins, {type: 'setLoadType', downLoadType: 2})
+					me.isMoveDown = true; // 标记下拉区域高度改变,在touchend重置回来
+				}
+				if (diff > 0) { // 向下拉
+					me.downHight += diff * me.optDown.outOffsetRate; // 越往下,高度变化越小
+				} else { // 向上收
+					me.downHight += diff; // 向上收回高度,则向上滑多少收多少高度
+				}
+			}
+			
+			me.downHight = Math.round(me.downHight) // 取整
+			var rate = me.downHight / me.optDown.offset; // 下拉区域当前高度与指定距离的比值
+			// me.optDown.onMoving && me.optDown.onMoving(me, rate, me.downHight); // 下拉过程中的回调,一直在执行
+			me.onMoving(ins, rate, me.downHight)
+		}
+	}
+	
+	me.lastPoint = curPoint; // 记录本次移动的点
+	
+	return isPrevent // false表示不往上冒泡,相当于调用了同时调用了stopPropagation和preventDefault (对小程序生效, h5和app无效)
+}
+
+function touchendEvent(e, ins) {
+	// 如果下拉区域高度已改变,则需重置回来
+	if (me.isMoveDown) {
+		if (me.downHight >= me.optDown.offset) {
+			// 符合触发刷新的条件
+			me.downHight = me.optDown.offset; // 更新下拉区域高度
+			// me.triggerDownScroll();
+			me.callMethod(ins, {type: 'triggerDownScroll'})
+		} else {
+			// 不符合的话 则重置
+			me.downHight = 0;
+			// me.optDown.endDownScroll && me.optDown.endDownScroll(me);
+			me.callMethod(ins, {type: 'endDownScroll'})
+		}
+		me.movetype = 0;
+		me.isMoveDown = false;
+	} else if (!me.isScrollBody && me.getScrollTop() === me.startTop) { // scroll-view到顶/左/右/底的滑动事件
+		var isScrollUp = me.getPoint(e).y - me.startPoint.y < 0; // 和起点比,移动的距离,大于0向下拉,小于0向上拉
+		// 上滑
+		if (isScrollUp) {
+			// 需检查滑动的角度
+			var angle = me.getAngle(me.getPoint(e), me.startPoint); // 两点之间的角度,区间 [0,90]
+			if (angle > 80) {
+				// 检查并触发上拉
+				// me.triggerUpScroll(true);
+				me.callMethod(ins, {type: 'triggerUpScroll'})
+			}
+		}
+	}
+	me.callMethod(ins, {type: 'setWxsProp'}) // 同步更新wxsProp的数据 (小程序是异步的,可能touchmove先执行,才到propObserver; h5和app是同步)
+}
+
+/* 是否禁用下拉刷新 */
+me.disabled = function(){
+	return !me.optDown || !me.optDown.use || me.optDown.native
+}
+
+/* 根据点击滑动事件获取第一个手指的坐标 */
+me.getPoint = function(e) {
+	if (!e) {
+		return {x: 0,y: 0}
+	}
+	if (e.touches && e.touches[0]) {
+		return {x: e.touches[0].pageX,y: e.touches[0].pageY}
+	} else if (e.changedTouches && e.changedTouches[0]) {
+		return {x: e.changedTouches[0].pageX,y: e.changedTouches[0].pageY}
+	} else {
+		return {x: e.clientX,y: e.clientY}
+	}
+}
+
+/* 计算两点之间的角度: 区间 [0,90]*/
+me.getAngle = function (p1, p2) {
+	var x = Math.abs(p1.x - p2.x);
+	var y = Math.abs(p1.y - p2.y);
+	var z = Math.sqrt(x * x + y * y);
+	var angle = 0;
+	if (z !== 0) {
+		angle = Math.asin(y / z) / Math.PI * 180;
+	}
+	return angle
+}
+
+/* 获取滚动条的位置 */
+me.getScrollTop = function() {
+	return me.scrollTop || 0
+}
+
+/* 获取body的高度 */
+me.getBodyHeight = function() {
+	return me.bodyHeight || 0;
+}
+
+/* 调用逻辑层的方法 */
+me.callMethod = function(ins, param) {
+	if(ins) ins.callMethod('wxsCall', param)
+}
+
+/* 导出模块 */
+module.exports = {
+	propObserver: propObserver,
+	callObserver: callObserver,
+	touchstartEvent: touchstartEvent,
+	touchmoveEvent: touchmoveEvent,
+	touchendEvent: touchendEvent
+}

+ 35 - 0
main.js

@@ -1,6 +1,7 @@
 import Vue from 'vue'
 import App from './App'
 //商城 begin
+import store from '@/store';
 import Server from './utils/server'
 import Storage from './utils/storage'
 import ApiEx from './utils/api'
@@ -14,6 +15,10 @@ import Filter from './utils/filter'
 import Mpi from './utils/mpi'
 //商城 end
 
+
+let vuexStore = require("@/store/$u.mixin.js");
+Vue.mixin(vuexStore);
+
 //uview
 import uView from 'uview-ui';
 Vue.use(uView);
@@ -22,6 +27,35 @@ Vue.config.productionTip = false
 
 App.mpType = 'app'
 
+import MescrollBody from "@/comps/mescroll-body/mescroll-body.vue"
+Vue.component('mescroll-body', MescrollBody)
+
+//小程序参数
+Vue.prototype.$wxData={
+	APPID:'wxaeb044e4a6b97df4',
+	SECRET:'0c575e3f4ae59ea630bbb90abcc4852c',
+	GRANTTYPE:'client_credential'
+}
+
+//解决ios系统时间显示错误问题
+Vue.prototype.$commonDate=value=>{
+	return new Date(value.replace(/\-/g, '/'))
+}
+//封装小程序审核时的标题设置
+Vue.prototype.$setNavigationBarTitle=(auditTitle,title)=>{
+	let appletType= uni.getStorageSync('appletType')
+	if (appletType==0) {
+		uni.setNavigationBarTitle({
+			title:auditTitle
+		})
+	}else{
+		uni.setNavigationBarTitle({
+			title:title
+		})
+	}
+	return appletType
+}
+
 //封装判空函数
 Vue.prototype.$isEmpty=function(value){
 	switch (typeof value) {
@@ -87,6 +121,7 @@ Vue.prototype.$dialog = Dialog
 
 
 const app = new Vue({
+	store,
     ...App
 })
 app.$mount()

+ 50 - 14
pages.json

@@ -3,6 +3,15 @@
 		"^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue"
 	},
 	"pages": [
+		
+		{
+			"path": "pages/index/index",
+			"style" :
+			{
+			    "enablePullDownRefresh": false,
+				"navigationStyle":"custom"
+			}
+		},
 		{
 			"path" : "pages/guide/guide",
 			"style":                                                                                   
@@ -11,15 +20,6 @@
 				"navigationBarTitleText": "",
 				"enablePullDownRefresh": false
 			}
-			
-		},
-		{
-			"path": "pages/index/index",
-			"style" :
-			{
-			    "enablePullDownRefresh": false,
-				"navigationStyle":"custom"
-			}
 		}
 	    ,{
             "path" : "pages/myhome/myhome",
@@ -92,7 +92,7 @@
             "path" : "pages/wode/myInfo/myInfo",
             "style" :                                                                                    
             {
-                "navigationBarTitleText": "",
+                "navigationBarTitleText": "认证信息",
                 "enablePullDownRefresh": false
             }
             
@@ -142,7 +142,7 @@
 		{
 			"path": "pages/myFamily/activateFace/activateFace",
 			"style": {
-				"navigationBarTitleText": "人脸激活"
+				"navigationBarTitleText": ""
 			}
 		},
 		{
@@ -172,7 +172,7 @@
 		{
 			"path": "pages/choosePlot/householdCert/householdCert",
 			"style": {
-				"navigationBarTitleText": ""
+				"navigationBarTitleText": "用户认证"
 			}
 		},
 		{
@@ -388,7 +388,7 @@
             "path" : "pages/tool-list/epidemic-pass/epidemic-pass",
             "style" :                                                                                    
             {
-                "navigationBarTitleText": "出入信息填写",
+                "navigationBarTitleText": "防疫通行",
                 "enablePullDownRefresh": false
             }
             
@@ -528,6 +528,42 @@
             }
             
         }
+        ,{
+            "path" : "pages/choosePlot/chooseBuilding/chooseBuilding",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "选择楼栋",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+        ,{
+            "path" : "pages/tool-list/epidemic-pass/list",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "登记记录",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+        ,{
+            "path" : "pages/healthCode/healthCode",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "防疫健康码",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+        ,{
+            "path" : "pages/myFamily/audit-detail/audit-detail",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "住户审核",
+                "enablePullDownRefresh": false
+            }
+            
+        }
     ],
 	 "subPackages": [{
 	 	"root": "pagesM/",
@@ -754,7 +790,7 @@
 				    "style" : {
 				        "navigationBarTitleText" : "订单详情",
 				        "navigationBarTextStyle" : "white",
-				        "navigationBarBackgroundColor" : "#E42F2F"
+				        "navigationBarBackgroundColor" : "#2f7ff5"
 				    }
 				},
 				{

+ 73 - 17
pages/auth/auth.vue

@@ -43,11 +43,25 @@
 				</view>
 				<view class="action">
 					<text class="text-grey text-df">
-						{{$isEmpty(data.unit_name)?'请选择楼栋':data.unit_name}}
+						{{$isEmpty(data.building_name)?'请选择楼栋':data.building_name}}
 					</text>
 				</view>
 			</view>
+			
 			<view @click="jump(3)" class="cu-item arrow" >
+				<view class="content">
+					<image style="width: 36rpx; height: 36rpx;margin: 0 24rpx 10rpx 10rpx;" 
+					src="/static/common/unit.png" class="png" mode="aspectFit"></image>
+					<text class="text-black text-bold">单元</text>
+				</view>
+				<view class="action">
+					<text class="text-grey text-df">
+						{{$isEmpty(data.unit_name)?'请选择楼栋':data.unit_name}}
+					</text>
+				</view>
+			</view>
+			
+			<view @click="jump(4)" class="cu-item arrow" >
 				<view class="content">
 					<image style="width: 50rpx; height: 50rpx;margin: 0 20rpx 10rpx 0;" 
 					src="/static/common/fangjian.png" class="png" mode="aspectFit"></image>
@@ -74,13 +88,7 @@
 		data() {
 			return {
 				totalStep:3,
-				numList: [{
-					name: '注册账号'
-				}, {
-					name: '选择小区'
-				}, {
-					name: '填写信息'
-				}],
+				
 				//小区id
 				residential_id:'',
 				//楼栋id
@@ -89,6 +97,10 @@
 					//小区
 					residential_name:"",
 					//楼栋
+					building_name:'',
+					//楼栋id
+					building_id:'',
+					//单元
 					unit_name:"",
 					//房间名
 					room_name:"",
@@ -115,6 +127,8 @@
 				this.data.room_id=options.room_id
 				this.data.room_name=options.room_name
 				this.data.residential_name=options.residential_name
+				this.data.building_name=options.building_name
+				this.data.building_id=options.building_id
 				this.data.unit_name=options.unit_name
 			}
 		},
@@ -123,8 +137,13 @@
 				let that=this
 				if(type==0){
 					//选择城市
+					let params={
+						city:app.globalData.city,
+						county:app.globalData.county,
+						currentCityCode:app.globalData.currentCityCode
+					}
 					uni.navigateTo({
-						url:"../choosePlot/choosePlot?city="+app.globalData.city+"&county="+app.globalData.county+"&currentCityCode="+app.globalData.currentCityCode
+						url:"../choosePlot/choosePlot"+this.$u.queryParams(params)
 					})
 					return
 				}
@@ -138,8 +157,13 @@
 				}
 				if(type==1){
 					//选择小区
+					let params={
+						city:app.globalData.city,
+						county:app.globalData.county,
+						currentCityCode:app.globalData.currentCityCode
+					}
 					uni.navigateTo({
-						url:"../choosePlot/choosePlot?city="+app.globalData.city+"&county="+app.globalData.county+"&currentCityCode="+app.globalData.currentCityCode
+						url:"../choosePlot/choosePlot"+this.$u.queryParams(params)
 					})
 					return
 				}
@@ -153,25 +177,48 @@
 				}
 				if(type==2){
 					//选择楼栋
+					let params={
+						residential_id:this.residential_id,
+						residential_name:this.data.residential_name
+					}
 					uni.navigateTo({
-						url: '/pages/choosePlot/chooseUnit/chooseUnit?residential_id=' + this.residential_id + '&residential_name=' + this.data.residential_name,
+						url:"../choosePlot/chooseBuilding/chooseBuilding"+this.$u.queryParams(params)
 					})
 					return
 				}
+				
 				//未选择楼栋
-				if(this.$isEmpty(this.data.unit_name)){
+				if(this.$isEmpty(this.data.building_name)){
 					uni.showToast({
 						title:"请选择楼栋",
 						icon:"none"
 					})
 					return
 				}
-				if(type==3){
-					let url="/pages/choosePlot/chooseRoom/chooseRoom?unit_id=" + this.unit_id + "&unit_name=" + this.data.unit_name + "&residential_name=" + this.data.residential_name
-					console.log(url)
+				
+				if (type==3) {
+					//选择单元
+					let params={
+						residential_name:this.data.residential_name,
+						building_id:this.data.building_id,
+						building_name:this.data.building_name
+					}
+					uni.navigateTo({
+						url:"../choosePlot/chooseUnit/chooseUnit"+this.$u.queryParams(params)
+					})
+				}
+				
+				if(type==4){
 					//选择房间
+					let params={
+						residential_name:this.data.residential_name,
+						building_name:this.data.building_name,
+						building_id:this.data.building_id,
+						unit_name:this.data.unit_name,
+						unit_id:this.unit_id
+					}
 					uni.navigateTo({
-						url:url
+						url:"/pages/choosePlot/chooseRoom/chooseRoom"+this.$u.queryParams(params)
 					})
 				}
 			},
@@ -191,13 +238,22 @@
 					return
 				}
 				
-				if(this.$isEmpty(this.data.unit_name)){
+				if(this.$isEmpty(this.data.building_name)){
 					uni.showToast({
 						title:"请选择楼栋",
 						icon:"none"
 					})
 					return
 				}
+				
+				if(this.$isEmpty(this.data.unit_name)){
+					uni.showToast({
+						title:"请选择单元",
+						icon:"none"
+					})
+					return
+				}
+				
 				if(this.$isEmpty(this.data.room_id)||this.$isEmpty(this.data.room_name)){
 					uni.showToast({
 						title:"请选择门牌号",

+ 163 - 164
pages/authorize_record/authorize_record.vue

@@ -1,6 +1,17 @@
 <template>
 <view :class="$isEmpty(list)?'empty-wrap':''">
-<view class="bg-white padding-20 flex justify-between" style="box-sizing: border-box;">
+<u-popup v-model="codeModelShow" mode="center"  width ="70%">
+	<view class="padding-bottom-50">
+		<view class="text-center text-df text-gray padding-50">
+			长按发送给好友
+		</view>
+		<view class="flex justify-center align-center">
+			<image :show-menu-by-longpress="true" :src="codeImg" style="width: 400rpx;height: 400rpx;" ></image>
+		</view>
+	</view>
+</u-popup>	
+
+<view class="bg-white padding-20 flex justify-between " style="box-sizing: border-box;position: fixed;top: 0;z-index: 999;">
 	<view class="text-sm text-gray padding-top-10">
 		<text>只显示最近一个月内的授权记录</text>
 	</view>
@@ -9,30 +20,44 @@
 		访客记录
 	</navigator>
 </view>
-<view class="container" v-if="list.length>0">
+<view style="height:88rpx;"></view>
+
+<view class="container " v-if="list.length>0">
   <view class="record_content">
 	   <view class="data" v-for="(item, index) in list" :key="index"  style="border-bottom: 1rpx solid #b6b6b6;">
 	   	<view class="top">
 	   		<view class="left">
-	   			<u-icon name="account" :size="30" color="rgb(94,94,94)"></u-icon>
-				<view class="padding-left-sm" v-if="item.guestType==0">访客授权: 朋友</view>
-				<view class="padding-left-sm" v-if="item.guestType==1">访客授权: 外卖</view>
-				<view class="padding-left-sm" v-if="item.guestType==2">访客授权: 快递</view>
-				<view class="padding-left-sm" v-if="item.guestType==3">访客授权: 其他</view>
+	   			<u-icon name="map-fill" :size="30" color="rgb(94,94,94)"></u-icon>
+				<view class="padding-left-sm" >
+					授权位置: {{item.residentialName}} {{item.unitName}} {{item.roomName}}
+				</view>
 	   		</view>
 	   	</view>
 	   	<view class="item">
 	   		<view class="left">
 	   			<view class="content" >
-	   				<view >授权时间:{{item.beginDate}}</view>
-	   				<view >失效时间:{{item.endDate}}</view>
+					<view class="">
+						<u-icon name="account" :size="30" color="rgb(94,94,94)"></u-icon>
+						<text class="padding-left-sm" v-if="item.guestType==0">访客授权: 朋友</text>
+						<text class="padding-left-sm" v-if="item.guestType==1">访客授权: 外卖</text>
+						<text class="padding-left-sm" v-if="item.guestType==2">访客授权: 快递</text>
+						<text class="padding-left-sm" v-if="item.guestType==3">访客授权: 其他</text>
+					</view>
+					<view class="">
+						<u-icon name="hourglass" :size="30" color="rgb(94,94,94)"></u-icon>
+						<text class="padding-left-sm">授权时间:{{item.beginDate}}</text>
+					</view>
+					<view class="">
+						<u-icon name="clock" :size="30" color="rgb(94,94,94)"></u-icon>
+						<text class="padding-left-sm">失效时间:{{item.endDate}}</text>
+					</view>
 	   			</view>
 	   		</view>
 	   	</view>
 	   	<view class="bottom" >
-	   		<view  class="cu-btn line-btn sm round margin-right-sm" @tap.stop="showModalFun" :data-password="item.password" :data-begin_date="item. beginDate" :data-end_date="item.endDate" :data-valid_count="item.validCount">
-	   			查看密码
-	   		</view>
+	   		<button @click="shareData=item;shareShow=true;" class="cu-btn line-btn sm round margin-right-sm"  >
+	   			分享
+	   		</button>
 	   		<view @tap.stop="backout" :data-id="item.id" class="cu-btn bg-btn sm round">
 	   			撤销
 	   		</view>
@@ -40,33 +65,33 @@
 	   </view>
   </view>
 </view>
-<view v-show="!showModal" @tap="addOpenPassword" class=" footer-fixed" >
+<view v-show="!showModal" @tap="addOpenPassword" class=" footer-fixed" style="z-index: 99;">
 	<view class="cu-btn  flex  text-lg bg-red-btn" style="padding: 46rpx 0;">
-		申请密码
+		授权开门
 	</view>
 </view>
-<!--弹窗-->
-<view class="modal-mask" @tap="closeModal" catchtouchmove="preventTouchMove" v-if="showModal"></view>
-<!--  -->
-<view class="modal-dialog" v-if="showModal">
-  <view class="modal-title">开门密码</view>
-    <view class="modal-content">
-      <view class="modal-input">
-        <text class="password">{{password}}</text>
-      </view>
-    </view>
-    <view class="modal-footer">
-      <button class="btn-cancel" open-type="share" data-status="cancel">转发</button>
-      <button class="btn-confirm" @tap="copy" data-status="confirm">复制</button>
-    </view>
-</view>
-
 <view class="default"  v-if="$isEmpty(list)">
   <image src="/static/common/empty.png" mode="heightFix"></image>
   <view>
     <text>没有获取到相关记录</text>
   </view>
 </view>
+<u-popup v-model="shareShow" mode="bottom" height="auto" >
+	<view class="flex flex-direction justify-between">
+		<view class="">
+			<button open-type="share" @click="shareShow=false" class="cu-btn flex bg-white " style="border-radius: 0;width: 100%;padding: 50rpx;border-bottom: 1rpx solid #ebebeb;">
+				分享给好友
+			</button>
+			<button @click="createQrcode" class="cu-btn flex bg-white " style="border-radius: 0;padding: 50rpx;border-bottom: 1rpx solid #ebebeb;">
+				生成二维码
+			</button>
+		</view>
+		<button class="cu-btn flex bg-white " style="padding: 55rpx;">
+			取消
+		</button>
+	</view>
+</u-popup>
+<!-- <u-action-sheet :list="shareList" v-model="shareShow"></u-action-sheet> -->
 </view>
 </template>
 
@@ -78,13 +103,23 @@ var app = getApp();
 export default {
   data() {
     return {
+	  codeModelShow:false,
+	  codeImg:'',
+	  
+	  accessToken:'',
+	  shareData:{},
+	  shareShow:false,
+	  shareList:[
+		  {
+			  text:'分享给好友',
+		  },
+		  {
+			  text:'生成二维码'
+		  }
+	  ],
+	  
+	  doorNeedAudit:0,
       list: null,
-      //密码记录
-      showModal: false,
-      password: "",
-      begin_date: "",
-      end_date: "",
-      valid_count: ""
     };
   },
   components: {},
@@ -94,7 +129,8 @@ export default {
    * 生命周期函数--监听页面加载
    */
   onLoad: function (options) {
-    this.getRecord();
+	  this.doorNeedAudit=uni.getStorageSync("doorNeedAudit")
+      this.getRecord();
   },
 
   /**
@@ -103,7 +139,6 @@ export default {
   onShow: function () {
     //回退的时候刷新
     let isFlush = uni.getStorageSync("isFlush");
-
     if (isFlush) {
       this.getRecord();
       uni.setStorageSync("isFlush", false);
@@ -111,54 +146,62 @@ export default {
   },
   //转发
   onShareAppMessage: function (ops) {
-    let title = "访客密码:" + this.password + ",有效次数:" + this.valid_count + "次,有效期" + this.begin_date + " 到 " + this.end_date;
-    return {
-      title: title,
-      path: '/pages/myPassword/myPassword?valid_count=' + this.valid_count + "&password=" + this.password + "&end_date=" + this.end_date,
-      imageUrl: "http://139.9.103.171:1888/img/image/ps_bg.png"
-    };
+	  let title ="访问房间:"+this.shareData.roomName+ "; 有效期: " + this.shareData.beginDate + " 到 " + this.shareData.endDate
+	  let path="/pages/guest/guest_form?id="+this.shareData.id+"&doorNeedAudit="+this.doorNeedAudit+"&memberId="+app.globalData.member.id
+	  this.shareShow=false
+	  return {
+		title: title,
+		path:path,
+		imageUrl: "http://139.9.103.171:1888/img/image/ps_bg.png"
+	  };
   },
   methods: {
-    //查看密码
-    showModalFun: function (event) {
-      this.setData({
-        showModal: true,
-        password: event.currentTarget.dataset.password,
-        begin_date: event.currentTarget.dataset.begin_date,
-        //获取记录的时候已经转换了一次
-        end_date: event.currentTarget.dataset.end_date,
-        valid_count: event.currentTarget.dataset.valid_count
-      });
-    },
-    //关闭弹窗
-    closeModal: function () {
-      this.setData({
-        showModal: false
-      });
-    },
-    //复制密码
-    copy: function (e) {
-      var that = this; //获取app.js里面定义的全局变量
-
-      if (uni.setClipboardData) {
-        //微信版本兼容处理
-        let title = "访客密码:" + this.password + ",有效次数:" + this.valid_count + "次,有效期" + this.begin_date + " 到 " + this.end_date;
-        uni.setClipboardData({
-          data: title,
-
-          success(res) {
-            uni.getClipboardData({
-              success(res) {
-				  that.closeModal()
-			  }
-            });
-          }
-
-        });
-      } else {//用户微信版本过低,不支持使用该功能
-      }
-    },
-
+	  /**
+	   * 生成二维码
+	   */
+	createQrcode(){
+		this.shareShow=false
+		this.getAccessToken()
+	},
+	/**
+	 * 获取accessToken
+	 */
+	getAccessToken(){
+		let that=this
+		let operation='miniprogram/getAccessToken'
+		let params={
+			appId:this.$wxData.APPID,
+			secret:this.$wxData.SECRET,
+			grantType:this.$wxData.GRANTTYPE
+		}
+		getApp().globalData.postRequest(params,operation,function(res){
+			that.getGenerateCode(res.data.access_token)
+		})
+	},
+	/**
+	 * 获取微信小程序码
+	 */
+	getGenerateCode(accessToken){
+		uni.showLoading({
+			title:"二维码生成中.."
+		})
+		let that=this
+		let params={
+			access_token:accessToken,
+			//详情id+手机号
+			scene:this.shareData.id+","+this.doorNeedAudit+","+app.globalData.member.id,
+			page:'pages/guest/guest_form',
+			width:80
+		}
+		let operation="miniprogram/generateCode"
+		setTimeout(()=>{
+			getApp().globalData.postRequest(params,operation,(res)=>{
+				that.codeImg=res.data
+				uni.hideLoading()
+				that.codeModelShow=true
+			})
+		},1000)
+	},
     /**新增 */
     addOpenPassword: function () {
       uni.navigateTo({
@@ -341,86 +384,42 @@ page{
 	min-height: 100vh;
 }
 
-/* 查看密码弹窗 */
-.modal-mask {
-  width: 100%;
-  height: 100%;
-  position: fixed;
-  top: 0;
-  left: 0;
-  background: #000;
-  opacity: 0.5;
-  overflow: hidden;
-  z-index: 9000;
-  color: #fff;
-}
-.modal-dialog {
-  width: 540rpx;
-  overflow: hidden;
-  position: fixed;
-  top: 50%;
-  left: 0;
-  z-index: 9999;
-  background: #f9f9f9;
-  margin: -180rpx 105rpx;
-  border-radius: 36rpx;
-}
-
-.modal-title {
-  padding-top: 50rpx;
-  font-size: 36rpx;
-  color: #030303;
-  text-align: center;
-}
-
-.modal-content {
-  padding: 50rpx 32rpx;
-}
-
-.modal-input {
-  display: flex;
-  font-size: 40rpx;
-}
-
-.password {
-  width: 100%;
-  height: 80rpx;
-  font-size: 40rpx;
-  line-height: 80rpx;
-  padding: 0 20rpx;
-  box-sizing: border-box;
-  color: #ec5300;
-  text-align: center;
-}
-
-input-holder {
-  color: #666;
-  font-size: 28rpx;
-}
-
-.modal-footer {
-  display: flex;
-  flex-direction: row;
-  height: 86rpx;
-  border-top: 1px solid #dedede;
-  font-size: 34rpx;
-  line-height: 86rpx;
-}
-.modal-footer button::after{
-   border: none;
-  
-}
-.modal-footer .btn-cancel {
-  width: 50%;
-  color: #666;
-  text-align: center;
-  border-right: 1px solid #dedede;
- border-radius: 0;
+//分享
+.drawer_screen {
+	width: 100%;
+	height: 100%;
+	position: fixed;
+	top: 0;
+	left: 0;
+	z-index: 1000;
+	background: #000;
+	opacity: 0.2;
+	overflow: hidden;
 }
-
-.modal-footer .btn-confirm {
-  width: 50%;
-  color: #ec5300;
-  text-align: center;
+.drawer_attr_box {
+	width: 100%;
+	overflow: hidden;
+	position: fixed;
+	bottom: 0;
+	left: 0;
+	z-index: 1001;
+	background: rgb(242, 242, 242);
+	.drawer_content {
+		overflow-y: scroll;
+		.btn {
+			background: #fff;
+			font-size: 30upx;
+			color: rgb(51, 51, 51);
+			border-bottom: 1px solid #e8e8e8;
+			border-radius: 0;
+			padding: 12upx 0;
+		}
+		.btn::after {
+			border: none;
+		}
+		.detail-cancel-btn {
+			margin-top: 10upx;
+		}
+	}
 }
 </style>

+ 56 - 126
pages/authorize_record/openPass/openPass.vue

@@ -24,9 +24,8 @@
 
   </view>
   <view class="form_group" >
-
     <view class="tui-picker-content">
-      <text class="type">密码有效时间:</text>
+      <text class="type">授权有效时间:</text>
       <view class="flex between itemBox">
         <view v-for="(item, index) in numArray" :key="index" :class="activeIndex == index ? 'active':''" @tap="activethis" :data-thisindex="index">
           <text>{{item}}小时</text>
@@ -34,44 +33,33 @@
       </view>
 
     </view>
-
-  </view>
-  <view class="form_group">
-
-    <text class="type">有效次数:</text>
-    <view class="stepper">
-      <text :class="minusStatus" type="number" @tap="bindMinus">-</text>
-      <input @input="bindManual" :value="valid_count"></input>
-      <text @tap="bindPlus">+</text>
-    </view>
-
   </view>
 <!-- <view class="submit_btn">
  <button class="ar_btn" @tap="getGuestAuthorize">获取开门密码</button>
 </view> -->
-<view @tap="getGuestAuthorize" class=" footer-fixed" >
+<view @tap="getGuestAuthorize" class=" footer-fixed" style="z-index: 99;">
 	<view class="cu-btn  flex  text-lg bg-red-btn" style="padding: 46rpx 0;">
-		获取开门密码
+		确认授权
 	</view>
 </view>
-
 </view>
+
+
 <!--弹窗-->
 <view class="modal-mask" @tap="closeModal" catchtouchmove="preventTouchMove" v-if="showModal"></view>
-<!--  -->
 <view class="modal-dialog" v-if="showModal">
-  <view class="modal-title">开门密码</view>
+  <view class="modal-title">提示</view>
     <view class="modal-content">
       <view class="modal-input">
-        <text class="password">{{password}}</text>
+        <text class="password">授权成功,请转发给好友填写表单</text>
       </view>
     </view>
     <view class="modal-footer">
-      <button class="btn-cancel" open-type="share" data-status="cancel">转发</button>
-      <button class="btn-confirm" @tap="copy" data-status="confirm">复制</button>
+      <button class="btn-confirm" @click="showModal=false" data-status="confirm">暂不转发</button>
+	  <button class="btn-cancel" open-type="share" data-status="cancel">立即转发</button>
     </view>
 </view>
-<u-select z-index="9999999"  mode="single-column"  value-name="id" label-name="name" v-model="roomSelectShow" :list="room_list" @confirm="roomChange"></u-select>
+<u-select z-index="999"  mode="single-column"  value-name="id" label-name="name" v-model="roomSelectShow" :list="room_list" @confirm="roomChange"></u-select>
 </view>
 </template>
 
@@ -84,18 +72,20 @@ var util = require("../../../utils/util.js");
 export default {
   data() {
     return {
+	  //是否需要审核通过访客表单后才能开门
+	  doorNeedAudit:0,
+		
 	  roomSelectShow:false,
 	  selectRoomName:'',
 	  selectRoomId:0,
+	
+	//授权记录 的id
+	  id:'',
 		
       room_list: null,
-      //有效次数
-      valid_count: 1,
       minusStatus: 'disable',
       //获取开门密码
       showModal: false,
-      //开门密码
-      password: null,
       //访客类型
       guestTypeIndex: 0,
       //默认选中第一个
@@ -116,27 +106,37 @@ export default {
    * 监听页面加载
    */
   onLoad() {
+	this.doorNeedAudit=uni.getStorageSync("doorNeedAudit")
     //禁用头部分享
     uni.hideShareMenu({});
     let room_list = app.globalData.room_list;
-	console.log(room_list,"**************");
-    if (room_list) {
-	  this.selectRoomId=room_list[0].id
-		
-      this.setData({
-        room_list: room_list
-      });
+    if (this.$isEmpty(room_list)) {
+		//获取房屋信息
+		this.geRoomByMemberId();
     } else {
-      //获取房屋信息
-      this.geRoomByMemberId();
+		//当前选择的小区
+		let residentialId=uni.getStorageSync("residentialId")
+		let room_list_new=[]
+		room_list.forEach(item=>{
+			if (item.residentialId==residentialId) {
+				room_list_new.push(item)
+			}
+		})
+		this.room_list=room_list_new
+		this.selectRoomId=room_list[0].id
     }
-  },
+ },
 
   onShareAppMessage: function (ops) {
-    let title = "访客密码:" + this.password + ",有效次数:" + this.valid_count + "次,有效期" + this.begin_date + " 到 " + this.end_date;
+	  
+	 this.showModal=false
+		
+	let roomName=this.selectRoomName?this.selectRoomName:this.room_list[0].name
+    let title ="访问房间:"+roomName+ "; 有效期" + this.begin_date + " 到 " + this.end_date;
+	// console.log("id:"+this.id+";doorNeedAudit="+this.doorNeedAudit+";memberId="+app.globalData.member.id);
     return {
       title: title,
-      path: '/pages/myPassword/myPassword?valid_count=' + this.valid_count + "&password=" + this.password + "&end_date=" + this.end_date,
+      path: "/pages/guest/guest_form?id="+this.id+"&doorNeedAudit="+this.doorNeedAudit+"&memberId="+app.globalData.member.id,
       imageUrl: "http://139.9.103.171:1888/img/image/ps_bg.png"
     };
   },
@@ -146,52 +146,6 @@ export default {
 		this.selectRoomId=e[0].value
 		this.selectRoomName=e[0].label
     },
-    //事件处理函数
-
-    /*点击减号*/
-    bindMinus: function () {
-      var valid_count = this.valid_count;
-
-      if (valid_count > 1) {
-        valid_count--;
-      }
-
-      var minusStatus = valid_count > 1 ? 'normal' : 'disable';
-      this.setData({
-        valid_count: valid_count,
-        minusStatus: minusStatus
-      });
-    },
-
-    /*点击加号*/
-    bindPlus: function () {
-      var valid_count = this.valid_count;
-
-      if (valid_count >= 10) {
-        uni.showToast({
-          title: '密码最大次数不能超过10次',
-          icon: 'none',
-          duration: 2000
-        });
-      } else {
-        valid_count++;
-        var minusStatus = valid_count > 1 ? 'normal' : 'disable';
-        this.setData({
-          valid_count: valid_count,
-          minusStatus: minusStatus
-        });
-      }
-    },
-
-    /*输入框事件*/
-    bindManual: function (e) {
-      var valid_count = e.detail.value;
-      var minusStatus = valid_count > 1 ? 'normal' : 'disable';
-      this.setData({
-        valid_count: valid_count,
-        minusStatus: minusStatus
-      });
-    },
     //访客类型
     guestTypethis: function (event) {
       //点击选中事件
@@ -210,29 +164,6 @@ export default {
         activeIndex: thisindex
       });
     },
-    //复制密码
-    copy: function (e) {
-      var that = this; //获取app.js里面定义的全局变量
-
-      if (uni.setClipboardData) {
-        //微信版本兼容处理
-        let title = "访客密码:" + this.password + ",有效次数:" + this.valid_count + "次,有效期" + this.begin_date + " 到 " + this.end_date;
-        uni.setClipboardData({
-          data: title,
-
-          success(res) {
-            uni.getClipboardData({
-              success(res) {
-				  that.closeModal()
-			  }
-
-            });
-          }
-
-        });
-      } else {//用户微信版本过低,不支持使用该功能
-      }
-    },
     //关闭弹窗
     closeModal: function () {
       this.setData({
@@ -246,13 +177,12 @@ export default {
       params['member_id'] = app.globalData.member.id;
       params['room_id'] = that.selectRoomId;
       params['guest_type'] = that.guestTypeIndex;
-      params['valid_count'] = that.valid_count; //选择有效时间数字
 
       let avalid_num = that.numArray[that.activeIndex]; //有效开始时间
 
-      let begin_date = new Date(); //提前30分钟
+      let begin_date = new Date();
 
-      begin_date.setMinutes(begin_date.getMinutes() - 30);
+      // begin_date.setMinutes(begin_date.getMinutes() - 30);
       params['begin_date'] = util.getTimestamp(begin_date); //有效结束时间
 
       let end_date = new Date(); //小时累加
@@ -260,7 +190,6 @@ export default {
       end_date.setHours(end_date.getHours() + avalid_num);
       params['end_date'] = util.getTimestamp(end_date); //有效次数
 
-      params['valid_count'] = that.valid_count;
 	  console.log(that.params);
       let operation = 'guestAuthorize/getGuestAuthorize';
       app.globalData.postRequest(params, operation, function (res) {
@@ -271,7 +200,7 @@ export default {
           that.setData({
             //显示复制密码弹窗
             showModal: true,
-            password: res.data.guestAuthorize.password,
+            id: res.data.guestAuthorize.id,
             begin_date: util.formatTime(res.data.guestAuthorize.beginDate),
             end_date: util.formatTime(res.data.guestAuthorize.endDate)
           });
@@ -285,15 +214,18 @@ export default {
       let that = this;
       let params = {};
       params['member_id'] = app.globalData.member.id;
-      ;
       let operation = 'estate/getRoomByMemberId';
       app.globalData.postRequest(params, operation, function (res) {
         console.info("获取成功" + res.data.result_msg); //获取成功
-
         if (res.data.result_code == 1) {
-          that.setData({
-            room_list: res.data.list
-          });
+			let residentialId=uni.getStorageSync("residentialId")
+			let room_list_new=[]
+			res.data.list.forEach(item=>{
+				if (item.residentialId==residentialId) {
+					room_list_new.push(item)
+				}
+			})
+           that.room_list=room_list_new
 		  that.selectRoomId=that.room_list[0].id
           app.globalData.room_list = res.data.list;
         }
@@ -303,8 +235,6 @@ export default {
 };
 </script>
 <style lang="scss">
-/* pages/openPass/openPass.wxss */
-
 .edit_wrap {
   font-size: 30rpx;
   color: #333;
@@ -430,7 +360,7 @@ export default {
   width: 540rpx;
   overflow: hidden;
   position: fixed;
-  top: 50%;
+  top: 45%;
   left: 0;
   z-index: 9999;
   background: #f9f9f9;
@@ -446,22 +376,22 @@ export default {
 }
 
 .modal-content {
-  padding: 50rpx 32rpx;
+  padding: 60rpx 0;
 }
 
 .modal-input {
   display: flex;
-  font-size: 40rpx;
+  font-size: 30rpx;
 }
 
 .password {
   width: 100%;
   height: 80rpx;
-  font-size: 40rpx;
+  font-size: 30rpx;
   line-height: 80rpx;
   padding: 0 20rpx;
   box-sizing: border-box;
-  color: #ec5300;
+  color: #606266;
   text-align: center;
 }
 
@@ -484,7 +414,7 @@ input-holder {
 }
 .modal-footer .btn-cancel {
   width: 50%;
-  color: #666;
+  color: #2a7fff;
   text-align: center;
   border-right: 1px solid #dedede;
  border-radius: 0;
@@ -492,7 +422,7 @@ input-holder {
 
 .modal-footer .btn-confirm {
   width: 50%;
-  color: #ec5300;
+  color: #666;
   text-align: center;
 }
 

+ 160 - 0
pages/choosePlot/chooseBuilding/chooseBuilding.vue

@@ -0,0 +1,160 @@
+<template>
+<view :class="$isEmpty(buiding_list)?'empty-wrap':''">
+	<view class="bg-gray" style="padding: 16rpx 30rpx;">
+		<text >当前选择小区:</text>
+	</view>
+	<view class="bg-white" style="padding:30rpx 30rpx 20rpx 30rpx;border-bottom: 1rpx solid #efefef;display: flex;justify-content: space-between;">
+		<view class="text-blue">
+			<text class="">{{residential_name}}</text>
+		</view>
+		<view class="cu-btn line-blue sm round" @tap="change">
+			<text class="cuIcon-refresh padding-right-10"></text>
+			<text>切换小区</text>
+		</view>
+	</view>
+	<view class="bg-gray" style="padding: 12rpx 30rpx;">
+		<text >选择楼栋:</text>
+	</view>
+	<u-cell-group v-if="!$isEmpty(buiding_list)">
+		<u-cell-item  @click="jump(item)"  v-for="(item, index) in buiding_list" :key="index"  :title="item.name" :arrow="false"></u-cell-item>
+	</u-cell-group>
+	<view class="default" v-if="$isEmpty(buiding_list)&&!loading">
+	  <image src="/static/common/empty.png" mode="heightFix"></image>
+	  <view>
+		<text >没有获取到楼栋信息</text>
+	  </view>
+	</view>
+	<u-back-top :scroll-top="scrollTop"></u-back-top>
+</view>
+</template>
+
+<script>
+var app = getApp();
+
+export default {
+  data() {
+    return {
+	  loading:true,
+	  scrollTop:0,
+		
+      buiding_list: null,
+      //小区集合
+      residential_name: null //小区名字
+
+    };
+  },
+	onPageScroll(e) {
+		this.scrollTop = e.scrollTop;
+	},
+  /**
+   * 生命周期函数--监听页面加载
+   */
+  onLoad: function (options) {
+    //小区名字
+    this.residential_name = options.residential_name
+    var residential_id = options.residential_id 
+	this.getBuilding(residential_id)
+  },
+  methods: {
+	  change(){
+		uni.navigateBack({
+			delta:1
+		})  
+	  },
+	  jump(item){
+		  app.globalData.building_id=item.id
+		  let params={
+			  building_name:item.name,
+			  building_id:item.id,
+			  residential_name:this.residential_name
+		  }
+		  uni.navigateTo({
+		  	url:"../chooseUnit/chooseUnit"+this.$u.queryParams(params)
+		  })
+	  },
+    //根据小区id获取楼栋信息
+    getBuilding: function (residential_id) {
+		uni.showLoading({
+			title:"数据加载中.."
+		})
+      let that = this;
+      let params = {
+		  residential_id:residential_id
+      };
+      let operation = 'estate/getBuildingsByResidentialId';
+      app.globalData.postRequest(params, operation, function (res) {
+        //获取成功
+        if (res.data.result_code == 1) {
+          that.setData({
+            buiding_list: res.data.list
+          });
+        } else {
+          app.globalData.oneFailHint(res.data.result_msg);
+        }
+		uni.hideLoading()
+		that.loading=false
+      });
+    }
+  }
+};
+</script>
+<style>
+page{
+  overflow-y: scroll
+}
+
+.isOver {
+	width: 100%;
+	height: 50px;
+	line-height: 50px;
+	text-align: center;
+	// background: #fff;
+	font-size: 28rpx;
+}
+	
+.nav_section {
+  width: 100%;
+  background:#fff;
+
+}
+
+.nav_section_items {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  padding: 30rpx;
+  border-bottom: 2rpx solid #ddd;
+  position: relative;
+}
+
+.nav_section_items:active {
+  background: #ddd;
+}
+
+
+
+.nav_section_items .section_cont view {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  display: block;
+}
+.nav_section_items .section_cont .section_cont_sub {
+  font-size: 30rpx;
+  line-height: 50rpx;
+  color: #000;
+  margin-bottom: 10rpx;
+}
+.section_cont_tel .info{
+  width: 500rpx;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  display: inline-block;
+}
+.default {  text-align: center;  position: fixed;  left: 50%;  top: 40%;  transform: translate(-50%, -50%);}
+.default text{
+	color: #AAAAAA;
+}
+.default image {  height: 250rpx;  display: inline-block;}.empty-wrap{	background-color: #FFFFFF;	min-height: 100vh;}
+</style>

+ 51 - 54
pages/choosePlot/choosePlot.vue

@@ -1,6 +1,6 @@
 <template>
 <view>
-	<view class="cu-bar bg-white search " >
+	<view class="cu-bar bg-white search search " >
 		<view class="search-form round">
 			<text class="cuIcon-search"></text>
 			<input @input="nameInputSearch"  placeholder="输入小区名称" placeholder-style="font-size: 28rpx"></input>
@@ -10,12 +10,12 @@
 	<view class="bg-gray" style="padding: 12rpx 30rpx;">
 		<text >当前选择城市:</text>
 	</view>
-	<view  style="padding:30rpx 30rpx 20rpx 30rpx;border-bottom: 1rpx solid #efefef;display: flex;justify-content: space-between;">
-		<view class="text-blue">
+	<view class="cf city" 	 >
+		<view class="text-blue fl">
 			<text class="cuIcon-location padding-right-10"></text>
 			<text class="">{{city}}{{county}}</text>
 		</view>
-		<view class="cu-btn line-blue sm round" @tap="switchCity">
+		<view class="cu-btn line-blue sm round fr" @tap="switchCity">
 			<text class="cuIcon-refresh padding-right-10"></text>
 			<text>切换城市</text>
 		</view>
@@ -23,23 +23,17 @@
 	<view class="bg-gray" style="padding: 12rpx 30rpx;">
 		<text >选择小区:</text>
 	</view>
-<view class="nav_section" v-if="residential_list.length>0">
-  <view v-for="(item, index) in residential_list" :key="index" @tap="jump" :data-id="item.id" :data-name="item.name">
-    <view class="nav_section_items">
-      <view class="section_cont">
-        <view class="section_cont_tel">
-          <text class="info">{{item.name}}</text>
-        </view>
-      </view>
-    </view>
-  </view>
-</view>
-<view class="default" v-if="residential_list==null || residential_list.length==0">
-  <image src="http://139.9.103.171:1888/img/image/default_icon.png"></image>
-  <view>
-    <text>没有获取到小区信息</text>
-  </view>
-</view>
+	<u-cell-group v-if="!$isEmpty(residential_list)">
+		<u-cell-item  @click="jump(item)"  v-for="(item, index) in residential_list" :key="index"  :title="item.name" :arrow="false"></u-cell-item>
+	</u-cell-group>
+	<u-divider bg-color="#ffffff" v-if="residential_list.length>=10" height="80">没有更多了</u-divider>
+	<view class="default" v-if="$isEmpty(residential_list)&&!loading">
+	  <image src="http://139.9.103.171:1888/miniofile/xlyq/empty/empty.png"></image>
+	  <view>
+		<text>没有获取到小区信息</text>
+	  </view>
+	</view>
+	<u-back-top :scroll-top="scrollTop"></u-back-top>
 </view>
 </template>
 
@@ -60,13 +54,14 @@ export default {
       //选择的当前城市所在的区编号,
       residential_list: null,
       //小区数据列表
-      sign: false
+      sign: false,
+	  loading:true,
+	  scrollTop:0,
     };
   },
-
-  components: {},
-  props: {},
-
+   onPageScroll(e) {
+		this.scrollTop = e.scrollTop;
+   },
   /**
    * 生命周期函数--监听页面加载
    */
@@ -95,14 +90,17 @@ export default {
     }
   },
   onShow() {
-  	
+  	if (this.canReset) {
+  		this.getCommunity()
+  	}
+	this.canReset=true
   },
   methods: {
-    jump(e) {
+    jump(item) {
 	  let that=this
-      let id = e.currentTarget.dataset.id;
+      let id = item.id;
 	  app.globalData.residentialId=id
-      let name = e.currentTarget.dataset.name;
+      let name = item.name;
 
       if (this.sign) {
         //清空全局list
@@ -112,21 +110,17 @@ export default {
         uni.navigateTo({
           url: '/pages/index/index?residential_id=' + id + '&residential_name=' + name
         });
-      } else {
-		 console.log("1111")
+		
+      }else {
+		  let params={
+			  residential_name:name,
+			  residential_id:id
+		  }
         uni.navigateTo({
-          url: '/pages/choosePlot/chooseUnit/chooseUnit?residential_id=' + id + '&residential_name=' + name,
-          success: function (res) {
-			  
-		  },
-          fail: function (res) {
-			  console.log(res)
-		  },
-          complete: function (res) {}
-        });
+        	url:"./chooseBuilding/chooseBuilding"+this.$u.queryParams(params)
+        })
       }
     },
-
     //切换城市
     switchCity: function () {
       //兼容地图插件
@@ -173,6 +167,9 @@ export default {
     },
     //根据区编号获取小区列表
     getCommunity: function (residential_name) {
+		uni.showLoading({
+			title:"加载中.."
+		})
       let that = this;
       let params = {};
       params['region_area'] = this.currentCityCode;
@@ -187,18 +184,15 @@ export default {
         } else {
           app.globalData.oneFailHint(res.data.result_msg);
         }
+		that.loading=false
+		uni.hideLoading()
       });
     },
     //输入小区名字联想搜索
     nameInputSearch: function (e) {
       let residential_name = e.detail.value;
       this.getCommunity(residential_name);
-    } // //小程序 点击搜索 按钮时  事件
-    // inputSearch(e) {
-    //   console.info("11111111");
-    //   debugger
-    // },
-
+    } 
   }
 };
 </script>
@@ -207,6 +201,13 @@ page{
   overflow-y: scroll;
   background-color:#FFFFFF
 }
+
+.city{
+	padding:30rpx 30rpx 20rpx 30rpx;
+	border-bottom: 1rpx solid #efefef;
+	z-index: 99;
+}
+
 input {
   text-align: center;
   font-size: 32rpx;
@@ -218,10 +219,6 @@ input {
   padding: 16rpx;
   border-bottom: 1rpx solid #e2e2e2;    
 }
-
-
-/* pages/myHome/myHome.wxss */
-
 .nav_section {
   width: 100%;
   background-color: #FFFFFF;
@@ -289,8 +286,8 @@ input {
 }
 
 .default image {
-  width: 128rpx;
-  height: 128rpx;
+  width: 180rpx;
+  height: 140rpx;
   display: inline-block;
 }
 </style>

+ 43 - 23
pages/choosePlot/chooseRoom/chooseRoom.vue

@@ -1,7 +1,7 @@
 <template>
 <view :class="$isEmpty(room_list)?'empty-wrap':''">
 <view class="bg-gray" style="padding: 16rpx 30rpx;">
-	<text >当前选择楼栋:</text>
+	<text >当前选择单元:</text>
 </view>
 <view class="bg-white" style="padding:30rpx 30rpx 20rpx 30rpx;border-bottom: 1rpx solid #efefef;display: flex;justify-content: space-between;">
 	<view class="text-blue">
@@ -9,29 +9,22 @@
 	</view>
 	<view class="cu-btn line-blue sm round" @tap="change">
 		<text class="cuIcon-refresh padding-right-10"></text>
-		<text>切换楼栋</text>
+		<text>切换单元</text>
 	</view>
 </view>
 	<view class="bg-gray" style="padding: 12rpx 30rpx;">
 		<text >选择房间:</text>
 	</view>
-<view class="nav_section" v-if="room_list.length>0">
-  <navigator open-type="redirect" v-for="(item, index) in room_list" :key="index" :url="'../../auth/auth?room_id=' + item.id + '&room_name=' + item.name + '&residential_name=' + residential_name + '&unit_name=' + unit_name">
-    <view class="nav_section_items">
-      <view class="section_cont">
-        <view class="section_cont_tel">
-          <text class="info">{{item.name}}</text>
-        </view>
-      </view>
-    </view>
-  </navigator>
-</view>
-<view class="default" v-if="$isEmpty(room_list)">
+	<u-cell-group v-if="!$isEmpty(room_list)">
+		<u-cell-item  @click="jump(item)"  v-for="(item, index) in room_list" :key="index"  :title="item.name" :arrow="false"></u-cell-item>
+	</u-cell-group>
+<view class="default" v-if="$isEmpty(room_list)&&!loading">
   <image src="/static/common/empty.png" mode="heightFix"></image>
   <view>
     <text>没有获取到房间信息</text>
   </view>
 </view>
+<u-back-top :scroll-top="scrollTop"></u-back-top>
 </view>
 </template>
 
@@ -47,24 +40,34 @@ export default {
 	  //小区名字
       residential_name: null,
 	  //楼栋名字
-      unit_name: null 
+	  building_name:null,
+	  //楼栋id
+	  building_id:null,
+	  //单元名字
+      unit_name: null ,
+	  
+	  loading:true,
+	  scrollTop:0
 
     };
   },
-  components: {},
-  props: {},
+	onPageScroll(e) {
+		this.scrollTop = e.scrollTop;
+	},
   /**
    * 生命周期函数--监听页面加载
    */
   onLoad: function (options) {
 	  this.city_county_name=uni.getStorageSync("cityCountyName")
     //小区名字
-    var residential_name = options.residential_name; //楼栋名字
-    var unit_name = options.unit_name;
-    this.setData({
-      residential_name: residential_name,
-      unit_name: unit_name
-    });
+    this.residential_name = options.residential_name; 
+	//楼栋名字
+	this.building_name=options.building_name
+	//楼栋id
+	this.building_id=options.building_id
+	//单元名字
+    this.unit_name = options.unit_name;
+    //单元id
     var unit_id = options.unit_id;
     this.getRoom(unit_id);
   },
@@ -74,8 +77,24 @@ export default {
 			delta:1
 		})  
 	  },
+	jump(item){
+		let params={
+			residential_name:this.residential_name,
+			building_name:this.building_name,
+			building_id:this.building_id,
+			unit_name:this.unit_name,
+			room_name:item.name,
+			room_id:item.id
+		}
+		uni.redirectTo({
+			url:'../../auth/auth'+this.$u.queryParams(params)
+		})
+	},
     //根据楼栋信息查询房间
     getRoom: function (unit_id) {
+		uni.showLoading({
+			title:'加载中..'
+		})
       let that = this;
       let params = {};
       params['unit_id'] = unit_id;
@@ -89,6 +108,7 @@ export default {
         } else {
           app.globalData.oneFailHint(res.data.result_msg);
         }
+		uni.hideLoading()
       });
     }
   }

+ 31 - 32
pages/choosePlot/chooseUnit/chooseUnit.vue

@@ -1,35 +1,27 @@
 <template>
 <view :class="$isEmpty(unit_list)?'empty-wrap':''">
 	<view class="bg-gray" style="padding: 16rpx 30rpx;">
-		<text >当前选择小区:</text>
+		<text >当前选择楼栋</text>
 	</view>
 	<view class="bg-white" style="padding:30rpx 30rpx 20rpx 30rpx;border-bottom: 1rpx solid #efefef;display: flex;justify-content: space-between;">
 		<view class="text-blue">
-			<text class="">{{residential_name}}</text>
+			<text class="">{{building_name}}</text>
 		</view>
 		<view class="cu-btn line-blue sm round" @tap="change">
 			<text class="cuIcon-refresh padding-right-10"></text>
-			<text>切换小区</text>
+			<text>切换楼栋</text>
 		</view>
 	</view>
 	<view class="bg-gray" style="padding: 12rpx 30rpx;">
-		<text >选择楼栋:</text>
+		<text >选择单元:</text>
 	</view>
-<view class="nav_section" v-if="unit_list.length>0">
-  <view @click="jump(item)" v-for="(item, index) in unit_list" :key="index" >
-    <view class="nav_section_items">
-      <view class="section_cont">
-        <view class="section_cont_tel">
-          <text class="info">{{item.name}}</text>
-        </view>
-      </view>
-    </view>
-  </view>
-</view>
+	<u-cell-group v-if="unit_list.length>0">
+		<u-cell-item  @click="jump(item)"  v-for="(item, index) in unit_list" :key="index"  :title="item.name" :arrow="false"></u-cell-item>
+	</u-cell-group>
 <view class="default" v-if="$isEmpty(unit_list)">
   <image src="/static/common/empty.png" mode="heightFix"></image>
   <view>
-    <text >没有获取到楼栋信息</text>
+    <text >没有获取到单元信息</text>
   </view>
 </view>
 </view>
@@ -42,9 +34,10 @@ export default {
   data() {
     return {
       unit_list: null,
-      //小区集合
-      residential_name: null //小区名字
-
+	  //小区
+	  residential_name:null,
+	  //楼栋
+      building_name: null 
     };
   },
 
@@ -55,15 +48,14 @@ export default {
    * 生命周期函数--监听页面加载
    */
   onLoad: function (options) {
-	  console.log(app.defaultCity,)
-    //小区名字
-    var residential_name = options.residential_name;
-    this.setData({
-      residential_name: residential_name
-    }); //小区id
+	  //小区名字
+	  this.residential_name=options.residential_name
+	  
+    //楼栋名字
+    this.building_name = options.building_name;
 
-    var residential_id = options.residential_id;
-    this.getUnit(residential_id);
+    var buildingId = options.building_id;
+    this.getUnit(buildingId);
   },
   methods: {
 	  change(){
@@ -73,16 +65,23 @@ export default {
 	  },
 	  jump(item){
 		  app.globalData.unitId=item.id
+		  let params={
+			  residential_name:this.residential_name,//小区名称
+			  building_name:this.building_name,//楼栋名称
+			  building_id:this.building_id,//楼栋id
+			  unit_name:item.name,//单元名称
+			  unit_id:item.id,//单元id
+		  }
 		  uni.navigateTo({
-		  	 url:"/pages/choosePlot/chooseRoom/chooseRoom?unit_id=" + item.id + "&unit_name=" + item.name + "&residential_name=" + this.residential_name
+		  	 url:"/pages/choosePlot/chooseRoom/chooseRoom" + this.$u.queryParams(params)
 		  })
 	  },
-    //根据小区id获取楼栋信息
-    getUnit: function (residential_id) {
+    //根据楼栋id获取楼栋信息
+    getUnit: function (buildingId) {
       let that = this;
       let params = {};
-      params['residential_id'] = residential_id;
-      let operation = 'estate/getByResidentialId';
+      params['building_id'] = buildingId;
+      let operation = 'estate/getUnitsByBuildingId';
       app.globalData.postRequest(params, operation, function (res) {
         //获取成功
         if (res.data.result_code == 1) {

+ 26 - 30
pages/choosePlot/householdCert/householdCert.vue

@@ -1,6 +1,6 @@
 <template>
-	<view class="bg-white">
-		<view class="" v-if="appletType==1">
+	<view class="bg-white" style="min-height: 100vh;">
+		<view class="" >
 			<view class="flex justify-between " style="padding: 30rpx;box-sizing: border-box;">
 					<view class="" style="font-size: 38rpx;">
 						<text class="text-bold text-black">您的申请信息</text>
@@ -13,7 +13,7 @@
 				<view class="">
 					<view style="padding: 50rpx 0 20rpx 48rpx;">
 						<text class="cuIcon-location padding-right-sm"></text>
-						<text class="local_city_info">{{residential_name}} {{unit_name}} {{room_name}}</text>
+						<text class="local_city_info">{{residential_name}},{{building_name}},{{unit_name}},{{room_name}}</text>
 					</view>
 				</view>
 				<view class="form">
@@ -31,7 +31,7 @@
 								<u-input :disabled="true" :border="true" type="text" v-model="nationalityName"></u-input>
 							</u-form-item>
 							<u-form-item :required="type==0?true:false"  label="证件号码" prop="id_card" label-width="150">
-								<u-input :border="true" placeholder="住户类型是业主时,必填" :trim="true"  maxlength="18" v-model="id_card" type="number"></u-input>
+								<u-input :border="true" placeholder="住户类型是业主时,必填" type="text" :trim="true"  maxlength="18" v-model="id_card"></u-input>
 							</u-form-item>
 							<u-form-item :required="true" label="性别" prop="sex" label-width="150">
 								<u-radio-group v-model="sex" >
@@ -86,8 +86,8 @@
 				    </view>
 				  </view>
 				</view>
-				
-				<view style="background-color: #FFFFFF;">
+				<!-- 人脸 begin ,微信小程序审核时,隐藏该模块 -->
+				<view style="background-color: #FFFFFF;" v-if="appletType==1">
 							<view class="form_group mb0" style="padding-left: 60rpx;">
 								 <view>
 									<text class="sex">人脸:</text>
@@ -104,7 +104,7 @@
 							  </upload-img>
 							  <view class="" style="color: #59a5f0;">
 								 <text class="cuIcon-camera padding-right-sm" style="font-size: 30rpx;"></text>
-								 <text v-if="$isEmpty(show_image_uri)">点击上传人</text>
+								 <text v-if="$isEmpty(show_image_uri)">点击上传人</text>
 								 <text style="margin-top: 40rpx;display: inline-block;" v-else>点击重新上传</text>
 							  </view>
 							</view>
@@ -121,6 +121,8 @@
 							</view>
 					</view>
 				</view>
+				<!-- 人脸 end -->
+				
 			  <u-action-sheet @click="photoChecked"  z-index="999999" :list="list" v-model="show"></u-action-sheet>
 			  <u-select z-index="999999" mode="single-column" :list="typeArry" v-model="typeShow" @confirm="typeConfirm"></u-select>
 			  <u-select z-index="999999" mode="single-column" :list="nationalityArry" v-model="nationalityShow" @confirm="nationalityConfirm"></u-select>
@@ -130,9 +132,6 @@
 			  	</view>
 			  </view>
 		</view>
-		<view v-else >
-			
-		</view>
  </view>
 </template>
 
@@ -149,9 +148,9 @@ export default {
 			//小程序审核状态
 			appletType:0,
 			
-			//默认点击弹出拍照模态框的是人面上传操作,1:护照,2:入境,3:人面
+			//默认点击弹出拍照模态框的是人脸上传操作,1:护照,2:入境,3:人脸
 			operaType:3,
-			//人上传模态框,上传照片或拍照
+			//人上传模态框,上传照片或拍照
 			list: [{
 				text: '相册上传',
 			}, {
@@ -181,7 +180,7 @@ export default {
 				},
 				{
 					value: '1',
-					label: '成员'
+					label: '家属'
 				},
 				{
 					value: '2',
@@ -219,6 +218,8 @@ export default {
 			//小区名字
 			community_name: '',
 			//楼栋名字
+			building_name:'',
+			//单元名字
 			unit_name: '',
 			//房间名字
 			room_name: '',
@@ -274,22 +275,13 @@ export default {
 		  this.appletType=uni.getStorageSync('appletType')
 		  //显示用户选择的小区+楼栋+房间名字
 		  this.residential_name = options.residential_name;
+		  this.building_name=options.building_name
 		  this.unit_name = options.unit_name;
 		  this.room_name = options.room_name;
 		  this.room_id = options.room_id;
 		  this.name=app.globalData.member.name
 	},
 	onShow() {
-		if (this.appletType==0) {
-			uni.setNavigationBarTitle({
-				title:"功能待开发"
-			})
-		}else{
-			uni.setNavigationBarTitle({
-				title:"用户认证"
-			})
-		}
-		
 		//总步骤数
 		//注册的流程总步骤数是3,其他流程总步骤数是2
 		if(this.$isEmpty(app.globalData.totalStep)){
@@ -317,7 +309,7 @@ export default {
 				this.chooseImage()
 			} else if(index==1){
 				if(this.operaType==3){
-					//拍照上传,拍照人
+					//拍照上传,拍照人
 					uni.navigateTo({
 						url:"../../my-camera/my-camera?type=0"
 					})
@@ -377,7 +369,7 @@ export default {
 			console.log("operatype: ",this.operaType);
 			console.log("imgUrl",imgUrl)
 			var that = this;
-			//是否需要md5加密上传人
+			//是否需要md5加密上传人
 			let is_need_md5 = false;
 			if (this.operaType == 3) {
 			  is_need_md5 = true;
@@ -421,7 +413,7 @@ export default {
 		    return;
 		  } 
 		  //用户类型
-		  let type = that.type; //['业主','成员','租户'],
+		  let type = that.type; //['业主','家属','租户'],
 		  params['type'] = type; //0 中国大陆 1 中国香港/澳门 2 中国台湾 3 海外
 		  //国籍
 		  let nationality = that.nationality;
@@ -461,10 +453,10 @@ export default {
 		  params['sex'] = that.sex;
 		  params['name'] = that.name;
 		  params['tel'] = app.globalData.member.tel;
-		  params['room_id'] = that.room_id; //申请来源0-小程序添加 1-后台添加  2-后台导入 3-app添加
-		  params['create_type'] = '0'; //申请的记录类型 0--认证类型 1--新增类型 2--编辑类型
-		  params['record_type'] = '0'; //会员id
-		  params['member_id'] = app.globalData.member.id;
+		  params['room_id'] = that.room_id; 
+		  params['create_type'] = '0'; //申请来源0-小程序添加 1-后台添加  2-后台导入 3-app添加
+		  params['record_type'] = '0'; //申请的记录类型 0--认证类型 1--新增类型 2--编辑类型
+		  params['member_id'] = app.globalData.member.id;//会员id
 	
 		  let operation = 'member/authentication';
 			app.globalData.postRequest(params, operation, function (res) {
@@ -487,6 +479,10 @@ export default {
 </script>
 
 <style scoped lang="scss">
+page{
+	background-color: #FFFFFF;
+}
+	
 .form {
 	padding:0 60rpx;
 	background-color: #FFFFFF;

+ 0 - 2
pages/community/community.vue

@@ -386,8 +386,6 @@
 			},
 			fetchStaticData(){
 				this.oldManList=[
-					
-					
 					{
 						name:'李爱琴',
 						sex:'女',

+ 1 - 1
pages/community/detail/carDetail.vue

@@ -20,7 +20,7 @@
 							<view class="padding-top-20">{{dataDetail.device}}</view>
 						</view>
 					</view>
-					<view class="padding-top-20">
+					<view style="padding: 20rpx;">
 						<image @click="previewImg(dataDetail.image)" style="width: 250rpx;height: 280rpx;border-radius: 12rpx;" mode="scaleToFill" :src="dataDetail.image"></image>
 					</view>
 				</view>

+ 21 - 1
pages/demo/demo2.vue

@@ -220,7 +220,27 @@ export default {
 		
 	},
 	methods:{
-		
+		goDetail(item){
+			if (this.$isEmpty(item.type)) {
+				uni.showToast({
+					title:"即将推出",
+					icon:"none"
+				})
+				return
+			}
+			if (item.type=='applet') {
+				//小程序跳转
+				uni.navigateToMiniProgram({
+				  appId: item.target,
+				  path: 'pages/index/index'
+				})
+			}else{
+				//h5跳转
+				uni.navigateTo({
+					url:"../webview/webview?url="+item.target
+				})
+			}
+		},
 	}
 };
 </script>

+ 480 - 26
pages/guest/guest_form.vue

@@ -1,13 +1,14 @@
 <template>
 	<view>
+		<u-toast ref="uToast"></u-toast>
 		<view class="card" >
 			<view class="form">
 				<view class="flex">
 					<view class="need" >*</view>
-					<view>访问区</view>
+					<view>访问区</view>
 				</view>
 				<view class="bg-gray padding-20 "  >
-					<input disabled type="text"  value="阅海万家D区" />
+					<input disabled type="text" v-model="data.guestPosition" />
 				</view>
 			</view>
 			<view class="form">
@@ -16,7 +17,7 @@
 					<view>访问日期</view>
 				</view>
 				<view class="bg-gray padding-20 "  >
-					<input disabled=""  type="text"  v-model="data.visitTime" />
+					<u-input  type="select" :select-open="timeShow" v-model="data.guestTime"  placeholder="请选择访问日期" @click="timeShow=true"></u-input>
 				</view>
 			</view>
 			<view class="form">
@@ -25,49 +26,76 @@
 					<view>接待人</view>
 				</view>
 				<view class="bg-gray padding-20 "  >
-					<input  type="text" placeholder="请填写接待人"  v-model="data.receiver" />
+					<input :disabled="auditStatus!=null?true:false" type="text" placeholder="请填写接待人"  v-model="data.userName" />
 				</view>
 			</view>
 			<view class="form">
 				<view class="flex">
 					<view class="need" >*</view>
-					<view>来访者姓名:</view>
+					<view>您的姓名:</view>
 				</view>
 				<view class="bg-gray padding-20 "  >
-					<input  type="text" placeholder="请填写您的姓名" v-model="data.visitName" />
+					<input :disabled="auditStatus!=null?true:false" type="text" placeholder="请填写您的姓名" v-model="data.guestName" />
 				</view>
 			</view>
 			<view class="form ">
 				<view class="flex">
 					<view class="need" >*</view>
-					<view>来访者联系方式</view>
+					<view>您的联系方式</view>
+				</view>
+				<view class="bg-gray padding-20  flex justify-between " style="box-sizing: border-box;" >
+					<input disabled maxlength="11" type="number" placeholder="请获取您的联系方式" v-model="data.guestTel" />
+					<button open-type="getPhoneNumber" @getphonenumber="getPhoneNumber" class="light sm cu-btn bg-blue radius">
+						获取手机号
+					</button>
+				</view>
+			</view>
+			<view class="form ">
+				<view class="flex">
+					<view class="need" >*</view>
+					<view>您的身份证号</view>
 				</view>
 				<view class="bg-gray padding-20 " >
-					<input maxlength="11" type="number" placeholder="请输入您的联系方式" v-model="data.phone" />
+					<input :disabled="auditStatus!=null?true:false" placeholder="请输入您的身份证号" v-model="data.guestIdcard" />
 				</view>
 			</view>
 		</view>
-		
 		<view class="card ">
 			<view class="form" style="height: 320rpx;">
 				<view class="flex">
 					<view class="need" >*</view>
-					<view>来访原因</view>
+					<view>来访目的</view>
 				</view>
 				<view  class="bg-gray padding-10">
-					<textarea @click="showMask"   v-model="data.visitReason" maxlength="100" style="width: 100%;height: 270rpx;line-height: 50rpx;"  placeholder="请填写来访原因"></textarea>
+					<textarea :disabled="auditStatus!=null?true:false"   v-model="data.guestReason" maxlength="100" style="width: 100%;height: 270rpx;line-height: 50rpx;"  placeholder="请填写来访原因"></textarea>
 					<view  class="text-right text-df text-gray padding-top-10">
-						{{data.visitReason.length}} / 100
+						{{data.guestReason.length}} / 100
 					</view>
 				</view>
 			</view>
 		</view>
 		<view class="bg-white" style="height: 160rpx;"></view>
-		<view style="z-index: 999;" class=" footer-fixed" @click="submit">
+		
+		<view v-if="!islock&&auditStatus==null"  style="z-index: 999;" class=" footer-fixed" @click="submit">
 			<view class="cu-btn  flex  text-lg bg-red-btn" style="padding: 46rpx 0;">
 				确定提交
 			</view>
 		</view>
+		<button open-type="share" v-if="!islock&&auditStatus==0"  style="z-index: 999;" class=" footer-fixed" >
+			<view class="cu-btn  flex  text-lg bg-orange light" style="padding: 46rpx 0;">
+				待审核,通知被访者审核
+			</view>
+		</button>
+		<view @click="auditStatus=null;operaType=1;oldData=$u.deepClone(data)" v-if="!islock&&auditStatus==2"  style="z-index: 999;" class=" footer-fixed" >
+			<view class="cu-btn  flex  text-lg bg-red" style="padding: 46rpx 0;">
+				审核不通过,点击重新填表
+			</view>
+		</view>
+		<view v-if="islock" style="z-index: 999;" class=" footer-fixed" >
+			<view class="cu-btn  flex  text-lg bg-gray" style="padding: 46rpx 0;">
+				已锁定
+			</view>
+		</view>
 		<u-mask z-index="99999" :show="maskShow" @click="hideMask">
 			<view style="margin: 20rpx;" @click.stop="">
 				<textarea  @keyboardheightchange="keyboardheightchange" v-model="data.visitReason"  value="" style="background-color: #FFFFFF;width: 100%;padding: 20rpx;box-sizing: border-box;" placeholder="请填写来访原因" />
@@ -76,7 +104,23 @@
 				</view>
 			</view>
 		</u-mask>
+		<!--弹窗-->
+		<view class="modal-mask"   v-if="showModal"></view>
+		<view class="modal-dialog" v-if="showModal">
+		  <view class="modal-title">提示</view>
+		    <view class="modal-content">
+		      <view class="modal-input">
+		        <text class="password">授权成功,请转发给好友填写表单</text>
+		      </view>
+		    </view>
+		    <view class="modal-footer">
+		      <button class="btn-confirm" @click="showModal=false;getAuthRecords()" data-status="confirm">暂不转发</button>
+			  <button class="btn-cancel" open-type="share"  data-status="cancel">立即转发</button>
+		    </view>
+		</view>
+		
 		
+		<u-picker @confirm="timeConfirm" :params="params" v-model="timeShow" mode="time"></u-picker>
 	</view>
 </template>
 
@@ -89,25 +133,349 @@
 		},
 		data() {
 			return {
+				//0新增表单操作,1修改表单操作
+				operaType:0,
+				
+				id:'',//授权记录的id
+				doorNeedAudit:0,//该授权开门是否需要审核
+				memberId:'',//业主的 memberId,用来获取设备列表
+				residentialId:'',//小区id,用来获取设备列表
+				openId:'',
+				sessionKey:'',
+				
+				showModal:false,
+				
+				//查询出来的审核状态
+				auditStatus:null,
+				islock:false,
+				
+				//时间选择器
+				timeShow:false,
+				params: {
+					year: true,
+					month: true,
+					day: true,
+					hour: true,
+					minute: true,
+					second: true
+				},
+				//审核不通过重新修改时的旧数据
+				oldData:{},
+				//提交的数据
 				data:{
-					//访客联系方式
-					phone:'19124812874',
-					//访客姓名
-					visitName:'黄明潘',
-					//访问时间
-					visitTime:this.$u.timeFormat(new Date(),'yyyy-mm-dd hh:MM:ss'),
-					//访问原因
-					visitReason:'看看小婉君',
-					//接单人
-					receiver:'小婉君'
-				}
+					//授权记录的表id
+					guestAuthId:'',
+					//被访者区域
+					guestPosition:'',
+					//来访日期
+					guestTime:this.$u.timeFormat(new Date(),'yyyy-mm-dd hh:MM:ss'),
+					//接待人
+					userName:'',
+					//来访者姓名
+					guestName:'',
+					//来访者联系方式
+					guestTel:'',
+					//来访者身份证号
+					guestIdcard:'',
+					//来访原因
+					guestReason:'',
+					//审核状态
+					auditStatus:0
+				},
+				//添加访客记录后,将访客记录id分享给好友审核
+				shareId:'',
 			}
 		},
-		onLoad() {
+		onShareAppMessage: function (ops) {
+		  this.showModal=false
+		  this.getAuthRecords()
+		  return {
+		    title: "我是"+this.data.guestName+",我正在填表申请开门,请审核",
+			path:"/pages/record/record?id="+this.shareId
+		  };
+		},
+		onLoad(options) {
 			that=this
+			if (!this.$isEmpty(options.scene)) {
+				let scene=decodeURIComponent(options.scene).split(",")
+				//从小程序二维码进入
+				options.id=scene[0]
+				options.doorNeedAudit=scene[1]
+				options.memberId=scene[2]
+			}
+			//附带的页面参数id为空,则锁定页面
+			if (this.$isEmpty(options.id)) {
+				uni.showModal({
+					showCancel:false,
+					content:"系统错误,已锁定",
+					success: (res) => {
+						if (res.confirm) {
+							that.islock=true
+						}
+					}
+				})
+				return
+			}
+			this.id=options.id 
+			this.doorNeedAudit=options.doorNeedAudit
+			this.memberId=options.memberId
+			this.data.guestAuthId=this.id
+			this.getAuthRecords()
 		},
 		methods: {
-
+			getPhoneNumber (e) {
+				let that=this
+				if (e.detail.errMsg == "getPhoneNumber:ok") {
+					console.log(e);
+					let params={
+						sessionKey:that.sessionKey,
+						encryptedData:e.detail.encryptedData,
+						iv:e.detail.iv
+					}
+					let operation = 'miniprogram/getOpenData';
+					getApp().globalData.postRequest(params,operation,function(res){
+						that.data.guestTel=res.data.purePhoneNumber
+					})
+				}else{
+					this.$refs.uToast.show({
+						title: '获取手机号失败!',
+						position:"top",
+						type: 'error',
+					})
+					return
+				}
+			},
+			/**
+			 * 跳转到设备列表
+			 */
+			jumpOpenDoor(){
+				console.log(this.memberId,this.residentialId);
+				uni.redirectTo({
+					url:"/pages/guest/open_door?memberId="+this.memberId+"&residentialId="+this.residentialId
+				})
+			},
+			timeConfirm(e){
+				this.data.guestTime=e.year+"-"+e.month+"-"+e.day+" "+e.hour+":"+e.minute+":"+e.second
+				console.log(this.data.guestTime);
+			},
+			/**
+			 * 先通过id查询授权记录表查看该授权是否过期
+			 * 过期了就不能进行接下来的操作,提示访客联系业主重新授权
+			 * 没有过期就判断审核配置,配置了不需要审核表单就直接跳到设备列表,
+			 * 需要审核就通过授权记录的id和openid查询访客记录表,查询到记录就直接跳到设备列表
+			 * 查不到记录就填表
+			 */
+			async getAuthRecords(){
+				let operation="guestAuthorize/getById/"+this.id
+				let params={}
+				let res=await app.globalData.postRequestAsync(params, operation);
+				if (res.data.result_code!=1) {
+					this.$refs.uToast.show({
+						title: '没有该授权记录',
+						position:"top",
+						type: 'error',
+					})
+					this.islock=true
+					return
+				}
+				//授权详情
+				let guestAuthorize=res.data.guestAuthorize
+				that.residentialId=guestAuthorize.residentialId
+				//授权结束时间
+				that.data.endTime=guestAuthorize.endDate
+				let endDate= that.$commonDate(guestAuthorize.endDate).getTime()
+				//当前时间
+				let now= new Date().getTime()
+				//判断授权是否过期
+				if (now>endDate) {
+					uni.showModal({
+						title:"提示",
+						content:"授权时间已过期,请联系被访者重新授权",
+						showCancel:false,
+						success: (res) => {
+							if (res.confirm) {
+								that.islock=true
+							}
+						}
+					})
+					return
+				}
+				// 授权没有过期
+				//通过openid,授权记录id查询访客记录表
+				let guestRes=await this.getGuestRecords()
+				if (guestRes.data.result_code!=1) {
+					//没有记录,就填表
+					that.data.guestPosition=guestAuthorize.residentialName+","
+									+guestAuthorize.buildingName+","+guestAuthorize.unitName+","+
+									guestAuthorize.roomName
+					that.data.userName=guestAuthorize.userName
+					that.data.residentialId=guestAuthorize.residentialId
+					that.data.residentialName=guestAuthorize.residentialName
+					that.data.userId=guestAuthorize.userId
+					return
+				}
+				//有记录,就判断审核状态
+				let guestRecord=guestRes.data.guestRecords[0]
+				var {orgId,orgPosition,rootOrgId,createDate,...restData} = guestRecord
+				that.data=restData
+				that.auditStatus=guestRecord.auditStatus
+				if (that.auditStatus==1) {
+					//审核通过。跳转到设备列表
+					that.jumpOpenDoor()
+				}
+			},
+			/**
+			 * 通过openid和授权记录id和审核通过的状态查看访客记录表
+			 */
+			async getGuestRecords(){
+				let jsCode = await new Promise((resolve, reject) => {  
+					uni.login({  
+						provider: 'weixin',  
+						success: res => {
+							resolve(res.code);  
+						},  
+						fail: err => {  
+							reject(err);  
+						}  
+					})
+				})
+				let params = {
+					js_code:jsCode,
+					name:'community'
+				};
+				let operation = 'miniprogram/getOpenid'; //发起请求
+				let res= await app.globalData.postRequestAsync(params, operation);
+				that.sessionKey=res.data.session_key
+				this.openId=res.data.openid
+				//获取成功
+				let url='guestRecord/getByCondition'
+				let guestParams={
+					guestAuthId:this.id,
+					openId:this.openId
+				}
+				let guestRes=await app.globalData.postRequestAsync(guestParams,url)
+				return guestRes
+			},
+			submit(){
+				let that=this
+				if (this.$isEmpty(this.data.guestPosition)) {
+					this.$refs.uToast.show({
+						title: '系统错误!',
+						position:"top",
+						type: 'error',
+					})
+					this.islock=true
+					return
+				}
+				if (this.$isEmpty(this.data.guestTime)) {
+					this.$refs.uToast.show({
+						title: '请选择访问日期',
+						position:"top",
+						type: 'error',
+					})
+					return
+				}
+				
+				if (this.$isEmpty(this.data.userName)) {
+					this.$refs.uToast.show({
+						title: '请填写接待人姓名',
+						position:"top",
+						type: 'error',
+					})
+					return
+				}
+				if (this.$isEmpty(this.data.guestName)) {
+					this.$refs.uToast.show({
+						title: '请填写您的姓名',
+						position:"top",
+						type: 'error',
+					})
+					return
+				}
+				if (this.$isEmpty(this.data.guestTel)) {
+					this.$refs.uToast.show({
+						title: '请填写联系方式',
+						position:"top",
+						type: 'error',
+					})
+					return
+				}
+				if (!this.$u.test.mobile(this.data.guestTel)) {
+					this.$refs.uToast.show({
+						title: '联系方式不正确',
+						position:"top",
+						type: 'error',
+					})
+					return
+				}
+				if (this.$isEmpty(this.data.guestIdcard)) {
+					this.$refs.uToast.show({
+						title: '请填写身份证号',
+						position:"top",
+						type: 'error',
+					})
+					return
+				}
+				if (!this.$u.test.idCard(this.data.guestIdcard)) {
+					this.$refs.uToast.show({
+						title: '身份证号不正确',
+						position:"top",
+						type: 'error',
+					})
+					return
+				}
+				if (this.$isEmpty(this.data.guestReason)) {
+					this.$refs.uToast.show({
+						title: '请填写来访目的',
+						position:"top",
+						type: 'error',
+					})
+					return
+				}
+				if (JSON.stringify(this.oldData)==JSON.stringify(this.data)) {
+					this.$refs.uToast.show({
+						title: '无任何修改痕迹,请先修改后再提交',
+						position:"top",
+						type: 'error',
+						icon:false,
+						duration:2500
+					})
+					return
+				}
+				this.data.openId=this.openId
+				let operation=''
+				if (this.operaType==0) {
+					//新增
+					operation="guestRecord/addGuestRecord"
+					if (this.doorNeedAudit==0) {
+						//1不需要审核,直接审核通过
+						this.data.auditStatus=1
+					}
+				}else{
+					//修改
+					operation="guestRecord/updateGuestRecord"
+					this.data.auditStatus=0
+				}
+				app.globalData.postRequest(this.data, operation,function(res){
+					if (res.data.result_code==1) {
+						if (that.doorNeedAudit==0) {
+							//不需要审核,直接跳转到设备列表页
+							that.jumpOpenDoor()
+						}else{
+							that.shareId=res.data.guestRecordId
+							//需要审核,弹框分享给好友审核
+							that.showModal=true
+						}
+					}else{
+						that.$refs.uToast.show({
+							title: '操作失败',
+							position:"top",
+							type: 'error',
+						})
+					}
+				})
+				
+			}
 		}
 	}
 </script>
@@ -129,4 +497,90 @@
 		color: #ff0000;
 		padding-right: 10rpx;
 	}
+	
+	
+	
+	.modal-mask {
+	  width: 100%;
+	  height: 100%;
+	  position: fixed;
+	  top: 0;
+	  left: 0;
+	  background: #000;
+	  opacity: 0.5;
+	  overflow: hidden;
+	  z-index: 9000;
+	  color: #fff;
+	}
+	
+	.modal-dialog {
+	  width: 540rpx;
+	  overflow: hidden;
+	  position: fixed;
+	  top: 45%;
+	  left: 0;
+	  z-index: 9999;
+	  background: #f9f9f9;
+	  margin: -180rpx 105rpx;
+	  border-radius: 36rpx;
+	}
+	
+	.modal-title {
+	  padding-top: 50rpx;
+	  font-size: 36rpx;
+	  color: #030303;
+	  text-align: center;
+	}
+	
+	.modal-content {
+	  padding: 60rpx 0;
+	}
+	
+	.modal-input {
+	  display: flex;
+	  font-size: 30rpx;
+	}
+	
+	.password {
+	  width: 100%;
+	  height: 80rpx;
+	  font-size: 30rpx;
+	  line-height: 80rpx;
+	  padding: 0 20rpx;
+	  box-sizing: border-box;
+	  color: #606266;
+	  text-align: center;
+	}
+	
+	input-holder {
+	  color: #666;
+	  font-size: 28rpx;
+	}
+	
+	.modal-footer {
+	  display: flex;
+	  flex-direction: row;
+	  height: 86rpx;
+	  border-top: 1px solid #dedede;
+	  font-size: 34rpx;
+	  line-height: 86rpx;
+	}
+	.modal-footer button::after{
+	   border: none;
+	  
+	}
+	.modal-footer .btn-cancel {
+	  width: 50%;
+	  color: #2a7fff;
+	  text-align: center;
+	 border-radius: 0;
+	}
+	
+	.modal-footer .btn-confirm {
+	  width: 50%;
+	  color: #666;
+	  border-right: 1px solid #dedede;
+	  text-align: center;
+	}
+	
 </style>

+ 32 - 13
pages/guest/open_door.vue

@@ -30,23 +30,21 @@ export default {
 	},
 	data() {
 		return {
+			memberId:'',
+			residentialId:'',
+			
 			isopen:false,
 			isloading:false,
-			doorValue:'5678',
-			device_list:[
-				{
-					id:'1234',
-					name:'宁夏冬美小区'
-				},
-				{
-					id:'5678',
-					name:'宁夏冬美小区2'
-				},
-			]
+			doorValue:'',
+			device_list:[]
 		};
 	},
-	onLoad() {
+	onLoad(options) {
 		that=this
+		this.memberId=options.memberId
+		this.residentialId=options.residentialId
+		console.log(this.memberId);
+		this.getAuthDevice()
 	},
 	methods:{
 		RadioChange(e) {
@@ -65,7 +63,7 @@ export default {
 		openDoor() {
 			 let device_id=this.doorValue
 			 let params = {};
-			 params['member_id'] = app.globalData.member.id;
+			 params['member_id'] = this.memberId;
 			 params['device_id'] = device_id;
 			 let operation = 'member/openDoor';
 			 app.globalData.postRequest(params, operation, function (res) {
@@ -76,6 +74,27 @@ export default {
 			   });
 			 });
 		},
+		/**
+		 * 获取设备列表
+		 */
+		getAuthDevice: function () {
+		  let that = this;
+		  let params = {};
+		  params['member_id'] = this.memberId;
+		  let operation = 'member/getAuthDeviceByMemberId';
+		  app.globalData.postRequest(params, operation, function (res) {
+				if (res.data.result_code == 1) {
+					let list=[]
+				    res.data.list.map(item => {
+				    	if (item.residentialId.indexOf(that.residentialId)>=0) {
+				    		list.push(item);
+				    	}
+				    });
+					that.device_list=list
+					that.doorValue=list[0].id
+				}
+		  });
+		},
 	}
 };
 </script>

+ 212 - 0
pages/healthCode/healthCode.vue

@@ -0,0 +1,212 @@
+<template>
+	<view class="">
+		<u-modal   @confirm="infoConfirm" title="身份信息" :mask-close-able="false" v-model="infoShow" >
+			<view class="slot-content" style="margin: 20rpx;">
+				<u-form label-width="150"  ref="uForm">
+					<u-form-item label="姓名" ><u-input v-model="personInfo.name" disabled /></u-form-item>
+					<u-form-item label="身份证号"><u-input v-model="personInfo.idNumber" /></u-form-item>
+				</u-form>
+			</view>
+		</u-modal>
+		<view v-if="loading" class="bg-white" style="padding: 0 50rpx;">
+			<image src="https://gdyjht.com.cn/loading.gif" mode="aspectFit" class="gif-white response" style="height:600upx;padding-top: 200rpx;"></image>
+		</view>
+		
+		<view class="flex flex-direction justify-between" v-else style="height: 100vh;">
+			<view  class="codeBox" :class="{ 'bg-red': healthCode.color=='red', 'bg-blue': healthCode.color=='green'}" >
+				<view class="timeBar">{{hideName}}</view>
+				<view class="timeBar">{{nowStr}}</view>
+				<image class="code" :src="healthCode.code"></image>
+				<view v-if="healthCode.color=='green'" class="timeBar" style="height: 250rpx;letter-spacing: 20rpx;">
+					<icon type="success" size="30"/>
+					未见异常
+				</view>
+				<view v-if="healthCode.color=='red'" class="timeBar" style="height: 250rpx;letter-spacing: 20rpx;">
+					<icon type="warn" size="30"/>
+					体温异常
+				</view>
+			</view>
+			<view class="tips">{{tips}}</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				loading:true,
+				
+				infoShow:false,
+				
+				hideName:'',
+				personInfo: {
+					name: "*",
+					idNumber: "*"
+				},
+				timer: '',
+				nowStr: "",
+				healthCode: {},
+				tips: "按照目前掌握的防疫相关数据,暂未发现您存在与防疫相关异常健康状况。防疫相关数据会随着疫情发展及时更新。此次查询并不会排除您的防疫相关健康风险。"
+			}
+		},
+	   onLoad() {
+		   console.log(this.$u.sys());
+		    this.getDateStr()
+			this.init()
+		},
+		beforeDestroy() {
+			clearInterval(this.timer);
+		},
+		methods: {
+			init(){
+				let member= getApp().globalData.member
+				this.personInfo.name=member.name
+				this.personInfo.idNumber=member.idcard
+				
+				if (this.$isEmpty(this.personInfo.name)) {
+					uni.showModal({
+						content:'系统异常',
+						showCancel:false,
+						success: (res) => {
+							uni.navigateBack({
+								delta:1
+							})
+						}
+					})
+					return
+				}
+				this.hideName=this.handelName(this.personInfo.name)
+				if (this.$isEmpty(this.personInfo.idNumber)) {
+					this.infoShow=true
+				}else{
+					this.fetchCode()
+				}
+			},
+			infoConfirm(){
+				if (this.$isEmpty(this.personInfo.idNumber)) {
+					this.$u.toast('请输入身份证号')
+					this.infoShow=true
+					return
+				}
+				if (!this.$u.test.idCard(this.personInfo.idNumber)) {
+					this.$u.toast('请输入正确的身份证号')
+					this.infoShow=true
+					return
+				}
+				this.fetchCode()
+			},
+			fetchCode(){
+				this.loading=true
+				let that=this
+				let operation='health/getCode'
+				let params={
+					userName:this.personInfo.name,
+					idCardNumber:this.personInfo.idNumber
+				}
+				getApp().globalData.postRequest(params,operation,function(res){
+					if (res.data.result_code!=1) {
+						uni.showModal({
+							content:res.data.result_msg,
+							showCancel:false,
+							success: (res) => {
+								if (res.confirm) {
+									uni.navigateBack({
+										delta:1
+									})
+								}
+							}
+						})
+					}
+					that.healthCode=res.data.result_msg
+					that.loading=false
+				})
+			},
+		    handelName(str,frontLen=0,endLen=1) {
+				var newStr;
+				var len = str.length-frontLen-endLen;
+				if (str.length === 2) {
+					newStr = str.substring(0, 1) + '*';
+				} else if (str.length > 2) {
+					var char = '';
+					for (let i = 0; i < len; i++) {
+						char += '*';
+					}
+					newStr = str.substring(0, frontLen) + char + str.substring(str.length-endLen);
+				} else {
+					newStr = str;
+				}
+				return newStr;
+			},
+			getDateStr(){this.timer = setInterval(()=>{
+					this.nowStr = this.$util.dateFormat(new Date(),"yyyy-MM-dd hh:mm:ss");
+				},1000);
+			},
+			navigate(path){
+				uni.navigateTo({
+					url:path
+				})
+			}
+		}
+	}
+</script>
+
+<style>
+	page{
+		background-color: #FFFFFF;
+	}
+	
+	.bg-blue{
+		background-color: #4594f1;
+		color: #FFFFFF;
+	}
+	
+	.timeBar{
+		width: 400rpx;
+		height: 100rpx;
+		color: white;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		font-size: 40rpx;
+		/* background-color: rgba(255,255,255,0.5); */
+	}
+	.code{
+		background: white;
+		padding: 5rpx;
+		width: 350rpx;
+		height: 350rpx;
+	}
+	.codeBox{
+		width: 100%;
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		justify-content: center;
+		border-radius: 5rpx;
+		flex-basis: 95%;
+	}
+	.tips{
+		padding: 40rpx 0;
+		width: 90%;
+		line-height: 55rpx;
+		text-indent: 2em;
+		margin: auto;
+		color: gray;
+		/* background: #18B566; */
+		font-size: 30rpx;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+	}
+	.link{
+		height: 100rpx;
+		width: 100%;
+		color: #007AFF;
+		display: flex;
+		text-decoration: underline;
+		font-style: italic;
+		align-items: center;
+		justify-content: center;
+	}
+</style>

+ 68 - 46
pages/index/index.vue

@@ -11,7 +11,7 @@
 					<picker v-else @change="typeChange" :value="plotIndex" :range="plotArray">
 					  <view class="padding-left-20 ">
 					  	<u-icon name="map" size="34"></u-icon>
-					  	<text class="padding-left-sm " style="font-size: 34rpx;">plot</text>
+					  	<text class="padding-left-sm " style="font-size: 34rpx;">{{plot}}</text>
 					  </view>
 					</picker>
 				</view>
@@ -37,7 +37,7 @@
 					<view class="cu-item" :class="item.index==5?'img1-lg':''" @click="top(item.index)" v-for="(item,index) in gridList" :key="index">
 						<block v-if="item.index==5">
 							<view class="grid-icon" >
-								<image  style="width: 100rpx;height: 100rpx;" :src="modalShow?'../../static/home/open1.png':'../../static/home/open4.png'"/>
+								<image  style="width: 88rpx;height: 88rpx;" :src="modalShow?'../../static/home/open1.png':'../../static/home/open4.png'"/>
 							</view>
 							<text  style="color: #333333;font-size: 30rpx;font-weight: 800;" >{{item.title}}</text>
 						</block>
@@ -134,10 +134,11 @@
 				//小区名字
 				plotIndex: 0,
 				residentialIdList: [] ,//小区id
+				
 				adList: [
 					{
 					  'videoType': 0,
-					  'videoUri': "http://139.9.103.171:1888/miniofile/app/banner2.jpeg"
+					  'videoUri': "http://139.9.103.171:1888/miniofile/app/banner.jpg"
 					},
 				],
 				elements: [{
@@ -146,26 +147,37 @@
 					color: '#e3f5ff',
 					icon: '../../static/home/fanyi1.png',
 					index:6
-				}, {
-					title: '物业缴费',
-					name: '在线物业缴费',
-					color: '#e9f9f3',
-					icon: '../../static/home/jiaofei.png',
-					index:7
+				}, 
+				{
+					title: '健康码',
+					name: '通行防疫码',
+					color: '#e5eef9',
+					icon: '../../static/home/health.png',
+					index:9
 				},
+				
 				{
 					title: '物业报修',
 					name: '在线物业报修',
 					color: '#ffefef',
 					icon: '../../static/home/baoxiu1.png',
 					index:8
-				}, {
-					title: '更多服务',
-					name: '更多智慧服务',
-					color: '#eeeeee',
-					icon: '../../static/home/more.png',
-					index:99
-				}],
+				}, 
+				{
+					title: '物业缴费',
+					name: '在线物业缴费',
+					color: '#e9f9f3',
+					icon: '../../static/home/jiaofei.png',
+					index:7
+				},
+				// {
+				// 	title: '更多服务',
+				// 	name: '更多智慧服务',
+				// 	color: '#eeeeee',
+				// 	icon: '../../static/home/more.png',
+				// 	index:99
+				// }
+				],
 				gridList:[
 					{
 						icon:'../../static/home/fangwu.png',
@@ -319,29 +331,22 @@
 					}, 1000);
 				}
 			},
-			handelShare(e){
-				this.e = e;
-				console.log(12,e)
+			handelShare(options){
 				//二维码扫描链接 start
-				if(e != null && e.q != null){
-					let url = decodeURIComponent(e.q);
-					let param = {};
-					// 把参数按&拆分成数组
-					let index = url.indexOf("?");
-					let query = url.substring(index+1,index.length);
-					var param_arr = query.split("&");
-					for (var i = 0; i < param_arr.length; i++) {
-					    var pair = param_arr[i].split("=");
-					    param[pair[0]]=pair[1];
-					}
-					if(param['type'] == "share"){
-						let path = 'pagesM/pages/goods_des';
-						let params = `id=${param['id']}&storeId=${param['storeId']}&inviteCode=${param['inviteCode']}`
-						let url = `${path}?${params}`;
-						console.error("url = " + url);
-						this.e = null;
-						uni.navigateTo({url: url});
+				if (!this.$isEmpty(options.scene)) {
+					let scene=decodeURIComponent(options.scene).split(",")
+					//从小程序二维码进入
+					console.log(scene);
+					let path="/pagesM/pages/goods_des"
+					let params= "?id="+scene[0]+"&storeId="+scene[1]
+					if (!this.$isEmpty(scene[2])) {
+						params=params+"&inviteCode="+scene[2]
 					}
+					let url=path+params
+					console.log(url);
+					uni.redirectTo({
+						url:url
+					})
 				}
 				//二维码扫描链接 end
 				
@@ -386,11 +391,13 @@
 			  Promise.all([_this.getRoomByMemberId()]).then(result => {
 			    let value = _this.plotArray[e.detail.value];
 			    let residentialId = _this.residentialIdList[e.detail.value];
-			
-			    uni.removeStorageSync("plotName");
-			    uni.removeStorageSync("residentialId");
+				
+				let residentialList= uni.getStorageSync('residentialList')
+				
+				uni.setStorageSync("personTel", residentialList[e.detail.value].personTel);
 			    uni.setStorageSync("plotName", value);
 			    uni.setStorageSync("residentialId", residentialId);
+				uni.setStorageSync('doorNeedAudit',residentialList[e.detail.value].doorNeedAudit)
 				
 				
 			    _this.setData({
@@ -494,6 +501,8 @@
 			    console.info("getMemberByOpenid==" + res.data.result_msg); //获取成功
 			    if (res.data.result_code == 1) {
 			      app.globalData.member = res.data.member;
+				  that.$u.vuex('vuex_member',res.data.member)
+				  
 			      app.globalData.anyHousePass = res.data.anyHousePass; //获取房屋列表
 			      _this.getRoomByMemberId();
 				  _this.getAuthDevice()
@@ -529,20 +538,25 @@
 			  app.globalData.postRequest(params, operation, function (res) {
 			    console.info("获取成功" , res.data); //获取成功
 			    let list = [];
-				
+				let doorNeedAuditList=[]
 			    let residentialIdList = [];
+				let personTelList=[]
+				
 			    if (res.data.result_code == 1) {
 					app.globalData.userId=res.data.list[0].userId
-			      res.data.list.map(item => {
+			       res.data.list.map(item => {
 			        if (list.indexOf(item.residentialName) == -1) {
 			          list.push(item.residentialName);
+					  doorNeedAuditList.push(item.doorNeedAudit)
 			          residentialIdList.push(item.residentialId);
+					  personTelList.push(item.personTel)
 			        }
 			      });
-			
 			      if (list.length < 1) {
+					  uni.removeStorageSync("personTel");
 			        uni.removeStorageSync("plotName");
 			        uni.removeStorageSync("residentialId");
+					uni.removeStorageSync("doorNeedAudit");
 			      } else {
 			        //获取本地储存的当前所在小区
 			        let plot = that.plot;
@@ -552,6 +566,8 @@
 			            plot: plot
 			          });
 			        } else {
+						uni.setStorageSync("personTel", personTelList[0]);
+					  uni.setStorageSync("doorNeedAudit", doorNeedAuditList[0]);
 			          uni.setStorageSync("plotName", list[0]);
 			          uni.setStorageSync("residentialId", residentialIdList[0]);
 			          that.setData({
@@ -562,8 +578,10 @@
 				  let residentialList=[]
 				  list.forEach((item,index)=>{
 					  let tmp={}
-					  tmp.residentialName=item
+					  tmp.personTel=personTelList[index]
 					  tmp.residentialId=residentialIdList[index]
+					  tmp.doorNeedAudit=doorNeedAuditList[index]
+					  tmp.estateTel=doorNeedAuditList[index]
 					  residentialList.push(tmp)
 				  })
 				  uni.setStorage({
@@ -607,10 +625,10 @@
 				  })
 				  return
 			  }
-			  var that = this;
+			   var that = this;
 			    var member = app.globalData.member;
 			    var anyHousePass = app.globalData.anyHousePass; //会员认证状态:{ 0:未认证,1:待审审核,2:已认证 }
-			    if (member == null) {
+			    if (this.$isEmpty(member)) {
 			      //去注册
 				  uni.navigateTo({
 				  	url:"../empty/empty"
@@ -670,6 +688,9 @@
 					  //物业报修
 					  url = '/pages/services/property/property';
 					  break;
+					case 9:
+					  url = '/pages/healthCode/healthCode';
+					  break;
 			        default:
 			          url = "";
 			          break;
@@ -714,6 +735,7 @@
 			        app.globalData.oneFailHint('亲,你的信息正在审核,请耐心等待');
 			      } else if (member.state == 2) {
 			        app.globalData.oneFailHint('亲,你的信息已审核通过');
+					that.getRoomByMemberId()
 			      }
 			      app.globalData.member = member;
 			      app.globalData.anyHousePass = res.data.anyHousePass;

+ 1 - 1
pages/my-camera/my-camera.vue

@@ -25,7 +25,7 @@
 	export default {
 		data() {
 			return {
-				//0 人 1 证件
+				//0 人 1 证件
 				type:0,
 				
 				flash:'off',

+ 40 - 44
pages/myFamily/activateFace/activateFace.vue

@@ -1,32 +1,39 @@
 <template>
 <view style="background-color: #FFFFFF;height: 100vh;">
-<view v-if="faceList!=null && faceList.length!=0">
-	<view class="head">请选择人脸套餐:</view>
-	<view class="content">
-	  <view class="faceList">
-	    <view v-for="(item, index) in faceList" :key="index" class="item" @tap="selectFace" :data-item="item" :data-index="index" :style="'border-color:' + (selectIndex==index?'#1296db':'gray')">
-	      <view class="day">{{item.days}}天</view>
-	      <view class="amount">售价{{item.amount}}元</view>
-	    </view>
-	  </view>
-	</view>
-	<view class="faceDate">
-	  人脸有效期:<text>{{faceEndDate}}</text>
-	</view>
-	<view @click="goPay"  class=" footer-fixed" >
-		<view class="cu-btn  flex  text-lg bg-red-btn" style="padding: 46rpx 0;">
-			支付
+	<view class="" v-if="appletType==1">
+		<view v-if="faceList!=null && faceList.length!=0">
+			<view class="head">请选择人脸套餐:</view>
+			<view class="content">
+			  <view class="faceList">
+			    <view v-for="(item, index) in faceList" :key="index" class="item" @tap="selectFace" :data-item="item" :data-index="index" :style="'border-color:' + (selectIndex==index?'#1296db':'gray')">
+			      <view class="day">{{item.days}}天</view>
+			      <view class="amount">售价{{item.amount}}元</view>
+			    </view>
+			  </view>
+			</view>
+			<view class="faceDate">
+			  人脸有效期:<text>{{faceEndDate}}</text>
+			</view>
+			<view @click="goPay"  class=" footer-fixed" >
+				<view class="cu-btn  flex  text-lg bg-red-btn" style="padding: 46rpx 0;">
+					支付
+				</view>
+			</view>
 		</view>
+		<view v-else>
+			<view class="default" >
+			   <image src="/static/common/empty.png" mode="heightFix"></image>
+			  <view>
+			    <text>没有相关信息</text>
+			  </view>
+			</view>
+		</view>	
 	</view>
-</view>
-<view v-else>
-	<view class="default" >
-	   <image src="/static/empty.png" mode="heightFix"></image>
-	  <view>
-	    <text>没有相关信息</text>
-	  </view>
+	
+	<view v-else>
+		<view class="" style="height: 300rpx;"></view>
+		<u-empty ></u-empty>
 	</view>
-</view>	
 
 </view>	
 
@@ -39,6 +46,10 @@ let app = getApp();
 export default {
   data() {
     return {
+	  // 小程序审核状态,0审核中,1审核通过
+	  //目的是为了隐藏wei gui的人脸功能
+	  appletType:0,
+		
       user_id: '',
       room_id: '',
       residential_id: '',
@@ -71,17 +82,16 @@ export default {
 
     this.getFaceList();
   },
+  onShow() {
+  	  this.appletType=this.$setNavigationBarTitle('套餐','人脸激活')
+	  console.log(this.appletType);
+  },
 
   /**
    * 生命周期函数--监听页面初次渲染完成
    */
   onReady: function () {},
 
-  /**
-   * 生命周期函数--监听页面显示
-   */
-  onShow: function () {},
-
   /**
    * 生命周期函数--监听页面隐藏
    */
@@ -210,19 +220,5 @@ export default {
 }
 
 
-.default {
-  text-align: center;
-  position: fixed;
-  left: 50%;
-  top: 40%;
-  transform: translate(-50%, -50%);
-}
-.default text{
-	color: #AAAAAA;
-}
-.default image {
-  height: 280rpx;
-  display: inline-block;
-}
-
+.default {  text-align: center;  position: fixed;  left: 50%;  top: 40%;  transform: translate(-50%, -50%);}.default text{	color: #AAAAAA;}.default image {  height: 280rpx;  display: inline-block;}
 </style>

+ 17 - 15
pages/myFamily/add/add.vue

@@ -1,5 +1,5 @@
 <template>
-	<view class="" style="background-color: #FFFFFF;">
+	<view class="" style="background-color: #FFFFFF;min-height: 100vh;">
 		<view class="form" style="padding-top: 20rpx;">
 				<u-form :border="true" ref="uForm" >
 					<u-form-item :required="true"  label="姓名:" prop="name" label-width="150">
@@ -21,7 +21,7 @@
 						<u-input :disabled="true" :border="true" type="text" v-model="nationalityName"></u-input>
 					</u-form-item>
 					<u-form-item :required="type==0?true:false"  label="证件号码" prop="id_card" label-width="150">
-						<u-input :border="true" placeholder="住户类型是业主时,必填" :trim="true"  maxlength="18" v-model="id_card" type="number"></u-input>
+						<u-input :border="true" placeholder="住户类型是业主时,必填" :trim="true"  maxlength="18" v-model="id_card" type="text"></u-input>
 					</u-form-item>
 					<u-form-item :required="true" label="性别" prop="sex" label-width="150">
 						<u-radio-group v-model="sex" >
@@ -77,7 +77,7 @@
 		  </view>
 		</view>
 		
-		<view style="background-color: #FFFFFF;">
+		<view style="background-color: #FFFFFF;" v-if="appletType==1">
 					<view class="form_group mb0" style="padding-left: 60rpx;">
 						 <view>
 							<text class="sex">人脸:</text>
@@ -94,7 +94,7 @@
 					  </upload-img>
 					  <view class="" style="color: #59a5f0;">
 						 <text class="cuIcon-camera padding-right-sm" style="font-size: 30rpx;"></text>
-						 <text v-if="$isEmpty(show_image_uri)">点击上传人</text>
+						 <text v-if="$isEmpty(show_image_uri)">点击上传人</text>
 						 <text style="margin-top: 40rpx;display: inline-block;" v-else>点击重新上传</text>
 					  </view>
 					</view>
@@ -135,9 +135,11 @@ export default {
 	},
 	data() {
 		return {
-			//默认点击弹出拍照模态框的是人面上传操作,1:护照,2:入境,3:人面
+			appletType:0,
+			
+			//默认点击弹出拍照模态框的是人脸上传操作,1:护照,2:入境,3:人脸
 			operaType:3,
-			//人面上传模态框,上传照片或拍照
+			//人上传模态框,上传照片或拍照
 			list: [{
 				text: '相册上传',
 			}, {
@@ -176,7 +178,7 @@ export default {
 				},
 				{
 					value: '1',
-					label: '成员'
+					label: '家属'
 				},
 				{
 					value: '2',
@@ -258,6 +260,8 @@ export default {
 		});
 	},
 	onShow() {
+		this.appletType=uni.getStorageSync("appletType")
+		
 		//获取当前页面的对象
 		let currPage=this.$util.getPageCtx()
 		if(!this.$isEmpty(currPage.data.image)){
@@ -299,7 +303,7 @@ export default {
 			console.log("operatype: ",this.operaType);
 			console.log("imgUrl",imgUrl)
 			var that = this;
-			//是否需要md5加密上传人
+			//是否需要md5加密上传人
 			let is_need_md5 = false;
 			if (this.operaType == 3) {
 			  is_need_md5 = true;
@@ -382,9 +386,7 @@ export default {
 		    app.globalData.autoFailHint("请填写手机");
 		    return;
 		  } //手机号码正则校验
-		  var telReg = /^(((13[0-9]{1})|(15[0-9]{1})|(18[0-9]{1})|(17[0-9]{1}))+\d{8})$/;
-		
-		  if (!telReg.test(tel)) {
+		  if (!this.$u.test.mobile(tel)) {
 		    app.globalData.autoFailHint("请填写正确手机号");
 		    return;
 		  }
@@ -433,13 +435,13 @@ export default {
 		  params['image_uri'] = that.image_uri;
 		  let face_code = that.face_code;
 		  params['face_code'] = that.face_code; //性别
-		
+		  params['oper_user_type']=0 //操作类型,业主操作
 		  params['sex'] = that.sex;
-		  params['member_id'] = app.globalData.member.id; //申请来源0-小程序添加 1-后台添加  2-后台导入 3-app添加
+		  params['member_id'] = app.globalData.member.id; 
 		
-		  params['create_type'] = '0'; ///申请的记录类型 0--认证类型 1--新增类型 2--编辑类型
+		  params['create_type'] = '0';//申请来源0-小程序添加 1-后台添加  2-后台导入 3-app添加
 		
-		  params['record_type'] = '1';
+		  params['record_type'] = '1'; ///申请的记录类型 0--认证类型 1--新增类型 2--编辑类型
 		  let operation = 'member/authentication';
 		  console.log(params)
 		  app.globalData.postRequest(params, operation, function (res) {

+ 50 - 45
pages/myFamily/addFamily/addFamily.vue

@@ -59,7 +59,7 @@
     </view>
      <view class="form_group">
       <text class="sex">证件号码:</text>
-      <input @input="id_cardFun" name="data_name" placeholder="住户类型是业主时,必填" placeholder-class="placeholder_style" type="text" value class="placeholder_style">
+		<input @input="id_cardFun" name="data_name" placeholder="住户类型是业主时,必填" placeholder-class="placeholder_style" type="text" value class="placeholder_style">
       </input>
     </view>
     <view class="form_group">
@@ -126,44 +126,46 @@
         </view>
       </view>
     </view>
-
-    <view class="form_group mb0">
-      <view>
-        <text class="red">*</text>
-        <text class="sex">人脸:</text>
-        <text class="tips">(人脸用于开门,请上传正脸图片)</text>
-      </view>
-    </view>
-
-    <view class>
-      <view class="upload_bg img_content">
-        <image :src="show_image_uri==null?'../../../image/face_bg.png':show_image_uri" class="upload_bgImg" mode="aspectFit"></image>
-        <view v-if="show_image_uri==null" @tap="chooseImage" data-index="3">
-          <view class="upload_btn">
-            <image src="http://139.9.103.171:1888/img/image/upload_btn.png"></image>
-          </view>
-          <view class="upload_text">
-            <text>点击上传人脸</text>
-          </view>
-        </view>
-        <view v-if="show_image_uri!=null" @tap="chooseImage" class="reUpload" data-index="3">
-          <image src="http://139.9.103.171:1888/img/image/picture.png" class="img_icon"></image>
-          <text>重新上传</text>
-        </view>
-      </view>
-      <view class="category">
-        <view v-for="(item, index) in iconArray" :key="index" class="category_item">
-          <view class="category_item_wrap" @tap="top" :data-index="item.index">
-            <view class="icon_wrap">
-              <image :src="item.iconUrl" class="index_icon"></image>
-            </view>
-            <view class="category_item_text">
-              <text>{{item.iconText}}</text>
-            </view>
-          </view>
-        </view>
-      </view>
-    </view>
+	<view class="" v-if="appletType==1">
+		<view class="form_group mb0">
+		  <view>
+		    <text class="red">*</text>
+		    <text class="sex">人脸:</text>
+		    <text class="tips">(人脸用于开门,请上传正脸图片)</text>
+		  </view>
+		</view>
+		
+		<view class >
+		  <view class="upload_bg img_content">
+		    <image :src="show_image_uri==null?'../../../image/face_bg.png':show_image_uri" class="upload_bgImg" mode="aspectFit"></image>
+		    <view v-if="show_image_uri==null" @tap="chooseImage" data-index="3">
+		      <view class="upload_btn">
+		        <image src="http://139.9.103.171:1888/img/image/upload_btn.png"></image>
+		      </view>
+		      <view class="upload_text">
+		        <text>点击上传人脸</text>
+		      </view>
+		    </view>
+		    <view v-if="show_image_uri!=null" @tap="chooseImage" class="reUpload" data-index="3">
+		      <image src="http://139.9.103.171:1888/img/image/picture.png" class="img_icon"></image>
+		      <text>重新上传</text>
+		    </view>
+		  </view>
+		  <view class="category">
+		    <view v-for="(item, index) in iconArray" :key="index" class="category_item">
+		      <view class="category_item_wrap" @tap="top" :data-index="item.index">
+		        <view class="icon_wrap">
+		          <image :src="item.iconUrl" class="index_icon"></image>
+		        </view>
+		        <view class="category_item_text">
+		          <text>{{item.iconText}}</text>
+		        </view>
+		      </view>
+		    </view>
+		  </view>
+		</view>
+	</view>
+    
 
   </form>
 
@@ -181,6 +183,8 @@ var app = getApp();
 export default {
   data() {
     return {
+	  appletType:0,
+	  
       name: null,
       //姓名
       tel: null,
@@ -188,7 +192,7 @@ export default {
       own_room_list: null,
       //房间列表下标
       own_room_list_index: 0,
-      typeArray: ['业主', '成员', '租户'],
+      typeArray: ['业主', '家属', '租户'],
       type: 0,
       nationalityArray: ['中国大陆', '中国香港/澳门', '中国台湾', '海外'],
       nationality: 0,
@@ -249,7 +253,10 @@ export default {
 
   components: {},
   props: {},
-
+  
+  onShow() {
+  	this.appletType=uni.getStorageSync("appletType")
+  },
   /**
    * 生命周期函数--监听页面加载
    */
@@ -382,10 +389,7 @@ export default {
         return;
       } //手机号码正则校验
 
-
-      var telReg = /^(((13[0-9]{1})|(15[0-9]{1})|(18[0-9]{1})|(17[0-9]{1}))+\d{8})$/;
-
-      if (!telReg.test(tel)) {
+      if (!this.$u.test.mobile(tel)) {
         app.globalData.autoFailHint("请填写正确手机号");
         return;
       }
@@ -469,6 +473,7 @@ page{
   background: #fff;
 }
 .edit_wrap {
+	background-color: #FFFFFF;
   font-size: 30rpx;
   padding: 0rpx 20rpx 120rpx;
   color: #333;

+ 151 - 0
pages/myFamily/apply-card.vue

@@ -0,0 +1,151 @@
+<template>
+	<view class="">
+		<view class="data" v-for="(item, index) in list" :key="index" >
+			<view class="top">
+				<view class="left">
+					<u-icon name="home" :size="30" color="rgb(94,94,94)"></u-icon>
+					<view class="title">{{item.residentialName}}-{{item.buildingName}}-{{item.unitName}}-{{item.roomName}}</view>
+				</view>
+				<view class="right">
+					<text v-if="item.checkState==0" class="text-warning">待审核</text>
+					<text v-if="item.checkState==1" class="text-green">已通过</text>
+					<text v-if="item.checkState==2" class="text-red">未通过</text>
+				</view>
+			</view>
+			<view class="item">
+				<view class="left">
+					<view  data-aid="undefined">
+					  <image v-if="!$isEmpty(item.imageUri)" mode="aspectFill" :src="item.imageUri"></image>
+					  <image v-else="" mode="aspectFill" src="http://139.9.103.171:1888/img/image/head.png"></image>
+					</view>
+					<view class="content" data-aid="undefined">
+						<view >
+							<text>姓名:{{item.name}}</text>
+							<text v-if="item.type==0"  class="cu-tag radius line-blue sm margin-left-20">业主</text>
+							<text v-if="item.type==1" class="cu-tag radius line-blue sm margin-left-20">家属</text>
+							<text v-if="item.type==2" class="cu-tag radius line-blue sm margin-left-20">租客</text>
+							<text v-if="item.type==3" class="cu-tag radius line-blue sm margin-left-20">访客</text>
+						</view>
+						<view >手机:{{item.tel}}</view>
+						<view >申请时间:{{item.createDate}}</view>
+						<view  v-if="item.checkState==2">
+						    <text>审核意见:</text>
+							<text >{{item.checkOpinion}}</text>
+						</view>
+					</view>
+				</view>
+			</view>
+			<view class="bottom" >
+				<view @click="edit(item)" v-if="item.checkState==2"  class="cu-btn line-btn round sm margin-right-sm" >
+					重新提交
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	props:{
+		list:Array
+	},
+	data() {
+		return {
+			
+		};
+	},
+	computed:{
+	    editShow() {
+			return item => {
+				//旧版本的逻辑,有点看不懂
+				if (item.checkState!=2) {
+					return false
+				}
+				this.vuex_own_room_list.forEach(val=>{
+					if (val.id==item.roomId) {
+						return true
+					}else{
+						return false
+					}
+				})
+			};
+		},
+	},
+	onLoad() {
+		
+	},
+	methods:{
+		edit(item){
+			let params={
+				apply_user_id:item.id,
+				name:item.name,
+				tel:item.tel,
+				room_name:item.roomName,
+				type:item.type,
+				id_card:item.idCard || '',
+				sex:item.sex,
+				nationality:item.nationality,
+				image_uri:item.imageUri,
+				passport_img_uri:item.passportImgUri || '',
+				entry_img_uri:item.entryImgUri
+			}
+			uni.navigateTo({
+				url:"/pages/myFamily/editApplyFamily/editApplyFamily"+this.$u.queryParams(params)
+			})
+		}
+	}
+};
+</script>
+
+<style lang="scss" scoped>
+.data {
+	background-color: #FFFFFF;
+	width: 720rpx;
+	margin:10rpx auto;
+	border-radius: 6rpx;
+	box-sizing: border-box;
+	padding: 20rpx;
+	font-size: 28rpx;
+	border-bottom: 1rpx solid #d1d1d1;
+	.top {
+		display: flex;
+		justify-content: space-between;
+		border-bottom: 1rpx dashed #DEDEDE;
+		padding-bottom: 20rpx;
+		.left {
+			display: flex;
+			align-items: center;
+			.title {
+				margin: 0 10rpx;
+				font-size: 32rpx;
+			}
+		}
+	}
+	.item {
+		display: flex;
+		flex-direction: row;
+		justify-content: space-between;
+		margin: 40rpx 0 20rpx 0;
+		.left {
+			display: flex;
+			image {
+				width: 130rpx;
+				height: 130rpx;
+				border-radius: 50%;
+			}
+			.content {
+				padding-left: 30rpx;
+				view{
+					padding-bottom: 16rpx;
+				}
+			}
+		}
+	}
+	.bottom {
+		display: flex;
+		margin-top: 20rpx;
+		justify-content: flex-end;
+		align-items: center;
+	}
+}
+</style>

+ 146 - 0
pages/myFamily/audit-card.vue

@@ -0,0 +1,146 @@
+<template>
+	<view >
+		<view class="data" v-for="(item, index) in list" :key="index" >
+			<view class="top">
+				<view class="left">
+					<u-icon name="home" :size="30" color="rgb(94,94,94)"></u-icon>
+					<view class="title">{{item.residentialName}}-{{item.buildingName}}-{{item.unitName}}-{{item.roomName}}</view>
+				</view>
+				<view class="right">
+					<text v-if="item.checkState==0" class="text-warning">待审核</text>
+					<text v-if="item.checkState==1" class="text-green">已通过</text>
+					<text v-if="item.checkState==2" class="text-red">未通过</text>
+				</view>
+			</view>
+			<view class="item">
+				<view class="left">
+					<view  data-aid="undefined">
+					  <image v-if="!$isEmpty(item.imageUri)" mode="aspectFill" :src="item.imageUri"></image>
+					  <image v-else="" mode="aspectFill" src="http://139.9.103.171:1888/img/image/head.png"></image>
+					</view>
+					<view class="content" data-aid="undefined">
+						<view >
+							<text>姓名:{{item.name}}</text>
+							<text v-if="item.type==0"  class="cu-tag radius line-blue sm margin-left-20">业主</text>
+							<text v-else-if="item.type==1" class="cu-tag radius line-blue sm margin-left-20">家属</text>
+							<text v-else-if="item.type==2" class="cu-tag radius line-blue sm margin-left-20">租客</text>
+							<text v-else-if="item.type==3" class="cu-tag radius line-blue sm margin-left-20">访客</text>
+						</view>
+						<view >手机:{{item.tel}}</view>
+						<view >申请时间:{{item.createDate}}</view>
+						<view  v-if="item.checkState==2">
+						    <text>审核意见:</text>
+							<text class="text-red">{{item.checkOpinion}}</text>
+						</view>
+					</view>
+				</view>
+			</view>
+			<view class="bottom" >
+				<view v-if="vuex_member.id!=item.memberId"  @click="audit(item)" class="cu-btn bg-blue round sm margin-right-sm" >
+				    去审核
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	props:{
+		list:Array
+	},
+	data() {
+		return {
+			
+		};
+	},
+	onLoad() {
+		
+	},
+	methods:{
+		audit(item){
+			let params={
+				apply_user_id:item.id,
+				name:item.name,
+				tel:item.tel,
+				residentialName:item.residentialName,
+				roomName:item.buildingName+"-"+item.unitName+"-"+item.roomName,
+				type:item.type,
+				id_card:item.idCard || '',
+				sex:item.sex,
+				nationality:item.nationality,
+				imageUri:item.imageUri || '',
+				passport_img_uri:item.passportImgUri || '',
+				entry_img_uri:item.entryImgUri || '',
+				waitAudit:true
+			}
+			uni.navigateTo({
+				url:"audit-detail/audit-detail"+this.$u.queryParams(params)
+			})
+			
+			// uni.navigateTo({
+			// 	url:"/pages/myFamily/editApplyFamily/editApplyFamily"+this.$u.queryParams(params)
+			// })
+		}
+	}
+};
+</script>
+
+<style lang="scss" scoped>
+
+.page{
+	background-color: #FFFFFF;
+	min-height: 100vh;
+}	
+
+.data {
+	background-color: #FFFFFF;
+	width: 720rpx;
+	margin:10rpx auto;
+	border-radius: 6rpx;
+	box-sizing: border-box;
+	padding: 20rpx;
+	font-size: 28rpx;
+	border-bottom: 1rpx solid #d1d1d1;
+	.top {
+		display: flex;
+		justify-content: space-between;
+		border-bottom: 1rpx dashed #DEDEDE;
+		padding-bottom: 20rpx;
+		.left {
+			display: flex;
+			align-items: center;
+			.title {
+				margin: 0 10rpx;
+				font-size: 32rpx;
+			}
+		}
+	}
+	.item {
+		display: flex;
+		flex-direction: row;
+		justify-content: space-between;
+		margin: 40rpx 0 20rpx 0;
+		.left {
+			display: flex;
+			image {
+				width: 130rpx;
+				height: 130rpx;
+				border-radius: 50%;
+			}
+			.content {
+				padding-left: 30rpx;
+				view{
+					padding-bottom: 16rpx;
+				}
+			}
+		}
+	}
+	.bottom {
+		display: flex;
+		margin-top: 20rpx;
+		justify-content: flex-end;
+		align-items: center;
+	}
+}
+</style>

+ 248 - 0
pages/myFamily/audit-detail/audit-detail.vue

@@ -0,0 +1,248 @@
+<template>
+	<view class="">
+		<u-toast ref="uToast"/>
+		<u-modal   :show-cancel-button="true"  @confirm="auditBtn(2)" title="审核意见" :mask-close-able="true" v-model="modelShow" >
+			<view class="slot-content" style="margin: 20rpx;">
+				<u-form label-width="150"  ref="uForm">
+					<u-form-item :border-bottom="false">
+						<u-input height="150" placeholder="请输入审核意见(选填)" v-model="checkOpinion" />
+					</u-form-item>
+				</u-form>
+			</view>
+		</u-modal>
+		<view class="data">
+			<view class="top">
+				<view class="left">
+					<view class="title ">
+						<text class="text-bold">住户姓名:</text>
+						<text>{{dataDetail.name}}</text>
+						<text v-if="dataDetail.sex==1" class="padding-left-10 text-sm ">[先生]</text>
+						<text v-if="dataDetail.sex==2" class="padding-left-10 text-sm ">[女士]</text>
+					</view>
+				</view>
+				<view class="right">
+					<text class="text-orange">待审核</text>
+				</view>
+			</view>
+			<view class="item">
+				<view class="left">
+					<view style="padding: 0 30rpx;">
+						<view class="flex justify-between">
+							<view >
+								<view class="content">
+									<text class="cuIcon-mobilefill text-blue text-bold"></text>
+									<text class="text-bold" style="padding: 0 10rpx;">手机号:</text>
+									<text>{{dataDetail.tel}}</text>
+									<image @click.stop="call(dataDetail.tel)" class="call" src="/static/call.png" ></image>
+								</view>
+								<view class="content">
+									<text class="cuIcon-circlefill text-blue text-bold"></text>
+									<text class="text-bold" style="padding: 0 10rpx;">小区:</text>
+									<text>{{dataDetail.residentialName}}</text>
+								</view>
+								<view class="content">
+									<text class="cuIcon-homefill text-blue text-bold"></text>
+									<text class="text-bold" style="padding: 0 10rpx;">房间号:</text>
+									<text>{{dataDetail.roomName}}</text>
+								</view>
+							</view>
+							<view >
+								<image @click="previewImg(dataDetail.imageUri)" style="width: 200rpx;height: 200rpx;" :src="dataDetail.imageUri?dataDetail.imageUri:'http://139.9.103.171:1888/miniofile/xlyq/face1.png'" ></image>
+								<view class="text-center text-blue padding-top-10">
+									(人脸图片)
+								</view>
+							</view>
+						</view>
+						<view class="content" style="padding-top: 20rpx;">
+							<text class="cuIcon-peoplefill text-blue"></text>
+							<text class="text-bold" style="padding: 0 10rpx;">住户类型:</text>
+							<text v-if="dataDetail.type==0">业主</text>
+							<text v-if="dataDetail.type==1">家属</text>
+							<text v-if="dataDetail.type==2">租户</text>
+						</view>
+						<view class="content">
+							<text class="cuIcon-infofill text-blue"></text>
+							<text class="text-bold" style="padding: 0 10rpx;">证件类型:</text>
+							<text v-if="dataDetail.nationality==0">身份证</text>
+							<text v-if="dataDetail.nationality==1">港澳居民往来内地通行证</text>
+							<text v-if="dataDetail.nationality==2">台湾居民往来大陆通行证</text>
+							<text v-if="dataDetail.nationality==3">护照</text>
+						</view>
+						<view class="content">
+							<text class="cuIcon-newsfill text-blue"></text>
+							<text class="text-bold" style="padding: 0 10rpx;">身份证号:</text>
+							<text >{{dataDetail.id_card || "未知"}}</text>
+						</view>
+						<view v-if="nationality==3" class="content">
+							<text class="cuIcon-picfill text-blue"></text>
+							<text class="text-bold" style="padding: 0 10rpx;">图片信息:</text>
+						</view>
+						<view v-if="nationality==3" class="cu-list grid col-2 no-border pab" >
+							<view class="cu-item">
+								<view class="flex justify-center align-center">
+									<image  :src="dataDetail.passportImgUri" style="width: 200rpx;height: 200rpx;"></image>
+								</view>
+								<text>护照图片</text>
+							</view>
+							<view class="cu-item">
+								<view class="flex justify-center align-center">
+									<image :src="dataDetail.entryImgUri"  style="width: 200rpx;height: 200rpx;"></image>
+								</view>
+								<text>入境证明</text>
+							</view>
+						</view>
+						<view v-if="nationality==3" class="" style="height: 150rpx;"></view>
+					</view>
+				</view>
+			</view>
+			<view class="footer-fixed" style="padding-bottom: 50rpx;z-index: 99;">
+				<view class="flex justify-around">
+					<view @click="auditBtn(1)" class="cu-btn round" style="padding: 40rpx;width: 45%;background-color: #61a300;color: #FFFFFF;">
+						通过
+					</view>
+					<view @click="fail"  class="cu-btn round" style="padding: 40rpx;width: 45%;background-color: #cf521b;color: #FFFFFF;">
+						不通过
+					</view>
+				</view>
+			</view>
+		
+		</view>
+	</view>
+</template>
+
+<script>
+var app=getApp()
+export default {
+	name: 'card',
+	data() {
+		return {
+			checkOpinion:'',
+			modelShow:false,
+			apply_user_id:'',
+			dataDetail:{}
+		};
+	},
+	onLoad(options) {
+		this.apply_user_id=options.apply_user_id,
+		this.dataDetail={
+			name:options.name,
+			tel:options.tel,
+			residentialName:options.residentialName,
+			roomName:options.roomName,
+			type:options.type,
+			id_card:options.id_card || '',
+			sex:options.sex,
+			nationality:options.nationality,
+			imageUri:options.imageUri || '',
+			passport_img_uri:options.passport_img_uri || '',
+			entry_img_uri:options.entry_img_uri || ''
+		}
+	},
+	onShow() {
+		
+	},
+	methods:{
+		call(phone){
+			uni.makePhoneCall({
+				phoneNumber:phone
+			})
+		},
+		previewImg(img){
+			let urls=[img]
+			uni.previewImage({
+				urls:urls
+			})
+		},
+		fail(){
+			this.modelShow=true
+		},
+		auditBtn(e) {
+		  let that = this;
+		  let params = {};
+		
+		  if (e == 2 && that.checkOpinion == '') {
+		    app.globalData.autoFailHint("请先填写审核意见");
+		    return;
+		  }
+		  params['id'] = that.apply_user_id;
+		  params['checkState'] = e;
+		  params['checkOpinion'] = that.checkOpinion;
+		  let operation = 'applyUser/updateCheckState';
+		  app.globalData.postRequest(params, operation, function (res) {
+		    //添加成功
+		    if (res.data.result_code==1) {
+				uni.showModal({
+					content:"操作成功",
+					showCancel:false,
+					success: (res) => {
+						if (res.confirm) {
+							uni.navigateBack({
+								delta:1
+							})
+						}
+					}
+				})
+		    } else {
+		      app.globalData.autoFailHint(res.data.msg);
+		    }
+		  });
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+page{
+	background-color: #FFFFFF;
+}
+view{
+	box-sizing: border-box;
+}
+	
+.bg-blue{
+	background-color: #59a5f0;
+	color: #FFFFFF;
+}
+.data {
+	background-color: #ffffff;
+	border-radius: 6rpx;
+	box-sizing: border-box;
+	padding:0 20rpx 20rpx;
+	font-size: 28rpx;
+	.top {
+		display: flex;
+		justify-content: space-between;
+		padding: 30rpx 0;
+		border-bottom: 1rpx solid #EEEEEE;
+		.left {
+			display: flex;
+			align-items: center;
+			.title {
+				margin: 0 10rpx;
+				font-size: 30rpx;
+			}
+		}
+		.right{
+			margin-right: 10rpx;
+		}
+	}
+	.item {
+		margin-bottom: 10rpx;
+		.content {
+			padding: 30rpx 0 ;
+			
+			.call{
+				width: 36rpx;
+				height: 36rpx;
+				margin-left: 10rpx;
+			}
+		}
+	}
+	.bottom {
+		display: flex;
+		margin-top: 30rpx;
+		justify-content: flex-end;
+		align-items: center;
+	}
+}
+</style>

+ 37 - 22
pages/myFamily/editApplyFamily/editApplyFamily.vue

@@ -1,5 +1,6 @@
 <template>
 <view class="container edit_wrap">
+	<u-toast ref="uToast" />
   <form :style="'pointer-events:' + (waitAudit?'none':'auto')">
     <view class="form_group">
       <text class="red">*</text>
@@ -120,15 +121,16 @@
 	  </view>
     </view>
 
-    <view class="form_group mb0">
-      <view>
-        <text class="red">*</text>
-        <text class="sex">人脸:</text>
-        <text class="tips">(人脸用于开门,请上传正脸图片)</text>
-      </view>
-    </view>
 
-    <view >
+
+    <view v-if="appletType==1">
+		<view class="form_group mb0">
+		  <view>
+		    <text class="red">*</text>
+		    <text class="sex">人脸:</text>
+		    <text class="tips">(人脸用于开门,请上传正脸图片)</text>
+		  </view>
+		</view>
 	  <view @click="show=true;operaType=3" style="margin: 30rpx 0 10rpx 0;display: flex;align-items: center;flex-direction: column;">
 	    <upload-img
 	  	  :width="$isEmpty(show_image_uri)?bgWidth:imgWidth"
@@ -139,7 +141,7 @@
 	    </upload-img>
 	    <view class="" style="color: #59a5f0;">
 	  	 <text class="cuIcon-camera padding-right-sm" style="font-size: 30rpx;"></text>
-	  	 <text v-if="$isEmpty(show_image_uri)">点击上传人</text>
+	  	 <text v-if="$isEmpty(show_image_uri)">点击上传人</text>
 	  	 <text style="margin-top: 40rpx;display: inline-block;" v-else>点击重新上传</text>
 	    </view>
 	  </view>
@@ -165,10 +167,10 @@
   
   <view  v-if="waitAudit"  class=" footer-fixed" >
 	  <view class="flex">
-	  	<view @tap="auditBtn" data-id="1" class="cu-btn  flex-sub  text-lg bg-red-btn" style="padding: 46rpx 0rpx;">
+	  	<view @click="auditBtn" data-id="1" class="cu-btn  flex-sub  text-lg bg-blue" style="padding: 46rpx 0rpx;">
 	  		审核通过
 	  	</view>
-		<view @tap="auditBtn" data-id="2" class="cu-btn  flex-sub  text-lg" style="padding: 46rpx 0;background-color: #fd9517;color: #FFFFFF;">
+		<view @click="auditBtn" data-id="2" class="cu-btn  flex-sub light text-lg bg-orange " style="padding: 46rpx 0;">
 			审核不通过
 		</view>
 	  </view>
@@ -188,9 +190,15 @@ export default {
 	},
   data() {
     return {
-		//默认点击弹出拍照模态框的是人面上传操作,1:护照,2:入境,3:人面
+		//操作类型,业主操作 0 其他
+		operUserType:'',
+		
+		// 小程序的审核状态
+		appletType:0,
+		
+		//默认点击弹出拍照模态框的是人脸上传操作,1:护照,2:入境,3:人脸
 		operaType:3,
-		//人面上传模态框,上传照片或拍照
+		//人上传模态框,上传照片或拍照
 		list: [{
 			text: '相册上传',
 		}, {
@@ -214,7 +222,7 @@ export default {
       //电话号码
       room_name: null,
       //房间名字
-      typeArray: ['业主', '成员', '租户'],
+      typeArray: ['业主', '家属', '租户'],
       type: 0,
       nationalityArray: ['中国大陆', '中国香港/澳门', '中国台湾', '海外'],
       nationality: 0,
@@ -277,6 +285,9 @@ export default {
    * 生命周期函数--监听页面加载
    */
   onLoad: function (options) {
+	  
+	  this.operUserType=options.operUserType
+	  
     let apply_user_id = options.apply_user_id;
     let name = options.name;
     let tel = options.tel;
@@ -346,6 +357,8 @@ export default {
     });
   },
   onShow() {
+	 this.appletType=uni.getStorageSync("appletType") 
+	 
   	//获取当前页面的对象
   	let currPage=this.$util.getPageCtx()
   	if(!this.$isEmpty(currPage.data.image)){
@@ -389,7 +402,7 @@ export default {
 		console.log("operatype: ",this.operaType);
 		console.log("imgUrl",imgUrl)
 		var that = this;
-		//是否需要md5加密上传人
+		//是否需要md5加密上传人
 		let is_need_md5 = false;
 		if (this.operaType == 3) {
 		  is_need_md5 = true;
@@ -496,11 +509,7 @@ export default {
         app.globalData.autoFailHint("请填写手机");
         return;
       } //手机号码正则校验
-
-
-      var telReg = /^(((13[0-9]{1})|(15[0-9]{1})|(18[0-9]{1})|(17[0-9]{1}))+\d{8})$/;
-
-      if (!telReg.test(tel)) {
+      if (!this.$u.test.mobile(tel)) {
         app.globalData.autoFailHint("请填写正确手机号");
         return;
       }
@@ -584,8 +593,13 @@ export default {
       let operation = 'applyUser/updateCheckState';
       app.globalData.postRequest(params, operation, function (res) {
         //添加成功
-        if (res.data.data) {
-          app.globalData.autoFailHint("审核成功");
+        if (res.data.result_code==1) {
+			that.$refs.uToast.show({
+				title: '审核成功',
+				type: 'success',
+				url: '/pages/myFamily/myFamily',
+				position:'top'
+			})
         } else {
           app.globalData.autoFailHint(res.data.msg);
         }
@@ -601,6 +615,7 @@ page{
   background: #fff;
 }
 .edit_wrap {
+	background-color: #FFFFFF;
   font-size: 30rpx;
   padding: 0rpx 20rpx 120rpx;
   color: #333;

+ 21 - 13
pages/myFamily/editFamily/editFamily.vue

@@ -1,5 +1,5 @@
 <template>
-	<view class="" style="background-color: #FFFFFF;">
+	<view class="" style="background-color: #FFFFFF;min-height: 100vh;">
 		<view class="form" style="padding-top: 20rpx;">
 				<u-form :border="true" ref="uForm" >
 					<u-form-item :required="true"  label="姓名:" prop="name" label-width="150">
@@ -21,7 +21,7 @@
 						<u-input :disabled="true" :border="true" type="text" v-model="nationalityName"></u-input>
 					</u-form-item>
 					<u-form-item :required="type==0?true:false"  label="证件号码" prop="id_card" label-width="150">
-						<u-input :border="true" placeholder="住户类型是业主时,必填" :trim="true"  maxlength="18" v-model="id_card" type="number"></u-input>
+						<u-input :border="true" placeholder="住户类型是业主时,必填" :trim="true"  maxlength="18" v-model="id_card" type="text"></u-input>
 					</u-form-item>
 					<u-form-item :required="true" label="性别" prop="sex" label-width="150">
 						<u-radio-group v-model="sex" >
@@ -76,7 +76,7 @@
 		  </view>
 		</view>
 		
-		<view style="background-color: #FFFFFF;">
+		<view style="background-color: #FFFFFF;" v-if="appletType==1">
 					<view class="form_group mb0" style="padding-left: 60rpx;">
 						 <view>
 							<text class="sex">人脸:</text>
@@ -94,7 +94,7 @@
 					  </upload-img>
 					  <view class="" style="color: #59a5f0;">
 						 <text class="cuIcon-camera padding-right-sm" style="font-size: 30rpx;"></text>
-						 <text v-if="$isEmpty(show_image_uri)">点击上传人</text>
+						 <text v-if="$isEmpty(show_image_uri)">点击上传人</text>
 						 <text style="margin-top: 40rpx;display: inline-block;" v-else>点击重新上传</text>
 					  </view>
 					</view>
@@ -133,9 +133,13 @@ export default {
 	},
 	data() {
 		return {
-			//默认点击弹出拍照模态框的是人面上传操作,1:护照,2:入境,3:人面
+			//操作类型,业主操作 0,其他
+			operUserType:'',
+			
+			appletType:0,
+			//默认点击弹出拍照模态框的是人脸上传操作,1:护照,2:入境,3:人脸
 			operaType:3,
-			//人面上传模态框,上传照片或拍照
+			//人上传模态框,上传照片或拍照
 			list: [{
 				text: '相册上传',
 			}, {
@@ -169,7 +173,7 @@ export default {
 			  	},
 			  	{
 			  		value: '1',
-			  		label: '成员'
+			  		label: '家属'
 			  	},
 			  	{
 			  		value: '2',
@@ -249,6 +253,10 @@ export default {
 		};
 	},
 	onShow() {
+		
+		this.appletType= uni.getStorageSync("appletType")
+		console.log(this.appletType);
+		
 		//获取当前页面的对象
 		let currPage=this.$util.getPageCtx()
 		if(!this.$isEmpty(currPage.data.image)){
@@ -258,6 +266,8 @@ export default {
 	onLoad: function (options) {
 		let that=this
 		
+		this.operUserType=options.operUserType
+		
 		let user_id = options.user_id;
 		let name = options.name;
 		let tel = options.tel;
@@ -371,7 +381,7 @@ export default {
 			console.log("operatype: ",this.operaType);
 			console.log("imgUrl",imgUrl)
 			var that = this;
-			//是否需要md5加密上传人
+			//是否需要md5加密上传人
 			let is_need_md5 = false;
 			if (this.operaType == 3) {
 			  is_need_md5 = true;
@@ -417,9 +427,7 @@ export default {
 		    app.globalData.autoFailHint("请填写手机");
 		    return;
 		  } //手机号码正则校验
-		  var telReg = /^(((13[0-9]{1})|(15[0-9]{1})|(18[0-9]{1})|(17[0-9]{1}))+\d{8})$/;
-		
-		  if (!telReg.test(tel)) {
+		  if (!this.$u.test.mobile(tel)) {
 		    app.globalData.autoFailHint("请填写正确手机号");
 		    return;
 		  }
@@ -466,8 +474,8 @@ export default {
 		    params['image_uri'] = that.image_uri;
 		    params['face_code'] = that.face_code;
 		  } //性别
-		
-		
+		  
+		  params['oper_user_type']=that.operUserType
 		  params['sex'] = that.sex; //添加了人脸
 		
 		  params['member_id'] = app.globalData.member.id; //申请来源0-小程序添加 1-后台添加  2-后台导入 3-app添加

+ 228 - 0
pages/myFamily/item.vue

@@ -0,0 +1,228 @@
+<template>
+	<view class="">
+		<u-toast ref="uToast"/>
+		<MeScroll  :up="up" :down="down" @up="upFn" :fixed="false" @down="downFn" @init="initMeScroll">
+			<!-- 审核通过 -->
+			<user-card @deleteUserById="deleteUserById" v-if="i==0" :list="userList" ></user-card>
+			<apply-card v-if="i==1" :list="applyList" ></apply-card>
+			<audit-card v-if="i==2" :list="auditList" ></audit-card>
+		</MeScroll>
+	</view>
+</template>
+<script>
+	import MeScroll from '@/comps/mescroll-body/mescroll-uni.vue'
+	import userCard from './user-card.vue'
+	import applyCard from './apply-card.vue'
+	import auditCard from './audit-card.vue'
+	var app=getApp()
+	export default {
+		name:'item',
+		components:{
+			MeScroll,userCard,applyCard,auditCard
+		},
+		props: {
+			//房间号
+			roomId:String,
+			
+			i: Number,
+			current:Number,
+			item:Object,
+			
+		},
+		data() {
+			return {
+				userList:[],//审核通过的数据列表
+				applyList:[],//申请记录的数据列表
+				auditList:[],//住户审核的数据列表
+				
+				isInit: false, // 是否初始化
+				list: [], // 列表数据
+				mescroll: null, // mescroll 对象
+				// 上拉配置参数
+				up: {
+					noMoreSize: 2, 
+					auto: false,
+					page: {
+						page: 0,
+						size: 10
+					}
+				},
+				// 下拉配置参数
+				down: {
+					use: false, 
+					auto: false
+				}
+			}
+		},
+		watch:{
+			current(val) {
+				if(!this.isInit && val === this.i) {
+					this.mescroll.resetUpScroll()
+				}
+			}
+		},
+		mounted() {
+			if(!this.isInit && this.i === 0) {
+				this.mescroll.resetUpScroll()
+			}
+		},
+		created() {
+			
+		},
+		methods: {
+			/**
+			 * 删除用户
+			 */
+			deleteUserById(id){
+				let that = this;
+				app.globalData.twoFailHint("确认删除该住户吗?", function () {
+				  let params = {
+						member_id:app.globalData.member.id,
+						user_id:id
+					};
+				  let operation = 'user/deleteUserById';
+				  app.globalData.postRequest(params, operation, function (res) {
+				    if (res.data.result_code == 1) {
+						that.$u.toast(res.data.result_msg)
+				        that.mescroll.resetUpScroll()
+				    } else {
+				      app.globalData.oneFailHint(res.data.result_msg);
+				    }
+				  });
+				});
+			},
+			/**
+			 * @param {Object} mescroll 初始化组件
+			 */
+			initMeScroll(mescroll) {
+				this.mescroll = mescroll
+			},
+			/**
+			 * @param {Object} mescroll 上拉回调
+			 */
+			upFn(mescroll) {
+				let that=this
+				if (this.i==0) {
+					//审核通过的用户列表
+					this.getUserListByMemberId(mescroll)
+				}else if (this.i==1) {
+					//申请记录列表
+					this.getApplyListByMemberId(mescroll)
+				}else if (this.i==2) {
+					//审核通过列表
+					this.getAuditListByMemberId(mescroll)
+				}
+			},
+			/**
+			 * 下拉回调
+			 * */
+			downFn(mescroll) {
+				setTimeout(()=>{
+					this.$u.toast('刷新成功')
+					this.mescroll.resetUpScroll()
+				},1500)
+			},
+			/**
+			 * 通过memberid获取审核通过标签页下的所有成员
+			 * @param {Object} mescroll
+			 */
+			getUserListByMemberId(mescroll) {
+				  let that = this;
+				  let params = {
+					  "pageNum":mescroll.num,
+					  "pageSize":mescroll.size,
+					  "member_id":getApp().globalData.member.id
+				  };
+				  if (!this.$isEmpty(this.roomId)) {
+				  	params.roomId=this.roomId
+				  }
+				  let operation = 'user/getAllUserByMemberId';
+				  try{
+				  	 getApp().globalData.postRequest(params, operation, function (res) {
+						 if (res.data.result_code == 1) {
+						 	 let data=res.data.list
+							 mescroll.endByPage(data.length, res.data.pages);
+							 if(mescroll.num == 1) that.userList = [];
+							 that.userList=that.userList.concat(data); //追加新数据
+						 }else{
+							 that.$u.toast(res.data.msg)
+							 mescroll.endErr();
+						 }
+				  	});
+				  }catch(e){
+						mescroll.endErr();
+				  }
+			},
+			/**
+			 * 获取申请列表
+			 */
+			getApplyListByMemberId(mescroll) {
+			  let that = this;
+			  let params = {
+				  "pageNum":mescroll.num,
+				  "pageSize":mescroll.size,
+				  "member_id":getApp().globalData.member.id
+			  };
+			  if (!this.$isEmpty(this.roomId)) {
+			  	params.roomId=this.roomId
+			  }
+			  let operation = 'applyUser/getAllApplyUserByMemberId';
+			  try{
+			  	getApp().globalData.postRequest(params, operation, function (res) {
+			  		 if (res.data.result_code == 1) {
+			  		 	 let data=res.data.list
+			  			 mescroll.endByPage(data.length, res.data.pages);
+			  			 if(mescroll.num == 1) that.applyList = [];
+			  			 that.applyList=that.applyList.concat(data); //追加新数据
+			  		 }else{
+			  			 that.$u.toast(res.data.msg)
+			  			 mescroll.endErr();
+			  		 }
+			  	})
+			  }catch(e){
+				  mescroll.endErr();
+			  }
+		   },
+		   /**
+			* 获取 住户审核列表
+			* @param {Object} mescroll
+			*/
+		   getAuditListByMemberId(mescroll) {
+			   let room_ids=[]
+			   this.vuex_own_room_list.forEach(item=>{
+				   room_ids.push(item.id)
+			   })
+			  let that = this;
+			  let params = {
+				  "pageNum":mescroll.num.toString(),
+				  "pageSize":mescroll.size.toString(),
+				  "check_states":0,//审核状态
+				  "room_ids":room_ids
+			  };
+			  let operation = 'applyUser/getAllApplyUserByRoomIds'
+			  try{
+				getApp().globalData.postRequest(params, operation, function (res) {
+					 if (res.data.result_code == 1) {
+						 let data=res.data.list
+						 mescroll.endByPage(data.length, res.data.pages);
+						 if(mescroll.num == 1) that.auditList = [];
+						 that.auditList=that.auditList.concat(data); //追加新数据
+					 }else{
+						 that.$u.toast(res.data.msg)
+						 mescroll.endErr();
+					 }
+				})
+			  }catch(e){
+				  mescroll.endErr();
+			  }
+		   },
+			
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	view{
+		box-sizing: border-box;
+	}
+</style>

+ 148 - 804
pages/myFamily/myFamily.vue

@@ -1,827 +1,171 @@
 <template>
-	<view :class="$isEmpty(user_list)||$isEmpty(apply_user_list)||$isEmpty(auditList)?'empty-wrap':''" :style="swiperCurrent==0?'':'background-color: #FFFFFF;'">
-		<view class="wrap">
-			<!-- <u-select v-model="show" :list="list"></u-select> -->
-			<u-sticky>
-				<u-tabs :list="list" font-size="29" active-color="#2f7ff5" inactive-color="#a6a6a6" bar-width="80"  :is-scroll="false" :current="current" @change="change"></u-tabs>
-			</u-sticky>
-			<swiper class="swiper-box" :current="swiperCurrent" @change="swiperChange" >
-				<swiper-item class="swiper-item">
-					<scroll-view v-if="!this.$isEmpty(user_list)" scroll-y style="height: 100%;width: 100%;" @scrolltolower="reachBottom">
-						<view class="cu-list menu" @click="locationShow=true">
-							<view class="cu-item" >
-								<view class="content">
-									<text >我的房屋</text>
-								</view>
-								<view class="action">
-									<text >{{selectLabel?selectLabel:room_list[0].name}}</text>
-									<text class="cuIcon-right padding-left-10"></text>
-								</view>
-							</view>
+	<view class="container">
+		<view class="tabs flex flex-direction u-border-bottom" >
+			<view class="flex">
+				<scroll-view scroll-x class="bg-white nav" :style="current==0?'width: 90%':''">
+					<view class="flex text-center">
+						<view class="cu-item flex-sub" :class="index==current?'text-blue text-xl text-bold':'text-lg'" v-for="(item,index) in tabs" :key="index" @tap="tabChange(index)" >
+							{{item.name}}
 						</view>
-						<view class="myFamily" >
-							<view class="data" v-for="(item, index) in user_list" :key="index"  style="border-bottom: 1rpx solid #b6b6b6;">
-								<view class="top">
-									<view class="left">
-										<u-icon name="home" :size="30" color="rgb(94,94,94)"></u-icon>
-										<view class="title">{{item.residentialName}}{{item.unitName}}{{item.roomName}}</view>
-									</view>
-								</view>
-								<view class="item">
-									<view class="left">
-										<view  data-aid="undefined">
-										  <image v-if="item.imageUri" mode="aspectFill" :src="item.imageUri">
-										  </image>
-										  <image v-if="item.imageUri==null" mode="aspectFill" src="http://139.9.103.171:1888/img/image/head.png">
-										  </image>
-										</view>
-										
-										<view class="content" data-aid="undefined">
-											<view >姓名:{{item.name}}</view>
-											<view >手机:{{item.tel}}</view>
-											<view >创建时间:{{item.createDate}}</view>
-											<view v-if="item.type==0">身份:业主</view>
-											<view v-if="item.type==1">身份:成员</view>
-											<view v-if="item.type==2">身份:租户</view>
-											<view v-if="item.type==3">身份:访客</view>
-										</view>
-									</view>
-								</view>
-								<view class="bottom" >
-									<navigator :url="'/pages/myFamily/editFamily/editFamily?user_id=' + item.id + '&name=' + item.name + '&tel=' + item.tel + '&room_name=' + item.roomName + '&type=' + item.type + '&id_card=' + (item.idCard==null?'':item.idCard) + '&sex=' + item.sex + '&nationality=' + (item.nationality==null?'':item.nationality) + '&image_uri=' + (item.imageUri==null?'':item.imageUri) + '&passport_img_uri=' + (item.passportImgUri==null?'':item.passportImgUri) + '&entry_img_uri=' + (item.entryImgUri==null?'':item.entryImgUri)" class="cu-btn line-btn round sm margin-right-sm"  @click.stop="">
-										编辑
-									</navigator>
-									<navigator :url="'/pages/myFamily/activateFace/activateFace?room_id=' + item.roomId + '&user_id=' + item.id + '&name=' + item.name + '&tel=' + item.tel + '&room_name=' + item.roomName + '&type=' + item.type + '&id_card=' + (item.idCard==null?'':item.idCard) + '&sex=' + item.sex + '&nationality=' + (item.nationality==null?'':item.nationality) + '&image_uri=' + (item.imageUri==null?'':item.imageUri) + '&passport_img_uri=' + (item.passportImgUri==null?'':item.passportImgUri) + '&entry_img_uri=' + (item.entryImgUri==null?'':item.entryImgUri)" class="cu-btn line-btn round sm margin-right-sm"  @click.stop="">
-										人面激活
-									</navigator>
-									<view v-if="item.isShowDelete"  :data-user_id="item.id" class="cu-btn bg-btn sm round" @click.stop="deleteUserById">
-										删除
-									</view>
-								</view>
-								
-							</view>
-						</view>
-					</scroll-view>
-					<view class="default" v-else>
-					   <image src="/static/common/empty.png" mode="heightFix"></image>
-					  <view>
-					    <text>没有相关信息</text>
-					  </view>
-					</view>
-				</swiper-item>
-				<swiper-item class="swiper-item">
-					<scroll-view v-if="!$isEmpty(apply_user_list)" scroll-y style="height: 100%;width: 100%;" @scrolltolower="reachBottom">
-						<view class="myFamily">
-						  <view style="border-bottom: 1rpx solid #b6b6b6;" v-for="(item, index) in apply_user_list" :key="index" class="nav_list" hover-class="none">
-						    <view class="flex">
-								<view class="margin-right-10 " style="margin-top: 2rpx;">
-									<u-icon name="home" :size="30" color="rgb(94,94,94)"></u-icon>
-								</view>
-						    	<view class="">
-									<text>{{item.residentialName}}{{item.unitName}}{{item.roomName}}</text>
-						    	</view>
-						    </view>
-						    <view class="myFamily_items">
-						      <view class="section_image" data-aid="undefined">
-						        <image style="border-radius: 50%;" v-if="item.imageUri" mode="aspectFill" :src="item.imageUri">
-						        </image>
-						        <image style="border-radius: 50%;" v-if="item.imageUri==null" mode="aspectFill" src="http://139.9.103.171:1888/img/image/head.png">
-						        </image>
-						      </view>
-						      <view class="section_cont" data-aid="undefined">
-						        <view class="section_cont_sub">
-						          <text>姓名:{{item.name}}</text>
-						          <text class="figure renter" v-if="item.type==0">身份:业主</text>
-						          <text class="figure renter" v-else-if="item.type==1">身份:成员</text>
-						          <text class="figure renter" v-else-if="item.type==2">身份:租客</text>
-						          <text class="figure renter" v-else-if="item.type==2">身份:访客</text>
-						        </view>
-						        <view class="section_cont_tel">
-						          <text>手机:{{item.tel}}</text>
-						        </view>
-						        <view class="section_cont_tel">
-						          <text>申请时间:{{item.createDate}}</text>
-						        </view>
-						        <view class="section_cont_tel">
-						          <view class data-aid="undefined">
-						            <text>状态:</text>
-						            <text v-if="item.checkState==0" class="col_red">待审核</text>
-						            <text v-if="item.checkState==1" class="col_red">审核通过</text>
-						            <text v-if="item.checkState==2" class="col_red">审核不通过</text>
-						          </view>
-						          <view class="section_cont_reason" v-if="item.checkState==2">
-						            <text class="reason">原因:<text class="col_red">{{item.checkOpinion}}</text> </text>
-						          </view>
-						        </view>
-						      </view>
-						      <!--审核不通过时显示 且会员有权限-->
-						      <view class="section_edit" v-if="item.isShow">
-						        <navigator :url="'/pages/myFamily/editApplyFamily/editApplyFamily?apply_user_id=' + item.id + '&name=' + item.name + '&tel=' + item.tel + '&room_name=' + item.roomName + '&type=' + item.type + '&id_card=' + (item.idCard==null?'':item.idCard) + '&sex=' + item.sex + '&nationality=' + item.nationality + '&image_uri=' + (item.imageUri==null?'':item.imageUri) + '&passport_img_uri=' + (item.passportImgUri==null?'':item.passportImgUri) + '&entry_img_uri=' + (item.entryImgUri==null?'':item.entryImgUri)">
-						          <view class="edit_btn">编辑</view>
-						        </navigator>
-						      </view>
-						    </view>
-						  </view>
-						</view>
-					</scroll-view>
-					<view class="default" v-else>
-						<image src="/static/common/empty.png" mode="heightFix"></image>
-					  <view>
-					    <text>没有相关信息</text>
-					  </view>
 					</view>
-				</swiper-item>
-				<swiper-item class="swiper-item">
-					<scroll-view  v-if="!$isEmpty(auditList)" scroll-y style="height: 100%;width: 100%;">
-						<view class="myFamily">
-						  <view style="border-bottom: 1rpx solid #b6b6b6;" v-for="(item, index) in auditList" :key="index" class="nav_list" hover-class="none">
-						    <view class="flex">
-						    	<view style="width: 40rpx;height: 40rpx;padding-right: 10rpx;">
-						    		<image src="http://139.9.103.171:1888/img/image/building.png"></image>
-						    	</view>
-						    	<view class="">
-									<text>{{item.residentialName}}{{item.unitName}}{{item.roomName}}</text>
-						    	</view>
-						    </view>
-						    <view class="myFamily_items">
-						      <view class="section_image" data-aid="undefined">
-						        <image v-if="item.imageUri" mode="aspectFill" :src="item.imageUri">
-						        </image>
-						        <image v-if="item.imageUri==null" mode="aspectFill" src="http://139.9.103.171:1888/img/image/head.png">
-						        </image>
-						      </view>
-						      <view class="section_cont" data-aid="undefined">
-						        <view class="section_cont_sub">
-						          <text>姓名:{{item.name}}</text>
-						          <text class="figure renter" v-if="item.type==0">身份:业主</text>
-						          <text class="figure renter" v-else-if="item.type==1">身份:成员</text>
-						          <text class="figure renter" v-else-if="item.type==2">身份:租客</text>
-						          <text class="figure renter" v-else-if="item.type==2">身份:访客</text>
-						        </view>
-						        <view class="section_cont_tel">
-						          <text>手机:{{item.tel}}</text>
-						        </view>
-						        <view class="section_cont_tel">
-						          <text>申请时间:{{item.createDate}}</text>
-						        </view>
-						        <view class="section_cont_tel">
-						          <view class data-aid="undefined">
-						            <text>状态:</text>
-						            <text v-if="item.checkState==0" class="col_red">待审核</text>
-						            <text v-if="item.checkState==1" class="col_red">审核通过</text>
-						            <text v-if="item.checkState==2" class="col_red">审核不通过</text>
-						          </view>
-						          <view class="section_cont_reason" v-if="item.checkState==2">
-						            <text class="reason">原因:<text class="col_red">{{item.checkOpinion}}</text> </text>
-						          </view>
-						        </view>
-						      </view>
-						      <!--审核不通过时显示 且会员有权限-->
-						      <view class="section_edit">
-						        <navigator :url="'/pages/myFamily/editApplyFamily/editApplyFamily?apply_user_id=' + item.id + '&name=' + item.name + '&tel=' + item.tel + '&room_name=' + item.roomName + '&type=' + item.type + '&id_card=' + (item.idCard==null?'':item.idCard) + '&sex=' + item.sex + '&nationality=' + item.nationality + '&image_uri=' + (item.imageUri==null?'':item.imageUri) + '&passport_img_uri=' + (item.passportImgUri==null?'':item.passportImgUri) + '&entry_img_uri=' + (item.entryImgUri==null?'':item.entryImgUri) + '&waitAudit=true'">
-						          <view class="edit_btn">审核</view>
-						        </navigator>
-						      </view>
-						    </view>
-						  </view>
-						</view>
+				</scroll-view>
+				<view v-if="current==0" @click="roomShow=!roomShow" class="flex justify-center padding-top-10 align-center" >
+					<u-icon name="home" size="32" top="-4"></u-icon>
+					<text class="text-blue padding-left-10 text-lg  text-bold">{{roomName}}</text>
+					<text v-if="!roomShow" class="text-blue cuIcon-unfold padding-left-10" ></text>
+					<text v-else class="text-blue cuIcon-fold padding-left-10" ></text>
+				</view>
+			</view>
+		</view>
+		<view style="height: 100%;">
+			<swiper style="height: 100%;" :current="current"  @change="swiperChange"
+				@animationfinish="animationfinish">
+				<swiper-item  v-for="(item, index) in tabs" :key="index">
+					<scroll-view scroll-y style="height: 100%;">
+						<item ref="mescrollItem" v-if="!$isEmpty(roomId)" :roomId="roomId" :i="index" :item="item" :current="current"></item>
 					</scroll-view>
-					<view class="default" v-else>
-					<image src="/static/common/empty.png" mode="heightFix"></image>
-					  <view>
-					    <text>没有相关信息</text>
-					  </view>
-					</view>
 				</swiper-item>
 			</swiper>
 		</view>
-		<u-select z-index="9999999"  mode="single-column"  value-name="id" label-name="name" v-model="locationShow" :list="room_list" @confirm="roomChange"></u-select>
-		<view style="height: 10rpx;"></view>
-		<view @click="add" v-if="!$isEmpty(own_room_list)" class=" footer-fixed" >
-			<view class="cu-btn  flex  text-lg bg-red-btn" style="padding: 46rpx 0;">
-				添加家人
-			</view>
-		</view>
+		
+		<u-picker mode="selector" v-model="roomShow"   :range="roomList" range-key="fullRoomName" @confirm="roomChange"></u-picker>
+		<!-- <u-select z-index="9999999"  mode="single-column"  value-name="id" label-name="name" v-model="roomShow" :list="roomList" @confirm="roomChange"></u-select> -->
 	</view>
 </template>
-
 <script>
-//获取app实例
-var app = getApp();
-var util = require("../../utils/util.js");
-	
-export default {
-	data() {
-		return {
-			locationShow:false,
-			selectLabel:'',
-	
-			//房屋成员
-			user_list: null,
-			//申请的认证列表
-			apply_user_list: null,
-			//审核列表
-			auditList: [],
-			//房屋id集合(业主)
-			room_ids: [],
-		
-			//当前用户业主身份的房子
-			own_room_list: null,
-			//当前显示住户信息下标
-			room_list_index: 0,
-			//复制一份user_list用于筛选房屋列表
-			user_lists: [] ,
-			room_list: "",
-			
-			list: [
-				{
-					name: '审核通过'
-				},
-				{
-					name: '申请记录'
-				},
-				{
-					name: '住户审核'
-				}
-			],
-			current: 0,
-			swiperCurrent: 0,
-		};
-	},
-	onLoad() {
-		this.initData()
-	},
-	onShow() {
-		this.initData()
-	},
-	methods: {
-		initData(){
-			this.geRoomByMemberId();
-			this.getAllApplyUserByMemberId();
-			this.getAllApplyUserByRoomIds();
-		},
-		add(){
-			uni.navigateTo({
-				url:"./add/add"
-			})
-		},
-		roomChange: function (e) {
-			// 选中的房屋 id
-		  let id=e[0].value
-		  //选中的房屋名字
-		  this.selectLabel=e[0].label
-		  //选中的房屋列表的下标
-		  let index= this.room_list.findIndex(value => value.id===id)
-		  
-		  // let index=e.detail.value
-		  let list = [];
-		  this.user_lists.map(item => {
-		    if (this.room_list[index].name == item.roomName) {
-		      list.push(item);
-		    }
-		  }); //拿到当前选择的房间,判断是否该显示添加家人按钮
-		
-		  let room_list = [];
-		  room_list.push(this.room_list[index]);
-		  this.ownRoomLists(room_list);
-		  this.setData({
-		    room_list_index: index,
-		    user_list: list
-		  });
-		  console.log(index)
-		},
-		//删除我的家人
-		deleteUserById: function (event) {
-		  let that = this;
-		  app.globalData.twoFailHint("确认删除该住户吗?", function () {
-		    //住户id
-		    let user_id = event.target.dataset.user_id;
-		    let params = {};
-		    params['member_id'] = app.globalData.member.id;
-		    params['user_id'] = user_id;
-		    let operation = 'user/deleteUserById';
-		    app.globalData.postRequest(params, operation, function (res) {
-		      console.info("获取成功" + res.data.result_msg); //删除成功
-		
-		      if (res.data.result_code == 1) {
-		        app.globalData.autoFailHint(res.data.result_msg, function () {
-		          //重新获取列表
-		          that.getAllUserByMemberId();
-		        });
-		      } else {
-		        app.globalData.oneFailHint(res.data.result_msg);
-		      }
-		    });
-		  });
-		},
-		//根据会员id获取我的家人列表
-		getAllUserByMemberId: function () {
-		  let that = this;
-		  let params = {
-			  "pageNum":0,
-			  "pageSize":15
-		  };
-		  params['member_id'] = app.globalData.member.id;
-		  let operation = 'user/getAllUserByMemberId';
-		  app.globalData.postRequest(params, operation, function (res) {
-		    //获取成功
-		    if (res.data.result_code == 1) {
-		      let user_list = res.data.list; //业主身份的房子
-		      let own_room_list = that.own_room_list;
-		
-		      for (let index in user_list) {
-		        user_list[index].createDate = util.formatTime(user_list[index].createDate);
-		        if (!that.$isEmpty(own_room_list)) {
-		          for (let i in own_room_list) {
-		            //该成员有被会员修改的权限
-		            if (user_list[index].roomId == own_room_list[i].id) {
-		              //显示 编辑
-		              user_list[index]['isShowEdit'] = true; //自己不能删除自己   且业主身份也不能删除
-		
-		              if (user_list[index].type != 0) {
-		                user_list[index]['isShowDelete'] = true;
-		              }
-		            }
-		          }
-		        } else {
-		          if (app.globalData.member.name == user_list[index].name) {
-		            //显示 编辑
-		            user_list[index]['isShowEdit'] = true;
-		          }
-		        }
-		      } //过滤掉其他小区,保留选择小区
-		      let list = [];
-		
-		      if (uni.getStorageSync('plotName')) {
-		        user_list.map(item => {
-		          if (item.residentialName == uni.getStorageSync('plotName')) {
-		            list.push(item);
-		          }
-		        });
-		      } else {
-		        list = user_list;
-		        list = user_lists;
-		      }
-		      that.setData({
-		        user_list: list,
-		        user_lists: list
-		      });
-		    } else {
-		      console.info("获取失败:" + res.data.result_msg);
-		    }
-		  });
-		},
-		//根据会员id获取我的申请列表
-		getAllApplyUserByMemberId: function () {
-		  let that = this;
-		  let params = {
-			  pageSize:200,
-			  pageNum:0
-		  };
-		  params['member_id'] = app.globalData.member.id;
-		  ;
-		  let operation = 'applyUser/getAllApplyUserByMemberId';
-		  app.globalData.postRequest(params, operation, function (res) {
-		    //获取成功
-		    if (res.data.result_code == 1) {
-		      //业主身份的房子
-		      let own_room_list = that.own_room_list;
-		      let apply_user_list = res.data.list;
-		      for (let index in apply_user_list) {
-		        //格式化日期
-		        apply_user_list[index].createDate = util.formatTime(apply_user_list[index].createDate);
-		
-		        if (!that.$isEmpty(own_room_list)) {
-		          //有业主身份的房子
-		          for (let i in own_room_list) {
-		            //该成员有被会员修改的权限--审核不通过
-		            if (apply_user_list[index].checkState == 2 && apply_user_list[index].roomId == own_room_list[i].id) {
-		              //显示 编辑
-		              apply_user_list[index]['isShow'] = true;
-		            }
-		          }
-		        } else {
-		          //没有业主身份的房子
-		          if (app.globalData.member.name == apply_user_list[index].name && apply_user_list[index].checkState == 2) {
-		            //显示 编辑
-		            apply_user_list[index]['isShow'] = true;
-		          }
-		        }
-		      } //过滤掉其他小区,保留选择小区
-		
-		
-		      let list = [];
-		
-		      if (uni.getStorageSync('plotName')) {
-		        apply_user_list.map(item => {
-		          if (item.residentialName == uni.getStorageSync('plotName')) {
-		            list.push(item);
-		          }
-		        });
-		      } else {
-		        list = apply_user_list;
-		      }
-		
-		      that.setData({
-		        apply_user_list: list
-		      });
-		    } else {
-		      console.info("获取失败:" + res.data.result_msg);
-		    }
-		  });
-		},
-		//根据会员id获取我的房屋列表
-		geRoomByMemberId() {
-		  let that = this;
-		  let params = {};
-		  params['member_id'] = app.globalData.member.id;
-		  console.log(params)
-		  let operation = 'estate/getRoomByMemberId';
-		  app.globalData.postRequest(params, operation, function (res) {
-		    console.info("获取成功" + res.data.result_msg); //获取成功
-		    // if (res.data.result_code == 1) {
-		    //   that.setData({
-		    //     room_list: res.data.list
-		    //   })
-		    //   app.room_list = res.data.list;
-		    //   that.ownRoomList(res.data.list);
-		    // }
-		
-		    if (res.data.result_code == 1) {
-		      let list = [];
-		      if (uni.getStorageSync('plotName')) {
-		        if (!that.$isEmpty(that.room_ids)) {
-		          that.room_ids.splice(0, that.room_ids.length);
-		        }
-		        res.data.list.map(item => {
-		          if (item.residentialName == uni.getStorageSync('plotName')) {
-		            list.push(item);
-		          }
-		          if (item.residentialName == uni.getStorageSync('plotName') && item.relationshipType == 0) {
-		            that.room_ids.push(item.id);
-		          }
-		        });
-		      } else {
-		        list = res.data.list;
-		      }
-		      that.setData({
-		        room_list: list,
-		        room_ids: that.room_ids //获取我的房屋id集合(业主)
-		
-		      });
-			  
-		      that.getAllApplyUserByRoomIds();
-		      app.globalData.room_list = list;
-		      that.ownRoomList(list);
-		    }
-		  });
-		},
-		//获取审核列表
-		getAllApplyUserByRoomIds: function () {
-		  let that = this;
-		  let params = {};
-		  params['room_ids'] = that.room_ids;
-		  params['check_states'] = "0";
-		  let operation = 'applyUser/getAllApplyUserByRoomIds';
-		  app.globalData.postRequest(params, operation, function (res) {
-		    //获取成功
-		    if (res.data.result_code == 1) {
-		      that.setData({
-		        auditList: res.data.list
-		      });
-		    }
-		  });
-		},
-		//业主身份的房子
-		ownRoomList: function (room_list) {
-		  let own_room_list = new Array();
-		
-		  for (let index in room_list) {
-		    //是业主身份的房子
-		    if (room_list[index].relationshipType == 0) {
-		      //业主
-		      own_room_list.push(room_list[index]);
-		    }
-		  }
-		
-		  this.setData({
-		    own_room_list: own_room_list
-		  }); //不常变数据保存到全局变量
-		
-		  app.globalData.own_room_list = own_room_list; //家庭成员
-		
-		  this.getAllUserByMemberId();
-		},
-		ownRoomLists: function (room_list) {
-		  let own_room_list = new Array();
-		
-		  for (let index in room_list) {
-		    //是业主身份的房子
-		    if (room_list[index].relationshipType == 0) {
-		      //业主
-		      own_room_list.push(room_list[index]);
-		    }
-		  }
-		
-		  this.setData({
-		    own_room_list: own_room_list
-		  }); //不常变数据保存到全局变量
-		
-		  app.globalData.own_room_list = own_room_list;
+	import item from "./item.vue"
+	export default {
+		components: {
+			item
 		},
-		reachBottom() {
-			
+		data() {
+			return {
+				roomShow:false,
+				roomList:[],
+				roomName:'',
+				roomId:'',
+				
+				scrollLeft:0,
+				current: 0,
+				swiperCurrent:0,
+				tabs: [
+					{
+						name: '审核通过',
+						value:0
+					},
+					{
+						name: '申请记录',
+						value:1
+					},
+					{
+						name: '住户审核',
+						value:2
+					}
+				],
+			}
 		},
-		// 轮播菜单
-		swiperChange(e){
-			this.swiperCurrent=e.detail.current
-			this.current = e.detail.current
-			// this.fetchData()
+		onShow(){
+			this.canReset && this.refreshMescroll()
+			this.canReset=true
 		},
-		change(index){
-			this.swiperCurrent=index
-			this.current = index;
-			// this.fetchData()
+		onLoad() {
+			this.getRoomByMemberId()
 		},
-		fetchData(){
-			let index=this.current
-			if(index==0){
-			  this.geRoomByMemberId();
-			}else if(index==1){
-			  this.getAllApplyUserByMemberId();
-			}else if(index==2){
-				this.getAllApplyUserByRoomIds();
-			}
+		methods:{
+			getRoomByMemberId(){
+				let that=this
+				let params={
+					member_id:getApp().globalData.member.id
+				}
+				let operation = 'estate/getRoomByMemberId';
+				getApp().globalData.postRequest(params,operation,(res)=>{
+					if (res.data.result_code == 1) {
+						that.roomList=res.data.list
+						
+						let own_room_list=[]
+						that.roomList.forEach(item=>{
+							if (item.relationshipType==0) {
+								own_room_list.push(item)
+							}
+							item.fullRoomName=item.buildingName+"-"+item.unitName+"-"+item.name
+							
+						})
+						//业主自己的房子
+						getApp().globalData.own_room_list = own_room_list;
+						that.$u.vuex('vuex_own_room_list',own_room_list)
+						
+						that.roomName=that.roomList[0].name
+						that.roomId=that.roomList[0].id
+						that.$u.vuex('vuex_relationshipType', that.roomList[0].relationshipType)
+					}
+				})
+			},
+			roomChange(e){
+				this.roomName=this.roomList[e[0]].name
+				this.roomId=this.roomList[e[0]].id
+				this.$u.vuex('vuex_relationshipType', this.roomList[e[0]].relationshipType)
+				this.refreshMescroll()
+			},
+			/**
+			 * 刷新列表
+			 */
+			refreshMescroll(){
+				let curMescroll = this.getMescroll(this.current)
+				this.$nextTick(function(){
+					curMescroll && curMescroll.resetUpScroll()
+				})
+			},
+			/**
+			 * 获取Mescroll对象
+			 * @param {Object} i
+			 */
+			getMescroll(i){
+				let mescrollItems = this.$refs.mescrollItem;
+				if(mescrollItems){
+					let item = mescrollItems[i]
+					if(item) return item.mescroll
+				}
+				return null
+			},
+			tabChange(index) {
+				this.current = index
+				// this.scrollLeft = (index - 1) * 60
+			},
+			swiperChange(e) {
+			  uni.pageScrollTo({
+			      scrollTop: 0,
+			      duration: 0
+			  });
+			  this.current = e.detail.current
+			  // this.scrollLeft = (this.current - 1) * 60
+			},
+			animationfinish({detail: { current }}) {
+				this.swiperCurrent = current;
+				this.current = current;
+			},
 		}
 	}
-};
 </script>
 
-
 <style lang="scss" scoped>
-.wrap {
-	display: flex;
-	flex-direction: column;
-	height: calc(100vh - var(--window-top));
-	width: 100%;
-}
-.swiper-box {
-	flex: 1;
-}
-.swiper-item {
-	height: 100%;
-}
-/* pages/myHome/myHome.wxss */
-.container {
-  height: 100%;
-  display: flex;
-  flex-direction: column;
-  box-sizing: border-box;
-}
-
-.nav {
-  display: flex;
-  height: 80rpx;
-  border-bottom: 1rpx solid #c7c7c9;
-  background: #fff;
-}
-
-.nav view {
-  flex: 1;
-  text-align: center;
-  height: 80rpx;
-  line-height: 80rpx;
-  color: #4a586a;
-}
-
-.nav view.active {
-  color: $base-btn-color;
-  border-bottom: 4rpx solid $base-btn-color;
-}
-
-.wrapCity {
-  flex: 1;
-}
-
-.wrapCity swiper {
-  height: 100%;
-}
-
-scroll-view {
-  display: box;
-  height: 100%;
-}
-
-.myFamily {
-  width: 100%;
-  padding-bottom: 100rpx;
-}
-
-.nav_list {
-  padding: 20rpx;
-  border-radius: 10rpx;
-  background: #fff;
-  margin-top: 4rpx;
-}
-
-.myFamily_items {
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  padding: 30rpx;
-  position: relative;
-}
-
-
-.myFamily_items .section_image {
-  width: 120rpx;
-  height: 120rpx;
-  position: absolute;
-  top: 50%;
-  transform: translate(0, -50%);
-}
-
-.myFamily_items .identity {
-  font-size: 24rpx;
-  color: #d24a58;
-}
-
-.myFamily_items .section_image image {
-  width: 100%;
-  height: 100%;
-}
-
-.myFamily_items .section_cont {
-  font-size: 24rpx;
-  color: #666;
-  margin-left: 140rpx;
-}
-
-.reason{
- text-overflow: -o-ellipsis-lastline;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  display: -webkit-box;
-  -webkit-line-clamp: 2;
-  -webkit-box-orient: vertical;
-}
-.myFamily_items .section_cont .section_cont_intro {
-  white-space: normal;
-  display: -webkit-box;
-  -webkit-line-clamp: 2;
-  -webkit-box-orient: vertical;
-}
-
-.myFamily_items .section_cont .section_cont_sub {
-  font-size: 28rpx;
-  line-height: 50rpx;
-  color: #666;
-  margin-bottom: 10rpx;
-}
-
-.myFamily_items .section_cont .section_cont_tel {
-  font-size: 28rpx;
-  color: #666;
-  line-height: 50rpx;
-  margin-bottom: 10rpx;
-}
-
-.myFamily_items .section_cont .section_cont_state {
-  font-size: 28rpx;
-}
-
-.myFamily_items .section_edit {
-  font-size: 24rpx;
-  position: absolute;
-  top: 50%;
-  right: 20rpx;
-  transform: translate(0, -50%);
-}
-
-.figure {
-  color: #d24a58;
-  border: 1px solid #d24a58;
-  border-radius: 6rpx;
-  font-size: 24rpx;
-  padding: 0 6rpx;
-  margin-left: 10rpx;
-}
-
-.figure.renter {
-  color: $base-btn-color;
-  border: 1px solid $base-btn-color;
-}
-.default {  text-align: center;  position: fixed;  left: 50%;  top: 40%;  transform: translate(-50%, -50%);}.default text{	color: #AAAAAA;}.default image {  height: 250rpx;  display: inline-block;}.empty-wrap{	background-color: #FFFFFF;	min-height: 100vh;}
-.edit_btn{
- background: $base-btn-color;
-  color: #fff;
-  height: 50rpx;
-  line-height: 50rpx;
-  border-radius: 10rpx;
-  padding:0 16rpx;
-  margin:6rpx;
-  text-align: center;
-}
-.delete_btn{
- background: #d24a58;
-  color: #fff;
-
-
-}
-.col_red{
-  color: #d24a58;
-}
-
-.form_group {
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  padding: 0 20rpx;
-  background: #fff;
-  line-height: 100rpx;
-  position: relative;
-  font-size: 26rpx;
-  border-bottom: 2rpx solid #ddd;
-  
-}
-.my-item .iconfont.arrow {
-  position: absolute;
-  right: 0;
-  top: 50%;
-  transform: translate(0, -50%);
-  font-size: 32rpx;
-  vertical-align: top;
- 
-}
-.my-item {
-  width: 100%;
-  position: relative;
-  background: #fff;
-  font-size: 28rpx;
-  box-sizing: border-box;
-}
-
-.my-item .status {
-  position: absolute;
-  right: 35rpx;
-  top: 50%;
-  transform: translate(0, -50%);
-  font-size: 28rpx;
-}
-
-
-	.cu-btn.sm {
-		padding: 0 24upx;
-		font-size: 24upx;
-		height: 54upx;
+	.text-xl{
+		font-size: 34rpx;
 	}
 	
-	.data {
+	.container {
+	  height: calc(100vh - 78rpx);
+	  background-color: #F6F6F6;
+	  padding: 78rpx 0rpx 0rpx;
+	 .tabs {
+	    position: fixed;
+	    top: -10rpx;
+		left: 0;
+		display: flex;
+		align-items: center;
+		width: 100%;
 		background-color: #FFFFFF;
-		width: 720rpx;
-		margin:10rpx auto;
-		border-radius: 6rpx;
 		box-sizing: border-box;
-		padding: 20rpx;
-		font-size: 28rpx;
-		.top {
-			display: flex;
-			justify-content: space-between;
-			.left {
-				display: flex;
-				align-items: center;
-				.title {
-					margin: 0 10rpx;
-					font-size: 32rpx;
-					font-weight: bold;
-				}
-			}
-		}
-		.item {
-			display: flex;
-			flex-direction: row;
-			justify-content: space-between;
-			margin: 40rpx 0 20rpx 0;
-			.left {
-				display: flex;
-				image {
-					width: 130rpx;
-					height: 130rpx;
-					border-radius: 50%;
-				}
-				.content {
-					padding-left: 30rpx;
-					view{
-						padding-bottom: 16rpx;
-					}
-				}
-			}
-		}
-		.bottom {
-			display: flex;
-			margin-top: 20rpx;
-			justify-content: flex-end;
-			align-items: center;
-		}
-	}
-</style>
+		z-index: 3;
+	  }
+}
+</style>

+ 847 - 0
pages/myFamily/myfamily1.vue

@@ -0,0 +1,847 @@
+<template>
+	<view :class="$isEmpty(user_list)||$isEmpty(apply_user_list)||$isEmpty(auditList)?'empty-wrap':''" :style="swiperCurrent==0?'':'background-color: #FFFFFF;'">
+		<view class="wrap">
+			<u-sticky >
+				<u-tabs :list="list" font-size="29" active-color="#2f7ff5" inactive-color="#a6a6a6" bar-width="80"  :is-scroll="false" :current="current" @change="change"></u-tabs>
+			</u-sticky>
+			<swiper class="swiper-box" :current="swiperCurrent" @change="swiperChange" >
+				<swiper-item class="swiper-item">
+					<scroll-view v-if="!this.$isEmpty(user_list)" scroll-y style="height: 100%" @scrolltolower="reachBottom">
+						<view class="cu-list menu" @click="locationShow=true">
+							<view class="cu-item" >
+								<view class="content">
+									<text >我的房屋</text>
+								</view>
+								<view class="action">
+									<text >{{selectLabel?selectLabel:room_list[0].name}}</text>
+									<text class="cuIcon-right padding-left-10"></text>
+								</view>
+							</view>
+						</view>
+						<view class="myFamily" >
+							<view class="data" v-for="(item, index) in user_list" :key="index"  style="border-bottom: 1rpx solid #b6b6b6;">
+								<view class="top">
+									<view class="left">
+										<u-icon name="home" :size="30" color="rgb(94,94,94)"></u-icon>
+										<view class="title">{{item.residentialName}}-{{item.buildingName}}-{{item.unitName}}-{{item.roomName}}</view>
+									</view>
+								</view>
+								<view class="item">
+									<view class="left">
+										<view  data-aid="undefined">
+										  <image v-if="item.imageUri" mode="aspectFill" :src="item.imageUri">
+										  </image>
+										  <image v-if="item.imageUri==null" mode="aspectFill" src="http://139.9.103.171:1888/img/image/head.png">
+										  </image>
+										</view>
+										
+										<view class="content" data-aid="undefined">
+											<view >姓名:{{item.name}}</view>
+											<view >手机:{{item.tel}}</view>
+											<view >创建时间:{{item.createDate}}</view>
+											<view v-if="item.type==0">身份:业主</view>
+											<view v-if="item.type==1">身份:成员</view>
+											<view v-if="item.type==2">身份:租户</view>
+											<view v-if="item.type==3">身份:访客</view>
+										</view>
+									</view>
+								</view>
+								<view class="bottom" >
+									<navigator :url="'/pages/myFamily/editFamily/editFamily?user_id=' + item.id + '&name=' + item.name + '&tel=' + item.tel + '&room_name=' + item.roomName + '&type=' + item.type + '&id_card=' + (item.idCard==null?'':item.idCard) + '&sex=' + item.sex + '&nationality=' + (item.nationality==null?'':item.nationality) + '&image_uri=' + (item.imageUri==null?'':item.imageUri) + '&passport_img_uri=' + (item.passportImgUri==null?'':item.passportImgUri) + '&entry_img_uri=' + (item.entryImgUri==null?'':item.entryImgUri)" class="cu-btn line-btn round sm margin-right-sm"  @click.stop="">
+										编辑
+									</navigator>
+									<!-- 小程序审核时,不要出现人脸功能 -->
+									<navigator v-if="appletType==1"  :url="'/pages/myFamily/activateFace/activateFace?room_id=' + item.roomId + '&user_id=' + item.id + '&name=' + item.name + '&tel=' + item.tel + '&room_name=' + item.roomName + '&type=' + item.type + '&id_card=' + (item.idCard==null?'':item.idCard) + '&sex=' + item.sex + '&nationality=' + (item.nationality==null?'':item.nationality) + '&image_uri=' + (item.imageUri==null?'':item.imageUri) + '&passport_img_uri=' + (item.passportImgUri==null?'':item.passportImgUri) + '&entry_img_uri=' + (item.entryImgUri==null?'':item.entryImgUri)" class="cu-btn line-btn round sm margin-right-sm"  @click.stop="">
+										人脸激活
+									</navigator>
+									<view v-if="item.isShowDelete"  :data-user_id="item.id" class="cu-btn bg-btn sm round" @click.stop="deleteUserById">
+										删除
+									</view>
+								</view>
+								
+							</view>
+						</view>
+					</scroll-view>
+					<view class="default" v-else>
+					   <image src="/static/common/empty.png" mode="heightFix"></image>
+					  <view>
+					    <text>没有相关信息</text>
+					  </view>
+					</view>
+				</swiper-item>
+				<swiper-item class="swiper-item">
+					<scroll-view v-if="!$isEmpty(apply_user_list)" scroll-y style="height: 100%" @scrolltolower="reachBottom">
+						<view class="myFamily">
+						  <view style="border-bottom: 1rpx solid #b6b6b6;" v-for="(item, index) in apply_user_list" :key="index" class="nav_list" hover-class="none">
+						    <view class="flex">
+								<view class="margin-right-10 " style="margin-top: 2rpx;">
+									<u-icon name="home" :size="30" color="rgb(94,94,94)"></u-icon>
+								</view>
+						    	<view class="">
+									<text>{{item.residentialName}}-{{item.buildingName}}-{{item.unitName}}-{{item.roomName}}</text>
+						    	</view>
+						    </view>
+						    <view class="myFamily_items">
+						      <view class="section_image" data-aid="undefined">
+						        <image style="border-radius: 50%;" v-if="item.imageUri" mode="aspectFill" :src="item.imageUri">
+						        </image>
+						        <image style="border-radius: 50%;" v-if="item.imageUri==null" mode="aspectFill" src="http://139.9.103.171:1888/img/image/head.png">
+						        </image>
+						      </view>
+						      <view class="section_cont" data-aid="undefined">
+						        <view class="section_cont_sub">
+						          <text>姓名:{{item.name}}</text>
+						          <text class="figure renter" v-if="item.type==0">业主</text>
+						          <text class="figure renter" v-else-if="item.type==1">家属</text>
+						          <text class="figure renter" v-else-if="item.type==2">租客</text>
+						          <text class="figure renter" v-else-if="item.type==2">访客</text>
+						        </view>
+						        <view class="section_cont_tel">
+						          <text>手机:{{item.tel}}</text>
+						        </view>
+						        <view class="section_cont_tel">
+						          <text>申请时间:{{item.createDate}}</text>
+						        </view>
+						        <view class="section_cont_tel">
+						          <view class data-aid="undefined">
+						            <text>状态:</text>
+						            <text v-if="item.checkState==0" class="col_red">待审核</text>
+						            <text v-if="item.checkState==1" class="col_red">审核通过</text>
+						            <text v-if="item.checkState==2" class="col_red">审核不通过</text>
+						          </view>
+						          <view class="section_cont_reason" v-if="item.checkState==2">
+						            <text class="reason">原因:<text class="col_red">{{item.checkOpinion}}</text> </text>
+						          </view>
+						        </view>
+						      </view>
+						      <!--审核不通过时显示 且会员有权限-->
+						      <view class="section_edit" v-if="item.isShow">
+						        <navigator :url="'/pages/myFamily/editApplyFamily/editApplyFamily?apply_user_id=' + item.id + '&name=' + item.name + '&tel=' + item.tel + '&room_name=' + item.roomName + '&type=' + item.type + '&id_card=' + (item.idCard==null?'':item.idCard) + '&sex=' + item.sex + '&nationality=' + item.nationality + '&image_uri=' + (item.imageUri==null?'':item.imageUri) + '&passport_img_uri=' + (item.passportImgUri==null?'':item.passportImgUri) + '&entry_img_uri=' + (item.entryImgUri==null?'':item.entryImgUri)">
+						          <view class="edit_btn">编辑</view>
+						        </navigator>
+						      </view>
+						    </view>
+						  </view>
+						</view>
+					</scroll-view>
+					<view class="default" v-else>
+						<image src="/static/common/empty.png" mode="heightFix"></image>
+					  <view>
+					    <text>没有相关信息</text>
+					  </view>
+					</view>
+				</swiper-item>
+				<swiper-item class="swiper-item">
+					<scroll-view  v-if="!$isEmpty(auditList)" scroll-y style="height: 100%;">
+						<view class="myFamily">
+						  <view style="border-bottom: 1rpx solid #b6b6b6;" v-for="(item, index) in auditList" :key="index" class="nav_list" hover-class="none">
+						    <view class="flex">
+						    	<view class="margin-right-10 " style="margin-top: 2rpx;">
+						    		<u-icon name="home" :size="30" color="rgb(94,94,94)"></u-icon>
+						    	</view>
+						    	<view class="">
+									<text>{{item.residentialName}}-{{item.buildingName}}-{{item.unitName}}-{{item.roomName}}</text>
+						    	</view>
+						    </view>
+						    <view class="myFamily_items">
+						      <view class="section_image" data-aid="undefined">
+						        <image v-if="item.imageUri" mode="aspectFill" :src="item.imageUri">
+						        </image>
+						        <image v-if="item.imageUri==null" mode="aspectFill" src="http://139.9.103.171:1888/img/image/head.png">
+						        </image>
+						      </view>
+						      <view class="section_cont" data-aid="undefined">
+						        <view class="section_cont_sub">
+						          <text>姓名:{{item.name}}</text>
+						          <text class="figure renter" v-if="item.type==0">身份:业主</text>
+						          <text class="figure renter" v-else-if="item.type==1">身份:家属</text>
+						          <text class="figure renter" v-else-if="item.type==2">身份:租客</text>
+						          <text class="figure renter" v-else-if="item.type==2">身份:访客</text>
+						        </view>
+						        <view class="section_cont_tel">
+						          <text>手机:{{item.tel}}</text>
+						        </view>
+						        <view class="section_cont_tel">
+						          <text>申请时间:{{item.createDate}}</text>
+						        </view>
+						        <view class="section_cont_tel">
+						          <view class data-aid="undefined">
+						            <text>状态:</text>
+						            <text v-if="item.checkState==0" class="col_red">待审核</text>
+						            <text v-if="item.checkState==1" class="col_red">审核通过</text>
+						            <text v-if="item.checkState==2" class="col_red">审核不通过</text>
+						          </view>
+						          <view class="section_cont_reason" v-if="item.checkState==2">
+						            <text class="reason">原因:<text class="col_red">{{item.checkOpinion}}</text> </text>
+						          </view>
+						        </view>
+						      </view>
+						      <!--审核不通过时显示 且会员有权限-->
+						      <view class="section_edit">
+						        <navigator :url="'/pages/myFamily/editApplyFamily/editApplyFamily?apply_user_id=' + item.id + '&name=' + item.name + '&tel=' + item.tel + '&room_name=' + item.roomName + '&type=' + item.type + '&id_card=' + (item.idCard==null?'':item.idCard) + '&sex=' + item.sex + '&nationality=' + item.nationality + '&image_uri=' + (item.imageUri==null?'':item.imageUri) + '&passport_img_uri=' + (item.passportImgUri==null?'':item.passportImgUri) + '&entry_img_uri=' + (item.entryImgUri==null?'':item.entryImgUri) + '&waitAudit=true'">
+						          <view class="edit_btn">审核</view>
+						        </navigator>
+						      </view>
+						    </view>
+						  </view>
+						</view>
+					</scroll-view>
+					<view class="default" v-else>
+					<image src="/static/common/empty.png" mode="heightFix"></image>
+					  <view>
+					    <text>没有相关信息</text>
+					  </view>
+					</view>
+				</swiper-item>
+			</swiper>
+		</view>
+		<u-select z-index="9999999"  mode="single-column"  value-name="id" label-name="name" v-model="locationShow" :list="room_list" @confirm="roomChange"></u-select>
+		<view style="height: 10rpx;"></view>
+		<view @click="add" v-if="!$isEmpty(own_room_list)" class=" footer-fixed" >
+			<view class="cu-btn  flex  text-lg bg-red-btn" style="padding: 46rpx 0;">
+				添加家人
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+//获取app实例
+var app = getApp();
+var util = require("../../utils/util.js")
+export default {
+	name: '',
+	data() {
+		return {
+			appletType:0,
+			
+			locationShow:false,
+			selectLabel:'',
+	
+			//房屋成员
+			user_list: null,
+			//申请的认证列表
+			apply_user_list: null,
+			//审核列表
+			auditList: [],
+			//房屋id集合(业主)
+			room_ids: [],
+		
+			//当前用户业主身份的房子
+			own_room_list: null,
+			//当前显示住户信息下标
+			room_list_index: 0,
+			//复制一份user_list用于筛选房屋列表
+			user_lists: [] ,
+			room_list: "",
+			
+			list: [
+				{
+					name: '审核通过'
+				},
+				{
+					name: '申请记录'
+				},
+				{
+					name: '住户审核'
+				}
+			],
+			current: 0,
+			swiperCurrent: 0,
+		};
+	},
+	onLoad() {
+		
+	},
+	onShow() {
+		this.appletType=uni.getStorageSync("appletType")
+		this.initData()
+	},
+	methods:{
+		initData(){
+			this.geRoomByMemberId();
+			this.getAllApplyUserByMemberId();
+			// this.getAllApplyUserByRoomIds();
+		},
+		add(){
+			uni.navigateTo({
+				url:"./add/add"
+			})
+		},
+		roomChange: function (e) {
+			// 选中的房屋 id
+		  let id=e[0].value
+		  //选中的房屋名字
+		  this.selectLabel=e[0].label
+		  //选中的房屋列表的下标
+		  let index= this.room_list.findIndex(value => value.id===id)
+		  
+		  // let index=e.detail.value
+		  let list = [];
+		  this.user_lists.map(item => {
+		    if (this.room_list[index].name == item.roomName) {
+		      list.push(item);
+		    }
+		  }); //拿到当前选择的房间,判断是否该显示添加家人按钮
+		
+		  let room_list = [];
+		  room_list.push(this.room_list[index]);
+		  this.ownRoomLists(room_list);
+		  this.setData({
+		    room_list_index: index,
+		    user_list: list
+		  });
+		  console.log(index)
+		},
+		//删除我的家人
+		deleteUserById: function (event) {
+		  let that = this;
+		  app.globalData.twoFailHint("确认删除该住户吗?", function () {
+		    //住户id
+		    let user_id = event.target.dataset.user_id;
+		    let params = {};
+		    params['member_id'] = app.globalData.member.id;
+		    params['user_id'] = user_id;
+		    let operation = 'user/deleteUserById';
+		    app.globalData.postRequest(params, operation, function (res) {
+		      console.info("获取成功" + res.data.result_msg); //删除成功
+		
+		      if (res.data.result_code == 1) {
+		        app.globalData.autoFailHint(res.data.result_msg, function () {
+		          //重新获取列表
+		          that.getAllUserByMemberId();
+		        });
+		      } else {
+		        app.globalData.oneFailHint(res.data.result_msg);
+		      }
+		    });
+		  });
+		},
+		//根据会员id获取我的家人列表
+		getAllUserByMemberId: function () {
+		  let that = this;
+		  let params = {
+			  "pageNum":"0",
+			  "pageSize":"15"
+		  };
+		  params['member_id'] = app.globalData.member.id;
+		  let operation = 'user/getAllUserByMemberId';
+		  app.globalData.postRequest(params, operation, function (res) {
+		    //获取成功
+		    if (res.data.result_code == 1) {
+		      let user_list = res.data.list; //业主身份的房子
+		      let own_room_list = that.own_room_list;
+		
+		      for (let index in user_list) {
+		        user_list[index].createDate = util.formatTime(user_list[index].createDate);
+		        if (!that.$isEmpty(own_room_list)) {
+		          for (let i in own_room_list) {
+		            //该成员有被会员修改的权限
+		            if (user_list[index].roomId == own_room_list[i].id) {
+		              //显示 编辑
+		              user_list[index]['isShowEdit'] = true; //自己不能删除自己   且业主身份也不能删除
+		
+		              if (user_list[index].type != 0) {
+		                user_list[index]['isShowDelete'] = true;
+		              }
+		            }
+		          }
+		        } else {
+		          if (app.globalData.member.name == user_list[index].name) {
+		            //显示 编辑
+		            user_list[index]['isShowEdit'] = true;
+		          }
+		        }
+		      } //过滤掉其他小区,保留选择小区
+		      let list = [];
+		
+		      if (uni.getStorageSync('plotName')) {
+		        user_list.map(item => {
+		          if (item.residentialName == uni.getStorageSync('plotName')) {
+		            list.push(item);
+		          }
+		        });
+		      } else {
+		        list = user_list;
+		        list = user_lists;
+		      }
+		      that.setData({
+		        user_list: list,
+		        user_lists: list
+		      });
+		    } else {
+		      console.info("获取失败:" + res.data.result_msg);
+		    }
+		  });
+		},
+		//根据会员id获取我的申请列表
+		getAllApplyUserByMemberId: function () {
+		  let that = this;
+		  let params = {
+			  pageSize:200,
+			  pageNum:0
+		  };
+		  params['member_id'] = app.globalData.member.id;
+		  ;
+		  let operation = 'applyUser/getAllApplyUserByMemberId';
+		  app.globalData.postRequest(params, operation, function (res) {
+		    //获取成功
+		    if (res.data.result_code == 1) {
+		      //业主身份的房子
+		      let own_room_list = that.own_room_list;
+		      let apply_user_list = res.data.list;
+		      for (let index in apply_user_list) {
+		        //格式化日期
+		        apply_user_list[index].createDate = util.formatTime(apply_user_list[index].createDate);
+		
+		        if (!that.$isEmpty(own_room_list)) {
+		          //有业主身份的房子
+		          for (let i in own_room_list) {
+		            //该成员有被会员修改的权限--审核不通过
+		            if (apply_user_list[index].checkState == 2 && apply_user_list[index].roomId == own_room_list[i].id) {
+		              //显示 编辑
+		              apply_user_list[index]['isShow'] = true;
+		            }
+		          }
+		        } else {
+		          //没有业主身份的房子
+		          if (app.globalData.member.name == apply_user_list[index].name && apply_user_list[index].checkState == 2) {
+		            //显示 编辑
+		            apply_user_list[index]['isShow'] = true;
+		          }
+		        }
+		      } //过滤掉其他小区,保留选择小区
+		
+		
+		      let list = [];
+		
+		      if (uni.getStorageSync('plotName')) {
+		        apply_user_list.map(item => {
+		          if (item.residentialName == uni.getStorageSync('plotName')) {
+		            list.push(item);
+		          }
+		        });
+		      } else {
+		        list = apply_user_list;
+		      }
+		
+		      that.setData({
+		        apply_user_list: list
+		      });
+		    } else {
+		      console.info("获取失败:" + res.data.result_msg);
+		    }
+		  });
+		},
+		//根据会员id获取我的房屋列表
+		geRoomByMemberId() {
+		  let that = this;
+		  let params = {};
+		  params['member_id'] = app.globalData.member.id;
+		  console.log(params)
+		  let operation = 'estate/getRoomByMemberId';
+		  app.globalData.postRequest(params, operation, function (res) {
+		    console.info("获取成功" + res.data.result_msg); //获取成功
+		    // if (res.data.result_code == 1) {
+		    //   that.setData({
+		    //     room_list: res.data.list
+		    //   })
+		    //   app.room_list = res.data.list;
+		    //   that.ownRoomList(res.data.list);
+		    // }
+		
+		    if (res.data.result_code == 1) {
+		      let list = [];
+		      if (uni.getStorageSync('plotName')) {
+		        if (!that.$isEmpty(that.room_ids)) {
+		          that.room_ids.splice(0, that.room_ids.length);
+		        }
+		        res.data.list.map(item => {
+		          if (item.residentialName == uni.getStorageSync('plotName')) {
+		            list.push(item);
+		          }
+		          if (item.residentialName == uni.getStorageSync('plotName') && item.relationshipType == 0) {
+		            that.room_ids.push(item.id);
+		          }
+		        });
+		      } else {
+		        list = res.data.list;
+		      }
+		      that.setData({
+		        room_list: list,
+		        room_ids: that.room_ids //获取我的房屋id集合(业主)
+		
+		      });
+			  
+		      that.getAllApplyUserByRoomIds();
+		      app.globalData.room_list = list;
+		      that.ownRoomList(list);
+		    }
+		  });
+		},
+		//获取审核列表
+		getAllApplyUserByRoomIds: function () {
+		  let that = this;
+		  let params = {
+			  pageSize:"200",
+			  pageNum:"0"
+		  };
+		  params['room_ids'] = that.room_ids;
+		  params['check_states'] = "0";
+		  
+		  let operation = 'applyUser/getAllApplyUserByRoomIds';
+		  app.globalData.postRequest(params, operation, function (res) {
+		    //获取成功
+		    if (res.data.result_code == 1) {
+		      that.setData({
+		        auditList: res.data.list
+		      });
+		    }
+		  });
+		},
+		//业主身份的房子
+		ownRoomList: function (room_list) {
+		  let own_room_list = new Array();
+		
+		  for (let index in room_list) {
+		    //是业主身份的房子
+		    if (room_list[index].relationshipType == 0) {
+		      //业主
+		      own_room_list.push(room_list[index]);
+		    }
+		  }
+		  this.setData({
+		    own_room_list: own_room_list
+		  }); //不常变数据保存到全局变量
+		
+		  app.globalData.own_room_list = own_room_list; //家庭成员
+		
+		  this.getAllUserByMemberId();
+		},
+		ownRoomLists: function (room_list) {
+		  let own_room_list = new Array();
+		
+		  for (let index in room_list) {
+		    //是业主身份的房子
+		    if (room_list[index].relationshipType == 0) {
+		      //业主
+		      own_room_list.push(room_list[index]);
+		    }
+		  }
+		
+		  this.setData({
+		    own_room_list: own_room_list
+		  }); //不常变数据保存到全局变量
+		
+		  app.globalData.own_room_list = own_room_list;
+		},
+		reachBottom() {
+			
+		},
+		// 轮播菜单
+		swiperChange(e){
+			this.swiperCurrent=e.detail.current
+			this.current = e.detail.current
+			// this.fetchData()
+		},
+		change(index){
+			this.swiperCurrent=index
+			this.current = index;
+			// this.fetchData()
+		},
+		fetchData(){
+			let index=this.current
+			if(index==0){
+			  this.geRoomByMemberId();
+			}else if(index==1){
+			  this.getAllApplyUserByMemberId();
+			}else if(index==2){
+				this.getAllApplyUserByRoomIds();
+			}
+		}
+	}
+};
+</script>
+<style lang="scss">
+	.wrap {
+		display: flex;
+		flex-direction: column;
+		height: calc(100vh - var(--window-top));
+		width: 100%;
+	}
+	
+	.container {
+		  width: 100%;
+		  height: calc(100vh);
+		  background-color: #F6F6F6;
+		  padding: 90rpx 0rpx 0rpx;
+		 .tabs {
+			 height: 90rpx;
+		    position: fixed;
+		    top: 0rpx;
+			left: 0;
+			right: 0;
+			width: 100%;
+			z-index: 3;
+		  }
+	}
+	
+	
+	.swiper-box {
+		flex: 1
+	}
+	.swiper-item {
+		height: 100%;
+	}
+	.container {
+	  height: 100%;
+	  display: flex;
+	  flex-direction: column;
+	  box-sizing: border-box;
+	}
+	
+	.nav {
+	  display: flex;
+	  height: 80rpx;
+	  border-bottom: 1rpx solid #c7c7c9;
+	  background: #fff;
+	}
+	
+	.nav view {
+	  flex: 1;
+	  text-align: center;
+	  height: 80rpx;
+	  line-height: 80rpx;
+	  color: #4a586a;
+	}
+	
+	.nav view.active {
+	  color: $base-btn-color;
+	  border-bottom: 4rpx solid $base-btn-color;
+	}
+	
+	.wrapCity {
+	  flex: 1;
+	}
+	
+	.wrapCity swiper {
+	  height: 100%;
+	}
+	
+	scroll-view {
+	  display: box;
+	  height: 100%;
+	}
+	
+	.myFamily {
+	  width: 100%;
+	  padding-bottom: 100rpx;
+	}
+	
+	.nav_list {
+	  padding: 20rpx;
+	  border-radius: 10rpx;
+	  background: #fff;
+	  margin-top: 4rpx;
+	}
+	
+	.myFamily_items {
+	  display: flex;
+	  flex-direction: row;
+	  justify-content: space-between;
+	  padding: 30rpx;
+	  position: relative;
+	}
+	
+	
+	.myFamily_items .section_image {
+	  width: 120rpx;
+	  height: 120rpx;
+	  position: absolute;
+	  top: 50%;
+	  transform: translate(0, -50%);
+	}
+	
+	.myFamily_items .identity {
+	  font-size: 24rpx;
+	  color: #d24a58;
+	}
+	
+	.myFamily_items .section_image image {
+	  width: 100%;
+	  height: 100%;
+	}
+	
+	.myFamily_items .section_cont {
+	  font-size: 24rpx;
+	  color: #666;
+	  margin-left: 140rpx;
+	}
+	
+	.reason{
+	 text-overflow: -o-ellipsis-lastline;
+	  overflow: hidden;
+	  text-overflow: ellipsis;
+	  display: -webkit-box;
+	  -webkit-line-clamp: 2;
+	  -webkit-box-orient: vertical;
+	}
+	.myFamily_items .section_cont .section_cont_intro {
+	  white-space: normal;
+	  display: -webkit-box;
+	  -webkit-line-clamp: 2;
+	  -webkit-box-orient: vertical;
+	}
+	
+	.myFamily_items .section_cont .section_cont_sub {
+	  font-size: 28rpx;
+	  line-height: 50rpx;
+	  color: #666;
+	  margin-bottom: 10rpx;
+	}
+	
+	.myFamily_items .section_cont .section_cont_tel {
+	  font-size: 28rpx;
+	  color: #666;
+	  line-height: 50rpx;
+	  margin-bottom: 10rpx;
+	}
+	
+	.myFamily_items .section_cont .section_cont_state {
+	  font-size: 28rpx;
+	}
+	
+	.myFamily_items .section_edit {
+	  font-size: 24rpx;
+	  position: absolute;
+	  top: 50%;
+	  right: 20rpx;
+	  transform: translate(0, -50%);
+	}
+	
+	.figure {
+	  color: #d24a58;
+	  border: 1px solid #d24a58;
+	  border-radius: 6rpx;
+	  font-size: 24rpx;
+	  padding: 0 6rpx;
+	  margin-left: 10rpx;
+	}
+	
+	.figure.renter {
+	  color: $base-btn-color;
+	  border: 1px solid $base-btn-color;
+	}
+	.default {  text-align: center;  position: fixed;  left: 50%;  top: 40%;  transform: translate(-50%, -50%);}.default text{	color: #AAAAAA;}.default image {  height: 250rpx;  display: inline-block;}.empty-wrap{	background-color: #FFFFFF;	min-height: 100vh;}
+	.edit_btn{
+	 background: $base-btn-color;
+	  color: #fff;
+	  height: 50rpx;
+	  line-height: 50rpx;
+	  border-radius: 10rpx;
+	  padding:0 16rpx;
+	  margin:6rpx;
+	  text-align: center;
+	}
+	.delete_btn{
+	 background: #d24a58;
+	  color: #fff;
+	
+	
+	}
+	.col_red{
+	  color: #d24a58;
+	}
+	
+	.form_group {
+	  display: flex;
+	  flex-direction: row;
+	  justify-content: space-between;
+	  padding: 0 20rpx;
+	  background: #fff;
+	  line-height: 100rpx;
+	  position: relative;
+	  font-size: 26rpx;
+	  border-bottom: 2rpx solid #ddd;
+	  
+	}
+	.my-item .iconfont.arrow {
+	  position: absolute;
+	  right: 0;
+	  top: 50%;
+	  transform: translate(0, -50%);
+	  font-size: 32rpx;
+	  vertical-align: top;
+	 
+	}
+	.my-item {
+	  width: 100%;
+	  position: relative;
+	  background: #fff;
+	  font-size: 28rpx;
+	  box-sizing: border-box;
+	}
+	
+	.my-item .status {
+	  position: absolute;
+	  right: 35rpx;
+	  top: 50%;
+	  transform: translate(0, -50%);
+	  font-size: 28rpx;
+	}
+	
+	
+		.cu-btn.sm {
+			padding: 0 24upx;
+			font-size: 24upx;
+			height: 54upx;
+		}
+		
+		.data {
+			background-color: #FFFFFF;
+			width: 720rpx;
+			margin:10rpx auto;
+			border-radius: 6rpx;
+			box-sizing: border-box;
+			padding: 20rpx;
+			font-size: 28rpx;
+			.top {
+				display: flex;
+				justify-content: space-between;
+				.left {
+					display: flex;
+					align-items: center;
+					.title {
+						margin: 0 10rpx;
+						font-size: 32rpx;
+					}
+				}
+			}
+			.item {
+				display: flex;
+				flex-direction: row;
+				justify-content: space-between;
+				margin: 40rpx 0 20rpx 0;
+				.left {
+					display: flex;
+					image {
+						width: 130rpx;
+						height: 130rpx;
+						border-radius: 50%;
+					}
+					.content {
+						padding-left: 30rpx;
+						view{
+							padding-bottom: 16rpx;
+						}
+					}
+				}
+			}
+			.bottom {
+				display: flex;
+				margin-top: 20rpx;
+				justify-content: flex-end;
+				align-items: center;
+			}
+		}
+</style>

+ 204 - 0
pages/myFamily/user-card.vue

@@ -0,0 +1,204 @@
+<template>
+	<view class="">
+		<view class="data" v-for="(item, index) in list" :key="index" >
+			<view class="top">
+				<view class="left">
+					<u-icon name="home" :size="30" color="rgb(94,94,94)"></u-icon>
+					<view class="title">{{item.residentialName}}-{{item.buildingName}}-{{item.unitName}}-{{item.roomName}}</view>
+				</view>
+			</view>
+			<view class="item">
+				<view class="left">
+					<view  data-aid="undefined">
+					  <image v-if="!$isEmpty(item.imageUri)" mode="aspectFill" :src="item.imageUri"></image>
+					  <image v-else="" mode="aspectFill" src="http://139.9.103.171:1888/img/image/head.png"></image>
+					</view>
+					<view class="content" data-aid="undefined">
+						<view >姓名:{{item.name}}</view>
+						<view >手机:{{item.tel}}</view>
+						<view >创建时间:{{item.createDate}}</view>
+						<view v-if="item.type==0">身份:业主</view>
+						<view v-if="item.type==1">身份:家属</view>
+						<view v-if="item.type==2">身份:租户</view>
+						<view v-if="item.type==3">身份:访客</view>
+					</view>
+				</view>
+			</view>
+			<view class="bottom" >
+				<!-- 业主可以编辑所有人,其他只可以编辑自己 -->
+				<view v-if="showEdit(item)" @click.stop="edit(item)" class="cu-btn line-btn round sm margin-right-sm"  >
+					编辑
+				</view>
+				<!-- 小程序审核时,不要出现人脸功能 -->
+				<!-- 业主可以激活所有人的人脸,其他只可以操作自己 -->
+				<navigator v-if="showActiveFace(item)" class="cu-btn line-btn round sm margin-right-sm"  @click.stop="activeFace(item)">
+					人脸激活
+				</navigator>
+				<!-- 自己不能删除自己,业主可以删除成员,但是也不能删除自己 -->
+				<view v-if="vuex_relationshipType==0&&item.type!=0" class="cu-btn bg-btn sm round" @click.stop="deleteUserById(item.id)">
+					删除
+				</view>
+			</view>
+		</view>
+		
+		<!-- 有自己房屋的人才可以显示添加家人的功能按钮 -->
+		<navigator url="add/add" v-if="!$isEmpty(vuex_own_room_list)" class=" footer-fixed" >
+			<view class="cu-btn  flex  text-lg bg-red-btn" style="padding: 46rpx 0;">
+				添加家人
+			</view>
+		</navigator>
+<!-- 		<navigator url="add/add" v-if="!$isEmpty(vuex_own_room_list)" class="cuIcon cu-btn round base-bg-color" style="position: fixed;bottom: 20%;left: 20rpx;width: 88rpx;height: 88rpx;">
+			<text class="cuIcon-add" style="font-size: 60rpx;"></text>
+		</navigator> -->
+	</view>
+</template>
+
+<script>
+export default {
+	props:{
+		list:Array
+	},
+	data() {
+		return {
+			//小程序的审核状态
+			appletType:0
+		};
+	},
+	created() {
+		this.appletType=uni.getStorageSync("appletType")
+	},
+	computed:{
+		 showEdit() {
+			return item => {
+				if (this.vuex_relationshipType==0) {
+					return true
+				}else {
+					if (this.vuex_member.name==item.name || this.vuex_member.tel==item.tel) {
+						 return true
+					}else{
+						return false
+					}
+				}
+			};
+		},
+		showActiveFace(){
+			//小程序的审核状态为1才显示人脸模块,
+			return item => {
+				if (this.appletType==1) {
+					if (this.vuex_relationshipType==0) {
+						return true
+					}
+					if (this.vuex_member.name==item.name || this.vuex_member.tel==item.tel) {
+						 return true
+					}else{
+						return false
+					}
+				}
+				return false
+			};
+		}
+	},
+	methods:{
+		edit(item){
+			let params={
+				user_id:item.id,
+				name:item.name,
+				tel:item.tel,
+				room_name:item.roomName,
+				type:item.type,
+				id_card:item.idCard || '',
+				sex:item.sex,
+				nationality:item.nationality || '',
+				image_uri:item.imageUri || '',
+				passport_img_uri:item.passportImgUri || '',
+				entry_img_uri:item.entryImgUri || ''
+			}
+			if (this.vuex_relationshipType==0) {
+				//业主身份操作
+				params['operUserType']=0
+			}else{
+				//不是业主身份操作
+				params['operUserType']=item.type
+			}
+			uni.navigateTo({
+				url:"/pages/myFamily/editFamily/editFamily"+this.$u.queryParams(params)
+			})
+		},
+		activeFace(item){
+			let params={
+				room_id:item.roomId,
+				user_id:item.id,
+				name:item.name,
+				tel:item.tel,
+				room_name:item.roomName,
+				type:item.type,
+				id_card:item.idCard || '',
+				sex:item.sex,
+				nationality:item.nationality || '',
+				image_uri:item.imageUri || '',
+				passport_img_uri:item.passportImgUri || '',
+				entry_img_uri:item.entryImgUri || ''
+			}
+			uni.navigateTo({
+				url:"/pages/myFamily/activateFace/activateFace"+this.$u.queryParams(params)
+			})
+		},
+		deleteUserById(id) {
+			this.$emit('deleteUserById',id)
+		},
+	}
+};
+</script>
+
+<style lang="scss" scoped>
+.data {
+	background-color: #FFFFFF;
+	width: 720rpx;
+	margin:10rpx auto;
+	border-radius: 6rpx;
+	box-sizing: border-box;
+	padding: 20rpx;
+	font-size: 28rpx;
+	border-bottom: 1rpx solid #d1d1d1;
+	.top {
+		display: flex;
+		justify-content: space-between;
+		border-bottom: 1rpx dashed #DEDEDE;
+		padding-bottom: 20rpx;
+		.left {
+			display: flex;
+			align-items: center;
+			.title {
+				margin: 0 10rpx;
+				font-size: 32rpx;
+			}
+		}
+	}
+	.item {
+		display: flex;
+		flex-direction: row;
+		justify-content: space-between;
+		margin: 40rpx 0 20rpx 0;
+		.left {
+			display: flex;
+			image {
+				width: 130rpx;
+				height: 130rpx;
+				border-radius: 50%;
+			}
+			.content {
+				padding-left: 30rpx;
+				view{
+					padding-bottom: 16rpx;
+				}
+			}
+		}
+	}
+	.bottom {
+		display: flex;
+		margin-top: 20rpx;
+		justify-content: flex-end;
+		align-items: center;
+	}
+}
+</style>

+ 3 - 3
pages/myPassword/myPassword.vue

@@ -31,9 +31,9 @@ export default {
    */
   onLoad: function (options) {
     this.setData({
-      valid_count: options.valid_count,
-      password: options.password,
-      end_date: options.end_date
+      valid_count: options.valid_count || 1,
+      password: options.password || '123456',
+      end_date: options.end_date || '2021年1月5日 15点15分'
     });
   },
   methods: {}

+ 109 - 214
pages/myhome/familyList.vue

@@ -1,222 +1,117 @@
 <template>
-<view :class="$isEmpty(user_list)?'empty-wrap':''">
-<view class="nav_section" v-if="user_list!=null && user_list.length!=0">
-  <view v-for="(item, index) in user_list" :key="index" class="nav_list">
-    <view class="nav_section_items">
-      <view class="section_image" data-aid="undefined">
-        <image v-if="item.imageUri" mode="aspectFill" :src="item.imageUri">
-        </image>
-        <image v-if="item.imageUri==null" mode="aspectFill" src="http://139.9.103.171:1888/img/image/head.png">
-        </image>
-      </view>
-      <view class="section_cont" data-aid="undefined">
-        <view class="section_cont_sub">
-          <text>姓名:{{item.name}}</text>
-        </view>
-        <view class="section_cont_tel">
-          <text>手机:{{item.tel}}</text>
-        </view>
-        <view class="section_cont_tel">
-          <text v-if="item.type==0">身份:业主</text>
-          <text v-else-if="item.type==1">身份:成员</text>
-          <text v-else-if="item.type==2">身份:租客</text>
-          <text v-else-if="item.type==3">身份:访客</text>
-        </view>
-      </view>
-    </view>
-  </view>
-</view>
-<!-- 1-业主  业主身份才能添加房屋成员 wx:if="{{relationship==1}}" -->
-<!-- <view class='submit_btn'>
-  <navigator url='/pages/myHome/myHomeFamily/addMyHomeFamily/addMyHomeFamily?room_id={{room_id}}&relationship={{relationship}}'>
-    <button class="ar_btn">添加成员</button>
-  </navigator>
-</view> -->
-<view class="default" v-else>
-  <image src="/static/common/empty.png" mode="heightFix"></image>
-  <view>
-    <text>没有获取到房屋成员信息</text>
-  </view>
-</view>
-</view>
+	<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback" :down="downOption" :up="upOption">
+		<view class="card" v-for="(item,index) in user_list" :key="index">
+			<view class="alignCenter">
+				<image :src="item.imageUri?item.imageUri:'http://139.9.103.171:1888/img/image/head.png'" mode="scaleToFill"></image>
+			</view>
+			<view class="content">
+				<view class="flex">
+					<text class="name">{{item.name}}</text>
+					<view style="margin:8rpx 0 0 15rpx;" class="cu-tag sm bg-blue radius">
+						<text v-if="item.type==0">业主</text>
+						<text v-if="item.type==1">家属</text>
+						<text v-if="item.type==2">租客</text>
+					</view>
+				</view>
+				<view class="padding-top-20 ">
+					<text class="cuIcon-mobile  padding-right-10"></text>
+					<text>{{item.tel}}</text>
+				</view>
+				<view class="padding-top-10 ">
+					<text class="cuIcon-vipcard  padding-right-10"></text>
+					<text>{{item.idCard || '暂无'}}</text>
+				</view>
+			</view>
+			
+			
+		</view>
+	</mescroll-body>
 </template>
-
 <script>
-//获取app实例
-var app = getApp();
-
+import MescrollMixin from "@/comps/mescroll-body/mescroll-mixins.js";
 export default {
-  data() {
-    return {
-      user_list: null
-    };
-  },
-  onLoad(options) {
-  	let room_id = options.room_id; //获取房间下的住户
-  	console.log(room_id)
-  	this.getUserByRoomId(room_id);
-  },
-  methods: {	  
-    //获取房间下的住户
-    getUserByRoomId: function (room_id) {
-      let that = this;
-      let params = {
-		  pageSize:200,
-		  pageNum:0,
-		  room_id:room_id
-	  };
-      let operation = 'user/getUserByRoomId';
-      app.globalData.postRequest(params, operation, function (res) {
-        console.info("获取数据结构" + res.data.result_msg); //获取成功
-
-        if (res.data.result_code == 1) {
-          that.setData({
-            user_list: res.data.list
-          });
-        }
-      });
-    }
-  }
+	mixins: [MescrollMixin], // 使用mixin
+	name: '',
+	data() {
+		return {
+			room_id:'',
+			user_list:[],
+			downOption:{
+				auto:false,
+				use:true
+			},
+			upOption:{
+				auto:true,
+				use:true,
+				noMoreSize:3
+			}
+		};
+	},
+	onLoad(options) {
+		this.room_id=options.room_id
+	},
+	methods:{
+		/**
+		 * 下拉刷新回调
+		 */
+		downCallback(){
+			setTimeout(()=>{
+				uni.showToast({
+					title:"刷新成功",
+					icon:"none"
+				})
+				this.mescroll.resetUpScroll()
+			},1500)
+		},
+		upCallback(mescroll){
+			let that=this
+			let params = {
+				  pageSize:mescroll.size,
+				  pageNum:mescroll.num,
+				  room_id:this.room_id
+			};
+			let operation = 'user/getUserByRoomId';
+			try{
+				getApp().globalData.postRequest(params,operation,(res)=>{
+					let data=res.data.list
+					//不推荐
+					mescroll.endSuccess(data.length)
+					//推荐用下面这个,但是后台没有给我返回total
+					// this.mescroll.endBySize(data.length, total)
+					if(mescroll.num == 1) that.user_list = []
+					that.user_list = that.user_list.concat(data)
+				})
+				
+				this.user_list
+			}catch(e){
+				mescroll.endErr()
+			}
+		}
+	}
 };
 </script>
-<style lang="scss">
-page {
-  overflow-y: scroll;
-}
-
-.nav_section {
-  width: 100%;
-  padding-bottom: 120rpx;
-}
-.nav_list{
-  margin-top: 2rpx;
-}
-.nav_section_items {
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  padding: 30rpx;
- 
-  position: relative;
-  background: #fff;
-}
-.nav_section_items .section_image {
-  width: 120rpx;
-  height: 120rpx;
-  position: absolute;
-  top: 50%;
-  transform: translate(0, -50%);
-}
-
-.nav_section_items .identity {
-  font-size: 24rpx;
-  color: #d24a58;
-}
-
-.nav_section_items .section_image image {
-  width: 100%;
-  height: 100%;
-}
-
-.nav_section_items .section_cont {
-  width: 400rpx;
-  font-size: 24rpx;
-  color: #666;
-  margin-left: 140rpx;
-}
-
-.nav_section_items .section_cont view {
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-  display: block;
-}
-
-.nav_section_items .section_cont .section_cont_intro {
-  white-space: normal;
-  display: -webkit-box;
-  -webkit-line-clamp: 2;
-  -webkit-box-orient: vertical;
-}
-
-.nav_section_items .section_cont .section_cont_sub {
-  font-size: 28rpx;
-  line-height: 50rpx;
-  color: #666;
-  margin-bottom: 10rpx;
-}
-
-.nav_section_items .section_cont .section_cont_tel {
-  font-size: 28rpx;
-  color: #666;
-  line-height: 50rpx;
-  margin-bottom: 10rpx;
-}
-
-.nav_section_items .section_cont .section_cont_state {
-  font-size: 28rpx;
-}
-
-.nav_section_items .section_edit {
-  width: 80rpx;
-  height: 40rpx;
-  font-size: 26rpx;
-  border-radius: 10rpx;
-  background: #d24a58;
-  line-height: 40rpx;
-  color: #fff;
-  text-align: center;
-  position: absolute;
-  top: 50%;
-  right: 20rpx;
-  transform: translate(0, -50%);
-}
-
-.building {
-  height: 80rpx;
-  line-height: 80rpx;
-  background: #fff;
-  padding: 0 20rpx;
-  color: #333;
-  border-bottom: 2rpx solid #ddd;
-}
-
-.building image {
-  width: 40rpx;
-  height: 40rpx;
-  vertical-align: text-top;
-  margin-right: 10rpx;
-}
-.figure{
-  color: #d24a58;
-  border:1px solid #d24a58;
-  border-radius: 6rpx;
-  font-size: 24rpx;
-  padding: 0 6rpx;
-  margin-left: 10rpx;
-}
-.figure.renter{
-  color: $base-btn-color;
-  border:1px solid $base-btn-color;
-
-}
-.default {
-  text-align: center;
-  position: fixed;
-  left: 50%;
-  top: 40%;
-  transform: translate(-50%, -50%);
-}
-.default text{
-	color: #AAAAAA;
-}
 
-.default image {
-  height: 250rpx;
-  display: inline-block;
-}
-.empty-wrap{
-	background-color: #FFFFFF;
-	min-height: 100vh;
-}
+<style lang="scss" scoped>
+	.card{
+		background-color: #FFFFFF;
+		margin: 20rpx;
+		padding:30rpx 20rpx;
+		// border-radius: 10rpx;
+		display: flex;
+		box-sizing: border-box;
+		image{
+			width: 120rpx;
+			height: 120rpx;
+			border-radius: 50%;
+		}
+		.content{
+			display: flex;
+			flex-direction: column;
+			padding-left: 20rpx;
+			.name{
+				font-size: 32rpx;
+				font-weight: 800;
+			}
+		}
+	}
 </style>

+ 128 - 134
pages/myhome/myhome.vue

@@ -1,141 +1,153 @@
 <template>
-<view :class="$isEmpty(room_list)?'empty-wrap':''">
-<view v-if="!$isEmpty(room_list)" style="padding-bottom: 90rpx;">
-	<view class="data" v-for="(item, index) in room_list" :key="index">
-		<view class="top">
-			<view class="left">
-				<u-icon name="home" :size="30" color="rgb(94,94,94)"></u-icon>
-				<view class="title">{{item.residentialName}}</view>
-			</view>
-		</view>
-		<view class="item">
-			<view class="left">
-				<view style="padding: 0 30rpx;">
-					<view class="content">
-						<text>楼栋信息:</text>
-						<text >{{item.unitName}}</text>
+	<view class="">
+		<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback" :down="downOption" :up="upOption">
+			<view class="data" v-for="(item, index) in room_list" :key="index">
+				<view class="top">
+					<view class="left">
+						<u-icon name="home" :size="30" color="rgb(94,94,94)"></u-icon>
+						<view class="title">{{item.residentialName}}</view>
 					</view>
-					<view class="content">
-						<text>房间信息:</text>
-						<text>{{item.name}}</text>
+				</view>
+				<view class="item">
+					<view class="left">
+						<view style="padding: 0 30rpx;">
+							<view class="content">
+								<text>房屋信息:</text>
+								<text >{{item.buildingName}},{{item.unitName}},{{item.name}}</text>
+							</view>
+							<view class="content">
+								<text>身份:</text>
+								<text  v-if="item.relationshipType==0">业主</text>
+								<text  v-if="item.relationshipType==1">家属</text>
+								<text  v-if="item.relationshipType==2">租户</text>
+								<text  v-if="item.relationshipType==3">访客</text>
+							</view>
+						</view>
 					</view>
-					<view class="content">
-						<text>身份:</text>
-						<text  v-if="item.relationshipType==0">业主</text>
-						<text  v-if="item.relationshipType==1">成员</text>
-						<text  v-if="item.relationshipType==2">租户</text>
-						<text  v-if="item.relationshipType==3">访客</text>
+				</view>
+				<view class="bottom" >
+					<view class="cu-btn  sm round bg-red-btn"  @click="jump(item.id)">
+						房屋成员
 					</view>
 				</view>
 			</view>
-		</view>
-		<view class="bottom" >
-			<view class="cu-btn  sm round bg-red-btn"  @click="jump(item.id)">
-				房屋成员
+		</mescroll-body>
+		<view @tap="choosePlot" class="footer-fixed" >
+			<view class="cu-btn  flex  text-lg bg-red-btn" style="padding: 46rpx 0;">
+				添加房屋认证
 			</view>
 		</view>
 	</view>
-	<view @tap="choosePlot" class="footer-fixed" >
-		<view class="cu-btn  flex  text-lg bg-red-btn" style="padding: 46rpx 0;">
-			添加房屋认证
-		</view>
-	</view>
-</view>
-
-<view class="default" v-else>
-	  <image src="/static/common/empty.png" mode="heightFix"></image>
-	<view>
-    <text>没有获取到我的房屋信息</text>
-  </view>
-</view>
-</view>
 </template>
 
 <script>
-//获取app实例
-var app = getApp();
-
+var app=getApp()
+import MescrollMixin from "@/comps/mescroll-body/mescroll-mixins.js";
 export default {
-  data() {
-    return {
-      room_list: null
-    };
-  },
-
-  components: {},
-  props: {},
-
-  /**
-   * 生命周期函数--监听页面加载
-   */
-  onLoad: function (options) {
-    //获取房屋信息
-    this.geRoomByMemberId();
-  },
-  methods: {
-	  
-	 jump(id){
-		 uni.navigateTo({
-			 url:"./familyList?room_id="+id
-		 })
-	 },
-    //根据会员id获取我的房屋列表
-    geRoomByMemberId: function () {
-      let that = this;
-      let params = {};
-      params['member_id'] = app.globalData.member.id;
-	  params['pageSize'] = 200;
-      let operation = 'estate/getRoomByMemberId';
-      app.globalData.postRequest(params, operation, function (res) {
-        console.info("获取成功" + res.data.result_msg); //获取成功
-
-        if (res.data.result_code == 1) {
-          let list = [];
-
-          if (uni.getStorageSync('plotName')) {
-            res.data.list.map(item => {
-              if (item.residentialName == uni.getStorageSync('plotName')) {
-                list.push(item);
-              }
-            });
-          } else {
-            list = res.data.list;
-          }
-
-          that.setData({
-            room_list: list
-          });
-          app.globalData.room_list = list;
-        }
-      });
-    },
-
-    choosePlot() {
-		if(!this.$isEmpty(app.globalData.totalStep)){
-			app.globalData.totalStep=2
+	mixins: [MescrollMixin], // 使用mixin
+	name: '',
+	data() {
+		return {
+			room_list:[],
+			downOption:{
+				auto:false,
+				use:true
+			},
+			upOption:{
+				auto:true,
+				use:true,
+				noMoreSize:5
+			}
+		};
+	},
+	onLoad() {
+		
+	},
+	methods:{
+		/**房屋成员
+		 * @param {Object} id
+		 */
+		jump(id){
+			 uni.navigateTo({
+				 url:"./familyList?room_id="+id
+			 })
+		},
+		/**
+		 * 房屋认证
+		 */
+		choosePlot() {
+			if(!this.$isEmpty(getApp().globalData.totalStep)){
+				getApp().globalData.totalStep=2
+			}
+			  uni.navigateTo({
+				url:"../auth/auth"
+			  })
+		},
+		/**
+		 * 下拉刷新回调
+		 * @param {Object} mescroll
+		 */
+		downCallback(mescroll){
+			setTimeout(()=>{
+				uni.showToast({
+					title:"刷新成功",
+					icon:"none"
+				})
+				this.mescroll.resetUpScroll()
+			},1500)
+		},
+		/**
+		 * 上拉加载回调
+		 */
+		upCallback(mescroll){
+			let that = this
+			let parmas={
+				member_id:getApp().globalData.member.id,
+				pageNum:mescroll.num,
+				pageSize:20
+			}
+			let operation = 'estate/getRoomByMemberId'
+			try{
+				getApp().globalData.postRequest(parmas,operation,(res)=>{
+					if (res.data.result_code!=1) {
+						mescroll.endErr()
+						return
+					}
+					let data=[]
+					if (uni.getStorageSync('plotName')) {
+						//如果选择了当前小区,就只把当前小区的房屋列表展示出来
+						  res.data.list.map(item => {
+							if (item.residentialName == uni.getStorageSync('plotName')) {
+							  data.push(item);
+							}
+						  })
+					} else {
+						// 如果没有选择到小区,就把所有的房屋列表展示出来
+					  data = res.data.list;
+					}
+					//不推荐
+					mescroll.endSuccess(data.length)
+					//推荐用下面这个,但是后台没有给我返回total
+					// this.mescroll.endBySize(data.length, total)
+					if(mescroll.num == 1) that.room_list = []
+					that.room_list = that.room_list.concat(data)
+					getApp().globalData.room_list = that.room_list
+				})
+			}catch(e){	
+				mescroll.endErr()
+			}
 		}
-		  uni.navigateTo({
-			url:"../auth/auth"
-		  })
-    }
-
-  }
+		
+	}
 };
 </script>
-<style lang="scss">
 
+<style lang="scss">
 view,
 button
  {
 	box-sizing: border-box;
 }
-
-.cu-btn.sm {
-	padding: 0 24upx;
-	font-size: 24upx;
-	height: 52upx;
-}
-
 .data {
 	width: 710rpx;
 	background-color: #ffffff;
@@ -173,23 +185,5 @@ button
 		align-items: center;
 	}
 }
-.default {
-  text-align: center;
-  position: fixed;
-  left: 50%;
-  top: 40%;
-  transform: translate(-50%, -50%);
-}
-.default text{
-	color: #AAAAAA;
-}
 
-.default image {
-  height: 250rpx;
-  display: inline-block;
-}
-.empty-wrap{
-	background-color: #FFFFFF;
-	min-height: 100vh;
-}
 </style>

+ 153 - 0
pages/record/card.vue

@@ -0,0 +1,153 @@
+<template>
+	<view class="">
+		<u-popup v-model="detailShow" mode="center" width="650" :closeable="true" border-radius="10">
+			<view style="padding: 60rpx 5rpx 10rpx;">
+				<u-cell-group >
+					<u-cell-item :icon-style="iconStyle"  :border-top="false" :arrow="false"  icon="account-fill"  title="访客姓名:" :value="detailData.guestName"></u-cell-item>
+					<u-cell-item :icon-style="iconStyle"  :arrow="false"  icon="bookmark-fill"  title="身份证号:" :value="detailData.guestIdcard"></u-cell-item>
+					<u-cell-item :icon-style="iconStyle"  :arrow="false"  icon="phone-fill"  title="手机号:" :value="detailData.guestTel"></u-cell-item>
+					<u-cell-item :icon-style="iconStyle"  :arrow="false"  icon="map-fill"  title="访问区域:" :value="detailData.guestPosition"></u-cell-item>
+					<u-cell-item :icon-style="iconStyle"  :arrow="false"  icon="clock-fill"  title="访问时间:" :value="detailData.guestTime"></u-cell-item>
+					<u-cell-item :icon-style="iconStyle"  :arrow="false"  icon="plus-people-fill"  title="接待人:" :value="detailData.userName"></u-cell-item>
+					<u-cell-item :icon-style="iconStyle"  :border-bottom="false" :arrow="false"  icon="error-circle-fill"  title="访问目的:" :value="detailData.guestReason"></u-cell-item>
+				</u-cell-group>
+			</view>
+		</u-popup>
+		
+		<view @click="showDetail(item)" class="data" v-for="(item, index) in list" :key="index">
+			<view class="top">
+				<view class="left">
+					<view class="title ">
+						<text class="text-bold">访客姓名:</text>
+						<text>{{item.guestName}}</text>
+					</view>
+				</view>
+				<view class="right">
+					<text class="" v-if="item.auditStatus==1">已通过</text>
+					<text class="text-orange" v-if="item.auditStatus==0">待审核</text>
+					<text class="text-red" v-if="item.auditStatus==2">未通过</text>
+				</view>
+			</view>
+			<view class="item">
+				<view class="left">
+					<view style="padding: 20rpx 30rpx 0;">
+						<view class="content">
+							<text class="padding-right-10">访问区域:</text>
+							<text >{{item.guestPosition}}</text>
+						</view>
+						<view class="content">
+							<text class="padding-right-10">联系方式:</text>
+							<text>{{item.guestTel}}</text>
+							<image @click.stop="call(item.guestTel)" class="call" src="/static/call.png" ></image>
+						</view>
+						<view class="content">
+							<text class="padding-right-10">来访目的:</text>
+							<text style="line-height: 50rpx;">{{item.remarks}}</text>
+						</view>
+					</view>
+				</view>
+			</view>
+			<view class="bottom" >
+				<!-- 待审核,显示取消工单 -->
+				<view @click.stop="pass(item)" v-if="item.auditStatus==0" class="cu-btn  sm round bg-blue margin-right-20" >
+					审核通过
+				</view>
+				<view @click.stop="fail(item)" v-if="item.auditStatus==0" class="cu-btn  sm round bg-blue" >
+					审核不通过
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	name: 'card',
+	props:{
+		list:{
+			type:Array,
+			default:()=>{
+				[]
+			}
+		}
+	},
+	data() {
+		return {
+		};
+	},
+	onLoad() {
+		
+	},
+	methods:{
+		call(phone){
+			uni.makePhoneCall({
+				phoneNumber:phone
+			})
+		},
+		showDetail(item){
+			this.$emit('showDetail',item)
+		},
+		pass(item){
+			this.$emit('pass',item)
+		},
+		fail(item){
+			this.$emit('fail',item)
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+.bg-blue{
+	background-color: #59a5f0;
+	color: #FFFFFF;
+}
+
+	
+.data {
+	width: 710rpx;
+	background-color: #ffffff;
+	margin: 20rpx auto;
+	border-radius: 6rpx;
+	box-sizing: border-box;
+	padding: 20rpx;
+	font-size: 28rpx;
+	.top {
+		display: flex;
+		justify-content: space-between;
+		padding-bottom: 20rpx;
+		border-bottom: 1rpx solid #EEEEEE;
+		.left {
+			display: flex;
+			align-items: center;
+			.title {
+				margin: 0 10rpx;
+				font-size: 30rpx;
+			}
+		}
+		.right{
+			margin-right: 10rpx;
+		}
+	}
+	.item {
+		margin: 5rpx 0 20rpx 0;
+		.content {
+			// border-bottom: 1rpx dashed #DDDDDD;
+			padding: 20rpx 0 ;
+			
+			.call{
+				width: 36rpx;
+				height: 36rpx;
+				margin-left: 40rpx;
+				margin-top: 10rpx;
+			}
+		}
+	}
+	.bottom {
+		display: flex;
+		margin-top: 30rpx;
+		justify-content: flex-end;
+		align-items: center;
+	}
+}
+</style>

+ 171 - 0
pages/record/item.vue

@@ -0,0 +1,171 @@
+<template>
+	<MeScroll  :up="up" :down="down" @up="upFn" :fixed="false" @down="downFn" @init="initMeScroll">
+		<card @showDetail="showDetail" @pass="pass" @fail="fail" :list="list" ></card>
+	</MeScroll>
+</template>
+<script>
+	import MeScroll from '@/comps/mescroll-body/mescroll-uni.vue'
+	import card from './card.vue'
+	var app=getApp()
+	export default {
+		components:{
+			MeScroll,card
+		},
+		props: {
+			params:Object,
+			type: Number,
+			i: Number,
+			item:Object
+		},
+		data() {
+			return {
+				//审核不通过时展示
+				modelShow:false,
+				//审核不通过的原因
+				opinion:'',
+				dataDetail:{},
+				
+				memberId:'',
+				isInit: false, // 是否初始化
+				list: [], // 列表数据
+				mescroll: null, // mescroll 对象
+				// 上拉配置参数
+				up: {
+					noMoreSize: 3, 
+					auto: true,
+					page: {
+						page: 0,
+						size: 10
+					}
+				},
+				// 下拉配置参数
+				down: {
+					use: true, 
+					auto: false
+				}
+			}
+		},
+		created() {
+			this.memberId=getApp().globalData.member.id
+		},
+		methods: {
+			showDetail(item){
+				this.$emit('test',item)
+			},
+			/**
+			 * 通过审核
+			 */
+			pass(item){
+				let that=this
+				let {rootOrgId,orgPosition,orgId,...params}=item
+				params.auditStatus=1
+				let operation="guestRecord/updateGuestRecord"
+				uni.showModal({
+					title:"提示",
+					content:"确定审核通过该访客信息吗?",
+					showCancel:true,
+					success: (res) => {
+						if (res.confirm) {
+							getApp().globalData.postRequest(params,operation,function(res){
+								console.log(res);
+								that.mescroll.resetUpScroll()
+							})
+						}
+					}
+				})
+			},
+			/**
+			 * 审核不通过
+			 * @param {Object}
+			 */
+			submitFailAudit(){
+				let that=this
+				let {rootOrgId,orgPosition,orgId,...params}=item
+				params.auditStatus=2
+				let operation="guestRecord/updateGuestRecord"
+				uni.showModal({
+					title:"提示",
+					content:"确定审核不通过该访客信息吗?",
+					showCancel:true,
+					success: (res) => {
+						if (res.confirm) {
+							getApp().globalData.postRequest(params,operation,function(res){
+								console.log(res);
+								that.mescroll.resetUpScroll()
+							})
+						}
+					}
+				})
+			},
+			/**
+			 * 显示审核不通过的意见框
+			 * @param {Object} item
+			 */
+			fail(item){
+				this.dataDetail=item
+				this.modelShow=true
+			},
+			/**
+			 * @param {Object} mescroll 初始化组件
+			 */
+			initMeScroll(mescroll) {
+				this.mescroll = mescroll
+			},
+			/**
+			 * @param {Object} mescroll 上拉回调
+			 */
+			upFn(mescroll) {
+				try{
+					let that=this
+					let params={
+						member_id:that.memberId,
+						current:mescroll.num,
+						size:mescroll.size,
+					}
+					if (this.item.value!=-1) {
+						params.auditStatus=this.item.value
+					}
+					if (!this.$isEmpty(this.params.id)) {
+						params.id=this.params.id
+					}
+					if (!this.$isEmpty(this.params.guestName)) {
+						params.guestName=this.params.guestName
+					}
+					if (!this.$isEmpty(this.params.guestTel)) {
+						params.guestTel=this.params.guestTel
+					}
+					let operation='guestRecord/getListByMemberId'
+					getApp().globalData.postRequest(params,operation,function(res){
+						let data=res.data.list
+						let length=data.length
+						let total=res.data.total
+						mescroll.endBySize(length, total);
+						if(mescroll.num == 1) that.list = []; //如果是第一页需手动制空列表
+						that.list=that.list.concat(data); //追加新数据
+					})
+				}catch(e){
+					mescroll.endErr();
+				}
+			},
+			/**
+			 * 下拉回调
+			 * */
+			downFn(mescroll) {
+				setTimeout(()=>{
+					this.mescroll.resetUpScroll()
+					uni.showToast({
+						title:"刷新成功",
+						icon:"none",
+						position:"top"
+					})
+				},1500)
+			},
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	view{
+		box-sizing: border-box;
+	}
+</style>

+ 203 - 154
pages/record/record.vue

@@ -1,160 +1,209 @@
 <template>
-<view style="background-color: #FFFFFF;height: 100vh;">
-<view class="nav_section" v-if="list.length>0">
-  <view>
-    <view v-for="(item, index) in list" :key="index" class="nav_section_items">
-      <view class="section_cont" data-aid="undefined">
-        <view class="section_cont_tel">
-          <text>访客类型:</text>
-          <text class="fr classify" v-if="item.accessUserType==0">朋友</text>
-          <text class="fr classify" v-else-if="item.accessUserType==1">外卖</text>
-          <text class="fr classify" v-else-if="item.accessUserType==2">快递</text>
-          <text class="fr classify" v-else-if="item.accessUserType==3">其他</text>
-          <text class="fr classify" v-else>其他</text>
-        </view>
-       <view class="section_cont_tel">
-          <text>开门密码:</text>
-           <text class="fr">{{item.accessCardNo}}</text>
-        </view>
-        <view class="section_cont_tel"> <text>开门时间:</text> <text class="fr">{{item.accessDate}}</text></view>
-        
-      </view>
-    </view>
-  </view>
-</view>
-<view class="default" v-if="list==null || list.length==0">
-    <image src="/static/common/empty.png" mode="heightFix"></image>
-  <view>
-    <text>没有获取到访客记录</text>
-  </view>
-</view>
-</view>
+	<view class="container">
+		<u-popup v-model="detailShow" mode="center" width="650" :closeable="true" border-radius="10">
+			<view style="padding: 60rpx 5rpx 10rpx;">
+				<u-cell-group >
+					<u-cell-item :icon-style="iconStyle"  :border-top="false" :arrow="false"  icon="account-fill"  title="访客姓名:" :value="detailData.guestName"></u-cell-item>
+					<u-cell-item :icon-style="iconStyle"  :arrow="false"  icon="bookmark-fill"  title="身份证号:" :value="detailData.guestIdcard"></u-cell-item>
+					<u-cell-item :icon-style="iconStyle"  :arrow="false"  icon="phone-fill"  title="手机号:" :value="detailData.guestTel"></u-cell-item>
+					<u-cell-item :icon-style="iconStyle"  :arrow="false"  icon="map-fill"  title="访问区域:" :value="detailData.guestPosition"></u-cell-item>
+					<u-cell-item :icon-style="iconStyle"  :arrow="false"  icon="clock-fill"  title="访问时间:" :value="detailData.guestTime"></u-cell-item>
+					<u-cell-item :icon-style="iconStyle"  :arrow="false"  icon="plus-people-fill"  title="接待人:" :value="detailData.userName"></u-cell-item>
+					<u-cell-item :icon-style="iconStyle"  :border-bottom="false" :arrow="false"  icon="error-circle-fill"  title="访问目的:" :value="detailData.guestReason"></u-cell-item>
+				</u-cell-group>
+			</view>
+		</u-popup>
+		<u-modal cancel-text="重置" cancel-color="#000000" @cancel="filterReset" :show-cancel-button="true"  @confirm="filterConfirm" title="筛选" :mask-close-able="true" v-model="filterShow" >
+			<view class="slot-content" style="margin: 20rpx;">
+				<u-form label-width="150"  ref="uForm">
+					<u-form-item label="主键id" v-if="!$isEmpty(params.id)"><u-input v-model="params.id" disabled /></u-form-item>
+					<u-form-item label="访客姓名"><u-input v-model="params.guestName" /></u-form-item>
+					<u-form-item :border-bottom="false" label="手机号"><u-input v-model="params.guestTel" type="number"  /></u-form-item>
+				</u-form>
+			</view>
+		</u-modal>
+		<view class="tabs flex flex-direction">
+			<view class="flex">
+				<scroll-view scroll-x class="bg-white nav" >
+					<view class="flex text-center">
+						<view class="cu-item flex-sub" :class="index==current?'text-blue text-xl text-bold ':'text-lg'" v-for="(item,index) in tabs" :key="index" @tap="tabChange(index)" >
+							{{item.name}}
+						</view>
+					</view>
+				</scroll-view>
+				<view class="flex justify-center align-center padding-right-20" style="flex: 10%;"  @click="show">
+					<text class="cuIcon-filter "  style="font-size: 40rpx;"></text>
+					<u-badge size="mini" type="error" :count="filterCount"></u-badge>
+				</view>
+			</view>
+		</view>
+		<view style="height: 100%;">
+			<swiper style="height: 100%;" :current="current"  @change="swiperChange"
+				@animationfinish="animationfinish">
+				<swiper-item  v-for="(item, index) in tabs" :key="index">
+					<scroll-view scroll-y style="height: 100%;">
+						<item @test="showDetail" ref="mescrollItem" :params="params" :i="index" :item="item" :type="current"></item>
+					</scroll-view>
+				</swiper-item>
+			</swiper>
+		</view>
+	</view>
 </template>
-
 <script>
-//获取app实例
-var app = getApp();
-var util = require("../../utils/util.js");
-
-export default {
-  data() {
-    return {
-      list: null
-    };
-  },
-
-  components: {},
-  props: {},
-
-  /**
-   * 生命周期函数--监听页面加载
-   */
-  onLoad: function (options) {
-    this.getPwdOpenRecord();
-  },
-  methods: {
-    //获取访客记录
-    getPwdOpenRecord: function () {
-      let that = this;
-      let params = {};
-      params['member_id'] = app.globalData.member.id;
-      let operation = 'accessRecords/getListByMemberId';
-      app.globalData.postRequest(params, operation, function (res) {
-        console.info("获取结果:" + res.data.result_msg); //获取成功
-
-        if (res.data.result_code == 1) {
-          let list = res.data.list;
-
-          for (let i in list) {
-            list[i].accessDate = util.formatTime(list[i].accessDate);
-          }
-
-          that.setData({
-            list: list
-          });
-        }
-      });
-    }
-  }
-};
+	import item from "./item.vue"
+	export default {
+		components: {
+			item
+		},
+		data() {
+			return {
+				iconStyle:{
+					color:"#59a5f0"
+				},
+				
+				detailShow:false,
+				detailData:{},
+				
+				filterCount:0,
+				filterShow:false,
+				params:{},
+				
+				current: 0,
+				swiperCurrent:0,
+				tabs: [
+					{
+						name: '全部',
+						value:-1
+					},
+					{
+						name: '待审核',
+						value:0
+					},
+					{
+						name: '已通过',
+						value:1
+					},
+					{
+						name:'未通过',
+						value:2
+					}
+				],
+			}
+		},
+		onShow(){
+			
+		},
+		onLoad(options) {
+			this.params.id=options.id
+			this.getFilterCount()
+		},
+		methods:{
+			/**显示详情
+			 * @param {Object} item
+			 */
+			showDetail(item){
+				this.detailShow=true
+				this.detailData=item
+			},
+			/**
+			 * 显示筛选弹窗
+			 */
+			show(){
+				this.filterShow=true
+			},
+			/**
+			 * 筛选
+			 */
+			filterConfirm(){
+				this.$nextTick(() => {
+					this.refreshMescroll()
+				})
+				this.getFilterCount()
+				
+			},
+			/**
+			 * 计算筛选的数量
+			 */
+			getFilterCount(){
+				let n=0
+				if (!this.$isEmpty(this.params.id)) {
+					n++
+				}
+				if (!this.$isEmpty(this.params.guestName)) {
+					n++
+				}
+				if (!this.$isEmpty(this.params.guestTel)) {
+					n++
+				}
+				this.filterCount=n
+			},
+			/**
+			 * 重置筛选项
+			 */
+			filterReset(){
+				this.filterCount=0
+				this.params={}
+				this.$nextTick(() => {
+					this.refreshMescroll()
+				})
+			},
+			/**
+			 * 刷新列表
+			 */
+			refreshMescroll(){
+				let curMescroll = this.getMescroll(this.current)
+				curMescroll && curMescroll.resetUpScroll()
+			},
+			/**
+			 * 获取Mescroll对象
+			 * @param {Object} i
+			 */
+			getMescroll(i){
+				let mescrollItems = this.$refs.mescrollItem;
+				if(mescrollItems){
+					let item = mescrollItems[i]
+					if(item) return item.mescroll
+				}
+				return null
+			},
+			
+			tabChange(index) {
+				this.current = index
+			},
+			swiperChange(e) {
+			  uni.pageScrollTo({
+			      scrollTop: 0,
+			      duration: 0
+			  });
+			  this.current = e.detail.current
+			},
+			animationfinish({detail: { current }}) {
+				this.swiperCurrent = current;
+				this.current = current;
+			},
+		}
+	}
 </script>
-<style>
-/* pages/myHome/myHome.wxss */
-page{
-  overflow-y: scroll;
-}
-.nav_section {
-  width: 100%;
-  overflow-y: scroll;
-}
-
-.nav_section_items {
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  padding: 30rpx;
-  border-bottom: 2rpx solid #ddd;
-  position: relative;
-  background: #fff;
-  margin: 30rpx;
-  border-radius: 10rpx;
-}
-
-
-.nav_section_items .section_image {
-  width: 170rpx;
-  height: 158rpx;
-  position: relative;
-}
-
-.nav_section_items .identity {
-  padding: 4rpx;
-  top: 0;
-  right: 0;
-  background: #29afec;
-  color: #fff;
-  font-size: 24rpx;
-  position: absolute;
-}
-
-.nav_section_items .section_image image {
-  width: 100%;
-  height: 100%;
-}
-
-.nav_section_items .section_cont {
-  width: 100%;
-  font-size: 26rpx;
-  color: #a9a9a9;
-}
-
-.nav_section_items .section_cont view {
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-  display: block;
-}
-
-.nav_section_items .section_cont .section_cont_intro {
-  white-space: normal;
-  display: -webkit-box;
-  -webkit-line-clamp: 2;
-  -webkit-box-orient: vertical;
-}
-
-.nav_section_items .section_cont .section_cont_tel {
-  font-size: 28rpx;
-  color: #666;
-  line-height: 80rpx;
-  margin-bottom: 10rpx;
-  width: 100%;
-  border-bottom: 1px dashed #a9a9a9;
-}
-.nav_section_items .section_cont .section_cont_tel .classify{
-  color: #d24a58;
-}
 
-.section_cont_tel .fr {
-  float: right;
+<style lang="scss" scoped>
+	.text-blue{
+		color: #59a5f0;
+	}
+	.text-xl{
+		font-size: 34rpx;
+	}
+	.container {
+	  height: calc(100vh);
+	  background-color: #F6F6F6;
+	  padding: 78rpx 0rpx 0rpx;
+	 .tabs {
+	    position: fixed;
+	    top: -10rpx;
+		left: 0;
+		width: 100%;
+		background-color: #FFFFFF;
+		box-sizing: border-box;
+		z-index: 3;
+	  }
 }
-.default {  text-align: center;  position: fixed;  left: 50%;  top: 40%;  transform: translate(-50%, -50%);}.default text{	color: #AAAAAA;}.default image {  height: 250rpx;  display: inline-block;}</style>
+</style>

+ 12 - 5
pages/register/register.vue

@@ -30,14 +30,14 @@
     </view>
     <view style="display:flex;margin:20rpx 20rpx">
 	  <u-checkbox v-model="isCheck" active-color="blue">
-		  <navigator url="/pages/webview/webview"><text style="color:#5db5fe">请阅读并同意用户协议</text></navigator>
 	  </u-checkbox>
+	  <navigator style="margin-left: -20rpx;" :url="webviewUrl"><text class="text-blue">请阅读并同意用户协议</text></navigator>
     </view>
 	<view class="tips">
 	  <text style="padding-left: 40rpx;">认证后用户可享受更多权益,随时获取到您所在小区的动态</text>
 	</view>
 	
-	<button open-type="getUserInfo" @getuserinfo="showDialogBtn"  class=" footer-fixed" >
+	<button style="border-radius: 0;" open-type="getUserInfo" @getuserinfo="showDialogBtn"  class=" footer-fixed" >
 		<view class="cu-btn  flex  text-lg bg-red-btn" style="padding: 46rpx 0;">
 			确认
 		</view>
@@ -53,6 +53,8 @@ var app = getApp();
 export default {
   data() {
     return {
+	  webviewUrl:'/pages/webview/webview?url=https://community.58fo.com/appfile/protocal.htm&title=隐私协议',
+	  
       text: '获取验证码',
       //按钮文字
       currentTime: 61,
@@ -70,7 +72,12 @@ export default {
     };
   },
   onLoad() {
-	this.tel=this.$auth.getMineBase().user.mobile || ''
+	  let userinfo=this.$auth.getMineBase().user
+	  if (!this.$isEmpty(userinfo)) {
+		  if (userinfo.mobile!='13800000000') {
+		  	this.tel=this.$auth.getMineBase().user.mobile
+		  }
+	  }
   },
   methods: {
     //获取姓名栏input中的值
@@ -104,7 +111,7 @@ export default {
         warn = "姓名不能为空";
       } else if (tel == null) {
         warn = "手机号码不能为空";
-      } else if (tel.trim().length != 11 || !/^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[189])\d{8}$/.test(tel)) {
+      } else if (!this.$u.test.mobile(tel)) {
         warn = "手机号格式不正确";
       } else {
         //发送短信
@@ -159,7 +166,7 @@ export default {
 	    app.globalData.autoFailHint("请输入手机号");
 	    return;
 	  }
-      if (tel.trim().length != 11 || !/^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\d{8}$/.test(tel)) {
+      if (!this.$u.test.mobile(tel)) {
         //自动关闭提示弹窗
         app.globalData.autoFailHint("请填写正确的手机号码");
         return;

+ 1 - 1
pages/services/property/comment.vue

@@ -4,7 +4,7 @@
 			<textarea maxlength="120" v-model="comment"  placeholder="请输入您的评价"/>
 			<text class="text-gray font-num-view">{{comment.length}} / 120字</text>
 		</view>
-		<view @click="save" class="cu-btn lg radius flex  bg-red footer-fixed">
+		<view @click="save" style="padding: 46rpx;" class="cu-btn lg  flex  bg-blue  footer-fixed">
 			确认保存
 		</view>
 	</view>

+ 7 - 7
pages/services/property/detail.vue

@@ -1,6 +1,6 @@
 <template>
 	<view>
-		<view class="bg-red padding" style="height: 100rpx;">
+<!-- 		<view class="bg-blue padding" style="height: 100rpx;">
 			<view class="text-xxl ">
 				<text v-if="dataDetail.handleStatus==-1">已撤销</text>
 				<text v-else-if="dataDetail.handleStatus==0">待处理</text>
@@ -11,9 +11,9 @@
 				<text v-else-if="dataDetail.handleStatus==0">当前工单待处理,请耐心等待</text>
 				<text v-else-if="dataDetail.handleStatus==1">当前工单已完成</text>
 			</view>
-		</view>
+		</view> -->
 		
-		<view class="margin-top bg-white padding solid-bottom">
+		<view class=" bg-white padding solid-bottom">
 			<view class="flex justify-between">
 				<view class="text-black">
 					<text>工单编号:{{dataDetail.repairNo}}</text>
@@ -65,18 +65,18 @@
 			</view>
 		</view>
 		
-		<view  class="footer-fixed  padding-sm bg-white flex justify-end margin-right-30" style="box-sizing: border-box;z-index: 999;">
+		<view  class="footer-fixed  padding-sm bg-white flex justify-end margin-right-30" style="box-sizing: border-box;z-index: 999;padding: 20rpx;">
 			<!-- 待处理,取消工单 -->
-			<view class="cu-btn line-red round " v-if="dataDetail.handleStatus==0" @click="cancelItem()">
+			<view class="cu-btn line-blue round " v-if="dataDetail.handleStatus==0" @click="cancelItem()">
 				取消工单
 			</view>
 			<!-- 已撤销工单,删除工单 -->
-			<view class="cu-btn line-red round margin-right-20" v-if="dataDetail.handleStatus==-1||dataDetail.handleStatus==1" @click="deleteItem()" >
+			<view class="cu-btn line-blue round margin-right-20" v-if="dataDetail.handleStatus==-1||dataDetail.handleStatus==1" @click="deleteItem()" >
 				删除工单
 			</view>
 			<!-- v-if="dataDetail.handleStatus==1&&dataDetail.estimateStatus==0" -->
 			<!-- 已处理,待评价 -->
-			<navigator url="./comment" v-if="dataDetail.handleStatus==1&&dataDetail.estimateStatus==0" class="cu-btn bg-red round "  >
+			<navigator url="./comment" v-if="dataDetail.handleStatus==1&&dataDetail.estimateStatus==0" class="cu-btn bg-blue  round "  >
 				写评价
 			</navigator>
 		</view>

+ 3 - 3
pages/services/property/list/card.vue

@@ -38,15 +38,15 @@
 					联系客服
 				</button>
 				<!-- 待处理,显示取消工单 -->
-				<view v-if="item.handleStatus==0" class="cu-btn  sm round bg-red" @click.stop="cancel(item)">
+				<view v-if="item.handleStatus==0" class="cu-btn  sm round bg-blue" @click.stop="cancel(item)">
 					取消工单
 				</view>
 				<!-- 已取消,显示删除订单 -->
-				<view v-if="item.handleStatus==-1" class="cu-btn  sm round bg-red" @click.stop="deleteItem(item)">
+				<view v-if="item.handleStatus==-1" class="cu-btn  sm round bg-blue" @click.stop="deleteItem(item)">
 					删除工单
 				</view>
 				<!-- 已完成,显示写评价 -->
-				<view v-if="item.handleStatus==1" class="cu-btn  sm round bg-red" @click.stop="comment(item)">
+				<view v-if="item.handleStatus==1" class="cu-btn  sm round bg-blue" @click.stop="comment(item)">
 					写评价
 				</view>
 			</view>

+ 4 - 3
pages/services/property/list/item.vue

@@ -4,7 +4,7 @@
 	</MeScroll>
 </template>
 <script>
-	import MeScroll from '@/comps/mescroll-uni/mescroll-uni.vue'
+	import MeScroll from '@/comps/mescroll-body/mescroll-uni.vue'
 	import card from './card.vue'
 	var app=getApp()
 	export default {
@@ -25,7 +25,7 @@
 				// 上拉配置参数
 				up: {
 					noMoreSize: 5, 
-					auto: true,
+					auto: false,
 					page: {
 						page: 0,
 						size: 10
@@ -107,8 +107,9 @@
 				let data={
 					"page":{
 						current:mescroll.num,
-						size:mescroll.size
+						size:mescroll.size,
 					},
+					memberId:getApp().globalData.member.id,
 					handleStatus:this.item.value
 				}
 				//已处理,待评价

+ 1 - 1
pages/services/property/list/list.vue

@@ -3,7 +3,7 @@
 		<view class="tabs">
 			<scroll-view scroll-x class="bg-white nav">
 				<view class="flex text-center">
-					<view class="cu-item flex-sub" :class="index==current?'text-red text-xl text-bold':'text-lg'" v-for="(item,index) in tabs" :key="index" @tap="tabChange(index)" >
+					<view class="cu-item flex-sub" :class="index==current?'text-blue text-xl text-bold':'text-lg'" v-for="(item,index) in tabs" :key="index" @tap="tabChange(index)" >
 						{{item.name}}
 					</view>
 				</view>

+ 5 - 10
pages/services/property/property.vue

@@ -36,15 +36,6 @@
 				<view class="bg-gray padding-20" @click="timeShow=true">
 					<input disabled  type="number" placeholder="请选择预约时间" v-model="dateTimeStr" />
 				</view>
-				<!-- <view class="flex" style="box-sizing: border-box;" >
-					<view class="flex-sub  bg-gray padding-20" @click="timeType='start';timeShow=true">
-						<input disabled="" type="text" placeholder="请选择开始时间" v-model="data.beginTime" />
-					</view>
-					<text class="padding-20">—</text>
-					<view class="flex-sub   bg-gray padding-20" @click="timeType='end';timeShow=true">
-						<input disabled="" type="text" placeholder="请选择结束时间" v-model="data.endTime" />
-					</view>
-				</view> -->
 			</view>
 		</view>
 		
@@ -96,7 +87,6 @@
 			<time-selector  @getDateTime="timeConfirm"></time-selector>
 		</u-popup>
 		
-		<!-- <u-picker  @confirm="timeConfirm" :params="params" z-index="9999999" v-model="timeShow" mode="time"></u-picker> -->
 		<u-select :default-value="defaultValue" value-name="residentialId" label-name="residentialName" @confirm="residentialConfirm" z-index="9999999" v-model="residentialShow" :list="residentialList"></u-select>
 	</view>
 </template>
@@ -149,6 +139,9 @@
 		onLoad() {
 			this.initData()
 		},
+		onShow() {
+			this.data.phone=getApp().globalData.member.tel
+		},
 		methods: {
 			initData(){
 				that=this
@@ -217,6 +210,7 @@
 				this.data.pic=JSON.stringify(this.base64_image)
 				let operation='estateRepair/addEstateRepair'
 				console.log(this.data);
+				return
 				app.globalData.postRequest(this.data, operation, function (res) {
 					if (res.data.add_result) {
 						app.globalData.oneFailHint("提交成功");
@@ -304,6 +298,7 @@
 					success: res => {
 						if (res.confirm) {
 							this.imgList.splice(index, 1)
+							this.base64_image.splice(index,1)
 						}
 					}
 				})

+ 1 - 2
pages/switchcity/switchcity.vue

@@ -253,8 +253,7 @@ export default {
 
       }); //从新获取楼栋信息
 
-      prevPage.getCommunity(); //上一个页面内执行setData操作,将我们想要的信息保存住。当我们返回去的时候,页面已经处理完毕。
-      //最后就是返回上一个页面。
+      // prevPage.getCommunity(); 
 
       uni.navigateBack(); //console.log(appInstance.defaultCounty);
       // wx.navigateBack({

+ 48 - 28
pages/tool-list/epidemic-pass/detail.vue

@@ -1,48 +1,50 @@
 <template>
-	<view>
-		<view class="card">
+	<view class="">
+		<view class="card bg-white">
 			<view class="top">
-				<text class="title">宁夏冬美小区</text>
+				<text class="title">{{dataDetail.residentialName}}</text>
 				<view class="avatar">
 					<u-avatar :sex-icon="userInfo.gender==1?'man':'woman'" show-sex="true" size="110" :src="userInfo.avatarUrl"></u-avatar>
 				</view>
 				<view class="text-center text-bold">
 					<text v-text="userInfo.nickName"></text>
 				</view>
-				<view class="text-center padding-top-50 " style="font-size: 26rpx;">
+				<view class="text-center text-blue padding-top-50 " style="font-size: 26rpx;">
 					请出示该通行证截图,由保安核检
 				</view>
 			</view>
 			<view class="bottom">
 				<view class="item">
 					<text class="">姓名:</text>
-					<text>黄明潘</text>
-				</view>
-				<view class="item">
-					<text class="">身份类型:</text>
-					<text>访客</text>
+					<text>{{memberName}}</text>
 				</view>
 				<view class="item">
 					<text class="">出入原因:</text>
-					<text>去朋友家</text>
+					<text>{{dataDetail.reason}}</text>
 				</view>
 				<view class="item">
 					<text class="">体温是否异常:</text>
-					<text class="text-red text-bold">是</text>
+					<text v-if="dataDetail.temparetureException==0">否</text>
+					<text v-if="dataDetail.temparetureException==1" class="text-red text-bold">异常</text>
 				</view>
 				<view class="item">
 					<text class="">是否有异常症状:</text>
-					<text>否</text>
+					<text v-if="dataDetail.symptomException==0">否</text>
+					<text v-if="dataDetail.symptomException==1" class="text-red text-bold">异常</text>
 				</view>
 				<view class="item">
 					<text class="">访问日期:</text>
-					<text>2020-11-09 15:56:23</text>
+					<text>{{dataDetail.createDate}}</text>
 				</view>
 			</view>
 		</view>
 		<view class="text-center text-sm text-gray">
 			通行证仅当天有效,隔日需要再次登记出入信息
 		</view>
+		<view v-if="show==true" @click="goList" class=" text-center margin-top-50">
+			<u-icon name="order" color="#0081ff"></u-icon>
+			<text class="text-blue text-df padding-left-10" >登记记录</text>
+		</view>
 	</view>
 </template>
 
@@ -50,27 +52,45 @@
 	export default {
 		data() {
 			return {
-				userInfo:{}
+				//如果是从列表跳过来的,隐藏登记记录
+				show:true,
+				
+				memberName:'',
+				userInfo:{},
+				dataDetail:{}
 			}
 		},
-		onLoad() {
-			this.login()
+		onLoad(options) {
+			this.show=options.show || true
+			this.fetchUserInfo()
+		},
+		onShow() {
+			this.memberName=getApp().globalData.member.name
+			this.dataDetail=getApp().globalData.pratiqueData
 		},
 		methods: {
-			login(){
+			fetchUserInfo(){
 				let that=this
-				uni.login({
-				  success: function () {
-				    uni.getUserInfo({
-				      success: function (res) {
-				        that.userInfo=res.userInfo
-						console.log(that.userInfo);
-				      }
-				    });
-				  }
-				});
+				that.userInfo=uni.getStorageSync("userInfo")
+				if (this.$isEmpty(that.userInfo)) {
+					uni.login({
+					  success: function () {
+					    uni.getUserInfo({
+					      success: function (res) {
+					        that.userInfo=res.userInfo
+					      }
+					    });
+					  }
+					});
+				}
+			},
+			goList(){
+				uni.navigateTo({
+					url:"/pages/tool-list/epidemic-pass/list"
+				})
 			}
-		}
+		},
+		
 	}
 </script>
 

+ 133 - 7
pages/tool-list/epidemic-pass/epidemic-pass.vue

@@ -8,7 +8,7 @@
 					<text>您的姓名</text>
 				</view>
 				<view class="input">
-					<input  type="text" value="" placeholder="请输入您的姓名"/>
+					<input disabled=""  type="text" value="" v-model="member.name" placeholder="请输入您的姓名"/>
 				</view>
 			</view>
 			
@@ -18,7 +18,7 @@
 					<text>出入原因</text>
 				</view>
 				<view class="input">
-					<input  type="text" value="" placeholder="请填写出入小区的原因"/>
+					<input  type="text" value="" v-model="reason" placeholder="请填写出入小区的原因"/>
 				</view>
 			</view>
 			
@@ -42,7 +42,19 @@
 				</view>
 			</view>
 		</view>
-		<view class=" footer-fixed" @click="submit">
+		<view @click="goList" class=" text-center margin-top-30">
+			<u-icon name="order" color="#0081ff"></u-icon>
+			<text class="text-blue text-df padding-left-10" >登记记录</text>
+		</view>
+		
+		
+		<button style="border-radius: 0;" v-if="$isEmpty(userInfo)" open-type="getUserInfo" @getuserinfo="getUserInfo" class=" footer-fixed" >
+			<view class="cu-btn  flex  text-lg bg-red-btn" style="padding: 46rpx 0;">
+				提交信息
+			</view>
+		</button>
+		
+		<view v-else @click="submit" class=" footer-fixed">
 			<view class="cu-btn  flex  text-lg bg-red-btn" style="padding: 46rpx 0;">
 				提交信息
 			</view>
@@ -54,22 +66,136 @@
 	export default {
 		data() {
 			return {
+				//出入小区
+				residentialId:'',
+				residplotName:'',
+				
+				member:{},
+				//出入原因
+				reason:'',
+				//体温是否异常
 				switch1Check:false,
-				switch2Check:false
+				//是否咳嗽
+				switch2Check:false,
+				
+				//获取用户信息
+				userInfo:{},
 			}
 		},
+		onLoad() {
+			this.member=getApp().globalData.member
+			this.residentialId=uni.getStorageSync("residentialId")
+			this.plotName=uni.getStorageSync("plotName")
+			if (this.$isEmpty(this.member)||this.$isEmpty(this.residentialId)) {
+				uni.showModal({
+					content:'系统异常',
+					showCancel:false,
+					success: (res) => {
+						if (res.confirm) {
+							uni.navigateBack({
+								delta:1
+							})
+						}
+					}
+				})
+				return
+			}
+			this.login()
+			this.getRecordByCondition()
+		},
 		methods: {
+			/**
+			 * 通过member和当天时间查询当天是否填写了防疫通行记录
+			 * 如果有记录,直接跳转到通行详情那去
+			 */
+			getRecordByCondition(){
+				let that=this
+				var date=new Date()
+				let createDate= date .toLocaleDateString().replace(RegExp("/", "g"), "-")+" "+"00:00:00"
+				let params={
+					memberId:this.member.id,
+					createDate:createDate,
+					residentialId:this.residentialId
+				}
+				console.log(params);
+				let operation='pratique/getListByMemberId'
+				getApp().globalData.postRequest(params,operation,function(res){
+					if (!that.$isEmpty(res.data.list)) {
+						getApp().globalData.pratiqueData=res.data.list[0]
+						uni.reLaunch({
+							url:"./detail"
+						})
+					}
+				})
+			},
 			switch1Change(e){
 				this.switch1Check=e.target.value
 			},
 			switch2Change(e){
 				this.switch2Check=e.target.value
 			},
+			getUserInfo(e){
+				if (this.$isEmpty(e.detail.userInfo)) {
+					this.$u.toast('用户拒绝获取头像信息')
+					return
+				}
+				this.userInfo=e.detail.userInfo
+				uni.setStorage({
+					key:"userInfo",
+					data:this.userInfo
+				})
+				this.submit()
+			},
+			login(){
+				let that=this
+				uni.login({
+				  success: function () {
+				    uni.getUserInfo({
+				      success: function (res) {
+				        that.userInfo=res.userInfo
+						uni.setStorage({
+							key:"userInfo",
+							data:that.userInfo
+						})
+				      }
+				    });
+				  }
+				});
+			},
 			submit(){
-				this.$u.toast('待开发')
-				return
+				let that=this
+				if (this.$isEmpty(this.reason)) {
+					this.$u.toast('请输入出入原因')
+					return
+				}
+				let params={
+					memberId:this.member.id,
+					reason:this.reason,
+					residentialId:this.residentialId,
+					residentialName:this.plotName,
+					temparetureException:0,
+					symptomException:0
+				}
+				if (this.switch1Check) {
+					params.temparetureException=1
+				}
+				
+				if (this.switch2Check) {
+					params.symptomException=1
+				}
+				let operation='pratique/addPratique'
+				getApp().globalData.postRequest(params,operation,(res)=>{
+					if (res.data.result_code==1) {
+						getApp().globalData.pratiqueData=res.data.pratique
+						uni.reLaunch({
+							url:"./detail"
+						})
+					}
+				})
+			},
+			goList(){
 				uni.navigateTo({
-					url:"./detail"
+					url:"/pages/tool-list/epidemic-pass/list"
 				})
 			}
 		}

+ 120 - 0
pages/tool-list/epidemic-pass/list.vue

@@ -0,0 +1,120 @@
+<template>
+	<view>
+	 <mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback" :down="downOption" :up="upOption">
+		 <view @click="goDetail(item)" class="card" v-for="(item,index) in list" :key="index">
+		 	<view class="item top" style="padding: 15rpx 0;">
+		 		<view class="">
+		 			<u-icon name="map"></u-icon>
+		 			<text class="padding-left-10">{{item.residentialName}}</text>
+		 		</view>
+		 	</view>
+		 	<view style="margin-left: 30rpx;">
+		 		<view class="item">
+		 			<view class="">
+		 				<text>体温是否异常:</text>
+		 				<text v-if="item.temparetureException==0" class="text-green text-bold">否</text>
+						<text v-if="item.temparetureException==1" class="text-red text-bold">异常</text>
+		 			</view>
+		 		</view>
+		 		<view class="item">
+		 			<view >
+		 				<text>是否咳嗽不适:</text>
+		 				<text v-if="item.symptomException==0" class="text-green text-bold">否</text>
+		 				<text v-if="item.symptomException==1" class="text-red text-bold">异常</text>
+		 			</view>
+		 		</view>
+		 		<view class="item">
+		 			<text class="padding-right-20">登记时间:</text>
+		 			<text>{{item.createDate}}</text>
+		 		</view>
+		 	</view>
+		 </view>
+	 </mescroll-body>
+	</view>
+</template>
+
+<script>
+	import MescrollMixin from "@/comps/mescroll-body/mescroll-mixins.js";
+	export default {
+		mixins: [MescrollMixin], // 使用mixin
+		data() {
+			return {
+				list:[],
+				upOption: {
+					noMoreSize: 5, 
+					auto: true,
+					page: {
+						page: 0,
+						size: 10
+					}
+				},
+				// 下拉配置参数
+				downOption: {
+					use: true, 
+					auto: false
+				}
+			}
+		},
+		onLoad() {
+			
+		},
+		methods: {
+			goDetail(item){
+				getApp().globalData.pratiqueData=item
+				uni.navigateTo({
+					url:"./detail?show=false"
+				})
+			},
+			downCallback(){
+				setTimeout(()=>{
+					this.mescroll.resetUpScroll()
+				},1500)
+			},
+			upCallback(mescroll){
+				let that=this
+				let member=getApp().globalData.member
+				let params={
+					memberId:member.id,
+					current:mescroll.num,
+					size:mescroll.size
+				}
+				let operation='pratique/getListByMemberId'
+				try{
+					getApp().globalData.postRequest(params, operation, function (res) {
+						let data=res.data.list
+						mescroll.endBySize(data.length, res.data.total);
+						if(mescroll.num == 1) that.list = []; //如果是第一页需手动制空列表
+						that.list=that.list.concat(data); //追加新数据
+					});
+				}catch(e){
+					mescroll.endErr();
+				}
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.card{
+		margin: 10rpx;
+		padding:0 20rpx 20rpx;
+		background-color: #FFFFFF;
+		border-radius: 10rpx;
+		
+		.top{
+			border-bottom: 1rpx dashed #DEDEDE;
+			font-weight: 800;
+			margin-bottom: 20rpx;
+		}
+		
+		.item{
+			padding: 10rpx;
+		}
+		
+		.bottom{
+			border-top: 1rpx dashed #DEDEDE;
+			margin-top: 10rpx;
+			padding-right: 20rpx;
+		}
+	}
+</style>

+ 2 - 11
pages/uploadFace/uploadFace.vue

@@ -2,15 +2,6 @@
 <view>
 	<view class="" v-if="appletType==1">
 		<view>
-		<!--  <picker class="cybm_pic_1" :value="index" :range="list" :range-key="'roomName'" @change="roomChange">
-		    <view class="picker form_group">
-		      <view class="my-item">
-		        <text class="info">我的房屋</text>
-		        <text class="status">{{list[index].roomName}}</text>
-		        <text class="iconfont icon-arrow-left arrow"></text>
-		      </view>
-		    </view>
-		  </picker> -->
 		  <view class="cu-list menu" @click="locationShow=true">
 		  	<view class="cu-item" >
 		  		<view class="content">
@@ -87,7 +78,7 @@ export default {
 	  locationShow:false,
 	  selectLabel:'',
 		
-	  //上传人
+	  //上传人
 	  actionList: [{
 	  	text: '相册上传',
 	  }, {
@@ -138,7 +129,7 @@ export default {
 	 	})
 	 }else{
 	 	uni.setNavigationBarTitle({
-	 		title:"人脸录入"
+	 		title:"上传人脸"
 	 	})
 	 }
   	//获取当前页面的对象

+ 9 - 2
pages/webview/webview.vue

@@ -1,7 +1,9 @@
 <template>
-<web-view :src="url"></web-view>
+	<view class="padding-20">
+		<web-view :src="url"></web-view>
+	</view>
 </template>
-
+				
 <script>
 
 export default {
@@ -20,6 +22,11 @@ export default {
   onLoad: function (options) {
 	 this.url=options.url || ''
 	 console.log(this.url);
+	 if (!this.$isEmpty(options.title)) {
+	 	uni.setNavigationBarTitle({
+	 		title:options.title
+	 	})
+	 }
   },
 
   /**

+ 1 - 1
pages/wode/direction/direction.vue

@@ -67,10 +67,10 @@
 				display: flex;
 				justify-content: space-between;
 				padding: 0 20rpx;
-				margin-bottom: 20rpx;
 				box-sizing: border-box;
 			}
 			.body{
+				margin-top: 20rpx;
 				line-height: 48rpx;
 				padding: 10rpx 15rpx 10rpx 30rpx;
 				background-color: #F2F2F2;

+ 36 - 24
pages/wode/wode.vue

@@ -3,7 +3,7 @@
 	<view class="pageBg">
 		<view  class="header">
 			<DtCustomBar title="我的"></DtCustomBar>
-			<view @tap="tapToWhich('/pagesM/pages/mine_info')" style="display: flex;align-items: center;margin: 0 30upx;">
+			<view  style="display: flex;align-items: center;margin: 0 30upx;">
 				<view class="member_head_img">
 					<block v-if="isLogin">
 						<image v-if="userDetail.avatar" :src="userDetail.avatar"></image>
@@ -15,7 +15,7 @@
 				</view>
 				<view v-if="isLogin" class="member_info">
 					<view class="member_name_box" style="margin-bottom: 20rpx;">
-						<view class="member_name">{{ userDetail.username }}</view>
+						<view class="member_name">{{ username }}</view>
 					</view>
 					<view class="member_phone_box">
 						<!-- <view class="member_phone">{{shopPhone}}</view> -->
@@ -125,17 +125,17 @@ export default {
 					index:3
 				},
 				{
-					icon:'../../static/wode/contact.png',
-					title:"联系物业",
+					icon:'../../static/wode/jiaofei1.png',
+					title:"物业缴费",
 					badge:0,
-					index:4
+					index:5
 				},
 				{
-					icon:'../../static/wode/msg.png',
-					title:"消息通知",
+					icon:'../../static/wode/contact.png',
+					title:"联系物业",
 					badge:0,
-					index:5
-				},
+					index:4
+				}
 				
 			],
 			isFirst:false,
@@ -156,11 +156,11 @@ export default {
 					itemIcon: '/static/wode/face.png',
 					index:7
 				},
-				{
-					itemName: '身份信息',
-					itemIcon: '/static/wode/shenfen.png',
-					index:8
-				},
+				// {
+				// 	itemName: '身份信息',
+				// 	itemIcon: '/static/wode/shenfen.png',
+				// 	index:8
+				// },
 				{
 					itemName: '收货地址',
 					itemIcon: '/static/wode/address.png',
@@ -194,7 +194,6 @@ export default {
 		};
 	},
 	computed: {
-		//社区begin
 		authStatus:{
 			  get(){
 				  if(this.state==0 && this.anyHousePass==false){
@@ -208,7 +207,19 @@ export default {
 				  }
 			  }
 		},
-		//社区 end
+		username:{
+			get(){
+				if (this.$isEmpty(getApp().globalData.member)) {
+					if (this.$isEmpty(this.userDetail.username)) {
+						return this.shopPhone
+					}else{
+						return this.userDetail.username
+					}
+				}else{
+					return getApp().globalData.member.name
+				}
+			}
+		}
 	},
 	methods: {
 		async tapGetUserInfo(e) {
@@ -297,15 +308,16 @@ export default {
 					break;
 				case 4: 
 					// 联系物业
-					this.makePhoneCall("19124812874");
+					let phone= uni.getStorageSync("personTel")
+					if (this.$isEmpty(phone)) {
+						this.$u.toast('暂无电话')
+					}else{
+						this.makePhoneCall(phone);
+					}
 					break;
 				case 5:
-					//消息通知
-					if (this.buttonMethod()) {
-						uni.navigateTo({
-							url: '/pages/wode/news/news'
-						})
-					}
+					//物业缴费
+					this.$u.toast('即将开放')
 					break;
 				case 6: 
 					//住户认证
@@ -507,7 +519,7 @@ export default {
 		}
 	},
 	onShow() {
-		//小程序audit期间隐藏掉
+		//小程序审核期间隐藏掉
 		let appletType= uni.getStorageSync('appletType')
 		let tmp=this.mineItemList
 		if (appletType=='0') {

+ 37 - 18
pagesM/comps/canvas/index.vue

@@ -459,24 +459,43 @@ export default {
      */
     _downImage(imageUrl,index,type) {
       return new Promise((resolve, reject) => {
-        if (/^http/.test(imageUrl) && !new RegExp(wx.env.USER_DATA_PATH).test(imageUrl)&&type!=='qrcode') {
-          wx.downloadFile({
-            url: this._mapHttpToHttps(imageUrl),
-            success: (res) => {
-              if (res.statusCode === 200) {
-                resolve(res.tempFilePath);
-              } else {
-                reject(res.errMsg);
-              }
-            },
-            fail(err) {
-              reject(err);
-            },
-          });
-        } else {
-          // 支持本地地址
-          resolve(imageUrl);
-        }
+		  if (/^http/.test(imageUrl)) {
+		    wx.downloadFile({
+		      url: this._mapHttpToHttps(imageUrl),
+		      success: (res) => {
+		        if (res.statusCode === 200) {
+		          resolve(res.tempFilePath);
+		        } else {
+		          reject(res.errMsg);
+		        }
+		      },
+		      fail(err) {
+		        reject(err);
+		      },
+		    });
+		  } else {
+		    // 支持本地地址
+		    resolve(imageUrl);
+		  }
+		  
+        // if (/^http/.test(imageUrl) && !new RegExp(wx.env.USER_DATA_PATH).test(imageUrl)&&type!=='qrcode') {
+        //   wx.downloadFile({
+        //     url: this._mapHttpToHttps(imageUrl),
+        //     success: (res) => {
+        //       if (res.statusCode === 200) {
+        //         resolve(res.tempFilePath);
+        //       } else {
+        //         reject(res.errMsg);
+        //       }
+        //     },
+        //     fail(err) {
+        //       reject(err);
+        //     },
+        //   });
+        // } else {
+        //   // 支持本地地址
+        //   resolve(imageUrl);
+        // }
       });
     },
     /**

+ 2 - 8
pagesM/comps/canvas/poster.vue

@@ -21,11 +21,6 @@ export default {
       // 是否预下载图片资源
       type: Boolean,
       default: false
-    },
-    hideLoading: {
-      // 是否隐藏loading
-      type: Boolean,
-      default: false
     }
   },
   data() {
@@ -69,15 +64,14 @@ export default {
       });
     },
     onCreate(reset = false) {
-      !this.hideLoading && uni.showLoading({ mask: true, title: "生成中" });
       return this.downloadResource(typeof reset === "boolean" && reset)
         .then(() => {
-          !this.hideLoading && uni.hideLoading();
+          uni.hideLoading();
           const poster = this.$refs.poster;
           poster.create(this.config);
         })
         .catch(err => {
-          !this.hideLoading && uni.hideLoading();
+          uni.hideLoading();
           uni.showToast({ icon: "none", title: err.errMsg || "生成失败" });
           console.error(err);
           this.$emit("fail", err);

+ 3 - 3
pagesM/comps/dt_order_item.vue

@@ -177,7 +177,7 @@ export default {
 		.order-no {
 			color: #666666;
 			.copy {
-				color: $dt-color-primary;
+				color: #0081ff;
 				margin: 0rpx 10rpx;
 			}
 		}
@@ -271,11 +271,11 @@ export default {
 		// content: '';
 	}
 	.btn-primary {
-		background-color: $dt-color-primary;
+		background-color: $base;
 		color: #fff;
 	}
 	.btn-primary:before {
-		border-color: $dt-color-primary;
+		border-color: $base;
 		box-sizing: border-box;
 		content: '';
 	}

+ 50 - 36
pagesM/pages/goods_des.vue

@@ -240,8 +240,6 @@
 				<button @tap="closeDrawer" class="btn detail-cancel-btn">取消</button>
 			</view>
 		</view>
-		<!-- 生成二维码 -->
-		<tki-qrcode  ref="tki_qrcode" :qrval="qrval" @onQrPath="onQrPath"></tki-qrcode>
 		<!-- 生成海报 -->
 		<cover-view class="imagePathBox" :hidden="maskHidden == false" v-if="maskHidden">
 			<cover-view class="shengcheng">
@@ -266,7 +264,6 @@ import DtPoster from '../comps/canvas/poster.vue';
 import DtLogin from '../comps/dt_login.vue';
 import FootGoodsCoupon from '../comps/foot_goods_coupon.vue';
 import FootGoodsBook from '../comps/foot_goods_book.vue';
-import tkiQrcode from '../comps/tki_qrcode.vue';
 
 export default {
 	components: {
@@ -277,8 +274,7 @@ export default {
 		DtPoster,
 		DtLogin,
 		FootGoodsCoupon,
-		FootGoodsBook,
-		tkiQrcode
+		FootGoodsBook
 	},
 	data() {
 		return {
@@ -629,20 +625,6 @@ export default {
 						// _this.isAutoHeight = false;
 						_this.autoHeight();
 					}, 500);
-					
-					// if (h != _space) {
-					// 	setTimeout(() => {
-					// 		_this.isAutoHeight = parseFloat(h) < 500;
-					// 		_this.autoHeight();
-					// 	}, 400);
-					// } else if (parseFloat(h) < 500) {
-					// 	if (_this.isAutoHeight) {
-					// 		setTimeout(() => {
-					// 			_this.isAutoHeight = false;
-					// 			_this.autoHeight();
-					// 		}, 400);
-					// 	}
-					// }
 				});
 		},
 		onGoodsNumChange(delta) {
@@ -769,7 +751,7 @@ export default {
 			}
 		},
 		showPoster() {
-			this.$u.toast('开放')
+			this.$u.toast('即将开放')
 			return
 			
 			if (this.isclick) {
@@ -785,16 +767,48 @@ export default {
 			if(this.$auth.isPromoter(true)){
 				inviteCode = this.$auth.getMemberId();
 			}
-			let path = `https://wap.lezhuapp.com/wapp/qrcode/`;
-			let param = encodeURI(`type=share&id=${this.base.id}&storeId=${this.base.store.id}&path=${currentPage.route}&inviteCode=${inviteCode}`)
-			this.qrval = path + param;
-			this.$refs.tki_qrcode.ifQrcode()
+			if (this.$isEmpty(inviteCode)) {
+				inviteCode=0
+			}
+			//由于微信小程序码的scence参数长度的限制,参数越简洁越好
+			let scene=this.base.id+","+this.base.store.id+","+inviteCode
+			this.getGenerateCode(scene)
 		},
-		onQrPath(res){
-			console.log(res)
-			this.drawPoster(res);
+		/**
+		 * 生成二维码
+		 */
+		getGenerateCode(scene){
+			uni.showLoading({
+				title:"生成中..."
+			})
+			let that=this
+			let operation='miniprogram/getAccessToken'
+			let params={
+				appId:this.$wxData.APPID,
+				secret:this.$wxData.SECRET,
+				grantType:this.$wxData.GRANTTYPE
+			}
+			getApp().globalData.postRequest(params,operation,function(res){
+				let params={
+					access_token:res.data.access_token,
+					scene:scene,
+					page:'pages/index/index',
+					width:60
+				}
+				let operation="miniprogram/generateCode"
+				setTimeout(()=>{
+					getApp().globalData.postRequest(params,operation,(res)=>{
+						//生成海报
+						that.drawPoster(res.data)
+					})
+				},800)
+			})
 		},
-		drawPoster(res) {
+		/**
+		 * 生成海报
+		 * @param {Object} qrImg 二维码图片
+		 */
+		drawPoster(qrImg) {
 			this.$set(this, 'posterConfig', {
 				width: 750,
 				height: 1334,
@@ -812,11 +826,11 @@ export default {
 						zIndex: 2
 					},
 					{
-						x: 510,
-						y: 1000,
-						width: 200,
-						height: 200,
-						url: res,
+						x: 480,
+						y: 950,
+						width: 260,
+						height: 260,
+						url: qrImg,
 						zIndex: 2,
 						type:'qrcode'
 					}
@@ -826,7 +840,7 @@ export default {
 						x: 35,
 						y: 1000,
 						text: this.base.name,
-						fontSize: 30,
+						fontSize: 32,
 						color: '#333333',
 						lineHeight: 50,
 						lineNum: 3,
@@ -850,6 +864,7 @@ export default {
 					}
 				]
 			});
+			uni.hideLoading()
 			this.$nextTick(() => {
 				this.$refs.dtPoster.onCreate();
 			});
@@ -857,7 +872,6 @@ export default {
 		closePoster() {
 			this.maskHidden = false;
 			this.isclick = false;
-			this.$refs.tki_qrcode.ifQrcode()
 		},
 		onPosterSuccess(path) {
 			this.imagePosterPath = path;
@@ -1780,7 +1794,7 @@ image {
 		z-index: 1200;
 		top: 1000upx;
 		left: 10%;
-		background: $dt-color-primary;
+		background: $base;
 		color: #fff;
 		font-size: 30upx;
 		border-radius: 10upx;

+ 0 - 1781
pagesM/pages/goods_des_old.vue

@@ -1,1781 +0,0 @@
-<template>
-	<view class="pageBg">
-		<!-- 商品图片 -->
-		<!-- productImages -->
-		<view class="goods_img_box">
-			<swiper
-				class="swiper"
-				interval="5000"
-				duration="500"
-				autoplay="true"
-				circular="true"
-				:indicator-dots="base.productImages!==undefined&&base.productImages.length>1"
-				indicator-color="#E5E5E5"
-				indicator-active-color="#888888"
-			>
-				<block v-if="base.productImages!==undefined&&base.productImages.length>0">
-					<swiper-item v-for="(item, index) in base.productImages" :key="index">
-						<image class="image" mode="aspectFill" :src="item.large" @tap="roopHeadImage(item.large)"></image>
-					</swiper-item>
-				</block>
-				<block v-else>
-					<swiper-item><image class="image" mode="aspectFill" :src="base.thumbnail || 'http://139.9.103.171:1888/img/image/goods_def.png'"></image></swiper-item>
-				</block>
-			</swiper>
-		</view>
-
-		<!-- 商品信息 -->
-		<view class="goods_info_box">
-			<view class="flex  bg-red padding-30">
-				<text class="text-price text-lg">{{ base.price ? base.price : '' }}</text>
-				<text class="textprice text-sm text-line-through">{{ base.marketPrice ? base.marketPrice : '' }}</text>
-			</view>
-			<!-- <view class="goods_price_share">
-				<view class="price">
-					<text class="sell_price">¥{{ base.price ? base.price : '' }}</text>
-					<text class="original_price">¥{{ base.marketPrice ? base.marketPrice : '' }}</text>
-				</view>
-				<image class="share_icon_btn" @tap="shareDrawer" src="http://139.9.103.171:1888/img/image/share_icon.png" mode="widthFix"></image>
-				<button class="share_icon_btn" @tap="shareDrawer"><image class="share_icon" src="http://139.9.103.171:1888/img/image/share_icon.png"></image></button>
-			</view> -->
-			<view class="goods_time_title">
-				<text class="goods_title" selectable="true">{{ base.name ? base.name : '' }}</text>
-			</view>
-			<view class="goods_active">
-				<!-- <view class="active_item">特价抢购</view>
-        <view class="active_item">1元换购</view>
-        <view class="active_item">包邮</view> -->
-			</view>
-			<view class="goods_des">{{ base.caption ? base.caption : '' }}</view>
-			<view class="goods_inventory_sales">
-				<!-- <text>月销量:{{ base.monthSales ? base.monthSales : 0 }}</text> -->
-				<text v-if="true">库存:{{ defaultAvailableStock }}</text>
-			</view>
-		</view>
-
-		<!-- 是否包邮 -->
-		<view
-			class="get_coupon"
-			v-if="
-				(base != null && base.promotion != null && base.promotion.freeShipping != null && base.promotion.freeShipping.isenabled) ||
-					(moneyOffsList != null && moneyOffsList.length > 0)
-			"
-		>
-			<view class="get_coupon_text">促销活动</view>
-			<view class="coupon">
-				<view class="coupon_list">
-					<view class="coupon_item">包邮</view>
-					<view class="coupon_list" v-for="(item, index) in moneyOffsList" :key="index">
-						<!-- 统一处理方式 -->
-						<view class="coupon_item" v-if="item.promotionNames.length > 0">{{ item.promotionNames }}</view>
-						<!-- <view class="coupon_item" v-if="item.discounttype == 0">满{{item.minprice}}减{{item.discounvalue}}</view> -->
-						<!-- 固定价格 -->
-						<!-- <view class="coupon_item" v-if="item.discounttype == 1">满{{item.minprice}}减{{item.discounvalue}}</view> -->
-						<!-- 金额减免 -->
-						<!-- <view class="coupon_item" v-if="item.discounttype == 2">{{item.minprice > 0 ? '满' + item.minprice : ''}} {{item.discounvalue}}折</view> -->
-						<!-- 百分比减免 -->
-						<!-- <view class="coupon_item" v-if="item.discounttype == 3">满{{item.minprice}}减{{item.discounvalue}}</view> -->
-						<!-- 重复金额减免 -->
-					</view>
-				</view>
-			</view>
-		</view>
-
-		<!-- 满减 -->
-		<!-- <view class="get_coupon" v-if="">
-      <view class="get_coupon_text">满减</view>
-      <view class="coupon">
-        <view class="coupon_list" v-for="(item,index) in moneyOffsList" :key="index">
-          <view class="coupon_item">满{{item.minprice}}减{{item.discounvalue}}</view>
-        </view>
-      </view>
-    </view> -->
-
-		<!-- 赠品 -->
-		<view class="get_coupon" v-if="giftsList != null && giftsList.length > 0">
-			<view class="get_coupon_text">赠品</view>
-			<view class="coupon">
-				<view class="coupon_list" v-for="(item, index) in giftsList" :key="index">
-					<view class="coupon_item">{{ item.name }}</view>
-				</view>
-			</view>
-		</view>
-			
-		<!-- 领取优惠券-->
-		<view class="get_coupon" v-if="base.promotion&&base.promotion.coupon!==undefined&&couponList.length > 0">
-			<view class="get_coupon_text">领取优惠券</view>
-			<view class="coupon" @tap="showCouponBox">
-				<view class="coupon_list">
-					<view class="coupon_item">{{ base.promotion.coupon.name }}</view>
-				</view>
-				<image src="http://139.9.103.171:1888/img/image/arrow.png"></image>
-			</view>
-		</view>
-		
-		<!-- 保障 -->
-		<view class="get_coupon" >
-			<view class="get_coupon_text">保障</view>
-			<view class="coupon">
-				<view style="font-size: 20upx;margin-right: 20upx;">
-					24小时无理由退换货
-				</view>
-			</view>
-		</view>
-			
-		<!-- 商品详细信息 -->
-		<view class="goods_detail_info_box">
-			<view class="goods_detail_tab">
-				<view :class="['goods_tab_item', current == 0 ? 'good_tab_item_active' : '']" @tap="tapTabItem(0)">图文详情</view>
-				<view :class="['goods_tab_item', current == 1 ? 'good_tab_item_active' : '']" @tap="tapTabItem(1)">商品参数</view>
-				<view :class="['goods_tab_item', current == 2 ? 'good_tab_item_active' : '']" @tap="tapTabItem(2)">
-					商品评价
-					<text v-if="reviewProdCount > 0">({{ reviewProdCount }})</text>
-				</view>
-			</view>
-			<swiper class="tab_content" :current="current" duration="300" @change="switchTab" :style="{ height: swiper_height }">
-				<swiper-item>
-					<view id="start0"></view>
-					<view class="tab1" v-if="info"><rich-text :nodes="info"></rich-text></view>
-					<view class="no_data_wrap" v-else><DtNoData msg="暂无数据" /></view>
-					<view id="end0"></view>
-				</swiper-item>
-				<swiper-item>
-					<view id="start1"></view>
-					<view class="tab2" v-if="introduction.length > 0">
-						<view class="goods_params_list">
-							<view class="goods_params_item" v-for="(item, index) in introduction" :key="index">
-								<view class="goods_params_title">【{{ item.name }}】</view>
-								<view class="goods_params_des">{{ item.value }}</view>
-							</view>
-						</view>
-						<view class="check_btn" @tap="jumpmanual">查看完整说明书</view>
-					</view>
-					<view class="no_data_wrap" v-else><DtNoData msg="暂无数据" /></view>
-					<view id="<end1></end1>"></view>
-				</swiper-item>
-				<swiper-item>
-					<view id="start2"></view>
-					<view class="tab3" v-if="reviewDatas.length > 0">
-						<DtGoodsComment :dataList="reviewDatas" @tapImage="roopImageClick" />
-						<view class="check_btn" @tap="moreGoodsComment">查看更多的评价</view>
-					</view>
-					<view class="no_data_wrap" v-else><DtNoData msg="暂无数据" /></view>
-					<view id="end2"></view>
-				</swiper-item>
-			</swiper>
-		</view>
-
-		<!--推荐商品-->
-		<view clsss="recommend" style="background:#F2F2F2">
-			<DtRecommendWrap title="为您推荐" />
-			<DtRecommendGoodsList :height="150" :dataList="recommendGoodsList" />
-		</view>
-
-		<!-- 工具栏 -->
-		<view class="tool_height" :style="footSafe"></view>
-		<view class="goods_sell_out_tip" v-if="!base.isMarketable">该商品正在补货中,先瞧瞧别的吧~</view>
-		<view class="goods_tool" :style="footSafe">
-			<view class="left">
-				<button
-					class="item item_btn"
-					open-type="contact"
-					session-from="weapp"
-					:send-message-title="base.name"
-					:send-message-path="'pages/goods_des?id=' + loadOptions.id"
-					:show-message-card="true"
-				>
-					<image src="http://139.9.103.171:1888/img/image/service_concat_icon.png" style="margin-top: -10upx;"></image>
-					<text>咨询</text>
-				</button>
-				<view class="item" @tap="setProductFavorite">
-					<image src="http://139.9.103.171:1888/img/image/collection_success_icon.png" v-if="isFavorite"></image>
-					<image src="http://139.9.103.171:1888/img/image/collection_icon.png" v-else></image>
-					<text>收藏</text>
-				</view>
-				<view class="item shop_car" @tap="goToShopCar">
-					<image src="http://139.9.103.171:1888/img/image/shop_icon.png"></image>
-					<text>购物车</text>
-					<view class="tip_count" v-if="shopCartNum > 0">{{ shopCartNum }}</view>
-				</view>
-			</view>
-			<view class="right">
-				<view class="sell_out" v-if="!base.isMarketable">已售罄</view>
-				<block v-else>
-					<view class="item add_shop_car" @tap="joinShopCar">加入购物车</view>
-					<view class="item buy" @tap="buyNow">{{ base.drugType == 'RX' ? '提交需求' : '立即购买' }}</view>
-					<!-- <view class="item buy" @tap="buyNow">立即购买</view> -->
-				</block>
-			</view>
-		</view>
-		<FootGoodsBook
-			ref="footBook"
-			:number.sync="number"
-			:specifications="specifications"
-			:selectSpecificationValueMaps="selectSpecificationValueMaps"
-			:base="base"
-			:selectSkuItemObj="selectSkuItemObj"
-			@selectsku="selectSku"
-			@goodsnum="onGoodsNumChange"
-			@goodsnumblur="blurInputNumber"
-			@confirm="confirmAddOrBuy"
-		/>
-		<view v-if="showDistributorCoupon" class="drawer_screen" ></view>
-		<view v-if="showDistributorCoupon" style="padding: 40upx;width: 400upx;height: 400upx;position: fixed;top: 0;left: 0;right: 0;bottom: 0; margin: auto;background-color: #fc7700;z-index: 10000;border-radius: 20upx;">
-			<image src="http://139.9.103.171:1888/img/image/close2.png" style="width: 50upx;position: absolute;top: -100upx;right: 0;" mode="widthFix" @tap="showDistributorCoupon=false"></image>
-			<view style="color: #fff;text-align: center;margin-bottom: 20upx;font-size: 34upx;">恭喜您获得优惠券</view>
-			<view  style="display: flex;position: relative;">
-				<image src="http://139.9.103.171:1888/img/image/coupon_img_white.png" style="width: 100%;display: block;" mode="widthFix"></image>
-				<view style="position: absolute;top:0;left:0;right:0;padding: 20upx;display: flex;justify-content: space-between;">
-					<view>
-						<view style="font-size: 28upx;line-height: 60upx;">{{distributorCoupon.name}}</view>
-						<view style="font-size: 20upx;color: gray;line-height: 60upx;">{{distributorCoupon.beginDate}}-{{distributorCoupon.endDate}}</view>
-					</view>
-					<view style="margin-right: 20upx;">
-						<view style="color: red;font-size: 32upx;line-height: 60upx;">¥{{distributorCoupon.amt}}</view>
-						<view style="font-size: 22upx;color: gray;line-height: 60upx;">{{distributorCoupon.type}}</view>
-					</view>
-				</view>
-			</view>
-			<button  @tap="onRecieve(distributorCoupon)" style="border-radius: 25px;line-height: 80upx;margin-top: 90upx;text-align: center;background-color: #fed116;color: #fc7700;">立即领取</button>
-		</view>
-		<!-- 产品优惠券列表 -->
-		<FootGoodsCoupon ref="footCoupon" :dataList="couponList" @visible="onVisible" @receive="onRecieve" />
-		
-		<!-- 使用animation属性指定需要执行的动画 -->
-		<view class="drawer_screen" @tap="closeDrawer" v-if="bg"></view>
-		<view :animation="animationData" class="drawer_attr_box" v-if="sharediv">
-			<view class="drawer_content">
-				<button open-type="share" class="btn">发送给好友</button>
-				<button @tap="showPoster" class="btn">生成海报</button>
-				<button @tap="closeDrawer" class="btn detail-cancel-btn">取消</button>
-			</view>
-		</view>
-		<!-- 生成二维码 -->
-		<tki-qrcode  ref="tki_qrcode" :qrval="qrval" @onQrPath="onQrPath"></tki-qrcode>
-		<!-- 生成海报 -->
-		<cover-view class="imagePathBox" :hidden="maskHidden == false" v-if="maskHidden">
-			<cover-view class="shengcheng">
-				<cover-image src="http://139.9.103.171:1888/img/image/close2.png" class="shareClose" @tap="closePoster"></cover-image>
-				<cover-image v-if="imagePosterPath" :src="imagePosterPath" class="shengcheng" mode="aspectFill"></cover-image>
-			</cover-view>
-			<button class="save" @tap="picdown">保存图片</button>
-		</cover-view>
-		<cover-view :hidden="maskHidden == false" class="mask"></cover-view>
-		<DtPoster ref="dtPoster" id="poster" :config="posterConfig" @success="onPosterSuccess" @fail="onPosterFail" />
-
-		<DtLogin ref="dialogLogin" @signIn="onSignIn"/>
-	</view>
-</template>
-
-<script>
-import DtGoodsComment from '../comps/dt_goods_comment.vue';
-import DtRecommendWrap from '../comps/dt_recommend_wrap.vue';
-import DtRecommendGoodsList from '../comps/dt_recommend_goods_list.vue';
-import DtNoData from '../comps/dt_no_data.vue';
-import DtPoster from '../comps/canvas/poster.vue';
-import DtLogin from '../comps/dt_login.vue';
-import FootGoodsCoupon from '../comps/foot_goods_coupon.vue';
-import FootGoodsBook from '../comps/foot_goods_book.vue';
-import tkiQrcode from '../comps/tki_qrcode.vue';
-
-export default {
-	components: {
-		DtGoodsComment,
-		DtNoData,
-		DtRecommendWrap,
-		DtRecommendGoodsList,
-		DtPoster,
-		DtLogin,
-		FootGoodsCoupon,
-		FootGoodsBook,
-		tkiQrcode
-	},
-	data() {
-		return {
-			isAutoHeight: true,
-			selectedTab: 0,
-			isLogin: false,
-			imageURL:'http://139.9.103.171:1888/img/image/coupon_img_white.png',	
-			swiper_height: 0,
-			space: '\xa0\xa0',
-			isWaitShow: false,
-			current: 0,
-			content: '',
-			showToastBox: false,
-			bg: false,
-			sharediv: false,
-			animationData: '',
-
-			posterConfig: {},
-			imagePosterPath: '',
-			maskHidden: false,
-			isclick: false,
-
-			reviewProdCount: 0,
-			productId: 0,
-			base: {},
-
-			reviewDatas: [],
-			couponList: [],
-			moneyOffsList: [],
-			giftsList: [],
-
-			goodsDetailInfo: {},
-			recommendGoodsList: [],
-			defaultAvailableStock: 0,
-
-			isFavorite: false, //是否收藏
-
-			number: 1, //购买数量
-			operationType: 1, //1添加购物车 2立即购买
-
-			shopCartNum: 0, //购物车种类数量
-
-			skus: [], //选中所有sku的不同情况数组
-			specifications: [], //所有sku
-
-			selectSpecificationValueMaps: {}, //选中sku
-			selectSkuItemObj: {}, //选中sku对应的情况
-
-			waitShow: false,
-
-			manual: [],
-
-			srcs: [],
-			imgBox: [],
-			inviteCode:null, //邀请码id (分销优惠券参数)
-			showDistributorCoupon:false,
-			distributorCoupon:null,
-			qrval:'',
-		};
-	},
-	computed: {
-		footSafe() {
-			return 'padding-bottom:' + this.safeAreaBottom + 'px';
-		},
-		info() {
-			let info = this.goodsDetailInfo.info;
-			if (!info) {
-				return '';
-			}
-			info = info.replace(/style=\"(.*?)\"/gi, '').replace(/<img/g, '<img style="width:100%;"');
-			return info;
-		},
-		introduction() {
-			let entriesList = [];
-			if (this.goodsDetailInfo.introduction && this.goodsDetailInfo.introduction.length > 0) {
-				this.goodsDetailInfo.introduction.forEach(introduction => {
-					introduction.entries.forEach(item => {
-						entriesList.push(item);
-					});
-				});
-			}
-			this.manual = entriesList;
-			return entriesList.slice(0, 5);
-		}
-	},
-	methods: {
-		//查看详情
-		onVisible(ev, idx) {
-			let couponList = this.couponList.slice(0);
-			couponList[idx].isShowDetail = !couponList[idx].isShowDetail;
-			console.log(330, couponList);
-			this.$set(this, 'couponList', couponList);
-		},
-		// 领取优惠券
-		async onRecieve(item) {
-			console.log('get Voucher', item);
-			let memberId = this.$auth.getMemberId();
-			let resp = await this.$api.couponExchange({
-				_isShowLoading: true,
-				memberId: memberId,
-				couponId: item.id
-			});
-			if (resp.result) {
-				this.showDistributorCoupon = false;
-				this.$dialog.success('领取成功');
-				this.getCouponByProductId();
-			} else {
-				this.$dialog.error('领取失败');
-			}
-		},
-		/**
-		 * 获取选中的sku对应的对象
-		 * @param {Object} selectSpecificationValueMaps
-		 * @return {Number} -1:组合不存在;1:选择成功;2:库存不足
-		 */
-		selectSkusItem(selectSpecificationValueMaps) {
-			let isSelectAll = this.isSelectAllSku(selectSpecificationValueMaps);
-			if (!isSelectAll) return 1;
-			let skuItemObjArr = [];
-			for (let sku of this.skus) {
-				let num = 0;
-				for (let spc of sku.specificationValues) {
-					for (let key in selectSpecificationValueMaps) {
-						let item = selectSpecificationValueMaps[key];
-						if (item.id + item.value == spc.id + spc.value) {
-							num++;
-							break;
-						}
-					}
-				}
-				if (num == sku.specificationValues.length) {
-					if(sku.availableStock <= 0){
-						return 2;
-					}
-					this.selectSkuItemObj = sku;
-					this.number = sku.wholesaleNumStart;
-					return 1;
-				}
-			}
-			return -1;
-		},
-
-		selectSku(skuIndex, item) {
-			if (this.skus != null && this.skus.length > 0) {
-				let isOk = 0;
-				for (let sku of this.skus) {
-					if (sku.specificationValues != null && sku.specificationValues.length > 0) {
-						for (let s of sku.specificationValues) {
-							if (s.id + s.value == item.id + item.value) {
-								let json = JSON.stringify(this.selectSpecificationValueMaps);
-								let temp = JSON.parse(json);
-								temp[skuIndex + ''] = { id: item.id, value: item.value };
-								if(skuIndex == 0 && temp['1'] != null){
-									this.selectSkuItemObj = {};
-									this.selectSkuItemObj[skuIndex + ''] = { id: item.id, value: item.value };
-									this.selectSpecificationValueMaps = {};
-									this.selectSpecificationValueMaps[skuIndex + ''] = { id: item.id, value: item.value };
-									this.number = 0;
-									this.$forceUpdate();
-									return;
-								}
-								isOk = this.selectSkusItem(temp);
-								if (isOk == 1) {
-									this.selectSpecificationValueMaps[skuIndex + ''] = { id: item.id, value: item.value };
-									break;
-								}else if(isOk == 2) break;
-							}
-						}
-					}
-					if (isOk > 0) break;
-				}
-				if (isOk == -1) uni.showToast({icon: 'none',title: '暂无此商品'});
-				if (isOk == 2) uni.showToast({icon: 'none',title: '库存不足'});
-				this.$forceUpdate();
-			}
-		},
-
-		//是否选完sku的规格
-		isSelectAllSku(maps) {
-			if (maps == null) maps = this.selectSpecificationValueMaps;
-			let length = 0;
-			for (let key in maps) {
-				if (maps[key] != null) length++;
-			}
-			return length == this.specifications.length;
-		},
-		
-		async confirmAddOrBuy() {
-			if (!this.isSelectAllSku()) {
-				this.$dialog.toast('请选择所有相关选项!');
-				return;
-			}
-			this.$refs.footBook.hide();
-			if (this.operationType == 1) {
-				if (this.shopCartNum >= 100) {
-					this.$dialog.toast('购物车已满');
-					return;
-				}
-				let dataArr = [];
-				let data = {};
-				data.skuId = this.selectSkuItemObj.id;
-				data.quantity = this.number;
-				dataArr.push(data);
-				let res = await this.$api.cartAdds(dataArr);
-				this.$dialog.toast('添加购物车成功');
-				this.cartKindCount();
-				this.$util.refreshPage(['pages/shop_car']);
-			}
-
-			if (this.operationType == 2) {
-				let data = {};
-				data.skuId = this.selectSkuItemObj.id;
-				data.quantity = this.number;
-				let paramsStr = JSON.stringify(data);
-				let isCanBuy = await this.$api.checkCartBuy(data);
-				this.$refs.footBook.hide();
-				if (isCanBuy) {
-					let params = {
-						params: paramsStr,
-						flag: this.$global.orderFlag.normal
-					};
-					uni.navigateTo({
-						url: '/pagesM/pages/order_confirm?' + this.$util.serialize(params)
-					});
-				}
-			}
-
-			this.closeToastBox();
-		},
-
-		//加入购物车
-		joinShopCar() {
-			let inviteCode = this.$auth.getInviteCode()
-			if (!this.$auth.isAuth) {
-				this.showLogin()
-				return
-			}else if(inviteCode!==null){//针对已登录情况
-				this.showLogin();
-				return
-			}
-			if (this.specifications.length == 0) {
-				this.$dialog.toast('暂无规格可选');
-				return;
-			}
-			// this.showToastBox = true;
-			this.$refs.footBook.show();
-			this.operationType = 1;
-		},
-
-		//立即购买
-		buyNow() {
-			let inviteCode = this.$auth.getInviteCode()
-			if (!this.$auth.isAuth) {
-				this.showLogin()
-				return
-			}else if(inviteCode!==null){//针对已登录情况
-				this.showLogin();
-				return
-			}
-			if (this.specifications.length == 0) {
-				this.$dialog.toast('暂无规格可选');
-				return;
-			}
-			// this.showToastBox = true;
-			
-			this.operationType = 2;
-			this.$refs.footBook.show();
-		},
-		//跳转购物车
-		goToShopCar() {
-			console.log("111")
-			uni.navigateTo({
-				url:'/pagesM/pages/shop_car'
-			})
-		},
-		//领取优惠券
-		showCouponBox() {
-			let inviteCode = this.$auth.getInviteCode()
-			if (!this.$auth.isAuth) {
-				this.showLogin()
-				return
-			}else if(inviteCode!==null){//针对已登录情况
-				this.showLogin();
-				return
-			}
-			// this.showCouponToastBox = true;
-			// console.log(this.$refs)
-			this.$refs.footCoupon.show();
-		},
-
-		//设置收藏
-		async setProductFavorite() {
-			let inviteCode = this.$auth.getInviteCode()
-			if (!this.$auth.isAuth) {
-				this.showLogin()
-				return
-			}else if(inviteCode!==null){//针对已登录情况
-				this.showLogin();
-				return
-			}
-			let data = {};
-			data.productId = this.productId;
-			data.memberId = this.$auth.getMemberId();
-			let res = await this.$api.setProductFavorite(data);
-			this.$util.refreshPage(['pages/mine_collection']);
-			this.isFavorite = res.result;
-			this.$dialog.toast(res.result ? '收藏成功' : '取消收藏');
-		},
-
-		switchTab(e) {
-			this.current = e.detail.current;
-			this.autoHeight();
-		},
-		tapTabItem(current) {
-			this.current = current;
-		},
-		autoHeight() {
-			if(!this.isAutoHeight) return;
-			let current = this.current;
-			let _this = this;
-			uni.createSelectorQuery()
-				.select('#end' + current)
-				.boundingClientRect()
-				.select('#start' + current)
-				.boundingClientRect()
-				.exec(rect => {
-					let top1 = rect == null || rect[0] == null || rect[0].top == null ? 0 : rect[0].top;
-					let top2 = rect == null || rect[1] == null || rect[1].top == null ? 0 : rect[1].top;
-					let _space = Math.abs(top1 - top2);
-					_space = _space === 0 ? '100%' : _space + 'px';
-					const h = _this.swiper_height;
-					if(_this.selectedTab != current){
-						_this.selectedTab = current;
-						_this.swiper_height = parseFloat(_space) < 500 ? '500px' : _space;
-					}else if (parseFloat(_this.swiper_height) <= parseFloat(_space)) _this.swiper_height = _space;
-					// Log.e(`================${_this.base.name}>>>h = ${h}; top1 = ${top1};  top2 = ${top2};  _space = ${_space}`);
-					_this.$forceUpdate();
-					setTimeout(() => {
-						// _this.isAutoHeight = false;
-						_this.autoHeight();
-					}, 500);
-					
-					// if (h != _space) {
-					// 	setTimeout(() => {
-					// 		_this.isAutoHeight = parseFloat(h) < 500;
-					// 		_this.autoHeight();
-					// 	}, 400);
-					// } else if (parseFloat(h) < 500) {
-					// 	if (_this.isAutoHeight) {
-					// 		setTimeout(() => {
-					// 			_this.isAutoHeight = false;
-					// 			_this.autoHeight();
-					// 		}, 400);
-					// 	}
-					// }
-				});
-		},
-		onGoodsNumChange(delta) {
-			if (delta < 0) {
-				if (this.number == 1) {
-					return;
-				}
-				if (this.number <= this.selectSkuItemObj.wholesaleNumStart) {
-					this.$dialog.toast('该商品起批量为' + this.selectSkuItemObj.wholesaleNumStart);
-					return;
-				}
-				this.number--;
-			} else {
-				if (this.number >= this.selectSkuItemObj.purchaseLimit && this.selectSkuItemObj.purchaseLimit > 0) {
-					return;
-				}
-				if (this.number >= this.selectSkuItemObj.availableStock) {
-					this.$dialog.toast('该商品库存不足');
-					return;
-				}
-				this.number++;
-			}
-		},
-		lessAction() {
-			if (this.number == 1) {
-				return;
-			}
-			if (this.number <= this.selectSkuItemObj.wholesaleNumStart) {
-				this.$dialog.toast('该商品起批量为' + this.selectSkuItemObj.wholesaleNumStart);
-				return;
-			}
-			this.number--;
-		},
-		addAction() {
-			if (this.number >= this.selectSkuItemObj.purchaseLimit && this.selectSkuItemObj.purchaseLimit > 0) {
-				return;
-			}
-			if (this.number >= this.selectSkuItemObj.availableStock) {
-				this.$dialog.toast('该商品库存不足');
-				return;
-			}
-			this.number++;
-		},
-
-		blurInputNumber(e) {
-			let number = e.detail.value ? e.detail.value : 1;
-			if (this.selectSkuItemObj.wholesaleNumStart) {
-				let wholesaleNumStart = this.selectSkuItemObj.wholesaleNumStart;
-				let availableStock = this.selectSkuItemObj.availableStock;
-				if (number < wholesaleNumStart) {
-					this.number = wholesaleNumStart;
-					this.$dialog.toast('该商品起批量为' + wholesaleNumStart);
-					return;
-				}
-				if (number > availableStock) {
-					this.number = wholesaleNumStart;
-					this.$dialog.toast('该商品库存不足');
-					return;
-				}
-				this.number = number;
-			} else {
-				this.number = number;
-			}
-		},
-
-		closeToastBox() {
-			this.showToastBox = false;
-		},
-		shareDrawer() {
-			this.animationDrawer("open")
-			// this.shareFriend();
-		},
-		closeDrawer() {
-			this.isclick = false;
-			this.animationDrawer('close');
-		},
-		shareFriend() {
-			this.bg = false;
-			this.sharediv = false;
-			this.isclick = false;
-			uni.showShareMenu({
-				withShareTicket: true
-			});
-		},
-
-		animationDrawer(currentStatu) {
-			/* 动画部分 */
-			// 第1步:创建动画实例
-			var animation = wx.createAnimation({
-				duration: 200, //动画时长
-				timingFunction: 'linear', //线性
-				delay: 0 //0则不延迟
-			});
-
-			// 第2步:这个动画实例赋给当前的动画实例
-			this.animation = animation;
-
-			// 第3步:执行第一组动画:Y轴偏移240px后(盒子高度是240px),停
-			animation.translateY(240).step();
-
-			// 第4步:导出动画对象赋给数据对象储存
-			this.animationData = animation.export();
-
-			// 第5步:设置定时器到指定时候后,执行第二组动画
-			setTimeout(
-				function() {
-					// 执行第二组动画:Y轴不偏移,停
-					animation.translateY(0).step();
-					// 给数据对象储存的第一组动画,更替为执行完第二组动画的动画对象
-					this.animationData = animation;
-					//关闭抽屉
-					if (currentStatu == 'close') {
-						this.bg = false;
-						this.sharediv = false;
-					}
-				}.bind(this),
-				200
-			);
-
-			// 显示抽屉
-			if (currentStatu == 'open') {
-				this.bg = true;
-				this.sharediv = true;
-			}
-		},
-		showPoster() {
-			this.$u.toast('未开放')
-			return
-			
-			if (this.isclick) {
-				return;
-			}
-			this.isclick = true;
-			// 获取页面path
-			let pages = getCurrentPages(); //获取加载的页面
-			let currentPage = pages[pages.length - 1]; //获取当前页面的对象
-			let inviteCode = null;
-			let resp = this.$auth.getMemberInfo();
-			if(this.$auth.isPromoter(true)){
-				inviteCode = this.$auth.getMemberId();
-			}
-			let path = `https://wap.lezhuapp.com/wapp/qrcode/`;
-			let param = encodeURI(`type=share&id=${this.base.id}&storeId=${this.base.store.id}&path=${currentPage.route}&inviteCode=${inviteCode}`)
-			this.qrval = path + param;
-			this.$refs.tki_qrcode.ifQrcode()
-		},
-		onQrPath(res){
-			console.log(res)
-			this.drawPoster(res);
-		},
-		drawPoster(res) {
-			this.$set(this, 'posterConfig', {
-				width: 750,
-				height: 1334,
-				backgroundColor: '#ffffff',
-				debug: true,
-				pixelRatio: 2,
-				preload: true,
-				images: [
-					{
-						x: 35,
-						y: 60,
-						width: 680,
-						height: 850,
-						url: this.base.thumbnail || 'http://139.9.103.171:1888/img/image/goods_def.png',
-						zIndex: 2
-					},
-					{
-						x: 510,
-						y: 1000,
-						width: 200,
-						height: 200,
-						url: res,
-						zIndex: 2,
-						type:'qrcode'
-					}
-				],
-				texts: [
-					{
-						x: 35,
-						y: 1000,
-						text: this.base.name,
-						fontSize: 30,
-						color: '#333333',
-						lineHeight: 50,
-						lineNum: 3,
-						textAlign: 'left',
-						fontFamily: 'SourceHanSansRegular',
-						zIndex: 11,
-						width: 400
-					},
-					{
-						x: 35,
-						y: 1200,
-						text: '¥' + this.base.price,
-						fontSize: 60,
-						color: '#D32222',
-						lineHeight: 50,
-						lineNum: 3,
-						textAlign: 'left',
-						fontFamily: 'SourceHanSansRegular',
-						zIndex: 11,
-						width: 400
-					}
-				]
-			});
-			this.$nextTick(() => {
-				this.$refs.dtPoster.onCreate();
-			});
-		},
-		closePoster() {
-			this.maskHidden = false;
-			this.isclick = false;
-			this.$refs.tki_qrcode.ifQrcode()
-		},
-		onPosterSuccess(path) {
-			this.imagePosterPath = path;
-			this.maskHidden = true;
-			this.isclick = false;
-		},
-		onPosterFail(e) {
-			this.isclick = false;
-		},
-		picdown() {
-			uni.saveImageToPhotosAlbum({
-				filePath: this.imagePosterPath,
-				success: res => {
-					console.log(res);
-					this.$dialog.success('图片已保存到相册,赶紧晒一下吧');
-					this.maskHidden = false;
-					this.sharediv = false;
-					this.bg = false;
-					this.isclick = false;
-				},
-				fail: res => {
-					if (res.errMsg == 'saveImageToPhotosAlbum:fail cancel') {
-						return;
-					}
-					if (res.errMsg == 'saveImageToPhotosAlbum:fail auth deny') {
-						this.$dialog.confirm({
-							content: '需要使用保存图片或视频到系统相册功能,请确认授权打开',
-							showCancel: false,
-							success: confirmRes => {}
-						});
-					}
-				}
-			});
-		},
-
-		// 通过商品id获取优惠券列表
-		async getCouponByProductId() {
-			let memberId = this.$auth.getMemberId();
-			let data = {};
-			data.productId = this.base.id;
-			data.memberId = memberId;
-			let resp = await this.$api.getCouponByProductId(data);
-			console.log(resp);
-			this.couponList = resp;
-			return resp;
-		},
-		//通过商品id获取分销优惠券列表
-		async getDistributorCoupon(){
-			let memberId = this.$auth.getMemberId();
-			let data = {};
-			data.productId = this.productId;
-			// data.inviteCode = this.inviteCode;
-			data.memberId = memberId;
-			let resp = await this.$api.getDistributorCouponByProductId(data);
-			if(JSON.stringify(resp) == '{}'||resp==''||resp==null||resp==undefined){return;}
-			this.distributorCoupon = resp;
-			this.distributorCoupon.beginDate = resp.beginDate.substr(0,10);
-			this.distributorCoupon.endDate = resp.endDate.substr(0,10);
-			this.showDistributorCoupon = true;
-		},		
-		// 获取商品详情推荐商品
-		async getRecommendProduct() {
-			let data = {};
-			data.productId = this.base.id;
-			data.productCategoryId = this.base.productCategoryId;
-			let resp = await this.$api.getRecommendProduct(data);
-			this.recommendGoodsList = resp.store;
-			return resp;
-		},
-
-		// 获取商品详情
-		async findProductInfoById() {
-			let memberId = this.$auth.getMemberId();
-			let resp = await this.$api.findProductInfoById({
-				_isShowLoading: true,
-				productId: this.productId,
-				memberId: memberId
-			});
-			console.log(502, resp);
-			this.base = resp.base; // 基本信息
-			
-			let imgBox = [];
-			for (let i = 0; i < this.base.productImages.length; i++) {
-				imgBox.push(this.base.productImages[i].large);
-			}
-			this.imgBox = imgBox;
-
-			this.skus = resp.base.skus.skus; //不同情况
-			let specifications = resp.base.skus.specifications; //sku规格
-			if (specifications != null && specifications.length > 0) {
-				let isOk = false;
-				for (var i = 0; i < specifications[0].entries.length; i++) {
-					specifications[0].entries[i].isExit = false;
-					for (let sku of this.skus) {
-						if (sku.specificationValues != null && sku.specificationValues.length > 0) {
-							for (let sv of sku.specificationValues) {
-								if (specifications[0].entries[i].id == sv.id) {
-									specifications[0].entries[i].isExit = true;
-									break;
-								}
-							}
-						}
-						if (specifications[0].entries[i].isExit == true) break;
-					}
-				}
-			}
-			this.specifications = specifications;
-			this.moneyOffsList = resp.base.promotion.moneyOffs;
-			this.giftsList = resp.base.promotion.gifts;
-
-			let defaultSkus = this.skus.filter(item => {
-				return item.isDefault;
-			});
-
-			this.defaultAvailableStock = defaultSkus[0].availableStock;
-			if (this.specifications.length == 0) {
-				this.selectSkuItemObj = Object.assign({}, defaultSkus[0]);
-				this.number = this.selectSkuItemObj.wholesaleNumStart;
-			}
-
-			this.shopCartNum = this.base.cartNum;
-			this.number = this.base.wholesaleNumStart;
-			this.isFavorite = this.base.isFavorite;
-
-			this.goodsDetailInfo = resp;
-			setTimeout(() => {
-				this.autoHeight();
-			}, 100);
-			
-			this.getRecommendProduct()
-			this.getCouponByProductId()
-			this.waitShow = true;
-			return resp;
-		},
-
-		//获取购物车商品种类
-		async cartKindCount() {
-			let resp = await this.$api.cartKindCount();
-			this.shopCartNum = resp.kindCount;
-		},
-
-		//获取评论
-		async getReviewList() {
-			let data = {};
-			data.pageNo = 1;
-			data.pageSize = 1;
-			data.productId = this.productId;
-			data.type = '';
-			let res = await this.$api.getReviewList(data);
-			console.log(res);
-			let srcs = [];
-			for (let i in res.datas) {
-				res.datas[i].imageUrls = JSON.parse(res.datas[i].imageUrls);
-				srcs = srcs.concat(res.datas[i].imageUrls);
-			}
-			this.srcs = srcs;
-			this.reviewDatas = res.datas;
-			return res;
-		},
-
-		roopHeadImage(img) {
-			uni.previewImage({
-				current: img, // 当前显示图片的http链接
-				urls: this.imgBox // 需要预览的图片http链接列表
-			});
-		},
-		roopImageClick(img) {
-			uni.previewImage({
-				current: img, // 当前显示图片的http链接
-				urls: this.srcs // 需要预览的图片http链接列表
-			});
-		},
-
-		//查看更多评价
-		moreGoodsComment() {
-			uni.navigateTo({
-				url: '/pagesM/pages/goods_comment_list?productId=' + this.productId
-			});
-		},
-
-		//查看说明书
-		jumpmanual() {
-			uni.navigateTo({
-				url: '/pagesM/pages/goods_manual'
-			});
-		},
-		showLogin() {
-			this.$refs.dialogLogin.show();
-		},
-		onSignIn(resp) {
-			this.$util.refreshPage(['pages/home', 'pages/shop_car', 'pages/mine']);
-			this.onPullDownRefreshPage();
-		},
-		// 获取总数
-		async reviewProductCount() {
-			let resp = await this.$api.reviewProductCount({
-				productId: this.productId
-			});
-			this.reviewProdCount = resp;
-			return resp;
-		},
-		onLoadPage(options) {
-			wx.hideShareMenu();
-			this.productId = options.id ? options.id : 0;
-			let inviteCode = options.inviteCode? options.inviteCode:null;
-			this.$auth.setInviteCode(inviteCode);
-			 this.findProductInfoById()
-			 this.getReviewList()
-			 this.reviewProductCount()
-		}
-	},
-
-	onShow() {
-		this.isAutoHeight = true;
-		this.autoHeight();
-	},
-	onLoad() {
-		wx.showShareMenu({
-		  withShareTicket: true
-		})
-	},
-	
-	onShareAppMessage(res) {
-		// if (res.from === 'button') {
-			let pages = getCurrentPages(); //获取加载的页面
-			let currentPage = pages[pages.length - 1]; //获取当前页面的对象
-			let inviteCode = null;
-			let resp = this.$auth.getMemberInfo();
-			if(this.$auth.isPromoter(true)){
-				inviteCode = this.$auth.getMemberId();
-			}
-			let path = `/pagesM/pages/home?type=share&id=${this.base.id}&storeId=${this.base.store.id}&path=${currentPage.route}&inviteCode=${inviteCode}`;
-			console.error('path = ' + path);
-			return {
-				title: this.base.name,
-				path: path,
-				success(res) {
-					// 转发成功
-					console.log('转发成功');
-				},
-				fail(res) {
-					// 转发失败
-					console.log('转发失败');
-				}
-			};
-		// }
-	},
-	onHide() {
-		this.isAutoHeight = false;
-	},
-	onUnload() {
-		this.isAutoHeight = false;
-	}
-};
-</script>
-
-<style lang="scss" scoped>
-.goods_img_box {
-	height: 750upx;
-	background: #fff;
-	.swiper {
-		height: 100%;
-		width: 100%;
-		image {
-			width: 100%;
-			height: 100%;
-		}
-	}
-}
-
-.goods_info_box {
-	padding-top: 20rpx;
-	display: flex;
-	flex-direction: column;
-	background: #fff;
-	.goods_price_share {
-		display: flex;
-		flex-direction: row;
-		justify-content: space-between;
-		align-items: center;
-		padding: 0 30upx;
-		.price {
-			flex: 1;
-			.sell_price {
-				color: #ee1515;
-				font-size: 48upx;
-			}
-			.original_price {
-				color: #999999;
-				font-size: 26upx;
-				text-decoration: line-through;
-				margin-left: 20upx;
-			}
-		}
-		.share_icon_btn {
-			width: 70upx;
-			height: 70upx;
-			// padding: 20upx 0;
-			// padding-left: 20upx;
-			.share_icon {
-				width: 70upx;
-				height: 70upx;
-			}
-		}
-	}
-	.goods_time_title {
-		display: flex;
-		flex-direction: row;
-		position: relative;
-		padding: 0 30upx;
-		word-wrap: break-all;
-		align-items: center;
-		.goods_title {
-			flex: 1;
-			font-size: 34upx;
-			color: #1b1414;
-			display: flex;
-			flex-direction: row;
-			align-items: center;
-			text-align: justify;
-		}
-		.goods_time {
-			position: absolute;
-			left: 30upx;
-			top: 6upx;
-			background: $dt-color-primary;
-			font-size: 18upx;
-			color: #fff;
-			border-radius: 4upx;
-			padding: 5upx 10upx;
-			height: 28upx;
-			display: flex;
-			align-items: center;
-		}
-	}
-	.goods_tip {
-		padding: 10upx 30upx;
-		font-size: 0.7rem;
-		color: #f04d0d;
-	}
-	.goods_active {
-		display: flex;
-		flex-direction: row;
-		align-items: center;
-		flex-wrap: wrap;
-		margin-top: 20upx;
-		padding: 0 30upx;
-		.active_item {
-			// border: 1upx solid #ee1515;
-			// border-radius: 4upx;
-			padding: 5upx 10upx;
-			color: #ee1515;
-			font-size: 20upx;
-			margin-right: 20upx;
-			position: relative;
-			margin-bottom: 10upx;
-		}
-		.active_item::after {
-			display: flex;
-			box-sizing: border-box;
-			align-items: center;
-			content: '';
-			position: absolute;
-			top: 0;
-			left: 0;
-			width: 200%;
-			height: 200%;
-			transform: scale(0.5);
-			transform-origin: 0 0;
-			border: 1upx solid #ee1515;
-			border-radius: 4upx;
-			pointer-events: none;
-		}
-	}
-	.goods_des {
-		color: #666;
-		font-size: 28upx;
-		padding: 10upx 30upx;
-	}
-	.goods_inventory_sales {
-		font-size: 24upx;
-		color: #999;
-		display: flex;
-		flex-direction: row;
-		align-items: center;
-		padding: 20upx 30upx;
-		border-top: 1upx solid #e5e5e5;
-		text {
-			width: 30%;
-		}
-	}
-}
-
-.get_coupon {
-	background: #fff;
-	padding: 20upx 30upx;
-	display: flex;
-	flex-direction: row;
-	align-items: center;
-	justify-content: space-between;
-	margin-top: 20upx;
-	.get_coupon_text {
-		color: #333;
-		font-size: 28upx;
-	}
-	.coupon {
-		display: flex;
-		flex-direction: row;
-		align-items: center;
-		.coupon_list {
-			display: flex;
-			flex-direction: row;
-			align-items: center;
-			color: #d32222;
-			font-size: 20upx;
-			.coupon_item {
-				position: relative;
-				padding: 10upx 20upx;
-				margin-right: 20upx;
-			}
-			.coupon_item::after {
-				display: flex;
-				box-sizing: border-box;
-				align-items: center;
-				content: '';
-				position: absolute;
-				top: 0;
-				left: 0;
-				width: 200%;
-				height: 200%;
-				transform: scale(0.5);
-				transform-origin: 0 0;
-				border: 1upx solid #ee1515;
-				border-radius: 4upx;
-				pointer-events: none;
-			}
-		}
-		image {
-			width: 10upx;
-			height: 18upx;
-		}
-	}
-}
-
-.goods_detail_info_box {
-	margin-top: 20upx;
-	background: #fff;
-	.goods_detail_tab {
-		display: flex;
-		flex-direction: row;
-		align-items: center;
-		justify-content: space-around;
-		padding: 0 30upx;
-		border-bottom: 1upx solid #e5e5e5;
-		.goods_tab_item {
-			flex: 1;
-			color: #666666;
-			font-size: 28upx;
-			padding: 20upx 0;
-			text-align: center;
-		}
-		.good_tab_item_active {
-			color: $dt-color-primary;
-		}
-	}
-
-	.tab_content {
-		.tab2 {
-			.goods_params_list {
-				display: flex;
-				flex-direction: column;
-				padding: 20upx 20upx 0 20upx;
-				.goods_params_item {
-					display: flex;
-					flex-direction: row;
-					margin-bottom: 30upx;
-					.goods_params_title {
-						color: #666666;
-						font-size: 28upx;
-					}
-					.goods_params_des {
-						flex: 1;
-						font-size: 28upx;
-						color: #333333;
-					}
-				}
-			}
-			.check_btn {
-				width: 600upx;
-				height: 60upx;
-				margin: 0 auto;
-				margin-bottom: 40upx;
-				line-height: 60upx;
-				text-align: center;
-				font-size: 26upx;
-				color: #666666;
-				border: 1upx solid #ccc;
-			}
-		}
-		.tab3 {
-			.check_btn {
-				width: 600upx;
-				height: 60upx;
-				margin: 0 auto;
-				margin-bottom: 40upx;
-				line-height: 60upx;
-				text-align: center;
-				font-size: 26upx;
-				color: #666666;
-				border: 1upx solid #ccc;
-			}
-		}
-		.no_data_wrap {
-			max-height: 300upx;
-			min-height: 300upx;
-			display: flex;
-			flex-direction: column;
-			align-items: center;
-			justify-content: center;
-		}
-	}
-}
-
-.tool_height {
-	height: 140upx;
-}
-.goods_tool {
-	display: flex;
-	height: 90upx;
-	position: fixed;
-	bottom: 0;
-	left: 0;
-	width: 100%;
-	background-color: #fff;
-	.left {
-		width: fit-content;
-		display: flex;
-		flex-direction: row;
-		align-items: center;
-		border-top: 1upx solid #ccc;
-		background: #fff;
-		box-sizing: border-box;
-		height: 100%;
-		button {
-			line-height: 1;
-		}
-		.item {
-			display: flex;
-			flex-direction: column;
-			align-items: center;
-			width: 110upx;
-			border-right: 1upx solid #ccc;
-			border-bottom: 1upx solid #ccc;
-			border-radius: 0;
-			box-sizing: border-box;
-			height: 100%;
-			justify-content: center;
-			image {
-				width: 35upx;
-				height: 35upx;
-				margin-bottom: 5upx;
-			}
-			text {
-				color: #666666;
-				font-size: 20upx;
-			}
-		}
-		.item:last-child {
-			border-right: none;
-		}
-		.shop_car {
-			position: relative;
-			.tip_count {
-				position: absolute;
-				right: 22upx;
-				top: 5rpx;
-				width: 24upx;
-				height: 24upx;
-				border-radius: 50%;
-				background-color: #ff3b30;
-				color: #fff;
-				font-size: 18upx;
-				text-align: center;
-				line-height: 24upx;
-			}
-		}
-	}
-	.right {
-		flex: 1;
-		display: flex;
-		flex-direction: row;
-		align-items: center;
-		.item {
-			width: 50%;
-			height: 90upx;
-			font-size: 30upx;
-			color: #fff;
-			display: flex;
-			align-items: center;
-			justify-content: center;
-		}
-		.add_shop_car {
-			background: orange;
-		}
-		.buy {
-			background: $dt-color-primary;
-		}
-		.sell_out {
-			width: 100%;
-			height: 90upx;
-			font-size: 30upx;
-			color: #fff;
-			display: flex;
-			align-items: center;
-			justify-content: center;
-			background: #cccccc;
-		}
-	}
-}
-.goods_sell_out_tip {
-	color: #ffffff;
-	font-size: 22upx;
-	background: rgba(0, 0, 0, 0.5);
-	position: fixed;
-	bottom: 90upx;
-	left: 0;
-	width: 100%;
-	text-align: center;
-	padding: 5upx 0;
-}
-
-.toast_box {
-	position: fixed;
-	height: 100%;
-	width: 100%;
-	z-index: 101;
-	left: 0;
-	bottom: 0upx;
-	background: rgba(0, 0, 0, 0.5);
-	display: flex;
-	flex-direction: column;
-	justify-content: space-between;
-	.toast_content {
-		background: white;
-		border-top-left-radius: 20upx;
-		border-top-right-radius: 20upx;
-		position: fixed;
-		width: 100%;
-		bottom: 0upx;
-		.goods_img_price_wrap {
-			display: flex;
-			flex-direction: row;
-			align-items: center;
-			padding: 30upx 0;
-			border-bottom: 1 solid #e5e5e5;
-			.goods_img {
-				height: 120upx;
-				width: 120upx;
-				padding-left: 30upx;
-				image {
-					width: 120upx;
-					height: 120upx;
-				}
-			}
-			.goods_price_box {
-				display: flex;
-				flex-direction: column;
-				justify-content: space-around;
-				height: 120upx;
-				padding-left: 28upx;
-				.price {
-					display: flex;
-					flex-direction: row;
-					align-items: center;
-					text {
-						padding-left: 10upx;
-						padding-top: 7upx;
-						font-size: 48upx;
-						color: #d32222;
-					}
-				}
-				.sku_params {
-					font-size: 24upx;
-					color: #999;
-				}
-				.count_num {
-					font-size: 24upx;
-					color: #999;
-				}
-			}
-		}
-
-		.goods-sku-list-wrap {
-			display: flex;
-			flex-direction: column;
-			.sku_item {
-				padding: 0 30upx;
-				.sku_name {
-					font-size: 24upx;
-					color: #333;
-					padding: 20upx 0upx;
-				}
-				.sku_value_box {
-					display: flex;
-					flex-wrap: wrap;
-					flex-direction: row;
-					text {
-						font-size: 26upx;
-						color: #333;
-						padding: 10upx 20upx;
-						margin-right: 15upx;
-						border: 2upx solid #ebebeb;
-						opacity: 0.6;
-						border-radius: 5px;
-						margin-bottom: 10upx;
-					}
-					.active {
-						background-color: $dt-color-primary;
-						border: 2upx solid $dt-color-primary;
-						color: #fff;
-						opacity: 1;
-					}
-
-					.disabled {
-						background-color: #e5e5e5;
-						color: #ccc;
-						opacity: 1;
-					}
-				}
-			}
-		}
-
-		.goods_num_select_wrap {
-			display: flex;
-			flex-direction: row;
-			justify-content: space-between;
-			align-items: center;
-			padding: 20upx 30upx 30upx 30upx;
-			.num_text {
-				font-size: 24upx;
-				color: rgb(51, 51, 51);
-			}
-			.number_select {
-				height: 50upx;
-				border-radius: 6upx;
-				border: 2upx solid #e5e5e5;
-				display: flex;
-				flex-direction: row;
-				align-items: center;
-				justify-content: space-around;
-				width: 200upx;
-				.number_change_less {
-					width: 60upx;
-					text-align: center;
-					border-right: 2upx solid #e5e5e5;
-					height: 100%;
-					line-height: 50upx;
-					font-size: 36upx;
-				}
-				.number_change_add {
-					width: 60upx;
-					text-align: center;
-					border-left: 2upx solid #e5e5e5;
-					height: 100%;
-					line-height: 50upx;
-					font-size: 36upx;
-				}
-
-				.goods_number {
-					width: 60upx;
-					padding: 0 10upx;
-					text-align: center;
-					font-size: 36upx;
-					color: #353535;
-				}
-			}
-		}
-
-		.comfirm_btn_box {
-			margin: 80upx 40upx;
-			button {
-				color: #fff;
-				border-radius: 6upx;
-				text-align: center;
-				background: $dt-color-primary;
-			}
-		}
-		.toastDelete {
-			position: absolute;
-			width: 30upx;
-			height: 30upx;
-			right: 10upx;
-			top: 0upx;
-			padding: 20upx;
-		}
-	}
-	.toast_coupon_content {
-		min-height: 800upx;
-		height: auto;
-		background: #f2f2f2;
-		position: fixed;
-		width: 100%;
-		bottom: 0upx;
-		border-top-left-radius: 20upx;
-		border-top-right-radius: 20upx;
-		.title {
-			color: #333333;
-			text-align: center;
-			font-size: 30upx;
-			height: 100upx;
-			line-height: 100upx;
-			background: #fff;
-		}
-		.coupon_wrap_list {
-			display: flex;
-			flex-direction: column;
-			align-items: center;
-			.coupon_height {
-				height: 20upx;
-			}
-		}
-		.toastDelete {
-			position: absolute;
-			width: 30upx;
-			height: 30upx;
-			right: 10upx;
-			top: 15upx;
-			padding: 20upx;
-		}
-	}
-}
-
-.drawer_screen {
-	width: 100%;
-	height: 100%;
-	position: fixed;
-	top: 0;
-	left: 0;
-	z-index: 1000;
-	background: #000;
-	opacity: 0.2;
-	overflow: hidden;
-}
-.drawer_attr_box {
-	width: 100%;
-	overflow: hidden;
-	position: fixed;
-	bottom: 0;
-	left: 0;
-	z-index: 1001;
-	background: rgb(242, 242, 242);
-	.drawer_content {
-		overflow-y: scroll;
-		.btn {
-			background: #fff;
-			font-size: 30upx;
-			color: rgb(51, 51, 51);
-			border-bottom: 1px solid #e8e8e8;
-			border-radius: 0;
-			padding: 14upx 0;
-		}
-		.btn::after {
-			border: none;
-		}
-		.detail-cancel-btn {
-			margin-top: 16upx;
-		}
-	}
-}
-
-.imagePathBox {
-	width: 100%;
-	height: 100%;
-	background: rgba(0, 0, 0, 0.7);
-	position: fixed;
-	top: 0;
-	left: 0;
-	right: 0;
-	bottom: 0;
-	z-index: 1200;
-	.save {
-		display: block;
-		width: 80%;
-		height: 80upx;
-		padding: 0;
-		line-height: 80upx;
-		text-align: center;
-		position: fixed;
-		z-index: 1200;
-		top: 1000upx;
-		left: 10%;
-		background: $dt-color-primary;
-		color: #fff;
-		font-size: 30upx;
-		border-radius: 10upx;
-	}
-	.save::after {
-		border: 0 !important;
-	}
-}
-.shengcheng {
-	width: 600upx;
-	height: 900upx;
-	position: fixed;
-	top: 100upx;
-	left: 50%;
-	z-index: 1200;
-	border-radius: 10upx;
-	transform: translate(-50%);
-	margin-top: -50upx;
-	.shareClose {
-		text-align: center;
-		position: fixed;
-		top: 60upx;
-		right: 10upx;
-		height: 46upx;
-		width: 46upx;
-		z-index: 1201;
-	}
-}
-</style>

+ 16 - 9
pagesM/pages/mine_info.vue

@@ -11,7 +11,7 @@
           <image src="http://139.9.103.171:1888/img/image/arrow.png"></image>
         </block>
         <button v-else class="avatar-wrap" open-type="getUserInfo" @getuserinfo="tapGetUserInfo" @tap.stop="()=>false">
-          <image class="avatar" src="http://139.9.103.171:1888/img/image/avatar.png" mode="aspectFill"></image>
+          <image class="avatar" src="https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png" mode="aspectFill"></image>
           <image src="http://139.9.103.171:1888/img/image/arrow.png"></image>
         </button>
       </view>
@@ -91,12 +91,12 @@ export default {
       range:['男','女'],
       endDate:'',
       dataDetail:{ // 会员信息
-        avatar:'https://gss1.bdstatic.com/9vo3dSag_xI4khGkpoWK1HF6hhy/baike/whfpf%3D360%2C280%2C50/sign=26cc5fe78d26cffc697fecf2df3c79a6/d0c8a786c9177f3ef680d5737fcf3bc79f3d5613.jpg',
+        avatar:'',
         gender:'MALE', // FEMALE
         birth:'',
-        username:'黄海贤',
-        idCard:'445227188405063055',
-        phone:'13666668888',
+        username:'',
+        idCard:'',
+        phone:'',
         name:'',
       },
     }
@@ -134,6 +134,8 @@ export default {
     },
     // 更新信息
     async tapSave(){
+		console.log(getApp().globalData.member);
+		console.log(this.index);
       let resp = await this.$api.BCedit({
         _isShowLoading:true,
         // phone:this.dataDetail.phone,
@@ -144,10 +146,15 @@ export default {
         birth:this.dataDetail.birth,
         idCard:this.dataDetail.idCard,
       })
-      
-      this.$dialog.success('保存成功',()=>{
-        this.$util.refreshPage(['pages/mine'])
-        uni.navigateBack()
+      uni.showModal({
+      	content:"保存成功",
+		showCancel:false,
+		success: (res) => {
+			if (res.confirm) {
+				this.$util.refreshPage(['pages/mine'])
+				uni.navigateBack()
+			}
+		}
       })
     },
     // 获取信息

+ 1 - 1
pagesM/pages/mine_order_list.vue

@@ -352,7 +352,7 @@ export default {
     onLoadPage(options) {
 	  wx.hideShareMenu();
       if (this.isLoad) {
-        this.curTab = parseInt(options.state)
+        this.curTab = parseInt(options.state) || 0
         this.memberId = this.$auth.getMemberId()
         if (options.state == 0) {
           this.queryDataList()

+ 135 - 8
pagesM/pages/mine_protocal.vue

@@ -1,7 +1,7 @@
 <template>
   <view class="dt-page">
     <view class="content">
-      <rich-text :nodes="dataDetail.content" :selectable="true"></rich-text>
+      <rich-text :nodes="content" :selectable="true"></rich-text>
     </view>
   </view>
 </template>
@@ -9,15 +9,141 @@
 export default {
   data(){
     return {
-      dataDetail:{}
+      content:{}
     }
   },
   methods:{
-    async queryDataDetail(){
-      let resp = await this.$api.getAppServiceAgreement({
-        _isShowLoading:true
-      })
-      this.dataDetail = resp
+    queryDataDetail(){
+      this.content=`宁夏电信智慧社区隐私政策
+特别提示:
+宁夏电信智慧社区(简称“本应用”)由中国电信股份有限公司(宁夏分公司)(简称 “我们”)创建和运营。为方便用户(简称“您”)注册和使用本应用的服务,我们可能会收集和使用您的相关数据和信息(统称“信息”或“用户信息”)。我们将通过《天翼智慧社区隐私政策》(简称“本隐私政策”)向您说明我们如何收集和使用您的信息,请您在注册和使用本应用的服务之前认真阅读、充分理解本隐私政策的全部内容。如果您对本隐私政策有疑问的,请通过本隐私政策约定的方式询问,我们将解释本隐私政策内容。您使用或继续使用本应用的服务,即意味着您已经同意本隐私政策,同意我们按照本隐私政策收集和使用您的相关数据和信息。
+
+一、隐私政策适用范围
+1.1 本隐私政策适用于我们通过本应用提供的服务。
+
+1.2 第三方通过本应用向您提供的服务,服务商通过天翼云市场向您提供服务或者中国电信国际有限公司通过本应用向您提供服务时,收集和使用您的信息的,适用您和第三方之间关于个人信息和隐私的约定。
+
+二、信息收集的目的和范围
+2.1 用户注册及实名认证
+
+您注册本应用账户、进行实名认证过程中,需要提供真实、准确、完整、有效的注册信息和资料,包括单位名称、单位证件、联系人及其身份证件、邮箱、联系电话、联系地址。如果您仅需使用本应用的浏览、搜索等基本服务,您不需要注册本应用账户,也无需提供上述信息。
+
+2.2 使用本应用及服务
+
+为提供持续服务、保证服务质量、满足监管部门要求等目的,在您使用服务的过程中,我们将接收并记录的您的浏览信息和行为轨迹,包括您的IP地址、浏览器的类型、使用的语言、访问日期和时间、软硬件特征信息、设备相关信息(例如设备型号、操作系统版本、设备设置、唯一设备标识符等软硬件特征信息)、设备所在位置相关信息(例如IP地址、基站等传感器信息)及网页记录、安全信息。
+
+2.3 除另有说明外,我们不会收集您使用服务所存储在本应用的任何数据信息、以及云主机内的日志信息。但是,您使用特定服务(例如服务器安全卫士产品)的,为向您提供服务之必要,我们将收集和使用您存储在本应用的数据信息,就该等数据信息的收集和使用,我们将通过产品协议等方式与您另行约定。
+
+三、如何收集信息
+3.1 用户注册及实名认证的相关信息将由您在注册和实名认证时主动向我们提交。
+
+3.2 用户自己授权。
+
+(1)相机、访问相册:新增设备和处理工单需要上传现场照片
+
+(2)语音:摄像头进行对讲
+
+(3)定位:新增设备获取当前位置经纬度上传信息; 获取安全帽当前位置, 记录安全帽的轨迹
+
+(4)通知:设备出现告警, 进行手机下发接收
+
+(5)手机读写权限,存储摄像头拍摄的视频和照片
+
+(6)存储用户基本信息、租户信息 : 用于鉴别获取整个app的个人所有权限, 用户登录后30天失效、过期清空缓存, 手动退出账号清空缓存
+
+3.3 除您提交授权外,我们可能通过 Cookies 和其他相关技术收集和使用您的信息。我们对Cookie的使用政策为:
+
+(1)为了改善用户访问体验,我们会根据业务需要在您的计算机上或移动设备上存储、设定或取用Cookies, Cookies是存储于您硬盘或设备内存中的小型数据文件,借助于 Cookies,我们能记录您的选择(如计算机或移动设备的语言、字体大小和其他浏览偏好),分析您使用我们服务的偏好,帮助我们改善本应用和您的访问体验,以及提供个性化的服务。
+
+(2)您可以通过自行修改浏览器设置的方式拒绝或管理Cookies。您理解并同意,您拒绝接受Cookies可能导致您无法享受最佳的服务体验登录或使用需依赖于Cookies的服务或功能。
+
+四、信息使用
+4.1 为更好地向您提供服务,在严格按照法律法规遵循必要性原则基础上,我们将收集的信息用于以下目的和用途:
+
+(1)为您提供服务,包括履行合同订单;交付、激活或验证产品或服务;应您的要求进行账号管理、变更;以及提供技术支持和客户服务;
+
+(2)向您发送重要通知;
+
+(3)开展内部审计、研究和分析,改善本应用和产品服务;
+
+(4)改善我们的防损和反欺诈计划;
+
+(5)遵从和执行适用的法律法规要求,相关的行业标准或我们的政策;
+
+(6)满足您个性化的需求;
+
+(7)向您发送您可能感兴趣的产品和服务的信息;
+
+(8)邀请您参与有关我们产品和服务的调查;
+
+(9)其他为向您提供服务而需要使用您用户信息的情形。
+
+五、信息存储
+5.1 本应用收集的有关您的信息将保存在本应用在中华人民共和国境内(为本隐私政策之目的,不含香港、澳门、台湾地区)的服务器上。如在符合适用法律规定的情形下因业务需要向境外传输个人信息的,我们会事先征得您的同意,向您告知用户信息出境的目的、接收方等情况,并履行相关法律法规规定的程序。
+
+5.2 在您的信息已经不再需要用于实现本隐私政策规定的目的和用途,也无需根据相关法律法规的规定保存时,我们将采取合理步骤以安全的方式销毁个人信息或使其不可识别并不可被再次编辑、修改、使用。
+
+六、信息共享、转移、公开披露
+6.1 共享
+
+未经您事先同意,我们不会与任何第三方共享您的信息,但以下情形除外:
+(1)在获取明确同意的情况下共享:经您事先明确同意,我们会与其他方共享您的信息;
+
+(2)根据相关法律法规的规定,或者行政、司法机关的要求,向第三方或者行政、司法机关披露您的信息;
+
+(3)与授权合作伙伴共享:为提供服务之需,我们的某些服务将由授权合作伙伴提供。例如,为进行实名认证,我们会将您提供的身份信息向授权合作伙伴提供,以确认您的真实身份。我们委托的第三方合作伙伴包括供应商、技术服务商、产品服务商、客户服务商等。我们仅会根据合法、正当、必要的原则,基于特定、明确的目的与授权合作伙伴共享您的用户信息,仅会共享提供服务所必要的用户信息,并要求合作伙伴按照本隐私政策以及其他任何相关的保密和安全措施来处理您的信息。
+
+(4)为向您提供服务之需,我们可能会向关联方中国电信披露您的信息。 对我们与之共享您的信息的组织和个人,我们会与其签署严格的保密协定,要求他们按照我们的说明、本隐私政策以及其他任何相关的保密和安全措施来处理您的信息。
+
+6.2 转移
+
+我们不会将您的个人信息转移给任何公司、组织和个人,但以下情况除外:
+
+(1)在获取明确同意的情况下转让:获得您的明确同意后,我们会向其他方转移您的个人信息。
+
+(2)在涉及合并、收购或破产清算时,如涉及到个人信息转让,我们会要求新的持有您的信息的公司、组织继续受此隐私政策的约束,否则我们将要求该公司、组织重新向您征求授权同意。
+
+6.3 公开披露
+
+我们仅会在以下情况下,公开披露您的个人信息:
+
+(1)获得您明确同意后;
+
+(2)基于法律的披露:在法律、法律程序、诉讼或政府主管部门强制性要求的情况下,我们可能会公开披露您的个人信息。
+
+七、信息保护
+7.1 我们对用户信息的保护
+
+我们非常重视您的信息安全。我们采用适当的物理、管理和技术保障措施来防止您的信息遭到未经授权访问、披露、使用、修改、损坏或丢失。
+
+例如,我们会使用混合加密技术提高信息的保密性;我们会使用受信赖的保护机制防止您的信息遭到恶意攻击;我们会部署访问控制机制,确保只有授权人员才可访问用户信息;我们会举办安全和培训,加强员工对于保护用户信息重要性的认识。
+
+但请您理解,由于技术的限制以及可能存在的各种恶意手段,在互联网环境下,即便竭尽所能加强安全措施,也不可能始终保证信息百分之百的安全。若不幸发生信息泄露等安全事件,我们会立即启动应急预案,阻止事件扩大,及时采取补救措施,并推送通知、公告等多种形式告知您。
+
+7.2 用户对信息的保管
+
+尽管有前述安全措施,但请您妥善保管您的账户、密码及其他信息,避免您的个人信息泄露。如果您发现您的账号、密码或其他信息被他人非法使用或有使用异常的情况的,应及时通知我们,我们将采取相应安全保障措施。
+
+八、信息管理
+8.1 查询
+
+您可以登录SaaS应用管理控制中心查询、管理您向我们提交的基本信息。
+
+8.2 变更
+
+您应确保向我们提交的所有个人数据都准确无误。如果您发现我们对您的信息收集、存储有错误,您可以通过在本应用用户中心提交工单、联系业务受理渠道等方式要求我们对相关信息予以更正。
+
+8.3 删除
+
+若您发现我们未按照法律法规的规定或者本隐私政策约定收集和使用您的信息,您可以通过工单、邮件等方式联系我们对相关信息进行删除。
+
+8.4 为保障安全,您申请查询、变更或删除您的信息时,可能需要提供书面请求,或以其他方式证明您的身份。我们可能会先要求您验证自己的身份,然后再处理您的请求。
+
+九、隐私政策的修订
+9.1 我们有权不时修订本隐私政策,修订后的本隐私政策将公布于本应用。您如果继续使用本应用的服务,即代表您已接受更新后的隐私政策。
+
+十、联系方式
+10.1 您对本隐私政策内容如有任何疑问,可以通过在本应用用户中心提交工单的方式与我们联系。`
     },
     onLoadPage(){
 	  wx.hideShareMenu();
@@ -30,7 +156,8 @@ export default {
 <style lang="scss" scoped>
 .dt-page{
   min-height:100vh;
-  background-color:#f2f2f2;
+  background-color:#FFFFFF;
+  line-height: 50rpx;
   .content{
     padding:30upx;
   }

+ 11 - 10
pagesM/pages/mine_setting.vue

@@ -31,8 +31,9 @@ export default {
     onTapItem(item){
       switch(item.id){
         case 0:
+		let url='https://community.58fo.com/appfile/protocal.htm'
           uni.navigateTo({
-            url:'/pagesM/pages/mine_protocal'
+          	url:"/pages/webview/webview?url="+url+"&title=隐私协议"
           })
           break;
         case 1:break;
@@ -78,18 +79,18 @@ export default {
       this.moduleList = [
         {
           id: 0,
-          title: '用户协议',
+          title: '隐私协议',
           value: '',
           hideArrow: false,
           isMarginTop:true
         },
-        // {
-        //   id: 1,
-        //   title: '技术支持',
-        //   value: '广州吉米特科技有限公司',
-        //   hideArrow: true,
-        //   isMarginTop:true
-        // }
+        {
+          id: 1,
+          title: '技术支持',
+          value: '宁夏新邻科技有限公司',
+          hideArrow: true,
+          isMarginTop:true
+        }
       ]
     }
   }
@@ -107,7 +108,7 @@ export default {
     height: 90upx;
     line-height: 90upx;
     border-radius:10upx;
-    background-color:$dt-color-primary;
+    background-color:#e54d42;
   }
 }
 

+ 6 - 6
pagesM/pages/order_detail.vue

@@ -390,7 +390,7 @@ export default {
     display: flex;
     flex-wrap: wrap;
     padding: 0 30upx;
-    background-color: $dt-color-primary;
+    background-color: $base-btn-color;
     color: #fff;
     font-weight: 400;
 
@@ -577,14 +577,14 @@ export default {
       width: 100%;
       height: 100%;
       box-sizing: border-box;
-      border: 2upx solid $dt-color-primary;
+      border: 2upx solid $base;
       border-radius: 6upx;
       content: "";
     }
 
     .btn-plain {
       background-color: transparent;
-      color: $dt-text-color;
+      color: $base;
     }
 
     .btn-plain:before {
@@ -593,18 +593,18 @@ export default {
     }
 
     .btn-primary {
-      background-color: $dt-color-primary;
+      background-color: $base;
       color: #fff;
     }
 
     .btn-primary:before {
-      border-color: $dt-color-primary;
+      border-color: $base;
       content: "";
     }
 
     .btn-primary-plain {
       background-color: transparent;
-      color: $dt-color-primary;
+      color: $base;
     }
   }
 }

+ 3 - 0
pagesM/pages/order_pay.vue

@@ -79,6 +79,9 @@ export default {
     },
 
     async payOrder() {
+		this.$u.toast('即将开放')
+		return
+		
       if (this.prePayOrder.expireDate) {
         let time = (this.$util.createDate(this.prePayOrder.expireDate)).getTime();
         let now = new Date().getTime();

BIN
static/call.png


BIN
static/common/unit.png


BIN
static/dialog/dialog_fail.png


BIN
static/dialog/dialog_success.png


BIN
static/dialog/dialog_warn.png


BIN
static/home/health.png


BIN
static/home/health5.png


BIN
static/noImg.png


BIN
static/wode/jiaofei1.png


+ 26 - 0
store/$u.mixin.js

@@ -0,0 +1,26 @@
+import { mapState } from 'vuex'
+import store from "@/store"
+
+// 尝试将用户在根目录中的store/index.js的vuex的state变量,全部加载到全局变量中
+let $uStoreKey = [];
+try{
+	$uStoreKey = store.state ? Object.keys(store.state) : [];
+}catch(e){
+	
+}
+module.exports = {
+	created() {
+		// 将vuex方法挂在到$u中
+		// 使用方法为:如果要修改vuex的state中的user.name变量为"史诗" => this.$u.vuex('user.name', '史诗')
+		// 如果要修改vuex的state的version变量为1.0.1 => this.$u.vuex('version', '1.0.1')
+		this.$u.vuex = (name, value) => {
+			this.$store.commit('$uStore', {
+				name,value
+			})
+		}
+	},
+	computed: {
+		// 将vuex的state中的所有变量,解构到全局混入的mixin中
+		...mapState($uStoreKey)
+	}
+}

+ 67 - 0
store/index.js

@@ -0,0 +1,67 @@
+import Vue from 'vue'
+import Vuex from 'vuex'
+Vue.use(Vuex)
+
+let lifeData = {};
+
+try{
+	// 尝试获取本地是否存在lifeData变量,第一次启动APP时是不存在的
+	lifeData = uni.getStorageSync('lifeData');
+}catch(e){
+	
+}
+
+// 需要永久存储,且下次APP启动需要取出的,在state中的变量名
+let saveStateKeys = [];
+
+// 保存变量到本地存储中
+const saveLifeData = function(key, value){
+	// 判断变量名是否在需要存储的数组中
+	if(saveStateKeys.indexOf(key) != -1) {
+		// 获取本地存储的lifeData对象,将变量添加到对象中
+		let tmp = uni.getStorageSync('lifeData');
+		// 第一次打开APP,不存在lifeData变量,故放一个{}空对象
+		tmp = tmp ? tmp : {};
+		tmp[key] = value;
+		// 执行这一步后,所有需要存储的变量,都挂载在本地的lifeData对象中
+		uni.setStorageSync('lifeData', tmp);
+	}
+}
+const store = new Vuex.Store({
+	// 下面这些值仅为示例,使用过程中请删除
+	state: {
+		// 如果上面从本地获取的lifeData对象下有对应的属性,就赋值给state中对应的变量
+		// 加上vuex_前缀,是防止变量名冲突,也让人一目了然
+		
+		//自己与房屋的关系 在 pages/myFamily/myFamily中定义
+		vuex_relationshipType: lifeData.vuex_relationshipType ? lifeData.vuex_relationshipType : -1,
+		//用户信息
+		vuex_member: lifeData.vuex_member ? lifeData.vuex_member : null,
+		//自己的房屋列表
+		vuex_own_room_list: lifeData.vuex_own_room_list ? lifeData.vuex_own_room_list : null,
+	},
+	mutations: {
+		$uStore(state, payload) {
+			// 判断是否多层级调用,state中为对象存在的情况,诸如user.info.score = 1
+			let nameArr = payload.name.split('.');
+			let saveKey = '';
+			let len = nameArr.length;
+			if(nameArr.length >= 2) {
+				let obj = state[nameArr[0]];
+				for(let i = 1; i < len - 1; i ++) {
+					obj = obj[nameArr[i]];
+				}
+				obj[nameArr[len - 1]] = payload.value;
+				saveKey = nameArr[0];
+			} else {
+				// 单层级变量,在state就是一个普通变量的情况
+				state[payload.name] = payload.value;
+				saveKey = payload.name;
+			}
+			// 保存变量到本地,见顶部函数定义
+			saveLifeData(saveKey, state[saveKey])
+		}
+	}
+})
+
+export default store

+ 3 - 3
utils/dialog.js

@@ -22,15 +22,15 @@ dialog.toast = (title, callfun = null, duration = 1000, mask = true, image = '',
 };
 
 dialog.success = (title, callfun = null, duration = 1000) => {
-  dialog.toast(title, callfun, duration, true, '/static/common/dialog_success.png')
+  dialog.toast(title, callfun, duration, true, '/static/dialog/dialog_success.png')
 };
 
 dialog.error = (title, callfun = null, duration = 1000) => {
-  dialog.toast(title, callfun, duration, true, '/static/common/dialog_fail.png')
+  dialog.toast(title, callfun, duration, true, '/static/dialog/dialog_fail.png')
 };
 
 dialog.warn = (title, callfun = null, duration = 1000) => {
-  dialog.toast(title, callfun, duration, true, '/static/common/dialog_warn.png')
+  dialog.toast(title, callfun, duration, true, '/static/dialog/dialog_warn.png')
 };
 
 dialog.showLoading = (title = '加载中..', mask = true) => {