ios-projects/AIStudyApp/docs/样式规范.md

551 lines
18 KiB
Markdown
Raw Normal View History

# 知习 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 | 同 brandCTA 语义 |
| `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 间距 = 1220
ScrollView bottom = 120有 TabBar/ 80100子页面
```
---
## 五、尺寸
```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 个 tabAI / 知识库 / 学习 / 分析 / 我的),选中态紫色高亮 + 圆形背景扩散。
```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`
- 卡片间距 `1220pt`
- 内容区底部留白至少 `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` |