434 lines
20 KiB
C#
434 lines
20 KiB
C#
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
|
||
};
|
||
}
|
||
}
|