├── .vscode └── settings.json ├── src ├── assets │ ├── tip │ │ ├── help │ │ │ ├── project.md │ │ │ ├── body.md │ │ │ ├── baseObject.md │ │ │ └── group.md │ │ └── requestparams │ │ │ ├── body.md │ │ │ ├── path.md │ │ │ └── query.md │ ├── image │ │ ├── jt.png │ │ ├── comp.png │ │ ├── logo.png │ │ ├── noImg.png │ │ ├── audioImg.png │ │ ├── javascr.jpg │ │ ├── login │ │ │ └── 1.png │ │ ├── Arrow_Down.png │ │ ├── project │ │ │ ├── qr.png │ │ │ ├── folder.png │ │ │ ├── cover-media.jpg │ │ │ └── cover-other.jpg │ │ ├── view-source.gif │ │ ├── group │ │ │ └── default.png │ │ └── header │ │ │ └── default.png │ ├── data │ │ ├── group_new │ │ ├── user.json │ │ ├── content.yaml │ │ ├── group_list │ │ ├── apis.json │ │ ├── editorSetting.json │ │ ├── project.json │ │ ├── menu.json │ │ └── draf.json │ ├── js │ │ ├── metadata.js │ │ ├── vuelint.js │ │ └── base.js │ └── style │ │ └── app.styl ├── store │ ├── getters.js │ ├── lng │ │ └── en.js │ ├── mutations.js │ ├── index.js │ ├── actions.js │ └── metadata.js ├── config │ ├── default.js │ ├── production.js │ ├── local.js │ └── index.js ├── login.js ├── emailActive.js ├── updatePassword.js ├── components │ ├── Footer.vue │ ├── User │ │ └── Item.vue │ ├── Content.vue │ ├── Dialogs.vue │ ├── Welcome.vue │ ├── CodeEditer.vue │ ├── pie-chart.vue │ ├── Upload.vue │ ├── PageRouter.vue │ ├── Tags.vue │ ├── Sidebar.vue │ └── Header.vue ├── RouterMap.js ├── emailActive.vue ├── dialog │ ├── DAddGroup.vue │ ├── DGroupsNew.vue │ ├── DAddPage.vue │ └── DCopyPage.vue ├── pages │ ├── projects │ │ ├── new.vue │ │ └── data.vue │ ├── 404.vue │ ├── noPage.vue │ ├── groups │ │ ├── new.vue │ │ └── CNew.vue │ ├── user.vue │ ├── pages │ │ ├── CDoc.vue │ │ ├── history.vue │ │ └── CNew.vue │ ├── dashboard │ │ ├── groups.vue │ │ └── component.vue │ ├── component │ │ └── editer.vue │ ├── completePage.vue │ ├── project.vue │ └── page.vue ├── extend │ ├── BaseComponent.js │ ├── Server.js │ ├── BasePage.js │ ├── BaseDialog.js │ ├── chartOptions.js │ ├── filter.js │ ├── UploadImg.js │ └── Util.js ├── main.js ├── app.vue └── updatePassword.vue ├── babel.config.js ├── .eslintignore ├── .gitignore ├── login.tpl ├── emailActive.tpl ├── updatePassword.tpl ├── .eslintrc.js ├── LICENSE ├── index.tpl ├── package.json ├── README.md ├── vue.config.js └── public └── fullpage.min.css /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /src/assets/tip/help/project.md: -------------------------------------------------------------------------------- 1 | 1. 每个项目存在很多页面 2 | 2. 不知道说啥 3 | 4 | -------------------------------------------------------------------------------- /src/store/getters.js: -------------------------------------------------------------------------------- 1 | export const getTwoNav = state => { 2 | } 3 | -------------------------------------------------------------------------------- /src/store/lng/en.js: -------------------------------------------------------------------------------- 1 | var Lng = { 2 | common: {} 3 | } 4 | export default Lng 5 | -------------------------------------------------------------------------------- /src/assets/tip/help/body.md: -------------------------------------------------------------------------------- 1 | ##### body 参数说明 2 | 一般在POST,PUT,PATCH 等操作的时候通过body传递整块的数据 -------------------------------------------------------------------------------- /src/assets/tip/requestparams/body.md: -------------------------------------------------------------------------------- 1 | ##### body 参数说明 2 | 一般在POST,PUT,PATCH 等操作的时候通过body传递整块的数据 -------------------------------------------------------------------------------- /src/assets/image/jt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ymm-tech/gods-pen-admin/HEAD/src/assets/image/jt.png -------------------------------------------------------------------------------- /src/assets/tip/requestparams/path.md: -------------------------------------------------------------------------------- 1 | ##### path 参数说明 2 | 一般在url上 例如 http://xxx/xx/:id 其中id的参数就是path替换的地方 -------------------------------------------------------------------------------- /src/assets/image/comp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ymm-tech/gods-pen-admin/HEAD/src/assets/image/comp.png -------------------------------------------------------------------------------- /src/assets/image/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ymm-tech/gods-pen-admin/HEAD/src/assets/image/logo.png -------------------------------------------------------------------------------- /src/assets/image/noImg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ymm-tech/gods-pen-admin/HEAD/src/assets/image/noImg.png -------------------------------------------------------------------------------- /src/assets/image/audioImg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ymm-tech/gods-pen-admin/HEAD/src/assets/image/audioImg.png -------------------------------------------------------------------------------- /src/assets/image/javascr.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ymm-tech/gods-pen-admin/HEAD/src/assets/image/javascr.jpg -------------------------------------------------------------------------------- /src/assets/image/login/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ymm-tech/gods-pen-admin/HEAD/src/assets/image/login/1.png -------------------------------------------------------------------------------- /src/assets/tip/help/baseObject.md: -------------------------------------------------------------------------------- 1 | 基础对象 2 | 基础对象可以理解为该项目的常用MODEL对象。可以导入项目中的model对象到基础对象中方便后续再页面数据返回的的时候快速使用已经定义好的对象 -------------------------------------------------------------------------------- /src/assets/image/Arrow_Down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ymm-tech/gods-pen-admin/HEAD/src/assets/image/Arrow_Down.png -------------------------------------------------------------------------------- /src/assets/image/project/qr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ymm-tech/gods-pen-admin/HEAD/src/assets/image/project/qr.png -------------------------------------------------------------------------------- /src/assets/image/view-source.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ymm-tech/gods-pen-admin/HEAD/src/assets/image/view-source.gif -------------------------------------------------------------------------------- /src/assets/image/group/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ymm-tech/gods-pen-admin/HEAD/src/assets/image/group/default.png -------------------------------------------------------------------------------- /src/assets/tip/requestparams/query.md: -------------------------------------------------------------------------------- 1 | ##### query 参数说明 2 | 一般在GET 等操作的时候在地址上的查询参数值,例如 http://xxx/index.html?id=1&k=2 中的 id和k等参数值 -------------------------------------------------------------------------------- /src/assets/image/header/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ymm-tech/gods-pen-admin/HEAD/src/assets/image/header/default.png -------------------------------------------------------------------------------- /src/assets/image/project/folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ymm-tech/gods-pen-admin/HEAD/src/assets/image/project/folder.png -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | comments: true, 3 | presets: [ 4 | ['@vue/app', {useBuiltIns: false}] 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /src/assets/data/group_new: -------------------------------------------------------------------------------- 1 | { 2 | "visibilitylevel":1, 3 | "description":"描述", 4 | "img":"url", 5 | "name":"项目名称", 6 | "id":12 7 | } -------------------------------------------------------------------------------- /src/assets/image/project/cover-media.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ymm-tech/gods-pen-admin/HEAD/src/assets/image/project/cover-media.jpg -------------------------------------------------------------------------------- /src/assets/image/project/cover-other.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ymm-tech/gods-pen-admin/HEAD/src/assets/image/project/cover-other.jpg -------------------------------------------------------------------------------- /src/assets/tip/help/group.md: -------------------------------------------------------------------------------- 1 | 1. 所有项目都会在一个项目组里面。 2 | 2. 每个人在组里面有不同的权限 3 | 创建者: 可以管理组里面的人和组的基本信息,并且在该组的项目里面有管理员的权限 4 | 管理员: 在该组项目中有管理员权限 5 | 开发者: 在该组项目中有开发者权限 6 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | dist/ 3 | src/assets/ 4 | src/assets/js/ 5 | src/components/PageRouter.vue 6 | src/components/Dialogs.vue 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | .cache 3 | .DS_Store 4 | .idea 5 | build 6 | dist 7 | node_modules 8 | .gitkeep 9 | converage 10 | yarn-error.log 11 | npm-debug.log 12 | .yarnclean 13 | src/config/docker.js -------------------------------------------------------------------------------- /src/config/default.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | VIEW_PATH: 'view', 3 | ADMIN_PATH: 'admin', 4 | EDITOR_PATH: 'editor', 5 | API_PATH: 'api', 6 | EDITOR_TITLE: '编辑器', 7 | ADMIN_TITLE: '管理后台', 8 | BAIDU_TONGJI: '' 9 | } 10 | -------------------------------------------------------------------------------- /src/assets/data/user.json: -------------------------------------------------------------------------------- 1 | { 2 | "code":1, 3 | "list":[1,1,1], 4 | "data":{ 5 | "id":12, 6 | "name":"王坤明", 7 | "email":"fdsa@qq.com", 8 | "account":"stoneship", 9 | "createTime":1481870187006, 10 | "updateTime":1481870187006 11 | } 12 | } 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/config/production.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 对于三个web项目,在构建阶段,web项目不再需要启动本地服务,一般来说, 3 | * 构建完成后会将所有静态资源文件部署在同一个(nginx)服务下,因此, 4 | * web项目的默认访问路径就是域名加项目名,如 xxxx.com/admin, 5 | * xxxx.com/editor,如无更名要求,无需再配置 6 | * 7 | * 对于 api 服务,服务启动以后,本地/内部访问地址为 http://127.0.0.1:7051/api, 8 | * 如果最终能通过 nginx 反代等操作使之与 web 服务同域名同端口号, 9 | * 则可以保持以下配置(无需配置)即可,否则,请将 API_PATH 配置为 api 服务外部实际访 10 | * 问路径,如 http://abc.125:7051/api 11 | */ 12 | 13 | module.exports = { 14 | } 15 | -------------------------------------------------------------------------------- /src/config/local.js: -------------------------------------------------------------------------------- 1 | /* 2 | * 在本地开发调试时,三个web项目和一个node项目都是在独立运行的 3 | * 因此需要配置每个服务的本地访问地址,以使能互相调用/请求 4 | * admin、editor、view、api 四个服务的默认端口号分别为 5 | * 8567、8565、8566、7051,因此默认配置如下 6 | */ 7 | 8 | module.exports = { 9 | ADMIN_PATH: 'http://127.0.0.1:8567/', // 管理后台访问地址 10 | EDITOR_PATH: 'http://127.0.0.1:8565/', // 编辑器访问地址 11 | VIEW_PATH: 'http://127.0.0.1:8566/', // 页面客户端访问地址 12 | API_PATH: 'http://127.0.0.1:7051/api', // api 服务端访问地址 13 | } 14 | -------------------------------------------------------------------------------- /src/login.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import ElementUI from 'element-ui' 3 | import Login from './login.vue' 4 | import EmaProxy from 'ema-proxy' 5 | import 'element-ui/lib/theme-chalk/index.css' 6 | require('./assets/js/base') 7 | window.EMA = new EmaProxy() 8 | require('./assets/style/base.css') 9 | 10 | Vue.use(ElementUI) 11 | Vue.config.devtools = !(process.env.NODE_ENV === 'production') 12 | 13 | new Vue({ 14 | el: '#app', 15 | render: h => h(Login) 16 | }) 17 | -------------------------------------------------------------------------------- /src/emailActive.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import ElementUI from 'element-ui' 3 | import emailActive from './emailActive.vue' 4 | import 'element-ui/lib/theme-chalk/index.css' 5 | require('./assets/js/base') 6 | require('./assets/style/base.css') 7 | import EmaProxy from 'ema-proxy' 8 | window.EMA = new EmaProxy() 9 | 10 | Vue.use(ElementUI) 11 | Vue.config.devtools = !(process.env.NODE_ENV === 'production') 12 | 13 | new Vue({ 14 | el: '#app', 15 | render: h => h(emailActive) 16 | }) 17 | -------------------------------------------------------------------------------- /src/assets/data/content.yaml: -------------------------------------------------------------------------------- 1 | path: /name 2 | type: get 3 | description: 获取用户姓名 4 | parameters: 5 | id: int|用户id 6 | name: string|用户姓名 7 | responses: 8 | 200: 9 | pageSize: int 10 | list: 11 | - name: int|描述 12 | url: string|描述 13 | pets: 14 | - $ref: $Pet 15 | age: int 16 | 500: 17 | code: int 18 | error: string 19 | definitions: 20 | Pet: 21 | product_id: string|Unique identifier 22 | description: string|Description of product. 23 | -------------------------------------------------------------------------------- /src/updatePassword.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import ElementUI from 'element-ui' 3 | import updatePassword from './updatePassword.vue' 4 | import 'element-ui/lib/theme-chalk/index.css' 5 | require('./assets/js/base') 6 | require('./assets/style/base.css') 7 | import EmaProxy from 'ema-proxy' 8 | window.EMA = new EmaProxy() 9 | 10 | Vue.use(ElementUI) 11 | Vue.config.devtools = !(process.env.NODE_ENV === 'production') 12 | 13 | new Vue({ 14 | el: '#app', 15 | render: h => h(updatePassword) 16 | }) 17 | -------------------------------------------------------------------------------- /src/assets/data/group_list: -------------------------------------------------------------------------------- 1 | { 2 | "pageSize": "12", 3 | "list": [ 4 | { 5 | "visibilitylevel":1, 6 | "description":"描述", 7 | "img":"http://secure.gravatar.com/avatar/fc5654afbe167b98e93674175607b80e?s=52&d=identicon", 8 | "name":"项目名称", 9 | "member":12, 10 | "role":1 11 | }, 12 | { 13 | "visibilitylevel":1, 14 | "description":"描述", 15 | "img":"http://secure.gravatar.com/avatar/fc5654afbe167b98e93674175607b80e?s=52&d=identicon", 16 | "name":"项目名2称", 17 | "member":12, 18 | "role":2 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /src/assets/data/apis.json: -------------------------------------------------------------------------------- 1 | { 2 | "list": [ 3 | { 4 | "createTime":1481870187006, 5 | "updateTime":1481870187006, 6 | "version":"1.1.2", 7 | "content":"", 8 | "path":"/home/user", 9 | "type":"get", 10 | "desc":"好多联系哈哈", 11 | "pid":10, 12 | "id":12 13 | }, 14 | { 15 | "createTime":1481870187006, 16 | "updateTime":1481870187006, 17 | "version":"1.1.2", 18 | "content":"", 19 | "path":"/home/add", 20 | "type":"post", 21 | "desc":"好多联系哈哈", 22 | "pid":10, 23 | "id":12 24 | } 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /src/config/index.js: -------------------------------------------------------------------------------- 1 | const defaultConfig = require('./default') 2 | 3 | let config = Object.assign(defaultConfig, require('./' + (process.env.CODE_ENV || 'local'))) 4 | 5 | ;['VIEW_PATH', 'ADMIN_PATH', 'EDITOR_PATH', 'API_PATH'].map(k => { 6 | if (config[k] === '/') return 7 | if (/^(https?:)?\/\//.test(config[k])) { 8 | config[k] = config[k].replace(/\/*$/, '/') 9 | } else { 10 | config[k] = config[k].replace(/^\/*|\/*$/g, '/') 11 | } 12 | }) 13 | 14 | config.ADMIN_NAME = process.env.NODE_ENV === 'development' ? '' : (config.ADMIN_PATH.match(/([^/]+)\/?$/) || ['', 'admin'])[1] 15 | 16 | config.enableGithub = config.github && config.github.clientId && config.github.clientSecret 17 | 18 | module.exports = config 19 | -------------------------------------------------------------------------------- /login.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <%= htmlWebpackPlugin.options.title %> 7 | 8 | 9 |
10 | <% if (/^[0-9a-zA-Z]{10,}$/.test(htmlWebpackPlugin.options.hmid)) { %> 11 | 12 | <% } %> 13 | <% if (process.env.NODE_ENV === 'production') { %> 14 | 15 | <% } %> 16 | 17 | 18 | -------------------------------------------------------------------------------- /emailActive.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <%= htmlWebpackPlugin.options.title %> 7 | 8 | 9 |
10 | <% if (/^[0-9a-zA-Z]{10,}$/.test(htmlWebpackPlugin.options.hmid)) { %> 11 | 12 | <% } %> 13 | <% if (process.env.NODE_ENV === 'production') { %> 14 | 15 | <% } %> 16 | 17 | 18 | -------------------------------------------------------------------------------- /updatePassword.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <%= htmlWebpackPlugin.options.title %> 7 | 8 | 9 |
10 | <% if (/^[0-9a-zA-Z]{10,}$/.test(htmlWebpackPlugin.options.hmid)) { %> 11 | 12 | <% } %> 13 | <% if (process.env.NODE_ENV === 'production') { %> 14 | 15 | <% } %> 16 | 17 | 18 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parserOptions: { 4 | sourceType: 'module', 5 | "allowImportExportEverywhere": true 6 | }, 7 | // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style 8 | extends: 'standard', 9 | // required to lint *.vue files 10 | plugins: [ 11 | 'html' 12 | ], 13 | // add your custom rules here 14 | 'rules': { 15 | "indent": 0, 16 | "no-multi-spaces": 0, 17 | "no-eval": 0, 18 | "no-new": 0, 19 | // allow paren-less arrow functions 20 | 'arrow-parens': 0, 21 | // allow debugger during development 22 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, 23 | "eqeqeq": 0,//必须使用全等 24 | "comma-dangle": [ 2, "only-multiline" ] //定义数组或对象最后多余的逗号 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/components/Footer.vue: -------------------------------------------------------------------------------- 1 | 10 | 13 | 28 | 29 | -------------------------------------------------------------------------------- /src/RouterMap.js: -------------------------------------------------------------------------------- 1 | import PageRouter from './components/PageRouter.vue' 2 | const config = require('./config/index.js') 3 | var map = { 4 | mode: 'hash', 5 | base: '/' + config.ADMIN_NAME, 6 | routes: [ 7 | { 8 | path: '/:name/:name1/:name2/:name3/:name4/name5', 9 | component: PageRouter 10 | }, 11 | { 12 | path: '/:name/:name1/:name2/:name3/:name4', 13 | component: PageRouter 14 | }, 15 | { 16 | path: '/:name/:name1/:name2/:name3', 17 | component: PageRouter 18 | }, 19 | { 20 | path: '/:name/:name1/:name2', 21 | component: PageRouter 22 | }, 23 | { 24 | path: '/:name/:name1', 25 | component: PageRouter 26 | }, 27 | { 28 | path: '/:name', 29 | component: PageRouter 30 | }, 31 | { 32 | path: '/', 33 | redirect: '/home' 34 | } 35 | ] 36 | } 37 | export default map 38 | -------------------------------------------------------------------------------- /src/components/User/Item.vue: -------------------------------------------------------------------------------- 1 | 12 | 16 | 36 | 37 | -------------------------------------------------------------------------------- /src/store/mutations.js: -------------------------------------------------------------------------------- 1 | export const initMenuData = (state, data) => { 2 | state.app.menuData = data 3 | } 4 | export const initUserInfo = (state, data) => { 5 | state.userInfo = { ...state.userInfo, 6 | ...data 7 | } 8 | } 9 | 10 | export const changeActiveIndex = (state, data) => { 11 | // 通过更新子节点修改对应导航的列表信息 12 | state.app.activeIndex = data 13 | } 14 | 15 | export const changeNavIndex = (state, data) => { 16 | state.app.navIndex = data || 0 17 | } 18 | 19 | export const changeNavTwoIndex = (state, data) => { 20 | state.app.navTwoIndex = data || 0 21 | } 22 | 23 | export const updataTheme = (state, data) => { 24 | Object.assign(state.app.theme, data) 25 | window.localStorage.setItem('theme', JSON.stringify(state.app.theme)) 26 | } 27 | 28 | export const changeAppSize = (state, data) => { 29 | if (data.width) { 30 | state.app.size.width = data.width 31 | } 32 | if (data.height) { 33 | state.app.size.height = data.height 34 | } 35 | } 36 | export const initCategorys = (state, data) => { 37 | state.Categorys = data 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Full Truck Alliance 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/emailActive.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 8 | 9 | 37 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vuex from 'vuex' 2 | import Vue from 'vue' 3 | import Metadata from 'src/store/metadata' 4 | import Lng from 'src/store/lng/en' 5 | import * as getters from './getters' 6 | import * as actions from './actions' 7 | import * as mutations from './mutations' 8 | var packageInfo = require('../../package.json') 9 | const debug = process.env.NODE_ENV !== 'production' 10 | if (debug) { 11 | Vue.use(Vuex) 12 | } 13 | // 初始化主题信息 14 | var theme = { 15 | isOpen: false, 16 | isLock: true 17 | } 18 | var localTheme = window.localStorage.getItem('theme') 19 | if (localTheme) { 20 | Object.assign(theme, JSON.parse(localTheme)) 21 | } 22 | const state = { 23 | app: { 24 | theme: theme, // 应用主题信息。 25 | packageInfo, 26 | navIndex: 0, // 导航索引 27 | navTwoIndex: 0, // 导航索引 28 | activeIndex: null, // 当前被选中的页面唯一编号id, 29 | size: { 30 | width: 0, 31 | height: 0 32 | }, 33 | menuData: [] // 功能菜单列表信息 34 | }, 35 | Lng: Lng, 36 | userInfo: {}, 37 | Categorys: [], 38 | Metadata 39 | } 40 | 41 | export default new Vuex.Store({ 42 | strict: debug, 43 | state, 44 | actions, 45 | getters: getters, 46 | mutations 47 | }) 48 | -------------------------------------------------------------------------------- /src/dialog/DAddGroup.vue: -------------------------------------------------------------------------------- 1 | 10 | 24 | 51 | 52 | -------------------------------------------------------------------------------- /src/dialog/DGroupsNew.vue: -------------------------------------------------------------------------------- 1 | 8 | 11 | 52 | 53 | -------------------------------------------------------------------------------- /src/pages/projects/new.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 24 | 25 | 52 | -------------------------------------------------------------------------------- /src/assets/data/editorSetting.json: -------------------------------------------------------------------------------- 1 | { 2 | "selectionStyle": "line", 3 | "highlightActiveLine": true, 4 | "highlightSelectedWord": true, 5 | "readOnly": false, 6 | "cursorStyle": "ace", 7 | "mergeUndoDeltas": true, 8 | "behavioursEnabled": true, 9 | "wrapBehavioursEnabled": true, 10 | "hScrollBarAlwaysVisible": false, 11 | "vScrollBarAlwaysVisible": false, 12 | "highlightGutterLine": true, 13 | "animatedScroll": false, 14 | "showInvisibles": false, 15 | "showPrintMargin": true, 16 | "printMarginColumn": 80, 17 | "printMargin": 80, 18 | "fadeFoldWidgets": false, 19 | "showFoldWidgets": true, 20 | "showLineNumbers": true, 21 | "showGutter": true, 22 | "displayIndentGuides": true, 23 | "fontSize": 14, 24 | "scrollPastEnd": 0, 25 | "theme": "ace/theme/solarized_dark", 26 | "scrollSpeed": 2, 27 | "dragDelay": 150, 28 | "dragEnabled": true, 29 | "focusTimout": 0, 30 | "tooltipFollowsMouse": true, 31 | "firstLineNumber": 1, 32 | "overwrite": false, 33 | "newLineMode": "auto", 34 | "useWorker": true, 35 | "useSoftTabs": true, 36 | "tabSize": 2, 37 | "wrap": "free", 38 | "indentedSoftWrap": true, 39 | "mode": "ace/mode/yaml", 40 | "enableMultiselect": true, 41 | "enableBlockSelect": true, 42 | "enableBasicAutocompletion": true, 43 | "enableSnippets": true, 44 | "enableLiveAutocompletion": true 45 | } -------------------------------------------------------------------------------- /src/extend/BaseComponent.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by stone on 2016/6/23. 3 | */ 4 | export default { 5 | replace: true, 6 | data: function () { 7 | return {} 8 | }, 9 | // 组件是你刚被创建,组件属性计算前 10 | beforeCreated: function () { 11 | }, 12 | // 组件创建完成,属性已绑定,但是dom还没生产,$el还不存在 13 | created: function () { 14 | this.ema = window.EMA.getProxy() 15 | }, 16 | // 模板编译挂载前 17 | beforeMount: function () { 18 | }, 19 | // 模板编译挂载之后,不保证组件已经在document中。 20 | mounted: function () { 21 | }, 22 | // 组件更新之前 23 | beforeUpdate: function () { 24 | }, 25 | // 组件更新之后 26 | updated: function () { 27 | }, 28 | // keep-alive 会用到 29 | // 组件被激活 30 | activated: function () { 31 | }, 32 | // 组件被移除 33 | deactivated: function () { 34 | }, 35 | beforDestroy: function () { 36 | }, 37 | destroyed: function () { 38 | this.ema.dispose() 39 | }, 40 | methods: { 41 | /** 42 | * 组件内部范围绑定事件 43 | * @param key 44 | * @param fn 45 | */ 46 | bindEvent: function (key, fn) { 47 | if (!this.$options.name) { 48 | } 49 | this.ema.bind(`${this.$options.name}.${key}`, fn) 50 | }, 51 | /** 52 | * 打开一个弹出框 53 | * @param data 54 | * { 55 | * name:'', //弹出框名称,dialog目录下弹出框名称 56 | * data:{}, //传给弹出框的基础数据 data能包含数据 57 | * methods:{} //传给弹出框的基础方法。方便回调等操作 58 | * } 59 | */ 60 | openDialog: function (data) { 61 | this.ema.fire('Dialogs.push', data) 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /index.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <%= htmlWebpackPlugin.options.title %> 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | <% if (/^[0-9a-zA-Z]{10,}$/.test(htmlWebpackPlugin.options.hmid)) { %> 18 | 19 | <% } %> 20 | <% if (process.env.NODE_ENV === 'production') { %> 21 | 22 | 23 | 24 | <% } %> 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/components/Content.vue: -------------------------------------------------------------------------------- 1 | 10 | 12 | 13 | 50 | 51 | -------------------------------------------------------------------------------- /src/assets/js/metadata.js: -------------------------------------------------------------------------------- 1 | //中心内容块 2 | export const contentPart = { 3 | 1: { 4 | name: '项目权限清晰', 5 | description: '类 gitlab 权限管理体系', 6 | img: require('../image/login/1.png') 7 | }, 8 | 2: { 9 | name: '编辑操作高效', 10 | description: '拖拽挪移,随心所欲', 11 | img: require('../image/login/1.png') 12 | }, 13 | 3: { 14 | name: '组件接入简单', 15 | description: '命令行工具一条龙服务', 16 | img: require('../image/login/1.png') 17 | }, 18 | 4: { 19 | name: '分发机制健全', 20 | description: '短链、二维码、分享能力应有尽有', 21 | img: require('../image/login/1.png') 22 | }, 23 | } 24 | 25 | // 底部区域块 26 | export const footerPart = { 27 | 1: { 28 | title: '相关资源', 29 | list: [ 30 | { 31 | name: '码良脚手架', 32 | des: '', 33 | link: 'https://github.com/ymm-tech/gods-pen-cli' 34 | }, 35 | { 36 | name: '码良部署', 37 | des: '', 38 | link: 'https://github.com/ymm-tech/gods-pen-docker' 39 | }, 40 | { 41 | name: '码良文档', 42 | des: '', 43 | link: 'https://github.com/ymm-tech/gods-pen-doc' 44 | } 45 | ] 46 | }, 47 | 2: { 48 | title: '社区', 49 | list: [ 50 | // { 51 | // name: '在线讨论', 52 | // link: 'http://www.baidu.com' 53 | // }, 54 | { 55 | name: '错误反馈', 56 | link: 'https://github.com/ymm-tech/gods-pen/issues' 57 | }, 58 | ] 59 | }, 60 | 3: { 61 | title: '关于我们', 62 | list: [ 63 | { 64 | name: '运满满', 65 | link: 'http://www.ymm56.com/' 66 | } 67 | ] 68 | } 69 | } -------------------------------------------------------------------------------- /src/pages/404.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 65 | 66 | 73 | -------------------------------------------------------------------------------- /src/pages/noPage.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 65 | 66 | 73 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import ElementUI from 'element-ui' 3 | import App from './app' 4 | import VueRouter from 'vue-router' 5 | import 'element-ui/lib/theme-chalk/index.css' 6 | import EmaProxy from 'ema-proxy' 7 | import store from './store' 8 | require('./assets/js/base') 9 | require('./extend/filter') 10 | require('./assets/style/base.css') 11 | import * as monaco from 'monaco-editor' 12 | import vuelint from './assets/js/vuelint' 13 | import routerMap from './RouterMap' 14 | 15 | Vue.use(ElementUI) 16 | Vue.use(VueRouter) 17 | Vue.config.devtools = !(process.env.NODE_ENV === 'production') 18 | 19 | const router = new VueRouter(routerMap) 20 | window.router = router 21 | let appData = { 22 | el: '#app', 23 | store: store, 24 | router: router, 25 | render: h => h(App) 26 | } 27 | 28 | window.EMA = new EmaProxy() 29 | 30 | // 脚本编辑器配置自动提醒 31 | monaco.languages.registerCompletionItemProvider('javascript', { 32 | provideCompletionItems: () => { 33 | return vuelint || [] 34 | } 35 | }) 36 | 37 | monaco.editor.defineTheme('maliang', { 38 | base: 'vs', 39 | inherit: true, 40 | rules: [ 41 | { token: 'keyword', foreground: '001dbf' }, 42 | { token: 'string', foreground: '42a071' }, 43 | { token: 'comment.js', fontStyle: 'italic', foreground: '93A1A1' }, 44 | { token: 'delimiter.bracket.js', foreground: 'd63300' }, 45 | { token: 'delimiter.parenthesis.js', foreground: 'd63300' }, 46 | // { token: '', background: 'fefaef', foreground: '657B83'}, 47 | // { token: 'identifier.js', foreground: '061232' }, 48 | ], 49 | colors: { 50 | 'editor.lineHighlightBackground': '#cccccc35', 51 | // 'editor.foreground': '#657B83', 52 | // 'editor.background': '#fefaef', 53 | } 54 | }) 55 | 56 | export default new Vue(appData) 57 | -------------------------------------------------------------------------------- /src/pages/groups/new.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 24 | 25 | 69 | -------------------------------------------------------------------------------- /src/extend/Server.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | const config = require('../config') 3 | 4 | let instance = axios.create({ 5 | baseURL: config.API_PATH, 6 | timeout: 30000, 7 | headers: {}, 8 | withCredentials: true, 9 | needLoading: false, // 是否需要加载效果 10 | ignoreCode: false // 是否忽略服务端的错误提示 11 | }) 12 | 13 | instance.interceptors.request.use(function (config) { 14 | if (config.needLoading) { 15 | window.EMA.fire('loading.show') 16 | } 17 | return config 18 | }, function (error) { 19 | return Promise.reject(error) 20 | }) 21 | 22 | instance.interceptors.response.use(function (response) { 23 | if (response.config.needLoading) { 24 | window.EMA.fire('loading.hide') 25 | } 26 | var code = response.data.code 27 | if (response.data.code && response.data.code != 1 && !response.config.ignoreCode) { 28 | switch (code) { 29 | case 999: 30 | window.EMA.fire('alert.show', '用户认证失败,重新登录', function () { 31 | window.EMA.fire('logout') 32 | }) 33 | break 34 | default: 35 | window.EMA.fire('alert.show', response.data.msg, function () {}) 36 | } 37 | throw new Error(response) 38 | } else { 39 | return response 40 | } 41 | }, function (error) { 42 | window.console.log(error) 43 | var status = error.response.status 44 | var message = error.message 45 | if (status != 200) { 46 | if (status == 401) { 47 | window.EMA.fire('alert.show', '用户认证失败,重新登录', function () { 48 | window.EMA.fire('logout') 49 | }) 50 | } else if (status == 403) { 51 | window.EMA.fire('alert.show', '用户无权限,重新登录', function () { 52 | window.EMA.fire('logout') 53 | }) 54 | } else if (status == 422) { 55 | window.EMA.fire('alert.show', '传递参数错误', function () {}) 56 | } else { 57 | window.EMA.fire('alert.show', message, function () {}) 58 | } 59 | } 60 | return Promise.reject(error) 61 | }) 62 | 63 | export default instance 64 | -------------------------------------------------------------------------------- /src/pages/user.vue: -------------------------------------------------------------------------------- 1 | 41 | 42 | 45 | 46 | 78 | -------------------------------------------------------------------------------- /src/store/actions.js: -------------------------------------------------------------------------------- 1 | var findMenuByKey = function (data, key, path) { 2 | if (data && data.length) { 3 | for (var i = 0; i < data.length; i++) { 4 | var val = data[i] 5 | if (val.resKey == key) { 6 | return { 7 | path: path, 8 | value: val 9 | } 10 | } else { 11 | var res = findMenuByKey(val.child, key, path.concat([i])) 12 | if (res) { 13 | return res 14 | } 15 | } 16 | } 17 | } 18 | } 19 | 20 | export const updataTheme = ({ 21 | commit 22 | }, data) => { 23 | commit('updataTheme', data) 24 | } 25 | 26 | /** 27 | * 28 | * @param context 29 | */ 30 | export const initUserInfo = ({ 31 | commit 32 | }, data) => { 33 | commit('initUserInfo', data) 34 | } 35 | /** 36 | * 37 | * @param context 38 | */ 39 | export const initMenuData = ({ 40 | commit 41 | }, data) => { 42 | commit('initMenuData', data) 43 | } 44 | 45 | /** 46 | * 47 | * @param context 48 | */ 49 | export const changeActiveIndex = ({ 50 | state, 51 | commit 52 | }, data) => { 53 | var info = findMenuByKey(state.app.menuData, data, []) 54 | console.log('info', info) 55 | if (!info) { 56 | return 57 | } 58 | commit('changeNavIndex', info.path[0]) 59 | commit('changeNavTwoIndex', info.path[1]) 60 | setTimeout(function () { 61 | commit('changeActiveIndex', data) 62 | }, 100) 63 | } 64 | 65 | /** 66 | * 67 | * @param context 68 | */ 69 | export const changeNavIndex = ({ 70 | commit 71 | }, data) => { 72 | commit('changeNavIndex', data) 73 | } 74 | 75 | /** 76 | * 77 | * @param context 78 | */ 79 | export const changeNavTwoIndex = ({ 80 | commit 81 | }, data) => { 82 | commit('changeNavTwoIndex', data) 83 | } 84 | 85 | /** 86 | * 87 | * @param context 88 | */ 89 | export const changeAppSize = ({ 90 | commit 91 | }, data) => { 92 | commit('changeAppSize', data) 93 | } 94 | 95 | export const initAllCategory = ({ 96 | commit 97 | }, data) => { 98 | commit('initCategorys', data) 99 | } 100 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gods-pen-admin", 3 | "version": "1.0.0", 4 | "description": "码良管理后台", 5 | "private": false, 6 | "keywords": [], 7 | "scripts": { 8 | "dev": "cross-env CODE_ENV=local vue-cli-service serve", 9 | "build": "cross-env CODE_ENV=production vue-cli-service build", 10 | "build-docker": "cross-env CODE_ENV=docker vue-cli-service build" 11 | }, 12 | "license": "ISC", 13 | "dependencies": { 14 | "axios": "^0.15.2", 15 | "babel-polyfill": "*", 16 | "caniuse-lite": "^1.0.0", 17 | "clipboard": "^1.5.16", 18 | "cross-env": "^3.1.3", 19 | "crypto-js": "^3.1.8", 20 | "dayjs": "^1.5.22", 21 | "deep-assign": "^2.0.0", 22 | "element-theme": "^0.7.1", 23 | "element-theme-default": "^1.2.3", 24 | "element-ui": "^2.3.6", 25 | "ema-proxy": "^1.0.1", 26 | "eslint-plugin-html": "^1.6.0", 27 | "global": "^4.3.2", 28 | "interface-import-javabean": "^1.0.0", 29 | "js-cookie": "^2.1.4", 30 | "js-yaml": "^3.7.0", 31 | "loader-utils": "^1.1.0", 32 | "lodash": "^4.17.4", 33 | "markdown-loader": "4.0.0", 34 | "monaco-editor": "^0.14.3", 35 | "monaco-editor-webpack-plugin": "^1.5.2", 36 | "qs": "^6.3.1", 37 | "title-notify": "^1.0.13", 38 | "vue": "^2.5.16", 39 | "vue-clipboards": "^1.1.0", 40 | "vue-echarts": "^3.0.7", 41 | "vue-router": "^2.0.1", 42 | "vue-template-compiler": "^2.5.16", 43 | "vuex": "^2.1.1" 44 | }, 45 | "devDependencies": { 46 | "@vue/cli-plugin-babel": "^3.1.1", 47 | "@vue/cli-plugin-eslint": "^3.1.1", 48 | "@vue/cli-service": "^3.1.1", 49 | "cross-env": "^3.1.3", 50 | "eslint": "^3.9.1", 51 | "eslint-config-standard": "^6.2.1", 52 | "eslint-plugin-promise": "^3.4.0", 53 | "eslint-plugin-standard": "^2.0.1", 54 | "html-loader": "0.5.5", 55 | "less": "3.9.0", 56 | "less-loader": "4.0.6", 57 | "stylus": "^0.54.5", 58 | "stylus-loader": "3.0.2" 59 | }, 60 | "postcss": { 61 | "plugins": { 62 | "autoprefixer": {} 63 | } 64 | }, 65 | "browserslist": [ 66 | "> 1%", 67 | "last 2 versions", 68 | "not ie <= 8" 69 | ] 70 | } 71 | -------------------------------------------------------------------------------- /src/assets/data/project.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "id", 4 | "require": "true", 5 | "type": "string", 6 | "mock": "@id", 7 | "description": "" 8 | }, 9 | { 10 | "name": "name", 11 | "require": "true", 12 | "type": "string", 13 | "mock": "@cname", 14 | "description": "" 15 | }, 16 | { 17 | "name": "description", 18 | "require": "true", 19 | "type": "string", 20 | "mock": "@url", 21 | "description": "" 22 | }, 23 | { 24 | "name": "version", 25 | "require": "true", 26 | "type": "string", 27 | "mock": "@email", 28 | "description": "" 29 | }, 30 | { 31 | "name": "createTime", 32 | "require": "true", 33 | "type": "number", 34 | "mock": "", 35 | "description": "" 36 | }, 37 | { 38 | "name": "cat", 39 | "require": "true", 40 | "type": "object", 41 | "mock": "", 42 | "description": "", 43 | "child": [ 44 | { 45 | "name": "id", 46 | "require": "true", 47 | "type": "number", 48 | "mock": "@image", 49 | "description": "" 50 | } 51 | ] 52 | }, 53 | { 54 | "name": "apis", 55 | "require": "true", 56 | "type": "array", 57 | "mock": "|5", 58 | "description": "", 59 | "child": [ 60 | { 61 | "name": "createTime", 62 | "require": "true", 63 | "type": "number", 64 | "mock": "@data", 65 | "description": "" 66 | }, 67 | { 68 | "name": "updateTime", 69 | "require": "true", 70 | "type": "number", 71 | "mock": "@image", 72 | "description": "" 73 | }, 74 | { 75 | "name": "version", 76 | "require": "true", 77 | "type": "string", 78 | "mock": "", 79 | "description": "" 80 | }, 81 | { 82 | "name": "content", 83 | "require": "true", 84 | "type": "string", 85 | "mock": "", 86 | "description": "" 87 | }, 88 | { 89 | "name": "id", 90 | "require": "true", 91 | "type": "number", 92 | "mock": "", 93 | "description": "" 94 | } 95 | ] 96 | } 97 | ] -------------------------------------------------------------------------------- /src/components/Dialogs.vue: -------------------------------------------------------------------------------- 1 | 6 | 11 | 12 | 77 | 78 | -------------------------------------------------------------------------------- /src/extend/BasePage.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 所有页面基础类 3 | */ 4 | import {mapState} from 'vuex' 5 | export default { 6 | /* 父类向下传递的参数数据 */ 7 | props: [], 8 | computed: mapState({ 9 | packageInfo: state => state.app.packageInfo, 10 | userInfo: state => state.userInfo 11 | }), 12 | data: function () { 13 | return {} 14 | }, 15 | // 组件是你刚被创建,组件属性计算前 16 | beforeCreated: function () { 17 | }, 18 | // 组件创建完成,属性已绑定,但是dom还没生产,$el还不存在 19 | created: function () { 20 | this.ema = window.EMA.getProxy() 21 | }, 22 | // 模板编译挂载前 23 | beforeMount: function () { 24 | }, 25 | // 模板编译挂载之后,不保证组件已经在document中。 26 | mounted: function () { 27 | this.$options.initPageTitle() 28 | // 更新页面定位信息 29 | this.$store.dispatch('changeActiveIndex', this.$options.name) 30 | console.info('当前页面', this.$options.name) 31 | }, 32 | // 组件更新之前 33 | beforeUpdate: function () { 34 | }, 35 | // 组件更新之后 36 | updated: function () { 37 | }, 38 | // keep-alive 会用到 39 | // 组件被激活 40 | activated: function () { 41 | }, 42 | // 组件被移除 43 | deactivated: function () { 44 | }, 45 | beforDestroy: function () { 46 | }, 47 | destroyed: function () { 48 | this.ema.dispose() 49 | }, 50 | initPageTitle: function () { 51 | if (this.pageName) { 52 | document.title = this.pageName 53 | } 54 | }, 55 | methods: { 56 | /** 57 | * 组件内部范围绑定事件 58 | * @param key 59 | * @param fn 60 | */ 61 | bindEvent: function (key, fn) { 62 | if (!this.$options.name) { 63 | console.warn('绑定事件的组件不存在组件名称', key) 64 | } 65 | this.ema.bind(`${this.$options.name}.${key}`, fn) 66 | }, 67 | /** 68 | * 打开一个弹出框 69 | * @param data 70 | * { 71 | * name:'', //弹出框名称,dialog目录下弹出框名称 72 | * data:{}, //传给弹出框的基础数据 data能包含数据 73 | * methods:{} //传给弹出框的基础方法。方便回调等操作 74 | * } 75 | */ 76 | openDialog: function (data) { 77 | this.ema.fire('Dialogs.push', data) 78 | }, 79 | /** 80 | * 添加一个页面到当前页面,必要参数 81 | * { 82 | * name: 页面名称 83 | * data:{} 数据覆盖 84 | * methods:{} 方法覆盖 85 | * } 86 | * @param data 87 | */ 88 | addPage: function (data) { 89 | this.ema.fire('Page.push', data) 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 码良管理后台 2 | 3 |

