Browse Source

预约清运用户端

zhangdan 4 years ago
commit
adfe3a552e
63 changed files with 4514 additions and 0 deletions
  1. 4 0
      .gitignore
  2. 11 0
      .hbuilderx/launch.json
  3. 52 0
      App.vue
  4. 53 0
      api/cleared.js
  5. 8 0
      api/data.js
  6. 43 0
      api/login.js
  7. 67 0
      api/unclear.js
  8. 148 0
      api/user.js
  9. 125 0
      components/m-input.vue
  10. 96 0
      components/uni-icons/icons.js
  11. 10 0
      components/uni-icons/uni-icons.vue
  12. 142 0
      components/uni-navbar/uni-navbar.vue
  13. 97 0
      libs/axios.js
  14. 0 0
      libs/qqmap-wx-jssdk.min.js
  15. 29 0
      libs/tools.js
  16. 5 0
      libs/validate.js
  17. 45 0
      main.js
  18. 85 0
      manifest.json
  19. 13 0
      package-lock.json
  20. 19 0
      package.json
  21. 114 0
      pages.json
  22. 223 0
      pages/agreement/agreement.vue
  23. 345 0
      pages/cleared/chooseNetwork.vue
  24. 213 0
      pages/cleared/details.vue
  25. 175 0
      pages/cleared/index.vue
  26. 253 0
      pages/cleared/network.vue
  27. 194 0
      pages/cleared/searchModal.vue
  28. 394 0
      pages/index/index.vue
  29. 225 0
      pages/index/map.vue
  30. 229 0
      pages/login/forget-pass.vue
  31. 74 0
      pages/login/login.scss
  32. 178 0
      pages/login/login.vue
  33. 147 0
      pages/login/pwLogin.vue
  34. 66 0
      pages/login/userAuthYs.vue
  35. 190 0
      pages/userCenter/changePwd.vue
  36. 145 0
      pages/userCenter/index.vue
  37. BIN
      static/CLOTHES.png
  38. BIN
      static/GLASS.png
  39. BIN
      static/HARM.png
  40. BIN
      static/METAL.png
  41. BIN
      static/MET_PLA.png
  42. BIN
      static/PAPER.png
  43. BIN
      static/PLASTIC.png
  44. BIN
      static/RECYCLING.png
  45. BIN
      static/filter.png
  46. BIN
      static/full-bg.png
  47. BIN
      static/ledou.png
  48. BIN
      static/login_icon_logo.png
  49. BIN
      static/logo.jpg
  50. BIN
      static/map-icon.png
  51. BIN
      static/md-big-pic.png
  52. BIN
      static/pop-bg.png
  53. BIN
      static/store-s.png
  54. BIN
      static/store.png
  55. BIN
      static/tabbar/cleared-active.png
  56. BIN
      static/tabbar/cleared.png
  57. BIN
      static/tabbar/unclean-active.png
  58. BIN
      static/tabbar/unclean.png
  59. BIN
      static/tabbar/user-active.png
  60. BIN
      static/tabbar/user.png
  61. 27 0
      store/$u.mixin.js
  62. 176 0
      store/index.js
  63. 94 0
      uni.scss

+ 4 - 0
.gitignore

@@ -0,0 +1,4 @@
+node_modules/
+.project
+unpackage/
+.DS_Store

+ 11 - 0
.hbuilderx/launch.json

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

+ 52 - 0
App.vue

@@ -0,0 +1,52 @@
+<script>
+	const uat_URL = 'https://driver.test.sxzxyj.net/gc-driver/' // 预发布
+	// const uat_URL = 'http://192.168.16.103:8304/gc-driver/' // 本地
+	const pro_URL = 'https://driver.sxzxyj.net/gc-driver/'  // 生产
+	const buildType = 1 // 打包环境对应类型,1 生产 0 预发布
+	const buildURL = buildType ? pro_URL : uat_URL // 打包后实际对应的url
+	const envText = ['预发布环境','生产环境']
+	const envTips = process.env.NODE_ENV == 'development' ? envText[0] : envText[buildType]
+	console.log(process.env.NODE_ENV)
+	export default {
+		globalData: {  
+			baseUrl: process.env.NODE_ENV == 'development' ? uat_URL : buildURL,
+			token: '',
+			version: '', // 当前版本号
+			buildType: buildType,
+			envTips: envTips
+		},
+		mounted() {
+			// 非V3模式
+			if(this.$scope){
+				this.$scope.globalData.token = this.$store.state.vuex_token
+			}else{
+				// V3模式
+				getApp({allowDefault: true}).globalData.token = this.$store.state.vuex_token
+			}
+		},
+		onLaunch: function() {
+			 console.log('App onLaunch')
+		},
+		onShow: function() {
+			console.log('App Show')
+		},
+		onHide: function() {
+			console.log('App Hide')
+		},
+	}
+</script>
+
+<style lang="scss">
+	@import "uview-ui/index.scss";
+	/*每个页面公共css */
+	page {
+		min-height: 100%;
+		display: flex;
+		background-color: #F8F8F8;
+	}
+	/* 登录页是否记住密码多选框样式 */
+	uni-checkbox.login-form-checkbox .uni-checkbox-input{
+		width: 24upx !important;
+		height: 24upx !important;
+	}
+</style>

+ 53 - 0
api/cleared.js

@@ -0,0 +1,53 @@
+import axios from '@/libs/axios.js'
+
+// 全部待清运网点列表
+export const waitToCleanList = params => {
+	let url = `cleanStation/waitToCleanList/${params.pageNo}/${params.pageSize}`
+	delete params.pageNo
+	delete params.pageSize
+	return axios.request({
+		url: url,
+		method: 'post',
+		data: params
+	})
+}
+
+// 网点设备列表信息
+export const stationDevice = params => {
+  return axios.request({
+    url: `device/queryWaitCleanDeviceByStationNo/${params.stationNo}`,
+    method: 'get',
+  })
+}
+
+//  网点信息
+export const getWaitToCleanDetailHeader = params => {
+  return axios.request({
+    url: `station/findById/${params.stationNo}`,
+    method: 'get',
+  })
+}
+
+// 已清运列表
+export const getAlreadyCleanList = params => {
+	let url = `cleanLog/getAlreadyCleanList/${params.pageNo}/${params.pageSize}`
+	delete params.pageNo
+	delete params.pageSize
+	return axios.request({
+		url: url,
+		method: 'post',
+		data: params
+	})
+}
+
+// 已清运网点设备列表信息
+export const getAlreadyCleanDetails = params => {
+	let url = `cleanLog/getAlreadyCleanDetails/${params.pageNo}/${params.pageSize}`
+	delete params.pageNo
+	delete params.pageSize
+	return axios.request({
+		url: url,
+		method: 'post',
+		data: params
+	})
+}

+ 8 - 0
api/data.js

@@ -0,0 +1,8 @@
+import axios from '@/libs/axios.js';
+// 根据字典code查询选项
+export const getLookUpDatas = (params) => {
+  return axios.request({
+    url: `lookup/findByLookup/${params.type}`,
+    method: 'get'
+  })
+}

+ 43 - 0
api/login.js

@@ -0,0 +1,43 @@
+import axios from '@/libs/axios.js';
+
+export const login = params => {
+  return axios.request({
+    url: `login`,
+    method: 'post',
+	data: params
+  },true)
+};
+export const logout = params => {
+  return axios.request({
+    url: `logout`,
+    data: params,
+    method: 'get'
+  })
+};
+
+// 验证是否登录过
+export const checkLogin = () => {
+  let token = getApp().globalData.token
+  if (token&&token!='') {
+    return axios.request({
+      url: `checkToken`,
+      method: 'get'
+    })
+  } else {
+    return new Promise(resolve => {
+      resolve({
+        status: '9001',
+        message: '系统未登录'
+      });
+    });
+  }
+};
+
+// 获取登录用户信息
+export const getUserInfo = params => {
+  return axios.request({
+    url: `customer/getDetail`,
+    data: params,
+    method: 'get'
+  })
+};

+ 67 - 0
api/unclear.js

@@ -0,0 +1,67 @@
+import axios from '@/libs/axios.js'
+
+// 个人待清运列表
+export const getSelfCleanTaskList = params => {
+	let url = `cleanStation/getSelfCleanTaskList/${params.pageNo}/${params.pageSize}`
+	delete params.pageNo
+	delete params.pageSize
+	return axios.request({
+		url: url,
+		method: 'post',
+		data: params
+	})
+}
+
+// 个人待清运列表详情
+export const getSelfCleanTaskDetails = params => {
+  return axios.request({
+    url: `cleanDevice/getSelfCleanTaskDetails`,
+    method: 'post',
+	data: params
+  })
+}
+
+// 新增个人待清运
+export const cleanStationAdd = params => {
+  return axios.request({
+    url: `cleanStation/addCleanTask`,
+    method: 'post',
+	data: params
+  })
+}
+
+// 移除个人待清运
+export const cleanStationRemove = params => {
+  return axios.request({
+    url: `cleanStation/removeCleanTask/${params.stationNo}`,
+    method: 'post',
+	data: params
+  })
+}
+
+// 扫码清运
+export const cleanDevice = params => {
+  return axios.request({
+    url: `cleanDevice/clean`,
+    method: 'post',
+	data: params
+  })
+}
+
+// 清运路线
+export const getCleanWay = params => {
+  return axios.request({
+    url: `cleanStation/getCleanWay`,
+    method: 'post',
+	data: params
+  })
+}
+
+//  扫码获取网点信息
+export const getDeviceMsg = params => {
+  return axios.request({
+    url: `cleanDevice/getDeviceMsg`,
+    method: 'post',
+	data: params
+  })
+}

+ 148 - 0
api/user.js

