Compare commits
	
		
			12 Commits 
		
	
	
	| Author | SHA1 | Date | 
|---|---|---|
| 
							
							
								
								 | 
						2b153be3ea | 2 years ago | 
| 
							
							
								
								 | 
						64aee01040 | 2 years ago | 
| 
							
							
								
								 | 
						ccf6ed2620 | 2 years ago | 
| 
							
							
								
								 | 
						a56e8f1a3c | 2 years ago | 
| 
							
							
								
								 | 
						98dd58b300 | 2 years ago | 
| 
							
							
								
								 | 
						905f934585 | 2 years ago | 
| 
							
							
								
								 | 
						18c3ea2d90 | 2 years ago | 
| 
							
							
								
								 | 
						50d2e7cad1 | 2 years ago | 
| 
							
							
								
								 | 
						01fe9f0eb2 | 2 years ago | 
| 
							
							
								
								 | 
						55679678bd | 2 years ago | 
| 
							
							
								
								 | 
						21e075c74a | 2 years ago | 
| 
							
							
								
								 | 
						3ecd0a05bd | 2 years ago | 
| 
		 After Width: | Height: | Size: 421 KiB  | 
@ -1,2 +1,3 @@
 | 
				
			|||||||
/node_modules
 | 
					/node_modules
 | 
				
			||||||
/unpackage/dist
 | 
					/unpackage/dist
 | 
				
			||||||
 | 
					/.hbuilderx
 | 
				
			||||||
