121 lines
4.4 KiB
Vue
121 lines
4.4 KiB
Vue
<script setup lang="ts">
|
||
import { ref } from "vue";
|
||
import { onLoad } from "@dcloudio/uni-app";
|
||
import { appApi, type HelpArticleDetailData } from "../../api/app";
|
||
import { helpArticleDetailFallback } from "../../mocks/app";
|
||
import { resolveErrorMessage } from "../../utils/feedback";
|
||
|
||
const detail = ref<HelpArticleDetailData>(helpArticleDetailFallback);
|
||
const articleId = ref(0);
|
||
const loading = ref(false);
|
||
const pageReady = ref(false);
|
||
const loadError = ref("");
|
||
|
||
function openArticle(id: number) {
|
||
uni.redirectTo({ url: `/pages/help/detail?id=${id}` });
|
||
}
|
||
|
||
function contactSupport() {
|
||
uni.navigateTo({ url: "/pages/support/index" });
|
||
}
|
||
|
||
onLoad(async (options) => {
|
||
articleId.value = Number(options?.id || 0);
|
||
if (!articleId.value) {
|
||
loadError.value = "缺少文章编号,无法查看内容。";
|
||
return;
|
||
}
|
||
|
||
loading.value = true;
|
||
try {
|
||
detail.value = await appApi.getHelpArticleDetail(articleId.value);
|
||
pageReady.value = true;
|
||
} catch (error) {
|
||
console.warn("help article fallback", error);
|
||
loadError.value = resolveErrorMessage(error, "帮助文章加载失败,请稍后重试。");
|
||
} finally {
|
||
loading.value = false;
|
||
}
|
||
});
|
||
</script>
|
||
|
||
<template>
|
||
<view class="app-page app-page--tight">
|
||
<view v-if="!pageReady && loading" class="section notice-card">
|
||
<view class="notice-card__title">正在加载文章</view>
|
||
<view class="notice-card__desc">请稍候,我们正在同步文章正文与相关问题。</view>
|
||
</view>
|
||
|
||
<view v-else-if="!pageReady && loadError" class="section notice-card">
|
||
<view class="notice-card__title">帮助文章加载失败</view>
|
||
<view class="notice-card__desc">{{ loadError }}</view>
|
||
</view>
|
||
|
||
<template v-else>
|
||
<view class="section-card section-card--soft">
|
||
<view style="display: flex; align-items: center; gap: 12rpx; flex-wrap: wrap">
|
||
<text class="tag tag--accent">{{ detail.article.category_text }}</text>
|
||
<text v-if="detail.article.is_recommended" class="tag tag--warning">推荐阅读</text>
|
||
<text class="certificate-meta-chip">{{ detail.article.updated_at }}</text>
|
||
</view>
|
||
<view class="page-title" style="margin-top: 20rpx; font-size: var(--font-size-2xl); color: var(--color-heading);">
|
||
{{ detail.article.title }}
|
||
</view>
|
||
<view class="section__desc">{{ detail.article.summary }}</view>
|
||
<view class="chip-list">
|
||
<view v-for="item in detail.article.keywords" :key="item" class="choice-chip">
|
||
{{ item }}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="section section-card section-card--soft">
|
||
<view class="section__title">详细说明</view>
|
||
<view
|
||
v-for="(item, index) in detail.article.content_blocks"
|
||
:key="`${detail.article.id}-${index}`"
|
||
class="report-meta__row report-meta__row--stacked"
|
||
>
|
||
<text class="report-meta__label">{{ index + 1 }}.</text>
|
||
<text class="report-meta__value">{{ item }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<view v-if="detail.related_articles.length" class="section">
|
||
<view class="section__heading">
|
||
<view>
|
||
<view class="section__title">相关问题</view>
|
||
<view class="section__desc">如果这个问题还没完全解决,可以继续看这些相关文章。</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view
|
||
v-for="item in detail.related_articles"
|
||
:key="item.id"
|
||
class="section message-card"
|
||
@click="openArticle(item.id)"
|
||
>
|
||
<view class="message-card__top">
|
||
<view style="flex: 1">
|
||
<view style="display: flex; align-items: center; gap: 12rpx; flex-wrap: wrap">
|
||
<text class="message-card__title">{{ item.title }}</text>
|
||
<text class="tag tag--neutral">{{ item.category_text }}</text>
|
||
</view>
|
||
</view>
|
||
<text class="message-card__time">{{ item.updated_at }}</text>
|
||
</view>
|
||
<view class="message-card__content">{{ item.summary }}</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="section section-note">
|
||
<view class="support-banner__title">还有疑问?</view>
|
||
<view class="support-banner__desc">如果帮助文章仍不能解决您的问题,可以直接联系客服发起工单,我们会尽快跟进。</view>
|
||
<view style="margin-top: 16rpx">
|
||
<text class="btn btn--ghost" @click="contactSupport">去客服支持</text>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
</view>
|
||
</template>
|