Compare commits

..

8 Commits

25 changed files with 4022 additions and 35 deletions

View File

@ -238,6 +238,7 @@
"password": "Password",
"createVirtualmachine": "Create Virtual Machine",
"createHpcbase": "Create Supercomputing Base Template",
"createVasp": "Create Vasp Task",
"createAibase": "Create Intelligent Computing Task",
"createAiCard": "Create Specific Computing Power Card Task",
"dict": "Dictionary",
@ -568,6 +569,11 @@
"application": "Application",
"deployment": "Deployment",
"instanceCenter": "Instance Center",
"instanceType": "Instance Type"
"instanceType": "Instance Type",
"createVaspTask": "Create Vasp Task",
"partition": "Partition",
"cmdScript": "Script",
"fileUpload": "File Upload",
"uploadSuccess": "Upload Success"
}
}

View File

@ -238,8 +238,9 @@
"password": "密码",
"createVirtualmachine": "创建虚拟机",
"createHpcbase": "创建超算基础模板",
"createVasp": "中国算力网-创建Vasp任务",
"createAibase": "创建智算训练任务",
"createAiCard": "创建指定算力卡训练任务",
"createAiCard": "中国算力网-创建指定算力卡训练任务",
"dict": "字典",
"dictName": "字典名称",
"dictCode": "code",
@ -568,6 +569,11 @@
"application": "应用",
"deployment": "部署",
"instanceCenter": "实例中心",
"instanceType": "实例类型"
"instanceType": "实例类型",
"createVaspTask": "创建Vasp任务",
"partition": "分区",
"cmdScript": "脚本",
"fileUpload": "文件上传",
"uploadSuccess": "上传成功"
}
}

View File

@ -19,3 +19,8 @@ export const getHomeOverview = () => {
export const getSituation = () => {
return request({ url: '/pcm/v1/monitoring/schedule/situation', method: 'get' })
}
export const getCpList = () => {
return request({ url: '/ai4m/v1/screen/resources', method: 'get' })
}

View File

@ -47,6 +47,12 @@ export const addApp = (data) => {
export const addHpcTask = (data) => {
return request({ url: '/pcm/v1/hpc/commitHpcTask', method: 'post', data })
}
export const uploadVaspContent = (data) => {
return request({ url: '/ai4m/v1/sftp/upload', method: 'post', data })
}
export const downloadVaspContent = (params) => {
return request({ url: '/ai4m/v1/sftp/download', method: 'get', params })
}
export const addVirtualMachine = (data) => {
return request({ url: '/pcm/v1/core/commitVmTask', method: 'post', data })
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -99,6 +99,17 @@ export const constantRoutes = [
component: () => import('@/views/monitorSelectPcm/index'),
meta: { title: 'monitorSelectPcm' },
hidden: true
},
{
path: '/resourceList',
component: () => import('@/views/cluster/resourceList'),
hidden: true
},
{
path: '/monitorSelectDev',
component: () => import('@/views/monitorSelectDev/index'),
meta: { title: 'monitorSelectDev' },
hidden: true
}
// {
// path: '/resourceList',

View File

@ -2,13 +2,14 @@
<div>
<Navbar />
<el-card class="list-detail">
<el-page-header content="资源清单" @back="goBack" />
<el-page-header content="算力清单" @back="goBack" />
<List
ref="multipleTable"
class="multipleTable"
:columns="columns"
:pagination="false"
func-name="getServerResourceData"
list-key="data"
:get-list-action="getCpList"
/>
</el-card>
</div>
@ -17,34 +18,38 @@
<script>
import List from '@/components/list'
import Navbar from '@/layout/components/Navbar'
import { getCpList } from '@/api/pcm/dashboard'
export default {
components: { List, Navbar },
data() {
return {
getCpList,
columns: [
{ prop: 'name', label: '资产名称' },
{ prop: 'ip', label: 'ip' },
{ prop: 'publicIp', label: '公网ip' },
{ prop: 'hpcPartition', label: '超算队列' },
{ prop: 'cpuName', label: 'cpu名称' },
{ prop: 'cpuGHz', label: 'cpu单核主频' },
{ prop: 'cpuCores', label: 'cpu单节点核心数' },
{ prop: 'cpuSingleCycle', label: 'cpu单周期指令执行数' },
{ prop: 'cpuGFlops', label: 'cpu理论峰值/GFlops' },
{ prop: 'totalThreads', label: 'cpu单节点线程数' },
{ prop: 'gpuDcu', label: 'gpu或dcu名称' },
{ prop: 'gpuGFlops', label: 'gpu理论峰值/GFlops' },
{ prop: 'memory', label: this.$t('page.memory') },
{ prop: 'num', label: '节点数' },
{ prop: 'region', label: '地域' },
{ prop: 'flops', width: 140, label: '理论峰值/GFlops' }
{ prop: 'name', label: '名称' },
// { prop: 'ip', label: 'ip' },
// { prop: 'publicIp', label: 'ip' },
// { prop: 'hpcPartition', label: '' },
// { prop: 'cpuName', label: 'cpu' },
// { prop: 'cpuGHz', label: 'cpu' },
// { prop: 'cpuCores', label: 'cpu' },
// { prop: 'cpuSingleCycle', label: 'cpu' },
// { prop: 'cpuGFlops', label: 'cpu/GFlops' },
// { prop: 'totalThreads', label: 'cpu线' },
// { prop: 'gpuDcu', label: 'gpudcu' },
// { prop: 'gpuGFlops', label: 'gpu/GFlops' },
// { prop: 'memory', label: '' },
{ prop: 'resourceType', label: '算力资源类型' },
{ prop: 'num', label: '卡数(张)' },
{ prop: 'singleTFLOPS', label: '单卡算力(TFLOPS@FP32)' },
// { prop: 'region', label: '' },
{ prop: 'totalPFLOPS', width: 140, label: '算力总量(PFLOPS@FP32)' }
]
}
},
methods: {
goBack() {
this.$router.push('/cluster/clusterMapViews')
this.$router.push('/monitorSelectPcm')
}
}

View File

@ -0,0 +1,143 @@
<template>
<div class="chainList">
<ul class="chain" :style="'width: '+ blockChainList*7 + 'vw'">
<li v-for="(item, index) in blockChainList" :key="index" class="chainItem">
<div class="item" @click="goChain" />
<div class="itemChain" />
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
blockChainList: [
{
name: ''
},
{
name: ''
},
{
name: ''
},
{
name: ''
},
{
name: ''
}
],
active: 0,
timer: ''
}
},
mounted() {
this.$nextTick(() => {
const vw = window.innerWidth / 100
const elwrapper = document.getElementsByClassName('chainList')[0]
elwrapper.style.width = '25vw'
const elBody = document.getElementsByClassName('chain')[0]
const elRow = document.getElementsByClassName('chainItem')
for (const node of elRow) {
node.style.width = '7vw'
}
elBody.style.left = 0
elBody.style.transactionDuration = '2000ms'
this.timer = setInterval(() => {
if (this.active < parseInt(this.blockChainList.length) - 2) {
this.active += 1
elBody.style.left = parseInt(elBody.style.left) - parseInt(vw * 3.5) + 'px'
} else {
if (this.isClear) {
clearInterval(this.timer)
}
// if (this.isAgain) {
this.active = 0
elBody.style.left = 0
// } else {
// clearInterval(this.timer)
// }
}
}, '5000')
})
},
destroyed() {
clearInterval(this.timer)
},
methods: {
goChain() {
this.$store.dispatch('user/setRouteType', 'blockChain')
this.$router.push({ path: '/blockChain/blockList' })
}
}
}
</script>
<style lang="scss" scoped>
.chainList{
width: 100%;
height: 6vh;
overflow: hidden;
position: relative;
padding: 0 10px;
ul {
width: 1000px;
height: 6vh;
list-style: none;
// overflow-x: auto;
white-space: nowrap;
margin: 0;
padding: 0;
position: absolute;
transition:left 1s ease-in-out;
left: 0;
}
li{
width: 7vw;
height: 6vh;
display: block;
float: left;
.item{
width: 50%;
height: 6vh;
display: block;
cursor: pointer;
background: url('../../../assets/monitor/chainItem.png') center no-repeat;
background-size: contain;
float: left;
position: relative;
.data{
display: block;
position: absolute;
width: 200px;
height: 50px;
z-index: 99;
border: 1px solid rgba(62, 223, 252, 1);
background-color: rgba(1, 14, 41, 0.8);
color: #ffffff;
// display: none;
}
&:hover{
background-image: url('../../../assets/monitor/chainItemClick.png');
// background-position: -1px -1px;
.data{
display: block;
}
}
}
.itemChain{
width: 50%;
height: 1vh;
margin-top: 2vh;
float: left;
// position: absolute;
background: url('../../../assets/monitor/chain.png') center no-repeat;
background-size: contain;
}
}
}
</style>

View File

@ -0,0 +1,312 @@
<template>
<!-- 计算域信息 -->
<div style="height:100%">
<el-row class="top">
<el-col :span="10"><div class="img" /></el-col>
<el-col :span="14">
<div class="text">
<el-carousel direction="vertical" :autoplay="true" @change="changeItem">
<el-carousel-item v-for="(item, index) in areaItem" :key="'areaItem' + index" class="areaList">
<div class="area">{{ item.domainName || 'DomainName' }}</div>
<table>
<tr>
<td>
<span>资源类型</span>
</td>
<td>
{{ item.resourceType }}
</td>
</tr>
<tr>
<td>
<span>适配技术栈</span>
</td>
<td>
{{ item.stack }}
</td>
</tr>
</table>
</el-carousel-item>
</el-carousel>
</div>
</el-col>
</el-row>
<el-row class="bottom">
<el-col :span="10">
<div id="radarChart" ref="radarChart" style="width: 100%; height: 16vh" />
</el-col>
<el-col :span="14">
<div class="text">
<table>
<tr>
<td>
<span>本地存储</span>
</td>
<td>
<el-progress :stroke-width="8" :percentage="Number(computePercent.diskUsage)" />
</td>
<td>
<span>/ {{ computePercent.diskTotal }} GB</span>
</td>
</tr>
<tr>
<td>
<span>节点数</span>
</td>
<td>
<el-progress :stroke-width="8" :percentage="Number(computePercent.nodeUsage)" />
</td>
<td>
<span> / {{ computePercent.nodeTotal }} </span>
</td>
</tr>
<tr>
<td>
<span>内存</span>
</td>
<td>
<el-progress :stroke-width="8" :percentage="Number(computePercent.memoryUsage)" />
</td>
<td>
<span>/ {{ computePercent.memoryTotal }} GB</span>
</td>
</tr>
<tr>
<td>
<span>cpuUsage</span>
</td>
<td>
<el-progress :stroke-width="8" :percentage="Number(computePercent.cpuUsage)" />
</td>
<td>
<span>/ {{ computePercent.cpuTotal }} Core</span>
</td>
</tr>
</table>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import * as echarts from 'echarts'
import { getComputeArea } from '@/api/container/monitorSelect.js'
import { debounce } from '@/utils'
export default {
data() {
return {
areaItem: [],
radarChart: undefined,
computePercent: {
diskUsage: 0,
memoryUsage: 0,
nodeUsage: 0,
cpuUsage: 0
}
}
},
mounted() {
getComputeArea().then((res) => {
this.areaItem = res.data.domainResourceList
const charts = echarts.init(this.$refs.radarChart)
const { diskUsage, memoryUsage, nodeUsage, cpuUsage } = this.areaItem[0]
this.computePercent = this.areaItem[0]
charts.setOption(this.returnRadarChart([diskUsage, memoryUsage, nodeUsage, cpuUsage]))
window.addEventListener('resize', debounce(() => {
charts.resize()
}, 100))
this.radarChart = charts
})
},
methods: {
changeItem(e) {
const { diskUsage, memoryUsage, nodeUsage, cpuUsage } = this.areaItem[e]
this.computePercent = this.areaItem[e]
this.radarChart.setOption(this.returnRadarChart([diskUsage, memoryUsage, nodeUsage, cpuUsage]))
},
fontSize(rem) {
const scale = window.innerHeight / 900
console.log(scale)
return scale >= 1 ? 16 * rem : 14 * rem
},
returnRadarChart(data) {
return {
tooltip: {
trigger: 'item',
backgroundColor: '#000033',
textStyle: { color: '#fff' },
borderWidth: 0,
position: 'right'
},
radar: {
radius: '60%',
shape: 'circle',
splitArea: {
show: false,
areaStyle: {
color: ['rgba(255,255,255,0.45)', 'rgba(255,255,255,0.35)', 'rgba(255,255,255,0.25)', 'rgba(255,255,255,0.15)', 'rgba(255,255,255,0.1)']
}
},
splitLine: {
lineStyle: {
color: 'rgba(14, 55, 100, 1)'
}
},
axisLine: { // 线
show: false // show
},
name: { // ()
formatter: '{value}',
textStyle: {
fontSize: this.fontSize(0.7)
}
},
indicator: [
{ name: '本地存储', max: 100 },
{ name: '内存', max: 100 },
{ name: '节点数', max: 100 },
{ name: 'cpuUsage', max: 100 }
],
nameGap: 4
},
series: [{
name: '计算域信息',
type: 'radar',
symbol: 'none',
data: [
{
value: data
}
],
itemStyle: {
color: ['red'],
opacity: 1
},
lineStyle: {
color: 'rgba(35, 162, 236, 0.8)',
type: 'dashed'
},
areaStyle: //
{
color: 'rgba(1, 154, 251, 0.5)'
}
}]
}
}
}
}
</script>
<style lang="scss" scoped>
.top{
// display: flex;
// justify-content: space-between;
// padding: 5px 3%;
margin: 1vh 0;
::v-deep .el-carousel__indicators{
display: none;
}
.img{
height: 8vh;
background: url('../../../assets/images/monitorSelect/computingArea.png') center no-repeat;
background-size: auto 100%;
// margin-left: 3vw;
}
}
.text{
// width: 65%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
height: 8vh;
.areaList{
height: 8vh;
}
span{
font-size: 1rem;
}
.area{
height: 2vh;
line-height: 2vh;
font-size: 1.13rem;
margin: 0.4vh 0;
background-image: linear-gradient(0deg, #00C0FF 0%, #ffffff 100%);
background-clip: text;
-webkit-text-fill-color: transparent;
}
table{
padding: 0;
border-spacing: 0px;
width: 100%;
td{
@media screen and (max-height: 900px) {
transform: scale(0.8);
transform-origin: 0 0;
}
color: #DDDDDD;
height: 3vh;
}
}
}
.bottom{
margin-top: 2vh;
.text{
margin-top: 1.5vh;
height: 14vh;
}
table tr td:nth-child(2) {
padding-right: 2.5rem;
}
span{
margin: 0;
// height: 2.4vh;
// line-height: 3.4vh;
// @media screen and (max-height: 900px) {
// transform: scale(0.8);
// transform-origin: 0 0;
// }
}
}
::v-deep {
.el-progress{
height: 2.4vh;
line-height: 2.4vh;
}
.el-progress-bar{
margin: 0;
line-height: 2.5rem;
margin-right: 0px;
padding-right: 0px;
margin-left: -10px;
}
.el-progress__text{
color: white;
font-size: 0.5rem!important;
}
.el-progress-bar__outer {
background-color: rgba(135, 189, 245, 0.2);
}
.el-progress-bar__inner{
background-image: linear-gradient(90deg, #419eff, #00d9a6);
}
}
// @media screen and (min-width: 1921px) {
// .top{
// .img{
// width: auto;
// height: 100%;
// }
// .text{
// .area{
// font-size: 20px;
// }
// }
// }
// }
</style>

View File

@ -0,0 +1,96 @@
<template>
<!-- 算力中心总数 -->
<div>
<div class="two">
<div v-for="(item, index) in dataArray" :key="'data'+index">
<p class="title">{{ item.name }}</p>
<div class="num">{{ item.value }}</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
dataArray: [
{
name: '算力中心总数(计算域)',
value: 34
},
{
name: '已接入算力 POps@FP16',
value: '112.06'
},
{
name: '接入集群数',
value: '48'
}
]
}
},
methods: {
}
}
</script>
<style lang="scss" scoped>
.two{
display: flex;
justify-content: space-between;
margin-top: 10px;
// text-align: center;
>div{
padding: 10px;
padding-top: 0;
background: url('../../../assets/images/monitorSelect/dataBg.png') no-repeat left;
background-size: auto 100%;
}
.title{
font-size: 1.1rem;
margin: 0.5rem;
margin-bottom: 0.3rem;
letter-spacing: 0.1rem;
font-weight: bold;
color: #DDDDDD;
}
.num{
font-size: 1.9rem;
font-family: Impact;
font-weight: 400;
// padding-bottom: 5px;
text-align: right;
width: 80%;
// text-indent: 130%;
letter-spacing: 0.1rem;
display: inline-block;
padding: 0 15px 3px;
}
}
// @media screen and (min-width: 1921px) {
// .one{
// background-size: 39px 39px;
// font-size: 20px;
// .num{
// font-size: 38px;
// }
// }
// .two{
// p{
// margin: 16px 0 ;
// }
// .title{
// font-size: 14px;
// }
// .num{
// font-size: 27px;
// padding: 0 17px 5px;
// }
// }
// }
</style>

