mdView 文档
欢迎使用 mdView 文档系统
👁8 次阅读·📖约 5 分钟

阅读配额与会员升级

概述

mdView 内置了基于角色的阅读配额系统,不同等级的用户在一定时间段内只能阅读指定数量的文章,超出后引导升级会员。

架构

用户请求文档
    │
    ▼
view/index.php 或 share.php
    │
    ├─ Permission 检查(文档等级门禁)  ← 现有逻辑
    │
    ├─ ReadingQuota::canRead()  ← 配额检查
    │     ├─ 查 reading_logs 表 → 统计当日/当周/当月已读数
    │     ├─ 查 settings.reading_quota_config → 当前角色配额上限
    │     └─ 超限 → 渲染超额引导页(含升级按钮)
    │
    ├─ ReadingQuota::logRead()  ← 记录阅读(同日同文去重)
    │
    └─ 正常渲染文档

数据模型

reading_logs

字段类型说明 idINTEGER PK user_idINTEGER用户 ID,0 表示未登录访客 doc_pathTEXT文档路径,如 `vitep/intro.md` ipTEXT访客 IP(未登录时用于去重) read_atTEXT阅读时间 `Y-m-d H:i:s`

去重规则:同一用户 + 同一文档 + 同一自然日 = 计 1 次。

settings 表配置

key = reading_quota_config,value 为 JSON:

{
  "visitor":     {"daily": 3,  "weekly": 10,  "monthly": 30,  "upgrade": "member"},
  "viewer":      {"daily": 5,  "weekly": 20,  "monthly": 50,  "upgrade": "member"},
  "member":      {"daily": 30, "weekly": 100, "monthly": 300, "upgrade": "premium"},
  "premium":     {"daily": 0,  "weekly": 0,   "monthly": 0,   "upgrade": ""},
  "editor":      {"daily": 0,  "weekly": 0,   "monthly": 0,   "upgrade": ""},
  "super_admin": {"daily": 0,  "weekly": 0,   "monthly": 0,   "upgrade": ""}
}

  • daily / weekly / monthly:配额上限,0 = 无限
  • upgrade:超额时推荐的升级角色 slug
  • 角色体系

    slug名称阅读权限每日每周每月 visitor未登录访客查看31030 viewer查看者查看52050 member普通会员查看30100300 premium高级会员查看+下载无限无限无限 editor编辑编辑无限无限无限 super_admin管理员全部无限无限无限

    核心类:ReadingQuota

    方法职责 ------ `getConfig()`从 settings 读取配额 JSON,无数据时用硬编码默认值 `getRoleConfig($slug)`获取指定角色配额 `canRead($userId, $slug, $docPath, $ip)`判断是否可读(查 logs 对比配额) `logRead($userId, $docPath, $ip)`记录阅读(同日同文去重) `getRemaining($userId, $slug, $ip)`返回剩余可读次数 `{daily, weekly, monthly, unlimited}` `renderExceededHtml($slug)`渲染超额提示卡片

    超额提示页

    当用户阅读数超出配额时,页面展示:

  • 📚 图标 + "阅读次数已用完"
  • 具体超额原因(今日/本周/本月)
  • 当前配额说明
  • "⭐ 升级到 XXX" 按钮 → 跳转 /upgrade
  • 剩余量信息 + 返回首页 / 切换账号链接
  • 升级页 /upgrade

    展示会员套餐对比卡片,包含:

  • 当前角色标签
  • 剩余可读次数
  • 套餐配额一览(每日/每周/每月)
  • 升级按钮(联系管理员)
  • 后台管理 /admin/reading-quota

    管理员可在后台直接修改各角色的阅读配额:

  • 可编辑表格:每日/每周/每月配额 + 超额升级目标
  • 保存到 settings.reading_quota_config(即时生效,无需重启)
  • 支持恢复默认配置
  • 调用方式

    前台页面

    view/index.phpshare.php 中,在权限检查后、渲染前插入:

    $quota    = new ReadingQuota();
    $userId   = $quota->getUserId();
    $roleSlug = $quota->getUserRoleSlug();
    $ip       = ReadingQuota::getIp();
    
    if (!$quota->canRead($userId, $roleSlug, $filePath, $ip)) {
        renderQuotaExceeded($title, $tree, $filePath, $quota, $roleSlug);
        return;
    }
    
    $quota->logRead($userId, $filePath, $ip);
    

    判断逻辑(canRead 内部)

  • 获取角色配额 → 若 daily/weekly/monthly 全为 0 → 直接放行
  • 查询 reading_logs 当日/当周/当月去重文章数
  • 任一级别超限 → 返回 false
  • 未超限 → 返回 true
  • 边界场景

    场景处理方式 ------ 未登录访客user_id=0,按 IP 去重,使用 `visitor` 配额 管理员/编辑配额全 0 → 无限,直接放行 分享页访问走同一套配额逻辑 同一文章重复读同日同文只计 1 次 跨天重置每日 00:00 起重新计数 配额配置丢失回退到硬编码默认值(宁可放行不可误拦)

    与 Permission 的关系

    维度PermissionReadingQuota --------- 控制什么能不能看全文(文档等级门禁)能看多少篇(频次限制) 判断依据`文档.level` vs `用户角色.level``reading_logs` 计数 vs 配额上限 执行顺序先后

    两者正交:先过 Permission 门禁(不过则截断预览),再过 Quota 限流(超过则引导升级)。