Procházet zdrojové kódy

feat(home): 支持按公司展示不同首页看板

- rd、jt 使用报表 iframe 并携带 SSO token
- rh、ry 使用对应本地看板组件
- 其它公司保留默认首页看板
Zimo před 1 týdnem
rodič
revize
1952201b05
3 změnil soubory, kde provedl 208 přidání a 101 odebrání
  1. 1 1
      .env.local
  2. 91 100
      src/views/Home/Index.vue
  3. 116 0
      src/views/Home/stat.vue

+ 1 - 1
.env.local

@@ -4,7 +4,7 @@ NODE_ENV=development
 VITE_DEV=true
 
 # 请求路径  http://192.168.188.79:48080  https://iot.deepoil.cc  http://172.26.0.56:48080
-VITE_BASE_URL='http://192.168.188.199:48080'
+VITE_BASE_URL='https://iot.deepoil.cc'
 
 # 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持 S3 服务
 VITE_UPLOAD_TYPE=server

+ 91 - 100
src/views/Home/Index.vue

@@ -1,116 +1,107 @@
 <script lang="ts" setup>
-import { DESIGN_HEIGHT, DESIGN_WIDTH } from '@/utils/kb'
-import hsummary from './kb/hsummary.vue'
-import hdeviceType from './kb/hdeviceType.vue'
-import dayfinish from './kb/dayfinish.vue'
-import hsafe from './kb/hsafe.vue'
-import hdeviceStatus from './kb/hdeviceStatus.vue'
-import horderTrend from './kb/horderTrend.vue'
-
-const company = ref('首页')
-
-const wrapperRef = ref<HTMLDivElement>()
-const scale = ref(1)
-
-let resizeObserver: ResizeObserver | null = null
-let resizeRaf = 0
-
-provide('homeKbScale', scale)
-
-const targetWrapperStyle = computed(() => ({
-  width: `${DESIGN_WIDTH * scale.value}px`,
-  height: `${DESIGN_HEIGHT * scale.value}px`
-}))
-
-const targetAreaStyle = computed(() => {
-  return {
-    '--kb-scale': scale.value,
-    width: `${DESIGN_WIDTH * scale.value}px`,
-    height: `${DESIGN_HEIGHT * scale.value}px`
-  }
-})
-
-function updateScale() {
-  cancelAnimationFrame(resizeRaf)
-
-  resizeRaf = requestAnimationFrame(() => {
-    const wrapper = wrapperRef.value
-    if (!wrapper) return
-
-    const { clientWidth, clientHeight } = wrapper
-    if (!clientWidth || !clientHeight) return
-
-    scale.value = Math.min(clientWidth / DESIGN_WIDTH, clientHeight / DESIGN_HEIGHT)
-    nextTick(() => {
-      window.dispatchEvent(new Event('homekb:resize'))
-    })
-  })
+import { IotOpeationFillApi } from '@/api/pms/iotopeationfill'
+import { IotStatApi } from '@/api/pms/stat'
+import { useUserStore } from '@/store/modules/user'
+import Rhkb from '@/views/pms/stat/rhkb.vue'
+import Rykb from '@/views/pms/stat/rykb.vue'
+import Stat from './stat.vue'
+
+const user = useUserStore().getUser
+
+const company = ref<string>('')
+const companyLoading = ref(true)
+const iframeUrl = ref('')
+const iframeLoading = ref(false)
+let iframeRequestId = 0
+
+const reportUrls: Record<string, string> = {
+  rd: 'https://report.deepoil.cc/webroot/decision/v10/entry/access/a12df128-c84f-44be-a55d-bababbf4a132?preview=true&page_number=1',
+  jt: 'https://report.deepoil.cc/webroot/decision/v10/entry/access/dbc9cf73-81ce-43f1-9923-45cdfa5d5d3a?preview=true&page_number=1'
 }
 
-onMounted(() => {
-  nextTick(updateScale)
-  resizeObserver = new ResizeObserver(updateScale)
-  if (wrapperRef.value) {
-    resizeObserver.observe(wrapperRef.value)
-  }
-  window.addEventListener('resize', updateScale)
+const currentCompany = computed(() => company.value?.toLowerCase())
+const currentView = computed(() => {
+  if (companyLoading.value) return 'loading'
+  if (currentCompany.value === 'rh') return 'rh'
+  if (currentCompany.value === 'ry') return 'ry'
+  if (currentCompany.value && reportUrls[currentCompany.value]) return 'report'
+  return 'stat'
 })
 
-onUnmounted(() => {
-  resizeObserver?.disconnect()
-  window.removeEventListener('resize', updateScale)
-  cancelAnimationFrame(resizeRaf)
-})
+watch(
+  () => user.deptId,
+  async (val) => {
+    companyLoading.value = true
+    try {
+      if (!val) {
+        company.value = ''
+        return
+      }
+      company.value = await IotOpeationFillApi.getOrgName(val)
+    } finally {
+      companyLoading.value = false
+    }
+  },
+  { immediate: true }
+)
+
+watch(
+  currentCompany,
+  async (val) => {
+    const requestId = ++iframeRequestId
+    iframeUrl.value = ''
+    const reportUrl = val ? reportUrls[val] : ''
+    if (!reportUrl) {
+      iframeLoading.value = false
+      return
+    }
+
+    iframeLoading.value = true
+    try {
+      const token = await IotStatApi.getSsoToken()
+      if (requestId !== iframeRequestId) return
+      iframeUrl.value = `${reportUrl}&ssoToken=${token}`
+    } finally {
+      if (requestId === iframeRequestId) {
+        iframeLoading.value = false
+      }
+    }
+  },
+  { immediate: true }
+)
 </script>
 <template>
-  <div ref="wrapperRef" class="bg absolute top-0 left-0 size-full z-10">
-    <div class="mx-a overflow-hidden" :style="targetWrapperStyle">
-      <div class="bg kb-screen" :style="targetAreaStyle">
-        <header class="header">{{ company }}</header>
-        <div class="kb-content">
-          <hsummary class="kb-stage-card kb-stage-card--1" />
-          <div class="home-top-grid">
-            <!-- <hmttr class="kb-stage-card kb-stage-card--2" /> -->
-            <hsafe class="row-span-2 kb-stage-card kb-stage-card--3" />
-            <hdeviceType class="row-span-2 kb-stage-card kb-stage-card--4" />
-            <dayfinish class="row-span-2 kb-stage-card kb-stage-card--5" />
-          </div>
-          <div class="home-bottom-grid">
-            <hdeviceStatus class="kb-stage-card kb-stage-card--6" />
-            <horderTrend class="kb-stage-card kb-stage-card--7" />
-          </div>
-        </div>
-      </div>
-    </div>
+  <div v-if="currentView === 'loading'" class="full-screen-container" v-loading="true"></div>
+  <div v-else-if="currentView === 'report'" class="full-screen-container" v-loading="iframeLoading">
+    <iframe
+      v-if="iframeUrl"
+      :src="iframeUrl"
+      frameborder="0"
+      class="full-screen-iframe"
+      allowfullscreen></iframe>
   </div>
+  <Rhkb v-else-if="currentView === 'rh'" />
+  <Rykb v-else-if="currentView === 'ry'" />
+  <Stat v-else />
 </template>
-<style lang="scss" scoped>
-@import url('@/styles/kb.scss');
 
-.kb-screen {
+<style scoped>
+.full-screen-container {
+  position: absolute;
+  inset: 0;
+  z-index: 1;
+  width: 100%;
+  height: calc(100vh - 90px);
   overflow: hidden;
 }
 
-.kb-content {
-  padding: calc(12px * var(--kb-scale)) calc(20px * var(--kb-scale)) 0;
-}
-
-.home-top-grid,
-.home-bottom-grid {
-  display: grid;
+.full-screen-iframe {
+  display: block;
   width: 100%;
-  margin-top: calc(12px * var(--kb-scale));
-  gap: calc(12px * var(--kb-scale));
-}
-
-.home-top-grid {
-  height: calc(384px * var(--kb-scale));
-  grid-template-rows: repeat(2, minmax(0, 1fr));
-  grid-template-columns: repeat(3, minmax(0, 1fr));
-}
-
-.home-bottom-grid {
-  height: calc(428px * var(--kb-scale));
-  grid-template-columns: repeat(2, minmax(0, 1fr));
+  height: 100%;
+  padding: 0;
+  margin: 0;
+  overflow: auto;
+  border: none;
 }
 </style>

+ 116 - 0
src/views/Home/stat.vue

@@ -0,0 +1,116 @@
+<script lang="ts" setup>
+import { DESIGN_HEIGHT, DESIGN_WIDTH } from '@/utils/kb'
+import hsummary from './kb/hsummary.vue'
+import hdeviceType from './kb/hdeviceType.vue'
+import dayfinish from './kb/dayfinish.vue'
+import hsafe from './kb/hsafe.vue'
+import hdeviceStatus from './kb/hdeviceStatus.vue'
+import horderTrend from './kb/horderTrend.vue'
+
+const company = ref('首页')
+
+const wrapperRef = ref<HTMLDivElement>()
+const scale = ref(1)
+
+let resizeObserver: ResizeObserver | null = null
+let resizeRaf = 0
+
+provide('homeKbScale', scale)
+
+const targetWrapperStyle = computed(() => ({
+  width: `${DESIGN_WIDTH * scale.value}px`,
+  height: `${DESIGN_HEIGHT * scale.value}px`
+}))
+
+const targetAreaStyle = computed(() => {
+  return {
+    '--kb-scale': scale.value,
+    width: `${DESIGN_WIDTH * scale.value}px`,
+    height: `${DESIGN_HEIGHT * scale.value}px`
+  }
+})
+
+function updateScale() {
+  cancelAnimationFrame(resizeRaf)
+
+  resizeRaf = requestAnimationFrame(() => {
+    const wrapper = wrapperRef.value
+    if (!wrapper) return
+
+    const { clientWidth, clientHeight } = wrapper
+    if (!clientWidth || !clientHeight) return
+
+    scale.value = Math.min(clientWidth / DESIGN_WIDTH, clientHeight / DESIGN_HEIGHT)
+    nextTick(() => {
+      window.dispatchEvent(new Event('homekb:resize'))
+    })
+  })
+}
+
+onMounted(() => {
+  nextTick(updateScale)
+  resizeObserver = new ResizeObserver(updateScale)
+  if (wrapperRef.value) {
+    resizeObserver.observe(wrapperRef.value)
+  }
+  window.addEventListener('resize', updateScale)
+})
+
+onUnmounted(() => {
+  resizeObserver?.disconnect()
+  window.removeEventListener('resize', updateScale)
+  cancelAnimationFrame(resizeRaf)
+})
+</script>
+<template>
+  <div ref="wrapperRef" class="bg absolute top-0 left-0 size-full z-10">
+    <div class="mx-a overflow-hidden" :style="targetWrapperStyle">
+      <div class="bg kb-screen" :style="targetAreaStyle">
+        <header class="header">{{ company }}</header>
+        <div class="kb-content">
+          <hsummary class="kb-stage-card kb-stage-card--1" />
+          <div class="home-top-grid">
+            <!-- <hmttr class="kb-stage-card kb-stage-card--2" /> -->
+            <hsafe class="row-span-2 kb-stage-card kb-stage-card--3" />
+            <hdeviceType class="row-span-2 kb-stage-card kb-stage-card--4" />
+            <dayfinish class="row-span-2 kb-stage-card kb-stage-card--5" />
+          </div>
+          <div class="home-bottom-grid">
+            <hdeviceStatus class="kb-stage-card kb-stage-card--6" />
+            <horderTrend class="kb-stage-card kb-stage-card--7" />
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<style lang="scss" scoped>
+@import url('@/styles/kb.scss');
+
+.kb-screen {
+  overflow: hidden;
+}
+
+.kb-content {
+  padding: calc(12px * var(--kb-scale)) calc(20px * var(--kb-scale)) 0;
+}
+
+.home-top-grid,
+.home-bottom-grid {
+  display: grid;
+  width: 100%;
+  margin-top: calc(12px * var(--kb-scale));
+  gap: calc(12px * var(--kb-scale));
+}
+
+.home-top-grid {
+  height: calc(384px * var(--kb-scale));
+  grid-template-rows: repeat(2, minmax(0, 1fr));
+  grid-template-columns: repeat(3, minmax(0, 1fr));
+}
+
+.home-bottom-grid {
+  height: calc(428px * var(--kb-scale));
+  grid-template-columns: repeat(2, minmax(0, 1fr));
+}
+</style>