This commit is contained in:
sjk
2025-11-17 14:09:17 +08:00
commit 31e46c5bf6
479 changed files with 109324 additions and 0 deletions

View File

@@ -0,0 +1,89 @@
package database
import (
"fmt"
"log"
"os"
"time"
"github.com/Nanqipro/YunQue-Tech-Projects/ai_english_learning/serve/config"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
var DB *gorm.DB
// InitDatabase 初始化数据库连接
func InitDatabase() {
cfg := config.GlobalConfig
// 构建DSN
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=%s&parseTime=True&loc=Local&multiStatements=true",
cfg.Database.User,
cfg.Database.Password,
cfg.Database.Host,
cfg.Database.Port,
cfg.Database.DBName,
cfg.Database.Charset,
)
// 配置GORM日志 - 使用自定义logger输出详细的SQL日志
gormLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
logger.Config{
SlowThreshold: time.Second, // 慢SQL阈值
LogLevel: logger.Info, // 日志级别Info会显示所有SQL
IgnoreRecordNotFoundError: true, // 忽略ErrRecordNotFound错误
Colorful: true, // 彩色输出
},
)
// 连接数据库
var err error
DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: gormLogger,
DisableForeignKeyConstraintWhenMigrating: true,
})
if err != nil {
log.Fatalf("Failed to connect to database: %v", err)
}
// 获取底层sql.DB对象进行连接池配置
sqlDB, err := DB.DB()
if err != nil {
log.Fatalf("Failed to get underlying sql.DB: %v", err)
}
// 设置连接池参数
sqlDB.SetMaxIdleConns(10) // 最大空闲连接数
sqlDB.SetMaxOpenConns(100) // 最大打开连接数
sqlDB.SetConnMaxLifetime(time.Hour) // 连接最大生存时间
sqlDB.SetConnMaxIdleTime(time.Minute * 30) // 连接最大空闲时间
// 测试连接
if err := sqlDB.Ping(); err != nil {
log.Fatalf("Failed to ping database: %v", err)
}
log.Println("Database connected successfully")
}
// CloseDatabase 关闭数据库连接
func CloseDatabase() {
if DB != nil {
sqlDB, err := DB.DB()
if err != nil {
log.Printf("Failed to get underlying sql.DB: %v", err)
return
}
if err := sqlDB.Close(); err != nil {
log.Printf("Failed to close database: %v", err)
}
}
}
// GetDB 获取数据库实例
func GetDB() *gorm.DB {
return DB
}

View File