View File

@ -0,0 +1,219 @@
<!-- 算力使用趋势 -->
<template>
<div :id="id" ref="echart" style="width: 100%; height: 80%" />
</template>
<script>
import { debounce } from '@/utils'
export default {
name: 'LineChart',
props: {
id: {
type: String,
default: ''
},
data: {
type: Object,
default: () => ({})
},
config: {
type: Object,
default: () => ({})
},
type: {
type: Number,
default: 0
}
},
data() {
return {
Data: { used: [], xData: [] }
// xDataNumber: 120,
}
},
watch: {
data: {
handler(newValue, oldValue) {
// console.log(newValue)
const TempData = JSON.parse(JSON.stringify(newValue))
this.Data.used = TempData.used
this.Data.xData = TempData.xData
this.drawLine()
},
deep: true
}
},
mounted() {
// this.Data = { used: [59688.1, 59252.5, 59189.0, 55766.5, 55537.2, 54804.4, 52764.9], xData: ["2022-06-30", "2022-07-31", "2022-07-31", "2022-08-31", "2022-09-30", "2022-10-31", "2022-11-30"] }
this.$nextTick(() => {
this.drawLine()
})
},
destroyed() {
clearInterval(this.timer)
},
methods: {
fontSize(rem) {
const scale = window.innerHeight / 900
return scale >= 1 ? 16 * rem : 12 * rem
},
drawLine() {
const scaleRate = window.innerHeight / 1080 >= 1
// domecharts
const chart = this.$echarts.init(this.$refs.echart)
var option
option = {
title: {
text: '',
textStyle: {
color: '#008B45'
}
},
color: ['rgba(79, 172, 254, 1)'],
tooltip: {
trigger: 'axis',
axisPointer: {
show: false
},
backgroundColor: '#000033',
textStyle: { fontSize: this.fontSize(0.7), color: '#fff' },
borderWidth: 0
},
grid: {
right: '5%',
bottom: '25%',
top: scaleRate ? '15%' : '20%',
left: '13%'
},
xAxis: {
type: 'category',
boundaryGap: false,
data: this.Data.xData,
axisLine: {
lineStyle: {
color: 'rgba(135, 189, 245, 0.1)'
}
},
axisLabel: {
show: true,
interval: 28,
// rotate: -18,
// padding: [1, 0, 0, -10],
margin: scaleRate ? 14 : 10,
textStyle: {
fontSize: this.fontSize(0.75),
lineHeight: scaleRate ? 20 : 10,
color: '#DDDDDD',
fontFamily: 'Source Han Sans CN'
},
formatter: function(params) {
return params.slice(5).replaceAll('-', '/')
}
// formatter: function(params) {
// switch (params) {
// case '2023-04-30':
// return params.slice(2).replaceAll('-', '/')
// case '2023-03-31':
// return params.slice(2).replaceAll('-', '/')
// case '2023-02-28':
// return params.slice(2).replaceAll('-', '/')
// case '2023-01-31':
// return params.slice(2).replaceAll('-', '/')
// case '2022-12-31':
// return params.slice(2).replaceAll('-', '/')
// case '2022-11-30':
// return params.slice(2).replaceAll('-', '/')
// case '2022-10-31':
// return params.slice(2).replaceAll('-', '/')
// case '2022-09-30':
// return params.slice(2).replaceAll('-', '/')
// default:
// // return params.slice(2).replaceAll('-', '/')
// }
// }
},
axisTick: {
// x
show: false
}
},
yAxis: {
type: 'value',
name: this.config.unit,
// nameTextStyle: { //
// padding: this.config.unit.length > 7 ? [0, 0, 0, 45] : [0, 0, 0, 0]
// },
nameTextStyle: {
color: '#aaa',
fontSize: this.fontSize(0.75),
nameLocation: 'start'
},
splitLine: {
show: true,
lineStyle: {
color: 'rgba(135, 189, 245, 0.1)'
}
},
nameGap: 10,
data: [],
axisLine: {
lineStyle: {
color: '#fff'
}
},
axisLabel: {
show: true,
interval: 0,
align: 'right',
textStyle: {
fontSize: this.fontSize(0.75),
color: 'rgba(221, 221, 221, 1)',
fontFamily: 'Source Han Sans CN'
}
},
scale: true,
min: 0,
splitNumber: 3
},
series: [
{
name: this.config.status[0] ? this.config.status[0] : '',
type: 'line',
symbol: 'none',
label: {
show: false
},
data: this.Data.used,
areaStyle: {
opacity: 1,
color: new this.$echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgba(0, 242, 254, 1)' // 0%
},
{
offset: 1,
color: 'rgba(79, 172, 254, 1)' // 100%
}
])
}
}
],
animation: true,
animationDuration: function(idx) {
//
return idx * 500
},
animationEasing: 'backln'
}
chart.setOption(option)
window.addEventListener('resize', debounce(() => {
chart.resize()
}, 100))
}
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,306 @@
<!-- 算力使用情况 -->
<template>
<div :id="id" ref="echart" style="width: 95%; height: 85%" />
</template>
<script>
import { debounce } from '@/utils'
export default {
name: 'Histogram',
props: {
id: {
type: String,
default: ''
},
data: {
type: Object,
default: () => { }
},
config: {
type: Object,
default: () => ({})
}
},
data() {
return {
timer: null,
Data: {
unused: [], used: [], xData: []
},
barWidth: '40%',
Max: 0
}
},
watch: {
data: {
handler(newValue, oldValue) {
const Data = { unused: [], used: [], xData: [] }
clearInterval(this.timer)
const TempData = JSON.parse(JSON.stringify(newValue))
// if (TempData.xData.length <= 5) {
// this.barWidth = this.fontSize(1.62)
// } else {
// this.barWidth = this.fontSize(0.81)
// }
Data.xData = TempData.xData
Data.used = TempData.used ? TempData.used : []
Data.unused = TempData.unused ? TempData.unused : []
if (Data.unused.length !== 0) { this.Max = Math.max(...Data.used) + Math.max(...Data.unused) } else { this.Max = Math.max(...Data.used) }
const num = this.digit(this.Max)
let number = this.Max.toString()[0]
number = parseFloat(number)
if (number < 9) {
number++
if (num <= 3) { this.Max = number + '00' } else if (num <= 4) { this.Max = number + '000' } else if (num <= 5) { this.Max = number + '0000' }
} else {
if (num <= 3) { this.Max = 1000 } else if (num <= 4) { this.Max = 10000 } else if (num <= 5) { this.Max = 100000 }
}
if (TempData.xData.length <= 5) {
this.Data = Data
this.drawLine()
} else {
this.Data.unused = Data.unused.slice(0, 5)
this.Data.used = Data.used.slice(0, 5)
this.Data.xData = Data.xData.slice(0, 5)
this.drawLine()
this.timer = setInterval(() => {
const unused = Data.unused.shift()
const used = Data.used.shift()
const xData = Data.xData.shift()
Data.unused.push(unused)
Data.used.push(used)
Data.xData.push(xData)
this.Data.unused = Data.unused.slice(0, 5)
this.Data.used = Data.used.slice(0, 5)
this.Data.xData = Data.xData.slice(0, 5)
this.drawLine()
}, 3000)
}
},
deep: true
}
},
mounted() {
// this.Data = {
// used: [1400, 700, 200, 800, 600], xData
// : ["", "", "", "GPU",""]
// }
this.$nextTick(() => {
this.drawLine()
})
},
destroyed() {
clearInterval(this.timer)
},
methods: {
fontSize(rem) {
const scale = window.innerHeight / 900
return scale >= 1 ? 16 * rem : 12 * rem
},
drawLine() {
const scaleRate = window.innerHeight / 900 >= 1
const chart = this.$echarts.init(this.$refs.echart)
var option
option = {
title: {
text: '',
textStyle: {
color: '#008B45'
},
padding: [10, 0, 0, 10] //
},
color: ['rgba(135, 189, 245, 1)', 'rgba(62, 223, 252, 1)', 'rgba(5, 155, 252, 1)'],
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'none',
show: false
},
backgroundColor: '#000033',
textStyle: { fontSize: this.fontSize(0.7), color: '#fff' },
borderWidth: 0
},
legend: {
right: '0',
itemWidth: 15,
selectedMode: false, //
textStyle: {
color: '#fff',
fontSize: this.fontSize(0.75),
fontFamily: 'Source Han Sans CN'
}
},
grid: {
right: '1%',
bottom: '20%',
top: scaleRate ? '15%' : '20%',
left: '15%'
},
xAxis: {
type: 'category',
data: this.Data.xData,
axisLine: {
lineStyle: {
color: 'rgba(135, 189, 245, 0.1)'
}
},
axisLabel: {
show: true,
interval: 0,
textStyle: {
fontSize: this.fontSize(0.75),
lineHeight: scaleRate ? 20 : 10,
color: 'rgba(221, 221, 221, 1)',
fontFamily: 'Source Han Sans CN'
},
margin: scaleRate ? (this.config.unit.length > 10 ? 35 : 8) : 10,
formatter: function(params) {
var provideNumber = 4 //
return params.slice(0, provideNumber) + (params.length > provideNumber ? '...' : '')
}
},
axisTick: {
// x
alignWithLabel: true
}
},
yAxis: {
type: 'value',
// offset: this.config.unit.length > 10 ? -40 : 0,
splitLine: {
show: true,
lineStyle: {
color: 'rgba(135, 189, 245, 0.1)'
}
},
name: this.config.unit,
nameTextStyle: {
color: '#aaa',
padding: [0, 10, 0, 0],
fontSize: this.fontSize(0.75),
nameLocation: 'start'
},
nameGap: 10,
data: [],
axisLine: {
lineStyle: {
color: 'rgba(135, 189, 245, 0.1)'
}
},
axisLabel: {
show: true,
textStyle: {
fontSize: this.fontSize(0.75),
color: 'rgba(221, 221, 221, 1)',
fontFamily: 'Source Han Sans CN'
}
},
scale: true,
min: 0,
max: 30000,
splitNumber: 3
},
series: [
{
name: this.config.status[0] ? this.config.status[0] : '',
type: 'bar',
stack: 'total',
barWidth: this.barWidth,
label: {
show: false
},
emphasis: {
focus: 'series'
},
data: this.Data.used ? this.Data.used : [],
itemStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: 'rgb(24, 144, 255)' // 0%
},
{
offset: 1,
color: 'rgba(24, 144, 255,0.5)' // 100%
}
],
global: false // false
}
}
},
{
name: this.config.status[1] ? this.config.status[1] : '',
type: 'bar',
stack: 'total',
barWidth: this.barWidth,
label: {
show: false
},
emphasis: {
focus: 'series'
},
data: this.Data.unused !== [] ? this.Data.unused : [],
itemStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: 'rgba(30, 231, 231,0.5)' // 0%
},
{
offset: 1,
color: 'rgb(30, 231, 231)' // 100%
}
],
global: false // false
}
}
}
],
animation: true,
animationDuration: function(idx) {
//
return idx * 100
},
animationEasing: 'backln'
}
chart.setOption(option)
window.addEventListener('resize', debounce(() => {
chart.resize()
}, 100))
},
digit(val) {
let num = Math.trunc(val)
// const number = num.toString() //
// var temp = num
var count = 0
if (num === 0) {
return 0
} else {
while (num !== 0) {
count++ //
num = parseInt(num / 10) // num 使
}
return count
}
}
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,154 @@
<template>
<div class="taskArea">
<el-row class="taskDiv">
<el-col v-for="(item,index) in taskDetail" :key="'task'+index" :span="8">
<div class="num">{{ item.num }}</div>
<div class="name">{{ item.name }}</div>
</el-col>
</el-row>
<dt-srcoll v-if="fresh" class="scrollList" :new-data="dutyRateData" :menu-data="menuData" :line-height="7" :is-again="true" :table-height="37" />
</div>
</template>
<script>
import DtSrcoll from '../components/scroll'
export default {
components: {
DtSrcoll
},
props: {
data: {
type: Object,
default: () => ({})
}
},
data() {
return {
taskDetail: [
{
name: '运行任务合计',
num: 0
},
{
name: '运行卡时数',
num: 0
},
{
name: '运行时长',
num: 0
}
],
menuData: [ //
{
name: '作业名称',
prop: 'name'
},
{
name: '作业状态',
prop: 'status'
},
{
name: '策略',
prop: 'strategy'
},
{
name: '协同状态',
prop: 'synergyStatus'
},
{
name: '承接方',
prop: 'serviceName'
}
],
dutyRateData: [],
fresh: false
}
},
watch: {
data: {
handler(newValue, oldValue) {
this.fresh = false
this.taskDetail[0].num = newValue.totalCount
this.taskDetail[1].num = newValue.cardTime
this.taskDetail[2].num = newValue.totalRunTime
this.dutyRateData = newValue.tableData.map(e => { e.strategy = '时间优先'; return e })
this.$nextTick(() => {
this.fresh = true
})
},
deep: true
}
}
}
</script>
<style lang="scss" scoped>
.taskArea{
height: 29vh;
}
.scrollList{
height: 32vh;
overflow: hidden;
}
.taskDiv{
display: flex;
justify-content: space-between;
text-align: center;
margin-bottom: 1%;
// height: calc(100% - 190px);
>div{
// width: 25%;
.num{
font-size: 1.5rem;
font-family: Impact;
color: #FFFFFF;
letter-spacing: 0.1rem;
// height: 3vh;
// line-height: 4vh;
height: 30%;
line-height: 200%;
}
.name{
font-size: 1rem;
letter-spacing: 0.1rem;
font-weight: bold;
height: 70%;
line-height: 300%;
background: url('../../../assets/images/monitorSelect/task.png') no-repeat center;
background-size: auto 100%;
}
}
}
::v-deep{
.el-table--mini th, .el-table--mini td{
// padding: 0.375rem 0;
height: 2vh;
padding: 0;
}
.el-table--mini th{
height: 4vh;
}
.el-table thead {
font-size: 1rem;
}
.el-table__body {
font-size: 0.9rem;
}
}
// @media screen and (min-width: 1921px) {
// .taskDiv{
// margin-bottom: 1%;
// >div{
// .num{
// font-size: 26px;
// }
// .name{
// font-size: 16px;
// height: 80px;
// line-height: 55px;
// }
// }
// }
// }
</style>

