Files
RustProxyAdmin/templates/admin/forwards.html
T
2026-09-30 16:11:51 +08:00

74 lines
4.2 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 "base.html" %}
{% block title %}端口转发 - RustProxyAdmin{% endblock %}
{% block page_title %}端口转发{% endblock %}
{% block page_desc %}管理端口转发条目(TCP/UDP){% endblock %}
{% block content %}
<div class="toolbar">
<input id="f-q" placeholder="搜索名称 / IP / 备注" style="width:220px">
<span id="common-filters"></span>
<button class="btn" onclick="__entryPage.page=1;__entryPage.reload()">筛选</button>
<button class="btn btn-primary" onclick="__entryPage.openForm()">新建转发</button>
</div>
<table class="tbl"><thead><tr id="thead"></tr></thead><tbody id="tbody"></tbody></table>
<div id="pager"></div>
<div class="batchbar" id="batchbar" style="display:none"></div>
<script src="/static/js/entries.js"></script>
<script>
(async () => {
await loadGT();
document.getElementById('common-filters').innerHTML = commonFiltersHtml();
document.getElementById('batchbar').innerHTML = batchBarHtml();
const L = initEntryPage({
runtimeBadge: true,
api: '/api/forward', etype: 'forward',
columns: [
{ label: '名称', cell: r => `<b>${esc(r.name)}</b>${r.remark ? `<div class="muted">${esc(r.remark)}</div>` : ''}` },
{ label: '节点', cell: r => esc(r.node_name || r.node_id) },
{ label: '协议', cell: r => `<span class="badge">${esc(r.proto)}</span>` },
{ label: '监听', cell: r => `<span class="mono">${esc(r.listen_ip)}:${r.listen_port}</span>` },
{ label: '目标', cell: r => `<span class="mono">${esc(r.target_ip)}:${r.target_port}</span>` },
{ label: '分组', cell: r => groupChip(r.group) },
{ label: '标签', cell: r => tagChips(r.tags) },
{ label: '配额', cell: quotaCell },
{ label: '到期', cell: expireCell },
{ label: '状态', cell: r => badgeFor(r.enabled, r.disabled_reason) },
{ label: '运行', cell: r => `<span data-rt="forward:${r.id}">-</span>` },
],
formHtml(item, isNew) {
const v = k => item ? (item[k] ?? '') : '';
return `
<div class="form-grid">
<div class="form-row"><label>名称 *</label><input id="fm-name" value="${esc(v('name'))}"></div>
<div class="form-row"><label>节点 *</label>${nodeSelectHtml('fm-node', item ? item.node_id : 1)}</div>
<div class="form-row"><label>协议 *</label><select id="fm-proto">${['tcp','udp','tcp+udp'].map(p => `<option ${v('proto') === p ? 'selected' : ''}>${p}</option>`).join('')}</select></div>
<div class="form-row"><label>分组</label>${groupSelectHtml('fm-group', item ? item.group_id : null)}</div>
<div class="form-row"><label>监听 IP</label><input id="fm-lip" value="${esc(item ? v('listen_ip') : '0.0.0.0')}"></div>
<div class="form-row"><label>监听端口 *</label><input id="fm-lport" type="number" min="1" max="65535" value="${esc(v('listen_port')) || '8080'}"></div>
<div class="form-row"><label>目标 IP *</label><input id="fm-tip" value="${esc(v('target_ip'))}"></div>
<div class="form-row"><label>目标端口 *</label><input id="fm-tport" type="number" min="1" max="65535" value="${esc(v('target_port')) || '80'}"></div>
<div class="form-row"><label>有效期</label>${expirePresetHtml(isNew ? 'permanent' : null)}</div>
<div class="form-row"><label>备注</label><input id="fm-remark" value="${esc(v('remark'))}"></div>
</div>
<div class="form-row"><label>标签</label><div>${tagCheckHtml(item ? item.tags.map(t => t.id) : [])}</div></div>`;
},
formData() {
const val = id => document.getElementById(id).value.trim();
return {
name: val('fm-name'), node_id: +document.getElementById('fm-node').value,
proto: document.getElementById('fm-proto').value,
listen_ip: val('fm-lip') || '0.0.0.0',
listen_port: +document.getElementById('fm-lport').value,
target_ip: val('fm-tip'),
target_port: +document.getElementById('fm-tport').value,
remark: val('fm-remark') || null,
group_id: document.getElementById('fm-group').value ? +document.getElementById('fm-group').value : null,
expire_preset: document.getElementById('fm-preset').value,
tag_ids: readTagIds(),
};
},
});
L.reload().catch(e => toast(e.message, true));
})();
</script>
{% endblock %}