@@ -0,0 +1,172 @@
package database
import (
"log"
"os"
"path/filepath"
"strings"
"github.com/Nanqipro/YunQue-Tech-Projects/ai_english_learning/serve/internal/models"
"gorm.io/gorm"
)
// AutoMigrate 自动迁移数据库表结构
func AutoMigrate(db *gorm.DB) error {
log.Println("开始数据库迁移...")
// 用户相关表
err := db.AutoMigrate(
&models.User{},
&models.UserSocialLink{},
&models.UserPreference{},
)
if err != nil {
return err
}
// 词汇相关表迁移由 SQL 脚本维护,避免与既有外键/类型冲突
// (跳过 Vocabulary* / UserVocabularyProgress / VocabularyTest 的 AutoMigrate
// 词汇书相关表(新增)
err = db.AutoMigrate(
&models.VocabularyBook{},
&models.VocabularyBookWord{},
)
if err != nil {
return err
}
// 学习相关表
err = db.AutoMigrate(
&models.Notification{},
&models.StudyPlan{},
&models.StudyPlanRecord{},
&models.ListeningMaterial{},
&models.ListeningRecord{},
&models.ReadingMaterial{},
&models.ReadingRecord{},
&models.WritingPrompt{},
&models.WritingSubmission{},
&models.SpeakingScenario{},
&models.SpeakingRecord{},
)
if err != nil {
return err
}
log.Println("数据库迁移完成")
return nil
}
// CreateIndexes 创建额外的索引
func CreateIndexes(db *gorm.DB) error {
log.Println("开始创建索引...")
// 创建索引的辅助函数
createIndexIfNotExists := func(indexName, tableName, columns string) {
// 检查索引是否存在
var count int64
db.Raw("SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema = DATABASE() AND table_name = ? AND index_name = ?", tableName, indexName).Scan(&count)
if count == 0 {
// 索引不存在,创建索引
sql := "CREATE INDEX " + indexName + " ON " + tableName + "(" + columns + ")"
result := db.Exec(sql)
if result.Error != nil {
log.Printf("创建索引 %s 失败: %v", indexName, result.Error)
}
}
}
// 用户表索引
createIndexIfNotExists("idx_users_email_verified", "ai_users", "email_verified")
createIndexIfNotExists("idx_users_status", "ai_users", "status")
createIndexIfNotExists("idx_users_created_at", "ai_users", "created_at")
// 词汇表索引
createIndexIfNotExists("idx_vocabulary_level", "ai_vocabulary", "level")
createIndexIfNotExists("idx_vocabulary_frequency", "ai_vocabulary", "frequency")
createIndexIfNotExists("idx_vocabulary_is_active", "ai_vocabulary", "is_active")
// 用户词汇进度索引
createIndexIfNotExists("idx_user_vocabulary_progress_user_vocab", "ai_user_vocabulary_progress", "user_id, vocabulary_id")
createIndexIfNotExists("idx_user_vocabulary_progress_mastery", "ai_user_vocabulary_progress", "mastery_level")
createIndexIfNotExists("idx_user_vocabulary_progress_next_review", "ai_user_vocabulary_progress", "next_review_at")
// 学习记录索引
createIndexIfNotExists("idx_listening_records_user_material", "ai_listening_records", "user_id, material_id")
createIndexIfNotExists("idx_reading_records_user_material", "ai_reading_records", "user_id, material_id")
createIndexIfNotExists("idx_writing_submissions_user_prompt", "ai_writing_submissions", "user_id, prompt_id")
createIndexIfNotExists("idx_speaking_records_user_scenario", "ai_speaking_records", "user_id, scenario_id")
// 材料表索引
createIndexIfNotExists("idx_listening_materials_level", "ai_listening_materials", "level")
createIndexIfNotExists("idx_reading_materials_level", "ai_reading_materials", "level")
createIndexIfNotExists("idx_writing_prompts_level", "ai_writing_prompts", "level")
createIndexIfNotExists("idx_speaking_scenarios_level", "ai_speaking_scenarios", "level")
log.Println("索引创建完成")
return nil
}
// ApplyMergedSchemaIfNeeded 读取并执行合并后的SQL脚本用于创建视图、触发器及扩展表
func ApplyMergedSchemaIfNeeded(db *gorm.DB) error {
// 检查一个扩展表是否存在,作为是否需要执行脚本的依据
var count int64
db.Raw("SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'ai_vocabulary_books'").Scan(&count)
if count > 0 {
// 已存在扩展结构,跳过
return nil
}
// 读取脚本文件(从 serve 目录运行,脚本位于 ../docs/
candidates := []string{
"../docs/database_schema_merged.sql",
"../docs/database_schema.sql",
}
var content []byte
var readErr error
for _, p := range candidates {
abs, _ := filepath.Abs(p)
content, readErr = os.ReadFile(abs)
if readErr == nil {
break
}
}
if readErr != nil {
log.Printf("读取数据库脚本失败: %v", readErr)
return nil
}
sql := string(content)
// 移除 DELIMITER 指令并将触发器结束符 // 转为 ;
lines := strings.Split(sql, "\n")
var cleaned []string
for _, line := range lines {
trimmed := strings.TrimSpace(line)
if strings.HasPrefix(trimmed, "DELIMITER") {
continue
}
// 将以 // 结尾的行替换为 ;
if strings.HasSuffix(trimmed, "//") {
cleaned = append(cleaned, strings.TrimSuffix(line, "//")+";")
continue
}
cleaned = append(cleaned, line)
}
cleanedSQL := strings.Join(cleaned, "\n")
// 关闭外键检查以避免初始化时的顺序问题
if err := db.Exec("SET FOREIGN_KEY_CHECKS=0;").Error; err != nil {
log.Printf("关闭外键检查失败: %v", err)
}
// 执行脚本(依赖 multiStatements=true
if err := db.Exec(cleanedSQL).Error; err != nil {
log.Printf("执行合并SQL失败: %v", err)
}
// 恢复外键检查
if err := db.Exec("SET FOREIGN_KEY_CHECKS=1;").Error; err != nil {
log.Printf("开启外键检查失败: %v", err)
}
return nil
}

