using Nirvana.Common; using Nirvana.Common.ApiBase; using Nirvana.Data; using SqlSugar; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using YBDevice.Entity; namespace YBDevice.NApi.DBServices { /// /// 儿童模式相关处理 /// public partial class ChildApp : BaseApp { /// /// 获取儿童信息 /// /// /// public async Task GetInfoAsync(int familyid) { //如果familyid=0,则加载演示数据 var data = new ChildInfoModel(); using (var dbClient = ReadDbContext.GetInstance()) { //如果传的成人类型,则自动寻找一个最新的 var family = await dbClient.Queryable().Where(x => x.Id == familyid && x.Type == 2 && x.Status != -1).FirstAsync(); if (family == null) { family = await dbClient.Queryable().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().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 : new FamilyApp().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); } } /// /// 获取成长曲线 /// /// 家庭成员ID /// public async Task GetGrowthCurveAsync(ChildGrowthQueryModel model) { //如果familyid为0,则加载演示数据 if (model.familyid <= 0) { var list = new List(); 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); } using (var dbClient = ReadDbContext.GetInstance()) { model.StartTime = model.StartTime.Date; model.EndTime = model.EndTime.Date; var tempquery = dbClient.Queryable() .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); } } /// /// 获取身高/体重成长测评报告,与标准身高进行对比 /// /// /// /// /// public async Task GetHWListAsync(int familyid, int page, int pagesize) { if (familyid <= 0) { var thlist = new List(); var twlist = new List(); 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 }); } using (var dbClient = ReadDbContext.GetInstance()) { var family = await dbClient.Queryable().FirstAsync(x => x.Id == familyid); if (family == null) { return new ResultInfo(ResultState.FAIL, "家庭成员未找到"); } var tempquery = dbClient.Queryable().Where(x => x.FamilyId == familyid); var query = await tempquery .OrderBy(x => x.CreateTime, OrderByType.Desc) .ToPageListAsync(page, pagesize); var hlist = new List(); var wlist = new List(); 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 }); } } /// /// 计算遗传身高和成年身高 /// /// /// public async Task PredictHeightAsync(ChildPredictHeightModel model) { //计算遗传身高 decimal geneticheight = await StandHeightAsync(model.sex, model.Birthday); //成年身高预测 decimal adultheight = AdultHeight(model.DadHeight, model.MomHeight, model.sex); if (model.familyid > 0) { using (var dbClient = ReadDbContext.GetInstance()) { await dbClient.Updateable().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 }); } /// /// 获取儿童增量信息 /// /// /// public async Task GetYearHeightInfoAsync(int familyid) { using (var dbClient = ReadDbContext.GetInstance()) { if(familyid == 0) { //返回演示数据 var ysfamily = new YSFamily(); var ysstanddata = await dbClient.Queryable().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().FirstAsync(x => x.Id == familyid); if (family == null) { return new ResultInfo(ResultState.FAIL, "成员未找到"); } var familydata = await dbClient.Queryable().FirstAsync(x => x.FamilyId == familyid); int month = family.Birthday.ToMonth(); int age = family.Birthday.ToAge(); var data = await dbClient.Queryable().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); } } /// /// 身高等级 /// /// 等级标准 /// 身高 /// 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 }; /// /// 半年增量标准身高值 /// /// 年龄 /// private decimal HalfYearStandHeight(int age) => (age) switch { _ when age < 10 => 2.5m, _ => 3m }; /// /// 半年增量标准 /// /// 半年增量 /// 标准增量 /// private int HalfYearHeightLevel(decimal height, decimal standheight) => (height, standheight) switch { _ when height >= standheight => (int)ChildYearHeightLevel.Normal, _ => (int)ChildHeightLevel.Low }; /// /// 一年的身高增量标准值 /// /// /// private decimal YearStandHeight(int age) => (age) switch { _ when age < 10 => 5m, _ => 6m }; /// /// 一年增量标准 /// /// 一年增量 /// 标准增量 /// private int YearHeightLevel(decimal height, decimal standheight) => (height, standheight) switch { _ when height >= standheight => (int)ChildYearHeightLevel.Normal, _ => (int)ChildHeightLevel.Low }; /// /// 成年身高预测,女孩的靶身高=(父亲身高+母亲身高-13cm)÷2 /// 男孩的靶身高=(父亲身高+母亲身高+13cm)÷2 /// /// 父亲身高 /// 母亲身高 /// 性别,1-男,2-女,0-未知 /// 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) }; /// /// 标准身高,参考 /// 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 /// /// /// /// /// private static async Task StandHeightAsync(int sex, DateTime birthday) { var month = birthday.ToMonth(); var height= await StandHeightAsync(sex, month); return height.ToDecimal(1); } /// /// 标准身高 /// /// 性别,1-男,2-女 /// 月龄 /// private static async Task StandHeightAsync(int sex, int month) { using (var dbClient = ReadDbContext.GetInstance()) { var data = await dbClient.Queryable().Where(x => x.Sex == sex && (x.Month >= month)).OrderBy(x => x.Month, OrderByType.Asc).FirstAsync(); return data != null ? data.median : 0; } } /// /// 标准身高,参考 /// 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 /// /// /// /// /// private static async Task StandWeightAsync(int sex, DateTime birthday) { var month = birthday.ToMonth(); return await StandWeightAsync(sex, month); } /// /// 标准体重 /// /// 性别,1-男,2-女 /// /// 月龄 /// private static async Task StandWeightAsync(int sex, int month) { using (var dbClient = ReadDbContext.GetInstance()) { var data = await dbClient.Queryable().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)); } /// /// 智能追踪分析,该分析是基于标准身高与实测身高的对比,对孩子是否因为后天因素有利于长高进行判断 /// /// 实测身高 /// 标准身高 /// 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 }; } }