├── .gitignore ├── README.md ├── babel.config.js ├── package.json ├── preview ├── cart.png ├── category.png ├── eat.png ├── home.png └── mine.png ├── public ├── icon.png └── index.html ├── src ├── App.vue ├── assets │ ├── img │ │ ├── ali.png │ │ ├── avatar.jpg │ │ ├── default_grey.jpg │ │ ├── empty_address.png │ │ ├── empty_cart.png │ │ ├── empty_order.jpg │ │ ├── hb.png │ │ ├── home_bg.png │ │ ├── icon_loading.png │ │ ├── top.png │ │ ├── vip.png │ │ └── wx.png │ └── js │ │ └── area.js ├── components │ ├── bscroll.vue │ ├── dropBall.vue │ ├── loading.vue │ └── scrollTop.vue ├── http.js ├── main.js ├── plugins │ ├── format.js │ ├── global.js │ ├── index.js │ └── rem.js ├── router.js ├── store │ ├── actions.js │ ├── index.js │ ├── mutation-types.js │ ├── mutations.js │ └── state.js └── views │ ├── cart │ ├── index.vue │ └── order │ │ ├── components │ │ └── timelist.vue │ │ ├── goodsList.vue │ │ └── orderFill.vue │ ├── category │ └── index.vue │ ├── detail │ └── index.vue │ ├── eat │ ├── collection │ │ └── collection.vue │ └── index.vue │ ├── home │ ├── components │ │ ├── header.vue │ │ ├── limit.vue │ │ └── special.vue │ ├── index.vue │ └── myMap.vue │ ├── layout.vue │ ├── login │ └── index.vue │ └── mine │ ├── address │ ├── addAddress.vue │ ├── editAddress.vue │ └── myAddress.vue │ ├── coupon.vue │ ├── index.vue │ ├── order.vue │ ├── profile │ ├── changeName.vue │ └── profile.vue │ └── vip │ ├── payVip.vue │ └── vip.vue ├── vue.config.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 移动端叮咚买菜 vue + vant 2 | 3 | ### 免责说明 4 | 本项目仅限技术交流,不建议商业使用,产生的一切侵权著作法律后果,与本作者无关。 5 | 6 | ### 预览 7 |
8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | ### 安装依赖(推荐yarn) 16 | ``` 17 | yarn install 18 | ``` 19 | 20 | ### 本地运行 21 | ``` 22 | yarn serve 23 | ``` 24 | 25 | ### 本地打包 26 | ``` 27 | yarn build 28 | ``` 29 | 30 | 31 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ], 5 | plugins: [ 6 | ['import', { 7 | libraryName: 'vant', 8 | libraryDirectory: 'es', 9 | style: true 10 | }, 'vant'] 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ding-buy", 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 | "better-scroll": "^1.15.2", 13 | "core-js": "^3.3.2", 14 | "fastclick": "^1.0.6", 15 | "reset-css": "^5.0.1", 16 | "vant": "^2.2.13", 17 | "vue": "^2.6.10", 18 | "vue-amap": "^0.5.10", 19 | "vue-router": "^3.1.3", 20 | "vue-waterfall2": "^1.9.5", 21 | "vuex": "^3.1.2" 22 | }, 23 | "devDependencies": { 24 | "@vue/cli-plugin-babel": "^4.0.0", 25 | "@vue/cli-plugin-eslint": "^4.0.0", 26 | "@vue/cli-service": "^4.0.0", 27 | "babel-eslint": "^10.0.3", 28 | "babel-plugin-import": "^1.12.2", 29 | "eslint": "^5.16.0", 30 | "eslint-plugin-vue": "^5.0.0", 31 | "node-sass": "^4.13.0", 32 | "sass-loader": "^8.0.0", 33 | "vue-template-compiler": "^2.6.10" 34 | }, 35 | "eslintConfig": { 36 | "root": true, 37 | "env": { 38 | "node": true 39 | }, 40 | "extends": [ 41 | "plugin:vue/essential", 42 | "eslint:recommended" 43 | ], 44 | "rules": {}, 45 | "parserOptions": { 46 | "parser": "babel-eslint" 47 | } 48 | }, 49 | "postcss": { 50 | "plugins": { 51 | "autoprefixer": {} 52 | } 53 | }, 54 | "browserslist": [ 55 | "> 1%", 56 | "last 2 versions" 57 | ] 58 | } 59 | -------------------------------------------------------------------------------- /preview/cart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZedCoding/ding-buy/3449edfd7a41deea67c46ffb538f662c1782cbca/preview/cart.png -------------------------------------------------------------------------------- /preview/category.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZedCoding/ding-buy/3449edfd7a41deea67c46ffb538f662c1782cbca/preview/category.png -------------------------------------------------------------------------------- /preview/eat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZedCoding/ding-buy/3449edfd7a41deea67c46ffb538f662c1782cbca/preview/eat.png -------------------------------------------------------------------------------- /preview/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZedCoding/ding-buy/3449edfd7a41deea67c46ffb538f662c1782cbca/preview/home.png -------------------------------------------------------------------------------- /preview/mine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZedCoding/ding-buy/3449edfd7a41deea67c46ffb538f662c1782cbca/preview/mine.png -------------------------------------------------------------------------------- /public/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZedCoding/ding-buy/3449edfd7a41deea67c46ffb538f662c1782cbca/public/icon.png -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 叮咚买菜 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 22 | -------------------------------------------------------------------------------- /src/assets/img/ali.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZedCoding/ding-buy/3449edfd7a41deea67c46ffb538f662c1782cbca/src/assets/img/ali.png -------------------------------------------------------------------------------- /src/assets/img/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZedCoding/ding-buy/3449edfd7a41deea67c46ffb538f662c1782cbca/src/assets/img/avatar.jpg -------------------------------------------------------------------------------- /src/assets/img/default_grey.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZedCoding/ding-buy/3449edfd7a41deea67c46ffb538f662c1782cbca/src/assets/img/default_grey.jpg -------------------------------------------------------------------------------- /src/assets/img/empty_address.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZedCoding/ding-buy/3449edfd7a41deea67c46ffb538f662c1782cbca/src/assets/img/empty_address.png -------------------------------------------------------------------------------- /src/assets/img/empty_cart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZedCoding/ding-buy/3449edfd7a41deea67c46ffb538f662c1782cbca/src/assets/img/empty_cart.png -------------------------------------------------------------------------------- /src/assets/img/empty_order.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZedCoding/ding-buy/3449edfd7a41deea67c46ffb538f662c1782cbca/src/assets/img/empty_order.jpg -------------------------------------------------------------------------------- /src/assets/img/hb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZedCoding/ding-buy/3449edfd7a41deea67c46ffb538f662c1782cbca/src/assets/img/hb.png -------------------------------------------------------------------------------- /src/assets/img/home_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZedCoding/ding-buy/3449edfd7a41deea67c46ffb538f662c1782cbca/src/assets/img/home_bg.png -------------------------------------------------------------------------------- /src/assets/img/icon_loading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZedCoding/ding-buy/3449edfd7a41deea67c46ffb538f662c1782cbca/src/assets/img/icon_loading.png -------------------------------------------------------------------------------- /src/assets/img/top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZedCoding/ding-buy/3449edfd7a41deea67c46ffb538f662c1782cbca/src/assets/img/top.png -------------------------------------------------------------------------------- /src/assets/img/vip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZedCoding/ding-buy/3449edfd7a41deea67c46ffb538f662c1782cbca/src/assets/img/vip.png -------------------------------------------------------------------------------- /src/assets/img/wx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZedCoding/ding-buy/3449edfd7a41deea67c46ffb538f662c1782cbca/src/assets/img/wx.png -------------------------------------------------------------------------------- /src/components/bscroll.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /src/components/dropBall.vue: -------------------------------------------------------------------------------- 1 | 16 | 55 | -------------------------------------------------------------------------------- /src/components/loading.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 34 | 35 | 87 | -------------------------------------------------------------------------------- /src/components/scrollTop.vue: -------------------------------------------------------------------------------- 1 | 6 | 43 | -------------------------------------------------------------------------------- /src/http.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | import router from './router' 3 | import { Notify } from 'vant'; 4 | 5 | const http = axios.create({ 6 | baseURL: 'https://mock.cangdu.org/mock/5d940466d360e8289c6a8eb7', 7 | timeout: 60000 // 请求超时时间, 8 | }) 9 | 10 | http.interceptors.request.use(config => { 11 | config.url += '?t=' + new Date().getTime(); // 加时间戳防止请求缓存 12 | return { ...config } 13 | }, error => { 14 | return Promise.reject(error) 15 | }) 16 | 17 | http.interceptors.response.use(response => { 18 | return response 19 | }, error => { 20 | if (error && error.response) { 21 | switch (error.response.status) { 22 | case 400: case 500: 23 | error.message = error.response.data.Message; 24 | break; 25 | case 401: 26 | error.message = '无效授权,请重新登录(401)'; 27 | router.push({ path: '/login' }) 28 | break; 29 | case 404: 30 | error.message = "请求未找到(404)"; 31 | break; 32 | default: 33 | error.message = "连接出错啦~" 34 | break; 35 | } 36 | } else { 37 | error.message = "连击服务器失败" 38 | } 39 | Notify({ type: 'danger', message: error.message, duration: 800 }); 40 | return new Promise(() => { }) // pending的promise,中止promise链 41 | }) 42 | 43 | export default http 44 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App'; 3 | import router from './router'; 4 | import store from './store' 5 | import "reset-css"; 6 | import waterfall from "vue-waterfall2"; 7 | import { rem, format } from './plugins'; 8 | import FastClick from 'fastclick'; 9 | import { 10 | Toast, 11 | Tabbar, 12 | TabbarItem, 13 | Icon, 14 | Button, 15 | Swipe, 16 | SwipeItem, 17 | Search, 18 | Divider, 19 | CountDown, 20 | Tab, 21 | Tabs, 22 | Loading, 23 | Lazyload, 24 | Cell, 25 | CellGroup, 26 | Grid, 27 | GridItem, 28 | Tag, 29 | NavBar, 30 | ActionSheet, 31 | DatetimePicker, 32 | Field, 33 | AddressList, 34 | AddressEdit, 35 | Dialog, 36 | CouponCell, 37 | CouponList, 38 | RadioGroup, 39 | Radio, 40 | Checkbox, 41 | Stepper, 42 | SubmitBar, 43 | ContactCard, 44 | ContactList, 45 | ContactEdit, 46 | Popup, 47 | Switch, 48 | Sticky, 49 | SwipeCell 50 | } from 'vant'; 51 | 52 | Vue.use(Toast) 53 | .use(Tabbar) 54 | .use(TabbarItem) 55 | .use(Icon) 56 | .use(Button) 57 | .use(Swipe) 58 | .use(SwipeItem) 59 | .use(Search) 60 | .use(Divider) 61 | .use(CountDown) 62 | .use(Tab) 63 | .use(Tabs) 64 | .use(Loading) 65 | .use(Lazyload) 66 | .use(Cell) 67 | .use(CellGroup) 68 | .use(Grid) 69 | .use(GridItem) 70 | .use(Tag) 71 | .use(NavBar) 72 | .use(ActionSheet) 73 | .use(DatetimePicker) 74 | .use(Field) 75 | .use(AddressList) 76 | .use(AddressEdit) 77 | .use(Dialog) 78 | .use(CouponCell) 79 | .use(CouponList) 80 | .use(RadioGroup) 81 | .use(Radio) 82 | .use(Checkbox) 83 | .use(Stepper) 84 | .use(SubmitBar) 85 | .use(ContactCard) 86 | .use(ContactList) 87 | .use(ContactEdit) 88 | .use(Popup) 89 | .use(Switch) 90 | .use(Sticky) 91 | .use(SwipeCell) 92 | .use(waterfall) 93 | .use(format) 94 | .use(rem) 95 | 96 | // 全局设置toast属性duration 97 | Toast.setDefaultOptions({ duration: 1500 }); 98 | 99 | import http from './http' 100 | Vue.prototype.$http = http; 101 | 102 | import loading from '@/components/loading'; 103 | import scrollTop from '@/components/scrollTop'; 104 | import dropBall from '@/components/dropBall'; 105 | Vue.component('loading', loading); 106 | Vue.component('scrollTop', scrollTop); 107 | Vue.component('dropBall', dropBall); 108 | 109 | // 解决移动端点击延迟200ms的问题 110 | if ('addEventListener' in document) { 111 | document.addEventListener('DOMContentLoaded', function () { 112 | FastClick.attach(document.body); 113 | }, false); 114 | } 115 | 116 | Vue.prototype.onClickLeft = () => { 117 | router.back(); 118 | } 119 | 120 | Vue.config.productionTip = false 121 | 122 | new Vue({ 123 | router, 124 | store, 125 | render: h => h(App), 126 | }).$mount('#app') 127 | -------------------------------------------------------------------------------- /src/plugins/format.js: -------------------------------------------------------------------------------- 1 | export default { 2 | install(Vue) { 3 | Vue.prototype.format = function (cur, format) { 4 | let date = new Date(cur); 5 | let args = { 6 | "M+": date.getMonth() + 1, 7 | "d+": date.getDate(), 8 | "h+": date.getHours(), 9 | "m+": date.getMinutes(), 10 | "s+": date.getSeconds(), 11 | "q+": Math.floor((date.getMonth() + 3) / 3), //quarter 12 | "S": date.getMilliseconds() 13 | }; 14 | if (/(y+)/.test(format)) 15 | format = format.replace( 16 | RegExp.$1, 17 | (date.getFullYear() + "").substr(4 - RegExp.$1.length) 18 | ); 19 | for (let i in args) { 20 | let n = args[i]; 21 | if (new RegExp("(" + i + ")").test(format)) 22 | format = format.replace( 23 | RegExp.$1, 24 | RegExp.$1.length == 1 ? n : ("00" + n).substr(("" + n).length) 25 | ); 26 | } 27 | return format; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/plugins/global.js: -------------------------------------------------------------------------------- 1 | // 本地储存 2 | export const setLocalStore = (key, value) => { 3 | if (!key) return; 4 | window.localStorage.setItem(key, JSON.stringify(value)); 5 | } 6 | 7 | export const getLocalStore = (key) => { 8 | if (!key) return; 9 | let temp = window.localStorage.getItem(key); 10 | return JSON.parse(temp); 11 | } 12 | 13 | export const removeLocalStore = (key) => { 14 | if (!key) return; 15 | window.localStorage.removeItem(key); 16 | } -------------------------------------------------------------------------------- /src/plugins/index.js: -------------------------------------------------------------------------------- 1 | import rem from './rem' 2 | import format from './format' 3 | 4 | export { rem, format } -------------------------------------------------------------------------------- /src/plugins/rem.js: -------------------------------------------------------------------------------- 1 | (function (doc, win) { 2 | var docEl = doc.documentElement, 3 | resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize', 4 | recalc = function () { 5 | var clientWidth = docEl.clientWidth; 6 | if (!clientWidth) return; 7 | docEl.style.fontSize = 15 * (clientWidth / 375) + 'px'; 8 | }; 9 | if (!doc.addEventListener) return; 10 | win.addEventListener(resizeEvt, recalc, false); 11 | doc.addEventListener('DOMContentLoaded', recalc, false); 12 | })(document, window); -------------------------------------------------------------------------------- /src/router.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | Vue.use(Router) 4 | 5 | const Home = () => import('@/views/home'); 6 | const Category = () => import('@/views/category'); 7 | const Eat = () => import('@/views/eat'); 8 | const Cart = () => import('@/views/cart'); 9 | const Mine = () => import('@/views/mine'); 10 | 11 | // 解决vue-router导航重复 12 | const originalPush = Router.prototype.push; 13 | Router.prototype.push = function push(location) { 14 | return originalPush.call(this, location).catch(err => err); 15 | }; 16 | 17 | const router = new Router({ 18 | mode: "history", 19 | routes: [ 20 | { 21 | path: '/', 22 | redirect: "/dashboard/home" 23 | }, 24 | { 25 | path: "/login", 26 | name: "Login", 27 | component: () => import('@/views/login') 28 | }, 29 | { 30 | path: "/dashboard", 31 | component: () => import('@/views/layout'), 32 | children: [ 33 | { 34 | path: 'home', 35 | name: "Home", 36 | component: Home, 37 | meta: { 38 | keepAlive: true 39 | } 40 | }, 41 | { 42 | path: "category", 43 | name: "Category", 44 | component: Category, 45 | }, 46 | { 47 | path: "eat", 48 | name: "Eat", 49 | component: Eat, 50 | meta: { 51 | keepAlive: true 52 | } 53 | }, 54 | { 55 | path: 'cart', 56 | name: "Cart", 57 | component: Cart 58 | }, 59 | { 60 | path: "mine", 61 | name: "Mine", 62 | component: Mine, 63 | meta: { 64 | keepAlive: true 65 | } 66 | } 67 | ] 68 | }, 69 | { 70 | path: "/dashboard/home/map", 71 | name: "MyMap", 72 | component: () => import('@/views/home/myMap') 73 | }, 74 | { 75 | path: "/mine/profile", 76 | name: "Profile", 77 | component: () => import('@/views/mine/profile/profile') 78 | }, 79 | { 80 | path: "/profile/changeName", 81 | name: "ChangeName", 82 | component: () => import('@/views/mine/profile/changeName') 83 | }, 84 | { 85 | path: "/mine/order", 86 | name: "Order", 87 | component: () => import('@/views/mine/order') 88 | }, 89 | { 90 | path: "/mine/coupons", 91 | name: "Coupon", 92 | component: () => import('@/views/mine/coupon') 93 | }, 94 | { 95 | path: "/mine/myaddress", 96 | name: "Address", 97 | component: () => import('@/views/mine/address/myAddress') 98 | }, 99 | { 100 | path: "/mine/addaddress", 101 | name: "AddAddress", 102 | component: () => import('@/views/mine/address/addAddress') 103 | }, 104 | { 105 | path: "/mine/editaddress", 106 | name: "EditAddress", 107 | component: () => import('@/views/mine/address/editAddress') 108 | }, 109 | { 110 | path: "/mine/myVip", 111 | name: "Vip", 112 | component: () => import('@/views/mine/vip/vip'), 113 | meta: { 114 | keepAlive: true 115 | } 116 | }, 117 | { 118 | path: "/mine/myVip/pay", 119 | name: "PayVip", 120 | component: () => import('@/views/mine/vip/payVip') 121 | }, 122 | { 123 | path: "/orderfill", 124 | name: "OrderFill", 125 | component: () => import('@/views/cart/order/orderFill') 126 | }, 127 | { 128 | path: "/goodslist", 129 | name: "GoodsList", 130 | component: () => import('@/views/cart/order/goodsList') 131 | }, 132 | { 133 | path: "/collection", 134 | name: "Collection", 135 | component: () => import('@/views/eat/collection/collection') 136 | } 137 | 138 | ] 139 | }) 140 | 141 | router.beforeEach((to, from, next) => { 142 | // const { token } = store.state; 143 | // if (!token && to.path !== "/login") { 144 | // next({ 145 | // path: "/login" 146 | // }); 147 | // } 148 | 149 | next(); 150 | }); 151 | 152 | 153 | 154 | export default router; -------------------------------------------------------------------------------- /src/store/actions.js: -------------------------------------------------------------------------------- 1 | import { USER_INFO } from './mutation-types' 2 | export default { 3 | // 同步用户信息 4 | syncUserInfo({ commit }, userInfo) { 5 | commit(USER_INFO, userInfo) 6 | } 7 | } -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import state from './state' 4 | import actions from './actions' 5 | import mutations from './mutations' 6 | 7 | Vue.use(Vuex) 8 | 9 | export default new Vuex.Store({ 10 | state, 11 | actions, 12 | mutations 13 | }) -------------------------------------------------------------------------------- /src/store/mutation-types.js: -------------------------------------------------------------------------------- 1 | // 用户信息 2 | export const USER_INFO = 'USER_INFO'; 3 | // 修改用户名 4 | export const CHANGE_USER_NAME = "CHANGE_USER_NAME"; 5 | // 修改性别 6 | export const CHANGE_SEX = "CHANGE_SEX"; 7 | // 修改生日 8 | export const CHANGE_BIRTHDAY = "CHANGE_BIRTHDAY"; 9 | // 增加地址 10 | export const ADD_ADDRESS = "ADD_ADDRESS"; 11 | // 修改地址 12 | export const EDIT_ADDRESS = "EDIT_ADDRESS"; 13 | // 删除地址 14 | export const REMOVE_ADDRESS = "REMOVE_ADDRESS"; 15 | 16 | // 加入购物车 17 | export const ADD_GOODS = "ADD_GOODS"; 18 | // 删除商品 19 | export const REMOVE_GOODS = "REMOVE_GOODS"; 20 | // 清空购物车 21 | export const CLEAR_CART = "CLEAR_CART"; 22 | // 全选/不选商品 23 | export const SELECT_ALL_GOODS = "SELECT_ALL_GOODS"; 24 | 25 | // 退出登录 26 | export const LOG_OUT = 'LOG_OUT'; -------------------------------------------------------------------------------- /src/store/mutations.js: -------------------------------------------------------------------------------- 1 | import { 2 | USER_INFO, 3 | CHANGE_USER_NAME, 4 | CHANGE_SEX, 5 | CHANGE_BIRTHDAY, 6 | ADD_ADDRESS, 7 | EDIT_ADDRESS, 8 | REMOVE_ADDRESS, 9 | ADD_GOODS, 10 | REMOVE_GOODS, 11 | CLEAR_CART, 12 | SELECT_ALL_GOODS, 13 | LOG_OUT 14 | } from './mutation-types' 15 | 16 | import { setLocalStore, removeLocalStore } from '../plugins/global'; 17 | export default { 18 | [USER_INFO](state, userInfo) { 19 | state.userInfo = userInfo; 20 | setLocalStore('userInfo', userInfo); 21 | }, 22 | [CHANGE_USER_NAME](state, name) { 23 | state.userInfo.user_name = name; 24 | setLocalStore('userInfo', state.userInfo); 25 | }, 26 | [CHANGE_SEX](state, sex) { 27 | state.userInfo.sex = sex; 28 | setLocalStore('userInfo', state.userInfo); 29 | }, 30 | [CHANGE_BIRTHDAY](state, day) { 31 | state.userInfo.birth_day = day; 32 | setLocalStore('userInfo', state.userInfo); 33 | }, 34 | [ADD_ADDRESS](state, address) { 35 | state.addressInfo.push(address); 36 | setLocalStore('addressInfo', state.addressInfo); 37 | }, 38 | [EDIT_ADDRESS](state, address) { 39 | let addressInfo = state.addressInfo; 40 | addressInfo = addressInfo.map(item => { 41 | if (item.id === address.id) { 42 | item = address; 43 | } 44 | return item; 45 | }) 46 | state.addressInfo = [...addressInfo]; 47 | setLocalStore('addressInfo', state.addressInfo); 48 | }, 49 | [REMOVE_ADDRESS](state, id) { 50 | let addressInfo = state.addressInfo 51 | let currentIndex; 52 | addressInfo.forEach((item, index) => { 53 | if (item.id === id) { 54 | currentIndex = index; 55 | } 56 | }) 57 | addressInfo.splice(currentIndex, 1); 58 | state.addressInfo = [...addressInfo]; 59 | setLocalStore('addressInfo', state.addressInfo); 60 | }, 61 | [ADD_GOODS](state, { id, name, small_image, price }) { 62 | let shopCartInfo = state.shopCartInfo 63 | if (shopCartInfo[id]) { 64 | shopCartInfo[id]['number']++; 65 | } else { 66 | shopCartInfo[id] = { 67 | id, 68 | number: 1, 69 | name, 70 | small_image, 71 | price, 72 | checked: true 73 | } 74 | } 75 | state.shopCartInfo = { ...shopCartInfo }; 76 | setLocalStore('shopCartInfo', state.shopCartInfo); 77 | }, 78 | [REMOVE_GOODS](state, id) { 79 | let shopCartInfo = state.shopCartInfo 80 | delete shopCartInfo[id]; 81 | state.shopCartInfo = { ...shopCartInfo }; 82 | setLocalStore('shopCartInfo', state.shopCartInfo); 83 | }, 84 | [CLEAR_CART](state) { 85 | state.shopCartInfo = {}; 86 | removeLocalStore('shopCartInfo'); 87 | }, 88 | [SELECT_ALL_GOODS](state, flag) { 89 | let shopCartInfo = state.shopCartInfo; 90 | Object.values(shopCartInfo).forEach(item => item.checked = flag); 91 | state.shopCartInfo = { ...shopCartInfo }; 92 | setLocalStore('shopCartInfo', state.shopCartInfo); 93 | }, 94 | [LOG_OUT](state) { 95 | state.userInfo = {}; 96 | state.addressInfo = []; 97 | state.shopCartInfo = {}; 98 | removeLocalStore('userInfo'); 99 | removeLocalStore('addressInfo'); 100 | removeLocalStore('shopCartInfo'); 101 | } 102 | } -------------------------------------------------------------------------------- /src/store/state.js: -------------------------------------------------------------------------------- 1 | import { getLocalStore } from '../plugins/global' 2 | 3 | const state = { 4 | userInfo: getLocalStore('userInfo') || {}, // 用户信息 5 | shopCartInfo: getLocalStore('shopCartInfo') || {}, // 购物车信息 6 | addressInfo: getLocalStore('addressInfo') || [], // 地址信息 7 | } 8 | 9 | export default state -------------------------------------------------------------------------------- /src/views/cart/index.vue: -------------------------------------------------------------------------------- 1 | 122 | 236 | -------------------------------------------------------------------------------- /src/views/cart/order/components/timelist.vue: -------------------------------------------------------------------------------- 1 | 42 | 118 | -------------------------------------------------------------------------------- /src/views/cart/order/goodsList.vue: -------------------------------------------------------------------------------- 1 | 27 | 43 | -------------------------------------------------------------------------------- /src/views/cart/order/orderFill.vue: -------------------------------------------------------------------------------- 1 | 105 | 245 | -------------------------------------------------------------------------------- /src/views/category/index.vue: -------------------------------------------------------------------------------- 1 | 132 | 259 | -------------------------------------------------------------------------------- /src/views/detail/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 16 | -------------------------------------------------------------------------------- /src/views/eat/collection/collection.vue: -------------------------------------------------------------------------------- 1 | 15 | 31 | -------------------------------------------------------------------------------- /src/views/eat/index.vue: -------------------------------------------------------------------------------- 1 | 90 | 207 | -------------------------------------------------------------------------------- /src/views/home/components/header.vue: -------------------------------------------------------------------------------- 1 | 32 | 97 | -------------------------------------------------------------------------------- /src/views/home/components/limit.vue: -------------------------------------------------------------------------------- 1 | 84 | 142 | -------------------------------------------------------------------------------- /src/views/home/components/special.vue: -------------------------------------------------------------------------------- 1 | 23 | 54 | -------------------------------------------------------------------------------- /src/views/home/index.vue: -------------------------------------------------------------------------------- 1 | 178 | 301 | -------------------------------------------------------------------------------- /src/views/home/myMap.vue: -------------------------------------------------------------------------------- 1 | 66 | 215 | -------------------------------------------------------------------------------- /src/views/layout.vue: -------------------------------------------------------------------------------- 1 | 28 | -------------------------------------------------------------------------------- /src/views/login/index.vue: -------------------------------------------------------------------------------- 1 | 136 | 191 | -------------------------------------------------------------------------------- /src/views/mine/address/addAddress.vue: -------------------------------------------------------------------------------- 1 | 14 | 36 | -------------------------------------------------------------------------------- /src/views/mine/address/editAddress.vue: -------------------------------------------------------------------------------- 1 | 21 | 66 | -------------------------------------------------------------------------------- /src/views/mine/address/myAddress.vue: -------------------------------------------------------------------------------- 1 | 20 | 65 | -------------------------------------------------------------------------------- /src/views/mine/coupon.vue: -------------------------------------------------------------------------------- 1 | 15 | 65 | -------------------------------------------------------------------------------- /src/views/mine/index.vue: -------------------------------------------------------------------------------- 1 | 55 | 133 | -------------------------------------------------------------------------------- /src/views/mine/order.vue: -------------------------------------------------------------------------------- 1 | 25 | 61 | -------------------------------------------------------------------------------- /src/views/mine/profile/changeName.vue: -------------------------------------------------------------------------------- 1 | 15 | 32 | -------------------------------------------------------------------------------- /src/views/mine/profile/profile.vue: -------------------------------------------------------------------------------- 1 | 35 | 107 | -------------------------------------------------------------------------------- /src/views/mine/vip/payVip.vue: -------------------------------------------------------------------------------- 1 | 54 | 115 | -------------------------------------------------------------------------------- /src/views/mine/vip/vip.vue: -------------------------------------------------------------------------------- 1 | 158 | 216 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const resolve = dir => path.join(__dirname, dir) 3 | const isProduction = process.env.NODE_ENV === 'production' ? true : false; 4 | 5 | module.exports = { 6 | productionSourceMap: false, 7 | lintOnSave: false, 8 | chainWebpack: config => { 9 | config.resolve.alias 10 | .set("@", resolve('src')) 11 | .set('assets', resolve('src/assets')) 12 | .set('components',resolve('src/components')) 13 | .set('views', resolve('src/views')) 14 | }, 15 | devServer: { 16 | open: true, 17 | } 18 | } --------------------------------------------------------------------------------