├── .browserslistrc
├── public
├── favicon.ico
└── index.html
├── babel.config.js
├── src
├── assets
│ ├── img
│ │ ├── common
│ │ │ ├── top.png
│ │ │ ├── placeholder.png
│ │ │ ├── arrow-left.svg
│ │ │ ├── back.svg
│ │ │ └── collect.svg
│ │ ├── profile
│ │ │ ├── timg.gif
│ │ │ ├── message.svg
│ │ │ ├── avatar.svg
│ │ │ ├── phone.svg
│ │ │ ├── pointer.svg
│ │ │ ├── cart.svg
│ │ │ ├── vip.svg
│ │ │ └── shopping.svg
│ │ ├── home
│ │ │ └── recommend_bg.jpg
│ │ ├── detail
│ │ │ └── detail_bottom.png
│ │ ├── cart
│ │ │ └── tick.svg
│ │ └── tabbar
│ │ │ ├── shopcart.svg
│ │ │ ├── shopcart_active.svg
│ │ │ ├── category.svg
│ │ │ ├── category_active.svg
│ │ │ ├── profile.svg
│ │ │ ├── home.svg
│ │ │ ├── profile_active.svg
│ │ │ └── home_active.svg
│ └── css
│ │ ├── base.css
│ │ └── normalize.css
├── store
│ ├── mutation-types.js
│ ├── getters.js
│ ├── index.js
│ ├── actions.js
│ └── mutations.js
├── components
│ ├── common
│ │ ├── swiper
│ │ │ ├── index.js
│ │ │ ├── SwiperItem.vue
│ │ │ └── Swiper.vue
│ │ ├── toast
│ │ │ ├── index.js
│ │ │ └── Toast.vue
│ │ ├── tabbar
│ │ │ ├── TabBar.vue
│ │ │ └── TabBarItem.vue
│ │ ├── navbar
│ │ │ └── NavBar.vue
│ │ ├── scroll
│ │ │ └── Scroll.vue
│ │ └── gridview
│ │ │ └── GridView.vue
│ └── content
│ │ ├── backTop
│ │ └── BackTop.vue
│ │ ├── goods
│ │ ├── GoodsList.vue
│ │ └── GoodsListItem.vue
│ │ ├── checkButton
│ │ └── CheckButton.vue
│ │ ├── tabControl
│ │ └── TabControl.vue
│ │ └── maintabbar
│ │ └── MainTabBar.vue
├── common
│ ├── const.js
│ ├── utils.js
│ └── mixin.js
├── network
│ ├── home.js
│ ├── request.js
│ ├── category.js
│ └── detail.js
├── views
│ ├── home
│ │ ├── childComps
│ │ │ ├── FeatureView.vue
│ │ │ ├── RecommendView.vue
│ │ │ └── HomeSwiper.vue
│ │ └── Home.vue
│ ├── detail
│ │ ├── childComponents
│ │ │ ├── detailSwiper.vue
│ │ │ ├── DetailNavBar.vue
│ │ │ ├── DetailParamInfo.vue
│ │ │ ├── DetailBottomBar.vue
│ │ │ ├── DetailGoodsInfo.vue
│ │ │ ├── DetailBaseInfo.vue
│ │ │ ├── DetailCommentInfo.vue
│ │ │ └── DetailShopInfo.vue
│ │ └── Detail.vue
│ ├── cart
│ │ ├── childComps
│ │ │ ├── CartList.vue
│ │ │ ├── CartListItem.vue
│ │ │ └── CartBottomBar.vue
│ │ └── Cart.vue
│ ├── profile
│ │ ├── childComponents
│ │ │ ├── UserInfo.vue
│ │ │ ├── AccountInfo.vue
│ │ │ └── NormalListView.vue
│ │ └── Profile.vue
│ └── category
│ │ ├── childComponents
│ │ ├── CategoryContent.vue
│ │ └── CategoryMenu.vue
│ │ └── Category.vue
├── App.vue
├── main.js
└── router
│ └── index.js
├── .editorconfig
├── .gitignore
├── README.md
├── postcss.config.js
├── package.json
├── SECURITY.md
├── vue.config.js
├── LICENSE
└── Vue响应式原理.html
/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not dead
4 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liudufu/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/liudufu/supermall/HEAD/src/assets/img/common/top.png
--------------------------------------------------------------------------------
/src/assets/img/profile/timg.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liudufu/supermall/HEAD/src/assets/img/profile/timg.gif
--------------------------------------------------------------------------------
/src/store/mutation-types.js:
--------------------------------------------------------------------------------
1 | export const ADD_COUNTER = 'add_counter';
2 | export const ADD_TO_CART = 'add_to_cart';
3 |
--------------------------------------------------------------------------------
/src/assets/img/common/placeholder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liudufu/supermall/HEAD/src/assets/img/common/placeholder.png
--------------------------------------------------------------------------------
/src/assets/img/home/recommend_bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liudufu/supermall/HEAD/src/assets/img/home/recommend_bg.jpg
--------------------------------------------------------------------------------
/src/assets/img/detail/detail_bottom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liudufu/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 | }
7 |
--------------------------------------------------------------------------------
/src/common/const.js:
--------------------------------------------------------------------------------
1 | //滚动到TOP_DISTANCE 位置显示回到顶部按钮
2 | export const TOP_DISTANCE = 2000
3 | export const POP = 'pop'
4 | export const NEW = 'new'
5 | export const SELL = 'sell'
6 |
--------------------------------------------------------------------------------
/src/store/getters.js:
--------------------------------------------------------------------------------
1 | export default {
2 | cartLength(state) {
3 | return state.cartList.length;
4 | },
5 | cartList(state) {
6 | return state.cartList;
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/.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_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/.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/components/common/swiper/SwiperItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
23 |
--------------------------------------------------------------------------------
/src/assets/img/cart/tick.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/network/home.js:
--------------------------------------------------------------------------------
1 | import {request} from "./request";
2 |
3 | export function getHomeMultidata() {
4 | return request({
5 | url: '/home/multidata'
6 | // url: '/test/getBanners'
7 | })
8 | }
9 |
10 | export function getHomeGoods(type, page) {
11 | return request({
12 | url: '/home/data',
13 | // url: '/test/getGoods',
14 | params: {
15 | type,
16 | page
17 | }
18 | })
19 | }
20 |
--------------------------------------------------------------------------------
/src/views/home/childComps/FeatureView.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
14 |
15 |
20 |
--------------------------------------------------------------------------------
/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 | //1、安装插件
8 | Vue.use(Vuex)
9 |
10 | //2、创建store对象
11 | const state = {
12 | cartList: []
13 | }
14 |
15 | const store = new Vuex.Store({
16 | state,
17 | mutations,
18 | actions,
19 | getters
20 | })
21 |
22 | //3、导出
23 | export default store
24 |
--------------------------------------------------------------------------------
/src/components/content/backTop/BackTop.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
24 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
21 |
22 |
25 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # supermall
2 |
3 | ## 项目简介
4 |
5 | 本项目是根据蘑菇街App的手机端页面做的整体布局。
6 |
7 | 功能有:主页包括浏览商品、上拉刷新下拉加载更多商品等功能。详情页包括商品的展示,以及商品的参数,评论,店家信息,还有加入购物车功能等。分类页面包括商品的分类展示,分类查看。购物车页面是管理添加的商品,是用Vuex保存的数据,并没有提交到数据库。
8 |
9 | ## 初始化项目
10 | ```
11 | npm install
12 | ```
13 |
14 | ### 运行项目
15 | ```
16 | npm run serve
17 | ```
18 |
19 | ### 打包项目
20 | ```
21 | npm run build
22 | ```
23 |
24 | ### 自定义配置
25 | 参照 [Configuration Reference](https://cli.vuejs.org/config/).
26 |
27 | ### 提示
28 | 如果接口失效,请联系微信coderwhy003获取新接口
29 |
--------------------------------------------------------------------------------
/src/assets/img/common/arrow-left.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | autoprefixer: {},
4 | "postcss-px-to-viewport": {
5 | viewportWidth: 375, // 视窗的宽度,对应的是我们设计稿的宽度.
6 | viewportHeight: 667, // 视窗的高度,对应的是我们设计稿的高度.(也可以不配置)
7 | unitPrecision: 5, // 指定`px`转换为视窗单位值的小数位数(很多时候无法整除)
8 | viewportUnit: 'vw', // 指定需要转换成的视窗单位,建议使用vw
9 | selectorBlackList: ['tab-bar', 'tab-bar-item','cart-bottom-bar'], // 指定不需要转换的类
10 | minPixelValue: 1, // 小于或等于`1px`不转换为视窗单位.
11 | mediaQuery: false // 允许在媒体查询中转换`px`
12 | },
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/assets/img/common/back.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/components/common/toast/index.js:
--------------------------------------------------------------------------------
1 | import Toast from "./Toast";
2 |
3 | const obj = {
4 |
5 | }
6 |
7 | obj.install = function (Vue) {
8 | // document.body.appendChild(Toast.$el)
9 | //1、创建组件构造器
10 | const toastConstructor = Vue.extend(Toast);
11 |
12 | //2、new的方式,根据组件构造器,可以创建出来一个组件对象
13 | const toast = new toastConstructor();
14 | //3、将组价对象,手动挂载到某一个元素上
15 | toast.$mount(document.createElement('div'));
16 |
17 | //4、toast.$el对应的就是div
18 | document.body.appendChild(toast.$el);
19 |
20 | Vue.prototype.$toast = toast;
21 | }
22 |
23 | export default obj
24 |
--------------------------------------------------------------------------------
/src/components/common/tabbar/TabBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/network/request.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 |
3 | export function request(config) {
4 | // 1.创建axios的实例
5 | const instance = axios.create({
6 | baseURL: 'http://123.207.32.32:8000',
7 |
8 | //baseURL: 'http://adi-v3.dev',
9 | timeout: 5000
10 | })
11 |
12 | // 2.axios的拦截器
13 | // 2.1.请求拦截的作用
14 | instance.interceptors.request.use(config => {
15 | return config
16 | }, err => {
17 | // console.log(err);
18 | })
19 |
20 | // 2.2.响应拦截
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/components/common/navbar/NavBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
14 |
15 |
30 |
--------------------------------------------------------------------------------
/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.2",
11 | "better-scroll": "^1.15.2",
12 | "core-js": "^3.6.5",
13 | "fastclick": "^1.0.6",
14 | "vue": "^2.6.11",
15 | "vue-lazyload": "^1.3.3",
16 | "vue-router": "^3.3.4",
17 | "vuex": "^3.5.1"
18 | },
19 | "devDependencies": {
20 | "@vue/cli-plugin-babel": "~4.4.0",
21 | "@vue/cli-service": "~4.4.0",
22 | "postcss-px-to-viewport": "^1.1.1",
23 | "vue-template-compiler": "^2.6.11"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= htmlWebpackPlugin.options.title %>
9 |
10 |
11 |
12 | We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App.vue'
3 | import router from './router'
4 | import store from "./store";
5 |
6 | import FastClick from 'fastclick';
7 | import VueLazyload from "vue-lazyload";
8 |
9 | import toast from 'components/common/toast'
10 |
11 | Vue.config.productionTip = false
12 |
13 | Vue.prototype.$bus = new Vue()
14 |
15 | //安装toast插件
16 | Vue.use(toast)
17 |
18 | //解决移动端三百毫秒的延迟
19 | FastClick.attach(document.body);
20 |
21 | //使用懒加载的插件(需要将使用懒加载的图片路径改为src->v-lazy)
22 | Vue.use(VueLazyload, {
23 | loading: require('assets/img/common/placeholder.png')
24 | });
25 |
26 | new Vue({
27 | render: h => h(App),
28 | router,
29 | store
30 | }).$mount('#app')
31 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Supported Versions
4 |
5 | Use this section to tell people about which versions of your project are
6 | currently being supported with security updates.
7 |
8 | | Version | Supported |
9 | | ------- | ------------------ |
10 | | 5.1.x | :white_check_mark: |
11 | | 5.0.x | :x: |
12 | | 4.0.x | :white_check_mark: |
13 | | < 4.0 | :x: |
14 |
15 | ## Reporting a Vulnerability
16 |
17 | Use this section to tell people how to report a vulnerability.
18 |
19 | Tell them where to go, how often they can expect to get an update on a
20 | reported vulnerability, what to expect if the vulnerability is accepted or
21 | declined, etc.
22 |
--------------------------------------------------------------------------------
/src/components/content/goods/GoodsList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
25 |
26 |
37 |
--------------------------------------------------------------------------------
/src/views/detail/childComponents/detailSwiper.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
28 |
29 |
35 |
--------------------------------------------------------------------------------
/src/store/actions.js:
--------------------------------------------------------------------------------
1 | import {
2 | ADD_COUNTER,
3 | ADD_TO_CART
4 | } from './mutation-types';
5 |
6 | export default {
7 | addCart(context, payload) {
8 | return new Promise((resolve, reject) => {
9 | //payload新加入的商品
10 | //1、查找数组中是否有该商品
11 | let product = context.state.cartList.find((item) => {
12 | return item.iid === payload.iid;
13 | });
14 | //2、判断product
15 | if(product) {
16 | // product.count += 1;
17 | context.commit(ADD_COUNTER, product);
18 | resolve('当前的商品数量加一');
19 | }else {
20 | payload.count = 1;
21 | // context.state.cartList.push(payload);
22 | context.commit(ADD_TO_CART, payload);
23 | resolve('添加了心得商品');
24 | }
25 | })
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/network/category.js:
--------------------------------------------------------------------------------
1 | import {request} from "./request";
2 |
3 | /**
4 | * 获取分类的数据
5 | * @returns {AxiosPromise}
6 | */
7 | export function getCategory() {
8 | return request({
9 | url: '/category'
10 | })
11 | }
12 |
13 | /**
14 | * 获取每个分类栏的数据
15 | * @param maitKey
16 | * @returns {AxiosPromise}
17 | */
18 | export function getSubcategory(maitKey) {
19 | return request({
20 | url: '/subcategory',
21 | params: {
22 | maitKey
23 | }
24 | })
25 | }
26 |
27 | /**
28 | * 获取每个分类里面的商品信息
29 | * @param miniWallkey
30 | * @param type
31 | * @returns {AxiosPromise}
32 | */
33 | export function getCategoryDetail(miniWallkey, type) {
34 | return request({
35 | url: '/subcategory/detail',
36 | params: {
37 | miniWallkey,
38 | type
39 | }
40 | })
41 | }
42 |
--------------------------------------------------------------------------------
/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 | // 'network': 'src/network',
9 | // 'views': 'src/views'
10 | // }
11 | // }
12 | // }
13 | // }
14 | const path = require('path');
15 |
16 | function resolve(dir) {
17 | return path.join(__dirname, dir)
18 | }
19 |
20 | module.exports = {
21 | chainWebpack:(config) => {
22 | config.resolve.alias
23 | .set('@', resolve('./src'))
24 | .set('assets', resolve('./src/assets'))
25 | .set('common', resolve('./src/common'))
26 | .set('components', resolve('./src/components'))
27 | .set('network', resolve('./src/network'))
28 | .set('views', resolve('./src/views'))
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/assets/img/tabbar/shopcart.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
8 | Created by potrace 1.15, written by Peter Selinger 2001-2017
9 |
10 |
12 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/views/home/childComps/RecommendView.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
25 |
26 |
45 |
--------------------------------------------------------------------------------
/src/assets/img/tabbar/shopcart_active.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
8 | Created by potrace 1.15, written by Peter Selinger 2001-2017
9 |
10 |
12 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 |
3 | import vueRouter from 'vue-router';
4 |
5 | const Home = () => import('../views/home/Home')
6 | const Category = () => import('../views/category/Category')
7 | const Cart = () => import('../views/cart/Cart')
8 | const Profile = () => import('../views/profile/Profile')
9 | const Detail = () => import('../views/detail/Detail')
10 | //安装插件
11 | Vue.use(vueRouter)
12 |
13 | //创建路由对象
14 | const routes = [
15 | {
16 | path: '',
17 | redirect: '/home'
18 | },
19 | {
20 | path: '/home',
21 | component: Home
22 | },
23 | {
24 | path: '/category',
25 | component: Category
26 | },
27 | {
28 | path: '/cart',
29 | component: Cart
30 | },
31 | {
32 | path: '/profile',
33 | component: Profile
34 | },
35 | {
36 | path: '/detail/:iid',
37 | component: Detail
38 | }
39 | ]
40 | const router = new vueRouter({
41 | routes,
42 | code: 'history'
43 | })
44 |
45 | export default router
46 |
--------------------------------------------------------------------------------
/src/components/content/checkButton/CheckButton.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
20 |
21 |
43 |
--------------------------------------------------------------------------------
/src/assets/img/tabbar/category.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
8 | Created by potrace 1.15, written by Peter Selinger 2001-2017
9 |
10 |
12 |
14 |
16 |
18 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/assets/img/tabbar/category_active.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
8 | Created by potrace 1.15, written by Peter Selinger 2001-2017
9 |
10 |
12 |
14 |
16 |
18 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/assets/img/tabbar/profile.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
8 | Created by potrace 1.15, written by Peter Selinger 2001-2017
9 |
10 |
12 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/assets/img/tabbar/home.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
8 | Created by potrace 1.15, written by Peter Selinger 2001-2017
9 |
10 |
12 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/assets/img/tabbar/profile_active.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
8 | Created by potrace 1.15, written by Peter Selinger 2001-2017
9 |
10 |
12 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/assets/img/profile/message.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/tabbar/home_active.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
8 | Created by potrace 1.15, written by Peter Selinger 2001-2017
9 |
10 |
12 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/common/utils.js:
--------------------------------------------------------------------------------
1 | //debounce 防抖动
2 | export function debounce(func, delay){
3 | let timer = null;
4 |
5 | return function (...args) {
6 | if(timer) {
7 | clearTimeout(timer);
8 | }
9 | timer = setTimeout(() => {
10 | func.apply(this, args);
11 | }, delay)
12 | }
13 | };
14 |
15 | // 时间戳转换
16 | export function formatDate(date, fmt) {
17 | //1、获取年份
18 | if (/(y+)/.test(fmt)) {
19 | fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
20 | }
21 | //2、获取
22 | let o = {
23 | 'M+': date.getMonth() + 1,
24 | 'd+': date.getDate(),
25 | 'h+': date.getHours(),
26 | 'm+': date.getMinutes(),
27 | 's+': date.getSeconds()
28 | };
29 | for (let k in o) {
30 | if (new RegExp(`(${k})`).test(fmt)) {
31 | let str = o[k] + '';
32 | fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? str : padLeftZero(str));
33 | }
34 | }
35 | return fmt;
36 | };
37 |
38 | function padLeftZero (str) {
39 | return ('00' + str).substr(str.length);
40 | };
41 |
--------------------------------------------------------------------------------
/src/views/home/childComps/HomeSwiper.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
44 |
45 |
48 |
--------------------------------------------------------------------------------
/src/views/cart/childComps/CartList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
10 |
11 |
12 |
31 |
32 |
43 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 liudufu
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/components/common/toast/Toast.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
39 |
40 |
53 |
--------------------------------------------------------------------------------
/src/views/cart/Cart.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 购物车({{cartLength}})
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
42 |
43 |
54 |
--------------------------------------------------------------------------------
/src/network/detail.js:
--------------------------------------------------------------------------------
1 | import {request} from "./request";
2 |
3 | export function getDetail(iid) {
4 | return request({
5 | url: '/detail',
6 | params: {
7 | iid
8 | }
9 | })
10 | }
11 |
12 | export function getRecommend() {
13 | return request({
14 | url: '/recommend'
15 | })
16 | }
17 |
18 | export class Goods {
19 | constructor(itemInfo, colums, services) {
20 | this.title = itemInfo.title;
21 | this.desc = itemInfo.desc;
22 | this.newPrice = itemInfo.price;
23 | this.oldPrice = itemInfo.oldPrice;
24 | this.discount = itemInfo.discount;
25 | this.columns = colums;
26 | this.services = services;
27 | this.realPrice = itemInfo.lowNowPrice;
28 | }
29 | }
30 |
31 | export class GoodsParam {
32 | constructor(info, rule) {
33 | //注:images可能没有值
34 | this.image = info.images ? info.images[0] : '';
35 | this.infos = info.set;
36 | this.sizes = rule.tables;
37 | }
38 | }
39 |
40 | export class Shop {
41 | constructor(shopInfo) {
42 | this.logo = shopInfo.shopLogo;
43 | this.name = shopInfo.name;
44 | this.fans = shopInfo.cFans;
45 | this.sells = shopInfo.cSells;
46 | this.score = shopInfo.score;
47 | this.goodsCount = shopInfo.cGoods;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/components/content/tabControl/TabControl.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
36 |
37 |
62 |
--------------------------------------------------------------------------------
/src/views/profile/childComponents/UserInfo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
登录/注册
6 |
7 |
8 |
暂无绑定手机号
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
22 |
23 |
67 |
--------------------------------------------------------------------------------
/src/views/profile/childComponents/AccountInfo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 0.00 元
6 |
7 |
我的余额
8 |
9 |
10 |
11 | 0 个
12 |
13 |
我的优惠
14 |
15 |
16 |
17 | 0 分
18 |
19 |
我的积分
20 |
21 |
22 |
23 |
24 |
29 |
30 |
61 |
--------------------------------------------------------------------------------
/src/views/detail/childComponents/DetailNavBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 | {{item}}
13 |
14 |
15 |
16 |
17 |
18 |
19 |
45 |
46 |
62 |
--------------------------------------------------------------------------------
/src/views/profile/Profile.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 我的档案
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
43 |
44 |
54 |
--------------------------------------------------------------------------------
/src/views/category/childComponents/CategoryContent.vue:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 |
45 |
46 |
64 |
--------------------------------------------------------------------------------
/src/store/mutations.js:
--------------------------------------------------------------------------------
1 | import {
2 | ADD_COUNTER,
3 | ADD_TO_CART
4 | } from './mutation-types'
5 |
6 | export default {
7 | //mutation唯一的目的,修改state中的状态
8 | //但是mutation方法规则是比较单一的,一个方法只做一件事情,所以addCart方法应放到actions中
9 | // addCart(state, payload) {
10 | // }
11 | [ADD_COUNTER](state, payload) {
12 | payload.count++;
13 | },
14 | [ADD_TO_CART](state, payload) {
15 | payload.checked = true;
16 | state.cartList.push(payload);
17 | },
18 | /**
19 | * 更新商品中Checked的值
20 | */
21 | updateChecked(state, payload) {
22 | //1、查找到当前要修改的商品
23 | let oldProduct = state.cartList.find(item => {
24 | return item.iid === payload.item.iid && item.productStyleMsg === payload.item.productStyleMsg && item.productSizeMsg === payload.item.productSizeMsg
25 | })
26 | //2、改变checked值
27 | oldProduct.checked = payload.checked;
28 | },
29 |
30 | /**
31 | * 更新商品中currentCounts的值
32 | */
33 | updateCounts(state, payload) {
34 | //1、查找到当前要修改的商品
35 | let oldProduct = state.cartList.find(item => {
36 | return item.iid === payload.item.iid && item.productStyleMsg === payload.item.productStyleMsg && item.productSizeMsg === payload.item.productSizeMsg
37 | })
38 | //2、改变checked值
39 | oldProduct.currentCounts += payload.number;
40 | },
41 | /**
42 | * 删除选中的商品
43 | */
44 | deleteProduct(state) {
45 | state.cartList = state.cartList.filter(item => !item.checked);
46 | }
47 | }
48 |
49 |
50 |
--------------------------------------------------------------------------------
/src/views/profile/childComponents/NormalListView.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
{{item.info}}
8 |
9 |
10 |
11 |
12 |
30 |
31 |
67 |
--------------------------------------------------------------------------------
/src/views/category/childComponents/CategoryMenu.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
38 |
39 |
62 |
--------------------------------------------------------------------------------
/src/assets/css/base.css:
--------------------------------------------------------------------------------
1 | @import "./normalize.css";
2 | /*:root -> 获取根元素html*/
3 | :root {
4 | /* --color-text 意思 是 定义变量 */
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 | *::after {
16 | margin: 0;
17 | padding: 0;
18 | box-sizing: border-box;
19 | }
20 |
21 | body {
22 | font-family: "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif;
23 | user-select: none; /* 禁止用户鼠标在页面上选中文字/图片等 */
24 | -webkit-tap-highlight-color: transparent; /* webkit是苹果浏览器引擎,tap点击,highlight背景高亮,color颜色,颜色用数值调节 */
25 | background: var(--color-background);
26 | color: var(--color-text);
27 | width: 100vw;
28 | }
29 |
30 | a {
31 | color: var(--color-text);
32 | text-decoration: none;
33 | }
34 |
35 |
36 | .clear-fix::after {
37 | clear: both;
38 | content: '';
39 | display: block;
40 | width: 0;
41 | height: 0;
42 | visibility: hidden;
43 | }
44 |
45 | .clear-fix {
46 | zoom: 1;
47 | }
48 |
49 | .arrow-right {
50 | border-top: 1px solid #999;
51 | border-left: 1px solid #999;
52 | width: 9px;
53 | height: 9px;
54 | background-color: transparent;
55 | transform: rotate(135deg);
56 | display: inline-block;
57 | margin-left: .1rem;
58 | }
59 |
60 | .left {
61 | float: left;
62 | }
63 |
64 | .right {
65 | float: right;
66 | }
67 |
68 |
--------------------------------------------------------------------------------
/src/assets/img/profile/avatar.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/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 |
27 |
28 |
40 |
41 |
44 |
--------------------------------------------------------------------------------
/src/assets/img/profile/phone.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/views/detail/childComponents/DetailParamInfo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
12 | {{info.key}}
13 | {{info.value}}
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
35 |
36 |
73 |
--------------------------------------------------------------------------------
/src/components/common/scroll/Scroll.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
71 |
72 |
75 |
--------------------------------------------------------------------------------
/src/components/common/gridview/GridView.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
65 |
66 |
73 |
--------------------------------------------------------------------------------
/src/views/detail/childComponents/DetailBottomBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 客服
7 |
8 |
9 |
10 | 店铺
11 |
12 |
13 |
14 | 收藏
15 |
16 |
17 |
21 |
22 |
23 |
24 |
25 |
35 |
36 |
99 |
--------------------------------------------------------------------------------
/src/assets/img/common/collect.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/common/mixin.js:
--------------------------------------------------------------------------------
1 | import {debounce} from "./utils";
2 |
3 | import BackTop from "components/content/backTop/BackTop";
4 | import TabControl from "components/content/tabControl/TabControl";
5 | import {POP, SELL, NEW} from "./const";
6 |
7 | export const itemListener = {
8 | data() {
9 | return {
10 | itemImgListener: null,
11 | refresh: null
12 | }
13 | },
14 | mounted() {
15 | this.refresh = debounce(this.$refs.scroll.refresh, 500);
16 | this.itemImgListener = () => {
17 | this.refresh()
18 | };
19 | this.$bus.$on('itemImgLoad', this.itemImgListener);
20 | console.log('mounted混入操作');
21 | }
22 | }
23 |
24 | export const backTopMinxin = {
25 | components: {
26 | BackTop
27 | },
28 | data() {
29 | return {
30 | isShowBackTop: false
31 | }
32 | },
33 | methods: {
34 | backClick() {
35 | this.$refs.scroll.scrollTo(0, 0)
36 | },
37 | }
38 | }
39 | /**
40 | * tabControl导航栏的公共代码
41 | * @type {{data: (function(): {currentType: string}), methods: {tabClick(*): void}}}
42 | */
43 | export const tabControlMixin = {
44 | components: {
45 | TabControl
46 | },
47 | data() {
48 | return {
49 | currentType: POP
50 | }
51 | },
52 | methods: {
53 | //1、监听tabControl的点击
54 | tabClick(index) {
55 | //调用此方法来保持两个tabControl的选项一致
56 | this._tabClick(index);
57 |
58 | switch (index) {
59 | case 0:
60 | //如果当前页面不是正在显示的就滚动到所点击标签的起始位置
61 | if (this.currentType != POP && this.isTabFixed) {
62 | this.$refs.scroll && this.$refs.scroll.scrollTo(0, (-this.tabOffsetTop), 0);
63 | }
64 | this.currentType = POP;
65 | break;
66 |
67 | case 1:
68 | if (this.currentType != NEW && this.isTabFixed) {
69 | this.$refs.scroll && this.$refs.scroll.scrollTo(0, (-this.tabOffsetTop), 0);
70 | }
71 | this.currentType = NEW;
72 | break;
73 |
74 | case 2:
75 | if (this.currentType != SELL && this.isTabFixed) {
76 | this.$refs.scroll && this.$refs.scroll.scrollTo(0, (-this.tabOffsetTop), 0);
77 | }
78 | this.currentType = SELL;
79 | break;
80 | }
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/assets/img/profile/pointer.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/profile/cart.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/content/goods/GoodsListItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
{{goodsItem.title}}
6 |
{{goodsItem.price}}
7 |
{{goodsItem.cfav}}
8 |
9 |
10 |
11 |
12 |
46 |
47 |
96 |
--------------------------------------------------------------------------------
/Vue响应式原理.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Title
6 |
7 |
8 |
9 |
16 |
17 |
18 |
19 | {{message}}
20 | {{message}}
21 | {{message}}
22 |
23 |
24 |
91 |
92 |
102 |
103 |
104 |
105 |
--------------------------------------------------------------------------------
/src/views/cart/childComps/CartListItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
{{itemInfo.title}}
14 |
{{itemInfo.desc}}
15 |
16 |
{{itemInfo.price}}
17 |
x{{itemInfo.count}}
18 |
19 |
20 |
21 |
22 |
23 |
46 |
47 |
107 |
--------------------------------------------------------------------------------
/src/views/detail/childComponents/DetailGoodsInfo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
{{detailInfo.desc}}
6 |
7 |
8 |
{{detailInfo.detailImage[0].key}}
9 |
10 |
15 |
16 |
17 |
18 |
19 |
53 |
54 |
106 |
--------------------------------------------------------------------------------
/src/views/detail/childComponents/DetailBaseInfo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{goods.title}}
4 |
5 | {{goods.newPrice}}
6 | {{goods.oldPrice}}
7 | {{goods.discount}}
8 |
9 |
10 | {{goods.columns[0]}}
11 | {{goods.columns[1]}}
12 | {{goods.services[goods.services.length-1].name}}
13 |
14 |
15 |
18 |
19 | {{goods.services[index-1].name}}
20 |
21 |
22 |
23 |
24 |
25 |
38 |
39 |
102 |
--------------------------------------------------------------------------------
/src/assets/img/profile/vip.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/views/detail/childComponents/DetailCommentInfo.vue:
--------------------------------------------------------------------------------
1 |
2 |
25 |
26 |
27 |
49 |
50 |
122 |
--------------------------------------------------------------------------------
/src/assets/img/profile/shopping.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/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 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
61 |
62 |
63 |
94 |
95 |
113 |
--------------------------------------------------------------------------------
/src/views/detail/childComponents/DetailShopInfo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
{{shop.name}}
6 |
7 |
8 |
9 |
10 |
11 | {{shop.sells | sellCountFilter}}
12 |
13 |
总销量
14 |
15 |
16 |
17 | {{shop.goodsCount}}
18 |
19 |
全部宝贝
20 |
21 |
22 |
23 |
24 |
25 | {{item.name}}
26 |
27 | {{item.score}}
28 |
29 |
30 | {{item.isBetter ? '高' : '低'}}
31 |
32 |
33 |
34 |
35 |
36 |
39 |
40 |
41 |
42 |
64 |
65 |
163 |
--------------------------------------------------------------------------------
/src/views/cart/childComps/CartBottomBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 | 全选
9 |
10 |
11 | 合计:¥{{totalPrice}}
12 |
13 |
16 | 取消
17 |
18 |
19 | 去结算({{checkLength}})
20 |
21 |
22 |
23 |
24 |
114 |
115 |
171 |
--------------------------------------------------------------------------------
/src/views/category/Category.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 商品分类
6 |
7 |
12 |
13 |
15 |
20 |
21 |
22 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
186 |
187 |
222 |
--------------------------------------------------------------------------------
/src/views/home/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
购物街
4 |
9 |
15 |
16 |
17 |
18 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
193 |
194 |
238 |
--------------------------------------------------------------------------------
/src/components/common/swiper/Swiper.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
13 |
14 |
15 |
16 |
211 |
212 |
246 |
--------------------------------------------------------------------------------
/src/assets/css/normalize.css:
--------------------------------------------------------------------------------
1 | /*! normalize.css v8.0.0 | 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 | * Correct the font size and margin on `h1` elements within `section` and
29 | * `article` contexts in Chrome, Firefox, and Safari.
30 | */
31 |
32 | h1 {
33 | font-size: 2em;
34 | margin: 0.67em 0;
35 | }
36 |
37 | /* Grouping content
38 | ========================================================================== */
39 |
40 | /**
41 | * 1. Add the correct box sizing in Firefox.
42 | * 2. Show the overflow in Edge and IE.
43 | */
44 |
45 | hr {
46 | box-sizing: content-box; /* 1 */
47 | height: 0; /* 1 */
48 | overflow: visible; /* 2 */
49 | }
50 |
51 | /**
52 | * 1. Correct the inheritance and scaling of font size in all browsers.
53 | * 2. Correct the odd `em` font sizing in all browsers.
54 | */
55 |
56 | pre {
57 | font-family: monospace, monospace; /* 1 */
58 | font-size: 1em; /* 2 */
59 | }
60 |
61 | /* Text-level semantics
62 | ========================================================================== */
63 |
64 | /**
65 | * Remove the gray background on active links in IE 10.
66 | */
67 |
68 | a {
69 | background-color: transparent;
70 | }
71 |
72 | /**
73 | * 1. Remove the bottom border in Chrome 57-
74 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
75 | */
76 |
77 | abbr[title] {
78 | border-bottom: none; /* 1 */
79 | text-decoration: underline; /* 2 */
80 | text-decoration: underline dotted; /* 2 */
81 | }
82 |
83 | /**
84 | * Add the correct font weight in Chrome, Edge, and Safari.
85 | */
86 |
87 | b,
88 | strong {
89 | font-weight: bolder;
90 | }
91 |
92 | /**
93 | * 1. Correct the inheritance and scaling of font size in all browsers.
94 | * 2. Correct the odd `em` font sizing in all browsers.
95 | */
96 |
97 | code,
98 | kbd,
99 | samp {
100 | font-family: monospace, monospace; /* 1 */
101 | font-size: 1em; /* 2 */
102 | }
103 |
104 | /**
105 | * Add the correct font size in all browsers.
106 | */
107 |
108 | small {
109 | font-size: 80%;
110 | }
111 |
112 | /**
113 | * Prevent `sub` and `sup` elements from affecting the line height in
114 | * all browsers.
115 | */
116 |
117 | sub,
118 | sup {
119 | font-size: 75%;
120 | line-height: 0;
121 | position: relative;
122 | vertical-align: baseline;
123 | }
124 |
125 | sub {
126 | bottom: -0.25em;
127 | }
128 |
129 | sup {
130 | top: -0.5em;
131 | }
132 |
133 | /* Embedded content
134 | ========================================================================== */
135 |
136 | /**
137 | * Remove the border on images inside links in IE 10.
138 | */
139 |
140 | img {
141 | border-style: none;
142 | }
143 |
144 | /* Forms
145 | ========================================================================== */
146 |
147 | /**
148 | * 1. Change the font styles in all browsers.
149 | * 2. Remove the margin in Firefox and Safari.
150 | */
151 |
152 | button,
153 | input,
154 | optgroup,
155 | select,
156 | textarea {
157 | font-family: inherit; /* 1 */
158 | font-size: 100%; /* 1 */
159 | line-height: 1.15; /* 1 */
160 | margin: 0; /* 2 */
161 | }
162 |
163 | /**
164 | * Show the overflow in IE.
165 | * 1. Show the overflow in Edge.
166 | */
167 |
168 | button,
169 | input { /* 1 */
170 | overflow: visible;
171 | }
172 |
173 | /**
174 | * Remove the inheritance of text transform in Edge, Firefox, and IE.
175 | * 1. Remove the inheritance of text transform in Firefox.
176 | */
177 |
178 | button,
179 | select { /* 1 */
180 | text-transform: none;
181 | }
182 |
183 | /**
184 | * Correct the inability to style clickable types in iOS and Safari.
185 | */
186 |
187 | button,
188 | [type="button"],
189 | [type="reset"],
190 | [type="submit"] {
191 | -webkit-appearance: button;
192 | }
193 |
194 | /**
195 | * Remove the inner border and padding in Firefox.
196 | */
197 |
198 | button::-moz-focus-inner,
199 | [type="button"]::-moz-focus-inner,
200 | [type="reset"]::-moz-focus-inner,
201 | [type="submit"]::-moz-focus-inner {
202 | border-style: none;
203 | padding: 0;
204 | }
205 |
206 | /**
207 | * Restore the focus styles unset by the previous rule.
208 | */
209 |
210 | button:-moz-focusring,
211 | [type="button"]:-moz-focusring,
212 | [type="reset"]:-moz-focusring,
213 | [type="submit"]:-moz-focusring {
214 | outline: 1px dotted ButtonText;
215 | }
216 |
217 | /**
218 | * Correct the padding in Firefox.
219 | */
220 |
221 | fieldset {
222 | padding: 0.35em 0.75em 0.625em;
223 | }
224 |
225 | /**
226 | * 1. Correct the text wrapping in Edge and IE.
227 | * 2. Correct the color inheritance from `fieldset` elements in IE.
228 | * 3. Remove the padding so developers are not caught out when they zero out
229 | * `fieldset` elements in all browsers.
230 | */
231 |
232 | legend {
233 | box-sizing: border-box; /* 1 */
234 | color: inherit; /* 2 */
235 | display: table; /* 1 */
236 | max-width: 100%; /* 1 */
237 | padding: 0; /* 3 */
238 | white-space: normal; /* 1 */
239 | }
240 |
241 | /**
242 | * Add the correct vertical alignment in Chrome, Firefox, and Opera.
243 | */
244 |
245 | progress {
246 | vertical-align: baseline;
247 | }
248 |
249 | /**
250 | * Remove the default vertical scrollbar in IE 10+.
251 | */
252 |
253 | textarea {
254 | overflow: auto;
255 | }
256 |
257 | /**
258 | * 1. Add the correct box sizing in IE 10.
259 | * 2. Remove the padding in IE 10.
260 | */
261 |
262 | [type="checkbox"],
263 | [type="radio"] {
264 | box-sizing: border-box; /* 1 */
265 | padding: 0; /* 2 */
266 | }
267 |
268 | /**
269 | * Correct the cursor style of increment and decrement buttons in Chrome.
270 | */
271 |
272 | [type="number"]::-webkit-inner-spin-button,
273 | [type="number"]::-webkit-outer-spin-button {
274 | height: auto;
275 | }
276 |
277 | /**
278 | * 1. Correct the odd appearance in Chrome and Safari.
279 | * 2. Correct the outline style in Safari.
280 | */
281 |
282 | [type="search"] {
283 | -webkit-appearance: textfield; /* 1 */
284 | outline-offset: -2px; /* 2 */
285 | }
286 |
287 | /**
288 | * Remove the inner padding in Chrome and Safari on macOS.
289 | */
290 |
291 | [type="search"]::-webkit-search-decoration {
292 | -webkit-appearance: none;
293 | }
294 |
295 | /**
296 | * 1. Correct the inability to style clickable types in iOS and Safari.
297 | * 2. Change font properties to `inherit` in Safari.
298 | */
299 |
300 | ::-webkit-file-upload-button {
301 | -webkit-appearance: button; /* 1 */
302 | font: inherit; /* 2 */
303 | }
304 |
305 | /* Interactive
306 | ========================================================================== */
307 |
308 | /*
309 | * Add the correct display in Edge, IE 10+, and Firefox.
310 | */
311 |
312 | details {
313 | display: block;
314 | }
315 |
316 | /*
317 | * Add the correct display in all browsers.
318 | */
319 |
320 | summary {
321 | display: list-item;
322 | }
323 |
324 | /* Misc
325 | ========================================================================== */
326 |
327 | /**
328 | * Add the correct display in IE 10+.
329 | */
330 |
331 | template {
332 | display: none;
333 | }
334 |
335 | /**
336 | * Add the correct display in IE 10.
337 | */
338 |
339 | [hidden] {
340 | display: none;
341 | }
342 |
--------------------------------------------------------------------------------
/src/views/detail/Detail.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
234 |
235 |
254 |
--------------------------------------------------------------------------------
{{commentInfo.content}}
16 |