├── public
├── favicon.ico
└── index.html
├── babel.config.js
├── src
├── assets
│ ├── img
│ │ ├── common
│ │ │ ├── top.png
│ │ │ ├── placeholder.png
│ │ │ ├── back.svg
│ │ │ └── collect.svg
│ │ ├── detail
│ │ │ ├── cart.png
│ │ │ └── detail_bottom.png
│ │ ├── home
│ │ │ └── recommend_bg.jpg
│ │ ├── cart
│ │ │ └── tick.svg
│ │ └── tabbar
│ │ │ ├── profile.svg
│ │ │ ├── home.svg
│ │ │ ├── home_active.svg
│ │ │ ├── profile_active.svg
│ │ │ ├── cart.svg
│ │ │ ├── cart_active.svg
│ │ │ ├── category.svg
│ │ │ └── category_active.svg
│ └── css
│ │ ├── base.css
│ │ └── normalize.css
├── store
│ ├── constant.js
│ ├── getters.js
│ ├── mutations.js
│ ├── index.js
│ └── actions.js
├── components
│ ├── common
│ │ ├── swiper
│ │ │ ├── index.js
│ │ │ ├── SwiperItem.vue
│ │ │ └── Swiper.vue
│ │ ├── backTop
│ │ │ └── BackTop.vue
│ │ ├── toast
│ │ │ ├── index.js
│ │ │ └── Toast.vue
│ │ ├── tabbar
│ │ │ ├── TabBar.vue
│ │ │ └── TabBarItem.vue
│ │ ├── navbar
│ │ │ └── NavBar.vue
│ │ └── scroll
│ │ │ └── Scroll.vue
│ └── content
│ │ ├── checkGoodsBtn
│ │ └── CheckGoodsBtn.vue
│ │ ├── tabControl
│ │ └── TabControl.vue
│ │ ├── goods
│ │ ├── GoodsList.vue
│ │ └── GoodsListItem.vue
│ │ └── mainTabBar
│ │ └── MainTabBar.vue
├── common
│ ├── utils.js
│ └── mixin.js
├── network
│ ├── category.js
│ ├── home.js
│ ├── request.js
│ └── detail.js
├── views
│ ├── home
│ │ ├── childComps
│ │ │ ├── FeatureView.vue
│ │ │ ├── RecommendView.vue
│ │ │ └── HomeSwiper.vue
│ │ └── Home.vue
│ ├── profile
│ │ └── Profile.vue
│ ├── detail
│ │ ├── childComps
│ │ │ ├── DetailRecommend.vue
│ │ │ ├── DetailSwiper.vue
│ │ │ ├── DetailNavBar.vue
│ │ │ ├── DetailGoodsInfo.vue
│ │ │ ├── DetailGoodsParams.vue
│ │ │ ├── DetailBottomBar.vue
│ │ │ ├── DetailBaseInfo.vue
│ │ │ ├── DetailCommentInfo.vue
│ │ │ └── DetailShopInfo.vue
│ │ └── Detail.vue
│ ├── category
│ │ ├── childComps
│ │ │ ├── CategorySideContentItem.vue
│ │ │ ├── CategorySideContent.vue
│ │ │ └── CategorySideBar.vue
│ │ └── Category.vue
│ └── cart
│ │ ├── childComps
│ │ ├── CartList.vue
│ │ ├── CartListItem.vue
│ │ └── CartBottomBar.vue
│ │ └── Cart.vue
├── App.vue
├── main.js
└── router
│ └── index.js
├── .editorconfig
├── .gitignore
├── vue.config.js
├── package.json
└── README.md
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sodaxiang/supermall/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/cli-plugin-babel/preset'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/src/assets/img/common/top.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sodaxiang/supermall/HEAD/src/assets/img/common/top.png
--------------------------------------------------------------------------------
/src/assets/img/detail/cart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sodaxiang/supermall/HEAD/src/assets/img/detail/cart.png
--------------------------------------------------------------------------------
/src/store/constant.js:
--------------------------------------------------------------------------------
1 | export const ADD_TO_CART = 'add_to_cart';
2 | export const ADD_TO_COUNTER = 'add_to_counter';
--------------------------------------------------------------------------------
/src/assets/img/home/recommend_bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sodaxiang/supermall/HEAD/src/assets/img/home/recommend_bg.jpg
--------------------------------------------------------------------------------
/src/assets/img/common/placeholder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sodaxiang/supermall/HEAD/src/assets/img/common/placeholder.png
--------------------------------------------------------------------------------
/src/assets/img/detail/detail_bottom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sodaxiang/supermall/HEAD/src/assets/img/detail/detail_bottom.png
--------------------------------------------------------------------------------
/src/components/common/swiper/index.js:
--------------------------------------------------------------------------------
1 | import Swiper from './Swiper';
2 | import SwiperItem from './SwiperItem';
3 |
4 | export {
5 | Swiper, SwiperItem
6 | }
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailling_whitespace = true
--------------------------------------------------------------------------------
/src/store/getters.js:
--------------------------------------------------------------------------------
1 | export default {
2 | cartList(state){
3 | return state.cartList;
4 | },
5 | cartListLength(state){
6 | return state.cartList.length;
7 | }
8 | }
--------------------------------------------------------------------------------
/src/common/utils.js:
--------------------------------------------------------------------------------
1 | export function debounce(func, delay=0){
2 | let timer = null;
3 | return function(){
4 | if(timer) clearTimeout(timer);
5 | timer = setTimeout(()=>{
6 | func.apply(this);
7 | }, delay);
8 | }
9 | }
--------------------------------------------------------------------------------
/src/store/mutations.js:
--------------------------------------------------------------------------------
1 | import {
2 | ADD_TO_CART,
3 | ADD_TO_COUNTER
4 | } from './constant';
5 |
6 | export default {
7 | [ADD_TO_CART](state,payload){
8 | state.cartList.push(payload);
9 | },
10 | [ADD_TO_COUNTER](state, payload){
11 | payload.num ++ ;
12 | }
13 | }
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | module.exports ={
2 | configureWebpack: {
3 | resolve: {
4 | alias: {
5 | // 'assets': 'src/assets',
6 | // 'common': 'src/common',
7 | // 'components': 'src/components',
8 | // 'views': 'src/views',
9 | }
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/src/network/category.js:
--------------------------------------------------------------------------------
1 | import { request } from './request';
2 |
3 | export function getAllCategory(){
4 | return request({
5 | url: '/category'
6 | })
7 | }
8 | export function getSubCategory(maitKey) {
9 | return request({
10 | url: '/subcategory',
11 | params:{
12 | maitKey
13 | }
14 | })
15 | }
--------------------------------------------------------------------------------
/src/components/common/swiper/SwiperItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
22 |
--------------------------------------------------------------------------------
/src/network/home.js:
--------------------------------------------------------------------------------
1 | import { request } from './request';
2 |
3 | export function getHomeMultidata() {
4 | return request({
5 | url: '/home/multidata'
6 | });
7 | }
8 |
9 | export function getHomeGoods(type, page){
10 | return request({
11 | url: '/home/data',
12 | params: {
13 | type,
14 | page
15 | }
16 | })
17 | }
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Vuex from 'vuex';
3 |
4 | import mutations from './mutations';
5 | import actions from './actions';
6 | import getters from './getters';
7 |
8 | Vue.use(Vuex);
9 |
10 | const state = {
11 | cartList:[]
12 | };
13 |
14 | export default new Vuex.Store({
15 | state,
16 | mutations,
17 | actions,
18 | getters
19 | })
--------------------------------------------------------------------------------
/src/assets/img/cart/tick.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/common/backTop/BackTop.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |

4 |
5 |
6 |
7 |
12 |
23 |
24 |
--------------------------------------------------------------------------------
/src/views/home/childComps/FeatureView.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
14 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/components/common/toast/index.js:
--------------------------------------------------------------------------------
1 | import Toast from './Toast';
2 |
3 | const obj = {};
4 |
5 | obj.install = function(Vue){
6 | // 1. 创建组件构造器
7 | const toastConstructor = Vue.extend(Toast);
8 |
9 | // 2.new的方式,根据组件构造器,创建一个组件对象
10 | const toast = new toastConstructor();
11 |
12 | // 3.将组件对象手动挂载到某一个DOM元素上
13 | toast.$mount(document.createElement('div'));
14 |
15 | // 4.toast.$el对应的就是div
16 | document.body.appendChild(toast.$el);
17 |
18 | Vue.prototype.$toast = toast;
19 | }
20 | export default obj;
--------------------------------------------------------------------------------
/src/views/profile/Profile.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
19 |
20 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/components/common/tabbar/TabBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
17 |
18 |
31 |
32 |
--------------------------------------------------------------------------------
/src/assets/img/common/back.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
24 |
25 |
28 |
--------------------------------------------------------------------------------
/src/components/common/navbar/NavBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
14 |
15 |
29 |
30 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import App from './App.vue';
3 | import VueLazyload from 'vue-lazyload';
4 |
5 | import router from './router';
6 | import store from './store';
7 |
8 | import toast from './components/common/toast';
9 |
10 | Vue.config.productionTip = false
11 |
12 | // 注册事件总总线
13 | Vue.prototype.$bus = new Vue();
14 | // 安装toast插件
15 | Vue.use(toast);
16 |
17 | // 使用vue-lazyload
18 | Vue.use(VueLazyload, {
19 | // error: './assets/common/placeholder.png',
20 | loading: require('./assets/img/common/placeholder.png')
21 | });
22 | new Vue({
23 | render: h => h(App),
24 | router,
25 | store
26 | }).$mount('#app')
27 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= htmlWebpackPlugin.options.title %>
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/network/request.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | export function request(config) {
4 |
5 | //1. 创建axios实例
6 | const instance = axios.create({
7 | baseURL: '找老师要',
8 | timeout: 5000,
9 | });
10 |
11 | //2. axios拦截器
12 | //2.1 axios请求拦截
13 | instance.interceptors.request.use(config => {
14 | // 一定要返回
15 | return config;
16 | }, err => {
17 | console.log(err);
18 | });
19 |
20 | // 2.2 axios响应拦截
21 | instance.interceptors.response.use(res => {
22 | return res.data;
23 | }, err => {
24 | console.log(err);
25 | });
26 |
27 | // 3.发送真正的网络请求
28 | return instance(config);
29 |
30 | }
--------------------------------------------------------------------------------
/src/views/detail/childComps/DetailRecommend.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
27 |
32 |
--------------------------------------------------------------------------------
/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.21.0",
11 | "better-scroll": "^2.0.5",
12 | "core-js": "^3.6.5",
13 | "vue": "^2.6.11",
14 | "vue-lazyload": "^1.3.3",
15 | "vue-router": "^3.4.9",
16 | "vuex": "^3.5.1"
17 | },
18 | "devDependencies": {
19 | "@vue/cli-plugin-babel": "~4.5.0",
20 | "@vue/cli-service": "~4.5.0",
21 | "vue-template-compiler": "^2.6.11"
22 | },
23 | "browserslist": [
24 | "> 1%",
25 | "last 2 versions",
26 | "not dead"
27 | ]
28 | }
29 |
--------------------------------------------------------------------------------
/src/common/mixin.js:
--------------------------------------------------------------------------------
1 | import { debounce } from './utils';
2 |
3 | export const itemListenerMixin = {
4 | data() {
5 | return {
6 | imgItemListener: null, //控制首页商品图片以及详情页商品推荐列表加载显示的listener
7 | }
8 | },
9 | mounted() {
10 | const refresh = debounce(this.$refs.scroll.refresh, 500)
11 | this.imgItemListener = ()=>{
12 | refresh;
13 | }
14 | this.$bus.$on('itemImgLoad', this.imgItemListener);
15 | },
16 | }
17 |
18 | // 返回顶部图标德混入
19 | export const backTopMixin = {
20 | data(){
21 | return {
22 | isShowBackTop: false,
23 | }
24 | },
25 | methods: {
26 | backTopClick(){
27 | this.$refs.scroll.scrollTo(0,0,500);
28 | },
29 | },
30 | }
--------------------------------------------------------------------------------
/src/views/detail/childComps/DetailSwiper.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
28 |
29 |
34 |
35 |
--------------------------------------------------------------------------------
/src/store/actions.js:
--------------------------------------------------------------------------------
1 | import {
2 | ADD_TO_CART,
3 | ADD_TO_COUNTER
4 | } from './constant';
5 |
6 | export default {
7 | // 加入购物车
8 | addCart({state, commit}, payload){
9 | return new Promise((resolve, reject)=>{
10 | //1.查找之前数组中是否含有该商品
11 | let product = state.cartList.find((item)=> item.iid === payload.iid);
12 |
13 | //2. 判断product,这里涉及深拷贝与浅拷贝
14 | if(product){
15 | commit(ADD_TO_COUNTER, product);
16 | resolve('成功添加购物车num+1');
17 | }else {
18 | payload.num = 1;
19 | payload.isSelected = false;
20 | commit(ADD_TO_CART, payload);
21 | resolve('成功添加购物车');
22 | }
23 | })
24 | }
25 | }
--------------------------------------------------------------------------------
/src/assets/img/tabbar/profile.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/tabbar/home.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/tabbar/home_active.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/tabbar/profile_active.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/content/checkGoodsBtn/CheckGoodsBtn.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |

4 |
5 |
6 |
18 |
19 |
35 |
--------------------------------------------------------------------------------
/src/assets/img/tabbar/cart.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/tabbar/cart_active.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/views/category/childComps/CategorySideContentItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
![subcategory]()
4 |
{{subCategoryItem.title}}
5 |
6 |
7 |
8 |
27 |
28 |
38 |
39 |
--------------------------------------------------------------------------------
/src/views/category/childComps/CategorySideContent.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
28 |
36 |
37 |
--------------------------------------------------------------------------------
/src/views/home/childComps/RecommendView.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
![]()
5 |
{{item.title}}
6 |
7 |
8 |
9 |
10 |
23 |
24 |
42 |
--------------------------------------------------------------------------------
/src/views/home/childComps/HomeSwiper.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/network/detail.js:
--------------------------------------------------------------------------------
1 | import { request } from './request';
2 |
3 | export function getGoodsDetail(iid) {
4 | return request({
5 | url: '/detail',
6 | params: {
7 | iid
8 | },
9 | })
10 | }
11 |
12 | export function getGoodsRecommend(){
13 | return request({
14 | url:'/recommend'
15 | });
16 | }
17 |
18 | export class Goods{
19 | constructor(itemInfo, columns, services){
20 | this.iid = itemInfo.iid;
21 | this.title = itemInfo.title;
22 | this.desc = itemInfo.desc;
23 | this.newPrice = itemInfo.price;
24 | this.oldPrice = itemInfo.oldPrice;
25 | this.discount = itemInfo.discountDesc;
26 | this.columns = columns;
27 | this.services = services;
28 | this.realPrice = itemInfo.lowNowPrice;
29 | }
30 | }
31 |
32 | export class Shop{
33 | constructor(shopInfo){
34 | this.logo = shopInfo.shopLogo;
35 | this.name = shopInfo.name;
36 | this.fans = shopInfo.cFans;
37 | this.sells = shopInfo.cSells;
38 | this.score = shopInfo.score;
39 | this.goodsCount = shopInfo.cGoods;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/assets/css/base.css:
--------------------------------------------------------------------------------
1 | @import "./normalize.css";
2 |
3 | /* :root -> 获取根元素html */
4 | :root {
5 | --color-text: #666;
6 | --color-high-text: #ff5777;
7 | --color-tint: #ff8198;
8 | --color-background: #fff;
9 | --font-size: 14px;
10 | --line-height: 1.5;
11 | }
12 |
13 | *,
14 | *::before {
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 | -webkit-tap-highlight-color: transparent; /* webkit是苹果浏览器引擎,tap带年底,highlight背景高亮,color颜色,颜色用数值调节*/
24 | background: var(--color-background);
25 | /* rem vw/vh */
26 | width: 100vw;
27 | line-height: var(--line-height);
28 | }
29 |
30 | a {
31 | color: var(--color-text);
32 | text-decoration: none;
33 | }
34 |
35 | .clear-fix::after {
36 | clear: both;
37 | content: '';
38 | display: block;
39 | width: 0;
40 | height: 0;
41 | visibility: hidden;
42 | }
43 |
44 | .clear-fix {
45 | zoom: 1;
46 | }
47 |
48 | .left {
49 | float: left;
50 | }
51 |
52 | .right {
53 | float: right;
54 | }
--------------------------------------------------------------------------------
/src/components/common/toast/Toast.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{message}}
4 |
5 |
6 |
7 |
29 |
30 |
51 |
--------------------------------------------------------------------------------
/src/views/cart/childComps/CartList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
购物车居然是空的(°ο°)~ @
8 |
再忙,也记得买点什么犒赏自己
9 |
去逛逛
10 |
11 |
12 |
13 |
14 |
38 |
39 |
53 |
54 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Router from 'vue-router';
3 |
4 | // 在VUE中路由遇到Error: Avoided redundant navigation to current location:报错显示是路由重复
5 | const originalPush = Router.prototype.push;
6 | Router.prototype.push = function push(location) {
7 | return originalPush.call(this, location).catch(err => err);
8 | }
9 | Vue.use(Router);
10 |
11 | const Home = () => import('@/views/home/Home.vue');
12 | const Category = () => import('@/views/category/Category.vue');
13 | const Cart = () => import('@/views/cart/Cart.vue');
14 | const Profile = () => import('@/views/profile/Profile.vue');
15 | const Detail = () => import('@/views/detail/Detail.vue');
16 |
17 | const routes = [
18 | {
19 | path: '',
20 | redirect: '/home'
21 | },
22 | {
23 | path: '/home',
24 | component: Home,
25 | },
26 | {
27 | path: '/category',
28 | component: Category,
29 | },
30 | {
31 | path: '/cart',
32 | component: Cart,
33 | },
34 | {
35 | path: '/profile',
36 | component: Profile,
37 | },
38 | {
39 | path: '/detail/:iid',
40 | component: Detail,
41 | }
42 | ]
43 | const router = new Router({
44 | routes,
45 | mode: 'history',
46 | });
47 |
48 | export default router;
--------------------------------------------------------------------------------
/src/components/content/tabControl/TabControl.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 | {{item}}
9 |
10 |
11 |
12 |
13 |
37 |
38 |
58 |
59 |
--------------------------------------------------------------------------------
/src/components/content/goods/GoodsList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 |
46 |
47 |
55 |
--------------------------------------------------------------------------------
/src/assets/img/tabbar/category.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/tabbar/category_active.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/views/detail/childComps/DetailNavBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |

5 |
6 |
14 |
15 |
16 |
17 |
42 |
43 |
59 |
--------------------------------------------------------------------------------
/src/components/content/mainTabBar/MainTabBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 首页
7 |
8 |
9 |
10 |
11 | 分类
12 |
13 |
14 |
15 |
16 | 购物车
17 |
18 |
19 |
20 |
21 | 我的
22 |
23 |
24 |
25 |
26 |
38 |
--------------------------------------------------------------------------------
/src/views/cart/Cart.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 购物车({{cartListLength}})
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
50 |
51 |
64 |
--------------------------------------------------------------------------------
/src/views/detail/childComps/DetailGoodsInfo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{goodsInfo.desc}}
5 |
6 |
{{goodsInfo.detailImage[0].key}}
7 |
8 |
![goods-img]()
14 |
15 |
16 |
17 |
18 |
19 |
45 |
65 |
--------------------------------------------------------------------------------
/src/components/common/scroll/Scroll.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
65 |
66 |
--------------------------------------------------------------------------------
/src/views/category/childComps/CategorySideBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
53 |
69 |
70 |
--------------------------------------------------------------------------------
/src/views/detail/childComps/DetailGoodsParams.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
14 |
15 |
19 | | {{info.key}} |
20 | {{info.value}} |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
40 |
41 |
65 |
--------------------------------------------------------------------------------
/src/views/detail/childComps/DetailBottomBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 客服
7 |
8 |
9 |
10 | 店铺
11 |
12 |
13 |
14 | 收藏
15 |
16 |
17 |
21 |
22 |
23 |
24 |
34 |
35 |
82 |
--------------------------------------------------------------------------------
/src/components/content/goods/GoodsListItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
![goods-img]()
8 |
9 |
{{goodsItem.title}}
10 |
{{goodsItem.price}}
11 |
{{goodsItem.cfav}}
12 |
13 |
14 |
15 |
16 |
35 |
77 |
78 |
--------------------------------------------------------------------------------
/src/components/common/tabbar/TabBarItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
57 |
58 |
71 |
72 |
--------------------------------------------------------------------------------
/src/assets/img/common/collect.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/views/cart/childComps/CartListItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
![goods_img]()
6 |
7 |
8 |
{{goodsItem.title}}
9 |
{{goodsItem.desc}}
10 |
11 |
{{goodsItem.price}}
12 |
X{{goodsItem.num}}
13 |
14 |
15 |
16 |
17 |
18 |
41 |
42 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # supermall
2 |
3 | ### 1.项目简介
4 | > * 该项目为使用vue-cli4搭建的一个前后端分离的商城项目;
5 | > * 使用了Vue[包括混入mixin,过滤器filters相关等],Vuex,Vue-Router,ES6,Axios以及Webpack等前端技术;
6 | > * 主要包含商城首页,详情页,购物车,商品分类,个人中心等模块;
7 | > * 项目涉及vue-lazyload, better-scroll相关运用。
8 |
9 | ### 2. 通过项目能够学到什么
10 | > * 1)Vue,Vuex,Vue-Router,Axios,Webpack的熟悉使用,使用vue-cli脚手架工具初始化Vue项目;
11 | > * 2)组件封装(如轮播图,导航栏的统一封装等),模块化开发,工程化思想;
12 | > * 3)项目开发的基本流程以及调试方法(devtools的使用);
13 | > * 4)学会使用vue-lazyload实现图片懒加载,使用better-scroll实现页面的滚动效果等。
14 |
15 | ### 3. 项目部分截图展示
16 | ###### 1)首页部分
17 | > 主要包括5个部分:顶部导航栏,轮播图,分类,流行推荐,商品部分。
18 | >
19 | 
20 | 
21 |
22 | ###### 2)详情页部分
23 | > 主要包括7个部分:商品轮播图,商品信息,商家信息,商品图片,商品参数,商品评论以及推荐商品。
24 | >
25 | 
26 | 
27 |
28 | ###### 3)购物车部分
29 | > 主要包括2个部分:购物车商品以及结算:涉及的点为商品选中与全选的设置。
30 | >
31 | 
32 | 
33 |
34 | ###### 4)分类页
35 | > 主要包括左边的主分类与右边的子分类
36 | >
37 | 
38 | 
39 |
40 | ### 4.项目非常适合Vue实战练手,能够有效提升以及理解对Vue的综合运用以及组件化,模块开发以及工程化思想。
41 | > 如有帮助,请给一个star喔~
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/views/detail/childComps/DetailBaseInfo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{baseInfo.title}}
4 |
5 | {{baseInfo.newPrice}}
6 | {{baseInfo.oldPrice}}
7 | {{baseInfo.discount}}
8 |
9 |
10 | {{baseInfo.columns && baseInfo.columns[0]}}
11 | {{baseInfo.columns && baseInfo.columns[1]}}
12 | {{baseInfo.services && baseInfo.services[ baseInfo.services.length-1].name}}
13 |
14 |
15 |
16 |
17 | {{baseInfo.services[index-1].name}}
18 |
19 |
20 |
21 |
22 |
23 |
36 |
37 |
90 |
91 |
--------------------------------------------------------------------------------
/src/views/cart/childComps/CartBottomBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 全选
6 |
7 |
合计:¥{{totalPrice}}
8 |
去结算({{totalNum}})
9 |
10 |
11 |
12 |
63 |
64 |
93 |
--------------------------------------------------------------------------------
/src/views/category/Category.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 商品分类
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
73 |
103 |
104 |
--------------------------------------------------------------------------------
/src/views/detail/childComps/DetailCommentInfo.vue:
--------------------------------------------------------------------------------
1 |
2 |
32 |
33 |
34 |
80 |
81 |
124 |
--------------------------------------------------------------------------------
/src/views/detail/childComps/DetailShopInfo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
![logo]()
5 |
{{shopInfo.name}}
6 |
7 |
8 |
9 |
{{shopInfo.sells | bigNumberTransform}}
10 |
总销量
11 |
12 |
13 |
{{shopInfo.goodsCount}}
14 |
全部宝贝
15 |
16 |
17 |
18 |
19 | | {{item.name}} |
20 | {{item.score}} |
21 | {{item.isBetter?"高":"低"}} |
22 |
23 |
24 |
25 |
26 |
29 |
30 |
31 |
32 |
98 |
99 |
155 |
--------------------------------------------------------------------------------
/src/views/home/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 购物街
5 |
6 |
13 |
21 |
22 |
23 |
24 |
29 |
33 |
34 |
35 |
36 |
37 |
38 |
187 |
188 |
224 |
--------------------------------------------------------------------------------
/src/views/detail/Detail.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
178 |
179 |
203 |
--------------------------------------------------------------------------------
/src/components/common/swiper/Swiper.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
214 |
215 |
245 |
246 |
--------------------------------------------------------------------------------
/src/assets/css/normalize.css:
--------------------------------------------------------------------------------
1 | /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
2 |
3 | /* Document
4 | ========================================================================== */
5 |
6 | /**
7 | * 1. Correct the line height in all browsers.
8 | * 2. Prevent adjustments of font size after orientation changes in iOS.
9 | */
10 |
11 | html {
12 | line-height: 1.15; /* 1 */
13 | -webkit-text-size-adjust: 100%; /* 2 */
14 | }
15 |
16 | /* Sections
17 | ========================================================================== */
18 |
19 | /**
20 | * Remove the margin in all browsers.
21 | */
22 |
23 | body {
24 | margin: 0;
25 | }
26 |
27 | /**
28 | * Render the `main` element consistently in IE.
29 | */
30 |
31 | main {
32 | display: block;
33 | }
34 |
35 | /**
36 | * Correct the font size and margin on `h1` elements within `section` and
37 | * `article` contexts in Chrome, Firefox, and Safari.
38 | */
39 |
40 | h1 {
41 | font-size: 2em;
42 | margin: 0.67em 0;
43 | }
44 |
45 | /* Grouping content
46 | ========================================================================== */
47 |
48 | /**
49 | * 1. Add the correct box sizing in Firefox.
50 | * 2. Show the overflow in Edge and IE.
51 | */
52 |
53 | hr {
54 | box-sizing: content-box; /* 1 */
55 | height: 0; /* 1 */
56 | overflow: visible; /* 2 */
57 | }
58 |
59 | /**
60 | * 1. Correct the inheritance and scaling of font size in all browsers.
61 | * 2. Correct the odd `em` font sizing in all browsers.
62 | */
63 |
64 | pre {
65 | font-family: monospace, monospace; /* 1 */
66 | font-size: 1em; /* 2 */
67 | }
68 |
69 | /* Text-level semantics
70 | ========================================================================== */
71 |
72 | /**
73 | * Remove the gray background on active links in IE 10.
74 | */
75 |
76 | a {
77 | background-color: transparent;
78 | }
79 |
80 | /**
81 | * 1. Remove the bottom border in Chrome 57-
82 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
83 | */
84 |
85 | abbr[title] {
86 | border-bottom: none; /* 1 */
87 | text-decoration: underline; /* 2 */
88 | text-decoration: underline dotted; /* 2 */
89 | }
90 |
91 | /**
92 | * Add the correct font weight in Chrome, Edge, and Safari.
93 | */
94 |
95 | b,
96 | strong {
97 | font-weight: bolder;
98 | }
99 |
100 | /**
101 | * 1. Correct the inheritance and scaling of font size in all browsers.
102 | * 2. Correct the odd `em` font sizing in all browsers.
103 | */
104 |
105 | code,
106 | kbd,
107 | samp {
108 | font-family: monospace, monospace; /* 1 */
109 | font-size: 1em; /* 2 */
110 | }
111 |
112 | /**
113 | * Add the correct font size in all browsers.
114 | */
115 |
116 | small {
117 | font-size: 80%;
118 | }
119 |
120 | /**
121 | * Prevent `sub` and `sup` elements from affecting the line height in
122 | * all browsers.
123 | */
124 |
125 | sub,
126 | sup {
127 | font-size: 75%;
128 | line-height: 0;
129 | position: relative;
130 | vertical-align: baseline;
131 | }
132 |
133 | sub {
134 | bottom: -0.25em;
135 | }
136 |
137 | sup {
138 | top: -0.5em;
139 | }
140 |
141 | /* Embedded content
142 | ========================================================================== */
143 |
144 | /**
145 | * Remove the border on images inside links in IE 10.
146 | */
147 |
148 | img {
149 | border-style: none;
150 | }
151 |
152 | /* Forms
153 | ========================================================================== */
154 |
155 | /**
156 | * 1. Change the font styles in all browsers.
157 | * 2. Remove the margin in Firefox and Safari.
158 | */
159 |
160 | button,
161 | input,
162 | optgroup,
163 | select,
164 | textarea {
165 | font-family: inherit; /* 1 */
166 | font-size: 100%; /* 1 */
167 | line-height: 1.15; /* 1 */
168 | margin: 0; /* 2 */
169 | }
170 |
171 | /**
172 | * Show the overflow in IE.
173 | * 1. Show the overflow in Edge.
174 | */
175 |
176 | button,
177 | input { /* 1 */
178 | overflow: visible;
179 | }
180 |
181 | /**
182 | * Remove the inheritance of text transform in Edge, Firefox, and IE.
183 | * 1. Remove the inheritance of text transform in Firefox.
184 | */
185 |
186 | button,
187 | select { /* 1 */
188 | text-transform: none;
189 | }
190 |
191 | /**
192 | * Correct the inability to style clickable types in iOS and Safari.
193 | */
194 |
195 | button,
196 | [type="button"],
197 | [type="reset"],
198 | [type="submit"] {
199 | -webkit-appearance: button;
200 | }
201 |
202 | /**
203 | * Remove the inner border and padding in Firefox.
204 | */
205 |
206 | button::-moz-focus-inner,
207 | [type="button"]::-moz-focus-inner,
208 | [type="reset"]::-moz-focus-inner,
209 | [type="submit"]::-moz-focus-inner {
210 | border-style: none;
211 | padding: 0;
212 | }
213 |
214 | /**
215 | * Restore the focus styles unset by the previous rule.
216 | */
217 |
218 | button:-moz-focusring,
219 | [type="button"]:-moz-focusring,
220 | [type="reset"]:-moz-focusring,
221 | [type="submit"]:-moz-focusring {
222 | outline: 1px dotted ButtonText;
223 | }
224 |
225 | /**
226 | * Correct the padding in Firefox.
227 | */
228 |
229 | fieldset {
230 | padding: 0.35em 0.75em 0.625em;
231 | }
232 |
233 | /**
234 | * 1. Correct the text wrapping in Edge and IE.
235 | * 2. Correct the color inheritance from `fieldset` elements in IE.
236 | * 3. Remove the padding so developers are not caught out when they zero out
237 | * `fieldset` elements in all browsers.
238 | */
239 |
240 | legend {
241 | box-sizing: border-box; /* 1 */
242 | color: inherit; /* 2 */
243 | display: table; /* 1 */
244 | max-width: 100%; /* 1 */
245 | padding: 0; /* 3 */
246 | white-space: normal; /* 1 */
247 | }
248 |
249 | /**
250 | * Add the correct vertical alignment in Chrome, Firefox, and Opera.
251 | */
252 |
253 | progress {
254 | vertical-align: baseline;
255 | }
256 |
257 | /**
258 | * Remove the default vertical scrollbar in IE 10+.
259 | */
260 |
261 | textarea {
262 | overflow: auto;
263 | }
264 |
265 | /**
266 | * 1. Add the correct box sizing in IE 10.
267 | * 2. Remove the padding in IE 10.
268 | */
269 |
270 | [type="checkbox"],
271 | [type="radio"] {
272 | box-sizing: border-box; /* 1 */
273 | padding: 0; /* 2 */
274 | }
275 |
276 | /**
277 | * Correct the cursor style of increment and decrement buttons in Chrome.
278 | */
279 |
280 | [type="number"]::-webkit-inner-spin-button,
281 | [type="number"]::-webkit-outer-spin-button {
282 | height: auto;
283 | }
284 |
285 | /**
286 | * 1. Correct the odd appearance in Chrome and Safari.
287 | * 2. Correct the outline style in Safari.
288 | */
289 |
290 | [type="search"] {
291 | -webkit-appearance: textfield; /* 1 */
292 | outline-offset: -2px; /* 2 */
293 | }
294 |
295 | /**
296 | * Remove the inner padding in Chrome and Safari on macOS.
297 | */
298 |
299 | [type="search"]::-webkit-search-decoration {
300 | -webkit-appearance: none;
301 | }
302 |
303 | /**
304 | * 1. Correct the inability to style clickable types in iOS and Safari.
305 | * 2. Change font properties to `inherit` in Safari.
306 | */
307 |
308 | ::-webkit-file-upload-button {
309 | -webkit-appearance: button; /* 1 */
310 | font: inherit; /* 2 */
311 | }
312 |
313 | /* Interactive
314 | ========================================================================== */
315 |
316 | /*
317 | * Add the correct display in Edge, IE 10+, and Firefox.
318 | */
319 |
320 | details {
321 | display: block;
322 | }
323 |
324 | /*
325 | * Add the correct display in all browsers.
326 | */
327 |
328 | summary {
329 | display: list-item;
330 | }
331 |
332 | /* Misc
333 | ========================================================================== */
334 |
335 | /**
336 | * Add the correct display in IE 10+.
337 | */
338 |
339 | template {
340 | display: none;
341 | }
342 |
343 | /**
344 | * Add the correct display in IE 10.
345 | */
346 |
347 | [hidden] {
348 | display: none;
349 | }
--------------------------------------------------------------------------------