hookehuyr

feat(新闻详情页): 添加加载状态和错误处理

在新闻详情页中添加加载状态显示和错误处理逻辑
- 使用VanLoading组件显示加载状态
- 添加错误状态提示和返回按钮
- 重构数据获取逻辑,增加try-catch处理
...@@ -15,6 +15,7 @@ declare module 'vue' { ...@@ -15,6 +15,7 @@ declare module 'vue' {
15 VanCell: typeof import('vant/es')['Cell'] 15 VanCell: typeof import('vant/es')['Cell']
16 VanIcon: typeof import('vant/es')['Icon'] 16 VanIcon: typeof import('vant/es')['Icon']
17 VanList: typeof import('vant/es')['List'] 17 VanList: typeof import('vant/es')['List']
18 + VanLoading: typeof import('vant/es')['Loading']
18 VanOverlay: typeof import('vant/es')['Overlay'] 19 VanOverlay: typeof import('vant/es')['Overlay']
19 VideoPlayer: typeof import('./components/VideoPlayer.vue')['default'] 20 VideoPlayer: typeof import('./components/VideoPlayer.vue')['default']
20 } 21 }
......
1 <template> 1 <template>
2 <div class="page-container"> 2 <div class="page-container">
3 - <!-- 内容区域 --> 3 + <!-- Loading状态 -->
4 - <div class="content-container"> 4 + <div class="loading-container" v-if="isLoading">
5 + <van-loading size="24px" color="#8b4513">加载中...</van-loading>
6 + </div>
7 +
8 + <!-- 内容区域 - 只有加载完成且有数据时才显示 -->
9 + <div class="content-container" v-else-if="!isLoading && article.title">
5 <!-- 文章头部 --> 10 <!-- 文章头部 -->
6 <div class="article-header"> 11 <div class="article-header">
7 <h1 class="article-title">{{ article.title }}</h1> 12 <h1 class="article-title">{{ article.title }}</h1>
...@@ -23,6 +28,15 @@ ...@@ -23,6 +28,15 @@
23 <div class="content-text" v-html="article.content"></div> 28 <div class="content-text" v-html="article.content"></div>
24 </div> 29 </div>
25 </div> 30 </div>
31 +
32 + <!-- 加载失败或无数据时的提示 -->
33 + <div class="error-container" v-else>
34 + <div class="error-message">
35 + <van-icon name="warning-o" size="48" color="#999" />
36 + <p>文章加载失败或不存在</p>
37 + <van-button type="primary" @click="$router.go(-1)">返回</van-button>
38 + </div>
39 + </div>
26 </div> 40 </div>
27 </template> 41 </template>
28 42
...@@ -43,42 +57,35 @@ const router = useRouter() ...@@ -43,42 +57,35 @@ const router = useRouter()
43 useTitle(() => '新闻详情'); 57 useTitle(() => '新闻详情');
44 58
45 // 文章数据 59 // 文章数据
46 -const article = ref({ 60 +const article = ref({})
47 - id: 1, 61 +// 加载状态
48 - title: '三坛大戒 | 护戒胜福田 成就最上因', 62 +const isLoading = ref(true)
49 - content: `
50 - <p>为弘承世尊遗教,光大如来戒法,绍隆佛种,续佛慧命,经研究并报中国佛教协会批复同意(中佛会〔2025〕35号),由江苏省佛教协会主办,苏州市佛教协会、苏州市姑苏区佛教协会、苏州工业园区佛教协会协办,苏州西园戒幢律寺、苏州工业园区积善寺承办的传戒三坛大戒法会定于2025年10月15日至11月15日举办。</p>
51 -
52 - <h3>天增上三学,以戒为首</h3>
53 - <h3>佛灭度后,以戒为师</h3>
54 -
55 - <p>《梵网经》云:"众生受佛戒,即入诸佛位。位同大觉已,真是诸佛子。"传戒法会,具称"千佛三坛大戒法会",三坛大戒是成就僧人最重要的增上缘仪式,谓授千佛共同所制戒。戒场分非同一般之法会场所,庄妙标有,无过之者。</p>
56 -
57 - <p>今苏州西园戒幢律寺作为主戒场传戒三坛大戒,正值因时,其事庄严,此意成就道场通达。</p>
58 - `,
59 - author: '戒幢律寺编辑部',
60 - publishDate: '2025-10-1',
61 - viewCount: 2156,
62 - likeCount: 156,
63 - isLiked: false,
64 - isCollected: false,
65 - coverImage: 'https://images.unsplash.com/photo-1545558014-8692077e9b5c?w=800&h=600&fit=crop',
66 -})
67 63
68 // 组件挂载时加载数据 64 // 组件挂载时加载数据
69 onMounted(async () => { 65 onMounted(async () => {
70 - const articleId = route.params.id 66 + try {
71 - const { code, data } = await getArticleDetailAPI({ i: articleId }) 67 + const articleId = route.params.id
72 - if (code) { 68 + const { code, data } = await getArticleDetailAPI({ i: articleId })
73 - article.value = { 69 + if (code) {
74 - ...data, 70 + let coverImage = data.file_list.photo ? data.file_list.photo.value : ''
75 - id: data.id, 71 + article.value = {
76 - title: data.post_title, 72 + ...data,
77 - content: data.post_content, 73 + id: data.id,
78 - publishDate: dayjs(data.post_date).format('YYYY-MM-DD HH:mm:ss'), 74 + title: data.post_title,
79 - author: data.post_author, 75 + content: data.post_content,
80 - coverImage: data.photo, 76 + publishDate: dayjs(data.post_date).format('YYYY-MM-DD HH:mm:ss'),
77 + author: data.post_author,
78 + coverImage: coverImage,
79 + }
80 + } else {
81 + Toast.fail('加载文章失败')
81 } 82 }
83 + } catch (error) {
84 + console.error('加载文章出错:', error)
85 + Toast.fail('加载文章出错')
86 + } finally {
87 + // 无论成功还是失败,都结束loading状态
88 + isLoading.value = false
82 } 89 }
83 }) 90 })
84 </script> 91 </script>
...@@ -88,6 +95,19 @@ onMounted(async () => { ...@@ -88,6 +95,19 @@ onMounted(async () => {
88 background: #f5f5f5; 95 background: #f5f5f5;
89 } 96 }
90 97
98 +.loading-container {
99 + position: fixed;
100 + top: 0;
101 + left: 0;
102 + width: 100%;
103 + height: 100vh;
104 + display: flex;
105 + justify-content: center;
106 + align-items: center;
107 + background: #f5f5f5;
108 + z-index: 999;
109 +}
110 +
91 .content-container { 111 .content-container {
92 background-color: #F2EBDB; 112 background-color: #F2EBDB;
93 min-height: 100vh; 113 min-height: 100vh;
...@@ -171,4 +191,24 @@ onMounted(async () => { ...@@ -171,4 +191,24 @@ onMounted(async () => {
171 .content-text :deep(p:last-child) { 191 .content-text :deep(p:last-child) {
172 margin-bottom: 0; 192 margin-bottom: 0;
173 } 193 }
194 +
195 +/* 错误状态样式 */
196 +.error-container {
197 + background-color: #F2EBDB;
198 + min-height: 100vh;
199 + display: flex;
200 + align-items: center;
201 + justify-content: center;
202 +}
203 +
204 +.error-message {
205 + text-align: center;
206 + padding: 2rem;
207 +}
208 +
209 +.error-message p {
210 + margin: 1rem 0;
211 + color: #999;
212 + font-size: 1rem;
213 +}
174 </style> 214 </style>
......