├── .DS_Store ├── client ├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .postcssrc.js ├── 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 │ └── webpack.test.conf.js ├── config │ ├── api.config.js │ ├── dev.env.js │ ├── index.js │ ├── prod.env.js │ └── test.env.js ├── index.html ├── mock │ └── goods.json ├── package.json ├── src │ ├── App.vue │ ├── api │ │ └── index.js │ ├── assets │ │ ├── css │ │ │ ├── app.css │ │ │ ├── base.css │ │ │ ├── checkout.css │ │ │ ├── login.css │ │ │ ├── product.css │ │ │ └── style.css │ │ ├── img │ │ │ ├── 1.jpg │ │ │ ├── 10.jpg │ │ │ ├── 11.jpg │ │ │ ├── 12.jpg │ │ │ ├── 13.jpg │ │ │ ├── 14.jpg │ │ │ ├── 15.jpg │ │ │ ├── 16.jpg │ │ │ ├── 2.jpg │ │ │ ├── 3.jpg │ │ │ ├── 4.jpg │ │ │ ├── 5.jpg │ │ │ ├── 6.jpg │ │ │ ├── 7.jpg │ │ │ ├── 8.jpg │ │ │ ├── 9.jpg │ │ │ ├── bnt_subOrder.gif │ │ │ ├── icon.png │ │ │ ├── logo-footer.png │ │ │ ├── logo.gif │ │ │ ├── logo.png │ │ │ ├── mi6.jpg │ │ │ ├── note.jpg │ │ │ ├── ok-2.png │ │ │ ├── photo.jpg │ │ │ ├── pingheng.jpg │ │ │ ├── user_purchase20150409154845.gif │ │ │ ├── v-face1.jpg │ │ │ ├── v-face2.jpg │ │ │ ├── v-face3.jpg │ │ │ ├── v-face4.jpg │ │ │ ├── vn-logo.png │ │ │ ├── vn_logo.png │ │ │ └── zipai.jpg │ │ └── logo.png │ ├── components │ │ ├── Footer.vue │ │ ├── Head.vue │ │ ├── Hello.vue │ │ ├── Modal.vue │ │ └── NavBread.vue │ ├── main.js │ ├── router │ │ └── index.js │ └── view │ │ ├── Address.vue │ │ ├── Cart.vue │ │ ├── GoodsList.vue │ │ ├── OrderConfirm.vue │ │ ├── OrderSuccess.vue │ │ └── user │ │ └── index.vue ├── static │ ├── .gitkeep │ ├── images │ │ ├── 201507 │ │ │ ├── 27_thumb_G_1437074702008.jpg │ │ │ ├── 28_thumb_G_1437074792369.jpg │ │ │ ├── 29_thumb_G_1437074933275.jpg │ │ │ ├── 30_thumb_G_1437075007558.jpg │ │ │ ├── 31_thumb_G_1437075539254.jpg │ │ │ ├── 32_thumb_G_1437075765802.jpg │ │ │ ├── 33_thumb_G_1437075865379.jpg │ │ │ ├── 34_thumb_G_1437076036973.jpg │ │ │ ├── 35_thumb_G_1437081702649.jpg │ │ │ ├── 36_thumb_G_1437082145888.jpg │ │ │ ├── 37_thumb_G_1437082214575.jpg │ │ │ ├── 38_thumb_G_1437082667838.jpg │ │ │ ├── 39_thumb_G_1437082747983.jpg │ │ │ ├── 40_thumb_G_1437082798686.jpg │ │ │ ├── 41_thumb_G_1437082849514.jpg │ │ │ ├── 42_thumb_G_1437082936092.jpg │ │ │ ├── 43_thumb_G_1437091900155.jpg │ │ │ ├── 44_thumb_G_1437092148601.jpg │ │ │ ├── 45_thumb_G_1437092199733.jpg │ │ │ └── 46_thumb_G_1437092278369.jpg │ │ ├── 201508 │ │ │ ├── 47_thumb_G_1439331077002.jpg │ │ │ ├── 53_thumb_G_1439511514539.jpg │ │ │ ├── 56_thumb_G_1440717641715.jpg │ │ │ ├── 57_thumb_G_1440717888680.jpg │ │ │ ├── 59_thumb_G_1440983020324.jpg │ │ │ ├── 60_thumb_G_1440983103483.jpg │ │ │ ├── 64_thumb_G_1440983246324.jpg │ │ │ ├── 65_thumb_G_1440983430401.jpg │ │ │ ├── 66_thumb_G_1440983490045.jpg │ │ │ ├── 67_thumb_G_1440983638116.jpg │ │ │ ├── 68_thumb_G_1440983695997.jpg │ │ │ ├── 69_thumb_G_1440983751530.jpg │ │ │ ├── 70_thumb_G_1440983810214.jpg │ │ │ ├── 71_thumb_G_1440983839269.jpg │ │ │ ├── 72_thumb_G_1440983887661.jpg │ │ │ ├── 73_thumb_G_1440983937959.jpg │ │ │ ├── 74_thumb_G_1440983959230.jpg │ │ │ ├── 75_thumb_G_1440984011595.jpg │ │ │ ├── 76_thumb_G_1440984280864.jpg │ │ │ └── 77_thumb_G_1440984390480.jpg │ │ └── 201509 │ │ │ ├── 101_thumb_G_1441738730692.jpg │ │ │ ├── 102_thumb_G_1441738765271.jpg │ │ │ ├── 103_thumb_G_1441738795942.jpg │ │ │ ├── 78_thumb_G_1441050387337.jpg │ │ │ ├── 79_thumb_G_1441050485953.jpg │ │ │ ├── 80_thumb_G_1441050558701.jpg │ │ │ ├── 81_thumb_G_1441050609661.jpg │ │ │ ├── 82_thumb_G_1441050801926.jpg │ │ │ ├── 83_thumb_G_1441052403875.jpg │ │ │ ├── 84_thumb_G_1441056023645.jpg │ │ │ ├── 85_thumb_G_1441056112107.jpg │ │ │ ├── 86_thumb_G_1441056239670.jpg │ │ │ ├── 87_thumb_G_1441056303542.jpg │ │ │ ├── 88_thumb_G_1441056484072.jpg │ │ │ ├── 89_thumb_G_1441056597778.jpg │ │ │ ├── 90_thumb_G_1441056659073.jpg │ │ │ ├── 91_thumb_G_1441056702928.jpg │ │ │ ├── 92_thumb_G_1441056728120.jpg │ │ │ ├── 93_thumb_G_1441056767939.jpg │ │ │ ├── 94_thumb_G_1441056891849.jpg │ │ │ ├── 96_thumb_G_1441738537157.jpg │ │ │ └── 98_thumb_G_1441738620606.jpg │ └── img │ │ ├── 1.jpg │ │ ├── 10.jpg │ │ ├── 11.jpg │ │ ├── 12.jpg │ │ ├── 13.jpg │ │ ├── 14.jpg │ │ ├── 15.jpg │ │ ├── 16.jpg │ │ ├── 2.jpg │ │ ├── 3.jpg │ │ ├── 4.jpg │ │ ├── 5.jpg │ │ ├── 6.jpg │ │ ├── 7.jpg │ │ ├── 8.jpg │ │ ├── 9.jpg │ │ ├── bnt_subOrder.gif │ │ ├── icon.png │ │ ├── logo-footer.png │ │ ├── logo.gif │ │ ├── logo.png │ │ ├── mi6.jpg │ │ ├── note.jpg │ │ ├── ok-2.png │ │ ├── photo.jpg │ │ ├── pingheng.jpg │ │ ├── user_purchase20150409154845.gif │ │ ├── v-face1.jpg │ │ ├── v-face2.jpg │ │ ├── v-face3.jpg │ │ ├── v-face4.jpg │ │ ├── vn-logo.png │ │ ├── vn_logo.1.png │ │ ├── vn_logo.png │ │ └── zipai.jpg └── test │ ├── e2e │ ├── custom-assertions │ │ └── elementCount.js │ ├── nightwatch.conf.js │ ├── runner.js │ └── specs │ │ └── test.js │ └── unit │ ├── .eslintrc │ ├── index.js │ ├── karma.conf.js │ └── specs │ └── Hello.spec.js ├── node_modules ├── debug │ ├── .coveralls.yml │ ├── .eslintrc │ ├── .npmignore │ ├── .travis.yml │ ├── CHANGELOG.md │ ├── LICENSE │ ├── Makefile │ ├── README.md │ ├── component.json │ ├── karma.conf.js │ ├── node.js │ ├── package.json │ └── src │ │ ├── browser.js │ │ ├── debug.js │ │ ├── index.js │ │ ├── inspector-log.js │ │ └── node.js ├── jsonp │ ├── .npmignore │ ├── .travis.yml │ ├── .zuul.yml │ ├── History.md │ ├── Readme.md │ ├── bower.json │ ├── component.json │ ├── index.js │ ├── package.json │ └── test │ │ └── basic.js └── ms │ ├── index.js │ ├── license.md │ ├── package.json │ └── readme.md ├── note ├── 01.开发goodlist组件.md ├── 02.vue项目中的@符号的意思.md ├── 03.在项目中引入css样式的方法.md ├── 04.当后端接口还没写完的时候.此时怎么做才不影响开发进度.md ├── 05.部组件拆分使用.md ├── 06.模拟mock数据.md ├── 07.图片懒加载.md ├── 08.使用express-generator生成express项目.md ├── 09.express连接mongodb数据库.md ├── 10.mongoose.操作指南.md ├── 11.根据价格排序.md ├── 12.按照价格区间筛选商品.md ├── 13.在vue中实现下拉加载数据,瀑布流.md ├── 14.域名注册.md ├── 15.表驱动法.md ├── 16.加入购物车.md ├── 17.登录逻辑.md ├── 18.登录前后台实现.md ├── 19.在项目前后分离的状态下,刷新页面,怎么保持用户登录.md ├── 20.退出登录.md ├── 21.如何在vue里面优雅的解决跨域,路由冲突问题.md ├── 22.登录拦截.md ├── 23.开发购物车页面.md ├── 24.调试问题的框架.md ├── 25.购物车列表里面的商品数量增加和减少,和是否被选中.md ├── 26.全选,全不选.md ├── 27.总价格实时变化.md ├── 28.商品删除.md ├── 29.封装全局模态框组件.购物车判断登录与未登录情况的弹出不同模态框.md ├── 30.在购物车列表页面去结账.md ├── 31.地址页面.md ├── 32.设置默认地址.md ├── 33.订单确认页面.md ├── 34.项目上线.md ├── 35.服务器购买.md ├── 36.域名购买.md ├── 36.连接阿里云工具.md ├── 37.【全栈项目上线(vue+node+mongodb)】安装lnmp环境.md ├── 38.项目上线解决方案.md ├── 39.怎么在一台主机上面部署多个网站.md ├── 40.nodejs服务上线.md ├── 41.homework.md ├── 42.项目上线使用webhooks.md ├── day.log.md ├── homework.md ├── item.guide.md ├── 分析需求.md ├── 常用工具.md ├── 思想.md ├── 接口文档.md ├── 推荐工具.md └── 项目需求.md ├── note01 ├── 01.技术栈.md ├── 02.项目结构.md ├── 03.项目初始化.md ├── 04.组件.md ├── 05.懒加载图片.md ├── 06.利用本地的vue项目里面express.模拟数据.md ├── 07.使用express-generator生成项目.md ├── 08.前端与后端交互的介质.md ├── 09.跨域.md ├── 10.价格排序.md ├── 11.按照价格区间筛选商品.md ├── 12.商品分页,瀑布流,下拉加载.md ├── 13.解决node修改完重启问题.md ├── 14.加入购物车.md ├── 15.mongoose.md ├── 16.用户登陆.md ├── 19.在vue中怎么优雅的配置本地代理.md ├── 20.登陆拦截.md ├── 21.国庆作业.md ├── 23.全选.全不选.md ├── 24.登录流程.md ├── 25.删除购物车.md ├── 26.设计数据库.md ├── 27.支付生成订单号.md ├── 28.项目上线.md ├── mongodb 安装连接方式.pdf ├── vue+express+mongodb项目上线 (1).pdf └── 学习效率.md ├── readme.md └── server ├── .gitignore ├── app.js ├── bin └── www ├── models ├── goods.js └── user.js ├── package-lock.json ├── package.json ├── public └── stylesheets │ └── style.css ├── routes ├── goods.js ├── index.js └── users.js ├── util └── util.js └── views ├── error.jade ├── index.jade └── layout.jade /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/.DS_Store -------------------------------------------------------------------------------- /client/.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 | } 19 | -------------------------------------------------------------------------------- /client/.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 10 | -------------------------------------------------------------------------------- /client/.eslintignore: -------------------------------------------------------------------------------- 1 | build/*.js 2 | config/*.js 3 | -------------------------------------------------------------------------------- /client/.eslintrc.js: -------------------------------------------------------------------------------- 1 | // http://eslint.org/docs/user-guide/configuring 2 | 3 | module.exports = { 4 | root: true, 5 | parser: 'babel-eslint', 6 | parserOptions: { 7 | sourceType: 'module' 8 | }, 9 | env: { 10 | browser: true, 11 | }, 12 | // https://github.com/standard/standard/blob/master/docs/RULES-en.md 13 | extends: 'standard', 14 | // required to lint *.vue files 15 | plugins: [ 16 | 'html' 17 | ], 18 | // add your custom rules here 19 | 'rules': { 20 | // allow paren-less arrow functions 21 | 'arrow-parens': 0, 22 | // allow async-await 23 | 'generator-star-spacing': 0, 24 | // allow debugger during development 25 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /client/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | test/unit/coverage 8 | test/e2e/reports 9 | selenium-debug.log 10 | 11 | # Editor directories and files 12 | .idea 13 | *.suo 14 | *.ntvs* 15 | *.njsproj 16 | *.sln 17 | -------------------------------------------------------------------------------- /client/.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | // to edit target browsers: use "browserslist" field in package.json 6 | "autoprefixer": {} 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /client/README.md: -------------------------------------------------------------------------------- 1 | # vnshop 2 | 3 | > vue&&node shop 4 | 5 | ## Build Setup 6 | 7 | ``` bash 8 | # install dependencies 9 | npm install 10 | 11 | # serve with hot reload at localhost:8080 12 | npm run dev 13 | 14 | # build for production with minification 15 | npm run build 16 | 17 | # build for production and view the bundle analyzer report 18 | npm run build --report 19 | 20 | # run unit tests 21 | npm run unit 22 | 23 | # run e2e tests 24 | npm run e2e 25 | 26 | # run all tests 27 | npm test 28 | ``` 29 | 30 | For detailed explanation on how things work, checkout the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader). 31 | 教程视频地址: 32 | 链接: https://pan.baidu.com/s/1qXB5BkS 密码: 6nru -------------------------------------------------------------------------------- /client/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, config.build.assetsSubDirectory), 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 | -------------------------------------------------------------------------------- /client/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 | -------------------------------------------------------------------------------- /client/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 | -------------------------------------------------------------------------------- /client/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 webpackConfig = (process.env.NODE_ENV === 'testing' || process.env.NODE_ENV === 'production') ? 14 | require('./webpack.prod.conf') : 15 | require('./webpack.dev.conf') 16 | 17 | // default port where dev server listens for incoming traffic 18 | var port = process.env.PORT || config.dev.port 19 | // automatically open browser, if not set will be false 20 | var autoOpenBrowser = !!config.dev.autoOpenBrowser 21 | // Define HTTP proxies to your custom API backend 22 | // https://github.com/chimurai/http-proxy-middleware 23 | var proxyTable = config.dev.proxyTable 24 | 25 | var app = express() 26 | var compiler = webpack(webpackConfig) 27 | // var router = express.Router(); 28 | // var goodsList = require('../mock/goods.json'); 29 | 30 | // // 对外暴漏一个路由,然后当你访问的时候给你做点事情 31 | // router.get("/goods", function(req, res, next) { 32 | // // req 请求 33 | // // res 响应 34 | // res.json(goodsList); 35 | // }) 36 | 37 | // app.use(router); 38 | 39 | var devMiddleware = require('webpack-dev-middleware')(compiler, { 40 | publicPath: webpackConfig.output.publicPath, 41 | quiet: true 42 | }) 43 | 44 | var hotMiddleware = require('webpack-hot-middleware')(compiler, { 45 | log: false, 46 | heartbeat: 2000 47 | }) 48 | // force page reload when html-webpack-plugin template changes 49 | compiler.plugin('compilation', function(compilation) { 50 | compilation.plugin('html-webpack-plugin-after-emit', function(data, cb) { 51 | hotMiddleware.publish({ action: 'reload' }) 52 | cb() 53 | }) 54 | }) 55 | 56 | // proxy api requests 57 | Object.keys(proxyTable).forEach(function(context) { 58 | var options = proxyTable[context] 59 | if (typeof options === 'string') { 60 | options = { target: options } 61 | } 62 | app.use(proxyMiddleware(options.filter || context, options)) 63 | }) 64 | 65 | // handle fallback for HTML5 history API 66 | app.use(require('connect-history-api-fallback')()) 67 | 68 | // serve webpack bundle output 69 | app.use(devMiddleware) 70 | 71 | // enable hot-reload and state-preserving 72 | // compilation error display 73 | app.use(hotMiddleware) 74 | 75 | // serve pure static assets 76 | var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory) 77 | app.use(staticPath, express.static('./static')) 78 | 79 | var uri = 'http://localhost:' + port 80 | 81 | var _resolve 82 | var readyPromise = new Promise(resolve => { 83 | _resolve = resolve 84 | }) 85 | 86 | console.log('> Starting dev server...') 87 | devMiddleware.waitUntilValid(() => { 88 | console.log('> Listening at ' + uri + '\n') 89 | // when env is testing, don't need open it 90 | if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') { 91 | opn(uri) 92 | } 93 | _resolve() 94 | }) 95 | 96 | var server = app.listen(port) 97 | 98 | module.exports = { 99 | ready: readyPromise, 100 | close: () => { 101 | server.close() 102 | } 103 | } -------------------------------------------------------------------------------- /client/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 | // generate loader string to be used with extract text plugin 24 | function generateLoaders (loader, loaderOptions) { 25 | var loaders = [cssLoader] 26 | if (loader) { 27 | loaders.push({ 28 | loader: loader + '-loader', 29 | options: Object.assign({}, loaderOptions, { 30 | sourceMap: options.sourceMap 31 | }) 32 | }) 33 | } 34 | 35 | // Extract CSS when that option is specified 36 | // (which is the case during production build) 37 | if (options.extract) { 38 | return ExtractTextPlugin.extract({ 39 | use: loaders, 40 | fallback: 'vue-style-loader' 41 | }) 42 | } else { 43 | return ['vue-style-loader'].concat(loaders) 44 | } 45 | } 46 | 47 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html 48 | return { 49 | css: generateLoaders(), 50 | postcss: generateLoaders(), 51 | less: generateLoaders('less'), 52 | sass: generateLoaders('sass', { indentedSyntax: true }), 53 | scss: generateLoaders('sass'), 54 | stylus: generateLoaders('stylus'), 55 | styl: generateLoaders('stylus') 56 | } 57 | } 58 | 59 | // Generate loaders for standalone style files (outside of .vue) 60 | exports.styleLoaders = function (options) { 61 | var output = [] 62 | var loaders = exports.cssLoaders(options) 63 | for (var extension in loaders) { 64 | var loader = loaders[extension] 65 | output.push({ 66 | test: new RegExp('\\.' + extension + '$'), 67 | use: loader 68 | }) 69 | } 70 | return output 71 | } 72 | -------------------------------------------------------------------------------- /client/build/vue-loader.conf.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils') 2 | var config = require('../config') 3 | var isProduction = process.env.NODE_ENV === 'production' 4 | 5 | module.exports = { 6 | loaders: utils.cssLoaders({ 7 | sourceMap: isProduction 8 | ? config.build.productionSourceMap 9 | : config.dev.cssSourceMap, 10 | extract: isProduction 11 | }), 12 | transformToRequire: { 13 | video: 'src', 14 | source: 'src', 15 | img: 'src', 16 | image: 'xlink:href' 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /client/build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var utils = require('./utils') 3 | var config = require('../config') 4 | var vueLoaderConfig = require('./vue-loader.conf') 5 | 6 | function resolve(dir) { 7 | return path.join(__dirname, '..', dir) 8 | } 9 | 10 | module.exports = { 11 | entry: { 12 | app: './src/main.js' 13 | }, 14 | output: { 15 | path: config.build.assetsRoot, 16 | filename: '[name].js', 17 | publicPath: process.env.NODE_ENV === 'production' ? 18 | config.build.assetsPublicPath : config.dev.assetsPublicPath 19 | }, 20 | resolve: { 21 | extensions: ['.js', '.vue', '.json', '.css'], 22 | alias: { 23 | 'vue$': 'vue/dist/vue.esm.js', 24 | '@': resolve('src'), 25 | } 26 | }, 27 | module: { 28 | rules: [ 29 | // { 30 | // test: /\.(js|vue)$/, 31 | // loader: 'eslint-loader', 32 | // enforce: 'pre', 33 | // include: [resolve('src'), resolve('test')], 34 | // options: { 35 | // formatter: require('eslint-friendly-formatter') 36 | // } 37 | // }, 38 | { 39 | test: /\.vue$/, 40 | loader: 'vue-loader', 41 | options: vueLoaderConfig 42 | }, 43 | { 44 | test: /\.js$/, 45 | loader: 'babel-loader', 46 | include: [resolve('src'), resolve('test')] 47 | }, 48 | { 49 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 50 | loader: 'url-loader', 51 | options: { 52 | limit: 10000, 53 | name: utils.assetsPath('img/[name].[hash:7].[ext]') 54 | } 55 | }, 56 | { 57 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, 58 | loader: 'url-loader', 59 | options: { 60 | limit: 10000, 61 | name: utils.assetsPath('media/[name].[hash:7].[ext]') 62 | } 63 | }, 64 | { 65 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 66 | loader: 'url-loader', 67 | options: { 68 | limit: 10000, 69 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') 70 | } 71 | } 72 | ] 73 | } 74 | } -------------------------------------------------------------------------------- /client/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 | // add hot-reload related code to entry chunks 10 | Object.keys(baseWebpackConfig.entry).forEach(function (name) { 11 | baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) 12 | }) 13 | 14 | module.exports = merge(baseWebpackConfig, { 15 | module: { 16 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) 17 | }, 18 | // cheap-module-eval-source-map is faster for development 19 | devtool: '#cheap-module-eval-source-map', 20 | plugins: [ 21 | new webpack.DefinePlugin({ 22 | 'process.env': config.dev.env 23 | }), 24 | // https://github.com/glenjamin/webpack-hot-middleware#installation--usage 25 | new webpack.HotModuleReplacementPlugin(), 26 | new webpack.NoEmitOnErrorsPlugin(), 27 | // https://github.com/ampedandwired/html-webpack-plugin 28 | new HtmlWebpackPlugin({ 29 | filename: 'index.html', 30 | template: 'index.html', 31 | inject: true 32 | }), 33 | new FriendlyErrorsPlugin() 34 | ] 35 | }) 36 | -------------------------------------------------------------------------------- /client/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 CopyWebpackPlugin = require('copy-webpack-plugin') 8 | var HtmlWebpackPlugin = require('html-webpack-plugin') 9 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 10 | var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') 11 | 12 | var env = process.env.NODE_ENV === 'testing' 13 | ? require('../config/test.env') 14 | : config.build.env 15 | 16 | var webpackConfig = merge(baseWebpackConfig, { 17 | module: { 18 | rules: utils.styleLoaders({ 19 | sourceMap: config.build.productionSourceMap, 20 | extract: true 21 | }) 22 | }, 23 | devtool: config.build.productionSourceMap ? '#source-map' : false, 24 | output: { 25 | path: config.build.assetsRoot, 26 | filename: utils.assetsPath('js/[name].[chunkhash].js'), 27 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') 28 | }, 29 | plugins: [ 30 | // http://vuejs.github.io/vue-loader/en/workflow/production.html 31 | new webpack.DefinePlugin({ 32 | 'process.env': env 33 | }), 34 | new webpack.optimize.UglifyJsPlugin({ 35 | compress: { 36 | warnings: false 37 | }, 38 | sourceMap: true 39 | }), 40 | // extract css into its own file 41 | new ExtractTextPlugin({ 42 | filename: utils.assetsPath('css/[name].[contenthash].css') 43 | }), 44 | // Compress extracted CSS. We are using this plugin so that possible 45 | // duplicated CSS from different components can be deduped. 46 | new OptimizeCSSPlugin({ 47 | cssProcessorOptions: { 48 | safe: true 49 | } 50 | }), 51 | // generate dist index.html with correct asset hash for caching. 52 | // you can customize output by editing /index.html 53 | // see https://github.com/ampedandwired/html-webpack-plugin 54 | new HtmlWebpackPlugin({ 55 | filename: process.env.NODE_ENV === 'testing' 56 | ? 'index.html' 57 | : config.build.index, 58 | template: 'index.html', 59 | inject: true, 60 | minify: { 61 | removeComments: true, 62 | collapseWhitespace: true, 63 | removeAttributeQuotes: true 64 | // more options: 65 | // https://github.com/kangax/html-minifier#options-quick-reference 66 | }, 67 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin 68 | chunksSortMode: 'dependency' 69 | }), 70 | // keep module.id stable when vender modules does not change 71 | new webpack.HashedModuleIdsPlugin(), 72 | // split vendor js into its own file 73 | new webpack.optimize.CommonsChunkPlugin({ 74 | name: 'vendor', 75 | minChunks: function (module, count) { 76 | // any required modules inside node_modules are extracted to vendor 77 | return ( 78 | module.resource && 79 | /\.js$/.test(module.resource) && 80 | module.resource.indexOf( 81 | path.join(__dirname, '../node_modules') 82 | ) === 0 83 | ) 84 | } 85 | }), 86 | // extract webpack runtime and module manifest to its own file in order to 87 | // prevent vendor hash from being updated whenever app bundle is updated 88 | new webpack.optimize.CommonsChunkPlugin({ 89 | name: 'manifest', 90 | chunks: ['vendor'] 91 | }), 92 | // copy custom static assets 93 | new CopyWebpackPlugin([ 94 | { 95 | from: path.resolve(__dirname, '../static'), 96 | to: config.build.assetsSubDirectory, 97 | ignore: ['.*'] 98 | } 99 | ]) 100 | ] 101 | }) 102 | 103 | if (config.build.productionGzip) { 104 | var CompressionWebpackPlugin = require('compression-webpack-plugin') 105 | 106 | webpackConfig.plugins.push( 107 | new CompressionWebpackPlugin({ 108 | asset: '[path].gz[query]', 109 | algorithm: 'gzip', 110 | test: new RegExp( 111 | '\\.(' + 112 | config.build.productionGzipExtensions.join('|') + 113 | ')$' 114 | ), 115 | threshold: 10240, 116 | minRatio: 0.8 117 | }) 118 | ) 119 | } 120 | 121 | if (config.build.bundleAnalyzerReport) { 122 | var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin 123 | webpackConfig.plugins.push(new BundleAnalyzerPlugin()) 124 | } 125 | 126 | module.exports = webpackConfig 127 | -------------------------------------------------------------------------------- /client/build/webpack.test.conf.js: -------------------------------------------------------------------------------- 1 | // This is the webpack config used for unit tests. 2 | 3 | var utils = require('./utils') 4 | var webpack = require('webpack') 5 | var merge = require('webpack-merge') 6 | var baseConfig = require('./webpack.base.conf') 7 | 8 | var webpackConfig = merge(baseConfig, { 9 | // use inline sourcemap for karma-sourcemap-loader 10 | module: { 11 | rules: utils.styleLoaders() 12 | }, 13 | devtool: '#inline-source-map', 14 | resolveLoader: { 15 | alias: { 16 | // necessary to to make lang="scss" work in test when using vue-loader's ?inject option 17 | // see discussion at https://github.com/vuejs/vue-loader/issues/724 18 | 'scss-loader': 'sass-loader' 19 | } 20 | }, 21 | plugins: [ 22 | new webpack.DefinePlugin({ 23 | 'process.env': require('../config/test.env') 24 | }) 25 | ] 26 | }) 27 | 28 | // no need for app entry during tests 29 | delete webpackConfig.entry 30 | 31 | module.exports = webpackConfig 32 | -------------------------------------------------------------------------------- /client/config/api.config.js: -------------------------------------------------------------------------------- 1 | const isProdMode = Object.is(process.env.NODE_ENV, 'production') 2 | 3 | module.exports = { 4 | baseUrl: isProdMode ? 'http://vnshop.shudong.wang/api/' : 'api/' 5 | } -------------------------------------------------------------------------------- /client/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 | -------------------------------------------------------------------------------- /client/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: 'static', 10 | assetsPublicPath: '/', 11 | productionSourceMap: true, 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 | autoOpenBrowser: true, 28 | assetsSubDirectory: 'static', 29 | assetsPublicPath: '/', 30 | proxyTable: { 31 | // '/goods/**': { 32 | // target: 'http://localhost:3000' 33 | // }, 34 | '/users/**': { 35 | target: 'http://localhost:3000' 36 | }, 37 | '/api/**': { 38 | target: 'http://localhost:3000', 39 | pathRewrite: { 40 | '^/api': '/' 41 | } 42 | } 43 | }, 44 | // CSS Sourcemaps off by default because relative paths are "buggy" 45 | // with this option, according to the CSS-Loader README 46 | // (https://github.com/webpack/css-loader#sourcemaps) 47 | // In our experience, they generally work as expected, 48 | // just be aware of this issue when enabling this option. 49 | cssSourceMap: false 50 | } 51 | } -------------------------------------------------------------------------------- /client/config/prod.env.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NODE_ENV: '"production"' 3 | } 4 | -------------------------------------------------------------------------------- /client/config/test.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var devEnv = require('./dev.env') 3 | 4 | module.exports = merge(devEnv, { 5 | NODE_ENV: '"testing"' 6 | }) 7 | -------------------------------------------------------------------------------- /client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | vnshop 6 | 7 | 8 |
9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /client/mock/goods.json: -------------------------------------------------------------------------------- 1 | { "data": [{ "_id": { "$oid": "58c284b13a1bb9aa7033801b" }, "productId": "201710003", "productName": "平衡车", "salePrice": 1999, "productImage": "pingheng.jpg", "productUrl": "" }, { "_id": { "$oid": "58c284d7117a2e6599abef5e" }, "productId": "201710004", "productName": "头戴式耳机-3", "salePrice": 80, "productImage": "2.jpg", "productUrl": "" }, { "_id": { "$oid": "58c284e6117a2e6599abef5f" }, "productId": "201710005", "productName": "小米笔记本", "salePrice": 3549, "productImage": "note.jpg", "productUrl": "" }, { "_id": { "$oid": "58c284f4117a2e6599abef60" }, "productId": "201710006", "productName": "小米6", "salePrice": 2499, "productImage": "mi6.jpg", "productUrl": "" }, { "_id": { "$oid": "58e704ef98dab115d336b3f1" }, "productId": "201710002", "productName": "智能插线板", "salePrice": 59, "productImage": "6.jpg", "productUrl": "" }, { "_id": { "$oid": "58e7050398dab115d336b3f2" }, "productId": "201710007", "productName": "自拍杆", "salePrice": 39, "productImage": "zipai.jpg", "productUrl": "" }, { "_id": { "$oid": "58e7050c98dab115d336b3f3" }, "productId": "201710008", "productName": "小米净水器", "salePrice": 1999, "productImage": "8.jpg", "productUrl": "" }, { "_id": { "$oid": "58e7051698dab115d336b3f4" }, "productId": "201710009", "productName": "IH 电饭煲", "salePrice": 999, "productImage": "9.jpg", "productUrl": "" }, { "_id": { "$oid": "58e7052198dab115d336b3f5" }, "productId": "201710010", "productName": "小米电视4A", "salePrice": 2099, "productImage": "10.jpg", "productUrl": "" }, { "_id": { "$oid": "58e7052a98dab115d336b3f6" }, "productId": "201710011", "productName": "Ear1000", "salePrice": 1000, "productImage": "11.jpg", "productUrl": "" }, { "_id": { "$oid": "58e7053298dab115d336b3f7" }, "productId": "201710012", "productName": "Ear1100", "salePrice": 1100, "productImage": "12.jpg", "productUrl": "" }, { "_id": { "$oid": "58e7053c98dab115d336b3f8" }, "productId": "201710013", "productName": "Ear2000", "salePrice": 2000, "productImage": "13.jpg", "productUrl": "" }, { "_id": { "$oid": "58e7054798dab115d336b3f9" }, "productId": "201710014", "productName": "Ear1600", "salePrice": 1600, "productImage": "14.jpg", "productUrl": "" }, { "_id": { "$oid": "58e7055198dab115d336b3fa" }, "productId": "201710015", "productName": "Ear1200", "salePrice": 1200, "productImage": "15.jpg", "productUrl": "" }, { "_id": { "$oid": "58e7057798dab115d336b3fb" }, "productId": "201710016", "productName": "Ear700", "salePrice": 700, "productImage": "16.jpg", "productUrl": "" }, { "_id": { "$oid": "58e7058498dab115d336b3fc" }, "productId": "201710017", "productName": "小钢炮蓝牙音箱", "salePrice": 129, "productImage": "1.jpg", "productUrl": "" }, { "_id": { "$oid": "58e7058d98dab115d336b3fd" }, "productId": "201710018", "productName": "智能摄像机", "salePrice": 389, "productImage": "photo.jpg", "productUrl": "" }] } -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vnshop", 3 | "version": "1.0.0", 4 | "description": "vue&&node shop", 5 | "author": "stark.wang", 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 | "unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run", 12 | "e2e": "node test/e2e/runner.js", 13 | "test": "npm run unit && npm run e2e", 14 | "lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs" 15 | }, 16 | "dependencies": { 17 | "vue": "^2.4.2", 18 | "vue-infinite-scroll": "^2.0.1", 19 | "vue-router": "^2.7.0" 20 | }, 21 | "devDependencies": { 22 | "autoprefixer": "^7.1.2", 23 | "axios": "^0.16.2", 24 | "babel-core": "^6.22.1", 25 | "babel-eslint": "^7.1.1", 26 | "babel-loader": "^7.1.1", 27 | "babel-plugin-istanbul": "^4.1.1", 28 | "babel-plugin-transform-runtime": "^6.22.0", 29 | "babel-preset-env": "^1.3.2", 30 | "babel-preset-stage-2": "^6.22.0", 31 | "babel-register": "^6.22.0", 32 | "chai": "^3.5.0", 33 | "chalk": "^2.0.1", 34 | "chromedriver": "^2.27.2", 35 | "connect-history-api-fallback": "^1.3.0", 36 | "copy-webpack-plugin": "^4.0.1", 37 | "cross-env": "^5.0.1", 38 | "cross-spawn": "^5.0.1", 39 | "css-loader": "^0.28.0", 40 | "cssnano": "^3.10.0", 41 | "eslint": "^3.19.0", 42 | "eslint-config-standard": "^6.2.1", 43 | "eslint-friendly-formatter": "^3.0.0", 44 | "eslint-loader": "^1.7.1", 45 | "eslint-plugin-html": "^3.0.0", 46 | "eslint-plugin-promise": "^3.4.0", 47 | "eslint-plugin-standard": "^2.0.1", 48 | "eventsource-polyfill": "^0.9.6", 49 | "express": "^4.14.1", 50 | "extract-text-webpack-plugin": "^2.0.0", 51 | "file-loader": "^0.11.1", 52 | "friendly-errors-webpack-plugin": "^1.1.3", 53 | "html-webpack-plugin": "^2.28.0", 54 | "http-proxy-middleware": "^0.17.3", 55 | "inject-loader": "^3.0.0", 56 | "karma": "^1.4.1", 57 | "karma-coverage": "^1.1.1", 58 | "karma-mocha": "^1.3.0", 59 | "karma-phantomjs-launcher": "^1.0.2", 60 | "karma-phantomjs-shim": "^1.4.0", 61 | "karma-sinon-chai": "^1.3.1", 62 | "karma-sourcemap-loader": "^0.3.7", 63 | "karma-spec-reporter": "0.0.31", 64 | "karma-webpack": "^2.0.2", 65 | "mocha": "^3.2.0", 66 | "nightwatch": "^0.9.12", 67 | "opn": "^5.1.0", 68 | "optimize-css-assets-webpack-plugin": "^2.0.0", 69 | "ora": "^1.2.0", 70 | "phantomjs-prebuilt": "^2.1.14", 71 | "rimraf": "^2.6.0", 72 | "selenium-server": "^3.0.1", 73 | "semver": "^5.3.0", 74 | "shelljs": "^0.7.6", 75 | "sinon": "^2.1.0", 76 | "sinon-chai": "^2.8.0", 77 | "url-loader": "^0.5.8", 78 | "vue-axios": "^2.0.2", 79 | "vue-lazyload": "^1.1.3", 80 | "vue-loader": "^13.0.4", 81 | "vue-style-loader": "^3.0.1", 82 | "vue-template-compiler": "^2.4.2", 83 | "webpack": "^2.6.1", 84 | "webpack-bundle-analyzer": "^2.2.1", 85 | "webpack-dev-middleware": "^1.10.0", 86 | "webpack-hot-middleware": "^2.18.0", 87 | "webpack-merge": "^4.1.0" 88 | }, 89 | "engines": { 90 | "node": ">= 4.0.0", 91 | "npm": ">= 3.0.0" 92 | }, 93 | "browserslist": [ 94 | "> 1%", 95 | "last 2 versions", 96 | "not ie <= 8" 97 | ] 98 | } 99 | -------------------------------------------------------------------------------- /client/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 15 | -------------------------------------------------------------------------------- /client/src/api/index.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import apiConfig from '../../config/api.config'; 3 | 4 | const service = axios.create({ 5 | baseURL: apiConfig.baseUrl 6 | // baseURL: 'api/' 7 | }) 8 | 9 | Vue.prototype.$http = service 10 | export default service -------------------------------------------------------------------------------- /client/src/assets/css/app.css: -------------------------------------------------------------------------------- 1 | @import './base.css'; 2 | @import './checkout.css'; 3 | @import './login.css'; 4 | @import './product.css'; 5 | @import './style.css'; -------------------------------------------------------------------------------- /client/src/assets/css/login.css: -------------------------------------------------------------------------------- 1 | /*nav*/ 2 | .header { 3 | width: 100%; 4 | background-color: white; 5 | font-family: "moderat",sans-serif; 6 | font-size: 16px; 7 | } 8 | .navbar { 9 | display: flex; 10 | justify-content: space-between; 11 | align-content: center; 12 | width: 100%; 13 | height: 70px; 14 | max-width: 1280px; 15 | margin: 0 auto; 16 | padding: 5px 20px 10px 20px; 17 | } 18 | .navbar-left-container { 19 | display: flex; 20 | justify-content: flex-start; 21 | align-items: center; 22 | margin-left: -20px; 23 | } 24 | .navbar-brand-logo { 25 | /*width: 120px;*/ 26 | } 27 | .header a, .footer a { 28 | color: #666; 29 | text-decoration: none; 30 | } 31 | a { 32 | -webkit-transition: color .3s ease-out; 33 | transition: color .3s ease-out; 34 | } 35 | .navbar-right-container { 36 | display: none; 37 | justify-content: flex-start; 38 | align-items: center; 39 | } 40 | .navbar-menu-container { 41 | display: flex; 42 | justify-content: flex-end; 43 | align-items: center; 44 | padding-top: 10px; 45 | } 46 | .navbar-link { 47 | padding-left: 15px; 48 | } 49 | .navbar-cart-container { 50 | position: relative; 51 | } 52 | .navbar-cart-count { 53 | justify-content: center; 54 | align-items: center; 55 | position: absolute; 56 | top: -9px; 57 | right: -11px; 58 | width: 20px; 59 | border-radius: 10px; 60 | color: white; 61 | background-color: #eb767d; 62 | font-size: 16px; 63 | font-weight: bold; 64 | text-align: center; 65 | } 66 | .navbar-cart-logo { 67 | width: 25px; 68 | height: 25px; 69 | transform: scaleX(-1); 70 | } 71 | /*login*/ 72 | .regi_form_input{ 73 | position: relative; 74 | height: 42px; 75 | line-height: 42px; 76 | background: none; 77 | margin-bottom: 15px; 78 | font-size: 14px; 79 | overflow: hidden; 80 | border:1px solid #ccc; 81 | padding-bottom: 0; 82 | } 83 | .regi_form_input .icon { 84 | display: inline-block; 85 | float: left; 86 | width: 25px; 87 | height: 29px; 88 | margin: 6px 0 0 14px; 89 | background-position: 4px 5px; 90 | background-image: url("/static/icon.png"); 91 | background-repeat: no-repeat; 92 | } 93 | .regi_form_input .IconPwd { 94 | background-position: -198px 3px; 95 | } 96 | .regi_form_input .regi_login_input{ 97 | position: absolute; 98 | left:45px; 99 | top:0; 100 | padding: 9px 0 10px; 101 | width: 270px; 102 | font-size: 14px; 103 | zoom: 1; 104 | border: none; 105 | color: #333; 106 | /*height: 23px;*/ 107 | line-height: 23px; 108 | background: 0 0!important; 109 | } 110 | .md-title{ 111 | position: absolute; 112 | top: 14px; 113 | line-height: 24px; 114 | padding: 8px 0; 115 | color: #333; 116 | font-size: 18px; 117 | font-weight: 400; 118 | font-style: normal; 119 | } 120 | .login-wrap{ 121 | margin-top:30px; 122 | } 123 | .md-content .btn-login{ 124 | display: block; 125 | height: 38px; 126 | line-height: 38px; 127 | border: 2px solid #009de6; 128 | background: #009de6; 129 | color: #fff; 130 | font-size: 18px; 131 | text-align: center; 132 | } 133 | .btn-login:hover { 134 | background: #61b1ef; 135 | border: 2px solid #61b1ef; 136 | } 137 | .error-wrap .error{ 138 | font-size: 12px; 139 | color: #d31723; 140 | visibility: hidden; 141 | display: block; 142 | padding: 0 0 7px 17px; 143 | line-height: 16px; 144 | height: 16px; 145 | text-align: left; 146 | background: url("/static/icon.png") 0 -100px no-repeat; 147 | } 148 | .md-content .error-wrap .error-show{ 149 | visibility: visible; 150 | height: auto; 151 | } 152 | -------------------------------------------------------------------------------- /client/src/assets/img/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/1.jpg -------------------------------------------------------------------------------- /client/src/assets/img/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/10.jpg -------------------------------------------------------------------------------- /client/src/assets/img/11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/11.jpg -------------------------------------------------------------------------------- /client/src/assets/img/12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/12.jpg -------------------------------------------------------------------------------- /client/src/assets/img/13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/13.jpg -------------------------------------------------------------------------------- /client/src/assets/img/14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/14.jpg -------------------------------------------------------------------------------- /client/src/assets/img/15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/15.jpg -------------------------------------------------------------------------------- /client/src/assets/img/16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/16.jpg -------------------------------------------------------------------------------- /client/src/assets/img/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/2.jpg -------------------------------------------------------------------------------- /client/src/assets/img/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/3.jpg -------------------------------------------------------------------------------- /client/src/assets/img/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/4.jpg -------------------------------------------------------------------------------- /client/src/assets/img/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/5.jpg -------------------------------------------------------------------------------- /client/src/assets/img/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/6.jpg -------------------------------------------------------------------------------- /client/src/assets/img/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/7.jpg -------------------------------------------------------------------------------- /client/src/assets/img/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/8.jpg -------------------------------------------------------------------------------- /client/src/assets/img/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/9.jpg -------------------------------------------------------------------------------- /client/src/assets/img/bnt_subOrder.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/bnt_subOrder.gif -------------------------------------------------------------------------------- /client/src/assets/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/icon.png -------------------------------------------------------------------------------- /client/src/assets/img/logo-footer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/logo-footer.png -------------------------------------------------------------------------------- /client/src/assets/img/logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/logo.gif -------------------------------------------------------------------------------- /client/src/assets/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/logo.png -------------------------------------------------------------------------------- /client/src/assets/img/mi6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/mi6.jpg -------------------------------------------------------------------------------- /client/src/assets/img/note.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/note.jpg -------------------------------------------------------------------------------- /client/src/assets/img/ok-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/ok-2.png -------------------------------------------------------------------------------- /client/src/assets/img/photo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/photo.jpg -------------------------------------------------------------------------------- /client/src/assets/img/pingheng.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/pingheng.jpg -------------------------------------------------------------------------------- /client/src/assets/img/user_purchase20150409154845.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/user_purchase20150409154845.gif -------------------------------------------------------------------------------- /client/src/assets/img/v-face1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/v-face1.jpg -------------------------------------------------------------------------------- /client/src/assets/img/v-face2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/v-face2.jpg -------------------------------------------------------------------------------- /client/src/assets/img/v-face3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/v-face3.jpg -------------------------------------------------------------------------------- /client/src/assets/img/v-face4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/v-face4.jpg -------------------------------------------------------------------------------- /client/src/assets/img/vn-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/vn-logo.png -------------------------------------------------------------------------------- /client/src/assets/img/vn_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/vn_logo.png -------------------------------------------------------------------------------- /client/src/assets/img/zipai.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/img/zipai.jpg -------------------------------------------------------------------------------- /client/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/src/assets/logo.png -------------------------------------------------------------------------------- /client/src/components/Head.vue: -------------------------------------------------------------------------------- 1 | 68 | 111 | 114 | 115 | -------------------------------------------------------------------------------- /client/src/components/Hello.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 33 | 34 | 35 | 54 | -------------------------------------------------------------------------------- /client/src/components/Modal.vue: -------------------------------------------------------------------------------- 1 | 25 | 30 | -------------------------------------------------------------------------------- /client/src/components/NavBread.vue: -------------------------------------------------------------------------------- 1 | 11 | -------------------------------------------------------------------------------- /client/src/main.js: -------------------------------------------------------------------------------- 1 | // The Vue build version to load with the `import` command 2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias. 3 | import Vue from 'vue' 4 | import App from './App' 5 | import router from './router' 6 | import '@/assets/css/app' 7 | import VueLazyLoad from 'vue-lazyload' 8 | 9 | import apiConfig from '../config/api.config' 10 | import Axios from 'axios' 11 | import VueAxios from 'vue-axios' 12 | 13 | import infiniteScroll from 'vue-infinite-scroll' 14 | Vue.use(infiniteScroll) 15 | 16 | Vue.use(VueAxios, Axios); 17 | Axios.defaults.baseURL = apiConfig.baseUrl; 18 | 19 | 20 | Vue.use(VueLazyLoad, { 21 | loading: '/static/img/ok-2.png' 22 | }) 23 | Vue.config.productionTip = false 24 | 25 | /* eslint-disable no-new */ 26 | new Vue({ 27 | el: '#app', 28 | router, 29 | template: '', 30 | components: { App } 31 | }) -------------------------------------------------------------------------------- /client/src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import Hello from '@/components/Hello' 4 | import GoodsList from '@/view/GoodsList' 5 | import User from '@/view/user/index' 6 | import Cart from '@/view/Cart' 7 | import Address from '@/view/Address' 8 | import OrderConfirm from '@/view/OrderConfirm' 9 | import OrderSuccess from '@/view/OrderSuccess' 10 | 11 | Vue.use(Router) 12 | 13 | export default new Router({ 14 | routes: [{ 15 | path: '/', 16 | name: 'GoodsList', 17 | component: GoodsList 18 | }, 19 | { 20 | path: '/cart', //?代表可写,也可以不写 /user/1 21 | component: Cart 22 | }, 23 | { 24 | path: '/address', 25 | component: Address 26 | }, 27 | { 28 | path: '/orderConfirm', 29 | component: OrderConfirm 30 | }, 31 | { 32 | path: '/orderSuccess', 33 | component: OrderSuccess 34 | }, 35 | { 36 | path: '/user/:stark?/:xiaorong?', //?代表可写,也可以不写 /user/1 37 | component: User 38 | }, 39 | ] 40 | }) -------------------------------------------------------------------------------- /client/src/view/OrderSuccess.vue: -------------------------------------------------------------------------------- 1 | 42 | -------------------------------------------------------------------------------- /client/src/view/user/index.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 90 | 91 | -------------------------------------------------------------------------------- /client/static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/.gitkeep -------------------------------------------------------------------------------- /client/static/images/201507/27_thumb_G_1437074702008.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201507/27_thumb_G_1437074702008.jpg -------------------------------------------------------------------------------- /client/static/images/201507/28_thumb_G_1437074792369.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201507/28_thumb_G_1437074792369.jpg -------------------------------------------------------------------------------- /client/static/images/201507/29_thumb_G_1437074933275.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201507/29_thumb_G_1437074933275.jpg -------------------------------------------------------------------------------- /client/static/images/201507/30_thumb_G_1437075007558.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201507/30_thumb_G_1437075007558.jpg -------------------------------------------------------------------------------- /client/static/images/201507/31_thumb_G_1437075539254.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201507/31_thumb_G_1437075539254.jpg -------------------------------------------------------------------------------- /client/static/images/201507/32_thumb_G_1437075765802.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201507/32_thumb_G_1437075765802.jpg -------------------------------------------------------------------------------- /client/static/images/201507/33_thumb_G_1437075865379.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201507/33_thumb_G_1437075865379.jpg -------------------------------------------------------------------------------- /client/static/images/201507/34_thumb_G_1437076036973.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201507/34_thumb_G_1437076036973.jpg -------------------------------------------------------------------------------- /client/static/images/201507/35_thumb_G_1437081702649.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201507/35_thumb_G_1437081702649.jpg -------------------------------------------------------------------------------- /client/static/images/201507/36_thumb_G_1437082145888.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201507/36_thumb_G_1437082145888.jpg -------------------------------------------------------------------------------- /client/static/images/201507/37_thumb_G_1437082214575.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201507/37_thumb_G_1437082214575.jpg -------------------------------------------------------------------------------- /client/static/images/201507/38_thumb_G_1437082667838.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201507/38_thumb_G_1437082667838.jpg -------------------------------------------------------------------------------- /client/static/images/201507/39_thumb_G_1437082747983.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201507/39_thumb_G_1437082747983.jpg -------------------------------------------------------------------------------- /client/static/images/201507/40_thumb_G_1437082798686.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201507/40_thumb_G_1437082798686.jpg -------------------------------------------------------------------------------- /client/static/images/201507/41_thumb_G_1437082849514.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201507/41_thumb_G_1437082849514.jpg -------------------------------------------------------------------------------- /client/static/images/201507/42_thumb_G_1437082936092.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201507/42_thumb_G_1437082936092.jpg -------------------------------------------------------------------------------- /client/static/images/201507/43_thumb_G_1437091900155.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201507/43_thumb_G_1437091900155.jpg -------------------------------------------------------------------------------- /client/static/images/201507/44_thumb_G_1437092148601.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201507/44_thumb_G_1437092148601.jpg -------------------------------------------------------------------------------- /client/static/images/201507/45_thumb_G_1437092199733.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201507/45_thumb_G_1437092199733.jpg -------------------------------------------------------------------------------- /client/static/images/201507/46_thumb_G_1437092278369.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201507/46_thumb_G_1437092278369.jpg -------------------------------------------------------------------------------- /client/static/images/201508/47_thumb_G_1439331077002.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201508/47_thumb_G_1439331077002.jpg -------------------------------------------------------------------------------- /client/static/images/201508/53_thumb_G_1439511514539.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201508/53_thumb_G_1439511514539.jpg -------------------------------------------------------------------------------- /client/static/images/201508/56_thumb_G_1440717641715.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201508/56_thumb_G_1440717641715.jpg -------------------------------------------------------------------------------- /client/static/images/201508/57_thumb_G_1440717888680.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201508/57_thumb_G_1440717888680.jpg -------------------------------------------------------------------------------- /client/static/images/201508/59_thumb_G_1440983020324.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201508/59_thumb_G_1440983020324.jpg -------------------------------------------------------------------------------- /client/static/images/201508/60_thumb_G_1440983103483.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201508/60_thumb_G_1440983103483.jpg -------------------------------------------------------------------------------- /client/static/images/201508/64_thumb_G_1440983246324.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201508/64_thumb_G_1440983246324.jpg -------------------------------------------------------------------------------- /client/static/images/201508/65_thumb_G_1440983430401.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201508/65_thumb_G_1440983430401.jpg -------------------------------------------------------------------------------- /client/static/images/201508/66_thumb_G_1440983490045.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201508/66_thumb_G_1440983490045.jpg -------------------------------------------------------------------------------- /client/static/images/201508/67_thumb_G_1440983638116.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201508/67_thumb_G_1440983638116.jpg -------------------------------------------------------------------------------- /client/static/images/201508/68_thumb_G_1440983695997.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201508/68_thumb_G_1440983695997.jpg -------------------------------------------------------------------------------- /client/static/images/201508/69_thumb_G_1440983751530.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201508/69_thumb_G_1440983751530.jpg -------------------------------------------------------------------------------- /client/static/images/201508/70_thumb_G_1440983810214.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201508/70_thumb_G_1440983810214.jpg -------------------------------------------------------------------------------- /client/static/images/201508/71_thumb_G_1440983839269.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201508/71_thumb_G_1440983839269.jpg -------------------------------------------------------------------------------- /client/static/images/201508/72_thumb_G_1440983887661.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201508/72_thumb_G_1440983887661.jpg -------------------------------------------------------------------------------- /client/static/images/201508/73_thumb_G_1440983937959.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201508/73_thumb_G_1440983937959.jpg -------------------------------------------------------------------------------- /client/static/images/201508/74_thumb_G_1440983959230.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201508/74_thumb_G_1440983959230.jpg -------------------------------------------------------------------------------- /client/static/images/201508/75_thumb_G_1440984011595.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201508/75_thumb_G_1440984011595.jpg -------------------------------------------------------------------------------- /client/static/images/201508/76_thumb_G_1440984280864.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201508/76_thumb_G_1440984280864.jpg -------------------------------------------------------------------------------- /client/static/images/201508/77_thumb_G_1440984390480.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201508/77_thumb_G_1440984390480.jpg -------------------------------------------------------------------------------- /client/static/images/201509/101_thumb_G_1441738730692.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201509/101_thumb_G_1441738730692.jpg -------------------------------------------------------------------------------- /client/static/images/201509/102_thumb_G_1441738765271.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201509/102_thumb_G_1441738765271.jpg -------------------------------------------------------------------------------- /client/static/images/201509/103_thumb_G_1441738795942.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201509/103_thumb_G_1441738795942.jpg -------------------------------------------------------------------------------- /client/static/images/201509/78_thumb_G_1441050387337.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201509/78_thumb_G_1441050387337.jpg -------------------------------------------------------------------------------- /client/static/images/201509/79_thumb_G_1441050485953.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201509/79_thumb_G_1441050485953.jpg -------------------------------------------------------------------------------- /client/static/images/201509/80_thumb_G_1441050558701.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201509/80_thumb_G_1441050558701.jpg -------------------------------------------------------------------------------- /client/static/images/201509/81_thumb_G_1441050609661.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201509/81_thumb_G_1441050609661.jpg -------------------------------------------------------------------------------- /client/static/images/201509/82_thumb_G_1441050801926.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201509/82_thumb_G_1441050801926.jpg -------------------------------------------------------------------------------- /client/static/images/201509/83_thumb_G_1441052403875.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201509/83_thumb_G_1441052403875.jpg -------------------------------------------------------------------------------- /client/static/images/201509/84_thumb_G_1441056023645.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201509/84_thumb_G_1441056023645.jpg -------------------------------------------------------------------------------- /client/static/images/201509/85_thumb_G_1441056112107.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201509/85_thumb_G_1441056112107.jpg -------------------------------------------------------------------------------- /client/static/images/201509/86_thumb_G_1441056239670.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201509/86_thumb_G_1441056239670.jpg -------------------------------------------------------------------------------- /client/static/images/201509/87_thumb_G_1441056303542.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201509/87_thumb_G_1441056303542.jpg -------------------------------------------------------------------------------- /client/static/images/201509/88_thumb_G_1441056484072.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201509/88_thumb_G_1441056484072.jpg -------------------------------------------------------------------------------- /client/static/images/201509/89_thumb_G_1441056597778.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201509/89_thumb_G_1441056597778.jpg -------------------------------------------------------------------------------- /client/static/images/201509/90_thumb_G_1441056659073.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201509/90_thumb_G_1441056659073.jpg -------------------------------------------------------------------------------- /client/static/images/201509/91_thumb_G_1441056702928.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201509/91_thumb_G_1441056702928.jpg -------------------------------------------------------------------------------- /client/static/images/201509/92_thumb_G_1441056728120.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201509/92_thumb_G_1441056728120.jpg -------------------------------------------------------------------------------- /client/static/images/201509/93_thumb_G_1441056767939.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201509/93_thumb_G_1441056767939.jpg -------------------------------------------------------------------------------- /client/static/images/201509/94_thumb_G_1441056891849.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201509/94_thumb_G_1441056891849.jpg -------------------------------------------------------------------------------- /client/static/images/201509/96_thumb_G_1441738537157.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201509/96_thumb_G_1441738537157.jpg -------------------------------------------------------------------------------- /client/static/images/201509/98_thumb_G_1441738620606.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/images/201509/98_thumb_G_1441738620606.jpg -------------------------------------------------------------------------------- /client/static/img/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/1.jpg -------------------------------------------------------------------------------- /client/static/img/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/10.jpg -------------------------------------------------------------------------------- /client/static/img/11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/11.jpg -------------------------------------------------------------------------------- /client/static/img/12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/12.jpg -------------------------------------------------------------------------------- /client/static/img/13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/13.jpg -------------------------------------------------------------------------------- /client/static/img/14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/14.jpg -------------------------------------------------------------------------------- /client/static/img/15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/15.jpg -------------------------------------------------------------------------------- /client/static/img/16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/16.jpg -------------------------------------------------------------------------------- /client/static/img/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/2.jpg -------------------------------------------------------------------------------- /client/static/img/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/3.jpg -------------------------------------------------------------------------------- /client/static/img/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/4.jpg -------------------------------------------------------------------------------- /client/static/img/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/5.jpg -------------------------------------------------------------------------------- /client/static/img/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/6.jpg -------------------------------------------------------------------------------- /client/static/img/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/7.jpg -------------------------------------------------------------------------------- /client/static/img/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/8.jpg -------------------------------------------------------------------------------- /client/static/img/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/9.jpg -------------------------------------------------------------------------------- /client/static/img/bnt_subOrder.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/bnt_subOrder.gif -------------------------------------------------------------------------------- /client/static/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/icon.png -------------------------------------------------------------------------------- /client/static/img/logo-footer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/logo-footer.png -------------------------------------------------------------------------------- /client/static/img/logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/logo.gif -------------------------------------------------------------------------------- /client/static/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/logo.png -------------------------------------------------------------------------------- /client/static/img/mi6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/mi6.jpg -------------------------------------------------------------------------------- /client/static/img/note.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/note.jpg -------------------------------------------------------------------------------- /client/static/img/ok-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/ok-2.png -------------------------------------------------------------------------------- /client/static/img/photo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/photo.jpg -------------------------------------------------------------------------------- /client/static/img/pingheng.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/pingheng.jpg -------------------------------------------------------------------------------- /client/static/img/user_purchase20150409154845.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/user_purchase20150409154845.gif -------------------------------------------------------------------------------- /client/static/img/v-face1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/v-face1.jpg -------------------------------------------------------------------------------- /client/static/img/v-face2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/v-face2.jpg -------------------------------------------------------------------------------- /client/static/img/v-face3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/v-face3.jpg -------------------------------------------------------------------------------- /client/static/img/v-face4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/v-face4.jpg -------------------------------------------------------------------------------- /client/static/img/vn-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/vn-logo.png -------------------------------------------------------------------------------- /client/static/img/vn_logo.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/vn_logo.1.png -------------------------------------------------------------------------------- /client/static/img/vn_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/vn_logo.png -------------------------------------------------------------------------------- /client/static/img/zipai.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/client/static/img/zipai.jpg -------------------------------------------------------------------------------- /client/test/e2e/custom-assertions/elementCount.js: -------------------------------------------------------------------------------- 1 | // A custom Nightwatch assertion. 2 | // the name of the method is the filename. 3 | // can be used in tests like this: 4 | // 5 | // browser.assert.elementCount(selector, count) 6 | // 7 | // for how to write custom assertions see 8 | // http://nightwatchjs.org/guide#writing-custom-assertions 9 | exports.assertion = function (selector, count) { 10 | this.message = 'Testing if element <' + selector + '> has count: ' + count 11 | this.expected = count 12 | this.pass = function (val) { 13 | return val === this.expected 14 | } 15 | this.value = function (res) { 16 | return res.value 17 | } 18 | this.command = function (cb) { 19 | var self = this 20 | return this.api.execute(function (selector) { 21 | return document.querySelectorAll(selector).length 22 | }, [selector], function (res) { 23 | cb.call(self, res) 24 | }) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /client/test/e2e/nightwatch.conf.js: -------------------------------------------------------------------------------- 1 | require('babel-register') 2 | var config = require('../../config') 3 | 4 | // http://nightwatchjs.org/gettingstarted#settings-file 5 | module.exports = { 6 | src_folders: ['test/e2e/specs'], 7 | output_folder: 'test/e2e/reports', 8 | custom_assertions_path: ['test/e2e/custom-assertions'], 9 | 10 | selenium: { 11 | start_process: true, 12 | server_path: require('selenium-server').path, 13 | host: '127.0.0.1', 14 | port: 4444, 15 | cli_args: { 16 | 'webdriver.chrome.driver': require('chromedriver').path 17 | } 18 | }, 19 | 20 | test_settings: { 21 | default: { 22 | selenium_port: 4444, 23 | selenium_host: 'localhost', 24 | silent: true, 25 | globals: { 26 | devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port) 27 | } 28 | }, 29 | 30 | chrome: { 31 | desiredCapabilities: { 32 | browserName: 'chrome', 33 | javascriptEnabled: true, 34 | acceptSslCerts: true 35 | } 36 | }, 37 | 38 | firefox: { 39 | desiredCapabilities: { 40 | browserName: 'firefox', 41 | javascriptEnabled: true, 42 | acceptSslCerts: true 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /client/test/e2e/runner.js: -------------------------------------------------------------------------------- 1 | // 1. start the dev server using production config 2 | process.env.NODE_ENV = 'testing' 3 | var server = require('../../build/dev-server.js') 4 | 5 | server.ready.then(() => { 6 | // 2. run the nightwatch test suite against it 7 | // to run in additional browsers: 8 | // 1. add an entry in test/e2e/nightwatch.conf.json under "test_settings" 9 | // 2. add it to the --env flag below 10 | // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox` 11 | // For more information on Nightwatch's config file, see 12 | // http://nightwatchjs.org/guide#settings-file 13 | var opts = process.argv.slice(2) 14 | if (opts.indexOf('--config') === -1) { 15 | opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js']) 16 | } 17 | if (opts.indexOf('--env') === -1) { 18 | opts = opts.concat(['--env', 'chrome']) 19 | } 20 | 21 | var spawn = require('cross-spawn') 22 | var runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' }) 23 | 24 | runner.on('exit', function (code) { 25 | server.close() 26 | process.exit(code) 27 | }) 28 | 29 | runner.on('error', function (err) { 30 | server.close() 31 | throw err 32 | }) 33 | }) 34 | -------------------------------------------------------------------------------- /client/test/e2e/specs/test.js: -------------------------------------------------------------------------------- 1 | // For authoring Nightwatch tests, see 2 | // http://nightwatchjs.org/guide#usage 3 | 4 | module.exports = { 5 | 'default e2e tests': function (browser) { 6 | // automatically uses dev Server port from /config.index.js 7 | // default: http://localhost:8080 8 | // see nightwatch.conf.js 9 | const devServer = browser.globals.devServerURL 10 | 11 | browser 12 | .url(devServer) 13 | .waitForElementVisible('#app', 5000) 14 | .assert.elementPresent('.hello') 15 | .assert.containsText('h1', 'Welcome to Your Vue.js App') 16 | .assert.elementCount('img', 1) 17 | .end() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /client/test/unit/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | }, 5 | "globals": { 6 | "expect": true, 7 | "sinon": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /client/test/unit/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | Vue.config.productionTip = false 4 | 5 | // require all test files (files that ends with .spec.js) 6 | const testsContext = require.context('./specs', true, /\.spec$/) 7 | testsContext.keys().forEach(testsContext) 8 | 9 | // require all src files except main.js for coverage. 10 | // you can also change this to match only the subset of files that 11 | // you want coverage for. 12 | const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/) 13 | srcContext.keys().forEach(srcContext) 14 | -------------------------------------------------------------------------------- /client/test/unit/karma.conf.js: -------------------------------------------------------------------------------- 1 | // This is a karma config file. For more details see 2 | // http://karma-runner.github.io/0.13/config/configuration-file.html 3 | // we are also using it with karma-webpack 4 | // https://github.com/webpack/karma-webpack 5 | 6 | var webpackConfig = require('../../build/webpack.test.conf') 7 | 8 | module.exports = function (config) { 9 | config.set({ 10 | // to run in additional browsers: 11 | // 1. install corresponding karma launcher 12 | // http://karma-runner.github.io/0.13/config/browsers.html 13 | // 2. add it to the `browsers` array below. 14 | browsers: ['PhantomJS'], 15 | frameworks: ['mocha', 'sinon-chai', 'phantomjs-shim'], 16 | reporters: ['spec', 'coverage'], 17 | files: ['./index.js'], 18 | preprocessors: { 19 | './index.js': ['webpack', 'sourcemap'] 20 | }, 21 | webpack: webpackConfig, 22 | webpackMiddleware: { 23 | noInfo: true 24 | }, 25 | coverageReporter: { 26 | dir: './coverage', 27 | reporters: [ 28 | { type: 'lcov', subdir: '.' }, 29 | { type: 'text-summary' } 30 | ] 31 | } 32 | }) 33 | } 34 | -------------------------------------------------------------------------------- /client/test/unit/specs/Hello.spec.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Hello from '@/components/Hello' 3 | 4 | describe('Hello.vue', () => { 5 | it('should render correct contents', () => { 6 | const Constructor = Vue.extend(Hello) 7 | const vm = new Constructor().$mount() 8 | expect(vm.$el.querySelector('.hello h1').textContent) 9 | .to.equal('Welcome to Your Vue.js App') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /node_modules/debug/.coveralls.yml: -------------------------------------------------------------------------------- 1 | repo_token: SIAeZjKYlHK74rbcFvNHMUzjRiMpflxve 2 | -------------------------------------------------------------------------------- /node_modules/debug/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "node": true 5 | }, 6 | "rules": { 7 | "no-console": 0, 8 | "no-empty": [1, { "allowEmptyCatch": true }] 9 | }, 10 | "extends": "eslint:recommended" 11 | } 12 | -------------------------------------------------------------------------------- /node_modules/debug/.npmignore: -------------------------------------------------------------------------------- 1 | support 2 | test 3 | examples 4 | example 5 | *.sock 6 | dist 7 | yarn.lock 8 | coverage 9 | bower.json 10 | -------------------------------------------------------------------------------- /node_modules/debug/.travis.yml: -------------------------------------------------------------------------------- 1 | 2 | language: node_js 3 | node_js: 4 | - "6" 5 | - "5" 6 | - "4" 7 | 8 | install: 9 | - make node_modules 10 | 11 | script: 12 | - make lint 13 | - make test 14 | - make coveralls 15 | -------------------------------------------------------------------------------- /node_modules/debug/LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2014 TJ Holowaychuk 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software 6 | and associated documentation files (the 'Software'), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 9 | subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or substantial 12 | portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 15 | LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 16 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 17 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 18 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | -------------------------------------------------------------------------------- /node_modules/debug/Makefile: -------------------------------------------------------------------------------- 1 | # get Makefile directory name: http://stackoverflow.com/a/5982798/376773 2 | THIS_MAKEFILE_PATH:=$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)) 3 | THIS_DIR:=$(shell cd $(dir $(THIS_MAKEFILE_PATH));pwd) 4 | 5 | # BIN directory 6 | BIN := $(THIS_DIR)/node_modules/.bin 7 | 8 | # Path 9 | PATH := node_modules/.bin:$(PATH) 10 | SHELL := /bin/bash 11 | 12 | # applications 13 | NODE ?= $(shell which node) 14 | YARN ?= $(shell which yarn) 15 | PKG ?= $(if $(YARN),$(YARN),$(NODE) $(shell which npm)) 16 | BROWSERIFY ?= $(NODE) $(BIN)/browserify 17 | 18 | .FORCE: 19 | 20 | install: node_modules 21 | 22 | node_modules: package.json 23 | @NODE_ENV= $(PKG) install 24 | @touch node_modules 25 | 26 | lint: .FORCE 27 | eslint browser.js debug.js index.js node.js 28 | 29 | test-node: .FORCE 30 | istanbul cover node_modules/mocha/bin/_mocha -- test/**.js 31 | 32 | test-browser: .FORCE 33 | mkdir -p dist 34 | 35 | @$(BROWSERIFY) \ 36 | --standalone debug \ 37 | . > dist/debug.js 38 | 39 | karma start --single-run 40 | rimraf dist 41 | 42 | test: .FORCE 43 | concurrently \ 44 | "make test-node" \ 45 | "make test-browser" 46 | 47 | coveralls: 48 | cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js 49 | 50 | .PHONY: all install clean distclean 51 | -------------------------------------------------------------------------------- /node_modules/debug/component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "debug", 3 | "repo": "visionmedia/debug", 4 | "description": "small debugging utility", 5 | "version": "2.6.9", 6 | "keywords": [ 7 | "debug", 8 | "log", 9 | "debugger" 10 | ], 11 | "main": "src/browser.js", 12 | "scripts": [ 13 | "src/browser.js", 14 | "src/debug.js" 15 | ], 16 | "dependencies": { 17 | "rauchg/ms.js": "0.7.1" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /node_modules/debug/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | // Generated on Fri Dec 16 2016 13:09:51 GMT+0000 (UTC) 3 | 4 | module.exports = function(config) { 5 | config.set({ 6 | 7 | // base path that will be used to resolve all patterns (eg. files, exclude) 8 | basePath: '', 9 | 10 | 11 | // frameworks to use 12 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter 13 | frameworks: ['mocha', 'chai', 'sinon'], 14 | 15 | 16 | // list of files / patterns to load in the browser 17 | files: [ 18 | 'dist/debug.js', 19 | 'test/*spec.js' 20 | ], 21 | 22 | 23 | // list of files to exclude 24 | exclude: [ 25 | 'src/node.js' 26 | ], 27 | 28 | 29 | // preprocess matching files before serving them to the browser 30 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor 31 | preprocessors: { 32 | }, 33 | 34 | // test results reporter to use 35 | // possible values: 'dots', 'progress' 36 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter 37 | reporters: ['progress'], 38 | 39 | 40 | // web server port 41 | port: 9876, 42 | 43 | 44 | // enable / disable colors in the output (reporters and logs) 45 | colors: true, 46 | 47 | 48 | // level of logging 49 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 50 | logLevel: config.LOG_INFO, 51 | 52 | 53 | // enable / disable watching file and executing tests whenever any file changes 54 | autoWatch: true, 55 | 56 | 57 | // start these browsers 58 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 59 | browsers: ['PhantomJS'], 60 | 61 | 62 | // Continuous Integration mode 63 | // if true, Karma captures browsers, runs the tests and exits 64 | singleRun: false, 65 | 66 | // Concurrency level 67 | // how many browser should be started simultaneous 68 | concurrency: Infinity 69 | }) 70 | } 71 | -------------------------------------------------------------------------------- /node_modules/debug/node.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./src/node'); 2 | -------------------------------------------------------------------------------- /node_modules/debug/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "_args": [ 3 | [ 4 | { 5 | "raw": "debug@^2.1.3", 6 | "scope": null, 7 | "escapedName": "debug", 8 | "name": "debug", 9 | "rawSpec": "^2.1.3", 10 | "spec": ">=2.1.3 <3.0.0", 11 | "type": "range" 12 | }, 13 | "D:\\stark\\vnshop\\node_modules\\jsonp" 14 | ] 15 | ], 16 | "_from": "debug@>=2.1.3 <3.0.0", 17 | "_id": "debug@2.6.9", 18 | "_inCache": true, 19 | "_location": "/debug", 20 | "_nodeVersion": "8.4.0", 21 | "_npmOperationalInternal": { 22 | "host": "s3://npm-registry-packages", 23 | "tmp": "tmp/debug-2.6.9.tgz_1506087154503_0.5196126794908196" 24 | }, 25 | "_npmUser": { 26 | "name": "tootallnate", 27 | "email": "nathan@tootallnate.net" 28 | }, 29 | "_npmVersion": "5.3.0", 30 | "_phantomChildren": {}, 31 | "_requested": { 32 | "raw": "debug@^2.1.3", 33 | "scope": null, 34 | "escapedName": "debug", 35 | "name": "debug", 36 | "rawSpec": "^2.1.3", 37 | "spec": ">=2.1.3 <3.0.0", 38 | "type": "range" 39 | }, 40 | "_requiredBy": [ 41 | "/jsonp" 42 | ], 43 | "_resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 44 | "_shasum": "5d128515df134ff327e90a4c93f4e077a536341f", 45 | "_shrinkwrap": null, 46 | "_spec": "debug@^2.1.3", 47 | "_where": "D:\\stark\\vnshop\\node_modules\\jsonp", 48 | "author": { 49 | "name": "TJ Holowaychuk", 50 | "email": "tj@vision-media.ca" 51 | }, 52 | "browser": "./src/browser.js", 53 | "bugs": { 54 | "url": "https://github.com/visionmedia/debug/issues" 55 | }, 56 | "component": { 57 | "scripts": { 58 | "debug/index.js": "browser.js", 59 | "debug/debug.js": "debug.js" 60 | } 61 | }, 62 | "contributors": [ 63 | { 64 | "name": "Nathan Rajlich", 65 | "email": "nathan@tootallnate.net", 66 | "url": "http://n8.io" 67 | }, 68 | { 69 | "name": "Andrew Rhyne", 70 | "email": "rhyneandrew@gmail.com" 71 | } 72 | ], 73 | "dependencies": { 74 | "ms": "2.0.0" 75 | }, 76 | "description": "small debugging utility", 77 | "devDependencies": { 78 | "browserify": "9.0.3", 79 | "chai": "^3.5.0", 80 | "concurrently": "^3.1.0", 81 | "coveralls": "^2.11.15", 82 | "eslint": "^3.12.1", 83 | "istanbul": "^0.4.5", 84 | "karma": "^1.3.0", 85 | "karma-chai": "^0.1.0", 86 | "karma-mocha": "^1.3.0", 87 | "karma-phantomjs-launcher": "^1.0.2", 88 | "karma-sinon": "^1.0.5", 89 | "mocha": "^3.2.0", 90 | "mocha-lcov-reporter": "^1.2.0", 91 | "rimraf": "^2.5.4", 92 | "sinon": "^1.17.6", 93 | "sinon-chai": "^2.8.0" 94 | }, 95 | "directories": {}, 96 | "dist": { 97 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 98 | "shasum": "5d128515df134ff327e90a4c93f4e077a536341f", 99 | "tarball": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" 100 | }, 101 | "gitHead": "13abeae468fea297d0dccc50bc55590809241083", 102 | "homepage": "https://github.com/visionmedia/debug#readme", 103 | "keywords": [ 104 | "debug", 105 | "log", 106 | "debugger" 107 | ], 108 | "license": "MIT", 109 | "main": "./src/index.js", 110 | "maintainers": [ 111 | { 112 | "name": "thebigredgeek", 113 | "email": "rhyneandrew@gmail.com" 114 | }, 115 | { 116 | "name": "kolban", 117 | "email": "kolban1@kolban.com" 118 | }, 119 | { 120 | "name": "tootallnate", 121 | "email": "nathan@tootallnate.net" 122 | }, 123 | { 124 | "name": "tjholowaychuk", 125 | "email": "tj@vision-media.ca" 126 | } 127 | ], 128 | "name": "debug", 129 | "optionalDependencies": {}, 130 | "readme": "ERROR: No README data found!", 131 | "repository": { 132 | "type": "git", 133 | "url": "git://github.com/visionmedia/debug.git" 134 | }, 135 | "version": "2.6.9" 136 | } 137 | -------------------------------------------------------------------------------- /node_modules/debug/src/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Detect Electron renderer process, which is node, but we should 3 | * treat as a browser. 4 | */ 5 | 6 | if (typeof process !== 'undefined' && process.type === 'renderer') { 7 | module.exports = require('./browser.js'); 8 | } else { 9 | module.exports = require('./node.js'); 10 | } 11 | -------------------------------------------------------------------------------- /node_modules/debug/src/inspector-log.js: -------------------------------------------------------------------------------- 1 | module.exports = inspectorLog; 2 | 3 | // black hole 4 | const nullStream = new (require('stream').Writable)(); 5 | nullStream._write = () => {}; 6 | 7 | /** 8 | * Outputs a `console.log()` to the Node.js Inspector console *only*. 9 | */ 10 | function inspectorLog() { 11 | const stdout = console._stdout; 12 | console._stdout = nullStream; 13 | console.log.apply(console, arguments); 14 | console._stdout = stdout; 15 | } 16 | -------------------------------------------------------------------------------- /node_modules/jsonp/.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /node_modules/jsonp/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '0.10' 4 | env: 5 | global: 6 | - secure: UOzXsaDRo/x7DYmfkhWHCSMf42tqJY7kuL+YcId8kK84Ffn6UN3FVHQBzIE4Ri7zH3h83lGrjkp8FZeONovRXWC/2HF5idI3FwKDiAFhpRkJvXDH72CcmLr9atMV66WVUWLWUUWbMRL8TNRk5Hhgm/y70fcy+jTYInUyX4X+lqA= 7 | - secure: R0xq3sNFDJRI08/25Vz0cJ14rEo6U/aL3D0J8QkoBb21ZQORqzTL6/3WR3tSnh+X+VKELpjS5L0G4qVgJmFQcQkyBFz+rTkcJHkE/IjO9EMV+P3EAetXirTaHBahcg33i3kOAJl4qCi9b/Y4c3atkt+ooGz3Hc67IEkHddYqp/E= 8 | -------------------------------------------------------------------------------- /node_modules/jsonp/.zuul.yml: -------------------------------------------------------------------------------- 1 | ui: tape 2 | browsers: 3 | - name: chrome 4 | version: 26..latest 5 | - name: firefox 6 | version: 21..latest 7 | - name: safari 8 | version: 5..latest 9 | - name: ie 10 | version: 6..latest 11 | - name: opera 12 | version: 11..latest 13 | - name: iphone 14 | version: 4.3..latest 15 | - name: ipad 16 | version: 4.3..latest 17 | - name: android 18 | version: 4.0..latest 19 | -------------------------------------------------------------------------------- /node_modules/jsonp/History.md: -------------------------------------------------------------------------------- 1 | 2 | 0.2.1 / 2016-10-31 3 | ================== 4 | 5 | * loose debug version (#21, @roderickhsiao) 6 | * component: update "repo" field 7 | 8 | 0.2.0 / 2015-03-18 9 | ================== 10 | 11 | * add `bower.json` 12 | * add travis/zuul/saucelabs testing 13 | * add support for custom callback `name` 14 | * pin `debug` dep 15 | 16 | 0.1.0 / 2014-12-30 17 | ================== 18 | 19 | * Make sure `script.parentNode` exists before removing the script element (#12, @azer) 20 | * Return function to cancel in-progress jsonp request (#11, @feross) 21 | * add documentation for `prefix` option (#10, @feross) 22 | 23 | 0.0.4 / 2014-03-11 24 | ================== 25 | 26 | * simplify the variable name "id" creation logic 27 | * Readme: add Installation notes 28 | * fix jshint warnings 29 | * add repository field to `package.json` 30 | * fallback to `document.head` if there is not any script tags in the dom 31 | * remove script safely 32 | 33 | 0.0.3 / 2013-02-03 34 | ================== 35 | 36 | * use `index.js` 37 | * go back to integer ids 38 | * honor `param` option 39 | 40 | 0.0.2 / 2013-02-03 41 | ================== 42 | 43 | * make IE<=8 happy 44 | 45 | 0.0.1 / 2012-07-03 46 | ================== 47 | 48 | * Initial release. 49 | -------------------------------------------------------------------------------- /node_modules/jsonp/Readme.md: -------------------------------------------------------------------------------- 1 | 2 | # jsonp 3 | 4 | A simple JSONP implementation. 5 | 6 | [![saucelabs][saucelabs-image]][saucelabs-url] 7 | 8 | ## Installation 9 | 10 | Install for node.js or browserify using `npm`: 11 | 12 | ``` bash 13 | $ npm install jsonp 14 | ``` 15 | 16 | Install for component(1) using `component`: 17 | 18 | ``` bash 19 | $ component install LearnBoost/jsonp 20 | ``` 21 | 22 | Install for browser using `bower`: 23 | 24 | ``` bash 25 | $ bower install jsonp 26 | ``` 27 | 28 | ## API 29 | 30 | ### jsonp(url, opts, fn) 31 | 32 | - `url` (`String`) url to fetch 33 | - `opts` (`Object`), optional 34 | - `param` (`String`) name of the query string parameter to specify 35 | the callback (defaults to `callback`) 36 | - `timeout` (`Number`) how long after a timeout error is emitted. `0` to 37 | disable (defaults to `60000`) 38 | - `prefix` (`String`) prefix for the global callback functions that 39 | handle jsonp responses (defaults to `__jp`) 40 | - `name` (`String`) name of the global callback functions that 41 | handle jsonp responses (defaults to `prefix` + incremented counter) 42 | - `fn` callback 43 | 44 | The callback is called with `err, data` parameters. 45 | 46 | If it times out, the `err` will be an `Error` object whose `message` is 47 | `Timeout`. 48 | 49 | Returns a function that, when called, will cancel the in-progress jsonp request 50 | (`fn` won't be called). 51 | 52 | ## License 53 | 54 | MIT 55 | 56 | [saucelabs-image]: https://saucelabs.com/browser-matrix/jsonp.svg 57 | [saucelabs-url]: https://saucelabs.com/u/jsonp 58 | -------------------------------------------------------------------------------- /node_modules/jsonp/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jsonp", 3 | "main": "index.js", 4 | "version": "0.2.1", 5 | "homepage": "https://github.com/webmodules/jsonp", 6 | "description": "A sane JSONP implementation.", 7 | "keywords": [ 8 | "jsonp" 9 | ], 10 | "license": "MIT", 11 | "ignore": [ 12 | "**/.*", 13 | "node_modules", 14 | "bower_components", 15 | "test", 16 | "tests" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /node_modules/jsonp/component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jsonp", 3 | "repo": "webmodules/jsonp", 4 | "description": "A sane JSONP implementation.", 5 | "version": "0.2.1", 6 | "dependencies": { 7 | "visionmedia/debug": "*" 8 | }, 9 | "scripts": [ 10 | "index.js" 11 | ], 12 | "main": "index.js" 13 | } 14 | -------------------------------------------------------------------------------- /node_modules/jsonp/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies 3 | */ 4 | 5 | var debug = require('debug')('jsonp'); 6 | 7 | /** 8 | * Module exports. 9 | */ 10 | 11 | module.exports = jsonp; 12 | 13 | /** 14 | * Callback index. 15 | */ 16 | 17 | var count = 0; 18 | 19 | /** 20 | * Noop function. 21 | */ 22 | 23 | function noop(){} 24 | 25 | /** 26 | * JSONP handler 27 | * 28 | * Options: 29 | * - param {String} qs parameter (`callback`) 30 | * - prefix {String} qs parameter (`__jp`) 31 | * - name {String} qs parameter (`prefix` + incr) 32 | * - timeout {Number} how long after a timeout error is emitted (`60000`) 33 | * 34 | * @param {String} url 35 | * @param {Object|Function} optional options / callback 36 | * @param {Function} optional callback 37 | */ 38 | 39 | function jsonp(url, opts, fn){ 40 | if ('function' == typeof opts) { 41 | fn = opts; 42 | opts = {}; 43 | } 44 | if (!opts) opts = {}; 45 | 46 | var prefix = opts.prefix || '__jp'; 47 | 48 | // use the callback name that was passed if one was provided. 49 | // otherwise generate a unique name by incrementing our counter. 50 | var id = opts.name || (prefix + (count++)); 51 | 52 | var param = opts.param || 'callback'; 53 | var timeout = null != opts.timeout ? opts.timeout : 60000; 54 | var enc = encodeURIComponent; 55 | var target = document.getElementsByTagName('script')[0] || document.head; 56 | var script; 57 | var timer; 58 | 59 | 60 | if (timeout) { 61 | timer = setTimeout(function(){ 62 | cleanup(); 63 | if (fn) fn(new Error('Timeout')); 64 | }, timeout); 65 | } 66 | 67 | function cleanup(){ 68 | if (script.parentNode) script.parentNode.removeChild(script); 69 | window[id] = noop; 70 | if (timer) clearTimeout(timer); 71 | } 72 | 73 | function cancel(){ 74 | if (window[id]) { 75 | cleanup(); 76 | } 77 | } 78 | 79 | window[id] = function(data){ 80 | debug('jsonp got', data); 81 | cleanup(); 82 | if (fn) fn(null, data); 83 | }; 84 | 85 | // add qs component 86 | url += (~url.indexOf('?') ? '&' : '?') + param + '=' + enc(id); 87 | url = url.replace('?&', '?'); 88 | 89 | debug('jsonp req "%s"', url); 90 | 91 | // create script 92 | script = document.createElement('script'); 93 | script.src = url; 94 | target.parentNode.insertBefore(script, target); 95 | 96 | return cancel; 97 | } 98 | -------------------------------------------------------------------------------- /node_modules/jsonp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "_args": [ 3 | [ 4 | { 5 | "raw": "jsonp", 6 | "scope": null, 7 | "escapedName": "jsonp", 8 | "name": "jsonp", 9 | "rawSpec": "", 10 | "spec": "latest", 11 | "type": "tag" 12 | }, 13 | "D:\\stark\\vnshop" 14 | ] 15 | ], 16 | "_from": "jsonp@latest", 17 | "_id": "jsonp@0.2.1", 18 | "_inCache": true, 19 | "_location": "/jsonp", 20 | "_nodeVersion": "6.9.1", 21 | "_npmOperationalInternal": { 22 | "host": "packages-12-west.internal.npmjs.com", 23 | "tmp": "tmp/jsonp-0.2.1.tgz_1481179988894_0.9502592894714326" 24 | }, 25 | "_npmUser": { 26 | "name": "feross", 27 | "email": "feross@feross.org" 28 | }, 29 | "_npmVersion": "3.10.8", 30 | "_phantomChildren": {}, 31 | "_requested": { 32 | "raw": "jsonp", 33 | "scope": null, 34 | "escapedName": "jsonp", 35 | "name": "jsonp", 36 | "rawSpec": "", 37 | "spec": "latest", 38 | "type": "tag" 39 | }, 40 | "_requiredBy": [ 41 | "#DEV:/", 42 | "#USER" 43 | ], 44 | "_resolved": "https://registry.npmjs.org/jsonp/-/jsonp-0.2.1.tgz", 45 | "_shasum": "a65b4fa0f10bda719a05441ea7b94c55f3e15bae", 46 | "_shrinkwrap": null, 47 | "_spec": "jsonp", 48 | "_where": "D:\\stark\\vnshop", 49 | "bugs": { 50 | "url": "https://github.com/LearnBoost/jsonp/issues" 51 | }, 52 | "component": { 53 | "scripts": { 54 | "jsonp": "jsonp.js" 55 | } 56 | }, 57 | "dependencies": { 58 | "debug": "^2.1.3" 59 | }, 60 | "description": "A sane JSONP implementation.", 61 | "devDependencies": { 62 | "tape": "^3.5.0", 63 | "zuul": "^1.17.1" 64 | }, 65 | "directories": {}, 66 | "dist": { 67 | "shasum": "a65b4fa0f10bda719a05441ea7b94c55f3e15bae", 68 | "tarball": "https://registry.npmjs.org/jsonp/-/jsonp-0.2.1.tgz" 69 | }, 70 | "gitHead": "790398945dc391ad2f06b365193a040a3dc01977", 71 | "homepage": "https://github.com/LearnBoost/jsonp#readme", 72 | "maintainers": [ 73 | { 74 | "name": "feross", 75 | "email": "feross@feross.org" 76 | }, 77 | { 78 | "name": "rauchg", 79 | "email": "rauchg@gmail.com" 80 | }, 81 | { 82 | "name": "tootallnate", 83 | "email": "nathan@tootallnate.net" 84 | } 85 | ], 86 | "name": "jsonp", 87 | "optionalDependencies": {}, 88 | "readme": "ERROR: No README data found!", 89 | "repository": { 90 | "type": "git", 91 | "url": "git+https://github.com/LearnBoost/jsonp.git" 92 | }, 93 | "scripts": { 94 | "test": "zuul -- test/*.js", 95 | "test-local": "zuul --local -- test/*.js" 96 | }, 97 | "version": "0.2.1" 98 | } 99 | -------------------------------------------------------------------------------- /node_modules/jsonp/test/basic.js: -------------------------------------------------------------------------------- 1 | var jsonp = require('../'); 2 | var querystring = require('querystring'); 3 | var test = require('tape'); 4 | 5 | // See http://doc.jsfiddle.net/use/echo.html 6 | var ENDPOINT = 'http://jsfiddle.net/echo/jsonp/'; 7 | 8 | test('basic jsonp', function (t) { 9 | t.plan(1); 10 | var obj = { 11 | beep: 'boop', 12 | yo: 'dawg' 13 | }; 14 | var q = querystring.encode(obj); 15 | jsonp(ENDPOINT + '?' + q, function (err, data) { 16 | if (err) throw err; 17 | t.deepEqual(data, obj); 18 | }); 19 | }); 20 | 21 | test('timeout', function (t) { 22 | t.plan(1); 23 | var obj = { 24 | delay: 5 // time in seconds after which data should be returned 25 | }; 26 | var q = querystring.encode(obj); 27 | jsonp(ENDPOINT + '?' + q, { timeout: 3000 }, function (err, data) { 28 | t.ok(err instanceof Error); 29 | }); 30 | }); 31 | 32 | test('named callback', function (t) { 33 | t.plan(1); 34 | var obj = { 35 | beep: 'boop', 36 | yo: 'dawg' 37 | }; 38 | var q = querystring.encode(obj); 39 | jsonp(ENDPOINT + '?' + q, { name: 'namedCb' }, function (err, data) { 40 | if (err) throw err; 41 | t.deepEqual(data, obj); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /node_modules/ms/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Helpers. 3 | */ 4 | 5 | var s = 1000; 6 | var m = s * 60; 7 | var h = m * 60; 8 | var d = h * 24; 9 | var y = d * 365.25; 10 | 11 | /** 12 | * Parse or format the given `val`. 13 | * 14 | * Options: 15 | * 16 | * - `long` verbose formatting [false] 17 | * 18 | * @param {String|Number} val 19 | * @param {Object} [options] 20 | * @throws {Error} throw an error if val is not a non-empty string or a number 21 | * @return {String|Number} 22 | * @api public 23 | */ 24 | 25 | module.exports = function(val, options) { 26 | options = options || {}; 27 | var type = typeof val; 28 | if (type === 'string' && val.length > 0) { 29 | return parse(val); 30 | } else if (type === 'number' && isNaN(val) === false) { 31 | return options.long ? fmtLong(val) : fmtShort(val); 32 | } 33 | throw new Error( 34 | 'val is not a non-empty string or a valid number. val=' + 35 | JSON.stringify(val) 36 | ); 37 | }; 38 | 39 | /** 40 | * Parse the given `str` and return milliseconds. 41 | * 42 | * @param {String} str 43 | * @return {Number} 44 | * @api private 45 | */ 46 | 47 | function parse(str) { 48 | str = String(str); 49 | if (str.length > 100) { 50 | return; 51 | } 52 | var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec( 53 | str 54 | ); 55 | if (!match) { 56 | return; 57 | } 58 | var n = parseFloat(match[1]); 59 | var type = (match[2] || 'ms').toLowerCase(); 60 | switch (type) { 61 | case 'years': 62 | case 'year': 63 | case 'yrs': 64 | case 'yr': 65 | case 'y': 66 | return n * y; 67 | case 'days': 68 | case 'day': 69 | case 'd': 70 | return n * d; 71 | case 'hours': 72 | case 'hour': 73 | case 'hrs': 74 | case 'hr': 75 | case 'h': 76 | return n * h; 77 | case 'minutes': 78 | case 'minute': 79 | case 'mins': 80 | case 'min': 81 | case 'm': 82 | return n * m; 83 | case 'seconds': 84 | case 'second': 85 | case 'secs': 86 | case 'sec': 87 | case 's': 88 | return n * s; 89 | case 'milliseconds': 90 | case 'millisecond': 91 | case 'msecs': 92 | case 'msec': 93 | case 'ms': 94 | return n; 95 | default: 96 | return undefined; 97 | } 98 | } 99 | 100 | /** 101 | * Short format for `ms`. 102 | * 103 | * @param {Number} ms 104 | * @return {String} 105 | * @api private 106 | */ 107 | 108 | function fmtShort(ms) { 109 | if (ms >= d) { 110 | return Math.round(ms / d) + 'd'; 111 | } 112 | if (ms >= h) { 113 | return Math.round(ms / h) + 'h'; 114 | } 115 | if (ms >= m) { 116 | return Math.round(ms / m) + 'm'; 117 | } 118 | if (ms >= s) { 119 | return Math.round(ms / s) + 's'; 120 | } 121 | return ms + 'ms'; 122 | } 123 | 124 | /** 125 | * Long format for `ms`. 126 | * 127 | * @param {Number} ms 128 | * @return {String} 129 | * @api private 130 | */ 131 | 132 | function fmtLong(ms) { 133 | return plural(ms, d, 'day') || 134 | plural(ms, h, 'hour') || 135 | plural(ms, m, 'minute') || 136 | plural(ms, s, 'second') || 137 | ms + ' ms'; 138 | } 139 | 140 | /** 141 | * Pluralization helper. 142 | */ 143 | 144 | function plural(ms, n, name) { 145 | if (ms < n) { 146 | return; 147 | } 148 | if (ms < n * 1.5) { 149 | return Math.floor(ms / n) + ' ' + name; 150 | } 151 | return Math.ceil(ms / n) + ' ' + name + 's'; 152 | } 153 | -------------------------------------------------------------------------------- /node_modules/ms/license.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Zeit, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /node_modules/ms/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "_args": [ 3 | [ 4 | { 5 | "raw": "ms@2.0.0", 6 | "scope": null, 7 | "escapedName": "ms", 8 | "name": "ms", 9 | "rawSpec": "2.0.0", 10 | "spec": "2.0.0", 11 | "type": "version" 12 | }, 13 | "D:\\stark\\vnshop\\node_modules\\debug" 14 | ] 15 | ], 16 | "_from": "ms@2.0.0", 17 | "_id": "ms@2.0.0", 18 | "_inCache": true, 19 | "_location": "/ms", 20 | "_nodeVersion": "7.8.0", 21 | "_npmOperationalInternal": { 22 | "host": "packages-18-east.internal.npmjs.com", 23 | "tmp": "tmp/ms-2.0.0.tgz_1494937565215_0.34005374647676945" 24 | }, 25 | "_npmUser": { 26 | "name": "leo", 27 | "email": "leo@zeit.co" 28 | }, 29 | "_npmVersion": "4.2.0", 30 | "_phantomChildren": {}, 31 | "_requested": { 32 | "raw": "ms@2.0.0", 33 | "scope": null, 34 | "escapedName": "ms", 35 | "name": "ms", 36 | "rawSpec": "2.0.0", 37 | "spec": "2.0.0", 38 | "type": "version" 39 | }, 40 | "_requiredBy": [ 41 | "/debug" 42 | ], 43 | "_resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 44 | "_shasum": "5608aeadfc00be6c2901df5f9861788de0d597c8", 45 | "_shrinkwrap": null, 46 | "_spec": "ms@2.0.0", 47 | "_where": "D:\\stark\\vnshop\\node_modules\\debug", 48 | "bugs": { 49 | "url": "https://github.com/zeit/ms/issues" 50 | }, 51 | "dependencies": {}, 52 | "description": "Tiny milisecond conversion utility", 53 | "devDependencies": { 54 | "eslint": "3.19.0", 55 | "expect.js": "0.3.1", 56 | "husky": "0.13.3", 57 | "lint-staged": "3.4.1", 58 | "mocha": "3.4.1" 59 | }, 60 | "directories": {}, 61 | "dist": { 62 | "shasum": "5608aeadfc00be6c2901df5f9861788de0d597c8", 63 | "tarball": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" 64 | }, 65 | "eslintConfig": { 66 | "extends": "eslint:recommended", 67 | "env": { 68 | "node": true, 69 | "es6": true 70 | } 71 | }, 72 | "files": [ 73 | "index.js" 74 | ], 75 | "gitHead": "9b88d1568a52ec9bb67ecc8d2aa224fa38fd41f4", 76 | "homepage": "https://github.com/zeit/ms#readme", 77 | "license": "MIT", 78 | "lint-staged": { 79 | "*.js": [ 80 | "npm run lint", 81 | "prettier --single-quote --write", 82 | "git add" 83 | ] 84 | }, 85 | "main": "./index", 86 | "maintainers": [ 87 | { 88 | "name": "leo", 89 | "email": "leo@zeit.co" 90 | }, 91 | { 92 | "name": "rauchg", 93 | "email": "rauchg@gmail.com" 94 | } 95 | ], 96 | "name": "ms", 97 | "optionalDependencies": {}, 98 | "readme": "ERROR: No README data found!", 99 | "repository": { 100 | "type": "git", 101 | "url": "git+https://github.com/zeit/ms.git" 102 | }, 103 | "scripts": { 104 | "lint": "eslint lib/* bin/*", 105 | "precommit": "lint-staged", 106 | "test": "mocha tests.js" 107 | }, 108 | "version": "2.0.0" 109 | } 110 | -------------------------------------------------------------------------------- /node_modules/ms/readme.md: -------------------------------------------------------------------------------- 1 | # ms 2 | 3 | [![Build Status](https://travis-ci.org/zeit/ms.svg?branch=master)](https://travis-ci.org/zeit/ms) 4 | [![Slack Channel](http://zeit-slackin.now.sh/badge.svg)](https://zeit.chat/) 5 | 6 | Use this package to easily convert various time formats to milliseconds. 7 | 8 | ## Examples 9 | 10 | ```js 11 | ms('2 days') // 172800000 12 | ms('1d') // 86400000 13 | ms('10h') // 36000000 14 | ms('2.5 hrs') // 9000000 15 | ms('2h') // 7200000 16 | ms('1m') // 60000 17 | ms('5s') // 5000 18 | ms('1y') // 31557600000 19 | ms('100') // 100 20 | ``` 21 | 22 | ### Convert from milliseconds 23 | 24 | ```js 25 | ms(60000) // "1m" 26 | ms(2 * 60000) // "2m" 27 | ms(ms('10 hours')) // "10h" 28 | ``` 29 | 30 | ### Time format written-out 31 | 32 | ```js 33 | ms(60000, { long: true }) // "1 minute" 34 | ms(2 * 60000, { long: true }) // "2 minutes" 35 | ms(ms('10 hours'), { long: true }) // "10 hours" 36 | ``` 37 | 38 | ## Features 39 | 40 | - Works both in [node](https://nodejs.org) and in the browser. 41 | - If a number is supplied to `ms`, a string with a unit is returned. 42 | - If a string that contains the number is supplied, it returns it as a number (e.g.: it returns `100` for `'100'`). 43 | - If you pass a string with a number and a valid unit, the number of equivalent ms is returned. 44 | 45 | ## Caught a bug? 46 | 47 | 1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device 48 | 2. Link the package to the global module directory: `npm link` 49 | 3. Within the module you want to test your local development instance of ms, just link it to the dependencies: `npm link ms`. Instead of the default one from npm, node will now use your clone of ms! 50 | 51 | As always, you can run the tests using: `npm test` 52 | -------------------------------------------------------------------------------- /note/01.开发goodlist组件.md: -------------------------------------------------------------------------------- 1 | ##把准备好的静态问题复制到 views/Goodlist.vue 2 | 3 | ## 静态文件是指 在仓库里面拉取的 shop-static 项目 4 | ``` 5 | https://github.com/itguide/shop-static 6 | ``` 7 | ### 创建GoodsList.vue 组件文件 8 | 在src里面创建一个views文件夹 9 | 在这个views里面 10 | 创建一个GoodsList.vue 文件 11 | ### 把静态文件里面的 body里面的文件复制到 12 | GoodsList.vue 13 | 14 | 19 | 24 | 25 | ### 把静态文件里面 shop-static/img 文件夹复制到 vue 项目 static 里面 26 | 27 | ### 修改路由里面的文件 28 | ``` 29 | import Vue from 'vue'; 30 | import Router from 'vue-router'; 31 | import HelloWorld from '@/components/HelloWorld'; 32 | import GoodsList from '@/views/GoodsList'; // 增加了 引入这个组件 33 | 34 | Vue.use(Router); 35 | 36 | export default new Router({ 37 | routes: [{ 38 | path: '/', 39 | name: 'Hello', 40 | component: GoodsList, //修改这个组件名字 41 | }, ], 42 | }); 43 | ``` -------------------------------------------------------------------------------- /note/02.vue项目中的@符号的意思.md: -------------------------------------------------------------------------------- 1 | ## @是什么意思? 2 | 3 | ## @ -> src 4 | 5 | ## 为什么是src 6 | 7 | ``` 8 | resolve: { 9 | extensions: ['.js', '.vue', '.json'], 10 | alias: { 11 | 'vue$': 'vue/dist/vue.esm.js', 12 | '@': resolve('src'), // @符号代表 src 13 | } 14 | }, 15 | ``` -------------------------------------------------------------------------------- /note/03.在项目中引入css样式的方法.md: -------------------------------------------------------------------------------- 1 | ##在组件里面引入 2 | 使用相对路径 3 | ``` 4 | 11 | ``` 12 | 13 | ## 在全局引入 14 | 15 | ``` 16 | 在入口文件引入 17 | main.js 18 | import '../static/css/index.css' 19 | 20 | 在css里面新建一个index.css 21 | 把所有的css 从这导入 22 | 23 | index.css 24 | @import 'base.css'; 25 | @import 'product.css'; 26 | @import 'checkout.css'; 27 | @import 'login.css'; 28 | ``` -------------------------------------------------------------------------------- /note/04.当后端接口还没写完的时候.此时怎么做才不影响开发进度.md: -------------------------------------------------------------------------------- 1 | # 后端接口还没写完,怎么做? 2 | ## 使用mock数据 3 | easy-mock.com 4 | 5 | 看06 笔记 6 | -------------------------------------------------------------------------------- /note/05.部组件拆分使用.md: -------------------------------------------------------------------------------- 1 | ##把可以拆分组件的内容单独放在一个组件 2 | 3 | ## 在需要的用到的组件里面引入 4 | 以下以 GoodsList.vue 为列子 5 | ``` 6 | 在script里面 7 | 先引入需要的子组件 8 | import NavHeader from '@/components/Header' 9 | import NavFooter from '@/components/Footer' 10 | import NavBread from '@/components/NavBread' 11 | 12 | export default{ 13 | 14 | 15 | components:{ 16 | NavHeader, 17 | NavFooter, 18 | NavBread 19 | }, 20 | 21 | 22 | ``` 23 | ## 在dom中使用 24 | 25 | ``` 26 | 如果不向自组件传递内容 27 | 就直接使用自闭合的标签 28 | 29 | 如果需要传递内容 需要在自组件里面写 插槽 slot 30 | 商品首页 31 | ``` -------------------------------------------------------------------------------- /note/06.模拟mock数据.md: -------------------------------------------------------------------------------- 1 | ## 可以使用第三方平台提供的数据 2 | easy-mock.com 3 | 在这个平台上可以把自己的json 数据方上去,可以修改请求的方式,post get 4 | 5 | ## 在本地新建一个mock的文件夹,里面放置json数据,使用vue cli server的express把这个数据请求,分发接口,供vue里面使用 6 | ``` 7 | 8 | 先引入外部json数据 9 | var goodsData = require('../mock/mock-goods.json'); 10 | 声明路由 11 | var router = express.Router(); 12 | 写一个goods接口 13 | router.get("/goods", function(req, res, next) { 14 | 当别人访问goods接口的时候,把这个数据以json方式返回给用户 15 | res.json(goodsData); 16 | }) 17 | 使用路由 18 | app.use(router); 19 | 20 | ``` 21 | 22 | 23 | ## 在vuejs里面使用axios请求以上两种接口 24 | ``` 25 | methods:{ 26 | getGoodsList(){ 27 | axios.get('http://easy-mock.com/mock/59664d4d58618039284c7710/example/goods/list').then(res=>{ 28 | console.log(res); 29 | this.goods = res.data.data; 30 | }) 31 | // axios.get('goods').then(res=>{ 32 | // this.goods = res.data.data; 33 | // }) 34 | } 35 | } 36 | ``` -------------------------------------------------------------------------------- /note/07.图片懒加载.md: -------------------------------------------------------------------------------- 1 | #在vue中使用图片懒加载详细指南 2 | 3 | https://segmentfault.com/a/1190000011672452 4 | ## 说明 5 | > 当网络请求比较慢的时候,提前给这张图片添加一个像素比较低的占位图片,不至于堆叠在一块,或显示大片空白,让用户体验更好一点。 6 | ## 使用方式 7 | 使用vue的 vue-lazyload 插件 8 | 插件地址: 9 | ``` 10 | https://www.npmjs.com/package/vue-lazyload 11 | 12 | ``` 13 | ## 案例 14 | demo: [懒加载案例demo](http://hilongjw.github.io/vue-lazyload/) 15 | 16 | # Installation 安装方式 17 | 18 | ## npm 19 | 20 | ```bash 21 | 22 | $ npm i vue-lazyload -D 23 | 24 | ``` 25 | 26 | ## CDN 27 | 28 | CDN: [https://unpkg.com/vue-lazyload/vue-lazyload.js](https://unpkg.com/vue-lazyload/vue-lazyload.js) 29 | 30 | ```html 31 | 32 | 36 | 37 | ``` 38 | 39 | # 用法 40 | 41 | main.js 在入口文件 42 | 43 | ```javascript 44 | 45 | import Vue from 'vue' 46 | import App from './App.vue' 47 | import VueLazyload from 'vue-lazyload' //引入这个懒加载插件 48 | 49 | Vue.use(VueLazyload) 50 | 51 | // 或者添加VueLazyload 选项 52 | Vue.use(VueLazyload, { 53 | preLoad: 1.3, 54 | error: 'dist/error.png', 55 | loading: 'dist/loading.gif', 56 | attempt: 1 57 | }) 58 | 59 | new Vue({ 60 | el: 'body', 61 | components: { 62 | App 63 | } 64 | }) 65 | ``` 66 | 67 | ## 在入口文件添加后,在组件任何地方都可以直接使用把 img 里的:src -> v-lazy 68 | ``` 69 |
70 | 71 |
72 | 73 | 把之前项目中img 标签里面的 :src 属性 改成 v-lazy 74 |
75 | 76 |
77 | ``` 78 | 79 | ## 参数选项说明 80 | 81 | |key|description|default|options| 82 | |:---|---|---|---| 83 | | `preLoad`|proportion of pre-loading height|`1.3`|`Number`| 84 | |`error`|当加载图片失败的时候|`'data-src'`|`String` 85 | |`loading`|当加载图片成功的时候|`'data-src'`|`String`| 86 | |`attempt`|尝试计数|`3`|`Number`| 87 | |`listenEvents`|想要监听的事件|`['scroll', 'wheel', 'mousewheel', 'resize', 'animationend', 'transitionend', 'touchmove']`| [Desired Listen Events](#desired-listen-events) | 88 | |`adapter`| 动态修改元素属性 |`{ }`| [Element Adapter](#element-adapter) | 89 | |`filter`| 图片监听或过滤器|`{ }`| [Image listener filter](#image-listener-filter) | 90 | |`lazyComponent`| lazyload component | `false` | [Lazy Component](#lazy-component) 91 | | `dispatchEvent`|触发dom事件|`false`|`Boolean`| 92 | | `throttleWait`|throttle wait|`200`|`Number`| 93 | | `observer`|use IntersectionObserver|`false`|`Boolean`| 94 | | `observerOptions`|IntersectionObserver options|{ rootMargin: '0px', threshold: 0.1 }|[IntersectionObserver](#intersectionobserver)| 95 | 96 | ### 想要监听的事件 97 | 98 | 您可以通过传递数组来配置想要使用vue - lazyload的事件 99 | 监听器的名字。 100 | 101 | ```javascript 102 | Vue.use(VueLazyload, { 103 | preLoad: 1.3, 104 | error: 'dist/error.png', 105 | loading: 'dist/loading.gif', 106 | attempt: 1, 107 | // the default is ['scroll', 'wheel', 'mousewheel', 'resize', 'animationend', 'transitionend'] 108 | listenEvents: [ 'scroll' ] 109 | }) 110 | ``` 111 | 112 | 如果您遇到这个插件重新设置加载的麻烦,这是很有用的 113 | 当你有某些动画和过渡的时候。 114 | -------------------------------------------------------------------------------- /note/08.使用express-generator生成express项目.md: -------------------------------------------------------------------------------- 1 | #【express项目脚手架】使用express-generator生成express项目 2 | ## 用法 3 | 4 | ### 安装全局express命令行 5 | ``` 6 | npm install express-generator -D 7 | ``` 8 | 9 | ### 生成项目,并且安装项目依赖的包 10 | ``` 11 | express server 12 | cd server 13 | npm i 14 | ``` 15 | 16 | ### 启动方式 17 | 18 | ``` 19 | node bin/www 20 | ``` 21 | 22 | ### 访问 localhost:3000 23 | 24 | ### 添加git忽略文件 .gitignore 25 | ``` 26 | .DS_Store 27 | node_modules/ 28 | dist/ 29 | npm-debug.log* 30 | yarn-debug.log* 31 | yarn-error.log* 32 | test/unit/coverage 33 | test/e2e/reports 34 | selenium-debug.log 35 | 36 | # Editor directories and files 37 | .idea 38 | .vscode 39 | *.suo 40 | *.ntvs* 41 | *.njsproj 42 | *.sln 43 | 44 | ``` 45 | 46 | ## 优化启动方式,让每次修改代码后不需要重启 47 | ### 使用nodemon方式: 48 | [nodemon](https://www.npmjs.com/package/nodemon) 49 | #### 安装 50 | ``` 51 | 全局安装: 52 | npm install -g nodemon 53 | 54 | or 55 | 本地安装: 56 | npm install --save-dev nodemon 57 | ``` 58 | #### 在package.json里面配置快捷启动方式 59 | > 在package.json 的scripts选项里面添加 60 | 61 | ``` 62 | "scripts": { 63 | "start": "node ./bin/www", 64 | "dev": "nodemon ./bin/www" 65 | }, 66 | ``` 67 | 68 | > 此时启动方式是: 69 | ``` 70 | npm run dev 71 | ``` 72 | 73 | ### 使用supervisor方式 74 | 75 | #### 使用方式说明 76 | ``` 77 | 安装 78 | npm install supervisor -g 79 | 80 | 使用 81 | supervisor bin/www 82 | ``` 83 | #### 把supervisor bin/www 的启动的方式添加到package.json 84 | > 在package.json 的scripts选项里面添加 85 | 86 | ``` 87 | "scripts": { 88 | "start": "node ./bin/www", 89 | "sup": "supervisor ./bin/www" 90 | }, 91 | ``` 92 | 93 | > 此时启动方式是: 94 | ``` 95 | npm run sup 96 | ``` 97 | 98 | ### 使用pm2的方式 99 | >详细使用方式请去官网 100 | [pm2](http://pm2.keymetrics.io/) 101 | 102 | #### 全局安装 103 | 104 | ``` 105 | npm install pm2 -g 106 | 107 | 启动方式 108 | pm2 start ./bin/www 109 | 110 | ``` 111 | 112 | #### 113 | 114 | > 在package.json 的scripts选项里面添加 115 | 116 | ``` 117 | "scripts": { 118 | "start": "node ./bin/www", 119 | "pm2": "pm2 start ./bin/www" 120 | }, 121 | ``` 122 | 123 | > 此时启动方式是: 124 | ``` 125 | npm run pm2 126 | ``` 127 | -------------------------------------------------------------------------------- /note/09.express连接mongodb数据库.md: -------------------------------------------------------------------------------- 1 | ## 安装 mongoose 模块 2 | 3 | ``` 4 | npm i mongoose -D 5 | ``` -------------------------------------------------------------------------------- /note/10.mongoose.操作指南.md: -------------------------------------------------------------------------------- 1 | ## 官方手册 2 | [官方手册](http://mongoosejs.com/docs/api.html#model_Model.find) 3 | 4 | ## find 查询 5 | 6 | ``` 7 | // named john and at least 18 8 | MyModel.find({ name: 'john', age: { $gte: 18 }}); 9 | 10 | // executes immediately, passing results to callback 11 | MyModel.find({ name: 'john', age: { $gte: 18 }}, function (err, docs) {}); 12 | 13 | // name LIKE john and only selecting the "name" and "friends" fields, executing immediately 14 | MyModel.find({ name: /john/i }, 'name friends', function (err, docs) { }) 15 | 16 | // passing options 17 | MyModel.find({ name: /john/i }, null, { skip: 10 }) 18 | 19 | // passing options and executing immediately 20 | MyModel.find({ name: /john/i }, null, { skip: 10 }, function (err, docs) {}); 21 | 22 | // executing a query explicitly 23 | var query = MyModel.find({ name: /john/i }, null, { skip: 10 }) 24 | query.exec(function (err, docs) {}); 25 | 26 | // using the promise returned from executing a query 27 | var query = MyModel.find({ name: /john/i }, null, { skip: 10 }); 28 | var promise = query.exec(); 29 | promise.addBack(function (err, docs) {}); 30 | ``` 31 | 32 | ##教程 33 | 34 | [菜鸟教程](http://www.runoob.com/mongodb/mongodb-operators.html) 35 | 36 | ## MongoDB 排序 37 | 38 | MongoDB sort()方法 39 | 在MongoDB中使用使用sort()方法对数据进行排序,sort()方法可以通过参数指定排序的字段,并使用 1 和 -1 来指定排序的方式,其中 1 为升序排列,而-1是用于降序排列。 40 | 41 | ``` 42 | router.get('/list', function(req, res, next) { 43 | let sort = req.param('sort'); 44 | 45 | let goodsModel = Goods.find({}).sort({ 'salePrice': sort }); 46 | 47 | goodsModel.exec({}, function(err, doc) { 48 | if (err) { 49 | res.json({ status: "1", msg: err.message }) 50 | } else { 51 | res.json({ status: '0', msg: '', result: doc }) 52 | } 53 | }) 54 | 55 | }) 56 | ``` -------------------------------------------------------------------------------- /note/11.根据价格排序.md: -------------------------------------------------------------------------------- 1 | 2 | ## 分析需求 3 | 4 | ### 需求1:价格排序: 5 | 点击页面的按钮从大到小排序,然后再点击从小到大排序 6 | 7 | 前台: 8 | 点击页面按钮 让下面的产品安装价格排序 9 | 需要一个api 10 | 同过两次点击,切换正序和倒序 ,给后端传一个参数 11 | 12 | 开始开发: 13 | 先思考,设计的时间越长,需要修改的时间越短 14 | 请求接口的时候,携带参数,1 -1 15 | 这个怎么来的,通过点击按钮来的 16 | 每次点击按钮 都会改变一个变量值 17 | 变量值默认是 1 18 | 19 | 拿到接口: 20 | postman 测试 21 | 22 | 后端api: 23 | baseurl: localhost:3000 24 | 1:表示接口正常 25 | 0:表示接口不正常 26 | 27 | http 状态码 28 | 200 ok 29 | 400 表示错误 30 | 31 | 拿到需求: 32 | 规定两个参数,来判断输出的结果 33 | 34 | 参数:sort 35 | 36 | api:/goods/list?sort=-1 37 | 接受两个参数: 38 | 接收: 1参数 39 | /goods/list?sort=1 40 | 返回数据: 41 | status:1 42 | msg: 43 | result: 44 | 商品正序数据 45 | 接收:-1 参数 46 | /goods/list?sort=-1 47 | 返回数据:商品倒序 48 | 49 | 开始开发: 50 | 在teambition 新建任务 51 | 第一步:从master 检出 最新代码 52 | git pull origin master 53 | 54 | 第二步:git 创建新的分支 55 | git checkout -b sort 56 | 57 | 测试完成: 58 | git checkout master //切换到master 59 | git merge sort // 合并到master 60 | 61 | develop 62 | 每次开发完一个功能,先合并到develop 63 | 64 | 65 | 66 | ## 接口代码: 67 | ``` 68 | router.get('/list', function(req, res, next) { 69 | let sort = req.param('sort'); 70 | 71 | let goodsModel = Goods.find({}).sort({ 'salePrice': sort }); 72 | 73 | goodsModel.exec({}, function(err, doc) { 74 | if (err) { 75 | res.json({ status: "1", msg: err.message }) 76 | } else { 77 | res.json({ status: '0', msg: '', result: doc }) 78 | } 79 | }) 80 | 81 | }) 82 | ``` 83 | 84 | ## vue前端操作 85 | 86 | 87 | ### 在dom里面添加了一个事件 88 | 89 | ``` 90 | 价格 91 | ``` 92 | 93 | ### 定义了一个data 94 | 95 | ``` 96 | data(){ 97 | return { 98 | goods:{}, 99 | sortFlag:true 100 | } 101 | }, 102 | 103 | ``` 104 | 105 | ### 在methods里面定义了一个方法 106 | 107 | ``` 108 | sortGoods(){ 109 | this.sortFlag = !this.sortFlag; 110 | this.getGoodsList(); 111 | } 112 | ``` 113 | 114 | ### 修改了之前的请求接口,增加了传sort参数 115 | ``` 116 | getGoodsList(){ 117 | let sort = this.sortFlag ? 1 : -1; 118 | axios.get('/goods/list',{params:{sort:sort}}).then(res=>{ 119 | this.goods = res.data.result; 120 | }) 121 | }, 122 | ``` -------------------------------------------------------------------------------- /note/12.按照价格区间筛选商品.md: -------------------------------------------------------------------------------- 1 | 按照价格区间筛选商品 2 | 后端: 3 | 每个那个啥,都价格,根据价格,最大值,最小值 4 | 从前台获取两个数,一个最大值,一个最小值,用mongodb条件查询 5 | 6 | 接收参数 7 | 8 | 根据前端传过来的参数,去数据库查询 9 | 10 | 实现思路: 11 | 根据前端传过来的数值,判断价格区间,然后去数据库里面查询 12 | -------------------------------------------------------------------------------- /note/14.域名注册.md: -------------------------------------------------------------------------------- 1 | ## 域名注册 2 | 网址: 3 | 4 | https://wanwang.aliyun.com/ 推荐阿里云 5 | 6 | http://dnspod.cn/ 7 | 8 | http://www.xinnet.com/ 9 | 10 | https://www.west.cn/ 11 | 12 | 注册完实名认证 审核需要几天 13 | 14 | 到时候买 国外的主机 30 5$ 15 | 16 | com cn net shudong.wang 17 | 18 | .top 1元 19 | 20 | vnshop.cn 21 | 22 | 23 | -------------------------------------------------------------------------------- /note/15.表驱动法.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/note/15.表驱动法.md -------------------------------------------------------------------------------- /note/16.加入购物车.md: -------------------------------------------------------------------------------- 1 | 需求: 2 | 点击加入购物车的时候,把商品id传给api 3 | 4 | 是否登录 5 | 6 | api: 7 | 接收商品的id 8 | user_id 9 | 10 | 根据用户id查询用户数据,确定好用户 11 | 通过商品id去数据库查询,把商品信息查询出来 12 | if(这个用户是否加入过这个商品){ 13 | 就把用户的这个商品数量加一 14 | }else{ 15 | 然后把这个商品信息放在这个用户里面 16 | } 17 | 18 | 然后保存在用户里面 -------------------------------------------------------------------------------- /note/17.登录逻辑.md: -------------------------------------------------------------------------------- 1 | 前端: 2 | 输入用户名和密码 3 | 点击登录: 4 | 携带 5 | 用户名 6 | 密码, 7 | 验证码,(输入字母,数字,拖拽的验证码,计算数,图片点击) 8 | 短信验证码, 9 | 短信平台:创蓝短信 ,阿里大鱼,https://www.yunpian.com/ 10 | 请求,登录接口 11 | 12 | 13 | 14 | 后端: 15 | 16 | 注册: 17 | 18 | 接收 username 19 | nickname 20 | password 21 | yanzhengma 22 | mail 23 | 24 | 使用正则验证 email 符不符合,邮箱规则 25 | 去数据库查询一下 mail 是否被注册 26 | 27 | password 28 | 检查password 是否是八位 必须包含 大小写 字母 数字 特殊符号 29 | 30 | 数据库里面的密码不是明文 31 | 把你的密码层层加密 base64 32 | 33 | sha1 34 | md5 35 | 36 | 37 | 38 | jwt 39 | passport 40 | 41 | redis 42 | 43 | token 44 | 45 | 46 | 每次请求api的时候 47 | 在header里面携带 token 48 | 49 | 50 | 脱库 51 | 社工库 52 | 53 | -------------------------------------------------------------------------------- /note/18.登录前后台实现.md: -------------------------------------------------------------------------------- 1 | ##后台登录接口 2 | 接收前台传过来的用户名和密码,去数据库里面查询 3 | 4 | 在rootes 里面的user.js 5 | ### 后台登录接口代码 6 | ``` 7 | router.post('/login', function(req, res, next) { 8 | let param = { 9 | userName: req.body.userName, 10 | userPwd: req.body.userPwd 11 | } 12 | console.log(param); 13 | User.findOne(param, function(err, doc) { 14 | console.log(err); 15 | if (err) { res.json({ "status": "1", msg: err.message }) } else { 16 | console.log('doc', doc); 17 | if (!doc) { res.json({ 'status': '1', msg: '', result: '用户名和密码错误' }) } 18 | 19 | //把userId 和 userName 存到cookie里面,在控制台的application里面找到cookie可以查看 20 | 21 | 第一个参数存的是 cookie 名字,第二个参数存的是值,地三个对象,里面 22 | path 是存的路径,maxAge 过期时间,以毫秒为单位 23 | res.cookie('userId', doc.userId, { 24 | path: '/', 25 | maxAge: 1000 * 60 * 60 26 | }) 27 | 28 | res.cookie("userName", doc.userName, { 29 | path: '/', 30 | maxAge: 1000 * 60 * 60 31 | }) 32 | 33 | if (doc) { 34 | res.json({ 35 | status: 0, 36 | msg: '', 37 | result: { 38 | userName: doc.userName //最后返回用户名 39 | } 40 | }) 41 | } 42 | } 43 | }) 44 | }) 45 | ``` 46 | 47 | ##前台实现 48 | 在Header组件里面 49 | 50 | 把静态页面的模态框代码拷贝进来 51 | 52 | 53 | 模态框依靠 md-show 来控制显示隐藏 54 | 55 | 遮罩层 依靠v-if 来控制显示隐藏 56 | 57 | ``` 58 | 59 | 87 |
88 | ``` 89 | 90 | ### js代码逻辑实现 91 | ``` 92 | import axios from 'axios' 93 | export default { 94 | data(){ 95 | return{ 96 | nickName:'', 97 | userName:'', 98 | userPwd:'', 99 | loginModalFlag:false // 控制 100 | } 101 | }, 102 | methods:{ 103 | login(){ 104 | axios.post('/users/login',{ 105 | userName:this.userName, 106 | userPwd:this.userPwd 107 | }).then(result=>{ 108 | let res = result.data; 109 | this.nickName = res.result.userName; 110 | this.loginModalFlag = false; 111 | }) 112 | } 113 | } 114 | } 115 | ``` -------------------------------------------------------------------------------- /note/19.在项目前后分离的状态下,刷新页面,怎么保持用户登录.md: -------------------------------------------------------------------------------- 1 | ##在项目前后分离的状态下,刷新页面,怎么保持用户登录 2 | 3 | 在头部组件里面,初始化的时候,调用一个接口检查是否登录 4 | 5 | 如果登录了,就把用户昵称给到这个nickname变量里面 6 | 如果未登录,就提示未登录 7 | 8 | ### 在组件初始化完成之后,自动调用是否登录接口 9 | ``` 10 | created(){ 11 | this.checkLogin() 12 | }, 13 | ``` 14 | 15 | 16 | ### 是否登录接口 17 | ``` 18 | checkLogin(){ 19 | axios.post('/users/checkLogin').then(result=>{ 20 | let res = result.data; 21 | 如果登录成功就把,登录的结果赋值到这里 22 | 如果未登录成功,这个结果空字符串 23 | this.nickName = res.result; 24 | }) 25 | }, 26 | ``` 27 | 28 | ``` 29 | / 检查是否登录 30 | router.post('/checkLogin', function(req, res, next) { 31 | // 使用cookies读取 cookies 32 | if (req.cookies.userId) { 33 | res.json({ 34 | status: '0', 35 | result: req.cookies.userName 36 | }) 37 | } else { 38 | res.json({ 39 | status: 1, 40 | msg: '未登录', 41 | result: '' 42 | }) 43 | } 44 | }) 45 | 46 | ``` -------------------------------------------------------------------------------- /note/20.退出登录.md: -------------------------------------------------------------------------------- 1 | ## 退出登录 2 | ``` 3 | // 退出登录 4 | router.post('/logout', function(req, res, next) { 5 | //清除 cookie 6 | 把userId的值变为空值 7 | res.cookie("userId", "", { 8 | path: '/', 9 | maxAge: -1 把时间变为负数 10 | }) 11 | 12 | res.json({ 13 | status: 0, 14 | msg: '', 15 | result: '退出成功' 16 | }) 17 | }) 18 | ``` 19 | 20 | 21 | ## 前台操作 22 | 23 | ### dom操作 24 | ``` 25 |
26 | 27 | 登录 28 | | 29 | 在这点击按钮执行 logout 函数 30 | 退出 31 |
32 | 33 | ``` 34 | 35 | ### js操作 36 | ``` 37 | logout(){ 38 | axios.post('/users/logout').then(result=>{ 39 | let res = result.data; 40 | this.nickName = ''; //把nickName 清空 41 | console.log(res); 42 | }) 43 | } 44 | ``` -------------------------------------------------------------------------------- /note/21.如何在vue里面优雅的解决跨域,路由冲突问题.md: -------------------------------------------------------------------------------- 1 | # 如何在vue里面优雅的解决跨域,路由冲突问题 2 | ## 当我们在路由里面配置成以下代理可以解决跨域问题 3 | ``` 4 | proxyTable: { 5 | '/goods/*': { 6 | target: 'http://localhost:3000' 7 | }, 8 | '/users/*': { 9 | target: 'http://localhost:3000' 10 | } 11 | }, 12 | ``` 13 | > 这种配置方式在一定程度上解决了跨域问题,但是会带来一些问题, 14 | 比如我们的vue 路由 也命名为 goods,这时候就会产生了冲突, 15 | 如果项目中接口很多,都在这里配置是很麻烦的,也容易产生路由冲突。 16 | 17 | ## 正确的姿势 18 | ## 如果把所有的接口,统一规范为一个入口,在一定程度上会解决冲突 19 | 20 | 把以上配置统一前面加上 /api/ 21 | 22 | ``` 23 | proxyTable: { 24 | '/api/**': { 25 | target: 'http://localhost:3000' 26 | }, 27 | }, 28 | ``` 29 | 30 | ## 如果我们配置成这种方式,在使用http请求的时候就会发生变化,会在请求前面加上一个api,相对路由也会发生变化,也会在接口前面加上api,这样也会很麻烦,我们可以使用以下方式来解决这个问题 31 | 32 | ``` 33 | proxyTable: { 34 | '/api/**': { 35 | target: 'http://localhost:3000', 36 | pathRewrite:{ 37 | '^/api':'/' 38 | } 39 | }, 40 | }, 41 | ``` 42 | 43 | ## 上面这个代码,就是把咱们虚拟的这个api接口,去掉,此时真正去后端请求的时候,不会加上api这个前缀了,那么这样我们前台http请求的时候,还必须加上api前缀才能匹配到这个代理,代码如下: 44 | 45 | ``` 46 | logout(){ 47 | axios.post('/api/users/logout').then(result=>{ 48 | let res = result.data; 49 | this.nickName = ''; 50 | console.log(res); 51 | }) 52 | }, 53 | getGoods(){ 54 | axios.post('/api/goods/list').then(result=>{ 55 | let res = result.data; 56 | this.nickName = ''; 57 | console.log(res); 58 | }) 59 | } 60 | ``` 61 | 62 | ## 我们可以利用axios的baseUrl直接默认值是 api,这样我们每次访问的时候,自动补上这个api前缀,就不需要我们自己手工在每个接口上面写这个前缀了 63 | 64 | 在入口文件里面配置如下: 65 | ``` 66 | import Axios from 'axios' 67 | import VueAxios from 'vue-axios' 68 | 69 | Vue.use(VueAxios, Axios) 70 | Axios.defaults.baseURL = 'api' 71 | 72 | 如果这配置 'api/' 会默认读取本地的域 73 | ``` 74 | 75 | ### 上面这样配置的话,不会区分生产和开发环境 76 | 在config 文件夹里面新建一个 api.config.js 配置文件 77 | 78 | ``` 79 | const isPro = Object.is(process.env.NODE_ENV, 'production') 80 | 81 | module.exports = { 82 | baseUrl: isPro ? 'http://www.vnshop.cn/api/' : 'api/' 83 | } 84 | ``` 85 | 86 | ### 然后在main.js 里面引入,这样可以保证动态的匹配生产和开发的定义前缀 87 | 88 | ``` 89 | import apiConfig from '../config/api.config' 90 | 91 | import Axios from 'axios' 92 | import VueAxios from 'vue-axios' 93 | 94 | Vue.use(VueAxios, Axios) 95 | Axios.defaults.baseURL = apiConfig.baseUrl 96 | ``` 97 | ### 经过上面配置后,在dom里面可以这样轻松的访问,也不需要在任何组件里面引入axios模块了。 98 | 99 | ``` 100 | logout(){ 101 | this.$http.post('/users/logout').then(result=>{ 102 | let res = result.data; 103 | this.nickName = ''; 104 | console.log(res); 105 | }) 106 | }, 107 | getGoods(){ 108 | this.$http.post('/goods/list').then(result=>{ 109 | let res = result.data; 110 | this.nickName = ''; 111 | console.log(res); 112 | }) 113 | } 114 | ``` 115 | 116 | ## 最终代码 117 | 118 | ### 在代理里面配置 119 | 120 | ``` 121 | proxyTable: { 122 | '/api/**': { 123 | target: 'http://localhost:3000', 124 | pathRewrite:{ 125 | '^/api':'/' 126 | } 127 | }, 128 | }, 129 | ``` 130 | 131 | ### 在config里面的api.config.js 配置 132 | 133 | 在config 文件夹里面新建一个 api.config.js 配置文件 134 | 135 | ``` 136 | const isPro = Object.is(process.env.NODE_ENV, 'production') 137 | 138 | module.exports = { 139 | baseUrl: isPro ? 'http://www.vnshop.cn/api/' : 'api/' 140 | } 141 | ``` 142 | 143 | 144 | ### 在main.js 入口文件里面配置 145 | 146 | ``` 147 | import apiConfig from '../config/api.config' 148 | 149 | import Axios from 'axios' 150 | import VueAxios from 'vue-axios' 151 | 152 | Vue.use(VueAxios, Axios) 153 | Axios.defaults.baseURL = apiConfig.baseUrl 154 | ``` 155 | 156 | 157 | 158 | ### 在dom里面请求api的姿势 159 | ``` 160 | logout(){ 161 | this.$http.post('/users/logout').then(result=>{ 162 | let res = result.data; 163 | this.nickName = ''; 164 | console.log(res); 165 | }) 166 | }, 167 | getGoods(){ 168 | this.$http.post('/goods/list').then(result=>{ 169 | let res = result.data; 170 | this.nickName = ''; 171 | console.log(res); 172 | }) 173 | } 174 | ``` 175 | -------------------------------------------------------------------------------- /note/22.登录拦截.md: -------------------------------------------------------------------------------- 1 | ## 访问拦截 2 | 当我们点击加入购物车的时候判断一下是否登录 3 | 规定哪些接口是可以访问的,哪些接口是需要登录后才能访问的 4 | 5 | ## 具体实现 6 | 在app.js里面 7 | use 一个函数 ,每次请求url都会走这块 8 | ``` 9 | app.use(function(req, res, next) { 10 | // console.log(1111); 11 | 12 | next() 放过通行 13 | }) 14 | ``` 15 | 16 | ## 在项目中使用 17 | 18 | ``` 19 | app.use(function(req, res, next) { 20 | // console.log(1111); 21 | if (req.cookies.userId) { 判断用户是否登录 22 | next() 23 | } else { 24 | if ( 25 | req.originalUrl == '/users/login' || 26 | req.path == '/goods/list' || 27 | req.originalUrl == '/users/checkLogin' 28 | ) { 29 | next() 30 | } else { 31 | res.json({ 32 | status: '1', 33 | msg: '当前用户未登录', 34 | result: '' 35 | }) 36 | } 37 | } 38 | }) 39 | ``` -------------------------------------------------------------------------------- /note/23.开发购物车页面.md: -------------------------------------------------------------------------------- 1 | #购物车列表页面渲染 2 | ## 把购物车组件写好 3 | 创建组件,设置路由,拷贝静态文件 4 | ## 写购物车api 5 | 查询出登录的用户的详细信息,取里面的购物列表返回给前台 6 | 7 | ## 前台代码 8 | 9 | ## dom循环出来 10 | ``` 11 |
  • 12 | 13 |
    {{item.productName}}
    14 |
    {{item.salePrice}}
    15 | {{item.productNum}} 16 |
    {{item.salePrice * item.productNum}}
    17 | 18 | ``` 19 | ``` 20 | import NavHeader from '@/components/Header' 21 | import NavFooter from '@/components/Footer' 22 | import NavBread from '@/components/NavBread' 23 | export default { 24 | data(){ 25 | return{ 26 | cartList:'' 27 | } 28 | }, 29 | components:{ 30 | NavHeader, 31 | NavFooter, 32 | NavBread 33 | }, 34 | created(){ 35 | this.getCartList() 36 | }, 37 | methods:{ 38 | getCartList(){ 39 | this.$http.post('/users/cartList').then(result=>{ 40 | let res = result.data; 41 | this.cartList = res.result; 42 | console.log(res); 43 | }) 44 | } 45 | } 46 | } 47 | ``` 48 | 49 | ## 后端接口 50 | ``` 51 | router.post("/cartList", function(req, res, next) { 52 | let userId = req.cookies.userId; 53 | User.findOne({ userId: userId }, function(err, doc) { 54 | if (err) { res.json({ status: '1', msg: err.message, result: '' }) } else { 55 | res.json({ 56 | status: 0, 57 | msg: '', 58 | result: doc.cartList 59 | }) 60 | } 61 | }) 62 | }) 63 | ``` -------------------------------------------------------------------------------- /note/24.调试问题的框架.md: -------------------------------------------------------------------------------- 1 | 调试问题的框架: 2 | 发生什么问题?怎么做是最好的解决方案? 3 | 4 | 404 5 | 6 | 先看你的错误信息 7 | 如果是英文,把他翻译出来,必须把报错信息,搞懂 8 | 提取里面语法错误,或者路径信息 关键词,http请求错误 9 | 10 | 如果没有报错,数据还没有,去检查network的 xhr 请求的api 11 | 到底有没有数据 12 | 没有数据? 13 | 测试api 14 | 排查是否真正的输出 15 | 去检查数据库 16 | 前端看报错,确定是否是后端问题, 17 | 如果后端有问题,去排查,有可能是数据库问题 18 | 要经常查看 node 服务器的控制台 打印的日志 19 | -------------------------------------------------------------------------------- /note/25.购物车列表里面的商品数量增加和减少,和是否被选中.md: -------------------------------------------------------------------------------- 1 | 2 | #购物车列表里面的商品数量增加和减少,和是否被选中 3 | ## 打算更新用户里面的商品? 4 | 要根据用户id 和商品id 确定哪个用户的商品 5 | 然后更新里面的数据 6 | 7 | ## api接口 8 | 接收参数: 9 | 商品id 10 | 商品数量 11 | 12 | ### api接口代码实现 13 | update: 14 | 参数一:条件 15 | 参数二:要设置的字段 16 | 参数三:回调函数 17 | 18 | 参数二:设置方式 cartList.$.productNum 19 | cartList 是user里面的对象 20 | $ 固定写法 21 | productNum 是要更新的字段, user.cartList 的属性 22 | ``` 23 | router.post('/cartEdit', function(req, res, next) { 24 | let userId = req.cookies.userId, 25 | productId = req.body.productId, 26 | productNum = req.body.productNum; 27 | 28 | 29 | User.update({ 'userId': userId, "cartList.productId": productId }, { 30 | "cartList.$.productNum": productNum 31 | }, function(err, doc) { 32 | if (err) { res.json({ status: '1', msg: err.message, result: '' }) } else { 33 | res.json({ 34 | status: 0, 35 | msg: '', 36 | result: '修改购物车商品成功' 37 | }) 38 | } 39 | }) 40 | 41 | }) 42 | ``` 43 | 44 | ### dom 实现 45 | 46 | ``` 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 |
    55 | - 56 | {{item.productNum}} 57 | + 58 |
    59 | 60 | 61 | editCart(flag,item){ 62 | if(flag == 'minu'){ 63 | if(item.productNum <= 1){ 64 | return; 65 | } 66 | item.productNum --; 67 | }else if(flag == 'add'){ 68 | item.productNum ++; 69 | }else{ 70 | item.checked = item.checked == '1' ? 0 : 1; 71 | } 72 | this.$http.post('/users/cartEdit',{ 73 | productId:item.productId, 74 | productNum:item.productNum 75 | }).then(result=>{ 76 | console.log(result); 77 | // alert(result.data.result); 78 | }) 79 | 80 | } 81 | ``` -------------------------------------------------------------------------------- /note/26.全选,全不选.md: -------------------------------------------------------------------------------- 1 | #切换全选,和全不选 2 | ## 当购物车里面的数据,差一个没全部选中的时候 3 | 这个时候,点击按钮,就全部选中 4 | 5 | 在全部选中的时候,点击按钮就全部没有选中,(取反) 6 | 7 | flag:来判断以上的条件 8 | return 布尔值 9 | 10 | 需要判断当前选中了多少 11 | 当前选中的商品 和 购物车里面的所有商品对比 12 | 13 | ## 代码实现 14 | 因为需要实时计算,写在computed里面 15 | ``` 16 | 17 | computed:{ 18 | // 购物车被选中的数量 19 | checkedCount(){ 20 | var i = 0; 21 | this.cartList.forEach(item=>{ 22 | if(item.checked == '1') i++; 23 | }) 24 | return i; 25 | }, 26 | // 判断是否全选 27 | checkedAllFlag(){ 28 | // 当前选中的商品 和 购物车里面的所有商品对比 29 | return this.checkedCount == this.cartList.length; 30 | } 31 | }, 32 | 33 | 34 | ``` 35 | 36 | ``` 37 | toggleCheckAll(){ 38 | let flag = !this.checkedAllFlag; 39 | 40 | this.cartList.forEach(item=>{ 41 | item.checked = flag ? 1 : 0; 42 | }) 43 | 44 | this.$http.post('/users/editCheckAll',{checkAll:this.checkedAllFlag}).then(res=>{ 45 | console.log(res); 46 | }) 47 | } 48 | ``` -------------------------------------------------------------------------------- /note/27.总价格实时变化.md: -------------------------------------------------------------------------------- 1 | #总价格实时变化 2 | 3 | ``` 4 |
    5 | Item total: {{totalPrice}} 6 |
    7 | 8 | totalPrice(){ 9 | let money = 0; 10 | this.cartList.forEach(item=>{ 11 | if(item.checked == '1'){ 12 | money += item.salePrice * item.productNum 13 | } 14 | }) 15 | return money; 16 | } 17 | ``` -------------------------------------------------------------------------------- /note/28.商品删除.md: -------------------------------------------------------------------------------- 1 | #商品删除 2 | 在生产环境中,真正的删除,就是改变了一个状态 3 | 原则性不允许删除任何东西 -------------------------------------------------------------------------------- /note/29.封装全局模态框组件.购物车判断登录与未登录情况的弹出不同模态框.md: -------------------------------------------------------------------------------- 1 | ## 29.封装全局模态框组件 2 | 把静态写好的组件放在 Modal.vue组件里面 3 | 代码如下 4 | 5 | ## 通过props父子组件传惨,通过slot定义插槽 6 | ``` 7 | 29 | 34 | 35 | ``` 36 | 37 | ## 在父组件里面使用 38 | 39 | ``` 40 | import Modal from '@/components/Modal' 41 | 42 | 43 | components:{ 44 | NavHeader, 45 | NavFooter, 46 | NavBread, 47 | Modal //在这加上 48 | }, 49 | 50 | 在打他里面加上 51 | data(){ 52 | return{ 53 | mdShowCart:false, 54 | mdShow:false, 55 | } 56 | } 57 | 58 | ``` 59 | 60 | ``` 61 | 62 | 63 |

    请先登录,否则无法加入购物车

    64 |
    65 | 关闭 66 |
    67 |
    68 | 69 | 70 | 71 |

    加入购物车成功

    72 |
    73 | 继续购物 74 | 查看购物车列表 75 |
    76 |
    77 | ``` 78 | 79 | ## 在业务层面操作 80 | ``` 81 | addCart(productId){ 82 | axios.post('/goods/addCart',{productId:productId}).then(res=>{ 83 | console.log(res.data); 84 | if(res.data.status == 1){ 85 | this.mdShow = true; //判断一下当未登录的情况下把未登录的模态框弹出 86 | }else{ 87 | } 88 | }) 89 | } 90 | ``` -------------------------------------------------------------------------------- /note/30.在购物车列表页面去结账.md: -------------------------------------------------------------------------------- 1 | ##30.在购物车列表页面去结账 2 | 3 | 点击结账按钮,跳转到地址页面 4 | 之前要判断一下是否有选中的商品 5 | ``` 6 | checkout(){ 7 | if(this.checkedCount > 0){ 8 | this.$router.push({ 9 | path:'/address' 10 | }) 11 | }else{ 12 | alert('购物车,必须有选中的商品!才能去结账') 13 | } 14 | } 15 | ``` -------------------------------------------------------------------------------- /note/31.地址页面.md: -------------------------------------------------------------------------------- 1 | ## 地址页面 2 | 创建组件,写路由 3 | ## 遍历地址信息 4 | api接口 5 | 返回地址信息 6 | ``` 7 | router.get('/addressList', function(req, res, next) { 8 | var userId = req.cookies.userId; 9 | User.findOne({ userId: userId }, function(err, doc) { 10 | if (err) { 11 | res.json({ status: 1, msg: err.message, result: '' }) 12 | } else { 13 | res.json({ status: 0, msg: '', result: doc.addressList }) 14 | } 15 | }) 16 | }) 17 | ``` 18 | 19 | ## vue前台遍历 20 | ``` 21 | methods:{ 22 | getAddressList(){ 23 | this.$http.get('/users/addressList').then(res=>{ 24 | this.addressList = res.data.result; 25 | }) 26 | } 27 | } 28 | ``` -------------------------------------------------------------------------------- /note/32.设置默认地址.md: -------------------------------------------------------------------------------- 1 | #设置默认地址 2 | 3 | api 接口 4 | ``` 5 | router.post("/setDefault", function(req, res, next) { 6 | var userId = req.cookies.userId, 7 | addressId = req.body.addressId; 8 | if (!addressId) { 9 | res.json({ 10 | status: '1003', 11 | msg: 'addressId Is null' 12 | }) 13 | } else { 14 | User.findOne({ userId: userId }, function(err, doc) { 15 | var addressList = doc.addressList; 16 | addressList.forEach(item => { 17 | if (item.addressId = addressId) { 18 | item.isDefault = true; 19 | } else { 20 | item.isDefault = false; 21 | } 22 | }) 23 | 24 | doc.save(function(err1, doc1) { 25 | if (err1) { 26 | res.json({ 27 | status: '1', 28 | msg: err.message, 29 | result: '' 30 | }) 31 | } else { 32 | res.json({ 33 | status: '0', 34 | msg: '', 35 | result: doc1 36 | }) 37 | } 38 | }) 39 | }) 40 | } 41 | }) 42 | ``` 43 | 44 | vue 前台实现 45 | ``` 46 | setDefault(addressId){ 47 | this.$http.post('/users/setDefault',{ 48 | addressId:addressId 49 | }).then(res=>{ 50 | if(res.data.status == '0'){ 51 | this.getAddressList(); 52 | } 53 | }) 54 | } 55 | ``` -------------------------------------------------------------------------------- /note/33.订单确认页面.md: -------------------------------------------------------------------------------- 1 | #订单确认页面 2 | 3 | ``` 4 | methods:{ 5 | init(){ 6 | this.$http.post('/users/cartList').then(response=>{ 7 | let res = response.data; 8 | this.cartList = res.result; 9 | 10 | this.cartList.forEach(item=>{ 11 | console.log(item); 12 | if(item.checked == '1'){ 13 | this.subTotal += item.productNum * item.salePrice 14 | } 15 | }) 16 | 17 | this.orderTotal = this.subTotal + this.shipping + this.tax - this.discount; 18 | }) 19 | } 20 | } 21 | ``` -------------------------------------------------------------------------------- /note/34.项目上线.md: -------------------------------------------------------------------------------- 1 | ## 选购服务器 2 | 板瓦工 推荐1g以上内存 3 | https://www.bwh1.net/ 4 | 5 | 阿里云 6 | https://common-buy.aliyun.com/?spm=5176.10003347.843204.1.Ql3ciJ&commodityCode=swas&request=undefined#/buy 7 | 8 | 9 | 推荐阿里云 10 | https://promotion.aliyun.com/ntms/act/qwbk.html?open_id=4dc9ecb7-9a7d-4800-a51a-a659a1ebb2ca-511180874&open_cid=187 11 | 12 | https://cloud.digitalocean.com/login 13 | 14 | https://www.vultr.com/ 15 | https://www.vultr.com/pricing/ 16 | 17 | ## 服务器系统选择 18 | Ubuntu 19 | 20 | ## 搭建环境 21 | nginx 22 | php fpm 23 | mysql 24 | mongodb 25 | nodejs 26 | 27 | pm2 28 | 29 | ## 绑定域名 30 | 子域名 31 | 32 | gitlab.com 33 | 34 | 35 | 野狗 36 | 37 | 38 | ## 做哪些事情 39 | bbs.shudong.wang 40 | 41 | wordpress 42 | 43 | hexo 44 | 45 | 今天把服务器搞定 46 | 47 | ## 域名注册 48 | 优先选购: 49 | .com .net .cn 50 | 51 | 位数要短一些 52 | 其它后缀尽量有意义 53 | 54 | vnshop.cn 55 | 56 | 国内的服务器必须备案 57 | 58 | 最好是国外的 59 | 或香港的 60 | 如果选国外的最好选择日本 61 | 62 | 优先选择香港 -------------------------------------------------------------------------------- /note/35.服务器购买.md: -------------------------------------------------------------------------------- 1 | ## https://segmentfault.com/a/1190000011772497 2 | #vps服务器购买操作 3 | ## 搭建vue + node + mongodb 项目需要购买服务器 4 | ## 服务器购买后最好选择Ubuntu系统(接下来的项目上线教程都是按照Ubuntu系统来讲) 5 | ### 注意点: 6 | >千万别绑定自己的信用卡,绑定后打算解绑需要另一张信用卡来解绑,好像国外都是这么干的 7 | ### 结账方式选择: 8 | 有支付宝的最好选择支付宝 9 | 没有支付宝的话,就选择PayPal(支持大部分银联卡) 10 | 11 | ## 选购服务器 12 | ### 支付方式支持 支付宝结账比较方便,同时也支持PayPal 13 | ## 选购搬瓦工(支持 ss 价格实惠) 14 | 板瓦工 推荐1g以上内存(因为node服务器消耗内存比较大) 15 | [bwh1](https://www.bwh1.net/) 16 | ### 注册账号的时候,需要填写一些信息,最后需要的验证码需要科学上网才能出现验证码图片,所以正确填写完验证码之后,才能注册,才能购买 17 | 18 | ![clipboard.png](/img/bVXyIg) 19 | 20 | ## 选购阿里云 21 | ### 注意:千万别选择window系统(如果不是必须window的话) 22 | ### 如果你选择了window系统,不能更换问Linux系统,解决办法:提交工单,去退货,然后重新购买 23 | > 如果你是学生,就去通过学生通道购买 9.9一个月 24 | 如果不是学生推荐一下链接 25 | https://common-buy.aliyun.com/?spm=5176.10003347.843204.1.Ql3ciJ&commodityCode=swas&request=undefined#/buy 26 | 27 | 如果你的域名没有备案,请买香港主机或其他国外主机 28 | 29 | ## 推荐阿里云(双十一搞活动)280一年 30 | https://promotion.aliyun.com/ntms/act/qwbk.html?open_id=4dc9ecb7-9a7d-4800-a51a-a659a1ebb2ca-511180874&open_cid=187 31 | 32 | ## 选购vultr 33 | ### 第一步注册账号 34 | ### 登录进去 35 | ### 注意点: 36 | >千万别绑定自己的信用卡,绑定后打算解绑需要另一张信用卡来解绑,好像国外都是这么干的 37 | ### 支付方式: 38 | 支持 PayPal (所有银联卡都支持) 39 | 40 | https://www.vultr.com/ 41 | https://www.vultr.com/pricing/ 42 | ![clipboard.png](/img/bVXyCS) 43 | 44 | 45 | ### 选择数字海洋 [digitalocean](https://www.digitalocean.com) 46 | >国外口碑不错 47 | > digitalocean 如果你有教育邮箱,就是edu结尾的邮箱, 可以去领100美金优惠券,这个查的很严,两个账号用一个支付方式,都使用了优惠券就回被查出来 48 | 优惠券两年后就不能用了 49 | 50 | #### 网址https://cloud.digitalocean.com/login 51 | 52 | ### 等大家买完后,接下来讲项目上线(敬请期待) 53 | ## 项目上线方式: 54 | ### 普通打包上传方式 55 | ### git webhooks pm2 自动化方式 56 | ### docker 方式 57 | 58 | #### 会不断优化此篇文章(请收藏) 59 | ## 下一篇文章(选购域名) 60 | ## 欢迎加入前端微信群,持续学习 61 | ![图片描述][1] 62 | 63 | 64 | [1]: /img/bVXyL8 -------------------------------------------------------------------------------- /note/36.域名购买.md: -------------------------------------------------------------------------------- 1 | ##域名购买 2 | ##域名厂商推荐 3 | > [阿里云](https://wanwang.aliyun.com/) (曾经万网) 推荐(备案比较方便) 4 | > [dnspod.cn](https://www.dnspod.cn/) (被腾讯收购了) 5 | > [新网](http://www.xinnet.com/) (被腾讯收购了) 6 | > [西部数码](http://west.cn/) (自营14年了,侧重搞域名交易的场所) 7 | > [百度域名注册](https://cloud.baidu.com/product/bcd.html) 8 | > [腾讯域名注册](https://dnspod.cloud.tencent.com/) 9 | ### 国外域名厂商 10 | 11 | > [狗爹](https://sg.godaddy.com/zh/tlds/gtld.aspx) 12 | ### 国外交易域名厂家 13 | > [sedo](sedo.com) 14 | > [park.io](park.io) 15 | 16 | ## 选购域名推荐 17 | 优先选择com 18 | 然后 net cn cc 19 | 如果上面没有你的选择可以找比较有意义的后缀 20 | shudong.wang 符合我的名字 21 | stark.wang 22 | vnshop.cn 23 | itnote.cn 24 | 25 | 原则性:好记,有意义 26 | 如果经济允许的话,可以选择一些比较短的新出的简短的后缀,比如vc cm cx 27 | 选择新出的后缀,两位的购买 28 | cx 两位的行情是 1000起步 29 | uv.cx 1200 目前行情,如果你可以的话 30 | chat 31 | 32 | ## 购买域名以阿里云为例子 33 | -------------------------------------------------------------------------------- /note/36.连接阿里云工具.md: -------------------------------------------------------------------------------- 1 | ##完整比较去去这个连接 2 | https://segmentfault.com/a/1190000011775015 3 | ## 连接Linux工具 4 | putty (免费) 5 | xshell(收费)(推荐)教程使用xshell 操作 6 | ## 安装xshell 7 | [下载地址](http://www.netsarang.com/download/main.html) 8 | 官方的如果下载慢:推荐大家去360软件管家下载 或者百度助手 9 | 10 | ### 下载操作 11 | ![clipboard.png](/img/bVXza9) 12 | 13 | ### 安装点击下一步,下一步,结束 14 | 15 | ### 使用方式 16 | 17 | ![clipboard.png](/img/bVXzcC) 18 | 19 | ![clipboard.png](/img/bVXzc0) 20 | 21 | > 名称:是自己随便填写的,以便区分自己的其它主机 22 | 主机:是自己购买的服务器ip 23 | >端口号:是自己购买的服务器端口号,一般默认是ssh 22 ,如果你买的国外主机,比如搬瓦工,会像你的邮箱发送几封邮件,其中一封,会标明有主机ip端口号 ,那个端口号需要在这填写,搬瓦工的端口号,不是22(切记) 24 | 25 | ### 例子: 26 | ![clipboard.png](/img/bVXzek) 27 | ### 输入用户名和密码: 28 | 29 | ![clipboard.png](/img/bVXzeP) 30 | 如果你刚买的主机,一般管理员用root来登录 31 | 用户名是root 32 | 密码是自己设定的,如果是搬瓦工的话,邮箱会有这个信息 33 | ### 阿里云怎么找回或设置自己的密码 34 | 如果是阿里云的话需要 35 | 36 | ![clipboard.png](/img/bVXzf9) 37 | 38 | ![clipboard.png](/img/bVXzfI) 39 | 40 | 先停止这个服务器,然后 41 | 42 | ![clipboard.png](/img/bVXzgn) 43 | 44 | 45 | 46 | ![clipboard.png](/img/bVXzhp) 47 | 48 | 49 | ![clipboard.png](/img/bVXzgU) 50 | 51 | 等重置完密码之后,就把自己设定的密码,在这登录 52 | 53 | ### 搬瓦工怎么找回自己的密码 54 | 55 | ![clipboard.png](/img/bVXzky) 56 | 57 | 进入控制面板的网址:https://kiwivm.64clouds.com/main.php 58 | 59 | ### 修改密码 60 | 改名密码之前先stop 61 | ![clipboard.png](/img/bVXzkL) 62 | 63 | #### 自定义设置密码 64 | ![clipboard.png](/img/bVXzkL) 65 | 如果这个不能用 请选择自动设置密码,下面图示 66 | #### 自动设置密码 67 | 68 | ![clipboard.png](/img/bVXzli) 69 | 设置了之后,会出现一个密码,需要记住,只出现一次,一定要记住 70 | 71 | ##当我们把服务器账号密码都搞定,然后登录 72 | 73 | 74 | ![clipboard.png](/img/bVXzic) 75 | 76 | 出现以下命令 77 | ``` 78 | [root@iZ238uepsriZ ~]# 79 | ``` 80 | root 是用户名 81 | iZ238uepsriZ 这个是主机名字 82 | ~ 是路径,波浪线代表家目录 家目录就是用户所在的目录 83 | ‘#’ 代码管理员权限操作 84 | 85 | 执行一些常用的shell 86 | ``` 87 | pwd :当前所在的路径 88 | cd :切换路径 89 | ls :查看当前文件下面都有神马 90 | ll :是ls -l 的别名 91 | cp :复制 92 | mv :重命名,剪切 93 | 94 | ``` 95 | ##接下来安装Nginx web环境 96 | 会安装以下环境: 97 | Nginx 98 | php 99 | mysql 100 | mongodb 101 | node 102 | pm2 103 | git 104 | docker 105 | ## 敬请期待后面文章 106 | ##(如需视频)欢迎加入前端持续学习 107 | ![图片描述][1] 108 | 109 | 110 | [1]: /img/bVXyL8 -------------------------------------------------------------------------------- /note/37.【全栈项目上线(vue+node+mongodb)】安装lnmp环境.md: -------------------------------------------------------------------------------- 1 | #37.【全栈项目上线(vue+node+mongodb)】安装lnmp环境 -------------------------------------------------------------------------------- /note/38.项目上线解决方案.md: -------------------------------------------------------------------------------- 1 | ##项目上线常用方案: 2 | 3 | ### 把本地的代码打包压缩一份上传到服务器,然后解压到相应地方 4 | > 把本地的代码压缩一下,然后上传到服务器 5 | ``` 6 | npm run build 7 | ``` 8 | > 生成一个dist 文件夹,把这个文件夹,压缩成zip格式的文件 9 | 然后通过xshell 上传到服务器 10 | #### 第一步:安装 lrzsz 11 | 12 | ``` 13 | apt-get install lrzsz -y 14 | ``` 15 | 16 | sz:将选定的文件发送到本地机器 17 | rz:运行该命令会弹出一个文件选择窗口,从本地选择文件上传到Linux服务器 18 | rz,sz是Linux/Unix同Windows进行ZModem文件传输的命令行工具, 19 | 20 | #### 第二步:把本地的项目文件通过rz上传到服务器 21 | 执行rz命令,然后跳出一个框,让你选择本地需要上传到服务器的文件。 22 | ``` 23 | rz 24 | ``` 25 | 在服务器哪执行的命令,就上传到哪去 26 | 27 | #### 第三步:移动到相应的位置解压文件 28 | 把上传的压缩包解压: 29 | 30 | ``` 31 | unzip dist.zip 32 | ``` 33 | 解压完之后,生成一个 dist文件夹 34 | 需要把这个文件夹里面的所有文件复制到 vn.itnote.cn文件夹里面去 35 | 36 | ``` 37 | cp -r dist/* vn.itnote.cn 38 | ``` 39 | > cp 是拷贝 -r 是深度拷贝,如果里面是文件,需要用 -r /* 代表把dist 文件夹里面的所有文件都拷贝 后面的vn.itnote.cn 文件夹,是要拷贝的目的地 40 | 41 | ### 从GitHub拉去到相应的地方 42 | ### 配置git webhooks 自动化上线 43 | ### 配置 pm2 自动化上线 44 | ### 使用docker 自动化上线 -------------------------------------------------------------------------------- /note/39.怎么在一台主机上面部署多个网站.md: -------------------------------------------------------------------------------- 1 | ## 怎么在一台主机上面部署多个网站 2 | ### 使用Nginx的虚拟化配置 3 | ### 操作步骤 4 | ### 第一步:执行 lnmp vhost add 5 | ``` 6 | lnmp vhost add 7 | ``` 8 | https://segmentfault.com/a/1190000011791001 -------------------------------------------------------------------------------- /note/40.nodejs服务上线.md: -------------------------------------------------------------------------------- 1 | 【全栈项目上线(vue+node+mongodb)】06.nodejs服务上线 -------------------------------------------------------------------------------- /note/41.homework.md: -------------------------------------------------------------------------------- 1 | 1.把概念理清 2 | nginx 3 | pm2 4 | Apache 5 | node 6 | express 7 | vue 8 | Ubuntu 9 | Linux 10 | git 11 | webhooks 12 | 13 | 2.把自己的项目上线 成功后留言到论坛 14 | http://bbs.shudong.wang/forum.php?mod=forumdisplay&fid=100 15 | 16 | 3.自己搭建的时候有问题提问到这里面来 17 | 18 | https://segmentfault.com/a/1190000011782975 19 | 20 | 4.每个人写一篇文章 21 | 发布到 22 | https://segmentfault.com/ -------------------------------------------------------------------------------- /note/42.项目上线使用webhooks.md: -------------------------------------------------------------------------------- 1 | ##项目上线 2 | ## github 和 打包上线,感觉比较繁琐 3 | > 每次更新完代码,手动push 到远程仓库,如果想让服务器的代码也同步的话,需要手动去服务器上面,拉取,编译,把编译后的代码复制需要的路径。 4 | ## 使用git webhooks 完美解决这个问题 5 | 详细笔记请移步 6 | https://segmentfault.com/a/1190000011808364 -------------------------------------------------------------------------------- /note/day.log.md: -------------------------------------------------------------------------------- 1 | 2017年10月23日 09:15:03 2 | day1: 3 | 组件拆分 4 | 请求mook数据 5 | 渲染列表 6 | day2: 7 | 图片懒加载 8 | vnshop server搭建好 9 | 配合mongodb 10 | 01.让学员把自己的商城项目提交到github的vnshop项目的issue方便查看 11 | 02.复习上周讲的商品组件 12 | 03.使用vue-lazyload插件实现图片懒加载 13 | 04.使用express脚手架生成,配置nodemon和supervisor方式启动修改后不需要重启node服务 14 | 05.使用express连接mongodb 15 | 07.使用express通过查询mongodb数据实现goods商品列表接口 16 | 08.使用vue请求server的goods的api,并且配置跨域成功访问 17 | -------------------------------------------------------------------------------- /note/homework.md: -------------------------------------------------------------------------------- 1 | 2017年10月20日 17:09:13 2 | 1.先把当前的项目解决,跟着敲 3 | 提交到github上面 4 | 5 | 2.有时间与经历研究一下这个项目 6 | https://github.com/vueguide/vue-toutiao 7 | 8 | 2017年10月26日17:24:45 9 | 1.显示一个默认地址 10 | 2.点击一个地址被选中 11 | 3.点击下一步,确认订单页面 12 | 4.确认订单页面实现,数据也实现渲染 13 | 14 | 15 | 2017年11月1日17:33:23 16 | https://github.com/itguide/-Api 17 | 18 | 把自己选的api提交 19 | https://github.com/itguide/item/issues 20 | 格式: 21 | api:api.shudong.wang 22 | ui link:shudong.wang 23 | category: shop 24 | 25 | 26 | 格式: 27 | FE10-城市+名字 28 | api:api.shudong.wang 29 | ui link:shudong.wang 30 | category: shop -------------------------------------------------------------------------------- /note/item.guide.md: -------------------------------------------------------------------------------- 1 | 组件化 2 | 复用 3 | 降低耦合(解耦) -------------------------------------------------------------------------------- /note/分析需求.md: -------------------------------------------------------------------------------- 1 | 2 | 需求1:价格排序: 3 | 点击页面的按钮从大到小排序,然后再点击从小到大排序 4 | 5 | 前台: 6 | 点击页面按钮 让下面的产品安装价格排序 7 | 需要一个api 8 | 同过两次点击,切换正序和倒序 ,给后端传一个参数 9 | 10 | 开始开发: 11 | 先思考,设计的时间越长,需要修改的时间越短 12 | 请求接口的时候,携带参数,1 -1 13 | 这个怎么来的,通过点击按钮来的 14 | 每次点击按钮 都会改变一个变量值 15 | 变量值默认是 1 16 | 17 | 拿到接口: 18 | postman 测试 19 | 20 | 后端api: 21 | baseurl: localhost:3000 22 | 1:表示接口正常 23 | 0:表示接口不正常 24 | 25 | http 状态码 26 | 200 ok 27 | 400 表示错误 28 | 29 | 拿到需求: 30 | 规定两个参数,来判断输出的结果 31 | 32 | 参数:sort 33 | 34 | api:/goods/list?sort=-1 35 | 接受两个参数: 36 | 接收: 1参数 37 | /goods/list?sort=1 38 | 返回数据: 39 | status:1 40 | msg: 41 | result: 42 | 商品正序数据 43 | 接收:-1 参数 44 | /goods/list?sort=-1 45 | 返回数据:商品倒序 46 | 47 | 48 | 49 | 开始开发: 50 | 在teambition 新建任务 51 | 第一步:从master 检出 最新代码 52 | git pull origin master 53 | 54 | 第二步:git 创建新的分支 55 | git checkout -b sort 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /note/常用工具.md: -------------------------------------------------------------------------------- 1 | json 插件 2 | https://chrome.google.com/webstore/search/json?utm_source=chrome-ntp-icon 3 | 4 | -------------------------------------------------------------------------------- /note/思想.md: -------------------------------------------------------------------------------- 1 | 现阶段: 2 | 每天是用时间换金钱 3 | 受限制 4 | 5 | 每一天 :要达到最高的效率 6 | 7 | 8 | 下一个阶段: 9 | 被动收入 10 | 让你的一份时间,可以出售多份 11 | 12 | 要创建自己的管道 13 | 14 | -------------------------------------------------------------------------------- /note/接口文档.md: -------------------------------------------------------------------------------- 1 | v1:输出所有数据 2 | // router.get('/list', function(req, res, next) { 3 | // Goods.find({}, function(err, doc) { 4 | // if (err) { 5 | // res.json({ status: "1", msg: err.message }) 6 | // } else { 7 | // res.json({ status: '0', msg: '', result: doc }) 8 | // } 9 | // }) 10 | // }) -------------------------------------------------------------------------------- /note/推荐工具.md: -------------------------------------------------------------------------------- 1 | https://sentry.io/welcome/ -------------------------------------------------------------------------------- /note/项目需求.md: -------------------------------------------------------------------------------- 1 | pm 产品经理 2 | 3 | 需求: 4 | 5 | 价格排序: 6 | 点击页面的按钮从大到小排序,然后再点击从小到大排序 -------------------------------------------------------------------------------- /note01/01.技术栈.md: -------------------------------------------------------------------------------- 1 | 一个中小型企业架构: 2 | 3 | 前后分离 4 | 5 | 前端: 6 | vuejs 7 | vue插件 8 | axios 9 | 10 | 后端: 11 | express 12 | 中间件 13 | jwt 14 | passport 15 | 16 | 数据库: 17 | mongodb 18 | redis:做缓存session 用户登陆信息 19 | 20 | 服务端: 21 | Linux :ubuntu + pm2 + git webhook 22 | 23 | web服务: 24 | nginx 25 | 做反向代理 26 | 27 | docker 28 | 29 | 30 | 域名: 31 | 都买一个自己的域名 32 | .com .net .cn 33 | 34 | vnshop.cn 35 | 36 | shudong.wang 37 | 38 | 课程规划: 39 | 第一个阶段: 40 | 使用express 简单api 41 | vue把api查出来显示在页面 42 | 43 | 44 | 模块: 45 | 商品列表 46 | 按照价格范围筛选 47 | 安装价格高低筛选 48 | 登陆 : 49 | 第一个阶段使用cookie 50 | 之后会增加jwt权限验证 51 | 购物车 52 | 购物车列表 53 | 加减数量实时计算价格 54 | 结账 55 | 结账页面 56 | 地址: 57 | 选择地址 58 | 提交订单: 59 | 生成订单号 60 | 订单信息 61 | 上线: 62 | 使用nginx反向代理 63 | 在一台ubuntu上 搭建node服务器 mongodb数据库服务 64 | vuejs上线 65 | pm2启动node 66 | node 是单线程,一旦发生错误,就会崩溃 挂掉 67 | pm2可以管理线程,自动重启 68 | 69 | web githook : 70 | 这个是git 钩子 71 | 当我们把代码提交到github 72 | 需要去服务器把代码拉取下拉 73 | web githook 可以自动监听这个push 事件 74 | 自动把代码拉取下来 75 | 76 | docker : 77 | 集装箱容器: 78 | 把你的环境都集成在一块 79 | 每次你同事来了,或新配置一个环境 80 | 几条命令就可以搞定 81 | 上线发现不对,可以立即回滚 82 | 83 | 时间: 84 | 五天就放假了 85 | 十一回来五天 86 | 87 | 购物车删除 88 | 地址 89 | 订单 90 | 91 | 周三,周四 92 | 上线(操作性挺强) 93 | 需要每个人买一台服务器 94 | ubuntu 95 | centos 96 | 搭建 97 | mongodb 98 | nodejs 99 | vuejs 100 | 101 | docker 102 | 103 | vuex 周二 104 | 105 | 讲一下简历 周五 106 | 项目方面 107 | 工作流程 108 | 109 | 模拟面试 110 | 面试题串讲 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /note01/02.项目结构.md: -------------------------------------------------------------------------------- 1 | client 2 | vue 3 | server 4 | express 5 | 6 | mkdir -p client server 7 | -------------------------------------------------------------------------------- /note01/03.项目初始化.md: -------------------------------------------------------------------------------- 1 | 2 | 初始化项目: 3 | vue 4 | vue init webpack client 5 | 6 | 把静态文件拉取下拉: 7 | https://github.com/itguide/shop-static.git 8 | 9 | git clone https://github.com/itguide/shop-static.git 10 | 11 | 12 | 协作工具 13 | git 14 | teambition 15 | pubu 16 | 17 | ui: 18 | 19 | 后端还没有给ui的时候怎么办? 20 | 自己县模拟数据,提前和后端约定好接口的规格,然后自己使用mock模拟数据 21 | easy-mock.com 22 | 准备数据 23 | http://easy-mock.com/mock/59664d4d58618039284c7710/example/goods/list 24 | 25 | -------------------------------------------------------------------------------- /note01/04.组件.md: -------------------------------------------------------------------------------- 1 | 如果组件的名字和变量的名字一致,就直接写,想改变名字就写成这种对象的方式 2 | HeadNav, 3 | 'stark':NavBread, 4 | NavBread -------------------------------------------------------------------------------- /note01/05.懒加载图片.md: -------------------------------------------------------------------------------- 1 | 懒加载图片使用vue插件 2 | 3 | vue-lazyload 4 | 5 | 使用方式 6 | ``` 7 | import VueLazyLoad from 'vue-lazyload' 8 | 9 | Vue.use(VueLazyLoad, { 10 | loading: '/static/img/ok-2.png'; //添加默认的图片 11 | }) 12 | ``` -------------------------------------------------------------------------------- /note01/06.利用本地的vue项目里面express.模拟数据.md: -------------------------------------------------------------------------------- 1 | 在mock 里面创建一个数据文件 2 | 3 | var app = express() 4 | var compiler = webpack(webpackConfig) 5 | var router = express.Router(); 6 | var goodsList = require('../mock/goods.json'); 7 | 8 | router.get("/goods", function(req, res, next) { 9 | res.json(goodsList); 10 | }) 11 | 12 | app.use(router); -------------------------------------------------------------------------------- /note01/07.使用express-generator生成项目.md: -------------------------------------------------------------------------------- 1 | npm i express-generator -g 2 | 3 | express server 4 | 5 | 6 | https://github.com/7fe/guide/blob/master/nodejs/mongodb/note/mongodb%20guide.pdf -------------------------------------------------------------------------------- /note01/08.前端与后端交互的介质.md: -------------------------------------------------------------------------------- 1 | json xml 2 | 3 | xml 4 | 5 | 6 | George 7 | John 8 | Reminder 9 | Don't forget the meeting! 10 | -------------------------------------------------------------------------------- /note01/09.跨域.md: -------------------------------------------------------------------------------- 1 | Failed to load http://localhost:3000/goods/list: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access. 2 | 3 | -------------------------------------------------------------------------------- /note01/10.价格排序.md: -------------------------------------------------------------------------------- 1 | 当我点击按钮的时候,要不就是按照价格从大到小,要不不小到达 2 | 3 | 前端: 4 | 点击安装触发一个事件,访问一个接口 5 | 每次点击携带,排序参数 6 | 后端: 7 | 通过前端传过来的参数,写业务逻辑,返回前端需要的排序数据 8 | 9 | 业务逻辑: 10 | 业务:就是老板交给你的任务 11 | 根据需求写的一些逻辑 12 | 13 | MongoDB sort()方法 14 | 在MongoDB中使用使用sort()方法对数据进行排序,sort()方法可以通过参数指定排序的字段,并使用 1 和 -1 来指定排序的方式,其中 1 为升序排列,而-1是用于降序排列。 15 | 语法 16 | sort()方法基本语法如下所示: 17 | >db.COLLECTION_NAME.find() 18 | 19 | 20 | ``` 21 | router.get("/list", function(req, res, next) { 22 | let sort = req.param('sort'); 接收前端请求的参数 23 | let goodModel = Goods.find({}).sort({ 'salePrice': sort }); 24 | 执行按照什么排序 25 | 26 | goodModel.exec({}, function(err, doc) { 执行最后的结果 27 | res.json({ status: 0, result: doc }) 28 | }) 29 | }) 30 | ``` -------------------------------------------------------------------------------- /note01/11.按照价格区间筛选商品.md: -------------------------------------------------------------------------------- 1 | 按照价格区间筛选商品 2 | 接口: 3 | 参数: 4 | 范围: 5 | all 所有 6 | 0 : 0 -100 7 | 1: 100 -500 8 | 2: 500 -1000 9 | 10 | 直接两个参数: 11 | 开始价格 - 结束价格 12 | 13 | 14 | 前端: 15 | 点击价格区间的按钮 16 | 商品重新渲染 17 | 18 | 19 | ``` 20 | MongoDB 条件操作符 21 | 22 | 描述 23 | 条件操作符用于比较两个表达式并从mongoDB集合中获取数据。 24 | 在本章节中,我们将讨论如何在MongoDB中使用条件操作符。 25 | MongoDB中条件操作符有: 26 | (>) 大于 - $gt 27 | (<) 小于 - $lt 28 | (>=) 大于等于 - $gte 29 | (<= ) 小于等于 - $lte 30 | 我们使用的数据库名称为"runoob" 我们的集合名称为"col",以下为我们插入的数据。 31 | 为了方便测试,我们可以先使用以下命令清空集合 "col" 的数据: 32 | db.col.remove({}) 33 | 34 | 35 | db.col.find({"likes" : {$gt : 100}}) 36 | 37 | Select * from col where likes > 100; 38 | ``` -------------------------------------------------------------------------------- /note01/12.商品分页,瀑布流,下拉加载.md: -------------------------------------------------------------------------------- 1 | 前端: 2 | 当用户打开首页的时候显示8条,当用户滚动屏幕到显示的商品边缘,然后加载新的数据。 3 | 4 | 实现: 5 | 检测用户滚动商品边缘,请求下一页的api,然后写入到页面 6 | 7 | 代码实现: 8 | infiniteScroll 9 | vue-infinite-scroll 10 | 11 | npm install vue-infinite-scroll --save 12 | 13 | 在页面里面使用 14 | 在 main.js 15 | 16 | import infiniteScroll from 'vue-infinite-scroll' 17 | Vue.use(infiniteScroll) 18 | 19 | 使用方式: 20 | https://www.npmjs.com/package/vue-infinite-scroll 21 | 22 | ``` 23 | 24 |
    25 | ... 26 |
    27 | 28 | v-infinite-scroll="loadMore" 当页面触发到底部的时候 执行这个函数 29 | infinite-scroll-disabled="busy" 判断当滚动满足条件后是否执行loadMore函数 30 | 31 | infinite-scroll-distance="10" 距离底部多远然后执行loadMore 32 | 33 | 34 | 35 | var count = 0; 36 | 37 | new Vue({ 38 | el: '#app', 39 | data: { 40 | data: [], 41 | busy: false 42 | }, 43 | methods: { 44 | loadMore: function() { 45 | this.busy = true; 46 | 47 | setTimeout(() => { 48 | for (var i = 0, j = 10; i < j; i++) { 49 | this.data.push({ name: count++ }); 50 | } 51 | this.busy = false; 52 | }, 1000); 53 | } 54 | } 55 | }); 56 | ``` 57 | 58 | 59 | ``` 60 | getGoods(flag){ 61 | let sort = this.sortFlag ? 1 : -1; 62 | let param = { 63 | sort:sort, 64 | priceLevel:this.priceChecked, 65 | page:this.page, 66 | pagesize:this.pagesize 67 | } 68 | axios.get('/goods/list',{params:param}).then(result=>{ 69 | let res = result.data; 70 | // this.list= res.data.result; 71 | if(flag){ //判断是否通过分页请求 72 | // 分页的数据追加到这个list里面 73 | this.list = this.list.concat(res.result); 74 | 75 | // 判断当数据加载完了,让数据截停 76 | console.log(res.result.length); 77 | if(res.result.length == 0){ 78 | this.busy = true; 79 | console.log(this.busy); 80 | }else{ 81 | this.busy = false; 82 | } 83 | }else{ 84 | // 第一次请求 85 | this.list = res.result; 86 | this.busy = false; 87 | } 88 | console.log(res.result); 89 | }) 90 | }, 91 | 92 | loadMore: function() { 93 | this.busy = true; 94 | setTimeout(() => { 95 | // console.log(1111); 96 | this.page++; 97 | this.getGoods(true); 98 | }, 500); 99 | } 100 | ``` 101 | 后端: 102 | api:需要两个参数 103 | page:第几页 104 | prepage: 一页显示几条 105 | -------------------------------------------------------------------------------- /note01/13.解决node修改完重启问题.md: -------------------------------------------------------------------------------- 1 | 2 | 使用方式1 3 | npm i supervisor -g 4 | supervisor bin/www 5 | 6 | 方式二 nodemon cross-env 7 | 8 | npm i cross-env nodemon -D 9 | 10 | 在package里面配置 11 | "start": "cross-env NODE_ENV=development ./node_modules/.bin/nodemon ./bin/www" 12 | 13 | 14 | 方式三 15 | pm2 16 | -------------------------------------------------------------------------------- /note01/14.加入购物车.md: -------------------------------------------------------------------------------- 1 | 业务逻辑 2 | 3 | 点击加入购物车的时候,把商品id传给api,然后在购物列表展示出来 4 | 5 | api: 6 | 接收商品 7 | goods_id 8 | userid 9 | 10 | 查询用哪个用户,确定好用户 11 | 通过商品id去数据库查询,把商品的信息查出来, 12 | 此时去查询这个商品是否存在于用户购物车列表里面 13 | 如果存在则商品数量加一,不存在把整个商品信息存到里面 14 | 然后存到这个用户里面 15 | 16 | 17 | -------------------------------------------------------------------------------- /note01/15.mongoose.md: -------------------------------------------------------------------------------- 1 | https://segmentfault.com/a/1190000010688972 2 | 3 | 4 | 名词解释 5 | Schema: 一种以文件形式存储的数据库模型骨架,不具备数据库的操作能力 6 | Model: 由Schema编译而成的假想(fancy)构造器,具有抽象属性和行为。Model的每一个实例(instance)就是一个document。document可以保存到数据库和从数据库返回。 7 | Instance: 由Model创建的实例。 -------------------------------------------------------------------------------- /note01/16.用户登陆.md: -------------------------------------------------------------------------------- 1 | 前端:点击登陆按钮,把用户的用户名和密码传到后端,到用户表里面去查询。 2 | 如果有这个用户,这个小点点,那个名字就变成用户名, 3 | 4 | 总结 : 5 | 给后端接口传 6 | 用户名 7 | 密码 8 | 返回结果: 9 | 登陆成功 10 | 登陆的信息 11 | 登录失败 12 | 失败的提示信息 13 | 14 | 15 | 后端: 16 | 接收两个参数 17 | 参数1:用户名 18 | 参数2: 密码 19 | 20 | 业务逻辑: 21 | 先把用户名去数据库查询,如果有, 22 | 去验证密码 23 | 验证密码 24 | 正确: 25 | 验证验证码 26 | 错误: 27 | 返回提示 28 | 如果没有 29 | 返回用户名不存在 30 | 31 | 如果上面验证成功 32 | 需要记录一下用户的登陆状态 33 | session 34 | 存在服务端 35 | 比较安全 36 | 37 | 占用服务器空间 38 | redis memcache 39 | 数据库 高速缓存 40 | cookie 41 | 存在本地 42 | 不安全 43 | 44 | 45 | 密码验证: 46 | md5(md5 + 随机数) 47 | 48 | md5不可逆 49 | 123456 50 | 34576asaddsadaslsalasd 51 | 52 | sha1 53 | base64 54 | 55 | -------------------------------------------------------------------------------- /note01/19.在vue中怎么优雅的配置本地代理.md: -------------------------------------------------------------------------------- 1 | ``` 2 | proxyTable: { 3 | '/goods/**': { 4 | target: 'http://localhost:3000' 5 | }, 6 | '/users/**': { 7 | target: 'http://localhost:3000' 8 | }, 9 | }, 10 | ``` 11 | 这样有个弊端 12 | 每次开发的时候都需要配置 13 | 万一 vue 的路由也是 goods users 就会产生矛盾 14 | 15 | 理想方式 16 | 配置一个路由,尽量避免和vue路由冲突 17 | 18 | 配置 19 | /api/** 20 | 21 | 每次在路由里面 22 | get('/api/users/login') 23 | get('/api/users/logout') 24 | get('/api/goods/list') 25 | 26 | 27 | get('/v1/goods/list') 28 | 29 | 30 | 最理想的方式 31 | get('/users/login) 32 | 33 | target: http://localhost:3000/users/login 34 | 35 | 36 | Axios.defaults.baseURL = apiConfig.baseUrl; 37 | 38 | 在每个使用axios请求的时候,自动加上api前缀 39 | 40 | 使用方式 41 | this.$http.get('users/login); 42 | 43 | 相当于访问:http://localhost:8080/api/users/login 44 | 代理 45 | 匹配到api 46 | 转发 47 | http://localhost:3000/users/login 48 | 49 | http://localhost:8080/api/goods/list 50 | 51 | http://localhost:3000/goods/list 52 | 53 | ``` 54 | '/api/**': { 55 | target: 'http://localhost:3000', 56 | pathRewrite: { 57 | '^/api': '/' 58 | } 59 | } 60 | ``` -------------------------------------------------------------------------------- /note01/20.登陆拦截.md: -------------------------------------------------------------------------------- 1 | 当我们添加购物车的时候,检测用户是否登陆 2 | 3 | 如果没登陆,提示弹窗 目前没有登陆,请去登陆 4 | 5 | -------------------------------------------------------------------------------- /note01/21.国庆作业.md: -------------------------------------------------------------------------------- 1 | 国庆回来要面临找工作 2 | 所以说呢,最好在国庆自己准备一个项目 3 | api记得提交到论坛 作业模块 4 | 5 | 可以在大群里面问 6 | 7 | 8 | 9 | 项目写累了刷刷面试题 10 | mianshiti.shudong.wanag -------------------------------------------------------------------------------- /note01/23.全选.全不选.md: -------------------------------------------------------------------------------- 1 | 1.判断:当前购物车里面的选中的数量 == 购物车所有的商品数量 2 | 3 | 能判断出:目前是全部选中的状态 4 | 5 | 如果是这个状态的时候:此时点击按钮全不选中 6 | 否则取反 7 | 8 | -------------------------------------------------------------------------------- /note01/24.登录流程.md: -------------------------------------------------------------------------------- 1 | 使用vue 2 | 3 | import Cookies from 'universal-cookie' 4 | const cookies = new Cookies() 5 | import { CookieDomain } from '../config.js' 6 | let cookieConfig = {} 7 | if(CookieDomain !== ''){ 8 | cookieConfig = { domain: CookieDomain } //path:'/',maxAge:365*24*60*60 9 | } 10 | 11 | export function saveCookie(name,value) { 12 | cookies.set(name, value, cookieConfig) 13 | } 14 | 15 | export function getCookie(name) { 16 | return cookies.get(name) 17 | } 18 | 19 | export function removeCookie(name) { 20 | cookies.remove(name, cookieConfig) 21 | } 22 | 23 | export function signOut() { 24 | cookies.remove('token', cookieConfig) 25 | } 26 | 27 | export function isLogin() { 28 | console.log(!!cookies.get('token'),'islogin'); 29 | return !!cookies.get('token') 30 | } 31 | 32 | 33 | 34 | router.beforeEach((to, from, next) => { 35 | // to.matched.some( 36 | // function(record){ 37 | // console.log(record.meta) 38 | // } 39 | // ) 40 | // console.log(to.matched.some(record => record.meta.requiresAuth)) 41 | if (to.matched.some(record => record.meta.goTop)) { 42 | window.scroll(0, 0) 43 | } 44 | 45 | if (to.matched.some(record => record.meta.requiresAuth)) { 46 | // console.log(record.meta.requiresAuth) 47 | if (!isLogin()) { 48 | return next({path: '/pages/login'}) 49 | } 50 | } 51 | if (to.matched.some(record => record.meta.requiresNotAuth)) { 52 | if (isLogin()) { 53 | return next({path: '/'}) 54 | } 55 | } 56 | next() 57 | }) 58 | 59 | export default router 60 | -------------------------------------------------------------------------------- /note01/25.删除购物车.md: -------------------------------------------------------------------------------- 1 | 前端: 2 | 点击删除按钮把商品删除 并且页面立刻把这个商品删除掉 3 | 后端: 4 | 接受参数: 5 | 用户id 6 | 商品id 7 | 8 | 9 | ``` 10 | // 操作的事情 11 | $pull: { 12 | 'cartList': { 13 | 'productId': productId 14 | } 15 | } 16 | ``` 17 | -------------------------------------------------------------------------------- /note01/26.设计数据库.md: -------------------------------------------------------------------------------- 1 | activity 2 | id 3 | user_id 4 | status 5 | 报名 10 6 | 预审核 15 7 | 审核 20 8 | 正常参加 30 9 | 迟到 40 10 | 爽约 50 11 | 12 | 参加活动 -------------------------------------------------------------------------------- /note01/27.支付生成订单号.md: -------------------------------------------------------------------------------- 1 | 前端: 2 | 后端: 3 | 接受参数: 4 | 用户id 5 | 地址id 6 | 订单总金额 7 | 8 | 9 | 10 | 订单号 11 | 订单总金额 12 | 地址信息 13 | 商品列表 14 | 订单状态 15 | 创建时间 16 | -------------------------------------------------------------------------------- /note01/28.项目上线.md: -------------------------------------------------------------------------------- 1 | #### 选购服务器 2 | 板瓦工 推荐1g以上内存 3 | https://www.bwh1.net/ 4 | 5 | 阿里云 6 | https://common-buy.aliyun.com/?spm=5176.10003347.843204.1.Ql3ciJ&commodityCode=swas&request=undefined#/buy 7 | 8 | 9 | 推荐阿里云 10 | https://promotion.aliyun.com/ntms/act/qwbk.html?open_id=4dc9ecb7-9a7d-4800-a51a-a659a1ebb2ca-511180874&open_cid=187 11 | 12 | https://cloud.digitalocean.com/login 13 | 14 | https://www.vultr.com/ 15 | https://www.vultr.com/pricing/ 16 | 17 | #### 搭建环境 18 | nginx 19 | php fpm 20 | mysql 21 | mongodb 22 | nodejs 23 | 24 | pm2 25 | 26 | #### 绑定域名 27 | 子域名 28 | 29 | gitlab.com 30 | 31 | 32 | 野狗 33 | 34 | 35 | #### 做哪些事情 36 | bbs.shudong.wang 37 | 38 | wordpress 39 | 40 | hexo 41 | 42 | 今天把服务器搞定 43 | 44 | #### 域名注册 45 | 优先选购: 46 | .com .net .cn 47 | 48 | 位数要短一些 49 | 其它后缀尽量有意义 50 | 51 | vnshop.cn 52 | 53 | 国内的服务器必须备案 54 | 55 | 最好是国外的 56 | 或香港的 57 | 如果选国外的最好选择日本 58 | 59 | 优先选择香港 -------------------------------------------------------------------------------- /note01/mongodb 安装连接方式.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/note01/mongodb 安装连接方式.pdf -------------------------------------------------------------------------------- /note01/vue+express+mongodb项目上线 (1).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wsdo/vnshop/99b6458c1c4512148b9e44aff51abab5d813154a/note01/vue+express+mongodb项目上线 (1).pdf -------------------------------------------------------------------------------- /note01/学习效率.md: -------------------------------------------------------------------------------- 1 | ## 使用云笔记 2 | 有道云 3 | 印象笔记 4 | 为之笔记 5 | 6 | 丢掉用纸和笔 7 | 辛辛苦苦记这么多,丢了什么都没了 8 | 还不利于 复制 9 | 10 | 平时使用 gtd 工具 11 | 番茄工作法 12 | 集中精力25分钟 休息5分钟 13 | 番茄时钟 14 | 15 | 小强升职记 16 | gtd 17 | get things done 18 | 19 | 使用mac 20 | mac pro 21 | 22 | 一定要配两个显示器 23 | 24 | 技术是吃饭的东西,一定要在这个上面下功夫 25 | 26 | 对于开发来说,命令行很方便 27 | 28 | 技术牛逼和你工作时间,关系并不是很大 29 | 30 | 最快的成长方式 31 | 32 | 三年工作经验的人都具备哪些技能 33 | Linux 34 | php java go 35 | node 36 | koa 37 | express 38 | thinkjs 39 | js 40 | 41 | 把自己的时间分块 42 | 第一个月去攻破哪个 43 | 把学习方法总结成框架 44 | 45 | 46 | 尤其是自己薪资 47 | 软实力 48 | 49 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # vnshop 商城 2 | > 如果帮助到你,那就点个star吧。 3 | 4 | 技术栈: vue mongodb node 5 | ![2019-04-24-23-30-32](http://s.shudong.wang/aaa.jpg) 6 | > 课程视频,可以联系我 7 | https://shudong.wang/about 8 | ## 项目架构 9 | 前后分离 10 | 11 | 前端: 12 | 使用vue cli 脚手架方式搭建 13 | 14 | api: 15 | 使用node express框架搭建 16 | 17 | [课程地址](https://segmentfault.com/ls/1650000018979204) 18 | 19 | ## 项目目录 20 | cd vnshop 21 | mkdir -p client note server 22 | 23 | #### vnshop 24 | client #客户端代码,里面放的是vue项目工程文件 25 | 26 | note #搭建项目的详细笔记 27 | 28 | server #node express 代码 29 | 30 | ## 项目上线 视频上传到segmentfault 讲堂 31 | 32 | ## vnshop项目视频 33 | ### 详细内容 34 | 35 | 01.课程规划 36 | 02.github操作的几个场景 37 | 03.把本地的仓库提交到远程 38 | 04.vue初识.周边资源介绍 39 | 05.vue.helloworl.插值,双向绑定 40 | 06.指令.bind if 41 | 07.生命周期案例详细讲解 42 | 08.jq在生命周期函数里面的应用 43 | 10.v-show指令 44 | 11.模版和渲染 45 | 12.插槽基本使用,具名插槽,项目中应用场景 46 | 13.组件1,组件2,全局组件 47 | 14.v-on事件 48 | 15.动态组件 49 | 16.props 50 | 17.watch监听,深度监听 51 | 18.filter自定义过滤器 52 | 19.git 操作指南上课代码拉下拉,并且更新代码 53 | 20.自定义指令 54 | 21.自定义拖拽指令 55 | 22.vue-resource.get.post.jsonp.方式请求接口 56 | 23.axios 请求api的方式post 和 get区别 57 | 24.vue-cli项目初始化 58 | 25.git合并 59 | 26.解决问题的方式 60 | 27.vue项目目录的说明 61 | 28.vue.编译流程,webpack文件讲解 62 | 29.vue文件分析 63 | 30.vue项目入口文件分析 64 | 31.路由history,hash,默认激活样式,exact讲解 65 | 32.自定义全局激活样式,嵌套路由 66 | 33.路由重定向 67 | 34.路由传参 68 | 35.复习 69 | 36.成产环境和开发环境 70 | 37.解决问题的能力 71 | 38.在vue项目中使用axios访问接口,解决跨域问题 72 | 39.案例,获取知乎日报的信息,写在组件上,解决跨域,图片403问题 73 | 40.使用vue-axios方式访问api 74 | 41.vue-axios源码分析 75 | 42.vuex介绍 76 | 43.vuex在项目简单入门使用 77 | 44.vuex 提交 mutation paload传参 78 | 45.解决api请求权限问题 79 | 46.学习的方式 80 | 47.mutations 提交type类型 81 | 48.actions使用方式 82 | 49.getters使用方式 83 | 50.mapState,mapGetters,mapAction辅助函数使用 84 | 51.项目初始化 85 | 52.vue常见错误收集 86 | 87 | ## 全栈项目上线 88 | [课程地址](https://segmentfault.com/ls/1650000018979204) 89 | 90 | 01.购买流行的vps服务器教程 91 | 02.域名注册 92 | 03.域名注册商介绍godaddy.com域名注册,park.io等信息 93 | 04.利用xshell连接Linux Ubuntu系统详细操作方式 94 | 05.【全栈项目上线(vue+node+mongodb)】安装lnmp环境 nginx mysql php 环境 95 | 06.lnmp环境安装成功并且测试 96 | 07.nodejs环境安装 97 | 08.安装mongodb 98 | 09.mongodb安装测试执行mongodb shell命令 99 | 10.解决无法解析主机名字问题 100 | 11.mongodb通用解决方案 101 | 12.缩减版的安装php mysql Nginx node mongodb 6分钟搞定 102 | 13.部署项目的方式,介绍 103 | 14.怎么在一台服务器上部署多个站点 104 | 15.项目上线方案一上传文件解压文件实现 105 | 16.项目上线方案二从github拉取 106 | 17.项目上线完毕 107 | 18.负载均衡的概念 108 | 19.使用git webhooks 优雅的自动化上线vue项目(巨详细) 109 | 20.git webhooks 自动化上线 110 | 21.搭建博客系统WordPress 111 | 22.搭建hexo博客 112 | 113 | 114 | -------------------------------------------------------------------------------- /server/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | test/unit/coverage 8 | test/e2e/reports 9 | selenium-debug.log 10 | 11 | # Editor directories and files 12 | .idea 13 | *.suo 14 | *.ntvs* 15 | *.njsproj 16 | *.sln 17 | -------------------------------------------------------------------------------- /server/app.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var path = require('path'); 3 | var favicon = require('serve-favicon'); 4 | var logger = require('morgan'); 5 | var cookieParser = require('cookie-parser'); 6 | var bodyParser = require('body-parser'); 7 | 8 | var index = require('./routes/index'); 9 | var users = require('./routes/users'); 10 | var goods = require('./routes/goods'); 11 | 12 | var app = express(); 13 | 14 | // view engine setup 15 | app.set('views', path.join(__dirname, 'views')); 16 | app.set('view engine', 'jade'); 17 | 18 | // uncomment after placing your favicon in /public 19 | //app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); 20 | app.use(logger('dev')); 21 | app.use(bodyParser.json()); 22 | app.use(bodyParser.urlencoded({ extended: false })); 23 | app.use(cookieParser()); 24 | app.use(express.static(path.join(__dirname, 'public'))); 25 | 26 | // 访问拦截 就是所有访问都走这个逻辑 27 | app.use(function(req, res, next) { 28 | if (req.cookies.userId) { 29 | next(); 30 | } else { 31 | if ( 32 | req.originalUrl == '/users/login' || 33 | req.path == '/goods/list' 34 | ) { 35 | next() 36 | } else { 37 | res.json({ 38 | status: '1', 39 | msg: '当前用户未登录', 40 | result: '' 41 | }) 42 | } 43 | } 44 | }) 45 | 46 | app.use('/', index); 47 | app.use('/users', users); 48 | app.use('/goods', goods); 49 | 50 | // catch 404 and forward to error handler 51 | app.use(function(req, res, next) { 52 | var err = new Error('Not Found'); 53 | err.status = 404; 54 | next(err); 55 | }); 56 | 57 | // error handler 58 | app.use(function(err, req, res, next) { 59 | // set locals, only providing error in development 60 | res.locals.message = err.message; 61 | res.locals.error = req.app.get('env') === 'development' ? err : {}; 62 | 63 | // render the error page 64 | res.status(err.status || 500); 65 | res.render('error'); 66 | }); 67 | 68 | module.exports = app; -------------------------------------------------------------------------------- /server/bin/www: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | var app = require('../app'); 8 | var debug = require('debug')('server:server'); 9 | var http = require('http'); 10 | 11 | /** 12 | * Get port from environment and store in Express. 13 | */ 14 | 15 | var port = normalizePort(process.env.PORT || '3000'); 16 | app.set('port', port); 17 | 18 | /** 19 | * Create HTTP server. 20 | */ 21 | 22 | var server = http.createServer(app); 23 | 24 | /** 25 | * Listen on provided port, on all network interfaces. 26 | */ 27 | 28 | server.listen(port); 29 | server.on('error', onError); 30 | server.on('listening', onListening); 31 | 32 | /** 33 | * Normalize a port into a number, string, or false. 34 | */ 35 | 36 | function normalizePort(val) { 37 | var port = parseInt(val, 10); 38 | 39 | if (isNaN(port)) { 40 | // named pipe 41 | return val; 42 | } 43 | 44 | if (port >= 0) { 45 | // port number 46 | return port; 47 | } 48 | 49 | return false; 50 | } 51 | 52 | /** 53 | * Event listener for HTTP server "error" event. 54 | */ 55 | 56 | function onError(error) { 57 | if (error.syscall !== 'listen') { 58 | throw error; 59 | } 60 | 61 | var bind = typeof port === 'string' 62 | ? 'Pipe ' + port 63 | : 'Port ' + port; 64 | 65 | // handle specific listen errors with friendly messages 66 | switch (error.code) { 67 | case 'EACCES': 68 | console.error(bind + ' requires elevated privileges'); 69 | process.exit(1); 70 | break; 71 | case 'EADDRINUSE': 72 | console.error(bind + ' is already in use'); 73 | process.exit(1); 74 | break; 75 | default: 76 | throw error; 77 | } 78 | } 79 | 80 | /** 81 | * Event listener for HTTP server "listening" event. 82 | */ 83 | 84 | function onListening() { 85 | var addr = server.address(); 86 | var bind = typeof addr === 'string' 87 | ? 'pipe ' + addr 88 | : 'port ' + addr.port; 89 | debug('Listening on ' + bind); 90 | } 91 | -------------------------------------------------------------------------------- /server/models/goods.js: -------------------------------------------------------------------------------- 1 | var mongoose = require('mongoose'); 2 | var Schema = mongoose.Schema; 3 | var productSchema = new Schema({ 4 | "productId": String, 5 | "productName": String, 6 | "productPrice": Number, 7 | "productImage": String, 8 | "productNum": String, 9 | }) 10 | 11 | module.exports = mongoose.model("Goods", productSchema) -------------------------------------------------------------------------------- /server/models/user.js: -------------------------------------------------------------------------------- 1 | var mongoose = require('mongoose'); 2 | var Schema = mongoose.Schema; 3 | var userSchema = new Schema({ 4 | "userId": String, 5 | "userName": String, 6 | "orderList": Array, 7 | "cartList": Array, 8 | "cartList": [{ 9 | "productId": String, 10 | "productName": String, 11 | "salePrice": Number, 12 | "productImage": String, 13 | "productUrl": String, 14 | "productNum": Number, 15 | "checked": String 16 | }], 17 | "addressList": [{ 18 | "addressId": String, 19 | "userName": String, 20 | "streetName": String, 21 | "postCode": Number, 22 | "tel": Number, 23 | "isDefault": Boolean 24 | }] 25 | }) 26 | 27 | module.exports = mongoose.model('user', userSchema); -------------------------------------------------------------------------------- /server/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "0.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "basic-auth": { 8 | "version": "2.0.1", 9 | "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", 10 | "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", 11 | "requires": { 12 | "safe-buffer": "5.1.2" 13 | } 14 | }, 15 | "depd": { 16 | "version": "1.1.2", 17 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 18 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 19 | }, 20 | "ee-first": { 21 | "version": "1.1.1", 22 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 23 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 24 | }, 25 | "morgan": { 26 | "version": "1.9.1", 27 | "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz", 28 | "integrity": "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==", 29 | "requires": { 30 | "basic-auth": "~2.0.0", 31 | "debug": "2.6.9", 32 | "depd": "~1.1.2", 33 | "on-finished": "~2.3.0", 34 | "on-headers": "~1.0.1" 35 | }, 36 | "dependencies": { 37 | "debug": { 38 | "version": "2.6.9", 39 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 40 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 41 | "requires": { 42 | "ms": "2.0.0" 43 | } 44 | } 45 | } 46 | }, 47 | "ms": { 48 | "version": "2.0.0", 49 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 50 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 51 | }, 52 | "on-finished": { 53 | "version": "2.3.0", 54 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 55 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 56 | "requires": { 57 | "ee-first": "1.1.1" 58 | } 59 | }, 60 | "on-headers": { 61 | "version": "1.0.2", 62 | "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", 63 | "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" 64 | }, 65 | "safe-buffer": { 66 | "version": "5.1.2", 67 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 68 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "cross-env NODE_ENV=development ./node_modules/.bin/nodemon ./bin/www" 7 | }, 8 | "dependencies": { 9 | "body-parser": "~1.17.1", 10 | "cookie-parser": "~1.4.3", 11 | "debug": "~2.6.3", 12 | "express": "~4.15.2", 13 | "jade": "~1.11.0", 14 | "morgan": "^1.9.1", 15 | "serve-favicon": "~2.4.2" 16 | }, 17 | "devDependencies": { 18 | "cross-env": "^5.0.5", 19 | "mongoose": "^4.11.13", 20 | "nodemon": "^1.12.1" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /server/public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | 6 | a { 7 | color: #00B7FF; 8 | } 9 | -------------------------------------------------------------------------------- /server/routes/goods.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | var mongoose = require('mongoose'); 4 | var Goods = require('../models/goods') 5 | var User = require('../models/user') 6 | mongoose.connect('mongodb://47.93.231.75:27017/shops'); 7 | 8 | mongoose.connection.on('connected', function() { 9 | console.log("mongondb connected success"); 10 | }) 11 | 12 | mongoose.connection.on('error', function() { 13 | console.log("mongondb connected fail"); 14 | }) 15 | 16 | mongoose.connection.on('disconnected', function() { 17 | console.log("mongondb connected disconnected"); 18 | }) 19 | 20 | router.get("/list", function(req, res, next) { 21 | 22 | let sort = req.param('sort'); 23 | let priceLevel = req.param('priceLevel'); 24 | let priceGt = '', 25 | priceLte = ''; 26 | 27 | let param = {}; 28 | 29 | if (priceLevel != 'all') { 30 | // switch (priceLevel) { 31 | // case '0': 32 | // priceGt = 0; 33 | // priceLte = 100; 34 | // break; 35 | // case '1': 36 | // priceGt = 100; 37 | // priceLte = 500; 38 | // break; 39 | // case '2': 40 | // priceGt = 500; 41 | // priceLte = 1000; 42 | // break; 43 | // case '3': 44 | // priceGt = 1000; 45 | // priceLte = 5000; 46 | // break; 47 | // } 48 | 49 | // 表驱动法 50 | let priceItem = [ 51 | [0, 100], 52 | [100, 500], 53 | [500, 1000], 54 | [1000, 5000] 55 | ]; 56 | param = { 57 | salePrice: { 58 | // $gt: priceGt, 59 | // $lte: priceLte 60 | $gt: priceItem[priceLevel][0], 61 | $lte: priceItem[priceLevel][1] 62 | } 63 | } 64 | } 65 | 66 | console.log(param); 67 | 68 | let currentPage = (parseInt(req.param('page')) > 0) ? parseInt(req.param('page')) : 1; //第几页 69 | let pagesize = (parseInt(req.param('pagesize')) > 0) ? parseInt(req.param('pagesize')) : 8; //每页显示多少条 70 | 71 | let skip = (currentPage - 1) * pagesize; 72 | 73 | // 数据库一共有17条数据 每页显示8条 第二页 从第九条开始 limit 从第9条起数8条为止 这个8就是limit 74 | 75 | let goodModel = Goods.find(param).sort({ 'salePrice': sort }).skip(skip).limit(pagesize); 76 | goodModel.exec({}, function(err, doc) { 77 | res.json({ status: 0, result: doc }) 78 | }) 79 | }) 80 | 81 | router.post('/addCart', function(req, res, next) { 82 | // 查询用哪个用户, 确定好用户 83 | let userId = '100000077'; 84 | // 商品id 85 | var productId = req.body.productId; 86 | // console.log(productId); 87 | User.findOne({ userId: userId }, function(err, userDoc) { 88 | // console.log(userDoc); 89 | // 通过商品id去数据库查询, 把商品的信息查出来, 90 | 91 | let goodItem = ''; 92 | userDoc.cartList.forEach(function(item) { 93 | if (item.productId == productId) { 94 | // 此时表示在购物车列表存在这个商品 95 | goodItem = item; 96 | item.productNum++; 97 | } 98 | }) 99 | 100 | // 如果不是第一次加入购物车 101 | if (goodItem) { 102 | userDoc.save(function(err3, doc3) { 103 | if (err3) { 104 | res.json({ status: "1", msg: err3.message }) 105 | } else { 106 | res.json({ status: 0, msg: '', result: '商品数量添加成功!' }) 107 | } 108 | }) 109 | } else { 110 | // 商品第一次加入购物车 111 | // 怎么判断是第一次加入购物车还是购物车里面已经有了 112 | Goods.findOne({ 'productId': productId }, function(err1, goodDoc) { 113 | console.log(goodDoc); 114 | console.log(productId); 115 | goodDoc.productNum = 1; 116 | goodDoc.checked = 1; 117 | // 此时去查询这个商品是否存在于用户购物车列表里面 118 | 119 | userDoc.cartList.push(goodDoc); 120 | userDoc.save(function(err2, doc2) { 121 | if (err2) { 122 | res.json({ status: 1, msg: err2.message }) 123 | } else { 124 | res.json({ status: 0, msg: '', result: "加入购物车成功" }) 125 | } 126 | }) 127 | }) 128 | } 129 | 130 | 131 | }) 132 | 133 | // 如果存在则商品数量加一, 不存在把整个商品信息存到里面 134 | // 然后存到这个用户里面 135 | 136 | }) 137 | module.exports = router; -------------------------------------------------------------------------------- /server/routes/index.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | /* GET home page. */ 5 | router.get('/', function(req, res, next) { 6 | res.render('index', { title: ' stark' }); 7 | }); 8 | 9 | router.get('/stark', function(req, res, next) { 10 | res.json({ 'name': 'stark' }); 11 | }); 12 | 13 | module.exports = router; -------------------------------------------------------------------------------- /server/util/util.js: -------------------------------------------------------------------------------- 1 | Date.prototype.Format = function(fmt) { //author: meizz 2 | var o = { 3 | "M+": this.getMonth() + 1, //月份 4 | "d+": this.getDate(), //日 5 | "h+": this.getHours(), //小时 6 | "m+": this.getMinutes(), //分 7 | "s+": this.getSeconds(), //秒 8 | "q+": Math.floor((this.getMonth() + 3) / 3), //季度 9 | "S": this.getMilliseconds() //毫秒 10 | }; 11 | if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); 12 | for (var k in o) 13 | if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); 14 | return fmt; 15 | } 16 | 17 | module.exports = {}; -------------------------------------------------------------------------------- /server/views/error.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= message 5 | h2= error.status 6 | pre #{error.stack} 7 | -------------------------------------------------------------------------------- /server/views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= title 5 | p Welcome to #{title} 6 | -------------------------------------------------------------------------------- /server/views/layout.jade: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | title= title 5 | link(rel='stylesheet', href='/stylesheets/style.css') 6 | body 7 | block content 8 | --------------------------------------------------------------------------------