// GoHttp 管理控制台 - 前端应用 new Vue({ el: '#app', data() { return { loading: false, activeTab: 'servers', servers: [], tcpProxies: [], runningTcpProxies: [], goroutines: 0, serverDialog: { visible: false, title: '添加服务器', isEdit: false, saving: false, form: this.getDefaultServerForm() }, tcpDialog: { visible: false, title: '添加TCP代理', isEdit: false, saving: false, form: this.getDefaultTcpForm() } } }, mounted() { this.refreshAll() this.startStatusPolling() }, methods: { // 获取默认服务器表单 getDefaultServerForm() { return { name: '', server: [], port: 8080, enable_ssl: false, certfile: '', keyfile: '', paths: [] } }, // 获取默认TCP代理表单 getDefaultTcpForm() { return { name: '', listen: '', target: '', enabled: true } }, // 重置服务器表单 resetServerForm() { this.serverDialog.form = this.getDefaultServerForm() this.serverDialog.isEdit = false }, // 重置TCP表单 resetTcpForm() { this.tcpDialog.form = this.getDefaultTcpForm() this.tcpDialog.isEdit = false }, // API请求封装 async request(method, url, data) { try { const options = { method: method, headers: { 'Content-Type': 'application/json' } } if (data && (method === 'POST' || method === 'PUT' || method === 'DELETE')) { options.body = JSON.stringify({ data }) } const response = await fetch(url, options) const result = await response.json() if (result.code !== 200) { this.$message.error(result.error || '操作失败') return null } return result } catch (error) { console.error('Request error:', error) this.$message.error('网络错误: ' + error.message) return null } }, // 刷新所有数据 async refreshAll() { this.loading = true await Promise.all([ this.fetchServers(), this.fetchTcpProxies(), this.fetchStatus() ]) this.loading = false }, // 获取服务器列表 async fetchServers() { const result = await this.request('GET', '/api/config') if (result) { this.servers = result.data || [] } }, // 获取TCP代理列表 async fetchTcpProxies() { const result = await this.request('GET', '/api/tcp') if (result) { this.tcpProxies = result.data || [] } }, // 获取系统状态 async fetchStatus() { const result = await this.request('GET', '/api/status') if (result && result.data) { this.goroutines = result.data.goroutines || 0 } }, // 定时获取状态 startStatusPolling() { setInterval(() => { if (this.activeTab === 'status') { this.fetchStatus() } }, 5000) }, // Tab切换 handleTabClick(tab) { if (tab.name === 'status') { this.fetchStatus() } }, // 判断TCP代理是否运行中 isTcpRunning(name) { return this.runningTcpProxies.includes(name) }, // 显示服务器对话框 showServerDialog(server) { if (server) { this.serverDialog.title = '编辑服务器' this.serverDialog.isEdit = true // 转换后端数据格式到前端 this.serverDialog.form = { name: server.name, server: server.server || [], port: server.port, enable_ssl: server.enable_ssl || false, certfile: server.certfile || '', keyfile: server.keyfile || '', paths: (server.paths || []).map(p => ({ path: p.path, type: p.root ? 'static' : (p.upstreams && p.upstreams.length > 0 ? 'proxy' : 'static'), root: p.root || '', default: p.default || '', upstreams: p.upstreams || [] })) } } else { this.serverDialog.title = '添加服务器' this.serverDialog.isEdit = false this.serverDialog.form = this.getDefaultServerForm() } this.serverDialog.visible = true }, // 添加路由 addPath() { this.serverDialog.form.paths.push({ path: '', type: 'static', root: '', default: 'index.html', upstreams: [] }) }, // 移除路由 removePath(index) { this.serverDialog.form.paths.splice(index, 1) }, // 路由类型变更 onPathTypeChange(path) { if (path.type === 'static') { path.upstreams = [] } else { path.root = '' path.default = '' } }, // 保存服务器 async saveServer() { const form = this.serverDialog.form if (!form.name || !form.port) { this.$message.warning('请填写必填项') return } // 转换前端数据格式到后端 const serverConfig = { name: form.name, server: form.server, port: form.port, enable_ssl: form.enable_ssl, certfile: form.certfile, keyfile: form.keyfile, paths: form.paths.map(p => ({ path: p.path, root: p.type === 'static' ? p.root : '', default: p.type === 'static' ? p.default : '', upstreams: p.type === 'proxy' ? p.upstreams : [], directives: p.directives || [] })) } this.serverDialog.saving = true const result = await this.request('POST', '/api/config', serverConfig) this.serverDialog.saving = false if (result) { this.$message.success('保存成功') this.serverDialog.visible = false await this.fetchServers() } }, // 重启服务器 async restartServer(name) { try { const result = await this.request('POST', `/api/server/restart/${name}`) if (result) { this.$message.success(`服务器 ${name} 已重启`) } } catch (e) { this.$message.error('重启失败') } }, // 删除服务器 async deleteServer(name) { try { await this.$confirm(`确定要删除服务器 "${name}" 吗?`, '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }) const result = await this.request('DELETE', `/api/server/${name}`) if (result) { this.$message.success('删除成功') await this.fetchServers() } } catch (e) { if (e !== 'cancel') { this.$message.error('删除失败') } } }, // 显示TCP代理对话框 showTcpDialog(tcp) { if (tcp) { this.tcpDialog.title = '编辑TCP代理' this.tcpDialog.isEdit = true this.tcpDialog.form = { name: tcp.name, listen: tcp.listen, target: tcp.target, enabled: tcp.enabled !== false } } else { this.tcpDialog.title = '添加TCP代理' this.tcpDialog.isEdit = false this.tcpDialog.form = this.getDefaultTcpForm() } this.tcpDialog.visible = true }, // 保存TCP代理 async saveTcpProxy() { const form = this.tcpDialog.form if (!form.name || !form.listen || !form.target) { this.$message.warning('请填写必填项') return } this.tcpDialog.saving = true const result = await this.request('POST', '/api/tcp', form) this.tcpDialog.saving = false if (result) { this.$message.success('保存成功') this.tcpDialog.visible = false await this.fetchTcpProxies() } }, // 切换TCP代理状态 async toggleTcpProxy(tcp) { const action = this.isTcpRunning(tcp.name) ? 'stop' : 'start' try { const result = await this.request('POST', `/api/tcp/${action}/${tcp.name}`) if (result) { this.$message.success(`TCP代理已${action === 'stop' ? '停止' : '启动'}`) // 更新运行状态 if (action === 'start') { if (!this.runningTcpProxies.includes(tcp.name)) { this.runningTcpProxies.push(tcp.name) } } else { this.runningTcpProxies = this.runningTcpProxies.filter(n => n !== tcp.name) } } } catch (e) { this.$message.error('操作失败') } }, // 删除TCP代理 async deleteTcpProxy(name) { try { await this.$confirm(`确定要删除TCP代理 "${name}" 吗?`, '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }) const result = await this.request('DELETE', `/api/tcp/${name}`) if (result) { this.$message.success('删除成功') this.runningTcpProxies = this.runningTcpProxies.filter(n => n !== name) await this.fetchTcpProxies() } } catch (e) { if (e !== 'cancel') { this.$message.error('删除失败') } } } } })