ai_v/templates/buy.html
24024 72bacacf4f feat(auth): 增加管理员订单管理和个人充值记录功能
- 新增全员订单管理页面,仅限管理员访问
- 购买积分页新增显示用户个人充值记录,管理员可见全员记录
- 支付模块增加用户充值历史查看页面及对应 API 接口
- buy.html 模板新增充值记录展示,包括个人和管理员视角的切换标签
- base.html 添加网站图标图像替换原图标字体图标
- 更新支付宝配置 AppID 和应用私钥
- 增加页面脚本支持充值记录标签页切换功能
- 补充日志,记录更多用户登录成功信息
2026-01-14 20:18:35 +08:00

283 lines
17 KiB
HTML

{% extends "base.html" %}
{% block title %}购买积分 - AI 视界{% endblock %}
{% block content %}
<div class="w-full h-full overflow-y-auto p-8 lg:p-12 custom-scrollbar">
<div class="max-w-4xl mx-auto space-y-12">
<div class="flex items-center gap-4">
<div class="w-12 h-12 bg-amber-500 text-white rounded-2xl flex items-center justify-center shadow-lg shadow-amber-200">
<i data-lucide="shopping-cart" class="w-7 h-7"></i>
</div>
<div>
<h1 class="text-3xl font-black text-slate-900 tracking-tight">充值积分</h1>
<p class="text-slate-400 text-sm">选择适合您的积分套餐,开启无限创作空间</p>
</div>
</div>
{% if success %}
<div class="bg-emerald-50 border border-emerald-100 rounded-3xl p-6 flex items-center gap-4 animate-in fade-in slide-in-from-top-4 duration-500">
<div class="w-12 h-12 bg-emerald-500 text-white rounded-2xl flex items-center justify-center shadow-lg shadow-emerald-100">
<i data-lucide="check" class="w-7 h-7"></i>
</div>
<div>
<h3 class="text-emerald-900 font-black">支付成功!</h3>
<p class="text-emerald-600 text-xs font-bold">您的订单 #{{ order.out_trade_no if order else '' }} 已完成,积分已到账。</p>
</div>
</div>
{% endif %}
<div class="relative group">
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 gap-6">
<!-- 套餐 1 -->
<div class="bg-white rounded-[2.5rem] border border-slate-100 p-8 shadow-xl group">
<div class="text-[10px] font-black text-slate-400 uppercase tracking-widest mb-4">体验测试</div>
<div class="flex items-baseline gap-1 mb-6">
<span class="text-4xl font-black text-slate-900">50</span>
<span class="text-sm text-slate-400 font-bold">积分</span>
</div>
<div class="space-y-4 mb-8">
<div class="flex items-center gap-2 text-xs font-bold text-slate-600">
<i data-lucide="check-circle-2" class="w-4 h-4 text-emerald-500"></i>
<span>快速开启 AI 体验</span>
</div>
</div>
<form action="/payment/create" method="POST">
<input type="hidden" name="package_id" value="50">
<button type="submit" class="w-full py-4 rounded-2xl bg-slate-900 text-white font-black text-sm">
¥ 5.00 购买
</button>
</form>
</div>
<!-- 套餐 2 -->
<div class="bg-white rounded-[2.5rem] border border-slate-100 p-8 shadow-xl relative">
<div class="absolute -top-3 right-6 bg-indigo-600 text-white text-[8px] font-black px-3 py-1 rounded-full shadow-lg uppercase">推荐</div>
<div class="text-[10px] font-black text-slate-400 uppercase tracking-widest mb-4">普通创作</div>
<div class="flex items-baseline gap-1 mb-6">
<span class="text-4xl font-black text-slate-900">200</span>
<span class="text-sm text-slate-400 font-bold">积分</span>
</div>
<div class="space-y-4 mb-8">
<div class="flex items-center gap-2 text-xs font-bold text-slate-600">
<i data-lucide="check-circle-2" class="w-4 h-4 text-emerald-500"></i>
<span>满足日常生成需求</span>
</div>
</div>
<form action="/payment/create" method="POST">
<input type="hidden" name="package_id" value="200">
<button type="submit" class="w-full py-4 rounded-2xl bg-indigo-600 text-white font-black text-sm">
¥ 20.00 购买
</button>
</form>
</div>
<!-- 套餐 3 -->
<div class="bg-indigo-900 rounded-[2.5rem] border border-indigo-800 p-8 shadow-2xl">
<div class="text-[10px] font-black text-indigo-300 uppercase tracking-widest mb-4">量大管饱</div>
<div class="flex items-baseline gap-1 mb-6">
<span class="text-4xl font-black text-white">1000</span>
<span class="text-sm text-indigo-300 font-bold">积分</span>
</div>
<div class="space-y-4 mb-8">
<div class="flex items-center gap-2 text-xs font-bold text-indigo-100">
<i data-lucide="check-circle-2" class="w-4 h-4 text-amber-400"></i>
<span>创作自由,无需等待</span>
</div>
</div>
<form action="/payment/create" method="POST">
<input type="hidden" name="package_id" value="1000">
<button type="submit" class="w-full py-4 rounded-2xl bg-white text-indigo-900 font-black text-sm">
¥ 100.00 购买
</button>
</form>
</div>
<!-- 套餐 4 -->
<div class="bg-amber-500 rounded-[2.5rem] border border-amber-400 p-8 shadow-2xl">
<div class="text-[10px] font-black text-amber-900 uppercase tracking-widest mb-4">豪掷千金</div>
<div class="flex items-baseline gap-1 mb-6">
<span class="text-4xl font-black text-slate-900">5000</span>
<span class="text-sm text-amber-900 font-bold">积分</span>
</div>
<div class="space-y-4 mb-8">
<div class="flex items-center gap-2 text-xs font-bold text-amber-900">
<i data-lucide="check-circle-2" class="w-4 h-4 text-white"></i>
<span>至尊权限,顶级服务</span>
</div>
</div>
<form action="/payment/create" method="POST">
<input type="hidden" name="package_id" value="5000">
<button type="submit" class="w-full py-4 rounded-2xl bg-slate-900 text-white font-black text-sm">
¥ 500.00 购买
</button>
</form>
</div>
</div>
</div>
<!-- 支付提示 -->
<div class="bg-slate-100/50 rounded-3xl p-6 text-center">
<p class="text-[10px] font-bold text-slate-400 uppercase tracking-widest">
<i data-lucide="shield-check" class="w-3 h-3 inline-block mr-1"></i>
支付安全保障 · 充值实时到账
</p>
</div>
<!-- 充值记录区域 -->
<div class="space-y-8 pt-8 border-t border-slate-200">
<!-- 标签页切换 -->
<div class="flex items-center gap-4 bg-slate-100 p-1.5 rounded-2xl w-fit">
<button onclick="switchTab('personal')" id="tabBtn-personal" class="px-6 py-2.5 rounded-xl text-sm font-black transition-all bg-white text-slate-900 shadow-sm">
我的充值
</button>
{% if is_admin %}
<button onclick="switchTab('admin')" id="tabBtn-admin" class="px-6 py-2.5 rounded-xl text-sm font-black transition-all text-slate-500 hover:text-slate-700">
全员记录 (管理员)
</button>
{% endif %}
</div>
<!-- 我的充值列表 -->
<div id="tab-personal" class="bg-white/70 backdrop-blur-xl rounded-[2.5rem] border border-slate-200/50 shadow-2xl overflow-hidden animate-in fade-in duration-500">
<div class="overflow-x-auto">
<table class="w-full text-left border-collapse">
<thead>
<tr class="border-b border-slate-100 bg-slate-50/50">
<th class="px-8 py-5 text-[10px] font-black text-slate-400 uppercase tracking-widest">订单号</th>
<th class="px-8 py-5 text-[10px] font-black text-slate-400 uppercase tracking-widest">积分/金额</th>
<th class="px-8 py-5 text-[10px] font-black text-slate-400 uppercase tracking-widest">状态</th>
<th class="px-8 py-5 text-[10px] font-black text-slate-400 uppercase tracking-widest">支付时间</th>
</tr>
</thead>
<tbody class="divide-y divide-slate-100">
{% if personal_orders %}
{% for order in personal_orders %}
<tr class="hover:bg-slate-50/50 transition-colors">
<td class="px-8 py-5">
<div class="flex flex-col">
<span class="text-xs font-bold text-slate-700">{{ order.out_trade_no }}</span>
<span class="text-[10px] text-slate-400 font-mono">Ali: {{ order.trade_no or '-' }}</span>
</div>
</td>
<td class="px-8 py-5">
<div class="flex flex-col">
<div class="flex items-center gap-1">
<i data-lucide="zap" class="w-3 h-3 text-amber-500"></i>
<span class="text-sm font-black text-slate-900">+{{ order.points }}</span>
</div>
<span class="text-[10px] font-bold text-slate-400">¥{{ order.amount }}</span>
</div>
</td>
<td class="px-8 py-5">
{% if order.status == 'PAID' %}
<span class="px-2 py-1 bg-emerald-50 text-emerald-600 text-[10px] font-black rounded-lg border border-emerald-100">已完成</span>
{% elif order.status == 'PENDING' %}
<span class="px-2 py-1 bg-amber-50 text-amber-600 text-[10px] font-black rounded-lg border border-amber-100">待支付</span>
{% else %}
<span class="px-2 py-1 bg-slate-50 text-slate-400 text-[10px] font-black rounded-lg border border-slate-100">已取消</span>
{% endif %}
</td>
<td class="px-8 py-5">
<span class="text-[10px] font-bold text-slate-400">{{ order.paid_at.strftime('%m-%d %H:%M') if order.paid_at else '-' }}</span>
</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td colspan="4" class="px-8 py-16 text-center">
<p class="text-slate-300 font-bold text-sm">暂无记录</p>
</td>
</tr>
{% endif %}
</tbody>
</table>
</div>
<div class="p-6 bg-slate-50/50 border-t border-slate-100 text-center">
<a href="/payment/history" class="text-[10px] font-black text-indigo-600 hover:text-indigo-700 uppercase tracking-widest flex items-center justify-center gap-1">
查看更多记录 <i data-lucide="chevron-right" class="w-3 h-3"></i>
</a>
</div>
</div>
{% if is_admin %}
<!-- 管理员全员记录列表 -->
<div id="tab-admin" class="hidden bg-white/70 backdrop-blur-xl rounded-[2.5rem] border border-slate-200/50 shadow-2xl overflow-hidden animate-in fade-in duration-500">
<div class="overflow-x-auto">
<table class="w-full text-left border-collapse">
<thead>
<tr class="border-b border-slate-100 bg-slate-50/50">
<th class="px-8 py-5 text-[10px] font-black text-slate-400 uppercase tracking-widest">用户信息</th>
<th class="px-8 py-5 text-[10px] font-black text-slate-400 uppercase tracking-widest">订单号</th>
<th class="px-8 py-5 text-[10px] font-black text-slate-400 uppercase tracking-widest">积分/金额</th>
<th class="px-8 py-5 text-[10px] font-black text-slate-400 uppercase tracking-widest">状态</th>
</tr>
</thead>
<tbody class="divide-y divide-slate-100">
{% if admin_orders %}
{% for order in admin_orders %}
<tr class="hover:bg-slate-50/50 transition-colors">
<td class="px-8 py-5">
<div class="flex flex-col">
<span class="text-xs font-bold text-slate-700">{{ order.user.phone if order.user else '未知' }}</span>
<span class="text-[10px] text-slate-400">UID: {{ order.user_id }}</span>
</div>
</td>
<td class="px-8 py-5">
<div class="flex flex-col">
<span class="text-[10px] font-bold text-slate-500">{{ order.out_trade_no }}</span>
</div>
</td>
<td class="px-8 py-5">
<div class="flex flex-col">
<span class="text-xs font-black text-slate-900">+{{ order.points }}</span>
<span class="text-[10px] font-bold text-slate-400">¥{{ order.amount }}</span>
</div>
</td>
<td class="px-8 py-5">
{% if order.status == 'PAID' %}
<span class="px-2 py-1 bg-emerald-50 text-emerald-600 text-[10px] font-black rounded-lg border border-emerald-100">已完成</span>
{% else %}
<span class="px-2 py-1 bg-slate-50 text-slate-400 text-[10px] font-black rounded-lg border border-slate-100">{{ order.status }}</span>
{% endif %}
</td>
</tr>
{% endfor %}
{% endif %}
</tbody>
</table>
</div>
<div class="p-6 bg-slate-50/50 border-t border-slate-100 text-center">
<a href="/admin/orders" class="text-[10px] font-black text-indigo-600 hover:text-indigo-700 uppercase tracking-widest flex items-center justify-center gap-1">
进入后台管理全员订单 <i data-lucide="chevron-right" class="w-3 h-3"></i>
</a>
</div>
</div>
{% endif %}
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
function switchTab(tab) {
// 切换内容显隐
document.getElementById('tab-personal').classList.toggle('hidden', tab !== 'personal');
const adminTab = document.getElementById('tab-admin');
if(adminTab) adminTab.classList.toggle('hidden', tab !== 'admin');
// 切换按钮样式
const personalBtn = document.getElementById('tabBtn-personal');
const adminBtn = document.getElementById('tabBtn-admin');
if(tab === 'personal') {
personalBtn.className = "px-6 py-2.5 rounded-xl text-sm font-black transition-all bg-white text-slate-900 shadow-sm";
if(adminBtn) adminBtn.className = "px-6 py-2.5 rounded-xl text-sm font-black transition-all text-slate-500 hover:text-slate-700";
} else {
personalBtn.className = "px-6 py-2.5 rounded-xl text-sm font-black transition-all text-slate-500 hover:text-slate-700";
if(adminBtn) adminBtn.className = "px-6 py-2.5 rounded-xl text-sm font-black transition-all bg-white text-slate-900 shadow-sm";
}
lucide.createIcons();
}
</script>
{% endblock %}