From b0a0b37b196618b5e1e0da9dd3cae93613d0da32 Mon Sep 17 00:00:00 2001 From: Eamon-meng <17516219072@163.com> Date: Mon, 1 Dec 2025 19:11:53 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E8=B0=83=E7=94=A8=E6=97=B6?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E7=94=A8=E6=88=B7=E7=9A=84x-data-ip=E5=92=8C?= =?UTF-8?q?x-data-ua=20&=20=E4=BF=AE=E6=94=B9isp=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=20&=20=E4=BD=BF=E7=94=A8=E6=95=99=E7=A8=8B?= =?UTF-8?q?=E5=88=9D=E7=89=88=20&=E5=90=8E=E5=8F=B0=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E5=90=8D=E5=AD=97=E6=AE=B5=E5=B1=95=E7=A4=BA=20&=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E6=94=AF=E4=BB=98=E5=B9=B3=E5=8F=B0=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/actions/base.ts | 13 ++- src/actions/channel.ts | 2 +- src/app/(api)/proxies/route.ts | 2 +- .../(home)/_components/header/menu-help.tsx | 2 +- .../help/tutorials/quick-start/page.tsx | 101 +++++++++++------- .../admin/(dashboard)/_client/userCenter.tsx | 2 +- src/app/admin/bills/page.tsx | 24 +++++ .../composites/quickStart/index.tsx | 18 ++++ .../quickStart/tutorial-content.tsx | 20 ++++ .../quickStart/tutorial-sidebar.tsx | 65 +++++++++++ src/components/composites/sidebar.tsx | 91 ++++++++++++++++ .../composites/user-center/index.tsx | 2 +- src/lib/models/models.ts | 1 + 13 files changed, 300 insertions(+), 43 deletions(-) create mode 100644 src/components/composites/quickStart/index.tsx create mode 100644 src/components/composites/quickStart/tutorial-content.tsx create mode 100644 src/components/composites/quickStart/tutorial-sidebar.tsx create mode 100644 src/components/composites/sidebar.tsx diff --git a/src/actions/base.ts b/src/actions/base.ts index bef4cf3..f246038 100644 --- a/src/actions/base.ts +++ b/src/actions/base.ts @@ -3,6 +3,7 @@ import {API_BASE_URL, ApiResponse, CLIENT_ID, CLIENT_SECRET} from '@/lib/api' import {cookies, headers} from 'next/headers' import {cache} from 'react' import {redirect} from 'next/navigation' +import {userAgent} from 'next/server' // ====================== // public @@ -113,7 +114,17 @@ const _callByUser = cache(async ( async function call(url: string, request: RequestInit): Promise> { let response: Response try { - response = await fetch(url, request) + const userHeaders = await headers() + // request.headers['x-data-ip'] = header.get('x-forwarded-for') + // request.headers['x-data-ua'] = header.get('user-agent') + response = await fetch(url, { + ...request, + headers: { + ...request.headers, + 'x-data-ip': userHeaders.get('x-forwarded-for') || '', + 'x-data-ua': userHeaders.get('user-agent') || '', + }, + }) } catch (e) { console.error('后端请求失败', url, (e as Error).message) diff --git a/src/actions/channel.ts b/src/actions/channel.ts index 7b88348..faf846f 100644 --- a/src/actions/channel.ts +++ b/src/actions/channel.ts @@ -29,7 +29,7 @@ export async function createChannels(params: { count: number prov?: string city?: string - isp?: string + isp?: number }) { return callByUser('/api/channel/create', params) } diff --git a/src/app/(api)/proxies/route.ts b/src/app/(api)/proxies/route.ts index c597aa6..65115ca 100644 --- a/src/app/(api)/proxies/route.ts +++ b/src/app/(api)/proxies/route.ts @@ -32,7 +32,7 @@ export async function GET(req: NextRequest) { count: Number(count), prov, city, - isp, + isp: Number(isp), }) if (!result.success) { throw new Error(result.message) diff --git a/src/app/(home)/_components/header/menu-help.tsx b/src/app/(home)/_components/header/menu-help.tsx index bc73f41..5056d99 100644 --- a/src/app/(home)/_components/header/menu-help.tsx +++ b/src/app/(home)/_components/header/menu-help.tsx @@ -33,7 +33,7 @@ export default function HelpMenu() { icon={h03} title="产品功能" items={[ - {lead: '常见问题', href: '#'}, + {lead: '常见问题', href: '/prodFeat'}, {lead: '产品介绍', href: '#'}, {lead: '行业资讯', href: '#'}, ]} diff --git a/src/app/(home)/help/tutorials/quick-start/page.tsx b/src/app/(home)/help/tutorials/quick-start/page.tsx index dff653c..435c49b 100644 --- a/src/app/(home)/help/tutorials/quick-start/page.tsx +++ b/src/app/(home)/help/tutorials/quick-start/page.tsx @@ -1,41 +1,68 @@ -import QuickStart from '@/components/docs/quickStart.mdx' -import Markdown from '@/components/markdown' +'use client' +import {useEffect, useState} from 'react' +import {useRouter, usePathname, useSearchParams} from 'next/navigation' +import BreadCrumb from '@/components/bread-crumb' +import Wrap from '@/components/wrap' +import QuickStart from '@/components/composites/quickStart' +import Sidebar, {MENU} from '@/components/composites/sidebar' + +export type CollectPageProps = {} + +export default function CollectPage(props: CollectPageProps) { + const router = useRouter() + const pathname = usePathname() + const searchParams = useSearchParams() + + // 初始根据 url ?doc=xxx 设置选中项,回退到默认 'browser-proxy' + const initialDoc = searchParams?.get('doc') ?? 'browser-proxy' + const [selected, setSelected] = useState(initialDoc) + const [collapsed, setCollapsed] = useState(false) + + // 当 selected 改变时同步更新 URL + useEffect(() => { + const url = `${pathname}?doc=${selected}` + router.replace(url) + }, [selected, pathname, router]) + + const selectedLabel = (() => { + for (const sec of MENU) { + const found = sec.items.find(i => i.key === selected) + if (found) return found.label + } + return selected + })() -export default function QuickStartPage() { return ( -
- - - -
+
+ + + {/* 两列布局:左侧侧边栏,右侧内容 */} +
+ setCollapsed(v => !v)} + selected={selected} + onSelect={key => setSelected(key)} + /> +
+ {selected === 'browser-proxy' && } + {selected !== 'browser-proxy' && ( +
+

+ {selected === 'code-download' ? '代码下载' : '占位页面'} +

+

+ 这里渲染对应文档内容(演示占位)。你可以替换为其它 MDX/组件,或把更多页面配置进 Sidebar 数据中。 +

+
+ )} +
+
+
+
) } - -// app/ -// ├── help/ -// │ ├── tutorials/ # 使用教程 -// │ │ ├── quick-start/ # 快速入手 -// │ │ │ └── page.tsx -// │ │ ├── code-download/ # 代码下载 -// │ │ │ └── page.tsx -// │ │ └── api-docs/ # API文档 -// │ │ └── page.tsx -// │ │ -// │ └── features/ # 产品功能 -// │ ├── faq/ # 常见问题 -// │ │ └── page.tsx -// │ ├── introduction/ # 产品介绍 -// │ │ └── page.tsx -// │ └── industry-news/ # 行业资讯 -// │ └── page.tsx -// │ -// components/ -// └── docs/ -// ├── tutorials/ -// │ ├── quickStart.mdx # MDX内容文件 -// │ ├── codeDownload.mdx -// │ └── apiDocs.mdx -// └── features/ -// ├── faq.mdx -// ├── introduction.mdx -// └── industryNews.mdx diff --git a/src/app/admin/(dashboard)/_client/userCenter.tsx b/src/app/admin/(dashboard)/_client/userCenter.tsx index 47ca275..a3978c3 100644 --- a/src/app/admin/(dashboard)/_client/userCenter.tsx +++ b/src/app/admin/(dashboard)/_client/userCenter.tsx @@ -26,7 +26,7 @@ async function UserCenter() {
-

