├── .babelrc
├── .editorconfig
├── .gitignore
├── .postcssrc.js
├── .vscode
└── settings.json
├── README.md
├── build
├── build.js
├── check-versions.js
├── dev-client.js
├── dev-server.js
├── utils.js
├── vue-loader.conf.js
├── webpack.base.conf.js
├── webpack.dev.conf.js
└── webpack.prod.conf.js
├── config
├── dev.env.js
├── index.js
└── prod.env.js
├── index.html
├── package-lock.json
├── package.json
├── project.config.json
├── src
├── App.vue
├── action
│ └── action.js
├── app.json
├── assets
│ ├── global.scss
│ └── iconfont.less
├── components
│ ├── card.vue
│ └── sep-line.vue
├── constants
│ ├── commonType.js
│ ├── errorCodeMap.js
│ ├── hostConfig.js
│ ├── pathConfig.js
│ └── responseCode.js
├── main.js
├── middlewares
│ └── index.js
├── network
│ ├── cache
│ │ └── cache.js
│ └── request
│ │ ├── HttpExtension.js
│ │ └── HttpRequest.js
├── pages
│ ├── addAddress
│ │ ├── index.vue
│ │ ├── main.js
│ │ └── main.json
│ ├── addressList
│ │ ├── data.js
│ │ ├── index.vue
│ │ ├── main.js
│ │ └── main.json
│ ├── categoryList
│ │ ├── data.js
│ │ ├── index.vue
│ │ ├── main.js
│ │ └── main.json
│ ├── citySearch
│ │ ├── index.vue
│ │ └── main.js
│ ├── citys
│ │ ├── index.vue
│ │ └── main.js
│ ├── commentList
│ │ ├── index.vue
│ │ ├── main.js
│ │ └── main.json
│ ├── couponList
│ │ ├── data.js
│ │ ├── index.vue
│ │ ├── main.js
│ │ └── main.json
│ ├── dicedActivity
│ │ ├── index.vue
│ │ ├── main.js
│ │ └── main.json
│ ├── expiredCoupon
│ │ ├── data.js
│ │ ├── index.vue
│ │ ├── main.js
│ │ └── main.json
│ ├── expiredRedPacket
│ │ ├── data.js
│ │ ├── index.vue
│ │ ├── main.js
│ │ └── main.json
│ ├── feedback
│ │ ├── index.vue
│ │ ├── main.js
│ │ └── main.json
│ ├── home
│ │ ├── data.js
│ │ ├── index.vue
│ │ ├── main.js
│ │ └── main.json
│ ├── index
│ │ ├── index.vue
│ │ └── main.js
│ ├── me
│ │ ├── index.vue
│ │ ├── main.js
│ │ └── main.json
│ ├── orderDetail
│ │ ├── index.vue
│ │ ├── main.js
│ │ └── main.json
│ ├── orderList
│ │ ├── data.js
│ │ ├── index.vue
│ │ ├── main.js
│ │ └── main.json
│ ├── pickProtocol
│ │ ├── index.vue
│ │ ├── main.js
│ │ └── main.json
│ ├── protocol
│ │ ├── index.vue
│ │ ├── main.js
│ │ └── main.json
│ ├── redPacket
│ │ ├── data.js
│ │ ├── index.vue
│ │ ├── main.js
│ │ └── main.json
│ ├── remark
│ │ ├── index.vue
│ │ ├── main.js
│ │ └── main.json
│ ├── searchList
│ │ ├── data.js
│ │ ├── index.vue
│ │ ├── main.js
│ │ └── main.json
│ ├── selectAddress
│ │ ├── data.js
│ │ ├── index.vue
│ │ ├── main.js
│ │ └── main.json
│ ├── share
│ │ ├── data.js
│ │ ├── index.vue
│ │ ├── main.js
│ │ └── main.json
│ ├── shoppingCart
│ │ ├── data.js
│ │ ├── index.vue
│ │ ├── main.js
│ │ └── main.json
│ └── submitOrder
│ │ ├── data.js
│ │ ├── index.vue
│ │ ├── main.js
│ │ └── main.json
├── store
│ ├── index.js
│ ├── modules
│ │ ├── shoppingCart.js
│ │ └── submitOrder.js
│ └── mutations-type.js
└── utils
│ ├── arrayExtension.js
│ ├── bus.js
│ ├── deepClone.js
│ ├── deviceInfo.js
│ ├── formatTime.js
│ ├── index.js
│ ├── mta_analysis.js
│ ├── regex.js
│ ├── stringExtension.js
│ ├── style.js
│ ├── toast.js
│ └── wxapi.js
└── static
├── .gitkeep
└── images
├── icon_tabbar_home@3x.png
├── icon_tabbar_home_selected@3x.png
├── icon_tabbar_mine@3x.png
├── icon_tabbar_mine_selected@3x.png
├── icon_tabbar_order@3x.png
└── icon_tabbar_order_selected@3x.png
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env", {
4 | "modules": false,
5 | "targets": {
6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
7 | }
8 | }],
9 | "stage-2"
10 | ],
11 | "plugins": ["transform-runtime"],
12 | "env": {
13 | "test": {
14 | "presets": ["env", "stage-2"],
15 | "plugins": ["istanbul"]
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | dist/
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Editor directories and files
9 | .idea
10 | *.suo
11 | *.ntvs*
12 | *.njsproj
13 | *.sln
--------------------------------------------------------------------------------
/.postcssrc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/michael-ciniawsky/postcss-load-config
2 |
3 | module.exports = {
4 | "plugins": {
5 | "postcss-mpvue-wxss": {}
6 | }
7 | }
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # mpvue-meituan
2 | > mpvue-meituan 是一款使用mpvue开发的实战小程序项目,完全仿制美团官方外卖点餐小程序开发而成,项目的框架结构完全按照企业开发架构搭建而成。结合了原生小程序的开发能力和Vue能力,使小程序开发起来更加便捷高效,项目使用了比较流行的Vuex框架来作为全局的状态数据管理,使数据交互更加的便捷,结合了sass的使用让写Css样式更加的得心应手。目前市面上有很多使用mpvue开发的示例Demo,但是那些示例Demo都过于简单,没有提供一套系统的框架结构,借鉴的意义不是很大。所以作者就开源了一个企业级框架开发的小程序供大家学习参考,总之是一个极力推荐学习的小程序实战项目。
3 |
4 | **掘金专栏文章详解:[mpvue-meituan](https://juejin.im/post/5bbb6198f265da0ac962ba00)**
5 |
6 | # 目录
7 | * [项目简介](#项目简介)
8 | * [主要功能](#主要功能)
9 | * [预览效果图](#预览效果图)
10 | * [安装调试](#安装调试)
11 | * [API数据来源](#API数据来源)
12 | * [技术要点](#技术要点)
13 | * [核心组件库](#核心组件库)
14 | * [开发中遇到的坑](#开发中遇到的坑)
15 | * [待完成功能](#待完成功能)
16 | * [待优化bug](#待优化bug)
17 | * [目录结构](#目录结构)
18 | * [总结](#总结)
19 |
20 | # 项目简介
21 | > mpvue-meituan 是一款使用mpvue开发的小程序,完全仿制美团官方外卖小程序。目前市面上大部分的小程序开发还是使用微信原生的开发能力,原生的开发能力约束太多,导致小程序开发成本变高。于是市面上衍生出不少小程序开发框架,其中最为流行的有下面三个框架:`wepy` `taro` `mpvue`。这三个框架出自不同的大厂,之前不太了解的小伙伴们可以自行查阅资料。本项目主要介绍如何使用vue来快速开发一款复杂的小程序项目。
22 |
23 | # 主要功能(20+页面)
24 | * 首页Tab
25 | * 首页商家列表
26 | * 选择收货地址列表
27 | * 选择城市
28 | * 商品搜索列表
29 | * 分类列表
30 | * 邀请好友领红包
31 | * 添加购物车页面
32 | * 食品档案
33 | * 订单Tab
34 | * 订单列表
35 | * 提交订单
36 | * 商品备注
37 | * 订单详情
38 | * 商品评论
39 | * 我的Tab
40 | * 我的页面
41 | * 美团红包页面
42 | * 无效红包页面
43 | * 代金券页面
44 | * 无效代金券列表
45 | * 收货地址列表
46 | * 新增收货地址
47 | * 帮助反馈
48 | * 协议说明
49 | * 待补充
50 |
51 | # 预览效果图
52 | 
53 |
54 | # 安装调试
55 |
56 | ```
57 | # install dependencies
58 | npm install
59 |
60 | # serve with hot reload at localhost:8080
61 | npm run dev
62 |
63 | # build for production with minification
64 | npm run build
65 |
66 | # build for production and view the bundle analyzer report
67 | npm run build --report
68 | ```
69 |
70 | # API数据来源
71 | > mpvue-meituan 项目的数据来源目前均来自美团外卖小程序抓包数据,将抓包数据存储为本地JSON,然后工程访问本地JSON数据。由于美团外卖小程序属于美团正式线上产品,故不能直接访问其真实API,使用本地JSON一样能实现绝大部分需求,少数需要数据交互的需求自己mock数据即可。
72 |
73 |
74 | # 技术要点
75 | * 微信原生小程序开发能力
76 | * mpvue开发小程序能力
77 | * Vue开发能力
78 | * less,sass 等css编译器用法
79 | * 小程序开发基础框架结构搭建
80 | * 小程序网络层封装
81 | * Vuex全局状态管理框架的使用
82 | * 小程序,vue组件化开发技巧
83 | * 小程序中iconFont使用技巧
84 | * 使用canvas绘制小程序分享海报技巧
85 | * 待补充
86 |
87 | # 核心组件库
88 | * mpvue
89 | * vuex
90 | * lodash
91 | * mpvue-wxparse
92 | * minapp-api-promise
93 | * 待补充
94 |
95 | # 开发中遇到的坑
96 | > 待补充
97 |
98 | # 待完成功能
99 | - [ ] 选择城市列表
100 | - [ ] 分类筛选功能
101 | - [ ] 购物车页面完善优化
102 | - [ ] 发表评论功能
103 | - [ ] 提交订单页面完善优化
104 | - [ ] canvas绘制分享海报
105 | - [x] 网络层工具封装
106 | - [x] vuex状态管理使用
107 | - [x] 常用工具类封装
108 | - [x] 组件化使用
109 | - [x] sass环境的搭建及使用
110 | - [ ] 待补充
111 |
112 | # 目录结构
113 |
114 | ```
115 | .
116 | ├── App.vue
117 | ├── action
118 | │ └── action.js
119 | ├── app.json
120 | ├── assets
121 | │ ├── global.scss
122 | │ └── iconfont.less
123 | ├── components
124 | │ ├── card.vue
125 | │ └── sep-line.vue
126 | ├── constants
127 | │ ├── commonType.js
128 | │ ├── errorCodeMap.js
129 | │ ├── hostConfig.js
130 | │ ├── pathConfig.js
131 | │ └── responseCode.js
132 | ├── main.js
133 | ├── middlewares
134 | │ └── index.js
135 | ├── network
136 | │ ├── cache
137 | │ │ └── cache.js
138 | │ └── request
139 | │ ├── HttpExtension.js
140 | │ └── HttpRequest.js
141 | ├── pages
142 | │ ├── addAddress
143 | │ │ ├── index.vue
144 | │ │ ├── main.js
145 | │ │ └── main.json
146 | │ ├── addressList
147 | │ │ ├── data.js
148 | │ │ ├── index.vue
149 | │ │ ├── main.js
150 | │ │ └── main.json
151 | │ ├── categoryList
152 | │ │ ├── data.js
153 | │ │ ├── index.vue
154 | │ │ ├── main.js
155 | │ │ └── main.json
156 | │ ├── citySearch
157 | │ │ ├── index.vue
158 | │ │ └── main.js
159 | │ ├── citys
160 | │ │ ├── index.vue
161 | │ │ └── main.js
162 | │ ├── commentList
163 | │ │ ├── index.vue
164 | │ │ ├── main.js
165 | │ │ └── main.json
166 | │ ├── couponList
167 | │ │ ├── data.js
168 | │ │ ├── index.vue
169 | │ │ ├── main.js
170 | │ │ └── main.json
171 | │ ├── dicedActivity
172 | │ │ ├── index.vue
173 | │ │ ├── main.js
174 | │ │ └── main.json
175 | │ ├── expiredCoupon
176 | │ │ ├── data.js
177 | │ │ ├── index.vue
178 | │ │ ├── main.js
179 | │ │ └── main.json
180 | │ ├── expiredRedPacket
181 | │ │ ├── data.js
182 | │ │ ├── index.vue
183 | │ │ ├── main.js
184 | │ │ └── main.json
185 | │ ├── feedback
186 | │ │ ├── index.vue
187 | │ │ ├── main.js
188 | │ │ └── main.json
189 | │ ├── home
190 | │ │ ├── data.js
191 | │ │ ├── index.vue
192 | │ │ ├── main.js
193 | │ │ └── main.json
194 | │ ├── index
195 | │ │ ├── index.vue
196 | │ │ └── main.js
197 | │ ├── me
198 | │ │ ├── index.vue
199 | │ │ ├── main.js
200 | │ │ └── main.json
201 | │ ├── orderDetail
202 | │ │ ├── index.vue
203 | │ │ ├── main.js
204 | │ │ └── main.json
205 | │ ├── orderList
206 | │ │ ├── data.js
207 | │ │ ├── index.vue
208 | │ │ └── main.js
209 | │ ├── pickProtocol
210 | │ │ ├── index.vue
211 | │ │ ├── main.js
212 | │ │ └── main.json
213 | │ ├── protocol
214 | │ │ ├── index.vue
215 | │ │ ├── main.js
216 | │ │ └── main.json
217 | │ ├── redPacket
218 | │ │ ├── data.js
219 | │ │ ├── index.vue
220 | │ │ ├── main.js
221 | │ │ └── main.json
222 | │ ├── remark
223 | │ │ ├── index.vue
224 | │ │ ├── main.js
225 | │ │ └── main.json
226 | │ ├── searchList
227 | │ │ ├── data.js
228 | │ │ ├── index.vue
229 | │ │ ├── main.js
230 | │ │ └── main.json
231 | │ ├── selectAddress
232 | │ │ ├── data.js
233 | │ │ ├── index.vue
234 | │ │ ├── main.js
235 | │ │ └── main.json
236 | │ ├── share
237 | │ │ ├── data.js
238 | │ │ ├── index.vue
239 | │ │ ├── main.js
240 | │ │ └── main.json
241 | │ ├── shoppingCart
242 | │ │ ├── data.js
243 | │ │ ├── index.vue
244 | │ │ ├── main.js
245 | │ │ └── main.json
246 | │ └── submitOrder
247 | │ ├── data.js
248 | │ ├── index.vue
249 | │ ├── main.js
250 | │ └── main.json
251 | ├── store
252 | │ ├── index.js
253 | │ ├── modules
254 | │ │ ├── shoppingCart.js
255 | │ │ └── submitOrder.js
256 | │ └── mutations-type.js
257 | └── utils
258 | ├── arrayExtension.js
259 | ├── bus.js
260 | ├── deepClone.js
261 | ├── deviceInfo.js
262 | ├── formatTime.js
263 | ├── index.js
264 | ├── mta_analysis.js
265 | ├── regex.js
266 | ├── stringExtension.js
267 | ├── style.js
268 | ├── toast.js
269 | └── wxapi.js
270 |
271 | 37 directories, 117 files
272 | ```
273 |
274 | # 总结
275 | > mpvue-meituan 项目是作者大约使用了2周时间开源的一款小程序项目,项目中基本涵盖了企业开发中常用的技术要点,非常适合想学习小程序开发的小伙伴们参考学习。相信此项目能给小伙伴们带来不一样的收获。大家也可以加作者的mpvue小程序交流群交流学习(`QQ群号:694979037`)。
276 | >
277 | > 当然,如果老铁们认为作者的开源项目还不错,也请点个 **`star`** 支持一下 ❤️❤️❤️❤️ ,也衷心的欢迎小伙伴们提些宝贵的意见和建议。
278 |
--------------------------------------------------------------------------------
/build/build.js:
--------------------------------------------------------------------------------
1 | require('./check-versions')()
2 |
3 | process.env.NODE_ENV = 'production'
4 |
5 | var ora = require('ora')
6 | var rm = require('rimraf')
7 | var path = require('path')
8 | var chalk = require('chalk')
9 | var webpack = require('webpack')
10 | var config = require('../config')
11 | var webpackConfig = require('./webpack.prod.conf')
12 |
13 | var spinner = ora('building for production...')
14 | spinner.start()
15 |
16 | rm(path.join(config.build.assetsRoot, '*'), err => {
17 | if (err) throw err
18 | webpack(webpackConfig, function (err, stats) {
19 | spinner.stop()
20 | if (err) throw err
21 | process.stdout.write(stats.toString({
22 | colors: true,
23 | modules: false,
24 | children: false,
25 | chunks: false,
26 | chunkModules: false
27 | }) + '\n\n')
28 |
29 | if (stats.hasErrors()) {
30 | console.log(chalk.red(' Build failed with errors.\n'))
31 | process.exit(1)
32 | }
33 |
34 | console.log(chalk.cyan(' Build complete.\n'))
35 | console.log(chalk.yellow(
36 | ' Tip: built files are meant to be served over an HTTP server.\n' +
37 | ' Opening index.html over file:// won\'t work.\n'
38 | ))
39 | })
40 | })
41 |
--------------------------------------------------------------------------------
/build/check-versions.js:
--------------------------------------------------------------------------------
1 | var chalk = require('chalk')
2 | var semver = require('semver')
3 | var packageConfig = require('../package.json')
4 | var shell = require('shelljs')
5 | function exec (cmd) {
6 | return require('child_process').execSync(cmd).toString().trim()
7 | }
8 |
9 | var versionRequirements = [
10 | {
11 | name: 'node',
12 | currentVersion: semver.clean(process.version),
13 | versionRequirement: packageConfig.engines.node
14 | }
15 | ]
16 |
17 | if (shell.which('npm')) {
18 | versionRequirements.push({
19 | name: 'npm',
20 | currentVersion: exec('npm --version'),
21 | versionRequirement: packageConfig.engines.npm
22 | })
23 | }
24 |
25 | module.exports = function () {
26 | var warnings = []
27 | for (var i = 0; i < versionRequirements.length; i++) {
28 | var mod = versionRequirements[i]
29 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
30 | warnings.push(mod.name + ': ' +
31 | chalk.red(mod.currentVersion) + ' should be ' +
32 | chalk.green(mod.versionRequirement)
33 | )
34 | }
35 | }
36 |
37 | if (warnings.length) {
38 | console.log('')
39 | console.log(chalk.yellow('To use this template, you must update following to modules:'))
40 | console.log()
41 | for (var i = 0; i < warnings.length; i++) {
42 | var warning = warnings[i]
43 | console.log(' ' + warning)
44 | }
45 | console.log()
46 | process.exit(1)
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/build/dev-client.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | require('eventsource-polyfill')
3 | var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
4 |
5 | hotClient.subscribe(function (event) {
6 | if (event.action === 'reload') {
7 | window.location.reload()
8 | }
9 | })
10 |
--------------------------------------------------------------------------------
/build/dev-server.js:
--------------------------------------------------------------------------------
1 | require('./check-versions')()
2 |
3 | var config = require('../config')
4 | if (!process.env.NODE_ENV) {
5 | process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
6 | }
7 |
8 | // var opn = require('opn')
9 | var path = require('path')
10 | var express = require('express')
11 | var webpack = require('webpack')
12 | var proxyMiddleware = require('http-proxy-middleware')
13 | var portfinder = require('portfinder')
14 | var webpackConfig = require('./webpack.dev.conf')
15 |
16 | // default port where dev server listens for incoming traffic
17 | var port = process.env.PORT || config.dev.port
18 | // automatically open browser, if not set will be false
19 | var autoOpenBrowser = !!config.dev.autoOpenBrowser
20 | // Define HTTP proxies to your custom API backend
21 | // https://github.com/chimurai/http-proxy-middleware
22 | var proxyTable = config.dev.proxyTable
23 |
24 | var app = express()
25 | var compiler = webpack(webpackConfig)
26 |
27 | // var devMiddleware = require('webpack-dev-middleware')(compiler, {
28 | // publicPath: webpackConfig.output.publicPath,
29 | // quiet: true
30 | // })
31 |
32 | // var hotMiddleware = require('webpack-hot-middleware')(compiler, {
33 | // log: false,
34 | // heartbeat: 2000
35 | // })
36 | // force page reload when html-webpack-plugin template changes
37 | // compiler.plugin('compilation', function (compilation) {
38 | // compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
39 | // hotMiddleware.publish({ action: 'reload' })
40 | // cb()
41 | // })
42 | // })
43 |
44 | // proxy api requests
45 | Object.keys(proxyTable).forEach(function (context) {
46 | var options = proxyTable[context]
47 | if (typeof options === 'string') {
48 | options = { target: options }
49 | }
50 | app.use(proxyMiddleware(options.filter || context, options))
51 | })
52 |
53 | // handle fallback for HTML5 history API
54 | app.use(require('connect-history-api-fallback')())
55 |
56 | // serve webpack bundle output
57 | // app.use(devMiddleware)
58 |
59 | // enable hot-reload and state-preserving
60 | // compilation error display
61 | // app.use(hotMiddleware)
62 |
63 | // serve pure static assets
64 | var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
65 | app.use(staticPath, express.static('./static'))
66 |
67 | // var uri = 'http://localhost:' + port
68 |
69 | var _resolve
70 | var readyPromise = new Promise(resolve => {
71 | _resolve = resolve
72 | })
73 |
74 | // console.log('> Starting dev server...')
75 | // devMiddleware.waitUntilValid(() => {
76 | // console.log('> Listening at ' + uri + '\n')
77 | // // when env is testing, don't need open it
78 | // if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
79 | // opn(uri)
80 | // }
81 | // _resolve()
82 | // })
83 |
84 | module.exports = new Promise((resolve, reject) => {
85 | portfinder.basePort = port
86 | portfinder.getPortPromise()
87 | .then(newPort => {
88 | if (port !== newPort) {
89 | console.log(`${port}端口被占用,开启新端口${newPort}`)
90 | }
91 | var server = app.listen(newPort, 'localhost')
92 | // for 小程序的文件保存机制
93 | require('webpack-dev-middleware-hard-disk')(compiler, {
94 | publicPath: webpackConfig.output.publicPath,
95 | quiet: true
96 | })
97 | resolve({
98 | ready: readyPromise,
99 | close: () => {
100 | server.close()
101 | }
102 | })
103 | }).catch(error => {
104 | console.log('没有找到空闲端口,请打开任务管理器杀死进程端口再试', error)
105 | })
106 | })
107 |
--------------------------------------------------------------------------------
/build/utils.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var config = require('../config')
3 | var ExtractTextPlugin = require('extract-text-webpack-plugin')
4 |
5 | exports.assetsPath = function (_path) {
6 | var assetsSubDirectory = process.env.NODE_ENV === 'production'
7 | ? config.build.assetsSubDirectory
8 | : config.dev.assetsSubDirectory
9 | return path.posix.join(assetsSubDirectory, _path)
10 | }
11 |
12 | exports.cssLoaders = function (options) {
13 | options = options || {}
14 |
15 | var cssLoader = {
16 | loader: 'css-loader',
17 | options: {
18 | minimize: process.env.NODE_ENV === 'production',
19 | sourceMap: options.sourceMap
20 | }
21 | }
22 |
23 | var postcssLoader = {
24 | loader: 'postcss-loader',
25 | options: {
26 | sourceMap: true
27 | }
28 | }
29 |
30 | var px2rpxLoader = {
31 | loader: 'px2rpx-loader',
32 | options: {
33 | baseDpr: 1,
34 | rpxUnit: 0.5
35 | }
36 | }
37 |
38 | // generate loader string to be used with extract text plugin
39 | function generateLoaders (loader, loaderOptions) {
40 | var loaders = [cssLoader, px2rpxLoader, postcssLoader]
41 | if (loader) {
42 | loaders.push({
43 | loader: loader + '-loader',
44 | options: Object.assign({}, loaderOptions, {
45 | sourceMap: options.sourceMap
46 | })
47 | })
48 | }
49 |
50 | // Extract CSS when that option is specified
51 | // (which is the case during production build)
52 | if (options.extract) {
53 | return ExtractTextPlugin.extract({
54 | use: loaders,
55 | fallback: 'vue-style-loader'
56 | })
57 | } else {
58 | return ['vue-style-loader'].concat(loaders)
59 | }
60 | }
61 |
62 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html
63 | return {
64 | css: generateLoaders(),
65 | wxss: generateLoaders(),
66 | postcss: generateLoaders(),
67 | less: generateLoaders('less'),
68 | sass: generateLoaders('sass', { indentedSyntax: true }),
69 | scss: generateLoaders('sass').concat(
70 | {
71 | loader: 'sass-resources-loader',
72 | options: {
73 | resources: path.resolve(__dirname, '../src/assets/global.scss')
74 | }
75 | }
76 | ),
77 | stylus: generateLoaders('stylus'),
78 | styl: generateLoaders('stylus')
79 | }
80 | }
81 |
82 | // Generate loaders for standalone style files (outside of .vue)
83 | exports.styleLoaders = function (options) {
84 | var output = []
85 | var loaders = exports.cssLoaders(options)
86 | for (var extension in loaders) {
87 | var loader = loaders[extension]
88 | output.push({
89 | test: new RegExp('\\.' + extension + '$'),
90 | use: loader
91 | })
92 | }
93 | return output
94 | }
95 |
--------------------------------------------------------------------------------
/build/vue-loader.conf.js:
--------------------------------------------------------------------------------
1 | var utils = require('./utils')
2 | var config = require('../config')
3 | // var isProduction = process.env.NODE_ENV === 'production'
4 | // for mp
5 | var isProduction = true
6 |
7 | module.exports = {
8 | loaders: utils.cssLoaders({
9 | sourceMap: isProduction
10 | ? config.build.productionSourceMap
11 | : config.dev.cssSourceMap,
12 | extract: isProduction
13 | }),
14 | transformToRequire: {
15 | video: 'src',
16 | source: 'src',
17 | img: 'src',
18 | image: 'xlink:href'
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/build/webpack.base.conf.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var fs = require('fs')
3 | var utils = require('./utils')
4 | var config = require('../config')
5 | var vueLoaderConfig = require('./vue-loader.conf')
6 | var MpvuePlugin = require('webpack-mpvue-asset-plugin')
7 | var glob = require('glob')
8 | var CopyWebpackPlugin = require('copy-webpack-plugin')
9 | var relative = require('relative')
10 |
11 | function resolve (dir) {
12 | return path.join(__dirname, '..', dir)
13 | }
14 |
15 | function getEntry (rootSrc) {
16 | var map = {};
17 | glob.sync(rootSrc + '/pages/**/main.js')
18 | .forEach(file => {
19 | var key = relative(rootSrc, file).replace('.js', '');
20 | map[key] = file;
21 | })
22 | return map;
23 | }
24 |
25 | const appEntry = { app: resolve('./src/main.js') }
26 | const pagesEntry = getEntry(resolve('./src'), 'pages/**/main.js')
27 | const entry = Object.assign({}, appEntry, pagesEntry)
28 |
29 | module.exports = {
30 | // 如果要自定义生成的 dist 目录里面的文件路径,
31 | // 可以将 entry 写成 {'toPath': 'fromPath'} 的形式,
32 | // toPath 为相对于 dist 的路径, 例:index/demo,则生成的文件地址为 dist/index/demo.js
33 | entry,
34 | target: require('mpvue-webpack-target'),
35 | output: {
36 | path: config.build.assetsRoot,
37 | filename: '[name].js',
38 | publicPath: process.env.NODE_ENV === 'production'
39 | ? config.build.assetsPublicPath
40 | : config.dev.assetsPublicPath
41 | },
42 | resolve: {
43 | extensions: ['.js', '.vue', '.json'],
44 | alias: {
45 | 'vue': 'mpvue',
46 | '@': resolve('src')
47 | },
48 | symlinks: false,
49 | aliasFields: ['mpvue', 'weapp', 'browser'],
50 | mainFields: ['browser', 'module', 'main']
51 | },
52 | module: {
53 | rules: [
54 | {
55 | test: /\.vue$/,
56 | loader: 'mpvue-loader',
57 | options: vueLoaderConfig
58 | },
59 | {
60 | test: /\.js$/,
61 | include: [resolve('src'), resolve('test')],
62 | use: [
63 | 'babel-loader',
64 | {
65 | loader: 'mpvue-loader',
66 | options: {
67 | checkMPEntry: true
68 | }
69 | },
70 | ]
71 | },
72 | {
73 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
74 | loader: 'url-loader',
75 | options: {
76 | limit: 10000,
77 | name: utils.assetsPath('img/[name].[ext]')
78 | }
79 | },
80 | {
81 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
82 | loader: 'url-loader',
83 | options: {
84 | limit: 10000,
85 | name: utils.assetsPath('media/[name].[ext]')
86 | }
87 | },
88 | {
89 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
90 | loader: 'url-loader',
91 | options: {
92 | limit: 10000,
93 | name: utils.assetsPath('fonts/[name].[ext]')
94 | }
95 | }
96 | ]
97 | },
98 | plugins: [
99 | new MpvuePlugin(),
100 | new CopyWebpackPlugin([{
101 | from: '**/*.json',
102 | to: ''
103 | }], {
104 | context: 'src/'
105 | }),
106 | new CopyWebpackPlugin([
107 | {
108 | from: path.resolve(__dirname, '../static'),
109 | to: path.resolve(__dirname, '../dist/static'),
110 | ignore: ['.*']
111 | }
112 | ])
113 | ]
114 | }
115 |
--------------------------------------------------------------------------------
/build/webpack.dev.conf.js:
--------------------------------------------------------------------------------
1 | var utils = require('./utils')
2 | var webpack = require('webpack')
3 | var config = require('../config')
4 | var merge = require('webpack-merge')
5 | var baseWebpackConfig = require('./webpack.base.conf')
6 | // var HtmlWebpackPlugin = require('html-webpack-plugin')
7 | var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
8 |
9 | // copy from ./webpack.prod.conf.js
10 | var path = require('path')
11 | var ExtractTextPlugin = require('extract-text-webpack-plugin')
12 | var CopyWebpackPlugin = require('copy-webpack-plugin')
13 | var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
14 |
15 | // add hot-reload related code to entry chunks
16 | // Object.keys(baseWebpackConfig.entry).forEach(function (name) {
17 | // baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
18 | // })
19 |
20 | module.exports = merge(baseWebpackConfig, {
21 | module: {
22 | rules: utils.styleLoaders({
23 | sourceMap: config.dev.cssSourceMap,
24 | extract: true
25 | })
26 | },
27 | // cheap-module-eval-source-map is faster for development
28 | // devtool: '#cheap-module-eval-source-map',
29 | devtool: '#source-map',
30 | output: {
31 | path: config.build.assetsRoot,
32 | // filename: utils.assetsPath('[name].[chunkhash].js'),
33 | // chunkFilename: utils.assetsPath('[id].[chunkhash].js')
34 | filename: utils.assetsPath('[name].js'),
35 | chunkFilename: utils.assetsPath('[id].js')
36 | },
37 | plugins: [
38 | new webpack.DefinePlugin({
39 | 'process.env': config.dev.env
40 | }),
41 |
42 | // copy from ./webpack.prod.conf.js
43 | // extract css into its own file
44 | new ExtractTextPlugin({
45 | // filename: utils.assetsPath('[name].[contenthash].css')
46 | filename: utils.assetsPath('[name].wxss')
47 | }),
48 | // Compress extracted CSS. We are using this plugin so that possible
49 | // duplicated CSS from different components can be deduped.
50 | new OptimizeCSSPlugin({
51 | cssProcessorOptions: {
52 | safe: true
53 | }
54 | }),
55 | new webpack.optimize.CommonsChunkPlugin({
56 | name: 'common/vendor',
57 | minChunks: function (module, count) {
58 | // any required modules inside node_modules are extracted to vendor
59 | return (
60 | module.resource &&
61 | /\.js$/.test(module.resource) &&
62 | module.resource.indexOf('node_modules') >= 0
63 | ) || count > 1
64 | }
65 | }),
66 | new webpack.optimize.CommonsChunkPlugin({
67 | name: 'common/manifest',
68 | chunks: ['common/vendor']
69 | }),
70 |
71 | // https://github.com/glenjamin/webpack-hot-middleware#installation--usage
72 | // new webpack.HotModuleReplacementPlugin(),
73 | new webpack.NoEmitOnErrorsPlugin(),
74 | // https://github.com/ampedandwired/html-webpack-plugin
75 | // new HtmlWebpackPlugin({
76 | // filename: 'index.html',
77 | // template: 'index.html',
78 | // inject: true
79 | // }),
80 | new FriendlyErrorsPlugin()
81 | ]
82 | })
83 |
--------------------------------------------------------------------------------
/build/webpack.prod.conf.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var utils = require('./utils')
3 | var webpack = require('webpack')
4 | var config = require('../config')
5 | var merge = require('webpack-merge')
6 | var baseWebpackConfig = require('./webpack.base.conf')
7 | var UglifyJsPlugin = require('uglifyjs-webpack-plugin')
8 | var CopyWebpackPlugin = require('copy-webpack-plugin')
9 | // var HtmlWebpackPlugin = require('html-webpack-plugin')
10 | var ExtractTextPlugin = require('extract-text-webpack-plugin')
11 | var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
12 |
13 | var env = config.build.env
14 |
15 | var webpackConfig = merge(baseWebpackConfig, {
16 | module: {
17 | rules: utils.styleLoaders({
18 | sourceMap: config.build.productionSourceMap,
19 | extract: true
20 | })
21 | },
22 | devtool: config.build.productionSourceMap ? '#source-map' : false,
23 | output: {
24 | path: config.build.assetsRoot,
25 | // filename: utils.assetsPath('[name].[chunkhash].js'),
26 | // chunkFilename: utils.assetsPath('[id].[chunkhash].js')
27 | filename: utils.assetsPath('[name].js'),
28 | chunkFilename: utils.assetsPath('[id].js')
29 | },
30 | plugins: [
31 | // http://vuejs.github.io/vue-loader/en/workflow/production.html
32 | new webpack.DefinePlugin({
33 | 'process.env': env
34 | }),
35 | new UglifyJsPlugin({
36 | sourceMap: true
37 | }),
38 | // extract css into its own file
39 | new ExtractTextPlugin({
40 | // filename: utils.assetsPath('[name].[contenthash].css')
41 | filename: utils.assetsPath('[name].wxss')
42 | }),
43 | // Compress extracted CSS. We are using this plugin so that possible
44 | // duplicated CSS from different components can be deduped.
45 | new OptimizeCSSPlugin({
46 | cssProcessorOptions: {
47 | safe: true
48 | }
49 | }),
50 | // generate dist index.html with correct asset hash for caching.
51 | // you can customize output by editing /index.html
52 | // see https://github.com/ampedandwired/html-webpack-plugin
53 | // new HtmlWebpackPlugin({
54 | // filename: config.build.index,
55 | // template: 'index.html',
56 | // inject: true,
57 | // minify: {
58 | // removeComments: true,
59 | // collapseWhitespace: true,
60 | // removeAttributeQuotes: true
61 | // // more options:
62 | // // https://github.com/kangax/html-minifier#options-quick-reference
63 | // },
64 | // // necessary to consistently work with multiple chunks via CommonsChunkPlugin
65 | // chunksSortMode: 'dependency'
66 | // }),
67 | // keep module.id stable when vender modules does not change
68 | new webpack.HashedModuleIdsPlugin(),
69 | // split vendor js into its own file
70 | new webpack.optimize.CommonsChunkPlugin({
71 | name: 'common/vendor',
72 | minChunks: function (module, count) {
73 | // any required modules inside node_modules are extracted to vendor
74 | return (
75 | module.resource &&
76 | /\.js$/.test(module.resource) &&
77 | module.resource.indexOf('node_modules') >= 0
78 | ) || count > 1
79 | }
80 | }),
81 | // extract webpack runtime and module manifest to its own file in order to
82 | // prevent vendor hash from being updated whenever app bundle is updated
83 | new webpack.optimize.CommonsChunkPlugin({
84 | name: 'common/manifest',
85 | chunks: ['common/vendor']
86 | })
87 | ]
88 | })
89 |
90 | // if (config.build.productionGzip) {
91 | // var CompressionWebpackPlugin = require('compression-webpack-plugin')
92 |
93 | // webpackConfig.plugins.push(
94 | // new CompressionWebpackPlugin({
95 | // asset: '[path].gz[query]',
96 | // algorithm: 'gzip',
97 | // test: new RegExp(
98 | // '\\.(' +
99 | // config.build.productionGzipExtensions.join('|') +
100 | // ')$'
101 | // ),
102 | // threshold: 10240,
103 | // minRatio: 0.8
104 | // })
105 | // )
106 | // }
107 |
108 | if (config.build.bundleAnalyzerReport) {
109 | var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
110 | webpackConfig.plugins.push(new BundleAnalyzerPlugin())
111 | }
112 |
113 | module.exports = webpackConfig
114 |
--------------------------------------------------------------------------------
/config/dev.env.js:
--------------------------------------------------------------------------------
1 | var merge = require('webpack-merge')
2 | var prodEnv = require('./prod.env')
3 |
4 | module.exports = merge(prodEnv, {
5 | NODE_ENV: '"development"'
6 | })
7 |
--------------------------------------------------------------------------------
/config/index.js:
--------------------------------------------------------------------------------
1 | // see http://vuejs-templates.github.io/webpack for documentation.
2 | var path = require('path')
3 |
4 | module.exports = {
5 | build: {
6 | env: require('./prod.env'),
7 | index: path.resolve(__dirname, '../dist/index.html'),
8 | assetsRoot: path.resolve(__dirname, '../dist'),
9 | assetsSubDirectory: '',
10 | assetsPublicPath: '/',
11 | productionSourceMap: false,
12 | // Gzip off by default as many popular static hosts such as
13 | // Surge or Netlify already gzip all static assets for you.
14 | // Before setting to `true`, make sure to:
15 | // npm install --save-dev compression-webpack-plugin
16 | productionGzip: false,
17 | productionGzipExtensions: ['js', 'css'],
18 | // Run the build command with an extra argument to
19 | // View the bundle analyzer report after build finishes:
20 | // `npm run build --report`
21 | // Set to `true` or `false` to always turn it on or off
22 | bundleAnalyzerReport: process.env.npm_config_report
23 | },
24 | dev: {
25 | env: require('./dev.env'),
26 | port: 8080,
27 | // 在小程序开发者工具中不需要自动打开浏览器
28 | autoOpenBrowser: false,
29 | assetsSubDirectory: '',
30 | assetsPublicPath: '/',
31 | proxyTable: {},
32 | // CSS Sourcemaps off by default because relative paths are "buggy"
33 | // with this option, according to the CSS-Loader README
34 | // (https://github.com/webpack/css-loader#sourcemaps)
35 | // In our experience, they generally work as expected,
36 | // just be aware of this issue when enabling this option.
37 | cssSourceMap: false
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/config/prod.env.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | NODE_ENV: '"production"'
3 | }
4 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | mpvue-meituan
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mpvue-meituan",
3 | "version": "1.0.0",
4 | "description": "mpvue 框架在美团外卖项目上实战",
5 | "author": "刘光强 <1126756952@qq.com>",
6 | "private": true,
7 | "scripts": {
8 | "dev": "node build/dev-server.js",
9 | "start": "node build/dev-server.js",
10 | "build": "node build/build.js"
11 | },
12 | "dependencies": {
13 | "lodash": "^4.17.10",
14 | "minapp-api-promise": "^1.0.2",
15 | "mpvue": "^1.0.11",
16 | "mpvue-wxparse": "^0.6.5",
17 | "vuex": "^3.0.1"
18 | },
19 | "devDependencies": {
20 | "babel-core": "^6.22.1",
21 | "babel-loader": "^7.1.1",
22 | "babel-plugin-transform-runtime": "^6.22.0",
23 | "babel-preset-env": "^1.3.2",
24 | "babel-preset-stage-2": "^6.22.0",
25 | "babel-register": "^6.22.0",
26 | "chalk": "^2.4.0",
27 | "connect-history-api-fallback": "^1.3.0",
28 | "copy-webpack-plugin": "^4.5.1",
29 | "css-loader": "^0.28.11",
30 | "cssnano": "^3.10.0",
31 | "eventsource-polyfill": "^0.9.6",
32 | "express": "^4.16.3",
33 | "extract-text-webpack-plugin": "^3.0.2",
34 | "file-loader": "^1.1.11",
35 | "friendly-errors-webpack-plugin": "^1.7.0",
36 | "glob": "^7.1.2",
37 | "html-webpack-plugin": "^3.2.0",
38 | "http-proxy-middleware": "^0.18.0",
39 | "mpvue-loader": "^1.1.2",
40 | "mpvue-template-compiler": "^1.0.11",
41 | "mpvue-webpack-target": "^1.0.0",
42 | "node-sass": "^4.9.3",
43 | "optimize-css-assets-webpack-plugin": "^3.2.0",
44 | "ora": "^2.0.0",
45 | "portfinder": "^1.0.13",
46 | "postcss-loader": "^2.1.4",
47 | "postcss-mpvue-wxss": "^1.0.0",
48 | "prettier": "~1.12.1",
49 | "px2rpx-loader": "^0.1.10",
50 | "relative": "^3.0.2",
51 | "rimraf": "^2.6.0",
52 | "sass-loader": "^7.1.0",
53 | "sass-resources-loader": "^1.3.3",
54 | "semver": "^5.3.0",
55 | "shelljs": "^0.8.1",
56 | "style-loader": "^0.23.0",
57 | "uglifyjs-webpack-plugin": "^1.2.5",
58 | "url-loader": "^1.0.1",
59 | "vue-style-loader": "^4.1.0",
60 | "webpack": "^3.11.0",
61 | "webpack-bundle-analyzer": "^2.2.1",
62 | "webpack-dev-middleware-hard-disk": "^1.12.0",
63 | "webpack-merge": "^4.1.0",
64 | "webpack-mpvue-asset-plugin": "^0.1.1"
65 | },
66 | "engines": {
67 | "node": ">= 4.0.0",
68 | "npm": ">= 3.0.0"
69 | },
70 | "browserslist": [
71 | "> 1%",
72 | "last 2 versions",
73 | "not ie <= 8"
74 | ]
75 | }
76 |
--------------------------------------------------------------------------------
/project.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "description": "项目配置文件。",
3 | "setting": {
4 | "urlCheck": false,
5 | "es6": false,
6 | "postcss": true,
7 | "minified": true,
8 | "newFeature": true
9 | },
10 | "miniprogramRoot": "dist/",
11 | "compileType": "miniprogram",
12 | "appid": "wx69720258b4555088",
13 | "projectname": "mpvue-meituan",
14 | "libVersion": "2.3.0",
15 | "condition": {
16 | "search": {
17 | "current": -1,
18 | "list": []
19 | },
20 | "conversation": {
21 | "current": -1,
22 | "list": []
23 | },
24 | "game": {
25 | "currentL": -1,
26 | "list": []
27 | },
28 | "miniprogram": {
29 | "current": -1,
30 | "list": []
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
75 |
76 |
--------------------------------------------------------------------------------
/src/action/action.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by guangqiang on 2017/10/3.
3 | */
4 |
5 | import {getFetch, postFetch, putFetch, getFetchFromCache, postFetchForValidator} from '@/network/request/HttpExtension'
6 | import {PATH} from '@/constants/pathConfig'
7 | import {ApiSource} from '@/constants/commonType'
8 |
9 | const movieList = params => getFetch(PATH.PICTURE_LIST, params, false)
10 | const movieShowTimeList = params => getFetch(PATH.MOVIE_SHOWTIME, params, false, ApiSource.TIMEMOVIE, () => {})
11 | const movieComeingNewList = params => getFetch(PATH.MOVIE_COMEING_NEW, params, ApiSource.TIMEMOVIE)
12 | const movieDetail = params => getFetch(PATH.MOVIE_DETAIL, params, ApiSource.TIMETICKET)
13 |
14 | const queryHomeHeadCategory = params => postFetch(`${PATH.HOME_HEAD_CATEGORY}?ui=${params.ui}®ion_id=${params.region_id}®ion_version=${params.region_version}`, params, false)
15 | const createActivity = params => postFetch(PATH.CREATE_ACTIVITY, params, true)
16 | const getActivityDetail = params => getFetch(`${PATH.GET_ACTIVITY_DETAIL}/${params.id}?longitude=${params.longitude}&latitude=${params.latitude}&append=${params.append}`, {}, false)
17 | const getActivityDetailGpsNull = params => getFetch(`${PATH.GET_ACTIVITY_DETAIL}/${params.id}?append=${params.append}`, {}, false)
18 | const bargainAction = params => postFetch(PATH.BARGAIN_EVENT, params, true)
19 | const bargainParticipatorList = params => getFetch(PATH.BARGAIN_PARTICIPATOR_LIST, params, false)
20 | const userLogin = params => postFetch(`${PATH.LOGIN}?trace=true`, params, false)
21 | const updateUserLogin = params => putFetch(PATH.UPDATE_USER_INFO, params, false)
22 | const refreshToken = params => postFetch(PATH.REFRESH_TOKEN, params, false)
23 | const queryActivityMaxLimit = params => getFetch(PATH.QUERY_ACTIVITY_MAXLIMIT, params, false)
24 | const conmuseRecordList = params => getFetch(PATH.CONSUME_RECORD_LIST, params, false)
25 | const getActivityList = params => getFetch(PATH.GETACTIVITY_LIST, params, false)
26 | const getConsumeDetailData = params => getFetch(`${PATH.PAYMENT_DETAIL}/${params.id}?append=${params.append}`, {}, false)
27 | const createOrderData = params => postFetch(PATH.CREATE_ORDER, params, false)
28 | const payOrderData = params => postFetch(`${PATH.PAY_ORDER}/${params.id}/pay`, params, false)
29 | const gotCouponFinish = params => postFetch(`${PATH.GOT_COUPON_FINISH}/${params.id}/metadata`, params, false)
30 | const getCouponCard = params => postFetch(PATH.GET_COUPON_CARD, params, false)
31 | const getCouponList = params => getFetch(PATH.GET_COUPON_LIST, params, false)
32 | const queryShopData = params => getFetch(`${PATH.QUERY_SHOP_DATA}/${params.id}?append=${params.append}`, {}, false)
33 | const getMyCouponList = params => getFetch(PATH.GET_MY_COUPON_LIST, params, false)
34 | const shareStatistic = params => postFetch(PATH.SHARE_STATISTIC, params, false)
35 | const cancelOrder = params => putFetch(`${PATH.CANCEL_ORDER}/${params.id}/cancel`, params, false)
36 | const miniAppLogin = params => postFetch(`${PATH.MINIAPP_LIGIN}?scene=bind`, params, false)
37 |
38 | const postFormId = () => {}
39 |
40 | export {
41 | movieList,
42 | movieDetail,
43 | getCityLocation,
44 | queryHomeHeadCategory
45 | }
--------------------------------------------------------------------------------
/src/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages": [
3 | "pages/home/main",
4 | "pages/shoppingCart/main",
5 | "pages/submitOrder/main",
6 | "pages/me/main",
7 | "pages/expiredRedPacket/main",
8 | "pages/expiredCoupon/main",
9 | "pages/redPacket/main",
10 | "pages/couponList/main",
11 | "pages/categoryList/main",
12 | "pages/selectAddress/main",
13 | "pages/searchList/main",
14 | "pages/addAddress/main",
15 | "pages/orderList/main",
16 | "pages/remark/main",
17 | "pages/citySearch/main",
18 | "pages/citys/main",
19 | "pages/index/main",
20 | "pages/addressList/main",
21 | "pages/protocol/main",
22 | "pages/feedback/main",
23 | "pages/pickProtocol/main",
24 | "pages/orderDetail/main"
25 | ],
26 | "window": {
27 | "backgroundTextStyle": "light",
28 | "navigationBarBackgroundColor": "#fff",
29 | "navigationBarTitleText": "WeChat",
30 | "navigationBarTextStyle": "black"
31 | },
32 | "tabBar": {
33 | "color": "#999",
34 | "selectedColor": "#000",
35 | "backgroundColor": "#fff",
36 | "borderStyle": "black",
37 | "list": [{
38 | "pagePath": "pages/home/main",
39 | "text": "首页",
40 | "iconPath": "static/images/icon_tabbar_home@3x.png",
41 | "selectedIconPath": "static/images/icon_tabbar_home_selected@3x.png"
42 | },
43 | {
44 | "pagePath": "pages/orderList/main",
45 | "text": "订单",
46 | "iconPath": "static/images/icon_tabbar_order@3x.png",
47 | "selectedIconPath": "static/images/icon_tabbar_order_selected@3x.png"
48 | },
49 | {
50 | "pagePath": "pages/me/main",
51 | "text": "我的",
52 | "iconPath": "static/images/icon_tabbar_mine@3x.png",
53 | "selectedIconPath": "static/images/icon_tabbar_mine_selected@3x.png"
54 | }
55 | ]
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/assets/global.scss:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-06-29 18:07:09 */
2 |
3 | // 美团外卖小程序主题色系
4 |
5 | /** 主题色 **/
6 | $theme-color: #F9D173;
7 |
8 | // 默认浅灰色背景颜色
9 | $page-bgcolor: #F4F4F4;
10 |
11 | // 黑色背景颜色
12 | $pageBlack-bgcolor: #2C2D30;
13 |
14 | // 默认黑色字体颜色
15 | $textBlack-color: #333;
16 |
17 | // 默认深灰色字体颜色
18 | $textDarkGray-color: #666;
19 |
20 | // 默认灰色字体颜色
21 | $textGray-color: #ccc;
22 |
23 | // 美团红
24 | $mtRed-color: #e74c3c;
25 |
26 | // 默认浅灰色
27 | $textLightGray-color: #ccc;
28 |
29 | // 默认分割线颜色
30 | $spLine-color: #e4e4e4;
31 |
32 | // 默认虚分割线颜色
33 | $dashedLine-color: #EAEAEA;
34 |
35 | // 默认placeholder颜色
36 | $placeholder-textcolor: #9B9B9B;
37 |
38 | // borderColor
39 | $border-color: #808080;
40 |
41 | // 导航title 颜色
42 | $nav-titlecolor: #262626;
43 |
44 | // 导航背景颜色
45 | $nav-bgcolor: #FEFEFE;
46 |
47 | /** width **/
48 | // 边框线宽度
49 | $border-width: 2rpx;
50 | // 分割线高度
51 | $line-width: 2rpx;
52 |
53 | /** height **/
54 | // 底部按钮高度
55 | $bottonBtn-height: 44;
56 | // 通用列表cell高度
57 | $cell-height: 44;
58 |
59 | /** font **/
60 | // 默认文字字体
61 | $text-font: 14;
62 | // 默认按钮文字字体
63 | $btn-font: 15;
64 | // 按钮小号文字字体
65 | $btnFont-small: 13;
66 | // 导航title字体
67 | $navTitle-font: 17;
68 | // tabBar文字字体
69 | $tabbarTitle-font: 12;
70 | // 占位符的默认字体大小
71 | $placeholder-font: 13;
72 |
73 | /** opacity **/
74 | // mask 透明度
75 | $modal-opacity: 0.3;
--------------------------------------------------------------------------------
/src/components/card.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
14 |
15 |
20 |
--------------------------------------------------------------------------------
/src/components/sep-line.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
47 |
48 |
--------------------------------------------------------------------------------
/src/constants/commonType.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by guangqiang on 2017/10/3.
3 | */
4 |
5 | const monthList = [
6 | 'Jan',
7 | 'Feb',
8 | 'Mar',
9 | 'Apr',
10 | 'May',
11 | 'Jun',
12 | 'Jul',
13 | 'Aug',
14 | 'Sep',
15 | 'Oct',
16 | 'Nov',
17 | 'Dec'
18 | ]
19 |
20 | const activityTabList = [
21 | {
22 | title: "全部",
23 | type: "all"
24 | },
25 | {
26 | title: "进行中",
27 | type: "doing"
28 | },
29 | {
30 | title: "已结束",
31 | type: "end"
32 | }
33 | ]
34 |
35 | const orderStatus = {
36 | '01': '待支付',
37 | '11': '已取消',
38 | '12': '超时取消',
39 | '20': '已部分支付',
40 | '21': '支付成功'
41 | }
42 |
43 | const bargainTip = [
44 | '扶我起来,我还能砍!',
45 | '唔给力吧!',
46 | '做好事,不用谢',
47 | '这一刀可还行伐',
48 | '感情深,砍得狠',
49 | '今天手感还不错',
50 | '看我慈悲刀法',
51 | '砍价应该体面~',
52 | '纸短情长啊不如砍价~',
53 | '给点力,砍到底'
54 | ]
55 |
56 | const bargainStatus = {
57 | DOING: 'DOING', // 正在砍
58 | SUCCESS: 'SUCCESS', // 砍价拼团成功
59 | FAIL: 'FAIL', // 拼团失败
60 | END: 'END', // 来迟了,
61 | OVER_LIMIT: 'OVER_LIMIT' // 本次活动领取超过上限
62 | }
63 |
64 | // 事件埋点统计类型
65 | const logEventType = {
66 | enterPage: 3001,
67 | exitPage: 3002,
68 | click: 3003,
69 | slide: 3004,
70 | gesture: 3005
71 | }
72 |
73 | // 同一工程多域名配置
74 | const ApiSource = {
75 | meituan: 'meituan',
76 | XIAMIMUSIC: 'XIAMIMUSIC',
77 | TIMEMOVIE: 'TIMEMOVIE'
78 | }
79 |
80 | export {
81 | monthList,
82 | logEventType,
83 | ApiSource,
84 | activityTabList,
85 | bargainTip,
86 | orderStatus,
87 | bargainStatus
88 | }
--------------------------------------------------------------------------------
/src/constants/errorCodeMap.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-07-19 20:41:50 */
2 |
3 | const errorCode = {
4 | '20220001': '活动已参与',
5 | '20210021': '您已创建了活动,不可重复创建哦',
6 | '20210000': '活动不存在',
7 | '20210010': '活动不处于开放状态',
8 | '20230015': '活动名额已用光,请再换个试试吧~',
9 | '20230016': '活动名额已用光,请再换个试试吧~',
10 | '20230017': '优惠券库存不足',
11 | '20210001': '活动已结束',
12 | '20210008': '活动已结束',
13 | '20210009': '活动暂未发布开放状态'
14 | }
15 |
16 | export {errorCode}
--------------------------------------------------------------------------------
/src/constants/hostConfig.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by guangqiang on 2017/10/1.
3 | */
4 |
5 | const host = {
6 | dev: {
7 | API_URL: 'https://meituan.cangdu.org',
8 | XIAMI_URL: 'https://api-m.mtime.cn',
9 | MSITE_URL: 'https://api.douban.com',
10 | VENILOG_URL: 'https://api.douban.com',
11 | appId: 'wx3d5c531f5e123456',
12 | envVersion: 'develop'
13 | },
14 | test: {
15 | API_URL: 'https://meituan.cangdu.org',
16 | XIAMI_URL: 'http://10.10.21.108:9990',
17 | MSITE_URL: 'https://api.douban.com',
18 | VENILOG_URL: 'https://api.douban.com',
19 | appId: 'wx3d5c531f5e123456',
20 | envVersion: 'develop'
21 | },
22 | qa: {
23 | API_URL: 'https://meituan.cangdu.org',
24 | XIAMI_URL: 'http://xiamirun.avosapps.com',
25 | MSITE_URL: 'https://api.douban.com',
26 | VENILOG_URL: 'https://api.douban.com'
27 | },
28 | pre: {
29 | API_URL: 'https://meituan.cangdu.org',
30 | XIAMI_URL: 'https://api-m.mtime.cn',
31 | MSITE_URL: 'https://api.douban.com',
32 | VENILOG_URL: 'https://api.douban.com',
33 | appId: 'wx3d5c531f5e123456',
34 | envVersion: 'develop'
35 | },
36 | prd: {
37 | API_URL: 'https://wx.waimai.meituan.com',
38 | XIAMI_URL: 'https://api-m.mtime.cn',
39 | MSITE_URL: 'https://api.douban.com',
40 | VENILOG_URL: 'https://api.douban.com',
41 | appId: 'wx3d5c531f5e123456',
42 | envVersion: 'trial'
43 | }
44 | }
45 |
46 | let ENV = 'prd'
47 | let currentHost = host[ENV]
48 |
49 | const SET_HOST = (env = 'dev') => {
50 | ENV = env
51 | currentHost = host[ENV]
52 | }
53 |
54 | const API_URL = currentHost.API_URL
55 | const XIAMI_URL = currentHost.XIAMI_URL
56 | const MSITE_URL = currentHost.MSITE_URL
57 | const VENILOG_URL = currentHost.VENILOG_URL
58 | export {ENV, API_URL, MSITE_URL, VENILOG_URL, XIAMI_URL, SET_HOST, currentHost}
--------------------------------------------------------------------------------
/src/constants/pathConfig.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-06-29 10:26:46 */
2 |
3 | const PATH = {
4 | HOME_HEAD_CATEGORY: '/weapp/v1/v8/home/head',
5 | PICTURE_DETAIL: '/hp/detail/',
6 | PICTURE_GRID_LIST: '/hp/bymonth/',
7 | MOVIE_LIST: '/movie/list/',
8 |
9 | CITY_LOCATION: '/v1/cities',
10 | CREATE_ACTIVITY: '/mc/v1/me/activities',
11 | GET_ACTIVITY_DETAIL: '/mc/v1/activities',
12 | BARGAIN_EVENT: '/mc/v1/me/participants',
13 | BARGAIN_PARTICIPATOR_LIST: '/mc/v1/participants',
14 | LOGIN: '/uc/v1/auth/login/wx-miniapp',
15 | UPDATE_USER_INFO: '/uc/v1/account/wx',
16 | REFRESH_TOKEN: '/uc/v1/auth/refresh-token',
17 | QUERY_ACTIVITY_MAXLIMIT: '/mc/v1/activities',
18 | CONSUME_RECORD_LIST: '/tc/v1/me/orders',
19 | GETACTIVITY_LIST: '/mc/v1/me/activities',
20 | PAYMENT_DETAIL: '/tc/v1/me/orders',
21 | CREATE_ORDER: '/tc/v1/me/orders',
22 | PAY_ORDER: '/tc/v1/me/orders',
23 | GOT_COUPON_FINISH: '/mc/v1/participants',
24 | GET_COUPON_CARD: '/mc/v1/coupons',
25 | GET_COUPON_LIST: '/mc/v1/coupons',
26 | QUERY_SHOP_DATA: '/sc/v1/shops',
27 | GET_MY_COUPON_LIST: '/mc/v1/me/coupons',
28 | SHARE_STATISTIC: '/cc/v1/me/footprints',
29 | CANCEL_ORDER: '/tc/v1/me/orders',
30 | POST_FORM_ID: '/xc/api/v1/miniapps',
31 | MINIAPP_LIGIN: '/uc/v1/auth/login/wx-miniapp'
32 | }
33 |
34 | export {PATH}
--------------------------------------------------------------------------------
/src/constants/responseCode.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by guangqiang on 2017/10/3.
3 | */
4 |
5 | const responseCode = {
6 | RESPONSE_SUCCESS: '200', // 请求成功,返回数据
7 | TOKEN_INVALID: '-117', // token 失效
8 | USER_LOGOUT: '-110', // 用户未登录
9 | PARTICIPANT_NOT_GRANT_JOIN: '20220010', // 用户没有权限参与
10 | ACTIVITY_CREATER_NOT_GRANT: '20210025', // 活动创建者没有权限
11 | }
12 |
13 | export default responseCode
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-08-30 14:28:14 */
2 |
3 | import Vue from 'vue'
4 | import App from './App'
5 | import store from './store'
6 | import * as util from './utils'
7 |
8 | Vue.config.productionTip = false
9 | App.mpType = 'app'
10 | Vue.prototype.util = util
11 |
12 | const app = new Vue({
13 | store,
14 | ...App
15 | })
16 |
17 | app.$mount()
--------------------------------------------------------------------------------
/src/middlewares/index.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Umbrella001/mpvue-meituan/ea9c57fce44c762edaa10114316ac91b20f27773/src/middlewares/index.js
--------------------------------------------------------------------------------
/src/network/cache/cache.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by guangqiang on 2017/10/3.
3 | */
4 |
5 | import {getStorage, setStorage} from '@/utils/wxapi'
6 |
7 | /**
8 | * @param key:key为请求 url
9 | * @param fetchFunc:回调函数
10 | * @param isCache:是否需要缓存
11 | * @returns {value}
12 | */
13 | const dataCache = (key, fetchFunc, isCache) => {
14 | // 不缓存,
15 | if (!isCache) {
16 | return fetchFunc()
17 | }
18 | // 需要缓存
19 | return getStorage(key).then(value => {
20 | if (value) {
21 | // 如果在缓存中找到数据,则返回缓存中的数据
22 | return value
23 | } else {
24 | // 如果在缓存中取不到数据,则从网络请求中获取数据,并将获取到的数据缓存下来
25 | return fetchFunc().then(value => {
26 | value ? setStorage(key, value) : null
27 | return value
28 | })
29 | }
30 | })
31 | }
32 |
33 | export {dataCache}
--------------------------------------------------------------------------------
/src/network/request/HttpExtension.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by guangqiang on 2017/10/3.
3 | */
4 |
5 | /** 网络请求工具类的拓展类,便于后期网络层修改维护 **/
6 |
7 | import HttpUtils from './HttpRequest'
8 | import {API_URL, XIAMIMUSIC, XIAMI_URL} from '@/constants/hostConfig'
9 | import {ApiSource} from '@/constants/commonType'
10 | import {dataCache} from '../cache/cache'
11 |
12 | /**
13 | * GET \ POST
14 | * 从缓存中读取数据
15 | * @param isCache 是否缓存
16 | * @param requestType 网络请求类型
17 | * @param url 请求url
18 | * @param params 请求参数
19 | * @param isLoading 是否显示Loading
20 | * @param source API资源
21 | * @param callback 是否有回调函数
22 | * @returns {value \ promise} 返回的值如果从缓存中取到数据就直接换行数据,或则返回promise对象
23 | */
24 | const fetchData = (isCache, requestType) => (url, params, isLoading, source, callback) => {
25 | switch (source) {
26 | case ApiSource.XIAMIMUSIC:
27 | url = `${XIAMI_URL}${url}`
28 | break
29 | case ApiSource.TIMEMOVIE:
30 | url = `${TIME_MOVIE_URL}${url}`
31 | break
32 | default:
33 | url = `${API_URL}${url}`
34 | break
35 | }
36 | const fetchFunc = () => {
37 | let promise = HttpUtils.fetch(url, params, requestType, isLoading)
38 | if (callback && typeof callback === 'function') {
39 | promise.then(response => {
40 | return callback(response)
41 | })
42 | }
43 | return promise
44 | }
45 | return dataCache(url, fetchFunc, isCache)
46 | }
47 |
48 | /**
49 | * GET 请求
50 | * @param url
51 | * @param params
52 | * @param source
53 | * @param callback
54 | * @returns {{promise: Promise}}
55 | */
56 | const getFetch = fetchData(false, 'GET')
57 |
58 | /**
59 | * POST 请求
60 | * @param url
61 | * @param params
62 | * @param callback
63 | * @returns {{promise: Promise}}
64 | */
65 | const postFetch = fetchData(false, 'POST')
66 |
67 | /**
68 | * PUT 请求
69 | * @param url
70 | * @param params
71 | * @param callback
72 | * @returns {{promise: Promise}}
73 | */
74 | const putFetch = fetchData(false, 'PUT')
75 |
76 | /**
77 | * DELETE 请求
78 | * @param url
79 | * @param params
80 | * @param callback
81 | * @returns {{promise: Promise}}
82 | */
83 | const deleteFetch = fetchData(false, 'DELETE')
84 |
85 | /**
86 | * GET 请求,带缓存策略
87 | * @param url
88 | * @param params
89 | * @param callback
90 | * @returns {{promise: Promise}}
91 | */
92 | const getFetchFromCache = fetchData(true, 'GET')
93 |
94 | /**
95 | * POST请求参数校验,通过middleware 来实现自动校验表单参数是否合法
96 | * @param url
97 | * @param params
98 | */
99 | const postFetchForValidator = (url, params) => {
100 | let promise
101 | promise = () => {
102 | return fetchData(false, 'POST')(url, {})
103 | }
104 | return {
105 | data: params,
106 | params,
107 | nextPayload: {
108 | promise: promise
109 | }
110 | }
111 | }
112 |
113 | export {getFetch, postFetch, putFetch, deleteFetch, getFetchFromCache, postFetchForValidator}
--------------------------------------------------------------------------------
/src/network/request/HttpRequest.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by guangqiang on 2017/10/3.
3 | */
4 |
5 | /** 封装的基于Fetch网络请求工具类 **/
6 |
7 | import responseCode from '@/constants/responseCode'
8 | import {request, login} from '@/utils/wxapi'
9 | import {API_URL, XIAMIMUSIC} from '@/constants/hostConfig'
10 | import {PATH} from '@/constants/pathConfig'
11 | import {currentHost} from "@/constants/hostConfig"
12 | import {errorCode} from "@/constants/errorCodeMap"
13 | import {timestampToCommonDate} from "@/utils/formatTime"
14 | import {_array} from "@/utils/arrayExtension"
15 |
16 | /**
17 | * fetch 网络请求的header,可自定义header 内容
18 | * @type {{Accept: string, Content-Type: string, accessToken: *}}
19 | */
20 | const header = {
21 | 'Content-Type': 'application/json'
22 | }
23 |
24 | /**
25 | * GET请求时,拼接请求URL
26 | * @param url 请求URL
27 | * @param params 请求参数
28 | * @returns {*}
29 | */
30 | const handleUrl = url => params => {
31 | if (params) {
32 | let paramsArray = []
33 | Object.keys(params).forEach(key => paramsArray.push(key + '=' + encodeURIComponent(params[key])))
34 | if (url.search(/\?/) === -1) {
35 | typeof (params) === 'object' ? url += '?' + paramsArray.join('&') : url
36 | } else {
37 | url += '&' + paramsArray.join('&')
38 | }
39 | }
40 | return url
41 | }
42 |
43 | /**
44 | * fetch 网络请求超时处理
45 | * @param original_promise 原始的fetch
46 | * @param timeout 超时时间 30s
47 | * @returns {Promise.<*>}
48 | */
49 | const timeoutFetch = (original_fetch, timeout = 30000) => {
50 | let timeoutBlock = () => {}
51 | let timeout_promise = new Promise((resolve, reject) => {
52 | timeoutBlock = () => {
53 | // 请求超时处理
54 | reject('timeout promise')
55 | }
56 | })
57 |
58 | let abortable_promise = Promise.race([
59 | original_fetch,
60 | timeout_promise
61 | ])
62 |
63 | setTimeout(() => {
64 | timeoutBlock()
65 | }, timeout)
66 |
67 | return abortable_promise
68 | }
69 |
70 | async function handleLogin(callback) {
71 | return callback()
72 | var loginInfo = wx.getStorageSync('loginInfo') || {}
73 | var refreshToken = loginInfo.refreshToken
74 | var newData = new Date().getTime()
75 | if (loginInfo.accessToken) {
76 | if (loginInfo.expiration > newData) {
77 | console.log('未过期')
78 | return callback()
79 | } else {
80 | console.log('已过期')
81 | let params = {
82 | url: `${API_URL}${PATH.REFRESH_TOKEN}`,
83 | data: {refreshToken: refreshToken},
84 | method: 'POST'
85 | }
86 | const refreshTokenInfo = await request(params)
87 | if (refreshTokenInfo.code != 0) {
88 | const wxLoginInfo = await login()
89 | let param = {
90 | url: `${API_URL}${PATH.LOGIN}?trace=true`,
91 | data: {appId: currentHost.appId, jsCode: wxLoginInfo.code},
92 | method: 'POST'
93 | }
94 | const qbLoginInfo = await request(param)
95 | console.log('silentUserId:', qbLoginInfo.data.user.id)
96 | console.log('silentAccessToken:', qbLoginInfo.data.accessToken)
97 | wx.setStorageSync('loginInfo', qbLoginInfo.data)
98 | return callback()
99 | } else {
100 | wx.setStorageSync('loginInfo', Object.assign(loginInfo, refreshTokenInfo.data))
101 | return callback()
102 | }
103 | }
104 | } else {
105 | console.log('未登录')
106 | const wxLoginInfo = await login()
107 | let params = {
108 | url: `${API_URL}${PATH.LOGIN}?trace=true`,
109 | data: {appId: currentHost.appId, jsCode: wxLoginInfo.code},
110 | method: 'POST'
111 | }
112 | const qbLoginInfo = await request(params)
113 | console.log('silentUserId:', qbLoginInfo.data.user.id)
114 | console.log('silentAccessToken:', qbLoginInfo.data.accessToken)
115 | wx.setStorageSync('loginInfo', qbLoginInfo.data)
116 | return callback()
117 | }
118 | }
119 |
120 | const networkLog = (url, params, res, beforeRequest, isSuccess) => {
121 | const pages = getCurrentPages()
122 | const currentPage = pages[pages.length - 1]
123 | const route = currentPage.route
124 | const networkType = wx.getStorageSync('networkType')
125 | const afterRequest = new Date().getTime()
126 | const timeDif = afterRequest - beforeRequest
127 | var networkArr = wx.getStorageSync('networkArr') || []
128 | if (networkArr.length >= 30) {
129 | wx.removeStorageSync('networkArr')
130 | networkArr = []
131 | }
132 | var time = timestampToCommonDate(new Date().getTime())
133 | networkArr = _array.unshift(networkArr, {url, params, res, time, route, timeDif, networkType, isSuccess})
134 | wx.setStorageSync('networkArr', networkArr)
135 | }
136 |
137 | const HttpUtils = {
138 | /**
139 | * fetch网络请求
140 | * @param {string} [url=''] 网络请求URL
141 | * @param {*} [params={}] 网络请求参数
142 | * @param {string} [requestType='GET'] 请求类型
143 | * @param {boolean} [isLoading=true] 是否需要Loading
144 | */
145 | fetch: (url = '', params = {}, requestType = 'GET', isLoading = false) => {
146 | const fetchCallback = () => {
147 | let promise = timeoutFetch(new Promise((resolve, reject) => {
148 | wx.showNavigationBarLoading()
149 | isLoading ? wx.showLoading({title: '加载中...', mask: true}) : null
150 | const beforeRequest = new Date().getTime()
151 | wx.request({
152 | url: url,
153 | data: params,
154 | header: header,
155 | method: requestType,
156 | success: function (res) {
157 | let isSuccess = false
158 | let resCode = res.statusCode
159 | if (parseInt(resCode / 100) == 2) {
160 | isSuccess = true
161 | resolve(res.data)
162 | } else if (resCode == responseCode.TOKEN_INVALID) {
163 | } else if (resCode == responseCode.USER_LOGOUT) {
164 | } else {
165 | wx.showToast({ title: '服务器异常', icon: 'none', duration: 4000 })
166 | }
167 | networkLog(url, params, res.data, beforeRequest, isSuccess)
168 | },
169 | fail: function (e) {
170 | wx.showToast({ title: e.errMsg, icon: 'none', duration: 4000 })
171 | networkLog(url, params, e, beforeRequest, false)
172 | reject(e)
173 | },
174 | complete: function () {
175 | isLoading ? wx.hideLoading() : null
176 | wx.hideNavigationBarLoading()
177 | wx.stopPullDownRefresh()
178 | }
179 | })
180 | }))
181 | return promise
182 | }
183 | return handleLogin(fetchCallback)
184 | }
185 | }
186 |
187 | export default HttpUtils
--------------------------------------------------------------------------------
/src/pages/addAddress/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 联系人:
5 |
6 |
7 |
8 |
9 |
10 |
11 | 先生
12 |
13 |
14 |
15 | 女士
16 |
17 |
18 |
19 | 手机号:
20 |
21 |
22 |
23 |
收货地址:
24 |
25 |
26 | 点击选择
27 |
28 |
29 |
30 |
31 |
32 |
33 | 门牌号:
34 |
35 |
36 |
37 | 保存地址
38 |
39 |
40 |
41 |
42 |
47 |
48 |
188 |
--------------------------------------------------------------------------------
/src/pages/addAddress/main.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-09-18 17:04:59 */
2 | import Vue from 'vue'
3 | import App from './index'
4 |
5 | const app = new Vue(App)
6 | app.$mount()
--------------------------------------------------------------------------------
/src/pages/addAddress/main.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "新增收货地址"
3 | }
--------------------------------------------------------------------------------
/src/pages/addressList/data.js:
--------------------------------------------------------------------------------
1 | const addressList = {
2 | "data": [{
3 | "phone": "15214313256",
4 | "can_not_shipping_type": 0,
5 | "category_icon": "",
6 | "gd_addr_type": "",
7 | "is_default": 0,
8 | "address_range_tip": "",
9 | "editable": 1,
10 | "bind_type": 11,
11 | "id": 935908631,
12 | "category": 0,
13 | "house_number": "2楼,外卖科技",
14 | "can_shipping": 1,
15 | "address": "上海科技绿洲B区18号楼",
16 | "name": "刘光强",
17 | "gender": "先生",
18 | "longitude": 121385976,
19 | "latitude": 31164474,
20 | "address_type": 0
21 | }, {
22 | "phone": "15214313256",
23 | "can_not_shipping_type": 0,
24 | "category_icon": "http://p1.meituan.net/aichequan/459e21821938f624d4b340e6444831f71644.png",
25 | "gd_addr_type": "",
26 | "is_default": 0,
27 | "address_range_tip": "",
28 | "editable": 1,
29 | "bind_type": 15,
30 | "id": 1225134045,
31 | "category": 1,
32 | "house_number": "18号楼888号",
33 | "can_shipping": 1,
34 | "address": "九星苑",
35 | "name": "刘先生",
36 | "gender": "先生",
37 | "longitude": 121381110,
38 | "latitude": 31150280,
39 | "address_type": 0
40 | }, {
41 | "phone": "15214313256",
42 | "can_not_shipping_type": 0,
43 | "category_icon": "",
44 | "gd_addr_type": "",
45 | "is_default": 0,
46 | "address_range_tip": "",
47 | "editable": 1,
48 | "bind_type": 11,
49 | "id": 684933800,
50 | "category": 0,
51 | "house_number": "401",
52 | "can_shipping": 1,
53 | "address": "广中西路911弄51号",
54 | "name": "光强",
55 | "gender": "先生",
56 | "longitude": 121437016,
57 | "latitude": 31278644,
58 | "address_type": 0
59 | }, {
60 | "phone": "15214313256",
61 | "can_not_shipping_type": 0,
62 | "category_icon": "",
63 | "gd_addr_type": "",
64 | "is_default": 0,
65 | "address_range_tip": "",
66 | "editable": 1,
67 | "bind_type": 11,
68 | "id": 716687722,
69 | "category": 0,
70 | "house_number": "1111号,111栋",
71 | "can_shipping": 1,
72 | "address": "沪太路1067弄11号",
73 | "name": "光强",
74 | "gender": "先生",
75 | "longitude": 121427128,
76 | "latitude": 31277978,
77 | "address_type": 0
78 | }],
79 | "code": 0,
80 | "msg": "成功"
81 | }
82 |
83 | export {addressList}
--------------------------------------------------------------------------------
/src/pages/addressList/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
{{item.address}} {{item.house_number}}
7 |
8 | {{item.name}}
9 | {{item.gender}}
10 | {{item.phone}}
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | 新增收货地址
19 |
20 |
21 |
22 |
23 |
41 |
42 |
109 |
--------------------------------------------------------------------------------
/src/pages/addressList/main.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-09-18 16:43:20 */
2 | import Vue from 'vue'
3 | import App from './index'
4 |
5 | const app = new Vue(App)
6 | app.$mount()
--------------------------------------------------------------------------------
/src/pages/addressList/main.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "我的收获地址"
3 | }
--------------------------------------------------------------------------------
/src/pages/categoryList/main.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-09-18 19:54:52 */
2 | import Vue from 'vue'
3 | import App from './index'
4 |
5 | const app = new Vue(App)
6 | app.$mount()
--------------------------------------------------------------------------------
/src/pages/categoryList/main.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "美食"
3 | }
--------------------------------------------------------------------------------
/src/pages/citySearch/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
搜索历史
9 |
10 |
11 | 合川路
12 | 上海市闵行区
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
29 |
30 |
110 |
--------------------------------------------------------------------------------
/src/pages/citySearch/main.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-09-14 18:14:27 */
2 | import Vue from 'vue'
3 | import App from './index'
4 |
5 | const app = new Vue(App)
6 | app.$mount()
7 |
--------------------------------------------------------------------------------
/src/pages/citys/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
21 |
22 |
23 |
A
24 |
25 |
26 | {{itx}}
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
49 |
50 |
164 |
--------------------------------------------------------------------------------
/src/pages/citys/main.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-08-30 18:13:59 */
2 | import Vue from 'vue'
3 | import App from './index'
4 |
5 | const app = new Vue(App)
6 | app.$mount()
7 |
--------------------------------------------------------------------------------
/src/pages/commentList/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 评论
4 |
5 |
6 |
7 |
12 |
13 |
16 |
--------------------------------------------------------------------------------
/src/pages/commentList/main.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-10-07 17:51:40 */
2 | import Vue from 'vue'
3 | import App from './index'
4 |
5 | const app = new Vue(App)
6 | app.$mount()
--------------------------------------------------------------------------------
/src/pages/commentList/main.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "评论"
3 | }
--------------------------------------------------------------------------------
/src/pages/couponList/data.js:
--------------------------------------------------------------------------------
1 | const couponList = {
2 | "data": {
3 | "page_index": 0,
4 | "poi_coupon_info_list": [{
5 | "valid": false,
6 | "poicoupon_view_id": "syAPBsPPPvyOk&source=wKid=OkPPOkPBt",
7 | "status": 1,
8 | "valid_day": 8,
9 | "code": "",
10 | "type": 1,
11 | "poi_id": 959825,
12 | "mutex_type": 1,
13 | "poi_url": "http://p1.meituan.net/waimaipoi/30759016da283ca9a103d83624cf26f340960.jpg",
14 | "info": "",
15 | "id": -11,
16 | "disable_descriptions": [],
17 | "title": "烧烤吧(龙虾)",
18 | "use_rule": "不可与满减、折扣商品、第二份半价活动优惠同时享受。在线支付专享。",
19 | "scheme": "",
20 | "valid_time_desc": "有效期至2018.10.01",
21 | "use_condition": "",
22 | "money": 35.0,
23 | "category_type": 0,
24 | "price_limit": "满65可用",
25 | "deadline": 1538409599
26 | }, {
27 | "valid": false,
28 | "poicoupon_view_id": "syAPBsPPPvywK&source=wKid=OkPPOkPBt",
29 | "status": 1,
30 | "valid_day": 8,
31 | "code": "",
32 | "type": 1,
33 | "poi_id": 5319356,
34 | "mutex_type": 1,
35 | "poi_url": "http://p0.meituan.net/waimaipoi/62f2afcb9bdf34e38fe183017995a307303008.jpg",
36 | "info": "",
37 | "id": -11,
38 | "disable_descriptions": [],
39 | "title": "串意十足烧烤店(古方路店)",
40 | "use_rule": "不可与满减、折扣商品、第二份半价活动优惠同时享受。在线支付专享。",
41 | "scheme": "",
42 | "valid_time_desc": "有效期至2018.10.01",
43 | "use_condition": "",
44 | "money": 31.0,
45 | "category_type": 0,
46 | "price_limit": "满48可用",
47 | "deadline": 1538409599
48 | }, {
49 | "valid": false,
50 | "poicoupon_view_id": "stsvayAsPvyts&source=wKid=OkPBBvvyt",
51 | "status": 1,
52 | "valid_day": 3,
53 | "code": "",
54 | "type": 1,
55 | "poi_id": 1602339,
56 | "mutex_type": 1,
57 | "poi_url": "http://p1.meituan.net/waimaipoi/172eb82855c13261baf78a056db93adc304216.jpg",
58 | "info": "",
59 | "id": -11,
60 | "disable_descriptions": [],
61 | "title": "席师傅特色麻辣香锅",
62 | "use_rule": "不可与满减、折扣商品、第二份半价活动优惠同时享受。在线支付专享。",
63 | "scheme": "",
64 | "valid_time_desc": "有效期至2018.09.26",
65 | "use_condition": "",
66 | "money": 28.0,
67 | "category_type": 0,
68 | "price_limit": "满45可用",
69 | "deadline": 1537977599
70 | }, {
71 | "valid": false,
72 | "poicoupon_view_id": "swKPPyAPPtsva&source=wKid=OkPBBvvyt",
73 | "status": 1,
74 | "valid_day": 3,
75 | "code": "",
76 | "type": 1,
77 | "poi_id": 5204575,
78 | "mutex_type": 1,
79 | "poi_url": "http://p1.meituan.net/business/4895902007cf8cad1e04d27d3f77d89f54971.jpg",
80 | "info": "",
81 | "id": -11,
82 | "disable_descriptions": [],
83 | "title": "九阿婆黄金猪排饭(漕河泾店)",
84 | "use_rule": "不可与满减、折扣商品、第二份半价活动优惠同时享受。在线支付专享。",
85 | "scheme": "",
86 | "valid_time_desc": "有效期至2018.09.26",
87 | "use_condition": "",
88 | "money": 26.0,
89 | "category_type": 0,
90 | "price_limit": "满30可用",
91 | "deadline": 1537977599
92 | }, {
93 | "valid": false,
94 | "poicoupon_view_id": "yBvvaOkyABvsP&source=wKid=OkPBBvwKv",
95 | "status": 1,
96 | "valid_day": 26,
97 | "code": "",
98 | "type": 1,
99 | "poi_id": 5631136,
100 | "mutex_type": 2,
101 | "poi_url": "http://p0.meituan.net/waimaipoi/c4ea604406e519bd53156313bf267c99100224.jpg",
102 | "info": "",
103 | "id": -11,
104 | "disable_descriptions": [],
105 | "title": "夜曲成人用品",
106 | "use_rule": "可与其他活动优惠同时享受。在线支付专享。",
107 | "scheme": "",
108 | "valid_time_desc": "有效期至2018.10.19",
109 | "use_condition": "",
110 | "money": 15.0,
111 | "category_type": 0,
112 | "price_limit": "满100可用",
113 | "deadline": 1539964799
114 | }, {
115 | "valid": false,
116 | "poicoupon_view_id": "PvyvaBvtsyAwK&source=wKid=OkPBvasPP",
117 | "status": 1,
118 | "valid_day": 7,
119 | "code": "",
120 | "type": 1,
121 | "poi_id": 4756335,
122 | "mutex_type": 2,
123 | "poi_url": "http://p1.meituan.net/waimaipoi/8f5a14a02bc26f9d7ea9fb6395ae108c4017.jpg",
124 | "info": "",
125 | "id": -11,
126 | "disable_descriptions": [],
127 | "title": "乐凯撒比萨(爱琴海购物公园店)",
128 | "use_rule": "可与其他活动优惠同时享受。在线支付专享。",
129 | "scheme": "",
130 | "valid_time_desc": "有效期至2018.09.30",
131 | "use_condition": "",
132 | "money": 9.0,
133 | "category_type": 0,
134 | "price_limit": "满90可用",
135 | "deadline": 1538323199
136 | }, {
137 | "valid": false,
138 | "poicoupon_view_id": "PPBvyyAtsOkwK&source=wKid=OkPBvatss",
139 | "status": 1,
140 | "valid_day": 3,
141 | "code": "",
142 | "type": 1,
143 | "poi_id": 4208203,
144 | "mutex_type": 2,
145 | "poi_url": "http://p0.meituan.net/waimaipoi/eec7c57c9497d61b02a886f0b8229ec3239616.jpg",
146 | "info": "",
147 | "id": -11,
148 | "disable_descriptions": [],
149 | "title": "重庆鸡公煲(漕宝店)",
150 | "use_rule": "可与其他活动优惠同时享受。在线支付专享。",
151 | "scheme": "",
152 | "valid_time_desc": "有效期至2018.09.26",
153 | "use_condition": "",
154 | "money": 5.0,
155 | "category_type": 0,
156 | "price_limit": "满56可用",
157 | "deadline": 1537977599
158 | }, {
159 | "valid": false,
160 | "poicoupon_view_id": "kOkBvBvvyOkwK&source=wKid=OkPBwKsPO",
161 | "status": 1,
162 | "valid_day": 23,
163 | "code": "",
164 | "type": 1,
165 | "poi_id": 2145959,
166 | "mutex_type": 2,
167 | "poi_url": "http://p1.meituan.net/waimaipoi/28cbe8190b93878db45cf126c5711eea40960.jpg",
168 | "info": "",
169 | "id": -11,
170 | "disable_descriptions": [],
171 | "title": "华城果业",
172 | "use_rule": "可与其他活动优惠同时享受。在线支付专享。",
173 | "scheme": "",
174 | "valid_time_desc": "有效期至2018.10.16",
175 | "use_condition": "",
176 | "money": 3.0,
177 | "category_type": 0,
178 | "price_limit": "满48可用",
179 | "deadline": 1539705599
180 | }, {
181 | "valid": false,
182 | "poicoupon_view_id": "vPBPBwKPPBvOk&source=wKid=OkPBOkPPB",
183 | "status": 1,
184 | "valid_day": 24,
185 | "code": "",
186 | "type": 1,
187 | "poi_id": 5439052,
188 | "mutex_type": 2,
189 | "poi_url": "http://p1.meituan.net/waimaipoi/339aeb47a0bff9d6ae6910309deb9aa811035.jpg",
190 | "info": "",
191 | "id": -11,
192 | "disable_descriptions": [],
193 | "title": "三米粥铺(东兰店)",
194 | "use_rule": "可与其他活动优惠同时享受。在线支付专享。",
195 | "scheme": "",
196 | "valid_time_desc": "有效期至2018.10.17",
197 | "use_condition": "",
198 | "money": 3.0,
199 | "category_type": 0,
200 | "price_limit": "满39可用",
201 | "deadline": 1539791999
202 | }],
203 | "show_coupon_token": 0,
204 | "has_more": 0,
205 | "coupon_token_url": "",
206 | "coupon_token_text": "去领券"
207 | },
208 | "code": 0,
209 | "msg": "成功"
210 | }
211 |
212 | export {couponList}
--------------------------------------------------------------------------------
/src/pages/couponList/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
![]()
7 |
8 | {{item.title}}
9 | 互斥券
10 | {{item.valid_time_desc}}
11 |
12 |
13 | ¥{{item.money}}
14 | {{item.price_limit}}
15 |
16 |
17 |
18 |
19 |
20 |
21 |
{{item.use_rule}}
22 |
23 | 去使用
24 |
25 |
26 |
27 |
28 |
29 |
30 | 没有更多商家代金券了
31 | |
32 | 查看过期券
33 | >>
34 |
35 |
36 |
37 |
38 |
67 |
68 |
185 |
--------------------------------------------------------------------------------
/src/pages/couponList/main.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-09-18 15:39:31 */
2 | import Vue from 'vue'
3 | import App from './index'
4 |
5 | const app = new Vue(App)
6 | app.$mount()
--------------------------------------------------------------------------------
/src/pages/couponList/main.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "商家代金券"
3 | }
--------------------------------------------------------------------------------
/src/pages/dicedActivity/index.vue:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Umbrella001/mpvue-meituan/ea9c57fce44c762edaa10114316ac91b20f27773/src/pages/dicedActivity/index.vue
--------------------------------------------------------------------------------
/src/pages/dicedActivity/main.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-09-19 23:23:49 */
2 | import Vue from 'vue'
3 | import App from './index'
4 |
5 | const app = new Vue(App)
6 | app.$mount()
--------------------------------------------------------------------------------
/src/pages/dicedActivity/main.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/src/pages/expiredCoupon/data.js:
--------------------------------------------------------------------------------
1 | const dataList = {
2 | "data": {
3 | "page_index": 0,
4 | "poi_coupon_info_list": [{
5 | "valid": false,
6 | "poicoupon_view_id": "vPPvyPBPBBvPP&source=wKid=OkPByAvaB",
7 | "status": 3,
8 | "valid_day": 0,
9 | "code": "",
10 | "type": 1,
11 | "poi_id": 5606842,
12 | "mutex_type": 1,
13 | "poi_url": "http://p1.meituan.net/waimaipoi/e3cda15ee74c4cc5ca6c0f75b427ca40321522.jpg",
14 | "info": "",
15 | "id": -11,
16 | "disable_descriptions": [],
17 | "title": "麻辣无双(东兰路店)",
18 | "use_rule": "不可与满减、折扣商品、第二份半价活动优惠同时享受。在线支付专享。",
19 | "scheme": "",
20 | "valid_time_desc": "有效期至2018.09.22",
21 | "use_condition": "",
22 | "money": 32.0,
23 | "category_type": 0,
24 | "price_limit": "满45可用",
25 | "deadline": 1537631999
26 | }, {
27 | "valid": false,
28 | "poicoupon_view_id": "vvayAtsBvsPyA&source=wKid=OkPByAvaB",
29 | "status": 3,
30 | "valid_day": 0,
31 | "code": "",
32 | "type": 1,
33 | "poi_id": 1602339,
34 | "mutex_type": 1,
35 | "poi_url": "http://p1.meituan.net/waimaipoi/172eb82855c13261baf78a056db93adc304216.jpg",
36 | "info": "",
37 | "id": -11,
38 | "disable_descriptions": [],
39 | "title": "席师傅特色麻辣香锅",
40 | "use_rule": "不可与满减、折扣商品、第二份半价活动优惠同时享受。在线支付专享。",
41 | "scheme": "",
42 | "valid_time_desc": "有效期至2018.09.22",
43 | "use_condition": "",
44 | "money": 28.0,
45 | "category_type": 0,
46 | "price_limit": "满45可用",
47 | "deadline": 1537631999
48 | }, {
49 | "valid": false,
50 | "poicoupon_view_id": "PsPvyOksPtsOk&source=wKid=OkPBBvvas",
51 | "status": 3,
52 | "valid_day": 0,
53 | "code": "",
54 | "type": 1,
55 | "poi_id": 4633504,
56 | "mutex_type": 1,
57 | "poi_url": "http://p0.meituan.net/waimaipoi/2fd1ecc03b71fcdcdc388981734e379a30167.jpg",
58 | "info": "",
59 | "id": -11,
60 | "disable_descriptions": [],
61 | "title": "粥宫壹号(漕宝路店)",
62 | "use_rule": "不可与满减、折扣商品、第二份半价活动优惠同时享受。在线支付专享。",
63 | "scheme": "",
64 | "valid_time_desc": "有效期至2018.09.22",
65 | "use_condition": "",
66 | "money": 18.0,
67 | "category_type": 0,
68 | "price_limit": "满25可用",
69 | "deadline": 1537631999
70 | }],
71 | "show_coupon_token": 0,
72 | "has_more": 0,
73 | "coupon_token_url": "",
74 | "coupon_token_text": "去领券"
75 | },
76 | "code": 0,
77 | "msg": "成功"
78 | }
79 |
80 | export {dataList}
--------------------------------------------------------------------------------
/src/pages/expiredCoupon/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
![]()
7 |
8 | {{item.title}}
9 | 互斥券
10 | {{item.valid_time_desc}}
11 |
12 |
13 | ¥{{item.money}}
14 | {{item.price_limit}}
15 |
16 |
17 |
18 |
19 |
20 |
21 | {{item.use_rule}}
22 |
23 |

24 |
25 |
26 |
27 | 没有更多过期商家代金券了
28 |
29 |
30 |
31 |
32 |
53 |
54 |
154 |
--------------------------------------------------------------------------------
/src/pages/expiredCoupon/main.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-09-18 16:31:10 */
2 | import Vue from 'vue'
3 | import App from './index'
4 |
5 | const app = new Vue(App)
6 | app.$mount()
--------------------------------------------------------------------------------
/src/pages/expiredCoupon/main.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "商家代金券"
3 | }
--------------------------------------------------------------------------------
/src/pages/expiredRedPacket/data.js:
--------------------------------------------------------------------------------
1 | const dataList = {
2 | "data": {
3 | "show_steal_entry": 0,
4 | "page_size": 20,
5 | "vp_entrance": {
6 | "text": "",
7 | "bg_url": "",
8 | "sub_text": "",
9 | "link": "",
10 | "buy_status": 0,
11 | "icon_url": "",
12 | "show": false
13 | },
14 | "page_index": 0,
15 | "coupon_total_num": 10,
16 | "has_more": 0,
17 | "coupon_list": [{
18 | "coupon_sign": "",
19 | "status": 3,
20 | "shipping_type": 0,
21 | "coupon_id": -11,
22 | "coupon_key": "",
23 | "coupon_type": 1,
24 | "steal_status": 0,
25 | "poi_exchanged_coupon": 0,
26 | "poi_id": 0,
27 | "amount": 6.0,
28 | "id": -11,
29 | "disable_descriptions": [],
30 | "title": "狂欢月专属红包",
31 | "use_limits": "限仅限外卖狂欢月部分指定商户可用,微信小程序,非到店自取订单使用。限登录和收餐手机号为15214313256使用。",
32 | "valid_time_desc": "有效期至2018.09.24",
33 | "coupon_view_id": "yOkPPvavyPBsP&source=tsid=OkPPwKtsv",
34 | "is_premium_type": false,
35 | "category_type": 0,
36 | "price_limit": "满30可用",
37 | "logo_url": ""
38 | }, {
39 | "coupon_sign": "",
40 | "status": 3,
41 | "shipping_type": 0,
42 | "coupon_id": -11,
43 | "coupon_key": "",
44 | "coupon_type": 1,
45 | "steal_status": 0,
46 | "poi_exchanged_coupon": 0,
47 | "poi_id": 0,
48 | "amount": 4.0,
49 | "id": -11,
50 | "disable_descriptions": [],
51 | "title": "通用红包",
52 | "use_limits": "限非到店自取订单使用。限登录和收餐手机号为15214313256使用。",
53 | "valid_time_desc": "有效期至2018.09.23",
54 | "coupon_view_id": "KwKtsBvsPOkwK&source=tsid=OkPBsPtsw",
55 | "is_premium_type": false,
56 | "category_type": 0,
57 | "price_limit": "满20可用",
58 | "logo_url": ""
59 | }, {
60 | "coupon_sign": "",
61 | "status": 3,
62 | "shipping_type": 0,
63 | "coupon_id": -11,
64 | "coupon_key": "",
65 | "coupon_type": 1,
66 | "steal_status": 0,
67 | "poi_exchanged_coupon": 0,
68 | "poi_id": 0,
69 | "amount": 4.0,
70 | "id": -11,
71 | "disable_descriptions": [],
72 | "title": "狂欢月专属红包",
73 | "use_limits": "限仅限外卖狂欢月部分指定商户可用,微信小程序,非到店自取订单使用。限登录和收餐手机号为15214313256使用。",
74 | "valid_time_desc": "有效期至2018.09.22",
75 | "coupon_view_id": "PvyvyvyyAPPOk&source=tsid=OkPBvyvaP",
76 | "is_premium_type": false,
77 | "category_type": 0,
78 | "price_limit": "满20可用",
79 | "logo_url": ""
80 | }, {
81 | "coupon_sign": "",
82 | "status": 3,
83 | "shipping_type": 0,
84 | "coupon_id": -11,
85 | "coupon_key": "",
86 | "coupon_type": 1,
87 | "steal_status": 0,
88 | "poi_exchanged_coupon": 0,
89 | "poi_id": 0,
90 | "amount": 4.0,
91 | "id": -11,
92 | "disable_descriptions": [],
93 | "title": "狂欢月专属红包",
94 | "use_limits": "限仅限外卖狂欢月部分指定商户可用,微信小程序,非到店自取订单使用。限登录和收餐手机号为15214313256使用。",
95 | "valid_time_desc": "有效期至2018.09.21",
96 | "coupon_view_id": "ssPyAtsPBPPBv&source=tsid=OkPBvavat",
97 | "is_premium_type": false,
98 | "category_type": 0,
99 | "price_limit": "满20可用",
100 | "logo_url": ""
101 | }, {
102 | "coupon_sign": "",
103 | "status": 3,
104 | "shipping_type": 0,
105 | "coupon_id": -11,
106 | "coupon_key": "",
107 | "coupon_type": 1,
108 | "steal_status": 0,
109 | "poi_exchanged_coupon": 0,
110 | "poi_id": 0,
111 | "amount": 4.0,
112 | "id": -11,
113 | "disable_descriptions": [],
114 | "title": "通用红包",
115 | "use_limits": "限非到店自取订单使用。限登录和收餐手机号为15214313256使用。",
116 | "valid_time_desc": "有效期至2018.09.20",
117 | "coupon_view_id": "KPPPByAwKBvvy&source=tsid=OkPBPPyAw",
118 | "is_premium_type": false,
119 | "category_type": 0,
120 | "price_limit": "满20可用",
121 | "logo_url": ""
122 | }, {
123 | "coupon_sign": "",
124 | "status": 3,
125 | "shipping_type": 0,
126 | "coupon_id": -11,
127 | "coupon_key": "",
128 | "coupon_type": 1,
129 | "steal_status": 0,
130 | "poi_exchanged_coupon": 0,
131 | "poi_id": 0,
132 | "amount": 4.0,
133 | "id": -11,
134 | "disable_descriptions": [],
135 | "title": "狂欢月专属红包",
136 | "use_limits": "限仅限外卖狂欢月部分指定商户可用,微信小程序,非到店自取订单使用。限登录和收餐手机号为15214313256使用。",
137 | "valid_time_desc": "有效期至2018.09.20",
138 | "coupon_view_id": "yPBwKOkPByAts&source=tsid=OkPBPPsPv",
139 | "is_premium_type": false,
140 | "category_type": 0,
141 | "price_limit": "满20可用",
142 | "logo_url": ""
143 | }, {
144 | "coupon_sign": "",
145 | "status": 3,
146 | "shipping_type": 0,
147 | "coupon_id": -11,
148 | "coupon_key": "",
149 | "coupon_type": 1,
150 | "steal_status": 0,
151 | "poi_exchanged_coupon": 0,
152 | "poi_id": 0,
153 | "amount": 1.0,
154 | "id": -11,
155 | "disable_descriptions": [],
156 | "title": "夜宵红包",
157 | "use_limits": "限非到店自取订单,21:00-23:59、00:00-05:00,夜宵频道使用。限登录和收餐手机号为15214313256使用。",
158 | "valid_time_desc": "有效期至2018.09.20",
159 | "coupon_view_id": "syAwKBvyAtsyA&source=tsid=OkPBBvvyt",
160 | "is_premium_type": false,
161 | "category_type": 0,
162 | "price_limit": "满40可用",
163 | "logo_url": ""
164 | }, {
165 | "coupon_sign": "",
166 | "status": 3,
167 | "shipping_type": 0,
168 | "coupon_id": -11,
169 | "coupon_key": "",
170 | "coupon_type": 1,
171 | "steal_status": 0,
172 | "poi_exchanged_coupon": 0,
173 | "poi_id": 0,
174 | "amount": 4.0,
175 | "id": -11,
176 | "disable_descriptions": [],
177 | "title": "狂欢月专属红包",
178 | "use_limits": "限仅限外卖狂欢月部分指定商户可用,微信小程序,非到店自取订单使用。限登录和收餐手机号为15214313256使用。",
179 | "valid_time_desc": "有效期至2018.09.19",
180 | "coupon_view_id": "APPOkPByAsPBv&source=tsid=OkPBPBvay",
181 | "is_premium_type": false,
182 | "category_type": 0,
183 | "price_limit": "满20可用",
184 | "logo_url": ""
185 | }, {
186 | "coupon_sign": "",
187 | "status": 3,
188 | "shipping_type": 0,
189 | "coupon_id": -11,
190 | "coupon_key": "",
191 | "coupon_type": 1,
192 | "steal_status": 0,
193 | "poi_exchanged_coupon": 0,
194 | "poi_id": 0,
195 | "amount": 3.0,
196 | "id": -11,
197 | "disable_descriptions": [],
198 | "title": "狂欢月专属红包",
199 | "use_limits": "限仅限外卖狂欢月部分指定商户可用,微信小程序,非到店自取订单使用。限登录和收餐手机号为15214313256使用。",
200 | "valid_time_desc": "有效期至2018.09.18",
201 | "coupon_view_id": "BwKyAPByAyAyA&source=tsid=OkPBOkPBP",
202 | "is_premium_type": false,
203 | "category_type": 0,
204 | "price_limit": "满20可用",
205 | "logo_url": ""
206 | }, {
207 | "coupon_sign": "",
208 | "status": 3,
209 | "shipping_type": 0,
210 | "coupon_id": -11,
211 | "coupon_key": "",
212 | "coupon_type": 1,
213 | "steal_status": 0,
214 | "poi_exchanged_coupon": 0,
215 | "poi_id": 0,
216 | "amount": 3.0,
217 | "id": -11,
218 | "disable_descriptions": [],
219 | "title": "狂欢月专属红包",
220 | "use_limits": "限仅限外卖狂欢月部分指定商户可用,微信小程序,非到店自取订单使用。限登录和收餐手机号为15214313256使用。",
221 | "valid_time_desc": "有效期至2018.09.17",
222 | "coupon_view_id": "ysPvyyAwKvayA&source=tsid=OkPBOkOkv",
223 | "is_premium_type": false,
224 | "category_type": 0,
225 | "price_limit": "满20可用",
226 | "logo_url": ""
227 | }]
228 | },
229 | "code": 0,
230 | "msg": "成功"
231 | }
232 |
233 | export {dataList}
--------------------------------------------------------------------------------
/src/pages/expiredRedPacket/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{item.title}}
8 | {{item.valid_time_desc}}
9 |
10 |
11 | ¥{{item.amount}}
12 | {{item.price_limit}}
13 |
14 |
15 |
16 |
17 |
18 |
{{item.use_limits}}
19 |

20 |
21 |
22 |
23 | 没有更多无效红包了
24 |
25 |
26 |
27 |
28 |
49 |
50 |
139 |
--------------------------------------------------------------------------------
/src/pages/expiredRedPacket/main.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-09-18 14:29:11 */
2 | import Vue from 'vue'
3 | import App from './index'
4 |
5 | const app = new Vue(App)
6 | app.$mount()
--------------------------------------------------------------------------------
/src/pages/expiredRedPacket/main.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "美团红包"
3 | }
--------------------------------------------------------------------------------
/src/pages/feedback/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
16 |
17 |
--------------------------------------------------------------------------------
/src/pages/feedback/main.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-09-25 17:10:23 */
2 |
3 | import Vue from 'vue'
4 | import App from './index'
5 |
6 | const app = new Vue(App)
7 | app.$mount()
--------------------------------------------------------------------------------
/src/pages/feedback/main.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "美团外卖"
3 | }
--------------------------------------------------------------------------------
/src/pages/home/main.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-09-14 20:16:03 */
2 | import Vue from 'vue'
3 | import App from '.'
4 |
5 | const app = new Vue(App)
6 | app.$mount()
--------------------------------------------------------------------------------
/src/pages/home/main.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "仿美团外卖"
3 | }
--------------------------------------------------------------------------------
/src/pages/index/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
![]()
5 |
6 |
7 |
8 |
9 |
10 |
15 |
16 |
20 |
去往Vuex示例页面dadad
21 |
22 |
23 |
24 |
75 |
76 |
114 |
--------------------------------------------------------------------------------
/src/pages/index/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './index'
3 |
4 | const app = new Vue(App)
5 | app.$mount()
6 |
--------------------------------------------------------------------------------
/src/pages/me/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
12 |
13 |
14 | {{item.title}}
15 | {{item.amount}}张
16 |
17 |
18 |
19 |
20 |
退出账号
21 |
22 |
23 |
24 |
90 |
91 |
177 |
--------------------------------------------------------------------------------
/src/pages/me/main.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-09-18 10:13:17 */
2 | import Vue from 'vue'
3 | import App from './index'
4 |
5 | const app = new Vue(App)
6 | app.$mount()
--------------------------------------------------------------------------------
/src/pages/me/main.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarBackgroundColor": "#FFD26B",
3 | "navigationBarTextStyle": "black",
4 | "navigationBarTitleText": "我的",
5 | "backgroundColor": "#eeeeee",
6 | "backgroundTextStyle": "light"
7 | }
--------------------------------------------------------------------------------
/src/pages/orderDetail/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 订单详情,待完成
4 |
5 |
6 |
7 |
12 |
13 |
16 |
--------------------------------------------------------------------------------
/src/pages/orderDetail/main.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-09-19 20:13:22 */
2 |
3 | import Vue from 'vue'
4 | import App from './index'
5 |
6 | const app = new Vue(App)
7 | app.$mount()
--------------------------------------------------------------------------------
/src/pages/orderDetail/main.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "订单详情"
3 | }
--------------------------------------------------------------------------------
/src/pages/orderList/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
![]()
7 |
{{item.poi_name}}
8 |
9 |
{{item.status_description}}
10 |
11 |
12 |
13 | {{itx.product_name}}
14 | x{{itx.product_count}}
15 |
16 |
17 |
18 | 共{{item.product_list.length}}件商品,实付
19 | ¥{{item.total}}
20 |
21 |
26 |
27 |
28 |
29 |
30 |
31 |
53 |
54 |
155 |
--------------------------------------------------------------------------------
/src/pages/orderList/main.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-09-17 23:39:29 */
2 | import Vue from 'vue'
3 | import App from './index'
4 |
5 | const app = new Vue(App)
6 | app.$mount()
--------------------------------------------------------------------------------
/src/pages/orderList/main.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "订单"
3 | }
--------------------------------------------------------------------------------
/src/pages/pickProtocol/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
16 |
17 |
--------------------------------------------------------------------------------
/src/pages/pickProtocol/main.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-09-26 23:28:01 */
2 | import Vue from 'vue'
3 | import App from './index'
4 |
5 | const app = new Vue(App)
6 | app.$mount()
--------------------------------------------------------------------------------
/src/pages/pickProtocol/main.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "到店自取用户协议"
3 | }
--------------------------------------------------------------------------------
/src/pages/protocol/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
16 |
17 |
--------------------------------------------------------------------------------
/src/pages/protocol/main.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-09-25 17:10:23 */
2 |
3 | import Vue from 'vue'
4 | import App from './index'
5 |
6 | const app = new Vue(App)
7 | app.$mount()
--------------------------------------------------------------------------------
/src/pages/protocol/main.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "协议及说明"
3 | }
--------------------------------------------------------------------------------
/src/pages/redPacket/data.js:
--------------------------------------------------------------------------------
1 | const redPacket = {
2 | "data": {
3 | "show_steal_entry": 0,
4 | "page_size": 20,
5 | "vp_entrance": {
6 | "text": "",
7 | "bg_url": "",
8 | "sub_text": "",
9 | "link": "",
10 | "buy_status": 0,
11 | "icon_url": "",
12 | "show": false
13 | },
14 | "page_index": 0,
15 | "coupon_total_num": 4,
16 | "has_more": 0,
17 | "coupon_list": [{
18 | "coupon_sign": "",
19 | "status": 1,
20 | "shipping_type": 0,
21 | "coupon_id": -11,
22 | "coupon_key": "",
23 | "coupon_type": 1,
24 | "steal_status": 0,
25 | "poi_exchanged_coupon": 0,
26 | "poi_id": 0,
27 | "amount": 6.0,
28 | "id": -11,
29 | "disable_descriptions": [],
30 | "title": "通用红包",
31 | "use_limits": "限非到店自取订单使用。限登录和收餐手机号为15214313256使用。",
32 | "valid_time_desc": "有效期至2018.09.25",
33 | "coupon_view_id": "syAPBsPPPvyPP&source=tsid=OkPPOkPBt",
34 | "is_premium_type": false,
35 | "category_type": 0,
36 | "price_limit": "满34可用",
37 | "logo_url": ""
38 | }, {
39 | "coupon_sign": "",
40 | "status": 1,
41 | "shipping_type": 0,
42 | "coupon_id": -11,
43 | "coupon_key": "",
44 | "coupon_type": 1,
45 | "steal_status": 0,
46 | "poi_exchanged_coupon": 0,
47 | "poi_id": 0,
48 | "amount": 6.0,
49 | "id": -11,
50 | "disable_descriptions": [],
51 | "title": "狂欢月专属红包",
52 | "use_limits": "限仅限外卖狂欢月部分指定商户可用,微信小程序,非到店自取订单使用。限登录和收餐手机号为15214313256使用。",
53 | "valid_time_desc": "有效期至2018.09.25",
54 | "coupon_view_id": "PtsPBPPtsBvBv&source=tsid=OkPPwKvyP",
55 | "is_premium_type": false,
56 | "category_type": 0,
57 | "price_limit": "满30可用",
58 | "logo_url": ""
59 | }, {
60 | "coupon_sign": "",
61 | "status": 1,
62 | "shipping_type": 0,
63 | "coupon_id": -11,
64 | "coupon_key": "",
65 | "coupon_type": 1,
66 | "steal_status": 0,
67 | "poi_exchanged_coupon": 0,
68 | "poi_id": 0,
69 | "amount": 6.0,
70 | "id": -11,
71 | "disable_descriptions": [],
72 | "title": "狂欢月专属红包",
73 | "use_limits": "限仅限外卖狂欢月部分指定商户可用,微信小程序,非到店自取订单使用。限登录和收餐手机号为15214313256使用。",
74 | "valid_time_desc": "有效期至2018.09.24",
75 | "coupon_view_id": "yOkPPvavyPBsP&source=tsid=OkPPwKtsv",
76 | "is_premium_type": false,
77 | "category_type": 0,
78 | "price_limit": "满30可用",
79 | "logo_url": ""
80 | }, {
81 | "coupon_sign": "",
82 | "status": 1,
83 | "shipping_type": 0,
84 | "coupon_id": -11,
85 | "coupon_key": "",
86 | "coupon_type": 1,
87 | "steal_status": 0,
88 | "poi_exchanged_coupon": 0,
89 | "poi_id": 0,
90 | "amount": 6.0,
91 | "id": -11,
92 | "disable_descriptions": [],
93 | "title": "到店自取专享红包",
94 | "use_limits": "限到店自取订单使用。限登录和收餐手机号为15214313256使用。",
95 | "valid_time_desc": "有效期至2018.09.27",
96 | "coupon_view_id": "PwKvavaPPyABv&source=tsid=OkPBsPsPP",
97 | "is_premium_type": false,
98 | "category_type": 0,
99 | "price_limit": "满30可用",
100 | "logo_url": ""
101 | }]
102 | },
103 | "code": 0,
104 | "msg": "成功"
105 | }
106 |
107 | export {redPacket}
--------------------------------------------------------------------------------
/src/pages/redPacket/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{item.title}}
8 | {{item.valid_time_desc}}
9 |
10 |
11 | ¥{{item.amount}}
12 | {{item.price_limit}}
13 |
14 |
15 |
16 |
17 |
18 |
{{item.use_limits}}
19 |
20 |
21 |
22 | 没有更多有效券了
23 | |
24 | 查看无效券
25 | >>
26 |
27 |
28 |
29 |
30 |
56 |
57 |
151 |
--------------------------------------------------------------------------------
/src/pages/redPacket/main.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-09-18 11:05:33 */
2 | import Vue from 'vue'
3 | import App from './index'
4 |
5 | const app = new Vue(App)
6 | app.$mount()
--------------------------------------------------------------------------------
/src/pages/redPacket/main.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "美团红包"
3 | }
--------------------------------------------------------------------------------
/src/pages/remark/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 0 / 50
7 |
8 |
9 |
10 | {{item}}
11 |
12 |
13 |
14 |
完成
15 |
16 |
17 |
18 |
27 |
28 |
88 |
--------------------------------------------------------------------------------
/src/pages/remark/main.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-09-17 23:03:07 */
2 | import Vue from 'vue'
3 | import App from './index'
4 |
5 | const app = new Vue(App)
6 | app.$mount()
--------------------------------------------------------------------------------
/src/pages/remark/main.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "添加备注"
3 | }
--------------------------------------------------------------------------------
/src/pages/searchList/data.js:
--------------------------------------------------------------------------------
1 | const searchData = {
2 | data: {
3 | "data": {
4 | "labels": [{
5 | "click_url": "",
6 | "label_id": 0,
7 | "label_name": "麻辣烫",
8 | "label_pic_url": "",
9 | "label_type": 12002,
10 | "search_keyword": "麻辣烫",
11 | "show_time_range": "",
12 | "wm_poi_id": 0,
13 | "wm_poi_view_id": ""
14 | }, {
15 | "click_url": "",
16 | "label_id": 0,
17 | "label_name": "瘦肉粥",
18 | "label_pic_url": "",
19 | "label_type": 12001,
20 | "search_keyword": "瘦肉粥",
21 | "show_time_range": "",
22 | "wm_poi_id": 0,
23 | "wm_poi_view_id": ""
24 | }, {
25 | "click_url": "",
26 | "label_id": 0,
27 | "label_name": "卤肉饭",
28 | "label_pic_url": "",
29 | "label_type": 12001,
30 | "search_keyword": "卤肉饭",
31 | "show_time_range": "",
32 | "wm_poi_id": 0,
33 | "wm_poi_view_id": ""
34 | }, {
35 | "click_url": "",
36 | "label_id": 0,
37 | "label_name": "土豆丝",
38 | "label_pic_url": "",
39 | "label_type": 12001,
40 | "search_keyword": "土豆丝",
41 | "show_time_range": "",
42 | "wm_poi_id": 0,
43 | "wm_poi_view_id": ""
44 | }, {
45 | "click_url": "",
46 | "label_id": 0,
47 | "label_name": "小炒肉",
48 | "label_pic_url": "",
49 | "label_type": 12001,
50 | "search_keyword": "小炒肉",
51 | "show_time_range": "",
52 | "wm_poi_id": 0,
53 | "wm_poi_view_id": ""
54 | }, {
55 | "click_url": "",
56 | "label_id": 0,
57 | "label_name": "冷面",
58 | "label_pic_url": "",
59 | "label_type": 12001,
60 | "search_keyword": "冷面",
61 | "show_time_range": "",
62 | "wm_poi_id": 0,
63 | "wm_poi_view_id": ""
64 | }, {
65 | "click_url": "",
66 | "label_id": 0,
67 | "label_name": "粉丝汤",
68 | "label_pic_url": "",
69 | "label_type": 12001,
70 | "search_keyword": "粉丝汤",
71 | "show_time_range": "",
72 | "wm_poi_id": 0,
73 | "wm_poi_view_id": ""
74 | }, {
75 | "click_url": "",
76 | "label_id": 0,
77 | "label_name": "空心菜",
78 | "label_pic_url": "",
79 | "label_type": 12001,
80 | "search_keyword": "空心菜",
81 | "show_time_range": "",
82 | "wm_poi_id": 0,
83 | "wm_poi_view_id": ""
84 | }, {
85 | "click_url": "",
86 | "label_id": 0,
87 | "label_name": "烤翅",
88 | "label_pic_url": "",
89 | "label_type": 12001,
90 | "search_keyword": "烤翅",
91 | "show_time_range": "",
92 | "wm_poi_id": 0,
93 | "wm_poi_view_id": ""
94 | }, {
95 | "click_url": "",
96 | "label_id": 0,
97 | "label_name": "鸡排",
98 | "label_pic_url": "",
99 | "label_type": 12002,
100 | "search_keyword": "鸡排",
101 | "show_time_range": "",
102 | "wm_poi_id": 0,
103 | "wm_poi_view_id": ""
104 | }, {
105 | "click_url": "",
106 | "label_id": 0,
107 | "label_name": "薯条",
108 | "label_pic_url": "",
109 | "label_type": 12001,
110 | "search_keyword": "薯条",
111 | "show_time_range": "",
112 | "wm_poi_id": 0,
113 | "wm_poi_view_id": ""
114 | }, {
115 | "click_url": "",
116 | "label_id": 0,
117 | "label_name": "茄子饭",
118 | "label_pic_url": "",
119 | "label_type": 12001,
120 | "search_keyword": "茄子饭",
121 | "show_time_range": "",
122 | "wm_poi_id": 0,
123 | "wm_poi_view_id": ""
124 | }, {
125 | "click_url": "",
126 | "label_id": 0,
127 | "label_name": "四季豆",
128 | "label_pic_url": "",
129 | "label_type": 12001,
130 | "search_keyword": "四季豆",
131 | "show_time_range": "",
132 | "wm_poi_id": 0,
133 | "wm_poi_view_id": ""
134 | }, {
135 | "click_url": "",
136 | "label_id": 0,
137 | "label_name": "金针菇",
138 | "label_pic_url": "",
139 | "label_type": 12001,
140 | "search_keyword": "金针菇",
141 | "show_time_range": "",
142 | "wm_poi_id": 0,
143 | "wm_poi_view_id": ""
144 | }, {
145 | "click_url": "",
146 | "label_id": 0,
147 | "label_name": "小丸子",
148 | "label_pic_url": "",
149 | "label_type": 12001,
150 | "search_keyword": "小丸子",
151 | "show_time_range": "",
152 | "wm_poi_id": 0,
153 | "wm_poi_view_id": ""
154 | }],
155 | "labels_tgt_stids": "",
156 | "recommend_poi": {
157 | "is_show_change_button": false,
158 | "next_page": 0,
159 | "recommend_poi_list": [],
160 | "tgt_stids": ""
161 | },
162 | "scene_type": "NORMAL",
163 | "searchHotLabelWithTgtStid": {
164 | "sceneType": "NORMAL",
165 | "searchHotLabelList": [{
166 | "click_url": "",
167 | "label_id": 0,
168 | "label_name": "麻辣烫",
169 | "label_pic_url": "",
170 | "label_type": 12002,
171 | "search_keyword": "麻辣烫",
172 | "show_time_range": "",
173 | "wm_poi_id": 0,
174 | "wm_poi_view_id": ""
175 | }, {
176 | "click_url": "",
177 | "label_id": 0,
178 | "label_name": "瘦肉粥",
179 | "label_pic_url": "",
180 | "label_type": 12001,
181 | "search_keyword": "瘦肉粥",
182 | "show_time_range": "",
183 | "wm_poi_id": 0,
184 | "wm_poi_view_id": ""
185 | }, {
186 | "click_url": "",
187 | "label_id": 0,
188 | "label_name": "卤肉饭",
189 | "label_pic_url": "",
190 | "label_type": 12001,
191 | "search_keyword": "卤肉饭",
192 | "show_time_range": "",
193 | "wm_poi_id": 0,
194 | "wm_poi_view_id": ""
195 | }, {
196 | "click_url": "",
197 | "label_id": 0,
198 | "label_name": "土豆丝",
199 | "label_pic_url": "",
200 | "label_type": 12001,
201 | "search_keyword": "土豆丝",
202 | "show_time_range": "",
203 | "wm_poi_id": 0,
204 | "wm_poi_view_id": ""
205 | }, {
206 | "click_url": "",
207 | "label_id": 0,
208 | "label_name": "小炒肉",
209 | "label_pic_url": "",
210 | "label_type": 12001,
211 | "search_keyword": "小炒肉",
212 | "show_time_range": "",
213 | "wm_poi_id": 0,
214 | "wm_poi_view_id": ""
215 | }, {
216 | "click_url": "",
217 | "label_id": 0,
218 | "label_name": "冷面",
219 | "label_pic_url": "",
220 | "label_type": 12001,
221 | "search_keyword": "冷面",
222 | "show_time_range": "",
223 | "wm_poi_id": 0,
224 | "wm_poi_view_id": ""
225 | }, {
226 | "click_url": "",
227 | "label_id": 0,
228 | "label_name": "粉丝汤",
229 | "label_pic_url": "",
230 | "label_type": 12001,
231 | "search_keyword": "粉丝汤",
232 | "show_time_range": "",
233 | "wm_poi_id": 0,
234 | "wm_poi_view_id": ""
235 | }, {
236 | "click_url": "",
237 | "label_id": 0,
238 | "label_name": "空心菜",
239 | "label_pic_url": "",
240 | "label_type": 12001,
241 | "search_keyword": "空心菜",
242 | "show_time_range": "",
243 | "wm_poi_id": 0,
244 | "wm_poi_view_id": ""
245 | }, {
246 | "click_url": "",
247 | "label_id": 0,
248 | "label_name": "烤翅",
249 | "label_pic_url": "",
250 | "label_type": 12001,
251 | "search_keyword": "烤翅",
252 | "show_time_range": "",
253 | "wm_poi_id": 0,
254 | "wm_poi_view_id": ""
255 | }, {
256 | "click_url": "",
257 | "label_id": 0,
258 | "label_name": "鸡排",
259 | "label_pic_url": "",
260 | "label_type": 12002,
261 | "search_keyword": "鸡排",
262 | "show_time_range": "",
263 | "wm_poi_id": 0,
264 | "wm_poi_view_id": ""
265 | }, {
266 | "click_url": "",
267 | "label_id": 0,
268 | "label_name": "薯条",
269 | "label_pic_url": "",
270 | "label_type": 12001,
271 | "search_keyword": "薯条",
272 | "show_time_range": "",
273 | "wm_poi_id": 0,
274 | "wm_poi_view_id": ""
275 | }, {
276 | "click_url": "",
277 | "label_id": 0,
278 | "label_name": "茄子饭",
279 | "label_pic_url": "",
280 | "label_type": 12001,
281 | "search_keyword": "茄子饭",
282 | "show_time_range": "",
283 | "wm_poi_id": 0,
284 | "wm_poi_view_id": ""
285 | }, {
286 | "click_url": "",
287 | "label_id": 0,
288 | "label_name": "四季豆",
289 | "label_pic_url": "",
290 | "label_type": 12001,
291 | "search_keyword": "四季豆",
292 | "show_time_range": "",
293 | "wm_poi_id": 0,
294 | "wm_poi_view_id": ""
295 | }, {
296 | "click_url": "",
297 | "label_id": 0,
298 | "label_name": "金针菇",
299 | "label_pic_url": "",
300 | "label_type": 12001,
301 | "search_keyword": "金针菇",
302 | "show_time_range": "",
303 | "wm_poi_id": 0,
304 | "wm_poi_view_id": ""
305 | }, {
306 | "click_url": "",
307 | "label_id": 0,
308 | "label_name": "小丸子",
309 | "label_pic_url": "",
310 | "label_type": 12001,
311 | "search_keyword": "小丸子",
312 | "show_time_range": "",
313 | "wm_poi_id": 0,
314 | "wm_poi_view_id": ""
315 | }],
316 | "tgtStidMap": {}
317 | },
318 | "search_history_type": []
319 | },
320 | "code": 0,
321 | "msg": "成功"
322 | }
323 | }
324 |
325 | export {searchData}
--------------------------------------------------------------------------------
/src/pages/searchList/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
搜索
13 |
14 |
热门搜索
15 |
16 |
17 |
18 | {{item.label_name}}
19 |
20 |
21 |
22 |
23 |
27 |
28 |
29 |
30 | {{item}}
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
54 |
55 |
194 |
--------------------------------------------------------------------------------
/src/pages/searchList/main.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-09-18 20:01:30 */
2 | import Vue from 'vue'
3 | import App from './index'
4 |
5 | const app = new Vue(App)
6 | app.$mount()
--------------------------------------------------------------------------------
/src/pages/searchList/main.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "搜索"
3 | }
--------------------------------------------------------------------------------
/src/pages/selectAddress/data.js:
--------------------------------------------------------------------------------
1 | const addressData = {
2 | cityData: {
3 | "data": {
4 | "result": "上海市"
5 | },
6 | "code": 0,
7 | "msg": "成功"
8 | },
9 | myAddress: {
10 | "data": [{
11 | "phone": "15214313256",
12 | "can_not_shipping_type": 0,
13 | "category_icon": "",
14 | "gd_addr_type": "",
15 | "is_default": 0,
16 | "address_range_tip": "",
17 | "editable": 1,
18 | "bind_type": 11,
19 | "id": 935908631,
20 | "category": 0,
21 | "can_shipping": 1,
22 | "address": "上海科技绿洲B区18号楼",
23 | "name": "刘光强",
24 | "gender": "先生",
25 | "longitude": 121385976,
26 | "latitude": 31164474,
27 | "address_type": 0
28 | }, {
29 | "phone": "15214313256",
30 | "can_not_shipping_type": 0,
31 | "category_icon": "http://p1.meituan.net/aichequan/459e21821938f624d4b340e6444831f71644.png",
32 | "gd_addr_type": "",
33 | "is_default": 0,
34 | "address_range_tip": "",
35 | "editable": 1,
36 | "bind_type": 15,
37 | "id": 1225134045,
38 | "category": 1,
39 | "can_shipping": 1,
40 | "address": "九星苑",
41 | "name": "刘先生",
42 | "gender": "先生",
43 | "longitude": 121381110,
44 | "latitude": 31150280,
45 | "address_type": 0
46 | }, {
47 | "phone": "15214313256",
48 | "can_not_shipping_type": 0,
49 | "category_icon": "",
50 | "gd_addr_type": "",
51 | "is_default": 0,
52 | "address_range_tip": "",
53 | "editable": 1,
54 | "bind_type": 11,
55 | "id": 684933800,
56 | "category": 0,
57 | "can_shipping": 1,
58 | "address": "广中西路911弄51号",
59 | "name": "光强",
60 | "gender": "先生",
61 | "longitude": 121437016,
62 | "latitude": 31278644,
63 | "address_type": 0
64 | }, {
65 | "phone": "15214313256",
66 | "can_not_shipping_type": 0,
67 | "category_icon": "",
68 | "gd_addr_type": "",
69 | "is_default": 0,
70 | "address_range_tip": "",
71 | "editable": 1,
72 | "bind_type": 11,
73 | "id": 716687722,
74 | "category": 0,
75 | "can_shipping": 1,
76 | "address": "沪太路1067弄11号",
77 | "name": "光强",
78 | "gender": "先生",
79 | "longitude": 121427128,
80 | "latitude": 31277978,
81 | "address_type": 0
82 | }],
83 | "code": 0,
84 | "msg": "成功"
85 | },
86 | nearbyAddress: {
87 | "data": {
88 | "mapPoiVo": [{
89 | "distance": 0.0,
90 | "location": "121.38111,31.15028",
91 | "address": "上海市闵行区东兰路1349弄",
92 | "wm_latitude": 31150280,
93 | "name": "九星苑",
94 | "type": "生活服务;小区",
95 | "wm_longitude": 121381110
96 | }, {
97 | "distance": 0.0,
98 | "location": "121.38175,31.1491",
99 | "address": "上海市闵行区龙茗路1597弄",
100 | "wm_latitude": 31149100,
101 | "name": "东兰·世茗雅苑",
102 | "type": "生活服务;小区",
103 | "wm_longitude": 121381750
104 | }, {
105 | "distance": 0.0,
106 | "location": "121.38156,31.15169",
107 | "address": "上海市闵行区龙茗路1597弄",
108 | "wm_latitude": 31151690,
109 | "name": "东兰雅苑",
110 | "type": "生活服务;小区",
111 | "wm_longitude": 121381560
112 | }, {
113 | "distance": 0.0,
114 | "location": "121.38289,31.15189",
115 | "address": "上海市闵行区古美路",
116 | "wm_latitude": 31151890,
117 | "name": "欧风新天地",
118 | "type": "生活服务;小区",
119 | "wm_longitude": 121382890
120 | }, {
121 | "distance": 0.0,
122 | "location": "121.37997,31.15555",
123 | "address": "上海市闵行区龙茗路2121弄1-35号",
124 | "wm_latitude": 31155550,
125 | "name": "金汇豪庭",
126 | "type": "生活服务;小区",
127 | "wm_longitude": 121379970
128 | }, {
129 | "distance": 0.0,
130 | "location": "121.3575,31.14975",
131 | "address": "上海市闵行区七宝",
132 | "wm_latitude": 31149750,
133 | "name": "七宝",
134 | "type": "",
135 | "wm_longitude": 121357500
136 | }, {
137 | "distance": 0.0,
138 | "location": "121.38302,31.15118",
139 | "address": "上海市闵行区龙茗路1650号(靠近复旦儿科医院)",
140 | "wm_latitude": 31151180,
141 | "name": "莫泰168(九星店)",
142 | "type": "酒店;二星级及以下/经济",
143 | "wm_longitude": 121383020
144 | }, {
145 | "distance": 0.0,
146 | "location": "121.38269,31.15208",
147 | "address": "上海市闵行区龙茗路1662号3楼",
148 | "wm_latitude": 31152080,
149 | "name": "99旅馆连锁(龙茗路店)",
150 | "type": "酒店;二星级及以下/经济",
151 | "wm_longitude": 121382690
152 | }, {
153 | "distance": 0.0,
154 | "location": "121.38573,31.15151",
155 | "address": "上海市闵行区东兰路1111弄",
156 | "wm_latitude": 31151510,
157 | "name": "欧风花都",
158 | "type": "生活服务;小区",
159 | "wm_longitude": 121385730
160 | }, {
161 | "distance": 0.0,
162 | "location": "121.38149,31.1542",
163 | "address": "上海市闵行区龙茗路1891",
164 | "wm_latitude": 31154200,
165 | "name": "和润家园",
166 | "type": "生活服务;小区",
167 | "wm_longitude": 121381490
168 | }],
169 | "count": 1988
170 | },
171 | "code": 0,
172 | "msg": "成功"
173 | }
174 | }
175 |
176 | export {addressData}
--------------------------------------------------------------------------------
/src/pages/selectAddress/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
19 |
20 |
上海市闵行区漕河泾开发区
21 |
22 |
23 | 重新定位
24 |
25 |
26 |
27 |
31 |
32 |
33 |
{{item.address}}
34 |
35 | {{item.name}}
36 | {{item.gender}}
37 | {{item.phone}}
38 |
39 |
40 |
41 |
45 |
46 |
47 |
51 |
52 |
53 | {{item.name}}
54 |
55 |
56 |
57 |
61 |
62 |
63 |
64 |
87 |
88 |
319 |
--------------------------------------------------------------------------------
/src/pages/selectAddress/main.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-09-19 10:21:37 */
2 | import Vue from 'vue'
3 | import App from './index'
4 |
5 | const app = new Vue(App)
6 | app.$mount()
--------------------------------------------------------------------------------
/src/pages/selectAddress/main.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "选择收货地址"
3 | }
--------------------------------------------------------------------------------
/src/pages/share/data.js:
--------------------------------------------------------------------------------
1 | const shareData = {
2 | "code": 0,
3 | "subcode": 0,
4 | "msg": "成功",
5 | "data": {
6 | "title": "15元外卖红包,点击免费领取",
7 | "content": "美团外卖新人专享,领完再去下单吧!",
8 | "invitationUrl": "https://promotion-waimai.meituan.com/invite/page/coupon?inviteCode=cz4Y7DgNjcNbVGmzgXonvicYTQb39OV3TKoA_CaeEqp1qKVb6RyAjStDaMb3K_c1&lq_source=1",
9 | "picUrl": "http://p1.meituan.net/codeman/766984ddf24c10857eb24f00a52084704931.png"
10 | }
11 | }
12 |
13 | export {shareData}
--------------------------------------------------------------------------------
/src/pages/share/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
16 |
17 |
--------------------------------------------------------------------------------
/src/pages/share/main.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-09-25 17:10:23 */
2 |
3 | import Vue from 'vue'
4 | import App from './index'
5 |
6 | const app = new Vue(App)
7 | app.$mount()
--------------------------------------------------------------------------------
/src/pages/share/main.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "邀请好友 各赢红包"
3 | }
--------------------------------------------------------------------------------
/src/pages/shoppingCart/main.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-09-15 14:28:08 */
2 | import Vue from 'vue'
3 | import App from './index'
4 | import store from '@/store'
5 |
6 | const app = new Vue({
7 | store,
8 | ...App
9 | })
10 | app.$mount()
--------------------------------------------------------------------------------
/src/pages/shoppingCart/main.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarBackgroundColor": "white",
3 | "navigationBarTextStyle": "black",
4 | "navigationBarTitleText": "正新汉堡·炸鸡(东兰餐厅店)",
5 | "backgroundColor": "#eeeeee",
6 | "backgroundTextStyle": "light"
7 | }
--------------------------------------------------------------------------------
/src/pages/submitOrder/main.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-09-17 17:31:46 */
2 | import Vue from 'vue'
3 | import App from './index'
4 | import store from '@/store'
5 |
6 | const app = new Vue({
7 | store,
8 | ...App
9 | })
10 | app.$mount()
--------------------------------------------------------------------------------
/src/pages/submitOrder/main.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "提交订单"
3 | }
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-06-29 10:26:46 */
2 |
3 | import Vue from 'vue'
4 | import Vuex from 'vuex'
5 | import shoppingCart from './modules/shoppingCart'
6 |
7 | Vue.use(Vuex)
8 |
9 | const store = new Vuex.Store({
10 | modules: {
11 | shoppingCart: {
12 | namespaced: true,
13 | ...shoppingCart
14 | }
15 | }
16 | })
17 |
18 | export default store
--------------------------------------------------------------------------------
/src/store/modules/shoppingCart.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-09-27 17:32:35 */
2 | import {formatYMD} from '@/utils/formatTime'
3 | import {_array} from '@/utils/arrayExtension'
4 | import {shoppingCart} from '@/pages/shoppingCart/data'
5 | import {deepClone} from '@/utils/deepClone'
6 |
7 | const state = {
8 | shopInfo: {},
9 | foods: [],
10 | spus: [],
11 | commentInfo: [],
12 | reduceFee: 0.0,
13 | visibleSkuModal: false,
14 | visibleItemModal: false,
15 | skuInfo: {},
16 | previewInfo: {}
17 | }
18 |
19 | const mutations = {
20 | changeShopInfoDataMut(state, info) {
21 | state.shopInfo = info
22 | },
23 | changeFoodsDataMut(state, info) {
24 | state.foods = info
25 | },
26 | changeSpusDataMut(state, info) {
27 | state.spus = info;
28 | },
29 | changeCommentDataMut(state, info) {
30 | state.commentInfo = info
31 | },
32 | changeReduceFeeDataMut(state, info) {
33 | state.reduceFee = info
34 | },
35 | changeSkuModalMut(state, info) {
36 | state.visibleSkuModal = info
37 | },
38 | changeItemModalMut(state, info) {
39 | state.visibleItemModal = info
40 | },
41 | changeSkuDataMut(state, info) {
42 | state.skuInfo = info
43 | },
44 | changePreviewDataMut(state, info) {
45 | state.previewInfo = info
46 | }
47 | }
48 |
49 | const actions = {
50 | getMenuDataAction({state, commit}) {
51 | var res = shoppingCart.menuData.data
52 |
53 | var shopInfo = res.poi_info || {}
54 | shopInfo.prompt_text = res.shopping_cart.prompt_text
55 | shopInfo.activity_info = JSON.parse(res.shopping_cart.activity_info.policy)
56 | commit('changeShopInfoDataMut', shopInfo)
57 |
58 | var foods = res.food_spu_tags
59 | foods = foods.map(item => {
60 | item.count = 0
61 | item.totalPrice = 0
62 | return item
63 | })
64 | commit('changeFoodsDataMut', foods)
65 |
66 | var arr = state.foods[0].spus.map(item => {
67 | item.sequence = 0
68 | return item
69 | })
70 | var spus = {title: foods[0].name, index: 0, list: arr}
71 | commit('changeSpusDataMut', spus)
72 | },
73 | getCommentDataAction({state, commit}) {
74 | var res = shoppingCart.commentData.data
75 | var commentData = res
76 | var comments = res.comments.map(item => {
77 | var reply = item.add_comment_list[0] || {}
78 | item.poi_reply_contents = `${reply.desc}:${reply.content}`
79 | item.commentTags = item.comment_labels.map(item => item.content).join()
80 | item.comment_time = formatYMD(item.comment_time * 1000)
81 | return item;
82 | })
83 | commentData.comments = comments
84 |
85 | var commentMolds = res.comment_categories.map(item => {
86 | var num = item.replace(/[^0-9]/ig,"");
87 | var characters = item.match(/[\u4e00-\u9fa5]/g);
88 | var title = characters.join("");
89 | return `${title}(${num})`
90 | })
91 | res.labels.map(item => {
92 | var tag = `${item.content}(${item.label_count})`
93 | commentMolds.push(tag)
94 | })
95 | commentData.commentMolds = commentMolds
96 |
97 | commit('changeCommentDataMut', commentData)
98 | },
99 | getCategoryMenuDataAction({state, commit}, {index}) {
100 | var spus = {}
101 | spus.title = state.foods[index].name
102 | spus.index = index
103 | spus.list = state.foods[index].spus.map(item => {
104 | if (!item.sequence) item.sequence = 0
105 | return item
106 | })
107 | commit('changeSpusDataMut', spus)
108 | },
109 | addItemAction({state, commit}, {item, index}) {
110 | var spus = state.spus
111 | spus.list[index].sequence += 1
112 | commit('changeSpusDataMut', spus)
113 |
114 | var foods = state.foods
115 | var foodsIndex = spus.index
116 | var selectedFood = foods[foodsIndex]
117 | selectedFood.count += 1
118 | selectedFood.totalPrice += item.min_price + (item.min_price > 0 ? 1 : 0 )
119 | commit('changeFoodsDataMut', foods)
120 | },
121 | reduceItemAction({state, commit}, {item, index}) {
122 | var spus = state.spus
123 | spus.list[index].sequence -= 1
124 | if (spus.list[index].sequence <= 0) spus.list[index].sequence = 0
125 | commit('changeSpusDataMut', spus)
126 |
127 | var foods = state.foods
128 | var foodsIndex = spus.index
129 | var selectedFood = foods[foodsIndex]
130 | selectedFood.count = selectedFood.count - 1
131 | selectedFood.totalPrice = selectedFood.totalPrice - item.min_price - (item.min_price > 0 ? 1 : 0)
132 | commit('changeFoodsDataMut', foods)
133 | },
134 | closeShoppingCartAction({state, commit}) {
135 | var array = state.foods
136 | var selectedArr = []
137 | array.map((item, index) => {
138 | item.spus.map((itm, idx) => {
139 | if (itm.sequence > 0) {
140 | var price = itm.min_price * itm.sequence
141 | itm.totalPrice = parseFloat(price).toFixed(1)
142 | selectedArr.push(itm)
143 | }
144 | })
145 | })
146 | var shopInfo = state.shopInfo
147 | shopInfo.selectedArr = selectedArr
148 | commit('changeShopInfoDataMut', shopInfo)
149 | wx.navigateTo({url: '/pages/submitOrder/main'})
150 | },
151 | selectSkuAction({state, commit}, {item, index}) {
152 | commit('changeSkuModalMut', true)
153 | var sku = {}
154 | var array = item.attrs
155 | var selectedItems = []
156 | for (let i = 0; i < array.length; i++) {
157 | var attr = array[i].values
158 | attr.map((item, idx) => {
159 | if (idx === 0) {
160 | item.selected = true;
161 | selectedItems.push(item.value)
162 | } else {
163 | item.selected = false;
164 | }
165 | return item
166 | })
167 | }
168 |
169 | sku.item = item
170 | sku.index = index
171 | sku.attrs = array
172 | sku.title = item.name
173 | sku.selectedCount = item.sequence
174 | sku.price = parseFloat(item.min_price).toFixed(1)
175 | sku.selectedItems = selectedItems.join(',')
176 | sku.time = new Date()
177 | commit('changeSkuDataMut', sku)
178 | },
179 | attrSelectAction({state, commit}, {itm, idx, setIdx}) {
180 | var sku = state.skuInfo
181 | var array = sku.attrs
182 | var selectedItems = sku.selectedItems.split(',')
183 | var section = array[setIdx]
184 | for (var i = 0; i < section.values.length; i++) {
185 | var item = section.values[i]
186 | if (i === idx) {
187 | item.selected = true
188 | selectedItems[setIdx] = item.value
189 | } else {
190 | item.selected = false
191 | }
192 | }
193 | sku.selectedItems = selectedItems.join(',')
194 | sku.time = new Date()
195 | commit('changeSkuDataMut', sku)
196 | },
197 | changeSkuModalDataAction({state, commit}, {num}) {
198 | var sku = state.skuInfo
199 | sku.selectedCount = sku.selectedCount + num
200 | commit('changeSkuDataMut', sku)
201 | },
202 | previewItemAction({state, commit}, {item, index}) {
203 | commit('changeItemModalMut', true)
204 | var preview = item
205 | preview.preIndex = index
206 | preview.description = item.skus[0].description
207 | commit('changePreviewDataMut', preview)
208 | }
209 | }
210 |
211 | const getters = {
212 |
213 | }
214 |
215 | export default {
216 | state,
217 | mutations,
218 | actions,
219 | getters
220 | }
--------------------------------------------------------------------------------
/src/store/modules/submitOrder.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-09-28 23:17:03 */
2 |
--------------------------------------------------------------------------------
/src/store/mutations-type.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-06-29 19:36:01 */
2 |
3 | // 命名规范:模块名+功能
4 | export const ITEM_MOVIE_DETAIL = 'ITEM_MOVIE_DETAIL' // 电影详情
5 | export const ITEM_CLEAR_MOVIE = 'ITEM_CLEAR_MOVIE' // 清除电影详情数据
6 | export const BOARD_MOVIE_LIST = 'BOARD_MOVIE_LIST' // 榜单电影列表
7 | export const LIST_MOVIE_LIST = 'LIST_MOVIE_LIST' // 电影列表
8 | export const LIST_CLEAR_STATE = 'LIST_CLEAR_STATE' // 清除电影列表数据
--------------------------------------------------------------------------------
/src/utils/arrayExtension.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by guangqiang on 2017/8/27.
3 | */
4 |
5 | /** 数组拓展工具类 **/
6 |
7 | const _array = {
8 |
9 | /**
10 | * 往数组中添加元素,若数组中已有此元素,则删除重复元素,添加新的元素
11 | * @param array
12 | * @param item
13 | * @returns {*}
14 | */
15 | update: (array, item) => {
16 | if(!Array.isArray(array)) {
17 | return []
18 | }
19 | for (let i = 0; i < array.length; i++) {
20 | let value = array[i]
21 | if (item === value) {
22 | array.splice(i, 1)
23 | }
24 | }
25 | array.push(item)
26 | return array
27 | },
28 |
29 | /**
30 | * 往数组中添加元素,若数组中有则不再添加
31 | * @param array
32 | * @param item
33 | * @returns {*}
34 | */
35 | add: (array, item) => {
36 | if(!Array.isArray(array)) {
37 | return []
38 | }
39 | for(let i = 0; i < array.length; i++) {
40 | let value = array[i]
41 | if (item === value) {
42 | return array
43 | }
44 | }
45 | array.push(item)
46 | return array
47 | },
48 |
49 | /**
50 | * 往数组中追加元素,元素追加到数组栈底
51 | * @param array
52 | * @param item
53 | * @returns {*}
54 | */
55 | push: (array, item) => {
56 | if(!Array.isArray(array)) {
57 | return []
58 | }
59 | array.push(item)
60 | return array
61 | },
62 |
63 | /**
64 | * 往数组中追加元素,元素追加到数组栈顶
65 | * @param array
66 | * @param item
67 | * @returns {*}
68 | */
69 | unshift: (array, item) => {
70 | if(!Array.isArray(array)) {
71 | return []
72 | }
73 | array.unshift(item)
74 | return array
75 | },
76 |
77 | /**
78 | * 往数组的指定位置插入一个元素
79 | * @param array
80 | * @param location
81 | * @param item
82 | * @returns {*}
83 | * @private
84 | */
85 | _splice: (array, location, item) => {
86 | if(!Array.isArray(array)) {
87 | return []
88 | }
89 | array.splice(location, 0, item)
90 | return array
91 | },
92 |
93 | /**
94 | * 往数组中指定位置插入指定长度个数的元素
95 | * @param array
96 | * @param item
97 | * @param location
98 | * @returns {*}
99 | */
100 | splice_A: (array, location, length, item) => {
101 | if(!Array.isArray(array)) {
102 | return []
103 | }
104 | array.splice(location, length, item)
105 | return array
106 | },
107 |
108 | /**
109 | * 删除数组中指定元素
110 | * @param array
111 | * @param item
112 | * @returns {*}
113 | */
114 | remove: (array, item) => {
115 | if(!Array.isArray(array)) {
116 | return []
117 | }
118 | for(let i = 0; i < array.length; i++) {
119 | let value = array[i]
120 | if (item === value) {
121 | array.splice(i, 1)
122 | }
123 | }
124 | return array
125 | },
126 |
127 | /**
128 | * 删除数组中最后一个元素
129 | * @param array
130 | * @returns {*}
131 | */
132 | pop: (array) => {
133 | if(!Array.isArray(array)) {
134 | return []
135 | }
136 | array.pop()
137 | return array
138 | },
139 |
140 | /**
141 | * 删除数组中第一个元素
142 | * @param array
143 | * @returns {*}
144 | */
145 | shift: (array) => {
146 | if(!Array.isArray(array)) {
147 | return []
148 | }
149 | array.shift()
150 | return array
151 | },
152 |
153 | /**
154 | * 删除数组中指定位置,指定长度的元素
155 | * @param array
156 | * @param location
157 | * @param length
158 | * @returns {*}
159 | */
160 | splice_D: (array, location, length) => {
161 | if(!Array.isArray(array)) {
162 | return []
163 | }
164 | array.splice(location, length)
165 | return array
166 | },
167 |
168 | /**
169 | * 交换数组中两个元素的位置
170 | * @param array
171 | * @param index1
172 | * @param index2
173 | * @returns {*}
174 | */
175 | swapItems: (array, index1, index2) => {
176 | array[index1] = array.splice(index2, 1, array[index1])[0];
177 | return array;
178 | },
179 |
180 | /**
181 | * 将指定位置的元素移至数组栈顶
182 | * @param array
183 | * @param index
184 | * @returns {*}
185 | */
186 | moveItemToFirst: (array, index) => {
187 | var temp = array[index];
188 | if(index == 0) return array;
189 | for (var i = 0; i < array.length; i++) {
190 | if(array[i] === array[index]) {
191 | array.splice(i, 1);
192 | break;
193 | }
194 | }
195 | array.unshift(temp);
196 | return array;
197 | },
198 |
199 | /**
200 | * 判断两个数组是否相等
201 | * @param arr1
202 | * @param arr2
203 | * @returns {boolean}
204 | */
205 | isEqual: (array1, array2) => {
206 | if(!(Array.isArray(array1) && Array.isArray(array2))) {
207 | return false
208 | }
209 | if(array1.length !== array2.length) {
210 | return false
211 | }
212 | for(let i = 0; i < array1.length; i++) {
213 | if (array1[i] !== array2[i]) {
214 | return false
215 | }
216 | }
217 | return true
218 | }
219 | }
220 |
221 | export {_array}
--------------------------------------------------------------------------------
/src/utils/bus.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-08-17 17:29:31 */
2 |
3 | import Vue from 'vue'
4 |
5 | export default new Vue
--------------------------------------------------------------------------------
/src/utils/deepClone.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by guangqiang on 2017/11/24.
3 | */
4 |
5 | function deepClone(data) {
6 |
7 | var obj = {};
8 | var originQueue = [data];
9 | var copyQueue = [obj];
10 | // 以下两个队列用来保存复制过程中访问过的对象,以此来避免对象环的问题(对象的某个属性值是对象本身)
11 | var visitQueue = [];
12 | var copyVisitQueue = [];
13 | while(originQueue.length > 0){
14 | var _data = originQueue.shift();
15 | var _obj = copyQueue.shift();
16 | visitQueue.push(_data);
17 | copyVisitQueue.push(_obj);
18 | for(var key in _data) {
19 | var _value = _data[key]
20 | if(typeof _value !== 'object') {
21 | _obj[key] = _value;
22 | } else {
23 | // 使用indexOf可以发现数组中是否存在相同的对象(实现indexOf的难点就在于对象比较)
24 | var index = visitQueue.indexOf(_value);
25 | if(index >= 0){
26 | _obj[key] = copyVisitQueue[index];
27 | }
28 | originQueue.push(_value);
29 | _obj[key] = {};
30 | copyQueue.push(_obj[key]);
31 | }
32 | }
33 | }
34 | return obj;
35 | }
36 |
37 | export {deepClone}
--------------------------------------------------------------------------------
/src/utils/deviceInfo.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-06-29 10:26:46 */
2 |
3 | /** 设备信息 **/
4 |
5 | const deviceInfo = {
6 | brand: wx.getSystemInfoSync().brand, // 手机型号
7 | model: wx.getSystemInfoSync().model, // 手机品牌,
8 | screenWidth: wx.getSystemInfoSync().screenWidth, // 屏幕宽度
9 | screenHeight: wx.getSystemInfoSync().screenHeight, // 屏幕高度
10 | windowWidth: wx.getSystemInfoSync().windowWidth, // 可使用窗口宽度
11 | windowHeight: wx.getSystemInfoSync().windowHeight, // 可使用窗口高度
12 | statusBarHeight: wx.getSystemInfoSync().statusBarHeight, // 状态栏的高度
13 | language: wx.getSystemInfoSync().language, // 微信设置的语言
14 | version: wx.getSystemInfoSync().version, // 微信版本号
15 | system: wx.getSystemInfoSync().system, // 操作系统版本
16 | platform: wx.getSystemInfoSync().platform, // 客户端平台
17 | fontSizeSetting: wx.getSystemInfoSync().fontSizeSetting, // 用户字体大小设置
18 | SDKVersion: wx.getSystemInfoSync().SDKVersion, // 客户端基础库版本
19 |
20 | // 当前config: debug \ release
21 | // mode: __DEV__ ? 'xdebug' : 'release'
22 | }
23 |
24 | export {deviceInfo}
--------------------------------------------------------------------------------
/src/utils/formatTime.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by guangqiang on 2017/10/3.
3 | */
4 |
5 | function add0(m) {return m < 10 ? '0' + m : m}
6 |
7 | const formatMediaTime = duration => {
8 | let min = Math.floor(duration / 60)
9 | let second = duration - min * 60
10 | min = add0(m)
11 | second = add0(second)
12 | return min + ':' + second
13 | }
14 |
15 | const timeTohhmmss = seconds => {
16 | let hh, mm, ss
17 | if (seconds === null || seconds < 0) return
18 | let pseconds = parseInt(seconds)
19 | hh = pseconds / 3600 | 0
20 | pseconds = parseInt(pseconds) - parseInt(hh) * 3600
21 | hh = add0(parseInt(hh))
22 | if (parseInt(hh) >= 24) hh = "00"
23 | mm = parseInt(pseconds) / 60 | 0
24 | ss = parseInt(pseconds) - parseInt(mm) * 60
25 | mm = add0(parseInt(mm))
26 | ss = add0(parseInt(ss))
27 | return hh + ":" + mm + ":" + ss
28 | }
29 |
30 | const getTodayDate = () => {
31 | let now = new Date()
32 | let yy = now.getFullYear()
33 | let mm = now.getMonth() + 1
34 | let dd = now.getDate()
35 | let day = new Array()
36 | day[0] = "星期日"
37 | day[1] = "星期一"
38 | day[2] = "星期二"
39 | day[3] = "星期三"
40 | day[4] = "星期四"
41 | day[5] = "星期五"
42 | day[6] = "星期六"
43 | return (yy + '年' + mm + '月' + dd + '日 ' + day[now.getDay()])
44 | }
45 |
46 | const timestampToCommonDate = timestamp => {
47 | var time = new Date(timestamp);
48 | var y = time.getFullYear();
49 | var m = time.getMonth() + 1;
50 | var d = time.getDate();
51 | var h = time.getHours();
52 | var mm = time.getMinutes();
53 | var s = time.getSeconds();
54 | return y + '-' + add0(m) + '-' + add0(d) + ' ' + add0(h) + ':' + add0(mm) + ':' + add0(s);
55 | }
56 |
57 | const formatTime = date => {
58 | const year = date.getFullYear()
59 | const month = date.getMonth() + 1
60 | const day = date.getDate()
61 | const hour = date.getHours()
62 | const minute = date.getMinutes()
63 | const second = date.getSeconds()
64 | const t1 = [year, month, day].map(formatNumber).join('/')
65 | const t2 = [hour, minute, second].map(formatNumber).join(':')
66 | return `${t1} ${t2}`
67 | }
68 |
69 | const formatYMD = timestamp => {
70 | const date = new Date(timestamp)
71 | const year = date.getFullYear()
72 | const month = add0(date.getMonth() + 1)
73 | const day = add0(date.getDate())
74 | return `${year}-${month}-${day}`
75 | }
76 |
77 | const dateFormatTimestamp = DATE => {
78 | var date = new Date(DATE).setHours(0, 0, 0, 0);
79 | return date
80 | }
81 |
82 | const getTimeInfo = str => {
83 | if (!str) return ''
84 | const date = new Date(str);
85 | const time = new Date().getTime() - date.getTime();
86 | if (time < 0) {
87 | return '';
88 | } else if (time / 1000 < 60) {
89 | return '刚刚';
90 | } else if ((time / 60000) < 60) {
91 | return parseInt((time / 60000)) + '分钟前';
92 | } else if ((time / 3600000) < 24) {
93 | return parseInt(time / 3600000) + '小时前';
94 | } else if ((time / 86400000) < 31) {
95 | return parseInt(time / 86400000) + '天前';
96 | } else if ((time / 2592000000) < 12) {
97 | return parseInt(time / 2592000000) + '月前';
98 | } else {
99 | return parseInt(time / 31536000000) + '年前';
100 | }
101 | }
102 |
103 | const seckillCountdown = timer => {
104 | var deadLine = timer
105 | var newData = new Date().getTime();
106 | var rightTime = deadLine - newData;
107 | var dd = '00',
108 | hh = '00',
109 | mm = '00',
110 | ss = '00';
111 | if (rightTime > 0) {
112 | dd = Math.floor(rightTime / 1000 / 60 / 60 / 24);
113 | hh = Math.floor((rightTime / 1000 / 60 / 60) % 24);
114 | mm = Math.floor((rightTime / 1000 / 60) % 60);
115 | ss = Math.floor((rightTime / 1000) % 60);
116 | hh = add0(parseInt(hh))
117 | mm = add0(parseInt(mm))
118 | ss = add0(parseInt(ss))
119 | }
120 | var seckill = dd + "天" + hh + "小时" + mm + "分" + ss + "秒"
121 | var over = Object.assign({}, {
122 | dd,
123 | hh,
124 | mm,
125 | ss,
126 | seckill
127 | })
128 | return over;
129 | }
130 |
131 | const yesterdayDate = currentDate => {
132 | var preDate = new Date(currentDate.getTime() - 24 * 60 * 60 * 1000);
133 | return preDate
134 | }
135 |
136 | const tomorrowDate = currentDate => {
137 | var nextDate = new Date(currentDate.getTime() + 24 * 60 * 60 * 1000);
138 | return nextDate
139 | }
140 |
141 | const nDayAgo = (t, n) => {
142 | // let now = new Date().getTime()
143 | var date = new Date(t - n * 24 * 60 * 60 * 1000);
144 | return date
145 | }
146 |
147 | const nDayLater = (t, n) => {
148 | var date = new Date(t + n * 24 * 60 * 60 * 1000);
149 | return date
150 | }
151 |
152 | export {
153 | formatMediaTime,
154 | timeTohhmmss,
155 | getTodayDate,
156 | formatTime,
157 | getTimeInfo,
158 | seckillCountdown,
159 | formatYMD,
160 | dateFormatTimestamp,
161 | yesterdayDate,
162 | tomorrowDate,
163 | nDayAgo,
164 | nDayLater,
165 | timestampToCommonDate
166 | }
--------------------------------------------------------------------------------
/src/utils/index.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-06-29 18:10:51 */
2 |
3 | import {deviceInfo} from './deviceInfo'
4 | import {RegExpr} from './regex'
5 | import {_array} from './arrayExtension'
6 | import toast from './toast'
7 | import {deepClone} from './deepClone'
8 | import Bus from './bus'
9 | import * as wxapi from './wxapi'
10 | import * as _string from './stringExtension'
11 | import * as formatTime from './formatTime'
12 |
13 | export {deviceInfo, RegExpr, _array, toast, deepClone, Bus, wxapi, _string, formatTime}
--------------------------------------------------------------------------------
/src/utils/mta_analysis.js:
--------------------------------------------------------------------------------
1 | var MTA_CONFIG={app_id:"",event_id:"",api_base:"https://pingtas.qq.com/pingd",prefix:"_mta_",version:"1.3.5",stat_share_app:!1,stat_pull_down_fresh:!1,stat_reach_bottom:!1};function getNetworkType(a){wx.getNetworkType({success:function(b){a(b.networkType)}})}function getSystemInfo(){var a=wx.getSystemInfoSync();return{adt:encodeURIComponent(a.model),scl:a.pixelRatio,scr:a.windowWidth+"x"+a.windowHeight,lg:a.language,fl:a.version,jv:encodeURIComponent(a.system),tz:encodeURIComponent(a.platform)}}
2 | function getUID(){try{return wx.getStorageSync(MTA_CONFIG.prefix+"auid")}catch(a){}}function setUID(){try{var a=getRandom();wx.setStorageSync(MTA_CONFIG.prefix+"auid",a);return a}catch(b){}}function getSID(){try{return wx.getStorageSync(MTA_CONFIG.prefix+"ssid")}catch(a){}}function setSID(){try{var a="s"+getRandom();wx.setStorageSync(MTA_CONFIG.prefix+"ssid",a);return a}catch(b){}}
3 | function getRandom(a){for(var b=[0,1,2,3,4,5,6,7,8,9],c=10;1c;c++)d=10*d+b[c];return(a||"")+(d+""+ +new Date)}function getPagePath(){try{var a=getCurrentPages(),b="/";0 {
13 | return /^[1][0-9]{10}$/.test(mobile)
14 | },
15 |
16 | /**
17 | * 校验纯数字
18 | * @param num
19 | * @returns {boolean}
20 | */
21 | checkNum: num => {
22 | return /^[0-9]+$/.test(num)
23 | },
24 |
25 | /**
26 | * 校验用户名:1-20位字符,首字符为字母
27 | * @param str
28 | * @returns {RegExp}
29 | */
30 | checkUserName: str => {
31 | return /^[a-zA-Z]{1,20}$/.test(str)
32 | },
33 |
34 | /**
35 | * 校验密码:6-20位,数字、字母、下划线
36 | * @param str
37 | * @returns {boolean}
38 | */
39 | checkPwd: str => {
40 | return /^(\\w){6,20}$/.test(str)
41 | },
42 |
43 | /**
44 | * 校验正整数 + 0
45 | * @param num
46 | * @returns {boolean}
47 | */
48 | checkPositiveInteger: num => {
49 | return /^[0-9]*[1-9][0-9]*$/.test(num)
50 | },
51 |
52 | /**
53 | * 校验字符串是否为数字
54 | * @param str
55 | * @returns {boolean}
56 | */
57 | isNumber: str => {
58 | var regPos = /^\d+(\.\d+)?$/; //非负浮点数
59 | var regNeg = /^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$/; //负浮点数
60 | if (regPos.test(str) || regNeg.test(str)) {
61 | return true;
62 | } else {
63 | return false;
64 | }
65 | }
66 | }
67 |
68 | export {
69 | RegExpr
70 | }
--------------------------------------------------------------------------------
/src/utils/stringExtension.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-07-22 22:38:29 */
2 |
3 | const isEmptyStr = str => {
4 | if (str == null || str == undefined || str == '') {
5 | return true
6 | } else {
7 | return false
8 | }
9 | }
10 |
11 | const isEmptyObj = obj => {
12 | if (typeof (obj) === 'object') {
13 | return !obj || (Array.isArray(obj) && obj.length === 0) || (obj.toString() === '[object Object]' && Object.keys(obj).length === 0);
14 | }
15 | if (typeof (obj) === 'boolean' || typeof (obj) === 'number') {
16 | return false;
17 | }
18 | if (typeof (obj) === 'string' && obj.trim().length === 0) {
19 | return true;
20 | }
21 | return !obj;
22 | }
23 |
24 | export {
25 | isEmptyStr,
26 | isEmptyObj
27 | }
--------------------------------------------------------------------------------
/src/utils/style.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-07-02 14:57:01 */
2 |
3 | const jointStyle = style => {
4 | let str = []
5 | Object.keys(style).forEach(key => {
6 | str.push(`${key}:${style[key]};`)
7 | })
8 | return str.join(';');
9 | }
10 |
11 | export {jointStyle}
12 |
--------------------------------------------------------------------------------
/src/utils/toast.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-06-29 19:58:09 */
2 |
3 | // toast 工具类
4 | class toast {
5 |
6 | static msg (title, {icon = 1}) {
7 | wx.showToast({
8 | title,
9 | icon: ['success', 'none'][icon]
10 | })
11 | }
12 |
13 | static confirm ({title = '提示', content, callback}) {
14 | wx.showModal({
15 | title,
16 | content,
17 | success: function (res) {
18 | if (res.confirm) {
19 | callback(res.confirm)
20 | } else if (res.cancel) {
21 | console.log('用户点击取消')
22 | }
23 | }
24 | })
25 | }
26 | }
27 |
28 | export default toast
--------------------------------------------------------------------------------
/src/utils/wxapi.js:
--------------------------------------------------------------------------------
1 | /** Created by guangqiang on 2018-06-29 18:17:42 */
2 |
3 | import {timestampToCommonDate} from "@/utils/formatTime"
4 | import {_array} from "@/utils/arrayExtension"
5 |
6 | const getStorage = key => new Promise((resolve, reject) => {
7 | wx.getStorage({
8 | key: key,
9 | success (res) {
10 | resolve(res.data)
11 | },
12 | fail (e) {
13 | reject(e)
14 | }
15 | })
16 | })
17 |
18 | const setStorage = (key, value) => new Promise((resolve, reject) => {
19 | wx.setStorage({
20 | key: key,
21 | data: value,
22 | success () {
23 | resolve()
24 | },
25 | fail (e) {
26 | reject(e)
27 | }
28 | })
29 | })
30 |
31 | const removeStorage = key => new Promise((resolve, reject) => {
32 | wx.removeStorage({
33 | key: key,
34 | success (res) {
35 | resolve(res.data)
36 | },
37 | fail (e) {
38 | reject(e)
39 | }
40 | })
41 | })
42 |
43 | const clearStorage = () => new Promise((resolve, reject) => {
44 | try {
45 | wx.clearStorageSync()
46 | resolve()
47 | } catch (e) {
48 | reject(e)
49 | }
50 | })
51 |
52 | const getLocation = () => new Promise((resolve) => {
53 | wx.getLocation({
54 | type: "wgs84",
55 | success ({ latitude, longitude, speed, accuracy }) {
56 | resolve({ latitude, longitude, speed, accuracy })
57 | },
58 | fail () {
59 | resolve({
60 | latitude: -999,
61 | longitude: -999
62 | })
63 | }
64 | })
65 | })
66 |
67 | const chooseLocation = () => new Promise((resolve, reject) => {
68 | wx.chooseLocation({
69 | success (res) {
70 | resolve(res)
71 | },
72 | fail (e) {
73 | reject(e)
74 | }
75 | })
76 | })
77 |
78 | const openLocation = ({latitude, longitude}) => new Promise((resolve, reject) => {
79 | wx.openLocation({
80 | latitude: latitude,
81 | longitude: longitude,
82 | scale: 18,
83 | success: function(res) {
84 | resolve(res)
85 | },
86 | fail: function(e) {
87 | reject(e)
88 | }
89 | })
90 | })
91 |
92 | const login = () => new Promise((resolve, reject) => {
93 | wx.login({
94 | success (res) {
95 | resolve(res)
96 | },
97 | fail (e) {
98 | reject(e)
99 | }
100 | })
101 | })
102 |
103 | const getUserInfo = obj => new Promise((resolve, reject) => {
104 | wx.getUserInfo({
105 | ...obj,
106 | success (res) {
107 | resolve(res)
108 | },
109 | fail (e) {
110 | reject(e)
111 | }
112 | })
113 | })
114 |
115 | const addCard = (cardId = '', cardExt = '', ) => new Promise((resolve, reject) => {
116 | wx.addCard({
117 | cardList: [
118 | {
119 | cardId: cardId,
120 | cardExt: cardExt
121 | }
122 | ],
123 | success: function(res) {
124 | resolve(res)
125 | },
126 | fail: function(e) {
127 | reject(e)
128 | }
129 | })
130 | })
131 |
132 | const chooseImage = (count = 1, sourceType = ['album']) => new Promise((resolve, reject) => {
133 | wx.chooseImage({
134 | count,
135 | sourceType,
136 | success (res) {
137 | resolve(res)
138 | },
139 | fail (e) {
140 | reject(e)
141 | }
142 | })
143 | })
144 |
145 | const handleScan = () => new Promise((resolve, reject) => {
146 | wx.scanCode({
147 | success: function(res) {
148 | resolve(res)
149 | },
150 | fail: function(e) {
151 | reject(e)
152 | }
153 | })
154 | })
155 |
156 | const showModal = (title, content, isCancel) => new Promise(resolve => {
157 | wx.showModal({
158 | title: title,
159 | content: content,
160 | showCancel: isCancel,
161 | success: function(res) {
162 | if (res.confirm) {
163 | resolve('ok')
164 | } else if (res.cancel) {
165 | resolve('cancle')
166 | }
167 | }
168 | })
169 | })
170 |
171 | const toast = content => new Promise((resolve, reject) => {
172 | wx.showToast({
173 | title: content,
174 | icon: 'none',
175 | duration: 4000,
176 | success: function(res) {
177 | resolve(res)
178 | },
179 | fail: function(e) {
180 | reject(e)
181 | }
182 | })
183 | })
184 |
185 | const toastSuccess = content => new Promise((resolve, reject) => {
186 | wx.showToast({
187 | title: content,
188 | icon: 'success',
189 | duration: 3000,
190 | success: function(res) {
191 | resolve(res)
192 | },
193 | fail: function(e) {
194 | reject(e)
195 | }
196 | })
197 | })
198 |
199 | const actionSheet = items => new Promise((resolve, reject) => {
200 | wx.showActionSheet({
201 | itemList: items,
202 | success: function(res) {
203 | resolve(res.tapIndex)
204 | },
205 | fail: function(e) {
206 | reject(e)
207 | }
208 | })
209 | })
210 |
211 | const showShareMenu = () => {
212 | return wx.showShareMenu
213 | }
214 |
215 | const pageScrollTo = () => {
216 | return wx.pageScrollTo
217 | }
218 |
219 | const alert = content => new Promise((resolve, reject) => {
220 | wx.showModal({
221 | title: '',
222 | content,
223 | showCancel: false,
224 | success: function(res) {
225 | resolve(res)
226 | },
227 | fail: function(e) {
228 | reject(e)
229 | }
230 | })
231 | })
232 |
233 | const navigateTo = url => {
234 | wx.navigateTo({
235 | url
236 | })
237 | }
238 |
239 | const redirectTo = url => {
240 | wx.redirectTo({
241 | url: url
242 | })
243 | }
244 |
245 | const startPullDownRefresh = () => new Promise((resolve, reject) => {
246 | wx.startPullDownRefresh({
247 | success (res) {
248 | resolve(res)
249 | },
250 | fail (e) {
251 | reject(e)
252 | }
253 | })
254 | })
255 |
256 | const stopPullDownRefresh = () => new Promise((resolve, reject) => {
257 | wx.stopPullDownRefresh({
258 | success (res) {
259 | resolve(res)
260 | },
261 | fail (e) {
262 | reject(e)
263 | }
264 | })
265 | })
266 |
267 | const request = params => new Promise((resolve, reject) => {
268 | wx.showNavigationBarLoading()
269 | const beforeRequest = new Date().getTime()
270 | wx.request({
271 | url: params.url,
272 | data: params.data,
273 | header: {'Content-Type': 'application/json', ...params.header},
274 | method: params.method,
275 | success: function(res) {
276 | let isSuccess = false
277 | if (parseInt(res.statusCode / 100) == 2) {
278 | if (res.data.code == 0) {
279 | isSuccess = true
280 | }
281 | }
282 |
283 | let response = res.data
284 | response.statusCode = res.statusCode
285 | const pages = getCurrentPages()
286 | const currentPage = pages[pages.length - 1]
287 | const route = currentPage.route
288 | const networkType = wx.getStorageSync('networkType')
289 | const afterRequest = new Date().getTime()
290 | const timeDif = afterRequest - beforeRequest
291 | var networkArr = wx.getStorageSync('networkArr') || []
292 | if (networkArr.length >= 30) {
293 | wx.removeStorageSync('networkArr')
294 | networkArr = []
295 | }
296 | var time = timestampToCommonDate(new Date().getTime())
297 | networkArr = _array.unshift(networkArr, {url: params.url, params: params.data, res: response, time, route, timeDif, networkType, isSuccess})
298 | wx.setStorageSync('networkArr', networkArr)
299 |
300 | if (!isSuccess) {
301 | wx.showToast({
302 | title: res.data.message,
303 | icon: 'none',
304 | duration: 4000
305 | })
306 | }
307 | wx.hideNavigationBarLoading()
308 | resolve(res.data)
309 | },
310 | fail: function(e) {
311 | const pages = getCurrentPages()
312 | const currentPage = pages[pages.length - 1]
313 | const route = currentPage.route
314 | const networkType = wx.getStorageSync('networkType')
315 | const afterRequest = new Date().getTime()
316 | const timeDif = afterRequest - beforeRequest
317 | var networkArr = wx.getStorageSync('networkArr') || []
318 | if (networkArr.length >= 30) {
319 | wx.removeStorageSync('networkArr')
320 | networkArr = []
321 | }
322 | var time = timestampToCommonDate(new Date().getTime())
323 | networkArr = _array.unshift(networkArr, {url, params, res: e, time, route, timeDif, networkType, isSuccess: false})
324 | wx.setStorageSync('networkArr', networkArr)
325 |
326 | wx.showToast({
327 | title: e.errMsg,
328 | icon: 'none',
329 | duration: 4000
330 | })
331 | wx.hideNavigationBarLoading()
332 | reject(e)
333 | }
334 | })
335 | })
336 |
337 | const checkNetWork = () => new Promise((resolve, reject) => {
338 | wx.getNetworkType({
339 | success: function(res) {
340 | let networkType = res.networkType
341 | if (networkType === 'none' || networkType === 'unknown') {
342 | resolve(false)
343 | } else {
344 | resolve(true)
345 | }
346 | },
347 | fail: function(e) {
348 | resolve(false)
349 | }
350 | })
351 | })
352 |
353 | const uploadFile = params => new Promise((resolve, reject) => {
354 | wx.uploadFile({
355 | ...params,
356 | success: function(res) {
357 | resolve(res)
358 | },
359 | fail: function(e) {
360 | reject(e)
361 | }
362 | })
363 | })
364 |
365 | const saveImage = url => {
366 | wx.downloadFile({
367 | url: url,
368 | success: function(res) {
369 | let path = res.tempFilePath;
370 | wx.saveImageToPhotosAlbum({
371 | filePath: path,
372 | success(res) {
373 | toastSuccess('保存成功!')
374 | },
375 | fail(res) {
376 | toast('保存失败!')
377 | }
378 | });
379 | },
380 | fail: function(res) {
381 | toast('保存失败!')
382 | }
383 | });
384 | }
385 |
386 | const checkSession = () => new Promise((resolve, reject) => {
387 | wx.checkSession({
388 | success: function() {
389 | // session_key 未过期,并且在本生命周期一直有效
390 | resolve(true)
391 | },
392 | fail: function() {
393 | // session_key 已经失效,需要重新执行登录流程
394 | resolve(false)
395 | }
396 | })
397 | })
398 |
399 | export {
400 | getStorage,
401 | setStorage,
402 | getLocation,
403 | chooseLocation,
404 | openLocation,
405 | removeStorage,
406 | clearStorage,
407 | login,
408 | request,
409 | chooseImage,
410 | showShareMenu,
411 | pageScrollTo,
412 | getUserInfo,
413 | alert,
414 | navigateTo,
415 | redirectTo,
416 | startPullDownRefresh,
417 | stopPullDownRefresh,
418 | uploadFile,
419 | handleScan,
420 | checkNetWork,
421 | addCard,
422 | showModal,
423 | toast,
424 | toastSuccess,
425 | actionSheet,
426 | saveImage,
427 | checkSession
428 | }
--------------------------------------------------------------------------------
/static/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Umbrella001/mpvue-meituan/ea9c57fce44c762edaa10114316ac91b20f27773/static/.gitkeep
--------------------------------------------------------------------------------
/static/images/icon_tabbar_home@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Umbrella001/mpvue-meituan/ea9c57fce44c762edaa10114316ac91b20f27773/static/images/icon_tabbar_home@3x.png
--------------------------------------------------------------------------------
/static/images/icon_tabbar_home_selected@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Umbrella001/mpvue-meituan/ea9c57fce44c762edaa10114316ac91b20f27773/static/images/icon_tabbar_home_selected@3x.png
--------------------------------------------------------------------------------
/static/images/icon_tabbar_mine@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Umbrella001/mpvue-meituan/ea9c57fce44c762edaa10114316ac91b20f27773/static/images/icon_tabbar_mine@3x.png
--------------------------------------------------------------------------------
/static/images/icon_tabbar_mine_selected@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Umbrella001/mpvue-meituan/ea9c57fce44c762edaa10114316ac91b20f27773/static/images/icon_tabbar_mine_selected@3x.png
--------------------------------------------------------------------------------
/static/images/icon_tabbar_order@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Umbrella001/mpvue-meituan/ea9c57fce44c762edaa10114316ac91b20f27773/static/images/icon_tabbar_order@3x.png
--------------------------------------------------------------------------------
/static/images/icon_tabbar_order_selected@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Umbrella001/mpvue-meituan/ea9c57fce44c762edaa10114316ac91b20f27773/static/images/icon_tabbar_order_selected@3x.png
--------------------------------------------------------------------------------