Sfoglia il codice sorgente

refactor: 统一文章详情页为 article-center/article-detail

删除 pages/mind/article-detail.vue(死代码,未注册)
删除 pages/mind-detail/article-detail.vue(功能不完整,无评论/阅读追踪)
更新 9 个文件的引用路径
移除 pages.json 中的旧注册
Sisyphus 1 mese fa
parent
commit
b8c9b79866

+ 0 - 6
cfc-frontend/pages.json

@@ -904,12 +904,6 @@
             "navigationBarTitleText": "心智成长"
           }
         },
-        {
-          "path": "article-detail",
-          "style": {
-            "navigationBarTitleText": "文章详情"
-          }
-        },
         {
           "path": "training",
           "style": {

+ 1 - 1
cfc-frontend/pages/action/index.vue

@@ -554,7 +554,7 @@ export default {
     },
     goArticleDetail: function(article) {
       var id = article.id || article
-      uni.navigateTo({ url: '/pages/mind-detail/article-detail?id=' + id })
+      uni.navigateTo({ url: '/pages/article-center/article-detail?id=' + id })
     },
     goMoreArticles: function() {
       uni.navigateTo({ url: '/pages/article-center/index?dimension=action' })

+ 1 - 1
cfc-frontend/pages/body/index.vue

@@ -446,7 +446,7 @@ export default {
     },
     goArticleDetail: function(article) {
       var id = article.id || article
-      uni.navigateTo({ url: '/pages/mind-detail/article-detail?id=' + id })
+      uni.navigateTo({ url: '/pages/article-center/article-detail?id=' + id })
     },
     goMoreArticles: function() {
       uni.navigateTo({ url: '/pages/article-center/index?dimension=body' })

+ 1 - 1
cfc-frontend/pages/discover/index.vue

@@ -216,7 +216,7 @@ export default {
       }
     },
     goArticleDetail(id) {
-      uni.navigateTo({ url: '/pages/mind/article-detail?id=' + id })
+      uni.navigateTo({ url: '/pages/article-center/article-detail?id=' + id })
     },
     goKnowledgeCenter() {
       uni.navigateTo({ url: '/pages/mind-extra/articles' })

+ 1 - 1
cfc-frontend/pages/home-pages/parent-index.vue

@@ -1058,7 +1058,7 @@ export default {
     },
     goArticleDetail: function(articleOrId) {
       var id = typeof articleOrId === 'object' ? articleOrId.id : articleOrId
-      uni.navigateTo({ url: '/pages/mind-detail/article-detail?id=' + id })
+      uni.navigateTo({ url: '/pages/article-center/article-detail?id=' + id })
     }
   }
 }

+ 2 - 2
cfc-frontend/pages/index-home/index.vue

@@ -770,7 +770,7 @@ export default {
     },
     goArticleDetail: function(article) {
       var id = article.id || article
-      uni.navigateTo({ url: '/pages/mind-detail/article-detail?id=' + id })
+      uni.navigateTo({ url: '/pages/article-center/article-detail?id=' + id })
     },
     goMoreArticles: function() {
       uni.navigateTo({ url: '/pages/article-center/index?dimension=action' })
@@ -938,7 +938,7 @@ export default {
     },
     goArticleDetail: function(article) {
       var id = article && article.id ? article.id : article
-      uni.navigateTo({ url: '/pages/mind-detail/article-detail?id=' + id })
+      uni.navigateTo({ url: '/pages/article-center/article-detail?id=' + id })
     },
     onTypeChange(value) {
       this.currentType = value

+ 0 - 403
cfc-frontend/pages/mind-detail/article-detail.vue

@@ -1,403 +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>
-      </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="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>
-</template>
-
-<script>
-import { getArticleDetail, recordArticleRead } from '../../utils/api.js'
-import MpHtml from '@/components/mp-html/mp-html.vue'
-
-export default {
-  components: { MpHtml },
-  data() {
-    return {
-      articleId: '',
-      article: null,
-      loading: true,
-      error: false,
-      errorMsg: '',
-      tagList: [],
-      readingSeconds: 0,
-      readingTimer: null,
-      readRecorded: false
-    }
-  },
-  onLoad(options) {
-    if (options && options.id) {
-      this.articleId = options.id
-      this.loadDetail(options.id)
-      this.startReadingTimer()
-    } else {
-      this.error = true
-      this.errorMsg = '参数错误'
-      this.loading = false
-    }
-  },
-  onHide() {
-    this.stopReadingTimer()
-  },
-  onUnload() {
-    this.stopReadingTimer()
-  },
-  methods: {
-    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 = []
-            }
-          }
-        } else {
-          this.error = true
-          this.errorMsg = '文章不存在或无权限查看'
-        }
-      } catch (e) {
-        this.error = true
-        this.errorMsg = '加载失败,请稍后重试'
-      } finally {
-        this.loading = false
-      }
-    },
-    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
-        // Auto-submit when reaching 60 seconds (threshold)
-        // But don't auto-submit - just indicate readiness
-      }, 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)
-    },
-    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)
-    }
-  }
-}
-</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;
-}
-.detail-category {
-  display: inline-block;
-  font-size: 20rpx;
-  color: #5B9BD5;
-  background: rgba(91, 155, 213, 0.1);
-  padding: 4rpx 16rpx;
-  border-radius: 8rpx;
-}
-
-/* ===== 标签 ===== */
-.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;
-}
-</style>

+ 1 - 1
cfc-frontend/pages/mind-detail/articles.vue

@@ -241,7 +241,7 @@ export default {
     },
     goDetail(id) {
       if (this.isLoggedIn) {
-        uni.navigateTo({ url: '/pages/mind/article-detail?id=' + id })
+        uni.navigateTo({ url: '/pages/article-center/article-detail?id=' + id })
       } else {
         uni.navigateTo({ url: '/pages/mind-detail/articles?redirect=' + encodeURIComponent('/pages/mind-detail/articles') })
       }

+ 0 - 751
cfc-frontend/pages/mind/article-detail.vue

@@ -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>

+ 1 - 1
cfc-frontend/pages/mind/index.vue

@@ -758,7 +758,7 @@ components: { TabTransition, PageBanner, RadarChart, LoginGuideCard, FamilyEnerg
     },
     goArticleDetail: function(article) {
       var id = article.id || article
-      uni.navigateTo({ url: '/pages/mind-detail/article-detail?id=' + id })
+      uni.navigateTo({ url: '/pages/article-center/article-detail?id=' + id })
     },
     goMoreRecommend: function() {
       uni.navigateTo({ url: '/pages/discover/index' })

+ 1 - 1
cfc-frontend/pages/wisdom-detail/cognitive-report.vue

@@ -292,7 +292,7 @@ export default {
       }
     },
     goArticle: function(articleId) {
-      uni.navigateTo({ url: '/pages/mind/article-detail?id=' + articleId })
+      uni.navigateTo({ url: '/pages/article-center/article-detail?id=' + articleId })
     },
     goAssessment: function() {
       uni.navigateTo({ url: '/pages/assessment/apply' })

+ 1 - 1
cfc-frontend/pages/wisdom/index.vue

@@ -466,7 +466,7 @@ export default {
       uni.navigateTo({ url: '/pages/article-center/index?dimension=wisdom' })
     },
     goArticleDetail: function(article) {
-      uni.navigateTo({ url: '/pages/mind-detail/article-detail?id=' + (article.id || article) })
+      uni.navigateTo({ url: '/pages/article-center/article-detail?id=' + (article.id || article) })
     },
 
     _watchPageReady() {