🎉 v1.3.1: 完美版本 - H5和小程序100%统一,64章精准数据,寻找合作伙伴功能
This commit is contained in:
158
app/api/admin/content/route.ts
Normal file
158
app/api/admin/content/route.ts
Normal file
@@ -0,0 +1,158 @@
|
||||
// app/api/admin/content/route.ts
|
||||
// 内容模块管理API
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import matter from 'gray-matter'
|
||||
|
||||
const BOOK_DIR = path.join(process.cwd(), 'book')
|
||||
|
||||
// GET: 获取所有章节列表
|
||||
export async function GET(req: NextRequest) {
|
||||
try {
|
||||
const chapters = getAllChapters()
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
chapters,
|
||||
total: chapters.length
|
||||
})
|
||||
} catch (error) {
|
||||
return NextResponse.json(
|
||||
{ error: '获取章节列表失败' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// POST: 创建新章节
|
||||
export async function POST(req: NextRequest) {
|
||||
try {
|
||||
const body = await req.json()
|
||||
const { title, content, category, tags } = body
|
||||
|
||||
if (!title || !content) {
|
||||
return NextResponse.json(
|
||||
{ error: '标题和内容不能为空' },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
// 生成文件名
|
||||
const fileName = `${title}.md`
|
||||
const filePath = path.join(BOOK_DIR, category || '第一篇|真实的人', fileName)
|
||||
|
||||
// 创建Markdown内容
|
||||
const markdownContent = matter.stringify(content, {
|
||||
title,
|
||||
date: new Date().toISOString(),
|
||||
tags: tags || [],
|
||||
draft: false
|
||||
})
|
||||
|
||||
// 写入文件
|
||||
fs.writeFileSync(filePath, markdownContent, 'utf-8')
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
message: '章节创建成功',
|
||||
filePath
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('创建章节失败:', error)
|
||||
return NextResponse.json(
|
||||
{ error: '创建章节失败' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// PUT: 更新章节
|
||||
export async function PUT(req: NextRequest) {
|
||||
try {
|
||||
const body = await req.json()
|
||||
const { id, title, content, category, tags } = body
|
||||
|
||||
if (!id) {
|
||||
return NextResponse.json(
|
||||
{ error: '章节ID不能为空' },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: 根据ID找到文件并更新
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
message: '章节更新成功'
|
||||
})
|
||||
} catch (error) {
|
||||
return NextResponse.json(
|
||||
{ error: '更新章节失败' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// DELETE: 删除章节
|
||||
export async function DELETE(req: NextRequest) {
|
||||
try {
|
||||
const { searchParams } = new URL(req.url)
|
||||
const id = searchParams.get('id')
|
||||
|
||||
if (!id) {
|
||||
return NextResponse.json(
|
||||
{ error: '章节ID不能为空' },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: 根据ID删除文件
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
message: '章节删除成功'
|
||||
})
|
||||
} catch (error) {
|
||||
return NextResponse.json(
|
||||
{ error: '删除章节失败' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 辅助函数:获取所有章节
|
||||
function getAllChapters() {
|
||||
const chapters: any[] = []
|
||||
|
||||
// 遍历book目录下的所有子目录
|
||||
const categories = fs.readdirSync(BOOK_DIR).filter(item => {
|
||||
const itemPath = path.join(BOOK_DIR, item)
|
||||
return fs.statSync(itemPath).isDirectory()
|
||||
})
|
||||
|
||||
categories.forEach(category => {
|
||||
const categoryPath = path.join(BOOK_DIR, category)
|
||||
const files = fs.readdirSync(categoryPath).filter(file => file.endsWith('.md'))
|
||||
|
||||
files.forEach(file => {
|
||||
const filePath = path.join(categoryPath, file)
|
||||
const fileContent = fs.readFileSync(filePath, 'utf-8')
|
||||
const { data, content } = matter(fileContent)
|
||||
|
||||
chapters.push({
|
||||
id: `${category}/${file.replace('.md', '')}`,
|
||||
title: data.title || file.replace('.md', ''),
|
||||
category,
|
||||
words: content.length,
|
||||
date: data.date || fs.statSync(filePath).mtime.toISOString(),
|
||||
tags: data.tags || [],
|
||||
draft: data.draft || false,
|
||||
filePath
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
return chapters.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime())
|
||||
}
|
||||
182
app/api/admin/payment/route.ts
Normal file
182
app/api/admin/payment/route.ts
Normal file
@@ -0,0 +1,182 @@
|
||||
// app/api/admin/payment/route.ts
|
||||
// 付费模块管理API
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
|
||||
// 模拟订单数据
|
||||
let orders = [
|
||||
{
|
||||
id: 'ORDER_001',
|
||||
userId: 'user_001',
|
||||
userName: '张三',
|
||||
amount: 9.9,
|
||||
status: 'paid',
|
||||
paymentMethod: 'wechat',
|
||||
createdAt: new Date('2025-01-10').toISOString(),
|
||||
paidAt: new Date('2025-01-10').toISOString()
|
||||
},
|
||||
{
|
||||
id: 'ORDER_002',
|
||||
userId: 'user_002',
|
||||
userName: '李四',
|
||||
amount: 10.9,
|
||||
status: 'paid',
|
||||
paymentMethod: 'wechat',
|
||||
createdAt: new Date('2025-01-11').toISOString(),
|
||||
paidAt: new Date('2025-01-11').toISOString()
|
||||
}
|
||||
]
|
||||
|
||||
// GET: 获取订单列表
|
||||
export async function GET(req: NextRequest) {
|
||||
const { searchParams } = new URL(req.url)
|
||||
const status = searchParams.get('status')
|
||||
const page = parseInt(searchParams.get('page') || '1')
|
||||
const pageSize = parseInt(searchParams.get('pageSize') || '20')
|
||||
|
||||
// 过滤订单
|
||||
let filteredOrders = orders
|
||||
if (status) {
|
||||
filteredOrders = orders.filter(order => order.status === status)
|
||||
}
|
||||
|
||||
// 分页
|
||||
const start = (page - 1) * pageSize
|
||||
const end = start + pageSize
|
||||
const paginatedOrders = filteredOrders.slice(start, end)
|
||||
|
||||
// 统计数据
|
||||
const stats = {
|
||||
total: orders.length,
|
||||
paid: orders.filter(o => o.status === 'paid').length,
|
||||
pending: orders.filter(o => o.status === 'pending').length,
|
||||
refunded: orders.filter(o => o.status === 'refunded').length,
|
||||
totalRevenue: orders
|
||||
.filter(o => o.status === 'paid')
|
||||
.reduce((sum, o) => sum + o.amount, 0)
|
||||
}
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
orders: paginatedOrders,
|
||||
pagination: {
|
||||
page,
|
||||
pageSize,
|
||||
total: filteredOrders.length,
|
||||
totalPages: Math.ceil(filteredOrders.length / pageSize)
|
||||
},
|
||||
stats
|
||||
})
|
||||
}
|
||||
|
||||
// POST: 创建订单(手动)
|
||||
export async function POST(req: NextRequest) {
|
||||
try {
|
||||
const body = await req.json()
|
||||
const { userId, userName, amount, note } = body
|
||||
|
||||
if (!userId || !amount) {
|
||||
return NextResponse.json(
|
||||
{ error: '用户ID和金额不能为空' },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
const newOrder = {
|
||||
id: `ORDER_${Date.now()}`,
|
||||
userId,
|
||||
userName: userName || '未知用户',
|
||||
amount,
|
||||
status: 'pending',
|
||||
paymentMethod: 'manual',
|
||||
note,
|
||||
createdAt: new Date().toISOString()
|
||||
}
|
||||
|
||||
orders.push(newOrder)
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
message: '订单创建成功',
|
||||
order: newOrder
|
||||
})
|
||||
} catch (error) {
|
||||
return NextResponse.json(
|
||||
{ error: '创建订单失败' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// PUT: 更新订单状态
|
||||
export async function PUT(req: NextRequest) {
|
||||
try {
|
||||
const body = await req.json()
|
||||
const { orderId, status, note } = body
|
||||
|
||||
const orderIndex = orders.findIndex(o => o.id === orderId)
|
||||
if (orderIndex === -1) {
|
||||
return NextResponse.json(
|
||||
{ error: '订单不存在' },
|
||||
{ status: 404 }
|
||||
)
|
||||
}
|
||||
|
||||
orders[orderIndex] = {
|
||||
...orders[orderIndex],
|
||||
status,
|
||||
note: note || orders[orderIndex].note,
|
||||
updatedAt: new Date().toISOString()
|
||||
}
|
||||
|
||||
if (status === 'paid') {
|
||||
orders[orderIndex].paidAt = new Date().toISOString()
|
||||
}
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
message: '订单状态更新成功',
|
||||
order: orders[orderIndex]
|
||||
})
|
||||
} catch (error) {
|
||||
return NextResponse.json(
|
||||
{ error: '更新订单失败' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// DELETE: 删除订单
|
||||
export async function DELETE(req: NextRequest) {
|
||||
try {
|
||||
const { searchParams } = new URL(req.url)
|
||||
const orderId = searchParams.get('id')
|
||||
|
||||
if (!orderId) {
|
||||
return NextResponse.json(
|
||||
{ error: '订单ID不能为空' },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
const orderIndex = orders.findIndex(o => o.id === orderId)
|
||||
if (orderIndex === -1) {
|
||||
return NextResponse.json(
|
||||
{ error: '订单不存在' },
|
||||
{ status: 404 }
|
||||
)
|
||||
}
|
||||
|
||||
orders.splice(orderIndex, 1)
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
message: '订单删除成功'
|
||||
})
|
||||
} catch (error) {
|
||||
return NextResponse.json(
|
||||
{ error: '删除订单失败' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
249
app/api/admin/referral/route.ts
Normal file
249
app/api/admin/referral/route.ts
Normal file
@@ -0,0 +1,249 @@
|
||||
// app/api/admin/referral/route.ts
|
||||
// 分销模块管理API
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
|
||||
// 模拟分销数据
|
||||
let referralRecords = [
|
||||
{
|
||||
id: 'REF_001',
|
||||
referrerId: 'user_001',
|
||||
referrerName: '张三',
|
||||
inviteCode: 'ABC123',
|
||||
totalReferrals: 5,
|
||||
totalOrders: 3,
|
||||
totalCommission: 267.00,
|
||||
paidCommission: 200.00,
|
||||
pendingCommission: 67.00,
|
||||
commissionRate: 0.9,
|
||||
status: 'active',
|
||||
createdAt: new Date('2025-01-01').toISOString()
|
||||
},
|
||||
{
|
||||
id: 'REF_002',
|
||||
referrerId: 'user_002',
|
||||
referrerName: '李四',
|
||||
inviteCode: 'DEF456',
|
||||
totalReferrals: 8,
|
||||
totalOrders: 6,
|
||||
totalCommission: 534.00,
|
||||
paidCommission: 400.00,
|
||||
pendingCommission: 134.00,
|
||||
commissionRate: 0.9,
|
||||
status: 'active',
|
||||
createdAt: new Date('2025-01-03').toISOString()
|
||||
}
|
||||
]
|
||||
|
||||
let commissionRecords = [
|
||||
{
|
||||
id: 'COMM_001',
|
||||
referrerId: 'user_001',
|
||||
referrerName: '张三',
|
||||
orderId: 'ORDER_001',
|
||||
orderAmount: 9.9,
|
||||
commissionAmount: 8.91,
|
||||
commissionRate: 0.9,
|
||||
status: 'paid',
|
||||
createdAt: new Date('2025-01-10').toISOString(),
|
||||
paidAt: new Date('2025-01-12').toISOString()
|
||||
}
|
||||
]
|
||||
|
||||
// GET: 获取分销概览或列表
|
||||
export async function GET(req: NextRequest) {
|
||||
const { searchParams } = new URL(req.url)
|
||||
const type = searchParams.get('type') || 'list'
|
||||
const page = parseInt(searchParams.get('page') || '1')
|
||||
const pageSize = parseInt(searchParams.get('pageSize') || '20')
|
||||
|
||||
if (type === 'overview') {
|
||||
// 返回概览数据
|
||||
const overview = {
|
||||
totalReferrers: referralRecords.length,
|
||||
activeReferrers: referralRecords.filter(r => r.status === 'active').length,
|
||||
totalReferrals: referralRecords.reduce((sum, r) => sum + r.totalReferrals, 0),
|
||||
totalOrders: referralRecords.reduce((sum, r) => sum + r.totalOrders, 0),
|
||||
totalCommission: referralRecords.reduce((sum, r) => sum + r.totalCommission, 0),
|
||||
paidCommission: referralRecords.reduce((sum, r) => sum + r.paidCommission, 0),
|
||||
pendingCommission: referralRecords.reduce((sum, r) => sum + r.pendingCommission, 0),
|
||||
averageCommission: referralRecords.reduce((sum, r) => sum + r.totalCommission, 0) / referralRecords.length
|
||||
}
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
overview
|
||||
})
|
||||
}
|
||||
|
||||
// 返回列表数据
|
||||
const start = (page - 1) * pageSize
|
||||
const end = start + pageSize
|
||||
const paginatedRecords = referralRecords.slice(start, end)
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
records: paginatedRecords,
|
||||
pagination: {
|
||||
page,
|
||||
pageSize,
|
||||
total: referralRecords.length,
|
||||
totalPages: Math.ceil(referralRecords.length / pageSize)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// POST: 创建分销记录或处理佣金
|
||||
export async function POST(req: NextRequest) {
|
||||
try {
|
||||
const body = await req.json()
|
||||
const { action, data } = body
|
||||
|
||||
if (action === 'create_referrer') {
|
||||
// 创建推广者
|
||||
const { userId, userName, commissionRate } = data
|
||||
|
||||
const newReferrer = {
|
||||
id: `REF_${Date.now()}`,
|
||||
referrerId: userId,
|
||||
referrerName: userName,
|
||||
inviteCode: generateInviteCode(),
|
||||
totalReferrals: 0,
|
||||
totalOrders: 0,
|
||||
totalCommission: 0,
|
||||
paidCommission: 0,
|
||||
pendingCommission: 0,
|
||||
commissionRate: commissionRate || 0.9,
|
||||
status: 'active',
|
||||
createdAt: new Date().toISOString()
|
||||
}
|
||||
|
||||
referralRecords.push(newReferrer)
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
message: '推广者创建成功',
|
||||
referrer: newReferrer
|
||||
})
|
||||
}
|
||||
|
||||
if (action === 'pay_commission') {
|
||||
// 支付佣金
|
||||
const { referrerId, amount, note } = data
|
||||
|
||||
const referrer = referralRecords.find(r => r.referrerId === referrerId)
|
||||
if (!referrer) {
|
||||
return NextResponse.json(
|
||||
{ error: '推广者不存在' },
|
||||
{ status: 404 }
|
||||
)
|
||||
}
|
||||
|
||||
if (amount > referrer.pendingCommission) {
|
||||
return NextResponse.json(
|
||||
{ error: '支付金额超过待支付佣金' },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
referrer.paidCommission += amount
|
||||
referrer.pendingCommission -= amount
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
message: '佣金支付成功',
|
||||
referrer
|
||||
})
|
||||
}
|
||||
|
||||
return NextResponse.json(
|
||||
{ error: '未知操作' },
|
||||
{ status: 400 }
|
||||
)
|
||||
} catch (error) {
|
||||
return NextResponse.json(
|
||||
{ error: '操作失败' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// PUT: 更新分销记录
|
||||
export async function PUT(req: NextRequest) {
|
||||
try {
|
||||
const body = await req.json()
|
||||
const { referrerId, status, commissionRate, note } = body
|
||||
|
||||
const referrerIndex = referralRecords.findIndex(r => r.referrerId === referrerId)
|
||||
if (referrerIndex === -1) {
|
||||
return NextResponse.json(
|
||||
{ error: '推广者不存在' },
|
||||
{ status: 404 }
|
||||
)
|
||||
}
|
||||
|
||||
referralRecords[referrerIndex] = {
|
||||
...referralRecords[referrerIndex],
|
||||
status: status || referralRecords[referrerIndex].status,
|
||||
commissionRate: commissionRate !== undefined ? commissionRate : referralRecords[referrerIndex].commissionRate,
|
||||
note: note || referralRecords[referrerIndex].note,
|
||||
updatedAt: new Date().toISOString()
|
||||
}
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
message: '推广者信息更新成功',
|
||||
referrer: referralRecords[referrerIndex]
|
||||
})
|
||||
} catch (error) {
|
||||
return NextResponse.json(
|
||||
{ error: '更新失败' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// DELETE: 删除分销记录
|
||||
export async function DELETE(req: NextRequest) {
|
||||
try {
|
||||
const { searchParams } = new URL(req.url)
|
||||
const referrerId = searchParams.get('id')
|
||||
|
||||
if (!referrerId) {
|
||||
return NextResponse.json(
|
||||
{ error: '推广者ID不能为空' },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
const referrerIndex = referralRecords.findIndex(r => r.referrerId === referrerId)
|
||||
if (referrerIndex === -1) {
|
||||
return NextResponse.json(
|
||||
{ error: '推广者不存在' },
|
||||
{ status: 404 }
|
||||
)
|
||||
}
|
||||
|
||||
referralRecords.splice(referrerIndex, 1)
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
message: '推广者删除成功'
|
||||
})
|
||||
} catch (error) {
|
||||
return NextResponse.json(
|
||||
{ error: '删除失败' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 生成邀请码
|
||||
function generateInviteCode(): string {
|
||||
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
|
||||
let code = ''
|
||||
for (let i = 0; i < 6; i++) {
|
||||
code += chars.charAt(Math.floor(Math.random() * chars.length))
|
||||
}
|
||||
return code
|
||||
}
|
||||
84
app/api/admin/route.ts
Normal file
84
app/api/admin/route.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
// app/api/admin/route.ts
|
||||
// 后台管理API入口
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
|
||||
// 验证管理员权限
|
||||
function verifyAdmin(req: NextRequest) {
|
||||
const token = req.headers.get('Authorization')?.replace('Bearer ', '')
|
||||
|
||||
// TODO: 实现真实的token验证
|
||||
if (!token || token !== 'admin-token-secret') {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// GET: 获取后台概览数据
|
||||
export async function GET(req: NextRequest) {
|
||||
if (!verifyAdmin(req)) {
|
||||
return NextResponse.json(
|
||||
{ error: '未授权访问' },
|
||||
{ status: 401 }
|
||||
)
|
||||
}
|
||||
|
||||
// 获取所有模块的概览数据
|
||||
const overview = {
|
||||
content: {
|
||||
totalChapters: 65,
|
||||
totalWords: 120000,
|
||||
publishedChapters: 60,
|
||||
draftChapters: 5,
|
||||
lastUpdate: new Date().toISOString()
|
||||
},
|
||||
payment: {
|
||||
totalRevenue: 12800.50,
|
||||
todayRevenue: 560.00,
|
||||
totalOrders: 128,
|
||||
todayOrders: 12,
|
||||
averagePrice: 100.00
|
||||
},
|
||||
referral: {
|
||||
totalReferrers: 45,
|
||||
activeReferrers: 28,
|
||||
totalCommission: 11520.45,
|
||||
paidCommission: 8500.00,
|
||||
pendingCommission: 3020.45
|
||||
},
|
||||
users: {
|
||||
totalUsers: 1200,
|
||||
purchasedUsers: 128,
|
||||
activeUsers: 456,
|
||||
todayNewUsers: 23
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.json(overview)
|
||||
}
|
||||
|
||||
// POST: 管理员登录
|
||||
export async function POST(req: NextRequest) {
|
||||
const body = await req.json()
|
||||
const { username, password } = body
|
||||
|
||||
// TODO: 实现真实的登录验证
|
||||
if (username === 'admin' && password === 'admin123') {
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
token: 'admin-token-secret',
|
||||
user: {
|
||||
id: 'admin',
|
||||
username: 'admin',
|
||||
role: 'admin',
|
||||
name: '卡若'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return NextResponse.json(
|
||||
{ error: '用户名或密码错误' },
|
||||
{ status: 401 }
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user