From 24147cb2de6f8761e7d0d27e49e00f8d499ae8d8 Mon Sep 17 00:00:00 2001
From: 13404089107 <puwei@sinata.cn>
Date: 星期五, 15 五月 2026 17:59:17 +0800
Subject: [PATCH] feat: 优化文章详情页图片自适应,完善课程ID解析逻辑
---
traditionalApp/pages/articleDetail/articleDetail.vue | 375 ++++++++++++++++++++---------------------
traditionalApp/pages/courseDetail/courseDetail.vue | 106 +++++-----
traditionalApp/manifest.json | 4
3 files changed, 241 insertions(+), 244 deletions(-)
diff --git a/traditionalApp/manifest.json b/traditionalApp/manifest.json
index 9aff6cf..b3efb10 100644
--- a/traditionalApp/manifest.json
+++ b/traditionalApp/manifest.json
@@ -3,8 +3,8 @@
"name" : "海诊康道",
"appid" : "__UNI__1A90541",
"description" : "",
- "versionName" : "1.0.11",
- "versionCode" : 111,
+ "versionName" : "1.0.14",
+ "versionCode" : 114,
"transformPx" : false,
/* 5+App特有相关 */
"app-plus" : {
diff --git a/traditionalApp/pages/articleDetail/articleDetail.vue b/traditionalApp/pages/articleDetail/articleDetail.vue
index f23851c..8404f2b 100644
--- a/traditionalApp/pages/articleDetail/articleDetail.vue
+++ b/traditionalApp/pages/articleDetail/articleDetail.vue
@@ -2,7 +2,7 @@
<view class="container">
<!-- 状态栏占位 -->
<view class="status-bar-placeholder" :style="{ height: statusBarHeight + 'px' }"></view>
-
+
<!-- 导航栏 -->
<view class="nav-bar">
<image class="back-icon" src="/static/image/home/left.png" mode="aspectFit" @tap="goBack"></image>
@@ -11,12 +11,7 @@
<!-- 视频播放器区域 -->
<view v-if="isVideoType" class="video-container">
- <video
- class="video-player"
- :src="detail.videoUrl"
- controls
- :autoplay="false"
- ></video>
+ <video class="video-player" :src="detail.videoUrl" controls :autoplay="false"></video>
</view>
<!-- 图文封面区域 -->
@@ -35,217 +30,219 @@
</template>
<script setup lang="ts">
-import { computed, onMounted, ref } from 'vue'
-import { onLoad } from '@dcloudio/uni-app'
-import { getHealthPopularizationDetail } from './service'
+ import { computed, onMounted, ref } from 'vue'
+ import { onLoad } from '@dcloudio/uni-app'
+ import { getHealthPopularizationDetail } from './service'
-interface PopularizationDetail {
- id?: number | null
- title: string
- coverImage: string
- contentType?: number | null
- contentTypeText: string
- content: string
- videoUrl: string
- videoFileName: string
-}
-
-const statusBarHeight = ref(0)
-const loading = ref(false)
-const popularizationId = ref('')
-const detail = ref<PopularizationDetail>(createDefaultDetail())
-
-/**
- * 创建健康科普详情页默认数据,避免接口返回前页面闪空。
- */
-function createDefaultDetail(): PopularizationDetail {
- return {
- id: null,
- title: '',
- coverImage: '',
- contentType: null,
- contentTypeText: '',
- content: '',
- videoUrl: '',
- videoFileName: '',
+ interface PopularizationDetail {
+ id ?: number | null
+ title : string
+ coverImage : string
+ contentType ?: number | null
+ contentTypeText : string
+ content : string
+ videoUrl : string
+ videoFileName : string
}
-}
-/**
- * 根据内容类型判断当前详情是否属于视频详情页。
- */
-const isVideoType = computed(() => Number(detail.value.contentType) === 2)
+ const statusBarHeight = ref(0)
+ const loading = ref(false)
+ const popularizationId = ref('')
+ const detail = ref<PopularizationDetail>(createDefaultDetail())
-/**
- * 将富文本正文转换为 `rich-text` 可直接消费的节点字符串。
- */
-const contentNodes = computed(() => buildRichTextNodes(detail.value.content, '暂无详情内容'))
-
-/**
- * 初始化导航栏所需的状态栏高度。
- */
-onMounted(() => {
- uni.getSystemInfo({
- success: (res) => {
- statusBarHeight.value = res.statusBarHeight || 0
+ /**
+ * 创建健康科普详情页默认数据,避免接口返回前页面闪空。
+ */
+ function createDefaultDetail() : PopularizationDetail {
+ return {
+ id: null,
+ title: '',
+ coverImage: '',
+ contentType: null,
+ contentTypeText: '',
+ content: '',
+ videoUrl: '',
+ videoFileName: '',
}
- })
-})
-
-/**
- * 页面加载时读取科普主键并拉取详情接口。
- */
-onLoad((options) => {
- popularizationId.value = typeof options?.id === 'string' ? options.id : ''
- loadDetail()
-})
-
-/**
- * 拉取健康科普详情接口并更新页面状态。
- */
-async function loadDetail() {
- if (!popularizationId.value) {
- detail.value = createDefaultDetail()
- return
}
- loading.value = true
- try {
- const response = await getHealthPopularizationDetail(popularizationId.value)
- if (response?.code !== 0 || !response.data) {
- showLoadFailedToast()
+
+ /**
+ * 根据内容类型判断当前详情是否属于视频详情页。
+ */
+ const isVideoType = computed(() => Number(detail.value.contentType) === 2)
+
+ /**
+ * 将富文本正文转换为 `rich-text` 可直接消费的节点字符串。
+ */
+ const contentNodes = computed(() => buildRichTextNodes(detail.value.content, '暂无详情内容'))
+
+ /**
+ * 初始化导航栏所需的状态栏高度。
+ */
+ onMounted(() => {
+ uni.getSystemInfo({
+ success: (res) => {
+ statusBarHeight.value = res.statusBarHeight || 0
+ }
+ })
+ })
+
+ /**
+ * 页面加载时读取科普主键并拉取详情接口。
+ */
+ onLoad((options) => {
+ popularizationId.value = typeof options?.id === 'string' ? options.id : ''
+ loadDetail()
+ })
+
+ /**
+ * 拉取健康科普详情接口并更新页面状态。
+ */
+ async function loadDetail() {
+ if (!popularizationId.value) {
+ detail.value = createDefaultDetail()
return
}
- // 图文和视频共用一个详情接口,前端只按内容类型切换展示结构。
- detail.value = {
- ...createDefaultDetail(),
- ...response.data,
+ loading.value = true
+ try {
+ const response = await getHealthPopularizationDetail(popularizationId.value)
+ if (response?.code !== 0 || !response.data) {
+ showLoadFailedToast()
+ return
+ }
+ // 图文和视频共用一个详情接口,前端只按内容类型切换展示结构。
+ detail.value = {
+ ...createDefaultDetail(),
+ ...response.data,
+ }
+ } catch {
+ showLoadFailedToast()
+ } finally {
+ loading.value = false
}
- } catch {
- showLoadFailedToast()
- } finally {
- loading.value = false
}
-}
-/**
- * 详情加载失败时给出统一提示。
- */
-function showLoadFailedToast() {
- uni.showToast({
- title: '健康科普详情加载失败',
- icon: 'none',
- })
-}
+ /**
+ * 详情加载失败时给出统一提示。
+ */
+ function showLoadFailedToast() {
+ uni.showToast({
+ title: '健康科普详情加载失败',
+ icon: 'none',
+ })
+ }
-/**
- * 将富文本内容转换为 `rich-text` 可直接渲染的节点。
- */
-function buildRichTextNodes(content?: string, fallbackText?: string) {
- if (typeof content === 'string' && content.trim()) {
- return content
+ /**
+ * 将富文本内容转换为 `rich-text` 可直接渲染的节点。
+ */
+ function buildRichTextNodes(content ?: string, fallbackText ?: string) {
+ if (typeof content === 'string' && content.trim()) {
+ return content.replace(/<img/gi,
+ '<img style="max-width:100%;height:auto;margin:0 auto;display:block"')
+ }
+ if (typeof fallbackText === 'string' && fallbackText.trim()) {
+ return `<p>${fallbackText.trim()}</p>`
+ }
+ return '<p></p>'
}
- if (typeof fallbackText === 'string' && fallbackText.trim()) {
- return `<p>${fallbackText.trim()}</p>`
- }
- return '<p></p>'
-}
-/**
- * 返回上一页;若没有历史栈,则回到首页避免停留在空白上下文。
- */
-function goBack() {
- const currentPages = getCurrentPages()
- if (currentPages.length > 1) {
- uni.navigateBack()
- return
+ /**
+ * 返回上一页;若没有历史栈,则回到首页避免停留在空白上下文。
+ */
+ function goBack() {
+ const currentPages = getCurrentPages()
+ if (currentPages.length > 1) {
+ uni.navigateBack()
+ return
+ }
+ uni.switchTab({
+ url: '/pages/home/home'
+ })
}
- uni.switchTab({
- url: '/pages/home/home'
- })
-}
</script>
<style>
-page, html {
- background-color: #F5F6F8;
-}
+ page,
+ html {
+ background-color: #F5F6F8;
+ }
</style>
<style lang="scss" scoped>
-.container {
- min-height: 100vh;
- background-color: #F5F6F8;
-}
+ .container {
+ min-height: 100vh;
+ background-color: #F5F6F8;
+ }
-.nav-bar {
- height: 88rpx;
- display: flex;
- align-items: center;
- padding: 0 24rpx;
- background-color: #fff;
- position: relative;
-}
+ .nav-bar {
+ height: 88rpx;
+ display: flex;
+ align-items: center;
+ padding: 0 24rpx;
+ background-color: #fff;
+ position: relative;
+ }
-.back-icon {
- width: 40rpx;
- height: 40rpx;
- position: absolute;
- left: 24rpx;
- z-index: 10;
-}
+ .back-icon {
+ width: 40rpx;
+ height: 40rpx;
+ position: absolute;
+ left: 24rpx;
+ z-index: 10;
+ }
-.nav-title {
- flex: 1;
- text-align: center;
- font-size: 36rpx;
- font-weight: 500;
- color: #333;
-}
+ .nav-title {
+ flex: 1;
+ text-align: center;
+ font-size: 36rpx;
+ font-weight: 500;
+ color: #333;
+ }
-.video-container {
- width: 100%;
- height: 402rpx;
-}
+ .video-container {
+ width: 100%;
+ height: 402rpx;
+ }
-.video-player {
- width: 100%;
- height: 100%;
-}
+ .video-player {
+ width: 100%;
+ height: 100%;
+ }
-.cover-container {
- width: 100%;
- height: 402rpx;
-}
+ .cover-container {
+ width: 100%;
+ height: 402rpx;
+ }
-.cover-image {
- width: 100%;
- height: 100%;
-}
+ .cover-image {
+ width: 100%;
+ height: 100%;
+ }
-.content-area {
- padding: 32rpx;
- background-color: #F5F6F8;
-}
+ .content-area {
+ padding: 32rpx;
+ background-color: #F5F6F8;
+ }
-.content-title {
- font-size: 32rpx;
- font-weight: 500;
- color: #333;
- line-height: 48rpx;
-}
+ .content-title {
+ font-size: 32rpx;
+ font-weight: 500;
+ color: #333;
+ line-height: 48rpx;
+ }
-.rich-content {
- margin-top: 24rpx;
- width: 100%;
- font-size: 28rpx;
- line-height: 1.8;
- color: #333;
-}
+ .rich-content {
+ margin-top: 24rpx;
+ width: 100%;
+ font-size: 28rpx;
+ line-height: 1.8;
+ color: #333;
+ }
-.status-text {
- margin-top: 24rpx;
- font-size: 26rpx;
- line-height: 40rpx;
- color: #86909C;
-}
-</style>
+ .status-text {
+ margin-top: 24rpx;
+ font-size: 26rpx;
+ line-height: 40rpx;
+ color: #86909C;
+ }
+</style>
\ No newline at end of file
diff --git a/traditionalApp/pages/courseDetail/courseDetail.vue b/traditionalApp/pages/courseDetail/courseDetail.vue
index 5566596..acb2131 100644
--- a/traditionalApp/pages/courseDetail/courseDetail.vue
+++ b/traditionalApp/pages/courseDetail/courseDetail.vue
@@ -205,7 +205,7 @@
<view v-if="!loading && allVideos.length === 0" class="empty-text">暂无课程章节</view>
</view>
</template>
-
+
<view v-if="loading" class="loading-text">加载中...</view>
<view v-if="isReadonlyDisplayMode" class="open-app-banner" @tap="openApp">
<view class="app-logo-placeholder"></view>
@@ -529,32 +529,32 @@
* 页面加载时读取课程主键并拉取详情接口。
*/
onLoad((options) => {
- courseId.value = resolveCourseId(options)
+ courseId.value = resolveCourseId(options)
loadCourseDetail()
})
-/**
- * 统一解析课程 id,兼容 App 路由参数和 H5 分享页地址参数。
- */
-function resolveCourseId(options?: Record<string, unknown>) {
- const routeCourseId = typeof options?.id === 'string' ? options.id.trim() : ''
- if (routeCourseId) {
- return routeCourseId
- }
- // #ifdef H5
- try {
- const searchCourseId = new URLSearchParams(window.location.search).get('id')?.trim() || ''
- if (searchCourseId) {
- return searchCourseId
+ /**
+ * 统一解析课程 id,兼容 App 路由参数和 H5 分享页地址参数。
+ */
+ function resolveCourseId(options ?: Record<string, unknown>) {
+ const routeCourseId = typeof options?.id === 'string' ? options.id.trim() : ''
+ if (routeCourseId) {
+ return routeCourseId
}
- const hashQuery = window.location.hash.split('?')[1] || ''
- return new URLSearchParams(hashQuery).get('id')?.trim() || ''
- } catch (error) {
- console.log('解析课程分享参数失败', error)
+ // #ifdef H5
+ try {
+ const searchCourseId = new URLSearchParams(window.location.search).get('id')?.trim() || ''
+ if (searchCourseId) {
+ return searchCourseId
+ }
+ const hashQuery = window.location.hash.split('?')[1] || ''
+ return new URLSearchParams(hashQuery).get('id')?.trim() || ''
+ } catch (error) {
+ console.log('解析课程分享参数失败', error)
+ }
+ // #endif
+ return ''
}
- // #endif
- return ''
-}
/**
* 页面显示时开启播放器安全能力。
@@ -890,19 +890,19 @@
* 拉起或跳转下载 APP
*/
function openApp() {
- const openAppUrl = 'https://m.malink.cn/s/7bIzeu'
- // #ifdef H5
- window.location.href = openAppUrl
- return
- // #endif
- // #ifdef APP-PLUS
- plus.runtime.openURL(openAppUrl)
- return
- // #endif
- uni.showToast({
- title: '当前环境不支持打开链接',
- icon: 'none',
- })
+ const openAppUrl = 'https://m.malink.cn/s/7bIzeu'
+ // #ifdef H5
+ window.location.href = openAppUrl
+ return
+ // #endif
+ // #ifdef APP-PLUS
+ plus.runtime.openURL(openAppUrl)
+ return
+ // #endif
+ uni.showToast({
+ title: '当前环境不支持打开链接',
+ icon: 'none',
+ })
}
/**
@@ -918,26 +918,26 @@
* 生成课程 H5 分享链接,供微信好友打开页面详情。
*/
function buildCourseShareUrl() {
- const shareBaseUrl = 'https://haizhentong.com/share/'
- const shareCourseId = resolveShareCourseId()
- if (!shareCourseId) {
- return shareBaseUrl
- }
- return `${shareBaseUrl}?id=${encodeURIComponent(shareCourseId)}`
+ const shareBaseUrl = 'https://haizhentong.com/share/'
+ const shareCourseId = resolveShareCourseId()
+ if (!shareCourseId) {
+ return shareBaseUrl
+ }
+ return `${shareBaseUrl}?id=${encodeURIComponent(shareCourseId)}`
}
-/**
- * 生成分享使用的课程 id,优先使用路由参数,详情数据兜底。
- */
-function resolveShareCourseId() {
- if (courseId.value) {
- return courseId.value
+ /**
+ * 生成分享使用的课程 id,优先使用路由参数,详情数据兜底。
+ */
+ function resolveShareCourseId() {
+ if (courseId.value) {
+ return courseId.value
+ }
+ if (courseDetail.value.id !== undefined && courseDetail.value.id !== null) {
+ return String(courseDetail.value.id)
+ }
+ return ''
}
- if (courseDetail.value.id !== undefined && courseDetail.value.id !== null) {
- return String(courseDetail.value.id)
- }
- return ''
-}
/**
* 通过微信好友聊天场景分享当前课程。
@@ -1924,4 +1924,4 @@
background-color: #E5E6EB;
color: #86909C;
}
-</style>
+</style>
\ No newline at end of file
--
Gitblit v1.7.1