fix
13404089107
2026-04-24 2c7f9507199982d0bb494744df8ee64b738490f7
fix
4个文件已修改
881 ■■■■■ 已修改文件
traditionalApp/manifest.json 268 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traditionalApp/pages.json 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traditionalApp/pages/activityNotice/activityNotice.vue 451 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traditionalApp/pages/home/home.vue 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traditionalApp/manifest.json
@@ -1,123 +1,147 @@
{
    "sassImplementationName" : "node-sass",
    "name" : "海诊康道",
    "appid" : "__UNI__1A90541",
    "description" : "",
    "versionName" : "1.0.0",
    "versionCode" : "100",
    "transformPx" : false,
    /* 5+App特有相关 */
    "app-plus" : {
        "usingComponents" : true,
        "nvueStyleCompiler" : "uni-app",
        "compilerVersion" : 3,
        "splashscreen" : {
            "alwaysShowBeforeRender" : true,
            "waiting" : true,
            "autoclose" : true,
            "delay" : 0
        },
        /* 模块配置 */
        "modules" : {
            "Barcode" : {},
            "VideoPlayer" : {}
        },
        /* 应用发布信息 */
        "distribute" : {
            /* android打包配置 */
            "android" : {
                "permissions" : [
                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
                    "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
                    "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
                    "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
                    "<uses-feature android:name=\"android.hardware.camera\"/>",
                    "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
                ]
            },
            /* ios打包配置 */
            "ios" : {
                "dSYMs" : false
            },
            /* SDK配置 */
            "sdkConfigs" : {
                "push" : {}
            },
            "icons" : {
                "android" : {
                    "hdpi" : "unpackage/res/icons/72x72.png",
                    "xhdpi" : "unpackage/res/icons/96x96.png",
                    "xxhdpi" : "unpackage/res/icons/144x144.png",
                    "xxxhdpi" : "unpackage/res/icons/192x192.png"
                },
                "ios" : {
                    "appstore" : "unpackage/res/icons/1024x1024.png",
                    "ipad" : {
                        "app" : "unpackage/res/icons/76x76.png",
                        "app@2x" : "unpackage/res/icons/152x152.png",
                        "notification" : "unpackage/res/icons/20x20.png",
                        "notification@2x" : "unpackage/res/icons/40x40.png",
                        "proapp@2x" : "unpackage/res/icons/167x167.png",
                        "settings" : "unpackage/res/icons/29x29.png",
                        "settings@2x" : "unpackage/res/icons/58x58.png",
                        "spotlight" : "unpackage/res/icons/40x40.png",
                        "spotlight@2x" : "unpackage/res/icons/80x80.png"
                    },
                    "iphone" : {
                        "app@2x" : "unpackage/res/icons/120x120.png",
                        "app@3x" : "unpackage/res/icons/180x180.png",
                        "notification@2x" : "unpackage/res/icons/40x40.png",
                        "notification@3x" : "unpackage/res/icons/60x60.png",
                        "settings@2x" : "unpackage/res/icons/58x58.png",
                        "settings@3x" : "unpackage/res/icons/87x87.png",
                        "spotlight@2x" : "unpackage/res/icons/80x80.png",
                        "spotlight@3x" : "unpackage/res/icons/120x120.png"
                    }
                }
            }
        }
    },
    /* 快应用特有相关 */
    "quickapp" : {},
    /* 小程序特有相关 */
    "mp-weixin" : {
        "appid" : "wx424c015a245af04d",
        "setting" : {
            "urlCheck" : false,
            "minified" : true
        },
        "usingComponents" : true
    },
    "mp-alipay" : {
        "usingComponents" : true
    },
    "mp-baidu" : {
        "usingComponents" : true
    },
    "mp-toutiao" : {
        "usingComponents" : true
    },
    "uniStatistics" : {
        "enable" : false
    },
    "vueVersion" : "3",
    "permission" : {
        "scope.userLocation" : {
            "desc" : "下载文件"
        }
    },
    "h5" : {
        "unipush" : {
            "enable" : false
        }
    }
}
    "sassImplementationName": "node-sass",
    "name": "海诊康道",
    "appid": "__UNI__1A90541",
    "description": "",
    "versionName": "1.0.1",
    "versionCode": 101,
    "transformPx": false,
    /* 5+App特有相关 */
    "app-plus": {
        "usingComponents": true,
        "nvueStyleCompiler": "uni-app",
        "compilerVersion": 3,
        "splashscreen": {
            "alwaysShowBeforeRender": true,
            "waiting": true,
            "autoclose": true,
            "delay": 0
        },
        /* 模块配置 */
        "modules": {
            "Barcode": {},
            "VideoPlayer": {},
            "Share": {},
            "OAuth": {}
        },
        /* 应用发布信息 */
        "distribute": {
            /* android打包配置 */
            "android": {
                "permissions": [
                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
                    "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
                    "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
                    "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
                    "<uses-feature android:name=\"android.hardware.camera\"/>",
                    "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
                ],
                "minSdkVersion": 30,
                "targetSdkVersion": 29
            },
            /* ios打包配置 */
            "ios": {
                "dSYMs": false,
                "capabilities": {
                    "entitlements": {
                        "com.apple.developer.associated-domains": [
                            "applinks:static-mp-dd6d96de-bdf2-4284-a975-638af4cc8ec8.next.bspapp.com"
                        ]
                    }
                }
            },
            /* SDK配置 */
            "sdkConfigs": {
                "push": {},
                "share": {
                    "weixin": {
                        "appid": "wx074c1f0cf5a0ecf4",
                        "UniversalLinks": "https://static-mp-dd6d96de-bdf2-4284-a975-638af4cc8ec8.next.bspapp.com/uni-universallinks/__UNI__1A90541/"
                    }
                },
                "oauth": {
                    "weixin": {
                        "appid": "wx074c1f0cf5a0ecf4",
                        "UniversalLinks": "https://static-mp-dd6d96de-bdf2-4284-a975-638af4cc8ec8.next.bspapp.com/uni-universallinks/__UNI__1A90541/"
                    }
                }
            },
            "icons": {
                "android": {
                    "hdpi": "unpackage/res/icons/72x72.png",
                    "xhdpi": "unpackage/res/icons/96x96.png",
                    "xxhdpi": "unpackage/res/icons/144x144.png",
                    "xxxhdpi": "unpackage/res/icons/192x192.png"
                },
                "ios": {
                    "appstore": "unpackage/res/icons/1024x1024.png",
                    "ipad": {
                        "app": "unpackage/res/icons/76x76.png",
                        "app@2x": "unpackage/res/icons/152x152.png",
                        "notification": "unpackage/res/icons/20x20.png",
                        "notification@2x": "unpackage/res/icons/40x40.png",
                        "proapp@2x": "unpackage/res/icons/167x167.png",
                        "settings": "unpackage/res/icons/29x29.png",
                        "settings@2x": "unpackage/res/icons/58x58.png",
                        "spotlight": "unpackage/res/icons/40x40.png",
                        "spotlight@2x": "unpackage/res/icons/80x80.png"
                    },
                    "iphone": {
                        "app@2x": "unpackage/res/icons/120x120.png",
                        "app@3x": "unpackage/res/icons/180x180.png",
                        "notification@2x": "unpackage/res/icons/40x40.png",
                        "notification@3x": "unpackage/res/icons/60x60.png",
                        "settings@2x": "unpackage/res/icons/58x58.png",
                        "settings@3x": "unpackage/res/icons/87x87.png",
                        "spotlight@2x": "unpackage/res/icons/80x80.png",
                        "spotlight@3x": "unpackage/res/icons/120x120.png"
                    }
                }
            }
        }
    },
    /* 快应用特有相关 */
    "quickapp": {},
    /* 小程序特有相关 */
    "mp-weixin": {
        "appid": "wxa17e8d1331e50934",
        "setting": {
            "urlCheck": false,
            "minified": true
        },
        "usingComponents": true
    },
    "mp-alipay": {
        "usingComponents": true
    },
    "mp-baidu": {
        "usingComponents": true
    },
    "mp-toutiao": {
        "usingComponents": true
    },
    "uniStatistics": {
        "enable": false
    },
    "vueVersion": "3",
    "permission": {
        "scope.userLocation": {
            "desc": "下载文件"
        }
    },
    "h5": {
        "unipush": {
            "enable": false
        }
    },
    "_spaceID": "mp-dd6d96de-bdf2-4284-a975-638af4cc8ec8"
}
traditionalApp/pages.json
@@ -334,7 +334,7 @@
                "iconPath": "static/image/tabBar/home.png",
                "selectedIconPath": "static/image/tabBar/Yhome.png",
                "text": "首页"
            },
            },
            {
                "pagePath": "pages/medicalHall/medicalHall",
                "iconPath": "static/image/tabBar/good.png",
@@ -368,4 +368,4 @@
        "backgroundColor": "#fff"
    },
    "uniIdRouter": {}
}
}
traditionalApp/pages/activityNotice/activityNotice.vue
@@ -8,20 +8,11 @@
            </view>
        </view>
        <scroll-view
            scroll-y
            class="list-scroll"
            @scrolltolower="loadMore"
        >
        <scroll-view scroll-y class="list-scroll" @scrolltolower="loadMore">
            <view v-if="noticeList.length === 0 && !loading" class="empty-box">
                <text class="empty-text">暂无活动通知</text>
            </view>
            <view
                v-for="item in noticeList"
                :key="item.id"
                class="notice-card"
                @tap="goDetail(item)"
            >
            <view v-for="item in noticeList" :key="item.id" class="notice-card" @tap="goDetail(item)">
                <view class="card-top">
                    <view class="title-wrap">
                        <text class="title">{{ item.title }}</text>
