|
|
@@ -42,12 +42,23 @@
|
|
|
</label>
|
|
|
<label class="filter-item filter-input-item">
|
|
|
<span class="selector-label">库位组</span>
|
|
|
- <input
|
|
|
- v-model.trim="locGroupKeyword"
|
|
|
- class="filter-input"
|
|
|
- type="text"
|
|
|
- placeholder="输入库位组"
|
|
|
- />
|
|
|
+ <span class="filter-input-wrap">
|
|
|
+ <input
|
|
|
+ v-model="locGroupKeywordInput"
|
|
|
+ class="filter-input"
|
|
|
+ type="text"
|
|
|
+ placeholder="输入库位组"
|
|
|
+ @keydown.enter="applyLocGroupFilter"
|
|
|
+ />
|
|
|
+ <button class="filter-confirm-btn" type="button" @click="applyLocGroupFilter">
|
|
|
+ <svg viewBox="0 0 16 16" aria-hidden="true" class="filter-confirm-icon">
|
|
|
+ <path
|
|
|
+ d="M6.5 2.5a4 4 0 1 0 2.47 7.15l2.69 2.68 1.06-1.06-2.68-2.69A4 4 0 0 0 6.5 2.5zm0 1.5a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5z"
|
|
|
+ fill="currentColor"
|
|
|
+ />
|
|
|
+ </svg>
|
|
|
+ </button>
|
|
|
+ </span>
|
|
|
</label>
|
|
|
<label class="toggle-item">
|
|
|
<span class="selector-label">库位组边框</span>
|
|
|
@@ -82,8 +93,9 @@
|
|
|
:current-level="currentLevel"
|
|
|
:selected-category="selectedCategory"
|
|
|
:selected-location-attribute="selectedLocationAttribute"
|
|
|
- :loc-group-keyword="locGroupKeyword"
|
|
|
+ :loc-group-keyword="appliedLocGroupKeyword"
|
|
|
:show-group-border="showGroupBorder"
|
|
|
+ @select-loc-group="handleSelectLocGroup"
|
|
|
/>
|
|
|
</div>
|
|
|
</main>
|
|
|
@@ -99,14 +111,25 @@ import LoginModal from './components/LoginModal.vue'
|
|
|
import { config } from './config'
|
|
|
import { isAuthenticated, removeToken } from './utils/auth'
|
|
|
|
|
|
-const currentLevel = ref(1)
|
|
|
+const LEVEL_STORAGE_KEY = 'warehouse-map.current-level'
|
|
|
+const getInitialLevel = () => {
|
|
|
+ const savedLevel = window.localStorage.getItem(LEVEL_STORAGE_KEY)
|
|
|
+ const parsedLevel = savedLevel ? Number(savedLevel) : NaN
|
|
|
+ if (Number.isInteger(parsedLevel) && parsedLevel >= config.minLevel && parsedLevel <= config.maxLevel) {
|
|
|
+ return parsedLevel
|
|
|
+ }
|
|
|
+ return config.minLevel
|
|
|
+}
|
|
|
+
|
|
|
+const currentLevel = ref(getInitialLevel())
|
|
|
const locations = ref<LocationResourceDataVO[]>([])
|
|
|
const loading = ref(false)
|
|
|
const error = ref('')
|
|
|
const showLoginModal = ref(false)
|
|
|
const selectedCategory = ref('')
|
|
|
const selectedLocationAttribute = ref<LocationAttributeCode | ''>('')
|
|
|
-const locGroupKeyword = ref('')
|
|
|
+const locGroupKeywordInput = ref('')
|
|
|
+const appliedLocGroupKeyword = ref('')
|
|
|
const showGroupBorder = ref(true)
|
|
|
const now = ref(Date.now())
|
|
|
const nextRefreshAt = ref(Date.now() + config.refreshInterval)
|
|
|
@@ -140,6 +163,10 @@ const getLocationAttributeLabel = (attribute: LocationAttributeCode) => {
|
|
|
return LOCATION_ATTRIBUTE_LABEL_MAP[attribute] || attribute
|
|
|
}
|
|
|
|
|
|
+const applyLocGroupFilter = () => {
|
|
|
+ appliedLocGroupKeyword.value = locGroupKeywordInput.value.trim()
|
|
|
+}
|
|
|
+
|
|
|
const refreshCountdownText = computed(() => {
|
|
|
const remainMs = Math.max(nextRefreshAt.value - now.value, 0)
|
|
|
const totalSeconds = Math.floor(remainMs / 1000)
|
|
|
@@ -182,6 +209,7 @@ const scheduleNextRefresh = () => {
|
|
|
}
|
|
|
|
|
|
const handleLevelChange = () => {
|
|
|
+ window.localStorage.setItem(LEVEL_STORAGE_KEY, String(currentLevel.value))
|
|
|
loadLocationData()
|
|
|
scheduleNextRefresh()
|
|
|
}
|
|
|
@@ -197,6 +225,11 @@ const handleLoginSuccess = () => {
|
|
|
scheduleNextRefresh()
|
|
|
}
|
|
|
|
|
|
+const handleSelectLocGroup = (locGroup1: string) => {
|
|
|
+ locGroupKeywordInput.value = locGroup1
|
|
|
+ appliedLocGroupKeyword.value = locGroup1
|
|
|
+}
|
|
|
+
|
|
|
const handleLoginCancel = () => {
|
|
|
// 不允许取消登录,必须登录才能使用
|
|
|
}
|
|
|
@@ -373,9 +406,16 @@ onBeforeUnmount(() => {
|
|
|
line-height: 1;
|
|
|
}
|
|
|
|
|
|
+.filter-input-wrap {
|
|
|
+ position: relative;
|
|
|
+ display: inline-flex;
|
|
|
+ width: 110px;
|
|
|
+}
|
|
|
+
|
|
|
.filter-input {
|
|
|
- min-width: 110px;
|
|
|
+ width: 100%;
|
|
|
padding: 6px 8px;
|
|
|
+ padding-right: 28px;
|
|
|
background: rgba(255, 255, 255, 0.04);
|
|
|
border: 1px solid rgba(111, 140, 167, 0.4);
|
|
|
color: #eef4f8;
|
|
|
@@ -395,6 +435,32 @@ onBeforeUnmount(() => {
|
|
|
border-color: #7a96af;
|
|
|
}
|
|
|
|
|
|
+.filter-confirm-btn {
|
|
|
+ position: absolute;
|
|
|
+ top: 1px;
|
|
|
+ right: 1px;
|
|
|
+ width: 24px;
|
|
|
+ height: calc(100% - 2px);
|
|
|
+ display: inline-flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ border: none;
|
|
|
+ border-left: 1px solid rgba(111, 140, 167, 0.3);
|
|
|
+ background: transparent;
|
|
|
+ color: #dce8f3;
|
|
|
+ cursor: pointer;
|
|
|
+ border-radius: 0 3px 3px 0;
|
|
|
+}
|
|
|
+
|
|
|
+.filter-confirm-btn:hover {
|
|
|
+ background: rgba(111, 140, 167, 0.14);
|
|
|
+}
|
|
|
+
|
|
|
+.filter-confirm-icon {
|
|
|
+ width: 12px;
|
|
|
+ height: 12px;
|
|
|
+}
|
|
|
+
|
|
|
.toggle-input {
|
|
|
position: absolute;
|
|
|
opacity: 0;
|