|
|
@@ -0,0 +1,559 @@ |
|
|
|
<template> |
|
|
|
<div> |
|
|
|
<div class="ui container"> |
|
|
|
<div class="header"> |
|
|
|
<div class="tab-c"> |
|
|
|
<a class="tab-item" :href="`/${repoOwnerName}/${repoName}/${item.url}`" :key="item.key" |
|
|
|
:class="item.type == curTab ? 'focus' : ''" v-for="item in tabs"> |
|
|
|
<span>{{ item.label }}</span> |
|
|
|
</a> |
|
|
|
</div> |
|
|
|
<div class="right-c"></div> |
|
|
|
</div> |
|
|
|
<div v-if="tableData.length > 0"> |
|
|
|
<div class="list-body table-container"> |
|
|
|
<el-table :data="tableData" style="min-width:100%" v-loading="loading" stripe> |
|
|
|
<el-table-column v-if="pageCfg.page.columns.indexOf('taskName') >= 0" :label="$t('cloudbrainObj.taskName')" |
|
|
|
align="left" header-align="left" min-width="250"> |
|
|
|
<template slot-scope="scope"> |
|
|
|
<a class="dispaly-job-name" :href="scope.row.task.jobLink"> |
|
|
|
{{ scope.row.task.display_job_name }} |
|
|
|
</a> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
<el-table-column v-if="pageCfg.page.columns.indexOf('status') >= 0" prop="Status" :label="$t('status')" |
|
|
|
align="left" header-align="left" min-width="120"> |
|
|
|
<template slot-scope="scope"> |
|
|
|
<div class="status-wrap"> |
|
|
|
<i :class="scope.row.task.status"></i> |
|
|
|
<span>{{ scope.row.task.status }}</span> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
<el-table-column v-if="pageCfg.page.columns.indexOf('appName') >= 0" prop="job_type" |
|
|
|
:label="$t('cloudbrainObj.appName')" align="center" header-align="center" min-width="120"> |
|
|
|
<template slot-scope="scope"> |
|
|
|
<span>{{ scope.row.task.app_name }}</span> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
<el-table-column v-if="pageCfg.page.columns.indexOf('createTime') >= 0" prop="created_unix" |
|
|
|
:label="$t('cloudbrainObj.createTime')" align="center" header-align="center" min-width="120"> |
|
|
|
<template slot-scope="scope"> |
|
|
|
<el-tooltip effect="dark" :content="dateFormat(scope.row.task.created_unix)" placement="top-start"> |
|
|
|
<span>{{ scope.row.task.createdFromNow }}</span> |
|
|
|
</el-tooltip> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
<el-table-column v-if="pageCfg.page.columns.indexOf('runDuration') >= 0" prop="formatted_duration" |
|
|
|
:label="$t('cloudbrainObj.runDuration')" align="center" header-align="center" min-width="120"> |
|
|
|
<template slot-scope="scope"> |
|
|
|
<span>{{ scope.row.task.formatted_duration }}</span> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
<el-table-column v-if="pageCfg.page.columns.indexOf('clusterAndComputeResource') >= 0" |
|
|
|
:label="$t('cloudbrainObj.clusterAndComputeResource')" align="center" header-align="center" min-width="150"> |
|
|
|
<template slot-scope="scope"> |
|
|
|
<span>{{ scope.row.task.clusterName }} {{ scope.row.task.computeSourceShow }}</span> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
<el-table-column v-if="pageCfg.page.columns.indexOf('creator') >= 0" prop="remark" |
|
|
|
:label="$t('modelManage.creator')" align="left" min-width="80" header-align="center"> |
|
|
|
<template slot-scope="scope"> |
|
|
|
<div class="creator-wrap"> |
|
|
|
<a :href="'/' + scope.row.creator.name" :title="scope.row.creator.full_name"> |
|
|
|
<img :src="scope.row.creator.rel_avatar_link"> |
|
|
|
</a> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
<el-table-column prop="remark" :label="$t('operation')" align="left" min-width="300" header-align="center"> |
|
|
|
<template slot-scope="scope"> |
|
|
|
<div class="op-wrap"> |
|
|
|
<a href="javascript:;" |
|
|
|
v-if="pageCfg.page.operations.indexOf('start') >= 0 && scope.row.can_modify && scope.row.task.canDebug" |
|
|
|
@click="opDebug(scope.row)" |
|
|
|
:class="scope.row.can_modify && scope.row.task.canDebug ? '' : 'disabled'">{{ |
|
|
|
$t('cloudbrainObj.startUse') |
|
|
|
}}</a> |
|
|
|
<a href="javascript:;" v-if="pageCfg.page.operations.indexOf('stop') >= 0" @click="opStop(scope.row)" |
|
|
|
:class="scope.row.can_delete && scope.row.task.canStop ? '' : 'disabled'">{{ $t('cloudbrainObj.stop') |
|
|
|
}}</a> |
|
|
|
<a href="javascript:;" v-if="pageCfg.page.operations.indexOf('delete') >= 0" |
|
|
|
@click="opDelete(scope.row)" |
|
|
|
:class="scope.row.can_delete && scope.row.task.canDelete ? '' : 'disabled'">{{ |
|
|
|
$t('cloudbrainObj.delete') }}</a> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
</el-table> |
|
|
|
</div> |
|
|
|
<div class="list-foot"> |
|
|
|
<el-pagination ref="paginationRef" background @current-change="currentChange" @size-change="sizeChange" |
|
|
|
:current-page.sync="page" :page-sizes="pageSizes" :page-size.sync="pageSize" |
|
|
|
layout="total, sizes, prev, pager, next, jumper" :total="total"> |
|
|
|
</el-pagination> |
|
|
|
</div> |
|
|
|
<div v-if="false" class="foot-tips" v-html="$t('cloudbrainObj.maxTaskTips')"></div> |
|
|
|
</div> |
|
|
|
<div class="empty-page" v-if="!loading && tableData.length == 0"> |
|
|
|
<div class="empty-icon"></div> |
|
|
|
<div class="empty-title">{{ pageCfg.page.emptyTitle }}</div> |
|
|
|
<div class="empty-content"> |
|
|
|
<div v-if="pageCfg.page.emptyTip0 && isRepoEmpty" |
|
|
|
v-html="$t('cloudbrainObj.debugTaskEmptyTip0', { url: `/${repoOwnerName}/${repoName}` })"></div> |
|
|
|
<div v-if="pageCfg.page.emptyTip1" v-html="pageCfg.page.emptyTip1"></div> |
|
|
|
<div v-if="pageCfg.page.emptyTip2" v-html="pageCfg.page.emptyTip2"></div> |
|
|
|
<div v-if="pageCfg.page.emptyTip3" v-html="pageCfg.page.emptyTip3"></div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<LoadingMask :loading="maskLoading" :content="maskLoadingContent"></LoadingMask> |
|
|
|
<el-dialog class="task-already-dlg" :visible.sync="taskAlreadyDialogShow" :lock-scroll="false" :show-close="false"> |
|
|
|
<div class="err-msg-box-already"> |
|
|
|
<div class="msg-content"> |
|
|
|
<i class="ri-information-line"></i> |
|
|
|
<div class="msg-content-tip"> |
|
|
|
<div class="line-1" v-html="$t('cloudbrainObj.sameTaskTips1')"></div> |
|
|
|
<div class="line-2" v-html="$t('cloudbrainObj.sameTaskTips2')"></div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</el-dialog> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
|
|
|
|
<script> |
|
|
|
import LoadingMask from '~/components/cloudbrain/LoadingMask.vue'; |
|
|
|
import { ListPageConfigs, getAiJobLink } from '../configs'; |
|
|
|
import { TABS } from '../configs'; |
|
|
|
import { CloudBrainTools } from '~/pages/cloudbrain/tools'; |
|
|
|
import { CLUSTERS } from '~/const'; |
|
|
|
import { timeSinceUnix, getListValueWithKey } from '~/utils'; |
|
|
|
import { getAiTaskList, getAiTaskDebugUrl, stopAiTask, deleteAiTask } from '~/apis/modules/cloudbrain'; |
|
|
|
|
|
|
|
import relativeTime from 'dayjs/plugin/relativeTime'; |
|
|
|
import localizedFormat from 'dayjs/plugin/localizedFormat'; |
|
|
|
import 'dayjs/locale/zh-cn'; |
|
|
|
import 'dayjs/locale/en'; |
|
|
|
import dayjs from 'dayjs'; |
|
|
|
import { lang } from '~/langs'; |
|
|
|
|
|
|
|
dayjs.locale(lang == 'zh-CN' ? 'zh-cn' : 'en'); |
|
|
|
dayjs.extend(relativeTime); |
|
|
|
dayjs.extend(localizedFormat); |
|
|
|
|
|
|
|
const cloudBrainTools = new CloudBrainTools(); |
|
|
|
|
|
|
|
export default { |
|
|
|
data() { |
|
|
|
return { |
|
|
|
curTab: 'task', |
|
|
|
tabs: [...TABS], |
|
|
|
repoOwnerName: location.pathname.split('/')[1], |
|
|
|
repoName: location.pathname.split('/')[2], |
|
|
|
isRepoEmpty: false, |
|
|
|
sort: '', |
|
|
|
pageCfg: { ...ListPageConfigs }, |
|
|
|
tableData: [], |
|
|
|
page: 1, |
|
|
|
pageSizes: [10], |
|
|
|
pageSize: 10, |
|
|
|
total: 0, |
|
|
|
canCreateTask: false, |
|
|
|
loading: false, |
|
|
|
errorMsgBoxShow: false, |
|
|
|
errorMsg: '', |
|
|
|
maskLoading: false, |
|
|
|
maskLoadingContent: '', |
|
|
|
operating: false, |
|
|
|
taskAlreadyDialogShow: false, |
|
|
|
}; |
|
|
|
}, |
|
|
|
components: { LoadingMask }, |
|
|
|
methods: { |
|
|
|
getTableData() { |
|
|
|
this.loading = true; |
|
|
|
getAiTaskList({ |
|
|
|
repoOwnerName: this.repoOwnerName, |
|
|
|
repoName: this.repoName, |
|
|
|
page: this.page, |
|
|
|
page_size: this.pageSize, |
|
|
|
job_type: this.pageCfg.page.jobType, |
|
|
|
compute_source: this.sort, |
|
|
|
}).then(res => { |
|
|
|
this.loading = false; |
|
|
|
res = res.data; |
|
|
|
if (res.code == 0) { |
|
|
|
const data = res.data; |
|
|
|
this.canCreateTask = data.can_create_task; |
|
|
|
this.isRepoEmpty = data.is_repo_empty; |
|
|
|
this.total = data.total; |
|
|
|
data.tasks.forEach(item => { |
|
|
|
const obj = Object.assign({}, item); |
|
|
|
delete obj.task; |
|
|
|
const task = item.task; |
|
|
|
Object.assign(task, obj); |
|
|
|
task.computeSourceShow = task.compute_source == 'GPU' ? 'CPU/GPU' : task.compute_source; |
|
|
|
task.clusterName = getListValueWithKey(CLUSTERS, task.cluster); |
|
|
|
task.repoOwnerName = this.repoOwnerName; |
|
|
|
task.repoName = this.repoName; |
|
|
|
task.jobLink = `/${this.repoOwnerName}/${this.repoName}/${getAiJobLink(task)}`; |
|
|
|
task.createdFromNow = this.calcFromNow(task.created_unix); |
|
|
|
cloudBrainTools.checkOperation(task); |
|
|
|
}); |
|
|
|
this.tableData = data.tasks || []; |
|
|
|
cloudBrainTools.initRefreshData(this.tableData); |
|
|
|
} |
|
|
|
}).catch(err => { |
|
|
|
this.loading = false; |
|
|
|
console.log(err); |
|
|
|
}); |
|
|
|
}, |
|
|
|
changeSort() { |
|
|
|
this.page = 1; |
|
|
|
this.getTableData(); |
|
|
|
}, |
|
|
|
currentChange(page) { |
|
|
|
this.page = page; |
|
|
|
this.getTableData(); |
|
|
|
}, |
|
|
|
sizeChange(pageSize) { |
|
|
|
this.page = 1; |
|
|
|
this.pageSize = pageSize; |
|
|
|
this.getTableData(); |
|
|
|
}, |
|
|
|
calcFromNow(unix) { |
|
|
|
return timeSinceUnix(unix, Date.now() / 1000); |
|
|
|
}, |
|
|
|
dateFormat(unix) { |
|
|
|
return lang == 'zh-CN' ? dayjs(unix * 1000).format('YYYY年MM月DD日 HH时mm分ss秒') : |
|
|
|
dayjs(unix * 1000).format('ddd, D MMM YYYY HH:mm:ss [CST]'); |
|
|
|
}, |
|
|
|
// operations |
|
|
|
opDebug(row) { |
|
|
|
if (this.operating) return; |
|
|
|
this.operating = true; |
|
|
|
getAiTaskDebugUrl({ |
|
|
|
repoOwnerName: row.task.repoOwnerName, |
|
|
|
repoName: row.task.repoName, |
|
|
|
id: row.task.id, |
|
|
|
}).then(res => { |
|
|
|
this.operating = false; |
|
|
|
res = res.data; |
|
|
|
if (res.code == 0) { |
|
|
|
if (res.data && res.data.url) { |
|
|
|
window.open(res.data.url) |
|
|
|
} |
|
|
|
} else { |
|
|
|
this.$message({ |
|
|
|
type: 'error', |
|
|
|
message: res.msg, |
|
|
|
}); |
|
|
|
} |
|
|
|
}).catch(err => { |
|
|
|
this.operating = false; |
|
|
|
console.log(err); |
|
|
|
}); |
|
|
|
}, |
|
|
|
opStop(row) { |
|
|
|
if (this.operating) return; |
|
|
|
this.operating = true; |
|
|
|
stopAiTask({ |
|
|
|
repoOwnerName: row.task.repoOwnerName, |
|
|
|
repoName: row.task.repoName, |
|
|
|
id: row.task.id, |
|
|
|
}).then(res => { |
|
|
|
this.operating = false; |
|
|
|
res = res.data; |
|
|
|
if (res.code == 0) { |
|
|
|
const data = res.data; |
|
|
|
Object.assign(row.task, data); |
|
|
|
row.task.createdFromNow = this.calcFromNow(row.task.created_unix); |
|
|
|
cloudBrainTools.checkOperation(row.task); |
|
|
|
} else { |
|
|
|
this.$message({ |
|
|
|
type: 'error', |
|
|
|
message: res.msg |
|
|
|
}); |
|
|
|
} |
|
|
|
}).catch(err => { |
|
|
|
this.operating = false; |
|
|
|
}); |
|
|
|
}, |
|
|
|
opDelete(row) { |
|
|
|
if (this.operating) return; |
|
|
|
this.$confirm(this.$t('cloudbrainObj.deleteConfirmTips'), this.$t('tips'), { |
|
|
|
confirmButtonText: this.$t('confirm'), |
|
|
|
cancelButtonText: this.$t('cancel'), |
|
|
|
type: 'warning' |
|
|
|
}).then(() => { |
|
|
|
this.operating = true; |
|
|
|
this.maskLoading = true; |
|
|
|
this.maskLoadingContent = this.$t('cloudbrainObj.deletingTips'); |
|
|
|
deleteAiTask({ |
|
|
|
repoOwnerName: row.task.repoOwnerName, |
|
|
|
repoName: row.task.repoName, |
|
|
|
id: row.task.id, |
|
|
|
}).then(res => { |
|
|
|
this.operating = false; |
|
|
|
this.maskLoading = false; |
|
|
|
if (this.total % this.pageSize == 1 && this.page > 1) { |
|
|
|
this.page -= 1; |
|
|
|
} |
|
|
|
this.getTableData(); |
|
|
|
}).catch(err => { |
|
|
|
this.maskLoading = false; |
|
|
|
this.operating = false; |
|
|
|
this.$message({ |
|
|
|
type: 'error', |
|
|
|
message: this.$t('operationFailed'), |
|
|
|
}); |
|
|
|
}); |
|
|
|
}).catch(() => { |
|
|
|
this.$message({ |
|
|
|
type: 'info', |
|
|
|
message: this.$t('cancelOperate'), |
|
|
|
}); |
|
|
|
}); |
|
|
|
}, |
|
|
|
}, |
|
|
|
beforeMount() { |
|
|
|
// const urlParams = getUrlSearchParams(); |
|
|
|
// const configs = getListPageConfigs(location.href) || {}; |
|
|
|
// this.pageCfg = configs; |
|
|
|
this.getTableData(); |
|
|
|
}, |
|
|
|
mounted() { }, |
|
|
|
beforeDestroy() { }, |
|
|
|
}; |
|
|
|
</script> |
|
|
|
|
|
|
|
<style scoped lang="less"> |
|
|
|
@import '~/components/cloudbrain/cloudbrain.less'; |
|
|
|
|
|
|
|
.container { |
|
|
|
min-height: 350px; |
|
|
|
} |
|
|
|
|
|
|
|
.header { |
|
|
|
margin-bottom: 26px; |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
justify-content: space-between; |
|
|
|
|
|
|
|
.tab-c { |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
|
|
|
|
.tab-item { |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
justify-content: center; |
|
|
|
font-size: 13px; |
|
|
|
color: rgba(0, 0, 0, .87); |
|
|
|
border: 1px solid rgba(34, 36, 38, .15); |
|
|
|
margin-left: -1px; |
|
|
|
height: 38px; |
|
|
|
padding: 0 12px; |
|
|
|
border-left: none; |
|
|
|
|
|
|
|
&.focus { |
|
|
|
color: #0087f5; |
|
|
|
border-color: #0087f5; |
|
|
|
border-left: 1px solid #0087f5; |
|
|
|
} |
|
|
|
|
|
|
|
&:first-child { |
|
|
|
border-radius: 0.28571429rem 0 0 0.28571429rem; |
|
|
|
border-left: 1px solid rgba(34, 36, 38, .15); |
|
|
|
|
|
|
|
&.focus { |
|
|
|
border-color: #0087f5; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
&:last-child { |
|
|
|
border-radius: 0 0.28571429rem 0.28571429rem 0; |
|
|
|
} |
|
|
|
|
|
|
|
&:hover:not(.focus) { |
|
|
|
background: rgba(0, 0, 0, .03); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.right-c { |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.table-container { |
|
|
|
/deep/ .el-table__body { |
|
|
|
td { |
|
|
|
height: 64px; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.dispaly-job-name { |
|
|
|
font-size: 14px; |
|
|
|
// padding-left: 10px; |
|
|
|
font-weight: bold; |
|
|
|
} |
|
|
|
|
|
|
|
.status-wrap { |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
|
|
|
|
i { |
|
|
|
margin-right: 4px; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.creator-wrap { |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
justify-content: center; |
|
|
|
|
|
|
|
img { |
|
|
|
height: 28px; |
|
|
|
width: 28px; |
|
|
|
border-radius: 100%; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.op-wrap { |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
justify-content: center; |
|
|
|
|
|
|
|
a { |
|
|
|
margin: 0 10px; |
|
|
|
font-size: 14px; |
|
|
|
color: #1678c2; |
|
|
|
|
|
|
|
&.disabled { |
|
|
|
color: rgba(0, 0, 0, .87); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.el-dropdown { |
|
|
|
margin: 0 10px; |
|
|
|
color: rgba(0, 0, 0, .87); |
|
|
|
cursor: pointer; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.list-foot { |
|
|
|
text-align: center; |
|
|
|
margin-top: 12px; |
|
|
|
} |
|
|
|
|
|
|
|
.foot-tips { |
|
|
|
margin-top: 2rem; |
|
|
|
color: #888888; |
|
|
|
font-size: 14px; |
|
|
|
|
|
|
|
/deep/ span { |
|
|
|
color: #f2711c; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/deep/ .el-dropdown-menu__item { |
|
|
|
a { |
|
|
|
color: #1678c2; |
|
|
|
} |
|
|
|
|
|
|
|
&.is-disabled { |
|
|
|
color: rgba(0, 0, 0, .87); |
|
|
|
pointer-events: none; |
|
|
|
opacity: 0.45 !important; |
|
|
|
|
|
|
|
a { |
|
|
|
color: rgba(0, 0, 0, .87); |
|
|
|
pointer-events: none; |
|
|
|
opacity: 0.45 !important; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.empty-page { |
|
|
|
display: flex; |
|
|
|
flex-direction: column; |
|
|
|
align-items: center; |
|
|
|
|
|
|
|
.empty-icon { |
|
|
|
height: 100px; |
|
|
|
width: 100px; |
|
|
|
background: url(/img/empty-box.svg) center center no-repeat; |
|
|
|
margin: 2rem 0 1rem; |
|
|
|
scale: 0.8; |
|
|
|
} |
|
|
|
|
|
|
|
.empty-title { |
|
|
|
text-align: center; |
|
|
|
color: #3f3f40; |
|
|
|
font-size: 18px; |
|
|
|
margin-bottom: 1rem; |
|
|
|
} |
|
|
|
|
|
|
|
.empty-content { |
|
|
|
margin: 2rem 0 0; |
|
|
|
|
|
|
|
div { |
|
|
|
font-size: 14px; |
|
|
|
color: #a6a6a6; |
|
|
|
line-height: 22px; |
|
|
|
margin-bottom: 4px; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.task-already-dlg { |
|
|
|
margin-top: 15vh; |
|
|
|
|
|
|
|
/deep/.el-dialog__header { |
|
|
|
display: none; |
|
|
|
} |
|
|
|
|
|
|
|
/deep/.el-dialog__body { |
|
|
|
padding: 0px 0px; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.err-msg-box-already { |
|
|
|
padding: 1em 1.5em; |
|
|
|
background-color: rgba(242, 113, 28, 0.05); |
|
|
|
border: 2px solid rgba(242, 113, 28, 1); |
|
|
|
border-radius: 5px; |
|
|
|
|
|
|
|
.msg-content { |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
|
|
|
|
i { |
|
|
|
font-size: 35px; |
|
|
|
color: rgba(242, 113, 28, 1); |
|
|
|
} |
|
|
|
|
|
|
|
.msg-content-tip { |
|
|
|
text-align: left; |
|
|
|
margin-left: 1rem; |
|
|
|
|
|
|
|
.line-1 { |
|
|
|
font-weight: 600; |
|
|
|
line-height: 2; |
|
|
|
|
|
|
|
span { |
|
|
|
color: rgba(242, 113, 28, 1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.line-2 { |
|
|
|
color: #939393 |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
</style> |