141 lines
5.9 KiB
HTML
141 lines
5.9 KiB
HTML
{% extends "admin/base.html" %}
|
||
{% block title %}消息模板 - Webhook{% endblock %}
|
||
{% block content %}
|
||
<div class="row mb-3">
|
||
<div class="col">
|
||
<h3>消息模板资源</h3>
|
||
</div>
|
||
<div class="col-auto">
|
||
<button type="button" class="btn btn-primary" onclick="openAddModal()">添加模板</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="alert alert-info alert-dismissible fade show" role="alert">
|
||
<strong>什么是“消息模板”?</strong>
|
||
<p class="mb-0">
|
||
消息模板(Message Templates)是<strong>纯文本资源</strong>,供“通知动作”调用。<br>
|
||
<strong>变量替换</strong>:使用 <code>{variable}</code> 语法插入 JSON 中的数据。<br>
|
||
例如:<code>{trans_order_info_remark}</code> 或 <code>{body_status}</code>(引擎会将嵌套JSON展平为下划线连接的键)。
|
||
</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>模板名称</th>
|
||
<th>内容预览</th>
|
||
<th>操作</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for t in templates %}
|
||
<tr>
|
||
<td>{{ t.id }}</td>
|
||
<td>{{ t.name }}</td>
|
||
<td>{{ t.template_content }}</td>
|
||
<td>
|
||
<button class="btn btn-sm btn-outline-primary"
|
||
onclick="openEditModal('{{ t.id }}', '{{ t.name }}', `{{ t.template_content }}`)">修改</button>
|
||
<form action="/admin/templates/delete" method="post" style="display:inline" onsubmit="return confirm('确定删除?')">
|
||
<input type="hidden" name="id" value="{{ t.id }}">
|
||
<button type="submit" class="btn btn-sm btn-danger">删除</button>
|
||
</form>
|
||
</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
|
||
<!-- Modal -->
|
||
<div class="modal fade" id="templateModal" tabindex="-1">
|
||
<div class="modal-dialog">
|
||
<form id="templateForm" action="/admin/templates" method="post">
|
||
<input type="hidden" name="id" id="templateId">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title" id="modalTitle">添加消息模板</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">模板名称</label>
|
||
<input type="text" class="form-control" name="name" id="templateName" required placeholder="收款成功通知">
|
||
</div>
|
||
<div class="mb-3">
|
||
<label class="form-label">模板内容</label>
|
||
<textarea class="form-control" name="template_content" id="templateContent" rows="3" required placeholder="收到{trans_amt}元"></textarea>
|
||
</div>
|
||
<div class="mb-3">
|
||
<label class="form-label">示例 Payload (JSON, 可选,用于预览)</label>
|
||
<textarea class="form-control font-monospace" id="templateSample" rows="4" placeholder='{"trans_amt": 100, "trans_order_info": {"remark": "abc"}}'></textarea>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
|
||
<button type="button" class="btn btn-outline-secondary" onclick="previewTemplate()">预览</button>
|
||
<button type="submit" class="btn btn-primary">保存</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
{% endblock %}
|
||
|
||
{% block scripts %}
|
||
<script>
|
||
var modal = new bootstrap.Modal(document.getElementById('templateModal'));
|
||
|
||
function openAddModal() {
|
||
document.getElementById('modalTitle').innerText = "添加消息模板";
|
||
document.getElementById('templateForm').action = "/admin/templates";
|
||
document.getElementById('templateId').value = "";
|
||
document.getElementById('templateName').value = "";
|
||
document.getElementById('templateContent').value = "";
|
||
document.getElementById('templateSample').value = '';
|
||
modal.show();
|
||
}
|
||
|
||
function openEditModal(id, name, content) {
|
||
document.getElementById('modalTitle').innerText = "修改消息模板";
|
||
document.getElementById('templateForm').action = "/admin/templates/update";
|
||
document.getElementById('templateId').value = id;
|
||
document.getElementById('templateName').value = name;
|
||
document.getElementById('templateContent').value = content;
|
||
document.getElementById('templateSample').value = '';
|
||
modal.show();
|
||
}
|
||
|
||
async function previewTemplate() {
|
||
const content = document.getElementById('templateContent').value;
|
||
let sample = {};
|
||
try {
|
||
const sampleText = document.getElementById('templateSample').value;
|
||
if (sampleText && sampleText.trim()) {
|
||
sample = JSON.parse(sampleText);
|
||
}
|
||
} catch (e) {
|
||
alert('示例 payload JSON 格式错误: ' + e);
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const res = await fetch('/admin/templates/preview', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ template_content: content, sample_payload: sample })
|
||
});
|
||
const data = await res.json();
|
||
if (res.ok) {
|
||
alert('渲染结果:\\n' + data.rendered);
|
||
} else {
|
||
alert('预览失败: ' + (data.error || '未知错误'));
|
||
}
|
||
} catch (e) {
|
||
alert('请求错误: ' + e);
|
||
}
|
||
}
|
||
</script>
|
||
{% endblock %}
|