├── static
├── .gitkeep
├── login.json
└── permission.json
├── src
├── store
│ ├── actions.js
│ ├── getters.js
│ ├── modules.js
│ ├── state.js
│ ├── mutations.js
│ ├── index.js
│ └── modules
│ │ └── permission.js
├── config
│ ├── baseUrl.js
│ └── httpConfig.js
├── assets
│ └── image
│ │ └── a.png
├── styles
│ ├── index.scss
│ ├── _mixin.scss
│ ├── _sidebar.scss
│ ├── _reset_element.scss
│ └── _normalize.scss
├── pages
│ ├── home
│ │ ├── component
│ │ │ ├── todo-list.vue
│ │ │ ├── total-status.vue
│ │ │ └── charts.vue
│ │ └── index.vue
│ ├── order-manage
│ │ ├── product-manage
│ │ │ ├── index.vue
│ │ │ ├── production-list
│ │ │ │ └── index.vue
│ │ │ └── review-manage
│ │ │ │ └── index.vue
│ │ ├── index.vue
│ │ ├── order-list
│ │ │ └── index.vue
│ │ └── return-goods
│ │ │ └── index.vue
│ ├── goods-manage
│ │ ├── index.vue
│ │ ├── goods-list
│ │ │ └── index.vue
│ │ └── goods-classify
│ │ │ └── index.vue
│ ├── finance-manage
│ │ ├── index.vue
│ │ └── component
│ │ │ ├── order-list
│ │ │ └── index.vue
│ │ │ ├── product-manage
│ │ │ └── index.vue
│ │ │ └── return-goods
│ │ │ └── index.vue
│ ├── layout
│ │ ├── component
│ │ │ ├── main-content
│ │ │ │ ├── content.vue
│ │ │ │ ├── index.vue
│ │ │ │ └── top-aside.vue
│ │ │ └── sidebar-nav.vue
│ │ └── index.vue
│ ├── login
│ │ └── login.vue
│ └── errorPage
│ │ ├── 403.vue
│ │ └── 404.vue
├── api
│ └── permission.js
├── App.vue
├── filters
│ └── filters.js
├── utils
│ └── recursion-router.js
├── router
│ ├── index.js
│ └── dynamic-router.js
├── components
│ └── dynamic-menu.vue
└── main.js
├── .eslintignore
├── config
├── prod.env.js
├── dev.env.js
└── index.js
├── .editorconfig
├── .gitignore
├── .babelrc
├── .postcssrc.js
├── index.html
├── README.md
├── .eslintrc.js
└── package.json
/static/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/store/actions.js:
--------------------------------------------------------------------------------
1 | export default {
2 |
3 | }
4 |
--------------------------------------------------------------------------------
/src/store/getters.js:
--------------------------------------------------------------------------------
1 | export default {
2 |
3 | }
4 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | /build/
2 | /config/
3 | /dist/
4 | /*.js
5 |
--------------------------------------------------------------------------------
/src/config/baseUrl.js:
--------------------------------------------------------------------------------
1 | const baseUrl = 'http://localhost:8080'
2 | export default baseUrl
3 |
--------------------------------------------------------------------------------
/src/assets/image/a.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/linrunzheng/vue-permission-control/HEAD/src/assets/image/a.png
--------------------------------------------------------------------------------
/src/store/modules.js:
--------------------------------------------------------------------------------
1 | import permission from './modules/permission'
2 |
3 | export default {
4 | permission
5 | }
6 |
--------------------------------------------------------------------------------
/static/login.json:
--------------------------------------------------------------------------------
1 | {
2 | "code": 0,
3 | "message": "登录成功",
4 | "data": {
5 | "token":"abcdedfhijklmnokrjsuvmxyz"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/config/prod.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | module.exports = {
3 | NODE_ENV: '"production"',
4 | BASE_API: '"https://easy-mock.com/mock/5950a2419adc231f356a6636/vue-admin"',
5 | }
6 |
--------------------------------------------------------------------------------
/src/styles/index.scss:
--------------------------------------------------------------------------------
1 | @import './normalize.scss';
2 | @import './reset_element.scss';
3 | @import './sidebar.scss';
4 | @import url('//at.alicdn.com/t/font_641452_q3ah7ae4qvndn29.css');
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/src/pages/home/component/todo-list.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | mmm
4 |
5 |
6 |
7 |
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | /dist/
4 | .svn/
5 | npm-debug.log*
6 | yarn-debug.log*
7 | yarn-error.log*
8 |
9 | # Editor directories and files
10 | .idea
11 | .vscode
12 | *.suo
13 | *.ntvs*
14 | *.njsproj
15 | *.sln
16 |
--------------------------------------------------------------------------------
/src/api/permission.js:
--------------------------------------------------------------------------------
1 | import axios from '@/config/httpConfig'
2 |
3 | export function fetchPermission() {
4 | return axios.get('/static/permission.json')
5 | }
6 |
7 | export function login() {
8 | return axios.get('/static/login.json')
9 | }
10 |
--------------------------------------------------------------------------------
/src/pages/order-manage/product-manage/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
14 |
--------------------------------------------------------------------------------
/config/dev.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const merge = require('webpack-merge')
3 | const prodEnv = require('./prod.env')
4 |
5 | module.exports = merge(prodEnv, {
6 | NODE_ENV: '"development"',
7 | BASE_API: '"https://easy-mock.com/mock/5950a2419adc231f356a6636/vue-admin"',
8 | })
9 |
--------------------------------------------------------------------------------
/src/pages/goods-manage/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
17 |
--------------------------------------------------------------------------------
/src/pages/order-manage/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
17 |
--------------------------------------------------------------------------------
/src/pages/finance-manage/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
17 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env", {
4 | "modules": false,
5 | "targets": {
6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
7 | }
8 | }],
9 | "stage-2"
10 | ],
11 | "plugins": ["transform-vue-jsx", "transform-runtime"]
12 | }
13 |
--------------------------------------------------------------------------------
/.postcssrc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/michael-ciniawsky/postcss-load-config
2 |
3 | module.exports = {
4 | "plugins": {
5 | "postcss-import": {},
6 | "postcss-url": {},
7 | // to edit target browsers: use "browserslist" field in package.json
8 | "autoprefixer": {}
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/pages/goods-manage/goods-list/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 产品列表
4 | 产品列表
5 | 产品列表
6 | 产品列表
7 | 产品列表
8 |
9 |
10 |
11 |
18 |
--------------------------------------------------------------------------------
/src/pages/layout/component/main-content/content.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
12 |
13 |
16 |
--------------------------------------------------------------------------------
/src/pages/order-manage/order-list/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 订单列表
4 | 订单列表
5 | 订单列表
6 | 订单列表
7 | 订单列表
8 |
9 |
10 |
11 |
18 |
--------------------------------------------------------------------------------
/src/pages/goods-manage/goods-classify/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 产品分类
4 | 产品分类
5 | 产品分类
6 | 产品分类
7 | 产品分类
8 |
9 |
10 |
11 |
18 |
--------------------------------------------------------------------------------
/src/pages/finance-manage/component/order-list/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 订单列表
4 | 订单列表
5 | 订单列表
6 | 订单列表
7 | 订单列表
8 |
9 |
10 |
11 |
18 |
--------------------------------------------------------------------------------
/src/pages/order-manage/return-goods/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 退货管理
4 | 退货管理
5 | 退货管理
6 | 退货管理
7 | 退货管理
8 | 退货管理
9 |
10 |
11 |
12 |
19 |
--------------------------------------------------------------------------------
/src/pages/order-manage/product-manage/production-list/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 生产列表
4 | 生产列表
5 | 生产列表
6 | 生产列表
7 | 生产列表
8 |
9 |
10 |
11 |
18 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | hongmu
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/pages/finance-manage/component/product-manage/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 生产管理
4 | 生产管理
5 | 生产管理
6 | 生产管理
7 | 生产管理
8 | 生产管理
9 |
10 |
11 |
12 |
19 |
--------------------------------------------------------------------------------
/src/pages/finance-manage/component/return-goods/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 退货管理
4 | 退货管理
5 | 退货管理
6 | 退货管理
7 | 退货管理
8 | 退货管理
9 |
10 |
11 |
12 |
19 |
--------------------------------------------------------------------------------
/src/store/state.js:
--------------------------------------------------------------------------------
1 | export default {
2 | get UserToken() {
3 | return localStorage.getItem('token')
4 | },
5 | set UserToken(value) {
6 | localStorage.setItem('token', value)
7 | },
8 | /* 导航菜单是否折叠 */
9 | isSidebarNavCollapse: false,
10 | /* 面包屑导航列表 */
11 | crumbList: []
12 | }
13 |
--------------------------------------------------------------------------------
/src/pages/order-manage/product-manage/review-manage/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 审核管理
4 | 审核管理
5 | 审核管理
6 | 审核管理
7 | 审核管理
8 | 审核管理
9 |
10 |
11 |
12 |
19 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
21 |
--------------------------------------------------------------------------------
/src/store/mutations.js:
--------------------------------------------------------------------------------
1 | export default {
2 | LOGIN_IN(state, token) {
3 | state.UserToken = token
4 | },
5 | LOGIN_OUT(state) {
6 | state.UserToken = ''
7 | },
8 | toggleNavCollapse(state) {
9 | state.isSidebarNavCollapse = !state.isSidebarNavCollapse
10 | },
11 | setCrumbList(state, list) {
12 | state.crumbList = list
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 |
4 | import state from './state'
5 | import getters from './getters'
6 | import modules from './modules'
7 | import actions from './actions'
8 | import mutations from './mutations'
9 |
10 | Vue.use(Vuex)
11 |
12 | export default new Vuex.Store({
13 | state,
14 | getters,
15 | mutations,
16 | actions,
17 | modules
18 | })
19 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # hongmu
2 |
3 | > A Vue.js project
4 |
5 | ## Build Setup
6 |
7 | ``` bash
8 | # install dependencies
9 | npm install
10 |
11 | # serve with hot reload at localhost:8080
12 | npm run dev
13 |
14 | # build for production with minification
15 | npm run build
16 |
17 | # build for production and view the bundle analyzer report
18 | npm run build --report
19 | ```
20 |
21 | For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).
22 |
--------------------------------------------------------------------------------
/src/pages/layout/component/main-content/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
26 |
--------------------------------------------------------------------------------
/src/filters/filters.js:
--------------------------------------------------------------------------------
1 | function formatNumber(n) {
2 | const str = n.toString()
3 | return str[1] ? str : `0${str}`
4 | }
5 |
6 | export function formatTime(date) {
7 | const year = date.getFullYear()
8 | const month = date.getMonth() + 1
9 | const day = date.getDate()
10 |
11 | const hour = date.getHours()
12 | const minute = date.getMinutes()
13 | const second = date.getSeconds()
14 |
15 | const t1 = [year, month, day].map(formatNumber).join('/')
16 | const t2 = [hour, minute, second].map(formatNumber).join(':')
17 |
18 | return `${t1} ${t2}`
19 | }
20 |
--------------------------------------------------------------------------------
/src/pages/home/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
29 |
--------------------------------------------------------------------------------
/src/pages/layout/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
25 |
26 |
29 |
--------------------------------------------------------------------------------
/src/pages/layout/component/sidebar-nav.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
33 |
--------------------------------------------------------------------------------
/src/styles/_mixin.scss:
--------------------------------------------------------------------------------
1 | $mainColor:#151519;
2 |
3 | @mixin table-center {
4 | display: table-cell;
5 | vertical-align: middle;
6 | text-align: center;
7 | }
8 |
9 | @mixin poa-center($w, $h) {
10 | position: absolute;
11 | width: $w;
12 | height: $h;
13 | left: 50%;
14 | top: 50%;
15 | transition: translate(-50%, -50%)
16 | }
17 |
18 | @mixin flex-center {
19 | display: flex;
20 | justify-content: center;
21 | align-items: center;
22 | }
23 |
24 | @mixin t-overflow($line:1) {
25 | @if $line==1 {
26 | overflow: hidden;
27 | text-overflow: ellipsis;
28 | white-space: nowrap;
29 | }
30 | @else {
31 | display: -webkit-box;
32 | -webkit-line-clamp: $line;
33 | -webkit-box-orient: vertical;
34 | overflow: hidden;
35 | text-overflow: ellipsis;
36 | }
37 | }
38 |
39 |
40 |
--------------------------------------------------------------------------------
/static/permission.json:
--------------------------------------------------------------------------------
1 | {
2 | "code": 0,
3 | "message": "获取权限成功",
4 | "data": [
5 | {
6 | "name": "订单管理",
7 | "children": [
8 | {
9 | "name": "订单列表"
10 | },
11 | {
12 | "name": "生产管理",
13 | "children": [
14 | {
15 | "name": "生产列表"
16 | },
17 | {
18 | "name": "审核管理"
19 | }
20 | ]
21 | },
22 | {
23 | "name": "退货管理"
24 | }
25 | ]
26 | },
27 | {
28 | "name": "产品管理",
29 | "children": [
30 | {
31 | "name": "产品列表"
32 | },
33 | {
34 | "name": "产品分类"
35 | }
36 | ]
37 | }
38 | ]
39 | }
40 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | // https://eslint.org/docs/user-guide/configuring
2 |
3 | module.exports = {
4 | root: true,
5 | parserOptions: {
6 | parser: 'babel-eslint'
7 | },
8 | env: {
9 | browser: true,
10 | },
11 | extends: [
12 | // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
13 | // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
14 | 'plugin:vue/essential',
15 | // https://github.com/standard/standard/blob/master/docs/RULES-en.md
16 | 'standard'
17 | ],
18 | // required to lint *.vue files
19 | plugins: [
20 | 'vue'
21 | ],
22 | // add your custom rules here
23 | rules: {
24 | "indent": ["error", 4],
25 | // allow async-await
26 | 'generator-star-spacing': 'off',
27 | 'space-before-function-paren': 'off',
28 | // allow debugger during development
29 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/utils/recursion-router.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * @param {Array} userRouter 后台返回的用户权限json
4 | * @param {Array} allRouter 前端配置好的所有动态路由的集合
5 | * @return {Array} realRoutes 过滤后的路由
6 | */
7 |
8 | export function recursionRouter(userRouter = [], allRouter = []) {
9 | var realRoutes = []
10 | allRouter.forEach((v, i) => {
11 | userRouter.forEach((item, index) => {
12 | if (item.name === v.meta.name) {
13 | if (item.children && item.children.length > 0) {
14 | v.children = recursionRouter(item.children, v.children)
15 | }
16 | realRoutes.push(v)
17 | }
18 | })
19 | })
20 | return realRoutes
21 | }
22 |
23 | /**
24 | *
25 | * @param {Array} routes 用户过滤后的路由
26 | *
27 | * 递归为所有有子路由的路由设置第一个children.path为默认路由
28 | */
29 | export function setDefaultRoute(routes) {
30 | routes.forEach((v, i) => {
31 | if (v.children && v.children.length > 0) {
32 | v.redirect = { name: v.children[0].name }
33 | setDefaultRoute(v.children)
34 | }
35 | })
36 | }
37 |
--------------------------------------------------------------------------------
/src/pages/home/component/total-status.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
¥455025元
8 |
本月销售总额
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
24 |
25 |
46 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 |
4 | import Login from 'pages/login/login'
5 | import NotFound from 'pages/errorPage/404'
6 | import Forbidden from 'pages/errorPage/403'
7 | import Layout from 'pages/layout/index'
8 | import Home from 'pages/home/index'
9 |
10 | Vue.use(Router)
11 |
12 | /* 初始路由 */
13 | export default new Router({
14 | routes: [
15 | {
16 | path: '/login',
17 | component: Login
18 | }
19 | ]
20 | })
21 |
22 | /* 准备动态添加的路由 */
23 | export const DynamicRoutes = [
24 | {
25 | path: '',
26 | component: Layout,
27 | name: 'container',
28 | redirect: 'home',
29 | meta: {
30 | requiresAuth: true,
31 | name: '首页'
32 | },
33 | children: [
34 | {
35 | path: 'home',
36 | component: Home,
37 | name: 'home',
38 | meta: {
39 | name: '首页',
40 | icon: 'icon-home'
41 | }
42 | }
43 | ]
44 | },
45 | {
46 | path: '/403',
47 | component: Forbidden
48 | },
49 | {
50 | path: '*',
51 | component: NotFound
52 | }
53 | ]
54 |
--------------------------------------------------------------------------------
/src/components/dynamic-menu.vue:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 |
39 |
40 |
43 |
--------------------------------------------------------------------------------
/src/styles/_sidebar.scss:
--------------------------------------------------------------------------------
1 | /* 侧边栏 */
2 | .sidebar {
3 | width: 200px !important;
4 | height: 100%;
5 | background: #304156;
6 | transition: all 0.25s;
7 | position: fixed;
8 | top: 0;
9 | bottom: 0;
10 | left: 0;
11 | z-index: 100;
12 | overflow-x: hidden;
13 | .iconfont {
14 | margin-right: 8px;
15 | color: #fff;
16 | font-size: 18px;
17 | }
18 | >div.menu-container>li.el-menu-item,
19 | >div.menu-container>li.el-submenu>.el-submenu__title {
20 | border-bottom: 1px solid rgba(238, 238, 238, 0.1);
21 | }
22 | .el-menu-item {
23 | background: #304156 !important;
24 | }
25 | /* 菜单hover时的背景 */
26 | .el-submenu__title:hover,
27 | .el-menu-item:hover {
28 | background: #223041 !important;
29 | }
30 | /* 菜单active时的背景 */
31 | /* .el-menu-item.is-active {
32 | background: #293748 !important;
33 | } */
34 | }
35 |
36 | /* 主体内容 */
37 | .main-container {
38 | min-height: 100%;
39 | margin-left: 200px;
40 | transition: margin-left 0.25s;
41 | position: relative;
42 | box-sizing: border-box;
43 | padding-top: 50px;
44 | }
45 |
46 | /* 折叠菜单下的样式 */
47 | .navCollapsed {
48 | .sidebar {
49 | width: 64px !important;
50 | ul {
51 | display: none;
52 | }
53 | .iconfont+span {
54 | display: none;
55 | }
56 | .el-submenu__icon-arrow {
57 | display: none;
58 | }
59 | }
60 | .main-container {
61 | margin-left: 64px;
62 | }
63 | .aside__top{
64 | left:64px!important;
65 | }
66 | }
--------------------------------------------------------------------------------
/src/styles/_reset_element.scss:
--------------------------------------------------------------------------------
1 | .el-menu {
2 | border: none;
3 | .iconfont {
4 | color: #fff;
5 | font-size: 16px;
6 | }
7 | .el-submenu__title {
8 | &:hover {
9 | background: none !important;
10 | }
11 | i.el-submenu__icon-arrow {
12 | color: #ddd;
13 | font-size: 15px;
14 | }
15 | }
16 | .el-menu-item-group__title {
17 | padding: 0;
18 | }
19 | }
20 |
21 | .el-breadcrumb {
22 | display: inline-block;
23 | vertical-align: middle;
24 | font-size: 14px;
25 | margin-left: 5px;
26 | .el-breadcrumb__inner {
27 | &.is-link {
28 | display: inline-block;
29 | font-weight: normal;
30 | color: #424040 !important;
31 | }
32 | }
33 | .is-last-link .is-link {
34 | font-weight: normal;
35 | color: #999 !important;
36 | }
37 | }
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | .sidebar-container {
49 | transition: width .28s;
50 | width: 180px ;
51 | height: 100%;
52 | position: fixed;
53 | top: 0;
54 | bottom: 0;
55 | left: 0;
56 | z-index: 1001;
57 | background: rgba(0,0,0,0.5)
58 | }
59 |
60 |
61 |
62 |
63 | .sidebar-container.navCollapsed {
64 | width: 63px ;
65 | }
66 |
67 | .navCollapsed{
68 | .el-submenu {
69 | &>.el-submenu__title {
70 | &>span {
71 | display: none;
72 | }
73 | .el-submenu__icon-arrow {
74 | display: none;
75 | }
76 | }
77 | }
78 |
79 | }
80 |
81 |
82 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from '@/App'
3 | import store from '@/store/index'
4 | import router from '@/router/index'
5 |
6 | import ElementUI from 'element-ui'
7 | import 'element-ui/lib/theme-chalk/index.css'
8 | import './styles/index.scss'
9 |
10 | import axios from './config/httpConfig'
11 | import * as globalFilter from './filters/filters'
12 |
13 | Vue.prototype.$http = axios
14 |
15 | Object.keys(globalFilter).forEach(key => {
16 | Vue.filter(key, globalFilter[key])
17 | })
18 |
19 | Vue.use(ElementUI)
20 |
21 | Vue.config.productionTip = false
22 |
23 | router.beforeEach((to, from, next) => {
24 | if (!store.state.UserToken) {
25 | if (
26 | to.matched.length > 0 &&
27 | !to.matched.some(record => record.meta.requiresAuth)
28 | ) {
29 | next()
30 | } else {
31 | next({ path: '/login' })
32 | }
33 | } else {
34 | if (!store.state.permission.permissionList) {
35 | store.dispatch('permission/FETCH_PERMISSION').then(() => {
36 | next({ path: to.path })
37 | })
38 | } else {
39 | if (to.path !== '/login') {
40 | next()
41 | } else {
42 | next(from.fullPath)
43 | }
44 | }
45 | }
46 | })
47 |
48 | router.afterEach((to, from, next) => {
49 | var routerList = to.matched
50 | store.commit('setCrumbList', routerList)
51 | store.commit('permission/SET_CURRENT_MENU', to.name)
52 | })
53 |
54 | /* eslint-disable no-new */
55 | new Vue({
56 | el: '#app',
57 | router,
58 | store,
59 | components: { App },
60 | template: ''
61 | })
62 |
--------------------------------------------------------------------------------
/src/pages/home/component/charts.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
home
4 |
home
5 |
home
6 |
home
7 |
home
8 |
home
9 |
home
10 |
home
11 |
home
12 |
home
13 |
home
14 |
home
15 |
home
16 |
home
17 |
home
18 |
home
19 |
home
20 |
home
21 |
home
22 |
home
23 |
home
24 |
home
25 |
home
26 |
home
27 |
home
28 |
home
29 |
home
30 |
home
31 |
home
32 |
home
33 |
home
34 |
home
35 |
home
36 |
home
37 |
home
38 |
home
39 |
home
40 |
home
41 |
home
42 |
home
43 |
home
44 |
home
45 |
home
46 |
home
47 |
home
48 |
home
49 |
home
50 |
home
51 |
home
52 |
home
53 |
home
54 |
home
55 |
home
56 |
home
57 |
home
58 |
home
59 |
home
60 |
home
61 |
home
62 |
home
63 |
home
64 |
home
65 |
home
66 |
home
67 |
home
68 |
home
69 |
home
70 |
home
71 |
home
72 |
home
73 |
74 |
75 |
76 |
83 |
--------------------------------------------------------------------------------
/src/store/modules/permission.js:
--------------------------------------------------------------------------------
1 | import { fetchPermission } from '@/api/permission'
2 | import router, { DynamicRoutes } from '@/router/index'
3 | import { recursionRouter, setDefaultRoute } from '@/utils/recursion-router'
4 | import dynamicRouter from '@/router/dynamic-router'
5 |
6 | export default {
7 | namespaced: true,
8 | state: {
9 | permissionList: null /** 所有路由 */,
10 | sidebarMenu: [] /** 导航菜单 */,
11 | currentMenu: '' /** 当前active导航菜单 */
12 | },
13 | getters: {},
14 | mutations: {
15 | SET_PERMISSION(state, routes) {
16 | state.permissionList = routes
17 | },
18 | CLEAR_PERMISSION(state) {
19 | state.permissionList = null
20 | },
21 | SET_MENU(state, menu) {
22 | state.sidebarMenu = menu
23 | },
24 | CLEAR_MENU(state) {
25 | state.sidebarMenu = []
26 | },
27 | SET_CURRENT_MENU(state, currentMenu) {
28 | state.currentMenu = currentMenu
29 | }
30 | },
31 | actions: {
32 | async FETCH_PERMISSION({ commit, state }) {
33 | let permissionList = await fetchPermission()
34 |
35 | /* 根据权限筛选出我们设置好的路由并加入到path=''的children */
36 | let routes = recursionRouter(permissionList, dynamicRouter)
37 | let MainContainer = DynamicRoutes.find(v => v.path === '')
38 | let children = MainContainer.children
39 | children.push(...routes)
40 |
41 | /* 生成左侧导航菜单 */
42 | commit('SET_MENU', children)
43 |
44 | /*
45 | 为所有有children的菜单路由设置第一个children为默认路由
46 | 主要是供面包屑用,防止点击面包屑后进入某个路由下的 '' 路由,比如/manage/
47 | 而我们的路由是
48 | [
49 | /manage/menu1,
50 | /manage/menu2
51 | ]
52 | */
53 | setDefaultRoute([MainContainer])
54 |
55 | /* 初始路由 */
56 | let initialRoutes = router.options.routes
57 |
58 | /* 动态添加路由 */
59 | router.addRoutes(DynamicRoutes)
60 |
61 | /* 完整的路由表 */
62 | commit('SET_PERMISSION', [...initialRoutes, ...DynamicRoutes])
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hongmu",
3 | "version": "1.0.0",
4 | "description": "A Vue.js project",
5 | "author": "fengkz ",
6 | "private": true,
7 | "scripts": {
8 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
9 | "start": "npm run dev",
10 | "lint": "eslint --ext .js,.vue src",
11 | "build": "node build/build.js"
12 | },
13 | "dependencies": {
14 | "axios": "^0.18.0",
15 | "element-ui": "^2.3.6",
16 | "vue": "^2.5.2",
17 | "vue-router": "^3.0.1",
18 | "vuex": "^3.0.1"
19 | },
20 | "devDependencies": {
21 | "autoprefixer": "^7.1.2",
22 | "babel-core": "^6.22.1",
23 | "babel-eslint": "^8.2.1",
24 | "babel-helper-vue-jsx-merge-props": "^2.0.3",
25 | "babel-loader": "^7.1.1",
26 | "babel-plugin-syntax-jsx": "^6.18.0",
27 | "babel-plugin-transform-runtime": "^6.22.0",
28 | "babel-plugin-transform-vue-jsx": "^3.5.0",
29 | "babel-preset-env": "^1.3.2",
30 | "babel-preset-stage-2": "^6.22.0",
31 | "chalk": "^2.0.1",
32 | "copy-webpack-plugin": "^4.0.1",
33 | "css-loader": "^0.28.0",
34 | "eslint": "^4.15.0",
35 | "eslint-config-standard": "^10.2.1",
36 | "eslint-friendly-formatter": "^3.0.0",
37 | "eslint-loader": "^1.7.1",
38 | "eslint-plugin-import": "^2.7.0",
39 | "eslint-plugin-node": "^5.2.0",
40 | "eslint-plugin-promise": "^3.4.0",
41 | "eslint-plugin-standard": "^3.0.1",
42 | "eslint-plugin-vue": "^4.0.0",
43 | "extract-text-webpack-plugin": "^3.0.0",
44 | "file-loader": "^1.1.4",
45 | "friendly-errors-webpack-plugin": "^1.6.1",
46 | "html-webpack-plugin": "^2.30.1",
47 | "node-notifier": "^5.1.2",
48 | "node-sass": "^4.8.3",
49 | "optimize-css-assets-webpack-plugin": "^3.2.0",
50 | "ora": "^1.2.0",
51 | "portfinder": "^1.0.13",
52 | "postcss-import": "^11.0.0",
53 | "postcss-loader": "^2.0.8",
54 | "postcss-url": "^7.2.1",
55 | "rimraf": "^2.6.0",
56 | "sass-loader": "^7.0.1",
57 | "semver": "^5.3.0",
58 | "shelljs": "^0.7.6",
59 | "uglifyjs-webpack-plugin": "^1.1.1",
60 | "url-loader": "^0.5.8",
61 | "vue-loader": "^13.3.0",
62 | "vue-style-loader": "^3.0.1",
63 | "vue-template-compiler": "^2.5.2",
64 | "webpack": "^3.6.0",
65 | "webpack-bundle-analyzer": "^2.9.0",
66 | "webpack-dev-server": "^2.9.1",
67 | "webpack-merge": "^4.1.0"
68 | },
69 | "engines": {
70 | "node": ">= 6.0.0",
71 | "npm": ">= 3.0.0"
72 | },
73 | "browserslist": [
74 | "> 1%",
75 | "last 2 versions",
76 | "not ie <= 8"
77 | ]
78 | }
79 |
--------------------------------------------------------------------------------
/src/styles/_normalize.scss:
--------------------------------------------------------------------------------
1 | @charset "utf-8";
2 |
3 | html {
4 |
5 | color: #000;
6 | background: #fff;
7 | overflow-y: scroll;
8 | -webkit-text-size-adjust: 100%;
9 | -ms-text-size-adjust: 100%;
10 | }
11 |
12 | html * {
13 | outline: none;
14 | -webkit-text-size-adjust: none;
15 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
16 | box-sizing: border-box;
17 | }
18 |
19 | html,
20 | body {
21 | font-family: "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif;
22 | height: 100%;
23 | width: 100%;
24 | overflow: auto;
25 | }
26 |
27 | body,
28 | div,
29 | dl,
30 | dt,
31 | dd,
32 | ul,
33 | ol,
34 | li,
35 | h1,
36 | h2,
37 | h3,
38 | h4,
39 | h5,
40 | h6,
41 | pre,
42 | code,
43 | form,
44 | fieldset,
45 | legend,
46 | input,
47 | textarea,
48 | p,
49 | blockquote,
50 | th,
51 | td,
52 | hr,
53 | button,
54 | article,
55 | aside,
56 | details,
57 | figcaption,
58 | figure,
59 | footer,
60 | header,
61 | hgroup,
62 | menu,
63 | nav,
64 | section {
65 | margin: 0;
66 | padding: 0;
67 | }
68 |
69 | input,
70 | select,
71 | textarea {
72 | font-size: 100%;
73 | }
74 |
75 | table {
76 | border-collapse: collapse;
77 | border-spacing: 0;
78 | }
79 |
80 | fieldset,
81 | img {
82 | border: 0;
83 | }
84 |
85 | abbr,
86 | acronym {
87 | border: 0;
88 | font-variant: normal;
89 | }
90 |
91 | del {
92 | text-decoration: line-through;
93 | }
94 |
95 | address,
96 | caption,
97 | cite,
98 | code,
99 | dfn,
100 | em,
101 | th,
102 | i,
103 | var {
104 | font-style: normal;
105 | font-weight: 500;
106 | }
107 |
108 | ol,
109 | ul {
110 | list-style: none;
111 | }
112 |
113 | caption,
114 | th {
115 | text-align: left;
116 | }
117 |
118 | h1,
119 | h2,
120 | h3,
121 | h4,
122 | h5,
123 | h6 {
124 | font-size: 100%;
125 | font-weight: 500;
126 | }
127 |
128 | q:before,
129 | q:after {
130 | content: '';
131 | }
132 |
133 | sub,
134 | sup {
135 | font-size: 75%;
136 | line-height: 0;
137 | position: relative;
138 | vertical-align: baseline;
139 | }
140 |
141 | sup {
142 | top: -0.5em;
143 | }
144 |
145 | sub {
146 | bottom: -0.25em;
147 | }
148 |
149 | a:hover {
150 | text-decoration: underline;
151 | }
152 |
153 | ins,
154 | a,
155 | a:active,
156 | a:visited,
157 | a:link {
158 | text-decoration: none;
159 | }
160 |
161 | .clearfix {
162 | &:after {
163 | display: table;
164 | clear: both;
165 | content: "";
166 | visibility: hidden;
167 | ;
168 | height: 0;
169 | }
170 | }
171 |
172 |
--------------------------------------------------------------------------------
/config/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | // Template version: 1.2.6
3 | // see http://vuejs-templates.github.io/webpack for documentation.
4 |
5 | const path = require('path')
6 |
7 | module.exports = {
8 | dev: {
9 |
10 | // Paths
11 | assetsSubDirectory: 'static',
12 | assetsPublicPath: '/',
13 | proxyTable: {},
14 |
15 | // Various Dev Server settings
16 | host: 'localhost', // can be overwritten by process.env.HOST
17 | port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
18 | autoOpenBrowser: true,
19 | errorOverlay: true,
20 | notifyOnErrors: false,
21 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
22 |
23 | // Use Eslint Loader?
24 | // If true, your code will be linted during bundling and
25 | // linting errors and warnings will be shown in the console.
26 | useEslint: true,
27 | // If true, eslint errors and warnings will also be shown in the error overlay
28 | // in the browser.
29 | showEslintErrorsInOverlay: false,
30 |
31 | /**
32 | * Source Maps
33 | */
34 |
35 | // https://webpack.js.org/configuration/devtool/#development
36 | devtool: 'cheap-source-map',
37 |
38 | // If you have problems debugging vue-files in devtools,
39 | // set this to false - it *may* help
40 | // https://vue-loader.vuejs.org/en/options.html#cachebusting
41 | cacheBusting: true,
42 |
43 | // CSS Sourcemaps off by default because relative paths are "buggy"
44 | // with this option, according to the CSS-Loader README
45 | // (https://github.com/webpack/css-loader#sourcemaps)
46 | // In our experience, they generally work as expected,
47 | // just be aware of this issue when enabling this option.
48 | cssSourceMap: false,
49 | },
50 |
51 | build: {
52 | // Template for index.html
53 | index: path.resolve(__dirname, '../dist/index.html'),
54 |
55 | // Paths
56 | assetsRoot: path.resolve(__dirname, '../dist'),
57 | assetsSubDirectory: 'static',
58 |
59 | // you can set by youself according to actual condition
60 | assetsPublicPath: './',
61 |
62 | /**
63 | * Source Maps
64 | */
65 |
66 | productionSourceMap: false,
67 | // https://webpack.js.org/configuration/devtool/#production
68 | devtool: '#source-map',
69 |
70 | // Gzip off by default as many popular static hosts such as
71 | // Surge or Netlify already gzip all static assets for you.
72 | // Before setting to `true`, make sure to:
73 | // npm install --save-dev compression-webpack-plugin
74 | productionGzip: false,
75 | productionGzipExtensions: ['js', 'css'],
76 |
77 | // Run the build command with an extra argument to
78 | // View the bundle analyzer report after build finishes:
79 | // `npm run build --report`
80 | // Set to `true` or `false` to always turn it on or off
81 | bundleAnalyzerReport: process.env.npm_config_report
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/config/httpConfig.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import store from '@/store/index.js'
3 | import baseURL from './baseUrl'
4 | import { Message } from 'element-ui'
5 | const http = {}
6 |
7 | var instance = axios.create({
8 | timeout: 5000,
9 | baseURL
10 | })
11 |
12 | // 添加请求拦截器
13 | instance.interceptors.request.use(
14 | function(config) {
15 | // 请求头添加token
16 | if (store.state.UserToken) {
17 | config.headers.Authorization = store.state.UserToken
18 | }
19 | return config
20 | },
21 | function(error) {
22 | return Promise.reject(error)
23 | }
24 | )
25 |
26 | // 响应拦截器即异常处理
27 | instance.interceptors.response.use(
28 | response => {
29 | return response.data
30 | },
31 | err => {
32 | if (err && err.response) {
33 | switch (err.response.status) {
34 | case 400:
35 | err.message = '请求出错'
36 | break
37 | case 401:
38 | Message.warning({
39 | message: '授权失败,请重新登录'
40 | })
41 | store.commit('LOGIN_OUT')
42 | setTimeout(() => {
43 | window.location.reload()
44 | }, 1000)
45 |
46 | return
47 | case 403:
48 | err.message = '拒绝访问'
49 | break
50 | case 404:
51 | err.message = '请求错误,未找到该资源'
52 | break
53 | case 500:
54 | err.message = '服务器端出错'
55 | break
56 | }
57 | } else {
58 | err.message = '连接服务器失败'
59 | }
60 | Message.error({
61 | message: err.message
62 | })
63 | return Promise.reject(err.response)
64 | }
65 | )
66 |
67 | http.get = function(url, options) {
68 | return new Promise((resolve, reject) => {
69 | instance
70 | .get(url, options)
71 | .then(response => {
72 | if (response.code === 0) {
73 | resolve(response.data)
74 | } else {
75 | Message.error({
76 | message: response.message
77 | })
78 | reject(response.message)
79 | }
80 | })
81 | .catch(e => {
82 | console.log(e)
83 | })
84 | })
85 | }
86 |
87 | http.post = function(url, data, options) {
88 | return new Promise((resolve, reject) => {
89 | instance
90 | .post(url, data, options)
91 | .then(response => {
92 | if (response.code === 0) {
93 | resolve(response.data)
94 | } else {
95 | Message.error({
96 | message: response.message
97 | })
98 | reject(response.message)
99 | }
100 | })
101 | .catch(e => {
102 | console.log(e)
103 | })
104 | })
105 | }
106 |
107 | export default http
108 |
--------------------------------------------------------------------------------
/src/pages/login/login.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
随便搞个登录页
4 |
5 |
6 | 账号:
7 |
8 |
9 |
10 | 密码:
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
43 |
44 |
117 |
--------------------------------------------------------------------------------
/src/router/dynamic-router.js:
--------------------------------------------------------------------------------
1 | /* 订单管理 */
2 | const Order = () => import('pages/order-manage')
3 | const OrderList = () => import('pages/order-manage/order-list')
4 | const ProductManage = () => import('pages/order-manage/product-manage')
5 | const ProductionList = () =>
6 | import('pages/order-manage/product-manage/production-list')
7 | const ReviewManage = () =>
8 | import('pages/order-manage/product-manage/review-manage')
9 | const ReturnGoods = () => import('pages/order-manage/return-goods')
10 |
11 | /* 产品管理 */
12 | const Goods = () => import('pages/goods-manage')
13 | const GoodsList = () => import('pages/goods-manage/goods-list')
14 | const GoodsClassify = () => import('pages/goods-manage/goods-classify')
15 |
16 | /* 需要权限判断的路由 */
17 | const dynamicRoutes = [
18 | {
19 | path: '/order',
20 | component: Order,
21 | name: 'order-manage',
22 | meta: {
23 | name: '订单管理',
24 | icon: 'icon-email'
25 | },
26 | children: [
27 | {
28 | path: 'list',
29 | name: 'order-list',
30 | component: OrderList,
31 | meta: {
32 | name: '订单列表',
33 | icon: 'icon-quit'
34 | }
35 | },
36 | {
37 | path: 'product',
38 | name: 'product-manage',
39 | component: ProductManage,
40 | meta: {
41 | name: '生产管理',
42 | icon: 'icon-service'
43 | },
44 | children: [
45 | {
46 | path: 'list',
47 | name: 'product-list',
48 | component: ProductionList,
49 | meta: {
50 | name: '生产列表',
51 | icon: 'icon-nav'
52 | }
53 | },
54 | {
55 | path: 'review',
56 | name: 'review-manage',
57 | component: ReviewManage,
58 | meta: {
59 | name: '审核管理',
60 | icon: 'icon-finance-manage'
61 | }
62 | }
63 | ]
64 | },
65 | {
66 | path: 'returnGoods',
67 | name: 'return-goods',
68 | component: ReturnGoods,
69 | meta: {
70 | name: '退货管理',
71 | icon: 'icon-product-manage'
72 | }
73 | }
74 | ]
75 | },
76 | {
77 | path: '/goods',
78 | component: Goods,
79 | name: 'goods',
80 | meta: {
81 | name: '产品管理',
82 | icon: 'icon-order-manage'
83 | },
84 | children: [
85 | {
86 | path: 'list',
87 | name: 'goods-list',
88 | component: GoodsList,
89 | meta: {
90 | name: '产品列表',
91 | icon: 'icon-home'
92 | }
93 | },
94 | {
95 | path: 'classify',
96 | name: 'goods-classify',
97 | component: GoodsClassify,
98 | meta: {
99 | name: '产品分类',
100 | icon: 'icon-product-manage'
101 | }
102 | }
103 | ]
104 | }
105 | ]
106 |
107 | export default dynamicRoutes
108 |
--------------------------------------------------------------------------------
/src/pages/layout/component/main-content/top-aside.vue:
--------------------------------------------------------------------------------
1 |
2 |
45 |
46 |
47 |
69 |
70 |
187 |
--------------------------------------------------------------------------------
/src/pages/errorPage/403.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
{{ message }}
7 |
对不起,你没有权限
8 |
返回首页
9 |
10 |
11 |
12 |
13 |
14 |
32 |
221 |
--------------------------------------------------------------------------------
/src/pages/errorPage/404.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
{{ message }}
7 |
请检查您输入的网址是否正确
8 |
返回首页
9 |
10 |
11 |
12 |
13 |
14 |
32 |
221 |
--------------------------------------------------------------------------------