From 1b6e7fa8865e20aae6ca3eb77d2153238c4ccc43 Mon Sep 17 00:00:00 2001 From: Cuishibing <643237029@qq.com> Date: Tue, 24 Mar 2026 22:54:24 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E6=88=BF=E6=BA=90?= =?UTF-8?q?=E5=AE=A1=E6=A0=B8=E5=8A=9F=E8=83=BD=E5=8F=8A=E5=AE=9A=E6=97=B6?= =?UTF-8?q?=E5=AE=A1=E6=A0=B8=E4=BB=BB=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/cron/review/route.ts | 30 ++++++++++++++++++++++++++++++ app/api/houses/[id]/route.ts | 11 ++++++++--- app/api/houses/route.ts | 11 ++++++++--- app/api/owner/houses/route.ts | 3 +++ app/owner/dashboard/page.tsx | 17 +++++++++++++++++ run_review.sh | 6 ++++++ 6 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 app/api/cron/review/route.ts create mode 100755 run_review.sh diff --git a/app/api/cron/review/route.ts b/app/api/cron/review/route.ts new file mode 100644 index 0000000..f5e43de --- /dev/null +++ b/app/api/cron/review/route.ts @@ -0,0 +1,30 @@ +import { NextRequest, NextResponse } from 'next/server'; +import pool from '@/lib/db'; + +const CRON_SECRET = 'smalltown_review_secret_2024'; + +export async function POST(request: NextRequest) { + let connection; + try { + const authHeader = request.headers.get('authorization'); + if (authHeader !== `Bearer ${CRON_SECRET}`) { + return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); + } + + connection = await pool.getConnection(); + + const [result] = await connection.query( + "UPDATE houses SET status = 'approved', reviewed_at = NOW() WHERE status = 'pending'" + ); + + const affectedRows = (result as any).affectedRowCount || 0; + + connection.release(); + return NextResponse.json({ success: true, approved: affectedRows }); + } catch (error) { + console.error('Review error:', error); + return NextResponse.json({ error: '审核失败' }, { status: 500 }); + } finally { + if (connection) connection.release(); + } +} \ No newline at end of file diff --git a/app/api/houses/[id]/route.ts b/app/api/houses/[id]/route.ts index 57f517f..a4d92a9 100644 --- a/app/api/houses/[id]/route.ts +++ b/app/api/houses/[id]/route.ts @@ -10,10 +10,11 @@ export async function GET( const { id } = await params; connection = await pool.getConnection(); - const [rows] = await connection.query('SELECT * FROM houses WHERE id = ?', [id]); + const [rows] = await connection.query("SELECT * FROM houses WHERE id = ? AND status = 'approved'", [id]); if (rows.length === 0) { - return NextResponse.json({ error: '房屋不存在' }, { status: 404 }); + connection.release(); + return NextResponse.json({ error: '房屋不存在或待审核' }, { status: 404 }); } const row = rows[0]; @@ -30,6 +31,7 @@ export async function GET( createdAt: row.created_at }; + connection.release(); return NextResponse.json({ house }); } catch (error) { console.error('Get house error:', error); @@ -75,7 +77,7 @@ export async function PUT( const { title, description, price, district, address, phone, images } = body; await connection.query( - 'UPDATE houses SET title = ?, description = ?, price = ?, district = ?, address = ?, phone = ?, images = ? WHERE id = ?', + 'UPDATE houses SET title = ?, description = ?, price = ?, district = ?, address = ?, phone = ?, images = ?, status = ?, reject_reason = NULL WHERE id = ?', [ title || houses[0].title, description ?? houses[0].description, @@ -84,6 +86,7 @@ export async function PUT( address || houses[0].address, phone || houses[0].phone, images ? JSON.stringify(images) : houses[0].images, + 'pending', id ] ); @@ -100,6 +103,8 @@ export async function PUT( address: row.address, phone: row.phone, images: row.images ? JSON.parse(row.images) : [], + status: row.status, + reject_reason: row.reject_reason, createdAt: row.created_at }; diff --git a/app/api/houses/route.ts b/app/api/houses/route.ts index f9a11f2..99fa296 100644 --- a/app/api/houses/route.ts +++ b/app/api/houses/route.ts @@ -11,7 +11,7 @@ export async function GET(request: NextRequest) { connection = await pool.getConnection(); - let sql = 'SELECT * FROM houses WHERE 1=1'; + let sql = "SELECT * FROM houses WHERE status = 'approved'"; const params: any[] = []; if (district && district !== '全部') { @@ -42,6 +42,7 @@ export async function GET(request: NextRequest) { createdAt: row.created_at })); + connection.release(); return NextResponse.json({ houses }); } catch (error) { console.error('Get houses error:', error); @@ -65,6 +66,7 @@ export async function POST(request: NextRequest) { const [users] = await connection.query('SELECT username FROM users WHERE token = ?', [token]); if (users.length === 0) { + connection.release(); return NextResponse.json({ error: '用户不存在' }, { status: 401 }); } @@ -72,13 +74,14 @@ export async function POST(request: NextRequest) { const { title, description, price, district, address, phone, images } = body; if (!title || !price || !district || !address || !phone) { + connection.release(); return NextResponse.json({ error: '请填写完整信息' }, { status: 400 }); } const id = crypto.randomUUID(); await connection.query( - 'INSERT INTO houses (id, owner, title, description, price, district, address, phone, images, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', - [id, users[0].username, title, description || '', Number(price), district, address, phone, JSON.stringify(images || []), new Date()] + 'INSERT INTO houses (id, owner, title, description, price, district, address, phone, images, status, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', + [id, users[0].username, title, description || '', Number(price), district, address, phone, JSON.stringify(images || []), 'pending', new Date()] ); const house = { @@ -91,9 +94,11 @@ export async function POST(request: NextRequest) { address, phone, images: images || [], + status: 'pending', createdAt: new Date() }; + connection.release(); return NextResponse.json({ success: true, house }); } catch (error) { console.error('Create house error:', error); diff --git a/app/api/owner/houses/route.ts b/app/api/owner/houses/route.ts index e8ccc09..0895e77 100644 --- a/app/api/owner/houses/route.ts +++ b/app/api/owner/houses/route.ts @@ -34,6 +34,9 @@ export async function GET(request: NextRequest) { address: row.address, phone: row.phone, images: row.images ? JSON.parse(row.images) : [], + status: row.status, + reject_reason: row.reject_reason, + reviewed_at: row.reviewed_at, createdAt: row.created_at })); diff --git a/app/owner/dashboard/page.tsx b/app/owner/dashboard/page.tsx index ca1d5a7..a8b1de1 100644 --- a/app/owner/dashboard/page.tsx +++ b/app/owner/dashboard/page.tsx @@ -13,6 +13,9 @@ interface House { address: string; phone: string; images: string[]; + status: string; + reject_reason?: string; + reviewed_at?: string; createdAt: string; } @@ -271,6 +274,20 @@ export default function OwnerDashboard() { {house.district} +
+ {house.status === 'pending' && ( + 审核中 + )} + {house.status === 'approved' && ( + 审核通过 + )} + {house.status === 'rejected' && ( + 审核驳回 + )} +
+ {house.status === 'rejected' && house.reject_reason && ( +

驳回原因:{house.reject_reason}

+ )} diff --git a/run_review.sh b/run_review.sh new file mode 100755 index 0000000..807a311 --- /dev/null +++ b/run_review.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +CRON_SECRET="smalltown_review_secret_2024" +API_URL="http://localhost:3000/api/cron/review" + +curl -X POST -H "Authorization: Bearer $CRON_SECRET" "$API_URL" \ No newline at end of file