|
|
@@ -9,8 +9,7 @@
|
|
|
<header class="header">
|
|
|
<h1 class="title">
|
|
|
{{ systemTitle }}
|
|
|
- <span class="title-meta">· 总库位 <span class="title-meta-value">{{ locations.length }}</span></span>
|
|
|
- <span class="title-meta">· 可用库位 <span class="title-meta-value">{{ availableLocationsCount }}</span></span>
|
|
|
+ <span class="title-meta">库位 <span class="title-meta-value">{{ availableLocationsCount }}/{{ locations.length }}</span></span>
|
|
|
<span class="title-fill-rate">
|
|
|
<span
|
|
|
class="title-meta title-fill-rate-item"
|
|
|
@@ -18,77 +17,62 @@
|
|
|
@mousemove="handleFillRateMouseMove"
|
|
|
@mouseleave="handleFillRateMouseLeave"
|
|
|
>
|
|
|
- · 总库满度 <span class="title-meta-value">{{ overallFillRate }}</span>
|
|
|
+ 库满度 <span class="title-meta-value">{{ overallFillRate }}</span>
|
|
|
</span>
|
|
|
<span
|
|
|
- class="title-meta title-meta-a title-fill-rate-item"
|
|
|
+ :class="[
|
|
|
+ 'title-meta',
|
|
|
+ 'title-meta-a',
|
|
|
+ 'title-fill-rate-item',
|
|
|
+ 'title-fill-rate-toggle',
|
|
|
+ { 'title-meta-inactive': !categoryColorVisibility.A }
|
|
|
+ ]"
|
|
|
@mouseenter="handleFillRateMouseEnter($event, categoryFillRateDetailMap.A)"
|
|
|
@mousemove="handleFillRateMouseMove"
|
|
|
@mouseleave="handleFillRateMouseLeave"
|
|
|
+ @click="toggleCategoryColorVisibility('A')"
|
|
|
>
|
|
|
A <span class="title-meta-value">{{ categoryFillRateMap.A }}</span>
|
|
|
</span>
|
|
|
<span
|
|
|
- class="title-meta title-meta-b title-fill-rate-item"
|
|
|
+ :class="[
|
|
|
+ 'title-meta',
|
|
|
+ 'title-meta-b',
|
|
|
+ 'title-fill-rate-item',
|
|
|
+ 'title-fill-rate-toggle',
|
|
|
+ { 'title-meta-inactive': !categoryColorVisibility.B }
|
|
|
+ ]"
|
|
|
@mouseenter="handleFillRateMouseEnter($event, categoryFillRateDetailMap.B)"
|
|
|
@mousemove="handleFillRateMouseMove"
|
|
|
@mouseleave="handleFillRateMouseLeave"
|
|
|
+ @click="toggleCategoryColorVisibility('B')"
|
|
|
>
|
|
|
B <span class="title-meta-value">{{ categoryFillRateMap.B }}</span>
|
|
|
</span>
|
|
|
<span
|
|
|
- class="title-meta title-meta-c title-fill-rate-item"
|
|
|
+ :class="[
|
|
|
+ 'title-meta',
|
|
|
+ 'title-meta-c',
|
|
|
+ 'title-fill-rate-item',
|
|
|
+ 'title-fill-rate-toggle',
|
|
|
+ { 'title-meta-inactive': !categoryColorVisibility.C }
|
|
|
+ ]"
|
|
|
@mouseenter="handleFillRateMouseEnter($event, categoryFillRateDetailMap.C)"
|
|
|
@mousemove="handleFillRateMouseMove"
|
|
|
@mouseleave="handleFillRateMouseLeave"
|
|
|
+ @click="toggleCategoryColorVisibility('C')"
|
|
|
>
|
|
|
C <span class="title-meta-value">{{ categoryFillRateMap.C }}</span>
|
|
|
</span>
|
|
|
</span>
|
|
|
- <span class="title-legend">
|
|
|
- <button
|
|
|
- type="button"
|
|
|
- :class="[
|
|
|
- 'legend-chip',
|
|
|
- 'legend-chip-a',
|
|
|
- { 'legend-chip-inactive': !categoryColorVisibility.A }
|
|
|
- ]"
|
|
|
- @click="toggleCategoryColorVisibility('A')"
|
|
|
- >
|
|
|
- A
|
|
|
- </button>
|
|
|
- <button
|
|
|
- type="button"
|
|
|
- :class="[
|
|
|
- 'legend-chip',
|
|
|
- 'legend-chip-b',
|
|
|
- { 'legend-chip-inactive': !categoryColorVisibility.B }
|
|
|
- ]"
|
|
|
- @click="toggleCategoryColorVisibility('B')"
|
|
|
- >
|
|
|
- B
|
|
|
- </button>
|
|
|
- <button
|
|
|
- type="button"
|
|
|
- :class="[
|
|
|
- 'legend-chip',
|
|
|
- 'legend-chip-c',
|
|
|
- { 'legend-chip-inactive': !categoryColorVisibility.C }
|
|
|
- ]"
|
|
|
- @click="toggleCategoryColorVisibility('C')"
|
|
|
- >
|
|
|
- C
|
|
|
- </button>
|
|
|
- </span>
|
|
|
</h1>
|
|
|
<div class="controls">
|
|
|
<label class="filter-item">
|
|
|
- <span class="selector-label">库位类型</span>
|
|
|
<select
|
|
|
v-model="selectedCategory"
|
|
|
- class="level-select"
|
|
|
+ :class="['level-select', { 'level-select-placeholder': !selectedCategory }]"
|
|
|
>
|
|
|
- <option value="">全部</option>
|
|
|
+ <option value="">库位类型</option>
|
|
|
<option
|
|
|
v-for="category in categoryOptions"
|
|
|
:key="category"
|
|
|
@@ -99,12 +83,11 @@
|
|
|
</select>
|
|
|
</label>
|
|
|
<label class="filter-item">
|
|
|
- <span class="selector-label">库位属性</span>
|
|
|
<select
|
|
|
v-model="selectedLocationAttribute"
|
|
|
- class="level-select"
|
|
|
+ :class="['level-select', { 'level-select-placeholder': !selectedLocationAttribute }]"
|
|
|
>
|
|
|
- <option value="">全部</option>
|
|
|
+ <option value="">库位属性</option>
|
|
|
<option
|
|
|
v-for="attribute in locationAttributeOptions"
|
|
|
:key="attribute"
|
|
|
@@ -115,24 +98,22 @@
|
|
|
</select>
|
|
|
</label>
|
|
|
<label class="filter-item">
|
|
|
- <span class="selector-label">容器</span>
|
|
|
<select
|
|
|
v-model="selectedHasContainer"
|
|
|
- class="level-select"
|
|
|
+ :class="['level-select', { 'level-select-placeholder': !selectedHasContainer }]"
|
|
|
>
|
|
|
- <option value="">全部</option>
|
|
|
+ <option value="">容器</option>
|
|
|
<option value="Y">有容器</option>
|
|
|
<option value="N">无容器</option>
|
|
|
</select>
|
|
|
</label>
|
|
|
<label class="filter-item filter-input-item">
|
|
|
- <span class="selector-label">库位组</span>
|
|
|
<span class="filter-input-wrap">
|
|
|
<input
|
|
|
v-model="locGroupKeywordInput"
|
|
|
class="filter-input"
|
|
|
type="text"
|
|
|
- placeholder="输入库位组"
|
|
|
+ placeholder="库位组"
|
|
|
@keydown.enter="applyLocGroupFilter"
|
|
|
>
|
|
|
<button
|
|
|
@@ -171,13 +152,12 @@
|
|
|
</span>
|
|
|
</label>
|
|
|
<label class="filter-item filter-input-item">
|
|
|
- <span class="selector-label">库位号</span>
|
|
|
<span class="filter-input-wrap">
|
|
|
<input
|
|
|
v-model="locationIdKeywordInput"
|
|
|
class="filter-input"
|
|
|
type="text"
|
|
|
- placeholder="输入库位号"
|
|
|
+ placeholder="库位号"
|
|
|
@keydown.enter="applyLocationIdFilter"
|
|
|
>
|
|
|
<button
|
|
|
@@ -215,25 +195,12 @@
|
|
|
</button>
|
|
|
</span>
|
|
|
</label>
|
|
|
- <label class="toggle-item">
|
|
|
- <span class="selector-label">库位组边框</span>
|
|
|
- <input
|
|
|
- :checked="showGroupBorder"
|
|
|
- class="toggle-input"
|
|
|
- type="checkbox"
|
|
|
- @change="handleGroupBorderToggle"
|
|
|
- >
|
|
|
- <span class="toggle-track">
|
|
|
- <span class="toggle-thumb" />
|
|
|
- </span>
|
|
|
- </label>
|
|
|
<label class="filter-item">
|
|
|
- <span class="selector-label">库区</span>
|
|
|
<select
|
|
|
v-model="selectedZoneId"
|
|
|
- class="level-select"
|
|
|
+ :class="['level-select', { 'level-select-placeholder': !selectedZoneId }]"
|
|
|
>
|
|
|
- <option value="">全部</option>
|
|
|
+ <option value="">库区</option>
|
|
|
<option
|
|
|
v-for="zoneId in zoneOptions"
|
|
|
:key="zoneId"
|
|
|
@@ -243,17 +210,6 @@
|
|
|
</option>
|
|
|
</select>
|
|
|
</label>
|
|
|
- <label class="toggle-item">
|
|
|
- <span class="selector-label">卡片</span>
|
|
|
- <input
|
|
|
- v-model="showTooltip"
|
|
|
- class="toggle-input"
|
|
|
- type="checkbox"
|
|
|
- >
|
|
|
- <span class="toggle-track">
|
|
|
- <span class="toggle-thumb" />
|
|
|
- </span>
|
|
|
- </label>
|
|
|
<select
|
|
|
v-model.number="currentLevel"
|
|
|
class="level-select level-select-floor"
|
|
|
@@ -310,17 +266,42 @@
|
|
|
</button>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <label class="toggle-item theme-toggle">
|
|
|
- <span class="selector-label">主题</span>
|
|
|
- <input
|
|
|
- v-model="isLightTheme"
|
|
|
- class="toggle-input"
|
|
|
- type="checkbox"
|
|
|
- >
|
|
|
- <span class="toggle-track">
|
|
|
- <span class="toggle-thumb" />
|
|
|
- </span>
|
|
|
- </label>
|
|
|
+ <div class="toggle-group">
|
|
|
+ <label class="toggle-item">
|
|
|
+ <span class="toggle-hint">组框</span>
|
|
|
+ <input
|
|
|
+ :checked="showGroupBorder"
|
|
|
+ class="toggle-input"
|
|
|
+ type="checkbox"
|
|
|
+ @change="handleGroupBorderToggle"
|
|
|
+ >
|
|
|
+ <span class="toggle-track">
|
|
|
+ <span class="toggle-thumb" />
|
|
|
+ </span>
|
|
|
+ </label>
|
|
|
+ <label class="toggle-item">
|
|
|
+ <span class="toggle-hint">卡片</span>
|
|
|
+ <input
|
|
|
+ v-model="showTooltip"
|
|
|
+ class="toggle-input"
|
|
|
+ type="checkbox"
|
|
|
+ >
|
|
|
+ <span class="toggle-track">
|
|
|
+ <span class="toggle-thumb" />
|
|
|
+ </span>
|
|
|
+ </label>
|
|
|
+ <label class="toggle-item theme-toggle">
|
|
|
+ <span class="toggle-hint">主题</span>
|
|
|
+ <input
|
|
|
+ v-model="isLightTheme"
|
|
|
+ class="toggle-input"
|
|
|
+ type="checkbox"
|
|
|
+ >
|
|
|
+ <span class="toggle-track">
|
|
|
+ <span class="toggle-thumb" />
|
|
|
+ </span>
|
|
|
+ </label>
|
|
|
+ </div>
|
|
|
<button
|
|
|
class="logout-btn"
|
|
|
@click="handleLogout"
|
|
|
@@ -863,6 +844,10 @@ onBeforeUnmount(() => {
|
|
|
--text-muted: rgba(255, 255, 255, 0.6);
|
|
|
--text-dim: #d8d8d8;
|
|
|
--label-text: #8e8e8e;
|
|
|
+ --rate-a: rgba(201, 242, 215, 0.88);
|
|
|
+ --rate-b: rgba(203, 220, 255, 0.9);
|
|
|
+ --rate-c: rgba(240, 220, 156, 0.9);
|
|
|
+ --rate-inactive: var(--text-muted);
|
|
|
--panel-bg: rgba(0, 0, 0, 0.96);
|
|
|
--panel-border: #1f1f1f;
|
|
|
--panel-shadow: 0 12px 28px rgba(0, 0, 0, 0.32);
|
|
|
@@ -908,6 +893,10 @@ onBeforeUnmount(() => {
|
|
|
--text-muted: rgba(0, 0, 0, 0.55);
|
|
|
--text-dim: #3f3f3f;
|
|
|
--label-text: #5f6368;
|
|
|
+ --rate-a: #1f7a3f;
|
|
|
+ --rate-b: #2f5fd7;
|
|
|
+ --rate-c: #b8921f;
|
|
|
+ --rate-inactive: var(--label-text);
|
|
|
--panel-bg: rgba(255, 255, 255, 0.96);
|
|
|
--panel-border: #d7dce3;
|
|
|
--panel-shadow: 0 12px 24px rgba(31, 35, 40, 0.12);
|
|
|
@@ -1019,6 +1008,22 @@ onBeforeUnmount(() => {
|
|
|
color: var(--text-muted);
|
|
|
}
|
|
|
|
|
|
+.title-meta-a {
|
|
|
+ color: var(--rate-a);
|
|
|
+}
|
|
|
+
|
|
|
+.title-meta-b {
|
|
|
+ color: var(--rate-b);
|
|
|
+}
|
|
|
+
|
|
|
+.title-meta-c {
|
|
|
+ color: var(--rate-c);
|
|
|
+}
|
|
|
+
|
|
|
+.title-meta-inactive {
|
|
|
+ color: var(--rate-inactive);
|
|
|
+}
|
|
|
+
|
|
|
.legend-chip {
|
|
|
display: inline-flex;
|
|
|
align-items: center;
|
|
|
@@ -1068,6 +1073,8 @@ onBeforeUnmount(() => {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
gap: 6px;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ row-gap: 6px;
|
|
|
}
|
|
|
|
|
|
.level-selector {
|
|
|
@@ -1095,11 +1102,24 @@ onBeforeUnmount(() => {
|
|
|
color: var(--text-dim);
|
|
|
}
|
|
|
|
|
|
+.toggle-group {
|
|
|
+ display: inline-flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+ flex-wrap: nowrap;
|
|
|
+}
|
|
|
+
|
|
|
.selector-label {
|
|
|
font-size: 11px;
|
|
|
color: var(--label-text);
|
|
|
}
|
|
|
|
|
|
+.toggle-hint {
|
|
|
+ font-size: 11px;
|
|
|
+ color: var(--label-text);
|
|
|
+ white-space: nowrap;
|
|
|
+}
|
|
|
+
|
|
|
.level-select {
|
|
|
min-width: 76px;
|
|
|
padding: 6px 24px 6px 8px;
|
|
|
@@ -1125,6 +1145,10 @@ onBeforeUnmount(() => {
|
|
|
line-height: 1;
|
|
|
}
|
|
|
|
|
|
+.level-select-placeholder {
|
|
|
+ color: var(--label-text);
|
|
|
+}
|
|
|
+
|
|
|
.level-select-floor {
|
|
|
min-width: 64px;
|
|
|
}
|
|
|
@@ -1238,6 +1262,7 @@ onBeforeUnmount(() => {
|
|
|
transform: translateX(16px);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
.level-select:hover,
|
|
|
.level-select:focus {
|
|
|
background: var(--input-hover-bg);
|