1173 lines
33 KiB
Markdown
1173 lines
33 KiB
Markdown
# 情绪博物馆功能完善实施计划
|
||
|
||
**创建时间**: 2025-07-05
|
||
**项目状态**: 基础框架已完成,需要功能完善
|
||
**开发框架**: SwiftUI + iOS 18.5
|
||
|
||
---
|
||
|
||
## 📋 当前状态分析
|
||
|
||
### ✅ 已完成功能
|
||
- [x] 基础TabView导航框架(记录、治愈、探索、个人)
|
||
- [x] 主题系统(深色模式支持)
|
||
- [x] 加载状态和骨架屏系统
|
||
- [x] 动画过渡效果
|
||
- [x] RecordView聊天化改造
|
||
- [x] AI对话基础框架
|
||
- [x] 情绪日历基础版
|
||
|
||
### ❌ 待完善功能
|
||
- [ ] 完整的AI对话系统
|
||
- [ ] 治愈页面(成长课题系统)
|
||
- [ ] 探索页面(地图+社区)
|
||
- [ ] 个人页面(用户信息+成就)
|
||
- [ ] 数据模型和存储
|
||
- [ ] 模拟数据系统
|
||
- [ ] 页面间跳转逻辑
|
||
- [ ] 所有弹窗页面的关闭按钮
|
||
|
||
---
|
||
|
||
## 🎯 第一阶段:数据模型和模拟数据系统
|
||
|
||
### 1.1 核心数据模型设计
|
||
|
||
#### 用户模型
|
||
```swift
|
||
struct User {
|
||
let id: UUID
|
||
let username: String
|
||
let email: String
|
||
let avatar: String?
|
||
let profile: UserProfile
|
||
let createdAt: Date
|
||
let lastActiveAt: Date
|
||
}
|
||
|
||
struct UserProfile {
|
||
let nickname: String
|
||
let birthDate: Date?
|
||
let location: String?
|
||
let bio: String?
|
||
let memberLevel: MemberLevel
|
||
let totalDays: Int
|
||
let growthStats: GrowthStats
|
||
}
|
||
|
||
struct GrowthStats {
|
||
let selfAwareness: Float // 自我感知 0-100
|
||
let emotionalResilience: Float // 情绪韧性 0-100
|
||
let actionPower: Float // 行动力 0-100
|
||
let empathy: Float // 共情力 0-100
|
||
let lifeEnthusiasm: Float // 生活热度 0-100
|
||
}
|
||
```
|
||
|
||
#### 对话系统模型
|
||
```swift
|
||
struct Conversation {
|
||
let id: UUID
|
||
let userId: UUID
|
||
let title: String
|
||
let messages: [Message]
|
||
let startTime: Date
|
||
let endTime: Date?
|
||
let emotionAnalysis: EmotionAnalysis?
|
||
let summary: String?
|
||
}
|
||
|
||
struct Message {
|
||
let id: UUID
|
||
let conversationId: UUID
|
||
let content: String
|
||
let type: MessageType
|
||
let sender: MessageSender
|
||
let timestamp: Date
|
||
let emotionScore: Float?
|
||
}
|
||
|
||
enum MessageType {
|
||
case text, voice, image, system
|
||
}
|
||
|
||
enum MessageSender {
|
||
case user, ai
|
||
}
|
||
|
||
struct EmotionAnalysis {
|
||
let primaryEmotion: EmotionType
|
||
let emotionIntensity: Float
|
||
let emotionTrend: EmotionTrend
|
||
let keywords: [String]
|
||
let aiInsights: String
|
||
}
|
||
```
|
||
|
||
#### 成长课题模型
|
||
```swift
|
||
struct GrowthTopic {
|
||
let id: UUID
|
||
let title: String
|
||
let description: String
|
||
let category: TopicCategory
|
||
let difficulty: Difficulty
|
||
let progress: Float
|
||
let level: Int
|
||
let totalLevels: Int
|
||
let isUnlocked: Bool
|
||
let completedAt: Date?
|
||
let rewards: [Reward]
|
||
let interactions: [TopicInteraction]
|
||
}
|
||
|
||
enum TopicCategory {
|
||
case selfAwareness // 自我认知
|
||
case emotionRegulation // 情绪调节
|
||
case socialSkills // 社交技能
|
||
case stressManagement // 压力管理
|
||
case lifeGoals // 人生目标
|
||
}
|
||
|
||
struct TopicInteraction {
|
||
let id: UUID
|
||
let topicId: UUID
|
||
let type: InteractionType
|
||
let content: String
|
||
let completedAt: Date
|
||
let reward: Reward?
|
||
}
|
||
|
||
enum InteractionType {
|
||
case aiChat, article, exercise, reflection
|
||
}
|
||
```
|
||
|
||
#### 地图和社区模型
|
||
```swift
|
||
struct LocationPin {
|
||
let id: UUID
|
||
let coordinate: Coordinate
|
||
let title: String
|
||
let description: String
|
||
let type: LocationType
|
||
let emotionTags: [EmotionType]
|
||
let photos: [String]
|
||
let createdBy: UUID?
|
||
let createdAt: Date
|
||
let likes: Int
|
||
let visits: Int
|
||
}
|
||
|
||
enum LocationType {
|
||
case personal // 个人收藏
|
||
case aiRecommended // AI推荐
|
||
case community // 社区分享
|
||
}
|
||
|
||
struct CommunityPost {
|
||
let id: UUID
|
||
let userId: UUID
|
||
let locationId: UUID?
|
||
let content: String
|
||
let photos: [String]
|
||
let tags: [String]
|
||
let likes: Int
|
||
let comments: [Comment]
|
||
let createdAt: Date
|
||
let isPrivate: Bool
|
||
}
|
||
|
||
struct Comment {
|
||
let id: UUID
|
||
let postId: UUID
|
||
let userId: UUID
|
||
let content: String
|
||
let createdAt: Date
|
||
let likes: Int
|
||
}
|
||
```
|
||
|
||
### 1.2 模拟数据管理器
|
||
|
||
创建 `MockDataManager.swift`:
|
||
```swift
|
||
class MockDataManager: ObservableObject {
|
||
static let shared = MockDataManager()
|
||
|
||
@Published var currentUser: User
|
||
@Published var conversations: [Conversation] = []
|
||
@Published var growthTopics: [GrowthTopic] = []
|
||
@Published var locationPins: [LocationPin] = []
|
||
@Published var communityPosts: [CommunityPost] = []
|
||
@Published var emotionRecords: [EmotionRecord] = []
|
||
|
||
private init() {
|
||
// 初始化模拟数据
|
||
}
|
||
|
||
// 生成丰富的模拟数据方法
|
||
func generateMockConversations() { }
|
||
func generateMockGrowthTopics() { }
|
||
func generateMockLocationPins() { }
|
||
func generateMockEmotionRecords() { }
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 第二阶段:RecordView功能完善
|
||
|
||
### 2.1 聊天记录入口页面
|
||
|
||
创建 `ChatHistoryView.swift`:
|
||
```swift
|
||
struct ChatHistoryView: View {
|
||
@Environment(\.dismiss) private var dismiss
|
||
@ObservedObject var mockData = MockDataManager.shared
|
||
@State private var searchText = ""
|
||
@State private var selectedFilter: ConversationFilter = .all
|
||
|
||
var body: some View {
|
||
NavigationView {
|
||
VStack(spacing: 0) {
|
||
// 搜索栏
|
||
searchBar
|
||
|
||
// 筛选器
|
||
filterTabs
|
||
|
||
// 对话列表
|
||
conversationList
|
||
}
|
||
.navigationTitle("聊天记录")
|
||
.navigationBarTitleDisplayMode(.large)
|
||
.toolbar {
|
||
ToolbarItem(placement: .navigationBarTrailing) {
|
||
Button("关闭") { dismiss() }
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private var searchBar: some View { /* 搜索功能 */ }
|
||
private var filterTabs: some View { /* 筛选标签 */ }
|
||
private var conversationList: some View { /* 对话列表 */ }
|
||
}
|
||
```
|
||
|
||
### 2.2 全屏对话页面
|
||
|
||
创建 `FullScreenChatView.swift`:
|
||
```swift
|
||
struct FullScreenChatView: View {
|
||
@Environment(\.dismiss) private var dismiss
|
||
@StateObject private var chatViewModel = ChatViewModel()
|
||
@State private var inputText = ""
|
||
@State private var isVoiceMode = false
|
||
|
||
var body: some View {
|
||
VStack(spacing: 0) {
|
||
// 顶部导航栏
|
||
chatNavigationBar
|
||
|
||
// 消息列表
|
||
messagesList
|
||
|
||
// 输入区域
|
||
chatInputArea
|
||
}
|
||
.background(Color.theme.background)
|
||
.ignoresSafeArea(.keyboard, edges: .bottom)
|
||
}
|
||
|
||
private var chatNavigationBar: some View {
|
||
HStack {
|
||
Button("收起") { dismiss() }
|
||
Spacer()
|
||
Text("AI助手")
|
||
Spacer()
|
||
Button(isVoiceMode ? "文字" : "语音") {
|
||
isVoiceMode.toggle()
|
||
}
|
||
}
|
||
.padding()
|
||
}
|
||
|
||
private var messagesList: some View { /* 消息列表实现 */ }
|
||
private var chatInputArea: some View { /* 输入区域实现 */ }
|
||
}
|
||
```
|
||
|
||
### 2.3 设置页面
|
||
|
||
创建 `SettingsView.swift`:
|
||
```swift
|
||
struct SettingsView: View {
|
||
@Environment(\.dismiss) private var dismiss
|
||
@StateObject private var themeManager = ThemeManager()
|
||
@State private var musicVolume: Float = 0.5
|
||
@State private var soundVolume: Float = 0.7
|
||
|
||
var body: some View {
|
||
NavigationView {
|
||
List {
|
||
// 主题设置
|
||
themeSection
|
||
|
||
// 音效设置
|
||
audioSection
|
||
|
||
// 隐私设置
|
||
privacySection
|
||
|
||
// 关于设置
|
||
aboutSection
|
||
}
|
||
.navigationTitle("设置")
|
||
.navigationBarTitleDisplayMode(.large)
|
||
.toolbar {
|
||
ToolbarItem(placement: .navigationBarTrailing) {
|
||
Button("关闭") { dismiss() }
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private var themeSection: some View { /* 主题设置 */ }
|
||
private var audioSection: some View { /* 音效设置 */ }
|
||
private var privacySection: some View { /* 隐私设置 */ }
|
||
private var aboutSection: some View { /* 关于设置 */ }
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 第三阶段:GrowthView(治愈页面)完善
|
||
|
||
### 3.1 成长课题主页
|
||
|
||
完善 `GrowthView.swift`:
|
||
```swift
|
||
struct GrowthView: View {
|
||
@StateObject private var themeManager = ThemeManager()
|
||
@ObservedObject var mockData = MockDataManager.shared
|
||
@State private var selectedCategory: TopicCategory = .selfAwareness
|
||
@State private var showingTopicDetail = false
|
||
@State private var selectedTopic: GrowthTopic?
|
||
|
||
var body: some View {
|
||
NavigationView {
|
||
ScrollView {
|
||
LazyVStack(spacing: 20) {
|
||
// 个人成长概览
|
||
growthOverviewCard
|
||
|
||
// 五维雷达图
|
||
growthRadarChart
|
||
|
||
// 课题分类标签
|
||
categoryTabs
|
||
|
||
// 课题列表
|
||
topicsList
|
||
|
||
// 成就展示
|
||
achievementsSection
|
||
}
|
||
.padding(.horizontal, 16)
|
||
}
|
||
.navigationTitle("治愈")
|
||
.navigationBarTitleDisplayMode(.large)
|
||
.refreshable {
|
||
await refreshGrowthData()
|
||
}
|
||
}
|
||
.environmentObject(themeManager)
|
||
.sheet(item: $selectedTopic) { topic in
|
||
TopicDetailView(topic: topic)
|
||
}
|
||
}
|
||
|
||
private var growthOverviewCard: some View { /* 成长概览卡片 */ }
|
||
private var growthRadarChart: some View { /* 五维雷达图 */ }
|
||
private var categoryTabs: some View { /* 分类标签 */ }
|
||
private var topicsList: some View { /* 课题列表 */ }
|
||
private var achievementsSection: some View { /* 成就展示 */ }
|
||
}
|
||
```
|
||
|
||
### 3.2 课题详情页面
|
||
|
||
创建 `TopicDetailView.swift`:
|
||
```swift
|
||
struct TopicDetailView: View {
|
||
@Environment(\.dismiss) private var dismiss
|
||
let topic: GrowthTopic
|
||
@State private var showingInteraction = false
|
||
@State private var selectedInteractionType: InteractionType = .aiChat
|
||
|
||
var body: some View {
|
||
NavigationView {
|
||
ScrollView {
|
||
VStack(spacing: 24) {
|
||
// 课题头部信息
|
||
topicHeader
|
||
|
||
// 进度展示
|
||
progressSection
|
||
|
||
// 互动选项
|
||
interactionOptions
|
||
|
||
// 已完成的互动
|
||
completedInteractions
|
||
|
||
// 相关推荐
|
||
relatedTopics
|
||
}
|
||
.padding()
|
||
}
|
||
.navigationTitle(topic.title)
|
||
.navigationBarTitleDisplayMode(.large)
|
||
.toolbar {
|
||
ToolbarItem(placement: .navigationBarTrailing) {
|
||
Button("关闭") { dismiss() }
|
||
}
|
||
}
|
||
}
|
||
.sheet(isPresented: $showingInteraction) {
|
||
TopicInteractionView(
|
||
topic: topic,
|
||
interactionType: selectedInteractionType
|
||
)
|
||
}
|
||
}
|
||
|
||
private var topicHeader: some View { /* 课题头部 */ }
|
||
private var progressSection: some View { /* 进度展示 */ }
|
||
private var interactionOptions: some View { /* 互动选项 */ }
|
||
private var completedInteractions: some View { /* 已完成互动 */ }
|
||
private var relatedTopics: some View { /* 相关推荐 */ }
|
||
}
|
||
```
|
||
|
||
### 3.3 课题互动页面
|
||
|
||
创建 `TopicInteractionView.swift`:
|
||
```swift
|
||
struct TopicInteractionView: View {
|
||
@Environment(\.dismiss) private var dismiss
|
||
let topic: GrowthTopic
|
||
let interactionType: InteractionType
|
||
@State private var interactionContent = ""
|
||
@State private var isCompleted = false
|
||
|
||
var body: some View {
|
||
NavigationView {
|
||
VStack {
|
||
switch interactionType {
|
||
case .aiChat:
|
||
TopicChatView(topic: topic)
|
||
case .article:
|
||
TopicArticleView(topic: topic)
|
||
case .exercise:
|
||
TopicExerciseView(topic: topic)
|
||
case .reflection:
|
||
TopicReflectionView(topic: topic)
|
||
}
|
||
}
|
||
.navigationTitle(interactionType.title)
|
||
.navigationBarTitleDisplayMode(.inline)
|
||
.toolbar {
|
||
ToolbarItem(placement: .navigationBarLeading) {
|
||
Button("关闭") { dismiss() }
|
||
}
|
||
ToolbarItem(placement: .navigationBarTrailing) {
|
||
Button("完成") {
|
||
completeInteraction()
|
||
}
|
||
.disabled(!isCompleted)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private func completeInteraction() {
|
||
// 完成互动逻辑
|
||
dismiss()
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 第四阶段:ExploreView(探索页面)完善
|
||
|
||
### 4.1 地图主页
|
||
|
||
完善 `ExploreView.swift`:
|
||
```swift
|
||
import MapKit
|
||
|
||
struct ExploreView: View {
|
||
@StateObject private var themeManager = ThemeManager()
|
||
@StateObject private var mapManager = MapManager()
|
||
@ObservedObject var mockData = MockDataManager.shared
|
||
@State private var viewMode: ExploreViewMode = .map
|
||
@State private var selectedPin: LocationPin?
|
||
@State private var showingPinDetail = false
|
||
@State private var showingAddPin = false
|
||
|
||
var body: some View {
|
||
NavigationView {
|
||
ZStack {
|
||
if viewMode == .map {
|
||
mapView
|
||
} else {
|
||
communityView
|
||
}
|
||
|
||
// 浮动控件
|
||
floatingControls
|
||
}
|
||
.navigationTitle("探索")
|
||
.navigationBarTitleDisplayMode(.large)
|
||
.toolbar {
|
||
ToolbarItem(placement: .navigationBarTrailing) {
|
||
Button(viewMode == .map ? "社区" : "地图") {
|
||
withAnimation {
|
||
viewMode = viewMode == .map ? .community : .map
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.environmentObject(themeManager)
|
||
.sheet(item: $selectedPin) { pin in
|
||
LocationDetailView(pin: pin)
|
||
}
|
||
.sheet(isPresented: $showingAddPin) {
|
||
AddLocationView()
|
||
}
|
||
}
|
||
|
||
private var mapView: some View {
|
||
Map(coordinateRegion: $mapManager.region, annotationItems: mockData.locationPins) { pin in
|
||
MapAnnotation(coordinate: pin.coordinate.clLocationCoordinate2D) {
|
||
LocationPinView(pin: pin) {
|
||
selectedPin = pin
|
||
showingPinDetail = true
|
||
}
|
||
}
|
||
}
|
||
.ignoresSafeArea()
|
||
}
|
||
|
||
private var communityView: some View {
|
||
CommunityFeedView()
|
||
}
|
||
|
||
private var floatingControls: some View { /* 浮动控件 */ }
|
||
}
|
||
|
||
enum ExploreViewMode {
|
||
case map, community
|
||
}
|
||
```
|
||
|
||
### 4.2 地点详情页面
|
||
|
||
创建 `LocationDetailView.swift`:
|
||
```swift
|
||
struct LocationDetailView: View {
|
||
@Environment(\.dismiss) private var dismiss
|
||
let pin: LocationPin
|
||
@State private var showingComments = false
|
||
@State private var isLiked = false
|
||
@State private var showingNavigation = false
|
||
|
||
var body: some View {
|
||
NavigationView {
|
||
ScrollView {
|
||
VStack(spacing: 20) {
|
||
// 地点图片轮播
|
||
locationPhotos
|
||
|
||
// 地点信息
|
||
locationInfo
|
||
|
||
// 情绪标签
|
||
emotionTags
|
||
|
||
// 操作按钮
|
||
actionButtons
|
||
|
||
// 相关笔记
|
||
relatedPosts
|
||
|
||
// 评论区域
|
||
commentsSection
|
||
}
|
||
.padding()
|
||
}
|
||
.navigationTitle(pin.title)
|
||
.navigationBarTitleDisplayMode(.large)
|
||
.toolbar {
|
||
ToolbarItem(placement: .navigationBarTrailing) {
|
||
Button("关闭") { dismiss() }
|
||
}
|
||
}
|
||
}
|
||
.sheet(isPresented: $showingNavigation) {
|
||
NavigationView(destination: pin.coordinate)
|
||
}
|
||
}
|
||
|
||
private var locationPhotos: some View { /* 图片轮播 */ }
|
||
private var locationInfo: some View { /* 地点信息 */ }
|
||
private var emotionTags: some View { /* 情绪标签 */ }
|
||
private var actionButtons: some View { /* 操作按钮 */ }
|
||
private var relatedPosts: some View { /* 相关笔记 */ }
|
||
private var commentsSection: some View { /* 评论区域 */ }
|
||
}
|
||
```
|
||
|
||
### 4.3 社区动态页面
|
||
|
||
创建 `CommunityFeedView.swift`:
|
||
```swift
|
||
struct CommunityFeedView: View {
|
||
@ObservedObject var mockData = MockDataManager.shared
|
||
@State private var refreshing = false
|
||
@State private var selectedPost: CommunityPost?
|
||
|
||
var body: some View {
|
||
ScrollView {
|
||
LazyVStack(spacing: 16) {
|
||
ForEach(mockData.communityPosts) { post in
|
||
CommunityPostCard(post: post) {
|
||
selectedPost = post
|
||
}
|
||
}
|
||
}
|
||
.padding(.horizontal, 16)
|
||
}
|
||
.refreshable {
|
||
await refreshFeed()
|
||
}
|
||
.sheet(item: $selectedPost) { post in
|
||
PostDetailView(post: post)
|
||
}
|
||
}
|
||
|
||
private func refreshFeed() async {
|
||
// 刷新动态逻辑
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4.4 添加地点页面
|
||
|
||
创建 `AddLocationView.swift`:
|
||
```swift
|
||
struct AddLocationView: View {
|
||
@Environment(\.dismiss) private var dismiss
|
||
@State private var locationName = ""
|
||
@State private var locationDescription = ""
|
||
@State private var selectedEmotions: [EmotionType] = []
|
||
@State private var selectedPhotos: [UIImage] = []
|
||
@State private var selectedCoordinate: Coordinate?
|
||
|
||
var body: some View {
|
||
NavigationView {
|
||
Form {
|
||
Section("基本信息") {
|
||
TextField("地点名称", text: $locationName)
|
||
TextField("地点描述", text: $locationDescription, axis: .vertical)
|
||
.lineLimit(3...6)
|
||
}
|
||
|
||
Section("位置信息") {
|
||
LocationPickerView(selectedCoordinate: $selectedCoordinate)
|
||
}
|
||
|
||
Section("情绪标签") {
|
||
EmotionTagPicker(selectedEmotions: $selectedEmotions)
|
||
}
|
||
|
||
Section("添加照片") {
|
||
PhotoPickerView(selectedPhotos: $selectedPhotos)
|
||
}
|
||
}
|
||
.navigationTitle("添加地点")
|
||
.navigationBarTitleDisplayMode(.inline)
|
||
.toolbar {
|
||
ToolbarItem(placement: .navigationBarLeading) {
|
||
Button("取消") { dismiss() }
|
||
}
|
||
ToolbarItem(placement: .navigationBarTrailing) {
|
||
Button("保存") {
|
||
saveLocation()
|
||
}
|
||
.disabled(locationName.isEmpty)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private func saveLocation() {
|
||
// 保存地点逻辑
|
||
dismiss()
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 第五阶段:InsightView(个人页面)完善
|
||
|
||
### 5.1 个人主页
|
||
|
||
完善 `InsightView.swift`:
|
||
```swift
|
||
struct InsightView: View {
|
||
@StateObject private var themeManager = ThemeManager()
|
||
@ObservedObject var mockData = MockDataManager.shared
|
||
@State private var showingProfile = false
|
||
@State private var showingSettings = false
|
||
@State private var showingAchievements = false
|
||
|
||
var body: some View {
|
||
NavigationView {
|
||
ScrollView {
|
||
LazyVStack(spacing: 20) {
|
||
// 用户头像和基本信息
|
||
userProfileCard
|
||
|
||
// 本周数据统计
|
||
weeklyStatsCard
|
||
|
||
// 成就展示
|
||
achievementsCard
|
||
|
||
// 社交数据
|
||
socialStatsCard
|
||
|
||
// 快捷功能
|
||
quickActionsCard
|
||
|
||
// 会员中心
|
||
membershipCard
|
||
}
|
||
.padding(.horizontal, 16)
|
||
}
|
||
.navigationTitle("我的")
|
||
.navigationBarTitleDisplayMode(.large)
|
||
.toolbar {
|
||
ToolbarItem(placement: .navigationBarTrailing) {
|
||
Button(action: { showingSettings = true }) {
|
||
Image(systemName: "gearshape")
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.environmentObject(themeManager)
|
||
.sheet(isPresented: $showingProfile) {
|
||
UserProfileView()
|
||
}
|
||
.sheet(isPresented: $showingSettings) {
|
||
SettingsView()
|
||
}
|
||
.sheet(isPresented: $showingAchievements) {
|
||
AchievementsView()
|
||
}
|
||
}
|
||
|
||
private var userProfileCard: some View { /* 用户资料卡片 */ }
|
||
private var weeklyStatsCard: some View { /* 本周统计 */ }
|
||
private var achievementsCard: some View { /* 成就展示 */ }
|
||
private var socialStatsCard: some View { /* 社交数据 */ }
|
||
private var quickActionsCard: some View { /* 快捷功能 */ }
|
||
private var membershipCard: some View { /* 会员中心 */ }
|
||
}
|
||
```
|
||
|
||
### 5.2 用户资料页面
|
||
|
||
创建 `UserProfileView.swift`:
|
||
```swift
|
||
struct UserProfileView: View {
|
||
@Environment(\.dismiss) private var dismiss
|
||
@ObservedObject var mockData = MockDataManager.shared
|
||
@State private var isEditing = false
|
||
@State private var editedProfile: UserProfile
|
||
|
||
init() {
|
||
_editedProfile = State(initialValue: MockDataManager.shared.currentUser.profile)
|
||
}
|
||
|
||
var body: some View {
|
||
NavigationView {
|
||
Form {
|
||
Section("基本信息") {
|
||
profileImageSection
|
||
|
||
if isEditing {
|
||
TextField("昵称", text: $editedProfile.nickname)
|
||
DatePicker("生日", selection: Binding(
|
||
get: { editedProfile.birthDate ?? Date() },
|
||
set: { editedProfile.birthDate = $0 }
|
||
), displayedComponents: .date)
|
||
TextField("所在地", text: Binding(
|
||
get: { editedProfile.location ?? "" },
|
||
set: { editedProfile.location = $0 }
|
||
))
|
||
TextField("个人简介", text: Binding(
|
||
get: { editedProfile.bio ?? "" },
|
||
set: { editedProfile.bio = $0 }
|
||
), axis: .vertical)
|
||
.lineLimit(3...6)
|
||
} else {
|
||
profileDisplaySection
|
||
}
|
||
}
|
||
|
||
Section("成长数据") {
|
||
growthStatsSection
|
||
}
|
||
|
||
Section("账户信息") {
|
||
accountInfoSection
|
||
}
|
||
}
|
||
.navigationTitle("个人资料")
|
||
.navigationBarTitleDisplayMode(.large)
|
||
.toolbar {
|
||
ToolbarItem(placement: .navigationBarLeading) {
|
||
Button("关闭") { dismiss() }
|
||
}
|
||
ToolbarItem(placement: .navigationBarTrailing) {
|
||
Button(isEditing ? "保存" : "编辑") {
|
||
if isEditing {
|
||
saveProfile()
|
||
}
|
||
isEditing.toggle()
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private var profileImageSection: some View { /* 头像编辑 */ }
|
||
private var profileDisplaySection: some View { /* 资料展示 */ }
|
||
private var growthStatsSection: some View { /* 成长数据 */ }
|
||
private var accountInfoSection: some View { /* 账户信息 */ }
|
||
|
||
private func saveProfile() {
|
||
// 保存用户资料
|
||
}
|
||
}
|
||
```
|
||
|
||
### 5.3 成就页面
|
||
|
||
创建 `AchievementsView.swift`:
|
||
```swift
|
||
struct AchievementsView: View {
|
||
@Environment(\.dismiss) private var dismiss
|
||
@ObservedObject var mockData = MockDataManager.shared
|
||
@State private var selectedCategory: AchievementCategory = .all
|
||
|
||
var body: some View {
|
||
NavigationView {
|
||
VStack(spacing: 0) {
|
||
// 成就统计概览
|
||
achievementOverview
|
||
|
||
// 分类筛选
|
||
categoryFilter
|
||
|
||
// 成就列表
|
||
achievementsList
|
||
}
|
||
.navigationTitle("我的成就")
|
||
.navigationBarTitleDisplayMode(.large)
|
||
.toolbar {
|
||
ToolbarItem(placement: .navigationBarTrailing) {
|
||
Button("关闭") { dismiss() }
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private var achievementOverview: some View { /* 成就概览 */ }
|
||
private var categoryFilter: some View { /* 分类筛选 */ }
|
||
private var achievementsList: some View { /* 成就列表 */ }
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 第六阶段:页面跳转逻辑完善
|
||
|
||
### 6.1 导航状态管理
|
||
|
||
创建 `NavigationManager.swift`:
|
||
```swift
|
||
class NavigationManager: ObservableObject {
|
||
@Published var currentTab: MainTab = .record
|
||
@Published var recordNavigation = NavigationPath()
|
||
@Published var growthNavigation = NavigationPath()
|
||
@Published var exploreNavigation = NavigationPath()
|
||
@Published var insightNavigation = NavigationPath()
|
||
|
||
// 全局弹窗状态
|
||
@Published var showingChatHistory = false
|
||
@Published var showingFullScreenChat = false
|
||
@Published var showingSettings = false
|
||
@Published var showingProfile = false
|
||
|
||
func navigateToChat(conversation: Conversation?) {
|
||
showingFullScreenChat = true
|
||
}
|
||
|
||
func navigateToTopic(topic: GrowthTopic) {
|
||
growthNavigation.append(topic)
|
||
}
|
||
|
||
func navigateToLocation(pin: LocationPin) {
|
||
exploreNavigation.append(pin)
|
||
}
|
||
}
|
||
|
||
enum MainTab: CaseIterable {
|
||
case record, growth, explore, insight
|
||
|
||
var title: String {
|
||
switch self {
|
||
case .record: return "记录"
|
||
case .growth: return "治愈"
|
||
case .explore: return "探索"
|
||
case .insight: return "我的"
|
||
}
|
||
}
|
||
|
||
var icon: String {
|
||
switch self {
|
||
case .record: return "brain.head.profile"
|
||
case .growth: return "heart"
|
||
case .explore: return "map"
|
||
case .insight: return "person"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 6.2 更新ContentView
|
||
|
||
更新主视图以支持完整的导航:
|
||
```swift
|
||
struct ContentView: View {
|
||
@StateObject private var navigationManager = NavigationManager()
|
||
@StateObject private var themeManager = ThemeManager()
|
||
@StateObject private var mockData = MockDataManager.shared
|
||
|
||
var body: some View {
|
||
TabView(selection: $navigationManager.currentTab) {
|
||
ForEach(MainTab.allCases, id: \.self) { tab in
|
||
NavigationStack(path: bindingForTab(tab)) {
|
||
viewForTab(tab)
|
||
.navigationDestination(for: GrowthTopic.self) { topic in
|
||
TopicDetailView(topic: topic)
|
||
}
|
||
.navigationDestination(for: LocationPin.self) { pin in
|
||
LocationDetailView(pin: pin)
|
||
}
|
||
.navigationDestination(for: CommunityPost.self) { post in
|
||
PostDetailView(post: post)
|
||
}
|
||
}
|
||
.tabItem {
|
||
Image(systemName: tab.icon)
|
||
Text(tab.title)
|
||
}
|
||
.tag(tab)
|
||
}
|
||
}
|
||
.environmentObject(navigationManager)
|
||
.environmentObject(themeManager)
|
||
.environmentObject(mockData)
|
||
.onAppear {
|
||
configureTabBarAppearance()
|
||
}
|
||
}
|
||
|
||
@ViewBuilder
|
||
private func viewForTab(_ tab: MainTab) -> some View {
|
||
switch tab {
|
||
case .record:
|
||
RecordView()
|
||
case .growth:
|
||
GrowthView()
|
||
case .explore:
|
||
ExploreView()
|
||
case .insight:
|
||
InsightView()
|
||
}
|
||
}
|
||
|
||
private func bindingForTab(_ tab: MainTab) -> Binding<NavigationPath> {
|
||
switch tab {
|
||
case .record:
|
||
return $navigationManager.recordNavigation
|
||
case .growth:
|
||
return $navigationManager.growthNavigation
|
||
case .explore:
|
||
return $navigationManager.exploreNavigation
|
||
case .insight:
|
||
return $navigationManager.insightNavigation
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 第七阶段:模拟数据生成
|
||
|
||
### 7.1 丰富的模拟数据
|
||
|
||
在 `MockDataManager.swift` 中添加:
|
||
```swift
|
||
extension MockDataManager {
|
||
func generateRichMockData() {
|
||
generateMockUser()
|
||
generateMockConversations()
|
||
generateMockGrowthTopics()
|
||
generateMockLocationPins()
|
||
generateMockCommunityPosts()
|
||
generateMockEmotionRecords()
|
||
generateMockAchievements()
|
||
}
|
||
|
||
private func generateMockUser() {
|
||
currentUser = User(
|
||
id: UUID(),
|
||
username: "emotion_explorer",
|
||
email: "user@example.com",
|
||
avatar: nil,
|
||
profile: UserProfile(
|
||
nickname: "情绪探索者",
|
||
birthDate: Calendar.current.date(byAdding: .year, value: -25, to: Date()),
|
||
location: "北京市",
|
||
bio: "在情绪的海洋中寻找内心的平静",
|
||
memberLevel: .premium,
|
||
totalDays: 127,
|
||
growthStats: GrowthStats(
|
||
selfAwareness: 78.5,
|
||
emotionalResilience: 65.2,
|
||
actionPower: 72.8,
|
||
empathy: 85.3,
|
||
lifeEnthusiasm: 69.7
|
||
)
|
||
),
|
||
createdAt: Calendar.current.date(byAdding: .day, value: -127, to: Date()) ?? Date(),
|
||
lastActiveAt: Date()
|
||
)
|
||
}
|
||
|
||
private func generateMockConversations() {
|
||
// 生成30天的对话记录
|
||
for i in 0..<30 {
|
||
let date = Calendar.current.date(byAdding: .day, value: -i, to: Date()) ?? Date()
|
||
let conversation = createMockConversation(for: date)
|
||
conversations.append(conversation)
|
||
}
|
||
}
|
||
|
||
private func generateMockGrowthTopics() {
|
||
// 为每个分类生成3-5个课题
|
||
TopicCategory.allCases.forEach { category in
|
||
for i in 1...4 {
|
||
let topic = createMockTopic(category: category, index: i)
|
||
growthTopics.append(topic)
|
||
}
|
||
}
|
||
}
|
||
|
||
private func generateMockLocationPins() {
|
||
// 生成北京地区的模拟地点
|
||
let beijingCoordinates = [
|
||
(39.9042, 116.4074), // 天安门
|
||
(39.9163, 116.3972), // 故宫
|
||
(40.0031, 116.3272), // 颐和园
|
||
(39.8844, 116.5564), // 798艺术区
|
||
(39.9389, 116.3467), // 什刹海
|
||
]
|
||
|
||
beijingCoordinates.enumerated().forEach { index, coord in
|
||
let pin = createMockLocationPin(
|
||
coordinate: Coordinate(latitude: coord.0, longitude: coord.1),
|
||
index: index
|
||
)
|
||
locationPins.append(pin)
|
||
}
|
||
}
|
||
|
||
// 具体的创建方法...
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 📅 实施时间表
|
||
|
||
### Week 1: 数据模型和基础功能
|
||
- [ ] Day 1-2: 创建完整的数据模型
|
||
- [ ] Day 3-4: 实现MockDataManager和模拟数据
|
||
- [ ] Day 5-7: 完善RecordView的所有子页面
|
||
|
||
### Week 2: 治愈页面开发
|
||
- [ ] Day 1-3: 实现GrowthView主页和课题系统
|
||
- [ ] Day 4-5: 开发课题详情和互动页面
|
||
- [ ] Day 6-7: 实现五维雷达图和成就系统
|
||
|
||
### Week 3: 探索页面开发
|
||
- [ ] Day 1-3: 集成地图SDK和地点功能
|
||
- [ ] Day 4-5: 实现社区动态和分享功能
|
||
- [ ] Day 6-7: 完善地点详情和导航功能
|
||
|
||
### Week 4: 个人页面和完善
|
||
- [ ] Day 1-2: 实现个人资料和设置页面
|
||
- [ ] Day 3-4: 完善成就系统和统计功能
|
||
- [ ] Day 5-7: 全面测试和优化
|
||
|
||
---
|
||
|
||
## ✅ 验收标准
|
||
|
||
### 功能完整性
|
||
- [ ] 所有页面都有关闭按钮
|
||
- [ ] 页面间跳转逻辑完整
|
||
- [ ] 模拟数据丰富真实
|
||
- [ ] 支持深色模式
|
||
- [ ] 动画流畅自然
|
||
|
||
### 用户体验
|
||
- [ ] 界面美观一致
|
||
- [ ] 交互反馈及时
|
||
- [ ] 加载状态友好
|
||
- [ ] 错误处理完善
|
||
- [ ] 无功能死角
|
||
|
||
### 技术质量
|
||
- [ ] 代码结构清晰
|
||
- [ ] 组件复用性好
|
||
- [ ] 性能表现良好
|
||
- [ ] 内存使用合理
|
||
- [ ] 无崩溃和卡顿
|
||
|
||
---
|
||
|
||
这个实施计划将指导我们按步骤完善整个应用,确保每个功能都得到充分实现。接下来我将按照这个计划开始实施第一阶段的工作。 |