WebhockTransfer/templates/admin/endpoints.html
houhuan 2bc7460f1f feat: 初始化Webhook中继系统项目
- 添加FastAPI应用基础结构,包括主入口、路由和模型定义
- 实现Webhook接收端点(/webhook/{namespace})和健康检查(/health)
- 添加管理后台路由和模板,支持端点、目标、渠道和模板管理
- 包含SQLite数据库模型定义和初始化逻辑
- 添加日志记录和统计服务
- 包含Dockerfile和配置示例文件
- 添加项目文档,包括设计、流程图和验收标准
2025-12-21 18:43:12 +08:00

125 lines
5.6 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{% extends "admin/base.html" %}
{% block title %}端点管理 - Webhook{% endblock %}
{% block content %}
<div class="row mb-3">
<div class="col">
<h3>接收端点 (Endpoints)</h3>
</div>
<div class="col-auto">
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addModal">添加端点</button>
</div>
</div>
<div class="alert alert-info alert-dismissible fade show" role="alert">
<strong>什么是“接收端点”?</strong>
<p class="mb-0">
接收端点Endpoints<strong>外部系统向本服务发送Webhook数据的入口地址</strong><br>
<strong>Namespace</strong>URL路径的唯一标识。例如创建 namespace 为 <code>client_a</code>,则外部请求地址为 <code>/webhook/client_a</code><br>
<strong>流程配置</strong>:点击列表中的 <span class="badge bg-info text-dark">Namespace</span><button class="btn btn-sm btn-outline-primary py-0 px-1">⚙️ 配置</button> 按钮,进入端点的规则编排页面。
</p>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<table class="table table-striped">
<thead>
<tr>
<th>ID</th>
<th>Namespace</th>
<th>完整URL示例</th>
<th>描述</th>
<th>状态</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for e in endpoints %}
<tr>
<td>{{ e.id }}</td>
<td><a href="/admin/endpoints/{{ e.id }}" class="text-decoration-none"><span class="badge bg-info text-dark fs-6">{{ e.namespace }}</span></a></td>
<td>
<code>/webhook/{{ e.namespace }}</code>
<button class="btn btn-sm btn-link text-decoration-none copy-btn" data-path="/webhook/{{ e.namespace }}" title="复制完整URL">📋</button>
</td>
<td>{{ e.description or '-' }}</td>
<td>
{% if e.is_active %}
<span class="badge bg-success">启用</span>
{% else %}
<span class="badge bg-secondary">禁用</span>
{% endif %}
</td>
<td>{{ e.created_at.strftime('%Y-%m-%d %H:%M') }}</td>
<td>
<a href="/admin/endpoints/{{ e.id }}" class="btn btn-sm btn-outline-primary">⚙️ 配置</a>
<form action="/admin/endpoints/toggle" method="post" style="display:inline">
<input type="hidden" name="id" value="{{ e.id }}">
{% if e.is_active %}
<button type="submit" class="btn btn-sm btn-warning">禁用</button>
{% else %}
<button type="submit" class="btn btn-sm btn-success">启用</button>
{% endif %}
</form>
<form action="/admin/endpoints/delete" method="post" style="display:inline" onsubmit="return confirm('确定删除?')">
<input type="hidden" name="id" value="{{ e.id }}">
<button type="submit" class="btn btn-sm btn-danger">删除</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<!-- Add Modal -->
<div class="modal fade" id="addModal" tabindex="-1">
<div class="modal-dialog">
<form action="/admin/endpoints" method="post">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">创建新端点</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label class="form-label">Namespace (URL路径的一部分)</label>
<input type="text" class="form-control" name="namespace" required placeholder="my-service-1">
<div class="form-text">只能包含字母、数字、下划线或连字符。</div>
</div>
<div class="mb-3">
<label class="form-label">描述</label>
<input type="text" class="form-control" name="description" placeholder="用于XX业务接收">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="submit" class="btn btn-primary">保存</button>
</div>
</div>
</form>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('.copy-btn').forEach(btn => {
btn.addEventListener('click', function() {
const path = this.getAttribute('data-path');
// Construct full URL based on current window location
const fullUrl = window.location.origin + path;
navigator.clipboard.writeText(fullUrl).then(() => {
const originalContent = this.innerHTML;
this.innerHTML = '✅';
setTimeout(() => {
this.innerHTML = originalContent;
}, 1500);
}).catch(err => {
console.error('Failed to copy: ', err);
alert('复制失败,请手动复制');
});
});
});
});
</script>
{% endblock %}