├── .browserslistrc
├── .eslintrc.js
├── .gitignore
├── README.md
├── babel.config.js
├── package.json
├── public
├── favicon.ico
└── index.html
├── src
├── App.vue
├── antd
│ └── index.ts
├── api
│ └── index.ts
├── assets
│ ├── images
│ │ ├── error
│ │ │ ├── 403.png
│ │ │ └── 404.png
│ │ ├── login
│ │ │ ├── login_bg.jpg
│ │ │ ├── login_bg.png
│ │ │ ├── login_bg1.jpg
│ │ │ └── login_form.png
│ │ └── logo.png
│ └── logo.png
├── axios.d.ts
├── components
│ ├── icon_font
│ │ └── index.ts
│ └── tabs
│ │ └── index.vue
├── config
│ └── baseURL.ts
├── main.ts
├── permission.ts
├── router
│ └── index.ts
├── shims-vue.d.ts
├── store
│ ├── actions.ts
│ ├── getters.ts
│ ├── index.ts
│ ├── modules
│ │ ├── asyncRouter.ts
│ │ └── user.ts
│ ├── mutation-types.ts
│ └── mutations.ts
├── styles
│ ├── index.less
│ ├── loading.less
│ └── normalize.less
├── utils
│ ├── axios.ts
│ ├── index.ts
│ └── recursion-router.ts
└── views
│ ├── demo
│ ├── icon
│ │ └── index.vue
│ └── table
│ │ └── index.vue
│ ├── echart
│ ├── bar
│ │ └── index.vue
│ ├── line
│ │ └── index.vue
│ └── pie
│ │ └── index.vue
│ ├── empty_layout
│ └── index.vue
│ ├── error
│ ├── 403.vue
│ └── 404.vue
│ ├── index
│ └── index.vue
│ ├── layout
│ ├── index.vue
│ └── menu
│ │ ├── index.vue
│ │ └── sub-menu.vue
│ ├── login
│ └── Login.vue
│ ├── order
│ ├── good
│ │ ├── check
│ │ │ └── index.vue
│ │ └── list
│ │ │ └── index.vue
│ ├── list
│ │ └── index.vue
│ └── return_goods
│ │ └── index.vue
│ ├── permission
│ ├── menu_manage
│ │ └── index.vue
│ ├── role_manage
│ │ └── index.vue
│ └── user_manage
│ │ └── index.vue
│ └── product
│ ├── category
│ └── index.vue
│ └── list
│ └── index.vue
├── tsconfig.json
└── vue.config.js
/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not dead
4 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true
5 | },
6 | extends: [
7 | 'plugin:vue/vue3-essential',
8 | 'eslint:recommended',
9 | '@vue/typescript/recommended',
10 | // '@vue/prettier',
11 | // '@vue/prettier/@typescript-eslint'
12 | ],
13 | parserOptions: {
14 | ecmaVersion: 2020
15 | },
16 | rules: {
17 | 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
18 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
19 | "@typescript-eslint/no-explicit-any": ["off"],
20 | "@typescript-eslint/explicit-module-boundary-types": ["off"],
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 |
6 | # local env files
7 | .env.local
8 | .env.*.local
9 |
10 | # Log files
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 | pnpm-debug.log*
15 |
16 | # Editor directories and files
17 | .idea
18 | .vscode
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vue3-admin
2 |
3 | ## Project setup
4 | ```
5 | npm install
6 | ```
7 |
8 | ### Compiles and hot-reloads for development
9 | ```
10 | npm run serve:randy
11 | ```
12 |
13 | ### Compiles and minifies for production
14 | ```
15 | npm run build
16 | ```
17 |
18 | ### Lints and fixes files
19 | ```
20 | npm run lint
21 | ```
22 |
23 | ### Customize configuration
24 | See [Configuration Reference](https://cli.vuejs.org/config/).
25 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['@vue/cli-plugin-babel/preset'],
3 | plugins: [
4 | ["import", { "libraryName": "ant-design-vue", "libraryDirectory": "es", "style": "css" }]
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue3-admin",
3 | "version": "0.1.0",
4 | "private": true,
5 | "authors": "543245444@qq.com",
6 | "scripts": {
7 | "serve": "vue-cli-service serve",
8 | "serve:randy": "cross-env API_TYPE=randy vue-cli-service serve",
9 | "build": "vue-cli-service build",
10 | "lint": "vue-cli-service lint"
11 | },
12 | "dependencies": {
13 | "ant-design-vue": "2.0.0",
14 | "axios": "^0.21.1",
15 | "core-js": "^3.6.5",
16 | "echarts": "^5.1.2",
17 | "vue": "^3.0.0",
18 | "vue-router": "^4.0.0-0",
19 | "vuex": "^4.0.0-0"
20 | },
21 | "devDependencies": {
22 | "@typescript-eslint/eslint-plugin": "^4.18.0",
23 | "@typescript-eslint/parser": "^4.18.0",
24 | "@vue/cli-plugin-babel": "~4.5.0",
25 | "@vue/cli-plugin-eslint": "~4.5.0",
26 | "@vue/cli-plugin-router": "~4.5.0",
27 | "@vue/cli-plugin-typescript": "~4.4.0",
28 | "@vue/cli-plugin-vuex": "~4.5.0",
29 | "@vue/cli-service": "~4.5.0",
30 | "@vue/compiler-sfc": "^3.0.0",
31 | "@vue/eslint-config-prettier": "^6.0.0",
32 | "@vue/eslint-config-typescript": "^7.0.0",
33 | "add-asset-html-webpack-plugin": "^3.2.0",
34 | "babel-plugin-import": "^1.13.3",
35 | "compression-webpack-plugin": "^4.0.0",
36 | "cross-env": "^7.0.3",
37 | "eslint": "^6.7.2",
38 | "eslint-plugin-prettier": "^3.3.1",
39 | "eslint-plugin-vue": "^7.0.0",
40 | "less": "^4.1.1",
41 | "less-loader": "^7.3.0",
42 | "prettier": "^2.2.1",
43 | "typescript": "~4.1.5",
44 | "webpack-bundle-analyzer": "^3.9.0",
45 | "vue-loader-v16": "^16.0.0-beta.5.4",
46 | "webpack": "^4.46.0"
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/loveRandy/vue3/120d25034b8b3d13af355af2b9740624716e242e/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= htmlWebpackPlugin.options.title %>
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
19 |

20 |
加载中,请稍后...
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/antd/index.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Form,
3 | Input,
4 | Button,
5 | Layout,
6 | Menu,
7 | Row,
8 | Col,
9 | Dropdown,
10 | Avatar,
11 | Tabs,
12 | Table,
13 | Alert,
14 | Card,
15 | List,
16 | Pagination,
17 | Divider,
18 | Popconfirm,
19 | Modal,
20 | Select,
21 | Result,
22 | Carousel
23 | } from 'ant-design-vue'
24 | import 'ant-design-vue/dist/antd.css'
25 | const components = [
26 | Form,
27 | Input,
28 | Button,
29 | Layout,
30 | Menu,
31 | Row,
32 | Col,
33 | Dropdown,
34 | Avatar,
35 | Tabs,
36 | Table,
37 | Alert,
38 | Card,
39 | List,
40 | Pagination,
41 | Divider,
42 | Popconfirm,
43 | Modal,
44 | Select,
45 | Result,
46 | Carousel
47 | ]
48 |
49 | export function setupAntd (app: any): any {
50 | components.forEach(component => {
51 | app.use(component)
52 | })
53 | }
54 |
--------------------------------------------------------------------------------
/src/api/index.ts:
--------------------------------------------------------------------------------
1 | import request from '@/utils/axios'
2 | import { AxiosRequestConfig }from 'axios'
3 |
4 | export const getRoleList = () => {
5 | const obj:AxiosRequestConfig = {
6 | url:'/user/info',
7 | method:'get'
8 | }
9 | return request(obj)
10 | }
11 |
12 | export const doLogin = (data:any) => {
13 | const obj:AxiosRequestConfig = {
14 | url:'/user/login',
15 | method:'post',
16 | data
17 | }
18 | return request(obj)
19 | }
20 |
--------------------------------------------------------------------------------
/src/assets/images/error/403.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/loveRandy/vue3/120d25034b8b3d13af355af2b9740624716e242e/src/assets/images/error/403.png
--------------------------------------------------------------------------------
/src/assets/images/error/404.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/loveRandy/vue3/120d25034b8b3d13af355af2b9740624716e242e/src/assets/images/error/404.png
--------------------------------------------------------------------------------
/src/assets/images/login/login_bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/loveRandy/vue3/120d25034b8b3d13af355af2b9740624716e242e/src/assets/images/login/login_bg.jpg
--------------------------------------------------------------------------------
/src/assets/images/login/login_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/loveRandy/vue3/120d25034b8b3d13af355af2b9740624716e242e/src/assets/images/login/login_bg.png
--------------------------------------------------------------------------------
/src/assets/images/login/login_bg1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/loveRandy/vue3/120d25034b8b3d13af355af2b9740624716e242e/src/assets/images/login/login_bg1.jpg
--------------------------------------------------------------------------------
/src/assets/images/login/login_form.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/loveRandy/vue3/120d25034b8b3d13af355af2b9740624716e242e/src/assets/images/login/login_form.png
--------------------------------------------------------------------------------
/src/assets/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/loveRandy/vue3/120d25034b8b3d13af355af2b9740624716e242e/src/assets/images/logo.png
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/loveRandy/vue3/120d25034b8b3d13af355af2b9740624716e242e/src/assets/logo.png
--------------------------------------------------------------------------------
/src/axios.d.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-undef */
2 | /* eslint-disable no-unused-vars */
3 | import * as axios from 'axios'
4 |
5 | declare module 'axios' {
6 | interface AxiosInstance {
7 | (config: AxiosRequestConfig): Promise
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/components/icon_font/index.ts:
--------------------------------------------------------------------------------
1 | import { createFromIconfontCN } from '@ant-design/icons-vue'
2 | const IconFont = createFromIconfontCN({
3 | scriptUrl: '//at.alicdn.com/t/font_2616466_kta9zjvexr.js'
4 | })
5 | export default IconFont
6 |
--------------------------------------------------------------------------------
/src/components/tabs/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/config/baseURL.ts:
--------------------------------------------------------------------------------
1 | const baseURL:string = process.env.NODE_ENV === 'production' ? '/' : '/api'
2 | export default baseURL
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import App from './App.vue'
3 | import router from './router'
4 | import store from './store'
5 | import { setupAntd } from '@/antd'
6 | import IconFont from '@/components/icon_font'
7 | import './permission'
8 | import '@/styles/index.less'
9 |
10 |
11 | const app = createApp(App)
12 | const win: any = window //
13 | if (process.env.NODE_ENV === 'development') {
14 | if ('__VUE_DEVTOOLS_GLOBAL_HOOK__' in win) {
15 | // 这里__VUE_DEVTOOLS_GLOBAL_HOOK__.Vue赋值一个createApp实例
16 | win.__VUE_DEVTOOLS_GLOBAL_HOOK__.Vue = app
17 | }
18 | }
19 | setupAntd(app)
20 | app.use(store)
21 | app.use(router)
22 | app.component('IconFont', IconFont)
23 | app.mount('#app')
24 |
--------------------------------------------------------------------------------
/src/permission.ts:
--------------------------------------------------------------------------------
1 | import router from '@/router'
2 | import store from './store'
3 |
4 |
5 | router.beforeEach(async (to) => {
6 |
7 | if (to.path === '/login' || to.path === '/404') {
8 | return true
9 | } else {
10 | const token = localStorage.getItem('token')
11 | if (!token) {
12 | return {
13 | name:'login'
14 | }
15 | } else {
16 | if (store.state.menuList.length === 0) {
17 | //根据接口获取路由信息
18 | const accessedRoutes = await store.dispatch('changeAsyncRoute', token)
19 |
20 | //动态增加路由
21 | accessedRoutes.forEach((item: any) => {
22 | router.addRoute(item)
23 | })
24 | router.push({ path: to.path })
25 | return true
26 | } else {
27 | return true
28 | }
29 | }
30 | }
31 | })
32 |
--------------------------------------------------------------------------------
/src/router/index.ts:
--------------------------------------------------------------------------------
1 | import { createRouter, createWebHashHistory } from 'vue-router'
2 | import Layout from '@/views/layout/index.vue'
3 | import EmptyLayout from '@/views/empty_layout/index.vue'
4 | export const constantRoutes = [
5 | {
6 | path: '/',
7 | component: Layout,
8 | redirect: '/index',
9 | name: 'Index',
10 | meta: {
11 | title: '首页',
12 | icon: 'icon-comments',
13 | single: true
14 | },
15 | children: [
16 | {
17 | path: '/index',
18 | name: 'Index',
19 | component: () => import('@/views/index/index.vue'),
20 | meta: {
21 | title: '首页',
22 | icon: 'icon-youxiang'
23 | }
24 | }
25 | ]
26 | },
27 | {
28 | path: '/demo',
29 | component: Layout,
30 | name: 'Demo',
31 | redirect: '/demo/table',
32 | meta: {
33 | title: '组件',
34 | icon: 'icon-product'
35 | },
36 | children: [
37 | {
38 | path: '/demo/table',
39 | name: 'Table',
40 | component: () => import('@/views/demo/table/index.vue'),
41 | meta: {
42 | title: '表格',
43 | icon: 'icon-packing-labeling'
44 | }
45 | },
46 | {
47 | path: '/demo/icon',
48 | name: 'Icon',
49 | component: () => import('@/views/demo/icon/index.vue'),
50 | meta: {
51 | title: '图标',
52 | icon: 'icon-trade-assurance'
53 | }
54 | }
55 | ]
56 | },
57 |
58 | {
59 | path: '/login',
60 | name: 'login',
61 | component: () => import('@/views/login/Login.vue'),
62 | hidden: true
63 | },
64 | {
65 | path: '/:pathMatch(.*)*',
66 | name: '404',
67 | component: () => import('@/views/error/404.vue'),
68 | hidden: true
69 | }
70 | ]
71 |
72 | export const asyncRoutes = [
73 | {
74 | path: '/error',
75 | name: 'Error',
76 | component: Layout,
77 | redirect: '/error/403',
78 | meta: {
79 | title: '错误页',
80 | icon: 'icon-logistic-logo'
81 | },
82 | children: [
83 | {
84 | path: '/error/403',
85 | name: 'Error403',
86 | component: () => import('@/views/error/403.vue'),
87 | meta: {
88 | title: '403',
89 | icon: 'icon-fencengpeizhi'
90 | }
91 | },
92 | {
93 | path: '/error/404',
94 | name: 'Error404',
95 | component: () => import('@/views/error/404.vue'),
96 | meta: {
97 | title: '404',
98 | icon: 'icon-tongguanshuju'
99 | }
100 | }
101 | ]
102 | },
103 | {
104 | path: '/echart',
105 | component: Layout,
106 | name: 'echart',
107 | redirect: '/echart/bar',
108 | meta: {
109 | title: '动态路由测试',
110 | icon: 'icon-searchcart'
111 | },
112 | children: [
113 | {
114 | path: '/echart/bar',
115 | name: 'Bar',
116 | component: () => import('@/views/echart/bar/index.vue'),
117 | meta: {
118 | title: '路由测试1',
119 | icon: 'icon-raw'
120 | }
121 | },
122 | {
123 | path: '/echart/line',
124 | name: 'Line',
125 | component: () => import('@/views/echart/line/index.vue'),
126 | meta: {
127 | title: '路由测试2',
128 | icon: 'icon-share'
129 | }
130 | },
131 | {
132 | path: '/echart/pie',
133 | name: 'Pie',
134 | component: () => import('@/views/echart/pie/index.vue'),
135 | meta: {
136 | title: '路由测试3',
137 | icon: 'icon-zhanghucaozuo'
138 | }
139 | }
140 | ]
141 | },
142 | {
143 | path: '/product',
144 | component: Layout,
145 | name: 'product-manage',
146 | redirect: '/product/list',
147 | meta: {
148 | title: '产品管理',
149 | icon: 'icon-searchcart'
150 | },
151 | children: [
152 | {
153 | path: '/product/list',
154 | name: 'product-list',
155 | component: () => import('@/views/product/list/index.vue'),
156 | meta: {
157 | title: '产品列表',
158 | icon: 'icon-raw'
159 | }
160 | },
161 | {
162 | path: '/product/category',
163 | name: 'review-manage',
164 | component: () => import('@/views/product/category/index.vue'),
165 | meta: {
166 | title: '产品分类',
167 | icon: 'icon-share'
168 | }
169 | }
170 | ]
171 | },
172 | {
173 | path: '/order',
174 | component: Layout,
175 | name: 'order-manage',
176 | redirect: '/order/list',
177 | meta: {
178 | title: '订单管理',
179 | icon: 'icon-cart-Empty'
180 | },
181 | children: [
182 | {
183 | path: '/order/list',
184 | name: 'order-list',
185 | component: () => import('@/views/order/list/index.vue'),
186 | meta: {
187 | title: '订单列表',
188 | icon: 'icon-Exportservices'
189 | }
190 | },
191 | {
192 | path: '/order/returnGoods',
193 | name: 'return-goods',
194 | component: () => import('@/views/order/return_goods/index.vue'),
195 | meta: {
196 | title: '退货管理',
197 | icon: 'icon-column'
198 | }
199 | },
200 | {
201 | path: '/order/product',
202 | component: EmptyLayout,
203 | name: 'goods',
204 | redirect: '/order/good/list',
205 | meta: {
206 | title: '货物管理',
207 | icon: 'icon-searchcart'
208 | },
209 | children: [
210 | {
211 | path: '/order/good/list',
212 | name: 'goods-list',
213 | component: () => import('@/views/order/good/list/index.vue'),
214 | meta: {
215 | title: '货物列表',
216 | icon: 'icon-apparel'
217 | }
218 | },
219 | {
220 | path: '/order/good/check',
221 | name: 'goods-classify',
222 | component: () => import('@/views/order/good/check/index.vue'),
223 | meta: {
224 | title: '退货管理',
225 | icon: 'icon-add-account'
226 | }
227 | },
228 | ]
229 | },
230 | ]
231 | },
232 | {
233 | path: '/permission',
234 | component: Layout,
235 | name: 'permission',
236 | redirect: '/permission/user',
237 | meta: {
238 | title: '产品管理',
239 | icon: 'icon-cecurity-protection'
240 | },
241 | children: [
242 | {
243 | path: '/permission/user',
244 | name: 'user-manage',
245 | component: () => import('@/views/permission/user_manage/index.vue'),
246 | meta: {
247 | title: '用户管理',
248 | icon: 'icon-confirm'
249 | }
250 | },
251 | {
252 | path: '/permission/role',
253 | name: 'role-manage',
254 | component: () => import('@/views/permission/role_manage/index.vue'),
255 | meta: {
256 | title: '角色管理',
257 | icon: 'icon-Customermanagement'
258 | }
259 | },
260 | {
261 | path: '/permission/menu',
262 | name: 'menu-manage',
263 | component: () => import('@/views/permission/menu_manage/index.vue'),
264 | meta: {
265 | title: '菜单管理',
266 | icon: 'icon-earth'
267 | }
268 | }
269 | ]
270 | },
271 | ]
272 |
273 | const router = createRouter({
274 | history: createWebHashHistory(),
275 | routes: constantRoutes
276 | })
277 |
278 | export default router
279 |
--------------------------------------------------------------------------------
/src/shims-vue.d.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | declare module '*.vue' {
3 | import type { DefineComponent } from 'vue'
4 | const component: DefineComponent<{}, {}, any>
5 | export default component
6 | }
7 |
--------------------------------------------------------------------------------
/src/store/actions.ts:
--------------------------------------------------------------------------------
1 | import { CHANGEROUTE } from './mutation-types'
2 | import { asyncRoutes, constantRoutes } from '@/router'
3 | import { recursionRouter ,setSingleItem} from '@/utils/recursion-router'
4 | import { getRoleList } from '@/api'
5 | export default {
6 | // 改变路由
7 | async changeAsyncRoute ({ commit }: any) {
8 | const res = await getRoleList()
9 | if (res.code === 1) {
10 | const userRouter: any[] = res.data.data
11 | const data = recursionRouter(userRouter, asyncRoutes)
12 | const menu = [...constantRoutes, ...data]
13 |
14 | const allRouterList = menu.filter(
15 | (item: { hidden: any }) => !item.hidden
16 | )
17 | //设置一下当前的menuList
18 | const currentMenu = setSingleItem(allRouterList, [])
19 | commit(CHANGEROUTE, currentMenu)
20 | return data
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/store/getters.ts:
--------------------------------------------------------------------------------
1 | const getters = {}
2 |
3 | export default getters
4 |
--------------------------------------------------------------------------------
/src/store/index.ts:
--------------------------------------------------------------------------------
1 | import { createStore } from 'vuex'
2 | import getters from '@/store/getters'
3 | import mutations from '@/store/mutations'
4 | import actions from '@/store/actions'
5 | // import user from './modules/user'
6 | // import asyncRouter from './modules/asyncRouter'
7 |
8 | export default createStore({
9 | state: {
10 | taskList: [],
11 | selectedKeys: [],
12 | routingPathData: [],
13 | menuList:[
14 | ]
15 | },
16 | getters,
17 | mutations,
18 | actions,
19 | // modules: {
20 | // user,
21 | // asyncRouter
22 | // }
23 | })
24 |
--------------------------------------------------------------------------------
/src/store/modules/asyncRouter.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | state: {
3 | routes: [],
4 | addRoutes: []
5 | },
6 | mutations: {
7 | SET_ROUTES: (state:any, routes:any) => {
8 | state.addRoutes = routes
9 | // state.routes = constantRoutes.concat(routes)
10 | state.routes = routes
11 | }
12 | },
13 | getters: {},
14 | actions: {
15 | generateRoutes({ commit }:any, roles:any) {
16 | return new Promise(resolve => {
17 | const accessedRoutes:any = roles
18 |
19 | commit('SET_ROUTES', accessedRoutes)
20 |
21 | resolve([])
22 | })
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/store/modules/user.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | state: {
3 | menus: []
4 | },
5 | mutations: {
6 | SET_MENUS: (state: any, menus: any) => {
7 | state.menus = menus
8 | }
9 | },
10 | getters: {},
11 | actions: {
12 | GetInfo ({ commit }: any) {
13 | return new Promise(resolve => {
14 | setTimeout(() => {
15 | commit('SET_MENUS', [123])
16 | resolve([123])
17 | }, 3000)
18 | })
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/store/mutation-types.ts:
--------------------------------------------------------------------------------
1 | export const ADDROUTINGPATHDATA = 'ADDROUTINGPATHDATA'
2 | export const CHANGEACTIVEKEYS = 'changeactivekeys'
3 | export const CHANGEROUTE = 'changeroute'
4 |
--------------------------------------------------------------------------------
/src/store/mutations.ts:
--------------------------------------------------------------------------------
1 | import {
2 | ADDROUTINGPATHDATA,
3 | CHANGEACTIVEKEYS,
4 | CHANGEROUTE
5 | } from './mutation-types'
6 | export default {
7 | // 路由路径
8 | [ADDROUTINGPATHDATA] (state: any, list: any) {
9 | state.routingPathData = list
10 | },
11 | [CHANGEACTIVEKEYS] (state: any, paramsData: any) {
12 | state.selectedKeys = paramsData
13 | },
14 | [CHANGEROUTE] (state: any, menuList: any) {
15 | state.menuList = menuList
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/styles/index.less:
--------------------------------------------------------------------------------
1 | @import './loading.less';
2 | @import './normalize.less';
--------------------------------------------------------------------------------
/src/styles/loading.less:
--------------------------------------------------------------------------------
1 | .ajax-loading {
2 | display: none;
3 | .loading {
4 | position: fixed;
5 | top: 50%;
6 | left: 50%;
7 | transform: translate(-50%, -50%);
8 | padding: 0 40px;
9 | height: 80px;
10 | line-height: 80px;
11 | background: rgba(0, 0, 0, 0.75);
12 | border-radius: 6px;
13 | text-align: center;
14 | z-index: 9999;
15 | font-size: 16px;
16 | color: #fff;
17 | img {
18 | width: 32px;
19 | vertical-align: middle;
20 | }
21 | span {
22 | margin-left: 12px;
23 | }
24 | }
25 | .overlay {
26 | position: fixed;
27 | left: 0;
28 | right: 0;
29 | top: 0;
30 | bottom: 0;
31 | z-index: 9998;
32 | background: rgb(255, 255, 255);
33 | opacity: 0.1;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/styles/normalize.less:
--------------------------------------------------------------------------------
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 | }
--------------------------------------------------------------------------------
/src/utils/axios.ts:
--------------------------------------------------------------------------------
1 | import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'
2 | import { getLocal } from '@/utils'
3 | import { message } from 'ant-design-vue'
4 |
5 | const baseURL = process.env.NODE_ENV === 'production' ? '/' : '/api'
6 | //创建axios实例
7 | const service = axios.create({
8 | baseURL: baseURL, // api的base_url
9 | timeout: 200000, // 请求超时时间
10 | withCredentials: true, // 选项表明了是否是跨域请求
11 | validateStatus (status: number) {
12 | switch (status) {
13 | case 400:
14 | message.error('请求出错')
15 | break
16 | case 401:
17 | message.warning('授权失败,请重新登录')
18 | localStorage.removeItem('token')
19 |
20 | // store.commit('LOGIN_OUT')
21 | setTimeout(() => {
22 | window.location.reload()
23 | }, 1000)
24 | break
25 | case 403:
26 | message.warning({
27 | message: '拒绝访问'
28 | })
29 | break
30 | case 404:
31 | message.warning({
32 | message: '请求错误,未找到该资源'
33 | })
34 | break
35 | case 500:
36 | message.warning({
37 | message: '服务端错误'
38 | })
39 | break
40 | }
41 | return status >= 200 && status < 300
42 | }
43 | })
44 |
45 | //请求拦截
46 | service.interceptors.request.use(
47 | (config: AxiosRequestConfig) => {
48 | // 请求头添加token
49 | const token = getLocal('token')
50 | if (token) {
51 | config.headers.Authorization = `Bearer ${token}`
52 | }
53 | const flag =
54 | (config.data && config.data.loading !== false) ||
55 | (config.params && config.params.loading !== false)
56 | if (flag) {
57 | let loading: any = undefined
58 | loading = document.getElementById('ajaxLoading')
59 | loading.style.display = 'block'
60 | }
61 | return config
62 | },
63 | (err: any) => {
64 | console.log('请求失败')
65 | return Promise.reject(err)
66 | }
67 | )
68 |
69 | //响应拦截
70 | service.interceptors.response.use(
71 | (response: AxiosResponse) => {
72 | const res = response.data
73 | const ele: any = document.getElementById('ajaxLoading')
74 | ele.style.display = 'none'
75 | switch (res.code) {
76 | case 1:
77 | return res
78 | case 401:
79 | // message.warning({
80 | // message: '授权失败,请重新登录'
81 | // })
82 | message.error(res.message)
83 | return Promise.reject('error')
84 | default:
85 | message.error(res.message)
86 | return Promise.reject('error')
87 | }
88 | },
89 | (error: { message: any }) => {
90 | const ele: any = document.getElementById('ajaxLoading')
91 | ele.style.display = 'none'
92 | console.log(error.message)
93 | return Promise.reject(error)
94 | }
95 | )
96 | export default service
97 |
--------------------------------------------------------------------------------
/src/utils/index.ts:
--------------------------------------------------------------------------------
1 | //获取localstorage
2 | export const getLocal = (item: string) => {
3 | return localStorage.getItem(item)
4 | }
5 |
6 | //设置localstorage
7 | export const setLocal = (key: string, value: any) => {
8 | localStorage.setItem(key, value)
9 | }
10 |
11 | //移除
12 | export const removeLocal = (key: string) => {
13 | localStorage.removeItem(key)
14 | }
--------------------------------------------------------------------------------
/src/utils/recursion-router.ts:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * @param {Array} userRouter 后台返回的用户权限json
4 | * @param {Array} allRouter 前端配置好的所有动态路由的集合
5 | * @return {Array} realRoutes 过滤后的路由
6 | */
7 |
8 | export function recursionRouter (
9 | userRouter: any[] = [],
10 | allRouter: any[] = []
11 | ): Array {
12 | const realRoutes = allRouter
13 | .filter(item => userRouter.includes(item.name))
14 | .map(item => ({
15 | ...item,
16 | children: item.children
17 | ? recursionRouter(userRouter, item.children)
18 | : null
19 | }))
20 | return realRoutes
21 | }
22 |
23 | //设置单层侧边栏
24 | export function setSingleItem (list: any[], newList: any[]) {
25 | newList = list.map(item => {
26 | if (item.children && item.children.length > 0) {
27 | if (item.meta && item.meta.single) {
28 | item = { ...item }
29 | item.children = null
30 | } else {
31 | item.children = setSingleItem(item.children, newList)
32 | }
33 |
34 | return item
35 | }
36 | return item
37 | })
38 | return newList
39 | }
40 |
--------------------------------------------------------------------------------
/src/views/demo/icon/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
18 |
--------------------------------------------------------------------------------
/src/views/demo/table/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
14 |
15 |
setSelectedKeys(e.target.value ? [e.target.value] : [])
22 | "
23 | @pressEnter="handleSearch(selectedKeys, confirm, column.dataIndex)"
24 | />
25 |
31 |
32 | Search
33 |
34 |
39 | Reset
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
54 |
59 | {{ fragment }}
60 |
61 | {{ fragment }}
62 |
63 |
64 |
65 | {{ text }}
66 |
67 |
68 |
69 |
70 |
71 |
228 |
--------------------------------------------------------------------------------
/src/views/echart/bar/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/views/echart/line/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
70 |
--------------------------------------------------------------------------------
/src/views/echart/pie/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
131 |
--------------------------------------------------------------------------------
/src/views/empty_layout/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/views/error/403.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
403
5 | 当前帐号没有操作角色,请联系管理员
6 | 回到首页
7 |
8 |

9 |
10 |
11 |
12 |
19 |
20 |
--------------------------------------------------------------------------------
/src/views/error/404.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
404
5 | 当前页面不存在...
6 | 回到首页
7 |
8 |

9 |
10 |
11 |
12 |
19 |
20 |
30 |
--------------------------------------------------------------------------------
/src/views/index/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
24 |
38 |
--------------------------------------------------------------------------------
/src/views/layout/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
19 |
20 |
21 |
25 |
26 |
27 |
28 |
29 |
30 |
33 |
34 |
35 |
36 |
64 |
98 |
--------------------------------------------------------------------------------
/src/views/layout/menu/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
23 |
24 |
25 |
67 |
68 |
--------------------------------------------------------------------------------
/src/views/layout/menu/sub-menu.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{ menuInfo.meta.title }}
7 |
8 |
9 |
10 |
11 |
12 |
13 | {{ item.meta.title }}
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
43 |
44 |
--------------------------------------------------------------------------------
/src/views/login/Login.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
38 |
39 |
40 |
41 |
42 |
43 |
88 |
--------------------------------------------------------------------------------
/src/views/order/good/check/index.vue:
--------------------------------------------------------------------------------
1 |
2 | 审核管理
3 |
--------------------------------------------------------------------------------
/src/views/order/good/list/index.vue:
--------------------------------------------------------------------------------
1 |
2 | 货物列表
3 |
--------------------------------------------------------------------------------
/src/views/order/list/index.vue:
--------------------------------------------------------------------------------
1 |
2 | 订单列表
3 |
--------------------------------------------------------------------------------
/src/views/order/return_goods/index.vue:
--------------------------------------------------------------------------------
1 |
2 | 退货管理
3 |
--------------------------------------------------------------------------------
/src/views/permission/menu_manage/index.vue:
--------------------------------------------------------------------------------
1 |
2 | menu-manage
3 |
--------------------------------------------------------------------------------
/src/views/permission/role_manage/index.vue:
--------------------------------------------------------------------------------
1 |
2 | role-manage
3 |
--------------------------------------------------------------------------------
/src/views/permission/user_manage/index.vue:
--------------------------------------------------------------------------------
1 |
2 | user-manage
3 |
--------------------------------------------------------------------------------
/src/views/product/category/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 | Go Console
10 | Buy Again
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/views/product/list/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
13 |
19 |
25 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "esnext",
5 | "strict": true,
6 | "jsx": "preserve",
7 | "importHelpers": true,
8 | "moduleResolution": "node",
9 | "skipLibCheck": true,
10 | "esModuleInterop": true,
11 | "allowSyntheticDefaultImports": true,
12 | "sourceMap": true,
13 | "baseUrl": ".",
14 | "types": [
15 | "webpack-env"
16 | ],
17 | "paths": {
18 | "@/*": [
19 | "src/*"
20 | ]
21 | },
22 | "lib": [
23 | "esnext",
24 | "dom",
25 | "dom.iterable",
26 | "scripthost"
27 | ]
28 | },
29 | "include": [
30 | "src/**/*.ts",
31 | "src/**/*.tsx",
32 | "src/**/*.vue",
33 | "tests/**/*.ts",
34 | "tests/**/*.tsx"
35 | ],
36 | "exclude": [
37 | "node_modules"
38 | ]
39 | }
40 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 |
2 | const proxyTargetMap = {
3 | prod: 'http://47.105.71.81:3306',
4 | randy: 'http://47.105.71.81:3306',
5 | peter: 'http://192.168.11.178:3001'
6 | }
7 | let proxyTarget = proxyTargetMap[process.env.API_TYPE] || proxyTargetMap.prod
8 | module.exports = {
9 | publicPath:'./',
10 | devServer: {
11 | open: true,
12 | // 查阅 https://github.com/vuejs/vue-docs-zh-cn/blob/master/vue-cli/cli-service.md#配置代理
13 | proxy: {
14 | '/api': {
15 | target: proxyTarget,
16 | changeOrigin: true,
17 | pathRewrite: {
18 | '^/api': ''
19 | }
20 | }
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------