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

546 lines
27 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Furion.DependencyInjection;
using Mapster;
using Nirvana.Common;
using Nirvana.Common.ApiBase;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using YBDevice.Body.BodyFatHelper;
using YBDevice.Body.Level;
using YBDevice.CommonService;
using YBDevice.CommonService.DevTypeInfo;
using YBDevice.Entity;
using YBDevice.NApi.Application.Prescription;
namespace YBDevice.NApi.Application.UserInfo
{
/// <summary>
/// 儿童信息处理
/// </summary>
public class ChildService : BaseService, IChildService, ITransient
{
private readonly ISqlSugarRepository<YB_Family> repository;
private readonly SqlSugarClient dbClient;
private readonly IFamilyService _familyService;
private readonly IDeviceTypeService _deviceTypeService;
private readonly IBodyFatHelperService _bodyFatHelperService;
private readonly IPrescriptionService _prescriptionService;
private readonly ILevelService _levelService;
private readonly ILevelService _abLevelService;
/// <summary>
/// 构造
/// </summary>
/// <param name="sqlSugarRepository"></param>
/// <param name="familyService"></param>
/// <param name="bodyFatHelperService"></param>
/// <param name="deviceTypeService"></param>
/// <param name="prescriptionService"></param>
/// <param name="resolveNamed"></param>
public ChildService(ISqlSugarRepository<YB_Family> sqlSugarRepository, IFamilyService familyService, IBodyFatHelperService bodyFatHelperService, IDeviceTypeService deviceTypeService, IPrescriptionService prescriptionService, Func<string, ITransient, object> resolveNamed)
{
repository = sqlSugarRepository;
dbClient = repository.Context;
_familyService = familyService;
_bodyFatHelperService = bodyFatHelperService;
_deviceTypeService = deviceTypeService;
_prescriptionService = prescriptionService;
_levelService = resolveNamed("LevelService", default) as ILevelService;
_abLevelService = resolveNamed("AbLevelService", default) as ILevelService;
}
/// <summary>
/// 获取儿童信息
/// </summary>
/// <param name="familyid"></param>
/// <param name="devtype">设备类型</param>
/// <param name="appid">小程序appid</param>
/// <returns></returns>
public async Task<ResultInfo> GetInfoAsync(int familyid, int devtype, string appid)
{
var data = new ChildInfoModel();
var family = await dbClient.Queryable<YB_Family>().Where(x => x.Id == familyid).FirstAsync();
if (family == null)
{
return new ResultInfo(ResultState.FAIL, "家庭成员未找到");
}
YB_FamilyData familydata = await dbClient.Queryable<YB_FamilyData>().Where(x => x.FamilyId == family.Id).FirstAsync();
YB_FamilyRealData familyrealdata = await dbClient.Queryable<YB_FamilyRealData>().Where(x => x.FamilyId == family.Id && x.DevType == devtype).FirstAsync();
decimal height = (familyrealdata != null && familyrealdata.LastHeight > 0) ? familyrealdata.LastHeight : family.Height;
decimal weight = (familyrealdata != null && familyrealdata.LastWeight > 0) ? familyrealdata.LastWeight.ToDecimal(1) : 0;
decimal head = (familyrealdata != null && familyrealdata.LastHead > 0) ? familyrealdata.LastHead.ToDecimal(1) : 0;
int age = family.Birthday.ToAge();
int month = family.Birthday.ToMonth();
//如果有测量数据,以最后一次测量时间为准
if (familyrealdata != null && familyrealdata.LastResultTime.HasValue)
{
month = family.Birthday.ToMonth(familyrealdata.LastResultTime.Value);
}
data = new ChildInfoModel
{
Height = height,
Head = head,
DadHeight = familydata != null ? familydata.DadHeight : 0,
Time = familyrealdata != null ? familyrealdata.LastResultTime.ToYearDateTimes() : "",
Weight = weight,
MomHeight = familydata != null ? familydata.MomHeight : 0,
HalfYearHeight = familydata != null ? (height - familydata.HalfYearHeight) : 0,
YearHeight = familydata != null ? (height - familydata.YearHeight) : 0,
Name = family.Name,
HeadImg = !string.IsNullOrEmpty(family.HeadImg) ? family.HeadImg : DefaultService.HeadImg(family.Sex, family.Type),
Age = family.Birthday.TomAge(),
Sex = family.Sex,
Birthday = family.Birthday.ToString("yyyy-MM-dd"),
Id = family.Id,
LastHeightTime = familyrealdata != null ? familyrealdata.LastResultHeightTime.ToYearDate() : "",
BMI = _bodyFatHelperService.CalcBMi(height, weight),
Type = family.Type,
ResultId = familyrealdata != null ? familyrealdata.LastResultId : null,
ReferList = GetReferList(),
DataReferList = GetDataReferList(family.Birthday)
};
var standdata = await _levelService.LevelAsync(family.Sex, family.Birthday, data.BMI, LevelType.BMI);
data.BMILevel = standdata.Level;
data.BMILevelColor = standdata.Color;
data.BMILevelList = standdata.list;
//如果是安邦小程序则使用安邦标准
if (appid == ABConst.MiniAppId)
{
standdata = await _abLevelService.LevelAsync(family.Sex, family.Birthday, data.Height, LevelType.Height);
data.HeightLevel = standdata.Level;
data.HeightLevelColor = standdata.Color;
data.HeightLevelList = standdata.list;
data.PredictHeight = age <= 16 ? standdata.Media : data.Height;
standdata = await _abLevelService.LevelAsync(family.Sex, family.Birthday, data.Weight, LevelType.Weight);
data.WeightLevel = standdata.Level;
data.WeightLevelColor = standdata.Color;
data.WeightLevelList = standdata.list;
data.StandWeight = age <= 16 ? standdata.Media : _bodyFatHelperService.CalcStandWeight(height, family.Sex);
}
else
{
standdata = await _levelService.LevelAsync(family.Sex, family.Birthday, data.Height, LevelType.Height);
data.HeightLevel = standdata.Level;
data.HeightLevelColor = standdata.Color;
data.HeightLevelList = standdata.list;
data.PredictHeight = age <= 16 ? standdata.Media : data.Height;
standdata = await _levelService.LevelAsync(family.Sex, family.Birthday, data.Weight, LevelType.Weight);
data.WeightLevel = standdata.Level;
data.WeightLevelColor = standdata.Color;
data.WeightLevelList = standdata.list;
data.StandWeight = age <= 16 ? standdata.Media : _bodyFatHelperService.CalcStandWeight(height, family.Sex);
}
standdata = await _levelService.LevelAsync(family.Sex, family.Birthday, data.Head, LevelType.Head);
data.HeadLevel = standdata.Level;
data.HeadLevelColor = standdata.Color;
data.HeadLevelList = standdata.list;
data.IsHeight = data.PredictHeight > data.Height;
data.AlertType = AletType(data.Height, data.PredictHeight);
data.GeneticHeight = AdultHeight(data.DadHeight, data.MomHeight, family.Sex);
if (appid == ABConst.MiniAppId)
{
data.cplist = await _prescriptionService.AB_Child(new ChildPrescriptionS2SDto
{
Age = month,
BMILevel = data.BMILevel,
HeightLevel = data.HeightLevel,
WeightLevel = data.WeightLevel
});
}
else
{
data.cplist = await _prescriptionService.Child(new ChildPrescriptionS2SDto
{
Age = month,
BMILevel = data.BMILevel,
HeightLevel = data.HeightLevel,
WeightLevel = data.WeightLevel
});
}
return new ResultInfo(ResultState.SUCCESS, "success", data);
}
/// <summary>
/// 获取文献引用列表
/// </summary>
/// <returns></returns>
private List<string> GetReferList()
{
var list = new List<string> {
"[1]华东师范大学专业硕士学位论文——跳跃运动对小学生身高和体质健康影响的实验研究",
"[2]李之俊.运动与脂肪动员研究进展[J].中国运动医学杂志2012.01.0169-72",
"[3]曾捷.跳跃运动队青少年根骨骨密度与体质影响的实验研究[D].硕士论文华东师范大学2013.10:16-18.",
"[4]牟其林.跳跃运动对贵州小学生骨密度、体质健康和体成分影响的实验研究[D].硕士论文.华东师范大学.2016.10.",
"[5]张玲莉,闫晓,邹军.运动训练与骨生长代谢的研究进展[J].中国骨质疏松杂志2013,19(7):761-765."
};
return list;
}
/// <summary>
/// 获取数据参考列表
/// </summary>
/// <param name="birthday">出生年月</param>
/// <returns></returns>
private List<string> GetDataReferList(DateTime birthday)
{
var list = new List<string> {
"《2005年九省/市儿童体格发育调查数据研究》中华儿科杂志2009年7期"
};
double month = birthday.ToDMonth();
if (month >= 5 * 12 * 1.0 && month <= 19 * 12 * 1.0)
{
list.Add("《WHO 5~19岁身高/体重判定标准》");
}
return list;
}
/// <summary>
/// 获取成长曲线
/// </summary>
/// <param name="model">家庭成员ID</param>
/// <returns></returns>
public async Task<ResultInfo> GetGrowthCurveAsync(ChildGrowthQueryModel model)
{
DateTime nowtime = DateTime.Now.Date;
if (model.StartTime.HasValue)
{
DateTime time = model.StartTime.Value.Date;
model.StartTime = time.AddDays(-time.Day).AddDays(1);
}
else
{
DateTime monthtime = nowtime.AddDays(-nowtime.Day).AddDays(1);//月初
model.StartTime = monthtime.AddYears(-2);//两年前
}
model.EndTime = model.EndTime.Date;
//如果时间段包含今天则加载今日数据
List<int> devtypes = await _deviceTypeService.GetDevTypesAsync(model.DevType);
List<YB_FamilyReportData> glist = new List<YB_FamilyReportData>();
if (nowtime >= model.StartTime && nowtime <= model.EndTime)
{
var familyrealdatalist = await dbClient.Queryable<YB_FamilyRealData>().Where(x => x.FamilyId == model.familyid && x.DevType == model.DevType).FirstAsync();
if (familyrealdatalist != null && (familyrealdatalist.MonthWeight > 0 || familyrealdatalist.MonthHeight > 0))
{
glist.Add(new YB_FamilyReportData
{
Head = familyrealdatalist.MonthHead,
Weight = familyrealdatalist.MonthWeight,
Height = familyrealdatalist.MonthHeight,
CreateTime = nowtime
});
}
}
var query = await dbClient.Queryable<YB_FamilyReportData>().Where(x => x.FamilyId == model.familyid && x.CreateTime >= model.StartTime && x.CreateTime <= model.EndTime && devtypes.Contains(x.DevType)).OrderBy(x => x.CreateTime, OrderByType.Desc)
.GroupBy(x => new
{
x.CreateTime
})
.Select(x => new YB_FamilyReportData
{
CreateTime = x.CreateTime,
Height = SqlFunc.AggregateMax(x.Height),
Weight = SqlFunc.AggregateMax(x.Weight),
Head = SqlFunc.AggregateMax(x.Head)
})
.ToListAsync();
glist.AddRange(query);
var list = glist.Adapt<List<ChildGrowthModel>>();
return new ResultInfo(ResultState.SUCCESS, "success", list);
}
/// <summary>
/// 获取身高/体重成长测评报告,与标准身高进行对比
/// </summary>
/// <param name="familyid"></param>
/// <param name="devtype">设备类型</param>
/// <returns></returns>
public async Task<ResultInfo> GetHWListAsync(int familyid, int devtype)
{
var family = await dbClient.Queryable<YB_Family>().FirstAsync(x => x.Id == familyid);
if (family == null)
{
return new ResultInfo(ResultState.FAIL, "家庭成员未找到");
}
//如果时间段包含今天则加载今日数据
List<int> devtypes = await _deviceTypeService.GetDevTypesAsync(devtype);
List<YB_FamilyReportData> glist = new List<YB_FamilyReportData>();
DateTime nowtime = DateTime.Now.Date;
DateTime starttime = nowtime.AddDays(-nowtime.Day).AddDays(1);//月初
DateTime endtime = starttime.AddYears(-1);
var familyrealdatalist = await dbClient.Queryable<YB_FamilyRealData>().Where(x => x.FamilyId == familyid && x.DevType == devtype).FirstAsync();
if (familyrealdatalist != null && (familyrealdatalist.MonthHeight > 0 || familyrealdatalist.MonthWeight > 0))
{
glist.Add(new YB_FamilyReportData
{
Head = familyrealdatalist.MonthHead,
Weight = familyrealdatalist.MonthWeight,
Height = familyrealdatalist.MonthHeight,
CreateTime = nowtime
});
}
var tempquery = dbClient.Queryable<YB_FamilyReportData>()
.Where(x => x.FamilyId == familyid && x.CreateTime < starttime && x.CreateTime >= endtime && x.DevType == devtype);
var query = await tempquery
.OrderBy(x => x.CreateTime, OrderByType.Desc)
.ToListAsync();
glist.AddRange(query);
var hlist = new List<ChildWHModel>();
var wlist = new List<ChildWHModel>();
var headlist = new List<ChildWHModel>();
//如果年龄过大,则标准体重使用算法
int age = family.Birthday.ToAge();
if (age > 16)
{
glist.ForEach(x =>
{
hlist.Add(new ChildWHModel
{
Time = x.CreateTime.ToYearMonth(),
Value = x.Height,
StandValue = x.Height
});
wlist.Add(new ChildWHModel
{
Time = x.CreateTime.ToYearMonth(),
Value = x.Weight.ToDecimal(1),
StandValue = _bodyFatHelperService.CalcStandWeight(x.Height, (GenderType)family.Sex)
});
headlist.Add(new ChildWHModel
{
Time = x.CreateTime.ToYearMonth(),
Value = x.Head.ToDecimal(1),
StandValue = 0
});
});
}
else
{
var sheightlist = await dbClient.Queryable<YB_NewHeightStand>().Where(x => x.Sex == family.Sex).OrderBy(x => x.Month, OrderByType.Asc).ToListAsync();
var sweightlist = await dbClient.Queryable<YB_NewWeightStand>().Where(x => x.Sex == family.Sex).OrderBy(x => x.Month, OrderByType.Asc).ToListAsync();
var sheadlist = await dbClient.Queryable<YB_HeadStand>().Where(x => x.Sex == family.Sex).OrderBy(x => x.Month, OrderByType.Asc).ToListAsync();
glist.ForEach(x =>
{
int month = family.Birthday.ToMonth(x.CreateTime);
var standheight = sheightlist.Where(x => x.Month >= month).FirstOrDefault();
var standweight = sweightlist.Where(x => x.Month >= month).FirstOrDefault();
var standhead = sheadlist.Where(x => x.Month >= month).FirstOrDefault();
hlist.Add(new ChildWHModel
{
Time = x.CreateTime.ToYearMonth(),
Value = x.Height,
StandValue = standheight != null ? standheight.median.ToDecimal(1) : 0
});
wlist.Add(new ChildWHModel
{
Time = x.CreateTime.ToYearMonth(),
Value = x.Weight.ToDecimal(1),
StandValue = standweight != null ? standweight.median.ToDecimal(1) : 0
});
headlist.Add(new ChildWHModel
{
Time = x.CreateTime.ToYearMonth(),
Value = x.Head.ToDecimal(1),
StandValue = standhead != null ? standhead.median.ToDecimal(1) : 0
});
});
}
return new ResultInfo(ResultState.SUCCESS, "success", new
{
hlist = hlist,
wlist = wlist,
headlist = headlist
});
}
/// <summary>
/// 计算遗传身高和成年身高
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public async Task<ResultInfo> PredictHeightAsync(ChildPredictHeightModel model)
{
var standdata = new LevelS2SDto();
//遗传/标准身高
decimal geneticheight = 0;
//成年身高预测
decimal adultheight = 0;
//如果是安邦小程序则使用安邦标准
if (model.AppId == ABConst.MiniAppId)
{
standdata = await _abLevelService.LevelAsync(model.sex, model.Birthday, model.Height, LevelType.Height);
geneticheight = standdata.Media;
adultheight = AbAdultHeight(model.DadHeight, model.MomHeight, model.sex);
}
else
{
standdata = await _levelService.LevelAsync(model.sex, model.Birthday, model.Height, LevelType.Height);
geneticheight = standdata.Media;
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,
ErrorValue = model.sex == GenderType.Male ? 7.5m : 6m
});
}
/// <summary>
/// 获取儿童增量信息
/// </summary>
/// <param name="familyid"></param>
/// <param name="devtype">设备类型</param>
/// <param name="appid">小程序appid</param>
/// <returns></returns>
public async Task<ResultInfo> GetYearHeightInfoAsync(int familyid, int devtype, string appid)
{
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_FamilyRealData>().FirstAsync(x => x.FamilyId == familyid && x.DevType == devtype);
int month = family.Birthday.ToMonth();
int age = family.Birthday.ToAge();
LevelS2SDto standdata = new LevelS2SDto();
decimal height = (familydata != null && familydata.LastHeight > 0) ? familydata.LastHeight : family.Height;
//如果是安邦小程序则使用安邦标准
if (appid == ABConst.MiniAppId)
{
standdata = await _abLevelService.LevelAsync(family.Sex, family.Birthday, height, LevelType.Height);
}
else
{
standdata = await _levelService.LevelAsync(family.Sex, family.Birthday, height, LevelType.Height);
}
var returndata = new ChildYearHeightModel
{
f1sd = standdata.Data != null ? standdata.Data.f1sd : 0,
f2sd = standdata.Data != null ? standdata.Data.f2sd : 0,
f3sd = standdata.Data != null ? standdata.Data.f3sd : 0,
z1sd = standdata.Data != null ? standdata.Data.z1sd : 0,
z2sd = standdata.Data != null ? standdata.Data.z2sd : 0,
z3sd = standdata.Data != null ? standdata.Data.z3sd : 0,
Height = height,
HalfYearHeight = familydata != null && familydata.HalfYearHeight > 0 ? familydata.LastHeight - familydata.HalfYearHeight : 0, //如果半年前身高为0则表示未测量过,则增量为0
median = standdata.Data != null ? standdata.Data.median : 0,
HalfYearStandHeight = HalfYearStandHeight(age),
YearHeight = familydata != null && familydata.YearHeight > 0 ? familydata.LastHeight - familydata.YearHeight : 0,
YearStandHeight = YearStandHeight(age),
HeightLevel = standdata != null ? standdata.HeightLevel : ChildHeightLevel.Error,
list = standdata.list
};
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="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, GenderType sex)
=> (dadheight, momheight, sex) switch
{
_ when dadheight <= 0 || momheight <= 0 => 0,
_ when (sex == GenderType.FeMale) => (37.85m + 0.75m * (dadheight + momheight) / 2).ToDecimal(1),
_ => (45.99m + 0.78m * (dadheight + momheight) / 2).ToDecimal(1)
};
/// <summary>
/// 安邦成年身高预测,男孩=(爸爸+妈妈+13➗2最终结果±7.5
/// 女孩:(爸爸+妈妈-13➗2最终结果±6
/// </summary>
/// <param name="dadheight"></param>
/// <param name="momheight"></param>
/// <param name="sex"></param>
/// <returns></returns>
private static decimal AbAdultHeight(decimal dadheight, decimal momheight, GenderType sex)
=> (dadheight, momheight, sex) switch
{
_ when dadheight <= 0 || momheight <= 0 => 0,
_ when (sex == GenderType.FeMale) => (dadheight + momheight - 13) / 2.ToDecimal(1),
_ => (dadheight + momheight + 13) / 2.ToDecimal(1)
};
/// <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
};
}
}