Files
frontend/src/views/InstanceDetail.vue
NanamiAdmin 8380720d5e refactor(styles): move common styles to shared CSS file
Extract duplicated styles across multiple components into a common CSS file and import it where needed. This improves maintainability by reducing code duplication and centralizing style definitions.
2026-03-09 22:25:58 +08:00

208 lines
6.0 KiB
Vue

<template>
<div class="instance-detail-page">
<div class="page-header">
<button class="back-btn" @click="goBack">
Back
</button>
<h2>{{ instanceName }} - Details</h2>
</div>
<div class="detail-content">
<div class="section">
<h3>Configuration</h3>
<div class="config-list">
<div class="config-item" v-for="(value, key) in instanceConfig" :key="key">
<span class="config-key">{{ key }}:</span>
<span class="config-value">{{ value }}</span>
</div>
</div>
</div>
<div class="section">
<h3>Proxy List</h3>
<div v-if="proxies.length > 0" class="proxy-list">
<div v-for="proxy in proxies" :key="proxy.name" class="proxy-item">
<div class="proxy-header">
<span class="proxy-name">{{ proxy.name }}</span>
<span :class="['proxy-status', proxy.status]">
{{ proxy.status }}
</span>
</div>
<div class="proxy-details">
<div class="proxy-detail" v-for="(value, key) in proxy.details" :key="key">
<span class="detail-key">{{ key }}:</span>
<span class="detail-value">{{ value }}</span>
</div>
</div>
</div>
</div>
<div v-else class="empty-state">
<p>No proxies available</p>
</div>
</div>
<div class="section">
<h3>Logs</h3>
<div class="logs-container">
<div v-if="logs.length > 0" class="log-list">
<div v-for="(log, index) in logs" :key="index" class="log-item">
<span class="log-time">{{ log.time }}</span>
<span :class="['log-level', log.level]">{{ log.level }}</span>
<span class="log-message">{{ log.message }}</span>
</div>
</div>
<div v-else class="empty-state">
<p>No logs available</p>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { ref, onMounted } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { instanceApi } from '../api/index.js';
import { showNotification, formatDate } from '../utils/functions.js';
export default {
name: 'InstanceDetail',
setup() {
const route = useRoute();
const router = useRouter();
const instanceName = ref(route.params.name);
const instanceConfig = ref({});
const proxies = ref([]);
const logs = ref([]);
const loadInstanceConfig = async () => {
try {
const result = await instanceApi.listInstances();
const instance = result.data.find(i => i.name === instanceName.value);
if (instance) {
instanceConfig.value = {
'Server Address': instance.serverAddr,
'Server Port': instance.serverPort,
'Auth Method': instance.auth_method,
'Boot At Start': instance.bootAtStart ? 'Yes' : 'No',
'Run User': instance.runUser,
'Config Path': instance.configPath,
'Created At': formatDate(instance.createdAt)
};
}
} catch (error) {
showNotification('Load instance configuration failed', 'error');
}
};
const loadProxies = async () => {
try {
const result = await instanceApi.getInstanceProxies(instanceName.value);
proxies.value = result.data.map(proxy => ({
name: proxy.name,
status: proxy.status || 'unknown',
details: proxy
}));
} catch (error) {
showNotification('Load proxy list failed', 'error');
}
};
const loadLogs = async () => {
try {
const result = await instanceApi.getInstanceLogs(instanceName.value);
logs.value = result.data.map(log => ({
time: formatDate(log.timestamp),
level: log.level,
message: log.message
}));
} catch (error) {
showNotification('Load logs failed', 'error');
}
};
const goBack = () => {
router.push('/instances');
};
onMounted(() => {
loadInstanceConfig();
loadProxies();
loadLogs();
});
return {
instanceName,
instanceConfig,
proxies,
logs,
goBack
};
}
};
</script>
<style scoped>
@import '../styles/common.css';
.instance-detail-page {
padding: 24px;
}
.page-header {
display: flex;
align-items: center;
gap: 16px;
}
.detail-content {
display: flex;
flex-direction: column;
gap: 24px;
}
.config-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.proxy-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.log-item {
padding: 8px;
border-radius: 4px;
}
.log-time {
min-width: 140px;
}
.log-level {
min-width: 60px;
font-weight: 500;
}
.log-level.INFO {
color: #1890ff;
}
.log-level.WARN {
color: #faad14;
}
.log-level.ERROR {
color: #ff4d4f;
}
.empty-state {
padding: 40px 20px;
font-size: 14px;
}
</style>