feat(新闻详情页): 添加加载状态和错误处理
在新闻详情页中添加加载状态显示和错误处理逻辑 - 使用VanLoading组件显示加载状态 - 添加错误状态提示和返回按钮 - 重构数据获取逻辑,增加try-catch处理
Showing
2 changed files
with
65 additions
and
24 deletions
| ... | @@ -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,33 +57,17 @@ const router = useRouter() | ... | @@ -43,33 +57,17 @@ 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 () => { |
| 66 | + try { | ||
| 70 | const articleId = route.params.id | 67 | const articleId = route.params.id |
| 71 | const { code, data } = await getArticleDetailAPI({ i: articleId }) | 68 | const { code, data } = await getArticleDetailAPI({ i: articleId }) |
| 72 | if (code) { | 69 | if (code) { |
| 70 | + let coverImage = data.file_list.photo ? data.file_list.photo.value : '' | ||
| 73 | article.value = { | 71 | article.value = { |
| 74 | ...data, | 72 | ...data, |
| 75 | id: data.id, | 73 | id: data.id, |
| ... | @@ -77,8 +75,17 @@ onMounted(async () => { | ... | @@ -77,8 +75,17 @@ onMounted(async () => { |
| 77 | content: data.post_content, | 75 | content: data.post_content, |
| 78 | publishDate: dayjs(data.post_date).format('YYYY-MM-DD HH:mm:ss'), | 76 | publishDate: dayjs(data.post_date).format('YYYY-MM-DD HH:mm:ss'), |
| 79 | author: data.post_author, | 77 | author: data.post_author, |
| 80 | - coverImage: data.photo, | 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> | ... | ... |
-
Please register or login to post a comment