mirror of
https://github.com/crawlab-team/crawlab.git
synced 2026-01-27 17:50:53 +01:00
* 增加Docker开发环境
* 更新Dockerfile构建文件,升级NodeJS依赖版本。 * 遵循ESLint重新格式化代码,修复部分警告 * 登录Token失效增加登出提示 * 网络请求问题增加错误错误提示 * 升级UI依赖库
This commit is contained in:
@@ -10,260 +10,262 @@
|
||||
<!--./tour-->
|
||||
|
||||
<!--tabs-->
|
||||
<el-tabs v-model="activeTabName" @tab-click="onTabClick" type="border-card">
|
||||
<el-tabs v-model="activeTabName" type="border-card" @tab-click="onTabClick">
|
||||
<el-tab-pane :label="$t('Overview')" name="overview">
|
||||
<task-overview @click-log="activeTabName = 'log'"/>
|
||||
<task-overview @click-log="activeTabName = 'log'" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('Log')" name="log">
|
||||
<log-view @search="getTaskLog(true)"/>
|
||||
<log-view @search="getTaskLog(true)" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('Results')" name="results">
|
||||
<div class="button-group">
|
||||
<el-button size="small" class="btn-download" type="primary" icon="el-icon-download" @click="downloadCSV">
|
||||
{{$t('Download CSV')}}
|
||||
{{ $t('Download CSV') }}
|
||||
</el-button>
|
||||
</div>
|
||||
<general-table-view :data="taskResultsData"
|
||||
:columns="taskResultsColumns"
|
||||
:page-num="resultsPageNum"
|
||||
:page-size="resultsPageSize"
|
||||
:total="taskResultsTotalCount"
|
||||
@page-change="onResultsPageChange"/>
|
||||
<general-table-view
|
||||
:data="taskResultsData"
|
||||
:columns="taskResultsColumns"
|
||||
:page-num="resultsPageNum"
|
||||
:page-size="resultsPageSize"
|
||||
:total="taskResultsTotalCount"
|
||||
@page-change="onResultsPageChange"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState,
|
||||
mapGetters
|
||||
} from 'vuex'
|
||||
import TaskOverview from '../../components/Overview/TaskOverview'
|
||||
import GeneralTableView from '../../components/TableView/GeneralTableView'
|
||||
import LogView from '../../components/ScrollView/LogView'
|
||||
import {
|
||||
mapState,
|
||||
mapGetters
|
||||
} from 'vuex'
|
||||
import TaskOverview from '../../components/Overview/TaskOverview'
|
||||
import GeneralTableView from '../../components/TableView/GeneralTableView'
|
||||
import LogView from '../../components/ScrollView/LogView'
|
||||
|
||||
export default {
|
||||
name: 'TaskDetail',
|
||||
components: {
|
||||
LogView,
|
||||
GeneralTableView,
|
||||
TaskOverview
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
activeTabName: 'overview',
|
||||
handle: undefined,
|
||||
export default {
|
||||
name: 'TaskDetail',
|
||||
components: {
|
||||
LogView,
|
||||
GeneralTableView,
|
||||
TaskOverview
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeTabName: 'overview',
|
||||
handle: undefined,
|
||||
|
||||
// tutorial
|
||||
tourSteps: [
|
||||
// overview
|
||||
{
|
||||
target: '.task-info-overview-wrapper',
|
||||
content: this.$t('This is the info of the task detail.'),
|
||||
params: {
|
||||
placement: 'right'
|
||||
// tutorial
|
||||
tourSteps: [
|
||||
// overview
|
||||
{
|
||||
target: '.task-info-overview-wrapper',
|
||||
content: this.$t('This is the info of the task detail.'),
|
||||
params: {
|
||||
placement: 'right'
|
||||
}
|
||||
},
|
||||
{
|
||||
target: '.task-info-spider-wrapper',
|
||||
content: this.$t('This is the spider info of the task.'),
|
||||
params: {
|
||||
placement: 'left'
|
||||
}
|
||||
},
|
||||
{
|
||||
target: '.spider-title',
|
||||
content: this.$t('You can click to view the spider detail for the task.'),
|
||||
params: {
|
||||
placement: 'left'
|
||||
}
|
||||
},
|
||||
{
|
||||
target: '.task-info-node-wrapper',
|
||||
content: this.$t('This is the node info of the task.'),
|
||||
params: {
|
||||
placement: 'left'
|
||||
}
|
||||
},
|
||||
{
|
||||
target: '.node-title',
|
||||
content: this.$t('You can click to view the node detail for the task.'),
|
||||
params: {
|
||||
placement: 'left'
|
||||
}
|
||||
},
|
||||
// log
|
||||
{
|
||||
target: '#tab-log',
|
||||
content: this.$t('Here you can view the log<br> details for the task. The<br> log is automatically updated.')
|
||||
},
|
||||
// results
|
||||
{
|
||||
target: '#tab-results',
|
||||
content: this.$t('Here you can view the results scraped by the spider.<br><br><strong>Note:</strong> If you find your results here are empty, please refer to the <a href="https://docs.crawlab.cn/Integration/" target="_blank" style="color: #409EFF">Documentation (Chinese)</a> about how to integrate your spider into Crawlab.')
|
||||
},
|
||||
{
|
||||
target: '.btn-download',
|
||||
content: this.$t('You can download your results as a CSV file by clicking this button.')
|
||||
}
|
||||
},
|
||||
{
|
||||
target: '.task-info-spider-wrapper',
|
||||
content: this.$t('This is the spider info of the task.'),
|
||||
params: {
|
||||
placement: 'left'
|
||||
],
|
||||
tourCallbacks: {
|
||||
onStop: () => {
|
||||
this.$utils.tour.finishTour('task-detail')
|
||||
},
|
||||
onPreviousStep: (currentStep) => {
|
||||
if (currentStep === 5) {
|
||||
this.activeTabName = 'overview'
|
||||
} else if (currentStep === 6) {
|
||||
this.activeTabName = 'log'
|
||||
}
|
||||
this.$utils.tour.prevStep('task-detail', currentStep)
|
||||
},
|
||||
onNextStep: (currentStep) => {
|
||||
if (currentStep === 4) {
|
||||
this.activeTabName = 'log'
|
||||
} else if (currentStep === 5) {
|
||||
this.activeTabName = 'results'
|
||||
}
|
||||
this.$utils.tour.nextStep('task-detail', currentStep)
|
||||
}
|
||||
},
|
||||
{
|
||||
target: '.spider-title',
|
||||
content: this.$t('You can click to view the spider detail for the task.'),
|
||||
params: {
|
||||
placement: 'left'
|
||||
}
|
||||
},
|
||||
{
|
||||
target: '.task-info-node-wrapper',
|
||||
content: this.$t('This is the node info of the task.'),
|
||||
params: {
|
||||
placement: 'left'
|
||||
}
|
||||
},
|
||||
{
|
||||
target: '.node-title',
|
||||
content: this.$t('You can click to view the node detail for the task.'),
|
||||
params: {
|
||||
placement: 'left'
|
||||
}
|
||||
},
|
||||
// log
|
||||
{
|
||||
target: '#tab-log',
|
||||
content: this.$t('Here you can view the log<br> details for the task. The<br> log is automatically updated.')
|
||||
},
|
||||
// results
|
||||
{
|
||||
target: '#tab-results',
|
||||
content: this.$t('Here you can view the results scraped by the spider.<br><br><strong>Note:</strong> If you find your results here are empty, please refer to the <a href="https://docs.crawlab.cn/Integration/" target="_blank" style="color: #409EFF">Documentation (Chinese)</a> about how to integrate your spider into Crawlab.')
|
||||
},
|
||||
{
|
||||
target: '.btn-download',
|
||||
content: this.$t('You can download your results as a CSV file by clicking this button.')
|
||||
}
|
||||
],
|
||||
tourCallbacks: {
|
||||
onStop: () => {
|
||||
this.$utils.tour.finishTour('task-detail')
|
||||
},
|
||||
onPreviousStep: (currentStep) => {
|
||||
if (currentStep === 5) {
|
||||
this.activeTabName = 'overview'
|
||||
} else if (currentStep === 6) {
|
||||
this.activeTabName = 'log'
|
||||
}
|
||||
this.$utils.tour.prevStep('task-detail', currentStep)
|
||||
},
|
||||
onNextStep: (currentStep) => {
|
||||
if (currentStep === 4) {
|
||||
this.activeTabName = 'log'
|
||||
} else if (currentStep === 5) {
|
||||
this.activeTabName = 'results'
|
||||
}
|
||||
this.$utils.tour.nextStep('task-detail', currentStep)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('task', [
|
||||
'taskForm',
|
||||
'taskResultsData',
|
||||
'taskResultsTotalCount',
|
||||
'taskLog',
|
||||
'logKeyword',
|
||||
'isLogAutoFetch',
|
||||
'currentLogIndex',
|
||||
'activeErrorLogItem'
|
||||
]),
|
||||
...mapGetters('task', [
|
||||
'taskResultsColumns',
|
||||
'logData'
|
||||
]),
|
||||
...mapState('file', [
|
||||
'currentPath'
|
||||
]),
|
||||
...mapState('deploy', [
|
||||
'deployList'
|
||||
]),
|
||||
resultsPageNum: {
|
||||
get () {
|
||||
return this.$store.state.task.resultsPageNum
|
||||
},
|
||||
computed: {
|
||||
...mapState('task', [
|
||||
'taskForm',
|
||||
'taskResultsData',
|
||||
'taskResultsTotalCount',
|
||||
'taskLog',
|
||||
'logKeyword',
|
||||
'isLogAutoFetch',
|
||||
'currentLogIndex',
|
||||
'activeErrorLogItem'
|
||||
]),
|
||||
...mapGetters('task', [
|
||||
'taskResultsColumns',
|
||||
'logData'
|
||||
]),
|
||||
...mapState('file', [
|
||||
'currentPath'
|
||||
]),
|
||||
...mapState('deploy', [
|
||||
'deployList'
|
||||
]),
|
||||
resultsPageNum: {
|
||||
get() {
|
||||
return this.$store.state.task.resultsPageNum
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('task/SET_RESULTS_PAGE_NUM', value)
|
||||
}
|
||||
},
|
||||
set (value) {
|
||||
this.$store.commit('task/SET_RESULTS_PAGE_NUM', value)
|
||||
}
|
||||
},
|
||||
resultsPageSize: {
|
||||
get () {
|
||||
return this.$store.state.task.resultsPageSize
|
||||
resultsPageSize: {
|
||||
get() {
|
||||
return this.$store.state.task.resultsPageSize
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('task/SET_RESULTS_PAGE_SIZE', value)
|
||||
}
|
||||
},
|
||||
set (value) {
|
||||
this.$store.commit('task/SET_RESULTS_PAGE_SIZE', value)
|
||||
}
|
||||
},
|
||||
isLogAutoScroll: {
|
||||
get () {
|
||||
return this.$store.state.task.isLogAutoScroll
|
||||
isLogAutoScroll: {
|
||||
get() {
|
||||
return this.$store.state.task.isLogAutoScroll
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('task/SET_IS_LOG_AUTO_SCROLL', value)
|
||||
}
|
||||
},
|
||||
set (value) {
|
||||
this.$store.commit('task/SET_IS_LOG_AUTO_SCROLL', value)
|
||||
}
|
||||
},
|
||||
isLogAutoFetch: {
|
||||
get () {
|
||||
return this.$store.state.task.isLogAutoFetch
|
||||
isLogAutoFetch: {
|
||||
get() {
|
||||
return this.$store.state.task.isLogAutoFetch
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('task/SET_IS_LOG_AUTO_FETCH', value)
|
||||
}
|
||||
},
|
||||
set (value) {
|
||||
this.$store.commit('task/SET_IS_LOG_AUTO_FETCH', value)
|
||||
}
|
||||
},
|
||||
isLogFetchLoading: {
|
||||
get () {
|
||||
return this.$store.state.task.isLogFetchLoading
|
||||
isLogFetchLoading: {
|
||||
get() {
|
||||
return this.$store.state.task.isLogFetchLoading
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('task/SET_IS_LOG_FETCH_LOADING', value)
|
||||
}
|
||||
},
|
||||
set (value) {
|
||||
this.$store.commit('task/SET_IS_LOG_FETCH_LOADING', value)
|
||||
}
|
||||
},
|
||||
currentLogIndex: {
|
||||
get () {
|
||||
return this.$store.state.task.currentLogIndex
|
||||
currentLogIndex: {
|
||||
get() {
|
||||
return this.$store.state.task.currentLogIndex
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('task/SET_CURRENT_LOG_INDEX', value)
|
||||
}
|
||||
},
|
||||
set (value) {
|
||||
this.$store.commit('task/SET_CURRENT_LOG_INDEX', value)
|
||||
logIndexMap() {
|
||||
const map = new Map()
|
||||
this.logData.forEach((d, index) => {
|
||||
map.set(d._id, index)
|
||||
})
|
||||
return map
|
||||
},
|
||||
isRunning() {
|
||||
return ['pending', 'running'].includes(this.taskForm.status)
|
||||
}
|
||||
},
|
||||
logIndexMap () {
|
||||
const map = new Map()
|
||||
this.logData.forEach((d, index) => {
|
||||
map.set(d._id, index)
|
||||
})
|
||||
return map
|
||||
},
|
||||
isRunning () {
|
||||
return ['pending', 'running'].includes(this.taskForm.status)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onTabClick (tab) {
|
||||
this.$st.sendEv('任务详情', '切换标签', tab.name)
|
||||
},
|
||||
onSpiderChange (id) {
|
||||
this.$router.push(`/spiders/${id}`)
|
||||
},
|
||||
onResultsPageChange (payload) {
|
||||
const { pageNum, pageSize } = payload
|
||||
this.resultsPageNum = pageNum
|
||||
this.resultsPageSize = pageSize
|
||||
this.$store.dispatch('task/getTaskResults', this.$route.params.id)
|
||||
},
|
||||
downloadCSV () {
|
||||
this.$store.dispatch('task/getTaskResultExcel', this.$route.params.id)
|
||||
this.$st.sendEv('任务详情', '结果', '下载CSV')
|
||||
},
|
||||
async getTaskLog (showLoading) {
|
||||
if (showLoading) {
|
||||
this.isLogFetchLoading = true
|
||||
}
|
||||
await this.$store.dispatch('task/getTaskLog', { id: this.$route.params.id, keyword: this.logKeyword })
|
||||
this.currentLogIndex = (this.logIndexMap.get(this.activeErrorLogItem.log_id) + 1) || 0
|
||||
this.isLogFetchLoading = false
|
||||
await this.$store.dispatch('task/getTaskErrorLog', this.$route.params.id)
|
||||
}
|
||||
},
|
||||
async created () {
|
||||
await this.$store.dispatch('task/getTaskData', this.$route.params.id)
|
||||
async created() {
|
||||
await this.$store.dispatch('task/getTaskData', this.$route.params.id)
|
||||
|
||||
this.isLogAutoFetch = !!this.isRunning
|
||||
this.isLogAutoScroll = !!this.isRunning
|
||||
this.isLogAutoFetch = !!this.isRunning
|
||||
this.isLogAutoScroll = !!this.isRunning
|
||||
|
||||
await this.$store.dispatch('task/getTaskResults', this.$route.params.id)
|
||||
await this.$store.dispatch('task/getTaskResults', this.$route.params.id)
|
||||
|
||||
this.getTaskLog()
|
||||
this.handle = setInterval(() => {
|
||||
if (this.isLogAutoFetch) {
|
||||
this.$store.dispatch('task/getTaskData', this.$route.params.id)
|
||||
this.getTaskLog()
|
||||
this.handle = setInterval(() => {
|
||||
if (this.isLogAutoFetch) {
|
||||
this.$store.dispatch('task/getTaskData', this.$route.params.id)
|
||||
this.$store.dispatch('task/getTaskResults', this.$route.params.id)
|
||||
this.getTaskLog()
|
||||
}
|
||||
}, 5000)
|
||||
},
|
||||
mounted() {
|
||||
if (!this.$utils.tour.isFinishedTour('task-detail')) {
|
||||
this.$utils.tour.startTour(this, 'task-detail')
|
||||
}
|
||||
},
|
||||
destroyed() {
|
||||
clearInterval(this.handle)
|
||||
},
|
||||
methods: {
|
||||
onTabClick(tab) {
|
||||
this.$st.sendEv('任务详情', '切换标签', tab.name)
|
||||
},
|
||||
onSpiderChange(id) {
|
||||
this.$router.push(`/spiders/${id}`)
|
||||
},
|
||||
onResultsPageChange(payload) {
|
||||
const { pageNum, pageSize } = payload
|
||||
this.resultsPageNum = pageNum
|
||||
this.resultsPageSize = pageSize
|
||||
this.$store.dispatch('task/getTaskResults', this.$route.params.id)
|
||||
this.getTaskLog()
|
||||
},
|
||||
downloadCSV() {
|
||||
this.$store.dispatch('task/getTaskResultExcel', this.$route.params.id)
|
||||
this.$st.sendEv('任务详情', '结果', '下载CSV')
|
||||
},
|
||||
async getTaskLog(showLoading) {
|
||||
if (showLoading) {
|
||||
this.isLogFetchLoading = true
|
||||
}
|
||||
await this.$store.dispatch('task/getTaskLog', { id: this.$route.params.id, keyword: this.logKeyword })
|
||||
this.currentLogIndex = (this.logIndexMap.get(this.activeErrorLogItem.log_id) + 1) || 0
|
||||
this.isLogFetchLoading = false
|
||||
await this.$store.dispatch('task/getTaskErrorLog', this.$route.params.id)
|
||||
}
|
||||
}, 5000)
|
||||
},
|
||||
mounted () {
|
||||
if (!this.$utils.tour.isFinishedTour('task-detail')) {
|
||||
this.$utils.tour.startTour(this, 'task-detail')
|
||||
}
|
||||
},
|
||||
destroyed () {
|
||||
clearInterval(this.handle)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -16,32 +16,37 @@
|
||||
<el-form class="filter-form" :model="filter" label-width="100px" label-position="right" inline>
|
||||
<el-form-item prop="node_id" :label="$t('Node')">
|
||||
<el-select v-model="filter.node_id" size="small" :placeholder="$t('Node')" @change="onFilterChange">
|
||||
<el-option value="" :label="$t('All')"/>
|
||||
<el-option v-for="node in nodeList" :key="node._id" :value="node._id" :label="node.name"/>
|
||||
<el-option value="" :label="$t('All')" />
|
||||
<el-option v-for="node in nodeList" :key="node._id" :value="node._id" :label="node.name" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item prop="spider_id" :label="$t('Spider')">
|
||||
<el-select v-model="filter.spider_id" size="small" :placeholder="$t('Spider')" @change="onFilterChange"
|
||||
:disabled="isFilterSpiderDisabled">
|
||||
<el-option value="" :label="$t('All')"/>
|
||||
<el-option v-for="spider in spiderList" :key="spider._id" :value="spider._id" :label="spider.name"/>
|
||||
<el-select
|
||||
v-model="filter.spider_id"
|
||||
size="small"
|
||||
:placeholder="$t('Spider')"
|
||||
:disabled="isFilterSpiderDisabled"
|
||||
@change="onFilterChange"
|
||||
>
|
||||
<el-option value="" :label="$t('All')" />
|
||||
<el-option v-for="spider in spiderList" :key="spider._id" :value="spider._id" :label="spider.name" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item prop="status" :label="$t('Status')">
|
||||
<el-select v-model="filter.status" size="small" :placeholder="$t('Status')" @change="onFilterChange">
|
||||
<el-option value="" :label="$t('All')"></el-option>
|
||||
<el-option value="pending" :label="$t('Pending')"></el-option>
|
||||
<el-option value="running" :label="$t('Running')"></el-option>
|
||||
<el-option value="finished" :label="$t('Finished')"></el-option>
|
||||
<el-option value="error" :label="$t('Error')"></el-option>
|
||||
<el-option value="cancelled" :label="$t('Cancelled')"></el-option>
|
||||
<el-option value="abnormal" :label="$t('Abnormal')"></el-option>
|
||||
<el-option value="" :label="$t('All')" />
|
||||
<el-option value="pending" :label="$t('Pending')" />
|
||||
<el-option value="running" :label="$t('Running')" />
|
||||
<el-option value="finished" :label="$t('Finished')" />
|
||||
<el-option value="error" :label="$t('Error')" />
|
||||
<el-option value="cancelled" :label="$t('Cancelled')" />
|
||||
<el-option value="abnormal" :label="$t('Abnormal')" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="right">
|
||||
<el-button class="btn-delete" @click="onRemoveMultipleTask" size="small" type="danger">
|
||||
<el-button class="btn-delete" size="small" type="danger" @click="onRemoveMultipleTask">
|
||||
删除任务
|
||||
</el-button>
|
||||
</div>
|
||||
@@ -49,13 +54,13 @@
|
||||
<!--./filter-->
|
||||
|
||||
<!--legend-->
|
||||
<status-legend/>
|
||||
<status-legend />
|
||||
<!--./legend-->
|
||||
|
||||
<!--table list-->
|
||||
<el-table
|
||||
:data="filteredTableData"
|
||||
ref="table"
|
||||
:data="filteredTableData"
|
||||
class="table"
|
||||
:header-cell-style="{background:'rgb(48, 65, 86)',color:'white'}"
|
||||
border
|
||||
@@ -63,76 +68,89 @@
|
||||
@row-click="onRowClick"
|
||||
@selection-change="onSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="45" align="center" reserve-selection/>
|
||||
<el-table-column type="selection" width="45" align="center" reserve-selection />
|
||||
<template v-for="col in columns">
|
||||
<el-table-column v-if="col.name === 'spider_name'"
|
||||
:key="col.name"
|
||||
:label="$t(col.label)"
|
||||
:sortable="col.sortable"
|
||||
:align="col.align"
|
||||
<el-table-column
|
||||
v-if="col.name === 'spider_name'"
|
||||
:key="col.name"
|
||||
:label="$t(col.label)"
|
||||
:sortable="col.sortable"
|
||||
:align="col.align"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<a href="javascript:" class="a-tag" @click="onClickSpider(scope.row)">{{scope.row[col.name]}}</a>
|
||||
<a href="javascript:" class="a-tag" @click="onClickSpider(scope.row)">{{ scope.row[col.name] }}</a>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-else-if="col.name.match(/_ts$/)"
|
||||
:key="col.name"
|
||||
:label="$t(col.label)"
|
||||
:sortable="col.sortable"
|
||||
:align="col.align"
|
||||
:width="col.width">
|
||||
<el-table-column
|
||||
v-else-if="col.name.match(/_ts$/)"
|
||||
:key="col.name"
|
||||
:label="$t(col.label)"
|
||||
:sortable="col.sortable"
|
||||
:align="col.align"
|
||||
:width="col.width"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{getTime(scope.row[col.name])}}
|
||||
{{ getTime(scope.row[col.name]) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-else-if="col.name === 'wait_duration'"
|
||||
:key="col.name"
|
||||
:label="$t(col.label)"
|
||||
:sortable="col.sortable"
|
||||
:align="col.align"
|
||||
:width="col.width">
|
||||
<el-table-column
|
||||
v-else-if="col.name === 'wait_duration'"
|
||||
:key="col.name"
|
||||
:label="$t(col.label)"
|
||||
:sortable="col.sortable"
|
||||
:align="col.align"
|
||||
:width="col.width"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{getWaitDuration(scope.row)}}
|
||||
{{ getWaitDuration(scope.row) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-else-if="col.name === 'runtime_duration'"
|
||||
:key="col.name"
|
||||
:label="$t(col.label)"
|
||||
:sortable="col.sortable"
|
||||
:align="col.align"
|
||||
:width="col.width">
|
||||
<el-table-column
|
||||
v-else-if="col.name === 'runtime_duration'"
|
||||
:key="col.name"
|
||||
:label="$t(col.label)"
|
||||
:sortable="col.sortable"
|
||||
:align="col.align"
|
||||
:width="col.width"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{getRuntimeDuration(scope.row)}}
|
||||
{{ getRuntimeDuration(scope.row) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-else-if="col.name === 'total_duration'"
|
||||
:key="col.name"
|
||||
:label="$t(col.label)"
|
||||
:sortable="col.sortable"
|
||||
:align="col.align"
|
||||
:width="col.width">
|
||||
<el-table-column
|
||||
v-else-if="col.name === 'total_duration'"
|
||||
:key="col.name"
|
||||
:label="$t(col.label)"
|
||||
:sortable="col.sortable"
|
||||
:align="col.align"
|
||||
:width="col.width"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{getTotalDuration(scope.row)}}
|
||||
{{ getTotalDuration(scope.row) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-else-if="col.name === 'node_name'"
|
||||
:key="col.name"
|
||||
:label="$t(col.label)"
|
||||
:sortable="col.sortable"
|
||||
:align="col.align"
|
||||
:width="col.width">
|
||||
<el-table-column
|
||||
v-else-if="col.name === 'node_name'"
|
||||
:key="col.name"
|
||||
:label="$t(col.label)"
|
||||
:sortable="col.sortable"
|
||||
:align="col.align"
|
||||
:width="col.width"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<a href="javascript:" class="a-tag" @click="onClickNode(scope.row)">{{scope.row[col.name]}}</a>
|
||||
<a href="javascript:" class="a-tag" @click="onClickNode(scope.row)">{{ scope.row[col.name] }}</a>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-else-if="col.name === 'status'"
|
||||
:key="col.name"
|
||||
:label="$t(col.label)"
|
||||
:sortable="col.sortable"
|
||||
:align="col.align"
|
||||
:width="col.width">
|
||||
<el-table-column
|
||||
v-else-if="col.name === 'status'"
|
||||
:key="col.name"
|
||||
:label="$t(col.label)"
|
||||
:sortable="col.sortable"
|
||||
:align="col.align"
|
||||
:width="col.width"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<status-tag :status="scope.row[col.name]"/>
|
||||
<status-tag :status="scope.row[col.name]" />
|
||||
<template
|
||||
v-if="scope.row.error_log_count > 0"
|
||||
>
|
||||
@@ -141,48 +159,57 @@
|
||||
type="danger"
|
||||
style="margin-left: 10px"
|
||||
>
|
||||
<i class="el-icon-warning"></i>
|
||||
<i class="el-icon-tickets"></i>
|
||||
<i class="el-icon-warning" />
|
||||
<i class="el-icon-tickets" />
|
||||
</el-tag>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-else
|
||||
:key="col.name"
|
||||
:property="col.name"
|
||||
:label="$t(col.label)"
|
||||
:sortable="col.sortable"
|
||||
:align="col.align"
|
||||
:width="col.width">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-else
|
||||
:key="col.name"
|
||||
:property="col.name"
|
||||
:label="$t(col.label)"
|
||||
:sortable="col.sortable"
|
||||
:align="col.align"
|
||||
:width="col.width"
|
||||
/>
|
||||
</template>
|
||||
<el-table-column :label="$t('Action')" align="left" fixed="right" width="150px">
|
||||
<template slot-scope="scope">
|
||||
<el-tooltip :content="$t('View')" placement="top">
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="onView(scope.row)"></el-button>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="onView(scope.row)" />
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="$t('Restart')" placement="top">
|
||||
<el-button type="warning" icon="el-icon-refresh" size="mini"
|
||||
@click="onRestart(scope.row, $event)"></el-button>
|
||||
<el-button
|
||||
type="warning"
|
||||
icon="el-icon-refresh"
|
||||
size="mini"
|
||||
@click="onRestart(scope.row, $event)"
|
||||
/>
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="$t('Remove')" placement="top">
|
||||
<el-button type="danger" icon="el-icon-delete" size="mini"
|
||||
@click="onRemove(scope.row, $event)"></el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
icon="el-icon-delete"
|
||||
size="mini"
|
||||
@click="onRemove(scope.row, $event)"
|
||||
/>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="pagination">
|
||||
<el-pagination
|
||||
@current-change="onPageChange"
|
||||
@size-change="onPageChange"
|
||||
:current-page.sync="pageNum"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:page-size.sync="pageSize"
|
||||
layout="sizes, prev, pager, next"
|
||||
:total="taskListTotalCount">
|
||||
</el-pagination>
|
||||
:total="taskListTotalCount"
|
||||
@current-change="onPageChange"
|
||||
@size-change="onPageChange"
|
||||
/>
|
||||
</div>
|
||||
<!--./table list-->
|
||||
</el-card>
|
||||
@@ -190,274 +217,274 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from 'vuex'
|
||||
import dayjs from 'dayjs'
|
||||
import StatusTag from '../../components/Status/StatusTag'
|
||||
import StatusLegend from '../../components/Status/StatusLegend'
|
||||
import {
|
||||
mapState
|
||||
} from 'vuex'
|
||||
import dayjs from 'dayjs'
|
||||
import StatusTag from '../../components/Status/StatusTag'
|
||||
import StatusLegend from '../../components/Status/StatusLegend'
|
||||
|
||||
export default {
|
||||
name: 'TaskList',
|
||||
components: { StatusLegend, StatusTag },
|
||||
data () {
|
||||
return {
|
||||
// setInterval handle
|
||||
handle: undefined,
|
||||
export default {
|
||||
name: 'TaskList',
|
||||
components: { StatusLegend, StatusTag },
|
||||
data() {
|
||||
return {
|
||||
// setInterval handle
|
||||
handle: undefined,
|
||||
|
||||
// determine if is edit mode
|
||||
isEditMode: false,
|
||||
// determine if is edit mode
|
||||
isEditMode: false,
|
||||
|
||||
// dialog visibility
|
||||
dialogVisible: false,
|
||||
// dialog visibility
|
||||
dialogVisible: false,
|
||||
|
||||
// table columns
|
||||
columns: [
|
||||
{ name: 'node_name', label: 'Node', width: '120' },
|
||||
{ name: 'spider_name', label: 'Spider', width: '120' },
|
||||
{ name: 'status', label: 'Status', width: '180' },
|
||||
{ name: 'param', label: 'Parameters', width: '120' },
|
||||
// { name: 'create_ts', label: 'Create Time', width: '100' },
|
||||
{ name: 'start_ts', label: 'Start Time', width: '100' },
|
||||
{ name: 'finish_ts', label: 'Finish Time', width: '100' },
|
||||
{ name: 'wait_duration', label: 'Wait Duration (sec)', align: 'right' },
|
||||
{ name: 'runtime_duration', label: 'Runtime Duration (sec)', align: 'right' },
|
||||
{ name: 'total_duration', label: 'Total Duration (sec)', width: '80', align: 'right' },
|
||||
{ name: 'result_count', label: 'Results Count', width: '80' },
|
||||
{ name: 'username', label: 'Owner', width: '100' }
|
||||
// table columns
|
||||
columns: [
|
||||
{ name: 'node_name', label: 'Node', width: '120' },
|
||||
{ name: 'spider_name', label: 'Spider', width: '120' },
|
||||
{ name: 'status', label: 'Status', width: '180' },
|
||||
{ name: 'param', label: 'Parameters', width: '120' },
|
||||
// { name: 'create_ts', label: 'Create Time', width: '100' },
|
||||
{ name: 'start_ts', label: 'Start Time', width: '100' },
|
||||
{ name: 'finish_ts', label: 'Finish Time', width: '100' },
|
||||
{ name: 'wait_duration', label: 'Wait Duration (sec)', align: 'right' },
|
||||
{ name: 'runtime_duration', label: 'Runtime Duration (sec)', align: 'right' },
|
||||
{ name: 'total_duration', label: 'Total Duration (sec)', width: '80', align: 'right' },
|
||||
{ name: 'result_count', label: 'Results Count', width: '80' },
|
||||
{ name: 'username', label: 'Owner', width: '100' }
|
||||
// { name: 'avg_num_results', label: 'Average Results Count per Second', width: '80' }
|
||||
],
|
||||
],
|
||||
|
||||
multipleSelection: [],
|
||||
multipleSelection: [],
|
||||
|
||||
// tutorial
|
||||
tourSteps: [
|
||||
{
|
||||
target: '.filter-form',
|
||||
content: this.$t('You can filter tasks from this area.')
|
||||
},
|
||||
{
|
||||
target: '.table',
|
||||
content: this.$t('This is a list of spider tasks executed sorted in a time descending order.')
|
||||
},
|
||||
{
|
||||
target: '.table .el-table__body-wrapper tr:nth-child(1)',
|
||||
content: this.$t('Click the row to or the view button to view the task detail.')
|
||||
},
|
||||
{
|
||||
target: '.table tr td:nth-child(1)',
|
||||
content: this.$t('Tick and select the tasks you would like to delete in batches.'),
|
||||
params: {
|
||||
placement: 'right'
|
||||
}
|
||||
},
|
||||
{
|
||||
target: '.btn-delete',
|
||||
content: this.$t('Click this button to delete selected tasks.'),
|
||||
params: {
|
||||
placement: 'left'
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
tourCallbacks: {
|
||||
onStop: () => {
|
||||
this.$utils.tour.finishTour('task-list')
|
||||
},
|
||||
onPreviousStep: (currentStep) => {
|
||||
this.$utils.tour.prevStep('task-list', currentStep)
|
||||
},
|
||||
onNextStep: (currentStep) => {
|
||||
this.$utils.tour.nextStep('task-list', currentStep)
|
||||
}
|
||||
},
|
||||
|
||||
isFilterSpiderDisabled: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('task', [
|
||||
'filter',
|
||||
'taskList',
|
||||
'taskListTotalCount',
|
||||
'taskForm'
|
||||
]),
|
||||
...mapState('spider', [
|
||||
'spiderList'
|
||||
]),
|
||||
...mapState('node', [
|
||||
'nodeList'
|
||||
]),
|
||||
pageNum: {
|
||||
get () {
|
||||
return this.$store.state.task.pageNum
|
||||
},
|
||||
set (value) {
|
||||
this.$store.commit('task/SET_PAGE_NUM', value)
|
||||
}
|
||||
},
|
||||
pageSize: {
|
||||
get () {
|
||||
return this.$store.state.task.pageSize
|
||||
},
|
||||
set (value) {
|
||||
this.$store.commit('task/SET_PAGE_SIZE', value)
|
||||
}
|
||||
},
|
||||
filteredTableData () {
|
||||
return this.taskList
|
||||
.map(d => d)
|
||||
.sort((a, b) => a.create_ts < b.create_ts ? 1 : -1)
|
||||
.filter(d => {
|
||||
// keyword
|
||||
if (!this.filter.keyword) return true
|
||||
for (let i = 0; i < this.columns.length; i++) {
|
||||
const colName = this.columns[i].name
|
||||
if (d[colName] && d[colName].toLowerCase().indexOf(this.filter.keyword.toLowerCase()) > -1) {
|
||||
return true
|
||||
// tutorial
|
||||
tourSteps: [
|
||||
{
|
||||
target: '.filter-form',
|
||||
content: this.$t('You can filter tasks from this area.')
|
||||
},
|
||||
{
|
||||
target: '.table',
|
||||
content: this.$t('This is a list of spider tasks executed sorted in a time descending order.')
|
||||
},
|
||||
{
|
||||
target: '.table .el-table__body-wrapper tr:nth-child(1)',
|
||||
content: this.$t('Click the row to or the view button to view the task detail.')
|
||||
},
|
||||
{
|
||||
target: '.table tr td:nth-child(1)',
|
||||
content: this.$t('Tick and select the tasks you would like to delete in batches.'),
|
||||
params: {
|
||||
placement: 'right'
|
||||
}
|
||||
},
|
||||
{
|
||||
target: '.btn-delete',
|
||||
content: this.$t('Click this button to delete selected tasks.'),
|
||||
params: {
|
||||
placement: 'left'
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onSearch (value) {
|
||||
},
|
||||
onRefresh () {
|
||||
this.$store.dispatch('task/getTaskList')
|
||||
this.$st.sendEv('任务列表', '搜索')
|
||||
},
|
||||
onRemoveMultipleTask () {
|
||||
if (this.multipleSelection.length === 0) {
|
||||
this.$message({
|
||||
type: 'error',
|
||||
message: '请选择要删除的任务'
|
||||
})
|
||||
return
|
||||
}
|
||||
this.$confirm('确定删除任务', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
let ids = this.multipleSelection.map(item => item._id)
|
||||
this.$store.dispatch('task/deleteTaskMultiple', ids).then((resp) => {
|
||||
if (resp.data.status === 'ok') {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '删除任务成功'
|
||||
})
|
||||
this.$store.dispatch('task/getTaskList')
|
||||
this.$refs['table'].clearSelection()
|
||||
return
|
||||
],
|
||||
|
||||
tourCallbacks: {
|
||||
onStop: () => {
|
||||
this.$utils.tour.finishTour('task-list')
|
||||
},
|
||||
onPreviousStep: (currentStep) => {
|
||||
this.$utils.tour.prevStep('task-list', currentStep)
|
||||
},
|
||||
onNextStep: (currentStep) => {
|
||||
this.$utils.tour.nextStep('task-list', currentStep)
|
||||
}
|
||||
},
|
||||
|
||||
isFilterSpiderDisabled: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('task', [
|
||||
'filter',
|
||||
'taskList',
|
||||
'taskListTotalCount',
|
||||
'taskForm'
|
||||
]),
|
||||
...mapState('spider', [
|
||||
'spiderList'
|
||||
]),
|
||||
...mapState('node', [
|
||||
'nodeList'
|
||||
]),
|
||||
pageNum: {
|
||||
get() {
|
||||
return this.$store.state.task.pageNum
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('task/SET_PAGE_NUM', value)
|
||||
}
|
||||
},
|
||||
pageSize: {
|
||||
get() {
|
||||
return this.$store.state.task.pageSize
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('task/SET_PAGE_SIZE', value)
|
||||
}
|
||||
},
|
||||
filteredTableData() {
|
||||
return this.taskList
|
||||
.map(d => d)
|
||||
.sort((a, b) => a.create_ts < b.create_ts ? 1 : -1)
|
||||
.filter(d => {
|
||||
// keyword
|
||||
if (!this.filter.keyword) return true
|
||||
for (let i = 0; i < this.columns.length; i++) {
|
||||
const colName = this.columns[i].name
|
||||
if (d[colName] && d[colName].toLowerCase().indexOf(this.filter.keyword.toLowerCase()) > -1) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$store.dispatch('task/getTaskList')
|
||||
this.$store.dispatch('spider/getSpiderList')
|
||||
this.$store.dispatch('node/getNodeList')
|
||||
},
|
||||
mounted() {
|
||||
this.handle = setInterval(() => {
|
||||
this.$store.dispatch('task/getTaskList')
|
||||
}, 5000)
|
||||
|
||||
if (!this.$utils.tour.isFinishedTour('task-list')) {
|
||||
this.$utils.tour.startTour(this, 'task-list')
|
||||
}
|
||||
},
|
||||
destroyed() {
|
||||
clearInterval(this.handle)
|
||||
},
|
||||
methods: {
|
||||
onSearch(value) {
|
||||
},
|
||||
onRefresh() {
|
||||
this.$store.dispatch('task/getTaskList')
|
||||
this.$st.sendEv('任务列表', '搜索')
|
||||
},
|
||||
onRemoveMultipleTask() {
|
||||
if (this.multipleSelection.length === 0) {
|
||||
this.$message({
|
||||
type: 'error',
|
||||
message: resp.data.error
|
||||
message: '请选择要删除的任务'
|
||||
})
|
||||
return
|
||||
}
|
||||
this.$confirm('确定删除任务', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
const ids = this.multipleSelection.map(item => item._id)
|
||||
this.$store.dispatch('task/deleteTaskMultiple', ids).then((resp) => {
|
||||
if (resp.data.status === 'ok') {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: '删除任务成功'
|
||||
})
|
||||
this.$store.dispatch('task/getTaskList')
|
||||
this.$refs['table'].clearSelection()
|
||||
return
|
||||
}
|
||||
this.$message({
|
||||
type: 'error',
|
||||
message: resp.data.error
|
||||
})
|
||||
})
|
||||
}).catch(() => {
|
||||
})
|
||||
}).catch(() => {
|
||||
})
|
||||
},
|
||||
onRemove (row, ev) {
|
||||
ev.stopPropagation()
|
||||
this.$confirm(this.$t('Are you sure to delete this task?'), this.$t('Notification'), {
|
||||
confirmButtonText: this.$t('Confirm'),
|
||||
cancelButtonText: this.$t('Cancel'),
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.$store.dispatch('task/deleteTask', row._id)
|
||||
.then(() => {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: this.$t('Deleted successfully')
|
||||
},
|
||||
onRemove(row, ev) {
|
||||
ev.stopPropagation()
|
||||
this.$confirm(this.$t('Are you sure to delete this task?'), this.$t('Notification'), {
|
||||
confirmButtonText: this.$t('Confirm'),
|
||||
cancelButtonText: this.$t('Cancel'),
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.$store.dispatch('task/deleteTask', row._id)
|
||||
.then(() => {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: this.$t('Deleted successfully')
|
||||
})
|
||||
})
|
||||
})
|
||||
this.$st.sendEv('任务列表', '删除任务')
|
||||
})
|
||||
},
|
||||
onRestart (row, ev) {
|
||||
ev.stopPropagation()
|
||||
this.$confirm(this.$t('Are you sure to restart this task?'), this.$t('Notification'), {
|
||||
confirmButtonText: this.$t('Confirm'),
|
||||
cancelButtonText: this.$t('Cancel'),
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.$store.dispatch('task/restartTask', row._id)
|
||||
.then(() => {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: this.$t('Restarted successfully')
|
||||
this.$st.sendEv('任务列表', '删除任务')
|
||||
})
|
||||
},
|
||||
onRestart(row, ev) {
|
||||
ev.stopPropagation()
|
||||
this.$confirm(this.$t('Are you sure to restart this task?'), this.$t('Notification'), {
|
||||
confirmButtonText: this.$t('Confirm'),
|
||||
cancelButtonText: this.$t('Cancel'),
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.$store.dispatch('task/restartTask', row._id)
|
||||
.then(() => {
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: this.$t('Restarted successfully')
|
||||
})
|
||||
})
|
||||
})
|
||||
this.$st.sendEv('任务列表', '重新开始任务')
|
||||
})
|
||||
},
|
||||
onView (row) {
|
||||
this.$router.push(`/tasks/${row._id}`)
|
||||
this.$st.sendEv('任务列表', '查看任务')
|
||||
},
|
||||
onClickSpider (row) {
|
||||
this.$router.push(`/spiders/${row.spider_id}`)
|
||||
this.$st.sendEv('任务列表', '点击爬虫详情')
|
||||
},
|
||||
onClickNode (row) {
|
||||
this.$router.push(`/nodes/${row.node_id}`)
|
||||
this.$st.sendEv('任务列表', '点击节点详情')
|
||||
},
|
||||
onPageChange () {
|
||||
setTimeout(() => {
|
||||
this.$st.sendEv('任务列表', '重新开始任务')
|
||||
})
|
||||
},
|
||||
onView(row) {
|
||||
this.$router.push(`/tasks/${row._id}`)
|
||||
this.$st.sendEv('任务列表', '查看任务')
|
||||
},
|
||||
onClickSpider(row) {
|
||||
this.$router.push(`/spiders/${row.spider_id}`)
|
||||
this.$st.sendEv('任务列表', '点击爬虫详情')
|
||||
},
|
||||
onClickNode(row) {
|
||||
this.$router.push(`/nodes/${row.node_id}`)
|
||||
this.$st.sendEv('任务列表', '点击节点详情')
|
||||
},
|
||||
onPageChange() {
|
||||
setTimeout(() => {
|
||||
this.$store.dispatch('task/getTaskList')
|
||||
}, 0)
|
||||
},
|
||||
getTime(str) {
|
||||
if (str.match('^0001')) return 'NA'
|
||||
return dayjs(str).format('YYYY-MM-DD HH:mm:ss')
|
||||
},
|
||||
getWaitDuration(row) {
|
||||
if (row.start_ts.match('^0001')) return 'NA'
|
||||
return dayjs(row.start_ts).diff(row.create_ts, 'second')
|
||||
},
|
||||
getRuntimeDuration(row) {
|
||||
if (row.finish_ts.match('^0001')) return 'NA'
|
||||
return dayjs(row.finish_ts).diff(row.start_ts, 'second')
|
||||
},
|
||||
getTotalDuration(row) {
|
||||
if (row.finish_ts.match('^0001')) return 'NA'
|
||||
return dayjs(row.finish_ts).diff(row.create_ts, 'second')
|
||||
},
|
||||
onRowClick(row, event, column) {
|
||||
if (column.label !== this.$t('Action')) {
|
||||
this.onView(row)
|
||||
}
|
||||
},
|
||||
onSelectionChange(val) {
|
||||
this.multipleSelection = val
|
||||
},
|
||||
onFilterChange() {
|
||||
this.$store.dispatch('task/getTaskList')
|
||||
}, 0)
|
||||
},
|
||||
getTime (str) {
|
||||
if (str.match('^0001')) return 'NA'
|
||||
return dayjs(str).format('YYYY-MM-DD HH:mm:ss')
|
||||
},
|
||||
getWaitDuration (row) {
|
||||
if (row.start_ts.match('^0001')) return 'NA'
|
||||
return dayjs(row.start_ts).diff(row.create_ts, 'second')
|
||||
},
|
||||
getRuntimeDuration (row) {
|
||||
if (row.finish_ts.match('^0001')) return 'NA'
|
||||
return dayjs(row.finish_ts).diff(row.start_ts, 'second')
|
||||
},
|
||||
getTotalDuration (row) {
|
||||
if (row.finish_ts.match('^0001')) return 'NA'
|
||||
return dayjs(row.finish_ts).diff(row.create_ts, 'second')
|
||||
},
|
||||
onRowClick (row, event, column) {
|
||||
if (column.label !== this.$t('Action')) {
|
||||
this.onView(row)
|
||||
this.$st.sendEv('任务列表', '筛选任务')
|
||||
}
|
||||
},
|
||||
onSelectionChange (val) {
|
||||
this.multipleSelection = val
|
||||
},
|
||||
onFilterChange () {
|
||||
this.$store.dispatch('task/getTaskList')
|
||||
this.$st.sendEv('任务列表', '筛选任务')
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.$store.dispatch('task/getTaskList')
|
||||
this.$store.dispatch('spider/getSpiderList')
|
||||
this.$store.dispatch('node/getNodeList')
|
||||
},
|
||||
mounted () {
|
||||
this.handle = setInterval(() => {
|
||||
this.$store.dispatch('task/getTaskList')
|
||||
}, 5000)
|
||||
|
||||
if (!this.$utils.tour.isFinishedTour('task-list')) {
|
||||
this.$utils.tour.startTour(this, 'task-list')
|
||||
}
|
||||
},
|
||||
destroyed () {
|
||||
clearInterval(this.handle)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
Reference in New Issue
Block a user