├── src ├── constants │ └── .gitignore ├── assets │ ├── logo.png │ ├── icons │ │ ├── iconfont.eot │ │ ├── iconfont.ttf │ │ ├── iconfont.woff │ │ ├── demo_fontclass.html │ │ ├── demo.css │ │ ├── demo_unicode.html │ │ ├── iconfont.css │ │ └── demo_symbol.html │ └── image │ │ └── file_type_icon.png ├── views │ ├── userManage │ │ └── admin │ │ │ └── router.vue │ ├── profile │ │ └── index.vue │ ├── components │ │ ├── tinymce-demo.vue │ │ ├── uploadList.vue │ │ └── upload-demo.vue │ ├── home │ │ ├── TabsView.vue │ │ ├── main.vue │ │ └── SidebarItem.vue │ ├── error │ │ ├── err404.vue │ │ ├── err500.vue │ │ └── err401.vue │ └── login │ │ └── index.vue ├── store │ ├── actions.js │ ├── getters.js │ ├── index.js │ ├── mutation-types.js │ └── modules │ │ ├── app.js │ │ └── admin.js ├── config │ └── app.js ├── App.vue ├── mock │ ├── fileResourceTag.js │ ├── upload.js │ ├── login.js │ ├── authAdmin.js │ ├── fileResource.js │ ├── adSite.js │ ├── index.js │ ├── ad.js │ └── authRole.js ├── api │ ├── file │ │ ├── fileResource.js │ │ ├── upload.js │ │ └── fileResourceTag.js │ ├── ad │ │ ├── ad.js │ │ └── adSite.js │ └── auth │ │ ├── login.js │ │ ├── authPermissionRule.js │ │ ├── authAdmin.js │ │ └── authRole.js ├── components │ ├── Tinymce │ │ ├── toolbar.js │ │ ├── plugins.js │ │ └── index.vue │ ├── common │ │ └── IconSvg.vue │ ├── HelloWorld.vue │ └── File │ │ └── Upload1.vue ├── utils │ ├── auth.js │ ├── store.js │ └── axios.js ├── main.js ├── element.js ├── styles │ ├── mixin.scss │ └── base.scss ├── filtres │ └── index.js ├── role.js └── router │ └── index.js ├── babel.config.js ├── .postcssrc.js ├── public ├── favicon.ico ├── tinymce4.7.5 │ ├── skins │ │ └── lightgray │ │ │ ├── img │ │ │ ├── anchor.gif │ │ │ ├── loader.gif │ │ │ ├── object.gif │ │ │ └── trans.gif │ │ │ ├── fonts │ │ │ ├── tinymce.eot │ │ │ ├── tinymce.ttf │ │ │ ├── tinymce.woff │ │ │ ├── tinymce-small.eot │ │ │ ├── tinymce-small.ttf │ │ │ ├── tinymce-small.woff │ │ │ └── tinymce-mobile.woff │ │ │ ├── content.inline.min.css │ │ │ └── content.min.css │ └── plugins │ │ ├── emoticons │ │ └── img │ │ │ ├── smiley-cool.gif │ │ │ ├── smiley-cry.gif │ │ │ ├── smiley-kiss.gif │ │ │ ├── smiley-wink.gif │ │ │ ├── smiley-yell.gif │ │ │ ├── smiley-frown.gif │ │ │ ├── smiley-sealed.gif │ │ │ ├── smiley-smile.gif │ │ │ ├── smiley-innocent.gif │ │ │ ├── smiley-laughing.gif │ │ │ ├── smiley-surprised.gif │ │ │ ├── smiley-undecided.gif │ │ │ ├── smiley-embarassed.gif │ │ │ ├── smiley-money-mouth.gif │ │ │ ├── smiley-tongue-out.gif │ │ │ └── smiley-foot-in-mouth.gif │ │ ├── codesample │ │ └── css │ │ │ └── prism.css │ │ └── visualblocks │ │ └── css │ │ └── visualblocks.css ├── index-dev.html └── index.html ├── .env.development ├── .env.production ├── .env.stage ├── tests └── unit │ ├── .eslintrc.js │ └── HelloWorld.spec.js ├── .editorconfig ├── .gitignore ├── .eslintrc.js ├── jest.config.js ├── vue.config.js ├── LICENSE ├── package.json └── README.md /src/constants/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ["@vue/app"] 3 | }; 4 | -------------------------------------------------------------------------------- /.postcssrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | autoprefixer: {} 4 | } 5 | } -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/src/assets/logo.png -------------------------------------------------------------------------------- /src/views/userManage/admin/router.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /.env.development: -------------------------------------------------------------------------------- 1 | VUE_APP_API_BASE=http://localhost:9998 2 | template=./public/index-dev.html 3 | outputDir=serve 4 | -------------------------------------------------------------------------------- /src/assets/icons/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/src/assets/icons/iconfont.eot -------------------------------------------------------------------------------- /src/assets/icons/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/src/assets/icons/iconfont.ttf -------------------------------------------------------------------------------- /src/assets/icons/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/src/assets/icons/iconfont.woff -------------------------------------------------------------------------------- /src/assets/image/file_type_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/src/assets/image/file_type_icon.png -------------------------------------------------------------------------------- /.env.production: -------------------------------------------------------------------------------- 1 | VUE_APP_API_BASE=http://localhost/vue-admin-php/public/index.php 2 | template=./public/index.html 3 | outputDir=dist 4 | -------------------------------------------------------------------------------- /.env.stage: -------------------------------------------------------------------------------- 1 | VUE_APP_API_BASE=http://localhost/vue-admin-php/public/index.php 2 | template=./public/index.html 3 | NODE_ENV=production 4 | outputDir=stage 5 | -------------------------------------------------------------------------------- /public/tinymce4.7.5/skins/lightgray/img/anchor.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/tinymce4.7.5/skins/lightgray/img/anchor.gif -------------------------------------------------------------------------------- /public/tinymce4.7.5/skins/lightgray/img/loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/tinymce4.7.5/skins/lightgray/img/loader.gif -------------------------------------------------------------------------------- /public/tinymce4.7.5/skins/lightgray/img/object.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/tinymce4.7.5/skins/lightgray/img/object.gif -------------------------------------------------------------------------------- /public/tinymce4.7.5/skins/lightgray/img/trans.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/tinymce4.7.5/skins/lightgray/img/trans.gif -------------------------------------------------------------------------------- /tests/unit/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | jest: true 4 | }, 5 | rules: { 6 | 'import/no-extraneous-dependencies': 'off' 7 | } 8 | } -------------------------------------------------------------------------------- /public/tinymce4.7.5/skins/lightgray/fonts/tinymce.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/tinymce4.7.5/skins/lightgray/fonts/tinymce.eot -------------------------------------------------------------------------------- /public/tinymce4.7.5/skins/lightgray/fonts/tinymce.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/tinymce4.7.5/skins/lightgray/fonts/tinymce.ttf -------------------------------------------------------------------------------- /public/tinymce4.7.5/skins/lightgray/fonts/tinymce.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/tinymce4.7.5/skins/lightgray/fonts/tinymce.woff -------------------------------------------------------------------------------- /public/tinymce4.7.5/plugins/emoticons/img/smiley-cool.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/tinymce4.7.5/plugins/emoticons/img/smiley-cool.gif -------------------------------------------------------------------------------- /public/tinymce4.7.5/plugins/emoticons/img/smiley-cry.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/tinymce4.7.5/plugins/emoticons/img/smiley-cry.gif -------------------------------------------------------------------------------- /public/tinymce4.7.5/plugins/emoticons/img/smiley-kiss.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/tinymce4.7.5/plugins/emoticons/img/smiley-kiss.gif -------------------------------------------------------------------------------- /public/tinymce4.7.5/plugins/emoticons/img/smiley-wink.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/tinymce4.7.5/plugins/emoticons/img/smiley-wink.gif -------------------------------------------------------------------------------- /public/tinymce4.7.5/plugins/emoticons/img/smiley-yell.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/tinymce4.7.5/plugins/emoticons/img/smiley-yell.gif -------------------------------------------------------------------------------- /public/tinymce4.7.5/plugins/emoticons/img/smiley-frown.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/tinymce4.7.5/plugins/emoticons/img/smiley-frown.gif -------------------------------------------------------------------------------- /public/tinymce4.7.5/plugins/emoticons/img/smiley-sealed.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/tinymce4.7.5/plugins/emoticons/img/smiley-sealed.gif -------------------------------------------------------------------------------- /public/tinymce4.7.5/plugins/emoticons/img/smiley-smile.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/tinymce4.7.5/plugins/emoticons/img/smiley-smile.gif -------------------------------------------------------------------------------- /public/tinymce4.7.5/skins/lightgray/fonts/tinymce-small.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/tinymce4.7.5/skins/lightgray/fonts/tinymce-small.eot -------------------------------------------------------------------------------- /public/tinymce4.7.5/skins/lightgray/fonts/tinymce-small.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/tinymce4.7.5/skins/lightgray/fonts/tinymce-small.ttf -------------------------------------------------------------------------------- /public/tinymce4.7.5/skins/lightgray/fonts/tinymce-small.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/tinymce4.7.5/skins/lightgray/fonts/tinymce-small.woff -------------------------------------------------------------------------------- /public/tinymce4.7.5/plugins/emoticons/img/smiley-innocent.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/tinymce4.7.5/plugins/emoticons/img/smiley-innocent.gif -------------------------------------------------------------------------------- /public/tinymce4.7.5/plugins/emoticons/img/smiley-laughing.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/tinymce4.7.5/plugins/emoticons/img/smiley-laughing.gif -------------------------------------------------------------------------------- /public/tinymce4.7.5/plugins/emoticons/img/smiley-surprised.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/tinymce4.7.5/plugins/emoticons/img/smiley-surprised.gif -------------------------------------------------------------------------------- /public/tinymce4.7.5/plugins/emoticons/img/smiley-undecided.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/tinymce4.7.5/plugins/emoticons/img/smiley-undecided.gif -------------------------------------------------------------------------------- /public/tinymce4.7.5/skins/lightgray/fonts/tinymce-mobile.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/tinymce4.7.5/skins/lightgray/fonts/tinymce-mobile.woff -------------------------------------------------------------------------------- /public/tinymce4.7.5/plugins/emoticons/img/smiley-embarassed.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/tinymce4.7.5/plugins/emoticons/img/smiley-embarassed.gif -------------------------------------------------------------------------------- /public/tinymce4.7.5/plugins/emoticons/img/smiley-money-mouth.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/tinymce4.7.5/plugins/emoticons/img/smiley-money-mouth.gif -------------------------------------------------------------------------------- /public/tinymce4.7.5/plugins/emoticons/img/smiley-tongue-out.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/tinymce4.7.5/plugins/emoticons/img/smiley-tongue-out.gif -------------------------------------------------------------------------------- /public/tinymce4.7.5/plugins/emoticons/img/smiley-foot-in-mouth.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lmxdawn/vue-admin-html-java/HEAD/public/tinymce4.7.5/plugins/emoticons/img/smiley-foot-in-mouth.gif -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /src/store/actions.js: -------------------------------------------------------------------------------- 1 | // import * as types from './mutation-types' 2 | // 3 | // export const addToCart = ({ commit }, product) => { 4 | // if (product.inventory > 0) { 5 | // commit(types.ADD_TO_CART, { 6 | // id: product.id 7 | // }) 8 | // } 9 | // } 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | /stage 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | 15 | # Editor directories and files 16 | .idea 17 | .vscode 18 | *.suo 19 | *.ntvs* 20 | *.njsproj 21 | *.sln 22 | *.sw* 23 | -------------------------------------------------------------------------------- /src/store/getters.js: -------------------------------------------------------------------------------- 1 | // export const cartProducts = state => { 2 | // return state.cart.added.map(({ id, quantity }) => { 3 | // const product = state.products.all.find(p => p.id === id) 4 | // return { 5 | // title: product.title, 6 | // price: product.price, 7 | // quantity 8 | // } 9 | // }) 10 | // } 11 | -------------------------------------------------------------------------------- /src/config/app.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 配置编译环境和线上环境之间的切换 3 | * 4 | * baseUrl: 域名地址 5 | * routerMode: 路由模式 6 | * imgBaseUrl: 图片所在域名地址 7 | * 8 | */ 9 | let BASE_URL = process.env.VUE_APP_API_BASE; 10 | // let ROUTER_MODE = "history"; 11 | let ROUTER_MODE = ""; 12 | let IMG_BASE_URL = BASE_URL; 13 | export { BASE_URL, ROUTER_MODE, IMG_BASE_URL }; 14 | -------------------------------------------------------------------------------- /src/views/profile/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 19 | 20 | 21 | 23 | -------------------------------------------------------------------------------- /tests/unit/HelloWorld.spec.js: -------------------------------------------------------------------------------- 1 | import { shallowMount } from "@vue/test-utils"; 2 | import HelloWorld from "@/components/HelloWorld.vue"; 3 | 4 | describe("HelloWorld.vue", () => { 5 | it("renders props.msg when passed", () => { 6 | const msg = "new message"; 7 | const wrapper = shallowMount(HelloWorld, { 8 | propsData: { msg } 9 | }); 10 | expect(wrapper.text()).toMatch(msg); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 26 | -------------------------------------------------------------------------------- /src/mock/fileResourceTag.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lk on 18/4/28. 3 | */ 4 | 5 | // 资源分组列表 6 | const index = { 7 | data: { 8 | total: 1, 9 | list: [ 10 | { 11 | id: 1, 12 | tag: "sss" 13 | } 14 | ] 15 | } 16 | }; 17 | 18 | // 新建资源分组 19 | const add = { 20 | data: { 21 | id: 2 22 | } 23 | }; 24 | 25 | export default { 26 | index, 27 | add 28 | }; 29 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | 'extends': [ 7 | 'plugin:vue/essential', 8 | '@vue/prettier' 9 | ], 10 | plugins: [ 11 | 'vue' 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 | parserOptions: { 18 | parser: 'babel-eslint' 19 | } 20 | } -------------------------------------------------------------------------------- /src/api/file/fileResource.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 资源管理相关 3 | */ 4 | import axios from "../../utils/axios"; 5 | 6 | // 列表 7 | export function fileResourceList(query) { 8 | return axios({ 9 | url: "/admin/file/resource/index", 10 | method: "get", 11 | params: query 12 | }); 13 | } 14 | // 添加 15 | export function fileResourceAdd(data) { 16 | return axios({ 17 | url: "/admin/file/resource/add", 18 | method: "POST", 19 | data: data 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /src/api/file/upload.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 上传相关 3 | */ 4 | import axios from "../../utils/axios"; 5 | 6 | // 获取七牛上传 upToken 7 | export function qiuNiuUpToken(query) { 8 | return axios({ 9 | url: "/admin/file/upload/qiuNiuUpToken", 10 | method: "get", 11 | params: query 12 | }); 13 | } 14 | 15 | // 上传文件 16 | export function createFile(url, formdata) { 17 | return axios({ 18 | url: url, 19 | method: "post", 20 | data: formdata 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /public/index-dev.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | VUE后台管理系统 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/api/file/fileResourceTag.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 资源分组相关 3 | */ 4 | import axios from "../../utils/axios"; 5 | 6 | // 列表 7 | export function fileResourceTagList(query) { 8 | return axios({ 9 | url: "/admin/file/resource_tag/index", 10 | method: "get", 11 | params: query 12 | }); 13 | } 14 | 15 | // 创建分组 16 | export function fileResourceTagAdd(data) { 17 | return axios({ 18 | url: "/admin/file/resource_tag/add", 19 | method: "post", 20 | data: data 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /src/components/Tinymce/toolbar.js: -------------------------------------------------------------------------------- 1 | // Here is a list of the toolbar 2 | // Detail list see https://www.tinymce.com/docs/advanced/editor-control-identifiers/#toolbarcontrols 3 | 4 | const toolbar = [ 5 | "searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote undo redo removeformat subscript superscript code codesample", 6 | "hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen" 7 | ]; 8 | 9 | export default toolbar; 10 | -------------------------------------------------------------------------------- /src/components/common/IconSvg.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 23 | 24 | 26 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleFileExtensions: ["js", "jsx", "json", "vue"], 3 | transform: { 4 | "^.+\\.vue$": "vue-jest", 5 | ".+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$": 6 | "jest-transform-stub", 7 | "^.+\\.jsx?$": "babel-jest" 8 | }, 9 | moduleNameMapper: { 10 | "^@/(.*)$": "/src/$1" 11 | }, 12 | snapshotSerializers: ["jest-serializer-vue"], 13 | testMatch: [ 14 | "/(tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx))" 15 | ] 16 | }; 17 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import Vuex from "vuex"; 3 | import * as actions from "./actions"; 4 | import * as getters from "./getters"; 5 | import app from "./modules/app"; 6 | import admin from "./modules/admin"; 7 | 8 | if (process.env.NODE_ENV === "development") { 9 | Vue.use(Vuex); 10 | } 11 | 12 | const debug = process.env.NODE_ENV !== "production"; 13 | 14 | export default new Vuex.Store({ 15 | actions, 16 | getters, 17 | modules: { 18 | app, 19 | admin 20 | }, 21 | strict: debug 22 | // plugins: debug ? [createLogger()] : [] 23 | }); 24 | -------------------------------------------------------------------------------- /src/mock/upload.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lk on 18/4/28. 3 | */ 4 | 5 | // 获取七牛云 6 | const qiuNiuUpToken = { 7 | data: { 8 | domain: "https://res.xxxxx.cn", 9 | expires_in: 86400, 10 | upToken: 11 | "GRUuplbSg1DrFbLlx2UPc0Qe0oIcIdqVRPgQ6i:nPJdU3WUHFcu5MSc4EOY8RSThGE=:eyJzY29wZSI6InNoaWd1YW5namkiLCJkZWFkbGluZSI6MTU0MzQ2NzcyN30=", 12 | uploadUrl: "/admin/file/upload/createFile" 13 | } 14 | }; 15 | 16 | // 上传文件 17 | const createFile = { 18 | key: "TIMjieTu_20180516105525-fu_ben_.png" 19 | }; 20 | 21 | export default { 22 | qiuNiuUpToken, 23 | createFile 24 | }; 25 | -------------------------------------------------------------------------------- /src/components/Tinymce/plugins.js: -------------------------------------------------------------------------------- 1 | // Any plugins you want to use has to be imported 2 | // Detail plugins list see https://www.tinymce.com/docs/plugins/ 3 | // Custom builds see https://www.tinymce.com/download/custom-builds/ 4 | 5 | const plugins = [ 6 | "advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools importcss insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount" 7 | ]; 8 | 9 | export default plugins; 10 | -------------------------------------------------------------------------------- /src/store/mutation-types.js: -------------------------------------------------------------------------------- 1 | // APP 相关 2 | export const TOGGLE_SIDEBAR = "TOGGLE_SIDEBAR"; 3 | export const SHOW_SIDEBAR = "SHOW_SIDEBAR"; 4 | export const ADD_VISITED_VIEWS = "ADD_VISITED_VIEWS"; 5 | export const DEL_VISITED_VIEWS = "DEL_VISITED_VIEWS"; 6 | 7 | // user(用户)相关 8 | export const RECEIVE_ADMIN_ID = "RECEIVE_ADMIN_ID"; // 用户ID 9 | export const RECEIVE_ADMIN_TOKEN = "RECEIVE_ADMIN_TOKEN"; // token 10 | export const RECEIVE_ADMIN_NAME = "RECEIVE_ADMIN_NAME"; // 昵称 11 | export const RECEIVE_ADMIN_AVATAR = "RECEIVE_ADMIN_AVATAR"; // 头像 12 | export const RECEIVE_ADMIN_AUTH_RULES = "RECEIVE_ADMIN_AUTH_RULES"; // 权限列表 13 | export const RECEIVE_ROUTERS = "RECEIVE_ROUTERS"; // 初始化路由表 14 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | baseUrl: process.env.NODE_ENV === "production" ? "./" : "/", 3 | outputDir: process.env.outputDir, 4 | configureWebpack: config => { 5 | if (process.env.NODE_ENV === "production") { 6 | // 为生产环境修改配置... 7 | config.externals = { 8 | vue: "Vue", 9 | vuex: "Vuex", 10 | "vue-router": "VueRouter", 11 | "element-ui": "ELEMENT" 12 | }; 13 | } else { 14 | // 为开发环境修改配置... 15 | } 16 | }, 17 | chainWebpack: config => { 18 | config.plugin("html").tap(args => { 19 | args[0].template = process.env.template; 20 | return args; 21 | }); 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /src/api/ad/ad.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lk on 17/6/4. 3 | */ 4 | import axios from "../../utils/axios"; 5 | 6 | // 谁最懂我相关 7 | 8 | // 列表 9 | export function adList(query) { 10 | return axios({ 11 | url: "/admin/ad/ad/index", 12 | method: "get", 13 | params: query 14 | }); 15 | } 16 | 17 | // 保存 18 | export function adSave(data, formName, method = "post") { 19 | var url = formName === "add" ? "/admin/ad/ad/save" : "/admin/ad/ad/edit"; 20 | return axios({ 21 | url: url, 22 | method: method, 23 | data: data 24 | }); 25 | } 26 | 27 | // 删除 28 | export function adDelete(data) { 29 | return axios({ 30 | url: "/admin/ad/ad/delete", 31 | method: "post", 32 | data: data 33 | }); 34 | } 35 | -------------------------------------------------------------------------------- /src/utils/auth.js: -------------------------------------------------------------------------------- 1 | import { getStore, setStore, removeStore } from "./store"; 2 | 3 | const adminId = "ADMIN-ID"; 4 | const adminToken = "ADMIN-TOKEN"; 5 | 6 | // 获取token 7 | export function getToken() { 8 | return getStore(adminToken); 9 | } 10 | 11 | // 设置token 12 | export function setToken(sid) { 13 | return setStore(adminToken, sid, 365); 14 | } 15 | 16 | // 删除token 17 | export function removeToken() { 18 | return removeStore(adminToken); 19 | } 20 | 21 | // 获取admin_id 22 | export function getAdminId() { 23 | return getStore(adminId); 24 | } 25 | 26 | // 设置admin_id 27 | export function setAdminId(id) { 28 | return setStore(adminId, id, 365); 29 | } 30 | 31 | // 删除admin_id 32 | export function removeAdminId() { 33 | return removeStore(adminId); 34 | } 35 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import "babel-polyfill"; // 解决Ie9 2 | import Vue from "vue"; 3 | import App from "./App.vue"; 4 | import router from "./router/index"; 5 | import store from "./store/index"; 6 | import "./element"; 7 | import * as filters from "./filtres/index"; // 全局过滤器 8 | import "./role"; // 权限 9 | 10 | import "./mock"; // 模拟数据 11 | 12 | import "./assets/icons/iconfont"; 13 | import IconSvg from "./components/common/IconSvg.vue"; // svg组件 14 | 15 | // 注册全局组件(register global) 16 | Vue.component("icon-svg", IconSvg); 17 | 18 | // 注册全局实用程序过滤器(register global utility filters). 19 | Object.keys(filters).forEach(key => { 20 | Vue.filter(key, filters[key]); 21 | }); 22 | 23 | Vue.config.productionTip = false; 24 | new Vue({ 25 | router, 26 | store, 27 | render: h => h(App) 28 | }).$mount("#app"); 29 | -------------------------------------------------------------------------------- /src/utils/store.js: -------------------------------------------------------------------------------- 1 | import Cookies from "js-cookie"; 2 | /** 3 | * 存储localStorage 4 | */ 5 | export const setStore = (name, content, expireDay) => { 6 | if (!name) return; 7 | if (typeof content !== "string") { 8 | content = JSON.stringify(content); 9 | } 10 | Cookies.set(name, content, { expires: expireDay }); 11 | }; 12 | 13 | /** 14 | * 获取localStorage 15 | */ 16 | export const getStore = name => { 17 | if (!name) return; 18 | let content = Cookies.get(name); 19 | try { 20 | content = JSON.parse(content); 21 | return content; 22 | } catch (e) { 23 | return content; 24 | } 25 | }; 26 | 27 | /** 28 | * 删除localStorage 29 | */ 30 | export const removeStore = name => { 31 | if (!name) return; 32 | Cookies.remove(name); 33 | }; 34 | -------------------------------------------------------------------------------- /src/mock/login.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lk on 18/4/28. 3 | */ 4 | 5 | const index = { 6 | data: { 7 | id: 1, 8 | token: 9 | "eyJpZHNzIjoiJDJ5JDEwJGNmMVpVb3BxM2lEUUk0bllVZXkxenUzajM0QVJlYmEuS3B4aDZ1MkNkY1J4clF6SE10MTRLIn0=_2018-04-27" 10 | } 11 | }; 12 | 13 | const userInfo = { 14 | data: { 15 | status: "1", 16 | id: 1, 17 | username: "admin", 18 | avatar: "", 19 | authRules: ["admin"], 20 | token: 21 | "eyJpZHNzIjoiJDJ5JDEwJGNmMVpVb3BxM2lEUUk0bllVZXkxenUzajM0QVJlYmEuS3B4aDZ1MkNkY1J4clF6SE10MTRLIn0=_2018-04-27" 22 | } 23 | }; 24 | 25 | const out = { code: 0, message: "success" }; 26 | 27 | const password = { code: 0, message: "success" }; 28 | 29 | export default { 30 | index, 31 | userInfo, 32 | out, 33 | password 34 | }; 35 | -------------------------------------------------------------------------------- /src/api/auth/login.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lk on 17/6/4. 3 | */ 4 | import axios from "../../utils/axios"; 5 | // 获取信息 6 | export function userInfo(id, token) { 7 | return axios({ 8 | url: "/admin/auth/login/userInfo", 9 | method: "get", 10 | params: { id, token } 11 | }); 12 | } 13 | 14 | export function loginName(userName, pwd) { 15 | return axios({ 16 | url: "/admin/auth/login/index", 17 | method: "post", 18 | data: { userName, pwd } 19 | }); 20 | } 21 | 22 | export function logout(uid, token) { 23 | return axios({ 24 | url: "/admin/auth/login/out", 25 | method: "post", 26 | data: { uid, token } 27 | }); 28 | } 29 | 30 | export function password(data) { 31 | return axios({ 32 | url: "/admin/auth/login/password", 33 | method: "post", 34 | data: data 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /src/api/auth/authPermissionRule.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lk on 17/6/4. 3 | */ 4 | import axios from "../../utils/axios"; 5 | 6 | // 权限管理 7 | 8 | // 获取列表 9 | export function authPermissionRuleList(query) { 10 | return axios({ 11 | url: "/admin/auth/permission_rule/index", 12 | method: "get", 13 | params: query 14 | }); 15 | } 16 | 17 | // 保存 18 | export function authPermissionRuleSave(data, formName, method = "post") { 19 | let url = 20 | formName !== "edit" 21 | ? "/admin/auth/permission_rule/save" 22 | : "/admin/auth/permission_rule/edit"; 23 | return axios({ 24 | url: url, 25 | method: method, 26 | data: data 27 | }); 28 | } 29 | 30 | // 删除 31 | export function authPermissionRuleDelete(data) { 32 | return axios({ 33 | url: "/admin/auth/permission_rule/delete", 34 | method: "post", 35 | data: data 36 | }); 37 | } 38 | -------------------------------------------------------------------------------- /src/api/ad/adSite.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lk on 17/6/4. 3 | */ 4 | import axios from "../../utils/axios"; 5 | 6 | // 谁最懂我相关 7 | 8 | // 列表 9 | export function adSiteList(query) { 10 | return axios({ 11 | url: "/admin/ad/site/index", 12 | method: "get", 13 | params: query 14 | }); 15 | } 16 | 17 | // 广告列表 18 | export function adSiteAdList(data) { 19 | return axios({ 20 | url: "/admin/ad/site/adList", 21 | method: "post", 22 | data: data 23 | }); 24 | } 25 | 26 | // 保存 27 | export function adSiteSave(data, formName, method = "post") { 28 | var url = 29 | formName === "add" ? "/admin/ad/site/save" : "/admin/ad/site/edit"; 30 | return axios({ 31 | url: url, 32 | method: method, 33 | data: data 34 | }); 35 | } 36 | 37 | // 删除 38 | export function adSiteDelete(data) { 39 | return axios({ 40 | url: "/admin/ad/site/delete", 41 | method: "post", 42 | data: data 43 | }); 44 | } 45 | -------------------------------------------------------------------------------- /src/api/auth/authAdmin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lk on 17/6/4. 3 | */ 4 | import axios from "../../utils/axios"; 5 | 6 | // 获取列表 7 | export function authAdminList(query) { 8 | return axios({ 9 | url: "/admin/auth/admin/index", 10 | method: "get", 11 | params: query 12 | }); 13 | } 14 | 15 | // 获取角色列表 16 | export function authAdminRoleList(query) { 17 | return axios({ 18 | url: "/admin/auth/admin/roleList", 19 | method: "get", 20 | params: query 21 | }); 22 | } 23 | 24 | // 保存 25 | export function authAdminSave(data, formName, method = "post") { 26 | let url = 27 | formName === "add" 28 | ? "/admin/auth/admin/save" 29 | : "/admin/auth/admin/edit"; 30 | return axios({ 31 | url: url, 32 | method: method, 33 | data: data 34 | }); 35 | } 36 | 37 | // 删除管理员 38 | export function authAdminDelete(data) { 39 | return axios({ 40 | url: "/admin/auth/admin/delete", 41 | method: "post", 42 | data: data 43 | }); 44 | } 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 lmxdawn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/api/auth/authRole.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lk on 17/6/4. 3 | */ 4 | import axios from "../../utils/axios"; 5 | 6 | // 获取列表 7 | export function authRoleList(query) { 8 | return axios({ 9 | url: "/admin/auth/role/index", 10 | method: "get", 11 | params: query 12 | }); 13 | } 14 | 15 | // 编辑 16 | export function authRoleAuthList(query) { 17 | return axios({ 18 | url: "/admin/auth/role/authList", 19 | method: "get", 20 | params: query 21 | }); 22 | } 23 | 24 | // 添加 25 | export function authRoleAuth(data) { 26 | return axios({ 27 | url: "/admin/auth/role/auth", 28 | method: "post", 29 | data: data 30 | }); 31 | } 32 | 33 | // 保存 34 | export function authRoleSave(data, formName, method = "post") { 35 | let url = 36 | formName === "add" ? "/admin/auth/role/save" : "/admin/auth/role/edit"; 37 | return axios({ 38 | url: url, 39 | method: method, 40 | data: data 41 | }); 42 | } 43 | 44 | // 删除 45 | export function authRoleDelete(data) { 46 | return axios({ 47 | url: "/admin/auth/role/delete", 48 | method: "post", 49 | data: data 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /src/mock/authAdmin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lk on 18/4/28. 3 | */ 4 | 5 | const index = { 6 | data: { 7 | total: 1, 8 | list: [ 9 | { 10 | id: 1, 11 | username: "admin", 12 | avatar: null, 13 | tel: "admin", 14 | email: "lmxdawn@gmail.com", 15 | status: 1, 16 | lastLoginIp: "127.0.0.1", 17 | lastLoginTime: 1493103488, 18 | createTime: 1487868050, 19 | roles: [] 20 | } 21 | ] 22 | } 23 | }; 24 | 25 | const roleList = { 26 | data: { 27 | total: 1, 28 | list: [ 29 | { 30 | id: 1, 31 | name: "超级管理员" 32 | } 33 | ] 34 | } 35 | }; 36 | 37 | const save = { 38 | data: { 39 | id: "2", 40 | username: "test", 41 | password: "", 42 | status: "1", 43 | roles: [1] 44 | } 45 | }; 46 | 47 | const edit = { 48 | code: 0, 49 | message: "success" 50 | }; 51 | 52 | const del = { 53 | code: 0, 54 | message: "success" 55 | }; 56 | 57 | export default { 58 | index, 59 | roleList, 60 | save, 61 | edit, 62 | del 63 | }; 64 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-project", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "stage": "vue-cli-service build --mode stage", 8 | "build": "vue-cli-service build", 9 | "lint": "vue-cli-service lint", 10 | "test:unit": "vue-cli-service test:unit" 11 | }, 12 | "dependencies": { 13 | "axios": "^0.18.0", 14 | "babel-polyfill": "^6.26.0", 15 | "element-ui": "^2.8.2", 16 | "js-cookie": "^2.2.0", 17 | "mockjs": "^1.0.1-beta3", 18 | "nprogress": "^0.2.0", 19 | "vue": "^2.5.16", 20 | "vue-router": "^3.0.1", 21 | "vuedraggable": "^2.17.0", 22 | "vuex": "^3.0.1" 23 | }, 24 | "devDependencies": { 25 | "@vue/cli-plugin-babel": "^3.0.0-beta.15", 26 | "@vue/cli-plugin-eslint": "^3.0.0-beta.15", 27 | "@vue/cli-plugin-unit-jest": "^3.0.0-beta.15", 28 | "@vue/cli-service": "^3.0.0-beta.15", 29 | "@vue/eslint-config-prettier": "^3.0.0-rc.3", 30 | "@vue/test-utils": "^1.0.0-beta.16", 31 | "babel-core": "7.0.0-bridge.0", 32 | "babel-jest": "^23.0.1", 33 | "node-sass": "^4.9.0", 34 | "sass-loader": "^7.0.1", 35 | "vue-template-compiler": "^2.5.16" 36 | }, 37 | "browserslist": [ 38 | "> 1%", 39 | "last 2 versions", 40 | "not ie <= 8" 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /src/mock/fileResource.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lk on 18/4/28. 3 | */ 4 | 5 | // 资源列表 6 | const index = { 7 | data: { 8 | total: 10, 9 | list: [ 10 | { 11 | id: 1, 12 | type: 0, 13 | filename: "home_many.png", 14 | path: 15 | "resources/image/20180529/0b429c0d31011ec46f2328ac0ca29c15.png", 16 | size: 9705, 17 | ext: "png", 18 | createTime: false, 19 | url: 20 | "http://www.test.com/uploads/resources/image/20180529/0b429c0d31011ec46f2328ac0ca29c15.png" 21 | }, 22 | { 23 | id: 2, 24 | type: 0, 25 | filename: "homeManyPlay.png", 26 | path: 27 | "resources/image/20180529/2988116bffc258321a48909f48841028.png", 28 | size: 9665, 29 | ext: "png", 30 | createTime: 1527601051, 31 | url: 32 | "http://www.test.com/uploads/resources/image/20180529/2988116bffc258321a48909f48841028.png" 33 | } 34 | ] 35 | } 36 | }; 37 | 38 | // 上传资源 39 | const add = { 40 | data: { 41 | id: 11 42 | } 43 | }; 44 | 45 | export default { 46 | index, 47 | add 48 | }; 49 | -------------------------------------------------------------------------------- /src/views/components/tinymce-demo.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 48 | 49 | 50 | 52 | -------------------------------------------------------------------------------- /src/views/components/uploadList.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 22 | 51 | 52 | 53 | 55 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | VUE后台管理系统 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/utils/axios.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import { Message } from "element-ui"; 3 | import store from "../store/index"; 4 | import { BASE_URL } from "../config/app"; 5 | import router from "../router/index"; 6 | 7 | // 创建axios实例 8 | const service = axios.create({ 9 | baseURL: BASE_URL, // api的base_url 10 | timeout: 5000 // 请求超时时间 11 | }); 12 | 13 | // request拦截器 14 | service.interceptors.request.use( 15 | config => { 16 | // Do something before request is sent 17 | if (store.getters.adminId && store.getters.token) { 18 | config.headers["X-Adminid"] = store.getters.adminId; 19 | config.headers["X-Token"] = store.getters.token; 20 | } 21 | return config; 22 | }, 23 | error => { 24 | // Do something with request error 25 | Promise.reject(error); 26 | } 27 | ); 28 | 29 | // respone拦截器 30 | service.interceptors.response.use( 31 | response => { 32 | const data = response.data; 33 | if (data.code) { 34 | if (data.code === 2) { 35 | store.dispatch("fedLogout").then(() => { 36 | Message.error("验证失败,请重新登录"); 37 | router.push({ 38 | path: "/login", 39 | query: { redirect: router.currentRoute.fullPath } // 从哪个页面跳转过来 40 | }); 41 | }); 42 | } 43 | } 44 | return data; 45 | }, 46 | error => { 47 | Message({ 48 | message: error.message, 49 | type: "error", 50 | duration: 5 * 1000 51 | }); 52 | return Promise.reject(error); 53 | } 54 | ); 55 | 56 | export default service; 57 | -------------------------------------------------------------------------------- /src/store/modules/app.js: -------------------------------------------------------------------------------- 1 | import { getStore, setStore } from "../../utils/store"; 2 | import * as types from "../mutation-types"; 3 | 4 | const state = { 5 | sidebar: { 6 | opened: !+getStore("sidebarStatus") 7 | }, 8 | visitedViews: [] 9 | }; 10 | 11 | // getters 12 | const getters = { 13 | sidebar: state => state.sidebar, 14 | visitedViews: state => state.visitedViews 15 | }; 16 | 17 | // actions 18 | const actions = { 19 | ToggleSideBar({ commit }) { 20 | commit(types.TOGGLE_SIDEBAR); 21 | }, 22 | ShowSideBar({ commit }) { 23 | commit(types.SHOW_SIDEBAR); 24 | }, 25 | addVisitedViews({ commit }, view) { 26 | commit(types.ADD_VISITED_VIEWS, view); 27 | }, 28 | delVisitedViews({ commit, state }, view) { 29 | return new Promise(resolve => { 30 | commit(types.DEL_VISITED_VIEWS, view); 31 | resolve([...state.visitedViews]); 32 | }); 33 | } 34 | }; 35 | 36 | // mutations 37 | const mutations = { 38 | [types.TOGGLE_SIDEBAR](state) { 39 | if (state.sidebar.opened) { 40 | setStore("sidebarStatus", 1, 365); 41 | } else { 42 | setStore("sidebarStatus", 0, 365); 43 | } 44 | state.sidebar.opened = !state.sidebar.opened; 45 | }, 46 | [types.SHOW_SIDEBAR](state) { 47 | if (state.sidebar.opened) { 48 | setStore("sidebarStatus", 1, 365); 49 | } 50 | state.sidebar.opened = false; 51 | }, 52 | [types.ADD_VISITED_VIEWS](state, view) { 53 | if (state.visitedViews.some(v => v.path === view.path)) return; 54 | state.visitedViews.push({ name: view.name, path: view.path }); 55 | }, 56 | [types.DEL_VISITED_VIEWS](state, view) { 57 | let index; 58 | for (const [i, v] of state.visitedViews.entries()) { 59 | if (v.path === view.path) { 60 | index = i; 61 | break; 62 | } 63 | } 64 | state.visitedViews.splice(index, 1); 65 | } 66 | }; 67 | 68 | export default { 69 | state, 70 | getters, 71 | actions, 72 | mutations 73 | }; 74 | -------------------------------------------------------------------------------- /src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 41 | 42 | 43 | 59 | -------------------------------------------------------------------------------- /src/views/home/TabsView.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 66 | 67 | 84 | -------------------------------------------------------------------------------- /src/views/home/main.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 37 | 38 | 85 | -------------------------------------------------------------------------------- /src/mock/adSite.js: -------------------------------------------------------------------------------- 1 | const index = { 2 | data: { 3 | total: 1, 4 | list: [ 5 | { 6 | siteId: 1, 7 | siteName: "测试12222111", 8 | describe: "支持android和ios", 9 | adIds: [4, 1], 10 | ads: [ 11 | { 12 | adId: 4, 13 | title: "fffxxxx", 14 | describe: "vvv", 15 | status: 0 16 | }, 17 | { 18 | adId: 1, 19 | title: "阿范德萨", 20 | describe: "撒地方士大夫", 21 | status: 1 22 | } 23 | ] 24 | }, 25 | { 26 | siteId: 2, 27 | siteName: "车是是是", 28 | describe: "车是是是发发发", 29 | adIds: [1, 2, 4], 30 | ads: [ 31 | { 32 | adId: 1, 33 | title: "阿范德萨", 34 | describe: "撒地方士大夫", 35 | status: 1 36 | }, 37 | { 38 | adId: 2, 39 | title: "ffff", 40 | describe: "fff", 41 | status: 0 42 | }, 43 | { 44 | adId: 4, 45 | title: "fffxxxx", 46 | describe: "vvv", 47 | status: 0 48 | } 49 | ] 50 | } 51 | ] 52 | } 53 | }; 54 | 55 | const adList = { 56 | data: { 57 | total: 1, 58 | list: [ 59 | { 60 | adId: 1, 61 | title: "阿范德萨", 62 | describe: "撒地方士大夫", 63 | status: 1 64 | }, 65 | { 66 | adId: 6, 67 | title: "侧嗯嗯得到的", 68 | describe: "车次多的的", 69 | status: 1 70 | }, 71 | { 72 | adId: 7, 73 | title: "hi额接口数据东方丽景", 74 | describe: "反倒是打发士大夫撒", 75 | status: 1 76 | } 77 | ] 78 | } 79 | }; 80 | 81 | const save = { 82 | data: { 83 | siteId: 2 84 | } 85 | }; 86 | 87 | const edit = { 88 | code: 0, 89 | message: "success" 90 | }; 91 | 92 | const del = { 93 | code: 0, 94 | message: "success" 95 | }; 96 | 97 | export default { 98 | index, 99 | adList, 100 | save, 101 | edit, 102 | del 103 | }; 104 | -------------------------------------------------------------------------------- /public/tinymce4.7.5/plugins/codesample/css/prism.css: -------------------------------------------------------------------------------- 1 | /* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript */ 2 | /** 3 | * prism.js default theme for JavaScript, CSS and HTML 4 | * Based on dabblet (http://dabblet.com) 5 | * @author Lea Verou 6 | */ 7 | 8 | code[class*="language-"], 9 | pre[class*="language-"] { 10 | color: black; 11 | text-shadow: 0 1px white; 12 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 13 | direction: ltr; 14 | text-align: left; 15 | white-space: pre; 16 | word-spacing: normal; 17 | word-break: normal; 18 | word-wrap: normal; 19 | line-height: 1.5; 20 | 21 | -moz-tab-size: 4; 22 | -o-tab-size: 4; 23 | tab-size: 4; 24 | 25 | -webkit-hyphens: none; 26 | -moz-hyphens: none; 27 | -ms-hyphens: none; 28 | hyphens: none; 29 | } 30 | 31 | pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, 32 | code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { 33 | text-shadow: none; 34 | background: #b3d4fc; 35 | } 36 | 37 | pre[class*="language-"]::selection, pre[class*="language-"] ::selection, 38 | code[class*="language-"]::selection, code[class*="language-"] ::selection { 39 | text-shadow: none; 40 | background: #b3d4fc; 41 | } 42 | 43 | @media print { 44 | code[class*="language-"], 45 | pre[class*="language-"] { 46 | text-shadow: none; 47 | } 48 | } 49 | 50 | /* Code blocks */ 51 | pre[class*="language-"] { 52 | padding: 1em; 53 | margin: .5em 0; 54 | overflow: auto; 55 | } 56 | 57 | :not(pre) > code[class*="language-"], 58 | pre[class*="language-"] { 59 | background: #f5f2f0; 60 | } 61 | 62 | /* Inline code */ 63 | :not(pre) > code[class*="language-"] { 64 | padding: .1em; 65 | border-radius: .3em; 66 | } 67 | 68 | .token.comment, 69 | .token.prolog, 70 | .token.doctype, 71 | .token.cdata { 72 | color: slategray; 73 | } 74 | 75 | .token.punctuation { 76 | color: #999; 77 | } 78 | 79 | .namespace { 80 | opacity: .7; 81 | } 82 | 83 | .token.property, 84 | .token.tag, 85 | .token.boolean, 86 | .token.number, 87 | .token.constant, 88 | .token.symbol, 89 | .token.deleted { 90 | color: #905; 91 | } 92 | 93 | .token.selector, 94 | .token.attr-name, 95 | .token.string, 96 | .token.char, 97 | .token.builtin, 98 | .token.inserted { 99 | color: #690; 100 | } 101 | 102 | .token.operator, 103 | .token.entity, 104 | .token.url, 105 | .language-css .token.string, 106 | .style .token.string { 107 | color: #a67f59; 108 | background: hsla(0, 0%, 100%, .5); 109 | } 110 | 111 | .token.atrule, 112 | .token.attr-value, 113 | .token.keyword { 114 | color: #07a; 115 | } 116 | 117 | .token.function { 118 | color: #DD4A68; 119 | } 120 | 121 | .token.regex, 122 | .token.important, 123 | .token.variable { 124 | color: #e90; 125 | } 126 | 127 | .token.important, 128 | .token.bold { 129 | font-weight: bold; 130 | } 131 | .token.italic { 132 | font-style: italic; 133 | } 134 | 135 | .token.entity { 136 | cursor: help; 137 | } 138 | 139 | -------------------------------------------------------------------------------- /src/views/components/upload-demo.vue: -------------------------------------------------------------------------------- 1 | 42 | 43 | 44 | 85 | 86 | 87 | 97 | -------------------------------------------------------------------------------- /public/tinymce4.7.5/skins/lightgray/content.inline.min.css: -------------------------------------------------------------------------------- 1 | .word-wrap{word-wrap:break-word;-ms-word-break:break-all;word-break:break-all;word-break:break-word;-ms-hyphens:auto;-moz-hyphens:auto;-webkit-hyphens:auto;hyphens:auto}.mce-content-body .mce-reset{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:black;font-family:Arial;font-size:11px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;line-height:normal;font-weight:normal;text-align:left;-webkit-tap-highlight-color:transparent;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;direction:ltr;max-width:none}.mce-object{border:1px dotted #3A3A3A;background:#D5D5D5 url(img/object.gif) no-repeat center}.mce-preview-object{display:inline-block;position:relative;margin:0 2px 0 2px;line-height:0;border:1px solid gray}.mce-preview-object[data-mce-selected="2"] .mce-shim{display:none}.mce-preview-object .mce-shim{position:absolute;top:0;left:0;width:100%;height:100%;background:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)}figure.align-left{float:left}figure.align-right{float:right}figure.image.align-center{display:table;margin-left:auto;margin-right:auto}figure.image{display:inline-block;border:1px solid gray;margin:0 2px 0 1px;background:#f5f2f0}figure.image img{margin:8px 8px 0 8px}figure.image figcaption{margin:6px 8px 6px 8px;text-align:center}.mce-toc{border:1px solid gray}.mce-toc h2{margin:4px}.mce-toc li{list-style-type:none}.mce-pagebreak{cursor:default;display:block;border:0;width:100%;height:5px;border:1px dashed #666;margin-top:15px;page-break-before:always}@media print{.mce-pagebreak{border:0}}.mce-item-anchor{cursor:default;display:inline-block;-webkit-user-select:all;-webkit-user-modify:read-only;-moz-user-select:all;-moz-user-modify:read-only;user-select:all;user-modify:read-only;width:9px !important;height:9px !important;border:1px dotted #3A3A3A;background:#D5D5D5 url(img/anchor.gif) no-repeat center}.mce-nbsp,.mce-shy{background:#AAA}.mce-shy::after{content:'-'}.mce-match-marker{background:#AAA;color:#fff}.mce-match-marker-selected{background:#3399ff;color:#fff}.mce-spellchecker-word{border-bottom:2px solid rgba(208,2,27,0.5);cursor:default}.mce-spellchecker-grammar{border-bottom:2px solid #008000;cursor:default}.mce-item-table,.mce-item-table td,.mce-item-table th,.mce-item-table caption{border:1px dashed #BBB}td[data-mce-selected],th[data-mce-selected]{background-color:#2276d2 !important}.mce-edit-focus{outline:1px dotted #333}.mce-content-body *[contentEditable=false] *[contentEditable=true]:focus{outline:2px solid #2276d2}.mce-content-body *[contentEditable=false] *[contentEditable=true]:hover{outline:2px solid #2276d2}.mce-content-body *[contentEditable=false][data-mce-selected]{outline:2px solid #2276d2}.mce-content-body *[data-mce-selected="inline-boundary"]{background:#bfe6ff}.mce-content-body .mce-item-anchor[data-mce-selected]{background:#D5D5D5 url(img/anchor.gif) no-repeat center}.mce-content-body hr{cursor:default}.ephox-snooker-resizer-bar{background-color:#2276d2;opacity:0}.ephox-snooker-resizer-cols{cursor:col-resize}.ephox-snooker-resizer-rows{cursor:row-resize}.ephox-snooker-resizer-bar.ephox-snooker-resizer-bar-dragging{opacity:.2}.mce-content-body{line-height:1.3} -------------------------------------------------------------------------------- /src/mock/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by lk on 18/4/28. 3 | */ 4 | 5 | import Mock from "mockjs"; 6 | 7 | import login from "./login"; 8 | import authAdmin from "./authAdmin"; 9 | import authPermissionRule from "./authPermissionRule"; 10 | import authRole from "./authRole"; 11 | import upload from "./upload"; 12 | import fileResourceTag from "./fileResourceTag"; 13 | import fileResource from "./fileResource"; 14 | import adSite from "./adSite"; 15 | import ad from "./ad"; 16 | 17 | // 登录相关 18 | Mock.mock(/\/admin\/auth\/login\/out/, "post", login.out); 19 | Mock.mock(/\/admin\/auth\/login\/password/, "post", login.password); 20 | Mock.mock(/\/admin\/auth\/login\/index/, "post", login.index); 21 | Mock.mock(/\/admin\/auth\/login\/userInfo/, "get", login.userInfo); 22 | // 管理员相关 23 | Mock.mock(/\/admin\/auth\/admin\/index/, "get", authAdmin.index); 24 | Mock.mock(/\/admin\/auth\/admin\/roleList/, "get", authAdmin.roleList); 25 | Mock.mock(/\/admin\/auth\/admin\/save/, "post", authAdmin.save); 26 | Mock.mock(/\/admin\/auth\/admin\/edit/, "post", authAdmin.edit); 27 | Mock.mock(/\/admin\/auth\/admin\/delete/, "post", authAdmin.del); 28 | // 权限相关 29 | Mock.mock( 30 | /\/admin\/auth\/permission_rule\/index/, 31 | "get", 32 | authPermissionRule.index 33 | ); 34 | Mock.mock( 35 | /\/admin\/auth\/permission_rule\/save/, 36 | "post", 37 | authPermissionRule.save 38 | ); 39 | Mock.mock( 40 | /\/admin\/auth\/permission_rule\/edit/, 41 | "post", 42 | authPermissionRule.edit 43 | ); 44 | Mock.mock( 45 | /\/admin\/auth\/permission_rule\/delete/, 46 | "post", 47 | authPermissionRule.del 48 | ); 49 | // 角色相关 50 | Mock.mock(/\/admin\/auth\/role\/index/, "get", authRole.index); 51 | Mock.mock(/\/admin\/auth\/role\/save/, "post", authRole.save); 52 | Mock.mock(/\/admin\/auth\/role\/edit/, "post", authRole.edit); 53 | Mock.mock(/\/admin\/auth\/role\/delete/, "post", authRole.del); 54 | Mock.mock(/\/admin\/auth\/role\/authList/, "get", authRole.authList); 55 | Mock.mock(/\/admin\/auth\/role\/auth/, "post", authRole.auth); 56 | 57 | /** 58 | * 上传相关 59 | */ 60 | // 获取文件列表 61 | Mock.mock(/admin\/file\/upload\/qiuNiuUpToken/, "get", upload.qiuNiuUpToken); 62 | // 上传文件 63 | Mock.mock(/admin\/file\/upload\/createFile/, "post", upload.createFile); 64 | 65 | /** 66 | * 资源分组相关 67 | */ 68 | // 获取资源分组列表 69 | Mock.mock(/admin\/file\/resource_tag\/index/, "get", fileResourceTag.index); 70 | // 新建资源分组 71 | Mock.mock(/admin\/file\/resource_tag\/add/, "post", fileResourceTag.add); 72 | /** 73 | * 资源相关 74 | */ 75 | // 获取资源列表 76 | Mock.mock(/admin\/file\/resource\/index/, "get", fileResource.index); 77 | // 上传资源 78 | Mock.mock(/admin\/file\/resource\/add/, "post", fileResource.add); 79 | 80 | // 广告位相关 81 | Mock.mock(/\/admin\/ad\/site\/index/, "get", adSite.index); 82 | Mock.mock(/\/admin\/ad\/site\/adList/, "post", adSite.adList); 83 | Mock.mock(/\/admin\/ad\/site\/save/, "post", adSite.save); 84 | Mock.mock(/\/admin\/ad\/site\/edit/, "post", adSite.edit); 85 | Mock.mock(/\/admin\/ad\/site\/delete/, "post", adSite.del); 86 | // 广告相关 87 | Mock.mock(/\/admin\/ad\/ad\/index/, "get", ad.index); 88 | Mock.mock(/\/admin\/ad\/ad\/save/, "post", ad.save); 89 | Mock.mock(/\/admin\/ad\/ad\/edit/, "post", ad.edit); 90 | Mock.mock(/\/admin\/ad\/ad\/delete/, "post", ad.del); 91 | 92 | export default Mock; 93 | -------------------------------------------------------------------------------- /public/tinymce4.7.5/skins/lightgray/content.min.css: -------------------------------------------------------------------------------- 1 | body{background-color:#FFFFFF;color:#000000;font-family:Verdana,Arial,Helvetica,sans-serif;font-size:14px;line-height:1.3;scrollbar-3dlight-color:#F0F0EE;scrollbar-arrow-color:#676662;scrollbar-base-color:#F0F0EE;scrollbar-darkshadow-color:#DDDDDD;scrollbar-face-color:#E0E0DD;scrollbar-highlight-color:#F0F0EE;scrollbar-shadow-color:#F0F0EE;scrollbar-track-color:#F5F5F5}td,th{font-family:Verdana,Arial,Helvetica,sans-serif;font-size:14px}.word-wrap{word-wrap:break-word;-ms-word-break:break-all;word-break:break-all;word-break:break-word;-ms-hyphens:auto;-moz-hyphens:auto;-webkit-hyphens:auto;hyphens:auto}.mce-content-body .mce-reset{margin:0;padding:0;border:0;outline:0;vertical-align:top;background:transparent;text-decoration:none;color:black;font-family:Arial;font-size:11px;text-shadow:none;float:none;position:static;width:auto;height:auto;white-space:nowrap;cursor:inherit;line-height:normal;font-weight:normal;text-align:left;-webkit-tap-highlight-color:transparent;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;direction:ltr;max-width:none}.mce-object{border:1px dotted #3A3A3A;background:#D5D5D5 url(img/object.gif) no-repeat center}.mce-preview-object{display:inline-block;position:relative;margin:0 2px 0 2px;line-height:0;border:1px solid gray}.mce-preview-object[data-mce-selected="2"] .mce-shim{display:none}.mce-preview-object .mce-shim{position:absolute;top:0;left:0;width:100%;height:100%;background:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)}figure.align-left{float:left}figure.align-right{float:right}figure.image.align-center{display:table;margin-left:auto;margin-right:auto}figure.image{display:inline-block;border:1px solid gray;margin:0 2px 0 1px;background:#f5f2f0}figure.image img{margin:8px 8px 0 8px}figure.image figcaption{margin:6px 8px 6px 8px;text-align:center}.mce-toc{border:1px solid gray}.mce-toc h2{margin:4px}.mce-toc li{list-style-type:none}.mce-pagebreak{cursor:default;display:block;border:0;width:100%;height:5px;border:1px dashed #666;margin-top:15px;page-break-before:always}@media print{.mce-pagebreak{border:0}}.mce-item-anchor{cursor:default;display:inline-block;-webkit-user-select:all;-webkit-user-modify:read-only;-moz-user-select:all;-moz-user-modify:read-only;user-select:all;user-modify:read-only;width:9px !important;height:9px !important;border:1px dotted #3A3A3A;background:#D5D5D5 url(img/anchor.gif) no-repeat center}.mce-nbsp,.mce-shy{background:#AAA}.mce-shy::after{content:'-'}.mce-match-marker{background:#AAA;color:#fff}.mce-match-marker-selected{background:#3399ff;color:#fff}.mce-spellchecker-word{border-bottom:2px solid rgba(208,2,27,0.5);cursor:default}.mce-spellchecker-grammar{border-bottom:2px solid #008000;cursor:default}.mce-item-table,.mce-item-table td,.mce-item-table th,.mce-item-table caption{border:1px dashed #BBB}td[data-mce-selected],th[data-mce-selected]{background-color:#2276d2 !important}.mce-edit-focus{outline:1px dotted #333}.mce-content-body *[contentEditable=false] *[contentEditable=true]:focus{outline:2px solid #2276d2}.mce-content-body *[contentEditable=false] *[contentEditable=true]:hover{outline:2px solid #2276d2}.mce-content-body *[contentEditable=false][data-mce-selected]{outline:2px solid #2276d2}.mce-content-body *[data-mce-selected="inline-boundary"]{background:#bfe6ff}.mce-content-body .mce-item-anchor[data-mce-selected]{background:#D5D5D5 url(img/anchor.gif) no-repeat center}.mce-content-body hr{cursor:default}.ephox-snooker-resizer-bar{background-color:#2276d2;opacity:0}.ephox-snooker-resizer-cols{cursor:col-resize}.ephox-snooker-resizer-rows{cursor:row-resize}.ephox-snooker-resizer-bar.ephox-snooker-resizer-bar-dragging{opacity:.2} a {color: #1478F0;} 2 | -------------------------------------------------------------------------------- /src/element.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | // import "element-ui/lib/theme-chalk/index.css"; 3 | 4 | import ELEMENT from "element-ui"; 5 | import { 6 | Pagination, 7 | Dialog, 8 | Autocomplete, 9 | Dropdown, 10 | DropdownMenu, 11 | DropdownItem, 12 | Menu, 13 | Submenu, 14 | MenuItem, 15 | MenuItemGroup, 16 | Input, 17 | InputNumber, 18 | Radio, 19 | RadioGroup, 20 | RadioButton, 21 | Checkbox, 22 | CheckboxButton, 23 | CheckboxGroup, 24 | Switch, 25 | Select, 26 | Option, 27 | OptionGroup, 28 | Button, 29 | ButtonGroup, 30 | Table, 31 | TableColumn, 32 | DatePicker, 33 | TimeSelect, 34 | TimePicker, 35 | Popover, 36 | Tooltip, 37 | Breadcrumb, 38 | BreadcrumbItem, 39 | Form, 40 | FormItem, 41 | Tabs, 42 | TabPane, 43 | Tag, 44 | Tree, 45 | Alert, 46 | Slider, 47 | Icon, 48 | Row, 49 | Col, 50 | Upload, 51 | Progress, 52 | Badge, 53 | Card, 54 | Rate, 55 | Steps, 56 | Step, 57 | Carousel, 58 | CarouselItem, 59 | Collapse, 60 | CollapseItem, 61 | Cascader, 62 | ColorPicker, 63 | Transfer, 64 | Container, 65 | Header, 66 | Aside, 67 | Main, 68 | Footer, 69 | Loading, 70 | MessageBox, 71 | Message, 72 | Notification 73 | } from "element-ui"; 74 | 75 | if (process.env.NODE_ENV === "development") { 76 | require("element-ui/lib/theme-chalk/index.css"); 77 | Vue.use(ELEMENT); 78 | 79 | Vue.use(Pagination); 80 | Vue.use(Dialog); 81 | Vue.use(Autocomplete); 82 | Vue.use(Dropdown); 83 | Vue.use(DropdownMenu); 84 | Vue.use(DropdownItem); 85 | Vue.use(Menu); 86 | Vue.use(Submenu); 87 | Vue.use(MenuItem); 88 | Vue.use(MenuItemGroup); 89 | Vue.use(Input); 90 | Vue.use(InputNumber); 91 | Vue.use(Radio); 92 | Vue.use(RadioGroup); 93 | Vue.use(RadioButton); 94 | Vue.use(Checkbox); 95 | Vue.use(CheckboxButton); 96 | Vue.use(CheckboxGroup); 97 | Vue.use(Switch); 98 | Vue.use(Select); 99 | Vue.use(Option); 100 | Vue.use(OptionGroup); 101 | Vue.use(Button); 102 | Vue.use(ButtonGroup); 103 | Vue.use(Table); 104 | Vue.use(TableColumn); 105 | Vue.use(DatePicker); 106 | Vue.use(TimeSelect); 107 | Vue.use(TimePicker); 108 | Vue.use(Popover); 109 | Vue.use(Tooltip); 110 | Vue.use(Breadcrumb); 111 | Vue.use(BreadcrumbItem); 112 | Vue.use(Form); 113 | Vue.use(FormItem); 114 | Vue.use(Tabs); 115 | Vue.use(TabPane); 116 | Vue.use(Tag); 117 | Vue.use(Tree); 118 | Vue.use(Alert); 119 | Vue.use(Slider); 120 | Vue.use(Icon); 121 | Vue.use(Row); 122 | Vue.use(Col); 123 | Vue.use(Upload); 124 | Vue.use(Progress); 125 | Vue.use(Badge); 126 | Vue.use(Card); 127 | Vue.use(Rate); 128 | Vue.use(Steps); 129 | Vue.use(Step); 130 | Vue.use(Carousel); 131 | Vue.use(CarouselItem); 132 | Vue.use(Collapse); 133 | Vue.use(CollapseItem); 134 | Vue.use(Cascader); 135 | Vue.use(ColorPicker); 136 | Vue.use(Transfer); 137 | Vue.use(Container); 138 | Vue.use(Header); 139 | Vue.use(Aside); 140 | Vue.use(Main); 141 | Vue.use(Footer); 142 | 143 | Vue.use(Loading.directive); 144 | 145 | Vue.prototype.$loading = Loading.service; 146 | Vue.prototype.$msgbox = MessageBox; 147 | Vue.prototype.$alert = MessageBox.alert; 148 | Vue.prototype.$confirm = MessageBox.confirm; 149 | Vue.prototype.$prompt = MessageBox.prompt; 150 | Vue.prototype.$notify = Notification; 151 | Vue.prototype.$message = Message; 152 | } 153 | -------------------------------------------------------------------------------- /src/styles/mixin.scss: -------------------------------------------------------------------------------- 1 | 2 | // Mixin 3 | 4 | $font-color: #4a4a4a; 5 | //头部高度 6 | $header-height: 60px; 7 | //底部高度 8 | $footer-height: 1.30666666rem; 9 | 10 | //清除浮动 11 | @mixin clearfix() { 12 | &:before, 13 | &:after { 14 | content: " "; 15 | display: table; 16 | } 17 | &:after { 18 | clear: both; 19 | } 20 | } 21 | 22 | 23 | //水平居中 24 | @mixin center-block() { 25 | display: block; 26 | margin-left: auto; 27 | margin-right: auto; 28 | } 29 | 30 | //全屏定位 31 | @mixin fxied-absolute(){ 32 | position:absolute; 33 | top:0; 34 | right:0; 35 | } 36 | @mixin fxied-fixed(){ 37 | position:fixed; 38 | top:0; 39 | right:0; 40 | } 41 | @mixin fxied-bottom(){ 42 | position:fixed; 43 | bottom: 0; 44 | right: 0; 45 | } 46 | //定位上下左右居中 47 | @mixin fxied-center() { 48 | position: absolute; 49 | top: 50%; 50 | left: 50%; 51 | transform: translate(-50%, -50%); 52 | } 53 | //定位上下居中 54 | @mixin fxied-top() { 55 | position: absolute; 56 | top: 50%; 57 | transform: translateY(-50%); 58 | } 59 | //左右居中 60 | @mixin fxied-left() { 61 | position: absolute; 62 | left: 50%; 63 | transform: translateX(-50%); 64 | } 65 | 66 | 67 | //尺寸助手 68 | @mixin size($width, $height) { 69 | width: $width; 70 | height: $height; 71 | } 72 | //正方形 73 | @mixin square($size) { 74 | @include size($size, $size); 75 | } 76 | 77 | //调整大小的文本域 78 | @mixin resizable($direction: both) { 79 | // Options: horizontal, vertical, both 80 | resize: $direction; 81 | // Safari fix 82 | overflow: auto; 83 | } 84 | 85 | //截断文本 元素必须是 block 或 inline-block 级。 86 | @mixin text-overflow() { 87 | overflow: hidden; 88 | text-overflow: ellipsis; 89 | white-space: nowrap; 90 | } 91 | 92 | //视网膜屏幕(Retina)下的图片 93 | @mixin img-retina($file-1x, $file-2x, $width-1x, $height-1x) { 94 | background-image: url($file-1x); 95 | 96 | @media 97 | only screen and (-webkit-min-device-pixel-ratio: 2), 98 | only screen and ( min--moz-device-pixel-ratio: 2), 99 | only screen and ( -o-min-device-pixel-ratio: 2/1), 100 | only screen and ( min-device-pixel-ratio: 2), 101 | only screen and ( min-resolution: 192dpi), 102 | only screen and ( min-resolution: 2dppx) { 103 | background-image: url($file-2x); 104 | background-size: $width-1x $height-1x; 105 | } 106 | } 107 | 108 | //左右浮动 109 | @mixin f_left(){ 110 | float: left; 111 | } 112 | @mixin f_right(){ 113 | float: right; 114 | } 115 | 116 | 117 | @mixin scrollBar { 118 | &::-webkit-scrollbar-track-piece { 119 | background: #d3dce6; 120 | } 121 | &::-webkit-scrollbar { 122 | width: 6px; 123 | } 124 | &::-webkit-scrollbar-thumb { 125 | background: #99a9bf; 126 | border-radius: 20px; 127 | } 128 | } 129 | 130 | @mixin relative { 131 | position: relative; 132 | width: 100%; 133 | height: 100%; 134 | } 135 | 136 | @mixin pct($pct) { 137 | width: #{$pct}; 138 | position: relative; 139 | margin: 0 auto; 140 | } 141 | 142 | @mixin triangle($width, $height, $color, $direction) { 143 | $width: $width/2; 144 | $color-border-style: $height solid $color; 145 | $transparent-border-style: $width solid transparent; 146 | height: 0; 147 | width: 0; 148 | @if $direction==up { 149 | border-bottom: $color-border-style; 150 | border-left: $transparent-border-style; 151 | border-right: $transparent-border-style; 152 | } 153 | @else if $direction==right { 154 | border-left: $color-border-style; 155 | border-top: $transparent-border-style; 156 | border-bottom: $transparent-border-style; 157 | } 158 | @else if $direction==down { 159 | border-top: $color-border-style; 160 | border-left: $transparent-border-style; 161 | border-right: $transparent-border-style; 162 | } 163 | @else if $direction==left { 164 | border-right: $color-border-style; 165 | border-top: $transparent-border-style; 166 | border-bottom: $transparent-border-style; 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/mock/ad.js: -------------------------------------------------------------------------------- 1 | const index = { 2 | total: 17, 3 | data: { 4 | total: 1, 5 | list: [ 6 | { 7 | adId: 1, 8 | title: "阿范德萨", 9 | describe: "撒地方士大夫", 10 | pic: "ttttt", 11 | jumpType: 0, 12 | jumpUrl: "sss", 13 | iosUrl: "", 14 | androidUrl: "", 15 | wxaAppid: "", 16 | channelType: 1, 17 | channelList: ["yin", "33"], 18 | androidVersionType: 0, 19 | androidVersionList: [], 20 | iosVersionType: 0, 21 | iosVersionList: [], 22 | newShowStartNum: 0, 23 | newShowMaxNum: 0, 24 | oldShowStartNum: 0, 25 | oldShowMaxNum: 0, 26 | startTime: "2019-01-08 00:00:00", 27 | endTime: "2019-01-10 00:00:00", 28 | eventName: "", 29 | status: 1, 30 | picUrl: "https://res.ishiguangji.cn/ttttt" 31 | }, 32 | { 33 | adId: 2, 34 | title: "ffff", 35 | describe: "fff", 36 | pic: "ff", 37 | jumpType: 0, 38 | jumpUrl: "", 39 | iosUrl: "", 40 | androidUrl: "", 41 | wxaAppid: "", 42 | channelType: 0, 43 | channelList: [], 44 | androidVersionType: 0, 45 | androidVersionList: [], 46 | iosVersionType: 0, 47 | iosVersionList: [], 48 | newShowStartNum: 0, 49 | newShowMaxNum: 0, 50 | oldShowStartNum: 0, 51 | oldShowMaxNum: 0, 52 | startTime: null, 53 | endTime: null, 54 | eventName: "", 55 | status: 0, 56 | picUrl: "https://res.ishiguangji.cn/ff" 57 | }, 58 | { 59 | adId: 3, 60 | title: "fvvs", 61 | describe: "vvv", 62 | pic: "dd", 63 | jumpType: 0, 64 | jumpUrl: "", 65 | iosUrl: "", 66 | androidUrl: "", 67 | wxaAppid: "", 68 | channelType: 0, 69 | channelList: [], 70 | androidVersionType: 0, 71 | androidVersionList: [], 72 | iosVersionType: 0, 73 | iosVersionList: [], 74 | newShowStartNum: 0, 75 | newShowMaxNum: 0, 76 | oldShowStartNum: 0, 77 | oldShowMaxNum: 0, 78 | startTime: null, 79 | endTime: null, 80 | eventName: "", 81 | status: 0, 82 | picUrl: "https://res.ishiguangji.cn/dd" 83 | }, 84 | { 85 | adId: 4, 86 | title: "fffxxxx", 87 | describe: "vvv", 88 | pic: "bb", 89 | jumpType: 0, 90 | jumpUrl: "", 91 | iosUrl: "", 92 | androidUrl: "", 93 | wxaAppid: "", 94 | channelType: 0, 95 | channelList: [], 96 | androidVersionType: 0, 97 | androidVersionList: [], 98 | iosVersionType: 0, 99 | iosVersionList: [], 100 | newShowStartNum: 0, 101 | newShowMaxNum: 0, 102 | oldShowStartNum: 0, 103 | oldShowMaxNum: 0, 104 | startTime: null, 105 | endTime: null, 106 | eventName: "", 107 | status: 0, 108 | picUrl: "https://res.ishiguangji.cn/bb" 109 | } 110 | ] 111 | } 112 | }; 113 | 114 | const save = { 115 | data: { 116 | adId: 5 117 | } 118 | }; 119 | 120 | const edit = { 121 | code: 0, 122 | message: "success" 123 | }; 124 | 125 | const del = { 126 | code: 0, 127 | message: "success" 128 | }; 129 | 130 | export default { 131 | index, 132 | save, 133 | edit, 134 | del 135 | }; 136 | -------------------------------------------------------------------------------- /src/views/error/err404.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 24 | 25 | 144 | -------------------------------------------------------------------------------- /src/styles/base.scss: -------------------------------------------------------------------------------- 1 | /* reset css */ 2 | *, ::before, ::after { 3 | /*选择所有标签*/ 4 | margin: 0; 5 | padding: 0; 6 | 7 | /*清除移动端默认的点击高亮效果*/ 8 | -webkit-tap-highlight-color: rgba(255, 255, 255, 0); 9 | 10 | /*设置所有的元素都是以边框开始计算宽度的 百分比*/ 11 | box-sizing: border-box; 12 | } 13 | 14 | body { 15 | font-size: 14px; 16 | color: #fff; 17 | -moz-osx-font-smoothing: grayscale; 18 | -webkit-font-smoothing: antialiased; 19 | text-rendering: optimizeLegibility; 20 | font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif; 21 | } 22 | 23 | a { 24 | text-decoration: none; 25 | &:hover { 26 | text-decoration: none; 27 | } 28 | } 29 | 30 | ul, ol { 31 | list-style: none; 32 | } 33 | 34 | input { 35 | border: none; 36 | outline: none; 37 | /*清除移动端默认的表单样式*/ 38 | -webkit-appearance: none; 39 | } 40 | 41 | .svg-icon { 42 | width: 1em; 43 | height: 1em; 44 | vertical-align: middle; 45 | fill: currentColor; 46 | overflow: hidden; 47 | -webkit-transition: font-size 0.25s ease-out 0s; 48 | -moz-transition: font-size 0.25s ease-out 0s; 49 | transition: font-size 0.25s ease-out 0s; 50 | } 51 | 52 | .el-message-box { 53 | width: auto; 54 | min-width: 40%; 55 | } 56 | 57 | .query-form { 58 | margin-top: 20px; 59 | } 60 | 61 | .table-expand { 62 | .el-form-item { 63 | margin-right: 0; 64 | margin-bottom: 0; 65 | width: 49%; 66 | label { 67 | width: 90px; 68 | color: #99a9bf; 69 | } 70 | } 71 | } 72 | 73 | .pagination-container { 74 | margin-top: 10px; 75 | } 76 | 77 | @media screen and (max-width: 768px) { 78 | .query-form-item.el-form-item { 79 | display: block !important; 80 | margin-right: 0; 81 | margin-bottom: 10px; 82 | } 83 | .query-form-item .el-form-item__content { 84 | width: 100%; 85 | .el-select { 86 | width: 100%; 87 | } 88 | } 89 | .el-dialog { 90 | width: 80%; 91 | } 92 | 93 | .el-message { 94 | min-width: 70% !important; 95 | } 96 | } 97 | 98 | .container-left { 99 | .submenu-title-noDropdown, 100 | .el-submenu__title { 101 | &:hover { 102 | background-color: #263445 !important; 103 | } 104 | } 105 | 106 | .nest-menu .el-submenu>.el-submenu__title, 107 | .el-submenu .el-menu-item { 108 | background-color: #1f2d3d !important; 109 | &:hover { 110 | background-color: #001528 !important; 111 | } 112 | } 113 | } 114 | // 左侧导航栏的折叠后的样式 115 | .el-menu--collapse { 116 | .el-submenu { 117 | .el-submenu__title { 118 | span { 119 | height: 0; 120 | width: 0; 121 | overflow: hidden; 122 | visibility: hidden; 123 | display: inline-block; 124 | } 125 | .el-submenu__icon-arrow { 126 | display: none; 127 | } 128 | } 129 | } 130 | .el-menu-item { 131 | .el-tooltip { 132 | span { 133 | height: 0; 134 | width: 0; 135 | overflow: hidden; 136 | visibility: hidden; 137 | display: inline-block; 138 | } 139 | } 140 | } 141 | } 142 | .el-menu--vertical { 143 | 144 | .nest-menu.el-submenu>.el-submenu__title, 145 | .el-menu-item { 146 | &:hover { 147 | // you can use $subMenuHover 148 | background-color: #263455 !important; 149 | } 150 | } 151 | 152 | // the scroll bar appears when the subMenu is too long 153 | 154 | } 155 | 156 | .table-scrollbar { 157 | height: 75vh; 158 | } 159 | 160 | @media screen and (min-width: 1919px) { 161 | .table-scrollbar { 162 | height: 80vh; 163 | } 164 | } 165 | 166 | @media screen and (min-width: 2500px) { 167 | .table-scrollbar { 168 | height: 85vh; 169 | } 170 | } 171 | 172 | // 能删除的列表 173 | .remove-list-box { 174 | width: 100%; 175 | border: 1px dashed #cccccc; 176 | display: inline-block; 177 | padding: 10px; 178 | background-color: #f6f6f6; 179 | } 180 | .remove-list { 181 | margin-bottom: 15px; 182 | .remove-list-item { 183 | position: relative; 184 | height: 40px; 185 | line-height: 40px; 186 | padding-left: 10px; 187 | margin-top: 1px; 188 | border-radius: 4px; 189 | background-color: #ffff; 190 | margin-bottom: 2px; 191 | } 192 | .remove-list-item:hover { 193 | background-color: rgba(0, 0, 0, 0.05) !important; 194 | } 195 | } 196 | .remove-list-close { 197 | position: absolute; 198 | top: 10px; 199 | right: 10px; 200 | cursor: pointer; 201 | } 202 | -------------------------------------------------------------------------------- /src/views/error/err500.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 26 | 27 | 159 | -------------------------------------------------------------------------------- /src/filtres/index.js: -------------------------------------------------------------------------------- 1 | function pluralize(time, label) { 2 | if (time === 1) { 3 | return time + label; 4 | } 5 | return time + label + "s"; 6 | } 7 | export function timeAgo(time) { 8 | const between = Date.now() / 1000 - Number(time); 9 | if (between < 3600) { 10 | return pluralize(~~(between / 60), " minute"); 11 | } else if (between < 86400) { 12 | return pluralize(~~(between / 3600), " hour"); 13 | } else { 14 | return pluralize(~~(between / 86400), " day"); 15 | } 16 | } 17 | 18 | /** 19 | * @return {string} 20 | */ 21 | export function formatDateStr(date_str, fmt) { 22 | let date = new Date(date_str); 23 | if (isNaN(date.getDate())) { 24 | return ""; 25 | } 26 | const o = { 27 | "M+": date.getMonth() + 1, //月份 28 | "d+": date.getDate(), //日 29 | "h+": date.getHours(), //小时 30 | "m+": date.getMinutes(), //分 31 | "s+": date.getSeconds(), //秒 32 | "q+": Math.floor((date.getMonth() + 3) / 3), //季度 33 | S: date.getMilliseconds() //毫秒 34 | }; 35 | if (/(y+)/.test(fmt)) 36 | fmt = fmt.replace( 37 | RegExp.$1, 38 | (date.getFullYear() + "").substr(4 - RegExp.$1.length) 39 | ); 40 | for (let k in o) 41 | if (new RegExp("(" + k + ")").test(fmt)) 42 | fmt = fmt.replace( 43 | RegExp.$1, 44 | RegExp.$1.length === 1 45 | ? o[k] 46 | : ("00" + o[k]).substr(("" + o[k]).length) 47 | ); 48 | return fmt; 49 | } 50 | 51 | export function parseTime(time, cFormat) { 52 | if (arguments.length === 0) { 53 | return null; 54 | } 55 | 56 | if ((time + "").length === 10) { 57 | time = +time * 1000; 58 | } 59 | 60 | const format = cFormat || "{y}-{m}-{d} {h}:{i}:{s}"; 61 | let date; 62 | if (typeof time === "object") { 63 | date = time; 64 | } else { 65 | date = new Date(parseInt(time)); 66 | } 67 | const formatObj = { 68 | y: date.getFullYear(), 69 | m: date.getMonth() + 1, 70 | d: date.getDate(), 71 | h: date.getHours(), 72 | i: date.getMinutes(), 73 | s: date.getSeconds(), 74 | a: date.getDay() 75 | }; 76 | const timeStr = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => { 77 | let value = formatObj[key]; 78 | if (key === "a") 79 | return ["一", "二", "三", "四", "五", "六", "日"][value - 1]; 80 | if (result.length > 0 && value < 10) { 81 | value = "0" + value; 82 | } 83 | return value || 0; 84 | }); 85 | return timeStr; 86 | } 87 | 88 | export function formatTime(time, option) { 89 | time = +time * 1000; 90 | const d = new Date(time); 91 | const now = Date.now(); 92 | 93 | const diff = (now - d) / 1000; 94 | 95 | if (diff < 30) { 96 | return "刚刚"; 97 | } else if (diff < 3600) { 98 | // less 1 hour 99 | return Math.ceil(diff / 60) + "分钟前"; 100 | } else if (diff < 3600 * 24) { 101 | return Math.ceil(diff / 3600) + "小时前"; 102 | } else if (diff < 3600 * 24 * 2) { 103 | return "1天前"; 104 | } 105 | if (option) { 106 | return parseTime(time, option); 107 | } else { 108 | return ( 109 | d.getMonth() + 110 | 1 + 111 | "月" + 112 | d.getDate() + 113 | "日" + 114 | d.getHours() + 115 | "时" + 116 | d.getMinutes() + 117 | "分" 118 | ); 119 | } 120 | } 121 | 122 | /* 数字 格式化 */ 123 | export function nFormatter(num, digits) { 124 | const si = [ 125 | { value: 1e18, symbol: "E" }, 126 | { value: 1e15, symbol: "P" }, 127 | { value: 1e12, symbol: "T" }, 128 | { value: 1e9, symbol: "G" }, 129 | { value: 1e6, symbol: "M" }, 130 | { value: 1e3, symbol: "k" } 131 | ]; 132 | for (let i = 0; i < si.length; i++) { 133 | if (num >= si[i].value) { 134 | return ( 135 | (num / si[i].value + 0.1) 136 | .toFixed(digits) 137 | .replace(/\.0+$|(\.[0-9]*[1-9])0+$/, "$1") + si[i].symbol 138 | ); 139 | } 140 | } 141 | return num.toString(); 142 | } 143 | 144 | export function html2Text(val) { 145 | const div = document.createElement("div"); 146 | div.innerHTML = val; 147 | return div.textContent || div.innerText; 148 | } 149 | 150 | export function toThousandslsFilter(num) { 151 | return (+num || 0) 152 | .toString() 153 | .replace(/^-?\d+/g, m => m.replace(/(?=(?!\b)(\d{3})+$)/g, ",")); 154 | } 155 | 156 | /** 157 | * 格式化文件大小 158 | * @param value 159 | * @returns {*} 160 | */ 161 | export function renderSize(value) { 162 | if (!value || value === null || value === "") { 163 | return ""; 164 | } 165 | let unitArr = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; 166 | let srcsize = parseFloat(value); 167 | let index = Math.floor(Math.log(srcsize) / Math.log(1024)); 168 | let size = srcsize / Math.pow(1024, index); 169 | size = size.toFixed(0); // 保留的小数位数 170 | return size + unitArr[index]; 171 | } 172 | -------------------------------------------------------------------------------- /src/role.js: -------------------------------------------------------------------------------- 1 | import router from "./router/index"; 2 | import store from "./store/index"; 3 | import NProgress from "nprogress"; // Progress 进度条 4 | import "nprogress/nprogress.css"; // Progress 进度条样式 5 | import { getAdminId } from "./utils/auth"; // 验权 6 | import { Message } from "element-ui"; 7 | import { asyncRouterMap } from "./router/index"; 8 | // permissiom judge 9 | function hasRole(authRules, permissionAuthRules) { 10 | if (!authRules || authRules.length <= 0) { 11 | return false; 12 | } 13 | if (authRules.indexOf("admin") >= 0) return true; // admin权限 直接通过 14 | if (!permissionAuthRules) return true; 15 | return authRules.some(role => permissionAuthRules.indexOf(role) >= 0); 16 | } 17 | 18 | /** 19 | * 通过meta.role判断是否与当前用户权限匹配 20 | * @param authRules 21 | * @param route 22 | */ 23 | function hasRouterRole(authRules, route) { 24 | if ( 25 | authRules.indexOf("admin") >= 0 || 26 | !route.meta || 27 | !route.meta.authRule 28 | ) { 29 | return true; 30 | } 31 | return authRules.some( 32 | authRule => route.meta.authRule.indexOf(authRule) >= 0 33 | ); 34 | } 35 | 36 | /** 37 | * 递归过滤异步路由表,返回符合用户角色权限的路由表 38 | * @param asyncRouterMap 39 | * @param authRules 40 | */ 41 | function filterAsyncRouter(asyncRouterMap, authRules) { 42 | const accessedRouters = asyncRouterMap.filter(route => { 43 | if (hasRouterRole(authRules, route)) { 44 | if (route.children && route.children.length) { 45 | route.children = filterAsyncRouter(route.children, authRules); 46 | } 47 | return true; 48 | } 49 | return false; 50 | }); 51 | return accessedRouters; 52 | } 53 | 54 | // register global progress. 55 | const whiteList = ["/login", "/401", "/404", "/500"]; // 不重定向白名单 56 | router.beforeEach((to, from, next) => { 57 | NProgress.start(); // 开启Progress 58 | if (whiteList.indexOf(to.path) !== -1) { 59 | // 在免登录白名单,直接进入 60 | next(); 61 | return; 62 | } 63 | let adminId = getAdminId(); 64 | if (adminId !== "undefined" && adminId !== "" && adminId) { 65 | // 判断是否有token 66 | if (to.path === "/login") { 67 | next({ path: "/" }); 68 | NProgress.done(); // router在hash模式下 手动改变hash 重定向回来 不会触发afterEach 暂时hack方案 ps:history模式下无问题,可删除该行! 69 | return; 70 | } 71 | if ( 72 | !store.getters.userName && 73 | (!store.getters.authRules || store.getters.authRules.length === 0) 74 | ) { 75 | // 判断当前用户是否已拉取完用户信息 76 | store 77 | .dispatch("userInfo") 78 | .then(data => { 79 | // 拉取user_info 80 | const authRules = data.authRules || []; 81 | if ( 82 | !(authRules instanceof Array) || 83 | authRules.length === 0 84 | ) { 85 | Message.error("权限验证失败,请联系管理员~"); 86 | next({ 87 | path: "/401", 88 | query: { noGoBack: true } 89 | }); 90 | NProgress.done(); 91 | return; 92 | } 93 | let accessedRouters = filterAsyncRouter( 94 | asyncRouterMap, 95 | authRules 96 | ); 97 | // 生成可访问的路由表 98 | router.addRoutes(accessedRouters); // 动态添加可访问路由表 99 | next({ ...to }); // hack方法 确保addRoutes已完成 100 | // 设置左边导航栏 101 | store 102 | .dispatch("filterRouter", { accessedRouters }) 103 | .then(() => {}); 104 | }) 105 | .catch(() => { 106 | store.dispatch("fedLogout").then(() => { 107 | Message.error("验证失败,请重新登录"); 108 | let redirect = to.fullPath; 109 | store.dispatch("loginOut").then(() => { 110 | next({ 111 | path: "/login", 112 | query: { redirect: redirect } 113 | }); 114 | }); 115 | }); 116 | }); 117 | return; 118 | } 119 | // 没有动态改变权限的需求可直接next() 删除下方权限判断 ↓ 120 | if (hasRole(store.getters.authRules, to.meta.authRule)) { 121 | next(); // 122 | return; 123 | } 124 | next({ 125 | path: "/401", 126 | query: { noGoBack: true } 127 | }); 128 | NProgress.done(); // router在hash模式下 手动改变hash 重定向回来 不会触发afterEach 暂时hack方案 ps:history模式下无问题,可删除该行! 129 | return; 130 | } 131 | let redirect = to.fullPath; 132 | store.dispatch("loginOut").then(() => { 133 | next({ 134 | path: "/login", 135 | query: { redirect: redirect } 136 | }); 137 | }); // 否则全部重定向到登录页 138 | NProgress.done(); // router在hash模式下 手动改变hash 重定向回来 不会触发afterEach 暂时hack方案 ps:history模式下无问题,可删除该行! 139 | }); 140 | 141 | router.afterEach(() => { 142 | NProgress.done(); // 结束Progress 143 | }); 144 | -------------------------------------------------------------------------------- /src/store/modules/admin.js: -------------------------------------------------------------------------------- 1 | import { userInfo, loginName, logout } from "../../api/auth/login"; 2 | import * as types from "../mutation-types"; 3 | import { constantRouterMap } from "../../router"; 4 | import { 5 | getToken, 6 | setToken, 7 | removeToken, 8 | getAdminId, 9 | setAdminId, 10 | removeAdminId 11 | } from "../../utils/auth"; 12 | // import { $NOT_NETWORK } from '../../utils/errorCode' 13 | import { Message } from "element-ui"; 14 | 15 | // initial state 16 | const state = { 17 | adminId: getAdminId(), // id 18 | userName: "", // 昵称 19 | avatar: "", // 头像 20 | token: getToken(), // 登录token 21 | authRules: [], // 权限列表 22 | routers: constantRouterMap // 路由列表 23 | }; 24 | 25 | // getters 26 | const getters = { 27 | adminId: state => state.adminId, 28 | userName: state => state.userName, 29 | avatar: state => state.avatar, 30 | token: state => state.token, 31 | authRules: state => state.authRules, 32 | routers: state => state.routers 33 | }; 34 | 35 | // actions 36 | const actions = { 37 | // 用户名登录 38 | loginName({ commit }, userInfo) { 39 | const userName = userInfo.userName ? userInfo.userName.trim() : ""; 40 | const pwd = userInfo.pwd ? userInfo.pwd : ""; 41 | return new Promise((resolve, reject) => { 42 | loginName(userName, pwd) 43 | .then(response => { 44 | if (response.code) { 45 | Message({ 46 | message: response.message, 47 | type: "error", 48 | duration: 5 * 1000 49 | }); 50 | } else { 51 | let data = response.data; 52 | commit(types.RECEIVE_ADMIN_ID, data.id); 53 | commit(types.RECEIVE_ADMIN_TOKEN, data.token); 54 | commit(types.RECEIVE_ADMIN_AUTH_RULES, []); 55 | } 56 | resolve(response); 57 | }) 58 | .catch(error => { 59 | reject(error); 60 | }); 61 | }); 62 | }, 63 | userInfo({ commit }) { 64 | return new Promise((resolve, reject) => { 65 | userInfo() 66 | .then(response => { 67 | if (response.code === 2) { 68 | reject("登录失效"); 69 | } 70 | const data = response.data || {}; 71 | commit(types.RECEIVE_ADMIN_NAME, data.username); 72 | commit(types.RECEIVE_ADMIN_AVATAR, data.avatar); 73 | commit(types.RECEIVE_ADMIN_AUTH_RULES, data.authRules); 74 | resolve(data); 75 | }) 76 | .catch(error => { 77 | reject(error); 78 | }); 79 | }); 80 | }, 81 | // 登出 82 | loginOut({ commit }) { 83 | return new Promise((resolve, reject) => { 84 | logout() 85 | .then(() => { 86 | commit(types.RECEIVE_ADMIN_ID, ""); 87 | commit(types.RECEIVE_ADMIN_TOKEN, ""); 88 | commit(types.RECEIVE_ADMIN_AUTH_RULES, []); 89 | resolve(); 90 | }) 91 | .catch(error => { 92 | reject(error); 93 | }); 94 | }); 95 | }, 96 | 97 | // 前端 登出 98 | fedLogout({ commit }) { 99 | return new Promise(resolve => { 100 | commit(types.RECEIVE_ADMIN_ID, ""); 101 | commit(types.RECEIVE_ADMIN_TOKEN, ""); 102 | commit(types.RECEIVE_ADMIN_AUTH_RULES, []); 103 | resolve(); 104 | }); 105 | }, 106 | /** 107 | * 过滤路由列表 108 | * @param commit 109 | * @param data 110 | * @returns {Promise} 111 | */ 112 | filterRouter({ commit }, data) { 113 | const { accessedRouters } = data; 114 | if (accessedRouters && accessedRouters.length > 0) { 115 | commit(types.RECEIVE_ROUTERS, accessedRouters); 116 | } 117 | } 118 | }; 119 | 120 | // mutations 121 | const mutations = { 122 | [types.RECEIVE_ADMIN_ID](state, adminId) { 123 | state.adminId = adminId; 124 | if (adminId === "") { 125 | removeAdminId(); 126 | } else { 127 | setAdminId(adminId); 128 | } 129 | }, 130 | [types.RECEIVE_ADMIN_TOKEN](state, token) { 131 | state.token = token; 132 | if (token === "") { 133 | removeToken(); 134 | } else { 135 | setToken(token); 136 | } 137 | }, 138 | [types.RECEIVE_ADMIN_NAME](state, userName) { 139 | state.userName = userName; 140 | }, 141 | [types.RECEIVE_ADMIN_AVATAR](state, avatar) { 142 | state.avatar = avatar; 143 | }, 144 | [types.RECEIVE_ADMIN_AUTH_RULES](state, authRules) { 145 | state.authRules = authRules; 146 | }, 147 | [types.RECEIVE_ROUTERS](state, routers) { 148 | const tempRm = constantRouterMap.concat(routers); 149 | state.routers = JSON.parse(JSON.stringify(tempRm)); 150 | } 151 | }; 152 | 153 | export default { 154 | state, 155 | getters, 156 | actions, 157 | mutations 158 | }; 159 | -------------------------------------------------------------------------------- /src/views/error/err401.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 24 | 25 | 176 | -------------------------------------------------------------------------------- /src/views/home/SidebarItem.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 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 103 | 104 | 121 | -------------------------------------------------------------------------------- /public/tinymce4.7.5/plugins/visualblocks/css/visualblocks.css: -------------------------------------------------------------------------------- 1 | .mce-visualblocks p { 2 | padding-top: 10px; 3 | border: 1px dashed #BBB; 4 | margin-left: 3px; 5 | background-image: url(data:image/gif;base64,R0lGODlhCQAJAJEAAAAAAP///7u7u////yH5BAEAAAMALAAAAAAJAAkAAAIQnG+CqCN/mlyvsRUpThG6AgA7); 6 | background-repeat: no-repeat; 7 | } 8 | 9 | .mce-visualblocks h1 { 10 | padding-top: 10px; 11 | border: 1px dashed #BBB; 12 | margin-left: 3px; 13 | background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGu1JuxHoAfRNRW3TWXyF2YiRUAOw==); 14 | background-repeat: no-repeat; 15 | } 16 | 17 | .mce-visualblocks h2 { 18 | padding-top: 10px; 19 | border: 1px dashed #BBB; 20 | margin-left: 3px; 21 | background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8Hybbx4oOuqgTynJd6bGlWg3DkJzoaUAAAOw==); 22 | background-repeat: no-repeat; 23 | } 24 | 25 | .mce-visualblocks h3 { 26 | padding-top: 10px; 27 | border: 1px dashed #BBB; 28 | margin-left: 3px; 29 | background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIZjI8Hybbx4oOuqgTynJf2Ln2NOHpQpmhAAQA7); 30 | background-repeat: no-repeat; 31 | } 32 | 33 | .mce-visualblocks h4 { 34 | padding-top: 10px; 35 | border: 1px dashed #BBB; 36 | margin-left: 3px; 37 | background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxInR0zqeAdhtJlXwV1oCll2HaWgAAOw==); 38 | background-repeat: no-repeat; 39 | } 40 | 41 | .mce-visualblocks h5 { 42 | padding-top: 10px; 43 | border: 1px dashed #BBB; 44 | margin-left: 3px; 45 | background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjane4iq5GlW05GgIkIZUAAAOw==); 46 | background-repeat: no-repeat; 47 | } 48 | 49 | .mce-visualblocks h6 { 50 | padding-top: 10px; 51 | border: 1px dashed #BBB; 52 | margin-left: 3px; 53 | background-image: url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjan04jep1iZ1XRlAo5bVgAAOw==); 54 | background-repeat: no-repeat; 55 | } 56 | 57 | .mce-visualblocks div:not([data-mce-bogus]) { 58 | padding-top: 10px; 59 | border: 1px dashed #BBB; 60 | margin-left: 3px; 61 | background-image: url(data:image/gif;base64,R0lGODlhEgAKAIABALu7u////yH5BAEAAAEALAAAAAASAAoAAAIfjI9poI0cgDywrhuxfbrzDEbQM2Ei5aRjmoySW4pAAQA7); 62 | background-repeat: no-repeat; 63 | } 64 | 65 | .mce-visualblocks section { 66 | padding-top: 10px; 67 | border: 1px dashed #BBB; 68 | margin: 0 0 1em 3px; 69 | background-image: url(data:image/gif;base64,R0lGODlhKAAKAIABALu7u////yH5BAEAAAEALAAAAAAoAAoAAAI5jI+pywcNY3sBWHdNrplytD2ellDeSVbp+GmWqaDqDMepc8t17Y4vBsK5hDyJMcI6KkuYU+jpjLoKADs=); 70 | background-repeat: no-repeat; 71 | } 72 | 73 | .mce-visualblocks article { 74 | padding-top: 10px; 75 | border: 1px dashed #BBB; 76 | margin: 0 0 1em 3px; 77 | background-image: url(data:image/gif;base64,R0lGODlhKgAKAIABALu7u////yH5BAEAAAEALAAAAAAqAAoAAAI6jI+pywkNY3wG0GBvrsd2tXGYSGnfiF7ikpXemTpOiJScasYoDJJrjsG9gkCJ0ag6KhmaIe3pjDYBBQA7); 78 | background-repeat: no-repeat; 79 | } 80 | 81 | .mce-visualblocks blockquote { 82 | padding-top: 10px; 83 | border: 1px dashed #BBB; 84 | background-image: url(data:image/gif;base64,R0lGODlhPgAKAIABALu7u////yH5BAEAAAEALAAAAAA+AAoAAAJPjI+py+0Knpz0xQDyuUhvfoGgIX5iSKZYgq5uNL5q69asZ8s5rrf0yZmpNkJZzFesBTu8TOlDVAabUyatguVhWduud3EyiUk45xhTTgMBBQA7); 85 | background-repeat: no-repeat; 86 | } 87 | 88 | .mce-visualblocks address { 89 | padding-top: 10px; 90 | border: 1px dashed #BBB; 91 | margin: 0 0 1em 3px; 92 | background-image: url(data:image/gif;base64,R0lGODlhLQAKAIABALu7u////yH5BAEAAAEALAAAAAAtAAoAAAI/jI+pywwNozSP1gDyyZcjb3UaRpXkWaXmZW4OqKLhBmLs+K263DkJK7OJeifh7FicKD9A1/IpGdKkyFpNmCkAADs=); 93 | background-repeat: no-repeat; 94 | } 95 | 96 | .mce-visualblocks pre { 97 | padding-top: 10px; 98 | border: 1px dashed #BBB; 99 | margin-left: 3px; 100 | background-image: url(data:image/gif;base64,R0lGODlhFQAKAIABALu7uwAAACH5BAEAAAEALAAAAAAVAAoAAAIjjI+ZoN0cgDwSmnpz1NCueYERhnibZVKLNnbOq8IvKpJtVQAAOw==); 101 | background-repeat: no-repeat; 102 | } 103 | 104 | .mce-visualblocks figure { 105 | padding-top: 10px; 106 | border: 1px dashed #BBB; 107 | margin: 0 0 1em 3px; 108 | background-image: url(data:image/gif;base64,R0lGODlhJAAKAIAAALu7u////yH5BAEAAAEALAAAAAAkAAoAAAI0jI+py+2fwAHUSFvD3RlvG4HIp4nX5JFSpnZUJ6LlrM52OE7uSWosBHScgkSZj7dDKnWAAgA7); 109 | background-repeat: no-repeat; 110 | } 111 | 112 | .mce-visualblocks hgroup { 113 | padding-top: 10px; 114 | border: 1px dashed #BBB; 115 | margin: 0 0 1em 3px; 116 | background-image: url(data:image/gif;base64,R0lGODlhJwAKAIABALu7uwAAACH5BAEAAAEALAAAAAAnAAoAAAI3jI+pywYNI3uB0gpsRtt5fFnfNZaVSYJil4Wo03Hv6Z62uOCgiXH1kZIIJ8NiIxRrAZNMZAtQAAA7); 117 | background-repeat: no-repeat; 118 | } 119 | 120 | .mce-visualblocks aside { 121 | padding-top: 10px; 122 | border: 1px dashed #BBB; 123 | margin: 0 0 1em 3px; 124 | background-image: url(data:image/gif;base64,R0lGODlhHgAKAIABAKqqqv///yH5BAEAAAEALAAAAAAeAAoAAAItjI+pG8APjZOTzgtqy7I3f1yehmQcFY4WKZbqByutmW4aHUd6vfcVbgudgpYCADs=); 125 | background-repeat: no-repeat; 126 | } 127 | 128 | .mce-visualblocks figcaption { 129 | border: 1px dashed #BBB; 130 | } 131 | 132 | .mce-visualblocks ul { 133 | padding-top: 10px; 134 | border: 1px dashed #BBB; 135 | margin: 0 0 1em 3px; 136 | background-image: url(data:image/gif;base64,R0lGODlhDQAKAIAAALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGuYnqUVSjvw26DzzXiqIDlVwAAOw==); 137 | background-repeat: no-repeat; 138 | } 139 | 140 | .mce-visualblocks ol { 141 | padding-top: 10px; 142 | border: 1px dashed #BBB; 143 | margin: 0 0 1em 3px; 144 | background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybH6HHt0qourxC6CvzXieHyeWQAAOw==); 145 | background-repeat: no-repeat; 146 | } 147 | 148 | .mce-visualblocks dl { 149 | padding-top: 10px; 150 | border: 1px dashed #BBB; 151 | margin: 0 0 1em 3px; 152 | background-image: url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybEOnmOvUoWznTqeuEjNSCqeGRUAOw==); 153 | background-repeat: no-repeat; 154 | } 155 | -------------------------------------------------------------------------------- /src/assets/icons/demo_fontclass.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | IconFont 7 | 8 | 9 | 10 | 11 |
12 |

