forked from JointCloud/JCC-RIP
liliang
This commit is contained in:
parent
4b592f8173
commit
3affdb6052
File diff suppressed because it is too large
Load Diff
|
@ -97,3 +97,55 @@ export function putHostNetwork(name, data) {
|
|||
data: data
|
||||
})
|
||||
}
|
||||
// 虚拟机管理-镜像列表
|
||||
export function getImages() {
|
||||
return request({
|
||||
url: '/v1/harvesterhci.io.virtualmachineimages',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function getImagesYaml(name) {
|
||||
return request({
|
||||
url: '/proxy/apis/cdi.kubevirt.io/v1beta1/namespaces/default/datavolumes/' + name,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function putImagesYaml(name, yaml) {
|
||||
return request({
|
||||
url: '/proxy/apis/cdi.kubevirt.io/v1beta1/namespaces/default/datavolumes/' + name,
|
||||
method: 'put',
|
||||
data: yaml
|
||||
})
|
||||
}
|
||||
|
||||
/* export function getVirtualMachineYaml(name) {
|
||||
return request({
|
||||
url: '/proxy/apis/kubevirt.io/v1/namespaces/default/virtualmachines/' + name,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function putVirtualMachineYaml(name, yaml) {
|
||||
return request({
|
||||
url: '/proxy/apis/kubevirt.io/v1/namespaces/default/virtualmachines/' + name,
|
||||
method: 'put',
|
||||
data: yaml
|
||||
})
|
||||
} */
|
||||
|
||||
/* export function getHostNetwork(name) {
|
||||
return request({
|
||||
url: '/proxy/v1/network.harvesterhci.io.nodenetworks/harvester-system/' + name + '-vlan',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function putHostNetwork(name, data) {
|
||||
return request({
|
||||
url: '/proxy/v1/network.harvesterhci.io.nodenetworks/harvester-system/' + name + '-vlan',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
} */
|
||||
|
|
|
@ -142,6 +142,55 @@ const virtualMachineRouter = {
|
|||
}]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'images',
|
||||
component: emptyLayout,
|
||||
redirect: 'images',
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: () => import('@/views/virtualMachine/images.vue'),
|
||||
name: 'images',
|
||||
meta: { title: '镜像', icon: 'el-icon-picture-outline', affix: true },
|
||||
hidden: false
|
||||
},
|
||||
{
|
||||
path: 'create',
|
||||
component: () => import('@/views/virtualMachine/imagesCreate.vue'),
|
||||
name: 'imagesCreate',
|
||||
meta: { activeMenu: '/virtual/images' },
|
||||
hidden: true
|
||||
},
|
||||
{
|
||||
path: 'detail',
|
||||
component: () => import('@/views/virtualMachine/imagesDetailPanel.vue'),
|
||||
name: 'detail',
|
||||
meta: { activeMenu: '/virtual/images' },
|
||||
hidden: true,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: () => import('@/views/virtualMachine/imagesDetail'),
|
||||
meta: { activeMenu: '/virtual/images', keepAlive: true }
|
||||
},
|
||||
{
|
||||
path: 'overview',
|
||||
component: () => import('@/views/virtualMachine/imagesDetail'),
|
||||
meta: { activeMenu: '/virtual/images', keepAlive: true }
|
||||
},
|
||||
{
|
||||
path: 'config',
|
||||
component: () => import('@/views/virtualMachine/imagesConfig'),
|
||||
meta: { activeMenu: '/virtual/images', keepAlive: true }
|
||||
},
|
||||
{
|
||||
path: 'yaml',
|
||||
component: () => import('@/views/virtualMachine/datavolumeYAML'),
|
||||
meta: { activeMenu: '/virtual/images', keepAlive: true }
|
||||
}]
|
||||
}
|
||||
]
|
||||
}]
|
||||
}
|
||||
export default virtualMachineRouter
|
||||
|
|
|
@ -2,7 +2,8 @@ import { getVolume } from '@/api/one-class-page/storageManagement'
|
|||
import { getNodeMessage, getNodeStatus } from '@/api/one-class-page/nodeManagement'
|
||||
import { getByValue } from '@/utils/data-process'
|
||||
import { getDaemonSets, getDeployments, getPods, getServices, getStatefulSets } from '@/api/one-class-page/workloadManagement'
|
||||
import { getVirtualHosts, getVirtualMachines, getDataVolume } from '@/api/one-class-page/virtualMachine'
|
||||
import { getVirtualHosts, getVirtualMachines, getDataVolume, getImages } from '@/api/one-class-page/virtualMachine'
|
||||
// import { getImages } from '@/api/one-class-page/virtualMachine'
|
||||
import {
|
||||
getBriefSystemProject,
|
||||
getBriefUserProject,
|
||||
|
@ -213,7 +214,7 @@ const getStatefulSetList = (clusterName, params) => {
|
|||
})
|
||||
}
|
||||
|
||||
const getDaemonSetList = (clusterName, params) => {
|
||||
const getDemoSetList = (clusterName, params) => {
|
||||
const listResult = []
|
||||
return new Promise(function(resolve) {
|
||||
getDaemonSets(clusterName, params).then(response => {
|
||||
|
@ -336,7 +337,7 @@ const getDataVolumeList = () => {
|
|||
return new Promise(function(resolve) {
|
||||
const listResult = []
|
||||
getDataVolume().then((res) => {
|
||||
// console.log(res)
|
||||
console.log(res)
|
||||
for (let item = 0; item < res.data.length; item++) {
|
||||
var obj = {}
|
||||
obj.index = item
|
||||
|
@ -357,6 +358,30 @@ const getDataVolumeList = () => {
|
|||
obj.creationTime = res.data[item].metadata.creationTimestamp
|
||||
obj.vm = res.data[item].metadata.ownerReferences[0].name
|
||||
obj.size = res.data[item].spec.pvc.resources.requests.storage
|
||||
// console.log(res.data)
|
||||
listResult[item] = obj
|
||||
}
|
||||
resolve({ total: res.data.length, rows: listResult })
|
||||
})
|
||||
})
|
||||
}
|
||||
const getImagesList = () => {
|
||||
return new Promise(function(resolve) {
|
||||
const listResult = []
|
||||
getImages().then((res) => {
|
||||
// console.log(res)
|
||||
for (let item = 0; item < res.data.length; item++) {
|
||||
var obj = {}
|
||||
obj.index = item
|
||||
obj.name = res.data[item].spec.displayName
|
||||
obj.state = res.data[item].metadata.state.name
|
||||
obj.creationTime = res.data[item].metadata.creationTimestamp
|
||||
obj.aliveTime = res.data[item].metadata.fields[5]
|
||||
obj.aliveTime = obj.aliveTime.replace('d', '天')
|
||||
obj.aliveTime = obj.aliveTime.replace('h', '小时')
|
||||
// obj.size = res.data[item].spec.pvc.resources.requests.storage
|
||||
obj.size = '510mb'
|
||||
console.log(res.data)
|
||||
listResult[item] = obj
|
||||
}
|
||||
resolve({ total: res.data.length, rows: listResult })
|
||||
|
@ -364,4 +389,4 @@ const getDataVolumeList = () => {
|
|||
})
|
||||
}
|
||||
|
||||
export default { getClusterHosts, getClusterMembers, getVolumeList, getNodeStatusList, getServiceList, getPodList, getDeploymentList, getStatefulSetList, getDaemonSetList, getUserProjectList, getSystemProjectList, getVirtualMachineList, getVirtualHostList, getDataVolumeList }
|
||||
export default { getClusterHosts, getClusterMembers, getVolumeList, getNodeStatusList, getServiceList, getPodList, getDeploymentList, getStatefulSetList, getDemoSetList, getUserProjectList, getSystemProjectList, getVirtualMachineList, getVirtualHostList, getDataVolumeList, getImagesList }
|
||||
|
|
|
@ -0,0 +1,156 @@
|
|||
<template>
|
||||
<div class="podInfo">
|
||||
<el-card class="basicInfo" shadow="never">
|
||||
<el-row type="flex" justify="space-between">
|
||||
<el-col>
|
||||
<div>
|
||||
<img src="@/assets/img/pod.png" class="sidebar-logo" alt="镜像">
|
||||
<h4>镜像</h4>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="3" :offset="8" class="btnBox">
|
||||
<div>
|
||||
<el-button round size="medium" type="primary" @click="creation">创建</el-button>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
<el-card shadow="never">
|
||||
<List
|
||||
ref="multipleTable"
|
||||
class="multipleTable"
|
||||
:columns="columns"
|
||||
:filter-map="filterMap"
|
||||
func-name="getImagesList"
|
||||
:cluster-name="clusterName"
|
||||
:pagination="true"
|
||||
tooltip-effect="dark"
|
||||
/>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import List from '@/components/list'
|
||||
import { getImagesYaml } from '@/api/one-class-page/virtualMachine'
|
||||
|
||||
export default {
|
||||
name: 'PodForm',
|
||||
components: { List },
|
||||
data() {
|
||||
return {
|
||||
timer: null,
|
||||
timeInterval: 10000,
|
||||
disabled: false,
|
||||
filterMap: {
|
||||
name: {
|
||||
label: '名称'
|
||||
},
|
||||
status: {
|
||||
label: '状态',
|
||||
type: 'select'
|
||||
}
|
||||
},
|
||||
columns: [
|
||||
{ prop: 'state', label: '状态', formatter: (row) => { return <el-tag type='success'>{row.state}</el-tag> } },
|
||||
{ prop: 'name', label: '名称', formatter: (row) => { return <a onClick={() => this.viewImagesDetail(row)}>{row.name}</a> } },
|
||||
{ prop: 'size', label: '大小' },
|
||||
{ prop: 'aliveTime', label: '存活时间', formatter: (row) => { return <el-tooltip effect='light' content={row.creationTime} placement='right'><span>{row.aliveTime}</span></el-tooltip> } },
|
||||
{
|
||||
prop: 'more', label: '更多操作', formatter: (row) => {
|
||||
return <div>
|
||||
<el-dropdown>
|
||||
<el-button size='mini' className='el-dropdown-link' type='primary' icon='el-icon-more' circle>
|
||||
</el-button>
|
||||
<el-dropdown-menu slot='dropdown'>
|
||||
<span onClick={() => this.clickOption(row, 1)}> <el-dropdown-item><i class='el-icon-edit'></i> 编辑配置 </el-dropdown-item> </span>
|
||||
<span onClick={() => this.clickOption(row, 2)}> <el-dropdown-item><i class='el-icon-tickets'></i> 克隆 </el-dropdown-item> </span>
|
||||
<span onClick={() => this.clickOption(row, 3)}> <el-dropdown-item><i class='el-icon-document'></i> 创建虚拟机 </el-dropdown-item> </span>
|
||||
<span onClick={() => this.clickOption(row, 4)}> <el-dropdown-item><i class='el-icon-download'></i> 下载YAML </el-dropdown-item> </span>
|
||||
<span onClick={() => this.clickOption(row, 5)}> <el-dropdown-item divided><i class='el-icon-delete'></i> 删除 </el-dropdown-item> </span>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
clusterName() {
|
||||
// console.log(this.$store.getters)
|
||||
// return this.$store.getters.clusterName
|
||||
if (localStorage.getItem('clusterName') === 'default') {
|
||||
return ''
|
||||
} else {
|
||||
return '/clusters/' + localStorage.getItem('clusterName')
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
},
|
||||
beforeDestroy() {
|
||||
// clearInterval(this.timer)
|
||||
// this.timer = null
|
||||
},
|
||||
methods: {
|
||||
viewImagesDetail(row) {
|
||||
this.$router.push({ path: `images/detail`, query: row })
|
||||
},
|
||||
creation() {
|
||||
this.$router.push({ path: `images/create` })
|
||||
},
|
||||
// selectOption(a) {
|
||||
// // console.log( this.$refs.sxx.value);
|
||||
// console.log(a.target.value)
|
||||
// }
|
||||
clickOption(row, command) {
|
||||
switch (command) {
|
||||
case 1:
|
||||
row.disableConfig = false
|
||||
this.$router.push({ path: `images/detail/config`, query: row })
|
||||
break
|
||||
case 2:
|
||||
row.clone = true
|
||||
this.$router.push({ path: `images/detail/config`, query: row })
|
||||
break
|
||||
case 3:
|
||||
row.editYaml = true
|
||||
// this.$router.push({ path: `images/detail/yaml`, query: row })
|
||||
break
|
||||
case 4:
|
||||
this.downloadHostYaml(row.name)
|
||||
break
|
||||
case 5:
|
||||
break
|
||||
default:
|
||||
}
|
||||
},
|
||||
viewVMDetail(row) {
|
||||
this.$router.push({ path: `virtual-machine/detail`, query: row })
|
||||
},
|
||||
downloadHostYaml(name) {
|
||||
getImagesYaml(name).then(res => {
|
||||
var data = JSON.stringify(res)
|
||||
// encodeURIComponent解决中文乱码
|
||||
const uri = 'data:text/csv;charset=utf-8,\ufeff' + encodeURIComponent(data)
|
||||
// 通过创建a标签实现
|
||||
const link = document.createElement('a')
|
||||
link.href = uri
|
||||
// 对下载的文件命名
|
||||
link.download = name + '.json'
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.btnBox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,152 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="formcontainer">
|
||||
<el-form ref="formData" :rules="rules" :model="formData" label-position="top">
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="名称"><el-input
|
||||
v-model="formData.name"
|
||||
:disabled="!clone"
|
||||
:hide-required-asterisk="true"
|
||||
/></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="描述"><el-input
|
||||
v-model="formData.description"
|
||||
placeholder="请输入一些内容更好地描述该资源"
|
||||
:disabled="isDisabled"
|
||||
:hide-required-asterisk="true"
|
||||
/></el-form-item></el-col>
|
||||
</el-row>
|
||||
<el-tabs type="border-card" tab-position="left">
|
||||
<el-tab-pane label="基本信息">
|
||||
<h4>基本信息</h4>
|
||||
<el-form-item label="资源类型">
|
||||
<el-select v-model="formData.resourceType" :disabled="!clone">
|
||||
<el-option
|
||||
v-for="item in options1"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="formData.resourceType==='VM Image'" label="镜像" :required="true">
|
||||
<el-select v-model="formData.image">
|
||||
<el-option
|
||||
v-for="item in options2"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="大小">
|
||||
<el-input
|
||||
v-model="formData.size"
|
||||
:disabled="!clone"
|
||||
><template slot="append">GIB</template></el-input>
|
||||
</el-form-item>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="标签">
|
||||
<h4>标签</h4>
|
||||
<div v-for="(item, index) in formData.tag" :key="item.id">
|
||||
<el-form-item>
|
||||
<el-row v-if="index=='0'" :gutter="20"><el-col :span="6"><h5>键</h5></el-col><el-col :span="6"><h5>值</h5></el-col></el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="6"><el-input v-model="item.key" placeholder="例如:test" /></el-col>
|
||||
<el-col :span="6"> <el-input v-model="item.value" placeholder="例如:test" /></el-col>
|
||||
<el-col :span="5"><el-button type="danger" icon="el-icon-delete" @click="removeTag(index)" /></el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<el-button type="primary" :disabled="isDisabled" @click="addTag">添加</el-button>
|
||||
</el-tab-pane>
|
||||
|
||||
</el-tabs>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-row type="flex" justify="end">
|
||||
<el-col :span="2.5">
|
||||
<el-button v-if="!isDisabled" type="info" @click="goBack">取消</el-button>
|
||||
<el-button v-if="!isDisabled" type="primary">创建</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
tagNum: 0,
|
||||
disableConfig: true,
|
||||
clone: false,
|
||||
formData: {
|
||||
name: '',
|
||||
description: '',
|
||||
size: '',
|
||||
resourceType: 'New',
|
||||
image: '',
|
||||
tag: []
|
||||
},
|
||||
options1: [{
|
||||
value: 'New',
|
||||
label: 'New'
|
||||
}, {
|
||||
value: 'VM Image',
|
||||
label: 'VM Image'
|
||||
}],
|
||||
options2: [{
|
||||
value: 'New',
|
||||
label: 'harvester-amd64.iso'
|
||||
}]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isDisabled() {
|
||||
return this.disableConfig && !this.clone
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getFormData()
|
||||
if (this.$route.query.disableConfig != null && typeof (this.$route.query.disableConfig) !== 'undefined') {
|
||||
this.disableConfig = this.$route.query.disableConfig
|
||||
}
|
||||
if (this.$route.query.clone != null && typeof (this.$route.query.clone) !== 'undefined') {
|
||||
this.clone = this.$route.query.clone
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getFormData() {
|
||||
this.formData.name = this.$route.query.name
|
||||
this.formData.size = this.$route.query.size.slice(0, -2)
|
||||
// this.formData.description = this.$route.query.description,
|
||||
// this.formData.resourceType = this.$route.query.resourceType
|
||||
},
|
||||
addTag() {
|
||||
this.formData.tag.push(
|
||||
{
|
||||
id: this.tagNum++,
|
||||
key: '',
|
||||
value: ''
|
||||
}
|
||||
)
|
||||
},
|
||||
removeTag(index) {
|
||||
this.formData.tag.splice(index, 1)
|
||||
},
|
||||
goBack() {
|
||||
this.$router.push({ path: '/virtual/images.vue' })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.formcontainer{
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,157 @@
|
|||
<template>
|
||||
<el-card shadow="never">
|
||||
<el-page-header content="详情" @back="goBack" />
|
||||
<h2>镜像:创建 </h2>
|
||||
<el-divider />
|
||||
<div class="formcontainer">
|
||||
<el-form ref="formData" :rules="rules" :model="formData" label-position="top">
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="名称" prop="name"><el-input
|
||||
v-model="formData.name"
|
||||
placeholder="请输入名称"
|
||||
:hide-required-asterisk="true"
|
||||
/></el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="描述"><el-input
|
||||
v-model="formData.description"
|
||||
placeholder="请输入一些内容更好地描述该资源"
|
||||
:hide-required-asterisk="true"
|
||||
/></el-form-item></el-col>
|
||||
</el-row>
|
||||
<el-tabs type="border-card" tab-position="left">
|
||||
<el-tab-pane label="基本信息">
|
||||
<h4>基本信息</h4>
|
||||
<el-form-item label="资源类型" prop="resourceType">
|
||||
<el-select v-model="formData.resourceType">
|
||||
<el-option
|
||||
v-for="item in options1"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="formData.resourceType==='VM Image'" label="镜像" :required="true">
|
||||
<el-select v-model="formData.image">
|
||||
<el-option
|
||||
v-for="item in options2"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="大小" prop="size">
|
||||
<el-input
|
||||
v-model="formData.size"
|
||||
><template slot="append">GIB</template></el-input>
|
||||
</el-form-item>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="标签">
|
||||
<h4>标签</h4>
|
||||
<div v-for="(item, index) in formData.tag" :key="item.id">
|
||||
<el-form-item>
|
||||
<el-row v-if="index=='0'" :gutter="20"><el-col :span="6"><h5>键</h5></el-col><el-col :span="6"><h5>值</h5></el-col></el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="6"><el-input v-model="item.key" placeholder="例如:test" /></el-col>
|
||||
<el-col :span="6"> <el-input v-model="item.value" placeholder="例如:test" /></el-col>
|
||||
<el-col :span="5"><el-button type="danger" icon="el-icon-delete" @click="removeTag(index)" /></el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<el-button type="primary" @click="addTag">添加</el-button>
|
||||
</el-tab-pane>
|
||||
|
||||
</el-tabs>
|
||||
</el-form>
|
||||
</div>
|
||||
<el-row type="flex" justify="end">
|
||||
<el-col :span="2.5">
|
||||
<el-button type="info" @click="goBack">取消</el-button>
|
||||
<el-button type="primary">创建</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
tagNum: 0,
|
||||
formData: {
|
||||
name: '',
|
||||
description: '',
|
||||
size: '',
|
||||
resourceType: 'New',
|
||||
image: '',
|
||||
tag: []
|
||||
},
|
||||
options1: [{
|
||||
value: 'New',
|
||||
label: 'New'
|
||||
}, {
|
||||
value: 'VM Image',
|
||||
label: 'VM Image'
|
||||
}],
|
||||
options2: [{
|
||||
value: 'New',
|
||||
label: 'harvester-amd64.iso'
|
||||
}],
|
||||
// 校验规则
|
||||
rules: {
|
||||
name: [
|
||||
{
|
||||
required: true, // 是否必填
|
||||
message: '名称不能为空', // 规则提示
|
||||
trigger: 'blur' // 何事件触发
|
||||
}
|
||||
],
|
||||
size: [
|
||||
{
|
||||
required: true, // 是否必填
|
||||
message: '大小不能为空', // 规则提示
|
||||
trigger: 'blur' // 何事件触发
|
||||
}
|
||||
],
|
||||
resourceType: [
|
||||
{
|
||||
required: true // 是否必填
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
},
|
||||
methods: {
|
||||
goBack() {
|
||||
this.$router.push({ path: '/virtual/images.vue' })
|
||||
},
|
||||
addTag() {
|
||||
this.formData.tag.push(
|
||||
{
|
||||
id: this.tagNum++,
|
||||
key: '',
|
||||
value: ''
|
||||
}
|
||||
)
|
||||
},
|
||||
removeTag(index) {
|
||||
this.formData.tag.splice(index, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.formcontainer{
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-tabs type="border-card" tab-position="left" style="height: 500px;">
|
||||
<el-tab-pane key="" label="基本信息">
|
||||
<el-card shadow="never">
|
||||
<h5>基本信息</h5>
|
||||
<FormData :data="formData1" :data-map="dataMap1" />
|
||||
<!-- <el-divider /> -->
|
||||
</el-card>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { FormData } from '@/components/FormData'
|
||||
export default {
|
||||
components: { FormData },
|
||||
data() {
|
||||
return {
|
||||
index: '',
|
||||
formData1: {
|
||||
resourceType: 'Blank',
|
||||
size: this.$route.query.size
|
||||
},
|
||||
dataMap1: {
|
||||
resourceType: '资源类型',
|
||||
size: '大小'
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
clusterName() {
|
||||
// console.log(this.$store.getters)
|
||||
// return this.$store.getters.clusterName
|
||||
return localStorage.getItem('clusterName')
|
||||
}
|
||||
// addTagNumCheck() {
|
||||
// let flag = false
|
||||
// this.editTagForm.tags.forEach(e => {
|
||||
// if (e.key === '') {
|
||||
// flag = true
|
||||
// }
|
||||
// })
|
||||
// return flag
|
||||
// },
|
||||
// addTaintNumCheck() {
|
||||
// let flag = false
|
||||
// this.editTaintForm.taints.forEach(e => {
|
||||
// if (e.key === '') {
|
||||
// flag = true
|
||||
// }
|
||||
// })
|
||||
// return flag
|
||||
// }
|
||||
},
|
||||
created() {
|
||||
this.index = this.$route.query.index
|
||||
},
|
||||
mounted() {
|
||||
// this.getFormData()
|
||||
},
|
||||
methods: {
|
||||
// getFormData() {
|
||||
// }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,193 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-card v-if="!clone" shadow="never">
|
||||
<el-page-header content="详情" @back="goBack" />
|
||||
<h2>镜像:{{ $route.query.name }} <el-tag type="success">{{ $route.query.state }} </el-tag> <el-dropdown @command="handleDropdown">
|
||||
<el-button class-name="el-dropdown-link" type="primary" icon="el-icon-more" circle />
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item command="1"> <i class="el-icon-edit" /> 编辑配置 </el-dropdown-item>
|
||||
<el-dropdown-item command="2"> <i class="el-icon-tickets" /> 克隆 </el-dropdown-item>
|
||||
<el-dropdown-item command="3"> <i class="el-icon-document" /> 创建虚拟机 </el-dropdown-item>
|
||||
<el-dropdown-item command="4"> <i class="el-icon-download" /> 下载YAML </el-dropdown-item>
|
||||
<el-dropdown-item command="5"> <i class="el-icon-delete" /> 删除 </el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown> </h2>
|
||||
<h6>存活时间:{{ $route.query.aliveTime }}</h6>
|
||||
<el-tabs v-model="activeNumber" @tab-click="switchTab">
|
||||
<el-tab-pane key="overview" label="详情" />
|
||||
<el-tab-pane key="config" label="设置" />
|
||||
<el-tab-pane key="yaml" label="YAML" />
|
||||
</el-tabs>
|
||||
|
||||
<router-view ref="detail" />
|
||||
</el-card>
|
||||
<el-card v-if="clone" shadow="never">
|
||||
<h2>镜像:从{{ $route.query.name }}克隆</h2>
|
||||
<el-divider />
|
||||
<router-view ref="detail" />
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import { getHostYaml } from '@/api/one-class-page/virtualMachine'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
tabList: {
|
||||
'0': 'overview',
|
||||
'1': 'config',
|
||||
'2': 'yaml'
|
||||
},
|
||||
activeNumber: '',
|
||||
index: '',
|
||||
enableConfig: false,
|
||||
clone: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
clusterName() {
|
||||
return localStorage.getItem('clusterName')
|
||||
}
|
||||
},
|
||||
created() {
|
||||
for (const i in Object.keys(this.tabList)) {
|
||||
// console.log('i=' + i)
|
||||
// const r = this.$route.path.split('/')
|
||||
// console.log(r)
|
||||
// console.log(this.$route.path)
|
||||
if (this.$route.path.split('/')[4] === this.tabList[i]) {
|
||||
this.activeNumber = i
|
||||
}
|
||||
}
|
||||
this.index = this.$route.query.index
|
||||
},
|
||||
mounted() {
|
||||
if (this.$route.query.clone != null && typeof (this.$route.query.clone) !== 'undefined') {
|
||||
this.clone = this.$route.query.clone
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goBack() {
|
||||
this.$router.push({ path: '/virtual/images.vue' })
|
||||
},
|
||||
switchTab(e) {
|
||||
// console.log(e)
|
||||
// console.log(this.activeNumber)
|
||||
var tab = this.tabList[e.index]
|
||||
tab = '/virtual/images/detail/' + tab
|
||||
if (this.$route.path.indexOf(tab) === -1) {
|
||||
this.$router.push({ path: tab, query: this.$route.query })
|
||||
}
|
||||
},
|
||||
handleDropdown(command) {
|
||||
switch (command) {
|
||||
case '1':
|
||||
this.$refs.detail.disableConfig = false
|
||||
break
|
||||
case '2':
|
||||
break
|
||||
case '3':
|
||||
// this.$refs.detail.editYaml = true
|
||||
break
|
||||
case '4':
|
||||
this.downloadHostYaml(this.$route.query.name)
|
||||
break
|
||||
case 5:
|
||||
break
|
||||
default:
|
||||
}
|
||||
},
|
||||
downloadHostYaml(name) {
|
||||
getHostYaml(name).then(res => {
|
||||
var data = JSON.stringify(res)
|
||||
// encodeURIComponent解决中文乱码
|
||||
const uri = 'data:text/csv;charset=utf-8,\ufeff' + encodeURIComponent(data)
|
||||
// 通过创建a标签实现
|
||||
const link = document.createElement('a')
|
||||
link.href = uri
|
||||
// 对下载的文件命名
|
||||
link.download = name + '.json'
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.jcce-terminal{
|
||||
width: 100%;
|
||||
height: 600px;
|
||||
border-radius: 5px;
|
||||
padding: 7px;
|
||||
border: 1px solid #eee;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.jcce-terminal,
|
||||
.jcce-terminal .terminal-wrapper {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.jcce-terminal .terminal {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
outline: medium none;
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
background: #181d28;
|
||||
/* padding: 2px 0 2px 2px; */
|
||||
}
|
||||
|
||||
.jcce-terminal .terminal .xterm-viewport::-webkit-scrollbar {
|
||||
height: 10px;
|
||||
overflow: visible;
|
||||
width: 12px;
|
||||
}
|
||||
|
||||
.jcce-terminal
|
||||
.terminal
|
||||
.xterm-viewport::-webkit-scrollbar-corner {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.jcce-terminal
|
||||
.terminal
|
||||
.xterm-viewport::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(255, 255, 255, 0.25);
|
||||
box-shadow: inset 1px 1px 0 rgba(255, 255, 255, 0.1),
|
||||
inset 0 -1px 0 rgba(255, 255, 255, 0.07);
|
||||
}
|
||||
|
||||
.jcce-terminal
|
||||
.terminal
|
||||
.xterm-viewport::-webkit-scrollbar-thumb:active,
|
||||
.jcce-terminal
|
||||
.terminal
|
||||
.xterm-viewport::-webkit-scrollbar-thumb:hover {
|
||||
background-color: rgba(255, 255, 255, 0.35);
|
||||
}
|
||||
|
||||
.jcce-terminal
|
||||
.terminal
|
||||
.xterm-viewport::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.jcce-terminal .terminal-actions {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
right: 34px;
|
||||
top: 10px;
|
||||
vertical-align: top;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,53 @@
|
|||
<template>
|
||||
<div>
|
||||
<vue-json-editor
|
||||
v-model="yaml"
|
||||
:show-btns="editYaml"
|
||||
:mode="'code'"
|
||||
lang="zh"
|
||||
style="height: 720px"
|
||||
@json-change="onJsonChange"
|
||||
@json-save="onJsonSave"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { getImagesYaml, putImagesYaml } from '@/api/one-class-page/virtualMachine'
|
||||
import vueJsonEditor from 'vue-json-editor'
|
||||
export default {
|
||||
components: {
|
||||
vueJsonEditor
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
yaml: '',
|
||||
editYaml: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
getImagesYaml(this.$route.query.name).then(res => {
|
||||
// console.log(res)
|
||||
this.yaml = res
|
||||
})
|
||||
if (this.$route.query.editYaml != null && typeof (this.$route.query.editYaml) !== 'undefined') {
|
||||
this.editYaml = this.$route.query.editYaml
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// onJsonChange() {
|
||||
|
||||
// },
|
||||
onJsonSave() {
|
||||
putImagesYaml(this.$route.query.name).then(res => {
|
||||
// console.log(res)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.jsoneditor-vue{
|
||||
height: 90%;
|
||||
}
|
||||
</style>
|
|
@ -24,7 +24,7 @@ module.exports = {
|
|||
* In most cases please use '/' !!!
|
||||
* Detail: https://cli.vuejs.org/config/#publicpath
|
||||
*/
|
||||
publicPath: process.env.NODE_ENV === 'production' ? "/monitor/":"/monitor/",
|
||||
publicPath: process.env.NODE_ENV === 'production' ? '/monitor/' : '/monitor/',
|
||||
outputDir: 'dist',
|
||||
assetsDir: 'static',
|
||||
lintOnSave: process.env.NODE_ENV === 'development',
|
||||
|
@ -41,7 +41,7 @@ module.exports = {
|
|||
ws: false,
|
||||
// target: 'http://124.71.196.205:30881/' /* EduCoder */
|
||||
// target: 'http://119.3.157.144:30881/', /* KubeX */
|
||||
target: 'http://119.45.100.73:30881/', /* Host */
|
||||
target: 'http://119.45.100.73:30881/' /* Host */
|
||||
// target: 'http://39.103.233.49:30881/', /* BJ-Member2 */
|
||||
},
|
||||
'^/v1': {
|
||||
|
@ -60,39 +60,38 @@ module.exports = {
|
|||
// ws: true,
|
||||
// target: 'http://124.71.196.205:30881/' /* EduCoder */
|
||||
// target: 'http://119.3.157.144:30881/', /* KubeX */
|
||||
target: 'http://119.45.100.73:30881/', /* Host */
|
||||
target: 'http://119.45.100.73:30881/'/* Host */
|
||||
// target: 'http://39.103.233.49:30881/', /* BJ-Member2 */
|
||||
// changeOrigin: true,
|
||||
},
|
||||
'^/prom': {
|
||||
ws: false,
|
||||
target: 'http://119.3.157.144:9090/', /* KubeX */
|
||||
target: 'http://119.3.157.144:9090/', /* KubeX */
|
||||
pathRewrite: {
|
||||
'^/prom': ''
|
||||
}
|
||||
},
|
||||
'^/api': {
|
||||
ws: false,
|
||||
target: 'http://119.45.100.73:30881/', /* Host */
|
||||
target: 'http://119.45.100.73:30881/'/* Host */
|
||||
// changeOrigin: true,
|
||||
},
|
||||
'^/authLedger': {
|
||||
ws: false,
|
||||
// target: 'http://119.45.100.73:30881/', /* Host */
|
||||
target: 'http://124.71.195.158:8080/',
|
||||
target: 'http://124.71.195.158:8080/'
|
||||
},
|
||||
'^/apiLedger': {
|
||||
ws: false,
|
||||
// target: 'http://119.45.100.73:30881/', /* Host */
|
||||
target: 'http://124.71.195.158:8080/',
|
||||
target: 'http://124.71.195.158:8080/'
|
||||
},
|
||||
'/kapis/terminal.kubesphere.io': {
|
||||
ws: true,
|
||||
changeOrigin: true,
|
||||
target: 'ws://119.45.100.73:30881/', /* Host */
|
||||
},
|
||||
|
||||
},
|
||||
target: 'ws://119.45.100.73:30881/' /* Host */
|
||||
}
|
||||
}
|
||||
// before: require('./mock/mock-server.js')
|
||||
},
|
||||
configureWebpack: {
|
||||
|
|
Loading…
Reference in New Issue