Merge pull request 'task list page' (#211) from annzee/JCC-RIP:cetc into master

This commit is contained in:
annzee 2024-07-12 10:55:07 +08:00
commit b269835e6e
12 changed files with 990 additions and 4 deletions

View File

@ -45,6 +45,9 @@
"menu": { "menu": {
"taskManagement": "Task", "taskManagement": "Task",
"taskList": "Task", "taskList": "Task",
"aiList": "AI Task",
"hpcList": "HPC Task",
"cloudList": "Cloud Task",
"jobTask": "TaskList", "jobTask": "TaskList",
"strategyManagement": "Strategy Management", "strategyManagement": "Strategy Management",
"schedulingStrategy": "Schedule Management", "schedulingStrategy": "Schedule Management",
@ -98,7 +101,8 @@
"storageMana": "Storage Mgmt", "storageMana": "Storage Mgmt",
"appObserve": "App Monitoring", "appObserve": "App Monitoring",
"logMana": "Log Mgmt", "logMana": "Log Mgmt",
"monitorSelectPcm": "JCCE" "monitorSelectPcm": "JCCE",
"fileManagement": "File Management"
}, },
"check": { "check": {
"input": "Please Input", "input": "Please Input",

View File

@ -45,6 +45,9 @@
"menu": { "menu": {
"taskManagement": "任务管理", "taskManagement": "任务管理",
"taskList": "任务列表", "taskList": "任务列表",
"aiList": "智算任务列表",
"hpcList": "超算任务列表",
"cloudList": "数算任务列表",
"jobTask": "作业任务", "jobTask": "作业任务",
"strategyManagement": "策略管理", "strategyManagement": "策略管理",
"schedulingStrategy": "调度策略", "schedulingStrategy": "调度策略",
@ -98,7 +101,8 @@
"storageMana": "存储管理", "storageMana": "存储管理",
"appObserve": "应用观测", "appObserve": "应用观测",
"logMana": "日志管理", "logMana": "日志管理",
"monitorSelectPcm": "云际算力网基础平台" "monitorSelectPcm": "云际算力网基础平台",
"fileManagement": "文件管理"
}, },
"check": { "check": {
"input": "请输入", "input": "请输入",

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@ -56,6 +56,9 @@
<el-dropdown-item v-if="menus.includes('systemManagement')" @click.native="toSetting"> <el-dropdown-item v-if="menus.includes('systemManagement')" @click.native="toSetting">
{{ $t('menu.systemManagement') }} {{ $t('menu.systemManagement') }}
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-if="!menus.includes('fileManagement')" @click.native="toFileManagement">
{{ $t('menu.fileManagement') }}
</el-dropdown-item>
<el-dropdown-item divided @click.native="logout"> <el-dropdown-item divided @click.native="logout">
<span style="display:block;">{{ $t('message.logout') }}</span> <span style="display:block;">{{ $t('message.logout') }}</span>
</el-dropdown-item> </el-dropdown-item>
@ -165,6 +168,10 @@ export default {
this.$store.dispatch('user/setRouteType', 'warnManagement') this.$store.dispatch('user/setRouteType', 'warnManagement')
this.$router.push({ path: '/warnManagement/warnList' }) this.$router.push({ path: '/warnManagement/warnList' })
}, },
toFileManagement() {
this.$store.dispatch('user/setRouteType', 'fileManagement')
this.$router.push({ path: '/fileManagement/fileList' })
},
toSetting() { toSetting() {
this.$store.dispatch('user/setRouteType', 'setting') this.$store.dispatch('user/setRouteType', 'setting')
this.$router.push({ path: '/setting/dictManagement' }) this.$router.push({ path: '/setting/dictManagement' })

View File

@ -18,6 +18,7 @@ import modelarts from './modules/modelarts'
import taskManagementRouter from './modules/taskManagement' import taskManagementRouter from './modules/taskManagement'
import strategyManagementRouter from './modules/strategy' import strategyManagementRouter from './modules/strategy'
import adapterMangementRouter from './modules/adapterManagement' import adapterMangementRouter from './modules/adapterManagement'
import fileManagementRouter from './modules/fileManagement'
/* Router Modules */ /* Router Modules */
// import componentsRouter from './modules/components' // import componentsRouter from './modules/components'
// import tableRouter from './modules/table' // import tableRouter from './modules/table'
@ -153,7 +154,8 @@ export const asyncRoutes = [
modelarts, modelarts,
taskManagementRouter, taskManagementRouter,
strategyManagementRouter, strategyManagementRouter,
adapterMangementRouter adapterMangementRouter,
fileManagementRouter
] ]
const createRouter = () => new Router({ const createRouter = () => new Router({

View File

@ -0,0 +1,20 @@
import Layout from '@/layout'
const fileManagementRouter = {
path: '/fileManagement',
component: Layout,
name: 'fileManagement',
meta: {
title: 'fileManagement',
icon: 'xunijiguanli-juan'
},
children: [
{
path: 'fileList',
component: () => import('@/views/fileManagement/fileList/list'),
name: 'fileManagement',
meta: { title: 'overview', icon: 'gailan', affix: true },
hidden: false
}
]
}
export default fileManagementRouter

View File

@ -28,6 +28,28 @@ const taskManagementRouter = {
name: 'taskList', name: 'taskList',
meta: { title: 'taskList', icon: 'gailan', affix: true }, meta: { title: 'taskList', icon: 'gailan', affix: true },
hidden: false hidden: false
}] },
{
path: 'cloudList',
component: () => import('@/views/taskManagement/cloudList/taskList'),
name: 'cloudList',
meta: { title: 'cloudList', icon: 'gailan', affix: true },
hidden: false
},
{
path: 'aiList',
component: () => import('@/views/taskManagement/aiList/taskList'),
name: 'aiList',
meta: { title: 'aiList', icon: 'gailan', affix: true },
hidden: false
},
{
path: 'hpcList',
component: () => import('@/views/taskManagement/hpcList/taskList'),
name: 'hpcList',
meta: { title: 'hpcList', icon: 'gailan', affix: true },
hidden: false
}
]
} }
export default taskManagementRouter export default taskManagementRouter

View File

@ -0,0 +1,408 @@
<template>
<div class="UsabilityMonitor">
<el-card>
<Exhibition :data="exhibitionArray" span="8" />
</el-card>
<el-row>
<el-card>
<el-row>
<div class="select-option">
<el-button class="opr-btn" size="middle" type="primary" @click="form={runEnv: 'python3'};dialogCreateVisible=true">上传文件</el-button>
<!-- <el-button class="opr-btn" size="middle" @click="downloadList">下载任务列表</el-button> -->
</div>
<div class="file-breadcrumb">
<span class="floatRight">{{ (diskfileList || []).length }}个文件</span>
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item :to="{ path: '/' }">全部文件</el-breadcrumb-item>
<!-- <el-breadcrumb-item>文件夹名</el-breadcrumb-item> -->
</el-breadcrumb>
</div>
<List
ref="multipleTable"
class="multipleTable"
:columns="columns"
:table-list-data="diskfileList"
:pagination="false"
tooltip-effect="dark"
/>
<div class="add-pagination">
<el-pagination
background
:hide-on-single-page="false"
:current-page="page"
layout="total, prev, pager, next, jumper"
:total="total"
@current-change="currentChange"
/>
</div>
<el-dialog :visible.sync="dialogCreateVisible" title="上传文件选择" width="35%">
<div class="upload-area">
<p>存储方式</p>
<el-row type="flex" justify="space-between">
<el-col :span="6">
<el-radio v-model="radio1" label="1" border>直接存储</el-radio>
</el-col>
<el-col :span="6">
<el-radio v-model="radio1" label="2" border>多副本方式</el-radio>
</el-col>
<el-col :span="6">
<el-radio v-model="radio1" label="3" border>纠删码方式</el-radio>
</el-col>
</el-row>
<p style="margin-top: 30px">本地上传</p>
<el-upload
:key="radio1"
ref="upload"
class="upload-file"
:headers="{'Authorization': token}"
:action="location + '/apis/jcc-cloudStorage/storage/uploadFile?mode=' + radio1"
:file-list="fileList"
:on-success="handleUploadSuccess"
:on-error="handleUploadError"
:auto-upload="false"
>
<el-button slot="trigger" size="small" type="primary">选取文件</el-button>
<div slot="tip" class="el-upload__tip">单个文件支持最大上传2G</div>
</el-upload>
<el-divider />
<el-button type="info" @click="submitUpload">确认</el-button>
<el-button @click="dialogCreateVisible=false">取消</el-button>
</div>
</el-dialog>
<el-dialog :visible.sync="dialogDetailVisible" title="存储文件详情" width="80%">
<div>
<!-- <div class="select-option" /> -->
<div class="tap-name">
存储文件名称
{{ tapTableData0.length > 0 ? tapTableData0[0].name : '' }}
<!-- 条带名/t1efne231_0 -->
</div>
<List
ref="tapTable0"
class="tapTable"
:columns="tapTableColumns"
:table-list-data="tapTableData0"
:pagination="false"
/>
<!-- <div class="add-pagination">
<el-pagination
background
:hide-on-single-page="false"
:current-page="1"
layout="total, prev, pager, next, jumper"
:total="10"
/>
</div> -->
</div>
</el-dialog>
</el-row>
</el-card>
</el-row>
</div>
</template>
<script>
import List from '@/components/list'
import Exhibition from '@/components/Exhibition'
import clip from '@/utils/clipboard'
import { numberToStr } from '@/utils/data-process'
// import deletePng from '@/assets/images/exhibition/statusMonitor-2.png'
import { getToken } from '@/utils/auth'
export default {
components: {
List,
Exhibition
},
data() {
return {
location: window.location.origin,
active: 1,
dialogCreateVisible: false,
dialogDetailVisible: false,
radio1: '1',
token: getToken(),
exhibitionArray: [
{
name: '文件个数',
src: 'usabilityMonitor-1',
value: '0'
},
{
name: '文件总大小',
src: 'usabilityMonitor-2',
value: '0'
},
{
name: '剩余空间容量',
src: 'usabilityMonitor-3',
value: '0'
}
],
columns: [
{ type: 'selection' },
{ prop: 'name', label: '文件名', formatter: (row) => { return <span>{row.name}</span> } },
{ prop: 'createdTime', label: '修改时间' },
{ prop: 'size', label: '大小', formatter: (row) => { return <span>{numberToStr(row.size - 0, 'B')}</span> } },
{ prop: '', label: '操作', formatter: (row) => {
const options = { width: 120 }
return <div class='opr-group'>
<el-popover
placement='bottom'
width='320'
trigger='click'>
<div class='qrcode-popover'>
<p>文件分享</p>
<div class='qrcode'>
<qrcode options={ options } value={row.url} />
</div>
<el-divider/>
<span>链接30天后失效</span>
<el-button size='middle' type='primary' onClick={ (e) => { this.handleCopy(row.url, e) }}>复制链接</el-button>
</div>
<svg-icon icon-class='fenxiang' slot='reference'/>
</el-popover>
<svg-icon icon-class='xiazai' onClick={() => this.downloadFile(row)} />
<svg-icon icon-class='bianji' onClick={() => this.viewDetail(row.id)} />
<svg-icon icon-class='shanchu' onClick={() => this.deleteFile(row.id)} />
</div>
} }
],
tapTableColumns: [
{ type: 'index', label: '序号' },
{ prop: 'clusterName', label: '集群/虚拟机' },
{ prop: 'size', label: '占用大小' },
{ prop: 'ip', label: 'IP' },
{ prop: 'address', label: '地点' },
// { prop: 'status', label: '', formatter: (row) => { return <span class={row.status === '' ? 'red' : 'nlue'}>{row.status}</span> } }
{ prop: 'status', label: '状态', formatter: (row) => <span class='nlue'>正常</span> } // wangqi
],
tapTableData0: [],
tapTableData1: [],
diskfileList: [],
fileList: [],
page: 1,
size: 12,
total: 0
}
},
mounted() {
this.getList()
this.getCount()
},
methods: {
currentChange(page) {
this.page = page
this.getList()
},
handleUploadSuccess() {
this.$message.success('文件上传成功')
this.dialogCreateVisible = false
this.fileList = []
this.getList()
},
handleUploadError() {
this.$message.warning('上传失败')
},
handleCopy(text, event) {
clip(text, event)
},
deleteFile(id) {
this.$confirm('<img src=""><p>文件删除后将不可恢复,是否确认删除?</p>', '温馨提示', {
dangerouslyUseHTMLString: true,
confirmButtonText: '确认',
center: true,
cancelButtonText: '取消'
}).then(() => {
this.$Api.deleteFile(id).then(e => {
this.$message.success('删除成功')
this.getList()
})
})
},
downloadFile(row) {
const a = document.createElement('a')
a.href = row.url
a.download = row.name //
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
},
addFolder() {},
downloadList() {},
viewDetail(id) {
this.$Api.getFileInfoById(id).then(res => {
this.tapTableData0 = [
{
name: res.data.name,
clusterName: res.data.clusterName,
size: res.data.size,
ip: res.data.ip,
address: res.data.city,
status: res.data.status === 1 ? '正常' : '异常'
}
]
this.dialogDetailVisible = true
})
},
submitUpload() {
this.$refs.upload.submit()
},
getBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader()
let fileResult = ''
reader.readAsDataURL(file)
reader.onload = () => {
fileResult = reader.result
}
reader.onerror = (error) => {
reject(error)
}
reader.onloadend = () => {
resolve(fileResult)
}
})
},
getCount() {
// this.$Api.getFileCount().then(e => {
// this.exhibitionArray[0].value = e.data?.fileCount
// this.exhibitionArray[1].value = numberToStr(e.data?.fileSum - 0, 'B')
// this.exhibitionArray[2].value = numberToStr(e.data?.surplusCapacity - 0, 'B')
// })
},
getList() {
this.$Api.getFileList({ 'mark': 'page', 'page': this.page }).then(e => {
this.diskfileList = e.rows
this.total = e.total
})
},
deleteFunc(id) {
},
handleClick() {
if (this.activeName === '1') {
this.form = { env: 'python' }
}
},
transBase64(code) {
return Buffer.from(code).toString('base64')
},
getResult() {
// this.dynamicData();
}
}
}
</script>
<style lang="scss">
.select-option{
padding: 20px;
color: var(--buttonDivC);
background: var(--listBtnColor);
}
.opr-group{
color:#999999;
svg{
margin-right: 37px;
cursor: pointer
}
.svg-icon{width:20px; height: 20px;}
}
.file-breadcrumb{
padding: 17px 32px;
.el-breadcrumb__item:last-child .el-breadcrumb__inner, .el-breadcrumb__item:last-child .el-breadcrumb__inner:hover, .el-breadcrumb__item:last-child .el-breadcrumb__inner a, .el-breadcrumb__item:last-child .el-breadcrumb__inner a:hover{
font-size: 16px!important;
color: var(--buttonDivC);
font-weight: 500!important;
}
.floatRight{
text-align: right;
float: right;
font-size: 16px!important;
color: var(--buttonDivC);
font-weight: 500!important;
}
}
.el-popper .qrcode-popover{
padding: 12px;
text-align: center;
p{
margin-top: 0;
text-align: left;
}
.qrcode{
margin: 24px auto;
margin-top: 40px;
width: 140px;
padding: 10px;
border: 1px solid #eeeeee;
border-radius: 10px;
}
>span{
display: block;
text-align: center;
font-size: 12px;
margin-bottom: 24px;
color: #999999;
}
.el-button{
margin-bottom: 16px;
}
}
.el-divider{
background-color: #EEEEEE;
}
.upload-area{
text-align: center;
p{
text-align: left;
color: var(--buttonDivC);
font-size: 12px;
margin-bottom: 8px;
}
.el-row--flex.is-justify-space-between{
margin-top: 20px;
}
.upload-file{
text-align: right;
}
.el-upload__tip{
float: left;
color: #999999;
font-size: 12px;
margin-top: 12px;
}
.el-upload{
.el-button{
float: right;
}
}
.el-upload-list__item-name{
text-align: left;
}
.el-radio{
width: 100%;
}
>.el-button{
margin: 100px 18px 10px 18px;
}
}
.red{
color: #D9001B;
}
.blue {
color: #3182CE;
}
.tap-name{
height: 48px;
line-height: 48px;
background: #3182CE;
border-radius: 2px;
margin-bottom: 24px;
padding: 0 27px;
color: #ffffff;
}
.add-pagination{
margin-bottom: 40px;
}
</style>

View File

@ -0,0 +1,210 @@
<template>
<div class="podInfo">
<el-card class="basicInfo">
<h4>{{ $t('page.ai')+$t('page.task') }}</h4>
<span class="tips title-tips">
{{ $t('page.taskDescription') }}</span>
</el-card>
<el-card>
<ul class="dataCard">
<li>
<p>训练任务</p>
<div>
<div class="data">
<span>运行中</span>
<p>30</p>
</div>
<div class="data">
<span>总数</span>
<p>100</p>
</div>
</div>
</li>
<li>
<p>推理任务</p>
<div>
<div class="data">
<span>运行中</span>
<p>30</p>
</div>
<div class="data">
<span>总数</span>
<p>100</p>
</div>
</div>
</li>
<li>
<p>模型实例</p>
<div>
<div class="data">
<span>运行中</span>
<p>30</p>
</div>
<div class="data">
<span>总数</span>
<p>100</p>
</div>
</div>
</li>
</ul>
<List
ref="multipleTable"
:key="$i18n.locale"
class="multipleTable"
:columns="columns"
:filter-map="filterMap"
:get-list-action="getAppList"
:default-sort="{prop: 'existTime', order: 'ascending'}"
:pagination="true"
page-key="pageNum"
limit-key="pageSize"
tooltip-effect="dark"
>
<template v-slot:filterBtns>
<el-button size="medium" type="primary" @click="createItem">{{ $t('message.create') }}</el-button>
</template>
</List>
</el-card>
</div>
</template>
<script>
import List from '@/components/list'
import { getAppList } from '@/api/task/task'
import { mapGetters } from 'vuex'
import { runtimeFormat } from '@/utils/index'
export default {
components: { List },
data() {
return {
getAppList,
strategyList: []
// columns: []
}
},
computed: {
...mapGetters([
'dict'
]),
filterMap() {
return {
name: {
label: this.$t('message.name')
},
status: {
label: this.$t('page.job') + this.$t('page.status'),
type: 'select',
dataSource: [
{
label: '已保留', value: 'unschedulable'
}, {
label: '已下发', value: 'running'
}, {
label: '错误', value: 'warning'
}
]
},
type: {
label: this.$t('page.task') + this.$t('page.type'),
type: 'select',
dataSource: [
{
label: '部署任务', value: 'unschedulable'
}, {
label: '应用任务', value: 'running'
}
]
}
}
},
columns() {
return this.setColumn()
}
},
watch: {
// '$i18n.locale'() {
// console.log('fff')
// this.setColumn()
// }
},
methods: {
setColumn() {
return [
{ prop: 'name', label: this.$t('page.taskName'), sortable: true, formatter: (row) => { return <a onClick={() => this.viewDetail(row)}>{row.name}</a> } },
{ prop: 'adapterTypeDict', label: this.$t('page.cpType'), formatter: row => {
return <div>{this.dict.adapter_type.filter(e => { return row.adapterTypeDict.toString() === e.itemValue })?.[0]?.['itemText'] || '-'}</div>
} },
{
prop: 'status',
label: this.$t('page.jobStatus')
},
{ prop: 'strategy', label: this.$t('page.policy'), formatter: row => {
const res = this.dict.schedule_Strategy.filter(e => { return row.strategy.toString() === e.itemValue })[0][this.$i18n.locale === 'en' ? 'itemText' : 'description']
return <div>{res}</div>
} },
{ prop: 'synergyStatus', label: this.$t('page.synergyStatus'), sortable: true, formatter: (row) => {
return <div>{!row.synergyStatus ? this.$t('page.notSynergistic') : this.$t('page.synergistic')}</div>
} },
// { prop: 'adapter', label: this.$t('page.adapter'), sortable: true },
// { prop: 'cluster', label: this.$t('page.cluster'), sortable: true },
{ prop: 'startTime', label: this.$t('page.startTime'), sortable: true, formatter: (row) => {
return <div>{row.startTime && new Date(row.startTime).toLocaleString() || '-'}</div>
} },
{ prop: 'runningTime', label: this.$t('page.elapsedTime'), sortable: true, formatter: row => {
return <div>{runtimeFormat(row.runningTime)}</div>
} },
{ prop: 'more', label: this.$t('page.more'), width: 200, formatter: (row) => {
const txt = this.$t('page.viewDetail')
return <div>
<el-dropdown>
<el-button className='el-dropdown-link' size='mini' icon='el-icon-more' circle>
</el-button>
<el-dropdown-menu slot='dropdown'>
<span onClick={() => this.viewDetail(row)}> <el-dropdown-item> {txt} </el-dropdown-item> </span>
</el-dropdown-menu>
</el-dropdown>
</div>
} }
]
},
viewDetail(row) {
this.$router.push({ path: `detail`, query: { id: row.id }})
},
createItem() {
this.$router.push({ path: `create` })
}
}
}
</script>
<style lang="scss">
.dataCard{
width: 100%;
padding: 0;
// display: flex;
// padding-bottom: 1rem;
// box-sizing: content-box;
li{
width: 26.7%;
margin: 0 3.3%;
float: left;
list-style-type: none;
box-shadow: 1px 1px 10px #050f27;
text-indent: 2rem;
margin-bottom: 2rem;
p{
font-size: 1.2rem;
}
>div{
display: flex;
.data:first-child{
span{
color: #3182CE;
}
}
}
}
}
</style>

View File

@ -0,0 +1,142 @@
<template>
<div class="podInfo">
<el-card class="basicInfo">
<h4>{{ $t('page.cloud')+$t('page.task') }}</h4>
<span class="tips title-tips">
{{ $t('page.taskDescription') }}</span>
</el-card>
<el-card>
<List
ref="multipleTable"
:key="$i18n.locale"
class="multipleTable"
:columns="columns"
:filter-map="filterMap"
:get-list-action="getAppList"
:default-sort="{prop: 'existTime', order: 'ascending'}"
:pagination="true"
page-key="pageNum"
limit-key="pageSize"
tooltip-effect="dark"
>
<template v-slot:filterBtns>
<el-button size="medium" type="primary" @click="createItem">{{ $t('message.create') }}</el-button>
</template>
</List>
</el-card>
</div>
</template>
<script>
import List from '@/components/list'
import { getAppList } from '@/api/task/task'
import { mapGetters } from 'vuex'
import { runtimeFormat } from '@/utils/index'
export default {
components: { List },
data() {
return {
getAppList,
strategyList: []
// columns: []
}
},
computed: {
...mapGetters([
'dict'
]),
filterMap() {
return {
name: {
label: this.$t('message.name')
},
status: {
label: this.$t('page.job') + this.$t('page.status'),
type: 'select',
dataSource: [
{
label: '已保留', value: 'unschedulable'
}, {
label: '已下发', value: 'running'
}, {
label: '错误', value: 'warning'
}
]
},
type: {
label: this.$t('page.task') + this.$t('page.type'),
type: 'select',
dataSource: [
{
label: '部署任务', value: 'unschedulable'
}, {
label: '应用任务', value: 'running'
}
]
}
}
},
columns() {
return this.setColumn()
}
},
watch: {
// '$i18n.locale'() {
// console.log('fff')
// this.setColumn()
// }
},
methods: {
setColumn() {
return [
{ prop: 'name', label: this.$t('page.taskName'), sortable: true, formatter: (row) => { return <a onClick={() => this.viewDetail(row)}>{row.name}</a> } },
{ prop: 'adapterTypeDict', label: this.$t('page.cpType'), formatter: row => {
return <div>{this.dict.adapter_type.filter(e => { return row.adapterTypeDict.toString() === e.itemValue })?.[0]?.['itemText'] || '-'}</div>
} },
{
prop: 'status',
label: this.$t('page.jobStatus')
},
{ prop: 'strategy', label: this.$t('page.policy'), formatter: row => {
const res = this.dict.schedule_Strategy.filter(e => { return row.strategy.toString() === e.itemValue })[0][this.$i18n.locale === 'en' ? 'itemText' : 'description']
return <div>{res}</div>
} },
{ prop: 'synergyStatus', label: this.$t('page.synergyStatus'), sortable: true, formatter: (row) => {
return <div>{!row.synergyStatus ? this.$t('page.notSynergistic') : this.$t('page.synergistic')}</div>
} },
// { prop: 'adapter', label: this.$t('page.adapter'), sortable: true },
// { prop: 'cluster', label: this.$t('page.cluster'), sortable: true },
{ prop: 'startTime', label: this.$t('page.startTime'), sortable: true, formatter: (row) => {
return <div>{row.startTime && new Date(row.startTime).toLocaleString() || '-'}</div>
} },
{ prop: 'runningTime', label: this.$t('page.elapsedTime'), sortable: true, formatter: row => {
return <div>{runtimeFormat(row.runningTime)}</div>
} },
{ prop: 'more', label: this.$t('page.more'), width: 200, formatter: (row) => {
const txt = this.$t('page.viewDetail')
return <div>
<el-dropdown>
<el-button className='el-dropdown-link' size='mini' icon='el-icon-more' circle>
</el-button>
<el-dropdown-menu slot='dropdown'>
<span onClick={() => this.viewDetail(row)}> <el-dropdown-item> {txt} </el-dropdown-item> </span>
</el-dropdown-menu>
</el-dropdown>
</div>
} }
]
},
viewDetail(row) {
this.$router.push({ path: `detail`, query: { id: row.id }})
},
createItem() {
this.$router.push({ path: `create` })
}
}
}
</script>
<style lang="scss">
</style>

View File

@ -0,0 +1,142 @@
<template>
<div class="podInfo">
<el-card class="basicInfo">
<h4>{{ $t('page.hpc')+ $t('page.task') }}</h4>
<span class="tips title-tips">
{{ $t('page.taskDescription') }}</span>
</el-card>
<el-card>
<List
ref="multipleTable"
:key="$i18n.locale"
class="multipleTable"
:columns="columns"
:filter-map="filterMap"
:get-list-action="getAppList"
:default-sort="{prop: 'existTime', order: 'ascending'}"
:pagination="true"
page-key="pageNum"
limit-key="pageSize"
tooltip-effect="dark"
>
<template v-slot:filterBtns>
<el-button size="medium" type="primary" @click="createItem">{{ $t('message.create') }}</el-button>
</template>
</List>
</el-card>
</div>
</template>
<script>
import List from '@/components/list'
import { getAppList } from '@/api/task/task'
import { mapGetters } from 'vuex'
import { runtimeFormat } from '@/utils/index'
export default {
components: { List },
data() {
return {
getAppList,
strategyList: []
// columns: []
}
},
computed: {
...mapGetters([
'dict'
]),
filterMap() {
return {
name: {
label: this.$t('message.name')
},
status: {
label: this.$t('page.job') + this.$t('page.status'),
type: 'select',
dataSource: [
{
label: '已保留', value: 'unschedulable'
}, {
label: '已下发', value: 'running'
}, {
label: '错误', value: 'warning'
}
]
},
type: {
label: this.$t('page.task') + this.$t('page.type'),
type: 'select',
dataSource: [
{
label: '部署任务', value: 'unschedulable'
}, {
label: '应用任务', value: 'running'
}
]
}
}
},
columns() {
return this.setColumn()
}
},
watch: {
// '$i18n.locale'() {
// console.log('fff')
// this.setColumn()
// }
},
methods: {
setColumn() {
return [
{ prop: 'name', label: this.$t('page.taskName'), sortable: true, formatter: (row) => { return <a onClick={() => this.viewDetail(row)}>{row.name}</a> } },
{ prop: 'adapterTypeDict', label: this.$t('page.cpType'), formatter: row => {
return <div>{this.dict.adapter_type.filter(e => { return row.adapterTypeDict.toString() === e.itemValue })?.[0]?.['itemText'] || '-'}</div>
} },
{
prop: 'status',
label: this.$t('page.jobStatus')
},
{ prop: 'strategy', label: this.$t('page.policy'), formatter: row => {
const res = this.dict.schedule_Strategy.filter(e => { return row.strategy.toString() === e.itemValue })[0][this.$i18n.locale === 'en' ? 'itemText' : 'description']
return <div>{res}</div>
} },
{ prop: 'synergyStatus', label: this.$t('page.synergyStatus'), sortable: true, formatter: (row) => {
return <div>{!row.synergyStatus ? this.$t('page.notSynergistic') : this.$t('page.synergistic')}</div>
} },
// { prop: 'adapter', label: this.$t('page.adapter'), sortable: true },
// { prop: 'cluster', label: this.$t('page.cluster'), sortable: true },
{ prop: 'startTime', label: this.$t('page.startTime'), sortable: true, formatter: (row) => {
return <div>{row.startTime && new Date(row.startTime).toLocaleString() || '-'}</div>
} },
{ prop: 'runningTime', label: this.$t('page.elapsedTime'), sortable: true, formatter: row => {
return <div>{runtimeFormat(row.runningTime)}</div>
} },
{ prop: 'more', label: this.$t('page.more'), width: 200, formatter: (row) => {
const txt = this.$t('page.viewDetail')
return <div>
<el-dropdown>
<el-button className='el-dropdown-link' size='mini' icon='el-icon-more' circle>
</el-button>
<el-dropdown-menu slot='dropdown'>
<span onClick={() => this.viewDetail(row)}> <el-dropdown-item> {txt} </el-dropdown-item> </span>
</el-dropdown-menu>
</el-dropdown>
</div>
} }
]
},
viewDetail(row) {
this.$router.push({ path: `detail`, query: { id: row.id }})
},
createItem() {
this.$router.push({ path: `create` })
}
}
}
</script>
<style lang="scss">
</style>

View File

@ -50,6 +50,31 @@ export default {
name: { name: {
label: this.$t('message.name') label: this.$t('message.name')
} }
// status: {
// label: this.$t('page.job') + this.$t('page.status'),
// type: 'select',
// dataSource: [
// {
// label: '', value: 'unschedulable'
// }, {
// label: '', value: 'running'
// }, {
// label: '', value: 'warning'
// }
// ]
// },
// type: {
// label: this.$t('page.task') + this.$t('page.type'),
// type: 'select',
// dataSource: [
// {
// label: '', value: 'unschedulable'
// }, {
// label: '', value: 'running'
// }
// ]
// }
} }
}, },
columns() { columns() {