View File

@ -0,0 +1,232 @@
<!-- 计算资源负载 -->
<template>
<div id="myBarEchart" ref="myBarEchart" style="width: 100%; height: 80%" />
</template>
<script>
import * as echarts from 'echarts'
import { getTotalAverage } from '@/api/top-menu/TotalNum'
import moment from 'moment'
import { debounce } from '@/utils'
export default {
data() {
const day = [[], [], [], [], [], [], []]
for (let i = 0; i < 7; i++) {
day[i][0] = moment().subtract(7 - i, 'days').endOf('day').unix()
day[i][1] = moment().subtract(7 - i, 'days').endOf('day').format('MMDD')
}
return {
day,
cpuAverage: [], // cpu
ramAverage: [] //
}
},
computed: {
jcceTheme() {
return localStorage.getItem('jcceTheme')
}
},
mounted() {
this.getAllData()
},
methods: {
fontSize(rem) {
const scale = window.innerHeight / 900
return scale >= 1 ? 16 * rem : 12 * rem
},
//
async getAllData() {
await getTotalAverage().then(res => {
const data = res.data
// cpu (%)
const cpuData = data.find(item => item.metric_name === 'cpu_avg_usage').data.result[0].values || []
cpuData.forEach(element => {
this.cpuAverage.push((element[1] - 0).toFixed(2))
// this.date.push(moment(element[0] * 1000).format('MM/DD'))
})
this.cpuAverage = this.cpuAverage.slice(0, 7)
// (%)
const ramAverage = data.find(item => item.metric_name === 'mem_avg_usage').data.result[0].values || []
ramAverage.forEach(element => {
this.ramAverage.push(((element[1] - 0) / 1024 / 1024 / 1024).toFixed(2))
})
this.ramAverage = this.ramAverage.slice(0, 7)
})
this.initCharts()
},
// echart
initCharts() {
const scaleRate = window.innerHeight / 900 >= 1
const chart = echarts.init(this.$refs.myBarEchart)
//
const legend = ['CPU整体负载', '内存整体负载', 'CPU平均负载', '内存平均负载']
// const legend = ['CPU', '', 'CPU']
chart.setOption({
legend: {
right: '0',
itemWidth: 14,
data: legend,
itemHeight: scaleRate ? 10 : 2,
selectedMode: false, //
textStyle: {
color: '#FFFFFF',
fontSize: this.fontSize(0.7)
}
},
grid: {
right: '12%',
bottom: '16%',
top: scaleRate ? '25%' : '30%',
left: '12%'
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#000033'
}
},
backgroundColor: '#000033',
textStyle: { fontSize: this.fontSize(0.7), color: '#fff' },
borderWidth: 0,
formatter: (params) => {
let val = params[0].name
for (let i = 0; i < params.length; i++) {
const unit = params[i].seriesName.indexOf('CPU') > -1 ? '核' : 'GB'
val += '<br/>' + params[i].marker + (params[i].seriesName.indexOf('平均') > -1 ? '七日' : '') + params[i].seriesName + ' ' + params[i].value + unit
}
return val
}
},
xAxis: {
type: 'category',
data: this.day.map(n => n[1]),
axisTick: {
show: false
},
axisLabel: {
textStyle: {
fontSize: this.fontSize(0.75),
color: 'rgba(221, 221, 221, 1)'
},
interval: 0,
margin: scaleRate ? 14 : 10
},
axisLine: {
lineStyle: {
color: 'rgba(135, 189, 245, 0.01)'
}
}
},
yAxis: [
{
name: '单位:核',
nameTextStyle: {
color: '#aaa',
// padding: [0, 10, 0, 0],
fontSize: this.fontSize(0.75),
nameLocation: 'start'
},
axisLabel: {
textStyle: {
fontSize: this.fontSize(0.75),
color: 'rgba(221, 221, 221, 1)'
},
formatter: '{value}'
},
splitLine: {
lineStyle: {
color: 'rgba(135, 189, 245, 0.1)'
}},
axisLine: {
lineStyle: {
color: '#DDDDDD'
}
},
splitNumber: 3,
position: 'left',
alignTicks: true
},
{
name: '单位GB',
nameTextStyle: {
color: '#aaa',
// padding: [0, 10, 0, 0],
fontSize: this.fontSize(0.75),
nameLocation: 'start'
},
axisLabel: {
textStyle: {
fontSize: this.fontSize(0.75),
color: 'rgba(221, 221, 221, 1)'
},
formatter: '{value}'
},
position: 'right',
alignTicks: true,
splitLine: {
lineStyle: {
color: 'rgba(255,255,255,0.1)'
}},
splitNumber: 3,
axisLine: {
lineStyle: {
color: '#999999'
}
}
}
],
color: '#3282CE',
series: [
{
name: legend[2],
data: this.cpuAverage,
type: 'line',
showSymbol: true,
symbol: 'circle',
symbolSize: 8,
itemStyle: {
color: '#30BFB6',
shadowColor: '#30BFB6',
shadowBlur: 8
},
yAxisIndex: 0,
lineStyle: {
color: '#30BFB6', // 线
width: 1
},
smooth: true
},
{
name: legend[3],
data: this.ramAverage,
yAxisIndex: 1,
type: 'line',
showSymbol: true,
symbol: 'circle',
symbolSize: 8,
itemStyle: {
color: '#87BDF5',
shadowColor: '#87BDF5',
shadowBlur: 8
},
lineStyle: {
color: '#87BDF5',
width: 1
},
smooth: true
}
]
})
window.addEventListener('resize', debounce(() => {
chart.resize()
}, 100))
}
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,355 @@
<!-- 计算资源负载 -->
<template>
<div id="myBarEchart" ref="myBarEchart" style="width: 100%; height: 80%" />
</template>
<script>
import * as echarts from 'echarts'
import { getTotalAverage } from '@/api/top-menu/TotalNum'
import moment from 'moment'
import { debounce } from '@/utils'
export default {
data() {
const day = [[], [], [], [], [], [], []]
for (let i = 0; i < 7; i++) {
day[i][0] = moment().subtract(7 - i, 'days').endOf('day').unix()
day[i][1] = moment().subtract(7 - i, 'days').endOf('day').format('MM/DD')
}
return {
day,
ramLoad: [], //
cpuLoad: [], // CPU
cpuAverage: [], // cpu
ramAverage: [] //
}
},
computed: {
jcceTheme() {
return localStorage.getItem('jcceTheme')
}
},
mounted() {
this.getAllData()
},
methods: {
fontSize(rem) {
const scale = window.innerHeight / 900
return scale >= 1 ? 16 * rem : 12 * rem
},
//
async getAllData() {
await getTotalAverage().then(res => {
this.ramLoad = res.data.memoryLoad
this.ramAverage = res.data.memoryAvg
this.cpuLoad = res.data.cpuLoad
this.cpuAverage = res.data.cpuAvg
// const data = res.data
// // GB
// const ramData = data.find(item => item.metric_name === 'mem_total_usage').data.result[0].values || []
// ramData.forEach(element => {
// this.ramLoad.push(((element[1] - 0) / 1024 / 1024 / 1024).toFixed(2))
// // this.date.push(moment(element[0] * 1000).format('MM/DD'))
// })
// this.ramLoad = this.ramLoad.slice(0, 7)
// // CPU Core
// const cpuLoad = data.find(item => item.metric_name === 'cpu_total_usage').data.result[0].values || []
// cpuLoad.forEach(element => {
// this.cpuLoad.push(((element[1] - 0)).toFixed(2))
// })
// this.cpuLoad = this.cpuLoad.slice(0, 7)
// // cpu (%)
// const cpuData = data.find(item => item.metric_name === 'cpu_avg_usage').data.result[0].values || []
// cpuData.forEach(element => {
// this.cpuAverage.push((element[1] - 0).toFixed(2))
// // this.date.push(moment(element[0] * 1000).format('MM/DD'))
// })
// this.cpuAverage = this.cpuAverage.slice(0, 7)
// // (%)
// const ramAverage = data.find(item => item.metric_name === 'mem_avg_usage').data.result[0].values || []
// ramAverage.forEach(element => {
// this.ramAverage.push(((element[1] - 0) / 1024 / 1024 / 1024).toFixed(2))
// })
// this.ramAverage = this.ramAverage.slice(0, 7)
})
this.initCharts()
},
// echart
initCharts() {
const scaleRate = window.innerHeight / 900 >= 1
const chart = echarts.init(this.$refs.myBarEchart)
//
const legend = ['CPU整体负载', '内存整体负载', 'CPU平均负载', '内存平均负载']
// const legend = ['CPU', '', 'CPU']
chart.setOption({
legend: {
right: '0',
itemWidth: 14,
data: legend,
itemHeight: scaleRate ? 10 : 2,
selectedMode: false, //
textStyle: {
color: '#FFFFFF',
fontSize: this.fontSize(0.7)
}
},
grid: {
right: '12%',
bottom: '16%',
top: scaleRate ? '25%' : '30%',
left: '12%'
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#000033'
}
},
backgroundColor: '#000033',
textStyle: { fontSize: this.fontSize(0.7), color: '#fff' },
borderWidth: 0,
formatter: (params) => {
let val = params[0].name
for (let i = 0; i < params.length; i++) {
const unit = params[i].seriesName.indexOf('CPU') > -1 ? '核' : 'GB'
val += '<br/>' + params[i].marker + (params[i].seriesName.indexOf('平均') > -1 ? '七日' : '') + params[i].seriesName + ' ' + params[i].value + unit
}
return val
}
},
xAxis: {
type: 'category',
data: this.day.map(n => n[1]),
axisTick: {
show: false
},
axisLabel: {
textStyle: {
fontSize: this.fontSize(0.75),
color: 'rgba(221, 221, 221, 1)'
},
interval: 0,
margin: scaleRate ? 14 : 10
},
axisLine: {
lineStyle: {
color: 'rgba(135, 189, 245, 0.01)'
}
}
},
yAxis: [
{
name: '单位:核',
nameTextStyle: {
color: '#aaa',
// padding: [0, 10, 0, 0],
fontSize: this.fontSize(0.75),
nameLocation: 'start'
},
axisLabel: {
textStyle: {
fontSize: this.fontSize(0.75),
color: 'rgba(221, 221, 221, 1)'
},
formatter: '{value}'
},
splitLine: {
lineStyle: {
color: 'rgba(135, 189, 245, 0.1)'
}},
axisLine: {
lineStyle: {
color: '#DDDDDD'
}
},
splitNumber: 3,
position: 'left',
alignTicks: true
},
{
name: '单位GB',
nameTextStyle: {
color: '#aaa',
// padding: [0, 10, 0, 0],
fontSize: this.fontSize(0.75),
nameLocation: 'start'
},
axisLabel: {
textStyle: {
fontSize: this.fontSize(0.75),
color: 'rgba(221, 221, 221, 1)'
},
formatter: '{value}'
},
position: 'right',
alignTicks: true,
splitLine: {
lineStyle: {
color: 'rgba(255,255,255,0.1)'
}},
splitNumber: 3,
axisLine: {
lineStyle: {
color: '#999999'
}
}
}
],
color: '#3282CE',
series: [
{
name: legend[0],
type: 'pictorialBar',
symbolSize: [12, 3],
yAxisIndex: 0,
tooltip: {
show: false
},
symbolOffset: [-9, 3],
z: 12,
color: 'rgba(5, 155, 252, 0.8)',
data: this.cpuLoad
},
{
name: legend[0],
type: 'pictorialBar',
symbolSize: [16, 6],
yAxisIndex: 0,
tooltip: {
show: false
},
symbolOffset: [-9, 6],
z: 12,
color: 'rgba(5, 155, 252, 0.5)',
data: this.cpuLoad
},
{
name: legend[0],
type: 'pictorialBar',
symbolSize: [20, 9],
yAxisIndex: 0,
tooltip: {
show: false
},
symbolOffset: [-9, 9],
z: 12,
color: 'rgba(5, 155, 252, 0.25)',
data: this.cpuLoad
},
{
type: 'bar',
name: legend[0],
barWidth: '10',
yAxisIndex: 0,
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: 'rgba(5, 155, 252, 0)' }, { offset: 1, color: 'rgba(5, 155, 252, 1)' }])
}
},
data: this.cpuLoad
},
{
name: legend[1],
yAxisIndex: 1,
type: 'pictorialBar',
symbolSize: [12, 3],
tooltip: {
show: false
},
symbolOffset: [9, 3],
z: 12,
color: 'rgba(62, 223, 252, 1)',
data: this.ramLoad
},
{
name: legend[1],
yAxisIndex: 1,
type: 'pictorialBar',
symbolSize: [16, 6],
tooltip: {
show: false
},
symbolOffset: [9, 6],
z: 12,
color: 'rgba(62, 223, 252, 0.5)',
data: this.ramLoad
},
{
name: legend[1],
yAxisIndex: 1,
type: 'pictorialBar',
symbolSize: [20, 9],
tooltip: {
show: false
},
symbolOffset: [9, 9],
z: 12,
color: 'rgba(62, 223, 252, 0.25)',
data: this.ramLoad
},
{
type: 'bar',
name: legend[1],
barWidth: '10',
barGap: '80%',
yAxisIndex: 1,
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: 'rgba(5, 155, 252, 0)' }, { offset: 1, color: 'rgba(62, 223, 252, 1)' }])
}
},
data: this.ramLoad
},
{
name: legend[2],
data: this.cpuAverage,
type: 'line',
showSymbol: true,
symbol: 'circle',
symbolSize: 8,
itemStyle: {
color: '#30BFB6',
shadowColor: '#30BFB6',
shadowBlur: 8
},
yAxisIndex: 0,
lineStyle: {
color: '#30BFB6', // 线
width: 1
},
smooth: true
},
{
name: legend[3],
data: this.ramAverage,
yAxisIndex: 1,
type: 'line',
showSymbol: true,
symbol: 'circle',
symbolSize: 8,
itemStyle: {
color: '#87BDF5',
shadowColor: '#87BDF5',
shadowBlur: 8
},
lineStyle: {
color: '#87BDF5',
width: 1
},
smooth: true
}
]
})
window.addEventListener('resize', debounce(() => {
chart.resize()
}, 100))
}
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,131 @@
<template>
<!-- 存储资源用量 -->
<div>
<div class="unUse use">
<div class="data">
<p class="num">{{ storageData.storageUsing }}TB</p>
<p class="percent"> {{ Math.round(storageData.usingRate*10000) /100 }}%</p>
</div>
<span class="type">未使用 </span>
</div>
<div class="used use">
<span class="type"> 已使用 </span>
<div class="data">
<p class="num">{{ storageData.storageUsed }}TB</p>
<p class="percent"> {{ Math.round(storageData.usageRate*10000) /100 }}%</p>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
data: {
type: Object,
default: () => ({})
}
},
data() {
return {
storageData: {}
}
},
watch: {
data: {
handler(newValue, oldValue) {
this.storageData = newValue
},
deep: true
}
}
}
</script>
<style lang="scss" scoped>
.use{
height: 8.5vh;
font-size: 1rem;
font-weight: bold;
margin-top: 1vh;
position: relative;
.data {
width: calc(100% - 14.3vh);
background: url(../../../assets/monitor/g-2.png) no-repeat;
background-size: 100% 62%;
background-position: -1vh 1.3vh;
height: 90%;
position: absolute;
top: 0;
right: 0;
font-family: PangMenZhengDao;
font-weight: 400;
.num{
font-size: 1.875rem;
color: #FFFFFF;
line-height: 1.25rem;
padding-top: 0.6rem;
margin:0 12%;
text-align: right;
letter-spacing: 0.1rem;
}
.percent{
// float: left;
position: absolute;
left: 0;
top: 0;
line-height: 7.5vh;
letter-spacing: 0.1rem;
margin: 0;
text-indent: 1rem;
font-size: 1.2rem;
color: #3EDFFC;
}
// display: block;
}
.type {
display: block;
width: 14.3vh;
height: 100%;
position: absolute;
top: 0;
background: url(../../../assets/monitor/g-1.png) no-repeat;
background-size: auto 100%;
text-align: right;
line-height: 7.5vh;
// padding: 0 10px;
}
}
.unUsed{
.type{
left: 0;
}
}
.used{
position:relative;
.data{
left: 0;
-moz-transform: matrix(-1, 0, 0, 1, 0, 0);
-webkit-transform: matrix(-1, 0, 0, 1, 0, 0);
-o-transform: matrix(-1, 0, 0, 1, 0, 0);
z-index: -1;
.num, .percent{
-moz-transform: matrix(-1, 0, 0, 1, 0, 0);
-webkit-transform: matrix(-1, 0, 0, 1, 0, 0);
-o-transform: matrix(-1, 0, 0, 1, 0, 0);
z-index: -1;
}
.num{
text-align: left;
}
}
.type{
text-align: left;
position: absolute;
right: 0;
background-image: url(../../../assets/monitor/b-1.png);
}
}
</style>

