first commit

This commit is contained in:
2026-06-03 10:09:03 +08:00
commit 81f5039458
6266 changed files with 188236 additions and 0 deletions
+11
View File
@@ -0,0 +1,11 @@
<script setup>
// Settings 父路由组件,用于显示子路由
</script>
<template>
<router-view />
</template>
<style scoped>
/* Settings 父路由容器 */
</style>
@@ -0,0 +1,420 @@
<template>
<div class="system-info-container">
<el-card class="info-card">
<template #header>
<div class="card-header">
<el-icon class="header-icon"><InfoFilled /></el-icon>
<span class="header-title">系统信息</span>
</div>
</template>
<div v-loading="loading" class="info-content">
<!-- 系统基本信息 -->
<el-descriptions title="系统基本信息" :column="2" border class="info-section">
<el-descriptions-item label="系统名称">
<el-tag type="primary">{{ systemInfo.name || '云泽管理系统' }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="系统版本">
<el-tag>{{ systemInfo.version || '1.0.0' }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="运行环境">
<el-tag type="success">{{ systemInfo.environment || 'Production' }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="系统时间">
{{ currentTime }}
</el-descriptions-item>
<el-descriptions-item label="运行时间">
{{ systemInfo.uptime || '-' }}
</el-descriptions-item>
<el-descriptions-item label="时区">
{{ systemInfo.timezone || Intl.DateTimeFormat().resolvedOptions().timeZone }}
</el-descriptions-item>
</el-descriptions>
<!-- 服务器信息 -->
<el-descriptions title="服务器信息" :column="2" border class="info-section">
<el-descriptions-item label="服务器地址">
{{ systemInfo.serverHost || '-' }}
</el-descriptions-item>
<el-descriptions-item label="API地址">
{{ apiBaseUrl }}
</el-descriptions-item>
<el-descriptions-item label="操作系统">
{{ systemInfo.os || clientInfo.os }}
</el-descriptions-item>
<el-descriptions-item label="CPU核心数">
{{ systemInfo.cpuCores || clientInfo.cpuCores }}
</el-descriptions-item>
<el-descriptions-item label="内存使用">
<el-progress
:percentage="systemInfo.memoryUsage || 0"
:color="getMemoryColor(systemInfo.memoryUsage)"
:format="(percentage) => `${percentage}%`"
/>
</el-descriptions-item>
<el-descriptions-item label="磁盘使用">
<el-progress
:percentage="systemInfo.diskUsage || 0"
:color="getDiskColor(systemInfo.diskUsage)"
:format="(percentage) => `${percentage}%`"
/>
</el-descriptions-item>
</el-descriptions>
<!-- 数据库信息 -->
<el-descriptions title="数据库信息" :column="2" border class="info-section">
<el-descriptions-item label="数据库类型">
<el-tag type="info">{{ systemInfo.dbType || 'MySQL' }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="数据库版本">
{{ systemInfo.dbVersion || '-' }}
</el-descriptions-item>
<el-descriptions-item label="数据库状态">
<el-tag :type="systemInfo.dbStatus === 'connected' ? 'success' : 'danger'">
{{ systemInfo.dbStatus === 'connected' ? '已连接' : '未连接' }}
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="连接数">
{{ systemInfo.dbConnections || '-' }}
</el-descriptions-item>
</el-descriptions>
<!-- 客户端信息 -->
<el-descriptions title="客户端信息" :column="2" border class="info-section">
<el-descriptions-item label="浏览器">
{{ clientInfo.browser }}
</el-descriptions-item>
<el-descriptions-item label="浏览器版本">
{{ clientInfo.browserVersion }}
</el-descriptions-item>
<el-descriptions-item label="操作系统">
{{ clientInfo.os }}
</el-descriptions-item>
<el-descriptions-item label="屏幕分辨率">
{{ clientInfo.screenResolution }}
</el-descriptions-item>
<el-descriptions-item label="设备类型">
<el-tag :type="clientInfo.isMobile ? 'warning' : 'success'">
{{ clientInfo.isMobile ? '移动设备' : '桌面设备' }}
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="用户代理">
<span class="user-agent">{{ clientInfo.userAgent }}</span>
</el-descriptions-item>
</el-descriptions>
<!-- 应用信息 -->
<el-descriptions title="应用信息" :column="2" border class="info-section">
<el-descriptions-item label="前端框架">
<el-tag type="success">Vue 3</el-tag>
</el-descriptions-item>
<el-descriptions-item label="UI框架">
<el-tag type="primary">Element Plus</el-tag>
</el-descriptions-item>
<el-descriptions-item label="构建工具">
<el-tag type="info">Vite</el-tag>
</el-descriptions-item>
<el-descriptions-item label="Node版本">
{{ clientInfo.nodeVersion || '-' }}
</el-descriptions-item>
</el-descriptions>
<!-- 操作按钮 -->
<div class="action-buttons">
<el-button type="primary" @click="refreshInfo" :loading="loading">
<el-icon><Refresh /></el-icon>
刷新信息
</el-button>
<el-button @click="copySystemInfo">
<el-icon><DocumentCopy /></el-icon>
复制信息
</el-button>
</div>
</div>
</el-card>
</div>
</template>
<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted } from 'vue';
import { ElMessage } from 'element-plus';
import { InfoFilled, Refresh, DocumentCopy } from '@element-plus/icons-vue';
// 系统信息数据
const loading = ref(false);
const systemInfo = ref<any>({});
const currentTime = ref(new Date().toLocaleString('zh-CN'));
// API基础地址
const apiBaseUrl = computed(() => {
return import.meta.env.VITE_API_BASE_URL || window.location.origin;
});
// 客户端信息
const clientInfo = computed(() => {
const ua = navigator.userAgent;
// 检测浏览器
let browser = 'Unknown';
let browserVersion = '';
if (ua.includes('Chrome') && !ua.includes('Edg')) {
browser = 'Chrome';
const match = ua.match(/Chrome\/([\d.]+)/);
browserVersion = match ? match[1] : '';
} else if (ua.includes('Firefox')) {
browser = 'Firefox';
const match = ua.match(/Firefox\/([\d.]+)/);
browserVersion = match ? match[1] : '';
} else if (ua.includes('Safari') && !ua.includes('Chrome')) {
browser = 'Safari';
const match = ua.match(/Version\/([\d.]+)/);
browserVersion = match ? match[1] : '';
} else if (ua.includes('Edg')) {
browser = 'Edge';
const match = ua.match(/Edg\/([\d.]+)/);
browserVersion = match ? match[1] : '';
}
// 检测操作系统
let os = 'Unknown';
if (ua.includes('Win')) os = 'Windows';
else if (ua.includes('Mac')) os = 'macOS';
else if (ua.includes('Linux')) os = 'Linux';
else if (ua.includes('Android')) os = 'Android';
else if (ua.includes('iOS')) os = 'iOS';
// 检测是否为移动设备
const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(ua);
return {
browser,
browserVersion,
os,
screenResolution: `${screen.width}x${screen.height}`,
isMobile,
userAgent: ua,
cpuCores: navigator.hardwareConcurrency || '-',
nodeVersion: '-', // Node.js 版本在浏览器环境中不可用
};
});
// 获取内存使用颜色
const getMemoryColor = (usage: number | undefined) => {
if (!usage) return '#3973ff';
if (usage >= 90) return '#f56c6c';
if (usage >= 70) return '#e6a23c';
return '#67c23a';
};
// 获取磁盘使用颜色
const getDiskColor = (usage: number | undefined) => {
if (!usage) return '#3973ff';
if (usage >= 90) return '#f56c6c';
if (usage >= 70) return '#e6a23c';
return '#67c23a';
};
// 获取系统信息
async function fetchSystemInfo() {
loading.value = true;
try {
// 如果有后端API,可以在这里调用
// const res = await getSystemInfo();
// if (res.success && res.data) {
// systemInfo.value = res.data;
// }
// 模拟数据(如果有API会替换)
systemInfo.value = {
name: '云泽管理系统',
version: '1.0.0',
environment: 'Production',
uptime: '24天 5小时 30分钟',
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
serverHost: window.location.hostname,
os: 'Linux',
cpuCores: '4',
memoryUsage: 65,
diskUsage: 42,
dbType: 'MySQL',
dbVersion: '8.0',
dbStatus: 'connected',
dbConnections: 15,
};
} catch (err: any) {
ElMessage.error('获取系统信息失败:' + (err.message || '未知错误'));
} finally {
loading.value = false;
}
}
// 刷新信息
function refreshInfo() {
fetchSystemInfo();
currentTime.value = new Date().toLocaleString('zh-CN');
ElMessage.success('信息已刷新');
}
// 复制系统信息
function copySystemInfo() {
const infoText = `系统信息报告
==================
系统名称:${systemInfo.value.name || '-'}
系统版本:${systemInfo.value.version || '-'}
运行环境:${systemInfo.value.environment || '-'}
系统时间:${currentTime.value}
运行时间:${systemInfo.value.uptime || '-'}
服务器信息:
- 服务器地址:${systemInfo.value.serverHost || '-'}
- API地址:${apiBaseUrl.value}
- 操作系统:${systemInfo.value.os || '-'}
- CPU核心数:${systemInfo.value.cpuCores || '-'}
- 内存使用:${systemInfo.value.memoryUsage || 0}%
- 磁盘使用:${systemInfo.value.diskUsage || 0}%
数据库信息:
- 数据库类型:${systemInfo.value.dbType || '-'}
- 数据库版本:${systemInfo.value.dbVersion || '-'}
- 数据库状态:${systemInfo.value.dbStatus === 'connected' ? '已连接' : '未连接'}
- 连接数:${systemInfo.value.dbConnections || '-'}
客户端信息:
- 浏览器:${clientInfo.value.browser} ${clientInfo.value.browserVersion}
- 操作系统:${clientInfo.value.os}
- 屏幕分辨率:${clientInfo.value.screenResolution}
- 设备类型:${clientInfo.value.isMobile ? '移动设备' : '桌面设备'}
生成时间:${new Date().toLocaleString('zh-CN')}`;
if (navigator.clipboard) {
navigator.clipboard.writeText(infoText).then(() => {
ElMessage.success('系统信息已复制到剪贴板');
}).catch(() => {
ElMessage.error('复制失败,请手动复制');
});
} else {
// 降级方案
const textarea = document.createElement('textarea');
textarea.value = infoText;
document.body.appendChild(textarea);
textarea.select();
try {
document.execCommand('copy');
ElMessage.success('系统信息已复制到剪贴板');
} catch {
ElMessage.error('复制失败,请手动复制');
}
document.body.removeChild(textarea);
}
}
// 更新时间
let timeInterval: NodeJS.Timeout | null = null;
onMounted(() => {
fetchSystemInfo();
// 每秒更新时间
timeInterval = setInterval(() => {
currentTime.value = new Date().toLocaleString('zh-CN');
}, 1000);
});
onUnmounted(() => {
if (timeInterval) {
clearInterval(timeInterval);
}
});
</script>
<style scoped lang="less">
.system-info-container {
padding: 24px;
background-color: var(--el-bg-color-page);
min-height: 100%;
.info-card {
background: var(--el-bg-color);
border: 1px solid var(--el-border-color-lighter);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
.card-header {
display: flex;
align-items: center;
gap: 8px;
.header-icon {
font-size: 20px;
color: var(--el-color-primary);
}
.header-title {
font-size: 18px;
font-weight: 600;
color: var(--el-text-color-primary);
}
}
.info-content {
.info-section {
margin-bottom: 24px;
:deep(.el-descriptions__title) {
font-size: 16px;
font-weight: 600;
color: var(--el-text-color-primary);
margin-bottom: 16px;
padding-bottom: 8px;
border-bottom: 2px solid #4f84ff;
}
:deep(.el-descriptions__label) {
font-weight: 600;
color: var(--el-text-color-regular);
background-color: var(--el-fill-color-lighter);
}
:deep(.el-descriptions__content) {
color: var(--el-text-color-primary);
}
.user-agent {
font-size: 12px;
color: var(--el-text-color-secondary);
word-break: break-all;
}
}
.action-buttons {
display: flex;
justify-content: center;
gap: 12px;
margin-top: 32px;
padding-top: 24px;
border-top: 1px solid var(--el-border-color-lighter);
}
}
}
}
@media (max-width: 768px) {
.system-info-container {
padding: 12px;
.info-card {
.info-content {
.info-section {
:deep(.el-descriptions) {
:deep(.el-descriptions__table) {
.el-descriptions__cell {
display: block;
width: 100% !important;
}
}
}
}
}
}
}
}
</style>