From c17c17724f917b78df759eccae9c3c0a66a80182 Mon Sep 17 00:00:00 2001 From: Eamon-meng <17516219072@163.com> Date: Thu, 5 Jun 2025 16:41:30 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=98=E6=9B=B4=E5=9B=BE=E6=A0=87=E5=92=8Cti?= =?UTF-8?q?tle=E6=8F=90=E7=A4=BA=E5=AE=8C=E5=96=84=E8=B4=A6=E6=88=B7?= =?UTF-8?q?=E6=80=BB=E8=A7=88=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- src/app/(auth)/login/layout.tsx | 17 +++ src/app/(home)/page.tsx | 24 +-- .../admin/(dashboard)/_assets/Mask group.webp | Bin 0 -> 2872 bytes src/app/admin/(dashboard)/_client/charts.tsx | 121 +++++++++++++++ src/app/admin/(dashboard)/_client/pins.tsx | 76 ++++++++++ src/app/admin/(dashboard)/layout.tsx | 17 +++ src/app/admin/(dashboard)/page.tsx | 141 ++++-------------- src/app/admin/_client/navbar.tsx | 35 +++-- src/app/admin/bills/layout.tsx | 17 +++ src/app/admin/channels/layout.tsx | 17 +++ src/app/admin/extract/layout.tsx | 17 +++ src/app/admin/identify/layout.tsx | 16 ++ src/app/admin/profile/layout.tsx | 17 +++ src/app/admin/purchase/layout.tsx | 17 +++ src/app/admin/resources/layout.tsx | 17 +++ src/app/admin/whitelist/layout.tsx | 17 +++ src/app/layout.tsx | 3 +- 18 files changed, 434 insertions(+), 137 deletions(-) create mode 100644 src/app/(auth)/login/layout.tsx create mode 100644 src/app/admin/(dashboard)/_assets/Mask group.webp create mode 100644 src/app/admin/(dashboard)/_client/charts.tsx create mode 100644 src/app/admin/(dashboard)/_client/pins.tsx create mode 100644 src/app/admin/(dashboard)/layout.tsx create mode 100644 src/app/admin/bills/layout.tsx create mode 100644 src/app/admin/channels/layout.tsx create mode 100644 src/app/admin/extract/layout.tsx create mode 100644 src/app/admin/identify/layout.tsx create mode 100644 src/app/admin/profile/layout.tsx create mode 100644 src/app/admin/purchase/layout.tsx create mode 100644 src/app/admin/resources/layout.tsx create mode 100644 src/app/admin/whitelist/layout.tsx diff --git a/package.json b/package.json index 7aafade..6388f82 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "onlyBuiltDependencies": [ "canvas", "sharp" - ], + ], "overrides": { "react-is": "19.0.0-rc.1" } diff --git a/src/app/(auth)/login/layout.tsx b/src/app/(auth)/login/layout.tsx new file mode 100644 index 0000000..30c3605 --- /dev/null +++ b/src/app/(auth)/login/layout.tsx @@ -0,0 +1,17 @@ + +import { ReactNode } from 'react' +import { Metadata } from 'next' + +export async function generateMetadata(): Promise { + return { + title: '登录 - 蓝狐代理', + } +} + +export type LoginLayoutProps = { + children: ReactNode +} + +export default async function LoginLayout(props: LoginLayoutProps) { + return props.children +} \ No newline at end of file diff --git a/src/app/(home)/page.tsx b/src/app/(home)/page.tsx index 2abf5d3..fe1ce3f 100644 --- a/src/app/(home)/page.tsx +++ b/src/app/(home)/page.tsx @@ -72,24 +72,24 @@ export default function Home() { ].join(' ')}> + {icon: `s1-check`, text: `IP时效3-30分钟(可定制)`}, + {icon: `s1-check`, text: `支持高并发提取`}, + ]}/> + {icon: `s1-check`, text: `IP覆盖全国各地`}, + {icon: `s1-check`, text: `平均响应时长:0.03s`}, + ]}/> + {icon: `s1-check`, text: `稳定长输不掉线`}, + {icon: `s1-check`, text: `全国热门静态IP线路`}, + ]}/> + {icon: `s1-check`, text: `可视化监控设计`}, + {icon: `s1-check`, text: `技术团队现场支持`}, + ]}/> diff --git a/src/app/admin/(dashboard)/_assets/Mask group.webp b/src/app/admin/(dashboard)/_assets/Mask group.webp new file mode 100644 index 0000000000000000000000000000000000000000..f7b1e25882cd7c52f4f3d419e071dc71c9ca72ae GIT binary patch literal 2872 zcmds#`#;oa8^`Z)9ID+&QfrqPLqkc_N>Ni7rw%(Q=j42faU4d;Av>m7Q5p$Zl4D46 zUdQoN$Z2I}u}ns^nj|J83}bwsuX;VN_J@6*Kj69V*L~gZ`?@}_?{#0_>$bKuGuyuj z06V-f!IofPFAD(J53fA{=m218VnTR1*0K7V8Pzp+Pf=!QNC)))~3!Z&hljE(9xdj;B@gLfpnltCD<2Ijzc zqki}dkDxpN3>EkS#1m-jFD)(YZ>gpO+U^qfGp zKGBI?_o^c!tgqdJT}KqIZM%Neol8mjQ)Z+&fL+%&dsO#Ip+CFMk6r5V*y93QAHv1z zT-9OJCFlR>lioyRujp|5*F{yyeZ-;hm+$V)9BLozu+7@tU)!it7r+(>7PLay7F})p z9I5p1d4_Xq zL4Ent^h`YoT|JVjI}N!|HJkBjym|8JhYaZ~JAKico7=KDS0_c+pln_axoL%4d~qh` zH)4BC`#bCTr$6ALL)M{V z2K>SXY}f!&POLDV-l5#BpVgb4dM1;|yjDb@pJ+e8U3=^-Tw32TQ?T2k#V#i&fJlz3 zM=6IIjp9sE)2EgEu`+pd-*?zeIRp;*g(o z&7OtSOOrdgY5T5n1uN;l3nONId1KkA!+$765barVC#i?NS$$pB11+ZC`gJ~%l{fc1 z@4Tg&7*bYOUP}T$x)qBxmDi5{RC&hx7F7KwhtqF}8%^35^Xbp0o$MWUA8eP;P$%OG z!~K^YO;hIv#ajid{Mfbm*{~%i#qd$j+&HC!7+0lubPA1zRVc+2Aj;`@U3KRoVs!~W zm_?6*9A(Hc^{vyl7>t+v3Ag??P=>l~wM~7-(U!`oe3KmEg0xTH>D0NsR9`fjMkv^F zf{n9K+Z0ZnyhuCu1R5~uO6)Zu{!Ee zHjZ(5G`T|M2_~L$+c!BvL}i}NFmGA14KlbSB87mvL4H`wMhJz27-ecxsA#r=y%&G%@_dk>(s zHiyi?+5$#u)LobHaeAD-aP6KylNoqn!@{pGL)Qe;Sai;1N-F^nz$$ zVg`jv-8}7{-TStt262Zffu$oIPj5nP(~}X*+*)dy=l;n1b!}{uH1YC8iuUfN{?cny zSN8*c5B3NL3QkUCs>SYDK4e=RJ2GM3Ib+BZogdyqJC}opr%1C+(vVYiVSt9Bx|9{G#=`ilx{OUCM&ZQS1Z&KIEk!GoL$Xcag5-(xfZBM6Na(_V!zZ_A+ z&hfE}ZC81<&g|ke^*nvEAZvlF7~{`#T6h(G4Z{A~uzH9Q^gh4*#@pta?b^FaZxbYC zt;&v{qvtBzDN!gbP`TR`T-BJ>a+xm_Oy{q^a?ps5j*O1kzNwv6EGqxRxKgjp;){k7 zY!o$;LU^?W&VKunt;AIyYNesm&@HEQ&UGCry`W + + const form = useForm({ + resolver: zodResolver(formSchema), + defaultValues: { + name: '', + age: '', + }, + }) + + return ( + + + + + + {/* {`Mask */} + 动态 IP 套餐 + 静态 IP 套餐 + +
+ 套餐编号} + className={`grid grid-cols-[70px_1fr] grid-rows-[auto_auto] `} + classNames={{ + message: `col-start-2`, + }} + > + {({ field }) => ( + + )} + +
+ 时间范围筛选} + className={`grid grid-cols-[100px_1fr] `} + classNames={{ + message: `col-start-2`, + }} + > + {({ field }) => ( + + )} + + - + + {({ field }) => ( + + )} + + +
+
+ + + + + {`coming +

敬请期待

+
+
+
+
+ ) +} \ No newline at end of file diff --git a/src/app/admin/(dashboard)/_client/pins.tsx b/src/app/admin/(dashboard)/_client/pins.tsx new file mode 100644 index 0000000..d890735 --- /dev/null +++ b/src/app/admin/(dashboard)/_client/pins.tsx @@ -0,0 +1,76 @@ +'use client' +import Image from 'next/image' +import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' +import soon from '../_assets/coming-soon.svg' +import mask from '../_assets/Mask group.webp' + + + +export default function Pins() { + + + return <> + + {/* 短效 */} + + + {`Mask 短效动态套餐 + + +
+

包时

+

+ 当日可提取数量 + todo +

+
+
+
+

包量

+

+ 剩余可提取数量 + todo +

+
+
+
+ + {/* 长效 */} + + + {`Mask 长效动态套餐 + + + {/* {`coming +

敬请期待

*/} +
+

包时

+

+ 当日可提取数量 + todo +

+
+
+
+

包量

+

+ 剩余可提取数量 + todo +

+
+
+
+ + {/* 固定 */} + + + 固定IP套餐 + + + {`coming +

敬请期待

+
+
+ +} + diff --git a/src/app/admin/(dashboard)/layout.tsx b/src/app/admin/(dashboard)/layout.tsx new file mode 100644 index 0000000..77b4d0d --- /dev/null +++ b/src/app/admin/(dashboard)/layout.tsx @@ -0,0 +1,17 @@ + +import { ReactNode } from 'react' +import { Metadata } from 'next' + +export async function generateMetadata(): Promise { + return { + title: '账户总览 - 蓝狐代理', + } +} + +export type BillsLayoutProps = { + children: ReactNode +} + +export default async function BillsLayout(props: BillsLayoutProps) { + return props.children +} \ No newline at end of file diff --git a/src/app/admin/(dashboard)/page.tsx b/src/app/admin/(dashboard)/page.tsx index c0a8a10..418e951 100644 --- a/src/app/admin/(dashboard)/page.tsx +++ b/src/app/admin/(dashboard)/page.tsx @@ -1,26 +1,24 @@ import Page from '@/components/page' import Image from 'next/image' -import {Card, CardContent, CardHeader, CardTitle} from '@/components/ui/card' -import {Tabs, TabsContent, TabsList, TabsTrigger} from '@/components/ui/tabs' -import {getProfile} from '@/actions/auth' -import {format} from 'date-fns' -import {CheckCircleIcon, CircleAlertIcon} from 'lucide-react' -import {Button, buttonVariants} from '@/components/ui/button' +import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' +import { getProfile } from '@/actions/auth' +import { format } from 'date-fns' +import { CheckCircleIcon, CircleAlertIcon } from 'lucide-react' +import { Button, buttonVariants } from '@/components/ui/button' import RechargeModal from '@/components/composites/recharge' -import {merge} from '@/lib/utils' - +import { merge } from '@/lib/utils' import banner from './_assets/banner.webp' -import soon from './_assets/coming-soon.svg' import actionBill from './_assets/action-bill.webp' import actionBuy from './_assets/action-buy.webp' import actionLogout from './_assets/action-logout.webp' import Link from 'next/link' -import {listAnnouncements} from '@/actions/announcement' -import DashboardChart from './_client/chart' +import { listAnnouncements } from '@/actions/announcement' +import Charts from './_client/charts' +import Pins from './_client/pins' export type DashboardPageProps = {} -export default async function DashboardPage(props: DashboardPageProps) { +export default function DashboardPage(props: DashboardPageProps) { return ( {/* banner */}
- {`banner + {`banner

代理IP资源,先测后买

短效/长效/固定IP代理,一站式服务

@@ -37,103 +35,21 @@ export default async function DashboardPage(props: DashboardPageProps) {
{/* 磁贴集 */} - + {/* 图表 */} - + {/* 信息 */} - + {/* 通知 */} - +
) } -async function Pins() { - return <> - {/* 短效 */} - - - 短效动态套餐 - - -
-

包时

-

- 当日可提取数量 - todo -

-
-
-
-

包量

-

- 剩余可提取数量 - todo -

-
-
-
- - {/* 长效 */} - - - 长效动态套餐 - - - {`coming -

敬请期待

-
-
- - {/* 固定 */} - - - 固定IP套餐 - - - {`coming -

敬请期待

-
-
- -} - -async function Charts() { - - const data = [ - {time: `2023-10-01`, count: 100}, - {time: `2023-10-02`, count: 50}, - {time: `2023-10-03`, count: 80}, - {time: `2023-10-04`, count: 200}, - {time: `2023-10-05`, count: 150}, - ] - - return ( - - - - - 动态 IP 套餐 - 静态 IP 套餐 - - - - - - - {`coming -

敬请期待

-
-
-
-
- ) -} - async function UserCenter() { const resp = await getProfile() @@ -160,7 +76,7 @@ async function UserCenter() { {profile.id_token ? <>
- + 已实名
@@ -170,7 +86,7 @@ async function UserCenter() { : <> - + 未实名 @@ -181,22 +97,22 @@ async function UserCenter() {

账户余额

¥{profile.balance}

- +

快捷入口

- - {`bill + + {`bill 我的帐单 - - {`buy + + {`buy 购买产品 - - {`logout + + {`logout 个人中心
@@ -225,14 +141,17 @@ async function Announcements() { return ( - 公告 +
+ 公告 + 查看更多 +
{announcements.length === 0 ? (
- {`coming -

暂无公告

+ {/* {`coming +

暂无公告

*/}
) : announcements.map(item => ( diff --git a/src/app/admin/_client/navbar.tsx b/src/app/admin/_client/navbar.tsx index c65cf27..f9411a2 100644 --- a/src/app/admin/_client/navbar.tsx +++ b/src/app/admin/_client/navbar.tsx @@ -7,9 +7,22 @@ import Image from 'next/image' import logoAvatar from '../_assets/logo-avatar.svg' import logoText from '../_assets/logo-text.svg' import {Tooltip, TooltipContent, TooltipProvider, TooltipTrigger} from '@/components/ui/tooltip' +import { UserRound } from 'lucide-react' +import { UserRoundPen } from 'lucide-react' +import { IdCard } from 'lucide-react' +import { LockKeyhole } from 'lucide-react' +import { Wallet } from 'lucide-react' +import { ShoppingCart } from 'lucide-react' +import { Package } from 'lucide-react' +import { HardDriveUpload } from 'lucide-react' +import { Eye } from 'lucide-react' +import { Archive } from 'lucide-react' +import { ArchiveRestore } from 'lucide-react' + export type NavbarProps = {} + export default function Navbar(props: NavbarProps) { const navbar = useLayoutStore(store => store.navbar) @@ -43,20 +56,20 @@ export default function Navbar(props: NavbarProps) { `group-data-[expand=true]:px-4 group-data-[expand=false]:px-3`, )}> - + } label={`账户总览`} expand={navbar}/> - - - - + } label={`个人中心`} expand={navbar}/> + } label={`实名认证`} expand={navbar}/> + } label={`白名单`} expand={navbar}/> + } label={`我的账单`} expand={navbar}/> - - + } label={`购买套餐`} expand={navbar}/> + } label={`套餐管理`} expand={navbar}/> - - - - + } label={`提取 IP`} expand={navbar}/> + } label={`IP 管理`} expand={navbar}/> + } label={`提取记录`} expand={navbar}/> + } label={`使用记录`} expand={navbar}/> diff --git a/src/app/admin/bills/layout.tsx b/src/app/admin/bills/layout.tsx new file mode 100644 index 0000000..ba3137b --- /dev/null +++ b/src/app/admin/bills/layout.tsx @@ -0,0 +1,17 @@ + +import { ReactNode } from 'react' +import { Metadata } from 'next' + +export async function generateMetadata(): Promise { + return { + title: '我的账单 - 蓝狐代理', + } +} + +export type BillsLayoutProps = { + children: ReactNode +} + +export default async function BillsLayout(props: BillsLayoutProps) { + return props.children +} \ No newline at end of file diff --git a/src/app/admin/channels/layout.tsx b/src/app/admin/channels/layout.tsx new file mode 100644 index 0000000..42e6efe --- /dev/null +++ b/src/app/admin/channels/layout.tsx @@ -0,0 +1,17 @@ + +import { ReactNode } from 'react' +import { Metadata } from 'next' + +export async function generateMetadata(): Promise { + return { + title: 'IP管理 - 蓝狐代理', + } +} + +export type ChannelsLayoutProps = { + children: ReactNode +} + +export default async function ChannelsLayout(props: ChannelsLayoutProps) { + return props.children +} \ No newline at end of file diff --git a/src/app/admin/extract/layout.tsx b/src/app/admin/extract/layout.tsx new file mode 100644 index 0000000..e7012a1 --- /dev/null +++ b/src/app/admin/extract/layout.tsx @@ -0,0 +1,17 @@ + +import { ReactNode } from 'react' +import { Metadata } from 'next' + +export async function generateMetadata(): Promise { + return { + title: '提取IP - 蓝狐代理', + } +} + +export type ExtractLayoutProps = { + children: ReactNode +} + +export default async function ExtractLayout(props: ExtractLayoutProps) { + return props.children +} \ No newline at end of file diff --git a/src/app/admin/identify/layout.tsx b/src/app/admin/identify/layout.tsx new file mode 100644 index 0000000..8a45e8a --- /dev/null +++ b/src/app/admin/identify/layout.tsx @@ -0,0 +1,16 @@ +import { ReactNode } from 'react' +import { Metadata } from 'next' + +export async function generateMetadata(): Promise { + return { + title: '实名认证 - 蓝狐代理', + } +} + +export type IdentifyLayoutProps = { + children: ReactNode +} + +export default async function IdentifyLayout(props: IdentifyLayoutProps) { + return props.children +} \ No newline at end of file diff --git a/src/app/admin/profile/layout.tsx b/src/app/admin/profile/layout.tsx new file mode 100644 index 0000000..7f365db --- /dev/null +++ b/src/app/admin/profile/layout.tsx @@ -0,0 +1,17 @@ + +import { ReactNode } from 'react' +import { Metadata } from 'next' + +export async function generateMetadata(): Promise { + return { + title: '个人中心 - 蓝狐代理', + } +} + +export type ProfileLayoutProps = { + children: ReactNode +} + +export default async function ProfileLayout(props: ProfileLayoutProps) { + return props.children +} \ No newline at end of file diff --git a/src/app/admin/purchase/layout.tsx b/src/app/admin/purchase/layout.tsx new file mode 100644 index 0000000..19fc988 --- /dev/null +++ b/src/app/admin/purchase/layout.tsx @@ -0,0 +1,17 @@ + +import { ReactNode } from 'react' +import { Metadata } from 'next' + +export async function generateMetadata(): Promise { + return { + title: '购买套餐 - 蓝狐代理', + } +} + +export type PurchaseLayoutProps = { + children: ReactNode +} + +export default async function PurchaseLayout(props: PurchaseLayoutProps) { + return props.children +} \ No newline at end of file diff --git a/src/app/admin/resources/layout.tsx b/src/app/admin/resources/layout.tsx new file mode 100644 index 0000000..4f29620 --- /dev/null +++ b/src/app/admin/resources/layout.tsx @@ -0,0 +1,17 @@ + +import { ReactNode } from 'react' +import { Metadata } from 'next' + +export async function generateMetadata(): Promise { + return { + title: '套餐管理 - 蓝狐代理', + } +} + +export type ResourcesLayoutProps = { + children: ReactNode +} + +export default async function ResourcesLayout(props: ResourcesLayoutProps) { + return props.children +} \ No newline at end of file diff --git a/src/app/admin/whitelist/layout.tsx b/src/app/admin/whitelist/layout.tsx new file mode 100644 index 0000000..e0a8593 --- /dev/null +++ b/src/app/admin/whitelist/layout.tsx @@ -0,0 +1,17 @@ + +import { ReactNode } from 'react' +import { Metadata } from 'next' + +export async function generateMetadata(): Promise { + return { + title: '白名单 - 蓝狐代理', + } +} + +export type WhitelistLayoutProps = { + children: ReactNode +} + +export default async function WhitelistLayout(props: WhitelistLayoutProps) { + return props.children +} \ No newline at end of file diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 82d3df1..2057b75 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -13,8 +13,7 @@ const font = localFont({ export async function generateMetadata(): Promise { return { - title: 'Create Next App', - description: 'Generated by create next app', + title: '蓝狐代理', } }