chore: rename Tiji→Kangkang test imports + scheme + sync docs
Rename @testable imports across all test/UI test files after the Tiji→Kangkang
project rename in 44ed01a. Add shared scheme. Sync CLAUDE.md / W2 plan / spec
v1.0 to current scope (Symptom feature noted, C1/C2 flow lockdown).
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
# 康记 / 体己 —— 工程前提
|
# 康康 —— 工程前提
|
||||||
|
|
||||||
> 这是一个 6 周决赛 demo 项目。今天是 2026-05-25,处于 W1末/W2初。
|
> 这是一个 6 周决赛 demo 项目。今天是 2026-05-25,处于 W1末/W2初。
|
||||||
> 任何 IDE/Claude 会话开始干活前,先读这份文件。
|
> 任何 IDE/Claude 会话开始干活前,先读这份文件。
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
## 1. 产品定位
|
## 1. 产品定位
|
||||||
|
|
||||||
- **名字**:康记(对内代号 体己 / Tiji)
|
- **名字**:康康(对内代号 Kangkang)
|
||||||
- **形态**:iOS 原生 App,SwiftUI + SwiftData
|
- **形态**:iOS 原生 App,SwiftUI + SwiftData
|
||||||
- **核心卖点**:**100% 本地推理**的个人健康影像档案 + 大白话解读 + 本地 RAG 问答
|
- **核心卖点**:**100% 本地推理**的个人健康影像档案 + 大白话解读 + 本地 RAG 问答
|
||||||
- **目标用户**:不愿把体检/化验报告交给云端的普通人
|
- **目标用户**:不愿把体检/化验报告交给云端的普通人
|
||||||
@@ -205,8 +205,8 @@ C2 解读 Tab 底部显示一段 diff 文本,**由 `ReportCompareService` 计算
|
|||||||
## 8. 现有代码状态(2026-05-25)
|
## 8. 现有代码状态(2026-05-25)
|
||||||
|
|
||||||
```
|
```
|
||||||
体己/
|
康康/
|
||||||
├── App/TijiApp.swift ✅ SwiftData container 已建
|
├── App/KangkangApp.swift ✅ SwiftData container 已建
|
||||||
├── RootView.swift ✅ 3 Tab + RecordSheet 已建
|
├── RootView.swift ✅ 3 Tab + RecordSheet 已建
|
||||||
├── Models/Models.swift ✅ Indicator / Report / DiaryEntry,缺 Asset / ChatTurn
|
├── Models/Models.swift ✅ Indicator / Report / DiaryEntry,缺 Asset / ChatTurn
|
||||||
├── DesignSystem/ ✅ Tokens + Components,沿用
|
├── DesignSystem/ ✅ Tokens + Components,沿用
|
||||||
|
|||||||
@@ -18,23 +18,23 @@
|
|||||||
|
|
||||||
| 路径 | 职责 |
|
| 路径 | 职责 |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `体己/AI/AIRuntime.swift` | actor 单例,推理串行化,暴露 prepare / generate / lastDecodeRate |
|
| `康康/AI/AIRuntime.swift` | actor 单例,推理串行化,暴露 prepare / generate / lastDecodeRate |
|
||||||
| `体己/AI/ModelStore.swift` | 模型路径管理 + bundle 旁路 |
|
| `康康/AI/ModelStore.swift` | 模型路径管理 + bundle 旁路 |
|
||||||
| `体己/AI/LLMSession.swift` | Qwen3-1.7B 加载 + 流式生成 |
|
| `康康/AI/LLMSession.swift` | Qwen3-1.7B 加载 + 流式生成 |
|
||||||
| `体己/AI/TokenChunk.swift` | 流式数据结构 |
|
| `康康/AI/TokenChunk.swift` | 流式数据结构 |
|
||||||
| `体己/Persistence/FileVault.swift` | `Application Support/Vault/` 加密目录读写 |
|
| `康康/Persistence/FileVault.swift` | `Application Support/Vault/` 加密目录读写 |
|
||||||
| `体己/Debug/DebugAIRunner.swift` | DEBUG-only 测试入口,挂在 MeView 末尾 |
|
| `康康/Debug/DebugAIRunner.swift` | DEBUG-only 测试入口,挂在 MeView 末尾 |
|
||||||
| `体己Tests/FileVaultTests.swift` | FileVault 单元测试 |
|
| `康康Tests/FileVaultTests.swift` | FileVault 单元测试 |
|
||||||
| `体己Tests/ModelStoreTests.swift` | ModelStore 单元测试 |
|
| `康康Tests/ModelStoreTests.swift` | ModelStore 单元测试 |
|
||||||
|
|
||||||
### 修改
|
### 修改
|
||||||
|
|
||||||
| 路径 | 改什么 |
|
| 路径 | 改什么 |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `体己/Models/Models.swift` | 加 Asset / ChatTurn,Indicator 加 report/asset/pinned,Report 加 indicators/assets 关系,DiaryEntry 加 tags |
|
| `康康/Models/Models.swift` | 加 Asset / ChatTurn,Indicator 加 report/asset/pinned,Report 加 indicators/assets 关系,DiaryEntry 加 tags |
|
||||||
| `体己/App/TijiApp.swift` | Schema 加入两个新 @Model |
|
| `康康/App/KangkangApp.swift` | Schema 加入两个新 @Model |
|
||||||
| `体己/Features/Me/MeView.swift` | DEBUG 块挂 DebugAIRunner |
|
| `康康/Features/Me/MeView.swift` | DEBUG 块挂 DebugAIRunner |
|
||||||
| `体己.xcodeproj` | SPM 加入 mlx-swift 与 mlx-swift-examples |
|
| `康康.xcodeproj` | SPM 加入 mlx-swift 与 mlx-swift-examples |
|
||||||
|
|
||||||
### 不动(W2 不碰)
|
### 不动(W2 不碰)
|
||||||
|
|
||||||
@@ -45,12 +45,12 @@
|
|||||||
## Task 1:Xcode 项目加入 MLX Swift SPM 依赖
|
## Task 1:Xcode 项目加入 MLX Swift SPM 依赖
|
||||||
|
|
||||||
**Files:**
|
**Files:**
|
||||||
- Modify: `体己.xcodeproj/project.pbxproj`(通过 Xcode UI 修改,不要手编)
|
- Modify: `康康.xcodeproj/project.pbxproj`(通过 Xcode UI 修改,不要手编)
|
||||||
|
|
||||||
- [ ] **Step 1:打开 Xcode 项目**
|
- [ ] **Step 1:打开 Xcode 项目**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
open /Users/xuhuayong/apps/体己/体己.xcodeproj
|
open /Users/xuhuayong/apps/康康/康康.xcodeproj
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2:加入 MLX Swift 依赖**
|
- [ ] **Step 2:加入 MLX Swift 依赖**
|
||||||
@@ -61,7 +61,7 @@ open /Users/xuhuayong/apps/体己/体己.xcodeproj
|
|||||||
https://github.com/ml-explore/mlx-swift
|
https://github.com/ml-explore/mlx-swift
|
||||||
```
|
```
|
||||||
|
|
||||||
选 "Up to Next Major" → 添加,勾选这些 product 加到 **体己** target:
|
选 "Up to Next Major" → 添加,勾选这些 product 加到 **康康** target:
|
||||||
- `MLX`
|
- `MLX`
|
||||||
- `MLXFast`
|
- `MLXFast`
|
||||||
- `MLXNN`
|
- `MLXNN`
|
||||||
@@ -76,13 +76,13 @@ https://github.com/ml-explore/mlx-swift
|
|||||||
https://github.com/ml-explore/mlx-swift-examples
|
https://github.com/ml-explore/mlx-swift-examples
|
||||||
```
|
```
|
||||||
|
|
||||||
勾选 `MLXLLM` 和 `MLXLMCommon` 加到 **体己** target。
|
勾选 `MLXLLM` 和 `MLXLMCommon` 加到 **康康** target。
|
||||||
|
|
||||||
- [ ] **Step 4:确认 Build Settings**
|
- [ ] **Step 4:确认 Build Settings**
|
||||||
|
|
||||||
Xcode → 体己 target → Build Settings → 搜 "Swift Language Version" → 确认 Swift 5(MLX 不支持 Swift 6 严格并发)。
|
Xcode → 康康 target → Build Settings → 搜 "Swift Language Version" → 确认 Swift 5(MLX 不支持 Swift 6 严格并发)。
|
||||||
|
|
||||||
体己 target → General → Minimum Deployments → iOS 17.0(MLX 要求)。
|
康康 target → General → Minimum Deployments → iOS 17.0(MLX 要求)。
|
||||||
|
|
||||||
- [ ] **Step 5:Build 验证**
|
- [ ] **Step 5:Build 验证**
|
||||||
|
|
||||||
@@ -93,8 +93,8 @@ Expected:Build Succeeded,无依赖错误。
|
|||||||
- [ ] **Step 6:提交**
|
- [ ] **Step 6:提交**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd /Users/xuhuayong/apps/体己
|
cd /Users/xuhuayong/apps/康康
|
||||||
git add 体己.xcodeproj
|
git add 康康.xcodeproj
|
||||||
git commit -m "build: add MLX Swift SPM dependencies"
|
git commit -m "build: add MLX Swift SPM dependencies"
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -103,11 +103,11 @@ git commit -m "build: add MLX Swift SPM dependencies"
|
|||||||
## Task 2:扩展 Models.swift —— Asset 与 ChatTurn
|
## Task 2:扩展 Models.swift —— Asset 与 ChatTurn
|
||||||
|
|
||||||
**Files:**
|
**Files:**
|
||||||
- Modify: `体己/Models/Models.swift`(全文重写)
|
- Modify: `康康/Models/Models.swift`(全文重写)
|
||||||
|
|
||||||
- [ ] **Step 1:把 Models.swift 替换为新内容**
|
- [ ] **Step 1:把 Models.swift 替换为新内容**
|
||||||
|
|
||||||
打开 `体己/Models/Models.swift`,**整文件替换**为:
|
打开 `康康/Models/Models.swift`,**整文件替换**为:
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
import Foundation
|
import Foundation
|
||||||
@@ -268,9 +268,9 @@ final class ChatTurn {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2:更新 TijiApp.swift Schema**
|
- [ ] **Step 2:更新 KangkangApp.swift Schema**
|
||||||
|
|
||||||
打开 `体己/App/TijiApp.swift`,替换 Schema 数组:
|
打开 `康康/App/KangkangApp.swift`,替换 Schema 数组:
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
let schema = Schema([
|
let schema = Schema([
|
||||||
@@ -302,7 +302,7 @@ Expected:App 启动到 RootView,无 fatalError。
|
|||||||
- [ ] **Step 5:提交**
|
- [ ] **Step 5:提交**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add 体己/Models/Models.swift 体己/App/TijiApp.swift
|
git add 康康/Models/Models.swift 康康/App/KangkangApp.swift
|
||||||
git commit -m "feat(models): add Asset/ChatTurn, indicator-report relationship, pinned flag"
|
git commit -m "feat(models): add Asset/ChatTurn, indicator-report relationship, pinned flag"
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -311,17 +311,17 @@ git commit -m "feat(models): add Asset/ChatTurn, indicator-report relationship,
|
|||||||
## Task 3:FileVault —— 加密目录读写(TDD)
|
## Task 3:FileVault —— 加密目录读写(TDD)
|
||||||
|
|
||||||
**Files:**
|
**Files:**
|
||||||
- Create: `体己/Persistence/FileVault.swift`
|
- Create: `康康/Persistence/FileVault.swift`
|
||||||
- Test: `体己Tests/FileVaultTests.swift`
|
- Test: `康康Tests/FileVaultTests.swift`
|
||||||
|
|
||||||
- [ ] **Step 1:写失败的测试**
|
- [ ] **Step 1:写失败的测试**
|
||||||
|
|
||||||
创建 `体己Tests/FileVaultTests.swift`:
|
创建 `康康Tests/FileVaultTests.swift`:
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
import Testing
|
import Testing
|
||||||
import UIKit
|
import UIKit
|
||||||
@testable import 体己
|
@testable import 康康
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
struct FileVaultTests {
|
struct FileVaultTests {
|
||||||
@@ -377,7 +377,7 @@ Expected:`FileVaultTests` 编译错误 "Cannot find 'FileVault' in scope"。
|
|||||||
|
|
||||||
- [ ] **Step 3:写最小 FileVault 实现**
|
- [ ] **Step 3:写最小 FileVault 实现**
|
||||||
|
|
||||||
创建 `体己/Persistence/FileVault.swift`:
|
创建 `康康/Persistence/FileVault.swift`:
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
import Foundation
|
import Foundation
|
||||||
@@ -454,11 +454,11 @@ final class FileVault {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 4:把 FileVault.swift 加入 体己 target**
|
- [ ] **Step 4:把 FileVault.swift 加入 康康 target**
|
||||||
|
|
||||||
Xcode 右键 `体己/` 目录 → New Group "Persistence" → 把 FileVault.swift 拖进去,确认 Target Membership 勾选 "体己"。
|
Xcode 右键 `康康/` 目录 → New Group "Persistence" → 把 FileVault.swift 拖进去,确认 Target Membership 勾选 "康康"。
|
||||||
|
|
||||||
把 FileVaultTests.swift 拖进 体己Tests target,确认 Target Membership 勾选 "体己Tests"。
|
把 FileVaultTests.swift 拖进 康康Tests target,确认 Target Membership 勾选 "康康Tests"。
|
||||||
|
|
||||||
- [ ] **Step 5:跑测试,确认全 pass**
|
- [ ] **Step 5:跑测试,确认全 pass**
|
||||||
|
|
||||||
@@ -469,7 +469,7 @@ Expected:`writeAndReadJPEGRoundtrip` / `removeMakesFileGone` / `wipeRemovesAllFi
|
|||||||
- [ ] **Step 6:提交**
|
- [ ] **Step 6:提交**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add 体己/Persistence/FileVault.swift 体己Tests/FileVaultTests.swift 体己.xcodeproj
|
git add 康康/Persistence/FileVault.swift 康康Tests/FileVaultTests.swift 康康.xcodeproj
|
||||||
git commit -m "feat(persistence): add FileVault with complete file protection"
|
git commit -m "feat(persistence): add FileVault with complete file protection"
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -478,17 +478,17 @@ git commit -m "feat(persistence): add FileVault with complete file protection"
|
|||||||
## Task 4:ModelStore —— 模型路径与 bundle 旁路(TDD)
|
## Task 4:ModelStore —— 模型路径与 bundle 旁路(TDD)
|
||||||
|
|
||||||
**Files:**
|
**Files:**
|
||||||
- Create: `体己/AI/ModelStore.swift`
|
- Create: `康康/AI/ModelStore.swift`
|
||||||
- Test: `体己Tests/ModelStoreTests.swift`
|
- Test: `康康Tests/ModelStoreTests.swift`
|
||||||
|
|
||||||
- [ ] **Step 1:写失败的测试**
|
- [ ] **Step 1:写失败的测试**
|
||||||
|
|
||||||
创建 `体己Tests/ModelStoreTests.swift`:
|
创建 `康康Tests/ModelStoreTests.swift`:
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
import Testing
|
import Testing
|
||||||
import Foundation
|
import Foundation
|
||||||
@testable import 体己
|
@testable import 康康
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
struct ModelStoreTests {
|
struct ModelStoreTests {
|
||||||
@@ -537,7 +537,7 @@ struct ModelStoreTests {
|
|||||||
|
|
||||||
- [ ] **Step 3:写 ModelStore 实现**
|
- [ ] **Step 3:写 ModelStore 实现**
|
||||||
|
|
||||||
创建 `体己/AI/ModelStore.swift`:
|
创建 `康康/AI/ModelStore.swift`:
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
import Foundation
|
import Foundation
|
||||||
@@ -621,8 +621,8 @@ final class ModelStore {
|
|||||||
|
|
||||||
- [ ] **Step 4:Xcode 中把文件加入 target**
|
- [ ] **Step 4:Xcode 中把文件加入 target**
|
||||||
|
|
||||||
右键 `体己/` → New Group "AI" → 拖入 ModelStore.swift,勾 "体己" target。
|
右键 `康康/` → New Group "AI" → 拖入 ModelStore.swift,勾 "康康" target。
|
||||||
ModelStoreTests.swift 拖入 体己Tests target。
|
ModelStoreTests.swift 拖入 康康Tests target。
|
||||||
|
|
||||||
- [ ] **Step 5:跑测试,全绿**
|
- [ ] **Step 5:跑测试,全绿**
|
||||||
|
|
||||||
@@ -633,7 +633,7 @@ Expected:3 个测试全 pass。
|
|||||||
- [ ] **Step 6:提交**
|
- [ ] **Step 6:提交**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add 体己/AI/ModelStore.swift 体己Tests/ModelStoreTests.swift 体己.xcodeproj
|
git add 康康/AI/ModelStore.swift 康康Tests/ModelStoreTests.swift 康康.xcodeproj
|
||||||
git commit -m "feat(ai): add ModelStore with path management and bundle seed"
|
git commit -m "feat(ai): add ModelStore with path management and bundle seed"
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -642,8 +642,8 @@ git commit -m "feat(ai): add ModelStore with path management and bundle seed"
|
|||||||
## Task 5:TokenChunk + AIRuntime actor 骨架
|
## Task 5:TokenChunk + AIRuntime actor 骨架
|
||||||
|
|
||||||
**Files:**
|
**Files:**
|
||||||
- Create: `体己/AI/TokenChunk.swift`
|
- Create: `康康/AI/TokenChunk.swift`
|
||||||
- Create: `体己/AI/AIRuntime.swift`
|
- Create: `康康/AI/AIRuntime.swift`
|
||||||
|
|
||||||
本任务**不接 MLX**,只搭骨架。Task 6 才接真模型。
|
本任务**不接 MLX**,只搭骨架。Task 6 才接真模型。
|
||||||
|
|
||||||
@@ -762,7 +762,7 @@ actor AIRuntime {
|
|||||||
|
|
||||||
- [ ] **Step 4:把文件加入 target**
|
- [ ] **Step 4:把文件加入 target**
|
||||||
|
|
||||||
把 TokenChunk.swift 和 AIRuntime.swift 拖进 AI group,勾 "体己" target。
|
把 TokenChunk.swift 和 AIRuntime.swift 拖进 AI group,勾 "康康" target。
|
||||||
|
|
||||||
(此时 Build 还是失败,正常)
|
(此时 Build 还是失败,正常)
|
||||||
|
|
||||||
@@ -775,7 +775,7 @@ actor AIRuntime {
|
|||||||
## Task 6:LLMSession —— 接 MLX 跑 Qwen3-1.7B
|
## Task 6:LLMSession —— 接 MLX 跑 Qwen3-1.7B
|
||||||
|
|
||||||
**Files:**
|
**Files:**
|
||||||
- Create: `体己/AI/LLMSession.swift`
|
- Create: `康康/AI/LLMSession.swift`
|
||||||
|
|
||||||
**预先准备(开发者手动一次)**:
|
**预先准备(开发者手动一次)**:
|
||||||
|
|
||||||
@@ -798,7 +798,7 @@ Expected:目录里有 `config.json` / `model.safetensors` / `tokenizer.json` 等
|
|||||||
|
|
||||||
- [ ] **Step 2:写 LLMSession 实现**
|
- [ ] **Step 2:写 LLMSession 实现**
|
||||||
|
|
||||||
创建 `体己/AI/LLMSession.swift`:
|
创建 `康康/AI/LLMSession.swift`:
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
import Foundation
|
import Foundation
|
||||||
@@ -866,7 +866,7 @@ actor LLMSession {
|
|||||||
|
|
||||||
> **注**:`MLXLMCommon` 的具体 API 版本可能在 GenerateParameters/stream 处略有差异。如果 Step 4 编译报错,查看 mlx-swift-examples 仓库 `Libraries/MLXLLM` 的最新示例,以仓库示例为准小幅调整。
|
> **注**:`MLXLMCommon` 的具体 API 版本可能在 GenerateParameters/stream 处略有差异。如果 Step 4 编译报错,查看 mlx-swift-examples 仓库 `Libraries/MLXLLM` 的最新示例,以仓库示例为准小幅调整。
|
||||||
|
|
||||||
- [ ] **Step 3:把 LLMSession.swift 加入 体己 target**
|
- [ ] **Step 3:把 LLMSession.swift 加入 康康 target**
|
||||||
|
|
||||||
拖入 AI group,确认 Target Membership。
|
拖入 AI group,确认 Target Membership。
|
||||||
|
|
||||||
@@ -878,9 +878,9 @@ Expected:Build Succeeded。
|
|||||||
|
|
||||||
若 MLX API 签名不匹配,参考 https://github.com/ml-explore/mlx-swift-examples 中 `Libraries/MLXLLM` 的最新 LLM 示例修正。
|
若 MLX API 签名不匹配,参考 https://github.com/ml-explore/mlx-swift-examples 中 `Libraries/MLXLLM` 的最新 LLM 示例修正。
|
||||||
|
|
||||||
- [ ] **Step 5:在 TijiApp 启动时打印沙盒路径(临时调试)**
|
- [ ] **Step 5:在 KangkangApp 启动时打印沙盒路径(临时调试)**
|
||||||
|
|
||||||
打开 `体己/App/TijiApp.swift`,在 `WindowGroup { RootView() }` 内加一个 `.onAppear`:
|
打开 `康康/App/KangkangApp.swift`,在 `WindowGroup { RootView() }` 内加一个 `.onAppear`:
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
.onAppear {
|
.onAppear {
|
||||||
@@ -912,7 +912,7 @@ cp -R ~/tiji-models/Qwen3-1.7B-MLX-4bit "$APP_SUPPORT/Models/"
|
|||||||
- [ ] **Step 7:提交(本任务 + Task 5 一起)**
|
- [ ] **Step 7:提交(本任务 + Task 5 一起)**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add 体己/AI/ 体己/App/TijiApp.swift 体己.xcodeproj
|
git add 康康/AI/ 康康/App/KangkangApp.swift 康康.xcodeproj
|
||||||
git commit -m "feat(ai): add AIRuntime actor and LLMSession with MLX Qwen3-1.7B"
|
git commit -m "feat(ai): add AIRuntime actor and LLMSession with MLX Qwen3-1.7B"
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -921,12 +921,12 @@ git commit -m "feat(ai): add AIRuntime actor and LLMSession with MLX Qwen3-1.7B"
|
|||||||
## Task 7:DebugAIRunner —— DEBUG 测试入口
|
## Task 7:DebugAIRunner —— DEBUG 测试入口
|
||||||
|
|
||||||
**Files:**
|
**Files:**
|
||||||
- Create: `体己/Debug/DebugAIRunner.swift`
|
- Create: `康康/Debug/DebugAIRunner.swift`
|
||||||
- Modify: `体己/Features/Me/MeView.swift`
|
- Modify: `康康/Features/Me/MeView.swift`
|
||||||
|
|
||||||
- [ ] **Step 1:创建 DebugAIRunner**
|
- [ ] **Step 1:创建 DebugAIRunner**
|
||||||
|
|
||||||
`体己/Debug/DebugAIRunner.swift`:
|
`康康/Debug/DebugAIRunner.swift`:
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
@@ -1000,7 +1000,7 @@ struct DebugAIRunner: View {
|
|||||||
|
|
||||||
- [ ] **Step 2:在 MeView 末尾挂上(仅 DEBUG)**
|
- [ ] **Step 2:在 MeView 末尾挂上(仅 DEBUG)**
|
||||||
|
|
||||||
打开 `体己/Features/Me/MeView.swift`,把现有内容整体替换为:
|
打开 `康康/Features/Me/MeView.swift`,把现有内容整体替换为:
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
@@ -1027,7 +1027,7 @@ struct MeView: View {
|
|||||||
|
|
||||||
- [ ] **Step 3:在 Xcode 中加入文件**
|
- [ ] **Step 3:在 Xcode 中加入文件**
|
||||||
|
|
||||||
右键 `体己/` → New Group "Debug" → 拖入 DebugAIRunner.swift,勾 "体己" target。
|
右键 `康康/` → New Group "Debug" → 拖入 DebugAIRunner.swift,勾 "康康" target。
|
||||||
|
|
||||||
- [ ] **Step 4:Build,确认 OK**
|
- [ ] **Step 4:Build,确认 OK**
|
||||||
|
|
||||||
@@ -1036,7 +1036,7 @@ struct MeView: View {
|
|||||||
- [ ] **Step 5:提交**
|
- [ ] **Step 5:提交**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add 体己/Debug/ 体己/Features/Me/MeView.swift 体己.xcodeproj
|
git add 康康/Debug/ 康康/Features/Me/MeView.swift 康康.xcodeproj
|
||||||
git commit -m "chore(debug): add AI self-test runner in MeView (DEBUG only)"
|
git commit -m "chore(debug): add AI self-test runner in MeView (DEBUG only)"
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -1092,7 +1092,7 @@ git commit --allow-empty -m "milestone: W2 LLM 自检通过 (simulator)"
|
|||||||
## Task 9:加一组 schema 重建烟测(防回归)
|
## Task 9:加一组 schema 重建烟测(防回归)
|
||||||
|
|
||||||
**Files:**
|
**Files:**
|
||||||
- Create: `体己Tests/ModelsSchemaTests.swift`
|
- Create: `康康Tests/ModelsSchemaTests.swift`
|
||||||
|
|
||||||
- [ ] **Step 1:写 schema 烟测**
|
- [ ] **Step 1:写 schema 烟测**
|
||||||
|
|
||||||
@@ -1100,7 +1100,7 @@ git commit --allow-empty -m "milestone: W2 LLM 自检通过 (simulator)"
|
|||||||
import Testing
|
import Testing
|
||||||
import SwiftData
|
import SwiftData
|
||||||
import Foundation
|
import Foundation
|
||||||
@testable import 体己
|
@testable import 康康
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
struct ModelsSchemaTests {
|
struct ModelsSchemaTests {
|
||||||
@@ -1179,7 +1179,7 @@ struct ModelsSchemaTests {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] **Step 2:加入 体己Tests target,跑测试**
|
- [ ] **Step 2:加入 康康Tests target,跑测试**
|
||||||
|
|
||||||
⌘U。
|
⌘U。
|
||||||
|
|
||||||
@@ -1190,7 +1190,7 @@ Expected:3 个测试全 pass。
|
|||||||
- [ ] **Step 3:提交**
|
- [ ] **Step 3:提交**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add 体己Tests/ModelsSchemaTests.swift 体己.xcodeproj
|
git add 康康Tests/ModelsSchemaTests.swift 康康.xcodeproj
|
||||||
git commit -m "test(models): add schema smoke tests for relationships and cascade"
|
git commit -m "test(models): add schema smoke tests for relationships and cascade"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# 康记 / 体己 —— 功能设计 Spec(v1.0)
|
# 康康 —— 功能设计 Spec(v1.0)
|
||||||
|
|
||||||
**日期**:2026-05-25
|
**日期**:2026-05-25
|
||||||
**状态**:Draft, 已与产品方对齐 §1-§6
|
**状态**:Draft, 已与产品方对齐 §1-§6
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
## 0. 概要
|
## 0. 概要
|
||||||
|
|
||||||
康记是一个 iOS 原生健康影像档案 App,**100% 端侧 AI 推理**,基于 SwiftUI + SwiftData + MLX Swift,目标 6 周交付决赛 demo。本 spec 把原始功能清单收敛为 **方案 B**:核心 5 模块 + Live Activity + 分享摘要,其余 P2/P3 全部 deferred。
|
康康是一个 iOS 原生健康影像档案 App,**100% 端侧 AI 推理**,基于 SwiftUI + SwiftData + MLX Swift,目标 6 周交付决赛 demo。本 spec 把原始功能清单收敛为 **方案 B**:核心 5 模块 + Live Activity + 分享摘要,其余 P2/P3 全部 deferred。
|
||||||
|
|
||||||
**5 大核心模块**
|
**5 大核心模块**
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ Persistence
|
|||||||
### 2.1 `AIRuntime` 接口
|
### 2.1 `AIRuntime` 接口
|
||||||
|
|
||||||
```
|
```
|
||||||
体己/AI/
|
康康/AI/
|
||||||
├── AIRuntime.swift // actor 单例,推理串行化
|
├── AIRuntime.swift // actor 单例,推理串行化
|
||||||
├── ModelStore.swift // 模型路径管理 + 下载 + bundle 旁路
|
├── ModelStore.swift // 模型路径管理 + 下载 + bundle 旁路
|
||||||
├── LLMSession.swift // Qwen3-1.7B 文本生成,流式
|
├── LLMSession.swift // Qwen3-1.7B 文本生成,流式
|
||||||
@@ -376,7 +376,7 @@ User → UI(B2Scan) → CaptureService → AIRuntime → Persistence
|
|||||||
### 4.3 服务层文件
|
### 4.3 服务层文件
|
||||||
|
|
||||||
```
|
```
|
||||||
体己/AI/ [7.5d]
|
康康/AI/ [7.5d]
|
||||||
├── AIRuntime.swift 2d
|
├── AIRuntime.swift 2d
|
||||||
├── ModelStore.swift 1d
|
├── ModelStore.swift 1d
|
||||||
├── LLMSession.swift 1d
|
├── LLMSession.swift 1d
|
||||||
@@ -387,17 +387,17 @@ User → UI(B2Scan) → CaptureService → AIRuntime → Persistence
|
|||||||
├── KeywordExtraction.swift
|
├── KeywordExtraction.swift
|
||||||
└── TrendNarrative.swift
|
└── TrendNarrative.swift
|
||||||
|
|
||||||
体己/Services/ [4.5d]
|
康康/Services/ [4.5d]
|
||||||
├── CaptureService.swift 1.5d
|
├── CaptureService.swift 1.5d
|
||||||
├── AskService.swift 1.5d
|
├── AskService.swift 1.5d
|
||||||
├── TrendService.swift 1d
|
├── TrendService.swift 1d
|
||||||
└── ReportCompareService.swift 0.5d
|
└── ReportCompareService.swift 0.5d
|
||||||
|
|
||||||
体己/Persistence/ [1d]
|
康康/Persistence/ [1d]
|
||||||
├── FileVault.swift 0.5d
|
├── FileVault.swift 0.5d
|
||||||
└── PermanentDelete.swift 0.5d
|
└── PermanentDelete.swift 0.5d
|
||||||
|
|
||||||
体己/Security/ [0.5d]
|
康康/Security/ [0.5d]
|
||||||
└── AppLock.swift 0.5d
|
└── AppLock.swift 0.5d
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -17,37 +17,37 @@
|
|||||||
containerPortal = 5E463CF12FC403BB0089145B /* Project object */;
|
containerPortal = 5E463CF12FC403BB0089145B /* Project object */;
|
||||||
proxyType = 1;
|
proxyType = 1;
|
||||||
remoteGlobalIDString = 5E463CF82FC403BB0089145B;
|
remoteGlobalIDString = 5E463CF82FC403BB0089145B;
|
||||||
remoteInfo = "体己";
|
remoteInfo = "康康";
|
||||||
};
|
};
|
||||||
5E463D132FC403BC0089145B /* PBXContainerItemProxy */ = {
|
5E463D132FC403BC0089145B /* PBXContainerItemProxy */ = {
|
||||||
isa = PBXContainerItemProxy;
|
isa = PBXContainerItemProxy;
|
||||||
containerPortal = 5E463CF12FC403BB0089145B /* Project object */;
|
containerPortal = 5E463CF12FC403BB0089145B /* Project object */;
|
||||||
proxyType = 1;
|
proxyType = 1;
|
||||||
remoteGlobalIDString = 5E463CF82FC403BB0089145B;
|
remoteGlobalIDString = 5E463CF82FC403BB0089145B;
|
||||||
remoteInfo = "体己";
|
remoteInfo = "康康";
|
||||||
};
|
};
|
||||||
/* End PBXContainerItemProxy section */
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
5E463CF92FC403BB0089145B /* 体己.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "体己.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
5E463CF92FC403BB0089145B /* 康康.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "康康.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
5E463D082FC403BC0089145B /* 体己Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "体己Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
5E463D082FC403BC0089145B /* 康康Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "康康Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
5E463D122FC403BC0089145B /* 体己UITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "体己UITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
5E463D122FC403BC0089145B /* 康康UITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "康康UITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
||||||
5E463CFB2FC403BB0089145B /* 体己 */ = {
|
5E463CFB2FC403BB0089145B /* 康康 */ = {
|
||||||
isa = PBXFileSystemSynchronizedRootGroup;
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
path = "体己";
|
path = "康康";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
5E463D0B2FC403BC0089145B /* 体己Tests */ = {
|
5E463D0B2FC403BC0089145B /* 康康Tests */ = {
|
||||||
isa = PBXFileSystemSynchronizedRootGroup;
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
path = "体己Tests";
|
path = "康康Tests";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
5E463D152FC403BC0089145B /* 体己UITests */ = {
|
5E463D152FC403BC0089145B /* 康康UITests */ = {
|
||||||
isa = PBXFileSystemSynchronizedRootGroup;
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
path = "体己UITests";
|
path = "康康UITests";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
/* End PBXFileSystemSynchronizedRootGroup section */
|
/* End PBXFileSystemSynchronizedRootGroup section */
|
||||||
@@ -82,9 +82,9 @@
|
|||||||
5E463CF02FC403BB0089145B = {
|
5E463CF02FC403BB0089145B = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
5E463CFB2FC403BB0089145B /* 体己 */,
|
5E463CFB2FC403BB0089145B /* 康康 */,
|
||||||
5E463D0B2FC403BC0089145B /* 体己Tests */,
|
5E463D0B2FC403BC0089145B /* 康康Tests */,
|
||||||
5E463D152FC403BC0089145B /* 体己UITests */,
|
5E463D152FC403BC0089145B /* 康康UITests */,
|
||||||
5E463CFA2FC403BB0089145B /* Products */,
|
5E463CFA2FC403BB0089145B /* Products */,
|
||||||
);
|
);
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -92,9 +92,9 @@
|
|||||||
5E463CFA2FC403BB0089145B /* Products */ = {
|
5E463CFA2FC403BB0089145B /* Products */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
5E463CF92FC403BB0089145B /* 体己.app */,
|
5E463CF92FC403BB0089145B /* 康康.app */,
|
||||||
5E463D082FC403BC0089145B /* 体己Tests.xctest */,
|
5E463D082FC403BC0089145B /* 康康Tests.xctest */,
|
||||||
5E463D122FC403BC0089145B /* 体己UITests.xctest */,
|
5E463D122FC403BC0089145B /* 康康UITests.xctest */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -102,9 +102,9 @@
|
|||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
5E463CF82FC403BB0089145B /* 体己 */ = {
|
5E463CF82FC403BB0089145B /* 康康 */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 5E463D1C2FC403BC0089145B /* Build configuration list for PBXNativeTarget "体己" */;
|
buildConfigurationList = 5E463D1C2FC403BC0089145B /* Build configuration list for PBXNativeTarget "康康" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
5E463CF52FC403BB0089145B /* Sources */,
|
5E463CF52FC403BB0089145B /* Sources */,
|
||||||
5E463CF62FC403BB0089145B /* Frameworks */,
|
5E463CF62FC403BB0089145B /* Frameworks */,
|
||||||
@@ -115,20 +115,20 @@
|
|||||||
dependencies = (
|
dependencies = (
|
||||||
);
|
);
|
||||||
fileSystemSynchronizedGroups = (
|
fileSystemSynchronizedGroups = (
|
||||||
5E463CFB2FC403BB0089145B /* 体己 */,
|
5E463CFB2FC403BB0089145B /* 康康 */,
|
||||||
);
|
);
|
||||||
name = "体己";
|
name = "康康";
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
FEED000000000000DEAD0003 /* MLXLLM */,
|
FEED000000000000DEAD0003 /* MLXLLM */,
|
||||||
FEED000000000000DEAD0004 /* MLXLMCommon */,
|
FEED000000000000DEAD0004 /* MLXLMCommon */,
|
||||||
);
|
);
|
||||||
productName = "体己";
|
productName = "康康";
|
||||||
productReference = 5E463CF92FC403BB0089145B /* 体己.app */;
|
productReference = 5E463CF92FC403BB0089145B /* 康康.app */;
|
||||||
productType = "com.apple.product-type.application";
|
productType = "com.apple.product-type.application";
|
||||||
};
|
};
|
||||||
5E463D072FC403BC0089145B /* 体己Tests */ = {
|
5E463D072FC403BC0089145B /* 康康Tests */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 5E463D1F2FC403BC0089145B /* Build configuration list for PBXNativeTarget "体己Tests" */;
|
buildConfigurationList = 5E463D1F2FC403BC0089145B /* Build configuration list for PBXNativeTarget "康康Tests" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
5E463D042FC403BC0089145B /* Sources */,
|
5E463D042FC403BC0089145B /* Sources */,
|
||||||
5E463D052FC403BC0089145B /* Frameworks */,
|
5E463D052FC403BC0089145B /* Frameworks */,
|
||||||
@@ -140,18 +140,18 @@
|
|||||||
5E463D0A2FC403BC0089145B /* PBXTargetDependency */,
|
5E463D0A2FC403BC0089145B /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
fileSystemSynchronizedGroups = (
|
fileSystemSynchronizedGroups = (
|
||||||
5E463D0B2FC403BC0089145B /* 体己Tests */,
|
5E463D0B2FC403BC0089145B /* 康康Tests */,
|
||||||
);
|
);
|
||||||
name = "体己Tests";
|
name = "康康Tests";
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
);
|
);
|
||||||
productName = "体己Tests";
|
productName = "康康Tests";
|
||||||
productReference = 5E463D082FC403BC0089145B /* 体己Tests.xctest */;
|
productReference = 5E463D082FC403BC0089145B /* 康康Tests.xctest */;
|
||||||
productType = "com.apple.product-type.bundle.unit-test";
|
productType = "com.apple.product-type.bundle.unit-test";
|
||||||
};
|
};
|
||||||
5E463D112FC403BC0089145B /* 体己UITests */ = {
|
5E463D112FC403BC0089145B /* 康康UITests */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 5E463D222FC403BC0089145B /* Build configuration list for PBXNativeTarget "体己UITests" */;
|
buildConfigurationList = 5E463D222FC403BC0089145B /* Build configuration list for PBXNativeTarget "康康UITests" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
5E463D0E2FC403BC0089145B /* Sources */,
|
5E463D0E2FC403BC0089145B /* Sources */,
|
||||||
5E463D0F2FC403BC0089145B /* Frameworks */,
|
5E463D0F2FC403BC0089145B /* Frameworks */,
|
||||||
@@ -163,13 +163,13 @@
|
|||||||
5E463D142FC403BC0089145B /* PBXTargetDependency */,
|
5E463D142FC403BC0089145B /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
fileSystemSynchronizedGroups = (
|
fileSystemSynchronizedGroups = (
|
||||||
5E463D152FC403BC0089145B /* 体己UITests */,
|
5E463D152FC403BC0089145B /* 康康UITests */,
|
||||||
);
|
);
|
||||||
name = "体己UITests";
|
name = "康康UITests";
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
);
|
);
|
||||||
productName = "体己UITests";
|
productName = "康康UITests";
|
||||||
productReference = 5E463D122FC403BC0089145B /* 体己UITests.xctest */;
|
productReference = 5E463D122FC403BC0089145B /* 康康UITests.xctest */;
|
||||||
productType = "com.apple.product-type.bundle.ui-testing";
|
productType = "com.apple.product-type.bundle.ui-testing";
|
||||||
};
|
};
|
||||||
/* End PBXNativeTarget section */
|
/* End PBXNativeTarget section */
|
||||||
@@ -195,7 +195,7 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
buildConfigurationList = 5E463CF42FC403BB0089145B /* Build configuration list for PBXProject "体己" */;
|
buildConfigurationList = 5E463CF42FC403BB0089145B /* Build configuration list for PBXProject "康康" */;
|
||||||
developmentRegion = en;
|
developmentRegion = en;
|
||||||
hasScannedForEncodings = 0;
|
hasScannedForEncodings = 0;
|
||||||
knownRegions = (
|
knownRegions = (
|
||||||
@@ -212,9 +212,9 @@
|
|||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
projectRoot = "";
|
projectRoot = "";
|
||||||
targets = (
|
targets = (
|
||||||
5E463CF82FC403BB0089145B /* 体己 */,
|
5E463CF82FC403BB0089145B /* 康康 */,
|
||||||
5E463D072FC403BC0089145B /* 体己Tests */,
|
5E463D072FC403BC0089145B /* 康康Tests */,
|
||||||
5E463D112FC403BC0089145B /* 体己UITests */,
|
5E463D112FC403BC0089145B /* 康康UITests */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
@@ -270,12 +270,12 @@
|
|||||||
/* Begin PBXTargetDependency section */
|
/* Begin PBXTargetDependency section */
|
||||||
5E463D0A2FC403BC0089145B /* PBXTargetDependency */ = {
|
5E463D0A2FC403BC0089145B /* PBXTargetDependency */ = {
|
||||||
isa = PBXTargetDependency;
|
isa = PBXTargetDependency;
|
||||||
target = 5E463CF82FC403BB0089145B /* 体己 */;
|
target = 5E463CF82FC403BB0089145B /* 康康 */;
|
||||||
targetProxy = 5E463D092FC403BC0089145B /* PBXContainerItemProxy */;
|
targetProxy = 5E463D092FC403BC0089145B /* PBXContainerItemProxy */;
|
||||||
};
|
};
|
||||||
5E463D142FC403BC0089145B /* PBXTargetDependency */ = {
|
5E463D142FC403BC0089145B /* PBXTargetDependency */ = {
|
||||||
isa = PBXTargetDependency;
|
isa = PBXTargetDependency;
|
||||||
target = 5E463CF82FC403BB0089145B /* 体己 */;
|
target = 5E463CF82FC403BB0089145B /* 康康 */;
|
||||||
targetProxy = 5E463D132FC403BC0089145B /* PBXContainerItemProxy */;
|
targetProxy = 5E463D132FC403BC0089145B /* PBXContainerItemProxy */;
|
||||||
};
|
};
|
||||||
/* End PBXTargetDependency section */
|
/* End PBXTargetDependency section */
|
||||||
@@ -425,7 +425,7 @@
|
|||||||
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
|
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
|
||||||
MACOSX_DEPLOYMENT_TARGET = 26.0;
|
MACOSX_DEPLOYMENT_TARGET = 26.0;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "tiji.--";
|
PRODUCT_BUNDLE_IDENTIFIER = "kangkang.--";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
REGISTER_APP_GROUPS = YES;
|
REGISTER_APP_GROUPS = YES;
|
||||||
SDKROOT = auto;
|
SDKROOT = auto;
|
||||||
@@ -470,7 +470,7 @@
|
|||||||
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
|
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
|
||||||
MACOSX_DEPLOYMENT_TARGET = 26.0;
|
MACOSX_DEPLOYMENT_TARGET = 26.0;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "tiji.--";
|
PRODUCT_BUNDLE_IDENTIFIER = "kangkang.--";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
REGISTER_APP_GROUPS = YES;
|
REGISTER_APP_GROUPS = YES;
|
||||||
SDKROOT = auto;
|
SDKROOT = auto;
|
||||||
@@ -498,7 +498,7 @@
|
|||||||
IPHONEOS_DEPLOYMENT_TARGET = 26.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 26.0;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 26.0;
|
MACOSX_DEPLOYMENT_TARGET = 26.0;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "tiji.--Tests";
|
PRODUCT_BUNDLE_IDENTIFIER = "kangkang.--Tests";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SDKROOT = auto;
|
SDKROOT = auto;
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
||||||
@@ -509,7 +509,7 @@
|
|||||||
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2,7";
|
TARGETED_DEVICE_FAMILY = "1,2,7";
|
||||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/体己.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/体己";
|
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/康康.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/康康";
|
||||||
XROS_DEPLOYMENT_TARGET = 26.0;
|
XROS_DEPLOYMENT_TARGET = 26.0;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
@@ -525,7 +525,7 @@
|
|||||||
IPHONEOS_DEPLOYMENT_TARGET = 26.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 26.0;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 26.0;
|
MACOSX_DEPLOYMENT_TARGET = 26.0;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "tiji.--Tests";
|
PRODUCT_BUNDLE_IDENTIFIER = "kangkang.--Tests";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SDKROOT = auto;
|
SDKROOT = auto;
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
||||||
@@ -536,7 +536,7 @@
|
|||||||
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2,7";
|
TARGETED_DEVICE_FAMILY = "1,2,7";
|
||||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/体己.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/体己";
|
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/康康.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/康康";
|
||||||
XROS_DEPLOYMENT_TARGET = 26.0;
|
XROS_DEPLOYMENT_TARGET = 26.0;
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
@@ -551,7 +551,7 @@
|
|||||||
IPHONEOS_DEPLOYMENT_TARGET = 26.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 26.0;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 26.0;
|
MACOSX_DEPLOYMENT_TARGET = 26.0;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "tiji.--UITests";
|
PRODUCT_BUNDLE_IDENTIFIER = "kangkang.--UITests";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SDKROOT = auto;
|
SDKROOT = auto;
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
||||||
@@ -562,7 +562,7 @@
|
|||||||
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2,7";
|
TARGETED_DEVICE_FAMILY = "1,2,7";
|
||||||
TEST_TARGET_NAME = "体己";
|
TEST_TARGET_NAME = "康康";
|
||||||
XROS_DEPLOYMENT_TARGET = 26.0;
|
XROS_DEPLOYMENT_TARGET = 26.0;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
@@ -577,7 +577,7 @@
|
|||||||
IPHONEOS_DEPLOYMENT_TARGET = 26.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 26.0;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 26.0;
|
MACOSX_DEPLOYMENT_TARGET = 26.0;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "tiji.--UITests";
|
PRODUCT_BUNDLE_IDENTIFIER = "kangkang.--UITests";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SDKROOT = auto;
|
SDKROOT = auto;
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
STRING_CATALOG_GENERATE_SYMBOLS = NO;
|
||||||
@@ -588,7 +588,7 @@
|
|||||||
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2,7";
|
TARGETED_DEVICE_FAMILY = "1,2,7";
|
||||||
TEST_TARGET_NAME = "体己";
|
TEST_TARGET_NAME = "康康";
|
||||||
XROS_DEPLOYMENT_TARGET = 26.0;
|
XROS_DEPLOYMENT_TARGET = 26.0;
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
@@ -596,7 +596,7 @@
|
|||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
5E463CF42FC403BB0089145B /* Build configuration list for PBXProject "体己" */ = {
|
5E463CF42FC403BB0089145B /* Build configuration list for PBXProject "康康" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
5E463D1A2FC403BC0089145B /* Debug */,
|
5E463D1A2FC403BC0089145B /* Debug */,
|
||||||
@@ -605,7 +605,7 @@
|
|||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
5E463D1C2FC403BC0089145B /* Build configuration list for PBXNativeTarget "体己" */ = {
|
5E463D1C2FC403BC0089145B /* Build configuration list for PBXNativeTarget "康康" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
5E463D1D2FC403BC0089145B /* Debug */,
|
5E463D1D2FC403BC0089145B /* Debug */,
|
||||||
@@ -614,7 +614,7 @@
|
|||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
5E463D1F2FC403BC0089145B /* Build configuration list for PBXNativeTarget "体己Tests" */ = {
|
5E463D1F2FC403BC0089145B /* Build configuration list for PBXNativeTarget "康康Tests" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
5E463D202FC403BC0089145B /* Debug */,
|
5E463D202FC403BC0089145B /* Debug */,
|
||||||
@@ -623,7 +623,7 @@
|
|||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
5E463D222FC403BC0089145B /* Build configuration list for PBXNativeTarget "体己UITests" */ = {
|
5E463D222FC403BC0089145B /* Build configuration list for PBXNativeTarget "康康UITests" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
5E463D232FC403BC0089145B /* Debug */,
|
5E463D232FC403BC0089145B /* Debug */,
|
||||||
|
|||||||
102
康康.xcodeproj/xcshareddata/xcschemes/康康.xcscheme
Normal file
102
康康.xcodeproj/xcshareddata/xcschemes/康康.xcscheme
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "2600"
|
||||||
|
version = "1.7">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES"
|
||||||
|
buildArchitectures = "Automatic">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "5E463CF82FC403BB0089145B"
|
||||||
|
BuildableName = "康康.app"
|
||||||
|
BlueprintName = "康康"
|
||||||
|
ReferencedContainer = "container:康康.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
shouldAutocreateTestPlan = "YES">
|
||||||
|
<Testables>
|
||||||
|
<TestableReference
|
||||||
|
skipped = "NO"
|
||||||
|
parallelizable = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "5E463D072FC403BC0089145B"
|
||||||
|
BuildableName = "康康Tests.xctest"
|
||||||
|
BlueprintName = "康康Tests"
|
||||||
|
ReferencedContainer = "container:康康.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</TestableReference>
|
||||||
|
<TestableReference
|
||||||
|
skipped = "NO"
|
||||||
|
parallelizable = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "5E463D112FC403BC0089145B"
|
||||||
|
BuildableName = "康康UITests.xctest"
|
||||||
|
BlueprintName = "康康UITests"
|
||||||
|
ReferencedContainer = "container:康康.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</TestableReference>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "5E463CF82FC403BB0089145B"
|
||||||
|
BuildableName = "康康.app"
|
||||||
|
BlueprintName = "康康"
|
||||||
|
ReferencedContainer = "container:康康.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "5E463CF82FC403BB0089145B"
|
||||||
|
BuildableName = "康康.app"
|
||||||
|
BlueprintName = "康康"
|
||||||
|
ReferencedContainer = "container:康康.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
@@ -4,11 +4,29 @@
|
|||||||
<dict>
|
<dict>
|
||||||
<key>SchemeUserState</key>
|
<key>SchemeUserState</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>体己.xcscheme_^#shared#^_</key>
|
<key>康康.xcscheme_^#shared#^_</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>orderHint</key>
|
<key>orderHint</key>
|
||||||
<integer>0</integer>
|
<integer>0</integer>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
|
<key>SuppressBuildableAutocreation</key>
|
||||||
|
<dict>
|
||||||
|
<key>5E463CF82FC403BB0089145B</key>
|
||||||
|
<dict>
|
||||||
|
<key>primary</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>5E463D072FC403BC0089145B</key>
|
||||||
|
<dict>
|
||||||
|
<key>primary</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>5E463D112FC403BC0089145B</key>
|
||||||
|
<dict>
|
||||||
|
<key>primary</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import SwiftUI
|
|||||||
import SwiftData
|
import SwiftData
|
||||||
|
|
||||||
@main
|
@main
|
||||||
struct TijiApp: App {
|
struct KangkangApp: App {
|
||||||
var sharedModelContainer: ModelContainer = {
|
var sharedModelContainer: ModelContainer = {
|
||||||
let schema = Schema([
|
let schema = Schema([
|
||||||
Indicator.self,
|
Indicator.self,
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ struct B1GuideView: View {
|
|||||||
.font(.system(size: 12))
|
.font(.system(size: 12))
|
||||||
.foregroundStyle(Tj.Palette.text2)
|
.foregroundStyle(Tj.Palette.text2)
|
||||||
.padding(.top, 2)
|
.padding(.top, 2)
|
||||||
Text("所有照片以 AES 加密存于本机沙盒。Tiji 服务端无法访问。")
|
Text("所有照片以 AES 加密存于本机沙盒。康康 服务端无法访问。")
|
||||||
.font(.system(size: 11))
|
.font(.system(size: 11))
|
||||||
.foregroundStyle(Tj.Palette.text2)
|
.foregroundStyle(Tj.Palette.text2)
|
||||||
.lineSpacing(4)
|
.lineSpacing(4)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Testing
|
import Testing
|
||||||
import UIKit
|
import UIKit
|
||||||
@testable import 体己
|
@testable import 康康
|
||||||
|
|
||||||
struct FileVaultTests {
|
struct FileVaultTests {
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Testing
|
import Testing
|
||||||
import Foundation
|
import Foundation
|
||||||
@testable import 体己
|
@testable import 康康
|
||||||
|
|
||||||
struct ModelStoreTests {
|
struct ModelStoreTests {
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import Testing
|
import Testing
|
||||||
import SwiftData
|
import SwiftData
|
||||||
import Foundation
|
import Foundation
|
||||||
@testable import 体己
|
@testable import 康康
|
||||||
|
|
||||||
struct ModelsSchemaTests {
|
struct ModelsSchemaTests {
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// __Tests.swift
|
// __Tests.swift
|
||||||
// 体己Tests
|
// 康康Tests
|
||||||
//
|
//
|
||||||
// Created by Tim on 2026/5/25.
|
// Created by Tim on 2026/5/25.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// __UITests.swift
|
// __UITests.swift
|
||||||
// 体己UITests
|
// 康康UITests
|
||||||
//
|
//
|
||||||
// Created by Tim on 2026/5/25.
|
// Created by Tim on 2026/5/25.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
//
|
//
|
||||||
// __UITestsLaunchTests.swift
|
// __UITestsLaunchTests.swift
|
||||||
// 体己UITests
|
// 康康UITests
|
||||||
//
|
//
|
||||||
// Created by Tim on 2026/5/25.
|
// Created by Tim on 2026/5/25.
|
||||||
//
|
//
|
||||||
|
|||||||
Reference in New Issue
Block a user