Răsfoiți Sursa

修复看板缩放导致图标显示错误问题

Zimo 2 zile în urmă
părinte
comite
e06b07656f

+ 138 - 48
src/styles/kb.scss

@@ -14,9 +14,9 @@
 }
 }
 
 
 .header {
 .header {
-  height: 52px;
+  height: calc(52px * var(--kb-scale, 1));
   font-family: YouSheBiaoTiHei, sans-serif;
   font-family: YouSheBiaoTiHei, sans-serif;
-  font-size: 32px;
+  font-size: calc(32px * var(--kb-scale, 1));
   color: var(--fvs-theme-color-1-2);
   color: var(--fvs-theme-color-1-2);
   text-align: center;
   text-align: center;
   background: url('@/assets/kb/header.png') center center / 100% 100% no-repeat;
   background: url('@/assets/kb/header.png') center center / 100% 100% no-repeat;
@@ -25,7 +25,7 @@
 .panel {
 .panel {
   background: linear-gradient(180deg, rgb(235 243 255 / 76%) 0%, rgb(221 233 251 / 58%) 100%);
   background: linear-gradient(180deg, rgb(235 243 255 / 76%) 0%, rgb(221 233 251 / 58%) 100%);
   border: 1px solid rgb(255 255 255 / 58%);
   border: 1px solid rgb(255 255 255 / 58%);
-  border-radius: 20px;
+  border-radius: calc(20px * var(--kb-scale, 1));
   box-shadow:
   box-shadow:
     inset 0 1px 0 rgb(255 255 255 / 72%),
     inset 0 1px 0 rgb(255 255 255 / 72%),
     0 18px 36px rgb(46 90 164 / 12%);
     0 18px 36px rgb(46 90 164 / 12%);
@@ -35,19 +35,20 @@
 .panel-title {
 .panel-title {
   position: relative;
   position: relative;
   display: flex;
   display: flex;
-  padding: 0 16px 0 36px;
+  height: calc(36px * var(--kb-scale, 1));
+  padding: 0 calc(16px * var(--kb-scale, 1)) 0 calc(36px * var(--kb-scale, 1));
   font-family: YouSheBiaoTiHei, sans-serif;
   font-family: YouSheBiaoTiHei, sans-serif;
-  font-size: 24px;
+  font-size: calc(24px * var(--kb-scale, 1));
   letter-spacing: 1px;
   letter-spacing: 1px;
   color: #03409b;
   color: #03409b;
   align-items: center;
   align-items: center;
 
 
   &::after {
   &::after {
     position: absolute;
     position: absolute;
-    right: 10px;
+    right: calc(10px * var(--kb-scale, 1));
     bottom: 0;
     bottom: 0;
-    left: 10px;
-    height: 2px;
+    left: calc(10px * var(--kb-scale, 1));
+    height: calc(2px * var(--kb-scale, 1));
     background: linear-gradient(
     background: linear-gradient(
       to right,
       to right,
       rgb(3 64 155 / 15%) 0%,
       rgb(3 64 155 / 15%) 0%,
@@ -60,46 +61,135 @@
 
 
   &::before {
   &::before {
     position: absolute;
     position: absolute;
-    right: 10px;
+    right: calc(10px * var(--kb-scale, 1));
     bottom: 0;
     bottom: 0;
     z-index: 1;
     z-index: 1;
-    width: 80px;
-    height: 4px;
+    width: calc(80px * var(--kb-scale, 1));
+    height: calc(4px * var(--kb-scale, 1));
     background: #03409b;
     background: #03409b;
-    border-radius: 2px 2px 0 0;
+    border-radius: calc(2px * var(--kb-scale, 1)) calc(2px * var(--kb-scale, 1)) 0 0;
     content: '';
     content: '';
   }
   }
 
 
   .icon-decorator {
   .icon-decorator {
     position: absolute;
     position: absolute;
-    left: 14px;
+    left: calc(14px * var(--kb-scale, 1));
     display: flex;
     display: flex;
     align-items: center;
     align-items: center;
-    gap: 3px;
+    gap: calc(3px * var(--kb-scale, 1));
 
 
     span {
     span {
-      width: 4px;
-      height: 18px;
+      width: calc(4px * var(--kb-scale, 1));
+      height: calc(18px * var(--kb-scale, 1));
       background: #03409b;
       background: #03409b;
-      border-radius: 2px;
+      border-radius: calc(2px * var(--kb-scale, 1));
 
 
       &:last-child {
       &:last-child {
-        height: 12px;
+        height: calc(12px * var(--kb-scale, 1));
         opacity: 0.5;
         opacity: 0.5;
       }
       }
     }
     }
   }
   }
 }
 }
 
 
+.panel-title--lg {
+  height: calc(48px * var(--kb-scale, 1));
+}
+
+.panel-title--md {
+  height: calc(40px * var(--kb-scale, 1));
+}
+
 .kb-panel-title-text {
 .kb-panel-title-text {
   font-family: YouSheBiaoTiHei, sans-serif;
   font-family: YouSheBiaoTiHei, sans-serif;
-  font-size: 24px;
+  font-size: calc(24px * var(--kb-scale, 1));
   font-weight: normal;
   font-weight: normal;
   line-height: 1;
   line-height: 1;
   letter-spacing: 1px;
   letter-spacing: 1px;
   color: #03409b;
   color: #03409b;
 }
 }
 
 
+.summary-panel {
+  height: calc(112px * var(--kb-scale, 1));
+}
+
+.summary-panel__title {
+  height: calc(32px * var(--kb-scale, 1));
+}
+
+.summary-panel__grid {
+  padding: calc(6px * var(--kb-scale, 1)) calc(10px * var(--kb-scale, 1));
+  gap: calc(10px * var(--kb-scale, 1));
+}
+
+.summary-card {
+  gap: calc(8px * var(--kb-scale, 1));
+  padding: calc(8px * var(--kb-scale, 1));
+}
+
+.device-list-panel {
+  height: calc(280px * var(--kb-scale, 1));
+  margin-top: calc(12px * var(--kb-scale, 1));
+}
+
+.device-list-panel__body {
+  padding: calc(8px * var(--kb-scale, 1)) calc(16px * var(--kb-scale, 1));
+}
+
+.device-list-panel__picker {
+  display: flex;
+  width: calc(260px * var(--kb-scale, 1));
+  align-items: center;
+}
+
+.device-list-panel__picker-input {
+  width: calc(260px * var(--kb-scale, 1)) !important;
+
+  :deep(.el-input__wrapper) {
+    min-height: calc(28px * var(--kb-scale, 1));
+    padding: 0 calc(10px * var(--kb-scale, 1));
+  }
+
+  :deep(.el-range-input),
+  :deep(.el-range-separator) {
+    font-size: calc(12px * var(--kb-scale, 1));
+  }
+
+  :deep(.el-range__icon),
+  :deep(.el-range__close-icon) {
+    font-size: calc(14px * var(--kb-scale, 1));
+  }
+}
+
+.kb-inline-picker {
+  display: flex;
+  width: var(--kb-picker-width);
+  align-items: center;
+}
+
+.kb-inline-picker--260 {
+  --kb-picker-width: calc(260px * var(--kb-scale, 1));
+}
+
+.kb-inline-picker__input {
+  width: var(--kb-picker-width) !important;
+
+  :deep(.el-input__wrapper) {
+    min-height: calc(28px * var(--kb-scale, 1));
+    padding: 0 calc(10px * var(--kb-scale, 1));
+  }
+
+  :deep(.el-range-input),
+  :deep(.el-range-separator) {
+    font-size: calc(12px * var(--kb-scale, 1));
+  }
+
+  :deep(.el-range__icon),
+  :deep(.el-range__close-icon) {
+    font-size: calc(14px * var(--kb-scale, 1));
+  }
+}
+
 .summary-card {
 .summary-card {
   position: relative;
   position: relative;
   cursor: default;
   cursor: default;
@@ -132,11 +222,11 @@
 
 
 .summary-card::after {
 .summary-card::after {
   position: absolute;
   position: absolute;
-  right: -16px;
-  bottom: -28px;
+  right: calc(-16px * var(--kb-scale, 1));
+  bottom: calc(-28px * var(--kb-scale, 1));
   z-index: 0;
   z-index: 0;
-  width: 84px;
-  height: 84px;
+  width: calc(84px * var(--kb-scale, 1));
+  height: calc(84px * var(--kb-scale, 1));
   pointer-events: none;
   pointer-events: none;
   background: radial-gradient(circle, var(--card-glow) 0%, rgb(255 255 255 / 0%) 70%);
   background: radial-gradient(circle, var(--card-glow) 0%, rgb(255 255 255 / 0%) 70%);
   content: '';
   content: '';
@@ -188,11 +278,11 @@
   position: relative;
   position: relative;
   z-index: 2;
   z-index: 2;
   display: flex;
   display: flex;
-  width: 48px;
-  height: 48px;
+  width: calc(48px * var(--kb-scale, 1));
+  height: calc(48px * var(--kb-scale, 1));
   background: linear-gradient(180deg, rgb(255 255 255 / 96%) 0%, rgb(242 247 255 / 92%) 100%);
   background: linear-gradient(180deg, rgb(255 255 255 / 96%) 0%, rgb(242 247 255 / 92%) 100%);
   border: 1px solid rgb(255 255 255 / 88%);
   border: 1px solid rgb(255 255 255 / 88%);
-  border-radius: 12px;
+  border-radius: calc(12px * var(--kb-scale, 1));
   box-shadow:
   box-shadow:
     inset 0 1px 0 rgb(255 255 255 / 95%),
     inset 0 1px 0 rgb(255 255 255 / 95%),
     0 6px 12px rgb(152 181 230 / 15%);
     0 6px 12px rgb(152 181 230 / 15%);
@@ -206,10 +296,10 @@
 
 
 .summary-card__icon::after {
 .summary-card__icon::after {
   position: absolute;
   position: absolute;
-  right: -3px;
-  bottom: -3px;
-  width: 15px;
-  height: 15px;
+  right: calc(-3px * var(--kb-scale, 1));
+  bottom: calc(-3px * var(--kb-scale, 1));
+  width: calc(15px * var(--kb-scale, 1));
+  height: calc(15px * var(--kb-scale, 1));
   background: radial-gradient(
   background: radial-gradient(
     circle at 30% 30%,
     circle at 30% 30%,
     rgb(255 255 255 / 96%) 0%,
     rgb(255 255 255 / 96%) 0%,
@@ -231,7 +321,7 @@
 .summary-card__icon-glyph {
 .summary-card__icon-glyph {
   position: relative;
   position: relative;
   z-index: 1;
   z-index: 1;
-  font-size: 25px;
+  font-size: calc(25px * var(--kb-scale, 1));
   color: var(--card-accent);
   color: var(--card-accent);
   transition:
   transition:
     transform 0.28s ease,
     transform 0.28s ease,
@@ -247,7 +337,7 @@
   position: relative;
   position: relative;
   z-index: 2;
   z-index: 2;
   display: flex;
   display: flex;
-  min-height: 48px;
+  min-height: calc(48px * var(--kb-scale, 1));
   min-width: 0;
   min-width: 0;
   flex-direction: column;
   flex-direction: column;
   justify-content: center;
   justify-content: center;
@@ -255,7 +345,7 @@
 
 
 .summary-card__label {
 .summary-card__label {
   overflow: hidden;
   overflow: hidden;
-  font-size: 14px;
+  font-size: calc(14px * var(--kb-scale, 1));
   font-weight: 600;
   font-weight: 600;
   color: #24364f;
   color: #24364f;
   text-overflow: ellipsis;
   text-overflow: ellipsis;
@@ -266,9 +356,9 @@
 }
 }
 
 
 .summary-card__value {
 .summary-card__value {
-  margin-top: 4px;
+  margin-top: calc(4px * var(--kb-scale, 1));
   font-family: YouSheBiaoTiHei, sans-serif;
   font-family: YouSheBiaoTiHei, sans-serif;
-  font-size: 19px;
+  font-size: calc(19px * var(--kb-scale, 1));
   line-height: 1;
   line-height: 1;
   letter-spacing: 1px;
   letter-spacing: 1px;
   color: #1f5bb8;
   color: #1f5bb8;
@@ -292,8 +382,8 @@
   top: 0;
   top: 0;
   right: 0;
   right: 0;
   z-index: 1;
   z-index: 1;
-  width: 36px;
-  height: 36px;
+  width: calc(36px * var(--kb-scale, 1));
+  height: calc(36px * var(--kb-scale, 1));
   pointer-events: none;
   pointer-events: none;
   background: linear-gradient(135deg, rgb(255 255 255 / 30%) 0%, rgb(255 255 255 / 0%) 70%);
   background: linear-gradient(135deg, rgb(255 255 255 / 30%) 0%, rgb(255 255 255 / 0%) 70%);
   opacity: 0.85;
   opacity: 0.85;
@@ -359,7 +449,7 @@
 .summary-card__placeholder {
 .summary-card__placeholder {
   display: inline-block;
   display: inline-block;
   font-family: YouSheBiaoTiHei, sans-serif;
   font-family: YouSheBiaoTiHei, sans-serif;
-  font-size: 19px;
+  font-size: calc(19px * var(--kb-scale, 1));
   line-height: 1;
   line-height: 1;
   letter-spacing: 1px;
   letter-spacing: 1px;
   color: rgb(31 91 184 / 45%);
   color: rgb(31 91 184 / 45%);
@@ -383,7 +473,7 @@
 
 
   :deep(.el-table__header-wrapper th.el-table__cell) {
   :deep(.el-table__header-wrapper th.el-table__cell) {
     // font-family: YouSheBiaoTiHei, sans-serif;
     // font-family: YouSheBiaoTiHei, sans-serif;
-    font-size: 20px;
+    font-size: calc(20px * var(--kb-scale, 1));
     font-weight: 500;
     font-weight: 500;
     letter-spacing: 0.5px;
     letter-spacing: 0.5px;
     color: #03409b;
     color: #03409b;
@@ -392,9 +482,9 @@
   }
   }
 
 
   :deep(.el-table__body td.el-table__cell) {
   :deep(.el-table__body td.el-table__cell) {
-    padding: 8px 0;
+    padding: calc(8px * var(--kb-scale, 1)) 0;
     // font-family: YouSheBiaoTiHei, sans-serif;
     // font-family: YouSheBiaoTiHei, sans-serif;
-    font-size: 16px;
+    font-size: calc(16px * var(--kb-scale, 1));
     color: #24364f;
     color: #24364f;
     background: rgb(255 255 255 / 16%);
     background: rgb(255 255 255 / 16%);
     border-bottom: 1px solid rgb(31 91 184 / 8%);
     border-bottom: 1px solid rgb(31 91 184 / 8%);
@@ -409,11 +499,11 @@
   }
   }
 
 
   :deep(.el-scrollbar__bar.is-vertical) {
   :deep(.el-scrollbar__bar.is-vertical) {
-    width: 8px;
+    width: calc(8px * var(--kb-scale, 1));
   }
   }
 
 
   :deep(.el-scrollbar__bar.is-horizontal) {
   :deep(.el-scrollbar__bar.is-horizontal) {
-    height: 8px;
+    height: calc(8px * var(--kb-scale, 1));
   }
   }
 
 
   :deep(.el-scrollbar__thumb) {
   :deep(.el-scrollbar__thumb) {
@@ -454,7 +544,7 @@
     rgb(255 255 255 / 0%) 68%,
     rgb(255 255 255 / 0%) 68%,
     rgb(255 255 255 / 0%) 100%
     rgb(255 255 255 / 0%) 100%
   );
   );
-  border-radius: 20px;
+  border-radius: calc(20px * var(--kb-scale, 1));
   content: '';
   content: '';
   opacity: 0;
   opacity: 0;
   transform: translateX(-140%) skewX(-22deg);
   transform: translateX(-140%) skewX(-22deg);
@@ -465,11 +555,11 @@
 
 
 .kb-stage-card::after {
 .kb-stage-card::after {
   position: absolute;
   position: absolute;
-  right: -24px;
-  bottom: -30px;
+  right: calc(-24px * var(--kb-scale, 1));
+  bottom: calc(-30px * var(--kb-scale, 1));
   z-index: 0;
   z-index: 0;
-  width: 120px;
-  height: 120px;
+  width: calc(120px * var(--kb-scale, 1));
+  height: calc(120px * var(--kb-scale, 1));
   pointer-events: none;
   pointer-events: none;
   background: radial-gradient(circle, var(--panel-glow) 0%, rgb(255 255 255 / 0%) 72%);
   background: radial-gradient(circle, var(--panel-glow) 0%, rgb(255 255 255 / 0%) 72%);
   content: '';
   content: '';

+ 41 - 19
src/views/Home/Index.vue

@@ -7,34 +7,27 @@ import hsafe from './kb/hsafe.vue'
 import hdeviceStatus from './kb/hdeviceStatus.vue'
 import hdeviceStatus from './kb/hdeviceStatus.vue'
 import horderTrend from './kb/horderTrend.vue'
 import horderTrend from './kb/horderTrend.vue'
 
 
-const company = ref('首页')
+const company = ref('首页123')
 
 
 const wrapperRef = ref<HTMLDivElement>()
 const wrapperRef = ref<HTMLDivElement>()
 const scale = ref(1)
 const scale = ref(1)
-const supportsZoom = ref(false)
 
 
 let resizeObserver: ResizeObserver | null = null
 let resizeObserver: ResizeObserver | null = null
 let resizeRaf = 0
 let resizeRaf = 0
 
 
+provide('homeKbScale', scale)
+
 const targetWrapperStyle = computed(() => ({
 const targetWrapperStyle = computed(() => ({
   width: `${DESIGN_WIDTH * scale.value}px`,
   width: `${DESIGN_WIDTH * scale.value}px`,
   height: `${DESIGN_HEIGHT * scale.value}px`
   height: `${DESIGN_HEIGHT * scale.value}px`
 }))
 }))
 
 
 const targetAreaStyle = computed(() => {
 const targetAreaStyle = computed(() => {
-  const style = {
-    width: `${DESIGN_WIDTH}px`,
-    height: `${DESIGN_HEIGHT}px`,
-    transformOrigin: '0 0'
-  } as Record<string, string | number>
-
-  if (supportsZoom.value) {
-    style.zoom = scale.value
-  } else {
-    style.transform = `scale(${scale.value})`
+  return {
+    '--kb-scale': scale.value,
+    width: `${DESIGN_WIDTH * scale.value}px`,
+    height: `${DESIGN_HEIGHT * scale.value}px`
   }
   }
-
-  return style
 })
 })
 
 
 function updateScale() {
 function updateScale() {
@@ -48,11 +41,13 @@ function updateScale() {
     if (!clientWidth || !clientHeight) return
     if (!clientWidth || !clientHeight) return
 
 
     scale.value = Math.min(clientWidth / DESIGN_WIDTH, clientHeight / DESIGN_HEIGHT)
     scale.value = Math.min(clientWidth / DESIGN_WIDTH, clientHeight / DESIGN_HEIGHT)
+    nextTick(() => {
+      window.dispatchEvent(new Event('homekb:resize'))
+    })
   })
   })
 }
 }
 
 
 onMounted(() => {
 onMounted(() => {
-  supportsZoom.value = typeof CSS !== 'undefined' && CSS.supports?.('zoom', '1') === true
   nextTick(updateScale)
   nextTick(updateScale)
   resizeObserver = new ResizeObserver(updateScale)
   resizeObserver = new ResizeObserver(updateScale)
   if (wrapperRef.value) {
   if (wrapperRef.value) {
@@ -70,17 +65,17 @@ onUnmounted(() => {
 <template>
 <template>
   <div ref="wrapperRef" class="bg absolute top-0 left-0 size-full z-10">
   <div ref="wrapperRef" class="bg absolute top-0 left-0 size-full z-10">
     <div class="mx-a overflow-hidden" :style="targetWrapperStyle">
     <div class="mx-a overflow-hidden" :style="targetWrapperStyle">
-      <div class="bg" :style="targetAreaStyle">
+      <div class="bg kb-screen" :style="targetAreaStyle">
         <header class="header">{{ company }}</header>
         <header class="header">{{ company }}</header>
-        <div class="mt-3 px-5">
+        <div class="kb-content">
           <hsummary class="kb-stage-card kb-stage-card--1" />
           <hsummary class="kb-stage-card kb-stage-card--1" />
-          <div class="w-full h-96 grid grid-rows-2 grid-cols-3 gap-3 mt-3">
+          <div class="home-top-grid">
             <!-- <hmttr class="kb-stage-card kb-stage-card--2" /> -->
             <!-- <hmttr class="kb-stage-card kb-stage-card--2" /> -->
             <hsafe class="row-span-2 kb-stage-card kb-stage-card--3" />
             <hsafe class="row-span-2 kb-stage-card kb-stage-card--3" />
             <hdeviceType class="row-span-2 kb-stage-card kb-stage-card--4" />
             <hdeviceType class="row-span-2 kb-stage-card kb-stage-card--4" />
             <dayfinish class="row-span-2 kb-stage-card kb-stage-card--5" />
             <dayfinish class="row-span-2 kb-stage-card kb-stage-card--5" />
           </div>
           </div>
-          <div class="w-full h-107 grid grid-cols-2 gap-3 mt-3">
+          <div class="home-bottom-grid">
             <hdeviceStatus class="kb-stage-card kb-stage-card--6" />
             <hdeviceStatus class="kb-stage-card kb-stage-card--6" />
             <horderTrend class="kb-stage-card kb-stage-card--7" />
             <horderTrend class="kb-stage-card kb-stage-card--7" />
           </div>
           </div>
@@ -91,4 +86,31 @@ onUnmounted(() => {
 </template>
 </template>
 <style lang="scss" scoped>
 <style lang="scss" scoped>
 @import url('@/styles/kb.scss');
 @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>
 </style>

+ 5 - 3
src/views/Home/kb/dayfinish.vue

@@ -203,17 +203,19 @@ onMounted(() => {
   initChart()
   initChart()
   loadChart()
   loadChart()
   window.addEventListener('resize', resizeChart)
   window.addEventListener('resize', resizeChart)
+  window.addEventListener('homekb:resize', resizeChart)
 })
 })
 
 
 onUnmounted(() => {
 onUnmounted(() => {
   window.removeEventListener('resize', resizeChart)
   window.removeEventListener('resize', resizeChart)
+  window.removeEventListener('homekb:resize', resizeChart)
   destroyChart()
   destroyChart()
 })
 })
 </script>
 </script>
 
 
 <template>
 <template>
   <div class="panel flex flex-col">
   <div class="panel flex flex-col">
-    <div class="panel-title h-12 flex items-center justify-between">
+    <div class="panel-title panel-title--lg flex items-center justify-between">
       <div class="kb-panel-title-text flex items-center">
       <div class="kb-panel-title-text flex items-center">
         <div class="icon-decorator">
         <div class="icon-decorator">
           <span></span>
           <span></span>
@@ -221,7 +223,7 @@ onUnmounted(() => {
         </div>
         </div>
         日报完成率
         日报完成率
       </div>
       </div>
-      <div class="w-260px! -translate-y-[2px]">
+      <div class="kb-inline-picker kb-inline-picker--260">
         <el-date-picker
         <el-date-picker
           v-model="createTime"
           v-model="createTime"
           value-format="YYYY-MM-DD HH:mm:ss"
           value-format="YYYY-MM-DD HH:mm:ss"
@@ -231,7 +233,7 @@ onUnmounted(() => {
           :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
           :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
           :shortcuts="rangeShortcuts"
           :shortcuts="rangeShortcuts"
           :clearable="false"
           :clearable="false"
-          class="w-260px!"
+          class="kb-inline-picker__input"
           @change="handleDateChange" />
           @change="handleDateChange" />
       </div>
       </div>
     </div>
     </div>

+ 3 - 1
src/views/Home/kb/hdeviceStatus.vue

@@ -108,17 +108,19 @@ onMounted(() => {
   initChart()
   initChart()
   loadChart()
   loadChart()
   window.addEventListener('resize', resizeChart)
   window.addEventListener('resize', resizeChart)
+  window.addEventListener('homekb:resize', resizeChart)
 })
 })
 
 
 onUnmounted(() => {
 onUnmounted(() => {
   window.removeEventListener('resize', resizeChart)
   window.removeEventListener('resize', resizeChart)
+  window.removeEventListener('homekb:resize', resizeChart)
   destroyChart()
   destroyChart()
 })
 })
 </script>
 </script>
 
 
 <template>
 <template>
   <div class="panel flex flex-col">
   <div class="panel flex flex-col">
-    <div class="panel-title h-9">
+    <div class="panel-title">
       <div class="icon-decorator">
       <div class="icon-decorator">
         <span></span>
         <span></span>
         <span></span>
         <span></span>

+ 3 - 1
src/views/Home/kb/hdeviceType.vue

@@ -152,17 +152,19 @@ onMounted(() => {
   initChart()
   initChart()
   loadChart()
   loadChart()
   window.addEventListener('resize', resizeChart)
   window.addEventListener('resize', resizeChart)
+  window.addEventListener('homekb:resize', resizeChart)
 })
 })
 
 
 onUnmounted(() => {
 onUnmounted(() => {
   window.removeEventListener('resize', resizeChart)
   window.removeEventListener('resize', resizeChart)
+  window.removeEventListener('homekb:resize', resizeChart)
   destroyChart()
   destroyChart()
 })
 })
 </script>
 </script>
 
 
 <template>
 <template>
   <div class="panel flex flex-col">
   <div class="panel flex flex-col">
-    <div class="panel-title h-12">
+    <div class="panel-title panel-title--lg">
       <div class="icon-decorator">
       <div class="icon-decorator">
         <span></span>
         <span></span>
         <span></span>
         <span></span>

+ 14 - 13
src/views/Home/kb/hmttr.vue

@@ -31,7 +31,7 @@ onMounted(() => {
 
 
 <template>
 <template>
   <div class="panel flex flex-col">
   <div class="panel flex flex-col">
-    <div class="panel-title h-10">
+    <div class="panel-title panel-title--md">
       <div class="icon-decorator">
       <div class="icon-decorator">
         <span></span>
         <span></span>
         <span></span>
         <span></span>
@@ -78,7 +78,8 @@ onMounted(() => {
 .metric-panel {
 .metric-panel {
   position: relative;
   position: relative;
   display: flex;
   display: flex;
-  padding: 12px 12px 9px;
+  padding: calc(12px * var(--kb-scale, 1)) calc(12px * var(--kb-scale, 1))
+    calc(9px * var(--kb-scale, 1));
   overflow: hidden;
   overflow: hidden;
   flex-direction: column;
   flex-direction: column;
 }
 }
@@ -92,9 +93,9 @@ onMounted(() => {
 }
 }
 
 
 .metric-panel__orbit--outer {
 .metric-panel__orbit--outer {
-  top: 20px;
-  width: 180px;
-  height: 180px;
+  top: calc(20px * var(--kb-scale, 1));
+  width: calc(180px * var(--kb-scale, 1));
+  height: calc(180px * var(--kb-scale, 1));
 }
 }
 
 
 .metric-panel__top,
 .metric-panel__top,
@@ -105,9 +106,9 @@ onMounted(() => {
 
 
 .metric-panel__tag {
 .metric-panel__tag {
   display: inline-flex;
   display: inline-flex;
-  padding: 4px 10px;
+  padding: calc(4px * var(--kb-scale, 1)) calc(10px * var(--kb-scale, 1));
   font-family: YouSheBiaoTiHei, sans-serif;
   font-family: YouSheBiaoTiHei, sans-serif;
-  font-size: 14px;
+  font-size: calc(14px * var(--kb-scale, 1));
   line-height: 1;
   line-height: 1;
   letter-spacing: 1px;
   letter-spacing: 1px;
   color: var(--metric-accent);
   color: var(--metric-accent);
@@ -127,7 +128,7 @@ onMounted(() => {
 }
 }
 
 
 .metric-panel__headline {
 .metric-panel__headline {
-  font-size: 16px;
+  font-size: calc(16px * var(--kb-scale, 1));
   font-weight: 600;
   font-weight: 600;
   letter-spacing: 1px;
   letter-spacing: 1px;
   color: #4f678a;
   color: #4f678a;
@@ -135,14 +136,14 @@ onMounted(() => {
 
 
 .metric-panel__value-row {
 .metric-panel__value-row {
   display: flex;
   display: flex;
-  margin-top: 10px;
+  margin-top: calc(10px * var(--kb-scale, 1));
   align-items: flex-end;
   align-items: flex-end;
   justify-content: center;
   justify-content: center;
 }
 }
 
 
 .metric-panel__value {
 .metric-panel__value {
   font-family: YouSheBiaoTiHei, sans-serif;
   font-family: YouSheBiaoTiHei, sans-serif;
-  font-size: 54px;
+  font-size: calc(54px * var(--kb-scale, 1));
   line-height: 0.92;
   line-height: 0.92;
   letter-spacing: 1px;
   letter-spacing: 1px;
   color: var(--metric-accent);
   color: var(--metric-accent);
@@ -150,10 +151,10 @@ onMounted(() => {
 }
 }
 
 
 .metric-panel__unit {
 .metric-panel__unit {
-  padding-bottom: 7px;
-  margin-left: 4px;
+  padding-bottom: calc(7px * var(--kb-scale, 1));
+  margin-left: calc(4px * var(--kb-scale, 1));
   font-family: YouSheBiaoTiHei, sans-serif;
   font-family: YouSheBiaoTiHei, sans-serif;
-  font-size: 22px;
+  font-size: calc(22px * var(--kb-scale, 1));
   line-height: 1;
   line-height: 1;
   color: #5b789e;
   color: #5b789e;
 }
 }

+ 3 - 1
src/views/Home/kb/horderTrend.vue

@@ -185,17 +185,19 @@ onMounted(() => {
   initChart()
   initChart()
   loadChart()
   loadChart()
   window.addEventListener('resize', resizeChart)
   window.addEventListener('resize', resizeChart)
+  window.addEventListener('homekb:resize', resizeChart)
 })
 })
 
 
 onUnmounted(() => {
 onUnmounted(() => {
   window.removeEventListener('resize', resizeChart)
   window.removeEventListener('resize', resizeChart)
+  window.removeEventListener('homekb:resize', resizeChart)
   destroyChart()
   destroyChart()
 })
 })
 </script>
 </script>
 
 
 <template>
 <template>
   <div class="panel flex flex-col">
   <div class="panel flex flex-col">
-    <div class="panel-title h-9">
+    <div class="panel-title">
       <div class="icon-decorator">
       <div class="icon-decorator">
         <span></span>
         <span></span>
         <span></span>
         <span></span>

+ 15 - 13
src/views/Home/kb/hsafe.vue

@@ -31,7 +31,7 @@ onMounted(() => {
 
 
 <template>
 <template>
   <div class="panel flex flex-col">
   <div class="panel flex flex-col">
-    <div class="panel-title h-12">
+    <div class="panel-title panel-title--lg">
       <div class="icon-decorator">
       <div class="icon-decorator">
         <span></span>
         <span></span>
         <span></span>
         <span></span>
@@ -79,15 +79,17 @@ onMounted(() => {
 .metric-panel {
 .metric-panel {
   position: relative;
   position: relative;
   display: grid;
   display: grid;
-  padding: 16px 14px 20px;
+  padding: calc(16px * var(--kb-scale, 1)) calc(14px * var(--kb-scale, 1))
+    calc(20px * var(--kb-scale, 1));
   overflow: hidden;
   overflow: hidden;
   grid-template-rows: auto minmax(0, 1fr);
   grid-template-rows: auto minmax(0, 1fr);
-  gap: 16px;
+  gap: calc(16px * var(--kb-scale, 1));
 }
 }
 
 
 .metric-panel::before {
 .metric-panel::before {
   position: absolute;
   position: absolute;
-  inset: 54px 18px 16px;
+  inset: calc(54px * var(--kb-scale, 1)) calc(18px * var(--kb-scale, 1))
+    calc(16px * var(--kb-scale, 1));
   pointer-events: none;
   pointer-events: none;
   background: radial-gradient(
   background: radial-gradient(
     circle at center,
     circle at center,
@@ -107,13 +109,13 @@ onMounted(() => {
 }
 }
 
 
 .metric-panel__orbit--outer {
 .metric-panel__orbit--outer {
-  width: 240px;
-  height: 240px;
+  width: calc(240px * var(--kb-scale, 1));
+  height: calc(240px * var(--kb-scale, 1));
 }
 }
 
 
 .metric-panel__orbit--inner {
 .metric-panel__orbit--inner {
-  width: 188px;
-  height: 188px;
+  width: calc(188px * var(--kb-scale, 1));
+  height: calc(188px * var(--kb-scale, 1));
   border-color: rgb(255 255 255 / 42%);
   border-color: rgb(255 255 255 / 42%);
   opacity: 0.55;
   opacity: 0.55;
 }
 }
@@ -134,9 +136,9 @@ onMounted(() => {
 
 
 .metric-panel__tag {
 .metric-panel__tag {
   display: inline-flex;
   display: inline-flex;
-  padding: 5px 12px;
+  padding: calc(5px * var(--kb-scale, 1)) calc(12px * var(--kb-scale, 1));
   font-family: YouSheBiaoTiHei, sans-serif;
   font-family: YouSheBiaoTiHei, sans-serif;
-  font-size: 16px;
+  font-size: calc(16px * var(--kb-scale, 1));
   line-height: 1;
   line-height: 1;
   letter-spacing: 2px;
   letter-spacing: 2px;
   color: var(--metric-accent);
   color: var(--metric-accent);
@@ -156,7 +158,7 @@ onMounted(() => {
 }
 }
 
 
 .metric-panel__headline {
 .metric-panel__headline {
-  font-size: 22px;
+  font-size: calc(22px * var(--kb-scale, 1));
   font-weight: 600;
   font-weight: 600;
   letter-spacing: 2px;
   letter-spacing: 2px;
   color: #4f678a;
   color: #4f678a;
@@ -165,14 +167,14 @@ onMounted(() => {
 
 
 .metric-panel__value-row {
 .metric-panel__value-row {
   display: flex;
   display: flex;
-  margin-top: 18px;
+  margin-top: calc(18px * var(--kb-scale, 1));
   align-items: flex-end;
   align-items: flex-end;
   justify-content: center;
   justify-content: center;
 }
 }
 
 
 .metric-panel__value {
 .metric-panel__value {
   font-family: YouSheBiaoTiHei, sans-serif;
   font-family: YouSheBiaoTiHei, sans-serif;
-  font-size: 90px;
+  font-size: calc(90px * var(--kb-scale, 1));
   line-height: 0.88;
   line-height: 0.88;
   letter-spacing: 2px;
   letter-spacing: 2px;
   color: var(--metric-accent);
   color: var(--metric-accent);

+ 4 - 4
src/views/Home/kb/hsummary.vue

@@ -224,8 +224,8 @@ onMounted(() => {
 </script>
 </script>
 
 
 <template>
 <template>
-  <div class="panel w-full h-28 flex flex-col">
-    <div class="panel-title h-8">
+  <div class="panel summary-panel w-full flex flex-col">
+    <div class="panel-title summary-panel__title">
       <div class="icon-decorator">
       <div class="icon-decorator">
         <span></span>
         <span></span>
         <span></span>
         <span></span>
@@ -233,11 +233,11 @@ onMounted(() => {
       工单情况
       工单情况
     </div>
     </div>
 
 
-    <div class="grid grid-cols-8 gap-2.5 flex-1 px-2.5 py-1.5">
+    <div class="summary-panel__grid grid grid-cols-8 flex-1">
       <article
       <article
         v-for="card in summaryCards"
         v-for="card in summaryCards"
         :key="card.key"
         :key="card.key"
-        class="summary-card relative flex h-full overflow-hidden rounded-md items-center gap-2 p-2"
+        class="summary-card relative flex h-full overflow-hidden rounded-md items-center"
         :style="{
         :style="{
           '--card-accent': card.accent,
           '--card-accent': card.accent,
           '--card-glow': card.glow
           '--card-glow': card.glow

+ 30 - 17
src/views/pms/stat/rhkb.vue

@@ -18,30 +18,23 @@ const company = ref('瑞恒')
 
 
 const wrapperRef = ref<HTMLDivElement>()
 const wrapperRef = ref<HTMLDivElement>()
 const scale = ref(1)
 const scale = ref(1)
-const supportsZoom = ref(false)
 
 
 let resizeObserver: ResizeObserver | null = null
 let resizeObserver: ResizeObserver | null = null
 let resizeRaf = 0
 let resizeRaf = 0
 
 
+provide('rhKbScale', scale)
+
 const targetWrapperStyle = computed(() => ({
 const targetWrapperStyle = computed(() => ({
   width: `${DESIGN_WIDTH * scale.value}px`,
   width: `${DESIGN_WIDTH * scale.value}px`,
   height: `${DESIGN_HEIGHT * scale.value}px`
   height: `${DESIGN_HEIGHT * scale.value}px`
 }))
 }))
 
 
 const targetAreaStyle = computed(() => {
 const targetAreaStyle = computed(() => {
-  const style = {
-    width: `${DESIGN_WIDTH}px`,
-    height: `${DESIGN_HEIGHT}px`,
-    transformOrigin: '0 0'
-  } as Record<string, string | number>
-
-  if (supportsZoom.value) {
-    style.zoom = scale.value
-  } else {
-    style.transform = `scale(${scale.value})`
+  return {
+    '--kb-scale': scale.value,
+    width: `${DESIGN_WIDTH * scale.value}px`,
+    height: `${DESIGN_HEIGHT * scale.value}px`
   }
   }
-
-  return style
 })
 })
 
 
 function updateScale() {
 function updateScale() {
@@ -55,11 +48,13 @@ function updateScale() {
     if (!clientWidth || !clientHeight) return
     if (!clientWidth || !clientHeight) return
 
 
     scale.value = Math.min(clientWidth / DESIGN_WIDTH, clientHeight / DESIGN_HEIGHT)
     scale.value = Math.min(clientWidth / DESIGN_WIDTH, clientHeight / DESIGN_HEIGHT)
+    nextTick(() => {
+      window.dispatchEvent(new Event('rhkb:resize'))
+    })
   })
   })
 }
 }
 
 
 onMounted(() => {
 onMounted(() => {
-  supportsZoom.value = typeof CSS !== 'undefined' && CSS.supports?.('zoom', '1') === true
   nextTick(updateScale)
   nextTick(updateScale)
   resizeObserver = new ResizeObserver(updateScale)
   resizeObserver = new ResizeObserver(updateScale)
   if (wrapperRef.value) {
   if (wrapperRef.value) {
@@ -78,11 +73,11 @@ onUnmounted(() => {
 <template>
 <template>
   <div ref="wrapperRef" class="bg absolute top-0 left-0 size-full z-10">
   <div ref="wrapperRef" class="bg absolute top-0 left-0 size-full z-10">
     <div class="mx-a overflow-hidden" :style="targetWrapperStyle">
     <div class="mx-a overflow-hidden" :style="targetWrapperStyle">
-      <div class="bg" id="rhkb" :style="targetAreaStyle">
+      <div class="bg kb-screen" id="rhkb" :style="targetAreaStyle">
         <header class="header">{{ company }}</header>
         <header class="header">{{ company }}</header>
-        <div class="mt-3 px-5">
+        <div class="kb-content">
           <rhsummary class="kb-stage-card kb-stage-card--1" />
           <rhsummary class="kb-stage-card kb-stage-card--1" />
-          <div class="w-full h-148 grid grid-rows-2 grid-cols-3 gap-3 mt-3">
+          <div class="kb-chart-grid">
             <deviceStatus class="kb-stage-card kb-stage-card--2" />
             <deviceStatus class="kb-stage-card kb-stage-card--2" />
             <deviceType class="kb-stage-card kb-stage-card--3" />
             <deviceType class="kb-stage-card kb-stage-card--3" />
             <operation class="kb-stage-card kb-stage-card--4" />
             <operation class="kb-stage-card kb-stage-card--4" />
@@ -99,4 +94,22 @@ onUnmounted(() => {
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>
 @import url('@/styles/kb.scss');
 @import url('@/styles/kb.scss');
+
+.kb-screen {
+  overflow: hidden;
+}
+
+.kb-content {
+  padding: calc(12px * var(--kb-scale)) calc(20px * var(--kb-scale)) 0;
+}
+
+.kb-chart-grid {
+  display: grid;
+  width: 100%;
+  height: calc(592px * var(--kb-scale));
+  margin-top: calc(12px * var(--kb-scale));
+  gap: calc(12px * var(--kb-scale));
+  grid-template-rows: repeat(2, minmax(0, 1fr));
+  grid-template-columns: repeat(3, minmax(0, 1fr));
+}
 </style>
 </style>

+ 9 - 6
src/views/pms/stat/rhkb/deviceList.vue

@@ -2,6 +2,7 @@
 import { IotStatApi } from '@/api/pms/stat'
 import { IotStatApi } from '@/api/pms/stat'
 import { rangeShortcuts } from '@/utils/formatTime'
 import { rangeShortcuts } from '@/utils/formatTime'
 import dayjs from 'dayjs'
 import dayjs from 'dayjs'
+import type { Ref } from 'vue'
 
 
 interface RhDeviceListRow {
 interface RhDeviceListRow {
   projectDeptId: number
   projectDeptId: number
@@ -34,8 +35,10 @@ const teamDialogVisible = ref(false)
 const teamLoading = ref(false)
 const teamLoading = ref(false)
 const currentProjectDeptName = ref('')
 const currentProjectDeptName = ref('')
 const teamList = ref<RhTeamRateRow[]>([])
 const teamList = ref<RhTeamRateRow[]>([])
+const kbScale = inject<Ref<number>>('rhKbScale', ref(1))
 
 
 const tableData = computed(() => list.value)
 const tableData = computed(() => list.value)
+const tableHeight = computed(() => Math.round(TABLE_HEIGHT * kbScale.value))
 
 
 function formatRate(value?: number | null) {
 function formatRate(value?: number | null) {
   return `${(Number(value ?? 0) * 100).toFixed(2)}%`
   return `${(Number(value ?? 0) * 100).toFixed(2)}%`
@@ -94,8 +97,8 @@ onMounted(() => {
 </script>
 </script>
 
 
 <template>
 <template>
-  <div class="panel w-full h-[280px] flex flex-col mt-3">
-    <div class="panel-title h-9 flex items-center justify-between">
+  <div class="panel device-list-panel w-full flex flex-col">
+    <div class="panel-title device-list-panel__title flex items-center justify-between">
       <div class="kb-panel-title-text flex items-center">
       <div class="kb-panel-title-text flex items-center">
         <div class="icon-decorator">
         <div class="icon-decorator">
           <span></span>
           <span></span>
@@ -103,7 +106,7 @@ onMounted(() => {
         </div>
         </div>
         项目部统计
         项目部统计
       </div>
       </div>
-      <div class="w-260px! -translate-y-[4px]">
+      <div class="device-list-panel__picker">
         <el-date-picker
         <el-date-picker
           v-model="createTime"
           v-model="createTime"
           value-format="YYYY-MM-DD HH:mm:ss"
           value-format="YYYY-MM-DD HH:mm:ss"
@@ -113,15 +116,15 @@ onMounted(() => {
           :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
           :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
           :clearable="false"
           :clearable="false"
           :shortcuts="rangeShortcuts"
           :shortcuts="rangeShortcuts"
-          class="w-260px!"
+          class="device-list-panel__picker-input"
           @change="handleDateChange" />
           @change="handleDateChange" />
       </div>
       </div>
     </div>
     </div>
     <!-- v-loading="loading" -->
     <!-- v-loading="loading" -->
-    <div class="flex-1 min-h-0 px-4 py-2">
+    <div class="device-list-panel__body flex-1 min-h-0">
       <el-table
       <el-table
         :data="tableData"
         :data="tableData"
-        :height="TABLE_HEIGHT"
+        :height="tableHeight"
         class="device-list-table"
         class="device-list-table"
         @row-click="handleRowClick">
         @row-click="handleRowClick">
         <el-table-column prop="projectDeptName" label="项目部" min-width="220" align="center" />
         <el-table-column prop="projectDeptName" label="项目部" min-width="220" align="center" />

+ 3 - 1
src/views/pms/stat/rhkb/deviceStatus.vue

@@ -108,17 +108,19 @@ onMounted(() => {
   initChart()
   initChart()
   loadChart()
   loadChart()
   window.addEventListener('resize', resizeChart)
   window.addEventListener('resize', resizeChart)
+  window.addEventListener('rhkb:resize', resizeChart)
 })
 })
 
 
 onUnmounted(() => {
 onUnmounted(() => {
   window.removeEventListener('resize', resizeChart)
   window.removeEventListener('resize', resizeChart)
+  window.removeEventListener('rhkb:resize', resizeChart)
   destroyChart()
   destroyChart()
 })
 })
 </script>
 </script>
 
 
 <template>
 <template>
   <div class="panel flex flex-col">
   <div class="panel flex flex-col">
-    <div class="panel-title h-9">
+    <div class="panel-title">
       <div class="icon-decorator">
       <div class="icon-decorator">
         <span></span>
         <span></span>
         <span></span>
         <span></span>

+ 3 - 1
src/views/pms/stat/rhkb/deviceType.vue

@@ -151,17 +151,19 @@ onMounted(() => {
   initChart()
   initChart()
   loadChart()
   loadChart()
   window.addEventListener('resize', resizeChart)
   window.addEventListener('resize', resizeChart)
+  window.addEventListener('rhkb:resize', resizeChart)
 })
 })
 
 
 onUnmounted(() => {
 onUnmounted(() => {
   window.removeEventListener('resize', resizeChart)
   window.removeEventListener('resize', resizeChart)
+  window.removeEventListener('rhkb:resize', resizeChart)
   destroyChart()
   destroyChart()
 })
 })
 </script>
 </script>
 
 
 <template>
 <template>
   <div class="panel flex flex-col">
   <div class="panel flex flex-col">
-    <div class="panel-title h-9">
+    <div class="panel-title">
       <div class="icon-decorator">
       <div class="icon-decorator">
         <span></span>
         <span></span>
         <span></span>
         <span></span>

+ 3 - 1
src/views/pms/stat/rhkb/historyGas.vue

@@ -180,17 +180,19 @@ onMounted(() => {
   initChart()
   initChart()
   loadChart()
   loadChart()
   window.addEventListener('resize', resizeChart)
   window.addEventListener('resize', resizeChart)
+  window.addEventListener('rhkb:resize', resizeChart)
 })
 })
 
 
 onUnmounted(() => {
 onUnmounted(() => {
   window.removeEventListener('resize', resizeChart)
   window.removeEventListener('resize', resizeChart)
+  window.removeEventListener('rhkb:resize', resizeChart)
   destroyChart()
   destroyChart()
 })
 })
 </script>
 </script>
 
 
 <template>
 <template>
   <div class="panel flex flex-col">
   <div class="panel flex flex-col">
-    <div class="panel-title h-9">
+    <div class="panel-title">
       <div class="icon-decorator">
       <div class="icon-decorator">
         <span></span>
         <span></span>
         <span></span>
         <span></span>

+ 3 - 1
src/views/pms/stat/rhkb/operation.vue

@@ -167,17 +167,19 @@ onMounted(() => {
   initChart()
   initChart()
   loadChart()
   loadChart()
   window.addEventListener('resize', resizeChart)
   window.addEventListener('resize', resizeChart)
+  window.addEventListener('rhkb:resize', resizeChart)
 })
 })
 
 
 onUnmounted(() => {
 onUnmounted(() => {
   window.removeEventListener('resize', resizeChart)
   window.removeEventListener('resize', resizeChart)
+  window.removeEventListener('rhkb:resize', resizeChart)
   destroyChart()
   destroyChart()
 })
 })
 </script>
 </script>
 
 
 <template>
 <template>
   <div class="panel flex flex-col">
   <div class="panel flex flex-col">
-    <div class="panel-title h-9">
+    <div class="panel-title">
       <div class="icon-decorator">
       <div class="icon-decorator">
         <span></span>
         <span></span>
         <span></span>
         <span></span>

+ 3 - 1
src/views/pms/stat/rhkb/orderTrend.vue

@@ -185,17 +185,19 @@ onMounted(() => {
   initChart()
   initChart()
   loadChart()
   loadChart()
   window.addEventListener('resize', resizeChart)
   window.addEventListener('resize', resizeChart)
+  window.addEventListener('rhkb:resize', resizeChart)
 })
 })
 
 
 onUnmounted(() => {
 onUnmounted(() => {
   window.removeEventListener('resize', resizeChart)
   window.removeEventListener('resize', resizeChart)
+  window.removeEventListener('rhkb:resize', resizeChart)
   destroyChart()
   destroyChart()
 })
 })
 </script>
 </script>
 
 
 <template>
 <template>
   <div class="panel flex flex-col">
   <div class="panel flex flex-col">
-    <div class="panel-title h-9">
+    <div class="panel-title">
       <div class="icon-decorator">
       <div class="icon-decorator">
         <span></span>
         <span></span>
         <span></span>
         <span></span>

+ 4 - 4
src/views/pms/stat/rhkb/rhsummary.vue

@@ -224,8 +224,8 @@ onMounted(() => {
 </script>
 </script>
 
 
 <template>
 <template>
-  <div class="panel w-full h-28 flex flex-col">
-    <div class="panel-title h-8">
+  <div class="panel summary-panel w-full flex flex-col">
+    <div class="panel-title summary-panel__title">
       <div class="icon-decorator">
       <div class="icon-decorator">
         <span></span>
         <span></span>
         <span></span>
         <span></span>
@@ -233,11 +233,11 @@ onMounted(() => {
       工单情况
       工单情况
     </div>
     </div>
 
 
-    <div class="grid grid-cols-8 gap-2.5 flex-1 px-2.5 py-1.5">
+    <div class="summary-panel__grid grid grid-cols-8 flex-1">
       <article
       <article
         v-for="card in summaryCards"
         v-for="card in summaryCards"
         :key="card.key"
         :key="card.key"
-        class="summary-card relative flex h-full overflow-hidden rounded-md items-center gap-2 p-2"
+        class="summary-card relative flex h-full overflow-hidden rounded-md items-center"
         :style="{
         :style="{
           '--card-accent': card.accent,
           '--card-accent': card.accent,
           '--card-glow': card.glow
           '--card-glow': card.glow

+ 3 - 1
src/views/pms/stat/rhkb/todayGas.vue

@@ -191,17 +191,19 @@ onMounted(() => {
   initChart()
   initChart()
   loadChart()
   loadChart()
   window.addEventListener('resize', resizeChart)
   window.addEventListener('resize', resizeChart)
+  window.addEventListener('rhkb:resize', resizeChart)
 })
 })
 
 
 onUnmounted(() => {
 onUnmounted(() => {
   window.removeEventListener('resize', resizeChart)
   window.removeEventListener('resize', resizeChart)
+  window.removeEventListener('rhkb:resize', resizeChart)
   destroyChart()
   destroyChart()
 })
 })
 </script>
 </script>
 
 
 <template>
 <template>
   <div class="panel flex flex-col">
   <div class="panel flex flex-col">
-    <div class="panel-title h-9">
+    <div class="panel-title">
       <div class="icon-decorator">
       <div class="icon-decorator">
         <span></span>
         <span></span>
         <span></span>
         <span></span>

+ 30 - 17
src/views/pms/stat/rykb.vue

@@ -17,30 +17,23 @@ const company = ref('瑞鹰')
 
 
 const wrapperRef = ref<HTMLDivElement>()
 const wrapperRef = ref<HTMLDivElement>()
 const scale = ref(1)
 const scale = ref(1)
-const supportsZoom = ref(false)
 
 
 let resizeObserver: ResizeObserver | null = null
 let resizeObserver: ResizeObserver | null = null
 let resizeRaf = 0
 let resizeRaf = 0
 
 
+provide('ryKbScale', scale)
+
 const targetWrapperStyle = computed(() => ({
 const targetWrapperStyle = computed(() => ({
   width: `${DESIGN_WIDTH * scale.value}px`,
   width: `${DESIGN_WIDTH * scale.value}px`,
   height: `${DESIGN_HEIGHT * scale.value}px`
   height: `${DESIGN_HEIGHT * scale.value}px`
 }))
 }))
 
 
 const targetAreaStyle = computed(() => {
 const targetAreaStyle = computed(() => {
-  const style = {
-    width: `${DESIGN_WIDTH}px`,
-    height: `${DESIGN_HEIGHT}px`,
-    transformOrigin: '0 0'
-  } as Record<string, string | number>
-
-  if (supportsZoom.value) {
-    style.zoom = scale.value
-  } else {
-    style.transform = `scale(${scale.value})`
+  return {
+    '--kb-scale': scale.value,
+    width: `${DESIGN_WIDTH * scale.value}px`,
+    height: `${DESIGN_HEIGHT * scale.value}px`
   }
   }
-
-  return style
 })
 })
 
 
 function updateScale() {
 function updateScale() {
@@ -54,11 +47,13 @@ function updateScale() {
     if (!clientWidth || !clientHeight) return
     if (!clientWidth || !clientHeight) return
 
 
     scale.value = Math.min(clientWidth / DESIGN_WIDTH, clientHeight / DESIGN_HEIGHT)
     scale.value = Math.min(clientWidth / DESIGN_WIDTH, clientHeight / DESIGN_HEIGHT)
+    nextTick(() => {
+      window.dispatchEvent(new Event('rykb:resize'))
+    })
   })
   })
 }
 }
 
 
 onMounted(() => {
 onMounted(() => {
-  supportsZoom.value = typeof CSS !== 'undefined' && CSS.supports?.('zoom', '1') === true
   nextTick(updateScale)
   nextTick(updateScale)
   resizeObserver = new ResizeObserver(updateScale)
   resizeObserver = new ResizeObserver(updateScale)
   if (wrapperRef.value) {
   if (wrapperRef.value) {
@@ -77,11 +72,11 @@ onUnmounted(() => {
 <template>
 <template>
   <div ref="wrapperRef" class="bg absolute top-0 left-0 size-full z-10">
   <div ref="wrapperRef" class="bg absolute top-0 left-0 size-full z-10">
     <div class="mx-a overflow-hidden" :style="targetWrapperStyle">
     <div class="mx-a overflow-hidden" :style="targetWrapperStyle">
-      <div class="bg" :style="targetAreaStyle">
+      <div class="bg kb-screen" :style="targetAreaStyle">
         <header class="header">{{ company }}</header>
         <header class="header">{{ company }}</header>
-        <div class="mt-3 px-5">
+        <div class="kb-content">
           <rysummary class="kb-stage-card kb-stage-card--1" />
           <rysummary class="kb-stage-card kb-stage-card--1" />
-          <div class="w-full h-148 grid grid-rows-2 grid-cols-3 gap-3 mt-3">
+          <div class="kb-chart-grid">
             <rydeviceStatus class="kb-stage-card kb-stage-card--2" />
             <rydeviceStatus class="kb-stage-card kb-stage-card--2" />
             <rydeviceType class="kb-stage-card kb-stage-card--6" />
             <rydeviceType class="kb-stage-card kb-stage-card--6" />
             <rydeviceList class="kb-stage-card kb-stage-card--4 kb-stage-card--list" />
             <rydeviceList class="kb-stage-card kb-stage-card--4 kb-stage-card--list" />
@@ -98,4 +93,22 @@ onUnmounted(() => {
 
 
 <style scoped lang="scss">
 <style scoped lang="scss">
 @import url('@/styles/kb.scss');
 @import url('@/styles/kb.scss');
+
+.kb-screen {
+  overflow: hidden;
+}
+
+.kb-content {
+  padding: calc(12px * var(--kb-scale)) calc(20px * var(--kb-scale)) 0;
+}
+
+.kb-chart-grid {
+  display: grid;
+  width: 100%;
+  height: calc(592px * var(--kb-scale));
+  margin-top: calc(12px * var(--kb-scale));
+  gap: calc(12px * var(--kb-scale));
+  grid-template-rows: repeat(2, minmax(0, 1fr));
+  grid-template-columns: repeat(3, minmax(0, 1fr));
+}
 </style>
 </style>

+ 36 - 9
src/views/pms/stat/rykb/ryProductionBriefs.vue

@@ -1,6 +1,7 @@
 <script lang="ts" setup>
 <script lang="ts" setup>
 import { IotStatApi } from '@/api/pms/stat'
 import { IotStatApi } from '@/api/pms/stat'
 import dayjs from 'dayjs'
 import dayjs from 'dayjs'
+import type { Ref } from 'vue'
 
 
 interface RyProductionBriefRow {
 interface RyProductionBriefRow {
   id: number
   id: number
@@ -33,6 +34,8 @@ const DEFAULT_DATE = dayjs().format('YYYY-MM-DD')
 const selectedDate = ref(DEFAULT_DATE)
 const selectedDate = ref(DEFAULT_DATE)
 const loading = ref(false)
 const loading = ref(false)
 const list = ref<RyProductionBriefRow[]>([])
 const list = ref<RyProductionBriefRow[]>([])
+const kbScale = inject<Ref<number>>('ryKbScale', ref(1))
+const tableHeight = computed(() => Math.round(TABLE_HEIGHT * kbScale.value))
 
 
 const tableData = computed(() => {
 const tableData = computed(() => {
   return [...list.value].sort((a, b) => {
   return [...list.value].sort((a, b) => {
@@ -163,8 +166,8 @@ onMounted(() => {
 </script>
 </script>
 
 
 <template>
 <template>
-  <div class="panel w-full h-[280px] flex flex-col mt-3">
-    <div class="panel-title h-9 flex items-center justify-between">
+  <div class="panel device-list-panel w-full flex flex-col">
+    <div class="panel-title flex items-center justify-between">
       <div class="kb-panel-title-text flex items-center">
       <div class="kb-panel-title-text flex items-center">
         <div class="icon-decorator">
         <div class="icon-decorator">
           <span></span>
           <span></span>
@@ -172,22 +175,22 @@ onMounted(() => {
         </div>
         </div>
         生产简报
         生产简报
       </div>
       </div>
-      <div class="w-120px! -translate-y-[4px]">
+      <div class="production-brief-panel__picker">
         <el-date-picker
         <el-date-picker
           v-model="selectedDate"
           v-model="selectedDate"
           value-format="YYYY-MM-DD"
           value-format="YYYY-MM-DD"
           type="date"
           type="date"
           placeholder="选择日期"
           placeholder="选择日期"
           :clearable="false"
           :clearable="false"
-          class="w-120px!"
+          class="production-brief-panel__picker-input"
           @change="handleDateChange" />
           @change="handleDateChange" />
       </div>
       </div>
     </div>
     </div>
-    <div class="flex-1 min-h-0 px-4 py-2">
+    <div class="device-list-panel__body flex-1 min-h-0">
       <el-table
       <el-table
         v-loading="loading"
         v-loading="loading"
         :data="tableData"
         :data="tableData"
-        :height="TABLE_HEIGHT"
+        :height="tableHeight"
         :span-method="tableSpanMethod"
         :span-method="tableSpanMethod"
         class="device-list-table production-brief-table">
         class="device-list-table production-brief-table">
         <el-table-column prop="projectClassification" label="公司" min-width="72" align="center" />
         <el-table-column prop="projectClassification" label="公司" min-width="72" align="center" />
@@ -241,15 +244,39 @@ onMounted(() => {
 <style lang="scss" scoped>
 <style lang="scss" scoped>
 @import url('@/styles/kb.scss');
 @import url('@/styles/kb.scss');
 
 
+.production-brief-panel__picker {
+  display: flex;
+  width: calc(120px * var(--kb-scale, 1));
+  align-items: center;
+}
+
+.production-brief-panel__picker-input {
+  width: calc(120px * var(--kb-scale, 1)) !important;
+
+  :deep(.el-input__wrapper) {
+    min-height: calc(28px * var(--kb-scale, 1));
+    padding: 0 calc(10px * var(--kb-scale, 1));
+  }
+
+  :deep(.el-input__inner) {
+    font-size: calc(12px * var(--kb-scale, 1));
+  }
+
+  :deep(.el-input__prefix-inner),
+  :deep(.el-input__suffix-inner) {
+    font-size: calc(14px * var(--kb-scale, 1));
+  }
+}
+
 .production-brief-table {
 .production-brief-table {
   :deep(.el-table__header-wrapper th.el-table__cell) {
   :deep(.el-table__header-wrapper th.el-table__cell) {
-    font-size: 16px;
+    font-size: calc(16px * var(--kb-scale, 1));
     line-height: 1.2;
     line-height: 1.2;
   }
   }
 
 
   :deep(.el-table__body td.el-table__cell) {
   :deep(.el-table__body td.el-table__cell) {
-    padding: 7px 0;
-    font-size: 14px;
+    padding: calc(7px * var(--kb-scale, 1)) 0;
+    font-size: calc(14px * var(--kb-scale, 1));
   }
   }
 }
 }
 </style>
 </style>

+ 35 - 7
src/views/pms/stat/rykb/rydeviceList.vue

@@ -2,6 +2,7 @@
 import { IotStatApi } from '@/api/pms/stat'
 import { IotStatApi } from '@/api/pms/stat'
 import { rangeShortcuts } from '@/utils/formatTime'
 import { rangeShortcuts } from '@/utils/formatTime'
 import dayjs from 'dayjs'
 import dayjs from 'dayjs'
+import type { Ref } from 'vue'
 
 
 interface RhDeviceListRow {
 interface RhDeviceListRow {
   projectDeptId: number
   projectDeptId: number
@@ -34,8 +35,10 @@ const teamDialogVisible = ref(false)
 const teamLoading = ref(false)
 const teamLoading = ref(false)
 const currentProjectDeptName = ref('')
 const currentProjectDeptName = ref('')
 const teamList = ref<RhTeamRateRow[]>([])
 const teamList = ref<RhTeamRateRow[]>([])
+const kbScale = inject<Ref<number>>('ryKbScale', ref(1))
 
 
 const tableData = computed(() => list.value)
 const tableData = computed(() => list.value)
+const tableHeight = computed(() => Math.round(TABLE_HEIGHT * kbScale.value))
 
 
 function formatRate(value?: number | null) {
 function formatRate(value?: number | null) {
   return `${(Number(value ?? 0) * 100).toFixed(2)}%`
   return `${(Number(value ?? 0) * 100).toFixed(2)}%`
@@ -95,7 +98,7 @@ onMounted(() => {
 
 
 <template>
 <template>
   <div class="panel w-full h-full flex flex-col">
   <div class="panel w-full h-full flex flex-col">
-    <div class="panel-title h-9 flex items-center justify-between">
+    <div class="panel-title flex items-center justify-between">
       <div class="kb-panel-title-text flex items-center">
       <div class="kb-panel-title-text flex items-center">
         <div class="icon-decorator">
         <div class="icon-decorator">
           <span></span>
           <span></span>
@@ -103,7 +106,7 @@ onMounted(() => {
         </div>
         </div>
         设备利用率
         设备利用率
       </div>
       </div>
-      <div class="w-220px! -translate-y-[4px]">
+      <div class="ry-device-list-panel__picker">
         <el-date-picker
         <el-date-picker
           v-model="createTime"
           v-model="createTime"
           value-format="YYYY-MM-DD HH:mm:ss"
           value-format="YYYY-MM-DD HH:mm:ss"
@@ -112,15 +115,15 @@ onMounted(() => {
           end-placeholder="结束日期"
           end-placeholder="结束日期"
           :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
           :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
           :clearable="false"
           :clearable="false"
-          class="w-220px!"
+          class="ry-device-list-panel__picker-input"
           @change="handleDateChange" />
           @change="handleDateChange" />
       </div>
       </div>
     </div>
     </div>
     <!-- v-loading="loading" -->
     <!-- v-loading="loading" -->
-    <div class="flex-1 min-h-0 px-4 py-2">
+    <div class="device-list-panel__body flex-1 min-h-0">
       <el-table
       <el-table
         :data="tableData"
         :data="tableData"
-        :height="TABLE_HEIGHT"
+        :height="tableHeight"
         class="device-list-table"
         class="device-list-table"
         @row-click="handleRowClick">
         @row-click="handleRowClick">
         <el-table-column prop="projectDeptName" label="项目部" min-width="150" align="center" />
         <el-table-column prop="projectDeptName" label="项目部" min-width="150" align="center" />
@@ -180,14 +183,39 @@ onMounted(() => {
 <style lang="scss" scoped>
 <style lang="scss" scoped>
 @import url('@/styles/kb.scss');
 @import url('@/styles/kb.scss');
 
 
+.ry-device-list-panel__picker {
+  display: flex;
+  width: calc(220px * var(--kb-scale, 1));
+  align-items: center;
+}
+
+.ry-device-list-panel__picker-input {
+  width: calc(220px * var(--kb-scale, 1)) !important;
+
+  :deep(.el-input__wrapper) {
+    min-height: calc(28px * var(--kb-scale, 1));
+    padding: 0 calc(10px * var(--kb-scale, 1));
+  }
+
+  :deep(.el-range-input),
+  :deep(.el-range-separator) {
+    font-size: calc(12px * var(--kb-scale, 1));
+  }
+
+  :deep(.el-range__icon),
+  :deep(.el-range__close-icon) {
+    font-size: calc(14px * var(--kb-scale, 1));
+  }
+}
+
 .device-list-table {
 .device-list-table {
   :deep(.el-table__header-wrapper th.el-table__cell) {
   :deep(.el-table__header-wrapper th.el-table__cell) {
-    font-size: 17px;
+    font-size: calc(17px * var(--kb-scale, 1));
     line-height: 1.25;
     line-height: 1.25;
   }
   }
 
 
   :deep(.el-table__body td.el-table__cell) {
   :deep(.el-table__body td.el-table__cell) {
-    font-size: 15px;
+    font-size: calc(15px * var(--kb-scale, 1));
   }
   }
 }
 }
 </style>
 </style>

+ 3 - 1
src/views/pms/stat/rykb/rydeviceStatus.vue

@@ -108,17 +108,19 @@ onMounted(() => {
   initChart()
   initChart()
   loadChart()
   loadChart()
   window.addEventListener('resize', resizeChart)
   window.addEventListener('resize', resizeChart)
+  window.addEventListener('rykb:resize', resizeChart)
 })
 })
 
 
 onUnmounted(() => {
 onUnmounted(() => {
   window.removeEventListener('resize', resizeChart)
   window.removeEventListener('resize', resizeChart)
+  window.removeEventListener('rykb:resize', resizeChart)
   destroyChart()
   destroyChart()
 })
 })
 </script>
 </script>
 
 
 <template>
 <template>
   <div class="panel flex flex-col">
   <div class="panel flex flex-col">
-    <div class="panel-title h-9">
+    <div class="panel-title">
       <div class="icon-decorator">
       <div class="icon-decorator">
         <span></span>
         <span></span>
         <span></span>
         <span></span>

+ 3 - 1
src/views/pms/stat/rykb/rydeviceType.vue

@@ -152,17 +152,19 @@ onMounted(() => {
   initChart()
   initChart()
   loadChart()
   loadChart()
   window.addEventListener('resize', resizeChart)
   window.addEventListener('resize', resizeChart)
+  window.addEventListener('rykb:resize', resizeChart)
 })
 })
 
 
 onUnmounted(() => {
 onUnmounted(() => {
   window.removeEventListener('resize', resizeChart)
   window.removeEventListener('resize', resizeChart)
+  window.removeEventListener('rykb:resize', resizeChart)
   destroyChart()
   destroyChart()
 })
 })
 </script>
 </script>
 
 
 <template>
 <template>
   <div class="panel flex flex-col">
   <div class="panel flex flex-col">
-    <div class="panel-title h-9">
+    <div class="panel-title">
       <div class="icon-decorator">
       <div class="icon-decorator">
         <span></span>
         <span></span>
         <span></span>
         <span></span>

+ 3 - 1
src/views/pms/stat/rykb/ryorderTrend.vue

@@ -185,17 +185,19 @@ onMounted(() => {
   initChart()
   initChart()
   loadChart()
   loadChart()
   window.addEventListener('resize', resizeChart)
   window.addEventListener('resize', resizeChart)
+  window.addEventListener('rykb:resize', resizeChart)
 })
 })
 
 
 onUnmounted(() => {
 onUnmounted(() => {
   window.removeEventListener('resize', resizeChart)
   window.removeEventListener('resize', resizeChart)
+  window.removeEventListener('rykb:resize', resizeChart)
   destroyChart()
   destroyChart()
 })
 })
 </script>
 </script>
 
 
 <template>
 <template>
   <div class="panel flex flex-col">
   <div class="panel flex flex-col">
-    <div class="panel-title h-9">
+    <div class="panel-title">
       <div class="icon-decorator">
       <div class="icon-decorator">
         <span></span>
         <span></span>
         <span></span>
         <span></span>

+ 4 - 4
src/views/pms/stat/rykb/rysummary.vue

@@ -260,8 +260,8 @@ onMounted(() => {
 </script>
 </script>
 
 
 <template>
 <template>
-  <div class="panel w-full h-28 flex flex-col">
-    <div class="panel-title h-8">
+  <div class="panel summary-panel w-full flex flex-col">
+    <div class="panel-title summary-panel__title">
       <div class="icon-decorator">
       <div class="icon-decorator">
         <span></span>
         <span></span>
         <span></span>
         <span></span>
@@ -269,11 +269,11 @@ onMounted(() => {
       工单情况
       工单情况
     </div>
     </div>
 
 
-    <div class="grid grid-cols-10 gap-2.5 flex-1 px-2.5 py-1.5">
+    <div class="summary-panel__grid grid grid-cols-10 flex-1">
       <article
       <article
         v-for="card in summaryCards"
         v-for="card in summaryCards"
         :key="card.key"
         :key="card.key"
-        class="summary-card relative flex h-full overflow-hidden rounded-md items-center gap-2 p-2"
+        class="summary-card relative flex h-full overflow-hidden rounded-md items-center"
         :style="{
         :style="{
           '--card-accent': card.accent,
           '--card-accent': card.accent,
           '--card-glow': card.glow
           '--card-glow': card.glow

+ 19 - 18
src/views/pms/stat/rykb/safeday.vue

@@ -24,7 +24,7 @@ onMounted(() => {
 
 
 <template>
 <template>
   <div class="panel flex flex-col">
   <div class="panel flex flex-col">
-    <div class="panel-title h-9">
+    <div class="panel-title">
       <div class="icon-decorator">
       <div class="icon-decorator">
         <span></span>
         <span></span>
         <span></span>
         <span></span>
@@ -61,7 +61,8 @@ onMounted(() => {
 .safe-day-panel {
 .safe-day-panel {
   position: relative;
   position: relative;
   display: flex;
   display: flex;
-  padding: 22px 24px 18px;
+  padding: calc(22px * var(--kb-scale, 1)) calc(24px * var(--kb-scale, 1))
+    calc(18px * var(--kb-scale, 1));
   overflow: hidden;
   overflow: hidden;
   flex-direction: column;
   flex-direction: column;
 }
 }
@@ -75,15 +76,15 @@ onMounted(() => {
 }
 }
 
 
 .safe-day-panel__orbit--outer {
 .safe-day-panel__orbit--outer {
-  top: 32px;
-  width: 320px;
-  height: 320px;
+  top: calc(32px * var(--kb-scale, 1));
+  width: calc(320px * var(--kb-scale, 1));
+  height: calc(320px * var(--kb-scale, 1));
 }
 }
 
 
 .safe-day-panel__orbit--inner {
 .safe-day-panel__orbit--inner {
-  top: 62px;
-  width: 240px;
-  height: 240px;
+  top: calc(62px * var(--kb-scale, 1));
+  width: calc(240px * var(--kb-scale, 1));
+  height: calc(240px * var(--kb-scale, 1));
   border-style: dashed;
   border-style: dashed;
 }
 }
 
 
@@ -100,9 +101,9 @@ onMounted(() => {
 }
 }
 
 
 .safe-day-panel__tag {
 .safe-day-panel__tag {
-  padding: 5px 12px;
+  padding: calc(5px * var(--kb-scale, 1)) calc(12px * var(--kb-scale, 1));
   font-family: YouSheBiaoTiHei, sans-serif;
   font-family: YouSheBiaoTiHei, sans-serif;
-  font-size: 16px;
+  font-size: calc(16px * var(--kb-scale, 1));
   line-height: 1;
   line-height: 1;
   letter-spacing: 1px;
   letter-spacing: 1px;
   color: #1f5bb8;
   color: #1f5bb8;
@@ -114,7 +115,7 @@ onMounted(() => {
 
 
 .safe-day-panel__center {
 .safe-day-panel__center {
   display: flex;
   display: flex;
-  padding-top: 14px;
+  padding-top: calc(14px * var(--kb-scale, 1));
   margin-top: auto;
   margin-top: auto;
   margin-bottom: auto;
   margin-bottom: auto;
   flex-direction: column;
   flex-direction: column;
@@ -124,7 +125,7 @@ onMounted(() => {
 }
 }
 
 
 .safe-day-panel__headline {
 .safe-day-panel__headline {
-  font-size: 20px;
+  font-size: calc(20px * var(--kb-scale, 1));
   font-weight: 600;
   font-weight: 600;
   letter-spacing: 1px;
   letter-spacing: 1px;
   color: #24364f;
   color: #24364f;
@@ -132,14 +133,14 @@ onMounted(() => {
 
 
 .safe-day-panel__value-row {
 .safe-day-panel__value-row {
   display: flex;
   display: flex;
-  margin-top: 10px;
+  margin-top: calc(10px * var(--kb-scale, 1));
   align-items: flex-end;
   align-items: flex-end;
   justify-content: center;
   justify-content: center;
 }
 }
 
 
 .safe-day-panel__value {
 .safe-day-panel__value {
   font-family: YouSheBiaoTiHei, sans-serif;
   font-family: YouSheBiaoTiHei, sans-serif;
-  font-size: 82px;
+  font-size: calc(82px * var(--kb-scale, 1));
   line-height: 0.9;
   line-height: 0.9;
   letter-spacing: 2px;
   letter-spacing: 2px;
   color: #1f5bb8;
   color: #1f5bb8;
@@ -147,16 +148,16 @@ onMounted(() => {
 }
 }
 
 
 .safe-day-panel__unit {
 .safe-day-panel__unit {
-  padding-bottom: 10px;
+  padding-bottom: calc(10px * var(--kb-scale, 1));
   font-family: YouSheBiaoTiHei, sans-serif;
   font-family: YouSheBiaoTiHei, sans-serif;
-  font-size: 30px;
+  font-size: calc(30px * var(--kb-scale, 1));
   line-height: 1;
   line-height: 1;
   color: #f08c2e;
   color: #f08c2e;
 }
 }
 
 
 .safe-day-panel__subline {
 .safe-day-panel__subline {
-  margin-top: 10px;
-  font-size: 15px;
+  margin-top: calc(10px * var(--kb-scale, 1));
+  font-size: calc(15px * var(--kb-scale, 1));
   color: #6f85aa;
   color: #6f85aa;
 }
 }
 </style>
 </style>

+ 3 - 1
src/views/pms/stat/rykb/xjwork.vue

@@ -197,17 +197,19 @@ onMounted(() => {
   initChart()
   initChart()
   loadChart()
   loadChart()
   window.addEventListener('resize', resizeChart)
   window.addEventListener('resize', resizeChart)
+  window.addEventListener('rykb:resize', resizeChart)
 })
 })
 
 
 onUnmounted(() => {
 onUnmounted(() => {
   window.removeEventListener('resize', resizeChart)
   window.removeEventListener('resize', resizeChart)
+  window.removeEventListener('rykb:resize', resizeChart)
   destroyChart()
   destroyChart()
 })
 })
 </script>
 </script>
 
 
 <template>
 <template>
   <div class="panel flex flex-col">
   <div class="panel flex flex-col">
-    <div class="panel-title h-9">
+    <div class="panel-title">
       <div class="icon-decorator">
       <div class="icon-decorator">
         <span></span>
         <span></span>
         <span></span>
         <span></span>

+ 7 - 7
src/views/pms/stat/rykb/zjStatsSwitch.vue

@@ -24,7 +24,7 @@ const activeTitle = computed(() =>
 
 
 <template>
 <template>
   <div class="panel flex flex-col">
   <div class="panel flex flex-col">
-    <div class="panel-title h-9 flex items-center justify-between">
+    <div class="panel-title flex items-center justify-between">
       <div class="kb-panel-title-text flex items-center">
       <div class="kb-panel-title-text flex items-center">
         <div class="icon-decorator">
         <div class="icon-decorator">
           <span></span>
           <span></span>
@@ -50,15 +50,15 @@ const activeTitle = computed(() =>
   --el-segmented-bg-color: rgb(31 91 184 / 10%);
   --el-segmented-bg-color: rgb(31 91 184 / 10%);
   --el-segmented-item-hover-bg-color: rgb(255 255 255 / 56%);
   --el-segmented-item-hover-bg-color: rgb(255 255 255 / 56%);
 
 
-  min-height: 26px;
-  padding: 2px;
+  min-height: calc(26px * var(--kb-scale, 1));
+  padding: calc(2px * var(--kb-scale, 1));
   border: 1px solid rgb(31 91 184 / 12%);
   border: 1px solid rgb(31 91 184 / 12%);
-  transform: translateY(-2px);
+  transform: translateY(calc(-2px * var(--kb-scale, 1)));
 
 
   :deep(.el-segmented__item) {
   :deep(.el-segmented__item) {
-    min-height: 22px;
-    padding: 0 8px;
-    font-size: 13px;
+    min-height: calc(22px * var(--kb-scale, 1));
+    padding: 0 calc(8px * var(--kb-scale, 1));
+    font-size: calc(13px * var(--kb-scale, 1));
     font-weight: 600;
     font-weight: 600;
     color: #29527f;
     color: #29527f;
   }
   }

+ 3 - 1
src/views/pms/stat/rykb/zjfinish.vue

@@ -202,17 +202,19 @@ onMounted(() => {
   initChart()
   initChart()
   loadChart()
   loadChart()
   window.addEventListener('resize', resizeChart)
   window.addEventListener('resize', resizeChart)
+  window.addEventListener('rykb:resize', resizeChart)
 })
 })
 
 
 onUnmounted(() => {
 onUnmounted(() => {
   window.removeEventListener('resize', resizeChart)
   window.removeEventListener('resize', resizeChart)
+  window.removeEventListener('rykb:resize', resizeChart)
   destroyChart()
   destroyChart()
 })
 })
 </script>
 </script>
 
 
 <template>
 <template>
   <div :class="embedded ? 'h-full flex flex-col' : 'panel flex flex-col'">
   <div :class="embedded ? 'h-full flex flex-col' : 'panel flex flex-col'">
-    <div v-if="!embedded" class="panel-title h-9">
+    <div v-if="!embedded" class="panel-title">
       <div class="icon-decorator">
       <div class="icon-decorator">
         <span></span>
         <span></span>
         <span></span>
         <span></span>

+ 3 - 1
src/views/pms/stat/rykb/zjwork.vue

@@ -245,17 +245,19 @@ onMounted(() => {
   initChart()
   initChart()
   loadChart()
   loadChart()
   window.addEventListener('resize', resizeChart)
   window.addEventListener('resize', resizeChart)
+  window.addEventListener('rykb:resize', resizeChart)
 })
 })
 
 
 onUnmounted(() => {
 onUnmounted(() => {
   window.removeEventListener('resize', resizeChart)
   window.removeEventListener('resize', resizeChart)
+  window.removeEventListener('rykb:resize', resizeChart)
   destroyChart()
   destroyChart()
 })
 })
 </script>
 </script>
 
 
 <template>
 <template>
   <div :class="embedded ? 'h-full flex flex-col' : 'panel flex flex-col'">
   <div :class="embedded ? 'h-full flex flex-col' : 'panel flex flex-col'">
-    <div v-if="!embedded" class="panel-title h-9">
+    <div v-if="!embedded" class="panel-title">
       <div class="icon-decorator">
       <div class="icon-decorator">
         <span></span>
         <span></span>
         <span></span>
         <span></span>