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'
# 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",
"description": "A magical vue admin. An out-of-box UI solution for enterprise applications. Newest development stack of vue. Lots of awesome features",
"author": "Pan <panfree23@gmail.com>",
"description": "",
"author": "",
"scripts": {
"dev": "vue-cli-service serve",
"lint": "eslint --ext .js,.vue src",

View File

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

View File

@ -37,7 +37,7 @@ export default {
const first = matched[0]
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)

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,
* please remove it before going online ! ! !
*/
if (process.env.NODE_ENV !== 'production') {
const { mockXHR } = require('../mock')
mockXHR()
}
// if (process.env.NODE_ENV !== 'production') {
// const { mockXHR } = require('../mock')
// mockXHR()
// }
Vue.use(Element, {
size: Cookies.get('size') || 'small' // set element-ui default size

View File

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

View File

@ -70,19 +70,74 @@ export const constantRoutes = [
component: () => import('@/views/error-page/401'),
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: '/',
component: Layout,
redirect: '/dashboard',
redirect: 'overview',
children: [
{
path: 'dashboard',
component: () => import('@/views/dashboard/index'),
name: 'Dashboard',
meta: { title: 'Dashboard', icon: 'dashboard', affix: true }
path: 'overview',
component: () => import('@/views/overview/index'),
name: 'Overview',
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',
// component: Layout,

View File

@ -5,7 +5,7 @@ module.exports = {
* @type {boolean} true | false
* @description Whether show the settings right-panel
*/
showSettings: true,
showSettings: 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 router, { resetRouter } from '@/router'
@ -33,10 +33,10 @@ const actions = {
login({ commit }, userInfo) {
const { username, password } = userInfo
return new Promise((resolve, reject) => {
login({ username: username.trim(), password: password }).then(response => {
const { data } = response
commit('SET_TOKEN', data.token)
setToken(data.token)
login({ 'grant_type': 'password', 'username': username.trim(), 'password': password }).then(response => {
console.log(response)
commit('SET_TOKEN', response.access_token)
setToken(response.access_token)
resolve()
}).catch(error => {
reject(error)
@ -75,20 +75,20 @@ const actions = {
// user logout
logout({ commit, state, dispatch }) {
return new Promise((resolve, reject) => {
logout(state.token).then(() => {
commit('SET_TOKEN', '')
commit('SET_ROLES', [])
removeToken()
resetRouter()
// logout(state.token).then(() => {
commit('SET_TOKEN', '')
commit('SET_ROLES', [])
removeToken()
resetRouter()
// reset visited views and cached views
// to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2485
dispatch('tagsView/delAllViews', null, { root: true })
// reset visited views and cached views
// to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2485
dispatch('tagsView/delAllViews', null, { root: true })
resolve()
}).catch(error => {
reject(error)
})
resolve()
// }).catch(error => {
// reject(error)
// })
})
},

View File

@ -24,6 +24,7 @@ html {
#app {
height: 100%;
color: #2c3e50;
}
*,
@ -189,3 +190,19 @@ aside {
.multiselect--active {
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'
const TokenKey = 'Admin-Token'
const TokenKey = 'access_token'
export function getToken() {
return Cookies.get(TokenKey)

View File

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

View File

@ -10,27 +10,19 @@
</h1>
gif来源<a href="https://zh.airbnb.com/" target="_blank">airbnb</a> 页面
<h2>你没有权限去该页面</h2>
<h6>如有不满请联系你领导</h6>
<ul class="list-unstyled">
<li>或者你可以去:</li>
<li class="link-type">
<router-link to="/dashboard">
<router-link to="/overview">
回首页
</router-link>
</li>
<li class="link-type">
<a href="https://www.taobao.com/">随便看看</a>
</li>
<li><a href="#" @click.prevent="dialogVisible=true">点我看图</a></li>
</ul>
</el-col>
<el-col :span="12">
<img :src="errGif" width="313" height="428" alt="Girl has dropped her ice cream.">
</el-col>
</el-row>
<el-dialog :visible.sync="dialogVisible" title="随便看">
<img :src="ewizardClap" class="pan-img">
</el-dialog>
</div>
</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>
<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-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>
</template>
<script>
import { validUsername } from '@/utils/validate'
import SocialSign from './components/SocialSignin'
import { isString } from '@/utils/validate'
// import SocialSign from './components/SocialSignin'
export default {
name: 'Login',
components: { SocialSign },
// components: { SocialSign },
data() {
const validateUsername = (rule, value, callback) => {
if (!validUsername(value)) {
if (!isString(value)) {
callback(new Error('Please enter the correct user name'))
} else {
callback()
@ -98,7 +76,7 @@ export default {
return {
loginForm: {
username: 'admin',
password: '111111'
password: 'P@88w0rd'
},
loginRules: {
username: [{ required: true, trigger: 'blur', validator: validateUsername }],
@ -158,6 +136,7 @@ export default {
this.loading = true
this.$store.dispatch('user/login', this.loginForm)
.then(() => {
this.$message.success('登录成功')
this.$router.push({ path: this.redirect || '/', query: this.otherQuery })
this.loading = false
})
@ -178,24 +157,6 @@ export default {
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>

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,
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: {
// provide the app's title in webpack's name field, so that