<template>
							 | 
						|
								    <view class="article-detail">
							 | 
						|
								        <!-- 导航栏 -->
							 | 
						|
								        <!-- #ifndef H5 -->
							 | 
						|
								        <uv-navbar :placeholder="true" left-icon="arrow-left" :title="articleData.title || '文章详情'"
							 | 
						|
								            @leftClick="goBack"></uv-navbar>
							 | 
						|
								        <!-- #endif -->
							 | 
						|
								
							 | 
						|
								        <!-- 文章内容 -->
							 | 
						|
								        <view class="article-container" v-if="articleData.id">
							 | 
						|
								            <!-- 文章标题 -->
							 | 
						|
								            <view class="article-title">{{ articleData.title }}</view>
							 | 
						|
								
							 | 
						|
								            <!-- 文章信息 -->
							 | 
						|
								            <view class="article-info">
							 | 
						|
								                <text class="article-time">{{ formatTime(articleData.createTime) }}</text>
							 | 
						|
								                <!-- <text class="article-author">{{ articleData.createBy }}</text> -->
							 | 
						|
								            </view>
							 | 
						|
								
							 | 
						|
								            <!-- 文章内容 -->
							 | 
						|
								            <view class="article-content">
							 | 
						|
								                <uv-parse :content="articleData.content"/>
							 | 
						|
								            </view>
							 | 
						|
								        </view>
							 | 
						|
								
							 | 
						|
								        <!-- 加载状态 -->
							 | 
						|
								        <view class="loading-container" v-else-if="loading">
							 | 
						|
								            <uv-loading-icon mode="circle"></uv-loading-icon>
							 | 
						|
								            <text class="loading-text">加载中...</text>
							 | 
						|
								        </view>
							 | 
						|
								
							 | 
						|
								        <!-- 音频播放悬浮按钮 -->
							 | 
						|
								        <view class="audio-float-button" v-if="hasAudio && articleData.id" @click="toggleAudio">
							 | 
						|
								            <uv-icon :name="isPlaying ? 'pause-circle-fill' : 'play-circle-fill'" size="50"
							 | 
						|
								                :color="isPlaying ? '#ff6b6b' : '#4CAF50'"></uv-icon>
							 | 
						|
								        </view>
							 | 
						|
								
							 | 
						|
								    </view>
							 | 
						|
								</template>
							 | 
						|
								
							 | 
						|
								<script>
							 | 
						|
								import audioManager from '@/utils/audioManager.js'
							 | 
						|
								
							 | 
						|
								export default {
							 | 
						|
								    data() {
							 | 
						|
								        return {
							 | 
						|
								            articleId: '',
							 | 
						|
								            articleData: {},
							 | 
						|
								            loading: true,
							 | 
						|
								            isPlaying: false,
							 | 
						|
								            audioUrl: '',
							 | 
						|
								            hasAudio: false
							 | 
						|
								        }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    onLoad(options) {
							 | 
						|
								        if (options.id) {
							 | 
						|
								            this.articleId = options.id
							 | 
						|
								            this.getArticleDetail()
							 | 
						|
								        }
							 | 
						|
								        
							 | 
						|
								        // 绑定音频管理器事件监听
							 | 
						|
								        this.bindAudioEvents()
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    onUnload() {
							 | 
						|
								        // 页面卸载时清理音频资源和事件监听
							 | 
						|
								        this.stopAudio()
							 | 
						|
								        this.unbindAudioEvents()
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    methods: {
							 | 
						|
								        // 绑定音频管理器事件监听
							 | 
						|
								        bindAudioEvents() {
							 | 
						|
								            audioManager.on('play', this.onAudioPlay)
							 | 
						|
								            audioManager.on('pause', this.onAudioPause)
							 | 
						|
								            audioManager.on('ended', this.onAudioEnded)
							 | 
						|
								            audioManager.on('error', this.onAudioError)
							 | 
						|
								        },
							 | 
						|
								
							 | 
						|
								        // 解绑音频管理器事件监听
							 | 
						|
								        unbindAudioEvents() {
							 | 
						|
								            audioManager.off('play', this.onAudioPlay)
							 | 
						|
								            audioManager.off('pause', this.onAudioPause)
							 | 
						|
								            audioManager.off('ended', this.onAudioEnded)
							 | 
						|
								            audioManager.off('error', this.onAudioError)
							 | 
						|
								        },
							 | 
						|
								
							 | 
						|
								        // 音频播放开始事件
							 | 
						|
								        onAudioPlay(data) {
							 | 
						|
								            if (data.audioType === 'article') {
							 | 
						|
								                this.isPlaying = true
							 | 
						|
								                console.log('文章音频开始播放')
							 | 
						|
								            }
							 | 
						|
								        },
							 | 
						|
								
							 | 
						|
								        // 音频暂停事件
							 | 
						|
								        onAudioPause(data) {
							 | 
						|
								            if (data.audioType === 'article') {
							 | 
						|
								                this.isPlaying = false
							 | 
						|
								                console.log('文章音频暂停播放')
							 | 
						|
								            }
							 | 
						|
								        },
							 | 
						|
								
							 | 
						|
								        // 音频播放结束事件
							 | 
						|
								        onAudioEnded(data) {
							 | 
						|
								            if (data.audioType === 'article') {
							 | 
						|
								                this.isPlaying = false
							 | 
						|
								                console.log('文章音频播放结束')
							 | 
						|
								            }
							 | 
						|
								        },
							 | 
						|
								
							 | 
						|
								        // 音频播放错误事件
							 | 
						|
								        onAudioError(data) {
							 | 
						|
								            if (data.audioType === 'article') {
							 | 
						|
								                this.isPlaying = false
							 | 
						|
								                console.error('文章音频播放错误:', data.error)
							 | 
						|
								                uni.showToast({
							 | 
						|
								                    title: '音频播放失败',
							 | 
						|
								                    icon: 'none'
							 | 
						|
								                })
							 | 
						|
								            }
							 | 
						|
								        },
							 | 
						|
								
							 | 
						|
								        // 返回上一页
							 | 
						|
								        goBack() {
							 | 
						|
								            uni.navigateBack()
							 | 
						|
								        },
							 | 
						|
								
							 | 
						|
								        // 获取文章详情
							 | 
						|
								        async getArticleDetail() {
							 | 
						|
								            try {
							 | 
						|
								                this.loading = true
							 | 
						|
								                const res = await this.$api.home.getArticleDetail({ id: this.articleId })
							 | 
						|
								
							 | 
						|
								                if (res.code === 200) {
							 | 
						|
								                    this.articleData = res.result
							 | 
						|
								
							 | 
						|
								                    // #ifdef H5
							 | 
						|
								                    window.document.title = this.articleData.title || '文章详情'
							 | 
						|
								                    // #endif
							 | 
						|
								
							 | 
						|
								                    // 处理音频数据
							 | 
						|
								                    if (res.result.audios && Object.keys(res.result.audios).length > 0) {
							 | 
						|
								                        // 获取第一个音频URL
							 | 
						|
								                        const audioKeys = Object.keys(res.result.audios)
							 | 
						|
								                        this.audioUrl = res.result.audios['501008'] || res.result.audios[audioKeys[0]]
							 | 
						|
								                        this.hasAudio = true
							 | 
						|
								                    }
							 | 
						|
								                } else {
							 | 
						|
								                    uni.showToast({
							 | 
						|
								                        title: res.message || '获取文章详情失败',
							 | 
						|
								                        icon: 'none'
							 | 
						|
								                    })
							 | 
						|
								                }
							 | 
						|
								            } catch (error) {
							 | 
						|
								                console.error('获取文章详情失败:', error)
							 | 
						|
								                uni.showToast({
							 | 
						|
								                    title: '网络错误,请重试',
							 | 
						|
								                    icon: 'none'
							 | 
						|
								                })
							 | 
						|
								            } finally {
							 | 
						|
								                this.loading = false
							 | 
						|
								            }
							 | 
						|
								        },
							 | 
						|
								
							 | 
						|
								        // 切换音频播放状态
							 | 
						|
								        toggleAudio() {
							 | 
						|
								            if (!this.audioUrl) {
							 | 
						|
								                console.error('音频URL为空')
							 | 
						|
								                return
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            try {
							 | 
						|
								                if (this.isPlaying) {
							 | 
						|
								                    // 暂停音频
							 | 
						|
								                    this.pauseAudio()
							 | 
						|
								                } else {
							 | 
						|
								                    // 播放音频
							 | 
						|
								                    this.playAudio()
							 | 
						|
								                }
							 | 
						|
								            } catch (error) {
							 | 
						|
								                console.error('音频播放切换异常:', error)
							 | 
						|
								                this.isPlaying = false
							 | 
						|
								            }
							 | 
						|
								        },
							 | 
						|
								
							 | 
						|
								        // 播放音频
							 | 
						|
								        async playAudio() {
							 | 
						|
								            if (!this.audioUrl) {
							 | 
						|
								                console.error('音频URL为空')
							 | 
						|
								                return
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            try {
							 | 
						|
								                // 使用audioManager播放音频,指定音频类型为'article'
							 | 
						|
								                await audioManager.playAudio(this.audioUrl, 'article')
							 | 
						|
								                console.log('开始播放文章音频:', this.audioUrl)
							 | 
						|
								            } catch (error) {
							 | 
						|
								                console.error('音频播放异常:', error)
							 | 
						|
								                this.isPlaying = false
							 | 
						|
								                uni.showToast({
							 | 
						|
								                    title: '音频播放失败',
							 | 
						|
								                    icon: 'none'
							 | 
						|
								                })
							 | 
						|
								            }
							 | 
						|
								        },
							 | 
						|
								
							 | 
						|
								        // 暂停音频
							 | 
						|
								        pauseAudio() {
							 | 
						|
								            try {
							 | 
						|
								                audioManager.pause()
							 | 
						|
								                console.log('暂停文章音频')
							 | 
						|
								            } catch (error) {
							 | 
						|
								                console.error('暂停音频失败:', error)
							 | 
						|
								            }
							 | 
						|
								        },
							 | 
						|
								
							 | 
						|
								        // 停止音频
							 | 
						|
								        stopAudio() {
							 | 
						|
								            try {
							 | 
						|
								                audioManager.stopCurrentAudio()
							 | 
						|
								                this.isPlaying = false
							 | 
						|
								                console.log('停止文章音频')
							 | 
						|
								            } catch (error) {
							 | 
						|
								                console.error('停止音频失败:', error)
							 | 
						|
								            }
							 | 
						|
								        },
							 | 
						|
								
							 | 
						|
								        // 格式化时间
							 | 
						|
								        formatTime(timeStr) {
							 | 
						|
								            if (!timeStr) return ''
							 | 
						|
								
							 | 
						|
								            // 处理iOS兼容性问题,将 "2025-10-23 16:36:43" 格式转换为 "2025/10/23 16:36:43"
							 | 
						|
								            let formattedTimeStr = timeStr.replace(/-/g, '/')
							 | 
						|
								
							 | 
						|
								            const date = new Date(formattedTimeStr)
							 | 
						|
								
							 | 
						|
								            // 检查日期是否有效
							 | 
						|
								            if (isNaN(date.getTime())) {
							 | 
						|
								                console.warn('Invalid date format:', timeStr)
							 | 
						|
								                return timeStr // 返回原始字符串
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            const year = date.getFullYear()
							 | 
						|
								            const month = String(date.getMonth() + 1).padStart(2, '0')
							 | 
						|
								            const day = String(date.getDate()).padStart(2, '0')
							 | 
						|
								            return `${year}-${month}-${day}`
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								}
							 | 
						|
								</script>
							 | 
						|
								
							 | 
						|
								<style lang="scss" scoped>
							 | 
						|
								.article-detail {
							 | 
						|
								    min-height: 100vh;
							 | 
						|
								    background: #fff;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								.article-container {
							 | 
						|
								    padding: 30rpx;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								.article-title {
							 | 
						|
								    font-size: 40rpx;
							 | 
						|
								    font-weight: 600;
							 | 
						|
								    color: #333;
							 | 
						|
								    line-height: 1.4;
							 | 
						|
								    margin-bottom: 30rpx;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								.article-info {
							 | 
						|
								    display: flex;
							 | 
						|
								    align-items: center;
							 | 
						|
								    gap: 30rpx;
							 | 
						|
								    margin-bottom: 40rpx;
							 | 
						|
								    padding-bottom: 30rpx;
							 | 
						|
								    border-bottom: 1px solid #f0f0f0;
							 | 
						|
								
							 | 
						|
								    .article-time {
							 | 
						|
								        font-size: 26rpx;
							 | 
						|
								        color: #999;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    .article-author {
							 | 
						|
								        font-size: 26rpx;
							 | 
						|
								        color: #666;
							 | 
						|
								
							 | 
						|
								        &::before {
							 | 
						|
								            content: '作者:';
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								.article-content {
							 | 
						|
								    font-size: 32rpx;
							 | 
						|
								    line-height: 1.8;
							 | 
						|
								    color: #333;
							 | 
						|
								
							 | 
						|
								    // 富文本内容样式
							 | 
						|
								    :deep(.rich-text) {
							 | 
						|
								        p {
							 | 
						|
								            margin-bottom: 20rpx;
							 | 
						|
								            line-height: 1.8;
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        img {
							 | 
						|
								            max-width: 100%;
							 | 
						|
								            height: auto;
							 | 
						|
								            border-radius: 8rpx;
							 | 
						|
								            margin: 20rpx 0;
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        section {
							 | 
						|
								            margin: 20rpx 0;
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								.loading-container {
							 | 
						|
								    display: flex;
							 | 
						|
								    flex-direction: column;
							 | 
						|
								    align-items: center;
							 | 
						|
								    justify-content: center;
							 | 
						|
								    height: 400rpx;
							 | 
						|
								
							 | 
						|
								    .loading-text {
							 | 
						|
								        margin-top: 20rpx;
							 | 
						|
								        font-size: 28rpx;
							 | 
						|
								        color: #999;
							 | 
						|
								    }
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// 音频播放悬浮按钮
							 | 
						|
								.audio-float-button {
							 | 
						|
								    position: fixed;
							 | 
						|
								    right: 30rpx;
							 | 
						|
								    bottom: 100rpx;
							 | 
						|
								    width: 100rpx;
							 | 
						|
								    height: 100rpx;
							 | 
						|
								    border-radius: 50%;
							 | 
						|
								    background: rgba(255, 255, 255, 0.9);
							 | 
						|
								    box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
							 | 
						|
								    display: flex;
							 | 
						|
								    align-items: center;
							 | 
						|
								    justify-content: center;
							 | 
						|
								    z-index: 999;
							 | 
						|
								    transition: all 0.3s ease;
							 | 
						|
								
							 | 
						|
								    &:active {
							 | 
						|
								        transform: scale(0.95);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // 添加呼吸动画效果
							 | 
						|
								    &::before {
							 | 
						|
								        content: '';
							 | 
						|
								        position: absolute;
							 | 
						|
								        top: -10rpx;
							 | 
						|
								        left: -10rpx;
							 | 
						|
								        right: -10rpx;
							 | 
						|
								        bottom: -10rpx;
							 | 
						|
								        border-radius: 50%;
							 | 
						|
								        background: rgba(76, 175, 80, 0.2);
							 | 
						|
								        animation: pulse 2s infinite;
							 | 
						|
								        z-index: -1;
							 | 
						|
								    }
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								@keyframes pulse {
							 | 
						|
								    0% {
							 | 
						|
								        transform: scale(1);
							 | 
						|
								        opacity: 1;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    50% {
							 | 
						|
								        transform: scale(1.1);
							 | 
						|
								        opacity: 0.7;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    100% {
							 | 
						|
								        transform: scale(1);
							 | 
						|
								        opacity: 1;
							 | 
						|
								    }
							 | 
						|
								}
							 | 
						|
								</style>
							 |