|
|
@@ -1,751 +0,0 @@
|
|
|
-<template>
|
|
|
- <view class="detail-container">
|
|
|
- <!-- 加载状态 -->
|
|
|
- <view v-if="loading" class="loading-wrap">
|
|
|
- <view class="loading-spinner"></view>
|
|
|
- <text class="loading-text">加载中...</text>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 错误状态 -->
|
|
|
- <view v-else-if="error" class="error-wrap">
|
|
|
- <text class="error-icon">📄</text>
|
|
|
- <text class="error-text">{{ errorMsg }}</text>
|
|
|
- <button class="retry-btn" @click="loadDetail(articleId)">重新加载</button>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 文章内容 -->
|
|
|
- <view v-else-if="article" class="detail-content">
|
|
|
- <!-- 封面图 -->
|
|
|
- <image
|
|
|
- v-if="article.coverImage"
|
|
|
- class="detail-cover"
|
|
|
- :src="article.coverImage"
|
|
|
- mode="widthFix"
|
|
|
- />
|
|
|
-
|
|
|
- <!-- 文章标题 -->
|
|
|
- <text class="detail-title">{{ article.title }}</text>
|
|
|
-
|
|
|
- <!-- 元信息 -->
|
|
|
- <view class="detail-meta">
|
|
|
- <text class="meta-author">{{ article.author || '浠艾福' }}</text>
|
|
|
- <text class="meta-separator">|</text>
|
|
|
- <text class="meta-date">{{ getFormattedDate() }}</text>
|
|
|
- <text class="meta-separator">|</text>
|
|
|
- <text class="meta-read">{{ article.readTime || 3 }} 分钟阅读</text>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 分类标签 + 内容类型/难度 -->
|
|
|
- <view class="detail-category-row">
|
|
|
- <text class="detail-category">{{ article.categoryName || '' }}</text>
|
|
|
- <text v-if="article.contentType" class="detail-type-badge" :class="'type-' + article.contentType">{{ contentTypeLabel(article.contentType) }}</text>
|
|
|
- <text v-if="article.difficultyLevel && article.difficultyLevel > 0" class="detail-difficulty">{{ '★'.repeat(article.difficultyLevel) }}{{ '☆'.repeat(5 - article.difficultyLevel) }}</text>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 维度标签 -->
|
|
|
- <view v-if="dimensionList.length" class="detail-dimensions">
|
|
|
- <text v-for="(dim, idx) in dimensionList" :key="idx" class="dimension-tag" :style="{ color: dim.color, background: dim.bgColor }">{{ dim.label }}</text>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 知识标签 -->
|
|
|
- <view v-if="tagList.length" class="detail-tags">
|
|
|
- <text v-for="(tag, idx) in tagList" :key="idx" class="tag-item">{{ tag }}</text>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 分割线 -->
|
|
|
- <view class="divider"></view>
|
|
|
-
|
|
|
- <!-- 文章正文(富文本) -->
|
|
|
- <view class="detail-body">
|
|
|
- <mp-html :content="article.content" />
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 收藏按钮 -->
|
|
|
- <view class="action-bar">
|
|
|
- <view class="action-btn" @click="toggleFavorite">
|
|
|
- <text class="action-icon">{{ isFavorited ? '❤️' : '🤍' }}</text>
|
|
|
- <text class="action-text">{{ isFavorited ? '已收藏' : '收藏' }}</text>
|
|
|
- </view>
|
|
|
- <view class="action-btn" @click="handleShare">
|
|
|
- <text class="action-icon">📤</text>
|
|
|
- <text class="action-text">分享</text>
|
|
|
- </view>
|
|
|
- <view class="action-btn">
|
|
|
- <text class="action-icon">👁</text>
|
|
|
- <text class="action-text">{{ article.viewCount || 0 }}</text>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 相关文章 -->
|
|
|
- <view class="related-section" v-if="relatedArticles.length > 0">
|
|
|
- <view class="related-header">
|
|
|
- <text class="related-title">📖 相关推荐</text>
|
|
|
- </view>
|
|
|
- <view class="related-list">
|
|
|
- <view
|
|
|
- v-for="item in relatedArticles"
|
|
|
- :key="item.id"
|
|
|
- class="related-card"
|
|
|
- @click="goRelatedArticle(item.id)"
|
|
|
- >
|
|
|
- <image
|
|
|
- class="related-cover"
|
|
|
- :src="item.coverImage || '/static/default-article.png'"
|
|
|
- mode="aspectFill"
|
|
|
- />
|
|
|
- <view class="related-info">
|
|
|
- <text class="related-name">{{ item.title }}</text>
|
|
|
- <text class="related-summary">{{ item.summary || '' }}</text>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 底部完成按钮 -->
|
|
|
- <view class="detail-footer">
|
|
|
- <!-- 定时器显示 -->
|
|
|
- <view class="reading-timer" v-if="readingSeconds >= 0">
|
|
|
- <text class="timer-icon">⏱</text>
|
|
|
- <text class="timer-text">{{ formatTime(readingSeconds) }}</text>
|
|
|
- <text class="timer-hint" v-if="readingSeconds < 60">阅读{{ 60 - readingSeconds }}秒可获取积分</text>
|
|
|
- <text class="timer-hint timer-ready" v-else>已达标,可领取积分</text>
|
|
|
- </view>
|
|
|
- <!-- 完成按钮 -->
|
|
|
- <button
|
|
|
- class="read-btn"
|
|
|
- :class="{ 'read-btn-active': readingSeconds >= 60 }"
|
|
|
- @click="onReadComplete"
|
|
|
- >阅读完成</button>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 空状态 -->
|
|
|
- <view v-else class="error-wrap">
|
|
|
- <text class="error-icon">📄</text>
|
|
|
- <text class="error-text">文章不存在</text>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 分享弹窗 -->
|
|
|
- <view class="modal-mask" v-if="showShareModal" @click="showShareModal = false">
|
|
|
- <view class="share-modal" @click.stop="">
|
|
|
- <text class="share-modal-title">分享到</text>
|
|
|
- <view class="share-modal-items">
|
|
|
- <view class="share-modal-item" @click="shareToWechat">
|
|
|
- <text class="share-modal-icon">💬</text>
|
|
|
- <text class="share-modal-label">微信好友</text>
|
|
|
- </view>
|
|
|
- <view class="share-modal-item" @click="shareToTimeline">
|
|
|
- <text class="share-modal-icon">📱</text>
|
|
|
- <text class="share-modal-label">朋友圈</text>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
-</template>
|
|
|
-
|
|
|
-<script>
|
|
|
-import { getArticleDetail, getFeaturedArticles, recordArticleRead } from '../../utils/api.js'
|
|
|
-import MpHtml from '@/components/mp-html/mp-html.vue'
|
|
|
-
|
|
|
-var DIMENSION_MAP = {
|
|
|
- body: { label: '身', color: '#FF8C42', bgColor: 'rgba(255,140,66,0.1)' },
|
|
|
- mind: { label: '心', color: '#FF6B9D', bgColor: 'rgba(255,107,157,0.1)' },
|
|
|
- wisdom: { label: '智', color: '#6366F1', bgColor: 'rgba(99,102,241,0.1)' },
|
|
|
- action: { label: '行', color: '#10B981', bgColor: 'rgba(16,185,129,0.1)' },
|
|
|
- wealth: { label: '富', color: '#F59E0B', bgColor: 'rgba(245,158,11,0.1)' }
|
|
|
-}
|
|
|
-
|
|
|
-export default {
|
|
|
- components: { MpHtml },
|
|
|
- data() {
|
|
|
- return {
|
|
|
- articleId: '',
|
|
|
- article: null,
|
|
|
- loading: true,
|
|
|
- error: false,
|
|
|
- errorMsg: '',
|
|
|
- tagList: [],
|
|
|
- dimensionList: [],
|
|
|
- relatedArticles: [],
|
|
|
- readingSeconds: 0,
|
|
|
- readingTimer: null,
|
|
|
- readRecorded: false,
|
|
|
- showShareModal: false,
|
|
|
- isFavorited: false
|
|
|
- }
|
|
|
- },
|
|
|
- onLoad(options) {
|
|
|
- if (options && options.id) {
|
|
|
- this.articleId = options.id
|
|
|
- this.token = uni.getStorageSync('token')
|
|
|
- this.baseUrl = this.token ? '' : ''
|
|
|
- this.loadDetail(options.id)
|
|
|
- this.startReadingTimer()
|
|
|
- } else {
|
|
|
- this.error = true
|
|
|
- this.errorMsg = '参数错误'
|
|
|
- this.loading = false
|
|
|
- }
|
|
|
- },
|
|
|
- onHide() {
|
|
|
- this.stopReadingTimer()
|
|
|
- },
|
|
|
- onUnload() {
|
|
|
- this.stopReadingTimer()
|
|
|
- },
|
|
|
- methods: {
|
|
|
- contentTypeLabel: function(type) {
|
|
|
- var labels = { article: '文章', knowledge: '知识点', course: '课程', tip: '贴士' }
|
|
|
- return labels[type] || type || ''
|
|
|
- },
|
|
|
- async loadDetail(id) {
|
|
|
- this.loading = true
|
|
|
- this.error = false
|
|
|
- try {
|
|
|
- const res = await getArticleDetail({ id: id })
|
|
|
- if (res.code === 200 && res.data) {
|
|
|
- this.article = res.data
|
|
|
- // 解析标签 JSON 字符串
|
|
|
- if (res.data.tags) {
|
|
|
- try {
|
|
|
- let parsed = JSON.parse(res.data.tags)
|
|
|
- this.tagList = Array.isArray(parsed) ? parsed : []
|
|
|
- } catch (e) {
|
|
|
- this.tagList = []
|
|
|
- }
|
|
|
- }
|
|
|
- // 解析维度 ID JSON
|
|
|
- if (res.data.dimensionIds) {
|
|
|
- try {
|
|
|
- var dimIds = JSON.parse(res.data.dimensionIds)
|
|
|
- if (Array.isArray(dimIds)) {
|
|
|
- this.dimensionList = dimIds.map(function(d) {
|
|
|
- return DIMENSION_MAP[d] || { label: d, color: '#64748B', bgColor: 'rgba(100,116,139,0.1)' }
|
|
|
- })
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
- this.dimensionList = []
|
|
|
- }
|
|
|
- }
|
|
|
- // 加载相关文章
|
|
|
- this.loadRelatedArticles()
|
|
|
- } else {
|
|
|
- this.error = true
|
|
|
- this.errorMsg = '文章不存在或无权限查看'
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
- this.error = true
|
|
|
- this.errorMsg = '加载失败,请稍后重试'
|
|
|
- } finally {
|
|
|
- this.loading = false
|
|
|
- }
|
|
|
- },
|
|
|
- async loadRelatedArticles() {
|
|
|
- try {
|
|
|
- var dimensionCode = null
|
|
|
- if (this.article && this.article.dimensionIds) {
|
|
|
- try {
|
|
|
- var dimIds = JSON.parse(this.article.dimensionIds)
|
|
|
- if (Array.isArray(dimIds) && dimIds.length > 0) {
|
|
|
- dimensionCode = dimIds[0]
|
|
|
- }
|
|
|
- } catch (e) {}
|
|
|
- }
|
|
|
- var params = { size: 3 }
|
|
|
- if (dimensionCode) {
|
|
|
- params.dimensionCode = dimensionCode
|
|
|
- }
|
|
|
- const res = await getFeaturedArticles(params)
|
|
|
- if (res.code === 200 && res.data) {
|
|
|
- var list = Array.isArray(res.data) ? res.data : (res.data.records || [])
|
|
|
- // 排除当前文章
|
|
|
- this.relatedArticles = list.filter(function(item) {
|
|
|
- return item.id !== (this.article && this.article.id)
|
|
|
- }.bind(this)).slice(0, 3)
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
- // 静默处理
|
|
|
- }
|
|
|
- },
|
|
|
- getFormattedDate() {
|
|
|
- if (this.article && this.article.publishedAt) {
|
|
|
- return this.article.publishedAt.slice(0, 10)
|
|
|
- }
|
|
|
- return ''
|
|
|
- },
|
|
|
- startReadingTimer() {
|
|
|
- var self = this
|
|
|
- this.readingTimer = setInterval(function() {
|
|
|
- self.readingSeconds = self.readingSeconds + 1
|
|
|
- }, 1000)
|
|
|
- },
|
|
|
- stopReadingTimer() {
|
|
|
- if (this.readingTimer) {
|
|
|
- clearInterval(this.readingTimer)
|
|
|
- this.readingTimer = null
|
|
|
- }
|
|
|
- },
|
|
|
- formatTime(seconds) {
|
|
|
- var m = Math.floor(seconds / 60)
|
|
|
- var s = seconds % 60
|
|
|
- return (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s)
|
|
|
- },
|
|
|
- toggleFavorite: function() {
|
|
|
- this.isFavorited = !this.isFavorited
|
|
|
- uni.showToast({ title: this.isFavorited ? '已收藏' : '已取消收藏', icon: 'none' })
|
|
|
- },
|
|
|
- handleShare: function() {
|
|
|
- var self = this
|
|
|
- uni.showActionSheet({
|
|
|
- itemList: ['微信好友', '朋友圈', '保存图片'],
|
|
|
- success: function(res) {
|
|
|
- var channel = 'wechat'
|
|
|
- if (res.tapIndex === 1) channel = 'friend'
|
|
|
-
|
|
|
- uni.request({
|
|
|
- url: self.baseUrl + '/api/share/create',
|
|
|
- method: 'POST',
|
|
|
- header: { 'Authorization': 'Bearer ' + self.token },
|
|
|
- data: {
|
|
|
- targetType: 'article',
|
|
|
- targetId: self.articleId,
|
|
|
- shareChannel: channel,
|
|
|
- title: self.article && self.article.title ? self.article.title : ''
|
|
|
- },
|
|
|
- success: function(createRes) {
|
|
|
- if (createRes.data && createRes.data.code === 200) {
|
|
|
- var shareEvent = createRes.data.data
|
|
|
- uni.showToast({ title: '分享成功', icon: 'success' })
|
|
|
-
|
|
|
- uni.request({
|
|
|
- url: self.baseUrl + '/api/share/click',
|
|
|
- method: 'POST',
|
|
|
- header: { 'Authorization': 'Bearer ' + self.token },
|
|
|
- data: { shareEventId: shareEvent.id }
|
|
|
- })
|
|
|
-
|
|
|
- self.showShareModal = true
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
- })
|
|
|
- },
|
|
|
- shareToWechat: function() {
|
|
|
- this.showShareModal = false
|
|
|
- uni.showToast({ title: '请使用微信分享', icon: 'none' })
|
|
|
- },
|
|
|
- shareToTimeline: function() {
|
|
|
- this.showShareModal = false
|
|
|
- uni.showToast({ title: '请使用微信朋友圈', icon: 'none' })
|
|
|
- },
|
|
|
- async onReadComplete() {
|
|
|
- if (this.readRecorded) {
|
|
|
- uni.navigateBack()
|
|
|
- return
|
|
|
- }
|
|
|
- this.stopReadingTimer()
|
|
|
- try {
|
|
|
- var childId = uni.getStorageSync('currentChildId')
|
|
|
- var res = await recordArticleRead({
|
|
|
- id: this.article.id,
|
|
|
- durationSeconds: this.readingSeconds,
|
|
|
- childId: childId || undefined
|
|
|
- })
|
|
|
- this.readRecorded = true
|
|
|
- if (res.data && res.data.pointsEarned > 0) {
|
|
|
- uni.showToast({ title: '获得' + res.data.pointsEarned + '积分!', icon: 'success' })
|
|
|
- } else if (res.data && res.data.belowThreshold) {
|
|
|
- uni.showToast({ title: '阅读时间未达标', icon: 'none' })
|
|
|
- } else if (res.data && res.data.alreadyCompleted) {
|
|
|
- uni.showToast({ title: '已读过此文', icon: 'none' })
|
|
|
- } else {
|
|
|
- uni.showToast({ title: '阅读记录已保存', icon: 'success' })
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
- uni.showToast({ title: '记录保存失败', icon: 'none' })
|
|
|
- }
|
|
|
- var self = this
|
|
|
- setTimeout(function() {
|
|
|
- uni.navigateBack()
|
|
|
- }, 1500)
|
|
|
- },
|
|
|
- goRelatedArticle: function(id) {
|
|
|
- uni.redirectTo({ url: '/pages/mind/article-detail?id=' + id })
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-</script>
|
|
|
-
|
|
|
-<style scoped>
|
|
|
-.detail-container {
|
|
|
- min-height: 100vh;
|
|
|
- background: #fff;
|
|
|
- padding-bottom: 120rpx;
|
|
|
-}
|
|
|
-
|
|
|
-/* ===== 加载状态 ===== */
|
|
|
-.loading-wrap {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- padding-top: 300rpx;
|
|
|
-}
|
|
|
-.loading-spinner {
|
|
|
- width: 60rpx;
|
|
|
- height: 60rpx;
|
|
|
- border: 4rpx solid #e0e0e0;
|
|
|
- border-top-color: #5B9BD5;
|
|
|
- border-radius: 50%;
|
|
|
- animation: spin 0.8s linear infinite;
|
|
|
- margin-bottom: 20rpx;
|
|
|
-}
|
|
|
-@keyframes spin {
|
|
|
- 0% { transform: rotate(0deg); }
|
|
|
- 100% { transform: rotate(360deg); }
|
|
|
-}
|
|
|
-.loading-text {
|
|
|
- font-size: 26rpx;
|
|
|
- color: #999;
|
|
|
-}
|
|
|
-
|
|
|
-/* ===== 错误状态 ===== */
|
|
|
-.error-wrap {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- align-items: center;
|
|
|
- padding-top: 300rpx;
|
|
|
-}
|
|
|
-.error-icon {
|
|
|
- font-size: 100rpx;
|
|
|
- margin-bottom: 24rpx;
|
|
|
-}
|
|
|
-.error-text {
|
|
|
- font-size: 28rpx;
|
|
|
- color: #999;
|
|
|
- margin-bottom: 30rpx;
|
|
|
-}
|
|
|
-.retry-btn {
|
|
|
- width: 240rpx;
|
|
|
- height: 72rpx;
|
|
|
- line-height: 72rpx;
|
|
|
- background: #5B9BD5;
|
|
|
- color: #fff;
|
|
|
- font-size: 28rpx;
|
|
|
- border-radius: 36rpx;
|
|
|
- text-align: center;
|
|
|
- border: none;
|
|
|
-}
|
|
|
-.retry-btn::after {
|
|
|
- border: none;
|
|
|
-}
|
|
|
-
|
|
|
-/* ===== 内容区 ===== */
|
|
|
-.detail-cover {
|
|
|
- width: 100%;
|
|
|
- max-height: 500rpx;
|
|
|
- display: block;
|
|
|
-}
|
|
|
-.detail-title {
|
|
|
- display: block;
|
|
|
- font-size: 36rpx;
|
|
|
- font-weight: bold;
|
|
|
- color: #333;
|
|
|
- line-height: 1.4;
|
|
|
- padding: 30rpx 30rpx 0;
|
|
|
-}
|
|
|
-
|
|
|
-/* ===== 元信息 ===== */
|
|
|
-.detail-meta {
|
|
|
- display: flex;
|
|
|
- flex-direction: row;
|
|
|
- align-items: center;
|
|
|
- padding: 16rpx 30rpx 0;
|
|
|
- font-size: 22rpx;
|
|
|
- color: #999;
|
|
|
-}
|
|
|
-.meta-author {
|
|
|
- color: #5B9BD5;
|
|
|
-}
|
|
|
-.meta-separator {
|
|
|
- margin: 0 12rpx;
|
|
|
- color: #ddd;
|
|
|
-}
|
|
|
-.meta-date,
|
|
|
-.meta-read {
|
|
|
- color: #999;
|
|
|
-}
|
|
|
-
|
|
|
-/* ===== 分类标签 ===== */
|
|
|
-.detail-category-row {
|
|
|
- padding: 16rpx 30rpx 0;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- gap: 12rpx;
|
|
|
- flex-wrap: wrap;
|
|
|
-}
|
|
|
-.detail-category {
|
|
|
- display: inline-block;
|
|
|
- font-size: 20rpx;
|
|
|
- color: #5B9BD5;
|
|
|
- background: rgba(91, 155, 213, 0.1);
|
|
|
- padding: 4rpx 16rpx;
|
|
|
- border-radius: 8rpx;
|
|
|
-}
|
|
|
-.detail-type-badge {
|
|
|
- display: inline-block;
|
|
|
- font-size: 18rpx;
|
|
|
- padding: 2rpx 12rpx;
|
|
|
- border-radius: 6rpx;
|
|
|
- background: #f0f0f0;
|
|
|
- color: #666;
|
|
|
-}
|
|
|
-.detail-type-badge.type-article {
|
|
|
- background: #e8f4fd;
|
|
|
- color: #2b7fc4;
|
|
|
-}
|
|
|
-.detail-type-badge.type-knowledge {
|
|
|
- background: #e8f8ee;
|
|
|
- color: #2a9055;
|
|
|
-}
|
|
|
-.detail-type-badge.type-course {
|
|
|
- background: #fef3e2;
|
|
|
- color: #c47a2b;
|
|
|
-}
|
|
|
-.detail-type-badge.type-tip {
|
|
|
- background: #f3e8fd;
|
|
|
- color: #7b2bc4;
|
|
|
-}
|
|
|
-.detail-difficulty {
|
|
|
- font-size: 18rpx;
|
|
|
- color: #f59e0b;
|
|
|
- margin-left: 4rpx;
|
|
|
-}
|
|
|
-
|
|
|
-/* ===== 维度标签 ===== */
|
|
|
-.detail-dimensions {
|
|
|
- display: flex;
|
|
|
- flex-direction: row;
|
|
|
- padding: 8rpx 30rpx 0;
|
|
|
- gap: 10rpx;
|
|
|
-}
|
|
|
-.dimension-tag {
|
|
|
- font-size: 18rpx;
|
|
|
- padding: 2rpx 14rpx;
|
|
|
- border-radius: 6rpx;
|
|
|
-}
|
|
|
-
|
|
|
-/* ===== 标签 ===== */
|
|
|
-.detail-tags {
|
|
|
- display: flex;
|
|
|
- flex-direction: row;
|
|
|
- flex-wrap: wrap;
|
|
|
- padding: 12rpx 30rpx 0;
|
|
|
- gap: 12rpx;
|
|
|
-}
|
|
|
-.tag-item {
|
|
|
- font-size: 20rpx;
|
|
|
- color: #8B5CF6;
|
|
|
- background: rgba(139, 92, 246, 0.08);
|
|
|
- padding: 4rpx 14rpx;
|
|
|
- border-radius: 8rpx;
|
|
|
-}
|
|
|
-
|
|
|
-/* ===== 分割线 ===== */
|
|
|
-.divider {
|
|
|
- height: 1rpx;
|
|
|
- background: #eee;
|
|
|
- margin: 24rpx 30rpx;
|
|
|
-}
|
|
|
-
|
|
|
-/* ===== 正文 ===== */
|
|
|
-.detail-body {
|
|
|
- padding: 0 30rpx;
|
|
|
- font-size: 28rpx;
|
|
|
- color: #444;
|
|
|
- line-height: 1.8;
|
|
|
-}
|
|
|
-.detail-body rich-text {
|
|
|
- word-break: break-word;
|
|
|
-}
|
|
|
-
|
|
|
-/* ===== 定时器 ===== */
|
|
|
-.reading-timer {
|
|
|
- display: flex;
|
|
|
- flex-direction: row;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- padding: 16rpx 0 20rpx;
|
|
|
-}
|
|
|
-.timer-icon {
|
|
|
- font-size: 32rpx;
|
|
|
- margin-right: 8rpx;
|
|
|
-}
|
|
|
-.timer-text {
|
|
|
- font-size: 32rpx;
|
|
|
- font-weight: bold;
|
|
|
- color: #333;
|
|
|
- margin-right: 16rpx;
|
|
|
-}
|
|
|
-.timer-hint {
|
|
|
- font-size: 22rpx;
|
|
|
- color: #999;
|
|
|
-}
|
|
|
-.timer-ready {
|
|
|
- color: #22c55e;
|
|
|
- font-weight: bold;
|
|
|
-}
|
|
|
-
|
|
|
-/* ===== 底部按钮 ===== */
|
|
|
-.detail-footer {
|
|
|
- padding: 40rpx 60rpx;
|
|
|
-}
|
|
|
-.read-btn {
|
|
|
- width: 100%;
|
|
|
- height: 88rpx;
|
|
|
- line-height: 88rpx;
|
|
|
- background: #ddd;
|
|
|
- color: #fff;
|
|
|
- font-size: 32rpx;
|
|
|
- font-weight: bold;
|
|
|
- border-radius: 44rpx;
|
|
|
- text-align: center;
|
|
|
- border: none;
|
|
|
- transition: background 0.3s;
|
|
|
-}
|
|
|
-.read-btn-active {
|
|
|
- background: linear-gradient(135deg, #5B9BD5, #3A7CC4);
|
|
|
-}
|
|
|
-.read-btn::after {
|
|
|
- border: none;
|
|
|
-}
|
|
|
-
|
|
|
-/* ===== 操作栏 ===== */
|
|
|
-.action-bar {
|
|
|
- display: flex;
|
|
|
- flex-direction: row;
|
|
|
- justify-content: space-around;
|
|
|
- padding: 24rpx 30rpx;
|
|
|
- border-bottom: 1rpx solid #eee;
|
|
|
-}
|
|
|
-.action-btn {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- align-items: center;
|
|
|
- padding: 8rpx 24rpx;
|
|
|
-}
|
|
|
-.action-icon {
|
|
|
- font-size: 36rpx;
|
|
|
- margin-bottom: 6rpx;
|
|
|
-}
|
|
|
-.action-text {
|
|
|
- font-size: 22rpx;
|
|
|
- color: #666;
|
|
|
-}
|
|
|
-
|
|
|
-/* ===== 相关推荐 ===== */
|
|
|
-.related-section {
|
|
|
- padding: 30rpx;
|
|
|
-}
|
|
|
-.related-header {
|
|
|
- margin-bottom: 20rpx;
|
|
|
-}
|
|
|
-.related-title {
|
|
|
- font-size: 30rpx;
|
|
|
- font-weight: bold;
|
|
|
- color: #333;
|
|
|
-}
|
|
|
-.related-list {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- gap: 20rpx;
|
|
|
-}
|
|
|
-.related-card {
|
|
|
- display: flex;
|
|
|
- flex-direction: row;
|
|
|
- background: #fff;
|
|
|
- border-radius: 16rpx;
|
|
|
- overflow: hidden;
|
|
|
- box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.06);
|
|
|
-}
|
|
|
-.related-cover {
|
|
|
- width: 180rpx;
|
|
|
- height: 140rpx;
|
|
|
- flex-shrink: 0;
|
|
|
- background: linear-gradient(135deg, #667eea, #764ba2);
|
|
|
-}
|
|
|
-.related-info {
|
|
|
- flex: 1;
|
|
|
- padding: 16rpx;
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- justify-content: center;
|
|
|
-}
|
|
|
-.related-name {
|
|
|
- font-size: 26rpx;
|
|
|
- font-weight: bold;
|
|
|
- color: #333;
|
|
|
- display: -webkit-box;
|
|
|
- -webkit-line-clamp: 2;
|
|
|
- -webkit-box-orient: vertical;
|
|
|
- overflow: hidden;
|
|
|
- margin-bottom: 8rpx;
|
|
|
-}
|
|
|
-.related-summary {
|
|
|
- font-size: 22rpx;
|
|
|
- color: #999;
|
|
|
- display: -webkit-box;
|
|
|
- -webkit-line-clamp: 1;
|
|
|
- -webkit-box-orient: vertical;
|
|
|
- overflow: hidden;
|
|
|
-}
|
|
|
-}
|
|
|
-.share-btn::after {
|
|
|
- border: none;
|
|
|
-}
|
|
|
-
|
|
|
-/* ===== 分享弹窗 ===== */
|
|
|
-.modal-mask {
|
|
|
- position: fixed;
|
|
|
- top: 0;
|
|
|
- left: 0;
|
|
|
- right: 0;
|
|
|
- bottom: 0;
|
|
|
- background: rgba(0, 0, 0, 0.5);
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- justify-content: flex-end;
|
|
|
- z-index: 1000;
|
|
|
-}
|
|
|
-.share-modal {
|
|
|
- background: #fff;
|
|
|
- border-radius: 24rpx 24rpx 0 0;
|
|
|
- padding: 40rpx;
|
|
|
-}
|
|
|
-.share-modal-title {
|
|
|
- display: block;
|
|
|
- text-align: center;
|
|
|
- font-size: 32rpx;
|
|
|
- font-weight: bold;
|
|
|
- margin-bottom: 32rpx;
|
|
|
-}
|
|
|
-.share-modal-items {
|
|
|
- display: flex;
|
|
|
- justify-content: space-around;
|
|
|
-}
|
|
|
-.share-modal-item {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- align-items: center;
|
|
|
-}
|
|
|
-.share-modal-icon {
|
|
|
- font-size: 48rpx;
|
|
|
- margin-bottom: 12rpx;
|
|
|
-}
|
|
|
-.share-modal-label {
|
|
|
- font-size: 24rpx;
|
|
|
- color: #64748B;
|
|
|
-}
|
|
|
-</style>
|