article-detail-features.md 6.0 KB

文章详情页功能状态与补充设计

当前状态

功能 状态 说明
阅读计时 ✅ 已完成 每秒计时,每30秒上报后端
分享 ✅ 已完成 微信分享 + 海报生成
自动完成阅读 ❌ 未实现 达到阅读时长后自动触发
文章评论 ❌ 未实现 需新建评论系统
评论审核 ❌ 未实现 管理员/发布人审核
AI答题 ❌ 未实现 浠宝/福宝提问
评论能量 ❌ 未实现 评论后奖励能量
答题能量 ❌ 未实现 答完题奖励能量

补充设计方案

一、自动完成阅读

触发条件: readingSeconds >= article.readTime * 60

前端逻辑(article-detail.vue):

reportReadingTime() {
  // 现有上报逻辑...
  
  // 新增:检查是否达到完成条件
  if (!this.readingCompleted && this.readingSeconds >= (this.article.readTime || 3) * 60) {
    this.completeReading()
  }
},
async completeReading() {
  this.readingCompleted = true
  // 隐藏计时器显示
  // 调用后端记录完成阅读
  await completeArticleRead({ articleId, childId, durationSeconds: this.readingSeconds })
  // 弹出浠宝答题
  this.showQuizDialog()
}

前端显示变化:

  • 达到时长后,右上角的 已读 X分X秒 标签隐藏
  • 后台继续计时但不显示

后端新增接口:

POST /api/articles/complete-read
body: { articleId, childId, durationSeconds }
→ 创建 ArticleReadingRecord(如果已达阅读时长)
→ 发放积分 + 能量

二、文章评论系统

数据库表

CREATE TABLE article_comments (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    article_id BIGINT NOT NULL COMMENT '文章ID',
    parent_id BIGINT COMMENT '父评论ID(回复时填充)',
    reply_to_id BIGINT COMMENT '引用的评论ID',
    user_id BIGINT NOT NULL COMMENT '评论用户ID',
    content TEXT NOT NULL COMMENT '评论内容',
    status VARCHAR(20) DEFAULT 'pending' COMMENT 'pending/approved/rejected',
    audit_by BIGINT COMMENT '审核人ID',
    audit_at DATETIME COMMENT '审核时间',
    earned_energy INT DEFAULT 0 COMMENT '获得的能量',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_article (article_id),
    INDEX idx_article_status (article_id, status),
    INDEX idx_parent (parent_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文章评论';

后端接口

接口 说明 角色
POST /api/articles/comments/list 获取已审核评论列表 所有人
POST /api/articles/comments/create 提交评论(状态=pending) 登录用户
POST /api/articles/comments/audit 审核评论(approved/rejected) 管理员/文章发布人
POST /api/articles/comments/my 查看我的评论 登录用户

审核流程

用户提交评论 → status=pending
  ├─ 文章发布人 → 可在文章详情页审核
  ├─ 文章管理员 → 可在管理后台审核
  └─ 超级管理员 → 可在管理后台审核
      ↓
  审核通过 → status=approved → 前端显示
  审核驳回 → status=rejected → 仅作者可见(显示"审核未通过")

评论的回复结构

评论A(用户1)
  ├─ 回复B(用户2)引用"评论A"内容
  │   └─ 回复C(用户1)引用"回复B"内容(同一层,通过reply_to_id引用)
  └─ 回复D(用户3)引用"评论A"内容

前端展示:

[用户1] 这篇文章写得真好!
  ├ [用户2] @用户1 同意!→ 引用原文
  └ [用户3] @用户1 学到了很多

三、AI答题功能

触发时机

阅读完成时 → 自动弹出浠宝/福宝对话框

交互流程

浠宝弹出:"👋 阅读完成!考考你三个问题~"
  ↓
问题1: "文章中提到...?"(从文章内容提取)
  → 用户选择/输入答案
  ↓
问题2: "..." 
  → 用户选择/输入答案
  ↓
问题3: "..."
  → 用户选择/输入答案
  ↓
"🎉 全部答对!获得 15 能量!"
  ↓
关闭对话框,回到文章底部

后端实现

使用 Dify Workflow API 生成题目:

POST /api/articles/quiz/generate
body: { articleId, childId }
→ 调用 Dify Workflow,传入文章内容
→ 返回 3 个问题(含选项和正确答案)

POST /api/articles/quiz/submit
body: { articleId, childId, answers: [{questionId, answer}] }
→ 比对答案
→ 答对 X 题 → 发放 X*5 能量

前端实现

<!-- 浠宝答题弹窗 -->
<view class="quiz-dialog" v-if="showQuiz">
  <view class="quiz-mascot">
    <image :src="mascotAvatar" />
    <text>{{ mascotName }}: {{ mascotMessage }}</text>
  </view>
  <view class="quiz-question" v-for="(q, i) in quizQuestions" :key="i">
    <text class="q-title">问题{{ i+1 }}: {{ q.question }}</text>
    <view class="q-options">
      <text v-for="opt in q.options" class="q-option"
        :class="{ selected: selectedAnswers[i] === opt }"
        @click="selectedAnswers[i] = opt">{{ opt }}</text>
    </view>
  </view>
  <button @click="submitQuiz">提交答案</button>
</view>

四、能量奖励汇总

行为 能量值 说明
完成阅读 5 达到阅读时长自动发放
发表评论 3 评论提交后发放
评论审核通过 2 额外奖励
答题全对 15 3题全对
答题对1题 5 答对1题
答题对2题 10 答对2题

五、实施路线图

步骤 内容 涉及文件 估算工时
1 后端:ArticleComment 实体 + Mapper 2文件 1h
2 后端:ArticleCommentController + Service 2文件 2h
3 后端:article_comments 表迁移 + schema.sql 2文件 0.5h
4 后端:完成阅读/答题/Dify接口 3文件 2h
5 前端:article-detail 评论区域 1文件 2h
6 前端:浠宝答题弹窗 1文件 2h
7 后端:管理后台评论审核接口 1文件 1h
8 前端:管理后台评论审核页面 1文件 1.5h
合计 13文件 ~12h