├── static ├── .gitkeep ├── img │ ├── cat.jpg │ ├── cloud.png │ ├── docker.png │ ├── docker2.png │ ├── index │ │ ├── logo.png │ │ ├── picture1.jpg │ │ ├── picture2.png │ │ ├── picture3.png │ │ ├── picture4.jpg │ │ ├── picture5.jpg │ │ ├── picture6.png │ │ ├── picture7.png │ │ ├── picture8.png │ │ └── background.jpg │ ├── gou.svg │ ├── icon_docker-image.svg │ ├── icon_docker.svg │ ├── people.svg │ └── swarm.svg ├── tree │ ├── add.png │ ├── sub.png │ └── jsoneditor.css ├── font │ ├── iconfont.eot │ ├── iconfont.ttf │ └── iconfont.woff ├── css │ ├── theme-green │ │ ├── fonts │ │ │ ├── element-icons.ttf │ │ │ └── element-icons.woff │ │ └── color-green.css │ ├── color-dark.css │ └── main.css ├── addons │ ├── fullscreen │ │ ├── fullscreen.css │ │ └── fullscreen.js │ ├── fit │ │ └── fit.js │ ├── attach │ │ └── attach.js │ ├── terminado │ │ └── terminado.js │ └── linkify │ │ └── linkify.js ├── term.html ├── vuetable.json └── js │ └── custom.js ├── .gitattributes ├── .gitignore ├── favicon.ico ├── config ├── prod.env.js ├── dev.env.js └── index.js ├── src ├── components │ ├── common │ │ ├── bus.js │ │ ├── Home.vue │ │ ├── Tags.vue │ │ ├── Sidebar.vue │ │ └── Header.vue │ ├── common_u │ │ ├── bus.js │ │ ├── Home_u.vue │ │ ├── Sidebar_u.vue │ │ ├── Tags_u.vue │ │ └── Header_u.vue │ ├── page │ │ ├── MonitorManage.vue │ │ ├── Portainer.vue │ │ ├── Visualizer.vue │ │ ├── 403.vue │ │ ├── 404.vue │ │ ├── TokenManage.vue │ │ ├── ProjectsDetails.vue │ │ ├── ServiceManage.vue │ │ ├── PublicLocalImage.vue │ │ ├── NoticeManage.vue │ │ ├── ProjectManage.vue │ │ ├── UserLocalImage.vue │ │ ├── Register.vue │ │ ├── VolumesManage.vue │ │ ├── ServiceDetails.vue │ │ └── SystemLog.vue │ └── page_u │ │ ├── mirror │ │ ├── mirrorDetail.vue │ │ ├── history.vue │ │ └── detail.vue │ │ ├── 403.vue │ │ ├── 404.vue │ │ ├── networkDetails.vue │ │ ├── Markdown.vue │ │ ├── createNetwork.vue │ │ ├── help.vue │ │ └── serviceDetails.vue ├── App.vue ├── main.js └── store │ └── store.js ├── .editorconfig ├── .idea ├── misc.xml ├── vcs.xml ├── modules.xml └── vue-manage-system.iml ├── .postcssrc.js ├── .babelrc ├── index.html └── package.json /static/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.js linguist-language=Vue -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log 5 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jitwxs/paas-protal/HEAD/favicon.ico -------------------------------------------------------------------------------- /static/img/cat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jitwxs/paas-protal/HEAD/static/img/cat.jpg -------------------------------------------------------------------------------- /static/tree/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jitwxs/paas-protal/HEAD/static/tree/add.png -------------------------------------------------------------------------------- /static/tree/sub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jitwxs/paas-protal/HEAD/static/tree/sub.png -------------------------------------------------------------------------------- /config/prod.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = { 3 | NODE_ENV: '"production"' 4 | } 5 | -------------------------------------------------------------------------------- /static/img/cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jitwxs/paas-protal/HEAD/static/img/cloud.png -------------------------------------------------------------------------------- /static/img/docker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jitwxs/paas-protal/HEAD/static/img/docker.png -------------------------------------------------------------------------------- /static/img/docker2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jitwxs/paas-protal/HEAD/static/img/docker2.png -------------------------------------------------------------------------------- /static/font/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jitwxs/paas-protal/HEAD/static/font/iconfont.eot -------------------------------------------------------------------------------- /static/font/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jitwxs/paas-protal/HEAD/static/font/iconfont.ttf -------------------------------------------------------------------------------- /static/font/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jitwxs/paas-protal/HEAD/static/font/iconfont.woff -------------------------------------------------------------------------------- /static/img/index/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jitwxs/paas-protal/HEAD/static/img/index/logo.png -------------------------------------------------------------------------------- /static/img/index/picture1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jitwxs/paas-protal/HEAD/static/img/index/picture1.jpg -------------------------------------------------------------------------------- /static/img/index/picture2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jitwxs/paas-protal/HEAD/static/img/index/picture2.png -------------------------------------------------------------------------------- /static/img/index/picture3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jitwxs/paas-protal/HEAD/static/img/index/picture3.png -------------------------------------------------------------------------------- /static/img/index/picture4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jitwxs/paas-protal/HEAD/static/img/index/picture4.jpg -------------------------------------------------------------------------------- /static/img/index/picture5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jitwxs/paas-protal/HEAD/static/img/index/picture5.jpg -------------------------------------------------------------------------------- /static/img/index/picture6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jitwxs/paas-protal/HEAD/static/img/index/picture6.png -------------------------------------------------------------------------------- /static/img/index/picture7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jitwxs/paas-protal/HEAD/static/img/index/picture7.png -------------------------------------------------------------------------------- /static/img/index/picture8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jitwxs/paas-protal/HEAD/static/img/index/picture8.png -------------------------------------------------------------------------------- /static/img/index/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jitwxs/paas-protal/HEAD/static/img/index/background.jpg -------------------------------------------------------------------------------- /src/components/common/bus.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | 3 | // 使用 Event Bus 4 | const bus = new Vue(); 5 | 6 | export default bus; -------------------------------------------------------------------------------- /src/components/common_u/bus.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | 3 | // 使用 Event Bus 4 | const bus = new Vue(); 5 | 6 | export default bus; -------------------------------------------------------------------------------- /static/css/theme-green/fonts/element-icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jitwxs/paas-protal/HEAD/static/css/theme-green/fonts/element-icons.ttf -------------------------------------------------------------------------------- /static/css/theme-green/fonts/element-icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jitwxs/paas-protal/HEAD/static/css/theme-green/fonts/element-icons.woff -------------------------------------------------------------------------------- /config/dev.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const merge = require('webpack-merge') 3 | const prodEnv = require('./prod.env') 4 | 5 | module.exports = merge(prodEnv, { 6 | NODE_ENV: '"development"' 7 | }) 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/components/page/MonitorManage.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | 11 | 14 | -------------------------------------------------------------------------------- /static/addons/fullscreen/fullscreen.css: -------------------------------------------------------------------------------- 1 | .xterm.fullscreen { 2 | position: fixed; 3 | top: 0; 4 | bottom: 0; 5 | left: 0; 6 | right: 0; 7 | width: auto; 8 | height: auto; 9 | z-index: 255; 10 | } 11 | -------------------------------------------------------------------------------- /.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | // to edit target browsers: use "browserslist" field in package.json 6 | "postcss-import": {}, 7 | "autoprefixer": {} 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { 4 | "modules": false, 5 | "targets": { 6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] 7 | } 8 | }], 9 | "stage-2" 10 | ], 11 | "plugins": ["transform-vue-jsx", "transform-runtime"] 12 | } 13 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vue-manage-system.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /static/css/color-dark.css: -------------------------------------------------------------------------------- 1 | .header{ 2 | background-color: #242f42; 3 | } 4 | .login-wrap{ 5 | background: #324157; 6 | } 7 | .plugins-tips{ 8 | background: #eef1f6; 9 | } 10 | .plugins-tips a{ 11 | color: #20a0ff; 12 | } 13 | .el-upload--text em { 14 | color: #20a0ff; 15 | } 16 | .pure-button{ 17 | background: #20a0ff; 18 | } 19 | .tags-li.active { 20 | border: 1px solid #409EFF; 21 | background-color: #409EFF; 22 | } 23 | .message-title{ 24 | color: #20a0ff; 25 | } 26 | .collapse-btn:hover{ 27 | background: rgb(40,52,70); 28 | } -------------------------------------------------------------------------------- /static/img/gou.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/img/icon_docker-image.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/css/theme-green/color-green.css: -------------------------------------------------------------------------------- 1 | .header{ 2 | background-color: #07c4a8; 3 | } 4 | .login-wrap{ 5 | background: rgba(56, 157, 170, 0.82);; 6 | } 7 | .plugins-tips{ 8 | background: #f2f2f2; 9 | } 10 | .plugins-tips a{ 11 | color: #00d1b2; 12 | } 13 | .el-upload--text em { 14 | color: #00d1b2; 15 | } 16 | .pure-button{ 17 | background: #00d1b2; 18 | } 19 | .pagination > .active > a, .pagination > .active > a:hover, .pagination > .active > a:focus, .pagination > .active > span, .pagination > .active > span:hover, .pagination > .active > span:focus { 20 | background-color: #00d1b2 !important; 21 | border-color: #00d1b2 !important; 22 | } 23 | .tags-li.active { 24 | border: 1px solid #00d1b2; 25 | background-color: #00d1b2; 26 | } 27 | .collapse-btn:hover{ 28 | background: #00d1b2; 29 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 无道云平台 | 基于Docker容器的PaaS系统 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /static/term.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 远程连接 | 无道云平台 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/components/page_u/mirror/mirrorDetail.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 38 | 39 | 42 | -------------------------------------------------------------------------------- /static/vuetable.json: -------------------------------------------------------------------------------- 1 | { 2 | "list": [{ 3 | "date": "1997-11-11", 4 | "name": "林丽", 5 | "address": "吉林省 辽源市 龙山区" 6 | }, { 7 | "date": "1987-09-24", 8 | "name": "文敏", 9 | "address": "江西省 萍乡市 芦溪县" 10 | }, { 11 | "date": "1996-08-08", 12 | "name": "杨秀兰", 13 | "address": "黑龙江省 黑河市 五大连池市" 14 | }, { 15 | "date": "1978-06-18", 16 | "name": "魏强", 17 | "address": "广东省 韶关市 始兴县" 18 | }, { 19 | "date": "1977-07-09", 20 | "name": "石秀兰", 21 | "address": "江苏省 宿迁市 宿豫区" 22 | }, { 23 | "date": "1994-09-20", 24 | "name": "朱洋", 25 | "address": "海外 海外 -" 26 | }, { 27 | "date": "1980-01-22", 28 | "name": "傅敏", 29 | "address": "海外 海外 -" 30 | }, { 31 | "date": "1985-10-10", 32 | "name": "毛明", 33 | "address": "内蒙古自治区 包头市 九原区" 34 | }, { 35 | "date": "1975-09-08", 36 | "name": "何静", 37 | "address": "西藏自治区 阿里地区 普兰县" 38 | }, { 39 | "date": "1970-06-07", 40 | "name": "郭秀英", 41 | "address": "四川省 巴中市 恩阳区" 42 | }] 43 | } -------------------------------------------------------------------------------- /src/components/page/Portainer.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 38 | 39 | 42 | -------------------------------------------------------------------------------- /src/components/page/Visualizer.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 38 | 39 | 42 | -------------------------------------------------------------------------------- /static/img/icon_docker.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 37 | 38 | 43 | -------------------------------------------------------------------------------- /src/components/page_u/mirror/history.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 47 | 48 | 51 | -------------------------------------------------------------------------------- /static/img/people.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 11 | 14 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/components/page/403.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 23 | 24 | 25 | 57 | -------------------------------------------------------------------------------- /src/components/page_u/403.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 23 | 24 | 25 | 57 | -------------------------------------------------------------------------------- /src/components/page_u/404.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 23 | 24 | 25 | 57 | -------------------------------------------------------------------------------- /src/components/page/404.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 23 | 24 | 25 | 57 | -------------------------------------------------------------------------------- /static/addons/fullscreen/fullscreen.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Fullscreen addon for xterm.js 3 | * @module xterm/addons/fullscreen/fullscreen 4 | * @license MIT 5 | */ 6 | (function (fullscreen) { 7 | if (typeof exports === 'object' && typeof module === 'object') { 8 | /* 9 | * CommonJS environment 10 | */ 11 | module.exports = fullscreen(require('../../xterm')); 12 | } else if (typeof define == 'function') { 13 | /* 14 | * Require.js is available 15 | */ 16 | define(['../../xterm'], fullscreen); 17 | } else { 18 | /* 19 | * Plain browser environment 20 | */ 21 | fullscreen(window.Terminal); 22 | } 23 | })(function (Xterm) { 24 | var exports = {}; 25 | 26 | /** 27 | * Toggle the given terminal's fullscreen mode. 28 | * @param {Xterm} term - The terminal to toggle full screen mode 29 | * @param {boolean} fullscreen - Toggle fullscreen on (true) or off (false) 30 | */ 31 | exports.toggleFullScreen = function (term, fullscreen) { 32 | var fn; 33 | 34 | if (typeof fullscreen == 'undefined') { 35 | fn = (term.element.classList.contains('fullscreen')) ? 'remove' : 'add'; 36 | } else if (!fullscreen) { 37 | fn = 'remove'; 38 | } else { 39 | fn = 'add'; 40 | } 41 | 42 | term.element.classList[fn]('fullscreen'); 43 | }; 44 | 45 | Xterm.prototype.toggleFullscreen = function (fullscreen) { 46 | exports.toggleFullScreen(this, fullscreen); 47 | }; 48 | 49 | return exports; 50 | }); 51 | -------------------------------------------------------------------------------- /src/components/common/Home.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 49 | -------------------------------------------------------------------------------- /src/components/common_u/Home_u.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 49 | -------------------------------------------------------------------------------- /static/tree/jsoneditor.css: -------------------------------------------------------------------------------- 1 | .json-editor { 2 | margin-left: 10px; 3 | padding: 20px; 4 | } 5 | 6 | .json-editor.expanded .item { 7 | display: block !important; 8 | } 9 | 10 | .json-editor .property, 11 | .json-editor .value { 12 | border: none; 13 | -webkit-border-radius: 5px; 14 | -moz-border-radius: 5px; 15 | border-radius: 5px; 16 | padding: 3px; 17 | margin-right: 2px; 18 | } 19 | 20 | .json-editor .value { 21 | background-color: #ECF3C3; 22 | width: 600px; 23 | } 24 | .json-editor .property { 25 | width: 154px; 26 | background-color: #B1C639; 27 | color: white; 28 | font-weight: bold; 29 | text-shadow: 1px 1px 1px black; 30 | } 31 | .json-editor button.property { 32 | width: 160px; 33 | } 34 | 35 | .json-editor .editing { 36 | border: 1px solid gray; 37 | outline: none; 38 | } 39 | 40 | .json-editor .item { 41 | line-height: 20px; 42 | margin-top: 2px; 43 | } 44 | .json-editor .item:last-child { 45 | border-bottom: none; 46 | } 47 | 48 | .json-editor .item > .item { 49 | margin-left: 30px; 50 | display: none; 51 | } 52 | 53 | .json-editor .item.expanded > .item { 54 | display: block; 55 | } 56 | 57 | .json-editor .expander { 58 | background: url("add.png") no-repeat center center; 59 | width: 16px; 60 | height: 11px; 61 | display: inline-block; 62 | margin-left: -15px; 63 | cursor: pointer; 64 | } 65 | .json-editor .item.expanded > .expander { 66 | background: url("sub.png") no-repeat center center; 67 | } 68 | 69 | .json-editor .item.appender > .property { 70 | background-color: #999999; 71 | cursor: pointer; 72 | width: 100px; 73 | } 74 | .json-editor .item.string > .property { background-color: #009408; } 75 | .json-editor .item.array > .property { background-color: #2D5B89; } 76 | .json-editor .item.object > .property { background-color: #E17000; } 77 | .json-editor .item.number > .property { background-color: #497B8D; } 78 | /*.json-editor .item.boolean { background-color: }*/ 79 | /*.json-editor .item.null { background-color: }*/ -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from './App'; 3 | import router from './router'; 4 | import axios from 'axios'; 5 | import ElementUI from 'element-ui'; 6 | import 'element-ui/lib/theme-chalk/index.css'; // 默认主题 7 | // import '../static/css/theme-green/index.css'; // 浅绿色主题 8 | import "babel-polyfill"; 9 | import qs from 'qs' 10 | import store from './store/store' 11 | import echarts from "echarts" 12 | import semantic from 'semantic' 13 | import '../node_modules/semantic-ui-css/semantic.min.css' 14 | 15 | Vue.prototype.$echarts = echarts; 16 | 17 | Vue.use(ElementUI, { size: 'small' }); 18 | 19 | //axios全局配置 20 | Vue.prototype.$axios = axios; 21 | axios.defaults.baseURL = '/api'; 22 | 23 | Vue.config.productionTip = false; 24 | 25 | axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; 26 | 27 | router.beforeEach((to, from, next) => { 28 | if (to.matched.some(record => record.meta.requiresAuth)) { 29 | //这里判断用户是否登录,我例子中是验证本地存储是否有token 30 | if (!sessionStorage.userToken) { 31 | next({ 32 | path: '/login', 33 | query: { redirect: to.fullPath } 34 | }) 35 | } else { 36 | next() 37 | } 38 | } else { 39 | next() // 确保一定要调用 next() 40 | } 41 | }) 42 | 43 | // 发送请求时拦截,转换数据格式 44 | axios.interceptors.request.use( (config) => { 45 | if (sessionStorage.userToken) { 46 | // 判断是否存在token,如果存在的话,则每个http header都加上token 47 | config.headers.Authorization = `${sessionStorage.userToken}`; 48 | } 49 | if (config.method=="post" || config.method =="put"){ 50 | config.data = qs.stringify(config.data); 51 | // config.headers['Content-Type'] = 'application/x-www-form-urlencoded'; 52 | } 53 | return config; 54 | }, (error) => { 55 | return Promise.reject(error); 56 | }); 57 | 58 | axios.interceptors.response.use(function (res) { 59 | if (res.data.code===28 || res.data.code===29 || res.data.code===30){ 60 | router.replace({ 61 | path:'/index' 62 | }) 63 | } 64 | return res; 65 | }, (err)=>{ 66 | return Promise.reject(error); 67 | }); 68 | 69 | 70 | new Vue({ 71 | el: '#app', 72 | store, 73 | router, 74 | render: h => h(App) 75 | }).$mount('#app'); 76 | -------------------------------------------------------------------------------- /src/components/page_u/networkDetails.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 60 | 61 | 71 | -------------------------------------------------------------------------------- /static/img/swarm.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/page_u/Markdown.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 63 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-manage-system", 3 | "version": "3.1.0", 4 | "description": "基于Vue.js 2.x系列 + element-ui 内容管理系统解决方案", 5 | "author": "lin-xin <2981207131@qq.com>", 6 | "private": true, 7 | "scripts": { 8 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", 9 | "build": "node build/build.js", 10 | "build:dll": "webpack --config build/webpack.dll.conf.js" 11 | }, 12 | "dependencies": { 13 | "axios": "^0.18.1", 14 | "babel-polyfill": "^6.23.0", 15 | "echarts": "^4.1.0", 16 | "element-ui": "^2.3.3", 17 | "jquery": "^3.3.1", 18 | "jsoneditor": "^5.19.0", 19 | "mavon-editor": "^2.5.4", 20 | "npm": "^6.1.0", 21 | "qs": "^6.5.2", 22 | "semantic-ui-css": "^2.3.3", 23 | "vue": "^2.5.16", 24 | "vue-cropperjs": "^2.2.0", 25 | "vue-quill-editor": "3.0.6", 26 | "vue-router": "^3.0.1", 27 | "vue-schart": "^1.0.0", 28 | "vuedraggable": "^2.16.0", 29 | "vuex": "^3.0.1" 30 | }, 31 | "devDependencies": { 32 | "autoprefixer": "^7.1.2", 33 | "babel-core": "^6.22.1", 34 | "babel-helper-vue-jsx-merge-props": "^2.0.3", 35 | "babel-loader": "^7.1.1", 36 | "babel-plugin-syntax-jsx": "^6.18.0", 37 | "babel-plugin-transform-runtime": "^6.22.0", 38 | "babel-plugin-transform-vue-jsx": "^3.5.0", 39 | "babel-preset-env": "^1.3.2", 40 | "babel-preset-stage-2": "^6.22.0", 41 | "chalk": "^2.0.1", 42 | "copy-webpack-plugin": "^4.0.1", 43 | "css-loader": "^0.28.0", 44 | "extract-text-webpack-plugin": "^3.0.0", 45 | "file-loader": "^1.1.4", 46 | "friendly-errors-webpack-plugin": "^1.6.1", 47 | "html-webpack-plugin": "^2.30.1", 48 | "node-notifier": "^5.1.2", 49 | "optimize-css-assets-webpack-plugin": "^3.2.0", 50 | "ora": "^1.2.0", 51 | "portfinder": "^1.0.13", 52 | "postcss-import": "^11.0.0", 53 | "postcss-loader": "^2.0.8", 54 | "rimraf": "^2.6.0", 55 | "semver": "^5.3.0", 56 | "shelljs": "^0.7.6", 57 | "uglifyjs-webpack-plugin": "^1.1.1", 58 | "url-loader": "^0.5.8", 59 | "vue-loader": "^13.3.0", 60 | "vue-style-loader": "^3.0.1", 61 | "vue-template-compiler": "^2.5.2", 62 | "webpack": "^3.6.0", 63 | "webpack-bundle-analyzer": "^3.3.2", 64 | "webpack-dev-server": "^2.9.1", 65 | "webpack-merge": "^4.1.0" 66 | }, 67 | "engines": { 68 | "node": ">= 4.0.0", 69 | "npm": ">= 3.0.0" 70 | }, 71 | "browserslist": [ 72 | "> 1%", 73 | "last 5 versions", 74 | "not ie <= 8" 75 | ] 76 | } 77 | -------------------------------------------------------------------------------- /config/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | // Template version: 1.2.7// see http://vuejs-templates.github.io/webpack for documentation. 3 | 4 | const path = require('path') 5 | 6 | module.exports = { 7 | dev: { 8 | 9 | // Paths 10 | assetsSubDirectory: 'static', 11 | assetsPublicPath: '/', 12 | proxyTable: { 13 | '/api':{ 14 | target:'http://192.168.100.110:9999', 15 | changeOrigin:true, 16 | pathRewrite:{ 17 | '/api':'' 18 | } 19 | } 20 | }, 21 | // Various Dev Server settings 22 | host: '0.0.0.0', // can be overwritten by process.env.HOST 23 | port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined 24 | autoOpenBrowser: false, 25 | errorOverlay: true, 26 | notifyOnErrors: true, 27 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- 28 | 29 | 30 | /** 31 | * Source Maps 32 | */ 33 | 34 | // https://webpack.js.org/configuration/devtool/#development 35 | devtool: 'eval-source-map', 36 | 37 | // If you have problems debugging vue-files in devtools, 38 | // set this to false - it *may* help 39 | // https://vue-loader.vuejs.org/en/options.html#cachebusting 40 | cacheBusting: true, 41 | 42 | // CSS Sourcemaps off by default because relative paths are "buggy" 43 | // with this option, according to the CSS-Loader README 44 | // (https://github.com/webpack/css-loader#sourcemaps) 45 | // In our experience, they generally work as expected, 46 | // just be aware of this issue when enabling this option. 47 | cssSourceMap: false, 48 | }, 49 | 50 | build: { 51 | // Template for index.html 52 | index: path.resolve(__dirname, '../dist/index.html'), 53 | 54 | // Paths 55 | assetsRoot: path.resolve(__dirname, '../dist'), 56 | assetsSubDirectory: 'static', 57 | assetsPublicPath: './', 58 | 59 | /** 60 | * Source Maps 61 | */ 62 | 63 | productionSourceMap: false, 64 | // https://webpack.js.org/configuration/devtool/#production 65 | devtool: '#source-map', 66 | 67 | // Gzip off by default as many popular static hosts such as 68 | // Surge or Netlify already gzip all static assets for you. 69 | // Before setting to `true`, make sure to: 70 | // npm install --save-dev compression-webpack-plugin 71 | productionGzip: false, 72 | productionGzipExtensions: ['js', 'css'], 73 | 74 | // Run the build command with an extra argument to 75 | // View the bundle analyzer report after build finishes: 76 | // `npm run build --report` 77 | // Set to `true` or `false` to always turn it on or off 78 | bundleAnalyzerReport: process.env.npm_config_report 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/components/page_u/mirror/detail.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 77 | 78 | 81 | -------------------------------------------------------------------------------- /src/components/page/TokenManage.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 79 | 80 | 83 | -------------------------------------------------------------------------------- /src/store/store.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | 4 | Vue.use(Vuex) 5 | 6 | const state = { 7 | token: '', 8 | userInfo: {}, 9 | projectId: '', 10 | editeContainerProjectId: '', 11 | containerId :'', 12 | hostaddr:'192.168.100.110:9999', 13 | serviceId:'', 14 | currentMirrorId:'', 15 | unreadMessageNum:0, 16 | networkId:'' 17 | }; 18 | 19 | const mutations = { 20 | SET_CONTAINERID(state, containerId){ 21 | state.containerId = containerId; 22 | }, 23 | 24 | SET_TOKEN(state, token) { 25 | state.token = token; 26 | sessionStorage.token = token 27 | }, 28 | DEL_TOKEN(state) { 29 | state.token = ''; 30 | sessionStorage.removeItem('token'); 31 | }, 32 | CHANGE_USER_INFO(state, userInfo) { 33 | state.userInfo = userInfo 34 | }, 35 | SET_PROJECT_ID(state, projectId) { 36 | state.projectId = projectId 37 | }, 38 | SET_EDITE_CONTAINER_PROJECT_ID(state, editeContainerId) { 39 | state.editeContainerProjectId = editeContainerId 40 | }, 41 | SET_SERVICE_ID(state,serviceId){ 42 | state.serviceId = serviceId 43 | }, 44 | SET_CURRENTMIRROR_ID(state,mirrorId){ 45 | state.currentMirrorId = mirrorId; 46 | }, 47 | SET_UNREAD_MESSAGE_NUM(state,num){ 48 | state.unreadMessageNum = num; 49 | }, 50 | SET_NETWORKID(state,networkId){ 51 | state.networkId = networkId; 52 | } 53 | } 54 | const actions = { 55 | changeUserInfo({commit}, userInfo) { 56 | commit('CHANGE_USER_INFO', userInfo) 57 | }, 58 | setProjectId({commit}, projectId) { 59 | 60 | commit("SET_PROJECT_ID", projectId) 61 | }, 62 | setEditeContainerProjectId({commit}, id) { 63 | commit("SET_EDITE_CONTAINER_PROJECT_ID", id) 64 | }, 65 | setContainerId({commit},containerId){ 66 | commit("SET_CONTAINERID",containerId) 67 | }, 68 | saveServiceId({commit},id){ 69 | commit("SET_SERVICE_ID",id) 70 | }, 71 | setUnreadMessageNum({commit},num){ 72 | commit('SET_UNREAD_MESSAGE_NUM',num); 73 | } 74 | } 75 | const getters = { 76 | getUserInfo(state) { 77 | return state.userInfo 78 | }, 79 | getProjectId(state) { 80 | return state.projectId; 81 | }, 82 | getEidteContainerProjectId(state) { 83 | 84 | return state.editeContainerProjectId; 85 | }, 86 | getContainerId(state){ 87 | return state.containerId; 88 | }, 89 | gethostaddr(state){ 90 | return state.hostaddr; 91 | }, 92 | getServiceId(state){ 93 | return state.serviceId; 94 | }, 95 | getCurrentMirrorId(state){ 96 | return state.currentMirrorId; 97 | }, 98 | getToken(state){ 99 | return state.token; 100 | }, 101 | getUnreadMessageNum(state){ 102 | return state.unreadMessageNum; 103 | }, 104 | getNetworkId(state){ 105 | return state.networkId; 106 | } 107 | }; 108 | export default new Vuex.Store({ 109 | state, 110 | mutations, 111 | actions, 112 | getters 113 | }) 114 | 115 | -------------------------------------------------------------------------------- /static/addons/fit/fit.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Fit terminal columns and rows to the dimensions of its DOM element. 3 | * 4 | * ## Approach 5 | * - Rows: Truncate the division of the terminal parent element height by the terminal row height. 6 | * 7 | * - Columns: Truncate the division of the terminal parent element width by the terminal character 8 | * width (apply display: inline at the terminal row and truncate its width with the current 9 | * number of columns). 10 | * @module xterm/addons/fit/fit 11 | * @license MIT 12 | */ 13 | 14 | (function (fit) { 15 | if (typeof exports === 'object' && typeof module === 'object') { 16 | /* 17 | * CommonJS environment 18 | */ 19 | module.exports = fit(require('../../xterm')); 20 | } else if (typeof define == 'function') { 21 | /* 22 | * Require.js is available 23 | */ 24 | define(['../../xterm'], fit); 25 | } else { 26 | /* 27 | * Plain browser environment 28 | */ 29 | fit(window.Terminal); 30 | } 31 | })(function (Xterm) { 32 | var exports = {}; 33 | 34 | exports.proposeGeometry = function (term) { 35 | if (!term.element.parentElement) { 36 | return null; 37 | } 38 | var parentElementStyle = window.getComputedStyle(term.element.parentElement), 39 | parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height')), 40 | parentElementWidth = Math.max(0, parseInt(parentElementStyle.getPropertyValue('width')) - 17), 41 | elementStyle = window.getComputedStyle(term.element), 42 | elementPaddingVer = parseInt(elementStyle.getPropertyValue('padding-top')) + parseInt(elementStyle.getPropertyValue('padding-bottom')), 43 | elementPaddingHor = parseInt(elementStyle.getPropertyValue('padding-right')) + parseInt(elementStyle.getPropertyValue('padding-left')), 44 | availableHeight = parentElementHeight - elementPaddingVer, 45 | availableWidth = parentElementWidth - elementPaddingHor, 46 | container = term.rowContainer, 47 | subjectRow = term.rowContainer.firstElementChild, 48 | contentBuffer = subjectRow.innerHTML, 49 | characterHeight, 50 | rows, 51 | characterWidth, 52 | cols, 53 | geometry; 54 | 55 | subjectRow.style.display = 'inline'; 56 | subjectRow.innerHTML = 'W'; // Common character for measuring width, although on monospace 57 | characterWidth = subjectRow.getBoundingClientRect().width; 58 | subjectRow.style.display = ''; // Revert style before calculating height, since they differ. 59 | characterHeight = subjectRow.getBoundingClientRect().height; 60 | subjectRow.innerHTML = contentBuffer; 61 | 62 | rows = parseInt(availableHeight / characterHeight); 63 | cols = parseInt(availableWidth / characterWidth); 64 | 65 | geometry = {cols: cols, rows: rows}; 66 | return geometry; 67 | }; 68 | 69 | exports.fit = function (term) { 70 | var geometry = exports.proposeGeometry(term); 71 | 72 | if (geometry) { 73 | term.resize(geometry.cols, geometry.rows); 74 | } 75 | }; 76 | 77 | Xterm.prototype.proposeGeometry = function () { 78 | return exports.proposeGeometry(this); 79 | }; 80 | 81 | Xterm.prototype.fit = function () { 82 | return exports.fit(this); 83 | }; 84 | 85 | return exports; 86 | }); 87 | -------------------------------------------------------------------------------- /static/css/main.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | } 5 | 6 | html, 7 | body, 8 | #app, 9 | .wrapper { 10 | width: 100%; 11 | height: 100%; 12 | overflow: hidden; 13 | } 14 | 15 | body { 16 | font-family: 'PingFang SC', "Helvetica Neue", Helvetica, "microsoft yahei", arial, STHeiTi, sans-serif; 17 | } 18 | 19 | a { 20 | text-decoration: none 21 | } 22 | 23 | .content-box { 24 | position: absolute; 25 | left: 250px; 26 | right: 0; 27 | top: 70px; 28 | bottom: 0; 29 | overflow-y: scroll; 30 | -webkit-transition: left .3s ease-in-out; 31 | transition: left .3s ease-in-out; 32 | background: #f0f0f0; 33 | } 34 | 35 | .content { 36 | width: auto; 37 | padding: 40px; 38 | } 39 | 40 | .content-collapse { 41 | left: 65px; 42 | } 43 | 44 | .container { 45 | padding: 30px; 46 | background: #fff; 47 | border: 1px solid #ddd; 48 | border-radius: 5px; 49 | } 50 | 51 | .crumbs { 52 | margin-bottom: 20px; 53 | } 54 | 55 | .pagination { 56 | margin: 20px 0; 57 | text-align: right; 58 | } 59 | 60 | .plugins-tips { 61 | padding: 20px 10px; 62 | margin-bottom: 20px; 63 | } 64 | 65 | .el-button+.el-tooltip { 66 | margin-left: 10px; 67 | } 68 | 69 | .el-table tr:hover { 70 | background: #f6faff; 71 | } 72 | 73 | .mgb20 { 74 | margin-bottom: 20px; 75 | } 76 | 77 | .move-enter-active, 78 | .move-leave-active { 79 | transition: opacity .5s; 80 | } 81 | 82 | .move-enter, 83 | .move-leave { 84 | opacity: 0; 85 | } 86 | 87 | /*BaseForm*/ 88 | 89 | .form-box { 90 | width: 600px; 91 | } 92 | 93 | .form-box .line { 94 | text-align: center; 95 | } 96 | 97 | .el-time-panel__content::after, 98 | .el-time-panel__content::before { 99 | margin-top: -7px; 100 | } 101 | 102 | .el-time-spinner__wrapper .el-scrollbar__wrap:not(.el-scrollbar__wrap--hidden-default) { 103 | padding-bottom: 0; 104 | } 105 | 106 | /*Upload*/ 107 | 108 | .pure-button { 109 | width: 150px; 110 | height: 40px; 111 | line-height: 40px; 112 | text-align: center; 113 | color: #fff; 114 | border-radius: 3px; 115 | } 116 | 117 | .g-core-image-corp-container .info-aside { 118 | height: 45px; 119 | } 120 | 121 | .el-upload--text { 122 | background-color: #fff; 123 | border: 1px dashed #d9d9d9; 124 | border-radius: 6px; 125 | box-sizing: border-box; 126 | width: 360px; 127 | height: 180px; 128 | text-align: center; 129 | cursor: pointer; 130 | position: relative; 131 | overflow: hidden; 132 | } 133 | 134 | .el-upload--text .el-icon-upload { 135 | font-size: 67px; 136 | color: #97a8be; 137 | margin: 40px 0 16px; 138 | line-height: 50px; 139 | } 140 | 141 | .el-upload--text { 142 | color: #97a8be; 143 | font-size: 14px; 144 | text-align: center; 145 | } 146 | 147 | .el-upload--text em { 148 | font-style: normal; 149 | } 150 | 151 | /*VueEditor*/ 152 | 153 | .ql-container { 154 | min-height: 400px; 155 | } 156 | 157 | .ql-snow .ql-tooltip { 158 | transform: translateX(117.5px) translateY(10px) !important; 159 | } 160 | 161 | .editor-btn { 162 | margin-top: 20px; 163 | } 164 | 165 | /*markdown*/ 166 | 167 | .v-note-wrapper .v-note-panel { 168 | min-height: 500px; 169 | } 170 | -------------------------------------------------------------------------------- /static/js/custom.js: -------------------------------------------------------------------------------- 1 | // 将字节转换为合适的格式 2 | function bitConvert(limit){ 3 | let size = ""; 4 | if( limit < 0.1 * 1024 ){ //如果小于0.1KB转化成B 5 | size = limit.toFixed(2) + "B"; 6 | }else if(limit < 0.1 * 1024 * 1024 ){//如果小于0.1MB转化成KB 7 | size = (limit / 1024).toFixed(2) + "KB"; 8 | }else if(limit < 0.1 * 1024 * 1024 * 1024){ //如果小于0.1GB转化成MB 9 | size = (limit / (1024 * 1024)).toFixed(2) + "MB"; 10 | }else{ //其他转化成GB 11 | size = (limit / (1024 * 1024 * 1024)).toFixed(2) + "GB"; 12 | } 13 | 14 | let sizestr = size + ""; 15 | let len = sizestr.indexOf("\."); 16 | let dec = sizestr.substr(len + 1, 2); 17 | if(dec === "00"){//当小数点后为00时 去掉小数部分 18 | return sizestr.substring(0,len) + sizestr.substr(len + 3,2); 19 | } 20 | return sizestr; 21 | } 22 | 23 | function getLocalTime(nS) { 24 | return new Date(parseInt(nS) * 1000).toLocaleString().replace(/:\d{1,2}$/,' '); 25 | } 26 | 27 | // 日期格式化 28 | function dateFormatter(str){//默认返回yyyy-MM-dd HH-mm-ss 29 | var hasTime = arguments[1] != false ? true : false;//可传第二个参数false,返回yyyy-MM-dd 30 | var d = new Date(str); 31 | var year = d.getFullYear(); 32 | var month = (d.getMonth()+1)<10 ? '0'+(d.getMonth()+1) : (d.getMonth()+1); 33 | var day = d.getDate()<10 ? '0'+d.getDate() : d.getDate(); 34 | var hour = d.getHours()<10 ? '0'+d.getHours() : d.getHours(); 35 | var minute = d.getMinutes()<10 ? '0'+d.getMinutes() : d.getMinutes(); 36 | var second = d.getSeconds()<10 ? '0'+d.getSeconds() : d.getSeconds(); 37 | if(hasTime){ 38 | return [year, month, day].join('-') + " " + [hour, minute, second].join(':'); 39 | }else{ 40 | return [year, month, day].join('-'); 41 | } 42 | } 43 | 44 | // JSON美化 45 | function syntaxHighlight(json) { 46 | if (typeof json != 'string') { 47 | json = JSON.stringify(json, undefined, 2); 48 | } 49 | json = json.replace(/&/g, '&').replace(//g, '>'); 50 | return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function(match) { 51 | var cls = 'number'; 52 | if (/^"/.test(match)) { 53 | if (/:$/.test(match)) { 54 | cls = 'key'; 55 | } else { 56 | cls = 'string'; 57 | } 58 | } else if (/true|false/.test(match)) { 59 | cls = 'boolean'; 60 | } else if (/null/.test(match)) { 61 | cls = 'null'; 62 | } 63 | return '' + match + ''; 64 | }); 65 | } 66 | 67 | //形如:{\"80\":[{\"HostIp\":\"0.0.0.0\",\"HostPort\":\"14752\"}]} 68 | function formatPort1(port) { 69 | if(port === null || port === "") { 70 | return null; 71 | } 72 | 73 | port = port.toString().replace("\\", ""); 74 | port = eval('(' + port + ')'); 75 | 76 | let resArry = new Array(); 77 | for (let key in port) { 78 | let value = port[key][0].HostPort; 79 | resArry.push(value + ":" + key); 80 | } 81 | return resArry.join(","); 82 | } 83 | 84 | // 形如:{\"80\":32111} 85 | function formatPort2(port) { 86 | if(port === null || port === "") { 87 | return port; 88 | } 89 | let foo = port.toString().replace("\\","").replace("{","").replace("}","").replace("\"","").replace("\"",""); 90 | let arr = foo.split(":"); 91 | arr.reverse(); 92 | return arr.join(":"); 93 | } 94 | -------------------------------------------------------------------------------- /src/components/common_u/Sidebar_u.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 94 | 95 | 114 | -------------------------------------------------------------------------------- /static/addons/attach/attach.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implements the attach method, that attaches the terminal to a WebSocket stream. 3 | * @module xterm/addons/attach/attach 4 | * @license MIT 5 | */ 6 | 7 | (function (attach) { 8 | if (typeof exports === 'object' && typeof module === 'object') { 9 | /* 10 | * CommonJS environment 11 | */ 12 | module.exports = attach(require('../../xterm')); 13 | } else if (typeof define == 'function') { 14 | /* 15 | * Require.js is available 16 | */ 17 | define(['../../xterm'], attach); 18 | } else { 19 | /* 20 | * Plain browser environment 21 | */ 22 | attach(window.Terminal); 23 | } 24 | })(function (Xterm) { 25 | 'use strict'; 26 | 27 | var exports = {}; 28 | 29 | /** 30 | * Attaches the given terminal to the given socket. 31 | * 32 | * @param {Xterm} term - The terminal to be attached to the given socket. 33 | * @param {WebSocket} socket - The socket to attach the current terminal. 34 | * @param {boolean} bidirectional - Whether the terminal should send data 35 | * to the socket as well. 36 | * @param {boolean} buffered - Whether the rendering of incoming data 37 | * should happen instantly or at a maximum 38 | * frequency of 1 rendering per 10ms. 39 | */ 40 | exports.attach = function (term, socket, bidirectional, buffered) { 41 | bidirectional = (typeof bidirectional == 'undefined') ? true : bidirectional; 42 | term.socket = socket; 43 | 44 | term._flushBuffer = function () { 45 | term.write(term._attachSocketBuffer); 46 | term._attachSocketBuffer = null; 47 | clearTimeout(term._attachSocketBufferTimer); 48 | term._attachSocketBufferTimer = null; 49 | }; 50 | 51 | term._pushToBuffer = function (data) { 52 | if (term._attachSocketBuffer) { 53 | term._attachSocketBuffer += data; 54 | } else { 55 | term._attachSocketBuffer = data; 56 | setTimeout(term._flushBuffer, 10); 57 | } 58 | }; 59 | 60 | term._getMessage = function (ev) { 61 | if (buffered) { 62 | term._pushToBuffer(ev.data); 63 | } else { 64 | term.write(ev.data); 65 | } 66 | }; 67 | 68 | term._sendData = function (data) { 69 | socket.send(data); 70 | }; 71 | 72 | socket.addEventListener('message', term._getMessage); 73 | 74 | if (bidirectional) { 75 | term.on('data', term._sendData); 76 | } 77 | 78 | socket.addEventListener('close', term.detach.bind(term, socket)); 79 | socket.addEventListener('error', term.detach.bind(term, socket)); 80 | }; 81 | 82 | /** 83 | * Detaches the given terminal from the given socket 84 | * 85 | * @param {Xterm} term - The terminal to be detached from the given socket. 86 | * @param {WebSocket} socket - The socket from which to detach the current 87 | * terminal. 88 | */ 89 | exports.detach = function (term, socket) { 90 | term.off('data', term._sendData); 91 | 92 | socket = (typeof socket == 'undefined') ? term.socket : socket; 93 | 94 | if (socket) { 95 | socket.removeEventListener('message', term._getMessage); 96 | } 97 | 98 | delete term.socket; 99 | }; 100 | 101 | /** 102 | * Attaches the current terminal to the given socket 103 | * 104 | * @param {WebSocket} socket - The socket to attach the current terminal. 105 | * @param {boolean} bidirectional - Whether the terminal should send data 106 | * to the socket as well. 107 | * @param {boolean} buffered - Whether the rendering of incoming data 108 | * should happen instantly or at a maximum 109 | * frequency of 1 rendering per 10ms. 110 | */ 111 | Xterm.prototype.attach = function (socket, bidirectional, buffered) { 112 | return exports.attach(this, socket, bidirectional, buffered); 113 | }; 114 | 115 | /** 116 | * Detaches the current terminal from the given socket. 117 | * 118 | * @param {WebSocket} socket - The socket from which to detach the current 119 | * terminal. 120 | */ 121 | Xterm.prototype.detach = function (socket) { 122 | return exports.detach(this, socket); 123 | }; 124 | 125 | return exports; 126 | }); 127 | -------------------------------------------------------------------------------- /static/addons/terminado/terminado.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This module provides methods for attaching a terminal to a terminado WebSocket stream. 3 | * 4 | * @module xterm/addons/terminado/terminado 5 | * @license MIT 6 | */ 7 | 8 | (function (attach) { 9 | if (typeof exports === 'object' && typeof module === 'object') { 10 | /* 11 | * CommonJS environment 12 | */ 13 | module.exports = attach(require('../../xterm')); 14 | } else if (typeof define == 'function') { 15 | /* 16 | * Require.js is available 17 | */ 18 | define(['../../xterm'], attach); 19 | } else { 20 | /* 21 | * Plain browser environment 22 | */ 23 | attach(window.Terminal); 24 | } 25 | })(function (Xterm) { 26 | 'use strict'; 27 | 28 | var exports = {}; 29 | 30 | /** 31 | * Attaches the given terminal to the given socket. 32 | * 33 | * @param {Xterm} term - The terminal to be attached to the given socket. 34 | * @param {WebSocket} socket - The socket to attach the current terminal. 35 | * @param {boolean} bidirectional - Whether the terminal should send data 36 | * to the socket as well. 37 | * @param {boolean} buffered - Whether the rendering of incoming data 38 | * should happen instantly or at a maximum 39 | * frequency of 1 rendering per 10ms. 40 | */ 41 | exports.terminadoAttach = function (term, socket, bidirectional, buffered) { 42 | bidirectional = (typeof bidirectional == 'undefined') ? true : bidirectional; 43 | term.socket = socket; 44 | 45 | term._flushBuffer = function () { 46 | term.write(term._attachSocketBuffer); 47 | term._attachSocketBuffer = null; 48 | clearTimeout(term._attachSocketBufferTimer); 49 | term._attachSocketBufferTimer = null; 50 | }; 51 | 52 | term._pushToBuffer = function (data) { 53 | if (term._attachSocketBuffer) { 54 | term._attachSocketBuffer += data; 55 | } else { 56 | term._attachSocketBuffer = data; 57 | setTimeout(term._flushBuffer, 10); 58 | } 59 | }; 60 | 61 | term._getMessage = function (ev) { 62 | var data = JSON.parse(ev.data) 63 | if( data[0] == "stdout" ) { 64 | if (buffered) { 65 | term._pushToBuffer(data[1]); 66 | } else { 67 | term.write(data[1]); 68 | } 69 | } 70 | }; 71 | 72 | term._sendData = function (data) { 73 | socket.send(JSON.stringify(['stdin', data])); 74 | }; 75 | 76 | term._setSize = function (size) { 77 | socket.send(JSON.stringify(['set_size', size.rows, size.cols])); 78 | }; 79 | 80 | socket.addEventListener('message', term._getMessage); 81 | 82 | if (bidirectional) { 83 | term.on('data', term._sendData); 84 | } 85 | term.on('resize', term._setSize); 86 | 87 | socket.addEventListener('close', term.terminadoDetach.bind(term, socket)); 88 | socket.addEventListener('error', term.terminadoDetach.bind(term, socket)); 89 | }; 90 | 91 | /** 92 | * Detaches the given terminal from the given socket 93 | * 94 | * @param {Xterm} term - The terminal to be detached from the given socket. 95 | * @param {WebSocket} socket - The socket from which to detach the current 96 | * terminal. 97 | */ 98 | exports.terminadoDetach = function (term, socket) { 99 | term.off('data', term._sendData); 100 | 101 | socket = (typeof socket == 'undefined') ? term.socket : socket; 102 | 103 | if (socket) { 104 | socket.removeEventListener('message', term._getMessage); 105 | } 106 | 107 | delete term.socket; 108 | }; 109 | 110 | /** 111 | * Attaches the current terminal to the given socket 112 | * 113 | * @param {WebSocket} socket - The socket to attach the current terminal. 114 | * @param {boolean} bidirectional - Whether the terminal should send data 115 | * to the socket as well. 116 | * @param {boolean} buffered - Whether the rendering of incoming data 117 | * should happen instantly or at a maximum 118 | * frequency of 1 rendering per 10ms. 119 | */ 120 | Xterm.prototype.terminadoAttach = function (socket, bidirectional, buffered) { 121 | return exports.terminadoAttach(this, socket, bidirectional, buffered); 122 | }; 123 | 124 | /** 125 | * Detaches the current terminal from the given socket. 126 | * 127 | * @param {WebSocket} socket - The socket from which to detach the current 128 | * terminal. 129 | */ 130 | Xterm.prototype.terminadoDetach = function (socket) { 131 | return exports.terminadoDetach(this, socket); 132 | }; 133 | 134 | return exports; 135 | }); 136 | -------------------------------------------------------------------------------- /src/components/page_u/createNetwork.vue: -------------------------------------------------------------------------------- 1 | 43 | 44 | 125 | 126 | 129 | -------------------------------------------------------------------------------- /src/components/common/Tags.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 91 | 92 | 93 | 164 | -------------------------------------------------------------------------------- /src/components/common_u/Tags_u.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 91 | 92 | 93 | 166 | -------------------------------------------------------------------------------- /src/components/page/ProjectsDetails.vue: -------------------------------------------------------------------------------- 1 | 62 | 63 | 126 | 127 | 130 | -------------------------------------------------------------------------------- /src/components/page_u/help.vue: -------------------------------------------------------------------------------- 1 | 74 | 75 | 121 | 122 | 124 | -------------------------------------------------------------------------------- /src/components/common/Sidebar.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 134 | 135 | 154 | -------------------------------------------------------------------------------- /src/components/page/ServiceManage.vue: -------------------------------------------------------------------------------- 1 | 61 | 62 | 147 | 148 | 151 | -------------------------------------------------------------------------------- /src/components/page/PublicLocalImage.vue: -------------------------------------------------------------------------------- 1 | 55 | 56 | 141 | 142 | 196 | -------------------------------------------------------------------------------- /src/components/common_u/Header_u.vue: -------------------------------------------------------------------------------- 1 | 40 | 129 | 204 | -------------------------------------------------------------------------------- /src/components/common/Header.vue: -------------------------------------------------------------------------------- 1 | 40 | 131 | 206 | -------------------------------------------------------------------------------- /src/components/page/NoticeManage.vue: -------------------------------------------------------------------------------- 1 | 69 | 70 | 170 | 171 | 191 | -------------------------------------------------------------------------------- /src/components/page/ProjectManage.vue: -------------------------------------------------------------------------------- 1 | 55 | 56 | 173 | 174 | 188 | -------------------------------------------------------------------------------- /src/components/page/UserLocalImage.vue: -------------------------------------------------------------------------------- 1 | 60 | 61 | 154 | 155 | 219 | -------------------------------------------------------------------------------- /static/addons/linkify/linkify.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Methods for turning URL subscrings in the terminal's content into links (`a` DOM elements). 3 | * @module xterm/addons/linkify/linkify 4 | * @license MIT 5 | */ 6 | 7 | (function (linkify) { 8 | if (typeof exports === 'object' && typeof module === 'object') { 9 | /* 10 | * CommonJS environment 11 | */ 12 | module.exports = linkify(require('../../xterm')); 13 | } else if (typeof define == 'function') { 14 | /* 15 | * Require.js is available 16 | */ 17 | define(['../../xterm'], linkify); 18 | } else { 19 | /* 20 | * Plain browser environment 21 | */ 22 | linkify(window.Terminal); 23 | } 24 | })(function (Xterm) { 25 | 'use strict'; 26 | 27 | var exports = {}, 28 | protocolClause = '(https?:\\/\\/)', 29 | domainCharacterSet = '[\\da-z\\.-]+', 30 | negatedDomainCharacterSet = '[^\\da-z\\.-]+', 31 | domainBodyClause = '(' + domainCharacterSet + ')', 32 | tldClause = '([a-z\\.]{2,6})', 33 | ipClause = '((\\d{1,3}\\.){3}\\d{1,3})', 34 | portClause = '(:\\d{1,5})', 35 | hostClause = '((' + domainBodyClause + '\\.' + tldClause + ')|' + ipClause + ')' + portClause + '?', 36 | pathClause = '(\\/[\\/\\w\\.-]*)*', 37 | negatedPathCharacterSet = '[^\\/\\w\\.-]+', 38 | bodyClause = hostClause + pathClause, 39 | start = '(?:^|' + negatedDomainCharacterSet + ')(', 40 | end = ')($|' + negatedPathCharacterSet + ')', 41 | lenientUrlClause = start + protocolClause + '?' + bodyClause + end, 42 | strictUrlClause = start + protocolClause + bodyClause + end, 43 | lenientUrlRegex = new RegExp(lenientUrlClause), 44 | strictUrlRegex = new RegExp(strictUrlClause); 45 | 46 | /** 47 | * Converts all valid URLs found in the given terminal line into 48 | * hyperlinks. The terminal line can be either the HTML element itself 49 | * or the index of the termina line in the children of the terminal 50 | * rows container. 51 | * 52 | * @param {Xterm} terminal - The terminal that owns the given line. 53 | * @param {number|HTMLDivElement} line - The terminal line that should get 54 | * "linkified". 55 | * @param {boolean} lenient - The regex type that will be used to identify links. If lenient is 56 | * false, the regex requires a protocol clause. Defaults to true. 57 | * @param {string} target - Sets target="" attribute with value provided to links. 58 | * Default doesn't set target attribute 59 | * @emits linkify 60 | * @emits linkify:line 61 | */ 62 | exports.linkifyTerminalLine = function (terminal, line, lenient, target) { 63 | if (typeof line == 'number') { 64 | line = terminal.rowContainer.children[line]; 65 | } else if (! (line instanceof HTMLDivElement)) { 66 | var message = 'The "line" argument should be either a number'; 67 | message += ' or an HTMLDivElement'; 68 | 69 | throw new TypeError(message); 70 | } 71 | 72 | if (typeof target === 'undefined') { 73 | target = ''; 74 | } else { 75 | target = 'target="' + target + '"'; 76 | } 77 | 78 | var buffer = document.createElement('span'), 79 | nodes = line.childNodes; 80 | 81 | for (var j=0; j' + url + '', 112 | newHTML = nodeHTML.replace(url, link); 113 | 114 | line.innerHTML = line.innerHTML.replace(nodeHTML, newHTML); 115 | } 116 | 117 | /** 118 | * This event gets emitted when conversion of all URL susbtrings 119 | * to HTML anchor elements (links) has finished, for a specific 120 | * line of the current Xterm instance. 121 | * 122 | * @event linkify:line 123 | */ 124 | terminal.emit('linkify:line', line); 125 | }; 126 | 127 | /** 128 | * Finds a link within a block of text. 129 | * 130 | * @param {string} text - The text to search . 131 | * @param {boolean} lenient - Whether to use the lenient search. 132 | * @return {string} A URL. 133 | */ 134 | exports.findLinkMatch = function (text, lenient) { 135 | var match = text.match(lenient ? lenientUrlRegex : strictUrlRegex); 136 | if (!match || match.length === 0) { 137 | return null; 138 | } 139 | return match[1]; 140 | } 141 | 142 | /** 143 | * Converts all valid URLs found in the terminal view into hyperlinks. 144 | * 145 | * @param {Xterm} terminal - The terminal that should get "linkified". 146 | * @param {boolean} lenient - The regex type that will be used to identify links. If lenient is 147 | * false, the regex requires a protocol clause. Defaults to true. 148 | * @param {string} target - Sets target="" attribute with value provided to links. 149 | * Default doesn't set target attribute 150 | * @emits linkify 151 | * @emits linkify:line 152 | */ 153 | exports.linkify = function (terminal, lenient, target) { 154 | var rows = terminal.rowContainer.children; 155 | 156 | lenient = (typeof lenient == "boolean") ? lenient : true; 157 | for (var i=0; i 2 |
3 | 4 | 5 | 6 | 7 | 18 | 19 | 20 | 21 | 41 |
42 | 43 | 44 | 178 | 179 | 218 | -------------------------------------------------------------------------------- /src/components/page_u/serviceDetails.vue: -------------------------------------------------------------------------------- 1 | 85 | 86 | 196 | 197 | 223 | -------------------------------------------------------------------------------- /src/components/page/VolumesManage.vue: -------------------------------------------------------------------------------- 1 | 69 | 70 | 210 | 211 | 230 | -------------------------------------------------------------------------------- /src/components/page/ServiceDetails.vue: -------------------------------------------------------------------------------- 1 | 91 | 92 | 233 | 234 | 236 | -------------------------------------------------------------------------------- /src/components/page/SystemLog.vue: -------------------------------------------------------------------------------- 1 | 85 | 86 | 216 | 217 | 244 | --------------------------------------------------------------------------------