├── .browserslistrc ├── .editorconfig ├── .eslintrc.js ├── .gitignore ├── .gitlab-ci.yml ├── .gitlab-deploy.sh ├── .prettierrc.js ├── .vscode └── settings.json ├── LICENSE ├── README.md ├── babel.config.js ├── jsconfig.json ├── package.json ├── public └── logo.ico ├── src ├── app.js ├── components │ ├── App.vue │ ├── app │ │ ├── app-footer.vue │ │ ├── app-frame.vue │ │ ├── app-header.vue │ │ ├── app-logo.vue │ │ ├── app-menu.vue │ │ └── modules │ │ │ ├── app-header-message.vue │ │ │ └── app-layout-setting.vue │ ├── common-item │ │ ├── a-item.vue │ │ └── b-item.vue │ ├── common │ │ ├── address-picker.vue │ │ ├── baidu-map │ │ │ ├── baidu-map.vue │ │ │ ├── index.js │ │ │ └── load.js │ │ ├── chart │ │ │ ├── echarts.vue │ │ │ ├── index.js │ │ │ └── theme.js │ │ ├── code-editor │ │ │ ├── code-editor.vue │ │ │ ├── index.js │ │ │ └── props.js │ │ ├── markdown-editor.vue │ │ ├── richtext-editor.vue │ │ ├── search-filter.vue │ │ ├── sub-menu.vue │ │ ├── sys-tabs │ │ │ ├── index.js │ │ │ ├── sys-tabs.vue │ │ │ └── utils.js │ │ └── upload.vue │ ├── demo-components │ │ ├── account │ │ │ ├── account-setting.vue │ │ │ ├── account.vue │ │ │ └── modules │ │ │ │ ├── account-info-edit.vue │ │ │ │ ├── account-info-show.vue │ │ │ │ ├── notice-setting.vue │ │ │ │ └── security-setting.vue │ │ ├── autocomplete1.vue │ │ ├── autocomplete2.vue │ │ ├── autocomplete3.vue │ │ ├── components │ │ │ ├── address-picker.vue │ │ │ ├── baidu-map.vue │ │ │ ├── chart.vue │ │ │ ├── code-editor.vue │ │ │ ├── datas │ │ │ │ ├── data1.js │ │ │ │ ├── data2.js │ │ │ │ ├── data3.js │ │ │ │ ├── data4.js │ │ │ │ └── data5.js │ │ │ ├── markdown-editor.vue │ │ │ └── richtext-editor.vue │ │ ├── form-detail.vue │ │ ├── form.vue │ │ ├── form │ │ │ ├── basic.vue │ │ │ └── create.vue │ │ ├── icons.vue │ │ ├── info │ │ │ ├── basic.vue │ │ │ └── detail.vue │ │ └── table │ │ │ ├── basic.vue │ │ │ ├── detail.vue │ │ │ └── search.vue │ ├── error-pages │ │ ├── 403.vue │ │ ├── 404.vue │ │ └── 500.vue │ ├── home │ │ └── index.vue │ ├── login │ │ └── index.vue │ └── management │ │ ├── authorization.vue │ │ └── users.vue ├── css │ ├── app.less │ ├── common.less │ ├── fonts │ │ ├── Read Me.txt │ │ ├── demo-files │ │ │ ├── demo.css │ │ │ └── demo.js │ │ ├── demo.html │ │ ├── fonts │ │ │ ├── heyuiadmin.eot │ │ │ ├── heyuiadmin.svg │ │ │ ├── heyuiadmin.ttf │ │ │ └── heyuiadmin.woff │ │ ├── selection.json │ │ ├── style.css │ │ ├── style.less │ │ └── variables.less │ ├── frame.less │ ├── markdown.less │ ├── overwrite.less │ ├── richtext-editor.less │ ├── var.js │ └── var.less ├── images │ ├── avatar.png │ ├── error-pages │ │ ├── 403.png │ │ ├── 404.png │ │ └── 500.png │ ├── folders.png │ └── logo.png ├── index.html ├── js │ ├── common │ │ ├── ajax.js │ │ ├── qiniuUpload.js │ │ ├── request.js │ │ └── utils.js │ ├── config │ │ ├── autocomplete-config.js │ │ ├── category-config.js │ │ ├── demo-components.js │ │ ├── dict-config.js │ │ ├── heyui-config.js │ │ ├── menu-config.js │ │ ├── router-config.js │ │ └── tree-config.js │ ├── model │ │ ├── Form.js │ │ └── login │ │ │ └── Login.js │ ├── vue │ │ ├── components.js │ │ ├── directives.js │ │ └── filters.js │ └── vuex │ │ └── store.js └── mock │ ├── index.js │ └── users.js └── vue.config.js /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not ie <= 8 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*.{js,jsx,ts,tsx,vue}] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | indent_style = space 8 | indent_size = 2 9 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | globals: { 7 | $: true, 8 | 'BMap': true 9 | }, 10 | extends: ['plugin:vue/vue3-essential'], 11 | parserOptions: { 12 | parser: 'babel-eslint', 13 | ecmaVersion: 6, 14 | sourceType: 'module' 15 | }, 16 | rules: { 17 | 'vue/script-setup-uses-vars': 'off' 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | docs/_book 3 | dist 4 | package-lock.json -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | stages: 2 | - deploy 3 | deploy: 4 | stage: deploy 5 | script: 6 | - bash .gitlab-deploy.sh 7 | only: 8 | - master 9 | tags: 10 | - heyui 11 | when: manual -------------------------------------------------------------------------------- /.gitlab-deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -d "dist" ]; then 4 | if [ -d "/home/gitlab-runner/heyui-admin" ]; then 5 | rm -rf /home/gitlab-runner/heyui-admin 6 | fi 7 | cp -rf dist /home/gitlab-runner/heyui-admin 8 | else 9 | echo "dist不存在" 10 | fi -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "eslintIntegration": true, 3 | "printWidth": 150, // 每行代码长度(默认80) 4 | "tabWidth": 2, // 每个tab相当于多少个空格(默认2) 5 | "useTabs": false, // 是否使用tab进行缩进(默认false) 6 | "singleQuote": true, // 使用单引号(默认false) 7 | "semi": true, // 声明结尾使用分号(默认true) 8 | "trailingComma": "none", // 多行使用拖尾逗号(默认none) 9 | "bracketSpacing": true, // 对象字面量的大括号间使用空格(默认true) 10 | "jsxBracketSameLine": false, // 多行JSX中的>放置在最后一行的结尾,而不是另起一行(默认false) 11 | "arrowParens": "avoid" // 只有一个参数的箭头函数的参数是否带圆括号(默认avoid) 12 | }; -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "[typescript]": { 3 | "editor.defaultFormatter": "esbenp.prettier-vscode", 4 | "editor.formatOnSave": true 5 | }, 6 | "[javascript]": { 7 | "editor.defaultFormatter": "esbenp.prettier-vscode", 8 | "editor.formatOnSave": true 9 | }, 10 | "[html]": { 11 | "editor.defaultFormatter": "esbenp.prettier-vscode", 12 | "editor.formatOnSave": true 13 | }, 14 | "[vue]": { 15 | "editor.defaultFormatter": "esbenp.prettier-vscode", 16 | "editor.formatOnSave": true 17 | }, 18 | "[less]": { 19 | "editor.defaultFormatter": "esbenp.prettier-vscode", 20 | "editor.formatOnSave": true 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018-present, Lan (vvpvvp) 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 |

HeyUI-Admin

2 | 3 |

4 | 5 | vue 6 | 7 | 8 | heyui 9 | 10 | 11 | license 12 | 13 |

