diff options
| author | hanyuxia <[email protected]> | 2024-11-08 13:38:00 +0800 |
|---|---|---|
| committer | hanyuxia <[email protected]> | 2024-11-08 13:38:00 +0800 |
| commit | d61a71c4dba78544e2818e9b0784f37a6f0f2bc4 (patch) | |
| tree | 02723e164ef9b19a858ed69eb979dc0c8558750f /src | |
| parent | e811f7f269da8e80670a975c790d6700a9f6a7e0 (diff) | |
feat: 1、面包屑 Jobs 可以点击,返回 job 列表页面;2、当 job 状态为结束状态时,不再请求log 和 详情接口;
Diffstat (limited to 'src')
| -rw-r--r-- | src/utils/constants.js | 8 | ||||
| -rw-r--r-- | src/views/jobs/index.vue | 18 | ||||
| -rw-r--r-- | src/views/jobs/log.vue | 53 |
3 files changed, 52 insertions, 27 deletions
diff --git a/src/utils/constants.js b/src/utils/constants.js index 7da684b..cd5dcbd 100644 --- a/src/utils/constants.js +++ b/src/utils/constants.js @@ -141,4 +141,12 @@ export const monthDict = { '10': 'Oct', '11': 'Nov', '12': 'Dec', +} +export const jobStatus = { + created: 'created', + pending: 'pending', + running: 'running', + passed: 'passed', + failed: 'failed', + cancel: 'cancel' }
\ No newline at end of file diff --git a/src/views/jobs/index.vue b/src/views/jobs/index.vue index be71b33..81575f0 100644 --- a/src/views/jobs/index.vue +++ b/src/views/jobs/index.vue @@ -54,27 +54,27 @@ </template> <template v-else-if="item.prop === 'status'"> <div class="statusWrap"> - <div class="statusTag created" v-if="scope.row.status === 'created'"> + <div class="statusTag created" v-if="scope.row.status === jobStatus.created"> <i class="asw-icon icon-Created statusIcon"></i> <span>{{ t('job.created') }}</span> </div> - <div class="statusTag danger" v-else-if="scope.row.status === 'pending'"> + <div class="statusTag danger" v-else-if="scope.row.status === jobStatus.pending"> <i class="asw-icon icon-Pending statusIcon"></i> <span>{{ t('job.pending') }}</span> </div> - <div class="statusTag" v-else-if="scope.row.status === 'running'"> + <div class="statusTag" v-else-if="scope.row.status === jobStatus.running"> <i class="asw-icon icon-Running statusIcon"></i> <span>{{ t('job.running') }}</span> </div> - <div class="statusTag success" v-else-if="scope.row.status === 'passed'"> + <div class="statusTag success" v-else-if="scope.row.status === jobStatus.passed"> <i class="asw-icon icon-Passed statusIcon"></i> <span>{{ t('job.passed') }}</span> </div> - <div class="statusTag error" v-else-if="scope.row.status === 'failed'"> + <div class="statusTag error" v-else-if="scope.row.status === jobStatus.failed"> <i class="asw-icon icon-Failed statusIcon"></i> <span>{{ t('job.failed') }}</span> </div> - <div class="statusTag cancel" v-else-if="scope.row.status === 'cancel'"> + <div class="statusTag cancel" v-else-if="scope.row.status === jobStatus.cancel"> <i class="asw-icon icon-Canceled statusIcon"></i> <span>{{ t('job.canceled') }}</span> </div> @@ -123,13 +123,13 @@ <template #dropdown> <el-dropdown-menu> <div v-has="'job_cancel'"> - <el-dropdown-item key="cancel" @click="tableCancel(scope.row)" :disabled="scope.row.status === 'passed' || scope.row.status === 'failed' || scope.row.status === 'cancel'"> + <el-dropdown-item key="cancel" @click="tableCancel(scope.row)" :disabled="scope.row.status === jobStatus.passed || scope.row.status === jobStatus.failed || scope.row.status === jobStatus.cancel"> <i class="asw-icon icon-cancel cp"></i> {{ t('job.cancel') }} </el-dropdown-item> </div> <div v-has="'job_retry'"> - <el-dropdown-item key="retry" @click="tableRetry(scope.row)" :disabled="scope.row.status === 'created' || scope.row.status === 'pending' || scope.row.status === 'running' || submitting"> + <el-dropdown-item key="retry" @click="tableRetry(scope.row)" :disabled="scope.row.status === jobStatus.created || scope.row.status === jobStatus.pending || scope.row.status === jobStatus.running || submitting"> <i class="asw-icon icon-retry cp"></i> {{t('job.retry')}} </el-dropdown-item> @@ -152,7 +152,7 @@ import { toThousands } from '@/utils'; import { useSystemStore } from '@/store/index'; import { useTable } from '@/hooks/useTable'; - import { monthDict } from '@/utils/constants'; + import { monthDict, jobStatus } from '@/utils/constants'; import { get } from 'lodash'; import { useRouter } from 'vue-router'; import moment from 'moment-timezone'; diff --git a/src/views/jobs/log.vue b/src/views/jobs/log.vue index 464da02..defa89e 100644 --- a/src/views/jobs/log.vue +++ b/src/views/jobs/log.vue @@ -2,34 +2,34 @@ <div id="jobs" class="log-detail"> <div class="log-detail__left"> <div class="detail-header"> - {{ t('overall.jobs') }} / {{ jobInfo.id }} + <span @click="jumpBack" class="hover-primary">{{ t('overall.jobs') }}</span> / {{ jobInfo.id }} </div> <div class="detail-log__container"> <div class="top-bar"> <div class="log-title">{{ jobInfo.id }}</div> <div class="log-title__start"> <div class="statusWrap"> - <div class="statusTag created" v-if="jobInfo.status === 'created'"> + <div class="statusTag created" v-if="jobInfo.status === jobStatus.created"> <i class="asw-icon icon-Created statusIcon"></i> <span>{{ t('job.created') }}</span> </div> - <div class="statusTag danger" v-else-if="jobInfo.status === 'pending'"> + <div class="statusTag danger" v-else-if="jobInfo.status === jobStatus.pending"> <i class="asw-icon icon-Pending statusIcon"></i> <span>{{ t('job.pending') }}</span> </div> - <div class="statusTag" v-else-if="jobInfo.status === 'running'"> + <div class="statusTag" v-else-if="jobInfo.status === jobStatus.running"> <i class="asw-icon icon-Running statusIcon"></i> <span>{{ t('job.running') }}</span> </div> - <div class="statusTag success" v-else-if="jobInfo.status === 'passed'"> + <div class="statusTag success" v-else-if="jobInfo.status === jobStatus.passed"> <i class="asw-icon icon-Passed statusIcon"></i> <span>{{ t('job.passed') }}</span> </div> - <div class="statusTag error" v-else-if="jobInfo.status === 'failed'"> + <div class="statusTag error" v-else-if="jobInfo.status === jobStatus.failed"> <i class="asw-icon icon-Failed statusIcon"></i> <span>{{ t('job.failed') }}</span> </div> - <div class="statusTag cancel" v-else-if="jobInfo.status === 'cancel'"> + <div class="statusTag cancel" v-else-if="jobInfo.status === jobStatus.cancel"> <i class="asw-icon icon-Canceled statusIcon"></i> <span>{{ t('job.canceled') }}</span> </div> @@ -50,8 +50,8 @@ </span> </div> </div> - <div class="job-not-started" v-if="jobInfo.status === 'cancel' || jobInfo.status === 'created'"> - <template v-if="jobInfo.status === 'cancel'"> + <div class="job-not-started" v-if="jobInfo.status === jobStatus.cancel || jobInfo.status === jobStatus.created"> + <template v-if="jobInfo.status === jobStatus.cancel"> <div class="status-icon"> <svg> <use xlink:href="#icon-Canceled1"></use> @@ -64,7 +64,7 @@ </el-button> </div> </template> - <template v-else-if="jobInfo.status === 'created'"> + <template v-else-if="jobInfo.status === jobStatus.created"> <div class="status-icon"> <svg> <use xlink:href="#icon-source-document_15399136"></use> @@ -78,7 +78,7 @@ </div> </template> </div> - <div class="log-content__container" v-else-if="jobInfo.status === 'pending' || jobInfo.status === 'running' || jobInfo.status === 'passed'|| jobInfo.status === 'failed'"> + <div class="log-content__container" v-else-if="jobInfo.status === jobStatus.pending || jobInfo.status === jobStatus.running || jobInfo.status === jobStatus.passed|| jobInfo.status === jobStatus.failed"> <div class="log-content" id="logScroll" v-html="logShowContent" style="white-space: pre-wrap;"> </div> </div> @@ -120,7 +120,7 @@ import { jobLogApi, jobDetailApi, jobCancelApi, jobAddApi} from '@/axios/api'; import { ElMessage } from 'element-plus'; import { useSystemStore } from '@/store/index'; - import { monthDict } from '@/utils/constants'; + import { monthDict, jobStatus } from '@/utils/constants'; import { get } from 'lodash'; import { useRouter } from 'vue-router'; import moment from 'moment-timezone'; @@ -145,7 +145,7 @@ let logShowContent = ref(''); let offset = ref(0); let timer = ref(null); - const getLogData = async () => { + const getLogData = async (isStop) => { try { let params = { offset: offset.value @@ -158,7 +158,9 @@ let logLineList = logRealContent.value.split("\n"); let indexWidth = logLineList.length.toString().length * 8; logShowContent.value = logLineList.map((item,index) => { - return `<div style="color:#99A0BC;margin-right:10px;width:${indexWidth}px;">${index}</div><div style="width:calc(100% - ${indexWidth+10}px);min-width:calc(100% - ${indexWidth+10}px);max-width:calc(100% - ${indexWidth+10}px);">${item}</div>`; + if(item) {//避免日志最后一行出现空行 + return `<div style="color:#99A0BC;margin-right:10px;width:${indexWidth}px;">${index}</div><div style="width:calc(100% - ${indexWidth+10}px);min-width:calc(100% - ${indexWidth+10}px);max-width:calc(100% - ${indexWidth+10}px);">${item}</div>`; + } }).join('\n') nextTick(() => { try { @@ -171,7 +173,13 @@ } else { ElMessage.error(res.msg || res.error); } - timer.value = setTimeout(getLogData,3000); + if(!isStop) { + if(jobInfo.status === jobStatus.running) { + timer.value = setTimeout(getLogData,3000); + } else if(jobInfo.status === jobStatus.passed || jobInfo.status === jobStatus.failed) { + timer.value = setTimeout(getLogData,60000,true);//passed或者failed状态需要再执行一次后停止,否则可能缺少日志,最后一次读取,为passed或者failed状态后1分钟 + } + } } catch (error) {console.error(error)} }; @@ -225,8 +233,10 @@ jobInfo.duration = result; } //获取日志信息 - if(jobInfo.status !== 'cancel' && jobInfo.status !== 'created') { - getLogData(); + if(jobInfo.status === jobStatus.running || jobInfo.status === jobStatus.passed || jobInfo.status === jobStatus.failed) { + if(!timer.value) {//避免多次启动日志查询 + getLogData(); + } } else { if(timer.value) { clearTimeout(timer.value); @@ -237,7 +247,14 @@ } else { ElMessage.error(res.msg || res.error); } - timerJob.value = setTimeout(getJobData,3000); + if(jobInfo.status === jobStatus.created || jobInfo.status === jobStatus.pending || jobInfo.status === jobStatus.running) { + timerJob.value = setTimeout(getJobData,3000); + } else { + if(timerJob.value) { + clearTimeout(timerJob.value); + timerJob.value = null; + } + } } catch (error) {} }; |
