feat: 管理后台订单列表展示用户备注,用户信息摊平显示

- 新增 userNotes 字段,创建订单时从 Sub2API 读取用户 notes 保存
- 管理后台订单列表将用户名、邮箱、备注拆分为独立列,节约行高

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
erio
2026-03-03 04:37:39 +08:00
parent f4709b784f
commit 42da18484c
7 changed files with 15 additions and 4 deletions

View File

@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "orders" ADD COLUMN "user_notes" TEXT;

View File

@@ -11,6 +11,7 @@ model Order {
userId Int @map("user_id")
userEmail String? @map("user_email")
userName String? @map("user_name")
userNotes String? @map("user_notes")
amount Decimal @db.Decimal(10, 2)
rechargeCode String @unique @map("recharge_code")
status OrderStatus @default(PENDING)

View File

@@ -12,6 +12,7 @@ interface AdminOrder {
userId: number;
userName: string | null;
userEmail: string | null;
userNotes: string | null;
amount: number;
status: string;
paymentType: string;

View File

@@ -34,6 +34,7 @@ export async function GET(request: NextRequest) {
userId: true,
userName: true,
userEmail: true,
userNotes: true,
amount: true,
status: true,
paymentType: true,

View File

@@ -5,6 +5,7 @@ interface Order {
userId: number;
userName: string | null;
userEmail: string | null;
userNotes: string | null;
amount: number;
status: string;
paymentType: string;
@@ -48,7 +49,9 @@ export default function OrderTable({ orders, onRetry, onCancel, onViewDetail, da
<thead className={dark ? 'bg-slate-800/50' : 'bg-gray-50'}>
<tr>
<th className={thCls}></th>
<th className={thCls}></th>
<th className={thCls}></th>
<th className={thCls}></th>
<th className={thCls}></th>
<th className={thCls}></th>
<th className={thCls}></th>
<th className={thCls}></th>
@@ -71,10 +74,11 @@ export default function OrderTable({ orders, onRetry, onCancel, onViewDetail, da
{order.id.slice(0, 12)}...
</button>
</td>
<td className="whitespace-nowrap px-4 py-3 text-sm">
<div className={dark ? 'text-slate-200' : ''}>{order.userName || '-'}</div>
<div className={`text-xs ${dark ? 'text-slate-500' : 'text-gray-400'}`}>{order.userEmail || `ID: ${order.userId}`}</div>
<td className={`whitespace-nowrap px-4 py-3 text-sm ${dark ? 'text-slate-200' : ''}`}>
{order.userName || `#${order.userId}`}
</td>
<td className={tdMuted}>{order.userEmail || '-'}</td>
<td className={tdMuted}>{order.userNotes || '-'}</td>
<td className={`whitespace-nowrap px-4 py-3 text-sm font-medium ${dark ? 'text-slate-200' : ''}`}>¥{order.amount.toFixed(2)}</td>
<td className="whitespace-nowrap px-4 py-3 text-sm">
<span className={`inline-flex rounded-full px-2 py-1 text-xs font-semibold ${dark ? statusInfo.dark : statusInfo.light}`}>

View File

@@ -102,6 +102,7 @@ export async function createOrder(input: CreateOrderInput): Promise<CreateOrderR
userId: input.userId,
userEmail: user.email,
userName: user.username,
userNotes: user.notes || null,
amount: new Prisma.Decimal(input.amount.toFixed(2)),
rechargeCode: '',
status: 'PENDING',

View File

@@ -4,6 +4,7 @@ export interface Sub2ApiUser {
email: string;
status: string; // "active", "banned", etc.
balance: number;
notes?: string;
}
export interface Sub2ApiRedeemCode {