feat(TopBar): add user settings & logout btn and finish logout function
refactor(auth): rename login-token to token for consistency Update all token references from 'login-token' to 'token' across the application. Also enhance TopBar with user menu functionality including logout and settings options. - Standardize token cookie name for better maintainability - Add dropdown menu to TopBar with logout functionality - Implement click-outside behavior for menu - Improve TopBar styling and user interaction
This commit is contained in:
@@ -8,7 +8,7 @@ const api = axios.create({
|
||||
|
||||
api.interceptors.request.use(
|
||||
config => {
|
||||
const token = getCookie('login-token');
|
||||
const token = getCookie('token');
|
||||
if (token) {
|
||||
config.headers['X-Token'] = token;
|
||||
}
|
||||
|
||||
@@ -22,18 +22,31 @@
|
||||
<div class="version-info" v-if="softwareInfo">
|
||||
<span>v{{ softwareInfo.Version }}</span>
|
||||
</div>
|
||||
<div class="user-info">
|
||||
<div class="avatar">{{ username.charAt(0).toUpperCase() }}</div>
|
||||
<span class="username">{{ username }}</span>
|
||||
<div class="user-profile" @click.stop="toggleMenu">
|
||||
<div class="user-info" ref="userInfoRef">
|
||||
<div class="avatar">{{ username.charAt(0).toUpperCase() }}</div>
|
||||
<span class="username">{{ username }}</span>
|
||||
</div>
|
||||
<div class="user-menu" v-show="menuVisible" @click.stop>
|
||||
<button class="menu-item" @click="handleSettings">
|
||||
<i class="fas fa-user-cog"></i>
|
||||
<span>User Settings</span>
|
||||
</button>
|
||||
<button class="menu-item" @click="handleLogout">
|
||||
<i class="fas fa-sign-out-alt"></i>
|
||||
<span>Logout</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { systemApi } from '../api/index.js';
|
||||
import { getCookie } from '../utils/functions.js';
|
||||
import { ref, onMounted, onBeforeUnmount } from 'vue';
|
||||
import { systemApi, authApi } from '../api/index.js';
|
||||
import { getCookie, setCookie, deleteCookie as removeCookie } from '../utils/functions.js';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
export default {
|
||||
name: 'TopBar',
|
||||
@@ -43,6 +56,9 @@ export default {
|
||||
const isOnline = ref(false);
|
||||
const softwareInfo = ref(null);
|
||||
const username = ref(getCookie('username') || 'User');
|
||||
const menuVisible = ref(false);
|
||||
const userInfoRef = ref(null);
|
||||
const router = useRouter();
|
||||
|
||||
const checkStatus = async () => {
|
||||
try {
|
||||
@@ -66,10 +82,44 @@ export default {
|
||||
emit('search', searchQuery.value);
|
||||
};
|
||||
|
||||
const toggleMenu = () => {
|
||||
menuVisible.value = !menuVisible.value;
|
||||
};
|
||||
|
||||
const handleSettings = () => {
|
||||
menuVisible.value = false;
|
||||
alert('User settings feature coming soon!');
|
||||
};
|
||||
|
||||
const handleLogout = async () => {
|
||||
menuVisible.value = false;
|
||||
try {
|
||||
await authApi.logout();
|
||||
} catch (error) {
|
||||
console.error('Logout API error:', error);
|
||||
}
|
||||
removeCookie('token');
|
||||
removeCookie('username');
|
||||
removeCookie('user-type');
|
||||
removeCookie('user-id');
|
||||
router.push('/login');
|
||||
};
|
||||
|
||||
const closeMenu = (event) => {
|
||||
if (userInfoRef.value && !userInfoRef.value.contains(event.target)) {
|
||||
menuVisible.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
checkStatus();
|
||||
getSoftwareInfo();
|
||||
setInterval(checkStatus, 5000);
|
||||
document.addEventListener('click', closeMenu);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
document.removeEventListener('click', closeMenu);
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -77,7 +127,12 @@ export default {
|
||||
isOnline,
|
||||
softwareInfo,
|
||||
username,
|
||||
handleSearch
|
||||
handleSearch,
|
||||
menuVisible,
|
||||
toggleMenu,
|
||||
handleSettings,
|
||||
handleLogout,
|
||||
userInfoRef
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -184,11 +239,26 @@ export default {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.user-profile {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
cursor: pointer;
|
||||
padding: 8px 12px;
|
||||
border-radius: 8px;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.user-info:hover {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.user-profile:hover .user-info {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.avatar {
|
||||
@@ -202,11 +272,51 @@ export default {
|
||||
color: white;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.username {
|
||||
font-size: 14px;
|
||||
color: var(--text-color);
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.user-menu {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
right: 0;
|
||||
margin-top: 8px;
|
||||
min-width: 180px;
|
||||
background: var(--card-bg);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
overflow: hidden;
|
||||
z-index: 101;
|
||||
border: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.user-menu .menu-item {
|
||||
width: 100%;
|
||||
padding: 12px 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
color: var(--text-color);
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.user-menu .menu-item:hover {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.user-menu .menu-item i {
|
||||
font-size: 16px;
|
||||
width: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -65,7 +65,7 @@ const router = createRouter({
|
||||
});
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
const token = getCookie('login-token');
|
||||
const token = getCookie('token');
|
||||
const userType = getCookie('user-type');
|
||||
|
||||
if (to.meta.requiresAuth && !token) {
|
||||
|
||||
@@ -112,7 +112,7 @@ export default {
|
||||
};
|
||||
|
||||
const handleLoginSuccess = (result) => {
|
||||
setCookie('login-token', result.data.token);
|
||||
setCookie('token', result.data.token);
|
||||
setCookie('user-id', result.data.userID);
|
||||
setCookie('username', result.data.username);
|
||||
setCookie('user-type', result.data.type);
|
||||
|
||||
Reference in New Issue
Block a user