├── .browserslistrc ├── public ├── robots.txt └── logo.ico ├── src ├── App.vue ├── static │ ├── images │ │ ├── 401.gif │ │ ├── 404.png │ │ ├── logo.png │ │ ├── login-bg.jpg │ │ ├── profile.jpg │ │ └── 404_cloud.png │ ├── icons │ │ ├── svg │ │ │ ├── chart.svg │ │ │ ├── size.svg │ │ │ ├── link.svg │ │ │ ├── guide.svg │ │ │ ├── money.svg │ │ │ ├── email.svg │ │ │ ├── drag.svg │ │ │ ├── documentation.svg │ │ │ ├── fullscreen.svg │ │ │ ├── lock.svg │ │ │ ├── user.svg │ │ │ ├── excel.svg │ │ │ ├── nav-editor.svg │ │ │ ├── music.svg │ │ │ ├── example.svg │ │ │ ├── play.svg │ │ │ ├── star.svg │ │ │ ├── slider.svg │ │ │ ├── table.svg │ │ │ ├── search.svg │ │ │ ├── nav-home.svg │ │ │ ├── webDate.svg │ │ │ ├── education.svg │ │ │ ├── stop.svg │ │ │ ├── tab.svg │ │ │ ├── nav-jxgl.svg │ │ │ ├── message.svg │ │ │ ├── switch.svg │ │ │ ├── theme.svg │ │ │ ├── nav-kwgl.svg │ │ │ ├── refresh.svg │ │ │ ├── druid.svg │ │ │ ├── code.svg │ │ │ ├── peoples.svg │ │ │ ├── input.svg │ │ │ ├── server.svg │ │ │ ├── home-student.svg │ │ │ ├── textarea.svg │ │ │ ├── time.svg │ │ │ ├── article.svg │ │ │ ├── edit.svg │ │ │ ├── nested.svg │ │ │ ├── nav-storage.svg │ │ │ ├── row.svg │ │ │ ├── monitor.svg │ │ │ ├── nav-again.svg │ │ │ ├── tree-table.svg │ │ │ ├── nav-jkgl.svg │ │ │ ├── eye.svg │ │ │ ├── build.svg │ │ │ ├── clipboard.svg │ │ │ ├── fullScreen1.svg │ │ │ ├── home-item.svg │ │ │ ├── list.svg │ │ │ ├── download.svg │ │ │ ├── fullScreen2.svg │ │ │ ├── icon.svg │ │ │ ├── international.svg │ │ │ ├── question.svg │ │ │ ├── wechat.svg │ │ │ ├── skill.svg │ │ │ ├── people.svg │ │ │ ├── nav-sbgl.svg │ │ │ ├── post.svg │ │ │ ├── laba.svg │ │ │ ├── onekey.svg │ │ │ ├── language.svg │ │ │ ├── checkbox.svg │ │ │ ├── eye-open.svg │ │ │ ├── validCode.svg │ │ │ ├── nav-more.svg │ │ │ ├── radio.svg │ │ │ ├── select.svg │ │ │ ├── upload.svg │ │ │ ├── nav-jckgl.svg │ │ │ ├── 404.svg │ │ │ ├── zip.svg │ │ │ ├── nav-ksks.svg │ │ │ ├── phone.svg │ │ │ ├── log.svg │ │ │ ├── bug.svg │ │ │ ├── home-point.svg │ │ │ ├── webUser.svg │ │ │ ├── github.svg │ │ │ ├── nav-yjgl.svg │ │ │ ├── home-worker.svg │ │ │ ├── pdf.svg │ │ │ ├── logininfor.svg │ │ │ ├── rate.svg │ │ │ ├── job.svg │ │ │ ├── exit-fullscreen.svg │ │ │ ├── tree.svg │ │ │ ├── swagger.svg │ │ │ ├── password.svg │ │ │ ├── nav-sys.svg │ │ │ ├── date-range.svg │ │ │ ├── shopping.svg │ │ │ ├── cascader.svg │ │ │ ├── dashboard.svg │ │ │ ├── component.svg │ │ │ ├── form.svg │ │ │ ├── tool.svg │ │ │ ├── dict.svg │ │ │ ├── time-range.svg │ │ │ └── system.svg │ │ └── index.js │ └── styles │ │ ├── element-variables.scss │ │ ├── variables.scss │ │ ├── transition.scss │ │ ├── mixin.scss │ │ ├── btn.scss │ │ └── element-ui.scss ├── utils │ ├── config.js │ ├── httpResponse.js │ ├── auth.js │ ├── permission.js │ ├── zipdownload.js │ ├── jsencrypt.js │ ├── tools.js │ ├── base.js │ └── scroll-to.js ├── views │ ├── admin │ │ ├── login │ │ │ └── 又拍云_logo6.png │ │ ├── layout │ │ │ ├── components │ │ │ │ ├── index.js │ │ │ │ ├── Sidebar │ │ │ │ │ ├── Item.vue │ │ │ │ │ ├── FixiOSBug.js │ │ │ │ │ ├── Link.vue │ │ │ │ │ ├── index.vue │ │ │ │ │ └── Logo.vue │ │ │ │ ├── AppMain.vue │ │ │ │ └── Settings │ │ │ │ │ └── index.vue │ │ │ └── mixin │ │ │ │ └── ResizeHandler.js │ │ ├── redirect.vue │ │ ├── home │ │ │ └── index.vue │ │ ├── error │ │ │ └── 401.vue │ │ └── system │ │ │ └── user │ │ │ └── profile │ │ │ ├── userInfo.vue │ │ │ └── resetPwd.vue │ └── front │ │ └── detail │ │ └── index.vue ├── api │ ├── admin │ │ ├── base.js │ │ ├── login.js │ │ ├── blog │ │ │ ├── article.js │ │ │ ├── articleType.js │ │ │ └── friendlyLink.js │ │ └── system │ │ │ ├── dict │ │ │ ├── type.js │ │ │ └── data.js │ │ │ ├── notice.js │ │ │ ├── dept.js │ │ │ ├── menu.js │ │ │ ├── role.js │ │ │ └── user.js │ └── front │ │ ├── blog │ │ ├── articleType.js │ │ ├── friendlyLink.js │ │ └── article.js │ │ └── system │ │ └── user.js ├── components │ ├── IconSelect │ │ ├── requireIcons.js │ │ └── index.vue │ ├── SvgIcon │ │ └── index.vue │ ├── Screenfull │ │ └── index.vue │ ├── Hamburger │ │ └── index.vue │ ├── SizeSelect │ │ └── index.vue │ ├── Breadcrumb │ │ └── index.vue │ └── Pagination │ │ └── index.vue ├── directive │ └── permission │ │ ├── index.js │ │ ├── hasRole.js │ │ └── hasPermi.js ├── store │ ├── getters.js │ ├── index.js │ └── modules │ │ ├── settings.js │ │ ├── app.js │ │ └── user.js ├── lang │ ├── index.js │ ├── zh.js │ └── en.js ├── settings.js ├── router │ └── dynamicRouter.js ├── registerServiceWorker.js ├── main.js └── permission.js ├── .env.development ├── .env.production ├── .editorconfig ├── .babelrc ├── .gitignore ├── babel.config.js ├── .eslintrc.js ├── package.json └── README.md /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /public/logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiheping/vue-cms/HEAD/public/logo.ico -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/static/images/401.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiheping/vue-cms/HEAD/src/static/images/401.gif -------------------------------------------------------------------------------- /src/static/images/404.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiheping/vue-cms/HEAD/src/static/images/404.png -------------------------------------------------------------------------------- /src/static/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiheping/vue-cms/HEAD/src/static/images/logo.png -------------------------------------------------------------------------------- /src/utils/config.js: -------------------------------------------------------------------------------- 1 | export const baseImgUrl = process.env.NODE_ENV === 'development' ? '/img_url' : '' 2 | -------------------------------------------------------------------------------- /src/static/images/login-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiheping/vue-cms/HEAD/src/static/images/login-bg.jpg -------------------------------------------------------------------------------- /src/static/images/profile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiheping/vue-cms/HEAD/src/static/images/profile.jpg -------------------------------------------------------------------------------- /.env.development: -------------------------------------------------------------------------------- 1 | # 开发环境配置 2 | ENV = 'development' 3 | 4 | # 理化生实验操作考试管理系统/开发环境 5 | VUE_APP_BASE_API = '/api/v1' 6 | -------------------------------------------------------------------------------- /.env.production: -------------------------------------------------------------------------------- 1 | # 生产环境配置 2 | ENV = 'production' 3 | 4 | # 理化生实验操作考试管理系统/生产环境 5 | VUE_APP_BASE_API = '/api/v1' 6 | -------------------------------------------------------------------------------- /src/static/images/404_cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiheping/vue-cms/HEAD/src/static/images/404_cloud.png -------------------------------------------------------------------------------- /src/views/admin/login/又拍云_logo6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caiheping/vue-cms/HEAD/src/views/admin/login/又拍云_logo6.png -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{js,jsx,ts,tsx,vue}] 2 | indent_style = space 3 | indent_size = 2 4 | trim_trailing_whitespace = true 5 | insert_final_newline = true 6 | -------------------------------------------------------------------------------- /src/api/admin/base.js: -------------------------------------------------------------------------------- 1 | import HttpRequest from '@/utils/request' 2 | 3 | // 上传头像 4 | export function uploadAvatar (params = {}) { 5 | return HttpRequest('/upload', 'post', params) 6 | } 7 | -------------------------------------------------------------------------------- /src/static/icons/svg/chart.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/api/front/blog/articleType.js: -------------------------------------------------------------------------------- 1 | import HttpRequest from '@/utils/request' 2 | 3 | export function getAllType (params = {}) { 4 | return HttpRequest('/front/blog/articleType/getAllType', 'get', params) 5 | } 6 | -------------------------------------------------------------------------------- /src/api/front/system/user.js: -------------------------------------------------------------------------------- 1 | import HttpRequest from '@/utils/request' 2 | 3 | // 获取用户信息 4 | export function getInfo (params = {}) { 5 | return HttpRequest('/front/system/getInfo', 'get', params, false) 6 | } 7 | -------------------------------------------------------------------------------- /src/api/front/blog/friendlyLink.js: -------------------------------------------------------------------------------- 1 | import HttpRequest from '@/utils/request' 2 | 3 | export function getAllLink (params = {}) { 4 | return HttpRequest('/front/blog/friendlyLink/getFriendlyLink', 'get', params) 5 | } 6 | -------------------------------------------------------------------------------- /src/utils/httpResponse.js: -------------------------------------------------------------------------------- 1 | import { Message } from 'element-ui' 2 | 3 | export function httpResponse (message = 'success', type = 'success') { 4 | Message({ 5 | type: type, 6 | message: message 7 | }) 8 | } 9 | -------------------------------------------------------------------------------- /src/static/styles/element-variables.scss: -------------------------------------------------------------------------------- 1 | /* 改变主题色变量 */ 2 | $--color-primary: teal; 3 | 4 | /* 改变 icon 字体路径变量,必需 */ 5 | $--font-path: '~element-ui/lib/theme-chalk/fonts'; 6 | 7 | @import "~element-ui/packages/theme-chalk/src/index"; 8 | -------------------------------------------------------------------------------- /src/static/icons/svg/size.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["@babel/preset-env", { "modules": false }]], 3 | "plugins": [ 4 | [ 5 | "component", 6 | { 7 | "libraryName": "element-ui", 8 | "styleLibraryName": "theme-chalk" 9 | } 10 | ] 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /src/static/icons/svg/link.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/views/admin/layout/components/index.js: -------------------------------------------------------------------------------- 1 | export { default as AppMain } from './AppMain' 2 | export { default as Navbar } from './Navbar' 3 | export { default as Settings } from './Settings/index' 4 | export { default as Sidebar } from './Sidebar/index.vue' 5 | export { default as TagsView } from './TagsView/index.vue' 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? 22 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | const plugins = ['@vue/babel-plugin-transform-vue-jsx'] 2 | // 生产环境移除console 3 | if (process.env.NODE_ENV === 'production') { 4 | plugins.push('transform-remove-console') 5 | } 6 | 7 | module.exports = { 8 | plugins: plugins, 9 | presets: [ 10 | '@vue/cli-plugin-babel/preset' 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /src/views/admin/redirect.vue: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /src/components/IconSelect/requireIcons.js: -------------------------------------------------------------------------------- 1 | 2 | const req = require.context('../../static/icons/svg', false, /\.svg$/) 3 | const requireAll = requireContext => requireContext.keys() 4 | 5 | const re = /\.\/(.*)\.svg/ 6 | 7 | const icons = requireAll(req).map(i => { 8 | return i.match(re)[1] 9 | }) 10 | 11 | export default icons 12 | -------------------------------------------------------------------------------- /src/static/icons/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import SvgIcon from '@/components/SvgIcon'// svg组件 3 | 4 | // register globally 5 | Vue.component('svg-icon', SvgIcon) 6 | 7 | const requireAll = requireContext => requireContext.keys().map(requireContext) 8 | const req = require.context('./svg', false, /\.svg$/) 9 | requireAll(req) 10 | -------------------------------------------------------------------------------- /src/static/icons/svg/guide.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/api/front/blog/article.js: -------------------------------------------------------------------------------- 1 | import HttpRequest from '@/utils/request' 2 | 3 | // 查询文章 4 | export function getArticle (params = {}) { 5 | return HttpRequest('/front/blog/getArticle', 'get', params) 6 | } 7 | 8 | // 查询某个文章 9 | export function getArticleById (id) { 10 | return HttpRequest('/front/blog/getArticleById/' + id, 'get', {}) 11 | } 12 | -------------------------------------------------------------------------------- /src/static/icons/svg/money.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/utils/auth.js: -------------------------------------------------------------------------------- 1 | import Cookies from 'js-cookie' 2 | 3 | const TokenKey = 'CMS-Token' 4 | 5 | export function getToken () { 6 | return Cookies.get(TokenKey) 7 | } 8 | 9 | export function setToken (token) { 10 | return Cookies.set(TokenKey, token) 11 | } 12 | 13 | export function removeToken () { 14 | return Cookies.remove(TokenKey) 15 | } 16 | -------------------------------------------------------------------------------- /src/static/icons/svg/email.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/drag.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/directive/permission/index.js: -------------------------------------------------------------------------------- 1 | import hasRole from './hasRole' 2 | import hasPermi from './hasPermi' 3 | 4 | const install = function (Vue) { 5 | Vue.directive('hasRole', hasRole) 6 | Vue.directive('hasPermi', hasPermi) 7 | } 8 | 9 | if (window.Vue) { 10 | window.hasRole = hasRole 11 | window.hasPermi = hasPermi 12 | Vue.use(install); // eslint-disable-line 13 | } 14 | 15 | export default install 16 | -------------------------------------------------------------------------------- /src/api/admin/login.js: -------------------------------------------------------------------------------- 1 | import HttpRequest from '@/utils/request' 2 | 3 | // 登录 4 | export function login (params = {}) { 5 | return HttpRequest('/login', 'post', params) 6 | } 7 | 8 | // 登出 9 | export function logout (params = {}) { 10 | return HttpRequest('/logout', 'post', params) 11 | } 12 | 13 | // 验证码 14 | export function getCodeImg (params = {}) { 15 | return HttpRequest('/captcha', 'get', params, false) 16 | } 17 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | extends: [ 7 | 'plugin:vue/essential', 8 | '@vue/standard' 9 | ], 10 | parserOptions: { 11 | parser: 'babel-eslint' 12 | }, 13 | rules: { 14 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 15 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/static/icons/svg/documentation.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/fullscreen.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/store/getters.js: -------------------------------------------------------------------------------- 1 | const getters = { 2 | sidebar: state => state.app.sidebar, 3 | size: state => state.app.size, 4 | device: state => state.app.device, 5 | visitedViews: state => state.tagsView.visitedViews, 6 | cachedViews: state => state.tagsView.cachedViews, 7 | token: state => state.user.token, 8 | userInfo: state => state.user.userInfo, 9 | permission_routes: state => state.permission.menus 10 | } 11 | export default getters 12 | -------------------------------------------------------------------------------- /src/static/icons/svg/lock.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/user.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/excel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/nav-editor.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/static/icons/svg/music.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/static/icons/svg/example.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/lang/index.js: -------------------------------------------------------------------------------- 1 | 2 | // 引入i18n国际化插件 3 | import Vue from 'vue' 4 | import VueI18n from 'vue-i18n' 5 | // process.env.NODE_ENV === "development" ? Vue.use(VueI18n) : null; 6 | 7 | import enLocale from './en' 8 | import zhLocale from './zh' 9 | 10 | Vue.use(VueI18n) 11 | 12 | // 注册i18n实例并引入语言文件,文件格式等下解析 13 | const i18n = new VueI18n({ 14 | locale: 'en', 15 | messages: { 16 | zh: { 17 | ...zhLocale 18 | }, 19 | en: { 20 | ...enLocale 21 | } 22 | } 23 | }) 24 | 25 | export default i18n 26 | -------------------------------------------------------------------------------- /src/static/icons/svg/play.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import app from './modules/app' 4 | import user from './modules/user' 5 | import tagsView from './modules/tagsView' 6 | import permission from './modules/permission' 7 | import settings from './modules/settings' 8 | import getters from './getters' 9 | 10 | Vue.use(Vuex) 11 | 12 | const store = new Vuex.Store({ 13 | modules: { 14 | app, 15 | user, 16 | tagsView, 17 | permission, 18 | settings 19 | }, 20 | getters 21 | }) 22 | 23 | export default store 24 | -------------------------------------------------------------------------------- /src/static/icons/svg/star.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/slider.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/table.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/search.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/nav-home.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/static/icons/svg/webDate.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/static/icons/svg/education.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/stop.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/settings.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | /** 3 | * 是否系统布局配置 4 | */ 5 | showSettings: false, 6 | 7 | /** 8 | * 是否显示 tagsView 9 | */ 10 | tagsView: true, 11 | 12 | /** 13 | * 是否固定头部 14 | */ 15 | fixedHeader: true, 16 | 17 | /** 18 | * 是否显示logo 19 | */ 20 | sidebarLogo: false, 21 | 22 | /** 23 | * @type {string | array} 'production' | ['production', 'development'] 24 | * @description Need show err logs component. 25 | * The default is only used in the production env 26 | * If you want to also use it in dev, you can pass ['production', 'development'] 27 | */ 28 | errorLog: 'production' 29 | } 30 | -------------------------------------------------------------------------------- /src/static/icons/svg/tab.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/views/admin/layout/components/Sidebar/Item.vue: -------------------------------------------------------------------------------- 1 | 30 | -------------------------------------------------------------------------------- /src/views/admin/home/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 我的博客 4 | 5 | 6 | 7 | 22 | 23 | 30 | -------------------------------------------------------------------------------- /src/static/icons/svg/nav-jxgl.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/static/icons/svg/message.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/switch.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/theme.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/nav-kwgl.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/static/icons/svg/refresh.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/views/admin/layout/components/Sidebar/FixiOSBug.js: -------------------------------------------------------------------------------- 1 | export default { 2 | computed: { 3 | device () { 4 | return this.$store.state.app.device 5 | } 6 | }, 7 | mounted () { 8 | // In order to fix the click on menu on the ios device will trigger the mouseleave bug 9 | this.fixBugIniOS() 10 | }, 11 | methods: { 12 | fixBugIniOS () { 13 | const $subMenu = this.$refs.subMenu 14 | if ($subMenu) { 15 | const handleMouseleave = $subMenu.handleMouseleave 16 | $subMenu.handleMouseleave = (e) => { 17 | if (this.device === 'mobile') { 18 | return 19 | } 20 | handleMouseleave(e) 21 | } 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/static/icons/svg/druid.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/code.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/peoples.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/router/dynamicRouter.js: -------------------------------------------------------------------------------- 1 | export default { 2 | Layout: () => import('@/views/admin/layout'), 3 | Home: () => import('@/views/admin/home'), 4 | 5 | // 系统管理 6 | User: () => import('@/views/admin/system/user'), 7 | Role: () => import('@/views/admin/system/role'), 8 | Notice: () => import('@/views/admin/system/notice'), 9 | Menu: () => import('@/views/admin/system/menu'), 10 | Dict: () => import('@/views/admin/system/dict'), 11 | Dept: () => import('@/views/admin/system/dept'), 12 | 13 | // 文章模块 14 | ArticleList: () => import('@/views/admin/blogModel/articleList'), 15 | ArticleType: () => import('@/views/admin/blogModel/articleType'), 16 | FriendlyLink: () => import('@/views/admin/blogModel/friendlyLink') 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/api/admin/blog/article.js: -------------------------------------------------------------------------------- 1 | import HttpRequest from '@/utils/request' 2 | 3 | // 查询文章 4 | export function getArticle (params = {}) { 5 | return HttpRequest('/admin/blog/article', 'get', params) 6 | } 7 | 8 | // 查询某个文章 9 | export function getArticleById (id) { 10 | return HttpRequest('/admin/blog/article/' + id, 'get', {}, false) 11 | } 12 | 13 | // 添加文章 14 | export function addArticle (params = {}) { 15 | return HttpRequest('/admin/blog/article', 'post', params) 16 | } 17 | 18 | // 修改文章 19 | export function updateArticle (params = {}) { 20 | return HttpRequest('/admin/blog/article/' + params.id, 'put', params) 21 | } 22 | // 删除文章 23 | export function delArticle (ids) { 24 | return HttpRequest('/admin/blog/article/' + ids, 'delete') 25 | } 26 | -------------------------------------------------------------------------------- /src/api/admin/system/dict/type.js: -------------------------------------------------------------------------------- 1 | import HttpRequest from '@/utils/request' 2 | 3 | // 查询列表 4 | export function listType (params = {}) { 5 | return HttpRequest('/admin/system/dictType', 'get', params) 6 | } 7 | 8 | // 查询某一个 9 | export function getType (id) { 10 | return HttpRequest('/admin/system/dictType/' + id, 'get', {}, false) 11 | } 12 | 13 | // 删除 14 | export function delType (ids) { 15 | return HttpRequest('/admin/system/dictType/' + ids, 'delete') 16 | } 17 | 18 | // 添加 19 | export function addType (params = {}) { 20 | return HttpRequest('/admin/system/dictType', 'post', params) 21 | } 22 | 23 | // 修改 24 | export function updateType (params = {}) { 25 | return HttpRequest('/admin/system/dictType/' + params.id, 'put', params) 26 | } 27 | -------------------------------------------------------------------------------- /src/static/icons/svg/input.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/api/admin/system/notice.js: -------------------------------------------------------------------------------- 1 | import HttpRequest from '@/utils/request' 2 | 3 | // 获取公告 4 | export function listNotice (params = {}) { 5 | return HttpRequest('/admin/system/notice', 'get', params) 6 | } 7 | 8 | // 获取某个公告 9 | export function getNotice (id) { 10 | return HttpRequest('/admin/system/notice/' + id, 'get', {}, false) 11 | } 12 | 13 | // 删除公告 14 | export function delNotice (ids) { 15 | return HttpRequest('/admin/system/notice/' + ids, 'delete') 16 | } 17 | 18 | // 添加公告 19 | export function addNotice (params = {}) { 20 | return HttpRequest('/admin/system/notice', 'post', params) 21 | } 22 | 23 | // 修改公告 24 | export function updateNotice (params = {}) { 25 | return HttpRequest('/admin/system/notice/' + params.id, 'put', params) 26 | } 27 | -------------------------------------------------------------------------------- /src/api/admin/system/dept.js: -------------------------------------------------------------------------------- 1 | import HttpRequest from '@/utils/request' 2 | 3 | // 查询列表 4 | export function getDept (params = {}) { 5 | return HttpRequest('/admin/system/department', 'get', params, false) 6 | } 7 | 8 | // 查询单个 9 | export function getDeptById (id) { 10 | return HttpRequest('/admin/system/department/' + id, 'get', {}, false) 11 | } 12 | 13 | // 删除 14 | export function delDept (ids) { 15 | return HttpRequest('/admin/system/department/' + ids, 'delete') 16 | } 17 | 18 | // 添加 19 | export function addDept (params) { 20 | return HttpRequest('/admin/system/department', 'post', params) 21 | } 22 | 23 | // 修改 24 | export function updateDept (params) { 25 | return HttpRequest('/admin/system/department/' + params.deptId, 'put', params) 26 | } 27 | -------------------------------------------------------------------------------- /src/static/icons/svg/server.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/home-student.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/directive/permission/hasRole.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 角色权限处理 3 | * Copyright (c) 2019 ruoyi 4 | */ 5 | 6 | import store from '@/store' 7 | 8 | export default { 9 | inserted (el, binding, vnode) { 10 | const { value } = binding 11 | const superAdmin = 'admin' 12 | const roles = store.getters && store.getters.userInfo.user.roles.map(item => item.roleName) 13 | 14 | if (value && value instanceof Array && value.length > 0) { 15 | const roleFlag = value 16 | 17 | const hasRole = roles.some(role => { 18 | return superAdmin === role || roleFlag.includes(role) 19 | }) 20 | 21 | if (!hasRole) { 22 | el.parentNode && el.parentNode.removeChild(el) 23 | } 24 | } else { 25 | throw new Error('请设置角色权限标签值"') 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/static/icons/svg/textarea.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/time.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/article.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/static/icons/svg/edit.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/directive/permission/hasPermi.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 操作权限处理 3 | * Copyright (c) 2019 ruoyi 4 | */ 5 | 6 | import store from '@/store' 7 | 8 | export default { 9 | inserted (el, binding, vnode) { 10 | const { value } = binding 11 | const allPermission = '*:*:*' 12 | const permissions = store.getters && store.getters.userInfo.permissions 13 | 14 | if (value && value instanceof Array && value.length > 0) { 15 | const permissionFlag = value 16 | 17 | const hasPermissions = permissions.some(permission => { 18 | return allPermission === permission || permissionFlag.includes(permission) 19 | }) 20 | 21 | if (!hasPermissions) { 22 | el.parentNode && el.parentNode.removeChild(el) 23 | } 24 | } else { 25 | throw new Error('请设置操作权限标签值') 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/static/icons/svg/nested.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/store/modules/settings.js: -------------------------------------------------------------------------------- 1 | import variables from '@/static/styles/element-variables.scss' 2 | import defaultSettings from '@/settings' 3 | 4 | const { showSettings, tagsView, fixedHeader, sidebarLogo } = defaultSettings 5 | 6 | const state = { 7 | theme: variables.theme, 8 | showSettings: showSettings, 9 | tagsView: tagsView, 10 | fixedHeader: fixedHeader, 11 | sidebarLogo: sidebarLogo 12 | } 13 | 14 | const mutations = { 15 | CHANGE_SETTING: (state, { key, value }) => { 16 | if (Object.prototype.hasOwnProperty.call(state, key)) { 17 | state[key] = value 18 | } 19 | } 20 | } 21 | 22 | const actions = { 23 | changeSetting ({ commit }, data) { 24 | commit('CHANGE_SETTING', data) 25 | } 26 | } 27 | 28 | export default { 29 | namespaced: true, 30 | state, 31 | mutations, 32 | actions 33 | } 34 | -------------------------------------------------------------------------------- /src/api/admin/system/menu.js: -------------------------------------------------------------------------------- 1 | import HttpRequest from '@/utils/request' 2 | 3 | // 获取路由 4 | export function getRouters (params = {}) { 5 | return HttpRequest('/admin/system/menu/userMenu', 'get', params, false) 6 | } 7 | 8 | // 获取路由 9 | export function getMenu (params = {}) { 10 | return HttpRequest('/admin/system/menu', 'get', params, false) 11 | } 12 | 13 | // 获取某条菜单 14 | export function getMenuById (id) { 15 | return HttpRequest('/admin/system/menu/' + id, 'get', {}, false) 16 | } 17 | 18 | export function delMenu (ids) { 19 | return HttpRequest('/admin/system/menu/' + ids, 'delete') 20 | } 21 | 22 | export function addMenu (params = {}) { 23 | return HttpRequest('/admin/system/menu', 'post', params) 24 | } 25 | 26 | export function updateMenu (params = {}) { 27 | return HttpRequest('/admin/system/menu/' + params.id, 'put', params) 28 | } 29 | -------------------------------------------------------------------------------- /src/components/SvgIcon/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 33 | 34 | 42 | -------------------------------------------------------------------------------- /src/static/icons/svg/nav-storage.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/static/icons/svg/row.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/monitor.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/nav-again.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/api/admin/system/dict/data.js: -------------------------------------------------------------------------------- 1 | import HttpRequest from '@/utils/request' 2 | 3 | // 查询字典数据列表 4 | export function listData (params) { 5 | return HttpRequest('/admin/system/dictData', 'get', params) 6 | } 7 | 8 | // 查询字典数据详细 9 | export function getDataById (id) { 10 | return HttpRequest('/admin/system/dictData/' + id, 'get', {}, false) 11 | } 12 | 13 | // 根据字典类型查询字典数据信息 14 | export function getDicts (dictType) { 15 | return HttpRequest('/admin/system/showByType/' + dictType, 'get') 16 | } 17 | 18 | // 新增字典数据 19 | export function addData (params) { 20 | return HttpRequest('/admin/system/dictData', 'post', params) 21 | } 22 | 23 | // 修改字典数据 24 | export function updateData (params) { 25 | return HttpRequest('/admin/system/dictData/' + params.id, 'put', params) 26 | } 27 | 28 | // 删除字典数据 29 | export function delData (ids) { 30 | return HttpRequest('/admin/system/dictData/' + ids, 'delete') 31 | } 32 | -------------------------------------------------------------------------------- /src/static/icons/svg/tree-table.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/nav-jkgl.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/api/admin/blog/articleType.js: -------------------------------------------------------------------------------- 1 | import HttpRequest from '@/utils/request' 2 | 3 | // 查询文章类型 4 | export function getArticleType (params = {}) { 5 | return HttpRequest('/admin/blog/articleType', 'get', params) 6 | } 7 | 8 | // 查询某个文章类型 9 | export function getArticleTypeById (id) { 10 | return HttpRequest('/admin/blog/articleType/' + id, 'get', {}, false) 11 | } 12 | 13 | export function getAllType () { 14 | return HttpRequest('/admin/blog/articleType/getAllType', 'get', {}) 15 | } 16 | 17 | // 添加文章类型 18 | export function addArticleType (params = {}) { 19 | return HttpRequest('/admin/blog/articleType', 'post', params) 20 | } 21 | 22 | // 修改文章类型 23 | export function updateArticleType (params = {}) { 24 | return HttpRequest('/admin/blog/articleType/' + params.id, 'put', params) 25 | } 26 | // 删除文章类型 27 | export function delArticleType (ids) { 28 | return HttpRequest('/admin/blog/articleType/' + ids, 'delete') 29 | } 30 | -------------------------------------------------------------------------------- /src/api/admin/blog/friendlyLink.js: -------------------------------------------------------------------------------- 1 | import HttpRequest from '@/utils/request' 2 | 3 | // 查询文章类型 4 | export function getFriendlyLink (params = {}) { 5 | return HttpRequest('/admin/blog/friendlyLink', 'get', params) 6 | } 7 | 8 | // 查询某个文章类型 9 | export function getFriendlyLinkById (id) { 10 | return HttpRequest('/admin/blog/friendlyLink/' + id, 'get', {}, false) 11 | } 12 | 13 | export function getAllType () { 14 | return HttpRequest('/admin/blog/friendlyLink/getAllType', 'get', {}) 15 | } 16 | 17 | // 添加文章类型 18 | export function addFriendlyLink (params = {}) { 19 | return HttpRequest('/admin/blog/friendlyLink', 'post', params) 20 | } 21 | 22 | // 修改文章类型 23 | export function updateFriendlyLink (params = {}) { 24 | return HttpRequest('/admin/blog/friendlyLink/' + params.id, 'put', params) 25 | } 26 | // 删除文章类型 27 | export function delFriendlyLink (ids) { 28 | return HttpRequest('/admin/blog/friendlyLink/' + ids, 'delete') 29 | } 30 | -------------------------------------------------------------------------------- /src/static/icons/svg/eye.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/views/admin/layout/components/Sidebar/Link.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 46 | -------------------------------------------------------------------------------- /src/static/styles/variables.scss: -------------------------------------------------------------------------------- 1 | // base color 2 | $blue:#324157; 3 | $light-blue:#3A71A8; 4 | $red:#C03639; 5 | $pink: #E65D6E; 6 | $green: #30B08F; 7 | $tiffany: #4AB7BD; 8 | $yellow:#FEC171; 9 | $panGreen: #30B08F; 10 | 11 | // sidebar 12 | $menuText:#bfcbd9; 13 | $menuActiveText:#409EFF; 14 | $subMenuActiveText:#f4f4f5; // https://github.com/ElemeFE/element/issues/12951 15 | 16 | $menuBg:#304156; 17 | $menuHover:#263445; 18 | 19 | $subMenuBg:#1f2d3d; 20 | $subMenuHover:#001528; 21 | 22 | $sideBarWidth: 200px; 23 | 24 | // the :export directive is the magic sauce for webpack 25 | // https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass 26 | :export { 27 | menuText: $menuText; 28 | menuActiveText: $menuActiveText; 29 | subMenuActiveText: $subMenuActiveText; 30 | menuBg: $menuBg; 31 | menuHover: $menuHover; 32 | subMenuBg: $subMenuBg; 33 | subMenuHover: $subMenuHover; 34 | sideBarWidth: $sideBarWidth; 35 | } 36 | -------------------------------------------------------------------------------- /src/static/icons/svg/build.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/styles/transition.scss: -------------------------------------------------------------------------------- 1 | // global transition css 2 | 3 | /* fade */ 4 | .fade-enter-active, 5 | .fade-leave-active { 6 | transition: opacity 0.28s; 7 | } 8 | 9 | .fade-enter, 10 | .fade-leave-active { 11 | opacity: 0; 12 | } 13 | 14 | /* fade-transform */ 15 | .fade-transform-leave-active, 16 | .fade-transform-enter-active { 17 | transition: all .5s; 18 | } 19 | 20 | .fade-transform-enter { 21 | opacity: 0; 22 | transform: translateX(-30px); 23 | } 24 | 25 | .fade-transform-leave-to { 26 | opacity: 0; 27 | transform: translateX(30px); 28 | } 29 | 30 | /* breadcrumb transition */ 31 | .breadcrumb-enter-active, 32 | .breadcrumb-leave-active { 33 | transition: all .5s; 34 | } 35 | 36 | .breadcrumb-enter, 37 | .breadcrumb-leave-active { 38 | opacity: 0; 39 | transform: translateX(20px); 40 | } 41 | 42 | .breadcrumb-move { 43 | transition: all .5s; 44 | } 45 | 46 | .breadcrumb-leave-active { 47 | position: absolute; 48 | } 49 | -------------------------------------------------------------------------------- /src/static/icons/svg/clipboard.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/utils/permission.js: -------------------------------------------------------------------------------- 1 | // @/utils/permission 2 | 3 | import store from '@/store' 4 | 5 | /** 6 | 7 | * 判断是否拥有页面权限 8 | 9 | */ 10 | 11 | export function pagePermission (permission = '') { 12 | // 这里要判断的权限没有设置的话,就等于不需要权限,直接返回 true 13 | if (!permission) return false 14 | const permissionList = store.state.permission.permissionList 15 | return !!permissionList.includes(permission) 16 | } 17 | 18 | /** 19 | 20 | * 判断是否拥有资源权限 21 | 22 | */ 23 | 24 | export function btnPermission (val = '') { 25 | // 这里要判断的权限没有设置的话,就等于不需要权限,直接返回 true 26 | if (!val) return false 27 | return store.state.permission.btnsPermissionList.includes(val) 28 | } 29 | 30 | export function includePermission (list = []) { 31 | // 这里要判断的权限没有设置的话,就等于不需要权限,直接返回 true 32 | if (!list.length) return false 33 | let flag = false 34 | list.forEach(item => { 35 | if (store.state.permission.btnsPermissionList.includes(item)) { 36 | flag = true 37 | } 38 | }) 39 | return flag 40 | } 41 | -------------------------------------------------------------------------------- /src/static/icons/svg/fullScreen1.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/home-item.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/static/icons/svg/list.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/download.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/utils/zipdownload.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | import { getToken } from '@/utils/auth' 3 | 4 | // const mimeMap = { 5 | // xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 6 | // zip: 'application/zip' 7 | // } 8 | 9 | const baseUrl = process.env.VUE_APP_BASE_API 10 | export function downLoadZip (str, filename) { 11 | axios({ 12 | method: 'get', 13 | url: baseUrl + str, 14 | responseType: 'blob', 15 | headers: { Authorization: 'Bearer ' + getToken() } 16 | }).then(res => { 17 | const blob = new Blob([res.data], { type: 'application/zip' }) 18 | const downloadElement = document.createElement('a') 19 | const href = window.URL.createObjectURL(blob) // 创建下载的链接 20 | downloadElement.href = href 21 | downloadElement.download = filename + '.zip' // 下载后文件名 22 | document.body.appendChild(downloadElement) 23 | downloadElement.click() // 点击下载 24 | document.body.removeChild(downloadElement) // 下载完成移除元素 25 | window.URL.revokeObjectURL(href) // 释放掉blob对象 26 | }) 27 | } 28 | -------------------------------------------------------------------------------- /src/api/admin/system/role.js: -------------------------------------------------------------------------------- 1 | import HttpRequest from '@/utils/request' 2 | 3 | // 查询角色 4 | export function getRole (params = {}) { 5 | return HttpRequest('/admin/system/role', 'get', params) 6 | } 7 | 8 | // 查询某个角色 9 | export function getRoleById (id) { 10 | return HttpRequest('/admin/system/role/' + id, 'get', {}, false) 11 | } 12 | 13 | // 添加角色 14 | export function addRole (params = {}) { 15 | return HttpRequest('/admin/system/role', 'post', params) 16 | } 17 | 18 | // 修改角色 19 | export function updateRole (params = {}) { 20 | return HttpRequest('/admin/system/role/' + params.id, 'put', params) 21 | } 22 | 23 | // 修改角色状态 24 | export function updateRoleStatus (params = {}) { 25 | return HttpRequest('/admin/system/role/changeRoleStatus', 'put', params) 26 | } 27 | 28 | // 删除角色 29 | export function delRole (ids) { 30 | return HttpRequest('/admin/system/role/' + ids, 'delete') 31 | } 32 | 33 | // 更新角色状态 34 | export function changeRoleStatus (id, params = {}) { 35 | return HttpRequest(`/admin/system/role/${id}/updateStatus`, 'put', params) 36 | } 37 | -------------------------------------------------------------------------------- /src/registerServiceWorker.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { register } from 'register-service-worker' 4 | 5 | if (process.env.NODE_ENV === 'production') { 6 | register(`${process.env.BASE_URL}service-worker.js`, { 7 | ready () { 8 | console.log( 9 | 'App is being served from cache by a service worker.\n' + 10 | 'For more details, visit https://goo.gl/AFskqB' 11 | ) 12 | }, 13 | registered () { 14 | console.log('Service worker has been registered.') 15 | }, 16 | cached () { 17 | console.log('Content has been cached for offline use.') 18 | }, 19 | updatefound () { 20 | console.log('New content is downloading.') 21 | }, 22 | updated () { 23 | console.log('New content is available; please refresh.') 24 | }, 25 | offline () { 26 | console.log('No internet connection found. App is running in offline mode.') 27 | }, 28 | error (error) { 29 | console.error('Error during service worker registration:', error) 30 | } 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /src/static/icons/svg/fullScreen2.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/international.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/question.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/Screenfull/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 43 | 44 | 54 | -------------------------------------------------------------------------------- /src/static/icons/svg/wechat.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/skill.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/people.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/nav-sbgl.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/post.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/laba.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/static/icons/svg/onekey.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/utils/jsencrypt.js: -------------------------------------------------------------------------------- 1 | import JSEncrypt from 'jsencrypt/bin/jsencrypt' 2 | 3 | // 密钥对生成 http://web.chacuo.net/netrsakeypair 4 | 5 | const publicKey = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANL378k3RiZHWx5AfJqdH9xRNBmD9wGD\n' + 6 | '2iRe41HdTNF8RUhNnHit5NpMNtGL0NPTSSpPjjI1kJfVorRvaQerUgkCAwEAAQ==' 7 | 8 | const privateKey = 'MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8\n' + 9 | 'mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9p\n' + 10 | 'B6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue\n' + 11 | '/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZ\n' + 12 | 'UBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6\n' + 13 | 'vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha\n' + 14 | '4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3\n' + 15 | 'tTbklZkD2A==' 16 | 17 | // 加密 18 | export function encrypt (txt) { 19 | const encryptor = new JSEncrypt() 20 | encryptor.setPublicKey(publicKey) // 设置公钥 21 | return encryptor.encrypt(txt) // 对需要加密的数据进行加密 22 | } 23 | 24 | // 解密 25 | export function decrypt (txt) { 26 | const encryptor = new JSEncrypt() 27 | encryptor.setPrivateKey(privateKey) 28 | return encryptor.decrypt(txt) 29 | } 30 | -------------------------------------------------------------------------------- /src/static/icons/svg/language.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/checkbox.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/eye-open.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/utils/tools.js: -------------------------------------------------------------------------------- 1 | // 递归返回菜单权限列表 2 | export function menuRecursion (arr, recursion = []) { 3 | if (arr.length) { 4 | arr.forEach(item => { 5 | if (item.url && (!item.list || !item.list.length)) { 6 | recursion.push(item.url) 7 | } 8 | if (item.list && item.list.length) { 9 | menuRecursion(item.list, recursion) 10 | } 11 | }) 12 | } 13 | return recursion 14 | } 15 | 16 | export function menuLists (arr) { 17 | if (arr.length) { 18 | arr.forEach(item => { 19 | item.label = item.alias 20 | item.value = item.alias 21 | if (item.children.length) { 22 | menuLists(item.children) 23 | } 24 | }) 25 | } 26 | } 27 | 28 | export function formatMenus (originalArr) { 29 | const arr1 = [] 30 | const arr2 = [] 31 | const obj = {} 32 | originalArr.forEach(item => { 33 | if (!arr1.includes(item.parentId)) { 34 | arr1.push(item.parentId) 35 | obj[item.parentId] = [] 36 | } else { 37 | obj[item.parentId].push(item) 38 | } 39 | }) 40 | originalArr.forEach(item => { 41 | for (const key in obj) { 42 | if (item.menuId === parseInt(key)) { 43 | item.children = obj[key] 44 | arr2.push(item) 45 | } 46 | } 47 | }) 48 | console.log(arr2) 49 | return arr2 50 | } 51 | -------------------------------------------------------------------------------- /src/static/icons/svg/validCode.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/lang/zh.js: -------------------------------------------------------------------------------- 1 | const zh = { 2 | // layout 3 | login: { 4 | login: '登录' 5 | }, 6 | commons: { 7 | xiaoai: '小爱', 8 | admin: '管理员', 9 | editor: '赵晓编', 10 | quit: '退出', 11 | hi: '您好', 12 | index: '首页', 13 | userManage: '用户管理', 14 | share: '分享功能', 15 | infoManage: '信息管理', 16 | infoShow: '个人信息', 17 | infoShow1: '个人信息子菜单1', 18 | infoShow2: '个人信息子菜单2', 19 | infoShow3: '个人信息子菜单3', 20 | infoShow4: '个人信息子菜单4', 21 | infoShow5: '个人信息子菜单5', 22 | infoModify: '修改信息', 23 | infoModify1: '修改信息子菜单1', 24 | infoModify2: '修改信息子菜单2', 25 | infoModify3: '修改信息子菜单3', 26 | fundManage: '资金管理', 27 | fundList: '资金流水', 28 | chinaTabsList: '区域投资', 29 | fundData: '资金数据', 30 | fundPosition: '投资分布', 31 | typePosition: '项目分布', 32 | incomePayPosition: '收支分布', 33 | permission: '权限设置', 34 | pagePer: '页面权限', 35 | directivePer: '按钮权限', 36 | errorPage: '错误页面', 37 | page401: '401', 38 | page404: '404', 39 | wechatNumber: '微信号' 40 | }, 41 | index: { 42 | yearLoss: '年度总盈亏', 43 | yearProfit: '年度收益率', 44 | potentialInvestor: '潜在投资人', 45 | intentionInvestor: '意向投资人', 46 | waitExamineInvestor: '待审投资人', 47 | examiningInvestor: '审核中投资人', 48 | tenMillion: '千万元', 49 | person: '人' 50 | } 51 | } 52 | 53 | export default zh 54 | -------------------------------------------------------------------------------- /src/static/icons/svg/nav-more.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/static/icons/svg/radio.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/select.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/Hamburger/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 13 | 14 | 15 | 16 | 32 | 33 | 45 | -------------------------------------------------------------------------------- /src/static/icons/svg/upload.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/nav-jckgl.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/utils/base.js: -------------------------------------------------------------------------------- 1 | import dayjs from 'dayjs' 2 | 3 | // 表单重置 4 | export function resetForm (refName) { 5 | if (this.$refs[refName]) { 6 | this.$refs[refName].resetFields() 7 | } 8 | } 9 | 10 | /** 11 | * 12 | * @param data 数据源 13 | * @param id字段 默认 'id' 14 | * @param parentId 父节点字段 默认 'parentId' 15 | * @param children 孩子节点字段 默认 'children' 16 | * @param rootId 根Id 默认 0 17 | * @returns {{obj, list: Array}} 18 | */ 19 | export function handleTree (data, id = 'id', parentId = 'parentId', children = 'children', rootId = 0) { 20 | const obj = {} 21 | data.forEach(item => { 22 | item[children] = [] 23 | obj[item[id]] = item 24 | }) 25 | const tree = [] 26 | data.forEach(list => { 27 | if (list[parentId] !== rootId) { 28 | if (obj[list[parentId]]) { 29 | obj[list[parentId]][children].push(list) 30 | } 31 | } else { 32 | tree.push(list) 33 | } 34 | }) 35 | return { 36 | tree, 37 | obj 38 | } 39 | } 40 | 41 | // 回显数据字典 42 | export function selectDictLabel (datas, value) { 43 | const actions = [] 44 | Object.keys(datas).map((key) => { 45 | if (datas[key].dictValue === ('' + value)) { 46 | actions.push(datas[key].dictLabel) 47 | return false 48 | } 49 | }) 50 | return actions.join('') 51 | } 52 | 53 | export function dateFormatter (row, column) { 54 | return dayjs(row.createdAt).format('YYYY-MM-DD HH:mm:ss') 55 | } 56 | -------------------------------------------------------------------------------- /src/static/icons/svg/404.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/zip.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/views/admin/layout/mixin/ResizeHandler.js: -------------------------------------------------------------------------------- 1 | import store from '@/store' 2 | 3 | const { body } = document 4 | const WIDTH = 992 // refer to Bootstrap's responsive design 5 | 6 | export default { 7 | watch: { 8 | $route (route) { 9 | if (this.device === 'mobile' && this.sidebar.opened) { 10 | store.dispatch('app/closeSideBar', { withoutAnimation: false }) 11 | } 12 | } 13 | }, 14 | beforeMount () { 15 | window.addEventListener('resize', this.$_resizeHandler) 16 | }, 17 | beforeDestroy () { 18 | window.removeEventListener('resize', this.$_resizeHandler) 19 | }, 20 | mounted () { 21 | const isMobile = this.$_isMobile() 22 | if (isMobile) { 23 | store.dispatch('app/toggleDevice', 'mobile') 24 | store.dispatch('app/closeSideBar', { withoutAnimation: true }) 25 | } 26 | }, 27 | methods: { 28 | // use $_ for mixins properties 29 | // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential 30 | $_isMobile () { 31 | const rect = body.getBoundingClientRect() 32 | return rect.width - 1 < WIDTH 33 | }, 34 | $_resizeHandler () { 35 | if (!document.hidden) { 36 | const isMobile = this.$_isMobile() 37 | store.dispatch('app/toggleDevice', isMobile ? 'mobile' : 'desktop') 38 | 39 | if (isMobile) { 40 | store.dispatch('app/closeSideBar', { withoutAnimation: true }) 41 | } 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/static/icons/svg/nav-ksks.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/store/modules/app.js: -------------------------------------------------------------------------------- 1 | import Cookies from 'js-cookie' 2 | 3 | const state = { 4 | loading: false, 5 | sidebar: { 6 | opened: Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true, 7 | withoutAnimation: false 8 | }, 9 | device: 'desktop', 10 | size: 'medium' 11 | } 12 | 13 | const mutations = { 14 | TOGGLE_SIDEBAR: state => { 15 | state.sidebar.opened = !state.sidebar.opened 16 | state.sidebar.withoutAnimation = false 17 | if (state.sidebar.opened) { 18 | Cookies.set('sidebarStatus', 1) 19 | } else { 20 | Cookies.set('sidebarStatus', 0) 21 | } 22 | }, 23 | CLOSE_SIDEBAR: (state, withoutAnimation) => { 24 | Cookies.set('sidebarStatus', 0) 25 | state.sidebar.opened = false 26 | state.sidebar.withoutAnimation = withoutAnimation 27 | }, 28 | TOGGLE_DEVICE: (state, device) => { 29 | state.device = device 30 | }, 31 | SET_SIZE: (state, size) => { 32 | state.size = size 33 | Cookies.set('size', size) 34 | } 35 | } 36 | 37 | const actions = { 38 | toggleSideBar ({ commit }) { 39 | commit('TOGGLE_SIDEBAR') 40 | }, 41 | closeSideBar ({ commit }, { withoutAnimation }) { 42 | commit('CLOSE_SIDEBAR', withoutAnimation) 43 | }, 44 | toggleDevice ({ commit }, device) { 45 | commit('TOGGLE_DEVICE', device) 46 | }, 47 | setSize ({ commit }, size) { 48 | commit('SET_SIZE', size) 49 | } 50 | } 51 | 52 | export default { 53 | namespaced: true, 54 | state, 55 | mutations, 56 | actions 57 | } 58 | -------------------------------------------------------------------------------- /src/static/icons/svg/phone.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/lang/en.js: -------------------------------------------------------------------------------- 1 | const zh = { 2 | login: { 3 | login: 'Login' 4 | }, 5 | // layout 6 | commons: { 7 | xiaoai: 'Ai.', 8 | admin: 'Admin', 9 | editor: 'Editor', 10 | quit: 'Sign Out', 11 | hi: 'Hi', 12 | index: 'Dashboard', 13 | userManage: 'Users', 14 | share: 'Share', 15 | infoManage: 'Infos', 16 | infoShow: 'InfoShow', 17 | infoShow1: 'InfoShow1', 18 | infoShow2: 'InfoShow2', 19 | infoShow3: 'InfoShow3', 20 | infoShow4: 'InfoShow4', 21 | infoShow5: 'InfoShow5', 22 | infoModify: 'InfoModify', 23 | infoModify1: 'InfoModify1', 24 | infoModify2: 'InfoModify2', 25 | infoModify3: 'InfoModify3', 26 | fundManage: 'Money', 27 | fundList: 'MoneyList', 28 | chinaTabsList: 'AreaList', 29 | fundData: 'FundData', 30 | fundPosition: 'FundPosition', 31 | typePosition: 'TypePosition', 32 | incomePayPosition: 'IncomePayPosition', 33 | permission: 'Permission', 34 | pagePer: 'PagePermission', 35 | directivePer: 'DirectivePermission', 36 | errorPage: 'ErrorPage', 37 | page401: '401', 38 | page404: '404', 39 | wechatNumber: 'wechat' 40 | }, 41 | index: { 42 | yearLoss: 'Year Loss', 43 | yearProfit: 'Year Profit', 44 | potentialInvestor: 'Potential Investor', 45 | intentionInvestor: 'Intention Investor', 46 | waitExamineInvestor: 'Wait Examine Investor', 47 | examiningInvestor: 'Examining Investor', 48 | tenMillion: 'Ten Million', 49 | person: 'P' 50 | } 51 | } 52 | 53 | export default zh 54 | -------------------------------------------------------------------------------- /src/static/icons/svg/log.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/bug.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/home-point.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/components/SizeSelect/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {{ item.label }} 9 | 10 | 11 | 12 | 13 | 14 | 57 | -------------------------------------------------------------------------------- /src/static/icons/svg/webUser.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/static/styles/mixin.scss: -------------------------------------------------------------------------------- 1 | @mixin clearfix { 2 | &:after { 3 | content: ""; 4 | display: table; 5 | clear: both; 6 | } 7 | } 8 | 9 | @mixin scrollBar { 10 | &::-webkit-scrollbar-track-piece { 11 | background: #d3dce6; 12 | } 13 | 14 | &::-webkit-scrollbar { 15 | width: 6px; 16 | } 17 | 18 | &::-webkit-scrollbar-thumb { 19 | background: #99a9bf; 20 | border-radius: 20px; 21 | } 22 | } 23 | 24 | @mixin relative { 25 | position: relative; 26 | width: 100%; 27 | height: 100%; 28 | } 29 | 30 | @mixin pct($pct) { 31 | width: #{$pct}; 32 | position: relative; 33 | margin: 0 auto; 34 | } 35 | 36 | @mixin triangle($width, $height, $color, $direction) { 37 | $width: $width/2; 38 | $color-border-style: $height solid $color; 39 | $transparent-border-style: $width solid transparent; 40 | height: 0; 41 | width: 0; 42 | 43 | @if $direction==up { 44 | border-bottom: $color-border-style; 45 | border-left: $transparent-border-style; 46 | border-right: $transparent-border-style; 47 | } 48 | 49 | @else if $direction==right { 50 | border-left: $color-border-style; 51 | border-top: $transparent-border-style; 52 | border-bottom: $transparent-border-style; 53 | } 54 | 55 | @else if $direction==down { 56 | border-top: $color-border-style; 57 | border-left: $transparent-border-style; 58 | border-right: $transparent-border-style; 59 | } 60 | 61 | @else if $direction==left { 62 | border-right: $color-border-style; 63 | border-top: $transparent-border-style; 64 | border-bottom: $transparent-border-style; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/static/icons/svg/github.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/Breadcrumb/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ item.meta.title }} 6 | {{ item.meta.title }} 7 | 8 | 9 | 10 | 11 | 12 | 44 | 45 | 58 | -------------------------------------------------------------------------------- /src/static/icons/svg/nav-yjgl.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/api/admin/system/user.js: -------------------------------------------------------------------------------- 1 | import HttpRequest from '@/utils/request' 2 | 3 | // 查询列表 4 | export function listUser (params = {}) { 5 | return HttpRequest('/admin/system/user', 'get', params) 6 | } 7 | 8 | // 查询某个用户 9 | export function getUser (id) { 10 | return HttpRequest('/admin/system/user/' + id, 'get', {}, false) 11 | } 12 | 13 | // 删除 14 | export function delUser (ids = []) { 15 | return HttpRequest('/admin/system/user/' + ids, 'delete') 16 | } 17 | 18 | // 新增 19 | export function addUser (params = {}) { 20 | return HttpRequest('/admin/system/user', 'post', params) 21 | } 22 | 23 | // 修改 24 | export function updateUser (params = {}) { 25 | return HttpRequest('/admin/system/user/' + params.id, 'put', params) 26 | } 27 | 28 | // 导出 29 | export function exportUser (params = {}) { 30 | return HttpRequest('/admin/system/user/export', 'get', params) 31 | } 32 | 33 | // 修改图片 34 | export function updateUserImg (userId, params = {}) { 35 | return HttpRequest(`/admin/system/user/${userId}/updateUserImg`, 'put', params) 36 | } 37 | 38 | // 重置密码 39 | export function resetUserPwd (userId, params = {}) { 40 | return HttpRequest(`/admin/system/user/${userId}/resetPwd`, 'put', params) 41 | } 42 | 43 | // 更新用户密码 44 | export function updateUserPwd (userId, params = {}) { 45 | return HttpRequest(`/admin/system/user/${userId}/updateUserPwd`, 'put', params) 46 | } 47 | 48 | // 导出模板 49 | export function importTemplate (params = {}) { 50 | return HttpRequest('/admin/system/user/import', 'get', params) 51 | } 52 | 53 | // 获取用户信息 54 | export function getInfo (params = {}) { 55 | return HttpRequest('/admin/system/getInfo', 'get', params, false) 56 | } 57 | -------------------------------------------------------------------------------- /src/static/icons/svg/home-worker.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/static/icons/svg/pdf.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/logininfor.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/rate.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/job.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/views/admin/layout/components/Sidebar/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 21 | 22 | 23 | 24 | 25 | 26 | 58 | -------------------------------------------------------------------------------- /src/static/icons/svg/exit-fullscreen.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/tree.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/swagger.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-template", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "@riophae/vue-treeselect": "^0.4.0", 12 | "axios": "^0.19.2", 13 | "core-js": "^3.6.4", 14 | "dayjs": "^1.10.3", 15 | "element-ui": "^2.13.0", 16 | "highlight.js": "^10.5.0", 17 | "js-cookie": "^2.2.1", 18 | "jsencrypt": "^3.0.0-rc.1", 19 | "marked": "^1.2.7", 20 | "mavon-editor": "^2.9.1", 21 | "nprogress": "^0.2.0", 22 | "register-service-worker": "^1.6.2", 23 | "screenfull": "^5.0.2", 24 | "uninstall": "0.0.0", 25 | "vue": "^2.6.11", 26 | "vue-cropper": "^0.5.5", 27 | "vue-i18n": "^8.15.4", 28 | "vue-particles": "^1.0.9", 29 | "vue-quill-editor": "^3.0.6", 30 | "vue-router": "^3.1.5", 31 | "vuex": "^3.1.2" 32 | }, 33 | "devDependencies": { 34 | "@babel/preset-env": "^7.8.4", 35 | "@vue/cli-plugin-babel": "^4.2.0", 36 | "@vue/cli-plugin-eslint": "^4.2.0", 37 | "@vue/cli-plugin-pwa": "^4.2.0", 38 | "@vue/cli-service": "^4.2.0", 39 | "@vue/eslint-config-standard": "^5.1.0", 40 | "babel-eslint": "^10.0.3", 41 | "babel-plugin-component": "^1.1.1", 42 | "babel-plugin-transform-remove-console": "^6.9.4", 43 | "compression-webpack-plugin": "^4.0.0", 44 | "eslint": "^6.7.2", 45 | "eslint-plugin-import": "^2.20.1", 46 | "eslint-plugin-node": "^11.0.0", 47 | "eslint-plugin-promise": "^4.2.1", 48 | "eslint-plugin-standard": "^4.0.0", 49 | "eslint-plugin-vue": "^6.1.2", 50 | "node-sass": "^4.12.0", 51 | "sass-loader": "^8.0.2", 52 | "svg-sprite-loader": "^4.2.1", 53 | "vue-template-compiler": "^2.6.11" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/static/icons/svg/password.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/nav-sys.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/components/IconSelect/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | {{ item }} 11 | 12 | 13 | 14 | 15 | 16 | 44 | 45 | 69 | -------------------------------------------------------------------------------- /src/static/styles/btn.scss: -------------------------------------------------------------------------------- 1 | @import './variables.scss'; 2 | 3 | @mixin colorBtn($color) { 4 | background: $color; 5 | 6 | &:hover { 7 | color: $color; 8 | 9 | &:before, 10 | &:after { 11 | background: $color; 12 | } 13 | } 14 | } 15 | 16 | .blue-btn { 17 | @include colorBtn($blue) 18 | } 19 | 20 | .light-blue-btn { 21 | @include colorBtn($light-blue) 22 | } 23 | 24 | .red-btn { 25 | @include colorBtn($red) 26 | } 27 | 28 | .pink-btn { 29 | @include colorBtn($pink) 30 | } 31 | 32 | .green-btn { 33 | @include colorBtn($green) 34 | } 35 | 36 | .tiffany-btn { 37 | @include colorBtn($tiffany) 38 | } 39 | 40 | .yellow-btn { 41 | @include colorBtn($yellow) 42 | } 43 | 44 | .pan-btn { 45 | font-size: 14px; 46 | color: #fff; 47 | padding: 14px 36px; 48 | border-radius: 8px; 49 | border: none; 50 | outline: none; 51 | transition: 600ms ease all; 52 | position: relative; 53 | display: inline-block; 54 | 55 | &:hover { 56 | background: #fff; 57 | 58 | &:before, 59 | &:after { 60 | width: 100%; 61 | transition: 600ms ease all; 62 | } 63 | } 64 | 65 | &:before, 66 | &:after { 67 | content: ''; 68 | position: absolute; 69 | top: 0; 70 | right: 0; 71 | height: 2px; 72 | width: 0; 73 | transition: 400ms ease all; 74 | } 75 | 76 | &::after { 77 | right: inherit; 78 | top: inherit; 79 | left: 0; 80 | bottom: 0; 81 | } 82 | } 83 | 84 | .custom-button { 85 | display: inline-block; 86 | line-height: 1; 87 | white-space: nowrap; 88 | cursor: pointer; 89 | background: #fff; 90 | color: #fff; 91 | -webkit-appearance: none; 92 | text-align: center; 93 | box-sizing: border-box; 94 | outline: 0; 95 | margin: 0; 96 | padding: 10px 15px; 97 | font-size: 14px; 98 | border-radius: 4px; 99 | } 100 | -------------------------------------------------------------------------------- /src/utils/scroll-to.js: -------------------------------------------------------------------------------- 1 | Math.easeInOutQuad = function (t, b, c, d) { 2 | t /= d / 2 3 | if (t < 1) { 4 | return c / 2 * t * t + b 5 | } 6 | t-- 7 | return -c / 2 * (t * (t - 2) - 1) + b 8 | } 9 | 10 | // requestAnimationFrame for Smart Animating http://goo.gl/sx5sts 11 | var requestAnimFrame = (function () { 12 | return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function (callback) { window.setTimeout(callback, 1000 / 60) } 13 | })() 14 | 15 | /** 16 | * Because it's so fucking difficult to detect the scrolling element, just move them all 17 | * @param {number} amount 18 | */ 19 | function move (amount) { 20 | document.documentElement.scrollTop = amount 21 | document.body.parentNode.scrollTop = amount 22 | document.body.scrollTop = amount 23 | } 24 | 25 | function position () { 26 | return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop 27 | } 28 | 29 | /** 30 | * @param {number} to 31 | * @param {number} duration 32 | * @param {Function} callback 33 | */ 34 | export function scrollTo (to, duration, callback) { 35 | const start = position() 36 | const change = to - start 37 | const increment = 20 38 | let currentTime = 0 39 | duration = (typeof (duration) === 'undefined') ? 500 : duration 40 | var animateScroll = function () { 41 | // increment the time 42 | currentTime += increment 43 | // find the value with the quadratic in-out easing function 44 | var val = Math.easeInOutQuad(currentTime, start, change, duration) 45 | // move the document.body 46 | move(val) 47 | // do the animation unless its over 48 | if (currentTime < duration) { 49 | requestAnimFrame(animateScroll) 50 | } else { 51 | if (callback && typeof (callback) === 'function') { 52 | // the animation is done so lets callback 53 | callback() 54 | } 55 | } 56 | } 57 | animateScroll() 58 | } 59 | -------------------------------------------------------------------------------- /src/views/admin/error/401.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 返回 5 | 6 | 7 | 8 | 9 | 401错误! 10 | 11 | 您没有访问权限! 12 | 对不起,您没有访问权限,请不要进行非法操作!您可以返回主页面 13 | 14 | 15 | 16 | 回首页 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 45 | 46 | 85 | -------------------------------------------------------------------------------- /src/static/styles/element-ui.scss: -------------------------------------------------------------------------------- 1 | // cover some element-ui styles 2 | 3 | .el-breadcrumb__inner, 4 | .el-breadcrumb__inner a { 5 | font-weight: 400 !important; 6 | } 7 | 8 | .el-upload { 9 | input[type="file"] { 10 | display: none !important; 11 | } 12 | } 13 | 14 | .el-upload__input { 15 | display: none; 16 | } 17 | 18 | .cell { 19 | .el-tag { 20 | margin-right: 0px; 21 | } 22 | } 23 | 24 | .small-padding { 25 | .cell { 26 | padding-left: 5px; 27 | padding-right: 5px; 28 | } 29 | } 30 | 31 | .fixed-width { 32 | .el-button--mini { 33 | //padding: 7px 10px; 34 | //width: 60px; 35 | } 36 | } 37 | 38 | .status-col { 39 | .cell { 40 | padding: 0 10px; 41 | text-align: center; 42 | 43 | .el-tag { 44 | margin-right: 0px; 45 | } 46 | } 47 | } 48 | 49 | // to fixed https://github.com/ElemeFE/element/issues/2461 50 | .el-dialog { 51 | transform: none; 52 | left: 0; 53 | position: relative; 54 | margin: 0 auto; 55 | } 56 | 57 | // refine element ui upload 58 | .upload-container { 59 | .el-upload { 60 | width: 100%; 61 | 62 | .el-upload-dragger { 63 | width: 100%; 64 | height: 200px; 65 | } 66 | } 67 | } 68 | 69 | // dropdown 70 | .el-dropdown-menu { 71 | a { 72 | display: block 73 | } 74 | } 75 | 76 | // fix date-picker ui bug in filter-item 77 | .el-range-editor.el-input__inner { 78 | display: inline-flex !important; 79 | } 80 | 81 | // to fix el-date-picker css style 82 | .el-range-separator { 83 | box-sizing: content-box; 84 | } 85 | 86 | .el-message-box__message{ 87 | max-height: 500px; 88 | overflow: auto; 89 | } 90 | 91 | .el-message{ 92 | z-index: 9999 !important; 93 | } 94 | 95 | .el-dialog__header { 96 | border-bottom: 1px solid #bebebe; 97 | } 98 | 99 | .el-tabs__item.is-active{ 100 | box-shadow: none !important; 101 | } 102 | 103 | .el-input--small, .el-input--mini{ 104 | font-size: 14px; 105 | } 106 | 107 | .el-drawer__header span{ 108 | outline: none; 109 | } 110 | 111 | -------------------------------------------------------------------------------- /src/static/icons/svg/date-range.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/views/admin/layout/components/Sidebar/Logo.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{ title }} 7 | 8 | 9 | 10 | {{ title }} 11 | 12 | 13 | 14 | 15 | 16 | 35 | 36 | 85 | -------------------------------------------------------------------------------- /src/store/modules/user.js: -------------------------------------------------------------------------------- 1 | import { login, logout } from '@/api/admin/login' 2 | import { getInfo } from '@/api/admin/system/user' 3 | import { getToken, setToken, removeToken } from '@/utils/auth' 4 | import { Message } from 'element-ui' 5 | 6 | const user = { 7 | state: { 8 | token: getToken(), 9 | frontUserInfo: null, 10 | userInfo: null 11 | }, 12 | 13 | mutations: { 14 | SET_TOKEN: (state, token) => { 15 | state.token = token 16 | }, 17 | SET_USERINFO: (state, userInfo) => { 18 | state.userInfo = userInfo 19 | } 20 | }, 21 | 22 | actions: { 23 | // 登录 24 | Login ({ commit }, params) { 25 | return new Promise((resolve, reject) => { 26 | login(params).then(res => { 27 | if (res.code === 200014) { 28 | Message({ 29 | type: 'error', 30 | message: res.msg 31 | }) 32 | } else { 33 | setToken(res.data.token) 34 | commit('SET_TOKEN', res.data.token) 35 | } 36 | resolve(res) 37 | }).catch(error => { 38 | reject(error) 39 | }) 40 | }) 41 | }, 42 | 43 | // 获取用户信息 44 | GetInfo ({ commit, state }) { 45 | return new Promise((resolve, reject) => { 46 | getInfo().then(res => { 47 | console.log(res) 48 | const userInfo = res.data 49 | commit('SET_USERINFO', userInfo) 50 | resolve(res) 51 | }).catch(error => { 52 | reject(error) 53 | }) 54 | }) 55 | }, 56 | 57 | // 退出系统 58 | LogOut ({ commit, state }) { 59 | return new Promise((resolve, reject) => { 60 | logout().then(() => { 61 | commit('SET_TOKEN', '') 62 | commit('SET_USERINFO', null) 63 | removeToken() 64 | resolve() 65 | }).catch(error => { 66 | reject(error) 67 | }) 68 | }) 69 | }, 70 | 71 | // 前端 登出 72 | FedLogOut ({ commit }) { 73 | return new Promise(resolve => { 74 | commit('SET_TOKEN', '') 75 | removeToken() 76 | resolve() 77 | }) 78 | } 79 | } 80 | } 81 | 82 | export default user 83 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import router from './router' 4 | import store from './store/index' 5 | import ElementUI from 'element-ui' 6 | import i18n from '@/lang' // 国际化 7 | import VueParticles from 'vue-particles' 8 | 9 | import { httpResponse } from './utils/httpResponse' 10 | import { btnPermission, includePermission } from './utils/permission' 11 | import Pagination from '@/components/Pagination' 12 | import { resetForm, handleTree, selectDictLabel, dateFormatter } from '@/utils/base' 13 | import { getDicts } from '@/api/admin/system/dict/data' 14 | import permission from './directive/permission' 15 | import { baseImgUrl } from './utils/config' 16 | import mavonEditor from 'mavon-editor' // markdown编辑器 17 | 18 | import './permission' // permission control 19 | import 'nprogress/nprogress.css' // progress bar style 20 | import './static/styles/element-variables.scss' // 自定义主题色 21 | import './static/styles/index.scss' 22 | import 'mavon-editor/dist/css/index.css' 23 | 24 | import '@/static/icons' 25 | 26 | import './static/styles/markdown.scss' // 引入代码高亮的css 27 | import hljs from 'highlight.js' 28 | 29 | // 封装成一个指令 30 | Vue.directive('highlight', (el) => { 31 | const blocks = el.querySelectorAll('pre code') 32 | blocks.forEach((block) => { 33 | hljs.highlightBlock(block) 34 | }) 35 | }) 36 | 37 | // use 38 | Vue.use(mavonEditor) 39 | 40 | Vue.use(ElementUI, { 41 | size: 'medium' // set element-ui default size 42 | }) 43 | Vue.use(VueParticles) 44 | Vue.config.productionTip = false 45 | Vue.prototype.baseImgUrl = baseImgUrl 46 | Vue.prototype.$httpResponse = httpResponse 47 | Vue.prototype.resetForm = resetForm // 重置表单 48 | Vue.prototype.getDicts = getDicts // 获取字典 49 | Vue.prototype.selectDictLabel = selectDictLabel 50 | Vue.prototype.dateFormatter = dateFormatter // 格式日期 51 | Vue.prototype.checkBtnPermission = btnPermission // 检查方法权限 52 | Vue.prototype.includePermission = includePermission // 检查方法列表权限 53 | Vue.prototype.handleTree = handleTree 54 | 55 | // 全局组件挂载 56 | Vue.component('Pagination', Pagination) 57 | 58 | Vue.use(permission) 59 | 60 | new Vue({ 61 | router, 62 | store, 63 | i18n, 64 | render: h => h(App) 65 | }).$mount('#app') 66 | -------------------------------------------------------------------------------- /src/static/icons/svg/shopping.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/views/admin/layout/components/AppMain.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 42 | 43 | 79 | 80 | 88 | -------------------------------------------------------------------------------- /src/permission.js: -------------------------------------------------------------------------------- 1 | import router from './router' 2 | import store from './store' 3 | import { Message } from 'element-ui' 4 | import NProgress from 'nprogress' 5 | import 'nprogress/nprogress.css' 6 | import { getToken } from '@/utils/auth' 7 | 8 | NProgress.configure({ showSpinner: false }) 9 | 10 | const whiteList = ['/login', '/register'] 11 | 12 | router.beforeEach((to, from, next) => { 13 | NProgress.start() 14 | // 前台 15 | if (to.fullPath.indexOf('/front') !== -1) { 16 | next() 17 | } else { // 后台 18 | if (getToken()) { 19 | /* has token */ 20 | if (to.path === '/login') { 21 | next({ name: store.state.permission.allRouterNames[0] }) 22 | NProgress.done() 23 | } else { 24 | if (!store.getters.userInfo) { 25 | // 判断当前用户是否已拉取完user_info信息 26 | store.dispatch('GetInfo').then(res => { 27 | store.dispatch('GenerateRoutes').then(accessRoutes => { 28 | router.addRoutes(accessRoutes) // 动态添加可访问路由表 29 | if (accessRoutes.length) { // 默认返回第一个 30 | // next({ 31 | // name: accessRoutes[0].children[0].name, 32 | // query: to.query, 33 | // replace: true 34 | // }) 35 | next({ 36 | ...to, 37 | replace: true 38 | }) 39 | } else { 40 | next({ 41 | path: '/404', 42 | replace: true 43 | }) 44 | } 45 | }) 46 | }).catch(err => { 47 | store.dispatch('FedLogOut').then(() => { 48 | Message.error(err) 49 | next({ path: '/' }) 50 | }) 51 | }) 52 | } else { 53 | next() 54 | } 55 | } 56 | } else { 57 | // 没有token 58 | console.log(to.path) 59 | if (whiteList.indexOf(to.path) !== -1) { 60 | // 在免登录白名单,直接进入 61 | next() 62 | } else { 63 | next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页 64 | NProgress.done() 65 | } 66 | } 67 | } 68 | }) 69 | 70 | router.afterEach(() => { 71 | NProgress.done() 72 | }) 73 | -------------------------------------------------------------------------------- /src/views/front/detail/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{$store.state.user.frontUserInfo ? $store.state.user.frontUserInfo.nickName: ''}} 8 | 9 | 10 | 11 | {{articleData.createdAt}} 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 分享 20 | 21 | 22 | 23 | 24 | 53 | 54 | 86 | -------------------------------------------------------------------------------- /src/static/icons/svg/cascader.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/dashboard.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/component.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/form.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/views/admin/system/user/profile/userInfo.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 男 15 | 女 16 | 17 | 18 | 19 | 保存 20 | 关闭 21 | 22 | 23 | 24 | 25 | 81 | -------------------------------------------------------------------------------- /src/views/admin/system/user/profile/resetPwd.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 保存 14 | 关闭 15 | 16 | 17 | 18 | 19 | 74 | -------------------------------------------------------------------------------- /src/static/icons/svg/tool.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/Pagination/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 5 | 16 | 17 | 18 | 19 | 98 | 99 | 111 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-cms 2 | 3 | ## 描述 4 | 5 | cms-api 为前后端分离的博客管理系统。 6 | 7 | ## 技术栈 8 | 9 | 后端技术栈:egg.js + mysql + sequelize + jwt 等 10 | 11 | 前端技术栈:vue全家桶 + axios + elementUI + markdown编辑器等 12 | 13 | 后端项目地址:https://github.com/caiheping/egg-cms 14 | 15 | ## 项目运行 16 | 17 | ### 后端项目运行 18 | 19 | 请移到:https://github.com/caiheping/egg-cms 20 | 21 | ### 前端项目运行 22 | 23 | > git clone https://github.com/caiheping/vue-cms.git 24 | > 25 | > 如果clone代码慢可以clone码云的仓库 26 | > 27 | > git clone https://gitee.com/caiheping/vue-cms.git 28 | > 29 | > cd ./vue-cms 30 | > 31 | > npm install 32 | > 33 | > npm run serve 34 | 35 | 36 | ## 项目功能 37 | 38 | - [x] 登录 -- 完成 39 | - [x] 首页 -- 去我的博客 40 | - [x] 文章列表 -- 增删改查 41 | - [x] 文章类型 -- 增删改查 42 | - [x] 用户中心 -- 增删改查 43 | - [x] 角色管理 -- 增删改查 44 | - [x] 菜单管理 -- 增删改查 45 | - [x] 部门管理 -- 增删改查 46 | - [x] 通知公告 -- 增删改查 47 | - [x] 头像上传 -- 完成 48 | - [x] 我的博客前端界面(知道地址后无需登录就可以进入) 49 | 50 | 51 | 52 | ### 目录结构 53 | 54 | 演示地址:http://blog.caihp.top (自己服务器只开放部分功能,想要查看全部功能,请copy代码在自己的电脑上看) 55 | 56 | 用户名: test 57 | 58 | 密码:123456 59 | 60 | ## 界面截图 61 | 62 | **登录页** 63 | 64 |  65 | 66 | **首页** 67 | 68 |  69 | 70 | 71 | 72 | **博客管理 > 文章列表** 73 | 74 |  75 | 76 | **博客管理 > 文章类型** 77 | 78 |  79 | 80 | 81 | 82 | **博客管理 > 友情链接** 83 | 84 |  85 | 86 | 87 | 88 | **系统管理 > 用户管理** 89 | 90 |  91 | 92 | 93 | 94 | **系统管理 > 角色管理** 95 | 96 |  97 | 98 | 99 | 100 | **系统管理 > 菜单管理** 101 | 102 |  103 | 104 | 105 | 106 | **系统管理 > 部门管理** 107 | 108 |  109 | 110 | 111 | 112 | **系统管理 > 字典管理** 113 | 114 |  115 | 116 | 117 | 118 | **系统管理 > 通知公告** 119 | 120 |  121 | 122 | 123 | 124 | **我的博客 > 首页** 125 | 126 |  127 | 128 | 129 | 130 | **我的博客 > 文章详情** 131 | 132 |  133 | 134 | 135 | 136 | 如果对您有帮助,您可以点右上角 "Star" 支持一下 谢谢! ^_^ 137 | -------------------------------------------------------------------------------- /src/static/icons/svg/dict.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/views/admin/layout/components/Settings/index.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 系统布局配置 5 | 6 | 7 | 主题颜色 8 | 9 | 10 | 11 | 12 | 开启 Tags-Views 13 | 14 | 15 | 16 | 17 | 固定 Header 18 | 19 | 20 | 21 | 22 | 显示 Logo 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 83 | 84 | 109 | -------------------------------------------------------------------------------- /src/static/icons/svg/time-range.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/static/icons/svg/system.svg: -------------------------------------------------------------------------------- 1 | 3 | --------------------------------------------------------------------------------