正在进行1.5版本更新,导入第一批代码

This commit is contained in:
2026-07-25 22:15:41 +08:00
parent 1669abf9e8
commit ce07f4f0f0
8 changed files with 717 additions and 117 deletions
+178 -95
View File
@@ -26,7 +26,7 @@
<!-- ====== 登录/注册页 ====== -->
<div v-if="!loggedIn" class="login-card">
<!-- Logo 区域(可替换) -->
<!-- Logo 区域 -->
<div class="login-logo">
<img src="/static/logo.svg" alt="frpc-console" class="logo-img" />
<span class="logo-text">frpc-console</span>
@@ -87,7 +87,7 @@
<!-- ====== 主界面 ====== -->
<div v-else class="main-panel" :class="{ visible: contentVisible }">
<!-- 顶部导航(含 Logo 小标) -->
<!-- 顶部导航 -->
<div class="top-bar">
<div class="top-left">
<img src="/static/logo.svg" alt="frpc-console" class="nav-logo" />
@@ -108,106 +108,18 @@
<!-- Tab 栏 -->
<div class="tab-bar">
<span class="tab-item" :class="{ active: activeTab === 'proxies' }"
@click="activeTab = 'proxies'">隧道列表</span>
@click="activeTab = 'proxies'">📋 隧道列表</span>
<span class="tab-item" :class="{ active: activeTab === 'config' }"
@click="activeTab = 'config'">全局配置信息</span>
@click="activeTab = 'config'">⚙️ 全局配置信息</span>
<span class="tab-item" :class="{ active: activeTab === 'logs' }"
@click="activeTab = 'logs'">📄 运行日志</span>
</div>
<!-- 内容区 -->
<div class="content-area">
<!-- ====== 全局配置 ====== -->
<div v-if="activeTab === 'config'" class="tab-content">
<!-- 账户管理 -->
<div class="profile-section">
<div class="profile-header">
<span>👤 账户管理</span>
<span class="profile-username">{{ loginForm.username }}</span>
</div>
<div class="profile-form">
<div class="form-row">
<label>当前密码</label>
<input v-model="passwordChange.oldPassword" type="password" placeholder="输入当前密码" />
</div>
<div class="form-row">
<label>新密码</label>
<input v-model="passwordChange.newPassword" type="password"
placeholder="至少8位,含大小写/数字/特殊字符" />
</div>
<div class="form-row">
<label>确认新密码</label>
<input v-model="passwordChange.confirmPassword" type="password"
placeholder="再次输入新密码" />
</div>
<button class="save-btn" @click="changePassword">修改密码</button>
<p v-if="passwordChangeError" class="login-error">{{ passwordChangeError }}</p>
<p v-if="passwordChangeSuccess" class="login-success">{{ passwordChangeSuccess }}</p>
</div>
</div>
<!-- 配置卡片 -->
<div class="config-grid">
<div class="metric-card">
<div class="metric-label">TCP Multiplexing</div>
<div class="metric-value">
<span class="status-dot active"></span>
<span class="status-text active">已启用(固定)</span>
</div>
</div>
<div class="metric-card">
<div class="metric-label">连接池大小</div>
<div class="metric-value">
<span class="big-number">{{ globalConfig.poolCount || 8 }}</span>
<span class="unit"></span>
</div>
</div>
<div class="metric-card">
<div class="metric-label">心跳间隔 / 超时</div>
<div class="metric-value">
<span class="digit">{{ globalConfig.heartbeatInterval || 15 }}s</span>
<span class="sep">/</span>
<span class="digit">{{ globalConfig.heartbeatTimeout || 70 }}s</span>
</div>
</div>
</div>
<div class="detail-collapse" @click="showDetail = !showDetail">
<span>{{ showDetail ? '收起全部配置 ▲' : '展开全部配置 ▼' }}</span>
</div>
<div v-show="showDetail" class="detail-panel">
<div class="form-row"><label>Server Address</label><input
v-model="globalConfig.serverAddr" /></div>
<div class="form-row"><label>Server Port</label><input type="number"
v-model="globalConfig.serverPort" /></div>
<div class="form-row"><label>Token</label><input type="password"
v-model="globalConfig.token" /></div>
<div class="form-row">
<label>Log Level</label>
<select v-model="globalConfig.logLevel">
<option value="trace">trace</option>
<option value="debug">debug</option>
<option value="info">info</option>
<option value="warn">warn</option>
<option value="error">error</option>
</select>
</div>
<div class="form-row"><label>Log Max Days</label><input type="number"
v-model="globalConfig.logMaxDays" /></div>
<div class="form-row"><label>TCP Mux Keepalive</label><input type="number"
v-model="globalConfig.tcpMuxKeepalive" /></div>
<div class="form-row"><label>Heartbeat Interval</label><input type="number"
v-model="globalConfig.heartbeatInterval" /></div>
<div class="form-row"><label>Heartbeat Timeout</label><input type="number"
v-model="globalConfig.heartbeatTimeout" /></div>
<div class="form-row"><label>Pool Count</label><input type="number"
v-model="globalConfig.poolCount" /></div>
<button class="save-btn" @click="saveConfig">保存配置并热加载</button>
</div>
</div>
<!-- ====== 隧道列表 ====== -->
<div v-else-if="activeTab === 'proxies'" class="tab-content">
<div v-if="activeTab === 'proxies'" class="tab-content">
<div class="toolbar">
<div class="toolbar-left">
<button class="btn-import" @click="triggerImport">导入 TOML</button>
@@ -245,6 +157,177 @@
<div v-if="filteredProxies.length === 0" class="empty-state">暂无隧道,点击「新增隧道」添加</div>
</div>
</div>
<!-- ====== 全局配置信息 ====== -->
<div v-if="activeTab === 'config'" class="tab-content config-tab-content">
<!-- 页面标题 -->
<div class="config-page-header">
<h2>⚙️ 全局配置信息</h2>
<p class="config-subtitle">管理 frpc 连接参数与传输设置</p>
</div>
<!-- 首次使用提示 -->
<div class="config-tip">
⚠️ 首次使用请修改「服务器地址」和「认证令牌」为您的真实 frps 配置
</div>
<!-- ===== 账户管理 ===== -->
<div class="profile-section">
<div class="profile-header">
<span>👤 账户管理</span>
<span class="profile-username">{{ loginForm.username }}</span>
</div>
<div class="profile-form">
<div class="form-row">
<label>当前密码</label>
<input v-model="passwordChange.oldPassword" type="password" placeholder="输入当前密码" />
</div>
<div class="form-row">
<label>新密码</label>
<input v-model="passwordChange.newPassword" type="password"
placeholder="至少8位,含大小写/数字/特殊字符" />
</div>
<div class="form-row">
<label>确认新密码</label>
<input v-model="passwordChange.confirmPassword" type="password"
placeholder="再次输入新密码" />
</div>
<button class="save-btn" @click="changePassword">修改密码</button>
<p v-if="passwordChangeError" class="login-error">{{ passwordChangeError }}</p>
<p v-if="passwordChangeSuccess" class="login-success">{{ passwordChangeSuccess }}</p>
</div>
</div>
<!-- ===== 卡片1: 服务器连接 ===== -->
<div class="config-card">
<div class="config-card-header">
<span class="card-icon">🌐</span>
<span class="card-title">服务器连接</span>
</div>
<div class="config-card-body">
<div class="form-row">
<label>服务器地址</label>
<input v-model="globalConfig.serverAddr" placeholder="例如: frp.example.com" />
</div>
<div class="form-row">
<label>服务器端口</label>
<input type="number" v-model="globalConfig.serverPort" placeholder="7000" />
</div>
<div class="form-row" style="grid-column: 1 / -1;">
<label>认证令牌</label>
<div class="token-input-wrapper">
<input :type="showToken ? 'text' : 'password'" v-model="globalConfig.token"
placeholder="CHANGE_ME" />
<button class="token-toggle-btn" @click="showToken = !showToken">
{{ showToken ? '隐藏' : '显示' }}
</button>
</div>
</div>
</div>
</div>
<!-- ===== 卡片2: 传输配置 ===== -->
<div class="config-card">
<div class="config-card-header">
<span class="card-icon">🔀</span>
<span class="card-title">传输配置</span>
</div>
<div class="config-card-body">
<div class="form-row readonly-row">
<label>TCP 多路复用</label>
<div class="readonly-value">
<span class="status-dot active"></span>
<span class="status-text active">已强制开启</span>
<span class="hint-text">优化连接性能,减少延迟,frp 官方推荐开启</span>
</div>
</div>
<div class="form-row">
<label>TCP Mux 保活间隔</label>
<input type="number" v-model="globalConfig.tcpMuxKeepalive" />
<span class="unit-suffix"></span>
</div>
<div class="form-row">
<label>心跳间隔</label>
<input type="number" v-model="globalConfig.heartbeatInterval" />
<span class="unit-suffix"></span>
</div>
<div class="form-row">
<label>心跳超时</label>
<input type="number" v-model="globalConfig.heartbeatTimeout" />
<span class="unit-suffix"></span>
</div>
<div class="form-row">
<label>连接池大小</label>
<input type="number" v-model="globalConfig.poolCount" />
<span class="unit-suffix"></span>
</div>
</div>
</div>
<!-- ===== 卡片3: 日志配置 ===== -->
<div class="config-card">
<div class="config-card-header">
<span class="card-icon">📋</span>
<span class="card-title">日志配置</span>
</div>
<div class="config-card-body">
<div class="form-row">
<label>日志级别</label>
<select v-model="globalConfig.logLevel">
<option value="trace">trace</option>
<option value="debug">debug</option>
<option value="info">info</option>
<option value="warn">warn</option>
<option value="error">error</option>
</select>
</div>
<div class="form-row">
<label>日志保留天数</label>
<input type="number" v-model="globalConfig.logMaxDays" />
<span class="unit-suffix"></span>
</div>
</div>
</div>
<!-- 保存按钮 -->
<button class="save-config-btn" @click="saveConfig">💾 保存配置并热加载</button>
</div>
<!-- ====== 运行日志 ====== -->
<div v-else-if="activeTab === 'logs'" class="tab-content log-tab-content">
<!-- 工具栏 -->
<div class="log-toolbar">
<div class="log-toolbar-left">
<span class="log-info-badge">📊 共 {{ logTotal }} 行</span>
<span v-if="logError" class="log-error-badge">⚠️ {{ logError }}</span>
</div>
<div class="log-toolbar-right">
<label class="log-auto-scroll-label">
<input type="checkbox" v-model="logAutoScroll" />
自动滚动
</label>
<button class="log-btn" @click="refreshLogs">🔄 刷新</button>
<button class="log-btn" @click="scrollLogToBottom">↓ 滚动到底部</button>
</div>
</div>
<!-- 日志显示区域 -->
<div class="log-terminal" id="logContainer">
<div v-if="logLines.length === 0 && !logError" class="log-empty">
暂无日志,frpc 尚未产生输出
</div>
<div v-else class="log-lines">
<div v-for="(line, idx) in logLines" :key="idx" class="log-line">{{ line }}</div>
</div>
</div>
<!-- 底部状态 -->
<div class="log-footer">
<span>🕐 上次更新: {{ logLastUpdate || '--:--:--' }}</span>
<span class="log-polling-status">🔄 自动刷新中 (8s)</span>
</div>
</div>
</div>
</div>
</div>