IconFont 图标

13 |
    14 | 15 |
  • 16 | 17 |
    通用
    18 |
    .icon-tongyong
    19 |
  • 20 | 21 |
  • 22 | 23 |
    wxb账户
    24 |
    .icon-wxbzhanghu
    25 |
  • 26 | 27 |
  • 28 | 29 |
    公用-圈
    30 |
    .icon-gongyongquan1
    31 |
  • 32 | 33 |
  • 34 | 35 |
    user
    36 |
    .icon-user
    37 |
  • 38 | 39 |
  • 40 | 41 |
    设置
    42 |
    .icon-shezhi1
    43 |
  • 44 | 45 |
  • 46 | 47 |
    用户管理
    48 |
    .icon-user-guanli
    49 |
  • 50 | 51 |
  • 52 | 53 |
    pwd
    54 |
    .icon-pwd
    55 |
  • 56 | 57 |
  • 58 | 59 |
    eye
    60 |
    .icon-eye
    61 |
  • 62 | 63 |
  • 64 | 65 |
    广告
    66 |
    .icon-guanggao
    67 |
  • 68 | 69 |
  • 70 | 71 |
    管理员
    72 |
    .icon-guanliyuan
    73 |
  • 74 | 75 |
  • 76 | 77 |
    权限-
    78 |
    .icon-cloud-permissions
    79 |
  • 80 | 81 |
  • 82 | 83 |
    首页
    84 |
    .icon-shouye
    85 |
  • 86 | 87 |
  • 88 | 89 |
    世界杯
    90 |
    .icon-shijiebei
    91 |
  • 92 | 93 |
  • 94 | 95 |
    角色
    96 |
    .icon-jiaose
    97 |
  • 98 | 99 |
  • 100 | 101 |
    报表
    102 |
    .icon-baobiao
    103 |
  • 104 | 105 |
  • 106 | 107 |
    管理员
    108 |
    .icon-guanliyuan1
    109 |
  • 110 | 111 |
  • 112 | 113 |
    题库
    114 |
    .icon-tiku
    115 |
  • 116 | 117 |
  • 118 | 119 |
    小程序
    120 |
    .icon-xiaochengxu
    121 |
  • 122 | 123 |
