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