138 lines
5.5 KiB
JavaScript
138 lines
5.5 KiB
JavaScript
import Link from "next/link";
|
|
import Image from "next/image";
|
|
import { fetchComponentData, fetchListViewData } from "@/utils/data";
|
|
|
|
// 渲染卡片内容
|
|
function renderCardImage(post) {
|
|
// 视频
|
|
if (post.video_src || post.videoId) {
|
|
if (post.video_src && (post.video_src.endsWith('.mp4') || post.video_src.startsWith('/files/'))) {
|
|
return (
|
|
<video controls className="w-full h-56 rounded-xl object-cover">
|
|
<source src={post.video_src} type="video/mp4" />
|
|
您的浏览器不支持视频播放。
|
|
</video>
|
|
);
|
|
}
|
|
const vid = post.videoId || (post.video_src && post.video_src.includes('youtube') ? post.video_src.split('embed/')[1] : null);
|
|
if (vid) {
|
|
return (
|
|
<iframe
|
|
className="w-full h-56 rounded-xl"
|
|
src={`https://www.youtube.com/embed/${vid}`}
|
|
title="YouTube video"
|
|
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
|
allowFullScreen
|
|
/>
|
|
);
|
|
}
|
|
}
|
|
// 单图
|
|
const img = post.image || (Array.isArray(post.images) && post.images[0]);
|
|
if (img) {
|
|
return (
|
|
<Image
|
|
className="!transition-all !duration-[0.35s] !ease-in-out group-hover:scale-105 w-full h-auto"
|
|
alt={post.title || "image"}
|
|
src={img}
|
|
width={960}
|
|
height={600}
|
|
/>
|
|
);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function getSummary(text, maxLen = 58) {
|
|
if (!text) return "";
|
|
if (/[\u4e00-\u9fa5]/.test(text)) {
|
|
return text.length > maxLen ? text.slice(0, maxLen) + "..." : text;
|
|
}
|
|
if (text.length <= maxLen) return text;
|
|
let cut = text.slice(0, maxLen);
|
|
if (!/\s/.test(text[maxLen])) {
|
|
const lastSpace = cut.lastIndexOf(" ");
|
|
if (lastSpace > 0) cut = cut.slice(0, lastSpace);
|
|
}
|
|
return cut + "...";
|
|
}
|
|
|
|
export default async function CategoryItems() {
|
|
// 获取数据
|
|
const componentDataResult = await fetchComponentData("CategoryItems");
|
|
const data = componentDataResult.data;
|
|
|
|
let posts = [];
|
|
if (data) {
|
|
const { t1: pagetype, t2: category, t4: count } = data;
|
|
const postsResult = await fetchListViewData({ pagetype, category, count });
|
|
posts = postsResult.data || [];
|
|
}
|
|
|
|
if (!data) {
|
|
return null;
|
|
}
|
|
|
|
// 从组件数据中提取字段
|
|
const { title, subtitle, t3: category_slug, t5: columns, button_text } = data;
|
|
|
|
return (
|
|
<div className="xl:w-10/12 lg:w-10/12 w-full flex-[0_0_auto] !px-[15px] max-w-full !mx-auto">
|
|
{(title || subtitle) && (
|
|
<div className="relative z-20 text-center mb-10 select-text">
|
|
{title && <h2 className="text-3xl font-bold mb-2">{title}</h2>}
|
|
{subtitle && <p className="text-lg text-gray-500">{subtitle}</p>}
|
|
</div>
|
|
)}
|
|
<div className={`blog classic-view grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-${columns || 4} gap-6`}>
|
|
{posts.length === 0 ? (
|
|
<div className={`col-span-${columns || 4} text-center py-12 text-gray-400`}>暂无数据</div>
|
|
) : (
|
|
posts.map((post, idx) => (
|
|
<article key={post.slug || post.id || idx} className="post !mb-8">
|
|
<div className="card">
|
|
<figure className="card-img-top overlay overlay-1 hover-scale group">
|
|
<Link href={post.slug ? `/${category_slug}/${post.slug}` : "#"} className="block relative">
|
|
{renderCardImage(post)}
|
|
<span className="bg"></span>
|
|
<figcaption className="group-hover:opacity-100 absolute w-full h-full opacity-0 text-center px-4 py-3 inset-0 z-[5] pointer-events-none p-2">
|
|
<h5 className="from-top !mb-0 absolute w-full translate-y-[-80%] p-[.75rem_1rem] left-0 top-2/4">
|
|
查看详情
|
|
</h5>
|
|
</figcaption>
|
|
</Link>
|
|
</figure>
|
|
<div className="card-body flex-[1_1_auto] p-[40px] xl:!p-[2rem_2.5rem_1.25rem] lg:!p-[2rem_2.5rem_1.25rem] md:!p-[2rem_2.5rem_1.25rem] max-md:pb-4">
|
|
<div className="post-header !mb-[.9rem]">
|
|
<div className="inline-flex !mb-[.4rem] uppercase !tracking-[0.02rem] text-[0.7rem] font-bold !text-[#aab0bc] relative align-top !pl-[1.4rem] before:content-[''] before:absolute before:inline-block before:translate-y-[-60%] before:w-3 before:h-[0.05rem] before:left-0 before:top-2/4 before:bg-[#1fc76f]">
|
|
{post.additional_title}
|
|
</div>
|
|
<h2 className="post-title !mt-1 !leading-[1.35] !mb-0 text-base md:!text-[0.85rem]">
|
|
<Link className="!text-[#333333] hover:!text-[#1fc76f]" href={post.slug ? `/${category_slug}/${post.slug}` : "#"}>
|
|
{post.title}
|
|
</Link>
|
|
</h2>
|
|
</div>
|
|
<div className="!relative !text-[0.7rem]">
|
|
<p>{getSummary(post.subtitle)}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</article>
|
|
))
|
|
)}
|
|
</div>
|
|
{category_slug && (
|
|
<div className="text-center mt-8">
|
|
<a
|
|
href={`/${category_slug}`}
|
|
className="btn btn-lg btn-fuchsia !text-white !bg-[#1A1A1A] hover:text-white hover:bg-[#1A1A1A] hover:!border-[#1A1A1A] active:text-white active:bg-[#1A1A1A] active:border-[#1A1A1A] disabled:text-white disabled:bg-[#1A1A1A] disabled:border-[#1A1A1A] !rounded-[0.8rem] mx-1"
|
|
>
|
|
{button_text || "更多"}
|
|
</a>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|