├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .postcssrc.js ├── .travis.yml ├── Dockerfile ├── LICENSE ├── README.md ├── cypress.json ├── docker-compose.yml ├── nginx_ops.conf ├── package-lock.json ├── package.json ├── public ├── favicon.ico └── index.html ├── src ├── App.vue ├── api │ ├── app.js │ ├── cmdb │ │ ├── adm_user.js │ │ ├── db.js │ │ ├── server.js │ │ ├── server_auth.js │ │ ├── server_group.js │ │ ├── server_log.js │ │ └── tag.js │ ├── cmdb2 │ │ ├── admin_user.js │ │ ├── asset_config.js │ │ ├── audit.js │ │ ├── db.js │ │ ├── idc.js │ │ ├── server.js │ │ ├── system_user.js │ │ └── tag.js │ ├── confd │ │ ├── conf.js │ │ └── project.js │ ├── cron.js │ ├── dashboard │ │ └── home.js │ ├── data.js │ ├── devops-tools.js │ ├── domain │ │ ├── dns.js │ │ └── domain.js │ ├── git-repo.js │ ├── k8s │ │ ├── app.js │ │ ├── project.js │ │ ├── publish.js │ │ └── task.js │ ├── mg │ │ └── resource-mg.js │ ├── routers.js │ ├── scheduler │ │ └── scheduler-task.js │ ├── task-other.js │ ├── task.js │ └── user.js ├── assets │ ├── icons │ │ ├── iconfont.css │ │ ├── iconfont.eot │ │ ├── iconfont.svg │ │ ├── iconfont.ttf │ │ └── iconfont.woff │ └── images │ │ ├── error-page │ │ ├── error-403.svg │ │ ├── error-404.svg │ │ └── error-500.svg │ │ ├── login-bg.jpg │ │ ├── login-bg1.jpg │ │ ├── logo-min.jpg │ │ ├── logo.png │ │ ├── qq-fance.png │ │ ├── qq-fance2.jpg │ │ └── talkingdata.png ├── components │ ├── charts │ │ ├── bar.vue │ │ ├── index.js │ │ ├── pie.vue │ │ └── theme.json │ ├── common-icon │ │ ├── common-icon.vue │ │ └── index.js │ ├── common │ │ ├── common.less │ │ └── util.js │ ├── count-to │ │ ├── count-to.vue │ │ ├── index.js │ │ └── index.less │ ├── drag-list │ │ ├── drag-list.vue │ │ └── index.js │ ├── editor │ │ ├── editor.vue │ │ └── index.js │ ├── form-group │ │ ├── form-group.vue │ │ └── index.js │ ├── icons │ │ ├── icons.vue │ │ └── index.js │ ├── info-card │ │ ├── index.js │ │ └── infor-card.vue │ ├── login-form │ │ ├── index.js │ │ ├── login-form.vue │ │ ├── mfa.vue │ │ └── register.vue │ ├── main │ │ ├── components │ │ │ ├── error-store │ │ │ │ ├── error-store.vue │ │ │ │ └── index.js │ │ │ ├── footer │ │ │ │ └── copyright.vue │ │ │ ├── fullscreen │ │ │ │ ├── fullscreen.vue │ │ │ │ └── index.js │ │ │ ├── header-bar │ │ │ │ ├── custom-bread-crumb │ │ │ │ │ ├── custom-bread-crumb.less │ │ │ │ │ ├── custom-bread-crumb.vue │ │ │ │ │ └── index.js │ │ │ │ ├── header-bar.less │ │ │ │ ├── header-bar.vue │ │ │ │ ├── index.js │ │ │ │ └── sider-trigger │ │ │ │ │ ├── index.js │ │ │ │ │ ├── sider-trigger.less │ │ │ │ │ └── sider-trigger.vue │ │ │ ├── language │ │ │ │ ├── index.js │ │ │ │ └── language.vue │ │ │ ├── side-menu │ │ │ │ ├── collapsed-menu.vue │ │ │ │ ├── index.js │ │ │ │ ├── item-mixin.js │ │ │ │ ├── mixin.js │ │ │ │ ├── side-menu-item.vue │ │ │ │ ├── side-menu.less │ │ │ │ └── side-menu.vue │ │ │ ├── tags-nav │ │ │ │ ├── index.js │ │ │ │ ├── tags-nav.less │ │ │ │ └── tags-nav.vue │ │ │ └── user │ │ │ │ ├── index.js │ │ │ │ ├── user.less │ │ │ │ └── user.vue │ │ ├── index.js │ │ ├── main.less │ │ └── main.vue │ ├── markdown │ │ ├── index.js │ │ └── markdown.vue │ ├── parent-view │ │ ├── index.js │ │ └── parent-view.vue │ ├── paste-editor │ │ ├── index.js │ │ ├── paste-editor.less │ │ ├── paste-editor.vue │ │ └── plugins │ │ │ └── placeholder.js │ ├── public │ │ ├── copyright.vue │ │ └── editor.vue │ ├── split-pane │ │ ├── index.css │ │ ├── index.js │ │ ├── index.less │ │ ├── split.vue │ │ └── trigger.vue │ └── tables │ │ ├── edit.vue │ │ ├── handle-btns.js │ │ ├── index.js │ │ ├── index.less │ │ └── tables.vue ├── config │ └── index.js ├── directive │ ├── directives.js │ └── index.js ├── index.less ├── libs │ ├── api.request.js │ ├── axios.js │ ├── excel.js │ ├── tools.js │ └── util.js ├── locale │ ├── index.js │ └── lang │ │ ├── en-US.js │ │ ├── zh-CN.js │ │ └── zh-TW.js ├── main.js ├── plugin │ ├── error-store │ │ └── index.js │ └── index.js ├── router │ ├── before-close.js │ ├── index.js │ └── routers.js ├── store │ ├── index.js │ └── module │ │ ├── app.js │ │ ├── router.js │ │ └── user.js └── view │ ├── cmdb │ ├── adm_user │ │ ├── Add.vue │ │ └── List.vue │ ├── common │ │ └── Api.vue │ ├── db │ │ ├── Add.vue │ │ ├── Detail.vue │ │ ├── List.vue │ │ └── multiAdd.vue │ ├── server │ │ ├── Add.vue │ │ ├── Detail.vue │ │ ├── List.vue │ │ └── multiAdd.vue │ ├── server_auth │ │ ├── Add.vue │ │ ├── Detail.vue │ │ └── List.vue │ ├── server_group │ │ ├── Add.vue │ │ └── List.vue │ ├── server_log │ │ ├── List.vue │ │ └── TtyLog.vue │ ├── tag │ │ ├── Add.vue │ │ └── List.vue │ └── webssh │ │ ├── Console.vue │ │ ├── Record.vue │ │ ├── WebSSH.vue │ │ └── Xterm.js │ ├── cmdb2 │ ├── admin_user.vue │ ├── asset_config.vue │ ├── asset_idc.vue │ ├── aws_events.vue │ ├── db_detail.vue │ ├── db_mg.vue │ ├── log_audit.vue │ ├── multi_add_db.vue │ ├── multi_add_server.vue │ ├── operational_audit.vue │ ├── server_detail.vue │ ├── server_mg.vue │ ├── system_user.vue │ ├── tag_mg.vue │ ├── web_ssh.vue │ └── webssh │ │ ├── Console.vue │ │ ├── Record.vue │ │ ├── WebSSH.vue │ │ ├── Xterm.js │ │ └── web-ssh.vue │ ├── components │ ├── count-to │ │ └── count-to.vue │ ├── drag-list │ │ └── drag-list.vue │ ├── editor │ │ └── editor.vue │ ├── icons │ │ └── icons.vue │ ├── markdown │ │ └── markdown.vue │ ├── split-pane │ │ └── split-pane.vue │ └── tables │ │ └── tables.vue │ ├── confd │ ├── config │ │ ├── Add.vue │ │ └── List.vue │ └── project │ │ ├── Add.vue │ │ └── List2.vue │ ├── cron │ ├── cron-jobs.vue │ └── cron-logs.vue │ ├── devops-tools │ ├── event-manager.vue │ ├── fault-manager.vue │ ├── paid-reminder.vue │ ├── password-mycrypy.vue │ ├── project-manager.vue │ ├── prometheus-alert.vue │ ├── remind-manager.vue │ └── zabbix-mg.vue │ ├── directive │ └── directive.vue │ ├── domain-name │ ├── checkDomain.js │ ├── cloud-account-mg.vue │ ├── cloud-domain-manage.vue │ ├── components │ │ ├── domain-detail.vue │ │ └── domain-edit.vue │ ├── domain-name-manage.vue │ ├── domain-name-monitor.vue │ └── domain-records.vue │ ├── error-page │ ├── 403.vue │ ├── 404.vue │ ├── 500.vue │ ├── back-btn-group.vue │ ├── error-content.vue │ └── error.less │ ├── error-store │ └── error-store.vue │ ├── excel │ ├── common.less │ ├── export-excel.vue │ └── upload-excel.vue │ ├── i18n │ └── i18n-page.vue │ ├── join-page.vue │ ├── k8s │ ├── app │ │ ├── Add.vue │ │ ├── List.vue │ │ └── ListDetail.vue │ ├── project │ │ ├── Add.vue │ │ ├── List.vue │ │ ├── ListDetail.vue │ │ └── Publish.vue │ └── publish │ │ ├── Detail.vue │ │ ├── List.vue │ │ └── components │ │ ├── Console.vue │ │ ├── baseInfo.vue │ │ ├── handle.vue │ │ └── handleResult.vue │ ├── login │ ├── login.less │ └── login.vue │ ├── multilevel │ ├── level-2-1.vue │ ├── level-2-2 │ │ └── level-3-1.vue │ └── level-2-3.vue │ ├── publish-store │ ├── components │ │ └── task-list.vue │ ├── project-conf.vue │ ├── project-create.vue │ ├── publish-list.vue │ └── publish │ │ ├── Detail.vue │ │ ├── List.vue │ │ ├── components │ │ ├── Console.vue │ │ ├── QAInfo.vue │ │ ├── baseInfo.vue │ │ ├── handle.vue │ │ ├── handleResult.vue │ │ ├── repoInfo.vue │ │ └── task-list.vue-bak │ │ └── detail-bak.vue │ ├── scheduler │ ├── args-list.vue │ ├── command-list.vue │ ├── task-template.vue │ └── task-user.vue │ ├── single-page │ ├── error-logger.vue │ └── home │ │ ├── example.vue │ │ ├── home.vue │ │ ├── index.js │ │ ├── issuesinfo.vue │ │ ├── logininfo.vue │ │ └── taskinfo.vue │ ├── system-manage │ ├── resource-management.vue │ ├── system.vue │ └── systemlog.vue │ ├── task-order │ ├── components │ │ └── task-list.vue │ ├── history-task-list.vue │ └── task-order-list.vue │ ├── tasks-center │ ├── assets │ │ ├── auto-rule.vue │ │ ├── project-mg.vue │ │ ├── proxy-info.vue │ │ ├── resource-mg.vue │ │ ├── tag-model.vue │ │ └── tree-model.vue │ ├── code-repository.vue-bak │ ├── docker-registry.vue │ ├── git-repo │ │ └── code-repository.vue │ ├── publish-config.vue │ └── task-submit │ │ ├── asset-purchase-aly.vue │ │ ├── asset-purchase-aws.vue │ │ ├── asset-purchase-conf.vue │ │ ├── asset-purchase-qcloud.vue │ │ ├── asset-purchase.vue │ │ ├── common-jobs.vue │ │ ├── create_task.vue │ │ ├── k8s-node-add.vue │ │ ├── mysql-audit.vue │ │ ├── mysql-optimize.vue │ │ ├── publish-app.vue │ │ ├── task-custom-proxy.vue │ │ ├── task-custom.vue │ │ └── task-post.vue │ ├── tools-methods │ └── tools-methods.vue │ ├── update │ ├── update-paste.vue │ └── update-table.vue │ └── user-manage │ ├── components │ └── func-edit.vue │ ├── functions.vue │ ├── role.vue │ ├── routescomponents.vue │ └── user.vue ├── swagger-ui ├── favicon-16x16.png ├── favicon-32x32.png ├── index.html ├── oauth2-redirect.html ├── swagger-ui-bundle.js ├── swagger-ui-bundle.js.map ├── swagger-ui-standalone-preset.js ├── swagger-ui-standalone-preset.js.map ├── swagger-ui.css ├── swagger-ui.css.map ├── swagger-ui.js ├── swagger-ui.js.map └── swagger.json ├── tests ├── e2e │ ├── .eslintrc │ ├── plugins │ │ └── index.js │ ├── specs │ │ └── test.js │ └── support │ │ ├── commands.js │ │ └── index.js └── unit │ ├── .eslintrc.js │ └── HelloWorld.spec.js └── vue.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@vue/app" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opendevops-cn/codo/b57acb97c17a36d94d26a9214bbc6c051ce081a4/.eslintignore -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | 'extends': [ 4 | 'plugin:vue/essential', 5 | '@vue/standard' 6 | ], 7 | rules: { 8 | // allow async-await 9 | 'generator-star-spacing': 'off', 10 | // allow debugger during development 11 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', 12 | 'vue/no-parsing-error': [2, { 'x-invalid-end-tag': false }], 13 | 'no-undef': 'off' 14 | }, 15 | parserOptions: { 16 | parser: 'babel-eslint' 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | /tests/e2e/videos/ 6 | /tests/e2e/screenshots/ 7 | 8 | # local env files 9 | .env.local 10 | .env.*.local 11 | 12 | # Log files 13 | npm-debug.log* 14 | yarn-debug.log* 15 | yarn-error.log* 16 | 17 | # Editor directories and files 18 | .idea 19 | .vscode 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw* 25 | 26 | build/env.js 27 | -------------------------------------------------------------------------------- /.postcssrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | autoprefixer: {} 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: stable 3 | script: npm run lint 4 | notifications: 5 | email: false 6 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM centos:7 as build-stage 2 | # 设置编码 3 | ENV LANG en_US.UTF-8 4 | # 同步时间 5 | ENV TZ=Asia/Shanghai 6 | RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone 7 | 8 | # 1. 安装基本依赖和nginx 9 | RUN yum update -y && yum install epel-release -y && yum update -y && yum install wget nginx git -y 10 | WORKDIR /app 11 | 12 | # 2. 准备node 13 | #RUN wget -q -c https://npm.taobao.org/mirrors/node/v10.16.1/node-v10.16.1-linux-x64.tar.xz && tar xf node-v10.16.1-linux-x64.tar.xz -C /usr/local/ 14 | RUN wget -q -c https://nodejs.org/dist/v10.16.1/node-v10.16.1-linux-x64.tar.xz && tar xf node-v10.16.1-linux-x64.tar.xz -C /usr/local/ 15 | 16 | RUN rm -rf /usr/local/bin/node && rm -rf /usr/local/bin/npm \ 17 | && ln -s /usr/local/node-v10.16.1-linux-x64/bin/node /usr/local/bin/node \ 18 | && ln -s /usr/local/node-v10.16.1-linux-x64/bin/node /usr/bin/node \ 19 | && ln -s /usr/local/node-v10.16.1-linux-x64/bin/npm /usr/local/bin/npm \ 20 | && ln -s /usr/local/node-v10.16.1-linux-x64/bin/npm /usr/bin/npm 21 | 22 | # 4. 复制代码 23 | RUN mkdir -p /app 24 | ADD . /app 25 | 26 | RUN rm -rf /app/node_modules && npm config set registry https://registry.npmjs.org/ \ 27 | && npm cache clean --force \ 28 | && npm install --ignore-script \ 29 | && npm run build 30 | 31 | 32 | ############################ 33 | 34 | FROM nginx as production 35 | 36 | MAINTAINER "shenshuo<191715030@qq.com>" 37 | 38 | RUN mkdir -p /var/www/codo 39 | 40 | WORKDIR /var/www/codo/ 41 | 42 | COPY nginx_ops.conf /etc/nginx/conf.d/codo_frontend.conf 43 | COPY --from=build-stage /app/dist /var/www/codo 44 | 45 | EXPOSE 80 46 | EXPOSE 443 47 | 48 | STOPSIGNAL SIGTERM 49 | 50 | CMD ["nginx", "-g", "daemon off;"] 51 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 iView 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Install 2 | 3 | ```bash 4 | // install dependencies 5 | npm install --ignore-script 6 | ``` 7 | 8 | ### Run 9 | 10 | #### Development 11 | 12 | ```bash 13 | npm run dev 14 | ``` 15 | 16 | #### Production(Build) 17 | 18 | ```bash 19 | npm run build 20 | ``` 21 | 22 | ### Docker 方式部署 23 | 24 | **修改`CODO_VER`release为最新的版本,静态文件的最终路径为 `/var/www/codo/`** 25 | 26 | ```bash 27 | echo -e "\033[32m [INFO]: codo(项目前端) Start install. \033[0m" 28 | CODO_VER="codo-beta-0.3.4" 29 | if ! which wget &>/dev/null; then yum install -y wget >/dev/null 2>&1;fi 30 | [ ! -d /var/www ] && mkdir -p /var/www 31 | cd /var/www && wget https://github.com/opendevops-cn/codo/releases/download/${CODO_VER}/${CODO_VER}.tar.gz 32 | tar zxf ${CODO_VER}.tar.gz 33 | if [ $? == 0 ];then 34 | echo -e "\033[32m [INFO]: codo(项目前端) install success. \033[0m" 35 | else 36 | echo -e "\033[31m [ERROR]: codo(项目前端) install faild \033[0m" 37 | exit -8 38 | fi 39 | ``` 40 | 41 | **放置`nginx`配置文件,如果想使用https请自行修改nginx的配置文件,也可以参考项目下的`nginx_ops.conf`文件。** 42 | 43 | **如果需要修改前端的访问域名可以直接修改配置文件中的server_name,proxy_pass对应的地址为网关地址,一定要和网关地址端口进行对应。** 44 | 45 | ```bash 46 | mkdir -p /my/nginx/conf.d/ 47 | cat >/my/nginx/conf.d/codo-init.conf<<\EOF 48 | server { 49 | listen 80; 50 | server_name demo-init.opendevops.cn; 51 | access_log /var/log/nginx/codo-access.log; 52 | error_log /var/log/nginx/codo-error.log; 53 | 54 | location / { 55 | root /var/www/codo; 56 | index index.html index.htm; 57 | try_files $uri $uri/ /index.html; 58 | } 59 | location /api { 60 | ### ws 支持 61 | proxy_http_version 1.1; 62 | proxy_set_header Upgrade $http_upgrade; 63 | proxy_set_header Connection "upgrade"; 64 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 65 | 66 | add_header 'Access-Control-Allow-Origin' '*'; 67 | proxy_pass http://gw.opendevops.cn:8888; 68 | } 69 | 70 | location ~ /(.svn|.git|admin|manage|.sh|.bash)$ { 71 | return 403; 72 | } 73 | } 74 | EOF 75 | ``` 76 | 77 | ```bash 78 | #bulid 镜像 79 | docker build . -t codo_image 80 | #启动 81 | docker-compose up -d 82 | ``` 83 | 84 | - 测试一下 `ls /var/www/codo/index.html` 看下前端文件是不是存在 85 | - 测试一下 `ls /my/nginx/conf.d/codo-init.conf` 看下nginx配置文件是不是存在 86 | - swagger-ui 复制到/var/www/codo/目录即可,详情请参考安装文档。 命令如下:cd /opt/codo/codo && \cp -r swagger-ui/ /var/www/codo/ 87 | 88 | ## License 89 | 90 | [MIT](http://opensource.org/licenses/MIT) 91 | 92 | Copyright (c) 2016-present, iView 93 | -------------------------------------------------------------------------------- /cypress.json: -------------------------------------------------------------------------------- 1 | { 2 | "pluginsFile": "tests/e2e/plugins/index.js" 3 | } 4 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | codo: 2 | restart: unless-stopped 3 | image: codo_image 4 | volumes: 5 | - /var/log/nginx/:/var/log/nginx/ 6 | - /var/www/codo/:/var/www/codo/ 7 | - /my/nginx/conf.d/:/etc/nginx/conf.d/ 8 | - /sys/fs/cgroup:/sys/fs/cgroup 9 | ports: 10 | - "80:80" 11 | - "443:443" -------------------------------------------------------------------------------- /nginx_ops.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name demo-init.opendevops.cn; 4 | access_log /var/log/nginx/codo-access.log; 5 | error_log /var/log/nginx/codo-error.log; 6 | 7 | location / { 8 | root /var/www/codo; 9 | index index.html index.htm; 10 | try_files $uri $uri/ /index.html; 11 | } 12 | location /api { 13 | ### ws 支持 14 | proxy_http_version 1.1; 15 | proxy_set_header Upgrade $http_upgrade; 16 | proxy_set_header Connection "upgrade"; 17 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 18 | 19 | add_header 'Access-Control-Allow-Origin' '*'; 20 | proxy_pass http://gw.opendevops.cn:8888; 21 | } 22 | 23 | location ~ /(.svn|.git|admin|manage|.sh|.bash)$ { 24 | return 403; 25 | } 26 | } 27 | 28 | ### 下面是使用https,要注意放置证书 29 | # server { 30 | # listen 80; 31 | # server_name demo-init.opendevops.cn; 32 | # rewrite ^(.*)$ https://$host$1 permanent; 33 | # } 34 | 35 | # server { 36 | # listen 443; 37 | # server_name demo-init.opendevops.cn; 38 | # access_log /var/log/nginx/codo-access.log; 39 | # error_log /var/log/nginx/codo-error.log; 40 | # ssl on; 41 | # index index.html index.htm; 42 | # ssl_certificate opendevops.crt; 43 | # ssl_certificate_key opendevops.key; 44 | # ssl_session_timeout 5m; 45 | # ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:ECDHE-RSA-AES128-SHA256:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!DSS:!PKS; 46 | # ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 47 | # ssl_prefer_server_ciphers on; 48 | 49 | # location / { 50 | # root /var/www/codo; 51 | # index index.html index.htm; 52 | # try_files $uri $uri/ /index.html; 53 | # } 54 | 55 | # location /api { 56 | # proxy_redirect off; 57 | # proxy_read_timeout 600; 58 | # proxy_http_version 1.1; 59 | # proxy_set_header Upgrade $http_upgrade; 60 | # proxy_set_header Connection "upgrade"; 61 | # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 62 | 63 | # add_header 'Access-Control-Allow-Origin' '*'; 64 | # proxy_pass http://gw.opendevops.cn:8888; 65 | # } 66 | 67 | # location ~ /(.svn|.git|admin|manage|.sh|.bash)$ { 68 | # return 403; 69 | # } 70 | # } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "codo", 3 | "version": "1.0.0", 4 | "author": "ss<191715030@qq.com>", 5 | "private": false, 6 | "scripts": { 7 | "dev": "vue-cli-service serve --open", 8 | "build": "vue-cli-service build", 9 | "lint": "vue-cli-service lint", 10 | "test:unit": "vue-cli-service test:unit", 11 | "test:e2e": "vue-cli-service test:e2e" 12 | }, 13 | "dependencies": { 14 | "@riophae/vue-treeselect": "0.0.38", 15 | "axios": "^0.18.1", 16 | "babel-core": "^6.26.3", 17 | "babel-loader": "^8.0.5", 18 | "clipboard": "^2.0.0", 19 | "clonedeep": "^2.0.0", 20 | "codemirror": "^5.38.0", 21 | "countup": "^1.8.2", 22 | "cropperjs": "^1.2.2", 23 | "dayjs": "^1.7.7", 24 | "echarts": "^4.0.4", 25 | "html2canvas": "^1.0.0-alpha.12", 26 | "iview-area": "^1.5.17", 27 | "js-cookie": "^2.2.0", 28 | "jwt-decode": "^2.2.0", 29 | "qrcode": "^1.3.0", 30 | "qrcodejs2": "0.0.2", 31 | "simplemde": "^1.11.2", 32 | "sortablejs": "^1.7.0", 33 | "view-design": "^4.1.3", 34 | "vue": "^2.5.10", 35 | "vue-clipboard2": "^0.2.1", 36 | "vue-i18n": "^7.8.0", 37 | "vue-qart": "^2.2.0", 38 | "vue-router": "^3.0.1", 39 | "vue-websocket": "^0.2.3", 40 | "vue2-ace-editor": "0.0.13", 41 | "vuedraggable": "^2.16.0", 42 | "vuex": "^3.0.1", 43 | "vuex-persistedstate": "^2.5.4", 44 | "wangeditor": "^3.1.1", 45 | "xlsx": "^0.13.3", 46 | "xterm": "^3.9.1" 47 | }, 48 | "devDependencies": { 49 | "@vue/cli-plugin-babel": "^3.0.1", 50 | "@vue/cli-plugin-eslint": "^3.0.1", 51 | "@vue/cli-plugin-unit-mocha": "^3.0.1", 52 | "@vue/cli-service": "^3.0.1", 53 | "@vue/eslint-config-standard": "^3.0.0-beta.10", 54 | "@vue/test-utils": "^1.0.0-beta.10", 55 | "chai": "^4.1.2", 56 | "eslint-plugin-cypress": "^2.0.1", 57 | "less": "^2.7.3", 58 | "less-loader": "^4.0.5", 59 | "lint-staged": "^6.0.0", 60 | "mockjs": "^1.0.1-beta3", 61 | "vue-template-compiler": "^2.5.13" 62 | }, 63 | "browserslist": [ 64 | "> 1%", 65 | "last 2 versions", 66 | "not ie <= 8" 67 | ], 68 | "gitHooks": { 69 | "pre-commit": "lint-staged" 70 | }, 71 | "lint-staged": { 72 | "*.js": [ 73 | "vue-cli-service lint", 74 | "git add" 75 | ], 76 | "*.vue": [ 77 | "vue-cli-service lint", 78 | "git add" 79 | ] 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opendevops-cn/codo/b57acb97c17a36d94d26a9214bbc6c051ce081a4/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | CODO 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 28 | -------------------------------------------------------------------------------- /src/api/app.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | 3 | export const getLoglist = (page, limit, key, value, date = ['', '']) => { 4 | return axios.request({ 5 | url: '/mg/v2/app/opt_log/', 6 | method: 'get', 7 | params: { 8 | page, 9 | limit, 10 | key, 11 | value, 12 | start_date: date[0], 13 | end_date: date.length > 1 ? date[1] : '' 14 | } 15 | }) 16 | } 17 | 18 | // 系统配置项 19 | // 发布应用选择 20 | export const getSysconfig = (value) => { 21 | return axios.request({ 22 | url: `/mg/v2/sysconfig/settings/${value}/`, 23 | method: 'get' 24 | }) 25 | } 26 | 27 | export const operationSysconfig = (data, meth) => { 28 | return axios.request({ 29 | url: '/mg/v2/sysconfig/settings/set/', 30 | method: 'post', 31 | data 32 | }) 33 | } 34 | // 检查配置 35 | export const CheckSysconfig = (data) => { 36 | return axios.request({ 37 | url: '/mg/v2/sysconfig/check/', 38 | method: 'post', 39 | data 40 | }) 41 | } 42 | -------------------------------------------------------------------------------- /src/api/cmdb/adm_user.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | 3 | // 获取所有管理用户 4 | export const getTableData = () => { 5 | return axios.request({ 6 | url: '/cmdb/v1/cmdb/adm_user/', 7 | method: 'get' 8 | }) 9 | } 10 | 11 | // 添加或修改管理用户 12 | export const Add = (data, url, action) => { 13 | return axios.request({ 14 | url: `/cmdb/v1/cmdb/adm_user${url}`, 15 | method: action, 16 | data 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /src/api/cmdb/db.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | 3 | // 获取所有主机 4 | export const getDBData = (params) => { 5 | return axios.request({ 6 | url: '/cmdb/v1/cmdb/db/', 7 | method: 'get', 8 | params 9 | }) 10 | } 11 | 12 | // 添加或修改DB 13 | export const addDBServer = (data, url, action) => { 14 | return axios.request({ 15 | url: `/cmdb/v1/cmdb/db${url}`, 16 | method: action, 17 | data 18 | }) 19 | } 20 | 21 | // 批量添加主机 22 | export const multiAdd = (data) => { 23 | return axios.request({ 24 | url: '/cmdb/v1/cmdb/db_multiadd/', 25 | method: 'post', 26 | data 27 | }) 28 | } 29 | 30 | // 批量删除主机 31 | export const delMulti = (data) => { 32 | return axios.request({ 33 | url: '/cmdb/v1/cmdb/db_multidel/', 34 | method: 'post', 35 | data 36 | }) 37 | } 38 | 39 | // 删除主机 40 | export const delDB = (id) => { 41 | return axios.request({ 42 | url: `/cmdb/v1/cmdb/db/${id}`, 43 | method: 'delete' 44 | }) 45 | } 46 | -------------------------------------------------------------------------------- /src/api/cmdb/server.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | import config from '@/config' 3 | 4 | // 获取所有主机 5 | export const getTableData = (params) => { 6 | return axios.request({ 7 | url: '/cmdb/v1/cmdb/server/', 8 | method: 'get', 9 | params 10 | }) 11 | } 12 | // // 根据条件搜索主机 13 | // export const searchTableData = (key, value) => { 14 | // return axios.request({ 15 | // url: `/api/cmdb/server/?${key}=${value}`, 16 | // method: 'get' 17 | // }) 18 | // } 19 | 20 | // 获取所有管理用户 21 | export const getAdmUser = () => { 22 | return axios.request({ 23 | url: '/cmdb/v1/cmdb/adm_user/', 24 | method: 'get' 25 | }) 26 | } 27 | 28 | // 获取所有主机组 getGroupList 29 | export const getGroupList = () => { 30 | return axios.request({ 31 | url: '/cmdb/v1/cmdb/server_group/', 32 | method: 'get' 33 | }) 34 | } 35 | 36 | // 获取所有主机组 getTagList 37 | export const getTagList = () => { 38 | return axios.request({ 39 | url: '/cmdb/v1/cmdb/tag/', 40 | method: 'get' 41 | }) 42 | } 43 | 44 | // 添加或修改主机 45 | export const addProject = (data, url, action) => { 46 | return axios.request({ 47 | url: `/cmdb/v1/cmdb/server${url}`, 48 | method: action, 49 | data 50 | }) 51 | } 52 | 53 | // 批量添加主机 54 | export const multiAdd = (data) => { 55 | return axios.request({ 56 | url: '/cmdb/v1/cmdb/server_multiadd/', 57 | method: 'post', 58 | data 59 | }) 60 | } 61 | 62 | // 删除主机 63 | export const delServer = (id) => { 64 | return axios.request({ 65 | url: `/cmdb/v1/cmdb/server/${id}`, 66 | method: 'delete' 67 | }) 68 | } 69 | 70 | // 批量删除主机 71 | export const delMultiServer = (data) => { 72 | return axios.request({ 73 | url: '/cmdb/v1/cmdb/server_multidel/', 74 | method: 'post', 75 | data 76 | }) 77 | } 78 | 79 | // 更新资产 80 | export const rsyncHostData = (data) => { 81 | return axios.request({ 82 | url: '/cmdb/v1/cmdb/server_update/', 83 | method: 'post', 84 | data 85 | }) 86 | } 87 | 88 | // 推送公钥 89 | export const rsyncPublicKeyData = (data) => { 90 | return axios.request({ 91 | url: '/cmdb/v1/cmdb/server_publickey/', 92 | method: 'post', 93 | data 94 | }) 95 | } 96 | 97 | // WEB Socket 98 | // export const webSocketUrl = 'ws://cmdb.opendevops.cn:8002/v1/cmdb/ws/terminal' 内网 99 | // export const webSocketUrl = 'ws://demo.opendevops.cn/api/cmdb/v1/cmdb/ws/terminal' // 外网 100 | const theDomain = process.env.NODE_ENV === 'development' ? 'demo.opendevops.cn' : config.domainName.pro 101 | // const theDomain = process.env.NODE_ENV === 'development' ? config.domainName.dev : config.domainName.pro 102 | const wsuri = '/cmdb/v1/cmdb/ws/terminal' 103 | const ws = config.isHttps ? 'wss' : 'ws' 104 | export const webSocketUrl = ws + '://' + theDomain + '/api' + wsuri 105 | -------------------------------------------------------------------------------- /src/api/cmdb/server_auth.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | 3 | // 获取所有授权规则 4 | export const getTableData = (params) => { 5 | return axios.request({ 6 | url: '/cmdb/v1/cmdb/server_auth/', 7 | method: 'get', 8 | params 9 | }) 10 | } 11 | 12 | // 添加或修改授权策略 13 | export const addRule = (data, url, action) => { 14 | return axios.request({ 15 | url: `/cmdb/v1/cmdb/server_auth${url}`, 16 | method: action, 17 | data 18 | }) 19 | } 20 | 21 | // 删除授权策略 22 | export const delRule = (id) => { 23 | return axios.request({ 24 | url: `/cmdb/v1/cmdb/server_auth/${id}`, 25 | method: 'delete' 26 | }) 27 | } 28 | 29 | // 获取系统用户列表 30 | export const getSystemUser = () => { 31 | return axios.request({ 32 | url: '/mg/v2/accounts/user/', 33 | method: 'get', 34 | params: { 35 | 'page': '1', 36 | 'limit': '10000' 37 | } 38 | }) 39 | } 40 | 41 | // gw接口登录 42 | export const loginGW = () => { 43 | return axios.request({ 44 | url: '/cmdb/v1/accounts/login/', 45 | method: 'post', 46 | data: { 47 | 'username': 'cmdb', 48 | 'password': 'GpJSWhgZs8hfDLR', 49 | 'dynamic': '' 50 | } 51 | }) 52 | } 53 | 54 | // 判断当前用户对资产是否有权限 55 | export const checkAuthServer = (sid) => { 56 | return axios.request({ 57 | url: '/cmdb/v1/cmdb/server_check_auth/', 58 | method: 'get', 59 | params: { 60 | // 'username': user, 61 | 'sid': sid 62 | } 63 | }) 64 | } 65 | -------------------------------------------------------------------------------- /src/api/cmdb/server_group.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | 3 | // 获取所有主机 4 | export const getTableData = () => { 5 | return axios.request({ 6 | url: '/cmdb/v1/cmdb/server_group/', 7 | method: 'get' 8 | }) 9 | } 10 | 11 | // 添加或修改主机组 12 | export const addServerGroup = (data, url, action) => { 13 | return axios.request({ 14 | url: `/cmdb/v1/cmdb/server_group${url}`, 15 | method: action, 16 | data 17 | }) 18 | } 19 | 20 | // 删除主机 21 | export const delGroup = (id) => { 22 | return axios.request({ 23 | url: `/cmdb/v1/cmdb/server_group/${id}`, 24 | method: 'delete' 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /src/api/cmdb/server_log.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | 3 | // 获取所有登录日志 4 | export const getLogData = (params) => { 5 | return axios.request({ 6 | url: '/cmdb/v1/cmdb/server_log/', 7 | method: 'get', 8 | params 9 | }) 10 | } 11 | 12 | // 获取所有Tty日志 13 | export const getTtyLogData = (lid) => { 14 | return axios.request({ 15 | url: `/cmdb/v1/cmdb/server_ttylog/?log_id=${lid}`, 16 | method: 'get' 17 | }) 18 | } 19 | 20 | // 获取回放日志 21 | export const getRecordData = (lid) => { 22 | return axios.request({ 23 | url: `/cmdb/v1/cmdb/server_recordlog/?log_id=${lid}`, 24 | method: 'get' 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /src/api/cmdb/tag.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | 3 | // 获取所有tag 4 | export const getTableData = () => { 5 | return axios.request({ 6 | url: '/cmdb/v1/cmdb/tag/', 7 | method: 'get' 8 | }) 9 | } 10 | 11 | // 添加或修改tag 12 | export const addTag = (data, url, action) => { 13 | return axios.request({ 14 | url: `/cmdb/v1/cmdb/tag${url}`, 15 | method: action, 16 | data 17 | }) 18 | } 19 | 20 | // 删除tag 21 | export const delTag = (id) => { 22 | return axios.request({ 23 | url: `/cmdb/v1/cmdb/tag/${id}`, 24 | method: 'delete' 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /src/api/cmdb2/admin_user.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | 3 | 4 | export const getAdminUserList = (key, value) => { 5 | return axios.request({ 6 | url: '/cmdb2/v1/cmdb/admin_user/', 7 | method: 'get', 8 | params: { 9 | key, 10 | value 11 | } 12 | }) 13 | } 14 | 15 | export const operationAdminUser = (data, meth) => { 16 | return axios.request({ 17 | url: '/cmdb2/v1/cmdb/admin_user/', 18 | method: meth, 19 | data 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /src/api/cmdb2/asset_config.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | 3 | 4 | // 获取RDS信息 5 | export const handleUpdateredis = () => { 6 | return axios.request({ 7 | url: '/cmdb2/v1/cmdb/asset_configs/handler_update_redis/', 8 | method: 'get' 9 | 10 | }) 11 | } 12 | 13 | // 获取RDS信息 14 | export const handleUpdaterds = () => { 15 | return axios.request({ 16 | url: '/cmdb2/v1/cmdb/asset_configs/handler_update_rds/', 17 | method: 'get' 18 | 19 | }) 20 | } 21 | 22 | // 获取EC2信息 23 | export const handleUpdateserver = () => { 24 | return axios.request({ 25 | url: '/cmdb2/v1/cmdb/asset_configs/handler_update_server/', 26 | method: 'get' 27 | 28 | }) 29 | } 30 | 31 | export const getAssetConfigsList = (key, value) => { 32 | return axios.request({ 33 | url: '/cmdb2/v1/cmdb/asset_configs/', 34 | method: 'get', 35 | params: { 36 | key, 37 | value 38 | } 39 | }) 40 | } 41 | 42 | export const operationAssetConfigs = (data, meth) => { 43 | return axios.request({ 44 | url: '/cmdb2/v1/cmdb/asset_configs/', 45 | method: meth, 46 | data 47 | }) 48 | } 49 | 50 | 51 | // 测试用户填写的数据是否正确 52 | export const apiPermission = (data) => { 53 | return axios.request({ 54 | url: '/cmdb2/v1/cmdb/asset_configs/api_permission/', 55 | method: 'post', 56 | data 57 | }) 58 | } 59 | 60 | // // 测试用户输入的ID/Key/region等信息是否正确(ECS) 61 | // export const ecsAuth = (data) => { 62 | // return axios.request({ 63 | // url: '/cmdb2/v1/cmdb/asset_configs/ecs_auth/', 64 | // method: 'post', 65 | // data 66 | // }) 67 | // } 68 | 69 | // // 测试用户输入的ID/Key/region等信息是否正确(RDS) 70 | // export const rdsAuth = (data) => { 71 | // return axios.request({ 72 | // url: '/cmdb2/v1/cmdb/asset_configs/rds_auth/', 73 | // method: 'post', 74 | // data 75 | // }) 76 | // } 77 | 78 | // // 测试用户输入的ID/Key/region等信息是否正确(redis) 79 | // export const redisAuth = (data) => { 80 | // return axios.request({ 81 | // url: '/cmdb2/v1/cmdb/asset_configs/redis_auth/', 82 | // method: 'post', 83 | // data 84 | // }) 85 | // } 86 | -------------------------------------------------------------------------------- /src/api/cmdb2/audit.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | 3 | // 获取IDC list 4 | export const getLoglist = (page, limit, key, value, date = ['', '']) => { 5 | return axios.request({ 6 | url: '/cmdb2/v1/cmdb/operational_audit/', 7 | method: 'get', 8 | params: { 9 | page, 10 | limit, 11 | key, 12 | value, 13 | start_date: date[0], 14 | end_date: date.length > 1 ? date[1] : '' 15 | } 16 | }) 17 | } 18 | 19 | 20 | 21 | // export const getoperationalAuditlist= (key, value) => { 22 | // return axios.request({ 23 | // url: '/cmdb2/v1/cmdb/operational_audit/', 24 | // method: 'get', 25 | // params: { 26 | // key, 27 | // value, 28 | // } 29 | // }) 30 | // } 31 | 32 | 33 | // export const getoperationalAuditlist = (page, limit, key, value, date = ['', '']) => { 34 | // return axios.request({ 35 | // url: '/cmdb2/v1/cmdb/operational_audit/', 36 | // method: 'get', 37 | // params: { 38 | // page, 39 | // limit, 40 | // key, 41 | // value, 42 | // start_date: date[0], 43 | // end_date: date.length > 1 ? date[1] : '' 44 | // } 45 | // }) 46 | // } -------------------------------------------------------------------------------- /src/api/cmdb2/db.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | import config from '@/config' 3 | 4 | 5 | //批量添加DB 6 | export const multiAdddb = (data) => { 7 | return axios.request({ 8 | url: '/cmdb2//v1/cmdb/db/multi_add/', 9 | method: 'post', 10 | data 11 | }) 12 | } 13 | 14 | //获取DBlist 15 | export const getDBlist= ( page, limit, key, value) => { 16 | return axios.request({ 17 | url: '/cmdb2/v1/cmdb/db/', 18 | method: 'get', 19 | params: { 20 | key, 21 | value, 22 | page, 23 | limit 24 | } 25 | }) 26 | } 27 | 28 | //获取DB详情 29 | export const getDBDetail= ( key, value) => { 30 | return axios.request({ 31 | url: '/cmdb2/v1/cmdb/db/', 32 | method: 'get', 33 | params: { 34 | key, 35 | value, 36 | // page, 37 | // limit 38 | } 39 | }) 40 | } 41 | 42 | //操作DB 43 | export const operationDB = (data, meth) => { 44 | return axios.request({ 45 | url: '/cmdb2/v1/cmdb/db/', 46 | method: meth, 47 | data 48 | }) 49 | } 50 | 51 | -------------------------------------------------------------------------------- /src/api/cmdb2/idc.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | 3 | // 获取IDC list 4 | 5 | export const getIDClist= (key, value) => { 6 | return axios.request({ 7 | url: '/cmdb2/v1/cmdb/idc/', 8 | method: 'get', 9 | params: { 10 | key, 11 | value, 12 | } 13 | }) 14 | } 15 | 16 | // 操作IDC管理 17 | export const operationIdc = (data, meth) => { 18 | return axios.request({ 19 | url: '/cmdb2/v1/cmdb/idc/', 20 | method: meth, 21 | data 22 | }) 23 | } -------------------------------------------------------------------------------- /src/api/cmdb2/system_user.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | 3 | 4 | export const getSystemUserList = (key, value) => { 5 | return axios.request({ 6 | url: '/cmdb2/v1/cmdb/system_user/', 7 | method: 'get', 8 | params: { 9 | key, 10 | value 11 | } 12 | }) 13 | } 14 | 15 | export const operationSystemUser = (data, meth) => { 16 | return axios.request({ 17 | url: '/cmdb2/v1/cmdb/system_user/', 18 | method: meth, 19 | data 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /src/api/cmdb2/tag.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | import config from '@/config' 3 | 4 | //触发更新tag_rule 5 | export const handUpdateTagrule = (data) => { 6 | return axios.request({ 7 | url: '/cmdb2/v1/cmdb/tag_rule/hand_update/', 8 | method: 'post', 9 | data 10 | }) 11 | } 12 | 13 | //GET 更新所有规则 14 | export const handUpdateAlltagrule = () => { 15 | return axios.request({ 16 | url: '/cmdb2/v1/cmdb/tag_rule/hand_update/', 17 | method: 'get' 18 | }) 19 | } 20 | 21 | // 获取所有tag规则 22 | export const getTagRulelist = (page, limit, key, value, date = ['', '']) => { 23 | return axios.request({ 24 | url: '/cmdb2/v1/cmdb/tag_rule/', 25 | method: 'get', 26 | params: { 27 | page, 28 | limit, 29 | key, 30 | value, 31 | start_date: date[0], 32 | end_date: date.length > 1 ? date[1] : '' 33 | } 34 | }) 35 | } 36 | 37 | export const operationTagrule = (data, meth) => { 38 | return axios.request({ 39 | url: '/cmdb2/v1/cmdb/tag_rule/', 40 | method: meth, 41 | data 42 | }) 43 | } 44 | 45 | // 获取所有TAG 46 | export const getTagList = (page, limit, key, value, date = ['', '']) => { 47 | return axios.request({ 48 | url: '/cmdb2/v1/cmdb/tag/', 49 | method: 'get', 50 | params: { 51 | page, 52 | limit, 53 | key, 54 | value, 55 | start_date: date[0], 56 | end_date: date.length > 1 ? date[1] : '' 57 | } 58 | }) 59 | } 60 | 61 | export const operationTag= (data, meth) => { 62 | return axios.request({ 63 | url: '/cmdb2/v1/cmdb/tag/', 64 | method: meth, 65 | data 66 | }) 67 | } -------------------------------------------------------------------------------- /src/api/confd/conf.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | 3 | // 根据project_code获取confTree 4 | export const getConfTree = (name) => { 5 | return axios.request({ 6 | url: '/kerrigan/v1/conf/tree/', 7 | method: 'get', 8 | params: { 9 | project_code: name 10 | } 11 | }) 12 | } 13 | 14 | export const getConf = (params) => { 15 | return axios.request({ 16 | url: '/kerrigan/v1/conf/config/', 17 | method: 'get', 18 | params 19 | }) 20 | } 21 | 22 | export const putConf = (data) => { 23 | return axios.request({ 24 | url: '/kerrigan/v1/conf/config/', 25 | method: 'put', 26 | data 27 | }) 28 | } 29 | 30 | export const postConf = (data) => { 31 | return axios.request({ 32 | url: '/kerrigan/v1/conf/config/', 33 | method: 'post', 34 | data 35 | }) 36 | } 37 | 38 | export const patchConf = (data) => { 39 | return axios.request({ 40 | url: '/kerrigan/v1/conf/config/', 41 | method: 'patch', 42 | data 43 | }) 44 | } 45 | 46 | export const deleteConf = (data) => { 47 | return axios.request({ 48 | url: '/kerrigan/v1/conf/config/', 49 | method: 'delete', 50 | data 51 | }) 52 | } 53 | 54 | export const diffConf = (params) => { 55 | return axios.request({ 56 | url: '/kerrigan/v1/conf/diff/', 57 | method: 'get', 58 | params 59 | }) 60 | } 61 | 62 | export const getHistory = (params) => { 63 | return axios.request({ 64 | url: '/kerrigan/v1/conf/history/', 65 | method: 'get', 66 | params 67 | }) 68 | } 69 | 70 | export const backHistory = (data) => { 71 | return axios.request({ 72 | url: '/kerrigan/v1/conf/history/', 73 | method: 'patch', 74 | data 75 | }) 76 | } 77 | 78 | export const getAuth = (params) => { 79 | return axios.request({ 80 | url: '/kerrigan/v1/conf/permissions/', 81 | method: 'get', 82 | params 83 | }) 84 | } 85 | 86 | export const setAuth = (data, action) => { 87 | return axios.request({ 88 | url: '/kerrigan/v1/conf/permissions/', 89 | method: action, 90 | data 91 | }) 92 | } 93 | -------------------------------------------------------------------------------- /src/api/confd/project.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | 3 | // 获取所有项目 4 | export const getProject = (params) => { 5 | return axios.request({ 6 | url: '/kerrigan/v1/conf/project/', 7 | method: 'get', 8 | params 9 | }) 10 | } 11 | 12 | // 添加项目 13 | export const addProject = (data) => { 14 | return axios.request({ 15 | url: '/kerrigan/v1/conf/project/', 16 | method: 'post', 17 | data 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /src/api/cron.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | 3 | export const getCronJobslist = (page, limit, value) => { 4 | return axios.request({ 5 | url: '/cron//v1/cron/job/', 6 | method: 'get', 7 | params: { 8 | page, 9 | limit, 10 | 'job_id': value 11 | } 12 | }) 13 | } 14 | 15 | export const operationCron = (data, meth) => { 16 | return axios.request({ 17 | url: '/cron//v1/cron/job/', 18 | method: meth, 19 | data 20 | }) 21 | } 22 | 23 | export const getCronLoglist = (page, limit, key, value, date = ['', '']) => { 24 | return axios.request({ 25 | url: '/cron//v1/cron/log/', 26 | method: 'get', 27 | params: { 28 | page, 29 | limit, 30 | key, 31 | value, 32 | start_date: date[0], 33 | end_date: date.length > 1 ? date[1] : '' 34 | } 35 | }) 36 | } 37 | -------------------------------------------------------------------------------- /src/api/dashboard/home.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | import config from '@/config' 3 | 4 | 5 | // 获取Tag,Home仪表盘拼图展示 6 | export const getTagList = () => { 7 | return axios.request({ 8 | url: '/cmdb2/v1/cmdb/tag/', 9 | method: 'get', 10 | }) 11 | } 12 | 13 | // 任务订单 14 | export const getTaskOrderlist = () => { 15 | return axios.request({ 16 | url: '/task/v2/task/list/', 17 | method: 'get' 18 | }) 19 | } 20 | 21 | 22 | // 历史任务订单状态+数量 23 | export const getTaskStatementlist = () => { 24 | return axios.request({ 25 | url: '/task/v2/task/statement/', 26 | method: 'get' 27 | }) 28 | } -------------------------------------------------------------------------------- /src/api/data.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | 3 | export const getTableData = () => { 4 | return axios.request({ 5 | url: 'get_table_data', 6 | method: 'get' 7 | }) 8 | } 9 | 10 | export const getDragList = () => { 11 | return axios.request({ 12 | url: 'get_drag_list', 13 | method: 'get' 14 | }) 15 | } 16 | 17 | export const errorReq = () => { 18 | return axios.request({ 19 | url: 'error_url', 20 | method: 'post' 21 | }) 22 | } 23 | 24 | export const saveErrorLogger = info => { 25 | return axios.request({ 26 | url: 'save_error_logger', 27 | data: info, 28 | method: 'post' 29 | }) 30 | } 31 | -------------------------------------------------------------------------------- /src/api/domain/dns.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | 3 | export const getDomainname= (key, value) => { 4 | return axios.request({ 5 | url: '/dns/v1/dns/bind/domain/', 6 | method: 'get', 7 | params: { 8 | key, 9 | value 10 | } 11 | }) 12 | } 13 | 14 | export const operationDomainname= (data, meth) => { 15 | return axios.request({ 16 | url: '/dns/v1/dns/bind/domain/', 17 | method: meth, 18 | data 19 | }) 20 | } 21 | 22 | export const getDomainzone= (page, limit, zone, key) => { 23 | return axios.request({ 24 | url: '/dns/v1/dns/bind/zone/', 25 | method: 'get', 26 | params: { 27 | page, 28 | limit, 29 | zone, 30 | key 31 | } 32 | }) 33 | } 34 | 35 | export const operationDomainzone= (data, meth) => { 36 | return axios.request({ 37 | url: '/dns/v1/dns/bind/zone/', 38 | method: meth, 39 | data 40 | }) 41 | } 42 | 43 | export const getLoglist= (domain) => { 44 | return axios.request({ 45 | url: '/dns/v1/dns/bind/log/', 46 | method: 'get', 47 | params: { 48 | domain 49 | } 50 | }) 51 | } 52 | 53 | export const getDomainconf= () => { 54 | return axios.request({ 55 | url: '/dns/v1/dns/bind/conf/', 56 | method: 'get', 57 | }) 58 | } 59 | -------------------------------------------------------------------------------- /src/api/domain/domain.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | 3 | export const getDomain = (search_value) => { 4 | return axios.request({ 5 | url: '/dns/v1/dns/cloud/domain/', 6 | method: 'get', 7 | params: { 8 | search_value 9 | } 10 | }) 11 | } 12 | 13 | export const operationDomain = (data, method) => { 14 | return axios.request({ 15 | url: '/dns/v1/dns/cloud/domain/', 16 | method: method, 17 | data 18 | }) 19 | } 20 | 21 | export const syncDomain = (key, value) => { 22 | return axios.request({ 23 | url: '/dns/v1/dns/cloud/sync/', 24 | method: 'get' 25 | }) 26 | } 27 | 28 | export const getDomainRecords = (page, limit, domain_name, search_value) => { 29 | return axios.request({ 30 | url: '/dns/v1/dns/cloud/record/', 31 | method: 'get', 32 | params: { 33 | page, 34 | limit, 35 | domain_name, 36 | search_value 37 | } 38 | }) 39 | } 40 | 41 | export const optDomainRecords = (data, method) => { 42 | return axios.request({ 43 | url: '/dns/v1/dns/cloud/record/', 44 | method: method, 45 | data 46 | }) 47 | } 48 | 49 | export const recordsChangeRemark = (data) => { 50 | return axios.request({ 51 | url: '/dns/v1/dns/cloud/remark/', 52 | method: 'post', 53 | data 54 | }) 55 | } 56 | 57 | export const getDomainLog = (page, limit, domain_name, search_value) => { 58 | return axios.request({ 59 | url: '/dns/v1/dns/cloud/logs/', 60 | method: 'get', 61 | params: { 62 | page, 63 | limit, 64 | domain_name, 65 | search_value 66 | } 67 | }) 68 | } 69 | export const getAccountlist = () => { 70 | return axios.request({ 71 | url: '/dns/v1/dns/cloud/account/', 72 | method: 'get' 73 | }) 74 | } 75 | 76 | export const operationAccount = (data, method) => { 77 | return axios.request({ 78 | url: '/dns/v1/dns/cloud/account/', 79 | method: method, 80 | data 81 | }) 82 | } -------------------------------------------------------------------------------- /src/api/git-repo.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | 3 | export const getGittree = () => { 4 | return axios.request({ 5 | url: '/task/other/v1/git/tree/', 6 | method: 'get' 7 | }) 8 | } 9 | 10 | export const getGittree2 = () => { 11 | return axios.request({ 12 | url: '/task/other/v1/git/tree2/', 13 | method: 'get' 14 | }) 15 | } 16 | 17 | export const getGitrepo = (git_url, group_name, searchVal) => { 18 | return axios.request({ 19 | url: '/task/other/v1/git/repo/', 20 | method: 'get', 21 | params: { 22 | git_url, 23 | group_name, 24 | 'search_val': searchVal 25 | } 26 | }) 27 | } 28 | 29 | export const optGitrepo = (data, meth) => { 30 | return axios.request({ 31 | url: '/task/other/v1/git/repo/', 32 | method: meth, 33 | data 34 | }) 35 | } 36 | 37 | export const getGituser = (git_url, group_name) => { 38 | return axios.request({ 39 | url: '/task/other/v1/git/user/', 40 | method: 'get', 41 | params: { 42 | git_url, 43 | group_name, 44 | } 45 | }) 46 | } 47 | 48 | export const optGithooks = (data, meth) => { 49 | return axios.request({ 50 | url: '/task/other/v1/git/hooks/', 51 | method: meth, 52 | data 53 | }) 54 | } 55 | 56 | export const getGitHooklog = (search_val, git_url, relative_path, hook_name) => { 57 | return axios.request({ 58 | url: '/task/other/v1/git/logs/', 59 | method: 'get', 60 | params: { 61 | search_val, 62 | git_url, 63 | relative_path, 64 | hook_name 65 | } 66 | }) 67 | } 68 | 69 | export const optGitHooklog = (data) => { 70 | return axios.request({ 71 | url: '/task/other/v1/git/logs/', 72 | method: 'delete', 73 | data 74 | }) 75 | } 76 | 77 | export const getGitConflist = () => { 78 | return axios.request({ 79 | url: '/task/other/v1/git/conf/', 80 | method: 'get' 81 | }) 82 | } 83 | 84 | export const optGitconf = (data, meth) => { 85 | return axios.request({ 86 | url: '/task/other/v1/git/conf/', 87 | method: meth, 88 | data 89 | }) 90 | } 91 | 92 | export const Gitsync = () => { 93 | return axios.request({ 94 | url: '/task/other/v1/git/sync/', 95 | method: 'post' 96 | }) 97 | } 98 | 99 | export const getGitRepotags = (git_url, project_id) => { 100 | return axios.request({ 101 | url: '/task/other/v1/git/tags/', 102 | method: 'get', 103 | params: { 104 | git_url, 105 | project_id, 106 | } 107 | }) 108 | } -------------------------------------------------------------------------------- /src/api/k8s/app.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | 3 | // 获取所有项目 4 | export const getTableData = () => { 5 | return axios.request({ 6 | url: '/k8s/v1/k8s/app/', 7 | method: 'get' 8 | }) 9 | } 10 | 11 | // 新建项目 12 | export const addApp = (data, url, action) => { 13 | return axios.request({ 14 | url: `/k8s/v1/k8s/app${url}`, 15 | method: action, 16 | data 17 | }) 18 | } 19 | 20 | // 获取所有APP 21 | export const getAppList = () => { 22 | return axios.request({ 23 | url: '/k8s/v1/k8s/app/', 24 | method: 'get' 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /src/api/k8s/project.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | 3 | // 获取所有项目 4 | export const getTableData = () => { 5 | return axios.request({ 6 | url: '/k8s/v1/k8s/project/', 7 | method: 'get' 8 | }) 9 | } 10 | 11 | // 新建项目 12 | export const addProject = (data, url, action) => { 13 | return axios.request({ 14 | url: `/k8s/v1/k8s/project${url}`, 15 | method: action, 16 | data 17 | }) 18 | } 19 | 20 | // 获取所有Env 21 | export const getEnvList = () => { 22 | return axios.request({ 23 | url: '/k8s/v1/k8s/env/', 24 | method: 'get' 25 | }) 26 | } 27 | 28 | // 获取所有User 29 | export const getUserList = () => { 30 | return axios.request({ 31 | url: '/k8s/v1/k8s/user/', 32 | method: 'get' 33 | }) 34 | } 35 | 36 | // 获取所有APP 37 | export const getAppList = () => { 38 | return axios.request({ 39 | url: '/k8s/v1/k8s/app/', 40 | method: 'get' 41 | }) 42 | } 43 | -------------------------------------------------------------------------------- /src/api/k8s/publish.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | 3 | // 获取所有发布信息 4 | export const getTableData = () => { 5 | return axios.request({ 6 | url: '/k8s/v1/k8s/publish/', 7 | method: 'get' 8 | }) 9 | } 10 | 11 | // 获取发布详情 12 | export const getPublishDetail = (pid) => { 13 | return axios.request({ 14 | url: `/k8s/v1/k8s/publish/${pid}/`, 15 | method: 'get' 16 | }) 17 | } 18 | 19 | // 对发布任务进行操作 20 | export const publishAction = (pid, data) => { 21 | return axios.request({ 22 | url: `/k8s/v1/k8s/publish/${pid}/`, 23 | method: 'patch', 24 | data: data 25 | }) 26 | } 27 | 28 | // 新建发布 29 | export const addPublish = (data) => { 30 | return axios.request({ 31 | url: '/k8s/v1/k8s/publish/', 32 | method: 'post', 33 | data 34 | }) 35 | } 36 | 37 | // 执行发布任务 38 | export const exeJob = (jid) => { 39 | return axios.request({ 40 | url: `/k8s/v1/k8s/job/exec/${jid}/`, 41 | method: 'post' 42 | }) 43 | } 44 | 45 | // 获取日志信息 46 | export const getLog = (project, jid) => { 47 | return axios.request({ 48 | url: '/k8s/v1/k8s/job/log/', 49 | method: 'get', 50 | params: { 51 | project_name: project, 52 | job_id: jid 53 | } 54 | }) 55 | } 56 | -------------------------------------------------------------------------------- /src/api/k8s/task.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | 3 | // 获取日志信息 4 | export const getTaskDetail = (publishId, appId, envId) => { 5 | return axios.request({ 6 | url: '/k8s/v1/k8s/job/detail/', 7 | method: 'get', 8 | params: { 9 | publish_id: publishId, 10 | app_id: appId, 11 | env_id: envId 12 | } 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /src/api/mg/resource-mg.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | import config from '@/config' 3 | 4 | // 5 | export const getResourceList = (page, limit, search_value) => { 6 | return axios.request({ 7 | url: '/mg/v2/overall/resource/', 8 | method: 'get', 9 | params: { 10 | page, 11 | limit, 12 | search_value 13 | } 14 | }) 15 | } 16 | 17 | 18 | export const optResource = (data, meth) => { 19 | return axios.request({ 20 | url: '/mg/v2/overall/resource/', 21 | method: meth, 22 | data 23 | }) 24 | } -------------------------------------------------------------------------------- /src/api/routers.js: -------------------------------------------------------------------------------- 1 | import axios from '@/libs/api.request' 2 | 3 | export const getRouterReq = (access) => { 4 | return axios.request({ 5 | url: 'get_router', 6 | params: { 7 | access 8 | }, 9 | method: 'get' 10 | }) 11 | } 12 | -------------------------------------------------------------------------------- /src/assets/icons/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opendevops-cn/codo/b57acb97c17a36d94d26a9214bbc6c051ce081a4/src/assets/icons/iconfont.eot -------------------------------------------------------------------------------- /src/assets/icons/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opendevops-cn/codo/b57acb97c17a36d94d26a9214bbc6c051ce081a4/src/assets/icons/iconfont.ttf -------------------------------------------------------------------------------- /src/assets/icons/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opendevops-cn/codo/b57acb97c17a36d94d26a9214bbc6c051ce081a4/src/assets/icons/iconfont.woff -------------------------------------------------------------------------------- /src/assets/images/login-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opendevops-cn/codo/b57acb97c17a36d94d26a9214bbc6c051ce081a4/src/assets/images/login-bg.jpg -------------------------------------------------------------------------------- /src/assets/images/login-bg1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opendevops-cn/codo/b57acb97c17a36d94d26a9214bbc6c051ce081a4/src/assets/images/login-bg1.jpg -------------------------------------------------------------------------------- /src/assets/images/logo-min.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opendevops-cn/codo/b57acb97c17a36d94d26a9214bbc6c051ce081a4/src/assets/images/logo-min.jpg -------------------------------------------------------------------------------- /src/assets/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opendevops-cn/codo/b57acb97c17a36d94d26a9214bbc6c051ce081a4/src/assets/images/logo.png -------------------------------------------------------------------------------- /src/assets/images/qq-fance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opendevops-cn/codo/b57acb97c17a36d94d26a9214bbc6c051ce081a4/src/assets/images/qq-fance.png -------------------------------------------------------------------------------- /src/assets/images/qq-fance2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opendevops-cn/codo/b57acb97c17a36d94d26a9214bbc6c051ce081a4/src/assets/images/qq-fance2.jpg -------------------------------------------------------------------------------- /src/assets/images/talkingdata.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opendevops-cn/codo/b57acb97c17a36d94d26a9214bbc6c051ce081a4/src/assets/images/talkingdata.png -------------------------------------------------------------------------------- /src/components/charts/bar.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 59 | -------------------------------------------------------------------------------- /src/components/charts/index.js: -------------------------------------------------------------------------------- 1 | import ChartPie from './pie.vue' 2 | import ChartBar from './bar.vue' 3 | export { ChartPie, ChartBar } 4 | -------------------------------------------------------------------------------- /src/components/charts/pie.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 74 | -------------------------------------------------------------------------------- /src/components/common-icon/common-icon.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 39 | 40 | 43 | -------------------------------------------------------------------------------- /src/components/common-icon/index.js: -------------------------------------------------------------------------------- 1 | import CommonIcon from './common-icon.vue' 2 | export default CommonIcon 3 | -------------------------------------------------------------------------------- /src/components/common/common.less: -------------------------------------------------------------------------------- 1 | .no-select{ 2 | -webkit-touch-callout: none; 3 | -webkit-user-select: none; 4 | -khtml-user-select: none; 5 | -moz-user-select: none; 6 | -ms-user-select: none; 7 | user-select: none; 8 | } 9 | -------------------------------------------------------------------------------- /src/components/common/util.js: -------------------------------------------------------------------------------- 1 | export const showTitle = (item, vm) => { 2 | return vm.$config.useI18n ? vm.$t(item.name) : ((item.meta && item.meta.title) || item.name) 3 | } 4 | -------------------------------------------------------------------------------- /src/components/count-to/index.js: -------------------------------------------------------------------------------- 1 | import countTo from './count-to.vue' 2 | export default countTo 3 | -------------------------------------------------------------------------------- /src/components/count-to/index.less: -------------------------------------------------------------------------------- 1 | @prefix: ~"count-to"; 2 | 3 | .@{prefix}-wrapper{ 4 | .content-outer{ 5 | display: inline-block; 6 | .@{prefix}-unit-text{ 7 | font-style: normal; 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/components/drag-list/drag-list.vue: -------------------------------------------------------------------------------- 1 | 21 | 84 | 93 | -------------------------------------------------------------------------------- /src/components/drag-list/index.js: -------------------------------------------------------------------------------- 1 | import DragList from './drag-list.vue' 2 | export default DragList 3 | -------------------------------------------------------------------------------- /src/components/editor/editor.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 70 | 71 | 74 | -------------------------------------------------------------------------------- /src/components/editor/index.js: -------------------------------------------------------------------------------- 1 | import Editor from './editor.vue' 2 | export default Editor 3 | -------------------------------------------------------------------------------- /src/components/form-group/index.js: -------------------------------------------------------------------------------- 1 | import FormGroup from './form-group.vue' 2 | export default FormGroup 3 | -------------------------------------------------------------------------------- /src/components/icons/icons.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 32 | 33 | 36 | -------------------------------------------------------------------------------- /src/components/icons/index.js: -------------------------------------------------------------------------------- 1 | import Icons from './icons.vue' 2 | export default Icons 3 | -------------------------------------------------------------------------------- /src/components/info-card/index.js: -------------------------------------------------------------------------------- 1 | import InforCard from './infor-card.vue' 2 | export default InforCard 3 | -------------------------------------------------------------------------------- /src/components/info-card/infor-card.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 55 | 56 | 95 | -------------------------------------------------------------------------------- /src/components/login-form/index.js: -------------------------------------------------------------------------------- 1 | import LoginForm from './login-form.vue' 2 | import RegisterForm from './register.vue' 3 | import MFA from './mfa.vue' 4 | export {LoginForm, RegisterForm, MFA} 5 | -------------------------------------------------------------------------------- /src/components/login-form/login-form.vue: -------------------------------------------------------------------------------- 1 | 29 | 95 | -------------------------------------------------------------------------------- /src/components/login-form/mfa.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 59 | 60 | 62 | -------------------------------------------------------------------------------- /src/components/main/components/error-store/error-store.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 38 | 39 | 50 | -------------------------------------------------------------------------------- /src/components/main/components/error-store/index.js: -------------------------------------------------------------------------------- 1 | import ErrorStore from './error-store.vue' 2 | export default ErrorStore 3 | -------------------------------------------------------------------------------- /src/components/main/components/footer/copyright.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /src/components/main/components/fullscreen/fullscreen.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 75 | 76 | 85 | -------------------------------------------------------------------------------- /src/components/main/components/fullscreen/index.js: -------------------------------------------------------------------------------- 1 | import Fullscreen from './fullscreen.vue' 2 | export default Fullscreen 3 | -------------------------------------------------------------------------------- /src/components/main/components/header-bar/custom-bread-crumb/custom-bread-crumb.less: -------------------------------------------------------------------------------- 1 | .custom-bread-crumb{ 2 | display: inline-block; 3 | vertical-align: top; 4 | } 5 | -------------------------------------------------------------------------------- /src/components/main/components/header-bar/custom-bread-crumb/custom-bread-crumb.vue: -------------------------------------------------------------------------------- 1 | 11 | 47 | -------------------------------------------------------------------------------- /src/components/main/components/header-bar/custom-bread-crumb/index.js: -------------------------------------------------------------------------------- 1 | import customBreadCrumb from './custom-bread-crumb.vue' 2 | export default customBreadCrumb 3 | -------------------------------------------------------------------------------- /src/components/main/components/header-bar/header-bar.less: -------------------------------------------------------------------------------- 1 | .header-bar{ 2 | width: 100%; 3 | height: 100%; 4 | position: relative; 5 | .custom-content-con{ 6 | float: right; 7 | height: auto; 8 | padding-right: 20px; 9 | line-height: 64px; 10 | & > *{ 11 | float: right; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/components/main/components/header-bar/header-bar.vue: -------------------------------------------------------------------------------- 1 | 10 | 35 | -------------------------------------------------------------------------------- /src/components/main/components/header-bar/index.js: -------------------------------------------------------------------------------- 1 | import HeaderBar from './header-bar' 2 | export default HeaderBar 3 | -------------------------------------------------------------------------------- /src/components/main/components/header-bar/sider-trigger/index.js: -------------------------------------------------------------------------------- 1 | import siderTrigger from './sider-trigger.vue' 2 | export default siderTrigger 3 | -------------------------------------------------------------------------------- /src/components/main/components/header-bar/sider-trigger/sider-trigger.less: -------------------------------------------------------------------------------- 1 | .trans{ 2 | transition: transform .2s ease; 3 | } 4 | @size: 40px; 5 | .sider-trigger-a{ 6 | padding: 6px; 7 | width: @size; 8 | height: @size; 9 | display: inline-block; 10 | text-align: center; 11 | color: #5c6b77; 12 | margin-top: 12px; 13 | i{ 14 | .trans; 15 | vertical-align: top; 16 | } 17 | &.collapsed i{ 18 | transform: rotateZ(90deg); 19 | .trans; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/components/main/components/header-bar/sider-trigger/sider-trigger.vue: -------------------------------------------------------------------------------- 1 | 4 | 25 | 28 | -------------------------------------------------------------------------------- /src/components/main/components/language/index.js: -------------------------------------------------------------------------------- 1 | import Language from './language.vue' 2 | export default Language 3 | -------------------------------------------------------------------------------- /src/components/main/components/language/language.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 52 | -------------------------------------------------------------------------------- /src/components/main/components/side-menu/collapsed-menu.vue: -------------------------------------------------------------------------------- 1 | 12 | 52 | -------------------------------------------------------------------------------- /src/components/main/components/side-menu/index.js: -------------------------------------------------------------------------------- 1 | import SideMenu from './side-menu.vue' 2 | export default SideMenu 3 | -------------------------------------------------------------------------------- /src/components/main/components/side-menu/item-mixin.js: -------------------------------------------------------------------------------- 1 | export default { 2 | props: { 3 | parentItem: { 4 | type: Object, 5 | default: () => {} 6 | }, 7 | theme: String, 8 | iconSize: Number 9 | }, 10 | computed: { 11 | parentName () { 12 | return this.parentItem.name 13 | }, 14 | children () { 15 | return this.parentItem.children 16 | }, 17 | textColor () { 18 | return this.theme === 'dark' ? '#fff' : '#495060' 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/components/main/components/side-menu/mixin.js: -------------------------------------------------------------------------------- 1 | import CommonIcon from '_c/common-icon' 2 | export default { 3 | components: { 4 | CommonIcon 5 | }, 6 | methods: { 7 | showTitle (item) { 8 | return this.$config.useI18n ? this.$t(item.name) : ((item.meta && item.meta.title) || item.name) 9 | }, 10 | showChildren (item) { 11 | return item.children && (item.children.length > 1 || (item.meta && item.meta.showAlways)) 12 | }, 13 | getNameOrHref (item, children0) { 14 | return item.href ? `isTurnByHref_${item.href}` : (children0 ? item.children[0].name : item.name) 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/components/main/components/side-menu/side-menu-item.vue: -------------------------------------------------------------------------------- 1 | 19 | 27 | -------------------------------------------------------------------------------- /src/components/main/components/side-menu/side-menu.less: -------------------------------------------------------------------------------- 1 | .side-menu-wrapper{ 2 | user-select: none; 3 | .menu-collapsed{ 4 | padding-top: 10px; 5 | 6 | .ivu-dropdown{ 7 | width: 100%; 8 | .ivu-dropdown-rel a{ 9 | width: 100%; 10 | } 11 | } 12 | .ivu-tooltip{ 13 | width: 100%; 14 | .ivu-tooltip-rel{ 15 | width: 100%; 16 | } 17 | .ivu-tooltip-popper .ivu-tooltip-content{ 18 | .ivu-tooltip-arrow{ 19 | border-right-color: #fff; 20 | } 21 | .ivu-tooltip-inner{ 22 | background: #fff; 23 | color: #495060; 24 | } 25 | } 26 | } 27 | 28 | 29 | } 30 | a.drop-menu-a{ 31 | display: inline-block; 32 | padding: 6px 15px; 33 | width: 100%; 34 | text-align: center; 35 | color: #495060; 36 | } 37 | } 38 | .menu-title{ 39 | padding-left: 6px; 40 | } 41 | -------------------------------------------------------------------------------- /src/components/main/components/tags-nav/index.js: -------------------------------------------------------------------------------- 1 | import TagsNav from './tags-nav.vue' 2 | export default TagsNav 3 | -------------------------------------------------------------------------------- /src/components/main/components/tags-nav/tags-nav.less: -------------------------------------------------------------------------------- 1 | .no-select{ 2 | -webkit-touch-callout: none; 3 | -webkit-user-select: none; 4 | -khtml-user-select: none; 5 | -moz-user-select: none; 6 | -ms-user-select: none; 7 | user-select: none; 8 | } 9 | .size{ 10 | width: 100%; 11 | height: 100%; 12 | } 13 | .tags-nav{ 14 | position: relative; 15 | border-top: 1px solid #F0F0F0; 16 | border-bottom: 1px solid #F0F0F0; 17 | .no-select; 18 | .size; 19 | .close-con{ 20 | position: absolute; 21 | right: 0; 22 | top: 0; 23 | height: 100%; 24 | width: 32px; 25 | background: #fff; 26 | text-align: center; 27 | z-index: 10; 28 | } 29 | .btn-con{ 30 | position: absolute; 31 | top: 0px; 32 | height: 100%; 33 | background: #fff; 34 | padding-top: 3px; 35 | z-index: 10; 36 | button{ 37 | padding: 6px 4px; 38 | line-height: 14px; 39 | text-align: center; 40 | } 41 | &.left-btn{ 42 | left: 0px; 43 | } 44 | &.right-btn{ 45 | right: 32px; 46 | border-right: 1px solid #F0F0F0; 47 | } 48 | } 49 | .scroll-outer{ 50 | position: absolute; 51 | left: 28px; 52 | right: 61px; 53 | top: 0; 54 | bottom: 0; 55 | box-shadow: 0px 0 3px 2px rgba(100,100,100,.1) inset; 56 | .scroll-body{ 57 | height: ~"calc(100% - 1px)"; 58 | display: inline-block; 59 | padding: 1px 4px 0; 60 | position: absolute; 61 | overflow: visible; 62 | white-space: nowrap; 63 | transition: left .3s ease; 64 | .ivu-tag-dot-inner{ 65 | transition: background .2s ease; 66 | } 67 | } 68 | } 69 | .contextmenu { 70 | position: absolute; 71 | margin: 0; 72 | padding: 5px 0; 73 | background: #fff; 74 | z-index: 100; 75 | list-style-type: none; 76 | border-radius: 4px; 77 | box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, .3); 78 | li { 79 | margin: 0; 80 | padding: 5px 15px; 81 | cursor: pointer; 82 | &:hover { 83 | background: #eee; 84 | } 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/components/main/components/user/index.js: -------------------------------------------------------------------------------- 1 | import User from './user.vue' 2 | export default User 3 | -------------------------------------------------------------------------------- /src/components/main/components/user/user.less: -------------------------------------------------------------------------------- 1 | .user{ 2 | &-avator-dropdown{ 3 | cursor: pointer; 4 | display: inline-block; 5 | // height: 64px; 6 | vertical-align: middle; 7 | // line-height: 64px; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/components/main/index.js: -------------------------------------------------------------------------------- 1 | import Main from './main.vue' 2 | export default Main 3 | -------------------------------------------------------------------------------- /src/components/main/main.less: -------------------------------------------------------------------------------- 1 | .main{ 2 | .logo-con{ 3 | height: 45px !important; 4 | padding: 0px; 5 | img{ 6 | height: 100%; 7 | width: 100%; 8 | padding: 0px; 9 | display: block; 10 | } 11 | } 12 | .header-con{ 13 | background: #fff; 14 | padding: 0 20px; 15 | height: 60px; 16 | width: 100%; 17 | } 18 | .main-layout-con{ 19 | height: 100%; 20 | overflow: hidden; 21 | } 22 | .main-content-con{ 23 | height: ~"calc(100% - 60px)"; 24 | overflow: hidden; 25 | } 26 | .tag-nav-wrapper{ 27 | padding: 0; 28 | height:40px; 29 | background:#F0F0F0; 30 | } 31 | .content-wrapper{ 32 | padding: 18px; 33 | height: ~"calc(100% - 80px)"; 34 | overflow: auto; 35 | } 36 | .left-sider{ 37 | .ivu-layout-sider-children{ 38 | overflow-y: scroll; 39 | margin-right: -18px; 40 | } 41 | } 42 | } 43 | .ivu-menu-item > i{ 44 | margin-right: 12px !important; 45 | } 46 | .ivu-menu-submenu > .ivu-menu > .ivu-menu-item > i { 47 | margin-right: 8px !important; 48 | } 49 | .collased-menu-dropdown{ 50 | width: 100%; 51 | margin: 0; 52 | line-height: normal; 53 | padding: 7px 0 6px 16px; 54 | clear: both; 55 | font-size: 12px !important; 56 | white-space: nowrap; 57 | list-style: none; 58 | cursor: pointer; 59 | transition: background 0.2s ease-in-out; 60 | &:hover{ 61 | background: rgba(100, 100, 100, 0.1); 62 | } 63 | & * { 64 | color: #515a6e; 65 | } 66 | .ivu-menu-item > i{ 67 | margin-right: 12px !important; 68 | } 69 | .ivu-menu-submenu > .ivu-menu > .ivu-menu-item > i { 70 | margin-right: 8px !important; 71 | } 72 | } 73 | 74 | .ivu-select-dropdown.ivu-dropdown-transfer{ 75 | max-height: 400px; 76 | } 77 | -------------------------------------------------------------------------------- /src/components/markdown/index.js: -------------------------------------------------------------------------------- 1 | import MarkdownEditor from './markdown.vue' 2 | export default MarkdownEditor 3 | -------------------------------------------------------------------------------- /src/components/markdown/markdown.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 63 | 64 | 77 | -------------------------------------------------------------------------------- /src/components/parent-view/index.js: -------------------------------------------------------------------------------- 1 | import ParentView from './parent-view.vue' 2 | export default ParentView 3 | -------------------------------------------------------------------------------- /src/components/parent-view/parent-view.vue: -------------------------------------------------------------------------------- 1 | 4 | 9 | -------------------------------------------------------------------------------- /src/components/paste-editor/index.js: -------------------------------------------------------------------------------- 1 | import PasteEditor from './paste-editor.vue' 2 | export default PasteEditor 3 | -------------------------------------------------------------------------------- /src/components/paste-editor/paste-editor.less: -------------------------------------------------------------------------------- 1 | .paste-editor-wrapper{ 2 | width: 100%; 3 | height: 100%; 4 | border: 1px dashed gainsboro; 5 | textarea.textarea-el{ 6 | width: 100%; 7 | height: 100%; 8 | } 9 | .CodeMirror{ 10 | height: 100%; 11 | padding: 0; 12 | .CodeMirror-code div .CodeMirror-line > span > span.cm-tab{ 13 | &::after{ 14 | content: '→'; 15 | color: #BFBFBF; 16 | } 17 | } 18 | } 19 | .first-row{ 20 | font-weight: 700; 21 | font-size: 14px; 22 | } 23 | .incorrect-row{ 24 | background: #F5CBD1; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/components/paste-editor/plugins/placeholder.js: -------------------------------------------------------------------------------- 1 | export default (codemirror) => { 2 | (function (mod) { 3 | mod(codemirror) 4 | })(function (CodeMirror) { 5 | CodeMirror.defineOption('placeholder', '', function (cm, val, old) { 6 | var prev = old && old !== CodeMirror.Init 7 | if (val && !prev) { 8 | cm.on('blur', onBlur) 9 | cm.on('change', onChange) 10 | cm.on('swapDoc', onChange) 11 | onChange(cm) 12 | } else if (!val && prev) { 13 | cm.off('blur', onBlur) 14 | cm.off('change', onChange) 15 | cm.off('swapDoc', onChange) 16 | clearPlaceholder(cm) 17 | var wrapper = cm.getWrapperElement() 18 | wrapper.className = wrapper.className.replace(' CodeMirror-empty', '') 19 | } 20 | 21 | if (val && !cm.hasFocus()) onBlur(cm) 22 | }) 23 | 24 | function clearPlaceholder (cm) { 25 | if (cm.state.placeholder) { 26 | cm.state.placeholder.parentNode.removeChild(cm.state.placeholder) 27 | cm.state.placeholder = null 28 | } 29 | } 30 | function setPlaceholder (cm) { 31 | clearPlaceholder(cm) 32 | var elt = cm.state.placeholder = document.createElement('pre') 33 | elt.style.cssText = 'height: 0; overflow: visible; color: #80848f;' 34 | elt.style.direction = cm.getOption('direction') 35 | elt.className = 'CodeMirror-placeholder' 36 | var placeHolder = cm.getOption('placeholder') 37 | if (typeof placeHolder === 'string') placeHolder = document.createTextNode(placeHolder) 38 | elt.appendChild(placeHolder) 39 | cm.display.lineSpace.insertBefore(elt, cm.display.lineSpace.firstChild) 40 | } 41 | 42 | function onBlur (cm) { 43 | if (isEmpty(cm)) setPlaceholder(cm) 44 | } 45 | function onChange (cm) { 46 | let wrapper = cm.getWrapperElement() 47 | let empty = isEmpty(cm) 48 | wrapper.className = wrapper.className.replace(' CodeMirror-empty', '') + (empty ? ' CodeMirror-empty' : '') 49 | 50 | if (empty) setPlaceholder(cm) 51 | else clearPlaceholder(cm) 52 | } 53 | 54 | function isEmpty (cm) { 55 | return (cm.lineCount() === 1) && (cm.getLine(0) === '') 56 | } 57 | }) 58 | } 59 | -------------------------------------------------------------------------------- /src/components/public/copyright.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | -------------------------------------------------------------------------------- /src/components/public/editor.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 96 | 97 | -------------------------------------------------------------------------------- /src/components/split-pane/index.css: -------------------------------------------------------------------------------- 1 | .ivu-split-wrapper { 2 | position: relative; 3 | width: 100%; 4 | height: 100%; 5 | } 6 | .ivu-split-pane { 7 | position: absolute; 8 | } 9 | .ivu-split-pane.left-pane, 10 | .ivu-split-pane.right-pane { 11 | top: 0px; 12 | bottom: 0px; 13 | } 14 | .ivu-split-pane.left-pane { 15 | left: 0px; 16 | } 17 | .ivu-split-pane.right-pane { 18 | right: 0px; 19 | } 20 | .ivu-split-pane.top-pane, 21 | .ivu-split-pane.bottom-pane { 22 | left: 0px; 23 | right: 0px; 24 | } 25 | .ivu-split-pane.top-pane { 26 | top: 0px; 27 | } 28 | .ivu-split-pane.bottom-pane { 29 | bottom: 0px; 30 | } 31 | .ivu-split-trigger-con { 32 | position: absolute; 33 | transform: translate(-50%, -50%); 34 | z-index: 10; 35 | } 36 | .ivu-split-trigger-bar-con { 37 | position: absolute; 38 | overflow: hidden; 39 | } 40 | .ivu-split-trigger-bar-con.vertical { 41 | left: 1px; 42 | top: 50%; 43 | height: 32px; 44 | transform: translate(0, -50%); 45 | } 46 | .ivu-split-trigger-bar-con.horizontal { 47 | left: 50%; 48 | top: 1px; 49 | width: 32px; 50 | transform: translate(-50%, 0); 51 | } 52 | .ivu-split-trigger-vertical { 53 | width: 6px; 54 | height: 100%; 55 | background: #F8F8F9; 56 | box-shadow: 0 0 4px 0 rgba(28, 36, 56, 0.4); 57 | cursor: col-resize; 58 | } 59 | .ivu-split-trigger-vertical .ivu-split-trigger-bar { 60 | width: 4px; 61 | height: 1px; 62 | background: rgba(23, 35, 61, 0.25); 63 | float: left; 64 | margin-top: 3px; 65 | } 66 | .ivu-split-trigger-horizontal { 67 | height: 6px; 68 | width: 100%; 69 | background: #F8F8F9; 70 | box-shadow: 0 0 4px 0 rgba(28, 36, 56, 0.4); 71 | cursor: row-resize; 72 | } 73 | .ivu-split-trigger-horizontal .ivu-split-trigger-bar { 74 | height: 4px; 75 | width: 1px; 76 | background: rgba(23, 35, 61, 0.25); 77 | float: left; 78 | margin-right: 3px; 79 | } 80 | .ivu-split-horizontal .ivu-split-trigger-con { 81 | top: 50%; 82 | height: 100%; 83 | width: 0; 84 | } 85 | .ivu-split-vertical .ivu-split-trigger-con { 86 | left: 50%; 87 | height: 0; 88 | width: 100%; 89 | } 90 | .ivu-split .no-select { 91 | -webkit-touch-callout: none; 92 | -webkit-user-select: none; 93 | -khtml-user-select: none; 94 | -moz-user-select: none; 95 | -ms-user-select: none; 96 | user-select: none; 97 | } 98 | -------------------------------------------------------------------------------- /src/components/split-pane/index.js: -------------------------------------------------------------------------------- 1 | import Split from './split.vue' 2 | export default Split 3 | -------------------------------------------------------------------------------- /src/components/split-pane/index.less: -------------------------------------------------------------------------------- 1 | @split-prefix-cls: ~"ivu-split"; 2 | @box-shadow: 0 0 4px 0 rgba(28, 36, 56, 0.4); 3 | @trigger-bar-background: rgba(23, 35, 61, 0.25); 4 | @trigger-background: #F8F8F9; 5 | @trigger-width: 6px; 6 | @trigger-bar-width: 4px; 7 | @trigger-bar-offset: (@trigger-width - @trigger-bar-width) / 2; 8 | @trigger-bar-interval: 3px; 9 | @trigger-bar-weight: 1px; 10 | @trigger-bar-con-height: (@trigger-bar-weight + @trigger-bar-interval) * 8; 11 | 12 | .@{split-prefix-cls}{ 13 | &-wrapper{ 14 | position: relative; 15 | width: 100%; 16 | height: 100%; 17 | } 18 | &-pane{ 19 | position: absolute; 20 | &.left-pane, &.right-pane{ 21 | top: 0px; 22 | bottom: 0px; 23 | } 24 | &.left-pane{ 25 | left: 0px; 26 | } 27 | &.right-pane{ 28 | right: 0px; 29 | } 30 | &.top-pane, &.bottom-pane{ 31 | left: 0px; 32 | right: 0px; 33 | } 34 | &.top-pane{ 35 | top: 0px; 36 | } 37 | &.bottom-pane{ 38 | bottom: 0px; 39 | } 40 | } 41 | &-trigger{ 42 | &-con{ 43 | position: absolute; 44 | transform: translate(-50%, -50%); 45 | z-index: 10; 46 | } 47 | &-bar-con{ 48 | position: absolute; 49 | overflow: hidden; 50 | &.vertical{ 51 | left: @trigger-bar-offset; 52 | top: 50%; 53 | height: @trigger-bar-con-height; 54 | transform: translate(0, -50%); 55 | } 56 | &.horizontal{ 57 | left: 50%; 58 | top: @trigger-bar-offset; 59 | width: @trigger-bar-con-height; 60 | transform: translate(-50%, 0); 61 | } 62 | } 63 | &-vertical{ 64 | width: @trigger-width; 65 | height: 100%; 66 | background: @trigger-background; 67 | box-shadow: @box-shadow; 68 | cursor: col-resize; 69 | .@{split-prefix-cls}-trigger-bar{ 70 | width: @trigger-bar-width; 71 | height: 1px; 72 | background: @trigger-bar-background; 73 | float: left; 74 | margin-top: @trigger-bar-interval; 75 | } 76 | } 77 | &-horizontal{ 78 | height: @trigger-width; 79 | width: 100%; 80 | background: @trigger-background; 81 | box-shadow: @box-shadow; 82 | cursor: row-resize; 83 | .@{split-prefix-cls}-trigger-bar{ 84 | height: @trigger-bar-width; 85 | width: 1px; 86 | background: @trigger-bar-background; 87 | float: left; 88 | margin-right: @trigger-bar-interval; 89 | } 90 | } 91 | } 92 | &-horizontal{ 93 | .@{split-prefix-cls}-trigger-con{ 94 | top: 50%; 95 | height: 100%; 96 | width: 0; 97 | } 98 | } 99 | &-vertical{ 100 | .@{split-prefix-cls}-trigger-con{ 101 | left: 50%; 102 | height: 0; 103 | width: 100%; 104 | } 105 | } 106 | .no-select{ 107 | -webkit-touch-callout: none; 108 | -webkit-user-select: none; 109 | -khtml-user-select: none; 110 | -moz-user-select: none; 111 | -ms-user-select: none; 112 | user-select: none; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/components/split-pane/trigger.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 40 | 41 | 44 | -------------------------------------------------------------------------------- /src/components/tables/edit.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 46 | 47 | 76 | -------------------------------------------------------------------------------- /src/components/tables/handle-btns.js: -------------------------------------------------------------------------------- 1 | const btns = { 2 | delete: (h, params, vm) => { 3 | return h('Poptip', { 4 | props: { 5 | confirm: true, 6 | title: '你确定要删除吗?' 7 | }, 8 | on: { 9 | 'on-ok': () => { 10 | vm.$emit('on-delete', params) 11 | vm.$emit('input', params.tableData.filter((item, index) => index !== params.row.initRowIndex)) 12 | } 13 | } 14 | }, [ 15 | h('Button', { 16 | props: { 17 | type: 'text', 18 | ghost: true 19 | } 20 | }, [ 21 | h('Icon', { 22 | props: { 23 | type: 'md-trash', 24 | size: 18, 25 | color: '#000000' 26 | } 27 | }) 28 | ]) 29 | ]) 30 | } 31 | } 32 | 33 | export default btns 34 | -------------------------------------------------------------------------------- /src/components/tables/index.js: -------------------------------------------------------------------------------- 1 | import Tables from './tables.vue' 2 | export default Tables 3 | -------------------------------------------------------------------------------- /src/components/tables/index.less: -------------------------------------------------------------------------------- 1 | .search-con{ 2 | padding: 5px 0; 3 | .search{ 4 | &-col{ 5 | display: inline-block; 6 | width: 200px; 7 | } 8 | &-input{ 9 | display: inline-block; 10 | width: 200px; 11 | margin-left: 2px; 12 | } 13 | &-btn{ 14 | margin-left: 2px; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/config/index.js: -------------------------------------------------------------------------------- 1 | export default { 2 | /** 3 | * @description token在Cookie中存储的天数,默认1天 4 | */ 5 | cookieExpires: 7, 6 | /** 7 | * @description 是否使用国际化,默认为false 8 | * 如果不使用,则需要在路由中给需要在菜单中展示的路由设置meta: {title: 'xxx'} 9 | * 用来在菜单中显示文字 10 | */ 11 | useI18n: true, 12 | /** 13 | * @description api请求基础路径 14 | */ 15 | baseUrl: { 16 | // dev: 'https://www.easy-mock.com/mock/5add9213ce4d0e69998a6f51/iview-admin/', 17 | // dev: 'http://172.16.0.223:9800/', 18 | dev: '', 19 | pro: '/api/' 20 | }, 21 | domainName: { 22 | // dev: 'https://www.easy-mock.com/mock/5add9213ce4d0e69998a6f51/iview-admin/', 23 | // dev: 'http://172.16.0.223:9800/', 24 | dev: 'demo.opendevops.cn', 25 | pro: window.location.host 26 | }, 27 | isHttps: 'https:' == document.location.protocol ? true : false, 28 | /** 29 | * @description 默认打开的首页的路由name值,默认为home 30 | */ 31 | homeName: 'home', 32 | /** 33 | * @description 需要加载的插件 34 | */ 35 | plugin: { 36 | 'error-store': { 37 | showInHeader: false, // 设为false后不会在顶部显示错误日志徽标 38 | developmentOff: true // 设为true后在开发环境不会收集错误信息,方便开发中排查错误 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /src/directive/directives.js: -------------------------------------------------------------------------------- 1 | import { on } from '@/libs/tools' 2 | const directives = { 3 | draggable: { 4 | inserted: (el, binding, vnode) => { 5 | let triggerDom = document.querySelector(binding.value.trigger) 6 | triggerDom.style.cursor = 'move' 7 | let bodyDom = document.querySelector(binding.value.body) 8 | let pageX = 0 9 | let pageY = 0 10 | let transformX = 0 11 | let transformY = 0 12 | let canMove = false 13 | const handleMousedown = e => { 14 | let transform = /\(.*\)/.exec(bodyDom.style.transform) 15 | if (transform) { 16 | transform = transform[0].slice(1, transform[0].length - 1) 17 | let splitxy = transform.split('px, ') 18 | transformX = parseFloat(splitxy[0]) 19 | transformY = parseFloat(splitxy[1].split('px')[0]) 20 | } 21 | pageX = e.pageX 22 | pageY = e.pageY 23 | canMove = true 24 | } 25 | const handleMousemove = e => { 26 | let xOffset = e.pageX - pageX + transformX 27 | let yOffset = e.pageY - pageY + transformY 28 | if (canMove) bodyDom.style.transform = `translate(${xOffset}px, ${yOffset}px)` 29 | } 30 | const handleMouseup = e => { 31 | canMove = false 32 | } 33 | on(triggerDom, 'mousedown', handleMousedown) 34 | on(document, 'mousemove', handleMousemove) 35 | on(document, 'mouseup', handleMouseup) 36 | }, 37 | update: (el, binding, vnode) => { 38 | if (!binding.value.recover) return 39 | let bodyDom = document.querySelector(binding.value.body) 40 | bodyDom.style.transform = '' 41 | } 42 | } 43 | } 44 | 45 | export default directives 46 | -------------------------------------------------------------------------------- /src/directive/index.js: -------------------------------------------------------------------------------- 1 | import directive from './directives' 2 | 3 | const importDirective = Vue => { 4 | /** 5 | * 拖拽指令 v-draggable="options" 6 | * options = { 7 | * trigger: /这里传入作为拖拽触发器的CSS选择器/, 8 | * body: /这里传入需要移动容器的CSS选择器/, 9 | * recover: /拖动结束之后是否恢复到原来的位置/ 10 | * } 11 | */ 12 | Vue.directive('draggable', directive.draggable) 13 | } 14 | 15 | export default importDirective 16 | -------------------------------------------------------------------------------- /src/index.less: -------------------------------------------------------------------------------- 1 | @import '~view-design/src/styles/index.less'; 2 | 3 | @menu-dark-title: #001529; 4 | @menu-dark-active-bg: #000c17; 5 | @layout-sider-background: #001529; 6 | // @primary-color: #2fb141; 7 | -------------------------------------------------------------------------------- /src/libs/api.request.js: -------------------------------------------------------------------------------- 1 | import HttpRequest from '@/libs/axios' 2 | import config from '@/config' 3 | const baseUrl = process.env.NODE_ENV === 'development' ? config.baseUrl.dev : config.baseUrl.pro 4 | 5 | const axios = new HttpRequest(baseUrl) 6 | export default axios 7 | -------------------------------------------------------------------------------- /src/locale/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueI18n from 'vue-i18n' 3 | import { localRead } from '@/libs/util' 4 | import customZhCn from './lang/zh-CN' 5 | import customZhTw from './lang/zh-TW' 6 | import customEnUs from './lang/en-US' 7 | import zhCnLocale from 'view-design/src/locale/lang/zh-CN' 8 | import enUsLocale from 'view-design/src/locale/lang/en-US' 9 | import zhTwLocale from 'view-design/src/locale/lang/zh-TW' 10 | 11 | Vue.use(VueI18n) 12 | 13 | // 自动根据浏览器系统语言设置语言 14 | const navLang = navigator.language 15 | const localLang = (navLang === 'zh-CN' || navLang === 'en-US') ? navLang : false 16 | let lang = localLang || localRead('local') || 'zh-CN' 17 | 18 | Vue.config.lang = lang 19 | 20 | // vue-i18n 6.x+写法 21 | Vue.locale = () => {} 22 | const messages = { 23 | 'zh-CN': Object.assign(zhCnLocale, customZhCn), 24 | 'zh-TW': Object.assign(zhTwLocale, customZhTw), 25 | 'en-US': Object.assign(enUsLocale, customEnUs) 26 | } 27 | const i18n = new VueI18n({ 28 | locale: lang, 29 | messages 30 | }) 31 | 32 | export default i18n 33 | 34 | // vue-i18n 5.x写法 35 | // Vue.locale('zh-CN', Object.assign(zhCnLocale, customZhCn)) 36 | // Vue.locale('en-US', Object.assign(zhTwLocale, customZhTw)) 37 | // Vue.locale('zh-TW', Object.assign(enUsLocale, customEnUs)) 38 | -------------------------------------------------------------------------------- /src/locale/lang/en-US.js: -------------------------------------------------------------------------------- 1 | export default { 2 | home: 'Home', 3 | components: 'Components', 4 | count_to_page: 'Count-to', 5 | tables_page: 'Table', 6 | split_pane_page: 'Split-pane', 7 | markdown_page: 'Markdown-editor', 8 | editor_page: 'Rich-Text-Editor', 9 | icons_page: 'Custom-icon', 10 | img_cropper_page: 'Image-editor', 11 | update: 'Update', 12 | doc: 'Document', 13 | join_page: 'QQ Group', 14 | update_table_page: 'Update .CSV', 15 | update_paste_page: 'Paste Table Data', 16 | multilevel: 'multilevel', 17 | directive_page: 'Directive', 18 | level_1: 'Level-1', 19 | level_2: 'Level-2', 20 | level_2_1: 'Level-2-1', 21 | level_2_3: 'Level-2-3', 22 | level_2_2: 'Level-2-2', 23 | level_2_2_1: 'Level-2-2-1', 24 | excel: 'Excel', 25 | 'upload-excel': 'Upload Excel', 26 | 'export-excel': 'Export Excel', 27 | tools_methods_page: 'Tools Methods', 28 | drag_list_page: 'Drag-list', 29 | i18n_page: 'Internationalization', 30 | modalTitle: 'Modal Title', 31 | content: 'This is the modal box content.', 32 | buttonText: 'Show Modal', 33 | 'i18n-tip': 'Note: Only this page is multi-language, other pages do not add language content to the multi-language package.', 34 | error_store_page: 'Error Collection', 35 | error_logger_page: 'Error Logger' 36 | } 37 | -------------------------------------------------------------------------------- /src/locale/lang/zh-TW.js: -------------------------------------------------------------------------------- 1 | export default { 2 | home: '首頁', 3 | components: '组件', 4 | count_to_page: '数字渐变', 5 | tables_page: '多功能表格', 6 | split_pane_page: '分割窗口', 7 | markdown_page: 'Markdown編輯器', 8 | editor_page: '富文本編輯器', 9 | icons_page: '自定義圖標', 10 | img_cropper_page: '圖片編輯器', 11 | update: '上傳數據', 12 | join_page: 'QQ群', 13 | doc: '文檔', 14 | update_table_page: '上傳CSV文件', 15 | update_paste_page: '粘貼表格數據', 16 | multilevel: '多级菜单', 17 | directive_page: '指令', 18 | level_1: 'Level-1', 19 | level_2: 'Level-2', 20 | level_2_1: 'Level-2-1', 21 | level_2_3: 'Level-2-3', 22 | level_2_2: 'Level-2-2', 23 | level_2_2_1: 'Level-2-2-1', 24 | excel: 'Excel', 25 | 'upload-excel': '上傳excel', 26 | 'export-excel': '導出excel', 27 | tools_methods_page: '工具函數', 28 | drag_list_page: '拖拽列表', 29 | i18n_page: '多語言', 30 | modalTitle: '模態框題目', 31 | content: '這是模態框內容', 32 | buttonText: '顯示模態框', 33 | 'i18n-tip': '注:僅此頁做了多語言,其他頁面沒有在多語言包中添加語言內容', 34 | error_store_page: '錯誤收集', 35 | error_logger_page: '錯誤日誌' 36 | } 37 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | // The Vue build version to load with the `import` command 2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias. 3 | import Vue from 'vue' 4 | import App from './App' 5 | import router from './router' 6 | import store from './store' 7 | // import iView from 'iview' 8 | import ViewUI from 'view-design' 9 | import i18n from '@/locale' 10 | import config from '@/config' 11 | import importDirective from '@/directive' 12 | import installPlugin from '@/plugin' 13 | // import 'iview/dist/styles/iview.css' 14 | import 'view-design/dist/styles/iview.css' 15 | import './index.less' 16 | import '@/assets/icons/iconfont.css' 17 | import VueClipboard from 'vue-clipboard2' 18 | 19 | Vue.use(VueClipboard) 20 | // 实际打包时应该不引入mock 21 | /* eslint-disable */ 22 | // if (process.env.NODE_ENV !== 'production') require('@/mock') 23 | 24 | Vue.use(ViewUI, { 25 | i18n: (key, value) => i18n.t(key, value) 26 | }) 27 | /** 28 | * @description 注册admin内置插件 29 | */ 30 | installPlugin(Vue) 31 | /** 32 | * @description 生产环境关掉提示 33 | */ 34 | Vue.config.productionTip = false 35 | /** 36 | * @description 全局注册应用配置 37 | */ 38 | Vue.prototype.$config = config 39 | /** 40 | * 注册指令 41 | */ 42 | importDirective(Vue) 43 | 44 | /* eslint-disable no-new */ 45 | new Vue({ 46 | el: '#app', 47 | router, 48 | i18n, 49 | store, 50 | render: h => h(App) 51 | }) 52 | -------------------------------------------------------------------------------- /src/plugin/error-store/index.js: -------------------------------------------------------------------------------- 1 | import store from '@/store' 2 | export default { 3 | install (Vue, options) { 4 | if (options.developmentOff && process.env.NODE_ENV === 'development') return 5 | Vue.config.errorHandler = (error, vm, mes) => { 6 | let info = { 7 | type: 'script', 8 | code: 0, 9 | mes: error.message, 10 | url: window.location.href 11 | } 12 | Vue.nextTick(() => { 13 | store.dispatch('addErrorLog', info) 14 | }) 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/plugin/index.js: -------------------------------------------------------------------------------- 1 | import config from '@/config' 2 | const { plugin } = config 3 | 4 | export default (Vue) => { 5 | for (let name in plugin) { 6 | const value = plugin[name] 7 | Vue.use(require(`./${name}`).default, typeof value === 'object' ? value : undefined) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/router/before-close.js: -------------------------------------------------------------------------------- 1 | import { Modal } from 'view-design' 2 | 3 | const beforeClose = { 4 | before_close_normal: (resolve) => { 5 | Modal.confirm({ 6 | title: '确定要关闭这一页吗', 7 | onOk: () => { 8 | resolve(true) 9 | }, 10 | onCancel: () => { 11 | resolve(false) 12 | } 13 | }) 14 | } 15 | } 16 | 17 | export default beforeClose 18 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import { routes } from './routers' 4 | import store from '@/store' 5 | // import iView from 'iview' 6 | import ViewUI from 'view-design' 7 | import { getToken, setTitle, setToken } from '@/libs/util' 8 | 9 | Vue.use(Router) 10 | const router = new Router({ 11 | routes, 12 | mode: 'history' 13 | }) 14 | // const LOGIN_PAGE_NAME = 'login' 15 | 16 | router.beforeEach((to, from, next) => { 17 | to.meta.title && setTitle(to.meta.title) 18 | ViewUI.LoadingBar.start() 19 | const token = getToken() 20 | if (token) { 21 | if (!store.state.router.hasGetRules) { 22 | store.dispatch('authorization').then(rules => { 23 | store.dispatch('concatRoutes', rules).then(routers => { 24 | router.addRoutes(routers) 25 | next({ ...to, replace: true }) 26 | }).catch((err) => { 27 | // console.log(err) 28 | setToken('') 29 | next({ name: 'login' }) 30 | }) 31 | }).catch((err1) => { 32 | // console.log(err1) 33 | setToken('') 34 | next({ name: 'login' }) 35 | }) 36 | } else { 37 | next() 38 | } 39 | } else { 40 | if (to.name === 'login') next() 41 | else next({ name: 'login' }) 42 | } 43 | }) 44 | 45 | router.afterEach(to => { 46 | ViewUI.LoadingBar.finish() 47 | window.scrollTo(0, 0) 48 | }) 49 | 50 | export default router 51 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import createPersistedState from "vuex-persistedstate" 4 | 5 | import user from './module/user' 6 | import app from './module/app' 7 | import router from './module/router' 8 | 9 | Vue.use(Vuex) 10 | 11 | export default new Vuex.Store({ 12 | //解决Vuex持久化插件 把用户数据持久化 13 | plugins: [createPersistedState({ 14 | storage: window.sessionStorage, 15 | reducer(val) { 16 | return { 17 | //只储存state中的user 18 | user: val.user 19 | } 20 | } 21 | })], 22 | state: { 23 | // 24 | }, 25 | mutations: { 26 | // 27 | }, 28 | actions: { 29 | // 30 | }, 31 | modules: { 32 | user, 33 | app, 34 | router 35 | } 36 | }) 37 | -------------------------------------------------------------------------------- /src/store/module/router.js: -------------------------------------------------------------------------------- 1 | import { routes, routerMap } from '@/router/routers' 2 | import { getMenuByRouter } from '@/libs/util' 3 | 4 | const state = { 5 | routers: routes, 6 | hasGetRules: false 7 | } 8 | 9 | const getters = { 10 | menuList: state => getMenuByRouter(state.routers, 'all') 11 | 12 | } 13 | const mutations = { 14 | CONCAT_ROUTES (state, routerList) { 15 | state.routers = routerList.concat(routes) 16 | state.hasGetRules = true 17 | } 18 | } 19 | 20 | const getAccesRouterList = (routes, rules) => { 21 | return routes.filter(item => { 22 | if (rules[item.name]) { 23 | if (item.children) item.children = getAccesRouterList(item.children, rules) 24 | return true 25 | } else return false 26 | }) 27 | } 28 | 29 | const actions = { 30 | concatRoutes ({ commit }, rules) { 31 | return new Promise((resolve, reject) => { 32 | try { 33 | let routerList = [] 34 | // 如果全部是true 直接返回 35 | if (Object.entries(rules).every(item => item[1])) { 36 | routerList = routerMap 37 | } else { 38 | routerList = getAccesRouterList(routerMap, rules) 39 | } 40 | 41 | commit('CONCAT_ROUTES', routerList) 42 | resolve(routerList) 43 | } catch (err) { 44 | reject(err) 45 | } 46 | }) 47 | } 48 | } 49 | 50 | export default { 51 | state, 52 | getters, 53 | mutations, 54 | actions 55 | } 56 | -------------------------------------------------------------------------------- /src/view/cmdb/common/Api.vue: -------------------------------------------------------------------------------- 1 | 18 | 45 | -------------------------------------------------------------------------------- /src/view/cmdb/db/multiAdd.vue: -------------------------------------------------------------------------------- 1 | 20 | 83 | -------------------------------------------------------------------------------- /src/view/cmdb/server/multiAdd.vue: -------------------------------------------------------------------------------- 1 | 21 | 84 | -------------------------------------------------------------------------------- /src/view/cmdb/server_auth/Detail.vue: -------------------------------------------------------------------------------- 1 | 42 | 51 | -------------------------------------------------------------------------------- /src/view/cmdb/server_log/TtyLog.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 38 | 39 | -------------------------------------------------------------------------------- /src/view/cmdb/webssh/Console.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /src/view/cmdb/webssh/WebSSH.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 28 | -------------------------------------------------------------------------------- /src/view/cmdb/webssh/Xterm.js: -------------------------------------------------------------------------------- 1 | import { Terminal } from 'xterm' 2 | import * as fit from 'xterm/lib/addons/fit/fit' 3 | import * as attach from 'xterm/lib/addons/attach/attach' 4 | Terminal.applyAddon(fit) 5 | Terminal.applyAddon(attach) 6 | 7 | export default Terminal 8 | -------------------------------------------------------------------------------- /src/view/cmdb2/log_audit.vue: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /src/view/cmdb2/multi_add_server.vue: -------------------------------------------------------------------------------- 1 | 18 | 79 | -------------------------------------------------------------------------------- /src/view/cmdb2/web_ssh.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /src/view/cmdb2/webssh/Console.vue: -------------------------------------------------------------------------------- 1 | 4 | 75 | -------------------------------------------------------------------------------- /src/view/cmdb2/webssh/WebSSH.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 28 | -------------------------------------------------------------------------------- /src/view/cmdb2/webssh/Xterm.js: -------------------------------------------------------------------------------- 1 | import { Terminal } from 'xterm' 2 | import * as fit from 'xterm/lib/addons/fit/fit' 3 | import * as attach from 'xterm/lib/addons/attach/attach' 4 | Terminal.applyAddon(fit) 5 | Terminal.applyAddon(attach) 6 | 7 | export default Terminal 8 | -------------------------------------------------------------------------------- /src/view/components/drag-list/drag-list.vue: -------------------------------------------------------------------------------- 1 | 30 | 62 | 114 | -------------------------------------------------------------------------------- /src/view/components/editor/editor.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 30 | 31 | 34 | -------------------------------------------------------------------------------- /src/view/components/icons/icons.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 55 | 56 | 64 | -------------------------------------------------------------------------------- /src/view/components/markdown/markdown.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 21 | 22 | 25 | -------------------------------------------------------------------------------- /src/view/components/split-pane/split-pane.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 40 | 41 | 80 | -------------------------------------------------------------------------------- /src/view/components/tables/tables.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 68 | 69 | 72 | -------------------------------------------------------------------------------- /src/view/confd/project/Add.vue: -------------------------------------------------------------------------------- 1 | 20 | 84 | -------------------------------------------------------------------------------- /src/view/directive/directive.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 58 | 59 | 72 | -------------------------------------------------------------------------------- /src/view/domain-name/components/domain-detail.vue: -------------------------------------------------------------------------------- 1 | 53 | -------------------------------------------------------------------------------- /src/view/domain-name/domain-name-monitor.vue: -------------------------------------------------------------------------------- 1 | 8 | p 9 | 19 | 20 | 23 | -------------------------------------------------------------------------------- /src/view/error-page/403.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 20 | -------------------------------------------------------------------------------- /src/view/error-page/404.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 20 | -------------------------------------------------------------------------------- /src/view/error-page/500.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 20 | -------------------------------------------------------------------------------- /src/view/error-page/back-btn-group.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 39 | -------------------------------------------------------------------------------- /src/view/error-page/error-content.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 29 | -------------------------------------------------------------------------------- /src/view/error-page/error.less: -------------------------------------------------------------------------------- 1 | .error-page{ 2 | width: 100%; 3 | height: 100%; 4 | position: relative; 5 | background: #f8f8f9; 6 | .content-con{ 7 | width: 700px; 8 | height: 600px; 9 | position: absolute; 10 | left: 50%; 11 | top: 50%; 12 | transform: translate(-50%, -60%); 13 | img{ 14 | display: block; 15 | width: 100%; 16 | height: 100%; 17 | } 18 | .text-con{ 19 | position: absolute; 20 | left: 0px; 21 | top: 0px; 22 | h4{ 23 | position: absolute; 24 | left: 0px; 25 | top: 0px; 26 | font-size: 80px; 27 | font-weight: 700; 28 | color: #348EED; 29 | } 30 | h5{ 31 | position: absolute; 32 | width: 700px; 33 | left: 0px; 34 | top: 100px; 35 | font-size: 20px; 36 | font-weight: 700; 37 | color: #67647D; 38 | } 39 | } 40 | .back-btn-group{ 41 | position: absolute; 42 | right: 0px; 43 | bottom: 20px; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/view/error-store/error-store.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 36 | 37 | 40 | -------------------------------------------------------------------------------- /src/view/excel/common.less: -------------------------------------------------------------------------------- 1 | .margin-top-8{ 2 | margin-top: 8px; 3 | } 4 | .margin-top-10{ 5 | margin-top: 10px; 6 | } 7 | .margin-top-20{ 8 | margin-top: 20px; 9 | } 10 | .margin-left-10{ 11 | margin-left: 10px; 12 | } 13 | .margin-bottom-10{ 14 | margin-bottom: 10px; 15 | } 16 | .margin-bottom-100{ 17 | margin-bottom: 100px; 18 | } 19 | .margin-right-10{ 20 | margin-right: 10px; 21 | } 22 | .padding-left-6{ 23 | padding-left: 6px; 24 | } 25 | .padding-left-8{ 26 | padding-left: 5px; 27 | } 28 | .padding-left-10{ 29 | padding-left: 10px; 30 | } 31 | .padding-left-20{ 32 | padding-left: 20px; 33 | } 34 | .height-100{ 35 | height: 100%; 36 | } 37 | .height-120px{ 38 | height: 100px; 39 | } 40 | .height-200px{ 41 | height: 200px; 42 | } 43 | .height-492px{ 44 | height: 492px; 45 | } 46 | .height-460px{ 47 | height: 460px; 48 | } 49 | .line-gray{ 50 | height: 0; 51 | border-bottom: 2px solid #dcdcdc; 52 | } 53 | .notwrap{ 54 | word-break:keep-all; 55 | white-space:nowrap; 56 | overflow: hidden; 57 | text-overflow: ellipsis; 58 | } 59 | .padding-left-5{ 60 | padding-left: 10px; 61 | } 62 | [v-cloak]{ 63 | display: none; 64 | } -------------------------------------------------------------------------------- /src/view/excel/export-excel.vue: -------------------------------------------------------------------------------- 1 | 4 | 16 | 82 | -------------------------------------------------------------------------------- /src/view/i18n/i18n-page.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 40 | 41 | 51 | -------------------------------------------------------------------------------- /src/view/join-page.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 35 | 36 | 47 | -------------------------------------------------------------------------------- /src/view/k8s/app/ListDetail.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /src/view/k8s/project/ListDetail.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /src/view/k8s/publish/components/Console.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 33 | 34 | 56 | -------------------------------------------------------------------------------- /src/view/k8s/publish/components/handle.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /src/view/login/login.less: -------------------------------------------------------------------------------- 1 | .login{ 2 | width: 100%; 3 | height: 100%; 4 | background-image: url('../../assets/images/login-bg.jpg'); 5 | background-size: cover; 6 | background-position: center; 7 | position: relative; 8 | &-con{ 9 | position: absolute; 10 | right: 160px; 11 | top: 50%; 12 | transform: translateY(-60%); 13 | width: 300px; 14 | &-header{ 15 | font-size: 16px; 16 | font-weight: 300; 17 | text-align: center; 18 | padding: 30px 0; 19 | } 20 | .form-con{ 21 | padding: 10px 0 0; 22 | } 23 | .login-tip{ 24 | font-size: 10px; 25 | text-align: center; 26 | color: #c3c3c3; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/view/login/login.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 21 | 22 | 97 | 98 | 100 | -------------------------------------------------------------------------------- /src/view/multilevel/level-2-1.vue: -------------------------------------------------------------------------------- 1 | 4 | 9 | -------------------------------------------------------------------------------- /src/view/multilevel/level-2-2/level-3-1.vue: -------------------------------------------------------------------------------- 1 | 4 | 9 | -------------------------------------------------------------------------------- /src/view/multilevel/level-2-3.vue: -------------------------------------------------------------------------------- 1 | 4 | 9 | -------------------------------------------------------------------------------- /src/view/publish-store/publish-list.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 105 | -------------------------------------------------------------------------------- /src/view/publish-store/publish/components/Console.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 33 | 34 | 56 | -------------------------------------------------------------------------------- /src/view/publish-store/publish/components/QAInfo.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | -------------------------------------------------------------------------------- /src/view/publish-store/publish/components/handle.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /src/view/single-page/error-logger.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 88 | 89 | 92 | -------------------------------------------------------------------------------- /src/view/single-page/home/example.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 115 | -------------------------------------------------------------------------------- /src/view/single-page/home/index.js: -------------------------------------------------------------------------------- 1 | import home from './home.vue' 2 | export default home 3 | -------------------------------------------------------------------------------- /src/view/single-page/home/issuesinfo.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 38 | 39 | 47 | -------------------------------------------------------------------------------- /src/view/single-page/home/logininfo.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | 14 | 44 | -------------------------------------------------------------------------------- /src/view/single-page/home/taskinfo.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 39 | 40 | 48 | -------------------------------------------------------------------------------- /src/view/tasks-center/assets/resource-mg.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 50 | 51 | -------------------------------------------------------------------------------- /src/view/tasks-center/task-submit/asset-purchase-conf.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /src/view/tasks-center/task-submit/asset-purchase.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 17 | 18 | 21 | -------------------------------------------------------------------------------- /src/view/tasks-center/task-submit/k8s-node-add.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 17 | 18 | 21 | -------------------------------------------------------------------------------- /src/view/tools-methods/tools-methods.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 79 | 80 | 83 | -------------------------------------------------------------------------------- /src/view/update/update-paste.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 62 | 63 | 78 | -------------------------------------------------------------------------------- /src/view/update/update-table.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 47 | 48 | 56 | -------------------------------------------------------------------------------- /swagger-ui/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opendevops-cn/codo/b57acb97c17a36d94d26a9214bbc6c051ce081a4/swagger-ui/favicon-16x16.png -------------------------------------------------------------------------------- /swagger-ui/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opendevops-cn/codo/b57acb97c17a36d94d26a9214bbc6c051ce081a4/swagger-ui/favicon-32x32.png -------------------------------------------------------------------------------- /swagger-ui/oauth2-redirect.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 68 | -------------------------------------------------------------------------------- /swagger-ui/swagger-ui.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":[],"names":[],"mappings":"","file":"swagger-ui.css","sourceRoot":""} -------------------------------------------------------------------------------- /tests/e2e/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "cypress" 4 | ], 5 | "env": { 6 | "mocha": true, 7 | "cypress/globals": true 8 | }, 9 | "rules": { 10 | "strict": "off" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/e2e/plugins/index.js: -------------------------------------------------------------------------------- 1 | // https://docs.cypress.io/guides/guides/plugins-guide.html 2 | 3 | module.exports = (on, config) => Object.assign({}, config, { 4 | fixturesFolder: 'tests/e2e/fixtures', 5 | integrationFolder: 'tests/e2e/specs', 6 | screenshotsFolder: 'tests/e2e/screenshots', 7 | videosFolder: 'tests/e2e/videos', 8 | supportFile: 'tests/e2e/support/index.js' 9 | }) 10 | -------------------------------------------------------------------------------- /tests/e2e/specs/test.js: -------------------------------------------------------------------------------- 1 | // https://docs.cypress.io/api/introduction/api.html 2 | 3 | describe('My First Test', () => { 4 | it('Visits the app root url', () => { 5 | cy.visit('/') 6 | cy.contains('h1', 'Welcome to Your Vue.js App') 7 | }) 8 | }) 9 | -------------------------------------------------------------------------------- /tests/e2e/support/commands.js: -------------------------------------------------------------------------------- 1 | // *********************************************** 2 | // This example commands.js shows you how to 3 | // create various custom commands and overwrite 4 | // existing commands. 5 | // 6 | // For more comprehensive examples of custom 7 | // commands please read more here: 8 | // https://on.cypress.io/custom-commands 9 | // *********************************************** 10 | // 11 | // 12 | // -- This is a parent command -- 13 | // Cypress.Commands.add("login", (email, password) => { ... }) 14 | // 15 | // 16 | // -- This is a child command -- 17 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) 18 | // 19 | // 20 | // -- This is a dual command -- 21 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) 22 | // 23 | // 24 | // -- This is will overwrite an existing command -- 25 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) 26 | -------------------------------------------------------------------------------- /tests/e2e/support/index.js: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import './commands' 18 | 19 | // Alternatively you can use CommonJS syntax: 20 | // require('./commands') 21 | -------------------------------------------------------------------------------- /tests/unit/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | mocha: true 4 | }, 5 | rules: { 6 | 'import/no-extraneous-dependencies': 'off' 7 | } 8 | } -------------------------------------------------------------------------------- /tests/unit/HelloWorld.spec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai' 2 | import { shallow } from '@vue/test-utils' 3 | import HelloWorld from '@/components/HelloWorld.vue' 4 | 5 | describe('HelloWorld.vue', () => { 6 | it('renders props.msg when passed', () => { 7 | const msg = 'new message' 8 | const wrapper = shallow(HelloWorld, { 9 | propsData: { msg } 10 | }) 11 | expect(wrapper.text()).to.include(msg) 12 | }) 13 | }) 14 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | 3 | const resolve = dir => { 4 | return path.join(__dirname, dir) 5 | } 6 | 7 | // 项目部署基础 8 | // 默认情况下,我们假设你的应用将被部署在域的根目录下, 9 | // 例如:https://www.my-app.com/ 10 | // 默认:'/' 11 | // 如果您的应用程序部署在子路径中,则需要在这指定子路径 12 | // 例如:https://www.foobar.com/my-app/ 13 | // 需要将它改为'/my-app/' 14 | const BASE_URL = process.env.NODE_ENV === 'production' ? '/' : '/' 15 | 16 | module.exports = { 17 | // Project deployment base 18 | // By default we assume your app will be deployed at the root of a domain, 19 | // e.g. https://www.my-app.com/ 20 | // If your app is deployed at a sub-path, you will need to specify that 21 | // sub-path here. For example, if your app is deployed at 22 | // https://www.foobar.com/my-app/ 23 | // then change this to '/my-app/' 24 | baseUrl: BASE_URL, 25 | // tweak internal webpack configuration. 26 | // see https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md 27 | // 如果你不需要使用eslint,把lintOnSave设为false即可 28 | // lintOnSave: true, 29 | lintOnSave: process.env.NODE_ENV !== 'production', 30 | chainWebpack: config => { 31 | config.resolve.alias 32 | .set('@', resolve('src')) // key,value自行定义,比如.set('@@', resolve('src/components')) 33 | .set('_c', resolve('src/components')) 34 | }, 35 | // 打包时不生成.map文件 36 | productionSourceMap: true, 37 | // 这里写你调用接口的基础路径,来解决跨域,如果设置了代理,那你本地开发环境的axios的baseUrl要写为 '' ,即空字符串 38 | devServer: { 39 | // proxy: 'http://172.16.0.223:9800/' 40 | proxy: 'http://gw.opendevops.cn/api/' 41 | } 42 | } --------------------------------------------------------------------------------