├── .github
└── FUNDING.yml
├── .gitignore
├── LICENSE
├── README.md
├── README_EN.md
├── auto-imports.d.ts
├── components.d.ts
├── index.html
├── package.json
├── public
├── mock
│ ├── role.json
│ ├── table.json
│ └── user.json
└── template.xlsx
├── screenshots
├── wms1.png
└── wms3.png
├── src
├── App.vue
├── api
│ └── index.ts
├── assets
│ ├── css
│ │ ├── icon.css
│ │ └── main.css
│ └── img
│ │ ├── img.jpg
│ │ ├── login-bg.jpg
│ │ ├── logo.svg
│ │ └── ucenter-bg.jpg
├── components
│ ├── countup.vue
│ ├── header.vue
│ ├── menu.ts
│ ├── sidebar.vue
│ ├── table-custom.vue
│ ├── table-detail.vue
│ ├── table-edit.vue
│ ├── table-search.vue
│ └── tabs.vue
├── main.ts
├── router
│ └── index.ts
├── store
│ ├── permiss.ts
│ ├── sidebar.ts
│ ├── tabs.ts
│ └── theme.ts
├── types
│ ├── form-option.ts
│ ├── menu.ts
│ ├── role.ts
│ ├── table.ts
│ └── user.ts
├── utils
│ ├── china.ts
│ ├── index.ts
│ └── request.ts
├── views
│ ├── chart
│ │ ├── echarts.vue
│ │ ├── options.ts
│ │ └── schart.vue
│ ├── dashboard.vue
│ ├── element
│ │ ├── calendar.vue
│ │ ├── carousel.vue
│ │ ├── form.vue
│ │ ├── statistic.vue
│ │ ├── steps.vue
│ │ ├── tabs.vue
│ │ ├── tour.vue
│ │ ├── upload.vue
│ │ └── watermark.vue
│ ├── home.vue
│ ├── pages
│ │ ├── 403.vue
│ │ ├── 404.vue
│ │ ├── editor.vue
│ │ ├── icon.vue
│ │ ├── login.vue
│ │ ├── markdown.vue
│ │ ├── register.vue
│ │ ├── reset-pwd.vue
│ │ ├── theme.vue
│ │ └── ucenter.vue
│ ├── system
│ │ ├── menu.vue
│ │ ├── role-permission.vue
│ │ ├── role.vue
│ │ └── user.vue
│ └── table
│ │ ├── basetable.vue
│ │ ├── export.vue
│ │ ├── import.vue
│ │ └── table-editor.vue
└── vite-env.d.ts
├── tsconfig.json
├── tsconfig.node.json
├── vite.config.ts
└── yarn.lock
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: https://lin-xin.github.io/images/weixin.jpg
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 |
6 | # local env files
7 | .env.local
8 | .env.*.local
9 |
10 | # Log files
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 | pnpm-debug.log*
15 |
16 | # Editor directories and files
17 | .idea
18 | .vscode
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016-2023 vue-manage-system
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.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vue-manage-system
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | 基于 Vue3 + pinia + Element Plus 的后台管理系统解决方案。[线上演示](https://lin-xin.github.io/example/vue-manage-system/)
11 |
12 | > Vue2 版本请看 [tag-V4.2.0](https://github.com/lin-xin/vue-manage-system/tree/V4.2.0),带后台功能请看 [tsrpc-manage-system](https://github.com/lin-xin/tsrpc-manage-system)
13 |
14 | [文档地址](https://lin-xin.github.io/example/vuems-doc/)
15 | [English document](https://github.com/lin-xin/manage-system/blob/master/README_EN.md)
16 |
17 | ## 赞助商
18 |
19 | ### 好问
20 |
21 | [
](https://www.bestqa.net/home/index.html)
22 |
23 | 专业问卷服务,一对一客服,按需定制
24 |
25 | ## 支持作者
26 |
27 | 请作者喝杯咖啡吧!(微信号:linxin_20)
28 |
29 | 
30 |
31 | ## 前言
32 |
33 | 该方案作为一套多功能的后台框架模板,适用于绝大部分的后台管理系统开发。基于 Vue3 + pinia + typescript,引用 Element Plus 组件库,方便开发。实现逻辑简单,适合外包项目,快速交付。
34 |
35 | ## 功能
36 |
37 | - [x] Element Plus
38 | - [x] vite 3
39 | - [x] pinia
40 | - [x] typescript
41 | - [x] 登录/注册
42 | - [x] Dashboard
43 | - [x] 表格/表单
44 | - [x] 图表 :bar_chart:
45 | - [x] 富文本/markdown 编辑器
46 | - [x] 图片拖拽/裁剪上传
47 | - [x] 权限管理
48 | - [x] 三级菜单
49 | - [x] 自定义图标
50 | - [x] 主题切换
51 |
52 | ## 安装步骤
53 |
54 | > 因为使用 vite3,node 版本需要 14.18+
55 |
56 | ```
57 | git clone https://github.com/lin-xin/vue-manage-system.git // 把模板下载到本地
58 | cd vue-manage-system // 进入模板目录
59 | npm install // 安装项目依赖,等待安装完成之后,安装失败可用 cnpm 或 yarn
60 |
61 | // 运行
62 | npm run dev
63 |
64 | // 执行构建命令,生成的dist文件夹放在服务器下即可访问
65 | npm run build
66 | ```
67 |
68 | ## 项目截图
69 |
70 | ### 首页
71 |
72 | 
73 |
74 | ### 登录
75 |
76 | 
77 |
78 | ## License
79 |
80 | [MIT](https://github.com/lin-xin/vue-manage-system/blob/master/LICENSE)
81 |
--------------------------------------------------------------------------------
/README_EN.md:
--------------------------------------------------------------------------------
1 | # vue-manage-system
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | The web management system solution based on Vue3 and ElementPlus。[live demo](https://lin-xin.gitee.io/example/work/)
20 |
21 | Please check the version of vue2 in [tag V4.2.0](https://github.com/lin-xin/vue-manage-system/tree/V4.2.0)
22 |
23 | ## Donation
24 |
25 | 
26 |
27 | ## Preface
28 |
29 | The scheme as a set of multi-function background frame templates, suitable for most of the WEB management system development. Convenient development fast simple good components based on Vue3 and ElementPlus. Color separation of color style, support manual switch themes, and it is convenient to use a custom theme color.
30 |
31 | ## Function
32 |
33 | - [x] Element-UI
34 | - [x] Login/Logout
35 | - [x] Dashboard
36 | - [x] Table
37 | - [x] Tabs
38 | - [x] From
39 | - [x] Chart :bar_chart:
40 | - [x] Editor
41 | - [x] Markdown
42 | - [x] Upload pictures by clipping or dragging
43 | - [x] Permission
44 | - [x] Three level menu
45 | - [x] Custom icon
46 |
47 | ## Installation steps
48 |
49 | git clone https://github.com/lin-xin/vue-manage-system.git // Clone templates
50 | cd vue-manage-system // Enter template directory
51 | npm install // Installation dependency
52 |
53 | ## Local development
54 |
55 | npm run dev
56 |
57 | ## Constructing production
58 |
59 | // Constructing project
60 | npm run build
61 |
62 | ## Component description and presentation
63 |
64 | ### vue-schart
65 |
66 | Vue.js wrapper for sChart.js. Github : [vue-schart](https://github.com/lin-xin/vue-schart#/)
67 |
68 | ```html
69 |
70 |
71 |
72 |
73 |
74 |
99 |
105 | ```
106 |
107 | ## Screenshot
108 |
109 | ### Default theme
110 |
111 | 
112 |
113 | ### Login
114 |
115 | 
116 |
117 | ## License
118 |
119 | [MIT](https://github.com/lin-xin/vue-manage-system/blob/master/LICENSE)
120 |
--------------------------------------------------------------------------------
/auto-imports.d.ts:
--------------------------------------------------------------------------------
1 | // Generated by 'unplugin-auto-import'
2 | export {}
3 | declare global {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/components.d.ts:
--------------------------------------------------------------------------------
1 | // generated by unplugin-vue-components
2 | // We suggest you to commit this file into source control
3 | // Read more: https://github.com/vuejs/core/pull/3399
4 | import '@vue/runtime-core'
5 |
6 | export {}
7 |
8 | declare module '@vue/runtime-core' {
9 | export interface GlobalComponents {
10 | Countup: typeof import('./src/components/countup.vue')['default']
11 | ElAvatar: typeof import('element-plus/es')['ElAvatar']
12 | ElButton: typeof import('element-plus/es')['ElButton']
13 | ElCalendar: typeof import('element-plus/es')['ElCalendar']
14 | ElCard: typeof import('element-plus/es')['ElCard']
15 | ElCarousel: typeof import('element-plus/es')['ElCarousel']
16 | ElCarouselItem: typeof import('element-plus/es')['ElCarouselItem']
17 | ElCascader: typeof import('element-plus/es')['ElCascader']
18 | ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
19 | ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
20 | ElCol: typeof import('element-plus/es')['ElCol']
21 | ElColorPicker: typeof import('element-plus/es')['ElColorPicker']
22 | ElCountdown: typeof import('element-plus/es')['ElCountdown']
23 | ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
24 | ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
25 | ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
26 | ElDialog: typeof import('element-plus/es')['ElDialog']
27 | ElDivider: typeof import('element-plus/es')['ElDivider']
28 | ElDropdown: typeof import('element-plus/es')['ElDropdown']
29 | ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
30 | ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
31 | ElForm: typeof import('element-plus/es')['ElForm']
32 | ElFormItem: typeof import('element-plus/es')['ElFormItem']
33 | ElIcon: typeof import('element-plus/es')['ElIcon']
34 | ElImage: typeof import('element-plus/es')['ElImage']
35 | ElInput: typeof import('element-plus/es')['ElInput']
36 | ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
37 | ElLink: typeof import('element-plus/es')['ElLink']
38 | ElMenu: typeof import('element-plus/es')['ElMenu']
39 | ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
40 | ElOption: typeof import('element-plus/es')['ElOption']
41 | ElPagination: typeof import('element-plus/es')['ElPagination']
42 | ElProgress: typeof import('element-plus/es')['ElProgress']
43 | ElRadio: typeof import('element-plus/es')['ElRadio']
44 | ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
45 | ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
46 | ElRate: typeof import('element-plus/es')['ElRate']
47 | ElResult: typeof import('element-plus/es')['ElResult']
48 | ElRow: typeof import('element-plus/es')['ElRow']
49 | ElSelect: typeof import('element-plus/es')['ElSelect']
50 | ElSlider: typeof import('element-plus/es')['ElSlider']
51 | ElSpace: typeof import('element-plus/es')['ElSpace']
52 | ElStatistic: typeof import('element-plus/es')['ElStatistic']
53 | ElStep: typeof import('element-plus/es')['ElStep']
54 | ElSteps: typeof import('element-plus/es')['ElSteps']
55 | ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
56 | ElSwitch: typeof import('element-plus/es')['ElSwitch']
57 | ElTable: typeof import('element-plus/es')['ElTable']
58 | ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
59 | ElTabPane: typeof import('element-plus/es')['ElTabPane']
60 | ElTabs: typeof import('element-plus/es')['ElTabs']
61 | ElTag: typeof import('element-plus/es')['ElTag']
62 | ElTimeline: typeof import('element-plus/es')['ElTimeline']
63 | ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
64 | ElTimePicker: typeof import('element-plus/es')['ElTimePicker']
65 | ElTooltip: typeof import('element-plus/es')['ElTooltip']
66 | ElTour: typeof import('element-plus/es')['ElTour']
67 | ElTourStep: typeof import('element-plus/es')['ElTourStep']
68 | ElTransfer: typeof import('element-plus/es')['ElTransfer']
69 | ElUpload: typeof import('element-plus/es')['ElUpload']
70 | ElWatermark: typeof import('element-plus/es')['ElWatermark']
71 | Header: typeof import('./src/components/header.vue')['default']
72 | RouterLink: typeof import('vue-router')['RouterLink']
73 | RouterView: typeof import('vue-router')['RouterView']
74 | Sidebar: typeof import('./src/components/sidebar.vue')['default']
75 | TableCustom: typeof import('./src/components/table-custom.vue')['default']
76 | TableDetail: typeof import('./src/components/table-detail.vue')['default']
77 | TableEdit: typeof import('./src/components/table-edit.vue')['default']
78 | TableSearch: typeof import('./src/components/table-search.vue')['default']
79 | Tabs: typeof import('./src/components/tabs.vue')['default']
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | vue-manage-system后台管理系统
9 |
10 |
11 |
12 |
13 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-manage-system",
3 | "version": "5.5.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "vite",
7 | "build": "vue-tsc --noEmit && vite build",
8 | "serve": "vite preview"
9 | },
10 | "dependencies": {
11 | "@element-plus/icons-vue": "*",
12 | "@wangeditor/editor": "^5.1.23",
13 | "@wangeditor/editor-for-vue": "^5.1.12",
14 | "axios": "^1.6.3",
15 | "countup.js": "^2.8.0",
16 | "echarts": "^5.5.0",
17 | "echarts-wordcloud": "^2.1.0",
18 | "element-plus": "^2.6.3",
19 | "md-editor-v3": "^2.11.2",
20 | "nprogress": "^0.2.0",
21 | "pinia": "^2.1.7",
22 | "vue": "^3.4.5",
23 | "vue-cropper": "1.1.1",
24 | "vue-echarts": "^6.6.9",
25 | "vue-router": "^4.2.5",
26 | "vue-schart": "^2.0.0",
27 | "xlsx": "^0.18.5"
28 | },
29 | "devDependencies": {
30 | "@vitejs/plugin-vue": "^3.0.0",
31 | "@vue/compiler-sfc": "^3.1.2",
32 | "typescript": "^4.6.4",
33 | "unplugin-auto-import": "^0.11.2",
34 | "unplugin-vue-components": "^0.22.4",
35 | "vite": "^3.0.0",
36 | "vite-plugin-vue-setup-extend": "^0.4.0",
37 | "vue-tsc": "^0.38.4"
38 | },
39 | "browserslist": [
40 | "> 1%",
41 | "last 2 versions",
42 | "not dead"
43 | ]
44 | }
45 |
--------------------------------------------------------------------------------
/public/mock/role.json:
--------------------------------------------------------------------------------
1 | {
2 | "list": [
3 | {
4 | "id": 1,
5 | "name": "管理员",
6 | "key": "admin",
7 | "status": true,
8 | "permiss": [
9 | "0",
10 | "1",
11 | "11",
12 | "12",
13 | "13",
14 | "2",
15 | "21",
16 | "22",
17 | "23",
18 | "24",
19 | "3",
20 | "31",
21 | "32",
22 | "33",
23 | "331",
24 | "332",
25 | "4",
26 | "41",
27 | "42",
28 | "5"
29 | ]
30 | },
31 | {
32 | "id": 2,
33 | "name": "普通用户",
34 | "key": "user",
35 | "status": true,
36 | "permiss": [
37 | "0",
38 | "1",
39 | "11",
40 | "12",
41 | "13"
42 | ]
43 | }
44 | ],
45 | "pageTotal": 2
46 | }
--------------------------------------------------------------------------------
/public/mock/table.json:
--------------------------------------------------------------------------------
1 | {
2 | "list": [
3 | {
4 | "id": 1,
5 | "name": "张三",
6 | "money": 123,
7 | "address": "广东省东莞市长安镇",
8 | "state": true,
9 | "date": "2019-11-1",
10 | "thumb": "https://lin-xin.gitee.io/images/post/wms.png"
11 | },
12 | {
13 | "id": 2,
14 | "name": "李四",
15 | "money": 456,
16 | "address": "广东省广州市白云区",
17 | "state": true,
18 | "date": "2019-10-11",
19 | "thumb": "https://lin-xin.gitee.io/images/post/node3.png"
20 | },
21 | {
22 | "id": 3,
23 | "name": "王五",
24 | "money": 789,
25 | "address": "湖南省长沙市",
26 | "state": false,
27 | "date": "2019-11-11",
28 | "thumb": "https://lin-xin.gitee.io/images/post/parcel.png"
29 | },
30 | {
31 | "id": 4,
32 | "name": "赵六",
33 | "money": 1011,
34 | "address": "福建省厦门市鼓浪屿",
35 | "state": true,
36 | "date": "2019-10-20",
37 | "thumb": "https://lin-xin.gitee.io/images/post/notice.png"
38 | }
39 | ],
40 | "pageTotal": 4
41 | }
--------------------------------------------------------------------------------
/public/mock/user.json:
--------------------------------------------------------------------------------
1 | {
2 | "list": [
3 | {
4 | "id": 1,
5 | "name": "张三",
6 | "password": "123",
7 | "email": "123@qq.com",
8 | "phone": "12345678944",
9 | "date": "2024-01-01",
10 | "role": "管理员"
11 | },
12 | {
13 | "id": 2,
14 | "name": "李四",
15 | "password": "123",
16 | "email": "1234@qq.com",
17 | "phone": "12345678945",
18 | "date": "2024-01-01",
19 | "role": "普通用户"
20 | }
21 | ],
22 | "pageTotal": 2
23 | }
--------------------------------------------------------------------------------
/public/template.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lin-xin/vue-manage-system/6a7019ec1a74cc05297d18647a5f944c242d468a/public/template.xlsx
--------------------------------------------------------------------------------
/screenshots/wms1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lin-xin/vue-manage-system/6a7019ec1a74cc05297d18647a5f944c242d468a/screenshots/wms1.png
--------------------------------------------------------------------------------
/screenshots/wms3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lin-xin/vue-manage-system/6a7019ec1a74cc05297d18647a5f944c242d468a/screenshots/wms3.png
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
15 |
18 |
--------------------------------------------------------------------------------
/src/api/index.ts:
--------------------------------------------------------------------------------
1 | import request from '../utils/request';
2 |
3 | export const fetchData = () => {
4 | return request({
5 | url: './mock/table.json',
6 | method: 'get'
7 | });
8 | };
9 |
10 | export const fetchUserData = () => {
11 | return request({
12 | url: './mock/user.json',
13 | method: 'get'
14 | });
15 | };
16 |
17 | export const fetchRoleData = () => {
18 | return request({
19 | url: './mock/role.json',
20 | method: 'get'
21 | });
22 | };
23 |
--------------------------------------------------------------------------------
/src/assets/css/icon.css:
--------------------------------------------------------------------------------
1 | [class*=" el-icon-lx"],
2 | [class^=el-icon-lx] {
3 | font-family: lx-iconfont !important;
4 | }
--------------------------------------------------------------------------------
/src/assets/css/main.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | outline: 0 !important;
5 | }
6 |
7 |
8 | body {
9 | font-family: 'PingFang SC', 'Helvetica Neue', Helvetica, 'microsoft yahei', arial, STHeiTi, sans-serif;
10 | }
11 |
12 | a {
13 | text-decoration: none;
14 | }
15 | i {
16 | font-style: normal;
17 | }
18 |
19 | .container {
20 | padding: 30px;
21 | background: #fff;
22 | border: 1px solid #ddd;
23 | border-radius: 5px;
24 | }
25 |
26 | .el-table th {
27 | background-color: #f5f7fa !important;
28 | }
29 |
30 | .plugins-tips {
31 | padding: 20px 10px;
32 | margin-bottom: 20px;
33 | background: #eef1f6;
34 | }
35 |
36 | .plugins-tips a {
37 | color: var(--el-color-primary);
38 | }
39 |
40 | .el-button + .el-tooltip {
41 | margin-left: 10px;
42 | }
43 |
44 | .mgb20 {
45 | margin-bottom: 20px;
46 | }
47 | .mgb10 {
48 | margin-bottom: 10px;
49 | }
50 | .mr10 {
51 | margin-right: 10px;
52 | }
53 |
54 | .move-enter-active,
55 | .move-leave-active {
56 | transition: opacity 0.1s ease;
57 | }
58 |
59 | .move-enter-from,
60 | .move-leave-to {
61 | opacity: 0;
62 | }
63 |
64 | .el-time-panel__content::after,
65 | .el-time-panel__content::before {
66 | margin-top: -7px;
67 | }
68 |
69 | .el-time-spinner__wrapper .el-scrollbar__wrap:not(.el-scrollbar__wrap--hidden-default) {
70 | padding-bottom: 0;
71 | }
72 |
73 | [hidden] {
74 | display: none !important;
75 | }
76 |
77 | .flex-center {
78 | display: flex;
79 | justify-content: center;
80 | align-items: center;
81 | }
82 |
83 | :root {
84 | --header-bg-color: #242f42;
85 | --header-text-color: #fff;
86 | --active-color: var(--el-color-primary);
87 | }
88 |
--------------------------------------------------------------------------------
/src/assets/img/img.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lin-xin/vue-manage-system/6a7019ec1a74cc05297d18647a5f944c242d468a/src/assets/img/img.jpg
--------------------------------------------------------------------------------
/src/assets/img/login-bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lin-xin/vue-manage-system/6a7019ec1a74cc05297d18647a5f944c242d468a/src/assets/img/login-bg.jpg
--------------------------------------------------------------------------------
/src/assets/img/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/ucenter-bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lin-xin/vue-manage-system/6a7019ec1a74cc05297d18647a5f944c242d468a/src/assets/img/ucenter-bg.jpg
--------------------------------------------------------------------------------
/src/components/countup.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/components/header.vue:
--------------------------------------------------------------------------------
1 |
2 |
64 |
65 |
105 |
205 |
--------------------------------------------------------------------------------
/src/components/menu.ts:
--------------------------------------------------------------------------------
1 | import { Menus } from '@/types/menu';
2 |
3 | export const menuData: Menus[] = [
4 | {
5 | id: '0',
6 | title: '系统首页',
7 | index: '/dashboard',
8 | icon: 'Odometer',
9 | },
10 | {
11 | id: '1',
12 | title: '系统管理',
13 | index: '1',
14 | icon: 'HomeFilled',
15 | children: [
16 | {
17 | id: '11',
18 | pid: '1',
19 | index: '/system-user',
20 | title: '用户管理',
21 | },
22 | {
23 | id: '12',
24 | pid: '1',
25 | index: '/system-role',
26 | title: '角色管理',
27 | },
28 | {
29 | id: '13',
30 | pid: '1',
31 | index: '/system-menu',
32 | title: '菜单管理',
33 | },
34 | ],
35 | },
36 | {
37 | id: '2',
38 | title: '组件',
39 | index: '2-1',
40 | icon: 'Calendar',
41 | children: [
42 | {
43 | id: '21',
44 | pid: '3',
45 | index: '/form',
46 | title: '表单',
47 | },
48 | {
49 | id: '22',
50 | pid: '3',
51 | index: '/upload',
52 | title: '上传',
53 | },
54 | {
55 | id: '23',
56 | pid: '2',
57 | index: '/carousel',
58 | title: '走马灯',
59 | },
60 | {
61 | id: '24',
62 | pid: '2',
63 | index: '/calendar',
64 | title: '日历',
65 | },
66 | {
67 | id: '25',
68 | pid: '2',
69 | index: '/watermark',
70 | title: '水印',
71 | },
72 | {
73 | id: '26',
74 | pid: '2',
75 | index: '/tour',
76 | title: '分布引导',
77 | },
78 | {
79 | id: '27',
80 | pid: '2',
81 | index: '/steps',
82 | title: '步骤条',
83 | },
84 | {
85 | id: '28',
86 | pid: '2',
87 | index: '/statistic',
88 | title: '统计',
89 | },
90 | {
91 | id: '29',
92 | pid: '3',
93 | index: '29',
94 | title: '三级菜单',
95 | children: [
96 | {
97 | id: '291',
98 | pid: '29',
99 | index: '/editor',
100 | title: '富文本编辑器',
101 | },
102 | {
103 | id: '292',
104 | pid: '29',
105 | index: '/markdown',
106 | title: 'markdown编辑器',
107 | },
108 | ],
109 | },
110 | ],
111 | },
112 | {
113 | id: '3',
114 | title: '表格',
115 | index: '3',
116 | icon: 'Calendar',
117 | children: [
118 | {
119 | id: '31',
120 | pid: '3',
121 | index: '/table',
122 | title: '基础表格',
123 | },
124 | {
125 | id: '32',
126 | pid: '3',
127 | index: '/table-editor',
128 | title: '可编辑表格',
129 | },
130 | {
131 | id: '33',
132 | pid: '3',
133 | index: '/import',
134 | title: '导入Excel',
135 | },
136 | {
137 | id: '34',
138 | pid: '3',
139 | index: '/export',
140 | title: '导出Excel',
141 | },
142 | ],
143 | },
144 | {
145 | id: '4',
146 | icon: 'PieChart',
147 | index: '4',
148 | title: '图表',
149 | children: [
150 | {
151 | id: '41',
152 | pid: '4',
153 | index: '/schart',
154 | title: 'schart图表',
155 | },
156 | {
157 | id: '42',
158 | pid: '4',
159 | index: '/echarts',
160 | title: 'echarts图表',
161 | },
162 | ],
163 | },
164 | {
165 | id: '5',
166 | icon: 'Guide',
167 | index: '/icon',
168 | title: '图标',
169 | permiss: '5',
170 | },
171 | {
172 | id: '7',
173 | icon: 'Brush',
174 | index: '/theme',
175 | title: '主题',
176 | },
177 | {
178 | id: '6',
179 | icon: 'DocumentAdd',
180 | index: '6',
181 | title: '附加页面',
182 | children: [
183 | {
184 | id: '61',
185 | pid: '6',
186 | index: '/ucenter',
187 | title: '个人中心',
188 | },
189 | {
190 | id: '62',
191 | pid: '6',
192 | index: '/login',
193 | title: '登录',
194 | },
195 | {
196 | id: '63',
197 | pid: '6',
198 | index: '/register',
199 | title: '注册',
200 | },
201 | {
202 | id: '64',
203 | pid: '6',
204 | index: '/reset-pwd',
205 | title: '重设密码',
206 | },
207 | {
208 | id: '65',
209 | pid: '6',
210 | index: '/403',
211 | title: '403',
212 | },
213 | {
214 | id: '66',
215 | pid: '6',
216 | index: '/404',
217 | title: '404',
218 | },
219 | ],
220 | },
221 | ];
222 |
--------------------------------------------------------------------------------
/src/components/sidebar.vue:
--------------------------------------------------------------------------------
1 |
2 |
53 |
54 |
55 |
68 |
69 |
91 |
--------------------------------------------------------------------------------
/src/components/table-custom.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
38 |
40 |
41 |
43 |
44 |
45 | {{ getIndex($index) }}
46 |
47 |
48 |
49 |
50 |
51 | 查看
52 |
53 |
54 | 编辑
55 |
56 |
57 | 删除
58 |
59 |
60 |
61 | {{ item.formatter(row[item.prop]) }}
62 |
63 |
64 | {{ row[item.prop] }}
65 |
66 |
67 |
68 |
69 |
70 |
71 |
73 |
74 |
75 |
76 |
191 |
192 |
207 |
--------------------------------------------------------------------------------
/src/components/table-detail.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ item.label }}
5 |
6 | {{ item.value || row[item.prop] }}
7 |
8 |
9 |
10 |
11 |
12 |
22 |
--------------------------------------------------------------------------------
/src/components/table-edit.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
9 |
11 |
13 |
14 |
15 |
17 |
20 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | 保 存
36 |
37 |
38 |
39 |
40 |
89 |
90 |
112 |
--------------------------------------------------------------------------------
/src/components/table-search.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
8 |
10 |
11 |
12 |
14 |
15 |
16 | 搜索
17 | 重置
18 |
19 |
20 |
21 |
22 |
23 |
51 |
52 |
61 |
--------------------------------------------------------------------------------
/src/components/tabs.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
13 |
14 |
15 | 标签选项
16 |
17 |
18 |
19 |
20 |
21 |
22 | 关闭其他
23 | 关闭当前
24 | 关闭所有
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
107 |
108 |
149 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue';
2 | import { createPinia } from 'pinia';
3 | import * as ElementPlusIconsVue from '@element-plus/icons-vue';
4 | import App from './App.vue';
5 | import router from './router';
6 | import { usePermissStore } from './store/permiss';
7 | import 'element-plus/dist/index.css';
8 | import './assets/css/icon.css';
9 |
10 | const app = createApp(App);
11 | app.use(createPinia());
12 | app.use(router);
13 |
14 | // 注册elementplus图标
15 | for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
16 | app.component(key, component);
17 | }
18 | // 自定义权限指令
19 | const permiss = usePermissStore();
20 | app.directive('permiss', {
21 | mounted(el, binding) {
22 | if (binding.value && !permiss.key.includes(String(binding.value))) {
23 | el['hidden'] = true;
24 | }
25 | },
26 | });
27 |
28 | app.mount('#app');
29 |
--------------------------------------------------------------------------------
/src/router/index.ts:
--------------------------------------------------------------------------------
1 | import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router';
2 | import { usePermissStore } from '../store/permiss';
3 | import Home from '../views/home.vue';
4 | import NProgress from 'nprogress';
5 | import 'nprogress/nprogress.css';
6 |
7 | const routes: RouteRecordRaw[] = [
8 | {
9 | path: '/',
10 | redirect: '/dashboard',
11 | },
12 | {
13 | path: '/',
14 | name: 'Home',
15 | component: Home,
16 | children: [
17 | {
18 | path: '/dashboard',
19 | name: 'dashboard',
20 | meta: {
21 | title: '系统首页',
22 | noAuth: true,
23 | },
24 | component: () => import(/* webpackChunkName: "dashboard" */ '../views/dashboard.vue'),
25 | },
26 | {
27 | path: '/system-user',
28 | name: 'system-user',
29 | meta: {
30 | title: '用户管理',
31 | permiss: '11',
32 | },
33 | component: () => import(/* webpackChunkName: "system-user" */ '../views/system/user.vue'),
34 | },
35 | {
36 | path: '/system-role',
37 | name: 'system-role',
38 | meta: {
39 | title: '角色管理',
40 | permiss: '12',
41 | },
42 | component: () => import(/* webpackChunkName: "system-role" */ '../views/system/role.vue'),
43 | },
44 | {
45 | path: '/system-menu',
46 | name: 'system-menu',
47 | meta: {
48 | title: '菜单管理',
49 | permiss: '13',
50 | },
51 | component: () => import(/* webpackChunkName: "system-menu" */ '../views/system/menu.vue'),
52 | },
53 | {
54 | path: '/table',
55 | name: 'basetable',
56 | meta: {
57 | title: '基础表格',
58 | permiss: '31',
59 | },
60 | component: () => import(/* webpackChunkName: "table" */ '../views/table/basetable.vue'),
61 | },
62 | {
63 | path: '/table-editor',
64 | name: 'table-editor',
65 | meta: {
66 | title: '可编辑表格',
67 | permiss: '32',
68 | },
69 | component: () => import(/* webpackChunkName: "table-editor" */ '../views/table/table-editor.vue'),
70 | },
71 | {
72 | path: '/schart',
73 | name: 'schart',
74 | meta: {
75 | title: 'schart图表',
76 | permiss: '41',
77 | },
78 | component: () => import(/* webpackChunkName: "schart" */ '../views/chart/schart.vue'),
79 | },
80 | {
81 | path: '/echarts',
82 | name: 'echarts',
83 | meta: {
84 | title: 'echarts图表',
85 | permiss: '42',
86 | },
87 | component: () => import(/* webpackChunkName: "echarts" */ '../views/chart/echarts.vue'),
88 | },
89 |
90 | {
91 | path: '/icon',
92 | name: 'icon',
93 | meta: {
94 | title: '图标',
95 | permiss: '5',
96 | },
97 | component: () => import(/* webpackChunkName: "icon" */ '../views/pages/icon.vue'),
98 | },
99 | {
100 | path: '/ucenter',
101 | name: 'ucenter',
102 | meta: {
103 | title: '个人中心',
104 | },
105 | component: () => import(/* webpackChunkName: "ucenter" */ '../views/pages/ucenter.vue'),
106 | },
107 | {
108 | path: '/editor',
109 | name: 'editor',
110 | meta: {
111 | title: '富文本编辑器',
112 | permiss: '291',
113 | },
114 | component: () => import(/* webpackChunkName: "editor" */ '../views/pages/editor.vue'),
115 | },
116 | {
117 | path: '/markdown',
118 | name: 'markdown',
119 | meta: {
120 | title: 'markdown编辑器',
121 | permiss: '292',
122 | },
123 | component: () => import(/* webpackChunkName: "markdown" */ '../views/pages/markdown.vue'),
124 | },
125 | {
126 | path: '/export',
127 | name: 'export',
128 | meta: {
129 | title: '导出Excel',
130 | permiss: '34',
131 | },
132 | component: () => import(/* webpackChunkName: "export" */ '../views/table/export.vue'),
133 | },
134 | {
135 | path: '/import',
136 | name: 'import',
137 | meta: {
138 | title: '导入Excel',
139 | permiss: '33',
140 | },
141 | component: () => import(/* webpackChunkName: "import" */ '../views/table/import.vue'),
142 | },
143 | {
144 | path: '/theme',
145 | name: 'theme',
146 | meta: {
147 | title: '主题设置',
148 | permiss: '7',
149 | },
150 | component: () => import(/* webpackChunkName: "theme" */ '../views/pages/theme.vue'),
151 | },
152 | {
153 | path: '/calendar',
154 | name: 'calendar',
155 | meta: {
156 | title: '日历',
157 | permiss: '24',
158 | },
159 | component: () => import(/* webpackChunkName: "calendar" */ '../views/element/calendar.vue'),
160 | },
161 | {
162 | path: '/watermark',
163 | name: 'watermark',
164 | meta: {
165 | title: '水印',
166 | permiss: '25',
167 | },
168 | component: () => import(/* webpackChunkName: "watermark" */ '../views/element/watermark.vue'),
169 | },
170 | {
171 | path: '/carousel',
172 | name: 'carousel',
173 | meta: {
174 | title: '走马灯',
175 | permiss: '23',
176 | },
177 | component: () => import(/* webpackChunkName: "carousel" */ '../views/element/carousel.vue'),
178 | },
179 | {
180 | path: '/tour',
181 | name: 'tour',
182 | meta: {
183 | title: '分步引导',
184 | permiss: '26',
185 | },
186 | component: () => import(/* webpackChunkName: "tour" */ '../views/element/tour.vue'),
187 | },
188 | {
189 | path: '/steps',
190 | name: 'steps',
191 | meta: {
192 | title: '步骤条',
193 | permiss: '27',
194 | },
195 | component: () => import(/* webpackChunkName: "steps" */ '../views/element/steps.vue'),
196 | },
197 | {
198 | path: '/form',
199 | name: 'forms',
200 | meta: {
201 | title: '表单',
202 | permiss: '21',
203 | },
204 | component: () => import(/* webpackChunkName: "form" */ '../views/element/form.vue'),
205 | },
206 | {
207 | path: '/upload',
208 | name: 'upload',
209 | meta: {
210 | title: '上传',
211 | permiss: '22',
212 | },
213 | component: () => import(/* webpackChunkName: "upload" */ '../views/element/upload.vue'),
214 | },
215 | {
216 | path: '/statistic',
217 | name: 'statistic',
218 | meta: {
219 | title: '统计',
220 | permiss: '28',
221 | },
222 | component: () => import(/* webpackChunkName: "statistic" */ '../views/element/statistic.vue'),
223 | },
224 | ],
225 | },
226 | {
227 | path: '/login',
228 | meta: {
229 | title: '登录',
230 | noAuth: true,
231 | },
232 | component: () => import(/* webpackChunkName: "login" */ '../views/pages/login.vue'),
233 | },
234 | {
235 | path: '/register',
236 | meta: {
237 | title: '注册',
238 | noAuth: true,
239 | },
240 | component: () => import(/* webpackChunkName: "register" */ '../views/pages/register.vue'),
241 | },
242 | {
243 | path: '/reset-pwd',
244 | meta: {
245 | title: '重置密码',
246 | noAuth: true,
247 | },
248 | component: () => import(/* webpackChunkName: "reset-pwd" */ '../views/pages/reset-pwd.vue'),
249 | },
250 | {
251 | path: '/403',
252 | meta: {
253 | title: '没有权限',
254 | noAuth: true,
255 | },
256 | component: () => import(/* webpackChunkName: "403" */ '../views/pages/403.vue'),
257 | },
258 | {
259 | path: '/404',
260 | meta: {
261 | title: '找不到页面',
262 | noAuth: true,
263 | },
264 | component: () => import(/* webpackChunkName: "404" */ '../views/pages/404.vue'),
265 | },
266 | { path: '/:path(.*)', redirect: '/404' },
267 | ];
268 |
269 | const router = createRouter({
270 | history: createWebHashHistory(),
271 | routes,
272 | });
273 |
274 | router.beforeEach((to, from, next) => {
275 | NProgress.start();
276 | const role = localStorage.getItem('vuems_name');
277 | const permiss = usePermissStore();
278 |
279 | if (!role && to.meta.noAuth !== true) {
280 | next('/login');
281 | } else if (typeof to.meta.permiss == 'string' && !permiss.key.includes(to.meta.permiss)) {
282 | // 如果没有权限,则进入403
283 | next('/403');
284 | } else {
285 | next();
286 | }
287 | });
288 |
289 | router.afterEach(() => {
290 | NProgress.done();
291 | });
292 |
293 | export default router;
294 |
--------------------------------------------------------------------------------
/src/store/permiss.ts:
--------------------------------------------------------------------------------
1 | import { defineStore } from 'pinia';
2 |
3 | interface ObjectList {
4 | [key: string]: string[];
5 | }
6 |
7 | export const usePermissStore = defineStore('permiss', {
8 | state: () => {
9 | const defaultList: ObjectList = {
10 | admin: [
11 | '0',
12 | '1',
13 | '11',
14 | '12',
15 | '13',
16 | '2',
17 | '21',
18 | '22',
19 | '23',
20 | '24',
21 | '25',
22 | '26',
23 | '27',
24 | '28',
25 | '29',
26 | '291',
27 | '292',
28 | '3',
29 | '31',
30 | '32',
31 | '33',
32 | '34',
33 | '4',
34 | '41',
35 | '42',
36 | '5',
37 | '7',
38 | '6',
39 | '61',
40 | '62',
41 | '63',
42 | '64',
43 | '65',
44 | '66',
45 | ],
46 | user: ['0', '1', '11', '12', '13'],
47 | };
48 | const username = localStorage.getItem('vuems_name');
49 | console.log(username);
50 | return {
51 | key: (username == 'admin' ? defaultList.admin : defaultList.user) as string[],
52 | defaultList,
53 | };
54 | },
55 | actions: {
56 | handleSet(val: string[]) {
57 | this.key = val;
58 | },
59 | },
60 | });
61 |
--------------------------------------------------------------------------------
/src/store/sidebar.ts:
--------------------------------------------------------------------------------
1 | import { defineStore } from 'pinia';
2 |
3 | export const useSidebarStore = defineStore('sidebar', {
4 | state: () => {
5 | return {
6 | collapse: false,
7 | bgColor: localStorage.getItem('sidebar-bg-color') || '#324157',
8 | textColor: localStorage.getItem('sidebar-text-color') || '#bfcbd9'
9 | };
10 | },
11 | getters: {},
12 | actions: {
13 | handleCollapse() {
14 | this.collapse = !this.collapse;
15 | },
16 | setBgColor(color: string) {
17 | this.bgColor = color;
18 | localStorage.setItem('sidebar-bg-color', color);
19 | },
20 | setTextColor(color: string) {
21 | this.textColor = color;
22 | localStorage.setItem('sidebar-text-color', color);
23 | }
24 | }
25 | });
26 |
--------------------------------------------------------------------------------
/src/store/tabs.ts:
--------------------------------------------------------------------------------
1 | import { defineStore } from 'pinia';
2 |
3 | interface ListItem {
4 | name: string;
5 | path: string;
6 | title: string;
7 | }
8 |
9 | export const useTabsStore = defineStore('tabs', {
10 | state: () => {
11 | return {
12 | list: []
13 | };
14 | },
15 | getters: {
16 | show: state => {
17 | return state.list.length > 0;
18 | },
19 | nameList: state => {
20 | return state.list.map(item => item.name);
21 | }
22 | },
23 | actions: {
24 | delTabsItem(index: number) {
25 | this.list.splice(index, 1);
26 | },
27 | setTabsItem(data: ListItem) {
28 | this.list.push(data);
29 | },
30 | clearTabs() {
31 | this.list = [];
32 | },
33 | closeTabsOther(data: ListItem[]) {
34 | this.list = data;
35 | },
36 | closeCurrentTag(data: any) {
37 | for (let i = 0, len = this.list.length; i < len; i++) {
38 | const item = this.list[i];
39 | if (item.path === data.$route.fullPath) {
40 | if (i < len - 1) {
41 | data.$router.push(this.list[i + 1].path);
42 | } else if (i > 0) {
43 | data.$router.push(this.list[i - 1].path);
44 | } else {
45 | data.$router.push('/');
46 | }
47 | this.list.splice(i, 1);
48 | break;
49 | }
50 | }
51 | }
52 | }
53 | });
54 |
--------------------------------------------------------------------------------
/src/store/theme.ts:
--------------------------------------------------------------------------------
1 | import { mix, setProperty } from '@/utils';
2 | import { defineStore } from 'pinia';
3 |
4 | export const useThemeStore = defineStore('theme', {
5 | state: () => {
6 | return {
7 | primary: '',
8 | success: '',
9 | warning: '',
10 | danger: '',
11 | info: '',
12 | headerBgColor: '#242f42',
13 | headerTextColor: '#fff',
14 | };
15 | },
16 | getters: {},
17 | actions: {
18 | initTheme() {
19 | ['primary', 'success', 'warning', 'danger', 'info'].forEach((type) => {
20 | const color = localStorage.getItem(`theme-${type}`) || '';
21 | if (color) {
22 | this.setPropertyColor(color, type); // 设置主题色
23 | }
24 | });
25 | const headerBgColor = localStorage.getItem('header-bg-color');
26 | headerBgColor && this.setHeaderBgColor(headerBgColor);
27 | const headerTextColor = localStorage.getItem('header-text-color');
28 | headerTextColor && this.setHeaderTextColor(headerTextColor);
29 | },
30 | resetTheme() {
31 | ['primary', 'success', 'warning', 'danger', 'info'].forEach((type) => {
32 | this.setPropertyColor('', type); // 重置主题色
33 | });
34 | },
35 | setPropertyColor(color: string, type: string = 'primary') {
36 | this[type] = color;
37 | setProperty(`--el-color-${type}`, color);
38 | localStorage.setItem(`theme-${type}`, color);
39 | this.setThemeLight(type);
40 | },
41 | setThemeLight(type: string = 'primary') {
42 | [3, 5, 7, 8, 9].forEach((v) => {
43 | setProperty(`--el-color-${type}-light-${v}`, mix('#ffffff', this[type], v / 10));
44 | });
45 | setProperty(`--el-color-${type}-dark-2`, mix('#ffffff', this[type], 0.2));
46 | },
47 | setHeaderBgColor(color: string) {
48 | this.headerBgColor = color;
49 | setProperty('--header-bg-color', color);
50 | localStorage.setItem(`header-bg-color`, color);
51 | },
52 | setHeaderTextColor(color: string) {
53 | this.headerTextColor = color;
54 | setProperty('--header-text-color', color);
55 | localStorage.setItem(`header-text-color`, color);
56 | }
57 | }
58 | });
--------------------------------------------------------------------------------
/src/types/form-option.ts:
--------------------------------------------------------------------------------
1 | export interface FormOption {
2 | list: FormOptionList[];
3 | labelWidth?: number | string;
4 | span?: number;
5 |
6 | }
7 |
8 | export interface FormOptionList {
9 | prop: string;
10 | label: string;
11 | type: string;
12 | placeholder?: string;
13 | disabled?: boolean;
14 | opts?: any[];
15 | format?: string;
16 | activeValue?: any;
17 | inactiveValue?: any;
18 | activeText?: string;
19 | inactiveText?: string;
20 | required?: boolean;
21 | }
--------------------------------------------------------------------------------
/src/types/menu.ts:
--------------------------------------------------------------------------------
1 | export interface Menus {
2 | id: string;
3 | pid?: string;
4 | icon?: string;
5 | index: string;
6 | title: string;
7 | permiss?: string;
8 | children?: Menus[];
9 | }
--------------------------------------------------------------------------------
/src/types/role.ts:
--------------------------------------------------------------------------------
1 |
2 | export interface Role {
3 | id: number;
4 | name: string;
5 | key: string;
6 | status: boolean;
7 | permiss: string[]
8 | }
--------------------------------------------------------------------------------
/src/types/table.ts:
--------------------------------------------------------------------------------
1 | export interface TableItem {
2 | id: number;
3 | name: string;
4 | thumb: string;
5 | money: number;
6 | state: string;
7 | date: string;
8 | address: string;
9 | }
--------------------------------------------------------------------------------
/src/types/user.ts:
--------------------------------------------------------------------------------
1 |
2 | export interface User {
3 | id: number;
4 | name: string;
5 | password: string;
6 | email: string;
7 | phone: string;
8 | role: string;
9 | date: string;
10 | }
11 |
12 | export interface Register {
13 | username: string;
14 | password: string;
15 | email: string;
16 | }
--------------------------------------------------------------------------------
/src/utils/index.ts:
--------------------------------------------------------------------------------
1 | export const setProperty = (prop: string, val: any, dom = document.documentElement) => {
2 | dom.style.setProperty(prop, val);
3 | };
4 |
5 | export const mix = (color1: string, color2: string, weight: number = 0.5): string => {
6 | let color = '#';
7 | for (let i = 0; i <= 2; i++) {
8 | const c1 = parseInt(color1.substring(1 + i * 2, 3 + i * 2), 16);
9 | const c2 = parseInt(color2.substring(1 + i * 2, 3 + i * 2), 16);
10 | const c = Math.round(c1 * weight + c2 * (1 - weight));
11 | color += c.toString(16).padStart(2, '0');
12 | }
13 | return color;
14 | };
15 |
--------------------------------------------------------------------------------
/src/utils/request.ts:
--------------------------------------------------------------------------------
1 | import axios, { AxiosInstance, AxiosError, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
2 |
3 | const service: AxiosInstance = axios.create({
4 | timeout: 5000
5 | });
6 |
7 | service.interceptors.request.use(
8 | (config: InternalAxiosRequestConfig) => {
9 | return config;
10 | },
11 | (error: AxiosError) => {
12 | console.log(error);
13 | return Promise.reject();
14 | }
15 | );
16 |
17 | service.interceptors.response.use(
18 | (response: AxiosResponse) => {
19 | if (response.status === 200) {
20 | return response;
21 | } else {
22 | Promise.reject();
23 | }
24 | },
25 | (error: AxiosError) => {
26 | console.log(error);
27 | return Promise.reject();
28 | }
29 | );
30 |
31 | export default service;
32 |
--------------------------------------------------------------------------------
/src/views/chart/echarts.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | vue-echarts:Apache ECharts™ 的 Vue.js 组件。 访问地址:
5 |
vue-echarts
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 |
75 |
76 |
88 |
--------------------------------------------------------------------------------
/src/views/chart/options.ts:
--------------------------------------------------------------------------------
1 | import { graphic } from 'echarts/core';
2 | export const barOptions = {
3 | xAxis: {
4 | type: 'category',
5 | data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
6 | },
7 | yAxis: {
8 | type: 'value',
9 | },
10 | tooltip: {
11 | trigger: 'axis',
12 | axisPointer: {
13 | type: 'shadow',
14 | },
15 | },
16 | color: ['#009688', '#f44336'],
17 | series: [
18 | {
19 | data: [120, 200, 150, 80, 70, 110, 130],
20 | type: 'bar',
21 | },
22 | {
23 | data: [180, 230, 190, 120, 110, 230, 235],
24 | type: 'bar',
25 | },
26 | ],
27 | };
28 |
29 | export const lineOptions = {
30 | tooltip: {
31 | trigger: 'axis',
32 | },
33 | grid: {
34 | left: '3%',
35 | right: '4%',
36 | bottom: '3%',
37 | containLabel: true,
38 | },
39 | xAxis: {
40 | type: 'category',
41 | boundaryGap: false,
42 | data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
43 | },
44 | yAxis: {
45 | type: 'value',
46 | },
47 | color: ['#009688', '#f44336'],
48 | series: [
49 | {
50 | name: 'Email',
51 | type: 'line',
52 | stack: 'Total',
53 | areaStyle: {},
54 | smooth: true,
55 | data: [120, 132, 101, 134, 90, 230, 210],
56 | },
57 | {
58 | name: 'Union Ads',
59 | type: 'line',
60 | stack: 'Total',
61 | areaStyle: {},
62 | smooth: true,
63 | data: [220, 182, 191, 234, 290, 330, 310],
64 | },
65 | ],
66 | };
67 |
68 | export const pieOptions = {
69 | title: {
70 | text: 'Referer of a Website',
71 | subtext: 'Fake Data',
72 | left: 'center',
73 | },
74 | tooltip: {
75 | trigger: 'item',
76 | },
77 | legend: {
78 | orient: 'vertical',
79 | left: 'left',
80 | },
81 | series: [
82 | {
83 | name: 'Access From',
84 | type: 'pie',
85 | radius: '50%',
86 | data: [
87 | { value: 1048, name: 'Search Engine' },
88 | { value: 735, name: 'Direct' },
89 | { value: 580, name: 'Email' },
90 | { value: 484, name: 'Union Ads' },
91 | { value: 300, name: 'Video Ads' },
92 | ],
93 | emphasis: {
94 | itemStyle: {
95 | shadowBlur: 10,
96 | shadowOffsetX: 0,
97 | shadowColor: 'rgba(0, 0, 0, 0.5)',
98 | },
99 | },
100 | },
101 | ],
102 | };
103 |
104 | export const wordOptions = {
105 | series: [
106 | {
107 | type: 'wordCloud',
108 | rotationRange: [0, 0],
109 | autoSize: {
110 | enable: true,
111 | minSize: 14,
112 | },
113 | textStyle: {
114 | fontFamily: '微软雅黑,sans-serif',
115 | color: function () {
116 | return (
117 | 'rgb(' +
118 | [
119 | Math.round(Math.random() * 160),
120 | Math.round(Math.random() * 160),
121 | Math.round(Math.random() * 160),
122 | ].join(',') +
123 | ')'
124 | );
125 | },
126 | },
127 | data: [
128 | {
129 | name: 'Vue',
130 | value: 10000,
131 | },
132 | {
133 | name: 'React',
134 | value: 9000,
135 | },
136 | {
137 | name: '图表',
138 | value: 4000,
139 | },
140 | {
141 | name: '产品',
142 | value: 7000,
143 | },
144 | {
145 | name: 'vue-manage-system',
146 | value: 2000,
147 | },
148 | {
149 | name: 'element-plus',
150 | value: 6000,
151 | },
152 | {
153 | name: '管理系统',
154 | value: 5000,
155 | },
156 | {
157 | name: '前端',
158 | value: 4000,
159 | },
160 | {
161 | name: '测试',
162 | value: 3000,
163 | },
164 | {
165 | name: '后端',
166 | value: 8000,
167 | },
168 | {
169 | name: '软件开发',
170 | value: 6000,
171 | },
172 | {
173 | name: '程序员',
174 | value: 4000,
175 | },
176 | ],
177 | },
178 | ],
179 | };
180 |
181 | export const ringOptions = {
182 | tooltip: {
183 | trigger: 'item',
184 | },
185 | legend: {
186 | top: '5%',
187 | left: 'center',
188 | },
189 |
190 | series: [
191 | {
192 | name: 'Access From',
193 | type: 'pie',
194 | radius: ['40%', '70%'],
195 | avoidLabelOverlap: false,
196 | itemStyle: {
197 | borderRadius: 10,
198 | borderColor: '#fff',
199 | borderWidth: 2,
200 | },
201 | label: {
202 | show: false,
203 | position: 'center',
204 | },
205 | emphasis: {
206 | label: {
207 | show: true,
208 | fontSize: 40,
209 | fontWeight: 'bold',
210 | },
211 | },
212 | labelLine: {
213 | show: false,
214 | },
215 | data: [
216 | { value: 1048, name: 'Search Engine' },
217 | { value: 735, name: 'Direct' },
218 | { value: 580, name: 'Email' },
219 | { value: 484, name: 'Union Ads' },
220 | { value: 300, name: 'Video Ads' },
221 | ],
222 | },
223 | ],
224 | };
225 |
226 | export const dashOpt1 = {
227 | xAxis: {
228 | type: 'category',
229 | boundaryGap: false,
230 | data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
231 | },
232 | yAxis: {
233 | type: 'value',
234 | },
235 | grid: {
236 | top: '2%',
237 | left: '2%',
238 | right: '3%',
239 | bottom: '2%',
240 | containLabel: true,
241 | },
242 | color: ['#009688', '#f44336'],
243 | series: [
244 | {
245 | type: 'line',
246 | areaStyle: {
247 | color: new graphic.LinearGradient(0, 0, 0, 1, [
248 | {
249 | offset: 0,
250 | color: 'rgba(0, 150, 136,0.8)',
251 | },
252 | {
253 | offset: 1,
254 | color: 'rgba(0, 150, 136,0.2)',
255 | },
256 | ]),
257 | },
258 | smooth: true,
259 | data: [120, 132, 301, 134, 90, 230, 210],
260 | },
261 | {
262 | type: 'line',
263 | smooth: true,
264 | data: [220, 122, 191, 234, 190, 130, 310],
265 | },
266 | ],
267 | };
268 |
269 | export const dashOpt2 = {
270 | legend: {
271 | bottom: '1%',
272 | left: 'center',
273 | },
274 | color: ['#3f51b5', '#009688', '#f44336', '#00bcd4', '#1ABC9C'],
275 | series: [
276 | {
277 | type: 'pie',
278 | radius: ['40%', '70%'],
279 | avoidLabelOverlap: false,
280 | itemStyle: {
281 | borderRadius: 10,
282 | borderColor: '#fff',
283 | borderWidth: 2,
284 | },
285 | data: [
286 | { value: 1048, name: '数码' },
287 | { value: 735, name: '食品' },
288 | { value: 580, name: '母婴' },
289 | { value: 484, name: '家电' },
290 | { value: 300, name: '运动' },
291 | ],
292 | },
293 | ],
294 | };
295 |
296 | export const mapOptions = {
297 | tooltip: {
298 | trigger: 'item',
299 | },
300 | geo: {
301 | map: 'china',
302 | roam: false,
303 | emphasis: {
304 | label: {
305 | show: false,
306 | },
307 | },
308 | },
309 | visualMap: {
310 | show: false,
311 | min: 0,
312 | max: 100,
313 | realtime: false,
314 | calculable: false,
315 | inRange: {
316 | color: ['#d2e0f5', '#71A9FF'],
317 | },
318 | },
319 | series: [
320 | {
321 | geoIndex: 0,
322 | name: '地域分布',
323 | type: 'map',
324 | coordinateSystem: 'geo',
325 | map: 'china',
326 | data: [
327 | { name: '北京', value: 100 },
328 | { name: '上海', value: 100 },
329 | { name: '广东', value: 100 },
330 | { name: '浙江', value: 90 },
331 | { name: '江西', value: 80 },
332 | { name: '山东', value: 70 },
333 | { name: '广西', value: 60 },
334 | { name: '河南', value: 50 },
335 | { name: '河南', value: 40 },
336 | { name: '青海', value: 70 },
337 | { name: '河南', value: 30 },
338 | { name: '黑龙江', value: 20 },
339 | { name: '新疆', value: 20 },
340 | { name: '云南', value: 20 },
341 | { name: '甘肃', value: 20 },
342 | ],
343 | },
344 | ],
345 | };
346 |
--------------------------------------------------------------------------------
/src/views/chart/schart.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | vue-schart:vue.js封装sChart.js的图表组件。 访问地址:
5 |
vue-schart
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 |
117 |
118 |
130 |
--------------------------------------------------------------------------------
/src/views/dashboard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
57 |
58 |
59 |
60 |
61 |
62 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
77 |
78 |
79 |
80 |
81 |
{{ activity.content }}
82 |
{{ activity.description }}
83 |
84 |
{{ activity.timestamp }}
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
96 |
97 |
98 |
99 |
100 |
101 |
105 |
106 |
107 |
{{ index + 1 }}
108 |
109 |
110 |
{{ rank.title }}
111 |
销量:{{ rank.value }}
112 |
113 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
223 |
224 |
232 |
358 |
--------------------------------------------------------------------------------
/src/views/element/calendar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ data.date.getDate() }}
6 |
7 |
8 |
9 |
{{ note.title }}
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
39 |
40 |
83 |
--------------------------------------------------------------------------------
/src/views/element/carousel.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 基础用法
5 |
6 |
7 | {{ item }}
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 |
45 |
46 |
67 |
--------------------------------------------------------------------------------
/src/views/element/form.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Left
5 | Right
6 | Top
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 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | 表单提交
73 | 重置表单
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/src/views/element/statistic.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 基础用法
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | Ratio of men to women
16 |
17 |
18 | /100
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | CountUp.js
32 |
33 | countup.js:用于快速创建以更有趣的方式显示数字数据的动画。 访问地址:
34 |
countUp.js
35 |
36 |
37 |
38 | 基础用法
39 |
40 |
41 |
42 | 具体配置
43 |
44 |
45 |
46 | 更新数值
47 |
48 |
49 |
50 |
51 |
52 | 统计卡片
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
261 |
262 |
286 |
--------------------------------------------------------------------------------
/src/views/element/steps.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
输入注册时的邮箱,我们会发送验证码到您的邮箱
5 |
6 |
下一步
7 |
8 |
9 |
验证码已发送至您的邮箱,请输入验证码
10 |
11 |
下一步
12 |
13 |
14 |
15 |
请输入6位以上密码
16 |
17 |
保存
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
39 |
40 |
--------------------------------------------------------------------------------
/src/views/element/tabs.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{ scope.row.title }}
8 |
9 |
10 |
11 |
12 |
13 | 标为已读
14 |
15 |
16 |
17 |
18 | 全部标为已读
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | {{ scope.row.title }}
27 |
28 |
29 |
30 |
31 |
32 | 删除
33 |
34 |
35 |
36 |
37 | 删除全部
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | {{ scope.row.title }}
47 |
48 |
49 |
50 |
51 |
52 | 还原
53 |
54 |
55 |
56 |
57 | 清空回收站
58 |
59 |
60 |
61 |
62 |
63 |
64 |
106 |
107 |
117 |
--------------------------------------------------------------------------------
/src/views/element/tour.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 |
--------------------------------------------------------------------------------
/src/views/element/upload.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
支持拖拽
4 |
8 |
10 |
11 |
12 | 将文件拖到此处,或
13 | 点击上传
14 |
15 |
16 |
17 |
支持裁剪
18 |
19 | vue-cropper:一个简单的vue图片裁剪插件。 访问地址:
20 |
vue-cropper。 示例请查看
21 |
个人中心-我的头像
22 |
23 |
24 |
25 |
26 |
31 |
32 |
45 |
--------------------------------------------------------------------------------
/src/views/element/watermark.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
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 |
37 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/src/views/home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
29 |
30 |
64 |
--------------------------------------------------------------------------------
/src/views/pages/403.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
403
5 |
啊哦~ 你没有权限访问该页面哦
6 |
7 |
8 | 返回首页
9 |
10 | 返回上一页
11 |
12 |
13 |
14 |
15 |
16 |
24 |
25 |
68 |
--------------------------------------------------------------------------------
/src/views/pages/404.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
404
5 |
啊哦~ 你所访问的页面不存在
6 |
7 |
8 | 返回首页
9 |
10 | 返回上一页
11 |
12 |
13 |
14 |
15 |
16 |
24 |
25 |
68 |
--------------------------------------------------------------------------------
/src/views/pages/editor.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | wangEditor:轻量级 web 富文本编辑器,配置方便,使用简单。 访问地址:
5 |
wangEditor
6 |
7 |
8 |
9 |
15 |
16 |
提交
17 |
18 |
19 |
20 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/src/views/pages/icon.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 使用方法
6 |
7 | 直接通过设置类名为 el-icon-lx-iconName 来使用即可。例如:(共{{ iconList.length }}个图标)
8 |
9 |
10 |
11 | <i class="el-icon-lx-redpacket_fill"></i>
12 |
13 |
14 |
15 | <i class="el-icon-lx-weibo"></i>
16 |
17 |
18 |
19 | <i class="el-icon-lx-emojifill"></i>
20 |
21 |
22 | 图标
23 |
24 |
25 |
26 |
34 |
35 |
36 | 前往官方文档查看
38 |
39 |
40 |
41 |
42 |
205 |
206 |
258 |
--------------------------------------------------------------------------------
/src/views/pages/login.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | 忘记密码
35 |
36 | 登录
37 | Tips : 用户名和密码随便填。
38 |
39 | 没有账号?立即注册
40 |
41 |
42 |
43 |
44 |
45 |
46 |
105 |
106 |
172 |
--------------------------------------------------------------------------------
/src/views/pages/markdown.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | md-editor-v3:vue3版本的 markdown 编辑器,配置丰富,请详看文档。 访问地址:
5 |
md-editor-v3
6 |
7 |
8 |
提交
9 |
10 |
11 |
12 |
22 |
--------------------------------------------------------------------------------
/src/views/pages/register.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | 注册
42 |
43 | 已有账号,立即登录
44 |
45 |
46 |
47 |
48 |
49 |
50 |
87 |
88 |
136 |
--------------------------------------------------------------------------------
/src/views/pages/reset-pwd.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
重置密码
5 |
输入你的邮箱,我们将发送重置密码邮件
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | 发送邮件
19 | 返回登录
20 |
21 |
22 |
23 |
24 |
25 |
55 |
56 |
103 |
--------------------------------------------------------------------------------
/src/views/pages/theme.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 系统主题
6 |
7 |
8 |
{{ item.name }}
10 |
11 |
12 |
13 | 重置主题
14 |
15 |
16 |
17 |
18 | Element-Plus主题
19 |
20 |
21 |
22 |
{{ theme.name }}
23 |
{{ theme.color }}
24 |
25 |
26 |
27 |
28 | 重置主题
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | 头部主题
37 |
38 |
39 |
40 |
背景颜色
41 |
{{ color.headerBgColor }}
42 |
44 |
45 |
46 |
文字颜色
47 |
{{ color.headerTextColor }}
48 |
50 |
51 |
52 |
53 | 重置主题
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | 菜单主题
62 |
63 |
64 |
65 |
背景颜色
66 |
{{ sidebar.bgColor }}
67 |
69 |
70 |
71 |
文字颜色
72 |
{{ sidebar.textColor }}
73 |
75 |
76 |
77 |
78 | 重置主题
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
186 |
187 |
206 |
--------------------------------------------------------------------------------
/src/views/pages/ucenter.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
{{ name }}
11 |
12 | @lin-xin
13 |
14 | lin-xin.gitee.io
15 |
16 |
FE Developer
17 |
23 |
24 |
35 |
36 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
55 |
56 |
57 | 选择图片
59 |
60 |
61 | 上传并保存
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | 保存
76 |
77 |
78 |
79 |
80 |
81 | 如果该框架
82 | vue-manage-system
85 | 对你有帮助,那就请作者喝杯饮料吧!
86 |
87 |
88 | 加微信号 linxin_20 探讨问题。
89 |
90 |
91 |

92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
143 |
144 |
265 |
266 |
271 |
--------------------------------------------------------------------------------
/src/views/system/menu.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 | 新增
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
19 |
20 |
21 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
143 |
144 |
--------------------------------------------------------------------------------
/src/views/system/role-permission.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 | 保存权限
13 |
14 |
15 |
16 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/src/views/system/role.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
8 |
9 | 新增
10 |
11 |
12 | 启用
13 | 禁用
14 |
15 |
16 | 管理
17 |
18 |
19 |
20 |
22 |
23 |
24 |
25 |
26 |
27 | 启用
28 | 禁用
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
161 |
162 |
--------------------------------------------------------------------------------
/src/views/system/user.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 | 新增
9 |
10 |
11 |
12 |
13 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
147 |
148 |
--------------------------------------------------------------------------------
/src/views/table/basetable.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 | 新增
10 |
11 |
12 | ¥{{ rows.money }}
13 |
14 |
15 |
17 |
18 |
19 |
20 |
21 | {{ rows.state ? '正常' : '异常' }}
22 |
23 |
24 |
25 |
26 |
27 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
161 |
162 |
170 |
--------------------------------------------------------------------------------
/src/views/table/export.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 导出Excel
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
69 |
70 |
99 |
--------------------------------------------------------------------------------
/src/views/table/import.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 | 批量导入
8 |
9 | 下载模板
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
98 |
99 |
110 |
--------------------------------------------------------------------------------
/src/views/table/table-editor.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{ rows.name }}
7 |
8 |
9 |
10 | {{ rows.password }}
11 |
12 |
13 |
14 | {{ rows.email }}
15 |
16 |
17 |
18 |
19 |
20 |
21 | {{ rows.role }}
22 |
23 |
24 |
25 |
26 | 编辑
27 |
28 |
29 | 删除
30 |
31 |
32 |
33 |
34 | 保存
35 |
36 |
37 | 取消
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | declare module '*.vue' {
4 | import type { DefineComponent } from 'vue'
5 | const component: DefineComponent<{}, {}, any>
6 | export default component
7 | }
8 |
9 | declare module 'vue-schart';
10 | declare module 'nprogress'
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "useDefineForClassFields": true,
5 | "module": "ESNext",
6 | "moduleResolution": "Node",
7 | "strict": false,
8 | "jsx": "preserve",
9 | "sourceMap": true,
10 | "resolveJsonModule": true,
11 | "isolatedModules": true,
12 | "esModuleInterop": true,
13 | "lib": ["ESNext", "DOM"],
14 | "skipLibCheck": true,
15 | "baseUrl": "./",
16 | "paths": {
17 | "@/*": ["src/*"]
18 | }
19 | },
20 | "include": ["src/**/*.ts", "src/**/*.d.ts","src/**/*.vue"],
21 | "references": [{ "path": "./tsconfig.node.json" }]
22 | }
23 |
--------------------------------------------------------------------------------
/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "module": "ESNext",
5 | "moduleResolution": "Node",
6 | "allowSyntheticDefaultImports": true
7 | },
8 | "include": ["vite.config.ts"]
9 | }
10 |
--------------------------------------------------------------------------------
/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import vue from '@vitejs/plugin-vue';
3 | import VueSetupExtend from 'vite-plugin-vue-setup-extend';
4 | import AutoImport from 'unplugin-auto-import/vite';
5 | import Components from 'unplugin-vue-components/vite';
6 | import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
7 | export default defineConfig({
8 | base: './',
9 | plugins: [
10 | vue(),
11 | VueSetupExtend(),
12 | AutoImport({
13 | resolvers: [ElementPlusResolver()]
14 | }),
15 | Components({
16 | resolvers: [ElementPlusResolver()]
17 | })
18 | ],
19 | optimizeDeps: {
20 | include: ['schart.js']
21 | },
22 | resolve: {
23 | alias: {
24 | '@': '/src',
25 | '~': '/src/assets'
26 | }
27 | },
28 | define: {
29 | __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: "true",
30 | },
31 | });
32 |
--------------------------------------------------------------------------------