@@ -38,249 +29,249 @@
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import { getActivityNoticePage, markActivityNoticeRead } from './service'
    import { onMounted, ref } from 'vue'
    import { onShow } from '@dcloudio/uni-app'
    import { getActivityNoticePage, markActivityNoticeRead } from './service'
interface ActivityNoticeItem {
    id: number
    title: string
    createdAt: string
    read: boolean
}
const statusBarHeight = ref(20)
const noticeList = ref<ActivityNoticeItem[]>([])
const loading = ref(false)
const page = ref(1)
const pageSize = ref(10)
const finished = ref(false)
/**
 * 页面初始化时记录状态栏高度。
 */
onMounted(() => {
    const systemInfo = uni.getSystemInfoSync()
    statusBarHeight.value = systemInfo.statusBarHeight || 20
})
/**
 * 页面展示时刷新活动通知列表。
 */
onShow(() => {
    resetAndLoad()
})
/**
 * 返回上一页。
 */
function goBack() {
    uni.navigateBack()
}
/**
 * 重置分页状态并重新拉取列表。
 */
function resetAndLoad() {
    page.value = 1
    finished.value = false
    noticeList.value = []
    loadList()
}
/**
 * 拉取活动通知分页列表。
 */
async function loadList() {
    if (loading.value || finished.value) {
        return
    interface ActivityNoticeItem {
        id : number
        title : string
        createdAt : string
        read : boolean
    }
    loading.value = true
    try {
        const response = await getActivityNoticePage({
            page: page.value,
            pageSize: pageSize.value,
        })
        if (response?.code !== 0 || !response.data) {
    const statusBarHeight = ref(20)
    const noticeList = ref<ActivityNoticeItem[]>([])
    const loading = ref(false)
    const page = ref(1)
    const pageSize = ref(10)
    const finished = ref(false)
    /**
     * 页面初始化时记录状态栏高度。
     */
    onMounted(() => {
        const systemInfo = uni.getSystemInfoSync()
        statusBarHeight.value = systemInfo.statusBarHeight || 20
    })
    /**
     * 页面展示时刷新活动通知列表。
     */
    onShow(() => {
        resetAndLoad()
    })
    /**
     * 返回上一页。
     */
    function goBack() {
        uni.navigateBack()
    }
    /**
     * 重置分页状态并重新拉取列表。
     */
    function resetAndLoad() {
        page.value = 1
        finished.value = false
        noticeList.value = []
        loadList()
    }
    /**
     * 拉取活动通知分页列表。
     */
    async function loadList() {
        if (loading.value || finished.value) {
            return
        }
        const nextList = Array.isArray(response.data.list) ? response.data.list.map(normalizeNoticeItem) : []
        if (page.value === 1) {
            noticeList.value = nextList
        } else {
            noticeList.value = noticeList.value.concat(nextList)
        }
        const total = Number(response.data.total || 0)
        const currentCount = noticeList.value.length
        finished.value = currentCount >= total || nextList.length < pageSize.value
        if (!finished.value) {
            page.value += 1
        }
    } finally {
        loading.value = false
    }
}
/**
 * 将活动通知数据归一化为页面结构。
 */
function normalizeNoticeItem(source: any): ActivityNoticeItem {
    return {
        id: Number(source?.id || 0),
        title: typeof source?.title === 'string' ? source.title.trim() : '',
        createdAt: typeof source?.createdAt === 'string' ? source.createdAt.trim() : '',
        read: Boolean(source?.read),
    }
}
/**
 * 触底后加载下一页活动通知。
 */
function loadMore() {
    loadList()
}
/**
 * 点击活动通知后先标记已读,再跳转详情页。
 */
async function goDetail(item: ActivityNoticeItem) {
    if (!item.id) {
        return
    }
    if (!item.read) {
        await markActivityNoticeRead(item.id)
        noticeList.value = noticeList.value.map((current) => {
            if (current.id !== item.id) {
                return current
        loading.value = true
        try {
            const response = await getActivityNoticePage({
                page: page.value,
                pageSize: pageSize.value,
            })
            if (response?.code !== 0 || !response.data) {
                return
            }
            return {
                ...current,
                read: true,
            const nextList = Array.isArray(response.data.list) ? response.data.list.map(normalizeNoticeItem) : []
            if (page.value === 1) {
                noticeList.value = nextList
            } else {
                noticeList.value = noticeList.value.concat(nextList)
            }
            const total = Number(response.data.total || 0)
            const currentCount = noticeList.value.length
            finished.value = currentCount >= total || nextList.length < pageSize.value
            if (!finished.value) {
                page.value += 1
            }
        } finally {
            loading.value = false
        }
    }
    /**
     * 将活动通知数据归一化为页面结构。
     */
    function normalizeNoticeItem(source : any) : ActivityNoticeItem {
        return {
            id: Number(source?.id || 0),
            title: typeof source?.title === 'string' ? source.title.trim() : '',
            createdAt: typeof source?.createdAt === 'string' ? source.createdAt.trim() : '',
            read: Boolean(source?.read),
        }
    }
    /**
     * 触底后加载下一页活动通知。
     */
    function loadMore() {
        loadList()
    }
    /**
     * 点击活动通知后先标记已读,再跳转详情页。
     */
    async function goDetail(item : ActivityNoticeItem) {
        if (!item.id) {
            return
        }
        if (!item.read) {
            await markActivityNoticeRead(item.id)
            noticeList.value = noticeList.value.map((current) => {
                if (current.id !== item.id) {
                    return current
                }
                return {
                    ...current,
                    read: true,
                }
            })
        }
        uni.navigateTo({
            url: `/pages/activityNotice/activityNoticeDetail?id=${item.id}`,
        })
    }
    uni.navigateTo({
        url: `/pages/activityNotice/activityNoticeDetail?id=${item.id}`,
    })
}
</script>
<style lang="scss" scoped>
.container {
    min-height: 100vh;
    background: #f6f7fb;
    display: flex;
    flex-direction: column;
}
    .container {
        min-height: 100vh;
        background: #f6f7fb;
        display: flex;
        flex-direction: column;
    }
.custom-navbar {
    background: #ffffff;
    position: sticky;
    top: 0;
    z-index: 20;
}
    .custom-navbar {
        background: #ffffff;
        position: sticky;
        top: 0;
        z-index: 20;
    }
.nav-content {
    height: 88rpx;
    padding: 0 32rpx;
    display: flex;
    align-items: center;
    justify-content: space-between;
}
    .nav-content {
        height: 88rpx;
        padding: 0 32rpx;
        display: flex;
        align-items: center;
        justify-content: space-between;
    }
.back-icon {
    width: 40rpx;
    height: 40rpx;
}
    .back-icon {
        width: 40rpx;
        height: 40rpx;
    }
.nav-title {
    font-size: 36rpx;
    line-height: 50rpx;
    font-weight: 600;
    color: #1a1a1a;
}
    .nav-title {
        font-size: 36rpx;
        line-height: 50rpx;
        font-weight: 600;
        color: #1a1a1a;
    }
.nav-placeholder {
    width: 40rpx;
    height: 40rpx;
}
    .nav-placeholder {
        width: 40rpx;
        height: 40rpx;
    }
.list-scroll {
    flex: 1;
    padding: 24rpx 24rpx 40rpx;
    box-sizing: border-box;
}
    .list-scroll {
        flex: 1;
        padding: 24rpx 24rpx 40rpx;
        box-sizing: border-box;
    }
.notice-card {
    background: #ffffff;
    border-radius: 24rpx;
    padding: 28rpx 24rpx;
    margin-bottom: 24rpx;
}
    .notice-card {
        background: #ffffff;
        border-radius: 24rpx;
        padding: 28rpx 24rpx;
        margin-bottom: 24rpx;
    }
.card-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    column-gap: 24rpx;
}
    .card-top {
        display: flex;
        align-items: center;
        justify-content: space-between;
        column-gap: 24rpx;
    }
.title-wrap {
    display: flex;
    align-items: center;
    flex: 1;
    min-width: 0;
}
    .title-wrap {
        display: flex;
        align-items: center;
        flex: 1;
        min-width: 0;
    }
.title {
    font-size: 32rpx;
    line-height: 44rpx;
    color: #1f2329;
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
    .title {
        font-size: 32rpx;
        line-height: 44rpx;
        color: #1f2329;
        font-weight: 500;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
.red-dot {
    width: 14rpx;
    height: 14rpx;
    border-radius: 50%;
    background: #d93026;
    margin-left: 12rpx;
    flex-shrink: 0;
}
    .red-dot {
        width: 14rpx;
        height: 14rpx;
        border-radius: 50%;
        background: #d93026;
        margin-left: 12rpx;
        flex-shrink: 0;
    }
.time {
    font-size: 24rpx;
    line-height: 34rpx;
    color: #86909c;
    flex-shrink: 0;
}
    .time {
        font-size: 24rpx;
        line-height: 34rpx;
        color: #86909c;
        flex-shrink: 0;
    }
.desc {
    margin-top: 16rpx;
    font-size: 26rpx;
    line-height: 38rpx;
    color: #86909c;
}
    .desc {
        margin-top: 16rpx;
        font-size: 26rpx;
        line-height: 38rpx;
        color: #86909c;
    }
.empty-box {
    padding-top: 200rpx;
    display: flex;
    align-items: center;
    justify-content: center;
}
    .empty-box {
        padding-top: 200rpx;
        display: flex;
        align-items: center;
        justify-content: center;
    }
.empty-text,
.footer-text {
    font-size: 26rpx;
    line-height: 36rpx;
    color: #86909c;
    text-align: center;
}
    .empty-text,
    .footer-text {
        font-size: 26rpx;
        line-height: 36rpx;
        color: #86909c;
        text-align: center;
    }
.footer-text {
    padding: 12rpx 0 24rpx;
}
</style>
    .footer-text {
        padding: 12rpx 0 24rpx;
    }
</style>
traditionalApp/pages/home/home.vue
@@ -25,6 +25,7 @@
                <view class="search-btn">搜索</view>
            </view>
            <!-- Banners -->
            <view v-if="bannerList.length" class="banner-section">
                <u-swiper :list="bannerList" :height="280" mode="none" name="imageUrl" bgColor="#fff" border-radius="20"
@@ -34,6 +35,12 @@
                        :class="{ active: bannerActiveIndex === index }"></view>
                </view>
            </view>
            <view class="AI" style="width: 702rpx;height: 160rpx;margin: 0 auto;margin-top: 26rpx;"
                @tap="goMiniProgram">
                <image src="/static/image/home/AI.png" mode="aspectFill" class="w100 h100"></image>
            </view>
            <!-- Live Section -->
            <view v-if="liveCourseList.length" class="section">
@@ -46,8 +53,8 @@
                    <view v-for="item in liveCourseList" :key="item.courseId" class="live-card">
                        <image :src="item.displayImage || defaultLiveCover" mode="aspectFill" class="live-bg"
                            @tap="handleLiveImageClick(item)"></image>
                        <image v-if="item.displayStatus === 'LIVING'" src="/static/image/home/zhibo.png" class="zhibo-icon"
                            mode="aspectFill"></image>
                        <image v-if="item.displayStatus === 'LIVING'" src="/static/image/home/zhibo.png"
                            class="zhibo-icon" mode="aspectFill"></image>
                        <view v-else class="live-bottom-bar">
                            <view class="time-tag" :class="{ ended: item.displayStatus === 'ENDED' }">
                                {{ item.displayStatusText }}
@@ -69,15 +76,19 @@
                        mode="aspectFill"></image>
                </view>
                <view v-if="featuredHealthCourseList.length" class="course-list">
                    <view v-for="item in featuredHealthCourseList" :key="item.id" class="course-item" @tap="goCourseDetail(item.id)">
                        <image :src="item.coverImage || defaultCourseCover" mode="aspectFill" class="course-img"></image>
                    <view v-for="item in featuredHealthCourseList" :key="item.id" class="course-item"
                        @tap="goCourseDetail(item.id)">
                        <image :src="item.coverImage || defaultCourseCover" mode="aspectFill" class="course-img">
                        </image>
                        <view class="course-info">
                            <view class="course-top">
                                <text v-if="resolveCourseTag(item)" class="tag-yangsheng">{{ resolveCourseTag(item) }}</text>
                                <text v-if="resolveCourseTag(item)"
                                    class="tag-yangsheng">{{ resolveCourseTag(item) }}</text>
                                <text class="course-name">{{ item.title }}</text>
                            </view>
                            <view class="course-bottom">
                                <text class="price"><text class="price-symbol">¥</text>{{ formatPrice(item.salePrice) }}</text>
                                <text class="price"><text
                                        class="price-symbol">¥</text>{{ formatPrice(item.salePrice) }}</text>
                                <view class="people">
                                    <image src="/static/image/home/person.png" class="person-icon"></image>
                                    <text>{{ formatLearningCount(item.learnUserCount) }}人正在学</text>
@@ -91,7 +102,8 @@
                <view v-if="featuredPopularizationList.length" class="article-grid">
                    <view v-for="item in featuredPopularizationList" :key="item.id" class="article-card"
                        @tap="goPopularizationDetail(item.id)">
                        <image :src="item.coverImage || defaultPopularizationCover" mode="aspectFill" class="article-bg"></image>
                        <image :src="item.coverImage || defaultPopularizationCover" mode="aspectFill"
                            class="article-bg"></image>
                        <view class="article-title">{{ item.title }}</view>
                    </view>
                </view>
@@ -109,46 +121,46 @@
    import { getBannerList, getHomeFeaturedContent, getHomeLiveCourseList } from "./service";
    interface HomeBannerItem {
        id: number | string;
        imageUrl: string;
        title?: string;
        jumpType?: string;
        targetId?: number | string | null;
        targetUrl?: string;
        id : number | string;
        imageUrl : string;
        title ?: string;
        jumpType ?: string;
        targetId ?: number | string | null;
        targetUrl ?: string;
    }
    interface HomeLiveCourseItem {
        courseId: number | string;
        title: string;
        coverImage?: string;
        liveImage?: string;
        displayImage?: string;
        displayStatus?: 'NOT_STARTED' | 'LIVING' | 'ENDED';
        displayStatusText?: string;
        nextStartTime?: string;
        courseId : number | string;
        title : string;
        coverImage ?: string;
        liveImage ?: string;
        displayImage ?: string;
        displayStatus ?: 'NOT_STARTED' | 'LIVING' | 'ENDED';
        displayStatusText ?: string;
        nextStartTime ?: string;
    }
    interface HomeFeaturedHealthCourseItem {
        id: number | string;
        title: string;
        coverImage?: string;
        levelName?: string;
        difficultyName?: string;
        salePrice?: number | string;
        learnUserCount?: number;
        id : number | string;
        title : string;
        coverImage ?: string;
        levelName ?: string;
        difficultyName ?: string;
        salePrice ?: number | string;
        learnUserCount ?: number;
    }
    interface HomeFeaturedPopularizationItem {
        id: number | string;
        title: string;
        coverImage?: string;
        contentType?: number;
        clickCount?: number;
        id : number | string;
        title : string;
        coverImage ?: string;
        contentType ?: number;
        clickCount ?: number;
    }
    interface HomeFeaturedContentResponse {
        healthCourses?: HomeFeaturedHealthCourseItem[];
        healthPopularizations?: HomeFeaturedPopularizationItem[];
        healthCourses ?: HomeFeaturedHealthCourseItem[];
        healthPopularizations ?: HomeFeaturedPopularizationItem[];
    }
    const statusBarHeight = ref(0);
@@ -231,13 +243,57 @@
                bannerActiveIndex.value = 0;
                return;
            }
            bannerList.value = res.data.filter((item: HomeBannerItem) => !!item?.imageUrl);
            bannerList.value = res.data.filter((item : HomeBannerItem) => !!item?.imageUrl);
            bannerActiveIndex.value = 0;
        } catch {
            bannerList.value = [];
            bannerActiveIndex.value = 0;
        }
    };
    //跳转海诊通小程序
    const goMiniProgram = () => {
        plus.share.getServices((services) => {
            const weixinService = services.find((service) => service.id === 'weixin');
            if (!weixinService) {
                uni.showToast({
                    title: '当前环境不支持打开微信小程序',
                    icon: 'none'
                });
                return;
            }
            if (!weixinService.nativeClient) {
                uni.showToast({
                    title: '请先安装微信客户端',
                    icon: 'none'
                });
                return;
            }
            weixinService.launchMiniProgram({
                // App 端拉起微信小程序需使用原始 ID,若当前值不是原始 ID 请替换为 gh_ 开头的值。
                id: 'gh_e3c3d19c3c71',
                path: 'pages/home/home',
                type: 0
            }, () => {
                console.log('跳转成功');
            }, (err) => {
                console.log('跳转失败', err);
                uni.showToast({
                    title: err?.message === 'badprogram' ? '请检查小程序原始ID及关联配置' : '打开小程序失败',
                    icon: 'none'
                });
            });
        }, (err) => {
            console.log('获取微信服务失败', err);
            uni.showToast({
                title: '微信服务不可用',
                icon: 'none'
            });
        });
        return;
    }
    /**
     * 请求首页养生直播模块列表。
@@ -249,7 +305,7 @@
                liveCourseList.value = [];
                return;
            }
            liveCourseList.value = res.data.filter((item: HomeLiveCourseItem) => !!item?.courseId);
            liveCourseList.value = res.data.filter((item : HomeLiveCourseItem) => !!item?.courseId);
        } catch {
            liveCourseList.value = [];
        }
@@ -268,10 +324,10 @@
            }
            const responseData = res.data as HomeFeaturedContentResponse;
            featuredHealthCourseList.value = Array.isArray(responseData.healthCourses)
                ? responseData.healthCourses.filter((item: HomeFeaturedHealthCourseItem) => !!item?.id)
                ? responseData.healthCourses.filter((item : HomeFeaturedHealthCourseItem) => !!item?.id)
                : [];
            featuredPopularizationList.value = Array.isArray(responseData.healthPopularizations)
                ? responseData.healthPopularizations.filter((item: HomeFeaturedPopularizationItem) => !!item?.id)
                ? responseData.healthPopularizations.filter((item : HomeFeaturedPopularizationItem) => !!item?.id)
                : [];
        } catch {
            featuredHealthCourseList.value = [];
@@ -301,7 +357,7 @@
    /**
     * 将课程价格格式化为首页展示文案。
     */
    const formatPrice = (price?: number | string) => {
    const formatPrice = (price ?: number | string) => {
        const numericPrice = Number(price || 0);
        if (!Number.isFinite(numericPrice)) {
            return '0.00';
@@ -312,7 +368,7 @@
    /**
     * 将学习人数格式化为首页展示文案。
     */
    const formatLearningCount = (count?: number) => {
    const formatLearningCount = (count ?: number) => {
        const safeCount = typeof count === 'number' && count > 0 ? count : 0;
        if (safeCount >= 10000) {
            return `${(Math.round(safeCount / 100) / 100).toFixed(2)}W`;
@@ -323,7 +379,7 @@
    /**
     * 解析首页养生课程卡片标签,优先展示等级,其次展示难度。
     */
    const resolveCourseTag = (item: HomeFeaturedHealthCourseItem) => {
    const resolveCourseTag = (item : HomeFeaturedHealthCourseItem) => {
        if (item.levelName) {
            return item.levelName;
        }
@@ -336,14 +392,14 @@
    /**
     * 同步当前轮播索引,用于自定义指示器展示。
     */
    const handleBannerChange = (index: number) => {
    const handleBannerChange = (index : number) => {
        bannerActiveIndex.value = index;
    };
    /**
     * 根据 banner 跳转类型分发到现有页面。
     */
    const handleBannerClick = (index: number) => {
    const handleBannerClick = (index : number) => {
        const currentBanner = bannerList.value[index];
        if (!currentBanner) {
            return;
@@ -385,21 +441,21 @@
    /**
     * 点击直播图片时统一进入直播详情页。
     */
    const handleLiveImageClick = (item: HomeLiveCourseItem) => {
    const handleLiveImageClick = (item : HomeLiveCourseItem) => {
        goLiveDetail(item.courseId);
    };
    /**
     * 点击直播名称时统一跳转直播介绍页。
     */
    const handleLiveTitleClick = (item: HomeLiveCourseItem) => {
    const handleLiveTitleClick = (item : HomeLiveCourseItem) => {
        goLiveDetail(item.courseId);
    };
    /**
     * 打开第三方链接。
     */
    const openThirdPartyUrl = (targetUrl?: string) => {
    const openThirdPartyUrl = (targetUrl ?: string) => {
        if (!targetUrl) {
            return;
        }
@@ -438,7 +494,7 @@
    /**
     * 跳转直播详情页。
     */
    const goLiveDetail = (courseId?: number | string | null) => {
    const goLiveDetail = (courseId ?: number | string | null) => {
        uni.navigateTo({
            url: courseId ? `/pages/liveDetail/liveDetail?id=${courseId}` : '/pages/liveDetail/liveDetail'
        });
@@ -447,7 +503,7 @@
    /**
     * 跳转养生课程详情页。
     */
    const goCourseDetail = (courseId?: number | string | null) => {
    const goCourseDetail = (courseId ?: number | string | null) => {
        uni.navigateTo({
            url: courseId ? `/pages/courseDetail/courseDetail?id=${courseId}` : '/pages/courseDetail/courseDetail'
        });
@@ -456,7 +512,7 @@
    /**
     * 跳转健康科普详情页。
     */
    const goPopularizationDetail = (popularizationId?: number | string | null) => {
    const goPopularizationDetail = (popularizationId ?: number | string | null) => {
        uni.navigateTo({
            url: popularizationId
                ? `/pages/articleDetail/articleDetail?id=${popularizationId}`
@@ -1064,4 +1120,4 @@
            opacity: 1;
        }
    }
</style>
</style>