From 87c4b63ce203f0fb34241eda92caeccbaceb7f54 Mon Sep 17 00:00:00 2001
From: quling <377956897@qq.com>
Date: 星期六, 22 八月 2026 15:11:01 +0800
Subject: [PATCH] feat0806: APP养生科普健康知识功能改造
---
tcm-training-admin-backend/src/main/java/com/tcm/training/admin/app/popularization/controller/AppHealthPopularizationController.java | 8 +
tcm-training-admin-backend/src/main/java/com/tcm/training/admin/app/popularization/service/AppHealthPopularizationService.java | 8 +
tcm-training-admin-backend/src/main/java/com/tcm/training/admin/app/popularization/vo/AppHealthPopularizationDetailVO.java | 2
traditionalApp/pages/publish/service.js | 6 +
traditionalApp/pages/healthCoursesHub/healthCoursesHub.vue | 8 +-
traditionalApp/pages/articleDetail/articleDetail.vue | 27 ++++++
traditionalApp/pages/publish/publish.vue | 69 +++++++++--------
traditionalApp/pages/healthPopularization/service.js | 6 +
traditionalApp/pages/healthPopularization/healthPopularization.vue | 69 +++++++++--------
9 files changed, 125 insertions(+), 78 deletions(-)
diff --git a/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/app/popularization/controller/AppHealthPopularizationController.java b/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/app/popularization/controller/AppHealthPopularizationController.java
index 9769c59..a11f045 100644
--- a/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/app/popularization/controller/AppHealthPopularizationController.java
+++ b/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/app/popularization/controller/AppHealthPopularizationController.java
@@ -8,6 +8,7 @@
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@@ -31,10 +32,13 @@
/**
* 获取 APP 健康科普列表。
+ *
+ * @param contentType 内容类型:1 健康知识、2 养生科普;不传则返回全部。
*/
@GetMapping("/health-popularizations")
- public ApiResponse<List<AppHealthPopularizationListItemVO>> list() {
- return ApiResponse.ok(appHealthPopularizationService.list());
+ public ApiResponse<List<AppHealthPopularizationListItemVO>> list(
+ @RequestParam(value = "contentType", required = false) Integer contentType) {
+ return ApiResponse.ok(appHealthPopularizationService.list(contentType));
}
/**
diff --git a/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/app/popularization/service/AppHealthPopularizationService.java b/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/app/popularization/service/AppHealthPopularizationService.java
index f4436bf..d6b6597 100644
--- a/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/app/popularization/service/AppHealthPopularizationService.java
+++ b/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/app/popularization/service/AppHealthPopularizationService.java
@@ -30,12 +30,15 @@
/**
* 获取 APP 健康科普列表页数据。
+ *
+ * @param contentType 内容类型:1 健康知识、2 养生科普;为空则返回全部。
*/
- public List<AppHealthPopularizationListItemVO> list() {
+ public List<AppHealthPopularizationListItemVO> list(Integer contentType) {
List<HealthPopularization> items = healthPopularizationMapper.selectList(new LambdaQueryWrapper<HealthPopularization>()
.eq(HealthPopularization::getDeleted, 0)
.eq(HealthPopularization::getStatus, STATUS_ENABLED)
- .orderByAsc(HealthPopularization::getSort)
+ .eq(contentType != null, HealthPopularization::getContentType, contentType)
+ .orderByDesc(HealthPopularization::getSort)
.orderByDesc(HealthPopularization::getId));
if (items == null || items.isEmpty()) {
return Collections.emptyList();
@@ -68,6 +71,7 @@
detailVO.setContent(trimToEmpty(item.getContent()));
detailVO.setVideoUrl(trimToEmpty(item.getVideoUrl()));
detailVO.setVideoFileName(trimToEmpty(item.getVideoFileName()));
+ detailVO.setVideoDescription(trimToEmpty(item.getVideoDescription()));
return detailVO;
}
diff --git a/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/app/popularization/vo/AppHealthPopularizationDetailVO.java b/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/app/popularization/vo/AppHealthPopularizationDetailVO.java
index 556e4ef..fb8951f 100644
--- a/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/app/popularization/vo/AppHealthPopularizationDetailVO.java
+++ b/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/app/popularization/vo/AppHealthPopularizationDetailVO.java
@@ -25,4 +25,6 @@
private String videoUrl;
private String videoFileName;
+
+ private String videoDescription;
}
diff --git a/traditionalApp/pages/articleDetail/articleDetail.vue b/traditionalApp/pages/articleDetail/articleDetail.vue
index cbbb0f5..c1fc71c 100644
--- a/traditionalApp/pages/articleDetail/articleDetail.vue
+++ b/traditionalApp/pages/articleDetail/articleDetail.vue
@@ -26,6 +26,11 @@
<rich-text v-if="!isVideoType" :nodes="contentNodes" class="rich-content"></rich-text>
<view v-if="loading" class="status-text">加载中...</view>
<view v-else-if="!detail.id" class="status-text">暂无详情内容</view>
+
+ <!-- 视频介绍:仅视频类型且有介绍文案时展示 -->
+ <view v-if="isVideoType && videoDescription" class="video-intro">
+ <text class="video-intro-text">{{ videoDescription }}</text>
+ </view>
</view>
</view>
</template>
@@ -45,6 +50,7 @@
content : string
videoUrl : string
videoFileName : string
+ videoDescription : string
}
const statusBarHeight = ref(0)
@@ -66,6 +72,7 @@
content: '',
videoUrl: '',
videoFileName: '',
+ videoDescription: '',
}
}
@@ -81,6 +88,11 @@
const source = detail.value as PopularizationDetail & { summary ?: string; description ?: string; subTitle ?: string }
return String(source.subtitle || source.subTitle || source.summary || source.description || '').trim()
})
+
+ /**
+ * 视频介绍文案,去除首尾空白后用于详情底部展示。
+ */
+ const videoDescription = computed(() => String(detail.value.videoDescription || '').trim())
/**
* 将富文本正文转换为 `rich-text` 可直接消费的节点字符串。
@@ -285,4 +297,19 @@
line-height: 40rpx;
color: #86909C;
}
+
+ .video-intro {
+ margin-top: 32rpx;
+ padding-top: 24rpx;
+ border-top: 1rpx solid #EBEDF0;
+ display: flex;
+ flex-direction: column;
+ }
+
+ .video-intro-text {
+ font-size: 28rpx;
+ line-height: 1.8;
+ color: #5B6475;
+ white-space: pre-wrap;
+ }
</style>
diff --git a/traditionalApp/pages/healthCoursesHub/healthCoursesHub.vue b/traditionalApp/pages/healthCoursesHub/healthCoursesHub.vue
index 48956ac..7d12012 100644
--- a/traditionalApp/pages/healthCoursesHub/healthCoursesHub.vue
+++ b/traditionalApp/pages/healthCoursesHub/healthCoursesHub.vue
@@ -39,20 +39,20 @@
}
/**
- * 进入复制后的养生科普二级页。
+ * 进入复制后的养生科普二级页(contentType=2 仅视频)。
*/
const goHealthPopularization = () => {
uni.navigateTo({
- url: '/pages/healthPopularization/healthPopularization'
+ url: '/pages/healthPopularization/healthPopularization?contentType=2'
})
}
/**
- * 进入原健康科普页,作为「健康知识」二级页。
+ * 进入原健康科普页,作为「健康知识」二级页(contentType=1 仅图文)。
*/
const goHealthKnowledge = () => {
uni.navigateTo({
- url: '/pages/publish/publish'
+ url: '/pages/publish/publish?contentType=1'
})
}
</script>
diff --git a/traditionalApp/pages/healthPopularization/healthPopularization.vue b/traditionalApp/pages/healthPopularization/healthPopularization.vue
index 140f81a..8a8045f 100644
--- a/traditionalApp/pages/healthPopularization/healthPopularization.vue
+++ b/traditionalApp/pages/healthPopularization/healthPopularization.vue
@@ -12,9 +12,7 @@
<view v-if="articleList.length" class="article-list">
<view class="article-item" v-for="item in articleList" :key="item.id" @tap="goToDetail(item.id)">
<image class="article-img" :src="item.coverImage || defaultCoverImage" mode="aspectFill"></image>
- <view class="article-shadow">
- <text class="article-text">{{ item.title }}</text>
- </view>
+ <text class="article-title">{{ item.title }}</text>
</view>
</view>
<view v-else-if="loading" class="status-text">加载中...</view>
@@ -25,7 +23,7 @@
<script setup lang="ts">
import { ref, onMounted } from 'vue';
-import { onPullDownRefresh } from '@dcloudio/uni-app'
+import { onLoad, onPullDownRefresh } from '@dcloudio/uni-app'
import { getHealthPopularizationList } from './service'
interface PopularizationListItem {
@@ -40,6 +38,18 @@
const loading = ref(false)
const articleList = ref<PopularizationListItem[]>([])
const defaultCoverImage = '/static/image/home/zixun.png'
+// 内容类型:2 养生科普,默认按养生科普过滤。
+const contentType = ref<number>(2)
+
+/**
+ * 读取路由参数中的内容类型,用于按类型过滤列表。
+ */
+onLoad((options) => {
+ const raw = Number(options?.contentType)
+ if (!Number.isNaN(raw) && raw > 0) {
+ contentType.value = raw
+ }
+})
/**
* 页面加载时初始化状态栏高度并拉取养生科普列表。
@@ -84,7 +94,7 @@
async function loadPopularizationList() {
loading.value = true
try {
- const response = await getHealthPopularizationList()
+ const response = await getHealthPopularizationList(contentType.value)
if (response?.code !== 0 || !Array.isArray(response.data)) {
articleList.value = []
return
@@ -163,43 +173,36 @@
.article-list {
display: flex;
- justify-content: space-between;
- flex-wrap: wrap;
+ flex-direction: column;
}
.article-item {
- width: 328rpx;
- height: 328rpx;
- border-radius: 16rpx;
- position: relative;
- overflow: hidden;
- margin-bottom: 24rpx;
-}
-
-.article-img {
- width: 100%;
- height: 100%;
-}
-
-.article-shadow {
- position: absolute;
- bottom: 0;
- left: 0;
- width: 100%;
- height: 64rpx;
- background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.8) 100%);
display: flex;
align-items: center;
- padding: 0 16rpx;
+ width: 100%;
+ padding: 24rpx 0;
+ border-bottom: 1rpx solid #F0F0F0;
box-sizing: border-box;
}
-.article-text {
- color: #FFFFFF;
- font-size: 24rpx;
- white-space: nowrap;
+.article-img {
+ width: 200rpx;
+ height: 150rpx;
+ border-radius: 12rpx;
+ flex-shrink: 0;
+ background-color: #F5F6F8;
+}
+
+.article-title {
+ flex: 1;
+ margin-left: 24rpx;
+ font-size: 30rpx;
+ line-height: 44rpx;
+ color: #333;
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
- width: 100%;
}
</style>
diff --git a/traditionalApp/pages/healthPopularization/service.js b/traditionalApp/pages/healthPopularization/service.js
index 419cab1..66cc99b 100644
--- a/traditionalApp/pages/healthPopularization/service.js
+++ b/traditionalApp/pages/healthPopularization/service.js
@@ -2,7 +2,9 @@
/**
* 获取 APP 养生科普列表(与原健康科普共用接口)。
+ * @param {number} [contentType] 内容类型:1 健康知识、2 养生科普;不传返回全部。
*/
-export const getHealthPopularizationList = () => {
- return request.get('/api/app/health-popularizations', {}, false, false)
+export const getHealthPopularizationList = (contentType) => {
+ const params = contentType == null ? {} : { contentType }
+ return request.get('/api/app/health-popularizations', params, false, false)
}
diff --git a/traditionalApp/pages/publish/publish.vue b/traditionalApp/pages/publish/publish.vue
index 9f48c75..e13aa36 100644
--- a/traditionalApp/pages/publish/publish.vue
+++ b/traditionalApp/pages/publish/publish.vue
@@ -15,9 +15,7 @@
<view v-if="articleList.length" class="article-list">
<view class="article-item" v-for="item in articleList" :key="item.id" @tap="goToDetail(item.id)">
<image class="article-img" :src="item.coverImage || defaultCoverImage" mode="aspectFill"></image>
- <view class="article-shadow">
- <text class="article-text">{{ item.title }}</text>
- </view>
+ <text class="article-title">{{ item.title }}</text>
</view>
</view>
<view v-else-if="loading" class="status-text">加载中...</view>
@@ -28,7 +26,7 @@
<script setup lang="ts">
import { ref, onMounted } from 'vue';
-import { onPullDownRefresh } from '@dcloudio/uni-app'
+import { onLoad, onPullDownRefresh } from '@dcloudio/uni-app'
import { getHealthPopularizationList } from './service'
interface PopularizationListItem {
@@ -43,6 +41,18 @@
const loading = ref(false)
const articleList = ref<PopularizationListItem[]>([])
const defaultCoverImage = '/static/image/home/zixun.png'
+// 内容类型:1 健康知识,默认按健康知识过滤。
+const contentType = ref<number>(1)
+
+/**
+ * 读取路由参数中的内容类型,用于按类型过滤列表。
+ */
+onLoad((options) => {
+ const raw = Number(options?.contentType)
+ if (!Number.isNaN(raw) && raw > 0) {
+ contentType.value = raw
+ }
+})
/**
* 页面加载时初始化状态栏高度并拉取健康知识列表。
@@ -87,7 +97,7 @@
async function loadPopularizationList() {
loading.value = true
try {
- const response = await getHealthPopularizationList()
+ const response = await getHealthPopularizationList(contentType.value)
if (response?.code !== 0 || !Array.isArray(response.data)) {
articleList.value = []
return
@@ -166,43 +176,36 @@
.article-list {
display: flex;
- justify-content: space-between;
- flex-wrap: wrap;
+ flex-direction: column;
}
.article-item {
- width: 328rpx;
- height: 328rpx;
- border-radius: 16rpx;
- position: relative;
- overflow: hidden;
- margin-bottom: 24rpx;
-}
-
-.article-img {
- width: 100%;
- height: 100%;
-}
-
-.article-shadow {
- position: absolute;
- bottom: 0;
- left: 0;
- width: 100%;
- height: 64rpx;
- background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.8) 100%);
display: flex;
align-items: center;
- padding: 0 16rpx;
+ width: 100%;
+ padding: 24rpx 0;
+ border-bottom: 1rpx solid #F0F0F0;
box-sizing: border-box;
}
-.article-text {
- color: #FFFFFF;
- font-size: 24rpx;
- white-space: nowrap;
+.article-img {
+ width: 200rpx;
+ height: 150rpx;
+ border-radius: 12rpx;
+ flex-shrink: 0;
+ background-color: #F5F6F8;
+}
+
+.article-title {
+ flex: 1;
+ margin-left: 24rpx;
+ font-size: 30rpx;
+ line-height: 44rpx;
+ color: #333;
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
- width: 100%;
}
</style>
diff --git a/traditionalApp/pages/publish/service.js b/traditionalApp/pages/publish/service.js
index a42ca25..914e865 100644
--- a/traditionalApp/pages/publish/service.js
+++ b/traditionalApp/pages/publish/service.js
@@ -2,7 +2,9 @@
/**
* 获取 APP 健康科普列表。
+ * @param {number} [contentType] 内容类型:1 健康知识、2 养生科普;不传返回全部。
*/
-export const getHealthPopularizationList = () => {
- return request.get('/api/app/health-popularizations', {}, false, false)
+export const getHealthPopularizationList = (contentType) => {
+ const params = contentType == null ? {} : { contentType }
+ return request.get('/api/app/health-popularizations', params, false, false)
}
--
Gitblit v1.7.1