首次提交:初始化项目代码

This commit is contained in:
sunct
2026-07-31 14:44:48 +08:00
commit a4fe393571
119 changed files with 29105 additions and 0 deletions
+87
View File
@@ -0,0 +1,87 @@
package bootstrap
import (
"context"
"fmt"
"os"
"resume-platform/internal/handler"
"resume-platform/internal/router"
"resume-platform/internal/security"
"resume-platform/pkg/config"
"resume-platform/pkg/logger"
)
func Run(ctx context.Context) error {
cfg, err := config.LoadConfig()
if err != nil {
return fmt.Errorf("failed to load config: %w", err)
}
if err := initLogger(cfg); err != nil {
return fmt.Errorf("failed to initialize logger: %w", err)
}
if err := initDataDir(); err != nil {
return fmt.Errorf("failed to initialize data directory: %w", err)
}
logger.Infof("Configuration loaded - AdminPath: %s, Mode: %s", cfg.Auth.AdminPath, cfg.Server.Mode)
container, err := NewServiceContainer(cfg)
if err != nil {
return fmt.Errorf("failed to initialize service container: %w", err)
}
handler.SetResumeRepository(container.Repo)
handler.LoadTokens()
if err := initSecurity(cfg); err != nil {
return fmt.Errorf("failed to initialize security: %w", err)
}
if err := container.InitResumeAgent(ctx, cfg); err != nil {
logger.Warnf("Failed to initialize Resume Agent: %v", err)
}
if err := startServer(ctx, cfg, container); err != nil {
return fmt.Errorf("failed to start server: %w", err)
}
return nil
}
func initLogger(cfg *config.Config) error {
return logger.Init(logger.Config{
Level: cfg.Log.Level,
Output: cfg.Log.Output,
})
}
func initDataDir() error {
return os.MkdirAll("./data", 0755)
}
func initSecurity(cfg *config.Config) error {
security.InitCaptcha(160, 50)
return nil
}
func startServer(ctx context.Context, cfg *config.Config, container *ServiceContainer) error {
r := router.NewRouter(
container.ResumeHandler,
container.AdminHandler,
container.AIHandler,
container.DocumentHandler,
container.ChatHandler,
container.IMHandler,
container.KnowledgeHandler,
cfg,
)
engine := r.Setup()
addr := fmt.Sprintf("%s:%d", cfg.Server.Host, cfg.Server.Port)
logger.Infof("Server starting on %s", addr)
return engine.Run(addr)
}
+205
View File
@@ -0,0 +1,205 @@
package bootstrap
import (
"context"
"resume-platform/internal/agent"
aiprovider "resume-platform/internal/ai"
"resume-platform/internal/handler"
"resume-platform/internal/repository"
"resume-platform/internal/security"
"resume-platform/internal/service/chat"
"resume-platform/internal/service/document"
"resume-platform/internal/service/knowledge"
"resume-platform/internal/service/portfolio"
"resume-platform/internal/service/quiz"
"resume-platform/internal/service/resume"
"resume-platform/internal/service/system"
"resume-platform/internal/service/user"
aiservice "resume-platform/internal/service/ai"
"resume-platform/pkg/config"
)
type ServiceContainer struct {
// Repository
Repo repository.ResumeRepository
// Core Services
ResumeService resume.ResumeService
SystemService system.SystemService
DocumentService document.DocumentService
UserService user.UserService
PortfolioService portfolio.PortfolioService
QuizService quiz.QuizService
// AI Services
AIProvider aiprovider.Provider
AIService *aiservice.AIService
QuestionGenerator *aiservice.QuestionGeneratorService
ResumeGenerator *resume.ResumeGeneratorService
ResumeAgent *agent.ResumeAgent
// Knowledge Services
EmbeddingService *knowledge.EmbeddingService
VectorService *knowledge.VectorService
KnowledgeBaseService *knowledge.KnowledgeBaseService
RAGService *knowledge.RAGService
// Chat Services
ChatService chat.ChatService
IMService *chat.IMService
// Handlers
ResumeHandler *handler.ResumeHandler
AdminHandler *handler.AdminHandler
AIHandler *handler.AIHandler
DocumentHandler *handler.DocumentHandler
ChatHandler *handler.ChatHandler
IMHandler *handler.IMHandler
KnowledgeHandler *handler.KnowledgeHandler
}
func NewServiceContainer(cfg *config.Config) (*ServiceContainer, error) {
container := &ServiceContainer{}
if err := container.initRepository(cfg); err != nil {
return nil, err
}
if err := container.initAIServices(cfg); err != nil {
return nil, err
}
if err := container.initCoreServices(cfg); err != nil {
return nil, err
}
if err := container.initKnowledgeServices(cfg); err != nil {
return nil, err
}
if err := container.initChatServices(cfg); err != nil {
return nil, err
}
if err := container.initHandlers(cfg); err != nil {
return nil, err
}
return container, nil
}
func (c *ServiceContainer) initRepository(cfg *config.Config) error {
dbPath := cfg.Database.Path
if dbPath == "" {
dbPath = "./data/resume.db"
}
repo, err := repository.NewSQLiteRepository(dbPath, cfg.Database.Password)
if err != nil {
return err
}
c.Repo = repo
return nil
}
func (c *ServiceContainer) initCoreServices(cfg *config.Config) error {
c.ResumeService = resume.NewResumeService(c.Repo)
c.SystemService = system.NewSystemService(c.Repo)
if _, err := c.ResumeService.InitDefaultResume(); err != nil {
return err
}
if err := c.SystemService.InitDefaultMenus(); err != nil {
return err
}
c.DocumentService = document.NewDocumentService(c.Repo, c.ResumeGenerator)
c.UserService = user.NewUserService(c.Repo)
c.PortfolioService = portfolio.NewPortfolioService(c.Repo)
c.QuizService = quiz.NewQuizService(c.Repo)
return nil
}
func (c *ServiceContainer) initAIServices(cfg *config.Config) error {
if !cfg.AI.Enabled {
return nil
}
provider, err := aiprovider.NewProvider(&cfg.AI)
if err != nil {
return err
}
c.AIProvider = provider
c.AIService = aiservice.NewAIService(provider)
c.QuestionGenerator = aiservice.NewQuestionGeneratorService(provider)
c.ResumeGenerator = resume.NewResumeGeneratorService(provider)
return nil
}
func (c *ServiceContainer) initKnowledgeServices(cfg *config.Config) error {
if c.AIProvider == nil {
return nil
}
c.EmbeddingService = knowledge.NewEmbeddingService(c.AIProvider, c.Repo)
c.VectorService = knowledge.NewVectorService(c.EmbeddingService, c.Repo)
c.KnowledgeBaseService = knowledge.NewKnowledgeBaseService(c.EmbeddingService, c.VectorService, c.Repo)
c.RAGService = knowledge.NewRAGService(c.AIProvider, c.KnowledgeBaseService)
c.DocumentService = document.NewDocumentServiceWithKnowledge(c.Repo, c.ResumeGenerator, c.KnowledgeBaseService)
return nil
}
func (c *ServiceContainer) initChatServices(cfg *config.Config) error {
c.ChatService = chat.NewChatService(c.Repo, c.AIService)
c.IMService = chat.NewIMService(c.AIProvider, c.ResumeAgent)
return nil
}
func (c *ServiceContainer) initHandlers(cfg *config.Config) error {
c.ResumeHandler = handler.NewResumeHandler(
c.ResumeService,
c.DocumentService,
c.UserService,
c.PortfolioService,
c.QuizService,
c.SystemService,
)
rateLimiter := security.NewRateLimiter(cfg.Auth.MaxLoginAttempts, cfg.Auth.LockoutDuration)
c.AdminHandler = handler.NewAdminHandler(cfg, rateLimiter)
c.AIHandler = handler.NewAIHandler(c.AIService, c.QuestionGenerator, nil, c.ResumeService, c.QuizService)
c.DocumentHandler = handler.NewDocumentHandler(c.DocumentService)
c.ChatHandler = handler.NewChatHandler(c.ChatService)
c.IMHandler = handler.NewIMHandler(c.IMService)
if c.KnowledgeBaseService != nil {
c.KnowledgeHandler = handler.NewKnowledgeHandler(c.KnowledgeBaseService, c.RAGService)
}
return nil
}
func (c *ServiceContainer) InitResumeAgent(ctx context.Context, cfg *config.Config) error {
if !cfg.AI.Enabled || c.AIProvider == nil {
return nil
}
agent, err := agent.NewResumeAgent(ctx, &cfg.AI)
if err != nil {
return err
}
c.ResumeAgent = agent
c.AIHandler.SetResumeAgent(agent)
return nil
}