{profile.phone}

+

{profile.username?.trim() || profile.email || profile.phone}

{`最后登录:${format(profile.last_login, 'yyyy-MM-dd HH:mm')}`}

{ + const trade = row.original.trade + if (!trade) return - + return ( +
+ {trade.platform === 1 ? ( + <> + 电脑网站 + + ) : trade.platform === 2 ? ( + <> + 手机网站 + + ) : ( + - + )} +
+ ) + }, + }, { accessorKey: 'created_at', header: '创建时间', cell: ({row}) => ( format(new Date(row.original.created_at), 'yyyy-MM-dd HH:mm') diff --git a/src/components/composites/quickStart/index.tsx b/src/components/composites/quickStart/index.tsx new file mode 100644 index 0000000..f0e8cf5 --- /dev/null +++ b/src/components/composites/quickStart/index.tsx @@ -0,0 +1,18 @@ +import TutorialSidebar from './tutorial-sidebar' +import TutorialContent from './tutorial-content' + +export default function QuickStart({hidePreview = false}: {hidePreview?: boolean}) { + return ( +
+ {!hidePreview && ( +
+ +
+ )} + +
+ +
+
+ ) +} diff --git a/src/components/composites/quickStart/tutorial-content.tsx b/src/components/composites/quickStart/tutorial-content.tsx new file mode 100644 index 0000000..c1590e8 --- /dev/null +++ b/src/components/composites/quickStart/tutorial-content.tsx @@ -0,0 +1,20 @@ +export default function TutorialContent() { + return ( + <> + {/* 页面标题 */} +
+

浏览器设置代理教程

+
发布时间: 2025-01-17 16:18:21
+
+
+
打开IE浏览器,选择“设置”,点击“Internet选项”,在弹出的“局域网LAN设置”中,代理服务器的复选框打上勾,并填写从神龙HTTP获取的ip地址及端口号,点击确定,刷新浏览器,浏览器的IP就改变了。
+
+
1、打开IE浏览器,选择“设置”;
+
+
2、点击“Internet选项”;
+
3、弹出“Internet选项”弹窗,选择连接—局域网设置;
+
+
4、在弹出的“局域网LAN设置”中,代理服务器的复选框打上勾,并填写从神龙HTTP代理获取的ip地址及端口。点击确定,即设置成功了。
+ + ) +} diff --git a/src/components/composites/quickStart/tutorial-sidebar.tsx b/src/components/composites/quickStart/tutorial-sidebar.tsx new file mode 100644 index 0000000..e412b64 --- /dev/null +++ b/src/components/composites/quickStart/tutorial-sidebar.tsx @@ -0,0 +1,65 @@ +'use client' + +import Link from 'next/link' +import {usePathname} from 'next/navigation' + +const tutorialSections = [ + { + title: '官网教程', + items: [ + {name: '浏览器设置代理教程', href: '/help/tutorials/browser-proxy'}, + {name: 'iOS设置代理教程', href: '/help/tutorials/ios-proxy'}, + {name: 'Windows10电脑设置代理教程', href: '/help/tutorials/windows-proxy'}, + {name: '安卓手机设置代理教程', href: '/help/tutorials/android-proxy'}, + {name: '查看终端、合并、修改协议、补重操作', href: '/help/tutorials/terminal-operations'}, + {name: '蓝狐HTTP代理如何生成API链接?', href: '/help/tutorials/api-generation'}, + {name: '蓝狐HTTP代理如何添加IP合宿?', href: '/help/tutorials/ip-hosting'}, + {name: '长效固定套餐操作手册', href: '/help/tutorials/long-term-package'}, + ], + }, + { + title: '客户端教程', + items: [ + {name: '操作指南', href: '/help/tutorials/client-guide'}, + ], + }, +] + +export default function TutorialSidebar() { + const pathname = usePathname() + + if (pathname?.includes('/quick-start')) { + return