# 情绪博物馆功能完善实施计划 **创建时间**: 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 { 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: 全面测试和优化 --- ## ✅ 验收标准 ### 功能完整性 - [ ] 所有页面都有关闭按钮 - [ ] 页面间跳转逻辑完整 - [ ] 模拟数据丰富真实 - [ ] 支持深色模式 - [ ] 动画流畅自然 ### 用户体验 - [ ] 界面美观一致 - [ ] 交互反馈及时 - [ ] 加载状态友好 - [ ] 错误处理完善 - [ ] 无功能死角 ### 技术质量 - [ ] 代码结构清晰 - [ ] 组件复用性好 - [ ] 性能表现良好 - [ ] 内存使用合理 - [ ] 无崩溃和卡顿 --- 这个实施计划将指导我们按步骤完善整个应用,确保每个功能都得到充分实现。接下来我将按照这个计划开始实施第一阶段的工作。