Skip to content

Commit e1ab9d5

Browse files
committed
使用虚拟滚动
1 parent 6fa6dd6 commit e1ab9d5

File tree

11 files changed

+320
-83
lines changed

11 files changed

+320
-83
lines changed

.vscode/settings.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
"editor.codeActionsOnSave": {
66
"source.fixAll": "explicit"
77
},
8-
"[css]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
8+
"[css]": {
9+
"editor.defaultFormatter": "esbenp.prettier-vscode"
10+
},
911
// Tailwind CSS Autocomplete, add more if used in projects
1012
"tailwindCSS.classAttributes": [
1113
"class",
@@ -14,4 +16,4 @@
1416
"containerClassName"
1517
],
1618
"typescript.preferences.importModuleSpecifier": "non-relative"
17-
}
19+
}

CHANGELOG

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## [100.1.1] - 2026-02-27
2+
3+
### Changed
4+
5+
- 搜索页使用虚拟滚动,优化滚动性能
6+
17
## [100.1.0] - 2026-02-27
28

39
### Added

VERSION.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
100.1.0
1+
100.1.1

docker-compose.dev.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
version: '3.8'
2+
3+
services:
4+
redis:
5+
image: redis:7-alpine
6+
container_name: lunatv-redis
7+
volumes:
8+
- redis-data:/data
9+
command: redis-server --appendonly yes
10+
healthcheck:
11+
test: ['CMD', 'redis-cli', 'ping']
12+
interval: 5s
13+
timeout: 3s
14+
retries: 5
15+
16+
app:
17+
build:
18+
context: .
19+
dockerfile: Dockerfile
20+
container_name: lunatv-app
21+
ports:
22+
- '3000:3000'
23+
depends_on:
24+
redis:
25+
condition: service_healthy
26+
environment:
27+
# 存储类型:使用 redis
28+
- NEXT_PUBLIC_STORAGE_TYPE=redis
29+
# Redis 连接地址(容器内通过 service name 访问)
30+
- REDIS_URL=redis://redis:6379
31+
# 站长账号
32+
- USERNAME=admin
33+
# 站长密码
34+
- PASSWORD=admin123
35+
# 站点名称(可选)
36+
- NEXT_PUBLIC_SITE_NAME=MoonTV
37+
38+
volumes:
39+
redis-data:

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"@dnd-kit/utilities": "^3.2.2",
2626
"@headlessui/react": "^2.2.4",
2727
"@heroicons/react": "^2.2.0",
28+
"@tanstack/react-virtual": "^3.13.19",
2829
"@types/crypto-js": "^4.2.2",
2930
"@upstash/redis": "^1.25.0",
3031
"@vidstack/react": "^1.12.13",

pnpm-lock.yaml

Lines changed: 19 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/dev-docker.sh

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/bin/bash
2+
# 本地构建并启动 Docker 镜像 + Redis
3+
# 用法: ./scripts/dev-docker.sh [up|down|rebuild|logs]
4+
5+
set -e
6+
7+
COMPOSE_FILE="docker-compose.dev.yml"
8+
9+
case "${1:-up}" in
10+
up)
11+
echo "🚀 构建并启动服务..."
12+
docker compose -f "$COMPOSE_FILE" up -d --build
13+
echo ""
14+
echo "✅ 服务已启动"
15+
echo " 应用: http://localhost:3000"
16+
echo " Redis: localhost:6379"
17+
echo ""
18+
echo " 默认账号: admin / admin123"
19+
echo " 查看日志: ./scripts/dev-docker.sh logs"
20+
echo " 停止服务: ./scripts/dev-docker.sh down"
21+
;;
22+
down)
23+
echo "🛑 停止并移除服务..."
24+
docker compose -f "$COMPOSE_FILE" down
25+
echo "✅ 已停止"
26+
;;
27+
rebuild)
28+
echo "🔄 重新构建并启动..."
29+
docker compose -f "$COMPOSE_FILE" down
30+
docker compose -f "$COMPOSE_FILE" up -d --build --force-recreate
31+
echo "✅ 已重新构建并启动"
32+
;;
33+
logs)
34+
docker compose -f "$COMPOSE_FILE" logs -f
35+
;;
36+
*)
37+
echo "用法: $0 [up|down|rebuild|logs]"
38+
exit 1
39+
;;
40+
esac

src/app/douban/page.tsx

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import DoubanCustomSelector from '@/components/DoubanCustomSelector';
1919
import DoubanSelector from '@/components/DoubanSelector';
2020
import PageLayout from '@/components/PageLayout';
2121
import VideoCard from '@/components/VideoCard';
22+
import VirtualGrid from '@/components/VirtualGrid';
2223

2324
function DoubanPageClient() {
2425
const searchParams = useSearchParams();
@@ -754,12 +755,18 @@ function DoubanPageClient() {
754755
{/* 内容展示区域 */}
755756
<div className='max-w-[95%] mx-auto mt-8 overflow-visible'>
756757
{/* 内容网格 */}
757-
<div className='justify-start grid grid-cols-3 gap-x-2 gap-y-12 px-0 sm:px-2 sm:grid-cols-[repeat(auto-fill,minmax(160px,1fr))] sm:gap-x-8 sm:gap-y-20'>
758-
{loading || !selectorsReady
759-
? // 显示骨架屏
760-
skeletonData.map((index) => <DoubanCardSkeleton key={index} />)
761-
: // 显示实际数据
762-
doubanData.map((item, index) => (
758+
{loading || !selectorsReady
759+
? // 显示骨架屏
760+
<div className='justify-start grid grid-cols-3 gap-x-2 gap-y-12 px-0 sm:px-2 sm:grid-cols-[repeat(auto-fill,minmax(160px,1fr))] sm:gap-x-8 sm:gap-y-20'>
761+
{skeletonData.map((index) => <DoubanCardSkeleton key={index} />)}
762+
</div>
763+
: // 显示实际数据
764+
<VirtualGrid
765+
items={doubanData}
766+
className='grid-cols-3 gap-x-2 px-0 sm:px-2 sm:grid-cols-[repeat(auto-fill,minmax(160px,1fr))] sm:gap-x-8'
767+
rowGapClass='pb-12 sm:pb-20'
768+
estimateRowHeight={320}
769+
renderItem={(item, index) => (
763770
<div key={`${item.title}-${index}`} className='w-full'>
764771
<VideoCard
765772
from='douban'
@@ -774,8 +781,9 @@ function DoubanPageClient() {
774781
}
775782
/>
776783
</div>
777-
))}
778-
</div>
784+
)}
785+
/>
786+
}
779787

780788
{/* 加载更多指示器 */}
781789
{hasMore && !loading && (

0 commit comments

Comments
 (0)