├── .browserslistrc ├── .gitignore ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── public ├── favicon.ico └── index.html ├── src ├── App.vue ├── assets │ ├── css │ │ ├── base.css │ │ └── normalize.css │ └── img │ │ ├── cart │ │ └── tick.svg │ │ ├── common │ │ ├── arrow-left.svg │ │ ├── back.svg │ │ ├── collect.svg │ │ ├── placeholder.png │ │ └── top.png │ │ ├── detail │ │ ├── cart.png │ │ └── detail_bottom.png │ │ ├── home │ │ └── recommend_bg.jpg │ │ ├── profile │ │ ├── avatar.svg │ │ ├── cart.svg │ │ ├── message.svg │ │ ├── phone.svg │ │ ├── pointer.svg │ │ ├── shopping.svg │ │ └── vip.svg │ │ └── tabbar │ │ ├── category.svg │ │ ├── category_active.svg │ │ ├── home.svg │ │ ├── home_active.svg │ │ ├── profile.svg │ │ ├── profile_active.svg │ │ ├── shopcart.svg │ │ └── shopcart_active.svg ├── common │ ├── const.js │ ├── mixin.js │ └── utils.js ├── components │ ├── common │ │ ├── backTop │ │ │ └── BackTop.vue │ │ ├── gridView │ │ │ └── GridView.vue │ │ ├── navbar │ │ │ └── NavBar.vue │ │ ├── scroll │ │ │ └── Scroll.vue │ │ ├── swiper │ │ │ ├── Swiper.vue │ │ │ ├── SwiperItem.vue │ │ │ └── index.js │ │ ├── tabbar │ │ │ ├── TabBar.vue │ │ │ └── TabBarItem.vue │ │ └── totast │ │ │ ├── Toast.vue │ │ │ └── index.js │ └── content │ │ ├── goods │ │ ├── GoodsList.vue │ │ └── GoodsListItem.vue │ │ ├── mainTabBar │ │ └── MainTabBar.vue │ │ └── tabControl │ │ └── TabControl.vue ├── main.js ├── network │ ├── category.js │ ├── detail.js │ ├── home.js │ └── request.js ├── router │ └── index.js ├── store │ ├── actions.js │ ├── getters.js │ ├── index.js │ ├── mutation-type.js │ ├── mutations.js │ └── state.js ├── views │ ├── cart │ │ ├── cart.vue │ │ └── childComps │ │ │ ├── CartBottonBar.vue │ │ │ ├── CartList.vue │ │ │ ├── CartListItem.vue │ │ │ └── CheckButton.vue │ ├── category │ │ ├── category.vue │ │ └── childComps │ │ │ ├── TabContentCategory.vue │ │ │ └── TabMenu.vue │ ├── detail │ │ ├── Detail.vue │ │ └── childComps │ │ │ ├── CartButton.vue │ │ │ ├── DetailBaseInfo.vue │ │ │ ├── DetailBottomBar.vue │ │ │ ├── DetailCommentInfo.vue │ │ │ ├── DetailGoodsInfo.vue │ │ │ ├── DetailNavBar.vue │ │ │ ├── DetailParamInfo.vue │ │ │ ├── DetailShopInfo.vue │ │ │ └── DetailSwiper.vue │ ├── home │ │ ├── childComps │ │ │ ├── FeatureView.vue │ │ │ ├── HomeSwiper.vue │ │ │ └── RecommendView.vue │ │ └── home.vue │ └── profile │ │ ├── childComps │ │ ├── AccountInfo.vue │ │ ├── NormalListView.vue │ │ └── UserInfo.vue │ │ └── profile.vue └── vue.config.js └── vue.config.js /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # supermall 2 | 3 | ## Project setup 4 | ``` 5 | npm install 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | npm run serve 11 | ``` 12 | 13 | ### Compiles and minifies for production 14 | ``` 15 | npm run build 16 | ``` 17 | 18 | ### Customize configuration 19 | See [Configuration Reference](https://cli.vuejs.org/config/). 20 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "supermall", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build" 8 | }, 9 | "dependencies": { 10 | "axios": "^0.18.0", 11 | "better-scroll": "^1.13.2", 12 | "core-js": "^3.6.5", 13 | "vue": "^2.6.11", 14 | "vue-router": "^3.0.1", 15 | "vuex": "^3.0.1" 16 | }, 17 | "devDependencies": { 18 | "@vue/cli-plugin-babel": "~4.5.0", 19 | "@vue/cli-service": "~4.5.0", 20 | "vue-template-compiler": "^2.6.11" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qiangfeidog/vue2_mall/1f6b512d0615584be7ddf5d9aa2ea4e00b2d5e73/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 购物小程序 10 | 11 | 12 | 13 | 16 |
17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 9 | 18 | 19 | 22 | -------------------------------------------------------------------------------- /src/assets/css/base.css: -------------------------------------------------------------------------------- 1 | @import "./normalize.css"; 2 | :root { 3 | /* 定义变量 */ 4 | --color-text: #666; 5 | --color-high-text: #ff5777; 6 | --color-tint: #ff8198; 7 | --color-background: #fff; 8 | --font-size: 14px; 9 | --line-height: 1.5; 10 | } 11 | 12 | *, 13 | *::before, 14 | *::after { 15 | margin: 0; 16 | padding: 0; 17 | box-sizing: border-box; 18 | } 19 | 20 | body { 21 | font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif; 22 | user-select: none; 23 | /* 禁止用户鼠标在页面上选中文字/图片等 */ 24 | -webkit-tap-highlight-color: transparent; 25 | /* webkit是苹果浏览器引擎,tap点击,highlight背景高亮,color颜色,颜色用数值调节 */ 26 | background: var(--color-background); 27 | color: var(--color-text); 28 | /* rem vw/vh */ 29 | width: 100vw; 30 | } 31 | 32 | a { 33 | color: var(--color-text); 34 | text-decoration: none; 35 | } 36 | 37 | .clear-fix::after { 38 | clear: both; 39 | content: ''; 40 | display: block; 41 | width: 0; 42 | height: 0; 43 | visibility: hidden; 44 | } 45 | 46 | .clear-fix { 47 | zoom: 1; 48 | } 49 | 50 | .left { 51 | float: left; 52 | } 53 | 54 | .right { 55 | float: right; 56 | } -------------------------------------------------------------------------------- /src/assets/css/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ 2 | 3 | 4 | /* Document 5 | ========================================================================== */ 6 | 7 | 8 | /** 9 | * 1. Correct the line height in all browsers. 10 | * 2. Prevent adjustments of font size after orientation changes in iOS. 11 | */ 12 | 13 | html { 14 | line-height: 1.15; 15 | /* 1 */ 16 | -webkit-text-size-adjust: 100%; 17 | /* 2 */ 18 | } 19 | 20 | 21 | /* Sections 22 | ========================================================================== */ 23 | 24 | 25 | /** 26 | * Remove the margin in all browsers. 27 | */ 28 | 29 | body { 30 | margin: 0; 31 | } 32 | 33 | 34 | /** 35 | * Render the `main` element consistently in IE. 36 | */ 37 | 38 | main { 39 | display: block; 40 | } 41 | 42 | 43 | /** 44 | * Correct the font size and margin on `h1` elements within `section` and 45 | * `article` contexts in Chrome, Firefox, and Safari. 46 | */ 47 | 48 | h1 { 49 | font-size: 2em; 50 | margin: 0.67em 0; 51 | } 52 | 53 | 54 | /* Grouping content 55 | ========================================================================== */ 56 | 57 | 58 | /** 59 | * 1. Add the correct box sizing in Firefox. 60 | * 2. Show the overflow in Edge and IE. 61 | */ 62 | 63 | hr { 64 | box-sizing: content-box; 65 | /* 1 */ 66 | height: 0; 67 | /* 1 */ 68 | overflow: visible; 69 | /* 2 */ 70 | } 71 | 72 | 73 | /** 74 | * 1. Correct the inheritance and scaling of font size in all browsers. 75 | * 2. Correct the odd `em` font sizing in all browsers. 76 | */ 77 | 78 | pre { 79 | font-family: monospace, monospace; 80 | /* 1 */ 81 | font-size: 1em; 82 | /* 2 */ 83 | } 84 | 85 | 86 | /* Text-level semantics 87 | ========================================================================== */ 88 | 89 | 90 | /** 91 | * Remove the gray background on active links in IE 10. 92 | */ 93 | 94 | a { 95 | background-color: transparent; 96 | } 97 | 98 | 99 | /** 100 | * 1. Remove the bottom border in Chrome 57- 101 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. 102 | */ 103 | 104 | abbr[title] { 105 | border-bottom: none; 106 | /* 1 */ 107 | text-decoration: underline; 108 | /* 2 */ 109 | text-decoration: underline dotted; 110 | /* 2 */ 111 | } 112 | 113 | 114 | /** 115 | * Add the correct font weight in Chrome, Edge, and Safari. 116 | */ 117 | 118 | b, 119 | strong { 120 | font-weight: bolder; 121 | } 122 | 123 | 124 | /** 125 | * 1. Correct the inheritance and scaling of font size in all browsers. 126 | * 2. Correct the odd `em` font sizing in all browsers. 127 | */ 128 | 129 | code, 130 | kbd, 131 | samp { 132 | font-family: monospace, monospace; 133 | /* 1 */ 134 | font-size: 1em; 135 | /* 2 */ 136 | } 137 | 138 | 139 | /** 140 | * Add the correct font size in all browsers. 141 | */ 142 | 143 | small { 144 | font-size: 80%; 145 | } 146 | 147 | 148 | /** 149 | * Prevent `sub` and `sup` elements from affecting the line height in 150 | * all browsers. 151 | */ 152 | 153 | sub, 154 | sup { 155 | font-size: 75%; 156 | line-height: 0; 157 | position: relative; 158 | vertical-align: baseline; 159 | } 160 | 161 | sub { 162 | bottom: -0.25em; 163 | } 164 | 165 | sup { 166 | top: -0.5em; 167 | } 168 | 169 | 170 | /* Embedded content 171 | ========================================================================== */ 172 | 173 | 174 | /** 175 | * Remove the border on images inside links in IE 10. 176 | */ 177 | 178 | img { 179 | border-style: none; 180 | } 181 | 182 | 183 | /* Forms 184 | ========================================================================== */ 185 | 186 | 187 | /** 188 | * 1. Change the font styles in all browsers. 189 | * 2. Remove the margin in Firefox and Safari. 190 | */ 191 | 192 | button, 193 | input, 194 | optgroup, 195 | select, 196 | textarea { 197 | font-family: inherit; 198 | /* 1 */ 199 | font-size: 100%; 200 | /* 1 */ 201 | line-height: 1.15; 202 | /* 1 */ 203 | margin: 0; 204 | /* 2 */ 205 | } 206 | 207 | 208 | /** 209 | * Show the overflow in IE. 210 | * 1. Show the overflow in Edge. 211 | */ 212 | 213 | button, 214 | input { 215 | /* 1 */ 216 | overflow: visible; 217 | } 218 | 219 | 220 | /** 221 | * Remove the inheritance of text transform in Edge, Firefox, and IE. 222 | * 1. Remove the inheritance of text transform in Firefox. 223 | */ 224 | 225 | button, 226 | select { 227 | /* 1 */ 228 | text-transform: none; 229 | } 230 | 231 | 232 | /** 233 | * Correct the inability to style clickable types in iOS and Safari. 234 | */ 235 | 236 | button, 237 | [type="button"], 238 | [type="reset"], 239 | [type="submit"] { 240 | -webkit-appearance: button; 241 | } 242 | 243 | 244 | /** 245 | * Remove the inner border and padding in Firefox. 246 | */ 247 | 248 | button::-moz-focus-inner, 249 | [type="button"]::-moz-focus-inner, 250 | [type="reset"]::-moz-focus-inner, 251 | [type="submit"]::-moz-focus-inner { 252 | border-style: none; 253 | padding: 0; 254 | } 255 | 256 | 257 | /** 258 | * Restore the focus styles unset by the previous rule. 259 | */ 260 | 261 | button:-moz-focusring, 262 | [type="button"]:-moz-focusring, 263 | [type="reset"]:-moz-focusring, 264 | [type="submit"]:-moz-focusring { 265 | outline: 1px dotted ButtonText; 266 | } 267 | 268 | 269 | /** 270 | * Correct the padding in Firefox. 271 | */ 272 | 273 | fieldset { 274 | padding: 0.35em 0.75em 0.625em; 275 | } 276 | 277 | 278 | /** 279 | * 1. Correct the text wrapping in Edge and IE. 280 | * 2. Correct the color inheritance from `fieldset` elements in IE. 281 | * 3. Remove the padding so developers are not caught out when they zero out 282 | * `fieldset` elements in all browsers. 283 | */ 284 | 285 | legend { 286 | box-sizing: border-box; 287 | /* 1 */ 288 | color: inherit; 289 | /* 2 */ 290 | display: table; 291 | /* 1 */ 292 | max-width: 100%; 293 | /* 1 */ 294 | padding: 0; 295 | /* 3 */ 296 | white-space: normal; 297 | /* 1 */ 298 | } 299 | 300 | 301 | /** 302 | * Add the correct vertical alignment in Chrome, Firefox, and Opera. 303 | */ 304 | 305 | progress { 306 | vertical-align: baseline; 307 | } 308 | 309 | 310 | /** 311 | * Remove the default vertical scrollbar in IE 10+. 312 | */ 313 | 314 | textarea { 315 | overflow: auto; 316 | } 317 | 318 | 319 | /** 320 | * 1. Add the correct box sizing in IE 10. 321 | * 2. Remove the padding in IE 10. 322 | */ 323 | 324 | [type="checkbox"], 325 | [type="radio"] { 326 | box-sizing: border-box; 327 | /* 1 */ 328 | padding: 0; 329 | /* 2 */ 330 | } 331 | 332 | 333 | /** 334 | * Correct the cursor style of increment and decrement buttons in Chrome. 335 | */ 336 | 337 | [type="number"]::-webkit-inner-spin-button, 338 | [type="number"]::-webkit-outer-spin-button { 339 | height: auto; 340 | } 341 | 342 | 343 | /** 344 | * 1. Correct the odd appearance in Chrome and Safari. 345 | * 2. Correct the outline style in Safari. 346 | */ 347 | 348 | [type="search"] { 349 | -webkit-appearance: textfield; 350 | /* 1 */ 351 | outline-offset: -2px; 352 | /* 2 */ 353 | } 354 | 355 | 356 | /** 357 | * Remove the inner padding in Chrome and Safari on macOS. 358 | */ 359 | 360 | [type="search"]::-webkit-search-decoration { 361 | -webkit-appearance: none; 362 | } 363 | 364 | 365 | /** 366 | * 1. Correct the inability to style clickable types in iOS and Safari. 367 | * 2. Change font properties to `inherit` in Safari. 368 | */ 369 | 370 | ::-webkit-file-upload-button { 371 | -webkit-appearance: button; 372 | /* 1 */ 373 | font: inherit; 374 | /* 2 */ 375 | } 376 | 377 | 378 | /* Interactive 379 | ========================================================================== */ 380 | 381 | 382 | /* 383 | * Add the correct display in Edge, IE 10+, and Firefox. 384 | */ 385 | 386 | details { 387 | display: block; 388 | } 389 | 390 | 391 | /* 392 | * Add the correct display in all browsers. 393 | */ 394 | 395 | summary { 396 | display: list-item; 397 | } 398 | 399 | 400 | /* Misc 401 | ========================================================================== */ 402 | 403 | 404 | /** 405 | * Add the correct display in IE 10+. 406 | */ 407 | 408 | template { 409 | display: none; 410 | } 411 | 412 | 413 | /** 414 | * Add the correct display in IE 10. 415 | */ 416 | 417 | [hidden] { 418 | display: none; 419 | } -------------------------------------------------------------------------------- /src/assets/img/cart/tick.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/img/common/arrow-left.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/img/common/back.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/assets/img/common/collect.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/img/common/placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qiangfeidog/vue2_mall/1f6b512d0615584be7ddf5d9aa2ea4e00b2d5e73/src/assets/img/common/placeholder.png -------------------------------------------------------------------------------- /src/assets/img/common/top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qiangfeidog/vue2_mall/1f6b512d0615584be7ddf5d9aa2ea4e00b2d5e73/src/assets/img/common/top.png -------------------------------------------------------------------------------- /src/assets/img/detail/cart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qiangfeidog/vue2_mall/1f6b512d0615584be7ddf5d9aa2ea4e00b2d5e73/src/assets/img/detail/cart.png -------------------------------------------------------------------------------- /src/assets/img/detail/detail_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qiangfeidog/vue2_mall/1f6b512d0615584be7ddf5d9aa2ea4e00b2d5e73/src/assets/img/detail/detail_bottom.png -------------------------------------------------------------------------------- /src/assets/img/home/recommend_bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qiangfeidog/vue2_mall/1f6b512d0615584be7ddf5d9aa2ea4e00b2d5e73/src/assets/img/home/recommend_bg.jpg -------------------------------------------------------------------------------- /src/assets/img/profile/avatar.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/img/profile/cart.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/img/profile/message.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/img/profile/phone.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/img/profile/pointer.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/img/profile/shopping.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/img/profile/vip.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/img/tabbar/category.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.15, written by Peter Selinger 2001-2017 9 | 10 | 12 | 14 | 16 | 18 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/assets/img/tabbar/category_active.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.15, written by Peter Selinger 2001-2017 9 | 10 | 12 | 14 | 16 | 18 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/assets/img/tabbar/home.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.15, written by Peter Selinger 2001-2017 9 | 10 | 12 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/assets/img/tabbar/home_active.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.15, written by Peter Selinger 2001-2017 9 | 10 | 12 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/assets/img/tabbar/profile.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.15, written by Peter Selinger 2001-2017 9 | 10 | 12 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/assets/img/tabbar/profile_active.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.15, written by Peter Selinger 2001-2017 9 | 10 | 12 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/assets/img/tabbar/shopcart.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.15, written by Peter Selinger 2001-2017 9 | 10 | 12 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/assets/img/tabbar/shopcart_active.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.15, written by Peter Selinger 2001-2017 9 | 10 | 12 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/common/const.js: -------------------------------------------------------------------------------- 1 | export const TOP_DISTANCE = 1000 2 | export const POP = 'pop' 3 | export const NEW = 'new' 4 | export const SELL = 'sell' -------------------------------------------------------------------------------- /src/common/mixin.js: -------------------------------------------------------------------------------- 1 | import BackTop from "@/components/common/backTop/BackTop" 2 | import { POP, NEW, SELL } from './const' 3 | export const backTopMxin = { 4 | components: { 5 | BackTop 6 | }, 7 | data() { 8 | return { 9 | isShowTop: false 10 | } 11 | }, 12 | methods: { 13 | backTopClick() { 14 | this.$refs.scroll.scroll.scrollTo(0, 0, 300) 15 | } 16 | } 17 | } 18 | 19 | export const tabControlMixin = { 20 | data: function() { 21 | return { 22 | currentType: POP 23 | } 24 | }, 25 | methods: { 26 | tabClick(index) { 27 | switch (index) { 28 | case 0: 29 | this.currentType = POP 30 | break 31 | case 1: 32 | this.currentType = NEW 33 | break 34 | case 2: 35 | this.currentType = SELL 36 | break 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /src/common/utils.js: -------------------------------------------------------------------------------- 1 | //防抖函数 2 | export function debounce(fun, delay) { 3 | let timer = null; 4 | return function(...args) { 5 | if (timer) clearTimeout(timer) 6 | timer = setTimeout(() => { 7 | fun.apply(this, args) 8 | }, delay) 9 | } 10 | } 11 | export function formatDate(date, fmt) { 12 | if (/(y+)/.test(fmt)) { 13 | fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length)); 14 | } 15 | let o = { 16 | 'M+': date.getMonth() + 1, 17 | 'd+': date.getDate(), 18 | 'h+': date.getHours(), 19 | 'm+': date.getMinutes(), 20 | 's+': date.getSeconds() 21 | }; 22 | for (let k in o) { 23 | if (new RegExp(`(${k})`).test(fmt)) { 24 | let str = o[k] + ''; 25 | fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? str : padLeftZero(str)); 26 | } 27 | } 28 | return fmt; 29 | }; 30 | 31 | function padLeftZero(str) { 32 | return ('00' + str).substr(str.length); 33 | }; -------------------------------------------------------------------------------- /src/components/common/backTop/BackTop.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /src/components/common/gridView/GridView.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 65 | 66 | 72 | -------------------------------------------------------------------------------- /src/components/common/navbar/NavBar.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 15 | -------------------------------------------------------------------------------- /src/components/common/scroll/Scroll.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 54 | 55 | -------------------------------------------------------------------------------- /src/components/common/swiper/Swiper.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 211 | 212 | 246 | -------------------------------------------------------------------------------- /src/components/common/swiper/SwiperItem.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 23 | -------------------------------------------------------------------------------- /src/components/common/swiper/index.js: -------------------------------------------------------------------------------- 1 | import Swiper from './Swiper' 2 | import SwiperItem from './SwiperItem' 3 | 4 | export { 5 | Swiper, SwiperItem 6 | } 7 | -------------------------------------------------------------------------------- /src/components/common/tabbar/TabBar.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 16 | 17 | -------------------------------------------------------------------------------- /src/components/common/tabbar/TabBarItem.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 33 | 34 | -------------------------------------------------------------------------------- /src/components/common/totast/Toast.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 18 | 19 | -------------------------------------------------------------------------------- /src/components/common/totast/index.js: -------------------------------------------------------------------------------- 1 | import Toast from './Toast' 2 | 3 | const plugin = {} 4 | 5 | function removeDom(event) { 6 | if (event.target.parentNode) { 7 | event.target.parentNode.removeChild(event.target) 8 | } 9 | } 10 | 11 | plugin.install = (Vue) => { 12 | const ToastConstructor = Vue.extend(Toast) 13 | 14 | // 注意:这里不能用箭头函数 15 | ToastConstructor.prototype.close = function() { 16 | this.isShow = false 17 | this.$el.addEventListener('transitionend', removeDom) 18 | } 19 | 20 | Vue.prototype.$toast = (options = {}) => { 21 | // 1.将创建出来的组件,挂载到某个div中 22 | const toast = new ToastConstructor() 23 | toast.$mount(document.createElement('div')) 24 | 25 | // 2.将toast的$el添加到body中 26 | document.body.appendChild(toast.$el) 27 | 28 | // 3.获取用户自定义数据 29 | const duration = options.duration || 2500 30 | toast.message = options.message 31 | toast.isShow = true 32 | 33 | // 4.定时器让toast消失 34 | setTimeout(() => { 35 | toast.close() 36 | }, duration) 37 | } 38 | } 39 | 40 | export default plugin -------------------------------------------------------------------------------- /src/components/content/goods/GoodsList.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 24 | 25 | -------------------------------------------------------------------------------- /src/components/content/goods/GoodsListItem.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 39 | 40 | -------------------------------------------------------------------------------- /src/components/content/mainTabBar/MainTabBar.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 37 | 38 | -------------------------------------------------------------------------------- /src/components/content/tabControl/TabControl.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 32 | 33 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import router from './router' 4 | import store from './store' 5 | import Totast from '@/components/common/totast/index.js' 6 | Vue.use(Totast) 7 | Vue.config.productionTip = false 8 | Vue.prototype.$bus = new Vue() 9 | new Vue({ 10 | render: h => h(App), 11 | router, 12 | store 13 | }).$mount('#app') -------------------------------------------------------------------------------- /src/network/category.js: -------------------------------------------------------------------------------- 1 | import { request } from './request' 2 | 3 | 4 | export function getCategory() { 5 | return request({ 6 | url: '/category' 7 | }) 8 | } 9 | 10 | export function getSubcategory(maitKey) { 11 | return request({ 12 | url: '/subcategory', 13 | params: { 14 | maitKey 15 | } 16 | }) 17 | } 18 | 19 | export function getCategoryDetail(miniWallkey, type) { 20 | return request({ 21 | url: '/subcategory/detail', 22 | params: { 23 | miniWallkey, 24 | type 25 | } 26 | }) 27 | } -------------------------------------------------------------------------------- /src/network/detail.js: -------------------------------------------------------------------------------- 1 | import { request } from "./request"; 2 | 3 | export function getDetail(iid) { 4 | return request({ 5 | url: '/detail', 6 | params: { 7 | iid 8 | } 9 | }) 10 | } 11 | export function getRecommend() { 12 | return request({ 13 | url: '/recommend' 14 | }) 15 | } 16 | export class Goods { 17 | constructor(itemInfo, columns, services) { 18 | this.title = itemInfo.title 19 | this.desc = itemInfo.desc 20 | this.newPrice = itemInfo.price 21 | this.oldPrice = itemInfo.oldPrice 22 | this.discount = itemInfo.discountDesc 23 | this.columns = columns 24 | this.services = services 25 | this.realPrice = itemInfo.lowNowPrice 26 | } 27 | } 28 | export class Shop { 29 | constructor(shopInfo) { 30 | this.logo = shopInfo.shopLogo; 31 | this.name = shopInfo.name; 32 | this.fans = shopInfo.cFans; 33 | this.sells = shopInfo.cSells; 34 | this.score = shopInfo.score; 35 | this.goodsCount = shopInfo.cGoods 36 | } 37 | } 38 | export class GoodsParam { 39 | constructor(info, rule) { 40 | // 注: images可能没有值(某些商品有值, 某些没有值) 41 | this.image = info.images ? info.images[0] : ''; 42 | this.infos = info.set; 43 | this.sizes = rule.tables; 44 | } 45 | } -------------------------------------------------------------------------------- /src/network/home.js: -------------------------------------------------------------------------------- 1 | import { request } from "./request"; 2 | export function getHomeMultidata() { 3 | return request({ 4 | url: '/home/multidata' 5 | }) 6 | } 7 | export function getHomeGoods(type, page) { 8 | return request({ 9 | url: '/home/data', 10 | params: { 11 | type, 12 | page 13 | } 14 | }) 15 | } -------------------------------------------------------------------------------- /src/network/request.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | 3 | export function request(config) { 4 | // 1.创建axios的实例 5 | const instance = axios.create({ 6 | baseURL: 'http://152.136.185.210:7878/api/m5', 7 | timeout: 5000 8 | }) 9 | 10 | // 2.axios的拦截器 11 | // 2.1.请求拦截的作用 12 | instance.interceptors.request.use(config => { 13 | return config 14 | }, err => { 15 | // console.log(err); 16 | }) 17 | 18 | // 2.2.响应拦截 19 | instance.interceptors.response.use(res => { 20 | return res.data 21 | }, err => { 22 | console.log(err); 23 | }) 24 | 25 | // 3.发送真正的网络请求 26 | return instance(config) 27 | } -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | 4 | Vue.use(Router) 5 | import Home from '../views/home/home.vue' 6 | import Category from '../views/category/category.vue' 7 | import Cart from '../views/cart/cart.vue' 8 | import Profile from '../views/profile/profile.vue' 9 | import Detail from '../views/detail/Detail' 10 | // 解决ElementUI导航栏中的vue-router在3.0版本以上重复点菜单报错问题 11 | // const originalPush = Router.prototype.push 12 | // Router.prototype.push = function push(location) { 13 | // return originalPush.call(this, location).catch(err => err) 14 | // } 15 | 16 | export default new Router({ 17 | mode: 'hash', 18 | routes: [ 19 | { 20 | path: '/', 21 | redirect: '/home', 22 | }, 23 | { 24 | path: '/home', 25 | component: Home, 26 | }, 27 | { 28 | path: '/category', 29 | component: Category, 30 | }, 31 | { 32 | path: '/cart', 33 | component: Cart, 34 | }, 35 | { 36 | path: '/profile', 37 | component: Profile, 38 | }, 39 | { 40 | path: '/detail/:id', 41 | component: Detail, 42 | }, 43 | ], 44 | }) 45 | -------------------------------------------------------------------------------- /src/store/actions.js: -------------------------------------------------------------------------------- 1 | import { 2 | ADD_COUNTER, 3 | ADD_TO_CART 4 | } from './mutation-type' 5 | export default { 6 | addCart(context, payload) { 7 | return new Promise((resolve, reject) => { 8 | // debugger; 9 | // 查看之前的cartlist中是否已经存在该商品 10 | let oldProduct = context.state.cartList.find(item => 11 | item.iid === payload.iid 12 | ) 13 | if (oldProduct) { 14 | // oldProduct.count++; 15 | context.commit(ADD_COUNTER, oldProduct) 16 | resolve('当前商品+1') 17 | } else { 18 | payload.count = 1 19 | // context.state.cartList.push(payload) 20 | context.commit(ADD_TO_CART, payload) 21 | resolve('添加了新商品') 22 | } 23 | }) 24 | } 25 | } -------------------------------------------------------------------------------- /src/store/getters.js: -------------------------------------------------------------------------------- 1 | export default { 2 | getCartListLength(state) { 3 | return state.cartList.length 4 | }, 5 | getCartList(state) { 6 | return state.cartList 7 | } 8 | } -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import actions from "./actions" 4 | import mutations from "./mutations" 5 | import state from "./state" 6 | import getters from "./getters" 7 | //安装插件 8 | Vue.use(Vuex) 9 | //创建store实例 10 | const store = new Vuex.Store({ 11 | state, 12 | mutations, 13 | actions, 14 | getters 15 | }) 16 | //挂载到Vue实例上 17 | export default store -------------------------------------------------------------------------------- /src/store/mutation-type.js: -------------------------------------------------------------------------------- 1 | export const ADD_COUNTER = 'add_counter' 2 | export const ADD_TO_CART = 'add_to_cart' -------------------------------------------------------------------------------- /src/store/mutations.js: -------------------------------------------------------------------------------- 1 | import { 2 | ADD_COUNTER, 3 | ADD_TO_CART 4 | } from './mutation-type' 5 | export default { 6 | [ADD_COUNTER](state, payload) { 7 | payload.count++ 8 | }, 9 | [ADD_TO_CART](state, payload) { 10 | payload.checked = true 11 | state.cartList.push(payload) 12 | } 13 | } -------------------------------------------------------------------------------- /src/store/state.js: -------------------------------------------------------------------------------- 1 | export default { 2 | cartList: [], 3 | isShow:false 4 | } -------------------------------------------------------------------------------- /src/views/cart/cart.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 36 | 37 | -------------------------------------------------------------------------------- /src/views/cart/childComps/CartBottonBar.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 71 | 72 | 111 | -------------------------------------------------------------------------------- /src/views/cart/childComps/CartList.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 21 | 22 | -------------------------------------------------------------------------------- /src/views/cart/childComps/CartListItem.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 50 | 51 | -------------------------------------------------------------------------------- /src/views/cart/childComps/CheckButton.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 17 | 18 | -------------------------------------------------------------------------------- /src/views/category/category.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 124 | 125 | -------------------------------------------------------------------------------- /src/views/category/childComps/TabContentCategory.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 30 | 31 | 49 | -------------------------------------------------------------------------------- /src/views/category/childComps/TabMenu.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 44 | 45 | -------------------------------------------------------------------------------- /src/views/detail/Detail.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 131 | 132 | -------------------------------------------------------------------------------- /src/views/detail/childComps/CartButton.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /src/views/detail/childComps/DetailBaseInfo.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 35 | 36 | 103 | -------------------------------------------------------------------------------- /src/views/detail/childComps/DetailBottomBar.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 33 | 34 | -------------------------------------------------------------------------------- /src/views/detail/childComps/DetailCommentInfo.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 46 | 47 | -------------------------------------------------------------------------------- /src/views/detail/childComps/DetailGoodsInfo.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 47 | 48 | 101 | -------------------------------------------------------------------------------- /src/views/detail/childComps/DetailNavBar.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 37 | 38 | -------------------------------------------------------------------------------- /src/views/detail/childComps/DetailParamInfo.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 31 | 32 | 69 | -------------------------------------------------------------------------------- /src/views/detail/childComps/DetailShopInfo.vue: -------------------------------------------------------------------------------- 1 | 37 | 38 | 58 | 59 | 159 | -------------------------------------------------------------------------------- /src/views/detail/childComps/DetailSwiper.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 28 | 29 | -------------------------------------------------------------------------------- /src/views/home/childComps/FeatureView.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /src/views/home/childComps/HomeSwiper.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 39 | 40 | -------------------------------------------------------------------------------- /src/views/home/childComps/RecommendView.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 25 | 26 | -------------------------------------------------------------------------------- /src/views/home/home.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 141 | 142 | -------------------------------------------------------------------------------- /src/views/profile/childComps/AccountInfo.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 29 | 30 | -------------------------------------------------------------------------------- /src/views/profile/childComps/NormalListView.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 30 | 31 | -------------------------------------------------------------------------------- /src/views/profile/childComps/UserInfo.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 22 | 23 | -------------------------------------------------------------------------------- /src/views/profile/profile.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 42 | 43 | -------------------------------------------------------------------------------- /src/vue.config.js: -------------------------------------------------------------------------------- 1 | // module.exports = { 2 | // configureWebpack: { 3 | // resolve: { 4 | // alias: { 5 | // assets: "@/assets", 6 | // common: "@/common", 7 | // components:"@/components", 8 | // network: "@/network", 9 | // views: "@/views" 10 | // } 11 | // } 12 | // } 13 | // }; 14 | // 用来配置文件的别名,方便路径的寻找 15 | // const path = require('path'); //引入path模块 16 | // function resolve(dir) { 17 | // return path.join(__dirname, dir) //path.join(__dirname)设置绝对路径 18 | // } 19 | 20 | // module.exports = { 21 | // chainWebpack: (config) => { 22 | // config.resolve.alias 23 | // //set第一个参数:设置的别名,第二个参数:设置的路径 24 | // .set('@', resolve('./src')) //根据目录的层级来决定,也可以自行设 25 | // .set('components', resolve('./src/components')) 26 | // .set('views', resolve('./src/views')) 27 | // .set('assets', resolve('./src/assets')) 28 | // } 29 | // } -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | publicPath: './', 3 | } 4 | --------------------------------------------------------------------------------