feat(schedule): add course table screens and navigation
Add complete schedule functionality including: - Schedule screen with weekly course table view - Course detail screen with transparent modal presentation - New ScheduleStack navigator integrated into main tab bar - Schedule service for API interactions - Type definitions for course entities Also includes bug fixes for group invite/request handlers to include required groupId parameter.
This commit is contained in:
@@ -15,18 +15,19 @@ import (
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Server ServerConfig `mapstructure:"server"`
|
||||
Database DatabaseConfig `mapstructure:"database"`
|
||||
Redis RedisConfig `mapstructure:"redis"`
|
||||
Cache CacheConfig `mapstructure:"cache"`
|
||||
S3 S3Config `mapstructure:"s3"`
|
||||
JWT JWTConfig `mapstructure:"jwt"`
|
||||
Log LogConfig `mapstructure:"log"`
|
||||
RateLimit RateLimitConfig `mapstructure:"rate_limit"`
|
||||
Upload UploadConfig `mapstructure:"upload"`
|
||||
Gorse GorseConfig `mapstructure:"gorse"`
|
||||
OpenAI OpenAIConfig `mapstructure:"openai"`
|
||||
Email EmailConfig `mapstructure:"email"`
|
||||
Server ServerConfig `mapstructure:"server"`
|
||||
Database DatabaseConfig `mapstructure:"database"`
|
||||
Redis RedisConfig `mapstructure:"redis"`
|
||||
Cache CacheConfig `mapstructure:"cache"`
|
||||
S3 S3Config `mapstructure:"s3"`
|
||||
JWT JWTConfig `mapstructure:"jwt"`
|
||||
Log LogConfig `mapstructure:"log"`
|
||||
RateLimit RateLimitConfig `mapstructure:"rate_limit"`
|
||||
Upload UploadConfig `mapstructure:"upload"`
|
||||
Gorse GorseConfig `mapstructure:"gorse"`
|
||||
OpenAI OpenAIConfig `mapstructure:"openai"`
|
||||
Email EmailConfig `mapstructure:"email"`
|
||||
ConversationCache ConversationCacheConfig `mapstructure:"conversation_cache"`
|
||||
}
|
||||
|
||||
type ServerConfig struct {
|
||||
@@ -173,6 +174,73 @@ type EmailConfig struct {
|
||||
Timeout int `mapstructure:"timeout"`
|
||||
}
|
||||
|
||||
// ConversationCacheConfig 会话缓存配置
|
||||
type ConversationCacheConfig struct {
|
||||
// TTL 配置
|
||||
DetailTTL string `mapstructure:"detail_ttl"`
|
||||
ListTTL string `mapstructure:"list_ttl"`
|
||||
ParticipantTTL string `mapstructure:"participant_ttl"`
|
||||
UnreadTTL string `mapstructure:"unread_ttl"`
|
||||
|
||||
// 消息缓存配置
|
||||
MessageDetailTTL string `mapstructure:"message_detail_ttl"`
|
||||
MessageListTTL string `mapstructure:"message_list_ttl"`
|
||||
MessageIndexTTL string `mapstructure:"message_index_ttl"`
|
||||
MessageCountTTL string `mapstructure:"message_count_ttl"`
|
||||
|
||||
// 批量写入配置
|
||||
BatchInterval string `mapstructure:"batch_interval"`
|
||||
BatchThreshold int `mapstructure:"batch_threshold"`
|
||||
BatchMaxSize int `mapstructure:"batch_max_size"`
|
||||
BufferMaxSize int `mapstructure:"buffer_max_size"`
|
||||
}
|
||||
|
||||
// ConversationCacheSettings 会话缓存运行时配置(用于传递给 cache 包)
|
||||
type ConversationCacheSettings struct {
|
||||
DetailTTL time.Duration
|
||||
ListTTL time.Duration
|
||||
ParticipantTTL time.Duration
|
||||
UnreadTTL time.Duration
|
||||
MessageDetailTTL time.Duration
|
||||
MessageListTTL time.Duration
|
||||
MessageIndexTTL time.Duration
|
||||
MessageCountTTL time.Duration
|
||||
BatchInterval time.Duration
|
||||
BatchThreshold int
|
||||
BatchMaxSize int
|
||||
BufferMaxSize int
|
||||
}
|
||||
|
||||
// ToSettings 将 ConversationCacheConfig 转换为 ConversationCacheSettings
|
||||
func (c *ConversationCacheConfig) ToSettings() *ConversationCacheSettings {
|
||||
return &ConversationCacheSettings{
|
||||
DetailTTL: parseDuration(c.DetailTTL, 5*time.Minute),
|
||||
ListTTL: parseDuration(c.ListTTL, 60*time.Second),
|
||||
ParticipantTTL: parseDuration(c.ParticipantTTL, 5*time.Minute),
|
||||
UnreadTTL: parseDuration(c.UnreadTTL, 30*time.Second),
|
||||
MessageDetailTTL: parseDuration(c.MessageDetailTTL, 30*time.Minute),
|
||||
MessageListTTL: parseDuration(c.MessageListTTL, 5*time.Minute),
|
||||
MessageIndexTTL: parseDuration(c.MessageIndexTTL, 30*time.Minute),
|
||||
MessageCountTTL: parseDuration(c.MessageCountTTL, 30*time.Minute),
|
||||
BatchInterval: parseDuration(c.BatchInterval, 5*time.Second),
|
||||
BatchThreshold: c.BatchThreshold,
|
||||
BatchMaxSize: c.BatchMaxSize,
|
||||
BufferMaxSize: c.BufferMaxSize,
|
||||
}
|
||||
}
|
||||
|
||||
// parseDuration 解析持续时间字符串,如果解析失败则返回默认值
|
||||
func parseDuration(s string, defaultVal time.Duration) time.Duration {
|
||||
if s == "" {
|
||||
return defaultVal
|
||||
}
|
||||
d, err := time.ParseDuration(s)
|
||||
if err != nil {
|
||||
return defaultVal
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
func Load(configPath string) (*Config, error) {
|
||||
viper.SetConfigFile(configPath)
|
||||
viper.SetConfigType("yaml")
|
||||
@@ -259,6 +327,19 @@ func Load(configPath string) (*Config, error) {
|
||||
viper.SetDefault("email.use_tls", true)
|
||||
viper.SetDefault("email.insecure_skip_verify", false)
|
||||
viper.SetDefault("email.timeout", 15)
|
||||
// ConversationCache 默认值
|
||||
viper.SetDefault("conversation_cache.detail_ttl", "5m")
|
||||
viper.SetDefault("conversation_cache.list_ttl", "60s")
|
||||
viper.SetDefault("conversation_cache.participant_ttl", "5m")
|
||||
viper.SetDefault("conversation_cache.unread_ttl", "30s")
|
||||
viper.SetDefault("conversation_cache.message_detail_ttl", "30m")
|
||||
viper.SetDefault("conversation_cache.message_list_ttl", "5m")
|
||||
viper.SetDefault("conversation_cache.message_index_ttl", "30m")
|
||||
viper.SetDefault("conversation_cache.message_count_ttl", "30m")
|
||||
viper.SetDefault("conversation_cache.batch_interval", "5s")
|
||||
viper.SetDefault("conversation_cache.batch_threshold", 100)
|
||||
viper.SetDefault("conversation_cache.batch_max_size", 500)
|
||||
viper.SetDefault("conversation_cache.buffer_max_size", 10000)
|
||||
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
return nil, fmt.Errorf("failed to read config: %w", err)
|
||||
|
||||
Reference in New Issue
Block a user