14 | 15 |
16 | 17 | ![image](https://user-images.githubusercontent.com/8186664/51449312-6cc17c00-1d66-11e9-9ec2-33e0ed703af9.png) 18 | 19 |
20 | 21 | ## 介绍 22 | 23 | heyui-admin 2.0 是一个成熟的企业应用解决方案,基于 vue3.0 和 heyui2.0 组件库的中后端系统。 24 | 25 | 这是一个成熟的前端开发解决方案,你可以使用这个架构完成几乎 90%的前端开发工作。 26 | 27 | heyui admin 1.0 版本的代码请参考:[heyui admin 1.0版本](https://github.com/heyui/heyui-admin/tree/v1) 28 | 29 | heyui 2.0 文档请参考:[heyui 2.0 版本](https://v2.heyui.top) 30 | 31 | ## 在线示例 32 | 33 | 我们启动了线上的项目,方便用户查看 heyui-admin 的实际使用效果。 34 | 35 | [在线预览](https://admin.heyui.top) 36 | 37 | ## 教学文档 38 | 39 | 我们为 heyui-admin 提供了相关的教程说明,如果你在使用的过程中有疑问,建议先查阅相关文档。 40 | 41 | [教学文档](http://docs.v2.heyui.top) 42 | 43 | ## 准备 44 | 45 | 项目基于以下依赖: 46 | 47 | - [heyui](https://v2.heyui.top/) 48 | - [vue](https://cn.vuejs.org/index.html) 49 | - [vuex](https://vuex.vuejs.org/zh-cn/) 50 | - [vue-router](https://router.vuejs.org/zh-cn/) 51 | - [axios](https://github.com/axios/axios) 52 | - [js-model](https://www.npmjs.com/package/js-model) 53 | - [manba](https://www.npmjs.com/package/manba) 54 | - [hey-utils](https://www.npmjs.com/package/hey-utils) 55 | - [hey-global](https://www.npmjs.com/package/hey-global) 56 | - [hey-log](https://www.npmjs.com/package/hey-log) 57 | 58 | 提前了解和学习这些知识将大大有助于这个项目的使用。 59 | 60 | ## 功能 61 | 62 | ``` 63 | - Js 64 | - common / 通用 65 | - ajax / 封装axios 66 | - request / 封装所有的请求 67 | - utils / 通用方法 68 | - model / Js模型 69 | - config / 配置 70 | - router-config / 路由配置 71 | - heyui-config / heyui配置 72 | - dict-config / 字典配置 73 | - autocomplete-config / autocomplete配置 74 | - category-config / category配置 75 | - tree-config / 树配置 76 | - menu-config / 系统菜单配置 77 | - vue 78 | - components / 通用组件 79 | - filters / 通用filters 80 | - directives / 通用directives 81 | - vuex 82 | - store 83 | 84 | - 框架组件 85 | - App 86 | - App头部 87 | - 消息 88 | - 全局搜索 89 | - App左侧菜单 90 | - 登录 91 | 92 | - 组件 93 | - 仪表盘 94 | - Icons 95 | - 信息页 96 | - 详情信息 97 | - Form 98 | - 基本的表单 99 | - 创建 100 | - Table 101 | - 基本表格 102 | - 搜索 103 | - 详情弹框 104 | - Components 105 | - 图表 106 | - 富文本编辑器Editor 107 | - 代码编辑器 108 | - Markdown编辑器 109 | - 剪贴板 110 | - 个人中心 111 | - 基本信息 112 | - 安全中心 113 | - 登出 114 | 115 | - 错误页面 116 | - 403 117 | - 404 118 | - 500 119 | ``` 120 | 121 | ## 开始 122 | 123 | ### 使用 vue-cli 124 | 125 | 需要全局安装 vue-cli@4.0.0+ 126 | 127 | ```bash 128 | # clone the project 129 | git clone https://github.com/heyui/heyui-admin.git 130 | 131 | cd heyui-admin 132 | 133 | # install dependency 134 | npm install 135 | 136 | # develop 137 | npm run dev 138 | ``` 139 | 140 | 141 | ## 构建 142 | 143 | ```bash 144 | # build 145 | npm run build 146 | ``` 147 | 148 | ## 浏览器支持 149 | 150 | 现代浏览器. 151 | 152 | **系统已经自动安装配置好 polyfill.** 153 | 154 | ## 打赏 155 | 156 | 如果你觉得这个项目帮助到了你,你可以帮作者买一杯茶🍵表示鼓励。 157 | 158 | ![image](https://heyui.github.io/heyui-admin-docs/images/docs/tea.jpg) 159 | 160 | 161 | ## License 162 | 163 | [MIT](https://github.com/heyui/heyui-admin/blob/master/LICENSE) 164 | 165 | Copyright (c) 2018-present Lan (vvpvvp) 166 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | ['@vue/app'] 4 | ], 5 | }; 6 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "paths": { 5 | "@*": ["src/*"] 6 | }, 7 | "target": "ES6", 8 | "module": "commonjs", 9 | "allowSyntheticDefaultImports": true 10 | }, 11 | "include": ["src/**/*"], 12 | "exclude": [ 13 | "node_modules" 14 | ] 15 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "heyui-admin", 3 | "version": "2.0.0", 4 | "description": "HeyUI components framework.", 5 | "main": "index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/heyui/heyui-admin.git" 9 | }, 10 | "homepage": "http://admin.heyui.top/", 11 | "keywords": [ 12 | "vue", 13 | "ui", 14 | "framework" 15 | ], 16 | "author": { 17 | "name": "vvpvvp" 18 | }, 19 | "license": "MIT", 20 | "dependencies": { 21 | "axios": "^v0.21.1", 22 | "brace": "^0.11.1", 23 | "core-js": "^3.6.5", 24 | "echarts": "^4.2.0-rc.2", 25 | "fetch-jsonp": "^1.1.3", 26 | "hey-utils": "^0.4.0", 27 | "heyui": "^2.1.0-alpha.10", 28 | "js-model": "^1.4.2", 29 | "lodash": "^4.0.8", 30 | "manba": "^1.3.5", 31 | "marked": "^0.6.2", 32 | "qs": "^6.4.0", 33 | "vue-router": "^4.0.3", 34 | "vuex": "^4.0.0", 35 | "wangeditor": "^3.1.1" 36 | }, 37 | "scripts": { 38 | "dev": "vue-cli-service serve", 39 | "build": "vue-cli-service build", 40 | "report": "vue-cli-service build --report", 41 | "lint": "vue-cli-service lint" 42 | }, 43 | "devDependencies": { 44 | "@vue/cli-plugin-babel": "~4.5.0", 45 | "@vue/cli-plugin-eslint": "~4.5.0", 46 | "@vue/cli-service": "~4.5.0", 47 | "@vue/compiler-sfc": "^3.0.0", 48 | "babel-eslint": "^10.1.0", 49 | "babel-plugin-import": "^1.13.3", 50 | "copy-webpack-plugin": "^6.4.1", 51 | "eslint": "^6.7.2", 52 | "eslint-plugin-vue": "^7.0.0-0", 53 | "less": "^4.1.1", 54 | "less-loader": "^7.3.0", 55 | "lint-staged": "^10.5.4", 56 | "mockjs": "^1.0.1-beta3", 57 | "vue-loader-v16": "^16.0.0-beta.5.4" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /public/logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyui/heyui-admin/a5f5dad31b4e8f0793379f73559096dc98648168/public/logo.ico -------------------------------------------------------------------------------- /src/app.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue'; 2 | import App from '@components/App'; 3 | import heyui from 'heyui'; 4 | import initHeyui from '@js/config/heyui-config'; 5 | import router from '@js/config/router-config'; 6 | import store from '@js/vuex/store'; 7 | import initComponents from '@js/vue/components'; 8 | import initFilters from '@js/vue/filters'; 9 | import initDirectives from '@js/vue/directives'; 10 | import '@js/vue/filters'; 11 | 12 | require('./css/app.less'); 13 | 14 | // 开发环境判断 15 | // process.env.NODE_ENV == 'development' 16 | 17 | // 使用mock文件, 自己开发的时候请删除 18 | require('./mock/index'); 19 | 20 | const app = createApp(App); 21 | app.use(heyui); 22 | app.use(store); 23 | app.use(router); 24 | initComponents(app); 25 | initFilters(app); 26 | initDirectives(app); 27 | initHeyui(); 28 | 29 | app.mount('#app'); 30 | export default app; 31 | -------------------------------------------------------------------------------- /src/components/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 15 | -------------------------------------------------------------------------------- /src/components/app/app-footer.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 19 | 28 | -------------------------------------------------------------------------------- /src/components/app/app-frame.vue: -------------------------------------------------------------------------------- 1 | 2 | 30 | 116 | -------------------------------------------------------------------------------- /src/components/app/app-header.vue: -------------------------------------------------------------------------------- 1 | 91 | 92 | 143 | 216 | -------------------------------------------------------------------------------- /src/components/app/app-logo.vue: -------------------------------------------------------------------------------- 1 | 36 | 41 | 51 | -------------------------------------------------------------------------------- /src/components/app/app-menu.vue: -------------------------------------------------------------------------------- 1 | 31 | 38 | 88 | -------------------------------------------------------------------------------- /src/components/app/modules/app-header-message.vue: -------------------------------------------------------------------------------- 1 | 52 | 83 | 116 | -------------------------------------------------------------------------------- /src/components/app/modules/app-layout-setting.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 58 | 81 | -------------------------------------------------------------------------------- /src/components/common-item/a-item.vue: -------------------------------------------------------------------------------- 1 | 19 | 28 | 52 | -------------------------------------------------------------------------------- /src/components/common-item/b-item.vue: -------------------------------------------------------------------------------- 1 | 3 | 8 | 28 | -------------------------------------------------------------------------------- /src/components/common/address-picker.vue: -------------------------------------------------------------------------------- 1 | 3 | 8 | 28 | -------------------------------------------------------------------------------- /src/components/common/baidu-map/baidu-map.vue: -------------------------------------------------------------------------------- 1 | 6 | 9 | 49 | -------------------------------------------------------------------------------- /src/components/common/baidu-map/index.js: -------------------------------------------------------------------------------- 1 | import BaiduMap from './baidu-map'; 2 | 3 | export default BaiduMap; 4 | -------------------------------------------------------------------------------- /src/components/common/baidu-map/load.js: -------------------------------------------------------------------------------- 1 | export default function () { 2 | return new Promise(function (resolve, reject) { 3 | var script = document.createElement('script'); 4 | script.type = 'text/javascript'; 5 | script.src = `//api.map.baidu.com/api?v=2.0&ak=20qOZbvLhZnFinXiG1NfGPLC&s=1&callback=baiduMapInitialize`; 6 | script.onerror = reject; 7 | window.baiduMapInitialize = function () { 8 | resolve(); 9 | }; 10 | document.head.appendChild(script); 11 | }); 12 | } 13 | -------------------------------------------------------------------------------- /src/components/common/chart/echarts.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 11 | 12 | 85 | -------------------------------------------------------------------------------- /src/components/common/chart/index.js: -------------------------------------------------------------------------------- 1 | import ECharts from './echarts'; 2 | 3 | require('echarts/lib/component/tooltip'); 4 | 5 | export default ECharts; 6 | -------------------------------------------------------------------------------- /src/components/common/code-editor/code-editor.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 316 | -------------------------------------------------------------------------------- /src/components/common/code-editor/index.js: -------------------------------------------------------------------------------- 1 | import Editor from './code-editor'; 2 | 3 | import 'brace/ext/language_tools'; 4 | import 'brace/theme/chaos'; 5 | import 'brace/theme/gob'; 6 | import 'brace/theme/tomorrow'; 7 | import 'brace/mode/javascript'; 8 | import 'brace/mode/sql'; 9 | import 'brace/mode/json'; 10 | import 'brace/mode/markdown'; 11 | 12 | export default Editor; 13 | -------------------------------------------------------------------------------- /src/components/common/code-editor/props.js: -------------------------------------------------------------------------------- 1 | export default { 2 | mode: { 3 | type: String, 4 | default: '' 5 | }, 6 | focus: { 7 | type: Boolean, 8 | default: false 9 | }, 10 | theme: { 11 | type: String, 12 | default: 'tomorrow' 13 | }, 14 | orientation: { 15 | type: String, 16 | default: 'beside' 17 | }, 18 | splits: { 19 | type: Number, 20 | default: 2 21 | }, 22 | name: { 23 | type: String, 24 | default: 'brace-editor' 25 | }, 26 | className: { 27 | type: String 28 | }, 29 | height: { 30 | type: String, 31 | default: '500px' 32 | }, 33 | width: { 34 | type: String, 35 | default: '100%' 36 | }, 37 | fontSize: { 38 | type: [String, Number], 39 | default: 14 40 | }, 41 | showGutter: { 42 | type: Boolean, 43 | default: true 44 | }, 45 | onChange: { 46 | type: Function, 47 | default: null 48 | }, 49 | onCopy: { 50 | type: Function, 51 | default: null 52 | }, 53 | onPaste: { 54 | type: Function, 55 | default: null 56 | }, 57 | onFocus: { 58 | type: Function 59 | }, 60 | onInput: { 61 | type: Function 62 | }, 63 | onBlur: { 64 | type: Function 65 | }, 66 | onScroll: { 67 | type: Function, 68 | default: null 69 | }, 70 | modelValue: { 71 | type: String 72 | }, 73 | onLoad: { 74 | type: Function, 75 | default: null 76 | }, 77 | onSelectionChange: { 78 | type: Function 79 | }, 80 | onCursorChange: { 81 | type: Function 82 | }, 83 | onBeforeLoad: { 84 | type: Function 85 | }, 86 | onValidate: { 87 | type: Function 88 | }, 89 | minLines: { 90 | type: Number, 91 | default: null 92 | }, 93 | maxLines: { 94 | type: Number, 95 | default: null 96 | }, 97 | readOnly: { 98 | type: Boolean, 99 | default: false 100 | }, 101 | highlightActiveLine: { 102 | type: Boolean, 103 | default: true 104 | }, 105 | tabSize: { 106 | type: Number, 107 | default: 2 108 | }, 109 | showPrintMargin: { 110 | type: Boolean, 111 | default: false 112 | }, 113 | cursorStart: { 114 | type: Number, 115 | default: 1 116 | }, 117 | debounceChangePeriod: { 118 | type: Number 119 | }, 120 | editorProps: { 121 | type: Object, 122 | default: function () { 123 | return { $blockScrolling: true }; 124 | } 125 | }, 126 | setOptions: { 127 | type: Object, 128 | default: function () { 129 | return {}; 130 | } 131 | }, 132 | styles: { 133 | type: Object, 134 | default: function () { 135 | return {}; 136 | } 137 | }, 138 | scrollMargin: { 139 | type: Array, 140 | default: function () { 141 | return [0, 0, 0, 0]; 142 | } 143 | }, 144 | annotations: { 145 | type: Array 146 | }, 147 | markers: { 148 | type: Array 149 | }, 150 | keyboardHandler: { 151 | type: String 152 | }, 153 | wrapEnabled: { 154 | type: Boolean, 155 | default: true 156 | }, 157 | enableBasicAutocompletion: { 158 | type: [Boolean, Array], 159 | default: false 160 | }, 161 | enableLiveAutocompletion: { 162 | type: [Boolean, Array], 163 | default: false 164 | }, 165 | commands: { 166 | type: Array 167 | } 168 | }; 169 | -------------------------------------------------------------------------------- /src/components/common/markdown-editor.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 31 | 32 | 70 | -------------------------------------------------------------------------------- /src/components/common/richtext-editor.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 65 | -------------------------------------------------------------------------------- /src/components/common/search-filter.vue: -------------------------------------------------------------------------------- 1 | 30 | 40 | 114 | -------------------------------------------------------------------------------- /src/components/common/sub-menu.vue: -------------------------------------------------------------------------------- 1 | 8 | 13 | 45 | -------------------------------------------------------------------------------- /src/components/common/sys-tabs/index.js: -------------------------------------------------------------------------------- 1 | import SysTabs from './sys-tabs'; 2 | 3 | export default SysTabs; 4 | -------------------------------------------------------------------------------- /src/components/common/sys-tabs/sys-tabs.vue: -------------------------------------------------------------------------------- 1 | 162 | 163 | 188 | 189 | 325 | -------------------------------------------------------------------------------- /src/components/common/sys-tabs/utils.js: -------------------------------------------------------------------------------- 1 | const objEqual = (obj1, obj2) => { 2 | const keysArr1 = Object.keys(obj1); 3 | const keysArr2 = Object.keys(obj2); 4 | if (keysArr1.length !== keysArr2.length) return false; 5 | else if (keysArr1.length === 0 && keysArr2.length === 0) return true; 6 | else return !keysArr1.some(key => obj1[key] != obj2[key]); 7 | }; 8 | 9 | export const isExsit = (obj, list) => { 10 | for (let route of list) { 11 | if (routeEqual(route, obj)) { 12 | return true; 13 | } 14 | } 15 | return false; 16 | }; 17 | 18 | export const showTitle = (item, vm) => { 19 | let { title } = item.meta; 20 | if (!title) return; 21 | return title; 22 | }; 23 | 24 | export const routeEqual = (route1, route2) => { 25 | const params1 = route1.params || {}; 26 | const params2 = route2.params || {}; 27 | const query1 = route1.query || {}; 28 | const query2 = route2.query || {}; 29 | return (route1.name === route2.name) && objEqual(params1, params2) && objEqual(query1, query2); 30 | }; 31 | -------------------------------------------------------------------------------- /src/components/common/upload.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 55 | -------------------------------------------------------------------------------- /src/components/demo-components/account/account-setting.vue: -------------------------------------------------------------------------------- 1 | 6 | 16 | 42 | -------------------------------------------------------------------------------- /src/components/demo-components/account/account.vue: -------------------------------------------------------------------------------- 1 | 5 | 22 | 53 | -------------------------------------------------------------------------------- /src/components/demo-components/account/modules/account-info-edit.vue: -------------------------------------------------------------------------------- 1 | 7 | 120 | 222 | -------------------------------------------------------------------------------- /src/components/demo-components/form/basic.vue: -------------------------------------------------------------------------------- 1 | 3 | 8 | 28 | -------------------------------------------------------------------------------- /src/components/demo-components/form/create.vue: -------------------------------------------------------------------------------- 1 | 3 | 8 | 28 | -------------------------------------------------------------------------------- /src/components/demo-components/icons.vue: -------------------------------------------------------------------------------- 1 | 20 | 38 | 185 | -------------------------------------------------------------------------------- /src/components/demo-components/info/basic.vue: -------------------------------------------------------------------------------- 1 | 3 | 8 | 28 | -------------------------------------------------------------------------------- /src/components/demo-components/info/detail.vue: -------------------------------------------------------------------------------- 1 | 3 | 8 | 28 | -------------------------------------------------------------------------------- /src/components/demo-components/table/basic.vue: -------------------------------------------------------------------------------- 1 | 50 | 130 | -------------------------------------------------------------------------------- /src/components/demo-components/table/detail.vue: -------------------------------------------------------------------------------- 1 | 3 | 8 | 28 | -------------------------------------------------------------------------------- /src/components/demo-components/table/search.vue: -------------------------------------------------------------------------------- 1 | 3 | 23 | 101 | -------------------------------------------------------------------------------- /src/components/error-pages/403.vue: -------------------------------------------------------------------------------- 1 | 8 | 14 | 34 | -------------------------------------------------------------------------------- /src/components/error-pages/404.vue: -------------------------------------------------------------------------------- 1 | 8 | 14 | 34 | -------------------------------------------------------------------------------- /src/components/error-pages/500.vue: -------------------------------------------------------------------------------- 1 | 8 | 14 | 34 | -------------------------------------------------------------------------------- /src/components/home/index.vue: -------------------------------------------------------------------------------- 1 | 33 | 139 | 160 | -------------------------------------------------------------------------------- /src/components/login/index.vue: -------------------------------------------------------------------------------- 1 | 105 | 106 | 127 | 156 | -------------------------------------------------------------------------------- /src/components/management/authorization.vue: -------------------------------------------------------------------------------- 1 | 43 | 95 | 168 | -------------------------------------------------------------------------------- /src/components/management/users.vue: -------------------------------------------------------------------------------- 1 | 6 | 27 | 47 | -------------------------------------------------------------------------------- /src/css/app.less: -------------------------------------------------------------------------------- 1 | @import (less) "~heyui/themes/common.less"; 2 | @import (less) "./overwrite.less"; 3 | @import (less) "./fonts/style.less"; 4 | @import (less) "./frame.less"; 5 | @import (less) "./markdown.less"; 6 | @import (less) "./common.less"; 7 | 8 | 9 | body{ 10 | background: #f3f6f8; 11 | color: rgb(47, 47, 47); 12 | font-weight: 400; 13 | } 14 | 15 | p { 16 | margin: 8px 0; 17 | } 18 | 19 | pre { 20 | white-space: pre-wrap; 21 | } -------------------------------------------------------------------------------- /src/css/common.less: -------------------------------------------------------------------------------- 1 | .font-size(@var, @size) { 2 | .font@{var} { 3 | font-size: @size !important; 4 | } 5 | } 6 | 7 | .font-size(12, 12px); 8 | .font-size(13, 13px); 9 | .font-size(14, 14px); 10 | .font-size(15, 15px); 11 | .font-size(16, 16px); 12 | .font-size(18, 18px); 13 | .font-size(20, 20px); 14 | .font-size(22, 22px); 15 | .font-size(28, 28px); 16 | 17 | .font-bold { 18 | font-weight: bold; 19 | } 20 | 21 | .common-page-tabs-bar { 22 | position: relative; 23 | margin-bottom: 2px; 24 | min-height: 50px; 25 | .h-tabs-default { 26 | min-height: 47px; 27 | } 28 | } 29 | 30 | .common-filter-bar { 31 | padding: 17px 0 8px; 32 | min-height: 66px; 33 | } 34 | 35 | .common-filter-select { 36 | height: 32px; 37 | background: rgba(0, 0, 0, 0.04); 38 | border-radius: 2px; 39 | color: rgba(0, 0, 0, 0.65); 40 | .h-select-value-single, 41 | .h-select-placeholder { 42 | height: 32px; 43 | line-height: 32px; 44 | } 45 | } 46 | 47 | .common-status-filter-tabs { 48 | border: 1px solid fade(@primary-color, 10%); 49 | background-color: fade(@primary-color, 5%); 50 | border-radius: 2px; 51 | 52 | > div { 53 | position: relative; 54 | padding: 20px 22px; 55 | 56 | > p { 57 | margin: 0; 58 | line-height: 22px; 59 | text-align: center; 60 | } 61 | 62 | .name { 63 | font-size: 14px; 64 | color: rgba(0, 0, 0, 0.65); 65 | } 66 | 67 | .code { 68 | color: rgba(0, 0, 0, 0.85); 69 | font-size: 18px; 70 | } 71 | 72 | .bold { 73 | font-weight: bold; 74 | } 75 | 76 | &:after { 77 | content: ''; 78 | border-right: 1px dashed #979797; 79 | position: absolute; 80 | top: 24px; 81 | right: 0; 82 | opacity: 0.3; 83 | bottom: 24px; 84 | } 85 | 86 | &:before { 87 | content: ''; 88 | background: @primary-color; 89 | position: absolute; 90 | height: 0; 91 | bottom: -1px; 92 | left: 22px; 93 | right: 22px; 94 | border-radius: 3px; 95 | transition: 0.3s; 96 | } 97 | 98 | &:hover, 99 | &.h-tabs-selected { 100 | .code, 101 | .name { 102 | color: @primary-color; 103 | } 104 | } 105 | 106 | &.h-tabs-selected { 107 | &:before { 108 | height: 3px; 109 | } 110 | } 111 | } 112 | 113 | &.last-float-right { 114 | > div:nth-last-child(2) { 115 | &:after { 116 | content: none; 117 | } 118 | } 119 | 120 | > div:last-child { 121 | float: right; 122 | 123 | &:after { 124 | content: none; 125 | } 126 | } 127 | } 128 | } 129 | 130 | .common-list-container { 131 | .common-list-item { 132 | padding-top: 14px; 133 | padding-bottom: 14px; 134 | align-items: center; 135 | display: flex; 136 | padding: 12px 0; 137 | border-bottom: @border; 138 | 139 | .common-list-meta { 140 | flex: 1; 141 | } 142 | } 143 | } 144 | 145 | .common-panel-tabs { 146 | border-bottom: 1px solid #eeeeee; 147 | padding: 0 25px; 148 | font-size: 18px; 149 | > .h-tabs-item { 150 | padding: 19px 0px; 151 | + div { 152 | margin-left: 30px; 153 | } 154 | } 155 | } 156 | 157 | .frame-page, 158 | .frame-flex-page { 159 | margin: 30px; 160 | .clearfix; 161 | 162 | &.frame-flex-page { 163 | display: flex; 164 | padding: 20px 0; 165 | } 166 | 167 | .frame-left { 168 | width: 224px; 169 | border-right: @border; 170 | margin-right: -1px; 171 | } 172 | 173 | .frame-main { 174 | flex: 1; 175 | border-left: @border; 176 | padding: 8px 40px; 177 | 178 | .subframe-title { 179 | font-size: 20px; 180 | color: rgba(0, 0, 0, 0.85); 181 | line-height: 28px; 182 | font-weight: 500; 183 | margin-bottom: 12px; 184 | } 185 | } 186 | } 187 | 188 | .error-page { 189 | height: calc(~'100vh - @{layout-header-height} -100px'); 190 | text-align: center; 191 | .background-image { 192 | height: 35vh; 193 | background-size: contain; 194 | background-repeat: no-repeat; 195 | background-position: center; 196 | margin: 18vh auto 50px; 197 | } 198 | p { 199 | font-size: 22px; 200 | color: #3788ee; 201 | margin-bottom: 20vh; 202 | } 203 | } 204 | 205 | ::-webkit-scrollbar { 206 | width: 12px; 207 | height: 12px; 208 | } 209 | 210 | ::-webkit-scrollbar-thumb { 211 | background-color: hsla(0, 0%, 44%, 0.06); 212 | border-radius: 12px; 213 | } 214 | 215 | ::-webkit-scrollbar-thumb:hover { 216 | background-color: @primary-color; 217 | border-radius: 12px; 218 | } 219 | -------------------------------------------------------------------------------- /src/css/fonts/Read Me.txt: -------------------------------------------------------------------------------- 1 | Open *demo.html* to see a list of all the glyphs in your font along with their codes/ligatures. 2 | 3 | To use the generated font in desktop programs, you can install the TTF font. In order to copy the character associated with each icon, refer to the text box at the bottom right corner of each glyph in demo.html. The character inside this text box may be invisible; but it can still be copied. See this guide for more info: https://icomoon.io/#docs/local-fonts 4 | 5 | You won't need any of the files located under the *demo-files* directory when including the generated font in your own projects. 6 | 7 | You can import *selection.json* back to the IcoMoon app using the *Import Icons* button (or via Main Menu → Manage Projects) to retrieve your icon selection. 8 | -------------------------------------------------------------------------------- /src/css/fonts/demo-files/demo.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 0; 3 | margin: 0; 4 | font-family: sans-serif; 5 | font-size: 1em; 6 | line-height: 1.5; 7 | color: #555; 8 | background: #fff; 9 | } 10 | h1 { 11 | font-size: 1.5em; 12 | font-weight: normal; 13 | } 14 | small { 15 | font-size: .66666667em; 16 | } 17 | a { 18 | color: #e74c3c; 19 | text-decoration: none; 20 | } 21 | a:hover, a:focus { 22 | box-shadow: 0 1px #e74c3c; 23 | } 24 | .bshadow0, input { 25 | box-shadow: inset 0 -2px #e7e7e7; 26 | } 27 | input:hover { 28 | box-shadow: inset 0 -2px #ccc; 29 | } 30 | input, fieldset { 31 | font-family: sans-serif; 32 | font-size: 1em; 33 | margin: 0; 34 | padding: 0; 35 | border: 0; 36 | } 37 | input { 38 | color: inherit; 39 | line-height: 1.5; 40 | height: 1.5em; 41 | padding: .25em 0; 42 | } 43 | input:focus { 44 | outline: none; 45 | box-shadow: inset 0 -2px #449fdb; 46 | } 47 | .glyph { 48 | font-size: 16px; 49 | width: 15em; 50 | padding-bottom: 1em; 51 | margin-right: 4em; 52 | margin-bottom: 1em; 53 | float: left; 54 | overflow: hidden; 55 | } 56 | .liga { 57 | width: 80%; 58 | width: calc(100% - 2.5em); 59 | } 60 | .talign-right { 61 | text-align: right; 62 | } 63 | .talign-center { 64 | text-align: center; 65 | } 66 | .bgc1 { 67 | background: #f1f1f1; 68 | } 69 | .fgc1 { 70 | color: #999; 71 | } 72 | .fgc0 { 73 | color: #000; 74 | } 75 | p { 76 | margin-top: 1em; 77 | margin-bottom: 1em; 78 | } 79 | .mvm { 80 | margin-top: .75em; 81 | margin-bottom: .75em; 82 | } 83 | .mtn { 84 | margin-top: 0; 85 | } 86 | .mtl, .mal { 87 | margin-top: 1.5em; 88 | } 89 | .mbl, .mal { 90 | margin-bottom: 1.5em; 91 | } 92 | .mal, .mhl { 93 | margin-left: 1.5em; 94 | margin-right: 1.5em; 95 | } 96 | .mhmm { 97 | margin-left: 1em; 98 | margin-right: 1em; 99 | } 100 | .mls { 101 | margin-left: .25em; 102 | } 103 | .ptl { 104 | padding-top: 1.5em; 105 | } 106 | .pbs, .pvs { 107 | padding-bottom: .25em; 108 | } 109 | .pvs, .pts { 110 | padding-top: .25em; 111 | } 112 | .unit { 113 | float: left; 114 | } 115 | .unitRight { 116 | float: right; 117 | } 118 | .size1of2 { 119 | width: 50%; 120 | } 121 | .size1of1 { 122 | width: 100%; 123 | } 124 | .clearfix:before, .clearfix:after { 125 | content: " "; 126 | display: table; 127 | } 128 | .clearfix:after { 129 | clear: both; 130 | } 131 | .hidden-true { 132 | display: none; 133 | } 134 | .textbox0 { 135 | width: 3em; 136 | background: #f1f1f1; 137 | padding: .25em .5em; 138 | line-height: 1.5; 139 | height: 1.5em; 140 | } 141 | #testDrive { 142 | display: block; 143 | padding-top: 24px; 144 | line-height: 1.5; 145 | } 146 | .fs0 { 147 | font-size: 16px; 148 | } 149 | .fs1 { 150 | font-size: 32px; 151 | } 152 | 153 | -------------------------------------------------------------------------------- /src/css/fonts/demo-files/demo.js: -------------------------------------------------------------------------------- 1 | if (!('boxShadow' in document.body.style)) { 2 | document.body.setAttribute('class', 'noBoxShadow'); 3 | } 4 | 5 | document.body.addEventListener('click', function (e) { 6 | var target = e.target; 7 | if (target.tagName === 'INPUT' && 8 | target.getAttribute('class').indexOf('liga') === -1) { 9 | target.select(); 10 | } 11 | }); 12 | 13 | (function () { 14 | var fontSize = document.getElementById('fontSize'); 15 | var testDrive = document.getElementById('testDrive'); 16 | var testText = document.getElementById('testText'); 17 | function updateTest() { 18 | testDrive.innerHTML = testText.value || String.fromCharCode(160); 19 | if (window.icomoonLiga) { 20 | window.icomoonLiga(testDrive); 21 | } 22 | } 23 | function updateSize() { 24 | testDrive.style.fontSize = fontSize.value + 'px'; 25 | } 26 | fontSize.addEventListener('change', updateSize, false); 27 | testText.addEventListener('input', updateTest, false); 28 | testText.addEventListener('change', updateTest, false); 29 | updateSize(); 30 | }()); 31 | -------------------------------------------------------------------------------- /src/css/fonts/fonts/heyuiadmin.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyui/heyui-admin/a5f5dad31b4e8f0793379f73559096dc98648168/src/css/fonts/fonts/heyuiadmin.eot -------------------------------------------------------------------------------- /src/css/fonts/fonts/heyuiadmin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyui/heyui-admin/a5f5dad31b4e8f0793379f73559096dc98648168/src/css/fonts/fonts/heyuiadmin.ttf -------------------------------------------------------------------------------- /src/css/fonts/fonts/heyuiadmin.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyui/heyui-admin/a5f5dad31b4e8f0793379f73559096dc98648168/src/css/fonts/fonts/heyuiadmin.woff -------------------------------------------------------------------------------- /src/css/fonts/style.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'heyuiadmin'; 3 | src: url('fonts/heyuiadmin.eot?minjmi'); 4 | src: url('fonts/heyuiadmin.eot?minjmi#iefix') format('embedded-opentype'), 5 | url('fonts/heyuiadmin.ttf?minjmi') format('truetype'), 6 | url('fonts/heyuiadmin.woff?minjmi') format('woff'), 7 | url('fonts/heyuiadmin.svg?minjmi#heyuiadmin') format('svg'); 8 | font-weight: normal; 9 | font-style: normal; 10 | } 11 | 12 | [class^="icon-"], [class*=" icon-"] { 13 | /* use !important to prevent issues with browser extensions that change fonts */ 14 | font-family: 'heyuiadmin' !important; 15 | speak: none; 16 | font-style: normal; 17 | font-weight: normal; 18 | font-variant: normal; 19 | text-transform: none; 20 | line-height: 1; 21 | 22 | /* Better Font Rendering =========== */ 23 | -webkit-font-smoothing: antialiased; 24 | -moz-osx-font-smoothing: grayscale; 25 | } 26 | 27 | .icon-eye:before { 28 | content: "\e000"; 29 | } 30 | .icon-paper-clip:before { 31 | content: "\e001"; 32 | } 33 | .icon-mail:before { 34 | content: "\e002"; 35 | } 36 | .icon-toggle:before { 37 | content: "\e003"; 38 | } 39 | .icon-layout:before { 40 | content: "\e004"; 41 | } 42 | .icon-link:before { 43 | content: "\e005"; 44 | } 45 | .icon-bell:before { 46 | content: "\e006"; 47 | } 48 | .icon-lock:before { 49 | content: "\e007"; 50 | } 51 | .icon-unlock:before { 52 | content: "\e008"; 53 | } 54 | .icon-ribbon:before { 55 | content: "\e009"; 56 | } 57 | .icon-image:before { 58 | content: "\e010"; 59 | } 60 | .icon-signal:before { 61 | content: "\e011"; 62 | } 63 | .icon-target:before { 64 | content: "\e012"; 65 | } 66 | .icon-clipboard:before { 67 | content: "\e013"; 68 | } 69 | .icon-clock:before { 70 | content: "\e014"; 71 | } 72 | .icon-watch:before { 73 | content: "\e015"; 74 | } 75 | .icon-air-play:before { 76 | content: "\e016"; 77 | } 78 | .icon-camera:before { 79 | content: "\e017"; 80 | } 81 | .icon-video:before { 82 | content: "\e018"; 83 | } 84 | .icon-disc:before { 85 | content: "\e019"; 86 | } 87 | .icon-printer:before { 88 | content: "\e020"; 89 | } 90 | .icon-monitor:before { 91 | content: "\e021"; 92 | } 93 | .icon-server:before { 94 | content: "\e022"; 95 | } 96 | .icon-cog:before { 97 | content: "\e023"; 98 | } 99 | .icon-heart:before { 100 | content: "\e024"; 101 | } 102 | .icon-paragraph:before { 103 | content: "\e025"; 104 | } 105 | .icon-align-justify:before { 106 | content: "\e026"; 107 | } 108 | .icon-align-left:before { 109 | content: "\e027"; 110 | } 111 | .icon-align-center:before { 112 | content: "\e028"; 113 | } 114 | .icon-align-right:before { 115 | content: "\e029"; 116 | } 117 | .icon-book:before { 118 | content: "\e030"; 119 | } 120 | .icon-layers:before { 121 | content: "\e031"; 122 | } 123 | .icon-stack:before { 124 | content: "\e032"; 125 | } 126 | .icon-stack-2:before { 127 | content: "\e033"; 128 | } 129 | .icon-paper:before { 130 | content: "\e034"; 131 | } 132 | .icon-paper-stack:before { 133 | content: "\e035"; 134 | } 135 | .icon-search:before { 136 | content: "\e036"; 137 | } 138 | .icon-zoom-in:before { 139 | content: "\e037"; 140 | } 141 | .icon-zoom-out:before { 142 | content: "\e038"; 143 | } 144 | .icon-reply:before { 145 | content: "\e039"; 146 | } 147 | .icon-circle-plus:before { 148 | content: "\e040"; 149 | } 150 | .icon-circle-minus:before { 151 | content: "\e041"; 152 | } 153 | .icon-circle-check:before { 154 | content: "\e042"; 155 | } 156 | .icon-circle-cross:before { 157 | content: "\e043"; 158 | } 159 | .icon-square-plus:before { 160 | content: "\e044"; 161 | } 162 | .icon-square-minus:before { 163 | content: "\e045"; 164 | } 165 | .icon-square-check:before { 166 | content: "\e046"; 167 | } 168 | .icon-square-cross:before { 169 | content: "\e047"; 170 | } 171 | .icon-microphone:before { 172 | content: "\e048"; 173 | } 174 | .icon-record:before { 175 | content: "\e049"; 176 | } 177 | .icon-skip-back:before { 178 | content: "\e050"; 179 | } 180 | .icon-rewind:before { 181 | content: "\e051"; 182 | } 183 | .icon-play:before { 184 | content: "\e052"; 185 | } 186 | .icon-pause:before { 187 | content: "\e053"; 188 | } 189 | .icon-stop:before { 190 | content: "\e054"; 191 | } 192 | .icon-fast-forward:before { 193 | content: "\e055"; 194 | } 195 | .icon-skip-forward:before { 196 | content: "\e056"; 197 | } 198 | .icon-shuffle:before { 199 | content: "\e057"; 200 | } 201 | .icon-repeat:before { 202 | content: "\e058"; 203 | } 204 | .icon-folder:before { 205 | content: "\e059"; 206 | } 207 | .icon-umbrella:before { 208 | content: "\e060"; 209 | } 210 | .icon-moon:before { 211 | content: "\e061"; 212 | } 213 | .icon-thermometer:before { 214 | content: "\e062"; 215 | } 216 | .icon-drop:before { 217 | content: "\e063"; 218 | } 219 | .icon-sun:before { 220 | content: "\e064"; 221 | } 222 | .icon-cloud:before { 223 | content: "\e065"; 224 | } 225 | .icon-cloud-upload:before { 226 | content: "\e066"; 227 | } 228 | .icon-cloud-download:before { 229 | content: "\e067"; 230 | } 231 | .icon-upload:before { 232 | content: "\e068"; 233 | } 234 | .icon-download:before { 235 | content: "\e069"; 236 | } 237 | .icon-location:before { 238 | content: "\e070"; 239 | } 240 | .icon-location-2:before { 241 | content: "\e071"; 242 | } 243 | .icon-map:before { 244 | content: "\e072"; 245 | } 246 | .icon-battery:before { 247 | content: "\e073"; 248 | } 249 | .icon-head:before { 250 | content: "\e074"; 251 | } 252 | .icon-briefcase:before { 253 | content: "\e075"; 254 | } 255 | .icon-speech-bubble:before { 256 | content: "\e076"; 257 | } 258 | .icon-anchor:before { 259 | content: "\e077"; 260 | } 261 | .icon-globe:before { 262 | content: "\e078"; 263 | } 264 | .icon-box:before { 265 | content: "\e079"; 266 | } 267 | .icon-reload:before { 268 | content: "\e080"; 269 | } 270 | .icon-share:before { 271 | content: "\e081"; 272 | } 273 | .icon-marquee:before { 274 | content: "\e082"; 275 | } 276 | .icon-marquee-plus:before { 277 | content: "\e083"; 278 | } 279 | .icon-marquee-minus:before { 280 | content: "\e084"; 281 | } 282 | .icon-tag:before { 283 | content: "\e085"; 284 | } 285 | .icon-power:before { 286 | content: "\e086"; 287 | } 288 | .icon-command:before { 289 | content: "\e087"; 290 | } 291 | .icon-alt:before { 292 | content: "\e088"; 293 | } 294 | .icon-esc:before { 295 | content: "\e089"; 296 | } 297 | .icon-bar-graph:before { 298 | content: "\e090"; 299 | } 300 | .icon-bar-graph-2:before { 301 | content: "\e091"; 302 | } 303 | .icon-pie-graph:before { 304 | content: "\e092"; 305 | } 306 | .icon-star:before { 307 | content: "\e093"; 308 | } 309 | .icon-arrow-left:before { 310 | content: "\e094"; 311 | } 312 | .icon-arrow-right:before { 313 | content: "\e095"; 314 | } 315 | .icon-arrow-up:before { 316 | content: "\e096"; 317 | } 318 | .icon-arrow-down:before { 319 | content: "\e097"; 320 | } 321 | .icon-volume:before { 322 | content: "\e098"; 323 | } 324 | .icon-mute:before { 325 | content: "\e099"; 326 | } 327 | .icon-content-right:before { 328 | content: "\e100"; 329 | } 330 | .icon-content-left:before { 331 | content: "\e101"; 332 | } 333 | .icon-grid:before { 334 | content: "\e102"; 335 | } 336 | .icon-grid-2:before { 337 | content: "\e103"; 338 | } 339 | .icon-columns:before { 340 | content: "\e104"; 341 | } 342 | .icon-loader:before { 343 | content: "\e105"; 344 | } 345 | .icon-bag:before { 346 | content: "\e106"; 347 | } 348 | .icon-ban:before { 349 | content: "\e107"; 350 | } 351 | .icon-flag:before { 352 | content: "\e108"; 353 | } 354 | .icon-trash:before { 355 | content: "\e109"; 356 | } 357 | .icon-expand:before { 358 | content: "\e110"; 359 | } 360 | .icon-contract:before { 361 | content: "\e111"; 362 | } 363 | .icon-maximize:before { 364 | content: "\e112"; 365 | } 366 | .icon-minimize:before { 367 | content: "\e113"; 368 | } 369 | .icon-plus:before { 370 | content: "\e114"; 371 | } 372 | .icon-minus:before { 373 | content: "\e115"; 374 | } 375 | .icon-check:before { 376 | content: "\e116"; 377 | } 378 | .icon-cross:before { 379 | content: "\e117"; 380 | } 381 | .icon-move:before { 382 | content: "\e118"; 383 | } 384 | .icon-delete:before { 385 | content: "\e119"; 386 | } 387 | .icon-menu:before { 388 | content: "\e120"; 389 | } 390 | .icon-archive:before { 391 | content: "\e121"; 392 | } 393 | .icon-inbox:before { 394 | content: "\e122"; 395 | } 396 | .icon-outbox:before { 397 | content: "\e123"; 398 | } 399 | .icon-file:before { 400 | content: "\e124"; 401 | } 402 | .icon-file-add:before { 403 | content: "\e125"; 404 | } 405 | .icon-file-subtract:before { 406 | content: "\e126"; 407 | } 408 | .icon-help:before { 409 | content: "\e127"; 410 | } 411 | .icon-open:before { 412 | content: "\e128"; 413 | } 414 | .icon-ellipsis:before { 415 | content: "\e129"; 416 | } 417 | -------------------------------------------------------------------------------- /src/css/fonts/variables.less: -------------------------------------------------------------------------------- 1 | @icomoon-font-family: "heyuiadmin"; 2 | @icomoon-font-path: "fonts"; 3 | 4 | @icon-eye: "\e000"; 5 | @icon-paper-clip: "\e001"; 6 | @icon-mail: "\e002"; 7 | @icon-toggle: "\e003"; 8 | @icon-layout: "\e004"; 9 | @icon-link: "\e005"; 10 | @icon-bell: "\e006"; 11 | @icon-lock: "\e007"; 12 | @icon-unlock: "\e008"; 13 | @icon-ribbon: "\e009"; 14 | @icon-image: "\e010"; 15 | @icon-signal: "\e011"; 16 | @icon-target: "\e012"; 17 | @icon-clipboard: "\e013"; 18 | @icon-clock: "\e014"; 19 | @icon-watch: "\e015"; 20 | @icon-air-play: "\e016"; 21 | @icon-camera: "\e017"; 22 | @icon-video: "\e018"; 23 | @icon-disc: "\e019"; 24 | @icon-printer: "\e020"; 25 | @icon-monitor: "\e021"; 26 | @icon-server: "\e022"; 27 | @icon-cog: "\e023"; 28 | @icon-heart: "\e024"; 29 | @icon-paragraph: "\e025"; 30 | @icon-align-justify: "\e026"; 31 | @icon-align-left: "\e027"; 32 | @icon-align-center: "\e028"; 33 | @icon-align-right: "\e029"; 34 | @icon-book: "\e030"; 35 | @icon-layers: "\e031"; 36 | @icon-stack: "\e032"; 37 | @icon-stack-2: "\e033"; 38 | @icon-paper: "\e034"; 39 | @icon-paper-stack: "\e035"; 40 | @icon-search: "\e036"; 41 | @icon-zoom-in: "\e037"; 42 | @icon-zoom-out: "\e038"; 43 | @icon-reply: "\e039"; 44 | @icon-circle-plus: "\e040"; 45 | @icon-circle-minus: "\e041"; 46 | @icon-circle-check: "\e042"; 47 | @icon-circle-cross: "\e043"; 48 | @icon-square-plus: "\e044"; 49 | @icon-square-minus: "\e045"; 50 | @icon-square-check: "\e046"; 51 | @icon-square-cross: "\e047"; 52 | @icon-microphone: "\e048"; 53 | @icon-record: "\e049"; 54 | @icon-skip-back: "\e050"; 55 | @icon-rewind: "\e051"; 56 | @icon-play: "\e052"; 57 | @icon-pause: "\e053"; 58 | @icon-stop: "\e054"; 59 | @icon-fast-forward: "\e055"; 60 | @icon-skip-forward: "\e056"; 61 | @icon-shuffle: "\e057"; 62 | @icon-repeat: "\e058"; 63 | @icon-folder: "\e059"; 64 | @icon-umbrella: "\e060"; 65 | @icon-moon: "\e061"; 66 | @icon-thermometer: "\e062"; 67 | @icon-drop: "\e063"; 68 | @icon-sun: "\e064"; 69 | @icon-cloud: "\e065"; 70 | @icon-cloud-upload: "\e066"; 71 | @icon-cloud-download: "\e067"; 72 | @icon-upload: "\e068"; 73 | @icon-download: "\e069"; 74 | @icon-location: "\e070"; 75 | @icon-location-2: "\e071"; 76 | @icon-map: "\e072"; 77 | @icon-battery: "\e073"; 78 | @icon-head: "\e074"; 79 | @icon-briefcase: "\e075"; 80 | @icon-speech-bubble: "\e076"; 81 | @icon-anchor: "\e077"; 82 | @icon-globe: "\e078"; 83 | @icon-box: "\e079"; 84 | @icon-reload: "\e080"; 85 | @icon-share: "\e081"; 86 | @icon-marquee: "\e082"; 87 | @icon-marquee-plus: "\e083"; 88 | @icon-marquee-minus: "\e084"; 89 | @icon-tag: "\e085"; 90 | @icon-power: "\e086"; 91 | @icon-command: "\e087"; 92 | @icon-alt: "\e088"; 93 | @icon-esc: "\e089"; 94 | @icon-bar-graph: "\e090"; 95 | @icon-bar-graph-2: "\e091"; 96 | @icon-pie-graph: "\e092"; 97 | @icon-star: "\e093"; 98 | @icon-arrow-left: "\e094"; 99 | @icon-arrow-right: "\e095"; 100 | @icon-arrow-up: "\e096"; 101 | @icon-arrow-down: "\e097"; 102 | @icon-volume: "\e098"; 103 | @icon-mute: "\e099"; 104 | @icon-content-right: "\e100"; 105 | @icon-content-left: "\e101"; 106 | @icon-grid: "\e102"; 107 | @icon-grid-2: "\e103"; 108 | @icon-columns: "\e104"; 109 | @icon-loader: "\e105"; 110 | @icon-bag: "\e106"; 111 | @icon-ban: "\e107"; 112 | @icon-flag: "\e108"; 113 | @icon-trash: "\e109"; 114 | @icon-expand: "\e110"; 115 | @icon-contract: "\e111"; 116 | @icon-maximize: "\e112"; 117 | @icon-minimize: "\e113"; 118 | @icon-plus: "\e114"; 119 | @icon-minus: "\e115"; 120 | @icon-check: "\e116"; 121 | @icon-cross: "\e117"; 122 | @icon-move: "\e118"; 123 | @icon-delete: "\e119"; 124 | @icon-menu: "\e120"; 125 | @icon-archive: "\e121"; 126 | @icon-inbox: "\e122"; 127 | @icon-outbox: "\e123"; 128 | @icon-file: "\e124"; 129 | @icon-file-add: "\e125"; 130 | @icon-file-subtract: "\e126"; 131 | @icon-help: "\e127"; 132 | @icon-open: "\e128"; 133 | @icon-ellipsis: "\e129"; 134 | 135 | -------------------------------------------------------------------------------- /src/css/frame.less: -------------------------------------------------------------------------------- 1 | @frame-box-shadow: rgba(0, 21, 41, 0.08); 2 | 3 | #app { 4 | .app-frame { 5 | min-height: 100vh; 6 | } 7 | 8 | .h-layout-sider { 9 | z-index: 2; 10 | box-shadow: 0 1px 4px @frame-box-shadow; 11 | } 12 | .h-layout-header { 13 | overflow: hidden; 14 | box-shadow: 0px 1px 4px 0 @frame-box-shadow; 15 | } 16 | 17 | .h-layout-sider-collapsed { 18 | .app-logo { 19 | padding-left: 5px; 20 | } 21 | .h-layout-header-fixed { 22 | .sys-tabs-vue { 23 | left: @layout-sider-collapse-width; 24 | } 25 | } 26 | } 27 | 28 | .h-layout-header-fixed { 29 | .sys-tabs-vue { 30 | position: fixed; 31 | top: @layout-header-height; 32 | right: 0; 33 | z-index: 2; 34 | left: @layout-sider-width; 35 | } 36 | .sys-tabs-vue + .h-layout-content { 37 | margin-top: @sys-tabs-height; 38 | } 39 | } 40 | .h-layout-sider-fixed .h-layout-header-fixed { 41 | .h-layout-content { 42 | overflow: auto; 43 | height: calc(~'100vh - @{layout-header-height}'); 44 | } 45 | .sys-tabs-vue + .h-layout-content { 46 | height: calc(~'100vh - @{layout-header-height} - @{sys-tabs-height}'); 47 | } 48 | } 49 | 50 | .h-layout-sider-theme-dark .app-logo a { 51 | color: #fff; 52 | } 53 | } 54 | 55 | @media (max-width: 900px) { 56 | #app { 57 | .app-header-info { 58 | .h-autocomplete, 59 | .app-header-icon-item { 60 | display: none; 61 | } 62 | } 63 | .h-layout { 64 | padding-left: 0; 65 | .app-menu-mask { 66 | position: fixed; 67 | left: @layout-sider-width; 68 | right: 0; 69 | top: 0; 70 | bottom: 0; 71 | background: rgba(0, 0, 0, 0.2); 72 | z-index: 1; 73 | } 74 | &.h-layout-sider-collapsed { 75 | > .h-layout-sider { 76 | transform: translateX(-@layout-sider-collapse-width); 77 | overflow: hidden; 78 | } 79 | .app-menu-mask { 80 | display: none; 81 | } 82 | } 83 | } 84 | .h-layout-content { 85 | -webkit-overflow-scrolling: touch; 86 | } 87 | .h-layout-header-fixed .h-layout-header { 88 | left: 0 !important; 89 | } 90 | .sys-tabs-vue { 91 | left: 0 !important; 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/css/markdown.less: -------------------------------------------------------------------------------- 1 | .markdown-info-show { 2 | li { 3 | list-style: disc; 4 | } 5 | 6 | h1, 7 | h2, 8 | h3, 9 | h4 { 10 | color: #111111; 11 | font-weight: 400; 12 | margin-top: 1em; 13 | } 14 | 15 | h1, 16 | h2, 17 | h3, 18 | h4, 19 | h5, 20 | p, 21 | dl { 22 | margin-bottom: 16px; 23 | padding: 0; 24 | } 25 | 26 | h1 { 27 | font-size: 38px; 28 | line-height: 54px; 29 | } 30 | 31 | h2 { 32 | font-size: 30px; 33 | line-height: 42px; 34 | } 35 | 36 | h1, 37 | h2 { 38 | border-bottom: 1px solid #EFEAEA; 39 | padding-bottom: 10px; 40 | } 41 | 42 | h3 { 43 | font-size: 24px; 44 | line-height: 30px; 45 | } 46 | 47 | h4 { 48 | font-size: 21px; 49 | line-height: 26px; 50 | } 51 | 52 | h5 { 53 | font-size: 18px; 54 | list-style: 23px; 55 | } 56 | 57 | a { 58 | color: #0099ff; 59 | margin: 0; 60 | padding: 0; 61 | vertical-align: baseline; 62 | } 63 | 64 | a:hover { 65 | text-decoration: none; 66 | color: #ff6600; 67 | } 68 | 69 | a:visited { 70 | /*color: purple;*/ 71 | } 72 | 73 | ul, 74 | ol { 75 | padding: 0; 76 | padding-left: 24px; 77 | margin: 0; 78 | } 79 | 80 | li { 81 | line-height: 24px; 82 | } 83 | 84 | p, 85 | ul, 86 | ol { 87 | font-size: 16px; 88 | line-height: 24px; 89 | } 90 | 91 | ol ol, 92 | ul ol { 93 | list-style-type: lower-roman; 94 | } 95 | 96 | code, 97 | pre { 98 | border-radius: 3px; 99 | background-color: #f7f7f7; 100 | color: inherit; 101 | } 102 | 103 | code { 104 | font-family: Consolas, Monaco, Andale Mono, monospace; 105 | margin: 0 2px; 106 | } 107 | 108 | pre { 109 | line-height: 1.7em; 110 | overflow: auto; 111 | padding: 6px 10px; 112 | border-left: 5px solid @primary-color; 113 | } 114 | 115 | pre>code { 116 | border: 0; 117 | display: inline; 118 | max-width: initial; 119 | padding: 0; 120 | margin: 0; 121 | overflow: initial; 122 | line-height: inherit; 123 | font-size: .85em; 124 | white-space: pre; 125 | background: 0 0; 126 | 127 | } 128 | 129 | code { 130 | color: #666555; 131 | } 132 | 133 | aside { 134 | display: block; 135 | float: right; 136 | width: 390px; 137 | } 138 | 139 | blockquote { 140 | border-left: .5em solid #eee; 141 | padding: 0 0 0 2em; 142 | margin-left: 0; 143 | } 144 | 145 | blockquote cite { 146 | font-size: 14px; 147 | line-height: 20px; 148 | color: #bfbfbf; 149 | } 150 | 151 | blockquote cite:before { 152 | content: '\2014 \00A0'; 153 | } 154 | 155 | blockquote p { 156 | color: #666; 157 | } 158 | 159 | hr { 160 | text-align: left; 161 | color: #999; 162 | height: 2px; 163 | padding: 0; 164 | margin: 16px 0; 165 | background-color: #e7e7e7; 166 | border: 0 none; 167 | } 168 | 169 | dl { 170 | padding: 0; 171 | } 172 | 173 | dl dt { 174 | padding: 10px 0; 175 | margin-top: 16px; 176 | font-size: 1em; 177 | font-style: italic; 178 | font-weight: bold; 179 | } 180 | 181 | dl dd { 182 | padding: 0 16px; 183 | margin-bottom: 16px; 184 | } 185 | 186 | dd { 187 | margin-left: 0; 188 | } 189 | } -------------------------------------------------------------------------------- /src/css/overwrite.less: -------------------------------------------------------------------------------- 1 | .h-panel { 2 | border: none; 3 | &-title { 4 | color: @dark-color; 5 | } 6 | &-bar { 7 | padding: 15px 25px; 8 | } 9 | &-tabs-bar { 10 | .h-tabs-default > .h-tabs-item { 11 | padding: 16px 15px; 12 | font-size: 18px; 13 | } 14 | } 15 | &-bar-s { 16 | padding-top: 8px; 17 | padding-bottom: 8px; 18 | .h-panel-title { 19 | font-size: 15px; 20 | } 21 | } 22 | &-body { 23 | padding: 25px; 24 | } 25 | } 26 | 27 | .h-menu-white .h-menu-li .h-menu-li-selected { 28 | background-color: #f0f6ff; 29 | } 30 | 31 | .h-table { 32 | td, th { 33 | padding: 10px 0 10px 16px; 34 | height: 48px; 35 | } 36 | } -------------------------------------------------------------------------------- /src/css/richtext-editor.less: -------------------------------------------------------------------------------- 1 | @import (css) "~wangeditor/release/wangEditor.min.css"; 2 | 3 | .w-e-text-container { 4 | border-radius: 0 0 3px 3px; 5 | border-color: #e4e4e4 !important; 6 | .w-e-panel-container .w-e-panel-tab-content input[type=text] { 7 | height: 30px; 8 | border-radius: 0px; 9 | &:focus { 10 | box-shadow: none; 11 | } 12 | } 13 | } 14 | 15 | .w-e-toolbar { 16 | border-radius: 3px 3px 0 0; 17 | border-color: #e4e4e4 !important; 18 | } -------------------------------------------------------------------------------- /src/css/var.js: -------------------------------------------------------------------------------- 1 | const vars = require('heyui/themes/var.js'); 2 | Object.assign(vars, { 3 | 'primary-color': '#3788ee', 4 | 'link-color': '#3788ee', 5 | 'blue-color': '#2d7bf4', 6 | 'green-color': '#0acf97', 7 | 'yellow-color': '#f9bc0b', 8 | 'red-color': '#f1556c', 9 | 'hover-background-color': '#f8f8f8', 10 | 'input-height': '32px', 11 | 'layout-header-height': '60px', 12 | 'layout-sider-width': '240px', 13 | 'layout-sider-collapse-width': '70px', 14 | 'menu-dark-color': '#001529', 15 | 'menu-white-background-color': '#ecf8f2', 16 | 'sys-tabs-height': '50px' 17 | }); 18 | module.exports = vars; 19 | -------------------------------------------------------------------------------- /src/css/var.less: -------------------------------------------------------------------------------- 1 | @import (less) '~/heyui/themes/var.less'; 2 | 3 | @primary-color: #3788ee; 4 | @red-color: #f1556c; 5 | @green-color: #0acf97; 6 | @yellow-color: #f9bc0b; 7 | @blue-color: #2d7bf4; 8 | 9 | @input-height: 32px; 10 | 11 | @layout-sider-width: 240px; 12 | @layout-header-height: 60px; 13 | 14 | @menu-dark-color: #001529; 15 | 16 | @sys-tabs-height: 50px; 17 | -------------------------------------------------------------------------------- /src/images/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyui/heyui-admin/a5f5dad31b4e8f0793379f73559096dc98648168/src/images/avatar.png -------------------------------------------------------------------------------- /src/images/error-pages/403.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyui/heyui-admin/a5f5dad31b4e8f0793379f73559096dc98648168/src/images/error-pages/403.png -------------------------------------------------------------------------------- /src/images/error-pages/404.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyui/heyui-admin/a5f5dad31b4e8f0793379f73559096dc98648168/src/images/error-pages/404.png -------------------------------------------------------------------------------- /src/images/error-pages/500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyui/heyui-admin/a5f5dad31b4e8f0793379f73559096dc98648168/src/images/error-pages/500.png -------------------------------------------------------------------------------- /src/images/folders.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyui/heyui-admin/a5f5dad31b4e8f0793379f73559096dc98648168/src/images/folders.png -------------------------------------------------------------------------------- /src/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heyui/heyui-admin/a5f5dad31b4e8f0793379f73559096dc98648168/src/images/logo.png -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | HeyUI Admin管理平台 14 | 15 | 16 |
17 | 20 |
21 | 22 | 35 | 36 | -------------------------------------------------------------------------------- /src/js/common/ajax.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import qs from 'qs'; 3 | import utils from './utils'; 4 | import { message } from 'heyui'; 5 | 6 | const DefaultParam = { repeatable: false }; 7 | 8 | let ajax = { 9 | PREFIX: '/api', 10 | Author: utils.getAuthor() || 'heyui', 11 | requestingApi: new Set(), 12 | extractUrl: function (url) { 13 | return url ? url.split('?')[0] : ''; 14 | }, 15 | isRequesting: function (url) { 16 | let api = this.extractUrl(url); 17 | return this.requestingApi.has(api); 18 | }, 19 | addRequest: function (url) { 20 | let api = this.extractUrl(url); 21 | this.requestingApi.add(api); 22 | }, 23 | deleteRequest: function (url) { 24 | let api = this.extractUrl(url); 25 | this.requestingApi.delete(api); 26 | }, 27 | get: function (url, param, extendParam) { 28 | let params = { 29 | url, 30 | method: 'GET' 31 | }; 32 | if (param) { 33 | ; 34 | params.params = param; 35 | } 36 | return this.ajax(params, extendParam); 37 | }, 38 | post: function (url, param, extendParam) { 39 | var params = { 40 | url, 41 | method: 'POST' 42 | }; 43 | if (param) params.data = qs.stringify(param); 44 | return this.ajax(params, extendParam); 45 | }, 46 | postJson: function (url, paramJson, extendParam) { 47 | return this.ajax({ 48 | url, 49 | method: 'POST', 50 | data: paramJson 51 | }, extendParam); 52 | }, 53 | patchJson: function (url, paramJson, dataType, extendParam) { 54 | return this.ajax({ 55 | url, 56 | method: 'PATCH', 57 | data: paramJson 58 | }, extendParam); 59 | }, 60 | delete: function (url, extendParam) { 61 | return this.ajax({ 62 | url: url, 63 | method: 'DELETE' 64 | }, extendParam); 65 | }, 66 | ajax: function (param, extendParam) { 67 | let params = utils.extend({}, DefaultParam, param, extendParam || {}); 68 | params.crossDomain = params.url.indexOf('http') === 0; 69 | let url = params.url; 70 | if (!params.crossDomain) { 71 | url = params.url = this.PREFIX + params.url; 72 | } 73 | if (params.method != 'GET') { 74 | if (this.isRequesting(url)) { 75 | return new Promise((resolve, reject) => { resolve({ ok: false, msg: '重复请求' }); }); 76 | } 77 | if (params.repeatable === false) { 78 | this.addRequest(url); 79 | } 80 | } 81 | let header = { 82 | author: this.Author, 83 | Authorization: utils.getLocal('token') 84 | }; 85 | let defaultParam = { 86 | headers: header, 87 | responseType: 'json', 88 | validateStatus: function (status) { 89 | return true; 90 | }, 91 | paramsSerializer: (params) => { 92 | return qs.stringify(params, { allowDots: true }); 93 | } 94 | }; 95 | if (params.crossDomain) { 96 | defaultParam.headers = {}; 97 | } 98 | let that = this; 99 | params = utils.extend({}, defaultParam, params); 100 | return new Promise((resolve) => { 101 | return axios.request(params).then((response) => { 102 | that.deleteRequest(params.url); 103 | let data = response.data; 104 | let status = response.status; 105 | // 如果后端统一封装返回,即所有的请求都是200, 错误码由返回结果提供,则使用以下代码获取状态 106 | // if (status == 200) { 107 | // status = data.status; 108 | // } 109 | if (status != 200) { 110 | if (status == 401) { 111 | window.top.location = '/login'; 112 | return; 113 | } 114 | if (status == 500) { 115 | message.error('后台异常'); 116 | } else if (status == 404) { 117 | message.error('请求不存在'); 118 | } else if (status != 200) { 119 | message.error(data._msg || '请求异常'); 120 | } 121 | } 122 | data.ok = data.status == 200; 123 | resolve(data); 124 | }).catch(() => { 125 | that.deleteRequest(params.url); 126 | resolve({ 127 | ok: false 128 | }); 129 | }); 130 | }); 131 | } 132 | }; 133 | export default ajax; 134 | -------------------------------------------------------------------------------- /src/js/common/qiniuUpload.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | const getToken = () => { 4 | return axios.get('https://www.heyui.top/api/uptoken'); 5 | }; 6 | 7 | export const upload = async file => { 8 | const tokenResp = await getToken(); 9 | const formData = new FormData(); 10 | // formData.append('key', file.name); 11 | formData.append('fname', file.name); 12 | formData.append('token', tokenResp.data.uptoken); 13 | formData.append('file', file); 14 | const resp = await axios.post('//upload-z2.qiniup.com', formData, { 15 | headers: { 'Content-Type': 'multipart/form-data' } 16 | }); 17 | return `//www.heyui.top/qiniu/img/${resp.data.key}`; 18 | }; 19 | -------------------------------------------------------------------------------- /src/js/common/request.js: -------------------------------------------------------------------------------- 1 | import Ajax from './ajax'; 2 | 3 | const Request = { 4 | User: { 5 | info() { 6 | return Ajax.get('/account/info'); 7 | } 8 | }, 9 | Dict: { 10 | get() { 11 | return Ajax.get(`/dict`); 12 | } 13 | }, 14 | Home: { 15 | getMessageList() { 16 | return Ajax.get(`/home/messages`); 17 | } 18 | }, 19 | Account: { 20 | menus() { 21 | } 22 | }, 23 | Login: { 24 | login(param) { 25 | return Ajax.postJson('/login', param); 26 | }, 27 | logout(param) { 28 | return Ajax.post('/logout', param); 29 | } 30 | }, 31 | Management: { 32 | users(params) { 33 | return Ajax.get('/management/users', params); 34 | }, 35 | roles(params) { 36 | return Ajax.get('/management/roles', params); 37 | } 38 | } 39 | }; 40 | 41 | export default Request; 42 | -------------------------------------------------------------------------------- /src/js/common/utils.js: -------------------------------------------------------------------------------- 1 | import utils from 'hey-utils'; 2 | 3 | const rclass = /[\t\r\n\f]/g; 4 | 5 | export default utils.extend({}, utils, { 6 | getClass(elem) { 7 | return (elem.getAttribute && elem.getAttribute('class')) || ''; 8 | }, 9 | hasClass(elem, selector) { 10 | let className; 11 | className = ` ${selector} `; 12 | if (elem.nodeType === 1 && (` ${this.getClass(elem)} `) 13 | .replace(rclass, ' ') 14 | .indexOf(className) > -1) { 15 | return true; 16 | } 17 | 18 | return false; 19 | } 20 | }); 21 | -------------------------------------------------------------------------------- /src/js/config/autocomplete-config.js: -------------------------------------------------------------------------------- 1 | import jsonp from 'fetch-jsonp'; 2 | 3 | const loadData = function (filter, callback) { 4 | jsonp(`https://suggest.taobao.com/sug?code=utf-8&q=${filter}`) 5 | .then(response => response.json()) 6 | .then((d) => { 7 | const result = d.result; 8 | const data = []; 9 | result.forEach((r) => { 10 | data.push({ 11 | name: r[0], 12 | id: r[1] 13 | }); 14 | }); 15 | callback(data); 16 | }); 17 | }; 18 | 19 | const baiduLoadData = function (filter, callback) { 20 | jsonp(`http://suggestion.baidu.com/su?wd=${filter}&p=3&cb=callback`, { 21 | jsonpCallbackFunction: 'callback' 22 | }) 23 | .then(response => response.json()) 24 | .then((d) => { 25 | callback(d.s); 26 | }); 27 | }; 28 | 29 | export default function () { 30 | return { 31 | globalSearch: { 32 | loadData: baiduLoadData, 33 | minWord: 0 34 | }, 35 | simple: { 36 | loadData, 37 | keyName: 'id', 38 | titleName: 'name', 39 | minWord: 1 40 | }, 41 | baidu: { 42 | loadData: baiduLoadData, 43 | minWord: 0 44 | }, 45 | company: { 46 | loadData(filter, next) { 47 | let list = []; 48 | for (let i = 0; i < 10; i++) { 49 | list.push({ 50 | id: `${i}`, 51 | name: `${filter}${i}` 52 | }); 53 | } 54 | next(list); 55 | }, 56 | keyName: 'id', 57 | titleName: 'name' 58 | }, 59 | account: { 60 | loadData(filter, next) { 61 | let list = []; 62 | let companyId = this.companyId; 63 | let companyName = this.companyName; 64 | for (let i = 0; i < 10; i++) { 65 | list.push({ 66 | id: `${companyId}-account${i}`, 67 | name: `${companyName}-account${filter}${i}` 68 | }); 69 | } 70 | next(list); 71 | }, 72 | keyName: 'id', 73 | titleName: 'name' 74 | } 75 | }; 76 | }; 77 | -------------------------------------------------------------------------------- /src/js/config/category-config.js: -------------------------------------------------------------------------------- 1 | let list = [ 2 | { id: 1, title: '一级' }, 3 | { id: 2, title: '二级' }, 4 | { id: 3, title: '三级', disabled: true }, 5 | { id: 10, title: '一级-0', parent: '1' }, 6 | { id: 11, title: '一级-1', parent: '1' }, 7 | { id: 12, title: '一级-2', parent: '1' }, 8 | { id: 13, title: '一级-3', parent: '1' }, 9 | { id: 14, title: '一级-4', parent: '1' }, 10 | { id: 101, title: '一级-0-1', parent: '10' }, 11 | { id: 102, title: '一级-0-2', parent: '10' }, 12 | { id: 103, title: '一级-0-3', parent: '10' }, 13 | { id: 20, title: '二级-0', parent: '2' }, 14 | { id: 21, title: '二级-1', parent: '2' }, 15 | { id: 22, title: '二级-2', parent: '2' }, 16 | { id: 23, title: '二级-3', parent: '2' }, 17 | { id: 24, title: '二级-4', parent: '2' }, 18 | { id: 30, title: '三级-0', parent: '3' }, 19 | { id: 31, title: '三级-1', parent: '3' }, 20 | { id: 32, title: '三级-2', parent: '3' }, 21 | { id: 33, title: '三级-3', parent: '3' } 22 | ]; 23 | export default function () { 24 | return { 25 | simple: { 26 | title: '测试', 27 | keyName: 'id', 28 | parentName: 'parent', 29 | titleName: 'title', 30 | dataMode: 'list', 31 | datas() { 32 | return list; 33 | } 34 | } 35 | }; 36 | }; 37 | -------------------------------------------------------------------------------- /src/js/config/demo-components.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | path: '/form', 4 | name: 'Form', 5 | component: () => import('@components/demo-components/form'), 6 | meta: { title: '表单', icon: 'icon-paper' } 7 | }, 8 | { 9 | path: '/form-detail', 10 | name: 'FormDetail', 11 | component: () => import('@components/demo-components/form-detail'), 12 | meta: { title: '表单详情' } 13 | }, 14 | { 15 | path: '/autocomplete1', 16 | name: 'Autocomplete1', 17 | component: () => import('@components/demo-components/autocomplete1'), 18 | meta: { title: '自动补全' } 19 | }, 20 | { 21 | path: '/autocomplete2', 22 | name: 'Autocomplete2', 23 | component: () => import('@components/demo-components/autocomplete2'), 24 | meta: { title: '自动补全2' } 25 | }, 26 | { 27 | path: '/autocomplete3', 28 | name: 'Autocomplete3', 29 | component: () => import('@components/demo-components/autocomplete3'), 30 | meta: { title: '自动补全3' } 31 | }, 32 | { 33 | path: '/icons', 34 | name: 'Icons', 35 | component: () => import('@components/demo-components/icons'), 36 | meta: { title: '图表列表', icon: 'icon-grid' } 37 | }, 38 | { 39 | path: '/form-basic', 40 | name: 'FormBasic', 41 | component: () => import('@components/demo-components/form/basic'), 42 | meta: { title: '基础表单', icon: 'icon-paper' } 43 | }, 44 | { 45 | path: '/form-create', 46 | name: 'FormCreate', 47 | component: () => import('@components/demo-components/form/create'), 48 | meta: { title: '创建表单' } 49 | }, 50 | { 51 | path: '/table-basic', 52 | name: 'TableBasic', 53 | component: () => import('@components/demo-components/table/basic'), 54 | meta: { title: '基础表格' } 55 | }, 56 | { 57 | path: '/table-search', 58 | name: 'TableSearch', 59 | component: () => import('@components/demo-components/table/search'), 60 | meta: { title: '查询表格' } 61 | }, 62 | { 63 | path: '/table-detail', 64 | name: 'TableDetail', 65 | component: () => import('@components/demo-components/table/detail'), 66 | meta: { title: '表格详情' } 67 | }, 68 | { 69 | path: '/account-basic', 70 | name: 'AccountBasic', 71 | component: () => import('@components/demo-components/account/account'), 72 | meta: { title: '个人中心', icon: 'icon-head' } 73 | }, 74 | { 75 | path: '/account-setting/', 76 | name: 'AccountSetting', 77 | component: () => import('@components/demo-components/account/account-setting'), 78 | children: [ 79 | { 80 | path: 'security-setting', 81 | name: 'SecuritySetting', 82 | component: () => import('@components/demo-components/account/modules/security-setting'), 83 | meta: { title: '安全设置' } 84 | }, 85 | { 86 | path: 'notice-setting', 87 | name: 'NoticeSetting', 88 | component: () => import('@components/demo-components/account/modules/notice-setting'), 89 | meta: { title: '通知设置' } 90 | } 91 | ], 92 | meta: { title: '个人设置' } 93 | }, 94 | { 95 | path: '/info-basic', 96 | name: 'InfoBasic', 97 | component: () => import('@components/demo-components/info/basic'), 98 | meta: { title: '基础信息' } 99 | }, 100 | { 101 | path: '/info-detail', 102 | name: 'InfoDetail', 103 | component: () => import('@components/demo-components/info/detail'), 104 | meta: { title: '信息详情' } 105 | }, 106 | { 107 | path: '/address-picker', 108 | name: 'AddressPicker', 109 | component: () => import('@components/demo-components/components/address-picker'), 110 | meta: { title: '地址选择器' } 111 | }, 112 | { 113 | path: '/chart', 114 | name: 'Chart', 115 | component: () => import('@components/demo-components/components/chart'), 116 | meta: { title: '图表' } 117 | }, 118 | { 119 | path: '/code-editor', 120 | name: 'CodeEditor', 121 | component: () => import('@components/demo-components/components/code-editor'), 122 | meta: { title: '代码编辑器' } 123 | }, 124 | { 125 | path: '/markdown-editor', 126 | name: 'MarkdownEditor', 127 | component: () => import('@components/demo-components/components/markdown-editor'), 128 | meta: { title: 'markdown编辑器' } 129 | }, 130 | { 131 | path: '/ricktext-editor', 132 | name: 'RicktextEditor', 133 | component: () => import('@components/demo-components/components/richtext-editor'), 134 | meta: { title: '富文本编辑器' } 135 | }, 136 | { 137 | path: '/baidu-map', 138 | name: 'BaiduMap', 139 | component: () => import('@components/demo-components/components/baidu-map'), 140 | meta: { title: '百度地图' } 141 | } 142 | ]; 143 | -------------------------------------------------------------------------------- /src/js/config/dict-config.js: -------------------------------------------------------------------------------- 1 | const staticDict = function () { 2 | return { 3 | select: [{ title: '选择1', key: 'a1', other: '其他值' }, { title: '选择2', key: 'a2' }, { title: '选择3', key: 'a3' }], 4 | simple: { 1: '苹果', 2: '梨子', 3: '香蕉', 4: '橙子', 5: '樱桃' } 5 | }; 6 | }; 7 | 8 | export default staticDict; 9 | -------------------------------------------------------------------------------- /src/js/config/heyui-config.js: -------------------------------------------------------------------------------- 1 | import dictConfig from './dict-config'; 2 | import autocompleteConfig from './autocomplete-config'; 3 | import treeConfig from './tree-config'; 4 | import categoryConfig from './category-config'; 5 | import { heyuiConfig } from 'heyui'; 6 | 7 | const config = () => { 8 | const staticDict = dictConfig(); 9 | Object.keys(staticDict).forEach((key) => { 10 | heyuiConfig.addDict(key, staticDict[key]); 11 | }); 12 | 13 | heyuiConfig.config('dict.keyName', 'key'); 14 | heyuiConfig.config('dict.titleName', 'title'); 15 | 16 | heyuiConfig.config('autocomplete.configs', autocompleteConfig()); 17 | heyuiConfig.config('tree.configs', treeConfig()); 18 | heyuiConfig.config('category.configs', categoryConfig()); 19 | 20 | heyuiConfig.config('menu', { 21 | keyName: 'key', 22 | titleName: 'title', 23 | childrenName: 'children' 24 | }); 25 | }; 26 | 27 | export default config; 28 | -------------------------------------------------------------------------------- /src/js/config/menu-config.js: -------------------------------------------------------------------------------- 1 | import utils from '@common/utils'; 2 | 3 | const fullMenus = [ 4 | { 5 | title: 'Dashboard', 6 | key: 'Home', 7 | icon: 'icon-monitor', 8 | count: 1 9 | }, 10 | { 11 | title: 'Icons', 12 | key: 'Icons', 13 | icon: 'icon-heart' 14 | }, 15 | { 16 | title: '列表应用', 17 | key: 'TableList', 18 | icon: 'icon-grid-2', 19 | children: [ 20 | { 21 | title: '基础表格', 22 | key: 'TableBasic' 23 | }, 24 | { 25 | title: '查询列表', 26 | key: 'TableSearch' 27 | } 28 | ] 29 | }, 30 | { 31 | title: '表单应用', 32 | key: 'FormFolder', 33 | icon: 'icon-paper', 34 | children: [ 35 | { 36 | title: '基础表单', 37 | key: 'Form' 38 | }, 39 | { 40 | title: '表单详情', 41 | key: 'FormDetail' 42 | } 43 | ] 44 | }, 45 | { 46 | title: '模糊匹配', 47 | key: 'AutoCompleteFolder', 48 | icon: 'icon-disc', 49 | children: [ 50 | { 51 | title: '模糊搜索', 52 | key: 'Autocomplete1' 53 | }, 54 | { 55 | title: '场景应用', 56 | key: 'Autocomplete2' 57 | }, 58 | { 59 | title: '复杂场景', 60 | key: 'Autocomplete3' 61 | } 62 | ] 63 | }, 64 | { 65 | title: '扩展组件', 66 | key: 'Advance-folder', 67 | icon: 'icon-bar-graph-2', 68 | children: [ 69 | { 70 | title: '图表', 71 | key: 'Chart' 72 | }, 73 | { 74 | title: '富文本编辑器', 75 | key: 'RicktextEditor' 76 | }, 77 | { 78 | title: '代码编辑器', 79 | key: 'CodeEditor' 80 | }, 81 | { 82 | title: 'Markdown编辑器', 83 | key: 'MarkdownEditor' 84 | }, 85 | { 86 | title: '百度地图', 87 | key: 'BaiduMap' 88 | } 89 | ] 90 | }, 91 | { 92 | title: '系统设置', 93 | key: 'SysSetting', 94 | icon: 'icon-cog', 95 | children: [ 96 | { 97 | title: '个人中心', 98 | key: 'AccountBasic' 99 | }, 100 | { 101 | title: '安全设置', 102 | key: 'SecuritySetting' 103 | }, 104 | { 105 | title: '权限设置', 106 | key: 'Authorization' 107 | } 108 | ] 109 | }, 110 | { 111 | title: '错误页面', 112 | key: 'ErrorPages', 113 | icon: 'icon-ban', 114 | children: [ 115 | { 116 | title: '系统错误', 117 | key: 'SystemError' 118 | }, 119 | { 120 | title: '权限错误', 121 | key: 'PermissionError' 122 | }, 123 | { 124 | title: '找不到页面', 125 | key: 'NotfoundError' 126 | } 127 | ] 128 | } 129 | ]; 130 | 131 | const getMenus = function (menuIdList = []) { 132 | return getAuthMenu(fullMenus, menuIdList); 133 | }; 134 | 135 | let getAuthMenu = (menus, menuIdList) => { 136 | let configMenu = []; 137 | for (let menu of menus) { 138 | let m = utils.copy(menu); 139 | if (menuIdList.indexOf(m.key) > -1) { 140 | configMenu.push(m); 141 | } 142 | if (menu.children && menu.children.length) { 143 | m.children = getAuthMenu(menu.children, menuIdList); 144 | } 145 | } 146 | return configMenu; 147 | }; 148 | 149 | const getKeys = function (menus) { 150 | let keys = []; 151 | for (let menu of menus) { 152 | keys.push(menu.key); 153 | if (menu.children && menu.children.length) { 154 | keys.push(...getKeys(menu.children)); 155 | } 156 | } 157 | return keys; 158 | }; 159 | 160 | let fullMenuKeys = getKeys(fullMenus); 161 | 162 | const isAuthPage = function (menus, name) { 163 | if (fullMenuKeys.indexOf(name) > -1 && menus.indexOf(name) == -1) { 164 | return false; 165 | } 166 | return true; 167 | }; 168 | 169 | export { getMenus, fullMenus, fullMenuKeys, isAuthPage }; 170 | -------------------------------------------------------------------------------- /src/js/config/router-config.js: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory } from 'vue-router'; 2 | import demoComponents from './demo-components'; 3 | import { loadingBar } from 'heyui'; 4 | 5 | const routeConfig = { 6 | mode: 'history', 7 | routes: [ 8 | { 9 | path: '/login', 10 | name: 'Login', 11 | component: () => import('@components/login/index') 12 | }, 13 | { 14 | path: '/', 15 | component: () => import('@components/app/app-frame'), 16 | children: [ 17 | { 18 | path: '', 19 | name: 'Home', 20 | component: () => import('@components/home/index'), 21 | meta: { title: '首页', icon: 'icon-monitor' } 22 | }, 23 | { 24 | path: '/system-error', 25 | name: 'SystemError', 26 | component: () => import('@components/error-pages/500'), 27 | meta: { title: '系统错误' } 28 | }, 29 | { 30 | path: '/permission-error', 31 | name: 'PermissionError', 32 | component: () => import('@components/error-pages/403'), 33 | meta: { title: '权限错误' } 34 | }, 35 | { 36 | path: '/notfound-error', 37 | name: 'NotfoundError', 38 | component: () => import('@components/error-pages/404'), 39 | meta: { title: '页面找不到' } 40 | }, 41 | { 42 | path: '/authorization', 43 | name: 'Authorization', 44 | component: () => import('@components/management/authorization'), 45 | meta: { title: '权限管理' } 46 | }, 47 | { 48 | path: '/users', 49 | name: 'Users', 50 | component: () => import('@components/management/users'), 51 | meta: { title: '用户管理' } 52 | }, 53 | ...demoComponents, 54 | { 55 | path: '/:pathMatch(.*)*', 56 | name: 'CommonNotfoundError', 57 | component: () => import('@components/error-pages/404'), 58 | meta: { title: '页面找不到' } 59 | } 60 | ] 61 | } 62 | ] 63 | }; 64 | 65 | const router = createRouter({ 66 | history: createWebHistory(), 67 | routes: routeConfig.routes 68 | }); 69 | 70 | let isFirstRouter = true; 71 | 72 | router.beforeEach((to, from, next) => { 73 | loadingBar.start(); 74 | if (to.meta && to.meta.title) { 75 | document.title = to.meta.title + ' - 管理应用'; 76 | } else { 77 | document.title = '管理系统'; 78 | } 79 | isFirstRouter = false; 80 | next(); 81 | }); 82 | 83 | router.afterEach(() => { 84 | loadingBar.success(); 85 | document.documentElement.scrollTop = 0; 86 | document.body.scrollTop = 0; 87 | let layoutContent = document.querySelector('.h-layout-content'); 88 | if (layoutContent) { 89 | layoutContent.scrollTop = 0; 90 | } 91 | // baidu 统计,如果有自己的统计,请至index.html修改至自己的埋点 92 | if (window._hmt) { 93 | window._hmt.push(['_trackPageview', window.location.pathname]); 94 | } 95 | }); 96 | 97 | export default router; 98 | -------------------------------------------------------------------------------- /src/js/config/tree-config.js: -------------------------------------------------------------------------------- 1 | let list = [ 2 | { id: 1, title: '一级' }, 3 | { id: 2, title: '二级' }, 4 | { id: 3, title: '三级', disabled: true }, 5 | { id: 10, title: '一级-0', parent: '1' }, 6 | { id: 11, title: '一级-1', parent: '1' }, 7 | { id: 12, title: '一级-2', parent: '1' }, 8 | { id: 13, title: '一级-3', parent: '1' }, 9 | { id: 14, title: '一级-4', parent: '1' }, 10 | { id: 101, title: '一级-0-1', parent: '10' }, 11 | { id: 102, title: '一级-0-2', parent: '10' }, 12 | { id: 103, title: '一级-0-3', parent: '10' }, 13 | { id: 20, title: '二级-0', parent: '2' }, 14 | { id: 21, title: '二级-1', parent: '2' }, 15 | { id: 22, title: '二级-2', parent: '2' }, 16 | { id: 23, title: '二级-3', parent: '2' }, 17 | { id: 24, title: '二级-4', parent: '2' }, 18 | { id: 30, title: '三级-0', parent: '3' }, 19 | { id: 31, title: '三级-1', parent: '3' }, 20 | { id: 32, title: '三级-2', parent: '3' }, 21 | { id: 33, title: '三级-3', parent: '3' } 22 | ]; 23 | 24 | export default function () { 25 | return { 26 | simple: { 27 | keyName: 'id', 28 | parentName: 'parent', 29 | titleName: 'title', 30 | dataMode: 'list', 31 | datas() { 32 | return list; 33 | } 34 | } 35 | }; 36 | }; 37 | -------------------------------------------------------------------------------- /src/js/model/Form.js: -------------------------------------------------------------------------------- 1 | import Model from 'js-model'; 2 | 3 | export default new Model({ 4 | int: null, 5 | number: null, 6 | url: null, 7 | email: null, 8 | tel: null, 9 | mobile: null, 10 | input: '', 11 | textarea: '测试', 12 | radio: 1, 13 | rate: null, 14 | checkbox: [1], 15 | select1: '人民币', 16 | select2: '', 17 | select3: [], 18 | taginputs: [], 19 | autocomplete: null, 20 | category: null, 21 | money: { 22 | min: null, 23 | max: null 24 | }, 25 | date: null, 26 | inputs: [], 27 | things: [''] 28 | }) 29 | ; 30 | -------------------------------------------------------------------------------- /src/js/model/login/Login.js: -------------------------------------------------------------------------------- 1 | import Model from 'js-model'; 2 | 3 | export default new Model({ 4 | username: '', 5 | password: '' 6 | }); 7 | -------------------------------------------------------------------------------- /src/js/vue/components.js: -------------------------------------------------------------------------------- 1 | import SubMenu from '@components/common/sub-menu'; 2 | import SearchFilter from '@components/common/search-filter'; 3 | import AItem from '@components/common-item/a-item'; 4 | import BItem from '@components/common-item/b-item'; 5 | import Upload from '@components/common/upload'; 6 | import { defineAsyncComponent } from 'vue'; 7 | 8 | export default app => { 9 | app.component('SubMenu', SubMenu); 10 | app.component('AItem', AItem); 11 | app.component('BItem', BItem); 12 | app.component('SearchFilter', SearchFilter); 13 | app.component('Upload', Upload); 14 | app.component( 15 | 'Chart', 16 | defineAsyncComponent(() => import('@components/common/chart')) 17 | ); 18 | app.component( 19 | 'CodeEditor', 20 | defineAsyncComponent(() => import('@components/common/code-editor')) 21 | ); 22 | app.component( 23 | 'RichTextEditor', 24 | defineAsyncComponent(() => import('@components/common/richtext-editor')) 25 | ); 26 | app.component( 27 | 'MarkdownEditor', 28 | defineAsyncComponent(() => import('@components/common/markdown-editor')) 29 | ); 30 | app.component( 31 | 'BaiduMap', 32 | defineAsyncComponent(() => import('@components/common/baidu-map')) 33 | ); 34 | }; 35 | -------------------------------------------------------------------------------- /src/js/vue/directives.js: -------------------------------------------------------------------------------- 1 | 2 | const uriReg = /^((http[s]{0,1}|ftp):\/\/)?[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.?/; 3 | const isUrl = function (value) { 4 | return (value && value.trim() && uriReg.test(value.trim())); 5 | }; 6 | 7 | export default (app) => { 8 | app.directive('url', { 9 | bind() { 10 | if (arguments[1] && arguments[1].value) { 11 | let el = arguments[0]; 12 | let text = arguments[1].value; 13 | let protocol; 14 | let pre = ''; 15 | let aft = ''; 16 | if (isUrl(text)) { 17 | protocol = (text.indexOf('http') != -1 ? '' : 'http://'); 18 | pre = ``; 19 | aft = ``; 20 | } 21 | el.innerHTML = pre + text + aft; 22 | } 23 | } 24 | }); 25 | } -------------------------------------------------------------------------------- /src/js/vue/filters.js: -------------------------------------------------------------------------------- 1 | import manba from 'manba'; 2 | 3 | export default (app) => { 4 | app.config.globalProperties.format = (value, format) => { 5 | if (value) { 6 | return manba(value).format(format || 'l'); 7 | } 8 | return ''; 9 | }; 10 | 11 | app.config.globalProperties.distance = (date) => { 12 | const hours = manba().distance(date, manba.HOUR); 13 | if (hours == 0) { 14 | const mins = manba().distance(date, manba.MINUTE); 15 | return `${mins}分钟`; 16 | } else if (hours < 24) { 17 | return `${hours}小时`; 18 | } else { 19 | const days = manba().distance(date, manba.DAY); 20 | return `${days}天`; 21 | } 22 | }; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /src/js/vuex/store.js: -------------------------------------------------------------------------------- 1 | import { createStore } from 'vuex'; 2 | import { getMenus } from '@js/config/menu-config'; 3 | 4 | export default createStore({ 5 | state: { 6 | user: {}, 7 | msgCount: { 8 | messages: 2 9 | }, 10 | menus: [], 11 | menuKeys: [], 12 | siderCollapsed: false, 13 | pageResizeCount: 0 14 | }, 15 | mutations: { 16 | updateMenus(state, data) { 17 | state.menus = getMenus(data); 18 | state.menuKeys = data; 19 | }, 20 | updateAccount(state, data) { 21 | state.user = data; 22 | }, 23 | updateSiderCollapse(state, isShow) { 24 | setTimeout(() => { 25 | state.pageResizeCount += 1; 26 | }, 600); 27 | state.siderCollapsed = isShow; 28 | }, 29 | updateMsgCount(state, data) { 30 | state.msgCount = data; 31 | } 32 | }, 33 | actions: { 34 | updateMenuKeys({ commit }, data) { 35 | commit('updateMenus', data); 36 | }, 37 | updateAccount({ commit }, data) { 38 | commit('updateAccount', data); 39 | }, 40 | updateSiderCollapse({ commit }, data) { 41 | commit('updateSiderCollapse', data); 42 | }, 43 | updateMsgCount({ commit }, data) { 44 | commit('updateMsgCount', data); 45 | } 46 | }, 47 | getters: { 48 | account: state => { 49 | return state.user; 50 | }, 51 | siderCollapsed: state => { 52 | return state.siderCollapsed; 53 | }, 54 | msgCount: state => { 55 | return state.msgCount; 56 | } 57 | } 58 | }); 59 | -------------------------------------------------------------------------------- /src/mock/index.js: -------------------------------------------------------------------------------- 1 | import users from './users'; 2 | const Mock = require('mockjs'); 3 | 4 | Mock.setup({ 5 | timeout: 0 - 300 6 | }); 7 | 8 | Mock.mock('/api/account/info', 'get', { 9 | status: 200, 10 | body: { 11 | name: 'vvpvvp', 12 | desc: '执着于理想,纯粹于当下', 13 | email: 'heyui@some.com', 14 | org: '某某公司', 15 | dept: '某某部门', 16 | title: '前端开发工程师', 17 | location: '上海市', 18 | tags: [ 19 | '善解人意', 20 | '开朗乐观', 21 | '真诚热情', 22 | '心地善良', 23 | '谦恭有礼', 24 | '彬彬有礼', 25 | '虚怀若谷', 26 | '严于律己', 27 | '雍容大度', 28 | '热情洋溢', 29 | '从容自若', 30 | '诚挚', 31 | '温厚', 32 | '谦让', 33 | '勤恳', 34 | '耿直' 35 | ] 36 | } 37 | }); 38 | 39 | Mock.mock('/api/dict', 'get', { 40 | status: 200, 41 | body: [ 42 | { 43 | name: 'simple', 44 | data: { 45 | 1: '苹果', 46 | 2: '梨子', 47 | 3: '香蕉', 48 | 4: '橙子', 49 | 5: '樱桃' 50 | } 51 | } 52 | ] 53 | }); 54 | 55 | Mock.mock('/api/login', 'post', { 56 | status: 200, 57 | body: { 58 | value: 'test' 59 | } 60 | }); 61 | 62 | Mock.mock('/api/logout', 'post', { 63 | status: 200 64 | }); 65 | 66 | Mock.mock('/api/home/messages', 'get', { 67 | status: 200, 68 | body: [ 69 | { 70 | id: 1, 71 | isReaded: false, 72 | title: '任务名称1', 73 | description: '你需要在某年某月完成某某任务' 74 | }, 75 | { 76 | id: 2, 77 | isReaded: false, 78 | title: '任务名称2', 79 | description: '你需要在某年某月完成某某任务' 80 | }, 81 | { 82 | id: 3, 83 | isReaded: true, 84 | title: '任务名称3', 85 | description: '你需要在某年某月完成某某任务' 86 | }, 87 | { 88 | id: 4, 89 | isReaded: true, 90 | title: '任务名称4', 91 | description: '你需要在某年某月完成某某任务' 92 | }, 93 | { 94 | id: 5, 95 | isReaded: true, 96 | title: '任务名称5', 97 | description: '你需要在某年某月完成某某任务' 98 | } 99 | ] 100 | }); 101 | 102 | Mock.mock('/api/management/users', 'get', { status: 200, body: users }); 103 | 104 | Mock.mock('/api/management/roles', 'get', { 105 | status: 200, 106 | body: [ 107 | { 108 | id: 1, 109 | name: '系统管理员', 110 | description: '最高权限,可操作任何页面和功能' 111 | }, 112 | { 113 | id: 2, 114 | name: '普通员工', 115 | description: '普通员工' 116 | }, 117 | { 118 | id: 3, 119 | name: 'Leader', 120 | description: '可进行团队数据查看,可导出数据' 121 | } 122 | ] 123 | }); 124 | -------------------------------------------------------------------------------- /src/mock/users.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { id: '1', name: '万事屋', parent: '-1' }, 3 | { id: '1.1', name: '坂田银时', parent: '1' }, 4 | { id: '1.2', name: '志村新八', parent: '1' }, 5 | { id: '1.3', name: '神乐', parent: '1' }, 6 | { id: '1.4', name: '定春', parent: '1' }, 7 | { id: '2', name: '真选组', parent: '2' }, 8 | { id: '2.1', name: '近藤勋', parent: '2' }, 9 | { id: '2.2', name: '土方十四郎', parent: '2' }, 10 | { id: '2.3', name: '冲田总悟', parent: '2' }, 11 | { id: '2.4', name: '山崎退', parent: '2' }, 12 | { id: '2.5', name: '伊东鸭太郎', parent: '2' }, 13 | { id: '2.6', name: '松平片栗虎', parent: '2' }, 14 | { id: '2.7', name: '神山', parent: '2' }, 15 | { id: '2.8', name: '未登场的队士们', parent: '2' }, 16 | { id: '3', name: '攘夷志士', parent: '-1' }, 17 | { id: '3.1', name: '桂小太郎', parent: '3' }, 18 | { id: '3.2', name: '伊丽莎白(艾利撒比斯)', parent: '3' }, 19 | { id: '3.3', name: '宫部', parent: '3' }, 20 | { id: '4', name: '私设舰队『快援队』', parent: '-1' }, 21 | { id: '4.1', name: '坂本辰马', parent: '4' }, 22 | { id: '4.2', name: '陆奥', parent: '4' }, 23 | { id: '5', name: '私人武装组织『鬼兵队』', parent: '-1' }, 24 | { id: '5.1', name: '高杉晋助', parent: '5' }, 25 | { id: '5.2', name: '河上万齐', parent: '5' }, 26 | { id: '5.3', name: '冈田似蔵', parent: '5' }, 27 | { id: '5.4', name: '来岛又子', parent: '5' }, 28 | { id: '5.5', name: '武市变平太', parent: '5' }, 29 | { id: '6', name: '宇宙海盗『春雨』', parent: '-1' }, 30 | { id: '6.1', name: '神威', parent: '6' }, 31 | { id: '6.2', name: '阿伏兔', parent: '6' }, 32 | { id: '6.3', name: '云业', parent: '6' }, 33 | { id: '6.4', name: '陀络', parent: '6' }, 34 | { id: '7', name: '歌舞伎町四天王', parent: '-1' }, 35 | { id: '7.1', name: '登势大婶', parent: '7' }, 36 | { id: '7.2', name: '凯萨琳(卡莎莲)', parent: '7' }, 37 | { id: '7.3', name: '玉子', parent: '7' }, 38 | { id: '7.4', name: '孔雀姬华佗', parent: '7' }, 39 | { id: '7.5', name: '西乡特盛', parent: '7' }, 40 | { id: '7.6', name: '侠客泥水次郎长', parent: '7' }, 41 | { id: '7.7', name: '黑驹胜男', parent: '7' }, 42 | { id: '8', name: '其他经常登场的人', parent: '-1' }, 43 | { id: '8.1', name: '吉田松阳', parent: '8' }, 44 | { id: '8.2', name: '志村妙', parent: '8' }, 45 | { id: '8.3', name: '长谷川泰三', parent: '8' }, 46 | { id: '8.4', name: '柳生九兵卫', parent: '8' }, 47 | { id: '8.5', name: '几松', parent: '8' }, 48 | { id: '8.6', name: '寺门通', parent: '8' }, 49 | { id: '8.7', name: '哈达王子(哈打王子)', parent: '8' }, 50 | { id: '8.8', name: '服部全藏', parent: '8' }, 51 | { id: '8.9', name: '猿飞菖蒲', parent: '8' }, 52 | { id: '8.10', name: '屁怒絽', parent: '8' }, 53 | { id: '8.11', name: '星海坊主', parent: '8' }, 54 | { id: '8.12', name: '结野主播', parent: '8' }, 55 | { id: '8.13', name: '花野咲', parent: '8' }, 56 | { id: '9', name: '其他曾经登场的重要人物', parent: '-1' }, 57 | { id: '9.1', name: '才藏', parent: '9' }, 58 | { id: '9.2', name: '阿国', parent: '9' }, 59 | { id: '9.3', name: '冲田三叶', parent: '9' }, 60 | { id: '9.4', name: '德川茂茂', parent: '9' }, 61 | { id: '9.5', name: '月咏', parent: '9' }, 62 | { id: '9.6', name: '日轮', parent: '9' }, 63 | { id: '9.7', name: '晴太', parent: '9' }, 64 | { id: '9.8', name: '白血球', parent: '9' } 65 | ]; 66 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | const globalVars = require('./src/css/var.js'); 4 | 5 | module.exports = { 6 | assetsDir: 'src/images', 7 | pages: { 8 | index: { 9 | entry: 'src/app.js', 10 | template: 'src/index.html', 11 | filename: 'index.html', 12 | chunks: ['chunk-vendors', 'chunk-common', 'index'] 13 | } 14 | }, 15 | css: { 16 | loaderOptions: { 17 | less: { 18 | lessOptions: { globalVars } 19 | } 20 | } 21 | }, 22 | configureWebpack: { 23 | resolve: { 24 | alias: { 25 | '@': path.resolve(__dirname, 'src/'), 26 | '@components': path.resolve(__dirname, 'src/components/'), 27 | '@common': path.resolve(__dirname, 'src/js/common/'), 28 | '@model': path.resolve(__dirname, 'src/js/model/'), 29 | '@js': path.resolve(__dirname, 'src/js/') 30 | } 31 | }, 32 | plugins: [new webpack.ProvidePlugin({})] 33 | }, 34 | devServer: { 35 | // proxy: { 36 | // 此处应该配置为开发服务器的后台地址 37 | // 配置文档: https://cli.vuejs.org/zh/config/#devserver-proxy 38 | // '/api': { 39 | // target: 'http://xxx.xx.xx' 40 | // } 41 | // } 42 | } 43 | }; 44 | --------------------------------------------------------------------------------