fix: 提交短链服务、sentry监控
This commit is contained in:
@@ -5,12 +5,9 @@ import useGlobalStore from '@/config/use-global';
|
||||
import { Card, CardContent } from '@workspace/airo-ui/components/card';
|
||||
import { useTranslations } from 'next-intl';
|
||||
|
||||
import CopyShortenedLink from '@/components/CopyShortenedLink/CopyShortenedLink';
|
||||
import Recharge from '@/components/subscribe/recharge';
|
||||
import SvgIcon from '@/components/SvgIcon';
|
||||
import { Button } from '@workspace/airo-ui/components/button';
|
||||
import Link from 'next/link';
|
||||
import { CopyToClipboard } from 'react-copy-to-clipboard';
|
||||
import { toast } from 'sonner';
|
||||
import Table from './components/Table/Table';
|
||||
import WalletDialog from './components/WalletDialog/WalletDialog';
|
||||
|
||||
@@ -67,18 +64,7 @@ export default function Page() {
|
||||
</p>
|
||||
<p className='flex justify-between text-base font-medium text-[#225BA9]'>
|
||||
<span> {user?.refer_code}</span>
|
||||
<CopyToClipboard
|
||||
text={`${location?.origin}/?invite=${user?.refer_code}`}
|
||||
onCopy={(text, result) => {
|
||||
if (result) {
|
||||
toast.success(dashboardT('copySuccess'));
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Button variant='link' size='sm' className='h-auto p-0 px-0 [&_svg]:size-5'>
|
||||
<SvgIcon name={'copy'}></SvgIcon>
|
||||
</Button>
|
||||
</CopyToClipboard>
|
||||
<CopyShortenedLink className={'sm:block'} />
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,12 +1,3 @@
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
export default async function MainLayout({ children }: { children: React.ReactNode }) {
|
||||
const CrispWithNoSSR = dynamic(() => import('@/components/Crisp/Crisp'));
|
||||
|
||||
return (
|
||||
<>
|
||||
<CrispWithNoSSR />
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// 你的后端 API 密钥,请确保将其存储在 .env.local 文件中
|
||||
const BACKEND_API_KEY = 'Q4PuYh7J2H_DlW2X4XUrwYV-yaKty8dw0dwP4LXM';
|
||||
import { NextResponse } from 'next/server';
|
||||
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
// 从客户端请求中获取 JSON 数据
|
||||
const requestBody = await request.json();
|
||||
// 检查请求的 hostname 是否为本地地址 (localhost 或 127.0.0.1)
|
||||
if (requestBody?.target?.includes('localhost') || requestBody?.target?.includes('127.0.0.1')) {
|
||||
console.log('Request is from localhost, returning self.');
|
||||
// 如果是本地请求,直接返回一个响应,不做转发
|
||||
return NextResponse.json({
|
||||
link: requestBody.target,
|
||||
});
|
||||
}
|
||||
|
||||
// 将客户端请求的 JSON 数据转发到真正的后端 API
|
||||
const backendResponse = await fetch('https://url.airoport.co/api/v2/links', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
// 🚨 在这里使用你的后端 API 密钥,它只在服务器端运行,非常安全
|
||||
'x-api-key': BACKEND_API_KEY,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
reuse: true,
|
||||
...requestBody,
|
||||
}),
|
||||
});
|
||||
|
||||
// 检查后端响应状态
|
||||
if (!backendResponse.ok) {
|
||||
// 转发后端 API 的错误响应
|
||||
const errorData = await backendResponse.json();
|
||||
return Response.json(errorData, { status: backendResponse.status });
|
||||
}
|
||||
|
||||
const backendData = await backendResponse.json();
|
||||
|
||||
// 将后端 API 的响应转发给前端
|
||||
return Response.json(backendData);
|
||||
} catch (error) {
|
||||
console.error('Proxy API Error:', error);
|
||||
return Response.json({ error: 'Internal server error' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import { useCountDown } from 'ahooks';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { UseFormReturn } from 'react-hook-form';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
interface SendCodeProps {
|
||||
type: 'email' | 'phone';
|
||||
@@ -47,6 +48,7 @@ export default function SendCode({ type, params, form }: SendCodeProps) {
|
||||
const setCodeTimer = () => {
|
||||
const endTime = Date.now() + verify_code_interval * 1000;
|
||||
setTargetDate(endTime);
|
||||
toast.success(t('register.sendCode'));
|
||||
localStorage.setItem(`verify_code_${type}`, endTime.toString());
|
||||
};
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import { unstable_noStore as noStore } from 'next/cache';
|
||||
import { Inter } from 'next/font/google';
|
||||
const inter = Inter({ subsets: ['latin'] });
|
||||
// import { Geist, Geist_Mono } from 'next/font/google';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { cookies } from 'next/headers';
|
||||
import { Metadata, Viewport } from 'next/types';
|
||||
import NextTopLoader from 'nextjs-toploader';
|
||||
@@ -99,6 +100,7 @@ export default async function RootLayout({
|
||||
console.log('Error fetching user info:', error);
|
||||
}
|
||||
}
|
||||
const CrispWithNoSSR = dynamic(() => import('@/components/Crisp/Crisp'));
|
||||
|
||||
return (
|
||||
<html suppressHydrationWarning lang={locale} dir={getLangDir(locale)}>
|
||||
@@ -120,6 +122,7 @@ export default async function RootLayout({
|
||||
<NextTopLoader showSpinner={false} />
|
||||
<Providers common={{ ...config }} user={user}>
|
||||
<Toaster richColors closeButton />
|
||||
<CrispWithNoSSR />
|
||||
{children}
|
||||
</Providers>
|
||||
</NextIntlClientProvider>
|
||||
|
||||
Reference in New Issue
Block a user