├── LICENSE ├── README.md ├── app.js ├── app.json ├── app.wxss ├── pages ├── auth │ ├── auth.js │ ├── auth.json │ ├── auth.wxml │ └── auth.wxss ├── index │ ├── index.js │ ├── index.wxml │ └── index.wxss └── logs │ ├── logs.js │ ├── logs.json │ ├── logs.wxml │ └── logs.wxss ├── project.config.json └── utils └── util.js /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### lime_mall 说明文档 2 | 本文档包含中文、The document contains English(In translation) 3 | > 本文档包含中文、The document contains English(In translation) 4 | > 5 | > 欢迎您发起 Pull request! 6 | 7 | 微信小程序(wxapp)点餐系统,提供在线预定、线上支付、外卖配送、到店桌号牌扫码点餐、为同桌买单等功能。 8 | 9 | 10 | ### 项目特色 11 | 12 | 市面上的点餐系统,分为同桌(同码)同号和同桌异号两种,如果接入其中一个,都无法满足所有人的需求。 13 | 14 | 如果接入的是同桌同码,在小面馆中,会发现同桌提交订单时,会把我还没点好的一起提交或者先提交订单的人,把没提交的菜品清空了。 15 | 16 | 为了在一个码中,能够为别人买单,抢别人的单来支付,为别人买部分单,以及各付各的需求。 17 | 18 | 本项目推出为自己点餐和为同桌买单功能。 19 | 20 | 21 | - 为 ta 点餐 22 | 点餐之前,就可以决定谁来买单,点餐前经过友好协商(激烈争取)后通过为ta买单功能进入,则同桌点好菜后,只能由买单人提交订单。 23 | 24 | 在为ta买单功能中,如果对方点的餐实在太多了,买单人可以在购物车中,单独修改某个菜品的买单意愿,比如将锅底修改为均摊,把香菜和折耳根的支付意愿修改为让ta自己付。 25 | 26 | 反之,如果双方都选择了为自己点餐,则购物车互不影响,且需要自行支付餐品费用。 27 | 28 | 29 | 为ta买单功能同样支持用于火锅店的饭前 AA 约定,大家只点自己喜欢吃的菜,最后自己支付自己的菜品费用。 30 | 31 | 32 | - 预测菜品完成时间 33 | 34 | > @Hassan 提供 idea 35 | 36 | 根据菜品平均制造时间和点单队列算法模型实现 0 物联网接入的菜品菜品完成时间预测。 37 | 38 | - 菜品智能推荐 39 | 40 | > @Hassan 提供 idea 41 | 42 | 根据当前制作进行中的菜品进行菜单推荐,要根据库存和你现在正在进行中的菜单进行推荐。 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | ### 联系方式 61 | 62 | 如果想尽快联系我,请添加尝试投递邮件到 -->:kangour@sina.cn 63 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | //app.js 2 | App({ 3 | onLaunch: function () { 4 | // 展示本地存储能力 5 | var logs = wx.getStorageSync('logs') || [] 6 | logs.unshift(Date.now()) 7 | wx.setStorageSync('logs', logs) 8 | 9 | // 登录 10 | wx.login({ 11 | success: res => { 12 | // 发送 res.code 到后台换取 openId, sessionKey, unionId 13 | } 14 | }) 15 | // 获取用户信息 16 | wx.getSetting({ 17 | success: res => { 18 | if (res.authSetting['scope.userInfo']) { 19 | // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框 20 | wx.getUserInfo({ 21 | success: res => { 22 | // 可以将 res 发送给后台解码出 unionId 23 | this.globalData.userInfo = res.userInfo 24 | 25 | // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回 26 | // 所以此处加入 callback 以防止这种情况 27 | if (this.userInfoReadyCallback) { 28 | this.userInfoReadyCallback(res) 29 | } 30 | } 31 | }) 32 | } 33 | } 34 | }) 35 | }, 36 | globalData: { 37 | userInfo: null 38 | } 39 | }) -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages": [ 3 | "pages/index/index", 4 | "pages/logs/logs", 5 | "pages/auth/auth" 6 | ], 7 | "window": { 8 | "backgroundTextStyle": "light", 9 | "navigationBarBackgroundColor": "#fff", 10 | "navigationBarTitleText": "WeChat", 11 | "navigationBarTextStyle": "black" 12 | } 13 | } -------------------------------------------------------------------------------- /app.wxss: -------------------------------------------------------------------------------- 1 | /**app.wxss**/ 2 | .container { 3 | height: 100%; 4 | display: flex; 5 | flex-direction: column; 6 | align-items: center; 7 | justify-content: space-between; 8 | padding: 200rpx 0; 9 | box-sizing: border-box; 10 | } 11 | -------------------------------------------------------------------------------- /pages/auth/auth.js: -------------------------------------------------------------------------------- 1 | Page({ 2 | data: { 3 | //判断小程序的API,回调,参数,组件等是否在当前版本可用。 4 | canIUse: wx.canIUse('button.open-type.getUserInfo') 5 | }, 6 | onLoad: function () { 7 | var that = this; 8 | // 查看是否授权 9 | wx.getSetting({ 10 | success: function (res) { 11 | if (res.authSetting['scope.userInfo']) { 12 | wx.getUserInfo({ 13 | success: function (res) { 14 | //从数据库获取用户信息 15 | that.queryUsreInfo(); 16 | //用户已经授权过 17 | wx.switchTab({ 18 | url: '' 19 | }) 20 | } 21 | }); 22 | } 23 | } 24 | }) 25 | }, 26 | bindGetUserInfo: function (e) { 27 | if (e.detail.userInfo) { 28 | //用户按了允许授权按钮 29 | var that = this; 30 | //插入登录的用户的相关信息到数据库 31 | wx.request({ 32 | url: getApp().globalData.urlPath + 'hstc_interface/insert_user', 33 | data: { 34 | openid: getApp().globalData.openid, 35 | nickName: e.detail.userInfo.nickName, 36 | avatarUrl: e.detail.userInfo.avatarUrl, 37 | province: e.detail.userInfo.province, 38 | city: e.detail.userInfo.city 39 | }, 40 | header: { 41 | 'content-type': 'application/json' 42 | }, 43 | success: function (res) { 44 | //从数据库获取用户信息 45 | that.queryUsreInfo(); 46 | console.log("插入小程序登录用户信息成功!"); 47 | } 48 | }); 49 | //授权成功后,跳转进入小程序首页 50 | wx.switchTab({ 51 | url: '' 52 | }) 53 | } else { 54 | //用户按了拒绝按钮 55 | wx.showModal({ 56 | title: '警告', 57 | content: '您点击了拒绝授权,将无法进入小程序,请授权之后再进入!!!', 58 | showCancel: false, 59 | confirmText: '返回授权', 60 | success: function (res) { 61 | if (res.confirm) { 62 | console.log('用户点击了“返回授权”') 63 | } 64 | } 65 | }) 66 | } 67 | }, 68 | //获取用户信息接口 69 | queryUsreInfo: function () { 70 | wx.request({ 71 | url: getApp().globalData.urlPath + 'hstc_interface/queryByOpenid', 72 | data: { 73 | openid: getApp().globalData.openid 74 | }, 75 | header: { 76 | 'content-type': 'application/json' 77 | }, 78 | success: function (res) { 79 | console.log(res.data); 80 | getApp().globalData.userInfo = res.data; 81 | } 82 | }); 83 | }, 84 | 85 | }) 86 | -------------------------------------------------------------------------------- /pages/auth/auth.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarTitleText": "授权登录" 3 | } -------------------------------------------------------------------------------- /pages/auth/auth.wxml: -------------------------------------------------------------------------------- 1 | 2 | pages/auth/auth.wxml 3 | 4 | 5 | 6 | 7 | 8 | 9 | 申请获取以下权限 10 | 获得你的公开信息(昵称,头像等) 11 | 12 | 13 | 16 | 17 | 18 | 请升级微信版本 19 | -------------------------------------------------------------------------------- /pages/auth/auth.wxss: -------------------------------------------------------------------------------- 1 | /* pages/auth/auth.wxss */ 2 | .header { 3 | margin: 90rpx 0 90rpx 50rpx; 4 | border-bottom: 1px solid #ccc; 5 | text-align: center; 6 | width: 650rpx; 7 | height: 300rpx; 8 | line-height: 450rpx; 9 | } 10 | 11 | .header image { 12 | width: 200rpx; 13 | height: 200rpx; 14 | } 15 | 16 | .content { 17 | margin-left: 50rpx; 18 | margin-bottom: 90rpx; 19 | } 20 | 21 | .content text { 22 | display: block; 23 | color: #9d9d9d; 24 | margin-top: 40rpx; 25 | } 26 | 27 | .bottom { 28 | border-radius: 80rpx; 29 | margin: 70rpx 50rpx; 30 | font-size: 35rpx; 31 | } 32 | -------------------------------------------------------------------------------- /pages/index/index.js: -------------------------------------------------------------------------------- 1 | //index.js 2 | //获取应用实例 3 | const app = getApp() 4 | 5 | Page({ 6 | data: { 7 | motto: 'Hello World', 8 | userInfo: {}, 9 | hasUserInfo: false, 10 | canIUse: wx.canIUse('button.open-type.getUserInfo') 11 | }, 12 | //事件处理函数 13 | bindViewTap: function() { 14 | wx.navigateTo({ 15 | url: '../logs/logs' 16 | }) 17 | }, 18 | onLoad: function () { 19 | if (app.globalData.userInfo) { 20 | this.setData({ 21 | userInfo: app.globalData.userInfo, 22 | hasUserInfo: true 23 | }) 24 | } else if (this.data.canIUse){ 25 | // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回 26 | // 所以此处加入 callback 以防止这种情况 27 | app.userInfoReadyCallback = res => { 28 | this.setData({ 29 | userInfo: res.userInfo, 30 | hasUserInfo: true 31 | }) 32 | } 33 | } else { 34 | // 在没有 open-type=getUserInfo 版本的兼容处理 35 | wx.getUserInfo({ 36 | success: res => { 37 | app.globalData.userInfo = res.userInfo 38 | this.setData({ 39 | userInfo: res.userInfo, 40 | hasUserInfo: true 41 | }) 42 | } 43 | }) 44 | } 45 | }, 46 | getUserInfo: function(e) { 47 | console.log(e) 48 | app.globalData.userInfo = e.detail.userInfo 49 | this.setData({ 50 | userInfo: e.detail.userInfo, 51 | hasUserInfo: true 52 | }) 53 | } 54 | }) 55 | -------------------------------------------------------------------------------- /pages/index/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{userInfo.nickName}} 8 | 9 | 10 | 11 | {{motto}} 12 | 13 | 14 | -------------------------------------------------------------------------------- /pages/index/index.wxss: -------------------------------------------------------------------------------- 1 | /**index.wxss**/ 2 | .userinfo { 3 | display: flex; 4 | flex-direction: column; 5 | align-items: center; 6 | } 7 | 8 | .userinfo-avatar { 9 | width: 128rpx; 10 | height: 128rpx; 11 | margin: 20rpx; 12 | border-radius: 50%; 13 | } 14 | 15 | .userinfo-nickname { 16 | color: #aaa; 17 | } 18 | 19 | .usermotto { 20 | margin-top: 200px; 21 | } -------------------------------------------------------------------------------- /pages/logs/logs.js: -------------------------------------------------------------------------------- 1 | //logs.js 2 | const util = require('../../utils/util.js') 3 | 4 | Page({ 5 | data: { 6 | logs: [] 7 | }, 8 | onLoad: function () { 9 | this.setData({ 10 | logs: (wx.getStorageSync('logs') || []).map(log => { 11 | return util.formatTime(new Date(log)) 12 | }) 13 | }) 14 | } 15 | }) 16 | -------------------------------------------------------------------------------- /pages/logs/logs.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarTitleText": "查看启动日志" 3 | } -------------------------------------------------------------------------------- /pages/logs/logs.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{index + 1}}. {{log}} 5 | 6 | 7 | -------------------------------------------------------------------------------- /pages/logs/logs.wxss: -------------------------------------------------------------------------------- 1 | .log-list { 2 | display: flex; 3 | flex-direction: column; 4 | padding: 40rpx; 5 | } 6 | .log-item { 7 | margin: 10rpx; 8 | } 9 | -------------------------------------------------------------------------------- /project.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "项目配置文件。", 3 | "packOptions": { 4 | "ignore": [] 5 | }, 6 | "setting": { 7 | "urlCheck": true, 8 | "es6": true, 9 | "postcss": true, 10 | "minified": true, 11 | "newFeature": true 12 | }, 13 | "compileType": "miniprogram", 14 | "libVersion": "2.2.5", 15 | "appid": "wxe0f9d7d9969b709e", 16 | "projectname": "lime-mall", 17 | "isGameTourist": false, 18 | "condition": { 19 | "search": { 20 | "current": -1, 21 | "list": [] 22 | }, 23 | "conversation": { 24 | "current": -1, 25 | "list": [] 26 | }, 27 | "plugin": { 28 | "current": -1, 29 | "list": [] 30 | }, 31 | "game": { 32 | "currentL": -1, 33 | "list": [] 34 | }, 35 | "miniprogram": { 36 | "current": 0, 37 | "list": [ 38 | { 39 | "id": -1, 40 | "name": "auth", 41 | "pathName": "pages/auth/auth" 42 | } 43 | ] 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /utils/util.js: -------------------------------------------------------------------------------- 1 | const formatTime = date => { 2 | const year = date.getFullYear() 3 | const month = date.getMonth() + 1 4 | const day = date.getDate() 5 | const hour = date.getHours() 6 | const minute = date.getMinutes() 7 | const second = date.getSeconds() 8 | 9 | return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':') 10 | } 11 | 12 | const formatNumber = n => { 13 | n = n.toString() 14 | return n[1] ? n : '0' + n 15 | } 16 | 17 | module.exports = { 18 | formatTime: formatTime 19 | } 20 | --------------------------------------------------------------------------------