MeiRiYiCheng_1_old/YBDevice.NApi/Application/UserInfo/ChildService.cs

434 lines
20 KiB
C#
Raw Normal View History

2025-07-16 17:14:38 +08:00
using Furion.DependencyInjection;
using Nirvana.Common;
using Nirvana.Common.ApiBase;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using YBDevice.Entity;
namespace YBDevice.NApi.Application.UserInfo
{
public class ChildService:BaseService,IChildService, ITransient
{
private readonly ISqlSugarRepository<YB_Family> repository;
private readonly SqlSugarClient dbClient;
private readonly IFamilyService _familyService;
public ChildService(ISqlSugarRepository<YB_Family> sqlSugarRepository,IFamilyService familyService)
{
repository = sqlSugarRepository;
dbClient = repository.Context;
_familyService = familyService;
}
/// <summary>
/// 获取儿童信息
/// </summary>
/// <param name="familyid"></param>
/// <returns></returns>
public async Task<ResultInfo> GetInfoAsync(int familyid)
{
//如果familyid=0,则加载演示数据
var data = new ChildInfoModel();
//如果传的成人类型,则自动寻找一个最新的
var family = await dbClient.Queryable<YB_Family>().Where(x => x.Id == familyid && x.Type == 2 && x.Status != -1).FirstAsync();
if (family == null)
{
family = await dbClient.Queryable<YB_Family>().Where(x => x.UserId == authInfo.UserId && x.Type == 2 && x.Status != -1).OrderBy(x => x.LastHeartTime, OrderByType.Desc).FirstAsync();
}
if (family == null)
{
var ysfamily = new YSFamily();
//返回一条演示数据
data = new ChildInfoModel
{
IsTest = true,
Height = ysfamily.Height,
DadHeight = ysfamily.DadHeight,
Time = ysfamily.Time,
Weight = ysfamily.Weight,
MomHeight = ysfamily.MomHeight,
Birthday = ysfamily.Birthday.ToString("yyyy-MM-dd"),
PredictHeight = await StandHeightAsync(ysfamily.Sex, ysfamily.Month),
HalfYearHeight = ysfamily.HalfYearHeight,
YearHeight = ysfamily.YearHeight,
Name = ysfamily.Name,
HeadImg = ysfamily.HeadImg,
Age = ysfamily.mAge,
Sex = ysfamily.Sex,
Id = ysfamily.Id
};
data.IsHeight = data.PredictHeight > data.Height;
data.AlertType = AletType(data.Height, data.PredictHeight);
data.GeneticHeight = AdultHeight(data.DadHeight, data.MomHeight, data.Sex);
return new ResultInfo(ResultState.SUCCESS, "success", data);
//return new ResultInfo(ResultState.FAIL, "成员未找到");
}
var familydata = await dbClient.Queryable<YB_FamilyData>().Where(x => x.FamilyId == family.Id).FirstAsync();
int month = family.Birthday.ToMonth();
data = new ChildInfoModel
{
Height = family.Height,
DadHeight = familydata != null ? familydata.DadHeight : 0,
Time = family.LastHeartTime,
Weight = family.Weight,
MomHeight = familydata != null ? familydata.MomHeight : 0,
PredictHeight = await StandHeightAsync(family.Sex, month),
HalfYearHeight = familydata != null ? family.Height - familydata.HalfYearHeight : 0,
YearHeight = familydata != null ? family.Height - familydata.YearHeight : 0,
Name = family.Name,
HeadImg = !string.IsNullOrEmpty(family.HeadImg) ? family.HeadImg : _familyService.HeadImg(family.Sex, family.Type),
Age = family.Birthday.TomAge(),
Sex = family.Sex,
Birthday = family.Birthday.ToString("yyyy-MM-dd"),
Id = family.Id
};
data.IsHeight = data.PredictHeight > data.Height;
data.AlertType = AletType(data.Height, data.PredictHeight);
data.GeneticHeight = AdultHeight(data.DadHeight, data.MomHeight, family.Sex);
return new ResultInfo(ResultState.SUCCESS, "success", data);
}
/// <summary>
/// 获取成长曲线
/// </summary>
/// <param name="model">家庭成员ID</param>
/// <returns></returns>
public async Task<ResultInfo> GetGrowthCurveAsync(ChildGrowthQueryModel model)
{
//如果familyid为0,则加载演示数据
if (model.familyid <= 0)
{
var list = new List<ChildGrowthModel>();
for (var i = 0; i < 10; i++)
{
list.Add(new ChildGrowthModel
{
Time = $"{i + 1}",
Height = 100 + i * 2,
Weight = 20 + i
});
}
return new ResultInfo(ResultState.SUCCESS, "success", list);
}
model.StartTime = model.StartTime.Date;
model.EndTime = model.EndTime.Date;
var tempquery = dbClient.Queryable<YB_FamilyReportData>()
.Where(x => x.FamilyId == model.familyid && x.CreateTime >= model.StartTime && x.CreateTime <= model.EndTime);
var query = await tempquery.OrderBy(x => x.CreateTime, OrderByType.Desc).Select(x => new ChildGrowthModel
{
Time = SqlFunc.ToString(x.CreateTime),
Height = x.Height,
Weight = x.Weight
})
.Mapper((it, cache) =>
{
it.Time = it.Time.ToDate().ToString("yyyy-MM");
})
.ToPageListAsync(model.page, model.pagesize);
return new ResultInfo(ResultState.SUCCESS, "success", query);
}
/// <summary>
/// 获取身高/体重成长测评报告,与标准身高进行对比
/// </summary>
/// <param name="familyid"></param>
/// <param name="page"></param>
/// <param name="pagesize"></param>
/// <returns></returns>
public async Task<ResultInfo> GetHWListAsync(int familyid, int page, int pagesize)
{
if (familyid <= 0)
{
var thlist = new List<ChildWHModel>();
var twlist = new List<ChildWHModel>();
for (var i = 0; i < 10; i++)
{
thlist.Add(new ChildWHModel
{
Time = $"{i + 1}",
Value = 100 + i * 2,
StandValue = await StandHeightAsync(1, 84)
});
twlist.Add(new ChildWHModel
{
Time = $"{i + 1}",
Value = 20 + i * 2,
StandValue = await StandWeightAsync(1, 84)
});
}
return new ResultInfo(ResultState.SUCCESS, "success", new
{
hlist = thlist,
wlist = twlist
});
}
var family = await dbClient.Queryable<YB_Family>().FirstAsync(x => x.Id == familyid);
if (family == null)
{
return new ResultInfo(ResultState.FAIL, "家庭成员未找到");
}
var tempquery = dbClient.Queryable<YB_FamilyReportData>().Where(x => x.FamilyId == familyid);
var query = await tempquery
.OrderBy(x => x.CreateTime, OrderByType.Desc)
.ToPageListAsync(page, pagesize);
var hlist = new List<ChildWHModel>();
var wlist = new List<ChildWHModel>();
query.ForEach(async x =>
{
hlist.Add(new ChildWHModel
{
Time = x.CreateTime.ToYearDate(),
Value = x.Height,
StandValue = await StandHeightAsync(family.Sex, family.Birthday)
});
wlist.Add(new ChildWHModel
{
Time = x.CreateTime.ToYearDate(),
Value = x.Weight,
StandValue = await StandWeightAsync(family.Sex, family.Birthday)
}); ;
});
return new ResultInfo(ResultState.SUCCESS, "success", new
{
hlist = hlist,
wlist = wlist
});
}
/// <summary>
/// 计算遗传身高和成年身高
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public async Task<ResultInfo> PredictHeightAsync(ChildPredictHeightModel model)
{
//计算遗传身高
decimal geneticheight = await StandHeightAsync(model.sex, model.Birthday);
//成年身高预测
decimal adultheight = AdultHeight(model.DadHeight, model.MomHeight, model.sex);
if (model.familyid > 0)
{
await dbClient.Updateable<YB_FamilyData>().SetColumns(x => new YB_FamilyData
{
DadHeight = model.DadHeight,
MomHeight = model.MomHeight
})
.Where(x => x.FamilyId == model.familyid)
.ExecuteCommandAsync();
}
return new ResultInfo(ResultState.SUCCESS, "success", new ChildPredictHeightReturnModel
{
GeneticHeight = geneticheight,
AdultHeight = adultheight
});
}
/// <summary>
/// 获取儿童增量信息
/// </summary>
/// <param name="familyid"></param>
/// <returns></returns>
public async Task<ResultInfo> GetYearHeightInfoAsync(int familyid)
{
if (familyid == 0)
{
//返回演示数据
var ysfamily = new YSFamily();
var ysstanddata = await dbClient.Queryable<YB_HeightStand>().Where(x => x.Sex == ysfamily.Sex && x.Month >= ysfamily.Month).OrderBy(x => x.Month, OrderByType.Asc).FirstAsync();
var ysdata = new ChildYearHeightModel
{
f1sd = ysstanddata.f1sd,
f2sd = ysstanddata.f2sd,
z1sd = ysstanddata.z1sd,
z2sd = ysstanddata.z2sd,
Height = ysfamily.Height,
HalfYearHeight = ysfamily.HalfYearHeight,
median = ysstanddata.median,
HalfYearStandHeight = HalfYearStandHeight(ysfamily.Age),
YearHeight = ysfamily.YearHeight,
HeightLevel = HeightLevel(ysstanddata, ysfamily.Height)
};
ysdata.HalfYearHeightLevel = HalfYearHeightLevel(ysdata.HalfYearHeight, ysdata.HalfYearStandHeight);
ysdata.YearHeightLevel = YearHeightLevel(ysdata.YearHeight, ysdata.YearStandHeight);
return new ResultInfo(ResultState.SUCCESS, "success", ysdata);
}
var family = await dbClient.Queryable<YB_Family>().FirstAsync(x => x.Id == familyid);
if (family == null)
{
return new ResultInfo(ResultState.FAIL, "成员未找到");
}
var familydata = await dbClient.Queryable<YB_FamilyData>().FirstAsync(x => x.FamilyId == familyid);
int month = family.Birthday.ToMonth();
int age = family.Birthday.ToAge();
var data = await dbClient.Queryable<YB_HeightStand>().Where(x => x.Sex == family.Sex && (x.Month >= month)).OrderBy(x => x.Month, OrderByType.Asc).FirstAsync();
var returndata = new ChildYearHeightModel
{
f1sd = data.f1sd,
f2sd = data.f2sd,
z1sd = data.z1sd,
z2sd = data.z2sd,
Height = family.Height,
HalfYearHeight = familydata != null && familydata.HalfYearHeight > 0 ? family.Height - familydata.HalfYearHeight : 0, //如果半年前身高为0则表示未测量过,则增量为0
median = data.median,
HalfYearStandHeight = HalfYearStandHeight(age),
YearHeight = familydata != null && familydata.YearHeight > 0 ? family.Height - familydata.YearHeight : 0,
YearStandHeight = YearStandHeight(age),
HeightLevel = HeightLevel(data, family.Height)
};
returndata.HalfYearHeightLevel = HalfYearHeightLevel(returndata.HalfYearHeight, returndata.HalfYearStandHeight);
returndata.YearHeightLevel = YearHeightLevel(returndata.YearHeight, returndata.YearStandHeight);
return new ResultInfo(ResultState.SUCCESS, "success", returndata);
}
/// <summary>
/// 身高等级
/// </summary>
/// <param name="data">等级标准</param>
/// <param name="height">身高</param>
/// <returns></returns>
private int HeightLevel(YB_HeightStand data, decimal height)
=> (data, height) switch
{
_ when height >= data.f1sd && height < data.z1sd => (int)ChildHeightLevel.Normal,
_ when height >= data.f2sd && height < data.f1sd => (int)ChildHeightLevel.Low,
_ when height >= data.z1sd && height < data.z2sd => (int)ChildHeightLevel.Height,
_ when height >= data.f3sd && height < data.f2sd => (int)ChildHeightLevel.MoreLow,
_ when height >= data.z2sd && height < data.z3sd => (int)ChildHeightLevel.MoreHeight,
_ => (int)ChildHeightLevel.Error
};
/// <summary>
/// 半年增量标准身高值
/// </summary>
/// <param name="age">年龄</param>
/// <returns></returns>
private decimal HalfYearStandHeight(int age)
=> (age) switch
{
_ when age < 10 => 2.5m,
_ => 3m
};
/// <summary>
/// 半年增量标准
/// </summary>
/// <param name="height">半年增量</param>
/// <param name="standheight">标准增量</param>
/// <returns></returns>
private int HalfYearHeightLevel(decimal height, decimal standheight)
=> (height, standheight) switch
{
_ when height >= standheight => (int)ChildYearHeightLevel.Normal,
_ => (int)ChildHeightLevel.Low
};
/// <summary>
/// 一年的身高增量标准值
/// </summary>
/// <param name="age"></param>
/// <returns></returns>
private decimal YearStandHeight(int age)
=> (age) switch
{
_ when age < 10 => 5m,
_ => 6m
};
/// <summary>
/// 一年增量标准
/// </summary>
/// <param name="height">一年增量</param>
/// <param name="standheight">标准增量</param>
/// <returns></returns>
private int YearHeightLevel(decimal height, decimal standheight)
=> (height, standheight) switch
{
_ when height >= standheight => (int)ChildYearHeightLevel.Normal,
_ => (int)ChildHeightLevel.Low
};
/// <summary>
/// 成年身高预测,女孩的靶身高=(父亲身高+母亲身高-13cm÷2
/// 男孩的靶身高=(父亲身高+母亲身高+13cm÷2
/// </summary>
/// <param name="dadheight">父亲身高</param>
/// <param name="momheight">母亲身高</param>
/// <param name="sex">性别,1-男,2-女,0-未知</param>
/// <returns></returns>
private static decimal AdultHeight(decimal dadheight, decimal momheight, int sex)
=> (dadheight, momheight, sex) switch
{
_ when dadheight <= 0 || momheight <= 0 => 0,
_ when (sex == 2) => (37.85m + 0.75m * (dadheight + momheight) / 2).ToDecimal(1),
_ => (45.99m + 0.78m * (dadheight + momheight) / 2).ToDecimal(1)
};
/// <summary>
/// 标准身高,参考
/// 5-19岁女孩:https://www.who.int/docs/default-source/child-growth/growth-reference-5-19-years/height-for-age-(5-19-years)/sft-hfa-girls-perc-5-19years.pdf?sfvrsn=59b013d8_4,
/// 5-19岁男孩:https://www.who.int/docs/default-source/child-growth/growth-reference-5-19-years/height-for-age-(5-19-years)/sft-hfa-boys-perc-5-19years.pdf?sfvrsn=3fe316bf_4
///
/// </summary>
/// <param name="sex"></param>
/// <param name="birthday"></param>
/// <returns></returns>
private async Task<decimal> StandHeightAsync(int sex, DateTime birthday)
{
var month = birthday.ToMonth();
var height = await StandHeightAsync(sex, month);
return height.ToDecimal(1);
}
/// <summary>
/// 标准身高
/// </summary>
/// <param name="sex">性别,1-男,2-女</param>
/// <param name="month">月龄</param>
/// <returns></returns>
private async Task<decimal> StandHeightAsync(int sex, int month)
{
var data = await dbClient.Queryable<YB_HeightStand>().Where(x => x.Sex == sex && (x.Month >= month)).OrderBy(x => x.Month, OrderByType.Asc).FirstAsync();
return data != null ? data.median : 0;
}
/// <summary>
/// 标准身高,参考
/// 5-19岁女孩:https://www.who.int/docs/default-source/child-growth/growth-reference-5-19-years/height-for-age-(5-19-years)/sft-hfa-girls-perc-5-19years.pdf?sfvrsn=59b013d8_4,
/// 5-19岁男孩:https://www.who.int/docs/default-source/child-growth/growth-reference-5-19-years/height-for-age-(5-19-years)/sft-hfa-boys-perc-5-19years.pdf?sfvrsn=3fe316bf_4
///
/// </summary>
/// <param name="sex"></param>
/// <param name="birthday"></param>
/// <returns></returns>
private async Task<decimal> StandWeightAsync(int sex, DateTime birthday)
{
var month = birthday.ToMonth();
return await StandWeightAsync(sex, month);
}
/// <summary>
/// 标准体重
/// </summary>
/// <param name="sex">性别,1-男,2-女</param>
/// /// <param name="month">月龄</param>
/// <returns></returns>
private async Task<decimal> StandWeightAsync(int sex, int month)
{
var data = await dbClient.Queryable<YB_WeightStand>().Where(x => x.Sex == sex && (x.Month >= month)).OrderBy(x => x.Month, OrderByType.Asc).FirstAsync();
return data != null ? data.median : 0;
//理想体重 = 22 ×身高² (米)
//return 22 * ((height / 100) * (height / 100));
}
/// <summary>
/// 智能追踪分析,该分析是基于标准身高与实测身高的对比,对孩子是否因为后天因素有利于长高进行判断
/// </summary>
/// <param name="height">实测身高</param>
/// <param name="standheight">标准身高</param>
/// <returns></returns>
private static int AletType(decimal height, decimal standheight)
=> (height, standheight) switch
{
_ when (standheight - height > 6) => (int)ChildAlertType.RedAlert,
_ when (standheight - height <= 6 && standheight - height > 3) => (int)ChildAlertType.OrangeAlert,
_ when (standheight - height <= 3 && standheight - height > 0) => (int)ChildAlertType.YellowAlert,
_ when (standheight - height <= 0 && standheight - height >= -4) => (int)ChildAlertType.BlueReward,
_ => (int)ChildAlertType.GreenAlert
};
}
}