@@ -0,0 +1,148 @@
+import axios from '@/libs/axios.js'
+
+//  axios.request()  第二个参数若为true则表示不传token
+
+// 手机号登录
+export const loginPhone = (params) => {
+  return axios.request({
+    url: 'loginPhone',
+    data: params,
+    method: 'post'
+  }, true)
+}
+// 微信授权登录
+export const login = (params) => {
+  return axios.request({
+    url: 'login',
+    data: params,
+    method: 'post'
+  }, true)
+}
+//  校验手机号是否注册
+export const validateUser = params => {
+  return axios.request({
+    url: `org/apply/validateUser/${params.phone}`,
+    method: 'get'
+  }, true)
+}
+// 获取图片验证码
+export const getCaptcha = randomCode => {
+  return axios.request({
+    url: `org/apply/getCaptcha/${randomCode}`,
+    method: 'get',
+    responseType: 'blob',
+  }, true)
+}
+// 发送短信验证码
+export const sendVerifyCode = params => {
+  return axios.request({
+    url: 'org/apply/sendVerifyCode',
+    method: 'post',
+    data: params
+  }, true)
+}
+// 申请试用
+export const apply = params => {
+  return axios.request({
+    url: 'org/apply/apply',
+    method: 'post',
+    data: params
+  }, true)
+}
+// 获取门店名称
+export const getStore = (token) => {
+  return axios.request({
+    url: 'getStore',
+    method: 'get'
+  })
+}
+// 登出
+export const logout = () => {
+  return axios.request({
+    url: 'logout',
+    method: 'get'
+  })
+}
+// 修改密码
+export const changePwd = params => {
+  return axios.request({
+    url: 'user/updatePwd',
+    method: 'post',
+    data: {
+      oldPassword: params.oldPassword,
+      password: params.password
+    }
+  }).then(res => res)
+} 
+//  忘记密码 校验手机号是否注册过
+export const memberGetByMobile = params => {
+  return axios.request({
+    url: 'member/getByMobile',
+    method: 'post',
+    data: params
+  }, true)
+}
+//  忘记密码 获取图片验证码
+export const memberCaptcha = randomCode => {
+  return axios.request({
+    url: `member/captcha/create/${randomCode}`,
+    method: 'get',
+    responseType: 'blob'
+  }, true)
+}
+//  忘记密码 发送短信验证码
+export const memberVerifyCode = params => {
+  return axios.request({
+    url: 'member/sendVerifyCode',
+    method: 'post',
+    data: params
+  }, true)
+}
+//  忘记密码 修改密码
+export const memberChangePwd = params => {
+  return axios.request({
+    url: 'member/changePwd',
+    method: 'post',
+    data: params
+  }, true)
+}
+//  忘记密码 校验短信验证码是否正确
+export const memberValidateVerifyCode = params => {
+  return axios.request({
+    url: 'member/validateVerifyCode',
+    method: 'post',
+    data: params
+  }, true)
+}
+// 获取通知消息未读数
+export const getUnreadCount = params => {
+  return axios.request({
+    url: 'noticeUser/queryNotReadCount',
+    method: 'post'
+  })
+}
+// 设置已读消息
+export const hasRead = params => {
+  return axios.request({
+    url: `noticeUser/setRead/${params.msg_id}`,
+    method: 'get'
+  })
+}
+// 查询所有消息
+export const getMessage = params => {
+  let url = `noticeUser/queryLike/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios.request({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+// 获取用户信息
+export const getUserInfo = params => {
+  return axios.request({
+    url: `user/userInfo`,
+    method: 'get'
+  })
+}

+ 125 - 0
components/m-input.vue

@@ -0,0 +1,125 @@
+<template>
+	<view class="m-input-view">
+		<input :focus="focus" :type="inputType" :value="value" @input="onInput" class="m-input-input" :placeholder="placeholder"
+		 :password="type==='password'&&!showPassword" :maxlength="maxlength" @focus="onFocus" @blur="onBlur" />
+		<!-- 优先显示密码可见按钮 -->
+		<view v-if="clearable&&!displayable&&value.length" class="m-input-icon">
+			<uni-icons color="#666666" type="clear" @click="clear"></uni-icons>
+		</view>
+		<view v-if="displayable" class="m-input-icon">
+			<uni-icons :style="{color:showPassword?'#666666':'#cccccc'}" type="eye" @click="display"></uni-icons>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		props: {
+			/**
+			 * 输入类型
+			 */
+			type: String,
+			/**
+			 * 值
+			 */
+			value: String,
+			/**
+			 * 占位符
+			 */
+			placeholder: String,
+			/**
+			 * 是否显示清除按钮
+			 */
+			clearable: {
+				type: [Boolean, String],
+				default: false
+			},
+			/**
+			 * 是否显示密码可见按钮
+			 */
+			displayable: {
+				type: [Boolean, String],
+				default: false
+			},
+			/**
+			 * 自动获取焦点
+			 */
+			focus: {
+				type: [Boolean, String],
+				default: false
+			},
+			maxlength: {
+				type: Number,
+				default: -1
+			}
+		},
+		model: {
+			prop: 'value',
+			event: 'input'
+		},
+		data() {
+			return {
+				/**
+				 * 显示密码明文
+				 */
+				showPassword: false,
+				/**
+				 * 是否获取焦点
+				 */
+				isFocus: false
+			}
+		},
+		computed: {
+			inputType() {
+				const type = this.type
+				return type === 'password' ? 'text' : type
+			}
+		},
+		methods: {
+			clear() {
+				this.$emit('input', '')
+			},
+			display() {
+				this.showPassword = !this.showPassword
+			},
+			onFocus() {
+				this.isFocus = true
+			},
+			onBlur() {
+				this.$nextTick(() => {
+					this.isFocus = false
+				})
+			},
+			onInput(e) {
+				this.$emit('input', e.detail.value)
+			}
+		}
+	}
+</script>
+
+<style>
+	.m-input-view {
+		display: inline-flex;
+		flex-direction: row;
+		align-items: center;
+		/* width: 100%; */
+		flex: 1;
+		padding: 0 10px;
+		margin-top: 20rpx;
+	}
+
+	.m-input-input {
+		flex: 1;
+		width: 100%;
+		min-height: 100%;
+		line-height: inherit;
+		background-color: rgba(0, 0, 0, 0);
+	}
+
+	.m-input-icon {
+		width: 20px;
+		font-size: 20px;
+		line-height: 20px;
+		color: #666666;
+	}
+</style>

+ 96 - 0
components/uni-icons/icons.js

@@ -0,0 +1,96 @@
+export default {
+	'contact': '\ue100',
+	'person': '\ue101',
+	'personadd': '\ue102',
+	'contact-filled': '\ue130',
+	'person-filled': '\ue131',
+	'personadd-filled': '\ue132',
+	'phone': '\ue200',
+	'email': '\ue201',
+	'chatbubble': '\ue202',
+	'chatboxes': '\ue203',
+	'phone-filled': '\ue230',
+	'email-filled': '\ue231',
+	'chatbubble-filled': '\ue232',
+	'chatboxes-filled': '\ue233',
+	'weibo': '\ue260',
+	'weixin': '\ue261',
+	'pengyouquan': '\ue262',
+	'chat': '\ue263',
+	'qq': '\ue264',
+	'videocam': '\ue300',
+	'camera': '\ue301',
+	'mic': '\ue302',
+	'location': '\ue303',
+	'mic-filled': '\ue332',
+	'speech': '\ue332',
+	'location-filled': '\ue333',
+	'micoff': '\ue360',
+	'image': '\ue363',
+	'map': '\ue364',
+	'compose': '\ue400',
+	'trash': '\ue401',
+	'upload': '\ue402',
+	'download': '\ue403',
+	'close': '\ue404',
+	'redo': '\ue405',
+	'undo': '\ue406',
+	'refresh': '\ue407',
+	'star': '\ue408',
+	'plus': '\ue409',
+	'minus': '\ue410',
+	'circle': '\ue411',
+	'checkbox': '\ue411',
+	'close-filled': '\ue434',
+	'clear': '\ue434',
+	'refresh-filled': '\ue437',
+	'star-filled': '\ue438',
+	'plus-filled': '\ue439',
+	'minus-filled': '\ue440',
+	'circle-filled': '\ue441',
+	'checkbox-filled': '\ue442',
+	'closeempty': '\ue460',
+	'refreshempty': '\ue461',
+	'reload': '\ue462',
+	'starhalf': '\ue463',
+	'spinner': '\ue464',
+	'spinner-cycle': '\ue465',
+	'search': '\ue466',
+	'plusempty': '\ue468',
+	'forward': '\ue470',
+	'back': '\ue471',
+	'left-nav': '\ue471',
+	'checkmarkempty': '\ue472',
+	'home': '\ue500',
+	'navigate': '\ue501',
+	'gear': '\ue502',
+	'paperplane': '\ue503',
+	'info': '\ue504',
+	'help': '\ue505',
+	'locked': '\ue506',
+	'more': '\ue507',
+	'flag': '\ue508',
+	'home-filled': '\ue530',
+	'gear-filled': '\ue532',
+	'info-filled': '\ue534',
+	'help-filled': '\ue535',
+	'more-filled': '\ue537',
+	'settings': '\ue560',
+	'list': '\ue562',
+	'bars': '\ue563',
+	'loop': '\ue565',
+	'paperclip': '\ue567',
+	'eye': '\ue568',
+	'arrowup': '\ue580',
+	'arrowdown': '\ue581',
+	'arrowleft': '\ue582',
+	'arrowright': '\ue583',
+	'arrowthinup': '\ue584',
+	'arrowthindown': '\ue585',
+	'arrowthinleft': '\ue586',
+	'arrowthinright': '\ue587',
+	'pulldown': '\ue588',
+	'closefill': '\ue589',
+	'sound': '\ue590',
+	'scan': '\ue612'
+}

File diff suppressed because it is too large
+ 10 - 0
components/uni-icons/uni-icons.vue


+ 142 - 0
components/uni-navbar/uni-navbar.vue

@@ -0,0 +1,142 @@
+<template>
+	<view class="navbar custom-class" :style="{ 'height': navHeight+'px' }">
+	  <view class="navbar-action-wrap navbar-action-group row item-center" :style="{'top': navTop+'px'}">
+			<view v-if="isBack" class="navbar-action_item" @tap="navBack">
+				<u-icon name="arrow-left" color="#2979ff" size="28"></u-icon>
+			</view>
+			<view v-if="isMap" class="navbar-action_item last map-bar" @tap="toMap">
+				<u-image class="map-icon" width="24rpx" height="36rpx" src="/static/map-icon.png"></u-image>
+				<view class="item-label">清运地图</view>
+			</view>
+	  </view>
+	  <view class='navbar-title' :style="{'top': navTop+'px'}">
+	    {{pageName}}
+	  </view>
+	</view>
+</template>
+
+<script>
+	export default {
+		props: {
+			pageName: String,
+			showNav:{
+			  type: Boolean,
+			  value: true
+			},
+			bgColor: {
+			  type: String,
+			  value: '#fff'
+			},
+			isBack: {
+				type: Boolean,
+				value: false
+			},
+			isMap: {
+				type: Boolean,
+				value: false
+			}
+		},
+		mounted() {
+			let menuButtonObject = wx.getMenuButtonBoundingClientRect()
+			const _this = this
+			wx.getSystemInfo({
+			  success (res) {
+				let statusBarHeight = res.statusBarHeight,
+				navTop = menuButtonObject.top,//胶囊按钮与顶部的距离
+				navHeight = statusBarHeight + menuButtonObject.height + (menuButtonObject.top - statusBarHeight)*2;//导航高度
+				_this.navHeight = navHeight;
+				_this.navTop = navTop;
+				_this.windowHeight = res.windowHeight;
+			  }
+			})
+		},
+		data() {
+			return {
+				navHeight: '',
+				navTop: '',
+				windowHeight: ''
+			}
+		},
+		methods: {
+			//回退
+			navBack: function () {
+				uni.navigateBack({
+				  delta: 1
+				})      
+			},
+			//配送地图
+			toMap: function () {
+				uni.navigateTo({
+					url: '/pages/index/map'
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.navbar {
+	  width: 100%;
+	  overflow: hidden;
+	  position: relative;
+	  top: 0;
+	  left: 0;
+	  z-index: 10;
+	  flex-shrink: 0;
+	  .navbar-action-wrap {
+	    display: -webkit-flex;
+	    display: flex;
+	    -webkit-box-align: center;
+	    -ms-flex-align: center;
+	    -webkit-align-items: center;
+	    align-items: center;
+	    position: absolute;
+	    left: 10px;
+	    z-index: 11;
+	    line-height: 1;
+	    padding-top: 8px;
+	    padding-bottom: 4px;
+	  }
+	  .navbar-action-group {
+	    overflow: hidden;
+		.navbar-action_item {
+		  border-right: 1px solid #f0f0f0;
+		  color: #333;
+		}
+		.last {
+		  border-right: none;
+		}
+		.map-bar{
+			text-align: center;
+			.map-icon{
+				display: inline-block;
+				margin-right: 10rpx;
+			}
+			.item-label{
+				display: inline-block;
+				font-size: 24rpx;
+				vertical-align: text-top;
+				color: #07c160;
+			}
+		}
+	  }
+	  .navbar-title {
+	    width: 100%;
+	    box-sizing: border-box;
+	    padding-left: 115px;
+	    padding-right: 115px;
+	    height: 32px;
+	    line-height: 32px;
+	    text-align: center;
+	    position: absolute;
+	    left: 0;
+	    z-index: 10;
+	    color: #333;
+	    font-size: 16px;
+	    font-weight: bold;
+	    text-overflow: ellipsis;
+	    overflow: hidden;
+	    white-space: nowrap;
+	  }
+	}
+</style>

+ 97 - 0
libs/axios.js

@@ -0,0 +1,97 @@
+import { objToUrl } from '@/libs/tools.js';
+const baseUrl = getApp().globalData.baseUrl
+//带Token请求
+const request = (opts, hasToken) => {
+	const authorization = getApp().globalData.token
+	// console.log(authorization,'authorization')
+	//  hasToken是否传入token,为true则不传token
+	const header = {
+			'content-Type': 'application/json;charset=UTF-8'
+		}
+	if(!hasToken&&authorization){
+		header['X-AUTH-TOKEN'] = authorization
+	}	
+	//此token是登录成功后后台返回保存在storage中的
+	let DefaultOpts = {
+		url: baseUrl+opts.url,
+		data: opts.data,
+		method: opts.method,
+		header: opts.header ? opts.header : header
+	}
+	let promise = new Promise(function(resolve, reject) {
+		uni.request(DefaultOpts).then(
+			(res) => {
+				if(res[0]&&res[0].errMsg.indexOf('request:fail')>=0){
+					resolve({
+						status: 6000,
+						message: "网络请求失败"
+					})
+				}
+				let ret = res[1]
+				if(res[1].data.status){
+					ret = res[1].data
+				}else if(res[1].status){
+					ret = res[1]
+				}
+				if(ret.status == '200'){
+					resolve(ret)
+				}else{
+					if(ret.status != '401'){
+						setTimeout(()=>{  //  通过延时避免uni.hideLoading()关闭加载中状态时同时关闭提示信息
+							uni.showToast({
+								icon:'none',
+								title: ret.message,
+								mask: true,
+								duration: 5000 
+							})
+						}, 1000)
+					}else{
+						setTimeout(()=>{
+							uni.showToast({
+								icon:'none',
+								title: '未登录或登录已过期,请重新登录',
+								duration: 5000 
+							})
+						}, 500)
+						setTimeout(function() {
+						  const currentRoute = getRoutePath()
+						  const url = `/pages/login/login?lanuch=${currentRoute.lanuch}&path=` + encodeURIComponent(currentRoute.url)
+						  uni.redirectTo({ url })
+						}, 1000);
+					}
+					resolve(ret)
+				}
+				resolve(ret)
+			}
+		).catch(
+			(response) => {
+				reject(response)
+			}
+		)
+	})
+	return promise
+}
+function getRoutePath() {
+  // eslint-disable-next-line no-undef
+  const pages = getCurrentPages(); // 获取加载的页面
+  const currentPage = pages[pages.length - 1]; // 获取当前页面的对象
+  let url = currentPage.route; // 当前页面url
+  const options = objToUrl(currentPage.options); // 如果要获取url中所带的参数可以查看options
+
+  const lanuch = [
+    'pages/index/index'
+  ].includes(url);
+  url = '/' + url;
+  if (options.length) {
+    url += '?' + options;
+  }
+  return {
+    url,
+    lanuch
+  };
+}
+
+export default {
+	baseUrl,
+	request
+}

File diff suppressed because it is too large
+ 0 - 0
libs/qqmap-wx-jssdk.min.js


+ 29 - 0
libs/tools.js

@@ -0,0 +1,29 @@
+export function objToUrl(obj) {
+  let uri = '';
+  let keys = Object.keys(obj);
+  keys.forEach(item => {
+    uri += '&' + item + '=' + obj[item];
+  });
+
+  uri = uri.substr(1);
+
+  return uri;
+}
+
+export function parseQueryString(url) {
+    var obj = {};
+    var keyvalue = [];
+    var key = "",
+        value = "";
+    var paraString = url.substring(url.indexOf("?") + 1, url.length).split("&");
+    for (var i in paraString) {
+        keyvalue = paraString[i].split("=");
+        key = keyvalue[0];
+        value = keyvalue[1];
+        obj[key] = value;
+    }
+    return obj;
+}
+
+
+  

+ 5 - 0
libs/validate.js

@@ -0,0 +1,5 @@
+//  正则有效手机号码
+export const isvalidPhone = function (str) {
+  const reg = /^1[0-9]{10}$/
+  return reg.test(str)
+}

+ 45 - 0
main.js

@@ -0,0 +1,45 @@
+import Vue from 'vue'
+import App from './App'
+import store from '@/store'
+Vue.config.productionTip = false
+
+App.mpType = 'app'
+import uView from "uview-ui"
+Vue.use(uView)
+
+let vuexStore = require("@/store/$u.mixin.js")
+Vue.mixin(vuexStore)
+/*
+* 提示信息
+*/ 
+Vue.prototype.toashMsg = function (title) {
+	title = title == undefined ? "系统繁忙" : title;
+	uni.showToast({
+		title:title,
+		icon:'none',
+		duration: 2000
+	})
+}
+/**
+ * 权限检查
+ */
+Vue.prototype.$hasPermissions = function (value) {
+ let isExist = false;
+ let permissionsStr = store.state.vuex_userData.permCodes;
+ // console.log(permissionsStr,'permissionsStr')
+ if (permissionsStr == undefined || permissionsStr == null) {
+  return false;
+ }
+ let has = permissionsStr.find(item => {
+   return item == value
+ })
+ if (has) {
+  isExist = true;
+ }
+ return isExist;
+}
+const app = new Vue({
+	store,
+    ...App
+})
+app.$mount()

+ 85 - 0
manifest.json

@@ -0,0 +1,85 @@
+{
+    "name" : "乐色管家清运端",
+    "appid" : "__UNI__D3A9765",
+    "description" : "乐色管家清运端小程序",
+    "versionName" : "1.0.0",
+    "versionCode" : "100",
+    "transformPx" : false,
+    /* 5+App特有相关 */
+    "app-plus" : {
+        "usingComponents" : true,
+        "nvueCompiler" : "uni-app",
+        "compilerVersion" : 3,
+        "splashscreen" : {
+            "alwaysShowBeforeRender" : true,
+            "waiting" : true,
+            "autoclose" : true,
+            "delay" : 0
+        },
+        /* 模块配置 */
+        "modules" : {},
+        /* 应用发布信息 */
+        "distribute" : {
+            /* android打包配置 */
+            "android" : {
+                "permissions" : [
+                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_CONTACTS\"/>",
+                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_CONTACTS\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
+                    "<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
+                    "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
+                    "<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+                    "<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
+                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
+                ]
+            },
+            /* ios打包配置 */
+            "ios" : {},
+            /* SDK配置 */
+            "sdkConfigs" : {}
+        }
+    },
+    /* 快应用特有相关 */
+    "quickapp" : {},
+    /* 小程序特有相关 */
+    "mp-weixin" : {
+        "appid" : "wxd38fd339f957b425",
+        "setting" : {
+            "urlCheck" : false,
+            "es6" : true,
+            "minified" : true
+        },
+        "usingComponents" : true,
+        "permission" : {
+            "scope.userLocation" : {
+                "desc" : "需要获取用户位置信息定位门店的位置"
+            }
+        }
+    },
+    "mp-alipay" : {
+        "usingComponents" : true
+    },
+    "mp-baidu" : {
+        "usingComponents" : true
+    },
+    "mp-toutiao" : {
+        "usingComponents" : true
+    },
+    "uniStatistics" : {
+        "enable" : false
+    }
+}

+ 13 - 0
package-lock.json

@@ -0,0 +1,13 @@
+{
+  "name": "zxyj-cust-mini-html",
+  "version": "1.0.0",
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "uview-ui": {
+      "version": "1.7.8",
+      "resolved": "https://registry.npmjs.org/uview-ui/-/uview-ui-1.7.8.tgz",
+      "integrity": "sha512-9mc3FbpvN7knmmdBmlGv9eF6us16co/bvTPrFEsS8QrSo9AZyrFyET9KHIdESwURP79jv1SLtR01VEb3HGSN8A=="
+    }
+  }
+}

+ 19 - 0
package.json

@@ -0,0 +1,19 @@
+{
+  "name": "zxyj-cust-mini-html",
+  "version": "1.0.0",
+  "description": "",
+  "main": "main.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "repository": {
+    "type": "git",
+    "url": "http://git.chelingzhu.com/chelingzhu-web/zxyj-cust-mini-html.git"
+  },
+  "keywords": [],
+  "author": "",
+  "license": "ISC",
+  "dependencies": {
+    "uview-ui": "^1.7.7"
+  }
+}

+ 114 - 0
pages.json

@@ -0,0 +1,114 @@
+{
+	"easycom": {
+		"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
+	},
+	"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
+		{
+			"path": "pages/index/index", // 待清运
+			"style": {
+				"navigationBarTitleText": "待清运清单",
+				"enablePullDownRefresh": false,
+				"navigationStyle": "custom"
+			}
+		},
+		{
+			"path": "pages/login/login",
+			"style": {
+				"navigationBarTitleText": "登录"
+			}
+		},
+		{
+			"path": "pages/login/pwLogin",
+			"style": {
+				"navigationBarTitleText": "密码登录"
+			}
+		},
+		{
+			"path": "pages/index/map",
+			"style": {
+				"navigationBarTitleText": "清运地图"
+			}
+		},
+		{
+			"path": "pages/cleared/chooseNetwork",
+			"style": {
+				"navigationBarTitleText": "待清运网点"
+			}
+		},
+		{
+			"path": "pages/cleared/network",
+			"style": {
+				"navigationBarTitleText": "网点详情"
+			}
+		},
+		{
+			"path": "pages/cleared/index", // 已清运
+			"style": {
+				"navigationBarTitleText": "已清运",
+				"enablePullDownRefresh": false
+			}
+		},
+		{
+			"path": "pages/cleared/details", // 已清运详情
+			"style": {
+				"navigationBarTitleText": "详情"
+			}
+		},
+		{
+			"path": "pages/userCenter/index",
+			"style": {
+				"navigationBarTitleText": "个人中心",
+				"navigationBarBackgroundColor": "#01c9b2",
+				"navigationBarTextStyle": "white"
+			}
+		},
+		{
+			"path": "pages/agreement/agreement",
+			"style": {
+				"navigationBarTitleText": "注意事项及服务协议"
+			}
+		},
+		{
+			"path": "pages/userCenter/changePwd",		//  我的>修改密码
+			"style": {
+				"navigationBarTitleText": "修改密码"
+			}
+		}
+    ],
+	"globalStyle": {
+		"navigationBarTextStyle": "black",
+		"navigationBarTitleText": "uni-app",
+		"navigationBarBackgroundColor": "#FFFFFF",
+		"backgroundColor": "#f2f2f2",
+		"app-plus": {
+			// 将回弹属性关掉
+			"bounce": "none",
+			"scrollIndicator": "none"
+		}
+	},
+	"tabBar": {
+		"color": "#7A7E83",
+		"selectedColor": "#01c9b2",
+		"backgroundColor": "#ffffff",
+		"fontSize": "14px",
+		"list": [
+		{
+			"pagePath": "pages/index/index",
+			"iconPath": "static/tabbar/unclean.png",
+			"selectedIconPath": "static/tabbar/unclean-active.png",
+			"text": "待清运"
+		},
+		{
+			"pagePath": "pages/cleared/index",
+			"iconPath": "static/tabbar/cleared.png",
+			"selectedIconPath": "static/tabbar/cleared-active.png",
+			"text": "已清运"
+		},
+		{
+			"pagePath": "pages/userCenter/index",
+			"iconPath": "static/tabbar/user.png",
+			"selectedIconPath": "static/tabbar/user-active.png",
+			"text": "我的"
+		}]
+	}
+}

+ 223 - 0
pages/agreement/agreement.vue

@@ -0,0 +1,223 @@
+<template>
+	<view class="content">
+		<view class="page-content">
+			<view class="page-care agreement">
+				<view class="title">-乐色管家清运端用户服务协议(声明)-</view>
+				<view class="xy-cons">
+					<view class="MsoNormal">
+						“乐色管家清运端用户小程序”(以下简称“用户小程序”)由陕西智享亿家环保科技有限公司(以下简称“本公司”)提供。用户在登录用户小程序时,均被视为已经仔细阅读本条款并完全同意。凡以任何方式登录本用户小程序,包括但不限于接受用户小程序服务、直接或间接使用本用户小程序资料、第三方链接等,均被视为自愿接受本用户小程序相关声明和用户服务协议的约束。
+					</view>
+					<view class="MsoNormal">
+						一、用户小程序使用
+					</view>
+					<view class="MsoNormal">
+						本用户小程序之设计、信息内容等任何组成部分均不得被复制、抄袭或被任何未经本公司允许的任何商业目的所使用。若本公司怀疑或确定用户行为违法或有损本公司利益,则本公司保留采取相关法律措施的权利,包括但不限于拒绝提供服务、冻结或删除用户帐户等。
+					</view>
+					<view class="MsoNormal">
+						二、链接
+					</view>
+						<view class="MsoNormal">(一) 本用户小程序对第三方网站的链接</view>
+						<view class="MsoNormal">
+							本用户小程序必要时将提供第三方经营的其他网站的超级链接或指引服务,或者通过帧联及其他方式在本用户小程序上提供第三方网站相关内容,此“内容”包括但不限于本用户小程序上包含或可获得的任何软件、资料、音频、信息以及本用户小程序上提供的其他任何信息
+						</view>
+						<view class="MsoNormal">
+							对于第三方网站的超级链接或指引服务,仅限于方便之用。本公司保留任何时段终止对第三方网站超级链接的权利。所链接的网站、网站之内容及其网站所提供的产品与服务均不受本公司的控制,因此本公司不对任何该等网站及其内容、产品或服务(包括对第三方网站的进一步链接)负责,并且不对其作出任何认可、建议、批准或介绍。若您一旦登录或使用任何所链接网站,请仔细阅读该网站免责条款,同时自行采取防护措施。由于您自行登录或使用所链接的第三方网站所产生的任何风险和损失,责任自担 ; 除非本公司另行明确规定或同意,否则,本公司将不是您和任何所链网站提供者之间达成的任何协议的当事方。
+						</view>
+					<view class="MsoNormal">
+						本用户小程序上出现对第三方网站的链接并不表示本公司或本用户小程序与其相关联,或已获得合法授权使用,包括但不限于被链接网站中显示的或可通过其链接到的任何商标、商号、标识或著作权等。
+					</view>
+					<view class="MsoNormal">
+						<view class="MsoNormal">(二) 第三方网站对本用户小程序的链接</view>
+						<view class="MsoNormal">
+							第三方网站对本用户小程序的链接,并不必然表示本公司对第三方作出了某种认可、授权、赞助,或表明其属于本公司的关联企业、合资企业、合作企业或业务伙伴。多数情况下,本公司并未意识到或授权第三方提供对本用户小程序的链接。
+						</view>
+						
+					</view>
+					<view class="MsoNormal">
+						三、前瞻性陈述
+					</view>
+					<view class="MsoNormal">
+						本用户小程序可能包含某些前瞻性陈述。这类前瞻性陈述包括但不限于:关于本公司业务经营策略的陈述;关于供应链服务网络扩建计划(包括与之有关的拟作出的资本投资)的陈述;关于计划发展的供应链服务及其相关应用的陈述;关于费用变动对本公司经营业绩的预期影响的陈述;关于竞争对本公司经营业绩的影响的陈述;关于供应链行业未来发展(包括行业结构调整及政府政策的变化)的陈述;以及与本公司未来业务发展、经营及业绩有关的其他陈述。本公司在使用“预期”、“相信”、“预测”、“期望”、“打算”及其他类似词语进行陈述时,旨在表明相关陈述属于前瞻性陈述
+					</view>
+					<view class="MsoNormal">
+						这些前瞻性陈述本质上具有相当风险和不确定性。本公司不能保证会及时或不断地更新这类前瞻性陈述。这类前瞻性陈述反映的是本公司当前状态下对未来事件的预见或规划,并不属于对未来本公司经营和业务的保证。未来本公司的实际经营和业务很有可能会因诸多客观因素而与某些前瞻性陈述有重大差异,这些因素包括但不限于:供应链行业结构的进一步调整;所需政府批准及许可条件、政策、资本投资的优先程度等监管政策的变化;行业竞争对本公司服务的需求或价格的影响;以及中国内地的政治、经济、文化、法律以及社会各方面情况的变化(包括经济增长、通货膨胀、外汇及可动用的信用额度等政策的变化)
+					</view>
+					<view class="MsoNormal">
+						此外,本公司未来往来供应链的扩建或收缩、资金投资、发展计划和规划,均取决于诸多种因素,包括但不限于是否能以可接受的条款获得足够融资;我们的发展和获得新技术及其应用的能力;是否有合格的管理及技术人员等诸多因素
+					</view>
+					<view class="MsoNormal">
+						四、用户隐私权的保护
+					</view>
+						<view class="MsoNormal">(一) 用户资料的收集</view>
+						<view class="MsoNormal">
+							本用户小程序用户在匿名的状态下即可访问并获取相关信息,本用户小程序请求用户提供相关用户信息之前,本用户小程序会释明用户相关信息用途。本公司承诺仅在与本公司经营活动和经营业务有关的合法目的下,并经用户同意以合法的方式收集必要的用户信息。
+						</view>
+						<view class="MsoNormal">
+							用户使用本用户小程序需注册后方提供的服务,用户需同意以下事项:依本用户小程序注册表之提示提供用户本人真实有效、正确、完整及最新的用户信息,并保证个人信息和资料的适时更新;本企业因用户所提供的不准确、不完整或未及时更新的用户信息给用户造成的任何损害,本公司不承担任何法律和赔偿责任。本公司因用户提供的不准确、不完整或未及时更新的用户信息给本公司造成损害的,本公司保留法律追责权利。
+						</view>
+						<view class="MsoNormal">(二) 用户资料的使用</view>
+						<view class="MsoNormal">
+							本公司有权为内部业务目的使用由您提供的用户信息,这类内部业务目的包括但不限于:促进本公司业务或本公司提供给客户的服务、产品的日常管理和运营;监测本用户小程序的使用及安全情况,实施内部控制、制备数据统计、进行规划和研究等;优化设计、服务和产品;市场调研和推广;记录、核对、确认及维护用户或其他相关人员的联络名单;解决争议、排除问题和执行本法律声明;服务本公司所涉及的任何经营活动或日常业务;或与上述任何一项目的直接相关的其它目的
+						</view>
+						<view class="MsoNormal">
+							基于以上目的,对用户信息有使用权的人,除本公司外,还包括经本公司合法授权、与本公司业务和经营活动有关的本公司的任何附属公司、联营公司、业务伙伴和专业顾问,以及向本公司提供或与本公司业务和经营活动有关的行政管理、电信服务、收付款服务、计算机信息服务或其它服务的任何代理人、承包商或第三方服务提供者。
+						</view>
+						<view class="MsoNormal">(三) 用户资料的披露</view>
+						<view class="MsoNormal">本用户小程序将采取合理有效的安全手段保护用户所提供的用户信息,在未经得用户许可前,本公司承诺并保证绝不将用户的任何个人信息和资料提供给任何无关第三方,但有下列情形之一的除外:</view>
+						<view class="MsoNormal">
+							<text>(</text>1<text>)根据法律、行政法规的规定,有权机关要求提供的</text>
+						</view>
+						<view class="MsoNormal">
+							<text>(</text>2<text>)由于用户对自身信息保密不当,导致用户非公开信息泄露的</text>
+						</view>
+						<view class="MsoNormal">
+							<text>(</text>3<text>)由于网络线路、黑客攻击、计算机病毒等原因造成的用户信息和资料泄露、丢失、被盗用或被篡改的</text>
+						</view>
+						<view class="MsoNormal">
+							<text>(</text>4<text>)为了保护本用户小程序用户的权利或财产</text>
+						</view>
+						<view class="MsoNormal">
+							<text>(</text>5<text>)在紧急的情况下,为了保护本用户小程序及其用户本人或公众安全的</text>
+						</view>
+						<view class="MsoNormal">
+							<text>(</text>6<text>)其他特殊或紧急情况</text>
+						</view>
+					<view class="MsoNormal">
+						五、知识产权保护
+					</view>
+					<view class="MsoNormal">
+						【本用户小程序所载述的域名、商标、商号、信息、文字、图形、图像、声音、链接、软件及所有其它内容或组成部分均由本公司、内容或组成部分提供商或第三方许可人提供。上述内容的知识产权依具体情况分别为本公司、内容或组成部分提供商或第三方许可人所拥有。
+					</view>
+					<view class="MsoNormal">
+						未经本公司或商标权人事先书面许可,任何单位或个人不得以任何方式或理由对本用户小程序的商标、商号或标识的任何部分进行使用、复制、修改、传播或与其它产品捆绑使用
+					</view>
+					<view class="MsoNormal">
+						除法律另有规定或双方另有约定外,未经本公司和/或其他权利人事先书面许可,任何人不得以任何形式通过任何方式(包括但不限于电子、机械复印或录制等方式)复制、展示、修改、转让、分发、重新发布、下载、张贴或传输本用户小程序的内容。
+					</view>
+					<view class="MsoNormal">
+						六、免责声明
+					</view>
+					<view class="MsoNormal">
+						本用户小程序所提供的信息,仅供参考之用,不宜用于任何研究或商业用途。本用户小程序并不保证该等信息的准确性、有效性、及时性或完整性。本公司及其员工无需以任何方式就任何信息传递或传送的失误、不准确或错误对用户或任何其他人士负任何直接或间接责任。在法律和本用户小程序允许的范围内,本公司不承担用户或任何第三方就使用或未能使用本用户小程序所提供的信息或任何链接所引致的任何直接、间接的损害赔偿(包括但不限于收益、预期利润的损失或失去的业务、未实现预期的节减)。本公司保留自行决定及修改、更正本用户小程序中任何内容和组成部分的权利(包括任何遗漏或错误的信息和内容)。本公司可以在任何时间对本用户小程序、本用户小程序上所描述的内容、产品、项目、服务或价格作出任何修改,而无需事前通知和事后说明,有需要的情况除外
+					</view>
+					<view class="MsoNormal">
+						本用户小程序、本用户小程序所述的内容、信息和材料以及在本用户小程序上可获得的软件等均“依原样”提供,不包含任何明示或暗示性质的陈述或保证。在法律许可或不禁止范围内,本公司承诺不作出任何明示或暗示性质的陈述和保证,包括但不限于有关安全性、准确性、完整性、适销性、无侵权、适合某项特别目的或没有计算机病毒的保证。您应为使用本用户小程序承担全部责任和风险。
+					</view>
+					<view class="MsoNormal">如发生以下情况,本用户小程序不对用户的直接或间接损失承担法律责任:</view>
+					<view class="MsoNormal">
+						<text>(</text>1<text>)营业中断</text>
+					</view>
+					<view class="MsoNormal">
+						<text>(</text>2<text>)无法登录本用户小程序,或登录本用户小程序延迟或中断</text>
+					</view>
+					<view class="MsoNormal">
+						<text>(</text>3<text>)数据无法传送、错误传送、毁损、灭失或其他修改</text>
+					</view>
+					<view class="MsoNormal">
+						<text>(</text>4<text>)因处理本用户小程序上对其它用户小程序的链接或本用户小程序上存在对其它用户小程序的链接所遭受的任何种类的损失或损害</text>
+					</view>
+					<view class="MsoNormal">
+						<text>(</text>5<text>)就客户使用本用户小程序(包括链接到第三方用户小程序或自第三方用户小程序链接)而可能产生的计算机病毒、系统失灵或功能紊乱</text>
+					</view>
+					<view class="MsoNormal">
+						<text>(</text>6<text>)本法律声明第四条第三项中规定的六种情形所引起的用户个人资料的披露或泄露</text>
+					</view>
+					<view class="MsoNormal">
+						<text>(</text>7<text>)因不可抗力或本公司无法合理控制的其他原因所导致的用户损失</text>
+					</view>
+					<view class="MsoNormal">
+						七、服务变更、暂停、中断或终止
+					</view>
+					<view class="MsoNormal">
+						如因系统升级或维护需要而暂停本用户小程序网络服务时,本用户小程序将尽可能事先通告。
+					</view>
+					<view class="MsoNormal">
+						如发生下列情形之一,本用户小程序有权随时暂停、中断或终止向用户提供本用户小程序用户服务而无需通知,并有权拒绝用户于当前、未来某时段或永久使用本用户小程序所提供服务之全部或任何部分:(1)用户提供任何错误、不实、过时、不完整或具有误导性的信息和资料,或本用户小程序有理由或有依据怀疑前述信息和资料为错误、不实、过时、不完整或具误导性的;(2)用户违反本法律声明或相关使用协议中规定的任何使用规则。
+					</view>
+					<view class="MsoNormal">
+						除上述情形外,本用户小程序同时保留在不事先通知用户的情况下随时暂停、中断或终止部分或全部网络服务的权利,对于所有服务的暂停、中断或终止而造成的任何损失,除法律另有规定或双方另有约定外,本公司不对用户或任何第三方承担任何法律责任。
+					</view>
+					<view class="MsoNormal">
+						八、条款修改
+					</view>
+					<view class="MsoNormal">
+						本公司保留在任何时间自行修改、增删本法律声明中的任何内容和条款的权利。您每次登录或使用本用户小程序时,均视为同意接受当时已生效的用户声明条款的制约。因此,建议您每次登录或使用本用户小程序时查看本法律声明是否修订或增删及修订或增删的情况
+					</view>
+					<view class="MsoNormal">
+						九、法律适用与司法管辖
+					</view>
+					<view class="MsoNormal">
+						本法律声明的制定、执行、解释及争议问题的解决和处理均适用中华人民共和国法律、法规。双方因使用本用户小程序所产生的争议,若协商不成,任何一方可向本公司所在地人民法院提起诉讼。
+					</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		components: {
+		},
+		data() {
+			return {
+			}
+		},
+		onLoad(option) {
+			uni.setNavigationBarTitle({
+				title: "服务协议"
+			})
+			// 开启分享
+			uni.showShareMenu({
+				withShareTicket: true,
+				menus: ['shareAppMessage', 'shareTimeline']
+			})
+		},
+		methods: {
+		}
+	}
+</script>
+
+<style lang="scss">
+	page{
+		width: 100%;
+		height: 100%;
+	}
+	.content{
+		padding: 0;
+		width: 100%;
+		height: 100%;
+		display: flex;
+		flex-direction: column;
+		.page-content{
+			flex: 1;
+			overflow-y: scroll;
+		}
+		.title{
+			font-size: 30rpx;
+			font-weight: 600;
+		}
+		.xy-cons{
+			padding: 30rpx;
+			line-height: 42rpx;
+			.MsoNormal{
+				text-indent: 52rpx;
+				margin-bottom: 14rpx;
+			}
+		}
+		.page-care{
+			width: 100%;
+			display: flex;
+			flex-direction: column;
+			align-items: center;
+			padding-top: 20rpx;
+		}
+		.footer{
+			width: 100%;
+			text-align: center;
+			line-height: 100rpx;
+			background-color: rgb(255,0,0);
+			color: #fff;
+		}
+	}
+</style>

+ 345 - 0
pages/cleared/chooseNetwork.vue

@@ -0,0 +1,345 @@
+<template>
+	<view class="choose-network-container">
+		<!-- 筛选弹框 -->
+		<search-modal v-if="openScreen" :visible="openScreen" :defaultParams="searchForm" @refresh="refresh" @close="openScreen=false"></search-modal>
+		<view class="choose-network-header">
+			<view class="checked-all">
+				<u-checkbox
+					v-if="listdata.length>0"
+					class="checked-all-c"
+					active-color="#01c9b2"
+					@change="checkedAll" 
+					v-model="isCheckedAll"
+					label-size="26"
+					name="checkedAll"
+				>全选</u-checkbox>
+			</view>
+			<view class="choose-checked" @tap="openScreen=true">
+				已选:<text>{{checkedList.length}}</text>
+				<image class="filter-icon" src="@/static/filter.png"></image>
+			</view>
+		</view>
+		<scroll-view class="scroll-con" scroll-y :scroll-top="scrollTop" @scrolltolower="onreachBottom">
+			<!-- 列表数据 -->
+			<u-checkbox-group class="cell-item-con">
+				<view class="cell-item" v-for="(item, index) in listdata" :key="index">
+					<view class="cell-item-c">
+						<u-checkbox
+							class="cell-item-checkbox"
+							@change="checkboxChange($event, index)"
+							active-color="#01c9b2"
+							v-model="item.checked"
+							:name="item.id">
+							<view class="cell-item-info">
+								<view class="cell-item-info-network">
+									{{item.stationName || '--'}}
+									<u-badge type="success" bgColor="#c90101" :count="item.unCleanNum" :offset="[-10,-32]" size="mini"></u-badge>
+								</view>
+								<view class="cell-item-info-weight">
+									<view class="cell-item-weight-bar">
+										{{ item.totalWeight }}kg
+										<u-badge class="badge" type="primary" bgColor="#01c9b2" count="总" :offset="[0,0]"></u-badge>
+									</view>
+									<view class="cell-item-weight-bar">
+										{{ item.maxWeight }}kg
+										<u-badge class="badge" type="warning" bgColor="#05695d" count="最大" :offset="[0,0]"></u-badge>
+									</view>
+								</view>
+							</view>
+						</u-checkbox>
+						<view class="details-con" @tap="goPage(item)">
+							<u-icon name="arrow-right" class="arrow-right" :size="28" color="#999"></u-icon>
+						</view>
+					</view>
+				</view>
+			</u-checkbox-group>
+			<u-empty class="nodata" :text="noDataText" v-if="listdata.length==0 && status!='loading'" mode="list"></u-empty>
+			<view class="loadmore" v-if="listdata.length!=0">
+				<u-loadmore v-if="total>pageSize || status=='loading'" :status="status" />
+			</view>
+		</scroll-view>
+		<view class="footer-bar">
+			<u-button class="footer-handle-btn handle-btn" hover-class="none" :custom-style="btnStyle" shape="circle" @click="handleAdd" size="medium" type="primary">
+				<text>加入待清运清单</text>
+			</u-button>
+		</view>
+	</view>
+</template>
+
+<script>
+	import searchModal from '@/pages/cleared/searchModal.vue'
+	import { waitToCleanList } from '@/api/cleared.js'
+	import { cleanStationAdd } from '@/api/unclear.js'
+	export default{
+		components: { searchModal },
+		data(){
+			return{
+				listdata: [],
+				pageNo: 1,  //  当前页码
+				pageSize: 40,  //  每页条数
+				total: 0,  //  数据总条数
+				noDataText: '暂无数据',  //  列表请求状态提示语
+				status: 'loadmore',  //  加载中状态
+				scrollTop: 0,  //  滚动条位置
+				isCheckedAll: false,  //  全选状态
+				checkedNum: 0,  //  已选个数
+				checkedList: [],  //  已选清运网点
+				openScreen: false, //  是否打开筛选
+				searchForm: {
+					//  查询条件
+					stationName: '',  //  网点名称
+					orderType: 'max', // 排序方式
+				},
+				btnStyle: {  //  自定义按钮样式
+					borderColor: '#07c160',
+					backgroundColor: '#07c160',
+					width: '100%'
+				},
+			}
+		},
+		onShow() {
+			this.openScreen = false  //  关闭筛选框
+			this.refresh(this.searchForm)
+		},
+		methods: {
+			//  加入清运单
+			handleAdd(){
+				if(this.checkedList.length > 0){
+					uni.showLoading({
+						mask: true,
+					    title: '加载中'
+					})
+					cleanStationAdd({ stationNoList: this.checkedList }).then(res => {
+						uni.hideLoading()
+						if(res.status == 200){
+							uni.showToast({ icon:'none', title: res.message })
+							setTimeout(()=>{
+								uni.navigateBack()
+							}, 1000)
+						}else{
+							uni.showToast({ icon:'none', title: res.message })
+						}
+					})
+				}else{
+					uni.showToast({ icon:'none', title: '请勾选需清运的网点' })
+				}
+			},
+			// 选中某个复选框时,由checkbox时触发
+			checkboxChange(e,ind) {
+				this.listdata[ind].checked = e.value
+				let len = 0
+				this.checkedList = []
+				this.listdata.map(item => {
+					if(item.checked){
+						len++
+						this.checkedList.push(item.stationNo)
+					}
+				})
+				this.checkedNum = len
+			},
+			// 全选
+			checkedAll(e) {
+				this.isCheckedAll = e
+				let len = 0
+				this.checkedList = []
+				this.listdata.map(val => {
+					val.checked = e.value ? true : false
+					if(val.checked){
+						len++
+						this.checkedList.push(val.stationNo)
+					}
+				})
+				this.checkedNum = len
+			},
+			// 获取查询参数 刷新列表
+			refresh(params){
+				this.searchForm = params
+				this.listdata = []
+				this.total = 0
+				this.isCheckedAll = false
+				this.checkedList = []
+				this.searchHandle(1)
+			},
+			// 搜索查询
+			searchHandle (pageNo) {
+				uni.showLoading({
+					mask: true,
+				    title: '加载中'
+				})
+				this.status = "loading"
+				pageNo ? this.pageNo = pageNo : null,
+				waitToCleanList({
+					pageNo: this.pageNo,
+					pageSize: this.pageSize,
+					stationName: this.searchForm.stationName,
+					orderType: this.searchForm.orderType
+				}).then(res => {
+					uni.hideLoading()
+					if (res.status == 200) {
+						res.data.list.map(item => {
+							item.checked = false
+							item.totalWeight = item.totalWeight ? (item.totalWeight/1000).toFixed(3) : 0
+							item.maxWeight = item.maxWeight ? (item.maxWeight/1000).toFixed(3) : 0
+						})
+						if(this.pageNo>1){
+							this.listdata = this.listdata.concat(res.data.list || [])
+						}else{
+							this.listdata = res.data.list || []
+							this.scrollTop = 0
+						}
+						this.total = res.data.count || 0
+						this.noDataText = '暂无数据'
+					} else {
+						this.noDataText = res.message
+						this.listdata = []
+						this.total = 0
+					}
+					this.status = "loadmore"
+				})
+			},
+			//  查看详情
+			goPage(record){
+				uni.navigateTo({
+				    url: '/pages/cleared/network?stationNo=' + record.stationNo
+				})
+			},
+			// scroll-view到底部加载更多
+			onreachBottom() {
+				if(this.listdata.length!=0 && this.listdata.length < this.total){
+					this.pageNo += 1
+					this.searchHandle()
+				}else{
+					uni.showToast({ title: '已经到底了', icon: 'none' })
+					this.status = "nomore"
+				}
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	page{
+		height: 100%;
+	}
+	.choose-network-container {
+		width: 100%;
+		height: 100%;
+		display: flex;
+		flex-direction: column;
+		padding-top: 80rpx;
+		padding-bottom: 102rpx;
+		position: relative;
+		// 顶部固定
+		.choose-network-header{
+			position: fixed;
+			top: 0;
+			left: 0;
+			width: 100%;
+			display: flex;
+			justify-content: space-between;
+			align-items: center;
+			padding: 0 $uni-spacing-row-base;
+			box-sizing: border-box;
+			background-color: #fff;
+			line-height: 80rpx;
+			font-size: 26rpx;
+			.checked-all{
+				.checked-all-c{
+					font-size: 26rpx;
+				}
+			}
+			.choose-checked{
+				text{
+					color: red;
+				}
+				.filter-icon{
+					width: 36rpx;
+					height: 36rpx;
+					padding-left: 30rpx;
+					vertical-align: text-top;
+				}
+			}
+		}
+		//  列表
+		.scroll-con{
+			flex: 1;
+			overflow: auto;
+		}
+		//  列表样式
+		.cell-item-con{
+			.cell-item{
+				margin: $uni-spacing-col-base $uni-spacing-row-base;
+				background-color: #fff;
+				border-radius: $uni-border-radius-base;
+				color: $uni-text-color;
+				font-size: $uni-font-size-base;
+				box-shadow: 3rpx 3rpx 5rpx #eee;
+				padding: 20rpx 20rpx 20rpx 20rpx;
+				.cell-item-c{
+					display: flex;
+					justify-content: space-around;
+					align-items: center;
+					.cell-item-checkbox{
+						flex-grow: 1;
+						.cell-item-info{
+							margin-left: 4rpx;
+							padding: 10rpx 4px;
+							width: 67vw;
+							.cell-item-info-network{
+								word-break: break-all;
+								margin-bottom: 22rpx;
+								display: inline-block;
+								position: relative;
+							}
+							.cell-item-info-weight{
+								font-size: 24rpx;
+								display: flex;
+								align-items: center;
+								justify-content: space-between;
+								.cell-item-weight-bar{
+									position: relative;
+									display: inline-block;
+									padding-right: 50rpx;
+									&:nth-child(2){
+										padding-right: 76rpx;
+										margin-left: 30rpx;
+									}
+								}
+							}
+						}
+					}
+					.details-con{
+						flex-shrink: 0;
+						padding: 30rpx 0;
+						.arrow-right{
+							margin-left: 64rpx;
+						}
+					}
+					
+				}
+			}
+		}
+		.footer-bar{
+			width: 100%;
+			height: 102rpx;
+			padding: 0 10%;
+			position: fixed;
+			bottom: 0;
+			left: 0;
+			text-align: center;
+			.footer-handle-btn{
+				display: block;
+				.btn-icon{
+					margin-right: 10rpx;
+				}
+			}
+			.handle-btn{
+				margin-top: 18rpx;
+				margin-bottom: 20rpx;
+			}
+		}
+		.nodata{
+			padding-top: 400rpx;
+		}
+	}
+</style>

+ 213 - 0
pages/cleared/details.vue

@@ -0,0 +1,213 @@
+<template>
+	<view class="cleared-details-container">
+		<scroll-view class="scroll-con" scroll-y :scroll-top="scrollTop" @scrolltolower="onreachBottom">
+			<!-- 列表数据 -->
+			<view class="cell-item-con">
+				<view class="cell-item" v-for="(item, index) in listdata" :key="index">
+					<view class="cell-item-c">
+						<u-image class="cell-item-pic" src="/static/md-big-pic.png" width="100rpx" height="100rpx"></u-image>
+						<view class="cell-item-info">
+							<view class="cell-item-info-network">{{item.stationName || '--'}}</view>
+							<view class="cell-item-info-weight">清运总重量:<text>{{ (item.totalWeight/1000).toFixed(3) }}kg</text></view>
+						</view>
+					</view>
+					<u-grid :col="3" :hover-class="none">
+						<u-grid-item>
+							<view class="cell-item-main">
+								<text class="cell-item-number blue">{{ item.clothes ? (item.clothes/1000).toFixed(3) : 0 }}</text>
+								<text class="cell-item-unit">kg</text>
+							</view>
+							<view class="cell-item-exp">废旧衣物</view>
+						</u-grid-item>
+						<u-grid-item>
+							<view class="cell-item-main">
+								<text class="cell-item-number red">{{ item.plastic ? (item.plastic/1000).toFixed(3) : 0 }}</text>
+								<text class="cell-item-unit">kg</text>
+							</view>
+							<view class="cell-item-exp">废旧塑料</view>
+						</u-grid-item>
+						<u-grid-item>
+							<view class="cell-item-main">
+								<text class="cell-item-number yellow">{{ item.metal ? (item.metal/1000).toFixed(3) : 0 }}</text>
+								<text class="cell-item-unit">kg</text>
+							</view>
+							<view class="cell-item-exp">废旧金属</view>
+						</u-grid-item>
+						<u-grid-item>
+							<view class="cell-item-main">
+								<text class="cell-item-number green">{{ item.paper ? (item.paper/1000).toFixed(3) : 0 }}</text>
+								<text class="cell-item-unit">kg</text>
+							</view>
+							<view class="cell-item-exp">废旧纸张</view>
+						</u-grid-item>
+						<u-grid-item>
+							<view class="cell-item-main">
+								<text class="cell-item-number yellow">{{ item.plaMet ? (item.plaMet/1000).toFixed(3) : 0 }}</text>
+								<text class="cell-item-unit">kg</text>
+							</view>
+							<view class="cell-item-exp">废旧金属/塑料</view>
+						</u-grid-item>
+						<u-grid-item>
+							<view class="cell-item-main">
+								<text class="cell-item-number yellow">{{ item.glass ? (item.glass/1000).toFixed(3) : 0 }}</text>
+								<text class="cell-item-unit">kg</text>
+							</view>
+							<view class="cell-item-exp">废旧玻璃</view>
+						</u-grid-item>
+						<u-grid-item>
+							<view class="cell-item-main">
+								<text class="cell-item-number yellow">{{ item.recycling ? (item.recycling/1000).toFixed(3) : 0 }}</text>
+								<text class="cell-item-unit">kg</text>
+							</view>
+							<view class="cell-item-exp">可回收物</view>
+						</u-grid-item>
+					</u-grid>
+				</view>
+			</view>
+			<u-empty class="nodata" :text="noDataText" v-if="listdata.length==0 && status!='loading'" mode="list"></u-empty>
+			<view class="loadmore" v-if="listdata.length!=0">
+				<u-loadmore v-if="total>pageSize || status=='loading'" :status="status" />
+			</view>
+		</scroll-view>
+	</view>
+</template>
+
+<script>
+	import { getAlreadyCleanDetails } from '@/api/cleared.js'
+	export default{
+		data(){
+			return{
+				listdata: [],
+				pageNo: 1,  //  当前页码
+				pageSize: 10,  //  每页条数
+				total: 0,  //  数据总条数
+				noDataText: '暂无数据',  //  列表请求状态提示语
+				status: 'loadmore',  //  加载中状态
+				scrollTop: 0,  //  滚动条位置
+				createDate: ''  //  时间
+			}
+		},
+		onLoad(options) {
+			this.createDate = options.createDate
+		},
+		onShow() {
+			this.refresh()
+		},
+		methods: {
+			// 获取查询参数 刷新列表
+			refresh(){
+				this.listdata = []
+				this.total = 0
+				this.searchHandle(1)
+			},
+			// 搜索查询
+			searchHandle (pageNo) {
+				uni.showLoading({
+					mask: true,
+				    title: '加载中'
+				})
+				this.status = "loading"
+				pageNo ? this.pageNo = pageNo : null
+				getAlreadyCleanDetails({
+					pageNo: this.pageNo,
+					pageSize: this.pageSize,
+					createDate: this.createDate
+				}).then(res => {
+					uni.hideLoading()
+					if (res.status == 200) {
+						if(this.pageNo>1){
+							this.listdata = this.listdata.concat(res.data.list || [])
+						}else{
+							this.listdata = res.data.list || []
+							this.scrollTop = 0
+						}
+						this.total = res.data.count || 0
+						this.noDataText = '暂无数据'
+					} else {
+						this.noDataText = res.message
+						this.listdata = []
+						this.total = 0
+					}
+					this.status = "loadmore"
+				})
+			},
+			// scroll-view到底部加载更多
+			onreachBottom() {
+				if(this.listdata.length!=0 && this.listdata.length < this.total){
+					this.pageNo++
+					this.searchHandle()
+				}else{
+					uni.showToast({ title: '已经到底了', icon: 'none' })
+					this.status = "nomore"
+				}
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.cleared-details-container{
+		width: 100%;
+		//  列表
+		.scroll-con{
+			overflow: auto;
+			height: 100vh;
+		}
+		.cell-item-con{
+			.cell-item{
+				margin: $uni-spacing-col-base $uni-spacing-row-base;
+				background-color: #fff;
+				border-radius: $uni-border-radius-base;
+				color: $uni-text-color;
+				font-size: $uni-font-size-base;
+				box-shadow: 3rpx 3rpx 5rpx #eee;
+				.cell-item-c{
+					display: flex;
+					align-items: center;
+					padding: $uni-spacing-col-base $uni-spacing-row-base;
+					.cell-item-pic{
+						flex-shrink: 0;
+						margin-right: 20rpx;
+					}
+					.cell-item-info{
+						flex-grow: 1;
+						.cell-item-info-network{
+							word-break: break-all;
+							margin-bottom: 10rpx;
+						}
+						.cell-item-info-weight{
+							font-size: 26rpx;
+							text{
+								font-weight: bold;
+							}
+						}
+					}
+				}
+				.cell-item-main{
+					margin-bottom: 10rpx;
+					.cell-item-number{
+						margin-right: 5rpx;
+					}
+					.cell-item-unit{
+						font-size: 26rpx;
+					}
+					.blue {
+						color: #1890FF;
+					}
+					.green {
+						color: #16b50e;
+					}
+					.red {
+						color: red;
+					}
+					.yellow {
+						color: #ff9900;
+					}
+				}
+			}
+		}
+		.nodata{
+			padding-top: 400rpx;
+		}
+	}
+</style>

+ 175 - 0
pages/cleared/index.vue

@@ -0,0 +1,175 @@
+<template>
+	<view class="cleared-container">
+		<scroll-view class="scroll-con" scroll-y :scroll-top="scrollTop" @scrolltolower="onreachBottom">
+			<!-- 列表数据 -->
+			<view class="cell-item-con">
+				<view class="cell-item" v-for="(item, index) in listdata" :key="index" @tap="goPage(item)">
+					<view class="cell-item-c">
+						<view class="cell-item-date">{{ item.cleanDate.substr(0,10) }}</view>
+						<view class="cell-item-orderNum">
+							<u-icon name="arrow-right" :size="28" color="#999"></u-icon>
+						</view>
+					</view>
+					<u-grid :col="3" :hover-class="none">
+						<u-grid-item>
+							<view class="cell-item-main">
+								<text class="cell-item-number blue">{{item.stationNum || 0}}</text>
+								<text class="cell-item-unit">个</text>
+							</view>
+							<view class="cell-item-exp">清运网点数</view>
+						</u-grid-item>
+						<u-grid-item>
+							<view class="cell-item-main">
+								<text class="cell-item-number green">{{item.boxNum || 0}}</text>
+								<text class="cell-item-unit">个</text>
+							</view>
+							<view class="cell-item-exp">清运箱体数</view>
+						</u-grid-item>
+						<u-grid-item>
+							<view class="cell-item-main">
+								<text class="cell-item-number red">{{ (item.totalWeight/1000).toFixed(3) || 0 }}</text>
+								<text class="cell-item-unit">kg</text>
+							</view>
+							<view class="cell-item-exp">清运总重量</view>
+						</u-grid-item>
+					</u-grid>
+				</view>
+			</view>
+			<u-empty class="nodata" :text="noDataText" v-if="listdata.length==0 && status!='loading'" mode="list"></u-empty>
+			<view class="loadmore" v-if="listdata.length!=0">
+				<u-loadmore v-if="total>pageSize || status=='loading'" :status="status" />
+			</view>
+		</scroll-view>
+	</view>
+</template>
+<script>
+	import { getAlreadyCleanList } from '@/api/cleared.js'
+	export default {
+		data() {
+			return {
+				listdata: [],
+				pageNo: 1,  //  当前页码
+				pageSize: 10,  //  每页条数
+				total: 0,  //  数据总条数
+				noDataText: '暂无数据',  //  列表请求状态提示语
+				status: 'loadmore',  //  加载中状态
+				scrollTop: 0,  //  滚动条位置
+			}
+		},
+		onShow() {
+			this.refresh()
+		},
+		methods:{
+			// 获取查询参数 刷新列表
+			refresh(){
+				this.listdata = []
+				this.total = 0
+				this.searchHandle(1)
+			},
+			// 搜索查询
+			searchHandle (pageNo) {
+				uni.showLoading({
+					mask: true,
+				    title: '加载中'
+				})
+				this.status = "loading"
+				pageNo ? this.pageNo = pageNo : null
+				getAlreadyCleanList({
+					pageNo: this.pageNo,
+					pageSize: this.pageSize,
+				}).then(res => {
+					uni.hideLoading()
+					if (res.status == 200) {
+						if(this.pageNo>1){
+							this.listdata = this.listdata.concat(res.data.list || [])
+						}else{
+							this.listdata = res.data.list || []
+							this.scrollTop = 0
+						}
+						this.total = res.data.count || 0
+						this.noDataText = '暂无数据'
+					} else {
+						this.noDataText = res.message
+						this.listdata = []
+						this.total = 0
+					}
+					this.status = "loadmore"
+				})
+			},
+			//  查看详情
+			goPage(row){
+				uni.navigateTo({
+				    url: '/pages/cleared/details?createDate='+row.cleanDate
+				})
+			},
+			// scroll-view到底部加载更多
+			onreachBottom() {
+				if(this.listdata.length!=0 && this.listdata.length < this.total){
+					this.pageNo++
+					this.searchHandle()
+				}else{
+					uni.showToast({ title: '已经到底了', icon: 'none' })
+					this.status = "nomore"
+				}
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	page{
+		height: 100%;
+	}
+	.cleared-container {
+		width: 100%;
+		height: 100%;
+		display: flex;
+		flex-direction: column;
+		//  列表
+		.scroll-con{
+			flex: 1;
+			overflow: auto;
+		}
+		//  列表样式
+		.cell-item-con{
+			.cell-item{
+				margin: $uni-spacing-col-base $uni-spacing-row-base;
+				background-color: #fff;
+				border-radius: $uni-border-radius-base;
+				color: $uni-text-color;
+				font-size: $uni-font-size-base;
+				box-shadow: 3rpx 3rpx 5rpx #eee;
+				.cell-item-c{
+					display: flex;
+					justify-content: space-between;
+					padding: 24rpx $uni-spacing-row-base;
+					.cell-item-date{
+						color: $uni-text-color-grey;
+					}
+				}
+				.cell-item-main{
+					display: inline-block;
+					margin-bottom: 10rpx;
+					.cell-item-number{
+						margin-right: 5rpx;
+					}
+					.cell-item-unit{
+						font-size: 26rpx;
+					}
+					.blue {
+						color: #1890FF;
+					}
+					.green {
+						color: #16b50e;
+					}
+					.red {
+						color: red;
+					}
+				}
+			}
+		}
+		.nodata{
+			padding-top: 400rpx;
+		}
+	}
+</style>

+ 253 - 0
pages/cleared/network.vue

@@ -0,0 +1,253 @@
+<template>
+	<view class="content">
+		<map 
+		id="map" 
+		:latitude="lat" 
+		:longitude="lng" 
+		scale="18" 
+		show-compass 
+		show-location 
+		:markers="markers"
+		style="width: 100%; height:500rpx;">
+		</map>
+		<!-- 网点信息及设备 -->
+		<view class="details" v-if="stationData">
+			<view class="details-address">
+				<image src="/static/md-big-pic.png" class="store-pic"></image>
+				<view class="store-info">
+					<view>{{ stationData.name || '--' }}</view>
+					<view>{{ stationData.provinceName||'' }}{{ stationData.cityName||'' }}{{ stationData.districtName||'' }}{{ stationData.address||'' }}</view>
+					<view>
+						营业时间:
+						<text v-for="(tItem, tInd) in stationData.deliveryTimeRuleItemList" :key="tInd">
+							{{ tItem.openTime }} - {{ tItem.closeTime }}{{ tInd == stationData.deliveryTimeRuleItemList.length - 1 ? '' : ',' }}
+						</text>
+					</view>
+				</view>
+			</view>
+			<!-- 设备列表 -->
+			<view class="details-dev">
+				<view class="details-dev-box" v-for="item in deviceData" :key="item.id">
+					<view class="details-dev-title">设备编号:<text>{{ item.srcDeviceCode }}</text></view>
+					<view class="details-dev-cons">
+						<view class="dev-item" v-for="boxItem in item.deviceTypeBoxList" :key="boxItem.id">
+							<view class="item-pic-con">
+								<text v-if="boxItem.flag==1" class="full-sign">已满</text>
+								<u-image mode="aspectFit" height="80" width="80" :src="`/static/${boxItem.rubbishType}.png`" class="type-sign"></u-image>
+							</view>
+							<view class="dev-main">
+								<view>
+									{{ boxItem.rubbishTypeDictValue }}
+								</view>
+								<view class="rule-con">
+									{{ boxItem.boxCode | stockVal(item) }}
+								</view>
+							</view>
+						</view>
+					</view>
+				</view>
+				<u-empty v-if="deviceData.length==0" icon-size="60" text="暂无设备" mode="list" margin-top="120"></u-empty>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import { stationDevice, getWaitToCleanDetailHeader } from '@/api/cleared.js'
+	export default {
+		data() {
+			return {
+				stationNo: '',  //  网点编号
+				lat: '',
+				lng: '',
+				mapCtx: null, // 地图对象
+				markers: [], // 标注点
+				stationData: null,  //  网点信息
+				deviceData: [],  //  设备信息
+			};
+		},
+		filters: {
+			stockVal: function (val, obj) {  //  各个内置箱体的当前【库存量】
+				let num
+				if(val == 1){
+					num = obj.boxOne ? (obj.boxOne/1000).toFixed(3) : 0
+					return num + 'kg'
+				}else if(val == 2){
+					num = obj.boxTwo ? (obj.boxTwo/1000).toFixed(3) : 0
+					return num + 'kg'
+				}else if(val == 3){
+					num = obj.boxThree ? (obj.boxThree/1000).toFixed(3) : 0
+					return num + 'kg'
+				}else if(val == 4){
+					num = obj.boxFour ? (obj.boxFour/1000).toFixed(3) : 0
+					return num + 'kg'
+				}else if(val == 5){
+					num = obj.boxFive ? (obj.boxFive/1000).toFixed(3) : 0
+					return num + 'kg'
+				}
+			}
+		},
+		onLoad(options) {
+			this.stationNo = options.stationNo
+			this.getStation()  //  网点信息
+			this.getDevice()  //  设备信息
+			// 开启分享
+			uni.showShareMenu({
+				withShareTicket: true,
+				menus: ['shareAppMessage', 'shareTimeline']
+			})
+		},
+		methods: {
+			//  网点信息
+			getStation(){
+				getWaitToCleanDetailHeader({ stationNo: this.stationNo }).then(res => {
+					if(res.status == 200){
+						this.stationData = res.data
+						this.markers = []
+						this.markers.push({
+							latitude: res.data.lat,
+							longitude: res.data.lng,
+							width: 30,
+							height: 30,
+							iconPath: "/static/store.png"
+						})
+						this.lng = res.data.lng
+						this.lat = res.data.lat
+					}else{
+						this.stationData = null
+						this.markers = []
+						this.lng = ''
+						this.lat = ''
+					}
+				})
+			},
+			//  设备信息
+			getDevice(){
+				stationDevice({ stationNo: this.stationNo }).then(res => {
+					if(res.status == 200){
+						this.deviceData = res.data
+					}else{
+						this.deviceData = []
+					}
+				})
+			},
+			//  根据垃圾类型获取兑换规则
+			getRule(type){
+				let row = null
+				if(this.stationData.goldExRuleItemList){
+					row = this.stationData.goldExRuleItemList.find(item => item.rubbishType == type)
+				}
+				return { rubbishWeight: row.rubbishWeight || 0, goleNum: row.goleNum || 0 }
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+.content{
+	width: 100%;
+	padding: 0;
+	.details{
+		margin: 20upx;
+		.details-address{
+			display: flex;
+			align-items: center;
+			padding: 20upx;
+			background: #FFFFFF;
+			border-radius: 15upx;
+			box-shadow: 0upx 3upx 6upx #eee;
+			margin-bottom: 20upx;
+			.store-pic{
+				width: 120rpx;
+				height:120rpx;
+				margin-right: 20rpx;
+			}
+			.store-info{
+				>view{
+					font-size: 24upx;
+					padding: 5upx 0;
+					color: #666;
+					&:first-child{
+						font-weight: bold;
+						font-size: 30upx;
+						color: #333;
+					}
+				}
+			}
+		}
+		.details-dev{
+			.details-dev-box{
+				padding: 20upx 20upx 5upx;
+				background: #FFFFFF;
+				border-radius: 15upx;
+				box-shadow: 0upx 3upx 6upx #eee;
+				margin-bottom: 20upx;
+				.details-dev-title{
+					border-bottom: 1px solid #F8F8F8;
+					padding: 10upx 0 20upx;
+					text{
+						color: #666;
+					}
+				}
+				.details-dev-cons{
+					padding: 10upx 0;
+					display: flex;
+					flex-wrap: wrap;
+					.dev-item{
+						width: 50%;
+						display: flex;
+						align-items: center;
+						> view{
+							padding: 25upx 10upx 15upx 0;
+							&:last-child{
+								view{
+									display: flex;
+									align-items: center;
+									.u-tag{
+										margin-left: 10upx;
+									}
+								}
+							}
+						}
+						.item-pic-con{
+							position: relative;
+							padding-left: 30rpx;
+							.full-sign{
+								font-size: 24rpx;
+								padding: 4rpx 10rpx 14rpx;
+								color: #fff;
+								background: url('/static/full-bg.png') no-repeat;
+								background-size: 100% 100%;
+								transform: scale(0.8);
+								position: absolute;
+								left: 0;
+								top: 0;
+								width: 68rpx;
+								height: 55rpx;
+								z-index: 9;
+							}
+						}
+						.dev-main{
+							.rule-con{
+								color: #666;
+								font-size: 24upx;
+								.goleNum{
+									color: #eb0000;
+									font-size: 26rpx;
+									font-weight: bold;
+									margin-left: 4rpx;
+								}
+								.ld-pic{
+									width: 30rpx;
+									height: 30rpx;
+									margin-left: 6rpx;
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+}
+</style>

+ 194 - 0
pages/cleared/searchModal.vue

@@ -0,0 +1,194 @@
+<template>
+	<!-- 待办单查询 -->
+	<div class="modal-content">
+		<u-popup v-model="isShow" class="search-popup" mode="right" @close="handleClose" length="85%">
+			<view class="search-title">筛选</view>
+			<u-form class="form-content" :model="form" ref="uForm" label-width="150">
+				<u-form-item label="网点名称:" prop="stationName" class="form-item"><u-input v-model="form.stationName" :maxlength="30" placeholder="请输入网点名称" /></u-form-item>
+				<u-form-item label="排序方式:" prop="orderType" class="form-item">
+					<view @tap="openSort=true" :style="{color: form.orderType?null:'#c0c4cc'}">{{orderTypeName}}</view>
+				</u-form-item>
+			</u-form>
+			<view class="uni-list-btns">
+				<u-button class="handle-btn search-btn" size="medium" hover-class="none" :custom-style="customBtnStyle" @click="handleSearch">查询</u-button>
+				<u-button class="handle-btn" size="medium" hover-class="none" @click="resetForm">重置</u-button>
+			</view>
+		</u-popup>
+		<u-picker mode="selector" v-model="openSort" :default-selector="selectDefault" :range="list" range-key="dispName" @confirm="confirm"></u-picker>
+	</div>
+</template>
+
+<script>
+import { getLookUpDatas } from '@/api/data.js'
+export default {
+	props: {
+		visible: {
+			type: Boolean,
+			default: false
+		},
+		defaultParams: {  //  默认筛选条件
+			type: Object,
+			default: () => {
+				return {}
+			}
+		}
+	},
+	watch: {
+		visible(newValue, oldValue) {
+			if (newValue) {
+				this.isShow = newValue
+			}
+		},
+		isShow(newValue, oldValue) {
+			if (newValue) {
+			} else {
+				this.init()
+				this.$emit('close')
+			}
+		}
+	},
+	data() {
+		return {
+			customBtnStyle: {  //  自定义按钮样式
+				borderColor: '#07c160',
+				backgroundColor: '#07c160',
+				color: '#fff'
+			},
+			isShow: this.visible, // 显示隐藏
+			form: {
+				stationName: '',  //  套餐名称
+				orderType: '', // 客户手机
+			},
+			list: [],
+			openSort: false,  //  选择
+			orderTypeName: '请选择',
+			selectDefault: [0],  //  下拉默认选中项
+		};
+	},
+	mounted() {
+		this.init()
+	},
+	created() {
+		this.getLookUpDatas()
+	},
+	methods: {
+		//  获取数据字典
+		getLookUpDatas(){
+			getLookUpDatas({ type: 'WAIT_CLEAN_SORT_RULE' }).then(res => {
+				if(res.status == 200){
+					this.list = res.data || []
+					this.form.orderType = this.defaultParams.orderType ? this.defaultParams.orderType : ''
+					if(this.defaultParams.orderType){
+						this.list.map((item, index) => {
+							if(item.code == this.form.orderType){
+								this.orderTypeName = this.list[index].dispName
+								this.selectDefault[0] = index
+							}
+						})
+					}
+				}else{
+					this.list = []
+					this.form.orderType = ''
+					this.orderTypeName = '请选择'
+					this.selectDefault = [0]
+				}
+			})
+		},
+		//  初始化数据
+		init(){
+			this.form.stationName = this.defaultParams.stationName ? this.defaultParams.stationName : ''
+		},
+		// 关闭弹窗
+		handleClose() {
+			this.isShow = false
+		},
+		// 查询
+		handleSearch() {
+			let params = {
+				stationName: this.form.stationName,
+				orderType: this.form.orderType,
+			};
+			this.$emit('refresh', params)
+			this.isShow = false
+		},
+		// 重置
+		resetForm() {
+			this.$refs.uForm.resetFields()
+			this.$emit('refresh', {orderType: 'max'})
+			this.isShow = false
+		},
+		//  确定
+		confirm(v){
+			this.selectDefault = v
+			this.form.orderType = this.list[v[0]].code
+			this.orderTypeName = this.list[v[0]].dispName
+		}
+	}
+};
+</script>
+
+<style lang="scss" scoped>
+.modal-content {
+	position: relative;
+}
+.search-popup {
+	.search-title {
+		text-align: center;
+		padding: 18rpx 22rpx;
+		color: #333;
+		border-bottom: 1px solid #eee;
+	}
+	.form-content {
+		display: block;
+		padding: 0 20rpx;
+		box-sizing: content-box;
+		.status-item {
+			width: 30%;
+			text-align: center;
+			line-height: 60rpx;
+			background-color: #F8F8F8;
+			color: #333;
+			border-radius: 6rpx;
+			font-size: 24rpx;
+			margin: 0 10rpx;
+		}
+		.active {
+			background-color: #ffaa00;
+			color: #fff;
+		}
+		.form-item-inp{
+			display: inline-block;
+			width: 88%;
+			vertical-align: top;
+		}
+	}
+	.uni-list {
+		margin: 20rpx;
+		.uni-list-cell {
+			display: flex;
+			align-items: center;
+			border-bottom: 1px dashed #eeeeee;
+			.uni-list-cell-db {
+				flex: 1;
+			}
+			.uni-input {
+				height: 2.5em;
+				line-height: 2.5em;
+			}
+		}
+	}
+	.uni-list-btns {
+		display: flex;
+		padding: 20rpx;
+		margin-top: 200rpx;
+		.handle-btn {
+			font-size: 28rpx;
+			margin: 0 30rpx;
+			width: 100%;
+			flex: 1;
+		}
+	}
+}
+.date-picker {
+}
+</style>

+ 394 - 0
pages/index/index.vue

@@ -0,0 +1,394 @@
+<template>
+	<view class="unclear-container">
+		<uni-navbar pageName="待清运清单" :isBack="false" :isMap="true"></uni-navbar>
+		<scroll-view class="scroll-con" scroll-y :scroll-top="scrollTop" @scrolltolower="onreachBottom">
+			<!-- 列表数据 -->
+			<view class="cell-item-con">
+				<view class="cell-item" v-for="(item, index) in listdata" :key="index">
+					<view class="cell-item-c" @tap="goPage(item)">
+						<view class="cell-item-info">
+							<view class="cell-item-info-network">
+								{{item.stationName || '--'}}
+								<u-badge type="success" bgColor="#c90101" :count="item.unCleanNum" :offset="[-10,-32]" size="mini"></u-badge>
+							</view>
+							<view class="cell-item-info-weight">
+								<view class="cell-item-weight-bar">
+									{{ item.totalWeight ? (item.totalWeight/1000).toFixed(3) : 0 }}kg
+									<u-badge class="badge" type="primary" bgColor="#01c9b2" count="总" :offset="[0,0]"></u-badge>
+								</view>
+								<view class="cell-item-weight-bar">
+									{{ item.maxWeight ? (item.maxWeight/1000).toFixed(3) : 0 }}kg
+									<u-badge class="badge" type="warning" bgColor="#05695d" count="最大" :offset="[0,0]"></u-badge>
+								</view>
+							</view>
+						</view>
+						<u-icon name="arrow-right" class="arrow-right" :size="28" color="#999"></u-icon>
+					</view>
+					<u-button size="mini" class="handle-btn" hover-class="none" :custom-style="customBtnStyle" @click="removeFun(item)">移除</u-button>
+				</view>
+			</view>
+			<u-empty class="nodata" :text="noDataText" v-if="listdata.length==0 && status!='loading'" mode="list"></u-empty>
+			<view class="loadmore" v-if="listdata.length!=0">
+				<u-loadmore v-if="total>pageSize || status=='loading'" :status="status" />
+			</view>
+		</scroll-view>
+		
+		<view class="footer-bar">
+			<u-button class="footer-handle-btn scan-btn" hover-class="none" :custom-style="scanBtnStyle" shape="circle" @click="clearingOutlets" size="medium" type="primary">
+				<u-icon name="scan" class="btn-icon" :size="28" color="#fff"></u-icon>
+				<text>扫码清运</text>
+			</u-button>
+			<u-button class="footer-handle-btn" hover-class="none" :custom-style="btnStyle" shape="circle" @click="openQuery" size="medium">
+				<u-icon name="plus" class="btn-icon" :size="28" color="#606266"></u-icon>
+				<text>增加清运网点</text>
+			</u-button>
+		</view>
+		<!-- 确认清运 -->
+		<u-popup v-model="messagePop" mode="center" class="custom-pop" length="80%" border-radius="14" :mask-close-able="false">
+			<view class="custom-con">
+				<view class="pop-title">提示</view>
+				<view class="pop-con">
+					<view class="pop-item">确认清运以下网点-设备内的可回收物?</view>
+					<view class="pop-item">{{networkData.stationName || ''}}</view>
+					<view class="pop-item">{{networkData.srcDeviceCode || ''}}</view>
+					<view class="form-con">
+						<u-form :model="form" ref="uForm">
+							<u-form-item label="备注" :border-bottom="false">
+								<u-input v-model="form.remarks" type="textarea" border />
+							</u-form-item>
+						</u-form>
+					</view>
+				</view>
+				<view class="btn-con">
+					<view class="handle-pop-btn cancel-btn" @click="cancelFun">取消</view>
+					<view class="handle-pop-btn submit-btn" @click="submitFun">确定</view>
+				</view>
+			</view>
+		</u-popup>
+	</view>
+</template>
+<script>
+	import { getSelfCleanTaskList, cleanDevice, cleanStationRemove, getDeviceMsg } from '@/api/unclear.js'
+	import { parseQueryString } from '@/libs/tools.js'
+	export default {
+		data() {
+			return {
+				listdata: [],
+				pageNo: 1,  //  当前页码
+				pageSize: 10,  //  每页条数
+				total: 0,  //  数据总条数
+				noDataText: '暂无数据',  //  列表请求状态提示语
+				status: 'loadmore',  //  加载中状态
+				customBtnStyle: {  //  自定义按钮样式
+					borderColor: '#01c9b2',
+					backgroundColor: '#01c9b2',
+					color: '#fff'
+				},
+				scrollTop: 0,  //  滚动条位置
+				scanBtnStyle: {  //  自定义按钮样式
+					borderColor: '#07c160',
+					backgroundColor: '#07c160',
+					width: '100%'
+				},
+				btnStyle: {  //  自定义按钮样式
+					width: '100%'
+				},
+				form: {
+					remarks: ''  //  备注
+				},
+				boxData: null,  //  箱体二维码数据
+				messagePop: false,  //  确认清运
+				networkData: null  //  网点详情
+			}
+		},
+		onShow() {
+			this.pageNo = 1
+			this.refresh()
+		},
+		methods:{
+			//  是否可清运
+			clearingOutlets(){
+				if(this.listdata.length==0){
+					uni.showToast({ title: '请先选择待清运网点,再进行扫码清运', icon: 'none' })
+				}else{
+					this.openScan()
+				}
+			},
+			//  扫码清运
+			openScan(){
+				const _this = this
+				uni.scanCode({
+					success(e) {
+						console.log(e)
+						//  箱体二维码数据
+						// {
+						// 	charSet: "ISO8859-1"
+						// 	errMsg: "scanCode:ok"
+						// 	rawData: "aHR0cDovL3d3dy5zeHp4eWoubmV0L3dlYi9zdGF0aWMvcXJjb2RlL2Rvd25sb2FkLWFwcC5odG1sP2lkPTFiODM3M2JhLWNmMDAtNDU2NS04Y2ZkLTVmOGZlNTYwYmNmMiZ0eXBlPWR1c3RiaW4="
+						// 	result: "http://www.sxzxyj.net/web/static/qrcode/download-app.html?id=1b8373ba-cf00-4565-8cfd-5f8fe560bcf2&type=dustbin"
+						// 	scanType: "QR_CODE"
+						// }
+						if(e.scanType == 'QR_CODE'){
+							//  将箱体二维码数据e.result携带参数转换为json
+							_this.boxData = parseQueryString(e.result)
+							_this.getNetworkInfo()
+						}
+					},
+					fail(err) {
+						console.log(err)
+					}
+				})
+			},
+			//  扫码获取网点信息
+			getNetworkInfo(){
+				const _this = this
+				getDeviceMsg(_this.boxData).then(res => {
+					if(res.status == 200){
+						_this.networkData = res.data
+						_this.form.remarks = ''
+						_this.messagePop = true
+					}else{
+						_this.messagePop = false
+					}
+				})
+			},
+			//  取消清运
+			cancelFun(){
+				this.messagePop = false
+			},
+			//  确定清运
+			submitFun(){
+				const _this = this
+				uni.showLoading({
+					mask: true,
+				    title: '加载中'
+				})
+				let obj = {}
+				obj.deviceNo = (this.networkData && this.networkData.deviceNo) ? this.networkData.deviceNo : ''
+				obj.remarks = this.form.remarks
+				cleanDevice(obj).then(res => {
+					uni.hideLoading()
+					if(res.status == 200){
+						uni.showToast({ icon:'none', title: '清运成功,库存重量已重置为0' })
+						_this.messagePop = false
+						setTimeout(()=>{
+							_this.refresh()
+						},1000)
+					}else{
+						uni.showToast({ icon:'none', title: res.message })
+					}
+				})
+			},
+			//  增加清运网点
+			openQuery(){
+				uni.navigateTo({
+				    url: '/pages/cleared/chooseNetwork'
+				})
+			},
+			// 获取查询参数 刷新列表
+			refresh(){
+				this.listdata = []
+				this.total = 0
+				this.searchHandle(1)
+			},
+			// 搜索查询
+			searchHandle (pageNo) {
+				uni.showLoading({
+					mask: true,
+				    title: '加载中'
+				})
+				this.status = "loading"
+				pageNo ? this.pageNo = pageNo : null
+				getSelfCleanTaskList({
+					pageNo: this.pageNo,
+					pageSize: this.pageSize
+				}).then(res => {
+					uni.hideLoading()
+					if (res.status == 200) {
+						if(this.pageNo>1){
+							this.listdata = this.listdata.concat(res.data.list || [])
+						}else{
+							this.listdata = res.data.list || []
+							this.scrollTop = 0
+						}
+						this.total = res.data.count || 0
+						this.noDataText = '暂无数据'
+					} else {
+						this.noDataText = res.message
+						this.listdata = []
+						this.total = 0
+					}
+					this.status = "loadmore"
+				})
+			},
+			//  移除
+			removeFun(row){
+				const _this = this
+				uni.showModal({
+				  title: '提示',
+				  content: '确认移除该网点的清运单?',
+				  success(res) {
+				    if (res.confirm) {
+						uni.showLoading({
+							mask: true,
+						    title: '加载中'
+						})
+						cleanStationRemove({ stationNo: row.stationNo }).then(ret => {
+							uni.hideLoading()
+							if(ret.status == 200){
+								uni.showToast({ title: ret.message, icon: 'none' })
+								_this.searchHandle(1)
+							}
+						})
+				    }
+				  }
+				})
+			},
+			//  查看详情
+			goPage(row){
+				uni.navigateTo({
+				    url: '/pages/cleared/network?stationNo='+row.stationNo
+				})
+			},
+			// scroll-view到底部加载更多
+			onreachBottom() {
+				if(this.listdata.length!=0 && this.listdata.length < this.total){
+					this.pageNo++
+					this.searchHandle()
+				}else{
+					uni.showToast({ title: '已经到底了', icon: 'none' })
+					this.status = "nomore"
+				}
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	page{
+		height: 100%;
+	}
+	.unclear-container {
+		width: 100%;
+		height: 100%;
+		display: flex;
+		flex-direction: column;
+		padding-bottom: 204rpx;
+		//  列表
+		.scroll-con{
+			flex: 1;
+			overflow: auto;
+		}
+		//  列表样式
+		.cell-item-con{
+			.cell-item{
+				margin: $uni-spacing-col-base $uni-spacing-row-base;
+				background-color: #fff;
+				border-radius: $uni-border-radius-base;
+				color: $uni-text-color;
+				font-size: $uni-font-size-base;
+				box-shadow: 3rpx 3rpx 5rpx #eee;
+				padding: 40rpx 20rpx;
+				position: relative;
+				.cell-item-c{
+					display: flex;
+					justify-content: space-around;
+					align-items: center;
+					.cell-item-info{
+						flex-grow: 1;
+						.cell-item-info-network{
+							word-break: break-all;
+							margin-bottom: 26rpx;
+							display: inline-block;
+							position: relative;
+						}
+						.cell-item-info-weight{
+							font-size: 24rpx;
+							display: flex;
+							align-items: center;
+							justify-content: space-between;
+							.cell-item-weight-bar{
+								position: relative;
+								display: inline-block;
+								padding-right: 50rpx;
+								&:nth-child(2){
+									padding-right: 76rpx;
+								}
+							}
+						}
+					}
+					.arrow-right{
+						flex-shrink: 0;
+						margin-left: 80rpx;
+					}
+				}
+				.handle-btn{
+					position: absolute;
+					right: $uni-spacing-row-sm;
+					top: $uni-spacing-col-sm;
+				}
+			}
+		}
+		.footer-bar{
+			width: 100%;
+			height: 204rpx;
+			padding: 0 10%;
+			position: fixed;
+			bottom: 0;
+			left: 0;
+			text-align: center;
+			.footer-handle-btn{
+				display: block;
+				.btn-icon{
+					margin-right: 10rpx;
+				}
+			}
+			.scan-btn{
+				margin-top: 24rpx;
+				margin-bottom: 20rpx;
+			}
+		}
+		// 弹框样式
+		.custom-pop{
+			.custom-con{
+				text-align: center;
+				background: url(/static/pop-bg.png) no-repeat;
+				background-size: 100% 100%;
+				font-size: 30rpx;
+				color: #5a5a5a;
+				line-height: 54rpx;
+				.pop-title{
+					padding: 20rpx 0;
+					color: #fff;
+					font-weight: bold;
+				}
+				.pop-con{
+					padding: 80rpx 0 40rpx;
+					.pop-item{
+						padding: 0 20rpx;
+					}
+					.form-con{
+						padding: 10rpx 30rpx;
+					}
+				}
+				.btn-con{
+					border-top: 1rpx solid rgba(213,213,213,0.8);
+					.handle-pop-btn{
+						padding: 20rpx 0;
+						width: 50%;
+						display: inline-block;
+					}
+					.cancel-btn{
+						border-right: 1rpx solid rgba(213,213,213,0.8);
+					}
+					.submit-btn{
+						color: #16d1bc;
+					}
+				}
+			}
+		}
+		.nodata{
+			padding-top: 400rpx;
+		}
+	}
+</style>

+ 225 - 0
pages/index/map.vue

@@ -0,0 +1,225 @@
+<template>
+	<view class="map-container">
+		<map
+			id="map"
+			:latitude="latitude"
+			:longitude="longitude"
+			scale="12"
+			show-compass
+			show-location
+			:markers="markers"
+			:polyline="polyline"
+			@markertap="markertap"
+			style="width: 100%; height:100%;">
+		</map>
+	</view>
+</template>
+
+<script>
+	import { getCleanWay } from '@/api/unclear.js'
+	var QQMapWX = require('@/libs/qqmap-wx-jssdk.min.js')
+	var qqmapsdk
+	export default{
+		data(){
+			return{
+				latitude: null,  //  纬度
+				longitude: null,  //  经度
+				markers: [],  //  所有网点标注点
+				distanceMark: [],  //  按距离计算远近后的网点标注点
+				polyline: null,  //  路线
+			}
+		},
+		onLoad() {
+			// 实例化API核心类
+			qqmapsdk = new QQMapWX({
+				key: 'FRCBZ-IDZWW-FGDRR-O3SQM-ZW5C2-LRBDM'
+			})
+		},
+		onShow() {
+			this.getLocation()
+		},
+		methods: {
+			//  获取当前位置
+			getLocation(){
+				const _this = this
+				uni.getLocation({
+				    type: 'gcj02',
+				    success: function (res) {
+						_this.latitude = res.latitude  //  纬度
+						_this.longitude = res.longitude  //  经度
+						_this.getCleanWay()  //  获取个人待清运清单
+				    }
+				})
+			},
+			// 标注点信息
+			getCleanWay(){
+				getCleanWay({ lng: this.longitude, lat: this.latitude }).then(res => {
+					if(res.status == 200){
+						this.markers = []
+						res.data.map((item, index) => {
+							if(item.lat && item.lng){  //  经纬度为空的错误数据,网点信息不在地图上显示
+								this.markers.push({
+									id: index+1,
+									latitude: item.lat,
+									longitude: item.lng,
+									width: '60rpx',
+									height: '60rpx',
+									iconPath: '/static/store.png',
+									label: {
+										content: item.stationName || '--',
+										bgColor: '#fff',
+									}
+								})
+							}
+						})
+						if(this.markers.length>0){
+							this.onCalculateDistance()  //  计算距离
+						}
+					}
+				})
+			},
+			//  将所有标注点与当前位置进行距离计算
+			onCalculateDistance(){
+				const _this = this
+				const startPos = { latitude: _this.latitude, longitude: _this.longitude }
+				let destPos = []
+				_this.markers.map(item => {
+					destPos.push({ latitude: item.latitude, longitude: item.longitude })
+				})
+				//调用距离计算接口
+				qqmapsdk.calculateDistance({
+					mode: 'driving', //可选值:'driving'(驾车)、'walking'(步行),不填默认:'walking',可不填
+					//from参数不填默认当前地址
+					//获取表单提交的经纬度并设置from和to参数(示例为string格式)
+					from: startPos, //若起点有数据则采用起点坐标,若为空默认当前地址
+					to: destPos, //终点坐标
+					success: function(res) {//成功后的回调
+					  var res = res.result
+					  _this.distanceMark = []
+					  for (var i = 0; i < res.elements.length; i++) {
+						//  将距离值加入标注点信息中
+						_this.distanceMark.push({
+							latitude: res.elements[i].to.lat,
+							longitude: res.elements[i].to.lng,
+							distance: res.elements[i].distance
+						})
+					  }
+					  //  数组升序排序
+					  _this.distanceMark.sort(_this.compare( 'distance', true ))
+					  _this.onDirection()  //  路线规划
+					},
+					fail: function(error) {
+					  console.error(error)
+					},
+					complete: function(res) {
+					  // console.log(res)
+					}
+				})
+			},
+			//  数组排序
+			compare(property, desc){
+				return function (a, b) {
+					var value1 = a[property]
+					var value2 = b[property]
+					if(desc==true){  // 升序排列
+						return value1 - value2
+					}else{  // 降序排列
+						return value2 - value1
+					}
+				}
+			},
+			//  路线规划
+			onDirection(){
+				const _this = this
+				_this.polyline = []
+				//  将所有标注点都按距离进行路线规划
+				var position = null
+				position = [
+					{ latitude: _this.latitude, longitude: _this.longitude },
+					{ latitude: _this.distanceMark[0].latitude, longitude: _this.distanceMark[0].longitude }
+				]
+				_this.getDirection(position, 0)
+			},
+			//  路线规划
+			getDirection(position, ind){
+				const _this = this
+				qqmapsdk.direction({
+					mode: 'driving',//可选值:'driving'(驾车)、'walking'(步行)、'bicycling'(骑行),不填默认:'driving',可不填
+					//from参数不填默认当前地址
+					from: {
+						latitude: position[0].latitude,
+						longitude: position[0].longitude
+					},
+					to: {
+						latitude: position[1].latitude,
+						longitude: position[1].longitude
+					}, 
+					policy: 'LEAST_TIME,NAV_POINT_FIRST',
+					success: function (res) {
+						var ret = res
+						var coors = ret.result.routes[0].polyline, pl = []
+						//坐标解压(返回的点串坐标,通过前向差分进行压缩)
+						var kr = 1000000
+						for (var i = 2; i < coors.length; i++) {
+						  coors[i] = Number(coors[i - 2]) + Number(coors[i]) / kr;
+						}
+						//将解压后的坐标放入点串数组pl中
+						for (var i = 0; i < coors.length; i += 2) {
+						  pl.push({ latitude: coors[i], longitude: coors[i + 1] })
+						}
+						//设置polyline属性,将路线显示出来,将解压坐标第一个数据作为起点
+						_this.polyline.push({
+							points: pl,
+							arrowLine: true,
+							width: 8,
+							color: '#07c160'
+						})
+					},
+					fail: function (error) {
+						console.error(error)
+					},
+					complete: function (res) {
+						// 腾讯地图使用限制
+						// 为了保证我们的服务稳定,我们对每个key的每个服务接口的调用量做了如下限制:
+						// 日调用量:1万次 / Key
+						// 并发数:5次 / key / 秒
+						
+						//  递归调用避免并发限制
+						if(ind < _this.distanceMark.length-1){
+							let pos = [
+								{ latitude: _this.distanceMark[ind].latitude, longitude: _this.distanceMark[ind].longitude },
+								{ latitude: _this.distanceMark[ind+1].latitude, longitude: _this.distanceMark[ind+1].longitude }
+							]
+							let subInd = ind
+							subInd++
+							setTimeout(()=>{
+								_this.getDirection(pos, subInd)
+							},300)
+						}
+					}
+				})
+			},
+			//  点击标注点,调用第三方地图查看规划路线
+			markertap(e){
+				this.markers.map(item => {
+					if(item.id == e.detail.markerId){
+						uni.openLocation({
+							latitude: item.latitude,
+							longitude: item.longitude,
+							success: function () {
+								
+							}
+						})
+					}
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.map-container {
+		width: 100%;
+		height: 100vh;
+	}
+</style>

+ 229 - 0
pages/login/forget-pass.vue

@@ -0,0 +1,229 @@
+<template>
+	<view class="forget-wrap">
+		<form class="login-form" @submit="formSubmit">
+			<view v-show="state == 0">
+				<view class="form-item">
+					<input v-model="form.phone" class="item-inp" name="phone" type="number" maxlength="11" placeholder="请输入登录手机号" />
+				</view>
+				<view class="form-item">
+					<input v-model="form.verifyCode" class="item-inp" name="verifyCode" type="number" maxlength="6" placeholder="请输入短信验证码" />
+					<button class="getcode-btn" :disabled="isDisable" @click="getCodeValidate">{{nowVal}}</button>
+				</view>
+				<view class="form-btn-con">
+					<button class="form-btn" @click="goStep">下一步</button>
+				</view>
+			</view>
+			<view v-show="state == 1">
+				<view class="form-item">
+					<input v-model="form.password" class="item-inp" name="password" password type="text" maxlength="12" placeholder="请输入新密码" />
+				</view>
+				<view class="form-item">
+					<input v-model="form.passwords" class="item-inp" name="passwords" password type="text" maxlength="12" placeholder="请再次输入新密码" />
+				</view>
+				<view class="form-btn-con">
+					<button class="form-btn" form-type="submit">提交</button>
+				</view>
+			</view>
+		</form>
+		<!-- 图文验证码 -->
+		<uni-popup ref="imageTxtPopup" type="center">
+			<popup-con type="forgetImageTxt" title="图文验证码" :popBtn="popBtn" :changeImg="changeImg" @captchaImg="captchaImg"></popup-con>
+		</uni-popup>
+	</view>
+</template>
+
+<script>
+	import { isvalidPhone } from '@/libs/validate.js'
+	import uniPopup from '@/components/uni-popup/uni-popup.vue'
+	import popupCon from '@/components/uni-popup/popup-con.vue'
+	import { memberVerifyCode, memberChangePwd, memberValidateVerifyCode, memberGetByMobile } from '@/api/user.js'
+	import { clzConfirm } from '@/libs/tools.js'
+	export default{
+		components: {
+			uniPopup,
+			popupCon
+		},
+		data(){
+			return{
+				state: 0,  //  忘记密码当前状态
+				form: {
+					phone: '',
+					verifyCode: '',
+					password: '',
+					passwords: ''
+				},
+				nowVal: '获取验证码',  //  按钮显示内容
+				count: '',  //  当前秒数
+				timer: null,  //  倒计时
+				isDisable: false,  //  是否禁止获取验证码
+				popBtn: [],  //  name为操作按钮名称,color为操作按钮颜色值
+				changeImg: false,  //  是否重新更换图形验证码
+				randomCode: '',  //  图片验证码随机码
+			}
+		},
+		onLoad(opts) {
+			if(opts.username){
+				this.form.phone = opts.username
+			}
+		},
+		methods: {
+			//  下一步
+			goStep(){
+				const _this = this
+				//  表单校验
+				if(this.form.phone == ''){
+					uni.showToast({icon: 'none',title: '请输入登录手机号'})
+					return
+				}
+				if(!isvalidPhone(this.form.phone)){
+				  uni.showToast({icon: 'none',title: '请输入正确的手机号码'})
+				  return
+				}
+				if(this.form.verifyCode == ''){
+					uni.showToast({icon: 'none',title: '请输入验证码'})
+					return
+				}
+				//  校验短信验证码是否正确
+				const obj = {}
+				obj.phone = _this.form.phone,
+				obj.random = _this.randomCode,  // 当前随机码
+				obj.verifyCode = _this.form.verifyCode
+				memberValidateVerifyCode(obj).then(res => {
+				  if(res.status == 200){
+				    _this.state = 1
+				  }else{
+					  uni.showToast({icon: 'none',title: res.message})
+				  }
+				})
+			},
+			//  表单提交
+			formSubmit(){
+				const _this = this
+				if(this.form.password == ''){
+					uni.showToast({icon: 'none',title: '请输入新密码'})
+					return
+				}
+				if(this.form.password.length < 6 || this.form.password.length > 12){
+					uni.showToast({icon: 'none',title: '请输入6-12位新密码'})
+					return
+				}
+				if(this.form.passwords == ''){
+					uni.showToast({icon: 'none',title: '请再次输入新密码'})
+					return
+				}
+				if(this.form.password != this.form.passwords){
+					uni.showToast({icon: 'none',title: '两次密码输入不一致'})
+					return
+				}
+				const obj = {}
+				obj.phone = _this.form.phone,
+				obj.random = _this.randomCode,  // 当前随机码
+				obj.verifyCode = _this.form.verifyCode,
+				obj.password = _this.form.password
+				memberChangePwd(obj).then(res => {
+					if(res.status == 200){
+						//  将修改后的账号密码  重新存储
+						_this.$u.vuex('vuex_user.account', _this.form.phone)
+						_this.$u.vuex('vuex_user.password', '')
+						clzConfirm({
+						    title: '提示',
+						    content: '修改成功',
+							confirmText: '去登录',
+							showCancel: false,
+							success: function (ret) {
+						        if (ret.confirm||ret.index==0) {
+									uni.reLaunch({
+										url: '/pages/login/login'
+									})
+						        }
+						    }
+						})
+					}
+				})
+			},
+			//  获取验证码
+			getCodeValidate(){
+				if(this.form.phone){
+					if(!isvalidPhone(this.form.phone)){
+						uni.showToast({icon: 'none',title: '请输入正确的手机号码'})
+						return
+					}else{
+						//  校验手机号是否注册过
+						memberGetByMobile({phone: this.form.phone}).then(res => {
+							if(res.status == 200){
+								//  图文验证码
+								this.$refs.imageTxtPopup.open()
+							}else{
+								uni.showToast({icon: 'none',title: res.message})
+							}
+						})
+					}
+				}else{
+					uni.showToast({icon: 'none',title: '请先输入手机号'})
+				}
+			},
+			//  开始倒计时
+			getCodeFun(){
+				const TIME_COUNT = 60
+				if (!this.timer) {
+				  this.count = TIME_COUNT
+				  this.timer = setInterval(() => {
+				    if (this.count > 0 && this.count <= TIME_COUNT) {
+				      this.count--
+				      this.nowVal = this.count + 's后重发'
+				      this.isDisable = true
+				    } else {
+				      this.nowVal = '重新获取验证码'
+				      clearInterval(this.timer)
+				      this.timer = null
+				      this.isDisable = false
+				    }
+				  }, 1000)
+				}
+			},
+			//  图文验证码
+			captchaImg(code, nowRandomCode){
+				this.captchaVerify(code, nowRandomCode)
+			},
+			//  验证图片验证码
+			captchaVerify(code, nowRandomCode){
+				const _this = this
+				let obj = {}
+				obj.phone = this.form.phone
+				obj.random = nowRandomCode
+				obj.captcha = code
+				//  短信验证码
+				memberVerifyCode(obj).then(res => {
+					console.log(JSON.stringify(res))
+					if(res.status == 200){  //  验证码输入正确
+						_this.randomCode = nowRandomCode  //  图片验证码随机码
+						//  关闭   图形验证码 弹框
+						_this.$refs.imageTxtPopup.close()
+						//  开启倒计时
+						this.getCodeFun()
+						uni.showToast({icon: 'none',title: '验证码发送成功'})
+					}else {  //  验证码输入错误
+						_this.randomCode = ''
+						//  切换验证码重新校验
+						_this.changeImg = false
+						_this.$nextTick(function(){
+							_this.changeImg = true
+						})
+						uni.showToast({icon: 'none',title: res.message})
+					}
+				})
+			},
+		}
+	}
+</script>
+<style scoped lang="scss">
+	@import './login.scss';
+	.forget-wrap .login-form{
+		padding-top: 300upx;
+	}
+	.getcode-btn {
+		background-color: #298bf2 !important;
+		color: #fff !important;
+		border: none !important;
+	}
+</style>

+ 74 - 0
pages/login/login.scss

@@ -0,0 +1,74 @@
+.pw-login-wrap, .forget-wrap, .apply-wrap{
+	background-color: #FFFFFF;
+	width: 100%;
+	height: 100vh;
+	box-sizing: border-box;
+	.logo{
+		display: flex;
+		justify-content: center;
+		padding: 100upx 0;
+	}
+	.login-form{
+		display: block;
+		width: 80%;
+		margin: 0 auto;
+		.form-item{
+			margin-bottom: 20upx;
+			position: relative;
+			display: flex;
+			align-items: center;
+			border: 1upx solid #dcdee2;
+			border-radius: 15upx;
+			.require-tip{
+				position: absolute;
+				left: 0;
+				top: 26upx;
+				color: red;
+			}
+			.item-inp{
+				flex-grow: 1;
+			}
+			.item-inp, .item-picker{
+				font-size: 30upx;
+				padding: 14upx 20upx;
+			}
+			.getcode-btn{
+				position: absolute;
+				right: 0upx;
+				top: 0;
+				font-size: 24upx;
+				background: #999;
+				color: #FFFFFF;
+				border: 0;
+				border-top-left-radius: 0;
+				border-bottom-left-radius: 0;
+				line-height: 3;
+				z-index: 10;
+			}
+		}
+		.flex-box{
+			display: flex;
+			justify-content: space-between;
+			font-size: 26upx;
+		}
+		.form-btn-con{
+			margin-top: 60upx;
+			.form-btn{
+				font-size: 32upx;
+				display: block;
+				line-height: 75upx;
+				margin: 0 auto;
+				background-color: #07c160;
+				color: #fff;
+			}
+			uni-button.form-btn:after{
+				border: none;
+			}
+			.apply-btn{
+				display: block;
+				text-align: center;
+				margin-top: 50upx;
+			}
+		}
+	}
+}

+ 178 - 0
pages/login/login.vue

@@ -0,0 +1,178 @@
+<template>
+	<view class="login-content">
+		<view>
+			<view>
+				<view class="logo">
+					<u-image src="/static/login_icon_logo" width="160" height="160" ></u-image>
+				</view>
+				<view class="login-btns">
+					<u-button shape="circle" hover-class="none" :custom-style="wxButton" class="login-btn" type="success" :hair-line="false" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">
+						微信授权登录
+					</u-button>
+					<u-gap height="30"></u-gap>
+					<u-button shape="circle" hover-class="none" :custom-style="phoneButton" class="login-btn" @click="pwLogin" type="primary">
+						账号密码登录
+					</u-button>
+				</view>
+			</view>
+		</view>
+		<view @click="toYs">登录即代表同意<text>隐私政策</text>和<text>服务条款</text></view>
+	</view>
+</template>
+
+<script>
+	import { login } from "@/api/login"
+	export default {
+		components: {},
+		data() {
+			return {
+				path: '/pages/index/index',
+				lanuch: true,
+				code: '',
+				wxButton: {
+					background: '#07c160'
+				},
+				phoneButton: {
+					background: '#00aaff'
+				}
+			}
+		},
+		mounted() {},
+		onLoad(option) {
+			//  隐藏小房子
+			uni.hideHomeButton()
+			// 为解决首次登录异常问题 进入页面先调微信登录获取code
+			this.wxLogin()
+			const {
+				path,
+				lanuch
+			} = option;
+			this.lanuch = (lanuch + '') === 'true';
+			if (path) {
+				this.path = decodeURIComponent(path);
+			}
+		},
+		methods: {
+			cansel(){
+				this.$store.state.vuex_noLogin = true
+				uni.reLaunch({
+					url: '/pages/index/index'
+				})
+			},
+			toYs(){
+				uni.navigateTo({
+					url: '/pages/agreement/agreement'
+				})
+			},
+			getPhoneNumber(e) {
+				let _this = this
+				uni.showLoading({
+					mask: true,
+					title: '加载中'
+				});
+				if (!this.code) {
+					this.wxLogin()
+				} 
+				if (e.target.errMsg === 'getPhoneNumber:ok') {
+					setTimeout(()=>{
+						login({
+							code: _this.code,
+							encryptedData: e.target.encryptedData,
+							iv: e.target.iv
+						}).then(res => {
+							uni.hideLoading();
+							_this.code = ''
+							if (res.status == 200) {
+								getApp().globalData.token = res.data
+								_this.$u.vuex('vuex_token',res.data)
+								uni.$emit("getUserInfo")
+								if (_this.path === '/pages/index/index' || _this.lanuch) {
+									uni.reLaunch({
+										url: _this.path
+									})
+								} else {
+									if (_this.path === '/pages/cleared/index' || _this.path === '/pages/userCenter/index') {  //  tabbar页面
+										uni.switchTab({
+											url: _this.path
+										})
+									} else {
+										uni.redirectTo({
+											url: _this.path
+										})
+									}
+								}
+							} else {
+								uni.showToast({
+									title: res.message,
+									icon: 'none',
+									duration: 2500
+								});
+							}
+						});
+					},300)
+				} else {
+					uni.showToast({
+						title: '授权失败',
+						icon: 'none',
+						duration: 2500
+					});
+				}
+			},
+			// 调微信登录 获取code
+			wxLogin () {
+				let _this = this
+				uni.login({
+					provider: 'weixin',
+					success(res) {
+						_this.code = res.code
+					}
+				})
+			},
+			// 手机号登录
+			pwLogin () {
+			  wx.navigateTo({
+			    url: '/pages/login/pwLogin'
+			  })
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.login-content {
+		width: 100%;
+		height: 100vh;
+		padding: 40upx;
+		display: flex;
+		flex-direction: column;
+		background-color: #fff;
+		> view{
+			text-align: center;
+			&:first-child{
+				flex-grow: 1;
+				height: 80vh;
+				padding: 20% 10%;
+				display: flex;
+				flex-direction: column;
+				justify-content: space-between;
+			}
+			&:last-child{
+				font-size: 24upx;
+				text{
+					color: #07c160;
+				}
+			}
+			.logo{
+				text-align: center;
+				display: flex;
+				justify-content: center;
+			}
+			.login-btns{
+				padding: 60upx 0;
+				.login-btn{
+					margin: 30upx 0;
+				}
+			}
+		}
+	}
+</style>

+ 147 - 0
pages/login/pwLogin.vue

@@ -0,0 +1,147 @@
+<template>
+	<view class="pw-login-wrap">
+		<!-- <view v-if="!buildType" style="text-align: center;color: #999999;padding-top: 40px;">{{ envTips }}</view> -->
+		<view class="logo">
+			<u-image src="/static/logo.jpg" width="140" height="140" ></u-image>
+		</view>
+		<form class="login-form" @submit="formSubmit">
+			<view class="form-item">
+				<input v-model="form.loginName" class="item-inp" name="loginName" type="text" maxlength="30" placeholder="请输入用户名" />
+			</view>
+			<view class="form-item">
+				<input v-model="form.password" class="item-inp" name="password" password type="text" maxlength="12" placeholder="请输入密码" />
+			</view>
+			<view class="flex-box" style="margin-top: 60upx;">
+				<view class="remember-pass">
+					<u-checkbox v-model="isRemember" value="true" :size="30" :label-size="26" active-color="#07c160" class="login-form-checkbox" @change="rememberChange">记住密码</u-checkbox>
+				</view>
+			</view>
+			<view class="form-btn-con">
+				<button class="form-btn" form-type="submit">登录</button>
+			</view>
+		</form>
+	</view>
+</template>
+
+<script>
+import { checkVersionToLoadUpdate, setStorageForAppVersion,clzConfirm } from '@/libs/tools'
+import { isvalidPhone } from '@/libs/validate.js';
+import { loginPhone } from '@/api/user.js';
+import { getSysVersion } from '@/api/data.js'
+export default {
+	data() {
+		return {
+			form: {
+				loginName: this.$store.state.vuex_user.account,
+				password: this.$store.state.vuex_user.password
+			},
+			isRemember: true, //  是否记住密码
+			envTips: '',
+			buildType: '',
+		};
+	},
+	mounted() {
+		this.isRemember = this.$store.state.vuex_isRemember || true;
+		this.envTips = getApp().globalData.envTips;
+		this.buildType = getApp().globalData.buildType;
+	},
+	onShow() {
+	},
+	methods: {
+		//  获取微信login  code
+		getWechatCode(){
+			const _this = this
+			wx.login({
+			  success (res) {
+			    if (res.code) {
+					//发起网络请求
+					let formData = JSON.parse(JSON.stringify(_this.form))
+					formData.code = res.code
+					_this.submitForm(formData)
+			    } else {
+					console.log('登录失败,点击“登录”重试!' + res.errMsg)
+			    }
+			  }
+			})
+		},
+		//  表单提交
+		formSubmit() {
+			const _this = this;
+			//  表单校验
+			if (_this.form.loginName == '') {
+				uni.showToast({ icon: 'none', title: '请输入用户名' });
+				return;
+			}
+			if (_this.form.password == '') {
+				uni.showToast({ icon: 'none', title: '请输入密码' });
+				return;
+			}
+			if (_this.form.password.length < 6 || _this.form.password.length > 12) {
+				uni.showToast({ icon: 'none', title: '请输入6-12位密码' });
+				return;
+			}
+			uni.showLoading({
+				title: '正在登录...'
+			});
+			// #ifdef MP-WEIXIN
+				//  获取微信login   code
+				this.getWechatCode()
+			// #endif
+			// #ifndef MP-WEIXIN
+				this.submitForm(_this.form)
+			// #endif
+		},
+		submitForm(formData){
+			const _this = this;
+			//  登录
+			loginPhone(formData).then(res => {
+				uni.hideLoading();
+				if (res.status == 200) {
+					_this.$u.vuex('vuex_token', res.data);
+					getApp().globalData.token = res.data;
+					//登录成功将用户名密码存储到用户本地
+					if (_this.isRemember) {
+						//用户勾选“记住密码”
+						_this.$u.vuex('vuex_user.account', _this.form.loginName);
+						_this.$u.vuex('vuex_user.password', _this.form.password);
+					} else {
+						//用户没有勾选“记住密码”
+						_this.$u.vuex('vuex_user.account', '');
+						_this.$u.vuex('vuex_user.password', '');
+						_this.form.loginName = '';
+						_this.form.password = '';
+					}
+					uni.setStorageSync('loginTimeOut', 'NO');
+					_this.toMain();
+				} else {
+					uni.showToast({ icon: 'none', title: res.message });
+				}
+			});
+		},
+		toMain() {
+			// 跳转到首页
+			uni.switchTab({
+				url: '/pages/index/index'
+			});
+		},
+		//  忘记密码
+		forgetPass() {
+			uni.navigateTo({
+				url: '/pages/login/forget-pass?username=' + this.form.loginName
+			});
+		},
+		//  判断是否记住密码
+		rememberChange(e) {
+			this.isRemember = e.value;
+		},
+		toYsPage() {
+			uni.navigateTo({
+				url: '/pages/agreement/agreement'
+			});
+		}
+	}
+};
+</script>
+<style scoped lang="scss">
+@import './login.scss';
+</style>

+ 66 - 0
pages/login/userAuthYs.vue

@@ -0,0 +1,66 @@
+<template>
+	<view class="article">
+		<view>章鱼车管家尊重并保护所有使用服务用户的个人隐私权。为了给您提供更准确、更有个性化的服务,本应用会按照本隐私权政策的规定使用和披露您的个人信息。但本应用将以高度的勤勉、审慎义务对待这些信息。除本隐私权政策另有规定外,在未征得您事先许可的情况下,本应用不会将这些信息对外披露或向第三方提供。</view>
+		<view>本应用会不时更新本隐私权政策。 您在同意本应用服务使用协议之时,即视为您已经同意本隐私权政策全部内容。本隐私权政策属于本应用服务使用协议不可分割的一部分。</view>
+		<view>
+			<p>适用范围</p>
+			<p>(a) 在您注册本应用帐号时,您根据本应用要求提供的个人注册信息;</p>
+			<p>(b) 在您使用本应用网络服务,或访问本应用平台网页时,本应用自动接收并记录的您的浏览器和计算机上的信息,包括但不限于您的IP地址、浏览器的类型、使用的语言、访问日期和时间、软硬件特征信息及您需求的网页记录等数据;</p>
+			<p>(c) 本应用通过合法途径从商业伙伴处取得的用户个人数据。您了解并同意,以下信息不适用本隐私权政策:(a) 您在使用本应用平台提供的搜索服务时输入的关键字信息;</p>
+			<p>(b) 本应用收集到的您在本应用发布的有关信息数据,包括但不限于参与活动、成交信息及评价详情;</p>
+			<p>(c) 违反法律规定或违反本应用规则行为及本应用已对您采取的措施。</p>
+		</view>
+		<view>
+			<p>信息使用</p>
+			<p>(a) 本应用不会向任何无关第三方提供、出售、出租、分享或交易您的个人信息,除非事先得到您的许可,或该第三方和本应用(含本应用关联公司)单独或共同为您提供服务,且在该服务结束后,其将被禁止访问包括其以前能够访问的所有这些资料。</p>
+			<p>(b) 本应用亦不允许任何第三方以任何手段收集、编辑、出售或者无偿传播您的个人信息。任何本应用平台用户如从事上述活动,一经发现,本应用有权立即终止与该用户的服务协议。</p>
+			<p>(c) 为服务用户的目的,本应用可能通过使用您的个人信息,向您提供您感兴趣的信息,包括但不限于向您发出产品和服务信息,或者与本应用合作伙伴共享信息以便他们向您发送有关其产品和服务的信息(后者需要您的事先同意)。</p>
+		</view>
+		<view>
+			<p>信息披露在如下情况下,本应用将依据您的个人意愿或法律的规定全部或部分的披露您的个人信息:</p>
+			<p>(a) 经您事先同意,向第三方披露;</p>
+			<p>(b) 为提供您所要求的产品和服务,而必须和第三方分享您的个人信息;</p>
+			<p>(c) 根据法律的有关规定,或者行政或司法机构的要求,向第三方或者行政、司法机构披露;</p>
+			<p>(d) 如您出现违反中国有关法律、法规或者本应用服务协议或相关规则的情况,需要向第三方披露;</p>
+			<p>(e) 如您是适格的知识产权投诉人并已提起投诉,应被投诉人要求,向被投诉人披露,以便双方处理可能的权利纠纷;</p>
+			<p>(f) 在本应用平台上创建的某一交易中,如交易任何一方履行或部分履行了交易义务并提出信息披露请求的,本应用有权决定向该用户提供其交易对方的联络方式等必要信息,以促成交易的完成或纠纷的解决。</p>
+			<p>(g) 其它本应用根据法律、法规或者网站政策认为合适的披露。</p>
+		</view>
+		<view><p>信息存储和交换本应用收集的有关您的信息和资料将保存在本应用及(或)其关联公司的服务器上,这些信息和资料可能传送至您所在国家、地区或本应用收集信息和资料所在地的境外并在境外被访问、存储和展示。</p></view>
+		<view>
+			<p>Cookie的使用</p>
+			<p>(a) 在您未拒绝接受cookies的情况下,本应用会在您的计算机上设定或取用cookies ,以便您能登录或使用依赖于cookies的本应用平台服务或功能。本应用使用cookies可为您提供更加周到的个性化服务,包括推广服务。</p>
+			<p>(b) 您有权选择接受或拒绝接受cookies。您可以通过修改浏览器设置的方式拒绝接受cookies。但如果您选择拒绝接受cookies,则您可能无法登录或使用依赖于cookies的本应用网络服务或功能。</p>
+			<p>(c) 通过本应用所设cookies所取得的有关信息,将适用本政策。</p>
+		</view>
+		<view>
+			<p>信息安全</p>
+			<p>(a) 本应用帐号均有安全保护功能,请妥善保管您的用户名及密码信息。本应用将通过对用户密码进行加密等安全措施确保您的信息不丢失,不被滥用和变造。尽管有前述安全措施,但同时也请您注意在信息网络上不存在“完善的安全措施”。</p>
+			<p>(b) 在使用本软件网络服务进行网上交易时,您不可避免的要向交易对方或潜在的交易对方披露自己的个人信息,如联络方式或者邮政地址。请您妥善保护自己的个人信息,仅在必要的情形下向他人提供。如您发现自己的个人信息泄密,请您立即联络本软件客服,以便本软件采取相应措施。</p>
+		</view>
+		<view>
+			<p>本隐私政策的更改</p>
+			<p>(a) 如果决定更改隐私政策,我们会在本政策中、本公司网站中以及我们认为适当的位置发布这些更改,以便您了解我们如何收集、使用您的个人信息,哪些人可以访问这些信息,以及在什么情况下我们会透露这些信息。</p>
+			<p>(b) 本公司保留随时修改本政策的权利,因此请经常查看。如对本政策作出重大更改,本公司会通过网站通知的形式告知。</p>
+		</view>
+    </view>
+</template>
+
+<script>
+</script>
+
+<style lang="scss">
+	.article{
+		 padding: 35upx 40upx;
+		 line-height: 46upx;
+		 >view{
+			 margin: 30upx 0;
+			 p{
+				 margin: 20upx 0;
+				 &:first-child{
+					 font-weight: bold;
+				 }
+			 }
+		 }
+	}
+</style>

+ 190 - 0
pages/userCenter/changePwd.vue

@@ -0,0 +1,190 @@
+<template>
+	<view class="changePwd-container">
+		<view class="content">
+			<view class="tishi">请先输入原密码,按步骤操作</view>
+			<view class="input-group">
+				<view class="input-row border">
+					<text class="title">原密码:</text>
+					<m-input class="m-input" :maxlength="30"  type="password"  displayable v-model="formCustom.oldPwd" placeholder="请输入原密码"></m-input>
+				</view>
+				<view class="input-row">
+					<text class="title">新密码:</text>
+					<m-input class="m-input" :maxlength="12" type="password" displayable v-model="formCustom.passwd" placeholder="请输入6-12位新密码"></m-input>
+				</view>
+				<view class="input-row">
+					<text class="title">再次输入:</text>
+					<m-input class="m-input" :maxlength="12" type="password" displayable v-model="formCustom.passwdCheck" placeholder="请输入6-12位新密码"></m-input>
+				</view>
+			</view>
+		</view>
+		<!-- 消息提醒弹窗 -->
+		<view class="form-footer-btn">
+			<u-button size="medium" hover-class="none" @click="handleReset">重置</u-button>
+			<u-button size="medium" hover-class="none" :loading="loading" :custom-style="customBtnStyle" @click="handleSubmit">保存</u-button>
+		</view>
+	</view>
+</template>
+
+<script>
+	import mInput from '../../components/m-input.vue'
+	import { changePwd, logout } from '@/api/user.js'
+	export default{
+		name:'changePwd',
+		components: {
+			mInput
+		},
+		data(){
+			return{
+				formCustom: {
+				  passwd: '',
+				  passwdCheck: '',
+				  oldPwd: ''
+				},
+				loading: false,
+				customBtnStyle: {  //  自定义按钮样式
+					borderColor: '#07c160',
+					backgroundColor: '#07c160',
+					color: '#fff'
+				},
+			}
+		},
+		methods:{
+			messageInfo(info){
+				uni.showToast({
+					icon:'none',
+					title: info
+				})
+			},
+			handleSubmit(){
+				let _this = this
+				//非空判断密码长度判断
+				if (this.formCustom.oldPwd === '') {
+				   this.messageInfo("请输入原密码")
+				   return 
+				}  
+				if (this.formCustom.passwd === '') {
+				   this.messageInfo("请输入新密码")
+				   return 
+				}
+				if (this.formCustom.passwd.length < 6) {
+				   this.messageInfo("新密码最少6位")
+				   return 
+				}
+				if (this.formCustom.passwdCheck === '') {
+				   this.messageInfo("请再次输入新密码")
+				   return 
+				}
+				if (this.formCustom.passwdCheck.length < 6) {
+				   this.messageInfo("再次输入新密码最少6位")
+				   return 
+				}
+				if (this.formCustom.passwdCheck !== this.formCustom.passwd) {
+				   this.messageInfo("再次输入的密码和新密码不一样")
+				   return 
+				}
+				// 保存
+				this.loading = true
+				changePwd({
+				  oldPassword: this.formCustom.oldPwd,
+				  password: this.formCustom.passwd
+				}).then(res => {
+				  if (res.status == '200') {
+				    this.messageInfo('修改成功, 请重新登录')
+				    setTimeout(function(){
+						_this.logout()
+					},800)
+				  } else {
+				    this.messageInfo(res.message)
+					this.loading = false
+				  }
+				})
+			},
+			logout(){
+				logout().then(res => {
+					console.log(res)
+					this.messageInfo(res.message)
+					if(res.status == 200){
+						// this.$store.commit("$closeWebsocket")
+						this.$store.state.vuex_token = ''
+						this.$store.state.vuex_userData = ''
+						uni.setStorageSync('setStatusIndexFunc', 0)
+						uni.reLaunch({
+							url: "/pages/login/login"
+						})
+					}
+					this.loading = false
+				})
+			},
+			handleReset (name) {
+				this.formCustom = {
+				  passwd: '',
+				  passwdCheck: '',
+				  oldPwd: ''
+				}
+			}
+		}
+	}
+	
+</script>
+
+<style lang="less">
+	page{
+		background: #FFFFFF;
+	}
+	.changePwd-container{
+		width: 100%;
+		font-size: 28rpx;
+		padding: 20rpx 40rpx ;
+		.content{
+			.tishi{
+				text-align: center;
+				line-height: 130rpx;
+				font-size: 30rpx;
+				color: #999;
+			}
+			.input-group{
+				margin-top:20rpx;
+			}
+			.input-row{
+				padding: 10rpx 20rpx;
+				background-color: #F8F8F8;
+				margin-bottom: 20rpx;
+				border-radius: 10rpx;
+				line-height: 32px;
+				display: flex;
+				align-items: center;
+				.title{
+					width:140rpx;
+					display: inline-block;
+					text-align: left;
+					color:#808080;
+				}
+			}
+			.uni-input-placeholder{
+				font-size: 26rpx;
+				color:#989898;
+			}
+		}
+		.u-size-default[data-v-1f520a08]{
+			height: 92rpx;
+		}
+		.m-input-input[data-v-5a85b703]{
+			position: relative;
+			bottom: 4rpx;
+		}
+		.m-input-icon[data-v-5a85b703]{
+			position: relative;
+			bottom: 10rpx;
+		}
+		.form-footer-btn{
+			margin: 140upx 50upx 0;
+			display: flex;
+			justify-content: space-between;
+		}
+		.form-footer-btn uni-button{
+			width: 50%;
+			margin: 0 50upx;
+			font-size: 30upx;
+		}
+	}
+</style>

+ 145 - 0
pages/userCenter/index.vue

@@ -0,0 +1,145 @@
+<template>
+	<view class="user-content">
+		<!-- 头部 -->
+		<view class="user-head">
+			<view class="user-photo">
+				<open-data type="userAvatarUrl" class="avatar"></open-data>
+			</view>
+			<view class="user-info">
+				<text class="user-name">{{userInfoData.name || ''}}</text>
+				<text class="user-phone">{{userInfoData.phone || ''}}</text>
+			</view>
+		</view>
+		<!-- 列表 -->
+		<view class="user-list">
+			<u-cell-group>
+				<u-cell-item icon="file-text" icon-size="40" :icon-style="{color:'#ffaa00'}" index="0" @click="toPage" title="服务协议及隐私政策"></u-cell-item>
+				<u-cell-item icon="lock" icon-size="38" :icon-style="{color:'#00aaff'}" index="1" @click="toPage" title="修改密码"></u-cell-item>
+			</u-cell-group>
+		</view>
+		<!-- 退出 -->
+		<view class="user-btn">
+			<u-button type="success" hover-class="none" :custom-style="quitButton" @click="quitSys" shape="circle">退出登录</u-button>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {logout} from '@/api/login.js'
+	import { getUserInfo } from '@/api/user.js'
+	export default {
+		data() {
+			return {
+				quitButton: {
+					borderRadius:'100rpx',
+					fontSize:'30rpx',
+					background: '#01c9b2'
+				},
+				userInfoData: null,  //  用户信息
+				userAvatarUrl: ''  //  用户头像
+			};
+		},
+		onShow() {
+			this.getUserInfo()
+		},
+		onLoad() {
+		},
+		methods:{
+			//  获取用户信息
+			getUserInfo(){
+				getUserInfo().then(res => {
+					if(res.status == 200){
+						this.userInfoData = res.data
+					}else{
+						this.userInfoData = null
+					}
+				})
+			},
+			// 打开对应的页面
+			toPage(index){
+				let pageUrl=[
+					'/pages/agreement/agreement?fromPage=usercenter',
+					'/pages/userCenter/changePwd'
+					]
+				uni.navigateTo({
+					url: pageUrl[index]
+				})
+			},
+			//  跳转
+			toUserPage(){
+				//  未登录跳转登录,已登录跳转用户信息页
+				uni.navigateTo({
+					url: '/pages/userCenter/userInfo/userInfo'
+				})
+			},
+			//  乐豆明细
+			toLdPage(){
+				uni.navigateTo({
+					url: '/pages/userCenter/ldDetailed'
+				})
+			},
+			// 退出登录
+			quitSys(){
+				let _this = this
+				uni.showModal({
+				  title: '提示',
+				  content: '您确定要退出登录吗?',
+				  success(res) {
+				    if (res.confirm) {
+				      logout({}).then(res => {
+				       getApp().globalData.token = ''
+				       _this.$u.vuex('vuex_token','')
+				        uni.reLaunch({
+				        	url: '/pages/login/login'
+				        })
+				      })
+				    }
+				  }
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.user-content{
+		width: 100%;
+		.user-head{
+			background: #01c9b2;
+			display: flex;
+			align-items: center;
+			padding: 35rpx 55rpx;
+			.user-photo{
+				flex-shrink: 0;
+				margin-right: 5rpx;
+				width: 130rpx;
+				height: 130rpx;
+				border-radius: 50%;
+				overflow: hidden;
+			}
+			.user-info{
+				flex-grow: 1;
+				padding: 0 20rpx;
+				color: #FFFFFF;
+				.user-name{
+					display: block;
+					font-size: 30rpx;
+					margin-bottom: 20rpx;
+				}
+				.user-phone{
+					display: block;
+					font-size: 26rpx;
+				}
+			}
+		}
+		.user-list{
+			border-radius: 15upx;
+			margin: 20upx;
+			overflow: hidden;
+			box-shadow: 0upx 3upx 6upx #eee;
+		}
+		.user-btn{
+			padding: 85rpx 200rpx;
+		}
+	}
+</style>

BIN
static/CLOTHES.png


BIN
static/GLASS.png


BIN
static/HARM.png


BIN
static/METAL.png


BIN
static/MET_PLA.png


BIN
static/PAPER.png


BIN
static/PLASTIC.png


BIN
static/RECYCLING.png


BIN
static/filter.png


BIN
static/full-bg.png


BIN
static/ledou.png


BIN
static/login_icon_logo.png


BIN
static/logo.jpg


BIN
static/map-icon.png


BIN
static/md-big-pic.png


BIN
static/pop-bg.png


BIN
static/store-s.png


BIN
static/store.png


BIN
static/tabbar/cleared-active.png


BIN
static/tabbar/cleared.png


BIN
static/tabbar/unclean-active.png


BIN
static/tabbar/unclean.png


BIN
static/tabbar/user-active.png


BIN
static/tabbar/user.png


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

@@ -0,0 +1,27 @@
+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)
+	}
+}

+ 176 - 0
store/index.js

@@ -0,0 +1,176 @@
+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 = [
+	'vuex_user',
+	'vuex_token',
+	'vuex_userData',
+	'vuex_payType',
+	'vuex_payStatus',
+	'vuex_storeId',
+	'vuex_bizId',
+	'vuex_orderNo',
+	'vuex_orderStatus',
+	'vuex_cartNums'
+];
+
+// 保存变量到本地存储中
+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);
+	}
+}
+
+// websocket 连接
+const SocketInit = function($store,state,wsUrl){
+	let token = getApp().globalData.token
+	// 开始连接
+	state.vuex_socket = uni.connectSocket({
+		header: {
+			'X-AUTH-TOKEN': token
+		},
+		url: wsUrl, // ws 请求地址
+		complete: () => {
+			console.log('连接complete回调!')
+		}
+	});
+	// 打开连接
+	state.vuex_socket.onOpen(function(e) {
+		console.log('连接成功!')
+		uni.$emit('wsMessage', 'connectOpen')
+	})
+	// 连接关闭
+	state.vuex_socket.onClose(function(e) {
+		console.log('ws关闭!')
+	})
+	// 连接错误
+	state.vuex_socket.onError(function(e) {
+		console.log('ws错误!', JSON.stringify(e))
+	})
+	// 接受消息
+	state.vuex_socket.onMessage(function(e) {
+		console.log(e,'onmessage')
+		if (e.data == 'pong' || e.data == 'connected') {
+			uni.$emit('wsMessage', e.data)
+		}else{
+			uni.$emit('wsMessage', JSON.parse(e.data))
+		}
+	})
+	// 发送心跳包
+	state.vuex_heartInterId = setInterval(function() {
+		// console.log(state.vuex_socket.readyState)
+		if (state.vuex_socket.readyState != 1) {
+			 // 停止心跳
+			 clearInterval(state.vuex_heartInterId)
+			 SocketInit($store,state,wsUrl)
+			 uni.$emit('wsMessage','reconnect')
+		} else {
+			$store.commit("$sendWebsocket", "ping")
+		}
+	}, 20000)
+}
+
+// store 对象
+const store = new Vuex.Store({
+	// 下面这些值仅为示例,使用过程中请删除
+	state: {
+		// 如果上面从本地获取的lifeData对象下有对应的属性,就赋值给state中对应的变量
+		// 加上vuex_前缀,是防止变量名冲突,也让人一目了然
+		vuex_user: lifeData.vuex_user ? lifeData.vuex_user : {
+			account: '',
+			password: ''
+		},
+		vuex_token: lifeData.vuex_token ? lifeData.vuex_token : '',
+		vuex_userData: lifeData.vuex_userData ? lifeData.vuex_userData : '',
+		vuex_payType: lifeData.vuex_payType ? lifeData.vuex_payType : [], // 支付方式数据字典
+		vuex_payStatus: lifeData.vuex_payStatus ? lifeData.vuex_payStatus : [], // 支付状态数据字典
+		// 订单信息
+		vuex_storeId: lifeData.vuex_storeId ? lifeData.vuex_storeId : '',// 网点id
+		vuex_bizId: lifeData.vuex_bizId ? lifeData.vuex_bizId : '',// 设备编号
+		vuex_orderNo: lifeData.vuex_orderNo ? lifeData.vuex_orderNo : '',// 订单编号
+		vuex_orderStatus: lifeData.vuex_orderStatus ? lifeData.vuex_orderStatus : '',// 订单状态
+		// 购物车及下单
+		vuex_cartList: [],
+		vuex_toOrderList: [],
+		// 如果无需保存到本地永久存储,无需lifeData.xx方式
+		vuex_socket: null,
+		vuex_wsMessageData: '',
+		vuex_heartInterId: null,
+		// 当前网络连接状态
+		vuex_netStatus: '',
+		// 客服电话
+		vuex_kfMobile: ''
+	},
+	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])
+		},
+		// 创建通知消息websocket
+		$webSocket(state, params) {
+			let _this = this
+			let url = getApp().globalData.baseUrl
+			let wsBaseUrl = url.indexOf("https:") >= 0 ? url.replace("https:", "wss:") : url.replace("http:", "ws:")
+			let wsUrl = wsBaseUrl + 'websocket/weixin/' + state.vuex_bizId
+			console.log(wsUrl,'wsUrl')
+			SocketInit(_this,state,wsUrl)
+		},
+		// 关闭websocket
+		$closeWebsocket(state) {
+			if (state.vuex_socket) {
+				state.vuex_socket.close({
+					complete: function(e) {
+						console.log('关闭websocket完成', e)
+						// 停止心跳
+						clearInterval(state.vuex_heartInterId)
+					}
+				})
+			}
+		},
+		// 发送消息
+		$sendWebsocket(state, msg) {
+			state.vuex_socket.send({
+				data: msg,
+				complete: function(e) {
+					console.log('ws发送完成', msg)
+				}
+			})
+		},
+	}
+})
+
+export default store

+ 94 - 0
uni.scss

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

Some files were not shown because too many files changed in this diff