| 功能 | 状态 | 说明 |
|---|---|---|
| 阅读计时 | ✅ 已完成 | 每秒计时,每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 学到了很多
阅读完成时 → 自动弹出浠宝/福宝对话框
浠宝弹出:"👋 阅读完成!考考你三个问题~"
↓
问题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 |