gohttp/adminui/index.html

264 lines
15 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>GoHttp 管理控制台</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/element-ui/2.15.13/theme-chalk/index.min.css">
<link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div id="app">
<div class="container mx-auto px-4 py-8">
<!-- Header -->
<el-header class="flex justify-between items-center mb-8">
<div class="flex items-center">
<i class="fas fa-server text-3xl mr-3 text-blue-400"></i>
<h1 class="text-2xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-blue-400 to-purple-500">
GoHttp 管理控制台
</h1>
</div>
<div class="flex items-center space-x-4">
<el-button type="primary" @click="refreshAll" :loading="loading">
<i class="fas fa-sync mr-2"></i>刷新
</el-button>
</div>
</el-header>
<!-- Tabs -->
<el-tabs v-model="activeTab" @tab-click="handleTabClick">
<!-- 服务器配置 -->
<el-tab-pane label="服务器配置" name="servers">
<el-card class="glass-card mb-6">
<div slot="header" class="flex justify-between items-center">
<span class="text-xl font-semibold text-blue-300">
<i class="fas fa-cog mr-2"></i>HTTP服务器
</span>
<el-button type="primary" @click="showServerDialog()" size="small">
<i class="fas fa-plus mr-1"></i>添加服务器
</el-button>
</div>
<el-table :data="servers" stripe style="width: 100%" v-loading="loading">
<el-table-column prop="name" label="名称" width="150"></el-table-column>
<el-table-column prop="server" label="域名" width="200">
<template slot-scope="scope">
{{ scope.row.server ? scope.row.server.join(', ') : '-' }}
</template>
</el-table-column>
<el-table-column prop="port" label="端口" width="100"></el-table-column>
<el-table-column label="SSL" width="80">
<template slot-scope="scope">
<el-tag :type="scope.row.enable_ssl ? 'success' : 'info'" size="small">
{{ scope.row.enable_ssl ? '启用' : '禁用' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="路径数" width="80">
<template slot-scope="scope">
{{ scope.row.paths ? scope.row.paths.length : 0 }}
</template>
</el-table-column>
<el-table-column label="操作" min-width="280">
<template slot-scope="scope">
<el-button type="text" size="small" @click="showServerDialog(scope.row)" class="mr-2">
<i class="fas fa-edit mr-1"></i>编辑
</el-button>
<el-button type="text" size="small" @click="restartServer(scope.row.name)" class="mr-2">
<i class="fas fa-redo mr-1"></i>重启
</el-button>
<el-button type="text" size="small" @click="deleteServer(scope.row.name)" class="text-red-400">
<i class="fas fa-trash mr-1"></i>删除
</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
</el-tab-pane>
<!-- TCP代理 -->
<el-tab-pane label="TCP代理" name="tcp">
<el-card class="glass-card mb-6">
<div slot="header" class="flex justify-between items-center">
<span class="text-xl font-semibold text-blue-300">
<i class="fas fa-exchange-alt mr-2"></i>TCP代理
</span>
<el-button type="primary" @click="showTcpDialog()" size="small">
<i class="fas fa-plus mr-1"></i>添加代理
</el-button>
</div>
<el-table :data="tcpProxies" stripe style="width: 100%" v-loading="loading">
<el-table-column prop="name" label="名称" width="150"></el-table-column>
<el-table-column prop="listen" label="监听" width="200"></el-table-column>
<el-table-column prop="target" label="目标"></el-table-column>
<el-table-column label="状态" width="100">
<template slot-scope="scope">
<el-tag :type="isTcpRunning(scope.row.name) ? 'success' : 'info'" size="small">
{{ isTcpRunning(scope.row.name) ? '运行中' : '已停止' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" min-width="200">
<template slot-scope="scope">
<el-button type="text" size="small" @click="showTcpDialog(scope.row)" class="mr-2">
<i class="fas fa-edit mr-1"></i>编辑
</el-button>
<el-button type="text" size="small" @click="toggleTcpProxy(scope.row)" class="mr-2">
<i :class="isTcpRunning(scope.row.name) ? 'fas fa-stop mr-1' : 'fas fa-play mr-1'"></i>
{{ isTcpRunning(scope.row.name) ? '停止' : '启动' }}
</el-button>
<el-button type="text" size="small" @click="deleteTcpProxy(scope.row.name)" class="text-red-400">
<i class="fas fa-trash mr-1"></i>删除
</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
</el-tab-pane>
<!-- 系统状态 -->
<el-tab-pane label="系统状态" name="status">
<el-row :gutter="20">
<el-col :span="8">
<el-card class="glass-card text-center">
<div class="text-3xl font-bold text-green-400 mb-1">{{ goroutines }}</div>
<div class="text-xs text-gray-400">Goroutines</div>
</el-card>
</el-col>
</el-row>
</el-tab-pane>
</el-tabs>
</div>
<!-- Server Dialog -->
<el-dialog :title="serverDialog.title" :visible.sync="serverDialog.visible" width="70%" @closed="resetServerForm">
<el-form :model="serverDialog.form" label-width="120px" ref="serverForm">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="名称" prop="name" :rules="[{ required: true, message: '请输入名称', trigger: 'blur' }]">
<el-input v-model="serverDialog.form.name" :disabled="serverDialog.isEdit"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="端口" prop="port" :rules="[{ required: true, message: '请输入端口', trigger: 'blur' }]">
<el-input-number v-model="serverDialog.form.port" :min="1" :max="65535"></el-input-number>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="域名" prop="server">
<el-select v-model="serverDialog.form.server" multiple filterable allow-create placeholder="输入域名后回车" style="width: 100%">
<el-option v-for="s in serverDialog.form.server" :key="s" :label="s" :value="s"></el-option>
</el-select>
</el-form-item>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="启用SSL">
<el-switch v-model="serverDialog.form.enable_ssl"></el-switch>
</el-form-item>
</el-col>
<el-col :span="12" v-if="serverDialog.form.enable_ssl">
<el-form-item label="证书文件">
<el-input v-model="serverDialog.form.certfile" placeholder="/path/to/cert.pem"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" v-if="serverDialog.form.enable_ssl">
<el-col :span="12">
<el-form-item label="密钥文件">
<el-input v-model="serverDialog.form.keyfile" placeholder="/path/to/key.pem"></el-input>
</el-form-item>
</el-col>
</el-row>
<!-- Paths -->
<el-divider><i class="fas fa-route mr-2"></i>路由配置</el-divider>
<div v-for="(path, index) in serverDialog.form.paths" :key="index" class="glass-card p-4 mb-4">
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="路径">
<el-input v-model="path.path" placeholder="/api"></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="类型">
<el-select v-model="path.type" @change="onPathTypeChange(path)">
<el-option label="静态文件" value="static"></el-option>
<el-option label="反向代理" value="proxy"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="操作">
<el-button type="danger" icon="el-icon-delete" circle @click="removePath(index)"></el-button>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" v-if="path.type === 'static'">
<el-col :span="12">
<el-form-item label="根目录">
<el-input v-model="path.root" placeholder="/var/www/html"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="默认文件">
<el-input v-model="path.default" placeholder="index.html"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20" v-if="path.type === 'proxy'">
<el-col :span="24">
<el-form-item label="上游服务器">
<el-select v-model="path.upstreams" multiple filterable allow-create placeholder="输入地址后回车" style="width: 100%">
<el-option v-for="u in path.upstreams" :key="u" :label="u" :value="u"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</div>
<el-button type="primary" plain @click="addPath" class="mb-4">
<i class="fas fa-plus mr-1"></i>添加路由
</el-button>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="serverDialog.visible = false">取消</el-button>
<el-button type="primary" @click="saveServer" :loading="serverDialog.saving">保存</el-button>
</span>
</el-dialog>
<!-- TCP Proxy Dialog -->
<el-dialog :title="tcpDialog.title" :visible.sync="tcpDialog.visible" width="500px" @closed="resetTcpForm">
<el-form :model="tcpDialog.form" label-width="100px" ref="tcpForm">
<el-form-item label="名称" prop="name" :rules="[{ required: true, message: '请输入名称', trigger: 'blur' }]">
<el-input v-model="tcpDialog.form.name" :disabled="tcpDialog.isEdit"></el-input>
</el-form-item>
<el-form-item label="监听地址" prop="listen" :rules="[{ required: true, message: '请输入监听地址', trigger: 'blur' }]">
<el-input v-model="tcpDialog.form.listen" placeholder="0.0.0.0:3306"></el-input>
</el-form-item>
<el-form-item label="目标地址" prop="target" :rules="[{ required: true, message: '请输入目标地址', trigger: 'blur' }]">
<el-input v-model="tcpDialog.form.target" placeholder="192.168.1.100:3306"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="tcpDialog.visible = false">取消</el-button>
<el-button type="primary" @click="saveTcpProxy" :loading="tcpDialog.saving">保存</el-button>
</span>
</el-dialog>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.14/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/element-ui/2.15.13/index.min.js"></script>
<script src="js/app.js"></script>
</body>
</html>