switch API to HTTPS api.longde.cloud, remove NSAllowsArbitraryLoads, migrate docs to startup-plan
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
d7e57dcebc
commit
dc4ad424e2
@ -5,7 +5,7 @@
|
||||
import Foundation
|
||||
|
||||
enum APIConfig {
|
||||
static let baseURL = "http://81.70.187.179:3001"
|
||||
static let baseURL = "https://api.longde.cloud"
|
||||
|
||||
static let timeout: TimeInterval = 30
|
||||
|
||||
|
||||
@ -18,11 +18,6 @@
|
||||
<string>$(MARKETING_VERSION)</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>UIApplicationSceneManifest</key>
|
||||
<dict>
|
||||
<key>UIApplicationSupportsMultipleScenes</key>
|
||||
|
||||
@ -1,668 +0,0 @@
|
||||
# 缺失项与待补全方向
|
||||
|
||||
> 基于 v0.1 创业计划文档与当前 iOS 代码对比分析
|
||||
> 整理时间:2026-05-10
|
||||
|
||||
本文档系统性列出知习 iOS App 当前在架构、页面、功能、设计等方面的缺失项,并给出优先级建议。
|
||||
|
||||
---
|
||||
|
||||
## 一、架构层缺失
|
||||
|
||||
### 1.1 MVVM 分层
|
||||
|
||||
**现状**:全部代码写在 SwiftUI View 中,无任何 ViewModel/ObservableObject/@Published。grep 搜索 ViewModel、ObservableObject、@Published 均为零结果。
|
||||
|
||||
**缺失**:
|
||||
- 无 ViewModel 层,业务逻辑、状态管理、数据转换全部堆在 View 里
|
||||
- 无 Model 层,数据结构通过 View 内的局部 struct 或硬编码数据隐式定义
|
||||
- 代码不可测试,无法单独验证业务逻辑
|
||||
|
||||
**计划要求**(`官网与技术基础.md` 第 5.3 节):
|
||||
```
|
||||
AIStudyApp/
|
||||
├── Features/
|
||||
│ ├── Onboarding/
|
||||
│ │ ├── Views/ ← 当前有,但无 ViewModel/Model 子目录
|
||||
│ │ ├── ViewModels/ ← 缺失
|
||||
│ │ └── Models/ ← 缺失
|
||||
```
|
||||
|
||||
### 1.2 Service 层
|
||||
|
||||
**现状**:无任何 Service 类,AI 分析、学习记录、用户管理等概念没有对应的服务抽象。
|
||||
|
||||
**缺失**:
|
||||
| Service | 职责 | 涉及的计划数据实体 |
|
||||
|---------|------|-------------------|
|
||||
| AuthService | Apple 登录、Token 管理、会话维护 | User |
|
||||
| LearningService | 学习记录 CRUD、进度追踪 | LearningSession |
|
||||
| AIService | AI 分析请求代理、结果解析 | AIAnalysis |
|
||||
| ReviewService | 复习任务生成、调度 | ReviewTask |
|
||||
| KnowledgeService | 知识库/路径/课程查询 | KnowledgeBase, LearningPath, Lesson |
|
||||
| FeedbackService | 用户反馈提交 | Feedback |
|
||||
|
||||
### 1.3 Repository 层
|
||||
|
||||
**现状**:零数据持久化,所有"数据"均为 View 中硬编码的 mock。
|
||||
|
||||
**缺失**:
|
||||
- 无数据访问抽象(未来可能切换 CoreData → API,需要 Repository 隔离)
|
||||
- 无本地缓存层
|
||||
- 无网络数据源层
|
||||
|
||||
### 1.4 网络层
|
||||
|
||||
**现状**:无任何网络请求代码,无 APIClient,无 URLSession 调用。
|
||||
|
||||
**缺失**:
|
||||
- APIClient(封装 URLSession,注入 baseURL、header、token)
|
||||
- APIEndpoint(枚举化 API 路径,统一请求构建)
|
||||
- APIError(统一错误模型和处理)
|
||||
- 请求/响应拦截器(日志、token 刷新)
|
||||
- Mock 层(本地开发和 UI 预览用)
|
||||
|
||||
### 1.5 依赖注入
|
||||
|
||||
**现状**:无任何 DI 模式,Service 和 ViewModel 尚未创建,暂时不存在注入问题。但需要在架构搭建时建立模式。
|
||||
|
||||
**建议**:初期使用构造函数注入 + `@EnvironmentObject`,避免引入第三方 DI 框架。
|
||||
|
||||
---
|
||||
|
||||
## 二、核心能力缺失
|
||||
|
||||
### 2.1 Sign in with Apple
|
||||
|
||||
**现状**:`LoginPage` 有 UI(手机号/邮箱/微信/Apple 入口),但 `AIStudyAppApp` 仅用 `@AppStorage("hasCompletedOnboarding")` 控制是否进入主界面,无实际认证。
|
||||
|
||||
**计划要求**:第一版登录方式仅为 Sign in with Apple(`Demo与MVP.md` 第 5.2 节)。
|
||||
|
||||
**需实现**:
|
||||
- ASAuthorizationController 集成
|
||||
- 获取 appleUserId、email、displayName
|
||||
- 后端验证 identityToken
|
||||
- Token 本地安全存储(Keychain)
|
||||
- 登录状态管理
|
||||
|
||||
### 2.2 后端 API 对接
|
||||
|
||||
**现状**:所有页面为静态 UI,无任何网络请求。
|
||||
|
||||
**计划定义的 P0 API**:
|
||||
- `POST /ai/analyze-learning-input` — AI 分析用户学习输入
|
||||
- `POST /ai/chat` — AI 对话
|
||||
- 用户/知识库/学习记录/反馈 CRUD
|
||||
|
||||
### 2.3 真实 AI 集成
|
||||
|
||||
**现状**:AI 相关页面全为静态文本。
|
||||
|
||||
**需对接**:
|
||||
- 后端 AI Provider 抽象层(MiniMax/DeepSeek/OpenAI 等)
|
||||
- 结构化 JSON 输出解析
|
||||
- AI 分析结果展示(掌握度评分、优缺点、建议)
|
||||
- AI 对话流式响应
|
||||
|
||||
### 2.4 本地数据持久化
|
||||
|
||||
**现状**:零持久化实现。
|
||||
|
||||
**需实现**:
|
||||
- UserDefaults / @AppStorage(简单偏好)
|
||||
- Keychain(Token、敏感信息)
|
||||
- 后续可考虑 CoreData 或 SwiftData(学习记录离线缓存)
|
||||
|
||||
### 2.5 多语言本地化
|
||||
|
||||
**现状**:所有文案硬编码在 View 中,无 Localizable.xcstrings 文件。
|
||||
|
||||
**计划要求**(`Demo与MVP.md` 第 6 节):
|
||||
- 默认简体中文
|
||||
- 预留英文
|
||||
- App UI 文案使用本地化资源
|
||||
|
||||
**需实现**:
|
||||
- 创建 `Localizable.xcstrings`
|
||||
- 将所有硬编码文案迁移为 `LocalizedStringKey`
|
||||
- 支持语言切换
|
||||
|
||||
### 2.6 错误/加载/空状态处理
|
||||
|
||||
**现状**:无任何错误处理、加载态、空状态 UI。
|
||||
|
||||
**至少需要**:
|
||||
- 网络请求 loading 指示器
|
||||
- 网络错误提示和重试按钮
|
||||
- AI 分析中的等待状态
|
||||
- 列表空状态(如知识库为空时的引导)
|
||||
- 登录失败错误提示
|
||||
|
||||
---
|
||||
|
||||
## 三、页面层面差距
|
||||
|
||||
### 3.1 与计划页面对比
|
||||
|
||||
| 计划页面 | 计划优先级 | 当前状态 | 说明 |
|
||||
|----------|-----------|---------|------|
|
||||
| 启动页/欢迎页 | P1 | ✅ 已实现 | SplashPage + WelcomePage |
|
||||
| 登录页 | P0 | ⚠️ 过度实现 | UI 包含计划不做的手机号/邮箱/微信登录 |
|
||||
| 语言与偏好页 | P1 | ❌ 未实现 | 无页面 |
|
||||
| 学习方向选择页 | P0 | ⚠️ 部分实现 | GoalSetupPage 有目标选择,但非学习方向选择 |
|
||||
| 学习路径页 | P0 | ✅ 已实现 | LibraryDetailPage |
|
||||
| 今日学习任务页 | P0 | ✅ 已实现 | StudyHomeView |
|
||||
| 内容阅读页 | P0 | ✅ 已实现 | KnowledgeDetailPage |
|
||||
| 主动回忆/笔记输入页 | P0 | ✅ 已实现 | DailyThinkingPage + RecallTestPage |
|
||||
| AI 分析结果页 | P0 | ✅ 已实现 | AIFeedbackPage |
|
||||
| AI 对话页 | P0 | ✅ 已实现 | AIChatPage |
|
||||
| 复习计划页 | P0 | ❌ 未独立 | 仅在 StudyHomeView 任务列表中混合出现 |
|
||||
| 学习进度页 | P1 | ✅ 已实现 | AnalysisHomeView |
|
||||
| 设置页 | P1 | ⚠️ 部分实现 | ProfileView 有设置菜单,但功能入口为空 |
|
||||
| 反馈页 | P1 | ❌ 未实现 | 无反馈收集入口 |
|
||||
|
||||
### 3.2 复习计划页(P0 缺失)
|
||||
|
||||
**计划描述**:系统生成复习任务,用户查看待复习内容,按推荐时间安排学习。
|
||||
|
||||
**当前**:复习任务混在 StudyHomeView 的任务列表里(如"高数 - 间隔复习 8 题"),缺少独立的复习计划视图。
|
||||
|
||||
**需实现**:
|
||||
- 独立的 `ReviewPlanView`
|
||||
- 按时间线展示待复习任务(今天、明天、本周)
|
||||
- 复习项来源标注(哪个知识点的第几次复习)
|
||||
- 复习完成状态追踪
|
||||
|
||||
### 3.3 反馈页(P1 缺失)
|
||||
|
||||
**计划描述**:App 内反馈入口,让内测用户提交问题和建议。
|
||||
|
||||
**需实现**:
|
||||
- 简洁的反馈表单(文本输入 + 分类选择)
|
||||
- 提交到后端 `/feedback` 接口
|
||||
- 确认提交状态页
|
||||
|
||||
### 3.4 等待名单入口
|
||||
|
||||
**计划**:官网 `/waitlist` 页面收集用户,App 内也需要引导用户加入等待名单/申请内测。
|
||||
|
||||
**需考虑**:是否在 App 内嵌等待名单入口(如 Welcome 页或设置页)。
|
||||
|
||||
---
|
||||
|
||||
## 四、设计与交互差距
|
||||
|
||||
### 4.1 Tab 结构调整
|
||||
|
||||
**计划设计**:4 个 Tab — 学习 | 知识库 | AI助手 | 我的
|
||||
|
||||
**当前实现**:5 个 Tab — AI | 知识库 | 学习 | 分析 | 我的
|
||||
|
||||
**差异分析**:
|
||||
- 当前把"学习"和"分析"拆成了两个独立 Tab
|
||||
- 计划把"AI助手"独立为一个 Tab,当前 AI 已是独立 Tab
|
||||
- "分析"在计划中属于"学习"Tab 下的子页面,不需要顶层 Tab
|
||||
|
||||
**建议**(两种方案):
|
||||
- **方案 A**:完全对齐计划 → 合并学习和分析为一个 Tab,保持 4 Tab
|
||||
- **方案 B**:保留 5 Tab 结构 → 更新计划文档,论证"分析"独立为 Tab 的合理性(学习数据可视化、学习进度监控是独立价值)
|
||||
|
||||
### 4.2 登录流程简化
|
||||
|
||||
**计划要求**:仅 Sign in with Apple,不做手机号/邮箱/微信登录。
|
||||
|
||||
**当前 UI**:包含 4 种登录方式入口。
|
||||
|
||||
**建议**:第一版简化为仅 Apple 登录按钮 + 跳过选项,移除手机号/邮箱/微信登录 UI。
|
||||
|
||||
### 4.3 深色模式
|
||||
|
||||
**现状**:所有页面用 `.preferredColorScheme(.dark)` 强制深色,未验证浅色模式。
|
||||
|
||||
**建议**:确认是否需要支持浅色模式。如果只做深色,在 DesignTokens 中声明 `colorScheme: .dark`。
|
||||
|
||||
### 4.4 无障碍
|
||||
|
||||
**现状**:未考虑 VoiceOver、Dynamic Type、高对比度等无障碍需求。
|
||||
|
||||
**至少需做**:
|
||||
- 关键按钮添加 `.accessibilityLabel`
|
||||
- 确保 Dynamic Type 下布局不破碎
|
||||
- 重点页面 VoiceOver 测试
|
||||
|
||||
### 4.5 动效
|
||||
|
||||
**计划要求**(`官网与技术基础.md` 第 6.3 节):
|
||||
- P0:页面过渡、按钮反馈、加载状态、AI 分析中状态、学习完成反馈
|
||||
- P1:今日任务卡片动效、进度条更新、AI 结果分块出现
|
||||
|
||||
**当前**:仅有基础 SwiftUI 隐式动画(withAnimation),未实现任何计划中的动效。
|
||||
|
||||
---
|
||||
|
||||
## 五、数据层缺失
|
||||
|
||||
### 5.1 Model 定义
|
||||
|
||||
**现状**:所有数据通过 View 内局部变量或硬编码定义,无独立 Model 文件。
|
||||
|
||||
**计划中定义的核心实体**(`Demo与MVP.md`):
|
||||
|
||||
```
|
||||
User
|
||||
├── id, appleUserId, displayName, email
|
||||
├── preferredLanguage, createdAt, lastLoginAt, status
|
||||
|
||||
KnowledgeBase
|
||||
├── id, title, description, language, targetUser
|
||||
├── createdAt, updatedAt
|
||||
|
||||
LearningPath
|
||||
├── id, knowledgeBaseId, title, description
|
||||
├── estimatedDays, order
|
||||
|
||||
Lesson
|
||||
├── id, pathId, title, content, objectives
|
||||
├── keyPoints, recallQuestions, practicePrompt
|
||||
├── order, estimatedMinutes
|
||||
|
||||
LearningSession
|
||||
├── id, userId, lessonId
|
||||
├── startedAt, endedAt, userInput
|
||||
├── aiAnalysis, masteryScore, weakPoints
|
||||
├── nextSuggestion, reviewAt
|
||||
|
||||
AIAnalysis
|
||||
├── id, userId, sessionId
|
||||
├── inputText, outputJson, masteryScore
|
||||
├── weakPoints, suggestions
|
||||
├── modelName, createdAt, costEstimate
|
||||
|
||||
ReviewTask
|
||||
├── id, userId, lessonId, sourceSessionId
|
||||
├── reviewType, scheduledAt, completedAt, status
|
||||
|
||||
Feedback
|
||||
UserLearningProfile
|
||||
```
|
||||
|
||||
**需实现**:在 `Features/*/Models/` 下创建对应的 Swift struct(需 Codable、Identifiable)。
|
||||
|
||||
### 5.2 API Contract
|
||||
|
||||
**现状**:无 API 类型定义。
|
||||
|
||||
**建议**:参考计划中定义的 JSON 结构,先创建 Swift Model,再定义 API 请求/响应类型(Request/Response struct),实现前后端类型同构。
|
||||
|
||||
### 5.3 数据流规范
|
||||
|
||||
**现状**:View 直接持有 @State,无数据流管理。
|
||||
|
||||
**建议**:
|
||||
- ViewModel 持有 @Published 状态
|
||||
- ViewModel 通过 Service 获取数据
|
||||
- Service 通过 Repository 访问数据源
|
||||
- View 通过 @StateObject / @ObservedObject 绑定 ViewModel
|
||||
|
||||
---
|
||||
|
||||
## 六、工程化缺失
|
||||
|
||||
### 6.1 大文件拆分
|
||||
|
||||
**当前问题**:
|
||||
|
||||
| 文件 | 行数 | 包含内容 |
|
||||
|------|------|----------|
|
||||
| `AIStudyAppApp.swift` | ~187 | 5 个完整页面 + 多个子组件 |
|
||||
| `DailyThinkingPage.swift` | ~200+ | 5 个页面 + 共享组件 |
|
||||
| `LibrarySubpages.swift` | ~150+ | 6 个页面 + 组件 |
|
||||
|
||||
**建议**:每个页面一个文件,共享组件移到 `Shared/Components/`。
|
||||
|
||||
### 6.2 共享组件管理
|
||||
|
||||
**现状**:`ZXTabBar` 在 ContentView.swift,`ZXBackHeader` 在 DailyThinkingPage.swift,`ZXCardRow` 在 LibrarySubpages.swift,散落各处。
|
||||
|
||||
**建议**:集中到 `Shared/Components/`,建立组件目录如:
|
||||
```
|
||||
Shared/Components/
|
||||
├── ZXTabBar.swift
|
||||
├── ZXBackHeader.swift
|
||||
├── ZXAIInputBar.swift
|
||||
├── ZXScoreBox.swift
|
||||
├── ZXIconBtn.swift
|
||||
├── ZXCardRow.swift
|
||||
├── ZXChip.swift
|
||||
├── ZXQuickAction.swift
|
||||
└── ZXStatBadge.swift
|
||||
```
|
||||
|
||||
### 6.3 测试
|
||||
|
||||
**现状**:无任何测试代码。
|
||||
|
||||
**至少需要**:
|
||||
- ViewModel 单元测试(当 ViewModel 创建后)
|
||||
- Service 层单元测试(Mock Repository)
|
||||
- 关键 UI 流程的 Snapshot 测试
|
||||
|
||||
### 6.4 CI/CD
|
||||
|
||||
**现状**:无。
|
||||
|
||||
**建议**(后续):
|
||||
- GitHub Actions / Xcode Cloud 自动构建
|
||||
- TestFlight 自动分发
|
||||
|
||||
### 6.5 崩溃监控与埋点
|
||||
|
||||
**现状**:无。
|
||||
|
||||
**建议**:接入 Firebase Crashlytics 或类似服务,至少在 TestFlight 阶段要有崩溃收集能力。
|
||||
|
||||
---
|
||||
|
||||
## 七、优先级建议
|
||||
|
||||
### P0 — 必须在接后端前完成
|
||||
|
||||
| 优先级 | 项目 | 理由 |
|
||||
|--------|------|------|
|
||||
| P0 | 创建 Model 层(所有数据实体) | 是 Service/ViewModel/API 的基础 |
|
||||
| P0 | 创建 API Contract 类型定义 | 前后端对齐的前提 |
|
||||
| P0 | 搭建 APIClient + APIEndpoint | 所有后端交互的唯一通道 |
|
||||
| P0 | 实现 AuthService + Apple 登录 | 用户身份是学习记录的前提 |
|
||||
| P0 | 简化登录页为纯 Apple 登录 | 对齐计划,减少不必要 UI |
|
||||
| P0 | 实现复习计划独立页 | 计划标记 P0,当前缺失 |
|
||||
| P0 | 拆分大文件 | 降低后续修改的认知负担 |
|
||||
| P0 | 集中共享组件 | 避免组件散落导致重复开发 |
|
||||
| P0 | 添加加载/错误/空状态处理 | 真机使用的基本体验保障 |
|
||||
|
||||
### P1 — 与后端对接同步推进
|
||||
|
||||
| 优先级 | 项目 | 理由 |
|
||||
|--------|------|------|
|
||||
| P1 | 搭建 ViewModel 层(逐步迁移) | 架构分层,但不阻塞功能开发 |
|
||||
| P1 | 搭建 Service 层 | 随 API 对接自然建立 |
|
||||
| P1 | 实现本地化架构 | 越晚做返工越多 |
|
||||
| P1 | 实现反馈页 | TestFlight 内测必须 |
|
||||
| P1 | 实现 Keychain 存储 | Token 安全存储 |
|
||||
|
||||
### P2 — App Store 前完成
|
||||
|
||||
| 优先级 | 项目 | 理由 |
|
||||
|--------|------|------|
|
||||
| P2 | Repository 层 | 当需要本地缓存 + 网络切换时再做 |
|
||||
| P2 | 动效补充 | 体验优化,不阻塞功能 |
|
||||
| P2 | 无障碍适配 | App Store 审核加分项 |
|
||||
| P2 | 测试 | 用户量增长后需要 |
|
||||
| P2 | Tab 结构调整决策 | 需要更多用户反馈来决策 |
|
||||
|
||||
---
|
||||
|
||||
## 八、总结
|
||||
|
||||
当前 iOS 项目完成了 UI 层的全量搭建(21 页),但缺少"能让产品真正运转"的架构底座和数据能力。核心矛盾是:
|
||||
|
||||
> UI 超前,架构滞后。页面能点,但无数据、无认证、无 AI、无服务。
|
||||
|
||||
接下来最合理的推进顺序:
|
||||
|
||||
```
|
||||
1. 建 Model 层(夯实数据基础)
|
||||
↓
|
||||
2. 搭网络层 + Apple 登录(接通身份和通信)
|
||||
↓
|
||||
3. 后端 API 逐个对接(AI 分析和学习记录最先)
|
||||
↓
|
||||
4. 重构 ViewModel 层(顺带解决架构问题)
|
||||
↓
|
||||
5. 补充缺失页面(复习计划、反馈)
|
||||
↓
|
||||
6. 本地化 + 动效 + 测试(打磨)
|
||||
```
|
||||
|
||||
一句话:**先把骨架搭对,再长肉。**
|
||||
|
||||
对,**登录第一版只保留苹果登录**,这是最正确的决策。
|
||||
|
||||
你整理的文档里也已经明确写了:当前 `LoginPage` 虽然有手机号、邮箱、微信、Apple 入口,但第一版计划要求只做 Sign in with Apple,并且需要实现 Apple 授权、后端验证、Keychain 存 token 和登录状态管理。
|
||||
文档后面也建议把登录页简化为 **仅 Apple 登录按钮 + 可选跳过入口**,移除手机号、邮箱、微信登录 UI。
|
||||
|
||||
---
|
||||
|
||||
# 登录页第一版最终方案
|
||||
|
||||
## 正式入口只保留
|
||||
|
||||
```text
|
||||
Sign in with Apple
|
||||
```
|
||||
|
||||
## 删除这些入口
|
||||
|
||||
```text
|
||||
手机号登录
|
||||
邮箱登录
|
||||
微信登录
|
||||
验证码登录
|
||||
第三方微信登录
|
||||
```
|
||||
|
||||
## “跳过”要不要保留?
|
||||
|
||||
我建议:
|
||||
|
||||
```text
|
||||
开发环境可以保留
|
||||
正式环境不要明显展示
|
||||
```
|
||||
|
||||
也就是说:
|
||||
|
||||
```swift
|
||||
#if DEBUG
|
||||
Button("跳过,进入演示模式") { ... }
|
||||
#endif
|
||||
```
|
||||
|
||||
不要把“跳过”作为正式登录入口,不然后面学习记录、知识库、AI 分析都会涉及匿名用户迁移,很麻烦。
|
||||
|
||||
---
|
||||
|
||||
# 登录流程应该这样设计
|
||||
|
||||
```text
|
||||
打开 App
|
||||
↓
|
||||
AppSession 检查 Keychain 里有没有 refreshToken
|
||||
↓
|
||||
如果有 token:调用 /auth/refresh 或 /users/me
|
||||
↓
|
||||
成功:进入主界面
|
||||
↓
|
||||
失败:进入登录页
|
||||
↓
|
||||
用户点击 Sign in with Apple
|
||||
↓
|
||||
iOS 获取 identityToken / authorizationCode / userIdentifier
|
||||
↓
|
||||
POST /api/auth/apple
|
||||
↓
|
||||
后端返回 accessToken / refreshToken / user
|
||||
↓
|
||||
iOS 把 token 存到 Keychain
|
||||
↓
|
||||
AppSession 更新 currentUser
|
||||
↓
|
||||
判断 onboardingCompleted
|
||||
↓
|
||||
未完成:进入首次引导 / 学习目标设置
|
||||
已完成:进入主界面
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# iOS 需要实现的文件
|
||||
|
||||
登录相关最少这些:
|
||||
|
||||
```text
|
||||
Features/Auth/Views/LoginView.swift
|
||||
Features/Auth/ViewModels/LoginViewModel.swift
|
||||
|
||||
Core/Services/AuthService.swift
|
||||
Core/Services/AuthServiceProtocol.swift
|
||||
|
||||
Core/Storage/KeychainStore.swift
|
||||
Core/Storage/TokenStore.swift
|
||||
|
||||
App/AppSession.swift
|
||||
|
||||
Core/Models/AuthModels.swift
|
||||
Core/Models/User.swift
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 接口请求结构
|
||||
|
||||
iOS 登录成功后给后端:
|
||||
|
||||
```swift
|
||||
struct AppleLoginRequest: Encodable {
|
||||
let identityToken: String
|
||||
let authorizationCode: String?
|
||||
let userIdentifier: String
|
||||
let fullName: AppleFullName?
|
||||
let email: String?
|
||||
}
|
||||
|
||||
struct AppleFullName: Encodable {
|
||||
let givenName: String?
|
||||
let familyName: String?
|
||||
}
|
||||
```
|
||||
|
||||
后端返回:
|
||||
|
||||
```swift
|
||||
struct AuthResponse: Decodable {
|
||||
let accessToken: String
|
||||
let refreshToken: String
|
||||
let expiresIn: Int
|
||||
let user: User
|
||||
}
|
||||
```
|
||||
|
||||
Token 存储:
|
||||
|
||||
```text
|
||||
accessToken → Keychain
|
||||
refreshToken → Keychain
|
||||
不要存 UserDefaults
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 给 Trae 的修改指令
|
||||
|
||||
你可以直接发这段:
|
||||
|
||||
```text
|
||||
现在调整知习 iOS App 的登录方案。
|
||||
|
||||
第一版登录方式只保留 Sign in with Apple。
|
||||
|
||||
请删除登录页中的:
|
||||
- 手机号登录
|
||||
- 邮箱登录
|
||||
- 微信登录
|
||||
- 其他第三方登录入口
|
||||
|
||||
正式 UI 只保留:
|
||||
- Sign in with Apple 按钮
|
||||
- 简短产品说明
|
||||
- 隐私政策 / 用户协议入口
|
||||
|
||||
开发环境可以保留一个 DEBUG-only 的“跳过,进入演示模式”按钮,但不能出现在 Release 版本。
|
||||
|
||||
请实现以下架构:
|
||||
|
||||
1. LoginView
|
||||
- 只展示 Apple 登录按钮
|
||||
- 点击后调用 LoginViewModel.loginWithApple()
|
||||
- 支持 loading / error 状态
|
||||
- 登录失败时展示错误提示
|
||||
|
||||
2. LoginViewModel
|
||||
- @MainActor
|
||||
- ObservableObject
|
||||
- @Published isLoading
|
||||
- @Published errorMessage
|
||||
- 调用 AuthService 处理 Apple 登录
|
||||
|
||||
3. AuthService
|
||||
- 集成 ASAuthorizationController
|
||||
- 获取 identityToken
|
||||
- 获取 authorizationCode
|
||||
- 获取 userIdentifier
|
||||
- 获取 email / fullName,如果 Apple 返回
|
||||
- 调用后端 POST /api/auth/apple
|
||||
- 接收 accessToken / refreshToken / user
|
||||
|
||||
4. TokenStore / KeychainStore
|
||||
- accessToken 存 Keychain
|
||||
- refreshToken 存 Keychain
|
||||
- 支持 save / load / clear
|
||||
|
||||
5. AppSession
|
||||
- 管理全局登录状态
|
||||
- currentUser
|
||||
- isAuthenticated
|
||||
- bootstrap()
|
||||
- loginWithApple()
|
||||
- logout()
|
||||
- refreshSession()
|
||||
|
||||
6. App 启动逻辑
|
||||
- 启动时先检查 Keychain 中是否存在 refreshToken
|
||||
- 如果存在,调用后端 refresh 或 /users/me
|
||||
- 成功后进入主界面
|
||||
- 失败则清空 token 并进入登录页
|
||||
|
||||
7. 登录成功后的跳转
|
||||
- 如果 user.onboardingCompleted == false,进入首次使用引导 / 学习目标设置
|
||||
- 如果 user.onboardingCompleted == true,进入 MainTabView
|
||||
|
||||
8. 注意
|
||||
- 不要再使用 @AppStorage("hasCompletedOnboarding") 单独决定是否进入主界面
|
||||
- 登录状态必须由 AppSession + Keychain token 决定
|
||||
- 不要把 token 存到 UserDefaults
|
||||
- 不要在 View 里直接写网络请求
|
||||
- 不要在 View 里直接处理 Apple 登录细节
|
||||
- 不要改变其他主页面 UI
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 登录页内容建议
|
||||
|
||||
页面可以非常简单:
|
||||
|
||||
```text
|
||||
知习
|
||||
|
||||
更懂你,更会学。
|
||||
|
||||
用 AI 把知识库、主动回忆和间隔复习连接起来,
|
||||
从“看过”走向“真正学会”。
|
||||
|
||||
[ Sign in with Apple ]
|
||||
|
||||
登录即代表你同意《用户服务协议》和《隐私政策》
|
||||
```
|
||||
|
||||
就够了。
|
||||
第一版登录越简单越好,别再做多登录方式。
|
||||
@ -1,139 +0,0 @@
|
||||
# 知习 ZhiXi — 项目架构
|
||||
|
||||
> 更新时间:2026-05-10
|
||||
|
||||
## 一、项目结构
|
||||
|
||||
```
|
||||
AIStudyApp/
|
||||
├── AIStudyAppApp.swift # 应用入口 + 引导流程路由
|
||||
│ ├── OnboardingFlowView # Splash → Welcome → Login → Onboarding → GoalSetup
|
||||
│ ├── SplashPage # 启动页
|
||||
│ ├── WelcomePage # 欢迎页
|
||||
│ ├── LoginPage # 登录页
|
||||
│ ├── OnboardingPage # 功能引导
|
||||
│ └── GoalSetupPage # 学习目标设置
|
||||
│
|
||||
├── ContentView.swift # 5-Tab 主界面
|
||||
│ ├── ZXTabBar # 自定义底部 Tab 栏
|
||||
│ ├── ZXAIInputBar # AI 输入栏
|
||||
│ ├── ZXScoreBox # 评分组件
|
||||
│ └── ZXIconBtn # 图标按钮
|
||||
│
|
||||
├── Core/
|
||||
│ └── DesignSystem/
|
||||
│ └── DesignTokens.swift # 颜色/渐变/圆角/间距/字号/排版
|
||||
│
|
||||
├── Features/
|
||||
│ ├── AI/
|
||||
│ │ ├── AIHomeView.swift # AI 首页(Tab 1)
|
||||
│ │ └── DailyThinkingPage.swift # 今日思考 + AIChat + RecallTest + WeakPoints + AIFeedback
|
||||
│ │
|
||||
│ ├── Library/
|
||||
│ │ ├── LibraryHomeView.swift # 知识库首页(Tab 2)
|
||||
│ │ └── LibrarySubpages.swift # Create/Detail/Add/Import/KnowledgeDetail/Edit
|
||||
│ │
|
||||
│ ├── Study/
|
||||
│ │ └── StudyHomeView.swift # 学习工作台(Tab 3)
|
||||
│ │
|
||||
│ ├── Analysis/
|
||||
│ │ └── AnalysisHomeView.swift # 学习分析(Tab 4)
|
||||
│ │
|
||||
│ └── Profile/
|
||||
│ └── ProfileView.swift # 我的(Tab 5)
|
||||
│
|
||||
└── Assets.xcassets/ # 资源文件
|
||||
```
|
||||
|
||||
## 二、导航架构
|
||||
|
||||
```
|
||||
@main AIStudyAppApp
|
||||
├── hasCompletedOnboarding == false
|
||||
│ └── OnboardingFlowView
|
||||
│ ├── step 0: SplashPage ──(2s)──→ step 1
|
||||
│ ├── step 1: WelcomePage ──"开始使用"──→ step 2
|
||||
│ │ ──"已有账号"──→ hasCompletedOnboarding = true
|
||||
│ ├── step 2: LoginPage ──"登录"──→ step 3
|
||||
│ │ ──"跳过"──→ hasCompletedOnboarding = true
|
||||
│ ├── step 3: OnboardingPage ──"下一步"──→ step 4
|
||||
│ └── step 4: GoalSetupPage ──"开始学习"──→ hasCompletedOnboarding = true
|
||||
│
|
||||
└── hasCompletedOnboarding == true
|
||||
└── ContentView (5-Tab)
|
||||
├── Tab "AI" → NavigationStack { AIHomeView }
|
||||
│ ├── → DailyThinkingPage → AIFeedbackPageView
|
||||
│ ├── → RecallTestPage
|
||||
│ ├── → WeakPointsPage
|
||||
│ └── → AIChatPage
|
||||
│
|
||||
├── Tab "知识库" → NavigationStack { LibraryHomeView }
|
||||
│ ├── → LibraryDetailPage → KnowledgeDetailPage
|
||||
│ ├── → CreateLibraryPage
|
||||
│ ├── → AddKnowledgePage
|
||||
│ ├── → ImportPage
|
||||
│ └── → EditKnowledgePage
|
||||
│
|
||||
├── Tab "学习" → NavigationStack { StudyHomeView }
|
||||
├── Tab "分析" → NavigationStack { AnalysisHomeView }
|
||||
└── Tab "我的" → NavigationStack { ProfileView }
|
||||
```
|
||||
|
||||
## 三、数据流(当前均为静态 Mock)
|
||||
|
||||
所有页面目前使用 `@State` 管理的本地假数据,尚未接入真实后端:
|
||||
|
||||
| 数据 | 当前状态 |
|
||||
|------|----------|
|
||||
| 用户信息 | ProfileView 中硬编码 |
|
||||
| 知识库列表 | LibraryHomeView 中硬编码 4 个 |
|
||||
| 学习任务 | StudyHomeView 中硬编码 5 个 |
|
||||
| AI 分析结果 | 各 AI 页面静态文本 |
|
||||
| 学习统计 | AnalysisHomeView 中硬编码 |
|
||||
| 登录状态 | @AppStorage 布尔值控制 |
|
||||
|
||||
## 四、技术栈
|
||||
|
||||
| 层 | 技术 | 备注 |
|
||||
|----|------|------|
|
||||
| 语言 | Swift | — |
|
||||
| UI 框架 | SwiftUI | iOS 17+ |
|
||||
| 架构模式 | 当前未分层(View 内聚) | 计划 MVVM + Service + Repository |
|
||||
| 设计系统 | 自定义 DesignTokens | 从 React 原型 1:1 提取 |
|
||||
| 构建工具 | Xcode | — |
|
||||
| 目标平台 | iPhone (iOS 17+) | 未做 iPad/Mac 适配 |
|
||||
|
||||
## 五、与计划架构的差异
|
||||
|
||||
计划文档(`官网与技术基础.md`)中定义的 iOS 目录结构:
|
||||
|
||||
```
|
||||
计划架构 当前实现
|
||||
───────────────────────────────── ─────────────────
|
||||
App/AIStudyApp.swift AIStudyAppApp.swift ✅
|
||||
App/AppConfig.swift 未实现 ❌
|
||||
App/AppRouter.swift 未实现 ❌
|
||||
Core/Network/ 未实现 ❌
|
||||
Core/Auth/ 未实现 ❌
|
||||
Core/Storage/ 未实现 ❌
|
||||
Core/Localization/ 未实现 ❌
|
||||
Core/DesignSystem/ DesignTokens.swift ✅ (部分)
|
||||
Features/*/Views/ Features/*/ ✅
|
||||
Features/*/ViewModels/ 未实现 ❌ (View 内聚状态)
|
||||
Features/*/Models/ 未实现 ❌ (无独立 Model)
|
||||
Shared/Components/ 分散在各 View 文件中 ⚠️
|
||||
Shared/Extensions/ 仅 Color hex 扩展 ✅
|
||||
Shared/Utils/ 未实现 ❌
|
||||
Shared/Constants/ 未实现 ❌
|
||||
Resources/Localizable.xcstrings 未实现 ❌
|
||||
Resources/PreviewData/ 未实现 ❌
|
||||
```
|
||||
|
||||
## 六、待重构项
|
||||
|
||||
1. **View 文件过大**:`AIStudyAppApp.swift` 包含 5 个独立页面,应拆分到各自文件
|
||||
2. **无 ViewModel 层**:所有状态和数据逻辑写在 View 中,需要抽离
|
||||
3. **无 Model 层**:数据结构(如学习任务、知识库卡片)分散在 View 中用局部变量定义
|
||||
4. **共享组件未集中**:`ZXTabBar`、`ZXBackHeader` 等组件散落在不同文件中
|
||||
5. **无网络层**:无 API Client、无 Auth Service、无 Storage 层
|
||||
6. **无本地化**:所有文案硬编码,未使用 `LocalizedStringKey`
|
||||
@ -1,157 +0,0 @@
|
||||
# AIStudyApp 现状与缺口分析 - 第一篇:现有资源盘点
|
||||
|
||||
> 生成日期:2026-05-11
|
||||
> 后端地址:http://81.70.187.179:3001
|
||||
|
||||
---
|
||||
|
||||
## 一、项目文件结构
|
||||
|
||||
```
|
||||
AIStudyApp/
|
||||
├── AIStudyAppApp.swift # 应用入口,含 5 步 Onboarding 流程
|
||||
├── ContentView.swift # 主 Tab 框架(5 个 Tab + 自定义底部栏)
|
||||
│
|
||||
├── Core/
|
||||
│ ├── DesignSystem/DesignTokens.swift # 颜色/渐变/间距/字体全局设计令牌
|
||||
│ ├── Models/APIModels.swift # 20+ DTO 数据模型
|
||||
│ ├── Network/
|
||||
│ │ ├── APIClient.swift # 通用 HTTP 客户端(actor, async/await)
|
||||
│ │ ├── APIConfig.swift # baseURL 配置
|
||||
│ │ └── APIError.swift # 错误枚举(网络/服务端/解码/认证)
|
||||
│ └── Services/APIService.swift # 8 个服务类,15 个公开方法
|
||||
│
|
||||
├── Features/
|
||||
│ ├── AI/
|
||||
│ │ ├── AIHomeView.swift # AI 首页 + ZXQuickAction + ZXAIInteractionRow 组件
|
||||
│ │ └── DailyThinkingPage.swift # 每日思考题 + RecallTestPage / WeakPointsPage /
|
||||
│ │ # AIFeedbackPageView / AIChatPage 子页面
|
||||
│ ├── Analysis/
|
||||
│ │ └── AnalysisHomeView.swift # 学习分析页 + ZXChartView 折线图 + ZXWeakRow 薄弱点
|
||||
│ ├── Library/
|
||||
│ │ ├── LibraryHomeView.swift # 知识库列表首页
|
||||
│ │ └── LibrarySubpages.swift # CreateLibraryPage / LibraryDetailPage /
|
||||
│ │ # AddKnowledgePage / KnowledgeDetailPage /
|
||||
│ │ # ImportPage / EditKnowledgePage
|
||||
│ ├── Profile/
|
||||
│ │ └── ProfileView.swift # 个人中心页
|
||||
│ └── Study/
|
||||
│ └── StudyHomeView.swift # 学习工作台 + 今日任务 + 周活跃柱状图
|
||||
│
|
||||
└── Info.plist # 手动管理(ATS例外 / Bundle元数据等)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 二、5 个 Tab 页面清单
|
||||
|
||||
| Tab | 标签 | SF Symbol | View |
|
||||
|-----|------|-----------|------|
|
||||
| 1 | AI | `brain.head.profile` | AIHomeView |
|
||||
| 2 | 知识库 | `books.vertical.fill` | LibraryHomeView |
|
||||
| 3 | 学习 | `bolt.fill` | StudyHomeView |
|
||||
| 4 | 分析 | `chart.bar.fill` | AnalysisHomeView |
|
||||
| 5 | 我的 | `person.fill` | ProfileView |
|
||||
|
||||
---
|
||||
|
||||
## 三、所有页面/子页面总览(共 21 个)
|
||||
|
||||
### AI 模块(1 主 + 4 子)
|
||||
|
||||
| 页面 | 数据来源 | 核心功能 |
|
||||
|------|---------|---------|
|
||||
| AIHomeView | 🔴硬编码 | API 状态检测、思考题卡片、快捷操作、互动记录、提问输入栏 |
|
||||
| DailyThinkingPage | 🔴硬编码 | AI 思考题展示 + 回答提交 |
|
||||
| RecallTestPage | 🔴硬编码 | 回忆测试输入 |
|
||||
| WeakPointsPage | 🔴硬编码 | 薄弱知识点静态列表 |
|
||||
| AIFeedbackPageView | 🔴硬编码 | AI 反馈评分 + 操作入口 |
|
||||
| AIChatPage | 🔴硬编码 | AI 对话气泡界面 |
|
||||
|
||||
### 知识库模块(1 主 + 6 子)
|
||||
|
||||
| 页面 | 数据来源 | 核心功能 |
|
||||
|------|---------|---------|
|
||||
| LibraryHomeView | 🔴硬编码 | 知识库列表 + 搜索框 + 创建入口 |
|
||||
| CreateLibraryPage | 🔴静态 | 创建表单(名称+描述) |
|
||||
| LibraryDetailPage | 🔴硬编码 | 知识点静态列表 |
|
||||
| AddKnowledgePage | 🔴静态 | 添加知识点表单 |
|
||||
| KnowledgeDetailPage | 🔴硬编码 | 知识点详情+标签+复习/费曼入口 |
|
||||
| ImportPage | 🔴静态 | 导入方式选择(拍照/文件/链接/相册) |
|
||||
| EditKnowledgePage | 🔴静态 | 编辑知识点表单 |
|
||||
|
||||
### 学习模块(1 主)
|
||||
|
||||
| 页面 | 数据来源 | 核心功能 |
|
||||
|------|---------|---------|
|
||||
| StudyHomeView | 🔴硬编码 | 今日进度环、任务列表(5个任务)、本周活跃柱状图 |
|
||||
|
||||
### 分析模块(1 主)
|
||||
|
||||
| 页面 | 数据来源 | 核心功能 |
|
||||
|------|---------|---------|
|
||||
| AnalysisHomeView | 🔴硬编码 | 4项统计徽章、掌握度7日折线图、薄弱知识点列表 |
|
||||
|
||||
### 个人中心(1 主)
|
||||
|
||||
| 页面 | 数据来源 | 核心功能 |
|
||||
|------|---------|---------|
|
||||
| ProfileView | 🔴硬编码 | 个人卡片、菜单列表、成就徽章 |
|
||||
|
||||
### 启动流程(5 步 Onboarding)
|
||||
|
||||
| 步骤 | 页面 | 功能 |
|
||||
|------|------|------|
|
||||
| Step 0 | SplashPage | 品牌开屏,2 秒自动跳转 |
|
||||
| Step 1 | WelcomePage | 3 大功能介绍 |
|
||||
| Step 2 | LoginPage | 手机号/邮箱 + 密码表单 + 微信/Apple 登录入口 |
|
||||
| Step 3 | OnboardingPage | 4 步功能轮播 |
|
||||
| Step 4 | GoalSetupPage | 学习目标/方法/每日时长选择 |
|
||||
|
||||
---
|
||||
|
||||
## 四、APIService 已封装方法(15 个)
|
||||
|
||||
| 服务类 | 方法 | 接口 |
|
||||
|--------|------|------|
|
||||
| WaitlistService | `join(...)` | POST /waitlist |
|
||||
| | `stats()` | GET /waitlist/stats |
|
||||
| AuthService | `appleLogin(...)` | POST /auth/apple |
|
||||
| | `logout()` | POST /auth/logout |
|
||||
| UserService | `myProfile()` | GET /users/me |
|
||||
| | `updateProfile(...)` | PATCH /users/me |
|
||||
| KnowledgeBaseService | `list()` | GET /knowledge-bases |
|
||||
| | `create(...)` | POST /knowledge-bases |
|
||||
| | `detail(id:)` | GET /knowledge-bases/:id |
|
||||
| KnowledgeItemService | `list(baseId:)` | GET /knowledge-items |
|
||||
| | `detail(id:)` | GET /knowledge-items/:id |
|
||||
| | `create(...)` | POST /knowledge-items |
|
||||
| AIAnalysisService | `analyze(...)` | POST /ai-analysis |
|
||||
| ActivityService | `summary()` | GET /activity/summary |
|
||||
| ReviewService | `due()` | GET /reviews/due |
|
||||
| FocusItemService | `list()` | GET /focus-items |
|
||||
| FeedbackService | `submit(...)` | POST /feedback |
|
||||
|
||||
---
|
||||
|
||||
## 五、后端接口 vs App 覆盖对照表
|
||||
|
||||
| 后端模块 | 接口数 | App 覆盖 | 状态 |
|
||||
|----------|--------|---------|------|
|
||||
| System | 3 | 0 | ❌ 无 |
|
||||
| Auth | 3 | 2(Service 有,View 未接) | 🔶 |
|
||||
| Users | 3 | 2(Service 有,View 未接) | 🔶 |
|
||||
| KnowledgeBase | 5 | 3(Service 有,View 未接) | 🔶 |
|
||||
| KnowledgeItems | 4 | 3(Service 有,View 未接) | 🔶 |
|
||||
| DocumentImport | 2 | 0 | ❌ 无 |
|
||||
| LearningSession | 3 | 0 | ❌ 无 |
|
||||
| ActiveRecall | 2 | 0 | ❌ 无 |
|
||||
| AIAnalysis | 3 | 1(Service 有,View 未接) | 🔶 |
|
||||
| FocusItems | 4 | 1(Service 有,View 未接) | 🔶 |
|
||||
| Review | 2 | 1(Service 有,View 未接) | 🔶 |
|
||||
| LearningActivity | 2 | 1(Service 有,View 未接) | 🔶 |
|
||||
| Notifications | 2 | 0 | ❌ 无 |
|
||||
| Feedback | 4 | 1(Service 有,View 未接) | 🔶 |
|
||||
| Waitlist | 3 | 2(Service 有,View 未接) | 🔶 |
|
||||
|
||||
> 覆盖率:Service 层 15/48 = 31%,View 层实际接入 0/48 = 0%
|
||||
@ -1,267 +0,0 @@
|
||||
# AIStudyApp 现状与缺口分析 - 第二篇:缺失功能与实施路线
|
||||
|
||||
> 接第一篇《现有资源盘点》
|
||||
> 生成日期:2026-05-11
|
||||
|
||||
---
|
||||
|
||||
## 一、优先级总览
|
||||
|
||||
```
|
||||
P0(核心闭环,本周必须) 4 项
|
||||
P1(数据接入,下周) 5 项
|
||||
P2(新页面/功能,后续) 5 项
|
||||
P3(体验增强,优化期) 5 项
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 二、P0 —— 核心学习闭环(4 项)
|
||||
|
||||
### P0-1:真实 Apple 登录流程
|
||||
|
||||
**现状:** LoginPage 是静态表单,没有调 API,Token 没有持久化。
|
||||
|
||||
**需要做:**
|
||||
|
||||
| 子任务 | 涉及文件 |
|
||||
|--------|---------|
|
||||
| 集成 `AuthenticationServices`,添加 `ASAuthorizationAppleIDButton` | LoginPage(内嵌在 AIStudyAppApp.swift) |
|
||||
| 拿到 `identityToken` 后调用 `AuthService.appleLogin(...)` | LoginPage |
|
||||
| 登录成功后用 `@AppStorage` 或 Keychain 存储 Token | APIClient |
|
||||
| `@main` 启动时检查已有 Token,跳过 Onboarding | AIStudyAppApp.swift |
|
||||
| 处理登录失败/网络错误的 UI 提示 | LoginPage |
|
||||
| 接入 `POST /auth/refresh` Token 自动刷新 | APIClient |
|
||||
|
||||
涉及接口:`POST /auth/apple`、`POST /auth/refresh`、`POST /auth/logout`
|
||||
|
||||
---
|
||||
|
||||
### P0-2:知识库 + 知识点接入真实 API
|
||||
|
||||
**现状:** LibraryHomeView 硬编码 4 个知识库,子页面表单没有提交。
|
||||
|
||||
**需要做:**
|
||||
|
||||
| 子任务 | 涉及文件 |
|
||||
|--------|---------|
|
||||
| `LibraryHomeView` 的 `.task {}` 中调 `KnowledgeBaseService.list()` | LibraryHomeView.swift |
|
||||
| 替换硬编码卡片为 `ForEach(bases)` 真实数据 | LibraryHomeView.swift |
|
||||
| `CreateLibraryPage` 表单提交调 `KnowledgeBaseService.create(...)` | LibrarySubpages.swift |
|
||||
| `LibraryDetailPage` 加载真实知识点列表 `KnowledgeItemService.list(baseId:)` | LibrarySubpages.swift |
|
||||
| `AddKnowledgePage` 表单提交调 `KnowledgeItemService.create(...)` | LibrarySubpages.swift |
|
||||
| `EditKnowledgePage` 提交调 `PATCH /knowledge-items/:id`(APIService 需新增 update 方法) | LibrarySubpages.swift + APIService.swift |
|
||||
| 增加 loading / empty / error 三种状态处理 | 各 Library 页面 |
|
||||
|
||||
涉及接口:`GET/POST /knowledge-bases`、`GET/POST/PATCH /knowledge-items`
|
||||
|
||||
---
|
||||
|
||||
### P0-3:学习会话追踪
|
||||
|
||||
**现状:** StudyHomeView 的"今日任务"是静态列表,没有学习计时,没有调任何接口。
|
||||
|
||||
**需要做:**
|
||||
|
||||
| 子任务 | 涉及文件 / 新建文件 |
|
||||
|--------|-------------------|
|
||||
| 新建 `LearningSessionView.swift`:含计时器(`Timer.publish`)+ 暂停/结束按钮 | **新文件** Features/Study/LearningSessionView.swift |
|
||||
| 点击 StudyHomeView 任务 → push 到 LearningSessionView | StudyHomeView.swift |
|
||||
| 入场调 `POST /learning-sessions`(传入 knowledgeBaseId) | LearningSessionView.swift |
|
||||
| 结束/暂停时调 `POST /learning-sessions/:id/end` | LearningSessionView.swift |
|
||||
| APIService 新增 `LearningSessionService` | APIService.swift |
|
||||
| APIModels 新增 `LearningSessionCreateRequest` / `LearningSessionResponse` | APIModels.swift |
|
||||
|
||||
涉及接口:`POST /learning-sessions`、`POST /learning-sessions/:id/end`、`GET /learning-sessions`
|
||||
|
||||
---
|
||||
|
||||
### P0-4:间隔复习卡片
|
||||
|
||||
**现状:** 没有复习页面。后端 `GET /reviews/due` + `POST /reviews/:id/submit` 已就绪。
|
||||
|
||||
**需要做:**
|
||||
|
||||
| 子任务 | 新建文件 |
|
||||
|--------|---------|
|
||||
| 新建 `ReviewCardView.swift`:正面问题 → 点击翻转 → 显示答案 → 评分按钮 | **新文件** Features/Study/ReviewCardView.swift |
|
||||
| 评分按钮:Again(1) / Hard(2) / Good(3) / Easy(4),调 `POST /reviews/:id/submit` | ReviewCardView.swift |
|
||||
| 复习入口放在 StudyHomeView "今日任务"区域顶部 | StudyHomeView.swift |
|
||||
| 复习入口放在 AIHomeView 快捷操作中 | AIHomeView.swift |
|
||||
| 到期卡片数为 0 时显示空状态"🎉 都复习完啦" | ReviewCardView.swift |
|
||||
|
||||
涉及接口:`GET /reviews/due`、`POST /reviews/:id/submit`
|
||||
|
||||
---
|
||||
|
||||
## 三、P1 —— 数据接入(5 项)
|
||||
|
||||
### P1-1:薄弱点 / AI 分析接真实数据
|
||||
|
||||
**现状:** AnalysisHomeView / WeakPointsPage 硬编码 3 条数据。
|
||||
|
||||
**需要做:**
|
||||
|
||||
| 子任务 | 涉及文件 |
|
||||
|--------|---------|
|
||||
| AnalysisHomeView `.task {}` 中调 `FocusItemService.list()` | AnalysisHomeView.swift |
|
||||
| 替换硬编码 ZXWeakRow 为 `ForEach(focusItems)` | AnalysisHomeView.swift |
|
||||
| RecallTestPage 提交回答时调 `AIAnalysisService.analyze(...)` | DailyThinkingPage.swift |
|
||||
| AIFeedbackPageView 展示真实分析结果 | DailyThinkingPage.swift |
|
||||
| APIModels 增补 FocusItem 字段对齐后端 | APIModels.swift |
|
||||
|
||||
涉及接口:`GET /focus-items`、`POST /ai-analysis`、`GET /ai-analysis/:id`
|
||||
|
||||
---
|
||||
|
||||
### P1-2:StudyHomeView 数据真实化
|
||||
|
||||
**现状:** 进度环、任务列表、周活跃柱状图全是硬编码。
|
||||
|
||||
**需要做:**
|
||||
|
||||
| 子任务 | 涉及文件 |
|
||||
|--------|---------|
|
||||
| 调 `ActivityService.summary()` 获取真实统计数据 | StudyHomeView.swift |
|
||||
| 进度环用真实 `totalMinutes` / `streakDays` | StudyHomeView.swift |
|
||||
| 周活跃图调 `GET /activity/heatmap`(APIService 需新增 heatmap 方法) | StudyHomeView.swift + APIService.swift |
|
||||
| 今日任务从 `GET /reviews/due` + `GET /focus-items` 拼接 | StudyHomeView.swift |
|
||||
|
||||
涉及接口:`GET /activity/summary`、`GET /activity/heatmap`
|
||||
|
||||
---
|
||||
|
||||
### P1-3:ProfileView 接入用户资料
|
||||
|
||||
**现状:** ProfileView 全部静态假数据(昵称"学习者"、假统计)。
|
||||
|
||||
**需要做:**
|
||||
|
||||
| 子任务 | 涉及文件 |
|
||||
|--------|---------|
|
||||
| `.task {}` 调 `UserService.myProfile()` | ProfileView.swift |
|
||||
| 替换头像(emoji → 真实 avatar URL / 默认头像) | ProfileView.swift |
|
||||
| 替换昵称、邮箱、统计数字 | ProfileView.swift |
|
||||
| 菜单项"学习目标设置"跳设置表单页 → `PATCH /users/me/preferences` | ProfileView.swift + 新 SettingsView |
|
||||
|
||||
涉及接口:`GET /users/me`、`PATCH /users/me`、`PATCH /users/me/preferences`
|
||||
|
||||
---
|
||||
|
||||
### P1-4:通知中心页面
|
||||
|
||||
**现状:** 完全没有通知页面。
|
||||
|
||||
**需要做:**
|
||||
|
||||
| 子任务 | 新建/涉及文件 |
|
||||
|--------|-------------|
|
||||
| 新建 `NotificationListView.swift` | **新文件** Features/Profile/NotificationListView.swift |
|
||||
| `.task {}` 调 `GET /notifications` | NotificationListView.swift |
|
||||
| 列表项点击标记已读 `POST /notifications/:id/read` | NotificationListView.swift |
|
||||
| ProfileView 右上角铃铛 badge 显示未读数 | ProfileView.swift |
|
||||
| APIService 新增 `NotificationService` | APIService.swift |
|
||||
|
||||
涉及接口:`GET /notifications`、`POST /notifications/:id/read`
|
||||
|
||||
---
|
||||
|
||||
### P1-5:反馈提交
|
||||
|
||||
**现状:** 没有反馈提交入口。
|
||||
|
||||
**需要做:**
|
||||
|
||||
| 子任务 | 涉及文件 |
|
||||
|--------|---------|
|
||||
| ProfileView 菜单加"帮助与反馈" → 跳反馈表单 | ProfileView.swift + 新 FeedbackView |
|
||||
| 调 `FeedbackService.submit(...)` | 新 FeedbackView |
|
||||
| 提交后显示"感谢反馈"提示 | 新 FeedbackView |
|
||||
|
||||
涉及接口:`POST /feedback`
|
||||
|
||||
---
|
||||
|
||||
## 四、P2 —— 新页面/功能(5 项)
|
||||
|
||||
### P2-1:文件导入真实接入
|
||||
|
||||
**现状:** ImportPage 只有 4 个静态按钮。
|
||||
|
||||
**需要做:** 接入 `PHPickerViewController`(相册选图)、`UIDocumentPickerViewController`(文件选择)、AVCaptureSession(拍照),上传后调 `POST /imports`,轮询 `GET /imports/:id/status`。APIService 新增 `DocumentImportService`。
|
||||
|
||||
---
|
||||
|
||||
### P2-2:全局搜索
|
||||
|
||||
**现状:** LibraryHomeView 有搜索框但无效。
|
||||
|
||||
**需要做:** 新建 `SearchView.swift`,调 `GET /knowledge-items?keyword=xxx`,支持搜索知识点/知识库/标签,展示搜索结果列表。
|
||||
|
||||
---
|
||||
|
||||
### P2-3:设置页面完善
|
||||
|
||||
**现状:** ProfileView 5 个菜单项全是假的。
|
||||
|
||||
**需要做:** 每个菜单项对应一个设置表单页:学习目标、复习提醒时间、学习报告邮件、学习方法偏好(费曼/回忆/间隔/综合)、数据同步状态。
|
||||
|
||||
---
|
||||
|
||||
### P2-4:主动回忆(Active Recall)流程
|
||||
|
||||
**现状:** RecallTestPage 只提交假的 AI 分析,没有调 `GET /active-recalls`。
|
||||
|
||||
**需要做:** 新建 ActiveRecallView,展示问题卡片 → 输入回答 → 调 `POST /active-recalls/:id/submit`。
|
||||
|
||||
---
|
||||
|
||||
### P2-5:Token 自动刷新与登录态管理
|
||||
|
||||
**现状:** Token 没有持久化,没有 refresh 逻辑。
|
||||
|
||||
**需要做:** Keychain 存储 accessToken + refreshToken;APIClient 拦截 401 → 自动调 `POST /auth/refresh` → 重试原请求;refresh 也失败 → 清 Token → 跳登录页。
|
||||
|
||||
---
|
||||
|
||||
## 五、P3 —— 体验增强(5 项)
|
||||
|
||||
| # | 项目 | 说明 |
|
||||
|---|------|------|
|
||||
| P3-1 | 下拉刷新 | 所有列表页 `.refreshable {}` + 页码分页 |
|
||||
| P3-2 | 加载/空/错误三态 | 每个数据加载页加 ProgressView / 空状态插图+文案 / 错误重试按钮 |
|
||||
| P3-3 | 离线缓存 | 用 UserDefaults 或本地 JSON 缓存最近数据,断网可展示 |
|
||||
| P3-4 | 深色模式 | 当前强制 `.dark`,需支持跟随系统 |
|
||||
| P3-5 | 无障碍 | VoiceOver labels、Dynamic Type 适配、高对比度 |
|
||||
|
||||
---
|
||||
|
||||
## 六、实施建议顺序
|
||||
|
||||
```
|
||||
第 1 周 ─ P0-1 登录 → P0-2 知识库CRUD → P0-3 学习会话
|
||||
第 2 周 ─ P0-4 复习卡片 → P1-1 薄弱点/AI分析 → P1-2 StudyHomeView 真实化
|
||||
第 3 周 ─ P1-3 ProfileView → P1-4 通知中心 → P1-5 反馈
|
||||
第 4 周 ─ P2-1 文件导入 → P2-2 搜索 → P2-3 设置页
|
||||
第 5 周 ─ P2-4 主动回忆 → P2-5 Token刷新
|
||||
第 6 周 ─ P3 体验增强
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 七、后端接口未封装清单(需新增 Service 方法)
|
||||
|
||||
| 模块 | 后端口 | 未封装接口 |
|
||||
|------|--------|----------|
|
||||
| KnowledgeBase | PATCH/DELETE | update / delete |
|
||||
| KnowledgeItems | PATCH/DELETE | update / delete |
|
||||
| LearningSession | POST/GET | start / end / list |
|
||||
| ActiveRecall | GET/POST | list / submit |
|
||||
| AIAnalysis | GET | result / job status |
|
||||
| Activity | GET | heatmap |
|
||||
| Notifications | GET/POST | list / markRead |
|
||||
| DocumentImport | POST/GET | create / status |
|
||||
| Review | POST | submit |
|
||||
| FocusItems | POST/PATCH | create / update / complete |
|
||||
|
||||
> 需新增约 15 个 Service 方法 + 对应 Request/Response DTO
|
||||
@ -1,235 +0,0 @@
|
||||
# 知习 ZhiXi — 页面清单与功能说明
|
||||
|
||||
> 更新时间:2026-05-10
|
||||
|
||||
## 项目概述
|
||||
|
||||
**知习 (ZhiXi)** 是一个 AI-first 系统化学习 iOS App,使用 SwiftUI 构建,深色主题。当前已完成 22 个页面的 UI 层实现,覆盖从引导流程到主界面 5 个 Tab 的完整交互链路。
|
||||
|
||||
---
|
||||
|
||||
## 一、引导流程(5 页)
|
||||
|
||||
所有引导页面定义在 `AIStudyAppApp.swift` 的 `OnboardingFlowView` 中,通过 `@AppStorage("hasCompletedOnboarding")` 控制显示。
|
||||
|
||||
### 1. SplashPage — 启动页
|
||||
|
||||
- **路由**:`OnboardingFlowView` step 0
|
||||
- **功能**:展示品牌 Logo、App 名称"知习"、副标题"AI-first 系统化学习",底部显示加载进度条,2 秒后自动跳转 Welcome
|
||||
- **视觉**:深色渐变背景 + 紫色/橙色光晕 + 品牌渐变图标
|
||||
|
||||
### 2. WelcomePage — 欢迎页
|
||||
|
||||
- **路由**:`OnboardingFlowView` step 1
|
||||
- **功能**:展示产品三大核心功能(主动回忆、费曼解释、AI 分析);提供"开始使用"和"已有账号?立即登录"两个入口
|
||||
- **UI 组件**:`FeatureRow`(emoji + 标题 + 描述卡片)
|
||||
|
||||
### 3. LoginPage — 登录页
|
||||
|
||||
- **路由**:`OnboardingFlowView` step 2
|
||||
- **功能**:支持手机号(+86)和邮箱两种登录方式切换;密码输入可切换明文/密文;底部提供微信登录和 Apple 登录入口;包含"忘记密码"链接
|
||||
- **UI 组件**:`ZXInputField`、`SocialLoginBtn`
|
||||
|
||||
### 4. OnboardingPage — 功能引导页
|
||||
|
||||
- **路由**:`OnboardingFlowView` step 3
|
||||
- **功能**:4 步滑动引导(输入知识 → 主动输出 → AI 分析 → 掌握知识),底部进度指示器,支持跳过
|
||||
- **UI 组件**:步进圆点指示器
|
||||
|
||||
### 5. GoalSetupPage — 学习目标设置页
|
||||
|
||||
- **路由**:`OnboardingFlowView` step 4
|
||||
- **功能**:设置学习目标(备考考试/职业技能/通识学习/自定义)、选择学习方法(间隔回忆/费曼技巧/AI 分析)、选择每日学习时间(15 分钟 ~ 不限制)
|
||||
- **UI 组件**:目标选项卡片(emoji + 标题 + 描述 + 单选圆点)、方法标签组、时间选择组
|
||||
|
||||
---
|
||||
|
||||
## 二、主界面 — 5 Tab 结构
|
||||
|
||||
`ContentView.swift` 实现底部 5 个 Tab 的导航:AI、知识库、学习、分析、我的。
|
||||
|
||||
### Tab 栏组件
|
||||
|
||||
- **ZXTabBar**:自定义底部 TabBar,包含选中态光晕动画、品牌紫色高亮
|
||||
- **ZXAIInputBar**:复用的 AI 输入栏(sparkles 图标 + 输入框 + 麦克风 + 发送按钮)
|
||||
- **ZXIconBtn**:通用图标按钮(支持 branded 紫色渐变样式)
|
||||
- **ZXScoreBox**:评分展示组件(分数 + 背景色 + 前景色,根据分数区间变色)
|
||||
|
||||
---
|
||||
|
||||
### Tab 1:AI 助手 — AIHomeView
|
||||
|
||||
- **文件**:`Features/AI/AIHomeView.swift`
|
||||
- **功能**:
|
||||
- 今日思考题卡片(展示 AI 生成的思考题,点击进入回答)
|
||||
- 快捷操作区(生成回忆测试、分析薄弱点、费曼解释练习、今日复习计划)
|
||||
- 最近 AI 互动列表(费曼复习、薄弱点分析、回忆测试记录,含评分)
|
||||
- AI 提问建议区(预设问题模板,点击可发送)
|
||||
- 底部 AI 输入栏
|
||||
- **子页面**:
|
||||
- `DailyThinkingPage` — 今日思考详情(见下方)
|
||||
- `RecallTestPage` — 回忆测试
|
||||
- `WeakPointsPage` — 薄弱点分析
|
||||
- `AIChatPage` — AI 对话
|
||||
- **UI 组件**:`ZXQuickAction`(emoji + 标签)、`ZXAIInteractionRow`(标签 + 标题 + 时间 + 评分)
|
||||
|
||||
#### AI 子页面(定义在 `Features/AI/DailyThinkingPage.swift`)
|
||||
|
||||
| 页面 | 功能 |
|
||||
|------|------|
|
||||
| **DailyThinkingPage** | 展示思考题 + 文本输入框,用户写下回答后提交给 AI 评估 |
|
||||
| **AIChatPage** | AI 对话页面,围绕当前知识库进行学习问答 |
|
||||
| **RecallTestPage** | 回忆测试:展示题目,用户回忆并写下理解,提交验证 |
|
||||
| **WeakPointsPage** | 薄弱知识点列表,每个知识点显示掌握分数、所属知识库、优先级 |
|
||||
| **AIFeedbackPage** | AI 反馈页,展示 AI 对用户回答的评分、优缺点分析、改进建议 |
|
||||
|
||||
**共享 UI 组件**:`ZXBackHeader` — 带返回按钮、标题、副标题、右侧操作区的通用导航头
|
||||
|
||||
---
|
||||
|
||||
### Tab 2:知识库 — LibraryHomeView
|
||||
|
||||
- **文件**:`Features/Library/LibraryHomeView.swift`
|
||||
- **功能**:
|
||||
- 知识库列表(机器学习、高等数学、英语词汇、产品设计等),每个卡片展示 emoji、名称、描述、知识点数量、掌握度百分比、标签、最近学习时间
|
||||
- 顶部搜索栏
|
||||
- 右上角搜索和创建按钮
|
||||
- 创建新知识库入口(虚线边框卡片)
|
||||
- **UI 组件**:`ZLibraryCard`(emoji + 名称 + 描述 + 进度条 + 标签 + 统计)
|
||||
|
||||
#### 知识库子页面(定义在 `Features/Library/LibrarySubpages.swift`)
|
||||
|
||||
| 页面 | 功能 |
|
||||
|------|------|
|
||||
| **CreateLibraryPage** | 创建新知识库:填写名称、描述 |
|
||||
| **LibraryDetailPage** | 知识库详情:展示该知识库下所有知识点列表,每个知识点显示标题、描述、掌握状态(已掌握/学习中/待复习) |
|
||||
| **AddKnowledgePage** | 添加知识点:填写标题、内容 |
|
||||
| **KnowledgeDetailPage** | 知识点详情:展示完整内容、标签、复习/费曼解释按钮 |
|
||||
| **ImportPage** | 导入资料 |
|
||||
| **EditKnowledgePage** | 编辑知识点 |
|
||||
|
||||
**知识库卡片组件**:`ZXCardRow` — emoji + 标题 + 描述 + 状态标签
|
||||
|
||||
---
|
||||
|
||||
### Tab 3:学习工作台 — StudyHomeView
|
||||
|
||||
- **文件**:`Features/Study/StudyHomeView.swift`
|
||||
- **功能**:
|
||||
- 日期和问候语("周四,1月16日")
|
||||
- 连续学习天数徽章(🔥)
|
||||
- 今日进度卡片:完成任务数/总任务数、进度百分比环形图、进度条、已学时间/剩余时间/掌握积分
|
||||
- 今日任务列表(机器学习回忆测试、高数间隔复习、英语词汇复习等),每个任务可勾选完成,显示任务类型标签和预计时长
|
||||
- 本周学习活跃柱状图(周一~周日,高亮当天)
|
||||
- 总计学习时长和日均统计
|
||||
- **数据模型**:`ZXSTask`(标题、类型、颜色、时长、完成状态)
|
||||
- **UI 组件**:`ZXSTaskRow`(勾选框 + 任务信息 + 类型标签 + 时长 + 播放按钮)
|
||||
|
||||
---
|
||||
|
||||
### Tab 4:学习分析 — AnalysisHomeView
|
||||
|
||||
- **文件**:`Features/Analysis/AnalysisHomeView.swift`
|
||||
- **功能**:
|
||||
- 顶部统计卡片行:综合掌握度(65%,+8%)、本周积分(1,240)、待巩固知识点数(23)、连续学习天数(14)
|
||||
- 掌握度趋势折线图(近 7 天数据)
|
||||
- 薄弱知识点列表(可导航至 WeakPointsPage)
|
||||
- AI 学习建议卡片
|
||||
- 知识库掌握分布(各知识库掌握度进度条)
|
||||
- **UI 组件**:`ZXStatBadge`(图标 + 标签 + 数值 + 变化趋势)、`ZXChartView`、`ZXWeakRow`
|
||||
|
||||
---
|
||||
|
||||
### Tab 5:我的 — ProfileView
|
||||
|
||||
- **文件**:`Features/Profile/ProfileView.swift`
|
||||
- **功能**:
|
||||
- 顶部导航栏(标题"我的" + 通知铃铛 + 设置齿轮)
|
||||
- 个人信息卡片:头像(emoji)、昵称"学习者"、邮箱、连续天数/知识点数/积分统计
|
||||
- 设置菜单:学习目标设置、复习提醒、学习报告、学习方法偏好、数据同步与备份
|
||||
- 成就展示区(连续 14 天、费曼达人、知识收藏家、速学者)
|
||||
- **UI 组件**:`ZXProfileStat`、`ZXProfileMenuRow`(emoji + 标题 + 描述 + 箭头)、`ZXAchievementBadge`
|
||||
|
||||
---
|
||||
|
||||
## 三、设计系统
|
||||
|
||||
文件:`Core/DesignSystem/DesignTokens.swift`
|
||||
|
||||
### 颜色系统
|
||||
| 类别 | Token | 值 |
|
||||
|------|-------|-----|
|
||||
| 主背景 | `Color.zxBg0` | `#0F0F1A` |
|
||||
| 品牌紫 | `Color.zxPurple` | `#7C6EFA` |
|
||||
| 品牌橙 | `Color.zxOrange` | `#F97316` |
|
||||
| 文字主色 | `Color.zxF0` | `#F0F0FF` |
|
||||
|
||||
### 渐变系统 (`ZXGradient`)
|
||||
- `page` — 页面背景渐变
|
||||
- `brand` — 品牌紫橙渐变
|
||||
- `brandPurple` — 紫色渐变
|
||||
- `thinkingCard` — 思考卡片渐变
|
||||
- `progressCard` — 进度卡片渐变
|
||||
- `feedbackScore` — 反馈评分渐变
|
||||
- `profileCard` — 个人信息卡片渐变
|
||||
- `ctaButton` / `ctaPurple` — CTA 按钮渐变
|
||||
|
||||
### 间距系统 (`ZXSpacing`)
|
||||
- `pageHPadding`: 20
|
||||
- `statusBarH`: 44
|
||||
- `tabBarH`: 83
|
||||
|
||||
### 尺寸系统 (`ZXSize`)
|
||||
- 图标按钮: 36, 头像: 36/64/80
|
||||
- 按钮高度: 42/52/56, 快捷操作: 72
|
||||
|
||||
### 排版系统 (`ZXFont`)
|
||||
- `titleLarge`: 22pt heavy, -0.5 tracking
|
||||
- `titleMedium`: 20pt heavy, -0.4 tracking
|
||||
- `sectionTitle`: 15pt bold
|
||||
- `body`: 13pt semibold
|
||||
- `bodySmall`: 12pt medium
|
||||
- `caption`: 10pt bold
|
||||
|
||||
---
|
||||
|
||||
## 四、页面状态总览
|
||||
|
||||
| # | 页面 | Tab | 文件 | 导航方式 | 状态 |
|
||||
|---|------|-----|------|----------|------|
|
||||
| 1 | Splash 启动页 | — | AIStudyAppApp.swift | 自动跳转 | ✅ |
|
||||
| 2 | Welcome 欢迎页 | — | AIStudyAppApp.swift | 按钮跳转 | ✅ |
|
||||
| 3 | Login 登录页 | — | AIStudyAppApp.swift | 按钮跳转 | ✅ |
|
||||
| 4 | Onboarding 引导 | — | AIStudyAppApp.swift | 步进/跳过 | ✅ |
|
||||
| 5 | GoalSetup 目标 | — | AIStudyAppApp.swift | 完成进入主界面 | ✅ |
|
||||
| 6 | AIHome AI 首页 | AI | AIHomeView.swift | Tab 1 | ✅ |
|
||||
| 7 | LibraryHome 知识库 | 知识库 | LibraryHomeView.swift | Tab 2 | ✅ |
|
||||
| 8 | StudyHome 学习 | 学习 | StudyHomeView.swift | Tab 3 | ✅ |
|
||||
| 9 | AnalysisHome 分析 | 分析 | AnalysisHomeView.swift | Tab 4 | ✅ |
|
||||
| 10 | Profile 我的 | 我的 | ProfileView.swift | Tab 5 | ✅ |
|
||||
| 11 | AIChat AI 对话 | AI | DailyThinkingPage.swift | NavigationLink | ✅ |
|
||||
| 12 | DailyThinking 今日思考 | AI | DailyThinkingPage.swift | NavigationLink | ✅ |
|
||||
| 13 | RecallTest 回忆测试 | AI | DailyThinkingPage.swift | NavigationLink | ✅ |
|
||||
| 14 | WeakPoints 薄弱点 | AI | DailyThinkingPage.swift | NavigationLink | ✅ |
|
||||
| 15 | AIFeedback AI 反馈 | AI | DailyThinkingPage.swift | NavigationLink | ✅ |
|
||||
| 16 | CreateLibrary 创建知识库 | 知识库 | LibrarySubpages.swift | NavigationLink | ✅ |
|
||||
| 17 | LibraryDetail 知识库详情 | 知识库 | LibrarySubpages.swift | NavigationLink | ✅ |
|
||||
| 18 | AddKnowledge 添加知识点 | 知识库 | LibrarySubpages.swift | NavigationLink | ✅ |
|
||||
| 19 | Import 导入资料 | 知识库 | LibrarySubpages.swift | NavigationLink | ✅ |
|
||||
| 20 | KnowledgeDetail 知识点详情 | 知识库 | LibrarySubpages.swift | NavigationLink | ✅ |
|
||||
| 21 | EditKnowledge 编辑知识点 | 知识库 | LibrarySubpages.swift | NavigationLink | ✅ |
|
||||
|
||||
---
|
||||
|
||||
## 五、当前未实现的功能
|
||||
|
||||
以下为产品计划中但当前 iOS 项目尚未实现的能力:
|
||||
|
||||
- Sign in with Apple(UI 已做,实际认证逻辑未接入)
|
||||
- 后端 API 对接(当前为纯本地 UI)
|
||||
- 真实 AI 分析(当前为静态展示)
|
||||
- 数据持久化(无本地存储/云端同步)
|
||||
- 多语言本地化架构
|
||||
- Apple IAP 支付
|
||||
- 推送通知
|
||||
- 崩溃监控/数据埋点
|
||||
@ -1,339 +0,0 @@
|
||||
# 个人开发者创业 v0.1 — iOS 相关需求整理
|
||||
|
||||
> 来源:`startup-plan/个人开发者创业 v0.1/` 各文档
|
||||
> 整理时间:2026-05-10
|
||||
|
||||
本文档从 v0.1 创业计划中提取所有与 iOS 客户端直接相关的内容,作为 iOS 开发的参考基线。
|
||||
|
||||
---
|
||||
|
||||
## 一、产品定位(来源:`0-项目总纲/项目总纲.md`)
|
||||
|
||||
- 产品长期方向:AI 驱动的系统化学习产品(知识库 + 笔记 + AI 学习教练 + 复习计划)
|
||||
- 当前只做三件事:确定方向 → 做 14 天验证 Demo → 找第一批真实反馈
|
||||
- 平台策略:**只做 iPhone**,不做 Android/iPad/Mac/Web 学习端
|
||||
- 不做:完整平台、泛学习大而全、复杂后端、支付
|
||||
|
||||
### 三个候选方向
|
||||
|
||||
1. 公考申论 AI 学习教练
|
||||
2. AI 工具学习知识库
|
||||
3. 程序员/前端面试学习助手
|
||||
|
||||
---
|
||||
|
||||
## 二、第一版产品形态(来源:`2-Demo与MVP/Demo与MVP.md`)
|
||||
|
||||
```
|
||||
iPhone App + 官网基础页面 + 最小后端 + AI API
|
||||
```
|
||||
|
||||
### MVP 核心学习闭环
|
||||
|
||||
```
|
||||
注册/登录 → 选择学习方向 → 进入学习路径 → 阅读知识内容
|
||||
→ 主动回忆/写笔记/写答案 → AI 分析 → 生成学习状态
|
||||
→ 给出复习和下一步建议 → 进入下一次学习
|
||||
```
|
||||
|
||||
### 第一版页面列表(计划 14 页)
|
||||
|
||||
| 优先级 | 页面 | 当前 iOS 实现 |
|
||||
|--------|------|---------------|
|
||||
| **P0** | 登录页 | `LoginPage` ✅ |
|
||||
| **P0** | 学习方向选择页 | `GoalSetupPage` ✅ (部分) |
|
||||
| **P0** | 学习路径页 | `LibraryHomeView` + `LibraryDetailPage` ✅ |
|
||||
| **P0** | 今日学习任务页 | `StudyHomeView` ✅ |
|
||||
| **P0** | 内容阅读页 | `KnowledgeDetailPage` ✅ |
|
||||
| **P0** | 主动回忆/笔记输入页 | `DailyThinkingPage` + `RecallTestPage` ✅ |
|
||||
| **P0** | AI 分析结果页 | `AIFeedbackPage` ✅ |
|
||||
| **P0** | AI 对话页 | `AIChatPage` ✅ |
|
||||
| **P0** | 复习计划页 | 未独立实现 ⚠️ (部分在 StudyHomeView) |
|
||||
| **P1** | 学习进度页 | `AnalysisHomeView` ✅ |
|
||||
| **P1** | 设置页 | `ProfileView` ✅ |
|
||||
| **P1** | 反馈页 | 未实现 ❌ |
|
||||
| **P1** | 启动页/欢迎页 | `SplashPage` + `WelcomePage` ✅ |
|
||||
| **P1** | 语言与基础偏好页 | 未实现 ❌ |
|
||||
|
||||
### 底部 Tab 设计(计划)
|
||||
|
||||
```
|
||||
学习 | 知识库 | AI助手 | 我的
|
||||
```
|
||||
|
||||
当前 iOS 实现为 5 个 Tab:`AI | 知识库 | 学习 | 分析 | 我的`(多了"分析"Tab,将计划的 AI 助手拆分为独立的分析页)
|
||||
|
||||
---
|
||||
|
||||
## 三、账号体系(来源:`2-Demo与MVP/Demo与MVP.md`)
|
||||
|
||||
- **第一版登录方式**:Sign in with Apple
|
||||
- **暂不做**:微信登录、手机号登录、邮箱密码登录、Google 登录
|
||||
|
||||
> ⚠️ 当前 iOS `LoginPage` 包含了手机号/邮箱登录 + 微信/Apple 登录 UI,与计划"A Sign in with Apple"的要求不完全一致。计划强调极简,实际 UI 做了更多登录方式入口。
|
||||
|
||||
### 用户身份模型(计划)
|
||||
|
||||
```
|
||||
User
|
||||
├── id
|
||||
├── appleUserId
|
||||
├── displayName
|
||||
├── email
|
||||
├── preferredLanguage
|
||||
├── createdAt
|
||||
├── lastLoginAt
|
||||
└── status
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、知识库设计(来源:`2-Demo与MVP/Demo与MVP.md`)
|
||||
|
||||
### 数据结构
|
||||
|
||||
```
|
||||
KnowledgeBase → LearningPath → Module → Lesson
|
||||
├── 正文内容
|
||||
├── 学习目标
|
||||
├── 重点概念
|
||||
├── 主动回忆问题
|
||||
├── 练习输入
|
||||
└── AI 分析规则
|
||||
```
|
||||
|
||||
### 第一版内容范围
|
||||
|
||||
只做一个小路径,例如"AI 工具入门 7 天路径",而不是大而全的知识库市场。
|
||||
|
||||
---
|
||||
|
||||
## 五、AI 能力需求(来源:`2-Demo与MVP/Demo与MVP.md`)
|
||||
|
||||
### AI 三大核心职责
|
||||
|
||||
1. 分析用户输入
|
||||
2. 判断用户当前学习状态
|
||||
3. 给出下一步学习建议
|
||||
|
||||
### AI 分析维度
|
||||
|
||||
```
|
||||
理解程度、要点覆盖、逻辑结构、表达清晰度、错误理解、遗漏内容、下一步建议
|
||||
```
|
||||
|
||||
### AI 输出结构(计划 JSON Schema)
|
||||
|
||||
```json
|
||||
{
|
||||
"masteryScore": 3,
|
||||
"understandingLevel": "基本理解",
|
||||
"summary": "用户能说出核心意思,但要点不够完整。",
|
||||
"strengths": ["能识别主要问题", "表达比较清楚"],
|
||||
"weakPoints": ["遗漏关键要点", "逻辑层次不够清晰"],
|
||||
"suggestions": ["补充材料中的第二个要点", "回答时先概括问题,再展开原因"],
|
||||
"reviewNeeded": true,
|
||||
"nextAction": "建议明天复习本节,并重新回答主动回忆问题。"
|
||||
}
|
||||
```
|
||||
|
||||
### 掌握度评分(0-5)
|
||||
|
||||
```
|
||||
0 = 没有作答/无法判断
|
||||
1 = 基本没理解
|
||||
2 = 理解较弱
|
||||
3 = 基本理解
|
||||
4 = 理解较好
|
||||
5 = 掌握很好
|
||||
```
|
||||
|
||||
### AI 对话页定位
|
||||
|
||||
只能围绕当前知识库和学习内容,不能做泛聊天。快捷问题预设:
|
||||
- 帮我解释这一节
|
||||
- 用更简单的话讲
|
||||
- 给我举个例子
|
||||
- 我哪里理解错了
|
||||
- 帮我总结重点
|
||||
- 生成一个复习问题
|
||||
|
||||
---
|
||||
|
||||
## 六、学习状态模型(来源:`2-Demo与MVP/Demo与MVP.md`)
|
||||
|
||||
### 用户学习画像
|
||||
|
||||
```
|
||||
UserLearningProfile
|
||||
├── userId
|
||||
├── currentKnowledgeBaseId
|
||||
├── currentPathId
|
||||
├── currentLessonId
|
||||
├── overallLevel
|
||||
├── weakPoints
|
||||
├── strengths
|
||||
├── recentMistakes
|
||||
├── reviewQueue
|
||||
├── learningStreak
|
||||
└── updatedAt
|
||||
```
|
||||
|
||||
### 单次学习记录
|
||||
|
||||
```
|
||||
LearningSession
|
||||
├── id
|
||||
├── userId
|
||||
├── lessonId
|
||||
├── startedAt
|
||||
├── endedAt
|
||||
├── userInput
|
||||
├── aiAnalysis
|
||||
├── masteryScore
|
||||
├── weakPoints
|
||||
├── nextSuggestion
|
||||
└── reviewAt
|
||||
```
|
||||
|
||||
### 复习任务
|
||||
|
||||
```
|
||||
ReviewTask
|
||||
├── id
|
||||
├── userId
|
||||
├── lessonId
|
||||
├── sourceSessionId
|
||||
├── reviewType
|
||||
├── scheduledAt
|
||||
├── completedAt
|
||||
└── status
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 七、UI 设计原则(来源:`2-Demo与MVP/Demo与MVP.md`)
|
||||
|
||||
```
|
||||
安静、清晰、克制、学习感、低干扰、Apple原生感、卡片式结构、适合长时间阅读
|
||||
```
|
||||
|
||||
- 不做花哨视觉
|
||||
- 不做复杂动画
|
||||
- 不做社交信息流
|
||||
- 不做游戏化过重设计
|
||||
- 优先保证阅读体验
|
||||
- 优先保证学习任务清晰
|
||||
- 优先保证 AI 分析结果可理解
|
||||
|
||||
---
|
||||
|
||||
## 八、技术选型(来源:`3-官网与技术基础/官网与技术基础.md`)
|
||||
|
||||
| 项目 | 计划选型 | 当前实现 |
|
||||
|------|----------|----------|
|
||||
| UI 框架 | SwiftUI | SwiftUI ✅ |
|
||||
| 架构模式 | MVVM + Service + Repository | 无分层(View 内聚)⚠️ |
|
||||
| 设计规范 | Apple HIG | 深色主题 + 自定义 DesignTokens ✅ |
|
||||
| 动效策略 | 轻量、有意义、服务学习体验 | 最小动效(仅基础过渡)⚠️ |
|
||||
| 多语言 | 预留架构,中文默认 | 未实现 ❌ |
|
||||
| 部署 | 4 核 4G 轻量云 + Nginx + Docker | 未接入 ❌ |
|
||||
|
||||
### 目录结构(计划 vs 实际)
|
||||
|
||||
计划定义了完整的分层目录(App/Core/Features/Shared/Resources),当前实现仅有 Features 和 DesignSystem,缺少 Network、Auth、Storage、Localization、ViewModel、Model 等层。
|
||||
|
||||
### 第一版 iOS 不做(来自计划)
|
||||
|
||||
- 复杂动画系统
|
||||
- iPad 专门布局 / Mac Catalyst / Watch App / Widget
|
||||
- 离线完整知识库
|
||||
- 复杂搜索
|
||||
- 文件导入
|
||||
- 推送通知
|
||||
- 支付订阅
|
||||
- 复杂自定义控件
|
||||
|
||||
---
|
||||
|
||||
## 九、数据实体汇总(来源:`2-Demo与MVP/Demo与MVP.md`)
|
||||
|
||||
```
|
||||
User
|
||||
KnowledgeBase
|
||||
LearningPath
|
||||
Lesson
|
||||
LearningSession
|
||||
AIAnalysis
|
||||
ReviewTask
|
||||
Feedback
|
||||
WaitlistEntry
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 十、核心 API 接口(来源:`3-官网与技术基础/官网与技术基础.md`)
|
||||
|
||||
### POST /ai/analyze-learning-input
|
||||
|
||||
分析用户学习输入,返回掌握度评估。
|
||||
|
||||
### POST /ai/chat
|
||||
|
||||
AI 对话接口,限于当前知识库上下文。
|
||||
|
||||
### 后端模块(P0)
|
||||
|
||||
Auth → User → Knowledge → Learning → AI → Review → Feedback → Waitlist
|
||||
|
||||
---
|
||||
|
||||
## 十一、成功标准(来源:`2-Demo与MVP/Demo与MVP.md`)
|
||||
|
||||
### 产品可用标准
|
||||
|
||||
- 用户能登录
|
||||
- 用户能选择学习路径
|
||||
- 用户能完成一节学习
|
||||
- 用户能输入内容
|
||||
- AI 能返回分析
|
||||
- 系统能生成复习建议
|
||||
- 用户知道下一步该干什么
|
||||
|
||||
### 验证成功标准
|
||||
|
||||
- 至少 10 个用户愿意试用
|
||||
- 至少 3 个用户完整走完学习闭环
|
||||
- 至少 3 条有效反馈
|
||||
- 至少 1 个用户表示愿意继续用
|
||||
- 至少 1 个用户表示未来愿意付费
|
||||
|
||||
---
|
||||
|
||||
## 十二、暂缓事项(来源:`99-暂缓事项/暂缓事项.md`)
|
||||
|
||||
以下为 v0.1 明确不做、后续解冻的事项:
|
||||
|
||||
| 类别 | 暂缓内容 | 解冻条件 |
|
||||
|------|----------|----------|
|
||||
| 商业化 | Apple IAP、订阅、免费试用 | TestFlight 有真实用户 + 有人愿意付费 |
|
||||
| 运营 | 社群、客服机器人、打卡活动 | 10+ 内测用户持续反馈 |
|
||||
| 数据 | 完整埋点、留存分析、付费转化 | App Store MVP 准备上线 |
|
||||
| 合规 | 公司注册、微信/支付宝、备案 | Apple 端稳定收入 |
|
||||
| 多端 | iPad、Mac、Android、Web | iPhone 核心稳定 + 用户多端需求 |
|
||||
|
||||
---
|
||||
|
||||
## 十三、当前 iOS 实现与计划的差距
|
||||
|
||||
| 维度 | 计划要求 | 当前状态 | 差距 |
|
||||
|------|----------|----------|------|
|
||||
| 登录 | Sign in with Apple | 多种登录 UI | 需简化或实现 Apple 登录 |
|
||||
| 架构 | MVVM + Service | View 内聚 | 需重构分层 |
|
||||
| 多语言 | 架构预留 | 未实现 | 需添加本地化 |
|
||||
| 后端对接 | REST API | 无 | 需接入 |
|
||||
| AI 集成 | 真实 AI 分析 | 静态 Mock | 需接入 AI API |
|
||||
| 数据持久化 | 本地缓存 + Keychain | 无 | 需实现 |
|
||||
| Tab 设计 | 4 个 Tab | 5 个 Tab | 多了"分析"Tab |
|
||||
| 反馈页 | P1 优先级 | 未实现 | 需添加 |
|
||||
| 复习计划页 | P0 优先级 | 部分实现 | 需独立设计 |
|
||||
@ -1,550 +0,0 @@
|
||||
# 知习 iOS 样式规范
|
||||
|
||||
> 基于现有 DesignTokens 与实际页面中反复出现的 UI 模式,归纳形成本规范。
|
||||
> 后续创建新页面时,优先从本文档引用的 token 和组件中选择,保持一致的设计语言。
|
||||
|
||||
---
|
||||
|
||||
## 一、色彩系统
|
||||
|
||||
所有颜色定义在 `Core/DesignSystem/DesignTokens.swift`,命名前缀 `zx`(知习)。
|
||||
|
||||
### 1.1 背景
|
||||
|
||||
| Token | 色值 | 用途 |
|
||||
|---|---|---|
|
||||
| `zxBg0` | `#0F0F1A` | 页面基底(与 zxBg1 组成 page 渐变) |
|
||||
| `zxBg1` | `#12122A` | page 渐变的第二色 |
|
||||
| `zxBg2` | `#0A0A14` | 手机外壳装饰用,极少使用 |
|
||||
| `zxBgSplash` | `#0D0D20` | 启动页专用 |
|
||||
|
||||
### 1.2 文字
|
||||
|
||||
所有文字色基于 `#F0F0FF`(近白紫调)变化透明度:
|
||||
|
||||
| Token | 透明度 | 用途 |
|
||||
|---|---|---|
|
||||
| `zxF0` | 100% | 标题、正文高亮 |
|
||||
| `zxF007` | 70% | 次重要正文 |
|
||||
| `zxF006` | 60% | — |
|
||||
| `zxF05` | 50% | 次要信息 |
|
||||
| `zxF0045` | 45% | — |
|
||||
| `zxF04` | 40% | 辅助描述 |
|
||||
| `zxF035` | 35% | 弱标签、灰色字段名 |
|
||||
| `zxF03` | 30% | 占位符级别 |
|
||||
| `zxF02` | 20% | 极弱(如未选中图标边框) |
|
||||
|
||||
### 1.3 品牌/语义色
|
||||
|
||||
| Token | 色值 | 含义 |
|
||||
|---|---|---|
|
||||
| `zxPurple` | `#7C6EFA` | 主品牌,选中态、标签、进度 |
|
||||
| `zxAccent` | `#A78BFA` | 次要品牌,AI 相关 |
|
||||
| `zxOrange` | `#F97316` | 热度/连续天数/回忆 |
|
||||
| `zxTeal` | `#2DD4BF` | 语言/词汇 |
|
||||
| `zxCyan` | `#4ECDC4` | 进度条渐变 |
|
||||
| `zxGreen` | `#34D399` | 已掌握、成功 |
|
||||
| `zxYellow` | `#F59E0B` | 薄弱/警告/待复习 |
|
||||
| `zxRed` | `#EF4444` | 错误/高优先级 |
|
||||
|
||||
**彩色半透明背景**(用于标签、badge 底衬):
|
||||
|
||||
```swift
|
||||
zxPurpleBG(0.12) // 紫色 12% 透明
|
||||
zxOrangeBG(0.10) // 橙色 10% 透明
|
||||
zxGreenBG(0.15) // 绿色 15% 透明
|
||||
zxYellowBG(0.15) // 黄色 15% 透明
|
||||
zxTealBG(0.10) // 青色 10% 透明
|
||||
zxRedBG(0.15) // 红色 15% 透明
|
||||
```
|
||||
|
||||
### 1.4 边框/分割线
|
||||
|
||||
| Token | 透明度 | 用途 |
|
||||
|---|---|---|
|
||||
| `zxBorder015` | 15% | 较明显边框 |
|
||||
| `zxBorder01` | 10% | 标准边框、虚线框 |
|
||||
| `zxBorder008` | 8% | 通用卡片边框 |
|
||||
| `zxBorder006` | 6% | 弱边框、卡片分隔 |
|
||||
| `zxBorder004` | 4% | 极弱边框 |
|
||||
|
||||
### 1.5 填充(半透明叠层)
|
||||
|
||||
| Token | 透明度 | 用途 |
|
||||
|---|---|---|
|
||||
| `zxFill01` | 10% | 图表柱状 |
|
||||
| `zxFill008` | 8% | 进度条底色 |
|
||||
| `zxFill006` | 6% | 列表图标底衬 |
|
||||
| `zxFill005` | 5% | 按钮/选中行底衬 |
|
||||
| `zxFill004` | 4% | 输入框/面板底色 |
|
||||
| `zxFill003` | 3% | 卡片底色 |
|
||||
|
||||
---
|
||||
|
||||
## 二、渐变
|
||||
|
||||
所有渐变定义在 `ZXGradient` enum。
|
||||
|
||||
| 渐变 | 颜色 | 方向 | 用途 |
|
||||
|---|---|---|---|
|
||||
| `page` | `#0F0F1A → #12122A` | top→bottom | 所有主页面背景 |
|
||||
| `splash` | `#0D0D20 → #0F0F1A → #130D20` | top→bottom | 启动页背景 |
|
||||
| `brand` | `#7C6EFA → #F97316` | topLeading→bottomTrailing | CTA 按钮、播放按钮 |
|
||||
| `brandPurple` | `#7C6EFA → #9B8BFF` | leading→trailing | 发送按钮、AI 气泡 |
|
||||
| `ctaButton` | `#7C6EFA → #F97316` | topLeading→bottomTrailing | 同 brand,CTA 语义 |
|
||||
| `ctaPurple` | `#7C6EFA → #9B8BFF` | topLeading→bottomTrailing | 紫色 CTA(创建/保存/提交) |
|
||||
| `progressBar` | `#7C6EFA → #4ECDC4` | leading→trailing | 进度条 |
|
||||
| `thinkingCard` | `#7C6EFA 8% → #F97316 4%` | topLeading→bottomTrailing | 思考卡片 |
|
||||
| `progressCard` | `#7C6EFA 10% → #F97316 5%` | topLeading→bottomTrailing | 进度卡片 |
|
||||
| `feedbackScore` | `#7C6EFA 12% → #34D399 6%` | topLeading→bottomTrailing | 反馈评分卡片 |
|
||||
| `profileCard` | `#7C6EFA 15% → #F97316 8%` | topLeading→bottomTrailing | 个人页卡片 |
|
||||
|
||||
---
|
||||
|
||||
## 三、圆角
|
||||
|
||||
```swift
|
||||
ZXRadius.xs = 2 // 进度指示器小圆点
|
||||
ZXRadius.sm = 8 // 小图标
|
||||
ZXRadius.md = 10 // 标准图标按钮
|
||||
ZXRadius.lg = 12 // 标签/徽章
|
||||
ZXRadius.xl = 14 // 卡片/输入框/行
|
||||
ZXRadius.xl2 = 16 // 大卡片/对话框
|
||||
ZXRadius.xl3 = 20 // 主要面板
|
||||
|
||||
ZXRadius.button = 12 // 标准按钮
|
||||
ZXRadius.buttonLg = 18 // 大按钮(CTA)
|
||||
ZXRadius.icon = 10 // 小图标
|
||||
ZXRadius.iconLg = 12 // 中图标
|
||||
ZXRadius.avatar = 13 // 头像/emoji 图标
|
||||
```
|
||||
|
||||
**使用原则**:
|
||||
- 卡片统一 `14`–`20`
|
||||
- 按钮统 `12`–`18`
|
||||
- 输入框 `14`
|
||||
- 标签 `Capsule()`(自动全圆角)
|
||||
|
||||
---
|
||||
|
||||
## 四、间距
|
||||
|
||||
```swift
|
||||
ZXSpacing.ss = 2 // 字间距/tracking 用
|
||||
ZXSpacing.xs = 4
|
||||
ZXSpacing.sm = 6
|
||||
ZXSpacing.md = 8 // 卡片内元素间距
|
||||
ZXSpacing.lg = 10
|
||||
ZXSpacing.xl = 12 // 行内元素间距
|
||||
ZXSpacing.xl2 = 14
|
||||
ZXSpacing.xl3 = 16 // 卡片间距
|
||||
ZXSpacing.xl4 = 20 // 页面水平内边距
|
||||
ZXSpacing.xl5 = 24
|
||||
ZXSpacing.xl6 = 28
|
||||
|
||||
// 专用
|
||||
ZXSpacing.pageHPadding = 20 // 所有页面两侧统一留白
|
||||
ZXSpacing.statusBarH = 44 // 状态栏 + Dynamic Island
|
||||
ZXSpacing.tabBarH = 83 // 底部 TabBar 总高
|
||||
ZXSpacing.homeIndicatorH = 34 // Home Indicator
|
||||
```
|
||||
|
||||
**页面结构公式**:
|
||||
```
|
||||
header top padding = statusBarH + 16
|
||||
每个 section 间距 = 12–20
|
||||
ScrollView bottom = 120(有 TabBar)/ 80–100(子页面)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、尺寸
|
||||
|
||||
```swift
|
||||
// 按钮
|
||||
ZXSize.iconBtn = 36 // 图标按钮(ZXIconBtn 默认)
|
||||
ZXSize.buttonH = 42 // 标准按钮高
|
||||
ZXSize.buttonLgH = 52 // 大按钮高
|
||||
ZXSize.buttonXlH = 56 // CTA 按钮高
|
||||
ZXSize.sendBtn = 30 // 发送按钮
|
||||
|
||||
// 图标
|
||||
ZXSize.iconSm = 14
|
||||
ZXSize.iconMd = 16
|
||||
ZXSize.iconLg = 18
|
||||
ZXSize.tabIcon = 22 // TabBar 图标
|
||||
ZXSize.listIcon = 40 // 列表图标
|
||||
ZXSize.libraryIcon = 44 // 知识库卡片图标
|
||||
|
||||
// 头像
|
||||
ZXSize.avatarSm = 36
|
||||
ZXSize.avatarMd = 64
|
||||
ZXSize.avatarLg = 80
|
||||
|
||||
// 其他
|
||||
ZXSize.quickActionH = 72 // 快捷操作高度
|
||||
ZXSize.inputH = 44 // 输入框高度
|
||||
ZXSize.progressH = 5 // 进度条高度
|
||||
ZXSize.scoreBox = 36 // 分数方块
|
||||
ZXSize.weakBox = 40 // 薄弱点分数方块
|
||||
ZXSize.topBar = 3 // 顶部装饰条
|
||||
ZXSize.searchIconBtn = 36 // 搜索图标按钮
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、字体层级
|
||||
|
||||
```swift
|
||||
// 使用方式: .font(.system(size: ZXFont.xxx.size, weight: ZXFont.xxx.weight))
|
||||
|
||||
titleLarge // 22pt, heavy, -0.5 → 页面主标题
|
||||
titleMedium // 20pt, heavy, -0.4 → 二级标题
|
||||
sectionTitle // 15pt, bold → 区域标题
|
||||
subsectionTitle // 14pt, bold → 子标题
|
||||
body // 13pt, semibold, 1.4 → 正文
|
||||
bodySmall // 12pt, medium → 辅助信息
|
||||
caption // 10pt, bold → 标签加粗
|
||||
captionSmall // 10pt, regular → 标签常规
|
||||
labelXs // 9pt, regular → 最小标签
|
||||
score // 12pt, heavy → 分数
|
||||
scoreLarge // 22pt, heavy, 1 → 大分数
|
||||
date // 12pt, medium → 日期
|
||||
description // 12pt, regular, 0.4 → 描述文字
|
||||
```
|
||||
|
||||
**实际页面中常用的内联声明**(可直接使用,也可用 ZXFont 引用):
|
||||
- 页面大标题:`.font(.system(size: 22, weight: .heavy)).tracking(-0.5)` `.foregroundColor(.zxF0)`
|
||||
- 区域标题:`.font(.system(size: 15, weight: .bold)).foregroundColor(.zxF0)`
|
||||
- 卡片标题:`.font(.system(size: 13, weight: .semibold)).foregroundColor(.zxF0)`
|
||||
- 辅助文字:`.font(.system(size: 12)).foregroundColor(.zxF04)`
|
||||
- 标签文字:`.font(.system(size: 10, weight: .semibold))`
|
||||
- 大数值:`.font(.system(size: 26, weight: .black))`
|
||||
|
||||
---
|
||||
|
||||
## 七、共享组件目录
|
||||
|
||||
以下组件散落在各页面文件中,新页面应直接复用,禁止重复实现。
|
||||
|
||||
### 7.1 导航/布局
|
||||
|
||||
**ZXTabBar**(`ContentView.swift:58`)
|
||||
5 个 tab(AI / 知识库 / 学习 / 分析 / 我的),选中态紫色高亮 + 圆形背景扩散。
|
||||
```swift
|
||||
ZXTabBar(active: $selectedTab)
|
||||
```
|
||||
|
||||
**ZXBackHeader**(`DailyThinkingPage.swift:52`)
|
||||
子页面顶部返回栏,含标题、副标题、可选的右侧按钮。
|
||||
```swift
|
||||
ZXBackHeader(title: "标题", subtitle: "副标题") { trailingView }
|
||||
ZXBackHeader(title: "标题", subtitle: nil, onBack: customBackAction) { ... }
|
||||
```
|
||||
|
||||
### 7.2 按钮
|
||||
|
||||
**ZXIconBtn**(`ContentView.swift:100`)
|
||||
标准 36pt 圆形图标按钮,可切换品牌渐变样式。
|
||||
```swift
|
||||
ZXIconBtn(icon: "bell", size: 36) { action }
|
||||
ZXIconBtn(icon: "plus", size: 36, branded: true) { action } // 品牌渐变底
|
||||
```
|
||||
|
||||
**ZXOutlineBtn**(`DailyThinkingPage.swift:167`)
|
||||
44pt 高描边文字按钮。
|
||||
```swift
|
||||
ZXOutlineBtn(text: "深入提问")
|
||||
```
|
||||
|
||||
### 7.3 列表/卡片行
|
||||
|
||||
**ZXCardRow**(`LibrarySubpages.swift:40`)
|
||||
带 emoji 图标、标题、描述、状态标签的标准列表行。
|
||||
```swift
|
||||
ZXCardRow(emoji: "📝", title: "标题", desc: "描述", status: "已掌握", c: .zxGreen)
|
||||
```
|
||||
|
||||
**ZXImportOption**(`LibrarySubpages.swift:93`)
|
||||
带大图标 + 标题描述的导入选项行。
|
||||
|
||||
**ZXProfileMenuRow**(`ProfileView.swift:58`)
|
||||
Profile 页菜单行,emoji + 标题 + 描述 + 箭头。
|
||||
|
||||
**ReviewTaskRow**(`ReviewPlanView.swift:82`)
|
||||
复习任务行,含完成勾选 + 复习类型标签 + 播放按钮。
|
||||
|
||||
**ZXAIInteractionRow**(`AIHomeView.swift:138`)
|
||||
AI 互动记录行,含标签 + 时间 + 分数。
|
||||
|
||||
### 7.4 数据展示
|
||||
|
||||
**ZXScoreBox**(`ContentView.swift:50`)
|
||||
36pt 方形分数格。
|
||||
```swift
|
||||
ZXScoreBox(score: 82, bg: .zxGreenBG(0.15), fg: .zxGreen)
|
||||
```
|
||||
|
||||
**ZXStatBadge**(`AnalysisHomeView.swift:74`)
|
||||
统计徽章,图标 + 数值 + 标签 + 趋势。
|
||||
|
||||
**ZXWeakRow**(`AnalysisHomeView.swift:91`)
|
||||
薄弱知识点行,分数 + 标题 + 库名 + 优先级。
|
||||
|
||||
**ZXAchievementBadge**(`ProfileView.swift:61`)
|
||||
成就徽章,emoji + 标签。
|
||||
|
||||
**ZXProfileStat**(`ProfileView.swift:55`)
|
||||
Profile 页三栏统计数字。
|
||||
|
||||
**ZXChartView**(`AnalysisHomeView.swift:117`)
|
||||
折线图(掌握度趋势)。
|
||||
|
||||
### 7.5 输入
|
||||
|
||||
**ZXAIInputBar**(`ContentView.swift:26`)
|
||||
AI 对话输入栏,含 sparkles 图标 + 文本框 + 麦克风 + 发送按钮。
|
||||
|
||||
### 7.6 标签
|
||||
|
||||
**ZXChip**(`LibrarySubpages.swift:74`)
|
||||
Capsule 标签,彩色文字 + 半透明底色。
|
||||
|
||||
**复习类型标签**(`ReviewTaskRow.swift:129`)
|
||||
4 种:间隔重复(紫) / 费曼(accent) / 回忆(橙) / 薄弱(黄)。
|
||||
|
||||
### 7.7 卡片装饰
|
||||
|
||||
**ZXQuickAction**(`AIHomeView.swift:132`)
|
||||
72pt 高快捷操作按钮,emoji + 文字。
|
||||
|
||||
**ZLibraryCard**(`LibraryHomeView.swift:32`)
|
||||
知识库卡片,顶部渐变色条 + emoji + 名称 + 进度 + 标签。
|
||||
|
||||
### 7.8 状态组件
|
||||
|
||||
**ZXLoadingView**(`Shared/Components/ZXLoadingView.swift`)
|
||||
全屏加载指示器,紫色 ProgressView + "加载中…" 文字。
|
||||
|
||||
**ZXShimmerList**(`Shared/Components/ZXLoadingView.swift`)
|
||||
骨架屏列表,传入 `count` 生成占位卡片。
|
||||
|
||||
**ZXErrorView**(`Shared/Components/ZXErrorView.swift`)
|
||||
全屏错误状态,黄色三角图标 + 消息 + 可选重试按钮。
|
||||
|
||||
**ZXErrorBanner**(`Shared/Components/ZXErrorView.swift`)
|
||||
内联错误横幅,黄色背景 + 消息 + 关闭按钮。
|
||||
|
||||
**ZXEmptyView**(`Shared/Components/ZXEmptyView.swift`)
|
||||
空状态视图,支持图标 + 标题 + 副标题 + 可选操作按钮。
|
||||
|
||||
### 7.9 其他
|
||||
|
||||
**FeatureRow**(`Shared/Components/FeatureRow.swift`)
|
||||
Welcome 页功能介绍行。
|
||||
|
||||
---
|
||||
|
||||
## 八、页面布局模式
|
||||
|
||||
### 8.1 主 Tab 页(有底部 TabBar)
|
||||
|
||||
```swift
|
||||
struct SomeHomeView: View {
|
||||
var body: some View {
|
||||
ZStack {
|
||||
ZXGradient.page.ignoresSafeArea() // ① 背景
|
||||
|
||||
VStack(spacing: 0) {
|
||||
// ② Header
|
||||
HStack {
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text("副标题").font(.system(size: 12)).foregroundColor(.zxF04)
|
||||
Text("主标题").font(.system(size: 22, weight: .heavy))
|
||||
.foregroundColor(.zxF0).tracking(-0.5)
|
||||
}
|
||||
Spacer()
|
||||
// 右侧按钮/状态
|
||||
}
|
||||
.padding(.horizontal, 20)
|
||||
.padding(.top, ZXSpacing.statusBarH + 16)
|
||||
.padding(.bottom, 12)
|
||||
|
||||
// ③ 可滚动内容
|
||||
ScrollView {
|
||||
VStack(spacing: 16) {
|
||||
// 卡片/列表...
|
||||
}
|
||||
.padding(.horizontal, 20)
|
||||
.padding(.bottom, 120) // 为 TabBar 留空间
|
||||
}
|
||||
.scrollIndicators(.hidden)
|
||||
}
|
||||
}
|
||||
.navigationBarHidden(true)
|
||||
.preferredColorScheme(.dark)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 8.2 子页面(有返回按钮,无 TabBar)
|
||||
|
||||
```swift
|
||||
struct SomeDetailPage: View {
|
||||
var body: some View {
|
||||
ZStack {
|
||||
Color.zxBg0.ignoresSafeArea() // 纯色(非渐变)
|
||||
|
||||
VStack(spacing: 0) {
|
||||
ZXBackHeader(title: "标题", subtitle: "副标题") {
|
||||
// 右侧按钮
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
VStack(spacing: 16) {
|
||||
// 内容
|
||||
}
|
||||
.padding(.horizontal, 20)
|
||||
.padding(.bottom, 80)
|
||||
}
|
||||
.scrollIndicators(.hidden)
|
||||
}
|
||||
}
|
||||
.navigationBarHidden(true)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 8.3 卡片通用写法
|
||||
|
||||
```swift
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
// 卡片内容
|
||||
}
|
||||
.padding(16)
|
||||
.background(Color.zxFill003) // 底色
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 16)
|
||||
.stroke(Color.zxBorder006, lineWidth: 1) // 边框
|
||||
)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 16)) // 裁剪
|
||||
```
|
||||
|
||||
渐变背景卡片把 `.background(Color.zxFill003)` 换成对应的 `ZXGradient.xxx`。
|
||||
|
||||
### 8.4 输入框通用写法
|
||||
|
||||
```swift
|
||||
TextField("占位文字", text: $text)
|
||||
.font(.system(size: 14))
|
||||
.tint(.zxPurple)
|
||||
.padding(.horizontal, 16)
|
||||
.frame(height: 52)
|
||||
.background(Color.zxFill004)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 14))
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 14)
|
||||
.stroke(Color.zxBorder008, lineWidth: 1)
|
||||
)
|
||||
```
|
||||
|
||||
### 8.5 状态标签(Capsule 形)
|
||||
|
||||
```swift
|
||||
Text("标签文字")
|
||||
.font(.system(size: 10, weight: .semibold))
|
||||
.foregroundColor(semanticColor)
|
||||
.padding(.horizontal, 8)
|
||||
.padding(.vertical, 2)
|
||||
.background(semanticColor.opacity(0.12))
|
||||
.clipShape(Capsule())
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 九、设计决策与约束
|
||||
|
||||
### 9.1 全局
|
||||
|
||||
- 强制深色模式:`.preferredColorScheme(.dark)`
|
||||
- 所有页面 `navigationBarHidden(true)`,使用自建导航
|
||||
- 禁止使用系统默认蓝色、默认圆角、默认间距
|
||||
|
||||
### 9.2 颜色
|
||||
|
||||
- 文字统一用 `#F0F0FF` 加透明度,不要用 `Color.white`
|
||||
- 不要直接写 `Color(hex: ...)` 内联,优先用现有 token;确需新色值先加 token
|
||||
- 语义色不要混用——紫色是品牌/AI,橙色是热度/连续,绿色是完成,黄色是警告
|
||||
|
||||
### 9.3 字体
|
||||
|
||||
- 不使用系统默认字体大小(如 `.title`、`.headline`),一律显式 `.system(size:weight:)`
|
||||
- 标题统一 tracking 负值(`-0.5` 或 `-0.4`)
|
||||
- 中文内容避免使用 `.bold` 以下的极细字体
|
||||
|
||||
### 9.4 布局
|
||||
|
||||
- 页面水平留白统一 `20pt`
|
||||
- 卡片间距 `12–20pt`
|
||||
- 内容区底部留白至少 `80pt`(子页面)或 `120pt`(有 TabBar)
|
||||
- 所有 ScrollView 隐藏指示器:`.scrollIndicators(.hidden)`
|
||||
|
||||
### 9.5 组件
|
||||
|
||||
- 优先复用第七节的共享组件,不要内联重复 UI
|
||||
- 新组件如通用性足够,应抽到 `Shared/` 目录
|
||||
|
||||
---
|
||||
|
||||
## 十、文件引用索引
|
||||
|
||||
| 规范项 | 定义文件 |
|
||||
|---|---|
|
||||
| 颜色/渐变/圆角/间距/尺寸/字体 | `Core/DesignSystem/DesignTokens.swift` |
|
||||
| ZXTabBar | `Shared/Components/ZXTabBar.swift` |
|
||||
| ZXIconBtn | `Shared/Components/ZXIconBtn.swift` |
|
||||
| ZXScoreBox | `Shared/Components/ZXScoreBox.swift` |
|
||||
| ZXAIInputBar | `Shared/Components/ZXAIInputBar.swift` |
|
||||
| ZXBackHeader | `Shared/Components/ZXBackHeader.swift` |
|
||||
| ZXOutlineBtn | `Shared/Components/ZXOutlineBtn.swift` |
|
||||
| ZXQuickAction | `Shared/Components/ZXQuickAction.swift` |
|
||||
| ZXAIInteractionRow | `Shared/Components/ZXAIInteractionRow.swift` |
|
||||
| ZXCardRow | `Shared/Components/ZXCardRow.swift` |
|
||||
| ZXChip | `Shared/Components/ZXChip.swift` |
|
||||
| ZXImportOption | `Shared/Components/ZXImportOption.swift` |
|
||||
| ZXWeakRow | `Shared/Components/ZXWeakRow.swift` |
|
||||
| ZXStatBadge | `Shared/Components/ZXStatBadge.swift` |
|
||||
| ZXProfileMenuRow | `Shared/Components/ZXProfileMenuRow.swift` |
|
||||
| ZXProfileStat | `Shared/Components/ZXProfileStat.swift` |
|
||||
| ZXAchievementBadge | `Shared/Components/ZXAchievementBadge.swift` |
|
||||
| ZXChartView | `Shared/Components/ZXChartView.swift` |
|
||||
| ZXSTaskRow + ZXSTask | `Shared/Components/ZXSTaskRow.swift` |
|
||||
| FeatureRow | `Shared/Components/FeatureRow.swift` |
|
||||
| ReviewTaskRow | `Shared/Components/ReviewTaskRow.swift` |
|
||||
| ZXLoadingView / ZXShimmerList | `Shared/Components/ZXLoadingView.swift` |
|
||||
| ZXErrorView / ZXErrorBanner | `Shared/Components/ZXErrorView.swift` |
|
||||
| ZXEmptyView | `Shared/Components/ZXEmptyView.swift` |
|
||||
| ZXLibraryCard | `Features/Library/LibraryHomeView.swift` |
|
||||
| AIHomeView | `Features/AI/AIHomeView.swift` |
|
||||
| DailyThinkingPage | `Features/AI/DailyThinkingPage.swift` |
|
||||
| RecallTestPage | `Features/AI/RecallTestPage.swift` |
|
||||
| WeakPointsPage | `Features/AI/WeakPointsPage.swift` |
|
||||
| AIFeedbackPageView | `Features/AI/AIFeedbackPage.swift` |
|
||||
| AIChatPage | `Features/AI/AIChatPage.swift` |
|
||||
| LibraryHomeView | `Features/Library/LibraryHomeView.swift` |
|
||||
| CreateLibraryPage | `Features/Library/CreateLibraryPage.swift` |
|
||||
| LibraryDetailPage | `Features/Library/LibraryDetailPage.swift` |
|
||||
| AddKnowledgePage | `Features/Library/AddKnowledgePage.swift` |
|
||||
| KnowledgeDetailPage | `Features/Library/KnowledgeDetailPage.swift` |
|
||||
| ImportPage | `Features/Library/ImportPage.swift` |
|
||||
| EditKnowledgePage | `Features/Library/EditKnowledgePage.swift` |
|
||||
| AnalysisHomeView | `Features/Analysis/AnalysisHomeView.swift` |
|
||||
| ProfileView | `Features/Profile/ProfileView.swift` |
|
||||
| ReviewPlanView | `Features/Review/ReviewPlanView.swift` |
|
||||
| StudyHomeView | `Features/Study/StudyHomeView.swift` |
|
||||
| SplashPage | `Features/Onboarding/SplashPage.swift` |
|
||||
| WelcomePage | `Features/Onboarding/WelcomePage.swift` |
|
||||
| OnboardingPage | `Features/Onboarding/OnboardingPage.swift` |
|
||||
| GoalSetupPage | `Features/Onboarding/GoalSetupPage.swift` |
|
||||
| AppRootView / OnboardingFlowView | `AIStudyAppApp.swift` |
|
||||
| LoginView | `Features/Auth/Views/LoginView.swift` |
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user