调整前端目录结构
This commit is contained in:
26
tone-page-web/app/(with-header-footer)/blog/page.tsx
Normal file
26
tone-page-web/app/(with-header-footer)/blog/page.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import { useCallback } from "react"
|
||||
|
||||
export default function Blog() {
|
||||
const formatNumber = useCallback((num: number) => {
|
||||
if (num >= 1000) {
|
||||
return (num / 1000).toFixed(1) + 'K';
|
||||
} else if (num >= 1000000) {
|
||||
return (num / 1000000).toFixed(1) + 'M';
|
||||
}
|
||||
return num.toString();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="max-w-120 w-auto mx-auto my-10 flex flex-col gap-8">
|
||||
{
|
||||
Array.from({ length: 10 }).map(() => (
|
||||
<div className="w-full px-5 cursor-default" key={Math.random()}>
|
||||
<a className="text-2xl font-medium cursor-pointer" target="_black">标题标题标题标题标题标题</a>
|
||||
<p className="text-sm font-medium text-zinc-400">描述描asdjkasdas 就叫你健康你健康呢即可述描述描述描述描述描述描述描述描述,描述描述</p>
|
||||
<p className="text-sm font-medium text-zinc-400 mt-3">{new Date().toLocaleString()} · {formatNumber(1090)} 次访问</p>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
18
tone-page-web/app/(with-header-footer)/layout.tsx
Normal file
18
tone-page-web/app/(with-header-footer)/layout.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import Header from "../components/Header";
|
||||
import Footer from "../components/Footer";
|
||||
|
||||
export default function LayoutWithHeaderFooter({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
<Header />
|
||||
<main className="flex-1 flex flex-col bg-zinc-50">
|
||||
{children}
|
||||
</main>
|
||||
<Footer />
|
||||
</>
|
||||
)
|
||||
}
|
||||
25
tone-page-web/app/(with-header-footer)/page.tsx
Normal file
25
tone-page-web/app/(with-header-footer)/page.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
'use client';
|
||||
import favicon from '../favicon.ico';
|
||||
import Image from 'next/image';
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div className="w-full flex-1 flex flex-col items-center justify-center">
|
||||
<Image
|
||||
src={favicon.src}
|
||||
alt="TONE's avatar"
|
||||
width={180}
|
||||
height={180}
|
||||
className="rounded-full duration-400 size-35 md:size-45 select-none"
|
||||
priority
|
||||
quality={100}
|
||||
/>
|
||||
<h1 className='text-4xl md:text-5xl font-bold mt-5 md:mt-8 gradient-title duration-400 select-none'>特恩(TONE)</h1>
|
||||
<h2 className='text-lg sm:text-xl md:text-2xl mt-3 font-medium text-zinc-400 duration-400 select-none'>一名啥都会一点点的程序员</h2>
|
||||
<div className='flex sm:flex-row flex-col gap-2 sm:gap-10 mt-5 md:mt-8 duration-400'>
|
||||
<a href='https://space.bilibili.com/474156211' target='_black' className='bg-[#488fe9] hover:bg-[#3972ba] text-center text-white w-45 sm:w-32 px-6 py-2 text-lg rounded-full cursor-pointer'>哔哩哔哩</a>
|
||||
<a href='https://github.com/tonecn' className='bg-[#da843f] hover:bg-[#c87d3e] text-center text-white w-45 sm:w-32 px-6 py-2 text-lg rounded-full cursor-pointer'>GitHub</a>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import { Resource } from "@/lib/types/resource";
|
||||
import Image from "next/image";
|
||||
|
||||
interface ResourceCardProps {
|
||||
resource: Resource;
|
||||
key: string;
|
||||
}
|
||||
|
||||
export function ResourceCard({ resource, key }: ResourceCardProps) {
|
||||
return (
|
||||
<a href={resource.link} target="_blank" key={key}>
|
||||
<Card className="w-full md:w-92 lg:w-100 md:rounded-xl rounded-none duration-300">
|
||||
<CardContent>
|
||||
<div className="flex gap-6">
|
||||
<div>
|
||||
<Image
|
||||
src={resource.imageUrl}
|
||||
alt="资源图片"
|
||||
width={90}
|
||||
height={90}
|
||||
className="rounded-md shadow"
|
||||
priority
|
||||
quality={100}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1 overflow-x-hidden">
|
||||
<div className="font-bold text-2xl">{resource.title}</div>
|
||||
<div className="font-medium text-sm text-zinc-400 mt-1">{resource.description}</div>
|
||||
<div className="flex gap-2 flex-wrap mt-4">
|
||||
{
|
||||
resource.tags.map((tag) => (
|
||||
<div
|
||||
id={tag.id}
|
||||
className="text-[10px] text-zinc-500 font-medium py-[1px] px-1.5 rounded-full bg-zinc-200"
|
||||
style={{ backgroundColor: tag.color }}
|
||||
>{tag.name}</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</a>
|
||||
)
|
||||
}
|
||||
30
tone-page-web/app/(with-header-footer)/resource/page.tsx
Normal file
30
tone-page-web/app/(with-header-footer)/resource/page.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import { ResourceCard } from "./components/ResourceCard";
|
||||
|
||||
export default function Resources() {
|
||||
return (
|
||||
<div className="flex-1 flex flex-col items-center">
|
||||
<h1 className="mt-6 md:mt-20 text-2xl md:text-5xl font-medium text-zinc-600 text-center duration-300">精心挑选并收藏的资源</h1>
|
||||
<p className="mt-4 md:mt-8 mx-3 text-zinc-400 text-sm text-center duration-300">请在浏览此部分内容前阅读并同意
|
||||
<a className="text-zinc-600">《使用条款和隐私政策》</a>
|
||||
,继续使用或浏览表示您接受协议条款。</p>
|
||||
|
||||
<div className="mt-6 sm:mt-10 md:mt-15 w-full flex flex-col md:w-auto md:mx-auto md:grid grid-cols-2 2xl:gap-x-35 lg:gap-x-20 gap-x-10 lg:gap-y-10 gap-y-5 sm:mb-10 duration-300">
|
||||
<ResourceCard
|
||||
key="1"
|
||||
resource={{
|
||||
id: Math.random().toString(),
|
||||
title: "Adobe全家桶",
|
||||
description: "包含了macOS、Windows操作系统的Adobe全系列软件",
|
||||
imageUrl: "",
|
||||
link: "https://bing.com",
|
||||
tags: [
|
||||
{ id: "1", name: "第三方来源", color: "" },
|
||||
{ id: "2", name: "macOS", color: "#dbedfd" },
|
||||
{ id: "3", name: "Windows", color: "#dbedfd" },
|
||||
],
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user