You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
8.3 KiB
8.3 KiB
02-数据库和模型设计
目标
实现数据库连接模块和所有数据模型定义,支持多数据库切换。
前置要求
- 项目结构已初始化
- 依赖已安装
实施步骤
步骤 1:创建配置加载模块
创建 server/internal/config/config.go:
package config
import (
"github.com/spf13/viper"
)
type Config struct {
Server ServerConfig
Database DatabaseConfig
JWT JWTConfig
AI AIConfig
}
type ServerConfig struct {
Port int
Mode string
}
type DatabaseConfig struct {
Driver string
SQLite SQLiteConfig
Postgres PostgresConfig
MySQL MySQLConfig
}
type SQLiteConfig struct {
Path string
}
type PostgresConfig struct {
Host string
Port int
User string
Password string
DBName string
}
type MySQLConfig struct {
Host string
Port int
User string
Password string
DBName string
}
type JWTConfig struct {
Secret string
ExpireHours int `mapstructure:"expire_hours"`
}
type AIConfig struct {
Provider string
APIKey string `mapstructure:"api_key"`
BaseURL string `mapstructure:"base_url"`
}
var AppConfig *Config
func LoadConfig(path string) error {
viper.SetConfigFile(path)
if err := viper.ReadInConfig(); err != nil {
return err
}
AppConfig = &Config{}
return viper.Unmarshal(AppConfig)
}
步骤 2:创建数据库连接模块
创建 server/internal/database/database.go:
package database
import (
"fmt"
"health-ai/internal/config"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
var DB *gorm.DB
func InitDatabase(cfg *config.DatabaseConfig) error {
var err error
switch cfg.Driver {
case "sqlite":
DB, err = gorm.Open(sqlite.Open(cfg.SQLite.Path), &gorm.Config{})
case "postgres":
// TODO: 添加 PostgreSQL 支持
// dsn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable",
// cfg.Postgres.Host, cfg.Postgres.Port, cfg.Postgres.User, cfg.Postgres.Password, cfg.Postgres.DBName)
// DB, err = gorm.Open(postgres.Open(dsn), &gorm.Config{})
return fmt.Errorf("postgres driver not implemented yet")
case "mysql":
// TODO: 添加 MySQL 支持
return fmt.Errorf("mysql driver not implemented yet")
default:
return fmt.Errorf("unsupported database driver: %s", cfg.Driver)
}
return err
}
func AutoMigrate(models ...interface{}) error {
return DB.AutoMigrate(models...)
}
步骤 3:创建数据模型
创建 server/internal/model/user.go:
package model
import (
"time"
"gorm.io/gorm"
)
// User 用户表
type User struct {
gorm.Model
Phone string `gorm:"uniqueIndex;size:20"`
Email string `gorm:"uniqueIndex;size:100"`
PasswordHash string `gorm:"size:255"`
Nickname string `gorm:"size:50"`
Avatar string `gorm:"size:255"`
SurveyCompleted bool `gorm:"default:false"`
}
// HealthProfile 健康档案
type HealthProfile struct {
gorm.Model
UserID uint `gorm:"uniqueIndex"`
Name string `gorm:"size:50"`
BirthDate *time.Time
Gender string `gorm:"size:10"` // male, female
Height float64 // cm
Weight float64 // kg
BMI float64
BloodType string `gorm:"size:10"` // A, B, AB, O
Occupation string `gorm:"size:50"`
MaritalStatus string `gorm:"size:20"` // single, married, divorced
Region string `gorm:"size:100"`
}
// LifestyleInfo 生活习惯
type LifestyleInfo struct {
gorm.Model
UserID uint `gorm:"uniqueIndex"`
SleepTime string `gorm:"size:10"` // HH:MM
WakeTime string `gorm:"size:10"`
SleepQuality string `gorm:"size:20"` // good, normal, poor
MealRegularity string `gorm:"size:20"` // regular, irregular
DietPreference string `gorm:"size:50"` // 偏好
DailyWaterML int // 每日饮水量 ml
ExerciseFrequency string `gorm:"size:20"` // never, sometimes, often, daily
ExerciseType string `gorm:"size:100"`
ExerciseDurationMin int // 每次运动时长
IsSmoker bool
AlcoholFrequency string `gorm:"size:20"` // never, sometimes, often
}
创建 server/internal/model/health.go:
package model
import "gorm.io/gorm"
// MedicalHistory 既往病史
type MedicalHistory struct {
gorm.Model
HealthProfileID uint
DiseaseName string `gorm:"size:100"`
DiseaseType string `gorm:"size:50"` // chronic, surgery, other
DiagnosedDate string `gorm:"size:20"`
Status string `gorm:"size:20"` // cured, treating, controlled
Notes string `gorm:"type:text"`
}
// FamilyHistory 家族病史
type FamilyHistory struct {
gorm.Model
HealthProfileID uint
Relation string `gorm:"size:20"` // father, mother, grandparent
DiseaseName string `gorm:"size:100"`
Notes string `gorm:"type:text"`
}
// AllergyRecord 过敏记录
type AllergyRecord struct {
gorm.Model
HealthProfileID uint
AllergyType string `gorm:"size:20"` // drug, food, other
Allergen string `gorm:"size:100"`
Severity string `gorm:"size:20"` // mild, moderate, severe
ReactionDesc string `gorm:"type:text"`
}
创建 server/internal/model/constitution.go:
package model
import (
"time"
"gorm.io/gorm"
)
// ConstitutionAssessment 体质测评记录
type ConstitutionAssessment struct {
gorm.Model
UserID uint
AssessedAt time.Time
Scores string `gorm:"type:text"` // JSON: 各体质得分
PrimaryConstitution string `gorm:"size:20"` // 主要体质
SecondaryConstitutions string `gorm:"type:text"` // JSON: 次要体质
Recommendations string `gorm:"type:text"` // JSON: 调养建议
}
// AssessmentAnswer 问卷答案
type AssessmentAnswer struct {
gorm.Model
AssessmentID uint
QuestionID uint
Score int // 1-5
}
// QuestionBank 问卷题库
type QuestionBank struct {
gorm.Model
ConstitutionType string `gorm:"size:20"` // 体质类型
QuestionText string `gorm:"type:text"`
Options string `gorm:"type:text"` // JSON: 选项
OrderNum int
}
创建 server/internal/model/conversation.go:
package model
import "gorm.io/gorm"
// Conversation 对话
type Conversation struct {
gorm.Model
UserID uint
Title string `gorm:"size:200"`
Messages []Message
}
// Message 消息
type Message struct {
gorm.Model
ConversationID uint
Role string `gorm:"size:20"` // user, assistant, system
Content string `gorm:"type:text"`
}
步骤 4:创建模型聚合文件
创建 server/internal/model/models.go:
package model
// AllModels 返回所有需要迁移的模型
func AllModels() []interface{} {
return []interface{}{
&User{},
&HealthProfile{},
&LifestyleInfo{},
&MedicalHistory{},
&FamilyHistory{},
&AllergyRecord{},
&ConstitutionAssessment{},
&AssessmentAnswer{},
&QuestionBank{},
&Conversation{},
&Message{},
}
}
步骤 5:更新主程序
更新 server/cmd/server/main.go:
package main
import (
"log"
"health-ai/internal/config"
"health-ai/internal/database"
"health-ai/internal/model"
)
func main() {
// 加载配置
if err := config.LoadConfig("config.yaml"); err != nil {
log.Fatalf("Failed to load config: %v", err)
}
log.Println("Config loaded")
// 初始化数据库
if err := database.InitDatabase(&config.AppConfig.Database); err != nil {
log.Fatalf("Failed to init database: %v", err)
}
log.Println("Database connected")
// 自动迁移
if err := database.AutoMigrate(model.AllModels()...); err != nil {
log.Fatalf("Failed to migrate: %v", err)
}
log.Println("Database migrated")
log.Println("Health AI Server Ready!")
}
需要创建的文件清单
| 文件路径 | 说明 |
|---|---|
internal/config/config.go |
配置加载 |
internal/database/database.go |
数据库连接 |
internal/model/user.go |
用户相关模型 |
internal/model/health.go |
健康相关模型 |
internal/model/constitution.go |
体质相关模型 |
internal/model/conversation.go |
对话相关模型 |
internal/model/models.go |
模型聚合 |
验收标准
- 配置文件可正常加载
- SQLite 数据库文件自动创建
- 所有表自动迁移成功
data/health.db文件生成
预计耗时
20-30 分钟
下一步
完成后进入 02-后端开发/03-用户认证模块.md