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.
289 lines
8.0 KiB
289 lines
8.0 KiB
package service
|
|
|
|
import (
|
|
"errors"
|
|
"time"
|
|
|
|
"health-ai/internal/model"
|
|
"health-ai/internal/repository/impl"
|
|
)
|
|
|
|
type HealthService struct {
|
|
healthRepo *impl.HealthRepository
|
|
constitutionRepo *impl.ConstitutionRepository
|
|
userRepo *impl.UserRepositoryImpl
|
|
}
|
|
|
|
func NewHealthService() *HealthService {
|
|
return &HealthService{
|
|
healthRepo: impl.NewHealthRepository(),
|
|
constitutionRepo: impl.NewConstitutionRepository(),
|
|
userRepo: impl.NewUserRepository(),
|
|
}
|
|
}
|
|
|
|
// ================= 响应结构体 =================
|
|
|
|
// HealthProfileResponse 健康档案响应
|
|
type HealthProfileResponse struct {
|
|
Profile *model.HealthProfile `json:"profile"`
|
|
Lifestyle *model.LifestyleInfo `json:"lifestyle"`
|
|
MedicalHistory []model.MedicalHistory `json:"medical_history"`
|
|
FamilyHistory []model.FamilyHistory `json:"family_history"`
|
|
AllergyRecords []model.AllergyRecord `json:"allergy_records"`
|
|
Constitution *ConstitutionScore `json:"constitution,omitempty"`
|
|
}
|
|
|
|
// ================= Service 方法 =================
|
|
|
|
// GetHealthProfile 获取完整健康档案
|
|
func (s *HealthService) GetHealthProfile(userID uint) (*HealthProfileResponse, error) {
|
|
resp := &HealthProfileResponse{}
|
|
|
|
// 获取基础档案
|
|
profile, err := s.healthRepo.GetProfileByUserID(userID)
|
|
if err == nil && profile.ID > 0 {
|
|
resp.Profile = profile
|
|
}
|
|
|
|
// 获取生活习惯
|
|
lifestyle, err := s.healthRepo.GetLifestyleByUserID(userID)
|
|
if err == nil && lifestyle.ID > 0 {
|
|
resp.Lifestyle = lifestyle
|
|
}
|
|
|
|
// 获取病史
|
|
if profile != nil && profile.ID > 0 {
|
|
resp.MedicalHistory, _ = s.healthRepo.GetMedicalHistories(profile.ID)
|
|
resp.FamilyHistory, _ = s.healthRepo.GetFamilyHistories(profile.ID)
|
|
resp.AllergyRecords, _ = s.healthRepo.GetAllergyRecords(profile.ID)
|
|
}
|
|
|
|
// 获取最新体质信息
|
|
constitution, err := s.constitutionRepo.GetLatestAssessment(userID)
|
|
if err == nil && constitution.ID > 0 {
|
|
resp.Constitution = &ConstitutionScore{
|
|
Type: constitution.PrimaryConstitution,
|
|
Name: model.ConstitutionNames[constitution.PrimaryConstitution],
|
|
Description: model.ConstitutionDescriptions[constitution.PrimaryConstitution],
|
|
}
|
|
}
|
|
|
|
return resp, nil
|
|
}
|
|
|
|
// GetBasicProfile 获取基础档案
|
|
func (s *HealthService) GetBasicProfile(userID uint) (*model.HealthProfile, error) {
|
|
profile, err := s.healthRepo.GetProfileByUserID(userID)
|
|
if err != nil {
|
|
return nil, errors.New("健康档案不存在")
|
|
}
|
|
return profile, nil
|
|
}
|
|
|
|
// GetLifestyle 获取生活习惯
|
|
func (s *HealthService) GetLifestyle(userID uint) (*model.LifestyleInfo, error) {
|
|
lifestyle, err := s.healthRepo.GetLifestyleByUserID(userID)
|
|
if err != nil {
|
|
return nil, errors.New("生活习惯信息不存在")
|
|
}
|
|
return lifestyle, nil
|
|
}
|
|
|
|
// GetMedicalHistory 获取病史列表
|
|
func (s *HealthService) GetMedicalHistory(userID uint) ([]model.MedicalHistory, error) {
|
|
profile, err := s.healthRepo.GetProfileByUserID(userID)
|
|
if err != nil {
|
|
return nil, errors.New("请先填写基础信息")
|
|
}
|
|
return s.healthRepo.GetMedicalHistories(profile.ID)
|
|
}
|
|
|
|
// GetFamilyHistory 获取家族病史列表
|
|
func (s *HealthService) GetFamilyHistory(userID uint) ([]model.FamilyHistory, error) {
|
|
profile, err := s.healthRepo.GetProfileByUserID(userID)
|
|
if err != nil {
|
|
return nil, errors.New("请先填写基础信息")
|
|
}
|
|
return s.healthRepo.GetFamilyHistories(profile.ID)
|
|
}
|
|
|
|
// GetAllergyRecords 获取过敏记录列表
|
|
func (s *HealthService) GetAllergyRecords(userID uint) ([]model.AllergyRecord, error) {
|
|
profile, err := s.healthRepo.GetProfileByUserID(userID)
|
|
if err != nil {
|
|
return nil, errors.New("请先填写基础信息")
|
|
}
|
|
return s.healthRepo.GetAllergyRecords(profile.ID)
|
|
}
|
|
|
|
// DeleteMedicalHistory 删除病史记录
|
|
func (s *HealthService) DeleteMedicalHistory(userID, historyID uint) error {
|
|
// TODO: 验证记录属于该用户
|
|
return s.healthRepo.DeleteMedicalHistory(historyID)
|
|
}
|
|
|
|
// DeleteFamilyHistory 删除家族病史记录
|
|
func (s *HealthService) DeleteFamilyHistory(userID, historyID uint) error {
|
|
// TODO: 验证记录属于该用户
|
|
return s.healthRepo.DeleteFamilyHistory(historyID)
|
|
}
|
|
|
|
// DeleteAllergyRecord 删除过敏记录
|
|
func (s *HealthService) DeleteAllergyRecord(userID, recordID uint) error {
|
|
// TODO: 验证记录属于该用户
|
|
return s.healthRepo.DeleteAllergyRecord(recordID)
|
|
}
|
|
|
|
// ================= 更新请求结构体 =================
|
|
|
|
// UpdateHealthProfileInput 更新健康档案输入
|
|
type UpdateHealthProfileInput struct {
|
|
Name string
|
|
BirthDate string
|
|
Gender string
|
|
Height float64
|
|
Weight float64
|
|
BloodType string
|
|
Occupation string
|
|
MaritalStatus string
|
|
Region string
|
|
}
|
|
|
|
// UpdateLifestyleInput 更新生活习惯输入
|
|
type UpdateLifestyleInput struct {
|
|
SleepTime string
|
|
WakeTime string
|
|
SleepQuality string
|
|
MealRegularity string
|
|
DietPreference string
|
|
DailyWaterML int
|
|
ExerciseFrequency string
|
|
ExerciseType string
|
|
ExerciseDurationMin int
|
|
IsSmoker *bool // 使用指针以区分未设置和false
|
|
AlcoholFrequency string
|
|
}
|
|
|
|
// UpdateHealthProfile 更新健康档案
|
|
func (s *HealthService) UpdateHealthProfile(userID uint, input *UpdateHealthProfileInput) (*model.HealthProfile, error) {
|
|
// 获取或创建健康档案
|
|
profile, err := s.healthRepo.GetProfileByUserID(userID)
|
|
if err != nil {
|
|
// 创建新档案
|
|
profile = &model.HealthProfile{
|
|
UserID: userID,
|
|
}
|
|
}
|
|
|
|
// 更新字段(只更新非空值)
|
|
if input.Name != "" {
|
|
profile.Name = input.Name
|
|
}
|
|
if input.BirthDate != "" {
|
|
// 解析日期字符串
|
|
parsedDate, err := time.Parse("2006-01-02", input.BirthDate)
|
|
if err == nil {
|
|
profile.BirthDate = &parsedDate
|
|
}
|
|
}
|
|
if input.Gender != "" {
|
|
profile.Gender = input.Gender
|
|
}
|
|
if input.Height > 0 {
|
|
profile.Height = input.Height
|
|
}
|
|
if input.Weight > 0 {
|
|
profile.Weight = input.Weight
|
|
// 计算BMI
|
|
if profile.Height > 0 {
|
|
heightM := profile.Height / 100
|
|
profile.BMI = profile.Weight / (heightM * heightM)
|
|
}
|
|
}
|
|
if input.BloodType != "" {
|
|
profile.BloodType = input.BloodType
|
|
}
|
|
if input.Occupation != "" {
|
|
profile.Occupation = input.Occupation
|
|
}
|
|
if input.MaritalStatus != "" {
|
|
profile.MaritalStatus = input.MaritalStatus
|
|
}
|
|
if input.Region != "" {
|
|
profile.Region = input.Region
|
|
}
|
|
|
|
// 保存或更新
|
|
if profile.ID == 0 {
|
|
if err := s.healthRepo.CreateProfile(profile); err != nil {
|
|
return nil, err
|
|
}
|
|
} else {
|
|
if err := s.healthRepo.UpdateProfile(profile); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return profile, nil
|
|
}
|
|
|
|
// UpdateLifestyle 更新生活习惯
|
|
func (s *HealthService) UpdateLifestyle(userID uint, input *UpdateLifestyleInput) (*model.LifestyleInfo, error) {
|
|
// 获取或创建生活习惯记录
|
|
lifestyle, err := s.healthRepo.GetLifestyleByUserID(userID)
|
|
if err != nil {
|
|
// 创建新记录
|
|
lifestyle = &model.LifestyleInfo{
|
|
UserID: userID,
|
|
}
|
|
}
|
|
|
|
// 更新字段(只更新非空值)
|
|
if input.SleepTime != "" {
|
|
lifestyle.SleepTime = input.SleepTime
|
|
}
|
|
if input.WakeTime != "" {
|
|
lifestyle.WakeTime = input.WakeTime
|
|
}
|
|
if input.SleepQuality != "" {
|
|
lifestyle.SleepQuality = input.SleepQuality
|
|
}
|
|
if input.MealRegularity != "" {
|
|
lifestyle.MealRegularity = input.MealRegularity
|
|
}
|
|
if input.DietPreference != "" {
|
|
lifestyle.DietPreference = input.DietPreference
|
|
}
|
|
if input.DailyWaterML > 0 {
|
|
lifestyle.DailyWaterML = input.DailyWaterML
|
|
}
|
|
if input.ExerciseFrequency != "" {
|
|
lifestyle.ExerciseFrequency = input.ExerciseFrequency
|
|
}
|
|
if input.ExerciseType != "" {
|
|
lifestyle.ExerciseType = input.ExerciseType
|
|
}
|
|
if input.ExerciseDurationMin > 0 {
|
|
lifestyle.ExerciseDurationMin = input.ExerciseDurationMin
|
|
}
|
|
if input.IsSmoker != nil {
|
|
lifestyle.IsSmoker = *input.IsSmoker
|
|
}
|
|
if input.AlcoholFrequency != "" {
|
|
lifestyle.AlcoholFrequency = input.AlcoholFrequency
|
|
}
|
|
|
|
// 保存或更新
|
|
if lifestyle.ID == 0 {
|
|
if err := s.healthRepo.CreateLifestyle(lifestyle); err != nil {
|
|
return nil, err
|
|
}
|
|
} else {
|
|
if err := s.healthRepo.UpdateLifestyle(lifestyle); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return lifestyle, nil
|
|
}
|
|
|