This is an automated email from the ASF dual-hosted git repository.

wuzhiguo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/bigtop-manager.git


The following commit(s) were added to refs/heads/main by this push:
     new 5ecd17f  BIGTOP-4168: Add log progress messages on the task log page 
(#25)
5ecd17f is described below

commit 5ecd17faebf2512687ba9b853691b5662e87f68a
Author: Fdefined <[email protected]>
AuthorDate: Thu Jul 25 17:32:35 2024 +0800

    BIGTOP-4168: Add log progress messages on the task log page (#25)
---
 bigtop-manager-ui/src/api/sse/index.ts             |   3 +-
 .../{locales/en_US/index.ts => api/sse/types.ts}   |  17 +--
 bigtop-manager-ui/src/components/job-info/job.vue  | 163 +++++++++++++--------
 .../src/components/job-info/stage.vue              |  46 ++----
 .../src/components/job-info/task-log.vue           |  34 +++--
 bigtop-manager-ui/src/components/job-info/task.vue |  39 ++---
 .../src/composables/use-base-table.ts              |  76 ++++++++++
 bigtop-manager-ui/src/locales/en_US/index.ts       |   4 +-
 .../src/locales/en_US/{index.ts => job.ts}         |  15 +-
 bigtop-manager-ui/src/locales/zh_CN/index.ts       |   4 +-
 .../src/locales/{en_US/index.ts => zh_CN/job.ts}   |  15 +-
 bigtop-manager-ui/src/utils/tools.ts               |   5 +-
 12 files changed, 249 insertions(+), 172 deletions(-)

diff --git a/bigtop-manager-ui/src/api/sse/index.ts 
b/bigtop-manager-ui/src/api/sse/index.ts
index 52ee663..22975e5 100644
--- a/bigtop-manager-ui/src/api/sse/index.ts
+++ b/bigtop-manager-ui/src/api/sse/index.ts
@@ -19,12 +19,13 @@
 
 import axios, { type AxiosProgressEvent, type CancelTokenSource } from 'axios'
 import request from '@/api/request.ts'
+import type { LogsRes } from './types'
 
 export const getLogs = (
   clusterId: number,
   id: number,
   func: Function
-): { promise: Promise<any>; cancel: () => void } => {
+): LogsRes => {
   const source: CancelTokenSource = axios.CancelToken.source()
 
   const promise = request({
diff --git a/bigtop-manager-ui/src/locales/en_US/index.ts 
b/bigtop-manager-ui/src/api/sse/types.ts
similarity index 69%
copy from bigtop-manager-ui/src/locales/en_US/index.ts
copy to bigtop-manager-ui/src/api/sse/types.ts
index 1f8ed5f..6f83d3e 100644
--- a/bigtop-manager-ui/src/locales/en_US/index.ts
+++ b/bigtop-manager-ui/src/api/sse/types.ts
@@ -17,18 +17,7 @@
  * under the License.
  */
 
-import common from '@/locales/en_US/common.ts'
-import login from '@/locales/en_US/login'
-import user from '@/locales/en_US/user.ts'
-import cluster from '@/locales/en_US/cluster.ts'
-import hosts from '@/locales/en_US/hosts.ts'
-import service from '@/locales/en_US/service.ts'
-
-export default {
-  common,
-  login,
-  user,
-  cluster,
-  hosts,
-  service
+export interface LogsRes {
+  promise: Promise<any>
+  cancel: () => void
 }
diff --git a/bigtop-manager-ui/src/components/job-info/job.vue 
b/bigtop-manager-ui/src/components/job-info/job.vue
index d2a2b34..e645c60 100644
--- a/bigtop-manager-ui/src/components/job-info/job.vue
+++ b/bigtop-manager-ui/src/components/job-info/job.vue
@@ -18,9 +18,8 @@
 -->
 
 <script setup lang="ts">
-  import { ref, watch, computed, reactive, toRaw, toRefs, nextTick } from 'vue'
+  import { ref, watch, computed, toRefs, nextTick } from 'vue'
   import { useClusterStore } from '@/store/cluster'
-  import { PaginationConfig } from 'ant-design-vue/es/pagination/Pagination'
   import { storeToRefs } from 'pinia'
   import {
     JobVO,
@@ -36,8 +35,10 @@
   import Stage from './stage.vue'
   import Task from './task.vue'
   import TaskLog from './task-log.vue'
+  import useBaseTable from '@/composables/use-base-table'
+  import type { TableColumnType, TablePaginationConfig } from 'ant-design-vue'
 
-  const columns = [
+  const columns: TableColumnType[] = [
     {
       title: 'common.name',
       dataIndex: 'name',
@@ -77,14 +78,14 @@
 
   const emits = defineEmits(['update:visible', 'closed'])
 
-  const loading = ref(false)
+  const showLogAwaitMsg = ref(false)
+  const isComplete = ref(false)
   const stages = ref<StageVO[]>([])
   const tasks = ref<TaskVO[]>([])
   const breadcrumbs = ref<any[]>([{ name: 'Job Info' }])
   const currTaskInfo = ref<TaskVO>()
-  const jobs = ref<JobVO[]>([])
   const intervalId = ref<Pausable | undefined>()
-  const logRef = ref<InstanceType<typeof TaskLog> | null>()
+  const logRef = ref<InstanceType<typeof TaskLog> | null>(null)
   const currPage = ref<string[]>([
     'isJobTable',
     'isStageTable',
@@ -92,12 +93,14 @@
     'isTaskLogs'
   ])
 
-  const paginationProps = reactive<PaginationConfig>({})
-  const jobsPageState = reactive<Pagination>({
-    pageNum: 1,
-    pageSize: 10,
-    sort: 'desc'
-  })
+  const {
+    loading,
+    columnsProp,
+    dataSource: jobs,
+    paginationProps,
+    onChange,
+    resetState
+  } = useBaseTable<JobVO>(columns, [])
 
   const getCurrPage = computed(() => {
     return currPage.value[breadcrumbs.value.length - 1]
@@ -105,10 +108,9 @@
 
   watch(visible, (val) => {
     if (val) {
+      resetState()
       loading.value = true
-      Object.assign(paginationProps, initPagedProps())
-      checkMetaOrigin(outerData.value ? true : false)
-      loading.value = false
+      checkDataOrigin(outerData.value ? true : false)
     }
   })
 
@@ -127,12 +129,13 @@
     }
   })
 
-  const checkMetaOrigin = (isOuter = false) => {
+  const checkDataOrigin = (isOuter = false) => {
     if (isOuter) {
       const { meta, currItem } = outerData.value as OuterData
       jobs.value = meta
       clickJob(meta[0])
       clickStage(currItem as StageVO)
+      loading.value = false
       return
     }
     getJobsList()
@@ -155,16 +158,21 @@
 
   const getJobsList = async () => {
     try {
-      const params = { ...toRaw(jobsPageState) }
-      const { content, total } = await getJobs(clusterId.value, params)
+      const params = {
+        pageNum: paginationProps.value.current,
+        pageSize: paginationProps.value.pageSize,
+        sort: 'desc'
+      } as Pagination
+      const { content } = await getJobs(clusterId.value, params)
       jobs.value = content.map((v) => {
         return {
           ...v
         }
       })
-      paginationProps.total = total
       loading.value = false
     } catch (error) {
+      console.log('error :>> ', error)
+    } finally {
       loading.value = false
     }
   }
@@ -173,7 +181,7 @@
     breadcrumbs.value.push(record)
     currTaskInfo.value = record
     await nextTick()
-    logRef.value?.getLogsInfo(record.id)
+    logRef.value?.getLogInfo(record.id)
   }
 
   const clickJob = (record: JobVO) => {
@@ -191,52 +199,47 @@
     breadcrumbs.value.splice(idx + 1, len)
   }
 
-  const handlePageChange = (page: number) => {
-    paginationProps.current = page
-    jobsPageState.pageNum = page
-    loading.value = true
-    getJobsList()
+  const handleClose = () => {
+    intervalId.value?.pause()
+    breadcrumbs.value = [{ name: 'Job Info' }]
+    resetState()
+    emits('update:visible', false)
   }
 
-  const handlePageSizeChange = (_current: number, size: number) => {
-    paginationProps.pageSize = size
-    jobsPageState.pageSize = size
-    loading.value = true
-    getJobsList()
+  const setShowLogAwaitMsg = (status: boolean) => {
+    showLogAwaitMsg.value = status
   }
 
-  const initPagedProps = () => {
-    return {
-      current: 1,
-      pageSize: 10,
-      size: 'small',
-      showSizeChanger: true,
-      pageSizeOptions: ['10', '20', '30', '40', '50'],
-      total: 0,
-      onChange: handlePageChange,
-      onShowSizeChange: handlePageSizeChange
-    }
+  const onLogComplete = (status: boolean) => {
+    isComplete.value = status
   }
 
-  const handleClose = () => {
-    intervalId.value?.pause()
-    breadcrumbs.value = [{ name: 'Job Info' }]
-    jobs.value = []
-    Object.assign(jobsPageState, {
-      pageNum: 1,
-      pageSize: 10,
-      sort: 'desc'
-    })
-    emits('update:visible', false)
+  const onTableChange = (pagination: TablePaginationConfig) => {
+    onChange(pagination)
+    loading.value = true
+    getJobsList()
   }
 </script>
 
 <template>
   <a-modal :open="props.visible" width="95%" @cancel="handleClose">
     <template #footer>
-      <a-button key="back" type="primary" @click="handleClose">
-        {{ $t('common.confirm') }}
-      </a-button>
+      <div :class="{ 'footer-btns': showLogAwaitMsg }">
+        <div
+          v-if="showLogAwaitMsg"
+          class="logs-wait-msg"
+          :class="{ 'loading-dot': !isComplete }"
+        >
+          {{
+            isComplete
+              ? $t('job.log_complete_message')
+              : $t('job.log_await_message')
+          }}
+        </div>
+        <a-button key="back" type="primary" @click="handleClose">
+          {{ $t('common.confirm') }}
+        </a-button>
+      </div>
     </template>
 
     <div class="breadcrumb">
@@ -250,15 +253,15 @@
         </a-breadcrumb-item>
       </a-breadcrumb>
     </div>
-
     <a-table
       v-show="getCurrPage == 'isJobTable'"
       :scroll="{ y: 500 }"
-      :pagination="paginationProps"
       :loading="loading"
       :data-source="jobs"
-      :columns="columns"
+      :columns="columnsProp"
+      :pagination="paginationProps"
       destroy-on-close
+      @change="onTableChange"
     >
       <template #headerCell="{ column }">
         <span>{{ $t(column.title) }}</span>
@@ -285,12 +288,56 @@
       <task :columns="columns" :tasks="tasks" @click-task="clickTask" />
     </template>
     <template v-if="getCurrPage == 'isTaskLogs'">
-      <task-log ref="logRef" />
+      <task-log
+        ref="logRef"
+        @vue:before-unmount="setShowLogAwaitMsg"
+        @on-log-receive="setShowLogAwaitMsg"
+        @on-log-complete="onLogComplete"
+      />
     </template>
   </a-modal>
 </template>
 
 <style lang="scss" scoped>
+  .footer-btns {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    flex-wrap: wrap;
+  }
+
+  .logs-wait-msg {
+    margin: 0;
+    padding: 0;
+  }
+
+  .loading-dot {
+    &::after {
+      content: '';
+      animation: wait 5s 0s infinite;
+    }
+  }
+
+  @keyframes wait {
+    16% {
+      content: '.';
+    }
+    32% {
+      content: '. .';
+    }
+    48% {
+      content: '. . .';
+    }
+    64% {
+      content: '. . . .';
+    }
+    80% {
+      content: '. . . . .';
+    }
+    96% {
+      content: '. . . . . .';
+    }
+  }
   .breadcrumb {
     :deep(.ant-breadcrumb) {
       margin-bottom: 16px !important;
diff --git a/bigtop-manager-ui/src/components/job-info/stage.vue 
b/bigtop-manager-ui/src/components/job-info/stage.vue
index 80942e6..183bfac 100644
--- a/bigtop-manager-ui/src/components/job-info/stage.vue
+++ b/bigtop-manager-ui/src/components/job-info/stage.vue
@@ -19,21 +19,20 @@
 
 <script lang="ts" setup>
   import { StageVO } from '@/api/job/types.ts'
-  import { ref, reactive, watch, computed } from 'vue'
-  import { PaginationConfig } from 'ant-design-vue/es/pagination/Pagination'
+  import { watch } from 'vue'
   import CustomProgress from './custom-progress.vue'
+  import useBaseTable from '@/composables/use-base-table'
+  import type { TableColumnType } from 'ant-design-vue'
 
   interface StageProps {
     stages: StageVO[]
-    columns: any
+    columns: TableColumnType[]
   }
 
-  const props = withDefaults(defineProps<StageProps>(), {})
-  const loading = ref(false)
-  const pagedList = computed(() => {
-    return props.stages
-  })
-
+  const props = defineProps<StageProps>()
+  const baseTable = useBaseTable<StageVO>(props.columns, props.stages)
+  const { dataSource, columnsProp, loading, paginationProps, onChange } =
+    baseTable
   watch(
     () => props.stages,
     (val) => {
@@ -48,26 +47,6 @@
       deep: true
     }
   )
-
-  const handlePageChange = (page: number) => {
-    paginationProps.current = page
-  }
-
-  const handlePageSizeChange = (_current: number, size: number) => {
-    paginationProps.pageSize = size
-  }
-
-  const paginationProps = reactive<PaginationConfig>({
-    current: 1,
-    pageSize: 10,
-    size: 'small',
-    showSizeChanger: true,
-    pageSizeOptions: ['10', '20', '30', '40', '50'],
-    total: pagedList.value.length,
-    onChange: handlePageChange,
-    onShowSizeChange: handlePageSizeChange
-  })
-
   const emits = defineEmits(['clickStage'])
   const clickStage = (record: StageVO) => {
     emits('clickStage', record)
@@ -77,11 +56,12 @@
 <template>
   <div class="stage-info">
     <a-table
-      :pagination="paginationProps"
-      :data-source="pagedList"
-      :columns="props.columns"
-      :loading="loading"
       :scroll="{ y: 500 }"
+      :loading="loading"
+      :columns="columnsProp"
+      :data-source="dataSource"
+      :pagination="paginationProps"
+      @change="onChange"
     >
       <template #headerCell="{ column }">
         <span>{{ $t(column.title) }}</span>
diff --git a/bigtop-manager-ui/src/components/job-info/task-log.vue 
b/bigtop-manager-ui/src/components/job-info/task-log.vue
index 7665639..36f1bfd 100644
--- a/bigtop-manager-ui/src/components/job-info/task-log.vue
+++ b/bigtop-manager-ui/src/components/job-info/task-log.vue
@@ -36,6 +36,8 @@
   const logMeta = ref<string>('')
   const canceler = ref<Canceler>()
 
+  const emit = defineEmits(['onLogReceive', 'onLogComplete'])
+
   watch(logMeta, (val) => {
     logText.value = val
       .split('\n\n')
@@ -45,16 +47,23 @@
       .join('\n')
   })
 
-  const getLogsInfo = async (id: number) => {
-    const { cancel } = getLogs(clusterId.value, id, getLogProgress)
+  const getLogInfo = async (id: number) => {
+    const { cancel, promise } = getLogs(clusterId.value, id, onLogReceive)
     canceler.value = cancel
+    promise.then(onLogComplete)
+    emit('onLogReceive', true)
   }
 
-  const getLogProgress = ({ event }: AxiosProgressEvent) => {
+  const onLogReceive = ({ event }: AxiosProgressEvent) => {
     logMeta.value = event.target.responseText
     scrollToBottom(logsInfoRef.value)
   }
 
+  const onLogComplete = (res: string | undefined) => {
+    cancelSseConnect()
+    emit('onLogComplete', res != undefined)
+  }
+
   const cancelSseConnect = () => {
     if (!canceler.value) {
       return
@@ -78,10 +87,12 @@
 
   onBeforeUnmount(() => {
     cancelSseConnect()
+    emit('onLogReceive', false)
+    emit('onLogComplete', false)
   })
 
   defineExpose({
-    getLogsInfo
+    getLogInfo
   })
 </script>
 
@@ -98,8 +109,10 @@
         </a-button>
       </div>
     </div>
-    <div class="logs_info">
-      <pre id="logs" ref="logsInfoRef">{{ logText }}</pre>
+    <div ref="logsInfoRef" class="logs_info">
+      <div id="logs">
+        <pre>{{ logText }}</pre>
+      </div>
     </div>
   </div>
 </template>
@@ -127,14 +140,17 @@
       background-color: #f5f5f5;
       border-radius: 4px;
       position: relative;
-      pre {
+      & > div {
         height: 100%;
         margin: 0;
         padding: 16px 14px;
         box-sizing: border-box;
-        color: #444;
         border-color: #eee;
-        line-height: 16px;
+        box-sizing: border-box;
+        pre {
+          line-height: 20px;
+          color: #444;
+        }
       }
     }
   }
diff --git a/bigtop-manager-ui/src/components/job-info/task.vue 
b/bigtop-manager-ui/src/components/job-info/task.vue
index d5e5b88..79d01a3 100644
--- a/bigtop-manager-ui/src/components/job-info/task.vue
+++ b/bigtop-manager-ui/src/components/job-info/task.vue
@@ -18,9 +18,9 @@
 -->
 
 <script setup lang="ts">
-  import { computed, reactive, ref } from 'vue'
-  import { PaginationConfig } from 'ant-design-vue/es/pagination/Pagination'
   import { TaskVO, State } from '@/api/job/types.ts'
+  import useBaseTable from '@/composables/use-base-table'
+  import type { TableColumnType } from 'ant-design-vue'
 
   import {
     CheckCircleTwoTone,
@@ -31,30 +31,13 @@
 
   interface TaskProps {
     tasks: TaskVO[]
-    columns: any
+    columns: TableColumnType[]
   }
-  const props = withDefaults(defineProps<TaskProps>(), {})
 
-  const pagedList = ref(computed(() => props.tasks))
-
-  const handlePageChange = (page: number) => {
-    paginationProps.current = page
-  }
-
-  const handlePageSizeChange = (_current: number, size: number) => {
-    paginationProps.pageSize = size
-  }
-
-  const paginationProps = reactive<PaginationConfig>({
-    current: 1,
-    pageSize: 10,
-    size: 'small',
-    showSizeChanger: true,
-    pageSizeOptions: ['10', '20', '30', '40', '50'],
-    total: pagedList.value.length,
-    onChange: handlePageChange,
-    onShowSizeChange: handlePageSizeChange
-  })
+  const props = defineProps<TaskProps>()
+  const baseTable = useBaseTable<TaskVO>(props.columns, props.tasks)
+  const { dataSource, columnsProp, loading, paginationProps, onChange } =
+    baseTable
 
   const emits = defineEmits(['clickTask'])
   const clickTask = (record: TaskVO) => {
@@ -65,10 +48,12 @@
 <template>
   <div class="task-info">
     <a-table
-      :pagination="paginationProps"
-      :data-source="pagedList"
-      :columns="props.columns"
       :scroll="{ y: 500 }"
+      :loading="loading"
+      :columns="columnsProp"
+      :data-source="dataSource"
+      :pagination="paginationProps"
+      @change="onChange"
     >
       <template #headerCell="{ column }">
         <span>{{ $t(column.title) }}</span>
diff --git a/bigtop-manager-ui/src/composables/use-base-table.ts 
b/bigtop-manager-ui/src/composables/use-base-table.ts
new file mode 100644
index 0000000..1efb742
--- /dev/null
+++ b/bigtop-manager-ui/src/composables/use-base-table.ts
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *    https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { ref, onUnmounted } from 'vue'
+import type { TablePaginationConfig, TableColumnType } from 'ant-design-vue'
+
+const useBaseTable = <T>(
+  columns: TableColumnType[],
+  rows?: T[],
+  pagination?: TablePaginationConfig | false | undefined
+) => {
+  const loading = ref(false)
+  const dataSource = ref<T[]>(rows || [])
+  const columnsProp = ref<TableColumnType[]>(columns)
+  const paginationProps = ref<TablePaginationConfig>({
+    current: 1,
+    pageSize: 10,
+    total: dataSource.value.length,
+    size: 'small',
+    showSizeChanger: true,
+    pageSizeOptions: ['10', '20', '30', '40', '50']
+  })
+
+  // merge pagination config
+  if (pagination) {
+    paginationProps.value = Object.assign(paginationProps.value, pagination)
+  }
+
+  const onChange = (pagination: TablePaginationConfig) => {
+    paginationProps.value = Object.assign(paginationProps.value, pagination)
+  }
+
+  const resetState = () => {
+    loading.value = false
+    dataSource.value = []
+    paginationProps.value = {
+      current: 1,
+      pageSize: 10,
+      total: dataSource.value.length || 0,
+      size: 'small',
+      showSizeChanger: true,
+      pageSizeOptions: ['10', '20', '30', '40', '50']
+    }
+  }
+
+  onUnmounted(() => {
+    resetState()
+  })
+
+  return {
+    columnsProp,
+    dataSource,
+    loading,
+    paginationProps,
+    onChange,
+    resetState
+  }
+}
+
+export default useBaseTable
diff --git a/bigtop-manager-ui/src/locales/en_US/index.ts 
b/bigtop-manager-ui/src/locales/en_US/index.ts
index 1f8ed5f..7fc6f12 100644
--- a/bigtop-manager-ui/src/locales/en_US/index.ts
+++ b/bigtop-manager-ui/src/locales/en_US/index.ts
@@ -23,6 +23,7 @@ import user from '@/locales/en_US/user.ts'
 import cluster from '@/locales/en_US/cluster.ts'
 import hosts from '@/locales/en_US/hosts.ts'
 import service from '@/locales/en_US/service.ts'
+import job from '@/locales/en_US/job.ts'
 
 export default {
   common,
@@ -30,5 +31,6 @@ export default {
   user,
   cluster,
   hosts,
-  service
+  service,
+  job
 }
diff --git a/bigtop-manager-ui/src/locales/en_US/index.ts 
b/bigtop-manager-ui/src/locales/en_US/job.ts
similarity index 71%
copy from bigtop-manager-ui/src/locales/en_US/index.ts
copy to bigtop-manager-ui/src/locales/en_US/job.ts
index 1f8ed5f..52b7e99 100644
--- a/bigtop-manager-ui/src/locales/en_US/index.ts
+++ b/bigtop-manager-ui/src/locales/en_US/job.ts
@@ -17,18 +17,7 @@
  * under the License.
  */
 
-import common from '@/locales/en_US/common.ts'
-import login from '@/locales/en_US/login'
-import user from '@/locales/en_US/user.ts'
-import cluster from '@/locales/en_US/cluster.ts'
-import hosts from '@/locales/en_US/hosts.ts'
-import service from '@/locales/en_US/service.ts'
-
 export default {
-  common,
-  login,
-  user,
-  cluster,
-  hosts,
-  service
+  log_await_message: 'Waiting for more logs',
+  log_complete_message: 'Done!'
 }
diff --git a/bigtop-manager-ui/src/locales/zh_CN/index.ts 
b/bigtop-manager-ui/src/locales/zh_CN/index.ts
index 7521822..7ebd07b 100644
--- a/bigtop-manager-ui/src/locales/zh_CN/index.ts
+++ b/bigtop-manager-ui/src/locales/zh_CN/index.ts
@@ -23,6 +23,7 @@ import user from '@/locales/zh_CN/user.ts'
 import cluster from '@/locales/zh_CN/cluster.ts'
 import hosts from '@/locales/zh_CN/hosts.ts'
 import service from '@/locales/zh_CN/service.ts'
+import job from '@/locales/zh_CN/job.ts'
 
 export default {
   common,
@@ -30,5 +31,6 @@ export default {
   user,
   cluster,
   hosts,
-  service
+  service,
+  job
 }
diff --git a/bigtop-manager-ui/src/locales/en_US/index.ts 
b/bigtop-manager-ui/src/locales/zh_CN/job.ts
similarity index 71%
copy from bigtop-manager-ui/src/locales/en_US/index.ts
copy to bigtop-manager-ui/src/locales/zh_CN/job.ts
index 1f8ed5f..9dff298 100644
--- a/bigtop-manager-ui/src/locales/en_US/index.ts
+++ b/bigtop-manager-ui/src/locales/zh_CN/job.ts
@@ -17,18 +17,7 @@
  * under the License.
  */
 
-import common from '@/locales/en_US/common.ts'
-import login from '@/locales/en_US/login'
-import user from '@/locales/en_US/user.ts'
-import cluster from '@/locales/en_US/cluster.ts'
-import hosts from '@/locales/en_US/hosts.ts'
-import service from '@/locales/en_US/service.ts'
-
 export default {
-  common,
-  login,
-  user,
-  cluster,
-  hosts,
-  service
+  log_await_message: '获取日志中 ',
+  log_complete_message: '完成 !'
 }
diff --git a/bigtop-manager-ui/src/utils/tools.ts 
b/bigtop-manager-ui/src/utils/tools.ts
index 033fc37..6dc36df 100644
--- a/bigtop-manager-ui/src/utils/tools.ts
+++ b/bigtop-manager-ui/src/utils/tools.ts
@@ -52,6 +52,7 @@ export const scrollToBottom = (container: HTMLElement | null) 
=> {
   if (!container) {
     return
   }
-  const { clientHeight, scrollHeight } = container
-  container.scrollTop = scrollHeight - clientHeight
+  requestAnimationFrame(() => {
+    container.scrollTop = container.scrollHeight
+  })
 }

Reply via email to