├── .browserslistrc ├── .eslintrc.js ├── .gitattributes ├── .gitignore ├── .prettierrc ├── README.md ├── babel.config.js ├── dist ├── favicon.ico ├── fonts │ ├── element-icons.535877f5.woff │ └── element-icons.732389de.ttf ├── img │ ├── cart-empty.8b316431.png │ ├── cart.png │ ├── center.png │ ├── clogo.13a5aaf4.png │ ├── detail.png │ ├── error.73de3ae8.png │ ├── favorite.png │ ├── home.png │ ├── login.png │ ├── order.png │ ├── product.png │ ├── register.png │ └── userdetail.png └── index.html ├── docker ├── Dockerfile ├── dist │ ├── favicon.ico │ ├── fonts │ │ ├── element-icons.535877f5.woff │ │ └── element-icons.732389de.ttf │ ├── img │ │ ├── cart-empty.8b316431.png │ │ ├── cart.png │ │ ├── center.png │ │ ├── clogo.13a5aaf4.png │ │ ├── detail.png │ │ ├── error.73de3ae8.png │ │ ├── favorite.png │ │ ├── home.png │ │ ├── login.png │ │ ├── order.png │ │ ├── product.png │ │ ├── register.png │ │ └── userdetail.png │ └── index.html ├── docker-compose.yaml └── nginx.conf ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── img │ ├── cart.png │ ├── center.png │ ├── detail.png │ ├── favorite.png │ ├── home.png │ ├── login.png │ ├── order.png │ ├── product.png │ ├── register.png │ └── userdetail.png └── index.html ├── src ├── App.vue ├── Global.js ├── api │ ├── addresses │ │ └── index.js │ ├── carousels │ │ └── index.js │ ├── carts │ │ └── index.js │ ├── categories │ │ └── index.js │ ├── count │ │ └── index.js │ ├── favorites │ │ └── index.js │ ├── img │ │ └── index.js │ ├── notice │ │ └── index.js │ ├── orders │ │ └── index.js │ ├── payment │ │ └── index.js │ ├── products │ │ └── index.js │ ├── ranking │ │ └── index.js │ ├── upload │ │ └── index.js │ └── users │ │ └── index.js ├── assets │ ├── css │ │ ├── button.css │ │ ├── github-markdown.css │ │ └── index.css │ ├── gt.js │ ├── imgs │ │ ├── QQlogo.png │ │ ├── cart-empty.png │ │ ├── clogo.png │ │ ├── error.png │ │ ├── github.png │ │ ├── logo.png │ │ ├── placeholder.png │ │ └── us-icon.png │ └── logo.png ├── components │ ├── CenterMenu.vue │ ├── Error.vue │ ├── MyList.vue │ ├── MyMarkdown.vue │ └── MyMenu.vue ├── main.js ├── router │ └── index.js ├── store │ ├── index.js │ └── modules │ │ ├── shoppingCart.js │ │ └── user.js └── views │ ├── About.vue │ ├── CallbackQQ.vue │ ├── Cart.vue │ ├── Center.vue │ ├── ConfirmOrder.vue │ ├── Details.vue │ ├── Favorite.vue │ ├── Goods.vue │ ├── Home.vue │ ├── Login.vue │ ├── Order.vue │ ├── OrderDetails.vue │ ├── Payment.vue │ ├── Register.vue │ ├── UserAddress.vue │ ├── UserDetails.vue │ ├── UserPass.vue │ └── VaildEmail.vue └── vue.config.js /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | 'extends': [ 7 | 'plugin:vue/essential', 8 | 'eslint:recommended' 9 | ], 10 | rules: { 11 | 'space-before-function-paren': 0, 12 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 13 | // 'no-console': 'off', 14 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', 15 | 'no-unused-vars': 'off', 16 | 'no-empty':'off' 17 | }, 18 | parserOptions: { 19 | parser: 'babel-eslint' 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | dist 4 | docker 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? 22 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "htmlWhitespaceSensitivity": "ignore" 5 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CMall 电子商城 2 | 3 | #### 基于 Vue 开发的小米商城前端界面[CMall](http://cmall.congz.top/#/) 4 | 5 | #### 感谢 [hai-27](https://github.com/hai-27) 的开源 [vue-store](https://github.com/hai-27/vue-store) 项目提供前端页面及框架支持 6 | 7 | #### 前端大部分内容已经重写以及加入了一些新功能 8 | 9 | #### 后端全部用 golang 重写接口,后端接口项目请至 [cmall-go](https://github.com/congz666/cmall-go) 10 | 11 | ## 项目依赖 12 | 13 | - Vue 14 | - Vue-router 15 | - Vuex 16 | - Element-ui 17 | - Axios 18 | 19 | ## 运行 20 | 21 | ``` 22 | git clone https://github.com/congz666/cmall-vue.git 23 | 24 | cd cmall-vue 25 | //运行 26 | npm run serve 27 | ``` 28 | 29 | 项目运行后启动在 8080 端口 30 | 31 | ## 图片展示 32 | 33 | 首页 34 | 35 | ![home](./public/img/home.png) 36 | 37 | 登录 38 | 39 | ![login](./public/img/login.png) 40 | 41 | 注册 42 | 43 | ![register](./public/img/register.png) 44 | 45 | 全部商品 46 | 47 | ![product](./public/img/product.png) 48 | 49 | 商品详情 50 | 51 | ![detail](./public/img/detail.png) 52 | 53 | 收藏 54 | 55 | ![favorite](./public/img/favorite.png) 56 | 57 | 订单 58 | 59 | ![order](./public/img/order.png) 60 | 61 | 购物车 62 | 63 | ![cart](./public/img/cart.png) 64 | 65 | 个人中心 66 | 67 | ![center](./public/img/center.png) 68 | 69 | 个人信息 70 | 71 | ![userdetail](./public/img/userdetail.png) 72 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /dist/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/dist/favicon.ico -------------------------------------------------------------------------------- /dist/fonts/element-icons.535877f5.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/dist/fonts/element-icons.535877f5.woff -------------------------------------------------------------------------------- /dist/fonts/element-icons.732389de.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/dist/fonts/element-icons.732389de.ttf -------------------------------------------------------------------------------- /dist/img/cart-empty.8b316431.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/dist/img/cart-empty.8b316431.png -------------------------------------------------------------------------------- /dist/img/cart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/dist/img/cart.png -------------------------------------------------------------------------------- /dist/img/center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/dist/img/center.png -------------------------------------------------------------------------------- /dist/img/clogo.13a5aaf4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/dist/img/clogo.13a5aaf4.png -------------------------------------------------------------------------------- /dist/img/detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/dist/img/detail.png -------------------------------------------------------------------------------- /dist/img/error.73de3ae8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/dist/img/error.73de3ae8.png -------------------------------------------------------------------------------- /dist/img/favorite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/dist/img/favorite.png -------------------------------------------------------------------------------- /dist/img/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/dist/img/home.png -------------------------------------------------------------------------------- /dist/img/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/dist/img/login.png -------------------------------------------------------------------------------- /dist/img/order.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/dist/img/order.png -------------------------------------------------------------------------------- /dist/img/product.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/dist/img/product.png -------------------------------------------------------------------------------- /dist/img/register.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/dist/img/register.png -------------------------------------------------------------------------------- /dist/img/userdetail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/dist/img/userdetail.png -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | CMall
-------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx:alpine 2 | 3 | COPY ./nginx.conf /etc/nginx/conf.d/default.conf 4 | COPY ./dist /usr/share/nginx/html 5 | -------------------------------------------------------------------------------- /docker/dist/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/docker/dist/favicon.ico -------------------------------------------------------------------------------- /docker/dist/fonts/element-icons.535877f5.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/docker/dist/fonts/element-icons.535877f5.woff -------------------------------------------------------------------------------- /docker/dist/fonts/element-icons.732389de.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/docker/dist/fonts/element-icons.732389de.ttf -------------------------------------------------------------------------------- /docker/dist/img/cart-empty.8b316431.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/docker/dist/img/cart-empty.8b316431.png -------------------------------------------------------------------------------- /docker/dist/img/cart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/docker/dist/img/cart.png -------------------------------------------------------------------------------- /docker/dist/img/center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/docker/dist/img/center.png -------------------------------------------------------------------------------- /docker/dist/img/clogo.13a5aaf4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/docker/dist/img/clogo.13a5aaf4.png -------------------------------------------------------------------------------- /docker/dist/img/detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/docker/dist/img/detail.png -------------------------------------------------------------------------------- /docker/dist/img/error.73de3ae8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/docker/dist/img/error.73de3ae8.png -------------------------------------------------------------------------------- /docker/dist/img/favorite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/docker/dist/img/favorite.png -------------------------------------------------------------------------------- /docker/dist/img/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/docker/dist/img/home.png -------------------------------------------------------------------------------- /docker/dist/img/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/docker/dist/img/login.png -------------------------------------------------------------------------------- /docker/dist/img/order.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/docker/dist/img/order.png -------------------------------------------------------------------------------- /docker/dist/img/product.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/docker/dist/img/product.png -------------------------------------------------------------------------------- /docker/dist/img/register.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/docker/dist/img/register.png -------------------------------------------------------------------------------- /docker/dist/img/userdetail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/docker/dist/img/userdetail.png -------------------------------------------------------------------------------- /docker/dist/index.html: -------------------------------------------------------------------------------- 1 | CMall
-------------------------------------------------------------------------------- /docker/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | nginx: 5 | image: registry.cn-hangzhou.aliyuncs.com/my_giligili/giligii:v1.0.0 6 | restart: always 7 | ports: 8 | - 3001:80 9 | 10 | 11 | server { 12 | listen 80; 13 | server_name www.congz.top; 14 | 15 | location / { 16 | proxy_set_header X-Real-IP $remote_addr; 17 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 18 | proxy_pass http://127.0.0.1:3001; 19 | } 20 | 21 | location /api { 22 | proxy_set_header X-Real-IP $remote_addr; 23 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 24 | proxy_pass http://127.0.0.1:3002; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /docker/nginx.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | location / { 4 | root /usr/share/nginx/html; 5 | index index.html; 6 | } 7 | } 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "store", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "axios": "^0.19.0", 12 | "core-js": "^3.4.3", 13 | "element-ui": "^2.13.0", 14 | "stylus-loader": "^3.0.2", 15 | "vue": "^2.6.10", 16 | "vue-lazyload": "^1.3.3", 17 | "vue-markdown": "^2.2.4", 18 | "vue-router": "^3.1.3", 19 | "vuex": "^3.1.2" 20 | }, 21 | "devDependencies": { 22 | "@vue/cli-plugin-babel": "^4.1.0", 23 | "@vue/cli-plugin-eslint": "^4.1.0", 24 | "@vue/cli-plugin-router": "^4.1.0", 25 | "@vue/cli-plugin-vuex": "^4.1.0", 26 | "@vue/cli-service": "^4.1.0", 27 | "babel-eslint": "^10.0.3", 28 | "eslint": "^5.16.0", 29 | "eslint-plugin-vue": "^5.0.0", 30 | "stylus": "^0.54.8", 31 | "stylus-loader": "^3.0.2", 32 | "vue-template-compiler": "^2.6.10" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/public/favicon.ico -------------------------------------------------------------------------------- /public/img/cart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/public/img/cart.png -------------------------------------------------------------------------------- /public/img/center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/public/img/center.png -------------------------------------------------------------------------------- /public/img/detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/public/img/detail.png -------------------------------------------------------------------------------- /public/img/favorite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/public/img/favorite.png -------------------------------------------------------------------------------- /public/img/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/public/img/home.png -------------------------------------------------------------------------------- /public/img/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/public/img/login.png -------------------------------------------------------------------------------- /public/img/order.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/public/img/order.png -------------------------------------------------------------------------------- /public/img/product.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/public/img/product.png -------------------------------------------------------------------------------- /public/img/register.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/public/img/register.png -------------------------------------------------------------------------------- /public/img/userdetail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/public/img/userdetail.png -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | CMall 9 | 10 | 11 | 17 |
18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 151 | 152 | 258 | 259 | -------------------------------------------------------------------------------- /src/Global.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Descripttion:全局变量 3 | * @Author: congz 4 | * @Date: 2020-06-04 11:22:40 5 | * @LastEditors: congz 6 | * @LastEditTime: 2020-07-17 19:41:54 7 | */ 8 | 9 | exports.install = function(Vue) { 10 | //Vue.prototype.$target = "http://47.115.85.237:3000/"; // 线上后端地址 11 | Vue.prototype.$target = 'http://localhost:3000/' // 本地后端地址 12 | // 封装提示成功的弹出框 13 | Vue.prototype.notifySucceed = function(title) { 14 | this.$notify({ 15 | title: title, 16 | type: 'success', 17 | offset: 100 18 | }) 19 | } 20 | // 封装提示失败的弹出框 21 | Vue.prototype.notifyError = function(title, msg) { 22 | this.$notify.error({ 23 | title: title, 24 | message: msg, 25 | offset: 100 26 | }) 27 | } 28 | // 封装登录超时的操作 29 | Vue.prototype.loginExpired = function(msg) { 30 | //token过期,需要重新登录 31 | this.$notify.error({ 32 | title: '登录已过期,需重新登录', 33 | message: msg 34 | }) 35 | this.$router.push({ 36 | name: 'Login' 37 | }) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/api/addresses/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Descripttion: 3 | * @Author: congz 4 | * @Date: 2020-07-20 11:08:33 5 | * @LastEditors: congz 6 | * @LastEditTime: 2020-08-05 15:32:59 7 | */ 8 | import axios from 'axios' 9 | 10 | // 创建购物车 11 | const postAddress = form => 12 | axios.post('/api/v1/addresses', form).then(res => res.data) 13 | 14 | // 读取购物车 15 | const showAddresses = user_id => 16 | axios.get(`/api/v1/addresses/${user_id}`).then(res => res.data) 17 | 18 | // 更新购物车 19 | const updateAddress = form => 20 | axios.put('/api/v1/addresses', form).then(res => res.data) 21 | 22 | // 删除购物车 23 | const deleteAddress = addressID => 24 | axios 25 | .delete('/api/v1/addresses', { 26 | data: { address_id: addressID } 27 | }) 28 | .then(res => res.data) 29 | 30 | export { postAddress, showAddresses, updateAddress, deleteAddress } 31 | -------------------------------------------------------------------------------- /src/api/carousels/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Descripttion:调用后端轮播图接口的函数 3 | * @Author: congz 4 | * @Date: 2020-06-10 19:03:02 5 | * @LastEditors: congz 6 | * @LastEditTime: 2020-07-17 11:00:28 7 | */ 8 | 9 | import axios from 'axios' 10 | 11 | // 创建轮播图 12 | const postCarousel = form => 13 | axios.post('/api/v1/carousels', form).then(res => res.data) 14 | 15 | // 读取视频列表 16 | const listCarousels = () => axios.get('/api/v1/carousels').then(res => res.data) 17 | 18 | export { postCarousel, listCarousels } 19 | -------------------------------------------------------------------------------- /src/api/carts/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Descripttion:调用后端购物车接口的函数 3 | * @Author: congz 4 | * @Date: 2020-06-14 15:50:08 5 | * @LastEditors: congz 6 | * @LastEditTime: 2020-08-05 15:33:58 7 | */ 8 | 9 | import axios from 'axios' 10 | 11 | // 创建购物车 12 | const postCart = form => axios.post('/api/v1/carts', form).then(res => res.data) 13 | 14 | // 读取购物车 15 | const showCarts = user_id => 16 | axios.get(`/api/v1/carts/${user_id}`).then(res => res.data) 17 | 18 | // 更新购物车 19 | const updateCart = form => 20 | axios.put('/api/v1/carts', form).then(res => res.data) 21 | 22 | // 删除购物车 23 | const deleteCart = form => 24 | axios.delete('/api/v1/carts', { data: form }).then(res => res.data) 25 | 26 | export { postCart, showCarts, updateCart, deleteCart } 27 | -------------------------------------------------------------------------------- /src/api/categories/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Descripttion:调用后端分类接口的函数 3 | * @Author: congz 4 | * @Date: 2020-06-12 22:36:05 5 | * @LastEditors: congz 6 | * @LastEditTime: 2020-08-12 20:56:52 7 | */ 8 | 9 | import axios from 'axios' 10 | 11 | // 创建分类 12 | const postCategory = form => 13 | axios.post('/api/v1/categories', form).then(res => res.data) 14 | 15 | // 读取分类列表 16 | const listCategories = () => 17 | axios.get('/api/v1/categories').then(res => res.data) 18 | 19 | export { postCategory, listCategories } 20 | -------------------------------------------------------------------------------- /src/api/count/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Descripttion:调用后端轮播图接口的函数 3 | * @Author: congz 4 | * @Date: 2020-06-10 19:03:02 5 | * @LastEditors: congz 6 | * @LastEditTime: 2020-08-13 10:11:10 7 | */ 8 | 9 | import axios from 'axios' 10 | 11 | // 获取数量 12 | const showCount = id => axios.get(`/api/v1/counts/${id}`).then(res => res.data) 13 | 14 | export { showCount } 15 | -------------------------------------------------------------------------------- /src/api/favorites/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Descripttion:调用后端收藏接口的函数 3 | * @Author: congz 4 | * @Date: 2020-06-12 10:19:12 5 | * @LastEditors: congz 6 | * @LastEditTime: 2020-08-05 15:34:43 7 | */ 8 | 9 | import axios from 'axios' 10 | 11 | // 创建收藏 12 | const postFavorite = form => 13 | axios.post('/api/v1/favorites', form).then(res => res.data) 14 | 15 | // 读取收藏夹 16 | const showFavorites = (user_id, start, limit) => 17 | axios 18 | .get(`/api/v1/favorites/${user_id}`, { params: { start, limit } }) 19 | .then(res => res.data) 20 | 21 | //删除收藏 22 | const deleteFavorite = form => 23 | axios.delete('/api/v1/favorites', { data: form }).then(res => res.data) 24 | 25 | export { postFavorite, showFavorites, deleteFavorite } 26 | -------------------------------------------------------------------------------- /src/api/img/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Descripttion:调用后端商品图片接口的函数 3 | * @Author: congz 4 | * @Date: 2020-06-10 18:59:36 5 | * @LastEditors: congz 6 | * @LastEditTime: 2020-07-22 19:44:14 7 | */ 8 | 9 | import axios from 'axios' 10 | 11 | //读取商品概述的图片 12 | const showInfoImgs = id => 13 | axios.get(`/api/v1/info-imgs/${id}`).then(res => res.data) 14 | 15 | //读取商品参数的图片 16 | const showParamImgs = id => 17 | axios.get(`/api/v1/param-imgs/${id}`).then(res => res.data) 18 | 19 | export { showInfoImgs, showParamImgs } 20 | -------------------------------------------------------------------------------- /src/api/notice/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Descripttion:调用后端md接口的函数 3 | * @Author: congz 4 | * @Date: 2020-06-12 23:26:38 5 | * @LastEditors: congz 6 | * @LastEditTime: 2020-08-04 11:13:59 7 | */ 8 | 9 | import axios from 'axios' 10 | 11 | // 公告详情 12 | const showNotice = () => axios.get('/api/v1/notices').then(res => res.data) 13 | 14 | export { showNotice } 15 | -------------------------------------------------------------------------------- /src/api/orders/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Descripttion:调用后端订单接口的函数 3 | * @Author: congz 4 | * @Date: 2020-06-14 14:24:12 5 | * @LastEditors: congz 6 | * @LastEditTime: 2020-08-12 20:03:36 7 | */ 8 | 9 | import axios from 'axios' 10 | 11 | // 创建订单 12 | const postOrder = form => 13 | axios.post('/api/v1/orders', form).then(res => res.data) 14 | 15 | // 读取订单 16 | const listOrders = (user_id, type, start, limit) => 17 | axios 18 | .get(`/api/v1/user/${user_id}/orders`, { 19 | params: { type, start, limit } 20 | }) 21 | .then(res => res.data) 22 | 23 | // 读取订单详情 24 | const showOrder = order_id => 25 | axios.get(`/api/v1/orders/${order_id}`).then(res => res.data) 26 | 27 | export { postOrder, listOrders, showOrder } 28 | -------------------------------------------------------------------------------- /src/api/payment/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Descripttion:调用支付接口的函数 3 | * @Author: congz 4 | * @Date: 2020-06-10 19:03:02 5 | * @LastEditors: congz 6 | * @LastEditTime: 2020-08-12 17:51:36 7 | */ 8 | 9 | import axios from 'axios' 10 | 11 | // 初始化支付信息 12 | const initPayment = form => 13 | axios.post('/api/v1/payments', form).then(res => res.data) 14 | 15 | export { initPayment } 16 | -------------------------------------------------------------------------------- /src/api/products/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Descripttion:调用后端商品接口的函数 3 | * @Author: congz 4 | * @Date: 2020-06-10 18:59:36 5 | * @LastEditors: congz 6 | * @LastEditTime: 2020-08-12 20:57:07 7 | */ 8 | 9 | import axios from 'axios' 10 | 11 | // 创建商品 12 | const postProduct = form => 13 | axios.post('/api/v1/products', form).then(res => res.data) 14 | 15 | // 读商品详情 16 | const showProduct = id => 17 | axios.get(`/api/v1/products/${id}`).then(res => res.data) 18 | 19 | // 读取商品列表 20 | const listProducts = (category_id, start, limit) => 21 | axios 22 | .get('/api/v1/products', { params: { category_id, start, limit } }) 23 | .then(res => res.data) 24 | 25 | //读取商品的图片 26 | const showPictures = id => axios.get(`/api/v1/imgs/${id}`).then(res => res.data) 27 | 28 | //搜索商品 29 | const searchProducts = form => 30 | axios.post('/api/v1/searches', form).then(res => res.data) 31 | 32 | // 排行榜详情 33 | const showRanking = () => axios.get('/api/v1/ranking/').then(res => res.data) 34 | 35 | export { 36 | postProduct, 37 | showProduct, 38 | listProducts, 39 | showPictures, 40 | searchProducts, 41 | showRanking 42 | } 43 | -------------------------------------------------------------------------------- /src/api/ranking/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Descripttion:调用后端热门商品&排行榜的函数 3 | * @Author: congz 4 | * @Date: 2020-07-23 14:16:19 5 | * @LastEditors: congz 6 | * @LastEditTime: 2020-07-23 15:16:56 7 | */ 8 | import axios from 'axios' 9 | 10 | // 读取热门家电 11 | const listElecRanking = () => 12 | axios.get('/api/v1/elec-rankings').then(res => res.data) 13 | 14 | // 读取热门配件 15 | const listAcceRanking = () => 16 | axios.get('/api/v1/acce-rankings').then(res => res.data) 17 | 18 | export { listElecRanking, listAcceRanking } 19 | -------------------------------------------------------------------------------- /src/api/upload/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Descripttion:调用后端上传接口的函数 3 | * @Author: congz 4 | * @Date: 2020-07-12 15:44:02 5 | * @LastEditors: congz 6 | * @LastEditTime: 2020-08-05 15:36:07 7 | */ 8 | 9 | import axios from 'axios' 10 | 11 | // 请求图片签名 12 | const UploadAvatar = fileName => 13 | axios.post('/api/v1/avatar', { filename: fileName }).then(res => res.data) 14 | 15 | export { UploadAvatar } 16 | -------------------------------------------------------------------------------- /src/api/users/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Descripttion:调用后端用户接口的函数 3 | * @Author: congz 4 | * @Date: 2020-06-11 09:39:58 5 | * @LastEditors: congz 6 | * @LastEditTime: 2020-08-19 10:16:06 7 | */ 8 | 9 | import axios from 'axios' 10 | 11 | //注册 12 | const postUser = form => 13 | axios.post('/api/v1/user/register', form).then(res => res.data) 14 | //登录 15 | const postLogin = form => 16 | axios.post('/api/v1/user/login', form).then(res => res.data) 17 | //检验token 18 | const checkToken = () => axios.get('/api/v1/ping').then(res => res.data) 19 | //修改信息 20 | const updateUser = form => axios.put('/api/v1/user', form).then(res => res.data) 21 | 22 | //发送邮件 23 | const sendEmail = form => 24 | axios.post('/api/v1/user/sending-email', form).then(res => res.data) 25 | 26 | //绑定或解绑邮箱 27 | const vaildEmail = val => 28 | axios.post('/api/v1/user/vaild-email', { token: val }).then(res => res.data) 29 | 30 | //QQ初始化 31 | const qqInit = () => axios.get('/api/v1/qq/login').then(res => res.data) 32 | //QQ登录 33 | const qqLogin = code => 34 | axios 35 | .post('/api/v1/qq/login', { authorization_code: code }) 36 | .then(res => res.data) 37 | //极验初始化 38 | const geetest = () => axios.get('/api/v1/geetest').then(res => res.data) 39 | 40 | export { 41 | postUser, 42 | postLogin, 43 | checkToken, 44 | updateUser, 45 | sendEmail, 46 | vaildEmail, 47 | qqInit, 48 | qqLogin, 49 | geetest 50 | } 51 | -------------------------------------------------------------------------------- /src/assets/css/index.css: -------------------------------------------------------------------------------- 1 | /* 2 | * @Description: 首页css样式 3 | * @Author: hai-27 4 | * @Date: 2020-02-07 16:23:00 5 | * @LastEditors: hai-27 6 | * @LastEditTime: 2020-02-27 00:46:58 7 | */ 8 | 9 | .main-box { 10 | background-color: #f2f2f2; 11 | padding-bottom: 20px; 12 | } 13 | 14 | .main { 15 | margin: 0 auto; 16 | max-width: 1225px; 17 | } 18 | 19 | /* 轮播图CSS */ 20 | .block { 21 | margin: 0 auto; 22 | max-width: 1225px; 23 | } 24 | 25 | .el-carousel__item:nth-child(2n) { 26 | background-color: #99a9bf; 27 | } 28 | 29 | .el-carousel__item:nth-child(2n + 1) { 30 | background-color: #d3dce6; 31 | } 32 | 33 | /* 轮播图CSS END */ 34 | 35 | .box-hd { 36 | height: 58px; 37 | margin: 20px 0 0 0; 38 | } 39 | 40 | .box-hd .title { 41 | float: left; 42 | font-size: 22px; 43 | font-weight: 200; 44 | line-height: 58px; 45 | color: #333; 46 | } 47 | 48 | .box-hd .more { 49 | float: right; 50 | } 51 | 52 | .box-hd .more a { 53 | font-size: 16px; 54 | line-height: 58px; 55 | color: #424242; 56 | } 57 | 58 | .box-hd .more a:hover { 59 | color: #ff6700; 60 | } 61 | 62 | .box-bd { 63 | height: 615px; 64 | } 65 | 66 | .box-bd .promo-list { 67 | float: left; 68 | height: 615px; 69 | width: 234px; 70 | } 71 | 72 | .box-bd .promo-list li { 73 | z-index: 1; 74 | width: 234px; 75 | height: 300px; 76 | margin-bottom: 14.5px; 77 | -webkit-transition: all 0.2s linear; 78 | transition: all 0.2s linear; 79 | } 80 | 81 | .box-bd .promo-list li:hover { 82 | z-index: 2; 83 | -webkit-box-shadow: 0 15px 30px rgba(0, 0, 0, .1); 84 | box-shadow: 0 15px 30px rgba(0, 0, 0, .1); 85 | -webkit-transform: translate3d(0, -2px, 0); 86 | transform: translate3d(0, -2px, 0); 87 | } 88 | 89 | .box-bd .promo-list li img { 90 | width: 234px; 91 | height: 300px; 92 | } 93 | 94 | .box-bd .promo-list img { 95 | width: 234px; 96 | } 97 | 98 | .box-bd .list { 99 | float: left; 100 | height: 615px; 101 | width: 991px; 102 | } -------------------------------------------------------------------------------- /src/assets/gt.js: -------------------------------------------------------------------------------- 1 | "v0.4.8 Geetest Inc."; 2 | 3 | (function (window) { 4 | "use strict"; 5 | if (typeof window === 'undefined') { 6 | throw new Error('Geetest requires browser environment'); 7 | } 8 | 9 | var document = window.document; 10 | var Math = window.Math; 11 | var head = document.getElementsByTagName("head")[0]; 12 | 13 | function _Object(obj) { 14 | this._obj = obj; 15 | } 16 | 17 | _Object.prototype = { 18 | _each: function (process) { 19 | var _obj = this._obj; 20 | for (var k in _obj) { 21 | if (_obj.hasOwnProperty(k)) { 22 | process(k, _obj[k]); 23 | } 24 | } 25 | return this; 26 | } 27 | }; 28 | 29 | function Config(config) { 30 | var self = this; 31 | new _Object(config)._each(function (key, value) { 32 | self[key] = value; 33 | }); 34 | } 35 | 36 | Config.prototype = { 37 | api_server: 'api.geetest.com', 38 | protocol: 'http://', 39 | typePath: '/gettype.php', 40 | fallback_config: { 41 | slide: { 42 | static_servers: ["static.geetest.com", "dn-staticdown.qbox.me"], 43 | type: 'slide', 44 | slide: '/static/js/geetest.0.0.0.js' 45 | }, 46 | fullpage: { 47 | static_servers: ["static.geetest.com", "dn-staticdown.qbox.me"], 48 | type: 'fullpage', 49 | fullpage: '/static/js/fullpage.0.0.0.js' 50 | } 51 | }, 52 | _get_fallback_config: function () { 53 | var self = this; 54 | if (isString(self.type)) { 55 | return self.fallback_config[self.type]; 56 | } else if (self.new_captcha) { 57 | return self.fallback_config.fullpage; 58 | } else { 59 | return self.fallback_config.slide; 60 | } 61 | }, 62 | _extend: function (obj) { 63 | var self = this; 64 | new _Object(obj)._each(function (key, value) { 65 | self[key] = value; 66 | }) 67 | } 68 | }; 69 | var isNumber = function (value) { 70 | return (typeof value === 'number'); 71 | }; 72 | var isString = function (value) { 73 | return (typeof value === 'string'); 74 | }; 75 | var isBoolean = function (value) { 76 | return (typeof value === 'boolean'); 77 | }; 78 | var isObject = function (value) { 79 | return (typeof value === 'object' && value !== null); 80 | }; 81 | var isFunction = function (value) { 82 | return (typeof value === 'function'); 83 | }; 84 | var MOBILE = /Mobi/i.test(navigator.userAgent); 85 | var pt = MOBILE ? 3 : 0; 86 | 87 | var callbacks = {}; 88 | var status = {}; 89 | 90 | var nowDate = function () { 91 | var date = new Date(); 92 | var year = date.getFullYear(); 93 | var month = date.getMonth() + 1; 94 | var day = date.getDate(); 95 | var hours = date.getHours(); 96 | var minutes = date.getMinutes(); 97 | var seconds = date.getSeconds(); 98 | 99 | if (month >= 1 && month <= 9) { 100 | month = '0' + month; 101 | } 102 | if (day >= 0 && day <= 9) { 103 | day = '0' + day; 104 | } 105 | if (hours >= 0 && hours <= 9) { 106 | hours = '0' + hours; 107 | } 108 | if (minutes >= 0 && minutes <= 9) { 109 | minutes = '0' + minutes; 110 | } 111 | if (seconds >= 0 && seconds <= 9) { 112 | seconds = '0' + seconds; 113 | } 114 | var currentdate = year + '-' + month + '-' + day + " " + hours + ":" + minutes + ":" + seconds; 115 | return currentdate; 116 | } 117 | 118 | var random = function () { 119 | return parseInt(Math.random() * 10000) + (new Date()).valueOf(); 120 | }; 121 | 122 | var loadScript = function (url, cb) { 123 | var script = document.createElement("script"); 124 | script.charset = "UTF-8"; 125 | script.async = true; 126 | 127 | // 对geetest的静态资源添加 crossOrigin 128 | if ( /static\.geetest\.com/g.test(url)) { 129 | script.crossOrigin = "anonymous"; 130 | } 131 | 132 | script.onerror = function () { 133 | cb(true); 134 | }; 135 | var loaded = false; 136 | script.onload = script.onreadystatechange = function () { 137 | if (!loaded && 138 | (!script.readyState || 139 | "loaded" === script.readyState || 140 | "complete" === script.readyState)) { 141 | 142 | loaded = true; 143 | setTimeout(function () { 144 | cb(false); 145 | }, 0); 146 | } 147 | }; 148 | script.src = url; 149 | head.appendChild(script); 150 | }; 151 | 152 | var normalizeDomain = function (domain) { 153 | // special domain: uems.sysu.edu.cn/jwxt/geetest/ 154 | // return domain.replace(/^https?:\/\/|\/.*$/g, ''); uems.sysu.edu.cn 155 | return domain.replace(/^https?:\/\/|\/$/g, ''); // uems.sysu.edu.cn/jwxt/geetest 156 | }; 157 | var normalizePath = function (path) { 158 | path = path.replace(/\/+/g, '/'); 159 | if (path.indexOf('/') !== 0) { 160 | path = '/' + path; 161 | } 162 | return path; 163 | }; 164 | var normalizeQuery = function (query) { 165 | if (!query) { 166 | return ''; 167 | } 168 | var q = '?'; 169 | new _Object(query)._each(function (key, value) { 170 | if (isString(value) || isNumber(value) || isBoolean(value)) { 171 | q = q + encodeURIComponent(key) + '=' + encodeURIComponent(value) + '&'; 172 | } 173 | }); 174 | if (q === '?') { 175 | q = ''; 176 | } 177 | return q.replace(/&$/, ''); 178 | }; 179 | var makeURL = function (protocol, domain, path, query) { 180 | domain = normalizeDomain(domain); 181 | 182 | var url = normalizePath(path) + normalizeQuery(query); 183 | if (domain) { 184 | url = protocol + domain + url; 185 | } 186 | 187 | return url; 188 | }; 189 | 190 | var load = function (config, send, protocol, domains, path, query, cb) { 191 | var tryRequest = function (at) { 192 | 193 | var url = makeURL(protocol, domains[at], path, query); 194 | loadScript(url, function (err) { 195 | if (err) { 196 | if (at >= domains.length - 1) { 197 | cb(true); 198 | // report gettype error 199 | if (send) { 200 | config.error_code = 508; 201 | var url = protocol + domains[at] + path; 202 | reportError(config, url); 203 | } 204 | } else { 205 | tryRequest(at + 1); 206 | } 207 | } else { 208 | cb(false); 209 | } 210 | }); 211 | }; 212 | tryRequest(0); 213 | }; 214 | 215 | 216 | var jsonp = function (domains, path, config, callback) { 217 | if (isObject(config.getLib)) { 218 | config._extend(config.getLib); 219 | callback(config); 220 | return; 221 | } 222 | if (config.offline) { 223 | callback(config._get_fallback_config()); 224 | return; 225 | } 226 | 227 | var cb = "geetest_" + random(); 228 | window[cb] = function (data) { 229 | if (data.status == 'success') { 230 | callback(data.data); 231 | } else if (!data.status) { 232 | callback(data); 233 | } else { 234 | callback(config._get_fallback_config()); 235 | } 236 | window[cb] = undefined; 237 | try { 238 | delete window[cb]; 239 | } catch (e) { 240 | } 241 | }; 242 | load(config, true, config.protocol, domains, path, { 243 | gt: config.gt, 244 | callback: cb 245 | }, function (err) { 246 | if (err) { 247 | callback(config._get_fallback_config()); 248 | } 249 | }); 250 | }; 251 | 252 | var reportError = function (config, url) { 253 | load(config, false, config.protocol, ['monitor.geetest.com'], '/monitor/send', { 254 | time: nowDate(), 255 | captcha_id: config.gt, 256 | challenge: config.challenge, 257 | pt: pt, 258 | exception_url: url, 259 | error_code: config.error_code 260 | }, function (err) {}) 261 | } 262 | 263 | var throwError = function (errorType, config) { 264 | var errors = { 265 | networkError: '网络错误', 266 | gtTypeError: 'gt字段不是字符串类型' 267 | }; 268 | if (typeof config.onError === 'function') { 269 | config.onError(errors[errorType]); 270 | } else { 271 | throw new Error(errors[errorType]); 272 | } 273 | }; 274 | 275 | var detect = function () { 276 | return window.Geetest || document.getElementById("gt_lib"); 277 | }; 278 | 279 | if (detect()) { 280 | status.slide = "loaded"; 281 | } 282 | 283 | window.initGeetest = function (userConfig, callback) { 284 | 285 | var config = new Config(userConfig); 286 | 287 | if (userConfig.https) { 288 | config.protocol = 'https://'; 289 | } else if (!userConfig.protocol) { 290 | config.protocol = window.location.protocol + '//'; 291 | } 292 | 293 | // for KFC 294 | if (userConfig.gt === '050cffef4ae57b5d5e529fea9540b0d1' || 295 | userConfig.gt === '3bd38408ae4af923ed36e13819b14d42') { 296 | config.apiserver = 'yumchina.geetest.com/'; // for old js 297 | config.api_server = 'yumchina.geetest.com'; 298 | } 299 | 300 | if(userConfig.gt){ 301 | window.GeeGT = userConfig.gt 302 | } 303 | 304 | if(userConfig.challenge){ 305 | window.GeeChallenge = userConfig.challenge 306 | } 307 | 308 | if (isObject(userConfig.getType)) { 309 | config._extend(userConfig.getType); 310 | } 311 | jsonp([config.api_server || config.apiserver], config.typePath, config, function (newConfig) { 312 | var type = newConfig.type; 313 | var init = function () { 314 | config._extend(newConfig); 315 | callback(new window.Geetest(config)); 316 | }; 317 | 318 | callbacks[type] = callbacks[type] || []; 319 | var s = status[type] || 'init'; 320 | if (s === 'init') { 321 | status[type] = 'loading'; 322 | 323 | callbacks[type].push(init); 324 | 325 | load(config, true, config.protocol, newConfig.static_servers || newConfig.domains, newConfig[type] || newConfig.path, null, function (err) { 326 | if (err) { 327 | status[type] = 'fail'; 328 | throwError('networkError', config); 329 | } else { 330 | status[type] = 'loaded'; 331 | var cbs = callbacks[type]; 332 | for (var i = 0, len = cbs.length; i < len; i = i + 1) { 333 | var cb = cbs[i]; 334 | if (isFunction(cb)) { 335 | cb(); 336 | } 337 | } 338 | callbacks[type] = []; 339 | } 340 | }); 341 | } else if (s === "loaded") { 342 | init(); 343 | } else if (s === "fail") { 344 | throwError('networkError', config); 345 | } else if (s === "loading") { 346 | callbacks[type].push(init); 347 | } 348 | }); 349 | 350 | }; 351 | 352 | 353 | })(window); 354 | 355 | -------------------------------------------------------------------------------- /src/assets/imgs/QQlogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/src/assets/imgs/QQlogo.png -------------------------------------------------------------------------------- /src/assets/imgs/cart-empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/src/assets/imgs/cart-empty.png -------------------------------------------------------------------------------- /src/assets/imgs/clogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/src/assets/imgs/clogo.png -------------------------------------------------------------------------------- /src/assets/imgs/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/src/assets/imgs/error.png -------------------------------------------------------------------------------- /src/assets/imgs/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/src/assets/imgs/github.png -------------------------------------------------------------------------------- /src/assets/imgs/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/src/assets/imgs/logo.png -------------------------------------------------------------------------------- /src/assets/imgs/placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/src/assets/imgs/placeholder.png -------------------------------------------------------------------------------- /src/assets/imgs/us-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/src/assets/imgs/us-icon.png -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/congz666/cmall-vue/c122bd1d3f56ee7885954b1326029f57b71c8879/src/assets/logo.png -------------------------------------------------------------------------------- /src/components/CenterMenu.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 70 | 79 | -------------------------------------------------------------------------------- /src/components/Error.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | -------------------------------------------------------------------------------- /src/components/MyList.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 39 | 90 | -------------------------------------------------------------------------------- /src/components/MyMarkdown.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 43 | -------------------------------------------------------------------------------- /src/components/MyMenu.vue: -------------------------------------------------------------------------------- 1 | 2 | 18 | 41 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Descripttion:入口文件 3 | * @Author: congz 4 | * @Date: 2020-06-04 11:22:40 5 | * @LastEditors: congz 6 | * @LastEditTime: 2020-08-13 09:19:22 7 | */ 8 | import Vue from 'vue' 9 | import App from './App.vue' 10 | import router from './router' 11 | import store from './store' 12 | import axios from 'axios' 13 | import ElementUI from 'element-ui' 14 | import 'element-ui/lib/theme-chalk/index.css' 15 | import VueLazyload from 'vue-lazyload' 16 | 17 | Vue.use(VueLazyload, { 18 | preLoad: 1.3, 19 | attempt: 1, // 加载图片数量 20 | listenEvents: [ 21 | 'scroll', 22 | 'wheel', 23 | 'mousewheel', 24 | 'resize', 25 | 'animationend', 26 | 'transitionend', 27 | 'touchmove' 28 | ] 29 | }) 30 | 31 | Vue.use(ElementUI) 32 | 33 | Vue.config.productionTip = false 34 | 35 | Vue.prototype.axios = axios 36 | // 导入极验 37 | 38 | // 绑定到原型 39 | Vue.prototype.$initGeet = require('@/assets/gt.js') 40 | 41 | // 全局函数及变量 42 | import Global from './Global' 43 | Vue.use(Global) 44 | 45 | // 全局请求拦截器 46 | axios.interceptors.request.use( 47 | config => { 48 | let token = window.localStorage.getItem('token') 49 | if (token) { 50 | //将token放到请求头发送给服务器,将tokenkey放在请求头中 51 | config.headers.Authorization = token 52 | //也可以这种写法 53 | // config.headers['accessToken'] = Token; 54 | } 55 | return config 56 | }, 57 | error => { 58 | // Do something with request error 59 | return Promise.reject(error) 60 | } 61 | ) 62 | //跳转页面时返回顶部 63 | router.afterEach((to, from, next) => { 64 | window.scrollTo(0, 0) 65 | }) 66 | 67 | // 全局拦截器,在进入需要用户权限的页面前校验是否已经登录 68 | router.beforeResolve((to, from, next) => { 69 | const loginUser = store.state.user.user 70 | // 判断路由是否设置相应校验用户权限 71 | if (to.meta.requireAuth) { 72 | if (!loginUser) { 73 | // 没有登录,转到登录界面 74 | router.push({ 75 | name: 'Login' 76 | }) 77 | if (from.name == null) { 78 | //此时,是在页面没有加载,直接在地址栏输入链接,进入需要登录验证的页面 79 | next('/') 80 | return 81 | } 82 | // 终止导航 83 | next(false) 84 | return 85 | } 86 | } 87 | next() 88 | }) 89 | 90 | // 相对时间过滤器,把时间戳转换成时间 91 | // 格式: 2020-02-25 21:43:23 92 | Vue.filter('dateFormat', cjsj => { 93 | if (cjsj / 10000000000 <= 1) { 94 | cjsj = cjsj * 1000 95 | } 96 | var date = new Date(cjsj) //时间戳为10位需*1000,时间戳为13位的话不需乘1000 97 | var Y = date.getFullYear() + '-' 98 | var M = 99 | (date.getMonth() + 1 < 10 100 | ? '0' + (date.getMonth() + 1) 101 | : date.getMonth() + 1) + '-' 102 | var D = 103 | (date.getDate() < 10 ? '0' + date.getDate() + ' ' : date.getDate()) + ' ' 104 | var h = 105 | date.getHours() < 10 ? '0' + date.getHours() + ':' : date.getHours() + ':' 106 | var m = 107 | date.getMinutes() < 10 108 | ? '0' + date.getMinutes() + ':' 109 | : date.getMinutes() + ':' 110 | var s = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds() 111 | return Y + M + D + h + m + s 112 | }) 113 | 114 | //全局组件 115 | import MyMenu from './components/MyMenu' 116 | Vue.component(MyMenu.name, MyMenu) 117 | import MyList from './components/MyList' 118 | Vue.component(MyList.name, MyList) 119 | 120 | Vue.config.productionTip = false 121 | 122 | new Vue({ 123 | router, 124 | store, 125 | render: h => h(App) 126 | }).$mount('#app') 127 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Descripttion:路由配置 3 | * @Author: congz 4 | * @Date: 2020-06-04 11:22:40 5 | * @LastEditors: congz 6 | * @LastEditTime: 2020-08-18 19:42:54 7 | */ 8 | 9 | import Vue from 'vue' 10 | import Router from 'vue-router' 11 | 12 | Vue.use(Router) 13 | const routes = [ 14 | { 15 | path: '/', 16 | name: 'Home', 17 | component: () => import('../views/Home.vue') 18 | }, 19 | { 20 | path: '/login', 21 | name: 'Login', 22 | component: () => import('../views/Login.vue'), 23 | meta: { 24 | showMenu: false 25 | } 26 | }, 27 | { 28 | path: '/register', 29 | name: 'Register', 30 | component: () => import('../views/Register.vue'), 31 | meta: { 32 | showMenu: false 33 | } 34 | }, 35 | { 36 | path: '/error', 37 | name: 'Error', 38 | component: () => import('../components/Error.vue') 39 | }, 40 | { 41 | path: '/goods', 42 | name: 'Goods', 43 | component: () => import('../views/Goods.vue') 44 | }, 45 | { 46 | path: '/about', 47 | name: 'About', 48 | component: () => import('../views/About.vue') 49 | }, 50 | { 51 | path: '/goods/details', 52 | name: 'Details', 53 | component: () => import('../views/Details.vue') 54 | }, 55 | { 56 | path: '/cart', 57 | name: 'Cart', 58 | component: () => import('../views/Cart.vue'), 59 | meta: { 60 | showMenu: false, 61 | requireAuth: true // 需要验证登录状态 62 | } 63 | }, 64 | { 65 | path: '/favorite', 66 | name: 'Favorite', 67 | component: () => import('../views/Favorite.vue'), 68 | meta: { 69 | requireAuth: true // 需要验证登录状态 70 | } 71 | }, 72 | { 73 | path: '/order', 74 | name: 'Order', 75 | component: () => import('../views/Order.vue'), 76 | meta: { 77 | requireAuth: true // 需要验证登录状态 78 | } 79 | }, 80 | { 81 | path: '/confirmOrder', 82 | name: 'ConfirmOrder', 83 | component: () => import('../views/ConfirmOrder.vue'), 84 | meta: { 85 | showMenu: false, 86 | requireAuth: true // 需要验证登录状态 87 | } 88 | }, 89 | { 90 | path: '/order/details', 91 | name: 'OrderDetails', 92 | component: () => import('../views/OrderDetails.vue'), 93 | meta: { 94 | requireAuth: true // 需要验证登录状态 95 | } 96 | }, 97 | { 98 | path: '/center', 99 | name: 'Center', 100 | component: () => import('../views/Center.vue'), 101 | meta: { 102 | requireAuth: true // 需要验证登录状态 103 | } 104 | }, 105 | { 106 | path: '/user/details', 107 | name: 'UserDetails', 108 | component: () => import('../views/UserDetails.vue'), 109 | meta: { 110 | requireAuth: true // 需要验证登录状态 111 | } 112 | }, 113 | { 114 | path: '/user/pass', 115 | name: 'UserPass', 116 | component: () => import('../views/UserPass.vue'), 117 | meta: { 118 | requireAuth: true // 需要验证登录状态 119 | } 120 | }, 121 | { 122 | path: '/user/address', 123 | name: 'UserAddress', 124 | component: () => import('../views/UserAddress.vue'), 125 | meta: { 126 | requireAuth: true // 需要验证登录状态 127 | } 128 | }, 129 | { 130 | path: `/vaild/email/:token`, 131 | name: 'VaildEmail', 132 | component: () => import('../views/VaildEmail.vue'), 133 | meta: { 134 | showMenu: false 135 | } 136 | }, 137 | { 138 | path: '/payment', 139 | name: 'Payment', 140 | component: () => import('../views/Payment.vue'), 141 | meta: { 142 | requireAuth: true // 需要验证登录状态 143 | } 144 | }, 145 | { 146 | path: '/callback/qq', 147 | name: 'CallbackQQ', 148 | component: () => import('../views/CallbackQQ.vue'), 149 | meta: { 150 | showMenu: false 151 | } 152 | } 153 | ] 154 | 155 | const router = new Router({ 156 | // base: '/dist', 157 | // mode: 'history', 158 | routes 159 | }) 160 | 161 | /* 由于Vue-router在3.1之后把$router.push()方法改为了Promise。所以假如没有回调函数,错误信息就会交给全局的路由错误处理。 162 | vue-router先报了一个Uncaught(in promise)的错误(因为push没加回调) ,然后再点击路由的时候才会触发NavigationDuplicated的错误(路由出现的错误,全局错误处理打印了出来)。*/ 163 | // 禁止全局路由错误处理打印 164 | const originalPush = Router.prototype.push 165 | Router.prototype.push = function push(location, onResolve, onReject) { 166 | if (onResolve || onReject) 167 | return originalPush.call(this, location, onResolve, onReject) 168 | return originalPush.call(this, location).catch(err => err) 169 | } 170 | 171 | export default router 172 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Descripttion:Vuex入口 3 | * @Author: congz 4 | * @Date: 2020-06-04 11:22:40 5 | * @LastEditors: congz 6 | * @LastEditTime: 2020-07-17 10:44:04 7 | */ 8 | 9 | import Vue from 'vue' 10 | import Vuex from 'vuex' 11 | 12 | import user from './modules/user' 13 | import shoppingCart from './modules/shoppingCart' 14 | 15 | Vue.use(Vuex) 16 | 17 | export default new Vuex.Store({ 18 | strict: true, 19 | modules: { 20 | user, 21 | shoppingCart 22 | } 23 | }) 24 | -------------------------------------------------------------------------------- /src/store/modules/shoppingCart.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Descripttion:购物车状态模块 3 | * @Author: congz 4 | * @Date: 2020-06-04 11:22:40 5 | * @LastEditors: congz 6 | * @LastEditTime: 2020-07-17 10:43:39 7 | */ 8 | 9 | export default { 10 | state: { 11 | shoppingCart: [] 12 | }, 13 | getters: { 14 | getShoppingCart(state) { 15 | // 获取购物车状态 16 | return state.shoppingCart 17 | }, 18 | getNum(state) { 19 | // 购物车商品总数量 20 | let totalNum = 0 21 | for (let i = 0; i < state.shoppingCart.length; i++) { 22 | const temp = state.shoppingCart[i] 23 | totalNum += temp.num 24 | } 25 | return totalNum 26 | }, 27 | getIsAllCheck(state) { 28 | // 判断是否全选 29 | let isAllCheck = true 30 | for (let i = 0; i < state.shoppingCart.length; i++) { 31 | const temp = state.shoppingCart[i] 32 | // 只要有一个商品没有勾选立即return false; 33 | if (!temp.check) { 34 | isAllCheck = false 35 | return isAllCheck 36 | } 37 | } 38 | return isAllCheck 39 | }, 40 | getCheckGoods(state) { 41 | // 获取勾选的商品信息 42 | // 用于确认订单页面 43 | let checkGoods = [] 44 | for (let i = 0; i < state.shoppingCart.length; i++) { 45 | const temp = state.shoppingCart[i] 46 | if (temp.check) { 47 | checkGoods.push(temp) 48 | } 49 | } 50 | return checkGoods 51 | }, 52 | getCheckNum(state) { 53 | // 获取购物车勾选的商品数量 54 | let totalNum = 0 55 | for (let i = 0; i < state.shoppingCart.length; i++) { 56 | const temp = state.shoppingCart[i] 57 | if (temp.check) { 58 | totalNum += temp.num 59 | } 60 | } 61 | return totalNum 62 | }, 63 | getTotalPrice(state) { 64 | // 购物车勾选的商品总价格 65 | let totalPrice = 0 66 | for (let i = 0; i < state.shoppingCart.length; i++) { 67 | const temp = state.shoppingCart[i] 68 | if (temp.check) { 69 | totalPrice += temp.discount_price * temp.num 70 | } 71 | } 72 | return totalPrice 73 | } 74 | }, 75 | mutations: { 76 | setShoppingCart(state, data) { 77 | // 设置购物车状态 78 | state.shoppingCart = data 79 | }, 80 | unshiftShoppingCart(state, data) { 81 | // 添加购物车 82 | // 用于在商品详情页点击添加购物车,后台添加成功后,更新vuex状态 83 | state.shoppingCart.unshift(data) 84 | }, 85 | updateShoppingCart(state, payload) { 86 | // 更新购物车 87 | // 可更新商品数量和是否勾选 88 | // 用于购物车点击勾选及加减商品数量 89 | if (payload.prop == 'num') { 90 | // 判断效果的商品数量是否大于限购数量或小于1 91 | if (state.shoppingCart[payload.key].maxNum < payload.val) { 92 | return 93 | } 94 | if (payload.val < 1) { 95 | return 96 | } 97 | } 98 | // 根据商品在购物车的数组的索引和属性更改 99 | state.shoppingCart[payload.key][payload.prop] = payload.val 100 | }, 101 | addShoppingCartNum(state, productID) { 102 | // 增加购物车商品数量 103 | // 用于在商品详情页点击添加购物车,后台返回002,“该商品已在购物车,数量 +1”,更新vuex的商品数量 104 | for (let i = 0; i < state.shoppingCart.length; i++) { 105 | const temp = state.shoppingCart[i] 106 | if (temp.productID == productID) { 107 | if (temp.num < temp.maxNum) { 108 | temp.num++ 109 | } 110 | } 111 | } 112 | }, 113 | deleteShoppingCart(state, id) { 114 | // 根据购物车id删除购物车商品 115 | for (let i = 0; i < state.shoppingCart.length; i++) { 116 | const temp = state.shoppingCart[i] 117 | if (temp.product_id == id) { 118 | state.shoppingCart.splice(i, 1) 119 | } 120 | } 121 | }, 122 | checkAll(state, data) { 123 | // 点击全选按钮,更改每个商品的勾选状态 124 | for (let i = 0; i < state.shoppingCart.length; i++) { 125 | state.shoppingCart[i].check = data 126 | } 127 | } 128 | }, 129 | actions: { 130 | setShoppingCart({ commit }, data) { 131 | commit('setShoppingCart', data) 132 | }, 133 | unshiftShoppingCart({ commit }, data) { 134 | commit('unshiftShoppingCart', data) 135 | }, 136 | updateShoppingCart({ commit }, payload) { 137 | commit('updateShoppingCart', payload) 138 | }, 139 | addShoppingCartNum({ commit }, productID) { 140 | commit('addShoppingCartNum', productID) 141 | }, 142 | deleteShoppingCart({ commit }, id) { 143 | commit('deleteShoppingCart', id) 144 | }, 145 | checkAll({ commit }, data) { 146 | commit('checkAll', data) 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /src/store/modules/user.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Descripttion:用户登录状态模块 3 | * @Author: congz 4 | * @Date: 2020-06-04 11:22:40 5 | * @LastEditors: congz 6 | * @LastEditTime: 2020-08-06 10:18:08 7 | */ 8 | 9 | export default { 10 | state: { 11 | user: '' // 登录的用户 12 | }, 13 | getters: { 14 | getUser(state) { 15 | return state.user 16 | } 17 | }, 18 | mutations: { 19 | setUser(state, data) { 20 | state.user = data 21 | } 22 | }, 23 | actions: { 24 | setUser({ commit }, data) { 25 | commit('setUser', data) 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/views/About.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 28 | 42 | -------------------------------------------------------------------------------- /src/views/CallbackQQ.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 19 | 78 | -------------------------------------------------------------------------------- /src/views/Cart.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 154 | 243 | -------------------------------------------------------------------------------- /src/views/Center.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 135 | 242 | -------------------------------------------------------------------------------- /src/views/Details.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 123 | 274 | 477 | -------------------------------------------------------------------------------- /src/views/Favorite.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 51 | 98 | -------------------------------------------------------------------------------- /src/views/Goods.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 60 | 244 | 245 | -------------------------------------------------------------------------------- /src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 122 | 282 | -------------------------------------------------------------------------------- /src/views/Login.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 53 | 54 | 169 | 170 | 218 | -------------------------------------------------------------------------------- /src/views/Order.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 128 | 191 | -------------------------------------------------------------------------------- /src/views/OrderDetails.vue: -------------------------------------------------------------------------------- 1 | 8 | 146 | 193 | -------------------------------------------------------------------------------- /src/views/Payment.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 68 | 152 | 153 | 234 | -------------------------------------------------------------------------------- /src/views/Register.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 43 | 44 | 168 | 169 | 193 | -------------------------------------------------------------------------------- /src/views/UserAddress.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 104 | 230 | -------------------------------------------------------------------------------- /src/views/UserDetails.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 56 | 172 | -------------------------------------------------------------------------------- /src/views/UserPass.vue: -------------------------------------------------------------------------------- 1 | 8 | 55 | 148 | -------------------------------------------------------------------------------- /src/views/VaildEmail.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 16 | 73 | 74 | 86 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Description: 配置文件 3 | * @Author: hai-27 4 | * @Date: 2020-02-07 16:23:00 5 | * @LastEditors: congz 6 | * @LastEditTime: 2020-07-22 21:39:29 7 | */ 8 | module.exports = { 9 | pwa: { 10 | iconPaths: { 11 | favicon32: 'favicon.ico', 12 | favicon16: 'favicon.ico', 13 | appleTouchIcon: 'favicon.ico', 14 | maskIcon: 'favicon.ico', 15 | msTileImage: 'favicon.ico' 16 | } 17 | }, 18 | publicPath: './', 19 | devServer: { 20 | open: true, 21 | proxy: { 22 | '^/api': { 23 | target: 'http://localhost:3000', 24 | ws: true, 25 | changeOrigin: true 26 | } 27 | } 28 | } 29 | } 30 | --------------------------------------------------------------------------------