Delete dkube-web directory
							
								
								
									
										23
									
								
								dkube-web/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						@ -1,23 +0,0 @@
 | 
				
			|||||||
.DS_Store
 | 
					 | 
				
			||||||
node_modules
 | 
					 | 
				
			||||||
/dist
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# 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?
 | 
					 | 
				
			||||||
@ -1,75 +0,0 @@
 | 
				
			|||||||
<div style="text-align: center"></div>
 | 
					 | 
				
			||||||
  <p align="center">
 | 
					 | 
				
			||||||
  <img src="https://user-images.githubusercontent.com/42825450/201523059-ed28e427-e1b6-443a-8326-100460e6dec9.jpg" width="250px" height="220px">
 | 
					 | 
				
			||||||
      <br>
 | 
					 | 
				
			||||||
      <i>Make the project development and release simpler, easier and more efficient.</i>
 | 
					 | 
				
			||||||
  </p>
 | 
					 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## What is DKube
 | 
					 | 
				
			||||||
This is a K8s cluster management platform;DKube Provides a wizard-style operation interface for K8s cluster management to help your team manage your cluster environment quickly and easily
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## 功能
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<details>
 | 
					 | 
				
			||||||
  <summary><b> K8s集群管理</b></summary>
 | 
					 | 
				
			||||||
</details>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<details>
 | 
					 | 
				
			||||||
  <summary><b> 平台化界面</b></summary>
 | 
					 | 
				
			||||||
</details>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<details>
 | 
					 | 
				
			||||||
  <summary><b> 更加便捷的管理K8s</b></summary>
 | 
					 | 
				
			||||||
</details>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<details>
 | 
					 | 
				
			||||||
  <summary><b> 支持YAML信息查看\变更</b></summary>
 | 
					 | 
				
			||||||
</details>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<details>
 | 
					 | 
				
			||||||
  <summary><b> 平台化管理控制器</b></summary>
 | 
					 | 
				
			||||||
</details>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<details>
 | 
					 | 
				
			||||||
  <summary><b> 实时查看容器日志</b></summary>
 | 
					 | 
				
			||||||
</details>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## 截图
 | 
					 | 
				
			||||||
<br/>
 | 
					 | 
				
			||||||
<table>
 | 
					 | 
				
			||||||
    <tr>
 | 
					 | 
				
			||||||
      <td width="50%" align="center"><b>登入认证管理</b></td>
 | 
					 | 
				
			||||||
      <td width="50%" align="center"><b>集群信息状态</b></td>
 | 
					 | 
				
			||||||
    </tr>
 | 
					 | 
				
			||||||
    <tr>
 | 
					 | 
				
			||||||
        <td width="50%" align="center"><img src="https://user-images.githubusercontent.com/42825450/193593148-4d258b30-b972-4583-b359-32978a8a8637.jpg?raw=true"></td>
 | 
					 | 
				
			||||||
        <td width="50%" align="center"><img src="https://user-images.githubusercontent.com/42825450/193593170-3373dabd-8d5d-4a01-a59f-49851f11f433.jpg?raw=true"></td>
 | 
					 | 
				
			||||||
    </tr>
 | 
					 | 
				
			||||||
    <tr>
 | 
					 | 
				
			||||||
      <td width="50%" align="center"><b>节点资源管理</b></td>
 | 
					 | 
				
			||||||
      <td width="50%" align="center"><b>名称空间管理</b></td>
 | 
					 | 
				
			||||||
    </tr>
 | 
					 | 
				
			||||||
        <td width="50%" align="center"><img src="https://user-images.githubusercontent.com/42825450/193593569-daebc649-f6c4-45a2-88f6-2aa4860c3dea.jpg?raw=true"></td>
 | 
					 | 
				
			||||||
        <td width="50%" align="center"><img src="https://user-images.githubusercontent.com/42825450/193593579-e0539ab0-6b22-4060-b254-c6495fb87cbd.jpg?raw=true"></td>
 | 
					 | 
				
			||||||
    <tr>
 | 
					 | 
				
			||||||
    </tr>
 | 
					 | 
				
			||||||
    <tr>
 | 
					 | 
				
			||||||
      <td width="50%" align="center"><b>YAML信息管理</b></td>
 | 
					 | 
				
			||||||
      <td width="50%" align="center"><b>Pod副本管理</b></td>
 | 
					 | 
				
			||||||
    </tr>
 | 
					 | 
				
			||||||
        <td width="50%" align="center"><img src="https://user-images.githubusercontent.com/42825450/193593867-4a98bd0f-a910-4b90-92e3-6a3164d0c241.jpg?raw=true"></td>
 | 
					 | 
				
			||||||
        <td width="50%" align="center"><img src="https://user-images.githubusercontent.com/42825450/193593871-ee004cb8-42cb-427a-a0cc-fa1e15e7d466.jpg?raw=true"></td>
 | 
					 | 
				
			||||||
    <tr>
 | 
					 | 
				
			||||||
    </tr>
 | 
					 | 
				
			||||||
</table>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## 部署
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- 前端 `dkube-web`,后端接口:`src\views\common\Config.js`
 | 
					 | 
				
			||||||
