|
@@ -7,14 +7,15 @@
|
|
|
@cancel="handleLoginCancel"
|
|
@cancel="handleLoginCancel"
|
|
|
/>
|
|
/>
|
|
|
|
|
|
|
|
- <header
|
|
|
|
|
- v-if="!showLoginModal"
|
|
|
|
|
- class="header"
|
|
|
|
|
- >
|
|
|
|
|
|
|
+ <header v-if="!showLoginModal" class="header">
|
|
|
<h1 class="title">
|
|
<h1 class="title">
|
|
|
{{ systemTitle }}
|
|
{{ systemTitle }}
|
|
|
- <span class="title-meta">库位
|
|
|
|
|
- <span class="title-meta-value">{{ availableLocationsCount }}/{{ locations.length }}</span></span>
|
|
|
|
|
|
|
+ <span class="title-meta"
|
|
|
|
|
+ >库位
|
|
|
|
|
+ <span class="title-meta-value"
|
|
|
|
|
+ >{{ availableLocationsCount }}/{{ locations.length }}</span
|
|
|
|
|
+ ></span
|
|
|
|
|
+ >
|
|
|
<span class="title-fill-rate">
|
|
<span class="title-fill-rate">
|
|
|
<span
|
|
<span
|
|
|
class="title-meta title-fill-rate-item"
|
|
class="title-meta title-fill-rate-item"
|
|
@@ -78,11 +79,7 @@
|
|
|
:class="['level-select', { 'level-select-placeholder': !selectedCategory }]"
|
|
:class="['level-select', { 'level-select-placeholder': !selectedCategory }]"
|
|
|
>
|
|
>
|
|
|
<option value="">库位类型</option>
|
|
<option value="">库位类型</option>
|
|
|
- <option
|
|
|
|
|
- v-for="category in categoryOptions"
|
|
|
|
|
- :key="category"
|
|
|
|
|
- :value="category"
|
|
|
|
|
- >
|
|
|
|
|
|
|
+ <option v-for="category in categoryOptions" :key="category" :value="category">
|
|
|
{{ category }}
|
|
{{ category }}
|
|
|
</option>
|
|
</option>
|
|
|
</select>
|
|
</select>
|
|
@@ -120,34 +117,22 @@
|
|
|
type="text"
|
|
type="text"
|
|
|
placeholder="库位组"
|
|
placeholder="库位组"
|
|
|
@keydown.enter="applyLocGroupFilter"
|
|
@keydown.enter="applyLocGroupFilter"
|
|
|
- >
|
|
|
|
|
|
|
+ />
|
|
|
<button
|
|
<button
|
|
|
v-if="locGroupKeywordInput"
|
|
v-if="locGroupKeywordInput"
|
|
|
class="filter-clear-btn"
|
|
class="filter-clear-btn"
|
|
|
type="button"
|
|
type="button"
|
|
|
@click="clearLocGroupFilter"
|
|
@click="clearLocGroupFilter"
|
|
|
>
|
|
>
|
|
|
- <svg
|
|
|
|
|
- viewBox="0 0 16 16"
|
|
|
|
|
- aria-hidden="true"
|
|
|
|
|
- class="filter-action-icon"
|
|
|
|
|
- >
|
|
|
|
|
|
|
+ <svg viewBox="0 0 16 16" aria-hidden="true" class="filter-action-icon">
|
|
|
<path
|
|
<path
|
|
|
d="M4.22 4.22a.75.75 0 0 1 1.06 0L8 6.94l2.72-2.72a.75.75 0 1 1 1.06 1.06L9.06 8l2.72 2.72a.75.75 0 1 1-1.06 1.06L8 9.06l-2.72 2.72a.75.75 0 1 1-1.06-1.06L6.94 8 4.22 5.28a.75.75 0 0 1 0-1.06z"
|
|
d="M4.22 4.22a.75.75 0 0 1 1.06 0L8 6.94l2.72-2.72a.75.75 0 1 1 1.06 1.06L9.06 8l2.72 2.72a.75.75 0 1 1-1.06 1.06L8 9.06l-2.72 2.72a.75.75 0 1 1-1.06-1.06L6.94 8 4.22 5.28a.75.75 0 0 1 0-1.06z"
|
|
|
fill="currentColor"
|
|
fill="currentColor"
|
|
|
/>
|
|
/>
|
|
|
</svg>
|
|
</svg>
|
|
|
</button>
|
|
</button>
|
|
|
- <button
|
|
|
|
|
- class="filter-confirm-btn"
|
|
|
|
|
- type="button"
|
|
|
|
|
- @click="applyLocGroupFilter"
|
|
|
|
|
- >
|
|
|
|
|
- <svg
|
|
|
|
|
- viewBox="0 0 16 16"
|
|
|
|
|
- aria-hidden="true"
|
|
|
|
|
- class="filter-action-icon"
|
|
|
|
|
- >
|
|
|
|
|
|
|
+ <button class="filter-confirm-btn" type="button" @click="applyLocGroupFilter">
|
|
|
|
|
+ <svg viewBox="0 0 16 16" aria-hidden="true" class="filter-action-icon">
|
|
|
<path
|
|
<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"
|
|
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"
|
|
fill="currentColor"
|
|
@@ -164,34 +149,22 @@
|
|
|
type="text"
|
|
type="text"
|
|
|
placeholder="库位号"
|
|
placeholder="库位号"
|
|
|
@keydown.enter="applyLocationIdFilter"
|
|
@keydown.enter="applyLocationIdFilter"
|
|
|
- >
|
|
|
|
|
|
|
+ />
|
|
|
<button
|
|
<button
|
|
|
v-if="locationIdKeywordInput"
|
|
v-if="locationIdKeywordInput"
|
|
|
class="filter-clear-btn"
|
|
class="filter-clear-btn"
|
|
|
type="button"
|
|
type="button"
|
|
|
@click="clearLocationIdFilter"
|
|
@click="clearLocationIdFilter"
|
|
|
>
|
|
>
|
|
|
- <svg
|
|
|
|
|
- viewBox="0 0 16 16"
|
|
|
|
|
- aria-hidden="true"
|
|
|
|
|
- class="filter-action-icon"
|
|
|
|
|
- >
|
|
|
|
|
|
|
+ <svg viewBox="0 0 16 16" aria-hidden="true" class="filter-action-icon">
|
|
|
<path
|
|
<path
|
|
|
d="M4.22 4.22a.75.75 0 0 1 1.06 0L8 6.94l2.72-2.72a.75.75 0 1 1 1.06 1.06L9.06 8l2.72 2.72a.75.75 0 1 1-1.06 1.06L8 9.06l-2.72 2.72a.75.75 0 1 1-1.06-1.06L6.94 8 4.22 5.28a.75.75 0 0 1 0-1.06z"
|
|
d="M4.22 4.22a.75.75 0 0 1 1.06 0L8 6.94l2.72-2.72a.75.75 0 1 1 1.06 1.06L9.06 8l2.72 2.72a.75.75 0 1 1-1.06 1.06L8 9.06l-2.72 2.72a.75.75 0 1 1-1.06-1.06L6.94 8 4.22 5.28a.75.75 0 0 1 0-1.06z"
|
|
|
fill="currentColor"
|
|
fill="currentColor"
|
|
|
/>
|
|
/>
|
|
|
</svg>
|
|
</svg>
|
|
|
</button>
|
|
</button>
|
|
|
- <button
|
|
|
|
|
- class="filter-confirm-btn"
|
|
|
|
|
- type="button"
|
|
|
|
|
- @click="applyLocationIdFilter"
|
|
|
|
|
- >
|
|
|
|
|
- <svg
|
|
|
|
|
- viewBox="0 0 16 16"
|
|
|
|
|
- aria-hidden="true"
|
|
|
|
|
- class="filter-action-icon"
|
|
|
|
|
- >
|
|
|
|
|
|
|
+ <button class="filter-confirm-btn" type="button" @click="applyLocationIdFilter">
|
|
|
|
|
+ <svg viewBox="0 0 16 16" aria-hidden="true" class="filter-action-icon">
|
|
|
<path
|
|
<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"
|
|
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"
|
|
fill="currentColor"
|
|
@@ -206,11 +179,7 @@
|
|
|
:class="['level-select', { 'level-select-placeholder': !selectedZoneId }]"
|
|
:class="['level-select', { 'level-select-placeholder': !selectedZoneId }]"
|
|
|
>
|
|
>
|
|
|
<option value="">库区</option>
|
|
<option value="">库区</option>
|
|
|
- <option
|
|
|
|
|
- v-for="zoneId in zoneOptions"
|
|
|
|
|
- :key="zoneId"
|
|
|
|
|
- :value="zoneId"
|
|
|
|
|
- >
|
|
|
|
|
|
|
+ <option v-for="zoneId in zoneOptions" :key="zoneId" :value="zoneId">
|
|
|
{{ zoneId }}
|
|
{{ zoneId }}
|
|
|
</option>
|
|
</option>
|
|
|
</select>
|
|
</select>
|
|
@@ -220,18 +189,9 @@
|
|
|
class="level-select level-select-floor"
|
|
class="level-select level-select-floor"
|
|
|
@change="handleLevelChange"
|
|
@change="handleLevelChange"
|
|
|
>
|
|
>
|
|
|
- <option
|
|
|
|
|
- v-for="level in levelRange"
|
|
|
|
|
- :key="level"
|
|
|
|
|
- :value="level"
|
|
|
|
|
- >
|
|
|
|
|
- {{ level }}层
|
|
|
|
|
- </option>
|
|
|
|
|
|
|
+ <option v-for="level in levelRange" :key="level" :value="level">{{ level }}层</option>
|
|
|
</select>
|
|
</select>
|
|
|
- <div
|
|
|
|
|
- ref="refreshControlRef"
|
|
|
|
|
- class="refresh-control"
|
|
|
|
|
- >
|
|
|
|
|
|
|
+ <div ref="refreshControlRef" class="refresh-control">
|
|
|
<button
|
|
<button
|
|
|
class="refresh-btn"
|
|
class="refresh-btn"
|
|
|
:disabled="loading || refreshing"
|
|
:disabled="loading || refreshing"
|
|
@@ -240,11 +200,7 @@
|
|
|
>
|
|
>
|
|
|
{{ refreshCountdownText }}
|
|
{{ refreshCountdownText }}
|
|
|
</button>
|
|
</button>
|
|
|
- <div
|
|
|
|
|
- v-if="showRefreshPopover"
|
|
|
|
|
- class="refresh-popover"
|
|
|
|
|
- @click.stop
|
|
|
|
|
- >
|
|
|
|
|
|
|
+ <div v-if="showRefreshPopover" class="refresh-popover" @click.stop>
|
|
|
<input
|
|
<input
|
|
|
ref="refreshIntervalInputRef"
|
|
ref="refreshIntervalInputRef"
|
|
|
v-model="refreshIntervalInput"
|
|
v-model="refreshIntervalInput"
|
|
@@ -252,17 +208,9 @@
|
|
|
type="text"
|
|
type="text"
|
|
|
inputmode="numeric"
|
|
inputmode="numeric"
|
|
|
@keydown.enter="applyRefreshInterval"
|
|
@keydown.enter="applyRefreshInterval"
|
|
|
- >
|
|
|
|
|
- <button
|
|
|
|
|
- class="refresh-popover-confirm"
|
|
|
|
|
- type="button"
|
|
|
|
|
- @click="applyRefreshInterval"
|
|
|
|
|
- >
|
|
|
|
|
- <svg
|
|
|
|
|
- viewBox="0 0 16 16"
|
|
|
|
|
- aria-hidden="true"
|
|
|
|
|
- class="filter-action-icon"
|
|
|
|
|
- >
|
|
|
|
|
|
|
+ />
|
|
|
|
|
+ <button class="refresh-popover-confirm" type="button" @click="applyRefreshInterval">
|
|
|
|
|
+ <svg viewBox="0 0 16 16" aria-hidden="true" class="filter-action-icon">
|
|
|
<path
|
|
<path
|
|
|
d="M6.46 11.03 3.43 8a.75.75 0 1 1 1.06-1.06l1.97 1.96 5.05-5.04A.75.75 0 0 1 12.57 4.9l-5.58 5.59a.75.75 0 0 1-1.06 0z"
|
|
d="M6.46 11.03 3.43 8a.75.75 0 1 1 1.06-1.06l1.97 1.96 5.05-5.04A.75.75 0 0 1 12.57 4.9l-5.58 5.59a.75.75 0 0 1-1.06 0z"
|
|
|
fill="currentColor"
|
|
fill="currentColor"
|
|
@@ -279,40 +227,27 @@
|
|
|
class="toggle-input"
|
|
class="toggle-input"
|
|
|
type="checkbox"
|
|
type="checkbox"
|
|
|
@change="handleGroupBorderToggle"
|
|
@change="handleGroupBorderToggle"
|
|
|
- >
|
|
|
|
|
|
|
+ />
|
|
|
<span class="toggle-track">
|
|
<span class="toggle-track">
|
|
|
<span class="toggle-thumb" />
|
|
<span class="toggle-thumb" />
|
|
|
</span>
|
|
</span>
|
|
|
</label>
|
|
</label>
|
|
|
<label class="toggle-item">
|
|
<label class="toggle-item">
|
|
|
<span class="toggle-hint">卡片</span>
|
|
<span class="toggle-hint">卡片</span>
|
|
|
- <input
|
|
|
|
|
- v-model="showTooltip"
|
|
|
|
|
- class="toggle-input"
|
|
|
|
|
- type="checkbox"
|
|
|
|
|
- >
|
|
|
|
|
|
|
+ <input v-model="showTooltip" class="toggle-input" type="checkbox" />
|
|
|
<span class="toggle-track">
|
|
<span class="toggle-track">
|
|
|
<span class="toggle-thumb" />
|
|
<span class="toggle-thumb" />
|
|
|
</span>
|
|
</span>
|
|
|
</label>
|
|
</label>
|
|
|
<label class="toggle-item theme-toggle">
|
|
<label class="toggle-item theme-toggle">
|
|
|
<span class="toggle-hint">主题</span>
|
|
<span class="toggle-hint">主题</span>
|
|
|
- <input
|
|
|
|
|
- v-model="isLightTheme"
|
|
|
|
|
- class="toggle-input"
|
|
|
|
|
- type="checkbox"
|
|
|
|
|
- >
|
|
|
|
|
|
|
+ <input v-model="isLightTheme" class="toggle-input" type="checkbox" />
|
|
|
<span class="toggle-track">
|
|
<span class="toggle-track">
|
|
|
<span class="toggle-thumb" />
|
|
<span class="toggle-thumb" />
|
|
|
</span>
|
|
</span>
|
|
|
</label>
|
|
</label>
|
|
|
</div>
|
|
</div>
|
|
|
- <button
|
|
|
|
|
- class="logout-btn"
|
|
|
|
|
- @click="handleLogout"
|
|
|
|
|
- >
|
|
|
|
|
- 退出
|
|
|
|
|
- </button>
|
|
|
|
|
|
|
+ <button class="logout-btn" @click="handleLogout">退出</button>
|
|
|
</div>
|
|
</div>
|
|
|
</header>
|
|
</header>
|
|
|
|
|
|
|
@@ -326,42 +261,30 @@
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
- <main
|
|
|
|
|
- v-if="!showLoginModal"
|
|
|
|
|
- class="main-content"
|
|
|
|
|
- >
|
|
|
|
|
- <div
|
|
|
|
|
- v-if="loading"
|
|
|
|
|
- class="loading"
|
|
|
|
|
- >
|
|
|
|
|
- 加载中...
|
|
|
|
|
- </div>
|
|
|
|
|
- <div
|
|
|
|
|
- v-else-if="error"
|
|
|
|
|
- class="error"
|
|
|
|
|
- >
|
|
|
|
|
|
|
+ <main v-if="!showLoginModal" class="main-content">
|
|
|
|
|
+ <div v-if="loading" class="loading">加载中...</div>
|
|
|
|
|
+ <div v-else-if="error" class="error">
|
|
|
{{ error }}
|
|
{{ error }}
|
|
|
</div>
|
|
</div>
|
|
|
- <div
|
|
|
|
|
- v-else
|
|
|
|
|
- class="map-container"
|
|
|
|
|
- >
|
|
|
|
|
- <WarehouseMap
|
|
|
|
|
- :locations="locations"
|
|
|
|
|
- :current-level="currentLevel"
|
|
|
|
|
- :selected-category="selectedCategory"
|
|
|
|
|
- :selected-location-attribute="selectedLocationAttribute"
|
|
|
|
|
- :selected-has-container="selectedHasContainer"
|
|
|
|
|
- :selected-zone-id="selectedZoneId"
|
|
|
|
|
- :loc-group-keyword="appliedLocGroupKeyword"
|
|
|
|
|
- :location-id-keyword="appliedLocationIdKeyword"
|
|
|
|
|
- :show-group-border="showGroupBorder"
|
|
|
|
|
- :show-tooltip="showTooltip"
|
|
|
|
|
- :category-color-visibility="categoryColorVisibility"
|
|
|
|
|
- :theme-mode="isLightTheme ? 'light' : 'dark'"
|
|
|
|
|
- @select-loc-group="handleSelectLocGroup"
|
|
|
|
|
- @select-location-id="handleSelectLocationId"
|
|
|
|
|
- />
|
|
|
|
|
|
|
+ <div v-else class="map-container">
|
|
|
|
|
+ <WorkingHighlight>
|
|
|
|
|
+ <WarehouseMap
|
|
|
|
|
+ :locations="locations"
|
|
|
|
|
+ :current-level="currentLevel"
|
|
|
|
|
+ :selected-category="selectedCategory"
|
|
|
|
|
+ :selected-location-attribute="selectedLocationAttribute"
|
|
|
|
|
+ :selected-has-container="selectedHasContainer"
|
|
|
|
|
+ :selected-zone-id="selectedZoneId"
|
|
|
|
|
+ :loc-group-keyword="appliedLocGroupKeyword"
|
|
|
|
|
+ :location-id-keyword="appliedLocationIdKeyword"
|
|
|
|
|
+ :show-group-border="showGroupBorder"
|
|
|
|
|
+ :show-tooltip="showTooltip"
|
|
|
|
|
+ :category-color-visibility="categoryColorVisibility"
|
|
|
|
|
+ :theme-mode="isLightTheme ? 'light' : 'dark'"
|
|
|
|
|
+ @select-loc-group="handleSelectLocGroup"
|
|
|
|
|
+ @select-location-id="handleSelectLocationId"
|
|
|
|
|
+ />
|
|
|
|
|
+ </WorkingHighlight>
|
|
|
</div>
|
|
</div>
|
|
|
</main>
|
|
</main>
|
|
|
</div>
|
|
</div>
|
|
@@ -382,6 +305,7 @@ import { fetchLocationData } from './api/location'
|
|
|
import type { LocationAttributeCode, LocationResourceDataVO } from './types'
|
|
import type { LocationAttributeCode, LocationResourceDataVO } from './types'
|
|
|
import WarehouseMap from './components/WarehouseMap.vue'
|
|
import WarehouseMap from './components/WarehouseMap.vue'
|
|
|
import LoginModal from './components/LoginModal.vue'
|
|
import LoginModal from './components/LoginModal.vue'
|
|
|
|
|
+import WorkingHighlight from './components/WorkingHighlight.vue'
|
|
|
import { config } from './config'
|
|
import { config } from './config'
|
|
|
import { AUTH_INVALID_EVENT, getApiEnvironment, isAuthenticated, removeToken } from './utils/auth'
|
|
import { AUTH_INVALID_EVENT, getApiEnvironment, isAuthenticated, removeToken } from './utils/auth'
|
|
|
|
|
|
|
@@ -457,6 +381,7 @@ const fillRateTooltipPosition = ref({
|
|
|
})
|
|
})
|
|
|
let refreshTimer: number | null = null
|
|
let refreshTimer: number | null = null
|
|
|
let countdownTimer: number | null = null
|
|
let countdownTimer: number | null = null
|
|
|
|
|
+const WORKING_HIGHLIGHT_REFRESH_EVENT = 'working-highlight-refresh'
|
|
|
|
|
|
|
|
const LOCATION_ATTRIBUTE_LABEL_MAP: Record<LocationAttributeCode, string> = {
|
|
const LOCATION_ATTRIBUTE_LABEL_MAP: Record<LocationAttributeCode, string> = {
|
|
|
OK: '正常',
|
|
OK: '正常',
|
|
@@ -640,10 +565,12 @@ const copyText = async (text: string) => {
|
|
|
|
|
|
|
|
const applyLocGroupFilter = () => {
|
|
const applyLocGroupFilter = () => {
|
|
|
appliedLocGroupKeyword.value = locGroupKeywordInput.value.trim()
|
|
appliedLocGroupKeyword.value = locGroupKeywordInput.value.trim()
|
|
|
|
|
+ triggerWorkingHighlightRefresh()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const applyLocationIdFilter = () => {
|
|
const applyLocationIdFilter = () => {
|
|
|
appliedLocationIdKeyword.value = locationIdKeywordInput.value.trim()
|
|
appliedLocationIdKeyword.value = locationIdKeywordInput.value.trim()
|
|
|
|
|
+ triggerWorkingHighlightRefresh()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const clearLocGroupFilter = () => {
|
|
const clearLocGroupFilter = () => {
|
|
@@ -683,6 +610,7 @@ const loadLocationData = async (options: { silent?: boolean } = {}) => {
|
|
|
error.value = ''
|
|
error.value = ''
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ let loaded = false
|
|
|
try {
|
|
try {
|
|
|
const data = await fetchLocationData({
|
|
const data = await fetchLocationData({
|
|
|
warehouse: config.warehouse,
|
|
warehouse: config.warehouse,
|
|
@@ -690,6 +618,7 @@ const loadLocationData = async (options: { silent?: boolean } = {}) => {
|
|
|
})
|
|
})
|
|
|
locations.value = data
|
|
locations.value = data
|
|
|
hasLoadedOnce.value = true
|
|
hasLoadedOnce.value = true
|
|
|
|
|
+ loaded = true
|
|
|
} catch (err: unknown) {
|
|
} catch (err: unknown) {
|
|
|
if (!shouldUseSilentRefresh) {
|
|
if (!shouldUseSilentRefresh) {
|
|
|
error.value = err instanceof Error ? err.message : '加载数据失败,请检查接口连接'
|
|
error.value = err instanceof Error ? err.message : '加载数据失败,请检查接口连接'
|
|
@@ -701,9 +630,17 @@ const loadLocationData = async (options: { silent?: boolean } = {}) => {
|
|
|
} else {
|
|
} else {
|
|
|
loading.value = false
|
|
loading.value = false
|
|
|
}
|
|
}
|
|
|
|
|
+ if (loaded) {
|
|
|
|
|
+ await nextTick()
|
|
|
|
|
+ triggerWorkingHighlightRefresh()
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+const triggerWorkingHighlightRefresh = () => {
|
|
|
|
|
+ window.dispatchEvent(new Event(WORKING_HIGHLIGHT_REFRESH_EVENT))
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
const scheduleNextRefresh = () => {
|
|
const scheduleNextRefresh = () => {
|
|
|
if (refreshTimer !== null) {
|
|
if (refreshTimer !== null) {
|
|
|
window.clearTimeout(refreshTimer)
|
|
window.clearTimeout(refreshTimer)
|