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

197 lines
7.9 KiB
HTML

{% extends "admin/base.html" %}
{% block title %}仪表盘 - Webhook{% endblock %}
{% block content %}
<div class="row mb-4">
<div class="col-md-4">
<div class="card text-center h-100 border-primary">
<div class="card-body d-flex flex-column justify-content-center">
<h5 class="card-title text-muted">今日请求总数</h5>
<p class="card-text display-4 text-primary fw-bold">{{ system_stats.today_count }}</p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card text-center h-100 border-success">
<div class="card-body d-flex flex-column justify-content-center">
<h5 class="card-title text-muted">系统运行时间</h5>
<p class="card-text display-6 text-success">{{ system_stats.uptime }}</p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card text-center h-100 border-info">
<div class="card-body d-flex flex-column justify-content-center">
<h5 class="card-title text-muted">最新活动</h5>
<p class="card-text lead">{{ system_stats.latest_log or '暂无数据' }}</p>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<!-- Simulation Card -->
<div class="card mb-4 border-warning">
<div class="card-header bg-warning text-dark d-flex justify-content-between align-items-center">
<h5 class="mb-0">⚡ 模拟数据推送</h5>
<small>测试您的规则配置</small>
</div>
<div class="card-body">
<div class="mb-3">
<label class="form-label">选择端点 (Namespace)</label>
<select class="form-select" id="simNamespace">
{% for ep in endpoints %}
<option value="{{ ep.namespace }}">{{ ep.namespace }} ({{ ep.description or 'No Desc' }})</option>
{% endfor %}
</select>
{% if not endpoints %}
<div class="text-danger small mt-1">请先创建端点</div>
{% endif %}
</div>
<div class="mb-3">
<label class="form-label">JSON Payload</label>
<textarea class="form-control font-monospace" id="simPayload" rows="6">
{
"event_define_no": "pay.wx_scaned",
"trans_order_info": {
"remark": "imcgcd03",
"amt": 100.00
}
}</textarea>
<div class="form-text">
<a href="#" onclick="fillSample('wx'); return false;">[微信示例]</a>
<a href="#" onclick="fillSample('ali'); return false;">[支付宝示例]</a>
</div>
</div>
<button class="btn btn-warning w-100" onclick="runSimulation()" {% if not endpoints %}disabled{% endif %}>
发送模拟请求 (POST)
</button>
<div id="simResult" class="mt-3 d-none">
<hr>
<h6>执行结果:</h6>
<pre class="bg-light p-2 border rounded small" id="simOutput"></pre>
<div class="text-center mt-2">
<a href="/admin/logs" class="btn btn-sm btn-outline-secondary">查看详细日志</a>
</div>
</div>
</div>
</div>
<div class="card mb-4">
<div class="card-header bg-light">
<h5 class="mb-0">快速开始</h5>
</div>
<div class="card-body">
<p>欢迎使用 Webhook 中继平台。请按照以下步骤配置您的第一个流程:</p>
<ol class="list-group list-group-numbered list-group-flush">
<li class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
<div class="fw-bold">添加资源</div>
配置转发目标 (Target) 或通知渠道 (Channel)。
</div>
<a href="/admin/targets" class="btn btn-sm btn-outline-primary">去配置</a>
</li>
<li class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
<div class="fw-bold">创建端点</div>
定义一个 Webhook 接收地址 (Namespace)。
</div>
<a href="/admin/endpoints" class="btn btn-sm btn-outline-primary">去创建</a>
</li>
<li class="list-group-item d-flex justify-content-between align-items-start">
<div class="ms-2 me-auto">
<div class="fw-bold">设置规则</div>
在端点详情页添加入站匹配规则和动作。
</div>
</li>
</ol>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card mb-4">
<div class="card-header bg-light d-flex justify-content-between align-items-center">
<h5 class="mb-0">系统状态</h5>
<span class="badge bg-success">Online</span>
</div>
<div class="card-body">
<ul class="list-group list-group-flush">
<li class="list-group-item">
<strong>API 基础地址:</strong>
<code>http://{your-host}:8090/webhook/</code>
</li>
<li class="list-group-item">
<strong>文档:</strong>
<a href="/docs" target="_blank">Swagger UI</a> / <a href="/redoc" target="_blank">Redoc</a>
</li>
<li class="list-group-item">
<strong>当前版本:</strong> v2.2.0 (Tree Rule Engine)
</li>
</ul>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
function fillSample(type) {
const area = document.getElementById('simPayload');
if (type === 'wx') {
area.value = JSON.stringify({
"event_define_no": "pay.wx_scaned",
"trans_order_info": {
"remark": "imcgcd03",
"amt": 88.88
}
}, null, 2);
} else if (type === 'ali') {
area.value = JSON.stringify({
"event_define_no": "pay.ali_scaned",
"trans_order_info": {
"remark": "imcgcd02",
"amt": 66.66
}
}, null, 2);
}
}
async function runSimulation() {
const ns = document.getElementById('simNamespace').value;
const payloadStr = document.getElementById('simPayload').value;
const resultDiv = document.getElementById('simResult');
const outputPre = document.getElementById('simOutput');
if (!ns) {
alert("请选择端点");
return;
}
try {
// Validate JSON
const payload = JSON.parse(payloadStr);
outputPre.innerText = "发送中...";
resultDiv.classList.remove('d-none');
const response = await fetch(`/webhook/${ns}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(payload)
});
const data = await response.json();
outputPre.innerText = "状态码: " + response.status + "\n" + JSON.stringify(data, null, 2);
} catch (e) {
alert("JSON 格式错误或请求失败: " + e);
outputPre.innerText = "错误: " + e;
}
}
</script>
{% endblock %}