Browse Source

增加库满度显示

handy 1 month ago
parent
commit
58eb8f724f
1 changed files with 58 additions and 0 deletions
  1. 58 0
      src/App.vue

+ 58 - 0
src/App.vue

@@ -11,6 +11,12 @@
         宝时立库
         <span class="title-meta">· 总库位 {{ locations.length }}</span>
         <span class="title-meta">· 可用库位 {{ availableLocationsCount }}</span>
+        <span class="title-fill-rate">
+          <span class="title-meta">· 总库满度 {{ overallFillRate }}</span>
+          <span class="title-meta title-meta-a">A {{ categoryFillRateMap.A }}</span>
+          <span class="title-meta title-meta-b">B {{ categoryFillRateMap.B }}</span>
+          <span class="title-meta title-meta-c">C {{ categoryFillRateMap.C }}</span>
+        </span>
         <span class="title-legend">
           <button
             type="button"
@@ -406,10 +412,43 @@ const categoryOptions = computed(() => {
   return [...new Set(locations.value.map((loc) => loc.category).filter(Boolean))].sort()
 })
 
+const hasContainer = (containerCode: string | null) => {
+  return Boolean(containerCode && containerCode.trim())
+}
+
+const formatFillRate = (total: number, occupied: number) => {
+  if (total <= 0) {
+    return '0.0%'
+  }
+  return `${((occupied / total) * 100).toFixed(1)}%`
+}
+
 const availableLocationsCount = computed(() => {
   return locations.value.filter((loc) => loc.locationAttribute === 'OK').length
 })
 
+const overallFillRate = computed(() => {
+  const occupiedCount = locations.value.filter((loc) => hasContainer(loc.containerCode)).length
+  return formatFillRate(locations.value.length, occupiedCount)
+})
+
+const categoryFillRateMap = computed<Record<'A' | 'B' | 'C', string>>(() => {
+  const categories: Array<'A' | 'B' | 'C'> = ['A', 'B', 'C']
+  return categories.reduce(
+    (result, category) => {
+      const categoryLocations = locations.value.filter((loc) => loc.category === category)
+      const occupiedCount = categoryLocations.filter((loc) => hasContainer(loc.containerCode)).length
+      result[category] = formatFillRate(categoryLocations.length, occupiedCount)
+      return result
+    },
+    {
+      A: '0.0%',
+      B: '0.0%',
+      C: '0.0%'
+    }
+  )
+})
+
 const locationAttributeOptions = computed<LocationAttributeCode[]>(() => {
   return [
     ...new Set(locations.value.map((loc) => loc.locationAttribute).filter(Boolean))
@@ -692,6 +731,25 @@ onBeforeUnmount(() => {
   margin-left: 2px;
 }
 
+.title-fill-rate {
+  display: inline-flex;
+  align-items: center;
+  gap: 6px;
+  margin-left: 2px;
+}
+
+.title-meta-a {
+  color: rgba(201, 242, 215, 0.78);
+}
+
+.title-meta-b {
+  color: rgba(203, 220, 255, 0.8);
+}
+
+.title-meta-c {
+  color: rgba(240, 220, 156, 0.82);
+}
+
 .legend-chip {
   display: inline-flex;
   align-items: center;