refactor(mp): 迁移文章列表页 — 使用统一组件库
- PageShell 替代手写 min-height/bg/padding - ContentCard 替代手写 article-card 卡片样式 - LoadingCard 替代初始加载态 - 精简 SCSS 删除已接管样式,保留分类筛选/卡片内容布局 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1,13 +1,11 @@
|
|||||||
@import '../../styles/variables.scss';
|
@import '../../styles/variables.scss';
|
||||||
@import '../../styles/mixins.scss';
|
|
||||||
|
|
||||||
.article-page {
|
// PageShell 已接管:min-height, background, padding
|
||||||
min-height: 100vh;
|
// ContentCard 已接管:article-card 背景/圆角/阴影/触摸反馈
|
||||||
background: $bg;
|
// LoadingCard 已接管:初始加载骨架屏
|
||||||
padding: 24px;
|
// EmptyState 已接管:空状态样式
|
||||||
padding-bottom: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* ─── 分类筛选滚动条(页面特有) ─── */
|
||||||
.article-categories {
|
.article-categories {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
@@ -31,20 +29,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ─── 文章列表布局 ─── */
|
||||||
.article-list {
|
.article-list {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 20px;
|
gap: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.article-card {
|
/* ─── 文章卡片内容(ContentCard 已接管外层卡片样式) ─── */
|
||||||
display: flex;
|
|
||||||
background: $card;
|
|
||||||
border-radius: $r;
|
|
||||||
padding: 28px;
|
|
||||||
box-shadow: $shadow-sm;
|
|
||||||
}
|
|
||||||
|
|
||||||
.article-card-body {
|
.article-card-body {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -107,25 +99,3 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty-state {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
padding: 120px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.empty-text {
|
|
||||||
font-size: var(--tk-font-body-lg);
|
|
||||||
color: var(--tk-text-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading-hint {
|
|
||||||
text-align: center;
|
|
||||||
padding: 24px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading-text {
|
|
||||||
font-size: var(--tk-font-h2);
|
|
||||||
color: var(--tk-text-secondary);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,9 +3,12 @@ import { View, Text, Image, ScrollView } from '@tarojs/components';
|
|||||||
import Taro, { useReachBottom } from '@tarojs/taro';
|
import Taro, { useReachBottom } from '@tarojs/taro';
|
||||||
import { usePageData } from '@/hooks/usePageData';
|
import { usePageData } from '@/hooks/usePageData';
|
||||||
import { listArticles, listCategories, Article, ArticleCategory } from '../../services/article';
|
import { listArticles, listCategories, Article, ArticleCategory } from '../../services/article';
|
||||||
import EmptyState from '../../components/EmptyState';
|
import PageShell from '@/components/ui/PageShell';
|
||||||
import ErrorState from '../../components/ErrorState';
|
import ContentCard from '@/components/ui/ContentCard';
|
||||||
import Loading from '../../components/Loading';
|
import LoadingCard from '@/components/ui/LoadingCard';
|
||||||
|
import EmptyState from '@/components/EmptyState';
|
||||||
|
import ErrorState from '@/components/ErrorState';
|
||||||
|
import Loading from '@/components/Loading';
|
||||||
import { useElderClass } from '../../hooks/useElderClass';
|
import { useElderClass } from '../../hooks/useElderClass';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
|
||||||
@@ -73,8 +76,12 @@ export default function ArticleList() {
|
|||||||
Taro.navigateTo({ url: `/pages/article/detail/index?id=${id}` });
|
Taro.navigateTo({ url: `/pages/article/detail/index?id=${id}` });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!loading && articles.length === 0 && !error && !categories.length) {
|
||||||
|
return <LoadingCard count={3} />;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View className={`article-page ${modeClass}`}>
|
<PageShell safeBottom className={modeClass}>
|
||||||
{/* 分类筛选 */}
|
{/* 分类筛选 */}
|
||||||
{categories.length > 0 && (
|
{categories.length > 0 && (
|
||||||
<ScrollView scrollX className='article-categories'>
|
<ScrollView scrollX className='article-categories'>
|
||||||
@@ -96,47 +103,44 @@ export default function ArticleList() {
|
|||||||
</ScrollView>
|
</ScrollView>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<View className='article-list'>
|
{error ? (
|
||||||
{error ? (
|
<ErrorState onRetry={() => fetchData(1, false, null)} />
|
||||||
<ErrorState onRetry={() => fetchData(1, false, null)} />
|
) : articles.length === 0 && !loading ? (
|
||||||
) : articles.map((a) => (
|
|
||||||
<View
|
|
||||||
className='article-card'
|
|
||||||
key={a.id}
|
|
||||||
onClick={() => goToDetail(a.id)}
|
|
||||||
>
|
|
||||||
<View className='article-card-body'>
|
|
||||||
<Text className='article-card-title'>{a.title}</Text>
|
|
||||||
{a.summary && (
|
|
||||||
<Text className='article-card-summary'>{a.summary}</Text>
|
|
||||||
)}
|
|
||||||
<View className='article-card-meta'>
|
|
||||||
{(a.category_name || a.category) && (
|
|
||||||
<Text className='article-card-tag'>{a.category_name || a.category}</Text>
|
|
||||||
)}
|
|
||||||
{a.published_at && (
|
|
||||||
<Text className='article-card-date'>
|
|
||||||
{a.published_at.slice(0, 10)}
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
{a.cover_image && (
|
|
||||||
<View className='article-card-cover'>
|
|
||||||
<Image className='cover-img' src={a.cover_image} mode='aspectFill' lazyLoad />
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
))}
|
|
||||||
</View>
|
|
||||||
|
|
||||||
{articles.length === 0 && !loading && (
|
|
||||||
<EmptyState text='暂无资讯文章' />
|
<EmptyState text='暂无资讯文章' />
|
||||||
|
) : (
|
||||||
|
<View className='article-list'>
|
||||||
|
{articles.map((a) => (
|
||||||
|
<ContentCard
|
||||||
|
key={a.id}
|
||||||
|
onPress={() => goToDetail(a.id)}
|
||||||
|
>
|
||||||
|
<View className='article-card-body'>
|
||||||
|
<Text className='article-card-title'>{a.title}</Text>
|
||||||
|
{a.summary && (
|
||||||
|
<Text className='article-card-summary'>{a.summary}</Text>
|
||||||
|
)}
|
||||||
|
<View className='article-card-meta'>
|
||||||
|
{(a.category_name || a.category) && (
|
||||||
|
<Text className='article-card-tag'>{a.category_name || a.category}</Text>
|
||||||
|
)}
|
||||||
|
{a.published_at && (
|
||||||
|
<Text className='article-card-date'>
|
||||||
|
{a.published_at.slice(0, 10)}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
{a.cover_image && (
|
||||||
|
<View className='article-card-cover'>
|
||||||
|
<Image className='cover-img' src={a.cover_image} mode='aspectFill' lazyLoad />
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
</ContentCard>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{loading && (
|
{loading && <Loading />}
|
||||||
<Loading />
|
</PageShell>
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user