View File

@@ -0,0 +1,553 @@
package database
import (
"log"
"time"
"github.com/Nanqipro/YunQue-Tech-Projects/ai_english_learning/serve/internal/models"
"github.com/Nanqipro/YunQue-Tech-Projects/ai_english_learning/serve/internal/utils"
"gorm.io/gorm"
)
// stringPtr 返回字符串指针
func stringPtr(s string) *string {
return &s
}
// SeedData 初始化种子数据
func SeedData(db *gorm.DB) error {
log.Println("开始初始化种子数据...")
// 检查是否已有数据
var userCount int64
db.Model(&models.User{}).Count(&userCount)
if userCount > 0 {
log.Println("数据库已有数据,跳过种子数据初始化")
return nil
}
// 创建词汇分类
if err := createVocabularyCategories(db); err != nil {
return err
}
// 创建示例词汇
if err := createSampleVocabularies(db); err != nil {
return err
}
// 创建测试用户
if err := createTestUsers(db); err != nil {
return err
}
// 创建听力材料
if err := createListeningMaterials(db); err != nil {
return err
}
// 创建阅读材料
if err := createReadingMaterials(db); err != nil {
return err
}
// 创建写作提示
if err := createWritingPrompts(db); err != nil {
return err
}
// 创建口语场景
if err := createSpeakingScenarios(db); err != nil {
return err
}
log.Println("种子数据初始化完成")
return nil
}
// createVocabularyCategories 创建词汇分类
func createVocabularyCategories(db *gorm.DB) error {
categories := []models.VocabularyCategory{
{
ID: utils.GenerateUUID(),
Name: "日常生活",
Description: stringPtr("日常生活中常用的词汇"),
Level: "beginner",
IsActive: true,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
},
{
ID: utils.GenerateUUID(),
Name: "商务英语",
Description: stringPtr("商务场景中使用的专业词汇"),
Level: "intermediate",
IsActive: true,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
},
{
ID: utils.GenerateUUID(),
Name: "学术英语",
Description: stringPtr("学术研究和论文写作中的词汇"),
Level: "advanced",
IsActive: true,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
},
{
ID: utils.GenerateUUID(),
Name: "旅游英语",
Description: stringPtr("旅游出行相关的实用词汇"),
Level: "beginner",
IsActive: true,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
},
{
ID: utils.GenerateUUID(),
Name: "科技英语",
Description: stringPtr("科技和互联网相关词汇"),
Level: "intermediate",
IsActive: true,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
},
}
for _, category := range categories {
if err := db.Create(&category).Error; err != nil {
return err
}
}
log.Println("词汇分类创建完成")
return nil
}
// createSampleVocabularies 创建示例词汇
func createSampleVocabularies(db *gorm.DB) error {
// 获取第一个分类ID
var category models.VocabularyCategory
if err := db.First(&category).Error; err != nil {
return err
}
vocabularies := []struct {
Word string
Phonetic string
Level string
Frequency int
Definitions []models.VocabularyDefinition
Examples []models.VocabularyExample
}{
{
Word: "hello",
Phonetic: "/həˈloʊ/",
Level: "beginner",
Frequency: 100,
Definitions: []models.VocabularyDefinition{
{
PartOfSpeech: "interjection",
Definition: "used as a greeting or to begin a phone conversation",
Translation: "你好",
SortOrder: 0,
CreatedAt: time.Now(),
},
},
Examples: []models.VocabularyExample{
{
Example: "Hello, how are you?",
Translation: "你好,你好吗?",
SortOrder: 0,
CreatedAt: time.Now(),
},
},
},
{
Word: "world",
Phonetic: "/wɜːrld/",
Level: "beginner",
Frequency: 95,
Definitions: []models.VocabularyDefinition{
{
PartOfSpeech: "noun",
Definition: "the earth, together with all of its countries and peoples",
Translation: "世界",
SortOrder: 0,
CreatedAt: time.Now(),
},
},
Examples: []models.VocabularyExample{
{
Example: "The world is a beautiful place.",
Translation: "世界是一个美丽的地方。",
SortOrder: 0,
CreatedAt: time.Now(),
},
},
},
{
Word: "learn",
Phonetic: "/lɜːrn/",
Level: "beginner",
Frequency: 90,
Definitions: []models.VocabularyDefinition{
{
PartOfSpeech: "verb",
Definition: "acquire knowledge of or skill in something",
Translation: "学习",
SortOrder: 0,
CreatedAt: time.Now(),
},
},
Examples: []models.VocabularyExample{
{
Example: "I want to learn English.",
Translation: "我想学习英语。",
SortOrder: 0,
CreatedAt: time.Now(),
},
},
},
{
Word: "study",
Phonetic: "/ˈstʌdi/",
Level: "beginner",
Frequency: 85,
Definitions: []models.VocabularyDefinition{
{
PartOfSpeech: "verb",
Definition: "devote time and attention to acquiring knowledge",
Translation: "学习,研究",
SortOrder: 0,
CreatedAt: time.Now(),
},
},
Examples: []models.VocabularyExample{
{
Example: "She studies hard every day.",
Translation: "她每天都努力学习。",
SortOrder: 0,
CreatedAt: time.Now(),
},
},
},
{
Word: "practice",
Phonetic: "/ˈpræktɪs/",
Level: "intermediate",
Frequency: 80,
Definitions: []models.VocabularyDefinition{
{
PartOfSpeech: "verb",
Definition: "perform an activity repeatedly to improve one's skill",
Translation: "练习",
SortOrder: 0,
CreatedAt: time.Now(),
},
},
Examples: []models.VocabularyExample{
{
Example: "Practice makes perfect.",
Translation: "熟能生巧。",
SortOrder: 0,
CreatedAt: time.Now(),
},
},
},
}
for _, vocabData := range vocabularies {
// 检查词汇是否已存在
var existingVocab models.Vocabulary
if err := db.Where("word = ?", vocabData.Word).First(&existingVocab).Error; err == nil {
// 词汇已存在,跳过
log.Printf("词汇 '%s' 已存在,跳过创建", vocabData.Word)
continue
}
// 创建词汇
vocab := models.Vocabulary{
Word: vocabData.Word,
Phonetic: &vocabData.Phonetic,
Level: vocabData.Level,
Frequency: vocabData.Frequency,
IsActive: true,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
if err := db.Create(&vocab).Error; err != nil {
return err
}
// 关联分类
if err := db.Model(&vocab).Association("Categories").Append(&category); err != nil {
return err
}
// 创建定义
for _, def := range vocabData.Definitions {
def.VocabularyID = vocab.ID
if err := db.Create(&def).Error; err != nil {
return err
}
}
// 创建例句
for _, example := range vocabData.Examples {
example.VocabularyID = vocab.ID
if err := db.Create(&example).Error; err != nil {
return err
}
}
}
log.Println("示例词汇创建完成")
return nil
}
// createTestUsers 创建测试用户
func createTestUsers(db *gorm.DB) error {
users := []models.User{
{
ID: 0, // 让数据库自动生成
Username: "testuser",
Email: "test@example.com",
PasswordHash: "$2a$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi", // password
Nickname: stringPtr("测试用户"),
Avatar: stringPtr("https://via.placeholder.com/150"),
Gender: stringPtr("other"),
BirthDate: nil,
Location: stringPtr("北京"),
Bio: stringPtr("这是一个测试用户"),
EmailVerified: true,
Status: "active",
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
},
{
ID: 0, // 让数据库自动生成
Username: "demo",
Email: "demo@example.com",
PasswordHash: "$2a$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi", // password
Nickname: stringPtr("演示用户"),
Avatar: stringPtr("https://via.placeholder.com/150"),
Gender: stringPtr("other"),
BirthDate: nil,
Location: stringPtr("上海"),
Bio: stringPtr("这是一个演示用户"),
EmailVerified: true,
Status: "active",
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
},
}
for _, user := range users {
if err := db.Create(&user).Error; err != nil {
return err
}
// 创建用户偏好设置
preference := models.UserPreference{
ID: 0, // 让数据库自动生成
UserID: user.ID,
DailyGoal: 30,
WeeklyGoal: 210,
ReminderEnabled: true,
ReminderTime: stringPtr("09:00:00"),
DifficultyLevel: "intermediate",
LearningMode: "casual",
PreferredTopics: stringPtr("[\"vocabulary\", \"listening\"]"),
NotificationSettings: stringPtr("{\"email\": true, \"push\": true}"),
PrivacySettings: stringPtr("{\"profile_public\": false}"),
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
if err := db.Create(&preference).Error; err != nil {
return err
}
}
log.Println("测试用户创建完成")
return nil
}
// createListeningMaterials 创建听力材料
func createListeningMaterials(db *gorm.DB) error {
materials := []models.ListeningMaterial{
{
ID: utils.GenerateUUID(),
Title: "Daily Conversation",
Description: stringPtr("Basic daily conversation practice"),
Level: "beginner",
Duration: 180, // 3 minutes
AudioURL: "https://example.com/audio/daily-conversation.mp3",
Transcript: stringPtr("A: Hello, how are you today? B: I'm fine, thank you. How about you?"),
IsActive: true,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
},
{
ID: utils.GenerateUUID(),
Title: "Business Meeting",
Description: stringPtr("Business meeting discussion"),
Level: "intermediate",
Duration: 300, // 5 minutes
AudioURL: "https://example.com/audio/business-meeting.mp3",
Transcript: stringPtr("Let's discuss the quarterly report and our future plans."),
IsActive: true,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
},
}
for _, material := range materials {
if err := db.Create(&material).Error; err != nil {
return err
}
}
log.Println("听力材料创建完成")
return nil
}
// intPtr 返回整数指针
func intPtr(i int) *int {
return &i
}
// createReadingMaterials 创建阅读材料
func createReadingMaterials(db *gorm.DB) error {
materials := []models.ReadingMaterial{
{
ID: utils.GenerateUUID(),
Title: "The Benefits of Reading",
Content: "Reading is one of the most beneficial activities for the human mind. It improves vocabulary, enhances critical thinking, and provides entertainment.",
Level: "beginner",
WordCount: 25,
Summary: stringPtr("这是一篇关于阅读益处的文章"),
Source: stringPtr("Education Weekly"),
Author: stringPtr("Reading Expert"),
Tags: stringPtr("[\"reading\", \"education\"]"),
IsActive: true,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
},
{
ID: utils.GenerateUUID(),
Title: "Climate Change and Technology",
Content: "Climate change represents one of the most pressing challenges of our time. Technology plays a crucial role in both contributing to and solving environmental problems.",
Level: "intermediate",
WordCount: 30,
Summary: stringPtr("这是一篇关于气候变化与科技的文章"),
Source: stringPtr("Science Today"),
Author: stringPtr("Climate Researcher"),
Tags: stringPtr("[\"climate\", \"technology\"]"),
IsActive: true,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
},
}
for _, material := range materials {
if err := db.Create(&material).Error; err != nil {
return err
}
}
log.Println("阅读材料创建完成")
return nil
}
// createWritingPrompts 创建写作提示
func createWritingPrompts(db *gorm.DB) error {
prompts := []models.WritingPrompt{
{
ID: utils.GenerateUUID(),
Title: "My Daily Routine",
Prompt: "Describe your daily routine from morning to evening. Include what you do, when you do it, and why.",
Level: "beginner",
MinWords: intPtr(100),
MaxWords: intPtr(200),
TimeLimit: intPtr(1800), // 30 minutes
Instructions: stringPtr("Write a clear and descriptive essay"),
Tags: stringPtr("[\"daily\", \"routine\"]"),
SampleAnswer: stringPtr("Every morning, I wake up at 7 AM and start my day..."),
Rubric: stringPtr("{\"grammar\": 25, \"vocabulary\": 25, \"coherence\": 25, \"content\": 25}"),
IsActive: true,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
},
{
ID: utils.GenerateUUID(),
Title: "The Impact of Social Media",
Prompt: "Discuss the positive and negative impacts of social media on modern society. Provide specific examples and your personal opinion.",
Level: "intermediate",
MinWords: intPtr(250),
MaxWords: intPtr(400),
TimeLimit: intPtr(2700), // 45 minutes
Instructions: stringPtr("Write a balanced argumentative essay"),
Tags: stringPtr("[\"social media\", \"society\"]"),
SampleAnswer: stringPtr("Social media has transformed how we communicate..."),
Rubric: stringPtr("{\"grammar\": 30, \"vocabulary\": 20, \"coherence\": 25, \"content\": 25}"),
IsActive: true,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
},
}
for _, prompt := range prompts {
if err := db.Create(&prompt).Error; err != nil {
return err
}
}
log.Println("写作提示创建完成")
return nil
}
// createSpeakingScenarios 创建口语场景
func createSpeakingScenarios(db *gorm.DB) error {
scenarios := []models.SpeakingScenario{
{
ID: utils.GenerateUUID(),
Title: "Restaurant Ordering",
Description: "You are at a restaurant and want to order food. The waiter will take your order.",
Level: "beginner",
Context: stringPtr("You are at a restaurant with friends"),
Tags: stringPtr("[\"restaurant\", \"food\"]"),
Dialogue: stringPtr("[{\"speaker\": \"waiter\", \"text\": \"Good evening, welcome to our restaurant!\"}]"),
KeyPhrases: stringPtr("[\"I'd like to order\", \"Could I have\", \"The bill, please\"]"),
IsActive: true,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
},
{
ID: utils.GenerateUUID(),
Title: "Job Interview",
Description: "You are in a job interview for a position you really want. Answer the interviewer's questions confidently.",
Level: "intermediate",
Context: stringPtr("You are applying for a job"),
Tags: stringPtr("[\"interview\", \"job\"]"),
Dialogue: stringPtr("[{\"speaker\": \"interviewer\", \"text\": \"Tell me about yourself\"}]"),
KeyPhrases: stringPtr("[\"I have experience in\", \"My strengths are\", \"I'm interested in\"]"),
IsActive: true,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
},
}
for _, scenario := range scenarios {
if err := db.Create(&scenario).Error; err != nil {
return err
}
}
log.Println("口语场景创建完成")
return nil
}

View File

@@ -0,0 +1,56 @@
package database
import (
"errors"
"github.com/Nanqipro/YunQue-Tech-Projects/ai_english_learning/serve/internal/model"
)
type UserRepository struct {
// 实际项目中这里会有数据库连接
}
func NewUserRepository() *UserRepository {
return &UserRepository{}
}
// 创建用户
func (r *UserRepository) Create(user *model.User) (string, error) {
// 实际项目中这里会执行数据库插入操作
// 模拟生成用户ID
user.ID = "user-123"
return user.ID, nil
}
// 根据ID获取用户
func (r *UserRepository) GetByID(id string) (*model.User, error) {
// 实际项目中这里会执行数据库查询操作
if id == "user-123" {
return &model.User{
ID: id,
Username: "testuser",
Email: "test@example.com",
Avatar: "",
}, nil
}
return nil, errors.New("用户不存在")
}
// 根据邮箱获取用户
func (r *UserRepository) GetByEmail(email string) (*model.User, error) {
// 实际项目中这里会执行数据库查询操作
if email == "test@example.com" {
return &model.User{
ID: "user-123",
Username: "testuser",
Email: email,
Password: "password123", // 实际项目中密码应该是加密的
}, nil
}
return nil, errors.New("用户不存在")
}
// 更新用户信息
func (r *UserRepository) Update(user *model.User) error {
// 实际项目中这里会执行数据库更新操作
return nil
}