├── public
├── favicon.ico
└── index.html
├── src
├── assets
│ ├── logo.png
│ ├── css
│ │ ├── reset.less
│ │ ├── base.css
│ │ └── normalize.css
│ └── img
│ │ ├── common
│ │ ├── normal.svg
│ │ ├── yes.svg
│ │ ├── check.svg
│ │ ├── down.svg
│ │ ├── back.svg
│ │ ├── success.svg
│ │ ├── warning.svg
│ │ ├── heart.svg
│ │ ├── shop_bag.svg
│ │ ├── message.svg
│ │ ├── vip.svg
│ │ ├── cust.svg
│ │ ├── fail.svg
│ │ ├── un_heart.svg
│ │ ├── shop.svg
│ │ ├── setting.svg
│ │ ├── code.svg
│ │ ├── GitHub.svg
│ │ └── top.svg
│ │ ├── profile
│ │ ├── in.svg
│ │ ├── w_send.svg
│ │ ├── phone.svg
│ │ ├── w_pay.svg
│ │ ├── w_comment.svg
│ │ ├── w_recovery.svg
│ │ ├── portrait.svg
│ │ ├── w_refund.svg
│ │ ├── foot.svg
│ │ └── coupon.svg
│ │ └── tabbar
│ │ ├── home.svg
│ │ ├── home_active.svg
│ │ ├── profile.svg
│ │ ├── profile_active.svg
│ │ ├── category.svg
│ │ ├── category_active.svg
│ │ ├── shopcart.svg
│ │ └── shopcart_active.svg
├── components
│ ├── common
│ │ ├── swiper
│ │ │ ├── index.js
│ │ │ ├── SwiperItem.vue
│ │ │ └── Swiper.vue
│ │ ├── tabbar
│ │ │ ├── TabBar.vue
│ │ │ └── TabBarItem.vue
│ │ ├── navbar
│ │ │ └── NavBar.vue
│ │ ├── toast
│ │ │ ├── index.js
│ │ │ ├── CustToast.vue
│ │ │ └── Toast.vue
│ │ └── scroll
│ │ │ └── scroll.vue
│ ├── content
│ │ ├── backTop
│ │ │ └── BackTop.vue
│ │ ├── tabControl
│ │ │ └── TabControl.vue
│ │ └── mainTabbar
│ │ │ └── MainTabBar.vue
│ └── HelloWorld.vue
├── api
│ ├── detail.js
│ ├── index.js
│ ├── category.js
│ └── home.js
├── utils
│ ├── url.js
│ ├── public.js
│ └── request.js
├── common
│ └── mixin.js
├── config
│ └── index.js
├── main.js
├── views
│ ├── detail
│ │ ├── childComps
│ │ │ ├── GoodsStyleInfo.vue
│ │ │ ├── SaleInfo.vue
│ │ │ ├── DetailSwiper.vue
│ │ │ ├── LogisticsInfo.vue
│ │ │ ├── GoodsDisplay.vue
│ │ │ ├── DiscountInfo.vue
│ │ │ ├── BaseInfo.vue
│ │ │ ├── DetailTabBar.vue
│ │ │ ├── ShopInfo.vue
│ │ │ ├── BottomBar.vue
│ │ │ └── CommentInfo.vue
│ │ └── Detail.vue
│ ├── category
│ │ ├── childComps
│ │ │ ├── GoodsLIst.vue
│ │ │ ├── LeftBar.vue
│ │ │ ├── TabBar.vue
│ │ │ └── GoodListItem.vue
│ │ └── Category.vue
│ ├── home
│ │ ├── childComps
│ │ │ ├── GoodsLIst.vue
│ │ │ ├── FeatureView.vue
│ │ │ ├── HomeSwiper.vue
│ │ │ ├── RecommendView.vue
│ │ │ ├── SwiperView.vue
│ │ │ └── GoodListItem.vue
│ │ └── Home.vue
│ ├── profile
│ │ ├── Profile.vue
│ │ └── childComps
│ │ │ ├── TabView.vue
│ │ │ ├── UserView.vue
│ │ │ ├── FeatureView.vue
│ │ │ └── OrderView.vue
│ ├── shopcart
│ │ ├── childComps
│ │ │ ├── DelBottomBar.vue
│ │ │ ├── SettleBottomBar.vue
│ │ │ └── ShopListItem.vue
│ │ └── ShopCart.vue
│ └── demo
│ │ └── Demo.vue
├── App.vue
├── router
│ └── index.js
└── store
│ └── index.js
├── babel.config.js
├── vue.config.js
├── .gitignore
├── package.json
├── DEPLOYMENT.md
└── README.md
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wxy2077/Mall/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wxy2077/Mall/HEAD/src/assets/logo.png
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/cli-plugin-babel/preset'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/src/components/common/swiper/index.js:
--------------------------------------------------------------------------------
1 | import Swiper from './Swiper'
2 | import SwiperItem from './SwiperItem'
3 |
4 | export {
5 | Swiper, SwiperItem
6 | }
7 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 |
2 | // 参考 https://cli.vuejs.org/zh/guide/deployment.html#github-pages
3 | module.exports = {
4 | publicPath: process.env.NODE_ENV === 'production'
5 | ? '/app/mall/'
6 | : '/',
7 | };
8 |
--------------------------------------------------------------------------------
/src/api/detail.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | *
4 | * 请求详情页内容
5 | * */
6 |
7 |
8 | import request from '@/utils/request'
9 |
10 | // 获取首页信息
11 | export function GoodsDetail(data) {
12 | return request(
13 | '/goods/detail',
14 | "POST",
15 | data,
16 | )
17 | }
18 |
19 |
20 |
--------------------------------------------------------------------------------
/.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 | pnpm-debug.log*
14 |
15 | # Editor directories and files
16 | .idea
17 | .vscode
18 | *.suo
19 | *.ntvs*
20 | *.njsproj
21 | *.sln
22 | *.sw?
23 |
--------------------------------------------------------------------------------
/src/api/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 汇总所有的接口
3 | * Author: CoderCharm
4 | * Time: 2020/06/11
5 | *
6 | */
7 | import * as home from './home';
8 | import * as detail from './detail';
9 | import * as category from './category';
10 |
11 |
12 | export default {
13 |
14 | home, //首页
15 | detail, // 详情页
16 | category, // 详情页
17 | }
18 |
--------------------------------------------------------------------------------
/src/utils/url.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * 封装url路由前缀
4 | * 后面扩展版本区分 可以更改这里
5 | * */
6 |
7 | import { appConfig } from '@/config'
8 |
9 | export default function concatUrl(e) {
10 | let url;
11 | // url = `${appConfig[process.env.NODE_ENV]}/api/leaf/mall${e}`;
12 | url = `${appConfig[process.env.NODE_ENV]}/api/v1${e}`;
13 | return url;
14 | }
15 |
--------------------------------------------------------------------------------
/src/common/mixin.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | *
4 | * 公共的混入对象
5 | * */
6 |
7 |
8 | // 返回到顶部
9 | export const backTopMixin = {
10 | data: function () {
11 | return {
12 | showBackTop: false
13 | }
14 | },
15 | methods: {
16 | backTop: function () {
17 | this.$refs.scroll.scrollTo(0, 0, 300);
18 | }
19 | }
20 | };
21 |
--------------------------------------------------------------------------------
/src/config/index.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | *
4 | * 自定义的一些配置信息,在main.js 通过prototype挂载到vue对象
5 | *
6 | * */
7 |
8 | export let appConfig = {
9 | development: 'http://127.0.0.1:8010',
10 | production: '',
11 | cookieTime: {
12 | refreshToken: 60 * 60 * 24 * 7, // refreshToken 存在7天
13 | accessToken: 60 * 60 // accessToken 存在1小时
14 | }
15 | };
16 |
--------------------------------------------------------------------------------
/src/components/common/swiper/SwiperItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
23 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 | import store from './store'
4 | import router from './router'
5 |
6 | Vue.config.productionTip = false;
7 |
8 | import showToast from '@/components/common/toast/index'
9 |
10 | Vue.use(showToast);
11 |
12 | new Vue({
13 | store,
14 | router,
15 | render: h => h(App)
16 | }).$mount('#app');
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/components/common/tabbar/TabBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
15 |
16 |
27 |
--------------------------------------------------------------------------------
/src/api/category.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | *
4 | * 请求分类数据
5 | * */
6 |
7 |
8 | import request from '@/utils/request'
9 |
10 | // 获取侧边栏分类
11 | export function getCategory() {
12 | return request(
13 | '/category',
14 | "GET",
15 | )
16 | }
17 |
18 |
19 | // 获取对应分类tabBar
20 | export function getTabBar(data) {
21 | return request(
22 | '/category/tab',
23 | "GET",
24 | data
25 | )
26 | }
27 |
28 | // 获取对应分类tabBar
29 | export function getGoods(data) {
30 | return request(
31 | '/category/goods',
32 | "POST",
33 | data
34 | )
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/src/assets/css/reset.less:
--------------------------------------------------------------------------------
1 | @charset "utf-8";
2 | html,
3 | body,
4 | div,
5 | dl,
6 | dt,
7 | dd,
8 | ul,
9 | ol,
10 | li,
11 | h2,
12 | h2,
13 | h3,
14 | pre,
15 | code,
16 | form,
17 | fieldset,
18 | legend,
19 | input,
20 | button,
21 | textarea,
22 | p,
23 | blockquote,
24 | th,
25 | td,
26 | section,
27 | article,
28 | aside,
29 | header,
30 | footer,
31 | nav,
32 | dialog,
33 | figure,
34 | figcaption,
35 | hgroup {
36 | margin: 0;
37 | padding: 0;
38 | }
39 |
40 | body {
41 | width: 100%;
42 | height: 100%;
43 | position: relative;
44 | overflow-x: hidden;
45 | }
46 | html{
47 | width: 100%;
48 | height: 100%;
49 | }
50 | ul,
51 | li,
52 | ol {
53 | list-style: none;
54 | }
--------------------------------------------------------------------------------
/src/assets/img/common/normal.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/content/backTop/BackTop.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
![]()
5 |
6 |
7 |
8 |
18 |
19 |
32 |
--------------------------------------------------------------------------------
/src/views/detail/childComps/GoodsStyleInfo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 请选择: 颜色 尺码
6 | >
7 |
8 |
9 |
10 |
18 |
19 |
31 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= htmlWebpackPlugin.options.title %>
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/views/detail/childComps/SaleInfo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 销量:{{ salesVolume }}
6 | 收藏:{{ salesCollect }}人
7 | {{ salesDeliver }}
8 |
9 |
10 |
11 |
20 |
21 |
31 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
21 |
22 |
31 |
--------------------------------------------------------------------------------
/src/components/HelloWorld.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ msg }}
4 |
5 | For a guide and recipes on how to configure / customize this project,
6 | check out the
7 | vue-cli documentation.
8 |
9 |
10 |
11 |
12 |
20 |
21 |
22 |
38 |
--------------------------------------------------------------------------------
/src/assets/img/profile/in.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/common/yes.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/api/home.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | *
4 | * 请求首页内容
5 | * */
6 |
7 |
8 | import request from '@/utils/request'
9 |
10 | // 获取首页信息
11 | export function GetBanner() {
12 | return request(
13 | '/home/banner',
14 | "get",
15 | )
16 | }
17 |
18 |
19 | // 获取首页 features 信息
20 | export function GetFeatures() {
21 | return request(
22 | '/home/features',
23 | "get",
24 | )
25 | }
26 |
27 |
28 | // 获取首页 recommends 信息
29 | export function GetRecommends() {
30 | return request(
31 | '/home/recommends',
32 | "get",
33 | )
34 | }
35 |
36 |
37 | // 获取首页 tab信息
38 | export function GetTab() {
39 | return request(
40 | '/home/tab',
41 | "get",
42 | )
43 | }
44 |
45 | // 获取首页goods信息
46 | export function GetGoods(data={}) {
47 | return request(
48 | '/home/goods',
49 | "get",
50 | data
51 | )
52 | }
53 |
54 |
55 |
--------------------------------------------------------------------------------
/src/views/category/childComps/GoodsLIst.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
31 |
32 |
41 |
--------------------------------------------------------------------------------
/src/views/home/childComps/GoodsLIst.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
29 |
30 |
39 |
--------------------------------------------------------------------------------
/src/components/common/navbar/NavBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
17 |
18 |
39 |
--------------------------------------------------------------------------------
/src/assets/img/common/check.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/utils/public.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * 公共的工具类
4 | * */
5 |
6 | // export function debounce(fn, delay=5000) {
7 | // // 记录上一次的延时器
8 | // var timer = null;
9 | //
10 | // return function () {
11 | // var args = arguments;
12 | // var that = this;
13 | // // 清除上一次延时器
14 | // clearTimeout(timer);
15 | // timer = setTimeout(function () {
16 | // fn.apply(that, args)
17 | // }, delay);
18 | // }
19 | // }
20 |
21 | // 防抖函数
22 | export function debounce(fn, delay) {
23 |
24 | delay = delay || 200;
25 | var timer;
26 | return function () {
27 | var th = this;
28 | var args = arguments;
29 | if (timer) {
30 | clearTimeout(timer);
31 | }
32 | window.console.log("防抖111111");
33 | timer = setTimeout(function () {
34 | timer = null;
35 | window.console.log("防抖了");
36 | fn.apply(th, args);
37 | }, delay);
38 | };
39 | }
40 |
--------------------------------------------------------------------------------
/src/assets/img/profile/w_send.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/profile/phone.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/tabbar/home.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/tabbar/home_active.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/common/down.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/views/detail/childComps/DetailSwiper.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
![]()
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
35 |
36 |
46 |
--------------------------------------------------------------------------------
/src/views/detail/childComps/LogisticsInfo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
{{ item }}
6 |
7 |
8 |
>
9 |
10 |
11 |
12 |
27 |
28 |
45 |
--------------------------------------------------------------------------------
/src/components/common/toast/index.js:
--------------------------------------------------------------------------------
1 | //
2 | import vue from 'vue'
3 |
4 | // 导入自定义到Toast组件
5 | import CustToast from './CustToast.vue'
6 |
7 |
8 | // 生成一个扩展实例构造器
9 | const ToastConstructor = vue.extend(CustToast);
10 |
11 | // 定义弹出组件的函数 接收三个参数 消息 toast类型 显示时间
12 | function showToast(message, type="normal", duration = 2000) {
13 |
14 | // 实例化一个 CustToast.vue
15 | const _toast = new ToastConstructor({
16 | data() {
17 | return {
18 | showToast: true,
19 | type: type,
20 | message: message,
21 | duration: duration
22 | }
23 | }
24 | });
25 |
26 | // 把实例化的 CustToast.vue 添加到 body 里
27 | let element = _toast.$mount().$el;
28 | document.body.appendChild(element);
29 |
30 | // duration时间到了后隐藏
31 | setTimeout(() => {_toast.showToast = false} ,duration)
32 | }
33 |
34 | // 需要在main.js 里面使用 Vue.use(showToast);
35 | showToast.install = (Vue) => {
36 | // 将组件注册到 vue 的 原型链里去,
37 | // 这样就可以在所有 vue 的实例里面使用 this.$toast()
38 | Vue.prototype.$toast = showToast
39 | };
40 |
41 | // 导出
42 | export default showToast
43 |
--------------------------------------------------------------------------------
/src/assets/img/common/back.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/views/home/childComps/FeatureView.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
26 |
27 |
48 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mall",
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.2",
12 | "better-scroll": "^1.15.2",
13 | "core-js": "^3.6.5",
14 | "swiper": "^5.4.5",
15 | "vue": "^2.6.11",
16 | "vue-awesome-swiper": "^4.1.1",
17 | "vue-router": "^3.3.1",
18 | "vuex": "^3.4.0"
19 | },
20 | "devDependencies": {
21 | "@vue/cli-plugin-babel": "^4.4.0",
22 | "@vue/cli-plugin-eslint": "^4.4.0",
23 | "@vue/cli-service": "^4.4.0",
24 | "babel-eslint": "^10.1.0",
25 | "eslint": "^5.1.0",
26 | "eslint-plugin-vue": "^6.2.2",
27 | "vue-template-compiler": "^2.6.11"
28 | },
29 | "eslintConfig": {
30 | "root": true,
31 | "env": {
32 | "node": true
33 | },
34 | "extends": [
35 | "plugin:vue/essential",
36 | "eslint:recommended"
37 | ],
38 | "parserOptions": {
39 | "parser": "babel-eslint"
40 | },
41 | "rules": {}
42 | },
43 | "browserslist": [
44 | "> 1%",
45 | "last 2 versions",
46 | "not dead"
47 | ]
48 | }
49 |
--------------------------------------------------------------------------------
/src/assets/img/common/success.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/common/warning.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/common/heart.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/profile/w_pay.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/views/category/childComps/LeftBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 | {{ item.cate_name }}
11 |
12 |
13 |
14 |
15 |
16 |
39 |
40 |
56 |
--------------------------------------------------------------------------------
/src/assets/img/common/shop_bag.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 |
2 | import Vue from 'vue'
3 | import VueRouter from 'vue-router'
4 |
5 | // 路由懒加载 用到才请求
6 | const Home = () => import('@/views/home/Home');
7 | const Category = () => import('@/views/category/Category');
8 | const Cart = () => import('@/views/shopcart/ShopCart');
9 | const Profile = () => import('@/views/profile/Profile');
10 |
11 | // 1.安装VueRouter
12 | Vue.use(VueRouter);
13 |
14 | // 2.配置路由信息
15 | const routes = [
16 | {
17 | path: '/',
18 | redirect: '/home'
19 | },
20 | {
21 | path: '/home',
22 | component: Home,
23 | meta:{
24 |
25 | }
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: '/demo',
41 | name: "Demo",
42 | component: () => import('@/views/demo/Demo'),
43 | },
44 | {
45 | path: '/detail',
46 | name: "Detail",
47 | component: () => import('@/views/detail/Detail'),
48 | }
49 | ];
50 |
51 | // 3.创建路由对象
52 | const router = new VueRouter({
53 | base: '/app/mall',
54 | routes,
55 | mode: 'history'
56 | });
57 |
58 | // 路由拦截
59 | router.beforeEach((to, from, next) =>{
60 | next()
61 | });
62 |
63 | // 4.导出
64 | export default router
65 |
--------------------------------------------------------------------------------
/src/views/home/childComps/HomeSwiper.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
44 |
45 |
56 |
--------------------------------------------------------------------------------
/src/assets/img/common/message.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/css/base.css:
--------------------------------------------------------------------------------
1 | @import "./normalize.css";
2 |
3 | :root {
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 | -webkit-tap-highlight-color: transparent; /* webkit是苹果浏览器引擎,tap点击,highlight背景高亮,color颜色,颜色用数值调节 */
24 | background: var(--color-background);
25 | color: var(--color-text);
26 | width: 100vw;
27 | }
28 |
29 | a {
30 | color: var(--color-text);
31 | text-decoration: none;
32 | }
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 | .arrow-right {
49 | border-top: 1px solid #999;
50 | border-left: 1px solid #999;
51 | width: 9px;
52 | height: 9px;
53 | background-color: transparent;
54 | transform: rotate(135deg);
55 | display: inline-block;
56 | margin-left: .1rem;
57 | }
58 |
59 | /*.left {*/
60 | /*float: left;*/
61 | /*}*/
62 |
63 | /*.right {*/
64 | /*float: right;*/
65 | /*}*/
--------------------------------------------------------------------------------
/src/assets/img/profile/w_comment.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/views/profile/Profile.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 个人中心
5 |
6 |
![]()
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
50 |
51 |
66 |
--------------------------------------------------------------------------------
/src/assets/img/profile/w_recovery.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/views/category/childComps/TabBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 | {{ item.tab_name }}
11 |
12 |
13 |
14 |
15 |
16 |
17 |
40 |
41 |
63 |
--------------------------------------------------------------------------------
/src/views/home/childComps/RecommendView.vue:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
29 |
30 |
61 |
--------------------------------------------------------------------------------
/src/views/detail/childComps/GoodsDisplay.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{ goodsDesc }}
8 |
9 |
穿着效果
10 |
11 |
![]()
12 |
13 |
14 |
15 |
16 |
17 |
34 |
35 |
65 |
--------------------------------------------------------------------------------
/src/components/content/tabControl/TabControl.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 | {{ item.tabName }}
10 |
11 |
12 |
13 |
14 |
36 |
37 |
65 |
--------------------------------------------------------------------------------
/src/assets/img/common/vip.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/common/cust.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/common/fail.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/views/home/childComps/SwiperView.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
48 |
49 |
59 |
--------------------------------------------------------------------------------
/src/views/profile/childComps/TabView.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
27 |
28 |
29 |
37 |
38 |
70 |
--------------------------------------------------------------------------------
/src/components/common/tabbar/TabBarItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
50 |
51 |
69 |
--------------------------------------------------------------------------------
/src/assets/img/profile/portrait.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/views/detail/childComps/DiscountInfo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 优惠
6 | 店铺优惠券
7 |
8 | {{ item }}
9 |
10 | 领券>
11 |
12 |
13 | 促销
14 | 满减
15 |
16 | {{ item }}
17 |
18 | 更多>
19 |
20 |
21 |
22 |
23 |
24 |
25 |
43 |
44 |
72 |
--------------------------------------------------------------------------------
/src/views/home/childComps/GoodListItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
![]()
4 |
5 |
{{ goods.title | cutTitle }}
6 |
¥{{ goods.price }}
7 |
✨ {{ goods.collection }}
8 |
9 |
10 |
11 |
12 |
47 |
48 |
73 |
--------------------------------------------------------------------------------
/src/views/category/childComps/GoodListItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
![]()
4 |
5 |
{{ goods.title | cutTitle }}
6 |
¥{{ goods.price }}
7 |
✨ {{ goods.collection }}
8 |
9 |
10 |
11 |
12 |
13 |
48 |
49 |
74 |
--------------------------------------------------------------------------------
/src/views/profile/childComps/UserView.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
![]()
6 |
7 |
8 |
9 | 登录/注册
10 |
11 |
12 |
![]()
13 |
未绑定手机号
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
34 |
35 |
81 |
--------------------------------------------------------------------------------
/src/views/detail/childComps/BaseInfo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{ title }}
8 |
9 |
10 |
11 | {{ price | addMoney }}
12 | {{ oldPrice| addMoney }}
13 | 活动价
14 |
15 |
16 |
17 |
18 |
19 |
44 |
45 |
92 |
--------------------------------------------------------------------------------
/src/views/detail/childComps/DetailTabBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
![]()
5 |
6 |
7 |
12 | {{item }}
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
52 |
53 |
79 |
--------------------------------------------------------------------------------
/src/assets/img/common/un_heart.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/views/profile/childComps/FeatureView.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
![]()
7 |
8 |
9 | 关注店铺
10 |
11 |
12 | 0
13 |
14 |
15 |
16 |
17 |
![]()
18 |
19 |
20 | 收藏
21 |
22 |
23 | 0
24 |
25 |
26 |
27 |
28 |
![]()
29 |
30 |
31 | 足迹
32 |
33 |
34 | 0
35 |
36 |
37 |
38 |
39 |
![]()
40 |
41 |
42 | 优惠卷
43 |
44 |
45 | 0
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
63 |
64 |
88 |
--------------------------------------------------------------------------------
/src/views/detail/childComps/ShopInfo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
![]()
6 |
7 |
{{ shopInfo.shopName }}
8 |
9 | 进店 >
10 |
11 |
12 | ⭐️⭐⭐⭐⭐ | 在线商品{{ shopInfo.goodsNum | dataFormat }}
13 |
14 |
15 |
16 | {{ shopInfo.follow | dataFormat }}人关注
17 | 累计销量{{ shopInfo.cumulativeSales | dataFormat }}+
18 | 五星好店
19 |
20 |
21 |
22 |
23 |
24 |
25 |
52 |
53 |
84 |
--------------------------------------------------------------------------------
/src/views/shopcart/childComps/DelBottomBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
11 |
全选
12 |
13 |
14 |
15 |
16 |
17 | 删除
18 |
19 |
20 |
21 |
22 |
41 |
42 |
92 |
--------------------------------------------------------------------------------
/src/components/common/scroll/scroll.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
79 |
80 |
83 |
--------------------------------------------------------------------------------
/src/assets/img/profile/w_refund.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/tabbar/profile.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/tabbar/profile_active.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/views/detail/childComps/BottomBar.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 |
28 |
29 |
30 |
31 |
47 |
48 |
99 |
--------------------------------------------------------------------------------
/src/components/common/toast/CustToast.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
11 | {{ message }}
12 |
13 |
14 |
15 |
16 |
47 |
48 |
96 |
--------------------------------------------------------------------------------
/src/assets/img/common/shop.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/content/mainTabbar/MainTabBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | {{ item.title }}
item.activeIcon
9 |
10 |
11 |
12 |
13 |
14 |
15 |
65 |
66 |
76 |
--------------------------------------------------------------------------------
/src/assets/img/profile/foot.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/views/demo/Demo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Vuex练习学习
4 |
5 |
显示: {{ $store.state.counter }}
6 |
7 |
8 |
9 |
10 |
11 |
{{ $store.state.info }}
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
当前请求: {{ currentPage }}
20 |
21 |
22 |
23 |
24 |
91 |
92 |
98 |
--------------------------------------------------------------------------------
/DEPLOYMENT.md:
--------------------------------------------------------------------------------
1 |
2 | ## 关于本项目的线上部署
3 |
4 | > nginx 多静态文件部署。
5 | > 我个人博客项目占用了`nginx`根路径,而我只有一个域名,也不准备用二级域名了, 所以就直接用路径区分开。
6 | > 一个域名,只部署一个静态文件服务,那很简单,只用把打包后文件放上去就行。
7 | > 多个Vue项目主要就是路径问题,静态js文件以及自定义的路由。
8 |
9 | #### 环境
10 |
11 | - vue 2.6.11
12 | - vue-router 3.3.1
13 | - vue-cli 4.4.0
14 |
15 | 由于我用的vue-cli 4,所以项目根路径下默认没有 `vue.config.js`文件, 我在官网看到关于这个vue.config.js是这样描述的.
16 |
17 | - 参考[官网说明](https://cli.vuejs.org/zh/config/)https://cli.vuejs.org/zh/config/:
18 | >有些针对 @vue/cli 的全局配置,例如你惯用的包管理器和你本地保存的 preset,都保存在 home 目录下一个名叫 .vuerc 的 JSON 文件。你可以用编辑器直接编辑这个文件来更改已保存的选项。
19 | 你也可以使用 vue config 命令来审查或修改全局的 CLI 配置
20 |
21 | ## 添加配置`vue.config.js` 文件 静态资源路由js,css等路径
22 | 但是 vue config 是全局的配置,我这个项目直接修改这里不合适,于是我就在项目 `根路径` 下自己手动添加了`vue.config.js`
23 |
24 | ```javascript
25 |
26 | // 参考 https://cli.vuejs.org/zh/guide/deployment.html#github-pages
27 | module.exports = {
28 | publicPath: process.env.NODE_ENV === 'production'
29 | ? '/app/mall/' // /app/mall/ 对应后面`nginx`路径,这里添加的目的是其他静态资源文件统一前缀路径
30 | : '/',
31 | };
32 | ```
33 | ## 修改src/router/index.js, 项目页面跳转路由
34 |
35 | ```javascript
36 | const router = new VueRouter({
37 | base: '/app/mall', // 主要添加这个 /app/mall 注意这个 和上面的一致,为nginx location路径, 也就是请求路径
38 | routes,
39 | mode: 'history'
40 | });
41 |
42 | ```
43 | ## 修改 src/config/index.js 项目生产请求地址(非必要)
44 | > 非必要,这个地方每个人封装的都不一样,默认会请求 部署的环境地址。
45 |
46 | ```javascript
47 | export let appConfig = {
48 | development: 'http://127.0.0.1:8010', // 本地开发 (ps:vue-cli会自动帮我们区分生产开发,npm run serve就是开发,
49 | production: 'https://www.your_domain.com', // 生产地址 npm run build 默认为生产
50 | };
51 |
52 | ```
53 |
54 | > 然后 我是在src/utils/url.js 文件里面 区分前缀的, 最后在 src/utils/request.js 文件里面使用。
55 |
56 | 修改好之后,可以`npm run serve`看看,区分好之后能否正常访问,是否有改错。
57 | 没有改错可以直接`npm run build` 生成静态文件
58 |
59 | ## 上传静态文件
60 | > 我是通过`FillZilla`上传静态资源文件
61 |
62 | 我是上传到服务器 `/data/mall/` 文件夹下, 记住这个文件路径, 后面nginx会指向这里。
63 |
64 |
65 | ## nginx 文件配置
66 |
67 | > Centos7 nginx默认配置地址为 `/etc/nginx/nginx.conf`
68 | 或者有的版本默认引入 `/etc/nginx/conf.d/default.conf`文件 配置
69 |
70 | ```
71 |
72 | server {
73 |
74 | listen 80;
75 | server_name localhost;
76 |
77 | #charset koi8-r;
78 | #access_log /var/log/nginx/host.access.log main;
79 |
80 | # ...
81 | location / {
82 | root /usr/share/nginx/html;
83 | index index.html index.htm;
84 | }
85 |
86 |
87 | # 添加文件
88 | # /app/mall 项目访问路径和上面地址对应
89 | location /app/mall/ {
90 | alias /data/mall/; # 项目存放路径
91 | try_files $uri $uri/ /app/mall/index.html; # 内部项目跳转路径
92 | }
93 |
94 | }
95 |
96 | ```
97 |
98 | 检测配置是否有语法错误
99 | ```
100 | nginx -t
101 |
102 | ```
103 | 重新加载配置
104 | ```
105 | nginx -s reload
106 |
107 | ```
108 |
109 | ## 个人项目部署地址
110 | 项目进度
111 | - 完成首页,分类页,购物车等页面,还差个人中心(2020/06/30)
112 |
113 | https://www.charmcode.cn/app/mall/home
114 |
115 | > PC端, Google浏览器需要F12 点击切换移动设备
116 |
117 |
118 |
119 |
120 |
121 |
--------------------------------------------------------------------------------
/src/assets/img/common/setting.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/tabbar/category.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/views/shopcart/childComps/SettleBottomBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
11 |
12 |
全选
13 |
14 |
15 | 合计: ¥{{ totalMoney }}
16 |
17 |
18 | 结算
19 |
20 |
21 |
22 |
23 |
67 |
68 |
121 |
--------------------------------------------------------------------------------
/src/assets/img/tabbar/category_active.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/views/shopcart/ShopCart.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 购物车({{ cartCount }})
5 | {{ state.text }}
6 |
7 |
8 |
9 |
10 |
11 |
18 |
19 |
20 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
99 |
100 |
103 |
--------------------------------------------------------------------------------
/src/assets/img/common/code.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/common/toast/Toast.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 | {{ message }}
9 |
10 |
11 |
12 |
75 |
76 |
124 |
--------------------------------------------------------------------------------
/src/assets/img/common/GitHub.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/views/detail/childComps/CommentInfo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
48 |
49 |
50 |
58 |
59 |
117 |
--------------------------------------------------------------------------------
/src/assets/img/profile/coupon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/views/profile/childComps/OrderView.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 我的订单
7 |
8 |
9 | 查看全部订单
10 |
11 |
12 |
13 |
14 |
![]()
15 |
16 | {{ wPay }}
17 |
18 |
待付款
19 |
20 |
21 |
![]()
22 |
23 | {{ wSend }}
24 |
25 |
待发货
26 |
27 |
28 |
![]()
29 |
30 | {{ wRecovery }}
31 |
32 |
待收获
33 |
34 |
35 |
![]()
36 |
37 | {{ wComment }}
38 |
39 |
评价
40 |
41 |
42 |
![]()
43 |
44 | {{ wRefund }}
45 |
46 |
退款/售后
47 |
48 |
49 |
50 |
51 |
52 |
53 |
67 |
68 |
123 |
--------------------------------------------------------------------------------
/src/utils/request.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | // import store from '@/store'
3 | // import router from '@/router'
4 | import concatUrl from '@/utils/url';
5 | // import { appConfig } from '@/config'
6 |
7 |
8 | /**
9 | * 刷新token
10 | * 当accessToken过期时调用
11 | * */
12 | export function getReferToken(){
13 | const refreshToken = localStorage.getItem("refreshToken");
14 | if(refreshToken) {
15 | const url = concatUrl('/auth/refresh/token/');
16 | axios({
17 | withCredentials: true,
18 | headers: {
19 | 'Content-Type': 'application/json; charset=utf-8',
20 | 'Authorization': refreshToken
21 | },
22 | method: 'post',
23 | url: url
24 | }).then(({data}) => {
25 | window.console.log("-----");
26 | window.console.log(data);
27 | window.console.log("-----");
28 | return data
29 | // $cookies.set("access_token", data.data.access_token, cookieTime['access_token']);
30 | });
31 | }
32 | }
33 |
34 |
35 |
36 | // 创建axios实例
37 | const service = axios.create({
38 | // baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
39 | // baseURL: 'http://127.0.0.1:5000/api', // url = base url + request url
40 | timeout: 50000,
41 | withCredentials: true,
42 | headers: {
43 | 'Content-Type': 'application/json; charset=utf-8'
44 | }
45 | });
46 |
47 |
48 | // 简单封装一层提示消息
49 | // const tip = (msg, type) => {
50 | // Message({
51 | // type: type,
52 | // showClose: true,
53 | // message: msg || 'Error',
54 | // duration: 5 * 1000
55 | // });
56 | // };
57 |
58 | // axios request拦截器
59 | service.interceptors.request.use(
60 | async config => {
61 | // do something before request is sent
62 | window.console.log("请求拦截");
63 | // 1.当发送网络请求时, 在页面中添加一个loading组件, 作为动画
64 |
65 | // 2.某些请求要求用户必须登录, 判断用户是否有token, 如果没有token跳转到login页面
66 |
67 | // 3.对请求的参数进行序列化(看服务器是否需要序列化)
68 | // config.data = qs.stringify(config.data)
69 | // console.log(config);
70 | return config
71 | },
72 | error => {
73 | // do something with request error
74 | window.console.log(error); // for debug
75 | return Promise.reject(error)
76 | }
77 | );
78 |
79 | // axios response 拦截器
80 | service.interceptors.response.use(
81 | /**
82 | * If you want to get http information such as headers or status
83 | * Please return response => response
84 | */
85 | response => {
86 | const res = response.data;
87 | // if the custom code is not 20000, it is judged as an error.
88 | if (res.code !== 200) {
89 | // tip(res.data, 'error')
90 | window.console.log(res)
91 | } else {
92 | return res
93 | }
94 | },
95 | error => {
96 | window.console.log('err' + error); // for debug
97 | // tip("网络错误!", "error");
98 | return Promise.reject(error)
99 | }
100 | );
101 |
102 |
103 | export const request = (url, method = 'POST', data = {}) => {
104 | let requestUrl = concatUrl(url);
105 |
106 | window.console.log(requestUrl);
107 |
108 | // 参数配置 如果是get方法就 设置成params 参数, 其他则设置成data参数
109 | let reConfig = method.toLocaleUpperCase() === "GET" ? {
110 | method,
111 | url: requestUrl,
112 | params: data
113 | } : {
114 | method,
115 | url: requestUrl,
116 | data
117 | };
118 |
119 | return service(reConfig);
120 | };
121 |
122 |
123 | export default request
124 |
--------------------------------------------------------------------------------
/src/views/shopcart/childComps/ShopListItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
![]()
9 |
10 |
11 |
![]()
12 |
13 |
14 |
{{ goodsInfo.title }}
15 |
型号:L
16 |
¥{{ goodsInfo.price }}
17 |
18 | -
19 | {{ goodsInfo.count }}
20 | +
21 |
22 |
23 |
24 |
25 |
26 |
54 |
55 |
136 |
--------------------------------------------------------------------------------
/src/assets/img/tabbar/shopcart.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/tabbar/shopcart_active.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Mall
2 | > 练习Vue时写的移动端商城项目,目前已经部署到线上。
3 |
4 | ## 对应API服务
5 | > 使用Python FastAPI构建
6 |
7 | [FastAPI服务地址](https://github.com/CoderCharm/MallAPI): https://github.com/CoderCharm/MallAPI
8 |
9 | 项目进度
10 | - 完成首页,分类页,购物车等页面,还差个人中心(2020/06/30)
11 |
12 | 线上地址
13 | https://www.charmcode.cn/app/mall/home
14 |
15 | > PC端, Google浏览器需要F12 点击切换移动设备
16 |
17 |
18 | ## 存在问题
19 |
20 | > 这些问题,暂时先不解决,整体完成后在解决。
21 |
22 | - 1 内容滚动不自然。
23 | - 2 有时候,首次进入页面,不能滑动内容。(疑似没有重新计算内容高度)
24 | - 3 没有记录滚动高度,切换分类时,滚动高度没有初始化。(应该单独记录每个分类的滚动高度)
25 | - 4 没有Toast弹窗提示。(后续完善)
26 | - 5 详情页,部分样式不完善。(不完善了)
27 | - 6 由于数据问题,商品详情页goodsId只有 123, 456, 789三个可以传。
28 | - 7 swiper 获取元素失败报错问题。(使用vue-awesome-swiper替换)
29 |
30 | ## 部署到线上 (同一个域名,部署多个Vue静态文件服务)
31 |
32 | [地址](DEPLOYMENT.md) DEPLOYMENT.md 个人总结
33 |
34 | #### Src文件目录
35 | ```
36 |
37 | |____App.vue
38 | |____config
39 | | |____index.js // 简单的自定义配置文件 比如请求的地址 生产和开发地址(ps:vue-cli会自动帮我们区分生产开发,npm run serve就是开发,build生产)
40 | |____utils
41 | | |____request.js // 封装的 axios服务
42 | | |____public.js
43 | | |____url.js // 在这里读取区分 开发生产的根路径
44 | |____main.js
45 | |____components // 全局组件
46 | | |____content // 只能本项目通用的全局组件
47 | | | |____tabControl
48 | | | | |____TabControl.vue
49 | | | |____mainTabbar
50 | | | | |____MainTabBar.vue
51 | | | |____backTop
52 | | | | |____BackTop.vue
53 | | |____HelloWorld.vue
54 | | |____common // 其他地方也能用的全局组件
55 | | | |____navbar
56 | | | | |____NavBar.vue
57 | | | |____swiper
58 | | | | |____Swiper.vue
59 | | | | |____SwiperItem.vue
60 | | | | |____index.js
61 | | | |____scroll
62 | | | | |____scroll.vue
63 | | | |____tabbar
64 | | | | |____TabBarItem.vue
65 | | | | |____TabBar.vue
66 | |____common
67 | | |____mixin.js
68 | |____api // 配合axios 区分的各模块路由
69 | | |____index.js
70 | | |____home.js
71 | | |____category.js
72 | | |____detail.js
73 | |____views // 各模块页面
74 | | |____demo
75 | | | |____Demo.vue
76 | | | |____childComps
77 | | |____home
78 | | | |____Home.vue
79 | | | |____childComps
80 | | | | |____FeatureView.vue
81 | | | | |____HomeSwiper.vue
82 | | | | |____GoodListItem.vue
83 | | | | |____RecommendView.vue
84 | | | | |____GoodsLIst.vue
85 | | |____category
86 | | | |____Category.vue
87 | | | |____childComps
88 | | | | |____LeftBar.vue
89 | | | | |____GoodListItem.vue
90 | | | | |____GoodsLIst.vue
91 | | | | |____TabBar.vue
92 | | |____shopcart
93 | | | |____childComps
94 | | | | |____DelBottomBar.vue
95 | | | | |____ShopListItem.vue
96 | | | | |____SettleBottomBar.vue
97 | | | |____ShopCart.vue
98 | | |____detail
99 | | | |____Detail.vue
100 | | | |____childComps
101 | | | | |____DetailSwiper.vue
102 | | | | |____GoodsDisplay.vue
103 | | | | |____GoodsStyleInfo.vue
104 | | | | |____LogisticsInfo.vue
105 | | | | |____DiscountInfo.vue
106 | | | | |____BottomBar.vue
107 | | | | |____CommentInfo.vue
108 | | | | |____BaseInfo.vue
109 | | | | |____SaleInfo.vue
110 | | | | |____ShopInfo.vue
111 | | | | |____DetailTabBar.vue
112 | | |____profile
113 | | | |____Profile.vue
114 | |____assets
115 | | |____css
116 | | | |____reset.less
117 | | | |____normalize.css
118 | | | |____base.css
119 | | |____img
120 | | | |____tabbar
121 | | | | |____home.svg
122 | | | | |____profile_active.svg
123 | | | | |____home_active.svg
124 | | | | |____category.svg
125 | | | | |____category_active.svg
126 | | | | |____shopcart.svg
127 | | | | |____shopcart_active.svg
128 | | | | |____profile.svg
129 | | | |____common
130 | | | | |____yes.svg
131 | | | | |____shop.svg
132 | | | | |____check.svg
133 | | | | |____back.svg
134 | | | | |____cust.svg
135 | | | | |____top.svg
136 | | | | |____heart.svg
137 | | |____logo.png
138 | |____store
139 | | |____index.js
140 | |____router // vue-router 本地路由文件
141 | | |____index.js
142 |
143 | ```
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 | ## Project setup
156 | ```
157 | npm install
158 | ```
159 |
160 | ### Compiles and hot-reloads for development
161 | ```
162 | npm run serve
163 | ```
164 |
165 | ### Compiles and minifies for production
166 | ```
167 | npm run build
168 | ```
169 |
170 | ### Run your tests
171 | ```
172 | npm run test
173 | ```
174 |
175 | ### Lints and fixes files
176 | ```
177 | npm run lint
178 | ```
179 |
180 | ### Customize configuration
181 | See [Configuration Reference](https://cli.vuejs.org/config/).
182 |
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 |
4 | Vue.use(Vuex)
5 |
6 | export default new Vuex.Store({
7 | state: {
8 | // 演示demo
9 | counter: 123,
10 | info: {
11 | name: "卡卡罗特",
12 | identity: "SuperSaiaMan",
13 | },
14 |
15 | // 购物车列表
16 | shopList: [],
17 |
18 | },
19 | mutations: {
20 | // 默认有一个state回调参数
21 | increment(state, params) {
22 | state.counter++;
23 | window.console.log(params)
24 | },
25 | // 另外一种提交风格 传入对象
26 | decrement(state, payload){
27 | window.console.log(state.counter);
28 | window.console.log(payload);
29 | state.counter --;
30 |
31 | // mutations里面必须是同步函数 https://vuex.vuejs.org/zh/guide/mutations.html#mutation-%E5%BF%85%E9%A1%BB%E6%98%AF%E5%90%8C%E6%AD%A5%E5%87%BD%E6%95%B0
32 | // setTimeout(() =>{
33 | // // 虽然相应里面已经更改 但是state 没有追踪到
34 | // state.info.name = "孙悟空";
35 | // }, 1000);
36 | // window.console.log(payload);
37 | },
38 | asyncModify(state, payload){
39 | // actions 来异步修改
40 | state.info.name = payload;
41 |
42 | },
43 | addInfo(state, params){
44 | // state.info["son"] = params // 不能响应式 修改
45 | // this.$set(state.info, "son", params) // 报错
46 | // 可参考官网响应式原理 https://cn.vuejs.org/v2/guide/reactivity.html#%E5%AF%B9%E4%BA%8E%E5%AF%B9%E8%B1%A1
47 | Vue.set(state.info, "son", params)
48 | },
49 | delInfo(state, params){
50 | // 不能响应式 能删除
51 | // delete state.info[params];
52 |
53 | // 响应式删除 对象 属性
54 | Vue.delete(state.info, params)
55 | },
56 |
57 | // 添加到购物车
58 | addShopList(state, params){
59 | // 判断之前是否添加过
60 | const oldInfo = state.shopList.find(item => item.goodsId === params.goodsId);
61 | // 如果没有
62 | if(!oldInfo){
63 | // 计数为1
64 | params.count = 1;
65 | // 默认被选中
66 | params.checked = true;
67 | state.shopList.push(params);
68 | }else{
69 | // 如果有 则+1
70 | oldInfo.count += 1
71 | }
72 |
73 | // window.console.log(state.shopList)
74 | },
75 | // 购物商品减少
76 | reduceShop(state, params){
77 | let currentIndex = state.shopList.indexOf(params);
78 | if(currentIndex !== -1){
79 | if(state.shopList[currentIndex].count > 1){
80 | state.shopList[currentIndex].count -= 1
81 | }
82 | // else{
83 | // state.shopList.splice(currentIndex, 1)
84 | // }
85 | }
86 | },
87 | // 改变单个商品选中状态
88 | changeChecked(state, params){
89 | // 查找当前对象
90 | const oldInfo = state.shopList.find(item => item.goodsId === params.goodsId);
91 | //
92 | if(oldInfo){
93 | oldInfo.checked = !oldInfo.checked
94 | }
95 | },
96 |
97 | // 全选/取消全选
98 | choiceAll(state, choice){
99 | state.shopList.forEach(el => {
100 | el['checked'] = choice
101 | })
102 | },
103 |
104 | // 删除 反向选择没选中的 重新赋值
105 | delChoice(state){
106 | state.shopList = state.shopList.filter(function(el){
107 | return !el.checked;
108 | })
109 | }
110 |
111 |
112 |
113 | },
114 | actions: {
115 | // 默认 context 上下文 参数回调
116 | aModify(context, payload){
117 | // 异步修改名字
118 | setTimeout(() =>{
119 | // actions 依旧要通过 mutations 来修改state
120 | context.commit('asyncModify', payload)
121 | }, 2000)
122 | }
123 |
124 | },
125 | getters: {
126 | // 相当于计算属性 https://www.bilibili.com/video/BV15741177Eh?p=133
127 | // state, getters 两个固定的默认参数
128 | // fun(state, getters){
129 | // 如果要接受参数
130 | // return (p) =>{
131 | // return 操作
132 | // }
133 | //
134 | // }
135 |
136 | cartList(state) {
137 | return state.shopList
138 | },
139 | cartCount(state) {
140 | return state.shopList.length
141 | }
142 | },
143 | modules: {}
144 | })
145 |
--------------------------------------------------------------------------------
/src/assets/img/common/top.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/views/category/Category.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 商品分类
5 |
6 |
7 |
8 |
14 |
15 |
19 |
20 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
167 |
168 |
195 |
--------------------------------------------------------------------------------
/src/views/detail/Detail.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
195 |
196 |
210 |
--------------------------------------------------------------------------------
/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 | }
--------------------------------------------------------------------------------
/src/views/home/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 购物街
5 |
6 |
7 |
12 |
13 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
197 |
198 |
239 |
--------------------------------------------------------------------------------
/src/components/common/swiper/Swiper.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
14 |
15 |
16 |
17 |
212 |
213 |
247 |
--------------------------------------------------------------------------------