Template
Remove 3x-ui integration from the panel.
Drop API sync, multi-panel registry, and UI/protocol paths; keep DB columns only for compatibility with existing installs. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+7
-99
@@ -17,18 +17,6 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{% if not xui_has_sub_url and xui_configured %}
|
||||
<div class="card" style="margin-bottom:var(--space-lg); border-color: rgba(245, 158, 11, 0.35); background: rgba(245, 158, 11, 0.06);">
|
||||
<div style="display:flex; gap:var(--space-md); align-items:flex-start;">
|
||||
<div style="font-size:1.4rem;">⚠️</div>
|
||||
<div>
|
||||
<div style="font-weight:600; margin-bottom:4px;">{{ _('invite_sub_url_missing_title') }}</div>
|
||||
<div class="form-hint" style="margin:0;">{{ _('invite_sub_url_missing_hint') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div id="invitesEmpty" class="empty-state {% if invites %}hidden{% endif %}">
|
||||
<div class="empty-icon">🔗</div>
|
||||
<div class="empty-title">{{ _('invites_empty') }}</div>
|
||||
@@ -42,12 +30,7 @@
|
||||
<div>
|
||||
<div style="font-weight:700; font-size:1.05rem;">{{ inv.name }}</div>
|
||||
<div style="font-size:0.8rem; color:var(--text-muted); margin-top:2px;">
|
||||
{% if inv.protocol == 'xui' %}
|
||||
3x-ui · {% for s in xui_servers if s.id == inv.xui_panel_id %}{{ s.name }}{% else %}{{ _('xui_server_select_label') }}{% endfor %}
|
||||
· inbound #{{ inv.xui_inbound_id or '—' }}
|
||||
{% else %}
|
||||
{{ inv.protocol }}
|
||||
{% endif %}
|
||||
{{ inv.protocol }}
|
||||
</div>
|
||||
</div>
|
||||
{% if inv.available %}
|
||||
@@ -127,8 +110,7 @@
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">{{ _('protocol_label') }}</label>
|
||||
<select class="form-select" id="inviteProtocol" onchange="updateInviteProtoFields()">
|
||||
<option value="xui">3x-ui VLESS</option>
|
||||
<select class="form-select" id="inviteProtocol">
|
||||
{% for s in servers %}
|
||||
{% set server_idx = loop.index0 %}
|
||||
{% for key, info in (s.protocols or {}).items() %}
|
||||
@@ -140,21 +122,6 @@
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="inviteInboundGroup">
|
||||
<label class="form-label">{{ _('xui_server_select_label') }}</label>
|
||||
<select class="form-select" id="inviteXuiPanel" onchange="loadInviteInbounds()">
|
||||
{% for s in xui_servers %}
|
||||
<option value="{{ s.id }}">{{ s.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<div class="form-hint">{{ _('xui_server_select_hint') }}</div>
|
||||
<label class="form-label" style="margin-top:var(--space-sm);">{{ _('xui_inbound_label') }}</label>
|
||||
<select class="form-select" id="inviteInboundId">
|
||||
<option value="">{{ _('invite_inbound_loading') }}</option>
|
||||
</select>
|
||||
<div class="form-hint">{{ _('invite_inbound_hint') }}</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">{{ _('invite_password_label') }}</label>
|
||||
<input class="form-input" type="password" id="invitePassword" placeholder="{{ _('share_password_hint') }}" autocomplete="new-password">
|
||||
@@ -186,9 +153,6 @@
|
||||
|
||||
<script>
|
||||
const invitesData = {{ invites | tojson }};
|
||||
const xuiConfigured = {{ 'true' if xui_configured else 'false' }};
|
||||
const xuiDefaultInbound = {{ xui_default_inbound | int }};
|
||||
const xuiDefaultPanelId = {{ (xui_default_panel_id or '') | tojson }};
|
||||
|
||||
function inviteUrl(token) {
|
||||
return `${window.location.origin}/invite/${token}`;
|
||||
@@ -199,46 +163,8 @@
|
||||
showToast(_('copied'), 'success');
|
||||
}
|
||||
|
||||
function updateInviteProtoFields() {
|
||||
const v = document.getElementById('inviteProtocol').value;
|
||||
document.getElementById('inviteInboundGroup').style.display = (v === 'xui') ? '' : 'none';
|
||||
if (v === 'xui') loadInviteInbounds(document.getElementById('inviteInboundId').value || xuiDefaultInbound);
|
||||
}
|
||||
|
||||
async function loadInviteInbounds(selected) {
|
||||
const select = document.getElementById('inviteInboundId');
|
||||
select.innerHTML = `<option value="">${_('invite_inbound_loading')}</option>`;
|
||||
if (!xuiConfigured) {
|
||||
select.innerHTML = `<option value="">${_('invite_inbound_need_xui')}</option>`;
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const panelId = document.getElementById('inviteXuiPanel')?.value || xuiDefaultPanelId || '';
|
||||
const q = panelId ? `?panel_id=${encodeURIComponent(panelId)}` : '';
|
||||
const data = await apiCall('/api/settings/xui/inbounds' + q);
|
||||
const list = data.inbounds || [];
|
||||
if (!list.length) {
|
||||
select.innerHTML = `<option value="">${_('invite_inbound_empty')}</option>`;
|
||||
return;
|
||||
}
|
||||
select.innerHTML = '';
|
||||
list.forEach((ib, idx) => {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = ib.id;
|
||||
opt.textContent = `${ib.remark || 'VLESS'} (:${ib.port})`;
|
||||
const prefer = selected || xuiDefaultInbound;
|
||||
if (prefer && String(ib.id) === String(prefer)) opt.selected = true;
|
||||
else if (!prefer && idx === 0) opt.selected = true;
|
||||
select.appendChild(opt);
|
||||
});
|
||||
} catch (e) {
|
||||
select.innerHTML = `<option value="">${_('error')}: ${e.message}</option>`;
|
||||
}
|
||||
}
|
||||
|
||||
function parseProtocolValue() {
|
||||
const raw = document.getElementById('inviteProtocol').value;
|
||||
if (raw === 'xui') return { protocol: 'xui', server_id: 0 };
|
||||
if (raw.includes('|')) {
|
||||
const [protocol, sid] = raw.split('|');
|
||||
return { protocol, server_id: parseInt(sid || '0') };
|
||||
@@ -248,13 +174,9 @@
|
||||
|
||||
function setProtocolSelect(protocol, serverId) {
|
||||
const sel = document.getElementById('inviteProtocol');
|
||||
if (protocol === 'xui') sel.value = 'xui';
|
||||
else {
|
||||
const want = `${protocol}|${serverId || 0}`;
|
||||
if ([...sel.options].some(o => o.value === want)) sel.value = want;
|
||||
else sel.value = 'xui';
|
||||
}
|
||||
updateInviteProtoFields();
|
||||
const want = `${protocol}|${serverId || 0}`;
|
||||
if ([...sel.options].some(o => o.value === want)) sel.value = want;
|
||||
else if (sel.options.length) sel.value = sel.options[0].value;
|
||||
}
|
||||
|
||||
function openCreateInvite() {
|
||||
@@ -268,12 +190,7 @@
|
||||
document.getElementById('inviteNote').value = '';
|
||||
document.getElementById('inviteClearPwdWrap').style.display = 'none';
|
||||
document.getElementById('inviteResetUsedWrap').style.display = 'none';
|
||||
setProtocolSelect('xui', 0);
|
||||
if (xuiDefaultPanelId) {
|
||||
const p = document.getElementById('inviteXuiPanel');
|
||||
if (p && [...p.options].some(o => o.value === xuiDefaultPanelId)) p.value = xuiDefaultPanelId;
|
||||
}
|
||||
loadInviteInbounds(xuiDefaultInbound);
|
||||
setProtocolSelect('awg', 0);
|
||||
openModal('inviteModal');
|
||||
}
|
||||
|
||||
@@ -292,12 +209,7 @@
|
||||
document.getElementById('inviteClearPassword').checked = false;
|
||||
document.getElementById('inviteResetUsedWrap').style.display = 'block';
|
||||
document.getElementById('inviteResetUsed').checked = false;
|
||||
setProtocolSelect(inv.protocol || 'xui', inv.server_id || 0);
|
||||
const panelSel = document.getElementById('inviteXuiPanel');
|
||||
if (panelSel && inv.xui_panel_id && [...panelSel.options].some(o => o.value === inv.xui_panel_id)) {
|
||||
panelSel.value = inv.xui_panel_id;
|
||||
}
|
||||
loadInviteInbounds(inv.xui_inbound_id || xuiDefaultInbound);
|
||||
setProtocolSelect(inv.protocol || 'awg', inv.server_id || 0);
|
||||
openModal('inviteModal');
|
||||
}
|
||||
|
||||
@@ -309,8 +221,6 @@
|
||||
try {
|
||||
const editId = document.getElementById('inviteEditId').value;
|
||||
const proto = parseProtocolValue();
|
||||
const inbound = parseInt(document.getElementById('inviteInboundId').value || '0');
|
||||
if (proto.protocol === 'xui' && !inbound) throw new Error(_('invite_inbound_required'));
|
||||
|
||||
const body = {
|
||||
name: document.getElementById('inviteName').value || 'Invite',
|
||||
@@ -319,8 +229,6 @@
|
||||
user_id: document.getElementById('inviteUserId').value || '',
|
||||
protocol: proto.protocol,
|
||||
server_id: proto.server_id,
|
||||
xui_inbound_id: inbound,
|
||||
xui_panel_id: document.getElementById('inviteXuiPanel')?.value || '',
|
||||
note: document.getElementById('inviteNote').value || '',
|
||||
};
|
||||
const pwd = document.getElementById('invitePassword').value;
|
||||
|
||||
Reference in New Issue
Block a user