From 0665a4e13c0e5df675f86be1b757d86bac418e44 Mon Sep 17 00:00:00 2001 From: luorijun Date: Fri, 9 May 2025 09:36:23 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E9=94=99=E8=AF=AF=E6=8F=90?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 ++-- src/actions/base.ts | 60 ++++++++++++++++++++-------------- src/app/(api)/proxies/route.ts | 26 +++++++-------- src/app/(auth)/login/page.tsx | 10 +++--- src/app/admin/bills/page.tsx | 12 +++---- src/middleware.ts | 15 +++++++-- 6 files changed, 74 insertions(+), 55 deletions(-) diff --git a/README.md b/README.md index 7a86252..5d3a881 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ ## TODO - 总览页 -- 个人中心 - 页面图片替换 - 网页标题根据实际页面变化 - 表格页筛选日期,范围筛选需要联动;检查时间范围选择,限定到一定范围内 +- 中间件 Limiter - 购买套餐页的冗余组件 - 确认各个页面操作列的内容 - 提取后刷新提取页套餐可用余量 @@ -13,16 +13,18 @@ - 后台页面: - 提取记录 - 使用记录 +- 登录流程有问题,在人机验证前不允许提交登录请求 ### 下阶段 +- markdown 文档渲染 - 后台首页改为 grid 布局,需要额外实现用于布局的客户端组件 - 检查页面,为后端请求标记 wait 实现防抖机制 - 页面切换动效 - 使用 pure js 的包代替 canvas,加快编译速度 - 验证码读秒用 store 保存到本地,(全局共享读秒时间)? - 将翻页操作反映在路由历史中,可以通过后退返回到上一个翻页状态? -- + ### 长期 - 检查扩大服务端组件边界 diff --git a/src/actions/base.ts b/src/actions/base.ts index 7ef0952..4f4d5ba 100644 --- a/src/actions/base.ts +++ b/src/actions/base.ts @@ -20,12 +20,12 @@ const _callPublic = cache(async ( data?: string, ): Promise> => { return call(`${API_BASE_URL}${endpoint}`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: data, + method: 'POST', + headers: { + 'Content-Type': 'application/json', }, + body: data, + }, ) }) @@ -113,24 +113,17 @@ const _callByUser = cache(async ( // ====================== async function call(url: string, request: RequestInit): Promise> { - const response = await fetch(url, request) - const type = response.headers.get('Content-Type') ?? 'text/plain' - if (type.indexOf('application/json') !== -1) { - const json = await response.json() - if (!response.ok) { - console.log('后端请求失败', url, `status=${response.status}`, json) - return { - success: false, - status: response.status, - message: json.message || '请求失败', - } - } - return { - success: true, - data: json, - } + let response: Response + try { + response = await fetch(url, request) } - else if (type.indexOf('text/plain') !== -1) { + catch (e) { + console.error('后端请求失败', url, (e as Error).message) + throw new Error(`请求失败,网络错误`) + } + + const type = response.headers.get('Content-Type') ?? 'text/plain' + if (type.indexOf('text/plain') !== -1) { const text = await response.text() if (!response.ok) { console.log('后端请求失败', url, `status=${response.status}`, text) @@ -141,12 +134,30 @@ async function call(url: string, request: RequestInit): Promise(rawResp: Promise>) { ].some(item => item.test(pathname)) if (match && !resp.success && resp.status === 401) { - console.log('!!!!!!!!!redirect', '"', pathname, '"', resp.message) - redirect(pathname === '/' ? '/login' : `/login?redirect=${pathname}`) + redirect('/login?force=true') } return resp diff --git a/src/app/(api)/proxies/route.ts b/src/app/(api)/proxies/route.ts index 6a4e4a0..a227550 100644 --- a/src/app/(api)/proxies/route.ts +++ b/src/app/(api)/proxies/route.ts @@ -46,19 +46,19 @@ export async function GET(req: NextRequest) { const separator = rSeparator.split(',').map(code => String.fromCharCode(parseInt(code))).join('') switch (format) { - case 'json': - const body = JSON.stringify(params) - return NextResponse.json(body) - case 'text': - const text = result.data.map(item => { - const list = [item.host, item.port] - if (item.username && item.password) { - list.push(item.username) - list.push(item.password) - } - return list.join(separator) - }).join(breaker) - return new NextResponse(text) + case 'json': + const body = JSON.stringify(params) + return NextResponse.json(body) + case 'text': + const text = result.data.map(item => { + const list = [item.host, item.port] + if (item.username && item.password) { + list.push(item.username) + list.push(item.password) + } + return list.join(separator) + }).join(breaker) + return new NextResponse(text) } } catch (error) { diff --git a/src/app/(auth)/login/page.tsx b/src/app/(auth)/login/page.tsx index af93267..450eaf4 100644 --- a/src/app/(auth)/login/page.tsx +++ b/src/app/(auth)/login/page.tsx @@ -89,7 +89,9 @@ export default function LoginPage(props: LoginPageProps) { }) } catch (e) { - toast.error(`请求失败:${e}`) + toast.error('短信发送失败', { + description: (e as Error).message, + }) return false } @@ -164,9 +166,7 @@ export default function LoginPage(props: LoginPageProps) { // 登录失败 if (!result.success) { - return toast.error(result.message, { - description: '请检查您的手机号码和验证码', - }) + throw new Error(result.message || '请检查手机号码和验证码是否正确') } // 登录成功 @@ -177,7 +177,7 @@ export default function LoginPage(props: LoginPageProps) { }) } catch (e) { - toast.error('登录错误', { + toast.error('登录失败', { description: (e as Error).message, }) } diff --git a/src/app/admin/bills/page.tsx b/src/app/admin/bills/page.tsx index a9647b0..b130597 100644 --- a/src/app/admin/bills/page.tsx +++ b/src/app/admin/bills/page.tsx @@ -68,8 +68,6 @@ export default function BillsPage(props: BillsPageProps) { } useEffect(() => { - console.log('init bill list') - refresh(1, 10).then() refresh(1, 10).then() }, []) @@ -240,11 +238,11 @@ export default function BillsPage(props: BillsPageProps) { { accessorKey: 'amount', header: `支付信息`, cell: ({row}) => (
- - {!row.original.trade && '余额'} - {row.original.trade && row.original.trade.method === 1 && '支付宝'} - {row.original.trade && row.original.trade.method === 2 && '微信'} - + + {!row.original.trade && '余额'} + {row.original.trade && row.original.trade.method === 1 && '支付宝'} + {row.original.trade && row.original.trade.method === 2 && '微信'} + 0 ? `text-green-400` : `text-orange-400` }>¥{row.original.amount} diff --git a/src/middleware.ts b/src/middleware.ts index f7c7c28..d2df209 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -1,5 +1,6 @@ import {NextRequest, NextResponse} from 'next/server' import {refreshAuth} from '@/actions/auth' +import { UnauthorizedError } from './lib/api' export const config = { matcher: [ @@ -28,15 +29,23 @@ export async function middleware(request: NextRequest) { console.log('❌ 刷新访问令牌失败', e) } + // 如果刷新访问令牌成功,则继续访问之前的页面 + const isLogin = request.nextUrl.pathname === '/login' + const redirect = request.nextUrl.searchParams.get('redirect') + if (isLogin && redirect) { + console.log('redirect to', redirect) + return NextResponse.redirect(`${request.nextUrl.origin}${redirect}`) + } + // 没有访问令牌不允许访问 admin 页面 - const match = [ + const isAdmin = [ RegExp(`^/admin.*`), ].some(item => item.test(request.nextUrl.pathname)) const accessToken = request.cookies.get('auth_token') - if (match && !accessToken) { - console.log('redirect!!!!!!!!!') + if (isAdmin && !accessToken) { + console.log('🚗🚗🚗🚗🚗 非正常重定向 🚗🚗🚗🚗🚗') return NextResponse.redirect(`${request.nextUrl.origin}/login?redirect=${request.nextUrl.pathname}`) }