Files
frontend/src/views/Sessions.vue
NanamiAdmin a93cfaa45f fix(Sessions): correct session property names and adjust styling
Update session property names to match backend API (Username, UserID, CreateAt, ExpireAt).
Add left margin to session info and update font family for session ID.
2026-03-10 19:09:44 +08:00

144 lines
3.9 KiB
Vue

<template>
<div class="sessions-page">
<div class="page-header">
<h2>Session Management</h2>
</div>
<div class="sessions-grid">
<div v-for="session in sessions" :key="session.ID" class="session-card">
<div class="card-header">
<div class="session-icon"><i class="fas fa-key" aria-hidden="true"></i></div>
<div class="session-info">
<div class="session-user">{{ session.Username }}</div>
<div class="session-id">{{ session.ID }}</div>
</div>
</div>
<div class="card-body">
<div class="info-row">
<span class="label">User ID:</span>
<span class="value">{{ session.UserID }}</span>
</div>
<div class="info-row">
<span class="label">Create Time:</span>
<span class="value">{{ formatDate(session.CreateAt) }}</span>
</div>
<div class="info-row">
<span class="label">Expire Time:</span>
<span class="value">{{ formatDate(session.ExpireAt) }}</span>
</div>
</div>
<div class="card-footer">
<button class="action-btn delete-btn" @click="deleteSession(session.ID)">
Delete Session
</button>
</div>
</div>
</div>
<div v-if="sessions.length === 0" class="empty-state">
<p>No active sessions</p>
</div>
</div>
</template>
<script>
import { ref, onMounted } from 'vue';
import { sessionApi } from '../api/index.js';
import { showNotification, formatDate } from '../utils/functions.js';
export default {
name: 'Sessions',
setup() {
const sessions = ref([]);
const loadSessions = async () => {
try {
const result = await sessionApi.listSessions();
sessions.value = result.data;
} catch (error) {
showNotification('Load session list failed', 'error');
}
};
const deleteSession = async (sessionId) => {
if (!confirm('Are you sure you want to delete this session? This will force the user to re-login.')) return;
try {
await sessionApi.removeSession(sessionId);
showNotification('Session deleted successfully', 'success');
await loadSessions();
} catch (error) {
showNotification(error.message || 'Delete session failed', 'error');
}
};
onMounted(() => {
loadSessions();
});
return {
sessions,
deleteSession,
formatDate
};
}
};
</script>
<style scoped>
@import '../styles/common.css';
.sessions-page {
padding: 24px;
}
.sessions-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: 20px;
}
.session-card {
transition: background-color 0.3s;
background-color: var(--card-bg);
padding: 16px;
border-radius: 8px;
}
.session-icon {
width: 48px;
height: 48px;
border-radius: 50%;
background: linear-gradient(135deg, var(--primary-color) 0%, #764ba2 100%);
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
}
.session-info {
flex: 1;
}
.session-user {
margin-left: 8px;
font-size: 16px;
font-weight: 600;
color: var(--text-color);
margin-bottom: 4px;
transition: color 0.3s;
}
.session-id {
margin-left: 8px;
font-size: 12px;
color: #999;
font-family: 'Consolas', Courier, monospace;
}
.card-body {
margin-bottom: 16px;
}
.action-btn {
flex: 1;
}
</style>