View File

@ -0,0 +1,232 @@
<template>
<div>
<el-table id="dbM" :data="newData" border style="width: 100%" align="center" size="mini" class="customer-table">
<el-table-column :label="menuData[0].name" :prop="menuData[0].prop" min-width="70" :show-overflow-tooltip="true" />
<el-table-column :label="menuData[1].name" min-width="70" align="center">
<template slot-scope="scope">
<div v-if="scope.row.status=='Completed'" class="other">已完成</div>
<div v-if="scope.row.status=='Running'" class="running">运行中</div>
<div v-if="scope.row.status=='Submitted'" class="other">已提交</div>
<div v-if="scope.row.status=='Saved'" class="other">已保存</div>
<div v-if="scope.row.status=='Failed'" class="pending">失败</div>
</template>
</el-table-column>
<el-table-column :label="menuData[2].name" :prop="menuData[2].prop" min-width="50" align="left" :show-overflow-tooltip="true" />
<el-table-column :label="menuData[3].name" :prop="menuData[3].prop" min-width="70" align="left" :show-overflow-tooltip="true" />
<el-table-column :label="menuData[4].name" :prop="menuData[4].prop" min-width="70" align="left" :show-overflow-tooltip="true" />
<slot name="footerTable" />
</el-table>
</div>
</template>
<script>
export default {
name: 'DtSrcoll',
props: {
newData: {
type: Array, //
default: () => []
},
menuData: {
type: Array,
default: () => []
}, //
lineHeight: { //
type: Number,
default: 4
},
rowTime: { //
type: Number,
default: 2000
},
duration: { //
type: Number,
default: 500
},
tableHeight: { //
type: Number,
default: 33
},
isClear: { //
type: Boolean,
default: false
},
isAgain: { //
type: Boolean,
default: false
},
isScroll: { //
type: Boolean,
default: true
}
},
data() {
return {
active: 0,
timer: ''
}
},
watch: {
newData: {
handler(newValue, oldValue) {
this.newData = newValue
},
deep: true
}
},
mounted() {
console.log(this.lineHeight)
const _this = this
this.$nextTick(() => {
const vh = window.innerHeight / 100
const elwrapper = document.getElementsByClassName('el-table__body-wrapper')[0]
elwrapper.style.height = this.lineHeight * 3.95 * 2 + 'vh'
const elBody = document.getElementsByClassName('el-table__body')[0]
const elRow = document.getElementsByClassName('el-table__row')
for (const node of elRow) {
node.style.height = '3.95vh'
}
elBody.style.top = 0
elBody.style.transactionDuration = this.duration + 'ms'
if (_this.isScroll) {
_this.timer = setInterval(() => {
if (_this.active < parseInt(_this.newData.length) - parseInt(_this.lineHeight)) {
_this.active += 1
elBody.style.top = parseInt(elBody.style.top) - parseInt(vh * 4) + 'px'
} else {
if (this.isClear) {
clearInterval(this.timer)
}
if (_this.isAgain) {
_this.active = 0
elBody.style.top = 0
} else {
clearInterval(_this.timer)
}
}
}, _this.rowTime)
}
})
},
destroyed() {
clearInterval(this.timer)
}
}
</script>
<style lang="scss" scoped>
::v-deep{
.el-table__body {
position: absolute;
transition: all 500ms linear;
background-color: transparent !important;
color: #fff;
font-size: 0.9rem;
overflow: hidden;
}
.el-table,
.el-table__expanded-cell {
color: #fff;
background-color: transparent !important;
}
.el-table th,
.el-table tr,
.el-table td {
color: #fff;
background-color: transparent !important;
}
.el-table .cell{
line-height: 3.95vh;
}
.el-table tr:nth-child(even) td{
background: rgba(35,185,255,0.06) !important;
}
.el-table--border,
.el-table--group {
border: 0px;
}
.el-table td.el-table__cell,
.el-table th.el-table__cell.is-leaf {
background-color: transparent !important;
border: 0px solid transparent !important;
}
.el-table--border,
.el-table--group {
border: 0px solid transparent !important;
}
.customer-table {
text-align: center !important;
}
.el-table__footer-wrapper,
.el-table__header-wrapper {
font-size: 0.9rem;
background: rgba(35,185,255,0.12);
}
.el-table--scrollable-x .el-table__body-wrapper {
overflow: hidden;
}
/* 去掉表格单元格边框 */
.customer-table th {
border: none;
}
.customer-table td,
.customer-table th.is-leaf {
border: none;
}
/* 表格最外边框 */
.el-table--border,
.el-table--group {
border: none;
}
/* 头部边框 */
.customer-table thead tr th.is-leaf {
border: 0px solid #EBEEF5;
border-right: none;
}
.customer-table thead tr th:nth-last-of-type(2) {
border-right: 0px solid #EBEEF5;
}
/* 表格最外层边框-底部边框 */
.el-table--border::after,
.el-table--group::after {
width: 0;
}
.customer-table::before {
width: 0;
}
.customer-table .el-table__fixed-right::before,
.el-table__fixed::before {
width: 0;
}
/* 表格有滚动时表格头边框 */
.el-table--border th.gutter:last-of-type {
border: 1px solid #EBEEF5;
border-left: none;
}
.pending, .other, .running {
width: 3.625rem;
height: 1.3rem;
line-height: 1.2rem;
background: linear-gradient(90deg, #0BBAFB 0%, #4285EC 100%);
border-radius: 1rem;
}
}
</style>

View File

@ -0,0 +1,826 @@
<template>
<div>
<div class="monitor">
<div class="top-menu">
<div class="menu">
<a href="">首页</a>
<!-- <a @click="viewMenu()">数算资源</a> -->
</div>
<!-- <div class="right">
<a @click="viewMenu('hpc/hpcOverview')">超算资源</a>
<a @click="toMonitor()">监控运维</a>
</div> -->
</div>
<div class="top">
<div class="top-title">
<h1>算网融合智能协同平台</h1>
</div>
</div>
<div class="floatLeft">
<div class="left">
<div class="left_1">
<div class="title"><p>计算域信息</p></div>
<ComputeDomain />
</div>
<div class="left_2">
<div class="title"><p>云际组件状态</p></div>
<el-row class="taskDiv">
<el-col v-for="(item,index) in taskDetail" :key="'task'+index" :span="12">
<div class="num">{{ item.num }}</div>
<div class="name">{{ item.name }}</div>
</el-col>
</el-row>
<!-- <ComputingPowerTrend id="ComputingPowerTrend" :data="tendData" :config="tendConfig" /> -->
</div>
<div class="left_3">
<div class="title"><p>存储资源用量</p></div>
<StorageResourceUsage :data="powerData" />
<!-- <ComputingPowerUse id="ComputingPowerUse" :data="centerData" :config="statusConfig" /> -->
</div>
<!-- <div class="left_4">
<div class="title"><p>分布记账</p></div>
<ChainLink :key="resizeKey" />
</div> -->
</div>
</div>
<div class="floatRight">
<div class="right">
<div class="right_1">
<div class="title"> <el-button class="createBtn" type="primary" size="mini" round @click="toHashCat()"><div>典型应用验证</div></el-button><p></p></div>
<CumulativeTasks :data="taskData" />
</div>
<div class="right_2">
<div class="title"><p>计算资源整体负载</p></div>
<ResourceLoadWhole />
</div>
<!-- <div class="right_3">
<div class="title"><p>计算资源平均负载</p></div>
<ResourceLoadAverage />
</div> -->
</div>
</div>
<div class="middle">
<ComputingPowerTotal />
</div>
<Earth :key="resizeKey" :center="{name: monitorSettingForm.center, longitude: Number(monitorSettingForm.centerPosition.split(',')[0]), latitude: Number(monitorSettingForm.centerPosition.split(',')[1])}" />
</div>
<el-dialog
title="创建云际跨域任务"
:visible.sync="dialogVisible"
width="30%"
>
<el-upload
action="#"
:http-request="httpRequest"
:limit="1"
:on-remove="handleRemove"
:file-list="fileList"
>
<el-button size="small" type="primary">点击选择yaml文件</el-button>
</el-upload>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="submitFile()"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import moment from 'moment'
import ComputeDomain from './components/ComputeDomain.vue'
import ComputingPowerTotal from './components/ComputingPowerTotal.vue'
import ResourceLoadWhole from './components/ResourceLoadWhole.vue'
import CumulativeTasks from './components/CumulativeTasks.vue'
import StorageResourceUsage from './components/StorageResourceUsage.vue'
import Earth from '@/views/prometheusMonitor/earthDev'
import { getComputePower, getScreenInfo, getCPUsage } from '@/api/container/monitorSelect.js'
import { getTaskCount, createScheduleTask } from '@/api/top-menu/TotalNum'
import { order } from '@/utils/data-process'
import { getMonitorSetting } from '@/api/container/monitorSelect'
import { debounce } from '@/utils'
export default {
components: { ComputeDomain, ComputingPowerTotal, ResourceLoadWhole, CumulativeTasks, StorageResourceUsage, Earth },
data() {
return {
monitorSettingForm: {
'title': '广域协同智能计算系统面板',
'titleColor': '#409EFF',
'mainColor': '',
'mainColor2': '',
'textColor': '',
'backgroundColor': '',
'center': '',
'centerPosition': '',
'provinceBgColor': ''
},
taskDetail: [
{
name: 'API每秒请求数 times/s',
num: 119.083
},
{
name: 'API请求延迟 ms',
num: 2.71
},
{
name: '调度器 调度次数',
num: 5
},
{
name: '调度失败的 容器节点',
num: 1
}
],
resizeKey: 0,
dialogVisible: false,
rs: new FormData(),
fileList: [],
powerData: {},
pageSize: 100,
taskData: {},
currentDate: '',
tendData: { used: [], xData: [] },
centerData: { used: [], xData: [] },
tendConfig: { unit: '单位: 卡时', status: ['使用量'] },
statusConfig: { unit: '单位: 卡时', status: ['使用量'] },
tabLightList: [
{
id: 'cluster',
title: '容器管理',
icon: 'rongqiguanli',
path: '/cluster/clusterMapViews'
},
{
id: 'virtual',
title: '虚拟机管理',
icon: 'xunijiguanlimokuai',
path: '/virtual/overview'
},
{
id: 'jccSchedule',
title: '调度中心',
icon: 'yunweijiankongmokuai',
path: '/jccSchedule/resourceLogicView'
},
{
id: 'disk',
title: '云际存储',
icon: 'xunijiguanli-juan',
path: '/disk'
},
{
id: 'functions',
title: '函数管理',
icon: 'fuwu',
path: '/functions/overview'
},
{
id: 'blockChain',
title: '云际记账',
icon: 'yunjijizhang',
path: '/blockChain/blockChainBrowser'
},
{
id: 'hpc',
title: '超算管理',
icon: 'fuwu',
path: '/hpc/hpcOverview'
},
{
id: 'hpc',
title: '智算管理',
icon: 'fuwu',
description: '智算管理描述',
path: '/modelarts/overview'
}
]
}
},
computed: {
jcceTheme() {
return localStorage.getItem('jcceTheme')
},
filteredLightTab() {
return this.tabLightList.filter(e => this.menus.includes(e.id))
}
},
created() {
getMonitorSetting().then(e => {
this.monitorSettingForm = e.data
})
this.getTend()
this.getAccrueCenter()
this.getTrainJob()
this.resize()
window.addEventListener('resize', debounce(() => {
this.resizeKey++
}, 100))
},
mounted() {
this.getPower()
// this.scaleListener()
},
methods: {
getPower() {
getScreenInfo().then((res) => {
this.powerData = res.data
})
},
toMonitor() {
window.open('http://192.168.19.164:8181/#/taskList')
},
toHashCat() {
window.open('https://dev.jointcloud.net/hashcat/')
},
handleRemove() {
this.rs.delete('file')
},
httpRequest(data) {
const isJar = data.file.name.indexOf('.yaml') === (data.file.name.length - 5)
if (!isJar) {
this.$message.warning('上传文件只能是 yaml 格式!')
} else {
this.rs.set('file', data.file)
}
},
submitFile() {
if (!this.rs.has('file')) {
this.$message.warning('请上传yaml文件')
return false
} else {
createScheduleTask(this.rs).then(res => {
if (res.code === 200) {
this.$message.success('操作成功')
this.dialogVisible = false
this.getTrainJob()
}
})
}
},
viewMenu(path) {
path ? this.$store.dispatch('user/setRouteType', path.split('/')[0]) : {}
this.$router.push({ path: path || `/monitorSelectBk` })
},
// scaleListener() {
// window.addEventListener('resize', this.resize())
// },
resize() {
// 1080
const scale = window.innerHeight / 900
if (scale >= 1) {
document.documentElement.style.fontSize = `${16 * scale}px`
} else {
document.documentElement.style.fontSize = `${14 * scale}px`
}
},
getCurrentDate() {
const date = moment().format('yyyy年MM月DD日')
const week = moment().format('E')
switch (week) {
case '1':
this.currentDate = date + ' ' + '星期一'
break
case '2':
this.currentDate = date + ' ' + '星期二'
break
case '3':
this.currentDate = date + ' ' + '星期三'
break
case '4':
this.currentDate = date + ' ' + '星期四'
break
case '5':
this.currentDate = date + ' ' + '星期五'
break
case '6':
this.currentDate = date + ' ' + '星期六'
break
case '0':
this.currentDate = date + ' ' + '星期日'
break
}
},
// changePage(type) {
// if (type === 'left') {
// //
// } else {
// //
// }
// },
getImg(src) {
const srcName = src === 'disk' || src === 'jccSchedule' ? 'blockChain' : src
return require('@/assets/img/' + srcName + '.png')
},
selectMonitor(monitor) {
if (monitor === '/disk') {
if (this.name === 'admin') {
window.location.href = '/disk/storage/sourceSetting'
} else {
window.location.href = '/disk/storage/diskList'
}
}
this.$store.dispatch('user/setRouteType', monitor.split('/')[1])
this.$router.push({ path: monitor })
},
getTend() {
getComputePower().then((res) => {
this.tendData = { used: [], xData: [] }
if (res.dailyComputerPowers !== null) {
const timeArr = []// 12
for (let i = 0; i < 180; i++) {
timeArr.push(
`${moment(new Date()).subtract(i, 'days').format('YYYY-MM-DD')}`
)
}
timeArr.reverse()//
const arr = [] //
for (let i = 0; i < timeArr.length; i++) {
arr.push({ date: timeArr[i], computerPower: 0 })
// arr
for (let j = 0; j < res.dailyComputerPowers.length; j++) {
if (res.dailyComputerPowers[j].date === timeArr[i]) {
arr[i] = { date: res.dailyComputerPowers[j].date, computerPower: res.dailyComputerPowers[j].computerPower }
}
}
}
arr.forEach((item) => {
this.tendData.used.push(item.computerPower.toFixed(1))
this.tendData.xData.push(item.date)
})
}
})
},
getTaskTotal() {
// getAccrueCenter().then((res) => {
// if (res.perCenterComputerPowers) {
// const data = res.accOtJobInfo
// this.accrueData = {
// config1: data.accCardRunSec,
// config2: data.accOtJobNum,
// config3: data.accRunSec
// }
// }
// })
},
getAccrueCenter() {
getCPUsage().then((res) => {
this.centerData = { used: [], xData: [] }
if (res.perCenterComputerPowers) {
const data = res.accOtJobInfo
this.accrueData = {
config1: data.accCardRunSec,
config2: data.accOtJobNum,
config3: data.accRunSec
}
const data1 = res.perCenterComputerPowers.filter(item => {
if (item.computerPower !== 0) {
return item
}
})
// this.timer = setInterval(() => {
// this.getTaskTotal()
// }, 1000)
data1.sort(order)
data1.forEach((item) => {
if (item.computerPower !== 0) {
this.centerData.used.push(item.computerPower.toFixed(1))
this.centerData.xData.push(item.centerName)
}
})
}
})
},
getTrainJob() {
getTaskCount().then(e => {
this.taskData = {
tableData: [],
totalCount: e.data?.allJobCount || 0,
cardTime: e.data?.allCardRunTime || 0,
totalRunTime: e.data?.allJobRunTime || 0
}
e.data?.trainJobs?.forEach((item) => {
this.taskData.tableData.push({
name: item.name,
status: item.status,
strategy: item.strategy,
serviceName: item.serviceName,
synergyStatus: item.synergyStatus
// undertaker: this.showUnderTaker(item)
})
})
})
},
showUnderTaker(item) {
if (item.tasks == null) {
return ''
} else if (item.tasks.length > 2) {
return item.tasks[0].centerName[0] + '等'
} else {
if (item.tasks[0].centerName == null) {
return ''
} else {
return item.tasks[0].centerName[0]
}
}
}
}
}
</script>
<style lang="scss" scoped>
@import "~@/styles/variables.scss";
::v-deep {
.el-dialog {
background: #2c3a4e !important;
color: white;
}
.el-upload-list__item-name {
color: #ffffff;
}
.el-upload-list__item:hover {
background-color: rgb(86, 90, 95)
}
.el-button--default {
color: white;
background: rgba(255,255,255,0.1);
border-color: rgba(255,255,255,0.01);
}
.el-dialog__title {
color: white;
}
}
.monitor {
background: url('../../assets/monitor/monitor_bg.jpeg') no-repeat;
background-size: 100% 100%;
width: 100%;
min-width: 1200px;
height: 100vh;
min-height: 900px;
overflow: hidden;
color: white;
font-size: 0.8rem;
font-family: Source Han Sans CN;
font-weight: 400;
display: block;
overflow: hidden;
.top {
width: 100%;
height: 8vh;
// vertical-align: baseline;
position: absolute;
z-index: 99;
background: url(../../assets/monitor/top-bg.png) center top no-repeat;
background-size: 100% 65%;
.top-title{
margin:0 auto;
// font-weight: bold;
// font-family: PangMenZhengDao;
// float: left;
// padding: 1rem 8rem;
// padding-right: 0;
height: 100%;
background: url(../../assets/monitor/c-top.png) center no-repeat;
background-size: 55% 10vh;
h1{
margin: 0;
font-size: 2rem;
line-height: 6vh;
letter-spacing: 0.3rem;
text-align: center;
text-shadow: 3px 5px 0px rgba(17,20,22,0.22);
background: linear-gradient(0deg, rgba(36,83,152,0.35) 0%, rgba(255,255,255,0.35) 100%);
background-clip: text;
-webkit-text-fill-color: #ffffff;
// background: linear-gradient(0deg, rgba(36,83,152,0.35) 0%, rgba(255,255,255,0.35) 100%);
// -webkit-background-clip: text;
// -webkit-text-fill-color: transparent;
}
// box-shadow: 0px 20px 10px 0px #02020a96;
}
}
.top-menu{
width: 100%;
position: absolute;
z-index: 100;
.menu a, .right a {
float: left;
font-size: 1.13rem;
display: block;
padding: 0.9rem 60px;
height: 3.5rem;
letter-spacing: 0.2rem;
}
.menu a, .right a{
&:hover{
background: url(../../assets/monitor/t-p.png) center no-repeat;
background-size: auto 70%;
}
}
.menu a:first-child{
background: url(../../assets/monitor/t-p.png) center no-repeat;
background-size: auto 70%;
}
.right {
a { float: right;}
// float: right;
}
}
.title{
background: url('../../assets/monitor/title-bg.png') no-repeat left;
background-size: 105% 100%;
background-position: -3.5vh;
height: 4.5vh;
p{
font-size: 1.4rem;
height: 2.8rem;
line-height: 2.3rem;
text-indent: 2.8vw;
margin: 0;
font-family: Source Han Sans CN;
font-weight: bold;
color: #FFFFFF;
letter-spacing: 0.2rem;
text-shadow: 0px 2px 8px rgba(5,28,55,0.42);
background: linear-gradient(0deg, rgba(14,197,236,1) 0%, rgba(49,190,255,1) 0%, rgba(239,252,254,1) 58.7646484375%);
background-clip: text;
-webkit-text-fill-color: transparent;
}
}
.floatLeft, .floatRight{
margin-top: 5vh;
}
.middle{
width: 38vw;
position: absolute;
left: 31vw;
z-index: 99;
margin-top: 10vh;
}
.floatLeft, .floatRight{
padding: 0 1vh 0 2vh;
padding-top: 5vh;
padding-bottom: 4vh;
}
.floatLeft .left::before, .floatRight .right::after{
// margin-top: 6vh;
content: '';
width: 27vw;
height: 95vh;
display:block;
position: absolute;
top: -5.2vh;
right: -2vh;
background: url(../../assets/monitor/left.png) no-repeat;
background-size: 100% 98%;
z-index: -1;
}
.floatLeft .left:after, .floatRight .right:before{
content: '';
width: 2vw;
height: 85vh;
position: absolute;
right: -3.5vw;
top: 3px;
display: block;
background: url(../../assets/monitor/leftr.png) no-repeat;
background-size: 100% 98%;
}
.floatRight .right:before{
left: -3.5vw;
-moz-transform: matrix(-1, 0, 0, 1, 0, 0);
-webkit-transform: matrix(-1, 0, 0, 1, 0, 0);
-o-transform:matrix(-1,0,0,1,0,0);
}
.floatLeft{
// background: #02020a96;
// box-shadow: 20px -30px 30px 0px #02020a96;
width: 27vw;
display: block;
// overflow: hidden;
position: absolute;
left: 0;
z-index: 10;
height: 95vh;
min-height: 800px;
.left {
width: 100%;
height: 90vh;
padding-left: 10px;
display: block;
position: relative;
&:before{
left: -2vh;
}
.left_1{
height: 32vh;
overflow: hidden;
}
.left_2 {
height: 30vh;
.taskDiv{
// display: flex;
// justify-content: space-between;
text-align: center;
margin-bottom: 1%;
// height: calc(100% - 190px);
>div{
background: url('../../assets/images/monitorSelect/data-bg.png') no-repeat center;
background-size: auto 100%;
height: 11vh;
margin-top: 2vh;
// width: 25%;
.num{
font-size: 1.5rem;
font-family: Impact;
color: #FFFFFF;
letter-spacing: 0.1rem;
font-family: PangMenZhengDao;
// height: 3vh;
// line-height: 4vh;
height: 3vh;
line-height: 2rem;
margin-bottom: 1vh;
}
.name{
font-size: 0.8rem;
letter-spacing: 0.1rem;
width: 60%;
margin: auto;
// font-weight: bold;
height: 70%;
// line-height: 300%;
}
}
}
}
.left_3 {
width: 100%;
height: 15vh;
}
// .left_4{
// height: 12vh;
// }
}
}
.floatRight {
// background: #02020a96;
// box-shadow: -20px -30px 30px 0px #02020a96;
background: none;
width: 27vw;
display: block;
// overflow: hidden;
position: absolute;
right: 0;
z-index: 10;
height: 95vh;
min-height: 800px;
padding: 0 2vh 0 1vh;
padding-top: 5vh;
padding-bottom: 4vh;
.createBtn{
height: 2.5vh;
line-height: 2.3vh;
margin: 0;
padding: 0 1rem;
position: absolute;
top: 0.5vh;
right: 2vh;
div{
font-size: 0.9rem;
@media screen and (max-height: 900px) {
transform: scale(0.8);
// transform-origin: 0;
}
}
}
.right {
width: 100%;
height: 100%;
padding-right: 10px;
display: block;
position: relative;
&:after{
// padding: 0 20px 0 10px;
-moz-transform: matrix(-1, 0, 0, 1, 0, 0);
-webkit-transform: matrix(-1, 0, 0, 1, 0, 0);
-o-transform:matrix(-1,0,0,1,0,0);
z-index: -1;
// padding-top: 50px;
// padding-bottom: 40px;
}
.right_1{
height: 50vh;
overflow: hidden;
}
.right_2{
// height: 31%;
height: 40vh;
}
.right_3{
height: 21vh;
// height: 27%;
}
}
}
// .fixedBottom {
// width:50vw;
// bottom: 0;
// display: block;
// position: absolute;
// z-index: 10;
// height: 13vh;
// left: 25vw;
// .el-row{position:relative; height: 100%}
// .lightLeft{
// font-size: 30px;
// position: absolute;
// left: -20px;
// top: 3vh;
// z-index: 10;
// color: #DDD;
// }
// .lightRight{
// font-size: 30px;
// position: absolute;
// right: -20px;
// top: 3vh;
// z-index: 10;
// color: #DDD;
// }
// // displayflex
// .div-block{
// display: flex;
// width: 100%;
// height: 100%;
// overflow: hidden;
// .monitorSelectDiv{
// display: block;
// height: 100%;
// width: 8.33vw;
// }
// > div{
// display: block;
// width: 100%;
// max-width: 8.5vw;
// font-size: 20px;
// color: #ffffff;
// height: 100vh;
// position: relative;
// text-align: center;
// &:hover{
// color: #3182CE;
// }
// .svg-icon {
// font-size: 80px;
// margin: 0 auto;
// }
// .selectTitle {
// margin-bottom: 24px;
// font-size: 16px;
// }
// span{
// display: block;
// padding: 0 100px;
// font-size: 14px;
// line-height: 24px;
// }
// }
// }
// }
}
// @media screen and (min-width: 1921px) {
// .monitor {
// font-size: 16px;
// .top {
// .top-title {
// font-size: 32px;
// padding: 10px 100px;
// img{
// top: 35px;
// }
// }
// }
// .title{
// font-size: 20px;
// height: 70px;
// }
// .middle, .floatLeft, .floatRight{
// margin-top: 110px;
// }
// }
// }
</style>
<style lang="less" rel="stylesheet/less">
@import "../../common/font/font.css";
</style>

View File

@ -2,7 +2,7 @@
<!-- 算力中心总数 -->
<div>
<div class="two">
<div v-for="(item, index) in dataArray" :key="'data'+index">
<div v-for="(item, index) in dataArray" :key="'data'+index" style="cursor: pointer;" @click="item.path && viewMenu(item.path)">
<p class="title">{{ item.name }}</p>
<div class="num">{{ item.value }}</div>
</div>
@ -23,11 +23,13 @@ export default {
dataArray: [
{
name: '算力中心总数(计算域)',
value: '-'
value: '-',
path: 'resourceList'
},
{
name: '已接入算力 POps@FP16',
value: '-'
value: '-',
path: 'resourceList'
},
{
name: '接入集群数',
@ -47,7 +49,10 @@ export default {
}
},
methods: {
viewMenu(path) {
path ? this.$store.dispatch('user/setRouteType', path.split('/')[0]) : {}
this.$router.push({ path: path || `/monitorSelectBk` })
}
}
}

View File

@ -0,0 +1,198 @@
<template>
<transition name="el-zoom-in-center">
<div class="transition-box province">
<province v-model="third" :map-type="9" :cluster="provinceClusters" @selectedCity="selectCity" />
</div>
</transition>
</template>
<script>
import province from './provinceDev.vue'
import dataCenter from './dataCenter'
export default {
components: { province },
props: {
center: {
type: Object,
default: () => {
return {
name: '鹏城云脑',
longitude: 114.057868,
latitude: 22.543099
}
}
}
},
data() {
return {
dataCenter,
loading: true,
provinceType: 5,
third: false,
provinceClusters: [],
mapCount: {},
selectCity: ''
}
},
mounted() {
this.provinceClusters = dataCenter.centerList
this.third = true
},
beforeDestroy() {
},
methods: {}
}
</script>
<style lang="scss" scoped>
.loading {
width: 100vw;
height: 100vh;
display: block;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: rgba(#071b45, 0.8);
}
.circle-breath {
background: #3EDFFC;
box-shadow: 0 0 0 0 rgb(250, 249, 250);
height: 10vh;
width: 10vh;
margin: 40vh auto;
// display: block;
border-radius: 50%;
animation: donghua 2.4s infinite;
.loadingGlobe{
font-size: 10vh;
animation: zhuan 3s linear infinite;
}
}
@keyframes zhuan {
0% {transform: rotateZ(0deg)}
25% {transform: rotateZ(90deg)}
50% {
transform: rotateZ(180deg)
}
75% {
transform: rotateZ(270deg)
}
100% {
transform: rotateZ(360deg)
}
}
@keyframes donghua {
0% {
transform: scale(0.60);
/* 注意rgba中的a的设置 */
box-shadow: 0 0 0 0 rgba(73, 171, 204, 0.6);
}
60% {
transform: scale(1);
box-shadow: 0 0 0 36px rgba(73, 182, 204, 0);
}
100% {
transform: scale(0.60);
box-shadow: 0 0 0 0 rgba(73, 167, 204, 0);
}
}
.province{
width: 100%;
height: 100%;
display: block;
position: absolute;
overflow: hidden;
top: 0;
left: 0;
background: url('../../assets/monitor/province-bg.png') center no-repeat;
background-size: 100% 100%;
}
.switchBtn {
font-size: 2.5rem;
position: absolute;
bottom: 6.5vh;
right: 30vw;
z-index: 100;
color: #fff;
}
.toChina{
bottom: 2.3vh;
}
.activeBtn{
color: #3EDFFC
}
.chinaDetail{
position:absolute;
bottom: 80px;
right: 28vw;
z-index: 100;
width: 140px;
.el-button,.el-button + .el-button{
margin: 0;
margin-bottom: 5px;
padding: 5px 15px;
width: 100%;
background-color: #b3afaf33;
color: #fff;
border-radius: 0;
text-align: left;
border: 0;
line-height: 2rem;
.svg-icon{
font-size: 1.4rem;
margin-right: 0.6rem;
}
}
.svg-icon{
font-size: 2rem;
margin-right: 0.6rem;
}
.active{
background-color: #ffffff6b!important;
}
}
.provinceDetail{
position:absolute;
bottom: 90px;
left: 30vw;
z-index: 100;
width: 400px;
height: auto;
// background-color: #cbdae51a;
}
.switchDataBtn{
position: absolute;
bottom: 3vh;
right: 35vw;
.el-button,.el-button + .el-button{
width: 10vw;
margin-bottom: 5px;
padding: 5px 15px;
// width: 100%;
// background-color: #24253a;
background-image: url('../../assets/images/monitorSelect/btn.png');
background-repeat: no-repeat;
background-size: 100% 100%;
border-radius: 0;
font-size: 1.2rem;
font-family: Source Han Sans CN;
font-weight: bold;
letter-spacing: 0.2rem;
// text-align: left;
border: 0;
line-height: 3rem;
}
.el-button--default{
color: #91d4fe;
}
.active{
color: #ffffff;
background-image: url('../../assets/images/monitorSelect/btn-p.png')!important;
}
}
</style>

View File

@ -0,0 +1,552 @@
<template>
<div>
<div class="top">
<div class="canvasBox">
<canvas id="container" />
</div>
</div>
<div class="spin">
<div class="circle circle1">
<div class="turnAround" />
</div>
<div class="circle circle2">
<div class="turnAround" />
</div>
<div class="circle circle3">
<div class="turnAround" />
</div>
</div>
</div>
</template>
<script>
import guangdongJson from './geoJson/guangdong.json'
import guangdongOutline from './geoJson/guangdongOutline.json'
import chuanyuJson from './geoJson/chuanyu.json'
import gansuJson from './geoJson/gansu.json'
import guizhouJson from './geoJson/guizhou.json'
import jingjinjiJson from './geoJson/jingjinji.json'
import neimengguJson from './geoJson/neimenggu.json'
import ningxiaJson from './geoJson/ningxia.json'
import changsanjiaoJson from './geoJson/changsanjiao.json'
import hunanJson from './geoJson/hunan.json'
import hunanOutline from './geoJson/hunanOutline.json'
export default {
props: {
value: {
type: Boolean,
default: false
},
mapType: {
type: Number,
default: 1
},
// count: {
// type: Object,
// default: () => { return { ys: 0, zs: 0, cs: 0 } }
// },
cluster: {
type: Array,
default: () => []
}
},
data() {
return {
selectedCity: '',
allJSON: {
guangdongJson,
chuanyuJson,
gansuJson,
guizhouJson, jingjinjiJson, neimengguJson, ningxiaJson, changsanjiaoJson,
guangdongOutline, hunanJson, hunanOutline
},
currentIndex: 0,
interval: undefined,
img: undefined,
activeTab: '',
scale: 1,
geoCenter: {},
offsetX: 0,
offsetY: 0,
eventType: '',
cursorFlag: false,
mapMap: {
1: 'ningxia',
2: 'neimenggu',
3: 'gansu',
4: 'guizhou',
5: 'guangdong',
6: 'chuanyu',
7: 'changsanjiao',
8: 'jingjinji',
9: 'hunan'
},
mapName: {
1: '宁夏回族自治区',
2: '内蒙古自治区',
3: '甘肃省',
4: '贵州省',
5: '粤港澳大湾区',
6: '川渝地区',
7: '长三角地区',
8: '京津冀地区',
9: '湖南省'
}
// geoCenterY: 0
}
},
computed: {
dialogVisible: {
get() {
return this.value
},
set(value) {
this.$emit('input', value)
}
}
},
watch: {
mapType(val) {
if (val) {
this.getBoxArea()
this.drawMap()
}
}
},
mounted() {
this.getBoxArea()
this.$nextTick(() => {
this.img = new Image()
this.img.src = process.env.VUE_APP_PUBLIC_SOURCE_API + '/click-point.svg'
this.img.addEventListener('load', () => {
this.setDataRoll()
})
const canvas = document.querySelector('#container')
//
canvas.addEventListener('mousemove', (event) => {
this.offsetX = event.offsetX / 0.55
this.offsetY = event.offsetY / 0.65
this.eventType = 'mousemove'
this.drawMap()
})
//
canvas.addEventListener('click', (event) => {
this.offsetX = event.offsetX / 0.55
this.offsetY = event.offsetY / 0.65
this.eventType = 'click'
clearInterval(this.interval)
this.drawMap()
})
})
},
methods: {
setDataRoll() {
clearInterval(this.interval)
this.interval = setInterval(() => {
this.currentIndex = (this.currentIndex + 1) % this.cluster.length//
this.drawMap()
}, 4000)
},
clickback() {
this.dialogVisible = false
},
filterData(data) {
this.selectedCity = data
if (data === '') {
this.setDataRoll()
}
this.$emit('selectedCity', data)
},
drawMap() {
const canvas = document.querySelector('#container')
const ctx = canvas.getContext('2d')
ctx.clearRect(0, 0, window.innerWidth, window.innerHeight)
this.initOutline()
this.initMap()
this.setPoint()
},
setPoint() {
const canvas = document.querySelector('#container')
const ctx = canvas.getContext('2d')
ctx.beginPath()
this.cluster.forEach((e, i) => {
const position = this.toScreenPosition(e.longitude, e.latitude)
if (this.currentIndex === i) {
ctx.drawImage(this.img, position.x - 40, position.y - 55, 80, 80)
ctx.fillStyle = 'rgba(255, 197, 39, 1)'
ctx.font = '30px PangMenZhengDao'
ctx.fillText(e.name, position.x - e.name.length / 2 * 35, position.y - 55)
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)'
const txtlength = e.name.length > e.address.length ? e.name.length : e.address.length
ctx.fillRect(position.x + 20, position.y + 5, txtlength * 27, 90)
ctx.strokeStyle = '#3EDFFC'
ctx.strokeRect(position.x + 20, position.y + 5, txtlength * 27, 90)
ctx.fillStyle = '#FFFFFF'
ctx.font = '20px Arial'
ctx.fillText('名称:' + e.name, position.x + 20 + 20, position.y + 5 + 40)
ctx.fillText('地址:' + e.address || '-', position.x + 20 + 20, position.y + 5 + 70)
} else {
ctx.beginPath()
ctx.arc(position.x, position.y, 5, 0, Math.PI * 2) // 5
ctx.fillStyle = '#ffffff' //
ctx.fill()
ctx.closePath()
}
})
ctx.stroke()
ctx.restore()
},
getBoxArea() {
const canvasW = window.innerWidth
const canvasH = window.innerHeight
let N = -90; let S = 90; let W = 180; let E = -180
this.allJSON[this.mapMap[this.mapType] + 'Json'].features.forEach(item => {
if (item.geometry.type === 'Polygon') {
item.geometry.coordinates = [item.geometry.coordinates]
}
item.geometry.coordinates.forEach(area => {
area[0].forEach(elem => {
if (elem[0] < W) {
W = elem[0]
}
if (elem[0] > E) {
E = elem[0]
}
if (elem[1] > N) {
N = elem[1]
}
if (elem[1] < S) {
S = elem[1]
}
})
})
})
var wScale = canvasW / Math.abs(E - W)
var hScale = canvasH / Math.abs(N - S)
this.scale = (wScale > hScale ? hScale : wScale) * 0.9
this.geoCenter = {
W: W,
N: N,
xoffset: canvasW / 2 - Math.abs(E - W) / 2 * this.scale,
yoffset: canvasH / 2 - Math.abs(N - S) / 2 * this.scale
}
},
toScreenPosition(longitude, latitude) {
return {
x: (longitude - this.geoCenter.W) * this.scale + this.geoCenter.xoffset,
y: (this.geoCenter.N - latitude) * this.scale + this.geoCenter.yoffset
}
},
initMap() {
const canvas = document.querySelector('#container')
const ctx = canvas.getContext('2d')
this.cursorFlag = false
ctx.beginPath()
ctx.strokeStyle = '#3EDFFC'
ctx.lineWidth = 1
this.allJSON[this.mapMap[this.mapType] + 'Json'].features.forEach(elem => {
const coordinates = elem.geometry.coordinates
coordinates.forEach(multiPolygon => {
multiPolygon.forEach(polygon => {
ctx.save()
ctx.beginPath()
// ctx.translate(0, 0)
for (let i = 0; i < polygon.length; i++) {
const position = this.toScreenPosition(polygon[i][0], polygon[i][1])
if (i === 0) {
ctx.moveTo(position.x, position.y - 5)
} else {
ctx.lineTo(position.x, position.y - 5)
}
}
ctx.closePath()
ctx.strokeStyle = '#34CEE9'
ctx.lineWidth = 1
if (ctx.isPointInPath(this.offsetX, this.offsetY)) {
this.cursorFlag = true
ctx.fillStyle = '#a2f7ff'
if (this.eventType === 'click') {
this.filterData(elem.properties.name)
//
}
} else {
if (this.eventType === 'mousemove' && this.selectedCity === '') ctx.fillStyle = 'transparent'
}
if (this.selectedCity === elem.properties.name) ctx.fillStyle = '#00eaff'
ctx.fill()
ctx.stroke()
ctx.restore()
})
})
})
if (this.cursorFlag) {
canvas.style.cursor = 'pointer'
} else {
canvas.style.cursor = 'default'
}
},
initOutline() {
const canvas = document.querySelector('#container')
const ctx = canvas.getContext('2d')
const canvasW = canvas.width = window.innerWidth
const canvasH = canvas.height = window.innerHeight
ctx.clearRect(0, 0, canvasW, canvasH)
ctx.fillStyle = 'transparent'
ctx.fillRect(0, 0, canvasW, canvasH)
ctx.beginPath()
ctx.strokeStyle = '#3EDFFC'
ctx.lineWidth = 1
this.allJSON[this.mapMap[this.mapType] + 'Outline'].features.forEach(elem => {
const coordinates = elem.geometry.coordinates
ctx.save()
coordinates.forEach(multiPolygon => {
multiPolygon.forEach(polygon => {
for (let i = 0; i < polygon.length; i++) {
const position = this.toScreenPosition(polygon[i][0], polygon[i][1])
if (i === 0) {
ctx.moveTo(position.x, position.y + 5)
} else {
ctx.lineTo(position.x, position.y + 5)
}
}
})
})
})
ctx.closePath()
if (!ctx.isPointInPath(this.offsetX, this.offsetY)) {
if (this.eventType === 'click') {
this.filterData('')
//
}
}
ctx.fillStyle = '#3edffc'
var grd = ctx.createLinearGradient(0, 0, 1500, 0)
for (let i = 0; i < 1000; i++) {
grd.addColorStop(i / 1000, 'white')
grd.addColorStop(i / 1000 + 0.001, '#059BFC')
}
ctx.fillStyle = grd
// ctx.shadowColor = '#3EDFFC'
// ctx.shadowBlur = 0
// // ctx.shadowOffsetX = 50
// ctx.shadowOffsetY = 20
ctx.fill()
ctx.stroke()
ctx.restore()
ctx.beginPath()
this.allJSON[this.mapMap[this.mapType] + 'Outline'].features.forEach(elem => {
const coordinates = elem.geometry.coordinates
ctx.save()
coordinates.forEach(multiPolygon => {
multiPolygon.forEach(polygon => {
for (let i = 0; i < polygon.length; i++) {
const position = this.toScreenPosition(polygon[i][0], polygon[i][1])
if (i === 0) {
ctx.moveTo(position.x, position.y - 5)
} else {
ctx.lineTo(position.x, position.y - 5)
}
}
})
})
})
ctx.closePath()
var g = ctx.createRadialGradient(700, 600, 50, 1000, 600, 600)
g.addColorStop(0, '#29a0ee')
g.addColorStop(1, '#0b4eaf')
ctx.fillStyle = g
ctx.fill()
ctx.stroke()
ctx.restore()
}
}
}
</script>
<style lang="scss" scoped>
.back{
position:absolute;
top: 20vh;
left: 31vw;
z-index: 99;
}
.data-view {
position: absolute;
right: 0px;
border: 1px solid #3EDFFC;
padding: 0 10px;
margin: 10px;
background-color: #1a2d47ad;
bottom: 0;
font-size: 0.8rem;
p{
color: #DDDDDD;
text-indent: 1rem;
position: relative;
}
p:before{
content: '';
display: block;
width: 8px;
height: 8px;
border-radius: 8px;
background-color: #0fe765;
position: absolute;
left: 3px;
top: 3px;
}
p:nth-child(3):before{
background-color: #3EDFFC;
}
p:nth-child(4):before{
background-color: #f3ca45;
}
h5{font-weight: bold; font-size: 1rem; margin: 1rem 0}
}
.top{
width: 100%;
position: absolute;
display: block;
height: 60vh;
z-index: 8;
}
.center{
position:absolute;
bottom: 11vh;
right: 30vw;
z-index: 100;
width: 20vh;
.el-button,.el-button + .el-button{
margin: 0;
// margin-bottom: 10px;
// padding: 10px 15px;
padding: 0.5vh 2rem;
height: 5vh;
width: 100%;
background: url(../../assets/monitor/b.png) left no-repeat;
background-size: 100% 100%;
font-weight: 500;
font-style: italic;
color: #FFFFFF;
text-shadow: 0px 2px 6px rgba(19,23,27,0.31);
border-radius: 0;
text-align: left;
border: 0;
// line-height: 4vh;
div{
font-size: 1.2rem;
@media screen and (max-height: 900px) {
// transform: scale(0.8);
font-size: 0.8rem;
}
}
}
.active{
background: url(../../assets/monitor/b-p.png) left no-repeat;
background-size: 100% 100%;
}
}
.canvasBox{
width: 100%;
height: 100%;
position: relative;
}
#container {
width: 55vw;
height: 65vh;
margin: auto;
margin-top: 18vh;
display: block;
}
.spin{
width: 100%;
height: 30vh;
display: block;
position: absolute;
bottom: 0;
perspective: 200vh;
z-index: 0;
// animation: rotate 13s linear infinite;
.circle {
width: 50vw;
height: 30vh;
position: absolute;
left: 0;
top: -49vh;
display: block;
// border: 1px solid #ffffff;
}
.circle1{
width: 28vw;
height: 80vh;
top: -25.5vh;
left: 36vw;
transform: rotateX(80deg);
.turnAround{
width: 100%;
height: 100%;
animation: rotate 8s linear infinite;
background: url('../../assets/monitor/circle1.png') center no-repeat;
background-size: 80% auto;
}
}
.circle2{
width: 54vw;
height: 99vh;
left: 23vw;
top: -34vh;
transform: rotateX(80deg);
.turnAround{
width: 100%;
height: 100%;
animation: backRotate 15s linear infinite;
background: url('../../assets/monitor/circle2.png') center no-repeat;
background-size: 80% auto;
}
}
.circle3{
width: 46vw;
height: 80vh;
left: 27vw;
top: -25vh;
transform: rotateX(80deg);
.turnAround{
width: 100%;
height: 100%;
animation: rotate 10s linear infinite;
background: url('../../assets/monitor/circle3.png') center no-repeat;
background-size: 80% auto;
opacity: 0.5;
}
}
@keyframes rotate {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
@keyframes backRotate {
0% {
transform: rotate(360deg);
}
100% {
transform: rotate(0deg);
}
}
}
</style>

View File

@ -0,0 +1,146 @@
<template>
<div>
<h3> {{ $t('page.createVaspTask') }} </h3>
<el-form
ref="formData"
class="form-wrap"
label-position="left"
:model="formData"
:rules="formDataRules"
>
<el-form-item :label="$t('page.taskName')" prop="name">
<el-input
v-model="formData.name"
:placeholder="$t('page.inputWarn')"
:max-length="30"
/>
</el-form-item>
<el-form-item :label="$t('page.partition')" prop="partition">
<el-input
v-model="formData.partition"
:max-length="30"
/>
</el-form-item>
<el-form-item :label="$t('page.nodeNum')" prop="nNode">
<el-input
v-model="formData.nNode"
/>
</el-form-item>
<el-form-item :label="$t('page.commandContent')" prop="cmdScript">
<el-input
v-model="formData.cmdScript"
type="textarea"
/>
</el-form-item>
<el-form-item :label="$t('page.workMenu')" prop="workDir">
<el-input
v-model="formData.workDir"
/>
</el-form-item>
<el-form-item :label="$t('page.fileUpload')">
<!-- <el-input v-model="taskInput" type="textarea" rows="10" /> -->
<el-upload
ref="upload"
class="upload-demo"
:file-list="fileList"
:auto-upload="false"
action="#"
:multiple="true"
>
<el-button slot="trigger" size="small">选取文件</el-button>
<!-- <el-button size="small" type="primary" @click="confirmUpload">确认上传</el-button> -->
</el-upload>
</el-form-item>
</el-form>
</div>
</template>
<script>
import generate from 'nanoid/generate'
export default {
data() {
return {
formData: {
'name': 'vasptask-' + generate('abcdefghijklmnopqrstuvwxyz', 12),
'partition': 'C64T1',
'nNode': '1',
'workDir': '/vasp',
'cmdScript': '#!/bin/bash\n sbatch vasp.sh'
},
fileList: [],
settingFlag: false
}
},
computed: {
formDataRules() {
return {
name: [
{ required: true, message: this.$t('check.input') + this.$t('message.name') },
{
pattern: /^[a-z]([-a-z0-9]*[a-z0-9])?$/,
message: this.$t('check.inputInvalid')
}
// { validator: this.nameValidator }
],
partition: [
{ required: true, message: this.$t('check.input') + this.$t('page.partition') }
],
cmdScript: [
{ required: true, message: this.$t('check.input') + this.$t('page.cmdScript') }
],
workDir: [
{ required: true, message: this.$t('check.input') + this.$t('page.workMenu') }
],
nNode: [
{ required: true, message: this.$t('check.input') + this.$t('page.nodeNum') }
]
}
}
},
methods: {
submitUpload() {
// console.log(formData)
//
return false
},
checkForm() {
let returnVal
this.$refs.formData.validate((valid) => {
if (valid) {
const form = new FormData()
this.$refs.upload.uploadFiles.forEach((file, index) => {
form.append(`files`, file.raw)
})
form.set('clusterId', '1830873903296155648')
form.set('workDir', this.formData.workDir)
// uploadVaspContent(form).then((e) => {
// if (e.code === 0) {
// this.$message.success(this.$t('page.uploadSuccess'))
const params = {
...this.formData,
fileData: form
}
returnVal = params
// } else {
// this.$message.error(e.data)
// // this.submitLoading = false
// }
// }).catch(e => {
// // this.submitLoading = false
// })
} else {
returnVal = false
}
})
return returnVal
}
}
}
</script>
<style lang="scss">
.form-wrap .el-form-item__label-wrap .el-form-item__label{
text-indent: -1rem!important;
}
</style>

View File

@ -43,7 +43,8 @@
<div class="taskForm">
<div v-show="!selectCluster&&!strategySetting">
<application-form v-show="cpType === 'cloud'&&taskType === 'application'" ref="application" />
<hpc-create v-if="cpType === 'hpc'" ref="hpcBase" />
<hpc-create v-if="cpType === 'hpc'&&taskType === 'hpcBase'" ref="hpcBase" />
<vasp-create v-if="cpType === 'hpc'&&taskType === 'hpcVasp'" ref="hpcVasp" />
<ai-create v-if="cpType === 'ai'&&taskType!=='deductive'" ref="aiBase" :type="taskType" :adapter-id="formData.adapterId" />
<vm-form v-if="taskType === 'virtualmachine'" ref="virtualmachine" />
<deductive-form v-if="taskType === 'deductive'" ref="deductive" :adapter-id="formData.adapterId" />
@ -203,11 +204,11 @@
<el-row type="flex" justify="end">
<el-col :span="2.5">
<el-button size="medium" @click="goBack">{{ $t("message.cancel") }}</el-button>
<el-button v-if="!selectCluster&&!strategySetting&&taskType!=='aiCard'&&taskType!=='deductive'" size="medium" type="primary" @click="next">{{ $t('message.next') }}</el-button>
<el-button v-if="!selectCluster&&!strategySetting&&taskType!=='aiCard'&&taskType!=='deductive'&&taskType!=='hpcVasp'" size="medium" type="primary" @click="next">{{ $t('message.next') }}</el-button>
<el-button v-if="selectCluster" size="medium" type="primary" @click="selectCluster=false">{{ $t('message.before') }}</el-button>
<el-button v-if="selectCluster&&!strategySetting&&taskType!=='aiCard'&&taskType!=='deductive'" size="medium" type="primary" @click="setStrategy">{{ $t('message.next') }}</el-button>
<el-button v-if="strategySetting" size="medium" type="primary" @click="strategySetting=false;selectCluster=true">{{ $t('message.before') }}</el-button>
<el-button v-if="strategySetting || taskType==='aiCard' || taskType==='deductive'" v-loading="submitLoading" size="medium" type="primary" @click="saveForm">{{ $t('message.create') }}</el-button>
<el-button v-if="strategySetting || taskType==='aiCard' || taskType==='deductive' || taskType==='hpcVasp'" v-loading="submitLoading" size="medium" type="primary" @click="saveForm">{{ $t('message.create') }}</el-button>
<!-- <el-button size="medium" type="primary" @click="saveForm">{{ $t("message.easyCreate") }}</el-button> -->
</el-col>
</el-row>
@ -216,9 +217,10 @@
<script>
import List from '@/components/list'
import { addApp, addHpcTask, addAITask, addVirtualMachine, getBalanceById, addDeductiveImageTask, addDeductiveTextTask } from '@/api/task/task'
import { addApp, addHpcTask, addAITask, addVirtualMachine, getBalanceById, addDeductiveImageTask, addDeductiveTextTask, uploadVaspContent } from '@/api/task/task'
import applicationForm from './components/applicationForm'
import hpcCreate from './components/hpcCreate.vue'
import vaspCreate from './components/hpcVasp.vue'
import { getClusterList } from '@/api/container/cluster'
import aiCreate from './components/aiCreate.vue'
import { getAdapterList } from '@/api/pcm/adapter'
@ -228,7 +230,7 @@ import { mapGetters } from 'vuex'
// import jobForm from './components/jobForm.vue'
export default {
components: { applicationForm, List, hpcCreate, aiCreate, vmForm, deductiveForm },
components: { applicationForm, List, hpcCreate, aiCreate, vmForm, deductiveForm, vaspCreate },
data() {
return {
getClusterList,
@ -255,7 +257,8 @@ export default {
'virtualmachine': 'createVirtualmachine'
},
'hpc': {
'hpcBase': 'createHpcbase'
'hpcBase': 'createHpcbase',
'hpcVasp': 'createVasp'
},
'ai': {
'aiBase': 'createAibase',
@ -373,6 +376,10 @@ export default {
list[i] = e.data.list.filter(r => r.type === '2')
break
}
case 'hpcVasp': {
list[i] = e.data.list.filter(r => r.id === '1830873578531196928')
break
}
case 'aiBase': {
list[i] = e.data.list.filter(r => r.type === '1')
break
@ -396,7 +403,7 @@ export default {
},
methods: {
getCluster() {
const query = { 'type': this.taskType === 'application' ? '0' : (this.taskType === 'aiBase' || this.taskType === 'aiCard') ? '1' : this.taskType === 'hpcBase' ? '2' : '0', 'adapterId': this.formData.adapterId, pageNum: 1, pageSize: 1000 }
const query = { 'type': this.taskType === 'application' ? '0' : (this.taskType === 'aiBase' || this.taskType === 'aiCard') ? '1' : (this.taskType === 'hpcBase' || this.taskType === 'hpcVasp') ? '2' : '0', 'adapterId': this.formData.adapterId, pageNum: 1, pageSize: 1000 }
this.getClusterList(query).then(e => {
this.currentClusterList = e.data.list || []
})
@ -498,6 +505,29 @@ export default {
})
break
}
case 'hpcVasp': {
delete formHook.adapterIds
delete formHook.aiClusterIds
formHook.clusterId = '1830873903296155648'
uploadVaspContent(formHook.fileData).then((e) => {
if (e.code === 0) {
// this.$message.success(this.$t('page.uploadSuccess'))
delete formHook.fileData
addHpcTask(formHook).then(() => {
this.$message.success(this.$t('page.createdSuccess'))
this.$router.push({ path: '/taskManagement/taskList' })
}).catch(e => {
this.submitLoading = false
})
} else {
this.$message.error(e.data)
this.submitLoading = false
}
}).catch(() => {
this.submitLoading = false
})
break
}
case 'aiBase': {
formHook.adapterId = formHook.adapterIds[0]
delete formHook.adapterIds

View File

@ -28,7 +28,7 @@
</el-tab-pane> -->
<el-tab-pane v-if="formData.clusterInfos && formData.taskTypeDict !== '11' && formData.taskTypeDict !== '12'" :label="$t('page.taskLog')">
<el-select v-model="cluster" style="width:70%" @change="selectCluster(cluster)">
<el-select v-if="!formData.subTaskInfos[0].workDir" v-model="cluster" style="width:70%" @change="selectCluster(cluster)">
<el-option
v-for="item in formData.clusterInfos"
:key="item.id"
@ -89,7 +89,7 @@
<script>
import List from '@/components/list'
import { FormData } from '@/components/FormData'
import { getTaskDetail, getTaskLog, getDeductiveDetail } from '@/api/task/task'
import { getTaskDetail, getTaskLog, getDeductiveDetail, downloadVaspContent } from '@/api/task/task'
import { mapGetters } from 'vuex'
import bootChart from './components/boot'
@ -168,6 +168,11 @@ export default {
if (this.formData.taskTypeDict === '12') {
this.inferId = this.formData.subTaskInfos[0].id
}
if (res.data.subTaskInfos[0].workDir) {
downloadVaspContent({ workDir: res.data.subTaskInfos[0].workDir, fileName: 'demo.out', clusterId: this.formData.clusterInfos[0].id }).then(e => {
this.log = e
})
}
}
})
},

View File

@ -63,6 +63,12 @@ module.exports = {
changeOrigin: true,
secure: false
},
'^/ai4m': {
ws: false,
target: 'https://ai4m.jointcloud.net:443/',
changeOrigin: true,
secure: false
},
'^/auth': {
ws: false,
target: 'https://comnet.jointcloud.net/',