主要更新: - 后台菜单精简(9项→6项) - 新增搜索功能(敏感信息过滤) - 分销绑定和提现系统完善 - 数据库初始化API(自动修复表结构) - 用户管理:显示绑定关系详情 - 小程序:上下章导航优化、匹配页面重构 - 修复hydration和数据类型问题
106 lines
3.3 KiB
TypeScript
106 lines
3.3 KiB
TypeScript
/**
|
||
* 用户绑定关系API
|
||
* 获取指定用户的所有绑定用户列表
|
||
*/
|
||
import { NextResponse } from 'next/server'
|
||
import { query } from '@/lib/db'
|
||
|
||
export async function GET(request: Request) {
|
||
try {
|
||
const { searchParams } = new URL(request.url)
|
||
const userId = searchParams.get('userId')
|
||
const referralCode = searchParams.get('code')
|
||
|
||
if (!userId && !referralCode) {
|
||
return NextResponse.json({
|
||
success: false,
|
||
error: '缺少用户ID或推广码'
|
||
}, { status: 400 })
|
||
}
|
||
|
||
// 如果传入userId,先获取该用户的推广码
|
||
let code = referralCode
|
||
if (userId && !referralCode) {
|
||
const userRows = await query('SELECT referral_code FROM users WHERE id = ?', [userId]) as any[]
|
||
if (userRows.length === 0) {
|
||
return NextResponse.json({
|
||
success: false,
|
||
error: '用户不存在'
|
||
}, { status: 404 })
|
||
}
|
||
code = userRows[0].referral_code
|
||
}
|
||
|
||
if (!code) {
|
||
return NextResponse.json({
|
||
success: true,
|
||
referrals: [],
|
||
stats: {
|
||
total: 0,
|
||
purchased: 0,
|
||
pendingEarnings: 0,
|
||
totalEarnings: 0
|
||
}
|
||
})
|
||
}
|
||
|
||
// 查询通过该推广码绑定的所有用户
|
||
const referrals = await query(`
|
||
SELECT
|
||
id, nickname, avatar, phone, open_id,
|
||
has_full_book, purchased_sections,
|
||
created_at, updated_at
|
||
FROM users
|
||
WHERE referred_by = ?
|
||
ORDER BY created_at DESC
|
||
`, [code]) as any[]
|
||
|
||
// 统计信息
|
||
const purchasedCount = referrals.filter(r => r.has_full_book || (r.purchased_sections && r.purchased_sections !== '[]')).length
|
||
|
||
// 查询该用户的收益信息
|
||
const earningsRows = await query(`
|
||
SELECT earnings, pending_earnings, withdrawn_earnings
|
||
FROM users WHERE ${userId ? 'id = ?' : 'referral_code = ?'}
|
||
`, [userId || code]) as any[]
|
||
|
||
const earnings = earningsRows[0] || { earnings: 0, pending_earnings: 0, withdrawn_earnings: 0 }
|
||
|
||
// 格式化返回数据
|
||
const formattedReferrals = referrals.map(r => ({
|
||
id: r.id,
|
||
nickname: r.nickname || '微信用户',
|
||
avatar: r.avatar,
|
||
phone: r.phone ? r.phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2') : null,
|
||
hasOpenId: !!r.open_id,
|
||
hasPurchased: r.has_full_book || (r.purchased_sections && r.purchased_sections !== '[]'),
|
||
hasFullBook: !!r.has_full_book,
|
||
purchasedSections: typeof r.purchased_sections === 'string'
|
||
? JSON.parse(r.purchased_sections || '[]').length
|
||
: 0,
|
||
createdAt: r.created_at,
|
||
status: r.has_full_book ? 'vip' : (r.purchased_sections && r.purchased_sections !== '[]' ? 'paid' : 'free')
|
||
}))
|
||
|
||
return NextResponse.json({
|
||
success: true,
|
||
referrals: formattedReferrals,
|
||
stats: {
|
||
total: referrals.length,
|
||
purchased: purchasedCount,
|
||
free: referrals.length - purchasedCount,
|
||
earnings: parseFloat(earnings.earnings) || 0,
|
||
pendingEarnings: parseFloat(earnings.pending_earnings) || 0,
|
||
withdrawnEarnings: parseFloat(earnings.withdrawn_earnings) || 0
|
||
}
|
||
})
|
||
|
||
} catch (error) {
|
||
console.error('Get referrals error:', error)
|
||
return NextResponse.json({
|
||
success: false,
|
||
error: '获取绑定关系失败'
|
||
}, { status: 500 })
|
||
}
|
||
}
|