kubex 20210123

This commit is contained in:
annzee 2021-01-23 18:02:16 +08:00
parent 8c7630daa2
commit a872acc16c
24 changed files with 642 additions and 133 deletions

View File

@ -2,4 +2,4 @@
ENV = 'development' ENV = 'development'
# base api # base api
VUE_APP_BASE_API = '/dev-api' VUE_APP_BASE_API = '/'

View File

@ -1,8 +1,8 @@
{ {
"name": "vue-element-admin", "name": "kubex",
"version": "4.4.0", "version": "4.4.0",
"description": "A magical vue admin. An out-of-box UI solution for enterprise applications. Newest development stack of vue. Lots of awesome features", "description": "",
"author": "Pan <panfree23@gmail.com>", "author": "",
"scripts": { "scripts": {
"dev": "vue-cli-service serve", "dev": "vue-cli-service serve",
"lint": "eslint --ext .js,.vue src", "lint": "eslint --ext .js,.vue src",

View File

@ -1,10 +1,11 @@
import request from '@/utils/request' import request from '@/utils/request'
const qs = require('qs')
export function login(data) { export function login(data) {
return request({ return request({
url: '/vue-element-admin/user/login', url: '/oauth/token',
method: 'post', method: 'post',
data data: qs.stringify(data)
}) })
} }

View File

@ -37,7 +37,7 @@ export default {
const first = matched[0] const first = matched[0]
if (!this.isDashboard(first)) { if (!this.isDashboard(first)) {
matched = [{ path: '/dashboard', meta: { title: 'Dashboard' }}].concat(matched) matched = [{ path: '/', meta: { title: 'KUBEX' }}].concat(matched)
} }
this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false) this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)

View File

@ -0,0 +1,28 @@
<template>
<el-card class="chartCard" style="height: 150px">
<el-table style="padding:20px 0" :data="clusterMessage">
<el-table-column prop="agent" label="服务商" width="140" />
<el-table-column prop="version" label="KubeX版本" width="140" />
<el-table-column prop="visible" label="集群可见性" width="140" />
</el-table>
</el-card>
</template>
<script>
export default {
name: 'ClusterMessage',
data() {
return {
clusterMessage: [
{ agent: 'KubeX', version: 'v0.1', visible: '部分可见' }
]
}
}
}
</script>
<style lang="scss">
.el-table::before{
height: 0;
}
</style>

View File

@ -0,0 +1,32 @@
<template>
<el-card class="chartCard" style="height: 150px">
<el-table style="padding:20px 0" :data="componentStatus">
<el-table-column prop="apiRequest" label="API每秒请求数" width="140" />
<el-table-column prop="delay" label="API请求延迟" width="140" />
<el-table-column prop="schedulerTimes" label="调度器调度次数" width="140" />
<el-table-column prop="schedulingPods" label="调度失败的容器组" width="140" />
</el-table>
</el-card>
</template>
<script>
export default {
name: 'ComponentStatus',
data() {
return {
componentStatus: [
{
apiRequest: '15.483 times/s',
delay: '2.41 ms',
schedulerTimes: '71',
schedulingPods: '2'
}
]
}
}
}
</script>
<style lang="scss">
</style>

View File

@ -0,0 +1,27 @@
<template>
<el-card class="chartCard">
<el-table style="padding:20px 0" :data="nodeMessage">
<el-table-column prop="node" label="节点" width="200" />
<el-table-column prop="CPU" label="CPU使用率" width="120" />
</el-table>
</el-card>
</template>
<script>
export default {
name: 'NodeMessage',
data() {
return {
nodeMessage: [
{ node: 'master 192.168.12.10', CPU: '16%' },
{ node: 'node1 192.168.12.11', CPU: '12%' },
{ node: 'node2 192.168.12.12', CPU: '7%' }
]
}
}
}
</script>
<style lang="scss">
</style>

View File

@ -0,0 +1,40 @@
<template>
<el-card class="chartCard">
<p>节点详细信息</p>
<el-table :data="nodeStatus">
<el-table-column prop="name" label="名称" width="140" />
<el-table-column prop="status" label="状态" width="140" />
<el-table-column prop="role" label="角色" width="140" />
<el-table-column prop="cpu" label="CPU" width="140" />
<el-table-column prop="ram" label="内存" width="140" />
<el-table-column prop="pod" label="Pods" width="140" />
<el-table-column prop="allocatedCPU" label="已分配CPU" width="180" />
<el-table-column prop="allocatedRAM" label="已分配内存" width="180s" />
</el-table>
</el-card>
</template>
<script>
export default {
name: 'NodeStatus',
data() {
return {
nodeStatus: [
{
name: 'master', status: '运行中', role: 'master, worker', cpu: '17%', ram: '48%', pod: '50%', allocatedCPU: '2.877 Core (79%)', allocatedRAM: '2.177 Gi (30%)'
},
{
name: 'node1', status: '运行中', role: 'worker', cpu: '13%', ram: '31%', pod: '25%', allocatedCPU: '1.612 Core (44%)', allocatedRAM: '2.06 Gi (29%)'
},
{
name: 'node2', status: '运行中', role: 'worker', cpu: '9%', ram: '50%', pod: '23%', allocatedCPU: '1.752 Core (48%)', allocatedRAM: '4.703 Gi (66%)'
}
]
}
}
}
</script>
<style lang="scss">
</style>

View File

@ -0,0 +1,99 @@
<template>
<el-card class="chartCard" style="height: 450px">
<el-row>
<el-col :span="24">
<el-col :span="6" class="center">
<el-progress type="circle" :percentage="80" style="width:130px;margin-top: 20px" />
</el-col>
<el-col :span="18" class="center">
<el-card style="height: 75px;margin-top: 10px;padding:10px">
<el-col :span="6">
<el-progress type="circle" :percentage="12" :width="75" />
</el-col>
<el-col :span="18">
<el-col :span="8">
<p>12%</p>
<p>CPU</p>
</el-col>
<el-col :span="8">
<p>1.49 core</p>
<p>已使用</p>
</el-col>
<el-col :span="8">
<p>12 core</p>
<p>总计</p>
</el-col>
</el-col>
</el-card>
<el-card style="height: 75px;margin-top: 10px;padding:10px">
<el-col :span="6">
<el-progress type="circle" :percentage="39" :width="75" />
</el-col>
<el-col :span="18">
<el-col :span="8">
<p>39%</p>
<p>内存</p>
</el-col>
<el-col :span="8">
<p>9.18 Gi</p>
<p>已使用</p>
</el-col>
<el-col :span="8">
<p>23.39 Gi</p>
<p>总计</p>
</el-col>
</el-col>
</el-card>
<el-card style="height: 75px;margin-top: 10px;padding:10px">
<el-col :span="6">
<el-progress type="circle" :percentage="31" :width="75" />
</el-col>
<el-col :span="18">
<el-col :span="8">
<p>31%</p>
<p>Pods</p>
</el-col>
<el-col :span="8">
<p>102</p>
<p>已使用</p>
</el-col>
<el-col :span="8">
<p>330</p>
<p>总计</p>
</el-col>
</el-col>
</el-card>
<el-card style="height: 75px;margin-top: 10px;padding:10px">
<el-col :span="6">
<el-progress type="circle" :percentage="86" :width="75" />
</el-col>
<el-col :span="18">
<el-col :span="8">
<p>86%</p>
<p>本地存储</p>
</el-col>
<el-col :span="8">
<p>54.12 GB</p>
<p>已使用</p>
</el-col>
<el-col :span="8">
<p>63 GB</p>
<p>总计</p>
</el-col>
</el-col>
</el-card>
</el-col>
</el-col>
</el-row>
</el-card>
</template>
<script>
export default {
name: 'ResourceUsage'
}
</script>
<style lang="scss">
</style>

View File

@ -28,10 +28,10 @@ import * as filters from './filters' // global filters
* Currently MockJs will be used in the production environment, * Currently MockJs will be used in the production environment,
* please remove it before going online ! ! ! * please remove it before going online ! ! !
*/ */
if (process.env.NODE_ENV !== 'production') { // if (process.env.NODE_ENV !== 'production') {
const { mockXHR } = require('../mock') // const { mockXHR } = require('../mock')
mockXHR() // mockXHR()
} // }
Vue.use(Element, { Vue.use(Element, {
size: Cookies.get('size') || 'small' // set element-ui default size size: Cookies.get('size') || 'small' // set element-ui default size

View File

@ -1,6 +1,6 @@
import router from './router' import router from './router'
import store from './store' // import store from './store'
import { Message } from 'element-ui' // import { Message } from 'element-ui'
import NProgress from 'nprogress' // progress bar import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style import 'nprogress/nprogress.css' // progress bar style
import { getToken } from '@/utils/auth' // get token from cookie import { getToken } from '@/utils/auth' // get token from cookie
@ -26,33 +26,34 @@ router.beforeEach(async(to, from, next) => {
next({ path: '/' }) next({ path: '/' })
NProgress.done() // hack: https://github.com/PanJiaChen/vue-element-admin/pull/2939 NProgress.done() // hack: https://github.com/PanJiaChen/vue-element-admin/pull/2939
} else { } else {
next()
// determine whether the user has obtained his permission roles through getInfo // determine whether the user has obtained his permission roles through getInfo
const hasRoles = store.getters.roles && store.getters.roles.length > 0 // const hasRoles = store.getters.roles && store.getters.roles.length > 0
if (hasRoles) { // if (hasRoles) {
next() // next()
} else { // } else {
try { // try {
// get user info // // get user info
// note: roles must be a object array! such as: ['admin'] or ,['developer','editor'] // // note: roles must be a object array! such as: ['admin'] or ,['developer','editor']
const { roles } = await store.dispatch('user/getInfo') // const { roles } = await store.dispatch('user/getInfo')
// generate accessible routes map based on roles // // generate accessible routes map based on roles
const accessRoutes = await store.dispatch('permission/generateRoutes', roles) // const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
// dynamically add accessible routes // // dynamically add accessible routes
router.addRoutes(accessRoutes) // router.addRoutes(accessRoutes)
// hack method to ensure that addRoutes is complete // // hack method to ensure that addRoutes is complete
// set the replace: true, so the navigation will not leave a history record // // set the replace: true, so the navigation will not leave a history record
next({ ...to, replace: true }) // next({ ...to, replace: true })
} catch (error) { // } catch (error) {
// remove token and go to login page to re-login // // remove token and go to login page to re-login
await store.dispatch('user/resetToken') // await store.dispatch('user/resetToken')
Message.error(error || 'Has Error') // Message.error(error || 'Has Error')
next(`/login?redirect=${to.path}`) // next(`/login?redirect=${to.path}`)
NProgress.done() // NProgress.done()
} // }
} // }
} }
} else { } else {
/* has no token*/ /* has no token*/

View File

@ -70,19 +70,74 @@ export const constantRoutes = [
component: () => import('@/views/error-page/401'), component: () => import('@/views/error-page/401'),
hidden: true hidden: true
}, },
// {
// path: '/',
// component: Layout,
// redirect: '/dashboard',
// children: [
// {
// path: 'dashboard',
// component: () => import('@/views/dashboard/index'),
// name: 'Dashboard',
// meta: { title: 'Dashboard', icon: 'dashboard', affix: true }
// }
// ]
// },
{ {
path: '/', path: '/',
component: Layout, component: Layout,
redirect: '/dashboard', redirect: 'overview',
children: [ children: [
{ {
path: 'dashboard', path: 'overview',
component: () => import('@/views/dashboard/index'), component: () => import('@/views/overview/index'),
name: 'Dashboard', name: 'Overview',
meta: { title: 'Dashboard', icon: 'dashboard', affix: true } meta: { title: '概览', icon: 'dashboard', affix: true }
} }
] ]
}, },
{
path: '/nodeManagement',
component: Layout,
redirect: 'nodeManagement',
children: [
{
path: 'nodeManagement',
component: () => import('@/views/nodeManagement/index'),
name: 'NodeManagement',
meta: { title: '节点管理', icon: 'el-icon-s-management', affix: true }
}
]
},
{
path: '/projectManagement',
component: Layout,
redirect: 'projectManagement',
children: [
{
path: 'projectManagement',
component: () => import('@/views/projectManagement/index'),
name: 'ProjectManagement',
meta: { title: '项目管理', icon: 'el-icon-s-management', affix: true }
}
]
},
{
path: '/storageManagement',
component: Layout,
redirect: 'storageManagement',
children: [
{
path: 'storageManagement',
component: () => import('@/views/storageManagement/index'),
name: 'StorageManagement',
meta: { title: '存储管理', icon: 'el-icon-s-management', affix: true }
}
]
},
// ],
// },
// { // {
// path: '/documentation', // path: '/documentation',
// component: Layout, // component: Layout,

View File

@ -5,7 +5,7 @@ module.exports = {
* @type {boolean} true | false * @type {boolean} true | false
* @description Whether show the settings right-panel * @description Whether show the settings right-panel
*/ */
showSettings: true, showSettings: false,
/** /**
* @type {boolean} true | false * @type {boolean} true | false

View File

@ -1,4 +1,4 @@
import { login, logout, getInfo } from '@/api/user' import { login, getInfo } from '@/api/user'
import { getToken, setToken, removeToken } from '@/utils/auth' import { getToken, setToken, removeToken } from '@/utils/auth'
import router, { resetRouter } from '@/router' import router, { resetRouter } from '@/router'
@ -33,10 +33,10 @@ const actions = {
login({ commit }, userInfo) { login({ commit }, userInfo) {
const { username, password } = userInfo const { username, password } = userInfo
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
login({ username: username.trim(), password: password }).then(response => { login({ 'grant_type': 'password', 'username': username.trim(), 'password': password }).then(response => {
const { data } = response console.log(response)
commit('SET_TOKEN', data.token) commit('SET_TOKEN', response.access_token)
setToken(data.token) setToken(response.access_token)
resolve() resolve()
}).catch(error => { }).catch(error => {
reject(error) reject(error)
@ -75,20 +75,20 @@ const actions = {
// user logout // user logout
logout({ commit, state, dispatch }) { logout({ commit, state, dispatch }) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
logout(state.token).then(() => { // logout(state.token).then(() => {
commit('SET_TOKEN', '') commit('SET_TOKEN', '')
commit('SET_ROLES', []) commit('SET_ROLES', [])
removeToken() removeToken()
resetRouter() resetRouter()
// reset visited views and cached views // reset visited views and cached views
// to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2485 // to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2485
dispatch('tagsView/delAllViews', null, { root: true }) dispatch('tagsView/delAllViews', null, { root: true })
resolve() resolve()
}).catch(error => { // }).catch(error => {
reject(error) // reject(error)
}) // })
}) })
}, },

View File

@ -24,6 +24,7 @@ html {
#app { #app {
height: 100%; height: 100%;
color: #2c3e50;
} }
*, *,
@ -189,3 +190,19 @@ aside {
.multiselect--active { .multiselect--active {
z-index: 1000 !important; z-index: 1000 !important;
} }
span.tips {
display: block;
line-height: 1em;
margin-top: 5px;
color: #999999;
}
.chartCard .el-card__body {
padding: 0 20px;
height: 260px;
}
.el-table th {
background: #F5F7FA;
}

View File

@ -1,6 +1,6 @@
import Cookies from 'js-cookie' import Cookies from 'js-cookie'
const TokenKey = 'Admin-Token' const TokenKey = 'access_token'
export function getToken() { export function getToken() {
return Cookies.get(TokenKey) return Cookies.get(TokenKey)

View File

@ -1,10 +1,13 @@
import axios from 'axios' import axios from 'axios'
import { MessageBox, Message } from 'element-ui' import { Message } from 'element-ui'
import store from '@/store' import store from '@/store'
import { getToken } from '@/utils/auth' import { getToken } from '@/utils/auth'
// create an axios instance // create an axios instance
const service = axios.create({ const service = axios.create({
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
// withCredentials: true, // send cookies when cross-domain requests // withCredentials: true, // send cookies when cross-domain requests
timeout: 5000 // request timeout timeout: 5000 // request timeout
@ -16,10 +19,7 @@ service.interceptors.request.use(
// do something before request is sent // do something before request is sent
if (store.getters.token) { if (store.getters.token) {
// let each request carry token config.headers['Authorization'] = 'Bearer ' + getToken()
// ['X-Token'] is a custom headers key
// please modify it according to the actual situation
config.headers['X-Token'] = getToken()
} }
return config return config
}, },
@ -46,7 +46,7 @@ service.interceptors.response.use(
const res = response.data const res = response.data
// if the custom code is not 20000, it is judged as an error. // if the custom code is not 20000, it is judged as an error.
if (res.code !== 20000) { if (response.status !== 200) {
Message({ Message({
message: res.message || 'Error', message: res.message || 'Error',
type: 'error', type: 'error',
@ -54,18 +54,18 @@ service.interceptors.response.use(
}) })
// 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired; // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
if (res.code === 50008 || res.code === 50012 || res.code === 50014) { // if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
// to re-login // // to re-login
MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', { // MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
confirmButtonText: 'Re-Login', // confirmButtonText: 'Re-Login',
cancelButtonText: 'Cancel', // cancelButtonText: 'Cancel',
type: 'warning' // type: 'warning'
}).then(() => { // }).then(() => {
store.dispatch('user/resetToken').then(() => { // store.dispatch('user/resetToken').then(() => {
location.reload() // location.reload()
}) // })
}) // })
} // }
return Promise.reject(new Error(res.message || 'Error')) return Promise.reject(new Error(res.message || 'Error'))
} else { } else {
return res return res

View File

@ -10,27 +10,19 @@
</h1> </h1>
gif来源<a href="https://zh.airbnb.com/" target="_blank">airbnb</a> 页面 gif来源<a href="https://zh.airbnb.com/" target="_blank">airbnb</a> 页面
<h2>你没有权限去该页面</h2> <h2>你没有权限去该页面</h2>
<h6>如有不满请联系你领导</h6>
<ul class="list-unstyled"> <ul class="list-unstyled">
<li>或者你可以去:</li> <li>或者你可以去:</li>
<li class="link-type"> <li class="link-type">
<router-link to="/dashboard"> <router-link to="/overview">
回首页 回首页
</router-link> </router-link>
</li> </li>
<li class="link-type">
<a href="https://www.taobao.com/">随便看看</a>
</li>
<li><a href="#" @click.prevent="dialogVisible=true">点我看图</a></li>
</ul> </ul>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<img :src="errGif" width="313" height="428" alt="Girl has dropped her ice cream."> <img :src="errGif" width="313" height="428" alt="Girl has dropped her ice cream.">
</el-col> </el-col>
</el-row> </el-row>
<el-dialog :visible.sync="dialogVisible" title="随便看">
<img :src="ewizardClap" class="pan-img">
</el-dialog>
</div> </div>
</template> </template>

View File

@ -47,42 +47,20 @@
<el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">Login</el-button> <el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">Login</el-button>
<div style="position:relative">
<div class="tips">
<span>Username : admin</span>
<span>Password : any</span>
</div>
<div class="tips">
<span style="margin-right:18px;">Username : editor</span>
<span>Password : any</span>
</div>
<el-button class="thirdparty-button" type="primary" @click="showDialog=true">
Or connect with
</el-button>
</div>
</el-form> </el-form>
<el-dialog title="Or connect with" :visible.sync="showDialog">
Can not be simulated on local, so please combine you own business simulation! ! !
<br>
<br>
<br>
<social-sign />
</el-dialog>
</div> </div>
</template> </template>
<script> <script>
import { validUsername } from '@/utils/validate' import { isString } from '@/utils/validate'
import SocialSign from './components/SocialSignin' // import SocialSign from './components/SocialSignin'
export default { export default {
name: 'Login', name: 'Login',
components: { SocialSign }, // components: { SocialSign },
data() { data() {
const validateUsername = (rule, value, callback) => { const validateUsername = (rule, value, callback) => {
if (!validUsername(value)) { if (!isString(value)) {
callback(new Error('Please enter the correct user name')) callback(new Error('Please enter the correct user name'))
} else { } else {
callback() callback()
@ -98,7 +76,7 @@ export default {
return { return {
loginForm: { loginForm: {
username: 'admin', username: 'admin',
password: '111111' password: 'P@88w0rd'
}, },
loginRules: { loginRules: {
username: [{ required: true, trigger: 'blur', validator: validateUsername }], username: [{ required: true, trigger: 'blur', validator: validateUsername }],
@ -158,6 +136,7 @@ export default {
this.loading = true this.loading = true
this.$store.dispatch('user/login', this.loginForm) this.$store.dispatch('user/login', this.loginForm)
.then(() => { .then(() => {
this.$message.success('登录成功')
this.$router.push({ path: this.redirect || '/', query: this.otherQuery }) this.$router.push({ path: this.redirect || '/', query: this.otherQuery })
this.loading = false this.loading = false
}) })
@ -178,24 +157,6 @@ export default {
return acc return acc
}, {}) }, {})
} }
// afterQRScan() {
// if (e.key === 'x-admin-oauth-code') {
// const code = getQueryObject(e.newValue)
// const codeMap = {
// wechat: 'code',
// tencent: 'code'
// }
// const type = codeMap[this.auth_type]
// const codeName = code[type]
// if (codeName) {
// this.$store.dispatch('LoginByThirdparty', codeName).then(() => {
// this.$router.push({ path: this.redirect || '/' })
// })
// } else {
// alert('')
// }
// }
// }
} }
} }
</script> </script>

View File

@ -0,0 +1,54 @@
<template>
<div>
<el-card class="chartCard">
<h4>
集群节点
</h4>
<span class="tips">集群节点提供了当前集群下节点的运行状态以及可以编辑删除节点</span>
<el-collapse v-model="activeName" accordion>
<el-collapse-item title="集群节点的类型?" name="1">
<div>节点分为主控 (Master) 节点和工作 (Worker) 节点</div>
</el-collapse-item>
<el-collapse-item title="什么是节点污点?" name="2">
<div>节点污点 (Taints) 可以阻止某些容器组 (Pod) 副本部署至该节点中,
与容忍度 (Tolerations) 一起工作确保容器组不会被调度到不合适的节点上</div>
</el-collapse-item>
</el-collapse>
</el-card>
<el-card class="chartCard" style="height:150px;width:600px">
<el-table style="margin-top:25px" :data="nodeReliefMessage">
<el-table-column prop="totalNumber" label="节点数量" />
<el-table-column prop="masterNumber" label="控制节点数量" />
<el-table-column prop="nodeNumber" label="工作节点数量" />
</el-table>
</el-card>
<NodeStatus />
</div>
</template>
<script>
import NodeStatus from '@/components/ClusterManagement/nodeStatus.vue'
export default {
name: '',
components: { NodeStatus },
data() {
return {
activeName: '1',
nodeReliefMessage: [
{ totalNumber: '3', masterNumber: '1', nodeNumber: '3' }
]
}
}
}
</script>
<style lang="scss">
.chartCard{
text-align: left;
span{
margin-bottom: 10px;
}
}
</style>

View File

@ -0,0 +1,47 @@
<template>
<div class="app-container">
<h4>hostHost 集群 </h4>
<span class="tips">
Automatically created by KubeX, we encourage you to use host cluster for clusters management only, deploy workloads to member clusters.</span>
<el-row :gutter="20">
<el-col :span="12">
<h5>集群信息</h5>
<ClusterMessage />
</el-col>
<el-col :span="12">
<h5>KubeX组件状态</h5>
<ComponentStatus />
</el-col>
<el-col :span="16">
<h5>集群资源使用情况</h5>
<ResourceUsage />
</el-col>
<el-col :span="8">
<h5>节点用量 Top3</h5>
<NodeMessage />
</el-col>
</el-row>
</div>
</template>
<script>
import ClusterMessage from '@/components/ClusterManagement/clusterMessage'
import ComponentStatus from '@/components/ClusterManagement/componentStatus'
import NodeMessage from '@/components/ClusterManagement/nodeMessage'
import ResourceUsage from '@/components/ClusterManagement/resourceUsage'
export default {
components: {
ClusterMessage, ComponentStatus, NodeMessage, ResourceUsage
},
data() {
return {
key: ''
}
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,80 @@
<template>
<div class="projectInfo">
<el-card class="chartCard" style="height:100px">
<h4>
项目
</h4>
<span class="tips">将根据项目资源进行分组, 可以按项目对资源进行查看管理</span>
</el-card>
<el-tabs type="border-card">
<el-tab-pane label="用户项目">
<el-table :data="nodeStatus">
<el-table-column prop="name" label="名称" width="140" />
<el-table-column prop="status" label="状态" width="140" />
<el-table-column prop="space" label="企业空间" width="140" />
<el-table-column prop="cpu" label="CPU使用量" width="140" />
<el-table-column prop="ram" label="内存使用量" width="140" />
<el-table-column prop="pod" label="Pods数量" width="140" />
</el-table>
</el-tab-pane>
<el-tab-pane label="系统项目">
<el-table :data="nodeStatus">
<el-table-column prop="name" label="名称" width="140" />
<el-table-column prop="status" label="状态" width="140" />
<el-table-column prop="space" label="企业空间" width="140" />
<el-table-column prop="cpu" label="CPU使用量" width="140" />
<el-table-column prop="ram" label="内存使用量" width="140" />
<el-table-column prop="pod" label="Pods数量" width="140" />
</el-table>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
export default {
name: 'ProjectForm',
data() {
return {
nodeStatus: [
{
name: 'a111', status: '活跃', space: '', cpu: '0 m', ram: '0 Bytes', pod: '0'
},
{
name: 'node1', status: '活跃', space: 'demo', cpu: '30 m', ram: '1.63 Gi', pod: '33'
},
{
name: 'aba', status: '活跃', space: 'demo', cpu: '0 m', ram: '0 Bytes', pod: '0'
},
{
name: 'cert-manager', status: '活跃', space: '', cpu: '10 m', ram: '105.65 Mi', pod: '3'
},
{
name: 'a111', status: '活跃', space: '', cpu: '0 m', ram: '0 Bytes', pod: '0'
},
{
name: 'node1', status: '活跃', space: 'demo', cpu: '30 m', ram: '1.63 Gi', pod: '33'
},
{
name: 'aba', status: '活跃', space: 'demo', cpu: '0 m', ram: '0 Bytes', pod: '0'
},
{
name: 'cert-manager', status: '活跃', space: '', cpu: '10 m', ram: '105.65 Mi', pod: '3'
},
{
name: 'aba', status: '活跃', space: 'demo', cpu: '0 m', ram: '0 Bytes', pod: '0'
},
{
name: 'cert-manager', status: '活跃', space: '', cpu: '10 m', ram: '105.65 Mi', pod: '3'
}
]
}
}
}
</script>
<style lang="scss" scoped>
.projectInfo{
text-align: left;
}
</style>

View File

@ -0,0 +1,68 @@
<template>
<div>
<el-card class="chartCard">
<h4>
存储卷信息
</h4>
<span class="tips" style="margin-bottom:10px">存储卷供用户创建的工作负载使用是将工作负载数据持久化的一种资源对象</span>
<el-collapse v-model="activeName" accordion>
<el-collapse-item title="什么是存储卷类型?" name="1">
<div>存储卷类型 (StorageClass) 是由集群管理员配置存储服务端的参数并按类型提供存储给集群用户使用</div>
</el-collapse-item>
<el-collapse-item title="什么是本地存储卷 (Local Volume) ?" name="2">
<div>本地存储卷表示挂载的本地存储设备如磁盘分区或目录</div>
</el-collapse-item>
</el-collapse>
</el-card>
<el-card class="chartCard" style="height: 700px; padding:20px 0">
<el-table :data="nodeStatus">
<el-table-column prop="name" label="名称" width="300" />
<el-table-column prop="status" label="状态" width="140" />
<el-table-column prop="mode" label="访问模式" width="200" />
<el-table-column prop="mount" label="挂载" width="140" />
<el-table-column prop="createtime" label="创建时间" width="140" />
</el-table>
</el-card>
</div>
</template>
<script>
export default {
name: 'StorageForm',
data() {
return {
activeName: '1',
nodeStatus: [
{
name: 'minio-87dz96', status: '准备就绪', mode: 'ReadWriteOnce', mount: '已挂载', createtime: '2021-01-07 13:49'
},
{
name: 'data-postgre-ux292w-postgresql-0', status: '准备就绪', mode: 'ReadWriteOnce', mount: '已挂载', createtime: '2021-01-05 12:09'
},
{
name: 'db-data-mongodb-5gupv8-0', status: '准备就绪', mode: 'ReadWriteOnce', mount: '已挂载', createtime: '2021-01-04 09:59'
},
{
name: 'ks-jenkins', status: '准备就绪', mode: 'ReadWriteOnce', mount: '未挂载', createtime: '2020-12-09 20:23'
},
{
name: 'harbor-hrypxk-harbor-registry', status: '准备就绪', mode: 'ReadWriteOnce', mount: '已挂载', createtime: '2020-11-22 03:00'
},
{
name: 'harbor-hrypxk-harbor-jobservice', status: '准备就绪', mode: 'ReadWriteOnce', mount: '已挂载', createtime: '2020-11-22 03:00'
},
{
name: 'harbor-hrypxk-harbor-chartmuseum', status: '准备就绪', mode: 'ReadWriteOnce', mount: '已挂载', createtime: '2020-11-22 03:00'
}
]
}
}
}
</script>
<style lang="scss">
.chartCard{
text-align: left;
}
</style>

View File

@ -36,7 +36,14 @@ module.exports = {
warnings: false, warnings: false,
errors: true errors: true
}, },
before: require('./mock/mock-server.js') proxy: {
'/': {
ws: false,
target: 'http://192.168.0.86:30881/',
// changeOrigin: true,
},
},
// before: require('./mock/mock-server.js')
}, },
configureWebpack: { configureWebpack: {
// provide the app's title in webpack's name field, so that // provide the app's title in webpack's name field, so that