Browse Source

fix(article): 阅读计时和知识测评适配所有登录用户

- 计时器不再依赖 currentChildId,改为判断 isLogin,已登录用户均可计时
- 匿名用户可浏览文章,读满时长后提示登录后完成知识测评并跳转登录
- 答题接口 getActiveMemberId() 优先 currentChildId,否则用 userId
- 移除 FREE 会员限制,所有登录用户均可参加文章知识测评
E2E Test Bot 3 days ago
parent
commit
adb3381ba0
1 changed files with 31 additions and 23 deletions
  1. 31 23
      cfc-frontend/pages/article-center/article-detail.vue

+ 31 - 23
cfc-frontend/pages/article-center/article-detail.vue

@@ -19,9 +19,9 @@
           <text class="meta-date">{{ formatDate(article.publishedAt) }}</text>
           <text class="meta-sep">|</text>
           <text class="meta-readtime">{{ article.readTime || 3 }}分钟阅读</text>
-           <text class="reading-time-badge" v-if="currentChildId && !readingCompleted">{{ formatReadingTime(readingSeconds) }}</text>
-           <text class="reading-time-badge completed" v-else-if="currentChildId && readingCompleted">✅ 阅读完成</text>
-           <text class="meta-sep" v-if="currentChildId">|</text>
+           <text class="reading-time-badge" v-if="isLogin && !readingCompleted">{{ formatReadingTime(readingSeconds) }}</text>
+            <text class="reading-time-badge completed" v-else-if="isLogin && readingCompleted">✅ 阅读完成</text>
+            <text class="meta-sep" v-if="isLogin">|</text>
            <text class="meta-readcount">{{ article.viewCount || 0 }}人阅读</text>
         </view>
         <view class="detail-category-row">
@@ -85,7 +85,7 @@
 </template>
 
 <script>
-import { getArticleDetail, reportReadingTime, getShareQrCode, completeArticleRead, generateQuiz, submitQuiz, getMyMembership } from '@/utils/api.js'
+import { getArticleDetail, reportReadingTime, getShareQrCode, completeArticleRead, generateQuiz, submitQuiz } from '@/utils/api.js'
 import shareMixin from '../../components/share-mixin.js'
 import ContentSharePoster from '@/components/ContentSharePoster.vue'
 import MpHtml from '@/components/mp-html/mp-html.vue'
@@ -99,7 +99,7 @@ export default {
       articleId: '', article: null, loading: true, error: false, errorMsg: '',
       readingSeconds: 0, lastReportedSeconds: 0, readingCompleted: false,
       isTimerRunning: false, timerHandle: null, syncHandle: null,
-      currentChildId: null,
+      currentChildId: null, isLogin: false,
       showPoster: false, posterQrCode: '',
       posterDimension: '', posterSummary: '', posterInviteText: '',
       contentTagStyle: { p: 'font-size:32rpx;color:#444;line-height:1.8;', div: 'font-size:32rpx;color:#444;line-height:1.8;', section: 'font-size:32rpx;color:#444;line-height:1.8;', li: 'font-size:32rpx;color:#444;line-height:1.8;', blockquote: 'font-size:32rpx;color:#444;line-height:1.8;' },
@@ -132,11 +132,13 @@ export default {
     if (aid) { this.articleId = aid; this.loadDetail(aid) }
     else { this.error = true; this.errorMsg = '参数错误'; this.loading = false }
     this.currentChildId = uni.getStorageSync('currentChildId') || null
+    this.isLogin = !!uni.getStorageSync('token')
   },
   onShow() {
     var memberId = uni.getStorageSync('currentChildId')
-    if (!this.article || this.error || !memberId) return
-    this.startNewReadingSession()
+    if (!this.article || this.error) return
+    // 已登录用户(家长/孩子/规划师)均可计时,匿名用户不计时
+    if (this.isLogin) this.startNewReadingSession()
   },
   onHide() { this.pauseReadingTimer() },
   onUnload() { this.pauseReadingTimer() },
@@ -195,9 +197,16 @@ export default {
       this.lastReportedSeconds = 0
       this.startReadingTimer()
     },
+    // 获取当前操作对象的 memberId:优先 currentChildId(切换视角),否则用 userId
+    getActiveMemberId: function() {
+      var mid = uni.getStorageSync('currentChildId')
+      if (mid) return parseInt(mid)
+      var uid = uni.getStorageSync('userId')
+      return uid ? parseInt(uid) : null
+    },
     startReadingTimer: function() {
-      var memberId = uni.getStorageSync('currentChildId')
-      if (!memberId) return
+      // 无登录态时不计时(匿名浏览只显示时长要求,不计时)
+      if (!this.isLogin) return
       if (this.isTimerRunning || this.readingCompleted) return
       this.isTimerRunning = true
       var self = this
@@ -216,18 +225,18 @@ export default {
       var delta = this.readingSeconds - this.lastReportedSeconds
       if (delta <= 0) return
       this.lastReportedSeconds = this.readingSeconds
-      var memberId = uni.getStorageSync('currentChildId')
-      if (!memberId || !this.article) return
-      reportReadingTime({ articleId: this.article.id, memberId: parseInt(memberId), durationSeconds: delta })
+      var memberId = this.getActiveMemberId()
+      if (!this.isLogin || !this.article) return
+      reportReadingTime({ articleId: this.article.id, memberId: memberId || 0, durationSeconds: delta })
 
       // 达到阅读时长自动完成
       var targetSeconds = (this.article.readTime || 3) * 60
       if (!this.readingCompleted && this.readingSeconds >= targetSeconds) {
         this.readingCompleted = true
         this.pauseReadingTimer()
-        try { await completeArticleRead({ articleId: this.article.id, memberId: parseInt(memberId), durationSeconds: this.readingSeconds }) } catch (e) {}
+        try { await completeArticleRead({ articleId: this.article.id, memberId: memberId || 0, durationSeconds: this.readingSeconds }) } catch (e) {}
         uni.showToast({ title: '阅读完成 +5能量', icon: 'success' })
-        // 弹出答题
+        // 弹出答题(登录用户)
         this.startQuiz()
       }
     },
@@ -260,15 +269,14 @@ export default {
     },
     // 答题
     async startQuiz() {
+      if (!this.isLogin) {
+        uni.showToast({ title: '登录后即可完成知识测评', icon: 'none' })
+        setTimeout(function() { uni.navigateTo({ url: '/pages/login/login' }) }, 1500)
+        return
+      }
+      var memberId = this.getActiveMemberId()
       try {
-        var memRes = await getMyMembership()
-        if (memRes.data && memRes.data.memberLevel && memRes.data.memberLevel === 'FREE') {
-          uni.showToast({ title: '浠宝/福宝答题是会员专属', icon: 'none' })
-          setTimeout(function() { uni.navigateTo({ url: '/pages/membership/upgrade' }) }, 1500)
-          return
-        }
-        var memberId = uni.getStorageSync('currentChildId')
-        var res = await generateQuiz({ articleId: this.articleId, memberId: parseInt(memberId || 0) })
+        var res = await generateQuiz({ articleId: this.articleId, memberId: memberId || 0 })
         if (res.code === 200 && res.data && res.data.questions && res.data.questions.length > 0) {
           this.quizRecordId = res.data.recordId
           this.quizQuestions = res.data.questions
@@ -278,7 +286,7 @@ export default {
       } catch (e) {}
     },
     async submitQuiz() {
-      var memberId = uni.getStorageSync('currentChildId')
+      var memberId = this.getActiveMemberId()
       var answers = []
       for (var i = 0; i < this.quizQuestions.length; i++) {
         answers.push(this.quizAnswers[i] || '')