4 | 5 |

6 | License 7 | 8 | 9 |

10 | 11 | 12 | ## :house: 官网 13 | 14 | 官网: https://godspen.ymm56.com/ 15 | 16 | 使用手册: https://godspen.ymm56.com/doc/cookbook/introduce.html 17 | 18 | 在线体验: https://godspen.ymm56.com/admin/#/home 19 | 20 | 私有部署: https://godspen.ymm56.com/doc/cookbook/install.html 21 | 22 | 23 | ![](https://ymm-maliang.oss-cn-hangzhou.aliyuncs.com/ymm-maliang/access/ymm_1539588655850.png) 24 | 25 | 26 |

:point_right: `喜欢别忘了加star支持我们,你的支持是我们坚持的动力` :point_left:

27 | 28 | ## 项目构成 29 | 30 | 码良系统由3个项目构成,分别是 [gods-pen-server](https://github.com/ymm-tech/gods-pen-server) 码良服务端、 31 | 32 | [gods-pen-admin](https://github.com/ymm-tech/gods-pen-admin) 33 | 34 | 码良管理后台以及于7月份就已经开源的 [gods-pen](https://github.com/ymm-tech/gods-pen) 码良编辑器。 35 | 36 | 37 | ## 详细部署文档 38 | 39 | https://godspen.ymm56.com/doc/cookbook/source.html 40 | 41 | ### 安装依赖 42 | 43 | ```bash 44 | yarn 45 | ``` 46 | 47 | ### 开发 48 | 49 | ```bash 50 | npm run dev 51 | ``` 52 | 53 | ### 打包 54 | 55 | ``` bash 56 | npm run build 57 | ``` 58 | 59 | ### 配置说明 60 | 61 | 配置文件位于 src/config/ 下,default.js 为默认配置,请不要修改 62 | 63 | 开发配置: 64 | 65 | local.js 为本地开发环境使的配置,一般情况下保持默认即可。 66 | 67 | 在本地开发调试时,三个 web 项目(admin、editor、view)和一个 node 项目(api)都是在独立运行的,因此需要配置每个服务的本地访问地址,以使项目之间能互相调用/请求,四个服务的默认端口号分别为 8567、8565、8566、7051,因此默认配置如 local.js 68 | 69 | 构建/部署配置: 70 | 71 | production.js 为构建阶段使用的配置,默认留空,全部使用了 default.js 配置,原因如下 72 | 73 | 对于三个 web 项目(admin、editor、view),在构建完成后,web 项目不在是分别启动服务,一般来说,会将所有静态资源文件部署在同一个(nginx)服务下,因此,web 项目的访问路径就是域名加项目名,如 xxxx.com/admin,xxxx.com/editor, 如无更换一级路径要求,无需再进行配置 74 | 75 | 对于 api 服务,服务启动以后,本地/内部访问地址为 http://127.0.0.1:7051/api, 如果最终能通过 nginx 反代等操作使之与 web 服务**同域名同端口**号,则也可以不用配置 API_PATH。否则,请将 API_PATH 配置为 api 服务**外部实际访问路径**,如 http://xxxx.com:7051/api 76 | 77 | 总之,所有的 XX_PATH 配置都应该与实际访问地址一致,其中特殊的是在与本服务同端口同域名时,可写成相对地址(即默认配置的值)。 78 | -------------------------------------------------------------------------------- /src/extend/BaseDialog.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by stone on 2016/6/23. 3 | */ 4 | export default { 5 | replace: true, 6 | data: function () { 7 | return { 8 | title: '', 9 | size: 'small', 10 | Visible: true // 弹出框显示状态 11 | } 12 | }, 13 | // 组件是你刚被创建,组件属性计算前 14 | beforeCreated: function () { 15 | console.log('dialog---beforeCreated', this.$options.name) 16 | }, 17 | // 组件创建完成,属性已绑定,但是dom还没生产,$el还不存在 18 | created: function () { 19 | this.ema = window.EMA.getProxy() 20 | console.log('dialog---created', this.$options.name) 21 | }, 22 | // 模板编译挂载前 23 | beforeMount: function () { 24 | console.log('dialog---beforeMount', this.$options.name) 25 | }, 26 | // 模板编译挂载之后,不保证组件已经在document中。 27 | mounted: function () { 28 | console.log('dialog---mounted', this.$options.name) 29 | }, 30 | // 组件更新之前 31 | beforeUpdate: function () { 32 | console.log('dialog---beforeUpdate', this.$options.name) 33 | }, 34 | // 组件更新之后 35 | updated: function () { 36 | console.log('dialog---updated', this.$options.name) 37 | }, 38 | // keep-alive 会用到 39 | // 组件被激活 40 | activated: function () { 41 | console.log('dialog---activated', this.$options.name) 42 | }, 43 | // 组件被移除 44 | deactivated: function () { 45 | console.log('dialog---deactivated', this.$options.name) 46 | }, 47 | beforDestroy: function () { 48 | console.log('dialog---beforDestroy', this.$options.name) 49 | }, 50 | destroyed: function () { 51 | this.ema.dispose() 52 | console.log('dialog---destroyed', this.$options.name) 53 | }, 54 | methods: { 55 | /** 56 | * 组件内部范围绑定事件 57 | * @param key 58 | * @param fn 59 | */ 60 | bindEvent: function (key, fn) { 61 | if (!this.$options.name) { 62 | console.warn('绑定事件的组件不存在组件名称', key) 63 | } 64 | this.ema.bind(`${this.$options.name}.${key}`, fn) 65 | }, 66 | /** 67 | * 打开一个弹出框 68 | * @param data 69 | * { 70 | * name:'', //弹出框名称,dialog目录下弹出框名称 71 | * data:{}, //传给弹出框的基础数据 data能包含数据 72 | * methods:{} //传给弹出框的基础方法。方便回调等操作 73 | * } 74 | */ 75 | openDialog: function (data) { 76 | this.ema.fire('Dialogs.push', data) 77 | }, 78 | close: function () { 79 | console.log('close') 80 | this.ema.fire('Dialogs.close', this.$options.name) 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/assets/data/menu.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "resCode": "01", 4 | "resKey": "01", 5 | "resName": "测试例子", 6 | "data": {}, 7 | "child": [ 8 | { 9 | "resCode": "0101", 10 | "resKey": "0101", 11 | "resName": "弹框", 12 | "data": {}, 13 | "child": [ 14 | { 15 | "resCode": "010101", 16 | "resKey": "demo-dialog1-1", 17 | "resName": "弹出框", 18 | "query": { 19 | "a": 1 20 | }, 21 | "child": [], 22 | "data": {} 23 | }, 24 | { 25 | "resCode": "010102", 26 | "resKey": "demo-dialog1-2", 27 | "resName": "弹出框2", 28 | "child": [], 29 | "data": {} 30 | } 31 | ] 32 | }, 33 | { 34 | "resCode": "0101", 35 | "resKey": "0102", 36 | "resName": "弹框", 37 | "data": {}, 38 | "child": [ 39 | { 40 | "resCode": "010201", 41 | "resKey": "demo-2dialog1-1", 42 | "resName": "弹出框", 43 | "child": [], 44 | "data": {} 45 | }, 46 | { 47 | "resCode": "010102", 48 | "resKey": "demo-2dialog1-2", 49 | "resName": "弹出框2", 50 | "child": [], 51 | "data": {} 52 | } 53 | ] 54 | } 55 | ] 56 | }, 57 | { 58 | "resCode": "02", 59 | "resKey": "02", 60 | "resName": "测试例子2", 61 | "data": {}, 62 | "child": [ 63 | { 64 | "resCode": "0202", 65 | "resKey": "0202", 66 | "resName": "弹框222", 67 | "data": {}, 68 | "child": [ 69 | { 70 | "resCode": "020202", 71 | "resKey": "demo-dialog2-2", 72 | "resName": "弹出框2222", 73 | "child": [], 74 | "data": {} 75 | }, 76 | { 77 | "resCode": "020202", 78 | "resKey": "demo-dialog2-1", 79 | "resName": "弹出框22222", 80 | "child": [], 81 | "data": {} 82 | }, 83 | { 84 | "resCode": "020202", 85 | "resKey": "demo-dialog", 86 | "resName": "弹出框22222", 87 | "child": [], 88 | "data": {} 89 | } 90 | ] 91 | } 92 | ] 93 | } 94 | ] -------------------------------------------------------------------------------- /src/app.vue: -------------------------------------------------------------------------------- 1 | 14 | 25 | 83 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin') 3 | const config = require('./src/config/index') 4 | 5 | const configureWebpack = { 6 | resolve: { 7 | alias: { 8 | 'src': path.join(__dirname, 'src') 9 | } 10 | }, 11 | externals: { 12 | 'jQuery': 'jQuery', 13 | 'plupload': 'plupload', 14 | }, 15 | module: { 16 | rules: [{ 17 | test: /\.md$/, 18 | use: [ 19 | { loader: 'html-loader' }, 20 | { loader: 'markdown-loader' } 21 | ] 22 | }] 23 | }, 24 | plugins: [new MonacoWebpackPlugin()] 25 | } 26 | 27 | if (process.env.NODE_ENV === 'production') { 28 | configureWebpack.externals.vue = 'Vue' 29 | configureWebpack.externals['vue-router'] = 'VueRouter' 30 | configureWebpack.externals.vuex = 'Vuex' 31 | } 32 | 33 | module.exports = { 34 | publicPath: '/' + config.ADMIN_NAME, 35 | assetsDir: 'static', 36 | outputDir: `dist/${config.ADMIN_NAME || 'admin'}`, 37 | lintOnSave: process.env.NODE_ENV !== 'production', 38 | productionSourceMap: process.env.NODE_ENV !== 'production', 39 | pages: { 40 | index: { 41 | entry: './src/main.js', 42 | filename: 'index.html', 43 | template: './index.tpl', 44 | title: config.ADMIN_TITLE, 45 | hmid: config.BAIDU_TONGJI 46 | }, 47 | login: { 48 | entry: './src/login.js', 49 | filename: 'login.html', 50 | template: './login.tpl', 51 | title: config.ADMIN_TITLE, 52 | hmid: config.BAIDU_TONGJI 53 | }, 54 | emailActive: { 55 | entry: './src/emailActive.js', 56 | filename: 'emailActive.html', 57 | template: './emailActive.tpl', 58 | title: config.ADMIN_TITLE, 59 | hmid: config.BAIDU_TONGJI 60 | }, 61 | updatePassword: { 62 | entry: './src/updatePassword.js', 63 | filename: 'updatePassword.html', 64 | template: './updatePassword.tpl', 65 | title: config.ADMIN_TITLE, 66 | hmid: config.BAIDU_TONGJI 67 | } 68 | }, 69 | devServer: { 70 | disableHostCheck: true, 71 | port: 8567, 72 | publicPath: '/', 73 | }, 74 | configureWebpack: configureWebpack, 75 | chainWebpack: config => { 76 | config.plugins.delete('preload-index') 77 | config.plugins.delete('prefetch-index') 78 | 79 | config.plugin('define').tap(args => { 80 | args[0]['process.env'].CODE_ENV = JSON.stringify(process.env.CODE_ENV) 81 | return args 82 | }) 83 | config.module 84 | .rule('wasm') 85 | .test(/\.wasm$/) 86 | .use('file-loader') 87 | .loader('file-loader') 88 | .tap(options => { 89 | return { 90 | limit: 0 91 | } 92 | }) 93 | } 94 | } -------------------------------------------------------------------------------- /src/assets/data/draf.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "12", 3 | "apis": [{ 4 | "request": "{\"query\":[],\"path\":[],\"body\":[{\"name\":\"list\",\"require\":false,\"type\":\"array\",\"mock\":\"1\",\"description\":\"\"},{\"name\":\"pageDTO\",\"require\":false,\"type\":\"array\",\"mock\":\"2\",\"description\":\"\"},{\"name\":\"\",\"require\":\"true\",\"type\":\"string\",\"mock\":\"3\",\"description\":\"\"}]}", 5 | "response": "[{\"name\":\"salesId\",\"require\":false,\"type\":\"number\",\"mock\":\"1\",\"description\":\"员工ID\"},{\"name\":\"teamId\",\"require\":false,\"type\":\"number\",\"mock\":\"2\",\"description\":\"在职人\"},{\"name\":\"teamName\",\"require\":false,\"type\":\"string\",\"mock\":\"34\",\"description\":\"在职人\"},{\"name\":\"memberNum\",\"require\":false,\"type\":\"number\",\"mock\":\"5\",\"description\":\"\"},{\"name\":\"signInNum\",\"require\":false,\"type\":\"number\",\"mock\":\"6\",\"description\":\"\"},{\"name\":\"salesLevelCode\",\"require\":false,\"type\":\"number\",\"mock\":\"7\",\"description\":\"\"}]", 6 | "description": "432", 7 | "name": "用户信息", 8 | "method": "post", 9 | "path": "xts/info" 10 | },{ 11 | "request": "{\"query\":[],\"path\":[],\"body\":[{\"name\":\"list\",\"require\":false,\"type\":\"array\",\"mock\":\"1\",\"description\":\"\"},{\"name\":\"pageDTO\",\"require\":false,\"type\":\"array\",\"mock\":\"2\",\"description\":\"\"},{\"name\":\"\",\"require\":\"true\",\"type\":\"string\",\"mock\":\"3\",\"description\":\"\"}]}", 12 | "response": "[{\"name\":\"salesId\",\"require\":false,\"type\":\"number\",\"mock\":\"1\",\"description\":\"员工ID\"},{\"name\":\"teamId\",\"require\":false,\"type\":\"number\",\"mock\":\"2\",\"description\":\"在职人\"},{\"name\":\"teamName\",\"require\":false,\"type\":\"string\",\"mock\":\"34\",\"description\":\"在职人\"},{\"name\":\"memberNum\",\"require\":false,\"type\":\"number\",\"mock\":\"5\",\"description\":\"\"},{\"name\":\"signInNum\",\"require\":false,\"type\":\"number\",\"mock\":\"6\",\"description\":\"\"},{\"name\":\"salesLevelCode\",\"require\":false,\"type\":\"number\",\"mock\":\"7\",\"description\":\"\"}]", 13 | "description": "432", 14 | "name": "用户信息", 15 | "method": "post", 16 | "path": "xts/info" 17 | }], 18 | "metadata": [{ 19 | "name": "BaseResponseUnE", 20 | "content": "[{\"name\":\"errorMsg\",\"require\":false,\"type\":\"string\",\"mock\":\"\",\"description\":\"\"},{\"name\":\"result\",\"require\":false,\"type\":\"number\",\"mock\":\"\",\"description\":\"\"}]", 21 | "remark": "" 22 | }, 23 | { 24 | "name": "BaseResponseUnE", 25 | "content": "[{\"name\":\"errorMsg\",\"require\":false,\"type\":\"string\",\"mock\":\"\",\"description\":\"\"},{\"name\":\"result\",\"require\":false,\"type\":\"number\",\"mock\":\"\",\"description\":\"\"}]", 26 | "remark": "" 27 | }] 28 | } -------------------------------------------------------------------------------- /src/assets/js/vuelint.js: -------------------------------------------------------------------------------- 1 | const lint = [ 2 | {label: 'silent'}, 3 | {label: 'optionMergeStrategies'}, 4 | {label: 'devtools'}, 5 | {label: 'errorHandler'}, 6 | {label: 'warnHandler'}, 7 | {label: 'ignoredElements'}, 8 | {label: 'keyCodes'}, 9 | {label: 'performance'}, 10 | {label: 'productionTip'}, 11 | {label: 'extend'}, 12 | {label: 'nextTick'}, 13 | {label: 'set'}, 14 | {label: 'delete'}, 15 | {label: 'directive'}, 16 | {label: 'filter'}, 17 | {label: 'component'}, 18 | {label: 'use'}, 19 | {label: 'mixin'}, 20 | {label: 'compile'}, 21 | {label: 'version'}, 22 | {label: 'data'}, 23 | {label: 'props'}, 24 | {label: 'propsData'}, 25 | {label: 'computed'}, 26 | {label: 'methods'}, 27 | {label: 'watch'}, 28 | {label: 'el'}, 29 | {label: 'template'}, 30 | {label: 'render'}, 31 | {label: 'renderError'}, 32 | {label: 'beforeCreate'}, 33 | {label: 'created'}, 34 | {label: 'beforeMount'}, 35 | {label: 'mounted'}, 36 | {label: 'beforeUpdate'}, 37 | {label: 'updated'}, 38 | {label: 'activated'}, 39 | {label: 'deactivated'}, 40 | {label: 'beforeDestroy'}, 41 | {label: 'destroyed'}, 42 | {label: 'directives'}, 43 | {label: 'filters'}, 44 | {label: 'components'}, 45 | {label: 'parent'}, 46 | {label: 'mixins'}, 47 | {label: 'extends'}, 48 | {label: 'provide'}, 49 | {label: 'inject'}, 50 | {label: 'name'}, 51 | {label: 'delimiters'}, 52 | {label: 'functional'}, 53 | {label: 'model'}, 54 | {label: 'inheritAttrs'}, 55 | {label: 'comments'}, 56 | {label: '$data'}, 57 | {label: '$props'}, 58 | {label: '$el'}, 59 | {label: '$options'}, 60 | {label: '$parent'}, 61 | {label: '$root'}, 62 | {label: '$children'}, 63 | {label: '$slots'}, 64 | {label: '$scopedSlots'}, 65 | {label: '$refs'}, 66 | {label: '$isServer'}, 67 | {label: '$attrs'}, 68 | {label: '$listeners'}, 69 | {label: '$watch'}, 70 | {label: '$set'}, 71 | {label: '$delete'}, 72 | {label: '$on'}, 73 | {label: '$once'}, 74 | {label: '$off'}, 75 | {label: '$emit'}, 76 | {label: '$mount'}, 77 | {label: '$forceUpdate'}, 78 | {label: '$nextTick'}, 79 | {label: '$destroy'}, 80 | {label: 'v-text'}, 81 | {label: 'v-html'}, 82 | {label: 'v-show'}, 83 | {label: 'v-if'}, 84 | {label: 'v-else'}, 85 | {label: 'v-else-if'}, 86 | {label: 'v-for'}, 87 | {label: 'v-on'}, 88 | {label: 'v-bind'}, 89 | {label: 'v-model'}, 90 | {label: 'v-pre'}, 91 | {label: 'v-cloak'}, 92 | {label: 'v-once'}, 93 | {label: 'key'}, 94 | {label: 'ref'}, 95 | {label: 'slot'}, 96 | {label: 'is'}, 97 | {label: 'component'}, 98 | {label: 'transition'}, 99 | {label: 'transition-group'}, 100 | {label: 'keep-alive'}, 101 | {label: 'slot'}, 102 | {label: 'immediate'}, 103 | {label: 'handler'}, 104 | {label: 'editerMethods'}, 105 | {label: 'params'}, 106 | {label: 'desc'}, 107 | ] 108 | 109 | export default lint 110 | -------------------------------------------------------------------------------- /src/updatePassword.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 40 | 41 | 96 | -------------------------------------------------------------------------------- /src/extend/chartOptions.js: -------------------------------------------------------------------------------- 1 | function line ({title, seriesNames, x, y, log, unit, legend = true, legendAlign = 'right', tooltip = true, dataZoom = true, dataZoomLimit = 30}, 2 | {seriesNames: seriesNames2, y: y2, log: log2, unit: unit2} = {}) { 3 | var xLength = x.length 4 | var option = { 5 | title: { 6 | text: title || '历史趋势', 7 | left: 'center', 8 | top: 10, 9 | textStyle: { 10 | color: '#666', 11 | fontWeight: '500' 12 | } 13 | }, 14 | legend: legend && { 15 | orient: 'vertical', 16 | right: legendAlign == 'right' ? 10 : 'auto', 17 | left: legendAlign == 'left' ? 60 : 'auto', 18 | top: 30, 19 | data: [...seriesNames, ...(seriesNames2 || [])].map(name => { 20 | return { 21 | name: name, 22 | } 23 | }) 24 | }, 25 | grid: { 26 | left: 60, 27 | right: 60, 28 | top: 40, 29 | bottom: 40, 30 | }, 31 | xAxis: { 32 | data: x, 33 | boundaryGap: seriesNames2 && seriesNames2.length > 0 34 | }, 35 | yAxis: [ 36 | { 37 | type: log ? 'log' : 'value', 38 | splitLine: { 39 | show: false 40 | }, 41 | axisLabel: { 42 | formatter: '{value} ' + (unit || '') 43 | } 44 | }, 45 | seriesNames2 && seriesNames2.length && { 46 | type: log2 ? 'log' : 'value', 47 | splitLine: { 48 | show: false 49 | }, 50 | axisLabel: { 51 | formatter: '{value} ' + (unit2 || '') 52 | } 53 | } 54 | ], 55 | tooltip: tooltip && { 56 | trigger: 'axis', 57 | axisPointer: { 58 | type: 'cross' 59 | }, 60 | textStyle: { 61 | fontSize: 12, 62 | fontWeight: 'lighter' 63 | } 64 | }, 65 | dataZoom: dataZoom && [ 66 | { 67 | type: 'slider', 68 | show: true, 69 | xAxisIndex: [0], 70 | start: (1 - dataZoomLimit / xLength) * 100, 71 | end: 100 72 | } 73 | ], 74 | sampling: 'average', 75 | series: [ 76 | ...y.map((s, i) => { 77 | return { 78 | itemStyle: { 79 | opacity: 0 80 | }, 81 | lineStyle: { 82 | // color: 'rgba(0,0,0,0)', 83 | width: 1, 84 | }, 85 | areaStyle: { 86 | // opacity: 0.8 - 0.1 * i 87 | }, 88 | smooth: true, 89 | name: seriesNames[i], 90 | type: 'line', 91 | data: s, 92 | } 93 | }), 94 | ...(seriesNames2 && seriesNames2.length && y2.map((s, i) => { 95 | return { 96 | itemStyle: { 97 | opacity: 0.8 98 | }, 99 | barMaxWidth: 30, 100 | yAxisIndex: 1, 101 | smooth: true, 102 | name: seriesNames2[i], 103 | type: 'bar', 104 | z: 20, 105 | data: s, 106 | } 107 | }) || []) 108 | ] 109 | } 110 | return option 111 | } 112 | 113 | export { 114 | line 115 | } 116 | -------------------------------------------------------------------------------- /src/pages/pages/CDoc.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 75 | 76 | 128 | -------------------------------------------------------------------------------- /src/extend/filter.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import {numberSplit} from './Util' 3 | import Metadata from '../store/metadata' 4 | var defaultHeaderIcon = require('../assets/image/header/default.png') 5 | var defaultProjectIcon = require('../assets/image/project/cover-media.jpg') 6 | var defaultGroupIcon = require('../assets/image/group/default.png') 7 | /** 8 | * 时间格式化 9 | */ 10 | Vue.filter('datetime', function (value, format) { 11 | return (new Date(value)).Format(format || 'yyyy-MM-dd hh:mm') 12 | }) 13 | /** 14 | * 充值时间格式化,value是以秒为单位 15 | */ 16 | Vue.filter('sdatetime', function (value, format) { 17 | var val = parseInt(value + '000') 18 | return (new Date(val)).Format(format || 'yyyy-MM-dd hh:mm') 19 | }) 20 | /** 21 | * 时间格式化,只显示月日 22 | */ 23 | Vue.filter('daytime', function (value, format) { 24 | return (new Date(value)).Format(format || 'MM-dd') 25 | }) 26 | 27 | /** 28 | * 金额格式化 29 | * value 金额,以分为单位 30 | */ 31 | Vue.filter('moneyFormat', function (value, num) { 32 | value = value / 100 // 转换为元 33 | num = typeof num === 'undefined' ? 2 : num 34 | if (parseFloat(value) > 0) { 35 | var str = parseFloat(value).toFixed(num) 36 | var strArr = str.split('.') 37 | return (/^0+$/.test(strArr[ 1 ])) ? strArr[ 0 ] : str 38 | } else { 39 | return 0 40 | } 41 | }) 42 | /** 43 | * 金额格式化(保存不同位小数) 44 | * value 金额,以分为单位 45 | */ 46 | Vue.filter('moneyDecFormat', function (value) { 47 | value = parseFloat(value) 48 | if (isNaN(value)) { 49 | return '' 50 | } 51 | value = value / 100// 转换为元 52 | if (value > 10) { 53 | value = value.toFixed(0) 54 | return value 55 | } 56 | if (value >= 1 && value <= 10) { 57 | value = value.toFixed(1) 58 | return value 59 | } 60 | if (value < 1) { 61 | value = value.toFixed(2) 62 | return value 63 | } 64 | }) 65 | 66 | /** 67 | * 金额格式化(保存不同位小数) 68 | * value 金额,以分为单位 69 | */ 70 | Vue.filter('toArray', function (value) { 71 | var array = [] 72 | value.forEach(function (value, key) { 73 | }) 74 | return array 75 | }) 76 | /** 77 | * 组角色过滤 78 | */ 79 | Vue.filter('groupRole', function (value) { 80 | var obj = Metadata.groupPower[ value - 1 ] 81 | if (obj) { 82 | return obj.label 83 | } 84 | return '' 85 | }) 86 | /** 87 | * 项目角色过滤 88 | */ 89 | Vue.filter('projectRole', function (value) { 90 | var obj = Metadata.projectPower[ value - 1 ] 91 | if (obj) { 92 | return obj.label 93 | } 94 | return '' 95 | }) 96 | /** 97 | * 默认头像 98 | */ 99 | Vue.filter('defaultHeader', function (value) { 100 | value = value || defaultHeaderIcon 101 | return value 102 | }) 103 | /** 104 | * 默认项目图片 105 | */ 106 | Vue.filter('defaultProject', function (value) { 107 | value = value || defaultProjectIcon 108 | return value 109 | }) 110 | /** 111 | * 默认团队图片 112 | */ 113 | Vue.filter('defaultGroup', function (value) { 114 | value = value || defaultGroupIcon 115 | return value 116 | }) 117 | /** 118 | * 数字分隔 119 | */ 120 | Vue.filter('numberSplit', function (val, round) { 121 | var num = numberSplit(round ? Math.round(val) : val) || 0 122 | return /NaN/.test(num) || !num ? 0 : num 123 | }) 124 | -------------------------------------------------------------------------------- /src/extend/UploadImg.js: -------------------------------------------------------------------------------- 1 | import plupload from 'plupload' 2 | import Utils from './Util' 3 | import Server from '../extend/Server' 4 | var getUploadConfig = function (callback) { 5 | Server({ 6 | url: 'upload/getTocken', 7 | method: 'get', // default 8 | needLoading: false, 9 | data: {} 10 | }).then((respond) => { 11 | var data = respond.data.data 12 | callback(data) 13 | }) 14 | } 15 | 16 | var UploadImage = function ({ 17 | id, 18 | fileName, 19 | filters, 20 | isAddUploadFile, 21 | callback 22 | }) { 23 | this.imgSrc = '' 24 | var uploadControll = false 25 | var me = this 26 | var acceptFilters = { 27 | image: { 28 | title: '资源选择', 29 | extensions: 'jpg,gif,png,jpeg' 30 | }, 31 | video: { 32 | title: '资源选择', 33 | extensions: 'mp4' 34 | }, 35 | audio: { 36 | title: '资源选择', 37 | extensions: 'mp3' 38 | } 39 | } 40 | this.uploader = new plupload.Uploader({ 41 | runtimes: 'html5', 42 | browse_button: id, 43 | url: 'https://oss.aliyuncs.com', 44 | filters: [acceptFilters[filters]], 45 | prevent_duplicates: true, 46 | max_file_size: '100mb', 47 | init: { 48 | PostInit () {}, 49 | FilesAdded (up, files) { 50 | if (uploadControll) { 51 | return false 52 | } 53 | uploadControll = true 54 | let that = this 55 | let name = files[0].name 56 | if (isAddUploadFile) { 57 | let pos = name.lastIndexOf('.') 58 | if (pos !== -1) { 59 | name = 'ymm_' + new Date().getTime() + name.substring(pos) 60 | } 61 | Utils.readAsDataURL(files[0].getNative(), function (src) { 62 | var filesSource = new window.File([Utils.getBlobBydataURI(src, files[0].type)], name, { 63 | type: files[0].type 64 | }) 65 | that.addFile(filesSource) 66 | that.removeFile(files[0]) 67 | me.send(name) 68 | }) 69 | } 70 | }, 71 | BeforeUpload (up, file) {}, 72 | UploadProgress (up, file) {}, 73 | FileUploaded (up, file, info) { 74 | if (info.status === 200) { 75 | me.imgSrc = me.imgSrc.replace('ymm.oss-cn-hangzhou.aliyuncs.com', 'imagecdn.ymm56.com') 76 | callback(me.imgSrc) 77 | } else {} 78 | uploadControll = false 79 | }, 80 | Error (up, err) {} 81 | } 82 | }) 83 | this.uploader.init() 84 | } 85 | 86 | UploadImage.prototype.send = function (name) { 87 | name = name || 'ymm' + new Date().getTime() + '.png' 88 | getUploadConfig((configUplaod) => { 89 | configUplaod.key = configUplaod.dir + name 90 | this.imgSrc = configUplaod.host + '/' + configUplaod.key 91 | let newMultipartParams = { 92 | 'key': configUplaod.key, 93 | 'policy': configUplaod.policy, 94 | 'OSSAccessKeyId': configUplaod.accessid, 95 | 'success_action_status': '200', 96 | 'signature': configUplaod.signature 97 | } 98 | console.log('newMultipartParams', newMultipartParams) 99 | this.uploader.setOption({ 100 | 'url': configUplaod.host, 101 | 'multipart_params': newMultipartParams 102 | }) 103 | this.uploader.start() 104 | }) 105 | } 106 | export default UploadImage 107 | -------------------------------------------------------------------------------- /src/components/Welcome.vue: -------------------------------------------------------------------------------- 1 | 17 | 58 | 124 | 125 | -------------------------------------------------------------------------------- /src/extend/Util.js: -------------------------------------------------------------------------------- 1 | import Server from '../extend/Server' 2 | 3 | function pipe () { 4 | var args = [].slice.call(arguments, 0) 5 | var val = args[ 0 ] 6 | for (let arg of args) { 7 | if (args.indexOf(arg) != 0 && typeof arg === 'function') val = arg(val) 8 | } 9 | return val 10 | } 11 | 12 | function baiduTongjiAjax (body) { 13 | return Server({ 14 | url: 'statistics/baidu', 15 | method: 'post', 16 | data: body 17 | }).then(({data}) => { 18 | let {header, body} = data 19 | if (header && header.desc === 'success') { 20 | return body && body.data && body.data[0] && body.data[0].result 21 | } else { 22 | return null 23 | } 24 | }) 25 | } 26 | 27 | function numberSplit (num) { 28 | return String(num).split('').reverse().map((a, i) => `${i % 3 === 2 ? ', ' : ''}${a}`).reverse().join('').replace(/^,/, '') 29 | } 30 | 31 | function combineTongjiData ({fields = [], items = []}, verbose = false) { 32 | if (verbose) { 33 | var [category, list] = items 34 | items = category.map((c, i) => [c[0], ...list[i]]) 35 | } 36 | var obj = [] 37 | for (let item of items) { 38 | obj.push(item.map((a, i) => [i, a]).reduce((a, b) => { 39 | var val = b[1] && b[1].val || b[1] 40 | var key = fields[b[0]] 41 | if (typeof val === 'number') { 42 | switch (key) { 43 | case 'pv_count': 44 | case 'visitor_count': 45 | case 'ip_count': 46 | val = numberSplit(val) 47 | break 48 | case 'bounce_ratio': 49 | val = val + '%' 50 | break 51 | case 'avg_visit_time': 52 | val = `${val / 60 | 0}分${val % 60}秒` 53 | } 54 | } 55 | a[key] = val 56 | return a 57 | }, {})) 58 | } 59 | return obj 60 | } 61 | 62 | function splitTrendData (result, pickedFields) { 63 | var sumData = result.sum && result.sum[0] 64 | var fields = result.fields.slice(1) 65 | var sumFields = fields.filter(f => f.indexOf('ratio') == -1) 66 | var items = result.items || [] 67 | var x = items[0].map(x => x[0]) 68 | var y = pickedFields 69 | .map(f => [f, fields.indexOf(f)]) 70 | .reduce((o, [k, i]) => { 71 | o[k] = items[1].map(d => d[i]) 72 | return o 73 | }, {}) 74 | var sum = pickedFields 75 | .map(f => [f, sumFields.indexOf(f)]) 76 | .reduce((o, [k, i]) => { 77 | o[k] = sumData[i] 78 | return o 79 | }, {}) 80 | 81 | return { 82 | x, 83 | y, 84 | sum, 85 | } 86 | } 87 | function getBlobBydataURI (dataURI, type) { 88 | var binary = window.atob(dataURI.split(',')[1]) 89 | var array = [] 90 | for (let i = 0, leng = binary.length; i < leng; i++) { 91 | array.push(binary.charCodeAt(i)) 92 | } 93 | let blob = new window.Blob([new Uint8Array(array)], { 94 | type: type 95 | }) 96 | return blob 97 | } 98 | function readAsDataURL (file, callback) { 99 | const reader = new window.FileReader() 100 | reader.readAsDataURL(file) 101 | reader.onload = function (e) { 102 | callback && callback(this.result) 103 | } 104 | } 105 | 106 | export { 107 | readAsDataURL, 108 | getBlobBydataURI, 109 | splitTrendData, 110 | numberSplit, 111 | combineTongjiData, 112 | pipe, 113 | baiduTongjiAjax, 114 | } 115 | 116 | export default { 117 | readAsDataURL, 118 | getBlobBydataURI, 119 | splitTrendData, 120 | numberSplit, 121 | combineTongjiData, 122 | pipe, 123 | baiduTongjiAjax, 124 | } 125 | -------------------------------------------------------------------------------- /src/store/metadata.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 基本元数据配置 3 | */ 4 | const state = { 5 | resourceType: { 6 | 7 | }, 8 | paramsType: [ 9 | 'string', 10 | 'number', 11 | 'boolean', 12 | 'object', 13 | 'array', 14 | 'array(string)', 15 | 'array(number)', 16 | 'array(boolean)', 17 | 'array(object)', 18 | 'array(array)' 19 | ], 20 | methods: [ 21 | { value: 'get', label: 'GET' }, 22 | { value: 'post', label: 'POST' }, 23 | { value: 'put', label: 'PUT' }, 24 | { value: 'delete', label: 'DELETE' }, 25 | { value: 'patch', label: 'PATCH' }, 26 | { value: 'head', label: 'HEAD' }, 27 | { value: 'options', label: 'OPTIONS' } 28 | ], 29 | projectPower: [ 30 | { 31 | value: '1', 32 | label: '所有者' 33 | }, 34 | { 35 | value: '2', 36 | label: '管理员' 37 | }, 38 | { 39 | value: '3', 40 | label: '开发人' 41 | }, 42 | { 43 | value: '4', 44 | label: '游客' 45 | } 46 | ], 47 | groupPower: [ 48 | { 49 | value: '1', 50 | label: '所有者' 51 | }, 52 | { 53 | value: '2', 54 | label: '管理员' 55 | }, 56 | { 57 | value: '3', 58 | label: '开发人' 59 | } 60 | ], 61 | pageType: [ 62 | {value: '0', label: 'web'}, 63 | {value: 1, label: 'flutter'}, 64 | ], 65 | mockAdvice: [ 66 | { value: '@id', desc: '随机id' }, 67 | { value: '@increment', desc: '自增id' }, 68 | { value: '@image', desc: '' }, 69 | { value: '@email', desc: '' }, 70 | { value: '@title', desc: '标题' }, 71 | { value: '@word', desc: '单词' }, 72 | { value: '@cparagraph', desc: '中文段落' }, 73 | { value: '@csentence', desc: '中文句子' }, 74 | { value: '@url', desc: '' }, 75 | { value: '@pick', desc: '挑选数组中的一个' }, 76 | { value: '@now', desc: '' }, 77 | 78 | { value: '@boolean', desc: '' }, 79 | { value: '@natural', desc: '' }, 80 | { value: '@integer', desc: '' }, 81 | { value: '@float', desc: '' }, 82 | { value: '@character', desc: '' }, 83 | { value: '@string', desc: '' }, 84 | { value: '@range', desc: '' }, 85 | { value: '@date', desc: '' }, 86 | { value: '@time', desc: '' }, 87 | { value: '@datetime', desc: '' }, 88 | { value: '@dataImage', desc: '' }, 89 | { value: '@color', desc: '' }, 90 | { value: '@hex', desc: 'hex格式颜色' }, 91 | { value: '@rgb', desc: 'rgb格式颜色' }, 92 | { value: '@rgba', desc: 'rgba格式颜色' }, 93 | { value: '@hsl', desc: 'hsl格式颜色' }, 94 | { value: '@paragraph', desc: '段落' }, 95 | { value: '@sentence', desc: '句子' }, 96 | { value: '@cword', desc: '' }, 97 | { value: '@ctitle', desc: '' }, 98 | { value: '@first', desc: '' }, 99 | { value: '@last', desc: '' }, 100 | { value: '@name', desc: '' }, 101 | { value: '@cfirst', desc: '' }, 102 | { value: '@clast', desc: '' }, 103 | { value: '@cname', desc: '' }, 104 | { value: '@domain', desc: '域名' }, 105 | { value: '@protocol', desc: '' }, 106 | { value: '@tld', desc: '' }, 107 | { value: '@ip', desc: '' }, 108 | { value: '@region', desc: '地区' }, 109 | { value: '@province', desc: '' }, 110 | { value: '@city', desc: '' }, 111 | { value: '@county', desc: '' }, 112 | { value: '@zip', desc: '邮编' }, 113 | { value: '@capitalize', desc: '' }, 114 | { value: '@upper', desc: '' }, 115 | { value: '@lower', desc: '' }, 116 | { value: '@shuffle', desc: '' }, 117 | { value: '@guid', desc: '32位唯一id' } 118 | ] 119 | } 120 | export default state 121 | -------------------------------------------------------------------------------- /src/pages/dashboard/groups.vue: -------------------------------------------------------------------------------- 1 | 56 | 57 | 60 | 61 | 112 | -------------------------------------------------------------------------------- /src/components/CodeEditer.vue: -------------------------------------------------------------------------------- 1 | 5 | 11 | 120 | 121 | -------------------------------------------------------------------------------- /public/fullpage.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * fullPage 3.0.2 3 | * https://github.com/alvarotrigo/fullPage.js 4 | * 5 | * @license GPLv3 for open source use only 6 | * or Fullpage Commercial License for commercial use 7 | * http://alvarotrigo.com/fullPage/pricing/ 8 | * 9 | * Copyright (C) 2018 http://alvarotrigo.com/fullPage - A project by Alvaro Trigo 10 | */.fp-enabled body,html.fp-enabled{margin:0;padding:0;overflow:hidden;-webkit-tap-highlight-color:rgba(0,0,0,0)}.fp-section{position:relative;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.fp-slide{float:left}.fp-slide,.fp-slidesContainer{height:100%;display:block}.fp-slides{z-index:1;height:100%;overflow:hidden;position:relative;-webkit-transition:all .3s ease-out;transition:all .3s ease-out}.fp-section.fp-table,.fp-slide.fp-table{display:table;table-layout:fixed;width:100%}.fp-tableCell{display:table-cell;vertical-align:middle;width:100%;height:100%}.fp-slidesContainer{float:left;position:relative}.fp-controlArrow{-webkit-user-select:none;-moz-user-select:none;-khtml-user-select:none;-ms-user-select:none;position:absolute;z-index:4;top:50%;cursor:pointer;width:0;height:0;border-style:solid;margin-top:-38px;-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.fp-controlArrow.fp-prev{left:15px;width:0;border-width:38.5px 34px 38.5px 0;border-color:transparent #fff transparent transparent}.fp-controlArrow.fp-next{right:15px;border-width:38.5px 0 38.5px 34px;border-color:transparent transparent transparent #fff}.fp-scrollable{overflow:hidden;position:relative}.fp-scroller{overflow:hidden}.iScrollIndicator{border:0!important}.fp-notransition{-webkit-transition:none!important;transition:none!important}#fp-nav{position:fixed;z-index:100;margin-top:-32px;top:50%;opacity:1;-webkit-transform:translate3d(0,0,0)}#fp-nav.fp-right{right:17px}#fp-nav.fp-left{left:17px}.fp-slidesNav{position:absolute;z-index:4;opacity:1;-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0);left:0!important;right:0;margin:0 auto!important}.fp-slidesNav.fp-bottom{bottom:17px}.fp-slidesNav.fp-top{top:17px}#fp-nav ul,.fp-slidesNav ul{margin:0;padding:0}#fp-nav ul li,.fp-slidesNav ul li{display:block;width:14px;height:13px;margin:7px;position:relative}.fp-slidesNav ul li{display:inline-block}#fp-nav ul li a,.fp-slidesNav ul li a{display:block;position:relative;z-index:1;width:100%;height:100%;cursor:pointer;text-decoration:none}#fp-nav ul li a.active span,#fp-nav ul li:hover a.active span,.fp-slidesNav ul li a.active span,.fp-slidesNav ul li:hover a.active span{height:12px;width:12px;margin:-6px 0 0 -6px;border-radius:100%}#fp-nav ul li a span,.fp-slidesNav ul li a span{border-radius:50%;position:absolute;z-index:1;height:4px;width:4px;border:0;background:#333;left:50%;top:50%;margin:-2px 0 0 -2px;-webkit-transition:all .1s ease-in-out;-moz-transition:all .1s ease-in-out;-o-transition:all .1s ease-in-out;transition:all .1s ease-in-out}#fp-nav ul li:hover a span,.fp-slidesNav ul li:hover a span{width:10px;height:10px;margin:-5px 0 0 -5px}#fp-nav ul li .fp-tooltip{position:absolute;top:-2px;color:#fff;font-size:14px;font-family:arial,helvetica,sans-serif;white-space:nowrap;max-width:220px;overflow:hidden;display:block;opacity:0;width:0;cursor:pointer}#fp-nav ul li:hover .fp-tooltip,#fp-nav.fp-show-active a.active+.fp-tooltip{-webkit-transition:opacity .2s ease-in;transition:opacity .2s ease-in;width:auto;opacity:1}#fp-nav ul li .fp-tooltip.fp-right{right:20px}#fp-nav ul li .fp-tooltip.fp-left{left:20px}.fp-auto-height .fp-slide,.fp-auto-height .fp-tableCell,.fp-auto-height.fp-section{height:auto!important}.fp-responsive .fp-auto-height-responsive .fp-slide,.fp-responsive .fp-auto-height-responsive .fp-tableCell,.fp-responsive .fp-auto-height-responsive.fp-section{height:auto!important} 11 | /*# sourceMappingURL=fullpage.min.css.map */ 12 | #fp-nav ul li a span, .fp-slidesNav ul li a span { 13 | background-color: #888; 14 | } -------------------------------------------------------------------------------- /src/assets/js/base.js: -------------------------------------------------------------------------------- 1 | Date.prototype.Format = function (fmt) { //author: meizz 2 | var o = { 3 | "M+": this.getMonth() + 1, //月份 4 | "d+": this.getDate(), //日 5 | "h+": this.getHours(), //小时 6 | "m+": this.getMinutes(), //分 7 | "s+": this.getSeconds(), //秒 8 | "q+": Math.floor((this.getMonth() + 3) / 3), //季度 9 | "S": this.getMilliseconds() //毫秒 10 | }; 11 | if (/(y+)/.test(fmt)) 12 | fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); 13 | for (var k in o) 14 | if (new RegExp("(" + k + ")").test(fmt)) 15 | fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[ k ]) : (("00" + o[ k ]).substr(("" + o[ k ]).length))); 16 | return fmt; 17 | }; 18 | +function () { 19 | "use strict"; 20 | var e = /\[([^\[]*)\]$/, n = /^(?:([a-z]*):)?(?:\/\/)?(?:([^:@]*)(?::([^@]*))?@)?([0-9a-z-._]+)?(?::([0-9]*))?(\/[^?#]*)?(?:\?([^#]*))?(?:#(.*))?$/i, t = [ "mailto", "bitcoin" ], o = { 21 | get: function (n, t) { 22 | n = n || "", "undefined" == typeof t && (t = {}), "undefined" == typeof t.full && (t.full = !1), "undefined" == typeof t.array && (t.array = !1), t.full === !0 && (n = o.parse(n, { get: !1 }).query || ""); 23 | for (var u = {}, d = n.split("&"), r = 0; r < d.length; r++)if (d[ r ].length) { 24 | var f = d[ r ].indexOf("="), i = d[ r ], s = !0; 25 | if (f >= 0 && (i = d[ r ].substr(0, f), s = d[ r ].substr(f + 1), s = decodeURIComponent(s)), t.array) { 26 | for (var a, p = [], y = u, c = i; a = c.match(e);)c = c.substr(0, a.index), p.unshift(decodeURIComponent(a[ 1 ])); 27 | if (c = decodeURIComponent(c), p.some(function (e) {return "undefined" == typeof y[ c ] && (y[ c ] = []), Array.isArray(y[ c ]) ? (y = y[ c ], "" === e && (e = y.length), void(c = e)) : !0}))continue; 28 | y[ c ] = s 29 | } else i = decodeURIComponent(i), u[ i ] = s 30 | } 31 | return u 32 | }, buildget: function (e, n) { 33 | var t = []; 34 | for (var u in e) { 35 | var d = encodeURIComponent(u); 36 | "undefined" != typeof n && (d = n + "[" + d + "]"); 37 | var r = e[ u ]; 38 | switch (typeof r) { 39 | case"boolean": 40 | r && t.push(d); 41 | break; 42 | case"number": 43 | r = r.toString(); 44 | case"string": 45 | t.push(d + "=" + encodeURIComponent(r)); 46 | break; 47 | case"object": 48 | t.push(o.buildget(r, d)) 49 | } 50 | } 51 | return t.join("&") 52 | }, parse: function (e, t) { 53 | "undefined" == typeof t && (t = {}); 54 | var u = e.match(n) || [], d = { 55 | url: e, 56 | scheme: u[ 1 ], 57 | user: u[ 2 ], 58 | pass: u[ 3 ], 59 | host: u[ 4 ], 60 | port: u[ 5 ] && +u[ 5 ], 61 | path: u[ 6 ], 62 | query: u[ 7 ], 63 | hash: u[ 8 ] 64 | }; 65 | return t.get !== !1 && (d.get = d.query && o.get(d.query, t.get)), d 66 | }, build: function (e, n) { 67 | n = n || {}; 68 | var u = ""; 69 | if ("undefined" != typeof e.scheme && (u += e.scheme, u += t.indexOf(e.scheme) >= 0 ? ":" : "://"), "undefined" != typeof e.user && (u += e.user, "undefined" == typeof e.pass && (u += "@")), "undefined" != typeof e.pass && (u += ":" + e.pass + "@"), "undefined" != typeof e.host && (u += e.host), "undefined" != typeof e.port && (u += ":" + e.port), "undefined" != typeof e.path && (u += e.path), n.useemptyget) "undefined" != typeof e.get ? u += "?" + o.buildget(e.get) : "undefined" != typeof e.query && (u += "?" + e.query); else { 70 | var d = e.get && o.buildget(e.get) || e.query; 71 | d && (u += "?" + d) 72 | } 73 | return "undefined" != typeof e.hash && (u += "#" + e.hash), u || e.url || "" 74 | } 75 | }; 76 | window.url = o 77 | }(); 78 | -------------------------------------------------------------------------------- /src/components/pie-chart.vue: -------------------------------------------------------------------------------- 1 | 18 | 51 | 52 | 119 | 120 | -------------------------------------------------------------------------------- /src/components/Upload.vue: -------------------------------------------------------------------------------- 1 | 6 | 8 | 141 | 142 | -------------------------------------------------------------------------------- /src/components/PageRouter.vue: -------------------------------------------------------------------------------- 1 | 8 | 15 | 126 | 127 | -------------------------------------------------------------------------------- /src/pages/dashboard/component.vue: -------------------------------------------------------------------------------- 1 | 45 | 46 | 62 | 63 | 145 | -------------------------------------------------------------------------------- /src/pages/groups/CNew.vue: -------------------------------------------------------------------------------- 1 | 53 | 54 | 64 | 65 | 153 | -------------------------------------------------------------------------------- /src/components/Tags.vue: -------------------------------------------------------------------------------- 1 | 20 | 35 | 169 | 170 | -------------------------------------------------------------------------------- /src/pages/pages/history.vue: -------------------------------------------------------------------------------- 1 | 30 | 31 | 33 | 151 | -------------------------------------------------------------------------------- /src/components/Sidebar.vue: -------------------------------------------------------------------------------- 1 | 75 | 82 | 83 | 143 | 144 | -------------------------------------------------------------------------------- /src/assets/style/app.styl: -------------------------------------------------------------------------------- 1 | put = #c5862b 2 | head = #c5862b 3 | delete = #c5862b 4 | post = #10a54a 5 | patch = #D38042 6 | get = #0f6ab4 7 | options = #0f6ab4 8 | 9 | .nav-links.el-tabs { 10 | 11 | } 12 | 13 | .nav-links.el-tabs .el-tabs__header { 14 | border: 0; 15 | margin: 0; 16 | } 17 | 18 | .nav-links.el-tabs .el-tabs__item { 19 | height: 53px; 20 | line-height: 60px; 21 | font-size: 16px; 22 | } 23 | 24 | 25 | .el-upload__input { 26 | display: none !important; 27 | } 28 | 29 | /*=========api 列表展示样式========*/ 30 | .type.post { 31 | color: #416bbb; 32 | } 33 | 34 | .type.get { 35 | color: #39bb2f; 36 | } 37 | 38 | .type.put { 39 | color: #bb7220; 40 | } 41 | 42 | .type.delete { 43 | color: #bb221b; 44 | } 45 | 46 | /*=======页面颜色==========*/ 47 | 48 | .el-table .put { 49 | color: put; 50 | } 51 | 52 | .el-table .head { 53 | color: head; 54 | } 55 | 56 | .el-table .delete { 57 | color: delete; 58 | } 59 | 60 | .el-table .post { 61 | color: post; 62 | } 63 | 64 | .el-table .patch { 65 | color: patch; 66 | } 67 | 68 | .el-table .get { 69 | color: get; 70 | } 71 | 72 | .el-table .options { 73 | color: options; 74 | } 75 | 76 | /*=========类型 列表展示样式========*/ 77 | .ia-splitter-handle { 78 | height: 100%; 79 | position: absolute; 80 | top: 0; 81 | right: -6px; 82 | width: 11px; 83 | z-index: 11; 84 | cursor: col-resize; 85 | } 86 | 87 | .ia-splitter-handle-highlight { 88 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAAMCAYAAABIvGxUAAADHmlDQ1BJQ0MgUHJvZmlsZQAAeAGFVN9r01AU/tplnbDhizpnEQk+aJFuZFN0Q5y2a1e6zVrqNrchSJumbVyaxiTtfrAH2YtvOsV38Qc++QcM2YNve5INxhRh+KyIIkz2IrOemzRNJ1MDufe73/nuOSfn5F6g+XFa0xQvDxRVU0/FwvzE5BTf8gFeHEMr/GhNi4YWSiZHQA/Tsnnvs/MOHsZsdO5v36v+Y9WalQwR8BwgvpQ1xCLhWaBpXNR0E+DWie+dMTXCzUxzWKcECR9nOG9jgeGMjSOWZjQ1QJoJwgfFQjpLuEA4mGng8w3YzoEU5CcmqZIuizyrRVIv5WRFsgz28B9zg/JfsKiU6Zut5xCNbZoZTtF8it4fOX1wjOYA1cE/Xxi9QbidcFg246M1fkLNJK4RJr3n7nRpmO1lmpdZKRIlHCS8YlSuM2xp5gsDiZrm0+30UJKwnzS/NDNZ8+PtUJUE6zHF9fZLRvS6vdfbkZMH4zU+pynWf0D+vff1corleZLw67QejdX0W5I6Vtvb5M2mI8PEd1E/A0hCgo4cZCjgkUIMYZpjxKr4TBYZIkqk0ml0VHmyONY7KJOW7RxHeMlfDrheFvVbsrj24Pue3SXXjrwVhcW3o9hR7bWB6bqyE5obf3VhpaNu4Te55ZsbbasLCFH+iuWxSF5lyk+CUdd1NuaQU5f8dQvPMpTuJXYSWAy6rPBe+CpsCk+FF8KXv9TIzt6tEcuAcSw+q55TzcbsJdJM0utkuL+K9ULGGPmQMUNanb4kTZyKOfLaUAsnBneC6+biXC/XB567zF3h+rkIrS5yI47CF/VFfCHwvjO+Pl+3b4hhp9u+02TrozFa67vTkbqisXqUj9sn9j2OqhMZsrG+sX5WCCu0omNqSrN0TwADJW1Ol/MFk+8RhAt8iK4tiY+rYleQTysKb5kMXpcMSa9I2S6wO4/tA7ZT1l3maV9zOfMqcOkb/cPrLjdVBl4ZwNFzLhegM3XkCbB8XizrFdsfPJ63gJE722OtPW1huos+VqvbdC5bHgG7D6vVn8+q1d3n5H8LeKP8BqkjCtbCoV8yAAAACXBIWXMAAAsSAAALEgHS3X78AAABZ2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNC40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPgogICAgICAgICA8eG1wOkNyZWF0b3JUb29sPkFkb2JlIEZpcmV3b3JrcyBDUzY8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CsO3s+UAAAAsSURBVAgdY7x69ep/BgaGRpZNmzYBaQYGxv//QQIMDExgEpnBcu3aNQoUAwChKRhfrNwRnQAAAABJRU5ErkJggg=="); 89 | background-position: right center; 90 | background-repeat: no-repeat 91 | position: absolute; 92 | top: 0; 93 | left: 4px; 94 | bottom: 0; 95 | width: 6px; 96 | border-left: 1px solid #ccc; 97 | } 98 | 99 | .el-radio-button__orig-radio:checked + .el-radio-button__inner { 100 | color: #fff; 101 | background-color: #1970a9; 102 | border-color: #1970a9; 103 | } 104 | 105 | .noborder input, .div-table li .noborder textarea { 106 | border none; 107 | } 108 | .el-tabs__nav-wrap::after{ 109 | background-color: rgba(228, 231, 237, 0) 110 | } 111 | 112 | .my-autocomplete { 113 | li { 114 | line-height: normal; 115 | padding: 7px; 116 | 117 | .name { 118 | text-overflow: ellipsis; 119 | overflow: hidden; 120 | } 121 | .addr { 122 | font-size: 12px; 123 | color: #b4b4b4; 124 | } 125 | 126 | .highlighted .addr { 127 | color: #ddd; 128 | } 129 | } 130 | } 131 | 132 | .el-tabs--border-card { 133 | background: #fff; 134 | border: 1px solid #d1dbe5; 135 | box-shadow: 0 2px 4px 0 rgba(0, 0, 0, .12), 0 0 6px 0 rgba(0, 0, 0, .04) 136 | } 137 | 138 | .el-tabs--border-card > .el-tabs__content { 139 | padding: 15px 140 | } 141 | 142 | .el-tabs--border-card > .el-tabs__header { 143 | background-color: #eef1f6; 144 | margin: 0 145 | } 146 | 147 | .el-tabs--border-card > .el-tabs__header .el-tabs__item { 148 | transition: all .3s cubic-bezier(.645, .045, .355, 1); 149 | border: 1px solid transparent; 150 | border-top: 0; 151 | margin-right: -1px; 152 | margin-left: -1px 153 | } 154 | 155 | .el-tabs--border-card > .el-tabs__header .el-tabs__item.is-active { 156 | background-color: #fff; 157 | border-right-color: #d1dbe5; 158 | border-left-color: #d1dbe5 159 | } 160 | 161 | .el-tabs--border-card > .el-tabs__header .el-tabs__item.is-active:first-child { 162 | border-left-color: #d1dbe5 163 | } 164 | 165 | .el-tabs--border-card > .el-tabs__header .el-tabs__item.is-active:last-child { 166 | border-right-color: #d1dbe5 167 | } 168 | .deprecated { 169 | text-decoration: line-through; 170 | } 171 | /*==============提示==============*/ 172 | .tipWarp { 173 | margin 5px 174 | } 175 | 176 | .el-dialog__headerbtn, .el-message-box__headerbtn { 177 | float: right; 178 | background: transparent; 179 | border: none; 180 | outline: none; 181 | padding: 0; 182 | cursor: pointer; 183 | } -------------------------------------------------------------------------------- /src/dialog/DAddPage.vue: -------------------------------------------------------------------------------- 1 | 52 | 78 | 169 | 170 | -------------------------------------------------------------------------------- /src/pages/component/editer.vue: -------------------------------------------------------------------------------- 1 | 56 | 57 | 81 | 82 | 178 | -------------------------------------------------------------------------------- /src/pages/completePage.vue: -------------------------------------------------------------------------------- 1 | 64 | 65 | 118 | 119 | 197 | -------------------------------------------------------------------------------- /src/dialog/DCopyPage.vue: -------------------------------------------------------------------------------- 1 | 42 | 68 | 175 | 176 | -------------------------------------------------------------------------------- /src/components/Header.vue: -------------------------------------------------------------------------------- 1 | 61 | 77 | 169 | 170 | -------------------------------------------------------------------------------- /src/pages/project.vue: -------------------------------------------------------------------------------- 1 | 68 | 69 | 122 | 123 | 200 | -------------------------------------------------------------------------------- /src/pages/page.vue: -------------------------------------------------------------------------------- 1 | 67 | 68 | 124 | 125 | 235 | -------------------------------------------------------------------------------- /src/pages/pages/CNew.vue: -------------------------------------------------------------------------------- 1 | 86 | 87 | 123 | 124 | 241 | -------------------------------------------------------------------------------- /src/pages/projects/data.vue: -------------------------------------------------------------------------------- 1 | 70 | 71 | 93 | 94 | 234 | --------------------------------------------------------------------------------