diff --git a/app/api/get-listview-data/route.js b/app/api/get-listview-data/route.js
index a00085d..ef1cb8e 100644
--- a/app/api/get-listview-data/route.js
+++ b/app/api/get-listview-data/route.js
@@ -6,12 +6,14 @@ export async function GET(request) {
try {
const { searchParams } = new URL(request.url);
const pagetype = searchParams.get('pagetype');
+ const category = searchParams.get('category');
+ const count = searchParams.get('count');
if (!pagetype) {
return Response.json({ error: '缺少pagetype参数' }, { status: 400 });
}
const response = await axios.get(
`${JINGROW_SERVER_URL}/api/method/jsite.api.v1.get_listview_data`,
- { params: { pagetype } }
+ { params: { pagetype, category, count } }
);
const data = response.data.message?.data || [];
return Response.json({ data });
diff --git a/app/page.jsx b/app/page.jsx
index 6be8ba1..22c0562 100644
--- a/app/page.jsx
+++ b/app/page.jsx
@@ -2,6 +2,7 @@ import Faqs from "@/components/homes/home-15/Faqs";
import Gallery from "@/components/homes/home-15/Gallery";
import Features from "@/components/homes/home-15/Features";
import Hero from "@/components/homes/home-15/Hero";
+import PageItems from "@/components/homes/home-15/PageItems";
import CategoryItems from "@/components/homes/home-15/CategoryItems";
import React from "react";
import { getSiteSettings } from "@/utlis/siteSettings";
@@ -40,7 +41,8 @@ export default function Page() {
>
diff --git a/components/homes/home-15/CategoryItems.jsx b/components/homes/home-15/CategoryItems.jsx
index 512d919..a4edce8 100644
--- a/components/homes/home-15/CategoryItems.jsx
+++ b/components/homes/home-15/CategoryItems.jsx
@@ -4,11 +4,12 @@ import { Swiper, SwiperSlide } from "swiper/react";
import { Navigation, Pagination } from "swiper/modules";
import Link from "next/link";
import Image from "next/image";
+import PropTypes from "prop-types";
const PAGE_SIZE = 8; // 每页8条,4列2行
const PAGE_SLUG = "case"; // 博客slug常量
-export default function CategoryItems() {
+export default function CategoryItems({ pagetype = "", category = "", count = undefined }) {
const [posts, setPosts] = useState([]);
const [currentPage, setCurrentPage] = useState(1);
const [totalPages, setTotalPages] = useState(1);
@@ -18,15 +19,16 @@ export default function CategoryItems() {
async function fetchData() {
setLoading(true);
try {
- const res = await fetch("/api/get-page-data", {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({ slug_list: [PAGE_SLUG], page: currentPage, page_size: PAGE_SIZE }),
- });
+ const params = new URLSearchParams({ pagetype });
+ if (category) params.append("category", category);
+ if (count !== undefined && count !== null) params.append("count", count);
+ params.append("page", currentPage);
+ params.append("page_size", PAGE_SIZE);
+ const res = await fetch(`/api/get-listview-data?${params.toString()}`);
const json = await res.json();
if (Array.isArray(json.data)) {
setPosts(json.data);
- setTotalPages(Math.ceil((json.total || 0) / PAGE_SIZE));
+ setTotalPages(Math.ceil((json.total || json.data.length || 0) / PAGE_SIZE));
} else {
setPosts([]);
setTotalPages(1);
@@ -38,7 +40,7 @@ export default function CategoryItems() {
setLoading(false);
}
fetchData();
- }, [currentPage]);
+ }, [currentPage, pagetype, category, count]);
// 分页控件
function PaginationComp() {
@@ -171,7 +173,7 @@ export default function CategoryItems() {
@@ -229,3 +231,12 @@ export default function CategoryItems() {
);
}
+
+CategoryItems.propTypes = {
+ pagetype: PropTypes.string,
+ category: PropTypes.string,
+ count: PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.number
+ ]),
+};
diff --git a/components/homes/home-15/PageItems.jsx b/components/homes/home-15/PageItems.jsx
new file mode 100644
index 0000000..142079f
--- /dev/null
+++ b/components/homes/home-15/PageItems.jsx
@@ -0,0 +1,240 @@
+"use client";
+import { useEffect, useState } from "react";
+import { Swiper, SwiperSlide } from "swiper/react";
+import { Navigation, Pagination } from "swiper/modules";
+import Link from "next/link";
+import Image from "next/image";
+
+export default function PageItems({ page_slug = "", page_size = 8, columns = 4 }) {
+ const [posts, setPosts] = useState([]);
+ const [currentPage, setCurrentPage] = useState(1);
+ const [totalPages, setTotalPages] = useState(1);
+ const [loading, setLoading] = useState(false);
+
+ // 静态映射,避免 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";
+
+ useEffect(() => {
+ async function fetchData() {
+ setLoading(true);
+ try {
+ const res = await fetch("/api/get-page-data", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ slug_list: [page_slug], page: currentPage, page_size }),
+ });
+ const json = await res.json();
+ if (Array.isArray(json.data)) {
+ setPosts(json.data);
+ setTotalPages(Math.ceil((json.total || 0) / page_size));
+ } else {
+ setPosts([]);
+ setTotalPages(1);
+ }
+ } catch (e) {
+ setPosts([]);
+ setTotalPages(1);
+ }
+ setLoading(false);
+ }
+ fetchData();
+ }, [currentPage, page_slug, page_size]);
+
+ // 分页控件
+ function PaginationComp() {
+ if (totalPages <= 1) return null;
+ return (
+
+ );
+ }
+
+ // 渲染卡片内容(只返回图片部分,结构在下方article里)
+ function renderCardImage(post, idx) {
+ // 多图轮播
+ if (Array.isArray(post.images) && post.images.length > 1) {
+ return (
+
+ {post.images.map((img, i) => (
+
+
+
+ ))}
+
+ );
+ }
+ // 视频
+ if (post.video_src || post.videoId) {
+ if (post.video_src && (post.video_src.endsWith('.mp4') || post.video_src.startsWith('/files/'))) {
+ return (
+
+ );
+ }
+ const vid = post.videoId || (post.video_src && post.video_src.includes('youtube') ? post.video_src.split('embed/')[1] : null);
+ if (vid) {
+ return (
+
+ );
+ }
+ }
+ // 单图
+ const img = post.image || (Array.isArray(post.images) && post.images[0]);
+ if (img) {
+ return (
+
+ );
+ }
+ return null;
+ }
+
+ function getSummary(text, maxLen = 100) {
+ 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 + "...";
+ }
+
+ return (
+
+
+ {loading ? (
+
加载中...
+ ) : posts.length === 0 ? (
+
暂无数据
+ ) : (
+ posts.map((post, idx) => (
+
+
+ {/* 图片/轮播/视频部分 */}
+
+
+ {renderCardImage(post, idx)}
+
+
+
+ 查看详情
+
+
+
+
+ {/* 文字内容 */}
+
+
+
+
+
+ {post.title}
+
+
+
+
+
{getSummary(post.subtitle)}
+
+
+ {/* 底部信息 */}
+
+
+
+ ))
+ )}
+
+
+
+ );
+}