├── .editorconfig ├── .env.development ├── .env.production ├── .env.staging ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── babel.config.js ├── build └── index.js ├── jest.config.js ├── jsconfig.json ├── mock ├── article.js ├── index.js ├── mock-server.js ├── remote-search.js ├── role │ ├── index.js │ └── routes.js ├── user.js └── utils.js ├── package.json ├── plopfile.js ├── postcss.config.js ├── public ├── favicon.ico └── index.html ├── src ├── App.vue ├── api │ ├── article.js │ ├── cmdb │ │ ├── assets.js │ │ └── servers.js │ ├── information │ │ └── centre.js │ ├── monitor │ │ ├── crud.js │ │ ├── error.js │ │ ├── ip.js │ │ ├── service.js │ │ └── users.js │ ├── qiniu.js │ ├── remote-search.js │ ├── role.js │ ├── system │ │ ├── departments.js │ │ ├── jobs.js │ │ ├── permissions.js │ │ ├── roles.js │ │ └── users.js │ └── user.js ├── assets │ ├── 401_images │ │ └── 401.gif │ ├── 404_images │ │ ├── 404.png │ │ └── 404_cloud.png │ ├── custom-theme │ │ ├── fonts │ │ │ ├── element-icons.ttf │ │ │ └── element-icons.woff │ │ └── index.css │ └── images │ │ └── login-bg.jpg ├── components │ ├── BackToTop │ │ └── index.vue │ ├── Breadcrumb │ │ └── index.vue │ ├── Charts │ │ ├── Keyboard.vue │ │ ├── LineMarker.vue │ │ ├── MixChart.vue │ │ └── mixins │ │ │ └── resize.js │ ├── DndList │ │ └── index.vue │ ├── DragSelect │ │ └── index.vue │ ├── Dropzone │ │ └── index.vue │ ├── ErrorLog │ │ └── index.vue │ ├── GithubCorner │ │ └── index.vue │ ├── Hamburger │ │ └── index.vue │ ├── HeaderSearch │ │ └── index.vue │ ├── ImageCropper │ │ ├── index.vue │ │ └── utils │ │ │ ├── data2blob.js │ │ │ ├── effectRipple.js │ │ │ ├── language.js │ │ │ └── mimes.js │ ├── JsonEditor │ │ └── index.vue │ ├── Kanban │ │ └── index.vue │ ├── MDinput │ │ └── index.vue │ ├── MarkdownEditor │ │ ├── default-options.js │ │ └── index.vue │ ├── Pagination │ │ └── index.vue │ ├── PanThumb │ │ └── index.vue │ ├── RightPanel │ │ └── index.vue │ ├── Screenfull │ │ └── index.vue │ ├── Share │ │ └── DropdownMenu.vue │ ├── SizeSelect │ │ └── index.vue │ ├── Sticky │ │ └── index.vue │ ├── SvgIcon │ │ └── index.vue │ ├── TextHoverEffect │ │ └── Mallki.vue │ ├── ThemePicker │ │ └── index.vue │ ├── Tinymce │ │ ├── components │ │ │ └── EditorImage.vue │ │ ├── dynamicLoadScript.js │ │ ├── index.vue │ │ ├── plugins.js │ │ └── toolbar.js │ ├── Upload │ │ ├── SingleImage.vue │ │ ├── SingleImage2.vue │ │ └── SingleImage3.vue │ └── UploadExcel │ │ └── index.vue ├── directive │ ├── clipboard │ │ ├── clipboard.js │ │ └── index.js │ ├── el-drag-dialog │ │ ├── drag.js │ │ └── index.js │ ├── el-table │ │ ├── adaptive.js │ │ └── index.js │ ├── permission │ │ ├── index.js │ │ └── permission.js │ ├── sticky.js │ └── waves │ │ ├── index.js │ │ ├── waves.css │ │ └── waves.js ├── filters │ └── index.js ├── icons │ ├── index.js │ ├── svg │ │ ├── 404.svg │ │ ├── Steve-Jobs.svg │ │ ├── Task Management.svg │ │ ├── alipay.svg │ │ ├── anq.svg │ │ ├── app.svg │ │ ├── backup.svg │ │ ├── bug.svg │ │ ├── chain.svg │ │ ├── chart.svg │ │ ├── clipboard.svg │ │ ├── codeConsole.svg │ │ ├── component.svg │ │ ├── dashboard.svg │ │ ├── database.svg │ │ ├── date.svg │ │ ├── deploy.svg │ │ ├── dept.svg │ │ ├── dev.svg │ │ ├── develop.svg │ │ ├── dictionary.svg │ │ ├── doc.svg │ │ ├── documentation.svg │ │ ├── download.svg │ │ ├── drag.svg │ │ ├── edit.svg │ │ ├── education.svg │ │ ├── email.svg │ │ ├── error.svg │ │ ├── example.svg │ │ ├── excel.svg │ │ ├── exit-fullscreen.svg │ │ ├── eye-open.svg │ │ ├── eye.svg │ │ ├── form.svg │ │ ├── fullscreen.svg │ │ ├── fwb.svg │ │ ├── github.svg │ │ ├── gonggao.svg │ │ ├── guide.svg │ │ ├── icon.svg │ │ ├── image.svg │ │ ├── index.svg │ │ ├── international.svg │ │ ├── ip.svg │ │ ├── ipvisits.svg │ │ ├── java.svg │ │ ├── language.svg │ │ ├── link.svg │ │ ├── list.svg │ │ ├── lock.svg │ │ ├── log.svg │ │ ├── login.svg │ │ ├── markdown.svg │ │ ├── menu.svg │ │ ├── message.svg │ │ ├── mnt.svg │ │ ├── money.svg │ │ ├── monitor.svg │ │ ├── nested.svg │ │ ├── network.svg │ │ ├── password.svg │ │ ├── pdf.svg │ │ ├── people.svg │ │ ├── peoples.svg │ │ ├── permission.svg │ │ ├── phone.svg │ │ ├── qiniu.svg │ │ ├── qq.svg │ │ ├── redis.svg │ │ ├── reset_password.svg │ │ ├── resources.svg │ │ ├── role.svg │ │ ├── search.svg │ │ ├── security.svg │ │ ├── server.svg │ │ ├── shopping.svg │ │ ├── size.svg │ │ ├── skill.svg │ │ ├── source.svg │ │ ├── sqlMonitor.svg │ │ ├── star.svg │ │ ├── storage.svg │ │ ├── swagger.svg │ │ ├── sys-tools.svg │ │ ├── system.svg │ │ ├── system1.svg │ │ ├── tab.svg │ │ ├── table.svg │ │ ├── task -2.svg │ │ ├── task.svg │ │ ├── tasks-1.svg │ │ ├── theme.svg │ │ ├── timing.svg │ │ ├── tools.svg │ │ ├── tree-table.svg │ │ ├── tree.svg │ │ ├── unlock.svg │ │ ├── user.svg │ │ ├── user1.svg │ │ ├── validCode.svg │ │ ├── visits.svg │ │ ├── web.svg │ │ ├── wechat.svg │ │ ├── weixin.svg │ │ ├── work.svg │ │ ├── zip.svg │ │ └── zujian.svg │ └── svgo.yml ├── layout │ ├── components │ │ ├── AppMain.vue │ │ ├── Navbar.vue │ │ ├── Settings │ │ │ └── index.vue │ │ ├── Sidebar │ │ │ ├── FixiOSBug.js │ │ │ ├── Item.vue │ │ │ ├── Link.vue │ │ │ ├── Logo.vue │ │ │ ├── SidebarItem.vue │ │ │ └── index.vue │ │ ├── TagsView │ │ │ ├── ScrollPane.vue │ │ │ └── index.vue │ │ └── index.js │ ├── index.vue │ └── mixin │ │ └── ResizeHandler.js ├── main.js ├── permission.js ├── router │ └── index.js ├── settings.js ├── store │ ├── getters.js │ ├── index.js │ └── modules │ │ ├── app.js │ │ ├── errorLog.js │ │ ├── permission.js │ │ ├── settings.js │ │ ├── tagsView.js │ │ └── user.js ├── styles │ ├── btn.scss │ ├── element-ui.scss │ ├── element-variables.scss │ ├── index.scss │ ├── mixin.scss │ ├── sidebar.scss │ ├── transition.scss │ └── variables.scss ├── utils │ ├── auth.js │ ├── clipboard.js │ ├── error-log.js │ ├── get-page-title.js │ ├── index.js │ ├── open-window.js │ ├── permission.js │ ├── request.js │ ├── rsaEncrypt.js │ ├── rulesValidate.js │ ├── scroll-to.js │ └── validate.js ├── vendor │ ├── Export2Excel.js │ └── Export2Zip.js └── views │ ├── cmdb │ └── servers │ │ ├── components │ │ └── cuForm.vue │ │ └── index.vue │ ├── dashboard │ ├── admin │ │ ├── components │ │ │ ├── BarChart.vue │ │ │ ├── BoxCard.vue │ │ │ ├── LineChart.vue │ │ │ ├── PanelGroup.vue │ │ │ ├── PieChart.vue │ │ │ ├── RaddarChart.vue │ │ │ ├── TodoList │ │ │ │ ├── Todo.vue │ │ │ │ ├── index.scss │ │ │ │ └── index.vue │ │ │ ├── TransactionTable.vue │ │ │ └── mixins │ │ │ │ └── resize.js │ │ └── index.vue │ ├── editor │ │ └── index.vue │ └── index.vue │ ├── error-log │ ├── components │ │ ├── ErrorTestA.vue │ │ └── ErrorTestB.vue │ └── index.vue │ ├── error-page │ ├── 401.vue │ └── 404.vue │ ├── icons │ ├── element-icons.js │ ├── index.vue │ └── svg-icons.js │ ├── information │ ├── components │ │ └── updatePass.vue │ └── index.vue │ ├── login │ ├── auth-redirect.vue │ ├── components │ │ └── SocialSignin.vue │ ├── index copy.vue │ └── index.vue │ ├── monitor │ ├── crud │ │ └── index.vue │ ├── error │ │ └── index.vue │ ├── ip │ │ ├── components │ │ │ └── cuForm.vue │ │ └── index.vue │ ├── service │ │ └── index.vue │ └── users │ │ └── index.vue │ ├── redirect │ └── index.vue │ ├── system │ ├── departments │ │ ├── components │ │ │ └── cuForm.vue │ │ └── index.vue │ ├── jobs │ │ ├── components │ │ │ ├── cuForm.vue │ │ │ ├── executionDialog.vue │ │ │ └── functionsDialog.vue │ │ └── index.vue │ ├── permissions │ │ ├── components │ │ │ └── cuForm.vue │ │ └── index.vue │ ├── roles │ │ ├── components │ │ │ └── cuForm.vue │ │ └── index.vue │ └── users │ │ ├── components │ │ ├── cuForm.vue │ │ ├── permissionsDialog.vue │ │ └── resetPwdForm.vue │ │ └── index.vue │ └── tool │ └── swagger │ ├── components │ └── iframe.vue │ └── index.vue └── vue.config.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | end_of_line = lf 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | [*.md] 13 | insert_final_newline = false 14 | trim_trailing_whitespace = false 15 | -------------------------------------------------------------------------------- /.env.development: -------------------------------------------------------------------------------- 1 | # just a flag 2 | ENV = 'development' 3 | 4 | # base api 5 | VUE_APP_BASE_API = 'http://127.0.0.1:8769/api' 6 | 7 | # base websocket 8 | VUE_APP_WS_API = 'ws://127.0.0.1:8769' 9 | -------------------------------------------------------------------------------- /.env.production: -------------------------------------------------------------------------------- 1 | # just a flag 2 | ENV = 'production' 3 | 4 | # base api 5 | VUE_APP_BASE_API = '/prod-api' 6 | 7 | -------------------------------------------------------------------------------- /.env.staging: -------------------------------------------------------------------------------- 1 | NODE_ENV = production 2 | 3 | # just a flag 4 | ENV = 'staging' 5 | 6 | # base api 7 | VUE_APP_BASE_API = '/stage-api' 8 | 9 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | build/*.js 2 | src/assets 3 | public 4 | dist 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | **/*.log 8 | 9 | tests/**/coverage/ 10 | tests/e2e/reports 11 | selenium-debug.log 12 | 13 | # Editor directories and files 14 | .idea 15 | .vscode 16 | *.suo 17 | *.ntvs* 18 | *.njsproj 19 | *.sln 20 | *.local 21 | 22 | package-lock.json 23 | yarn.lock 24 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 10 3 | script: npm run test 4 | notifications: 5 | email: false 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-present PanJiaChen 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 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | // https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app 4 | '@vue/cli-plugin-babel/preset' 5 | ], 6 | 'env': { 7 | 'development': { 8 | // babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require(). 9 | // This plugin can significantly increase the speed of hot updates, when you have a large number of pages. 10 | // https://panjiachen.github.io/vue-element-admin-site/guide/advanced/lazy-loading.html 11 | 'plugins': ['dynamic-import-node'] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /build/index.js: -------------------------------------------------------------------------------- 1 | const { run } = require('runjs') 2 | const chalk = require('chalk') 3 | const config = require('../vue.config.js') 4 | const rawArgv = process.argv.slice(2) 5 | const args = rawArgv.join(' ') 6 | 7 | if (process.env.npm_config_preview || rawArgv.includes('--preview')) { 8 | const report = rawArgv.includes('--report') 9 | 10 | run(`vue-cli-service build ${args}`) 11 | 12 | const port = 9526 13 | const publicPath = config.publicPath 14 | 15 | var connect = require('connect') 16 | var serveStatic = require('serve-static') 17 | const app = connect() 18 | 19 | app.use( 20 | publicPath, 21 | serveStatic('./dist', { 22 | index: ['index.html', '/'] 23 | }) 24 | ) 25 | 26 | app.listen(port, function () { 27 | console.log(chalk.green(`> Preview at http://localhost:${port}${publicPath}`)) 28 | if (report) { 29 | console.log(chalk.green(`> Report at http://localhost:${port}${publicPath}report.html`)) 30 | } 31 | 32 | }) 33 | } else { 34 | run(`vue-cli-service build ${args}`) 35 | } 36 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleFileExtensions: ['js', 'jsx', 'json', 'vue'], 3 | transform: { 4 | '^.+\\.vue$': 'vue-jest', 5 | '.+\\.(css|styl|less|sass|scss|svg|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 | collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'], 17 | coverageDirectory: '/tests/unit/coverage', 18 | // 'collectCoverage': true, 19 | 'coverageReporters': [ 20 | 'lcov', 21 | 'text-summary' 22 | ], 23 | testURL: 'http://localhost/' 24 | } 25 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "./", 4 | "paths": { 5 | "@/*": ["src/*"] 6 | } 7 | }, 8 | "exclude": ["node_modules", "dist"] 9 | } -------------------------------------------------------------------------------- /mock/index.js: -------------------------------------------------------------------------------- 1 | const Mock = require('mockjs') 2 | const { param2Obj } = require('./utils') 3 | 4 | const user = require('./user') 5 | const role = require('./role') 6 | const article = require('./article') 7 | const search = require('./remote-search') 8 | 9 | const mocks = [ 10 | ...user, 11 | ...role, 12 | ...article, 13 | ...search 14 | ] 15 | 16 | // for front mock 17 | // please use it cautiously, it will redefine XMLHttpRequest, 18 | // which will cause many of your third-party libraries to be invalidated(like progress event). 19 | function mockXHR() { 20 | // mock patch 21 | // https://github.com/nuysoft/Mock/issues/300 22 | Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send 23 | Mock.XHR.prototype.send = function() { 24 | if (this.custom.xhr) { 25 | this.custom.xhr.withCredentials = this.withCredentials || false 26 | 27 | if (this.responseType) { 28 | this.custom.xhr.responseType = this.responseType 29 | } 30 | } 31 | this.proxy_send(...arguments) 32 | } 33 | 34 | function XHR2ExpressReqWrap(respond) { 35 | return function(options) { 36 | let result = null 37 | if (respond instanceof Function) { 38 | const { body, type, url } = options 39 | // https://expressjs.com/en/4x/api.html#req 40 | result = respond({ 41 | method: type, 42 | body: JSON.parse(body), 43 | query: param2Obj(url) 44 | }) 45 | } else { 46 | result = respond 47 | } 48 | return Mock.mock(result) 49 | } 50 | } 51 | 52 | for (const i of mocks) { 53 | Mock.mock(new RegExp(i.url), i.type || 'get', XHR2ExpressReqWrap(i.response)) 54 | } 55 | } 56 | 57 | module.exports = { 58 | mocks, 59 | mockXHR 60 | } 61 | -------------------------------------------------------------------------------- /mock/remote-search.js: -------------------------------------------------------------------------------- 1 | const Mock = require('mockjs') 2 | 3 | const NameList = [] 4 | const count = 100 5 | 6 | for (let i = 0; i < count; i++) { 7 | NameList.push(Mock.mock({ 8 | name: '@first' 9 | })) 10 | } 11 | NameList.push({ name: 'mock-Pan' }) 12 | 13 | module.exports = [ 14 | // username search 15 | { 16 | url: '/vue-element-admin/search/user', 17 | type: 'get', 18 | response: config => { 19 | const { name } = config.query 20 | const mockNameList = NameList.filter(item => { 21 | const lowerCaseName = item.name.toLowerCase() 22 | return !(name && lowerCaseName.indexOf(name.toLowerCase()) < 0) 23 | }) 24 | return { 25 | code: 20000, 26 | data: { items: mockNameList } 27 | } 28 | } 29 | }, 30 | 31 | // transaction list 32 | { 33 | url: '/vue-element-admin/transaction/list', 34 | type: 'get', 35 | response: _ => { 36 | return { 37 | code: 20000, 38 | data: { 39 | total: 20, 40 | 'items|20': [{ 41 | order_no: '@guid()', 42 | timestamp: +Mock.Random.date('T'), 43 | username: '@name()', 44 | price: '@float(1000, 15000, 0, 2)', 45 | 'status|1': ['success', 'pending'] 46 | }] 47 | } 48 | } 49 | } 50 | } 51 | ] 52 | -------------------------------------------------------------------------------- /mock/user.js: -------------------------------------------------------------------------------- 1 | 2 | const tokens = { 3 | admin: { 4 | token: 'admin-token' 5 | }, 6 | editor: { 7 | token: 'editor-token' 8 | } 9 | } 10 | 11 | const users = { 12 | 'admin-token': { 13 | roles: ['admin'], 14 | introduction: 'I am a super administrator', 15 | avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', 16 | name: 'Super Admin' 17 | }, 18 | 'editor-token': { 19 | roles: ['editor'], 20 | introduction: 'I am an editor', 21 | avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', 22 | name: 'Normal Editor' 23 | } 24 | } 25 | 26 | module.exports = [ 27 | // user login 28 | { 29 | url: '/vue-element-admin/user/login', 30 | type: 'post', 31 | response: config => { 32 | const { username } = config.body 33 | const token = tokens[username] 34 | 35 | // mock error 36 | if (!token) { 37 | return { 38 | code: 60204, 39 | message: 'Account and password are incorrect.' 40 | } 41 | } 42 | 43 | return { 44 | code: 20000, 45 | data: token 46 | } 47 | } 48 | }, 49 | 50 | // get user info 51 | { 52 | url: '/vue-element-admin/user/info\.*', 53 | type: 'get', 54 | response: config => { 55 | const { token } = config.query 56 | const info = users[token] 57 | 58 | // mock error 59 | if (!info) { 60 | return { 61 | code: 50008, 62 | message: 'Login failed, unable to get user details.' 63 | } 64 | } 65 | 66 | return { 67 | code: 20000, 68 | data: info 69 | } 70 | } 71 | }, 72 | 73 | // user logout 74 | { 75 | url: '/vue-element-admin/user/logout', 76 | type: 'post', 77 | response: _ => { 78 | return { 79 | code: 20000, 80 | data: 'success' 81 | } 82 | } 83 | } 84 | ] 85 | -------------------------------------------------------------------------------- /mock/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} url 3 | * @returns {Object} 4 | */ 5 | function param2Obj(url) { 6 | const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ') 7 | if (!search) { 8 | return {} 9 | } 10 | const obj = {} 11 | const searchArr = search.split('&') 12 | searchArr.forEach(v => { 13 | const index = v.indexOf('=') 14 | if (index !== -1) { 15 | const name = v.substring(0, index) 16 | const val = v.substring(index + 1, v.length) 17 | obj[name] = val 18 | } 19 | }) 20 | return obj 21 | } 22 | 23 | /** 24 | * This is just a simple version of deep copy 25 | * Has a lot of edge cases bug 26 | * If you want to use a perfect deep copy, use lodash's _.cloneDeep 27 | * @param {Object} source 28 | * @returns {Object} 29 | */ 30 | function deepClone(source) { 31 | if (!source && typeof source !== 'object') { 32 | throw new Error('error arguments', 'deepClone') 33 | } 34 | const targetObj = source.constructor === Array ? [] : {} 35 | Object.keys(source).forEach(keys => { 36 | if (source[keys] && typeof source[keys] === 'object') { 37 | targetObj[keys] = deepClone(source[keys]) 38 | } else { 39 | targetObj[keys] = source[keys] 40 | } 41 | }) 42 | return targetObj 43 | } 44 | 45 | module.exports = { 46 | param2Obj, 47 | deepClone 48 | } 49 | -------------------------------------------------------------------------------- /plopfile.js: -------------------------------------------------------------------------------- 1 | const viewGenerator = require('./plop-templates/view/prompt') 2 | const componentGenerator = require('./plop-templates/component/prompt') 3 | const storeGenerator = require('./plop-templates/store/prompt.js') 4 | 5 | module.exports = function(plop) { 6 | plop.setGenerator('view', viewGenerator) 7 | plop.setGenerator('component', componentGenerator) 8 | plop.setGenerator('store', storeGenerator) 9 | } 10 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | autoprefixer: {} 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianPangJi/fe_admin/395c009cc57b26d562b7bae81928fff046aaf43d/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | <%= webpackConfig.name %> 10 | 11 | 12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /src/api/article.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | export function fetchList(query) { 4 | return request({ 5 | url: '/vue-element-admin/article/list', 6 | method: 'get', 7 | params: query 8 | }) 9 | } 10 | 11 | export function fetchArticle(id) { 12 | return request({ 13 | url: '/vue-element-admin/article/detail', 14 | method: 'get', 15 | params: { id } 16 | }) 17 | } 18 | 19 | export function fetchPv(pv) { 20 | return request({ 21 | url: '/vue-element-admin/article/pv', 22 | method: 'get', 23 | params: { pv } 24 | }) 25 | } 26 | 27 | export function createArticle(data) { 28 | return request({ 29 | url: '/vue-element-admin/article/create', 30 | method: 'post', 31 | data 32 | }) 33 | } 34 | 35 | export function updateArticle(data) { 36 | return request({ 37 | url: '/vue-element-admin/article/update', 38 | method: 'post', 39 | data 40 | }) 41 | } 42 | -------------------------------------------------------------------------------- /src/api/cmdb/assets.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // 获取资产状态列表 4 | export function getAssetsStatus() { 5 | return request({ 6 | url: '/cmdb/assets/status/', 7 | method: 'get' 8 | }) 9 | } 10 | 11 | // 获取资产管理员 12 | export function getAssetsAdmin(data) { 13 | return request({ 14 | url: `/cmdb/assets/admin/?search=${data}`, 15 | method: 'get' 16 | }) 17 | } 18 | 19 | // 获取机房机柜Tree结构数据 20 | export function getIDCCabinetsTree() { 21 | return request({ 22 | url: '/cmdb/assets/cabinets/', 23 | method: 'get' 24 | }) 25 | } 26 | -------------------------------------------------------------------------------- /src/api/cmdb/servers.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // 新增服务器 4 | export function createServer(data) { 5 | return request({ 6 | url: '/cmdb/servers/', 7 | method: 'post', 8 | data 9 | }) 10 | } 11 | 12 | // 删除服务器 13 | export function deleteServer(id) { 14 | return request({ 15 | url: `/cmdb/servers/${id}/`, 16 | method: 'delete' 17 | }) 18 | } 19 | 20 | // 批量删除服务器 21 | export function deleteServers(ids) { 22 | return request({ 23 | url: '/cmdb/servers/', 24 | method: 'delete', 25 | data: { 'ids': ids } 26 | }) 27 | } 28 | 29 | // 修改服务器 30 | export function updateServer(id, data) { 31 | return request({ 32 | url: `/cmdb/servers/${id}/`, 33 | method: 'put', 34 | data 35 | }) 36 | } 37 | 38 | // 获取服务器列表 39 | export function getServers(data) { 40 | return request({ 41 | url: '/cmdb/servers/', 42 | method: 'get', 43 | params: data 44 | }) 45 | } 46 | 47 | // 获取服务器详情 48 | export function getServer(id) { 49 | return request({ 50 | url: `/cmdb/servers/${id}/`, 51 | method: 'get' 52 | }) 53 | } 54 | 55 | // 获取服务器类型列表 56 | export function getServerType() { 57 | return request({ 58 | url: '/cmdb/servers/type/', 59 | method: 'get' 60 | }) 61 | } 62 | 63 | // 获取服务器系统类型列表 64 | export function getServerSystemType() { 65 | return request({ 66 | url: '/cmdb/servers/system-type/', 67 | method: 'get' 68 | }) 69 | } 70 | -------------------------------------------------------------------------------- /src/api/information/centre.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // 个人中心修改密码 4 | export function changePassword(data) { 5 | return request({ 6 | url: '/information/change-password/', 7 | method: 'put', 8 | data 9 | }) 10 | } 11 | 12 | // 个人中心修改头像 13 | export function changeAvatar(data) { 14 | return request({ 15 | url: '/information/change-avatar/', 16 | method: 'put', 17 | data 18 | }) 19 | } 20 | 21 | // 个人中心修改个人信息 22 | export function changeInformation(data) { 23 | return request({ 24 | url: '/information/change-information/', 25 | method: 'put', 26 | data 27 | }) 28 | } 29 | -------------------------------------------------------------------------------- /src/api/monitor/crud.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // 获取CRUD日志列表 4 | export function getCRUD(data) { 5 | return request({ 6 | url: '/monitor/crud/', 7 | method: 'get', 8 | params: data 9 | }) 10 | } 11 | -------------------------------------------------------------------------------- /src/api/monitor/error.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // 获取错误日志列表 4 | export function getErrorLogs(data) { 5 | return request({ 6 | url: '/monitor/error/', 7 | method: 'get', 8 | params: data 9 | }) 10 | } 11 | 12 | // 清空错误日志 13 | export function deleteErrorLogs() { 14 | return request({ 15 | url: '/monitor/error/', 16 | method: 'delete' 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /src/api/monitor/ip.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // 新增黑名单IP 4 | export function createIp(data) { 5 | return request({ 6 | url: '/monitor/ip/', 7 | method: 'post', 8 | data 9 | }) 10 | } 11 | 12 | // 删除黑名单IP 13 | export function deleteIp(id) { 14 | return request({ 15 | url: `/monitor/ip/${id}/`, 16 | method: 'delete' 17 | }) 18 | } 19 | 20 | // 批量删除黑名单IP 21 | export function deleteIps(ids) { 22 | return request({ 23 | url: '/monitor/ip/', 24 | method: 'delete', 25 | data: { 'ids': ids } 26 | }) 27 | } 28 | 29 | // 修改黑名单IP 30 | export function updateIp(id, data) { 31 | return request({ 32 | url: `/monitor/ip/${id}/`, 33 | method: 'put', 34 | data 35 | }) 36 | } 37 | 38 | // 获取黑名单IP列表 39 | export function getIps(data) { 40 | return request({ 41 | url: '/monitor/ip/', 42 | method: 'get', 43 | params: data 44 | }) 45 | } 46 | 47 | // 获取黑名单IP详情 48 | export function getIp(id) { 49 | return request({ 50 | url: `/monitor/ip/${id}/`, 51 | method: 'get' 52 | }) 53 | } 54 | -------------------------------------------------------------------------------- /src/api/monitor/service.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // 获取服务器信息 4 | export function getService() { 5 | return request({ 6 | url: '/monitor/service/', 7 | method: 'get' 8 | }) 9 | } 10 | -------------------------------------------------------------------------------- /src/api/monitor/users.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // 获取在线用户列表 4 | export function getUsers(data) { 5 | return request({ 6 | url: '/monitor/users/', 7 | method: 'get', 8 | params: data 9 | }) 10 | } 11 | -------------------------------------------------------------------------------- /src/api/qiniu.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | export function getToken() { 4 | return request({ 5 | url: '/qiniu/upload/token', // 假地址 自行替换 6 | method: 'get' 7 | }) 8 | } 9 | -------------------------------------------------------------------------------- /src/api/remote-search.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | export function searchUser(name) { 4 | return request({ 5 | url: '/vue-element-admin/search/user', 6 | method: 'get', 7 | params: { name } 8 | }) 9 | } 10 | 11 | export function transactionList(query) { 12 | return request({ 13 | url: '/vue-element-admin/transaction/list', 14 | method: 'get', 15 | params: query 16 | }) 17 | } 18 | -------------------------------------------------------------------------------- /src/api/role.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | export function getRoutes() { 4 | return request({ 5 | url: '/vue-element-admin/routes', 6 | method: 'get' 7 | }) 8 | } 9 | 10 | export function getRoles() { 11 | return request({ 12 | url: '/vue-element-admin/roles', 13 | method: 'get' 14 | }) 15 | } 16 | 17 | export function addRole(data) { 18 | return request({ 19 | url: '/vue-element-admin/role', 20 | method: 'post', 21 | data 22 | }) 23 | } 24 | 25 | export function updateRole(id, data) { 26 | return request({ 27 | url: `/vue-element-admin/role/${id}`, 28 | method: 'put', 29 | data 30 | }) 31 | } 32 | 33 | export function deleteRole(id) { 34 | return request({ 35 | url: `/vue-element-admin/role/${id}`, 36 | method: 'delete' 37 | }) 38 | } 39 | -------------------------------------------------------------------------------- /src/api/system/departments.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // 新增部门 4 | export function createDepartment(data) { 5 | return request({ 6 | url: '/system/departments/', 7 | method: 'post', 8 | data 9 | }) 10 | } 11 | 12 | // 删除部门 13 | export function deleteDepartment(id) { 14 | return request({ 15 | url: `/system/departments/${id}/`, 16 | method: 'delete' 17 | }) 18 | } 19 | 20 | // 批量删除部门 21 | export function deleteDepartments(ids) { 22 | return request({ 23 | url: '/system/departments/', 24 | method: 'delete', 25 | data: { 'ids': ids } 26 | }) 27 | } 28 | 29 | // 修改部门 30 | export function updateDepartment(id, data) { 31 | return request({ 32 | url: `/system/departments/${id}/`, 33 | method: 'put', 34 | data 35 | }) 36 | } 37 | 38 | // 获取部门列表 39 | export function getDepartments(data) { 40 | return request({ 41 | url: '/system/departments/', 42 | method: 'get', 43 | params: data 44 | }) 45 | } 46 | 47 | // 获取部门详情 48 | export function getDepartment(id) { 49 | return request({ 50 | url: `/system/departments/${id}/`, 51 | method: 'get' 52 | }) 53 | } 54 | -------------------------------------------------------------------------------- /src/api/system/jobs.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // 新增调度任务 4 | export function createJob(data) { 5 | return request({ 6 | url: '/system/jobs/', 7 | method: 'post', 8 | data 9 | }) 10 | } 11 | 12 | // 删除调度任务 13 | export function deleteJob(id) { 14 | return request({ 15 | url: `/system/jobs/${id}/`, 16 | method: 'delete' 17 | }) 18 | } 19 | 20 | // 清除所有调度任务 21 | export function deleteJobs() { 22 | return request({ 23 | url: '/system/jobs/', 24 | method: 'delete' 25 | }) 26 | } 27 | 28 | // 启动/暂停调度任务 29 | export function updateJob(id, data) { 30 | return request({ 31 | url: `/system/jobs/${id}/`, 32 | method: 'patch', 33 | data 34 | }) 35 | } 36 | 37 | // 获取调度任务列表 38 | export function getJobs(data) { 39 | return request({ 40 | url: '/system/jobs/', 41 | method: 'get', 42 | params: data 43 | }) 44 | } 45 | 46 | // 获取调度任务-任务函数列表 47 | export function getJobFunctions(data) { 48 | return request({ 49 | url: '/system/jobs/functions/', 50 | method: 'get', 51 | params: data 52 | }) 53 | } 54 | 55 | // 获取调度任务-执行过程列表 56 | export function getJobExecutions(data) { 57 | return request({ 58 | url: '/system/jobs/executions/', 59 | method: 'get', 60 | params: data 61 | }) 62 | } 63 | -------------------------------------------------------------------------------- /src/api/system/permissions.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // 新增权限 4 | export function createPermission(data) { 5 | return request({ 6 | url: '/system/permissions/', 7 | method: 'post', 8 | data 9 | }) 10 | } 11 | 12 | // 删除权限 13 | export function deletePermission(id) { 14 | return request({ 15 | url: `/system/permissions/${id}/`, 16 | method: 'delete' 17 | }) 18 | } 19 | 20 | // 批量删除权限 21 | export function deletePermissions(ids) { 22 | return request({ 23 | url: '/system/permissions/', 24 | method: 'delete', 25 | data: { 'ids': ids } 26 | }) 27 | } 28 | 29 | // 修改权限 30 | export function updatePermission(id, data) { 31 | return request({ 32 | url: `/system/permissions/${id}/`, 33 | method: 'put', 34 | data 35 | }) 36 | } 37 | 38 | // 获取权限列表 39 | export function getPermissions(data) { 40 | return request({ 41 | url: '/system/permissions/', 42 | method: 'get', 43 | params: data 44 | }) 45 | } 46 | 47 | // 获取权限详情 48 | export function getPermission(id) { 49 | return request({ 50 | url: `/system/permissions/${id}/`, 51 | method: 'get' 52 | }) 53 | } 54 | 55 | // 获取请求方法列表 56 | export function getPermissionMethods() { 57 | return request({ 58 | url: '/system/permissions/methods/', 59 | method: 'get' 60 | }) 61 | } 62 | -------------------------------------------------------------------------------- /src/api/system/roles.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // 新增角色 4 | export function createRole(data) { 5 | return request({ 6 | url: '/system/roles/', 7 | method: 'post', 8 | data 9 | }) 10 | } 11 | 12 | // 删除角色 13 | export function deleteRole(id) { 14 | return request({ 15 | url: `/system/roles/${id}/`, 16 | method: 'delete' 17 | }) 18 | } 19 | 20 | // 批量删除角色 21 | export function deleteRoles(ids) { 22 | return request({ 23 | url: '/system/roles/', 24 | method: 'delete', 25 | data: { 'ids': ids } 26 | }) 27 | } 28 | 29 | // 修改角色 30 | export function updateRole(id, data) { 31 | return request({ 32 | url: `/system/roles/${id}/`, 33 | method: 'put', 34 | data 35 | }) 36 | } 37 | 38 | // 修改角色权限 39 | export function updateRolePermissions(id, permissions) { 40 | return request({ 41 | url: `/system/roles/${id}/`, 42 | method: 'patch', 43 | data: { 'permissions': permissions } 44 | }) 45 | } 46 | 47 | // 获取角色列表 48 | export function getRoles(data) { 49 | return request({ 50 | url: '/system/roles/', 51 | method: 'get', 52 | params: data 53 | }) 54 | } 55 | 56 | // 获取角色详情 57 | export function getRole(id) { 58 | return request({ 59 | url: `/system/roles/${id}/`, 60 | method: 'get' 61 | }) 62 | } 63 | -------------------------------------------------------------------------------- /src/api/system/users.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // 新增用户 4 | export function createUser(data) { 5 | return request({ 6 | url: '/system/users/', 7 | method: 'post', 8 | data 9 | }) 10 | } 11 | 12 | // 删除用户 13 | export function deleteUser(id) { 14 | return request({ 15 | url: `/system/users/${id}/`, 16 | method: 'delete' 17 | }) 18 | } 19 | 20 | // 批量删除用户 21 | export function deleteUsers(ids) { 22 | return request({ 23 | url: '/system/users/', 24 | method: 'delete', 25 | data: { 'ids': ids } 26 | }) 27 | } 28 | 29 | // 修改用户 30 | export function updateUser(id, data) { 31 | return request({ 32 | url: `/system/users/${id}/`, 33 | method: 'put', 34 | data 35 | }) 36 | } 37 | 38 | // 修改用户状态 39 | export function updateUserActive(id, data) { 40 | return request({ 41 | url: `/system/users/${id}/`, 42 | method: 'patch', 43 | data 44 | }) 45 | } 46 | 47 | // 获取用户列表 48 | export function getUsers(data) { 49 | return request({ 50 | url: '/system/users/', 51 | method: 'get', 52 | params: data 53 | }) 54 | } 55 | 56 | // 获取用户详情 57 | export function getUser(id) { 58 | return request({ 59 | url: `/system/users/${id}/`, 60 | method: 'get' 61 | }) 62 | } 63 | 64 | // 重置密码 65 | export function resetPassword(id, data) { 66 | return request({ 67 | url: `/system/users/reset-password/${id}/`, 68 | method: 'patch', 69 | data 70 | }) 71 | } 72 | 73 | // 获取用户权限列表 74 | export function getUserPermissions(id) { 75 | return request({ 76 | url: `/system/users/${id}/permissions/`, 77 | method: 'get' 78 | }) 79 | } 80 | -------------------------------------------------------------------------------- /src/api/user.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // 用户登录 4 | export function login(data) { 5 | return request({ 6 | url: '/oauth/login/', 7 | method: 'post', 8 | data 9 | }) 10 | } 11 | 12 | // 获取当前登录用户信息 13 | export function getInfo() { 14 | return request({ 15 | url: '/oauth/info/', 16 | method: 'get' 17 | }) 18 | } 19 | 20 | // 用户登出 21 | export function logout() { 22 | return request({ 23 | url: '/oauth/logout/', 24 | method: 'post' 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /src/assets/401_images/401.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianPangJi/fe_admin/395c009cc57b26d562b7bae81928fff046aaf43d/src/assets/401_images/401.gif -------------------------------------------------------------------------------- /src/assets/404_images/404.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianPangJi/fe_admin/395c009cc57b26d562b7bae81928fff046aaf43d/src/assets/404_images/404.png -------------------------------------------------------------------------------- /src/assets/404_images/404_cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianPangJi/fe_admin/395c009cc57b26d562b7bae81928fff046aaf43d/src/assets/404_images/404_cloud.png -------------------------------------------------------------------------------- /src/assets/custom-theme/fonts/element-icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianPangJi/fe_admin/395c009cc57b26d562b7bae81928fff046aaf43d/src/assets/custom-theme/fonts/element-icons.ttf -------------------------------------------------------------------------------- /src/assets/custom-theme/fonts/element-icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianPangJi/fe_admin/395c009cc57b26d562b7bae81928fff046aaf43d/src/assets/custom-theme/fonts/element-icons.woff -------------------------------------------------------------------------------- /src/assets/images/login-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TianPangJi/fe_admin/395c009cc57b26d562b7bae81928fff046aaf43d/src/assets/images/login-bg.jpg -------------------------------------------------------------------------------- /src/components/Charts/mixins/resize.js: -------------------------------------------------------------------------------- 1 | import { debounce } from '@/utils' 2 | 3 | export default { 4 | data() { 5 | return { 6 | $_sidebarElm: null, 7 | $_resizeHandler: null 8 | } 9 | }, 10 | mounted() { 11 | this.initListener() 12 | }, 13 | activated() { 14 | if (!this.$_resizeHandler) { 15 | // avoid duplication init 16 | this.initListener() 17 | } 18 | 19 | // when keep-alive chart activated, auto resize 20 | this.resize() 21 | }, 22 | beforeDestroy() { 23 | this.destroyListener() 24 | }, 25 | deactivated() { 26 | this.destroyListener() 27 | }, 28 | methods: { 29 | // use $_ for mixins properties 30 | // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential 31 | $_sidebarResizeHandler(e) { 32 | if (e.propertyName === 'width') { 33 | this.$_resizeHandler() 34 | } 35 | }, 36 | initListener() { 37 | this.$_resizeHandler = debounce(() => { 38 | this.resize() 39 | }, 100) 40 | window.addEventListener('resize', this.$_resizeHandler) 41 | 42 | this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0] 43 | this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler) 44 | }, 45 | destroyListener() { 46 | window.removeEventListener('resize', this.$_resizeHandler) 47 | this.$_resizeHandler = null 48 | 49 | this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler) 50 | }, 51 | resize() { 52 | const { chart } = this 53 | chart && chart.resize() 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/components/DragSelect/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 50 | 51 | 66 | -------------------------------------------------------------------------------- /src/components/GithubCorner/index.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 55 | -------------------------------------------------------------------------------- /src/components/Hamburger/index.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 32 | 33 | 45 | -------------------------------------------------------------------------------- /src/components/ImageCropper/utils/data2blob.js: -------------------------------------------------------------------------------- 1 | /** 2 | * database64文件格式转换为2进制 3 | * 4 | * @param {[String]} data dataURL 的格式为 “data:image/png;base64,****”,逗号之前都是一些说明性的文字,我们只需要逗号之后的就行了 5 | * @param {[String]} mime [description] 6 | * @return {[blob]} [description] 7 | */ 8 | export default function(data, mime) { 9 | data = data.split(',')[1] 10 | data = window.atob(data) 11 | var ia = new Uint8Array(data.length) 12 | for (var i = 0; i < data.length; i++) { 13 | ia[i] = data.charCodeAt(i) 14 | } 15 | // canvas.toDataURL 返回的默认格式就是 image/png 16 | return new Blob([ia], { 17 | type: mime 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /src/components/ImageCropper/utils/effectRipple.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 点击波纹效果 3 | * 4 | * @param {[event]} e [description] 5 | * @param {[Object]} arg_opts [description] 6 | * @return {[bollean]} [description] 7 | */ 8 | export default function(e, arg_opts) { 9 | var opts = Object.assign({ 10 | ele: e.target, // 波纹作用元素 11 | type: 'hit', // hit点击位置扩散center中心点扩展 12 | bgc: 'rgba(0, 0, 0, 0.15)' // 波纹颜色 13 | }, arg_opts) 14 | var target = opts.ele 15 | if (target) { 16 | var rect = target.getBoundingClientRect() 17 | var ripple = target.querySelector('.e-ripple') 18 | if (!ripple) { 19 | ripple = document.createElement('span') 20 | ripple.className = 'e-ripple' 21 | ripple.style.height = ripple.style.width = Math.max(rect.width, rect.height) + 'px' 22 | target.appendChild(ripple) 23 | } else { 24 | ripple.className = 'e-ripple' 25 | } 26 | switch (opts.type) { 27 | case 'center': 28 | ripple.style.top = (rect.height / 2 - ripple.offsetHeight / 2) + 'px' 29 | ripple.style.left = (rect.width / 2 - ripple.offsetWidth / 2) + 'px' 30 | break 31 | default: 32 | ripple.style.top = (e.pageY - rect.top - ripple.offsetHeight / 2 - document.body.scrollTop) + 'px' 33 | ripple.style.left = (e.pageX - rect.left - ripple.offsetWidth / 2 - document.body.scrollLeft) + 'px' 34 | } 35 | ripple.style.backgroundColor = opts.bgc 36 | ripple.className = 'e-ripple z-active' 37 | return false 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/components/ImageCropper/utils/mimes.js: -------------------------------------------------------------------------------- 1 | export default { 2 | 'jpg': 'image/jpeg', 3 | 'png': 'image/png', 4 | 'gif': 'image/gif', 5 | 'svg': 'image/svg+xml', 6 | 'psd': 'image/photoshop' 7 | } 8 | -------------------------------------------------------------------------------- /src/components/JsonEditor/index.vue: -------------------------------------------------------------------------------- 1 |