├── client ├── src │ ├── Router.js │ ├── AppConfig.js │ ├── index.css │ ├── App.test.js │ ├── Pastry.css │ ├── App.css │ ├── index.js │ ├── common.js │ ├── logo.svg │ ├── Login.js │ ├── Register.js │ ├── registerServiceWorker.js │ ├── Pastry.js │ └── App.js ├── public │ ├── logo.png │ ├── favicon.ico │ ├── default_avatar.png │ ├── manifest.json │ └── index.html ├── config-overrides.js ├── package.json └── README.md ├── server ├── views │ ├── error.ejs │ ├── stats.ejs │ ├── users.ejs │ ├── pastry_order.ejs │ ├── noodles_order.ejs │ └── dinner_order.ejs ├── public │ ├── images │ │ └── default_avatar.png │ ├── stylesheets │ │ └── style.css │ └── javascripts │ │ ├── zepto.cookie.min.js │ │ └── common.js ├── config.js ├── service │ ├── schedule.js │ ├── users.js │ ├── wechat.js │ └── pastry.js ├── package.json ├── utils │ ├── mailHelper.js │ ├── common.js │ └── redis.js ├── dinner.sql ├── bin │ └── www ├── routes │ ├── pastry.js │ ├── index.js │ ├── users.js │ ├── dinner.js │ └── noodles.js └── app.js └── .gitignore /client/src/Router.js: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /client/src/AppConfig.js: -------------------------------------------------------------------------------- 1 | const ServerUrl = '/api'; 2 | 3 | export {ServerUrl}; -------------------------------------------------------------------------------- /client/public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gytai/dinner/master/client/public/logo.png -------------------------------------------------------------------------------- /client/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gytai/dinner/master/client/public/favicon.ico -------------------------------------------------------------------------------- /client/public/default_avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gytai/dinner/master/client/public/default_avatar.png -------------------------------------------------------------------------------- /server/views/error.ejs: -------------------------------------------------------------------------------- 1 |
<%= error.stack %>4 | -------------------------------------------------------------------------------- /server/public/images/default_avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gytai/dinner/master/server/public/images/default_avatar.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | .idea 3 | client/node_modules 4 | server/node_modules 5 | client/build -------------------------------------------------------------------------------- /server/public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | 5 | } 6 | 7 | a { 8 | color: #00B7FF; 9 | } 10 | -------------------------------------------------------------------------------- /client/src/index.css: -------------------------------------------------------------------------------- 1 | html,body { 2 | width: 100%; 3 | height: 100%; 4 | margin: 0; 5 | padding: 0; 6 | font-family: sans-serif; 7 | } 8 | 9 | #root{ 10 | height: 100%; 11 | background: #ffffff; 12 | } 13 | -------------------------------------------------------------------------------- /client/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(
不是公司员工不能使用
"); 18 | } 19 | 20 | req.session.uid = userinfo.userid; 21 | req.session.avatar = userinfo.avatar; 22 | req.session.name = userinfo.name; 23 | 24 | res.cookie('userid', userinfo.userid); 25 | res.cookie('avatar', userinfo.avatar); 26 | res.cookie('name', userinfo.name); 27 | 28 | //检查用户是否注册 29 | userSvc.register(userinfo.userid,userinfo.name,userinfo.avatar).then(data=>{ 30 | return res.redirect(config.dinner.client_url); 31 | }).catch(err=>{ 32 | console.error(err); 33 | return res.send("不是公司员工不能使用
"); 34 | }); 35 | }).catch(function (err) { 36 | console.error(err); 37 | return res.send("不是公司员工不能使用
"); 38 | }); 39 | }else{ 40 | var url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + 41 | config.wechat.CORPID+"&redirect_uri="+config.wechat.REDIRECT_URI+"&response_type=code" + 42 | "&scope=snsapi_userinfo&agentid="+config.wechat.AGENTID+"&state=meyer#wechat_redirect"; 43 | return res.redirect(url); 44 | } 45 | }else{ 46 | return res.redirect(config.dinner.client_url); 47 | } 48 | 49 | // req.session.uid = "02447"; 50 | // req.session.avatar = "http://p.qlogo.cn/bizmail/hRtpMXc8kYVkxxFWTSm5Fw6El15wkvWJUnjkXcckicKYz2lPDdkfRicQ/0"; 51 | // req.session.name = "邰广银"; 52 | // return res.redirect(config.dinner.client_url); 53 | }); 54 | 55 | router.get('/stats',function (req, res, next) { 56 | pastry.stats().then(function (data) { 57 | res.render("stats",{ 58 | dinner_num:data.dinner_num || 0, 59 | baozi_num:data.pastry.baozi_num || 0, 60 | mantou_num:data.pastry.mantou_num || 0 61 | }); 62 | }); 63 | 64 | }); 65 | 66 | 67 | module.exports = router; 68 | -------------------------------------------------------------------------------- /server/app.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var path = require('path'); 3 | var favicon = require('serve-favicon'); 4 | var logger = require('morgan'); 5 | var cookieParser = require('cookie-parser'); 6 | var bodyParser = require('body-parser'); 7 | var session = require('express-session'); 8 | var schedule = require('./service/schedule'); 9 | 10 | var app = express(); 11 | global.app = app; 12 | 13 | var mysql = require('mysql'); 14 | var connection = mysql.createConnection({ 15 | host: 'localhost', 16 | user: 'root', 17 | password: 'root', 18 | database:'dinner' 19 | }); 20 | 21 | connection.connect(function (err) { 22 | if (err) { 23 | console.error('mysql数据库连接错误: ' + err.stack); 24 | return; 25 | } 26 | console.log('mysql数据库连接成功, id ' + connection.threadId); 27 | }); 28 | 29 | global.app.set("mysql",connection); 30 | 31 | var index = require('./routes/index'); 32 | var users = require('./routes/users'); 33 | var pastry = require('./routes/pastry'); 34 | var dinner = require('./routes/dinner'); 35 | var noodles = require('./routes/noodles'); 36 | // view engine setup 37 | app.set('views', path.join(__dirname, 'views')); 38 | app.set('view engine', 'ejs'); 39 | 40 | // uncomment after placing your favicon in /public 41 | //app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); 42 | app.use(logger('dev')); 43 | app.use(bodyParser.json()); 44 | app.use(bodyParser.urlencoded({ extended: false })); 45 | app.use(cookieParser()); 46 | app.use(express.static(path.join(__dirname, 'public'))); 47 | 48 | app.use(session({ 49 | secret: '12345', 50 | name: 'dinnerapp', //这里的name值得是cookie的name,默认cookie的name是:connect.sid 51 | cookie: {maxAge: 1000*60*30 }, //设置maxAge是30分钟,即30min后session和相应的cookie失效过期 52 | resave: true, 53 | saveUninitialized: true 54 | })); 55 | 56 | app.all('*',function (req, res, next) { 57 | res.header("Access-Control-Allow-Credentials: true"); 58 | res.header('Access-Control-Allow-Origin', '*'); 59 | res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild'); 60 | res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS'); 61 | 62 | next(); 63 | }); 64 | 65 | app.use('/', index); 66 | app.use('/users', users); 67 | app.use('/pastry', pastry); 68 | app.use('/dinner', dinner); 69 | app.use('/noodles', noodles); 70 | 71 | // catch 404 and forward to error handler 72 | app.use(function(req, res, next) { 73 | var err = new Error('Not Found'); 74 | err.status = 404; 75 | next(err); 76 | }); 77 | 78 | // error handler 79 | app.use(function(err, req, res, next) { 80 | // set locals, only providing error in development 81 | res.locals.message = err.message; 82 | res.locals.error = req.app.get('env') === 'development' ? err : {}; 83 | console.error(err.message); 84 | // render the error page 85 | res.status(err.status || 500); 86 | res.render('error'); 87 | }); 88 | 89 | //重置定时器 90 | schedule.reset_pastry_num(); 91 | 92 | 93 | module.exports = app; 94 | -------------------------------------------------------------------------------- /client/src/Login.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { NavBar,InputItem,Button,WhiteSpace,Toast,List } from 'antd-mobile'; 3 | import axios from 'axios'; 4 | import { 5 | Link 6 | } from 'react-router-dom' 7 | import {ServerUrl} from "./AppConfig"; 8 | 9 | class Login extends Component { 10 | constructor(props) { 11 | super(props); 12 | this.state = { 13 | account:'', 14 | password:'' 15 | }; 16 | this.login = this.login.bind(this); 17 | } 18 | 19 | login() { 20 | if(!this.state.account){ 21 | Toast.fail('工号不能为空.', 1); 22 | return; 23 | } 24 | if(!this.state.password){ 25 | Toast.fail('密码不能为空.', 1); 26 | return; 27 | } 28 | 29 | axios.post(ServerUrl+'/users/login',{ 30 | account:this.state.account, 31 | password:this.state.password 32 | }).then(function(res){ 33 | console.log(res); 34 | if(res.data && res.data.code == 200){ 35 | Toast.success('登录成功'); 36 | sessionStorage.setItem("uid",res.data.data.uid); 37 | sessionStorage.setItem("uname",res.data.data.name); 38 | sessionStorage.setItem("pastry_order_start_time",res.data.config.pastry_order_start_time); 39 | sessionStorage.setItem("pastry_order_end_time",res.data.config.pastry_order_end_time); 40 | sessionStorage.setItem("pastry_baozi_sum",res.data.config.pastry_baozi_sum); 41 | sessionStorage.setItem("pastry_mantou_sum",res.data.config.pastry_mantou_sum); 42 | setTimeout(function () { 43 | window.location.href = '/'; 44 | },1000); 45 | }else{ 46 | Toast.fail('登录失败:'+res.data.msg); 47 | } 48 | }).catch(function(err){ 49 | console.log(err); 50 | Toast.fail('登录失败'); 51 | }); 52 | } 53 | 54 | handleAccountChange(data){ 55 | this.setState({account: data}); 56 | } 57 | 58 | handlePasswordChange(data){ 59 | this.setState({password: data}); 60 | } 61 | 62 | render() { 63 | return ( 64 |
71 |