create project
|
@ -0,0 +1,92 @@
|
|||
version: 2
|
||||
name: 阿里云test环境
|
||||
description: ""
|
||||
global:
|
||||
concurrent: 1
|
||||
param:
|
||||
- ref: secret_name
|
||||
name: ""
|
||||
value: '"jcce-aliyuncs"'
|
||||
required: false
|
||||
type: STRING
|
||||
hidden: false
|
||||
- ref: project_name
|
||||
name: ""
|
||||
value: '"kubex-frontend"'
|
||||
required: false
|
||||
type: STRING
|
||||
hidden: false
|
||||
trigger:
|
||||
webhook: gitlink@1.0.0
|
||||
event:
|
||||
- ref: create_tag
|
||||
ruleset:
|
||||
- param-ref: tag
|
||||
operator: EQ
|
||||
value: '""'
|
||||
ruleset-operator: AND
|
||||
workflow:
|
||||
- ref: start
|
||||
name: 开始
|
||||
task: start
|
||||
- ref: git_clone_0
|
||||
name: git clone
|
||||
task: git_clone@1.2.6
|
||||
input:
|
||||
ssh_key: ((test.gitlink_sshkey))
|
||||
remote_url: '"https://gitlink.org.cn/JointCloud/JCC-RIP.git"'
|
||||
ref: '"refs/heads/earth"'
|
||||
commit_id: '""'
|
||||
depth: 1
|
||||
needs:
|
||||
- start
|
||||
- ref: docker_image_build_0
|
||||
name: docker镜像构建
|
||||
task: docker_image_build@1.6.0
|
||||
input:
|
||||
docker_username: ((test.docker_user))
|
||||
docker_password: ((test.docker_password))
|
||||
image_name: '"registry.cn-hangzhou.aliyuncs.com/jcce/jcc-rip'
|
||||
image_tag: git_clone_0.commit_time
|
||||
registry_address: '"registry.cn-hangzhou.aliyuncs.com"'
|
||||
docker_build_path: git_clone_0.git_path
|
||||
workspace: git_clone_0.git_path
|
||||
image_clean: true
|
||||
image_push: true
|
||||
build_args: '""'
|
||||
needs:
|
||||
- shell_0
|
||||
- ref: end
|
||||
name: 结束
|
||||
task: end
|
||||
needs:
|
||||
- kubectl_deploy_0
|
||||
- ref: kubectl_deploy_0
|
||||
name: kubectl部署资源
|
||||
task: kubectl_deploy@1.1.0
|
||||
input:
|
||||
command: '"apply"'
|
||||
resource_file_path: git_clone_0.git_path + '/deploy/k8s/jcc-rip-frontend.yaml'
|
||||
certificate_authority_data: ((test.k8s_cad))
|
||||
server: '"https://47.92.39.128:6443"'
|
||||
client_certificate_data: ((test.k8s_ccd))
|
||||
client_key_data: ((test.k8s_ckd))
|
||||
hosts: '""'
|
||||
needs:
|
||||
- docker_image_build_0
|
||||
- ref: shell_0
|
||||
name: shell
|
||||
image: docker.jianmuhub.com/library/debian:buster-slim
|
||||
env:
|
||||
IMAGE_NAME: '"registry.cn-hangzhou.aliyuncs.com/jcce/jcc-rip"'
|
||||
IMAGE_TAG: git_clone_0.commit_time
|
||||
SECRET_NAME: global.secret_name
|
||||
PROJECT_NAME: global.project_name
|
||||
PROJECT_PATH: git_clone_0.git_path + '/deploy/k8s/'
|
||||
script:
|
||||
- cd ${PROJECT_PATH}
|
||||
- sed -i "s#image_name#${IMAGE_NAME}:${IMAGE_TAG}#" ${PROJECT_NAME}.yaml
|
||||
- sed -i "s#secret_name#${SECRET_NAME}#" ${PROJECT_NAME}.yaml
|
||||
- cat ${PROJECT_NAME}.yaml
|
||||
needs:
|
||||
- git_clone_0
|
|
@ -0,0 +1,7 @@
|
|||
# just a flag
|
||||
ENV = 'development'
|
||||
|
||||
# base api
|
||||
VUE_APP_BASE_API = '/jcc-ks'
|
||||
VUE_APP_FUNCTION_API = ''
|
||||
VUE_APP_PUBLIC_SOURCE_API = ''
|
|
@ -0,0 +1,8 @@
|
|||
# just a flag
|
||||
ENV = 'production'
|
||||
|
||||
# base api
|
||||
VUE_APP_BASE_API = '/jcc-ks'
|
||||
VUE_APP_FUNCTION_API = 'apis/v1'
|
||||
VUE_APP_PUBLIC_SOURCE_API = '/monitor'
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
build/*.js
|
||||
src/assets
|
||||
public
|
||||
dist
|
||||
src/icons/iconfont.js
|
|
@ -0,0 +1,198 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
parserOptions: {
|
||||
parser: 'babel-eslint',
|
||||
sourceType: 'module'
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
node: true,
|
||||
es6: true,
|
||||
},
|
||||
extends: ['plugin:vue/recommended', 'eslint:recommended'],
|
||||
|
||||
// add your custom rules here
|
||||
//it is base on https://github.com/vuejs/eslint-config-vue
|
||||
rules: {
|
||||
"vue/max-attributes-per-line": [2, {
|
||||
"singleline": 10,
|
||||
"multiline": {
|
||||
"max": 1,
|
||||
"allowFirstLine": false
|
||||
}
|
||||
}],
|
||||
"vue/singleline-html-element-content-newline": "off",
|
||||
"vue/multiline-html-element-content-newline":"off",
|
||||
"vue/name-property-casing": ["error", "PascalCase"],
|
||||
"vue/no-v-html": "off",
|
||||
'accessor-pairs': 2,
|
||||
'arrow-spacing': [2, {
|
||||
'before': true,
|
||||
'after': true
|
||||
}],
|
||||
'block-spacing': [2, 'always'],
|
||||
'brace-style': [2, '1tbs', {
|
||||
'allowSingleLine': true
|
||||
}],
|
||||
'camelcase': [0, {
|
||||
'properties': 'always'
|
||||
}],
|
||||
'comma-dangle': [2, 'never'],
|
||||
'comma-spacing': [2, {
|
||||
'before': false,
|
||||
'after': true
|
||||
}],
|
||||
'comma-style': [2, 'last'],
|
||||
'constructor-super': 2,
|
||||
'curly': [2, 'multi-line'],
|
||||
'dot-location': [2, 'property'],
|
||||
'eol-last': 2,
|
||||
'eqeqeq': ["error", "always", {"null": "ignore"}],
|
||||
'generator-star-spacing': [2, {
|
||||
'before': true,
|
||||
'after': true
|
||||
}],
|
||||
'handle-callback-err': [2, '^(err|error)$'],
|
||||
'indent': [2, 2, {
|
||||
'SwitchCase': 1
|
||||
}],
|
||||
'jsx-quotes': [2, 'prefer-single'],
|
||||
'key-spacing': [2, {
|
||||
'beforeColon': false,
|
||||
'afterColon': true
|
||||
}],
|
||||
'keyword-spacing': [2, {
|
||||
'before': true,
|
||||
'after': true
|
||||
}],
|
||||
'new-cap': [2, {
|
||||
'newIsCap': true,
|
||||
'capIsNew': false
|
||||
}],
|
||||
'new-parens': 2,
|
||||
'no-array-constructor': 2,
|
||||
'no-caller': 2,
|
||||
'no-console': 'off',
|
||||
'no-class-assign': 2,
|
||||
'no-cond-assign': 2,
|
||||
'no-const-assign': 2,
|
||||
'no-control-regex': 0,
|
||||
'no-delete-var': 2,
|
||||
'no-dupe-args': 2,
|
||||
'no-dupe-class-members': 2,
|
||||
'no-dupe-keys': 2,
|
||||
'no-duplicate-case': 2,
|
||||
'no-empty-character-class': 2,
|
||||
'no-empty-pattern': 2,
|
||||
'no-eval': 2,
|
||||
'no-ex-assign': 2,
|
||||
'no-extend-native': 2,
|
||||
'no-extra-bind': 2,
|
||||
'no-extra-boolean-cast': 2,
|
||||
'no-extra-parens': [2, 'functions'],
|
||||
'no-fallthrough': 2,
|
||||
'no-floating-decimal': 2,
|
||||
'no-func-assign': 2,
|
||||
'no-implied-eval': 2,
|
||||
'no-inner-declarations': [2, 'functions'],
|
||||
'no-invalid-regexp': 2,
|
||||
'no-irregular-whitespace': 2,
|
||||
'no-iterator': 2,
|
||||
'no-label-var': 2,
|
||||
'no-labels': [2, {
|
||||
'allowLoop': false,
|
||||
'allowSwitch': false
|
||||
}],
|
||||
'no-lone-blocks': 2,
|
||||
'no-mixed-spaces-and-tabs': 2,
|
||||
'no-multi-spaces': 2,
|
||||
'no-multi-str': 2,
|
||||
'no-multiple-empty-lines': [2, {
|
||||
'max': 1
|
||||
}],
|
||||
'no-native-reassign': 2,
|
||||
'no-negated-in-lhs': 2,
|
||||
'no-new-object': 2,
|
||||
'no-new-require': 2,
|
||||
'no-new-symbol': 2,
|
||||
'no-new-wrappers': 2,
|
||||
'no-obj-calls': 2,
|
||||
'no-octal': 2,
|
||||
'no-octal-escape': 2,
|
||||
'no-path-concat': 2,
|
||||
'no-proto': 2,
|
||||
'no-redeclare': 2,
|
||||
'no-regex-spaces': 2,
|
||||
'no-return-assign': [2, 'except-parens'],
|
||||
'no-self-assign': 2,
|
||||
'no-self-compare': 2,
|
||||
'no-sequences': 2,
|
||||
'no-shadow-restricted-names': 2,
|
||||
'no-spaced-func': 2,
|
||||
'no-sparse-arrays': 2,
|
||||
'no-this-before-super': 2,
|
||||
'no-throw-literal': 2,
|
||||
'no-trailing-spaces': 2,
|
||||
'no-undef': 2,
|
||||
'no-undef-init': 2,
|
||||
'no-unexpected-multiline': 2,
|
||||
'no-unmodified-loop-condition': 2,
|
||||
'no-unneeded-ternary': [2, {
|
||||
'defaultAssignment': false
|
||||
}],
|
||||
'no-unreachable': 2,
|
||||
'no-unsafe-finally': 2,
|
||||
'no-unused-vars': [2, {
|
||||
'vars': 'all',
|
||||
'args': 'none'
|
||||
}],
|
||||
'no-useless-call': 2,
|
||||
'no-useless-computed-key': 2,
|
||||
'no-useless-constructor': 2,
|
||||
'no-useless-escape': 0,
|
||||
'no-whitespace-before-property': 2,
|
||||
'no-with': 2,
|
||||
'one-var': [2, {
|
||||
'initialized': 'never'
|
||||
}],
|
||||
'operator-linebreak': [2, 'after', {
|
||||
'overrides': {
|
||||
'?': 'before',
|
||||
':': 'before'
|
||||
}
|
||||
}],
|
||||
'padded-blocks': [2, 'never'],
|
||||
'quotes': [2, 'single', {
|
||||
'avoidEscape': true,
|
||||
'allowTemplateLiterals': true
|
||||
}],
|
||||
'semi': [2, 'never'],
|
||||
'semi-spacing': [2, {
|
||||
'before': false,
|
||||
'after': true
|
||||
}],
|
||||
'space-before-blocks': [2, 'always'],
|
||||
'space-before-function-paren': [2, 'never'],
|
||||
'space-in-parens': [2, 'never'],
|
||||
'space-infix-ops': 2,
|
||||
'space-unary-ops': [2, {
|
||||
'words': true,
|
||||
'nonwords': false
|
||||
}],
|
||||
'spaced-comment': [2, 'always', {
|
||||
'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
|
||||
}],
|
||||
'template-curly-spacing': [2, 'never'],
|
||||
'use-isnan': 2,
|
||||
'valid-typeof': 2,
|
||||
'wrap-iife': [2, 'any'],
|
||||
'yield-star-spacing': [2, 'both'],
|
||||
'yoda': [2, 'never'],
|
||||
'prefer-const': 2,
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
|
||||
'object-curly-spacing': [2, 'always', {
|
||||
objectsInObjects: false
|
||||
}],
|
||||
'array-bracket-spacing': [2, 'never']
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
*.zip
|
||||
*.rar
|
||||
.VSCodeCounter
|
||||
|
||||
package-lock.json
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Log files
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
|
@ -0,0 +1,25 @@
|
|||
FROM node:16.20-alpine3.17 AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY . .
|
||||
COPY deploy/nginx/ /app/
|
||||
RUN npm install --registry=https://registry.npmmirror.com &&\
|
||||
npm run build:prod
|
||||
|
||||
FROM nginx:stable-alpine
|
||||
WORKDIR /app
|
||||
|
||||
#修改alpine源为上海交通大学
|
||||
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.sjtug.sjtu.edu.cn/g' /etc/apk/repositories && \
|
||||
apk update && \
|
||||
apk upgrade && \
|
||||
apk add --no-cache ca-certificates && update-ca-certificates && \
|
||||
apk add --update tzdata && \
|
||||
rm -rf /var/cache/apk/*
|
||||
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html/jcc-rip
|
||||
RUN rm /etc/nginx/conf.d/default.conf
|
||||
COPY deploy/nginx/default.conf /etc/nginx/conf.d/default.conf
|
||||
EXPOSE 80
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
45
README.md
|
@ -1,2 +1,45 @@
|
|||
# JCC-TASK
|
||||
# JCCE
|
||||
Thanks to KubeSphere and Harvester for providing back-end support for this system.
|
||||
## need node environment
|
||||
|
||||
## install dependencies
|
||||
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
### Commands for Compilation and Hot Reloading
|
||||
|
||||
```
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Production Environment Build Commands
|
||||
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
|
||||
```bash
|
||||
# build for test environment
|
||||
npm run build:stage
|
||||
|
||||
# build for production environment
|
||||
npm run build:prod
|
||||
```
|
||||
|
||||
## Advanced
|
||||
|
||||
```bash
|
||||
# preview the release environment effect
|
||||
npm run preview
|
||||
|
||||
# preview the release environment effect + static resource analysis
|
||||
npm run preview -- --report
|
||||
|
||||
# code format check
|
||||
npm run lint
|
||||
|
||||
# code format check and auto fix
|
||||
npm run lint -- --fix
|
||||
```
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
module.exports = {
|
||||
presets: [
|
||||
// https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app
|
||||
'@vue/cli-plugin-babel/preset'
|
||||
],
|
||||
'env': {
|
||||
'development': {
|
||||
// babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require().
|
||||
// This plugin can significantly increase the speed of hot updates, when you have a large number of pages.
|
||||
// https://panjiachen.github.io/vue-element-admin-site/guide/advanced/lazy-loading.html
|
||||
'plugins': ['dynamic-import-node']
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
const { run } = require('runjs')
|
||||
const chalk = require('chalk')
|
||||
const config = require('../vue.config.js')
|
||||
const rawArgv = process.argv.slice(2)
|
||||
const args = rawArgv.join(' ')
|
||||
|
||||
if (process.env.npm_config_preview || rawArgv.includes('--preview')) {
|
||||
const report = rawArgv.includes('--report')
|
||||
|
||||
run(`vue-cli-service build ${args}`)
|
||||
|
||||
const port = 9526
|
||||
const publicPath = config.publicPath
|
||||
|
||||
var connect = require('connect')
|
||||
var serveStatic = require('serve-static')
|
||||
const app = connect()
|
||||
|
||||
app.use(
|
||||
publicPath,
|
||||
serveStatic('./dist', {
|
||||
index: ['index.html', '/']
|
||||
})
|
||||
)
|
||||
|
||||
app.listen(port, function () {
|
||||
console.log(chalk.green(`> Preview at http://localhost:${port}${publicPath}`))
|
||||
if (report) {
|
||||
console.log(chalk.green(`> Report at http://localhost:${port}${publicPath}report.html`))
|
||||
}
|
||||
|
||||
})
|
||||
} else {
|
||||
run(`vue-cli-service build ${args}`)
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 10000,
|
||||
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
kind: Deployment
|
||||
apiVersion: apps/v1
|
||||
metadata:
|
||||
name: jcc-rip-frontend
|
||||
namespace: jcce-system
|
||||
labels:
|
||||
k8s-app: jcc-rip
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
k8s-app: jcc-rip
|
||||
template:
|
||||
metadata:
|
||||
name: jcc-rip
|
||||
labels:
|
||||
k8s-app: jcc-rip
|
||||
spec:
|
||||
imagePullSecrets:
|
||||
- name: secret_name
|
||||
containers:
|
||||
- name: jcc-rip
|
||||
image: image_name
|
||||
resources: {}
|
||||
imagePullPolicy: Always
|
||||
securityContext:
|
||||
privileged: false
|
||||
procMount: Default
|
||||
ports:
|
||||
- containerPort: 80
|
||||
volumeMounts: []
|
||||
volumes: []
|
||||
restartPolicy: Always
|
||||
terminationGracePeriodSeconds: 30
|
||||
dnsPolicy: ClusterFirst
|
||||
securityContext: {}
|
||||
schedulerName: default-scheduler
|
||||
strategy:
|
||||
type: RollingUpdate
|
||||
rollingUpdate:
|
||||
maxUnavailable: 25%
|
||||
maxSurge: 25%
|
||||
revisionHistoryLimit: 10
|
||||
progressDeadlineSeconds: 600
|
||||
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
namespace: jcce-system
|
||||
name: jcc-rip-service
|
||||
labels:
|
||||
k8s-service: jcc-rip
|
||||
spec:
|
||||
selector:
|
||||
k8s-app: jcc-rip
|
||||
ports:
|
||||
- name: web
|
||||
protocol: TCP
|
||||
port: 80
|
||||
targetPort: 80
|
||||
type: ClusterIP
|
|
@ -0,0 +1,55 @@
|
|||
upstream jcc-backend {
|
||||
server dev.jointcloud.net:443;
|
||||
}
|
||||
|
||||
upstream pcm-backend {
|
||||
server pcm-core-api:8999;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
|
||||
access_log /var/log/nginx/host.access.log main;
|
||||
error_log /var/log/nginx/error.log error;
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html/jcc-rip; #站点目录
|
||||
index index.html index.htm;
|
||||
}
|
||||
|
||||
#monitor项目
|
||||
location /monitor {
|
||||
alias /usr/share/nginx/html/jcc-rip/;
|
||||
try_files $uri $uri/ /monitor/index.html; #解决页面刷新404问题
|
||||
index index.html index.htm;
|
||||
autoindex on;
|
||||
}
|
||||
|
||||
location /pcm/ {
|
||||
proxy_http_version 1.1;
|
||||
proxy_pass http://pcm-backend/pcm/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
client_max_body_size 12288m;
|
||||
root html;
|
||||
index index.html index.htm;
|
||||
}
|
||||
|
||||
location /apis/ {
|
||||
proxy_http_version 1.1;
|
||||
proxy_pass https://jcc-backend/apis/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
client_max_body_size 12288m;
|
||||
root html;
|
||||
index index.html index.htm;
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
{
|
||||
"name": "jcce",
|
||||
"version": "4.4.0",
|
||||
"description": "",
|
||||
"author": "",
|
||||
"scripts": {
|
||||
"dev": "vue-cli-service serve",
|
||||
"lint": "eslint --ext .js,.vue src",
|
||||
"build:prod": "vue-cli-service build --mode production",
|
||||
"build:stage": "vue-cli-service build --mode staging",
|
||||
"preview": "node build/index.js --preview",
|
||||
"new": "plop",
|
||||
"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
|
||||
"test:unit": "jest --clearCache && vue-cli-service test:unit",
|
||||
"test:ci": "npm run lint && npm run test:unit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/helper-define-map": "^7.13.12",
|
||||
"@babel/helper-regex": "^7.10.5",
|
||||
"@jiaminghi/data-view": "^2.10.0",
|
||||
"@tweenjs/tween.js": "^18.6.4",
|
||||
"axios": "0.18.1",
|
||||
"clipboard": "2.0.4",
|
||||
"codemirror": "5.45.0",
|
||||
"core-js": "3.6.5",
|
||||
"driver.js": "0.9.5",
|
||||
"dropzone": "5.5.1",
|
||||
"echarts": "^5.0.0",
|
||||
"element-ui": "^2.13.2",
|
||||
"file-saver": "2.0.1",
|
||||
"flv.js": "^1.6.2",
|
||||
"fuse.js": "3.4.4",
|
||||
"is-svg": "^4.3.1",
|
||||
"js-cookie": "2.2.0",
|
||||
"jsonlint": "1.6.3",
|
||||
"jszip": "3.2.1",
|
||||
"less-loader": "^6.0.0",
|
||||
"levenary": "^1.1.1",
|
||||
"moment": "^2.29.1",
|
||||
"nanoid": "^1.0.2",
|
||||
"normalize.css": "7.0.0",
|
||||
"nprogress": "0.2.0",
|
||||
"path-to-regexp": "2.4.0",
|
||||
"proj4": "^2.8.1",
|
||||
"randomstring": "^1.2.1",
|
||||
"screenfull": "4.2.0",
|
||||
"script-loader": "0.7.2",
|
||||
"sortablejs": "1.8.4",
|
||||
"spark-md5": "^3.0.2",
|
||||
"vue": "2.6.10",
|
||||
"vue-codemirror": "^4.0.6",
|
||||
"vue-count-to": "1.0.13",
|
||||
"vue-dplayer": "^0.0.10",
|
||||
"vue-grid-layout": "^2.4.0",
|
||||
"vue-i18n": "^7.3.3",
|
||||
"vue-json-editor": "^1.4.3",
|
||||
"vue-router": "3.0.2",
|
||||
"vue-splitpane": "1.0.4",
|
||||
"vuedraggable": "^2.20.0",
|
||||
"vuex": "3.1.0",
|
||||
"xlsx": "0.14.1",
|
||||
"xterm": "^4.12.0",
|
||||
"xterm-addon-attach": "^0.6.0",
|
||||
"xterm-addon-fit": "^0.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "4.4.4",
|
||||
"@vue/cli-plugin-eslint": "4.4.4",
|
||||
"@vue/cli-plugin-unit-jest": "4.4.4",
|
||||
"@vue/cli-service": "4.4.4",
|
||||
"@vue/test-utils": "1.0.0-beta.29",
|
||||
"autoprefixer": "9.5.1",
|
||||
"babel-eslint": "10.1.0",
|
||||
"babel-jest": "23.6.0",
|
||||
"babel-plugin-dynamic-import-node": "2.3.3",
|
||||
"chalk": "2.4.2",
|
||||
"chokidar": "2.1.5",
|
||||
"connect": "3.6.6",
|
||||
"eslint": "6.7.2",
|
||||
"eslint-plugin-vue": "6.2.2",
|
||||
"filemanager-webpack-plugin": "^3.0.0-alpha.4",
|
||||
"html-webpack-plugin": "3.2.0",
|
||||
"husky": "^1.3.1",
|
||||
"less": "^4.1.1",
|
||||
"lint-staged": "8.1.5",
|
||||
"mockjs": "1.0.1-beta3",
|
||||
"plop": "2.3.0",
|
||||
"runjs": "4.3.2",
|
||||
"sass": "1.26.2",
|
||||
"sass-loader": "8.0.2",
|
||||
"script-ext-html-webpack-plugin": "2.1.3",
|
||||
"serve-static": "1.13.2",
|
||||
"svg-sprite-loader": "4.1.3",
|
||||
"svgo": "1.2.0",
|
||||
"uglifyjs-webpack-plugin": "^2.2.0",
|
||||
"vue-template-compiler": "2.6.10"
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions"
|
||||
],
|
||||
"bugs": {
|
||||
"url": "https://github.com/PanJiaChen/vue-element-admin/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.9",
|
||||
"npm": ">= 3.0.0"
|
||||
},
|
||||
"keywords": [
|
||||
"vue",
|
||||
"admin",
|
||||
"dashboard",
|
||||
"element-ui",
|
||||
"boilerplate",
|
||||
"admin-template",
|
||||
"management-system"
|
||||
],
|
||||
"license": "MIT",
|
||||
"lint-staged": {
|
||||
"src/**/*.{js,vue}": [
|
||||
"eslint --fix",
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "lint-staged"
|
||||
}
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/PanJiaChen/vue-element-admin.git"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
module.exports = {
|
||||
plugins: {
|
||||
autoprefixer: {}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="_层_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 36 38" style="enable-background:new 0 0 36 38;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:url(#SVGID_1_);}
|
||||
.st1{fill-rule:evenodd;clip-rule:evenodd;fill:url(#形状_6_拷贝_3_2_);}
|
||||
.st2{fill-rule:evenodd;clip-rule:evenodd;fill:url(#形状_6_拷贝_3_3_);}
|
||||
</style>
|
||||
<radialGradient id="SVGID_1_" cx="18.1244" cy="1032.4509" r="9.92" gradientTransform="matrix(1.8182 0 0 1.5085 -14.9171 -1535.1727)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" style="stop-color:#FFF76A;stop-opacity:0.5"/>
|
||||
<stop offset="1" style="stop-color:#FFE66A;stop-opacity:0"/>
|
||||
</radialGradient>
|
||||
<ellipse class="st0" cx="18" cy="22.9" rx="18" ry="15.1"/>
|
||||
<linearGradient id="形状_6_拷贝_3_2_" gradientUnits="userSpaceOnUse" x1="17.7698" y1="24.9024" x2="18.0223" y2="0.9229">
|
||||
<stop offset="0.2549" style="stop-color:#FFD153"/>
|
||||
<stop offset="1" style="stop-color:#FFD153;stop-opacity:0"/>
|
||||
</linearGradient>
|
||||
<path id="形状_6_拷贝_3" class="st1" d="M1.8,0L18,25L34.3,0"/>
|
||||
<linearGradient id="形状_6_拷贝_3_3_" gradientUnits="userSpaceOnUse" x1="17.8853" y1="18.3956" x2="18.0265" y2="4.9804">
|
||||
<stop offset="0.2644" style="stop-color:#FFFFFF"/>
|
||||
<stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0"/>
|
||||
</linearGradient>
|
||||
<path id="形状_6_拷贝_3_1_" class="st2" d="M8.9,4.5l9.1,14l9.1-14"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 200 200" style="enable-background:new 0 0 200 200;" xml:space="preserve">
|
||||
<path d="M131.2,28.5c1.4,0,2.4,1.1,2.4,2.4V169c0,1.4-1.1,2.4-2.4,2.4H68.8c-1.4,0-2.4-1.1-2.4-2.4V31c0-1.4,1.1-2.4,2.4-2.4H131.2
|
||||
M131.2,18.8H68.8c-6.7,0-12.2,5.4-12.2,12.2V169c0,6.7,5.4,12.2,12.2,12.2h62.4c6.7,0,12.2-5.4,12.2-12.2V31
|
||||
C143.3,24.2,137.9,18.8,131.2,18.8z"/>
|
||||
<path d="M79,54.8h42.9v9.7H79V54.8z M79,75.9h42.9v9.7H79V75.9z M94.4,128.3h10.2v10.2H94.4V128.3z M171.6,33.2h-20.6V43h20.6v118.3
|
||||
h-20.6v9.7h20.6c5.4,0,9.7-4.4,9.7-9.7V43C181.4,37.6,177,33.2,171.6,33.2z M29.7,33.2h20.6V43H29.7v118.3h20.6v9.7H29.7
|
||||
c-5.4,0-9.7-4.4-9.7-9.7V43C20,37.6,24.3,33.2,29.7,33.2z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 938 B |
After Width: | Height: | Size: 4.2 KiB |
|
@ -0,0 +1,31 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
<!-- 使用CDN的CSS文件 -->
|
||||
<% for (var i in htmlWebpackPlugin.options.cdn &&
|
||||
htmlWebpackPlugin.options.cdn.css) { %>
|
||||
<link rel="stylesheet" href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" />
|
||||
<% } %>
|
||||
|
||||
<!-- 使用CDN的JS文件 -->
|
||||
<% for (var i in htmlWebpackPlugin.options.cdn &&
|
||||
htmlWebpackPlugin.options.cdn.js) { %>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"
|
||||
></script>
|
||||
<% } %>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,151 @@
|
|||
{
|
||||
"message": {
|
||||
"china": "中文",
|
||||
"english": "English",
|
||||
"login": "登录r",
|
||||
"logout": "退出登录r",
|
||||
"back": "Back",
|
||||
"save": "Save",
|
||||
"cancel": "Cancel",
|
||||
"to": "To",
|
||||
"startDate": "Start Date",
|
||||
"endDate": "End Date",
|
||||
"search": "Search",
|
||||
"reset": "Reset",
|
||||
"count": "Count:",
|
||||
"create": "Create",
|
||||
"name": "Name",
|
||||
"confirm": "确定",
|
||||
"easyCreate": "快捷创建",
|
||||
"next": "下一步",
|
||||
"success": "操作成功",
|
||||
"before": "上一步",
|
||||
"pleaseInput": "请输入",
|
||||
"pleaseChoose": "请选择"
|
||||
},
|
||||
"menu": {
|
||||
"taskManagement": "Task Management",
|
||||
"taskList": "Task List",
|
||||
"jobTask": "作业任务",
|
||||
"strategyManagement": "策略管理r",
|
||||
"schedulingStrategy": "调度策略r",
|
||||
"warnStrategy": "告警策略r",
|
||||
"adapterManagement": "驱动器管理r",
|
||||
"adapterList": "驱动器列表r",
|
||||
"clusterManagement": "集群管理r",
|
||||
"resourceUsageTop": "资源中心使用TOP3r",
|
||||
"resourceCenter": "资源中心r",
|
||||
"scheduleStatus": "调度情况r",
|
||||
"messageList": "消息列表r",
|
||||
"alertNotification": "告警通知r",
|
||||
"hpcManagement": "超算管理",
|
||||
"hpcOverview": "超算概览r",
|
||||
"aiManagement": "智算管理",
|
||||
"autoStudy": "自动学习",
|
||||
"warnCenter": "告警中心",
|
||||
"warnList": "告警列表",
|
||||
"warnSet": "告警设置",
|
||||
"overview": "概览",
|
||||
"clusterNodes": "集群节点",
|
||||
"project": "项目",
|
||||
"storage": "存储",
|
||||
"workload": "工作负载",
|
||||
"containerNodes": "容器节点",
|
||||
"services": "服务",
|
||||
"containerManagement": "容器管理",
|
||||
"mainEngine": "主机",
|
||||
"virtualMachine": "虚拟机",
|
||||
"volume": "卷",
|
||||
"image": "镜像",
|
||||
"namespace": "命名空间",
|
||||
"virtualMachineMana": "虚拟机管理"
|
||||
},
|
||||
"check": {
|
||||
"input": "请输入",
|
||||
"select": "请选择",
|
||||
"inputInvalid": "名称格式不合法。字母开头,仅能包含小写字母、数字和-。",
|
||||
"requireSelect": "必选项"
|
||||
},
|
||||
"page": {
|
||||
"cloud": "cloud",
|
||||
"hpc": "hpc",
|
||||
"ai": "ai",
|
||||
"title": "JCCE",
|
||||
"JointDomainresourceflux": "Joint Domain resource flux",
|
||||
"task": "Task",
|
||||
"taskDescription": "Support for creating tasks that are interoperable and interconnected between different computing environments or hardware platforms, ensuring that each task can run independently on different computing environments or hardware platforms.",
|
||||
"taskName": "Task Name",
|
||||
"jobStatus": "Job Status",
|
||||
"policy": "Policy",
|
||||
"synergyStatus": "Synergy Status",
|
||||
"adapter": "Adapter",
|
||||
"cluster": "Cluster",
|
||||
"startTime": "Start Time",
|
||||
"more": "More",
|
||||
"participantName": "Participant Name",
|
||||
"calculationType":"计算类型",
|
||||
"stackName":"技术栈名称",
|
||||
"stackVersion":"技术栈版本号",
|
||||
"address":"地址",
|
||||
"creationTime":"创建时间",
|
||||
"delete":"删除",
|
||||
"associatedCluster":"已关联集群",
|
||||
"description":"description",
|
||||
"edit":"编辑",
|
||||
"total":"总条数",
|
||||
"addAdapter":"新增驱动器",
|
||||
"updateAdapter": "编辑驱动器",
|
||||
"bindCluster":"绑定集群",
|
||||
"clusterAssociation":"集群关联",
|
||||
"adapterSetting":"驱动器设置",
|
||||
"adapterDesc":"支持用户上传新的PCM适配技术栈,并通过当前功能,进行适配绑定",
|
||||
"clusterDesc": "对多集群以及每个集群的基础资源, 服务组件和应用资源等的统一管理",
|
||||
"deleteWarn":"您确定要删除吗",
|
||||
"deleteSuccess":"删除成功",
|
||||
"viewDetail": "View Detail",
|
||||
"cpType": "计算类型r",
|
||||
"taskType": "任务类型r",
|
||||
"createApplication": "创建容器应用r",
|
||||
"createJob": "创建容器定时任务r",
|
||||
"memory": "内存",
|
||||
"storage": "存储",
|
||||
"distributedTask": "已下发任务",
|
||||
"reservedTask": "已保留任务",
|
||||
"errorTask": "错误任务",
|
||||
"reason": "原因",
|
||||
"eventDetail": "事件详情",
|
||||
"updateDate": "更新时间",
|
||||
"clusterName": "集群名",
|
||||
"kbVersion": "kubernetes版本",
|
||||
"createTime": "创建时间",
|
||||
"classification": "分类r",
|
||||
"vmCluster": "虚拟机集群",
|
||||
"containerCluster": "容器集群",
|
||||
"hpcDomain": "超算域",
|
||||
"job": "作业",
|
||||
"ClusterSum": "集群总数",
|
||||
"AdapterSum": "驱动器总数",
|
||||
"TaskSum": "任务总数",
|
||||
"dispatchAdapter": "分配驱动器",
|
||||
"strategySelected": "调度策略选择",
|
||||
"updateCluster": "编辑集群",
|
||||
"addCluster": "新增集群",
|
||||
"chooseAdapter": "选择适配器",
|
||||
"name": "名称",
|
||||
"monitorAddress": "监控地址",
|
||||
"version": "版本号",
|
||||
"otherName": "别名",
|
||||
"area": "区域",
|
||||
"projectId": "项目Id",
|
||||
"tag": "标签",
|
||||
"authType": "认证方式",
|
||||
"skak": "SK/AK认证",
|
||||
"passAuth": "密码认证",
|
||||
"tokenAuth": "Token认证",
|
||||
"userName": "用户名",
|
||||
"password": "密码",
|
||||
"createVirtualmachine": "创建虚拟机",
|
||||
"createHpcbase": "创建超算基础模板",
|
||||
"createAibase": "创建智算任务"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
{
|
||||
"message": {
|
||||
"china": "中文",
|
||||
"english": "English",
|
||||
"login": "登录",
|
||||
"logout": "退出登录",
|
||||
"back": "返回",
|
||||
"save": "保存",
|
||||
"cancel": "取消",
|
||||
"to": "至",
|
||||
"startDate": "开始日期",
|
||||
"endDate": "结束日期",
|
||||
"search": "搜索",
|
||||
"reset": "重置",
|
||||
"count": "总条数:",
|
||||
"create": "创建",
|
||||
"name": "名称",
|
||||
"confirm": "确定",
|
||||
"easyCreate": "快捷创建",
|
||||
"next": "下一步",
|
||||
"success": "操作成功",
|
||||
"before": "上一步",
|
||||
"pleaseInput": "请输入",
|
||||
"pleaseChoose": "请选择"
|
||||
},
|
||||
"menu": {
|
||||
"taskManagement": "任务管理",
|
||||
"taskList": "任务列表",
|
||||
"jobTask": "作业任务",
|
||||
"strategyManagement": "策略管理",
|
||||
"schedulingStrategy": "调度策略",
|
||||
"warnStrategy": "告警策略",
|
||||
"adapterManagement": "驱动器管理",
|
||||
"adapterList": "驱动器列表",
|
||||
"clusterManagement": "集群管理",
|
||||
"resourceUsageTop": "资源中心使用TOP3",
|
||||
"resourceCenter": "资源中心",
|
||||
"scheduleStatus": "调度情况",
|
||||
"messageList": "消息列表",
|
||||
"alertNotification": "告警通知",
|
||||
"hpcManagement": "超算管理",
|
||||
"hpcOverview": "超算概览",
|
||||
"aiManagement": "智算管理",
|
||||
"autoStudy": "自动学习",
|
||||
"warnCenter": "告警中心",
|
||||
"warnList": "告警列表",
|
||||
"warnSet": "告警设置",
|
||||
"overview": "概览",
|
||||
"clusterNodes": "集群节点",
|
||||
"project": "项目",
|
||||
"storage": "存储",
|
||||
"workload": "工作负载",
|
||||
"containerNodes": "容器节点",
|
||||
"services": "服务",
|
||||
"containerManagement": "容器管理",
|
||||
"mainEngine": "主机",
|
||||
"virtualMachine": "虚拟机",
|
||||
"volume": "卷",
|
||||
"image": "镜像",
|
||||
"namespace": "命名空间",
|
||||
"virtualMachineMana": "虚拟机管理"
|
||||
},
|
||||
"check": {
|
||||
"input": "请输入",
|
||||
"select": "请选择",
|
||||
"inputInvalid": "名称格式不合法。字母开头,仅能包含小写字母、数字和-。",
|
||||
"requireSelect": "必选项"
|
||||
},
|
||||
"page": {
|
||||
"cloud": "数算",
|
||||
"hpc": "超算",
|
||||
"ai": "智算",
|
||||
"title": "云际计算基础平台",
|
||||
"JointDomainresourceflux": " 云际全域资源态势感知 ",
|
||||
"task": "任务",
|
||||
"taskDescription": "支持创建不同计算环境或不同硬件平台之间的任务进行互联互通互操作,确保每个任务在不同的计算环境或硬件平台上都可以独立地运行。 ",
|
||||
"taskName": "任务名称",
|
||||
"jobStatus": "作业状态",
|
||||
"policy": "作业策略",
|
||||
"synergyStatus": "协同状态",
|
||||
"adapter": "驱动器",
|
||||
"cluster": "集群",
|
||||
"startTime": "作业开始时间",
|
||||
"more": "更多操作",
|
||||
"participantName": "Participant名称",
|
||||
"calculationType":"计算类型",
|
||||
"stackName":"技术栈名称",
|
||||
"stackVersion":"技术栈版本号",
|
||||
"address":"地址",
|
||||
"creationTime":"创建时间",
|
||||
"delete":"删除",
|
||||
"associatedCluster":"已关联集群",
|
||||
"description":"描述",
|
||||
"edit":"编辑",
|
||||
"total":"总条数",
|
||||
"addAdapter":"新增驱动器",
|
||||
"updateAdapter": "编辑驱动器",
|
||||
"bindCluster":"绑定集群",
|
||||
"clusterAssociation":"集群关联",
|
||||
"adapterSetting":"驱动器设置",
|
||||
"adapterDesc":"支持用户上传新的PCM适配技术栈,并通过当前功能,进行适配绑定",
|
||||
"clusterDesc": "对多集群以及每个集群的基础资源, 服务组件和应用资源等的统一管理",
|
||||
"deleteWarn":"您确定要删除吗",
|
||||
"deleteSuccess":"删除成功",
|
||||
"viewDetail": "View Detail",
|
||||
"cpType": "计算类型",
|
||||
"taskType": "任务类型",
|
||||
"createApplication": "创建容器应用",
|
||||
"createJob": "创建容器定时任务",
|
||||
"memory": "内存",
|
||||
"storage": "存储",
|
||||
"distributedTask": "已下发任务",
|
||||
"reservedTask": "已保留任务",
|
||||
"errorTask": "错误任务",
|
||||
"reason": "原因",
|
||||
"eventDetail": "事件详情",
|
||||
"updateDate": "更新时间",
|
||||
"clusterName": "集群名",
|
||||
"kbVersion": "kubernetes版本",
|
||||
"createTime": "创建时间",
|
||||
"classification": "分类",
|
||||
"vmCluster": "虚拟机集群",
|
||||
"containerCluster": "容器集群",
|
||||
"hpcDomain": "超算域",
|
||||
"job": "作业",
|
||||
"ClusterSum": "集群总数",
|
||||
"AdapterSum": "驱动器总数",
|
||||
"TaskSum": "任务总数",
|
||||
"dispatchAdapter": "分配驱动器",
|
||||
"strategySelected": "调度策略选择",
|
||||
"updateCluster": "编辑集群",
|
||||
"addCluster": "新增集群",
|
||||
"chooseAdapter": "选择适配器",
|
||||
"name": "名称",
|
||||
"monitorAddress": "监控地址",
|
||||
"version": "版本号",
|
||||
"otherName": "别名",
|
||||
"area": "区域",
|
||||
"projectId": "项目Id",
|
||||
"tag": "标签",
|
||||
"authType": "认证方式",
|
||||
"skak": "SK/AK认证",
|
||||
"passAuth": "密码认证",
|
||||
"tokenAuth": "Token认证",
|
||||
"userName": "用户名",
|
||||
"password": "密码",
|
||||
"createVirtualmachine": "创建虚拟机",
|
||||
"createHpcbase": "创建超算基础模板",
|
||||
"createAibase": "创建智算任务"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="_层_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 25.3 22" style="enable-background:new 0 0 25.3 22;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill-rule:evenodd;clip-rule:evenodd;fill:url(#形状_6_拷贝_3_1_);}
|
||||
</style>
|
||||
<linearGradient id="形状_6_拷贝_3_1_" gradientUnits="userSpaceOnUse" x1="12.4196" y1="21.8865" x2="12.6413" y2="0.822">
|
||||
<stop offset="0.2441" style="stop-color:#FFFFFF"/>
|
||||
<stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0"/>
|
||||
</linearGradient>
|
||||
<path id="形状_6_拷贝_3" class="st0" d="M0,0l12.6,22L25.3,0"/>
|
||||
</svg>
|
After Width: | Height: | Size: 789 B |
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1679903317167" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7202" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M896 853.333333h-128a42.666667 42.666667 0 0 1-42.666667-42.666666v-128a213.333333 213.333333 0 0 0 60.586667-417.28A298.666667 298.666667 0 0 0 215.893333 346.026667 170.666667 170.666667 0 0 0 256 682.666667h42.666667v128a42.666667 42.666667 0 0 1-42.666667 42.666666H128a42.666667 42.666667 0 0 0 0 85.333334h128a128 128 0 0 0 128-128v-128h85.333333v213.333333a42.666667 42.666667 0 1 0 85.333334 0v-213.333333h85.333333v128a128 128 0 0 0 128 128h128a42.666667 42.666667 0 1 0 0-85.333334zM256 597.333333a85.333333 85.333333 0 1 1 0-170.666666 42.666667 42.666667 0 0 0 42.666667-42.666667 213.333333 213.333333 0 0 1 415.146666-68.693333 42.666667 42.666667 0 0 0 33.28 28.586666A128 128 0 0 1 853.333333 469.333333a128 128 0 0 1-128 128H256z" p-id="7203"></path></svg>
|
After Width: | Height: | Size: 1.1 KiB |
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 200 200" style="enable-background:new 0 0 200 200;" xml:space="preserve">
|
||||
<path d="M175.1,112h-12.6V88h12.6c4.9,0,8.8-3.9,8.8-8.8s-3.9-8.8-8.8-8.8h-12.6V59.8c0-12.3-10-22.2-22.2-22.2h-10.6V24.9
|
||||
c0-4.9-3.9-8.8-8.8-8.8c-4.9,0-8.8,3.9-8.8,8.8v12.6H88V24.9c0-4.9-3.9-8.8-8.8-8.8s-8.8,3.9-8.8,8.8v12.6H59.8
|
||||
c-12.3,0-22.2,10-22.2,22.2v10.6H24.9c-4.9,0-8.8,3.9-8.8,8.8s3.9,8.8,8.8,8.8h12.6V112H24.9c-4.9,0-8.8,3.9-8.8,8.8
|
||||
c0,4.9,3.9,8.8,8.8,8.8h12.6v10.6c0,12.3,10,22.2,22.2,22.2h10.6v12.6c0,4.9,3.9,8.8,8.8,8.8s8.8-3.9,8.8-8.8v-12.6H112v12.6
|
||||
c0,4.9,3.9,8.8,8.8,8.8s8.8-3.9,8.8-8.8v-12.6h10.6c12.3,0,22.2-10,22.2-22.2v-10.6h12.6c4.9,0,8.8-3.9,8.8-8.8
|
||||
C183.9,116,179.9,112,175.1,112z M144.8,140.2c0,2.5-2.1,4.6-4.6,4.6H59.8c-2.5,0-4.6-2.1-4.6-4.6V59.8c0-2.5,2.1-4.6,4.6-4.6h80.4
|
||||
c2.5,0,4.6,2.1,4.6,4.6V140.2z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
|
@ -0,0 +1,27 @@
|
|||
<template>
|
||||
<div id="app">
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'App',
|
||||
computed: {
|
||||
jcceTheme() {
|
||||
return localStorage.getItem('jcceTheme')
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
localStorage.setItem('jcceTheme', 'jcceDark') // Please delete code if you need other color
|
||||
const jcceTheme = this.jcceTheme || 'jcceDark'
|
||||
document.documentElement.setAttribute('jcceTheme', jcceTheme)
|
||||
localStorage.setItem('jcceTheme', jcceTheme)
|
||||
|
||||
if (jcceTheme === 'jcceDark') {
|
||||
require('./styles/dark-theme/dark.scss')
|
||||
document.body.className = jcceTheme
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,261 @@
|
|||
import request from '@/utils/request'
|
||||
// import moment from 'moment'
|
||||
|
||||
export default {
|
||||
// pod delete
|
||||
deleteCurrent(clusterName, namespace, name, classification) {
|
||||
if (classification === 'userProject') {
|
||||
return request({
|
||||
url: `/jcc-schedule/api/v1/namespace/delete/${clusterName}/${namespace}/false`,
|
||||
method: 'delete'
|
||||
})
|
||||
} else if (classification === 'storage') {
|
||||
return request({
|
||||
url: `/jcc-schedule/api/v1/storage/pvc/${clusterName}/${namespace}/${name}/false`,
|
||||
method: 'delete'
|
||||
})
|
||||
} else if (classification === 'pods') {
|
||||
return request({
|
||||
url: `/jcc-schedule/api/v1/pod/delete/${clusterName}/${namespace}/${name}/false`,
|
||||
method: 'delete'
|
||||
})
|
||||
} else if (classification === 'services') { // 服务
|
||||
return request({
|
||||
url: `/jcc-schedule/api/v1/service/delete/${clusterName}/${namespace}/${name}/false`,
|
||||
method: 'delete'
|
||||
})
|
||||
} else {
|
||||
return request({
|
||||
url: `/jcc-schedule/api/v1/${classification}/delete/${clusterName}/${namespace}/${name}/false`,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
},
|
||||
// return exist: false
|
||||
// http://119.45.100.73:30880/api/clusters/bj-member2/v1/namespaces post
|
||||
|
||||
// {"apiVersion":"v1","kind":"Namespace","metadata":{"name":"what","labels":{},"annotations":{"kubesphere.io/creator":"nudt"}}}
|
||||
|
||||
// http://119.45.100.73:30880/apis/apps/v1/namespaces/kubesphere-system/deployments/tower
|
||||
|
||||
getVirtualStorage() {
|
||||
return request({
|
||||
url: '/jcc-vm/v1/harvester/longhorn.io.nodes',
|
||||
method: 'get'
|
||||
})
|
||||
},
|
||||
|
||||
// 通道hash查询接口
|
||||
getCurrentChannel() {
|
||||
return request({
|
||||
url: `/blockChain/apiLedger/curChannel`,
|
||||
method: 'get'
|
||||
})
|
||||
},
|
||||
// 通道指标统计查询接口
|
||||
getStatisticsCount(hash) {
|
||||
return request({
|
||||
url: `/blockChain/apiLedger/status/${hash}`,
|
||||
method: 'get'
|
||||
})
|
||||
},
|
||||
getUserCount() {
|
||||
return request({
|
||||
url: `/jcc-ledger/contract/getUserNum`
|
||||
})
|
||||
},
|
||||
getTradeCount() {
|
||||
return request({
|
||||
url: `/jcc-ledger/contract/getVolume`
|
||||
})
|
||||
},
|
||||
// 块链列表
|
||||
getBlockList(hash, query) {
|
||||
return request({
|
||||
url: `/blockChain/apiLedger/blockAndTxList/${hash}/0`,
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
},
|
||||
// 监控列表
|
||||
getMonitorList(query) {
|
||||
// const time = { from: moment().subtract(1, 'months').format('YYYY-MM-DD HH:mm:ss.SSS'), to: moment().add(1, 'days').format('YYYY-MM-DD HH:mm:ss.SSS') }
|
||||
console.log(query)
|
||||
return request({
|
||||
url: `/jcc-ledger/transactions/getTxInfo?chainCodeName=monitor&`,
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
},
|
||||
// 评论列表
|
||||
getEvaluationList(query) {
|
||||
// const time = { from: moment().subtract(1, 'months').format('YYYY-MM-DD HH:mm:ss.SSS'), to: moment().add(1, 'days').format('YYYY-MM-DD HH:mm:ss.SSS') }
|
||||
console.log(query)
|
||||
return request({
|
||||
url: `/jcc-ledger/transactions/getTxInfo?chainCodeName=evaluation&`,
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
},
|
||||
// 交易列表
|
||||
getTradeList(query) {
|
||||
// const time = { from: moment().subtract(1, 'months').format('YYYY-MM-DD HH:mm:ss.SSS'), to: moment().add(1, 'days').format('YYYY-MM-DD HH:mm:ss.SSS') }
|
||||
console.log(query)
|
||||
return request({
|
||||
url: `/jcc-ledger/transactions/getTxInfo?chainCodeName=record`,
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
},
|
||||
// 交易详情
|
||||
getTradeDetail(hash) {
|
||||
return request({
|
||||
url: `/jcc-ledger/transactions/getTxByHash`,
|
||||
method: 'get',
|
||||
params: { txHash: hash }
|
||||
})
|
||||
},
|
||||
getTradeMapByDate(query) {
|
||||
return request({
|
||||
url: `/jcc-ledger/transactions/getTxCntGroup`,
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
},
|
||||
// 证书详情
|
||||
getCertificationDetail(hash) {
|
||||
return request({
|
||||
url: `/jcc-ledger/transactions/getCert`,
|
||||
method: 'get',
|
||||
params: { txHash: hash }
|
||||
})
|
||||
},
|
||||
// 搜索证书
|
||||
getCertificationByType(query, queryType) {
|
||||
return request({
|
||||
url: `/jcc-ledger/transactions/${queryType}`,
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
},
|
||||
// 函数
|
||||
checkFunctionName(functionName) {
|
||||
return request({
|
||||
url: `/jcc-faas-manager/function/exist/${functionName}`,
|
||||
method: 'get'
|
||||
})
|
||||
},
|
||||
createFunction(query) {
|
||||
return request({
|
||||
url: '/jcc-faas-manager/function/createFunction',
|
||||
method: 'post',
|
||||
data: query
|
||||
})
|
||||
},
|
||||
deleteFunctionByName() {
|
||||
return request({
|
||||
url: '/jcc-faas-manager/function/delete/functionByName',
|
||||
method: 'delete'
|
||||
})
|
||||
},
|
||||
deleteFunction(functionId) {
|
||||
return request({
|
||||
url: `/jcc-faas-manager/function/deleteFunction/${functionId}`,
|
||||
method: 'delete'
|
||||
})
|
||||
},
|
||||
getFunctionByFunctionName() {
|
||||
return request({
|
||||
url: '/jcc-faas-manager/function/delete/functionByName',
|
||||
method: 'get'
|
||||
})
|
||||
},
|
||||
invokeFunction(params, query) {
|
||||
return request({
|
||||
url: '/jcc-faas-manager/function/invokeFunction',
|
||||
method: 'post',
|
||||
params: params,
|
||||
data: query
|
||||
})
|
||||
},
|
||||
listFunctions(query) {
|
||||
return request({
|
||||
url: '/jcc-faas-manager/function/lists',
|
||||
method: 'get',
|
||||
params: query || { page: 1, size: 10 }
|
||||
})
|
||||
},
|
||||
// updateFunction() {
|
||||
// return request({
|
||||
// url: '/function/updateFunction',
|
||||
// method: 'put'
|
||||
// })
|
||||
// },
|
||||
getFunctionOverview() {
|
||||
return request({
|
||||
url: '/jcc-faas-manager/function/selectFunctionOverview',
|
||||
method: 'get'
|
||||
})
|
||||
},
|
||||
getFunctionMap() {
|
||||
return request({
|
||||
url: '/jcc-faas-manager/function/selectFunctionList',
|
||||
method: 'get'
|
||||
})
|
||||
},
|
||||
// 大屏总营收接口
|
||||
getRevenue() {
|
||||
return request({
|
||||
url: '/jcc-mall/order/queryRevenue',
|
||||
method: 'get'
|
||||
})
|
||||
},
|
||||
// 大屏地球查询
|
||||
getMapArea() {
|
||||
return request({
|
||||
url: '/jcc-faas-manager/function/device/queryByArea',
|
||||
method: 'get'
|
||||
})
|
||||
},
|
||||
// 大屏云厂商服务器数量查询接口
|
||||
getCloudServerCount() {
|
||||
return request({
|
||||
url: '/jcc-faas-manager/function/device/queryByManufacturer',
|
||||
method: 'get'
|
||||
})
|
||||
},
|
||||
// 大屏服务器数量统计接口
|
||||
getServerDeviceCount() {
|
||||
return request({
|
||||
url: '/jcc-faas-manager/function/device/queryDeviceCount',
|
||||
method: 'get'
|
||||
})
|
||||
},
|
||||
|
||||
// 大屏服务器数量统计接口
|
||||
getOrderStatus() {
|
||||
return request({
|
||||
url: '/jcc-mall/order/countOrderStatus',
|
||||
method: 'get'
|
||||
})
|
||||
},
|
||||
|
||||
// CPU、内存 总量 用量 旧旧大屏kubeshpere接口
|
||||
getCoreStatus() {
|
||||
// return request({
|
||||
// url: process.env.VUE_APP_BASE_API + '/kapis/clusters/host/monitoring.kubesphere.io/v1alpha3/cluster?start=1628697600&end=1628783999&step=3600s×=20&metrics_filter=cluster_cpu_usage%7Ccluster_cpu_total%7Ccluster_memory_usage_wo_cache%7Ccluster_memory_total%24',
|
||||
// method: 'get'
|
||||
// })
|
||||
},
|
||||
|
||||
// harvester
|
||||
// cpu 内存状态获取
|
||||
getUsageStatus() {
|
||||
return request({
|
||||
url: '/jcc-vm/v1/metrics.k8s.io.nodes',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
import request from '@/utils/request'
|
||||
|
||||
export function fetchList(query) {
|
||||
return request({
|
||||
url: '/vue-element-admin/article/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
export function fetchArticle(id) {
|
||||
return request({
|
||||
url: '/vue-element-admin/article/detail',
|
||||
method: 'get',
|
||||
params: { id }
|
||||
})
|
||||
}
|
||||
|
||||
export function fetchPv(pv) {
|
||||
return request({
|
||||
url: '/vue-element-admin/article/pv',
|
||||
method: 'get',
|
||||
params: { pv }
|
||||
})
|
||||
}
|
||||
|
||||
export function createArticle(data) {
|
||||
return request({
|
||||
url: '/vue-element-admin/article/create',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function updateArticle(data) {
|
||||
return request({
|
||||
url: '/vue-element-admin/article/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
import request from '@/utils/request'
|
||||
|
||||
export function getToken() {
|
||||
return request({
|
||||
url: '/qiniu/upload/token', // 假地址 自行替换
|
||||
method: 'get'
|
||||
})
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
import request from '@/utils/request'
|
||||
|
||||
export function searchUser(name) {
|
||||
return request({
|
||||
url: '/vue-element-admin/search/user',
|
||||
method: 'get',
|
||||
params: { name }
|
||||
})
|
||||
}
|
||||
|
||||
export function transactionList(query) {
|
||||
return request({
|
||||
url: '/vue-element-admin/transaction/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
import request from '@/utils/request'
|
||||
|
||||
export function getRoutes() {
|
||||
return request({
|
||||
url: '/vue-element-admin/routes',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function getRoles() {
|
||||
return request({
|
||||
url: '/vue-element-admin/roles',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function addRole(data) {
|
||||
return request({
|
||||
url: '/vue-element-admin/role',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function updateRole(id, data) {
|
||||
return request({
|
||||
url: `/vue-element-admin/role/${id}`,
|
||||
method: 'put',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function deleteRole(id) {
|
||||
return request({
|
||||
url: `/vue-element-admin/role/${id}`,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
import request from '@/utils/request'
|
||||
// const qs = require('qs')
|
||||
|
||||
// export function login(data) {
|
||||
// return request({
|
||||
// url: process.env.VUE_APP_BASE_API + '/login',
|
||||
// method: 'post',
|
||||
// data: data,
|
||||
// headers: {
|
||||
// 'Content-Type': 'application/json'
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
|
||||
// export function harvesterLogin(data) {
|
||||
// return request({
|
||||
// url: '/virtual/v3-public/localProviders/local?action=login',
|
||||
// method: 'post',
|
||||
// // params: { action: 'login'},
|
||||
// data: data,
|
||||
// headers: {
|
||||
// 'Content-Type': 'application/json;charset=UTF-8'
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// export function harvesterFirstLogin(data) {
|
||||
// return request({
|
||||
// url: '/virtual/v3-public/authProviders',
|
||||
// method: 'get',
|
||||
// headers: {
|
||||
// 'Content-Type': 'application/json;charset=UTF-8'
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
|
||||
export function blockChainLogin(query) {
|
||||
return request({
|
||||
url: `/blockChain/authLedger/login`,
|
||||
method: 'post',
|
||||
data: query,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
import request from '@/utils/request'
|
||||
|
||||
const preUrl = '/jcc-alert'
|
||||
export function getWarningListByPod(params) {
|
||||
return request({
|
||||
url: preUrl + '/alarm/getAllAlarms/1',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
export function getWarningListByVirtual(params) {
|
||||
return request({
|
||||
url: preUrl + '/alarm/getAllAlarms/2',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
export function getWarningDetail(id) {
|
||||
return request({
|
||||
url: preUrl + '/alarm/getAlarmDetail/' + id,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function getWarningSet(params) {
|
||||
return request({
|
||||
url: preUrl + '/alarm/getAllRules/3',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
export function getClusters() {
|
||||
return request({
|
||||
url: preUrl + '/alarm/getClusters',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
// 删除告警
|
||||
export function deleteWarning(id) {
|
||||
return request({
|
||||
url: preUrl + '/alarm/deleteById/' + id,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
export function deleteWarningRule(id) {
|
||||
return request({
|
||||
url: preUrl + '/alarm/deleteRule/' + id,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
export function postWarningRule(data) {
|
||||
return request({
|
||||
url: preUrl + '/alarm/createAlarmRule',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
import request from '@/utils/request'
|
||||
|
||||
// 集群管理页面--所有集群信息
|
||||
export function getClusterList(params) {
|
||||
return request({
|
||||
url: '/pcm/v1/adapter/cluster/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 资源清单
|
||||
export function getServerResources() {
|
||||
return request({
|
||||
url: '/jcc-schedule/api/v1/resource/getServerResources',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function getClusterSum() {
|
||||
return request({
|
||||
url: '/pcm/v1/adapter/clusterSum',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
import request from '@/utils/request'
|
||||
|
||||
export const getAppList = (params) => {
|
||||
return request({ url: '/pcm/v1/core/task/list', method: 'get', params })
|
||||
}
|
||||
export const getAppPodsByAppName = (name, params) => {
|
||||
return request({ url: '/pcm/v1/apps/pods/' + name, method: 'get', params })
|
||||
}
|
||||
export const addApp = (data) => {
|
||||
return request({ url: '/pcm/v1/core/task/create', method: 'post', data })
|
||||
}
|
||||
export const addNewApp = (params) => {
|
||||
return request({ url: '/pcm/v1/core/commitTask', method: 'post', params })
|
||||
}
|
||||
export const getDetail = (name, params) => {
|
||||
return request({ url: '/pcm/v1/apps/detail/' + name, method: 'get', params })
|
||||
}
|
||||
export const getCPUsage = (params) => {
|
||||
return request({ url: `/pcm/v1/storage/perCenterComputerPowers`, method: 'get', params })
|
||||
}
|
||||
export const getCharts = (params) => {
|
||||
return request({ url: '/pcm/v1/cloud/controller/Metrics', method: 'get', params })
|
||||
}
|
||||
export const getAppDetail = (appName, params) => {
|
||||
return request({ url: `/pcm/v1/apps/appDetail/${appName}`, method: 'get', params })
|
||||
}
|
||||
export const getAppDetailInfo = (appName, params) => {
|
||||
return request({ url: `/pcm/v1/apps/getAppByAppName/${appName}`, method: 'get', params })
|
||||
}
|
||||
export const getAppDistributeInfo = (appName, params) => {
|
||||
return request({ url: `/pcm/v1/apps/distribute/${appName}`, method: 'get', params })
|
||||
}
|
||||
// 暂停
|
||||
export const pauseApp = (params) => {
|
||||
return request({ url: `/pcm/v1/apps/pauseApp?nsID=${params.nsID}&name=${params.name}`, method: 'put' })
|
||||
}
|
||||
// 启动
|
||||
export const startApp = (params) => {
|
||||
return request({ url: `/pcm/v1/apps/startApp?nsID=${params.nsID}&name=${params.name}`, method: 'put' })
|
||||
}
|
||||
// 重启
|
||||
export const restartApp = (params) => {
|
||||
return request({ url: `/pcm/v1/apps/restartApp?nsID=${params.nsID}&name=${params.name}`, method: 'put' })
|
||||
}
|
||||
// 删除
|
||||
export const deleteApp = (params) => {
|
||||
return request({ url: `/pcm/v1/apps/deleteApp?nsID=${params.nsID}&name=${params.name}`, method: 'delete' })
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
// 大屏云厂商服务器数量查询接口
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function getTotalName() {
|
||||
return request({
|
||||
url: '/jcc-faas-manager/function/device/queryByManufacturer',
|
||||
method: 'get',
|
||||
data: JSON,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
}
|
||||
// 大屏服务器数量统计接口
|
||||
export function getTotalNum() {
|
||||
return request({
|
||||
url: '/jcc-faas-manager/function/device/queryDeviceCount',
|
||||
method: 'get',
|
||||
data: JSON,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 大屏地球地区查询接口
|
||||
export function originEarthRegion() {
|
||||
return request({
|
||||
url: '/jcc-faas-manager/function/device/queryByArea',
|
||||
method: 'get',
|
||||
data: JSON,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
}
|
||||
export function getEarthRegion() {
|
||||
return request({
|
||||
// url: '/jcc-faas-manager/function/device/queryByArea',
|
||||
url: '/pcm/v1/core/listCenter',
|
||||
method: 'get',
|
||||
data: JSON,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
}
|
||||
export function getProvinceDetail(id) {
|
||||
return request({
|
||||
url: '/pcm/v1/core/listCluster/' + id,
|
||||
method: 'get'
|
||||
// headers: {
|
||||
// 'Content-Type': 'application/json'
|
||||
// }
|
||||
})
|
||||
}
|
||||
|
||||
// 大屏地球各个区域服务器资源详细接口
|
||||
export function getEarthDetails(area) {
|
||||
return request({
|
||||
url: '/jcc-extend/container/device/queryResDetailByArea?area=' + area,
|
||||
method: 'get',
|
||||
data: JSON,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// CPU平均使用率接口
|
||||
// export function getCpuAverage(start, end, step) {
|
||||
// return request({
|
||||
// url: '/monitoringscreen/api/v1/query_range?query=avg(1%20-%20avg(rate(node_cpu_seconds_total%7Borigin_prometheus%3D~%22%22%2Cjob%3D~%22node-exporter%22%2Cmode%3D%22idle%22%7D%5B2m%5D))%20by%20(instance))%20*%20100' + '&start=' + start + '&end=' + end + '&step=' + step + '&_=1642578431700',
|
||||
// method: 'get',
|
||||
// data: JSON,
|
||||
// headers: {
|
||||
// 'Content-Type': 'application/json'
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
|
||||
// 整体总负载 平均使用情况
|
||||
export function getTotalAverage() {
|
||||
return request({
|
||||
url: '/jcc-schedule/api/v1/resource/getOverallMetrics',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 计量计费接口总价格
|
||||
export function getMeasure(start, end, step) {
|
||||
return request({
|
||||
url: process.env.VUE_APP_BASE_API + '/kapis/clusters/host/metering.kubesphere.io/v1alpha1/cluster' + '?start=' + start + '&end=' + end + '&step=' + step + 's&metrics_filter=meter_cluster_cpu_usage%7Cmeter_cluster_memory_usage%7Cmeter_cluster_net_bytes_transmitted%7Cmeter_cluster_net_bytes_received%7Cmeter_cluster_pvc_bytes_total&resources_filter=host',
|
||||
method: 'get',
|
||||
data: JSON,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// // 内存整体负载接口
|
||||
// export function getRamLoad(start, end, step) {
|
||||
// return request({
|
||||
// url: '/monitoringscreen/api/v1/query_range?query=sum(node_memory_MemTotal_bytes%7Borigin_prometheus%3D~%22%22%2Cjob%3D~%22node-exporter%22%7D%20-%20node_memory_MemAvailable_bytes%7Borigin_prometheus%3D~%22%22%2Cjob%3D~%22node-exporter%22%7D)&start=' + start + '&end=' + end + '&step=' + step + '&_=1642669327729',
|
||||
// method: 'get',
|
||||
// data: JSON,
|
||||
// headers: {
|
||||
// 'Content-Type': 'application/json'
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
|
||||
// 计量计费列表接口
|
||||
export function getMeteringList(start, end, step) {
|
||||
return request({
|
||||
url: process.env.VUE_APP_BASE_API + '/kapis/clusters/host/metering.kubesphere.io/v1alpha1/cluster' + '?start=' + start + '&end=' + end + '&step=' + step + 's&metrics_filter=meter_cluster_cpu_usage%7Cmeter_cluster_memory_usage%7Cmeter_cluster_net_bytes_transmitted%7Cmeter_cluster_net_bytes_received%7Cmeter_cluster_pvc_bytes_total&resources_filter=host',
|
||||
method: 'get',
|
||||
data: JSON,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// // CPU整体负载接口
|
||||
// export function getCpuAllload(start, end) {
|
||||
// return request({
|
||||
// url: '/monitoringscreen/api/v1/query_range?query=node_load15%7Binstance%3D~%22k8s-master%22%7D&start=' + start + '&end=' + end + '&step=900&_=1645409802467',
|
||||
// method: 'get',
|
||||
// data: JSON,
|
||||
// headers: {
|
||||
// 'Content-Type': 'application/json'
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
|
||||
// 累计任务情况接口
|
||||
export function getTaskList() {
|
||||
return request({
|
||||
url: '/pcm/v1/core/taskList',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 累计任务情况计数
|
||||
export function getTaskCount() {
|
||||
return request({
|
||||
url: '/pcm/v1/core/jobTotal',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 控制面板 控制跨域调度任务
|
||||
export function createScheduleTask(data) {
|
||||
return request({
|
||||
url: '/pcm/v1/core/scheduleTaskByYaml',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
|
@ -0,0 +1,282 @@
|
|||
import request from '@/utils/request'
|
||||
|
||||
const preUrl = '/apis/jcc-admin'
|
||||
export function login(username, password) {
|
||||
return request({
|
||||
url: preUrl + '/admin/login',
|
||||
method: 'post',
|
||||
data: {
|
||||
username,
|
||||
password
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function getInfo() {
|
||||
return request({
|
||||
url: preUrl + '/admin/info',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function logout() {
|
||||
return request({
|
||||
url: preUrl + '/admin/logout',
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
export function getUserList(params) {
|
||||
return request({
|
||||
url: preUrl + '/admin/list',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
export function createAdmin(data) {
|
||||
return request({
|
||||
url: preUrl + '/admin/register',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function updateAdmin(id, data) {
|
||||
return request({
|
||||
url: preUrl + '/admin/update/' + id,
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function updateUserStatus(id, params) {
|
||||
return request({
|
||||
url: preUrl + '/admin/updateStatus/' + id,
|
||||
method: 'put',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
export function deleteAdmin(id) {
|
||||
return request({
|
||||
url: preUrl + '/admin/delete/' + id,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
export function getRoleByAdmin(id) {
|
||||
return request({
|
||||
url: preUrl + '/admin/role/' + id,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function allocRole(data) {
|
||||
return request({
|
||||
url: preUrl + '/admin/role/update',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 角色列表
|
||||
export function getRoleList(params) {
|
||||
return request({
|
||||
url: preUrl + '/role/list',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
export function createRole(data) {
|
||||
return request({
|
||||
url: preUrl + '/role/create',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function updateRole(id, data) {
|
||||
return request({
|
||||
url: preUrl + '/role/update/' + id,
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function updateRoleStatus(id, params) {
|
||||
return request({
|
||||
url: preUrl + '/role/updateStatus/' + id,
|
||||
method: 'put',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
export function deleteRole(data) {
|
||||
return request({
|
||||
url: preUrl + '/role/delete',
|
||||
method: 'delete',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function fetchAllRoleList() {
|
||||
return request({
|
||||
url: preUrl + '/role/listAll',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function listMenuByRole(roleId) {
|
||||
return request({
|
||||
url: preUrl + '/role/listMenu/' + roleId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function listResourceByRole(roleId) {
|
||||
return request({
|
||||
url: preUrl + '/role/listResource/' + roleId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function allocMenu(data) {
|
||||
return request({
|
||||
url: preUrl + '/role/allocMenu',
|
||||
method: 'post',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
|
||||
export function allocResource(data) {
|
||||
return request({
|
||||
url: preUrl + '/role/allocResource',
|
||||
method: 'post',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
|
||||
// 菜单列表
|
||||
export function getMenuList(parentId, params) {
|
||||
return request({
|
||||
url: preUrl + '/menu/list/' + parentId,
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
export function deleteMenu(id) {
|
||||
return request({
|
||||
url: preUrl + '/menu/delete/' + id,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
export function createMenu(data) {
|
||||
return request({
|
||||
url: preUrl + '/menu/create',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function updateMenu(id, data) {
|
||||
return request({
|
||||
url: preUrl + '/menu/update/' + id,
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function getMenu(id) {
|
||||
return request({
|
||||
url: preUrl + '/menu/' + id,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function updateHidden(id, params) {
|
||||
return request({
|
||||
url: preUrl + '/menu/updateHidden/' + id,
|
||||
method: 'put',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
export function fetchTreeList() {
|
||||
return request({
|
||||
url: preUrl + '/menu/treeList',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 资源列表
|
||||
export function getResourceList(params) {
|
||||
return request({
|
||||
url: preUrl + '/resource/list',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
export function createResource(data) {
|
||||
return request({
|
||||
url: preUrl + '/resource/create',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function updateResource(id, data) {
|
||||
return request({
|
||||
url: preUrl + '/resource/update/' + id,
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function deleteResource(id) {
|
||||
return request({
|
||||
url: preUrl + '/resource/delete/' + id,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
export function fetchAllResourceList() {
|
||||
return request({
|
||||
url: preUrl + '/resource/listAll',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function listAllCate() {
|
||||
return request({
|
||||
url: preUrl + '/resourceCategory/listAll',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function createResourceCategory(data) {
|
||||
return request({
|
||||
url: preUrl + '/resourceCategory/create',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function updateResourceCategory(id, data) {
|
||||
return request({
|
||||
url: preUrl + '/resourceCategory/update/' + id,
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function deleteResourceCategory(id) {
|
||||
return request({
|
||||
url: preUrl + '/resourceCategory/delete/' + id,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
After Width: | Height: | Size: 6.0 KiB |
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1708954274349" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13419" xmlns:xlink="http://www.w3.org/1999/xlink" width="18" height="18"><path d="M892.489143 917.942857a35.620571 35.620571 0 0 1-39.643429-31.451428 36.571429 36.571429 0 0 1 0-6.509715v-140.361143c0-38.546286-25.380571-38.546286-34.962285-38.546285a43.885714 43.885714 0 0 0-45.129143 43.154285V880.274286a39.277714 39.277714 0 0 1-78.409143 0v-212.845715a35.766857 35.766857 0 0 1 33.206857-38.180571 47.981714 47.981714 0 0 1 41.691429 20.333714 102.4 102.4 0 0 1 62.976-20.333714 92.818286 92.818286 0 0 1 99.035428 102.912v147.968a36.571429 36.571429 0 0 1-10.166857 27.136 39.058286 39.058286 0 0 1-28.452571 10.678857z m-267.117714-8.557714H471.04c-49.005714 0-70.875429-21.942857-70.875429-70.363429V622.153143c0-48.64 21.942857-70.363429 70.875429-70.363429h147.529143a37.083429 37.083429 0 1 1 0 74.166857H485.376a10.313143 10.313143 0 0 0-4.096 0.585143v63.414857h121.417143a34.011429 34.011429 0 0 1 37.376 36.132572 34.596571 34.596571 0 0 1-37.376 36.571428H480.987429v68.681143a12.288 12.288 0 0 0 0.365714 3.584 31.232 31.232 0 0 0 3.876571 0H625.371429a35.254857 35.254857 0 0 1 37.376 32.914286 35.84 35.84 0 0 1 0 4.022857 34.669714 34.669714 0 0 1-31.817143 37.302857 35.620571 35.620571 0 0 1-5.632 0zM298.422857 479.012571a36.571429 36.571429 0 0 1-41.106286-38.692571V350.573714H159.524571c-52.516571 0-75.995429-23.478857-75.995428-75.776V167.424c0-52.077714 23.478857-75.337143 75.995428-75.337143h97.718858V56.027429a35.547429 35.547429 0 0 1 32.621714-38.253715 36.571429 36.571429 0 0 1 6.582857 0c34.669714 0 41.984 20.772571 41.984 38.180572v36.132571h98.669714c52.516571 0 75.995429 23.259429 75.995429 75.337143v107.373714c0 52.443429-23.478857 75.776-75.995429 75.776H338.505143V440.32a36.571429 36.571429 0 0 1-33.645714 38.765714 36.571429 36.571429 0 0 1-6.436572 0zM172.032 168.521143c-7.314286 0-8.118857 0.658286-8.118857 8.118857v89.380571c0 7.314286 0.658286 8.192 8.118857 8.192h85.284571V168.521143H171.958857z m166.546286 105.618286h86.235428c7.314286 0 8.118857-0.950857 8.118857-8.118858V176.566857c0-7.314286-0.950857-8.118857-8.118857-8.118857h-86.308571v105.691429zM512.146286 1024a512 512 0 0 1-497.371429-632.758857 41.325714 41.325714 0 0 1 49.298286-30.061714 40.740571 40.740571 0 0 1 30.134857 49.078857 431.542857 431.542857 0 0 0 417.938286 532.187428 40.740571 40.740571 0 1 1 0 81.554286z m456.557714-354.450286a40.740571 40.740571 0 0 1-39.643429-50.761143 431.542857 431.542857 0 0 0-416.914285-537.307428 40.740571 40.740571 0 1 1 0-81.481143 512 512 0 0 1 496.201143 638.829714 40.813714 40.813714 0 0 1-39.789715 30.72z" fill="#eeeeee" p-id="13420"></path></svg>
|
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 636 KiB |
After Width: | Height: | Size: 192 KiB |
After Width: | Height: | Size: 151 KiB |
|
@ -0,0 +1,31 @@
|
|||
@font-face {
|
||||
font-family: 'DISPLAY FREE TFB'; /* 重命名字体名 */
|
||||
src: url('DISPLAY FREE TFB.ttf'); /* 引入字体 */
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'PangMenZhengDao'; /* 重命名字体名 */
|
||||
src: url('PangMenZhengDao.ttf'); /* 引入字体 */
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'SourceHanSansCN'; /* 重命名字体名 */
|
||||
src: url('SourceHanSansCN.otf'); /* 引入字体 */
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'PingFang SC'; /* 重命名字体名 */
|
||||
src: url('PingFang SC.ttf'); /* 引入字体 */
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Impact'; /* 重命名字体名 */
|
||||
src: url('impact.ttf'); /* 引入字体 */
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
|
@ -0,0 +1,241 @@
|
|||
<template>
|
||||
<!-- 初始容器 和 其他 -->
|
||||
<el-dialog v-if="dialogVisible" :close-on-click-modal="false" width="80%" :title="(!createContainerForm.name?'添加':'编辑')+'容器'" :visible.sync="dialogVisible" append-to-body>
|
||||
|
||||
<el-form ref="createContainerForm" :model="createContainerForm">
|
||||
<div class="border">
|
||||
<p>
|
||||
容器设置
|
||||
<span class="tips">对容器的名称及容器的计算资源进行设置</span>
|
||||
</p>
|
||||
<el-form-item label="镜像" required="">
|
||||
<el-input v-model="createContainerForm.image" placeholder="直接输入名称 例:nginx:latest" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="border">
|
||||
<p>
|
||||
端口设置
|
||||
<span class="tips">设置容器的访问策略</span>
|
||||
</p>
|
||||
<div>
|
||||
<div>
|
||||
<el-form-item
|
||||
v-for="(tag, index) in createContainerForm.ports"
|
||||
:key="'tag'+index"
|
||||
label=""
|
||||
>
|
||||
<el-row>
|
||||
<el-col :span="5">
|
||||
<el-tooltip
|
||||
class="item"
|
||||
effect="dark"
|
||||
content="为了充分利用应用治理的能力,请选择服务实际使用的协议。例如,如果服务暴露的是 HTTP 服务,则选择 http 协议,会生成形如 http-[name] 的端口名称。"
|
||||
placement="top-start"
|
||||
>
|
||||
<i class="el-icon-question" />
|
||||
</el-tooltip>
|
||||
协议
|
||||
<el-select v-model="tag.protocol" style="width:70%" @change="selectPolicy(tag)">
|
||||
<el-option
|
||||
v-for="item in protocolOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="5">
|
||||
名称
|
||||
<el-input v-model="tag.name" style="width:70%" />
|
||||
</el-col>
|
||||
<el-col :span="5">
|
||||
容器端口
|
||||
<el-input v-model="tag.containerPort" :max="65535" type="number" style="width:70%" />
|
||||
</el-col>
|
||||
<el-col v-if="classification === 'statefulsets'" :span="5">
|
||||
服务端口
|
||||
<el-input v-model="tag.servicePort" :max="65535" type="number" style="width:70%" />
|
||||
</el-col>
|
||||
<el-col :span="4"><el-button icon="el-icon-delete" circle @click.prevent="removeTag(tag,index)" /></el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-button type="primary" plain round :disabled="addTagNumCheck" @click="addTag">添加端口</el-button>
|
||||
</div>
|
||||
</div></div></el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button icon="el-icon-close" circle @click="dialogVisible = false" />
|
||||
<el-button icon="el-icon-check" circle @click="ok" />
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import moment from 'moment'
|
||||
import { isEmpty } from 'lodash'
|
||||
import generate from 'nanoid/generate'
|
||||
import { mountOptions, imagePullPolicyOptions, protocolOptions } from '@/utils/map'
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
formData: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {
|
||||
ports: []
|
||||
}
|
||||
}
|
||||
},
|
||||
namespace: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
classification: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
// isEdit: {
|
||||
// type: Boolean,
|
||||
// default: false
|
||||
// }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
imageList: [],
|
||||
activeName: 'first',
|
||||
imageData: undefined,
|
||||
noImage: false,
|
||||
loading: false,
|
||||
mountOptions,
|
||||
editInfoForm: {},
|
||||
imagePullPolicyOptions,
|
||||
protocolOptions,
|
||||
moment
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dialogVisible: {
|
||||
get() {
|
||||
return this.value
|
||||
},
|
||||
set(value) {
|
||||
this.$emit('input', value)
|
||||
}
|
||||
},
|
||||
createContainerForm: {
|
||||
get() {
|
||||
return this.formData
|
||||
},
|
||||
set(value) {
|
||||
// this.$emit('input', value)
|
||||
}
|
||||
},
|
||||
addTagNumCheck() {
|
||||
let flag = false
|
||||
this.createContainerForm.ports.forEach(e => {
|
||||
if (e.containerPort === '') {
|
||||
flag = true
|
||||
}
|
||||
})
|
||||
return flag
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// 'createContainerForm.image'(newVal) {
|
||||
// throttle(this.selectMirror(), 800)
|
||||
// }
|
||||
},
|
||||
mounted() {
|
||||
moment.locale('zh-cn')
|
||||
// this.getImageList()
|
||||
if (this.classification === 'statefulsets') {
|
||||
this.createContainerForm.ports.push({ protocol: 'HTTP', name: 'http-0', containerPort: 1, servicePort: 1 })
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
selectPolicy(tag) {
|
||||
tag.name = tag.protocol.toLowerCase() + '-'
|
||||
},
|
||||
addTag() {
|
||||
if (this.classification === 'statefulsets') {
|
||||
this.createContainerForm.ports.push({ protocol: 'HTTP', name: 'http-0', containerPort: 1, servicePort: 1 })
|
||||
} else {
|
||||
this.createContainerForm.ports.push({ protocol: 'HTTP', name: 'http-0', containerPort: 1 })
|
||||
}
|
||||
},
|
||||
removeTag(tag, index) {
|
||||
this.createContainerForm.ports.splice(index, 1)
|
||||
// this.blurInput()
|
||||
},
|
||||
// getImageList() {
|
||||
// this.$Api.getImagesList().then(res => {
|
||||
// const arr = res.summaries.map(e => {
|
||||
// return { name: e.name, description: e.short_description, star: e.star_count, imgUrl: e.logo_url.large || e.logo_url.small }
|
||||
// })
|
||||
// this.imageList = arr
|
||||
// })
|
||||
// },
|
||||
useDefaultPorts() {
|
||||
// 端口赋值
|
||||
const ports = this.imageData.exposedPorts.map(port => {
|
||||
const protocol = port.split('/')[1]
|
||||
const containerPort = Number(port.split('/')[0])
|
||||
|
||||
return {
|
||||
name: `${protocol}-${containerPort}`,
|
||||
protocol: protocol.toUpperCase(),
|
||||
containerPort: parseInt(containerPort),
|
||||
servicePort: containerPort
|
||||
}
|
||||
})
|
||||
if (!isEmpty(ports)) {
|
||||
this.createContainerForm.ports = ports
|
||||
}
|
||||
},
|
||||
ok() {
|
||||
// generate('0123456789abcdefghijklmnopqrstuvwxyz', length || 6)
|
||||
const container = Object.assign(this.createContainerForm)
|
||||
console.log(container)
|
||||
if (isEmpty(this.createContainerForm.ports)) {
|
||||
this.$delete(this.createContainerForm, 'ports')
|
||||
}
|
||||
// container.imageTag = this.imageData.imageTag
|
||||
// TODO container名称修改待添加
|
||||
if (!this.createContainerForm.name) {
|
||||
container.name = 'container-' + generate('0123456789abcdefghijklmnopqrstuvwxyz', 6)
|
||||
container.imagePullPolicy = 'IfNotPresent'
|
||||
this.$emit('addImage', container)
|
||||
} else {
|
||||
this.$emit('editImage', container)
|
||||
}
|
||||
this.dialogVisible = false
|
||||
|
||||
// 存在容器挂载
|
||||
// if(this.createContainerForm.readOnly !== 'null'){
|
||||
// this.formData.spec.template.spec.containers.forEach(e=>{
|
||||
|
||||
// })
|
||||
},
|
||||
handleClick() {}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.border{
|
||||
border: 1px solid var(--tabsCardBorderColor);
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.grayCard{
|
||||
// background: #eeeeee;
|
||||
p{margin: 0;}
|
||||
.tips{
|
||||
margin-top: 0;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
table td{padding: 0 5px; border: 0!important;}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,218 @@
|
|||
<template>
|
||||
<!-- 添加存储卷 -->
|
||||
<el-dialog v-if="dialogVisible" :close-on-click-modal="false" width="80%" title="存储卷" :visible.sync="dialogVisible" append-to-body>
|
||||
<el-form ref="volumeData" :model="volumeData">
|
||||
<el-tabs v-model="activeName" type="card" @tab-click="handleClick">
|
||||
<el-tab-pane label="已有存储卷" name="first">
|
||||
<el-form-item
|
||||
v-if="activeName==='first'"
|
||||
prop="firstName"
|
||||
label=""
|
||||
required
|
||||
>
|
||||
<el-select v-model="volumeData.firstName" class="selectPro" placeholder="选择已有存储卷">
|
||||
<el-option
|
||||
v-for="item in volumesList"
|
||||
:key="item.label"
|
||||
:label="item.label"
|
||||
:value="item.label"
|
||||
>
|
||||
<span style="width:50%; display:block;float:left">{{ item.label }}{{ item.alias?'('+item.alias+')':'' }}存储类型:{{ item.storageClassName }}</span>
|
||||
<span style="width:10%;display:block;float:left; color: #8492a6; font-size: 13px">容量:{{ item.storage }}</span>
|
||||
<span style="width:40%; display:block;float:left; text-align:right">访问模式:{{ item.accessModes }}</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="临时存储卷" name="second">
|
||||
<el-form-item
|
||||
v-if="activeName==='second'"
|
||||
prop="secondName"
|
||||
label="存储卷名称"
|
||||
required
|
||||
>
|
||||
<el-input v-model="volumeData.secondName" :maxlength="63" />
|
||||
<span class="tips">最长 63 个字符,只能包含小写字母、数字及分隔符("-"),且必须以小写字母或数字开头及结尾</span>
|
||||
</el-form-item>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="HostPath" name="third">
|
||||
<el-alert
|
||||
title="HostPath 将主机的文件系统挂载到Pod中,它使一些应用程序能逃出对其做出的隔离限制,请谨慎使用。"
|
||||
type="warning"
|
||||
/>
|
||||
<el-form-item
|
||||
v-if="activeName==='third'"
|
||||
prop="thirdName"
|
||||
label="存储卷名称"
|
||||
required
|
||||
>
|
||||
<el-input v-model="volumeData.thirdName" :maxlength="63" />
|
||||
<span class="tips">最长 63 个字符,只能包含小写字母、数字及分隔符("-"),且必须以小写字母或数字开头及结尾</span>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="activeName==='third'"
|
||||
prop="hostPath"
|
||||
label="HostPath"
|
||||
required
|
||||
>
|
||||
<el-input v-model="volumeData.path" :maxlength="63" />
|
||||
<span class="tips">最长 63 个字符,只能包含小写字母、数字及分隔符("-"),且必须以小写字母或数字开头及结尾</span>
|
||||
</el-form-item>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<table v-if="formData.spec.template.spec.containers">
|
||||
<tr v-for="(item, index) in formData.spec.template.spec.containers" :key="index" class="dataList">
|
||||
<td>容器</td>
|
||||
<td>{{ item.name }}</td>
|
||||
<td>
|
||||
<el-select v-model="createVolumesForm[index].readOnly">
|
||||
<el-option
|
||||
v-for="it in mountOptions"
|
||||
:key="it.value"
|
||||
:label="it.label"
|
||||
:value="it.value"
|
||||
/>
|
||||
</el-select>
|
||||
</td>
|
||||
<td><el-input v-model="createVolumesForm[index].mountPath" :disabled="createVolumesForm[index].readOnly == null" placeholder="容器挂载路径, 例如: /data" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button icon="el-icon-close" circle @click="dialogVisible = false" />
|
||||
<el-button icon="el-icon-check" circle @click="ok" />
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mountOptions } from '@/utils/map'
|
||||
import generate from 'nanoid/generate'
|
||||
import { getVolume } from '@/api/container/storageManagement'
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
formData: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
isEdit: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
createVolumesForm: [],
|
||||
volumeData: {
|
||||
firstName: '',
|
||||
secondName: '',
|
||||
thirdName: '',
|
||||
hostPath: ''
|
||||
},
|
||||
volumesList: [],
|
||||
activeName: 'first',
|
||||
mountOptions
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
clusterName() {
|
||||
return localStorage.getItem('clusterName')
|
||||
},
|
||||
dialogVisible: {
|
||||
get() {
|
||||
return this.value
|
||||
},
|
||||
set(value) {
|
||||
this.$emit('input', value)
|
||||
}
|
||||
}
|
||||
// codeData: {
|
||||
// get() {
|
||||
// return this.code + ''
|
||||
// },
|
||||
// set(value) {
|
||||
// this.$emit('code', value)
|
||||
// }
|
||||
// }
|
||||
},
|
||||
watch: {
|
||||
'formData.spec.template.spec.containers': {
|
||||
handler(val) {
|
||||
this.createVolumesForm = []
|
||||
for (let i = 0; i < this.formData.spec.template.spec.containers.length; i++) {
|
||||
this.createVolumesForm.push({ readOnly: null, mountPath: '' })
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
// code(val) {
|
||||
// this.codeData = val
|
||||
// }
|
||||
},
|
||||
mounted() {
|
||||
this.getVolumeList()
|
||||
},
|
||||
methods: {
|
||||
getVolumeList() {
|
||||
getVolume({ clusterName: this.clusterName, pageNum: 1, pageSize: 999 }).then(res => {
|
||||
const arr = res.data.list.map(e => { return { label: e.metadata.name, alias: e.metadata?.annotations?.['kubesphere.io/alias-name'], accessModes: e.spec.accessModes.join(','), storage: e.spec.resources.requests.storage, storageClassName: e.spec.storageClassName } })
|
||||
this.volumesList = arr
|
||||
})
|
||||
},
|
||||
ok() {
|
||||
this.$refs.volumeData.validate((valid) => {
|
||||
if (valid) {
|
||||
// 存在容器挂载
|
||||
const newFormData = Object.assign({}, this.formData)
|
||||
let newSpecVolume = {}
|
||||
switch (this.activeName) {
|
||||
case 'first':
|
||||
newSpecVolume = {
|
||||
name: `volume-${generate('0123456789abcdefghijklmnopqrstuvwxyz', 6)}`,
|
||||
persistentVolumeClaim: { claimName: this.volumeData[this.activeName + 'Name'] }
|
||||
}
|
||||
break
|
||||
case 'second':
|
||||
newSpecVolume = {
|
||||
name: this.volumeData[this.activeName + 'Name'],
|
||||
emptyDir: {}
|
||||
}
|
||||
break
|
||||
case 'third':
|
||||
newSpecVolume = {
|
||||
name: this.volumeData[this.activeName + 'Name'],
|
||||
hostPath: {
|
||||
path: this.volumeData.hostPath
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
newFormData.spec.template.spec.containers.forEach((e, index) => {
|
||||
if (this.createVolumesForm[index]?.readOnly !== null) {
|
||||
if (!e.volumeMounts) { e.volumeMounts = [] }
|
||||
e.volumeMounts.push({
|
||||
name: newSpecVolume.name,
|
||||
readOnly: this.createVolumesForm[index]?.readOnly,
|
||||
mountPath: this.createVolumesForm[index]?.mountPath
|
||||
})
|
||||
}
|
||||
})
|
||||
newFormData.spec.template.spec.volumes.push(newSpecVolume)
|
||||
|
||||
this.$emit('addVolumes', newFormData)
|
||||
this.dialogVisible = false
|
||||
}
|
||||
})
|
||||
},
|
||||
handleClick() {}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,167 @@
|
|||
<template>
|
||||
<!-- 编辑基本信息对话框 -->
|
||||
<el-dialog v-if="dialogFormVisible" :close-on-click-modal="false" title="编辑信息" :visible.sync="dialogFormVisible">
|
||||
<el-form ref="editInfoForm" :model="editInfoForm">
|
||||
<el-form-item
|
||||
prop="name"
|
||||
label="名称"
|
||||
>
|
||||
<el-input v-model="editInfoForm.name" :disabled="true" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
prop="aliasName"
|
||||
label="别名"
|
||||
>
|
||||
<el-input v-model="editInfoForm.aliasName" :maxlength="63" />
|
||||
<span class="tips">别名可以由任意字符组成,帮助您更好的区分资源,最长 63 个字符。</span>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
prop="description"
|
||||
label="描述信息"
|
||||
>
|
||||
<el-input v-model="editInfoForm.description" type="textarea" :maxlength="256" />
|
||||
<span class="tips">描述信息不超过 256 个字符</span>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogFormVisible = false">{{ $t("message.cancel") }}</el-button>
|
||||
<el-button type="primary" @click="submitInfoEdit">更 新</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { updateProjectData } from '@/api/container/projectManagement'
|
||||
import { updatePvcAlias } from '@/api/container/storageManagement'
|
||||
import { updateWorkloads } from '@/api/container/workloadManagement'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
type: { // 必传
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
classification: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
editInfoForm: {
|
||||
name: '',
|
||||
aliasName: '',
|
||||
description: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dialogFormVisible: {
|
||||
get() {
|
||||
return this.value
|
||||
},
|
||||
set(value) {
|
||||
this.$emit('input', value)
|
||||
}
|
||||
},
|
||||
clusterName() {
|
||||
return localStorage.getItem('clusterName')
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
data(val) {
|
||||
if (this.type === 'project') {
|
||||
this.editInfoForm = {
|
||||
name: val.metadata.name || '',
|
||||
aliasName: val.metadata.annotations ? val.metadata.annotations['kubesphere.io/alias-name'] : '',
|
||||
description: val.metadata.annotations ? val.metadata.annotations['kubesphere.io/description'] : ''
|
||||
}
|
||||
} else if (this.type === 'storage') {
|
||||
this.editInfoForm = {
|
||||
name: val.metadata.name || '',
|
||||
aliasName: val.metadata.annotations ? val.metadata.annotations['kubesphere.io/alias-name'] : '',
|
||||
description: val.metadata.annotations ? val.metadata.annotations['kubesphere.io/description'] : '',
|
||||
namespace: val.metadata.annotations ? val.metadata.namespace : '',
|
||||
clusterName: this.clusterName
|
||||
}
|
||||
} else if (this.type === 'workloads') {
|
||||
this.editInfoForm = {
|
||||
name: val.metadata.name || '',
|
||||
aliasName: val.metadata.annotations ? val.metadata.annotations['kubesphere.io/alias-name'] : '',
|
||||
description: val.metadata.annotations ? val.metadata.annotations['kubesphere.io/description'] : '',
|
||||
nsName: val.metadata.annotations ? val.metadata.namespace : ''
|
||||
}
|
||||
} else {
|
||||
this.editInfoForm = {
|
||||
name: val.metadata.name || '',
|
||||
aliasName: val.metadata.annotations ? val.metadata.annotations['kubesphere.io/alias-name'] : '',
|
||||
description: val.metadata.annotations ? val.metadata.annotations['kubesphere.io/description'] : ''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
methods: {
|
||||
submitInfoEdit() {
|
||||
if (this.type === 'project') {
|
||||
updateProjectData(this.clusterName, {
|
||||
metadata: {
|
||||
...this.data.metadata,
|
||||
annotations: {
|
||||
'kubesphere.io/alias-name': this.editInfoForm.aliasName,
|
||||
'kubesphere.io/description': this.editInfoForm.description
|
||||
}
|
||||
},
|
||||
spec: this.data.spec,
|
||||
status: this.data.status
|
||||
}).then(res => {
|
||||
this.$message.success('操作成功')
|
||||
this.dialogFormVisible = false
|
||||
this.$emit('getList')
|
||||
})
|
||||
} else if (this.type === 'storage') {
|
||||
updatePvcAlias(this.clusterName, {
|
||||
...this.data,
|
||||
metadata: {
|
||||
...this.data.metadata,
|
||||
annotations: {
|
||||
'kubesphere.io/alias-name': this.editInfoForm.aliasName,
|
||||
'kubesphere.io/description': this.editInfoForm.description
|
||||
}
|
||||
}
|
||||
}).then(res => {
|
||||
this.$message.success('操作成功')
|
||||
this.dialogFormVisible = false
|
||||
this.$emit('getList')
|
||||
})
|
||||
} else if (this.type === 'workloads') {
|
||||
updateWorkloads(this.classification, this.clusterName, {
|
||||
metadata: {
|
||||
...this.data.metadata,
|
||||
annotations: {
|
||||
'kubesphere.io/alias-name': this.editInfoForm.aliasName,
|
||||
'kubesphere.io/description': this.editInfoForm.description
|
||||
}
|
||||
},
|
||||
spec: this.data.spec
|
||||
}).then(res => {
|
||||
this.$message.success('操作成功')
|
||||
this.dialogFormVisible = false
|
||||
this.$emit('getList')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,41 @@
|
|||
<template>
|
||||
<!-- 证书显示 -->
|
||||
<el-dialog :close-on-click-modal="false" width="70%" title="交易证书" :visible.sync="dialogCertVisible">
|
||||
<div class="certification">
|
||||
<p>兹证明:<br>
|
||||
申请人 {{ certificationData.buyerName }} 于 {{ certificationData.transTime }} 通过 {{ certificationData.sellerName }} 平台提交了以下电子数据及信息:
|
||||
</p>
|
||||
<FormData :column="1" :data="certificationData" :data-map="certDataMap" />
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.certification{
|
||||
width: 100%;
|
||||
height: 750px;
|
||||
background: url('../../assets/cert_bg.png') white center no-repeat;
|
||||
background-size: auto 100%;
|
||||
text-align: center;
|
||||
padding-top: 120px;
|
||||
p{
|
||||
font-size: 0.8rem;
|
||||
text-align: left;
|
||||
width: 370px;
|
||||
margin: auto;
|
||||
padding: 10px 15px;
|
||||
}
|
||||
table.table.formData {
|
||||
width: 50%;
|
||||
margin: 0 auto;
|
||||
font-size: 0.5rem;
|
||||
td {
|
||||
line-height: 0.9rem;
|
||||
text-align: left;
|
||||
}
|
||||
td:nth-child(odd) {
|
||||
width: 40%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,75 @@
|
|||
<template>
|
||||
<!-- 查看/编辑配置文件 -->
|
||||
<el-dialog :close-on-click-modal="false" width="80%" :title="(isEdit? '编辑': '查看') +'配置文件'" :visible.sync="dialogVisible">
|
||||
<codemirror v-model="codeData" class="code-mirror" :options="cmOption" />
|
||||
<div v-if="isEdit" slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">{{ $t("message.cancel") }}</el-button>
|
||||
<el-button type="primary" @click="submitSettingEdit">更 新</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
code: {
|
||||
type: String,
|
||||
default: ``
|
||||
},
|
||||
isEdit: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
cmOption: {
|
||||
autoCloseBrackets: true,
|
||||
tabSize: 4,
|
||||
styleActiveLine: true,
|
||||
lineNumbers: true,
|
||||
line: true,
|
||||
mode: 'text/x-yaml'
|
||||
// keyMap: "emacs"
|
||||
},
|
||||
codeData: ``
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dialogVisible: {
|
||||
get() {
|
||||
return this.value
|
||||
},
|
||||
set(value) {
|
||||
this.$emit('input', value)
|
||||
}
|
||||
}
|
||||
// codeData: {
|
||||
// get() {
|
||||
// return this.code + ''
|
||||
// },
|
||||
// set(value) {
|
||||
// this.$emit('code', value)
|
||||
// }
|
||||
// }
|
||||
},
|
||||
watch: {
|
||||
code(val) {
|
||||
this.codeData = val
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
submitSettingEdit() {
|
||||
return this.$emit('submitSettingEdit', this.codeData)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,198 @@
|
|||
<template>
|
||||
<!-- 配置文件和密钥 -->
|
||||
<el-dialog v-if="dialogVisible" :close-on-click-modal="false" width="80%" title="配置文件和密钥" :visible.sync="dialogVisible" append-to-body>
|
||||
<el-form ref="settingForm" :model="settingForm">
|
||||
<el-tabs v-model="activeName" type="card" @tab-click="handleClick">
|
||||
<el-tab-pane label="配置字典" name="first">
|
||||
<el-form-item
|
||||
v-if="activeName==='first'"
|
||||
prop="firstName"
|
||||
label=""
|
||||
required
|
||||
>
|
||||
<el-select v-model="settingForm.firstName" class="selectPro" placeholder="请选择配置文件">
|
||||
<el-option
|
||||
v-for="item in configmapList"
|
||||
:key="item.label"
|
||||
:label="item.label"
|
||||
:value="item.label"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="保密字典" name="second">
|
||||
<el-form-item
|
||||
v-if="activeName==='second'"
|
||||
prop="secondName"
|
||||
label=""
|
||||
required
|
||||
>
|
||||
<el-select v-model="settingForm.secondName" class="selectPro" placeholder="请选择配置文件">
|
||||
<el-option
|
||||
v-for="item in secretList"
|
||||
:key="item.label"
|
||||
:label="item.label"
|
||||
:value="item.label"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<table v-if="formData.spec.template.spec.containers">
|
||||
<tr v-for="(item, index) in formData.spec.template.spec.containers" :key="index" class="dataList">
|
||||
<td>容器</td>
|
||||
<td>{{ item.name }}</td>
|
||||
<td>
|
||||
<el-select v-model="createVolumesForm[index].readOnly">
|
||||
<el-option
|
||||
v-for="it in settingMountOptions"
|
||||
:key="it.value"
|
||||
:label="it.label"
|
||||
:value="it.value"
|
||||
/>
|
||||
</el-select>
|
||||
</td>
|
||||
<td><el-input v-model="createVolumesForm[index].mountPath" :disabled="createVolumesForm[index].readOnly == null" placeholder="容器挂载路径, 例如: /data" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button icon="el-icon-close" circle @click="dialogVisible = false" />
|
||||
<el-button icon="el-icon-check" circle @click="ok" />
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { settingMountOptions } from '@/utils/map'
|
||||
import { getConfigmapData, getSecretData } from '@/api/container/workloadManagement'
|
||||
import generate from 'nanoid/generate'
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
formData: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
isEdit: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
createVolumesForm: [],
|
||||
settingForm: {
|
||||
firstName: '',
|
||||
secondName: ''
|
||||
},
|
||||
configmapList: [],
|
||||
secretList: [],
|
||||
activeName: 'first',
|
||||
settingMountOptions
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
clusterName() {
|
||||
return localStorage.getItem('clusterName')
|
||||
},
|
||||
dialogVisible: {
|
||||
get() {
|
||||
return this.value
|
||||
},
|
||||
set(value) {
|
||||
this.$emit('input', value)
|
||||
}
|
||||
}
|
||||
// codeData: {
|
||||
// get() {
|
||||
// return this.code + ''
|
||||
// },
|
||||
// set(value) {
|
||||
// this.$emit('code', value)
|
||||
// }
|
||||
// }
|
||||
},
|
||||
watch: {
|
||||
'formData.spec.template.spec.containers': {
|
||||
handler(val) {
|
||||
this.createVolumesForm = []
|
||||
for (let i = 0; i < this.formData.spec.template.spec.containers.length; i++) {
|
||||
this.createVolumesForm.push({ readOnly: null, mountPath: '' })
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
// code(val) {
|
||||
// this.codeData = val
|
||||
// }
|
||||
},
|
||||
mounted() {
|
||||
this.getConfigmapList()
|
||||
this.getSecretList()
|
||||
},
|
||||
methods: {
|
||||
getConfigmapList() {
|
||||
getConfigmapData({ clusterName: this.clusterName, namespace: this.formData.metadata.namespace }).then(res => {
|
||||
const arr = res.data.map(e => { return { label: e.metadata.name } })
|
||||
this.configmapList = arr
|
||||
})
|
||||
},
|
||||
getSecretList() {
|
||||
getSecretData({ clusterName: this.clusterName, namespace: this.formData.metadata.namespace }).then(res => {
|
||||
const arr = res.data.map(e => { return { label: e.metadata.name } })
|
||||
this.secretList = arr
|
||||
})
|
||||
},
|
||||
ok() {
|
||||
this.$refs.settingForm.validate((valid) => {
|
||||
if (valid) {
|
||||
// 存在容器挂载
|
||||
const newFormData = Object.assign({}, this.formData)
|
||||
let newSpecVolume = {}
|
||||
switch (this.activeName) {
|
||||
case 'first':
|
||||
newSpecVolume = {
|
||||
name: `volume-${generate('0123456789abcdefghijklmnopqrstuvwxyz', 6)}`,
|
||||
configMap: { name: this.settingForm[this.activeName + 'Name'] }
|
||||
}
|
||||
break
|
||||
case 'second':
|
||||
newSpecVolume = {
|
||||
name: `volume-${generate('0123456789abcdefghijklmnopqrstuvwxyz', 6)}`,
|
||||
secret: { secretName: this.settingForm[this.activeName + 'Name'] }
|
||||
}
|
||||
break
|
||||
}
|
||||
newFormData.spec.template.spec.containers.forEach((e, index) => {
|
||||
if (this.createVolumesForm[index]?.readOnly !== null) {
|
||||
if (!e.volumeMounts) { e.volumeMounts = [] }
|
||||
e.volumeMounts.push({
|
||||
name: newSpecVolume.name,
|
||||
readOnly: this.createVolumesForm[index]?.readOnly,
|
||||
mountPath: this.createVolumesForm[index]?.mountPath
|
||||
})
|
||||
}
|
||||
})
|
||||
newFormData.spec.template.spec.volumes.push(newSpecVolume)
|
||||
|
||||
this.$emit('addSettingOrKey', newFormData)
|
||||
this.dialogVisible = false
|
||||
}
|
||||
})
|
||||
},
|
||||
handleClick() {}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,23 @@
|
|||
<template>
|
||||
<div />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
// get http://119.45.100.73:30880/kapis/tenant.kubesphere.io/v1alpha2/workspaces?sortBy=createTime&limit=10
|
||||
// get http://119.45.100.73:30880/kapis/iam.kubesphere.io/v1alpha2/workspaces/{system-workspace}/workspacemembers?sortBy=createTime&limit=10
|
||||
|
||||
// http://119.45.100.73:30880/api/clusters/bj-member2/v1/namespaces/kube-federation-system
|
||||
|
||||
// {
|
||||
// "metadata": {
|
||||
// "labels": {
|
||||
// "kubesphere.io/workspace":"system-workspace"
|
||||
// },
|
||||
// "annotations": {
|
||||
// "kubesphere.io/creator":"admin"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,86 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-upload
|
||||
class="avatar-uploader"
|
||||
action="#"
|
||||
:limit="1"
|
||||
:http-request="httpRequest"
|
||||
:show-file-list="false"
|
||||
>
|
||||
<img v-if="imageUrl" :src="imageUrl" class="avatar">
|
||||
<i v-else class="el-icon-plus avatar-uploader-icon" />
|
||||
</el-upload>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { uploadImage } from '@/api/container/monitorSelect'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
imageUrl: {
|
||||
get() {
|
||||
return this.value
|
||||
},
|
||||
set(value) {
|
||||
this.$emit('input', value)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
httpRequest(data) {
|
||||
// const isJar = data.file.name.indexOf('.jar') === (data.file.name.length - 4)
|
||||
// const isJPG = data.file.type === 'image/jpeg'
|
||||
// const isLt2M = data.file.size / 1024 / 1024 < 2
|
||||
// if (!isJPG) {
|
||||
// this.$message.error('上传文件只能是 JPG 格式!')
|
||||
// } else {
|
||||
// 转base64
|
||||
const form = new FormData()
|
||||
form.set('file', data.file)
|
||||
form.set('mode', '1')
|
||||
uploadImage(form).then((e) => {
|
||||
if (e.code === 200) {
|
||||
// console.log(e) e.url
|
||||
this.imageUrl = e.data[0].url
|
||||
this.$message.success('文件上传成功')
|
||||
}
|
||||
})
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.avatar-uploader .el-upload {
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.avatar-uploader .el-upload:hover {
|
||||
border-color: #409EFF;
|
||||
}
|
||||
.avatar-uploader-icon {
|
||||
border: 1px dashed #d9d9d9;
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
line-height: 100px;
|
||||
text-align: center;
|
||||
}
|
||||
.avatar {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,111 @@
|
|||
<template>
|
||||
<transition :name="transitionName">
|
||||
<div v-show="visible" :style="customStyle" class="back-to-ceiling" @click="backToTop">
|
||||
<svg width="16" height="16" viewBox="0 0 17 17" xmlns="http://www.w3.org/2000/svg" class="Icon Icon--backToTopArrow" aria-hidden="true" style="height:16px;width:16px"><path d="M12.036 15.59a1 1 0 0 1-.997.995H5.032a.996.996 0 0 1-.997-.996V8.584H1.03c-1.1 0-1.36-.633-.578-1.416L7.33.29a1.003 1.003 0 0 1 1.412 0l6.878 6.88c.782.78.523 1.415-.58 1.415h-3.004v7.004z" /></svg>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'BackToTop',
|
||||
props: {
|
||||
visibilityHeight: {
|
||||
type: Number,
|
||||
default: 400
|
||||
},
|
||||
backPosition: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
customStyle: {
|
||||
type: Object,
|
||||
default: function() {
|
||||
return {
|
||||
right: '50px',
|
||||
bottom: '50px',
|
||||
width: '40px',
|
||||
height: '40px',
|
||||
'border-radius': '4px',
|
||||
'line-height': '45px',
|
||||
background: '#e7eaf1'
|
||||
}
|
||||
}
|
||||
},
|
||||
transitionName: {
|
||||
type: String,
|
||||
default: 'fade'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
interval: null,
|
||||
isMoving: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
window.addEventListener('scroll', this.handleScroll)
|
||||
},
|
||||
beforeDestroy() {
|
||||
window.removeEventListener('scroll', this.handleScroll)
|
||||
if (this.interval) {
|
||||
clearInterval(this.interval)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleScroll() {
|
||||
this.visible = window.pageYOffset > this.visibilityHeight
|
||||
},
|
||||
backToTop() {
|
||||
if (this.isMoving) return
|
||||
const start = window.pageYOffset
|
||||
let i = 0
|
||||
this.isMoving = true
|
||||
this.interval = setInterval(() => {
|
||||
const next = Math.floor(this.easeInOutQuad(10 * i, start, -start, 500))
|
||||
if (next <= this.backPosition) {
|
||||
window.scrollTo(0, this.backPosition)
|
||||
clearInterval(this.interval)
|
||||
this.isMoving = false
|
||||
} else {
|
||||
window.scrollTo(0, next)
|
||||
}
|
||||
i++
|
||||
}, 16.7)
|
||||
},
|
||||
easeInOutQuad(t, b, c, d) {
|
||||
if ((t /= d / 2) < 1) return c / 2 * t * t + b
|
||||
return -c / 2 * (--t * (t - 2) - 1) + b
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.back-to-ceiling {
|
||||
position: fixed;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.back-to-ceiling:hover {
|
||||
background: #d5dbe7;
|
||||
}
|
||||
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
transition: opacity .5s;
|
||||
}
|
||||
|
||||
.fade-enter,
|
||||
.fade-leave-to {
|
||||
opacity: 0
|
||||
}
|
||||
|
||||
.back-to-ceiling .Icon {
|
||||
fill: #9aaabf;
|
||||
background: none;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,92 @@
|
|||
<template>
|
||||
<div>
|
||||
<a href="/monitor/overview"><img class="logo" src="@/assets/JCCE-logo.png" alt=""></a>
|
||||
<el-breadcrumb class="app-breadcrumb" separator="/">
|
||||
<transition-group name="breadcrumb">
|
||||
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
|
||||
<span v-if="item.redirect==='noRedirect'||index==levelList.length-1" class="no-redirect">{{ item.meta.title }}</span>
|
||||
<a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
|
||||
</el-breadcrumb-item>
|
||||
</transition-group>
|
||||
</el-breadcrumb>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import pathToRegexp from 'path-to-regexp'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
levelList: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
$route(route) {
|
||||
// if you go to the redirect page, do not update the breadcrumbs
|
||||
if (route.path.startsWith('/redirect/')) {
|
||||
return
|
||||
}
|
||||
this.getBreadcrumb()
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getBreadcrumb()
|
||||
},
|
||||
methods: {
|
||||
getBreadcrumb() {
|
||||
// only show routes with meta.title
|
||||
let matched = this.$route.matched.filter(item => item.meta && item.meta.title)
|
||||
const first = matched[0]
|
||||
|
||||
if (!this.isDashboard(first)) {
|
||||
matched = [].concat(matched)
|
||||
}
|
||||
|
||||
this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
|
||||
},
|
||||
isDashboard(route) {
|
||||
const name = route && route.name
|
||||
if (!name) {
|
||||
return false
|
||||
}
|
||||
return name.trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase()
|
||||
},
|
||||
pathCompile(path) {
|
||||
// To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
|
||||
const { params } = this.$route
|
||||
var toPath = pathToRegexp.compile(path)
|
||||
return toPath(params)
|
||||
},
|
||||
handleLink(item) {
|
||||
const { redirect, path } = item
|
||||
if (redirect) {
|
||||
this.$router.push(redirect)
|
||||
return
|
||||
}
|
||||
this.$router.push(this.pathCompile(path))
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.logo{
|
||||
height: 40px;
|
||||
margin-top: 5px;
|
||||
display: block;
|
||||
float: left;
|
||||
}
|
||||
.app-breadcrumb.el-breadcrumb {
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
line-height: 50px;
|
||||
margin-left: 8px;
|
||||
|
||||
.no-redirect {
|
||||
color: #97a8be;
|
||||
cursor: text;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,155 @@
|
|||
<template>
|
||||
<div :id="id" :class="className" :style="{height:height,width:width}" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import resize from './mixins/resize'
|
||||
|
||||
export default {
|
||||
mixins: [resize],
|
||||
props: {
|
||||
className: {
|
||||
type: String,
|
||||
default: 'chart'
|
||||
},
|
||||
id: {
|
||||
type: String,
|
||||
default: 'chart'
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default: '200px'
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: '200px'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
chart: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initChart()
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (!this.chart) {
|
||||
return
|
||||
}
|
||||
this.chart.dispose()
|
||||
this.chart = null
|
||||
},
|
||||
methods: {
|
||||
initChart() {
|
||||
this.chart = echarts.init(document.getElementById(this.id))
|
||||
|
||||
const xAxisData = []
|
||||
const data = []
|
||||
const data2 = []
|
||||
for (let i = 0; i < 50; i++) {
|
||||
xAxisData.push(i)
|
||||
data.push((Math.sin(i / 5) * (i / 5 - 10) + i / 6) * 5)
|
||||
data2.push((Math.sin(i / 5) * (i / 5 + 10) + i / 6) * 3)
|
||||
}
|
||||
this.chart.setOption({
|
||||
backgroundColor: '#08263a',
|
||||
grid: {
|
||||
left: '5%',
|
||||
right: '5%'
|
||||
},
|
||||
xAxis: [{
|
||||
show: false,
|
||||
data: xAxisData
|
||||
}, {
|
||||
show: false,
|
||||
data: xAxisData
|
||||
}],
|
||||
visualMap: {
|
||||
show: false,
|
||||
min: 0,
|
||||
max: 50,
|
||||
dimension: 0,
|
||||
inRange: {
|
||||
color: ['#4a657a', '#308e92', '#b1cfa5', '#f5d69f', '#f5898b', '#ef5055']
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
axisLine: {
|
||||
show: false
|
||||
},
|
||||
axisLabel: {
|
||||
textStyle: {
|
||||
color: '#4a657a'
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
color: '#08263f'
|
||||
}
|
||||
},
|
||||
axisTick: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
series: [{
|
||||
name: 'back',
|
||||
type: 'bar',
|
||||
data: data2,
|
||||
z: 1,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
opacity: 0.4,
|
||||
barBorderRadius: 5,
|
||||
shadowBlur: 3,
|
||||
shadowColor: '#111'
|
||||
}
|
||||
}
|
||||
}, {
|
||||
name: 'Simulate Shadow',
|
||||
type: 'line',
|
||||
data,
|
||||
z: 2,
|
||||
showSymbol: false,
|
||||
animationDelay: 0,
|
||||
animationEasing: 'linear',
|
||||
animationDuration: 1200,
|
||||
lineStyle: {
|
||||
normal: {
|
||||
color: 'transparent'
|
||||
}
|
||||
},
|
||||
areaStyle: {
|
||||
normal: {
|
||||
color: '#08263a',
|
||||
shadowBlur: 50,
|
||||
shadowColor: '#000'
|
||||
}
|
||||
}
|
||||
}, {
|
||||
name: 'front',
|
||||
type: 'bar',
|
||||
data,
|
||||
xAxisIndex: 1,
|
||||
z: 3,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
barBorderRadius: 5
|
||||
}
|
||||
}
|
||||
}],
|
||||
animationEasing: 'elasticOut',
|
||||
animationEasingUpdate: 'elasticOut',
|
||||
animationDelay(idx) {
|
||||
return idx * 20
|
||||
},
|
||||
animationDelayUpdate(idx) {
|
||||
return idx * 20
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,227 @@
|
|||
<template>
|
||||
<div :id="id" :class="className" :style="{height:height,width:width}" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import resize from './mixins/resize'
|
||||
|
||||
export default {
|
||||
mixins: [resize],
|
||||
props: {
|
||||
className: {
|
||||
type: String,
|
||||
default: 'chart'
|
||||
},
|
||||
id: {
|
||||
type: String,
|
||||
default: 'chart'
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default: '200px'
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: '200px'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
chart: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initChart()
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (!this.chart) {
|
||||
return
|
||||
}
|
||||
this.chart.dispose()
|
||||
this.chart = null
|
||||
},
|
||||
methods: {
|
||||
initChart() {
|
||||
this.chart = echarts.init(document.getElementById(this.id))
|
||||
|
||||
this.chart.setOption({
|
||||
backgroundColor: '#394056',
|
||||
title: {
|
||||
top: 20,
|
||||
text: 'Requests',
|
||||
textStyle: {
|
||||
fontWeight: 'normal',
|
||||
fontSize: 16,
|
||||
color: '#F1F1F3'
|
||||
},
|
||||
left: '1%'
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
lineStyle: {
|
||||
color: '#57617B'
|
||||
}
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
top: 20,
|
||||
icon: 'rect',
|
||||
itemWidth: 14,
|
||||
itemHeight: 5,
|
||||
itemGap: 13,
|
||||
data: ['CMCC', 'CTCC', 'CUCC'],
|
||||
right: '4%',
|
||||
textStyle: {
|
||||
fontSize: 12,
|
||||
color: '#F1F1F3'
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
top: 100,
|
||||
left: '2%',
|
||||
right: '2%',
|
||||
bottom: '2%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: [{
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: '#57617B'
|
||||
}
|
||||
},
|
||||
data: ['13:00', '13:05', '13:10', '13:15', '13:20', '13:25', '13:30', '13:35', '13:40', '13:45', '13:50', '13:55']
|
||||
}],
|
||||
yAxis: [{
|
||||
type: 'value',
|
||||
name: '(%)',
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: '#57617B'
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
margin: 10,
|
||||
textStyle: {
|
||||
fontSize: 14
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: '#57617B'
|
||||
}
|
||||
}
|
||||
}],
|
||||
series: [{
|
||||
name: 'CMCC',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
symbol: 'circle',
|
||||
symbolSize: 5,
|
||||
showSymbol: false,
|
||||
lineStyle: {
|
||||
normal: {
|
||||
width: 1
|
||||
}
|
||||
},
|
||||
areaStyle: {
|
||||
normal: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
||||
offset: 0,
|
||||
color: 'rgba(137, 189, 27, 0.3)'
|
||||
}, {
|
||||
offset: 0.8,
|
||||
color: 'rgba(137, 189, 27, 0)'
|
||||
}], false),
|
||||
shadowColor: 'rgba(0, 0, 0, 0.1)',
|
||||
shadowBlur: 10
|
||||
}
|
||||
},
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: 'rgb(137,189,27)',
|
||||
borderColor: 'rgba(137,189,2,0.27)',
|
||||
borderWidth: 12
|
||||
|
||||
}
|
||||
},
|
||||
data: [220, 182, 191, 134, 150, 120, 110, 125, 145, 122, 165, 122]
|
||||
}, {
|
||||
name: 'CTCC',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
symbol: 'circle',
|
||||
symbolSize: 5,
|
||||
showSymbol: false,
|
||||
lineStyle: {
|
||||
normal: {
|
||||
width: 1
|
||||
}
|
||||
},
|
||||
areaStyle: {
|
||||
normal: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
||||
offset: 0,
|
||||
color: 'rgba(0, 136, 212, 0.3)'
|
||||
}, {
|
||||
offset: 0.8,
|
||||
color: 'rgba(0, 136, 212, 0)'
|
||||
}], false),
|
||||
shadowColor: 'rgba(0, 0, 0, 0.1)',
|
||||
shadowBlur: 10
|
||||
}
|
||||
},
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: 'rgb(0,136,212)',
|
||||
borderColor: 'rgba(0,136,212,0.2)',
|
||||
borderWidth: 12
|
||||
|
||||
}
|
||||
},
|
||||
data: [120, 110, 125, 145, 122, 165, 122, 220, 182, 191, 134, 150]
|
||||
}, {
|
||||
name: 'CUCC',
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
symbol: 'circle',
|
||||
symbolSize: 5,
|
||||
showSymbol: false,
|
||||
lineStyle: {
|
||||
normal: {
|
||||
width: 1
|
||||
}
|
||||
},
|
||||
areaStyle: {
|
||||
normal: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
||||
offset: 0,
|
||||
color: 'rgba(219, 50, 51, 0.3)'
|
||||
}, {
|
||||
offset: 0.8,
|
||||
color: 'rgba(219, 50, 51, 0)'
|
||||
}], false),
|
||||
shadowColor: 'rgba(0, 0, 0, 0.1)',
|
||||
shadowBlur: 10
|
||||
}
|
||||
},
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: 'rgb(219,50,51)',
|
||||
borderColor: 'rgba(219,50,51,0.2)',
|
||||
borderWidth: 12
|
||||
}
|
||||
},
|
||||
data: [220, 182, 125, 145, 122, 191, 134, 150, 120, 110, 165, 122]
|
||||
}]
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,271 @@
|
|||
<template>
|
||||
<div :id="id" :class="className" :style="{height:height,width:width}" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import resize from './mixins/resize'
|
||||
|
||||
export default {
|
||||
mixins: [resize],
|
||||
props: {
|
||||
className: {
|
||||
type: String,
|
||||
default: 'chart'
|
||||
},
|
||||
id: {
|
||||
type: String,
|
||||
default: 'chart'
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default: '200px'
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: '200px'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
chart: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initChart()
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (!this.chart) {
|
||||
return
|
||||
}
|
||||
this.chart.dispose()
|
||||
this.chart = null
|
||||
},
|
||||
methods: {
|
||||
initChart() {
|
||||
this.chart = echarts.init(document.getElementById(this.id))
|
||||
const xData = (function() {
|
||||
const data = []
|
||||
for (let i = 1; i < 13; i++) {
|
||||
data.push(i + 'month')
|
||||
}
|
||||
return data
|
||||
}())
|
||||
this.chart.setOption({
|
||||
backgroundColor: '#344b58',
|
||||
title: {
|
||||
text: 'statistics',
|
||||
x: '20',
|
||||
top: '20',
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
fontSize: '22'
|
||||
},
|
||||
subtextStyle: {
|
||||
color: '#90979c',
|
||||
fontSize: '16'
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
textStyle: {
|
||||
color: '#fff'
|
||||
}
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '5%',
|
||||
right: '5%',
|
||||
borderWidth: 0,
|
||||
top: 150,
|
||||
bottom: 95,
|
||||
textStyle: {
|
||||
color: '#fff'
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
x: '5%',
|
||||
top: '10%',
|
||||
textStyle: {
|
||||
color: '#90979c'
|
||||
},
|
||||
data: ['female', 'male', 'average']
|
||||
},
|
||||
calculable: true,
|
||||
xAxis: [{
|
||||
type: 'category',
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: '#90979c'
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
show: false
|
||||
},
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
splitArea: {
|
||||
show: false
|
||||
},
|
||||
axisLabel: {
|
||||
interval: 0
|
||||
|
||||
},
|
||||
data: xData
|
||||
}],
|
||||
yAxis: [{
|
||||
type: 'value',
|
||||
splitLine: {
|
||||
show: false
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: '#90979c'
|
||||
}
|
||||
},
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
axisLabel: {
|
||||
interval: 0
|
||||
},
|
||||
splitArea: {
|
||||
show: false
|
||||
}
|
||||
}],
|
||||
dataZoom: [{
|
||||
show: true,
|
||||
height: 30,
|
||||
xAxisIndex: [
|
||||
0
|
||||
],
|
||||
bottom: 30,
|
||||
start: 10,
|
||||
end: 80,
|
||||
handleIcon: 'path://M306.1,413c0,2.2-1.8,4-4,4h-59.8c-2.2,0-4-1.8-4-4V200.8c0-2.2,1.8-4,4-4h59.8c2.2,0,4,1.8,4,4V413z',
|
||||
handleSize: '110%',
|
||||
handleStyle: {
|
||||
color: '#d3dee5'
|
||||
|
||||
},
|
||||
textStyle: {
|
||||
color: '#fff' },
|
||||
borderColor: '#90979c'
|
||||
|
||||
}, {
|
||||
type: 'inside',
|
||||
show: true,
|
||||
height: 15,
|
||||
start: 1,
|
||||
end: 35
|
||||
}],
|
||||
series: [{
|
||||
name: 'female',
|
||||
type: 'bar',
|
||||
stack: 'total',
|
||||
barMaxWidth: 35,
|
||||
barGap: '10%',
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: 'rgba(255,144,128,1)',
|
||||
label: {
|
||||
show: true,
|
||||
textStyle: {
|
||||
color: '#fff'
|
||||
},
|
||||
position: 'insideTop',
|
||||
formatter(p) {
|
||||
return p.value > 0 ? p.value : ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
data: [
|
||||
709,
|
||||
1917,
|
||||
2455,
|
||||
2610,
|
||||
1719,
|
||||
1433,
|
||||
1544,
|
||||
3285,
|
||||
5208,
|
||||
3372,
|
||||
2484,
|
||||
4078
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
name: 'male',
|
||||
type: 'bar',
|
||||
stack: 'total',
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: 'rgba(0,191,183,1)',
|
||||
barBorderRadius: 0,
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
formatter(p) {
|
||||
return p.value > 0 ? p.value : ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
data: [
|
||||
327,
|
||||
1776,
|
||||
507,
|
||||
1200,
|
||||
800,
|
||||
482,
|
||||
204,
|
||||
1390,
|
||||
1001,
|
||||
951,
|
||||
381,
|
||||
220
|
||||
]
|
||||
}, {
|
||||
name: 'average',
|
||||
type: 'line',
|
||||
stack: 'total',
|
||||
symbolSize: 10,
|
||||
symbol: 'circle',
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: 'rgba(252,230,48,1)',
|
||||
barBorderRadius: 0,
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
formatter(p) {
|
||||
return p.value > 0 ? p.value : ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
data: [
|
||||
1036,
|
||||
3693,
|
||||
2962,
|
||||
3810,
|
||||
2519,
|
||||
1915,
|
||||
1748,
|
||||
4675,
|
||||
6209,
|
||||
4323,
|
||||
2865,
|
||||
4298
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,56 @@
|
|||
import { debounce } from '@/utils'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
$_sidebarElm: null,
|
||||
$_resizeHandler: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initListener()
|
||||
},
|
||||
activated() {
|
||||
if (!this.$_resizeHandler) {
|
||||
// avoid duplication init
|
||||
this.initListener()
|
||||
}
|
||||
|
||||
// when keep-alive chart activated, auto resize
|
||||
this.resize()
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.destroyListener()
|
||||
},
|
||||
deactivated() {
|
||||
this.destroyListener()
|
||||
},
|
||||
methods: {
|
||||
// use $_ for mixins properties
|
||||
// https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
|
||||
$_sidebarResizeHandler(e) {
|
||||
if (e.propertyName === 'width') {
|
||||
this.$_resizeHandler()
|
||||
}
|
||||
},
|
||||
initListener() {
|
||||
this.$_resizeHandler = debounce(() => {
|
||||
this.resize()
|
||||
}, 100)
|
||||
window.addEventListener('resize', this.$_resizeHandler)
|
||||
|
||||
this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0]
|
||||
this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler)
|
||||
},
|
||||
destroyListener() {
|
||||
window.removeEventListener('resize', this.$_resizeHandler)
|
||||
this.$_resizeHandler = null
|
||||
|
||||
this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler)
|
||||
},
|
||||
resize() {
|
||||
const { chart } = this
|
||||
chart && chart.resize()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
<template>
|
||||
<div class="dndList">
|
||||
<div :style="{width:width1}" class="dndList-list">
|
||||
<h3>{{ list1Title }}</h3>
|
||||
<draggable :set-data="setData" :list="list1" group="article" class="dragArea">
|
||||
<div v-for="element in list1" :key="element.id" class="list-complete-item">
|
||||
<div class="list-complete-item-handle">
|
||||
{{ element.id }}[{{ element.author }}] {{ element.title }}
|
||||
</div>
|
||||
<div style="position:absolute;right:0px;">
|
||||
<span style="float: right ;margin-top: -20px;margin-right:5px;" @click="deleteEle(element)">
|
||||
<i style="color:#ff4949" class="el-icon-delete" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</draggable>
|
||||
</div>
|
||||
<div :style="{width:width2}" class="dndList-list">
|
||||
<h3>{{ list2Title }}</h3>
|
||||
<draggable :list="list2" group="article" class="dragArea">
|
||||
<div v-for="element in list2" :key="element.id" class="list-complete-item">
|
||||
<div class="list-complete-item-handle2" @click="pushEle(element)">
|
||||
{{ element.id }} [{{ element.author }}] {{ element.title }}
|
||||
</div>
|
||||
</div>
|
||||
</draggable>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import draggable from 'vuedraggable'
|
||||
|
||||
export default {
|
||||
name: 'DndList',
|
||||
components: { draggable },
|
||||
props: {
|
||||
list1: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
list2: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
list1Title: {
|
||||
type: String,
|
||||
default: 'list1'
|
||||
},
|
||||
list2Title: {
|
||||
type: String,
|
||||
default: 'list2'
|
||||
},
|
||||
width1: {
|
||||
type: String,
|
||||
default: '48%'
|
||||
},
|
||||
width2: {
|
||||
type: String,
|
||||
default: '48%'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
isNotInList1(v) {
|
||||
return this.list1.every(k => v.id !== k.id)
|
||||
},
|
||||
isNotInList2(v) {
|
||||
return this.list2.every(k => v.id !== k.id)
|
||||
},
|
||||
deleteEle(ele) {
|
||||
for (const item of this.list1) {
|
||||
if (item.id === ele.id) {
|
||||
const index = this.list1.indexOf(item)
|
||||
this.list1.splice(index, 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
if (this.isNotInList2(ele)) {
|
||||
this.list2.unshift(ele)
|
||||
}
|
||||
},
|
||||
pushEle(ele) {
|
||||
for (const item of this.list2) {
|
||||
if (item.id === ele.id) {
|
||||
const index = this.list2.indexOf(item)
|
||||
this.list2.splice(index, 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
if (this.isNotInList1(ele)) {
|
||||
this.list1.push(ele)
|
||||
}
|
||||
},
|
||||
setData(dataTransfer) {
|
||||
// to avoid Firefox bug
|
||||
// Detail see : https://github.com/RubaXa/Sortable/issues/1012
|
||||
dataTransfer.setData('Text', '')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.dndList {
|
||||
background: #fff;
|
||||
padding-bottom: 40px;
|
||||
&:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
.dndList-list {
|
||||
float: left;
|
||||
padding-bottom: 30px;
|
||||
&:first-of-type {
|
||||
margin-right: 2%;
|
||||
}
|
||||
.dragArea {
|
||||
margin-top: 15px;
|
||||
min-height: 50px;
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list-complete-item {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
font-size: 14px;
|
||||
padding: 5px 12px;
|
||||
margin-top: 4px;
|
||||
border: 1px solid #bfcbd9;
|
||||
transition: all 1s;
|
||||
}
|
||||
|
||||
.list-complete-item-handle {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
margin-right: 50px;
|
||||
}
|
||||
|
||||
.list-complete-item-handle2 {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.list-complete-item.sortable-chosen {
|
||||
background: #4AB7BD;
|
||||
}
|
||||
|
||||
.list-complete-item.sortable-ghost {
|
||||
background: #30B08F;
|
||||
}
|
||||
|
||||
.list-complete-enter,
|
||||
.list-complete-leave-active {
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,41 @@
|
|||
export const FormData = {
|
||||
props: {
|
||||
data: { type: Object },
|
||||
dataMap: { type: Object },
|
||||
columns: { type: Number, default: 2 }
|
||||
// column: { type: Number, default: 2 }
|
||||
},
|
||||
render(h) {
|
||||
const formatDate = (e) => {
|
||||
return new Date(e).toLocaleString()
|
||||
}
|
||||
const td = (e) => {
|
||||
const res = []
|
||||
for (const k in e) {
|
||||
res.push(<td style='width: 18%'>{this.dataMap[e[k]]}</td>)
|
||||
res.push(<td style='width: 32%'>{this.dataMap[e[k]].indexOf('时间') > -1 ? formatDate(this.data[e[k]]) : this.data[e[k] || '-']}</td>)
|
||||
}
|
||||
return res
|
||||
}
|
||||
const list = () => {
|
||||
const res = []
|
||||
const liData = []
|
||||
// 分组
|
||||
for (let i = 0; i < Object.keys(this.dataMap).length; i += this.columns) {
|
||||
res.push(Object.keys(this.dataMap).slice(i, i + this.columns))
|
||||
}
|
||||
for (const i in res) {
|
||||
liData.push(<tr>
|
||||
{td(res[i])}
|
||||
</tr>)
|
||||
}
|
||||
return liData
|
||||
}
|
||||
|
||||
return (
|
||||
<table class='table formData'>
|
||||
{list()}
|
||||
</table>
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,181 @@
|
|||
<template>
|
||||
<div :class="{'show':show}" class="header-search">
|
||||
<svg-icon class-name="search-icon" icon-class="search" @click.stop="click" />
|
||||
<el-select
|
||||
ref="headerSearchSelect"
|
||||
v-model="search"
|
||||
:remote-method="querySearch"
|
||||
filterable
|
||||
default-first-option
|
||||
remote
|
||||
placeholder="Search"
|
||||
class="header-search-select"
|
||||
@change="change"
|
||||
>
|
||||
<el-option v-for="item in options" :key="item.path" :value="item" :label="item.title.join(' > ')" />
|
||||
</el-select>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// fuse is a lightweight fuzzy-search module
|
||||
// make search results more in line with expectations
|
||||
import Fuse from 'fuse.js'
|
||||
import path from 'path'
|
||||
|
||||
export default {
|
||||
name: 'HeaderSearch',
|
||||
data() {
|
||||
return {
|
||||
search: '',
|
||||
options: [],
|
||||
searchPool: [],
|
||||
show: false,
|
||||
fuse: undefined
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
routes() {
|
||||
return this.$store.getters.permission_routes
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
routes() {
|
||||
this.searchPool = this.generateRoutes(this.routes)
|
||||
},
|
||||
searchPool(list) {
|
||||
this.initFuse(list)
|
||||
},
|
||||
show(value) {
|
||||
if (value) {
|
||||
document.body.addEventListener('click', this.close)
|
||||
} else {
|
||||
document.body.removeEventListener('click', this.close)
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.searchPool = this.generateRoutes(this.routes)
|
||||
},
|
||||
methods: {
|
||||
click() {
|
||||
this.show = !this.show
|
||||
if (this.show) {
|
||||
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.focus()
|
||||
}
|
||||
},
|
||||
close() {
|
||||
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.blur()
|
||||
this.options = []
|
||||
this.show = false
|
||||
},
|
||||
change(val) {
|
||||
this.$router.push(val.path)
|
||||
this.search = ''
|
||||
this.options = []
|
||||
this.$nextTick(() => {
|
||||
this.show = false
|
||||
})
|
||||
},
|
||||
initFuse(list) {
|
||||
this.fuse = new Fuse(list, {
|
||||
shouldSort: true,
|
||||
threshold: 0.4,
|
||||
location: 0,
|
||||
distance: 100,
|
||||
maxPatternLength: 32,
|
||||
minMatchCharLength: 1,
|
||||
keys: [{
|
||||
name: 'title',
|
||||
weight: 0.7
|
||||
}, {
|
||||
name: 'path',
|
||||
weight: 0.3
|
||||
}]
|
||||
})
|
||||
},
|
||||
// Filter out the routes that can be displayed in the sidebar
|
||||
// And generate the internationalized title
|
||||
generateRoutes(routes, basePath = '/', prefixTitle = []) {
|
||||
let res = []
|
||||
|
||||
for (const router of routes) {
|
||||
// skip hidden router
|
||||
if (router.hidden) { continue }
|
||||
|
||||
const data = {
|
||||
path: path.resolve(basePath, router.path),
|
||||
title: [...prefixTitle]
|
||||
}
|
||||
|
||||
if (router.meta && router.meta.title) {
|
||||
data.title = [...data.title, router.meta.title]
|
||||
|
||||
if (router.redirect !== 'noRedirect') {
|
||||
// only push the routes with title
|
||||
// special case: need to exclude parent router without redirect
|
||||
res.push(data)
|
||||
}
|
||||
}
|
||||
|
||||
// recursive child routes
|
||||
if (router.children) {
|
||||
const tempRoutes = this.generateRoutes(router.children, data.path, data.title)
|
||||
if (tempRoutes.length >= 1) {
|
||||
res = [...res, ...tempRoutes]
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
},
|
||||
querySearch(query) {
|
||||
if (query !== '') {
|
||||
this.options = this.fuse.search(query)
|
||||
} else {
|
||||
this.options = []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.header-search {
|
||||
font-size: 0 !important;
|
||||
|
||||
.search-icon {
|
||||
cursor: pointer;
|
||||
font-size: 18px;
|
||||
vertical-align: middle;
|
||||
height: 4em;
|
||||
}
|
||||
|
||||
.header-search-select {
|
||||
font-size: 18px;
|
||||
transition: width 0.2s;
|
||||
width: 0;
|
||||
overflow: hidden;
|
||||
background: transparent;
|
||||
border-radius: 0;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
|
||||
::v-deep .el-input__inner {
|
||||
border-radius: 0;
|
||||
border: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
box-shadow: none !important;
|
||||
border-bottom: 1px solid #d9d9d9;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
&.show {
|
||||
.header-search-select {
|
||||
width: 210px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,31 @@
|
|||
// doc: https://nhnent.github.io/tui.editor/api/latest/ToastUIEditor.html#ToastUIEditor
|
||||
export default {
|
||||
minHeight: '200px',
|
||||
previewStyle: 'vertical',
|
||||
useCommandShortcut: true,
|
||||
useDefaultHTMLSanitizer: true,
|
||||
usageStatistics: false,
|
||||
hideModeSwitch: false,
|
||||
toolbarItems: [
|
||||
'heading',
|
||||
'bold',
|
||||
'italic',
|
||||
'strike',
|
||||
'divider',
|
||||
'hr',
|
||||
'quote',
|
||||
'divider',
|
||||
'ul',
|
||||
'ol',
|
||||
'task',
|
||||
'indent',
|
||||
'outdent',
|
||||
'divider',
|
||||
'table',
|
||||
'image',
|
||||
'link',
|
||||
'divider',
|
||||
'code',
|
||||
'codeblock'
|
||||
]
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
<template>
|
||||
<div :id="id" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// deps for editor
|
||||
import 'codemirror/lib/codemirror.css' // codemirror
|
||||
import 'tui-editor/dist/tui-editor.css' // editor ui
|
||||
import 'tui-editor/dist/tui-editor-contents.css' // editor content
|
||||
|
||||
import Editor from 'tui-editor'
|
||||
import defaultOptions from './default-options'
|
||||
|
||||
export default {
|
||||
name: 'MarkdownEditor',
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
id: {
|
||||
type: String,
|
||||
required: false,
|
||||
default() {
|
||||
return 'markdown-editor-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
|
||||
}
|
||||
},
|
||||
options: {
|
||||
type: Object,
|
||||
default() {
|
||||
return defaultOptions
|
||||
}
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'markdown'
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '300px'
|
||||
},
|
||||
language: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'en_US' // https://github.com/nhnent/tui.editor/tree/master/src/js/langs
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
editor: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
editorOptions() {
|
||||
const options = Object.assign({}, defaultOptions, this.options)
|
||||
options.initialEditType = this.mode
|
||||
options.height = this.height
|
||||
options.language = this.language
|
||||
return options
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value(newValue, preValue) {
|
||||
if (newValue !== preValue && newValue !== this.editor.getValue()) {
|
||||
this.editor.setValue(newValue)
|
||||
}
|
||||
},
|
||||
language(val) {
|
||||
this.destroyEditor()
|
||||
this.initEditor()
|
||||
},
|
||||
height(newValue) {
|
||||
this.editor.height(newValue)
|
||||
},
|
||||
mode(newValue) {
|
||||
this.editor.changeMode(newValue)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initEditor()
|
||||
},
|
||||
destroyed() {
|
||||
this.destroyEditor()
|
||||
},
|
||||
methods: {
|
||||
initEditor() {
|
||||
this.editor = new Editor({
|
||||
el: document.getElementById(this.id),
|
||||
...this.editorOptions
|
||||
})
|
||||
if (this.value) {
|
||||
this.editor.setValue(this.value)
|
||||
}
|
||||
this.editor.on('change', () => {
|
||||
this.$emit('input', this.editor.getValue())
|
||||
})
|
||||
},
|
||||
destroyEditor() {
|
||||
if (!this.editor) return
|
||||
this.editor.off('change')
|
||||
this.editor.remove()
|
||||
},
|
||||
setValue(value) {
|
||||
this.editor.setValue(value)
|
||||
},
|
||||
getValue() {
|
||||
return this.editor.getValue()
|
||||
},
|
||||
setHtml(value) {
|
||||
this.editor.setHtml(value)
|
||||
},
|
||||
getHtml() {
|
||||
return this.editor.getHtml()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,101 @@
|
|||
<template>
|
||||
<div :class="{'hidden':hidden}" class="pagination-container">
|
||||
<el-pagination
|
||||
:background="background"
|
||||
:current-page.sync="currentPage"
|
||||
:page-size.sync="pageSize"
|
||||
:layout="layout"
|
||||
:page-sizes="pageSizes"
|
||||
:total="total"
|
||||
v-bind="$attrs"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { scrollTo } from '@/utils/scroll-to'
|
||||
|
||||
export default {
|
||||
name: 'Pagination',
|
||||
props: {
|
||||
total: {
|
||||
required: true,
|
||||
type: Number
|
||||
},
|
||||
page: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
limit: {
|
||||
type: Number,
|
||||
default: 20
|
||||
},
|
||||
pageSizes: {
|
||||
type: Array,
|
||||
default() {
|
||||
return [10, 20, 30, 50]
|
||||
}
|
||||
},
|
||||
layout: {
|
||||
type: String,
|
||||
default: 'total, sizes, prev, pager, next, jumper'
|
||||
},
|
||||
background: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
autoScroll: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
hidden: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentPage: {
|
||||
get() {
|
||||
return this.page
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('update:page', val)
|
||||
}
|
||||
},
|
||||
pageSize: {
|
||||
get() {
|
||||
return this.limit
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('update:limit', val)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleSizeChange(val) {
|
||||
this.$emit('pagination', { page: this.currentPage, limit: val })
|
||||
if (this.autoScroll) {
|
||||
scrollTo(0, 800)
|
||||
}
|
||||
},
|
||||
handleCurrentChange(val) {
|
||||
this.$emit('pagination', { page: val, limit: this.pageSize })
|
||||
if (this.autoScroll) {
|
||||
scrollTo(0, 800)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.pagination-container {
|
||||
background: #fff;
|
||||
padding: 32px 16px;
|
||||
}
|
||||
.pagination-container.hidden {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,142 @@
|
|||
<template>
|
||||
<div :style="{zIndex:zIndex,height:height,width:width}" class="pan-item">
|
||||
<div class="pan-info">
|
||||
<div class="pan-info-roles-container">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
<!-- eslint-disable-next-line -->
|
||||
<div :style="{backgroundImage: `url(${image})`}" class="pan-thumb"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'PanThumb',
|
||||
props: {
|
||||
image: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
zIndex: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default: '150px'
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: '150px'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.pan-item {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
cursor: default;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.pan-info-roles-container {
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.pan-thumb {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-position: center center;
|
||||
background-size: cover;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
transform-origin: 95% 40%;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
/* .pan-thumb:after {
|
||||
content: '';
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
top: 40%;
|
||||
left: 95%;
|
||||
margin: -4px 0 0 -4px;
|
||||
background: radial-gradient(ellipse at center, rgba(14, 14, 14, 1) 0%, rgba(125, 126, 125, 1) 100%);
|
||||
box-shadow: 0 0 1px rgba(255, 255, 255, 0.9);
|
||||
} */
|
||||
|
||||
.pan-info {
|
||||
position: absolute;
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
box-shadow: inset 0 0 0 5px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.pan-info h3 {
|
||||
color: #fff;
|
||||
text-transform: uppercase;
|
||||
position: relative;
|
||||
letter-spacing: 2px;
|
||||
font-size: 18px;
|
||||
margin: 0 60px;
|
||||
padding: 22px 0 0 0;
|
||||
height: 85px;
|
||||
font-family: 'Open Sans', Arial, sans-serif;
|
||||
text-shadow: 0 0 1px #fff, 0 1px 2px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.pan-info p {
|
||||
color: #fff;
|
||||
padding: 10px 5px;
|
||||
font-style: italic;
|
||||
margin: 0 30px;
|
||||
font-size: 12px;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.pan-info p a {
|
||||
display: block;
|
||||
color: #333;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
border-radius: 50%;
|
||||
color: #fff;
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
font-size: 9px;
|
||||
letter-spacing: 1px;
|
||||
padding-top: 24px;
|
||||
margin: 7px auto 0;
|
||||
font-family: 'Open Sans', Arial, sans-serif;
|
||||
opacity: 0;
|
||||
transition: transform 0.3s ease-in-out 0.2s, opacity 0.3s ease-in-out 0.2s, background 0.2s linear 0s;
|
||||
transform: translateX(60px) rotate(90deg);
|
||||
}
|
||||
|
||||
.pan-info p a:hover {
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.pan-item:hover .pan-thumb {
|
||||
transform: rotate(-110deg);
|
||||
}
|
||||
|
||||
.pan-item:hover .pan-info p a {
|
||||
opacity: 1;
|
||||
transform: translateX(0px) rotate(0deg);
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,145 @@
|
|||
<template>
|
||||
<div ref="rightPanel" :class="{show:show}" class="rightPanel-container">
|
||||
<div class="rightPanel-background" />
|
||||
<div class="rightPanel">
|
||||
<div class="handle-button" :style="{'top':buttonTop+'px','background-color':theme}" @click="show=!show">
|
||||
<i :class="show?'el-icon-close':'el-icon-setting'" />
|
||||
</div>
|
||||
<div class="rightPanel-items">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { addClass, removeClass } from '@/utils'
|
||||
|
||||
export default {
|
||||
name: 'RightPanel',
|
||||
props: {
|
||||
clickNotClose: {
|
||||
default: false,
|
||||
type: Boolean
|
||||
},
|
||||
buttonTop: {
|
||||
default: 250,
|
||||
type: Number
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
theme() {
|
||||
return this.$store.state.settings.theme
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
show(value) {
|
||||
if (value && !this.clickNotClose) {
|
||||
this.addEventClick()
|
||||
}
|
||||
if (value) {
|
||||
addClass(document.body, 'showRightPanel')
|
||||
} else {
|
||||
removeClass(document.body, 'showRightPanel')
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.insertToBody()
|
||||
},
|
||||
beforeDestroy() {
|
||||
const elx = this.$refs.rightPanel
|
||||
elx.remove()
|
||||
},
|
||||
methods: {
|
||||
addEventClick() {
|
||||
window.addEventListener('click', this.closeSidebar)
|
||||
},
|
||||
closeSidebar(evt) {
|
||||
const parent = evt.target.closest('.rightPanel')
|
||||
if (!parent) {
|
||||
this.show = false
|
||||
window.removeEventListener('click', this.closeSidebar)
|
||||
}
|
||||
},
|
||||
insertToBody() {
|
||||
const elx = this.$refs.rightPanel
|
||||
const body = document.querySelector('body')
|
||||
body.insertBefore(elx, body.firstChild)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.showRightPanel {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
width: calc(100% - 15px);
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.rightPanel-background {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
transition: opacity .3s cubic-bezier(.7, .3, .1, 1);
|
||||
background: rgba(0, 0, 0, .2);
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.rightPanel {
|
||||
width: 100%;
|
||||
max-width: 260px;
|
||||
height: 100vh;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, .05);
|
||||
transition: all .25s cubic-bezier(.7, .3, .1, 1);
|
||||
transform: translate(100%);
|
||||
background: #fff;
|
||||
z-index: 40000;
|
||||
}
|
||||
|
||||
.show {
|
||||
transition: all .3s cubic-bezier(.7, .3, .1, 1);
|
||||
|
||||
.rightPanel-background {
|
||||
z-index: 20000;
|
||||
opacity: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.rightPanel {
|
||||
transform: translate(0);
|
||||
}
|
||||
}
|
||||
|
||||
.handle-button {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
position: absolute;
|
||||
left: -48px;
|
||||
text-align: center;
|
||||
font-size: 24px;
|
||||
border-radius: 6px 0 0 6px !important;
|
||||
z-index: 0;
|
||||
pointer-events: auto;
|
||||
cursor: pointer;
|
||||
color: #fff;
|
||||
line-height: 48px;
|
||||
i {
|
||||
font-size: 24px;
|
||||
line-height: 48px;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,66 @@
|
|||
<template>
|
||||
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
|
||||
<svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
|
||||
<use :xlink:href="iconName" />
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
|
||||
import { isExternal } from '@/utils/validate'
|
||||
import '@/icons/iconfont'
|
||||
|
||||
export default {
|
||||
name: 'SvgIcon',
|
||||
props: {
|
||||
iconClass: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
className: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isExternal() {
|
||||
return isExternal(this.iconClass)
|
||||
},
|
||||
iconName() {
|
||||
return `#icon-${this.iconClass}`
|
||||
},
|
||||
svgClass() {
|
||||
if (this.className) {
|
||||
return 'svg-icon ' + this.className
|
||||
} else {
|
||||
return 'svg-icon'
|
||||
}
|
||||
},
|
||||
styleExternalIcon() {
|
||||
return {
|
||||
mask: `url(${this.iconClass}) no-repeat 50% 50%`,
|
||||
'-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// const sp = document.createElement('script')
|
||||
// sp.src = '//at.alicdn.com/t/font_3285719_pjqspf3oomf.js' // iconfont网站更新了图标时 需要更新此Symbol链接
|
||||
// document.body.appendChild(sp)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.svg-icon {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
vertical-align: -0.34em;
|
||||
fill: currentColor;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.svg-external-icon {
|
||||
background-color: currentColor;
|
||||
mask-size: cover!important;
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,125 @@
|
|||
<template>
|
||||
<div id="xterm" class="xterm" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Terminal } from 'xterm'
|
||||
import { FitAddon } from 'xterm-addon-fit'
|
||||
import { AttachAddon } from 'xterm-addon-attach'
|
||||
|
||||
export default {
|
||||
name: 'Terminal',
|
||||
props: {
|
||||
url: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {
|
||||
cluster: '',
|
||||
podName: '',
|
||||
namespaces: '',
|
||||
container: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initSocket()
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.socket.close()
|
||||
this.term.dispose()
|
||||
},
|
||||
methods: {
|
||||
initTerm() {
|
||||
const term = new Terminal({
|
||||
lineHeight: 1.2,
|
||||
cursorBlink: true,
|
||||
cursorStyle: 'underline',
|
||||
fontSize: 12,
|
||||
fontFamily: "Monaco, Menlo, Consolas, 'Courier New', monospace",
|
||||
theme: {
|
||||
background: '#181d28'
|
||||
}
|
||||
})
|
||||
const attachAddon = new AttachAddon(this.socket)
|
||||
const fitAddon = new FitAddon()
|
||||
term.loadAddon(attachAddon)
|
||||
term.loadAddon(fitAddon)
|
||||
term.open(document.getElementById('xterm'))
|
||||
fitAddon.fit()
|
||||
term.focus()
|
||||
term.writeln('Welcome to xterm.js')
|
||||
term.prompt = () => {
|
||||
term.write('\r\n$ ')
|
||||
}
|
||||
|
||||
// term.onKey(e => {
|
||||
// const printable = !e.domEvent.altKey && !e.domEvent.altGraphKey && !e.domEvent.ctrlKey && !e.domEvent.metaKey;
|
||||
|
||||
// if (e.domEvent.code === 13) {
|
||||
// console.log('baa')
|
||||
// // prompt(term);
|
||||
// term.prompt()
|
||||
// } else if (e.domEvent.code === 8) {
|
||||
// // Do not delete the prompt
|
||||
// if (term._core.buffer.x > 2) {
|
||||
// term.write('\b \b');
|
||||
// }
|
||||
// } else if (printable) {
|
||||
// term.write(e.key);
|
||||
// }
|
||||
// });
|
||||
term.onData((data) => {
|
||||
const order = JSON.stringify({
|
||||
Op: 'stdin',
|
||||
Data: data
|
||||
})
|
||||
this.socket.send(order)
|
||||
})
|
||||
this.term = term
|
||||
},
|
||||
initSocket() {
|
||||
// this.socket = new WebSocket(`ws://${location.host}/${this.getUrl(this.url)}`);
|
||||
this.socket = new WebSocket(`wss://echo.websocket.org`)
|
||||
this.socketOnClose()
|
||||
this.socketOnOpen()
|
||||
this.socketOnMessage()
|
||||
this.socketOnError()
|
||||
},
|
||||
getUrl(url) {
|
||||
return `kapis/terminal.kubesphere.io/v1alpha2${url.cluster}/namespaces/${url.namespaces}/pods/${url.podName}?container=${url.container}&shell=sh`
|
||||
},
|
||||
socketOnMessage() {
|
||||
this.socket.onmessage = (event) => {
|
||||
// 接收推送的消息
|
||||
const data = (typeof JSON.parse(event.data)) === 'object' ? JSON.parse(event.data).Data : event.data
|
||||
console.log(data)
|
||||
|
||||
this.term.write(data)
|
||||
}
|
||||
},
|
||||
socketOnOpen() {
|
||||
this.socket.onopen = () => {
|
||||
// 链接成功后
|
||||
console.log('success')
|
||||
this.initTerm()
|
||||
}
|
||||
},
|
||||
socketOnClose() {
|
||||
this.socket.onclose = () => {
|
||||
// console.log('close socket')
|
||||
}
|
||||
},
|
||||
socketOnError() {
|
||||
this.socket.onerror = (err) => {
|
||||
console.log(err)
|
||||
console.log('socket 链接失败')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,113 @@
|
|||
<template>
|
||||
<a :class="className" class="link--mallki" href="#">
|
||||
{{ text }}
|
||||
<span :data-letters="text" />
|
||||
<span :data-letters="text" />
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
className: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
text: {
|
||||
type: String,
|
||||
default: 'vue-element-admin'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* Mallki */
|
||||
|
||||
.link--mallki {
|
||||
font-weight: 800;
|
||||
color: #4dd9d5;
|
||||
font-family: 'Dosis', sans-serif;
|
||||
-webkit-transition: color 0.5s 0.25s;
|
||||
transition: color 0.5s 0.25s;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
outline: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.link--mallki:hover {
|
||||
-webkit-transition: none;
|
||||
transition: none;
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.link--mallki::before {
|
||||
content: '';
|
||||
width: 100%;
|
||||
height: 6px;
|
||||
margin: -3px 0 0 0;
|
||||
background: #3888fa;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
-webkit-transform: translate3d(-100%, 0, 0);
|
||||
transform: translate3d(-100%, 0, 0);
|
||||
-webkit-transition: -webkit-transform 0.4s;
|
||||
transition: transform 0.4s;
|
||||
-webkit-transition-timing-function: cubic-bezier(0.7, 0, 0.3, 1);
|
||||
transition-timing-function: cubic-bezier(0.7, 0, 0.3, 1);
|
||||
}
|
||||
|
||||
.link--mallki:hover::before {
|
||||
-webkit-transform: translate3d(100%, 0, 0);
|
||||
transform: translate3d(100%, 0, 0);
|
||||
}
|
||||
|
||||
.link--mallki span {
|
||||
position: absolute;
|
||||
height: 50%;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.link--mallki span::before {
|
||||
content: attr(data-letters);
|
||||
color: red;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
color: #3888fa;
|
||||
-webkit-transition: -webkit-transform 0.5s;
|
||||
transition: transform 0.5s;
|
||||
}
|
||||
|
||||
.link--mallki span:nth-child(2) {
|
||||
top: 50%;
|
||||
}
|
||||
|
||||
.link--mallki span:first-child::before {
|
||||
top: 0;
|
||||
-webkit-transform: translate3d(0, 100%, 0);
|
||||
transform: translate3d(0, 100%, 0);
|
||||
}
|
||||
|
||||
.link--mallki span:nth-child(2)::before {
|
||||
bottom: 0;
|
||||
-webkit-transform: translate3d(0, -100%, 0);
|
||||
transform: translate3d(0, -100%, 0);
|
||||
}
|
||||
|
||||
.link--mallki:hover span::before {
|
||||
-webkit-transition-delay: 0.3s;
|
||||
transition-delay: 0.3s;
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
-webkit-transition-timing-function: cubic-bezier(0.2, 1, 0.3, 1);
|
||||
transition-timing-function: cubic-bezier(0.2, 1, 0.3, 1);
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,175 @@
|
|||
<template>
|
||||
<el-color-picker
|
||||
v-model="theme"
|
||||
:predefine="['#409EFF', '#1890ff', '#304156','#212121','#11a983', '#13c2c2', '#6959CD', '#f5222d', ]"
|
||||
class="theme-picker"
|
||||
popper-class="theme-picker-dropdown"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const version = require('element-ui/package.json').version // element-ui version from node_modules
|
||||
const ORIGINAL_THEME = '#409EFF' // default color
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
chalk: '', // content of theme-chalk css
|
||||
theme: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
defaultTheme() {
|
||||
return this.$store.state.settings.theme
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
defaultTheme: {
|
||||
handler: function(val, oldVal) {
|
||||
this.theme = val
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
async theme(val) {
|
||||
const oldVal = this.chalk ? this.theme : ORIGINAL_THEME
|
||||
if (typeof val !== 'string') return
|
||||
const themeCluster = this.getThemeCluster(val.replace('#', ''))
|
||||
const originalCluster = this.getThemeCluster(oldVal.replace('#', ''))
|
||||
console.log(themeCluster, originalCluster)
|
||||
|
||||
const $message = this.$message({
|
||||
message: ' Compiling the theme',
|
||||
customClass: 'theme-message',
|
||||
type: 'success',
|
||||
duration: 0,
|
||||
iconClass: 'el-icon-loading'
|
||||
})
|
||||
|
||||
const getHandler = (variable, id) => {
|
||||
return () => {
|
||||
const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', ''))
|
||||
const newStyle = this.updateStyle(this[variable], originalCluster, themeCluster)
|
||||
|
||||
let styleTag = document.getElementById(id)
|
||||
if (!styleTag) {
|
||||
styleTag = document.createElement('style')
|
||||
styleTag.setAttribute('id', id)
|
||||
document.head.appendChild(styleTag)
|
||||
}
|
||||
styleTag.innerText = newStyle
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.chalk) {
|
||||
const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`
|
||||
await this.getCSSString(url, 'chalk')
|
||||
}
|
||||
|
||||
const chalkHandler = getHandler('chalk', 'chalk-style')
|
||||
|
||||
chalkHandler()
|
||||
|
||||
const styles = [].slice.call(document.querySelectorAll('style'))
|
||||
.filter(style => {
|
||||
const text = style.innerText
|
||||
return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text)
|
||||
})
|
||||
styles.forEach(style => {
|
||||
const { innerText } = style
|
||||
if (typeof innerText !== 'string') return
|
||||
style.innerText = this.updateStyle(innerText, originalCluster, themeCluster)
|
||||
})
|
||||
|
||||
this.$emit('change', val)
|
||||
|
||||
$message.close()
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
updateStyle(style, oldCluster, newCluster) {
|
||||
let newStyle = style
|
||||
oldCluster.forEach((color, index) => {
|
||||
newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index])
|
||||
})
|
||||
return newStyle
|
||||
},
|
||||
|
||||
getCSSString(url, variable) {
|
||||
return new Promise(resolve => {
|
||||
const xhr = new XMLHttpRequest()
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === 4 && xhr.status === 200) {
|
||||
this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '')
|
||||
resolve()
|
||||
}
|
||||
}
|
||||
xhr.open('GET', url)
|
||||
xhr.send()
|
||||
})
|
||||
},
|
||||
|
||||
getThemeCluster(theme) {
|
||||
const tintColor = (color, tint) => {
|
||||
let red = parseInt(color.slice(0, 2), 16)
|
||||
let green = parseInt(color.slice(2, 4), 16)
|
||||
let blue = parseInt(color.slice(4, 6), 16)
|
||||
|
||||
if (tint === 0) { // when primary color is in its rgb space
|
||||
return [red, green, blue].join(',')
|
||||
} else {
|
||||
red += Math.round(tint * (255 - red))
|
||||
green += Math.round(tint * (255 - green))
|
||||
blue += Math.round(tint * (255 - blue))
|
||||
|
||||
red = red.toString(16)
|
||||
green = green.toString(16)
|
||||
blue = blue.toString(16)
|
||||
|
||||
return `#${red}${green}${blue}`
|
||||
}
|
||||
}
|
||||
|
||||
const shadeColor = (color, shade) => {
|
||||
let red = parseInt(color.slice(0, 2), 16)
|
||||
let green = parseInt(color.slice(2, 4), 16)
|
||||
let blue = parseInt(color.slice(4, 6), 16)
|
||||
|
||||
red = Math.round((1 - shade) * red)
|
||||
green = Math.round((1 - shade) * green)
|
||||
blue = Math.round((1 - shade) * blue)
|
||||
|
||||
red = red.toString(16)
|
||||
green = green.toString(16)
|
||||
blue = blue.toString(16)
|
||||
|
||||
return `#${red}${green}${blue}`
|
||||
}
|
||||
|
||||
const clusters = [theme]
|
||||
for (let i = 0; i <= 9; i++) {
|
||||
clusters.push(tintColor(theme, Number((i / 10).toFixed(2))))
|
||||
}
|
||||
clusters.push(shadeColor(theme, 0.1))
|
||||
return clusters
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.theme-message,
|
||||
.theme-picker-dropdown {
|
||||
z-index: 99999 !important;
|
||||
}
|
||||
|
||||
.theme-picker .el-color-picker__trigger {
|
||||
height: 26px !important;
|
||||
width: 26px !important;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.theme-picker-dropdown .el-color-dropdown__link-btn {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,134 @@
|
|||
<template>
|
||||
<div class="upload-container">
|
||||
<el-upload
|
||||
:data="dataObj"
|
||||
:multiple="false"
|
||||
:show-file-list="false"
|
||||
:on-success="handleImageSuccess"
|
||||
class="image-uploader"
|
||||
drag
|
||||
action="https://httpbin.org/post"
|
||||
>
|
||||
<i class="el-icon-upload" />
|
||||
<div class="el-upload__text">
|
||||
将文件拖到此处,或<em>点击上传</em>
|
||||
</div>
|
||||
</el-upload>
|
||||
<div class="image-preview">
|
||||
<div v-show="imageUrl.length>1" class="image-preview-wrapper">
|
||||
<img :src="imageUrl+'?imageView2/1/w/200/h/200'">
|
||||
<div class="image-preview-action">
|
||||
<i class="el-icon-delete" @click="rmImage" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getToken } from '@/api/common/qiniu'
|
||||
|
||||
export default {
|
||||
name: 'SingleImageUpload',
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tempUrl: '',
|
||||
dataObj: { token: '', key: '' }
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
imageUrl() {
|
||||
return this.value
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
rmImage() {
|
||||
this.emitInput('')
|
||||
},
|
||||
emitInput(val) {
|
||||
this.$emit('input', val)
|
||||
},
|
||||
handleImageSuccess() {
|
||||
this.emitInput(this.tempUrl)
|
||||
},
|
||||
beforeUpload() {
|
||||
const _self = this
|
||||
return new Promise((resolve, reject) => {
|
||||
getToken().then(response => {
|
||||
const key = response.data.qiniu_key
|
||||
const token = response.data.qiniu_token
|
||||
_self._data.dataObj.token = token
|
||||
_self._data.dataObj.key = key
|
||||
this.tempUrl = response.data.qiniu_url
|
||||
resolve(true)
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
reject(false)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "~@/styles/mixin.scss";
|
||||
.upload-container {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
@include clearfix;
|
||||
.image-uploader {
|
||||
width: 60%;
|
||||
float: left;
|
||||
}
|
||||
.image-preview {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
position: relative;
|
||||
border: 1px dashed #d9d9d9;
|
||||
float: left;
|
||||
margin-left: 50px;
|
||||
.image-preview-wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.image-preview-action {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
cursor: default;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
opacity: 0;
|
||||
font-size: 20px;
|
||||
background-color: rgba(0, 0, 0, .5);
|
||||
transition: opacity .3s;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
line-height: 200px;
|
||||
.el-icon-delete {
|
||||
font-size: 36px;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
.image-preview-action {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,130 @@
|
|||
<template>
|
||||
<div class="singleImageUpload2 upload-container">
|
||||
<el-upload
|
||||
:data="dataObj"
|
||||
:multiple="false"
|
||||
:show-file-list="false"
|
||||
:on-success="handleImageSuccess"
|
||||
class="image-uploader"
|
||||
drag
|
||||
action="https://httpbin.org/post"
|
||||
>
|
||||
<i class="el-icon-upload" />
|
||||
<div class="el-upload__text">
|
||||
Drag或<em>点击上传</em>
|
||||
</div>
|
||||
</el-upload>
|
||||
<div v-show="imageUrl.length>0" class="image-preview">
|
||||
<div v-show="imageUrl.length>1" class="image-preview-wrapper">
|
||||
<img :src="imageUrl">
|
||||
<div class="image-preview-action">
|
||||
<i class="el-icon-delete" @click="rmImage" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getToken } from '@/api/common/qiniu'
|
||||
|
||||
export default {
|
||||
name: 'SingleImageUpload2',
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tempUrl: '',
|
||||
dataObj: { token: '', key: '' }
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
imageUrl() {
|
||||
return this.value
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
rmImage() {
|
||||
this.emitInput('')
|
||||
},
|
||||
emitInput(val) {
|
||||
this.$emit('input', val)
|
||||
},
|
||||
handleImageSuccess() {
|
||||
this.emitInput(this.tempUrl)
|
||||
},
|
||||
beforeUpload() {
|
||||
const _self = this
|
||||
return new Promise((resolve, reject) => {
|
||||
getToken().then(response => {
|
||||
const key = response.data.qiniu_key
|
||||
const token = response.data.qiniu_token
|
||||
_self._data.dataObj.token = token
|
||||
_self._data.dataObj.key = key
|
||||
this.tempUrl = response.data.qiniu_url
|
||||
resolve(true)
|
||||
}).catch(() => {
|
||||
reject(false)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.upload-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
.image-uploader {
|
||||
height: 100%;
|
||||
}
|
||||
.image-preview {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
border: 1px dashed #d9d9d9;
|
||||
.image-preview-wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.image-preview-action {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
cursor: default;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
opacity: 0;
|
||||
font-size: 20px;
|
||||
background-color: rgba(0, 0, 0, .5);
|
||||
transition: opacity .3s;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
line-height: 200px;
|
||||
.el-icon-delete {
|
||||
font-size: 36px;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
.image-preview-action {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,157 @@
|
|||
<template>
|
||||
<div class="upload-container">
|
||||
<el-upload
|
||||
:data="dataObj"
|
||||
:multiple="false"
|
||||
:show-file-list="false"
|
||||
:on-success="handleImageSuccess"
|
||||
class="image-uploader"
|
||||
drag
|
||||
action="https://httpbin.org/post"
|
||||
>
|
||||
<i class="el-icon-upload" />
|
||||
<div class="el-upload__text">
|
||||
将文件拖到此处,或<em>点击上传</em>
|
||||
</div>
|
||||
</el-upload>
|
||||
<div class="image-preview image-app-preview">
|
||||
<div v-show="imageUrl.length>1" class="image-preview-wrapper">
|
||||
<img :src="imageUrl">
|
||||
<div class="image-preview-action">
|
||||
<i class="el-icon-delete" @click="rmImage" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="image-preview">
|
||||
<div v-show="imageUrl.length>1" class="image-preview-wrapper">
|
||||
<img :src="imageUrl">
|
||||
<div class="image-preview-action">
|
||||
<i class="el-icon-delete" @click="rmImage" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getToken } from '@/api/common/qiniu'
|
||||
|
||||
export default {
|
||||
name: 'SingleImageUpload3',
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tempUrl: '',
|
||||
dataObj: { token: '', key: '' }
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
imageUrl() {
|
||||
return this.value
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
rmImage() {
|
||||
this.emitInput('')
|
||||
},
|
||||
emitInput(val) {
|
||||
this.$emit('input', val)
|
||||
},
|
||||
handleImageSuccess(file) {
|
||||
this.emitInput(file.files.file)
|
||||
},
|
||||
beforeUpload() {
|
||||
const _self = this
|
||||
return new Promise((resolve, reject) => {
|
||||
getToken().then(response => {
|
||||
const key = response.data.qiniu_key
|
||||
const token = response.data.qiniu_token
|
||||
_self._data.dataObj.token = token
|
||||
_self._data.dataObj.key = key
|
||||
this.tempUrl = response.data.qiniu_url
|
||||
resolve(true)
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
reject(false)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "~@/styles/mixin.scss";
|
||||
.upload-container {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
@include clearfix;
|
||||
.image-uploader {
|
||||
width: 35%;
|
||||
float: left;
|
||||
}
|
||||
.image-preview {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
position: relative;
|
||||
border: 1px dashed #d9d9d9;
|
||||
float: left;
|
||||
margin-left: 50px;
|
||||
.image-preview-wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.image-preview-action {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
cursor: default;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
opacity: 0;
|
||||
font-size: 20px;
|
||||
background-color: rgba(0, 0, 0, .5);
|
||||
transition: opacity .3s;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
line-height: 200px;
|
||||
.el-icon-delete {
|
||||
font-size: 36px;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
.image-preview-action {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
.image-app-preview {
|
||||
width: 320px;
|
||||
height: 180px;
|
||||
position: relative;
|
||||
border: 1px dashed #d9d9d9;
|
||||
float: left;
|
||||
margin-left: 50px;
|
||||
.app-fake-conver {
|
||||
height: 44px;
|
||||
position: absolute;
|
||||
width: 100%; // background: rgba(0, 0, 0, .1);
|
||||
text-align: center;
|
||||
line-height: 64px;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,87 @@
|
|||
<template>
|
||||
<!-- 添加键值对 -->
|
||||
<div>
|
||||
<el-form-item
|
||||
v-for="(tag, index) in editTagForm"
|
||||
:key="'tag'+index"
|
||||
label=""
|
||||
>
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="8"><el-input v-model.trim="tag.key" placeholder="键" @blur="blurInput" /></el-col>
|
||||
<el-col :span="8"><el-input v-model="tag.value" placeholder="值" @blur="blurInput" /></el-col>
|
||||
<el-col :span="4"><el-button icon="el-icon-delete" circle @click.prevent="removeTag(tag,index)" /></el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-button type="primary" class="addBtn" plain round :disabled="addTagNumCheck" @click="addTag">{{ btnName }}</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
btnName: {
|
||||
type: String,
|
||||
default: '添加标签'
|
||||
},
|
||||
value: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
editTagForm: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
addTagNumCheck() {
|
||||
let flag = false
|
||||
this.editTagForm.forEach(e => {
|
||||
if (e.key === '') {
|
||||
flag = true
|
||||
}
|
||||
})
|
||||
return flag
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value(val) {
|
||||
this.setValue(val)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.setValue(this.value)
|
||||
},
|
||||
methods: {
|
||||
setValue(val) {
|
||||
const arr = []
|
||||
for (const i in val) {
|
||||
arr.push({ key: i, value: val[i] })
|
||||
}
|
||||
this.editTagForm = arr
|
||||
},
|
||||
addTag() {
|
||||
this.editTagForm.push({ key: '', value: '' })
|
||||
},
|
||||
removeTag(tag, index) {
|
||||
this.editTagForm.splice(index, 1)
|
||||
this.blurInput()
|
||||
},
|
||||
blurInput() {
|
||||
const obj = {}
|
||||
this.editTagForm.forEach(e => {
|
||||
if (e.key !== '') {
|
||||
obj[e.key] = e.value
|
||||
}
|
||||
})
|
||||
this.$emit('input', obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.addBtn{
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,338 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="list-btns">
|
||||
<el-form v-if="filterMap" :inline="true" class="demo-form-inline">
|
||||
<el-form-item
|
||||
v-for="(item, key) in filterMap"
|
||||
:key="key"
|
||||
:label="item.label+':'"
|
||||
>
|
||||
<RenderCell
|
||||
v-if="item.render"
|
||||
:render="item.render"
|
||||
:item-key="key"
|
||||
:filter-data="filterData"
|
||||
/>
|
||||
<template v-else>
|
||||
<el-select
|
||||
v-if="item.type === 'select'"
|
||||
v-model="filterData[key]"
|
||||
size="medium"
|
||||
>
|
||||
<el-option v-for="(it,idx) in item.dataSource" :key="key+idx" :label="it.label" :value="it.value" />
|
||||
</el-select>
|
||||
<el-datepicker
|
||||
v-else-if="item.type === 'date'"
|
||||
v-model="filterData[key]"
|
||||
type="date"
|
||||
/>
|
||||
<template
|
||||
v-else-if="item.type === 'dateRange'"
|
||||
>
|
||||
<el-date-picker
|
||||
v-model="filterData[key]"
|
||||
type="daterange"
|
||||
:range-separator="$t('message.to')"
|
||||
:start-placeholder="$t('message.startDate')"
|
||||
:end-placeholder="$t('message.endDate')"
|
||||
/>
|
||||
<!-- <el-datepicker
|
||||
v-model="filterData[item.key1]"
|
||||
type="date"
|
||||
:clearable="false"
|
||||
:format='item.format'>
|
||||
</el-datepicker>
|
||||
-
|
||||
<el-datepicker
|
||||
v-model="filterData[item.key2]"
|
||||
type="date"
|
||||
:clearable="false"
|
||||
:format='item.format'>
|
||||
</el-datepicker> -->
|
||||
</template>
|
||||
<el-input
|
||||
v-else
|
||||
v-model="filterData[key]"
|
||||
size="medium"
|
||||
@enter="onSearchClick"
|
||||
/>
|
||||
</template>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
size="medium"
|
||||
type="info"
|
||||
@click="onSearchClick"
|
||||
>
|
||||
{{ $t('message.search') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
size="medium"
|
||||
@click="resetSearch"
|
||||
>
|
||||
{{ $t('message.reset') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- {{tableData}}-->
|
||||
<div class="btn-right"><slot name="filterBtns" class="slot" /></div>
|
||||
</div>
|
||||
<el-table
|
||||
v-if="tableData.length>0"
|
||||
ref="multipleTable"
|
||||
class="multipleTable"
|
||||
:data="paginationAuto ? (tableData.slice((page - 1) * 10, page * 10)) : tableData"
|
||||
v-bind="$attrs"
|
||||
:max-height="height"
|
||||
:border="border"
|
||||
:highlight-current-row="listColumns.length>0 && listColumns[0].type !== 'selection'"
|
||||
tooltip-effect="dark"
|
||||
style="width: 100%"
|
||||
size="medium"
|
||||
v-on="$listeners"
|
||||
>
|
||||
<el-table-column
|
||||
v-for="(item, index) in listColumns"
|
||||
:key="index"
|
||||
:prop="item.prop"
|
||||
:label="item.label"
|
||||
:width="item.width"
|
||||
:formatter="item.formatter"
|
||||
:sortable="item.sortable"
|
||||
:show-overflow-tooltip="item.showOverflowTooltip"
|
||||
:type="item.type||''"
|
||||
:selectable="item.selectable"
|
||||
>
|
||||
<!-- <template slot="header" slot-scope="scope">
|
||||
<RenderCell
|
||||
v-if="typeof item.label === 'function'"
|
||||
:render="item.label"
|
||||
:index="scope.$index"
|
||||
:row="scope.row" />
|
||||
<span v-else>
|
||||
{{item.label}}
|
||||
</span>
|
||||
</template>
|
||||
<template slot-scope="scope" >
|
||||
<RenderCell
|
||||
v-if="item.render"
|
||||
:render="item.render"
|
||||
:index="scope.$index"
|
||||
:row="scope.row" />
|
||||
<span v-else>
|
||||
{{
|
||||
item.formatter? item.formatter(scope.row, scope.row[item.prop]): scope.row[item.prop]
|
||||
}}
|
||||
</span>
|
||||
</template> -->
|
||||
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-pagination
|
||||
v-if="pagination"
|
||||
background
|
||||
:hide-on-single-page="true"
|
||||
:current-page="page"
|
||||
:pager-count="5"
|
||||
:layout=" small ? 'prev, pager, next' :'total, prev, pager, next, jumper'"
|
||||
:small="small"
|
||||
:total="paginationAuto ? tableData.length :total"
|
||||
@current-change="currentChange"
|
||||
/>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import RenderCell from './renderCell'
|
||||
|
||||
export default {
|
||||
name: 'List',
|
||||
components: { RenderCell },
|
||||
props: {
|
||||
getListAction: {
|
||||
type: Function,
|
||||
default: undefined
|
||||
},
|
||||
map: {
|
||||
type: Object,
|
||||
default: undefined
|
||||
},
|
||||
columns: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
pagination: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
paginationAuto: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
query: {
|
||||
type: Object,
|
||||
default: undefined
|
||||
}, // api query
|
||||
filterMap: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
defaultFilterData: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
}
|
||||
},
|
||||
funcName: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
isRefresh: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
tableListData: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
clusterName: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
listKey: {
|
||||
type: String,
|
||||
default: 'list'
|
||||
},
|
||||
totalKey: {
|
||||
type: String,
|
||||
default: 'total'
|
||||
},
|
||||
pageKey: {
|
||||
type: String,
|
||||
default: 'page'
|
||||
},
|
||||
limitKey: {
|
||||
type: String,
|
||||
default: 'limit'
|
||||
},
|
||||
small: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: 'auto'
|
||||
},
|
||||
border: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
const filterData = { ...this.defaultFilterData }
|
||||
return {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0,
|
||||
tableData: [],
|
||||
listColumns: [],
|
||||
filterData
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
tableListData(val) {
|
||||
this.tableData = val
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.funcName || this.getListAction) {
|
||||
this.getList()
|
||||
} else {
|
||||
this.tableData = this.tableListData
|
||||
}
|
||||
|
||||
this.listColumns = this.columns || this.mapToColums(this.map)
|
||||
},
|
||||
beforeDestroy() {
|
||||
clearInterval(this.timer)
|
||||
this.timer = null
|
||||
},
|
||||
methods: {
|
||||
setCurrent(row) {
|
||||
this.$refs.multipleTable.setCurrentRow(row)
|
||||
},
|
||||
mapToColums(map) {
|
||||
const column = []
|
||||
Object.keys(map).forEach((e) => {
|
||||
if (e === 'selection' || e === 'index') {
|
||||
column.push({ type: e, key: map[e] })
|
||||
} else {
|
||||
column.push({ prop: e, label: map[e] })
|
||||
}
|
||||
})
|
||||
return column
|
||||
},
|
||||
currentChange(page) {
|
||||
this.page = page
|
||||
if (!this.paginationAuto) {
|
||||
this.getList()
|
||||
}
|
||||
},
|
||||
onSearchClick() {
|
||||
this.page = 1
|
||||
this.getList()
|
||||
},
|
||||
resetSearch() {
|
||||
this.filterData = {}
|
||||
this.getList()
|
||||
},
|
||||
async getList() {
|
||||
const params = {
|
||||
[this.pageKey]: this.pagination ? this.page : undefined,
|
||||
[this.limitKey]: this.pagination ? this.limit : undefined,
|
||||
...this.query,
|
||||
...this.filterData
|
||||
}
|
||||
if (this.getListAction) {
|
||||
const ListData = await this.getListAction(params)
|
||||
this.total = Number(ListData?.data?.[this.totalKey]) || Number(ListData[this.totalKey]) || 0
|
||||
this.tableData = ListData?.data?.[this.listKey] || ListData[this.listKey] || []
|
||||
} else {
|
||||
const clusterName = this.clusterName
|
||||
const ListData = await this.$HandleFunc[this.funcName](clusterName, params)
|
||||
this.total = ListData.total
|
||||
this.tableData = ListData.rows
|
||||
}
|
||||
},
|
||||
setCurrentRow(row) {
|
||||
this.$refs.multipleTable.setCurrentRow(row)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.filter-field{
|
||||
margin-bottom: 20px;
|
||||
// font-size: 0.9rem;
|
||||
.filter-item{
|
||||
margin-right: 20px;
|
||||
margin-bottom: 20px;
|
||||
.el-input{
|
||||
width: 100px;
|
||||
}
|
||||
float: left;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
.multipleTable{
|
||||
// margin-top: 20px;
|
||||
}
|
||||
.el-pagination{
|
||||
margin-top: 15px;
|
||||
float: right;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,8 @@
|
|||
export default {
|
||||
name: 'render-cell',
|
||||
functional: true,
|
||||
props: {
|
||||
render: Function
|
||||
},
|
||||
render: (h, ctx) => ctx.props.render(h, ctx.data.attrs)
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
// import parseTime, formatTime and set to filter
|
||||
export { parseTime, formatTime } from '@/utils'
|
||||
|
||||
/**
|
||||
* Show plural label if time is plural number
|
||||
* @param {number} time
|
||||
* @param {string} label
|
||||
* @return {string}
|
||||
*/
|
||||
function pluralize(time, label) {
|
||||
if (time === 1) {
|
||||
return time + label
|
||||
}
|
||||
return time + label + 's'
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} time
|
||||
*/
|
||||
export function timeAgo(time) {
|
||||
const between = Date.now() / 1000 - Number(time)
|
||||
if (between < 3600) {
|
||||
return pluralize(~~(between / 60), ' minute')
|
||||
} else if (between < 86400) {
|
||||
return pluralize(~~(between / 3600), ' hour')
|
||||
} else {
|
||||
return pluralize(~~(between / 86400), ' day')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Number formatting
|
||||
* like 10000 => 10k
|
||||
* @param {number} num
|
||||
* @param {number} digits
|
||||
*/
|
||||
export function numberFormatter(num, digits) {
|
||||
const si = [
|
||||
{ value: 1E18, symbol: 'E' },
|
||||
{ value: 1E15, symbol: 'P' },
|
||||
{ value: 1E12, symbol: 'T' },
|
||||
{ value: 1E9, symbol: 'G' },
|
||||
{ value: 1E6, symbol: 'M' },
|
||||
{ value: 1E3, symbol: 'k' }
|
||||
]
|
||||
for (let i = 0; i < si.length; i++) {
|
||||
if (num >= si[i].value) {
|
||||
return (num / si[i].value).toFixed(digits).replace(/\.0+$|(\.[0-9]*[1-9])0+$/, '$1') + si[i].symbol
|
||||
}
|
||||
}
|
||||
return num.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* 10000 => "10,000"
|
||||
* @param {number} num
|
||||
*/
|
||||
export function toThousandFilter(num) {
|
||||
return (+num || 0).toString().replace(/^-?\d+/g, m => m.replace(/(?=(?!\b)(\d{3})+$)/g, ','))
|
||||
}
|
||||
|
||||
/**
|
||||
* Upper case first char
|
||||
* @param {String} string
|
||||
*/
|
||||
export function uppercaseFirst(string) {
|
||||
return string.charAt(0).toUpperCase() + string.slice(1)
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
import Vue from 'vue'
|
||||
import SvgIcon from '@/components/SvgIcon'// svg component
|
||||
|
||||
// register globally
|
||||
Vue.component('svg-icon', SvgIcon)
|
||||
|
||||
const req = require.context('./svg', false, /\.svg$/)
|
||||
const requireAll = requireContext => requireContext.keys().map(requireContext)
|
||||
requireAll(req)
|
|
@ -0,0 +1 @@
|
|||
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M121.718 73.272v9.953c3.957-7.584 6.199-16.05 6.199-24.995C127.917 26.079 99.273 0 63.958 0 28.644 0 0 26.079 0 58.23c0 .403.028.806.028 1.21l22.97-25.953h13.34l-19.76 27.187h6.42V53.77l13.728-19.477v49.361H22.998V73.272H2.158c5.951 20.284 23.608 36.208 45.998 41.399-1.44 3.3-5.618 11.263-12.565 12.674-8.607 1.764 23.358.428 46.163-13.178 17.519-4.611 31.938-15.849 39.77-30.513h-13.506V73.272H85.02V59.464l22.998-25.977h13.008l-19.429 27.187h6.421v-7.433l13.727-19.402v39.433h-.027zm-78.24 2.822a10.516 10.516 0 0 1-.996-4.535V44.548c0-1.613.332-3.124.996-4.535a11.66 11.66 0 0 1 2.713-3.68c1.134-1.032 2.49-1.864 4.04-2.468 1.55-.605 3.21-.908 4.982-.908h11.292c1.77 0 3.431.303 4.981.908 1.522.604 2.85 1.41 3.986 2.418l-12.26 16.303v-2.898a1.96 1.96 0 0 0-.665-1.512c-.443-.403-.996-.604-1.66-.604-.665 0-1.218.201-1.661.604a1.96 1.96 0 0 0-.664 1.512v9.071L44.364 77.606a10.556 10.556 0 0 1-.886-1.512zm35.73-4.535c0 1.613-.332 3.124-.997 4.535a11.66 11.66 0 0 1-2.712 3.68c-1.134 1.032-2.49 1.864-4.04 2.469-1.55.604-3.21.907-4.982.907H55.185c-1.77 0-3.431-.303-4.981-.907-1.55-.605-2.906-1.437-4.041-2.47a12.49 12.49 0 0 1-1.384-1.512l13.727-18.217v6.375c0 .605.222 1.109.665 1.512.442.403.996.604 1.66.604.664 0 1.218-.201 1.66-.604a1.96 1.96 0 0 0 .665-1.512V53.87L75.97 36.838c.913.932 1.66 1.99 2.214 3.175.664 1.41.996 2.922.996 4.535v27.011h.028z"/></svg>
|
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 8.7 KiB |
After Width: | Height: | Size: 8.7 KiB |
After Width: | Height: | Size: 8.7 KiB |
|
@ -0,0 +1 @@
|
|||
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M127.88 73.143c0 1.412-.506 2.635-1.518 3.669-1.011 1.033-2.209 1.55-3.592 1.55h-17.887c0 9.296-1.783 17.178-5.35 23.645l16.609 17.044c1.011 1.034 1.517 2.257 1.517 3.67 0 1.412-.506 2.635-1.517 3.668-.958 1.033-2.155 1.55-3.593 1.55-1.438 0-2.635-.517-3.593-1.55l-15.811-16.063a15.49 15.49 0 0 1-1.196 1.06c-.532.434-1.65 1.208-3.353 2.322a50.104 50.104 0 0 1-5.192 2.974c-1.758.87-3.94 1.658-6.546 2.364-2.607.706-5.189 1.06-7.748 1.06V47.044H58.89v73.062c-2.716 0-5.417-.367-8.106-1.102-2.688-.734-5.003-1.631-6.945-2.692a66.769 66.769 0 0 1-5.268-3.179c-1.571-1.057-2.73-1.94-3.476-2.65L33.9 109.34l-14.611 16.877c-1.066 1.14-2.344 1.711-3.833 1.711-1.277 0-2.422-.434-3.434-1.304-1.012-.978-1.557-2.187-1.635-3.627-.079-1.44.333-2.705 1.236-3.794l16.129-18.51c-3.087-6.197-4.63-13.644-4.63-22.342H5.235c-1.383 0-2.58-.517-3.592-1.55S.125 74.545.125 73.132c0-1.412.506-2.635 1.518-3.668 1.012-1.034 2.21-1.55 3.592-1.55h17.887V43.939L9.308 29.833c-1.012-1.033-1.517-2.256-1.517-3.669 0-1.412.505-2.635 1.517-3.668 1.012-1.034 2.21-1.55 3.593-1.55s2.58.516 3.593 1.55l13.813 14.106h67.396l13.814-14.106c1.012-1.034 2.21-1.55 3.592-1.55 1.384 0 2.581.516 3.593 1.55 1.012 1.033 1.518 2.256 1.518 3.668 0 1.413-.506 2.636-1.518 3.67l-13.814 14.105v23.975h17.887c1.383 0 2.58.516 3.593 1.55 1.011 1.033 1.517 2.256 1.517 3.668l-.005.01zM89.552 26.175H38.448c0-7.23 2.489-13.386 7.466-18.469C50.892 2.623 56.92.082 64 .082c7.08 0 13.108 2.541 18.086 7.624 4.977 5.083 7.466 11.24 7.466 18.469z"/></svg>
|
After Width: | Height: | Size: 1.5 KiB |
|
@ -0,0 +1 @@
|
|||
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M0 54.857h36.571V128H0V54.857zM91.429 27.43H128V128H91.429V27.429zM45.714 0h36.572v128H45.714V0z"/></svg>
|
After Width: | Height: | Size: 179 B |
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 833 833" style="enable-background:new 0 0 833 833;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill-rule:evenodd;clip-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linejoin:round;}
|
||||
.st1{fill-rule:evenodd;clip-rule:evenodd;}
|
||||
</style>
|
||||
<path d="M417.2,61.3C221.4,61.3,62.7,220,62.7,415.8s158.7,354.5,354.5,354.5s354.5-158.7,354.5-354.5S613,61.3,417.2,61.3z
|
||||
M417.2,732.5c-173.4,0-314-140.6-314-314s140.6-314,314-314s314,140.6,314,314S590.6,732.5,417.2,732.5z"/>
|
||||
<path id="形状_1" class="st0" d="M591.2,252.4l-0.9-7.3l-1.8-4.6l-2.7-6.4l-2.7-7.3l-2.7-8.2l-5.5-10.1l-3.7-1.8l-4.6,0.9L561,203
|
||||
h-11l-10.1,2.7l-5.5,4.6l-3.7,2.7l2.7,2.7l2.7,6.4l-3.7,3.7l-9.1,17.4l0.9,3.7c-2.5,0.6-5,1.5-7.3,2.7c-2.7,1.7-6.4,6.4-6.4,6.4
|
||||
l-6.4-4.6l-11,22l1.8,2.7c0,0,3.6-3.4,7.3-2.7c2.2,0.4,4.2,1.8,5.5,3.7c0,0,5.7-4.3,8.2-3.7s8.2,9.1,8.2,9.1l2.7,5.5l-6.4,0.9
|
||||
l-6.4,0.9l-5.5,2.7l-6.4-0.9l-3.7,6.4l-6.4,6.4l-2.7-1.8l-9.1,8.2h-8.2l-7.3-2.7l-4.6,7.3l2.7,5.5l-11.9,12.8l-9.1,3.7h-14.6
|
||||
l-21,8.2l-4.6-1.8h-4.6l-14.6-3.7l-3.7-4.6h-41.2l-7.3-19.2l-6.4,0.9l-7.3-7.3h-6.4l-12.8-2.7l-6.4-5.5l3.7-11l-6.4-14.6l-11-3.7
|
||||
l-8.2-6.4l-1.8-5.5l-5.5-1.8l-1.8,4.6l-7.3,5.5l-1.8,13.7l-10.1,1.8l-8.2-2.7l-9.1,16.5l1.8,7.3l-8.2-1.8l-12.8,5.5l8.2,18.3
|
||||
l-5.5,7.3v4.6l-1.8,2.7l-18.3,9.1h-5.5l-4.6,10.1l-9.1-5.5l-5.5,5.5h-5.5l-1.8,6.4l-2.7,4.6l10.1,17.4l6.4,7.3l3.7,3.7l2.8,6.4
|
||||
l5.5,2.7l8.2,0.9l1.8,6.4l8.2,3.7l-4.6,4.6l2.7,6.4l1.8,5.5l-6.4,1.8l2.7,4.6v7.3l2.7,1.8l5.5,2.7l3.7,0.9l5.5,7.3l4.6-5.5
|
||||
l17.4,11.9l2.7-2.7l13.7,14.6l8.2-0.9l5.5,2.7l10.1-3.7l1.8,8.2l8.2-8.2l6.4,1.8l8.2,1.8l0.9,2.7l1.8,4.6h8.2l8.2-3.7l5.5-0.9
|
||||
l10.1-8.2l10.1,7.3l3.7-9.1l7.3,6.4l-1.8,4.6l5.5,11.9l-11,9.1l-0.9,10.1l12.8-2.7l-2.7,5.5l4.6,8.2l-0.9,4.6l5.5,1.8l3.7,4.6
|
||||
l4.6-2.7l7.3,5.5l-1.8-10.1l3.7-1.8l5.5-2.7h8.2l0.9,4.6l11-11l11.9,6.4l-1.8,5.5l11.9,4.6h11l4.6,5.5h4.6l4.6-4.6l7.3-0.9l3.7,2.7
|
||||
l9.1-6.4l1.8-7.3l4.6,7.3l5.5-5.5h7.3l11.9-9.1l10.1-6.4l5.5-8.2l4.6-9.1l9.1-8.2l4.6-7.3l2.7-10.1l-0.9-7.3h6.4l-6.4-10.1v-6.4
|
||||
l-2.7-8.2l-3.7-2.7l-2.7-11.9l-11-8.2l4.6-8.2l7.3-3.7l6.4-7.3l6.4-1.8l-6.4-6.4l-7.3-0.9l-7.3,3.7l-5.5-2.7l-0.9-5.5l-9.1-4.6
|
||||
l0.9-5.5l6.4,1.8l19.2-18.3l6.4-0.9l1.8,2.7l-3.7,8.2l-0.9,7.3l11-6.4l2.7,6.4l2.7-7.3l8.2-4.6l10.1-7.3l8.2-8.2l10.1,2.7L593,343
|
||||
l5.5-0.9l6.4-4.6l4.6-5.5l5.5,5.5l2.7-6.4l3.7-4.6l-1.8-15.6l6.4-5.5l8.2,3.7l9.2-12.8l-3.7-4.6l3.7-6.4l-0.9-2.7l7.3-4.6l-1.8-4.6
|
||||
l3.7-4.6l-24.7,11l-8.2-2.7l-3.7-13.7l-14.6-9.1L591.2,252.4z"/>
|
||||
<path id="圆角矩形_1_拷贝" class="st1" d="M434.7,559.8v5.5l11,6.4l10.1-8.2l5.5-9.1c0,0-8.5-6.4-9.1-6.4s-7.1,0.4-7.3,0.9
|
||||
s-11,8.2-11,8.2L434.7,559.8z M539.9,503.1c0,0-11.6,12.6-12.8,18.3s4.2,18.5,7.3,18.3s8.9-13.8,11-21s3.5-13,0-14.6
|
||||
S539.9,503.1,539.9,503.1L539.9,503.1z M545.4,536l-9.1,10.1l1.8,3.7l10.1-10.1L545.4,536z M528.2,558.5l-4.3,12.9l3.2,2.6l5.1-13.3
|
||||
L528.2,558.5z M519.7,617.6l-4.8,12.7l3.1,2.7l5.6-13.1L519.7,617.6z M497.7,649l-7.6,11.2l2.3,3.4l8.5-11.4L497.7,649z M473.4,685
|
||||
l-12.9,4.4l-0.2,4.1l13.7-3.9L473.4,685z M449.8,615.7l-3.1,13.3l3.4,2.3l3.9-13.7L449.8,615.7z M439.7,584.6l6.4,12l4.1-0.5
|
||||
l-6.1-12.9L439.7,584.6z M521.2,585.4c1.3,0,2.3,1,2.3,2.3v10.1c0,1.3-1.1,2.3-2.3,2.2c-1.2,0-2.2-1-2.2-2.2v-10
|
||||
C518.9,586.4,519.9,585.4,521.2,585.4L521.2,585.4L521.2,585.4z M434.2,658.6c1.3,0,2.3,1,2.3,2.3l0,0v10.1c0,1.3-1,2.3-2.3,2.3
|
||||
s-2.3-1-2.3-2.3l0,0v-10.1C432,659.6,433,658.6,434.2,658.6z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 3.5 KiB |
|
@ -0,0 +1 @@
|
|||
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M54.857 118.857h64V73.143H89.143c-1.902 0-3.52-.668-4.855-2.002-1.335-1.335-2.002-2.954-2.002-4.855V36.57H54.857v82.286zM73.143 16v-4.571a2.2 2.2 0 0 0-.677-1.61 2.198 2.198 0 0 0-1.609-.676H20.571c-.621 0-1.158.225-1.609.676a2.198 2.198 0 0 0-.676 1.61V16a2.2 2.2 0 0 0 .676 1.61c.451.45.988.676 1.61.676h50.285c.622 0 1.158-.226 1.61-.677.45-.45.676-.987.676-1.609zm18.286 48h21.357L91.43 42.642V64zM128 73.143v48c0 1.902-.667 3.52-2.002 4.855-1.335 1.335-2.953 2.002-4.855 2.002H52.57c-1.901 0-3.52-.667-4.854-2.002-1.335-1.335-2.003-2.953-2.003-4.855v-11.429H6.857c-1.902 0-3.52-.667-4.855-2.002C.667 106.377 0 104.759 0 102.857v-96c0-1.902.667-3.52 2.002-4.855C3.337.667 4.955 0 6.857 0h77.714c1.902 0 3.52.667 4.855 2.002 1.335 1.335 2.003 2.953 2.003 4.855V30.29c1 .622 1.856 1.29 2.569 2.003l29.147 29.147c1.335 1.335 2.478 3.145 3.429 5.43.95 2.287 1.426 4.383 1.426 6.291v-.018z"/></svg>
|
After Width: | Height: | Size: 971 B |
|
@ -0,0 +1 @@
|
|||
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h54.857v54.857H0V0zm0 73.143h54.857V128H0V73.143zm73.143 0H128V128H73.143V73.143zm27.428-18.286C115.72 54.857 128 42.577 128 27.43 128 12.28 115.72 0 100.571 0 85.423 0 73.143 12.28 73.143 27.429c0 15.148 12.28 27.428 27.428 27.428z"/></svg>
|
After Width: | Height: | Size: 319 B |
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 200 200" style="enable-background:new 0 0 200 200;" xml:space="preserve">
|
||||
<path d="M131.2,28.5c1.4,0,2.4,1.1,2.4,2.4V169c0,1.4-1.1,2.4-2.4,2.4H68.8c-1.4,0-2.4-1.1-2.4-2.4V31c0-1.4,1.1-2.4,2.4-2.4H131.2
|
||||
M131.2,18.8H68.8c-6.7,0-12.2,5.4-12.2,12.2V169c0,6.7,5.4,12.2,12.2,12.2h62.4c6.7,0,12.2-5.4,12.2-12.2V31
|
||||
C143.3,24.2,137.9,18.8,131.2,18.8z"/>
|
||||
<path d="M79,54.8h42.9v9.7H79V54.8z M79,75.9h42.9v9.7H79V75.9z M94.4,128.3h10.2v10.2H94.4V128.3z M171.6,33.2h-20.6V43h20.6v118.3
|
||||
h-20.6v9.7h20.6c5.4,0,9.7-4.4,9.7-9.7V43C181.4,37.6,177,33.2,171.6,33.2z M29.7,33.2h20.6V43H29.7v118.3h20.6v9.7H29.7
|
||||
c-5.4,0-9.7-4.4-9.7-9.7V43C20,37.6,24.3,33.2,29.7,33.2z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 938 B |
|
@ -0,0 +1 @@
|
|||
<svg width="128" height="100" xmlns="http://www.w3.org/2000/svg"><path d="M27.429 63.638c0-2.508-.893-4.65-2.679-6.424-1.786-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.465 2.662-1.785 1.774-2.678 3.916-2.678 6.424 0 2.508.893 4.65 2.678 6.424 1.786 1.775 3.94 2.662 6.465 2.662 2.524 0 4.678-.887 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zm13.714-31.801c0-2.508-.893-4.65-2.679-6.424-1.785-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zM71.714 65.98l7.215-27.116c.285-1.23.107-2.378-.536-3.443-.643-1.064-1.56-1.762-2.75-2.094-1.19-.33-2.333-.177-3.429.462-1.095.639-1.81 1.573-2.143 2.804l-7.214 27.116c-2.857.237-5.405 1.266-7.643 3.088-2.238 1.822-3.738 4.152-4.5 6.992-.952 3.644-.476 7.098 1.429 10.364 1.905 3.265 4.69 5.37 8.357 6.317 3.667.947 7.143.474 10.429-1.42 3.285-1.892 5.404-4.66 6.357-8.305.762-2.84.619-5.607-.429-8.305-1.047-2.697-2.762-4.85-5.143-6.46zm47.143-2.342c0-2.508-.893-4.65-2.678-6.424-1.786-1.775-3.94-2.662-6.465-2.662-2.524 0-4.678.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.786 1.775 3.94 2.662 6.464 2.662 2.524 0 4.679-.887 6.465-2.662 1.785-1.775 2.678-3.916 2.678-6.424zm-45.714-45.43c0-2.509-.893-4.65-2.679-6.425C68.68 10.01 66.524 9.122 64 9.122c-2.524 0-4.679.887-6.464 2.661-1.786 1.775-2.679 3.916-2.679 6.425 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zm32 13.629c0-2.508-.893-4.65-2.679-6.424-1.785-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zM128 63.638c0 12.351-3.357 23.78-10.071 34.286-.905 1.372-2.19 2.058-3.858 2.058H13.93c-1.667 0-2.953-.686-3.858-2.058C3.357 87.465 0 76.037 0 63.638c0-8.613 1.69-16.847 5.071-24.703C8.452 31.08 13 24.312 18.714 18.634c5.715-5.68 12.524-10.199 20.429-13.559C47.048 1.715 55.333.035 64 .035c8.667 0 16.952 1.68 24.857 5.04 7.905 3.36 14.714 7.88 20.429 13.559 5.714 5.678 10.262 12.446 13.643 20.301 3.38 7.856 5.071 16.09 5.071 24.703z"/></svg>
|
After Width: | Height: | Size: 2.3 KiB |
|
@ -0,0 +1 @@
|
|||
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M71.984 44.815H115.9L71.984 9.642v35.173zM16.094.05h63.875l47.906 38.37v76.74c0 3.392-1.682 6.645-4.677 9.044-2.995 2.399-7.056 3.746-11.292 3.746H16.094c-4.236 0-8.297-1.347-11.292-3.746-2.995-2.399-4.677-5.652-4.677-9.044V12.84C.125 5.742 7.23.05 16.094.05zm71.86 102.32V89.58h-71.86v12.79h71.86zm23.952-25.58V64H16.094v12.79h95.812z"/></svg>
|
After Width: | Height: | Size: 418 B |
|
@ -0,0 +1 @@
|
|||
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M73.137 29.08h-9.209 29.7L63.886.093 34.373 29.08h20.49v27.035H27.238v17.948h27.625v27.133h18.274V74.063h27.41V56.115h-27.41V29.08zm-9.245 98.827l27.518-26.711H36.59l27.302 26.71zM.042 64.982l27.196 27.029V38.167L.042 64.982zm100.505-26.815V92.01l27.41-27.029-27.41-26.815z"/></svg>
|
After Width: | Height: | Size: 356 B |
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><svg id="_层_2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12.44 12.44"><defs><style>.cls-1{fill:#fff;}</style></defs><g id="_层_3"><path class="cls-1" d="M6.22,12.44C2.79,12.44,0,9.65,0,6.22S2.79,0,6.22,0s6.22,2.79,6.22,6.22-2.79,6.22-6.22,6.22Zm0-8.91c-1.48,0-2.68,1.2-2.68,2.68s1.2,2.69,2.68,2.69,2.68-1.21,2.68-2.69-1.2-2.68-2.68-2.68Z"/></g></svg>
|
After Width: | Height: | Size: 397 B |
|
@ -0,0 +1 @@
|
|||
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M106.133 67.2a4.797 4.797 0 0 0-4.8 4.8c0 .187.014.36.027.533h-.027V118.4H9.6V26.667h50.133c2.654 0 4.8-2.147 4.8-4.8 0-2.654-2.146-4.8-4.8-4.8H9.6a9.594 9.594 0 0 0-9.6 9.6V118.4c0 5.307 4.293 9.6 9.6 9.6h91.733c5.307 0 9.6-4.293 9.6-9.6V72.533h-.026c.013-.173.026-.346.026-.533 0-2.653-2.146-4.8-4.8-4.8z"/><path d="M125.16 13.373L114.587 2.8c-3.747-3.747-9.854-3.72-13.6.027l-52.96 52.96a4.264 4.264 0 0 0-.907 1.36L33.813 88.533c-.746 1.76-.226 3.534.907 4.68 1.133 1.147 2.92 1.667 4.693.92l31.4-13.293c.507-.213.96-.52 1.36-.907l52.96-52.96c3.747-3.746 3.774-9.853.027-13.6zM66.107 72.4l-18.32 7.76 7.76-18.32L92.72 24.667l10.56 10.56L66.107 72.4zm52.226-52.227l-8.266 8.267-10.56-10.56 8.266-8.267.027-.026 10.56 10.56-.027.026z"/></svg>
|
After Width: | Height: | Size: 818 B |
|
@ -0,0 +1 @@
|
|||
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M88.883 119.565c-7.284 0-19.434 2.495-21.333 8.25v.127c-4.232.13-5.222 0-7.108 0-1.895-5.76-14.045-8.256-21.333-8.256H0V0h42.523c9.179 0 17.109 5.47 21.47 13.551C68.352 5.475 76.295 0 85.478 0H128v119.57l-39.113-.005h-.004zM60.442 24.763c0-9.651-8.978-16.507-17.777-16.507H7.108V111.43H39.11c7.054-.14 18.177.082 21.333 6.12v-4.628c-.134-5.722-.004-13.522 0-13.832V27.413l.004-2.655-.004.005zm60.442-16.517h-35.55c-8.802 0-17.78 6.856-17.78 16.493v74.259c.004.32.138 8.115 0 13.813v4.627c3.155-6.022 14.279-6.26 21.333-6.114h32V8.25l-.003-.005z"/></svg>
|
After Width: | Height: | Size: 627 B |
|
@ -0,0 +1 @@
|
|||
<svg width="128" height="96" xmlns="http://www.w3.org/2000/svg"><path d="M64.125 56.975L120.188.912A12.476 12.476 0 0 0 115.5 0h-103c-1.588 0-3.113.3-4.513.838l56.138 56.137z"/><path d="M64.125 68.287l-62.3-62.3A12.42 12.42 0 0 0 0 12.5v71C0 90.4 5.6 96 12.5 96h103c6.9 0 12.5-5.6 12.5-12.5v-71a12.47 12.47 0 0 0-1.737-6.35L64.125 68.287z"/></svg>
|
After Width: | Height: | Size: 347 B |