# 免费版 + Pro 解锁实施 TODO 日期:2026-06-26 范围:TagLauncher 首期“免费下载 + Pro 一次性买断解锁” ## 已冻结的实现原则 1. 免费版保留完整核心价值: - 标签整理 - 基础启动 - Quick Search 2. 首期 Pro 功能范围: - 全部高级主题 - 导入 / 导出布局 - 无限自定义备注 - 手动自定义应用图标排序结果持久化 3. 老用户权益规则: - `originalAppVersion` 早于“免费 + Pro 首个正式版本”则自动获得 Pro - `originalPurchaseDate` 仅在版本信息缺失或不可用时兜底 - 该“首个正式版本”阈值必须收口到单一配置点,发布前再冻结,不允许散落在各业务模块 4. 免费预览绝不能写脏真实数据: - 主题预览不写 `appGridThemeID` - 排序预览不写 `containerAppOrder` - 免费用户触发导入 / 导出时不打开文件面板 - 免费用户第 6 个新备注不写 `appNotes` / `appNoteMetadata` 5. UI 方案: - 不做独立 Pro 页签 - `Data` 页顶部放完整 Pro 状态区 - `Theme` 页顶部放轻量镜像状态条 - 高级功能入口使用小型 `Pro` 胶囊,不做全局 `V` 锁 - 遵循现有设置页语言:克制、原生、低营销 ## 已落地的发布参数 1. Pro 商品 ID:`com.taglauncher.pro.lifetime`,集中在 `ProEntitlementConfig.lifetimeProductID` 2. Pro 价格展示:运行时读取 StoreKit product display price;提交 ASC 时仍需按线上价格最终确认 3. 免费 + Pro 首个正式版本号:`8.1.0`,集中在 `ProEntitlementConfig.firstFreeProVersion` 4. `originalPurchaseDate` 兜底日期:当前保持 `nil`,仅当版本阈值无法判断且后续明确兜底日期时启用 ## Phase 1:权益中心与购买基础能力 - [x] 新增统一权益中心 `ProEntitlementCenter` - [x] 建立状态模型: - [x] 免费用户 - [x] 购买获得 Pro - [x] 老付费自动 Pro - [x] 正在购买 / 正在恢复 - [x] 购买失败 / 取消 / 无可恢复购买 - [x] 接入 StoreKit 2 当前权益查询 - [x] 接入 `Transaction.updates` - [x] 接入购买 Pro - [x] 接入恢复购买 - [x] 加入离线缓存,避免离线启动误丢 Pro - [x] 加入 QA 注入开关: - [x] `TAGLAUNCHER_QA_PRO_STATE=free|pro|legacyPro` - [x] `TAGLAUNCHER_QA_THEME_PREVIEW_SECONDS` ## Phase 2:Pro 功能门禁 ### 主题 - [x] 免费主题固定为:默认、深蓝、黑色 - [x] 其它主题点击进入预览,不直接写持久化主题 - [x] 预览默认 5 分钟,QA 可缩短 - [x] 预览结束恢复进入前真实主题 - [x] Theme 页增加轻量状态条 - [x] Pro 主题卡增加 `Pro` 胶囊 ### 备注 - [x] 统一计算“有非空手写备注的应用数量” - [x] 免费用户允许编辑已有备注 - [x] 免费用户新增第 6 个备注时阻止保存 - [x] 删除 / 清空备注后释放额度 - [x] 备注提示文案与剩余额度联动 ### 排序 - [x] 免费用户允许拖拽排序预览 - [x] 预览只改内存态,不写 `TagEditor.reorderApps` - [x] 退出预览恢复进入前顺序 - [x] Pro 用户按现有逻辑正常持久化 - [x] 明确预览提示,不误导用户“已保存” ### 导入 / 导出 - [x] 免费用户点击导入 / 导出时直接拦截 - [x] 不打开 `NSSavePanel` / `NSOpenPanel` - [x] 设置页按钮旁增加低噪音 `Pro` 标识 - [x] `TagDatabase.exportTo/importFrom` 也补硬门禁,防止绕过 ## Phase 3:设置页与提示 UI - [x] `Data` 页顶部新增完整 Pro 状态区 - [x] 免费态展示: - [x] 权益摘要 - [x] 解锁 Pro - [x] 恢复购买 - [x] 已解锁态展示: - [x] `Pro 已解锁` - [x] 如属老用户,显示“感谢早期支持” - [x] 处理中状态不弹二级窗,按钮原位 loading - [x] 失败 / 取消结果用内联反馈,不打断 - [x] 拦截弹窗统一语法: - [x] 功能名 - [x] 用户收益 - [x] 解锁 Pro - [x] 恢复购买 - [x] 关闭 ## Phase 4:多语言与 QA - [x] 补齐 29 个语言包 Pro 文案 - [x] 禁止任一语种出现其他语种残留 - [x] 增加静态 QA: - [x] 文案键完整性 - [x] 非中文语言禁止混入中文 - [x] 非英文语言禁止直接回退英文关键 Pro 文案 - [x] 增加功能 QA: - [x] 免费 / Pro / legacy Pro 三态源码门禁 - [x] 购买 / 恢复 / 无恢复 / 失败 / 取消状态源码门禁 - [x] 主题预览不写脏数据 - [x] 排序预览不写脏数据 - [x] 备注额度边界 - [x] 导入导出拦截 ## 本轮首期实现范围 本轮先做: 1. 权益中心骨架与 QA 注入 2. 旧付费用户自动 Pro 判定链路 3. 设置页 `Data` / `Theme` 的 Pro UI 4. 主题、导入导出、备注、排序四类门禁接入 5. 最小必要 QA 脚本与 changelog 记录 ## 2026-06-26 实施记录 - 新增 `src/Apptag/ProEntitlement.swift`:统一 Pro 权益中心、StoreKit 2 当前权益 / 交易更新 / 购买 / 恢复、离线缓存、老用户自动 Pro 和 QA 状态注入。 - 新增 `src/Apptag/ProAccessViews.swift`:统一 Pro 胶囊和解锁提示视图。 - 接入 `ApptagApp.swift`、`AppGridTheme.swift`、`ContentView.swift`、`PreferencesView.swift`、`DataLayer.swift`、`L10n.swift`,覆盖主题、导入导出、备注额度、排序持久化和设置页状态入口。 - 补齐 29 个语言包 `pro.*` 文案。 - 新增 `Scripts/pro_localization_qa.sh`:静态检查 29 语种 Pro 文案键完整、占位符完整、无生成污染和无英文兜底复制。 - 新增 `Scripts/pro_feature_gate_qa.sh`:源码门禁 Pro 权益、老用户自动 Pro、主题门禁、导入导出硬拦截、备注额度、排序预览和 Pro UI 提示。 本轮不做: 1. ASC / IAP 上架资料提交 2. TestFlight 真机购买证据 3. 官网 / 支持页口径更新 4. 后续新 Pro 功能扩展