808 lines
26 KiB
Swift
808 lines
26 KiB
Swift
//
|
|
// GrowthView.swift
|
|
// EmotionMuseum
|
|
//
|
|
// Created by 华中敏 on 2025/6/13.
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
// MARK: - 治愈页面主视图
|
|
struct GrowthView: View {
|
|
@StateObject private var themeManager = ThemeManager()
|
|
@State private var showingTopicDetail = false
|
|
@State private var selectedTopic: GrowthTopic?
|
|
@State private var showingInsights = false
|
|
@State private var showingRadarChart = false
|
|
@State private var loadingState: LoadingState = .idle
|
|
@State private var isInitialLoading = true
|
|
|
|
var body: some View {
|
|
NavigationView {
|
|
LoadingStateView(loadingState: isInitialLoading ? .loading : .loaded) {
|
|
ScrollView {
|
|
VStack(spacing: 24) {
|
|
// 情绪洞察卡片
|
|
EmotionalInsightCard {
|
|
showingInsights = true
|
|
}
|
|
.transition(.scale(scale: 0.8).combined(with: .opacity))
|
|
|
|
// 用户画像五维图
|
|
UserProfileRadarCard {
|
|
showingRadarChart = true
|
|
}
|
|
.transition(.scale(scale: 0.8).combined(with: .opacity))
|
|
|
|
// 成长课题系统
|
|
GrowthTopicsSection { topic in
|
|
selectedTopic = topic
|
|
showingTopicDetail = true
|
|
}
|
|
.transition(.scale(scale: 0.8).combined(with: .opacity))
|
|
|
|
// 今日推荐行动
|
|
TodayActionCard()
|
|
.transition(.scale(scale: 0.8).combined(with: .opacity))
|
|
|
|
// 成长历程
|
|
GrowthTimelineCard()
|
|
.transition(.scale(scale: 0.8).combined(with: .opacity))
|
|
}
|
|
.padding(.horizontal)
|
|
.padding(.vertical)
|
|
}
|
|
.refreshable {
|
|
await refreshData()
|
|
}
|
|
} loadingView: {
|
|
AnyView(growthViewSkeleton)
|
|
}
|
|
.navigationTitle("成长治愈")
|
|
.navigationBarTitleDisplayMode(.large)
|
|
}
|
|
.environmentObject(themeManager)
|
|
.preferredColorScheme(themeManager.systemFollowsDeviceTheme ? nil : (themeManager.isDarkMode ? .dark : .light))
|
|
.sheet(isPresented: $showingTopicDetail) {
|
|
if let topic = selectedTopic {
|
|
TopicDetailView(topic: topic)
|
|
.environmentObject(themeManager)
|
|
}
|
|
}
|
|
.sheet(isPresented: $showingInsights) {
|
|
EmotionalInsightsView()
|
|
.environmentObject(themeManager)
|
|
}
|
|
.sheet(isPresented: $showingRadarChart) {
|
|
NavigationView {
|
|
VStack {
|
|
Text("用户画像雷达图")
|
|
.font(.title)
|
|
.padding()
|
|
|
|
Text("这里显示用户的多维度能力雷达图")
|
|
.foregroundColor(.secondary)
|
|
.padding()
|
|
|
|
Spacer()
|
|
}
|
|
.navigationTitle("用户画像")
|
|
.navigationBarTitleDisplayMode(.inline)
|
|
.toolbar {
|
|
ToolbarItem(placement: .navigationBarTrailing) {
|
|
Button("关闭") {
|
|
showingRadarChart = false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.environmentObject(themeManager)
|
|
}
|
|
.onAppear {
|
|
simulateInitialLoading()
|
|
}
|
|
}
|
|
|
|
// MARK: - 私有方法
|
|
private func simulateInitialLoading() {
|
|
loadingState = .loading
|
|
|
|
// 模拟异步加载过程
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 1.2) {
|
|
withAnimation(.easeOut(duration: 0.8)) {
|
|
isInitialLoading = false
|
|
loadingState = .loaded
|
|
}
|
|
}
|
|
}
|
|
|
|
private func refreshData() async {
|
|
loadingState = .loading
|
|
|
|
// 模拟数据刷新
|
|
try? await Task.sleep(nanoseconds: 800_000_000) // 0.8秒
|
|
|
|
DispatchQueue.main.async {
|
|
withAnimation(.easeOut(duration: 0.6)) {
|
|
loadingState = .loaded
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - 骨架屏视图
|
|
private var growthViewSkeleton: some View {
|
|
ScrollView {
|
|
VStack(spacing: 24) {
|
|
// 情绪洞察卡片骨架屏
|
|
insightCardSkeleton
|
|
|
|
// 用户画像卡片骨架屏
|
|
radarCardSkeleton
|
|
|
|
// 成长课题骨架屏
|
|
topicsGridSkeleton
|
|
|
|
// 今日推荐骨架屏
|
|
actionCardSkeleton
|
|
|
|
// 成长历程骨架屏
|
|
timelineCardSkeleton
|
|
}
|
|
.padding(.horizontal)
|
|
.padding(.vertical)
|
|
}
|
|
.background(Color.theme.background)
|
|
}
|
|
|
|
private var insightCardSkeleton: some View {
|
|
VStack(alignment: .leading, spacing: 16) {
|
|
HStack {
|
|
VStack(alignment: .leading, spacing: 4) {
|
|
SkeletonView(width: 80, height: 20, cornerRadius: 6)
|
|
SkeletonView(width: 140, height: 12, cornerRadius: 3)
|
|
}
|
|
Spacer()
|
|
SkeletonView(width: 24, height: 24, cornerRadius: 12)
|
|
}
|
|
|
|
VStack(spacing: 12) {
|
|
ForEach(0..<3, id: \.self) { _ in
|
|
HStack(spacing: 12) {
|
|
SkeletonView(width: 20, height: 16, cornerRadius: 4)
|
|
SkeletonView(width: 80, height: 14, cornerRadius: 3)
|
|
Spacer()
|
|
SkeletonView(width: 60, height: 14, cornerRadius: 3)
|
|
}
|
|
}
|
|
}
|
|
|
|
HStack {
|
|
SkeletonView(width: 100, height: 12, cornerRadius: 3)
|
|
Spacer()
|
|
SkeletonView(width: 12, height: 12, cornerRadius: 3)
|
|
}
|
|
}
|
|
.padding()
|
|
.background(Color.theme.cardBackground)
|
|
.cornerRadius(16)
|
|
}
|
|
|
|
private var radarCardSkeleton: some View {
|
|
VStack(spacing: 16) {
|
|
HStack {
|
|
SkeletonView(width: 80, height: 20, cornerRadius: 6)
|
|
Spacer()
|
|
SkeletonView(width: 24, height: 24, cornerRadius: 12)
|
|
}
|
|
|
|
VStack(spacing: 8) {
|
|
ForEach(0..<5, id: \.self) { _ in
|
|
HStack {
|
|
SkeletonView(width: 60, height: 12, cornerRadius: 3)
|
|
SkeletonView(height: 8, cornerRadius: 4)
|
|
SkeletonView(width: 40, height: 12, cornerRadius: 3)
|
|
}
|
|
}
|
|
}
|
|
|
|
HStack {
|
|
SkeletonView(width: 120, height: 12, cornerRadius: 3)
|
|
Spacer()
|
|
SkeletonView(width: 12, height: 12, cornerRadius: 3)
|
|
}
|
|
}
|
|
.padding()
|
|
.background(Color.theme.cardBackground)
|
|
.cornerRadius(16)
|
|
}
|
|
|
|
private var topicsGridSkeleton: some View {
|
|
VStack(alignment: .leading, spacing: 16) {
|
|
HStack {
|
|
SkeletonView(width: 80, height: 20, cornerRadius: 6)
|
|
Spacer()
|
|
SkeletonView(width: 60, height: 12, cornerRadius: 3)
|
|
}
|
|
|
|
LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 2), spacing: 12) {
|
|
ForEach(0..<4, id: \.self) { _ in
|
|
VStack(alignment: .leading, spacing: 12) {
|
|
HStack {
|
|
SkeletonView(width: 20, height: 20, cornerRadius: 10)
|
|
Spacer()
|
|
SkeletonView(width: 30, height: 12, cornerRadius: 3)
|
|
}
|
|
|
|
VStack(alignment: .leading, spacing: 4) {
|
|
SkeletonView(width: 100, height: 14, cornerRadius: 3)
|
|
SkeletonView(width: 120, height: 12, cornerRadius: 3)
|
|
SkeletonView(width: 80, height: 12, cornerRadius: 3)
|
|
}
|
|
|
|
VStack(spacing: 4) {
|
|
HStack {
|
|
SkeletonView(width: 30, height: 10, cornerRadius: 2)
|
|
Spacer()
|
|
SkeletonView(width: 30, height: 10, cornerRadius: 2)
|
|
}
|
|
SkeletonView(height: 4, cornerRadius: 2)
|
|
}
|
|
}
|
|
.padding()
|
|
.background(Color.theme.cardBackground)
|
|
.cornerRadius(12)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private var actionCardSkeleton: some View {
|
|
VStack(alignment: .leading, spacing: 16) {
|
|
HStack {
|
|
SkeletonView(width: 80, height: 20, cornerRadius: 6)
|
|
Spacer()
|
|
SkeletonView(width: 24, height: 24, cornerRadius: 12)
|
|
}
|
|
|
|
VStack(spacing: 12) {
|
|
ForEach(0..<3, id: \.self) { _ in
|
|
HStack(spacing: 12) {
|
|
SkeletonView(width: 24, height: 24, cornerRadius: 12)
|
|
|
|
VStack(alignment: .leading, spacing: 2) {
|
|
SkeletonView(width: 160, height: 14, cornerRadius: 3)
|
|
HStack(spacing: 8) {
|
|
SkeletonView(width: 60, height: 16, cornerRadius: 8)
|
|
SkeletonView(width: 40, height: 12, cornerRadius: 3)
|
|
}
|
|
}
|
|
Spacer()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.padding()
|
|
.background(Color.theme.cardBackground)
|
|
.cornerRadius(16)
|
|
}
|
|
|
|
private var timelineCardSkeleton: some View {
|
|
VStack(alignment: .leading, spacing: 16) {
|
|
SkeletonView(width: 80, height: 20, cornerRadius: 6)
|
|
|
|
VStack(alignment: .leading, spacing: 12) {
|
|
ForEach(0..<4, id: \.self) { _ in
|
|
HStack(spacing: 12) {
|
|
VStack {
|
|
SkeletonView(width: 8, height: 8, cornerRadius: 4)
|
|
SkeletonView(width: 1, height: 20, cornerRadius: 1)
|
|
}
|
|
|
|
VStack(alignment: .leading, spacing: 2) {
|
|
HStack {
|
|
SkeletonView(width: 100, height: 14, cornerRadius: 3)
|
|
Spacer()
|
|
SkeletonView(width: 40, height: 12, cornerRadius: 3)
|
|
}
|
|
SkeletonView(width: 180, height: 12, cornerRadius: 3)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.padding()
|
|
.background(Color.theme.cardBackground)
|
|
.cornerRadius(16)
|
|
}
|
|
}
|
|
|
|
// MARK: - 情绪洞察卡片
|
|
struct EmotionalInsightCard: View {
|
|
let onTap: () -> Void
|
|
|
|
var body: some View {
|
|
Button(action: onTap) {
|
|
VStack(alignment: .leading, spacing: 16) {
|
|
HStack {
|
|
VStack(alignment: .leading, spacing: 4) {
|
|
Text("情绪洞察")
|
|
.font(.headline)
|
|
.fontWeight(.semibold)
|
|
.foregroundColor(Color.theme.primaryText)
|
|
|
|
Text("基于你的对话记录生成")
|
|
.font(.caption)
|
|
.foregroundColor(Color.theme.secondaryText)
|
|
}
|
|
|
|
Spacer()
|
|
|
|
Image(systemName: "brain.head.profile")
|
|
.font(.title2)
|
|
.foregroundColor(.purple)
|
|
}
|
|
|
|
VStack(alignment: .leading, spacing: 12) {
|
|
InsightRow(
|
|
icon: "heart.fill",
|
|
title: "主要情绪状态",
|
|
value: "平静自省",
|
|
color: .blue
|
|
)
|
|
|
|
InsightRow(
|
|
icon: "target",
|
|
title: "成长焦点",
|
|
value: "人际关系",
|
|
color: .green
|
|
)
|
|
|
|
InsightRow(
|
|
icon: "chart.line.uptrend.xyaxis",
|
|
title: "进步指数",
|
|
value: "↗️ 稳步提升",
|
|
color: .orange
|
|
)
|
|
}
|
|
|
|
HStack {
|
|
Text("点击查看详细分析")
|
|
.font(.caption)
|
|
.foregroundColor(Color.theme.secondaryText)
|
|
|
|
Spacer()
|
|
|
|
Image(systemName: "chevron.right")
|
|
.font(.caption)
|
|
.foregroundColor(Color.theme.secondaryText)
|
|
}
|
|
}
|
|
.padding()
|
|
.background(
|
|
RoundedRectangle(cornerRadius: 16)
|
|
.fill(Color(.systemGray6))
|
|
)
|
|
}
|
|
.buttonStyle(PlainButtonStyle())
|
|
}
|
|
}
|
|
|
|
struct InsightRow: View {
|
|
let icon: String
|
|
let title: String
|
|
let value: String
|
|
let color: Color
|
|
|
|
var body: some View {
|
|
HStack(spacing: 12) {
|
|
Image(systemName: icon)
|
|
.font(.subheadline)
|
|
.foregroundColor(color)
|
|
.frame(width: 20)
|
|
|
|
Text(title)
|
|
.font(.subheadline)
|
|
.foregroundColor(Color.theme.secondaryText)
|
|
|
|
Spacer()
|
|
|
|
Text(value)
|
|
.font(.subheadline)
|
|
.fontWeight(.medium)
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - 用户画像雷达图卡片
|
|
struct UserProfileRadarCard: View {
|
|
let onTap: () -> Void
|
|
|
|
var body: some View {
|
|
Button(action: onTap) {
|
|
VStack(spacing: 16) {
|
|
HStack {
|
|
Text("成长画像")
|
|
.font(.headline)
|
|
.fontWeight(.semibold)
|
|
|
|
Spacer()
|
|
|
|
Image(systemName: "person.crop.circle.badge.checkmark")
|
|
.font(.title2)
|
|
.foregroundColor(.green)
|
|
}
|
|
|
|
// 简化的五维显示
|
|
VStack(spacing: 8) {
|
|
ProfileDimensionRow(name: "自我感知", value: 0.8, color: .blue)
|
|
ProfileDimensionRow(name: "情绪韧性", value: 0.7, color: .purple)
|
|
ProfileDimensionRow(name: "行动力", value: 0.6, color: .orange)
|
|
ProfileDimensionRow(name: "共情力", value: 0.9, color: .green)
|
|
ProfileDimensionRow(name: "生活热度", value: 0.7, color: .red)
|
|
}
|
|
|
|
HStack {
|
|
Text("点击查看完整雷达图")
|
|
.font(.caption)
|
|
.foregroundColor(.secondary)
|
|
|
|
Spacer()
|
|
|
|
Image(systemName: "chevron.right")
|
|
.font(.caption)
|
|
.foregroundColor(.secondary)
|
|
}
|
|
}
|
|
.padding()
|
|
.background(
|
|
RoundedRectangle(cornerRadius: 16)
|
|
.fill(Color(.systemGray6))
|
|
)
|
|
}
|
|
.buttonStyle(PlainButtonStyle())
|
|
}
|
|
}
|
|
|
|
struct ProfileDimensionRow: View {
|
|
let name: String
|
|
let value: Double
|
|
let color: Color
|
|
|
|
var body: some View {
|
|
HStack {
|
|
Text(name)
|
|
.font(.caption)
|
|
.foregroundColor(.primary)
|
|
.frame(width: 60, alignment: .leading)
|
|
|
|
ProgressView(value: value)
|
|
.progressViewStyle(LinearProgressViewStyle(tint: color))
|
|
|
|
Text("\(Int(value * 100))%")
|
|
.font(.caption)
|
|
.fontWeight(.medium)
|
|
.foregroundColor(color)
|
|
.frame(width: 40, alignment: .trailing)
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - 成长课题系统
|
|
struct GrowthTopicsSection: View {
|
|
let onTopicTap: (GrowthTopic) -> Void
|
|
|
|
var body: some View {
|
|
VStack(alignment: .leading, spacing: 16) {
|
|
HStack {
|
|
Text("成长课题")
|
|
.font(.headline)
|
|
.fontWeight(.semibold)
|
|
|
|
Spacer()
|
|
|
|
Text("3个进行中")
|
|
.font(.caption)
|
|
.foregroundColor(.secondary)
|
|
}
|
|
|
|
LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 2), spacing: 12) {
|
|
ForEach(sampleGrowthTopics) { topic in
|
|
TopicCard(topic: topic) {
|
|
onTopicTap(topic)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
struct TopicCard: View {
|
|
let topic: GrowthTopic
|
|
let onTap: () -> Void
|
|
|
|
var body: some View {
|
|
Button(action: onTap) {
|
|
VStack(alignment: .leading, spacing: 12) {
|
|
HStack {
|
|
Image(systemName: topic.icon)
|
|
.font(.title3)
|
|
.foregroundColor(topic.color)
|
|
|
|
Spacer()
|
|
|
|
Text("Lv.\(topic.level)")
|
|
.font(.caption)
|
|
.fontWeight(.bold)
|
|
.foregroundColor(topic.color)
|
|
}
|
|
|
|
VStack(alignment: .leading, spacing: 4) {
|
|
Text(topic.title)
|
|
.font(.subheadline)
|
|
.fontWeight(.medium)
|
|
.multilineTextAlignment(.leading)
|
|
|
|
Text(topic.description)
|
|
.font(.caption)
|
|
.foregroundColor(.secondary)
|
|
.lineLimit(2)
|
|
.multilineTextAlignment(.leading)
|
|
}
|
|
|
|
VStack(spacing: 4) {
|
|
HStack {
|
|
Text("进度")
|
|
.font(.caption2)
|
|
.foregroundColor(.secondary)
|
|
|
|
Spacer()
|
|
|
|
Text("\(Int(topic.progress * 100))%")
|
|
.font(.caption2)
|
|
.fontWeight(.medium)
|
|
}
|
|
|
|
ProgressView(value: topic.progress)
|
|
.progressViewStyle(LinearProgressViewStyle(tint: topic.color))
|
|
}
|
|
}
|
|
.padding()
|
|
.background(
|
|
RoundedRectangle(cornerRadius: 12)
|
|
.fill(Color(.systemGray6))
|
|
)
|
|
}
|
|
.buttonStyle(PlainButtonStyle())
|
|
}
|
|
}
|
|
|
|
// MARK: - 今日推荐行动
|
|
struct TodayActionCard: View {
|
|
var body: some View {
|
|
VStack(alignment: .leading, spacing: 16) {
|
|
HStack {
|
|
Text("今日推荐")
|
|
.font(.headline)
|
|
.fontWeight(.semibold)
|
|
|
|
Spacer()
|
|
|
|
Image(systemName: "lightbulb.fill")
|
|
.font(.title3)
|
|
.foregroundColor(.yellow)
|
|
}
|
|
|
|
VStack(spacing: 12) {
|
|
ActionItemView(
|
|
title: "与朋友分享一件开心的事",
|
|
category: "人际关系",
|
|
duration: "5分钟",
|
|
color: .blue
|
|
)
|
|
|
|
ActionItemView(
|
|
title: "写下今天的三个感恩点",
|
|
category: "自我觉察",
|
|
duration: "10分钟",
|
|
color: .green
|
|
)
|
|
|
|
ActionItemView(
|
|
title: "深呼吸练习",
|
|
category: "情绪调节",
|
|
duration: "3分钟",
|
|
color: .purple
|
|
)
|
|
}
|
|
}
|
|
.padding()
|
|
.background(
|
|
RoundedRectangle(cornerRadius: 16)
|
|
.fill(Color(.systemGray6))
|
|
)
|
|
}
|
|
}
|
|
|
|
struct ActionItemView: View {
|
|
let title: String
|
|
let category: String
|
|
let duration: String
|
|
let color: Color
|
|
@State private var isCompleted = false
|
|
|
|
var body: some View {
|
|
HStack(spacing: 12) {
|
|
Button(action: { isCompleted.toggle() }) {
|
|
Image(systemName: isCompleted ? "checkmark.circle.fill" : "circle")
|
|
.font(.title3)
|
|
.foregroundColor(isCompleted ? color : .gray)
|
|
}
|
|
|
|
VStack(alignment: .leading, spacing: 2) {
|
|
Text(title)
|
|
.font(.subheadline)
|
|
.fontWeight(.medium)
|
|
.strikethrough(isCompleted)
|
|
|
|
HStack(spacing: 8) {
|
|
Text(category)
|
|
.font(.caption)
|
|
.padding(.horizontal, 8)
|
|
.padding(.vertical, 2)
|
|
.background(color.opacity(0.2))
|
|
.foregroundColor(color)
|
|
.cornerRadius(8)
|
|
|
|
Text(duration)
|
|
.font(.caption)
|
|
.foregroundColor(.secondary)
|
|
}
|
|
}
|
|
|
|
Spacer()
|
|
}
|
|
.opacity(isCompleted ? 0.6 : 1.0)
|
|
.animation(.easeInOut(duration: 0.2), value: isCompleted)
|
|
}
|
|
}
|
|
|
|
// MARK: - 成长历程
|
|
struct GrowthTimelineCard: View {
|
|
var body: some View {
|
|
VStack(alignment: .leading, spacing: 16) {
|
|
Text("成长历程")
|
|
.font(.headline)
|
|
.fontWeight(.semibold)
|
|
|
|
VStack(alignment: .leading, spacing: 12) {
|
|
TimelineItem(
|
|
date: "今天",
|
|
title: "完成情绪记录",
|
|
description: "记录了平静的心情状态",
|
|
color: .blue,
|
|
isRecent: true
|
|
)
|
|
|
|
TimelineItem(
|
|
date: "昨天",
|
|
title: "课题升级",
|
|
description: "人际关系课题提升到Lv.2",
|
|
color: .green,
|
|
isRecent: true
|
|
)
|
|
|
|
TimelineItem(
|
|
date: "3天前",
|
|
title: "解锁新课题",
|
|
description: "开始学习情绪调节技巧",
|
|
color: .purple,
|
|
isRecent: false
|
|
)
|
|
|
|
TimelineItem(
|
|
date: "1周前",
|
|
title: "达成里程碑",
|
|
description: "连续7天完成情绪记录",
|
|
color: .orange,
|
|
isRecent: false
|
|
)
|
|
}
|
|
}
|
|
.padding()
|
|
.background(
|
|
RoundedRectangle(cornerRadius: 16)
|
|
.fill(Color(.systemGray6))
|
|
)
|
|
}
|
|
}
|
|
|
|
struct TimelineItem: View {
|
|
let date: String
|
|
let title: String
|
|
let description: String
|
|
let color: Color
|
|
let isRecent: Bool
|
|
|
|
var body: some View {
|
|
HStack(spacing: 12) {
|
|
VStack {
|
|
Circle()
|
|
.fill(color)
|
|
.frame(width: 8, height: 8)
|
|
|
|
if !isRecent {
|
|
Rectangle()
|
|
.fill(Color(.systemGray4))
|
|
.frame(width: 1, height: 20)
|
|
}
|
|
}
|
|
|
|
VStack(alignment: .leading, spacing: 2) {
|
|
HStack {
|
|
Text(title)
|
|
.font(.subheadline)
|
|
.fontWeight(.medium)
|
|
|
|
Spacer()
|
|
|
|
Text(date)
|
|
.font(.caption)
|
|
.foregroundColor(.secondary)
|
|
}
|
|
|
|
Text(description)
|
|
.font(.caption)
|
|
.foregroundColor(.secondary)
|
|
.lineLimit(2)
|
|
}
|
|
}
|
|
.opacity(isRecent ? 1.0 : 0.7)
|
|
}
|
|
}
|
|
|
|
// MARK: - GrowthTopic UI扩展
|
|
extension GrowthTopic {
|
|
var icon: String {
|
|
category.icon
|
|
}
|
|
|
|
var color: Color {
|
|
category.color
|
|
}
|
|
}
|
|
|
|
// MARK: - 模拟数据
|
|
let sampleGrowthTopics = [
|
|
GrowthTopic(
|
|
title: "人际关系边界",
|
|
description: "学习建立健康的人际关系边界",
|
|
category: .relationships,
|
|
difficulty: .intermediate,
|
|
progress: 0.7,
|
|
level: 2
|
|
),
|
|
GrowthTopic(
|
|
title: "情绪调节技能",
|
|
description: "掌握情绪识别和调节的核心技能",
|
|
category: .emotionRegulation,
|
|
difficulty: .beginner,
|
|
progress: 0.3,
|
|
level: 1
|
|
),
|
|
GrowthTopic(
|
|
title: "深度自我认知",
|
|
description: "提升对内在世界的认知和理解",
|
|
category: .selfAwareness,
|
|
difficulty: .advanced,
|
|
progress: 0.9,
|
|
level: 3
|
|
),
|
|
GrowthTopic(
|
|
title: "行动力提升",
|
|
description: "培养执行力和目标达成能力",
|
|
category: .lifeGoals,
|
|
difficulty: .beginner,
|
|
progress: 0.4,
|
|
level: 1
|
|
)
|
|
] |