大改动

This commit is contained in:
宇阳
2024-08-23 14:09:08 +08:00
parent f2b24e95f4
commit e2be9aeb3f
14 changed files with 410 additions and 7 deletions

7
package-lock.json generated
View File

@@ -8,6 +8,7 @@
"name": "thrive",
"version": "0.1.0",
"dependencies": {
"dayjs": "^1.11.13",
"next": "14.2.5",
"react": "^18",
"react-dom": "^18",
@@ -556,6 +557,12 @@
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"dev": true
},
"node_modules/dayjs": {
"version": "1.11.13",
"resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz",
"integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==",
"license": "MIT"
},
"node_modules/didyoumean": {
"version": "1.2.2",
"resolved": "https://registry.npmmirror.com/didyoumean/-/didyoumean-1.2.2.tgz",

View File

@@ -9,6 +9,7 @@
"lint": "next lint"
},
"dependencies": {
"dayjs": "^1.11.13",
"next": "14.2.5",
"react": "^18",
"react-dom": "^18",

View File

@@ -1,6 +1,9 @@
import Swiper from "@/components/Swiper";
import Typed from "@/components/Typed";
import Starry from "@/components/Starry"
import Container from "@/components/Container";
import ArticleLayout from "@/components/ArticleLayout";
import Sidebar from "@/components/Sidebar";
export default function Home() {
return (
@@ -11,6 +14,13 @@ export default function Home() {
{/* 打字机组件 */}
<Typed className="absolute top-[40%] left-[50%] transform -translate-x-1/2 w-[80%] text-center text-white text-[30px] custom_text_shadow"></Typed>
</Swiper>
<Container>
{/* 文章列表 */}
<ArticleLayout />
{/* 侧边栏 */}
<Sidebar />
</Container>
</>
);
}

View File

@@ -0,0 +1,145 @@
@import "@/styles/var.scss";
.ClassicsComponent {
.classics {
// 文章列表
.item {
position: relative;
overflow: hidden;
display: flex;
height: 230px;
margin-bottom: 15px;
background-color: #333;
@include container;
// 文章封面
.cover {
position: relative;
width: 45%;
background: url("") no-repeat center;
background-size: cover;
transition: all $move;
transform: scale(1);
clip-path: polygon(0 0, 100% 0, 90% 100%, 0 100%);
z-index: 1;
&:hover {
transform: scale(1.2);
transition: all $move;
}
}
// 文章信息
.info {
position: relative;
width: 65%;
padding: 20px 40px;
z-index: 2;
.link {
display: flex;
flex-direction: column;
justify-content: space-between;
height: 100%;
// 文章标题
h3 {
position: relative;
width: 100%;
padding-top: 10px;
padding-bottom: 20px;
color: #fff;
font-size: 25px;
// 防止超长文本 溢出
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
// 文章简述
p {
color: #dfdfdf;
font-size: 15px;
line-height: 30px;
text-indent: 2em;
// 多行文本溢出
display: -webkit-box !important;
overflow: hidden;
word-break: break-all;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
}
.fun {
display: flex;
padding-top: 20px;
text-align: end;
.fun_item {
display: flex;
align-items: center;
padding-left: 30px;
font-size: 12px;
color: #ffffff;
span:nth-of-type(1) {
padding-right: 5px;
}
svg {
padding: 4px;
margin-top: -2px;
margin-right: 3px;
font-size: 23px;
color: #fff;
border-radius: 50%;
vertical-align: middle;
}
&:nth-child(1) svg {
background-color: #539dfd;
}
&:nth-child(2) svg {
margin-right: 0;
background-color: #eb373a;
}
&:nth-child(3) svg {
background-color: #f5a630;
}
}
}
.start {
justify-content: start;
}
.end {
justify-content: end;
}
}
}
// 背景虚化
.bg {
position: absolute;
width: 100%;
height: 250px;
background-position-x: center;
background-position-y: center;
background-size: cover;
filter: blur(2.5rem) brightness(0.6);
}
}
// 最后一个文章取消下边距
& .item:last-of-type {
margin-bottom: 0;
}
}
}

View File

@@ -0,0 +1,95 @@
import React, { useEffect, useState } from 'react';
import dayjs from 'dayjs';
import Link from 'next/link';
import { randomImage } from '@/utils';
// import Empty from '@/components/Empty';
// import Pagination from '@/components/Pagination';
import { Article } from '@/types/app/article';
import "./index.scss"
import { RiFireLine } from "react-icons/ri";
import { IoTimeOutline } from "react-icons/io5";
import { GoTag } from "react-icons/go";
interface ClassicsProps {
data: Paginate<Article[]>;
}
const Classics: React.FC<ClassicsProps> = ({ data }) => {
// const [paginate, setPaginate] = useState<Page>({ page: data.page, size: data.size });
// useEffect(() => {
// if (data) onGet({ page: paginate.page, size: paginate.size });
// }, [paginate, data, onGet]);
if (!data) {
return null;
}
return (
<div className='ClassicsComponent'>
<div className="classics">
{data?.result.map((item, index) => (
<div className="item" key={item.id}>
{index % 2 === 0 && (
<div
className="cover"
style={{ backgroundImage: `url(${item.cover || randomImage()})` }}
/>
)}
<div className="info">
<Link href={`/article/${item.id}`} className='link'>
<h3>{item.title}</h3>
<p>{item.description}</p>
<div className={`fun ${index % 2 === 0 ? 'end' : 'start'}`}>
<div className='fun_item'>
<span><IoTimeOutline /></span>
<span>{dayjs(+item.createTime!).format('YYYY-MM-DD')}</span>
</div>
<div className='fun_item'>
<span><RiFireLine /></span>
<span>{item.view}</span>
</div>
<div className='fun_item'>
<span><GoTag /></span>
<span>{item.cateList[0]?.name}</span>
</div>
</div>
</Link>
</div>
<div
className="bg"
style={{ backgroundImage: `url(${item.cover || randomImage()})` }}
/>
{index % 2 !== 0 && (
<div
className="cover"
style={{
clipPath: 'polygon(10% 0, 100% 0, 100% 100%, 0 100%)',
backgroundImage: `url(${item.cover || randomImage()})`,
}}
/>
)}
</div>
))}
{/* {!data.total && <Empty info="暂无文章" />} */}
{/* {data.total >= 5 && (
<Pagination
paginate={paginate}
onChange={(newPaginate) => setPaginate(newPaginate)}
/>
)} */}
</div>
</div>
);
};
export default Classics;

View File

@@ -0,0 +1,12 @@
import Classics from "./Classics"
import Request from '@/utils/request'
export default async () => {
const { data } = await Request("/article")
return (
<>
<Classics data={data}></Classics>
</>
)
}

View File

@@ -0,0 +1,26 @@
.ContainerComponent {
.main {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
padding: 20px;
margin: 0 auto;
.left {
margin: 0 auto;
transition: width $move;
}
.right {
width: 24%;
border-radius: $round;
transition: width $move;
// 粘性定位
.sticky {
position: sticky;
top: 70px;
}
}
}
}

View File

@@ -0,0 +1,11 @@
export default ({ children }: { children: React.ReactNode }) => {
return (
<>
<div className="ContainerComponent">
<div className="main w-[1200px]">
{children}
</div>
</div>
</>
)
}

View File

@@ -1,24 +1,23 @@
"use client"
import React, { useState, useEffect } from 'react';
import Link from 'next/link';
import React, { useState, useEffect } from 'react';
import Request from '@/utils/request';
import Show from '@/components/Show'
import lightLogo from '@/assets/image/light_logo.png';
import darkLogo from '@/assets/image/dark_logo.png';
import "./index.scss"
import { IoIosArrowDown } from 'react-icons/io';
import { Cate } from '@/types/app/cate';
import Show from '@/components/Show'
import "./index.scss"
const Header = () => {
const [isScrolled, setIsScrolled] = useState(false);
const [cateList, setCateList] = useState<Cate[]>([])
const getCateList = async () => {
const res = await fetch("http://localhost:9999/api/cate/all")
const { data } = await res.json()
const { data } = await Request("/cate/all")
console.log(data);
setCateList(data)
}

View File

@@ -0,0 +1,9 @@
export default () => {
return (
<>
<div>
<h1>Hello World!</h1>
</div>
</>
)
}

View File

@@ -3,6 +3,18 @@ body {
background-color: #f9f9f9;
}
// 滚动条轨道
::-webkit-scrollbar-track {
border-radius: 5px;
background-color: #f5f5f5;
}
// 进度条颜色
::-webkit-scrollbar-thumb {
background-color: #d4d4d4;
}
// 文字阴影
.custom_text_shadow {
text-shadow: 0 0.1875rem 0.3125rem #1c1f21;
}

View File

@@ -12,4 +12,47 @@ $move: 0.3s;
$round: 5px;
// 阴影效果
$boxShadow: 0 2px 8px rgba(186, 186, 186, 0.15);
$boxShadow: 0 2px 8px rgba(186, 186, 186, 0.15);
// 文字效果
$fontSty: PingFang SC, "Hiragino Sans GB", "Microsoft JhengHei", "Microsoft YaHei", sans-serif; //文章列表字体
// 文本标题
$textColor: var(--textColor, #333);
// 边框
$borderColor: var(--borderColor, #eee);
// 下边框
$underBorderColor: var(--underBorderColor, #eee);
// 阴影
$shadeColor: var(--shadeColor, 0 2px 8px rgba(186, 186, 186, 0.15));
// 封装CSS容器样式
@mixin container {
border-radius: $round;
border: 1px solid $borderColor;
transition: all $move;
&:hover {
box-shadow: $shadeColor;
}
}
// 封装右侧模块标题样式
@mixin titleRight {
.title {
display: flex;
justify-content: center;
align-items: center;
padding-bottom: 15px;
border-bottom: 1px solid $underBorderColor;
font-size: 17px;
font-weight: 400;
color: $textColor;
transition: all $move;
img {
width: 30px;
height: 20px;
}
}
}

27
src/utils/index.ts Normal file
View File

@@ -0,0 +1,27 @@
// 生成随机数
export function getRandom(min: number, max: number): number {
return Math.floor(Math.random() * (max - min + 1) + min);
}
// 随机预览图
export function randomImage() {
const covers = [
"https://bu.dusays.com/2023/11/10/654e2da1d80f8.jpg",
"https://bu.dusays.com/2023/11/10/654e2d719d31c.jpg",
"https://bu.dusays.com/2023/11/10/654e2cf92cd45.jpg",
"https://bu.dusays.com/2023/11/10/654e2cf6055b0.jpg",
"https://bu.dusays.com/2023/11/10/654e2db0889fe.jpg",
"https://bu.dusays.com/2023/11/10/654e2d50015a9.jpg",
"https://bu.dusays.com/2023/11/05/65473848ed863.jpg",
"https://bu.dusays.com/2023/11/10/654e2c870e280.jpg",
"https://bu.dusays.com/2023/11/10/654e2c717eb73.jpg",
"https://bu.dusays.com/2023/11/10/654e2c5d75d5b.jpg",
"https://bu.dusays.com/2023/11/10/654e2da27801e.jpg",
"https://bu.dusays.com/2023/11/10/654e2d2a67517.jpg",
"https://bu.dusays.com/2023/11/10/654e2cf47f17a.jpg",
"https://bu.dusays.com/2023/11/05/65473848ed863.jpg"
];
return covers[getRandom(0, covers.length - 1)];
}

6
src/utils/request.ts Normal file
View File

@@ -0,0 +1,6 @@
const url = "http://localhost:9999/api"
export default async (api: string) => {
const res = await fetch(`${url}${api}`)
return res.json()
}