forked from JointCloud/JCC-RIP
kubex 20210123
This commit is contained in:
parent
8c7630daa2
commit
a872acc16c
|
@ -2,4 +2,4 @@
|
||||||
ENV = 'development'
|
ENV = 'development'
|
||||||
|
|
||||||
# base api
|
# base api
|
||||||
VUE_APP_BASE_API = '/dev-api'
|
VUE_APP_BASE_API = '/'
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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
|
||||||
|
|
|
@ -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*/
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
})
|
// })
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue