更新管理员登录和鉴权逻辑,优化用户体验;重构相关API以支持更安全的身份验证;调整数据库初始化以兼容新字段,确保用户信息安全;修复部分组件样式和功能,提升整体可用性。

This commit is contained in:
2026-01-31 23:25:14 +08:00
parent c7b125535c
commit bd23273190
22 changed files with 861 additions and 150 deletions

View File

@@ -6,6 +6,7 @@
import { NextResponse } from 'next/server'
import fs from 'fs'
import path from 'path'
import { requireAdminResponse } from '@/lib/admin-auth'
// 获取书籍目录
const BOOK_DIR = path.join(process.cwd(), 'book')
@@ -14,6 +15,8 @@ const BOOK_DIR = path.join(process.cwd(), 'book')
* GET - 获取所有章节列表
*/
export async function GET(request: Request) {
const authErr = requireAdminResponse(request)
if (authErr) return authErr
try {
const { searchParams } = new URL(request.url)
const includeContent = searchParams.get('content') === 'true'
@@ -274,6 +277,8 @@ export async function GET(request: Request) {
* POST - 更新章节设置
*/
export async function POST(request: Request) {
const authErr = requireAdminResponse(request)
if (authErr) return authErr
try {
const body = await request.json()
const { action, chapterId, data } = body

View File

@@ -5,11 +5,14 @@ import { NextRequest, NextResponse } from 'next/server'
import fs from 'fs'
import path from 'path'
import matter from 'gray-matter'
import { requireAdminResponse } from '@/lib/admin-auth'
const BOOK_DIR = path.join(process.cwd(), 'book')
// GET: 获取所有章节列表
export async function GET(req: NextRequest) {
const authErr = requireAdminResponse(req)
if (authErr) return authErr
try {
const chapters = getAllChapters()
@@ -28,6 +31,8 @@ export async function GET(req: NextRequest) {
// POST: 创建新章节
export async function POST(req: NextRequest) {
const authErr = requireAdminResponse(req)
if (authErr) return authErr
try {
const body = await req.json()
const { title, content, category, tags } = body
@@ -70,6 +75,8 @@ export async function POST(req: NextRequest) {
// PUT: 更新章节
export async function PUT(req: NextRequest) {
const authErr = requireAdminResponse(req)
if (authErr) return authErr
try {
const body = await req.json()
const { id, title, content, category, tags } = body
@@ -97,6 +104,8 @@ export async function PUT(req: NextRequest) {
// DELETE: 删除章节
export async function DELETE(req: NextRequest) {
const authErr = requireAdminResponse(req)
if (authErr) return authErr
try {
const { searchParams } = new URL(req.url)
const id = searchParams.get('id')

View File

@@ -0,0 +1,9 @@
import { NextRequest, NextResponse } from 'next/server'
import { getAdminCookieName, getAdminCookieOptions } from '@/lib/admin-auth'
export async function POST(_req: NextRequest) {
const res = NextResponse.json({ success: true })
const opts = getAdminCookieOptions()
res.cookies.set(getAdminCookieName(), '', { ...opts, maxAge: 0 })
return res
}

View File

@@ -2,6 +2,7 @@
// 付费模块管理API
import { NextRequest, NextResponse } from 'next/server'
import { requireAdminResponse } from '@/lib/admin-auth'
// 模拟订单数据
let orders = [
@@ -29,6 +30,8 @@ let orders = [
// GET: 获取订单列表
export async function GET(req: NextRequest) {
const authErr = requireAdminResponse(req)
if (authErr) return authErr
const { searchParams } = new URL(req.url)
const status = searchParams.get('status')
const page = parseInt(searchParams.get('page') || '1')
@@ -71,6 +74,8 @@ export async function GET(req: NextRequest) {
// POST: 创建订单(手动)
export async function POST(req: NextRequest) {
const authErr = requireAdminResponse(req)
if (authErr) return authErr
try {
const body = await req.json()
const { userId, userName, amount, note } = body
@@ -110,6 +115,8 @@ export async function POST(req: NextRequest) {
// PUT: 更新订单状态
export async function PUT(req: NextRequest) {
const authErr = requireAdminResponse(req)
if (authErr) return authErr
try {
const body = await req.json()
const { orderId, status, note } = body
@@ -148,6 +155,8 @@ export async function PUT(req: NextRequest) {
// DELETE: 删除订单
export async function DELETE(req: NextRequest) {
const authErr = requireAdminResponse(req)
if (authErr) return authErr
try {
const { searchParams } = new URL(req.url)
const orderId = searchParams.get('id')

View File

@@ -2,6 +2,7 @@
// 分销模块管理API
import { NextRequest, NextResponse } from 'next/server'
import { requireAdminResponse } from '@/lib/admin-auth'
// 模拟分销数据
let referralRecords = [
@@ -52,6 +53,8 @@ let commissionRecords = [
// GET: 获取分销概览或列表
export async function GET(req: NextRequest) {
const authErr = requireAdminResponse(req)
if (authErr) return authErr
const { searchParams } = new URL(req.url)
const type = searchParams.get('type') || 'list'
const page = parseInt(searchParams.get('page') || '1')
@@ -95,6 +98,8 @@ export async function GET(req: NextRequest) {
// POST: 创建分销记录或处理佣金
export async function POST(req: NextRequest) {
const authErr = requireAdminResponse(req)
if (authErr) return authErr
try {
const body = await req.json()
const { action, data } = body
@@ -170,6 +175,8 @@ export async function POST(req: NextRequest) {
// PUT: 更新分销记录
export async function PUT(req: NextRequest) {
const authErr = requireAdminResponse(req)
if (authErr) return authErr
try {
const body = await req.json()
const { referrerId, status, commissionRate, note } = body
@@ -205,6 +212,8 @@ export async function PUT(req: NextRequest) {
// DELETE: 删除分销记录
export async function DELETE(req: NextRequest) {
const authErr = requireAdminResponse(req)
if (authErr) return authErr
try {
const { searchParams } = new URL(req.url)
const referrerId = searchParams.get('id')

View File

@@ -1,25 +1,27 @@
// app/api/admin/route.ts
// 后台管理API入口
// 后台管理API入口:登录与鉴权(账号密码从环境变量读取,默认 admin / admin123
import { NextRequest, NextResponse } from 'next/server'
import {
verifyAdminToken,
getAdminTokenFromRequest,
verifyAdminCredentials,
getAdminCredentials,
createAdminToken,
getAdminCookieName,
getAdminCookieOptions,
} from '@/lib/admin-auth'
// 验证管理员权限
function verifyAdmin(req: NextRequest) {
const token = req.headers.get('Authorization')?.replace('Bearer ', '')
// TODO: 实现真实的token验证
if (!token || token !== 'admin-token-secret') {
return false
}
return true
function requireAdmin(req: NextRequest): boolean {
const token = getAdminTokenFromRequest(req)
return verifyAdminToken(token)
}
// GET: 获取后台概览数据
// GET: 获取后台概览数据(需已登录)
export async function GET(req: NextRequest) {
if (!verifyAdmin(req)) {
if (!requireAdmin(req)) {
return NextResponse.json(
{ error: '未授权访问' },
{ error: '未授权访问,请先登录' },
{ status: 401 }
)
}
@@ -58,27 +60,31 @@ export async function GET(req: NextRequest) {
return NextResponse.json(overview)
}
// POST: 管理员登录
// POST: 管理员登录(账号密码从环境变量 ADMIN_USERNAME / ADMIN_PASSWORD 读取,默认 admin / admin123
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: '卡若'
}
})
if (!username || !password) {
return NextResponse.json(
{ error: '请输入用户名和密码' },
{ status: 400 }
)
}
return NextResponse.json(
{ error: '用户名或密码错误' },
{ status: 401 }
)
if (!verifyAdminCredentials(String(username).trim(), String(password))) {
return NextResponse.json(
{ error: '用户名或密码错误' },
{ status: 401 }
)
}
const token = createAdminToken()
const res = NextResponse.json({
success: true,
user: { id: 'admin', username: getAdminCredentials().username, role: 'admin', name: '卡若' },
})
const opts = getAdminCookieOptions()
res.cookies.set(getAdminCookieName(), token, opts)
return res
}

View File

@@ -6,9 +6,12 @@
import { NextResponse } from 'next/server'
import { query } from '@/lib/db'
import { createTransfer } from '@/lib/wechat-transfer'
import { requireAdminResponse } from '@/lib/admin-auth'
// 获取所有提现记录
export async function GET(request: Request) {
const authErr = requireAdminResponse(request)
if (authErr) return authErr
try {
const { searchParams } = new URL(request.url)
const status = searchParams.get('status') // pending, success, failed, all
@@ -84,6 +87,8 @@ export async function GET(request: Request) {
// 处理提现(审批/拒绝)
export async function PUT(request: Request) {
const authErr = requireAdminResponse(request)
if (authErr) return authErr
try {
const body = await request.json()
const { id, action, reason } = body // action: approve, reject