Kaynağa Gözat

[Feature][UI Next] Add monitor master. (#7917)

songjianet 3 yıl önce
ebeveyn
işleme
f5aca0f11b

+ 6 - 3
dolphinscheduler-ui-next/src/components/chart/modules/Gauge.tsx

@@ -28,12 +28,15 @@ const props = {
     type: [String, Number] as PropType<string | number>,
     default: 400,
   },
+  data: {
+    type: [String, Number] as PropType<string | number>,
+  },
 }
 
 const GaugeChart = defineComponent({
   name: 'GaugeChart',
   props,
-  setup() {
+  setup(props) {
     const gaugeChartRef: Ref<HTMLDivElement | null> = ref(null)
 
     const option = {
@@ -73,12 +76,12 @@ const GaugeChart = defineComponent({
           },
           detail: {
             valueAnimation: true,
-            formatter: '{value} km/h',
+            formatter: '{value} %',
             color: 'auto',
           },
           data: [
             {
-              value: 70,
+              value: props.data,
             },
           ],
         },

+ 2 - 2
dolphinscheduler-ui-next/src/components/modal/index.module.scss

@@ -23,7 +23,7 @@
   display: flex;
   justify-content: flex-end;
 
-  button:first-child {
-    margin-right: 20px;
+  button:last-child {
+    margin-left: 20px;
   }
 }

+ 9 - 3
dolphinscheduler-ui-next/src/components/modal/index.tsx

@@ -32,6 +32,10 @@ const props = {
   cancelText: {
     type: String as PropType<string>,
   },
+  cancelShow: {
+    type: Boolean as PropType<boolean>,
+    default: true,
+  },
   confirmText: {
     type: String as PropType<string>,
   },
@@ -72,9 +76,11 @@ const Modal = defineComponent({
             default: () => renderSlot($slots, 'default'),
             footer: () => (
               <div class={styles['btn-box']}>
-                <NButton quaternary size='small' onClick={onCancel}>
-                  {this.cancelText || t('modal.cancel')}
-                </NButton>
+                {this.cancelShow && (
+                  <NButton quaternary size='small' onClick={onCancel}>
+                    {this.cancelText || t('modal.cancel')}
+                  </NButton>
+                )}
                 <NButton
                   type='info'
                   size='small'

+ 0 - 1
dolphinscheduler-ui-next/src/layouts/content/components/sidebar/index.tsx

@@ -38,7 +38,6 @@ const Sidebar = defineComponent({
 
     const { handleMenuClick } = useMenuClick()
 
-    
     return { collapsedRef, defaultExpandedKeys, handleMenuClick }
   },
   render() {

+ 5 - 5
dolphinscheduler-ui-next/src/layouts/content/index.tsx

@@ -56,11 +56,11 @@ const Content = defineComponent({
     const genSideMenu = (state: any) => {
       const key = menuStore.getMenuKey
       state.sideMenuOptions =
-      state.menuOptions.filter((menu: { key: string }) => menu.key === key)[0]
-      .children || []
-      state.isShowSide = 
-      state.menuOptions.filter((menu: { key: string }) => menu.key === key)[0]
-      .isShowSide || false
+        state.menuOptions.filter((menu: { key: string }) => menu.key === key)[0]
+          .children || []
+      state.isShowSide =
+        state.menuOptions.filter((menu: { key: string }) => menu.key === key)[0]
+          .isShowSide || false
     }
 
     const getSideMenuOptions = (item: any) => {

+ 10 - 0
dolphinscheduler-ui-next/src/locales/modules/en_US.ts

@@ -116,6 +116,16 @@ const profile = {
 }
 
 const monitor = {
+  master: {
+    cpu_usage: 'CPU Usage',
+    memory_usage: 'Memory Usage',
+    load_average: 'Load Average',
+    create_time: 'Create Time',
+    last_heartbeat_time: 'Last Heartbeat Time',
+    directory_detail: 'Directory Detail',
+    host: 'Host',
+    directory: 'Directory',
+  },
   db: {
     health_state: 'Health State',
     max_connections: 'Max Connections',

+ 10 - 0
dolphinscheduler-ui-next/src/locales/modules/zh_CN.ts

@@ -115,6 +115,16 @@ const profile = {
 }
 
 const monitor = {
+  master: {
+    cpu_usage: '处理器使用量',
+    memory_usage: '内存使用量',
+    load_average: '平均负载量',
+    create_time: '创建时间',
+    last_heartbeat_time: '最后心跳时间',
+    directory_detail: '目录详情',
+    host: '主机',
+    directory: '注册目录',
+  },
   db: {
     health_state: '健康状态',
     max_connections: '最大连接数',

+ 1 - 1
dolphinscheduler-ui-next/src/router/modules/monitor.ts

@@ -32,7 +32,7 @@ export default {
     {
       path: '/monitor/servers/master',
       name: 'servers-master',
-      component: components['home'],
+      component: components['master'],
       meta: {
         title: '服务管理-Master',
       },

+ 11 - 1
dolphinscheduler-ui-next/src/service/modules/monitor/types.ts

@@ -25,4 +25,14 @@ interface DatabaseRes {
   date: string
 }
 
-export { DatabaseRes }
+interface MasterRes {
+  id: number
+  host: string
+  port: number
+  zkDirectory: string
+  resInfo: string
+  createTime: string
+  lastHeartbeatTime: string
+}
+
+export { DatabaseRes, MasterRes }

+ 56 - 0
dolphinscheduler-ui-next/src/views/monitor/servers/master/index.module.scss

@@ -0,0 +1,56 @@
+/*
+ * 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
+ *
+ *    http://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.
+ */
+
+@mixin base {
+  font-size: 100px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  min-height: 400px;
+}
+
+.header-card {
+  margin-bottom: 8px;
+
+  .content {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+
+    .left {
+      margin-right: 20px;
+    }
+  }
+
+  .link-btn {
+    color: #579cd8;
+    cursor: pointer;
+
+    &:hover {
+      color: #80bef7;
+    }
+  }
+}
+
+.card {
+  @include base;
+}
+
+.load-average {
+  @include base;
+  color: dodgerblue;
+}

+ 136 - 0
dolphinscheduler-ui-next/src/views/monitor/servers/master/index.tsx

@@ -0,0 +1,136 @@
+/*
+ * 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
+ *
+ *    http://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 { defineComponent, ref } from 'vue'
+import { NGrid, NGi, NCard, NNumberAnimation, NDataTable } from 'naive-ui'
+import { useI18n } from 'vue-i18n'
+import { useMaster } from './use-master'
+import styles from './index.module.scss'
+import Card from '@/components/card'
+import Gauge from '@/components/chart/modules/Gauge'
+import Modal from '@/components/modal'
+import type { MasterRes } from '@/service/modules/monitor/types'
+import type { Ref } from 'vue'
+import type { TableColumns } from 'naive-ui/es/data-table/src/interface'
+
+const master = defineComponent({
+  name: 'master',
+  setup() {
+    let showModalRef = ref(false)
+    const { t } = useI18n()
+    const { getMaster } = useMaster()
+    const masterRef: Ref<Array<MasterRes>> = ref(getMaster())
+    const columnsRef: TableColumns<any> = [
+      { title: '#', key: 'id' },
+      { title: t('monitor.master.directory'), key: 'directory' },
+    ]
+
+    return { t, masterRef, showModalRef, columnsRef }
+  },
+  render() {
+    const { t, masterRef, columnsRef } = this
+
+    return (
+      <div>
+        <NCard class={styles['header-card']}>
+          <div class={styles['content']}>
+            <p>
+              <span class={styles.left}>{`${t('monitor.master.host')}: ${
+                masterRef[0] ? masterRef[0].host : ' - '
+              }`}</span>
+              <span
+                class={styles['link-btn']}
+                onClick={() => (this.showModalRef = true)}
+              >
+                {t('monitor.master.directory_detail')}
+              </span>
+            </p>
+            <p>
+              <span class={styles.left}>{`${t('monitor.master.create_time')}: ${
+                masterRef[0] ? masterRef[0].createTime : ' - '
+              }`}</span>
+              <span>{`${t('monitor.master.last_heartbeat_time')}: ${
+                masterRef[0] ? masterRef[0].lastHeartbeatTime : ' - '
+              }`}</span>
+            </p>
+          </div>
+        </NCard>
+        <NGrid x-gap='12' cols='3'>
+          <NGi>
+            <Card title={t('monitor.master.cpu_usage')}>
+              <div class={styles.card}>
+                {masterRef[0] && (
+                  <Gauge
+                    data={(
+                      JSON.parse(masterRef[0].resInfo).cpuUsage * 100
+                    ).toFixed(2)}
+                  />
+                )}
+              </div>
+            </Card>
+          </NGi>
+          <NGi>
+            <Card title={t('monitor.master.memory_usage')}>
+              <div class={styles.card}>
+                {masterRef[0] && (
+                  <Gauge
+                    data={(
+                      JSON.parse(masterRef[0].resInfo).memoryUsage * 100
+                    ).toFixed(2)}
+                  />
+                )}
+              </div>
+            </Card>
+          </NGi>
+          <NGi>
+            <Card title={t('monitor.master.load_average')}>
+              <div class={[styles.card, styles['load-average']]}>
+                {masterRef[0] && (
+                  <NNumberAnimation
+                    precision={2}
+                    from={0}
+                    to={JSON.parse(masterRef[0].resInfo).loadAverage}
+                  />
+                )}
+              </div>
+            </Card>
+          </NGi>
+        </NGrid>
+        <Modal
+          title={t('monitor.master.directory_detail')}
+          show={this.showModalRef}
+          cancelShow={false}
+          onConfirm={() => (this.showModalRef = false)}
+        >
+          {{
+            default: () =>
+              masterRef[0] && (
+                <NDataTable
+                  columns={columnsRef}
+                  data={[{ id: 1, directory: masterRef[0].zkDirectory }]}
+                  striped
+                  size={'small'}
+                />
+              ),
+          }}
+        </Modal>
+      </div>
+    )
+  },
+})
+
+export default master

+ 28 - 0
dolphinscheduler-ui-next/src/views/monitor/servers/master/use-master.ts

@@ -0,0 +1,28 @@
+/*
+ * 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
+ *
+ *    http://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 { useAsyncState } from '@vueuse/core'
+import { listMaster } from '@/service/modules/monitor'
+
+export function useMaster() {
+  const getMaster = () => {
+    const { state } = useAsyncState(listMaster(), [])
+    return state
+  }
+
+  return { getMaster }
+}