```shell
 | 
					 | 
				
			||||||
npm install
 | 
					 | 
				
			||||||
npm run build
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
@ -1,5 +0,0 @@
 | 
				
			|||||||
module.exports = {
 | 
					 | 
				
			||||||
  presets: [
 | 
					 | 
				
			||||||
    '@vue/cli-plugin-babel/preset'
 | 
					 | 
				
			||||||
  ]
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,19 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
  "compilerOptions": {
 | 
					 | 
				
			||||||
    "target": "es5",
 | 
					 | 
				
			||||||
    "module": "esnext",
 | 
					 | 
				
			||||||
    "baseUrl": "./",
 | 
					 | 
				
			||||||
    "moduleResolution": "node",
 | 
					 | 
				
			||||||
    "paths": {
 | 
					 | 
				
			||||||
      "@/*": [
 | 
					 | 
				
			||||||
        "src/*"
 | 
					 | 
				
			||||||
      ]
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "lib": [
 | 
					 | 
				
			||||||
      "esnext",
 | 
					 | 
				
			||||||
      "dom",
 | 
					 | 
				
			||||||
      "dom.iterable",
 | 
					 | 
				
			||||||
      "scripthost"
 | 
					 | 
				
			||||||
    ]
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										29239
									
								
								dkube-web/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						@ -1,55 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
  "name": "dkube-web",
 | 
					 | 
				
			||||||
  "version": "1.0.0",
 | 
					 | 
				
			||||||
  "private": true,
 | 
					 | 
				
			||||||
  "scripts": {
 | 
					 | 
				
			||||||
    "serve": "vue-cli-service serve",
 | 
					 | 
				
			||||||
    "build": "vue-cli-service build",
 | 
					 | 
				
			||||||
    "lint": "vue-cli-service lint"
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  "dependencies": {
 | 
					 | 
				
			||||||
    "@element-plus/icons-vue": "^1.1.4",
 | 
					 | 
				
			||||||
    "axios": "^0.26.1",
 | 
					 | 
				
			||||||
    "codemirror-editor-vue3": "^2.1.3",
 | 
					 | 
				
			||||||
    "core-js": "^3.6.5",
 | 
					 | 
				
			||||||
    "echarts": "^5.3.2",
 | 
					 | 
				
			||||||
    "element-plus": "^2.1.5",
 | 
					 | 
				
			||||||
    "json-editor-vue3": "^1.0.5",
 | 
					 | 
				
			||||||
    "json2yaml": "^1.1.0",
 | 
					 | 
				
			||||||
    "jsonwebtoken": "^8.5.1",
 | 
					 | 
				
			||||||
    "moment": "^2.29.2",
 | 
					 | 
				
			||||||
    "nprogress": "^0.2.0",
 | 
					 | 
				
			||||||
    "vue": "^3.0.0",
 | 
					 | 
				
			||||||
    "vue-router": "^4.0.14",
 | 
					 | 
				
			||||||
    "xterm": "^4.18.0",
 | 
					 | 
				
			||||||
    "xterm-addon-fit": "^0.5.0"
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  "devDependencies": {
 | 
					 | 
				
			||||||
    "@vue/cli-plugin-babel": "~4.5.15",
 | 
					 | 
				
			||||||
    "@vue/cli-plugin-eslint": "~4.5.15",
 | 
					 | 
				
			||||||
    "@vue/cli-service": "~4.5.15",
 | 
					 | 
				
			||||||
    "@vue/compiler-sfc": "^3.0.0",
 | 
					 | 
				
			||||||
    "babel-eslint": "^10.1.0",
 | 
					 | 
				
			||||||
    "eslint": "^6.7.2",
 | 
					 | 
				
			||||||
    "eslint-plugin-vue": "^7.0.0"
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  "eslintConfig": {
 | 
					 | 
				
			||||||
    "root": true,
 | 
					 | 
				
			||||||
    "env": {
 | 
					 | 
				
			||||||
      "node": true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "extends": [
 | 
					 | 
				
			||||||
      "plugin:vue/vue3-essential",
 | 
					 | 
				
			||||||
      "eslint:recommended"
 | 
					 | 
				
			||||||
    ],
 | 
					 | 
				
			||||||
    "parserOptions": {
 | 
					 | 
				
			||||||
      "parser": "babel-eslint"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "rules": {}
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  "browserslist": [
 | 
					 | 
				
			||||||
    "> 1%",
 | 
					 | 
				
			||||||
    "last 2 versions",
 | 
					 | 
				
			||||||
    "not dead"
 | 
					 | 
				
			||||||
  ]
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
		 Before Width: | Height: | Size: 9.3 KiB  | 
@ -1,17 +0,0 @@
 | 
				
			|||||||
<!DOCTYPE html>
 | 
					 | 
				
			||||||
<html lang="">
 | 
					 | 
				
			||||||
  <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>
 | 
					 | 
				
			||||||
  </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>
 | 
					 | 
				
			||||||
@ -1,15 +0,0 @@
 | 
				
			|||||||
<template>
 | 
					 | 
				
			||||||
  <router-view></router-view>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style>
 | 
					 | 
				
			||||||
html,body {
 | 
					 | 
				
			||||||
  width: 100%;
 | 
					 | 
				
			||||||
  height: 100%;
 | 
					 | 
				
			||||||
  padding: 0;
 | 
					 | 
				
			||||||
  margin: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#nprogress .bar {
 | 
					 | 
				
			||||||
  background: #2186c0 !important;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
| 
		 Before Width: | Height: | Size: 3.5 KiB  | 
| 
		 Before Width: | Height: | Size: 21 KiB  | 
| 
		 Before Width: | Height: | Size: 16 KiB  | 
| 
		 Before Width: | Height: | Size: 17 KiB  | 
| 
		 Before Width: | Height: | Size: 8.0 MiB  | 
| 
		 Before Width: | Height: | Size: 9.3 KiB  | 
| 
		 Before Width: | Height: | Size: 9.3 KiB  | 
@ -1,58 +0,0 @@
 | 
				
			|||||||
<template>
 | 
					 | 
				
			||||||
  <div class="hello">
 | 
					 | 
				
			||||||
    <h1>{{ msg }}</h1>
 | 
					 | 
				
			||||||
    <p>
 | 
					 | 
				
			||||||
      For a guide and recipes on how to configure / customize this project,<br>
 | 
					 | 
				
			||||||
      check out the
 | 
					 | 
				
			||||||
      <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
 | 
					 | 
				
			||||||
    </p>
 | 
					 | 
				
			||||||
    <h3>Installed CLI Plugins</h3>
 | 
					 | 
				
			||||||
    <ul>
 | 
					 | 
				
			||||||
      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
 | 
					 | 
				
			||||||
      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
 | 
					 | 
				
			||||||
    </ul>
 | 
					 | 
				
			||||||
    <h3>Essential Links</h3>
 | 
					 | 
				
			||||||
    <ul>
 | 
					 | 
				
			||||||
      <li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
 | 
					 | 
				
			||||||
      <li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
 | 
					 | 
				
			||||||
      <li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
 | 
					 | 
				
			||||||
      <li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
 | 
					 | 
				
			||||||
      <li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
 | 
					 | 
				
			||||||
    </ul>
 | 
					 | 
				
			||||||
    <h3>Ecosystem</h3>
 | 
					 | 
				
			||||||
    <ul>
 | 
					 | 
				
			||||||
      <li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
 | 
					 | 
				
			||||||
      <li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
 | 
					 | 
				
			||||||
      <li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
 | 
					 | 
				
			||||||
      <li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
 | 
					 | 
				
			||||||
      <li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
 | 
					 | 
				
			||||||
    </ul>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script>
 | 
					 | 
				
			||||||
export default {
 | 
					 | 
				
			||||||
  name: 'HelloWorld',
 | 
					 | 
				
			||||||
  props: {
 | 
					 | 
				
			||||||
    msg: String
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
 | 
					 | 
				
			||||||
<style scoped>
 | 
					 | 
				
			||||||
h3 {
 | 
					 | 
				
			||||||
  margin: 40px 0 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
ul {
 | 
					 | 
				
			||||||
  list-style-type: none;
 | 
					 | 
				
			||||||
  padding: 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
li {
 | 
					 | 
				
			||||||
  display: inline-block;
 | 
					 | 
				
			||||||
  margin: 0 10px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
a {
 | 
					 | 
				
			||||||
  color: #42b983;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
@ -1,219 +0,0 @@
 | 
				
			|||||||
<template>
 | 
					 | 
				
			||||||
    <div class="common-layout">
 | 
					 | 
				
			||||||
        <el-container style="height: 100vh;">
 | 
					 | 
				
			||||||
            <el-aside class="aside" :width="asideWidth">
 | 
					 | 
				
			||||||
                <el-affix class="aside-affix" :z-index="1200">
 | 
					 | 
				
			||||||
                    <div class="aside-logo" >
 | 
					 | 
				
			||||||
                        <el-image class="logo-image" :src="logo" />
 | 
					 | 
				
			||||||
                        <span :class="[isCollapse ? 'is-collapse' : '']">
 | 
					 | 
				
			||||||
                            <span class="logo-name" >DKube</span>
 | 
					 | 
				
			||||||
                        </span>
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                </el-affix>
 | 
					 | 
				
			||||||
                <el-menu class="aside-menu"
 | 
					 | 
				
			||||||
                    router
 | 
					 | 
				
			||||||
                    :default-active="$route.path"
 | 
					 | 
				
			||||||
                    :collapse="isCollapse"
 | 
					 | 
				
			||||||
                    background-color="#131b27"
 | 
					 | 
				
			||||||
                    text-color="#bfcbd9"
 | 
					 | 
				
			||||||
                    active-text-color="#20a0ff">
 | 
					 | 
				
			||||||
                    <div v-for="menu in routers" :key="menu">
 | 
					 | 
				
			||||||
                        <el-menu-item class="aside-menu-item" v-if="menu.children && menu.children.length == 1" :index="menu.children[0].path">
 | 
					 | 
				
			||||||
                        <el-icon><component :is="menu.children[0].icon" /></el-icon>
 | 
					 | 
				
			||||||
                        <template #title>
 | 
					 | 
				
			||||||
                            {{menu.children[0].name}}
 | 
					 | 
				
			||||||
                        </template>
 | 
					 | 
				
			||||||
                        </el-menu-item>
 | 
					 | 
				
			||||||
                        <el-sub-menu class="aside-submenu" v-else-if="menu.children" :index="menu.path">
 | 
					 | 
				
			||||||
                            <template #title>
 | 
					 | 
				
			||||||
                                <el-icon><component :is="menu.icon" /></el-icon>
 | 
					 | 
				
			||||||
                                <span :class="[isCollapse ? 'is-collapse' : '']">{{menu.name}}</span>
 | 
					 | 
				
			||||||
                            </template>
 | 
					 | 
				
			||||||
                            <el-menu-item class="aside-menu-childitem" v-for="child in menu.children" :key="child" :index="child.path">
 | 
					 | 
				
			||||||
                                <el-icon><component :is="child.icon" /></el-icon>
 | 
					 | 
				
			||||||
                                <template #title>
 | 
					 | 
				
			||||||
                                    {{child.name}}
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-menu-item>
 | 
					 | 
				
			||||||
                        </el-sub-menu>
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                </el-menu>
 | 
					 | 
				
			||||||
            </el-aside>
 | 
					 | 
				
			||||||
            <el-container>
 | 
					 | 
				
			||||||
                <el-header class="header" >
 | 
					 | 
				
			||||||
                    <el-row :gutter="20">
 | 
					 | 
				
			||||||
                        <el-col :span="1">
 | 
					 | 
				
			||||||
                            <div class="header-collapse" @click="onCollapse">
 | 
					 | 
				
			||||||
                                <el-icon><component :is="isCollapse ? 'expand':'fold'" /></el-icon>
 | 
					 | 
				
			||||||
                            </div>
 | 
					 | 
				
			||||||
                        </el-col>
 | 
					 | 
				
			||||||
                        <el-col :span="10" >
 | 
					 | 
				
			||||||
                            <div class="header-breadcrumb">
 | 
					 | 
				
			||||||
                                <el-breadcrumb separator="/" v-if="this.$route.matched[0].path != '/main'">
 | 
					 | 
				
			||||||
                                    <el-breadcrumb-item :to="{ path: '/' }">工作台</el-breadcrumb-item>
 | 
					 | 
				
			||||||
                                    <template v-for="(matched,m) in this.$route.matched" :key="m">
 | 
					 | 
				
			||||||
                                        <el-breadcrumb-item v-if="matched.name != undefined" >
 | 
					 | 
				
			||||||
                                        {{ matched.name }}
 | 
					 | 
				
			||||||
                                        </el-breadcrumb-item>
 | 
					 | 
				
			||||||
                                    </template>
 | 
					 | 
				
			||||||
                                </el-breadcrumb>
 | 
					 | 
				
			||||||
                                <el-breadcrumb separator="/" v-else>
 | 
					 | 
				
			||||||
                                    <el-breadcrumb-item>工作台</el-breadcrumb-item>
 | 
					 | 
				
			||||||
                                </el-breadcrumb> 
 | 
					 | 
				
			||||||
                            </div>
 | 
					 | 
				
			||||||
                        </el-col>
 | 
					 | 
				
			||||||
                        <el-col class="header-menu" :span="13">
 | 
					 | 
				
			||||||
                            <el-dropdown>
 | 
					 | 
				
			||||||
                                <div class="header-dropdown">
 | 
					 | 
				
			||||||
                                    <el-image class="avator-image" :src="avator" />
 | 
					 | 
				
			||||||
                                    <span>{{ username }}</span>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                                <template #dropdown>
 | 
					 | 
				
			||||||
                                    <el-dropdown-menu>
 | 
					 | 
				
			||||||
                                        <el-dropdown-item icon="el-icon-switch-button" @click="logout()">退出</el-dropdown-item>
 | 
					 | 
				
			||||||
                                        <el-dropdown-item icon="el-icon-unlock">修改密码</el-dropdown-item>
 | 
					 | 
				
			||||||
                                    </el-dropdown-menu>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-dropdown>
 | 
					 | 
				
			||||||
                        </el-col>
 | 
					 | 
				
			||||||
                    </el-row>
 | 
					 | 
				
			||||||
                </el-header>
 | 
					 | 
				
			||||||
                <el-main class="main">
 | 
					 | 
				
			||||||
                    <router-view></router-view>
 | 
					 | 
				
			||||||
                </el-main>
 | 
					 | 
				
			||||||
                <el-footer class="footer">
 | 
					 | 
				
			||||||
                    <el-icon style="width:2em;top:3px;font-size:18px"><place/></el-icon>
 | 
					 | 
				
			||||||
                    <a class="footer el-icon-place">2022 DevOps </a>
 | 
					 | 
				
			||||||
                </el-footer>
 | 
					 | 
				
			||||||
                <el-backtop target=".el-main"></el-backtop>
 | 
					 | 
				
			||||||
            </el-container>
 | 
					 | 
				
			||||||
        </el-container>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script>
 | 
					 | 
				
			||||||
import {useRouter} from 'vue-router'
 | 
					 | 
				
			||||||
export default {
 | 
					 | 
				
			||||||
    data() {
 | 
					 | 
				
			||||||
        return {
 | 
					 | 
				
			||||||
            avator: require('@/assets/avator/avator.png'),
 | 
					 | 
				
			||||||
            logo: require('@/assets/k8s/k8s-metrics.png'),
 | 
					 | 
				
			||||||
            isCollapse: false,
 | 
					 | 
				
			||||||
            asideWidth: '220px',
 | 
					 | 
				
			||||||
            routers: [],
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    computed: {
 | 
					 | 
				
			||||||
        username() {
 | 
					 | 
				
			||||||
            let username = localStorage.getItem('username');
 | 
					 | 
				
			||||||
            return username ? username : '未知';
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    methods: {
 | 
					 | 
				
			||||||
        onCollapse() {
 | 
					 | 
				
			||||||
            if (this.isCollapse) {
 | 
					 | 
				
			||||||
                this.asideWidth = '220px'
 | 
					 | 
				
			||||||
                this.isCollapse = false
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                this.isCollapse = true
 | 
					 | 
				
			||||||
                this.asideWidth = '64px'
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        logout() {
 | 
					 | 
				
			||||||
            localStorage.removeItem('username');
 | 
					 | 
				
			||||||
            localStorage.removeItem('token');
 | 
					 | 
				
			||||||
            this.$router.push('/login');
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    beforeMount() {
 | 
					 | 
				
			||||||
        this.routers = useRouter().options.routes
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style scoped>
 | 
					 | 
				
			||||||
    .aside {
 | 
					 | 
				
			||||||
        transition: all .5s;
 | 
					 | 
				
			||||||
        background-color: #131b27;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .aside-logo {
 | 
					 | 
				
			||||||
        background-color: #131b27;
 | 
					 | 
				
			||||||
        height: 60px;
 | 
					 | 
				
			||||||
        color: white;
 | 
					 | 
				
			||||||
        cursor: pointer;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .logo-image {
 | 
					 | 
				
			||||||
        width: 40px;
 | 
					 | 
				
			||||||
        height: 40px;
 | 
					 | 
				
			||||||
        top: 12px;
 | 
					 | 
				
			||||||
        padding-left: 12px;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .logo-name {
 | 
					 | 
				
			||||||
        font-size: 20px;
 | 
					 | 
				
			||||||
        font-weight: bold;
 | 
					 | 
				
			||||||
        padding: 10px;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .aside::-webkit-scrollbar {
 | 
					 | 
				
			||||||
        display: none;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .aside-affix {
 | 
					 | 
				
			||||||
        border-bottom-width: 0;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .aside-menu {
 | 
					 | 
				
			||||||
        border-right-width: 0;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .aside-menu-item.is-active {
 | 
					 | 
				
			||||||
        background-color: #1f2a3a;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .aside-menu-item {
 | 
					 | 
				
			||||||
        padding-left: 20px !important;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .aside-menu-childitem {
 | 
					 | 
				
			||||||
        padding-left: 20px !important;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .aside-menu-childitem.is-active {
 | 
					 | 
				
			||||||
        background-color: #1f2a3a;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .aside-menu-childitem:hover {
 | 
					 | 
				
			||||||
        background-color: #142c4e;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .header {
 | 
					 | 
				
			||||||
        z-index:1200;
 | 
					 | 
				
			||||||
        line-height: 60px;
 | 
					 | 
				
			||||||
        font-size: 24px;
 | 
					 | 
				
			||||||
        box-shadow: 0 2px 4px rgba(0, 0, 0, .12),0 0 6px rgba(0, 0, 0, .04)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .header-collapse {
 | 
					 | 
				
			||||||
        cursor: pointer;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .header-breadcrumb {
 | 
					 | 
				
			||||||
        padding-top: 0.9em;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .header-menu {
 | 
					 | 
				
			||||||
        text-align: right;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .is-collapse {
 | 
					 | 
				
			||||||
        display: none;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .header-dropdown {
 | 
					 | 
				
			||||||
        line-height: 60px;
 | 
					 | 
				
			||||||
        cursor: pointer;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .avator-image {
 | 
					 | 
				
			||||||
        top: 12px;
 | 
					 | 
				
			||||||
        width: 40px;
 | 
					 | 
				
			||||||
        height: 40px;
 | 
					 | 
				
			||||||
        border-radius: 50%;
 | 
					 | 
				
			||||||
        margin-right: 8px;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .main {
 | 
					 | 
				
			||||||
        padding: 10px;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .footer {
 | 
					 | 
				
			||||||
        z-index: 1200;
 | 
					 | 
				
			||||||
        color: rgb(187, 184, 184);
 | 
					 | 
				
			||||||
        font-size: 14px;
 | 
					 | 
				
			||||||
        text-align: center;
 | 
					 | 
				
			||||||
        line-height: 60px;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
@ -1,18 +0,0 @@
 | 
				
			|||||||
import { createApp } from 'vue'
 | 
					 | 
				
			||||||
import ElementPlus from 'element-plus'
 | 
					 | 
				
			||||||
import 'element-plus/dist/index.css'
 | 
					 | 
				
			||||||
import * as ELIcons from '@element-plus/icons-vue'
 | 
					 | 
				
			||||||
import App from './App.vue'
 | 
					 | 
				
			||||||
import router from './router'
 | 
					 | 
				
			||||||
import { GlobalCmComponent } from "codemirror-editor-vue3";
 | 
					 | 
				
			||||||
import 'codemirror/theme/idea.css'
 | 
					 | 
				
			||||||
import 'codemirror/mode/yaml/yaml.js'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const app = createApp(App)
 | 
					 | 
				
			||||||
for (let iconName in ELIcons) {
 | 
					 | 
				
			||||||
    app.component(iconName, ELIcons[iconName])
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
app.use(ElementPlus)
 | 
					 | 
				
			||||||
app.use(GlobalCmComponent, { componentName: "codemirror" });
 | 
					 | 
				
			||||||
app.use(router)
 | 
					 | 
				
			||||||
app.mount('#app')
 | 
					 | 
				
			||||||
@ -1,221 +0,0 @@
 | 
				
			|||||||
import {createRouter,createWebHistory} from 'vue-router'
 | 
					 | 
				
			||||||
import NProgress from 'nprogress'
 | 
					 | 
				
			||||||
import 'nprogress/nprogress.css'
 | 
					 | 
				
			||||||
import Layout from "@/layout/Layout"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import jwt from 'jsonwebtoken'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const routes =[
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        path: '/login',
 | 
					 | 
				
			||||||
        component: () => import('@/views/login/Login.vue'),
 | 
					 | 
				
			||||||
        icon: "odometer",
 | 
					 | 
				
			||||||
        meta: {title: "登录", requireAuth: false},
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        path: '/',
 | 
					 | 
				
			||||||
        redirect: '/home'
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        path: '/home',
 | 
					 | 
				
			||||||
        component: Layout,
 | 
					 | 
				
			||||||
        icon: "odometer",
 | 
					 | 
				
			||||||
        children: [
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                path: "/home",
 | 
					 | 
				
			||||||
                name: "K8s概览",
 | 
					 | 
				
			||||||
                icon: "odometer",
 | 
					 | 
				
			||||||
                meta: {title: "K8s概览", requireAuth: true},
 | 
					 | 
				
			||||||
                component: () => import('@/views/home/Home.vue'),
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        path: '/workflow',
 | 
					 | 
				
			||||||
        component: Layout,
 | 
					 | 
				
			||||||
        icon: "VideoPlay",
 | 
					 | 
				
			||||||
        children: [
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                path: "/workflow",
 | 
					 | 
				
			||||||
                name: "工作流",
 | 
					 | 
				
			||||||
                icon: "VideoPlay",
 | 
					 | 
				
			||||||
                meta: {title: "工作流", requireAuth: true},
 | 
					 | 
				
			||||||
                component: () => import('@/views/workflow/Workflow.vue')
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        path: "/cluster",
 | 
					 | 
				
			||||||
        name: "集群信息",
 | 
					 | 
				
			||||||
        component: Layout,
 | 
					 | 
				
			||||||
        icon: "home-filled",
 | 
					 | 
				
			||||||
        meta: {title: "集群信息", requireAuth: true},
 | 
					 | 
				
			||||||
        children: [
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                path: "/cluster/node",
 | 
					 | 
				
			||||||
                name: "Node",
 | 
					 | 
				
			||||||
                icon: "el-icon-s-data",
 | 
					 | 
				
			||||||
                meta: {title: "Node", requireAuth: true},
 | 
					 | 
				
			||||||
                component: () => import("@/views/node/Node.vue")
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                path: "/cluster/namespace",
 | 
					 | 
				
			||||||
                name: "Namespace",
 | 
					 | 
				
			||||||
                icon: "el-icon-document-add",
 | 
					 | 
				
			||||||
                meta: {title: "Namespace", requireAuth: true},
 | 
					 | 
				
			||||||
                component: () => import("@/views/namespace/Namespace.vue")
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                path: "/cluster/persistentvolume",
 | 
					 | 
				
			||||||
                name: "PersistentVolume",
 | 
					 | 
				
			||||||
                icon: "el-icon-document-add",
 | 
					 | 
				
			||||||
                meta: {title: "PersistemtVolume", requireAuth: true},
 | 
					 | 
				
			||||||
                component: () => import("@/views/persistentvolume/PersistentVolume.vue")
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        path: '/workload',
 | 
					 | 
				
			||||||
        name: '工作负载',
 | 
					 | 
				
			||||||
        component: Layout,
 | 
					 | 
				
			||||||
        icon: "menu",
 | 
					 | 
				
			||||||
        meta: {title: "工作负载", requireAuth: true},
 | 
					 | 
				
			||||||
        children: [
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                path: '/workload/deployment',
 | 
					 | 
				
			||||||
                name: 'Deployment',
 | 
					 | 
				
			||||||
                icon: 'el-icon-s-data',
 | 
					 | 
				
			||||||
                meta: {title: "Deployment", requireAuth: true},
 | 
					 | 
				
			||||||
                component: () => import("@/views/deployment/Deployment.vue")
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                path: '/workload/pod',
 | 
					 | 
				
			||||||
                name: 'Pod',
 | 
					 | 
				
			||||||
                icon: 'el-icon-document-add', 
 | 
					 | 
				
			||||||
                meta: {title: "Pod", requireAuth: true},
 | 
					 | 
				
			||||||
                component: () => import("@/views/pod/Pod.vue")
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                path: '/workload/daemonset',
 | 
					 | 
				
			||||||
                name: 'DaemonSet',
 | 
					 | 
				
			||||||
                icon: 'el-icon-document-add',
 | 
					 | 
				
			||||||
                meta: {title: "DaemonSet", requireAuth: true},
 | 
					 | 
				
			||||||
                component: () => import("@/views/daemonset/DaemonSet.vue")
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                path: '/workload/statefulset',
 | 
					 | 
				
			||||||
                name: 'StatefulSet',
 | 
					 | 
				
			||||||
                icon: 'el-icon-document-add', 
 | 
					 | 
				
			||||||
                meta: {title: "StatefulSet", requireAuth: true},
 | 
					 | 
				
			||||||
                component: () => import("@/views/statefulset/StatefulSet.vue")
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        path: "/loadbalance",
 | 
					 | 
				
			||||||
        name: "负载均衡",
 | 
					 | 
				
			||||||
        component: Layout,
 | 
					 | 
				
			||||||
        icon: "files",
 | 
					 | 
				
			||||||
        meta: {title: "负载均衡", requireAuth: true},
 | 
					 | 
				
			||||||
        children: [
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                path: "/loadbalance/service",
 | 
					 | 
				
			||||||
                name: "Service",
 | 
					 | 
				
			||||||
                icon: "el-icon-s-data",
 | 
					 | 
				
			||||||
                meta: {title: "Service", requireAuth: true},
 | 
					 | 
				
			||||||
                component: () => import("@/views/service/Service.vue")
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                path: "/loadbalance/ingress",
 | 
					 | 
				
			||||||
                name: "Ingress",
 | 
					 | 
				
			||||||
                icon: "el-icon-document-add",
 | 
					 | 
				
			||||||
                meta: {title: "Ingress", requireAuth: true},
 | 
					 | 
				
			||||||
                component: () => import("@/views/ingress/Ingress.vue")
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        path: "/storage",
 | 
					 | 
				
			||||||
        name: "存储与配置",
 | 
					 | 
				
			||||||
        component: Layout,
 | 
					 | 
				
			||||||
        icon: "tickets",
 | 
					 | 
				
			||||||
        meta: {title: "存储与配置", requireAuth: true},
 | 
					 | 
				
			||||||
        children: [
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                path: "/storage/configmap",
 | 
					 | 
				
			||||||
                name: "Configmap",
 | 
					 | 
				
			||||||
                icon: "el-icon-document-add",
 | 
					 | 
				
			||||||
                meta: {title: "Configmap", requireAuth: true},
 | 
					 | 
				
			||||||
                component: () => import("@/views/configmap/ConfigMap.vue")
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                path: "/storage/secret",
 | 
					 | 
				
			||||||
                name: "Secret",
 | 
					 | 
				
			||||||
                icon: "el-icon-document-add",
 | 
					 | 
				
			||||||
                meta: {title: "Secret", requireAuth: true},
 | 
					 | 
				
			||||||
                component: () => import("@/views/secret/Secret.vue")
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                path: "/storage/persistentvolumeclaim",
 | 
					 | 
				
			||||||
                name: "PersistentVolumeClaim",
 | 
					 | 
				
			||||||
                icon: "el-icon-s-data",
 | 
					 | 
				
			||||||
                meta: {title: "PersistentVolumeClaim", requireAuth: true},
 | 
					 | 
				
			||||||
                component: () => import("@/views/persistentvolumeclaim/PersistentVolumeClaim.vue")
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        path: '/404',
 | 
					 | 
				
			||||||
        component: () => import('@/views/common/404.vue'),
 | 
					 | 
				
			||||||
        meta: {
 | 
					 | 
				
			||||||
            title: '404'
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        path: '/403',
 | 
					 | 
				
			||||||
        component: () => import('@/views/common/403.vue'),
 | 
					 | 
				
			||||||
        meta: {
 | 
					 | 
				
			||||||
            title: '403'
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        path: '/:pathMatch(.*)',
 | 
					 | 
				
			||||||
        redirect: '/404'
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const router = createRouter ({
 | 
					 | 
				
			||||||
    history: createWebHistory(),
 | 
					 | 
				
			||||||
    routes
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
NProgress.inc(100)
 | 
					 | 
				
			||||||
NProgress.configure({ easing: 'ease', speed: 600,showSpinner: false})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
router.beforeEach((to,from,next) => {
 | 
					 | 
				
			||||||
    NProgress.start()
 | 
					 | 
				
			||||||
    if (to.meta.title) {
 | 
					 | 
				
			||||||
        document.title = to.meta.title
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        document.title = "DKube"
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    next()
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
router.beforeEach((to, from, next) => {
 | 
					 | 
				
			||||||
    jwt.verify(localStorage.getItem('token'), 'devops', function (err) {
 | 
					 | 
				
			||||||
        if (to.path === '/login') {
 | 
					 | 
				
			||||||
            next()
 | 
					 | 
				
			||||||
        } else if (err) {
 | 
					 | 
				
			||||||
            next('/login');
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            next();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
router.afterEach (() => {
 | 
					 | 
				
			||||||
    NProgress.done()
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default router
 | 
					 | 
				
			||||||
@ -1,44 +0,0 @@
 | 
				
			|||||||
import axios from 'axios';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const httpClient = axios.create({
 | 
					 | 
				
			||||||
    validateStatus(status) {
 | 
					 | 
				
			||||||
        return status >= 200 && status < 504
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    timeout: 10000
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
httpClient.defaults.retry = 3 
 | 
					 | 
				
			||||||
httpClient.defaults.retryDelay = 1000
 | 
					 | 
				
			||||||
httpClient.defaults.shouldRetry = true
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
httpClient.interceptors.request.use (
 | 
					 | 
				
			||||||
    config => {
 | 
					 | 
				
			||||||
        config.headers['Content-Type'] = 'application/json'
 | 
					 | 
				
			||||||
        config.headers['Accept-Language'] = 'zh-CN'
 | 
					 | 
				
			||||||
        config.headers['Authorization'] = localStorage.getItem('token') 
 | 
					 | 
				
			||||||
        if (config.method === 'post') {
 | 
					 | 
				
			||||||
            if (!config.data) {
 | 
					 | 
				
			||||||
                config.data = {}
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return config
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    err => {
 | 
					 | 
				
			||||||
        Promise.reject(err)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
httpClient.interceptors.response.use (
 | 
					 | 
				
			||||||
    response => {
 | 
					 | 
				
			||||||
        if (response.status !== 200) {
 | 
					 | 
				
			||||||
            return Promise.reject(response.data)
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            return response.data
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    err => {
 | 
					 | 
				
			||||||
        return Promise.reject(err)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default httpClient;
 | 
					 | 
				
			||||||
@ -1,44 +0,0 @@
 | 
				
			|||||||
<template>
 | 
					 | 
				
			||||||
    <div class="main-body-div">
 | 
					 | 
				
			||||||
        <el-row>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <img class="main-body-img" src="../../assets/img/403.png" />
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
                </el-col>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <p class="status-code">403</p>
 | 
					 | 
				
			||||||
                    <p class="status-describe">你暂时无权限访问该页面······</p>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
        </el-row>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script>
 | 
					 | 
				
			||||||
export default {
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style scoped>
 | 
					 | 
				
			||||||
  .main-body-img {
 | 
					 | 
				
			||||||
    margin-top: 150px
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  .main-body-div {
 | 
					 | 
				
			||||||
    text-align: center;
 | 
					 | 
				
			||||||
    height: 100vh;
 | 
					 | 
				
			||||||
    width: 100vw;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  .status-code {
 | 
					 | 
				
			||||||
    margin-top: 20px;
 | 
					 | 
				
			||||||
    margin-bottom: 10px;
 | 
					 | 
				
			||||||
    font-size: 95px;
 | 
					 | 
				
			||||||
    font-weight: bold;
 | 
					 | 
				
			||||||
    color: rgb(54, 95, 230);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  .status-describe {
 | 
					 | 
				
			||||||
    color: rgb(145, 143, 143);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
@ -1,43 +0,0 @@
 | 
				
			|||||||
<template>
 | 
					 | 
				
			||||||
    <div class="main-body-div">
 | 
					 | 
				
			||||||
        <el-row>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <img class="main-body-img" src="../../assets/img/404.png" />
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
                </el-col>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <p class="status-code">404</p>
 | 
					 | 
				
			||||||
                    <p class="status-describe">你所访问的页面不存在······</p>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
        </el-row>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script>
 | 
					 | 
				
			||||||
export default {
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style scoped>
 | 
					 | 
				
			||||||
  .main-body-img {
 | 
					 | 
				
			||||||
    margin-top: 15%;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  .main-body-div {
 | 
					 | 
				
			||||||
    text-align: center;
 | 
					 | 
				
			||||||
    height: 100vh;
 | 
					 | 
				
			||||||
    width: 100vw;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  .status-code {
 | 
					 | 
				
			||||||
    margin: 20px 0 20px 0;
 | 
					 | 
				
			||||||
    font-size: 95px;
 | 
					 | 
				
			||||||
    font-weight: bold;
 | 
					 | 
				
			||||||
    color: rgb(54, 95, 230);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  .status-describe {
 | 
					 | 
				
			||||||
    color: rgb(145, 143, 143);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
@ -1,72 +0,0 @@
 | 
				
			|||||||
export default {
 | 
					 | 
				
			||||||
    loginAuth: 'http://localhost:9090/api/login',
 | 
					 | 
				
			||||||
    k8sWorkflowCreate: 'http://localhost:9090/api/k8s/workflow/create',
 | 
					 | 
				
			||||||
    k8sWorkflowDetail: 'http://localhost:9090/api/k8s/workflow/detail',
 | 
					 | 
				
			||||||
    k8sWorkflowList: 'http://localhost:9090/api/k8s/workflows',
 | 
					 | 
				
			||||||
    k8sWorkflowDel: 'http://localhost:9090/api/k8s/workflow/del',
 | 
					 | 
				
			||||||
    k8sDeploymentList: 'http://localhost:9090/api/k8s/deployments',
 | 
					 | 
				
			||||||
    k8sDeploymentDetail: 'http://localhost:9090/api/k8s/deployment/detail',
 | 
					 | 
				
			||||||
    k8sDeploymentUpdate: 'http://localhost:9090/api/k8s/deployment/update',
 | 
					 | 
				
			||||||
    k8sDeploymentScale: 'http://localhost:9090/api/k8s/deployment/scale',
 | 
					 | 
				
			||||||
    k8sDeploymentRestart: 'http://localhost:9090/api/k8s/deployment/restart',
 | 
					 | 
				
			||||||
    k8sDeploymentDel: 'http://localhost:9090/api/k8s/deployment/del',
 | 
					 | 
				
			||||||
    k8sDeploymentCreate: 'http://localhost:9090/api/k8s/deployment/create',
 | 
					 | 
				
			||||||
    k8sDeploymentNumNp: 'http://localhost:9090/api/k8s/deployment/numnp',
 | 
					 | 
				
			||||||
    k8sPodList: 'http://localhost:9090/api/k8s/pods',
 | 
					 | 
				
			||||||
    k8sPodDetail: 'http://localhost:9090/api/k8s/pod/detail',
 | 
					 | 
				
			||||||
    k8sPodUpdate: 'http://localhost:9090/api/k8s/pod/update',
 | 
					 | 
				
			||||||
    k8sPodDel: 'http://localhost:9090/api/k8s/pod/del',
 | 
					 | 
				
			||||||
    k8sPodContainer: 'http://localhost:9090/api/k8s/pod/container',
 | 
					 | 
				
			||||||
    k8sPodLog: 'http://localhost:9090/api/k8s/pod/log',
 | 
					 | 
				
			||||||
    k8sPodNumNp: 'http://localhost:9090/api/k8s/pod/numnp',
 | 
					 | 
				
			||||||
    k8sDaemonSetList: 'http://localhost:9090/api/k8s/daemonsets',
 | 
					 | 
				
			||||||
    k8sDaemonSetDetail: 'http://localhost:9090/api/k8s/daemonset/detail',
 | 
					 | 
				
			||||||
    k8sDaemonSetUpdate: 'http://localhost:9090/api/k8s/daemonset/update',
 | 
					 | 
				
			||||||
    k8sDaemonSetDel: 'http://localhost:9090/api/k8s/daemonset/del',
 | 
					 | 
				
			||||||
    k8sStatefulSetList: 'http://localhost:9090/api/k8s/statefulsets',
 | 
					 | 
				
			||||||
    k8sStatefulSetDetail: 'http://localhost:9090/api/k8s/daemonset/detail',
 | 
					 | 
				
			||||||
    k8sStatefulSetUpdate: 'http://localhost:9090/api/k8s/daemonset/update',
 | 
					 | 
				
			||||||
    k8sStatefulSetDel: 'http://localhost:9090/api/k8s/daemonset/del',
 | 
					 | 
				
			||||||
    k8sServiceList: 'http://localhost:9090/api/k8s/services',
 | 
					 | 
				
			||||||
    k8sServiceDetail: 'http://localhost:9090/api/k8s/service/detail',
 | 
					 | 
				
			||||||
    k8sServiceUpdate: 'http://localhost:9090/api/k8s/service/update',
 | 
					 | 
				
			||||||
    k8sServiceDel: 'http://localhost:9090/api/k8s/service/del',
 | 
					 | 
				
			||||||
    k8sServiceCreate: 'http://localhost:9090/api/k8s/service/create',
 | 
					 | 
				
			||||||
    k8sIngressList: 'http://localhost:9090/api/k8s/ingresses',
 | 
					 | 
				
			||||||
    k8sIngressDetail: 'http://localhost:9090/api/k8s/ingress/detail',
 | 
					 | 
				
			||||||
    k8sIngressUpdate: 'http://localhost:9090/api/k8s/ingress/update',
 | 
					 | 
				
			||||||
    k8sIngressDel: 'http://localhost:9090/api/k8s/ingress/del',
 | 
					 | 
				
			||||||
    k8sIngressCreate: 'http://localhost:9090/api/k8s/ingress/create',
 | 
					 | 
				
			||||||
    k8sConfigMapList: 'http://localhost:9090/api/k8s/configmaps',
 | 
					 | 
				
			||||||
    k8sConfigMapDetail: 'http://localhost:9090/api/k8s/configmap/detail',
 | 
					 | 
				
			||||||
    k8sConfigMapUpdate: 'http://localhost:9090/api/k8s/configmap/update',
 | 
					 | 
				
			||||||
    k8sConfigMapDel: 'http://localhost:9090/api/k8s/configmap/del',
 | 
					 | 
				
			||||||
    k8sSecretList: 'http://localhost:9090/api/k8s/secrets',
 | 
					 | 
				
			||||||
    k8sSecretDetail: 'http://localhost:9090/api/k8s/secret/detail',
 | 
					 | 
				
			||||||
    k8sSecretUpdate: 'http://localhost:9090/api/k8s/secret/update',
 | 
					 | 
				
			||||||
    k8sSecretDel: 'http://localhost:9090/api/k8s/secret/del',
 | 
					 | 
				
			||||||
    k8sPvcList: 'http://localhost:9090/api/k8s/pvcs',
 | 
					 | 
				
			||||||
    k8sPvcDetail: 'http://localhost:9090/api/k8s/pvc/detail',
 | 
					 | 
				
			||||||
    k8sPvcUpdate: 'http://localhost:9090/api/k8s/pvc/update',
 | 
					 | 
				
			||||||
    k8sPvcDel: 'http://localhost:9090/api/k8s/pvc/del',
 | 
					 | 
				
			||||||
    k8sNodeList: 'http://localhost:9090/api/k8s/nodes',
 | 
					 | 
				
			||||||
    k8sNodeDetail: 'http://localhost:9090/api/k8s/node/detail',
 | 
					 | 
				
			||||||
    k8sNamespaceList: 'http://localhost:9090/api/k8s/namespaces',
 | 
					 | 
				
			||||||
    k8sNamespaceDetail: 'http://localhost:9090/api/k8s/namespace/detail',
 | 
					 | 
				
			||||||
    k8sNamespaceDel: 'http://localhost:9090/api/k8s/namespace/del',
 | 
					 | 
				
			||||||
    k8sPvList: 'http://localhost:9090/api/k8s/pvs',
 | 
					 | 
				
			||||||
    k8sPvDetail: 'http://localhost:9090/api/k8s/pv/detail',
 | 
					 | 
				
			||||||
    k8sTerminalWs: 'ws://localhost:8081/ws',
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    cmOptions: {
 | 
					 | 
				
			||||||
        mode: 'text/yaml',
 | 
					 | 
				
			||||||
        theme: 'idea',
 | 
					 | 
				
			||||||
        lineNumbers: true,
 | 
					 | 
				
			||||||
        smartIndent: true,
 | 
					 | 
				
			||||||
        indentUnit: 4,
 | 
					 | 
				
			||||||
        styleActiveLine: true,
 | 
					 | 
				
			||||||
        matchBrackets: true,
 | 
					 | 
				
			||||||
        readOnly: false,
 | 
					 | 
				
			||||||
        lineWrapping: true
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,365 +0,0 @@
 | 
				
			|||||||
<template>
 | 
					 | 
				
			||||||
    <div class="configmap">
 | 
					 | 
				
			||||||
        <el-row>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="configmap-head-card" shadow="never" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                        <el-row>
 | 
					 | 
				
			||||||
                            <el-col :span="6">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <span>命名空间: </span>
 | 
					 | 
				
			||||||
                                    <el-select v-model="namespaceValue" filterable placeholder="请选择">
 | 
					 | 
				
			||||||
                                        <el-option
 | 
					 | 
				
			||||||
                                        v-for="(item, index) in namespaceList"
 | 
					 | 
				
			||||||
                                        :key="index"
 | 
					 | 
				
			||||||
                                        :label="item.metadata.name"
 | 
					 | 
				
			||||||
                                        :value="item.metadata.name">
 | 
					 | 
				
			||||||
                                        </el-option>
 | 
					 | 
				
			||||||
                                    </el-select>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                            <el-col :span="2" :offset="16">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Refresh" plain @click="getConfigMaps()">刷新</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                        </el-row>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="configmap-head-card" shadow="never" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                        <el-row>
 | 
					 | 
				
			||||||
                            <el-col :span="2">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-button disabled style="border-radius:2px;" icon="Edit" type="primary">创建</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                            <el-col :span="6">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-input class="configmap-head-search" clearable placeholder="请输入" v-model="searchInput"></el-input>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Search" type="primary" plain @click="getConfigMaps()">搜索</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                        </el-row>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="configmap-body-card" shadow="never" :body-style="{padding:'5px'}">
 | 
					 | 
				
			||||||
                        <el-table
 | 
					 | 
				
			||||||
                        style="width:100%;font-size:12px;margin-bottom:10px;"
 | 
					 | 
				
			||||||
                        :data="configMapList"
 | 
					 | 
				
			||||||
                        v-loading="appLoading">
 | 
					 | 
				
			||||||
                            <el-table-column width="20"></el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=left label="ConfigMap名">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <a class="configmap-body-configmapname">{{ scope.row.metadata.name }}</a>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="标签">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <div v-for="(val, key) in scope.row.metadata.labels" :key="key">
 | 
					 | 
				
			||||||
                                        <el-popover
 | 
					 | 
				
			||||||
                                            placement="right"
 | 
					 | 
				
			||||||
                                            :width="200"
 | 
					 | 
				
			||||||
                                            trigger="hover"
 | 
					 | 
				
			||||||
                                            :content="key + ':' + val">
 | 
					 | 
				
			||||||
                                            <template #reference>
 | 
					 | 
				
			||||||
                                                <el-tag style="margin-bottom: 5px" type="warning">{{ ellipsis(key + ":" + val) }}</el-tag>
 | 
					 | 
				
			||||||
                                            </template>
 | 
					 | 
				
			||||||
                                        </el-popover>
 | 
					 | 
				
			||||||
                                    </div>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="DATA">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                        <el-popover
 | 
					 | 
				
			||||||
                                            style="overflow:auto"
 | 
					 | 
				
			||||||
                                            placement="right"
 | 
					 | 
				
			||||||
                                            :width="400"
 | 
					 | 
				
			||||||
                                            trigger="click">
 | 
					 | 
				
			||||||
                                            <div style="overflow-y:auto;max-height:500px;">
 | 
					 | 
				
			||||||
                                                <span>{{ scope.row.data }}</span>
 | 
					 | 
				
			||||||
                                            </div>
 | 
					 | 
				
			||||||
                                            <template #reference>
 | 
					 | 
				
			||||||
                                                <el-icon style="font-size:18px;cursor:pointer;"><reading/></el-icon>
 | 
					 | 
				
			||||||
                                            </template>
 | 
					 | 
				
			||||||
                                        </el-popover>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center min-width="100" label="创建时间">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-tag type="info">{{ timeTrans(scope.row.metadata.creationTimestamp) }} </el-tag>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="操作" width="200">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-button size="small" style="border-radius:2px;" icon="Edit" type="primary" plain @click="getConfigMapDetail(scope)">YAML</el-button>
 | 
					 | 
				
			||||||
                                    <el-button size="small" style="border-radius:2px;" icon="Delete" type="danger" @click="handleConfirm(scope, '删除', delConfigMap)">删除</el-button>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                        </el-table>
 | 
					 | 
				
			||||||
                        <el-pagination
 | 
					 | 
				
			||||||
                        class="configmap-body-pagination"
 | 
					 | 
				
			||||||
                        background
 | 
					 | 
				
			||||||
                        @size-change="handleSizeChange"
 | 
					 | 
				
			||||||
                        @current-change="handleCurrentChange"
 | 
					 | 
				
			||||||
                        :current-page="currentPage"
 | 
					 | 
				
			||||||
                        :page-sizes="pagesizeList"
 | 
					 | 
				
			||||||
                        :page-size="pagesize"
 | 
					 | 
				
			||||||
                        layout="total, sizes, prev, pager, next, jumper"
 | 
					 | 
				
			||||||
                        :total="configMapTotal">
 | 
					 | 
				
			||||||
                        </el-pagination>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
        </el-row>
 | 
					 | 
				
			||||||
        <el-dialog title="YAML信息" v-model="yamlDialog" width="45%" top="5%">
 | 
					 | 
				
			||||||
        <codemirror
 | 
					 | 
				
			||||||
            :value="contentYaml"
 | 
					 | 
				
			||||||
            border
 | 
					 | 
				
			||||||
            :options="cmOptions"
 | 
					 | 
				
			||||||
            height="500"
 | 
					 | 
				
			||||||
            style="font-size:14px;"
 | 
					 | 
				
			||||||
            @change="onChange"
 | 
					 | 
				
			||||||
        ></codemirror>
 | 
					 | 
				
			||||||
            <template #footer>
 | 
					 | 
				
			||||||
                <span class="dialog-footer">
 | 
					 | 
				
			||||||
                    <el-button @click="yamlDialog = false">取 消</el-button>
 | 
					 | 
				
			||||||
                    <el-button type="primary" @click="updateConfigMap()">更 新</el-button>
 | 
					 | 
				
			||||||
                </span>
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
        </el-dialog>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script>
 | 
					 | 
				
			||||||
import common from "../common/Config";
 | 
					 | 
				
			||||||
import httpClient from '../../utils/request';
 | 
					 | 
				
			||||||
import yaml2obj from 'js-yaml';
 | 
					 | 
				
			||||||
import json2yaml from 'json2yaml';
 | 
					 | 
				
			||||||
export default {
 | 
					 | 
				
			||||||
    data() {
 | 
					 | 
				
			||||||
        return {
 | 
					 | 
				
			||||||
            cmOptions: common.cmOptions,
 | 
					 | 
				
			||||||
            contentYaml: '',
 | 
					 | 
				
			||||||
            currentPage: 1,
 | 
					 | 
				
			||||||
            pagesize: 10,
 | 
					 | 
				
			||||||
            pagesizeList: [10, 20, 30],
 | 
					 | 
				
			||||||
            searchInput: '',
 | 
					 | 
				
			||||||
            namespaceValue: 'default',
 | 
					 | 
				
			||||||
            namespaceList: [],
 | 
					 | 
				
			||||||
            namespaceListUrl: common.k8sNamespaceList,
 | 
					 | 
				
			||||||
            appLoading: false,
 | 
					 | 
				
			||||||
            configMapList: [],
 | 
					 | 
				
			||||||
            configMapTotal: 0,
 | 
					 | 
				
			||||||
            getConfigMapsData: {
 | 
					 | 
				
			||||||
                url: common.k8sConfigMapList,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    filter_name: '',
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                    page: '',
 | 
					 | 
				
			||||||
                    limit: '',
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            configMapDetail: {},
 | 
					 | 
				
			||||||
            getConfigMapDetailData: {
 | 
					 | 
				
			||||||
                url: common.k8sConfigMapDetail,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    configmap_name: '',
 | 
					 | 
				
			||||||
                    namespace: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            yamlDialog: false,
 | 
					 | 
				
			||||||
            updateConfigMapData: {
 | 
					 | 
				
			||||||
                url: common.k8sConfigMapUpdate,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                    content: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            delConfigMapData: {
 | 
					 | 
				
			||||||
                url: common.k8sconfigmapDel,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    configmap_name: '',
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    methods: {
 | 
					 | 
				
			||||||
        transYaml(content) {
 | 
					 | 
				
			||||||
            return json2yaml.stringify(content)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        transObj(content) {
 | 
					 | 
				
			||||||
            return yaml2obj.load(content)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        onChange(val) {
 | 
					 | 
				
			||||||
            this.contentYaml = val
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleSizeChange(size) {
 | 
					 | 
				
			||||||
            this.pagesize = size;
 | 
					 | 
				
			||||||
            this.getConfigMaps()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleCurrentChange(currentPage) {
 | 
					 | 
				
			||||||
            this.currentPage = currentPage;
 | 
					 | 
				
			||||||
            this.getConfigMaps()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleClose(done) {
 | 
					 | 
				
			||||||
            this.$confirm('确认关闭?')
 | 
					 | 
				
			||||||
            .then(() => {
 | 
					 | 
				
			||||||
                done();
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(() => {});
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        ellipsis(value) {
 | 
					 | 
				
			||||||
            return value.length>15?value.substring(0,15)+'...':value
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        timeTrans(timestamp) {
 | 
					 | 
				
			||||||
            let date = new Date(new Date(timestamp).getTime() + 8 * 3600 * 1000)
 | 
					 | 
				
			||||||
            date = date.toJSON();
 | 
					 | 
				
			||||||
            date = date.substring(0, 19).replace('T', ' ')
 | 
					 | 
				
			||||||
            return date 
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        restartTotal(e) {
 | 
					 | 
				
			||||||
            let index, sum = 0
 | 
					 | 
				
			||||||
            let containerStatuses = e.row.status.containerStatuses
 | 
					 | 
				
			||||||
            for ( index in containerStatuses) {
 | 
					 | 
				
			||||||
                sum = sum + containerStatuses[index].restartCount 
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return sum
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getNamespaces() {
 | 
					 | 
				
			||||||
            httpClient.get(this.namespaceListUrl)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.namespaceList = res.data.items
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getConfigMaps() {
 | 
					 | 
				
			||||||
            this.appLoading = true
 | 
					 | 
				
			||||||
            this.getConfigMapsData.params.filter_name = this.searchInput
 | 
					 | 
				
			||||||
            this.getConfigMapsData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            this.getConfigMapsData.params.page = this.currentPage
 | 
					 | 
				
			||||||
            this.getConfigMapsData.params.limit = this.pagesize
 | 
					 | 
				
			||||||
            httpClient.get(this.getConfigMapsData.url, {params: this.getConfigMapsData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.configMapList = res.data.items
 | 
					 | 
				
			||||||
                this.configMapTotal = res.data.total
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.appLoading = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getConfigMapDetail(e) {
 | 
					 | 
				
			||||||
            this.getConfigMapDetailData.params.configmap_name = e.row.metadata.name
 | 
					 | 
				
			||||||
            this.getConfigMapDetailData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            httpClient.get(this.getConfigMapDetailData.url, {params: this.getConfigMapDetailData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.configMapDetail = res.data
 | 
					 | 
				
			||||||
                this.contentYaml = this.transYaml(this.configMapDetail)
 | 
					 | 
				
			||||||
                this.yamlDialog = true
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        updateConfigMap() {
 | 
					 | 
				
			||||||
            let content = JSON.stringify(this.transObj(this.contentYaml))
 | 
					 | 
				
			||||||
            this.updateConfigMapData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            this.updateConfigMapData.params.content = content
 | 
					 | 
				
			||||||
            httpClient.put(this.updateConfigMapData.url, this.updateConfigMapData.params)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.yamlDialog = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        delConfigMap(e) {
 | 
					 | 
				
			||||||
            this.delConfigMapData.params.configmap_name = e.row.metadata.name
 | 
					 | 
				
			||||||
            this.delConfigMapData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            httpClient.delete(this.delConfigMapData.url, {data: this.delConfigMapData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.getConfigMaps()
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleConfirm(obj, operateName, fn) {
 | 
					 | 
				
			||||||
            this.confirmContent = '确认继续 ' + operateName + ' 操作吗?'
 | 
					 | 
				
			||||||
            this.$confirm(this.confirmContent,'提示',{
 | 
					 | 
				
			||||||
                confirmButtonText: '确定',
 | 
					 | 
				
			||||||
                cancelButtonText: '取消',
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .then(() => {
 | 
					 | 
				
			||||||
                fn(obj)
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            .catch(() => {
 | 
					 | 
				
			||||||
                this.$message.info({
 | 
					 | 
				
			||||||
                    message: '已取消操作'
 | 
					 | 
				
			||||||
                })          
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    watch: {
 | 
					 | 
				
			||||||
        namespaceValue: {
 | 
					 | 
				
			||||||
            handler() {
 | 
					 | 
				
			||||||
                localStorage.setItem('namespace', this.namespaceValue)
 | 
					 | 
				
			||||||
                this.currentPage = 1
 | 
					 | 
				
			||||||
                this.getConfigMaps()
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    beforeMount() {
 | 
					 | 
				
			||||||
        if (localStorage.getItem('namespace') !== undefined && localStorage.getItem('namespace') !== null) {
 | 
					 | 
				
			||||||
            this.namespaceValue = localStorage.getItem('namespace')
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        this.getNamespaces()
 | 
					 | 
				
			||||||
        this.getConfigMaps()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style scoped>
 | 
					 | 
				
			||||||
    .configmap-head-card,.configmap-body-card {
 | 
					 | 
				
			||||||
        border-radius: 1px;
 | 
					 | 
				
			||||||
        margin-bottom: 5px;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .configmap-head-search {
 | 
					 | 
				
			||||||
        width:160px;
 | 
					 | 
				
			||||||
        margin-right:10px; 
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .configmap-body-configmapname {
 | 
					 | 
				
			||||||
        color: #4795EE;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .configmap-body-configmapname:hover {
 | 
					 | 
				
			||||||
        color: rgb(84, 138, 238);
 | 
					 | 
				
			||||||
        cursor: pointer;
 | 
					 | 
				
			||||||
        font-weight: bold;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
@ -1,369 +0,0 @@
 | 
				
			|||||||
<template>
 | 
					 | 
				
			||||||
    <div class="daemonset">
 | 
					 | 
				
			||||||
        <el-row>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="daemonset-head-card" shadow="never" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                        <el-row>
 | 
					 | 
				
			||||||
                            <el-col :span="6">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <span>命名空间: </span>
 | 
					 | 
				
			||||||
                                    <el-select v-model="namespaceValue" filterable placeholder="请选择">
 | 
					 | 
				
			||||||
                                        <el-option
 | 
					 | 
				
			||||||
                                        v-for="(item, index) in namespaceList"
 | 
					 | 
				
			||||||
                                        :key="index"
 | 
					 | 
				
			||||||
                                        :label="item.metadata.name"
 | 
					 | 
				
			||||||
                                        :value="item.metadata.name">
 | 
					 | 
				
			||||||
                                        </el-option>
 | 
					 | 
				
			||||||
                                    </el-select>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                            <el-col :span="2" :offset="16">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Refresh" plain @click="getDaemonSets()">刷新</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                        </el-row>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="daemonset-head-card" shadow="never" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                        <el-row>
 | 
					 | 
				
			||||||
                            <el-col :span="2">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-button disabled style="border-radius:2px;" icon="Edit" type="primary">创建</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                            <el-col :span="6">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-input class="daemonset-head-search" clearable placeholder="请输入" v-model="searchInput"></el-input>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Search" type="primary" plain @click="getDaemonSets()">搜索</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                        </el-row>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="daemonset-body-card" shadow="never" :body-style="{padding:'5px'}">
 | 
					 | 
				
			||||||
                        <el-table
 | 
					 | 
				
			||||||
                        style="width:100%;font-size:12px;margin-bottom:10px;"
 | 
					 | 
				
			||||||
                        :data="daemonSetList"
 | 
					 | 
				
			||||||
                        v-loading="appLoading">
 | 
					 | 
				
			||||||
                            <el-table-column width="20"></el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=left label="DaemonSet名">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <a class="daemonset-body-daemonsetname">{{ scope.row.metadata.name }}</a>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="标签">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <div v-for="(val, key) in scope.row.metadata.labels" :key="key">
 | 
					 | 
				
			||||||
                                        <el-popover
 | 
					 | 
				
			||||||
                                            placement="right"
 | 
					 | 
				
			||||||
                                            :width="200"
 | 
					 | 
				
			||||||
                                            trigger="hover"
 | 
					 | 
				
			||||||
                                            :content="key + ':' + val">
 | 
					 | 
				
			||||||
                                            <template #reference>
 | 
					 | 
				
			||||||
                                                <el-tag style="margin-bottom: 5px" type="warning">{{ ellipsis(key + ":" + val) }}</el-tag>
 | 
					 | 
				
			||||||
                                            </template>
 | 
					 | 
				
			||||||
                                        </el-popover>
 | 
					 | 
				
			||||||
                                    </div>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="容器组">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <span>{{ scope.row.status.numberAvailable>0?scope.row.status.numberAvailable:0  }} / {{ scope.row.status.desiredNumberScheduled>0?scope.row.status.desiredNumberScheduled:0 }} </span>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center min-width="100" label="创建时间">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-tag type="info">{{ timeTrans(scope.row.metadata.creationTimestamp) }} </el-tag>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="镜像">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <div v-for="(val, key) in scope.row.spec.template.spec.containers" :key="key">
 | 
					 | 
				
			||||||
                                        <el-popover
 | 
					 | 
				
			||||||
                                            placement="right"
 | 
					 | 
				
			||||||
                                            :width="200"
 | 
					 | 
				
			||||||
                                            trigger="hover"
 | 
					 | 
				
			||||||
                                            :content="val.image">
 | 
					 | 
				
			||||||
                                            <template #reference>
 | 
					 | 
				
			||||||
                                                <el-tag style="margin-bottom: 5px">{{ ellipsis(val.image.split('/')[2]==undefined?val.image:val.image.split('/')[2]) }}</el-tag>
 | 
					 | 
				
			||||||
                                            </template>
 | 
					 | 
				
			||||||
                                        </el-popover>
 | 
					 | 
				
			||||||
                                    </div>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="操作" width="200">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-button size="small" style="border-radius:2px;" icon="Edit" type="primary" plain @click="getDaemonSetDetail(scope)">YAML</el-button>
 | 
					 | 
				
			||||||
                                    <el-button size="small" style="border-radius:2px;" icon="Delete" type="danger" @click="handleConfirm(scope, '删除', delDaemonSet)">删除</el-button>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                        </el-table>
 | 
					 | 
				
			||||||
                        <el-pagination
 | 
					 | 
				
			||||||
                        class="daemonset-body-pagination"
 | 
					 | 
				
			||||||
                        background
 | 
					 | 
				
			||||||
                        @size-change="handleSizeChange"
 | 
					 | 
				
			||||||
                        @current-change="handleCurrentChange"
 | 
					 | 
				
			||||||
                        :current-page="currentPage"
 | 
					 | 
				
			||||||
                        :page-sizes="pagesizeList"
 | 
					 | 
				
			||||||
                        :page-size="pagesize"
 | 
					 | 
				
			||||||
                        layout="total, sizes, prev, pager, next, jumper"
 | 
					 | 
				
			||||||
                        :total="daemonSetTotal">
 | 
					 | 
				
			||||||
                        </el-pagination>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
        </el-row>
 | 
					 | 
				
			||||||
        <el-dialog title="YAML信息" v-model="yamlDialog" width="45%" top="5%">
 | 
					 | 
				
			||||||
            <codemirror
 | 
					 | 
				
			||||||
                :value="contentYaml"
 | 
					 | 
				
			||||||
                border
 | 
					 | 
				
			||||||
                :options="cmOptions"
 | 
					 | 
				
			||||||
                height="500"
 | 
					 | 
				
			||||||
                style="font-size:14px;"
 | 
					 | 
				
			||||||
                @change="onChange"
 | 
					 | 
				
			||||||
            ></codemirror>
 | 
					 | 
				
			||||||
            <template #footer>
 | 
					 | 
				
			||||||
                <span class="dialog-footer">
 | 
					 | 
				
			||||||
                    <el-button @click="yamlDialog = false">取 消</el-button>
 | 
					 | 
				
			||||||
                    <el-button type="primary" @click="updateDaemonSet()">更 新</el-button>
 | 
					 | 
				
			||||||
                </span>
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
        </el-dialog>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script>
 | 
					 | 
				
			||||||
import common from "../common/Config";
 | 
					 | 
				
			||||||
import httpClient from '../../utils/request';
 | 
					 | 
				
			||||||
import yaml2obj from 'js-yaml';
 | 
					 | 
				
			||||||
import json2yaml from 'json2yaml';
 | 
					 | 
				
			||||||
export default {
 | 
					 | 
				
			||||||
    data() {
 | 
					 | 
				
			||||||
        return {
 | 
					 | 
				
			||||||
            cmOptions: common.cmOptions,
 | 
					 | 
				
			||||||
            contentYaml: '',
 | 
					 | 
				
			||||||
            currentPage: 1,
 | 
					 | 
				
			||||||
            pagesize: 10,
 | 
					 | 
				
			||||||
            pagesizeList: [10, 20, 30],
 | 
					 | 
				
			||||||
            searchInput: '',
 | 
					 | 
				
			||||||
            namespaceValue: 'default',
 | 
					 | 
				
			||||||
            namespaceList: [],
 | 
					 | 
				
			||||||
            namespaceListUrl: common.k8sNamespaceList,
 | 
					 | 
				
			||||||
            appLoading: false,
 | 
					 | 
				
			||||||
            daemonSetList: [],
 | 
					 | 
				
			||||||
            daemonSetTotal: 0,
 | 
					 | 
				
			||||||
            getDaemonSetsData: {
 | 
					 | 
				
			||||||
                url: common.k8sDaemonSetList,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    filter_name: '',
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                    page: '',
 | 
					 | 
				
			||||||
                    limit: '',
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            daemonSetDetail: {},
 | 
					 | 
				
			||||||
            getDaemonSetDetailData: {
 | 
					 | 
				
			||||||
                url: common.k8sDaemonSetDetail,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    daemonset_name: '',
 | 
					 | 
				
			||||||
                    namespace: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            yamlDialog: false,
 | 
					 | 
				
			||||||
            updateDaemonSetData: {
 | 
					 | 
				
			||||||
                url: common.k8sDaemonSetUpdate,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                    content: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            delDaemonSetData: {
 | 
					 | 
				
			||||||
                url: common.k8sdaemonsetDel,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    daemonset_name: '',
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    methods: {
 | 
					 | 
				
			||||||
        transYaml(content) {
 | 
					 | 
				
			||||||
            return json2yaml.stringify(content)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        transObj(content) {
 | 
					 | 
				
			||||||
            return yaml2obj.load(content)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        onChange(val) {
 | 
					 | 
				
			||||||
            this.contentYaml = val
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleSizeChange(size) {
 | 
					 | 
				
			||||||
            this.pagesize = size;
 | 
					 | 
				
			||||||
            this.getDaemonSets()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleCurrentChange(currentPage) {
 | 
					 | 
				
			||||||
            this.currentPage = currentPage;
 | 
					 | 
				
			||||||
            this.getDaemonSets()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleClose(done) {
 | 
					 | 
				
			||||||
            this.$confirm('确认关闭?')
 | 
					 | 
				
			||||||
            .then(() => {
 | 
					 | 
				
			||||||
                done();
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(() => {});
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        ellipsis(value) {
 | 
					 | 
				
			||||||
            return value.length>15?value.substring(0,15)+'...':value
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        timeTrans(timestamp) {
 | 
					 | 
				
			||||||
            let date = new Date(new Date(timestamp).getTime() + 8 * 3600 * 1000)
 | 
					 | 
				
			||||||
            date = date.toJSON();
 | 
					 | 
				
			||||||
            date = date.substring(0, 19).replace('T', ' ')
 | 
					 | 
				
			||||||
            return date 
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        restartTotal(e) {
 | 
					 | 
				
			||||||
            let index, sum = 0
 | 
					 | 
				
			||||||
            let containerStatuses = e.row.status.containerStatuses
 | 
					 | 
				
			||||||
            for ( index in containerStatuses) {
 | 
					 | 
				
			||||||
                sum = sum + containerStatuses[index].restartCount 
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return sum
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getNamespaces() {
 | 
					 | 
				
			||||||
            httpClient.get(this.namespaceListUrl)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.namespaceList = res.data.items
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getDaemonSets() {
 | 
					 | 
				
			||||||
            this.appLoading = true
 | 
					 | 
				
			||||||
            this.getDaemonSetsData.params.filter_name = this.searchInput
 | 
					 | 
				
			||||||
            this.getDaemonSetsData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            this.getDaemonSetsData.params.page = this.currentPage
 | 
					 | 
				
			||||||
            this.getDaemonSetsData.params.limit = this.pagesize
 | 
					 | 
				
			||||||
            httpClient.get(this.getDaemonSetsData.url, {params: this.getDaemonSetsData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.daemonSetList = res.data.items
 | 
					 | 
				
			||||||
                this.daemonSetTotal = res.data.total
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.appLoading = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getDaemonSetDetail(e) {
 | 
					 | 
				
			||||||
            this.getDaemonSetDetailData.params.daemonset_name = e.row.metadata.name
 | 
					 | 
				
			||||||
            this.getDaemonSetDetailData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            httpClient.get(this.getDaemonSetDetailData.url, {params: this.getDaemonSetDetailData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.daemonSetDetail = res.data
 | 
					 | 
				
			||||||
                this.contentYaml = this.transYaml(this.daemonSetDetail)
 | 
					 | 
				
			||||||
                this.yamlDialog = true
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        updateDaemonSet() {
 | 
					 | 
				
			||||||
            let content = JSON.stringify(this.transObj(this.contentYaml))
 | 
					 | 
				
			||||||
            this.updateDaemonSetData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            this.updateDaemonSetData.params.content = content
 | 
					 | 
				
			||||||
            httpClient.put(this.updateDaemonSetData.url, this.updateDaemonSetData.params)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.yamlDialog = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        delDaemonSet(e) {
 | 
					 | 
				
			||||||
            this.delDaemonSetData.params.daemonset_name = e.row.metadata.name
 | 
					 | 
				
			||||||
            this.delDaemonSetData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            httpClient.delete(this.delDaemonSetData.url, {data: this.delDaemonSetData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.getDaemonSets()
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleConfirm(obj, operateName, fn) {
 | 
					 | 
				
			||||||
            this.confirmContent = '确认继续 ' + operateName + ' 操作吗?'
 | 
					 | 
				
			||||||
            this.$confirm(this.confirmContent,'提示',{
 | 
					 | 
				
			||||||
                confirmButtonText: '确定',
 | 
					 | 
				
			||||||
                cancelButtonText: '取消',
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .then(() => {
 | 
					 | 
				
			||||||
                fn(obj)
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            .catch(() => {
 | 
					 | 
				
			||||||
                this.$message.info({
 | 
					 | 
				
			||||||
                    message: '已取消操作'
 | 
					 | 
				
			||||||
                })          
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    watch: {
 | 
					 | 
				
			||||||
        namespaceValue: {
 | 
					 | 
				
			||||||
            handler() {
 | 
					 | 
				
			||||||
                localStorage.setItem('namespace', this.namespaceValue)
 | 
					 | 
				
			||||||
                this.currentPage = 1
 | 
					 | 
				
			||||||
                this.getDaemonSets()
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    beforeMount() {
 | 
					 | 
				
			||||||
        if (localStorage.getItem('namespace') !== undefined && localStorage.getItem('namespace') !== null) {
 | 
					 | 
				
			||||||
            this.namespaceValue = localStorage.getItem('namespace')
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        this.getNamespaces()
 | 
					 | 
				
			||||||
        this.getDaemonSets()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style scoped>
 | 
					 | 
				
			||||||
    .daemonset-head-card,.daemonset-body-card {
 | 
					 | 
				
			||||||
        border-radius: 1px;
 | 
					 | 
				
			||||||
        margin-bottom: 5px;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .daemonset-head-search {
 | 
					 | 
				
			||||||
        width:160px;
 | 
					 | 
				
			||||||
        margin-right:10px; 
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .daemonset-body-daemonsetname {
 | 
					 | 
				
			||||||
        color: #4795EE;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .daemonset-body-daemonsetname:hover {
 | 
					 | 
				
			||||||
        color: rgb(84, 138, 238);
 | 
					 | 
				
			||||||
        cursor: pointer;
 | 
					 | 
				
			||||||
        font-weight: bold;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
@ -1,611 +0,0 @@
 | 
				
			|||||||
<template>
 | 
					 | 
				
			||||||
    <div class="deploy">
 | 
					 | 
				
			||||||
        <el-row>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="deploy-head-card" shadow="never" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                        <el-row>
 | 
					 | 
				
			||||||
                            <el-col :span="6">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <span>命名空间: </span>
 | 
					 | 
				
			||||||
                                    <el-select v-model="namespaceValue" filterable placeholder="请选择">
 | 
					 | 
				
			||||||
                                        <el-option
 | 
					 | 
				
			||||||
                                        v-for="(item, index) in namespaceList"
 | 
					 | 
				
			||||||
                                        :key="index"
 | 
					 | 
				
			||||||
                                        :label="item.metadata.name"
 | 
					 | 
				
			||||||
                                        :value="item.metadata.name">
 | 
					 | 
				
			||||||
                                        </el-option>
 | 
					 | 
				
			||||||
                                    </el-select>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                            <el-col :span="2" :offset="16">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Refresh" plain @click="getDeployments()">刷新</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                        </el-row>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="deploy-head-card" shadow="never" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                        <el-row>
 | 
					 | 
				
			||||||
                            <el-col :span="2">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Edit" type="primary" @click="createDeploymentDrawer = true" v-loading.fullscreen.lock="fullscreenLoading">创建</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                            <el-col :span="6">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-input class="deploy-head-search" clearable placeholder="请输入" v-model="searchInput"></el-input>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Search" type="primary" plain @click="getDeployments()">搜索</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                        </el-row>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="deploy-body-card" shadow="never" :body-style="{padding:'5px'}">
 | 
					 | 
				
			||||||
                        <el-table
 | 
					 | 
				
			||||||
                        style="width:100%;font-size:12px;margin-bottom:10px;"
 | 
					 | 
				
			||||||
                        :data="deploymentList"
 | 
					 | 
				
			||||||
                        v-loading="appLoading">
 | 
					 | 
				
			||||||
                            <el-table-column width="20"></el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=left label="Deployment名">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <a class="deploy-body-deployname">{{ scope.row.metadata.name }}</a>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="标签">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <div v-for="(val, key) in scope.row.metadata.labels" :key="key">
 | 
					 | 
				
			||||||
                                        <el-popover
 | 
					 | 
				
			||||||
                                            placement="right"
 | 
					 | 
				
			||||||
                                            :width="200"
 | 
					 | 
				
			||||||
                                            trigger="hover"
 | 
					 | 
				
			||||||
                                            :content="key + ':' + val">
 | 
					 | 
				
			||||||
                                            <template #reference>
 | 
					 | 
				
			||||||
                                                <el-tag style="margin-bottom: 5px" type="warning">{{ ellipsis(key + ":" + val) }}</el-tag>
 | 
					 | 
				
			||||||
                                            </template>
 | 
					 | 
				
			||||||
                                        </el-popover>
 | 
					 | 
				
			||||||
                                    </div>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="容器组">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <span>{{ scope.row.status.availableReplicas>0?scope.row.status.availableReplicas:0  }} / {{ scope.row.spec.replicas>0?scope.row.spec.replicas:0 }} </span>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center min-width="100" label="创建时间">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-tag type="info">{{ timeTrans(scope.row.metadata.creationTimestamp) }} </el-tag>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="镜像">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <div v-for="(val, key) in scope.row.spec.template.spec.containers" :key="key">
 | 
					 | 
				
			||||||
                                        <el-popover
 | 
					 | 
				
			||||||
                                            placement="right"
 | 
					 | 
				
			||||||
                                            :width="200"
 | 
					 | 
				
			||||||
                                            trigger="hover"
 | 
					 | 
				
			||||||
                                            :content="val.image">
 | 
					 | 
				
			||||||
                                            <template #reference>
 | 
					 | 
				
			||||||
                                                <el-tag style="margin-bottom: 5px">{{ ellipsis(val.image.split('/')[2]==undefined?val.image:val.image.split('/')[2]) }}</el-tag>
 | 
					 | 
				
			||||||
                                            </template>
 | 
					 | 
				
			||||||
                                        </el-popover>
 | 
					 | 
				
			||||||
                                    </div>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="操作" width="400">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-button size="small" style="border-radius:2px;" icon="Edit" type="primary" plain @click="getDeploymentDetail(scope)">YAML</el-button>
 | 
					 | 
				
			||||||
                                    <el-button size="small" style="border-radius:2px;" icon="Plus" type="primary" @click="handleScale(scope)">扩缩</el-button>
 | 
					 | 
				
			||||||
                                    <el-button size="small" style="border-radius:2px;" icon="RefreshLeft" type="primary" @click="handleConfirm(scope, '重启', restartDeployment)">重启</el-button>
 | 
					 | 
				
			||||||
                                    <el-button size="small" style="border-radius:2px;" icon="Delete" type="danger" @click="handleConfirm(scope, '删除', delDeployment)">删除</el-button>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                        </el-table>
 | 
					 | 
				
			||||||
                        <el-pagination
 | 
					 | 
				
			||||||
                        class="deploy-body-pagination"
 | 
					 | 
				
			||||||
                        background
 | 
					 | 
				
			||||||
                        @size-change="handleSizeChange"
 | 
					 | 
				
			||||||
                        @current-change="handleCurrentChange"
 | 
					 | 
				
			||||||
                        :current-page="currentPage"
 | 
					 | 
				
			||||||
                        :page-sizes="pagesizeList"
 | 
					 | 
				
			||||||
                        :page-size="pagesize"
 | 
					 | 
				
			||||||
                        layout="total, sizes, prev, pager, next, jumper"
 | 
					 | 
				
			||||||
                        :total="deploymentTotal">
 | 
					 | 
				
			||||||
                        </el-pagination>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
        </el-row>
 | 
					 | 
				
			||||||
        <el-drawer
 | 
					 | 
				
			||||||
            v-model="createDeploymentDrawer"
 | 
					 | 
				
			||||||
            :direction="direction"
 | 
					 | 
				
			||||||
            :before-close="handleClose">
 | 
					 | 
				
			||||||
            <template #title>
 | 
					 | 
				
			||||||
                <h4>创建Deployment</h4>
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
            <template #default>
 | 
					 | 
				
			||||||
                <el-row type="flex" justify="center">
 | 
					 | 
				
			||||||
                    <el-col :span="20">
 | 
					 | 
				
			||||||
                        <el-form ref="createDeployment" :rules="createDeploymentRules" :model="createDeployment" label-width="80px">
 | 
					 | 
				
			||||||
                            <el-form-item class="deploy-create-form" label="名称" prop="name">
 | 
					 | 
				
			||||||
                                <el-input v-model="createDeployment.name"></el-input>
 | 
					 | 
				
			||||||
                            </el-form-item>
 | 
					 | 
				
			||||||
                            <el-form-item class="deploy-create-form" label="命名空间" prop="namespace">
 | 
					 | 
				
			||||||
                                <el-select v-model="createDeployment.namespace" filterable placeholder="请选择">
 | 
					 | 
				
			||||||
                                    <el-option
 | 
					 | 
				
			||||||
                                    v-for="(item, index) in namespaceList"
 | 
					 | 
				
			||||||
                                    :key="index"
 | 
					 | 
				
			||||||
                                    :label="item.metadata.name"
 | 
					 | 
				
			||||||
                                    :value="item.metadata.name">
 | 
					 | 
				
			||||||
                                    </el-option>
 | 
					 | 
				
			||||||
                                </el-select>
 | 
					 | 
				
			||||||
                            </el-form-item>
 | 
					 | 
				
			||||||
                            <el-form-item class="deploy-create-form" label="副本数" prop="replicas">
 | 
					 | 
				
			||||||
                                <el-input-number v-model="createDeployment.replicas" :min="1" :max="10"></el-input-number>
 | 
					 | 
				
			||||||
                                    <el-popover
 | 
					 | 
				
			||||||
                                        placement="top"
 | 
					 | 
				
			||||||
                                        :width="100"
 | 
					 | 
				
			||||||
                                        trigger="hover"
 | 
					 | 
				
			||||||
                                        content="申请副本数上限为10个">
 | 
					 | 
				
			||||||
                                        <template #reference>
 | 
					 | 
				
			||||||
                                            <el-icon style="width:2em;font-size:18px;color:#4795EE"><WarningFilled/></el-icon>
 | 
					 | 
				
			||||||
                                        </template>
 | 
					 | 
				
			||||||
                                    </el-popover>
 | 
					 | 
				
			||||||
                            </el-form-item>
 | 
					 | 
				
			||||||
                            <el-form-item class="deploy-create-form" label="镜像" prop="image">
 | 
					 | 
				
			||||||
                                <el-input v-model="createDeployment.image"></el-input>
 | 
					 | 
				
			||||||
                            </el-form-item>
 | 
					 | 
				
			||||||
                            <el-form-item class="deploy-create-form" label="标签" prop="label_str">
 | 
					 | 
				
			||||||
                                <el-input v-model="createDeployment.label_str" placeholder="示例: project=ms,app=gateway"></el-input>
 | 
					 | 
				
			||||||
                            </el-form-item>
 | 
					 | 
				
			||||||
                            <el-form-item class="deploy-create-form" label="资源配额" prop="resource">
 | 
					 | 
				
			||||||
                                <el-select v-model="createDeployment.resource" placeholder="请选择">
 | 
					 | 
				
			||||||
                                    <el-option value="0.5/1" label="0.5C1G"></el-option>
 | 
					 | 
				
			||||||
                                    <el-option value="1/2" label="1C2G"></el-option>
 | 
					 | 
				
			||||||
                                    <el-option value="2/4" label="2C4G"></el-option>
 | 
					 | 
				
			||||||
                                    <el-option value="4/8" label="4C8G"></el-option>
 | 
					 | 
				
			||||||
                                </el-select>
 | 
					 | 
				
			||||||
                            </el-form-item>
 | 
					 | 
				
			||||||
                            <el-form-item class="deploy-create-form" label="容器端口" prop="container_port">
 | 
					 | 
				
			||||||
                                <el-input v-model="createDeployment.container_port" placeholder="示例: 80"></el-input>
 | 
					 | 
				
			||||||
                            </el-form-item>
 | 
					 | 
				
			||||||
                            <el-form-item class="deploy-create-form" label="健康检查" prop="health">
 | 
					 | 
				
			||||||
                                <el-switch v-model="createDeployment.health_check" />
 | 
					 | 
				
			||||||
                            </el-form-item>
 | 
					 | 
				
			||||||
                            <el-form-item class="deploy-create-form" label="检查路径" prop="healthPath">
 | 
					 | 
				
			||||||
                                <el-input v-model="createDeployment.health_path" placeholder="示例: /health"></el-input>
 | 
					 | 
				
			||||||
                            </el-form-item>
 | 
					 | 
				
			||||||
                        </el-form>
 | 
					 | 
				
			||||||
                    </el-col>
 | 
					 | 
				
			||||||
                </el-row>
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
            <template #footer>
 | 
					 | 
				
			||||||
                <el-button @click="createDeploymentDrawer = false">取消</el-button>
 | 
					 | 
				
			||||||
                <el-button type="primary" @click="submitForm('createDeployment')">立即创建</el-button>
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
        </el-drawer>
 | 
					 | 
				
			||||||
        <el-dialog title="YAML信息" v-model="yamlDialog" width="45%" top="2%">
 | 
					 | 
				
			||||||
            <codemirror
 | 
					 | 
				
			||||||
                :value="contentYaml"
 | 
					 | 
				
			||||||
                border
 | 
					 | 
				
			||||||
                :options="cmOptions"
 | 
					 | 
				
			||||||
                height="500"
 | 
					 | 
				
			||||||
                style="font-size:14px;"
 | 
					 | 
				
			||||||
                @change="onChange"
 | 
					 | 
				
			||||||
            ></codemirror>
 | 
					 | 
				
			||||||
            <template #footer>
 | 
					 | 
				
			||||||
                <span class="dialog-footer">
 | 
					 | 
				
			||||||
                    <el-button @click="this.yamlDialog = false">取 消</el-button>
 | 
					 | 
				
			||||||
                    <el-button type="primary" @click="updateDeployment()">更 新</el-button>
 | 
					 | 
				
			||||||
                </span>
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
        </el-dialog>
 | 
					 | 
				
			||||||
        <el-dialog title="副本数调整" v-model="scaleDialog" width="25%">
 | 
					 | 
				
			||||||
            <div style="text-align:center">
 | 
					 | 
				
			||||||
                <span>实例数: </span>
 | 
					 | 
				
			||||||
                <el-input-number :step="1" v-model="scaleNum" :min="0" :max="30" label="描述文字"></el-input-number>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
            <template #footer>
 | 
					 | 
				
			||||||
                <span class="dialog-footer">
 | 
					 | 
				
			||||||
                    <el-button @click="scaleDialog = false">取 消</el-button>
 | 
					 | 
				
			||||||
                    <el-button type="primary" @click="scaleDeployment()">更 新</el-button>
 | 
					 | 
				
			||||||
                </span>
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
        </el-dialog>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script>
 | 
					 | 
				
			||||||
import common from "../common/Config";
 | 
					 | 
				
			||||||
import httpClient from '../../utils/request';
 | 
					 | 
				
			||||||
import yaml2obj from 'js-yaml';
 | 
					 | 
				
			||||||
import json2yaml from 'json2yaml';
 | 
					 | 
				
			||||||
export default {
 | 
					 | 
				
			||||||
    data() {
 | 
					 | 
				
			||||||
        return {
 | 
					 | 
				
			||||||
            cmOptions: common.cmOptions,
 | 
					 | 
				
			||||||
            contentYaml: '',
 | 
					 | 
				
			||||||
            currentPage: 1,
 | 
					 | 
				
			||||||
            pagesize: 10,
 | 
					 | 
				
			||||||
            pagesizeList: [10, 20, 30],
 | 
					 | 
				
			||||||
            searchInput: '',
 | 
					 | 
				
			||||||
            namespaceValue: 'default',
 | 
					 | 
				
			||||||
            namespaceList: [],
 | 
					 | 
				
			||||||
            namespaceListUrl: common.k8sNamespaceList,
 | 
					 | 
				
			||||||
            appLoading: false,
 | 
					 | 
				
			||||||
            deploymentList: [],
 | 
					 | 
				
			||||||
            deploymentTotal: 0,
 | 
					 | 
				
			||||||
            getDeploymentsData: {
 | 
					 | 
				
			||||||
                url: common.k8sDeploymentList,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    filter_name: '',
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                    page: '',
 | 
					 | 
				
			||||||
                    limit: '',
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            fullscreenLoading: false,
 | 
					 | 
				
			||||||
            direction: 'rtl',
 | 
					 | 
				
			||||||
            createDeploymentDrawer: false,
 | 
					 | 
				
			||||||
            createDeployment: {
 | 
					 | 
				
			||||||
                name: '',
 | 
					 | 
				
			||||||
                namespace: '',
 | 
					 | 
				
			||||||
                replicas: 1,
 | 
					 | 
				
			||||||
                image: '',
 | 
					 | 
				
			||||||
                resource: '',
 | 
					 | 
				
			||||||
                health_check: false,
 | 
					 | 
				
			||||||
                health_path: '',
 | 
					 | 
				
			||||||
                label_str: '',
 | 
					 | 
				
			||||||
                label: {},
 | 
					 | 
				
			||||||
                container_port: ''
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            createDeploymentData: {
 | 
					 | 
				
			||||||
                url: common.k8sDeploymentCreate,
 | 
					 | 
				
			||||||
                params: {}
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            createDeploymentRules: {
 | 
					 | 
				
			||||||
                name: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请填写名称',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                image: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请填写镜像',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                namespace: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请选择命名空间',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                resource: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请选择配额',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                label_str: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请填写标签',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                container_port: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请填写容器端口',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            deploymentDetail: {},
 | 
					 | 
				
			||||||
            getDeploymentDetailData: {
 | 
					 | 
				
			||||||
                url: common.k8sDeploymentDetail,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    deployment_name: '',
 | 
					 | 
				
			||||||
                    namespace: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            yamlDialog: false,
 | 
					 | 
				
			||||||
            updateDeploymentData: {
 | 
					 | 
				
			||||||
                url: common.k8sDeploymentUpdate,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                    content: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            scaleNum: 0,
 | 
					 | 
				
			||||||
            scaleDialog: false,
 | 
					 | 
				
			||||||
            scaleDeploymentData: {
 | 
					 | 
				
			||||||
                url: common.k8sDeploymentScale,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    deployment_name: '',
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                    scale_num: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            restartDeploymentData: {
 | 
					 | 
				
			||||||
                url: common.k8sDeploymentRestart,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    deployment_name: '',
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            delDeploymentData: {
 | 
					 | 
				
			||||||
                url: common.k8sDeploymentDel,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    deployment_name: '',
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    methods: {
 | 
					 | 
				
			||||||
        transYaml(content) {
 | 
					 | 
				
			||||||
            return json2yaml.stringify(content)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        transObj(content) {
 | 
					 | 
				
			||||||
            return yaml2obj.load(content)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        onChange(val) {
 | 
					 | 
				
			||||||
            this.contentYaml = val
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleSizeChange(size) {
 | 
					 | 
				
			||||||
            this.pagesize = size;
 | 
					 | 
				
			||||||
            this.getDeployments()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleCurrentChange(currentPage) {
 | 
					 | 
				
			||||||
            this.currentPage = currentPage;
 | 
					 | 
				
			||||||
            this.getDeployments()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleClose(done) {
 | 
					 | 
				
			||||||
            this.$confirm('确认关闭?')
 | 
					 | 
				
			||||||
            .then(() => {
 | 
					 | 
				
			||||||
                done();
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(() => {});
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        ellipsis(value) {
 | 
					 | 
				
			||||||
            return value.length>15?value.substring(0,15)+'...':value
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        timeTrans(timestamp) {
 | 
					 | 
				
			||||||
            let date = new Date(new Date(timestamp).getTime() + 8 * 3600 * 1000)
 | 
					 | 
				
			||||||
            date = date.toJSON();
 | 
					 | 
				
			||||||
            date = date.substring(0, 19).replace('T', ' ')
 | 
					 | 
				
			||||||
            return date 
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getNamespaces() {
 | 
					 | 
				
			||||||
            httpClient.get(this.namespaceListUrl)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.namespaceList = res.data.items
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getDeployments() {
 | 
					 | 
				
			||||||
            this.appLoading = true
 | 
					 | 
				
			||||||
            this.getDeploymentsData.params.filter_name = this.searchInput
 | 
					 | 
				
			||||||
            this.getDeploymentsData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            this.getDeploymentsData.params.page = this.currentPage
 | 
					 | 
				
			||||||
            this.getDeploymentsData.params.limit = this.pagesize
 | 
					 | 
				
			||||||
            httpClient.get(this.getDeploymentsData.url, {params: this.getDeploymentsData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.deploymentList = res.data.items
 | 
					 | 
				
			||||||
                this.deploymentTotal = res.data.total
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.appLoading = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getDeploymentDetail(e) {
 | 
					 | 
				
			||||||
            this.getDeploymentDetailData.params.deployment_name = e.row.metadata.name
 | 
					 | 
				
			||||||
            this.getDeploymentDetailData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            httpClient.get(this.getDeploymentDetailData.url, {params: this.getDeploymentDetailData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.deploymentDetail = res.data
 | 
					 | 
				
			||||||
                this.contentYaml = this.transYaml(this.deploymentDetail)
 | 
					 | 
				
			||||||
                this.yamlDialog = true
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        updateDeployment() {
 | 
					 | 
				
			||||||
            let content = JSON.stringify(this.transObj(this.contentYaml))
 | 
					 | 
				
			||||||
            this.updateDeploymentData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            this.updateDeploymentData.params.content = content
 | 
					 | 
				
			||||||
            httpClient.put(this.updateDeploymentData.url, this.updateDeploymentData.params)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
                this.getDeployments()
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.yamlDialog = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        handleScale(e) {
 | 
					 | 
				
			||||||
            this.scaleDialog = true
 | 
					 | 
				
			||||||
            this.deploymentDetail = e.row
 | 
					 | 
				
			||||||
            this.scaleNum = e.row.spec.replicas
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        scaleDeployment() {
 | 
					 | 
				
			||||||
            this.scaleDeploymentData.params.deployment_name = this.deploymentDetail.metadata.name
 | 
					 | 
				
			||||||
            this.scaleDeploymentData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            this.scaleDeploymentData.params.scale_num = this.scaleNum
 | 
					 | 
				
			||||||
            httpClient.put(this.scaleDeploymentData.url, this.scaleDeploymentData.params)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
                this.getDeployments()
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.scaleDialog = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        restartDeployment(e) {
 | 
					 | 
				
			||||||
            this.restartDeploymentData.params.deployment_name = e.row.metadata.name
 | 
					 | 
				
			||||||
            this.restartDeploymentData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            httpClient.put(this.restartDeploymentData.url, this.restartDeploymentData.params)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
                this.getDeployments()
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        delDeployment(e) {
 | 
					 | 
				
			||||||
            this.delDeploymentData.params.deployment_name = e.row.metadata.name
 | 
					 | 
				
			||||||
            this.delDeploymentData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            httpClient.delete(this.delDeploymentData.url, {data: this.delDeploymentData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
                this.getDeployments()
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        handleConfirm(obj, operateName, fn) {
 | 
					 | 
				
			||||||
            this.confirmContent = '确认继续 ' + operateName + ' 操作吗?'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            this.$confirm(this.confirmContent,'提示',{
 | 
					 | 
				
			||||||
                confirmButtonText: '确定',
 | 
					 | 
				
			||||||
                cancelButtonText: '取消',
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .then(() => {
 | 
					 | 
				
			||||||
                fn(obj)
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(() => {
 | 
					 | 
				
			||||||
                this.$message.info({
 | 
					 | 
				
			||||||
                    message: '已取消操作'
 | 
					 | 
				
			||||||
                })          
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        createDeployFunc() {
 | 
					 | 
				
			||||||
            let reg = new RegExp("(^[A-Za-z]+=[A-Za-z0-9]+).*")
 | 
					 | 
				
			||||||
            if (!reg.test(this.createDeployment.label_str)) {
 | 
					 | 
				
			||||||
                this.$message.warning({
 | 
					 | 
				
			||||||
                    message: "标签填写异常,请确认后重新填写"
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
                return
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            this.fullscreenLoading = true
 | 
					 | 
				
			||||||
            let label = new Map()
 | 
					 | 
				
			||||||
            let cpu, memory
 | 
					 | 
				
			||||||
            let a = (this.createDeployment.label_str).split(",")
 | 
					 | 
				
			||||||
            a.forEach(item => {
 | 
					 | 
				
			||||||
                let b = item.split("=")
 | 
					 | 
				
			||||||
                label[b[0]] = b[1]
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            let resourceList = this.createDeployment.resource.split("/")
 | 
					 | 
				
			||||||
            cpu = resourceList[0]
 | 
					 | 
				
			||||||
            memory = resourceList[1] + "Gi"
 | 
					 | 
				
			||||||
            this.createDeploymentData.params = this.createDeployment
 | 
					 | 
				
			||||||
            this.createDeploymentData.params.container_port = parseInt(this.createDeployment.container_port)
 | 
					 | 
				
			||||||
            this.createDeploymentData.params.label = label
 | 
					 | 
				
			||||||
            this.createDeploymentData.params.cpu = cpu
 | 
					 | 
				
			||||||
            this.createDeploymentData.params.memory = memory
 | 
					 | 
				
			||||||
            httpClient.post(this.createDeploymentData.url, this.createDeploymentData.params)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
                this.getDeployments()
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.resetForm('createDeployment')
 | 
					 | 
				
			||||||
            this.fullscreenLoading = false
 | 
					 | 
				
			||||||
            this.createDeploymentDrawer = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        resetForm(formName) {
 | 
					 | 
				
			||||||
            this.$refs[formName].resetFields()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        submitForm(formName) {
 | 
					 | 
				
			||||||
            this.$refs[formName].validate((valid) => {
 | 
					 | 
				
			||||||
                if (valid) {
 | 
					 | 
				
			||||||
                    this.createDeployFunc()
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    return false;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    watch: {
 | 
					 | 
				
			||||||
        namespaceValue: {
 | 
					 | 
				
			||||||
            handler() {
 | 
					 | 
				
			||||||
                localStorage.setItem('namespace', this.namespaceValue)
 | 
					 | 
				
			||||||
                this.currentPage = 1
 | 
					 | 
				
			||||||
                this.getDeployments()
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    beforeMount() {
 | 
					 | 
				
			||||||
        if (localStorage.getItem('namespace') !== undefined && localStorage.getItem('namespace') !== null) {
 | 
					 | 
				
			||||||
            this.namespaceValue = localStorage.getItem('namespace')
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        this.getNamespaces()
 | 
					 | 
				
			||||||
        this.getDeployments()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style scoped>
 | 
					 | 
				
			||||||
    .deploy-head-card,.deploy-body-card {
 | 
					 | 
				
			||||||
        border-radius: 1px;
 | 
					 | 
				
			||||||
        margin-bottom: 5px;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .deploy-head-search {
 | 
					 | 
				
			||||||
        width:160px;
 | 
					 | 
				
			||||||
        margin-right:10px; 
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .deploy-body-deployname {
 | 
					 | 
				
			||||||
        color: #4795EE;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .deploy-body-deployname:hover {
 | 
					 | 
				
			||||||
        color: rgb(84, 138, 238);
 | 
					 | 
				
			||||||
        cursor: pointer;
 | 
					 | 
				
			||||||
        font-weight: bold;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
@ -1,365 +0,0 @@
 | 
				
			|||||||
<template>
 | 
					 | 
				
			||||||
  <div class="home">
 | 
					 | 
				
			||||||
      <el-collapse v-model="activeNames">
 | 
					 | 
				
			||||||
          <el-collapse-item title="集群资源" name="1">
 | 
					 | 
				
			||||||
              <el-row :gutter="10" style="margin-bottom: 10px;">
 | 
					 | 
				
			||||||
                  <el-col :span="5">
 | 
					 | 
				
			||||||
                      <el-card class="home-node-card" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                          <div style="float:left;padding-top:20%">
 | 
					 | 
				
			||||||
                              <el-progress  :stroke-width="20" :show-text="false" type="circle" :percentage="namespaceActive/namespaceTotal * 100"></el-progress>
 | 
					 | 
				
			||||||
                          </div>
 | 
					 | 
				
			||||||
                          <div>
 | 
					 | 
				
			||||||
                              <p class="home-node-card-title">命名空间: Active/总量</p>
 | 
					 | 
				
			||||||
                              <p class="home-node-card-num">{{ namespaceActive }}/{{ namespaceTotal }}</p>
 | 
					 | 
				
			||||||
                          </div>
 | 
					 | 
				
			||||||
                      </el-card>
 | 
					 | 
				
			||||||
                  </el-col>
 | 
					 | 
				
			||||||
                  <el-col :span="5">
 | 
					 | 
				
			||||||
                      <el-card class="home-node-card" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                          <div>
 | 
					 | 
				
			||||||
                              <p class="home-node-card-title">服务数</p>
 | 
					 | 
				
			||||||
                              <p class="home-node-card-num">{{ deploymentTotal }}</p>
 | 
					 | 
				
			||||||
                          </div>
 | 
					 | 
				
			||||||
                      </el-card>
 | 
					 | 
				
			||||||
                  </el-col>
 | 
					 | 
				
			||||||
                  <el-col :span="5">
 | 
					 | 
				
			||||||
                      <el-card class="home-node-card" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                          <div>
 | 
					 | 
				
			||||||
                              <p class="home-node-card-title">实例数</p>
 | 
					 | 
				
			||||||
                              <p class="home-node-card-num">{{ podTotal }}</p>
 | 
					 | 
				
			||||||
                          </div>
 | 
					 | 
				
			||||||
                      </el-card>
 | 
					 | 
				
			||||||
                  </el-col>
 | 
					 | 
				
			||||||
              </el-row>
 | 
					 | 
				
			||||||
          </el-collapse-item>
 | 
					 | 
				
			||||||
          <el-collapse-item title="节点资源" name="2">
 | 
					 | 
				
			||||||
              <el-row :gutter="10" style="margin-bottom: 10px;">
 | 
					 | 
				
			||||||
                  <el-col :span="5">
 | 
					 | 
				
			||||||
                      <el-card class="home-node-card" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                          <div style="float:left;padding-top:20%">
 | 
					 | 
				
			||||||
                              <el-progress :stroke-width="20" :show-text="false" type="circle" :percentage="nodeTotal/nodeTotal * 100"></el-progress>
 | 
					 | 
				
			||||||
                          </div>
 | 
					 | 
				
			||||||
                          <div>
 | 
					 | 
				
			||||||
                              <p class="home-node-card-title">节点: Ready/总数量</p>
 | 
					 | 
				
			||||||
                              <p class="home-node-card-num">{{ nodeTotal }}/{{ nodeTotal }}</p>
 | 
					 | 
				
			||||||
                          </div>
 | 
					 | 
				
			||||||
                      </el-card>
 | 
					 | 
				
			||||||
                  </el-col>
 | 
					 | 
				
			||||||
                  <el-col :span="5">
 | 
					 | 
				
			||||||
                      <el-card class="home-node-card" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                          <div style="float:left;padding-top:20%">
 | 
					 | 
				
			||||||
                              <el-progress :stroke-width="20" :show-text="false" type="circle" :percentage="nodeCpuAllocatable/nodeCpuCapacity * 100"></el-progress>
 | 
					 | 
				
			||||||
                          </div>
 | 
					 | 
				
			||||||
                          <div>
 | 
					 | 
				
			||||||
                              <p class="home-node-card-title">CPU: 可分配/容量</p>
 | 
					 | 
				
			||||||
                              <p class="home-node-card-num">{{ nodeCpuAllocatable }}/{{ nodeCpuCapacity }}</p>
 | 
					 | 
				
			||||||
                          </div>
 | 
					 | 
				
			||||||
                      </el-card>
 | 
					 | 
				
			||||||
                  </el-col>
 | 
					 | 
				
			||||||
                  <el-col :span="5">
 | 
					 | 
				
			||||||
                      <el-card class="home-node-card" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                          <div style="float:left;padding-top:20%">
 | 
					 | 
				
			||||||
                              <el-progress :stroke-width="20" :show-text="false" type="circle" :percentage="nodeMemAllocatable/nodeMemCapacity * 100"></el-progress>
 | 
					 | 
				
			||||||
                          </div>
 | 
					 | 
				
			||||||
                          <div>
 | 
					 | 
				
			||||||
                              <p class="home-node-card-title">内存: 可分配/容量</p>
 | 
					 | 
				
			||||||
                              <p class="home-node-card-num">{{ specTrans(nodeMemAllocatable) }}Gi/{{ specTrans(nodeMemCapacity) }}Gi</p>
 | 
					 | 
				
			||||||
                          </div>
 | 
					 | 
				
			||||||
                      </el-card>
 | 
					 | 
				
			||||||
                  </el-col>
 | 
					 | 
				
			||||||
                  <el-col :span="5">
 | 
					 | 
				
			||||||
                      <el-card class="home-node-card" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                          <div style="float:left;padding-top:20%">
 | 
					 | 
				
			||||||
                              <el-progress :stroke-width="20" :show-text="false" type="circle" :percentage="nodePodAllocatable/nodePodAllocatable * 100"></el-progress>
 | 
					 | 
				
			||||||
                          </div>
 | 
					 | 
				
			||||||
                          <div>
 | 
					 | 
				
			||||||
                              <p class="home-node-card-title">POD: 可分配/容量</p>
 | 
					 | 
				
			||||||
                              <p class="home-node-card-num">{{ nodePodAllocatable }}/{{ nodePodAllocatable }}</p>
 | 
					 | 
				
			||||||
                          </div>
 | 
					 | 
				
			||||||
                      </el-card>
 | 
					 | 
				
			||||||
                  </el-col>
 | 
					 | 
				
			||||||
              </el-row>
 | 
					 | 
				
			||||||
          </el-collapse-item>
 | 
					 | 
				
			||||||
          <el-collapse-item title="资源统计" name="3">
 | 
					 | 
				
			||||||
              <el-row :gutter="10">
 | 
					 | 
				
			||||||
                  <el-col :span="24" style="margin-bottom: 10px;">
 | 
					 | 
				
			||||||
                      <el-card class="home-dash-card" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                          <div id="podNumDash" style="height: 300px;">
 | 
					 | 
				
			||||||
                          </div>
 | 
					 | 
				
			||||||
                      </el-card>
 | 
					 | 
				
			||||||
                  </el-col>
 | 
					 | 
				
			||||||
                  <el-col :span="24">
 | 
					 | 
				
			||||||
                      <el-card class="home-dash-card" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                          <div id="deployNumDash" style="height: 300px;">
 | 
					 | 
				
			||||||
                          </div>
 | 
					 | 
				
			||||||
                      </el-card>
 | 
					 | 
				
			||||||
                  </el-col>
 | 
					 | 
				
			||||||
              </el-row>
 | 
					 | 
				
			||||||
          </el-collapse-item>
 | 
					 | 
				
			||||||
      </el-collapse>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script>
 | 
					 | 
				
			||||||
import * as echarts from 'echarts'
 | 
					 | 
				
			||||||
import common from "../common/Config";
 | 
					 | 
				
			||||||
import httpClient from '../../utils/request';
 | 
					 | 
				
			||||||
export default {
 | 
					 | 
				
			||||||
  data() {
 | 
					 | 
				
			||||||
      return {
 | 
					 | 
				
			||||||
          activeNames: ["1", "2", "3"],
 | 
					 | 
				
			||||||
          namespaceActive: 0,
 | 
					 | 
				
			||||||
          namespaceValue: 'default',
 | 
					 | 
				
			||||||
          namespaceTotal: 0,
 | 
					 | 
				
			||||||
          namespaceListUrl: common.k8sNamespaceList,
 | 
					 | 
				
			||||||
          nodeTotal: 0,
 | 
					 | 
				
			||||||
          nodeCpuAllocatable: 0,
 | 
					 | 
				
			||||||
          nodeCpuCapacity: 0,
 | 
					 | 
				
			||||||
          nodeMemAllocatable: 0,
 | 
					 | 
				
			||||||
          nodeMemCapacity: 0,
 | 
					 | 
				
			||||||
          nodePodAllocatable: 0,
 | 
					 | 
				
			||||||
          nodePodCapacity: 0,
 | 
					 | 
				
			||||||
          getNodesData: {
 | 
					 | 
				
			||||||
              url: common.k8sNodeList,
 | 
					 | 
				
			||||||
              params: {}
 | 
					 | 
				
			||||||
          },
 | 
					 | 
				
			||||||
          deploymentTotal: 0,
 | 
					 | 
				
			||||||
          getDeploymentsData: {
 | 
					 | 
				
			||||||
              url: common.k8sDeploymentList,
 | 
					 | 
				
			||||||
              params: {
 | 
					 | 
				
			||||||
                  namespace: '',
 | 
					 | 
				
			||||||
              }
 | 
					 | 
				
			||||||
          },
 | 
					 | 
				
			||||||
          podTotal: 0,
 | 
					 | 
				
			||||||
          getPodsData: {
 | 
					 | 
				
			||||||
              url: common.k8sPodList,
 | 
					 | 
				
			||||||
              params: {
 | 
					 | 
				
			||||||
                  namespace: '',
 | 
					 | 
				
			||||||
              }
 | 
					 | 
				
			||||||
          },
 | 
					 | 
				
			||||||
          podNumNp: [],
 | 
					 | 
				
			||||||
          podNumNpUrl: common.k8sPodNumNp,
 | 
					 | 
				
			||||||
          deploymentNumNp: [],
 | 
					 | 
				
			||||||
          deploymentNumNpUrl: common.k8sDeploymentNumNp
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  methods: {
 | 
					 | 
				
			||||||
      getNamespaces() {
 | 
					 | 
				
			||||||
          httpClient.get(this.namespaceListUrl)
 | 
					 | 
				
			||||||
          .then(res => {
 | 
					 | 
				
			||||||
              this.namespaceTotal = res.data.total
 | 
					 | 
				
			||||||
              let namespaceList = res.data.items
 | 
					 | 
				
			||||||
              let index
 | 
					 | 
				
			||||||
              for (index in namespaceList) {
 | 
					 | 
				
			||||||
                  if (namespaceList[index].status.phase === "Active" ) {
 | 
					 | 
				
			||||||
                      this.namespaceActive = this.namespaceActive + 1
 | 
					 | 
				
			||||||
                  }
 | 
					 | 
				
			||||||
              }
 | 
					 | 
				
			||||||
          })
 | 
					 | 
				
			||||||
          .catch(res => {
 | 
					 | 
				
			||||||
              this.$message.error({
 | 
					 | 
				
			||||||
              message: res.msg
 | 
					 | 
				
			||||||
              })
 | 
					 | 
				
			||||||
          })
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      specTrans(num) {
 | 
					 | 
				
			||||||
          let a = num / 1024 / 1024
 | 
					 | 
				
			||||||
          return a.toFixed(0)
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      getNodes() {
 | 
					 | 
				
			||||||
          httpClient.get(this.getNodesData.url, {params: this.getNodesData.params})
 | 
					 | 
				
			||||||
          .then(res => {
 | 
					 | 
				
			||||||
              this.nodeTotal = res.data.total
 | 
					 | 
				
			||||||
              let nodeList = res.data.items
 | 
					 | 
				
			||||||
              let index
 | 
					 | 
				
			||||||
              for (index in nodeList) {
 | 
					 | 
				
			||||||
                  let isnum = /^\d+$/.test(nodeList[index].status.allocatable.cpu);
 | 
					 | 
				
			||||||
                  if (!isnum) {
 | 
					 | 
				
			||||||
                      continue
 | 
					 | 
				
			||||||
                  }
 | 
					 | 
				
			||||||
                  this.nodeCpuAllocatable = parseInt(nodeList[index].status.allocatable.cpu) + this.nodeCpuAllocatable
 | 
					 | 
				
			||||||
                  this.nodeCpuCapacity = parseInt(nodeList[index].status.capacity.cpu) + this.nodeCpuCapacity
 | 
					 | 
				
			||||||
                  this.nodeMemAllocatable = parseInt(nodeList[index].status.allocatable.memory) + this.nodeMemAllocatable
 | 
					 | 
				
			||||||
                  this.nodeMemCapacity = parseInt(nodeList[index].status.capacity.memory) + this.nodeMemCapacity
 | 
					 | 
				
			||||||
                  this.nodePodAllocatable = parseInt(nodeList[index].status.allocatable.pods) + this.nodePodAllocatable
 | 
					 | 
				
			||||||
                  this.nodePodCapacity = parseInt(nodeList[index].status.capacity.pods) + this.nodePodCapacity
 | 
					 | 
				
			||||||
              }
 | 
					 | 
				
			||||||
          })
 | 
					 | 
				
			||||||
          .catch(res => {
 | 
					 | 
				
			||||||
              this.$message.error({
 | 
					 | 
				
			||||||
              message: res.msg
 | 
					 | 
				
			||||||
              })
 | 
					 | 
				
			||||||
          })
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      getDeployments() {
 | 
					 | 
				
			||||||
          this.getDeploymentsData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
          httpClient.get(this.getDeploymentsData.url, {params: this.getDeploymentsData.params})
 | 
					 | 
				
			||||||
          .then(res => {
 | 
					 | 
				
			||||||
              this.deploymentTotal = res.data.total
 | 
					 | 
				
			||||||
          })
 | 
					 | 
				
			||||||
          .catch(res => {
 | 
					 | 
				
			||||||
              this.$message.error({
 | 
					 | 
				
			||||||
              message: res.msg
 | 
					 | 
				
			||||||
              })
 | 
					 | 
				
			||||||
          })
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      getPods() {
 | 
					 | 
				
			||||||
          this.getPodsData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
          httpClient.get(this.getPodsData.url, {params: this.getPodsData.params})
 | 
					 | 
				
			||||||
          .then(res => {
 | 
					 | 
				
			||||||
              this.podTotal = res.data.total
 | 
					 | 
				
			||||||
          })
 | 
					 | 
				
			||||||
          .catch(res => {
 | 
					 | 
				
			||||||
              this.$message.error({
 | 
					 | 
				
			||||||
              message: res.msg
 | 
					 | 
				
			||||||
              })
 | 
					 | 
				
			||||||
          })
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      getDeploymentNumNp() {
 | 
					 | 
				
			||||||
          httpClient.get(this.deploymentNumNpUrl)
 | 
					 | 
				
			||||||
          .then(res => {
 | 
					 | 
				
			||||||
              this.deploymentNumNp = res.data
 | 
					 | 
				
			||||||
              this.getDeployNumDash()
 | 
					 | 
				
			||||||
          })
 | 
					 | 
				
			||||||
          .catch(res => {
 | 
					 | 
				
			||||||
              this.$message.error({
 | 
					 | 
				
			||||||
              message: res.msg
 | 
					 | 
				
			||||||
              })
 | 
					 | 
				
			||||||
          })
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      getPodNumNp() {
 | 
					 | 
				
			||||||
          httpClient.get(this.podNumNpUrl)
 | 
					 | 
				
			||||||
          .then(res => {
 | 
					 | 
				
			||||||
              this.podNumNp = res.data
 | 
					 | 
				
			||||||
              this.getPodNumDash()
 | 
					 | 
				
			||||||
          })
 | 
					 | 
				
			||||||
          .catch(res => {
 | 
					 | 
				
			||||||
              this.$message.error({
 | 
					 | 
				
			||||||
              message: res.msg
 | 
					 | 
				
			||||||
              })
 | 
					 | 
				
			||||||
          })
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      getPodNumDash(){
 | 
					 | 
				
			||||||
          if (this.podNumDash != null && this.podNumDash != "" && this.podNumDash != undefined) {
 | 
					 | 
				
			||||||
              this.podNumDash.dispose()
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          this.podNumDash = echarts.init(document.getElementById('podNumDash'));
 | 
					 | 
				
			||||||
          this.podNumDash.setOption({
 | 
					 | 
				
			||||||
              title: { text: 'Pods per Namespace', textStyle: {color:'rgb(134, 135, 136)'}},
 | 
					 | 
				
			||||||
              color: ['#67E0E3', '#9FE6B8', '#FFDB5C','#ff9f7f', '#fb7293', '#E062AE', '#E690D1', '#e7bcf3', '#9d96f5', '#8378EA', '#96BFFF'],
 | 
					 | 
				
			||||||
              tooltip: { 
 | 
					 | 
				
			||||||
                  trigger: "axis", 
 | 
					 | 
				
			||||||
                  axisPointer: { 
 | 
					 | 
				
			||||||
                      type: "cross", 
 | 
					 | 
				
			||||||
                      label: { 
 | 
					 | 
				
			||||||
                          backgroundColor: "#76baf1" 
 | 
					 | 
				
			||||||
                      } 
 | 
					 | 
				
			||||||
                  } 
 | 
					 | 
				
			||||||
              },
 | 
					 | 
				
			||||||
              legend: {
 | 
					 | 
				
			||||||
                  data: ['Pods']
 | 
					 | 
				
			||||||
              },
 | 
					 | 
				
			||||||
              dataset: {
 | 
					 | 
				
			||||||
                  dimensions: ['namespace','pod_num'],
 | 
					 | 
				
			||||||
                  source: this.podNumNp
 | 
					 | 
				
			||||||
              },
 | 
					 | 
				
			||||||
              xAxis: {
 | 
					 | 
				
			||||||
                  type: 'category',
 | 
					 | 
				
			||||||
                  axisLabel:{
 | 
					 | 
				
			||||||
                      interval: 0,
 | 
					 | 
				
			||||||
                      formatter: function (value) {
 | 
					 | 
				
			||||||
                          return value.length>5?value.substring(0,5)+'...':value
 | 
					 | 
				
			||||||
                      }
 | 
					 | 
				
			||||||
                  },
 | 
					 | 
				
			||||||
              },
 | 
					 | 
				
			||||||
              yAxis: [
 | 
					 | 
				
			||||||
                  {type: 'value'}
 | 
					 | 
				
			||||||
              ],
 | 
					 | 
				
			||||||
              series: [{
 | 
					 | 
				
			||||||
                  name: 'Pods',
 | 
					 | 
				
			||||||
                  type: 'bar',
 | 
					 | 
				
			||||||
                  label: {
 | 
					 | 
				
			||||||
                      show: true,
 | 
					 | 
				
			||||||
                      position: 'top'
 | 
					 | 
				
			||||||
                      }
 | 
					 | 
				
			||||||
                  }
 | 
					 | 
				
			||||||
              ]
 | 
					 | 
				
			||||||
          });
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      getDeployNumDash(){
 | 
					 | 
				
			||||||
          if (this.deployNumDash != null && this.deployNumDash != "" && this.deployNumDash != undefined) {
 | 
					 | 
				
			||||||
              this.deployNumDash.dispose()
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          this.deployNumDash = echarts.init(document.getElementById('deployNumDash'));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          this.deployNumDash.setOption({
 | 
					 | 
				
			||||||
              title: { text: 'Deployments per Namespace', textStyle: {color:'rgb(134, 135, 136)'}},
 | 
					 | 
				
			||||||
              color: ['#9FE6B8', '#FFDB5C','#ff9f7f', '#fb7293', '#E062AE', '#E690D1', '#e7bcf3', '#9d96f5', '#8378EA', '#96BFFF'],
 | 
					 | 
				
			||||||
              tooltip: { trigger: "axis", axisPointer: { type: "cross", label: { backgroundColor: "#76baf1" } } },
 | 
					 | 
				
			||||||
              legend: {
 | 
					 | 
				
			||||||
                  data: ['Deployments']
 | 
					 | 
				
			||||||
              },
 | 
					 | 
				
			||||||
              dataset: {
 | 
					 | 
				
			||||||
                  dimensions: ['namespace','deployment_num'],
 | 
					 | 
				
			||||||
                  source: this.deploymentNumNp
 | 
					 | 
				
			||||||
              },
 | 
					 | 
				
			||||||
              xAxis: {
 | 
					 | 
				
			||||||
                  type: 'category',
 | 
					 | 
				
			||||||
                  axisLabel:{
 | 
					 | 
				
			||||||
                      interval: 0,
 | 
					 | 
				
			||||||
                      formatter: function (value) {
 | 
					 | 
				
			||||||
                          return value.length>5?value.substring(0,5)+'...':value
 | 
					 | 
				
			||||||
                      }
 | 
					 | 
				
			||||||
                  },
 | 
					 | 
				
			||||||
              },
 | 
					 | 
				
			||||||
              yAxis: [
 | 
					 | 
				
			||||||
                  {type: 'value'}
 | 
					 | 
				
			||||||
              ],
 | 
					 | 
				
			||||||
              series: [{
 | 
					 | 
				
			||||||
                  name: 'Deployments',
 | 
					 | 
				
			||||||
                  type: 'bar',
 | 
					 | 
				
			||||||
                  label: {
 | 
					 | 
				
			||||||
                      show: true,
 | 
					 | 
				
			||||||
                      position: 'top'
 | 
					 | 
				
			||||||
                      }
 | 
					 | 
				
			||||||
                  }
 | 
					 | 
				
			||||||
              ]
 | 
					 | 
				
			||||||
          });
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  beforeMount() {
 | 
					 | 
				
			||||||
      this.getNamespaces()
 | 
					 | 
				
			||||||
      this.getNodes()
 | 
					 | 
				
			||||||
      this.getDeployments()
 | 
					 | 
				
			||||||
      this.getPods()
 | 
					 | 
				
			||||||
      this.getDeploymentNumNp()
 | 
					 | 
				
			||||||
      this.getPodNumNp()
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style scoped>
 | 
					 | 
				
			||||||
  :v-deep .el-collapse-item__header {
 | 
					 | 
				
			||||||
      font-size: 16px;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  .home-node-card {
 | 
					 | 
				
			||||||
      border-radius:1px;
 | 
					 | 
				
			||||||
      text-align: center;
 | 
					 | 
				
			||||||
      background-color: rgb(250, 253, 255);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  .home-dash-card {
 | 
					 | 
				
			||||||
      border-radius:1px;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  .home-node-card-title {
 | 
					 | 
				
			||||||
      font-size: 12px;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  .home-node-card-num {
 | 
					 | 
				
			||||||
      font-size: 22px;
 | 
					 | 
				
			||||||
      font-weight: bold;
 | 
					 | 
				
			||||||
      color: rgb(63, 92, 135);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  :v-deep .el-progress-circle {
 | 
					 | 
				
			||||||
      height: 50px !important;
 | 
					 | 
				
			||||||
      width: 50px !important;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
@ -1,556 +0,0 @@
 | 
				
			|||||||
<template>
 | 
					 | 
				
			||||||
    <div class="ingress">
 | 
					 | 
				
			||||||
        <el-row>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="ingress-head-card" shadow="never" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                        <el-row>
 | 
					 | 
				
			||||||
                            <el-col :span="6">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <span>命名空间: </span>
 | 
					 | 
				
			||||||
                                    <el-select v-model="namespaceValue" filterable placeholder="请选择">
 | 
					 | 
				
			||||||
                                        <el-option
 | 
					 | 
				
			||||||
                                        v-for="(item, index) in namespaceList"
 | 
					 | 
				
			||||||
                                        :key="index"
 | 
					 | 
				
			||||||
                                        :label="item.metadata.name"
 | 
					 | 
				
			||||||
                                        :value="item.metadata.name">
 | 
					 | 
				
			||||||
                                        </el-option>
 | 
					 | 
				
			||||||
                                    </el-select>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                            <el-col :span="2" :offset="16">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Refresh" plain @click="getIngresss()">刷新</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                        </el-row>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="ingress-head-card" shadow="never" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                        <el-row>
 | 
					 | 
				
			||||||
                            <el-col :span="2">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Edit" type="primary" @click="createIngressDrawer = true" v-loading.fullscreen.lock="fullscreenLoading">创建</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                            <el-col :span="6">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-input class="ingress-head-search" clearable placeholder="请输入" v-model="searchInput"></el-input>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Search" type="primary" plain @click="getIngresss()">搜索</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                        </el-row>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="ingress-body-card" shadow="never" :body-style="{padding:'5px'}">
 | 
					 | 
				
			||||||
                        <el-table
 | 
					 | 
				
			||||||
                        style="width:100%;font-size:12px;margin-bottom:10px;"
 | 
					 | 
				
			||||||
                        :data="ingressList"
 | 
					 | 
				
			||||||
                        v-loading="appLoading">
 | 
					 | 
				
			||||||
                            <el-table-column width="10"></el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=left label="Ingress名">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <a class="ingress-body-ingressname">{{ scope.row.metadata.name }}</a>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="标签" min-width='120'>
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <div v-for="(val, key) in scope.row.metadata.labels" :key="key">
 | 
					 | 
				
			||||||
                                        <el-popover
 | 
					 | 
				
			||||||
                                            placement="right"
 | 
					 | 
				
			||||||
                                            :width="200"
 | 
					 | 
				
			||||||
                                            trigger="hover"
 | 
					 | 
				
			||||||
                                            :content="key + ':' + val">
 | 
					 | 
				
			||||||
                                            <template #reference>
 | 
					 | 
				
			||||||
                                                <el-tag style="margin-bottom: 5px" type="warning">{{ ellipsis(key + ":" + val) }}</el-tag>
 | 
					 | 
				
			||||||
                                            </template>
 | 
					 | 
				
			||||||
                                        </el-popover>
 | 
					 | 
				
			||||||
                                    </div>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="Host" min-width='120'>
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <div v-for="(item, index) in scope.row.spec.rules" :key="index">
 | 
					 | 
				
			||||||
                                        <el-popover
 | 
					 | 
				
			||||||
                                            placement="right"
 | 
					 | 
				
			||||||
                                            :width="200"
 | 
					 | 
				
			||||||
                                            trigger="hover"
 | 
					 | 
				
			||||||
                                            :content="item.host">
 | 
					 | 
				
			||||||
                                            <template #reference>
 | 
					 | 
				
			||||||
                                                <el-tag style="margin-bottom: 5px" type="danger">{{ ellipsis(item.host) }}</el-tag>
 | 
					 | 
				
			||||||
                                            </template>
 | 
					 | 
				
			||||||
                                        </el-popover>
 | 
					 | 
				
			||||||
                                    </div>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="Path">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <div v-for="(item, index) in scope.row.spec.rules" :key="index">
 | 
					 | 
				
			||||||
                                        <el-popover
 | 
					 | 
				
			||||||
                                            placement="right"
 | 
					 | 
				
			||||||
                                            :width="100"
 | 
					 | 
				
			||||||
                                            trigger="hover"
 | 
					 | 
				
			||||||
                                            :content="item.http.paths[0].path">
 | 
					 | 
				
			||||||
                                            <template #reference>
 | 
					 | 
				
			||||||
                                                <el-tag style="margin-bottom: 5px" type="danger">{{ item.http.paths[0].path }}</el-tag>
 | 
					 | 
				
			||||||
                                            </template>
 | 
					 | 
				
			||||||
                                        </el-popover>
 | 
					 | 
				
			||||||
                                    </div>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="EXTERNAL-IP">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <span>{{ scope.row.status.loadBalancer.ingress ? scope.row.status.loadBalancer.ingress[0].ip : '' }} </span>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="TLS">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <span>{{ scope.row.spec.tls ? 'YES' : '' }} </span>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center min-width="100" label="创建时间">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-tag type="info">{{ timeTrans(scope.row.metadata.creationTimestamp) }} </el-tag>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="操作" width="200">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-button size="small" style="border-radius:2px;" icon="Edit" type="primary" plain @click="getIngressDetail(scope)">YAML</el-button>
 | 
					 | 
				
			||||||
                                    <el-button size="small" style="border-radius:2px;" icon="Delete" type="danger" @click="handleConfirm(scope, '删除', delIngress)">删除</el-button>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                        </el-table>
 | 
					 | 
				
			||||||
                        <el-pagination
 | 
					 | 
				
			||||||
                        class="ingress-body-pagination"
 | 
					 | 
				
			||||||
                        background
 | 
					 | 
				
			||||||
                        @size-change="handleSizeChange"
 | 
					 | 
				
			||||||
                        @current-change="handleCurrentChange"
 | 
					 | 
				
			||||||
                        :current-page="currentPage"
 | 
					 | 
				
			||||||
                        :page-sizes="pagesizeList"
 | 
					 | 
				
			||||||
                        :page-size="pagesize"
 | 
					 | 
				
			||||||
                        layout="total, sizes, prev, pager, next, jumper"
 | 
					 | 
				
			||||||
                        :total="ingressTotal">
 | 
					 | 
				
			||||||
                        </el-pagination>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
        </el-row>
 | 
					 | 
				
			||||||
        <el-dialog title="YAML信息" v-model="yamlDialog" width="45%" top="5%">
 | 
					 | 
				
			||||||
            <codemirror
 | 
					 | 
				
			||||||
                :value="contentYaml"
 | 
					 | 
				
			||||||
                border
 | 
					 | 
				
			||||||
                :options="cmOptions"
 | 
					 | 
				
			||||||
                height="500"
 | 
					 | 
				
			||||||
                style="font-size:14px;"
 | 
					 | 
				
			||||||
                @change="onChange"
 | 
					 | 
				
			||||||
            ></codemirror>
 | 
					 | 
				
			||||||
            <template #footer>
 | 
					 | 
				
			||||||
                <span class="dialog-footer">
 | 
					 | 
				
			||||||
                    <el-button @click="yamlDialog = false">取 消</el-button>
 | 
					 | 
				
			||||||
                    <el-button type="primary" @click="updateIngress()">更 新</el-button>
 | 
					 | 
				
			||||||
                </span>
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
        </el-dialog>
 | 
					 | 
				
			||||||
        <el-drawer
 | 
					 | 
				
			||||||
            v-model="createIngressDrawer"
 | 
					 | 
				
			||||||
            :direction="direction"
 | 
					 | 
				
			||||||
            :before-close="handleClose">
 | 
					 | 
				
			||||||
            <template #title>
 | 
					 | 
				
			||||||
                <h4>创建Ingress</h4>
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
            <template #default>
 | 
					 | 
				
			||||||
                <el-row type="flex" justify="center">
 | 
					 | 
				
			||||||
                    <el-col :span="20">
 | 
					 | 
				
			||||||
                        <el-form ref="createIngress" :rules="createIngressRules" :model="createIngress" label-width="80px">
 | 
					 | 
				
			||||||
                            <el-form-item class="ingress-create-form" label="名称" prop="name">
 | 
					 | 
				
			||||||
                                <el-input v-model="createIngress.name"></el-input>
 | 
					 | 
				
			||||||
                            </el-form-item>
 | 
					 | 
				
			||||||
                            <el-form-item class="ingress-create-form" label="命名空间" prop="namespace">
 | 
					 | 
				
			||||||
                                <el-select v-model="createIngress.namespace" filterable placeholder="请选择">
 | 
					 | 
				
			||||||
                                    <el-option
 | 
					 | 
				
			||||||
                                    v-for="(item, index) in namespaceList"
 | 
					 | 
				
			||||||
                                    :key="index"
 | 
					 | 
				
			||||||
                                    :label="item.metadata.name"
 | 
					 | 
				
			||||||
                                    :value="item.metadata.name">
 | 
					 | 
				
			||||||
                                    </el-option>
 | 
					 | 
				
			||||||
                                </el-select>
 | 
					 | 
				
			||||||
                            </el-form-item>
 | 
					 | 
				
			||||||
                            <el-form-item class="SERVICE-create-form" label="标签" prop="label_str">
 | 
					 | 
				
			||||||
                                <el-input v-model="createIngress.label_str" placeholder="示例: project=ms,app=gateway"></el-input>
 | 
					 | 
				
			||||||
                            </el-form-item>
 | 
					 | 
				
			||||||
                            <el-form-item class="deploy-create-form" label="域名" prop="host">
 | 
					 | 
				
			||||||
                                <el-input v-model="createIngress.host" placeholder="示例: www.example.com"></el-input>
 | 
					 | 
				
			||||||
                            </el-form-item>
 | 
					 | 
				
			||||||
                            <el-form-item class="ingress-create-form" label="Path" prop="path">
 | 
					 | 
				
			||||||
                                <el-input v-model="createIngress.path" placeholder="示例: /abc"></el-input>
 | 
					 | 
				
			||||||
                            </el-form-item>
 | 
					 | 
				
			||||||
                            <el-form-item class="deploy-create-form" label="匹配类型" prop="path_type">
 | 
					 | 
				
			||||||
                                <el-select v-model="createIngress.path_type" placeholder="请选择">
 | 
					 | 
				
			||||||
                                    <el-option value="Prefix" label="Prefix"></el-option>
 | 
					 | 
				
			||||||
                                    <el-option value="Exact" label="Exact"></el-option>
 | 
					 | 
				
			||||||
                                    <el-option value="ImplementationSpecific" label="ImplementationSpecific"></el-option>
 | 
					 | 
				
			||||||
                                </el-select>
 | 
					 | 
				
			||||||
                            </el-form-item>
 | 
					 | 
				
			||||||
                            <el-form-item class="ingress-create-form" label="Service名" prop="service_name">
 | 
					 | 
				
			||||||
                                <el-input disabled v-model="createIngress.name"></el-input>
 | 
					 | 
				
			||||||
                            </el-form-item>
 | 
					 | 
				
			||||||
                            <el-form-item class="ingress-create-form" label="Service端口" prop="service_port">
 | 
					 | 
				
			||||||
                                <el-input v-model="createIngress.service_port" placeholder="示例: 80"></el-input>
 | 
					 | 
				
			||||||
                            </el-form-item>
 | 
					 | 
				
			||||||
                        </el-form>
 | 
					 | 
				
			||||||
                    </el-col>
 | 
					 | 
				
			||||||
                </el-row>
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
            <template #footer>
 | 
					 | 
				
			||||||
                <el-button @click="createIngressDrawer = false">取消</el-button>
 | 
					 | 
				
			||||||
                <el-button type="primary" @click="submitForm('createIngress')">立即创建</el-button>
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
        </el-drawer>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script>
 | 
					 | 
				
			||||||
import common from "../common/Config";
 | 
					 | 
				
			||||||
import httpClient from '../../utils/request';
 | 
					 | 
				
			||||||
import yaml2obj from 'js-yaml';
 | 
					 | 
				
			||||||
import json2yaml from 'json2yaml';
 | 
					 | 
				
			||||||
export default {
 | 
					 | 
				
			||||||
    data() {
 | 
					 | 
				
			||||||
        return {
 | 
					 | 
				
			||||||
            cmOptions: common.cmOptions,
 | 
					 | 
				
			||||||
            contentYaml: '',
 | 
					 | 
				
			||||||
            currentPage: 1,
 | 
					 | 
				
			||||||
            pagesize: 10,
 | 
					 | 
				
			||||||
            pagesizeList: [10, 20, 30],
 | 
					 | 
				
			||||||
            searchInput: '',
 | 
					 | 
				
			||||||
            namespaceValue: 'default',
 | 
					 | 
				
			||||||
            namespaceList: [],
 | 
					 | 
				
			||||||
            namespaceListUrl: common.k8sNamespaceList,
 | 
					 | 
				
			||||||
            appLoading: false,
 | 
					 | 
				
			||||||
            ingressList: [],
 | 
					 | 
				
			||||||
            ingressTotal: 0,
 | 
					 | 
				
			||||||
            getIngresssData: {
 | 
					 | 
				
			||||||
                url: common.k8sIngressList,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    filter_name: '',
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                    page: '',
 | 
					 | 
				
			||||||
                    limit: '',
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            ingressDetail: {},
 | 
					 | 
				
			||||||
            getIngressDetailData: {
 | 
					 | 
				
			||||||
                url: common.k8sIngressDetail,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    ingress_name: '',
 | 
					 | 
				
			||||||
                    namespace: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            yamlDialog: false,
 | 
					 | 
				
			||||||
            updateIngressData: {
 | 
					 | 
				
			||||||
                url: common.k8sIngressUpdate,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                    content: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            delIngressData: {
 | 
					 | 
				
			||||||
                url: common.k8sIngressDel,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    ingress_name: '',
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            fullscreenLoading: false,
 | 
					 | 
				
			||||||
            direction: 'rtl',
 | 
					 | 
				
			||||||
            createIngressDrawer: false,
 | 
					 | 
				
			||||||
            createIngress: {
 | 
					 | 
				
			||||||
                name: '',
 | 
					 | 
				
			||||||
                namespace: '',
 | 
					 | 
				
			||||||
                label_str: '',
 | 
					 | 
				
			||||||
                host: '',
 | 
					 | 
				
			||||||
                path: '',
 | 
					 | 
				
			||||||
                path_type: '',
 | 
					 | 
				
			||||||
                service_name: '',
 | 
					 | 
				
			||||||
                service_port: '',
 | 
					 | 
				
			||||||
                hosts: {}
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            createIngressData: {
 | 
					 | 
				
			||||||
                url: common.k8sIngressCreate,
 | 
					 | 
				
			||||||
                params: {}
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            createIngressRules: {
 | 
					 | 
				
			||||||
                name: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请填写名称',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                namespace: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请选择命名空间',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                host: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请填写域名',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                path: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请填写路径',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                service_port: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请填写Service端口',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                label_str: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请填写标签',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                path_type: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请选择匹配类型',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    methods: {
 | 
					 | 
				
			||||||
        transYaml(content) {
 | 
					 | 
				
			||||||
            return json2yaml.stringify(content)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        transObj(content) {
 | 
					 | 
				
			||||||
            return yaml2obj.load(content)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        onChange(val) {
 | 
					 | 
				
			||||||
            this.contentYaml = val
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleSizeChange(size) {
 | 
					 | 
				
			||||||
            this.pagesize = size;
 | 
					 | 
				
			||||||
            this.getIngresss()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleCurrentChange(currentPage) {
 | 
					 | 
				
			||||||
            this.currentPage = currentPage;
 | 
					 | 
				
			||||||
            this.getIngresss()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleClose(done) {
 | 
					 | 
				
			||||||
            this.$confirm('确认关闭?')
 | 
					 | 
				
			||||||
            .then(() => {
 | 
					 | 
				
			||||||
                done();
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(() => {});
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        ellipsis(value) {
 | 
					 | 
				
			||||||
            return value.length>15?value.substring(0,15)+'...':value
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        timeTrans(timestamp) {
 | 
					 | 
				
			||||||
            let date = new Date(new Date(timestamp).getTime() + 8 * 3600 * 1000)
 | 
					 | 
				
			||||||
            date = date.toJSON();
 | 
					 | 
				
			||||||
            date = date.substring(0, 19).replace('T', ' ')
 | 
					 | 
				
			||||||
            return date 
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        restartTotal(e) {
 | 
					 | 
				
			||||||
            let index, sum = 0
 | 
					 | 
				
			||||||
            let containerStatuses = e.row.status.containerStatuses
 | 
					 | 
				
			||||||
            for ( index in containerStatuses) {
 | 
					 | 
				
			||||||
                sum = sum + containerStatuses[index].restartCount 
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return sum
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getNamespaces() {
 | 
					 | 
				
			||||||
            httpClient.get(this.namespaceListUrl)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.namespaceList = res.data.items
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getIngresss() {
 | 
					 | 
				
			||||||
            this.appLoading = true
 | 
					 | 
				
			||||||
            this.getIngresssData.params.filter_name = this.searchInput
 | 
					 | 
				
			||||||
            this.getIngresssData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            this.getIngresssData.params.page = this.currentPage
 | 
					 | 
				
			||||||
            this.getIngresssData.params.limit = this.pagesize
 | 
					 | 
				
			||||||
            httpClient.get(this.getIngresssData.url, {params: this.getIngresssData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.ingressList = res.data.items
 | 
					 | 
				
			||||||
                this.ingressTotal = res.data.total
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.appLoading = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getIngressDetail(e) {
 | 
					 | 
				
			||||||
            this.getIngressDetailData.params.ingress_name = e.row.metadata.name
 | 
					 | 
				
			||||||
            this.getIngressDetailData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            httpClient.get(this.getIngressDetailData.url, {params: this.getIngressDetailData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.ingressDetail = res.data
 | 
					 | 
				
			||||||
                this.contentYaml = this.transYaml(this.ingressDetail)
 | 
					 | 
				
			||||||
                this.yamlDialog = true
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        updateIngress() {
 | 
					 | 
				
			||||||
            let content = JSON.stringify(this.transObj(this.contentYaml))
 | 
					 | 
				
			||||||
            this.updateIngressData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            this.updateIngressData.params.content = content
 | 
					 | 
				
			||||||
            httpClient.put(this.updateIngressData.url, this.updateIngressData.params)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.yamlDialog = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        delIngress(e) {
 | 
					 | 
				
			||||||
            this.delIngressData.params.ingress_name = e.row.metadata.name
 | 
					 | 
				
			||||||
            this.delIngressData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            httpClient.delete(this.delIngressData.url, {data: this.delIngressData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.getIngresss()
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleConfirm(obj, operateName, fn) {
 | 
					 | 
				
			||||||
            this.confirmContent = '确认继续 ' + operateName + ' 操作吗?'
 | 
					 | 
				
			||||||
            this.$confirm(this.confirmContent,'提示',{
 | 
					 | 
				
			||||||
                confirmButtonText: '确定',
 | 
					 | 
				
			||||||
                cancelButtonText: '取消',
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .then(() => {
 | 
					 | 
				
			||||||
                fn(obj)
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            .catch(() => {
 | 
					 | 
				
			||||||
                this.$message.info({
 | 
					 | 
				
			||||||
                    message: '已取消操作'
 | 
					 | 
				
			||||||
                })          
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        createIngressFunc() {
 | 
					 | 
				
			||||||
            let reg = new RegExp("(^[A-Za-z]+=[A-Za-z0-9]+).*")
 | 
					 | 
				
			||||||
            if (!reg.test(this.createIngress.label_str)) {
 | 
					 | 
				
			||||||
                this.$message.warning({
 | 
					 | 
				
			||||||
                    message: "标签填写异常,请确认后重新填写"
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
                return
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            this.fullscreenLoading = true
 | 
					 | 
				
			||||||
            let label = new Map()
 | 
					 | 
				
			||||||
            let a = (this.createIngress.label_str).split(",")
 | 
					 | 
				
			||||||
            a.forEach(item => {
 | 
					 | 
				
			||||||
                let b = item.split("=")
 | 
					 | 
				
			||||||
                label[b[0]] = b[1]
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            let hosts = new Map()
 | 
					 | 
				
			||||||
            let httpPaths = []
 | 
					 | 
				
			||||||
            let httpPath = {
 | 
					 | 
				
			||||||
                path: this.createIngress.path,
 | 
					 | 
				
			||||||
                path_type: this.createIngress.path_type,
 | 
					 | 
				
			||||||
                service_name: this.createIngress.name,
 | 
					 | 
				
			||||||
                service_port: parseInt(this.createIngress.service_port)
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            httpPaths.push(httpPath)
 | 
					 | 
				
			||||||
            hosts[this.createIngress.host] = httpPaths
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            this.createIngressData.params = this.createIngress
 | 
					 | 
				
			||||||
            this.createIngressData.params.label = label
 | 
					 | 
				
			||||||
            this.createIngressData.params.hosts = hosts
 | 
					 | 
				
			||||||
            httpClient.post(this.createIngressData.url, this.createIngressData.params)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
                this.getIngresss()
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.resetForm('createIngress')
 | 
					 | 
				
			||||||
            this.fullscreenLoading = false
 | 
					 | 
				
			||||||
            this.createIngressDrawer = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        resetForm(formName) {
 | 
					 | 
				
			||||||
            this.$refs[formName].resetFields()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        submitForm(formName) {
 | 
					 | 
				
			||||||
            this.$refs[formName].validate((valid) => {
 | 
					 | 
				
			||||||
                if (valid) {
 | 
					 | 
				
			||||||
                    this.createIngressFunc()
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    return false;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    watch: {
 | 
					 | 
				
			||||||
        namespaceValue: {
 | 
					 | 
				
			||||||
            handler() {
 | 
					 | 
				
			||||||
                localStorage.setItem('namespace', this.namespaceValue)
 | 
					 | 
				
			||||||
                this.currentPage = 1
 | 
					 | 
				
			||||||
                this.getIngresss()
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    beforeMount() {
 | 
					 | 
				
			||||||
        if (localStorage.getItem('namespace') !== undefined && localStorage.getItem('namespace') !== null) {
 | 
					 | 
				
			||||||
            this.namespaceValue = localStorage.getItem('namespace')
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        this.getNamespaces()
 | 
					 | 
				
			||||||
        this.getIngresss()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style scoped>
 | 
					 | 
				
			||||||
    .ingress-head-card,.ingress-body-card {
 | 
					 | 
				
			||||||
        border-radius: 1px;
 | 
					 | 
				
			||||||
        margin-bottom: 5px;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .ingress-head-search {
 | 
					 | 
				
			||||||
        width:160px;
 | 
					 | 
				
			||||||
        margin-right:10px; 
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .ingress-body-ingressname {
 | 
					 | 
				
			||||||
        color: #4795EE;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .ingress-body-ingressname:hover {
 | 
					 | 
				
			||||||
        color: rgb(84, 138, 238);
 | 
					 | 
				
			||||||
        cursor: pointer;
 | 
					 | 
				
			||||||
        font-weight: bold;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
@ -1,96 +0,0 @@
 | 
				
			|||||||
<template>
 | 
					 | 
				
			||||||
    <div class="login">
 | 
					 | 
				
			||||||
        <el-card class="login-card">
 | 
					 | 
				
			||||||
            <template #header>
 | 
					 | 
				
			||||||
                <div class="login-card-header">
 | 
					 | 
				
			||||||
                    <span>用户登录</span>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
            <el-form :model="loginData" :rules="loginDataRules" ref="loginData">
 | 
					 | 
				
			||||||
                <el-form-item prop="username">
 | 
					 | 
				
			||||||
                    <el-input prefix-icon="UserFilled" v-model.trim="loginData.username" maxlength="32" placeholder="请输入账号" clearable></el-input>
 | 
					 | 
				
			||||||
                </el-form-item>
 | 
					 | 
				
			||||||
                <el-form-item prop="password">
 | 
					 | 
				
			||||||
                    <el-input prefix-icon="Lock" v-model.trim="loginData.password" maxlength="16" show-password placeholder="请输入密码" clearable></el-input>
 | 
					 | 
				
			||||||
                </el-form-item>
 | 
					 | 
				
			||||||
                <el-form-item>
 | 
					 | 
				
			||||||
                    <el-button type="primary" style="width: 100%;border-radius: 2px" :loading="loginLoading" @click="handleLogin">登 录</el-button>
 | 
					 | 
				
			||||||
                </el-form-item>
 | 
					 | 
				
			||||||
            </el-form>
 | 
					 | 
				
			||||||
        </el-card>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script>
 | 
					 | 
				
			||||||
import common from "../common/Config";
 | 
					 | 
				
			||||||
import httpClient from '../../utils/request';
 | 
					 | 
				
			||||||
import moment from 'moment';
 | 
					 | 
				
			||||||
import jwt from 'jsonwebtoken';
 | 
					 | 
				
			||||||
export default{
 | 
					 | 
				
			||||||
    data() {
 | 
					 | 
				
			||||||
        return {
 | 
					 | 
				
			||||||
            loginLoading: false,
 | 
					 | 
				
			||||||
            loginUrl: common.loginAuth,
 | 
					 | 
				
			||||||
            loginData: {
 | 
					 | 
				
			||||||
                username: '',
 | 
					 | 
				
			||||||
                password: ''
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            loginDataRules: {
 | 
					 | 
				
			||||||
                username: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请填写用户名',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                password: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请填写密码',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    methods: {
 | 
					 | 
				
			||||||
        handleLogin() {
 | 
					 | 
				
			||||||
            httpClient.post(this.loginUrl, this.loginData)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                localStorage.setItem('username', this.loginData.username);
 | 
					 | 
				
			||||||
                localStorage.setItem('loginDate', moment().format('YYYY-MM-DD HH:mm:ss'));
 | 
					 | 
				
			||||||
                let token = jwt.sign(this.loginData, 'devops', { expiresIn: '10h' });
 | 
					 | 
				
			||||||
                localStorage.setItem('token', token);
 | 
					 | 
				
			||||||
                this.$router.push('/');
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                    message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style scoped>
 | 
					 | 
				
			||||||
    .login {
 | 
					 | 
				
			||||||
        position: absolute;
 | 
					 | 
				
			||||||
        width: 100%;
 | 
					 | 
				
			||||||
        height: 100%;
 | 
					 | 
				
			||||||
        background: aquamarine;
 | 
					 | 
				
			||||||
        background-image: url(../../assets/img/login3.webp);
 | 
					 | 
				
			||||||
        background-size: 100%;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .login-card {
 | 
					 | 
				
			||||||
        position: absolute;
 | 
					 | 
				
			||||||
        left: 40%;
 | 
					 | 
				
			||||||
        top: 30%;
 | 
					 | 
				
			||||||
        width: 350px;
 | 
					 | 
				
			||||||
        border-radius: 5px;
 | 
					 | 
				
			||||||
        background: rgb(255, 255, 255);
 | 
					 | 
				
			||||||
        overflow: hidden;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .login-card-header {
 | 
					 | 
				
			||||||
        text-align: center;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
@ -1,313 +0,0 @@
 | 
				
			|||||||
<template>
 | 
					 | 
				
			||||||
    <div class="namespace">
 | 
					 | 
				
			||||||
        <el-row>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="namespace-head-card" shadow="never" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                        <el-row>
 | 
					 | 
				
			||||||
                            <el-col :span="2">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-button disabled style="border-radius:2px;" icon="Edit" type="primary">创建</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                            <el-col :span="6">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-input class="namespace-head-search" clearable placeholder="请输入" v-model="searchInput"></el-input>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Search" type="primary" plain @click="getNamespaces()">搜索</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                            <el-col :span="2" :offset="14">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Refresh" plain @click="getNamespaces()">刷新</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                        </el-row>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="namespace-body-card" shadow="never" :body-style="{padding:'5px'}">
 | 
					 | 
				
			||||||
                        <el-table
 | 
					 | 
				
			||||||
                        style="width:100%;font-size:12px;margin-bottom:10px;"
 | 
					 | 
				
			||||||
                        :data="namespaceList"
 | 
					 | 
				
			||||||
                        v-loading="appLoading">
 | 
					 | 
				
			||||||
                            <el-table-column width="20"></el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=left label="Namespace名">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <a class="namespace-body-namespacename">{{ scope.row.metadata.name }}</a>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="标签" min-width='120'>
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <div v-for="(val, key) in scope.row.metadata.labels" :key="key">
 | 
					 | 
				
			||||||
                                        <el-popover
 | 
					 | 
				
			||||||
                                            placement="right"
 | 
					 | 
				
			||||||
                                            :width="200"
 | 
					 | 
				
			||||||
                                            trigger="hover"
 | 
					 | 
				
			||||||
                                            :content="key + ':' + val">
 | 
					 | 
				
			||||||
                                            <template #reference>
 | 
					 | 
				
			||||||
                                                <el-tag style="margin-bottom: 5px" type="warning">{{ ellipsis(key + ":" + val) }}</el-tag>
 | 
					 | 
				
			||||||
                                            </template>
 | 
					 | 
				
			||||||
                                        </el-popover>
 | 
					 | 
				
			||||||
                                    </div>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center prop="status.phase" label="状态">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <span :class="[scope.row.status.phase === 'Active' ? 'success-status' : 'error-status']">{{ scope.row.status.phase }}</span>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center min-width="100" label="创建时间">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-tag type="info">{{ timeTrans(scope.row.metadata.creationTimestamp) }} </el-tag>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="操作" min-width="120">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-button size="small" style="border-radius:2px;" icon="Edit" type="primary" plain @click="getNamespaceDetail(scope)">YAML</el-button>
 | 
					 | 
				
			||||||
                                    <el-button size="small" style="border-radius:2px;" icon="Delete" type="danger" @click="handleConfirm(scope, '删除', delNamespace)">删除</el-button>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                        </el-table>
 | 
					 | 
				
			||||||
                        <el-pagination
 | 
					 | 
				
			||||||
                        class="namespace-body-pagination"
 | 
					 | 
				
			||||||
                        background
 | 
					 | 
				
			||||||
                        @size-change="handleSizeChange"
 | 
					 | 
				
			||||||
                        @current-change="handleCurrentChange"
 | 
					 | 
				
			||||||
                        :current-page="currentPage"
 | 
					 | 
				
			||||||
                        :page-sizes="pagesizeList"
 | 
					 | 
				
			||||||
                        :page-size="pagesize"
 | 
					 | 
				
			||||||
                        layout="total, sizes, prev, pager, next, jumper"
 | 
					 | 
				
			||||||
                        :total="namespaceTotal">
 | 
					 | 
				
			||||||
                        </el-pagination>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
        </el-row>
 | 
					 | 
				
			||||||
        <el-dialog title="YAML信息" v-model="yamlDialog" width="45%" top="5%">
 | 
					 | 
				
			||||||
            <codemirror
 | 
					 | 
				
			||||||
                :value="contentYaml"
 | 
					 | 
				
			||||||
                border
 | 
					 | 
				
			||||||
                :options="cmOptions"
 | 
					 | 
				
			||||||
                height="500"
 | 
					 | 
				
			||||||
                style="font-size:14px;"
 | 
					 | 
				
			||||||
                @change="onChange"
 | 
					 | 
				
			||||||
            ></codemirror>
 | 
					 | 
				
			||||||
            <template #footer>
 | 
					 | 
				
			||||||
                <span class="dialog-footer">
 | 
					 | 
				
			||||||
                    <el-button @click="yamlDialog = false">取 消</el-button>
 | 
					 | 
				
			||||||
                    <el-button disabled type="primary" @click="updateNamespace()">更 新</el-button>
 | 
					 | 
				
			||||||
                </span>
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
        </el-dialog>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script>
 | 
					 | 
				
			||||||
import common from "../common/Config";
 | 
					 | 
				
			||||||
import httpClient from '../../utils/request';
 | 
					 | 
				
			||||||
import yaml2obj from 'js-yaml';
 | 
					 | 
				
			||||||
import json2yaml from 'json2yaml';
 | 
					 | 
				
			||||||
export default {
 | 
					 | 
				
			||||||
    data() {
 | 
					 | 
				
			||||||
        return {
 | 
					 | 
				
			||||||
            cmOptions: common.cmOptions,
 | 
					 | 
				
			||||||
            contentYaml: '',
 | 
					 | 
				
			||||||
            currentPage: 1,
 | 
					 | 
				
			||||||
            pagesize: 10,
 | 
					 | 
				
			||||||
            pagesizeList: [10, 20, 30],
 | 
					 | 
				
			||||||
            searchInput: '',
 | 
					 | 
				
			||||||
            namespaceValue: 'default',
 | 
					 | 
				
			||||||
            namespaceList: [],
 | 
					 | 
				
			||||||
            namespaceListUrl: common.k8sNamespaceList,
 | 
					 | 
				
			||||||
            appLoading: false,
 | 
					 | 
				
			||||||
            namespaceTotal: 0,
 | 
					 | 
				
			||||||
            getNamespacesData: {
 | 
					 | 
				
			||||||
                url: common.k8sNamespaceList,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    filter_name: '',
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                    page: 1,
 | 
					 | 
				
			||||||
                    limit: 10,
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            namespaceDetail: {},
 | 
					 | 
				
			||||||
            getNamespaceDetailData: {
 | 
					 | 
				
			||||||
                url: common.k8sNamespaceDetail,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    namespace_name: '',
 | 
					 | 
				
			||||||
                    namespace: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            yamlDialog: false,
 | 
					 | 
				
			||||||
            updateNamespaceData: {
 | 
					 | 
				
			||||||
                url: common.k8sNamespaceUpdate,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                    content: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            delNamespaceData: {
 | 
					 | 
				
			||||||
                url: common.k8snamespaceDel,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    namespace_name: '',
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    methods: {
 | 
					 | 
				
			||||||
        transYaml(content) {
 | 
					 | 
				
			||||||
            return json2yaml.stringify(content)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        transObj(content) {
 | 
					 | 
				
			||||||
            return yaml2obj.load(content)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        onChange(val) {
 | 
					 | 
				
			||||||
            this.contentYaml = val
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleSizeChange(size) {
 | 
					 | 
				
			||||||
            this.pagesize = size;
 | 
					 | 
				
			||||||
            this.getNamespaces()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleCurrentChange(currentPage) {
 | 
					 | 
				
			||||||
            this.currentPage = currentPage;
 | 
					 | 
				
			||||||
            this.getNamespaces()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleClose(done) {
 | 
					 | 
				
			||||||
            this.$confirm('确认关闭?')
 | 
					 | 
				
			||||||
            .then(() => {
 | 
					 | 
				
			||||||
                done();
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(() => {});
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        ellipsis(value) {
 | 
					 | 
				
			||||||
            return value.length>15?value.substring(0,15)+'...':value
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        timeTrans(timestamp) {
 | 
					 | 
				
			||||||
            let date = new Date(new Date(timestamp).getTime() + 8 * 3600 * 1000)
 | 
					 | 
				
			||||||
            date = date.toJSON();
 | 
					 | 
				
			||||||
            date = date.substring(0, 19).replace('T', ' ')
 | 
					 | 
				
			||||||
            return date 
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        specTrans(str) {
 | 
					 | 
				
			||||||
            if ( str.indexOf('Ki') == -1 ) {
 | 
					 | 
				
			||||||
                return str
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            let num = str.slice(0,-2) / 1024 / 1024
 | 
					 | 
				
			||||||
            return num.toFixed(0)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getNamespaces() {
 | 
					 | 
				
			||||||
            this.getNamespacesData.params.filter_name = this.searchInput
 | 
					 | 
				
			||||||
            this.getNamespacesData.params.limit = this.pagesize
 | 
					 | 
				
			||||||
            this.getNamespacesData.params.page = this.currentPage
 | 
					 | 
				
			||||||
            httpClient.get(this.getNamespacesData.url, {params: this.getNamespacesData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.namespaceList = res.data.items
 | 
					 | 
				
			||||||
                this.namespaceTotal = res.data.total
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getNamespaceDetail(e) {
 | 
					 | 
				
			||||||
            this.getNamespaceDetailData.params.namespace_name = e.row.metadata.name
 | 
					 | 
				
			||||||
            this.getNamespaceDetailData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            httpClient.get(this.getNamespaceDetailData.url, {params: this.getNamespaceDetailData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.namespaceDetail = res.data
 | 
					 | 
				
			||||||
                this.contentYaml = this.transYaml(this.namespaceDetail)
 | 
					 | 
				
			||||||
                this.yamlDialog = true
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        updateNamespace() {
 | 
					 | 
				
			||||||
            let content = JSON.stringify(this.transObj(this.contentYaml))
 | 
					 | 
				
			||||||
            this.updateNamespaceData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            this.updateNamespaceData.params.content = content
 | 
					 | 
				
			||||||
            httpClient.put(this.updateNamespaceData.url, this.updateNamespaceData.params)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.yamlDialog = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        delNamespace(e) {
 | 
					 | 
				
			||||||
            this.delNamespaceData.params.namespace_name = e.row.metadata.name
 | 
					 | 
				
			||||||
            this.delNamespaceData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            httpClient.delete(this.delNamespaceData.url, {data: this.delNamespaceData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.getNamespaces()
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleConfirm(obj, operateName, fn) {
 | 
					 | 
				
			||||||
            this.confirmContent = '确认继续 ' + operateName + ' 操作吗?'
 | 
					 | 
				
			||||||
            this.$confirm(this.confirmContent,'提示',{
 | 
					 | 
				
			||||||
                confirmButtonText: '确定',
 | 
					 | 
				
			||||||
                cancelButtonText: '取消',
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .then(() => {
 | 
					 | 
				
			||||||
                fn(obj)
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            .catch(() => {
 | 
					 | 
				
			||||||
                this.$message.info({
 | 
					 | 
				
			||||||
                    message: '已取消操作'
 | 
					 | 
				
			||||||
                })          
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    beforeMount() {
 | 
					 | 
				
			||||||
        this.getNamespaces()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style scoped>
 | 
					 | 
				
			||||||
    .namespace-head-card,.namespace-body-card {
 | 
					 | 
				
			||||||
        border-radius: 1px;
 | 
					 | 
				
			||||||
        margin-bottom: 5px;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .namespace-head-search {
 | 
					 | 
				
			||||||
        width:160px;
 | 
					 | 
				
			||||||
        margin-right:10px; 
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .namespace-body-namespacename {
 | 
					 | 
				
			||||||
        color: #4795EE;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .namespace-body-namespacename:hover {
 | 
					 | 
				
			||||||
        color: rgb(84, 138, 238);
 | 
					 | 
				
			||||||
        cursor: pointer;
 | 
					 | 
				
			||||||
        font-weight: bold;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .success-status {
 | 
					 | 
				
			||||||
        color: rgb(27, 202, 21);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .warning-status {
 | 
					 | 
				
			||||||
        color: rgb(233, 200, 16);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .error-status {
 | 
					 | 
				
			||||||
        color: rgb(226, 23, 23);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
@ -1,319 +0,0 @@
 | 
				
			|||||||
<template>
 | 
					 | 
				
			||||||
    <div class="node">
 | 
					 | 
				
			||||||
        <el-row>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="node-head-card" shadow="never" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                        <el-row>
 | 
					 | 
				
			||||||
                            <el-col :span="2">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-button disabled style="border-radius:2px;" icon="Edit" type="primary">创建</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                            <el-col :span="6">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-input class="node-head-search" clearable placeholder="请输入" v-model="searchInput"></el-input>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Search" type="primary" plain @click="getNodes()">搜索</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                            <el-col :span="2" :offset="14">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Refresh" plain @click="getNodes()">刷新</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                        </el-row>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="node-body-card" shadow="never" :body-style="{padding:'5px'}">
 | 
					 | 
				
			||||||
                        <el-table
 | 
					 | 
				
			||||||
                        style="width:100%;font-size:12px;margin-bottom:10px;"
 | 
					 | 
				
			||||||
                        :data="nodeList"
 | 
					 | 
				
			||||||
                        v-loading="appLoading">
 | 
					 | 
				
			||||||
                            <el-table-column width="20"></el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=left label="Node名">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <p class="node-body-nodename">{{ scope.row.metadata.name }}</p>
 | 
					 | 
				
			||||||
                                    <p class="node-body-ip">{{ scope.row.status.addresses[0].address }}</p>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="规格">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-tag type="warning">{{ scope.row.status.capacity.cpu }}核{{ specTrans(scope.row.status.capacity.memory) }}G</el-tag>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="POD-CIDR">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <span>{{ scope.row.spec.podCIDR }} </span>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="版本">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <span>{{ scope.row.status.nodeInfo.kubeletVersion }} </span>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center min-width="100" label="创建时间">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-tag type="info">{{ timeTrans(scope.row.metadata.creationTimestamp) }} </el-tag>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="操作" min-width="120">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-button size="small" style="border-radius:2px;" icon="Edit" type="primary" plain @click="getNodeDetail(scope)">YAML</el-button>
 | 
					 | 
				
			||||||
                                    <el-button disabled size="small" style="border-radius:2px;" icon="Document" type="warning" plain @click="handleConfirm(scope, '删除', delIngress)">详情</el-button>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                        </el-table>
 | 
					 | 
				
			||||||
                        <el-pagination
 | 
					 | 
				
			||||||
                        class="node-body-pagination"
 | 
					 | 
				
			||||||
                        background
 | 
					 | 
				
			||||||
                        @size-change="handleSizeChange"
 | 
					 | 
				
			||||||
                        @current-change="handleCurrentChange"
 | 
					 | 
				
			||||||
                        :current-page="currentPage"
 | 
					 | 
				
			||||||
                        :page-sizes="pagesizeList"
 | 
					 | 
				
			||||||
                        :page-size="pagesize"
 | 
					 | 
				
			||||||
                        layout="total, sizes, prev, pager, next, jumper"
 | 
					 | 
				
			||||||
                        :total="nodeTotal">
 | 
					 | 
				
			||||||
                        </el-pagination>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
        </el-row>
 | 
					 | 
				
			||||||
        <el-dialog title="YAML信息" v-model="yamlDialog" width="45%" top="5%">
 | 
					 | 
				
			||||||
            <codemirror
 | 
					 | 
				
			||||||
                :value="contentYaml"
 | 
					 | 
				
			||||||
                border
 | 
					 | 
				
			||||||
                :options="cmOptions"
 | 
					 | 
				
			||||||
                height="500"
 | 
					 | 
				
			||||||
                style="font-size:14px;"
 | 
					 | 
				
			||||||
                @change="onChange"
 | 
					 | 
				
			||||||
            ></codemirror>
 | 
					 | 
				
			||||||
            <template #footer>
 | 
					 | 
				
			||||||
                <span class="dialog-footer">
 | 
					 | 
				
			||||||
                    <el-button @click="yamlDialog = false">取 消</el-button>
 | 
					 | 
				
			||||||
                    <el-button disabled type="primary" @click="updateNode()">更 新</el-button>
 | 
					 | 
				
			||||||
                </span>
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
        </el-dialog>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script>
 | 
					 | 
				
			||||||
import common from "../common/Config";
 | 
					 | 
				
			||||||
import httpClient from '../../utils/request';
 | 
					 | 
				
			||||||
import yaml2obj from 'js-yaml';
 | 
					 | 
				
			||||||
import json2yaml from 'json2yaml';
 | 
					 | 
				
			||||||
export default {
 | 
					 | 
				
			||||||
    data() {
 | 
					 | 
				
			||||||
        return {
 | 
					 | 
				
			||||||
            cmOptions: common.cmOptions,
 | 
					 | 
				
			||||||
            contentYaml: '',
 | 
					 | 
				
			||||||
            currentPage: 1,
 | 
					 | 
				
			||||||
            pagesize: 10,
 | 
					 | 
				
			||||||
            pagesizeList: [10, 20, 30],
 | 
					 | 
				
			||||||
            searchInput: '',
 | 
					 | 
				
			||||||
            namespaceValue: 'default',
 | 
					 | 
				
			||||||
            namespaceList: [],
 | 
					 | 
				
			||||||
            namespaceListUrl: common.k8sNamespaceList,
 | 
					 | 
				
			||||||
            appLoading: false,
 | 
					 | 
				
			||||||
            nodeList: [],
 | 
					 | 
				
			||||||
            nodeTotal: 0,
 | 
					 | 
				
			||||||
            getNodesData: {
 | 
					 | 
				
			||||||
                url: common.k8sNodeList,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    filter_name: '',
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                    page: '',
 | 
					 | 
				
			||||||
                    limit: '',
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            nodeDetail: {},
 | 
					 | 
				
			||||||
            getNodeDetailData: {
 | 
					 | 
				
			||||||
                url: common.k8sNodeDetail,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    node_name: '',
 | 
					 | 
				
			||||||
                    namespace: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            yamlDialog: false,
 | 
					 | 
				
			||||||
            updateNodeData: {
 | 
					 | 
				
			||||||
                url: common.k8sNodeUpdate,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                    content: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            delNodeData: {
 | 
					 | 
				
			||||||
                url: common.k8snodeDel,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    node_name: '',
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    methods: {
 | 
					 | 
				
			||||||
        transYaml(content) {
 | 
					 | 
				
			||||||
            return json2yaml.stringify(content)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        transObj(content) {
 | 
					 | 
				
			||||||
            return yaml2obj.load(content)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        onChange(val) {
 | 
					 | 
				
			||||||
            this.contentYaml = val
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleSizeChange(size) {
 | 
					 | 
				
			||||||
            this.pagesize = size;
 | 
					 | 
				
			||||||
            this.getNodes()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleCurrentChange(currentPage) {
 | 
					 | 
				
			||||||
            this.currentPage = currentPage;
 | 
					 | 
				
			||||||
            this.getNodes()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleClose(done) {
 | 
					 | 
				
			||||||
            this.$confirm('确认关闭?')
 | 
					 | 
				
			||||||
            .then(() => {
 | 
					 | 
				
			||||||
                done();
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(() => {});
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        ellipsis(value) {
 | 
					 | 
				
			||||||
            return value.length>15?value.substring(0,15)+'...':value
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        timeTrans(timestamp) {
 | 
					 | 
				
			||||||
            let date = new Date(new Date(timestamp).getTime() + 8 * 3600 * 1000)
 | 
					 | 
				
			||||||
            date = date.toJSON();
 | 
					 | 
				
			||||||
            date = date.substring(0, 19).replace('T', ' ')
 | 
					 | 
				
			||||||
            return date 
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        specTrans(str) {
 | 
					 | 
				
			||||||
            if ( str.indexOf('Ki') == -1 ) {
 | 
					 | 
				
			||||||
                return str
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            let num = str.slice(0,-2) / 1024 / 1024
 | 
					 | 
				
			||||||
            return num.toFixed(0)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getNamespaces() {
 | 
					 | 
				
			||||||
            httpClient.get(this.namespaceListUrl)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.namespaceList = res.data.items
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getNodes() {
 | 
					 | 
				
			||||||
            this.appLoading = true
 | 
					 | 
				
			||||||
            this.getNodesData.params.filter_name = this.searchInput
 | 
					 | 
				
			||||||
            this.getNodesData.params.page = this.currentPage
 | 
					 | 
				
			||||||
            this.getNodesData.params.limit = this.pagesize
 | 
					 | 
				
			||||||
            httpClient.get(this.getNodesData.url, {params: this.getNodesData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.nodeList = res.data.items
 | 
					 | 
				
			||||||
                this.nodeTotal = res.data.total
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.appLoading = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getNodeDetail(e) {
 | 
					 | 
				
			||||||
            this.getNodeDetailData.params.node_name = e.row.metadata.name
 | 
					 | 
				
			||||||
            this.getNodeDetailData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            httpClient.get(this.getNodeDetailData.url, {params: this.getNodeDetailData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.nodeDetail = res.data
 | 
					 | 
				
			||||||
                this.contentYaml = this.transYaml(this.nodeDetail)
 | 
					 | 
				
			||||||
                this.yamlDialog = true
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        updateNode() {
 | 
					 | 
				
			||||||
            let content = JSON.stringify(this.transObj(this.contentYaml))
 | 
					 | 
				
			||||||
            this.updateNodeData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            this.updateNodeData.params.content = content
 | 
					 | 
				
			||||||
            httpClient.put(this.updateNodeData.url, this.updateNodeData.params)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.yamlDialog = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        delNode(e) {
 | 
					 | 
				
			||||||
            this.delNodeData.params.node_name = e.row.metadata.name
 | 
					 | 
				
			||||||
            this.delNodeData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            httpClient.delete(this.delNodeData.url, {data: this.delNodeData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.getNodes()
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleConfirm(obj, operateName, fn) {
 | 
					 | 
				
			||||||
            this.confirmContent = '确认继续 ' + operateName + ' 操作吗?'
 | 
					 | 
				
			||||||
            this.$confirm(this.confirmContent,'提示',{
 | 
					 | 
				
			||||||
                confirmButtonText: '确定',
 | 
					 | 
				
			||||||
                cancelButtonText: '取消',
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .then(() => {
 | 
					 | 
				
			||||||
                fn(obj)
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            .catch(() => {
 | 
					 | 
				
			||||||
                this.$message.info({
 | 
					 | 
				
			||||||
                    message: '已取消操作'
 | 
					 | 
				
			||||||
                })          
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    beforeMount() {
 | 
					 | 
				
			||||||
        this.getNodes()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style scoped>
 | 
					 | 
				
			||||||
    .node-head-card,.node-body-card {
 | 
					 | 
				
			||||||
        border-radius: 1px;
 | 
					 | 
				
			||||||
        margin-bottom: 5px;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .node-head-search {
 | 
					 | 
				
			||||||
        width:160px;
 | 
					 | 
				
			||||||
        margin-right:10px; 
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .node-body-nodename {
 | 
					 | 
				
			||||||
        margin: 0px;
 | 
					 | 
				
			||||||
        color: #4795EE;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .node-body-ip {
 | 
					 | 
				
			||||||
        margin: 0px;
 | 
					 | 
				
			||||||
        color: rgb(145, 145, 145);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .node-body-nodename:hover {
 | 
					 | 
				
			||||||
        color: rgb(84, 138, 238);
 | 
					 | 
				
			||||||
        cursor: pointer;
 | 
					 | 
				
			||||||
        font-weight: bold;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
@ -1,316 +0,0 @@
 | 
				
			|||||||
<template>
 | 
					 | 
				
			||||||
    <div class="pv">
 | 
					 | 
				
			||||||
        <el-row>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="pv-head-card" shadow="never" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                        <el-row>
 | 
					 | 
				
			||||||
                            <el-col :span="2">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-button disabled style="border-radius:2px;" icon="Edit" type="primary">创建</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                            <el-col :span="6">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-input class="pv-head-search" clearable placeholder="请输入" v-model="searchInput"></el-input>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Search" type="primary" plain @click="getPvs()">搜索</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                            <el-col :span="2" :offset="14">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Refresh" plain @click="getPvs()">刷新</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                        </el-row>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="pv-body-card" shadow="never" :body-style="{padding:'5px'}">
 | 
					 | 
				
			||||||
                        <el-table
 | 
					 | 
				
			||||||
                        style="width:100%;font-size:12px;margin-bottom:10px;"
 | 
					 | 
				
			||||||
                        :data="pvList"
 | 
					 | 
				
			||||||
                        v-loading="appLoading">
 | 
					 | 
				
			||||||
                            <el-table-column width="20"></el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=left label="PV名">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <a class="pv-body-pvname">{{ scope.row.metadata.name }}</a>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="状态">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <span :class="[scope.row.status.phase === 'Bound' ? 'success-status' : 'error-status']">{{ scope.row.status.phase }}</span>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center prop="spec.accessModes[0]" label="访问模式"></el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center prop="spec.capacity.storage" label="容量"></el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center prop="spec.claimRef.name" label="PVC"></el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center min-width="100" label="创建时间">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-tag type="info">{{ timeTrans(scope.row.metadata.creationTimestamp) }} </el-tag>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="操作" min-width="120">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-button size="small" style="border-radius:2px;" icon="Edit" type="primary" plain @click="getPvDetail(scope)">YAML</el-button>
 | 
					 | 
				
			||||||
                                    <el-button size="small" style="border-radius:2px;" icon="Delete" type="danger" @click="handleConfirm(scope, '删除', delPv)">删除</el-button>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                        </el-table>
 | 
					 | 
				
			||||||
                        <el-pagination
 | 
					 | 
				
			||||||
                        class="pv-body-pagination"
 | 
					 | 
				
			||||||
                        background
 | 
					 | 
				
			||||||
                        @size-change="handleSizeChange"
 | 
					 | 
				
			||||||
                        @current-change="handleCurrentChange"
 | 
					 | 
				
			||||||
                        :current-page="currentPage"
 | 
					 | 
				
			||||||
                        :page-sizes="pagesizeList"
 | 
					 | 
				
			||||||
                        :page-size="pagesize"
 | 
					 | 
				
			||||||
                        layout="total, sizes, prev, pager, next, jumper"
 | 
					 | 
				
			||||||
                        :total="pvTotal">
 | 
					 | 
				
			||||||
                        </el-pagination>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
        </el-row>
 | 
					 | 
				
			||||||
        <el-dialog title="YAML信息" v-model="yamlDialog" width="45%" top="5%">
 | 
					 | 
				
			||||||
            <codemirror
 | 
					 | 
				
			||||||
                :value="contentYaml"
 | 
					 | 
				
			||||||
                border
 | 
					 | 
				
			||||||
                :options="cmOptions"
 | 
					 | 
				
			||||||
                height="500"
 | 
					 | 
				
			||||||
                style="font-size:14px;"
 | 
					 | 
				
			||||||
                @change="onChange"
 | 
					 | 
				
			||||||
            ></codemirror>
 | 
					 | 
				
			||||||
            <template #footer>
 | 
					 | 
				
			||||||
                <span class="dialog-footer">
 | 
					 | 
				
			||||||
                    <el-button @click="yamlDialog = false">取 消</el-button>
 | 
					 | 
				
			||||||
                    <el-button disabled type="primary" @click="updatePv()">更 新</el-button>
 | 
					 | 
				
			||||||
                </span>
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
        </el-dialog>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script>
 | 
					 | 
				
			||||||
import common from "../common/Config";
 | 
					 | 
				
			||||||
import httpClient from '../../utils/request';
 | 
					 | 
				
			||||||
import yaml2obj from 'js-yaml';
 | 
					 | 
				
			||||||
import json2yaml from 'json2yaml';
 | 
					 | 
				
			||||||
export default {
 | 
					 | 
				
			||||||
    data() {
 | 
					 | 
				
			||||||
        return {
 | 
					 | 
				
			||||||
            cmOptions: common.cmOptions,
 | 
					 | 
				
			||||||
            contentYaml: '',
 | 
					 | 
				
			||||||
            currentPage: 1,
 | 
					 | 
				
			||||||
            pagesize: 10,
 | 
					 | 
				
			||||||
            pagesizeList: [10, 20, 30],
 | 
					 | 
				
			||||||
            searchInput: '',
 | 
					 | 
				
			||||||
            namespaceValue: 'default',
 | 
					 | 
				
			||||||
            namespaceList: [],
 | 
					 | 
				
			||||||
            namespaceListUrl: common.k8sNamespaceList,
 | 
					 | 
				
			||||||
            appLoading: false,
 | 
					 | 
				
			||||||
            pvList: [],
 | 
					 | 
				
			||||||
            pvTotal: 0,
 | 
					 | 
				
			||||||
            getPvsData: {
 | 
					 | 
				
			||||||
                url: common.k8sPvList,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    filter_name: '',
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                    page: '',
 | 
					 | 
				
			||||||
                    limit: '',
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            pvDetail: {},
 | 
					 | 
				
			||||||
            getPvDetailData: {
 | 
					 | 
				
			||||||
                url: common.k8sPvDetail,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    pv_name: '',
 | 
					 | 
				
			||||||
                    namespace: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            yamlDialog: false,
 | 
					 | 
				
			||||||
            updatePvData: {
 | 
					 | 
				
			||||||
                url: common.k8sPvUpdate,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                    content: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            delPvData: {
 | 
					 | 
				
			||||||
                url: common.k8spvDel,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    pv_name: '',
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    methods: {
 | 
					 | 
				
			||||||
        transYaml(content) {
 | 
					 | 
				
			||||||
            return json2yaml.stringify(content)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        transObj(content) {
 | 
					 | 
				
			||||||
            return yaml2obj.load(content)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        onChange(val) {
 | 
					 | 
				
			||||||
            this.contentYaml = val
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleSizeChange(size) {
 | 
					 | 
				
			||||||
            this.pagesize = size;
 | 
					 | 
				
			||||||
            this.getPvs()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleCurrentChange(currentPage) {
 | 
					 | 
				
			||||||
            this.currentPage = currentPage;
 | 
					 | 
				
			||||||
            this.getPvs()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleClose(done) {
 | 
					 | 
				
			||||||
            this.$confirm('确认关闭?')
 | 
					 | 
				
			||||||
            .then(() => {
 | 
					 | 
				
			||||||
                done();
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(() => {});
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        ellipsis(value) {
 | 
					 | 
				
			||||||
            return value.length>15?value.substring(0,15)+'...':value
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        timeTrans(timestamp) {
 | 
					 | 
				
			||||||
            let date = new Date(new Date(timestamp).getTime() + 8 * 3600 * 1000)
 | 
					 | 
				
			||||||
            date = date.toJSON();
 | 
					 | 
				
			||||||
            date = date.substring(0, 19).replace('T', ' ')
 | 
					 | 
				
			||||||
            return date 
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        specTrans(str) {
 | 
					 | 
				
			||||||
            if ( str.indexOf('Ki') == -1 ) {
 | 
					 | 
				
			||||||
                return str
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            let num = str.slice(0,-2) / 1024 / 1024
 | 
					 | 
				
			||||||
            return num.toFixed(0)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getNamespaces() {
 | 
					 | 
				
			||||||
            httpClient.get(this.namespaceListUrl)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.namespaceList = res.data.items
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getPvs() {
 | 
					 | 
				
			||||||
            this.appLoading = true
 | 
					 | 
				
			||||||
            this.getPvsData.params.filter_name = this.searchInput
 | 
					 | 
				
			||||||
            this.getPvsData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            this.getPvsData.params.page = this.currentPage
 | 
					 | 
				
			||||||
            this.getPvsData.params.limit = this.pagesize
 | 
					 | 
				
			||||||
            httpClient.get(this.getPvsData.url, {params: this.getPvsData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.pvList = res.data.items
 | 
					 | 
				
			||||||
                this.pvTotal = res.data.total
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.appLoading = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getPvDetail(e) {
 | 
					 | 
				
			||||||
            this.getPvDetailData.params.pv_name = e.row.metadata.name
 | 
					 | 
				
			||||||
            this.getPvDetailData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            httpClient.get(this.getPvDetailData.url, {params: this.getPvDetailData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.pvDetail = res.data
 | 
					 | 
				
			||||||
                this.contentYaml = this.transYaml(this.pvDetail)
 | 
					 | 
				
			||||||
                this.yamlDialog = true
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        updatePv() {
 | 
					 | 
				
			||||||
            let content = JSON.stringify(this.transObj(this.contentYaml))
 | 
					 | 
				
			||||||
            this.updatePvData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            this.updatePvData.params.content = content
 | 
					 | 
				
			||||||
            httpClient.put(this.updatePvData.url, this.updatePvData.params)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.yamlDialog = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        delPv(e) {
 | 
					 | 
				
			||||||
            this.delPvData.params.pv_name = e.row.metadata.name
 | 
					 | 
				
			||||||
            this.delPvData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            httpClient.delete(this.delPvData.url, {data: this.delPvData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.getPvs()
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleConfirm(obj, operateName, fn) {
 | 
					 | 
				
			||||||
            this.confirmContent = '确认继续 ' + operateName + ' 操作吗?'
 | 
					 | 
				
			||||||
            this.$confirm(this.confirmContent,'提示',{
 | 
					 | 
				
			||||||
                confirmButtonText: '确定',
 | 
					 | 
				
			||||||
                cancelButtonText: '取消',
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .then(() => {
 | 
					 | 
				
			||||||
                fn(obj)
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            .catch(() => {
 | 
					 | 
				
			||||||
                this.$message.info({
 | 
					 | 
				
			||||||
                    message: '已取消操作'
 | 
					 | 
				
			||||||
                })          
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    beforeMount() {
 | 
					 | 
				
			||||||
        this.getPvs()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style scoped>
 | 
					 | 
				
			||||||
    .pv-head-card,.pv-body-card {
 | 
					 | 
				
			||||||
        border-radius: 1px;
 | 
					 | 
				
			||||||
        margin-bottom: 5px;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .pv-head-search {
 | 
					 | 
				
			||||||
        width:160px;
 | 
					 | 
				
			||||||
        margin-right:10px; 
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .pv-body-pvname {
 | 
					 | 
				
			||||||
        color: #4795EE;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .pv-body-pvname:hover {
 | 
					 | 
				
			||||||
        color: rgb(84, 138, 238);
 | 
					 | 
				
			||||||
        cursor: pointer;
 | 
					 | 
				
			||||||
        font-weight: bold;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .success-status {
 | 
					 | 
				
			||||||
        color: rgb(27, 202, 21);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .warning-status {
 | 
					 | 
				
			||||||
        color: rgb(233, 200, 16);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .error-status {
 | 
					 | 
				
			||||||
        color: rgb(226, 23, 23);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
@ -1,369 +0,0 @@
 | 
				
			|||||||
<template>
 | 
					 | 
				
			||||||
    <div class="pvc">
 | 
					 | 
				
			||||||
        <el-row>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="pvc-head-card" shadow="never" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                        <el-row>
 | 
					 | 
				
			||||||
                            <el-col :span="6">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <span>命名空间: </span>
 | 
					 | 
				
			||||||
                                    <el-select v-model="namespaceValue" filterable placeholder="请选择">
 | 
					 | 
				
			||||||
                                        <el-option
 | 
					 | 
				
			||||||
                                        v-for="(item, index) in namespaceList"
 | 
					 | 
				
			||||||
                                        :key="index"
 | 
					 | 
				
			||||||
                                        :label="item.metadata.name"
 | 
					 | 
				
			||||||
                                        :value="item.metadata.name">
 | 
					 | 
				
			||||||
                                        </el-option>
 | 
					 | 
				
			||||||
                                    </el-select>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                            <el-col :span="2" :offset="16">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Refresh" plain @click="getPvcs()">刷新</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                        </el-row>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="pvc-head-card" shadow="never" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                        <el-row>
 | 
					 | 
				
			||||||
                            <el-col :span="2">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-button disabled style="border-radius:2px;" icon="Edit" type="primary">创建</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                            <el-col :span="6">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-input class="pvc-head-search" clearable placeholder="请输入" v-model="searchInput"></el-input>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Search" type="primary" plain @click="getPvcs()">搜索</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                        </el-row>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="pvc-body-card" shadow="never" :body-style="{padding:'5px'}">
 | 
					 | 
				
			||||||
                        <el-table
 | 
					 | 
				
			||||||
                        style="width:100%;font-size:12px;margin-bottom:10px;"
 | 
					 | 
				
			||||||
                        :data="pvcList"
 | 
					 | 
				
			||||||
                        v-loading="appLoading">
 | 
					 | 
				
			||||||
                            <el-table-column width="20"></el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=left label="PVC名">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <a class="pvc-body-pvcname">{{ scope.row.metadata.name }}</a>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="标签">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <div v-for="(val, key) in scope.row.metadata.labels" :key="key">
 | 
					 | 
				
			||||||
                                        <el-popover
 | 
					 | 
				
			||||||
                                            placement="right"
 | 
					 | 
				
			||||||
                                            :width="200"
 | 
					 | 
				
			||||||
                                            trigger="hover"
 | 
					 | 
				
			||||||
                                            :content="key + ':' + val">
 | 
					 | 
				
			||||||
                                            <template #reference>
 | 
					 | 
				
			||||||
                                                <el-tag style="margin-bottom: 5px" type="warning">{{ ellipsis(key + ":" + val) }}</el-tag>
 | 
					 | 
				
			||||||
                                            </template>
 | 
					 | 
				
			||||||
                                        </el-popover>
 | 
					 | 
				
			||||||
                                    </div>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="状态">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <span :class="[scope.row.status.phase === 'Bound' ? 'success-status' : 'error-status']">{{ scope.row.status.phase }}</span>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center prop="status.capacity.storage" label="容量">
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center prop="status.accessModes[0]" label="访问模式">
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center prop="spec.storageClassName" label="StorageClass">
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center min-width="100" label="创建时间">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-tag type="info">{{ timeTrans(scope.row.metadata.creationTimestamp) }} </el-tag>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="操作" width="200">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-button size="small" style="border-radius:2px;" icon="Edit" type="primary" plain @click="getPvcDetail(scope)">YAML</el-button>
 | 
					 | 
				
			||||||
                                    <el-button size="small" style="border-radius:2px;" icon="Delete" type="danger" @click="handleConfirm(scope, '删除', delPvc)">删除</el-button>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                        </el-table>
 | 
					 | 
				
			||||||
                        <el-pagination
 | 
					 | 
				
			||||||
                        class="pvc-body-pagination"
 | 
					 | 
				
			||||||
                        background
 | 
					 | 
				
			||||||
                        @size-change="handleSizeChange"
 | 
					 | 
				
			||||||
                        @current-change="handleCurrentChange"
 | 
					 | 
				
			||||||
                        :current-page="currentPage"
 | 
					 | 
				
			||||||
                        :page-sizes="pagesizeList"
 | 
					 | 
				
			||||||
                        :page-size="pagesize"
 | 
					 | 
				
			||||||
                        layout="total, sizes, prev, pager, next, jumper"
 | 
					 | 
				
			||||||
                        :total="pvcTotal">
 | 
					 | 
				
			||||||
                        </el-pagination>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
        </el-row>
 | 
					 | 
				
			||||||
        <el-dialog title="YAML信息" v-model="yamlDialog" width="45%" top="5%">
 | 
					 | 
				
			||||||
            <codemirror
 | 
					 | 
				
			||||||
                :value="contentYaml"
 | 
					 | 
				
			||||||
                border
 | 
					 | 
				
			||||||
                :options="cmOptions"
 | 
					 | 
				
			||||||
                height="500"
 | 
					 | 
				
			||||||
                style="font-size:14px;"
 | 
					 | 
				
			||||||
                @change="onChange"
 | 
					 | 
				
			||||||
            ></codemirror>
 | 
					 | 
				
			||||||
            <template #footer>
 | 
					 | 
				
			||||||
                <span class="dialog-footer">
 | 
					 | 
				
			||||||
                    <el-button @click="yamlDialog = false">取 消</el-button>
 | 
					 | 
				
			||||||
                    <el-button type="primary" @click="updatePvc()">更 新</el-button>
 | 
					 | 
				
			||||||
                </span>
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
        </el-dialog>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script>
 | 
					 | 
				
			||||||
import common from "../common/Config";
 | 
					 | 
				
			||||||
import httpClient from '../../utils/request';
 | 
					 | 
				
			||||||
import yaml2obj from 'js-yaml';
 | 
					 | 
				
			||||||
import json2yaml from 'json2yaml';
 | 
					 | 
				
			||||||
export default {
 | 
					 | 
				
			||||||
    data() {
 | 
					 | 
				
			||||||
        return {
 | 
					 | 
				
			||||||
            cmOptions: common.cmOptions,
 | 
					 | 
				
			||||||
            contentYaml: '',
 | 
					 | 
				
			||||||
            currentPage: 1,
 | 
					 | 
				
			||||||
            pagesize: 10,
 | 
					 | 
				
			||||||
            pagesizeList: [10, 20, 30],
 | 
					 | 
				
			||||||
            searchInput: '',
 | 
					 | 
				
			||||||
            namespaceValue: 'default',
 | 
					 | 
				
			||||||
            namespaceList: [],
 | 
					 | 
				
			||||||
            namespaceListUrl: common.k8sNamespaceList,
 | 
					 | 
				
			||||||
            appLoading: false,
 | 
					 | 
				
			||||||
            pvcList: [],
 | 
					 | 
				
			||||||
            pvcTotal: 0,
 | 
					 | 
				
			||||||
            getPvcsData: {
 | 
					 | 
				
			||||||
                url: common.k8sPvcList,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    filter_name: '',
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                    page: '',
 | 
					 | 
				
			||||||
                    limit: '',
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            pvcDetail: {},
 | 
					 | 
				
			||||||
            getPvcDetailData: {
 | 
					 | 
				
			||||||
                url: common.k8sPvcDetail,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    pvc_name: '',
 | 
					 | 
				
			||||||
                    namespace: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            yamlDialog: false,
 | 
					 | 
				
			||||||
            updatePvcData: {
 | 
					 | 
				
			||||||
                url: common.k8sPvcUpdate,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                    content: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            delPvcData: {
 | 
					 | 
				
			||||||
                url: common.k8spvcDel,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    pvc_name: '',
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    methods: {
 | 
					 | 
				
			||||||
        transYaml(content) {
 | 
					 | 
				
			||||||
            return json2yaml.stringify(content)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        transObj(content) {
 | 
					 | 
				
			||||||
            return yaml2obj.load(content)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        onChange(val) {
 | 
					 | 
				
			||||||
            this.contentYaml = val
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleSizeChange(size) {
 | 
					 | 
				
			||||||
            this.pagesize = size;
 | 
					 | 
				
			||||||
            this.getPvcs()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleCurrentChange(currentPage) {
 | 
					 | 
				
			||||||
            this.currentPage = currentPage;
 | 
					 | 
				
			||||||
            this.getPvcs()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleClose(done) {
 | 
					 | 
				
			||||||
            this.$confirm('确认关闭?')
 | 
					 | 
				
			||||||
            .then(() => {
 | 
					 | 
				
			||||||
                done();
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(() => {});
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        ellipsis(value) {
 | 
					 | 
				
			||||||
            return value.length>15?value.substring(0,15)+'...':value
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        timeTrans(timestamp) {
 | 
					 | 
				
			||||||
            let date = new Date(new Date(timestamp).getTime() + 8 * 3600 * 1000)
 | 
					 | 
				
			||||||
            date = date.toJSON();
 | 
					 | 
				
			||||||
            date = date.substring(0, 19).replace('T', ' ')
 | 
					 | 
				
			||||||
            return date 
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        restartTotal(e) {
 | 
					 | 
				
			||||||
            let index, sum = 0
 | 
					 | 
				
			||||||
            let containerStatuses = e.row.status.containerStatuses
 | 
					 | 
				
			||||||
            for ( index in containerStatuses) {
 | 
					 | 
				
			||||||
                sum = sum + containerStatuses[index].restartCount 
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return sum
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getNamespaces() {
 | 
					 | 
				
			||||||
            httpClient.get(this.namespaceListUrl)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.namespaceList = res.data.items
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getPvcs() {
 | 
					 | 
				
			||||||
            this.appLoading = true
 | 
					 | 
				
			||||||
            this.getPvcsData.params.filter_name = this.searchInput
 | 
					 | 
				
			||||||
            this.getPvcsData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            this.getPvcsData.params.page = this.currentPage
 | 
					 | 
				
			||||||
            this.getPvcsData.params.limit = this.pagesize
 | 
					 | 
				
			||||||
            httpClient.get(this.getPvcsData.url, {params: this.getPvcsData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.pvcList = res.data.items
 | 
					 | 
				
			||||||
                this.pvcTotal = res.data.total
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.appLoading = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getPvcDetail(e) {
 | 
					 | 
				
			||||||
            this.getPvcDetailData.params.pvc_name = e.row.metadata.name
 | 
					 | 
				
			||||||
            this.getPvcDetailData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            httpClient.get(this.getPvcDetailData.url, {params: this.getPvcDetailData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.pvcDetail = res.data
 | 
					 | 
				
			||||||
                this.contentYaml = this.transYaml(this.pvcDetail)
 | 
					 | 
				
			||||||
                this.yamlDialog = true
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        updatePvc() {
 | 
					 | 
				
			||||||
            let content = JSON.stringify(this.transObj(this.contentYaml))
 | 
					 | 
				
			||||||
            this.updatePvcData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            this.updatePvcData.params.content = content
 | 
					 | 
				
			||||||
            httpClient.put(this.updatePvcData.url, this.updatePvcData.params)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.yamlDialog = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        delPvc(e) {
 | 
					 | 
				
			||||||
            this.delPvcData.params.pvc_name = e.row.metadata.name
 | 
					 | 
				
			||||||
            this.delPvcData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            httpClient.delete(this.delPvcData.url, {data: this.delPvcData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.getPvcs()
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleConfirm(obj, operateName, fn) {
 | 
					 | 
				
			||||||
            this.confirmContent = '确认继续 ' + operateName + ' 操作吗?'
 | 
					 | 
				
			||||||
            this.$confirm(this.confirmContent,'提示',{
 | 
					 | 
				
			||||||
                confirmButtonText: '确定',
 | 
					 | 
				
			||||||
                cancelButtonText: '取消',
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .then(() => {
 | 
					 | 
				
			||||||
                fn(obj)
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            .catch(() => {
 | 
					 | 
				
			||||||
                this.$message.info({
 | 
					 | 
				
			||||||
                    message: '已取消操作'
 | 
					 | 
				
			||||||
                })          
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    watch: {
 | 
					 | 
				
			||||||
        namespaceValue: {
 | 
					 | 
				
			||||||
            handler() {
 | 
					 | 
				
			||||||
                localStorage.setItem('namespace', this.namespaceValue)
 | 
					 | 
				
			||||||
                this.currentPage = 1
 | 
					 | 
				
			||||||
                this.getPvcs()
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    beforeMount() {
 | 
					 | 
				
			||||||
        if (localStorage.getItem('namespace') !== undefined && localStorage.getItem('namespace') !== null) {
 | 
					 | 
				
			||||||
            this.namespaceValue = localStorage.getItem('namespace')
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        this.getNamespaces()
 | 
					 | 
				
			||||||
        this.getPvcs()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style scoped>
 | 
					 | 
				
			||||||
    .pvc-head-card,.pvc-body-card {
 | 
					 | 
				
			||||||
        border-radius: 1px;
 | 
					 | 
				
			||||||
        margin-bottom: 5px;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .pvc-head-search {
 | 
					 | 
				
			||||||
        width:160px;
 | 
					 | 
				
			||||||
        margin-right:10px; 
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .pvc-body-pvcname {
 | 
					 | 
				
			||||||
        color: #4795EE;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .pvc-body-pvcname:hover {
 | 
					 | 
				
			||||||
        color: rgb(84, 138, 238);
 | 
					 | 
				
			||||||
        cursor: pointer;
 | 
					 | 
				
			||||||
        font-weight: bold;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .success-status {
 | 
					 | 
				
			||||||
        color: rgb(27, 202, 21);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .warning-status {
 | 
					 | 
				
			||||||
        color: rgb(233, 200, 16);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .error-status {
 | 
					 | 
				
			||||||
        color: rgb(226, 23, 23);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
@ -1,644 +0,0 @@
 | 
				
			|||||||
<template>
 | 
					 | 
				
			||||||
    <div class="pod">
 | 
					 | 
				
			||||||
        <el-row>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="pod-head-card" shadow="never" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                        <el-row>
 | 
					 | 
				
			||||||
                            <el-col :span="6">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <span>命名空间: </span>
 | 
					 | 
				
			||||||
                                    <el-select v-model="namespaceValue" filterable placeholder="请选择">
 | 
					 | 
				
			||||||
                                        <el-option
 | 
					 | 
				
			||||||
                                        v-for="(item, index) in namespaceList"
 | 
					 | 
				
			||||||
                                        :key="index"
 | 
					 | 
				
			||||||
                                        :label="item.metadata.name"
 | 
					 | 
				
			||||||
                                        :value="item.metadata.name">
 | 
					 | 
				
			||||||
                                        </el-option>
 | 
					 | 
				
			||||||
                                    </el-select>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                            <el-col :span="2" :offset="16">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Refresh" plain @click="getPods()">刷新</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                        </el-row>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="pod-head-card" shadow="never" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                        <el-row>
 | 
					 | 
				
			||||||
                            <el-col :span="2">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-button disabled style="border-radius:2px;" icon="Edit" type="primary">创建</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                            <el-col :span="6">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-input class="pod-head-search" clearable placeholder="请输入" v-model="searchInput"></el-input>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Search" type="primary" plain @click="getPods()">搜索</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                        </el-row>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="pod-body-card" shadow="never" :body-style="{padding:'5px'}">
 | 
					 | 
				
			||||||
                        <el-table
 | 
					 | 
				
			||||||
                        style="width:100%;font-size:12px;margin-bottom:10px;"
 | 
					 | 
				
			||||||
                        :data="podList"
 | 
					 | 
				
			||||||
                        v-loading="appLoading"
 | 
					 | 
				
			||||||
                        :row-key="getRowKeys"
 | 
					 | 
				
			||||||
                        :expand-row-keys="expandKeys"
 | 
					 | 
				
			||||||
                        @expand-change="expandChange">
 | 
					 | 
				
			||||||
                            <el-table-column width="10"></el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column type="expand">
 | 
					 | 
				
			||||||
                                <template #default="props">
 | 
					 | 
				
			||||||
                                    <el-tabs v-model="activeName" type="card">
 | 
					 | 
				
			||||||
                                        <el-tab-pane label="容器" name="container">
 | 
					 | 
				
			||||||
                                            <el-card shadow="never" style="border-radius:1px;" :body-style="{padding:'5px'}">
 | 
					 | 
				
			||||||
                                                <el-table
 | 
					 | 
				
			||||||
                                                style="width:100%;font-size:12px;"
 | 
					 | 
				
			||||||
                                                :data="props.row.spec.containers">
 | 
					 | 
				
			||||||
                                                    <el-table-column align=left prop="name" label="容器名"></el-table-column>
 | 
					 | 
				
			||||||
                                                    <el-table-column align=left prop="image" label="镜像"></el-table-column>
 | 
					 | 
				
			||||||
                                                    <el-table-column align=center label="Pod IP">
 | 
					 | 
				
			||||||
                                                        <span>{{ props.row.status.podIP }}</span>
 | 
					 | 
				
			||||||
                                                    </el-table-column>
 | 
					 | 
				
			||||||
                                                    <el-table-column align=center prop="args" label="启动命令"></el-table-column>
 | 
					 | 
				
			||||||
                                                    <el-table-column align=center label="环境变量">
 | 
					 | 
				
			||||||
                                                        <template v-slot="scope">
 | 
					 | 
				
			||||||
                                                            <el-popover :width="500" placement="left" trigger="hover">
 | 
					 | 
				
			||||||
                                                                <el-table style="width:100%;font-size:12px;" size="mini" :show-header="false" :data="scope.row.env">
 | 
					 | 
				
			||||||
                                                                    <el-table-column property="name" label="名称"></el-table-column>
 | 
					 | 
				
			||||||
                                                                    <el-table-column property="value" label="值"></el-table-column>
 | 
					 | 
				
			||||||
                                                                </el-table>
 | 
					 | 
				
			||||||
                                                                <template #reference>
 | 
					 | 
				
			||||||
                                                                <el-button size="small">此处查看</el-button>
 | 
					 | 
				
			||||||
                                                                </template>
 | 
					 | 
				
			||||||
                                                            </el-popover>
 | 
					 | 
				
			||||||
                                                        </template>
 | 
					 | 
				
			||||||
                                                    </el-table-column>
 | 
					 | 
				
			||||||
                                                </el-table>
 | 
					 | 
				
			||||||
                                            </el-card>
 | 
					 | 
				
			||||||
                                        </el-tab-pane>
 | 
					 | 
				
			||||||
                                        <el-tab-pane label="日志" name="log">
 | 
					 | 
				
			||||||
                                            <el-card shadow="never" style="border-radius:1px;" :body-style="{padding:'5px'}">
 | 
					 | 
				
			||||||
                                                <el-row :gutter="10">
 | 
					 | 
				
			||||||
                                                    <el-col :span="3">
 | 
					 | 
				
			||||||
                                                        <el-select size="small" v-model="containerValue" placeholder="请选择">
 | 
					 | 
				
			||||||
                                                            <el-option v-for="item in containerList" :key="item" :value="item">
 | 
					 | 
				
			||||||
                                                            </el-option>
 | 
					 | 
				
			||||||
                                                        </el-select>
 | 
					 | 
				
			||||||
                                                    </el-col>
 | 
					 | 
				
			||||||
                                                    <el-col :span="2">
 | 
					 | 
				
			||||||
                                                        <el-button style="border-radius:2px;" size="small" type="primary" @click="getPodLog(props.row.metadata.name)">查看</el-button>
 | 
					 | 
				
			||||||
                                                    </el-col>
 | 
					 | 
				
			||||||
                                                    <el-col :span="24" style="margin-top: 5px">
 | 
					 | 
				
			||||||
                                                        <el-card shadow="never" class="pod-body-log-card" :body-style="{padding:'5px'}">
 | 
					 | 
				
			||||||
                                                            <span class="pod-body-log-span">{{ logContent }}</span>
 | 
					 | 
				
			||||||
                                                        </el-card>
 | 
					 | 
				
			||||||
                                                    </el-col>
 | 
					 | 
				
			||||||
                                                 </el-row>
 | 
					 | 
				
			||||||
                                            </el-card>
 | 
					 | 
				
			||||||
                                        </el-tab-pane>
 | 
					 | 
				
			||||||
                                        <el-tab-pane label="终端" name="shell">
 | 
					 | 
				
			||||||
                                            <el-card shadow="never" style="border-radius:1px;" :body-style="{padding:'5px'}">
 | 
					 | 
				
			||||||
                                                <el-row :gutter="10">
 | 
					 | 
				
			||||||
                                                    <el-col :span="3">
 | 
					 | 
				
			||||||
                                                        <el-select size="small" v-model="containerValue" placeholder="请选择">
 | 
					 | 
				
			||||||
                                                            <el-option v-for="item in containerList" :key="item" :value="item">
 | 
					 | 
				
			||||||
                                                            </el-option>
 | 
					 | 
				
			||||||
                                                        </el-select>
 | 
					 | 
				
			||||||
                                                    </el-col>
 | 
					 | 
				
			||||||
                                                    <el-col :span="1">
 | 
					 | 
				
			||||||
                                                        <el-button style="border-radius:2px;" size="small" type="primary" @click="initSocket(props.row)">连接</el-button>
 | 
					 | 
				
			||||||
                                                    </el-col>
 | 
					 | 
				
			||||||
                                                    <el-col :span="1">
 | 
					 | 
				
			||||||
                                                        <el-button style="border-radius:2px;" size="small" type="danger" @click="closeSocket()">关闭</el-button>
 | 
					 | 
				
			||||||
                                                    </el-col>
 | 
					 | 
				
			||||||
                                                    <el-col :span="24" style="margin-top: 5px">
 | 
					 | 
				
			||||||
                                                        <el-card shadow="never" class="pod-body-shell-card" :body-style="{padding:'5px'}">
 | 
					 | 
				
			||||||
                                                            <div id="xterm"></div>
 | 
					 | 
				
			||||||
                                                        </el-card>
 | 
					 | 
				
			||||||
                                                    </el-col>
 | 
					 | 
				
			||||||
                                                 </el-row>
 | 
					 | 
				
			||||||
                                            </el-card>
 | 
					 | 
				
			||||||
                                        </el-tab-pane>
 | 
					 | 
				
			||||||
                                    </el-tabs>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=left label="Pod名">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <a class="pod-body-podname" @click="expandMap[scope.row.metadata.name] ? expandChange(scope.row, []) : expandChange(scope.row, [scope.row])">{{ scope.row.metadata.name }}</a>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center min-width="150" label="节点">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-tag v-if="scope.row.spec.nodeName !== undefined" type="warning">{{ scope.row.spec.nodeName }}</el-tag>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="状态">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <div :class="{'success-dot':scope.row.status.phase == 'Running', 'warning-dot':scope.row.status.phase == 'Pending', 'error-dot':scope.row.status.phase != 'Running' && scope.row.status.phase != 'Pending'}"></div>
 | 
					 | 
				
			||||||
                                    <span :class="{'success-status':scope.row.status.phase == 'Running', 'warning-status':scope.row.status.phase == 'Pending', 'error-status':scope.row.status.phase != 'Running' && scope.row.status.phase != 'Pending'}">{{ scope.row.status.phase }} </span>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="重启数">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <span>{{ restartTotal(scope) }} </span>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center min-width="100" label="创建时间">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-tag type="info">{{ timeTrans(scope.row.metadata.creationTimestamp) }} </el-tag>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="操作" width="200">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-button size="small" style="border-radius:2px;" icon="Edit" type="primary" plain @click="getPodDetail(scope)">YAML</el-button>
 | 
					 | 
				
			||||||
                                    <el-button size="small" style="border-radius:2px;" icon="Delete" type="danger" @click="handleConfirm(scope, '删除', delPod)">删除</el-button>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                        </el-table>
 | 
					 | 
				
			||||||
                        <el-pagination
 | 
					 | 
				
			||||||
                        class="pod-body-pagination"
 | 
					 | 
				
			||||||
                        background
 | 
					 | 
				
			||||||
                        @size-change="handleSizeChange"
 | 
					 | 
				
			||||||
                        @current-change="handleCurrentChange"
 | 
					 | 
				
			||||||
                        :current-page="currentPage"
 | 
					 | 
				
			||||||
                        :page-sizes="pagesizeList"
 | 
					 | 
				
			||||||
                        :page-size="pagesize"
 | 
					 | 
				
			||||||
                        layout="total, sizes, prev, pager, next, jumper"
 | 
					 | 
				
			||||||
                        :total="podTotal">
 | 
					 | 
				
			||||||
                        </el-pagination>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
        </el-row>
 | 
					 | 
				
			||||||
        <el-dialog title="YAML信息" v-model="yamlDialog" width="45%" top="5%">
 | 
					 | 
				
			||||||
            <codemirror
 | 
					 | 
				
			||||||
                :value="contentYaml"
 | 
					 | 
				
			||||||
                border
 | 
					 | 
				
			||||||
                :options="cmOptions"
 | 
					 | 
				
			||||||
                height="500"
 | 
					 | 
				
			||||||
                style="font-size:14px;"
 | 
					 | 
				
			||||||
                @change="onChange"
 | 
					 | 
				
			||||||
            ></codemirror>
 | 
					 | 
				
			||||||
            <template #footer>
 | 
					 | 
				
			||||||
                <span class="dialog-footer">
 | 
					 | 
				
			||||||
                    <el-button @click="yamlDialog = false">取 消</el-button>
 | 
					 | 
				
			||||||
                    <el-button type="primary" @click="updatePod()">更 新</el-button>
 | 
					 | 
				
			||||||
                </span>
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
        </el-dialog>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script>
 | 
					 | 
				
			||||||
import common from "../common/Config";
 | 
					 | 
				
			||||||
import httpClient from '../../utils/request';
 | 
					 | 
				
			||||||
import { Terminal } from 'xterm';
 | 
					 | 
				
			||||||
import { FitAddon } from 'xterm-addon-fit';
 | 
					 | 
				
			||||||
import 'xterm/css/xterm.css';
 | 
					 | 
				
			||||||
import 'xterm/lib/xterm.js';
 | 
					 | 
				
			||||||
import yaml2obj from 'js-yaml';
 | 
					 | 
				
			||||||
import json2yaml from 'json2yaml';
 | 
					 | 
				
			||||||
export default {
 | 
					 | 
				
			||||||
    data() {
 | 
					 | 
				
			||||||
        return {
 | 
					 | 
				
			||||||
            cmOptions: common.cmOptions,
 | 
					 | 
				
			||||||
            contentYaml: '',
 | 
					 | 
				
			||||||
            currentPage: 1,
 | 
					 | 
				
			||||||
            pagesize: 10,
 | 
					 | 
				
			||||||
            pagesizeList: [10, 20, 30],
 | 
					 | 
				
			||||||
            searchInput: '',
 | 
					 | 
				
			||||||
            namespaceValue: 'default',
 | 
					 | 
				
			||||||
            namespaceList: [],
 | 
					 | 
				
			||||||
            namespaceListUrl: common.k8sNamespaceList,
 | 
					 | 
				
			||||||
            appLoading: false,
 | 
					 | 
				
			||||||
            podList: [],
 | 
					 | 
				
			||||||
            podTotal: 0,
 | 
					 | 
				
			||||||
            getPodsData: {
 | 
					 | 
				
			||||||
                url: common.k8sPodList,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    filter_name: '',
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                    page: '',
 | 
					 | 
				
			||||||
                    limit: '',
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            podDetail: {},
 | 
					 | 
				
			||||||
            getPodDetailData: {
 | 
					 | 
				
			||||||
                url: common.k8sPodDetail,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    pod_name: '',
 | 
					 | 
				
			||||||
                    namespace: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            yamlDialog: false,
 | 
					 | 
				
			||||||
            updatePodData: {
 | 
					 | 
				
			||||||
                url: common.k8sPodUpdate,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                    content: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            delPodData: {
 | 
					 | 
				
			||||||
                url: common.k8sPodDel,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    pod_name: '',
 | 
					 | 
				
			||||||
                    namespace: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            activeName: 'container',
 | 
					 | 
				
			||||||
            expandKeys: [],
 | 
					 | 
				
			||||||
            expandMap: {},
 | 
					 | 
				
			||||||
            containerList: {},
 | 
					 | 
				
			||||||
            containerValue: '',
 | 
					 | 
				
			||||||
            getPodContainerData: {
 | 
					 | 
				
			||||||
                url: common.k8sPodContainer,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    pod_name: '',
 | 
					 | 
				
			||||||
                    namespace: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            logContent: '',
 | 
					 | 
				
			||||||
            getPodLogData: {
 | 
					 | 
				
			||||||
                url: common.k8sPodLog,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    container_name: '',
 | 
					 | 
				
			||||||
                    pod_name: '',
 | 
					 | 
				
			||||||
                    namespace: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            term: null,
 | 
					 | 
				
			||||||
            socket: null
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    methods: {
 | 
					 | 
				
			||||||
        transYaml(content) {
 | 
					 | 
				
			||||||
            return json2yaml.stringify(content)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        transObj(content) {
 | 
					 | 
				
			||||||
            return yaml2obj.load(content)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        onChange(val) {
 | 
					 | 
				
			||||||
            this.contentYaml = val
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleSizeChange(size) {
 | 
					 | 
				
			||||||
            this.pagesize = size;
 | 
					 | 
				
			||||||
            this.getPods()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleCurrentChange(currentPage) {
 | 
					 | 
				
			||||||
            this.currentPage = currentPage;
 | 
					 | 
				
			||||||
            this.getPods()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleClose(done) {
 | 
					 | 
				
			||||||
            this.$confirm('确认关闭?')
 | 
					 | 
				
			||||||
            .then(() => {
 | 
					 | 
				
			||||||
                done();
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(() => {});
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        ellipsis(value) {
 | 
					 | 
				
			||||||
            return value.length>15?value.substring(0,15)+'...':value
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        timeTrans(timestamp) {
 | 
					 | 
				
			||||||
            let date = new Date(new Date(timestamp).getTime() + 8 * 3600 * 1000)
 | 
					 | 
				
			||||||
            date = date.toJSON();
 | 
					 | 
				
			||||||
            date = date.substring(0, 19).replace('T', ' ')
 | 
					 | 
				
			||||||
            return date 
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        restartTotal(e) {
 | 
					 | 
				
			||||||
            let index, sum = 0
 | 
					 | 
				
			||||||
            let containerStatuses = e.row.status.containerStatuses
 | 
					 | 
				
			||||||
            for ( index in containerStatuses) {
 | 
					 | 
				
			||||||
                sum = sum + containerStatuses[index].restartCount 
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return sum
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getNamespaces() {
 | 
					 | 
				
			||||||
            httpClient.get(this.namespaceListUrl)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.namespaceList = res.data.items
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getPods() {
 | 
					 | 
				
			||||||
            this.appLoading = true
 | 
					 | 
				
			||||||
            this.getPodsData.params.filter_name = this.searchInput
 | 
					 | 
				
			||||||
            this.getPodsData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            this.getPodsData.params.page = this.currentPage
 | 
					 | 
				
			||||||
            this.getPodsData.params.limit = this.pagesize
 | 
					 | 
				
			||||||
            httpClient.get(this.getPodsData.url, {params: this.getPodsData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.podList = res.data.items
 | 
					 | 
				
			||||||
                this.podTotal = res.data.total
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.appLoading = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getPodDetail(e) {
 | 
					 | 
				
			||||||
            this.getPodDetailData.params.pod_name = e.row.metadata.name
 | 
					 | 
				
			||||||
            this.getPodDetailData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            httpClient.get(this.getPodDetailData.url, {params: this.getPodDetailData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.podDetail = res.data
 | 
					 | 
				
			||||||
                this.contentYaml = this.transYaml(this.podDetail)
 | 
					 | 
				
			||||||
                this.yamlDialog = true
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        updatePod() {
 | 
					 | 
				
			||||||
            let content = JSON.stringify(this.transObj(this.contentYaml))
 | 
					 | 
				
			||||||
            this.updatePodData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            this.updatePodData.params.content = content
 | 
					 | 
				
			||||||
            httpClient.put(this.updatePodData.url, this.updatePodData.params)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.yamlDialog = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        delPod(e) {
 | 
					 | 
				
			||||||
            this.delPodData.params.pod_name = e.row.metadata.name
 | 
					 | 
				
			||||||
            this.delPodData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            httpClient.delete(this.delPodData.url, {data: this.delPodData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.getPods()
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleConfirm(obj, operateName, fn) {
 | 
					 | 
				
			||||||
            this.confirmContent = '确认继续 ' + operateName + ' 操作吗?'
 | 
					 | 
				
			||||||
            this.$confirm(this.confirmContent,'提示',{
 | 
					 | 
				
			||||||
                confirmButtonText: '确定',
 | 
					 | 
				
			||||||
                cancelButtonText: '取消',
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .then(() => {
 | 
					 | 
				
			||||||
                fn(obj)
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            .catch(() => {
 | 
					 | 
				
			||||||
                this.$message.info({
 | 
					 | 
				
			||||||
                    message: '已取消操作'
 | 
					 | 
				
			||||||
                })          
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getRowKeys(row) {
 | 
					 | 
				
			||||||
            return row.metadata.name
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        expandChange(row, expandedRows) {
 | 
					 | 
				
			||||||
            this.expandKeys = []
 | 
					 | 
				
			||||||
            this.logContent= ''
 | 
					 | 
				
			||||||
            this.containerValue = ''
 | 
					 | 
				
			||||||
            this.activeName = 'container'
 | 
					 | 
				
			||||||
            if (expandedRows.length > 0) {
 | 
					 | 
				
			||||||
                this.expandMap[row.metadata.name] = 1
 | 
					 | 
				
			||||||
                this.setExpandMap(row.metadata.name)
 | 
					 | 
				
			||||||
                row ? (this.expandKeys.push(row.metadata.name), this. getPodContainer(row)) : ''
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                this.expandMap[row.metadata.name] = 0
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        setExpandMap(podName) {
 | 
					 | 
				
			||||||
            let key
 | 
					 | 
				
			||||||
            for ( key in this.expandMap ) {
 | 
					 | 
				
			||||||
                key !== podName ? this.expandMap[key] = 0 : ''
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getPodContainer(row) {
 | 
					 | 
				
			||||||
            this.getPodContainerData.params.pod_name = row.metadata.name
 | 
					 | 
				
			||||||
            this.getPodContainerData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            httpClient.get(this.getPodContainerData.url, {params: this.getPodContainerData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.containerList = res.data
 | 
					 | 
				
			||||||
                this.containerValue = this.containerList[0]
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getPodLog(podName) {
 | 
					 | 
				
			||||||
            this.getPodLogData.params.pod_name = podName
 | 
					 | 
				
			||||||
            this.getPodLogData.params.container_name = this.containerValue
 | 
					 | 
				
			||||||
            this.getPodLogData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            httpClient.get(this.getPodLogData.url, {params: this.getPodLogData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.logContent = res.data
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        initTerm() {
 | 
					 | 
				
			||||||
            this.term = new Terminal({
 | 
					 | 
				
			||||||
                rendererType: 'canvas',
 | 
					 | 
				
			||||||
                rows: 30,
 | 
					 | 
				
			||||||
                cols: 110,
 | 
					 | 
				
			||||||
                convertEol: false, 
 | 
					 | 
				
			||||||
                scrollback: 10,
 | 
					 | 
				
			||||||
                disableStdin: false,
 | 
					 | 
				
			||||||
                cursorStyle: 'underline', 
 | 
					 | 
				
			||||||
                cursorBlink: true,
 | 
					 | 
				
			||||||
                theme: {
 | 
					 | 
				
			||||||
                foreground: 'white',
 | 
					 | 
				
			||||||
                background: '#060101',
 | 
					 | 
				
			||||||
                cursor: 'help'
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
            this.term.open(document.getElementById('xterm'))
 | 
					 | 
				
			||||||
            const fitAddon = new FitAddon()
 | 
					 | 
				
			||||||
            this.term.loadAddon(fitAddon)
 | 
					 | 
				
			||||||
            fitAddon.fit();
 | 
					 | 
				
			||||||
            this.term.focus();
 | 
					 | 
				
			||||||
            let _this = this;
 | 
					 | 
				
			||||||
            this.term.onData(function (key) {
 | 
					 | 
				
			||||||
                let msgOrder = {
 | 
					 | 
				
			||||||
                operation: 'stdin',
 | 
					 | 
				
			||||||
                data: key,
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
                _this.socket.send(JSON.stringify(msgOrder));
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
            let msgOrder2 = {
 | 
					 | 
				
			||||||
                operation: 'resize',
 | 
					 | 
				
			||||||
                cols: this.term.cols,
 | 
					 | 
				
			||||||
                rows: this.term.rows,
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
            this.socket.send(JSON.stringify(msgOrder2))
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        initSocket(row) {
 | 
					 | 
				
			||||||
            let terminalWsUrl = common.k8sTerminalWs + "?pod_name=" + row.metadata.name + "&container_name=" + this.containerValue + "&namespace=" + this.namespaceValue
 | 
					 | 
				
			||||||
            this.socket = new WebSocket(terminalWsUrl);
 | 
					 | 
				
			||||||
            this.socketOnClose();
 | 
					 | 
				
			||||||
            this.socketOnOpen();
 | 
					 | 
				
			||||||
            this.socketOnMessage();
 | 
					 | 
				
			||||||
            this.socketOnError();
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        socketOnOpen() {
 | 
					 | 
				
			||||||
            this.socket.onopen = () => {
 | 
					 | 
				
			||||||
                this.initTerm()
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        socketOnMessage() {
 | 
					 | 
				
			||||||
            this.socket.onmessage = (msg) => {
 | 
					 | 
				
			||||||
                let content = JSON.parse(msg.data)
 | 
					 | 
				
			||||||
                this.term.write(content.data)
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        socketOnClose() {
 | 
					 | 
				
			||||||
            this.socket.onclose = () => {
 | 
					 | 
				
			||||||
                this.term.write("链接已关闭")
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        socketOnError() {
 | 
					 | 
				
			||||||
            this.socket.onerror = () => {
 | 
					 | 
				
			||||||
                console.log('socket 链接失败')
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        closeSocket() {
 | 
					 | 
				
			||||||
            if (this.socket === null) {
 | 
					 | 
				
			||||||
                    return 
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            this.term.write("链接关闭中。。。")
 | 
					 | 
				
			||||||
            this.socket.close()
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    watch: {
 | 
					 | 
				
			||||||
        namespaceValue: {
 | 
					 | 
				
			||||||
            handler() {
 | 
					 | 
				
			||||||
                localStorage.setItem('namespace', this.namespaceValue)
 | 
					 | 
				
			||||||
                this.currentPage = 1
 | 
					 | 
				
			||||||
                this.getPods()
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        activeName: {
 | 
					 | 
				
			||||||
            handler() {
 | 
					 | 
				
			||||||
                if ( this.activeName == 'log' ) {
 | 
					 | 
				
			||||||
                    this.expandKeys.length == 1 ? this.getPodLog(this.expandKeys[0]) : ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    beforeMount() {
 | 
					 | 
				
			||||||
        if (localStorage.getItem('namespace') !== undefined && localStorage.getItem('namespace') !== null) {
 | 
					 | 
				
			||||||
            this.namespaceValue = localStorage.getItem('namespace')
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        this.getNamespaces()
 | 
					 | 
				
			||||||
        this.getPods()
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    beforeUnmount() {
 | 
					 | 
				
			||||||
        if ( this.socket !== null ) {
 | 
					 | 
				
			||||||
            this.socket.close()
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style scoped>
 | 
					 | 
				
			||||||
    .pod-head-card,.pod-body-card {
 | 
					 | 
				
			||||||
        border-radius: 1px;
 | 
					 | 
				
			||||||
        margin-bottom: 5px;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .pod-head-search {
 | 
					 | 
				
			||||||
        width:160px;
 | 
					 | 
				
			||||||
        margin-right:10px; 
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .pod-body-podname {
 | 
					 | 
				
			||||||
        color: #4795EE;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .pod-body-podname:hover {
 | 
					 | 
				
			||||||
        color: rgb(84, 138, 238);
 | 
					 | 
				
			||||||
        cursor: pointer;
 | 
					 | 
				
			||||||
        font-weight: bold;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .success-dot{
 | 
					 | 
				
			||||||
        display:inline-block;
 | 
					 | 
				
			||||||
        width: 7px;
 | 
					 | 
				
			||||||
        height:7px;
 | 
					 | 
				
			||||||
        background: rgb(27, 202, 21);
 | 
					 | 
				
			||||||
        border-radius:50%;
 | 
					 | 
				
			||||||
        border:1px solid rgb(27, 202, 21);
 | 
					 | 
				
			||||||
        margin-right: 10px;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .warning-dot{
 | 
					 | 
				
			||||||
        display:inline-block;
 | 
					 | 
				
			||||||
        width: 7px;
 | 
					 | 
				
			||||||
        height:7px;
 | 
					 | 
				
			||||||
        background: rgb(233, 200, 16);
 | 
					 | 
				
			||||||
        border-radius:50%;
 | 
					 | 
				
			||||||
        border:1px solid rgb(233, 200, 16);
 | 
					 | 
				
			||||||
        margin-right: 10px;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .error-dot{
 | 
					 | 
				
			||||||
        display:inline-block;
 | 
					 | 
				
			||||||
        width: 7px;
 | 
					 | 
				
			||||||
        height:7px;
 | 
					 | 
				
			||||||
        background: rgb(226, 23, 23);
 | 
					 | 
				
			||||||
        border-radius:50%;
 | 
					 | 
				
			||||||
        border:1px solid rgb(226, 23, 23);
 | 
					 | 
				
			||||||
        margin-right: 10px;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .success-status {
 | 
					 | 
				
			||||||
        color: rgb(27, 202, 21);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .warning-status {
 | 
					 | 
				
			||||||
        color: rgb(233, 200, 16);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .error-status {
 | 
					 | 
				
			||||||
        color: rgb(226, 23, 23);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    :v-deep .el-tabs__item {
 | 
					 | 
				
			||||||
        font-size: 12px;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    :v-deep .el-tabs__header {
 | 
					 | 
				
			||||||
        margin-bottom: 8px;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .pod-body-log-card, .pod-body-shell-card {
 | 
					 | 
				
			||||||
        border-radius:1px;
 | 
					 | 
				
			||||||
        height:600px;
 | 
					 | 
				
			||||||
        overflow:auto;
 | 
					 | 
				
			||||||
        background-color: #060101;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .pod-body-log-card {
 | 
					 | 
				
			||||||
        color: aliceblue;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .pod-body-log-span {
 | 
					 | 
				
			||||||
        white-space:pre;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
@ -1,367 +0,0 @@
 | 
				
			|||||||
<template>
 | 
					 | 
				
			||||||
    <div class="secret">
 | 
					 | 
				
			||||||
        <el-row>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="secret-head-card" shadow="never" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                        <el-row>
 | 
					 | 
				
			||||||
                            <el-col :span="6">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <span>命名空间: </span>
 | 
					 | 
				
			||||||
                                    <el-select v-model="namespaceValue" filterable placeholder="请选择">
 | 
					 | 
				
			||||||
                                        <el-option
 | 
					 | 
				
			||||||
                                        v-for="(item, index) in namespaceList"
 | 
					 | 
				
			||||||
                                        :key="index"
 | 
					 | 
				
			||||||
                                        :label="item.metadata.name"
 | 
					 | 
				
			||||||
                                        :value="item.metadata.name">
 | 
					 | 
				
			||||||
                                        </el-option>
 | 
					 | 
				
			||||||
                                    </el-select>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                            <el-col :span="2" :offset="16">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Refresh" plain @click="getSecrets()">刷新</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                        </el-row>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="secret-head-card" shadow="never" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                        <el-row>
 | 
					 | 
				
			||||||
                            <el-col :span="2">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-button disabled style="border-radius:2px;" icon="Edit" type="primary">创建</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                            <el-col :span="6">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-input class="secret-head-search" clearable placeholder="请输入" v-model="searchInput"></el-input>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Search" type="primary" plain @click="getSecrets()">搜索</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                        </el-row>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="secret-body-card" shadow="never" :body-style="{padding:'5px'}">
 | 
					 | 
				
			||||||
                        <el-table
 | 
					 | 
				
			||||||
                        style="width:100%;font-size:12px;margin-bottom:10px;"
 | 
					 | 
				
			||||||
                        :data="secretList"
 | 
					 | 
				
			||||||
                        v-loading="appLoading">
 | 
					 | 
				
			||||||
                            <el-table-column width="20"></el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=left label="Secret名">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <a class="secret-body-secretname">{{ scope.row.metadata.name }}</a>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="标签">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <div v-for="(val, key) in scope.row.metadata.labels" :key="key">
 | 
					 | 
				
			||||||
                                        <el-popover
 | 
					 | 
				
			||||||
                                            placement="right"
 | 
					 | 
				
			||||||
                                            :width="200"
 | 
					 | 
				
			||||||
                                            trigger="hover"
 | 
					 | 
				
			||||||
                                            :content="key + ':' + val">
 | 
					 | 
				
			||||||
                                            <template #reference>
 | 
					 | 
				
			||||||
                                                <el-tag style="margin-bottom: 5px" type="warning">{{ ellipsis(key + ":" + val) }}</el-tag>
 | 
					 | 
				
			||||||
                                            </template>
 | 
					 | 
				
			||||||
                                        </el-popover>
 | 
					 | 
				
			||||||
                                    </div>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="DATA">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                        <el-popover
 | 
					 | 
				
			||||||
                                            style="overflow:auto"
 | 
					 | 
				
			||||||
                                            placement="right"
 | 
					 | 
				
			||||||
                                            :width="400"
 | 
					 | 
				
			||||||
                                            trigger="click">
 | 
					 | 
				
			||||||
                                            <div style="overflow-y:auto;max-height:500px;">
 | 
					 | 
				
			||||||
                                                <span>{{ scope.row.data }}</span>
 | 
					 | 
				
			||||||
                                            </div>
 | 
					 | 
				
			||||||
                                            <template #reference>
 | 
					 | 
				
			||||||
                                                <el-icon style="font-size:18px;cursor:pointer;"><reading/></el-icon>
 | 
					 | 
				
			||||||
                                            </template>
 | 
					 | 
				
			||||||
                                        </el-popover>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center prop="type" min-width="100" label="类型">
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center min-width="100" label="创建时间">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-tag type="info">{{ timeTrans(scope.row.metadata.creationTimestamp) }} </el-tag>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="操作" width="200">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-button size="small" style="border-radius:2px;" icon="Edit" type="primary" plain @click="getSecretDetail(scope)">YAML</el-button>
 | 
					 | 
				
			||||||
                                    <el-button size="small" style="border-radius:2px;" icon="Delete" type="danger" @click="handleConfirm(scope, '删除', delSecret)">删除</el-button>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                        </el-table>
 | 
					 | 
				
			||||||
                        <el-pagination
 | 
					 | 
				
			||||||
                        class="secret-body-pagination"
 | 
					 | 
				
			||||||
                        background
 | 
					 | 
				
			||||||
                        @size-change="handleSizeChange"
 | 
					 | 
				
			||||||
                        @current-change="handleCurrentChange"
 | 
					 | 
				
			||||||
                        :current-page="currentPage"
 | 
					 | 
				
			||||||
                        :page-sizes="pagesizeList"
 | 
					 | 
				
			||||||
                        layout="total, sizes, prev, pager, next, jumper"
 | 
					 | 
				
			||||||
                        :prev-click="getSecrets"
 | 
					 | 
				
			||||||
                        :total="secretTotal">
 | 
					 | 
				
			||||||
                        </el-pagination>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
        </el-row>
 | 
					 | 
				
			||||||
        <el-dialog title="YAML信息" v-model="yamlDialog" width="45%" top="5%">
 | 
					 | 
				
			||||||
            <codemirror
 | 
					 | 
				
			||||||
                :value="contentYaml"
 | 
					 | 
				
			||||||
                border
 | 
					 | 
				
			||||||
                :options="cmOptions"
 | 
					 | 
				
			||||||
                height="500"
 | 
					 | 
				
			||||||
                style="font-size:14px;"
 | 
					 | 
				
			||||||
                @change="onChange"
 | 
					 | 
				
			||||||
            ></codemirror>
 | 
					 | 
				
			||||||
            <template #footer>
 | 
					 | 
				
			||||||
                <span class="dialog-footer">
 | 
					 | 
				
			||||||
                    <el-button @click="yamlDialog = false">取 消</el-button>
 | 
					 | 
				
			||||||
                    <el-button type="primary" @click="updateSecret()">更 新</el-button>
 | 
					 | 
				
			||||||
                </span>
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
        </el-dialog>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script>
 | 
					 | 
				
			||||||
import common from "../common/Config";
 | 
					 | 
				
			||||||
import httpClient from '../../utils/request';
 | 
					 | 
				
			||||||
import yaml2obj from 'js-yaml';
 | 
					 | 
				
			||||||
import json2yaml from 'json2yaml';
 | 
					 | 
				
			||||||
export default {
 | 
					 | 
				
			||||||
    data() {
 | 
					 | 
				
			||||||
        return {
 | 
					 | 
				
			||||||
            cmOptions: common.cmOptions,
 | 
					 | 
				
			||||||
            contentYaml: '',
 | 
					 | 
				
			||||||
            currentPage: 1,
 | 
					 | 
				
			||||||
            pagesize: 10,
 | 
					 | 
				
			||||||
            pagesizeList: [10, 20, 30],
 | 
					 | 
				
			||||||
            searchInput: '',
 | 
					 | 
				
			||||||
            namespaceValue: 'default',
 | 
					 | 
				
			||||||
            namespaceList: [],
 | 
					 | 
				
			||||||
            namespaceListUrl: common.k8sNamespaceList,
 | 
					 | 
				
			||||||
            appLoading: false,
 | 
					 | 
				
			||||||
            secretList: [],
 | 
					 | 
				
			||||||
            secretTotal: 0,
 | 
					 | 
				
			||||||
            getSecretsData: {
 | 
					 | 
				
			||||||
                url: common.k8sSecretList,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    filter_name: '',
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                    page: '',
 | 
					 | 
				
			||||||
                    limit: '',
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            secretDetail: {},
 | 
					 | 
				
			||||||
            getSecretDetailData: {
 | 
					 | 
				
			||||||
                url: common.k8sSecretDetail,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    secret_name: '',
 | 
					 | 
				
			||||||
                    namespace: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            yamlDialog: false,
 | 
					 | 
				
			||||||
            updateSecretData: {
 | 
					 | 
				
			||||||
                url: common.k8sSecretUpdate,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                    content: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            delSecretData: {
 | 
					 | 
				
			||||||
                url: common.k8ssecretDel,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    secret_name: '',
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    methods: {
 | 
					 | 
				
			||||||
        transYaml(content) {
 | 
					 | 
				
			||||||
            return json2yaml.stringify(content)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        transObj(content) {
 | 
					 | 
				
			||||||
            return yaml2obj.load(content)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        onChange(val) {
 | 
					 | 
				
			||||||
            this.contentYaml = val
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleSizeChange(size) {
 | 
					 | 
				
			||||||
            this.pagesize = size;
 | 
					 | 
				
			||||||
            this.getSecrets()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleCurrentChange(currentPage) {
 | 
					 | 
				
			||||||
            this.currentPage = currentPage;
 | 
					 | 
				
			||||||
            this.getSecrets()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleClose(done) {
 | 
					 | 
				
			||||||
            this.$confirm('确认关闭?')
 | 
					 | 
				
			||||||
            .then(() => {
 | 
					 | 
				
			||||||
                done();
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(() => {});
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        ellipsis(value) {
 | 
					 | 
				
			||||||
            return value.length>15?value.substring(0,15)+'...':value
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        timeTrans(timestamp) {
 | 
					 | 
				
			||||||
            let date = new Date(new Date(timestamp).getTime() + 8 * 3600 * 1000)
 | 
					 | 
				
			||||||
            date = date.toJSON();
 | 
					 | 
				
			||||||
            date = date.substring(0, 19).replace('T', ' ')
 | 
					 | 
				
			||||||
            return date 
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        restartTotal(e) {
 | 
					 | 
				
			||||||
            let index, sum = 0
 | 
					 | 
				
			||||||
            let containerStatuses = e.row.status.containerStatuses
 | 
					 | 
				
			||||||
            for ( index in containerStatuses) {
 | 
					 | 
				
			||||||
                sum = sum + containerStatuses[index].restartCount 
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return sum
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getNamespaces() {
 | 
					 | 
				
			||||||
            httpClient.get(this.namespaceListUrl)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.namespaceList = res.data.items
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getSecrets() {
 | 
					 | 
				
			||||||
            this.appLoading = true
 | 
					 | 
				
			||||||
            this.getSecretsData.params.filter_name = this.searchInput
 | 
					 | 
				
			||||||
            this.getSecretsData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            this.getSecretsData.params.page = this.currentPage
 | 
					 | 
				
			||||||
            this.getSecretsData.params.limit = this.pagesize
 | 
					 | 
				
			||||||
            httpClient.get(this.getSecretsData.url, {params: this.getSecretsData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.secretList = res.data.items
 | 
					 | 
				
			||||||
                this.secretTotal = res.data.total
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.appLoading = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getSecretDetail(e) {
 | 
					 | 
				
			||||||
            this.getSecretDetailData.params.secret_name = e.row.metadata.name
 | 
					 | 
				
			||||||
            this.getSecretDetailData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            httpClient.get(this.getSecretDetailData.url, {params: this.getSecretDetailData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.secretDetail = res.data
 | 
					 | 
				
			||||||
                this.contentYaml = this.transYaml(this.secretDetail)
 | 
					 | 
				
			||||||
                this.yamlDialog = true
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        updateSecret() {
 | 
					 | 
				
			||||||
            let content = JSON.stringify(this.transObj(this.contentYaml))
 | 
					 | 
				
			||||||
            this.updateSecretData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            this.updateSecretData.params.content = content
 | 
					 | 
				
			||||||
            httpClient.put(this.updateSecretData.url, this.updateSecretData.params)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.yamlDialog = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        delSecret(e) {
 | 
					 | 
				
			||||||
            this.delSecretData.params.secret_name = e.row.metadata.name
 | 
					 | 
				
			||||||
            this.delSecretData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            httpClient.delete(this.delSecretData.url, {data: this.delSecretData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.getSecrets()
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleConfirm(obj, operateName, fn) {
 | 
					 | 
				
			||||||
            this.confirmContent = '确认继续 ' + operateName + ' 操作吗?'
 | 
					 | 
				
			||||||
            this.$confirm(this.confirmContent,'提示',{
 | 
					 | 
				
			||||||
                confirmButtonText: '确定',
 | 
					 | 
				
			||||||
                cancelButtonText: '取消',
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .then(() => {
 | 
					 | 
				
			||||||
                fn(obj)
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            .catch(() => {
 | 
					 | 
				
			||||||
                this.$message.info({
 | 
					 | 
				
			||||||
                    message: '已取消操作'
 | 
					 | 
				
			||||||
                })          
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    watch: {
 | 
					 | 
				
			||||||
        namespaceValue: {
 | 
					 | 
				
			||||||
            handler() {
 | 
					 | 
				
			||||||
                localStorage.setItem('namespace', this.namespaceValue)
 | 
					 | 
				
			||||||
                this.currentPage = 1
 | 
					 | 
				
			||||||
                this.getSecrets()
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    beforeMount() {
 | 
					 | 
				
			||||||
        if (localStorage.getItem('namespace') !== undefined && localStorage.getItem('namespace') !== null) {
 | 
					 | 
				
			||||||
            this.namespaceValue = localStorage.getItem('namespace')
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        this.getNamespaces()
 | 
					 | 
				
			||||||
        this.getSecrets()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style scoped>
 | 
					 | 
				
			||||||
    .secret-head-card,.secret-body-card {
 | 
					 | 
				
			||||||
        border-radius: 1px;
 | 
					 | 
				
			||||||
        margin-bottom: 5px;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .secret-head-search {
 | 
					 | 
				
			||||||
        width:160px;
 | 
					 | 
				
			||||||
        margin-right:10px; 
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .secret-body-secretname {
 | 
					 | 
				
			||||||
        color: #4795EE;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .secret-body-secretname:hover {
 | 
					 | 
				
			||||||
        color: rgb(84, 138, 238);
 | 
					 | 
				
			||||||
        cursor: pointer;
 | 
					 | 
				
			||||||
        font-weight: bold;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
@ -1,518 +0,0 @@
 | 
				
			|||||||
<template>
 | 
					 | 
				
			||||||
    <div class="service">
 | 
					 | 
				
			||||||
        <el-row>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="service-head-card" shadow="never" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                        <el-row>
 | 
					 | 
				
			||||||
                            <el-col :span="6">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <span>命名空间: </span>
 | 
					 | 
				
			||||||
                                    <el-select v-model="namespaceValue" filterable placeholder="请选择">
 | 
					 | 
				
			||||||
                                        <el-option
 | 
					 | 
				
			||||||
                                        v-for="(item, index) in namespaceList"
 | 
					 | 
				
			||||||
                                        :key="index"
 | 
					 | 
				
			||||||
                                        :label="item.metadata.name"
 | 
					 | 
				
			||||||
                                        :value="item.metadata.name">
 | 
					 | 
				
			||||||
                                        </el-option>
 | 
					 | 
				
			||||||
                                    </el-select>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                            <el-col :span="2" :offset="16">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Refresh" plain @click="getServices()">刷新</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                        </el-row>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="service-head-card" shadow="never" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                        <el-row>
 | 
					 | 
				
			||||||
                            <el-col :span="2">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Edit" type="primary" @click="createServiceDrawer = true" v-loading.fullscreen.lock="fullscreenLoading">创建</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                            <el-col :span="6">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-input class="service-head-search" clearable placeholder="请输入" v-model="searchInput"></el-input>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Search" type="primary" plain @click="getServices()">搜索</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                        </el-row>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="service-body-card" shadow="never" :body-style="{padding:'5px'}">
 | 
					 | 
				
			||||||
                        <el-table
 | 
					 | 
				
			||||||
                        style="width:100%;font-size:12px;margin-bottom:10px;"
 | 
					 | 
				
			||||||
                        :data="serviceList"
 | 
					 | 
				
			||||||
                        v-loading="appLoading">
 | 
					 | 
				
			||||||
                            <el-table-column width="20"></el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=left label="Service名">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <a class="service-body-servicename">{{ scope.row.metadata.name }}</a>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="标签" min-width='120'>
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <div v-for="(val, key) in scope.row.metadata.labels" :key="key">
 | 
					 | 
				
			||||||
                                        <el-popover
 | 
					 | 
				
			||||||
                                            placement="right"
 | 
					 | 
				
			||||||
                                            :width="200"
 | 
					 | 
				
			||||||
                                            trigger="hover"
 | 
					 | 
				
			||||||
                                            :content="key + ':' + val">
 | 
					 | 
				
			||||||
                                            <template #reference>
 | 
					 | 
				
			||||||
                                                <el-tag style="margin-bottom: 5px" type="warning">{{ ellipsis(key + ":" + val) }}</el-tag>
 | 
					 | 
				
			||||||
                                            </template>
 | 
					 | 
				
			||||||
                                        </el-popover>
 | 
					 | 
				
			||||||
                                    </div>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="类型">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <span style="font-weight:bold;">{{ scope.row.spec.type }} </span>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="CLUSTER-IP">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <span>{{ scope.row.spec.clusterIP }} </span>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="EXTERNAL-IP">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <span>{{ scope.row.status.loadBalancer.ingress ? scope.row.status.loadBalancer.ingress[0].ip : '' }} </span>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="端口">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <span v-if="!scope.row.spec.ports[0].nodePort">{{ scope.row.spec.ports[0].port }}/{{ scope.row.spec.ports[0].protocol }}</span>
 | 
					 | 
				
			||||||
                                    <span v-if="scope.row.spec.ports[0].nodePort">{{ scope.row.spec.ports[0].port }}:{{ scope.row.spec.ports[0].nodePort }}/{{ scope.row.spec.ports[0].protocol }}</span>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center min-width="100" label="创建时间">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-tag type="info">{{ timeTrans(scope.row.metadata.creationTimestamp) }} </el-tag>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="操作" width="200">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-button size="small" style="border-radius:2px;" icon="Edit" type="primary" plain @click="getServiceDetail(scope)">YAML</el-button>
 | 
					 | 
				
			||||||
                                    <el-button size="small" style="border-radius:2px;" icon="Delete" type="danger" @click="handleConfirm(scope, '删除', delService)">删除</el-button>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                        </el-table>
 | 
					 | 
				
			||||||
                        <el-pagination
 | 
					 | 
				
			||||||
                        class="service-body-pagination"
 | 
					 | 
				
			||||||
                        background
 | 
					 | 
				
			||||||
                        @size-change="handleSizeChange"
 | 
					 | 
				
			||||||
                        @current-change="handleCurrentChange"
 | 
					 | 
				
			||||||
                        :current-page="currentPage"
 | 
					 | 
				
			||||||
                        :page-sizes="pagesizeList"
 | 
					 | 
				
			||||||
                        :page-size="pagesize"
 | 
					 | 
				
			||||||
                        layout="total, sizes, prev, pager, next, jumper"
 | 
					 | 
				
			||||||
                        :total="serviceTotal">
 | 
					 | 
				
			||||||
                        </el-pagination>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
        </el-row>
 | 
					 | 
				
			||||||
        <el-dialog title="YAML信息" v-model="yamlDialog" width="45%" top="5%">
 | 
					 | 
				
			||||||
            <codemirror
 | 
					 | 
				
			||||||
                :value="contentYaml"
 | 
					 | 
				
			||||||
                border
 | 
					 | 
				
			||||||
                :options="cmOptions"
 | 
					 | 
				
			||||||
                height="500"
 | 
					 | 
				
			||||||
                style="font-size:14px;"
 | 
					 | 
				
			||||||
                @change="onChange"
 | 
					 | 
				
			||||||
            ></codemirror>
 | 
					 | 
				
			||||||
            <template #footer>
 | 
					 | 
				
			||||||
                <span class="dialog-footer">
 | 
					 | 
				
			||||||
                    <el-button @click="yamlDialog = false">取 消</el-button>
 | 
					 | 
				
			||||||
                    <el-button type="primary" @click="updateService()">更 新</el-button>
 | 
					 | 
				
			||||||
                </span>
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
        </el-dialog>
 | 
					 | 
				
			||||||
        <el-drawer
 | 
					 | 
				
			||||||
            v-model="createServiceDrawer"
 | 
					 | 
				
			||||||
            :direction="direction"
 | 
					 | 
				
			||||||
            :before-close="handleClose">
 | 
					 | 
				
			||||||
            <template #title>
 | 
					 | 
				
			||||||
                <h4>创建Service</h4>
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
            <template #default>
 | 
					 | 
				
			||||||
                <el-row type="flex" justify="center">
 | 
					 | 
				
			||||||
                    <el-col :span="20">
 | 
					 | 
				
			||||||
                        <el-form ref="createService" :rules="createServiceRules" :model="createService" label-width="80px">
 | 
					 | 
				
			||||||
                            <el-form-item class="service-create-form" label="名称" prop="name">
 | 
					 | 
				
			||||||
                                <el-input v-model="createService.name"></el-input>
 | 
					 | 
				
			||||||
                            </el-form-item>
 | 
					 | 
				
			||||||
                            <el-form-item class="service-create-form" label="命名空间" prop="namespace">
 | 
					 | 
				
			||||||
                                <el-select v-model="createService.namespace" filterable placeholder="请选择">
 | 
					 | 
				
			||||||
                                    <el-option
 | 
					 | 
				
			||||||
                                    v-for="(item, index) in namespaceList"
 | 
					 | 
				
			||||||
                                    :key="index"
 | 
					 | 
				
			||||||
                                    :label="item.metadata.name"
 | 
					 | 
				
			||||||
                                    :value="item.metadata.name">
 | 
					 | 
				
			||||||
                                    </el-option>
 | 
					 | 
				
			||||||
                                </el-select>
 | 
					 | 
				
			||||||
                            </el-form-item>
 | 
					 | 
				
			||||||
                            <el-form-item class="service-create-form" label="类型" prop="type">
 | 
					 | 
				
			||||||
                                <el-select v-model="createService.type" placeholder="请选择">
 | 
					 | 
				
			||||||
                                    <el-option value="ClusterIP" label="ClusterIP"></el-option>
 | 
					 | 
				
			||||||
                                    <el-option value="NodePort" label="NodePort"></el-option>
 | 
					 | 
				
			||||||
                                </el-select>
 | 
					 | 
				
			||||||
                            </el-form-item>
 | 
					 | 
				
			||||||
                            <el-form-item class="deploy-create-form" label="容器端口" prop="container_port">
 | 
					 | 
				
			||||||
                                <el-input v-model="createService.container_port" placeholder="示例: 80"></el-input>
 | 
					 | 
				
			||||||
                            </el-form-item>
 | 
					 | 
				
			||||||
                            <el-form-item class="service-create-form" label="Service端口" prop="port">
 | 
					 | 
				
			||||||
                                <el-input v-model="createService.port" placeholder="示例: 80"></el-input>
 | 
					 | 
				
			||||||
                            </el-form-item>
 | 
					 | 
				
			||||||
                            <el-form-item v-if="createService.type == 'NodePort'" class="service-create-form" label="NodePort" prop="node_port">
 | 
					 | 
				
			||||||
                                <el-input v-model="createService.node_port" placeholder="示例: 30001"></el-input>
 | 
					 | 
				
			||||||
                            </el-form-item>
 | 
					 | 
				
			||||||
                            <el-form-item class="SERVICE-create-form" label="标签" prop="label_str">
 | 
					 | 
				
			||||||
                                <el-input v-model="createService.label_str" placeholder="示例: project=ms,app=gateway"></el-input>
 | 
					 | 
				
			||||||
                            </el-form-item>
 | 
					 | 
				
			||||||
                        </el-form>
 | 
					 | 
				
			||||||
                    </el-col>
 | 
					 | 
				
			||||||
                </el-row>
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
            <template #footer>
 | 
					 | 
				
			||||||
                <el-button @click="createServiceDrawer = false">取消</el-button>
 | 
					 | 
				
			||||||
                <el-button type="primary" @click="submitForm('createService')">立即创建</el-button>
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
        </el-drawer>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script>
 | 
					 | 
				
			||||||
import common from "../common/Config";
 | 
					 | 
				
			||||||
import httpClient from '../../utils/request';
 | 
					 | 
				
			||||||
import yaml2obj from 'js-yaml';
 | 
					 | 
				
			||||||
import json2yaml from 'json2yaml';
 | 
					 | 
				
			||||||
export default {
 | 
					 | 
				
			||||||
    data() {
 | 
					 | 
				
			||||||
        return {
 | 
					 | 
				
			||||||
            cmOptions: common.cmOptions,
 | 
					 | 
				
			||||||
            contentYaml: '',
 | 
					 | 
				
			||||||
            currentPage: 1,
 | 
					 | 
				
			||||||
            pagesize: 10,
 | 
					 | 
				
			||||||
            pagesizeList: [10, 20, 30],
 | 
					 | 
				
			||||||
            searchInput: '',
 | 
					 | 
				
			||||||
            namespaceValue: 'default',
 | 
					 | 
				
			||||||
            namespaceList: [],
 | 
					 | 
				
			||||||
            namespaceListUrl: common.k8sNamespaceList,
 | 
					 | 
				
			||||||
            appLoading: false,
 | 
					 | 
				
			||||||
            serviceList: [],
 | 
					 | 
				
			||||||
            serviceTotal: 0,
 | 
					 | 
				
			||||||
            getServicesData: {
 | 
					 | 
				
			||||||
                url: common.k8sServiceList,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    filter_name: '',
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                    page: '',
 | 
					 | 
				
			||||||
                    limit: '',
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            serviceDetail: {},
 | 
					 | 
				
			||||||
            getServiceDetailData: {
 | 
					 | 
				
			||||||
                url: common.k8sServiceDetail,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    service_name: '',
 | 
					 | 
				
			||||||
                    namespace: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            yamlDialog: false,
 | 
					 | 
				
			||||||
            updateServiceData: {
 | 
					 | 
				
			||||||
                url: common.k8sServiceUpdate,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                    content: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            delServiceData: {
 | 
					 | 
				
			||||||
                url: common.k8sServiceDel,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    service_name: '',
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            fullscreenLoading: false,
 | 
					 | 
				
			||||||
            direction: 'rtl',
 | 
					 | 
				
			||||||
            createServiceDrawer: false,
 | 
					 | 
				
			||||||
            createService: {
 | 
					 | 
				
			||||||
                name: '',
 | 
					 | 
				
			||||||
                namespace: '',
 | 
					 | 
				
			||||||
                type: 'ClusterIP',
 | 
					 | 
				
			||||||
                container_port: '',
 | 
					 | 
				
			||||||
                port: '',
 | 
					 | 
				
			||||||
                node_port: '',
 | 
					 | 
				
			||||||
                label: {},
 | 
					 | 
				
			||||||
                label_str: ''
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            createServiceData: {
 | 
					 | 
				
			||||||
                url: common.k8sServiceCreate,
 | 
					 | 
				
			||||||
                params: {}
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            createServiceRules: {
 | 
					 | 
				
			||||||
                name: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请填写名称',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                namespace: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请选择命名空间',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                port: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请填写Service端口',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                node_port: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请填写NodePort',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                label_str: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请填写标签',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                container_port: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请填写容器端口',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    methods: {
 | 
					 | 
				
			||||||
        transYaml(content) {
 | 
					 | 
				
			||||||
            return json2yaml.stringify(content)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        transObj(content) {
 | 
					 | 
				
			||||||
            return yaml2obj.load(content)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        onChange(val) {
 | 
					 | 
				
			||||||
            this.contentYaml = val
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleSizeChange(size) {
 | 
					 | 
				
			||||||
            this.pagesize = size;
 | 
					 | 
				
			||||||
            this.getServices()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleCurrentChange(currentPage) {
 | 
					 | 
				
			||||||
            this.currentPage = currentPage;
 | 
					 | 
				
			||||||
            this.getServices()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleClose(done) {
 | 
					 | 
				
			||||||
            this.$confirm('确认关闭?')
 | 
					 | 
				
			||||||
            .then(() => {
 | 
					 | 
				
			||||||
                done();
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(() => {});
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        ellipsis(value) {
 | 
					 | 
				
			||||||
            return value.length>15?value.substring(0,15)+'...':value
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        timeTrans(timestamp) {
 | 
					 | 
				
			||||||
            let date = new Date(new Date(timestamp).getTime() + 8 * 3600 * 1000)
 | 
					 | 
				
			||||||
            date = date.toJSON();
 | 
					 | 
				
			||||||
            date = date.substring(0, 19).replace('T', ' ')
 | 
					 | 
				
			||||||
            return date 
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        restartTotal(e) {
 | 
					 | 
				
			||||||
            let index, sum = 0
 | 
					 | 
				
			||||||
            let containerStatuses = e.row.status.containerStatuses
 | 
					 | 
				
			||||||
            for ( index in containerStatuses) {
 | 
					 | 
				
			||||||
                sum = sum + containerStatuses[index].restartCount 
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return sum
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getNamespaces() {
 | 
					 | 
				
			||||||
            httpClient.get(this.namespaceListUrl)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.namespaceList = res.data.items
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getServices() {
 | 
					 | 
				
			||||||
            this.appLoading = true
 | 
					 | 
				
			||||||
            this.getServicesData.params.filter_name = this.searchInput
 | 
					 | 
				
			||||||
            this.getServicesData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            this.getServicesData.params.page = this.currentPage
 | 
					 | 
				
			||||||
            this.getServicesData.params.limit = this.pagesize
 | 
					 | 
				
			||||||
            httpClient.get(this.getServicesData.url, {params: this.getServicesData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.serviceList = res.data.items
 | 
					 | 
				
			||||||
                this.serviceTotal = res.data.total
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.appLoading = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getServiceDetail(e) {
 | 
					 | 
				
			||||||
            this.getServiceDetailData.params.service_name = e.row.metadata.name
 | 
					 | 
				
			||||||
            this.getServiceDetailData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            httpClient.get(this.getServiceDetailData.url, {params: this.getServiceDetailData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.serviceDetail = res.data
 | 
					 | 
				
			||||||
                this.contentYaml = this.transYaml(this.serviceDetail)
 | 
					 | 
				
			||||||
                this.yamlDialog = true
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        updateService() {
 | 
					 | 
				
			||||||
            let content = JSON.stringify(this.transObj(this.contentYaml))
 | 
					 | 
				
			||||||
            this.updateServiceData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            this.updateServiceData.params.content = content
 | 
					 | 
				
			||||||
            httpClient.put(this.updateServiceData.url, this.updateServiceData.params)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.yamlDialog = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        delService(e) {
 | 
					 | 
				
			||||||
            this.delServiceData.params.service_name = e.row.metadata.name
 | 
					 | 
				
			||||||
            this.delServiceData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            httpClient.delete(this.delServiceData.url, {data: this.delServiceData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.getServices()
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleConfirm(obj, operateName, fn) {
 | 
					 | 
				
			||||||
            this.confirmContent = '确认继续 ' + operateName + ' 操作吗?'
 | 
					 | 
				
			||||||
            this.$confirm(this.confirmContent,'提示',{
 | 
					 | 
				
			||||||
                confirmButtonText: '确定',
 | 
					 | 
				
			||||||
                cancelButtonText: '取消',
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .then(() => {
 | 
					 | 
				
			||||||
                fn(obj)
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            .catch(() => {
 | 
					 | 
				
			||||||
                this.$message.info({
 | 
					 | 
				
			||||||
                    message: '已取消操作'
 | 
					 | 
				
			||||||
                })          
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        createServiceFunc() {
 | 
					 | 
				
			||||||
            let reg = new RegExp("(^[A-Za-z]+=[A-Za-z0-9]+).*")
 | 
					 | 
				
			||||||
            if (!reg.test(this.createService.label_str)) {
 | 
					 | 
				
			||||||
                this.$message.warning({
 | 
					 | 
				
			||||||
                    message: "标签填写异常,请确认后重新填写"
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
                return
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            this.fullscreenLoading = true
 | 
					 | 
				
			||||||
            let label = new Map()
 | 
					 | 
				
			||||||
            let a = (this.createService.label_str).split(",")
 | 
					 | 
				
			||||||
            a.forEach(item => {
 | 
					 | 
				
			||||||
                let b = item.split("=")
 | 
					 | 
				
			||||||
                label[b[0]] = b[1]
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.createServiceData.params = this.createService
 | 
					 | 
				
			||||||
            this.createServiceData.params.label = label
 | 
					 | 
				
			||||||
            this.createServiceData.params.container_port = parseInt(this.createService.container_port)
 | 
					 | 
				
			||||||
            this.createServiceData.params.port = parseInt(this.createService.port)
 | 
					 | 
				
			||||||
            this.createServiceData.params.node_port = parseInt(this.createService.node_port)
 | 
					 | 
				
			||||||
            httpClient.post(this.createServiceData.url, this.createServiceData.params)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
                this.getServices()
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.resetForm('createService')
 | 
					 | 
				
			||||||
            this.fullscreenLoading = false
 | 
					 | 
				
			||||||
            this.createServiceDrawer = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        resetForm(formName) {
 | 
					 | 
				
			||||||
            this.$refs[formName].resetFields()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        submitForm(formName) {
 | 
					 | 
				
			||||||
            this.$refs[formName].validate((valid) => {
 | 
					 | 
				
			||||||
                if (valid) {
 | 
					 | 
				
			||||||
                    this.createServiceFunc()
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    return false;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    watch: {
 | 
					 | 
				
			||||||
        namespaceValue: {
 | 
					 | 
				
			||||||
            handler() {
 | 
					 | 
				
			||||||
                localStorage.setItem('namespace', this.namespaceValue)
 | 
					 | 
				
			||||||
                this.currentPage = 1
 | 
					 | 
				
			||||||
                this.getServices()
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    beforeMount() {
 | 
					 | 
				
			||||||
        if (localStorage.getItem('namespace') !== undefined && localStorage.getItem('namespace') !== null) {
 | 
					 | 
				
			||||||
            this.namespaceValue = localStorage.getItem('namespace')
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        this.getNamespaces()
 | 
					 | 
				
			||||||
        this.getServices()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style scoped>
 | 
					 | 
				
			||||||
    .service-head-card,.service-body-card {
 | 
					 | 
				
			||||||
        border-radius: 1px;
 | 
					 | 
				
			||||||
        margin-bottom: 5px;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .service-head-search {
 | 
					 | 
				
			||||||
        width:160px;
 | 
					 | 
				
			||||||
        margin-right:10px; 
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .service-body-servicename {
 | 
					 | 
				
			||||||
        color: #4795EE;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .service-body-servicename:hover {
 | 
					 | 
				
			||||||
        color: rgb(84, 138, 238);
 | 
					 | 
				
			||||||
        cursor: pointer;
 | 
					 | 
				
			||||||
        font-weight: bold;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
@ -1,370 +0,0 @@
 | 
				
			|||||||
<template>
 | 
					 | 
				
			||||||
    <div class="statefulset">
 | 
					 | 
				
			||||||
        <el-row>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="statefulset-head-card" shadow="never" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                        <el-row>
 | 
					 | 
				
			||||||
                            <el-col :span="6">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <span>命名空间: </span>
 | 
					 | 
				
			||||||
                                    <el-select v-model="namespaceValue" filterable placeholder="请选择">
 | 
					 | 
				
			||||||
                                        <el-option
 | 
					 | 
				
			||||||
                                        v-for="(item, index) in namespaceList"
 | 
					 | 
				
			||||||
                                        :key="index"
 | 
					 | 
				
			||||||
                                        :label="item.metadata.name"
 | 
					 | 
				
			||||||
                                        :value="item.metadata.name">
 | 
					 | 
				
			||||||
                                        </el-option>
 | 
					 | 
				
			||||||
                                    </el-select>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                            <el-col :span="2" :offset="16">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Refresh" plain @click="getStatefulSets()">刷新</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                        </el-row>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="statefulset-head-card" shadow="never" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                        <el-row>
 | 
					 | 
				
			||||||
                            <el-col :span="2">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-button disabled style="border-radius:2px;" icon="Edit" type="primary">创建</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                            <el-col :span="6">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-input class="statefulset-head-search" clearable placeholder="请输入" v-model="searchInput"></el-input>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Search" type="primary" plain @click="getStatefulSets()">搜索</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                        </el-row>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="statefulset-body-card" shadow="never" :body-style="{padding:'5px'}">
 | 
					 | 
				
			||||||
                        <el-table
 | 
					 | 
				
			||||||
                        style="width:100%;font-size:12px;margin-bottom:10px;"
 | 
					 | 
				
			||||||
                        :data="statefulSetList"
 | 
					 | 
				
			||||||
                        v-loading="appLoading">
 | 
					 | 
				
			||||||
                            <el-table-column width="20"></el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=left label="StatefulSet名">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <a class="statefulset-body-statefulsetname">{{ scope.row.metadata.name }}</a>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="标签">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <div v-for="(val, key) in scope.row.metadata.labels" :key="key">
 | 
					 | 
				
			||||||
                                        <el-popover
 | 
					 | 
				
			||||||
                                            placement="right"
 | 
					 | 
				
			||||||
                                            :width="200"
 | 
					 | 
				
			||||||
                                            trigger="hover"
 | 
					 | 
				
			||||||
                                            :content="key + ':' + val">
 | 
					 | 
				
			||||||
                                            <template #reference>
 | 
					 | 
				
			||||||
                                                <el-tag style="margin-bottom: 5px" type="warning">{{ ellipsis(key + ":" + val) }}</el-tag>
 | 
					 | 
				
			||||||
                                            </template>
 | 
					 | 
				
			||||||
                                        </el-popover>
 | 
					 | 
				
			||||||
                                    </div>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="容器组">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <span>{{ scope.row.status.currentReplicas>0?scope.row.status.currentReplicas:0  }} / {{ scope.row.spec.replicas>0?scope.row.spec.replicas:0 }} </span>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center min-width="100" label="创建时间">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-tag type="info">{{ timeTrans(scope.row.metadata.creationTimestamp) }} </el-tag>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="镜像">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <div v-for="(val, key) in scope.row.spec.template.spec.containers" :key="key">
 | 
					 | 
				
			||||||
                                        <el-popover
 | 
					 | 
				
			||||||
                                            placement="right"
 | 
					 | 
				
			||||||
                                            :width="200"
 | 
					 | 
				
			||||||
                                            trigger="hover"
 | 
					 | 
				
			||||||
                                            :content="val.image">
 | 
					 | 
				
			||||||
                                            <template #reference>
 | 
					 | 
				
			||||||
                                                <el-tag style="margin-bottom: 5px">{{ ellipsis(val.image.split('/')[2]==undefined?val.image:val.image.split('/')[2]) }}</el-tag>
 | 
					 | 
				
			||||||
                                            </template>
 | 
					 | 
				
			||||||
                                        </el-popover>
 | 
					 | 
				
			||||||
                                    </div>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="操作" width="200">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-button size="small" style="border-radius:2px;" icon="Edit" type="primary" plain @click="getStatefulSetDetail(scope)">YAML</el-button>
 | 
					 | 
				
			||||||
                                    <el-button size="small" style="border-radius:2px;" icon="Delete" type="danger" @click="handleConfirm(scope, '删除', delStatefulSet)">删除</el-button>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                        </el-table>
 | 
					 | 
				
			||||||
                        <el-pagination
 | 
					 | 
				
			||||||
                        class="statefulset-body-pagination"
 | 
					 | 
				
			||||||
                        background
 | 
					 | 
				
			||||||
                        @size-change="handleSizeChange"
 | 
					 | 
				
			||||||
                        @current-change="handleCurrentChange"
 | 
					 | 
				
			||||||
                        :current-page="currentPage"
 | 
					 | 
				
			||||||
                        :page-sizes="pagesizeList"
 | 
					 | 
				
			||||||
                        :page-size="pagesize"
 | 
					 | 
				
			||||||
                        layout="total, sizes, prev, pager, next, jumper"
 | 
					 | 
				
			||||||
                        :total="statefulSetTotal">
 | 
					 | 
				
			||||||
                        </el-pagination>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
        </el-row>
 | 
					 | 
				
			||||||
        <el-dialog title="YAML信息" v-model="yamlDialog" width="45%" top="5%">
 | 
					 | 
				
			||||||
            <codemirror
 | 
					 | 
				
			||||||
                :value="contentYaml"
 | 
					 | 
				
			||||||
                border
 | 
					 | 
				
			||||||
                :options="cmOptions"
 | 
					 | 
				
			||||||
                height="500"
 | 
					 | 
				
			||||||
                style="font-size:14px;"
 | 
					 | 
				
			||||||
                @change="onChange"
 | 
					 | 
				
			||||||
            ></codemirror>
 | 
					 | 
				
			||||||
            <template #footer>
 | 
					 | 
				
			||||||
                <span class="dialog-footer">
 | 
					 | 
				
			||||||
                    <el-button @click="yamlDialog = false">取 消</el-button>
 | 
					 | 
				
			||||||
                    <el-button type="primary" @click="updateStatefulSet()">更 新</el-button>
 | 
					 | 
				
			||||||
                </span>
 | 
					 | 
				
			||||||
            </template>
 | 
					 | 
				
			||||||
        </el-dialog>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script>
 | 
					 | 
				
			||||||
import common from "../common/Config";
 | 
					 | 
				
			||||||
import httpClient from '../../utils/request';
 | 
					 | 
				
			||||||
import yaml2obj from 'js-yaml';
 | 
					 | 
				
			||||||
import json2yaml from 'json2yaml';
 | 
					 | 
				
			||||||
export default {
 | 
					 | 
				
			||||||
    data() {
 | 
					 | 
				
			||||||
        return {
 | 
					 | 
				
			||||||
            cmOptions: common.cmOptions,
 | 
					 | 
				
			||||||
            contentYaml: '',
 | 
					 | 
				
			||||||
            currentPage: 1,
 | 
					 | 
				
			||||||
            pagesize: 10,
 | 
					 | 
				
			||||||
            pagesizeList: [10, 20, 30],
 | 
					 | 
				
			||||||
            searchInput: '',
 | 
					 | 
				
			||||||
            namespaceValue: 'default',
 | 
					 | 
				
			||||||
            namespaceList: [],
 | 
					 | 
				
			||||||
            namespaceListUrl: common.k8sNamespaceList,
 | 
					 | 
				
			||||||
            appLoading: false,
 | 
					 | 
				
			||||||
            statefulSetList: [],
 | 
					 | 
				
			||||||
            statefulSetTotal: 0,
 | 
					 | 
				
			||||||
            getStatefulSetsData: {
 | 
					 | 
				
			||||||
                url: common.k8sStatefulSetList,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    filter_name: '',
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                    page: '',
 | 
					 | 
				
			||||||
                    limit: '',
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            statefulSetDetail: {},
 | 
					 | 
				
			||||||
            getStatefulSetDetailData: {
 | 
					 | 
				
			||||||
                url: common.k8sStatefulSetDetail,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    statefulset_name: '',
 | 
					 | 
				
			||||||
                    namespace: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            yamlDialog: false,
 | 
					 | 
				
			||||||
            updateStatefulSetData: {
 | 
					 | 
				
			||||||
                url: common.k8sStatefulSetUpdate,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                    content: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            delStatefulSetData: {
 | 
					 | 
				
			||||||
                url: common.k8sstatefulsetDel,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    statefulset_name: '',
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    methods: {
 | 
					 | 
				
			||||||
        transYaml(content) {
 | 
					 | 
				
			||||||
            return json2yaml.stringify(content)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        transObj(content) {
 | 
					 | 
				
			||||||
            return yaml2obj.load(content)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        onChange(val) {
 | 
					 | 
				
			||||||
            this.contentYaml = val
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleSizeChange(size) {
 | 
					 | 
				
			||||||
            this.pagesize = size;
 | 
					 | 
				
			||||||
            this.getStatefulSets()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleCurrentChange(currentPage) {
 | 
					 | 
				
			||||||
            this.currentPage = currentPage;
 | 
					 | 
				
			||||||
            this.getStatefulSets()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleClose(done) {
 | 
					 | 
				
			||||||
            this.$confirm('确认关闭?')
 | 
					 | 
				
			||||||
            .then(() => {
 | 
					 | 
				
			||||||
                done();
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(() => {});
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        ellipsis(value) {
 | 
					 | 
				
			||||||
            return value.length>15?value.substring(0,15)+'...':value
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        timeTrans(timestamp) {
 | 
					 | 
				
			||||||
            let date = new Date(new Date(timestamp).getTime() + 8 * 3600 * 1000)
 | 
					 | 
				
			||||||
            date = date.toJSON();
 | 
					 | 
				
			||||||
            date = date.substring(0, 19).replace('T', ' ')
 | 
					 | 
				
			||||||
            return date 
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        restartTotal(e) {
 | 
					 | 
				
			||||||
            let index, sum = 0
 | 
					 | 
				
			||||||
            let containerStatuses = e.row.status.containerStatuses
 | 
					 | 
				
			||||||
            for ( index in containerStatuses) {
 | 
					 | 
				
			||||||
                sum = sum + containerStatuses[index].restartCount 
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return sum
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getNamespaces() {
 | 
					 | 
				
			||||||
            httpClient.get(this.namespaceListUrl)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.namespaceList = res.data.items
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getStatefulSets() {
 | 
					 | 
				
			||||||
            this.appLoading = true
 | 
					 | 
				
			||||||
            this.getStatefulSetsData.params.filter_name = this.searchInput
 | 
					 | 
				
			||||||
            this.getStatefulSetsData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            this.getStatefulSetsData.params.page = this.currentPage
 | 
					 | 
				
			||||||
            this.getStatefulSetsData.params.limit = this.pagesize
 | 
					 | 
				
			||||||
            httpClient.get(this.getStatefulSetsData.url, {params: this.getStatefulSetsData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.statefulSetList = res.data.items
 | 
					 | 
				
			||||||
                this.statefulSetTotal = res.data.total
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.appLoading = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getStatefulSetDetail(e) {
 | 
					 | 
				
			||||||
            this.getStatefulSetDetailData.params.statefulset_name = e.row.metadata.name
 | 
					 | 
				
			||||||
            this.getStatefulSetDetailData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            httpClient.get(this.getStatefulSetDetailData.url, {params: this.getStatefulSetDetailData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.statefulSetDetail = res.data
 | 
					 | 
				
			||||||
                this.contentYaml = this.transYaml(this.statefulSetDetail)
 | 
					 | 
				
			||||||
                this.yamlDialog = true
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        updateStatefulSet() {
 | 
					 | 
				
			||||||
            let content = JSON.stringify(this.transObj(this.contentYaml))
 | 
					 | 
				
			||||||
            this.updateStatefulSetData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            this.updateStatefulSetData.params.content = content
 | 
					 | 
				
			||||||
            httpClient.put(this.updateStatefulSetData.url, this.updateStatefulSetData.params)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.yamlDialog = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        delStatefulSet(e) {
 | 
					 | 
				
			||||||
            this.delStatefulSetData.params.statefulset_name = e.row.metadata.name
 | 
					 | 
				
			||||||
            this.delStatefulSetData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            httpClient.delete(this.delStatefulSetData.url, {data: this.delStatefulSetData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.getStatefulSets()
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleConfirm(obj, operateName, fn) {
 | 
					 | 
				
			||||||
            this.confirmContent = '确认继续 ' + operateName + ' 操作吗?'
 | 
					 | 
				
			||||||
            this.$confirm(this.confirmContent,'提示',{
 | 
					 | 
				
			||||||
                confirmButtonText: '确定',
 | 
					 | 
				
			||||||
                cancelButtonText: '取消',
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .then(() => {
 | 
					 | 
				
			||||||
                fn(obj)
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            .catch(() => {
 | 
					 | 
				
			||||||
                this.$message.info({
 | 
					 | 
				
			||||||
                    message: '已取消操作'
 | 
					 | 
				
			||||||
                })          
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    watch: {
 | 
					 | 
				
			||||||
        namespaceValue: {
 | 
					 | 
				
			||||||
            handler() {
 | 
					 | 
				
			||||||
                localStorage.setItem('namespace', this.namespaceValue)
 | 
					 | 
				
			||||||
                this.currentPage = 1
 | 
					 | 
				
			||||||
                this.getStatefulSets()
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    beforeMount() {
 | 
					 | 
				
			||||||
        if (localStorage.getItem('namespace') !== undefined && localStorage.getItem('namespace') !== null) {
 | 
					 | 
				
			||||||
            this.namespaceValue = localStorage.getItem('namespace')
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        this.getNamespaces()
 | 
					 | 
				
			||||||
        this.getStatefulSets()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style scoped>
 | 
					 | 
				
			||||||
    .statefulset-head-card,.statefulset-body-card {
 | 
					 | 
				
			||||||
        border-radius: 1px;
 | 
					 | 
				
			||||||
        margin-bottom: 5px;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .statefulset-head-search {
 | 
					 | 
				
			||||||
        width:160px;
 | 
					 | 
				
			||||||
        margin-right:10px; 
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .statefulset-body-statefulsetname {
 | 
					 | 
				
			||||||
        color: #4795EE;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .statefulset-body-statefulsetname:hover {
 | 
					 | 
				
			||||||
        color: rgb(84, 138, 238);
 | 
					 | 
				
			||||||
        cursor: pointer;
 | 
					 | 
				
			||||||
        font-weight: bold;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@ -1,608 +0,0 @@
 | 
				
			|||||||
<template>
 | 
					 | 
				
			||||||
    <div class="workflow">
 | 
					 | 
				
			||||||
        <el-row>
 | 
					 | 
				
			||||||
            <!-- header1 -->
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="workflow-head-card" shadow="never" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                        <el-row>
 | 
					 | 
				
			||||||
                            <el-col :span="6">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <span>命名空间: </span>
 | 
					 | 
				
			||||||
                                    <el-select v-model="namespaceValue" filterable placeholder="请选择">
 | 
					 | 
				
			||||||
                                        <el-option
 | 
					 | 
				
			||||||
                                        v-for="(item, index) in namespaceList"
 | 
					 | 
				
			||||||
                                        :key="index"
 | 
					 | 
				
			||||||
                                        :label="item.metadata.name"
 | 
					 | 
				
			||||||
                                        :value="item.metadata.name">
 | 
					 | 
				
			||||||
                                        </el-option>
 | 
					 | 
				
			||||||
                                    </el-select>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                            <el-col :span="2" :offset="16">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Refresh" plain @click="getWorkflows()">刷新</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                        </el-row>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
            <!-- header2 -->
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="workflow-head-card" shadow="never" :body-style="{padding:'30px 10px 20px 10px'}">
 | 
					 | 
				
			||||||
                        <el-steps :active="active" align-center finish-status="success">
 | 
					 | 
				
			||||||
                            <el-step title="步骤1" description="选择工作流类型, ClusterIP NodePort Workflow"></el-step>
 | 
					 | 
				
			||||||
                            <el-step title="步骤2" description="填写Deployment Workflow Workflow表单"></el-step>
 | 
					 | 
				
			||||||
                            <el-step title="步骤3" description="创建Deployment Workflow Workflow"></el-step>
 | 
					 | 
				
			||||||
                        </el-steps>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
            <!-- header3 -->
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="workflow-head-card" shadow="never" :body-style="{padding:'10px'}">
 | 
					 | 
				
			||||||
                        <el-row>
 | 
					 | 
				
			||||||
                            <el-col :span="3">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Edit" type="primary" @click="createWorkflowDrawerIndex1 = true" v-loading.fullscreen.lock="fullscreenLoading">创建工作流</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                            <el-col :span="6">
 | 
					 | 
				
			||||||
                                <div>
 | 
					 | 
				
			||||||
                                    <el-input class="workflow-head-search" clearable placeholder="请输入" v-model="searchInput"></el-input>
 | 
					 | 
				
			||||||
                                    <el-button style="border-radius:2px;" icon="Search" type="primary" plain @click="getWorkflows()">搜索</el-button>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </el-col>
 | 
					 | 
				
			||||||
                        </el-row>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
            <el-col :span="24">
 | 
					 | 
				
			||||||
                <div>
 | 
					 | 
				
			||||||
                    <el-card class="workflow-body-card" shadow="never" :body-style="{padding:'5px'}">
 | 
					 | 
				
			||||||
                        <el-table
 | 
					 | 
				
			||||||
                        style="width:100%;font-size:12px;margin-bottom:10px;"
 | 
					 | 
				
			||||||
                        :data="workflowList"
 | 
					 | 
				
			||||||
                        v-loading="appLoading">
 | 
					 | 
				
			||||||
                            <el-table-column width="20"></el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column min-width="50" align=left label="ID" prop="id"></el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column min-width="100" label="Workflow名">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <a class="workflow-body-workflowname">{{ scope.row.name }}</a>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column label="类型" prop="type">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-tag type="warning">{{ scope.row.type }}</el-tag>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column label="实例数" prop="replicas"></el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column min-width="100" label="deployment" prop="deployment"></el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column min-width="150" label="service" prop="service"></el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column min-width="150" label="ingress" prop="ingress"></el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center min-width="150" label="创建时间">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-tag type="info">{{ timeTransNot8(scope.row.created_at) }} </el-tag>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                            <el-table-column align=center label="操作" width="200">
 | 
					 | 
				
			||||||
                                <template v-slot="scope">
 | 
					 | 
				
			||||||
                                    <el-button size="small" disabled style="border-radius:2px;" icon="Edit" type="primary" plain @click="getWorkflowDetail(scope)">详情</el-button>
 | 
					 | 
				
			||||||
                                    <el-button size="small" style="border-radius:2px;" icon="Delete" type="danger" @click="handleConfirm(scope, '删除', delWorkflow)">删除</el-button>
 | 
					 | 
				
			||||||
                                </template>
 | 
					 | 
				
			||||||
                            </el-table-column>
 | 
					 | 
				
			||||||
                        </el-table>
 | 
					 | 
				
			||||||
                        <el-pagination
 | 
					 | 
				
			||||||
                        class="workflow-body-pagination"
 | 
					 | 
				
			||||||
                        background
 | 
					 | 
				
			||||||
                        @size-change="handleSizeChange"
 | 
					 | 
				
			||||||
                        @current-change="handleCurrentChange"
 | 
					 | 
				
			||||||
                        :current-page="currentPage"
 | 
					 | 
				
			||||||
                        :page-sizes="pagesizeList"
 | 
					 | 
				
			||||||
                        :page-size="pagesize"
 | 
					 | 
				
			||||||
                        layout="total, sizes, prev, pager, next, jumper"
 | 
					 | 
				
			||||||
                        :total="workflowTotal">
 | 
					 | 
				
			||||||
                        </el-pagination>
 | 
					 | 
				
			||||||
                    </el-card>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </el-col>
 | 
					 | 
				
			||||||
        </el-row>
 | 
					 | 
				
			||||||
    <el-drawer
 | 
					 | 
				
			||||||
        v-model="createWorkflowDrawerIndex1"
 | 
					 | 
				
			||||||
        :direction="direction"
 | 
					 | 
				
			||||||
        :before-close="handleClose">
 | 
					 | 
				
			||||||
        <template #title>
 | 
					 | 
				
			||||||
            <h4>创建Workflow-步骤1</h4>
 | 
					 | 
				
			||||||
        </template>
 | 
					 | 
				
			||||||
        <template #default>
 | 
					 | 
				
			||||||
            <el-row type="flex" justify="center">
 | 
					 | 
				
			||||||
                <el-col :span="20">
 | 
					 | 
				
			||||||
                    <el-form label-width="80px">
 | 
					 | 
				
			||||||
                        <el-form-item class="workflow-create-form" label="类型" prop="name">
 | 
					 | 
				
			||||||
                            <el-radio v-model="createWorkflow.type" label="ClusterIP">ClusterIP</el-radio>
 | 
					 | 
				
			||||||
                            <el-radio v-model="createWorkflow.type" label="NodePort">NodePort</el-radio>
 | 
					 | 
				
			||||||
                            <el-radio v-model="createWorkflow.type" label="Ingress">Ingress</el-radio>
 | 
					 | 
				
			||||||
                        </el-form-item>
 | 
					 | 
				
			||||||
                    </el-form>
 | 
					 | 
				
			||||||
                </el-col>
 | 
					 | 
				
			||||||
            </el-row>
 | 
					 | 
				
			||||||
        </template>
 | 
					 | 
				
			||||||
        <template #footer>
 | 
					 | 
				
			||||||
            <el-button @click="drawerCancel('createWorkflowDrawerIndex1')">取消</el-button>
 | 
					 | 
				
			||||||
            <el-button type="primary" @click="workflowIndex1Next()">下一步</el-button>
 | 
					 | 
				
			||||||
        </template>
 | 
					 | 
				
			||||||
    </el-drawer>
 | 
					 | 
				
			||||||
    <el-drawer
 | 
					 | 
				
			||||||
        v-model="createWorkflowDrawerIndex2_1"
 | 
					 | 
				
			||||||
        :direction="direction"
 | 
					 | 
				
			||||||
        :before-close="handleClose">
 | 
					 | 
				
			||||||
        <template #title>
 | 
					 | 
				
			||||||
            <h4>创建Workflow-步骤2</h4>
 | 
					 | 
				
			||||||
        </template>
 | 
					 | 
				
			||||||
        <template #default>
 | 
					 | 
				
			||||||
            <el-row type="flex" justify="center">
 | 
					 | 
				
			||||||
                <el-col :span="20">
 | 
					 | 
				
			||||||
                    <el-form ref="createWorkflow" :rules="createWorkflowRules" :model="createWorkflow" label-width="80px">
 | 
					 | 
				
			||||||
                        <h4 style="margin-bottom:10px">Deployment</h4>
 | 
					 | 
				
			||||||
                        <el-form-item class="workflow-create-form" label="名称" prop="name">
 | 
					 | 
				
			||||||
                            <el-input v-model="createWorkflow.name"></el-input>
 | 
					 | 
				
			||||||
                        </el-form-item>
 | 
					 | 
				
			||||||
                        <el-form-item class="workflow-create-form" label="命名空间" prop="namespace">
 | 
					 | 
				
			||||||
                            <el-select v-model="createWorkflow.namespace" filterable placeholder="请选择">
 | 
					 | 
				
			||||||
                                <el-option
 | 
					 | 
				
			||||||
                                v-for="(item, index) in namespaceList"
 | 
					 | 
				
			||||||
                                :key="index"
 | 
					 | 
				
			||||||
                                :label="item.metadata.name"
 | 
					 | 
				
			||||||
                                :value="item.metadata.name">
 | 
					 | 
				
			||||||
                                </el-option>
 | 
					 | 
				
			||||||
                            </el-select>
 | 
					 | 
				
			||||||
                        </el-form-item>
 | 
					 | 
				
			||||||
                        <el-form-item class="workflow-create-form" label="副本数" prop="replicas">
 | 
					 | 
				
			||||||
                            <el-input-number v-model="createWorkflow.replicas" :min="1" :max="10"></el-input-number>
 | 
					 | 
				
			||||||
                                <el-popover
 | 
					 | 
				
			||||||
                                    placement="top"
 | 
					 | 
				
			||||||
                                    :width="100"
 | 
					 | 
				
			||||||
                                    trigger="hover"
 | 
					 | 
				
			||||||
                                    content="申请副本数上限为10个">
 | 
					 | 
				
			||||||
                                    <template #reference>
 | 
					 | 
				
			||||||
                                        <el-icon style="width:2em;font-size:18px;color:#4795EE"><WarningFilled/></el-icon>
 | 
					 | 
				
			||||||
                                    </template>
 | 
					 | 
				
			||||||
                                </el-popover>
 | 
					 | 
				
			||||||
                        </el-form-item>
 | 
					 | 
				
			||||||
                        <el-form-item class="workflow-create-form" label="镜像" prop="image">
 | 
					 | 
				
			||||||
                            <el-input v-model="createWorkflow.image"></el-input>
 | 
					 | 
				
			||||||
                        </el-form-item>
 | 
					 | 
				
			||||||
                        <el-form-item class="workflow-create-form" label="标签" prop="label_str">
 | 
					 | 
				
			||||||
                            <el-input v-model="createWorkflow.label_str" placeholder="示例: project=ms,app=gateway"></el-input>
 | 
					 | 
				
			||||||
                        </el-form-item>
 | 
					 | 
				
			||||||
                        <el-form-item class="workflow-create-form" label="资源配额" prop="resource">
 | 
					 | 
				
			||||||
                            <el-select v-model="createWorkflow.resource" placeholder="请选择">
 | 
					 | 
				
			||||||
                                <el-option value="0.5/1" label="0.5C1G"></el-option>
 | 
					 | 
				
			||||||
                                <el-option value="1/2" label="1C2G"></el-option>
 | 
					 | 
				
			||||||
                                <el-option value="2/4" label="2C4G"></el-option>
 | 
					 | 
				
			||||||
                                <el-option value="4/8" label="4C8G"></el-option>
 | 
					 | 
				
			||||||
                            </el-select>
 | 
					 | 
				
			||||||
                        </el-form-item>
 | 
					 | 
				
			||||||
                        <el-form-item class="workflow-create-form" label="容器端口" prop="container_port">
 | 
					 | 
				
			||||||
                            <el-input v-model="createWorkflow.container_port" placeholder="示例: 80"></el-input>
 | 
					 | 
				
			||||||
                        </el-form-item>
 | 
					 | 
				
			||||||
                        <el-form-item class="workflow-create-form" label="健康检查" prop="health">
 | 
					 | 
				
			||||||
                            <el-switch v-model="createWorkflow.health_check" />
 | 
					 | 
				
			||||||
                        </el-form-item>
 | 
					 | 
				
			||||||
                        <el-form-item class="workflow-create-form" label="检查路径" prop="healthPath">
 | 
					 | 
				
			||||||
                            <el-input v-model="createWorkflow.health_path" placeholder="示例: /health"></el-input>
 | 
					 | 
				
			||||||
                        </el-form-item>
 | 
					 | 
				
			||||||
                    </el-form>
 | 
					 | 
				
			||||||
                </el-col>
 | 
					 | 
				
			||||||
            </el-row>
 | 
					 | 
				
			||||||
        </template>
 | 
					 | 
				
			||||||
        <template #footer>
 | 
					 | 
				
			||||||
            <el-button @click="drawerCancel('createWorkflowDrawerIndex2_1')">取消</el-button>
 | 
					 | 
				
			||||||
            <el-button type="primary" @click="submitForm('createWorkflow', workflowIndex2_1Next)">下一步</el-button>
 | 
					 | 
				
			||||||
        </template>
 | 
					 | 
				
			||||||
    </el-drawer>
 | 
					 | 
				
			||||||
    <el-drawer
 | 
					 | 
				
			||||||
        v-model="createWorkflowDrawerIndex2_2"
 | 
					 | 
				
			||||||
        :direction="direction"
 | 
					 | 
				
			||||||
        :before-close="handleClose">
 | 
					 | 
				
			||||||
        <template #title>
 | 
					 | 
				
			||||||
            <h4>创建Workflow-步骤2</h4>
 | 
					 | 
				
			||||||
        </template>
 | 
					 | 
				
			||||||
        <template #default>
 | 
					 | 
				
			||||||
            <el-row type="flex" justify="center">
 | 
					 | 
				
			||||||
                <el-col :span="20">
 | 
					 | 
				
			||||||
                    <el-form ref="createWorkflow" :rules="createWorkflowRules" :model="createWorkflow" label-width="80px">
 | 
					 | 
				
			||||||
                        <h4 style="margin-bottom:10px">Service</h4>
 | 
					 | 
				
			||||||
                        <el-form-item class="service-create-form" label="Service端口" prop="port">
 | 
					 | 
				
			||||||
                            <el-input v-model="createWorkflow.port" placeholder="示例: 80"></el-input>
 | 
					 | 
				
			||||||
                        </el-form-item>
 | 
					 | 
				
			||||||
                        <el-form-item v-if="createWorkflow.type == 'NodePort'" class="service-create-form" label="NodePort" prop="node_port">
 | 
					 | 
				
			||||||
                            <el-input v-model="createWorkflow.node_port" placeholder="示例: 30001"></el-input>
 | 
					 | 
				
			||||||
                        </el-form-item>
 | 
					 | 
				
			||||||
                        <el-divider v-if="createWorkflow.type == 'Ingress'"></el-divider>
 | 
					 | 
				
			||||||
                        <h4 v-if="createWorkflow.type == 'Ingress'" style="margin-bottom:10px">Ingress</h4>
 | 
					 | 
				
			||||||
                        <el-form-item v-if="createWorkflow.type == 'Ingress'" class="deploy-create-form" label="域名" prop="host">
 | 
					 | 
				
			||||||
                            <el-input v-model="createWorkflow.host" placeholder="示例: www.example.com"></el-input>
 | 
					 | 
				
			||||||
                        </el-form-item>
 | 
					 | 
				
			||||||
                        <el-form-item v-if="createWorkflow.type == 'Ingress'" class="ingress-create-form" label="Path" prop="path">
 | 
					 | 
				
			||||||
                            <el-input v-model="createWorkflow.path" placeholder="示例: /abc"></el-input>
 | 
					 | 
				
			||||||
                        </el-form-item>
 | 
					 | 
				
			||||||
                        <el-form-item v-if="createWorkflow.type == 'Ingress'" class="deploy-create-form" label="匹配类型" prop="path_type">
 | 
					 | 
				
			||||||
                            <el-select v-model="createWorkflow.path_type" placeholder="请选择">
 | 
					 | 
				
			||||||
                                <el-option value="Prefix" label="Prefix"></el-option>
 | 
					 | 
				
			||||||
                                <el-option value="Exact" label="Exact"></el-option>
 | 
					 | 
				
			||||||
                                <el-option value="ImplementationSpecific" label="ImplementationSpecific"></el-option>
 | 
					 | 
				
			||||||
                            </el-select>
 | 
					 | 
				
			||||||
                        </el-form-item>
 | 
					 | 
				
			||||||
                    </el-form>
 | 
					 | 
				
			||||||
                </el-col>
 | 
					 | 
				
			||||||
            </el-row>
 | 
					 | 
				
			||||||
        </template>
 | 
					 | 
				
			||||||
        <template #footer>
 | 
					 | 
				
			||||||
            <el-button @click="drawerCancel('createWorkflowDrawerIndex2_2')">取消</el-button>
 | 
					 | 
				
			||||||
            <el-button type="primary" @click="submitForm('createWorkflow', createWorkflowFunc)">立即创建</el-button>
 | 
					 | 
				
			||||||
        </template>
 | 
					 | 
				
			||||||
    </el-drawer>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script>
 | 
					 | 
				
			||||||
import common from "../common/Config";
 | 
					 | 
				
			||||||
import httpClient from '../../utils/request';
 | 
					 | 
				
			||||||
export default {
 | 
					 | 
				
			||||||
    data() {
 | 
					 | 
				
			||||||
        return {
 | 
					 | 
				
			||||||
            active: 0,
 | 
					 | 
				
			||||||
            createWorkflowDrawerIndex1: false,
 | 
					 | 
				
			||||||
            createWorkflowDrawerIndex2_1: false,
 | 
					 | 
				
			||||||
            createWorkflowDrawerIndex2_2: false,
 | 
					 | 
				
			||||||
            currentPage: 1,
 | 
					 | 
				
			||||||
            pagesize: 10,
 | 
					 | 
				
			||||||
            pagesizeList: [10, 20, 30],
 | 
					 | 
				
			||||||
            searchInput: '',
 | 
					 | 
				
			||||||
            namespaceValue: 'default',
 | 
					 | 
				
			||||||
            namespaceList: [],
 | 
					 | 
				
			||||||
            namespaceListUrl: common.k8sNamespaceList,
 | 
					 | 
				
			||||||
            appLoading: false,
 | 
					 | 
				
			||||||
            workflowList: [],
 | 
					 | 
				
			||||||
            workflowTotal: 0,
 | 
					 | 
				
			||||||
            getWorkflowsData: {
 | 
					 | 
				
			||||||
                url: common.k8sWorkflowList,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    name: '',
 | 
					 | 
				
			||||||
                    namespace: '',
 | 
					 | 
				
			||||||
                    page: '',
 | 
					 | 
				
			||||||
                    limit: '',
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            fullscreenLoading: false,
 | 
					 | 
				
			||||||
            direction: 'rtl',
 | 
					 | 
				
			||||||
            createWorkflowDrawer: false,
 | 
					 | 
				
			||||||
            createWorkflow: {
 | 
					 | 
				
			||||||
                name: '',
 | 
					 | 
				
			||||||
                namespace: '',
 | 
					 | 
				
			||||||
                replicas: 1,
 | 
					 | 
				
			||||||
                image: '',
 | 
					 | 
				
			||||||
                resource: '',
 | 
					 | 
				
			||||||
                health_check: false,
 | 
					 | 
				
			||||||
                health_path: '',
 | 
					 | 
				
			||||||
                label_str: '',
 | 
					 | 
				
			||||||
                label: {},
 | 
					 | 
				
			||||||
                container_port: '',
 | 
					 | 
				
			||||||
                type: '',
 | 
					 | 
				
			||||||
                port: '',
 | 
					 | 
				
			||||||
                node_port: '',
 | 
					 | 
				
			||||||
                host: '',
 | 
					 | 
				
			||||||
                path: '',
 | 
					 | 
				
			||||||
                path_type: ''
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            createWorkflowData: {
 | 
					 | 
				
			||||||
                url: common.k8sWorkflowCreate,
 | 
					 | 
				
			||||||
                params: {}
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            createWorkflowRules: {
 | 
					 | 
				
			||||||
                name: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请填写名称',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                image: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请填写镜像',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                namespace: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请选择命名空间',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                resource: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请选择配额',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                label_str: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请填写标签',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                container_port: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请填写容器端口',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                type: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请填写工作流类型',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                port: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请填写Workflow端口',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                node_port: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请填写NodePort',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                host: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请填写域名',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                path: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '请填写路径',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
                path_type: [{
 | 
					 | 
				
			||||||
                    required: true,
 | 
					 | 
				
			||||||
                    message: '你选择匹配类型',
 | 
					 | 
				
			||||||
                    trigger: 'change'
 | 
					 | 
				
			||||||
                }],
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            delWorkflowData: {
 | 
					 | 
				
			||||||
                url: common.k8sWorkflowDel,
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                    id: ''
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    methods: {
 | 
					 | 
				
			||||||
        handleSizeChange(size) {
 | 
					 | 
				
			||||||
            this.pagesize = size;
 | 
					 | 
				
			||||||
            this.getWorkflows()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleCurrentChange(currentPage) {
 | 
					 | 
				
			||||||
            this.currentPage = currentPage;
 | 
					 | 
				
			||||||
            this.getWorkflows()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleClose(done) {
 | 
					 | 
				
			||||||
            this.$confirm('确认关闭?')
 | 
					 | 
				
			||||||
            .then(() => {
 | 
					 | 
				
			||||||
                done();
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(() => {});
 | 
					 | 
				
			||||||
            this.active = 0
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        drawerCancel(drawerName) {
 | 
					 | 
				
			||||||
            switch (drawerName) {
 | 
					 | 
				
			||||||
                case 'createWorkflowDrawerIndex1':
 | 
					 | 
				
			||||||
                    this.createWorkflowDrawerIndex1 = false
 | 
					 | 
				
			||||||
                    break
 | 
					 | 
				
			||||||
                case 'createWorkflowDrawerIndex2_1':
 | 
					 | 
				
			||||||
                    this.createWorkflowDrawerIndex2_1 = false
 | 
					 | 
				
			||||||
                    break
 | 
					 | 
				
			||||||
                case 'createWorkflowDrawerIndex2_2':
 | 
					 | 
				
			||||||
                    this.createWorkflowDrawerIndex2_2 = false
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            this.active = 0
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        ellipsis(value) {
 | 
					 | 
				
			||||||
            return value.length>15?value.substring(0,15)+'...':value
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        timeTrans(timestamp) {
 | 
					 | 
				
			||||||
            let date = new Date(new Date(timestamp).getTime() + 8 * 3600 * 1000)
 | 
					 | 
				
			||||||
            date = date.toJSON();
 | 
					 | 
				
			||||||
            date = date.substring(0, 19).replace('T', ' ')
 | 
					 | 
				
			||||||
            return date 
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        timeTransNot8(timestamp) {
 | 
					 | 
				
			||||||
            let date = new Date(new Date(timestamp).getTime() + 8 * 3600 * 1000)
 | 
					 | 
				
			||||||
            date = date.toJSON();
 | 
					 | 
				
			||||||
            date = date.substring(0, 19).replace('T', ' ')
 | 
					 | 
				
			||||||
            return date 
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getNamespaces() {
 | 
					 | 
				
			||||||
            httpClient.get(this.namespaceListUrl)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.namespaceList = res.data.items
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        getWorkflows() {
 | 
					 | 
				
			||||||
            this.appLoading = true
 | 
					 | 
				
			||||||
            this.getWorkflowsData.params.name = this.searchInput
 | 
					 | 
				
			||||||
            this.getWorkflowsData.params.namespace = this.namespaceValue
 | 
					 | 
				
			||||||
            this.getWorkflowsData.params.page = this.currentPage
 | 
					 | 
				
			||||||
            this.getWorkflowsData.params.limit = this.pagesize
 | 
					 | 
				
			||||||
            httpClient.get(this.getWorkflowsData.url, {params: this.getWorkflowsData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.workflowList = res.data.items
 | 
					 | 
				
			||||||
                this.workflowTotal = res.data.total
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.appLoading = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        delWorkflow(e) {
 | 
					 | 
				
			||||||
            this.delWorkflowData.params.id = e.row.id
 | 
					 | 
				
			||||||
            httpClient.delete(this.delWorkflowData.url, {data: this.delWorkflowData.params})
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.getWorkflows()
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            console.log(123)
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        handleConfirm(obj, operateName, fn) {
 | 
					 | 
				
			||||||
            this.confirmContent = '确认继续 ' + operateName + ' 操作吗?'
 | 
					 | 
				
			||||||
            this.$confirm(this.confirmContent,'提示',{
 | 
					 | 
				
			||||||
                confirmButtonText: '确定',
 | 
					 | 
				
			||||||
                cancelButtonText: '取消',
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .then(() => {
 | 
					 | 
				
			||||||
                fn(obj)
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(() => {
 | 
					 | 
				
			||||||
                this.$message.info({
 | 
					 | 
				
			||||||
                    message: '已取消操作'
 | 
					 | 
				
			||||||
                })          
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        createWorkflowFunc() {
 | 
					 | 
				
			||||||
            let reg = new RegExp("(^[A-Za-z]+=[A-Za-z0-9]+).*")
 | 
					 | 
				
			||||||
            if (!reg.test(this.createWorkflow.label_str)) {
 | 
					 | 
				
			||||||
                this.$message.warning({
 | 
					 | 
				
			||||||
                    message: "标签填写异常,请确认后重新填写"
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
                return
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            this.fullscreenLoading = true
 | 
					 | 
				
			||||||
            let label = new Map()
 | 
					 | 
				
			||||||
            let cpu, memory
 | 
					 | 
				
			||||||
            let a = (this.createWorkflow.label_str).split(",")
 | 
					 | 
				
			||||||
            a.forEach(item => {
 | 
					 | 
				
			||||||
                let b = item.split("=")
 | 
					 | 
				
			||||||
                label[b[0]] = b[1]
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            let resourceList = this.createWorkflow.resource.split("/")
 | 
					 | 
				
			||||||
            cpu = resourceList[0]
 | 
					 | 
				
			||||||
            memory = resourceList[1] + "Gi"
 | 
					 | 
				
			||||||
            this.createWorkflowData.params = this.createWorkflow
 | 
					 | 
				
			||||||
            this.createWorkflowData.params.label = label
 | 
					 | 
				
			||||||
            this.createWorkflowData.params.cpu = cpu
 | 
					 | 
				
			||||||
            this.createWorkflowData.params.memory = memory
 | 
					 | 
				
			||||||
            this.createWorkflowData.params.container_port = parseInt(this.createWorkflow.container_port)
 | 
					 | 
				
			||||||
            this.createWorkflowData.params.port = parseInt(this.createWorkflow.port)
 | 
					 | 
				
			||||||
            this.createWorkflowData.params.node_port = parseInt(this.createWorkflow.node_port)
 | 
					 | 
				
			||||||
            if (this.createWorkflow.type == 'Ingress') {
 | 
					 | 
				
			||||||
                let hosts = new Map()
 | 
					 | 
				
			||||||
                let httpPaths = []
 | 
					 | 
				
			||||||
                let httpPath = {
 | 
					 | 
				
			||||||
                    path: this.createWorkflow.path,
 | 
					 | 
				
			||||||
                    path_type: this.createWorkflow.path_type,
 | 
					 | 
				
			||||||
                    service_name: this.createWorkflow.name,
 | 
					 | 
				
			||||||
                    service_port: parseInt(this.createWorkflow.port)
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                httpPaths.push(httpPath)
 | 
					 | 
				
			||||||
                hosts[this.createWorkflow.host] = httpPaths
 | 
					 | 
				
			||||||
                this.createWorkflowData.params.hosts = hosts
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            httpClient.post(this.createWorkflowData.url, this.createWorkflowData.params)
 | 
					 | 
				
			||||||
            .then(res => {
 | 
					 | 
				
			||||||
                this.$message.success({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
                this.getWorkflows()
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .catch(res => {
 | 
					 | 
				
			||||||
                this.$message.error({
 | 
					 | 
				
			||||||
                message: res.msg
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            this.resetForm('createWorkflow')
 | 
					 | 
				
			||||||
            this.createWorkflowDrawerIndex2_2 = false
 | 
					 | 
				
			||||||
            this.active = 3
 | 
					 | 
				
			||||||
            this.fullscreenLoading = false
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        resetForm(formName) {
 | 
					 | 
				
			||||||
            this.$refs[formName].resetFields()
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        submitForm(formName, fn) {
 | 
					 | 
				
			||||||
            this.$refs[formName].validate((valid) => {
 | 
					 | 
				
			||||||
                if (valid) {
 | 
					 | 
				
			||||||
                    fn()
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    return false;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        workflowIndex1Next() {
 | 
					 | 
				
			||||||
            if (!this.createWorkflow.type) {
 | 
					 | 
				
			||||||
                this.$message.warning({
 | 
					 | 
				
			||||||
                    message: "请选择工作流类型"
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
                return
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            this.createWorkflowDrawerIndex1 = false
 | 
					 | 
				
			||||||
            this.createWorkflowDrawerIndex2_1 = true
 | 
					 | 
				
			||||||
            this.active = 1
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        workflowIndex2_1Next() {
 | 
					 | 
				
			||||||
            this.createWorkflowDrawerIndex2_1 = false
 | 
					 | 
				
			||||||
            this.createWorkflowDrawerIndex2_2 = true
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    watch: {
 | 
					 | 
				
			||||||
        namespaceValue: {
 | 
					 | 
				
			||||||
            handler() {
 | 
					 | 
				
			||||||
                localStorage.setItem('namespace', this.namespaceValue)
 | 
					 | 
				
			||||||
                this.currentPage = 1
 | 
					 | 
				
			||||||
                this.getWorkflows()
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    beforeMount() {
 | 
					 | 
				
			||||||
        if (localStorage.getItem('namespace') !== undefined && localStorage.getItem('namespace') !== null) {
 | 
					 | 
				
			||||||
            this.namespaceValue = localStorage.getItem('namespace')
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        this.getNamespaces()
 | 
					 | 
				
			||||||
        this.getWorkflows()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<style scoped>
 | 
					 | 
				
			||||||
    .workflow-head-card,.workflow-body-card {
 | 
					 | 
				
			||||||
        border-radius: 1px;
 | 
					 | 
				
			||||||
        margin-bottom: 5px;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .workflow-head-search {
 | 
					 | 
				
			||||||
        width:160px;
 | 
					 | 
				
			||||||
        margin-right:10px; 
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .workflow-body-workflowname {
 | 
					 | 
				
			||||||
        color: #4795EE;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .workflow-body-workflowname:hover {
 | 
					 | 
				
			||||||
        color: rgb(84, 138, 238);
 | 
					 | 
				
			||||||
        cursor: pointer;
 | 
					 | 
				
			||||||
        font-weight: bold;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    :v-deep .el-drawer__header {
 | 
					 | 
				
			||||||
        margin-bottom: 0px !important;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    v-deep .el-drawer__body {
 | 
					 | 
				
			||||||
        padding: 0px 0px 0px 0px;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
</style>
 | 
					 | 
				
			||||||
@ -1,8 +0,0 @@
 | 
				
			|||||||
module.exports = {
 | 
					 | 
				
			||||||
    devServer:{
 | 
					 | 
				
			||||||
        host: '0.0.0.0',
 | 
					 | 
				
			||||||
        port: 8080,
 | 
					 | 
				
			||||||
        open: true
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    lintOnSave: false
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||