Files
mailova/app/templates/admin_invites.html

115 lines
5.8 KiB
HTML

{% extends "base.html" %}
{% block title %}邀请码管理 - 星笺{% endblock %}
{% block content %}
<div class="section-header">
<h1>邀请码管理</h1>
</div>
{% if success %}
<div class="alert alert-success">{{ success }}</div>
{% endif %}
{% if error %}
<div class="alert alert-error">{{ error }}</div>
{% endif %}
<!-- Add new code -->
<div class="form-card" style="margin-bottom:1.5rem">
<h3 style="margin-bottom:.75rem">创建邀请码</h3>
<form method="post" action="/admin/invites/add" style="display:flex;flex-direction:column;gap:.85rem">
<div>
<label style="margin-top:0">邀请码(留空自动生成)</label>
<input type="text" name="code" maxlength="8" placeholder="自动生成" style="text-transform:uppercase">
</div>
<div>
<label style="margin-top:0">限制类型</label>
<select name="limit_type" id="limit_type" onchange="toggleLimitFields()">
<option value="unlimited">无限制</option>
<option value="uses">使用次数</option>
<option value="expires">有效期</option>
</select>
</div>
<div id="max_uses_field" style="display:none;align-items:center;gap:.3rem">
<label style="margin:0;font-size:.8rem;white-space:nowrap">次数</label>
<input type="number" name="max_uses" min="1" value="1" class="aif-input aif-short">
</div>
<div id="expires_field" style="display:none;align-items:center;gap:.3rem">
<label style="margin:0;font-size:.8rem;white-space:nowrap">有效期</label>
<input type="datetime-local" name="expires_at" class="aif-input aif-date">
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">创建</button>
</div>
</form>
</div>
<!-- Invite code list -->
{% if codes %}
<div class="postcard-list">
{% for c in codes %}
<div class="postcard-row" style="flex-direction:column;align-items:stretch;gap:.75rem">
<div style="display:flex;align-items:center;gap:1rem;flex-wrap:wrap">
<strong style="font-family:monospace;font-size:1.1rem">{{ c.code }}</strong>
<span style="font-size:.8rem;color:var(--text-muted)">创建者: {{ c.creator.username if c.creator else '-' }}</span>
<span style="font-size:.8rem;color:var(--text-muted)">{{ c.created_at|to_local|strftime('%Y-%m-%d %H:%M') }}</span>
{% if c.max_uses is not none %}
<span class="badge">已用 {{ c.use_count }} / {{ c.max_uses }}</span>
{% else %}
<span class="badge">已用 {{ c.use_count }} / ∞</span>
{% endif %}
{% if c.expires_at %}
<span class="badge">过期: {{ c.expires_at|to_local|strftime('%Y-%m-%d %H:%M') }}</span>
{% else %}
<span class="badge">永不过期</span>
{% endif %}
{% if c.registered_users %}
<span class="badge" style="background:#e8f5e9">注册用户: {{ c.registered_users|map(attribute='username')|join(', ') }}</span>
{% endif %}
</div>
<form method="post" action="/admin/invites/{{ c.id }}/edit" class="admin-invite-form" id="edit-form-{{ c.id }}">
<div class="aif-field">
<select name="limit_type" class="aif-select" onchange="toggleEditFields({{ c.id }}, this.value)">
<option value="unlimited"{% if c.max_uses is none and not c.expires_at %} selected{% endif %}>无限制</option>
<option value="uses"{% if c.max_uses is not none %} selected{% endif %}>次数限制</option>
<option value="expires"{% if c.expires_at %} selected{% endif %}>有效期</option>
</select>
</div>
<div style="display:{% if c.max_uses is not none %}inline-flex{% else %}none{% endif %};align-items:center;gap:.3rem;align-self:flex-end">
<label style="margin:0;font-size:.8rem;white-space:nowrap">次数</label>
<input type="number" name="max_uses" value="{{ c.max_uses or 1 }}" min="1" class="aif-input aif-short">
</div>
<div style="display:{% if c.expires_at %}inline-flex{% else %}none{% endif %};align-items:center;gap:.3rem;align-self:flex-end">
<label style="margin:0;font-size:.8rem;white-space:nowrap">有效期</label>
<input type="datetime-local" name="expires_at" value="{{ c.expires_at|to_local|strftime('%Y-%m-%dT%H:%M') if c.expires_at else '' }}" class="aif-input aif-date">
</div>
<div style="display:flex;gap:.4rem;align-self:flex-end">
<button type="submit" class="btn btn-sm">保存</button>
<button type="button" class="btn btn-danger btn-sm" onclick="if(confirm('确定删除?'))this.closest('form').nextElementSibling.submit()">删除</button>
</div>
</form>
<form method="post" action="/admin/invites/{{ c.id }}/delete" style="display:none"></form>
</div>
{% endfor %}
</div>
{% else %}
<div class="empty-state">
<div class="empty-icon">🔑</div>
<p>暂无邀请码</p>
</div>
{% endif %}
<script>
function toggleLimitFields() {
var t = document.getElementById('limit_type').value;
document.getElementById('max_uses_field').style.display = t === 'uses' ? 'inline-flex' : 'none';
document.getElementById('expires_field').style.display = t === 'expires' ? 'inline-flex' : 'none';
}
function toggleEditFields(id, val) {
var form = document.getElementById('edit-form-' + id);
var num = form.querySelector('[name="max_uses"]').parentElement;
var date = form.querySelector('[name="expires_at"]').parentElement;
num.style.display = val === 'uses' ? 'inline-flex' : 'none';
date.style.display = val === 'expires' ? 'inline-flex' : 'none';
}
</script>
{% endblock %}