startup-plan/技术设计/ios-projects/已完成/[已完成]-样式规范.md
2026-05-15 17:29:57 +08:00

551 lines
18 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 知习 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` |