Browse Source

[Feature][UI Next] Add charts setting. (#7543)

songjianet 3 years ago
parent
commit
46fa9ed9c8

+ 2 - 0
dolphinscheduler-ui-next/package.json

@@ -12,6 +12,8 @@
   "dependencies": {
     "@vueuse/core": "^7.2.2",
     "axios": "^0.24.0",
+    "echarts": "^5.2.2",
+    "lodash": "^4.17.21",
     "date-fns": "^2.27.0",
     "naive-ui": "^2.21.5",
     "nprogress": "^0.2.0",

+ 66 - 0
dolphinscheduler-ui-next/src/components/chart/index.ts

@@ -0,0 +1,66 @@
+/*
+ * 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 { getCurrentInstance, onMounted, onBeforeUnmount, watch } from 'vue'
+import { useThemeStore } from '@/store/theme/theme'
+import { throttle } from 'echarts'
+import type { Ref } from 'vue'
+import type { ECharts } from 'echarts'
+import type { ECBasicOption } from 'echarts/types/dist/shared'
+
+function initChart<Opt extends ECBasicOption>(
+  domRef: Ref<HTMLDivElement | null>,
+  option: Opt
+): ECharts | null {
+  let chart: ECharts | null = null
+  const themeStore = useThemeStore()
+  const globalProperties =
+    getCurrentInstance()?.appContext.config.globalProperties
+
+  const init = () => {
+    chart = globalProperties?.echarts.init(
+      domRef.value,
+      themeStore.darkTheme ? 'dark-bold' : 'macarons'
+    )
+    chart && chart.setOption(option)
+  }
+
+  const resize = throttle(() => {
+    chart && chart.resize()
+  }, 20)
+
+  watch(
+    () => themeStore.darkTheme,
+    () => {
+      chart?.dispose()
+      init()
+    }
+  )
+
+  onMounted(() => {
+    init()
+    addEventListener('resize', resize)
+  })
+
+  onBeforeUnmount(() => {
+    removeEventListener('resize', resize)
+  })
+
+  return chart
+}
+
+export default initChart

+ 106 - 0
dolphinscheduler-ui-next/src/components/chart/modules/Gauge.tsx

@@ -0,0 +1,106 @@
+/*
+ * 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, PropType, ref } from 'vue'
+import initChart from '@/components/chart'
+import type { Ref } from 'vue'
+
+const props = {
+  height: {
+    type: [String, Number] as PropType<string | number>,
+    default: 400,
+  },
+  width: {
+    type: [String, Number] as PropType<string | number>,
+    default: 400,
+  },
+}
+
+const GaugeChart = defineComponent({
+  name: 'GaugeChart',
+  props,
+  setup() {
+    const gaugeChartRef: Ref<HTMLDivElement | null> = ref(null)
+
+    const option = {
+      series: [
+        {
+          type: 'gauge',
+          axisLine: {
+            lineStyle: {
+              width: 30,
+            },
+          },
+          pointer: {
+            itemStyle: {
+              color: 'auto',
+            },
+          },
+          axisTick: {
+            distance: -30,
+            length: 8,
+            lineStyle: {
+              color: '#fff',
+              width: 2,
+            },
+          },
+          splitLine: {
+            distance: -30,
+            length: 30,
+            lineStyle: {
+              color: '#fff',
+              width: 4,
+            },
+          },
+          axisLabel: {
+            color: 'auto',
+            distance: 40,
+            fontSize: 20,
+          },
+          detail: {
+            valueAnimation: true,
+            formatter: '{value} km/h',
+            color: 'auto',
+          },
+          data: [
+            {
+              value: 70,
+            },
+          ],
+        },
+      ],
+    }
+
+    initChart(gaugeChartRef, option)
+
+    return { gaugeChartRef }
+  },
+  render() {
+    const { height, width } = this
+    return (
+      <div
+        ref='gaugeChartRef'
+        style={{
+          height: typeof height === 'number' ? height + 'px' : height,
+          width: typeof width === 'number' ? width + 'px' : width,
+        }}
+      />
+    )
+  },
+})
+
+export default GaugeChart

+ 97 - 0
dolphinscheduler-ui-next/src/components/chart/modules/Pie.tsx

@@ -0,0 +1,97 @@
+/*
+ * 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, PropType, ref } from 'vue'
+import initChart from '@/components/chart'
+import type { Ref } from 'vue'
+
+const props = {
+  height: {
+    type: [String, Number] as PropType<string | number>,
+    default: 400,
+  },
+  width: {
+    type: [String, Number] as PropType<string | number>,
+    default: 400,
+  },
+}
+
+const PieChart = defineComponent({
+  name: 'PieChart',
+  props,
+  setup() {
+    const pieChartRef: Ref<HTMLDivElement | null> = ref(null)
+
+    const option = {
+      tooltip: {
+        trigger: 'item',
+        backgroundColor: '#fff',
+      },
+      legend: {
+        top: '5%',
+        left: 'center',
+      },
+      series: [
+        {
+          name: 'Access From',
+          type: 'pie',
+          radius: ['40%', '70%'],
+          avoidLabelOverlap: false,
+          label: {
+            show: false,
+            position: 'center',
+          },
+          emphasis: {
+            label: {
+              show: true,
+              fontSize: '40',
+              fontWeight: 'bold',
+            },
+          },
+          labelLine: {
+            show: false,
+          },
+          data: [
+            { value: 1048, name: 'Search Engine' },
+            { value: 735, name: 'Direct' },
+            { value: 580, name: 'Email' },
+            { value: 484, name: 'Union Ads' },
+            { value: 300, name: 'Video Ads' },
+          ],
+        },
+      ],
+    }
+
+    initChart(pieChartRef, option)
+
+    return { pieChartRef }
+  },
+  render() {
+    const { height, width } = this
+    return (
+      <div
+        ref='pieChartRef'
+        style={{
+          height: typeof height === 'number' ? height + 'px' : height,
+          width: typeof width === 'number' ? width + 'px' : width,
+        }}
+      />
+    )
+  },
+})
+
+export default PieChart

+ 0 - 24
dolphinscheduler-ui-next/src/components/table/DSTable.tsx

@@ -1,24 +0,0 @@
-/*
- * 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 } from 'vue'
-
-const DSTable = defineComponent({
-  name: 'DSTable',
-})
-
-export default DSTable

+ 21 - 20
dolphinscheduler-ui-next/src/layouts/basic/components/sider/index.tsx

@@ -50,27 +50,28 @@ const Sider = defineComponent({
     return { handleMenuClick }
   },
   render() {
-    return 
-      this.visible ?
-      (
-        <NLayoutSider
-          width={240}
-          collapseMode={'width'}
-          collapsedWidth={64}
+    return
+    this.visible ? (
+      <NLayoutSider
+        width={240}
+        collapseMode={'width'}
+        collapsedWidth={64}
+        inverted={this.inverted}
+        nativeScrollbar={false}
+        show-trigger
+        bordered
+      >
+        <NMenu
+          onUpdate:value={this.handleMenuClick}
           inverted={this.inverted}
-          nativeScrollbar={false}
-          show-trigger
-          bordered
-        >
-          <NMenu
-            onUpdate:value={this.handleMenuClick}
-            inverted={this.inverted}
-            collapsedWidth={64}
-            collapsedIconSize={22}
-            options={this.menuOptions}
-          />
-        </NLayoutSider>
-      ) : ''
+          collapsedWidth={64}
+          collapsedIconSize={22}
+          options={this.menuOptions}
+        />
+      </NLayoutSider>
+    ) : (
+      ''
+    )
   },
 })
 

+ 0 - 34
dolphinscheduler-ui-next/src/layouts/content/Content.tsx

@@ -1,34 +0,0 @@
-/*
- * 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 } from 'vue'
-import { NLayout, NLayoutContent } from 'naive-ui'
-
-const Content = defineComponent({
-  name: 'Content',
-  render() {
-    return (
-      <NLayout>
-        <NLayoutContent>
-          <router-view />
-        </NLayoutContent>
-      </NLayout>
-    )
-  },
-})
-
-export default Content

+ 4 - 0
dolphinscheduler-ui-next/src/main.ts

@@ -20,9 +20,13 @@ import App from './App'
 import router from './router'
 import { createPinia } from 'pinia'
 import i18n from '@/locales'
+import * as echarts from 'echarts'
+import 'echarts/theme/macarons'
+import 'echarts/theme/dark-bold'
 import './assets/styles/default.scss'
 
 const app = createApp(App)
+app.config.globalProperties.echarts = echarts
 app.use(router)
 app.use(createPinia())
 app.use(i18n)

+ 4 - 4
dolphinscheduler-ui-next/src/router/modules/datasource.ts

@@ -34,8 +34,8 @@ export default {
       name: 'datasource-list',
       component: components['home'],
       meta: {
-        title: '数据源中心'
-      }
-    }
-  ]
+        title: '数据源中心',
+      },
+    },
+  ],
 }

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

@@ -42,8 +42,8 @@ export default {
       name: 'servers-worker',
       component: components['home'],
       meta: {
-        title: '服务管理-Worker'
-      }
-    }
-  ]
+        title: '服务管理-Worker',
+      },
+    },
+  ],
 }

+ 4 - 4
dolphinscheduler-ui-next/src/router/modules/projects.ts

@@ -42,8 +42,8 @@ export default {
       name: 'projects-index',
       component: components['home'],
       meta: {
-        title: '工作流监控'
-      }
-    }
-  ]
+        title: '工作流监控',
+      },
+    },
+  ],
 }

+ 4 - 4
dolphinscheduler-ui-next/src/router/modules/resources.ts

@@ -42,8 +42,8 @@ export default {
       name: 'resource-file-create',
       component: components['home'],
       meta: {
-        title: '创建资源'
-      }
-    }
-  ]
+        title: '创建资源',
+      },
+    },
+  ],
 }

+ 4 - 4
dolphinscheduler-ui-next/src/router/modules/security.ts

@@ -42,8 +42,8 @@ export default {
       name: 'users-manage',
       component: components['home'],
       meta: {
-        title: '用户管理'
-      }
-    }
-  ]
+        title: '用户管理',
+      },
+    },
+  ],
 }

+ 10 - 10
dolphinscheduler-ui-next/src/store/route/route.ts

@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import { toRaw } from "vue";
-import { defineStore } from "pinia";
-import RouteState from "./types";
-import { RouteRecordRaw } from "vue-router";
+import { toRaw } from 'vue'
+import { defineStore } from 'pinia'
+import RouteState from './types'
+import { RouteRecordRaw } from 'vue-router'
 
 export const useAsyncRouteStore = defineStore({
-  id: "route",
+  id: 'route',
   state: (): RouteState => ({
     menus: [],
     routers: [],
@@ -29,18 +29,18 @@ export const useAsyncRouteStore = defineStore({
   }),
   getters: {
     getMenus(): RouteRecordRaw[] {
-      return this.menus;
+      return this.menus
     },
     getRouters(): RouteRecordRaw[] {
-      return toRaw(this.addRouters);
+      return toRaw(this.addRouters)
     },
   },
   actions: {
     setMenus(menus) {
-      this.menus = menus;
+      this.menus = menus
     },
     async generateRouters(routes) {
-      console.log(routes);
+      console.log(routes)
     },
   },
-});
+})

+ 5 - 5
dolphinscheduler-ui-next/src/store/route/types.ts

@@ -14,12 +14,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import { RouteRecordRaw } from "vue-router";
+import { RouteRecordRaw } from 'vue-router'
 
 interface RouteState {
-  menus: RouteRecordRaw[];
-  routers: any[];
-  addRouters: any[];
+  menus: RouteRecordRaw[]
+  routers: any[]
+  addRouters: any[]
 }
 
-export default RouteState;
+export default RouteState

+ 9 - 1
dolphinscheduler-ui-next/src/views/home/index.tsx

@@ -17,11 +17,19 @@
 
 import { defineComponent } from 'vue'
 import styles from './index.module.scss'
+import PieChart from '@/components/chart/modules/Pie'
+import GaugeChart from '@/components/chart/modules/Gauge'
 
 export default defineComponent({
   name: 'home',
   setup() {},
   render() {
-    return <div class={styles.container}>Home Test</div>
+    return (
+      <div class={styles.container}>
+        Home Test
+        <PieChart />
+        <GaugeChart />
+      </div>
+    )
   },
 })

+ 6 - 1
dolphinscheduler-ui-next/src/views/login/index.tsx

@@ -82,7 +82,12 @@ const login = defineComponent({
                 />
               </NFormItem>
             </NForm>
-            <NButton round type='primary' onClick={this.handleLogin}>
+            <NButton
+              round
+              type='info'
+              style={{ width: '100%' }}
+              onClick={this.handleLogin}
+            >
               {this.t('login.signin')}
             </NButton>
           </div>

+ 4 - 4
dolphinscheduler-ui-next/src/views/login/use-login.ts

@@ -19,12 +19,12 @@ import { useRouter } from 'vue-router'
 import type { Router } from 'vue-router'
 import { queryLog } from '@/service/modules/login'
 
-export function useLogin (state) {
+export function useLogin(state: any) {
   const router: Router = useRouter()
   const handleLogin = () => {
     state.loginFormRef.validate((valid: any) => {
       if (!valid) {
-        queryLog({...state.loginForm}).then((res: Response) => {
+        queryLog({ ...state.loginForm }).then((res: Response) => {
           console.log('res', res)
           router.push({ path: 'home' })
         })
@@ -34,6 +34,6 @@ export function useLogin (state) {
     })
   }
   return {
-    handleLogin
+    handleLogin,
   }
-}
+}

+ 4 - 4
dolphinscheduler-ui-next/src/views/login/use-translate.ts

@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import { WritableComputedRef } from "vue"
+import { WritableComputedRef } from 'vue'
 
-export function useTranslate (locale: WritableComputedRef<string>) {
+export function useTranslate(locale: WritableComputedRef<string>) {
   const handleChange = (value: string) => {
     locale.value = value
   }
   return {
-    handleChange
+    handleChange,
   }
-}
+}

+ 5 - 3
dolphinscheduler-ui-next/src/views/login/use-validate.ts

@@ -19,7 +19,7 @@ import { reactive, ref } from 'vue'
 import { FormRules } from 'naive-ui'
 import { useI18n } from 'vue-i18n'
 
-export function useValidate () {
+export function useValidate() {
   const { t, locale } = useI18n()
   const state = reactive({
     loginFormRef: ref(),
@@ -48,6 +48,8 @@ export function useValidate () {
   })
 
   return {
-    state, t, locale
+    state,
+    t,
+    locale,
   }
-}
+}