124 | 125 |

font-class引用

126 |
127 | 128 |

font-class是unicode使用方式的一种变种,主要是解决unicode书写不直观,语意不明确的问题。

129 |

与unicode使用方式相比,具有如下特点:

130 |
    131 |
  • 兼容性良好,支持ie8+,及所有现代浏览器。
  • 132 |
  • 相比于unicode语意明确,书写更直观。可以很容易分辨这个icon是什么。
  • 133 |
  • 因为使用class来定义图标,所以当要替换图标时,只需要修改class里面的unicode引用。
  • 134 |
  • 不过因为本质上还是使用的字体,所以多色图标还是不支持的。
  • 135 |
136 |

使用步骤如下:

137 |

第一步:引入项目下面生成的fontclass代码:

138 | 139 | 140 |
<link rel="stylesheet" type="text/css" href="./iconfont.css">
141 |

第二步:挑选相应图标并获取类名,应用于页面:

142 |
<i class="iconfont icon-xxx"></i>
143 |
144 |

"iconfont"是你项目下的font-family。可以通过编辑项目查看,默认是"iconfont"。

145 |
146 |
147 | 148 | 149 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import VueRouter from "vue-router"; 3 | 4 | if (process.env.NODE_ENV === "development") { 5 | Vue.use(VueRouter); 6 | } 7 | 8 | import { ROUTER_MODE } from "../config/app"; 9 | 10 | import Home from "../views/home/index.vue"; 11 | 12 | // 管理组相关 13 | import adminRouter from "../views/userManage/admin/router.vue"; 14 | import authAdmin from "../views/userManage/admin/authAdmin.vue"; 15 | import authRole from "../views/userManage/admin/authRole.vue"; 16 | import authPermissionRule from "../views/userManage/admin/authPermissionRule.vue"; 17 | 18 | // 上传相关 19 | import tinymce from "../views/components/tinymce-demo.vue"; 20 | import upload from "../views/components/upload-demo.vue"; 21 | 22 | // 广告管理 23 | import adSite from "../views/adManage/adSite.vue"; 24 | import ad from "../views/adManage/ad.vue"; 25 | 26 | // Vue.use(VueRouter); 27 | 28 | const err401 = r => 29 | require.ensure([], () => r(require("../views/error/err401.vue")), "home"); 30 | const err404 = r => 31 | require.ensure([], () => r(require("../views/error/err404.vue")), "home"); 32 | const login = r => 33 | require.ensure([], () => r(require("../views/login/index.vue")), "home"); 34 | const main = r => 35 | require.ensure([], () => r(require("../views/home/main.vue")), "home"); 36 | 37 | // 注意 权限字段 authRule (严格区分大小写) 38 | export const constantRouterMap = [ 39 | { 40 | path: "*", 41 | component: err404, 42 | hidden: true 43 | }, 44 | { 45 | path: "/401", 46 | component: err401, 47 | name: "401", 48 | hidden: true 49 | }, 50 | { 51 | path: "/404", 52 | component: err404, 53 | name: "404", 54 | hidden: true 55 | }, 56 | { 57 | path: "/500", 58 | component: err404, 59 | name: "500", 60 | hidden: true 61 | }, 62 | { 63 | path: "/login", 64 | component: login, 65 | name: "登录", 66 | hidden: true 67 | }, 68 | { 69 | path: "/", 70 | component: Home, 71 | redirect: "/readme", 72 | name: "首页", 73 | hidden: true 74 | }, 75 | { 76 | path: "/readme", 77 | component: Home, 78 | redirect: "/readme/main", 79 | icon: "shouye", 80 | name: "控制台", 81 | noDropdown: true, 82 | children: [ 83 | { 84 | path: "main", 85 | component: main 86 | } 87 | ] 88 | }, 89 | { 90 | path: "/components", 91 | redirect: "/components/uploadList", 92 | component: Home, 93 | name: "components", 94 | icon: "tongyong", 95 | children: [ 96 | { 97 | path: "uploadList", 98 | name: "上传图片的展示", 99 | component: r => 100 | require.ensure( 101 | [], 102 | () => r(require("../views/components/uploadList.vue")), 103 | "home" 104 | ) 105 | }, 106 | { 107 | path: "tinymce", 108 | name: "tinymce富文本编辑器", 109 | component: tinymce 110 | }, 111 | { 112 | path: "upload", 113 | name: "上传的demo", 114 | component: upload 115 | } 116 | ] 117 | } 118 | ]; 119 | 120 | export default new VueRouter({ 121 | // mode: 'history', //后端支持可开 122 | mode: ROUTER_MODE, 123 | routes: constantRouterMap, 124 | strict: process.env.NODE_ENV !== "production" 125 | }); 126 | 127 | export const asyncRouterMap = [ 128 | { 129 | path: "/userManage", 130 | redirect: "/userManage/adminManage/index", 131 | component: Home, 132 | icon: "guanliyuan1", 133 | name: "用户管理", 134 | meta: { 135 | authRule: ["user_manage"] 136 | }, 137 | // noDropdown: true, 138 | children: [ 139 | { 140 | path: "/userManage/adminManage", 141 | component: adminRouter, 142 | redirect: "/userManage/authAdmin/index", 143 | name: "管理组", 144 | icon: "", 145 | meta: { 146 | authRule: ["user_manage/admin_manage"] 147 | }, 148 | children: [ 149 | { 150 | path: "authAdmin", 151 | component: authAdmin, 152 | name: "管理员管理", 153 | icon: "", 154 | meta: { 155 | authRule: ["admin/auth/admin/index"] 156 | } 157 | }, 158 | { 159 | path: "authRole", 160 | component: authRole, 161 | name: "角色管理", 162 | icon: "", 163 | meta: { 164 | authRule: ["admin/auth/role/index"] 165 | } 166 | }, 167 | { 168 | path: "authPermissionRule", 169 | component: authPermissionRule, 170 | name: "权限管理", 171 | icon: "", 172 | meta: { 173 | authRule: ["admin/auth/permission_rule/index"] 174 | } 175 | } 176 | ] 177 | } 178 | ] 179 | }, 180 | { 181 | path: "/adManage", 182 | redirect: "/adManage/adSite", 183 | component: Home, 184 | icon: "guanggao", 185 | name: "广告相关", 186 | meta: { 187 | // authRule: ["ad_manage"] 188 | }, 189 | // noDropdown: true, 190 | children: [ 191 | { 192 | path: "adSite", 193 | component: adSite, 194 | name: "广告位管理", 195 | icon: "", 196 | meta: { 197 | // authRule: ["admin/ad/site/index"] 198 | } 199 | }, 200 | { 201 | path: "ad", 202 | component: ad, 203 | name: "广告管理", 204 | icon: "", 205 | meta: { 206 | // authRule: ["admin/ad/ad/index"] 207 | } 208 | } 209 | ] 210 | } 211 | ]; 212 | -------------------------------------------------------------------------------- /src/views/login/index.vue: -------------------------------------------------------------------------------- 1 | 48 | 49 | 119 | 120 | 200 | -------------------------------------------------------------------------------- /src/components/Tinymce/index.vue: -------------------------------------------------------------------------------- 1 |