@ -0,0 +1,66 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<view class="dishes-item">
 | 
				
			||||||
 | 
						    <!-- 菜品左侧图片区域 -->
 | 
				
			||||||
 | 
						    <view class="dishes-item-left">
 | 
				
			||||||
 | 
						      <image :src="dishes.dish_src" class="dishes-pic"></image>
 | 
				
			||||||
 | 
						    </view>
 | 
				
			||||||
 | 
						    <!-- 菜品右侧信息区域 -->
 | 
				
			||||||
 | 
						    <view class="dishes-item-right">
 | 
				
			||||||
 | 
						      <!-- 菜品标题 -->
 | 
				
			||||||
 | 
						       <view class="dishes-name">{{dishes.dish_name}}</view>
 | 
				
			||||||
 | 
						       <view class="dishes-info-box">
 | 
				
			||||||
 | 
												
 | 
				
			||||||
 | 
							   </view>
 | 
				
			||||||
 | 
						    </view>
 | 
				
			||||||
 | 
						</view>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						export default {
 | 
				
			||||||
 | 
						    props: {
 | 
				
			||||||
 | 
								dishes: {
 | 
				
			||||||
 | 
									type: Object,
 | 
				
			||||||
 | 
									default:{},
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							data: {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss">
 | 
				
			||||||
 | 
					    .dishes-item {
 | 
				
			||||||
 | 
					      display: flex;
 | 
				
			||||||
 | 
					      padding: 10px 5px;
 | 
				
			||||||
 | 
					      border-bottom: 1px solid #f0f0f0;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					     .dishes-item-left {
 | 
				
			||||||
 | 
					        margin-right: 5px;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					     .dishes-pic {
 | 
				
			||||||
 | 
					          width: 100px;
 | 
				
			||||||
 | 
					          height: 100px;
 | 
				
			||||||
 | 
					          display: block;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					     .dishes-item-right {
 | 
				
			||||||
 | 
					        display: flex;
 | 
				
			||||||
 | 
					        flex-direction: column;
 | 
				
			||||||
 | 
					        justify-content: space-between;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					     .dishes-name {
 | 
				
			||||||
 | 
					          font-size: 13px;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					     .dishes-price {
 | 
				
			||||||
 | 
					          font-size: 16px;
 | 
				
			||||||
 | 
					          color: #c00000;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
@ -0,0 +1,119 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<view class="login-container">
 | 
				
			||||||
 | 
							<uni-icons type="contact-filled" size="100" color="#afafaf"></uni-icons>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							<button type="primary" class="btn-login" @click="getUserInfo()">一键登录</button>
 | 
				
			||||||
 | 
							<text class="login-text">登陆后尽享更多权益</text>
 | 
				
			||||||
 | 
							<image :src="headerURL"></image>
 | 
				
			||||||
 | 
						</view>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script>
 | 
				
			||||||
 | 
						import {
 | 
				
			||||||
 | 
							mapMutations
 | 
				
			||||||
 | 
						} from 'vuex'
 | 
				
			||||||
 | 
						export default {
 | 
				
			||||||
 | 
							name: "my-login",
 | 
				
			||||||
 | 
							data() {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									nickName: '',
 | 
				
			||||||
 | 
									headerURL: '',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							methods: {
 | 
				
			||||||
 | 
								...mapMutations('m_user', ['updateUserInfo', 'updatetoken','savetokentostorage','saveUserInfoToStorage']),
 | 
				
			||||||
 | 
								getUserInfo() {
 | 
				
			||||||
 | 
									let that = this
 | 
				
			||||||
 | 
									uni.showModal({
 | 
				
			||||||
 | 
										title: '温馨提示',
 | 
				
			||||||
 | 
										content: '授权后使用',
 | 
				
			||||||
 | 
										success: function(res) {
 | 
				
			||||||
 | 
											if (res.confirm) {
 | 
				
			||||||
 | 
												uni.getUserProfile({
 | 
				
			||||||
 | 
													desc: '获取你的昵称头像',
 | 
				
			||||||
 | 
													success: userRes => {
 | 
				
			||||||
 | 
														if (userRes.userInfo !==
 | 
				
			||||||
 | 
															undefined) {
 | 
				
			||||||
 | 
															let userInfo = {
 | 
				
			||||||
 | 
																avatarURL: userRes.userInfo.avatarUrl,
 | 
				
			||||||
 | 
																nickName: userRes.userInfo.nickName
 | 
				
			||||||
 | 
															}
 | 
				
			||||||
 | 
															that.nickName = userRes.userInfo.nickName
 | 
				
			||||||
 | 
															console.log(userInfo)
 | 
				
			||||||
 | 
															that.getOpenID(userInfo)
 | 
				
			||||||
 | 
														} else {
 | 
				
			||||||
 | 
															uni.showToast({
 | 
				
			||||||
 | 
																icon: 'none',
 | 
				
			||||||
 | 
																title: '获取失败,请重试'
 | 
				
			||||||
 | 
															})
 | 
				
			||||||
 | 
														}
 | 
				
			||||||
 | 
													},
 | 
				
			||||||
 | 
													fail: error => {}
 | 
				
			||||||
 | 
												})
 | 
				
			||||||
 | 
											} else if (res.cancel) {}
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										fail: error => {
 | 
				
			||||||
 | 
											
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								async getOpenID(userInfo) {
 | 
				
			||||||
 | 
									let that = this
 | 
				
			||||||
 | 
									uni.login({
 | 
				
			||||||
 | 
										provider: 'weixin',
 | 
				
			||||||
 | 
										success: function(loginAuth) {
 | 
				
			||||||
 | 
											let code = loginAuth.code
 | 
				
			||||||
 | 
											uniCloud.callFunction({
 | 
				
			||||||
 | 
												name: 'wxlogin',
 | 
				
			||||||
 | 
												data: {
 | 
				
			||||||
 | 
													code: code
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
												success: function(res) {
 | 
				
			||||||
 | 
													that.updatetoken(res)
 | 
				
			||||||
 | 
													that.savetokentostorage()
 | 
				
			||||||
 | 
													that.updateUserInfo(userInfo)
 | 
				
			||||||
 | 
													that.saveUserInfoToStorage()
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											})
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
									console.log(userInfo)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss">
 | 
				
			||||||
 | 
						.login-container {
 | 
				
			||||||
 | 
							height: 750rpx;
 | 
				
			||||||
 | 
							background-color: #f8f8f8;
 | 
				
			||||||
 | 
							display: flex;
 | 
				
			||||||
 | 
							flex-direction: column;
 | 
				
			||||||
 | 
							justify-content: center;
 | 
				
			||||||
 | 
							align-items: center;
 | 
				
			||||||
 | 
							position: relative;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							&::after {
 | 
				
			||||||
 | 
								content: '';
 | 
				
			||||||
 | 
								display: block;
 | 
				
			||||||
 | 
								width: 100%;
 | 
				
			||||||
 | 
								height: 40px;
 | 
				
			||||||
 | 
								background-color: #f8f8f8;
 | 
				
			||||||
 | 
								position: absolute;
 | 
				
			||||||
 | 
								bottom: 0;
 | 
				
			||||||
 | 
								left: 0;
 | 
				
			||||||
 | 
								border-radius: 100%;
 | 
				
			||||||
 | 
								transform: translateY(50%);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							.btn-login {
 | 
				
			||||||
 | 
								width: 90%;
 | 
				
			||||||
 | 
								border-radius: 100px;
 | 
				
			||||||
 | 
								margin: 15px 0;
 | 
				
			||||||
 | 
								background-color: #C00000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
@ -0,0 +1,64 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<view class="my-search-container"   @click="searchBoxHandler">
 | 
				
			||||||
 | 
						    <!-- 使用 view 组件模拟 input 输入框的样式 -->
 | 
				
			||||||
 | 
						    <view class="my-search-box">
 | 
				
			||||||
 | 
						      <uni-icons type="search" size="17"></uni-icons>
 | 
				
			||||||
 | 
						      <text class="placeholder">搜索</text>
 | 
				
			||||||
 | 
						    </view>
 | 
				
			||||||
 | 
						  </view>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script>
 | 
				
			||||||
 | 
						export default {
 | 
				
			||||||
 | 
							name:"my-search",
 | 
				
			||||||
 | 
							props: {
 | 
				
			||||||
 | 
								 // 背景颜色
 | 
				
			||||||
 | 
								  bgcolor: {
 | 
				
			||||||
 | 
								    type: String,
 | 
				
			||||||
 | 
								    default: '#C00000'
 | 
				
			||||||
 | 
								  },
 | 
				
			||||||
 | 
								  // 圆角尺寸
 | 
				
			||||||
 | 
								  radius: {
 | 
				
			||||||
 | 
								    type: Number,
 | 
				
			||||||
 | 
								    // 单位是 px
 | 
				
			||||||
 | 
								    default: 18
 | 
				
			||||||
 | 
								  }
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							data() {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							methods: {
 | 
				
			||||||
 | 
								searchBoxHandler(){
 | 
				
			||||||
 | 
									  // 触发外界通过 @click 绑定的 click 事件处理函数
 | 
				
			||||||
 | 
									    this.$emit('click')
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss">
 | 
				
			||||||
 | 
					  .my-search-container {
 | 
				
			||||||
 | 
					    background-color: #c00000;
 | 
				
			||||||
 | 
					    height: 50px;
 | 
				
			||||||
 | 
					    padding: 0 10px;
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    align-items: center;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  .my-search-box {
 | 
				
			||||||
 | 
					    height: 36px;
 | 
				
			||||||
 | 
					    background-color: #ffffff;
 | 
				
			||||||
 | 
					    border-radius: 15px;
 | 
				
			||||||
 | 
					    width: 100%;
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    align-items: center;
 | 
				
			||||||
 | 
					    justify-content: center;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    .placeholder {
 | 
				
			||||||
 | 
					      font-size: 15px;
 | 
				
			||||||
 | 
					      margin-left: 5px;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
@ -0,0 +1,171 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<view class="my-userinfo-container">
 | 
				
			||||||
 | 
							<!--头像和昵称区域-->
 | 
				
			||||||
 | 
							<view class="top-box">
 | 
				
			||||||
 | 
								<image :src="userinfo.avatarURL" class="avatar"></image>
 | 
				
			||||||
 | 
								<button class="header" open-type="chooseAvatar" @chooseavatar="chooseAvatar">修改头像</button>
 | 
				
			||||||
 | 
							</view>
 | 
				
			||||||
 | 
							<!--面版区域-->
 | 
				
			||||||
 | 
							<view class="panel-list">
 | 
				
			||||||
 | 
								<!--第一个面板-->
 | 
				
			||||||
 | 
								<view class="panel">
 | 
				
			||||||
 | 
									<view class="panel-body">
 | 
				
			||||||
 | 
										<view class="panel-item">
 | 
				
			||||||
 | 
											<text>8</text>
 | 
				
			||||||
 | 
											<text>收藏的菜品</text>
 | 
				
			||||||
 | 
										</view>
 | 
				
			||||||
 | 
										<view class="panel-item">
 | 
				
			||||||
 | 
											<text>2</text>
 | 
				
			||||||
 | 
											<text>信息</text>
 | 
				
			||||||
 | 
										</view>
 | 
				
			||||||
 | 
										<view class="panel-item">
 | 
				
			||||||
 | 
											<text>6</text>
 | 
				
			||||||
 | 
											<text>足迹</text>
 | 
				
			||||||
 | 
										</view>
 | 
				
			||||||
 | 
									</view>
 | 
				
			||||||
 | 
								</view>
 | 
				
			||||||
 | 
								<!--第二个面板-->
 | 
				
			||||||
 | 
								<view class="panel">
 | 
				
			||||||
 | 
									<view class="panel-title">
 | 
				
			||||||
 | 
										我的评价
 | 
				
			||||||
 | 
									</view>
 | 
				
			||||||
 | 
									<view class="panel-body">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									</view>
 | 
				
			||||||
 | 
								</view>
 | 
				
			||||||
 | 
								<!--第三个面板-->
 | 
				
			||||||
 | 
								<view class="panel">
 | 
				
			||||||
 | 
									<view class="third-panel-list">
 | 
				
			||||||
 | 
										<text>反馈与帮助</text>
 | 
				
			||||||
 | 
										<uni-icons type="arrowright" size="15"></uni-icons>
 | 
				
			||||||
 | 
									</view>
 | 
				
			||||||
 | 
									<view class="third-panel-list" @click="logout">
 | 
				
			||||||
 | 
										<text>退出登录</text>
 | 
				
			||||||
 | 
										<uni-icons type="arrowright" size="15"></uni-icons>
 | 
				
			||||||
 | 
									</view>
 | 
				
			||||||
 | 
								</view>
 | 
				
			||||||
 | 
							</view>
 | 
				
			||||||
 | 
						</view>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script>
 | 
				
			||||||
 | 
						import {
 | 
				
			||||||
 | 
							mapState,
 | 
				
			||||||
 | 
							mapMutations
 | 
				
			||||||
 | 
						} from 'vuex'
 | 
				
			||||||
 | 
						export default {
 | 
				
			||||||
 | 
							name: "my-userinfo",
 | 
				
			||||||
 | 
							data() {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							onLoad() {
 | 
				
			||||||
 | 
								this.updateUserInfo(uni.getStorageInfoSync('userinfo'))
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							computed: {
 | 
				
			||||||
 | 
								...mapState('m_user', ['userinfo'])
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							methods: {
 | 
				
			||||||
 | 
								...mapMutations('m_user', ['updatetoken', 'updateUserInfo','saveUserInfoToStorage']),
 | 
				
			||||||
 | 
								chooseAvatar(e) {
 | 
				
			||||||
 | 
									this.userinfo.avatarURL = e.detail.avatarUrl
 | 
				
			||||||
 | 
									this.saveUserInfoToStorage()
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								async logout() {
 | 
				
			||||||
 | 
									let that = this
 | 
				
			||||||
 | 
									uni.showModal({
 | 
				
			||||||
 | 
										title: '提示',
 | 
				
			||||||
 | 
										content: '确认退出登录吗?',
 | 
				
			||||||
 | 
										success: (succ) => {
 | 
				
			||||||
 | 
											if (succ.confirm) {
 | 
				
			||||||
 | 
												that.updatetoken('')
 | 
				
			||||||
 | 
												that.savetokentostorage()
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss">
 | 
				
			||||||
 | 
						.my-userinfo-container {
 | 
				
			||||||
 | 
							height: 100%;
 | 
				
			||||||
 | 
							background-color: #f4f4f4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							.top-box {
 | 
				
			||||||
 | 
								height: 400rpx;
 | 
				
			||||||
 | 
								background-color: #efefef;
 | 
				
			||||||
 | 
								display: flex;
 | 
				
			||||||
 | 
								justify-content: center;
 | 
				
			||||||
 | 
								align-items: center;
 | 
				
			||||||
 | 
								flex-direction: column;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								.avatar {
 | 
				
			||||||
 | 
									width: 90px;
 | 
				
			||||||
 | 
									height: 90px;
 | 
				
			||||||
 | 
									border-radius: 45px;
 | 
				
			||||||
 | 
									border: 2px solid #FFF;
 | 
				
			||||||
 | 
									box-shadow: 0 1px 5px black;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								.nikname {
 | 
				
			||||||
 | 
									font-size: 16px;
 | 
				
			||||||
 | 
									color: black;
 | 
				
			||||||
 | 
									font-weight: bold;
 | 
				
			||||||
 | 
									margin-top: 10px;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.panel-list {
 | 
				
			||||||
 | 
							padding: 0 10px;
 | 
				
			||||||
 | 
							position: relative;
 | 
				
			||||||
 | 
							top: -10px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							.panel {
 | 
				
			||||||
 | 
								background-color: white;
 | 
				
			||||||
 | 
								border-radius: 3px;
 | 
				
			||||||
 | 
								margin-bottom: 8px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								.panel-title {
 | 
				
			||||||
 | 
									line-height: 45px;
 | 
				
			||||||
 | 
									padding-left: 10px;
 | 
				
			||||||
 | 
									font-size: 15px;
 | 
				
			||||||
 | 
									border-bottom: 1px solid #f8f8f8;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								.panel-body {
 | 
				
			||||||
 | 
									display: flex;
 | 
				
			||||||
 | 
									justify-content: space-around;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									.panel-item {
 | 
				
			||||||
 | 
										display: flex;
 | 
				
			||||||
 | 
										flex-direction: column;
 | 
				
			||||||
 | 
										align-items: center;
 | 
				
			||||||
 | 
										justify-content: space-around;
 | 
				
			||||||
 | 
										padding: 10px 0;
 | 
				
			||||||
 | 
										font-size: 13px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										.icon {
 | 
				
			||||||
 | 
											width: 35px;
 | 
				
			||||||
 | 
											height: 35px;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.third-panel-list {
 | 
				
			||||||
 | 
							display: flex;
 | 
				
			||||||
 | 
							justify-content: space-between;
 | 
				
			||||||
 | 
							align-items: center;
 | 
				
			||||||
 | 
							font-size: 18px;
 | 
				
			||||||
 | 
							padding: 0 10px;
 | 
				
			||||||
 | 
							line-height: 45px;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
@ -0,0 +1,543 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "name": "canteen",
 | 
				
			||||||
 | 
					  "version": "1.0.0",
 | 
				
			||||||
 | 
					  "lockfileVersion": 3,
 | 
				
			||||||
 | 
					  "requires": true,
 | 
				
			||||||
 | 
					  "packages": {
 | 
				
			||||||
 | 
					    "": {
 | 
				
			||||||
 | 
					      "name": "canteen",
 | 
				
			||||||
 | 
					      "version": "1.0.0",
 | 
				
			||||||
 | 
					      "license": "ISC",
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "@escook/request-miniprogram": "^0.2.1",
 | 
				
			||||||
 | 
					        "request-promise": "^4.2.6"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/@escook/request-miniprogram": {
 | 
				
			||||||
 | 
					      "version": "0.2.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/@escook/request-miniprogram/-/request-miniprogram-0.2.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-ueWV5YsaEm/ycQZuEjMiA88GFMhfBQSjy9GrP9omy4xAQajkGTbYIlnhzsDfWzRPmRC1fKmAiKMrCVcgS+SHcQ=="
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/ajv": {
 | 
				
			||||||
 | 
					      "version": "6.12.6",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "fast-deep-equal": "^3.1.1",
 | 
				
			||||||
 | 
					        "fast-json-stable-stringify": "^2.0.0",
 | 
				
			||||||
 | 
					        "json-schema-traverse": "^0.4.1",
 | 
				
			||||||
 | 
					        "uri-js": "^4.2.2"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "funding": {
 | 
				
			||||||
 | 
					        "type": "github",
 | 
				
			||||||
 | 
					        "url": "https://github.com/sponsors/epoberezkin"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/asn1": {
 | 
				
			||||||
 | 
					      "version": "0.2.6",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "safer-buffer": "~2.1.0"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/assert-plus": {
 | 
				
			||||||
 | 
					      "version": "1.0.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">=0.8"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/asynckit": {
 | 
				
			||||||
 | 
					      "version": "0.4.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
 | 
				
			||||||
 | 
					      "peer": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/aws-sign2": {
 | 
				
			||||||
 | 
					      "version": "0.7.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": "*"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/aws4": {
 | 
				
			||||||
 | 
					      "version": "1.12.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==",
 | 
				
			||||||
 | 
					      "peer": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/bcrypt-pbkdf": {
 | 
				
			||||||
 | 
					      "version": "1.0.2",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "tweetnacl": "^0.14.3"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/bluebird": {
 | 
				
			||||||
 | 
					      "version": "3.7.2",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/caseless": {
 | 
				
			||||||
 | 
					      "version": "0.12.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==",
 | 
				
			||||||
 | 
					      "peer": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/combined-stream": {
 | 
				
			||||||
 | 
					      "version": "1.0.8",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "delayed-stream": "~1.0.0"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">= 0.8"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/core-util-is": {
 | 
				
			||||||
 | 
					      "version": "1.0.2",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==",
 | 
				
			||||||
 | 
					      "peer": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/dashdash": {
 | 
				
			||||||
 | 
					      "version": "1.14.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "assert-plus": "^1.0.0"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">=0.10"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/delayed-stream": {
 | 
				
			||||||
 | 
					      "version": "1.0.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">=0.4.0"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/ecc-jsbn": {
 | 
				
			||||||
 | 
					      "version": "0.1.2",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "jsbn": "~0.1.0",
 | 
				
			||||||
 | 
					        "safer-buffer": "^2.1.0"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/extend": {
 | 
				
			||||||
 | 
					      "version": "3.0.2",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
 | 
				
			||||||
 | 
					      "peer": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/extsprintf": {
 | 
				
			||||||
 | 
					      "version": "1.3.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==",
 | 
				
			||||||
 | 
					      "engines": [
 | 
				
			||||||
 | 
					        "node >=0.6.0"
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      "peer": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/fast-deep-equal": {
 | 
				
			||||||
 | 
					      "version": "3.1.3",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
 | 
				
			||||||
 | 
					      "peer": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/fast-json-stable-stringify": {
 | 
				
			||||||
 | 
					      "version": "2.1.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
 | 
				
			||||||
 | 
					      "peer": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/forever-agent": {
 | 
				
			||||||
 | 
					      "version": "0.6.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": "*"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/form-data": {
 | 
				
			||||||
 | 
					      "version": "2.3.3",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "asynckit": "^0.4.0",
 | 
				
			||||||
 | 
					        "combined-stream": "^1.0.6",
 | 
				
			||||||
 | 
					        "mime-types": "^2.1.12"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">= 0.12"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/getpass": {
 | 
				
			||||||
 | 
					      "version": "0.1.7",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "assert-plus": "^1.0.0"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/har-schema": {
 | 
				
			||||||
 | 
					      "version": "2.0.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">=4"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/har-validator": {
 | 
				
			||||||
 | 
					      "version": "5.1.5",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
 | 
				
			||||||
 | 
					      "deprecated": "this library is no longer supported",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "ajv": "^6.12.3",
 | 
				
			||||||
 | 
					        "har-schema": "^2.0.0"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">=6"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/http-signature": {
 | 
				
			||||||
 | 
					      "version": "1.2.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "assert-plus": "^1.0.0",
 | 
				
			||||||
 | 
					        "jsprim": "^1.2.2",
 | 
				
			||||||
 | 
					        "sshpk": "^1.7.0"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">=0.8",
 | 
				
			||||||
 | 
					        "npm": ">=1.3.7"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/is-typedarray": {
 | 
				
			||||||
 | 
					      "version": "1.0.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
 | 
				
			||||||
 | 
					      "peer": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/isstream": {
 | 
				
			||||||
 | 
					      "version": "0.1.2",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==",
 | 
				
			||||||
 | 
					      "peer": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/jsbn": {
 | 
				
			||||||
 | 
					      "version": "0.1.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==",
 | 
				
			||||||
 | 
					      "peer": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/json-schema": {
 | 
				
			||||||
 | 
					      "version": "0.4.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
 | 
				
			||||||
 | 
					      "peer": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/json-schema-traverse": {
 | 
				
			||||||
 | 
					      "version": "0.4.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
 | 
				
			||||||
 | 
					      "peer": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/json-stringify-safe": {
 | 
				
			||||||
 | 
					      "version": "5.0.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
 | 
				
			||||||
 | 
					      "peer": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/jsprim": {
 | 
				
			||||||
 | 
					      "version": "1.4.2",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "assert-plus": "1.0.0",
 | 
				
			||||||
 | 
					        "extsprintf": "1.3.0",
 | 
				
			||||||
 | 
					        "json-schema": "0.4.0",
 | 
				
			||||||
 | 
					        "verror": "1.10.0"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">=0.6.0"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/lodash": {
 | 
				
			||||||
 | 
					      "version": "4.17.21",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/mime-db": {
 | 
				
			||||||
 | 
					      "version": "1.52.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">= 0.6"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/mime-types": {
 | 
				
			||||||
 | 
					      "version": "2.1.35",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "mime-db": "1.52.0"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">= 0.6"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/oauth-sign": {
 | 
				
			||||||
 | 
					      "version": "0.9.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": "*"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/performance-now": {
 | 
				
			||||||
 | 
					      "version": "2.1.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
 | 
				
			||||||
 | 
					      "peer": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/psl": {
 | 
				
			||||||
 | 
					      "version": "1.9.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag=="
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/punycode": {
 | 
				
			||||||
 | 
					      "version": "2.3.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">=6"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/qs": {
 | 
				
			||||||
 | 
					      "version": "6.5.3",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">=0.6"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/request": {
 | 
				
			||||||
 | 
					      "version": "2.88.2",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
 | 
				
			||||||
 | 
					      "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "aws-sign2": "~0.7.0",
 | 
				
			||||||
 | 
					        "aws4": "^1.8.0",
 | 
				
			||||||
 | 
					        "caseless": "~0.12.0",
 | 
				
			||||||
 | 
					        "combined-stream": "~1.0.6",
 | 
				
			||||||
 | 
					        "extend": "~3.0.2",
 | 
				
			||||||
 | 
					        "forever-agent": "~0.6.1",
 | 
				
			||||||
 | 
					        "form-data": "~2.3.2",
 | 
				
			||||||
 | 
					        "har-validator": "~5.1.3",
 | 
				
			||||||
 | 
					        "http-signature": "~1.2.0",
 | 
				
			||||||
 | 
					        "is-typedarray": "~1.0.0",
 | 
				
			||||||
 | 
					        "isstream": "~0.1.2",
 | 
				
			||||||
 | 
					        "json-stringify-safe": "~5.0.1",
 | 
				
			||||||
 | 
					        "mime-types": "~2.1.19",
 | 
				
			||||||
 | 
					        "oauth-sign": "~0.9.0",
 | 
				
			||||||
 | 
					        "performance-now": "^2.1.0",
 | 
				
			||||||
 | 
					        "qs": "~6.5.2",
 | 
				
			||||||
 | 
					        "safe-buffer": "^5.1.2",
 | 
				
			||||||
 | 
					        "tough-cookie": "~2.5.0",
 | 
				
			||||||
 | 
					        "tunnel-agent": "^0.6.0",
 | 
				
			||||||
 | 
					        "uuid": "^3.3.2"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">= 6"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/request-promise": {
 | 
				
			||||||
 | 
					      "version": "4.2.6",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.6.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ==",
 | 
				
			||||||
 | 
					      "deprecated": "request-promise has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142",
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "bluebird": "^3.5.0",
 | 
				
			||||||
 | 
					        "request-promise-core": "1.1.4",
 | 
				
			||||||
 | 
					        "stealthy-require": "^1.1.1",
 | 
				
			||||||
 | 
					        "tough-cookie": "^2.3.3"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">=0.10.0"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "peerDependencies": {
 | 
				
			||||||
 | 
					        "request": "^2.34"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/request-promise-core": {
 | 
				
			||||||
 | 
					      "version": "1.1.4",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==",
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "lodash": "^4.17.19"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">=0.10.0"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "peerDependencies": {
 | 
				
			||||||
 | 
					        "request": "^2.34"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/safe-buffer": {
 | 
				
			||||||
 | 
					      "version": "5.2.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
 | 
				
			||||||
 | 
					      "funding": [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "type": "github",
 | 
				
			||||||
 | 
					          "url": "https://github.com/sponsors/feross"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "type": "patreon",
 | 
				
			||||||
 | 
					          "url": "https://www.patreon.com/feross"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "type": "consulting",
 | 
				
			||||||
 | 
					          "url": "https://feross.org/support"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      "peer": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/safer-buffer": {
 | 
				
			||||||
 | 
					      "version": "2.1.2",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
 | 
				
			||||||
 | 
					      "peer": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/sshpk": {
 | 
				
			||||||
 | 
					      "version": "1.17.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "asn1": "~0.2.3",
 | 
				
			||||||
 | 
					        "assert-plus": "^1.0.0",
 | 
				
			||||||
 | 
					        "bcrypt-pbkdf": "^1.0.0",
 | 
				
			||||||
 | 
					        "dashdash": "^1.12.0",
 | 
				
			||||||
 | 
					        "ecc-jsbn": "~0.1.1",
 | 
				
			||||||
 | 
					        "getpass": "^0.1.1",
 | 
				
			||||||
 | 
					        "jsbn": "~0.1.0",
 | 
				
			||||||
 | 
					        "safer-buffer": "^2.0.2",
 | 
				
			||||||
 | 
					        "tweetnacl": "~0.14.0"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "bin": {
 | 
				
			||||||
 | 
					        "sshpk-conv": "bin/sshpk-conv",
 | 
				
			||||||
 | 
					        "sshpk-sign": "bin/sshpk-sign",
 | 
				
			||||||
 | 
					        "sshpk-verify": "bin/sshpk-verify"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">=0.10.0"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/stealthy-require": {
 | 
				
			||||||
 | 
					      "version": "1.1.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==",
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">=0.10.0"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/tough-cookie": {
 | 
				
			||||||
 | 
					      "version": "2.5.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "psl": "^1.1.28",
 | 
				
			||||||
 | 
					        "punycode": "^2.1.1"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">=0.8"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/tunnel-agent": {
 | 
				
			||||||
 | 
					      "version": "0.6.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "safe-buffer": "^5.0.1"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": "*"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/tweetnacl": {
 | 
				
			||||||
 | 
					      "version": "0.14.5",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==",
 | 
				
			||||||
 | 
					      "peer": true
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/uri-js": {
 | 
				
			||||||
 | 
					      "version": "4.4.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "punycode": "^2.1.0"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/uuid": {
 | 
				
			||||||
 | 
					      "version": "3.4.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
 | 
				
			||||||
 | 
					      "deprecated": "Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.",
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "bin": {
 | 
				
			||||||
 | 
					        "uuid": "bin/uuid"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/verror": {
 | 
				
			||||||
 | 
					      "version": "1.10.0",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==",
 | 
				
			||||||
 | 
					      "engines": [
 | 
				
			||||||
 | 
					        "node >=0.6.0"
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      "peer": true,
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "assert-plus": "^1.0.0",
 | 
				
			||||||
 | 
					        "core-util-is": "1.0.2",
 | 
				
			||||||
 | 
					        "extsprintf": "^1.2.0"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "name": "canteen",
 | 
				
			||||||
 | 
					  "version": "1.0.0",
 | 
				
			||||||
 | 
					  "description": "",
 | 
				
			||||||
 | 
					  "main": "main.js",
 | 
				
			||||||
 | 
					  "scripts": {
 | 
				
			||||||
 | 
					    "test": "echo \"Error: no test specified\" && exit 1"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "keywords": [],
 | 
				
			||||||
 | 
					  "author": "",
 | 
				
			||||||
 | 
					  "license": "ISC",
 | 
				
			||||||
 | 
					  "dependencies": {
 | 
				
			||||||
 | 
					    "@escook/request-miniprogram": "^0.2.1",
 | 
				
			||||||
 | 
					    "request-promise": "^4.2.6"
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,19 +1,39 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
	<view>
 | 
					  <view class="my-container">
 | 
				
			||||||
 | 
					    <my-login v-if="!token"></my-login>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    <my-userinfo v-else></my-userinfo>
 | 
				
			||||||
 | 
						<m-tabbar native=""></m-tabbar>
 | 
				
			||||||
  </view>
 | 
					  </view>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
 | 
					  import {mapState} from "vuex"
 | 
				
			||||||
 | 
					  import {
 | 
				
			||||||
 | 
					  	mapMutations
 | 
				
			||||||
 | 
					  } from 'vuex'
 | 
				
			||||||
  export default {
 | 
					  export default {
 | 
				
			||||||
    data() {
 | 
					    data() {
 | 
				
			||||||
      return {
 | 
					      return {
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
						onLoad(){
 | 
				
			||||||
 | 
							this.updatetoken(uni.getStorageSync('token'))
 | 
				
			||||||
 | 
							this.savetokentostorage()
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						methods:{
 | 
				
			||||||
 | 
							...mapMutations('m_user', ['updateUserInfo', 'updatetoken','savetokentostorage'])
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					    computed: {
 | 
				
			||||||
 | 
					      ...mapState('m_user',['token'])
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style lang="scss">
 | 
					<style lang="scss">
 | 
				
			||||||
 | 
					page,
 | 
				
			||||||
 | 
					.my-container {
 | 
				
			||||||
 | 
					  height: 100%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,138 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<view>
 | 
				
			||||||
 | 
							<view class="dish-list">
 | 
				
			||||||
 | 
								<view class="product-list">
 | 
				
			||||||
 | 
									<view class="dish" v-for="(dishes, i) in dishList" :key="i" @click="gotoDetail(dishes)">
 | 
				
			||||||
 | 
										<image class="image" v-if="dishes" mode="widthFix" :src="dishes.dish_src"></image>
 | 
				
			||||||
 | 
										<view class="name">{{dishes.dish_name}}</view>
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
									</view>
 | 
				
			||||||
 | 
								</view>
 | 
				
			||||||
 | 
								<view class="loading-text">{{}}</view>
 | 
				
			||||||
 | 
							</view>
 | 
				
			||||||
 | 
							  <m-tabbar native=""></m-tabbar>
 | 
				
			||||||
 | 
						</view>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script>
 | 
				
			||||||
 | 
						import {
 | 
				
			||||||
 | 
							mapState
 | 
				
			||||||
 | 
						} from "vuex"
 | 
				
			||||||
 | 
						import {
 | 
				
			||||||
 | 
							mapMutations
 | 
				
			||||||
 | 
						} from 'vuex'
 | 
				
			||||||
 | 
						export default {
 | 
				
			||||||
 | 
							data() {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									user_id:'',
 | 
				
			||||||
 | 
									labelList:[],
 | 
				
			||||||
 | 
									dishList:[]
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							onLoad(){
 | 
				
			||||||
 | 
								let that = this
 | 
				
			||||||
 | 
								this.getUserID()
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							methods: {
 | 
				
			||||||
 | 
								gotoDetail(item) {
 | 
				
			||||||
 | 
									console.log(item._id)
 | 
				
			||||||
 | 
									uni.navigateTo({
 | 
				
			||||||
 | 
										url: '/subpkg/dishDetail/dishDetail?_id=' + encodeURIComponent(JSON.stringify(item._id))
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								async getDishes() {
 | 
				
			||||||
 | 
									let that = this
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
									uniCloud.callFunction({
 | 
				
			||||||
 | 
										name: "getDishes",
 | 
				
			||||||
 | 
										data: {
 | 
				
			||||||
 | 
											api: "getByLabels",
 | 
				
			||||||
 | 
											labels: that.labelList
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										success: function(res) {
 | 
				
			||||||
 | 
											console.log(res)
 | 
				
			||||||
 | 
											that.dishList = res.result
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								async getRecommend() {
 | 
				
			||||||
 | 
									let that = this
 | 
				
			||||||
 | 
									uniCloud.callFunction({
 | 
				
			||||||
 | 
										name:'recommendService',
 | 
				
			||||||
 | 
										data:{
 | 
				
			||||||
 | 
											token:that.user_id
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										success: (res) => {
 | 
				
			||||||
 | 
											that.labelList = res.result
 | 
				
			||||||
 | 
											that.getDishes()
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								async getUserID(){
 | 
				
			||||||
 | 
									let that = this
 | 
				
			||||||
 | 
									
 | 
				
			||||||
 | 
									uniCloud.callFunction({
 | 
				
			||||||
 | 
										name:'getUser',
 | 
				
			||||||
 | 
										data:that.token,
 | 
				
			||||||
 | 
										success(res) {
 | 
				
			||||||
 | 
											that.user_id = res.result.data[0]._id
 | 
				
			||||||
 | 
											that.getRecommend()
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							computed: {
 | 
				
			||||||
 | 
								...mapState('m_user', ['token'])
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style scoped lang="scss">
 | 
				
			||||||
 | 
					    .dish-list {
 | 
				
			||||||
 | 
					    	padding-top: 10px;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .loading-text {
 | 
				
			||||||
 | 
					    	width: 100%;
 | 
				
			||||||
 | 
					    	display: flex;
 | 
				
			||||||
 | 
					    	justify-content: center;
 | 
				
			||||||
 | 
					    	align-items: center;
 | 
				
			||||||
 | 
					    	height: 30px;
 | 
				
			||||||
 | 
					    	color: #979797;
 | 
				
			||||||
 | 
					    	font-size: 12px;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .product-list {
 | 
				
			||||||
 | 
					    	width: 92%;
 | 
				
			||||||
 | 
					    	padding: 0 4% 3vw 4%;
 | 
				
			||||||
 | 
					    	display: flex;
 | 
				
			||||||
 | 
					    	justify-content: space-between;
 | 
				
			||||||
 | 
					    	flex-wrap: wrap;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .product {
 | 
				
			||||||
 | 
					    	width: 48%;
 | 
				
			||||||
 | 
					    	border-radius: 10px;
 | 
				
			||||||
 | 
					    	background-color: #fff;
 | 
				
			||||||
 | 
					    	margin: 0 0 7px 0;
 | 
				
			||||||
 | 
					    	box-shadow: 0 3px 12px rgba(0, 0, 0, 0.1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .image {
 | 
				
			||||||
 | 
					    	width: 100%;
 | 
				
			||||||
 | 
					    	width: 150px;
 | 
				
			||||||
 | 
					    	height: 150px;
 | 
				
			||||||
 | 
					    	border-radius: 0px 10px 0 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .name {
 | 
				
			||||||
 | 
					    	width: 92%;
 | 
				
			||||||
 | 
					    	padding: 5px 4%;
 | 
				
			||||||
 | 
					    	display: -webkit-box;
 | 
				
			||||||
 | 
					    	-webkit-box-orient: vertical;
 | 
				
			||||||
 | 
					    	-webkit-line-clamp: 2;
 | 
				
			||||||
 | 
					    	text-align: justify;
 | 
				
			||||||
 | 
					    	overflow: hidden;
 | 
				
			||||||
 | 
					    	font-size: 15px;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 1.2 KiB  | 
| 
		 After Width: | Height: | Size: 765 B  | 
| 
		 After Width: | Height: | Size: 4.0 KiB  | 
| 
		 After Width: | Height: | Size: 1.0 KiB  | 
| 
		 After Width: | Height: | Size: 1.3 KiB  | 
| 
		 After Width: | Height: | Size: 1.5 KiB  | 
| 
		 After Width: | Height: | Size: 2.7 KiB  | 
| 
		 After Width: | Height: | Size: 1.9 KiB  | 
| 
		 After Width: | Height: | Size: 1.5 KiB  | 
| 
		 After Width: | Height: | Size: 544 B  | 
| 
		 After Width: | Height: | Size: 759 B  | 
| 
		 After Width: | Height: | Size: 2.4 KiB  | 
| 
		 After Width: | Height: | Size: 30 KiB  | 
| 
		 After Width: | Height: | Size: 2.9 KiB  | 
| 
		 After Width: | Height: | Size: 7.4 KiB  | 
| 
		 After Width: | Height: | Size: 1.2 KiB  | 
| 
		 After Width: | Height: | Size: 1.4 KiB  | 
| 
		 After Width: | Height: | Size: 1.1 KiB  | 
| 
		 After Width: | Height: | Size: 1.1 KiB  | 
| 
		 After Width: | Height: | Size: 2.7 KiB  | 
| 
		 After Width: | Height: | Size: 1.2 KiB  | 
| 
		 After Width: | Height: | Size: 1.4 KiB  | 
| 
		 After Width: | Height: | Size: 715 B  | 
| 
		 After Width: | Height: | Size: 1.5 KiB  | 
| 
		 After Width: | Height: | Size: 2.9 KiB  | 
| 
		 After Width: | Height: | Size: 3.1 KiB  | 
| 
		 After Width: | Height: | Size: 5.2 KiB  | 
| 
		 After Width: | Height: | Size: 5.3 KiB  | 
| 
		 After Width: | Height: | Size: 2.2 KiB  | 
| 
		 After Width: | Height: | Size: 2.2 KiB  | 
| 
		 After Width: | Height: | Size: 11 KiB  | 
| 
		 After Width: | Height: | Size: 11 KiB  | 
| 
		 After Width: | Height: | Size: 5.6 KiB  | 
| 
		 After Width: | Height: | Size: 5.4 KiB  | 
| 
		 After Width: | Height: | Size: 596 B  | 
| 
		 After Width: | Height: | Size: 3.0 KiB  | 
| 
		 After Width: | Height: | Size: 589 B  | 
| 
		 After Width: | Height: | Size: 1.6 KiB  | 
| 
		 After Width: | Height: | Size: 3.9 KiB  | 
@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					import Vue from 'vue'
 | 
				
			||||||
 | 
					import Vuex from 'vuex'
 | 
				
			||||||
 | 
					import moduleUser from './user.js'
 | 
				
			||||||
 | 
					Vue.use(Vuex)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 const store = new Vuex.Store({
 | 
				
			||||||
 | 
					  modules: {
 | 
				
			||||||
 | 
					    'm_user': moduleUser
 | 
				
			||||||
 | 
					  } 
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default store
 | 
				
			||||||
@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					export default {
 | 
				
			||||||
 | 
					  //开启命名空间
 | 
				
			||||||
 | 
					  namespaced: true ,
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  //数据
 | 
				
			||||||
 | 
					  state: () => ({
 | 
				
			||||||
 | 
					    token : '',
 | 
				
			||||||
 | 
					    //用户的信息对象
 | 
				
			||||||
 | 
					    userinfo: JSON.parse(uni.getStorageSync('userinfo') || '{}')
 | 
				
			||||||
 | 
					  }),
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  //方法
 | 
				
			||||||
 | 
					  mutations : {
 | 
				
			||||||
 | 
					    updateUserInfo(state,userinfo){
 | 
				
			||||||
 | 
					      state.userinfo = userinfo
 | 
				
			||||||
 | 
					      this.commit('m_user/saveUserInfoToStorage')
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    saveUserInfoToStorage(state)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      uni.setStorageSync('userinfo',JSON.stringify(state.userinfo))
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    updatetoken(state, token)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      state.token = token
 | 
				
			||||||
 | 
					      this.commit('m_user/savetokentostorage')
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    savetokentostorage(state){
 | 
				
			||||||
 | 
					      uni.setStorageSync('token',state.token)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  getters: {},
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,172 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<view>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							<view class="image_view">
 | 
				
			||||||
 | 
								<image class='dish_image' :src="dish_image_src"></image>
 | 
				
			||||||
 | 
							</view>
 | 
				
			||||||
 | 
							<view>
 | 
				
			||||||
 | 
								<text>{{"菜品名称:" + dish_name + '\n'}}</text>
 | 
				
			||||||
 | 
								<text>{{"菜品位置:" + dish_location + dish_window_name + '\n'}}</text>
 | 
				
			||||||
 | 
								<text>{{"菜品类别:" + JSON.stringify(dish_label) + '\n'}}</text>
 | 
				
			||||||
 | 
								<text>{{"菜品评分:" + dish_avg_score + '\n'}}</text>
 | 
				
			||||||
 | 
							</view>
 | 
				
			||||||
 | 
							<view>
 | 
				
			||||||
 | 
								<text>{{"菜品打分:\n"}}</text>
 | 
				
			||||||
 | 
								<uni-rate v-model="value" @change="onChange" allow-half="true" size="75" />
 | 
				
			||||||
 | 
							</view>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						</view>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script>
 | 
				
			||||||
 | 
						import {
 | 
				
			||||||
 | 
							mapState
 | 
				
			||||||
 | 
						} from "vuex"
 | 
				
			||||||
 | 
						import {
 | 
				
			||||||
 | 
							mapMutations
 | 
				
			||||||
 | 
						} from 'vuex'
 | 
				
			||||||
 | 
						export default {
 | 
				
			||||||
 | 
							data() {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									dish_image_src: '',
 | 
				
			||||||
 | 
									dish_name: '',
 | 
				
			||||||
 | 
									dish_label: [],
 | 
				
			||||||
 | 
									dish_location: '',
 | 
				
			||||||
 | 
									dish_window_name: '',
 | 
				
			||||||
 | 
									value: 4,
 | 
				
			||||||
 | 
									comentData: [],
 | 
				
			||||||
 | 
									dish_id: '',
 | 
				
			||||||
 | 
									dish_avg_score: 5.0,
 | 
				
			||||||
 | 
									dish_label_id: [0, 0, 0, 0, 0, 0, 0],
 | 
				
			||||||
 | 
									user_id:''
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							onLoad(option) {
 | 
				
			||||||
 | 
								let that = this
 | 
				
			||||||
 | 
								//this.getLabels()
 | 
				
			||||||
 | 
								this.dish_id = JSON.parse(decodeURIComponent(option._id))
 | 
				
			||||||
 | 
								this.getUserID()
 | 
				
			||||||
 | 
								this.getImage()
 | 
				
			||||||
 | 
								this.getLabels()
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								console.log(this.token)
 | 
				
			||||||
 | 
								console.log(this.dish_id)
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							methods: {
 | 
				
			||||||
 | 
								async getUserID(){
 | 
				
			||||||
 | 
									let that = this
 | 
				
			||||||
 | 
									
 | 
				
			||||||
 | 
									uniCloud.callFunction({
 | 
				
			||||||
 | 
										name:'getUser',
 | 
				
			||||||
 | 
										data:that.token,
 | 
				
			||||||
 | 
										success(res) {
 | 
				
			||||||
 | 
											that.user_id = res.result.data[0]._id
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								,
 | 
				
			||||||
 | 
								async recommendData() {
 | 
				
			||||||
 | 
									let that = this
 | 
				
			||||||
 | 
									if (this.token) {
 | 
				
			||||||
 | 
										uniCloud.callFunction({
 | 
				
			||||||
 | 
											name: 'recommendDataUpdate',
 | 
				
			||||||
 | 
											data: {
 | 
				
			||||||
 | 
												token: that.user_id,
 | 
				
			||||||
 | 
												labels: that.dish_label_id
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
											success:function(res){
 | 
				
			||||||
 | 
												console.log(res)
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										})
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								async getImage() {
 | 
				
			||||||
 | 
									let that = this
 | 
				
			||||||
 | 
									uniCloud.callFunction({
 | 
				
			||||||
 | 
										name: 'getDishes',
 | 
				
			||||||
 | 
										data: {
 | 
				
			||||||
 | 
											api: 'getByID',
 | 
				
			||||||
 | 
											id: this.dish_id
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										success: function(res) {
 | 
				
			||||||
 | 
											that.dish_image_src = res.result.data[0].dish_src
 | 
				
			||||||
 | 
											that.dish_name = res.result.data[0].dish_name
 | 
				
			||||||
 | 
											that.dish_location = res.result.data[0].location
 | 
				
			||||||
 | 
											that.dish_window_name = res.result.data[0].window_name
 | 
				
			||||||
 | 
											that.dish_avg_score = res.result.data[0].avg_score
 | 
				
			||||||
 | 
											console.log(res)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								async getLabels() {
 | 
				
			||||||
 | 
									let that = this
 | 
				
			||||||
 | 
									uniCloud.callFunction({
 | 
				
			||||||
 | 
										name: 'getlablelist',
 | 
				
			||||||
 | 
										data: {
 | 
				
			||||||
 | 
											id: that.dish_id
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										success: function(res) {
 | 
				
			||||||
 | 
											that.dish_label = res.result
 | 
				
			||||||
 | 
											for (let i = 0; i < that.dish_label.length; i++) {
 | 
				
			||||||
 | 
												console.log(that.dish_label[i])
 | 
				
			||||||
 | 
												if (that.dish_label[i] === "面") {
 | 
				
			||||||
 | 
													that.dish_label_id[0] = 1;
 | 
				
			||||||
 | 
												} else if (that.dish_label[i] === "鸡蛋") {
 | 
				
			||||||
 | 
													that.dish_label_id[1] = 1;
 | 
				
			||||||
 | 
												} else if (that.dish_label[i] === "牛肉") {
 | 
				
			||||||
 | 
													that.dish_label_id[2] = 1;
 | 
				
			||||||
 | 
												} else if (that.dish_label[i] === "米饭") {
 | 
				
			||||||
 | 
													that.dish_label_id[3] = 1;
 | 
				
			||||||
 | 
												} else if (that.dish_label[i] === "汤") {
 | 
				
			||||||
 | 
													that.dish_label_id[4] = 1;
 | 
				
			||||||
 | 
												} else if (that.dish_label[i] === "麻辣烫") {
 | 
				
			||||||
 | 
													that.dish_label_id[5] = 1;
 | 
				
			||||||
 | 
												} else if (that.dish_label[i] === "鸭肉") {
 | 
				
			||||||
 | 
													that.dish_label_id[6] = 1;
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											
 | 
				
			||||||
 | 
											that.recommendData()
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								onChange(e) {
 | 
				
			||||||
 | 
									let that = this
 | 
				
			||||||
 | 
									uniCloud.callFunction({
 | 
				
			||||||
 | 
										name: 'scoreUpdate',
 | 
				
			||||||
 | 
										data: {
 | 
				
			||||||
 | 
											score: that.value,
 | 
				
			||||||
 | 
											dish_id: that.dish_id
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								...mapMutations('m_user', ['updateUserInfo', 'updatetoken', 'savetokentostorage'])
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							computed: {
 | 
				
			||||||
 | 
								...mapState('m_user', ['token'])
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss">
 | 
				
			||||||
 | 
						.image_view {
 | 
				
			||||||
 | 
							height: 400rpx;
 | 
				
			||||||
 | 
							display: flex;
 | 
				
			||||||
 | 
							justify-content: center;
 | 
				
			||||||
 | 
							padding-left: 10rpx;
 | 
				
			||||||
 | 
							padding-right: 10rpx;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.dish_image {
 | 
				
			||||||
 | 
							display: flex;
 | 
				
			||||||
 | 
							height: 400rpx;
 | 
				
			||||||
 | 
							width: 600rpx;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.evaluete {}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
@ -0,0 +1,192 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<view>
 | 
				
			||||||
 | 
							<view class="search-box">
 | 
				
			||||||
 | 
								<uni-search-bar @input="input" :radius="100" cancelButton="none" :focus="true"></uni-search-bar>
 | 
				
			||||||
 | 
								<button  class="search" @click="goToSearchList">搜索</button>
 | 
				
			||||||
 | 
							</view>
 | 
				
			||||||
 | 
							<!--搜索建议-->
 | 
				
			||||||
 | 
							<view class="sugest-list" v-if="searchresult.length !== 0">
 | 
				
			||||||
 | 
								<view class="sugest-item" v-for="(item,i) in searchresult" :key="i" @click="gotodetail(item)">
 | 
				
			||||||
 | 
									<view class="dish-name">{{item.dish_name}}</view>
 | 
				
			||||||
 | 
									<uni-icons type="arrowright" size="16"></uni-icons>
 | 
				
			||||||
 | 
								</view>
 | 
				
			||||||
 | 
							</view>
 | 
				
			||||||
 | 
							<!--搜索历史-->
 | 
				
			||||||
 | 
							<view class="history-box" v-else>
 | 
				
			||||||
 | 
								<!--标题区域-->
 | 
				
			||||||
 | 
								<view class="history-title">
 | 
				
			||||||
 | 
									<text>搜索历史</text>
 | 
				
			||||||
 | 
									<uni-icons type="trash" size="17" @click="clean"></uni-icons>
 | 
				
			||||||
 | 
								</view>
 | 
				
			||||||
 | 
								<!--列表区域-->
 | 
				
			||||||
 | 
								<view class="history-list">
 | 
				
			||||||
 | 
									<uni-tag  v-for="(item,i) in histories" :text="item" :key="i" @click="gotosearchdetail(item)"></uni-tag>
 | 
				
			||||||
 | 
								</view>
 | 
				
			||||||
 | 
							</view>
 | 
				
			||||||
 | 
						</view>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script>
 | 
				
			||||||
 | 
						export default {
 | 
				
			||||||
 | 
							data() {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									timer: null,
 | 
				
			||||||
 | 
									kw: '',
 | 
				
			||||||
 | 
									searchresult: [],
 | 
				
			||||||
 | 
									//搜索结果
 | 
				
			||||||
 | 
									searchlist: [],
 | 
				
			||||||
 | 
									//搜索历史的数组
 | 
				
			||||||
 | 
									historylist: [],
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							onLoad() {
 | 
				
			||||||
 | 
								this.historylist = JSON.parse(uni.getStorageSync('kw') || '[]')
 | 
				
			||||||
 | 
								this.cnt = this.historylist.length
 | 
				
			||||||
 | 
								console.log(this.historylist)
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							methods: {
 | 
				
			||||||
 | 
								async goToSearchList() {
 | 
				
			||||||
 | 
									this.getsearchresult()
 | 
				
			||||||
 | 
									this.savesearchhistory()
 | 
				
			||||||
 | 
									let that = this
 | 
				
			||||||
 | 
									setTimeout(()=>{
 | 
				
			||||||
 | 
										uni.$emit('item',this.searchresult)
 | 
				
			||||||
 | 
									},500)
 | 
				
			||||||
 | 
									uni.navigateTo({
 | 
				
			||||||
 | 
										url:'/subpkg/searchList/searchList?searchlist=' + encodeURIComponent(JSON.stringify(this.searchresult))
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								//input输入事件的处理函数
 | 
				
			||||||
 | 
								input(e) {
 | 
				
			||||||
 | 
									//延时器
 | 
				
			||||||
 | 
									clearTimeout(this.timer)
 | 
				
			||||||
 | 
									this.timer = setTimeout(
 | 
				
			||||||
 | 
										() => {
 | 
				
			||||||
 | 
											this.kw = e
 | 
				
			||||||
 | 
											this.getsearchresult()
 | 
				
			||||||
 | 
										}, 500)
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								async getsearchresult() {
 | 
				
			||||||
 | 
									let that = this
 | 
				
			||||||
 | 
									//判断搜索关键词是否为空
 | 
				
			||||||
 | 
									if (this.kw.length === 0) {
 | 
				
			||||||
 | 
										this.searchresult = []
 | 
				
			||||||
 | 
										return
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									uniCloud.callFunction({
 | 
				
			||||||
 | 
										name:'getDishes',
 | 
				
			||||||
 | 
										data:{
 | 
				
			||||||
 | 
											api:'getByName',
 | 
				
			||||||
 | 
											dish_name:that.kw
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										success:function(res){
 | 
				
			||||||
 | 
											that.searchresult = res.result.data
 | 
				
			||||||
 | 
											that.searchlist = res.result.data
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								gotodetail(item) {
 | 
				
			||||||
 | 
									this.savesearchhistory()
 | 
				
			||||||
 | 
									console.log(item._id)
 | 
				
			||||||
 | 
									uni.navigateTo({
 | 
				
			||||||
 | 
										url: '/subpkg/dishDetail/dishDetail?_id=' +encodeURIComponent(JSON.stringify(item._id))
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								savesearchhistory() {
 | 
				
			||||||
 | 
									const set = new Set(this.historylist)
 | 
				
			||||||
 | 
									set.delete(this.kw)
 | 
				
			||||||
 | 
									set.add(this.kw)
 | 
				
			||||||
 | 
									this.historylist = Array.from(set)
 | 
				
			||||||
 | 
									uni.setStorageSync('kw', JSON.stringify(this.historylist))
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								//清空本地历史记录
 | 
				
			||||||
 | 
								clean() {
 | 
				
			||||||
 | 
									this.historylist = []
 | 
				
			||||||
 | 
									uni.setStorageSync('kw', '[]')
 | 
				
			||||||
 | 
									this.cnt = 0
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								gotosearchdetail(item) {
 | 
				
			||||||
 | 
									let historyresult = []
 | 
				
			||||||
 | 
									uniCloud.callFunction({
 | 
				
			||||||
 | 
										name:'getDishes',
 | 
				
			||||||
 | 
										data:{
 | 
				
			||||||
 | 
											api:'getByName',
 | 
				
			||||||
 | 
											dish_name:item
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										success:function(res){
 | 
				
			||||||
 | 
											historyresult = res.result.data
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
									setTimeout(()=>{
 | 
				
			||||||
 | 
										uni.$emit('item',historyresult)
 | 
				
			||||||
 | 
									},500)
 | 
				
			||||||
 | 
									uni.navigateTo({
 | 
				
			||||||
 | 
										url:'/subpkg/searchList/searchList?searchlist=' + encodeURIComponent(JSON.stringify(historyresult))
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
									
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							computed: {
 | 
				
			||||||
 | 
								histories() {
 | 
				
			||||||
 | 
									return [...this.historylist].reverse()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss">
 | 
				
			||||||
 | 
						.search-box {
 | 
				
			||||||
 | 
							position: sticky;
 | 
				
			||||||
 | 
							top: 0;
 | 
				
			||||||
 | 
							z-index: 999;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.sugest-list {
 | 
				
			||||||
 | 
							padding: 0 5px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							.sugest-item {
 | 
				
			||||||
 | 
								display: flex;
 | 
				
			||||||
 | 
								align-items: center;
 | 
				
			||||||
 | 
								justify-content: space-between;
 | 
				
			||||||
 | 
								font-size: 12px;
 | 
				
			||||||
 | 
								padding: 13px 0;
 | 
				
			||||||
 | 
								border-bottom: 1 px solid #efefef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								.dish-name {
 | 
				
			||||||
 | 
									white-space: nowrap;
 | 
				
			||||||
 | 
									overflow: hidden;
 | 
				
			||||||
 | 
									text-overflow: ellipsis;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.history-box {
 | 
				
			||||||
 | 
							padding: 0 5px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							.history-title {
 | 
				
			||||||
 | 
								display: flex;
 | 
				
			||||||
 | 
								justify-content: space-between;
 | 
				
			||||||
 | 
								height: 40px;
 | 
				
			||||||
 | 
								align-items: center;
 | 
				
			||||||
 | 
								font-size: 13px;
 | 
				
			||||||
 | 
								border-bottom: 1px solid #efefef;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							.history-list {
 | 
				
			||||||
 | 
								display: flex;
 | 
				
			||||||
 | 
								flex-wrap: wrap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								.uni-tag {
 | 
				
			||||||
 | 
									margin-top: 5px;
 | 
				
			||||||
 | 
									margin-right: 5px;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						.search{
 | 
				
			||||||
 | 
							height: 50rpx;
 | 
				
			||||||
 | 
							width: 200rpx;
 | 
				
			||||||
 | 
							font-size: 20rpx;
 | 
				
			||||||
 | 
							justify-content: center;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
@ -0,0 +1,83 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<view>
 | 
				
			||||||
 | 
							<view class="search-list" v-for="data in dishList" :key="data._id">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								<view class="dish-item" @click="goToDetail(data)">
 | 
				
			||||||
 | 
									<image class="dish-image" :src="data.dish_src"></image>
 | 
				
			||||||
 | 
								</view>
 | 
				
			||||||
 | 
								<view class="dish-intro">
 | 
				
			||||||
 | 
									<text>{{'菜名:' +  data.dish_name + '\n'}}</text>
 | 
				
			||||||
 | 
									<text>{{'地点:' +  data.location + '\n'}}</text>
 | 
				
			||||||
 | 
									<text>{{'窗口:' +  data.window_name + '\n'}}</text>
 | 
				
			||||||
 | 
									<text>{{'评分:' +  data.avg_score + '\n'}}</text>
 | 
				
			||||||
 | 
								</view>
 | 
				
			||||||
 | 
							</view>
 | 
				
			||||||
 | 
						</view>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script>
 | 
				
			||||||
 | 
						export default {
 | 
				
			||||||
 | 
							data() {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									dishList: []
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							onLoad(e) {
 | 
				
			||||||
 | 
								let that = this
 | 
				
			||||||
 | 
								uni.$on('item', (res) => {
 | 
				
			||||||
 | 
									that.dishList = res
 | 
				
			||||||
 | 
									console.log(res)
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								//this.dishList = JSON.parse(decodeURIComponent(e.searchlist))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							methods:{
 | 
				
			||||||
 | 
								goToDetail(item) {
 | 
				
			||||||
 | 
									console.log(item._id)
 | 
				
			||||||
 | 
									uni.navigateTo({
 | 
				
			||||||
 | 
										url: '/subpkg/dishDetail/dishDetail?_id=' +encodeURIComponent(JSON.stringify(item._id)) 
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="scss">
 | 
				
			||||||
 | 
						.search-list {
 | 
				
			||||||
 | 
							padding-left: 5rpx;
 | 
				
			||||||
 | 
							padding-right: 5rpx;
 | 
				
			||||||
 | 
							border-style: solid;
 | 
				
			||||||
 | 
							border-radius: 5px;
 | 
				
			||||||
 | 
							border-color: #65654b;
 | 
				
			||||||
 | 
							border-width: 3rpx;
 | 
				
			||||||
 | 
							display: flex;
 | 
				
			||||||
 | 
							justify-content: space-around;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.dish-intro {
 | 
				
			||||||
 | 
							padding-left: 5rpx;
 | 
				
			||||||
 | 
							padding-right: 5rpx;
 | 
				
			||||||
 | 
							border-style: solid;
 | 
				
			||||||
 | 
							border-radius: 5px;
 | 
				
			||||||
 | 
							border-color: #65654b;
 | 
				
			||||||
 | 
							border-width: 3rpx;
 | 
				
			||||||
 | 
							display: flex;
 | 
				
			||||||
 | 
							flex-direction: column;
 | 
				
			||||||
 | 
							justify-content: center;
 | 
				
			||||||
 | 
							height: 256rpx;
 | 
				
			||||||
 | 
							font-size: 18rpx;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.dish-image {
 | 
				
			||||||
 | 
							padding-left: 5rpx;
 | 
				
			||||||
 | 
							padding-right: 5rpx;
 | 
				
			||||||
 | 
							border-style: solid;
 | 
				
			||||||
 | 
							border-radius: 5px;
 | 
				
			||||||
 | 
							border-color: #65654b;
 | 
				
			||||||
 | 
							border-width: 3rpx;
 | 
				
			||||||
 | 
							width: 475rpx;
 | 
				
			||||||
 | 
							height: 256rpx;
 | 
				
			||||||
 | 
							display: flex;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					exports.main = async (event, context) => {
 | 
				
			||||||
 | 
						//event为客户端上传的参数
 | 
				
			||||||
 | 
						const db = uniCloud.database()
 | 
				
			||||||
 | 
						const res = await db.collection('user-label').where({token:event.token}).get()
 | 
				
			||||||
 | 
						console.log(res.data[0].label_id[0])
 | 
				
			||||||
 | 
						return res
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "name": "ArrayTest",
 | 
				
			||||||
 | 
					  "dependencies": {},
 | 
				
			||||||
 | 
					  "extensions": {
 | 
				
			||||||
 | 
					    "uni-cloud-jql": {}
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					const {
 | 
				
			||||||
 | 
						createApi
 | 
				
			||||||
 | 
					} = require('./shared/index')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let reportDataReceiver, dataStatCron
 | 
				
			||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
						//uni统计数据上报数据接收器初始化
 | 
				
			||||||
 | 
						initReceiver: (options = {}) => {
 | 
				
			||||||
 | 
							if(!reportDataReceiver) {
 | 
				
			||||||
 | 
								reportDataReceiver = require('./stat/receiver')
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							options.clientType = options.clientType || __ctx__.PLATFORM
 | 
				
			||||||
 | 
							return createApi(reportDataReceiver, options)
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						//uni统计数据统计模块初始化
 | 
				
			||||||
 | 
						initStat: (options = {}) => {
 | 
				
			||||||
 | 
							if(!dataStatCron) {
 | 
				
			||||||
 | 
								dataStatCron = require('./stat/stat')
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							options.clientType = options.clientType || __ctx__.PLATFORM
 | 
				
			||||||
 | 
							return createApi(dataStatCron, options)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "name": "uni-stat",
 | 
				
			||||||
 | 
					    "version": "1.0.0",
 | 
				
			||||||
 | 
					    "lockfileVersion": 1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "name": "uni-stat",
 | 
				
			||||||
 | 
					  "version": "1.0.0",
 | 
				
			||||||
 | 
					  "description": "",
 | 
				
			||||||
 | 
					  "main": "index.js",
 | 
				
			||||||
 | 
					  "scripts": {
 | 
				
			||||||
 | 
					    "test": "echo \"Error: no test specified\" && exit 1"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "keywords": [],
 | 
				
			||||||
 | 
					  "author": "",
 | 
				
			||||||
 | 
					  "license": "ISC",
 | 
				
			||||||
 | 
					  "dependencies": {
 | 
				
			||||||
 | 
					    "uni-config-center": "file:../../../../uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center"
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @class UniCloudError 错误处理模块
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					module.exports = class UniCloudError extends Error {
 | 
				
			||||||
 | 
					  constructor (options) {
 | 
				
			||||||
 | 
					    super(options.message)
 | 
				
			||||||
 | 
					    this.errMsg = options.message || ''
 | 
				
			||||||
 | 
					    Object.defineProperties(this, {
 | 
				
			||||||
 | 
					      message: {
 | 
				
			||||||
 | 
					        get () {
 | 
				
			||||||
 | 
					          return `errCode: ${options.code || ''} | errMsg: ` + this.errMsg
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        set (msg) {
 | 
				
			||||||
 | 
					          this.errMsg = msg
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
						UniCloudError: require('./error'),
 | 
				
			||||||
 | 
						createApi: require('./create-api'),
 | 
				
			||||||
 | 
						... require('./utils')
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
						DateTime: require('./date'),
 | 
				
			||||||
 | 
						UniCrypto: require('./uni-crypto')
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @class AppCrashLogs 原生应用崩溃日志模型
 | 
				
			||||||
 | 
					 * @function clean 原生应用崩溃日志清理函数
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const BaseMod = require('./base')
 | 
				
			||||||
 | 
					const {
 | 
				
			||||||
 | 
						DateTime,
 | 
				
			||||||
 | 
						UniCrypto
 | 
				
			||||||
 | 
					} = require('../lib')
 | 
				
			||||||
 | 
					module.exports = class AppCrashLogs extends BaseMod {
 | 
				
			||||||
 | 
						constructor() {
 | 
				
			||||||
 | 
							super()
 | 
				
			||||||
 | 
							this.tableName = 'app-crash-logs'
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * 原生应用崩溃日志清理函数
 | 
				
			||||||
 | 
						 * @param {Number} days 保留天数
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						async clean(days = 7) {
 | 
				
			||||||
 | 
							days = Math.max(parseInt(days), 1)
 | 
				
			||||||
 | 
							console.log('clean app crash logs - day:', days)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const dateTime = new DateTime()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const res = await this.delete(this.tableName, {
 | 
				
			||||||
 | 
								create_time: {
 | 
				
			||||||
 | 
									$lt: dateTime.getTimeBySetDays(0 - days)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!res.code) {
 | 
				
			||||||
 | 
								console.log('clean app crash log:', res)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return res
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,107 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @class Channel 渠道模型
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const BaseMod = require('./base')
 | 
				
			||||||
 | 
					const Scenes = require('./scenes')
 | 
				
			||||||
 | 
					const {
 | 
				
			||||||
 | 
						DateTime
 | 
				
			||||||
 | 
					} = require('../lib')
 | 
				
			||||||
 | 
					module.exports = class Channel extends BaseMod {
 | 
				
			||||||
 | 
						constructor() {
 | 
				
			||||||
 | 
							super()
 | 
				
			||||||
 | 
							this.tableName = 'app-channels'
 | 
				
			||||||
 | 
							this.scenes = new Scenes()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * 获取渠道信息
 | 
				
			||||||
 | 
						 * @param {String} appid
 | 
				
			||||||
 | 
						 * @param {String} platformId 平台编号
 | 
				
			||||||
 | 
						 * @param {String} channel 渠道代码
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						async getChannel(appid, platformId, channel) {
 | 
				
			||||||
 | 
							const cacheKey = 'uni-stat-channel-' + appid + '-' + platformId + '-' + channel
 | 
				
			||||||
 | 
							let channelData = await this.getCache(cacheKey)
 | 
				
			||||||
 | 
							if (!channelData) {
 | 
				
			||||||
 | 
								const channelInfo = await this.getCollection(this.tableName).where({
 | 
				
			||||||
 | 
									appid: appid,
 | 
				
			||||||
 | 
									platform_id: platformId,
 | 
				
			||||||
 | 
									channel_code: channel
 | 
				
			||||||
 | 
								}).limit(1).get()
 | 
				
			||||||
 | 
								channelData = []
 | 
				
			||||||
 | 
								if (channelInfo.data.length > 0) {
 | 
				
			||||||
 | 
									channelData = channelInfo.data[0]
 | 
				
			||||||
 | 
									if (channelData.channel_name === '') {
 | 
				
			||||||
 | 
										const scenesName = await this.scenes.getScenesNameByPlatformId(platformId, channel)
 | 
				
			||||||
 | 
										if (scenesName) {
 | 
				
			||||||
 | 
											await this.update(this.tableName, {
 | 
				
			||||||
 | 
												channel_name: scenesName,
 | 
				
			||||||
 | 
												update_time: new DateTime().getTime()
 | 
				
			||||||
 | 
											}, {
 | 
				
			||||||
 | 
												_id: channelData._id
 | 
				
			||||||
 | 
											})
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									await this.setCache(cacheKey, channelData)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return channelData
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * 获取渠道信息没有则进行创建
 | 
				
			||||||
 | 
						 * @param {String} appid
 | 
				
			||||||
 | 
						 * @param {String} platformId
 | 
				
			||||||
 | 
						 * @param {String} channel
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						async getChannelAndCreate(appid, platformId, channel) {
 | 
				
			||||||
 | 
							if (!appid || !platformId) {
 | 
				
			||||||
 | 
								return []
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const channelInfo = await this.getChannel(appid, platformId, channel)
 | 
				
			||||||
 | 
							if (channelInfo.length === 0) {
 | 
				
			||||||
 | 
								const thisTime = new DateTime().getTime()
 | 
				
			||||||
 | 
								const insertParam = {
 | 
				
			||||||
 | 
									appid: appid,
 | 
				
			||||||
 | 
									platform_id: platformId,
 | 
				
			||||||
 | 
									channel_code: channel,
 | 
				
			||||||
 | 
									channel_name: await this.scenes.getScenesNameByPlatformId(platformId, channel),
 | 
				
			||||||
 | 
									create_time: thisTime,
 | 
				
			||||||
 | 
									update_time: thisTime
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								const res = await this.insert(this.tableName, insertParam)
 | 
				
			||||||
 | 
								if (res && res.id) {
 | 
				
			||||||
 | 
									return Object.assign(insertParam, {
 | 
				
			||||||
 | 
										_id: res.id
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return channelInfo
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * 获取渠道_id
 | 
				
			||||||
 | 
						 * @param {String} appid
 | 
				
			||||||
 | 
						 * @param {String} platformId
 | 
				
			||||||
 | 
						 * @param {String} channel
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						async getChannelId(appid, platformId, channel) {
 | 
				
			||||||
 | 
							const channelInfo = await this.getChannel(appid, platformId, channel)
 | 
				
			||||||
 | 
							return channelInfo.length > 0 ? channelInfo._id : ''
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * 获取渠道码或者场景值
 | 
				
			||||||
 | 
						 * @param {Object} params 上报参数
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						getChannelCode(params) {
 | 
				
			||||||
 | 
							//小程序未上报渠道则使用场景值
 | 
				
			||||||
 | 
							if (params.ch) {
 | 
				
			||||||
 | 
								return params.ch
 | 
				
			||||||
 | 
							} else if (params.sc && params.ut.indexOf('mp-') === 0) {
 | 
				
			||||||
 | 
								return params.sc
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return this.scenes.defualtCode
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,184 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @class Device 设备模型
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const BaseMod = require('./base')
 | 
				
			||||||
 | 
					const Platform = require('./platform')
 | 
				
			||||||
 | 
					const {
 | 
				
			||||||
 | 
						DateTime
 | 
				
			||||||
 | 
					} = require('../lib')
 | 
				
			||||||
 | 
					module.exports = class Device extends BaseMod {
 | 
				
			||||||
 | 
						constructor() {
 | 
				
			||||||
 | 
							super()
 | 
				
			||||||
 | 
							this.tableName = 'opendb-device'
 | 
				
			||||||
 | 
							this.tablePrefix = false
 | 
				
			||||||
 | 
							this.cacheKeyPre = 'uni-stat-device-'
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * 通过设备编号获取设备信息
 | 
				
			||||||
 | 
						 * @param {Object} deviceId 设备编号
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						async getDeviceById(deviceId) {
 | 
				
			||||||
 | 
							const cacheKey = this.cacheKeyPre + deviceId
 | 
				
			||||||
 | 
							let deviceData = await this.getCache(cacheKey)
 | 
				
			||||||
 | 
							if (!deviceData) {
 | 
				
			||||||
 | 
								const deviceRes = await this.getCollection().where({
 | 
				
			||||||
 | 
									device_id: deviceId
 | 
				
			||||||
 | 
								}).get()
 | 
				
			||||||
 | 
								deviceData = []
 | 
				
			||||||
 | 
								if (deviceRes.data.length > 0) {
 | 
				
			||||||
 | 
									deviceData = deviceRes.data[0]
 | 
				
			||||||
 | 
									await this.setCache(cacheKey, deviceData)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return deviceData
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * 设置设备信息
 | 
				
			||||||
 | 
						 * @param {Object} params 上报参数
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						async setDevice(params) {
 | 
				
			||||||
 | 
							// 设备信息
 | 
				
			||||||
 | 
							if (!params.did) {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									code: 200,
 | 
				
			||||||
 | 
									msg: 'Parameter "did" not found'
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							const deviceData = await this.getDeviceById(params.did)
 | 
				
			||||||
 | 
							//不存在则添加
 | 
				
			||||||
 | 
							if(deviceData.length === 0) {
 | 
				
			||||||
 | 
								return await this.addDevice(params)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								return await this.updateDevice(params, deviceData)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * 添加设备信息
 | 
				
			||||||
 | 
						 * @param {Object} params 上报参数
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						async addDevice(params) {
 | 
				
			||||||
 | 
							const dateTime = new DateTime()
 | 
				
			||||||
 | 
							const platform = new Platform()
 | 
				
			||||||
 | 
							const fillParams = {
 | 
				
			||||||
 | 
								device_id: params.did,
 | 
				
			||||||
 | 
								appid: params.ak,
 | 
				
			||||||
 | 
								vendor: params.brand ? params.brand : '',
 | 
				
			||||||
 | 
								push_clientid: params.cid ? params.cid : '',
 | 
				
			||||||
 | 
								imei: params.imei ? params.imei : '',
 | 
				
			||||||
 | 
								oaid: params.oaid ? params.oaid : '',
 | 
				
			||||||
 | 
								idfa: params.idfa ? params.idfa : '',
 | 
				
			||||||
 | 
								imsi: params.imsi ? params.imsi : '',
 | 
				
			||||||
 | 
								model: params.md ? params.md : '',
 | 
				
			||||||
 | 
								uni_platform: params.up ? params.up : '',
 | 
				
			||||||
 | 
								os_name: params.on ? params.on : platform.getOsName(params.p),
 | 
				
			||||||
 | 
								os_version: params.sv ? params.sv : '',
 | 
				
			||||||
 | 
								os_language: params.lang ? params.lang : '',
 | 
				
			||||||
 | 
								os_theme: params.ot ? params.ot : '',
 | 
				
			||||||
 | 
								pixel_ratio: params.pr ? params.pr : '',
 | 
				
			||||||
 | 
								network_model: params.net ? params.net : '',
 | 
				
			||||||
 | 
								window_width: params.ww ? params.ww : '',
 | 
				
			||||||
 | 
								window_height: params.wh ? params.wh : '',
 | 
				
			||||||
 | 
								screen_width: params.sw ? params.sw : '',
 | 
				
			||||||
 | 
								screen_height: params.sh ? params.sh : '',
 | 
				
			||||||
 | 
								rom_name: params.rn ? params.rn : '',
 | 
				
			||||||
 | 
								rom_version: params.rv ? params.rv : '',
 | 
				
			||||||
 | 
								location_ip: params.ip ? params.ip : '',
 | 
				
			||||||
 | 
								location_latitude: params.lat ? parseFloat(params.lat) : 0,
 | 
				
			||||||
 | 
								location_longitude: params.lng ? parseFloat(params.lng) : 0,
 | 
				
			||||||
 | 
								location_country: params.cn ? params.cn : '',
 | 
				
			||||||
 | 
								location_province: params.pn ? params.pn : '',
 | 
				
			||||||
 | 
								location_city: params.ct ? params.ct : '',
 | 
				
			||||||
 | 
								create_date: dateTime.getTime(),
 | 
				
			||||||
 | 
								last_update_date: dateTime.getTime()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							const res = await this.insert(this.tableName, fillParams)
 | 
				
			||||||
 | 
							if (res && res.id) {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									code: 0,
 | 
				
			||||||
 | 
									msg: 'success',
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									code: 500,
 | 
				
			||||||
 | 
									msg: 'Device data filled error'
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * 修改设备信息
 | 
				
			||||||
 | 
						 * @param {Object} params
 | 
				
			||||||
 | 
						 * @param {Object} deviceData
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						async updateDevice(params, deviceData) {
 | 
				
			||||||
 | 
							//最新的参数
 | 
				
			||||||
 | 
							const dateTime = new DateTime()
 | 
				
			||||||
 | 
							const platform = new Platform()
 | 
				
			||||||
 | 
							console.log('device params', params)
 | 
				
			||||||
 | 
							const newDeviceParams = {
 | 
				
			||||||
 | 
								appid: params.ak,
 | 
				
			||||||
 | 
								push_clientid: params.cid ? params.cid : '',
 | 
				
			||||||
 | 
								imei: params.imei ? params.imei : '',
 | 
				
			||||||
 | 
								oaid: params.oaid ? params.oaid : '',
 | 
				
			||||||
 | 
								idfa: params.idfa ? params.idfa : '',
 | 
				
			||||||
 | 
								imsi: params.imsi ? params.imsi : '',
 | 
				
			||||||
 | 
								uni_platform: params.up ? params.up : '',
 | 
				
			||||||
 | 
								os_name: params.on ? params.on : platform.getOsName(params.p),
 | 
				
			||||||
 | 
								os_version: params.sv ? params.sv : '',
 | 
				
			||||||
 | 
								os_language: params.lang ? params.lang : '',
 | 
				
			||||||
 | 
								pixel_ratio: params.pr ? params.pr : '',
 | 
				
			||||||
 | 
								network_model: params.net ? params.net : '',
 | 
				
			||||||
 | 
								window_width: params.ww ? params.ww : '',
 | 
				
			||||||
 | 
								window_height: params.wh ? params.wh : '',
 | 
				
			||||||
 | 
								screen_width: params.sw ? params.sw : '',
 | 
				
			||||||
 | 
								screen_height: params.sh ? params.sh : '',
 | 
				
			||||||
 | 
								rom_name: params.rn ? params.rn : '',
 | 
				
			||||||
 | 
								rom_version: params.rv ? params.rv : '',
 | 
				
			||||||
 | 
								location_ip: params.ip ? params.ip : '',
 | 
				
			||||||
 | 
								location_latitude: params.lat ? parseFloat(params.lat) : '',
 | 
				
			||||||
 | 
								location_longitude: params.lng ? parseFloat(params.lng) : '',
 | 
				
			||||||
 | 
								location_country: params.cn ? params.cn : '',
 | 
				
			||||||
 | 
								location_province: params.pn ? params.pn : '',
 | 
				
			||||||
 | 
								location_city: params.ct ? params.ct : '',
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//检查是否有需要更新的数据
 | 
				
			||||||
 | 
							const updateData = {}
 | 
				
			||||||
 | 
							for(let key in newDeviceParams) {
 | 
				
			||||||
 | 
								if(newDeviceParams[key] && newDeviceParams[key] !== deviceData[key]) {
 | 
				
			||||||
 | 
									updateData[key] = newDeviceParams[key]
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							if(Object.keys(updateData).length) {
 | 
				
			||||||
 | 
								if(this.debug) {
 | 
				
			||||||
 | 
									console.log('Device need to update', updateData)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								//数据更新
 | 
				
			||||||
 | 
								updateData.last_update_date = dateTime.getTime()
 | 
				
			||||||
 | 
								await this.update(this.tableName, updateData, {device_id: params.did})
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if(this.debug) {
 | 
				
			||||||
 | 
									console.log('Device not need update', newDeviceParams)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return {
 | 
				
			||||||
 | 
								code: 0,
 | 
				
			||||||
 | 
								msg: 'success'
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						async bindPush(params) {
 | 
				
			||||||
 | 
							if (!params.cid) {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									code: 200,
 | 
				
			||||||
 | 
									msg: 'Parameter "cid" not found'
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return await this.setDevice(params)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,141 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @class ErrorLog 错误日志模型
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const BaseMod = require('./base')
 | 
				
			||||||
 | 
					const Platform = require('./platform')
 | 
				
			||||||
 | 
					const Channel = require('./channel')
 | 
				
			||||||
 | 
					const {
 | 
				
			||||||
 | 
						DateTime,
 | 
				
			||||||
 | 
						UniCrypto
 | 
				
			||||||
 | 
					} = require('../lib')
 | 
				
			||||||
 | 
					module.exports = class ErrorLog extends BaseMod {
 | 
				
			||||||
 | 
						constructor() {
 | 
				
			||||||
 | 
							super()
 | 
				
			||||||
 | 
							this.tableName = 'error-logs'
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * 错误日志数据填充
 | 
				
			||||||
 | 
						 * @param {Object} reportParams 上报参数
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						async fill(reportParams) {
 | 
				
			||||||
 | 
							let params, errorHash, errorCount, cacheKey;
 | 
				
			||||||
 | 
							const fillParams = []
 | 
				
			||||||
 | 
							const platform = new Platform()
 | 
				
			||||||
 | 
							const dateTime = new DateTime()
 | 
				
			||||||
 | 
							const uniCrypto = new UniCrypto()
 | 
				
			||||||
 | 
							const channel = new Channel()
 | 
				
			||||||
 | 
							const {
 | 
				
			||||||
 | 
								needCheck,
 | 
				
			||||||
 | 
								checkTime
 | 
				
			||||||
 | 
							} = this.getConfig('errorCheck')
 | 
				
			||||||
 | 
							const errorCheckTime = Math.max(checkTime, 1)
 | 
				
			||||||
 | 
							let spaceId
 | 
				
			||||||
 | 
							let spaceProvider
 | 
				
			||||||
 | 
							for (const rk in reportParams) {
 | 
				
			||||||
 | 
								params = reportParams[rk]
 | 
				
			||||||
 | 
								errorHash = uniCrypto.md5(params.em)
 | 
				
			||||||
 | 
								cacheKey = 'error-count-' + errorHash
 | 
				
			||||||
 | 
								// 校验在指定时间段内是否已存在相同的错误项
 | 
				
			||||||
 | 
								if (needCheck) {
 | 
				
			||||||
 | 
									errorCount = await this.getCache(cacheKey)
 | 
				
			||||||
 | 
									if (!errorCount) {
 | 
				
			||||||
 | 
										errorCount = await this.getCollection(this.tableName).where({
 | 
				
			||||||
 | 
											error_hash: errorHash,
 | 
				
			||||||
 | 
											create_time: {
 | 
				
			||||||
 | 
												$gte: dateTime.getTime() - errorCheckTime * 60000
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}).count()
 | 
				
			||||||
 | 
										if (errorCount && errorCount.total > 0) {
 | 
				
			||||||
 | 
											await this.setCache(cacheKey, errorCount, errorCheckTime * 60)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (errorCount && errorCount.total > 0) {
 | 
				
			||||||
 | 
										if (this.debug) {
 | 
				
			||||||
 | 
											console.log('This error have already existsed: ' + params.em)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										continue
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//获取云端信息
 | 
				
			||||||
 | 
								spaceId = null
 | 
				
			||||||
 | 
								spaceProvider = null
 | 
				
			||||||
 | 
								if (params.spi) {
 | 
				
			||||||
 | 
									//云函数调用参数
 | 
				
			||||||
 | 
									spaceId = params.spi.spaceId
 | 
				
			||||||
 | 
									spaceProvider = params.spi.provider
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									//云对象调用参数
 | 
				
			||||||
 | 
									if (params.spid) {
 | 
				
			||||||
 | 
										spaceId = params.spid
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if (params.sppd) {
 | 
				
			||||||
 | 
										spaceProvider = params.sppd
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// 填充数据
 | 
				
			||||||
 | 
								fillParams.push({
 | 
				
			||||||
 | 
									appid: params.ak,
 | 
				
			||||||
 | 
									version: params.v ? params.v : '',
 | 
				
			||||||
 | 
									platform: platform.getPlatformCode(params.ut, params.p),
 | 
				
			||||||
 | 
									channel: channel.getChannelCode(params),
 | 
				
			||||||
 | 
									device_id: params.did,
 | 
				
			||||||
 | 
									uid: params.uid ? params.uid : '',
 | 
				
			||||||
 | 
									os: params.on ? params.on : platform.getOsName(params.p),
 | 
				
			||||||
 | 
									ua: params.ua ? params.ua : '',
 | 
				
			||||||
 | 
									page_url: params.url ? params.url : '',
 | 
				
			||||||
 | 
									space_id: spaceId ? spaceId : '',
 | 
				
			||||||
 | 
									space_provider: spaceProvider ? spaceProvider : '',
 | 
				
			||||||
 | 
									platform_version: params.mpv ? params.mpv : '',
 | 
				
			||||||
 | 
									error_msg: params.em ? params.em : '',
 | 
				
			||||||
 | 
									error_hash: errorHash,
 | 
				
			||||||
 | 
									create_time: dateTime.getTime()
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (fillParams.length === 0) {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									code: 200,
 | 
				
			||||||
 | 
									msg: 'Invild param'
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const res = await this.insert(this.tableName, fillParams)
 | 
				
			||||||
 | 
							if (res && res.inserted) {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									code: 0,
 | 
				
			||||||
 | 
									msg: 'success'
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									code: 500,
 | 
				
			||||||
 | 
									msg: 'Filled error'
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * 错误日志清理
 | 
				
			||||||
 | 
						 * @param {Number} days 日志保留天数
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						async clean(days) {
 | 
				
			||||||
 | 
							days = Math.max(parseInt(days), 1)
 | 
				
			||||||
 | 
							console.log('clean error logs - day:', days)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const dateTime = new DateTime()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const res = await this.delete(this.tableName, {
 | 
				
			||||||
 | 
								create_time: {
 | 
				
			||||||
 | 
									$lt: dateTime.getTimeBySetDays(0 - days)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!res.code) {
 | 
				
			||||||
 | 
								console.log('clean error log:', res)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return res
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,72 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @class StatEvent 事件统计模型
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const BaseMod = require('./base')
 | 
				
			||||||
 | 
					const {
 | 
				
			||||||
 | 
						DateTime
 | 
				
			||||||
 | 
					} = require('../lib')
 | 
				
			||||||
 | 
					module.exports = class StatEvent extends BaseMod {
 | 
				
			||||||
 | 
						constructor() {
 | 
				
			||||||
 | 
							super()
 | 
				
			||||||
 | 
							this.tableName = 'events'
 | 
				
			||||||
 | 
							this.defaultEvent = this.getConfig('event') || {
 | 
				
			||||||
 | 
								login: '登录',
 | 
				
			||||||
 | 
								register: '注册',
 | 
				
			||||||
 | 
								click: '点击',
 | 
				
			||||||
 | 
								share: '分享',
 | 
				
			||||||
 | 
								pay_success: '支付成功',
 | 
				
			||||||
 | 
								pay_fail: '支付失败'
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * 获取事件信息
 | 
				
			||||||
 | 
						 * @param {String} appid: DCloud appid
 | 
				
			||||||
 | 
						 * @param {String} eventKey 事件键值
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						async getEvent(appid, eventKey) {
 | 
				
			||||||
 | 
							const cacheKey = 'uni-stat-event-' + appid + '-' + eventKey
 | 
				
			||||||
 | 
							let eventData = await this.getCache(cacheKey)
 | 
				
			||||||
 | 
							if (!eventData) {
 | 
				
			||||||
 | 
								const eventInfo = await this.getCollection(this.tableName).where({
 | 
				
			||||||
 | 
									appid: appid,
 | 
				
			||||||
 | 
									event_key: eventKey
 | 
				
			||||||
 | 
								}).get()
 | 
				
			||||||
 | 
								eventData = []
 | 
				
			||||||
 | 
								if (eventInfo.data.length > 0) {
 | 
				
			||||||
 | 
									eventData = eventInfo.data[0]
 | 
				
			||||||
 | 
									await this.setCache(cacheKey, eventData)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return eventData
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * 获取事件信息不存在则创建
 | 
				
			||||||
 | 
						 * @param {String} appid: DCloud appid
 | 
				
			||||||
 | 
						 * @param {String} eventKey 事件键值
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						async getEventAndCreate(appid, eventKey) {
 | 
				
			||||||
 | 
							const eventInfo = await this.getEvent(appid, eventKey)
 | 
				
			||||||
 | 
							if (eventInfo.length === 0) {
 | 
				
			||||||
 | 
								const thisTime = new DateTime().getTime()
 | 
				
			||||||
 | 
								const insertParam = {
 | 
				
			||||||
 | 
									appid: appid,
 | 
				
			||||||
 | 
									event_key: eventKey,
 | 
				
			||||||
 | 
									event_name: this.defaultEvent[eventKey] ? this.defaultEvent[eventKey] : '',
 | 
				
			||||||
 | 
									create_time: thisTime,
 | 
				
			||||||
 | 
									update_time: thisTime
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								const res = await this.insert(this.tableName, insertParam)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (res && res.id) {
 | 
				
			||||||
 | 
									return Object.assign(insertParam, {
 | 
				
			||||||
 | 
										_id: res.id
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return eventInfo
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,156 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @class EventLog 事件日志模型
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const BaseMod = require('./base')
 | 
				
			||||||
 | 
					const Platform = require('./platform')
 | 
				
			||||||
 | 
					const Channel = require('./channel')
 | 
				
			||||||
 | 
					const StatEvent = require('./event')
 | 
				
			||||||
 | 
					const SessionLog = require('./sessionLog')
 | 
				
			||||||
 | 
					const ShareLog = require('./shareLog')
 | 
				
			||||||
 | 
					const {
 | 
				
			||||||
 | 
						DateTime
 | 
				
			||||||
 | 
					} = require('../lib')
 | 
				
			||||||
 | 
					module.exports = class EventLog extends BaseMod {
 | 
				
			||||||
 | 
						constructor() {
 | 
				
			||||||
 | 
							super()
 | 
				
			||||||
 | 
							this.tableName = 'event-logs'
 | 
				
			||||||
 | 
							this.sessionLogInfo = []
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * 事件日志填充
 | 
				
			||||||
 | 
						 * @param {Object} reportParams 上报参数
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						async fill(reportParams) {
 | 
				
			||||||
 | 
							let params;
 | 
				
			||||||
 | 
							let sessionKey, sessionLogKey;
 | 
				
			||||||
 | 
							let sessionLogInfo;
 | 
				
			||||||
 | 
							const sessionData = []
 | 
				
			||||||
 | 
							const fillParams = []
 | 
				
			||||||
 | 
							const shareParams = []
 | 
				
			||||||
 | 
							const sessionLog = new SessionLog()
 | 
				
			||||||
 | 
							const event = new StatEvent()
 | 
				
			||||||
 | 
							const platform = new Platform()
 | 
				
			||||||
 | 
							const dateTime = new DateTime()
 | 
				
			||||||
 | 
							const channel = new Channel()
 | 
				
			||||||
 | 
							for (const rk in reportParams) {
 | 
				
			||||||
 | 
								params = reportParams[rk]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//暂存下会话数据,减少读库
 | 
				
			||||||
 | 
								sessionKey = params.ak + params.did + params.p
 | 
				
			||||||
 | 
								if (!this.sessionLogInfo[sessionKey]) {
 | 
				
			||||||
 | 
									// 会话日志
 | 
				
			||||||
 | 
									sessionLogInfo = await sessionLog.getSession(params)
 | 
				
			||||||
 | 
									if (sessionLogInfo.code) {
 | 
				
			||||||
 | 
										return sessionLogInfo
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if (this.debug) {
 | 
				
			||||||
 | 
										console.log('sessionLogInfo', JSON.stringify(sessionLogInfo))
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									this.sessionLogInfo[sessionKey] = sessionLogInfo
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									sessionLogInfo = this.sessionLogInfo[sessionKey]
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// 会话数据
 | 
				
			||||||
 | 
								sessionLogKey = sessionLogInfo.data.sessionLogId.toString()
 | 
				
			||||||
 | 
								if (!sessionData[sessionLogKey]) {
 | 
				
			||||||
 | 
									sessionData[sessionLogKey] = {
 | 
				
			||||||
 | 
										eventCount: sessionLogInfo.data.eventCount + 1,
 | 
				
			||||||
 | 
										addEventCount: 1,
 | 
				
			||||||
 | 
										uid: sessionLogInfo.data.uid,
 | 
				
			||||||
 | 
										createTime: sessionLogInfo.data.createTime
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									sessionData[sessionLogKey].eventCount++
 | 
				
			||||||
 | 
									sessionData[sessionLogKey].addEventCount++
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// 事件
 | 
				
			||||||
 | 
								const eventInfo = await event.getEventAndCreate(params.ak, params.e_n)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// 填充数据
 | 
				
			||||||
 | 
								fillParams.push({
 | 
				
			||||||
 | 
									appid: params.ak,
 | 
				
			||||||
 | 
									version: params.v ? params.v : '',
 | 
				
			||||||
 | 
									platform: platform.getPlatformCode(params.ut, params.p),
 | 
				
			||||||
 | 
									channel: channel.getChannelCode(params),
 | 
				
			||||||
 | 
									device_id: params.did,
 | 
				
			||||||
 | 
									uid: params.uid ? params.uid : '',
 | 
				
			||||||
 | 
									session_id: sessionLogInfo.data.sessionLogId,
 | 
				
			||||||
 | 
									page_id: sessionLogInfo.data.pageId,
 | 
				
			||||||
 | 
									event_key: eventInfo.event_key,
 | 
				
			||||||
 | 
									param: params.e_v ? params.e_v : '',
 | 
				
			||||||
 | 
									// 版本
 | 
				
			||||||
 | 
									sdk_version: params.mpsdk ? params.mpsdk : '',
 | 
				
			||||||
 | 
									platform_version: params.mpv ? params.mpv : '',
 | 
				
			||||||
 | 
									// 设备相关
 | 
				
			||||||
 | 
									device_os_name: params.on ? params.on : platform.getOsName(params.p),
 | 
				
			||||||
 | 
									device_os_version: params.sv ? params.sv : '',
 | 
				
			||||||
 | 
									device_vendor: params.brand ? params.brand : '',
 | 
				
			||||||
 | 
									device_model: params.md ? params.md : '',
 | 
				
			||||||
 | 
									device_language: params.lang ? params.lang : '',
 | 
				
			||||||
 | 
									device_pixel_ratio: params.pr ? params.pr : '',
 | 
				
			||||||
 | 
									device_window_width: params.ww ? params.ww : '',
 | 
				
			||||||
 | 
									device_window_height: params.wh ? params.wh : '',
 | 
				
			||||||
 | 
									device_screen_width: params.sw ? params.sw : '',
 | 
				
			||||||
 | 
									device_screen_height: params.sh ? params.sh : '',
 | 
				
			||||||
 | 
									create_time: dateTime.getTime()
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								// 分享数据
 | 
				
			||||||
 | 
								if (eventInfo.event_key === 'share') {
 | 
				
			||||||
 | 
									shareParams.push(params)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (fillParams.length === 0) {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									code: 200,
 | 
				
			||||||
 | 
									msg: 'Invild param'
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (shareParams.length > 0) {
 | 
				
			||||||
 | 
								const shareLog = new ShareLog()
 | 
				
			||||||
 | 
								await shareLog.fill(shareParams, this.sessionLogInfo)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const res = await this.insert(this.tableName, fillParams)
 | 
				
			||||||
 | 
							if (res && res.inserted) {
 | 
				
			||||||
 | 
								for (const sid in sessionData) {
 | 
				
			||||||
 | 
									await sessionLog.updateSession(sid, sessionData[sid])
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									code: 0,
 | 
				
			||||||
 | 
									msg: 'success'
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								return {
 | 
				
			||||||
 | 
									code: 500,
 | 
				
			||||||
 | 
									msg: 'Filled error'
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * 事件日志清理
 | 
				
			||||||
 | 
						 * @param {Number} days 保留天数
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						async clean(days) {
 | 
				
			||||||
 | 
							days = Math.max(parseInt(days), 1)
 | 
				
			||||||
 | 
							console.log('clean event logs - day:', days)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							const dateTime = new DateTime()
 | 
				
			||||||
 | 
							//删除过期数据
 | 
				
			||||||
 | 
							const res = await this.delete(this.tableName, {
 | 
				
			||||||
 | 
								create_time: {
 | 
				
			||||||
 | 
									$lt: dateTime.getTimeBySetDays(0 - days)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!res.code) {
 | 
				
			||||||
 | 
								console.log('clean event log:', res)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return res
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 基础对外模型
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
						BaseMod: require('./base'),
 | 
				
			||||||
 | 
						SessionLog: require('./sessionLog'),
 | 
				
			||||||
 | 
						UserSessionLog: require('./userSessionLog'),
 | 
				
			||||||
 | 
						PageLog: require('./pageLog'),
 | 
				
			||||||
 | 
						EventLog: require('./eventLog'),
 | 
				
			||||||
 | 
						ShareLog: require('./shareLog'),
 | 
				
			||||||
 | 
						ErrorLog: require('./errorLog'),
 | 
				
			||||||
 | 
						AppCrashLogs: require('./appCrashLogs'),
 | 
				
			||||||
 | 
						StatResult: require('./statResult'),
 | 
				
			||||||
 | 
						ActiveUsers: require('./activeUsers'),
 | 
				
			||||||
 | 
						ActiveDevices: require('./activeDevices'),
 | 
				
			||||||
 | 
						PageResult: require('./pageResult'),
 | 
				
			||||||
 | 
						EventResult: require('./eventResult'),
 | 
				
			||||||
 | 
						ErrorResult: require('./errorResult'),
 | 
				
			||||||
 | 
						Loyalty: require('./loyalty'),
 | 
				
			||||||
 | 
						RunErrors: require('./runErrors'),
 | 
				
			||||||
 | 
						uniPay: require('./uni-pay'),
 | 
				
			||||||
 | 
						Setting: require('./setting'),
 | 
				
			||||||
 | 
					}
 | 
				
			||||||