├── middlewares ├── w2-proxy ├── history.js ├── statistic.js └── check.js ├── index.js ├── config ├── .gitignore ├── development.js └── default.js ├── public ├── favicon.ico ├── img │ ├── default.jpg │ └── .gitignore ├── elm │ └── static │ │ ├── img │ │ └── activity.png │ │ ├── css │ │ └── app.css │ │ └── js │ │ ├── manifest.js │ │ ├── invoice.7a9e2184152292b47d94.min.js │ │ ├── vipDescription.199af1dcfbb98c257ee0.min.js │ │ ├── searchAddress.747b2cd095404ae58611.min.js │ │ ├── setusername.4a32303d281e56e641cc.min.js │ │ ├── city.ccfd1a3eb85c7b7630e8.min.js │ │ ├── addDetail.75da563d1e4448287a21.min.js │ │ ├── service.42109737c50ef928069c.min.js │ │ └── home.5bd8d38bf00f59523e9e.min.js └── index.html ├── logs └── .gitignore ├── screenshots ├── ewm.png ├── elm_msite.png ├── elm_shop.png ├── manage_home.png └── manage_shop.png ├── InitData ├── delivery.js ├── remark.js ├── payments.js ├── activity.js ├── rate.js ├── category.js └── entry.js ├── todo.txt ├── views └── home.ejs ├── .babelrc ├── routes ├── eus.js ├── v3.js ├── v4.js ├── member.js ├── payapi.js ├── promotion.js ├── ugc.js ├── bos.js ├── statis.js ├── admin.js ├── v2.js ├── index.js ├── shopping.js └── v1.js ├── .gitignore ├── controller ├── member │ └── vipcart.js ├── v2 │ ├── entry.js │ └── user.js ├── v3 │ └── explain.js ├── v1 │ ├── captchas.js │ ├── remark.js │ ├── search.js │ ├── cities.js │ ├── address.js │ ├── carts.js │ └── order.js ├── promotion │ └── hongbao.js ├── shopping │ └── category.js ├── ugc │ └── rating.js ├── statis │ └── statis.js └── admin │ └── admin.js ├── models ├── v2 │ ├── user.js │ ├── entry.js │ └── userInfo.js ├── statis │ └── statis.js ├── v1 │ ├── remark.js │ ├── payments.js │ ├── address.js │ ├── cities.js │ └── cart.js ├── v3 │ └── explain.js ├── admin │ └── admin.js ├── shopping │ ├── delivery.js │ ├── activity.js │ ├── category.js │ ├── shop.js │ └── food.js ├── ids.js ├── promotion │ └── hongbao.js ├── ugc │ └── rating.js └── bos │ └── order.js ├── mongodb └── db.js ├── ecosystem.config.js ├── package.json ├── app.js ├── prototype ├── baseComponent.js └── addressComponent.js └── README.md /middlewares/w2-proxy: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | require('babel-core/register'); 2 | require('./app.js'); -------------------------------------------------------------------------------- /config/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | production.js -------------------------------------------------------------------------------- /config/development.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | 5 | } -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bailicangdu/node-elm/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /logs/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore -------------------------------------------------------------------------------- /screenshots/ewm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bailicangdu/node-elm/HEAD/screenshots/ewm.png -------------------------------------------------------------------------------- /public/img/default.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bailicangdu/node-elm/HEAD/public/img/default.jpg -------------------------------------------------------------------------------- /screenshots/elm_msite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bailicangdu/node-elm/HEAD/screenshots/elm_msite.png -------------------------------------------------------------------------------- /screenshots/elm_shop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bailicangdu/node-elm/HEAD/screenshots/elm_shop.png -------------------------------------------------------------------------------- /InitData/delivery.js: -------------------------------------------------------------------------------- 1 | export default { 2 | color: "57A9FF", 3 | id: 1, 4 | is_solid: true, 5 | text: "蜂鸟专送" 6 | } -------------------------------------------------------------------------------- /screenshots/manage_home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bailicangdu/node-elm/HEAD/screenshots/manage_home.png -------------------------------------------------------------------------------- /screenshots/manage_shop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bailicangdu/node-elm/HEAD/screenshots/manage_shop.png -------------------------------------------------------------------------------- /public/img/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore 5 | !default.jpg -------------------------------------------------------------------------------- /public/elm/static/img/activity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bailicangdu/node-elm/HEAD/public/elm/static/img/activity.png -------------------------------------------------------------------------------- /todo.txt: -------------------------------------------------------------------------------- 1 | ## TODO 2 | 3 | - [ ] 图片管理系统 -- 进行中 4 | - [ ] 七日数据查询优化 5 | - [ ] 日志优化 6 | - [ ] 内存管理优化 7 | - [ ] 负载均衡优化 8 | - [ ] 弃用百度地图,改用腾讯地图 9 | -------------------------------------------------------------------------------- /views/home.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 首页 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["stage-3"], 3 | "plugins": [ 4 | "transform-async-to-generator", 5 | "transform-es2015-modules-commonjs", 6 | "transform-export-extensions" 7 | ] 8 | } -------------------------------------------------------------------------------- /routes/eus.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import express from 'express'; 4 | import User from '../controller/v2/user' 5 | const router = express.Router(); 6 | 7 | router.post('/v1/users/:user_id/avatar', User.updateAvatar) 8 | 9 | export default router -------------------------------------------------------------------------------- /routes/v3.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import express from 'express'; 4 | import Explain from '../controller/v3/explain' 5 | const router = express.Router(); 6 | 7 | router.get('/profile/explain', Explain.getExpalin) 8 | 9 | export default router -------------------------------------------------------------------------------- /routes/v4.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import express from 'express'; 4 | import Food from '../controller/shopping/shop' 5 | const router = express.Router(); 6 | 7 | router.get('/restaurants', Food.searchResaturant); 8 | 9 | export default router -------------------------------------------------------------------------------- /InitData/remark.js: -------------------------------------------------------------------------------- 1 | export default { 2 | remarks: [ 3 | [ 4 | "不要辣", 5 | "少点辣", 6 | "多点辣" 7 | ], 8 | [ 9 | "不要香菜" 10 | ], 11 | [ 12 | "不要洋葱" 13 | ], 14 | [ 15 | "多点醋" 16 | ], 17 | [ 18 | "多点葱" 19 | ], 20 | [ 21 | "去冰", 22 | "少冰" 23 | ] 24 | ] 25 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | coverage 3 | package-lock.json 4 | .DS_Store 5 | **/.DS_Store 6 | .env.local 7 | .env.development.local 8 | .env.test.local 9 | .env.production.local 10 | 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | -------------------------------------------------------------------------------- /middlewares/history.js: -------------------------------------------------------------------------------- 1 | // 'use strict' 2 | 3 | // export default (req, res, next) => { 4 | // if ((/manage/gi).test(req.url)) { 5 | // res.sendFile(__dirname + '/public/manage/index.html') 6 | // }else{ 7 | // res.sendFile(__dirname + '/public/elm/index.html') 8 | // } 9 | // } -------------------------------------------------------------------------------- /routes/member.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import express from 'express'; 4 | import VipCart from '../controller/member/vipcart' 5 | const router = express.Router(); 6 | 7 | router.post('/v1/users/:user_id/delivery_card/physical_card/bind', VipCart.useCart) 8 | 9 | export default router -------------------------------------------------------------------------------- /controller/member/vipcart.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | class VipCart { 4 | constructor(props) { 5 | 6 | } 7 | async useCart(req, res, next){ 8 | res.send({ 9 | status: 0, 10 | type: 'INVALID_CART', 11 | message: '无效的卡号' 12 | }) 13 | } 14 | } 15 | 16 | 17 | export default new VipCart() -------------------------------------------------------------------------------- /routes/payapi.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import express from 'express'; 4 | const router = express.Router(); 5 | 6 | router.get('/payment/queryOrder', (req, res, next) => { 7 | res.send({ 8 | status: 0, 9 | type: 'PAY_FAILED', 10 | message: '暂不开放支付功能', 11 | }); 12 | }) 13 | 14 | export default router; -------------------------------------------------------------------------------- /models/v2/user.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import mongoose from 'mongoose' 4 | 5 | const Schema = mongoose.Schema; 6 | 7 | const userSchema = new Schema({ 8 | user_id: Number, 9 | username: String, 10 | password: String, 11 | }) 12 | 13 | const User = mongoose.model('User', userSchema); 14 | 15 | export default User -------------------------------------------------------------------------------- /config/default.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | port: parseInt(process.env.PORT, 10) || 8001, 5 | url: 'mongodb://localhost:27017/elm', 6 | session: { 7 | name: 'SID', 8 | secret: 'SID', 9 | cookie: { 10 | httpOnly: true, 11 | secure: false, 12 | maxAge: 365 * 24 * 60 * 60 * 1000, 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /routes/promotion.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import express from 'express'; 4 | import Hongbao from '../controller/promotion/hongbao' 5 | const router = express.Router(); 6 | 7 | router.get('/v2/users/:user_id/hongbaos', Hongbao.getHongbao) 8 | router.get('/v2/users/:user_id/expired_hongbaos', Hongbao.getExpiredHongbao) 9 | 10 | export default router -------------------------------------------------------------------------------- /models/statis/statis.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import mongoose from 'mongoose' 4 | 5 | const Schema = mongoose.Schema; 6 | 7 | const statisSchema = new Schema({ 8 | date: String, 9 | origin: String, 10 | id: Number, 11 | }) 12 | 13 | statisSchema.index({id: 1}) 14 | 15 | const Statis = mongoose.model('Statis', statisSchema) 16 | 17 | export default Statis -------------------------------------------------------------------------------- /InitData/payments.js: -------------------------------------------------------------------------------- 1 | export default [{ 2 | description: "(商家仅支持在线支付)", 3 | disabled_reason: "", 4 | id: 1, 5 | is_online_payment: true, 6 | name: "在线支付", 7 | promotion: [], 8 | select_state: 1, 9 | }, { 10 | description: "(商家不支持货到付款)", 11 | disabled_reason: "商家仅支持在线支付", 12 | id: 2, 13 | is_online_payment: false, 14 | name: "货到付款", 15 | promotion: [], 16 | select_state: -1, 17 | }] -------------------------------------------------------------------------------- /routes/ugc.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import express from 'express'; 4 | import Rating from '../controller/ugc/rating' 5 | const router = express.Router(); 6 | 7 | router.get('/v2/restaurants/:restaurant_id/ratings', Rating.getRatings) 8 | router.get('/v2/restaurants/:restaurant_id/ratings/scores', Rating.getScores) 9 | router.get('/v2/restaurants/:restaurant_id/ratings/tags', Rating.getTags) 10 | 11 | export default router -------------------------------------------------------------------------------- /routes/bos.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import express from 'express'; 4 | import Order from '../controller/v1/order' 5 | const router = express.Router(); 6 | 7 | router.get('/v2/users/:user_id/orders', Order.getOrders) 8 | router.get('/v1/users/:user_id/orders/:order_id/snapshot', Order.getDetail) 9 | router.get('/orders', Order.getAllOrders) 10 | router.get('/orders/count', Order.getOrdersCount) 11 | 12 | export default router -------------------------------------------------------------------------------- /models/v1/remark.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import mongoose from 'mongoose' 4 | import remarkData from '../../InitData/remark' 5 | const Schema = mongoose.Schema; 6 | 7 | const remarkSchema = new Schema({ 8 | remarks: [], 9 | }) 10 | 11 | const Remark = mongoose.model('Remark', remarkSchema); 12 | 13 | Remark.findOne((err, data) => { 14 | if(!data){ 15 | Remark.create(remarkData) 16 | } 17 | }) 18 | 19 | export default Remark -------------------------------------------------------------------------------- /models/v3/explain.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import mongoose from 'mongoose' 4 | import explainData from '../../InitData/explain' 5 | 6 | const Schema = mongoose.Schema; 7 | 8 | const explainSchema = new Schema({ 9 | data: Schema.Types.Mixed, 10 | }) 11 | 12 | const Explain = mongoose.model('Explain', explainSchema); 13 | 14 | Explain.findOne((err, data) => { 15 | if(!data){ 16 | Explain.create({data: explainData}); 17 | } 18 | }) 19 | 20 | export default Explain -------------------------------------------------------------------------------- /controller/v2/entry.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import EntryModel from '../../models/v2/entry' 4 | 5 | class Entry { 6 | constructor(){ 7 | 8 | } 9 | async getEntry(req, res, next){ 10 | try{ 11 | const entries = await EntryModel.find({}, '-_id'); 12 | res.send(entries); 13 | }catch(err){ 14 | console.log('获取数据失败'); 15 | res.send({ 16 | status: 0, 17 | type: 'ERROR_DATA', 18 | message: '获取数据失败' 19 | }) 20 | return 21 | } 22 | } 23 | } 24 | 25 | export default new Entry() -------------------------------------------------------------------------------- /routes/statis.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | import express from 'express' 4 | import Statis from '../controller/statis/statis' 5 | 6 | const router = express.Router() 7 | 8 | router.get('/api/:date/count', Statis.apiCount) 9 | router.get('/api/count', Statis.apiAllCount) 10 | router.get('/api/all', Statis.allApiRecord) 11 | router.get('/user/:date/count', Statis.userCount) 12 | router.get('/order/:date/count', Statis.orderCount) 13 | router.get('/admin/:date/count', Statis.adminCount) 14 | 15 | export default router -------------------------------------------------------------------------------- /routes/admin.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import express from 'express' 4 | import Admin from '../controller/admin/admin' 5 | const router = express.Router() 6 | 7 | router.post('/login', Admin.login); 8 | // router.post('/register', Admin.register); 9 | router.get('/signout', Admin.singout); 10 | router.get('/all', Admin.getAllAdmin); 11 | router.get('/count', Admin.getAdminCount); 12 | router.get('/info', Admin.getAdminInfo); 13 | router.post('/update/avatar/:admin_id', Admin.updateAvatar); 14 | 15 | export default router 16 | -------------------------------------------------------------------------------- /routes/v2.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import express from 'express'; 4 | import Entry from '../controller/v2/entry' 5 | import CityHandle from '../controller/v1/cities' 6 | import User from '../controller/v2/user' 7 | const router = express.Router(); 8 | 9 | router.get('/index_entry', Entry.getEntry); 10 | router.get('/pois/:geohash', CityHandle.pois); 11 | router.post('/login', User.login); 12 | router.get('/signout', User.signout); 13 | router.post('/changepassword', User.chanegPassword); 14 | 15 | 16 | export default router -------------------------------------------------------------------------------- /controller/v3/explain.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import ExplainModel from '../../models/v3/explain' 4 | 5 | class Explain { 6 | constructor(){ 7 | 8 | } 9 | async getExpalin(req, res, next){ 10 | try{ 11 | const explain = await ExplainModel.findOne(); 12 | res.send(explain.data) 13 | }catch(err){ 14 | console.log('获取服务中心数据失败', err); 15 | res.send({ 16 | status: 0, 17 | type: 'ERROR_GET_SERVER_DATA', 18 | message: '获取服务中心数据失败' 19 | }) 20 | } 21 | } 22 | } 23 | 24 | export default new Explain() -------------------------------------------------------------------------------- /models/admin/admin.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import mongoose from 'mongoose' 4 | 5 | const Schema = mongoose.Schema; 6 | 7 | const adminSchema = new Schema({ 8 | user_name: String, 9 | password: String, 10 | id: Number, 11 | create_time: String, 12 | admin: {type: String, default: '管理员'}, 13 | status: Number, //1:普通管理、 2:超级管理员 14 | avatar: {type: String, default: 'default.jpg'}, 15 | city: String, 16 | }) 17 | 18 | adminSchema.index({id: 1}); 19 | 20 | const Admin = mongoose.model('Admin', adminSchema); 21 | 22 | 23 | export default Admin 24 | -------------------------------------------------------------------------------- /models/shopping/delivery.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import mongoose from 'mongoose' 4 | import deliveryData from '../../InitData/delivery' 5 | 6 | const Schema = mongoose.Schema; 7 | 8 | const DeliverySchema = new Schema({ 9 | color: String, 10 | id: Number, 11 | is_solid: Boolean, 12 | text: String 13 | }) 14 | 15 | DeliverySchema.index({id: 1}); 16 | 17 | const Delivery = mongoose.model('Delivery', DeliverySchema); 18 | 19 | Delivery.findOne((err, data) => { 20 | if (!data) { 21 | Delivery.create(deliveryData); 22 | } 23 | }) 24 | 25 | export default Delivery 26 | -------------------------------------------------------------------------------- /controller/v1/captchas.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import captchapng from 'captchapng'; 4 | 5 | class Captchas { 6 | constructor(){ 7 | 8 | } 9 | //验证码 10 | async getCaptchas(req, res, next){ 11 | const cap = parseInt(Math.random()*9000+1000); 12 | const p = new captchapng(80,30, cap); 13 | p.color(0, 0, 0, 0); 14 | p.color(80, 80, 80, 255); 15 | const base64 = p.getBase64(); 16 | res.cookie('cap', cap, { maxAge: 300000, httpOnly: true }); 17 | res.send({ 18 | status: 1, 19 | code: 'data:image/png;base64,' + base64 20 | }); 21 | } 22 | } 23 | 24 | export default new Captchas() -------------------------------------------------------------------------------- /models/v2/entry.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import mongoose from 'mongoose' 4 | import entryData from '../../InitData/entry' 5 | 6 | const Schema = mongoose.Schema; 7 | 8 | const entrySchema = new Schema({ 9 | id: Number, 10 | is_in_serving: Boolean, 11 | description: String, 12 | title: String, 13 | link: String, 14 | image_url: String, 15 | icon_url: String, 16 | title_color: String 17 | }); 18 | 19 | const Entry = mongoose.model('Entry', entrySchema) 20 | 21 | Entry.findOne((err, data) => { 22 | if (!data) { 23 | for (let i = 0; i < entryData.length; i++) { 24 | Entry.create(entryData[i]); 25 | } 26 | } 27 | }) 28 | 29 | export default Entry -------------------------------------------------------------------------------- /models/v1/payments.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import mongoose from 'mongoose' 4 | import paymentsData from '../../InitData/payments' 5 | 6 | const Schema = mongoose.Schema; 7 | 8 | const paymentsSchema = new Schema({ 9 | description: String, 10 | disabled_reason: String, 11 | id: Number, 12 | is_online_payment: Boolean, 13 | name: String, 14 | promotion: [], 15 | select_state: Number, 16 | }) 17 | 18 | const Payments = mongoose.model('Payments', paymentsSchema); 19 | 20 | Payments.findOne((err, data) => { 21 | if (!data) { 22 | paymentsData.forEach(item => { 23 | Payments.create(item); 24 | }) 25 | } 26 | }) 27 | 28 | 29 | export default Payments -------------------------------------------------------------------------------- /models/shopping/activity.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import mongoose from 'mongoose' 4 | import activityData from '../../InitData/activity' 5 | 6 | const Schema = mongoose.Schema; 7 | 8 | const activitySchema = new Schema({ 9 | description: String, 10 | icon_color: String, 11 | icon_name: String, 12 | id: Number, 13 | name: String, 14 | ranking_weight: Number 15 | }) 16 | 17 | activitySchema.index({index: 1}); 18 | 19 | const Activity = mongoose.model('Activity', activitySchema); 20 | 21 | Activity.findOne((err, data) => { 22 | if (!data) { 23 | activityData.forEach(item => { 24 | Activity.create(item); 25 | }) 26 | } 27 | }) 28 | 29 | export default Activity -------------------------------------------------------------------------------- /middlewares/statistic.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import BaseComponent from '../prototype/baseComponent' 4 | import StatisModel from '../models/statis/statis' 5 | import dtime from 'time-formater' 6 | 7 | class Statistic extends BaseComponent { 8 | constructor(){ 9 | super() 10 | this.apiRecord = this.apiRecord.bind(this) 11 | } 12 | async apiRecord(req, res, next){ 13 | try{ 14 | const statis_id = await this.getId('statis_id') 15 | const apiInfo = { 16 | date: dtime().format('YYYY-MM-DD'), 17 | origin: req.headers.origin, 18 | id: statis_id, 19 | } 20 | StatisModel.create(apiInfo) 21 | }catch(err){ 22 | console.log('API记录出错', err); 23 | } 24 | next() 25 | } 26 | } 27 | 28 | export default new Statistic() -------------------------------------------------------------------------------- /mongodb/db.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import mongoose from 'mongoose'; 4 | import config from 'config-lite'; 5 | import chalk from 'chalk'; 6 | mongoose.connect(config.url, {useMongoClient:true}); 7 | mongoose.Promise = global.Promise; 8 | 9 | const db = mongoose.connection; 10 | 11 | db.once('open' ,() => { 12 | console.log( 13 | chalk.green('连接数据库成功') 14 | ); 15 | }) 16 | 17 | db.on('error', function(error) { 18 | console.error( 19 | chalk.red('Error in MongoDb connection: ' + error) 20 | ); 21 | mongoose.disconnect(); 22 | }); 23 | 24 | db.on('close', function() { 25 | console.log( 26 | chalk.red('数据库断开,重新连接数据库') 27 | ); 28 | mongoose.connect(config.url, {server:{auto_reconnect:true}}); 29 | }); 30 | 31 | export default db; 32 | -------------------------------------------------------------------------------- /controller/v1/remark.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import BaseComponent from '../../prototype/baseComponent' 4 | import RemarkModel from '../../models/v1/remark' 5 | 6 | class Remark extends BaseComponent{ 7 | constructor(){ 8 | super() 9 | } 10 | async getRemarks(req, res, next){ 11 | const cart_id = req.params.cart_id; 12 | if (!cart_id || !Number(cart_id)) { 13 | res.send({ 14 | status: 0, 15 | type: 'ERROR_PARAMS', 16 | message: '购物车ID参数错误' 17 | }) 18 | return 19 | } 20 | try{ 21 | const remarks = await RemarkModel.findOne({}, '-_id'); 22 | res.send(remarks); 23 | }catch(err){ 24 | console.log('获取备注数据失败',err); 25 | res.send({ 26 | status: 0, 27 | type: 'ERROR_GET_DATA', 28 | message: '获取备注数据失败' 29 | }) 30 | } 31 | } 32 | } 33 | 34 | export default new Remark() -------------------------------------------------------------------------------- /models/ids.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import mongoose from 'mongoose' 4 | 5 | const idsSchema = new mongoose.Schema({ 6 | restaurant_id: Number, 7 | food_id: Number, 8 | order_id: Number, 9 | user_id: Number, 10 | address_id: Number, 11 | cart_id: Number, 12 | img_id: Number, 13 | category_id: Number, 14 | item_id: Number, 15 | sku_id: Number, 16 | admin_id: Number, 17 | statis_id: Number, 18 | }); 19 | 20 | const Ids = mongoose.model('Ids', idsSchema); 21 | 22 | Ids.findOne((err, data) => { 23 | if (!data) { 24 | const newIds = new Ids({ 25 | restaurant_id: 0, 26 | food_id: 0, 27 | order_id: 0, 28 | user_id: 0, 29 | address_id: 0, 30 | cart_id: 0, 31 | img_id: 0, 32 | category_id: 0, 33 | item_id: 0, 34 | sku_id: 0, 35 | admin_id: 0, 36 | statis_id: 0, 37 | }); 38 | newIds.save(); 39 | } 40 | }) 41 | export default Ids -------------------------------------------------------------------------------- /InitData/activity.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | description: "", 4 | icon_color: "3FBDE6", 5 | icon_name: "品", 6 | id: 8, 7 | name: "品牌商家", 8 | ranking_weight: 7 9 | }, 10 | { 11 | description: "已加入“外卖保”计划,食品安全有保障", 12 | icon_color: "999999", 13 | icon_name: "保", 14 | id: 7, 15 | name: "外卖保", 16 | ranking_weight: 6 17 | }, 18 | { 19 | description: "新店", 20 | icon_color: "E8842D", 21 | icon_name: "新", 22 | id: 5, 23 | name: "新店", 24 | ranking_weight: 4 25 | }, 26 | { 27 | description: "该商家支持开发票,请在下单时填写好发票抬头", 28 | icon_color: "999999", 29 | icon_name: "票", 30 | id: 4, 31 | name: "开发票", 32 | ranking_weight: 3 33 | }, 34 | { 35 | description: "可使用支付宝、微信、手机QQ进行在线支付", 36 | icon_color: "FF4E00", 37 | icon_name: "付", 38 | id: 3, 39 | name: "在线支付", 40 | ranking_weight: 2 41 | }, 42 | { 43 | description: "准时必达,超时秒赔", 44 | icon_color: "57A9FF", 45 | icon_name: "准", 46 | id: 9, 47 | name: "准时达", 48 | ranking_weight: 1 49 | } 50 | ] -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | elm 12 | 13 | 14 |
15 | 16 |
17 | 18 | 19 | -------------------------------------------------------------------------------- /ecosystem.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | apps : [{ 3 | name: 'node-elm', 4 | script: 'index.js', 5 | instances: 1 , 6 | autorestart: true, 7 | watch: false, 8 | max_memory_restart: '1G', 9 | output: 'logs/out.log', 10 | error: 'logs/error.log', 11 | log: 'logs/combined.outerr.log', 12 | env: { 13 | NODE_ENV: 'development' 14 | }, 15 | env_production: { 16 | NODE_ENV: 'production', 17 | HOST: '0.0.0.0', 18 | PORT: 8001, 19 | } 20 | }], 21 | deploy: { 22 | production: { 23 | user: 'root', 24 | host: ['139.224.234.213'], 25 | port: '22', 26 | ref : 'origin/master', 27 | repo: 'git@github.com:bailicangdu/node-elm.git', 28 | path: '/root/mygit/node-elm', 29 | 'ssh_options': 'StrictHostKeyChecking=no', 30 | 'post-deploy': 'npm install && pm2 reload ecosystem.config.js --env production', 31 | } 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /routes/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import v1 from './v1' 4 | import v2 from './v2' 5 | import v3 from './v3' 6 | import v4 from './v4' 7 | import ugc from './ugc' 8 | import bos from './bos' 9 | import eus from './eus' 10 | import admin from './admin' 11 | import payapi from './payapi' 12 | import statis from './statis' 13 | import member from './member' 14 | import shopping from './shopping' 15 | import promotion from './promotion' 16 | 17 | export default app => { 18 | // app.get('/', (req, res, next) => { 19 | // res.redirect('/'); 20 | // }); 21 | app.use('/v1', v1); 22 | app.use('/v2', v2); 23 | app.use('/v3', v3); 24 | app.use('/v4', v4); 25 | app.use('/ugc', ugc); 26 | app.use('/bos', bos); 27 | app.use('/eus', eus); 28 | app.use('/admin', admin); 29 | app.use('/payapi', payapi); 30 | app.use('/member', member); 31 | app.use('/statis', statis); 32 | app.use('/shopping', shopping); 33 | app.use('/promotion', promotion); 34 | } -------------------------------------------------------------------------------- /models/promotion/hongbao.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | import mongoose from 'mongoose' 4 | import hongbaoData from '../../InitData/hongbao' 5 | 6 | const Schema = mongoose.Schema; 7 | 8 | const hongbaoSchema = new Schema({ 9 | id: Number, 10 | sn: String, 11 | user_id: Number, 12 | amount: Number, 13 | sum_condition: Number, 14 | name: String, 15 | phone: String, 16 | begin_date: String, 17 | end_date: String, 18 | description_map: { 19 | phone: String, 20 | online_paid_only: String, 21 | validity_delta: String, 22 | validity_periods: String, 23 | sum_condition: String 24 | }, 25 | limit_map: {}, 26 | status: Number, 27 | present_status: Number, 28 | share_status: Number, 29 | }) 30 | 31 | hongbaoSchema.index({id: 1}); 32 | 33 | const Hongbao = mongoose.model('Hongbao', hongbaoSchema); 34 | 35 | Hongbao.findOne((err, data) => { 36 | if (!data) { 37 | hongbaoData.forEach(item => { 38 | Hongbao.create(item) 39 | }) 40 | } 41 | }) 42 | 43 | export default Hongbao -------------------------------------------------------------------------------- /models/v1/address.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import mongoose from 'mongoose' 4 | 5 | const Schema = mongoose.Schema; 6 | 7 | const addressSchema = new Schema({ 8 | id: Number, 9 | address: String, 10 | phone: String, 11 | user_id: Number, 12 | is_valid: {type: Number, default: 1}, 13 | created_at: {type: Date, default: Date.now()}, 14 | phone_bk: String, 15 | tag_type: Number, 16 | name: String, 17 | st_geohash: String, 18 | address_detail: String, 19 | poi_type: {type: Number, default: 0}, 20 | sex: {type: Number, default: 1}, 21 | city_id: {type: Number, default: 1}, 22 | tag: {type: String, default: '家'}, 23 | is_user_default: {type: Boolean, default: true}, 24 | is_deliverable: {type: Boolean, default: true}, 25 | agent_fee: {type: Number, default: 0}, 26 | deliver_amount: {type: Number, default: 0}, 27 | phone_had_bound: {type: Boolean, default: true}, 28 | }) 29 | 30 | addressSchema.index({id: 1}); 31 | 32 | const Address = mongoose.model('Address', addressSchema); 33 | 34 | export default Address -------------------------------------------------------------------------------- /middlewares/check.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import AdminModel from '../models/admin/admin' 4 | 5 | class Check { 6 | constructor(){ 7 | 8 | } 9 | async checkAdmin(req, res, next){ 10 | const admin_id = req.session.admin_id; 11 | if (!admin_id || !Number(admin_id)) { 12 | res.send({ 13 | status: 0, 14 | type: 'ERROR_SESSION', 15 | message: '亲,您还没有登录', 16 | }) 17 | return 18 | }else{ 19 | const admin = await AdminModel.findOne({id: admin_id}); 20 | if (!admin) { 21 | res.send({ 22 | status: 0, 23 | type: 'HAS_NO_ACCESS', 24 | message: '亲,您还不是管理员', 25 | }) 26 | return 27 | } 28 | } 29 | next() 30 | } 31 | async checkSuperAdmin(req, res, next){ 32 | const admin_id = req.session.admin_id; 33 | if (!admin_id || !Number(admin_id)) { 34 | res.send({ 35 | status: 0, 36 | type: 'ERROR_SESSION', 37 | message: '亲,您还没有登录', 38 | }) 39 | return 40 | }else{ 41 | const admin = await AdminModel.findOne({id: admin_id}); 42 | if (!admin || admin.status != 2) { 43 | res.send({ 44 | status: 0, 45 | type: 'HAS_NO_ACCESS', 46 | message: '亲,您的权限不足', 47 | }) 48 | return 49 | } 50 | } 51 | next() 52 | } 53 | } 54 | 55 | export default new Check() -------------------------------------------------------------------------------- /models/v2/userInfo.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import mongoose from 'mongoose' 4 | 5 | const Schema = mongoose.Schema; 6 | 7 | const userInfoSchema = new Schema({ 8 | avatar: {type: String, default: 'default.jpg'}, 9 | balance: {type: Number, default: 0}, 10 | brand_member_new: {type: Number, default: 0}, 11 | current_address_id: {type: Number, default: 0}, 12 | current_invoice_id: {type: Number, default: 0}, 13 | delivery_card_expire_days: {type: Number, default: 0}, 14 | email: {type: String, default: ''}, 15 | gift_amount: {type: Number, default: 3}, 16 | city: String, 17 | registe_time: String, 18 | id: Number, 19 | user_id: Number, 20 | is_active: {type: Number, default: 1}, 21 | is_email_valid: {type: Boolean, default: false}, 22 | is_mobile_valid: {type: Boolean, default: true}, 23 | mobile: {type: String, default: ''}, 24 | point: {type: Number, default: 0}, 25 | username: String, 26 | column_desc: { 27 | game_desc: {type: String, default: '玩游戏领红包'}, 28 | game_image_hash: {type: String, default: '05f108ca4e0c543488799f0c7c708cb1jpeg'}, 29 | game_is_show: {type: Number, default: 1}, 30 | game_link: {type: String, default: 'https://gamecenter.faas.ele.me'}, 31 | gift_mall_desc: {type: String, default: '0元好物在这里'}, 32 | }, 33 | }) 34 | 35 | userInfoSchema.index({id: 1}); 36 | 37 | 38 | const UserInfo = mongoose.model('UserInfo', userInfoSchema); 39 | 40 | export default UserInfo -------------------------------------------------------------------------------- /models/shopping/category.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import mongoose from 'mongoose' 4 | import categoryData from '../../InitData/category' 5 | 6 | const Schema = mongoose.Schema; 7 | 8 | const categorySchema = new Schema({ 9 | count: Number, 10 | id: Number, 11 | ids: [], 12 | image_url: String, 13 | level: Number, 14 | name: String, 15 | sub_categories: [ 16 | { 17 | count: Number, 18 | id: Number, 19 | image_url: String, 20 | level: Number, 21 | name: String 22 | }, 23 | ] 24 | }); 25 | 26 | categorySchema.statics.addCategory = async function (type){ 27 | const categoryName = type.split('/'); 28 | try{ 29 | const allcate = await this.findOne(); 30 | const subcate = await this.findOne({name: categoryName[0]}); 31 | allcate.count ++; 32 | subcate.count ++ ; 33 | subcate.sub_categories.map(item => { 34 | if (item.name == categoryName[1]) { 35 | return item.count ++ 36 | } 37 | }) 38 | await allcate.save(); 39 | await subcate.save(); 40 | console.log('保存cetegroy成功'); 41 | return 42 | }catch(err){ 43 | console.log('保存cetegroy失败'); 44 | throw new Error(err) 45 | } 46 | } 47 | 48 | const Category = mongoose.model('Category', categorySchema) 49 | 50 | Category.findOne((err, data) => { 51 | if (!data) { 52 | for (let i = 0; i < categoryData.length; i++) { 53 | Category.create(categoryData[i]); 54 | } 55 | } 56 | }) 57 | 58 | export default Category -------------------------------------------------------------------------------- /routes/shopping.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import express from 'express'; 4 | import Shop from '../controller/shopping/shop' 5 | import Food from '../controller/shopping/food' 6 | import Category from '../controller/shopping/category' 7 | import Check from '../middlewares/check' 8 | 9 | const router = express.Router(); 10 | 11 | router.post('/addshop', Check.checkAdmin, Shop.addShop); 12 | router.get('/restaurants', Shop.getRestaurants); 13 | router.get('/restaurants/count', Shop.getShopCount); 14 | router.post('/updateshop', Check.checkAdmin, Shop.updateshop); 15 | router.delete('/restaurant/:restaurant_id', Check.checkSuperAdmin, Shop.deleteResturant); 16 | router.get('/restaurant/:restaurant_id', Shop.getRestaurantDetail); 17 | router.post('/addfood', Check.checkAdmin, Food.addFood); 18 | router.get('/getcategory/:restaurant_id', Food.getCategory); 19 | router.post('/addcategory', Check.checkAdmin, Food.addCategory); 20 | router.get('/v2/menu', Food.getMenu); 21 | router.get('/v2/menu/:category_id', Food.getMenuDetail); 22 | router.get('/v2/foods', Food.getFoods); 23 | router.get('/v2/foods/count', Food.getFoodsCount); 24 | router.post('/v2/updatefood', Check.checkAdmin, Food.updateFood); 25 | router.delete('/v2/food/:food_id', Check.checkSuperAdmin, Food.deleteFood); 26 | router.get('/v2/restaurant/category', Category.getCategories); 27 | router.get('/v1/restaurants/delivery_modes', Category.getDelivery); 28 | router.get('/v1/restaurants/activity_attributes', Category.getActivity); 29 | 30 | export default router -------------------------------------------------------------------------------- /controller/v1/search.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import AddressComponent from '../../prototype/addressComponent'; 4 | import Cities from '../../models/v1/cities'; 5 | import CityHandle from './cities' 6 | 7 | class SearchPlace extends AddressComponent{ 8 | constructor(){ 9 | super() 10 | this.search = this.search.bind(this) 11 | } 12 | async search(req, res, next){ 13 | let {type = 'search', city_id, keyword} = req.query; 14 | if (!keyword) { 15 | res.send({ 16 | name: 'ERROR_QUERY_TYPE', 17 | message: '参数错误', 18 | }) 19 | return 20 | }else if(isNaN(city_id)){ 21 | try{ 22 | const cityname = await CityHandle.getCityName(req); 23 | const cityInfo = await Cities.cityGuess(cityname); 24 | city_id = cityInfo.id; 25 | }catch(err){ 26 | console.log('搜索地址时,获取定位城失败') 27 | res.send({ 28 | name: 'ERROR_GET_POSITION', 29 | message: '获取数据失败', 30 | }) 31 | } 32 | } 33 | try{ 34 | const cityInfo = await Cities.getCityById(city_id); 35 | const resObj = await this.searchPlace(keyword, cityInfo.name, type); 36 | const cityList = []; 37 | resObj.data.forEach((item, index) => { 38 | cityList.push({ 39 | name: item.title, 40 | address: item.address, 41 | latitude: item.location.lat, 42 | longitude: item.location.lng, 43 | geohash: item.location.lat + ',' + item.location.lng, 44 | }) 45 | }); 46 | res.send(cityList); 47 | }catch(err){ 48 | res.send({ 49 | name: 'GET_ADDRESS_ERROR', 50 | message: '获取地址信息失败', 51 | }); 52 | } 53 | } 54 | } 55 | 56 | export default new SearchPlace(); -------------------------------------------------------------------------------- /controller/promotion/hongbao.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | import HongbaoModel from '../../models/promotion/hongbao' 4 | import BaseComponent from '../../prototype/baseComponent' 5 | 6 | class Hongbao extends BaseComponent{ 7 | constructor(){ 8 | super() 9 | this.getHongbao = this.getHongbao.bind(this); 10 | this.getExpiredHongbao = this.getExpiredHongbao.bind(this); 11 | } 12 | async getHongbao(req, res, next){ 13 | this.hongbaoHandle(req, res, 'intime') 14 | } 15 | async getExpiredHongbao(req, res, next){ 16 | this.hongbaoHandle(req, res, 'expired') 17 | } 18 | async hongbaoHandle(req, res, type){ 19 | const present_status = type == 'intime'? 1 : 4; 20 | const user_id = req.params.user_id; 21 | const {limit = 0, offset = 0} = req.query; 22 | try{ 23 | if(!user_id || !Number(user_id)){ 24 | throw new Error('user_id参数错误') 25 | }else if(!Number(limit)){ 26 | throw new Error('limit参数错误') 27 | }else if(typeof Number(offset) !== 'number'){ 28 | throw new Error('offset参数错误') 29 | } 30 | }catch(err){ 31 | console.log(err.message, err); 32 | res.send({ 33 | status: 0, 34 | type: 'ERROR_PARAMS', 35 | message: err.message 36 | }) 37 | return 38 | } 39 | try{ 40 | const hongbaos = await HongbaoModel.find({present_status}, '-_id').limit(Number(limit)).skip(Number(offset)); 41 | res.send(hongbaos) 42 | }catch(err){ 43 | console.log('获取红包数据失败'); 44 | res.send({ 45 | status: 0, 46 | type: 'ERROR_TO_GET_HONGBAO_DATA', 47 | message: '获取红包数据失败' 48 | }) 49 | } 50 | } 51 | async exchange(req, res, next){ 52 | res.send({ 53 | status: 0, 54 | type: 'NOT_ALLOWD_API', 55 | message: '无效的兑换码' 56 | }) 57 | } 58 | } 59 | 60 | export default new Hongbao() -------------------------------------------------------------------------------- /public/elm/static/css/app.css: -------------------------------------------------------------------------------- 1 | a,article,aside,b,body,button,dd,div,dl,dt,figcaption,figure,footer,h1,h2,h3,h4,h5,h6,header,i,input,li,nav,p,section,select,span,textarea,ul{padding:0;margin:0;list-style:none;font-style:normal;text-decoration:none;border:none;color:#333;font-weight:400;font-family:Microsoft Yahei;box-sizing:border-box;-webkit-tap-highlight-color:transparent;-webkit-font-smoothing:antialiased}a:hover,article:hover,aside:hover,b:hover,body:hover,button:hover,dd:hover,div:hover,dl:hover,dt:hover,figcaption:hover,figure:hover,footer:hover,h1:hover,h2:hover,h3:hover,h4:hover,h5:hover,h6:hover,header:hover,i:hover,input:hover,li:hover,nav:hover,p:hover,section:hover,select:hover,span:hover,textarea:hover,ul:hover{outline:none}::-webkit-scrollbar{width:0;height:0;background-color:#f5f5f5}::-webkit-scrollbar-track{-webkit-box-shadow:inset 0 0 1px transparent;border-radius:10px;background-color:#f5f5f5}::-webkit-scrollbar-thumb{border-radius:10px;-webkit-box-shadow:inset 0 0 6px rgba(0,0,0,.3);background-color:#555}input[type=button],input[type=reset],input[type=search],input[type=submit],textarea{-webkit-appearance:none}body,html{height:100%;width:100%;background-color:#f5f5f5}.clear:after{content:"";display:block;clear:both}.clear{zoom:1}.back_img{background-repeat:no-repeat;background-size:100% 100%}.margin{margin:0 auto}.left{float:left}.right{float:right}.hide{display:none}.show{display:block}.ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.paddingTop{padding-top:1.95rem}@keyframes backOpacity{0%{opacity:1}25%{opacity:.5}50%{opacity:1}75%{opacity:.5}to{opacity:1}}.animation_opactiy{animation:backOpacity 2s ease-in-out infinite}.router-fade-enter-active,.router-fade-leave-active{transition:opacity .3s}.router-fade-enter,.router-fade-leave-active{opacity:0} -------------------------------------------------------------------------------- /routes/v1.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import express from 'express' 4 | import CityHandle from '../controller/v1/cities' 5 | import SearchPlace from '../controller/v1/search' 6 | import Carts from '../controller/v1/carts' 7 | import Address from '../controller/v1/address' 8 | import Remark from '../controller/v1/remark' 9 | import BaseComponent from '../prototype/baseComponent' 10 | import Captchas from '../controller/v1/captchas' 11 | import User from '../controller/v2/user' 12 | import Order from '../controller/v1/order' 13 | import Hongbao from '../controller/promotion/hongbao' 14 | const baseHandle = new BaseComponent(); 15 | const router = express.Router(); 16 | 17 | router.get('/cities', CityHandle.getCity); 18 | router.get('/cities/:id', CityHandle.getCityById); 19 | router.get('/exactaddress', CityHandle.getExactAddress); 20 | router.get('/pois', SearchPlace.search); 21 | router.post('/addimg/:type', baseHandle.uploadImg); 22 | router.post('/carts/checkout', Carts.checkout); 23 | router.get('/carts/:cart_id/remarks', Remark.getRemarks); 24 | router.post('/captchas', Captchas.getCaptchas); 25 | router.get('/user', User.getInfo); 26 | router.get('/user/:user_id', User.getInfoById); 27 | router.get('/users/list', User.getUserList); 28 | router.get('/users/count', User.getUserCount); 29 | router.get('/users/:user_id/addresses', Address.getAddress); 30 | router.post('/users/:user_id/addresses', Address.addAddress); 31 | router.get('/user/city/count', User.getUserCity); 32 | router.get('/addresse/:address_id', Address.getAddAddressById); 33 | router.delete('/users/:user_id/addresses/:address_id', Address.deleteAddress); 34 | router.post('/users/:user_id/carts/:cart_id/orders', Order.postOrder); 35 | router.post('/users/:user_id/hongbao/exchange', Hongbao.exchange); 36 | 37 | 38 | export default router -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-elm", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "author": "cangdu <1264889788@qq.com>", 7 | "license": "GPL", 8 | "private": true, 9 | "scripts": { 10 | "dev": "cross-env NODE_ENV=development nodemon --harmony index.js", 11 | "check": "cross-env NODE_ENV=production nodemon --harmony index.js", 12 | "test": "echo \"Error: no test specified\" && exit 1", 13 | "deploy": "pm2 deploy production" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/bailicangdu/node-elm" 18 | }, 19 | "dependencies": { 20 | "babel": "^6.23.0", 21 | "babel-cli": "^6.24.1", 22 | "babel-core": "^6.24.0", 23 | "babel-preset-es2015": "^6.24.0", 24 | "babel-preset-stage-3": "^6.22.0", 25 | "babel-register": "^6.24.0", 26 | "bluebird": "^3.5.0", 27 | "captchapng": "0.0.1", 28 | "chalk": "^2.3.0", 29 | "config-lite": "^1.5.0", 30 | "connect-flash": "^0.1.1", 31 | "connect-history-api-fallback": "^1.3.0", 32 | "connect-mongo": "^1.3.2", 33 | "cookie-parser": "^1.4.3", 34 | "cross-env": "^5.0.0", 35 | "express": "^4.15.2", 36 | "express-session": "^1.15.2", 37 | "express-winston": "^2.3.0", 38 | "formidable": "^1.1.1", 39 | "gm": "^1.23.0", 40 | "marked": "^0.3.6", 41 | "moment": "^2.18.1", 42 | "mongodb": "^2.2.25", 43 | "mongoose": "^4.9.3", 44 | "node-fetch": "^1.6.3", 45 | "pinyin": "^2.8.3", 46 | "pm2": "^2.8.0", 47 | "qiniu": "^6.1.13", 48 | "sha1": "^1.1.1", 49 | "time-formater": "1.0.1", 50 | "time-stamp": "^2.0.0", 51 | "winston": "^2.3.1" 52 | }, 53 | "devDependencies": { 54 | "babel-plugin-transform-async-to-generator": "^6.24.1", 55 | "babel-plugin-transform-es2015-classes": "^6.24.1", 56 | "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", 57 | "babel-plugin-transform-export-extensions": "^6.22.0", 58 | "nodemon": "^1.18.6" 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /controller/shopping/category.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import CategoryModel from '../../models/shopping/category' 4 | import BaseComponent from '../../prototype/baseComponent' 5 | import DeliveryModel from '../../models/shopping/delivery' 6 | import ActivityModel from '../../models/shopping/activity' 7 | 8 | class Category extends BaseComponent{ 9 | constructor(){ 10 | super() 11 | } 12 | //获取所有餐馆分类和数量 13 | async getCategories(req, res, next){ 14 | try{ 15 | const categories = await CategoryModel.find({}, '-_id'); 16 | res.send(categories); 17 | }catch(err){ 18 | console.log('获取categories失败'); 19 | res.send({ 20 | status: 0, 21 | type: 'ERROR_DATA', 22 | message: '获取categories失败' 23 | }) 24 | } 25 | } 26 | async addCategory(type){ 27 | try{ 28 | await CategoryModel.addCategory(type) 29 | }catch(err){ 30 | console.log('增加category数量失败'); 31 | } 32 | } 33 | async findById(id){ 34 | try{ 35 | const CateEntity = await CategoryModel.findOne({'sub_categories.id': id}); 36 | let categoName = CateEntity.name; 37 | CateEntity.sub_categories.forEach(item => { 38 | if (item.id == id) { 39 | categoName += '/' + item.name; 40 | } 41 | }) 42 | return categoName 43 | }catch(err){ 44 | console.log('通过category id获取数据失败') 45 | throw new Error(err) 46 | } 47 | } 48 | //获取配送方式 49 | async getDelivery(req, res, next){ 50 | try{ 51 | const deliveries = await DeliveryModel.find({}, '-_id'); 52 | res.send(deliveries) 53 | }catch(err){ 54 | console.log('获取配送方式数据失败'); 55 | res.send({ 56 | status: 0, 57 | type: 'ERROR_DATA', 58 | message: '获取配送方式数据失败' 59 | }) 60 | } 61 | } 62 | //获取活动列表 63 | async getActivity(req, res, next){ 64 | try{ 65 | const activities = await ActivityModel.find({}, '-_id'); 66 | res.send(activities) 67 | }catch(err){ 68 | console.log('获取活动数据失败'); 69 | res.send({ 70 | status: 0, 71 | type: 'ERROR_DATA', 72 | message: '获取活动数据失败' 73 | }) 74 | } 75 | } 76 | } 77 | 78 | export default new Category() -------------------------------------------------------------------------------- /models/ugc/rating.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import mongoose from 'mongoose' 4 | import {ratingList, scores, tags} from '../../InitData/rate' 5 | const Schema = mongoose.Schema; 6 | 7 | const rateSchema = new Schema({ 8 | restaurant_id: Number, 9 | ratings: [ 10 | { 11 | avatar: {type: String, default: ''}, 12 | highlights: [], 13 | item_ratings: [ 14 | { 15 | food_id: Number, 16 | food_name: String, 17 | image_hash: {type: String, default: ''}, 18 | is_valid: {type: Number, default: 1}, 19 | }, 20 | ], 21 | rated_at: String, 22 | rating_star: Number, 23 | rating_text: String, 24 | tags: {type: Array, default: []}, 25 | time_spent_desc: String, 26 | username: {type: String, default: "匿名用户"}, 27 | }, 28 | ], 29 | scores: { 30 | compare_rating: {type: Number, default: 0}, 31 | deliver_time: {type: Number, default: 0}, 32 | food_score: {type: Number, default: 0}, 33 | order_rating_amount: {type: Number, default: 0}, 34 | overall_score: {type: Number, default: 0}, 35 | service_score: {type: Number, default: 0}, 36 | }, 37 | tags: [{ 38 | count: {type: Number, default: 0}, 39 | name: String, 40 | unsatisfied: {type: Boolean, default: false}, 41 | }] 42 | }) 43 | 44 | rateSchema.index({restaurant_id: 1}); 45 | 46 | rateSchema.statics.initData = async function (restaurant_id){ 47 | try{ 48 | const data = await this.findOne({restaurant_id}); 49 | if (!data) { 50 | const newRating = { 51 | restaurant_id, 52 | ratings: ratingList, 53 | scores, 54 | tags, 55 | } 56 | await this.create(newRating); 57 | return true 58 | }else{ 59 | return false 60 | } 61 | }catch(err){ 62 | console.log('初始化评论数据失败'); 63 | throw new Error(err) 64 | } 65 | } 66 | 67 | rateSchema.statics.getData = async function (restaurant_id, type){ 68 | try{ 69 | const data = await this.findOne({restaurant_id}, '-_id'); 70 | if (!data) { 71 | throw new Error('未找到当前餐馆的评论数据'); 72 | }else{ 73 | return data[type] 74 | } 75 | }catch(err){ 76 | console.log('初始化评论数据失败'); 77 | throw new Error(err) 78 | } 79 | } 80 | 81 | const Rating = mongoose.model('Rating', rateSchema); 82 | 83 | 84 | 85 | export default Rating -------------------------------------------------------------------------------- /controller/ugc/rating.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import RatingModel from '../../models/ugc/rating' 4 | 5 | class Rating { 6 | constructor(){ 7 | this.type = ['ratings', 'scores', 'tags']; 8 | this.getRatings = this.getRatings.bind(this); 9 | this.getScores = this.getScores.bind(this); 10 | this.getTags = this.getTags.bind(this); 11 | } 12 | async initData(restaurant_id){ 13 | try{ 14 | const status = await RatingModel.initData(restaurant_id); 15 | if (status) { 16 | console.log('初始化评论数据成功'); 17 | } 18 | }catch(err){ 19 | console.log('初始化评论数据失败'); 20 | throw new Error(err); 21 | } 22 | } 23 | async getRatings(req, res, next){ 24 | const restaurant_id = req.params.restaurant_id; 25 | if (!restaurant_id || !Number(restaurant_id)) { 26 | res.send({ 27 | status: 0, 28 | type: 'ERROR_PARAMS', 29 | message: '餐馆ID参数错误' 30 | }) 31 | return 32 | } 33 | try{ 34 | const ratings = await RatingModel.getData(restaurant_id, this.type[0]); 35 | res.send(ratings) 36 | }catch(err){ 37 | console.log('获取评论列表失败', err); 38 | res.send({ 39 | status: 0, 40 | type: "ERROR_DATA", 41 | message: '未找到当前餐馆的评论数据' 42 | }) 43 | } 44 | } 45 | async getScores(req, res, next){ 46 | const restaurant_id = req.params.restaurant_id; 47 | if (!restaurant_id || !Number(restaurant_id)) { 48 | res.send({ 49 | status: 0, 50 | type: 'ERROR_PARAMS', 51 | message: '餐馆ID参数错误' 52 | }) 53 | return 54 | } 55 | try{ 56 | const scores = await RatingModel.getData(restaurant_id, this.type[1]); 57 | res.send(scores) 58 | }catch(err){ 59 | console.log('获取评论列表失败', err); 60 | res.send({ 61 | status: 0, 62 | type: "ERROR_DATA", 63 | message: '未找到当前餐馆的评论数据' 64 | }) 65 | } 66 | } 67 | async getTags(req, res, next){ 68 | const restaurant_id = req.params.restaurant_id; 69 | if (!restaurant_id || !Number(restaurant_id)) { 70 | res.send({ 71 | status: 0, 72 | type: 'ERROR_PARAMS', 73 | message: '餐馆ID参数错误' 74 | }) 75 | return 76 | } 77 | try{ 78 | const tags = await RatingModel.getData(restaurant_id, this.type[2]); 79 | res.send(tags) 80 | }catch(err){ 81 | console.log('获取评论列表失败', err); 82 | res.send({ 83 | status: 0, 84 | type: "ERROR_DATA", 85 | message: '未找到当前餐馆的评论数据' 86 | }) 87 | } 88 | } 89 | } 90 | 91 | export default new Rating() -------------------------------------------------------------------------------- /models/v1/cities.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import mongoose from 'mongoose'; 4 | import cityData from '../../InitData/cities' 5 | 6 | const citySchema = new mongoose.Schema({ 7 | data: {} 8 | }); 9 | 10 | citySchema.statics.cityGuess = function(name){ 11 | return new Promise(async (resolve, reject) => { 12 | const firtWord = name.substr(0,1).toUpperCase(); 13 | try{ 14 | const city = await this.findOne(); 15 | Object.entries(city.data).forEach(item => { 16 | if(item[0] == firtWord){ 17 | item[1].forEach(cityItem => { 18 | if (cityItem.pinyin == name) { 19 | resolve(cityItem) 20 | } 21 | }) 22 | } 23 | }) 24 | }catch(err){ 25 | reject({ 26 | name: 'ERROR_DATA', 27 | message: '查找数据失败', 28 | }); 29 | console.error(err); 30 | } 31 | }) 32 | } 33 | 34 | citySchema.statics.cityHot = function (){ 35 | return new Promise(async (resolve, reject) => { 36 | try{ 37 | const city = await this.findOne(); 38 | resolve(city.data.hotCities) 39 | }catch(err){ 40 | reject({ 41 | name: 'ERROR_DATA', 42 | message: '查找数据失败', 43 | }); 44 | console.error(err); 45 | } 46 | }) 47 | } 48 | 49 | citySchema.statics.cityGroup = function (){ 50 | return new Promise(async (resolve, reject) => { 51 | try{ 52 | const city = await this.findOne(); 53 | const cityObj = city.data; 54 | delete(cityObj._id) 55 | delete(cityObj.hotCities) 56 | resolve(cityObj) 57 | }catch(err){ 58 | reject({ 59 | name: 'ERROR_DATA', 60 | message: '查找数据失败', 61 | }); 62 | console.error(err); 63 | } 64 | }) 65 | } 66 | 67 | citySchema.statics.getCityById = function(id){ 68 | return new Promise(async (resolve, reject) => { 69 | try{ 70 | const city = await this.findOne(); 71 | Object.entries(city.data).forEach(item => { 72 | if(item[0] !== '_id' && item[0] !== 'hotCities'){ 73 | item[1].forEach(cityItem => { 74 | if (cityItem.id == id) { 75 | resolve(cityItem) 76 | } 77 | }) 78 | } 79 | }) 80 | }catch(err){ 81 | reject({ 82 | name: 'ERROR_DATA', 83 | message: '查找数据失败', 84 | }); 85 | console.error(err); 86 | } 87 | }) 88 | } 89 | 90 | const Cities = mongoose.model('Cities', citySchema); 91 | 92 | 93 | Cities.findOne((err, data) => { 94 | if (!data) { 95 | Cities.create({data: cityData}); 96 | } 97 | }); 98 | 99 | export default Cities -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import db from './mongodb/db.js'; 3 | import config from 'config-lite'; 4 | import router from './routes/index.js'; 5 | import cookieParser from 'cookie-parser' 6 | import session from 'express-session'; 7 | import connectMongo from 'connect-mongo'; 8 | import winston from 'winston'; 9 | import expressWinston from 'express-winston'; 10 | import history from 'connect-history-api-fallback'; 11 | import chalk from 'chalk'; 12 | // import Statistic from './middlewares/statistic' 13 | 14 | const app = express(); 15 | 16 | app.all('*', (req, res, next) => { 17 | const { origin, Origin, referer, Referer } = req.headers; 18 | const allowOrigin = origin || Origin || referer || Referer || '*'; 19 | res.header("Access-Control-Allow-Origin", allowOrigin); 20 | res.header("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With"); 21 | res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS"); 22 | res.header("Access-Control-Allow-Credentials", true); //可以带cookies 23 | res.header("X-Powered-By", 'Express'); 24 | if (req.method == 'OPTIONS') { 25 | res.sendStatus(200); 26 | } else { 27 | next(); 28 | } 29 | }); 30 | 31 | // app.use(Statistic.apiRecord) 32 | const MongoStore = connectMongo(session); 33 | app.use(cookieParser()); 34 | app.use(session({ 35 | name: config.session.name, 36 | secret: config.session.secret, 37 | resave: true, 38 | saveUninitialized: false, 39 | cookie: config.session.cookie, 40 | store: new MongoStore({ 41 | url: config.url 42 | }) 43 | })) 44 | 45 | // app.use(expressWinston.logger({ 46 | // transports: [ 47 | // new (winston.transports.Console)({ 48 | // json: true, 49 | // colorize: true 50 | // }), 51 | // new winston.transports.File({ 52 | // filename: 'logs/success.log' 53 | // }) 54 | // ] 55 | // })); 56 | 57 | router(app); 58 | 59 | // app.use(expressWinston.errorLogger({ 60 | // transports: [ 61 | // new winston.transports.Console({ 62 | // json: true, 63 | // colorize: true 64 | // }), 65 | // new winston.transports.File({ 66 | // filename: 'logs/error.log' 67 | // }) 68 | // ] 69 | // })); 70 | 71 | app.use(history()); 72 | app.use(express.static('./public')); 73 | app.listen(config.port, () => { 74 | console.log( 75 | chalk.green(`成功监听端口:${config.port}`) 76 | ) 77 | }); -------------------------------------------------------------------------------- /models/v1/cart.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import mongoose from 'mongoose' 4 | 5 | const Schema = mongoose.Schema; 6 | 7 | const cartSchema = Schema({ 8 | id: Number, 9 | cart: { 10 | id: Number, 11 | groups: [ 12 | [ 13 | { 14 | attrs: [], 15 | extra: [], 16 | id: Number, 17 | new_specs: [], 18 | name: String, 19 | price: Number, 20 | quantity: Number, 21 | specs: [String], 22 | packing_fee: Number, 23 | sku_id: Number, 24 | stock: Number, 25 | } 26 | ] 27 | ], 28 | extra: [{ 29 | description: String, 30 | name: {type: String, default: '餐盒'}, 31 | price: {type: Number, default: 0}, 32 | quantity: {type: Number, default: 0}, 33 | type: {type: Number, default: 0}, 34 | }], 35 | deliver_amount: Number, 36 | deliver_time: String, 37 | discount_amount: String, 38 | dist_info: String, 39 | is_address_too_far: {type: Boolean, default: false}, 40 | is_deliver_by_fengniao: Boolean, 41 | is_online_paid: {type: Number, default: 1}, 42 | is_ontime_available: {type: Number, default: 0}, 43 | must_new_user: {type: Number, default: 0}, 44 | must_pay_online: {type: Number, default: 0}, 45 | ontime_status: {type: Number, default: 0}, 46 | ontime_unavailable_reason: String, 47 | original_total: Number, 48 | phone: String, 49 | promise_delivery_time: {type: Number, default: 0}, 50 | restaurant_id: Number, 51 | restaurant_info: Schema.Types.Mixed, 52 | restaurant_minimum_order_amount: Number, 53 | restaurant_name_for_url: String, 54 | restaurant_status: {type: Number, default: 1}, 55 | service_fee_explanation: {type: Number, default: 0}, 56 | total: Number, 57 | user_id: Number, 58 | }, 59 | delivery_reach_time: String, 60 | invoice: { 61 | is_available: {type: Boolean, default: false}, 62 | status_text: String, 63 | }, 64 | sig: String, 65 | current_address: {}, 66 | payments: [{ 67 | description: String, 68 | disabled_reason: String, 69 | id: Number, 70 | is_online_payment: {type: Boolean, default: true}, 71 | name: String, 72 | promotion:[], 73 | select_state: Number, 74 | }], 75 | deliver_times: [], 76 | deliver_times_v2: [], 77 | merchant_coupon_info: {}, 78 | number_of_meals: {}, 79 | discount_rule: {}, 80 | hongbao_info: {}, 81 | is_support_coupon: {type: Boolean, default: false}, 82 | is_support_ninja: {type: Number, default: 1}, 83 | }) 84 | 85 | cartSchema.index({id: 1}); 86 | 87 | const Cart = mongoose.model('Cart', cartSchema); 88 | 89 | export default Cart -------------------------------------------------------------------------------- /models/shopping/shop.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import mongoose from 'mongoose' 4 | 5 | const shopSchema = new mongoose.Schema({ 6 | activities: [{ 7 | description: String, 8 | icon_color: String, 9 | icon_name: String, 10 | id: Number, 11 | name: String, 12 | }], 13 | address: String, 14 | delivery_mode: { 15 | color: String, 16 | id: Number, 17 | is_solid: Boolean, 18 | text: String 19 | }, 20 | description: { type: String, default: "" }, 21 | order_lead_time: { type: String, default: "" }, 22 | distance: { type: String, default: "" }, 23 | location:{type:[Number],index: '2d'}, 24 | float_delivery_fee: { type: Number, default: 0 }, 25 | float_minimum_order_amount: { type: Number, default: 0 }, 26 | id: Number, 27 | category: String, 28 | identification: { 29 | company_name: { type: String, default: "" }, 30 | identificate_agency: { type: String, default: "" }, 31 | identificate_date: { type: Date, default: Date.now }, 32 | legal_person: { type: String, default: "" }, 33 | licenses_date: { type: String, default: "" }, 34 | licenses_number: { type: String, default: "" }, 35 | licenses_scope: { type: String, default: "" }, 36 | operation_period: { type: String, default: "" }, 37 | registered_address: { type: String, default: "" }, 38 | registered_number: { type: String, default: "" }, 39 | }, 40 | image_path: { type: String, default: "" }, 41 | is_premium: { type: Boolean, default: false }, 42 | is_new: { type: Boolean, default: false }, 43 | latitude: Number, 44 | longitude: Number, 45 | license: { 46 | business_license_image: { type: String, default: "" }, 47 | catering_service_license_image: { type: String, default: "" }, 48 | }, 49 | name: { 50 | type: String, 51 | required: true 52 | }, 53 | opening_hours: { type: Array, default: ["08:30/20:30"] }, 54 | phone: { 55 | type: String, 56 | required: true 57 | }, 58 | piecewise_agent_fee: { 59 | tips: String 60 | }, 61 | promotion_info: { type: String, default: "欢迎光临,用餐高峰请提前下单,谢谢" }, 62 | rating: { type: Number, default: 0 }, 63 | rating_count: { type: Number, default: 0 }, 64 | recent_order_num: { type: Number, default: 0 }, 65 | status: { type: Number, default: 0 }, 66 | supports: [{ 67 | description: String, 68 | icon_color: String, 69 | icon_name: String, 70 | id: Number, 71 | name: String 72 | }], 73 | }); 74 | 75 | shopSchema.index({ id: 1 }); //primary_key 主键 76 | 77 | const Shop = mongoose.model('Shop', shopSchema); 78 | 79 | export default Shop -------------------------------------------------------------------------------- /models/bos/order.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import mongoose from 'mongoose' 4 | 5 | const Schema = mongoose.Schema; 6 | 7 | const orderSchema = new Schema({ 8 | basket: { 9 | abandoned_extra: [ 10 | { 11 | category_id: Number, 12 | name: {type: String, default: ''}, 13 | price: {type: Number, default: 0}, 14 | quantity: {type: Number, default: 0}, 15 | } 16 | ], 17 | deliver_fee: { 18 | category_id: {type: Number, default: 2}, 19 | name: {type: String, default: '配送费'}, 20 | price: {type: Number, default: 4}, 21 | quantity: {type: Number, default: 1}, 22 | }, 23 | extra: [], 24 | group: [ 25 | [ 26 | { 27 | attrs: [], 28 | new_specs: [], 29 | name: String, 30 | price: Number, 31 | quantity: Number, 32 | specs: [String] 33 | } 34 | ] 35 | ], 36 | packing_fee: { 37 | category_id: {type: Number, default: 1}, 38 | name: {type: String, default: '餐盒'}, 39 | price: Number, 40 | quantity: Number 41 | }, 42 | pindan_map: [] 43 | }, 44 | formatted_created_at: String, 45 | order_time: Number, 46 | time_pass: Number, 47 | id: Number, 48 | is_brand: {type: Number, default: 0}, 49 | is_deletable: {type: Number, default: 1}, 50 | is_new_pay: {type: Number, default: 1}, 51 | is_pindan: {type: Number, default: 0}, 52 | operation_confirm: {type: Number, default: 0}, 53 | operation_pay: {type: Number, default: 0}, 54 | operation_rate: {type: Number, default: 0}, 55 | operation_rebuy: {type: Number, default: 2}, 56 | operation_upload_photo: {type: Number, default: 0}, 57 | pay_remain_seconds: {type: Number, default: 0}, 58 | rated_point: {type: Number, default: 0}, 59 | remind_reply_count: {type: Number, default: 0}, 60 | restaurant_id: Number, 61 | restaurant_image_hash: String, 62 | restaurant_image_url: String, 63 | restaurant_name: String, 64 | restaurant_type: {type: Number, default: 0}, 65 | status_bar: { 66 | color: String, 67 | image_type: String, 68 | sub_title: String, 69 | title: String, 70 | }, 71 | status_code: {type: Number, default: 0}, 72 | timeline_node: { 73 | actions: [], 74 | description: String, 75 | in_processing: {type: Number, default: 0}, 76 | sub_description: String, 77 | title: String, 78 | }, 79 | top_show: {type: Number, default: 0}, 80 | total_amount: Number, 81 | total_quantity: Number, 82 | unique_id: Number, 83 | user_id: Number, 84 | address_id: Number, 85 | }) 86 | 87 | orderSchema.index({id: 1}); 88 | 89 | const Order = mongoose.model('Order', orderSchema); 90 | 91 | export default Order -------------------------------------------------------------------------------- /public/elm/static/js/manifest.js: -------------------------------------------------------------------------------- 1 | !function(e){function a(d){if(c[d])return c[d].exports;var f=c[d]={exports:{},id:d,loaded:!1};return e[d].call(f.exports,f,f.exports,a),f.loaded=!0,f.exports}var d=window.webpackJsonp;window.webpackJsonp=function(b,o){for(var r,t,i=0,n=[];i { 75 | cityName += item[0]; 76 | }) 77 | return cityName; 78 | }catch(err){ 79 | return '北京'; 80 | } 81 | } 82 | async getExactAddress(req, res, next){ 83 | try{ 84 | const position = await this.geocoder(req) 85 | res.send(position); 86 | }catch(err){ 87 | console.log('获取精确位置信息失败'); 88 | res.send({ 89 | name: 'ERROR_DATA', 90 | message: '获取精确位置信息失败', 91 | }); 92 | } 93 | } 94 | async pois(req, res, next){ 95 | try{ 96 | const geohash = req.params.geohash || ''; 97 | if (geohash.indexOf(',') == -1) { 98 | res.send({ 99 | status: 0, 100 | type: 'ERROR_PARAMS', 101 | message: '参数错误', 102 | }) 103 | return; 104 | } 105 | const poisArr = geohash.split(','); 106 | const result = await this.getpois(poisArr[0], poisArr[1]); 107 | const address = { 108 | address: result.result.address, 109 | city: result.result.address_component.province, 110 | geohash, 111 | latitude: poisArr[0], 112 | longitude: poisArr[1], 113 | name: result.result.formatted_addresses.recommend, 114 | } 115 | res.send(address); 116 | }catch(err){ 117 | console.log('getpois返回信息失败', err); 118 | res.send({ 119 | status: 0, 120 | type: 'ERROR_DATA', 121 | message: '获取数据失败', 122 | }) 123 | } 124 | } 125 | } 126 | export default new CityHandle() -------------------------------------------------------------------------------- /InitData/rate.js: -------------------------------------------------------------------------------- 1 | export const ratingList = [{"avatar":"","highlights":[],"item_ratings":[{"food_id":508807792,"food_name":"超级至尊比萨-铁盘","image_hash":"dc864033625905f0a15a2d181d53a425jpeg","is_valid":1},{"food_id":508808743,"food_name":"韩式浓情风味鸡(标准份)","image_hash":"074e0e203f613deff4e456c31e4177d1jpeg","is_valid":1}],"rated_at":"2017-02-10","rating_star":5,"rating_text":"","tags":[],"time_spent_desc":"按时送达","username":"4*******b"},{"avatar":"15f6cf782b0c9cd5ca8daa7f76ab05aejpeg","highlights":[],"item_ratings":[{"food_id":508809467,"food_name":"香草凤尾虾-5只装","image_hash":"","is_valid":1},{"food_id":508808754,"food_name":"鸡茸蘑菇汤","image_hash":"5388b26ad173389d89e0e015dbf295fcjpeg","is_valid":1}],"rated_at":"2017-02-09","rating_star":5,"rating_text":"","tags":[],"time_spent_desc":"","username":"t****n"},{"avatar":"","highlights":[],"item_ratings":[{"food_id":508809480,"food_name":"冰柠檬红茶(标准份)","image_hash":"","is_valid":1}],"rated_at":"2017-01-18","rating_star":5,"rating_text":"","tags":[],"time_spent_desc":"","username":",******C"},{"avatar":"","highlights":[],"item_ratings":[],"rated_at":"2017-02-10","rating_star":5,"rating_text":"","tags":[],"time_spent_desc":"","username":"试******春"},{"avatar":"1b523ca27369a0eed1ce0c3fc0a5ba8bjpeg","highlights":[],"item_ratings":[{"food_id":529149980,"food_name":"富贵“鸡”祥大吉大利比萨","image_hash":"","is_valid":1},{"food_id":144654782,"food_name":"热柠檬红茶","image_hash":"","is_valid":1}],"rated_at":"2017-02-10","rating_star":5,"rating_text":"","tags":[],"time_spent_desc":"","username":"王******a"},{"avatar":"","highlights":[],"item_ratings":[{"food_id":508808726,"food_name":"加州风情香烤牛肉比萨-铁盘","image_hash":"","is_valid":1},{"food_id":508810265,"food_name":"海鲜至尊比萨-铁盘","image_hash":"","is_valid":1},{"food_id":508807792,"food_name":"超级至尊比萨-铁盘","image_hash":"","is_valid":1}],"rated_at":"2017-02-10","rating_star":5,"rating_text":"","tags":[],"time_spent_desc":"","username":"3*******7"},{"avatar":"","highlights":[],"item_ratings":[{"food_id":529149980,"food_name":"富贵“鸡”祥大吉大利比萨","image_hash":"","is_valid":1},{"food_id":508808743,"food_name":"韩式浓情风味鸡(标准份)","image_hash":"","is_valid":1}],"rated_at":"2017-02-10","rating_star":5,"rating_text":"","tags":[],"time_spent_desc":"","username":"3*******6"},{"avatar":"818cf0c977c77ca365557230db619a18jpeg","highlights":[],"item_ratings":[],"rated_at":"2017-02-10","rating_star":5,"rating_text":"送餐速度很快!","tags":[],"time_spent_desc":"","username":"3*******7"},{"avatar":"","highlights":[],"item_ratings":[],"rated_at":"2017-02-10","rating_star":5,"rating_text":"","tags":[],"time_spent_desc":"","username":"3*******b"},{"avatar":"","highlights":[],"item_ratings":[],"rated_at":"2017-02-09","rating_star":5,"rating_text":"","tags":[],"time_spent_desc":"","username":"景***0"}]; 2 | 3 | export const scores = {"compare_rating":0.76869,"deliver_time":40,"food_score":4.76378,"order_rating_amount":473,"overall_score":4.72836,"service_score":4.69295}; 4 | 5 | export const tags = [{"count":473,"name":"全部","unsatisfied":false},{"count":453,"name":"满意","unsatisfied":false},{"count":20,"name":"不满意","unsatisfied":true},{"count":2,"name":"有图","unsatisfied":false},{"count":47,"name":"味道好","unsatisfied":false},{"count":32,"name":"送货快","unsatisfied":false},{"count":18,"name":"分量足","unsatisfied":false},{"count":15,"name":"包装精美","unsatisfied":false},{"count":15,"name":"干净卫生","unsatisfied":false},{"count":15,"name":"食材新鲜","unsatisfied":false},{"count":11,"name":"服务不错","unsatisfied":false}]; -------------------------------------------------------------------------------- /controller/statis/statis.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | import StatisModel from '../../models/statis/statis' 4 | import UserInfoModel from '../../models/v2/userInfo' 5 | import OrderModel from '../../models/bos/order' 6 | import dtime from 'time-formater' 7 | import AdminModel from '../../models/admin/admin' 8 | 9 | class Statis { 10 | constructor(){ 11 | 12 | } 13 | async apiCount(req, res, next){ 14 | const date = req.params.date; 15 | if (!date) { 16 | console.log('参数错误') 17 | res.send({ 18 | status: 0, 19 | type: 'ERROR_PARAMS', 20 | message: '参数错误' 21 | }) 22 | return 23 | } 24 | try{ 25 | const count = await StatisModel.find({date}).count() 26 | res.send({ 27 | status: 1, 28 | count, 29 | }) 30 | }catch(err){ 31 | console.log('获取当天API请求次数失败'); 32 | res.send({ 33 | status: 0, 34 | type: 'ERROR_GET_TODAY_API_COUNT', 35 | message: '获取当天API请求次数失败' 36 | }) 37 | } 38 | } 39 | async apiAllCount(req, res, next){ 40 | try{ 41 | const count = await StatisModel.count() 42 | res.send({ 43 | status: 1, 44 | count, 45 | }) 46 | }catch(err){ 47 | console.log('获取所有API请求次数失败'); 48 | res.send({ 49 | status: 0, 50 | type: 'ERROR_GET_ALL_API_COUNT', 51 | message: '获取所有API请求次数失败' 52 | }) 53 | } 54 | } 55 | async allApiRecord(req, res, next){ 56 | try{ 57 | const allRecord = await StatisModel.find({}, '-_id -__v') 58 | res.send(allRecord) 59 | }catch(err){ 60 | console.log('获取所有API请求信息失败'); 61 | res.send({ 62 | status: 0, 63 | type: 'GET_ALL_API_RECORD_DATA_FAILED', 64 | message: '获取所有API请求信息失败' 65 | }) 66 | } 67 | } 68 | async userCount(req, res, next){ 69 | const date = req.params.date; 70 | if (!date) { 71 | console.log('参数错误') 72 | res.send({ 73 | status: 0, 74 | type: 'ERROR_PARAMS', 75 | message: '参数错误' 76 | }) 77 | return 78 | } 79 | try{ 80 | const count = await UserInfoModel.find({registe_time: eval('/^' + date + '/gi')}).count() 81 | res.send({ 82 | status: 1, 83 | count, 84 | }) 85 | }catch(err){ 86 | console.log('获取当天注册人数失败'); 87 | res.send({ 88 | status: 0, 89 | type: 'ERROR_GET_USER_REGISTE_COUNT', 90 | message: '获取当天注册人数失败' 91 | }) 92 | } 93 | } 94 | async adminCount(req, res, next){ 95 | const date = req.params.date; 96 | if (!date) { 97 | console.log('参数错误') 98 | res.send({ 99 | status: 0, 100 | type: 'ERROR_PARAMS', 101 | message: '参数错误' 102 | }) 103 | return 104 | } 105 | try{ 106 | const count = await AdminModel.find({create_time: eval('/^' + date + '/gi')}).count() 107 | res.send({ 108 | status: 1, 109 | count, 110 | }) 111 | }catch(err){ 112 | console.log('获取当天注册管理员人数失败'); 113 | res.send({ 114 | status: 0, 115 | type: 'ERROR_GET_ADMIN_REGISTE_COUNT', 116 | message: '获取当天注册管理员人数失败' 117 | }) 118 | } 119 | } 120 | async orderCount(req, res, next){ 121 | const date = req.params.date; 122 | if (!date) { 123 | console.log('参数错误') 124 | res.send({ 125 | status: 0, 126 | type: 'ERROR_PARAMS', 127 | message: '参数错误' 128 | }) 129 | return 130 | } 131 | try{ 132 | const count = await OrderModel.find({formatted_created_at: eval('/^' + date + '/gi')}).count() 133 | res.send({ 134 | status: 1, 135 | count, 136 | }) 137 | }catch(err){ 138 | console.log('获取当天订单数量失败'); 139 | res.send({ 140 | status: 0, 141 | type: 'ERROR_GET_ORDER_COUNT', 142 | message: '获取当天订单数量失败' 143 | }) 144 | } 145 | } 146 | } 147 | 148 | export default new Statis() -------------------------------------------------------------------------------- /controller/v1/address.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import BaseComponent from '../../prototype/baseComponent' 4 | import AddressModel from '../../models/v1/address' 5 | import formidable from 'formidable' 6 | 7 | class Address extends BaseComponent{ 8 | constructor(){ 9 | super() 10 | this.addAddress = this.addAddress.bind(this); 11 | 12 | } 13 | async getAddress(req, res, next){ 14 | const user_id = req.params.user_id; 15 | if (!user_id || !Number(user_id)) { 16 | res.send({ 17 | type: 'ERROR_USER_ID', 18 | message: 'user_id参数错误', 19 | }) 20 | return 21 | } 22 | try{ 23 | const addressList = await AddressModel.find({user_id}, '-_id'); 24 | res.send(addressList) 25 | }catch(err){ 26 | console.log('获取收获地址失败', err); 27 | res.send({ 28 | type: 'ERROR_GET_ADDRESS', 29 | message: '获取地址列表失败' 30 | }) 31 | } 32 | } 33 | async addAddress(req, res, next){ 34 | const form = new formidable.IncomingForm(); 35 | form.parse(req, async (err, fields, files) => { 36 | const user_id = req.params.user_id; 37 | const {address, address_detail, geohash, name, phone, phone_bk, poi_type = 0, sex, tag, tag_type} = fields; 38 | try{ 39 | if (!user_id || !Number(user_id)) { 40 | throw new Error('用户ID参数错误'); 41 | }else if(!address){ 42 | throw new Error('地址信息错误'); 43 | }else if(!address_detail){ 44 | throw new Error('详细地址信息错误'); 45 | }else if(!geohash){ 46 | throw new Error('geohash参数错误'); 47 | }else if(!name){ 48 | throw new Error('收货人姓名错误'); 49 | }else if(!phone){ 50 | throw new Error('收获手机号错误'); 51 | }else if(!sex){ 52 | throw new Error('性别错误'); 53 | }else if(!tag){ 54 | throw new Error('标签错误'); 55 | }else if(!tag_type){ 56 | throw new Error('标签类型错误'); 57 | } 58 | }catch(err){ 59 | console.log(err.message); 60 | res.send({ 61 | status: 0, 62 | type: 'GET_WRONG_PARAM', 63 | message: err.message 64 | }) 65 | return 66 | } 67 | try{ 68 | const address_id = await this.getId('address_id'); 69 | const newAddress = { 70 | id: address_id, 71 | address, 72 | phone, 73 | phone_bk: phone_bk&&phone_bk, 74 | name, 75 | st_geohash: geohash, 76 | address_detail, 77 | sex, 78 | tag, 79 | tag_type, 80 | user_id, 81 | } 82 | await AddressModel.create(newAddress); 83 | res.send({ 84 | status: 1, 85 | success: '添加地址成功' 86 | }) 87 | }catch(err){ 88 | console.log('添加地址失败', err); 89 | res.send({ 90 | status: 0, 91 | type: 'ERROR_ADD_ADDRESS', 92 | message: '添加地址失败' 93 | }) 94 | } 95 | }) 96 | } 97 | async deleteAddress(req, res, next){ 98 | const {user_id, address_id} = req.params; 99 | if (!user_id || !Number(user_id) || !address_id || !Number(address_id)) { 100 | res.send({ 101 | type: 'ERROR_PARAMS', 102 | message: '参数错误', 103 | }) 104 | return 105 | } 106 | try{ 107 | await AddressModel.findOneAndRemove({id: address_id}); 108 | res.send({ 109 | status: 1, 110 | success: '删除地址成功', 111 | }) 112 | }catch(err){ 113 | console.log('删除收获地址失败', err); 114 | res.send({ 115 | type: 'ERROR_DELETE_ADDRESS', 116 | message: '删除收获地址失败' 117 | }) 118 | } 119 | } 120 | async getAddAddressById(req, res, next){ 121 | const address_id = req.params.address_id; 122 | if (!address_id || !Number(address_id)) { 123 | res.send({ 124 | type: 'ERROR_PARAMS', 125 | message: '参数错误', 126 | }) 127 | return 128 | } 129 | try{ 130 | const address = await AddressModel.findOne({id: address_id}); 131 | res.send(address) 132 | }catch(err){ 133 | console.log('获取地址信息失败', err); 134 | res.send({ 135 | type: 'ERROR_GET_ADDRESS', 136 | message: '获取地址信息失败' 137 | }) 138 | } 139 | } 140 | } 141 | 142 | export default new Address() -------------------------------------------------------------------------------- /controller/v1/carts.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import AddressComponent from '../../prototype/addressComponent' 4 | import formidable from 'formidable' 5 | import PaymentsModel from '../../models/v1/payments' 6 | import ShopModel from '../../models/shopping/shop' 7 | import CartModel from '../../models/v1/cart' 8 | 9 | class Carts extends AddressComponent{ 10 | constructor(){ 11 | super(); 12 | this.extra = [{ 13 | description: '', 14 | name: '餐盒', 15 | price: 0, 16 | quantity: 1, 17 | type: 0, 18 | }] 19 | this.checkout = this.checkout.bind(this); 20 | } 21 | async checkout(req, res, next){ 22 | const UID = req.session.UID; 23 | const form = new formidable.IncomingForm(); 24 | form.parse(req, async (err, fields, files) => { 25 | const {come_from, geohash, entities = [], restaurant_id} = fields; 26 | try{ 27 | if(!(entities instanceof Array) || !entities.length){ 28 | throw new Error('entities参数错误') 29 | }else if(!(entities[0] instanceof Array) || !entities[0].length){ 30 | throw new Error('entities参数错误') 31 | }else if(!restaurant_id){ 32 | throw new Error('restaurant_id参数错误') 33 | } 34 | }catch(err){ 35 | console.log(err); 36 | res.send({ 37 | status: 0, 38 | type: 'ERROR_PARAMS', 39 | message: err.message 40 | }) 41 | return 42 | } 43 | let payments; //付款方式 44 | let cart_id; //购物车id 45 | let restaurant; //餐馆详情 46 | let deliver_time; //配送时间 47 | let delivery_reach_time; //到达时间 48 | let from = geohash.split(',')[0] + ',' + geohash.split(',')[1]; 49 | try{ 50 | payments = await PaymentsModel.find({}, '-_id'); 51 | cart_id = await this.getId('cart_id'); 52 | restaurant = await ShopModel.findOne({id: restaurant_id}); 53 | const to = restaurant.latitude+ ',' + restaurant.longitude; 54 | deliver_time = await this.getDistance(from, to, 'tiemvalue'); 55 | let time = new Date().getTime() + deliver_time*1000; 56 | let hour = ('0' + new Date(time).getHours()).substr(-2); 57 | let minute = ('0' + new Date(time).getMinutes()).substr(-2); 58 | delivery_reach_time = hour + ':' + minute; 59 | }catch(err){ 60 | console.log('获取数据数据失败', err); 61 | res.send({ 62 | status: 0, 63 | type: 'ERROR_DATA', 64 | message: '添加购物车失败', 65 | }) 66 | return 67 | } 68 | const deliver_amount = 4; 69 | let price = 0; //食品价格 70 | entities[0].map(item => { 71 | price += item.price * item.quantity; 72 | if (item.packing_fee) { 73 | this.extra[0].price += item.packing_fee*item.quantity; 74 | } 75 | if (item.specs[0]) { 76 | return item.name = item.name + '-' + item.specs[0]; 77 | } 78 | }) 79 | //食品总价格 80 | const total = price + this.extra[0].price * this.extra[0].quantity + deliver_amount; 81 | //是否支持发票 82 | let invoice = { 83 | is_available: false, 84 | status_text: "商家不支持开发票", 85 | }; 86 | restaurant.supports.forEach(item => { 87 | if (item.icon_name == '票') { 88 | invoice = { 89 | is_available: true, 90 | status_text: "不需要开发票", 91 | }; 92 | } 93 | }) 94 | const checkoutInfo = { 95 | id: cart_id, 96 | cart: { 97 | id: cart_id, 98 | groups: entities, 99 | extra: this.extra, 100 | deliver_amount, 101 | is_deliver_by_fengniao: !!restaurant.delivery_mode, 102 | original_total: total, 103 | phone: restaurant.phone, 104 | restaurant_id, 105 | restaurant_info: restaurant, 106 | restaurant_minimum_order_amount: restaurant.float_minimum_order_amount, 107 | total, 108 | user_id: UID, 109 | }, 110 | delivery_reach_time, 111 | invoice, 112 | sig: Math.ceil(Math.random()*1000000).toString(), 113 | payments, 114 | } 115 | try{ 116 | const newCart = new CartModel(checkoutInfo); 117 | const cart = await newCart.save(); 118 | res.send(cart) 119 | }catch(err){ 120 | console.log('保存购物车数据失败'); 121 | res.send({ 122 | status: 0, 123 | type: 'ERROR_TO_SAVE_CART', 124 | message: '加入购物车失败' 125 | }) 126 | } 127 | }) 128 | } 129 | } 130 | 131 | export default new Carts() -------------------------------------------------------------------------------- /prototype/baseComponent.js: -------------------------------------------------------------------------------- 1 | import fetch from 'node-fetch'; 2 | import Ids from '../models/ids' 3 | import formidable from 'formidable' 4 | import path from 'path' 5 | import fs from 'fs' 6 | import qiniu from 'qiniu' 7 | import gm from 'gm' 8 | qiniu.conf.ACCESS_KEY = 'Ep714TDrVhrhZzV2VJJxDYgGHBAX-KmU1xV1SQdS'; 9 | qiniu.conf.SECRET_KEY = 'XNIW2dNffPBdaAhvm9dadBlJ-H6yyCTIJLxNM_N6'; 10 | 11 | 12 | export default class BaseComponent { 13 | constructor(){ 14 | this.idList = ['restaurant_id', 'food_id', 'order_id', 'user_id', 'address_id', 'cart_id', 'img_id', 'category_id', 'item_id', 'sku_id', 'admin_id', 'statis_id']; 15 | this.imgTypeList = ['shop', 'food', 'avatar','default']; 16 | this.uploadImg = this.uploadImg.bind(this) 17 | this.qiniu = this.qiniu.bind(this) 18 | } 19 | async fetch(url = '', data = {}, type = 'GET', resType = 'JSON'){ 20 | type = type.toUpperCase(); 21 | resType = resType.toUpperCase(); 22 | if (type == 'GET') { 23 | let dataStr = ''; //数据拼接字符串 24 | Object.keys(data).forEach(key => { 25 | dataStr += key + '=' + data[key] + '&'; 26 | }) 27 | 28 | if (dataStr !== '') { 29 | dataStr = dataStr.substr(0, dataStr.lastIndexOf('&')); 30 | url = url + '?' + dataStr; 31 | } 32 | } 33 | 34 | let requestConfig = { 35 | method: type, 36 | headers: { 37 | 'Accept': 'application/json', 38 | 'Content-Type': 'application/json' 39 | }, 40 | } 41 | 42 | if (type == 'POST') { 43 | Object.defineProperty(requestConfig, 'body', { 44 | value: JSON.stringify(data) 45 | }) 46 | } 47 | let responseJson; 48 | try { 49 | const response = await fetch(url, requestConfig); 50 | if (resType === 'TEXT') { 51 | responseJson = await response.text(); 52 | }else{ 53 | responseJson = await response.json(); 54 | } 55 | } catch (err) { 56 | console.log('获取http数据失败', err); 57 | throw new Error(err) 58 | } 59 | return responseJson 60 | } 61 | //获取id列表 62 | async getId(type){ 63 | if (!this.idList.includes(type)) { 64 | console.log('id类型错误'); 65 | throw new Error('id类型错误'); 66 | return 67 | } 68 | try{ 69 | const idData = await Ids.findOne(); 70 | idData[type] ++ ; 71 | await idData.save(); 72 | return idData[type] 73 | }catch(err){ 74 | console.log('获取ID数据失败'); 75 | throw new Error(err) 76 | } 77 | } 78 | 79 | async uploadImg(req, res, next){ 80 | const type = req.params.type; 81 | try{ 82 | //const image_path = await this.qiniu(req, type); 83 | const image_path = await this.getPath(req, res); 84 | res.send({ 85 | status: 1, 86 | image_path, 87 | }) 88 | }catch(err){ 89 | console.log('上传图片失败', err); 90 | res.send({ 91 | status: 0, 92 | type: 'ERROR_UPLOAD_IMG', 93 | message: '上传图片失败' 94 | }) 95 | } 96 | } 97 | 98 | async getPath(req, res){ 99 | return new Promise((resolve, reject) => { 100 | const form = formidable.IncomingForm(); 101 | form.uploadDir = './public/img'; 102 | form.parse(req, async (err, fields, files) => { 103 | let img_id; 104 | try{ 105 | img_id = await this.getId('img_id'); 106 | }catch(err){ 107 | console.log('获取图片id失败'); 108 | fs.unlinkSync(files.file.path); 109 | reject('获取图片id失败'); 110 | } 111 | const hashName = (new Date().getTime() + Math.ceil(Math.random()*10000)).toString(16) + img_id; 112 | const extname = path.extname(files.file.name); 113 | if (!['.jpg', '.jpeg', '.png'].includes(extname)) { 114 | fs.unlinkSync(files.file.path); 115 | res.send({ 116 | status: 0, 117 | type: 'ERROR_EXTNAME', 118 | message: '文件格式错误' 119 | }) 120 | reject('上传失败'); 121 | return 122 | } 123 | const fullName = hashName + extname; 124 | const repath = './public/img/' + fullName; 125 | try{ 126 | fs.renameSync(files.file.path, repath); 127 | gm(repath) 128 | .resize(200, 200, "!") 129 | .write(repath, async (err) => { 130 | // if(err){ 131 | // console.log('裁切图片失败'); 132 | // reject('裁切图片失败'); 133 | // return 134 | // } 135 | resolve(fullName) 136 | }) 137 | }catch(err){ 138 | console.log('保存图片失败', err); 139 | if (fs.existsSync(repath)) { 140 | fs.unlinkSync(repath); 141 | } else { 142 | fs.unlinkSync(files.file.path); 143 | } 144 | reject('保存图片失败') 145 | } 146 | }); 147 | }) 148 | } 149 | 150 | async qiniu(req, type = 'default'){ 151 | return new Promise((resolve, reject) => { 152 | const form = formidable.IncomingForm(); 153 | form.uploadDir = './public/img'; 154 | form.parse(req, async (err, fields, files) => { 155 | let img_id; 156 | try{ 157 | img_id = await this.getId('img_id'); 158 | }catch(err){ 159 | console.log('获取图片id失败'); 160 | fs.unlinkSync(files.file.path); 161 | reject('获取图片id失败') 162 | } 163 | const hashName = (new Date().getTime() + Math.ceil(Math.random()*10000)).toString(16) + img_id; 164 | const extname = path.extname(files.file.name); 165 | const repath = './public/img/' + hashName + extname; 166 | try{ 167 | const key = hashName + extname; 168 | await fs.rename(files.file.path, repath); 169 | const token = this.uptoken('node-elm', key); 170 | const qiniuImg = await this.uploadFile(token.toString(), key, repath); 171 | fs.unlinkSync(repath); 172 | resolve(qiniuImg) 173 | }catch(err){ 174 | console.log('保存至七牛失败', err); 175 | fs.unlinkSync(files.file.path) 176 | reject('保存至七牛失败') 177 | } 178 | }); 179 | 180 | }) 181 | } 182 | uptoken(bucket, key){ 183 | var putPolicy = new qiniu.rs.PutPolicy(bucket+":"+key); 184 | return putPolicy.token(); 185 | } 186 | uploadFile(uptoken, key, localFile){ 187 | return new Promise((resolve, reject) => { 188 | var extra = new qiniu.io.PutExtra(); 189 | qiniu.io.putFile(uptoken, key, localFile, extra, function(err, ret) { 190 | if(!err) { 191 | resolve(ret.key) 192 | } else { 193 | console.log('图片上传至七牛失败', err); 194 | reject(err) 195 | } 196 | }); 197 | 198 | }) 199 | } 200 | } -------------------------------------------------------------------------------- /prototype/addressComponent.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import BaseComponent from './baseComponent' 4 | 5 | /* 6 | 腾讯地图和百度地图API统一调配组件 7 | */ 8 | class AddressComponent extends BaseComponent { 9 | constructor(){ 10 | super(); 11 | this.tencentkey = 'RLHBZ-WMPRP-Q3JDS-V2IQA-JNRFH-EJBHL'; 12 | this.tencentkey2 = 'RRXBZ-WC6KF-ZQSJT-N2QU7-T5QIT-6KF5X'; 13 | this.tencentkey3 = 'OHTBZ-7IFRG-JG2QF-IHFUK-XTTK6-VXFBN'; 14 | this.tencentkey4 = 'Z2BBZ-QBSKJ-DFUFG-FDGT3-4JRYV-JKF5O'; 15 | this.baidukey = 'fjke3YUipM9N64GdOIh1DNeK2APO2WcT'; 16 | // this.baidukey2 = 'fjke3YUipM9N64GdOIh1DNeK2APO2WcT'; 17 | } 18 | //获取定位地址 19 | async guessPosition(req){ 20 | return new Promise(async (resolve, reject) => { 21 | let ip; 22 | const defaultIp = '180.158.102.141'; 23 | if (process.env.NODE_ENV == 'development') { 24 | ip = defaultIp; 25 | } else { 26 | try { 27 | ip = req.headers['x-forwarded-for'] || 28 | req.connection.remoteAddress || 29 | req.socket.remoteAddress || 30 | req.connection.socket.remoteAddress; 31 | const ipArr = ip.split(':'); 32 | ip = ipArr[ipArr.length -1] || defaultIp; 33 | } catch (e) { 34 | ip = defaultIp; 35 | } 36 | } 37 | try{ 38 | let result = await this.fetch('http://apis.map.qq.com/ws/location/v1/ip', { 39 | ip, 40 | key: this.tencentkey, 41 | }) 42 | if (result.status != 0) { 43 | result = await this.fetch('http://apis.map.qq.com/ws/location/v1/ip', { 44 | ip, 45 | key: this.tencentkey2, 46 | }) 47 | } 48 | if (result.status != 0) { 49 | result = await this.fetch('http://apis.map.qq.com/ws/location/v1/ip', { 50 | ip, 51 | key: this.tencentkey3, 52 | }) 53 | } 54 | if (result.status != 0) { 55 | result = await this.fetch('http://apis.map.qq.com/ws/location/v1/ip', { 56 | ip, 57 | key: this.tencentkey4, 58 | }) 59 | } 60 | if (result.status == 0) { 61 | const cityInfo = { 62 | lat: result.result.location.lat, 63 | lng: result.result.location.lng, 64 | city: result.result.ad_info.city, 65 | } 66 | cityInfo.city = cityInfo.city.replace(/市$/, ''); 67 | resolve(cityInfo) 68 | }else{ 69 | console.log('定位失败', result) 70 | reject('定位失败'); 71 | } 72 | }catch(err){ 73 | reject(err); 74 | } 75 | }) 76 | } 77 | //搜索地址 78 | async searchPlace(keyword, cityName, type = 'search'){ 79 | try{ 80 | const resObj = await this.fetch('http://apis.map.qq.com/ws/place/v1/search', { 81 | key: this.tencentkey, 82 | keyword: encodeURIComponent(keyword), 83 | boundary: 'region(' + encodeURIComponent(cityName) + ',0)', 84 | page_size: 10, 85 | }); 86 | if (resObj.status == 0) { 87 | return resObj 88 | }else{ 89 | throw new Error('搜索位置信息失败'); 90 | } 91 | }catch(err){ 92 | throw new Error(err); 93 | } 94 | } 95 | //测量距离 96 | async getDistance(from, to, type){ 97 | try{ 98 | let res 99 | res = await this.fetch('http://api.map.baidu.com/routematrix/v2/driving', { 100 | ak: this.baidukey, 101 | output: 'json', 102 | origins: from, 103 | destinations: to, 104 | }) 105 | // if(res.status !== 0){ 106 | // res = await this.fetch('http://api.map.baidu.com/routematrix/v2/driving', { 107 | // ak: this.baidukey2, 108 | // output: 'json', 109 | // origins: from, 110 | // destinations: to, 111 | // }) 112 | // } 113 | if(res.status == 0){ 114 | const positionArr = []; 115 | let timevalue; 116 | res.result.forEach(item => { 117 | timevalue = parseInt(item.duration.value) + 1200; 118 | let durationtime = Math.ceil(timevalue%3600/60) + '分钟'; 119 | if(Math.floor(timevalue/3600)){ 120 | durationtime = Math.floor(timevalue/3600) + '小时' + durationtime; 121 | } 122 | positionArr.push({ 123 | distance: item.distance.text, 124 | order_lead_time: durationtime, 125 | }) 126 | }) 127 | if (type == 'tiemvalue') { 128 | return timevalue 129 | }else{ 130 | return positionArr 131 | } 132 | }else{ 133 | if (type == 'tiemvalue') { 134 | return 2000; 135 | } else { 136 | throw new Error('调用百度地图测距失败'); 137 | } 138 | } 139 | }catch(err){ 140 | console.log('获取位置距离失败'); 141 | throw new Error(err); 142 | } 143 | } 144 | //通过ip地址获取精确位置 145 | async geocoder(req){ 146 | try{ 147 | const address = await this.guessPosition(req); 148 | const params = { 149 | key: this.tencentkey, 150 | location: address.lat + ',' + address.lng 151 | }; 152 | let res = await this.fetch('http://apis.map.qq.com/ws/geocoder/v1/', params); 153 | if (res.status != 0) { 154 | params.key = this.tencentkey2; 155 | res = await this.fetch('http://apis.map.qq.com/ws/geocoder/v1/', params); 156 | } 157 | if (res.status != 0) { 158 | params.key = this.tencentkey3; 159 | res = await this.fetch('http://apis.map.qq.com/ws/geocoder/v1/', params); 160 | } 161 | if (res.status != 0) { 162 | params.key = this.tencentkey4; 163 | res = await this.fetch('http://apis.map.qq.com/ws/geocoder/v1/', params); 164 | } 165 | if (res.status == 0) { 166 | return res 167 | }else{ 168 | throw new Error('获取具体位置信息失败'); 169 | } 170 | }catch(err){ 171 | console.log('geocoder获取定位失败', err); 172 | throw new Error(err); 173 | } 174 | } 175 | //通过geohash获取精确位置 176 | async getpois(lat, lng){ 177 | try{ 178 | const params = { 179 | key: this.tencentkey, 180 | location: lat + ',' + lng 181 | }; 182 | let res = await this.fetch('http://apis.map.qq.com/ws/geocoder/v1/', params); 183 | if (res.status != 0) { 184 | params.key = this.tencentkey2; 185 | res = await this.fetch('http://apis.map.qq.com/ws/geocoder/v1/', params); 186 | } 187 | if (res.status != 0) { 188 | params.key = this.tencentkey3; 189 | res = await this.fetch('http://apis.map.qq.com/ws/geocoder/v1/', params); 190 | } 191 | if (res.status != 0) { 192 | params.key = this.tencentkey4; 193 | res = await this.fetch('http://apis.map.qq.com/ws/geocoder/v1/', params); 194 | } 195 | if (res.status == 0) { 196 | return res 197 | }else{ 198 | throw new Error('通过获geohash取具体位置失败'); 199 | } 200 | }catch(err){ 201 | console.log('getpois获取定位失败', err) 202 | throw new Error(err); 203 | } 204 | } 205 | } 206 | 207 | export default AddressComponent -------------------------------------------------------------------------------- /public/elm/static/js/invoice.7a9e2184152292b47d94.min.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([42,45],{5:function(e,t,a){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var n=a(10),o=i(n),r=a(4);t.default={data:function(){return{}},mounted:function(){this.getUserInfo()},props:["signinUp","headTitle","goBack"],computed:(0,o.default)({},(0,r.mapState)(["userInfo"])),methods:(0,o.default)({},(0,r.mapActions)(["getUserInfo"]))}},6:function(e,t,a){t=e.exports=a(2)(),t.push([e.id,"#head_top[data-v-cec0c0c0]{background-color:#3190e8;position:fixed;z-index:100;left:0;top:0;width:100%;height:1.95rem}.head_goback[data-v-cec0c0c0]{left:.4rem;width:.6rem;height:1rem;line-height:2.2rem;margin-left:.4rem}.head_login[data-v-cec0c0c0]{right:.55rem;font-size:.65rem;color:#fff;position:absolute;top:50%;transform:translateY(-50%)}.head_login .login_span[data-v-cec0c0c0]{color:#fff}.head_login .user_avatar[data-v-cec0c0c0]{fill:#fff;width:.8rem;height:.8rem}.title_head[data-v-cec0c0c0]{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:50%;color:#fff;text-align:center}.title_head .title_text[data-v-cec0c0c0]{font-size:.8rem;color:#fff;text-align:center;font-weight:700}","",{version:3,sources:["/./src/components/header/head.vue"],names:[],mappings:"AACA,2BAA2B,yBAAyB,eAAe,YAAY,OAAO,MAAM,WAAW,cAAc,CACpH,AACD,8BAA8B,WAAY,YAAY,YAAY,mBAAmB,iBAAiB,CACrG,AACD,6BAA6B,aAAc,iBAAiB,WAAW,kBAAkB,QAAQ,AAAkE,0BAA0B,CAC5L,AACD,yCAAyC,UAAU,CAClD,AACD,0CAA0C,UAAU,YAAY,YAAY,CAC3E,AACD,6BAA6B,kBAAkB,QAAQ,SAAS,AAA4E,+BAAgC,UAAU,WAAW,iBAAiB,CACjN,AACD,yCAAyC,gBAAgB,WAAW,kBAAkB,eAAgB,CACrG",file:"head.vue",sourcesContent:["\n#head_top[data-v-cec0c0c0]{background-color:#3190e8;position:fixed;z-index:100;left:0;top:0;width:100%;height:1.95rem\n}\n.head_goback[data-v-cec0c0c0]{left:0.4rem;width:.6rem;height:1rem;line-height:2.2rem;margin-left:.4rem\n}\n.head_login[data-v-cec0c0c0]{right:0.55rem;font-size:.65rem;color:#fff;position:absolute;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)\n}\n.head_login .login_span[data-v-cec0c0c0]{color:#fff\n}\n.head_login .user_avatar[data-v-cec0c0c0]{fill:#fff;width:.8rem;height:.8rem\n}\n.title_head[data-v-cec0c0c0]{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%, -50%);-ms-transform:translate(-50%, -50%);transform:translate(-50%, -50%);width:50%;color:#fff;text-align:center\n}\n.title_head .title_text[data-v-cec0c0c0]{font-size:.8rem;color:#fff;text-align:center;font-weight:bold\n}\n"],sourceRoot:"webpack://"}])},7:function(e,t,a){var i=a(6);"string"==typeof i&&(i=[[e.id,i,""]]);a(3)(i,{});i.locals&&(e.exports=i.locals)},8:function(e,t,a){a(7);var i=a(1)(a(5),a(9),"data-v-cec0c0c0",null);e.exports=i.exports},9:function(e,t){e.exports={render:function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("header",{attrs:{id:"head_top"}},[e._t("logo"),e._v(" "),e._t("search"),e._v(" "),e.goBack?a("section",{staticClass:"head_goback",on:{click:function(t){e.$router.go(-1)}}},[a("svg",{attrs:{width:"100%",height:"100%",xmlns:"http://www.w3.org/2000/svg",version:"1.1"}},[a("polyline",{staticStyle:{fill:"none",stroke:"rgb(255,255,255)","stroke-width":"2"},attrs:{points:"12,18 4,9 12,0"}})])]):e._e(),e._v(" "),e.signinUp?a("router-link",{staticClass:"head_login",attrs:{to:e.userInfo?"/profile":"/login"}},[e.userInfo?a("svg",{staticClass:"user_avatar"},[a("use",{attrs:{"xmlns:xlink":"http://www.w3.org/1999/xlink","xlink:href":"#user"}})]):a("span",{staticClass:"login_span"},[e._v("登录|注册")])]):e._e(),e._v(" "),e.headTitle?a("section",{staticClass:"title_head ellipsis"},[a("span",{staticClass:"title_text"},[e._v(e._s(e.headTitle))])]):e._e(),e._v(" "),e._t("edit"),e._v(" "),e._t("msite-title"),e._v(" "),e._t("changecity"),e._v(" "),e._t("changeLogin")],2)},staticRenderFns:[]}},136:function(e,t,a){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var n=a(10),o=i(n),r=a(8),c=i(r),s=a(4);t.default={data:function(){return{invoice:!1}},components:{headTop:c.default},props:[],methods:(0,o.default)({},(0,s.mapMutations)(["CONFIRM_INVOICE"]),{chooseInvoice:function(){this.invoice=!this.invoice},confrimInvoice:function(){this.CONFIRM_INVOICE(this.invoice),this.$router.go(-1)}})}},253:function(e,t,a){t=e.exports=a(2)(),t.push([e.id,".rating_page[data-v-7bae01d6]{position:fixed;top:0;left:0;right:0;bottom:0;background-color:#f5f5f5;z-index:204;padding-top:1.95rem}.rating_page p[data-v-7bae01d6],.rating_page span[data-v-7bae01d6]{font-family:Helvetica Neue,Tahoma,Arial}.choose_invoice[data-v-7bae01d6]{display:-ms-flexbox;display:flex;-ms-flex-pack:justify;justify-content:space-between;-ms-flex-align:center;align-items:center;background-color:#fff;line-height:2.5rem;margin-top:.5rem;padding:0 .7rem}.choose_invoice span[data-v-7bae01d6]{font-size:.75rem;color:#333}.choose_invoice svg[data-v-7bae01d6]{width:.8rem;height:.8rem;fill:#999}.choose_invoice .choosed[data-v-7bae01d6]{fill:#4cd964}.determine[data-v-7bae01d6]{background-color:#4cd964;font-size:.7rem;color:#fff;text-align:center;margin:0 .7rem;line-height:1.8rem;border-radius:.2rem;margin-top:.5rem}","",{version:3,sources:["/./src/page/confirmOrder/children/invoice.vue"],names:[],mappings:"AACA,8BAA8B,eAAe,MAAM,OAAO,QAAQ,SAAS,yBAAyB,YAAY,mBAAmB,CAClI,AACD,mEAAmE,uCAAuC,CACzG,AACD,iCAA0E,oBAAoB,aAAa,AAA+D,sBAAsB,8BAA8B,AAAoD,sBAAsB,mBAAmB,sBAAsB,mBAAmB,iBAAkB,eAAe,CACpY,AACD,sCAAsC,iBAAiB,UAAU,CAChE,AACD,qCAAqC,YAAY,aAAa,SAAS,CACtE,AACD,0CAA0C,YAAY,CACrD,AACD,4BAA4B,yBAAyB,gBAAgB,WAAW,kBAAkB,eAAe,mBAAmB,oBAAqB,gBAAiB,CACzK",file:"invoice.vue",sourcesContent:["\n.rating_page[data-v-7bae01d6]{position:fixed;top:0;left:0;right:0;bottom:0;background-color:#f5f5f5;z-index:204;padding-top:1.95rem\n}\n.rating_page p[data-v-7bae01d6],.rating_page span[data-v-7bae01d6]{font-family:Helvetica Neue,Tahoma,Arial\n}\n.choose_invoice[data-v-7bae01d6]{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;background-color:#fff;line-height:2.5rem;margin-top:0.5rem;padding:0 .7rem\n}\n.choose_invoice span[data-v-7bae01d6]{font-size:.75rem;color:#333\n}\n.choose_invoice svg[data-v-7bae01d6]{width:.8rem;height:.8rem;fill:#999\n}\n.choose_invoice .choosed[data-v-7bae01d6]{fill:#4cd964\n}\n.determine[data-v-7bae01d6]{background-color:#4cd964;font-size:.7rem;color:#fff;text-align:center;margin:0 .7rem;line-height:1.8rem;border-radius:0.2rem;margin-top:0.5rem\n}\n"],sourceRoot:"webpack://"}])},302:function(e,t,a){var i=a(253);"string"==typeof i&&(i=[[e.id,i,""]]);a(3)(i,{});i.locals&&(e.exports=i.locals)},358:function(e,t,a){a(302);var i=a(1)(a(136),a(425),"data-v-7bae01d6",null);e.exports=i.exports},425:function(e,t){e.exports={render:function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",{staticClass:"rating_page"},[a("head-top",{attrs:{"head-title":"选择发票抬头","go-back":"true"}}),e._v(" "),a("section",{staticClass:"choose_invoice"},[a("span",[e._v("不需要开发票")]),e._v(" "),a("svg",{class:{choosed:e.invoice},on:{click:e.chooseInvoice}},[a("use",{attrs:{"xmlns:xlink":"http://www.w3.org/1999/xlink","xlink:href":"#select"}})])]),e._v(" "),a("div",{staticClass:"determine",on:{click:e.confrimInvoice}},[e._v("确定")])],1)},staticRenderFns:[]}}}); -------------------------------------------------------------------------------- /public/elm/static/js/vipDescription.199af1dcfbb98c257ee0.min.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([39,45],{5:function(t,e,a){"use strict";function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=a(10),i=o(n),r=a(4);e.default={data:function(){return{}},mounted:function(){this.getUserInfo()},props:["signinUp","headTitle","goBack"],computed:(0,i.default)({},(0,r.mapState)(["userInfo"])),methods:(0,i.default)({},(0,r.mapActions)(["getUserInfo"]))}},6:function(t,e,a){e=t.exports=a(2)(),e.push([t.id,"#head_top[data-v-cec0c0c0]{background-color:#3190e8;position:fixed;z-index:100;left:0;top:0;width:100%;height:1.95rem}.head_goback[data-v-cec0c0c0]{left:.4rem;width:.6rem;height:1rem;line-height:2.2rem;margin-left:.4rem}.head_login[data-v-cec0c0c0]{right:.55rem;font-size:.65rem;color:#fff;position:absolute;top:50%;transform:translateY(-50%)}.head_login .login_span[data-v-cec0c0c0]{color:#fff}.head_login .user_avatar[data-v-cec0c0c0]{fill:#fff;width:.8rem;height:.8rem}.title_head[data-v-cec0c0c0]{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:50%;color:#fff;text-align:center}.title_head .title_text[data-v-cec0c0c0]{font-size:.8rem;color:#fff;text-align:center;font-weight:700}","",{version:3,sources:["/./src/components/header/head.vue"],names:[],mappings:"AACA,2BAA2B,yBAAyB,eAAe,YAAY,OAAO,MAAM,WAAW,cAAc,CACpH,AACD,8BAA8B,WAAY,YAAY,YAAY,mBAAmB,iBAAiB,CACrG,AACD,6BAA6B,aAAc,iBAAiB,WAAW,kBAAkB,QAAQ,AAAkE,0BAA0B,CAC5L,AACD,yCAAyC,UAAU,CAClD,AACD,0CAA0C,UAAU,YAAY,YAAY,CAC3E,AACD,6BAA6B,kBAAkB,QAAQ,SAAS,AAA4E,+BAAgC,UAAU,WAAW,iBAAiB,CACjN,AACD,yCAAyC,gBAAgB,WAAW,kBAAkB,eAAgB,CACrG",file:"head.vue",sourcesContent:["\n#head_top[data-v-cec0c0c0]{background-color:#3190e8;position:fixed;z-index:100;left:0;top:0;width:100%;height:1.95rem\n}\n.head_goback[data-v-cec0c0c0]{left:0.4rem;width:.6rem;height:1rem;line-height:2.2rem;margin-left:.4rem\n}\n.head_login[data-v-cec0c0c0]{right:0.55rem;font-size:.65rem;color:#fff;position:absolute;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)\n}\n.head_login .login_span[data-v-cec0c0c0]{color:#fff\n}\n.head_login .user_avatar[data-v-cec0c0c0]{fill:#fff;width:.8rem;height:.8rem\n}\n.title_head[data-v-cec0c0c0]{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%, -50%);-ms-transform:translate(-50%, -50%);transform:translate(-50%, -50%);width:50%;color:#fff;text-align:center\n}\n.title_head .title_text[data-v-cec0c0c0]{font-size:.8rem;color:#fff;text-align:center;font-weight:bold\n}\n"],sourceRoot:"webpack://"}])},7:function(t,e,a){var o=a(6);"string"==typeof o&&(o=[[t.id,o,""]]);a(3)(o,{});o.locals&&(t.exports=o.locals)},8:function(t,e,a){a(7);var o=a(1)(a(5),a(9),"data-v-cec0c0c0",null);t.exports=o.exports},9:function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("header",{attrs:{id:"head_top"}},[t._t("logo"),t._v(" "),t._t("search"),t._v(" "),t.goBack?a("section",{staticClass:"head_goback",on:{click:function(e){t.$router.go(-1)}}},[a("svg",{attrs:{width:"100%",height:"100%",xmlns:"http://www.w3.org/2000/svg",version:"1.1"}},[a("polyline",{staticStyle:{fill:"none",stroke:"rgb(255,255,255)","stroke-width":"2"},attrs:{points:"12,18 4,9 12,0"}})])]):t._e(),t._v(" "),t.signinUp?a("router-link",{staticClass:"head_login",attrs:{to:t.userInfo?"/profile":"/login"}},[t.userInfo?a("svg",{staticClass:"user_avatar"},[a("use",{attrs:{"xmlns:xlink":"http://www.w3.org/1999/xlink","xlink:href":"#user"}})]):a("span",{staticClass:"login_span"},[t._v("登录|注册")])]):t._e(),t._v(" "),t.headTitle?a("section",{staticClass:"title_head ellipsis"},[a("span",{staticClass:"title_text"},[t._v(t._s(t.headTitle))])]):t._e(),t._v(" "),t._t("edit"),t._v(" "),t._t("msite-title"),t._v(" "),t._t("changecity"),t._v(" "),t._t("changeLogin")],2)},staticRenderFns:[]}},167:function(t,e,a){"use strict";function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=a(10),i=o(n),r=a(8),s=o(r),c=a(4);a(16);e.default={data:function(){return{}},mounted:function(){},computed:(0,i.default)({},(0,c.mapState)(["userInfo"])),components:{headTop:s.default},methods:(0,i.default)({},(0,c.mapMutations)(["SAVE_AVANDER"]))}},244:function(t,e,a){e=t.exports=a(2)(),e.push([t.id,".page_container[data-v-67b03784]{position:fixed;top:0;left:0;right:0;bottom:0;background-color:#fff;z-index:202;padding-top:1.95rem;overflow-y:auto;color:#999;font-size:.6rem;padding:2rem .7rem 0}.page_container p[data-v-67b03784],.page_container span[data-v-67b03784]{font-family:Helvetica Neue,Tahoma,Arial}.markdown h1[data-v-67b03784],.markdown h2[data-v-67b03784],.markdown h3[data-v-67b03784],.markdown h4[data-v-67b03784],.markdown h5[data-v-67b03784]{margin-top:.666667rem;margin-bottom:.2rem;font-size:.7rem;font-weight:600;color:#333}.markdown ul li[data-v-67b03784]{color:#666;margin-bottom:.2rem}","",{version:3,sources:["/./src/page/vipcard/children/vipDescription.vue"],names:[],mappings:"AACA,iCAAiC,eAAe,MAAM,OAAO,QAAQ,SAAS,sBAAsB,YAAY,oBAAoB,gBAAgB,WAAW,gBAAgB,oBAAoB,CAClM,AACD,yEAAyE,uCAAuC,CAC/G,AACD,sJAAsJ,sBAAuB,oBAAqB,gBAAiB,gBAAgB,UAAU,CAC5O,AACD,iCAAiC,WAAW,mBAAmB,CAC9D",file:"vipDescription.vue",sourcesContent:["\n.page_container[data-v-67b03784]{position:fixed;top:0;left:0;right:0;bottom:0;background-color:#fff;z-index:202;padding-top:1.95rem;overflow-y:auto;color:#999;font-size:.6rem;padding:2rem .7rem 0\n}\n.page_container p[data-v-67b03784],.page_container span[data-v-67b03784]{font-family:Helvetica Neue,Tahoma,Arial\n}\n.markdown h1[data-v-67b03784],.markdown h2[data-v-67b03784],.markdown h3[data-v-67b03784],.markdown h4[data-v-67b03784],.markdown h5[data-v-67b03784]{margin-top:0.666667rem;margin-bottom:0.2rem;font-size:0.7rem;font-weight:600;color:#333\n}\n.markdown ul li[data-v-67b03784]{color:#666;margin-bottom:.2rem\n}\n"],sourceRoot:"webpack://"}])},293:function(t,e,a){var o=a(244);"string"==typeof o&&(o=[[t.id,o,""]]);a(3)(o,{});o.locals&&(t.exports=o.locals)},389:function(t,e,a){a(293);var o=a(1)(a(167),a(416),"data-v-67b03784",null);t.exports=o.exports},416:function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"page_container"},[a("head-top",{attrs:{"head-title":"我的优惠","go-back":"true"}}),t._v(" "),t._m(0)],1)},staticRenderFns:[function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"markdown"},[a("blockquote",[a("p",[t._v("尊敬的用户,随着会员体系逐渐完善,自2016年10月10日起,饿了么会员权益将做如下优化:\n 购卡后31天内,累积享有30单减免配送费服务(每日最多3单,每单最高减免4元)。\n 注:已购买的会员服务不受影响,当前会员服务失效前无法购买新卡。")])]),t._v(" "),a("h3",{attrs:{id:"q1-"}},[t._v("Q1: 特权介绍")]),t._v(" "),a("ul",[a("li",[t._v("身份标识:饿了么会员服务有效期内,享有专属皇冠标识。")]),t._v(" "),a("li",[t._v("减免配送费: 饿了么会员卡自绑定账户之日起31天内,在「蜂鸟专送」标识商家下单,享有30次减免配送费特权,每日最多减免3单,每单最高可减4元。")]),t._v(" "),a("li",[t._v("更多特权,敬请期待!")])]),t._v(" "),a("h3",{attrs:{id:"q2-"}},[t._v("Q2: 资费介绍")]),t._v(" "),a("ul",[a("li",[t._v("饿了么会员卡:20元")])]),t._v(" "),a("h3",{attrs:{id:"q3-"}},[t._v("Q3: 使用说明")]),t._v(" "),a("p",[t._v("当用户满足以下任一条件,会员服务自动失效:")]),t._v(" "),a("ol",[a("li",[t._v("自绑定之日起超过31天;")]),t._v(" "),a("li",[t._v("在31天内累计使用减免配送费的蜂鸟订单数量达到30单;")])]),t._v(" "),a("h3",{attrs:{id:"q4-"}},[t._v("Q4: 购卡说明")]),t._v(" "),a("ul",[a("li",[t._v("在线购买:饿了么App>我的>饿了么会员卡")])]),t._v(" "),a("h3",{attrs:{id:"q5-"}},[t._v("Q5: 温馨提示")]),t._v(" "),a("ul",[a("li",[t._v("用户在当前会员服务失效前,无法购买新卡。")]),t._v(" "),a("li",[t._v("请认准饿了么官方渠道,任何从其他第三方途径获得的会员卡,饿了么不保证其可用性。")])])])}]}}}); -------------------------------------------------------------------------------- /controller/v1/order.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import BaseComponent from '../../prototype/baseComponent' 4 | import formidable from 'formidable' 5 | import OrderModel from '../../models/bos/order' 6 | import CartModel from '../../models/v1/cart' 7 | import dtime from 'time-formater' 8 | import AddressModel from '../../models/v1/address' 9 | 10 | class Order extends BaseComponent{ 11 | constructor(){ 12 | super() 13 | this.postOrder = this.postOrder.bind(this); 14 | } 15 | async postOrder(req, res, next){ 16 | const form = new formidable.IncomingForm(); 17 | form.parse(req, async (err, fields, files) => { 18 | if (err) { 19 | console.log('formidable解析出错', err); 20 | res.send({ 21 | status: 1, 22 | message: '下单失败' 23 | }) 24 | return 25 | } 26 | const {user_id, cart_id} = req.params; 27 | const {address_id, come_from = 'mobile_web', deliver_time = '', description, entities, geohash, paymethod_id = 1} = fields; 28 | try{ 29 | if(!(entities instanceof Array) || !entities.length){ 30 | throw new Error('entities参数错误') 31 | }else if(!(entities[0] instanceof Array) || !entities[0].length){ 32 | throw new Error('entities参数错误') 33 | }else if(!address_id){ 34 | throw new Error('address_id参数错误') 35 | }else if(!user_id || !Number(user_id)){ 36 | throw new Error('user_id参数错误') 37 | }else if(!cart_id || !Number(cart_id)){ 38 | throw new Error('cart_id参数错误') 39 | }else if(!user_id){ 40 | throw new Error('未登录') 41 | } 42 | }catch(err){ 43 | console.log(err.message, err); 44 | res.send({ 45 | status: 0, 46 | type: 'ERROR_PARAMS', 47 | message: err.message 48 | }) 49 | return 50 | } 51 | let cartDetail; 52 | let order_id; 53 | try{ 54 | cartDetail = await CartModel.findOne({id: cart_id}); 55 | order_id = await this.getId('order_id'); 56 | }catch(err){ 57 | console.log('获取数据失败', err); 58 | res.send({ 59 | status: 0, 60 | type: 'ERROR_GET_DATA', 61 | message: '获取订单失败', 62 | }) 63 | return 64 | } 65 | const deliver_fee = {price: cartDetail.cart.deliver_amount}; 66 | const orderObj = { 67 | basket: { 68 | group: entities, 69 | packing_fee: { 70 | name: cartDetail.cart.extra[0].name, 71 | price: cartDetail.cart.extra[0].price, 72 | quantity: cartDetail.cart.extra[0].quantity, 73 | }, 74 | deliver_fee, 75 | }, 76 | restaurant_id: cartDetail.cart.restaurant_id, 77 | restaurant_image_url: cartDetail.cart.restaurant_info.image_path, 78 | restaurant_name: cartDetail.cart.restaurant_info.name, 79 | formatted_created_at: dtime().format('YYYY-MM-DD HH:mm'), 80 | order_time: new Date().getTime(), 81 | time_pass: 900, 82 | status_bar: { 83 | color: 'f60', 84 | image_type: '', 85 | sub_title: '15分钟内支付', 86 | title: '', 87 | }, 88 | total_amount: cartDetail.cart.total, 89 | total_quantity: entities[0].length, 90 | unique_id: order_id, 91 | id: order_id, 92 | user_id, 93 | address_id, 94 | } 95 | try{ 96 | await OrderModel.create(orderObj); 97 | res.send({ 98 | status: 1, 99 | success: '下单成功,请及时付款', 100 | need_validation: false, 101 | }) 102 | }catch(err){ 103 | console.log('保存订单数据失败'); 104 | res.send({ 105 | status: 0, 106 | type: 'ERROR_SAVE_ORDER', 107 | message: '保存订单失败' 108 | }) 109 | } 110 | }) 111 | } 112 | async getOrders(req, res, next){ 113 | const user_id = req.params.user_id; 114 | const {limit = 0, offset = 0} = req.query; 115 | try{ 116 | if(!user_id || !Number(user_id)){ 117 | throw new Error('user_id参数错误') 118 | }else if(!Number(limit)){ 119 | throw new Error('limit参数错误') 120 | }else if(typeof Number(offset) !== 'number'){ 121 | throw new Error('offset参数错误') 122 | } 123 | }catch(err){ 124 | console.log(err.message, err); 125 | res.send({ 126 | status: 0, 127 | type: 'ERROR_PARAMS', 128 | message: err.message 129 | }) 130 | return 131 | } 132 | try{ 133 | const orders = await OrderModel.find({user_id}).sort({id: -1}).limit(Number(limit)).skip(Number(offset)); 134 | const timeNow = new Date().getTime(); 135 | orders.map(item => { 136 | if (timeNow - item.order_time < 900000) { 137 | item.status_bar.title = '等待支付'; 138 | }else{ 139 | item.status_bar.title = '支付超时'; 140 | } 141 | item.time_pass = Math.ceil((timeNow - item.order_time)/1000); 142 | item.save() 143 | return item 144 | }) 145 | res.send(orders); 146 | }catch(err){ 147 | console.log('获取订单列表失败', err); 148 | res.send({ 149 | status: 0, 150 | type: 'ERROR_GET_ORDER_LIST', 151 | message: '获取订单列表失败' 152 | }) 153 | } 154 | } 155 | async getDetail(req, res, next){ 156 | const {user_id, order_id} = req.params; 157 | try{ 158 | if (!user_id || !Number(user_id)) { 159 | throw new Error('user_id参数错误') 160 | }else if(!order_id || !Number(order_id)){ 161 | throw new Error('order_id参数错误') 162 | } 163 | }catch(err){ 164 | console.log(err.message); 165 | res.send({ 166 | status: 0, 167 | type: 'GET_ERROR_PARAM', 168 | message: err.message, 169 | }) 170 | return 171 | } 172 | try{ 173 | const order = await OrderModel.findOne({id: order_id}, '-_id'); 174 | const addressDetail = await AddressModel.findOne({id: order.address_id}); 175 | const orderDetail = {...order, ...{addressDetail: addressDetail.address, consignee: addressDetail.name, deliver_time: '尽快送达', pay_method: '在线支付', phone: addressDetail.phone}}; 176 | res.send(orderDetail) 177 | }catch(err){ 178 | console.log('获取订单信息失败', err); 179 | res.send({ 180 | status: 0, 181 | type: 'ERROR_TO_GET_ORDER_DETAIL', 182 | message: '获取订单信息失败' 183 | }) 184 | } 185 | } 186 | async getAllOrders(req, res, next){ 187 | const {restaurant_id, limit = 20, offset = 0} = req.query; 188 | try{ 189 | let filter = {}; 190 | if (restaurant_id && Number(restaurant_id)) { 191 | filter = {restaurant_id} 192 | } 193 | 194 | const orders = await OrderModel.find(filter).sort({id: -1}).limit(Number(limit)).skip(Number(offset)); 195 | const timeNow = new Date().getTime(); 196 | orders.map(item => { 197 | if (timeNow - item.order_time < 900000) { 198 | item.status_bar.title = '等待支付'; 199 | }else{ 200 | item.status_bar.title = '支付超时'; 201 | } 202 | item.time_pass = Math.ceil((timeNow - item.order_time)/1000); 203 | item.save() 204 | return item 205 | }) 206 | res.send(orders); 207 | }catch(err){ 208 | console.log('获取订单数据失败', err); 209 | res.send({ 210 | status: 0, 211 | type: 'GET_ORDER_DATA_ERROR', 212 | message: '获取订单数据失败' 213 | }) 214 | } 215 | } 216 | async getOrdersCount(req, res, next){ 217 | const restaurant_id = req.query.restaurant_id; 218 | try{ 219 | let filter = {}; 220 | if (restaurant_id && Number(restaurant_id)) { 221 | filter = {restaurant_id} 222 | } 223 | 224 | const count = await OrderModel.find(filter).count(); 225 | res.send({ 226 | status: 1, 227 | count, 228 | }) 229 | }catch(err){ 230 | console.log('获取订单数量失败', err); 231 | res.send({ 232 | status: 0, 233 | type: 'ERROR_TO_GET_COUNT', 234 | message: '获取订单数量失败' 235 | }) 236 | } 237 | } 238 | } 239 | 240 | export default new Order() -------------------------------------------------------------------------------- /controller/admin/admin.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import AdminModel from '../../models/admin/admin' 4 | import AddressComponent from '../../prototype/addressComponent' 5 | import crypto from 'crypto' 6 | import formidable from 'formidable' 7 | import dtime from 'time-formater' 8 | 9 | class Admin extends AddressComponent { 10 | constructor(){ 11 | super() 12 | this.login = this.login.bind(this) 13 | this.register = this.register.bind(this) 14 | this.encryption = this.encryption.bind(this) 15 | this.updateAvatar = this.updateAvatar.bind(this) 16 | } 17 | async login(req, res, next){ 18 | const form = new formidable.IncomingForm(); 19 | form.parse(req, async (err, fields, files) => { 20 | if (err) { 21 | res.send({ 22 | status: 0, 23 | type: 'FORM_DATA_ERROR', 24 | message: '表单信息错误' 25 | }) 26 | return 27 | } 28 | const {user_name, password, status = 1} = fields; 29 | try{ 30 | if (!user_name) { 31 | throw new Error('用户名参数错误') 32 | }else if(!password){ 33 | throw new Error('密码参数错误') 34 | } 35 | }catch(err){ 36 | console.log(err.message, err); 37 | res.send({ 38 | status: 0, 39 | type: 'GET_ERROR_PARAM', 40 | message: err.message, 41 | }) 42 | return 43 | } 44 | const newpassword = this.encryption(password); 45 | try{ 46 | const admin = await AdminModel.findOne({user_name}) 47 | if (!admin) { 48 | const adminTip = status == 1 ? '管理员' : '超级管理员' 49 | const admin_id = await this.getId('admin_id'); 50 | const cityInfo = await this.guessPosition(req); 51 | const newAdmin = { 52 | user_name, 53 | password: newpassword, 54 | id: admin_id, 55 | create_time: dtime().format('YYYY-MM-DD HH:mm'), 56 | admin: adminTip, 57 | status, 58 | city: cityInfo.city 59 | } 60 | await AdminModel.create(newAdmin) 61 | req.session.admin_id = admin_id; 62 | res.send({ 63 | status: 1, 64 | success: '注册管理员成功', 65 | }) 66 | }else if(newpassword.toString() != admin.password.toString()){ 67 | console.log('管理员登录密码错误'); 68 | res.send({ 69 | status: 0, 70 | type: 'ERROR_PASSWORD', 71 | message: '该用户已存在,密码输入错误', 72 | }) 73 | }else{ 74 | req.session.admin_id = admin.id; 75 | res.send({ 76 | status: 1, 77 | success: '登录成功' 78 | }) 79 | } 80 | }catch(err){ 81 | console.log('登录管理员失败', err); 82 | res.send({ 83 | status: 0, 84 | type: 'LOGIN_ADMIN_FAILED', 85 | message: '登录管理员失败', 86 | }) 87 | } 88 | }) 89 | } 90 | async register(req, res, next){ 91 | const form = new formidable.IncomingForm(); 92 | form.parse(req, async (err, fields, files) => { 93 | if (err) { 94 | res.send({ 95 | status: 0, 96 | type: 'FORM_DATA_ERROR', 97 | message: '表单信息错误' 98 | }) 99 | return 100 | } 101 | const {user_name, password, status = 1} = fields; 102 | try{ 103 | if (!user_name) { 104 | throw new Error('用户名错误') 105 | }else if(!password){ 106 | throw new Error('密码错误') 107 | } 108 | }catch(err){ 109 | console.log(err.message, err); 110 | res.send({ 111 | status: 0, 112 | type: 'GET_ERROR_PARAM', 113 | message: err.message, 114 | }) 115 | return 116 | } 117 | try{ 118 | const admin = await AdminModel.findOne({user_name}) 119 | if (admin) { 120 | console.log('该用户已经存在'); 121 | res.send({ 122 | status: 0, 123 | type: 'USER_HAS_EXIST', 124 | message: '该用户已经存在', 125 | }) 126 | }else{ 127 | const adminTip = status == 1 ? '管理员' : '超级管理员' 128 | const admin_id = await this.getId('admin_id'); 129 | const newpassword = this.encryption(password); 130 | const newAdmin = { 131 | user_name, 132 | password: newpassword, 133 | id: admin_id, 134 | create_time: dtime().format('YYYY-MM-DD'), 135 | admin: adminTip, 136 | status, 137 | } 138 | await AdminModel.create(newAdmin) 139 | req.session.admin_id = admin_id; 140 | res.send({ 141 | status: 1, 142 | message: '注册管理员成功', 143 | }) 144 | } 145 | }catch(err){ 146 | console.log('注册管理员失败', err); 147 | res.send({ 148 | status: 0, 149 | type: 'REGISTER_ADMIN_FAILED', 150 | message: '注册管理员失败', 151 | }) 152 | } 153 | }) 154 | } 155 | encryption(password){ 156 | const newpassword = this.Md5(this.Md5(password).substr(2, 7) + this.Md5(password)); 157 | return newpassword 158 | } 159 | Md5(password){ 160 | const md5 = crypto.createHash('md5'); 161 | return md5.update(password).digest('base64'); 162 | } 163 | async singout(req, res, next){ 164 | try{ 165 | delete req.session.admin_id; 166 | res.send({ 167 | status: 1, 168 | success: '退出成功' 169 | }) 170 | }catch(err){ 171 | console.log('退出失败', err) 172 | res.send({ 173 | status: 0, 174 | message: '退出失败' 175 | }) 176 | } 177 | } 178 | async getAllAdmin(req, res, next){ 179 | const {limit = 20, offset = 0} = req.query; 180 | try{ 181 | const allAdmin = await AdminModel.find({}, '-_id -password').sort({id: -1}).skip(Number(offset)).limit(Number(limit)) 182 | res.send({ 183 | status: 1, 184 | data: allAdmin, 185 | }) 186 | }catch(err){ 187 | console.log('获取超级管理列表失败', err); 188 | res.send({ 189 | status: 0, 190 | type: 'ERROR_GET_ADMIN_LIST', 191 | message: '获取超级管理列表失败' 192 | }) 193 | } 194 | } 195 | async getAdminCount(req, res, next){ 196 | try{ 197 | const count = await AdminModel.count() 198 | res.send({ 199 | status: 1, 200 | count, 201 | }) 202 | }catch(err){ 203 | console.log('获取管理员数量失败', err); 204 | res.send({ 205 | status: 0, 206 | type: 'ERROR_GET_ADMIN_COUNT', 207 | message: '获取管理员数量失败' 208 | }) 209 | } 210 | } 211 | async getAdminInfo(req, res, next){ 212 | const admin_id = req.session.admin_id; 213 | if (!admin_id || !Number(admin_id)) { 214 | // console.log('获取管理员信息的session失效'); 215 | res.send({ 216 | status: 0, 217 | type: 'ERROR_SESSION', 218 | message: '获取管理员信息失败' 219 | }) 220 | return 221 | } 222 | try{ 223 | const info = await AdminModel.findOne({id: admin_id}, '-_id -__v -password'); 224 | if (!info) { 225 | throw new Error('未找到当前管理员') 226 | }else{ 227 | res.send({ 228 | status: 1, 229 | data: info 230 | }) 231 | } 232 | }catch(err){ 233 | console.log('获取管理员信息失败'); 234 | res.send({ 235 | status: 0, 236 | type: 'GET_ADMIN_INFO_FAILED', 237 | message: '获取管理员信息失败' 238 | }) 239 | } 240 | } 241 | async updateAvatar(req, res, next){ 242 | const admin_id = req.params.admin_id; 243 | if (!admin_id || !Number(admin_id)) { 244 | console.log('admin_id参数错误', admin_id) 245 | res.send({ 246 | status: 0, 247 | type: 'ERROR_ADMINID', 248 | message: 'admin_id参数错误', 249 | }) 250 | return 251 | } 252 | 253 | try{ 254 | const image_path = await this.getPath(req); 255 | await AdminModel.findOneAndUpdate({id: admin_id}, {$set: {avatar: image_path}}); 256 | res.send({ 257 | status: 1, 258 | image_path, 259 | }) 260 | return 261 | }catch(err){ 262 | console.log('上传图片失败', err); 263 | res.send({ 264 | status: 0, 265 | type: 'ERROR_UPLOAD_IMG', 266 | message: '上传图片失败' 267 | }) 268 | return 269 | } 270 | } 271 | } 272 | 273 | export default new Admin() -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 | 因为前端项目是根据饿了么官网接口写的,所以后台系统也保持了和官网一致的API接口。 4 | 5 | 整个项目分为两部分:前台项目接口、后台管理接口,共60多个。涉及登陆、注册、添加商品、商品展示、筛选排序、购物车、下单、用户中心等,构成一个完整的流程。 6 | 7 | __注1:此项目纯属个人瞎搞,不用于任何商业用途。__ 8 | 9 | __注2:项目预览地址和接口需要使用https访问哦!__ 10 | 11 | 12 | # 说明 13 | 14 | > node-elm 接口文档: [接口文档地址](https://github.com/bailicangdu/node-elm/blob/master/API.md) 15 | 16 | > 如果对您对此项目有兴趣,可以点 "Star" 支持一下 谢谢! ^_^ 17 | 18 | > 或者您可以 "follow" 一下,我会不断开源更多的有趣的项目 19 | 20 | > 开发环境 macOS 10.12.4 nodejs 6.10.0 Mongodb 3.4.2 21 | 22 | > 部署环境 阿里云 CentOS 7.2 64位 23 | 24 | > 如有问题请直接在 Issues 中提,或者您发现问题并有非常好的解决方案,欢迎 PR 👍 25 | 26 | > 相关项目地址:[前端项目地址](https://github.com/bailicangdu/vue2-elm) 、 [后台管理系统地址](https://github.com/bailicangdu/back-manage) 27 | 28 | ## 技术栈 29 | 30 | nodejs + express + mongodb + mongoose + es6/7 + vue + element-ui 31 | 32 | 33 | ## 项目运行 34 | 35 | ``` 36 | 项目运行之前,请确保系统已经安装以下应用 37 | 1、node (6.0 及以上版本) 38 | 2、mongodb (开启状态) 39 | 3、GraphicsMagick (裁切图片) 40 | ``` 41 | 42 | ``` 43 | git clone https://github.com/bailicangdu/node-elm   44 | 45 | cd node-elm 46 | 47 | npm install 或 yarn(推荐) 48 | 49 | npm run dev 50 | 51 | 访问: http://localhost:8001(如果已启动前台程序,则不需打开此地址) 52 | 53 | ``` 54 | 55 | ## API接口文档 56 | 57 | 接口文档地址:https://github.com/bailicangdu/node-elm/blob/master/API.md 58 | 59 | ## 数据库文件 60 | 61 | 数据库备份文件:https://cangdu.org/file/elm.zip (mongodb) 62 | 63 | 按照mongodb的方式恢复备份即可 64 | 65 | 66 | ## 效果演示 67 | 68 | #### (可在后台管理系统添加商铺,食品等数据,并在前端地址查看效果) 69 | 70 | ### 前端网址 71 | [前端网址戳这里](https://cangdu.org/elm/)(请用chrome手机模式预览) 72 | 73 | ###### 移动端扫描下方二维码 74 | 75 | 76 | 77 | ### 后台管理系统网址 78 | [后台管理网址戳这里](https://cangdu.org/manage/) 79 | 80 | 81 | 82 | 83 | ## 目标功能 84 | 85 | - [x] IP定位 -- 完成 86 | - [x] 城市列表 -- 完成 87 | - [x] 搜索地址 -- 完成 88 | - [x] 上传图片 -- 完成 89 | - [x] 添加商铺 -- 完成 90 | - [x] 添加食品 -- 完成 91 | - [x] 测量距离 -- 完成 92 | - [x] 搜索美食,餐馆 -- 完成 93 | - [x] 根据距离、销量、评分、特色菜、配送方式等进行排序和筛选 -- 完成 94 | - [x] 评价列表 -- 完成 95 | - [x] 食品详情 -- 完成 96 | - [x] 商家详情 -- 完成 97 | - [x] 购物车功能 -- 完成 98 | - [x] 登录、注册 -- 完成 99 | - [x] 修改密码 -- 完成 100 | - [x] 用户信息 -- 完成 101 | - [x] 添加、删除、修改收货地址 -- 完成 102 | - [x] 下单 -- 完成 ✨✨ 103 | - [x] 订单信息 -- 完成 104 | - [x] 红包 -- 完成 105 | - [x] 商铺管理 -- 完成 106 | - [x] 食品管理 -- 完成 107 | - [x] 管理员权限验证 -- 完成 108 | - [x] 超级管理员 -- 完成 109 | - [x] 订单管理 -- 完成 110 | - [x] 流量统计 -- 完成 111 | - [x] 前后台路由同构 -- 完成 112 | - [x] 部署上线 -- 完成 113 | 114 | 115 | ## 部分截图 116 | 117 | #### 部分前台页面 118 | 119 | 120 | 121 | #### 部分后台管理系统页面 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | ## 项目布局 131 | 132 | ``` 133 | . 134 | ├── InitData 初始化数据 135 | │   ├── activity.js 餐馆活动 136 | │   ├── category.js 餐馆分类 137 | │   ├── cities.js 城市列表 138 | │   ├── delivery.js 配送方式 139 | │   ├── entry.js 食品分类 140 | │   ├── explain.js 解释说明 141 | │   ├── hongbao.js 红包 142 | │   ├── payments.js 支付方式 143 | │   ├── rate.js 评论 144 | │   └── remark.js 备注列表 145 | ├── config 运行配置 146 | │   ├── default.js 默认配置 147 | │   └── development.js 开发环境 148 | ├── controller 处理中心,负责路由及数据库的具体操作 149 | │   ├── admin 150 | │   │   └── admin.js 管理员 151 | │   ├── bos 152 | │   ├── eus 153 | │   ├── member 154 | │   │   └── vipcart.js 会员卡 155 | │   ├── payapi 156 | │   ├── promotion 157 | │   │   └── hongbao.js 红包 158 | │   ├── shopping 159 | │   │   ├── category.js 餐馆分类 160 | │   │   ├── food.js 食品 161 | │   │   └── shop.js 餐馆 162 | │   ├── statis 163 | │   │   └── statis.js 数据统计 164 | │   ├── ugc 165 | │   │   └── rating.js 评论 166 | │   ├── v1 167 | │   │   ├── address.js 收获地址 168 | │   │   ├── captchas.js 验证码 169 | │   │   ├── carts.js 购物车 170 | │   │   ├── cities.js 城市列表 171 | │   │   ├── order.js 订单 172 | │   │   ├── remark.js 备注 173 | │   │   └── search.js 搜索 174 | │   ├── v2 175 | │   │   ├── entry.js 食品分类 176 | │   │   └── user.js 用户信息 177 | │   ├── v3 178 | │   │   └── explain.js 解析说明 179 | │   └── v4 180 | ├── logs 日志文件 181 | ├── middlewares 中间件 182 | │   ├── check.js 权限验证 183 | │   └── statistic.js API数据统计 184 | ├── models 模型(数据库) 185 | │   ├── admin 186 | │   │   └── admin.js 管理员模型 187 | │   ├── bos 188 | │   │   └── order.js 订单模型 189 | │   ├── eus 190 | │   ├── ids.js 191 | │   ├── member 192 | │   ├── payapi 193 | │   ├── promotion 194 | │   │   └── hongbao.js 红包模型 195 | │   ├── shopping 196 | │   │   ├── activity.js 餐馆活动模型 197 | │   │   ├── category.js 餐馆分类模型 198 | │   │   ├── delivery.js 配送方式模型 199 | │   │   ├── food.js 食品模型 200 | │   │   └── shop.js 餐馆模型 201 | │   ├── statis 202 | │   │   └── statis.js 数据统计模型 203 | │   ├── ugc 204 | │   │   └── rating.js 评论模型 205 | │   ├── v1 206 | │   │   ├── address.js 收获地址模型 207 | │   │   ├── cart.js 购物车模型 208 | │   │   ├── cities.js 城市列表模型 209 | │   │   ├── payments.js 付款方式模型 210 | │   │   └── remark.js 备注模型 211 | │   ├── v2 212 | │   │   ├── entry.js 食品分类模型 213 | │   │   ├── user.js 用户模型 214 | │   │   └── userInfo.js 用户信息模型 215 | │   ├── v3 216 | │   │   └── explain.js 解释说明模型 217 | │   └── v4 218 | ├── mongodb 连接数据库 219 | │   └── db.js 220 | ├── prototype 基础功能Class 221 | │   ├── addressComponent.js 与腾讯、百度地图API相关的Class 222 | │   └── baseComponent.js 底层类 223 | ├── public 静态资源目录 224 | ├── routes 路由配置 225 | │   ├── admin.js 管理员 226 | │   ├── bos.js 订单 227 | │   ├── eus.js 用户 228 | │   ├── index.js 路由配置主文件 229 | │   ├── member.js 会员卡 230 | │   ├── payapi.js 付款 231 | │   ├── promotion.js 红包 232 | │   ├── shopping.js 餐馆、食品、Menu 233 | │   ├── statis.js 数据统计 234 | │   ├── ugc.js 评论 235 | │   ├── v1.js 城市、用户、收获地址 236 | │   ├── v2.js 登陆、退出 237 | │   ├── v3.js 解释说明 238 | │   └── v4.js 餐馆 239 | ├── screenshots 项目截图 240 | ├── views 241 | ├── .babelrc 242 | ├── .gitignore 243 | ├── API.md 接口文档 244 | ├── app.js 基础配置 245 | ├── COPYING GPL协议 246 | ├── index.js 入口文件 247 | ├── package.json 248 | ├── README.md 249 | . 250 | 251 | 47 directories, 197 files 252 | 253 | ``` 254 | 255 | ## License 256 | 257 | [GPL](https://github.com/bailicangdu/node-elm/blob/master/COPYING) 258 | -------------------------------------------------------------------------------- /public/elm/static/js/searchAddress.747b2cd095404ae58611.min.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([43,45],{5:function(e,t,a){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=a(10),s=r(o),n=a(4);t.default={data:function(){return{}},mounted:function(){this.getUserInfo()},props:["signinUp","headTitle","goBack"],computed:(0,s.default)({},(0,n.mapState)(["userInfo"])),methods:(0,s.default)({},(0,n.mapActions)(["getUserInfo"]))}},6:function(e,t,a){t=e.exports=a(2)(),t.push([e.id,"#head_top[data-v-cec0c0c0]{background-color:#3190e8;position:fixed;z-index:100;left:0;top:0;width:100%;height:1.95rem}.head_goback[data-v-cec0c0c0]{left:.4rem;width:.6rem;height:1rem;line-height:2.2rem;margin-left:.4rem}.head_login[data-v-cec0c0c0]{right:.55rem;font-size:.65rem;color:#fff;position:absolute;top:50%;transform:translateY(-50%)}.head_login .login_span[data-v-cec0c0c0]{color:#fff}.head_login .user_avatar[data-v-cec0c0c0]{fill:#fff;width:.8rem;height:.8rem}.title_head[data-v-cec0c0c0]{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:50%;color:#fff;text-align:center}.title_head .title_text[data-v-cec0c0c0]{font-size:.8rem;color:#fff;text-align:center;font-weight:700}","",{version:3,sources:["/./src/components/header/head.vue"],names:[],mappings:"AACA,2BAA2B,yBAAyB,eAAe,YAAY,OAAO,MAAM,WAAW,cAAc,CACpH,AACD,8BAA8B,WAAY,YAAY,YAAY,mBAAmB,iBAAiB,CACrG,AACD,6BAA6B,aAAc,iBAAiB,WAAW,kBAAkB,QAAQ,AAAkE,0BAA0B,CAC5L,AACD,yCAAyC,UAAU,CAClD,AACD,0CAA0C,UAAU,YAAY,YAAY,CAC3E,AACD,6BAA6B,kBAAkB,QAAQ,SAAS,AAA4E,+BAAgC,UAAU,WAAW,iBAAiB,CACjN,AACD,yCAAyC,gBAAgB,WAAW,kBAAkB,eAAgB,CACrG",file:"head.vue",sourcesContent:["\n#head_top[data-v-cec0c0c0]{background-color:#3190e8;position:fixed;z-index:100;left:0;top:0;width:100%;height:1.95rem\n}\n.head_goback[data-v-cec0c0c0]{left:0.4rem;width:.6rem;height:1rem;line-height:2.2rem;margin-left:.4rem\n}\n.head_login[data-v-cec0c0c0]{right:0.55rem;font-size:.65rem;color:#fff;position:absolute;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)\n}\n.head_login .login_span[data-v-cec0c0c0]{color:#fff\n}\n.head_login .user_avatar[data-v-cec0c0c0]{fill:#fff;width:.8rem;height:.8rem\n}\n.title_head[data-v-cec0c0c0]{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%, -50%);-ms-transform:translate(-50%, -50%);transform:translate(-50%, -50%);width:50%;color:#fff;text-align:center\n}\n.title_head .title_text[data-v-cec0c0c0]{font-size:.8rem;color:#fff;text-align:center;font-weight:bold\n}\n"],sourceRoot:"webpack://"}])},7:function(e,t,a){var r=a(6);"string"==typeof r&&(r=[[e.id,r,""]]);a(3)(r,{});r.locals&&(e.exports=r.locals)},8:function(e,t,a){a(7);var r=a(1)(a(5),a(9),"data-v-cec0c0c0",null);e.exports=r.exports},9:function(e,t){e.exports={render:function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("header",{attrs:{id:"head_top"}},[e._t("logo"),e._v(" "),e._t("search"),e._v(" "),e.goBack?a("section",{staticClass:"head_goback",on:{click:function(t){e.$router.go(-1)}}},[a("svg",{attrs:{width:"100%",height:"100%",xmlns:"http://www.w3.org/2000/svg",version:"1.1"}},[a("polyline",{staticStyle:{fill:"none",stroke:"rgb(255,255,255)","stroke-width":"2"},attrs:{points:"12,18 4,9 12,0"}})])]):e._e(),e._v(" "),e.signinUp?a("router-link",{staticClass:"head_login",attrs:{to:e.userInfo?"/profile":"/login"}},[e.userInfo?a("svg",{staticClass:"user_avatar"},[a("use",{attrs:{"xmlns:xlink":"http://www.w3.org/1999/xlink","xlink:href":"#user"}})]):a("span",{staticClass:"login_span"},[e._v("登录|注册")])]):e._e(),e._v(" "),e.headTitle?a("section",{staticClass:"title_head ellipsis"},[a("span",{staticClass:"title_text"},[e._v(e._s(e.headTitle))])]):e._e(),e._v(" "),e._t("edit"),e._v(" "),e._t("msite-title"),e._v(" "),e._t("changecity"),e._v(" "),e._t("changeLogin")],2)},staticRenderFns:[]}},134:function(e,t,a){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=a(20),s=r(o),n=a(19),i=r(n),A=a(10),c=r(A),l=a(8),d=r(l),f=a(16),h=a(4);t.default={data:function(){return{searchValue:null,searchData:null}},components:{headTop:d.default},props:[],methods:(0,c.default)({},(0,h.mapMutations)(["CHOOSE_SEARCH_ADDRESS"]),{searchPlace:function(){var e=this;return(0,i.default)(s.default.mark(function t(){return s.default.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:if(!e.searchValue){t.next=4;break}return t.next=3,(0,f.searchNearby)(e.searchValue);case 3:e.searchData=t.sent;case 4:case"end":return t.stop()}},t,e)}))()},choooedAddress:function(e){this.CHOOSE_SEARCH_ADDRESS(e),this.$router.go(-1)}})}},238:function(e,t,a){t=e.exports=a(2)(),t.push([e.id,".search_address_page[data-v-3ab7c394]{position:fixed;top:0;left:0;right:0;bottom:0;background-color:#fff;z-index:204;overflow-y:auto;padding-top:1.95rem}.search_address_page p[data-v-3ab7c394],.search_address_page span[data-v-3ab7c394]{font-family:Helvetica Neue,Tahoma,Arial}.search_form[data-v-3ab7c394]{display:-ms-flexbox;display:flex;padding:.7rem}.search_form input[data-v-3ab7c394]{font-size:.65rem;color:#999;-ms-flex:4;flex:4;background-color:#f1f1f1;margin-right:.6rem;height:1.5rem;border-radius:.15rem;padding:0 .4rem}.search_form button[data-v-3ab7c394]{-ms-flex:1;flex:1;font-size:.65rem;color:#fff;background-color:#3190e8;border-radius:.15rem}.address_list[data-v-3ab7c394]{padding:.7rem}.address_list li[data-v-3ab7c394]{padding:.7rem 0;border-bottom:.025rem solid #f5f5f5;line-height:1rem}.address_list li h4[data-v-3ab7c394]{font-size:.75rem;color:#555}.address_list li p[data-v-3ab7c394]{font-size:.65rem;color:#999}.empty_tips[data-v-3ab7c394]{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:100%}.empty_tips p[data-v-3ab7c394]{font-size:.5rem;color:#aaa;line-height:.7rem;text-align:center}","",{version:3,sources:["/./src/page/confirmOrder/children/children/children/searchAddress.vue"],names:[],mappings:"AACA,sCAAsC,eAAe,MAAM,OAAO,QAAQ,SAAS,sBAAsB,YAAY,gBAAgB,mBAAmB,CACvJ,AACD,mFAAmF,uCAAuC,CACzH,AACD,8BAAuE,oBAAoB,aAAa,aAAa,CACpH,AACD,oCAAoC,iBAAiB,WAAW,AAAkC,WAAW,OAAO,yBAAyB,mBAAmB,cAAc,qBAAsB,eAAe,CAClN,AACD,qCAAuE,WAAW,OAAO,iBAAiB,WAAW,yBAAyB,oBAAqB,CAClK,AACD,+BAA+B,aAAa,CAC3C,AACD,kCAAkC,gBAAgB,oCAAqC,gBAAgB,CACtG,AACD,qCAAqC,iBAAiB,UAAU,CAC/D,AACD,oCAAoC,iBAAiB,UAAU,CAC9D,AACD,6BAA6B,kBAAkB,QAAQ,SAAS,AAA4E,+BAAgC,UAAU,CACrL,AACD,+BAA+B,gBAAgB,WAAW,kBAAkB,iBAAiB,CAC5F",file:"searchAddress.vue",sourcesContent:["\n.search_address_page[data-v-3ab7c394]{position:fixed;top:0;left:0;right:0;bottom:0;background-color:#fff;z-index:204;overflow-y:auto;padding-top:1.95rem\n}\n.search_address_page p[data-v-3ab7c394],.search_address_page span[data-v-3ab7c394]{font-family:Helvetica Neue,Tahoma,Arial\n}\n.search_form[data-v-3ab7c394]{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;padding:.7rem\n}\n.search_form input[data-v-3ab7c394]{font-size:.65rem;color:#999;-webkit-box-flex:4;-webkit-flex:4;-ms-flex:4;flex:4;background-color:#f1f1f1;margin-right:.6rem;height:1.5rem;border-radius:0.15rem;padding:0 .4rem\n}\n.search_form button[data-v-3ab7c394]{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;font-size:.65rem;color:#fff;background-color:#3190e8;border-radius:0.15rem\n}\n.address_list[data-v-3ab7c394]{padding:.7rem\n}\n.address_list li[data-v-3ab7c394]{padding:.7rem 0;border-bottom:0.025rem solid #f5f5f5;line-height:1rem\n}\n.address_list li h4[data-v-3ab7c394]{font-size:.75rem;color:#555\n}\n.address_list li p[data-v-3ab7c394]{font-size:.65rem;color:#999\n}\n.empty_tips[data-v-3ab7c394]{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%, -50%);-ms-transform:translate(-50%, -50%);transform:translate(-50%, -50%);width:100%\n}\n.empty_tips p[data-v-3ab7c394]{font-size:.5rem;color:#aaa;line-height:.7rem;text-align:center\n}\n"],sourceRoot:"webpack://"}])},286:function(e,t,a){var r=a(238);"string"==typeof r&&(r=[[e.id,r,""]]);a(3)(r,{});r.locals&&(e.exports=r.locals)},356:function(e,t,a){a(286);var r=a(1)(a(134),a(409),"data-v-3ab7c394",null);e.exports=r.exports},409:function(e,t){e.exports={render:function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",{staticClass:"search_address_page"},[a("section",[a("head-top",{attrs:{"head-title":"搜索","go-back":"true"}}),e._v(" "),a("form",{staticClass:"search_form"},[a("input",{directives:[{name:"model",rawName:"v-model",value:e.searchValue,expression:"searchValue"}],attrs:{type:"search",name:"search",placeholder:"请输入小区/写字楼/学校等"},domProps:{value:e.searchValue},on:{input:function(t){t.target.composing||(e.searchValue=t.target.value)}}}),e._v(" "),a("button",{on:{click:function(t){t.preventDefault(),e.searchPlace()}}},[e._v("搜索")])]),e._v(" "),e.searchData?a("ul",{staticClass:"address_list"},e._l(e.searchData,function(t,r){return a("li",{key:r,on:{click:function(a){e.choooedAddress(t)}}},[a("h4",[e._v(e._s(t.name))]),e._v(" "),a("p",[e._v(e._s(t.address))])])})):a("div",{staticClass:"empty_tips"},[a("p",[e._v("找不到地址?")]),e._v(" "),a("p",[e._v("尝试输入小区、写字楼或学校名")]),e._v(" "),a("p",[e._v("详细地址(如门牌号等)可稍后输入哦")])])],1)])},staticRenderFns:[]}}}); -------------------------------------------------------------------------------- /controller/v2/user.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import AddressComponent from '../../prototype/addressComponent' 4 | import formidable from 'formidable' 5 | import UserInfoModel from '../../models/v2/userInfo' 6 | import UserModel from '../../models/v2/user' 7 | import crypto from 'crypto' 8 | import dtime from 'time-formater' 9 | 10 | class User extends AddressComponent { 11 | constructor(){ 12 | super() 13 | this.login = this.login.bind(this); 14 | this.encryption = this.encryption.bind(this); 15 | this.chanegPassword = this.chanegPassword.bind(this); 16 | this.updateAvatar = this.updateAvatar.bind(this); 17 | } 18 | async login(req, res, next){ 19 | const cap = req.cookies.cap; 20 | if (!cap) { 21 | console.log('验证码失效') 22 | res.send({ 23 | status: 0, 24 | type: 'ERROR_CAPTCHA', 25 | message: '验证码失效', 26 | }) 27 | return 28 | } 29 | const form = new formidable.IncomingForm(); 30 | form.parse(req, async (err, fields, files) => { 31 | const {username, password, captcha_code} = fields; 32 | try{ 33 | if (!username) { 34 | throw new Error('用户名参数错误'); 35 | }else if(!password){ 36 | throw new Error('密码参数错误'); 37 | }else if(!captcha_code){ 38 | throw new Error('验证码参数错误'); 39 | } 40 | }catch(err){ 41 | console.log('登陆参数错误', err); 42 | res.send({ 43 | status: 0, 44 | type: 'ERROR_QUERY', 45 | message: err.message, 46 | }) 47 | return 48 | } 49 | if (cap.toString() !== captcha_code.toString()) { 50 | res.send({ 51 | status: 0, 52 | type: 'ERROR_CAPTCHA', 53 | message: '验证码不正确', 54 | }) 55 | return 56 | } 57 | const newpassword = this.encryption(password); 58 | try{ 59 | const user = await UserModel.findOne({username}); 60 | //创建一个新的用户 61 | if (!user) { 62 | const user_id = await this.getId('user_id'); 63 | const cityInfo = await this.guessPosition(req); 64 | const registe_time = dtime().format('YYYY-MM-DD HH:mm'); 65 | const newUser = {username, password: newpassword, user_id}; 66 | const newUserInfo = {username, user_id, id: user_id, city: cityInfo.city, registe_time, }; 67 | UserModel.create(newUser); 68 | const createUser = new UserInfoModel(newUserInfo); 69 | const userinfo = await createUser.save(); 70 | req.session.user_id = user_id; 71 | res.send(userinfo); 72 | }else if (user.password.toString() !== newpassword.toString()) { 73 | console.log('用户登录密码错误') 74 | res.send({ 75 | status: 0, 76 | type: 'ERROR_PASSWORD', 77 | message: '密码错误', 78 | }) 79 | return 80 | }else{ 81 | req.session.user_id = user.user_id; 82 | const userinfo = await UserInfoModel.findOne({user_id: user.user_id}, '-_id'); 83 | res.send(userinfo) 84 | } 85 | }catch(err){ 86 | console.log('用户登陆失败', err); 87 | res.send({ 88 | status: 0, 89 | type: 'SAVE_USER_FAILED', 90 | message: '登陆失败', 91 | }) 92 | } 93 | }) 94 | } 95 | async getInfo(req, res, next){ 96 | const sid = req.session.user_id; 97 | const qid = req.query.user_id; 98 | const user_id = sid || qid; 99 | if (!user_id || !Number(user_id)) { 100 | // console.log('获取用户信息的参数user_id无效', user_id) 101 | res.send({ 102 | status: 0, 103 | type: 'GET_USER_INFO_FAIELD', 104 | message: '通过session获取用户信息失败', 105 | }) 106 | return 107 | } 108 | try{ 109 | const userinfo = await UserInfoModel.findOne({user_id}, '-_id'); 110 | res.send(userinfo) 111 | }catch(err){ 112 | console.log('通过session获取用户信息失败', err); 113 | res.send({ 114 | status: 0, 115 | type: 'GET_USER_INFO_FAIELD', 116 | message: '通过session获取用户信息失败', 117 | }) 118 | } 119 | } 120 | async getInfoById(req, res, next){ 121 | const user_id = req.params.user_id; 122 | if (!user_id || !Number(user_id)) { 123 | console.log('通过ID获取用户信息失败') 124 | res.send({ 125 | status: 0, 126 | type: 'GET_USER_INFO_FAIELD', 127 | message: '通过用户ID获取用户信息失败', 128 | }) 129 | return 130 | } 131 | try{ 132 | const userinfo = await UserInfoModel.findOne({user_id}, '-_id'); 133 | res.send(userinfo) 134 | }catch(err){ 135 | console.log('通过用户ID获取用户信息失败', err); 136 | res.send({ 137 | status: 0, 138 | type: 'GET_USER_INFO_FAIELD', 139 | message: '通过用户ID获取用户信息失败', 140 | }) 141 | } 142 | } 143 | async signout(req, res, next){ 144 | delete req.session.user_id; 145 | res.send({ 146 | status: 1, 147 | message: '退出成功' 148 | }) 149 | } 150 | async chanegPassword(req, res, next){ 151 | const cap = req.cookies.cap; 152 | if (!cap) { 153 | console.log('验证码失效') 154 | res.send({ 155 | status: 0, 156 | type: 'ERROR_CAPTCHA', 157 | message: '验证码失效', 158 | }) 159 | return 160 | } 161 | const form = new formidable.IncomingForm(); 162 | form.parse(req, async (err, fields, files) => { 163 | const {username, oldpassWord, newpassword, confirmpassword, captcha_code} = fields; 164 | try{ 165 | if (!username) { 166 | throw new Error('用户名参数错误'); 167 | }else if(!oldpassWord){ 168 | throw new Error('必须添加旧密码'); 169 | }else if(!newpassword){ 170 | throw new Error('必须填写新密码'); 171 | }else if(!confirmpassword){ 172 | throw new Error('必须填写确认密码'); 173 | }else if(newpassword !== confirmpassword){ 174 | throw new Error('两次密码不一致'); 175 | }else if(!captcha_code){ 176 | throw new Error('请填写验证码'); 177 | } 178 | }catch(err){ 179 | console.log('修改密码参数错误', err); 180 | res.send({ 181 | status: 0, 182 | type: 'ERROR_QUERY', 183 | message: err.message, 184 | }) 185 | return 186 | } 187 | if (cap.toString() !== captcha_code.toString()) { 188 | res.send({ 189 | status: 0, 190 | type: 'ERROR_CAPTCHA', 191 | message: '验证码不正确', 192 | }) 193 | return 194 | } 195 | const md5password = this.encryption(oldpassWord); 196 | try{ 197 | const user = await UserModel.findOne({username}); 198 | if (!user) { 199 | res.send({ 200 | status: 0, 201 | type: 'USER_NOT_FOUND', 202 | message: '未找到当前用户', 203 | }) 204 | }else if(user.password.toString() !== md5password.toString()){ 205 | res.send({ 206 | status: 0, 207 | type: 'ERROR_PASSWORD', 208 | message: '密码不正确', 209 | }) 210 | }else{ 211 | user.password = this.encryption(newpassword); 212 | user.save(); 213 | res.send({ 214 | status: 1, 215 | success: '密码修改成功', 216 | }) 217 | } 218 | }catch(err){ 219 | console.log('修改密码失败', err); 220 | res.send({ 221 | status: 0, 222 | type: 'ERROR_CHANGE_PASSWORD', 223 | message: '修改密码失败', 224 | }) 225 | } 226 | }) 227 | } 228 | encryption(password){ 229 | const newpassword = this.Md5(this.Md5(password).substr(2, 7) + this.Md5(password)); 230 | return newpassword 231 | } 232 | Md5(password){ 233 | const md5 = crypto.createHash('md5'); 234 | return md5.update(password).digest('base64'); 235 | } 236 | async getUserList(req, res, next){ 237 | const {limit = 20, offset = 0} = req.query; 238 | try{ 239 | const users = await UserInfoModel.find({}, '-_id').sort({user_id: -1}).limit(Number(limit)).skip(Number(offset)); 240 | res.send(users); 241 | }catch(err){ 242 | console.log('获取用户列表数据失败', err); 243 | res.send({ 244 | status: 0, 245 | type: 'GET_DATA_ERROR', 246 | message: '获取用户列表数据失败' 247 | }) 248 | } 249 | } 250 | async getUserCount(req, res, next){ 251 | try{ 252 | const count = await UserInfoModel.count(); 253 | res.send({ 254 | status: 1, 255 | count, 256 | }) 257 | }catch(err){ 258 | console.log('获取用户数量失败', err); 259 | res.send({ 260 | status: 0, 261 | type: 'ERROR_TO_GET_USER_COUNT', 262 | message: '获取用户数量失败' 263 | }) 264 | } 265 | } 266 | async updateAvatar(req, res, next){ 267 | const sid = req.session.user_id; 268 | const pid = req.params.user_id; 269 | const user_id = sid || pid; 270 | if (!user_id || !Number(user_id)) { 271 | console.log('更新头像,user_id错误', user_id) 272 | res.send({ 273 | status: 0, 274 | type: 'ERROR_USERID', 275 | message: 'user_id参数错误', 276 | }) 277 | return 278 | } 279 | 280 | try{ 281 | const image_path = await this.getPath(req); 282 | await UserInfoModel.findOneAndUpdate({user_id}, {$set: {avatar: image_path}}); 283 | res.send({ 284 | status: 1, 285 | image_path, 286 | }) 287 | }catch(err){ 288 | console.log('上传图片失败', err); 289 | res.send({ 290 | status: 0, 291 | type: 'ERROR_UPLOAD_IMG', 292 | message: '上传图片失败' 293 | }) 294 | } 295 | } 296 | async getUserCity(req, res, next){ 297 | const cityArr = ['北京', '上海', '深圳', '杭州']; 298 | const filterArr = []; 299 | cityArr.forEach(item => { 300 | filterArr.push(UserInfoModel.find({city: item}).count()) 301 | }) 302 | filterArr.push(UserInfoModel.$where('!"北京上海深圳杭州".includes(this.city)').count()) 303 | Promise.all(filterArr).then(result => { 304 | res.send({ 305 | status: 1, 306 | user_city: { 307 | beijing: result[0], 308 | shanghai: result[1], 309 | shenzhen: result[2], 310 | hangzhou: result[3], 311 | qita: result[4], 312 | } 313 | }) 314 | }).catch(err => { 315 | console.log('获取用户分布城市数据失败', err); 316 | res.send({ 317 | status: 0, 318 | type: 'ERROR_GET_USER_CITY', 319 | message: '获取用户分布城市数据失败' 320 | }) 321 | }) 322 | } 323 | } 324 | 325 | export default new User() -------------------------------------------------------------------------------- /public/elm/static/js/setusername.4a32303d281e56e641cc.min.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([36,45],{5:function(t,e,a){"use strict";function n(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var o=a(10),i=n(o),r=a(4);e.default={data:function(){return{}},mounted:function(){this.getUserInfo()},props:["signinUp","headTitle","goBack"],computed:(0,i.default)({},(0,r.mapState)(["userInfo"])),methods:(0,i.default)({},(0,r.mapActions)(["getUserInfo"]))}},6:function(t,e,a){e=t.exports=a(2)(),e.push([t.id,"#head_top[data-v-cec0c0c0]{background-color:#3190e8;position:fixed;z-index:100;left:0;top:0;width:100%;height:1.95rem}.head_goback[data-v-cec0c0c0]{left:.4rem;width:.6rem;height:1rem;line-height:2.2rem;margin-left:.4rem}.head_login[data-v-cec0c0c0]{right:.55rem;font-size:.65rem;color:#fff;position:absolute;top:50%;transform:translateY(-50%)}.head_login .login_span[data-v-cec0c0c0]{color:#fff}.head_login .user_avatar[data-v-cec0c0c0]{fill:#fff;width:.8rem;height:.8rem}.title_head[data-v-cec0c0c0]{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:50%;color:#fff;text-align:center}.title_head .title_text[data-v-cec0c0c0]{font-size:.8rem;color:#fff;text-align:center;font-weight:700}","",{version:3,sources:["/./src/components/header/head.vue"],names:[],mappings:"AACA,2BAA2B,yBAAyB,eAAe,YAAY,OAAO,MAAM,WAAW,cAAc,CACpH,AACD,8BAA8B,WAAY,YAAY,YAAY,mBAAmB,iBAAiB,CACrG,AACD,6BAA6B,aAAc,iBAAiB,WAAW,kBAAkB,QAAQ,AAAkE,0BAA0B,CAC5L,AACD,yCAAyC,UAAU,CAClD,AACD,0CAA0C,UAAU,YAAY,YAAY,CAC3E,AACD,6BAA6B,kBAAkB,QAAQ,SAAS,AAA4E,+BAAgC,UAAU,WAAW,iBAAiB,CACjN,AACD,yCAAyC,gBAAgB,WAAW,kBAAkB,eAAgB,CACrG",file:"head.vue",sourcesContent:["\n#head_top[data-v-cec0c0c0]{background-color:#3190e8;position:fixed;z-index:100;left:0;top:0;width:100%;height:1.95rem\n}\n.head_goback[data-v-cec0c0c0]{left:0.4rem;width:.6rem;height:1rem;line-height:2.2rem;margin-left:.4rem\n}\n.head_login[data-v-cec0c0c0]{right:0.55rem;font-size:.65rem;color:#fff;position:absolute;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)\n}\n.head_login .login_span[data-v-cec0c0c0]{color:#fff\n}\n.head_login .user_avatar[data-v-cec0c0c0]{fill:#fff;width:.8rem;height:.8rem\n}\n.title_head[data-v-cec0c0c0]{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%, -50%);-ms-transform:translate(-50%, -50%);transform:translate(-50%, -50%);width:50%;color:#fff;text-align:center\n}\n.title_head .title_text[data-v-cec0c0c0]{font-size:.8rem;color:#fff;text-align:center;font-weight:bold\n}\n"],sourceRoot:"webpack://"}])},7:function(t,e,a){var n=a(6);"string"==typeof n&&(n=[[t.id,n,""]]);a(3)(n,{});n.locals&&(t.exports=n.locals)},8:function(t,e,a){a(7);var n=a(1)(a(5),a(9),"data-v-cec0c0c0",null);t.exports=n.exports},9:function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("header",{attrs:{id:"head_top"}},[t._t("logo"),t._v(" "),t._t("search"),t._v(" "),t.goBack?a("section",{staticClass:"head_goback",on:{click:function(e){t.$router.go(-1)}}},[a("svg",{attrs:{width:"100%",height:"100%",xmlns:"http://www.w3.org/2000/svg",version:"1.1"}},[a("polyline",{staticStyle:{fill:"none",stroke:"rgb(255,255,255)","stroke-width":"2"},attrs:{points:"12,18 4,9 12,0"}})])]):t._e(),t._v(" "),t.signinUp?a("router-link",{staticClass:"head_login",attrs:{to:t.userInfo?"/profile":"/login"}},[t.userInfo?a("svg",{staticClass:"user_avatar"},[a("use",{attrs:{"xmlns:xlink":"http://www.w3.org/1999/xlink","xlink:href":"#user"}})]):a("span",{staticClass:"login_span"},[t._v("登录|注册")])]):t._e(),t._v(" "),t.headTitle?a("section",{staticClass:"title_head ellipsis"},[a("span",{staticClass:"title_text"},[t._v(t._s(t.headTitle))])]):t._e(),t._v(" "),t._t("edit"),t._v(" "),t._t("msite-title"),t._v(" "),t._t("changecity"),t._v(" "),t._t("changeLogin")],2)},staticRenderFns:[]}},18:function(t,e,a){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.getImgPath=e.loadMore=void 0;var n=a(27);a(17),e.loadMore={directives:{"load-more":{bind:function(t,e){var a=window.screen.height,o=void 0,i=void 0,r=void 0,s=void 0,c=void 0,A=void 0,l=void 0,d=void 0,p=t.attributes.type&&t.attributes.type.value,u=2;2==p?(l=t,d=t.children[0]):(l=document.body,d=t),t.addEventListener("touchstart",function(){o=d.clientHeight,2==p&&(o=o),i=t.offsetTop,r=(0,n.getStyle)(t,"paddingBottom"),s=(0,n.getStyle)(t,"marginBottom")},!1),t.addEventListener("touchmove",function(){f()},!1),t.addEventListener("touchend",function(){A=l.scrollTop,m()},!1);var m=function t(){c=requestAnimationFrame(function(){l.scrollTop!=A?(A=l.scrollTop,t()):(cancelAnimationFrame(c),o=d.clientHeight,f())})},f=function(){l.scrollTop+a>=o+i+r+s-u&&e.value()}}}}},e.getImgPath={methods:{getImgPath:function(t){var e=void 0;if(!t)return"//elm.cangdu.org/img/default.jpg";e=t.indexOf("jpeg")!==-1?".jpeg":".png";var a="/"+t.substr(0,1)+"/"+t.substr(1,2)+"/"+t.substr(3)+e;return"https://fuss10.elemecdn.com"+a}}}},155:function(t,e,a){"use strict";function n(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var o=a(10),i=n(o),r=a(8),s=n(r),c=a(18),A=a(4);e.default={data:function(){return{earn:!0,bordercolor:!1,opacityall:!1,inputValue:"",newusername:""}},created:function(){},mixins:[c.getImgPath],components:{headTop:s.default},mounted:function(){},computed:(0,i.default)({},(0,A.mapState)(["userInfo"])),props:[],methods:(0,i.default)({},(0,A.mapMutations)(["RETSET_NAME"]),{inputThing:function(){return this.inputValue.length<5||this.inputValue.length>24?(this.earn=!1,this.bordercolor=!0,this.opacityall=!1,!1):(this.earn=!0,this.bordercolor=!1,this.opacityall=!0,!0)},resetName:function(){var t=this.inputThing();t&&(this.RETSET_NAME(this.inputValue),this.$router.go(-1))}})}},234:function(t,e,a){e=t.exports=a(2)(),e.push([t.id,".rating_page[data-v-348472c9]{position:absolute;top:0;left:0;right:0;bottom:0;z-index:202;background:#f2f2f2;padding-top:1.95rem}.rating_page p[data-v-348472c9],.rating_page span[data-v-348472c9]{font-family:Helvetica Neue,Tahoma,Arial}.setname[data-v-348472c9]{width:15.2rem;margin:0 auto}.setname .setname-top[data-v-348472c9]{padding-top:.4rem}.setname .setname-top input[data-v-348472c9]{background:none;width:15.2rem;border:1px solid #ddd;border-radius:2px;padding:.2rem .1rem;line-height:1.2rem;font-size:.7rem;display:block}.setname .setname-top .setname-input[data-v-348472c9]{border-color:#ea3106}.setname .setname-top p[data-v-348472c9]{width:100%;font-size:.4rem;color:#666;padding:.4rem 0 1rem}.setname .setname-top .unlikep[data-v-348472c9]{font-size:.58rem;color:#ea3106;padding-top:.1rem}.setname .reset[data-v-348472c9]{width:100%;background:#3199e8}.setname .reset button[data-v-348472c9]{display:block;width:100%;background:none;line-height:2rem;font-size:.7rem;color:#fff;opacity:.6;transition:all 1s}.setname .reset .fontopacity[data-v-348472c9]{transition:all 1s;opacity:1}","",{version:3,sources:["/./src/page/profile/children/children/setusername.vue"],names:[],mappings:"AACA,8BAA8B,kBAAkB,MAAM,OAAO,QAAQ,SAAS,YAAY,mBAAmB,mBAAmB,CAC/H,AACD,mEAAmE,uCAAuC,CACzG,AACD,0BAA0B,cAAc,aAAa,CACpD,AACD,uCAAuC,iBAAiB,CACvD,AACD,6CAA6C,gBAAgB,cAAc,sBAAsB,kBAAkB,oBAAoB,mBAAmB,gBAAgB,aAAa,CACtL,AACD,sDAAsD,oBAAoB,CACzE,AACD,yCAAyC,WAAW,gBAAgB,WAAW,oBAAoB,CAClG,AACD,gDAAgD,iBAAiB,cAAc,iBAAiB,CAC/F,AACD,iCAAiC,WAAW,kBAAkB,CAC7D,AACD,wCAAwC,cAAc,WAAW,gBAAgB,iBAAiB,gBAAgB,WAAW,WAAW,AAA0B,iBAAiB,CAClL,AACD,8CAAwE,kBAAkB,SAAS,CAClG",file:"setusername.vue",sourcesContent:["\n.rating_page[data-v-348472c9]{position:absolute;top:0;left:0;right:0;bottom:0;z-index:202;background:#f2f2f2;padding-top:1.95rem\n}\n.rating_page p[data-v-348472c9],.rating_page span[data-v-348472c9]{font-family:Helvetica Neue,Tahoma,Arial\n}\n.setname[data-v-348472c9]{width:15.2rem;margin:0 auto\n}\n.setname .setname-top[data-v-348472c9]{padding-top:.4rem\n}\n.setname .setname-top input[data-v-348472c9]{background:none;width:15.2rem;border:1px solid #ddd;border-radius:2px;padding:.2rem .1rem;line-height:1.2rem;font-size:.7rem;display:block\n}\n.setname .setname-top .setname-input[data-v-348472c9]{border-color:#ea3106\n}\n.setname .setname-top p[data-v-348472c9]{width:100%;font-size:.4rem;color:#666;padding:.4rem 0 1rem\n}\n.setname .setname-top .unlikep[data-v-348472c9]{font-size:.58rem;color:#ea3106;padding-top:.1rem\n}\n.setname .reset[data-v-348472c9]{width:100%;background:#3199e8\n}\n.setname .reset button[data-v-348472c9]{display:block;width:100%;background:none;line-height:2rem;font-size:.7rem;color:#fff;opacity:.6;-webkit-transition:all 1s;transition:all 1s\n}\n.setname .reset .fontopacity[data-v-348472c9]{-webkit-transition:all 1s;transition:all 1s;opacity:1\n}\n"],sourceRoot:"webpack://"}])},282:function(t,e,a){var n=a(234);"string"==typeof n&&(n=[[t.id,n,""]]);a(3)(n,{});n.locals&&(t.exports=n.locals)},377:function(t,e,a){a(282);var n=a(1)(a(155),a(405),"data-v-348472c9",null);t.exports=n.exports},405:function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"rating_page"},[a("head-top",{attrs:{"head-title":"修改用户名","go-back":"true"}}),t._v(" "),a("section",{staticClass:"setname"},[a("section",{staticClass:"setname-top"},[a("input",{directives:[{name:"model",rawName:"v-model",value:t.inputValue,expression:"inputValue"}],class:{"setname-input":t.bordercolor},attrs:{type:"text",placeholder:"输入用户名"},domProps:{value:t.inputValue},on:{input:[function(e){e.target.composing||(t.inputValue=e.target.value)},t.inputThing]}}),t._v(" "),a("div",[t.earn?a("p",[t._v("用户名只能修改一次(5-24字符之间)")]):a("p",{staticClass:"unlikep"},[t._v("用户名长度在5到24位之间")])])]),t._v(" "),a("section",{staticClass:"reset"},[a("button",{class:{fontopacity:t.opacityall},on:{click:t.resetName}},[t._v("确认修改")])])])],1)},staticRenderFns:[]}}}); -------------------------------------------------------------------------------- /InitData/category.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | count: 0, 4 | ids: [ 5 | 207, 6 | 220, 7 | 260, 8 | 233, 9 | 239, 10 | 244, 11 | 248, 12 | 252 13 | ], 14 | image_url: "", 15 | level: 1, 16 | name: "全部商家" 17 | }, 18 | { 19 | count: 0, 20 | id: 207, 21 | ids: [ 22 | 207 23 | ], 24 | image_url: "bff533cf9617bd57fe1dfb05603bebcfpng", 25 | level: 1, 26 | name: "快餐便当", 27 | sub_categories: [ 28 | { 29 | count: 0, 30 | id: 207, 31 | image_url: "44545a0518aab93817cfe611e88bb702png", 32 | level: 1, 33 | name: "全部快餐便当" 34 | }, 35 | { 36 | count: 0, 37 | id: 265, 38 | image_url: "be84bc4d7cf12deee9115b16eb099302png", 39 | level: 2, 40 | name: "简餐" 41 | }, 42 | { 43 | count: 0, 44 | id: 209, 45 | image_url: "66b78c0e7099c278977298d7c6042c80png", 46 | level: 2, 47 | name: "盖浇饭" 48 | }, 49 | { 50 | count: 0, 51 | id: 213, 52 | image_url: "02e6c9e3bf338ec0ba0d923717b9f8acpng", 53 | level: 2, 54 | name: "米粉面馆" 55 | }, 56 | { 57 | count: 0, 58 | id: 215, 59 | image_url: "af6ab89041b3e77fe115d1e4b72d69f0png", 60 | level: 2, 61 | name: "包子粥店" 62 | }, 63 | { 64 | count: 0, 65 | id: 219, 66 | image_url: "eddd9dc7e5d21debe2fb278ae01fefe9png", 67 | level: 2, 68 | name: "香锅砂锅" 69 | }, 70 | { 71 | count: 0, 72 | id: 214, 73 | image_url: "4d347d0dc65dd75fb2911256aabf2327png", 74 | level: 2, 75 | name: "麻辣烫" 76 | }, 77 | { 78 | count: 0, 79 | id: 217, 80 | image_url: "65b575c2278a3f6e5c70af45b578cbeepng", 81 | level: 2, 82 | name: "饺子馄饨" 83 | }, 84 | { 85 | count: 0, 86 | id: 212, 87 | image_url: "7d47af01fccc46fc3621865a9cc07c93png", 88 | level: 2, 89 | name: "汉堡" 90 | }, 91 | { 92 | count: 0, 93 | id: 216, 94 | image_url: "4c6af48f68284ad91c6d95d2bd3f4aa6png", 95 | level: 2, 96 | name: "生煎锅贴" 97 | }, 98 | { 99 | count: 0, 100 | id: 267, 101 | image_url: "79637dc36d67de4fe48d121ea77b3eddpng", 102 | level: 2, 103 | name: "黄焖鸡米饭" 104 | }, 105 | { 106 | count: 0, 107 | id: 266, 108 | image_url: "c09d1ff71384e2e1664f72e0a928810dpng", 109 | level: 2, 110 | name: "烧腊饭" 111 | }, 112 | { 113 | count: 0, 114 | id: 269, 115 | image_url: "180cb951c2d4eb2e220debf4571bf83apng", 116 | level: 2, 117 | name: "煲仔饭" 118 | }, 119 | { 120 | count: 0, 121 | id: 268, 122 | image_url: "cdf208b399b854e456f23d28b1972e97png", 123 | level: 2, 124 | name: "咖喱饭" 125 | } 126 | ] 127 | }, 128 | { 129 | count: 0, 130 | id: 220, 131 | ids: [ 132 | 220 133 | ], 134 | image_url: "655ac1bfd1e818013a9f099e964f1e9djpeg", 135 | level: 1, 136 | name: "特色菜系", 137 | sub_categories: [ 138 | { 139 | count: 0, 140 | id: 220, 141 | image_url: "ef32dabbcd88fbed5a336383e74c733dpng", 142 | level: 1, 143 | name: "全部特色菜系" 144 | }, 145 | { 146 | count: 0, 147 | id: 221, 148 | image_url: "43b0e4694f8ebc393cce6723d5df5222png", 149 | level: 2, 150 | name: "川湘菜" 151 | }, 152 | { 153 | count: 0, 154 | id: 263, 155 | image_url: "94ac841e2c3e27f8eeeaa917574ed574png", 156 | level: 2, 157 | name: "其他菜系" 158 | }, 159 | { 160 | count: 0, 161 | id: 225, 162 | image_url: "2d098842683548f9626cf0a8c879257dpng", 163 | level: 2, 164 | name: "江浙菜" 165 | }, 166 | { 167 | count: 0, 168 | id: 222, 169 | image_url: "e320bf1ab9762cb1faad27d79f51219cpng", 170 | level: 2, 171 | name: "粤菜" 172 | }, 173 | { 174 | count: 0, 175 | id: 232, 176 | image_url: "a33f1ec0044ddd4d282fbc8b1f0a946fpng", 177 | level: 2, 178 | name: "海鲜" 179 | }, 180 | { 181 | count: 0, 182 | id: 231, 183 | image_url: "c03d81f550eb849ed2d4d0290ced9099png", 184 | level: 2, 185 | name: "火锅烤鱼" 186 | }, 187 | { 188 | count: 0, 189 | id: 223, 190 | image_url: "aa4de1e9b54170cf495d8052407658c5png", 191 | level: 2, 192 | name: "东北菜" 193 | }, 194 | { 195 | count: 0, 196 | id: 226, 197 | image_url: "741d15270496d7699dd2e7804fccc7a1png", 198 | level: 2, 199 | name: "西北菜" 200 | }, 201 | { 202 | count: 0, 203 | id: 224, 204 | image_url: "54dabf93116f4a336fcc91431be43828png", 205 | level: 2, 206 | name: "云南菜" 207 | }, 208 | { 209 | count: 0, 210 | id: 228, 211 | image_url: "a7e6d9cf1993fa4fe0bd02d74d40c9c2png", 212 | level: 2, 213 | name: "新疆菜" 214 | }, 215 | { 216 | count: 0, 217 | id: 227, 218 | image_url: "e19bf59188a157dfc372b3d254fc986dpng", 219 | level: 2, 220 | name: "鲁菜" 221 | } 222 | ] 223 | }, 224 | { 225 | count: 0, 226 | id: 260, 227 | ids: [ 228 | 260 229 | ], 230 | image_url: "1babf6efbfdb0ef701f19689a5529e5fjpeg", 231 | level: 1, 232 | name: "异国料理", 233 | sub_categories: [ 234 | { 235 | count: 0, 236 | id: 260, 237 | image_url: "754c5c2ad1b01668a7186ec5f0fb0e59png", 238 | level: 1, 239 | name: "全部异国料理" 240 | }, 241 | { 242 | count: 0, 243 | id: 229, 244 | image_url: "cf8c84a2fe5ecf27b21bcbddc1724d36png", 245 | level: 2, 246 | name: "日韩料理" 247 | }, 248 | { 249 | count: 0, 250 | id: 230, 251 | image_url: "78c45200d58e5c02cb70fb8287df732dpng", 252 | level: 2, 253 | name: "西餐" 254 | }, 255 | { 256 | count: 0, 257 | id: 211, 258 | image_url: "bb7eb2afe778ba9afbe54f9d282818d1png", 259 | level: 2, 260 | name: "披萨意面" 261 | }, 262 | { 263 | count: 0, 264 | id: 264, 265 | image_url: "614053401fddc171eed0436f3cd1f7dcpng", 266 | level: 2, 267 | name: "东南亚菜" 268 | } 269 | ] 270 | }, 271 | { 272 | count: 0, 273 | id: 233, 274 | ids: [ 275 | 233 276 | ], 277 | image_url: "435a7eda7659bac613e524ca7c1ae12epng", 278 | level: 1, 279 | name: "小吃夜宵", 280 | sub_categories: [ 281 | { 282 | count: 0, 283 | id: 233, 284 | image_url: "7d714540b1590552d991fd731e8772a3png", 285 | level: 1, 286 | name: "全部小吃夜宵" 287 | }, 288 | { 289 | count: 0, 290 | id: 236, 291 | image_url: "d049fb617edcea921185258d1675db83png", 292 | level: 2, 293 | name: "小龙虾" 294 | }, 295 | { 296 | count: 0, 297 | id: 237, 298 | image_url: "90483b16d9598aec798263220eb3a821png", 299 | level: 2, 300 | name: "地方小吃" 301 | }, 302 | { 303 | count: 0, 304 | id: 218, 305 | image_url: "3c6e2763cf4ee56f18fd1b7360585fb3png", 306 | level: 2, 307 | name: "烧烤" 308 | }, 309 | { 310 | count: 0, 311 | id: 234, 312 | image_url: "71164ef684e8a13b5e66a20a1c55671cpng", 313 | level: 2, 314 | name: "炸鸡炸串" 315 | }, 316 | { 317 | count: 0, 318 | id: 235, 319 | image_url: "efdba78945f83ed1e8e6e838718b4c65png", 320 | level: 2, 321 | name: "鸭脖卤味" 322 | }, 323 | { 324 | count: 0, 325 | id: 238, 326 | image_url: "d7e0be7e5420e213ea42e4fa3efa762bpng", 327 | level: 2, 328 | name: "零食" 329 | } 330 | ] 331 | }, 332 | { 333 | count: 0, 334 | id: 239, 335 | ids: [ 336 | 239 337 | ], 338 | image_url: "48243703799592368585b23589cf3ba8png", 339 | level: 1, 340 | name: "甜品饮品", 341 | sub_categories: [ 342 | { 343 | count: 0, 344 | id: 239, 345 | image_url: "3233a4cac2e5e02cade80cce22992796png", 346 | level: 1, 347 | name: "全部甜品饮品" 348 | }, 349 | { 350 | count: 0, 351 | id: 240, 352 | image_url: "3a40add809b4405e677c4cab574e56c4png", 353 | level: 2, 354 | name: "奶茶果汁" 355 | }, 356 | { 357 | count: 0, 358 | id: 241, 359 | image_url: "213cbac0242d4845d1d28af0fa5fe35epng", 360 | level: 2, 361 | name: "甜品" 362 | }, 363 | { 364 | count: 0, 365 | id: 242, 366 | image_url: "c2f05ef82a7ee44b7848b7fb598d42e3png", 367 | level: 2, 368 | name: "咖啡" 369 | } 370 | ] 371 | }, 372 | { 373 | count: 0, 374 | id: 244, 375 | ids: [ 376 | 244 377 | ], 378 | image_url: "6235a6fce94bed63a21508f68a72c158png", 379 | level: 1, 380 | name: "果蔬生鲜", 381 | sub_categories: [ 382 | { 383 | count: 0, 384 | id: 244, 385 | image_url: "1ce198f37a81285f4afa2aaf826a558fpng", 386 | level: 1, 387 | name: "全部果蔬生鲜" 388 | }, 389 | { 390 | count: 0, 391 | id: 245, 392 | image_url: "a831a37ec670ca93cd35a8a6b5a20e62png", 393 | level: 2, 394 | name: "水果" 395 | }, 396 | { 397 | count: 0, 398 | id: 247, 399 | image_url: "6d3cef77e055d03598cba821ebcf1f06png", 400 | level: 2, 401 | name: "生鲜" 402 | }, 403 | { 404 | count: 0, 405 | id: 246, 406 | image_url: "1729548b88614c1b3a6e71ef7f89f294png", 407 | level: 2, 408 | name: "蔬菜" 409 | }, 410 | { 411 | count: 0, 412 | id: 270, 413 | image_url: "a2ab438ee4ac09e6e53b3f96694bac81png", 414 | level: 2, 415 | name: "海鲜水产" 416 | } 417 | ] 418 | }, 419 | { 420 | count: 0, 421 | id: 248, 422 | ids: [ 423 | 248 424 | ], 425 | image_url: "0e07558e305abfb2618ae760142222f9png", 426 | level: 1, 427 | name: "鲜花蛋糕", 428 | sub_categories: [ 429 | { 430 | count: 0, 431 | id: 248, 432 | image_url: "3edf3f4ef8ed1d300896c5b9178685ebpng", 433 | level: 1, 434 | name: "全部鲜花蛋糕" 435 | }, 436 | { 437 | count: 0, 438 | id: 251, 439 | image_url: "cf598de7338b4bf9dd2924736c4ec9d2png", 440 | level: 2, 441 | name: "鲜花" 442 | }, 443 | { 444 | count: 0, 445 | id: 249, 446 | image_url: "ac94b005c97ef158282326cb49389893png", 447 | level: 2, 448 | name: "蛋糕" 449 | }, 450 | { 451 | count: 0, 452 | id: 250, 453 | image_url: "512232422a83e25a2c0a5588b7b6e730png", 454 | level: 2, 455 | name: "面包" 456 | } 457 | ] 458 | }, 459 | { 460 | count: 0, 461 | id: 252, 462 | ids: [ 463 | 252 464 | ], 465 | image_url: "ac15c5dd59b641bdfdeb822362547fb4png", 466 | level: 1, 467 | name: "商店超市", 468 | sub_categories: [ 469 | { 470 | count: 0, 471 | id: 252, 472 | image_url: "df21b511f287ccb402e68285d2653caepng", 473 | level: 1, 474 | name: "全部商店超市" 475 | }, 476 | { 477 | count: 0, 478 | id: 254, 479 | image_url: "92ae70438be9a3adfc5a560c1e6ae818png", 480 | level: 2, 481 | name: "超市" 482 | }, 483 | { 484 | count: 0, 485 | id: 271, 486 | image_url: "841d136b17fa4cb871a296c9e4997cfapng", 487 | level: 2, 488 | name: "便利店" 489 | }, 490 | { 491 | count: 0, 492 | id: 274, 493 | image_url: "7df84232aebbb5ffb53e564c9e328d31png", 494 | level: 2, 495 | name: "名酒坊" 496 | }, 497 | { 498 | count: 0, 499 | id: 273, 500 | image_url: "c2b0e2b27ea55a9a7211f14ad95dcd0apng", 501 | level: 2, 502 | name: "零食饮料" 503 | }, 504 | { 505 | count: 0, 506 | id: 255, 507 | image_url: "825031dc99e1f99c26feb7186b6cf3a6png", 508 | level: 2, 509 | name: "水站" 510 | }, 511 | { 512 | count: 0, 513 | id: 258, 514 | image_url: "54b7ce87994d6770f1ead57b0038c569png", 515 | level: 2, 516 | name: "茶" 517 | }, 518 | { 519 | count: 0, 520 | id: 256, 521 | image_url: "f6460e330d25dabd4fd8db07cf53f039png", 522 | level: 2, 523 | name: "奶站" 524 | }, 525 | { 526 | count: 0, 527 | id: 257, 528 | image_url: "b435af6662fd0b3e9fb6537474753f72png", 529 | level: 2, 530 | name: "粮油" 531 | }, 532 | { 533 | count: 0, 534 | id: 272, 535 | image_url: "f7e32a289deca477c286362e3a1bc2bcpng", 536 | level: 2, 537 | name: "美妆母婴" 538 | } 539 | ] 540 | } 541 | ] -------------------------------------------------------------------------------- /public/elm/static/js/city.ccfd1a3eb85c7b7630e8.min.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([44,45],{5:function(t,e,i){"use strict";function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var a=i(10),r=o(a),n=i(4);e.default={data:function(){return{}},mounted:function(){this.getUserInfo()},props:["signinUp","headTitle","goBack"],computed:(0,r.default)({},(0,n.mapState)(["userInfo"])),methods:(0,r.default)({},(0,n.mapActions)(["getUserInfo"]))}},6:function(t,e,i){e=t.exports=i(2)(),e.push([t.id,"#head_top[data-v-cec0c0c0]{background-color:#3190e8;position:fixed;z-index:100;left:0;top:0;width:100%;height:1.95rem}.head_goback[data-v-cec0c0c0]{left:.4rem;width:.6rem;height:1rem;line-height:2.2rem;margin-left:.4rem}.head_login[data-v-cec0c0c0]{right:.55rem;font-size:.65rem;color:#fff;position:absolute;top:50%;transform:translateY(-50%)}.head_login .login_span[data-v-cec0c0c0]{color:#fff}.head_login .user_avatar[data-v-cec0c0c0]{fill:#fff;width:.8rem;height:.8rem}.title_head[data-v-cec0c0c0]{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:50%;color:#fff;text-align:center}.title_head .title_text[data-v-cec0c0c0]{font-size:.8rem;color:#fff;text-align:center;font-weight:700}","",{version:3,sources:["/./src/components/header/head.vue"],names:[],mappings:"AACA,2BAA2B,yBAAyB,eAAe,YAAY,OAAO,MAAM,WAAW,cAAc,CACpH,AACD,8BAA8B,WAAY,YAAY,YAAY,mBAAmB,iBAAiB,CACrG,AACD,6BAA6B,aAAc,iBAAiB,WAAW,kBAAkB,QAAQ,AAAkE,0BAA0B,CAC5L,AACD,yCAAyC,UAAU,CAClD,AACD,0CAA0C,UAAU,YAAY,YAAY,CAC3E,AACD,6BAA6B,kBAAkB,QAAQ,SAAS,AAA4E,+BAAgC,UAAU,WAAW,iBAAiB,CACjN,AACD,yCAAyC,gBAAgB,WAAW,kBAAkB,eAAgB,CACrG",file:"head.vue",sourcesContent:["\n#head_top[data-v-cec0c0c0]{background-color:#3190e8;position:fixed;z-index:100;left:0;top:0;width:100%;height:1.95rem\n}\n.head_goback[data-v-cec0c0c0]{left:0.4rem;width:.6rem;height:1rem;line-height:2.2rem;margin-left:.4rem\n}\n.head_login[data-v-cec0c0c0]{right:0.55rem;font-size:.65rem;color:#fff;position:absolute;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)\n}\n.head_login .login_span[data-v-cec0c0c0]{color:#fff\n}\n.head_login .user_avatar[data-v-cec0c0c0]{fill:#fff;width:.8rem;height:.8rem\n}\n.title_head[data-v-cec0c0c0]{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%, -50%);-ms-transform:translate(-50%, -50%);transform:translate(-50%, -50%);width:50%;color:#fff;text-align:center\n}\n.title_head .title_text[data-v-cec0c0c0]{font-size:.8rem;color:#fff;text-align:center;font-weight:bold\n}\n"],sourceRoot:"webpack://"}])},7:function(t,e,i){var o=i(6);"string"==typeof o&&(o=[[t.id,o,""]]);i(3)(o,{});o.locals&&(t.exports=o.locals)},8:function(t,e,i){i(7);var o=i(1)(i(5),i(9),"data-v-cec0c0c0",null);t.exports=o.exports},9:function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,i=t._self._c||e;return i("header",{attrs:{id:"head_top"}},[t._t("logo"),t._v(" "),t._t("search"),t._v(" "),t.goBack?i("section",{staticClass:"head_goback",on:{click:function(e){t.$router.go(-1)}}},[i("svg",{attrs:{width:"100%",height:"100%",xmlns:"http://www.w3.org/2000/svg",version:"1.1"}},[i("polyline",{staticStyle:{fill:"none",stroke:"rgb(255,255,255)","stroke-width":"2"},attrs:{points:"12,18 4,9 12,0"}})])]):t._e(),t._v(" "),t.signinUp?i("router-link",{staticClass:"head_login",attrs:{to:t.userInfo?"/profile":"/login"}},[t.userInfo?i("svg",{staticClass:"user_avatar"},[i("use",{attrs:{"xmlns:xlink":"http://www.w3.org/1999/xlink","xlink:href":"#user"}})]):i("span",{staticClass:"login_span"},[t._v("登录|注册")])]):t._e(),t._v(" "),t.headTitle?i("section",{staticClass:"title_head ellipsis"},[i("span",{staticClass:"title_text"},[t._v(t._s(t.headTitle))])]):t._e(),t._v(" "),t._t("edit"),t._v(" "),t._t("msite-title"),t._v(" "),t._t("changecity"),t._v(" "),t._t("changeLogin")],2)},staticRenderFns:[]}},132:function(t,e,i){"use strict";function o(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var a=i(8),r=o(a),n=i(16),s=i(27);e.default={data:function(){return{inputVaule:"",cityid:"",cityname:"",placelist:[],placeHistory:[],historytitle:!0,placeNone:!1}},mounted:function(){var t=this;this.cityid=this.$route.params.cityid,(0,n.currentcity)(this.cityid).then(function(e){t.cityname=e.name}),this.initData()},components:{headTop:r.default},computed:{},methods:{initData:function(){(0,s.getStore)("placeHistory")?this.placelist=JSON.parse((0,s.getStore)("placeHistory")):this.placelist=[]},postpois:function(){var t=this;this.inputVaule&&(0,n.searchplace)(this.cityid,this.inputVaule).then(function(e){t.historytitle=!1,t.placelist=e,t.placeNone=!e.length})},nextpage:function(t,e){var i=(0,s.getStore)("placeHistory"),o=this.placelist[t];if(i){var a=!1;this.placeHistory=JSON.parse(i),this.placeHistory.forEach(function(t){t.geohash==e&&(a=!0)}),a||this.placeHistory.push(o)}else this.placeHistory.push(o);(0,s.setStore)("placeHistory",this.placeHistory),this.$router.push({path:"/msite",query:{geohash:e}})},clearAll:function(){(0,s.removeStore)("placeHistory"),this.initData()}}}},224:function(t,e,i){e=t.exports=i(2)(),e.push([t.id,".city_container[data-v-0b97e5f4]{padding-top:2.35rem}.change_city[data-v-0b97e5f4]{right:.4rem;font-size:.6rem;color:#fff;position:absolute;top:50%;transform:translateY(-50%)}.city_form[data-v-0b97e5f4]{background-color:#fff;border-top:1px solid #e4e4e4;border-bottom:1px solid #e4e4e4;padding-top:.4rem}.city_form div[data-v-0b97e5f4]{width:90%;margin:0 auto;text-align:center}.city_form div .input_style[data-v-0b97e5f4]{border-radius:.1rem;margin-bottom:.4rem;width:100%;height:1.4rem}.city_form div .city_input[data-v-0b97e5f4]{border:1px solid #e4e4e4;padding:0 .3rem;font-size:.65rem;color:#333}.city_form div .city_submit[data-v-0b97e5f4]{background-color:#3190e8;font-size:.65rem;color:#fff}.pois_search_history[data-v-0b97e5f4]{border-top:1px solid #e4e4e4;border-bottom:1px solid #e4e4e4;padding-left:.5rem;font:.475rem/.8rem Microsoft YaHei}.getpois_ul[data-v-0b97e5f4]{background-color:#fff;border-top:1px solid #e4e4e4}.getpois_ul li[data-v-0b97e5f4]{margin:0 auto;padding-top:.65rem;border-bottom:1px solid #e4e4e4}.getpois_ul li .pois_name[data-v-0b97e5f4]{margin:0 auto .35rem;width:90%;font-size:.65rem;color:#333}.getpois_ul li .pois_address[data-v-0b97e5f4]{width:90%;margin:0 auto .55rem;font-size:.45rem;color:#999}.search_none_place[data-v-0b97e5f4]{margin:0 auto;font:.65rem/1.75rem Microsoft YaHei;color:#333;background-color:#fff;text-indent:.5rem}.clear_all_history[data-v-0b97e5f4]{font-size:.7rem;color:#666;text-align:center;line-height:2rem;background-color:#fff}","",{version:3,sources:["/./src/page/city/city.vue"],names:[],mappings:"AACA,iCAAiC,mBAAmB,CACnD,AACD,8BAA8B,YAAa,gBAAgB,WAAW,kBAAkB,QAAQ,AAAkE,0BAA0B,CAC3L,AACD,4BAA4B,sBAAsB,6BAA6B,gCAAgC,iBAAkB,CAChI,AACD,gCAAgC,UAAU,cAAc,iBAAiB,CACxE,AACD,6CAA6C,oBAAqB,oBAAqB,WAAW,aAAa,CAC9G,AACD,4CAA4C,yBAAyB,gBAAiB,iBAAiB,UAAU,CAChH,AACD,6CAA6C,yBAAyB,iBAAiB,UAAU,CAChG,AACD,sCAAsC,6BAA6B,gCAAgC,mBAAoB,kCAAqC,CAC3J,AACD,6BAA6B,sBAAsB,4BAA4B,CAC9E,AACD,gCAAgC,cAAc,mBAAoB,+BAA+B,CAChG,AACD,2CAA2C,qBAAsB,UAAU,iBAAiB,UAAU,CACrG,AACD,8CAA8C,UAAU,qBAAsB,iBAAiB,UAAU,CACxG,AACD,oCAAoC,cAAc,oCAAuC,WAAW,sBAAsB,iBAAkB,CAC3I,AACD,oCAAoC,gBAAgB,WAAW,kBAAkB,iBAAiB,qBAAqB,CACtH",file:"city.vue",sourcesContent:['\n.city_container[data-v-0b97e5f4]{padding-top:2.35rem\n}\n.change_city[data-v-0b97e5f4]{right:0.4rem;font-size:.6rem;color:#fff;position:absolute;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)\n}\n.city_form[data-v-0b97e5f4]{background-color:#fff;border-top:1px solid #e4e4e4;border-bottom:1px solid #e4e4e4;padding-top:0.4rem\n}\n.city_form div[data-v-0b97e5f4]{width:90%;margin:0 auto;text-align:center\n}\n.city_form div .input_style[data-v-0b97e5f4]{border-radius:0.1rem;margin-bottom:0.4rem;width:100%;height:1.4rem\n}\n.city_form div .city_input[data-v-0b97e5f4]{border:1px solid #e4e4e4;padding:0 0.3rem;font-size:.65rem;color:#333\n}\n.city_form div .city_submit[data-v-0b97e5f4]{background-color:#3190e8;font-size:.65rem;color:#fff\n}\n.pois_search_history[data-v-0b97e5f4]{border-top:1px solid #e4e4e4;border-bottom:1px solid #e4e4e4;padding-left:0.5rem;font:0.475rem/.8rem "Microsoft YaHei"\n}\n.getpois_ul[data-v-0b97e5f4]{background-color:#fff;border-top:1px solid #e4e4e4\n}\n.getpois_ul li[data-v-0b97e5f4]{margin:0 auto;padding-top:0.65rem;border-bottom:1px solid #e4e4e4\n}\n.getpois_ul li .pois_name[data-v-0b97e5f4]{margin:0 auto 0.35rem;width:90%;font-size:.65rem;color:#333\n}\n.getpois_ul li .pois_address[data-v-0b97e5f4]{width:90%;margin:0 auto 0.55rem;font-size:.45rem;color:#999\n}\n.search_none_place[data-v-0b97e5f4]{margin:0 auto;font:0.65rem/1.75rem "Microsoft YaHei";color:#333;background-color:#fff;text-indent:0.5rem\n}\n.clear_all_history[data-v-0b97e5f4]{font-size:.7rem;color:#666;text-align:center;line-height:2rem;background-color:#fff\n}\n'],sourceRoot:"webpack://"}])},271:function(t,e,i){var o=i(224);"string"==typeof o&&(o=[[t.id,o,""]]);i(3)(o,{});o.locals&&(t.exports=o.locals)},354:function(t,e,i){i(271);var o=i(1)(i(132),i(394),"data-v-0b97e5f4",null);t.exports=o.exports},394:function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,i=t._self._c||e;return i("div",{staticClass:"city_container"},[i("head-top",{attrs:{"head-title":t.cityname,"go-back":"true"}},[i("router-link",{staticClass:"change_city",attrs:{slot:"changecity",to:"/home"},slot:"changecity"},[t._v("切换城市")])],1),t._v(" "),i("form",{staticClass:"city_form",on:{submit:function(t){t.preventDefault()}}},[i("div",[i("input",{directives:[{name:"model",rawName:"v-model",value:t.inputVaule,expression:"inputVaule"}],staticClass:"city_input input_style",attrs:{type:"search",name:"city",placeholder:"输入学校、商务楼、地址",required:""},domProps:{value:t.inputVaule},on:{input:function(e){e.target.composing||(t.inputVaule=e.target.value)}}})]),t._v(" "),i("div",[i("input",{staticClass:"city_submit input_style",attrs:{type:"submit",name:"submit",value:"提交"},on:{click:t.postpois}})])]),t._v(" "),t.historytitle?i("header",{staticClass:"pois_search_history"},[t._v("搜索历史")]):t._e(),t._v(" "),i("ul",{staticClass:"getpois_ul"},t._l(t.placelist,function(e,o){return i("li",{key:o,on:{click:function(i){t.nextpage(o,e.geohash)}}},[i("h4",{staticClass:"pois_name ellipsis"},[t._v(t._s(e.name))]),t._v(" "),i("p",{staticClass:"pois_address ellipsis"},[t._v(t._s(e.address))])])})),t._v(" "),t.historytitle&&t.placelist.length?i("footer",{staticClass:"clear_all_history",on:{click:t.clearAll}},[t._v("清空所有")]):t._e(),t._v(" "),t.placeNone?i("div",{staticClass:"search_none_place"},[t._v("很抱歉!无搜索结果")]):t._e()],1)},staticRenderFns:[]}}}); -------------------------------------------------------------------------------- /public/elm/static/js/addDetail.75da563d1e4448287a21.min.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([37,45],{5:function(t,e,a){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=a(10),o=i(n),r=a(4);e.default={data:function(){return{}},mounted:function(){this.getUserInfo()},props:["signinUp","headTitle","goBack"],computed:(0,o.default)({},(0,r.mapState)(["userInfo"])),methods:(0,o.default)({},(0,r.mapActions)(["getUserInfo"]))}},6:function(t,e,a){e=t.exports=a(2)(),e.push([t.id,"#head_top[data-v-cec0c0c0]{background-color:#3190e8;position:fixed;z-index:100;left:0;top:0;width:100%;height:1.95rem}.head_goback[data-v-cec0c0c0]{left:.4rem;width:.6rem;height:1rem;line-height:2.2rem;margin-left:.4rem}.head_login[data-v-cec0c0c0]{right:.55rem;font-size:.65rem;color:#fff;position:absolute;top:50%;transform:translateY(-50%)}.head_login .login_span[data-v-cec0c0c0]{color:#fff}.head_login .user_avatar[data-v-cec0c0c0]{fill:#fff;width:.8rem;height:.8rem}.title_head[data-v-cec0c0c0]{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:50%;color:#fff;text-align:center}.title_head .title_text[data-v-cec0c0c0]{font-size:.8rem;color:#fff;text-align:center;font-weight:700}","",{version:3,sources:["/./src/components/header/head.vue"],names:[],mappings:"AACA,2BAA2B,yBAAyB,eAAe,YAAY,OAAO,MAAM,WAAW,cAAc,CACpH,AACD,8BAA8B,WAAY,YAAY,YAAY,mBAAmB,iBAAiB,CACrG,AACD,6BAA6B,aAAc,iBAAiB,WAAW,kBAAkB,QAAQ,AAAkE,0BAA0B,CAC5L,AACD,yCAAyC,UAAU,CAClD,AACD,0CAA0C,UAAU,YAAY,YAAY,CAC3E,AACD,6BAA6B,kBAAkB,QAAQ,SAAS,AAA4E,+BAAgC,UAAU,WAAW,iBAAiB,CACjN,AACD,yCAAyC,gBAAgB,WAAW,kBAAkB,eAAgB,CACrG",file:"head.vue",sourcesContent:["\n#head_top[data-v-cec0c0c0]{background-color:#3190e8;position:fixed;z-index:100;left:0;top:0;width:100%;height:1.95rem\n}\n.head_goback[data-v-cec0c0c0]{left:0.4rem;width:.6rem;height:1rem;line-height:2.2rem;margin-left:.4rem\n}\n.head_login[data-v-cec0c0c0]{right:0.55rem;font-size:.65rem;color:#fff;position:absolute;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)\n}\n.head_login .login_span[data-v-cec0c0c0]{color:#fff\n}\n.head_login .user_avatar[data-v-cec0c0c0]{fill:#fff;width:.8rem;height:.8rem\n}\n.title_head[data-v-cec0c0c0]{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%, -50%);-ms-transform:translate(-50%, -50%);transform:translate(-50%, -50%);width:50%;color:#fff;text-align:center\n}\n.title_head .title_text[data-v-cec0c0c0]{font-size:.8rem;color:#fff;text-align:center;font-weight:bold\n}\n"],sourceRoot:"webpack://"}])},7:function(t,e,a){var i=a(6);"string"==typeof i&&(i=[[t.id,i,""]]);a(3)(i,{});i.locals&&(t.exports=i.locals)},8:function(t,e,a){a(7);var i=a(1)(a(5),a(9),"data-v-cec0c0c0",null);t.exports=i.exports},9:function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("header",{attrs:{id:"head_top"}},[t._t("logo"),t._v(" "),t._t("search"),t._v(" "),t.goBack?a("section",{staticClass:"head_goback",on:{click:function(e){t.$router.go(-1)}}},[a("svg",{attrs:{width:"100%",height:"100%",xmlns:"http://www.w3.org/2000/svg",version:"1.1"}},[a("polyline",{staticStyle:{fill:"none",stroke:"rgb(255,255,255)","stroke-width":"2"},attrs:{points:"12,18 4,9 12,0"}})])]):t._e(),t._v(" "),t.signinUp?a("router-link",{staticClass:"head_login",attrs:{to:t.userInfo?"/profile":"/login"}},[t.userInfo?a("svg",{staticClass:"user_avatar"},[a("use",{attrs:{"xmlns:xlink":"http://www.w3.org/1999/xlink","xlink:href":"#user"}})]):a("span",{staticClass:"login_span"},[t._v("登录|注册")])]):t._e(),t._v(" "),t.headTitle?a("section",{staticClass:"title_head ellipsis"},[a("span",{staticClass:"title_text"},[t._v(t._s(t.headTitle))])]):t._e(),t._v(" "),t._t("edit"),t._v(" "),t._t("msite-title"),t._v(" "),t._t("changecity"),t._v(" "),t._t("changeLogin")],2)},staticRenderFns:[]}},18:function(t,e,a){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.getImgPath=e.loadMore=void 0;var i=a(27);a(17),e.loadMore={directives:{"load-more":{bind:function(t,e){var a=window.screen.height,n=void 0,o=void 0,r=void 0,s=void 0,d=void 0,A=void 0,c=void 0,l=void 0,f=t.attributes.type&&t.attributes.type.value,p=2;2==f?(c=t,l=t.children[0]):(c=document.body,l=t),t.addEventListener("touchstart",function(){n=l.clientHeight,2==f&&(n=n),o=t.offsetTop,r=(0,i.getStyle)(t,"paddingBottom"),s=(0,i.getStyle)(t,"marginBottom")},!1),t.addEventListener("touchmove",function(){m()},!1),t.addEventListener("touchend",function(){A=c.scrollTop,u()},!1);var u=function t(){d=requestAnimationFrame(function(){c.scrollTop!=A?(A=c.scrollTop,t()):(cancelAnimationFrame(d),n=l.clientHeight,m())})},m=function(){c.scrollTop+a>=n+o+r+s-p&&e.value()}}}}},e.getImgPath={methods:{getImgPath:function(t){var e=void 0;if(!t)return"//elm.cangdu.org/img/default.jpg";e=t.indexOf("jpeg")!==-1?".jpeg":".png";var a="/"+t.substr(0,1)+"/"+t.substr(1,2)+"/"+t.substr(3)+e;return"https://fuss10.elemecdn.com"+a}}}},154:function(t,e,a){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var n=a(10),o=i(n),r=a(8),s=i(r),d=a(18),A=a(16),c=a(4);e.default={data:function(){return{warning:!0,inputAdress:"",adressList:[]}},created:function(){this.inputAdress=this.addAddress?this.addAddress:this.inputAdress},mounted:function(){},mixins:[d.getImgPath],components:{headTop:s.default},computed:(0,o.default)({},(0,c.mapState)(["addAddress"])),props:[],methods:(0,o.default)({},(0,c.mapMutations)(["SAVE_ADDDETAIL"]),{inputThing:function(){var t=this;(0,A.searchNearby)(this.inputAdress).then(function(e){t.adressList=e,t.warning=!0,t.adressList.length>0&&(t.warning=!1,""==t.inputAdress&&(t.adressList=[],t.warning=!0))})},listClick:function(t){this.SAVE_ADDDETAIL(this.adressList[t].name),this.$router.go(-1)}})}},252:function(t,e,a){e=t.exports=a(2)(),e.push([t.id,".rating_page[data-v-78b5a23a]{position:absolute;top:0;left:0;right:0;bottom:0;background-color:#f2f2f2;z-index:205;padding-top:1.95rem}.rating_page p[data-v-78b5a23a],.rating_page span[data-v-78b5a23a]{font-family:Helvetica Neue,Tahoma,Arial}.add-detail[data-v-78b5a23a]{display:-ms-flexbox;display:flex;-ms-flex-pack:justify;justify-content:space-between;background:#fff;padding:.5rem}.add-detail input[data-v-78b5a23a]{display:block;width:11.8rem;padding:.4rem;background:#f2f2f2;border:1px solid #ddd;border-radius:5px;font-size:.6rem}.add-detail button[data-v-78b5a23a]{display:block;width:3rem;background:#3199e8;font-size:.7rem;color:#fff;border-radius:5px}.warnpart[data-v-78b5a23a]{background:#fff6e4;font-size:.62rem;color:#ff883f;text-align:center;padding:.2rem 0}.point[data-v-78b5a23a]{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:100%}.point p[data-v-78b5a23a]{width:100%;text-align:center;font-size:.7rem;color:#969696;margin-bottom:.4rem}.poisearch-container[data-v-78b5a23a]{background:#f2f2f2}.poisearch-container li[data-v-78b5a23a]{border-bottom:1px solid #ccc;padding:.4rem}.poisearch-container li p[data-v-78b5a23a]{font-size:.65rem;color:#969696}.poisearch-container li p[data-v-78b5a23a]:first-child{margin-bottom:.2rem}.poisearch-container li[data-v-78b5a23a]:last-child{border:0}","",{version:3,sources:["/./src/page/profile/children/children/children/children/addDetail.vue"],names:[],mappings:"AACA,8BAA8B,kBAAkB,MAAM,OAAO,QAAQ,SAAS,yBAAyB,YAAY,mBAAmB,CACrI,AACD,mEAAmE,uCAAuC,CACzG,AACD,6BAAsE,oBAAoB,aAAa,AAA+D,sBAAsB,8BAA8B,gBAAgB,aAAa,CACtP,AACD,mCAAmC,cAAc,cAAc,cAAc,mBAAmB,sBAAsB,kBAAkB,eAAe,CACtJ,AACD,oCAAoC,cAAc,WAAW,mBAAmB,gBAAgB,WAAW,iBAAiB,CAC3H,AACD,2BAA2B,mBAAmB,iBAAiB,cAAc,kBAAkB,eAAe,CAC7G,AACD,wBAAwB,kBAAkB,QAAQ,SAAS,AAA4E,+BAAgC,UAAU,CAChL,AACD,0BAA0B,WAAW,kBAAkB,gBAAgB,cAAc,mBAAmB,CACvG,AACD,sCAAsC,kBAAkB,CACvD,AACD,yCAAyC,6BAA6B,aAAa,CAClF,AACD,2CAA2C,iBAAiB,aAAa,CACxE,AACD,uDAAuD,mBAAmB,CACzE,AACD,oDAAoD,QAAQ,CAC3D",file:"addDetail.vue",sourcesContent:["\n.rating_page[data-v-78b5a23a]{position:absolute;top:0;left:0;right:0;bottom:0;background-color:#f2f2f2;z-index:205;padding-top:1.95rem\n}\n.rating_page p[data-v-78b5a23a],.rating_page span[data-v-78b5a23a]{font-family:Helvetica Neue,Tahoma,Arial\n}\n.add-detail[data-v-78b5a23a]{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;background:#fff;padding:.5rem\n}\n.add-detail input[data-v-78b5a23a]{display:block;width:11.8rem;padding:.4rem;background:#f2f2f2;border:1px solid #ddd;border-radius:5px;font-size:.6rem\n}\n.add-detail button[data-v-78b5a23a]{display:block;width:3rem;background:#3199e8;font-size:.7rem;color:#fff;border-radius:5px\n}\n.warnpart[data-v-78b5a23a]{background:#FFF6E4;font-size:.62rem;color:#FF883F;text-align:center;padding:.2rem 0\n}\n.point[data-v-78b5a23a]{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%, -50%);-ms-transform:translate(-50%, -50%);transform:translate(-50%, -50%);width:100%\n}\n.point p[data-v-78b5a23a]{width:100%;text-align:center;font-size:.7rem;color:#969696;margin-bottom:.4rem\n}\n.poisearch-container[data-v-78b5a23a]{background:#f2f2f2\n}\n.poisearch-container li[data-v-78b5a23a]{border-bottom:1px solid #ccc;padding:.4rem\n}\n.poisearch-container li p[data-v-78b5a23a]{font-size:.65rem;color:#969696\n}\n.poisearch-container li p[data-v-78b5a23a]:first-child{margin-bottom:.2rem\n}\n.poisearch-container li[data-v-78b5a23a]:last-child{border:0\n}\n"],sourceRoot:"webpack://"}])},301:function(t,e,a){var i=a(252);"string"==typeof i&&(i=[[t.id,i,""]]);a(3)(i,{});i.locals&&(t.exports=i.locals)},376:function(t,e,a){a(301);var i=a(1)(a(154),a(424),"data-v-78b5a23a",null);t.exports=i.exports},424:function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"rating_page"},[a("head-top",{attrs:{"head-title":"搜索地址","go-back":"true"}}),t._v(" "),a("section",[a("div",{staticClass:"add-detail"},[a("input",{directives:[{name:"model",rawName:"v-model",value:t.inputAdress,expression:"inputAdress"}],attrs:{type:"text",placeholder:"请输入小区/写字楼/学校等"},domProps:{value:t.inputAdress},on:{input:function(e){e.target.composing||(t.inputAdress=e.target.value)}}}),t._v(" "),a("button",{on:{click:t.inputThing}},[t._v("确认")])]),t._v(" "),a("div",{staticClass:"warnpart"},[t._v("为了满足商家的送餐要求,建议您从列表中选择地址")]),t._v(" "),a("div",{directives:[{name:"show",rawName:"v-show",value:t.warning,expression:"warning"}],staticClass:"point"},[a("p",[t._v("找不到地址?")]),t._v(" "),a("p",[t._v("请尝试输入小区、写字楼或学校名")]),t._v(" "),a("p",[t._v("详细地址(如门牌号)可稍后输入哦。")])])]),t._v(" "),a("section",{directives:[{name:"show",rawName:"v-show",value:t.adressList,expression:"adressList"}],staticClass:"poisearch-container"},[a("ul",t._l(t.adressList,function(e,i){return a("li",{on:{click:function(e){t.listClick(i)}}},[a("p",[t._v(t._s(e.name))]),t._v(" "),a("p",[t._v(t._s(e.address))])])}))])],1)},staticRenderFns:[]}}}); -------------------------------------------------------------------------------- /public/elm/static/js/service.42109737c50ef928069c.min.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([40,45],{5:function(e,t,a){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var n=a(10),s=i(n),o=a(4);t.default={data:function(){return{}},mounted:function(){this.getUserInfo()},props:["signinUp","headTitle","goBack"],computed:(0,s.default)({},(0,o.mapState)(["userInfo"])),methods:(0,s.default)({},(0,o.mapActions)(["getUserInfo"]))}},6:function(e,t,a){t=e.exports=a(2)(),t.push([e.id,"#head_top[data-v-cec0c0c0]{background-color:#3190e8;position:fixed;z-index:100;left:0;top:0;width:100%;height:1.95rem}.head_goback[data-v-cec0c0c0]{left:.4rem;width:.6rem;height:1rem;line-height:2.2rem;margin-left:.4rem}.head_login[data-v-cec0c0c0]{right:.55rem;font-size:.65rem;color:#fff;position:absolute;top:50%;transform:translateY(-50%)}.head_login .login_span[data-v-cec0c0c0]{color:#fff}.head_login .user_avatar[data-v-cec0c0c0]{fill:#fff;width:.8rem;height:.8rem}.title_head[data-v-cec0c0c0]{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:50%;color:#fff;text-align:center}.title_head .title_text[data-v-cec0c0c0]{font-size:.8rem;color:#fff;text-align:center;font-weight:700}","",{version:3,sources:["/./src/components/header/head.vue"],names:[],mappings:"AACA,2BAA2B,yBAAyB,eAAe,YAAY,OAAO,MAAM,WAAW,cAAc,CACpH,AACD,8BAA8B,WAAY,YAAY,YAAY,mBAAmB,iBAAiB,CACrG,AACD,6BAA6B,aAAc,iBAAiB,WAAW,kBAAkB,QAAQ,AAAkE,0BAA0B,CAC5L,AACD,yCAAyC,UAAU,CAClD,AACD,0CAA0C,UAAU,YAAY,YAAY,CAC3E,AACD,6BAA6B,kBAAkB,QAAQ,SAAS,AAA4E,+BAAgC,UAAU,WAAW,iBAAiB,CACjN,AACD,yCAAyC,gBAAgB,WAAW,kBAAkB,eAAgB,CACrG",file:"head.vue",sourcesContent:["\n#head_top[data-v-cec0c0c0]{background-color:#3190e8;position:fixed;z-index:100;left:0;top:0;width:100%;height:1.95rem\n}\n.head_goback[data-v-cec0c0c0]{left:0.4rem;width:.6rem;height:1rem;line-height:2.2rem;margin-left:.4rem\n}\n.head_login[data-v-cec0c0c0]{right:0.55rem;font-size:.65rem;color:#fff;position:absolute;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)\n}\n.head_login .login_span[data-v-cec0c0c0]{color:#fff\n}\n.head_login .user_avatar[data-v-cec0c0c0]{fill:#fff;width:.8rem;height:.8rem\n}\n.title_head[data-v-cec0c0c0]{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%, -50%);-ms-transform:translate(-50%, -50%);transform:translate(-50%, -50%);width:50%;color:#fff;text-align:center\n}\n.title_head .title_text[data-v-cec0c0c0]{font-size:.8rem;color:#fff;text-align:center;font-weight:bold\n}\n"],sourceRoot:"webpack://"}])},7:function(e,t,a){var i=a(6);"string"==typeof i&&(i=[[e.id,i,""]]);a(3)(i,{});i.locals&&(e.exports=i.locals)},8:function(e,t,a){a(7);var i=a(1)(a(5),a(9),"data-v-cec0c0c0",null);e.exports=i.exports},9:function(e,t){e.exports={render:function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("header",{attrs:{id:"head_top"}},[e._t("logo"),e._v(" "),e._t("search"),e._v(" "),e.goBack?a("section",{staticClass:"head_goback",on:{click:function(t){e.$router.go(-1)}}},[a("svg",{attrs:{width:"100%",height:"100%",xmlns:"http://www.w3.org/2000/svg",version:"1.1"}},[a("polyline",{staticStyle:{fill:"none",stroke:"rgb(255,255,255)","stroke-width":"2"},attrs:{points:"12,18 4,9 12,0"}})])]):e._e(),e._v(" "),e.signinUp?a("router-link",{staticClass:"head_login",attrs:{to:e.userInfo?"/profile":"/login"}},[e.userInfo?a("svg",{staticClass:"user_avatar"},[a("use",{attrs:{"xmlns:xlink":"http://www.w3.org/1999/xlink","xlink:href":"#user"}})]):a("span",{staticClass:"login_span"},[e._v("登录|注册")])]):e._e(),e._v(" "),e.headTitle?a("section",{staticClass:"title_head ellipsis"},[a("span",{staticClass:"title_text"},[e._v(e._s(e.headTitle))])]):e._e(),e._v(" "),e._t("edit"),e._v(" "),e._t("msite-title"),e._v(" "),e._t("changecity"),e._v(" "),e._t("changeLogin")],2)},staticRenderFns:[]}},160:function(e,t,a){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var n=a(20),s=i(n),o=a(65),r=i(o),l=a(19),c=i(l),A=a(10),d=i(A),f=a(8),u=i(f),m=a(16),p=a(4);t.default={data:function(){return{serviceData:null,questionTitle:[],questionDetail:[]}},mounted:function(){this.initData()},mixins:[],components:{headTop:u.default},props:[],methods:(0,d.default)({},(0,p.mapMutations)(["SAVE_QUESTION"]),{initData:function(){var e=this;return(0,c.default)(s.default.mark(function t(){return s.default.wrap(function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,(0,m.getService)();case 2:e.serviceData=t.sent,(0,r.default)(e.serviceData).forEach(function(t){var a=!1;e.questionTitle.forEach(function(i){i==e.serviceData[t]&&(a=!0)}),t.indexOf("Caption")===-1||a?a||e.questionDetail.push(e.serviceData[t]):e.questionTitle.push(e.serviceData[t])});case 4:case"end":return t.stop()}},t,e)}))()},toQuestionDetail:function(e,t){this.SAVE_QUESTION({title:e,detail:this.questionDetail[t]}),this.$router.push("/service/questionDetail")}})}},229:function(e,t,a){t=e.exports=a(2)(),t.push([e.id,".rating_page[data-v-1a228d92]{background-color:#fff;padding-top:1.95rem}.rating_page p[data-v-1a228d92],.rating_page span[data-v-1a228d92]{font-family:Helvetica Neue,Tahoma,Arial}.service_connect[data-v-1a228d92]{display:-ms-flexbox;display:flex;-ms-flex-pack:justify;justify-content:space-between}.service_connect a[data-v-1a228d92]{-ms-flex:1;flex:1;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;height:4rem;border-bottom:1px solid #f5f5f5}.service_connect a svg[data-v-1a228d92]{width:1rem;height:1rem}.service_connect a span[data-v-1a228d92]{margin-top:.4rem;font-size:.6rem;color:#666}.service_connect .service_left[data-v-1a228d92]{border-right:1px solid #f5f5f5}.hot_questions .qustion_header[data-v-1a228d92]{font-size:.75rem;color:#333;line-height:3rem;border-bottom:1px solid #f5f5f5;padding-left:.7rem}.hot_questions .question_title[data-v-1a228d92]{padding:0 .7rem;line-height:2rem;border-bottom:1px solid #f5f5f5;display:-ms-flexbox;display:flex;-ms-flex-pack:justify;justify-content:space-between;-ms-flex-align:center;align-items:center}.hot_questions .question_title span[data-v-1a228d92]{font-size:.6rem;color:#666}.hot_questions .question_title svg[data-v-1a228d92]{width:.6rem;height:.6rem}.router-slid-enter-active[data-v-1a228d92],.router-slid-leave-active[data-v-1a228d92]{transition:all .4s}.router-slid-enter[data-v-1a228d92],.router-slid-leave-active[data-v-1a228d92]{transform:translate3d(2rem,0,0);opacity:0}","",{version:3,sources:["/./src/page/service/service.vue"],names:[],mappings:"AACA,8BAA8B,sBAAsB,mBAAmB,CACtE,AACD,mEAAmE,uCAAuC,CACzG,AACD,kCAA2E,oBAAoB,aAAa,AAA+D,sBAAsB,6BAA6B,CAC7N,AACD,oCAAsE,WAAW,OAAO,AAAyC,oBAAoB,aAAa,AAAuF,0BAA0B,sBAAsB,AAAoD,sBAAsB,mBAAmB,AAAuD,qBAAqB,uBAAuB,YAAY,+BAA+B,CACnhB,AACD,wCAAwC,WAAW,WAAW,CAC7D,AACD,yCAAyC,iBAAiB,gBAAgB,UAAU,CACnF,AACD,gDAAgD,8BAA8B,CAC7E,AACD,gDAAgD,iBAAiB,WAAW,iBAAiB,gCAAgC,kBAAkB,CAC9I,AACD,gDAAgD,gBAAgB,iBAAiB,gCAAgC,AAAyC,oBAAoB,aAAa,AAA+D,sBAAsB,8BAA8B,AAAoD,sBAAsB,kBAAkB,CACzY,AACD,qDAAqD,gBAAgB,UAAU,CAC9E,AACD,oDAAoD,YAAY,YAAY,CAC3E,AACD,sFAAiH,kBAAkB,CAClI,AACD,+EAAyH,gCAAkC,SAAS,CACnK",file:"service.vue",sourcesContent:["\n.rating_page[data-v-1a228d92]{background-color:#fff;padding-top:1.95rem\n}\n.rating_page p[data-v-1a228d92],.rating_page span[data-v-1a228d92]{font-family:Helvetica Neue,Tahoma,Arial\n}\n.service_connect[data-v-1a228d92]{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between\n}\n.service_connect a[data-v-1a228d92]{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;height:4rem;border-bottom:1px solid #f5f5f5\n}\n.service_connect a svg[data-v-1a228d92]{width:1rem;height:1rem\n}\n.service_connect a span[data-v-1a228d92]{margin-top:.4rem;font-size:.6rem;color:#666\n}\n.service_connect .service_left[data-v-1a228d92]{border-right:1px solid #f5f5f5\n}\n.hot_questions .qustion_header[data-v-1a228d92]{font-size:.75rem;color:#333;line-height:3rem;border-bottom:1px solid #f5f5f5;padding-left:.7rem\n}\n.hot_questions .question_title[data-v-1a228d92]{padding:0 .7rem;line-height:2rem;border-bottom:1px solid #f5f5f5;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center\n}\n.hot_questions .question_title span[data-v-1a228d92]{font-size:.6rem;color:#666\n}\n.hot_questions .question_title svg[data-v-1a228d92]{width:.6rem;height:.6rem\n}\n.router-slid-enter-active[data-v-1a228d92],.router-slid-leave-active[data-v-1a228d92]{-webkit-transition:all .4s;transition:all .4s\n}\n.router-slid-enter[data-v-1a228d92],.router-slid-leave-active[data-v-1a228d92]{-webkit-transform:translate3d(2rem, 0, 0);transform:translate3d(2rem, 0, 0);opacity:0\n}\n"],sourceRoot:"webpack://"}])},277:function(e,t,a){var i=a(229);"string"==typeof i&&(i=[[e.id,i,""]]);a(3)(i,{});i.locals&&(e.exports=i.locals)},382:function(e,t,a){a(277);var i=a(1)(a(160),a(400),"data-v-1a228d92",null);e.exports=i.exports},400:function(e,t){e.exports={render:function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",{staticClass:"rating_page"},[a("head-top",{attrs:{"head-title":"服务中心","go-back":"true"}}),e._v(" "),a("section",{staticClass:"service_connect"},[a("a",{staticClass:"service_left",attrs:{href:"https://ecs-im.ele.me/"}},[a("svg",[a("use",{attrs:{"xmlns:xlink":"http://www.w3.org/1999/xlink","xlink:href":"#human"}})]),e._v(" "),a("span",[e._v("在线客服")])]),e._v(" "),a("a",{staticClass:"service_right",attrs:{href:"tel:10105757"}},[a("svg",[a("use",{attrs:{"xmlns:xlink":"http://www.w3.org/1999/xlink","xlink:href":"#phone"}})]),e._v(" "),a("span",[e._v("在线客服")])])]),e._v(" "),e.serviceData?a("section",{staticClass:"hot_questions"},[a("h4",{staticClass:"qustion_header"},[e._v("热门问题")]),e._v(" "),a("ul",e._l(e.questionTitle,function(t,i){return a("li",{key:i,staticClass:"question_title",on:{click:function(a){e.toQuestionDetail(t,i)}}},[a("span",[e._v(e._s(t))]),e._v(" "),a("svg",{staticClass:"arrow-svg",attrs:{fill:"#999"}},[a("use",{attrs:{"xmlns:xlink":"http://www.w3.org/1999/xlink","xlink:href":"#arrow-right"}})])])}))]):e._e(),e._v(" "),a("transition",{attrs:{name:"router-slid",mode:"out-in"}},[a("router-view")],1)],1)},staticRenderFns:[]}}}); -------------------------------------------------------------------------------- /InitData/entry.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | id: 15, 4 | is_in_serving: true, 5 | description: "附近美食一网打尽", 6 | title: "美食", 7 | link: "eleme://restaurants?filter_key=%7B%22category_schema%22%3A%7B%22category_name%22%3A%22%5Cu7f8e%5Cu98df%22%2C%22complex_category_ids%22%3A%5B207%2C220%2C233%2C260%5D%2C%22is_show_all_category%22%3Afalse%7D%2C%22restaurant_category_id%22%3A%7B%22id%22%3A207%2C%22name%22%3A%22%5Cu5feb%5Cu9910%5Cu4fbf%5Cu5f53%22%2C%22sub_categories%22%3A%5B%5D%2C%22image_url%22%3A%22%22%7D%2C%22activities%22%3A%5B%5D%7D&target_name=%E7%BE%8E%E9%A3%9F&animation_type=1&is_need_mark=0&banner_type=", 8 | image_url: "/b/7e/d1890cf73ae6f2adb97caa39de7fcjpeg.jpeg", 9 | icon_url: "", 10 | title_color: "" 11 | }, 12 | { 13 | id: 20, 14 | is_in_serving: true, 15 | description: "苦了累了,来点甜的", 16 | title: "甜品饮品", 17 | link: "eleme://restaurants?filter_key=%7B%22category_schema%22%3A%7B%22category_name%22%3A%22%5Cu751c%5Cu54c1%5Cu996e%5Cu54c1%22%2C%22complex_category_ids%22%3A%5B240%2C241%2C242%5D%2C%22is_show_all_category%22%3Atrue%7D%2C%22restaurant_category_id%22%3A%7B%22id%22%3A239%2C%22name%22%3A%22%5Cu751c%5Cu54c1%5Cu996e%5Cu54c1%22%2C%22sub_categories%22%3A%5B%5D%2C%22image_url%22%3A%22%22%7D%2C%22activities%22%3A%5B%5D%7D&target_name=%E7%94%9C%E5%93%81%E9%A5%AE%E5%93%81&animation_type=1&is_need_mark=0&banner_type=", 18 | image_url: "/2/35/696aa5cf9820adada9b11a3d14bf5jpeg.jpeg", 19 | icon_url: "", 20 | title_color: "" 21 | }, 22 | { 23 | id: 10, 24 | is_in_serving: true, 25 | description: "足不出户,便利回家", 26 | title: "商超便利", 27 | link: "eleme://restaurants?filter_key=%7B%22category_schema%22%3A%7B%22category_name%22%3A%22%5Cu5546%5Cu8d85%5Cu4fbf%5Cu5229%22%2C%22complex_category_ids%22%3A%5B254%2C255%2C256%2C257%2C258%2C271%2C272%2C273%2C274%5D%2C%22is_show_all_category%22%3Atrue%7D%2C%22restaurant_category_id%22%3A%7B%22id%22%3A252%2C%22name%22%3A%22%5Cu5546%5Cu5e97%5Cu8d85%5Cu5e02%22%2C%22sub_categories%22%3A%5B%5D%2C%22image_url%22%3A%22%22%7D%2C%22activities%22%3A%5B%5D%7D&target_name=%E5%95%86%E8%B6%85%E4%BE%BF%E5%88%A9&animation_type=1&is_need_mark=0&banner_type=", 28 | image_url: "/0/da/f42235e6929a5cb0e7013115ce78djpeg.jpeg", 29 | icon_url: "", 30 | title_color: "" 31 | }, 32 | { 33 | id: 1, 34 | is_in_serving: true, 35 | description: "0元早餐0起送,每天都有新花样。", 36 | title: "预订早餐", 37 | link: "eleme://web?url=https%3A%2F%2Fzaocan.ele.me&target_name=%E9%A2%84%E8%AE%A2%E6%97%A9%E9%A4%90&animation_type=1&is_need_mark=&banner_type=", 38 | image_url: "/d/49/7757ff22e8ab28e7dfa5f7e2c2692jpeg.jpeg", 39 | icon_url: "", 40 | title_color: "" 41 | }, 42 | { 43 | id: 8, 44 | is_in_serving: true, 45 | description: "一天变女神", 46 | title: "果蔬生鲜", 47 | link: "eleme://restaurants?filter_key=%7B%22category_schema%22%3A%7B%22category_name%22%3A%22%5Cu679c%5Cu852c%5Cu751f%5Cu9c9c%22%2C%22complex_category_ids%22%3A%5B245%2C246%2C247%5D%2C%22is_show_all_category%22%3Atrue%7D%2C%22restaurant_category_id%22%3A%7B%22id%22%3A244%2C%22name%22%3A%22%5Cu679c%5Cu852c%5Cu751f%5Cu9c9c%22%2C%22sub_categories%22%3A%5B%5D%2C%22image_url%22%3A%22%22%7D%2C%22activities%22%3A%5B%5D%7D&target_name=%E6%9E%9C%E8%94%AC%E7%94%9F%E9%B2%9C&animation_type=1&is_need_mark=0&banner_type=", 48 | image_url: "/4/34/ea0d51c9608310cf41faa5de6b8efjpeg.jpeg", 49 | icon_url: "", 50 | title_color: "" 51 | }, 52 | { 53 | id: 403297, 54 | is_in_serving: true, 55 | description: "大胆尝鲜,遇见惊喜", 56 | title: "新店特惠", 57 | link: "eleme://restaurants?filter_key=%7B%22category_schema%22%3A%7B%22category_name%22%3A%22%5Cu65b0%5Cu5e97%5Cu7279%5Cu60e0%22%2C%22complex_category_ids%22%3A%5B207%2C220%2C233%2C239%2C244%2C248%2C252%2C260%5D%2C%22is_show_all_category%22%3Atrue%7D%2C%22restaurant_category_id%22%3A%7B%22id%22%3A207%2C%22name%22%3A%22%5Cu5feb%5Cu9910%5Cu4fbf%5Cu5f53%22%2C%22sub_categories%22%3A%5B%5D%2C%22image_url%22%3A%22%22%7D%2C%22support_ids%22%3A%5B-1%5D%2C%22activities%22%3A%5B%5D%7D&target_name=%E6%96%B0%E5%BA%97%E7%89%B9%E6%83%A0&animation_type=1&is_need_mark=0&banner_type=", 58 | image_url: "/a/fa/d41b04d520d445dc5de42dae9a384jpeg.jpeg", 59 | icon_url: "", 60 | title_color: "" 61 | }, 62 | { 63 | id: 92, 64 | is_in_serving: true, 65 | description: "准时必达,超时赔付", 66 | title: "准时达", 67 | link: "eleme://restaurants?filter_key=%7B%22support_ids%22%3A%5B9%5D%2C%22activities%22%3A%5B%7B%22id%22%3A9%2C%22name%22%3A%22%5Cu51c6%5Cu65f6%5Cu8fbe%22%2C%22icon_name%22%3A%22%5Cu51c6%22%2C%22icon_color%22%3A%22E8842D%22%2C%22is_need_filling%22%3A0%2C%22is_multi_choice%22%3A1%2C%22filter_value%22%3A9%2C%22filter_key%22%3A%22support_ids%22%2C%22description%22%3A%22%5Cu51c6%5Cu65f6%5Cu8fbe%22%7D%5D%7D&target_name=%E5%87%86%E6%97%B6%E8%BE%BE&animation_type=1&is_need_mark=0&banner_type=", 68 | image_url: "/3/84/8e031bf7b3c036b4ec19edff16e46jpeg.jpeg", 69 | icon_url: "", 70 | title_color: "" 71 | }, 72 | { 73 | id: 225, 74 | is_in_serving: true, 75 | description: "有菜有肉,营养均衡", 76 | title: "简餐", 77 | link: "eleme://restaurants?filter_key=%7B%22activity_types%22%3A%5B3%5D%2C%22category_schema%22%3A%7B%22category_name%22%3A%22%5Cu7b80%5Cu9910%22%2C%22complex_category_ids%22%3A%5B209%2C212%2C215%2C265%5D%2C%22is_show_all_category%22%3Atrue%7D%2C%22restaurant_category_id%22%3A%7B%22id%22%3A207%2C%22name%22%3A%22%5Cu5feb%5Cu9910%5Cu4fbf%5Cu5f53%22%2C%22sub_categories%22%3A%5B%5D%2C%22image_url%22%3A%22%22%7D%2C%22activities%22%3A%5B%7B%22id%22%3A3%2C%22name%22%3A%22%5Cu4e0b%5Cu5355%5Cu7acb%5Cu51cf%22%2C%22icon_name%22%3A%22%5Cu51cf%22%2C%22icon_color%22%3A%22f07373%22%2C%22is_need_filling%22%3A1%2C%22is_multi_choice%22%3A0%2C%22filter_value%22%3A3%2C%22filter_key%22%3A%22activity_types%22%7D%5D%7D&target_name=%E7%AE%80%E9%A4%90&animation_type=1&is_need_mark=0&banner_type=", 78 | image_url: "/d/38/7bddb07503aea4b711236348e2632jpeg.jpeg", 79 | icon_url: "", 80 | title_color: "" 81 | }, 82 | { 83 | id: 65, 84 | is_in_serving: true, 85 | description: "", 86 | title: "土豪推荐", 87 | link: "eleme://restaurants?filter_key=%7B%22activities%22%3A%5B%7B%22filter_key%22%3A%22tags%22%2C%22filter_value%22%3A0%7D%5D%7D&target_name=%E5%9C%9F%E8%B1%AA%E6%8E%A8%E8%8D%90&animation_type=1&is_need_mark=0&banner_type=", 88 | image_url: "/e/7e/02b72b5e63c127d5bfae57b8e4ab1jpeg.jpeg", 89 | icon_url: "", 90 | title_color: "" 91 | }, 92 | { 93 | id: 236, 94 | is_in_serving: true, 95 | description: "大口大口把你吃掉", 96 | title: "汉堡薯条", 97 | link: "eleme://restaurants?filter_key=%7B%22category_schema%22%3A%7B%22category_name%22%3A%22%5Cu6c49%5Cu5821%22%2C%22complex_category_ids%22%3A%5B212%5D%2C%22is_show_all_category%22%3Atrue%7D%2C%22restaurant_category_id%22%3A%7B%22id%22%3A207%2C%22name%22%3A%22%5Cu5feb%5Cu9910%5Cu4fbf%5Cu5f53%22%2C%22sub_categories%22%3A%5B%5D%2C%22image_url%22%3A%22%22%7D%2C%22activities%22%3A%5B%5D%7D&target_name=%E6%B1%89%E5%A0%A1%E8%96%AF%E6%9D%A1&animation_type=1&is_need_mark=0&banner_type=", 98 | image_url: "/b/7f/432619fb21a40b05cd25d11eca02djpeg.jpeg", 99 | icon_url: "", 100 | title_color: "" 101 | }, 102 | { 103 | id: 289, 104 | is_in_serving: true, 105 | description: "老字号,好味道", 106 | title: "包子粥店", 107 | link: "eleme://restaurants?filter_key=%7B%22category_schema%22%3A%7B%22category_name%22%3A%22%5Cu5305%5Cu5b50%5Cu7ca5%5Cu5e97%22%2C%22complex_category_ids%22%3A%5B215%5D%2C%22is_show_all_category%22%3Atrue%7D%2C%22restaurant_category_id%22%3A%7B%22id%22%3A207%2C%22name%22%3A%22%5Cu5feb%5Cu9910%5Cu4fbf%5Cu5f53%22%2C%22sub_categories%22%3A%5B%5D%2C%22image_url%22%3A%22%22%7D%2C%22activities%22%3A%5B%5D%7D&target_name=%E5%8C%85%E5%AD%90%E7%B2%A5%E5%BA%97&animation_type=1&is_need_mark=0&banner_type=", 108 | image_url: "/2/17/244241b514affc0f12f4168cf6628jpeg.jpeg", 109 | icon_url: "", 110 | title_color: "" 111 | }, 112 | { 113 | id: 9, 114 | is_in_serving: true, 115 | description: "内心小公举,一直被宠爱", 116 | title: "鲜花蛋糕", 117 | link: "eleme://restaurants?filter_key=%7B%22category_schema%22%3A%7B%22category_name%22%3A%22%5Cu9c9c%5Cu82b1%5Cu86cb%5Cu7cd5%22%2C%22complex_category_ids%22%3A%5B249%2C250%2C251%5D%2C%22is_show_all_category%22%3Atrue%7D%2C%22restaurant_category_id%22%3A%7B%22id%22%3A248%2C%22name%22%3A%22%5Cu9c9c%5Cu82b1%5Cu86cb%5Cu7cd5%22%2C%22sub_categories%22%3A%5B%5D%2C%22image_url%22%3A%22%22%7D%2C%22activities%22%3A%5B%5D%7D&target_name=%E9%B2%9C%E8%8A%B1%E8%9B%8B%E7%B3%95&animation_type=1&is_need_mark=0&banner_type=", 118 | image_url: "/8/83/171fd98b85dee3b3f4243b7459b48jpeg.jpeg", 119 | icon_url: "", 120 | title_color: "" 121 | }, 122 | { 123 | id: 286, 124 | is_in_serving: true, 125 | description: "", 126 | title: "麻辣烫", 127 | link: "eleme://restaurants?filter_key=%7B%22category_schema%22%3A%7B%22category_name%22%3A%22%5Cu9ebb%5Cu8fa3%5Cu70eb%22%2C%22complex_category_ids%22%3A%5B214%5D%2C%22is_show_all_category%22%3Atrue%7D%2C%22restaurant_category_id%22%3A%7B%22id%22%3A207%2C%22name%22%3A%22%5Cu5feb%5Cu9910%5Cu4fbf%5Cu5f53%22%2C%22sub_categories%22%3A%5B%5D%2C%22image_url%22%3A%22%22%7D%2C%22activities%22%3A%5B%5D%7D&target_name=%E9%BA%BB%E8%BE%A3%E7%83%AB&animation_type=1&is_need_mark=0&banner_type=", 128 | image_url: "/3/c7/a9ef469a12e7a596b559145b87f09jpeg.jpeg", 129 | icon_url: "", 130 | title_color: "" 131 | }, 132 | { 133 | id: 288, 134 | is_in_serving: true, 135 | description: "无辣不欢", 136 | title: "川湘菜", 137 | link: "eleme://restaurants?filter_key=%7B%22category_schema%22%3A%7B%22category_name%22%3A%22%5Cu5ddd%5Cu6e58%5Cu83dc%22%2C%22complex_category_ids%22%3A%5B221%5D%2C%22is_show_all_category%22%3Atrue%7D%2C%22restaurant_category_id%22%3A%7B%22id%22%3A220%2C%22name%22%3A%22%5Cu7279%5Cu8272%5Cu83dc%5Cu7cfb%22%2C%22sub_categories%22%3A%5B%5D%2C%22image_url%22%3A%22%22%7D%2C%22activities%22%3A%5B%5D%7D&target_name=%E5%B7%9D%E6%B9%98%E8%8F%9C&animation_type=1&is_need_mark=0&banner_type=", 138 | image_url: "/9/7c/9700836a33e05c2410bda8da59117jpeg.jpeg", 139 | icon_url: "", 140 | title_color: "" 141 | }, 142 | { 143 | id: 287, 144 | is_in_serving: true, 145 | description: "西餐始祖,欧洲的味道", 146 | title: "披萨意面", 147 | link: "eleme://restaurants?filter_key=%7B%22category_schema%22%3A%7B%22category_name%22%3A%22%5Cu62ab%5Cu8428%5Cu610f%5Cu9762%22%2C%22complex_category_ids%22%3A%5B211%5D%2C%22is_show_all_category%22%3Atrue%7D%2C%22restaurant_category_id%22%3A%7B%22id%22%3A260%2C%22name%22%3A%22%5Cu5f02%5Cu56fd%5Cu6599%5Cu7406%22%2C%22sub_categories%22%3A%5B%5D%2C%22image_url%22%3A%22%22%7D%2C%22activities%22%3A%5B%5D%7D&target_name=%E6%8A%AB%E8%90%A8%E6%84%8F%E9%9D%A2&animation_type=1&is_need_mark=0&banner_type=", 148 | image_url: "/7/b6/235761e50d391445f021922b71789jpeg.jpeg", 149 | icon_url: "", 150 | title_color: "" 151 | }, 152 | { 153 | id: 285, 154 | is_in_serving: true, 155 | description: "寿司定食,泡菜烤肉", 156 | title: "日韩料理", 157 | link: "eleme://restaurants?filter_key=%7B%22category_schema%22%3A%7B%22category_name%22%3A%22%5Cu65e5%5Cu97e9%5Cu6599%5Cu7406%22%2C%22complex_category_ids%22%3A%5B229%5D%2C%22is_show_all_category%22%3Atrue%7D%2C%22restaurant_category_id%22%3A%7B%22id%22%3A260%2C%22name%22%3A%22%5Cu5f02%5Cu56fd%5Cu6599%5Cu7406%22%2C%22sub_categories%22%3A%5B%5D%2C%22image_url%22%3A%22%22%7D%2C%22activities%22%3A%5B%5D%7D&target_name=%E6%97%A5%E9%9F%A9%E6%96%99%E7%90%86&animation_type=1&is_need_mark=0&banner_type=", 158 | image_url: "/6/1a/1e0f448be0624c62db416e864d2afjpeg.jpeg", 159 | icon_url: "", 160 | title_color: "" 161 | } 162 | ] -------------------------------------------------------------------------------- /public/elm/static/js/home.5bd8d38bf00f59523e9e.min.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([41,45],{5:function(t,e,i){"use strict";function a(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var o=i(10),n=a(o),r=i(4);e.default={data:function(){return{}},mounted:function(){this.getUserInfo()},props:["signinUp","headTitle","goBack"],computed:(0,n.default)({},(0,r.mapState)(["userInfo"])),methods:(0,n.default)({},(0,r.mapActions)(["getUserInfo"]))}},6:function(t,e,i){e=t.exports=i(2)(),e.push([t.id,"#head_top[data-v-cec0c0c0]{background-color:#3190e8;position:fixed;z-index:100;left:0;top:0;width:100%;height:1.95rem}.head_goback[data-v-cec0c0c0]{left:.4rem;width:.6rem;height:1rem;line-height:2.2rem;margin-left:.4rem}.head_login[data-v-cec0c0c0]{right:.55rem;font-size:.65rem;color:#fff;position:absolute;top:50%;transform:translateY(-50%)}.head_login .login_span[data-v-cec0c0c0]{color:#fff}.head_login .user_avatar[data-v-cec0c0c0]{fill:#fff;width:.8rem;height:.8rem}.title_head[data-v-cec0c0c0]{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:50%;color:#fff;text-align:center}.title_head .title_text[data-v-cec0c0c0]{font-size:.8rem;color:#fff;text-align:center;font-weight:700}","",{version:3,sources:["/./src/components/header/head.vue"],names:[],mappings:"AACA,2BAA2B,yBAAyB,eAAe,YAAY,OAAO,MAAM,WAAW,cAAc,CACpH,AACD,8BAA8B,WAAY,YAAY,YAAY,mBAAmB,iBAAiB,CACrG,AACD,6BAA6B,aAAc,iBAAiB,WAAW,kBAAkB,QAAQ,AAAkE,0BAA0B,CAC5L,AACD,yCAAyC,UAAU,CAClD,AACD,0CAA0C,UAAU,YAAY,YAAY,CAC3E,AACD,6BAA6B,kBAAkB,QAAQ,SAAS,AAA4E,+BAAgC,UAAU,WAAW,iBAAiB,CACjN,AACD,yCAAyC,gBAAgB,WAAW,kBAAkB,eAAgB,CACrG",file:"head.vue",sourcesContent:["\n#head_top[data-v-cec0c0c0]{background-color:#3190e8;position:fixed;z-index:100;left:0;top:0;width:100%;height:1.95rem\n}\n.head_goback[data-v-cec0c0c0]{left:0.4rem;width:.6rem;height:1rem;line-height:2.2rem;margin-left:.4rem\n}\n.head_login[data-v-cec0c0c0]{right:0.55rem;font-size:.65rem;color:#fff;position:absolute;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)\n}\n.head_login .login_span[data-v-cec0c0c0]{color:#fff\n}\n.head_login .user_avatar[data-v-cec0c0c0]{fill:#fff;width:.8rem;height:.8rem\n}\n.title_head[data-v-cec0c0c0]{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%, -50%);-ms-transform:translate(-50%, -50%);transform:translate(-50%, -50%);width:50%;color:#fff;text-align:center\n}\n.title_head .title_text[data-v-cec0c0c0]{font-size:.8rem;color:#fff;text-align:center;font-weight:bold\n}\n"],sourceRoot:"webpack://"}])},7:function(t,e,i){var a=i(6);"string"==typeof a&&(a=[[t.id,a,""]]);i(3)(a,{});a.locals&&(t.exports=a.locals)},8:function(t,e,i){i(7);var a=i(1)(i(5),i(9),"data-v-cec0c0c0",null);t.exports=a.exports},9:function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,i=t._self._c||e;return i("header",{attrs:{id:"head_top"}},[t._t("logo"),t._v(" "),t._t("search"),t._v(" "),t.goBack?i("section",{staticClass:"head_goback",on:{click:function(e){t.$router.go(-1)}}},[i("svg",{attrs:{width:"100%",height:"100%",xmlns:"http://www.w3.org/2000/svg",version:"1.1"}},[i("polyline",{staticStyle:{fill:"none",stroke:"rgb(255,255,255)","stroke-width":"2"},attrs:{points:"12,18 4,9 12,0"}})])]):t._e(),t._v(" "),t.signinUp?i("router-link",{staticClass:"head_login",attrs:{to:t.userInfo?"/profile":"/login"}},[t.userInfo?i("svg",{staticClass:"user_avatar"},[i("use",{attrs:{"xmlns:xlink":"http://www.w3.org/1999/xlink","xlink:href":"#user"}})]):i("span",{staticClass:"login_span"},[t._v("登录|注册")])]):t._e(),t._v(" "),t.headTitle?i("section",{staticClass:"title_head ellipsis"},[i("span",{staticClass:"title_text"},[t._v(t._s(t.headTitle))])]):t._e(),t._v(" "),t._t("edit"),t._v(" "),t._t("msite-title"),t._v(" "),t._t("changecity"),t._v(" "),t._t("changeLogin")],2)},staticRenderFns:[]}},145:function(t,e,i){"use strict";function a(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(e,"__esModule",{value:!0});var o=i(8),n=a(o),r=i(16);e.default={data:function(){return{guessCity:"",guessCityid:"",hotcity:[],groupcity:{}}},mounted:function(){var t=this;(0,r.cityGuess)().then(function(e){t.guessCity=e.name,t.guessCityid=e.id}),(0,r.hotcity)().then(function(e){t.hotcity=e}),(0,r.groupcity)().then(function(e){t.groupcity=e})},components:{headTop:n.default},computed:{sortgroupcity:function(){for(var t={},e=65;e<=90;e++)this.groupcity[String.fromCharCode(e)]&&(t[String.fromCharCode(e)]=this.groupcity[String.fromCharCode(e)]);return t}},methods:{reload:function(){window.location.reload()}}}},240:function(t,e,i){e=t.exports=i(2)(),e.push([t.id,".head_logo[data-v-3ea254f4]{left:.4rem;font-weight:400;font-size:.7rem;color:#fff;width:2.3rem;height:.7rem;position:absolute;top:50%;transform:translateY(-50%)}.city_nav[data-v-3ea254f4]{padding-top:2.35rem;border-top:1px solid #e4e4e4;background-color:#fff;margin-bottom:.4rem}.city_nav .city_tip[data-v-3ea254f4]{display:-ms-flexbox;display:flex;-ms-flex-pack:justify;justify-content:space-between;line-height:1.45rem;padding:0 .45rem}.city_nav .city_tip span[data-v-3ea254f4]:first-of-type{font-size:.55rem;color:#666}.city_nav .city_tip span[data-v-3ea254f4]:nth-of-type(2){font-weight:900;font-size:.475rem;color:#9f9f9f}.city_nav .guess_city[data-v-3ea254f4]{display:-ms-flexbox;display:flex;-ms-flex-pack:justify;justify-content:space-between;-ms-flex-align:center;align-items:center;height:1.8rem;padding:0 .45rem;border-top:1px solid #e4e4e4;border-bottom:2px solid #e4e4e4;font:.75rem/1.8rem Microsoft YaHei}.city_nav .guess_city span[data-v-3ea254f4]:first-of-type{color:#3190e8}.city_nav .guess_city .arrow_right[data-v-3ea254f4]{width:.6rem;height:.6rem;fill:#999}#hot_city_container[data-v-3ea254f4]{background-color:#fff;margin-bottom:.4rem}.citylistul li[data-v-3ea254f4]{float:left;text-align:center;color:#3190e8;border-bottom:.025rem solid #e4e4e4;border-right:.025rem solid #e4e4e4;width:25%;height:1.75rem;font:.6rem/1.75rem Microsoft YaHei}.citylistul li[data-v-3ea254f4]:nth-of-type(4n){border-right:none}.city_title[data-v-3ea254f4]{color:#666;font-weight:400;text-indent:.45rem;border-top:2px solid #e4e4e4;border-bottom:1px solid #e4e4e4;font:.55rem/1.45rem Helvetica Neue}.city_title span[data-v-3ea254f4]{font-size:.475rem;color:#999}.letter_classify_li[data-v-3ea254f4]{margin-bottom:.4rem;background-color:#fff;border-bottom:1px solid #e4e4e4}.letter_classify_li .groupcity_name_container li[data-v-3ea254f4]{color:#666}","",{version:3,sources:["/./src/page/home/home.vue"],names:[],mappings:"AACA,4BAA4B,WAAY,gBAAgB,gBAAgB,WAAW,aAAa,aAAa,kBAAkB,QAAQ,AAAkE,0BAA0B,CAClO,AACD,2BAA2B,oBAAoB,6BAA6B,sBAAsB,mBAAoB,CACrH,AACD,qCAA8E,oBAAoB,aAAa,AAA+D,sBAAsB,8BAA8B,oBAAoB,gBAAiB,CACtQ,AACD,wDAAyD,iBAAiB,UAAU,CACnF,AACD,yDAAyD,gBAAgB,kBAAkB,aAAa,CACvG,AACD,uCAAgF,oBAAoB,aAAa,AAA+D,sBAAsB,8BAA8B,AAAoD,sBAAsB,mBAAmB,cAAc,iBAAkB,6BAA6B,gCAAgC,kCAAqC,CAClc,AACD,0DAA2D,aAAa,CACvE,AACD,oDAAoD,YAAY,aAAa,SAAS,CACrF,AACD,qCAAqC,sBAAsB,mBAAoB,CAC9E,AACD,gCAAgC,WAAW,kBAAkB,cAAc,oCAAqC,mCAAoC,UAAU,eAAe,kCAAqC,CACjN,AACD,gDAAgD,iBAAiB,CAChE,AACD,6BAA6B,WAAW,gBAAgB,mBAAoB,6BAA6B,gCAAgC,kCAAqC,CAC7K,AACD,kCAAkC,kBAAkB,UAAU,CAC7D,AACD,qCAAqC,oBAAqB,sBAAsB,+BAA+B,CAC9G,AACD,kEAAkE,UAAU,CAC3E",file:"home.vue",sourcesContent:['\n.head_logo[data-v-3ea254f4]{left:0.4rem;font-weight:400;font-size:.7rem;color:#fff;width:2.3rem;height:.7rem;position:absolute;top:50%;-webkit-transform:translateY(-50%);-ms-transform:translateY(-50%);transform:translateY(-50%)\n}\n.city_nav[data-v-3ea254f4]{padding-top:2.35rem;border-top:1px solid #e4e4e4;background-color:#fff;margin-bottom:0.4rem\n}\n.city_nav .city_tip[data-v-3ea254f4]{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;line-height:1.45rem;padding:0 0.45rem\n}\n.city_nav .city_tip span[data-v-3ea254f4]:nth-of-type(1){font-size:.55rem;color:#666\n}\n.city_nav .city_tip span[data-v-3ea254f4]:nth-of-type(2){font-weight:900;font-size:.475rem;color:#9f9f9f\n}\n.city_nav .guess_city[data-v-3ea254f4]{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;height:1.8rem;padding:0 0.45rem;border-top:1px solid #e4e4e4;border-bottom:2px solid #e4e4e4;font:0.75rem/1.8rem "Microsoft YaHei"\n}\n.city_nav .guess_city span[data-v-3ea254f4]:nth-of-type(1){color:#3190e8\n}\n.city_nav .guess_city .arrow_right[data-v-3ea254f4]{width:.6rem;height:.6rem;fill:#999\n}\n#hot_city_container[data-v-3ea254f4]{background-color:#fff;margin-bottom:0.4rem\n}\n.citylistul li[data-v-3ea254f4]{float:left;text-align:center;color:#3190e8;border-bottom:0.025rem solid #e4e4e4;border-right:0.025rem solid #e4e4e4;width:25%;height:1.75rem;font:0.6rem/1.75rem "Microsoft YaHei"\n}\n.citylistul li[data-v-3ea254f4]:nth-of-type(4n){border-right:none\n}\n.city_title[data-v-3ea254f4]{color:#666;font-weight:400;text-indent:0.45rem;border-top:2px solid #e4e4e4;border-bottom:1px solid #e4e4e4;font:0.55rem/1.45rem "Helvetica Neue"\n}\n.city_title span[data-v-3ea254f4]{font-size:.475rem;color:#999\n}\n.letter_classify_li[data-v-3ea254f4]{margin-bottom:0.4rem;background-color:#fff;border-bottom:1px solid #e4e4e4\n}\n.letter_classify_li .groupcity_name_container li[data-v-3ea254f4]{color:#666\n}\n'],sourceRoot:"webpack://"}])},288:function(t,e,i){var a=i(240);"string"==typeof a&&(a=[[t.id,a,""]]);i(3)(a,{});a.locals&&(t.exports=a.locals)},367:function(t,e,i){i(288);var a=i(1)(i(145),i(411),"data-v-3ea254f4",null);t.exports=a.exports},411:function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,i=t._self._c||e;return i("div",[i("head-top",{attrs:{"signin-up":"home"}},[i("span",{staticClass:"head_logo",attrs:{slot:"logo"},on:{click:t.reload},slot:"logo"},[t._v("ele.me")])]),t._v(" "),i("nav",{staticClass:"city_nav"},[t._m(0),t._v(" "),i("router-link",{staticClass:"guess_city",attrs:{to:"/city/"+t.guessCityid}},[i("span",[t._v(t._s(t.guessCity))]),t._v(" "),i("svg",{staticClass:"arrow_right"},[i("use",{attrs:{"xmlns:xlink":"http://www.w3.org/1999/xlink","xlink:href":"#arrow-right"}})])])],1),t._v(" "),i("section",{attrs:{id:"hot_city_container"}},[i("h4",{staticClass:"city_title"},[t._v("热门城市")]),t._v(" "),i("ul",{staticClass:"citylistul clear"},t._l(t.hotcity,function(e){return i("router-link",{key:e.id,attrs:{tag:"li",to:"/city/"+e.id}},[t._v("\n "+t._s(e.name)+"\n ")])}))]),t._v(" "),i("section",{staticClass:"group_city_container"},[i("ul",{staticClass:"letter_classify"},t._l(t.sortgroupcity,function(e,a,o){return i("li",{key:a,staticClass:"letter_classify_li"},[i("h4",{staticClass:"city_title"},[t._v(t._s(a)+"\n "),0==o?i("span",[t._v("(按字母排序)")]):t._e()]),t._v(" "),i("ul",{staticClass:"groupcity_name_container citylistul clear"},t._l(e,function(e){return i("router-link",{key:e.id,staticClass:"ellipsis",attrs:{tag:"li",to:"/city/"+e.id}},[t._v("\n "+t._s(e.name)+"\n ")])}))])}))])],1)},staticRenderFns:[function(){var t=this,e=t.$createElement,i=t._self._c||e;return i("div",{staticClass:"city_tip"},[i("span",[t._v("当前定位城市:")]),t._v(" "),i("span",[t._v("定位不准时,请在城市列表中选择")])])}]}}}); --------------------------------------------------------------------------------