- 新增全员订单管理页面,仅限管理员访问 - 购买积分页新增显示用户个人充值记录,管理员可见全员记录 - 支付模块增加用户充值历史查看页面及对应 API 接口 - buy.html 模板新增充值记录展示,包括个人和管理员视角的切换标签 - base.html 添加网站图标图像替换原图标字体图标 - 更新支付宝配置 AppID 和应用私钥 - 增加页面脚本支持充值记录标签页切换功能 - 补充日志,记录更多用户登录成功信息
283 lines
17 KiB
HTML
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 %} |