jingrow/components/common/ListPageTemplate.jsx

89 lines
3.7 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Image from "next/image";
import Link from "next/link";
/**
* 列表页模板组件
* @param {Object[]} items - 列表数据,需包含 title, image, content, slug 字段
* @param {string} basePath - 详情页基础路径
* @param {number} columns - 每行显示的列数默认4
*/
export default function ListPageTemplate({ items, basePath = "", columns = 4 }) {
// 静态映射,避免 Tailwind JIT 无法识别动态类名
const colClass = {
1: "lg:grid-cols-1",
2: "lg:grid-cols-2",
3: "lg:grid-cols-3",
4: "lg:grid-cols-4",
5: "lg:grid-cols-5",
6: "lg:grid-cols-6",
}[columns] || "lg:grid-cols-4";
// 摘要函数,兼容中英文
function getSummary(text, maxLen = 58) {
if (!text) return "";
if (/[-]/.test(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 + "...";
} else {
// 中文
return text.length > maxLen ? text.slice(0, maxLen) + "..." : text;
}
}
return (
<div className="w-full flex-[0_0_auto] !px-[15px] max-w-full !mx-auto">
<div className={`blog classic-view grid grid-cols-1 sm:grid-cols-2 ${colClass} gap-6`}>
{items.map((item, idx) => (
<article key={item.slug || idx} className="post !mb-8">
<div className="card">
{/* 图片部分 */}
<figure className="card-img-top overlay overlay-1 hover-scale group">
<Link href={`${basePath}/${item.slug}`} className="block relative">
{item.image && (
<Image
className="!transition-all !duration-[0.35s] !ease-in-out group-hover:scale-105 w-full h-auto"
alt={item.title || "image"}
src={item.image}
width={960}
height={600}
/>
)}
<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]">
{item.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={`${basePath}/${item.slug}`}
>
{item.title}
</Link>
</h2>
</div>
<div className="!relative !text-[0.7rem]">
<p>{getSummary(item.subtitle)}</p>
</div>
</div>
</div>
</article>
))}
</div>
</div>
);
}