353 lines
11 KiB
JavaScript
353 lines
11 KiB
JavaScript
// 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('删除失败')
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}) |