refactor(components): move status indicator from topbar to sidebar

Relocate the online status indicator component from the top navigation bar to the sidebar for better layout organization. Remove unused code and update styling to match sidebar theme.
This commit is contained in:
2026-04-05 21:31:44 +08:00
parent c53854722d
commit 928998f255
2 changed files with 60 additions and 39 deletions

View File

@@ -12,6 +12,12 @@
<span class="menu-text">{{ item.title }}</span>
</router-link>
</div>
<div class="status-info">
<div class="status-item">
<span :class="['status-dot', { online: isOnline }]"></span>
<span class="status-text">{{ isOnline ? 'Online' : 'Offline' }}</span>
</div>
</div>
<div class="theme-toggle">
<button @click="toggleTheme" class="theme-button">
<span class="theme-icon"><i :class="isDarkMode ? 'fas fa-sun' : 'fas fa-moon'" aria-hidden="true"></i></span>
@@ -22,8 +28,9 @@
</template>
<script>
import { computed, inject } from 'vue';
import { ref, computed, inject, onMounted, onBeforeUnmount } from 'vue';
import { getCookie } from '../utils/functions.js';
import { systemApi } from '../api/index.js';
export default {
name: 'SideBar',
@@ -31,6 +38,8 @@ export default {
const userType = getCookie('user-type') || 'visitor';
const isDarkMode = inject('isDarkMode');
const toggleTheme = inject('toggleTheme');
const isOnline = ref(false);
let statusInterval;
const allMenuItems = [
{ path: '/instances', title: 'Instance Management', icon: 'fas fa-box', permission: ['superuser', 'admin', 'visitor'] },
@@ -45,10 +54,31 @@ export default {
return allMenuItems.filter(item => item.permission.includes(userType));
});
const checkStatus = async () => {
try {
const result = await systemApi.getStatus();
isOnline.value = result.data.Status === 'Online';
} catch (error) {
isOnline.value = false;
}
};
onMounted(() => {
checkStatus();
statusInterval = setInterval(checkStatus, 60000);
});
onBeforeUnmount(() => {
if (statusInterval) {
clearInterval(statusInterval);
}
});
return {
menuItems,
isDarkMode,
toggleTheme
toggleTheme,
isOnline
};
}
};
@@ -156,4 +186,32 @@ export default {
.theme-text {
font-weight: 500;
}
.status-info {
padding: 16px;
border-top: 1px solid rgba(255, 255, 255, 0.1);
}
.status-item {
display: flex;
align-items: center;
gap: 8px;
}
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #ff4d4f;
}
.status-dot.online {
background: #52c41a;
}
.status-text {
font-size: 14px;
color: var(--sidebar-text);
font-weight: 500;
}
</style>

View File

@@ -15,10 +15,6 @@
</div>
</div>
<div class="topbar-right">
<div class="status-info">
<span :class="['status-dot', { online: isOnline }]"></span>
<span class="status-text">{{ isOnline ? 'Online' : 'Offline' }}</span>
</div>
<div class="version-info" v-if="softwareInfo">
<span>v{{ softwareInfo.Version }}</span>
</div>
@@ -88,7 +84,6 @@ export default {
emits: ['search'],
setup(props, { emit }) {
const searchQuery = ref('');
const isOnline = ref(false);
const softwareInfo = ref(null);
const username = ref(getCookie('username') || 'User');
const menuVisible = ref(false);
@@ -103,15 +98,6 @@ export default {
});
const router = useRouter();
const checkStatus = async () => {
try {
const result = await systemApi.getStatus();
isOnline.value = result.data.Status === 'Online';
} catch (error) {
isOnline.value = false;
}
};
const getSoftwareInfo = async () => {
try {
const result = await systemApi.getSoftwareInfo();
@@ -207,9 +193,7 @@ export default {
};
onMounted(() => {
checkStatus();
getSoftwareInfo();
setInterval(checkStatus, 60000);
document.addEventListener('click', closeMenu);
});
@@ -219,7 +203,6 @@ export default {
return {
searchQuery,
isOnline,
softwareInfo,
username,
handleSearch,
@@ -312,27 +295,7 @@ export default {
gap: 24px;
}
.status-info {
display: flex;
align-items: center;
gap: 8px;
}
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #ff4d4f;
}
.status-dot.online {
background: #52c41a;
}
.status-text {
font-size: 14px;
color: var(--text-color);
}
.version-info {
font-size: 14px;