using Microsoft.EntityFrameworkCore;
using VOL.Entity.DomainModels.XinWei;
using YD_YiLu.Api.Context;
using YD_YiLu.Api.Services.Interface;
using YD_YiLu.Api.SmartSportsEntitys;
using YD_YiLu.Api.Utilities;
using YD_YiLu.Commons;
using YD_YiLu.Commons.Dto.DeviceSync;
using YD_YiLu.Commons.Utils;
namespace YD_YiLu.Api.Services.Impl
{
///
/// 壹动站/壹体屏/活力课间屏 设备同步服务实现
///
public class DeviceSyncService : IDeviceSyncService
{
private readonly SmartSportsContext _context;
public DeviceSyncService(SmartSportsContext context)
{
_context = context;
}
public async Task GetOrgIdByDeviceAsync(string deviceSerial)
{
var device = await _context.YL_Device.FirstOrDefaultAsync(x => x.SerialNumber == deviceSerial);
if (device?.OrgId != null)
return device.OrgId;
else return 0;
}
public async Task UserPageAsync(DeviceSyncUserPageRequestDto dto)
{
var orgId = await GetOrgIdByDeviceAsync(dto.DeviceSerial);
if (!orgId.HasValue) return new DeviceSyncUserPageResponseDto();
string schoolCode = await _context.School.Where(x => x.Id == orgId).Select(x => x.SchoolCode).FirstAsync();
var query = _context.Student.Where(x => x.SchoolCode == schoolCode);
//if (dto.UserType == 1) query = query.Where(x => false);
//else if (dto.UserType == 2) { }
//else if (dto.UserType == 3) query = query.Where(x => false);
var total = await query.CountAsync();
var pageIndex = dto.PageIndex < 1 ? 1 : dto.PageIndex;
var fullSync = dto.FullSync || dto.PageSize <= 0;
var pageSize = fullSync ? total : (dto.PageSize <= 0 ? 10 : dto.PageSize);
var listQuery = query.OrderBy(x => x.Id);
if (!fullSync)
listQuery = (IOrderedQueryable)listQuery.Skip((pageIndex - 1) * pageSize).Take(pageSize);
var list = await listQuery
.Select(s => new DeviceSyncUserDto
{
UserId = s.Id,
UserType = 2,
Username = s.StudentNo,
Nickname = s.StudentName,
GradeName = "",
OrganizationId = s.Id,
OrganizationName = s.ClassName ?? "",
FacePictureUrl = s.Photo ?? "",
Identity = "学生",
Gender = s.Sex == 1 ? "男" : "女",
Birthday = s.Birthday.HasValue ? s.Birthday.Value.ToString("yyyy-MM-dd") : "",
UserSerial = s.StudentNo,
})
.ToListAsync();
foreach (var u in list)
{
var c = await _context.Class.FindAsync(u.OrganizationId);
if (c != null)
{
u.OrganizationName = c.ClassName ?? "";
u.GradeName = c.GradeName ?? "";
}
}
return new DeviceSyncUserPageResponseDto
{
SyncId = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
Current = fullSync ? 1 : pageIndex,
Pages = fullSync ? 1 : (total == 0 ? 0 : (int)Math.Ceiling(total / (double)Math.Max(pageSize, 1))),
Total = total,
UserList = list
};
}
public async Task UserSyncAsync(string deviceSerial, int deviceType, int userType)
{
return await UserPageAsync(new DeviceSyncUserPageRequestDto
{
DeviceSerial = deviceSerial,
DeviceType = deviceType,
UserType = userType,
PageIndex = 1,
FullSync = true,
PageSize = 0
});
}
public async Task> OrganizationAsync(DeviceSyncOrganizationRequestDto dto)
{
var orgId = await GetOrgIdByDeviceAsync(dto.DeviceSerial);
if (!orgId.HasValue) return new List();
string schoolCode = await _context.School.Where(x => x.Id == orgId).Select(x => x.SchoolCode).FirstAsync();
var grades = await _context.Grade.Where(x => x.SchoolCode == schoolCode).OrderBy(x => x.Id).ToListAsync();
var classes = await _context.Class.Where(x => x.SchoolCode == schoolCode).ToListAsync();
var result = new List();
foreach (var g in grades)
{
var gradeClasses = classes.Where(x => x.GradeId == g.Id).ToList();
result.Add(new DeviceSyncOrganizationDto
{
OrganizationId = g.Id,
ParentId = 0,
ParentName = null,
OrganizationName = g.GradeName,
OrganizationType = "年级",
Children = gradeClasses.Select(c => new DeviceSyncOrganizationDto
{
OrganizationId = c.Id,
ParentId = g.Id,
ParentName = g.GradeName,
OrganizationName = c.ClassName ?? "",
OrganizationType = "班级",
ChildrenIds = new List()
}).ToList(),
ChildrenIds = gradeClasses.Select(x => x.Id).ToList()
});
}
return result;
}
public async Task> TrainPushAsync(List list)
{
if (list == null || !list.Any())
return new List();
var result = new List();
// 👉 1. 设备校验(可选,看你业务)
var orgId = await GetOrgIdByDeviceAsync(list.First().DeviceSerial);
if (!orgId.HasValue)
return result;
// 👉 2. 批量查已存在的 TrainSerial(防重复)
var trainSerials = list.Select(x => x.TrainSerial).ToList();
var existSerials = await _context.YL_Train
.Where(x => trainSerials.Contains(x.TrainSerial))
.Select(x => x.TrainSerial)
.ToListAsync();
var newEntities = new List();
foreach (var item in list)
{
// 👉 3. 唯一校验(跳过已存在)
if (existSerials.Contains(item.TrainSerial))
continue;
var entity = new YL_Train
{
DeviceSerial = item.DeviceSerial,
DeviceType = item.DeviceType,
UserSerial = item.UserSerial,
TrainSerial = item.TrainSerial,
VideoSerial = item.VideoSerial,
TrainExam = item.TrainExam,
QuizId = item.QuizId,
StandardCounts = item.StandardCounts,
UnStandardCounts = item.UnStandardCounts,
TimeKeeping = item.TimeKeeping,
Duration = item.Duration,
Distance = item.Distance,
CourseId = item.CourseId,
StartTime = Util.ParseDateTime(item.StartTime),
EndTime = Util.ParseDateTime(item.EndTime),
// 👉 成绩计算(建议统一规则)
Score = CalculateScore(item),
IsValid = 1, // 默认有效
UploadTime = DateTime.Now,
CreateTime = DateTime.Now
};
newEntities.Add(entity);
}
// 👉 4. 批量入库(关键优化点)
if (newEntities.Any())
{
_context.YL_Train.AddRange(newEntities);
await _context.SaveChangesAsync();
}
// 👉 5. 返回结果
result = newEntities.Select(x => new DeviceSyncTrainPushResponseItem
{
TrainId = x.Id,
UserSerial = x.UserSerial
}).ToList();
return result;
}
private double? CalculateScore(DeviceSyncTrainPushRequestDto item)
{
// 👉 根据课目类型决定成绩字段
// 这里给你一个通用策略(你可以按课目细化)
// 计数类(跳绳/仰卧起坐)
if (item.StandardCounts > 0)
return item.StandardCounts;
// 计时类(悬垂)
if (item.TimeKeeping.HasValue)
return item.TimeKeeping;
// 距离类(跳远)
if (item.Distance.HasValue)
return item.Distance;
return null;
}
public async Task TrainDetailsAsync(int trainId)
{
// 1. 获取训练记录
var train = await _context.YL_Train.FirstOrDefaultAsync(t => t.Id == trainId);
if (train == null) return null;
// 2. 获取学生信息
var student = await _context.Student.FirstOrDefaultAsync(s => s.StudentNo == train.UserSerial);
if (student == null) return null;
// 3. 最近10次训练记录(CountList)
var recentTrains = await _context.YL_Train
.Where(t => t.UserSerial == train.UserSerial && t.CourseId == train.CourseId)
.OrderByDescending(t => t.StartTime)
.Take(10)
.Select(t => new CountListItem
{
TrainId = t.Id,
Score = (t.Score ?? 0).ToString("0"), // 先拿数值
Time = t.StartTime.ToString("yyyy-MM-dd HH:mm:ss")
})
.AsNoTracking() // 可选,提高性能
.ToListAsync();
// 在内存中格式化
var recentTrainsDto = recentTrains
.Select(t => new CountListItem
{
TrainId = t.TrainId,
Score = t.Score, // 格式化整数
Time = t.Time
})
.ToList();
// 4. 近10日最佳成绩(DailyList)
var tenDaysAgo = DateTime.Now.Date.AddDays(-10);
var dailyScores = await _context.YL_Train
.Where(t => t.UserSerial == train.UserSerial
&& t.CourseId == train.CourseId
&& t.StartTime >= tenDaysAgo)
.GroupBy(t => t.StartTime.Date)
.Select(g => new
{
Date = g.Key,
MaxScore = g.Max(t => t.Score) ?? 0
})
.OrderByDescending(g => g.Date)
.ToListAsync();
// 在内存中格式化
var dailyListDto = dailyScores
.Select(d => new DailyListItem
{
Score = d.MaxScore.ToString("0"),
Time = d.Date.ToString("yyyy-MM-dd 00:00:00")
})
.ToList();
// 5. 课程名称(枚举描述)
string courseName = Util.GetEnumDescription(train.CourseId);
// 6. 返回 DTO
return new DeviceSyncTrainDetailsDto
{
TrainId = train.Id,
UserSerial = train.UserSerial,
UserType = 2, // 学生
Nickname = student.StudentName,
FacePictureUrl = student.Photo ?? "",
Identity = "学生",
OrganizationId = (int)student.ClassId,
OrganizationName = student.ClassName,
Gender = student.Sex == 1 ? "男" : "女",
Score = train.Score?.ToString("0") ?? "0",
UnStandardCounts = train.UnStandardCounts,
CourseId = train.CourseId,
CourseName = courseName,
TrainType = "自由练习",
VideoUrl = train.VideoSerial,
StartTime = train.StartTime.ToString("yyyy-MM-dd HH:mm:ss"),
EndTime = train.EndTime.ToString("yyyy-MM-dd HH:mm:ss"),
CountList = recentTrains,
DailyList = dailyListDto,
KeyframeList = new List() // 暂时为空
};
}
public async Task> GradeOrderAsync(DeviceSyncGradeOrderRequestDto dto)
{
// 1️⃣ 获取组织ID
var orgId = await GetOrgIdByDeviceAsync(dto.DeviceSerial);
if (!orgId.HasValue) return new List();
// 2️⃣ 获取学校编码
string schoolCode = await _context.School
.Where(x => x.Id == orgId)
.Select(x => x.SchoolCode)
.FirstAsync();
var (start, end) = GetDateRange(dto.DateType, dto.QueryStartTime, dto.QueryEndTime);
// 4️⃣ 主查询(YL_Train + Student)
var query = from t in _context.YL_Train
join s in _context.Student on t.UserSerial equals s.StudentNo
where s.SchoolCode == schoolCode
select new { t, s };
// 5️⃣ 条件过滤
if (dto.CourseId.HasValue)
query = query.Where(x => x.t.CourseId == dto.CourseId.Value);
if (dto.Gender > 0)
query = query.Where(x => x.s.Sex == dto.Gender.Value);
if (dto.OrganizeId != null && dto.OrganizeId.Count > 0 && dto.OrganizeId[0] > 0)
query = query.Where(x => dto.OrganizeId.Contains(x.s.ClassId ?? 0));
if (start.HasValue)
query = query.Where(x => x.t.StartTime >= start.Value);
if (end.HasValue)
query = query.Where(x => x.t.StartTime < end.Value.AddDays(1));
// 6️⃣ 分组求总成绩并排序
var grouped = await query
.GroupBy(x => new { x.s.Id, x.s.StudentName, x.s.ClassId, x.s.ClassName, x.s.Sex, x.t.CourseId })
.Select(g => new
{
Key = g.Key,
Score = g.Sum(x => x.t.Score ?? 0)
})
.OrderByDescending(x => x.Score)
.Skip((dto.Page - 1) * dto.Size)
.Take(dto.Size)
.ToListAsync(); // ✅ 确保在此处完成
// 7️⃣ 返回结果
return grouped.Select(x => new DeviceSyncGradeOrderItemDto
{
UserId = x.Key.Id,
Nickname = x.Key.StudentName,
OrganizationId = x.Key.ClassId ?? 0,
OrganizationName = x.Key.ClassName ?? "",
Gender = x.Key.Sex,
Score = Math.Round(x.Score).ToString("0"),
CourseId = x.Key.CourseId,
CourseName = Util.GetEnumDescription(x.Key.CourseId)
}).ToList();
}
public async Task> LastGradeAsync(DeviceSyncLastGradeRequestDto dto)
{
if (dto?.UserSerials == null || dto.UserSerials.Count == 0)
return new List();
var serials = dto.UserSerials
.Where(x => !string.IsNullOrWhiteSpace(x))
.Select(x => x.Trim())
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
var students = await _context.Student
.Where(s => serials.Contains(s.StudentNo))
.ToListAsync();
var studentSerials = students.Select(s => s.StudentNo).ToList();
var trains = await _context.YL_Train
.Where(t => studentSerials.Contains(t.UserSerial))
.ToListAsync();
// 👉 人 + 课程 聚合
var trainGroup = trains
.GroupBy(t => new { t.UserSerial, t.CourseId })
.ToDictionary(
g => (g.Key.UserSerial, g.Key.CourseId),
g => new
{
Best = g.Max(x => x.Score ?? 0),
Last = g.OrderByDescending(x => x.EndTime).FirstOrDefault()?.Score ?? 0
});
// 👉 课程枚举(必须全返回)
var courseIds = new List { 2, 7, 8, 9, 10, 11 };
var result = new List();
foreach (var serial in serials)
{
var st = students.FirstOrDefault(s => s.StudentNo == serial);
var user = new DeviceSyncUserDto
{
UserId = st?.Id ?? 0,
UserType = 0, // 你自己定义
Username = st?.StudentNo ?? serial,
Nickname = st?.StudentName ?? "",
OrganizationId = st?.ClassId ?? 0,
OrganizationName = st?.ClassName ?? "",
GradeName = "", // 没有就空
FacePictureUrl = st?.Photo ?? "",
Identity = "", // 可选
Gender = st == null ? "" : (st.Sex == 1 ? "男" : "女"),
Birthday = st?.Birthday?.ToString("yyyy-MM-dd") ?? "",
UserSerial = serial
};
// 👉 构造 trainLimitValues
foreach (var cid in courseIds)
{
if (trainGroup.TryGetValue((serial, cid), out var val))
{
user.TrainLimitValues.Add(new TrainLimitValueDto
{
CourseId = cid,
BestResult = Math.Round(val.Best).ToString("0"),
LastResult = Math.Round(val.Last).ToString("0")
});
}
else
{
user.TrainLimitValues.Add(new TrainLimitValueDto
{
CourseId = cid,
BestResult = "0",
LastResult = "0"
});
}
}
result.Add(user);
}
return result;
}
public async Task> RecordAppAsync(DeviceSyncRecordAppRequestDto dto)
{
var orgId = await GetOrgIdByDeviceAsync(dto.DeviceSerial);
if (!orgId.HasValue)
return new List();
// 👉 1. 学校编码
string schoolCode = await _context.School
.Where(x => x.Id == orgId)
.Select(x => x.SchoolCode)
.FirstAsync();
// 👉 2. 时间范围
var (start, end) = GetDateRange(dto.DateType, dto.QueryStartTime, dto.QueryEndTime);
// 👉 3. 主查询(YL_Train + Student)
var query = from t in _context.YL_Train
join s in _context.Student on t.UserSerial equals s.StudentNo
where s.SchoolCode == schoolCode
select new { t, s };
// 👉 4. 条件过滤
if (dto.CourseId.HasValue)
query = query.Where(x => x.t.CourseId == dto.CourseId.Value);
if (dto.Gender > 0)
query = query.Where(x => x.s.Sex == dto.Gender.Value);
if (!string.IsNullOrEmpty(dto.UserSerial))
query = query.Where(x => x.t.UserSerial == dto.UserSerial);
if (!string.IsNullOrEmpty(dto.UserName))
query = query.Where(x => x.s.StudentName.Contains(dto.UserName));
if (dto.OrganizeId != null && dto.OrganizeId.Count > 0)
query = query.Where(x => dto.OrganizeId.Contains(x.s.ClassId ?? 0));
if (start.HasValue)
query = query.Where(x => x.t.StartTime >= start.Value);
if (end.HasValue)
query = query.Where(x => x.t.StartTime < end.Value.AddDays(1));
// 👉 5. 分页 + 排序
var list = await query
.OrderByDescending(x => x.t.StartTime)
.Skip((dto.Page - 1) * dto.Size)
.Take(dto.Size)
.Select(x => new DeviceSyncRecordAppItemDto
{
TrainId = x.t.Id,
Nickname = x.s.StudentName,
OrganizationId = x.s.ClassId ?? 0,
OrganizationName = x.s.ClassName,
Gender = x.s.Sex,
FacePictureUrl = x.s.Photo,
Score = x.t.Score.HasValue ? x.t.Score.Value.ToString("0.##") : "0",
StartTime = x.t.StartTime.ToString("yyyy-MM-dd HH:mm:ss"),
EndTime = x.t.EndTime.ToString("yyyy-MM-dd HH:mm:ss"),
CourseId = x.t.CourseId,
CourseName = Util.GetEnumDescription(x.t.CourseId), // 👉 建议后面接字典表
})
.ToListAsync();
return list;
}
public async Task MyRecordAsync(DeviceSyncMyRecordRequestDto dto)
{
var result = new DeviceSyncMyRecordResponseDto();
var orgId = await GetOrgIdByDeviceAsync(dto.DeviceSerial);
if (!orgId.HasValue) return result;
// 👉 1. 查学生
string schoolCode = await _context.School
.Where(x => x.Id == orgId)
.Select(x => x.SchoolCode)
.FirstAsync();
var student = await _context.Student
.FirstOrDefaultAsync(x => x.SchoolCode == schoolCode && x.StudentNo == dto.UserSerial);
if (student == null) return result;
var c = await _context.Class.FindAsync(student.ClassId);
// 👉 2. 时间范围
var (start, end) = GetDateRange(dto.DateType, dto.QueryStartTime, dto.QueryEndTime);
var query = _context.YL_Train
.Where(x => x.UserSerial == dto.UserSerial);
if (start.HasValue)
query = query.Where(x => x.StartTime >= start.Value);
if (end.HasValue)
query = query.Where(x => x.StartTime < end.Value.AddDays(1));
if (dto.CourseType > 0)
query = query.Where(x => x.CourseId == dto.CourseType);
var trains = await query.ToListAsync();
if (!trains.Any())
return result;
// 👉 3. 统计
var trainDays = trains.Select(x => x.StartTime.Date).Distinct().Count();
var totalSeconds = trains.Sum(x => x.Duration);
var trainHours = (totalSeconds / 3600.0).ToString("0.00");
// 👉 4. gradeList(按天统计)
var gradeList = trains
.GroupBy(x => x.StartTime.Date)
.Select(g => new GradeListItem
{
Time = g.Key.ToString("yyyy-MM-dd"),
Duration = g.Sum(x => x.Duration).ToString(),
Count = g.Sum(x => x.StandardCounts).ToString()
}).ToList();
// 👉 5. graphTrainList(课目统计)
var graphList = trains
.GroupBy(x => x.CourseId)
.Select(g => new GraphTrainListItem
{
CourseId = g.Key,
CourseName = Util.GetEnumDescription(g.Key),
Time = g.Sum(x => x.Duration).ToString(),
Count = g.Count()
}).ToList();
// 👉 6. courseBestList(最好/平均/最差)
var courseBestList = trains
.Where(x => x.Score.HasValue)
.GroupBy(x => x.CourseId)
.Select(g => new CourseBestListItem
{
CourseId = g.Key,
CourseName = Util.GetEnumDescription(g.Key),
BestGrade = g.Max(x => x.Score).ToString(),
AvgGrade = g.Average(x => x.Score).ToString(),
WorstGrade = g.Min(x => x.Score).ToString()
}).ToList();
// 👉 7. 返回
result = new DeviceSyncMyRecordResponseDto
{
UserSync = new UserSyncDto
{
UserId = student.Id,
UserType = 2,
Nickname = student.StudentName,
OrganizationId = student.ClassId ?? 0,
OrganizationName = c?.ClassName ?? "",
FacePictureUrl = student.Photo,
Identity = "学生",
Gender = student.Sex == 1 ? "男" : "女",
Birthday = student.Birthday?.ToString("yyyy-MM-dd") ?? "",
UserSerial = student.StudentNo,
Height = "",
Weight = ""
},
TrainCourseSum = graphList.Count,
TrainDays = trainDays,
TrainHours = trainHours,
TrainCounts = trains.Count,
GradeList = gradeList,
GraphTrainList = graphList,
//CourseBestList = courseBestList
};
return result;
}
public async Task TeacherLoginAsync(TeacherLoginRequestDto dto)
{
var pwdHash = MD5Helper.MD5Encrypt32(dto.Password);
var user = await _context.Sys_User.FirstOrDefaultAsync(x => x.UserName == dto.Username && x.UserPwd == pwdHash);
if (user == null) return null;
var school = await _context.School.FirstOrDefaultAsync(x => x.SchoolCode == user.SchoolCode);
return new TeacherLoginResponseDto
{
UserId = user.User_Id,
Nickname = user.UserTrueName ?? user.UserName,
Username = user.UserName,
OrganizationId = school?.Id ?? 0,
OrganizationName = school?.SchoolName ?? user.SchoolName ?? "",
SerialNumber = user.UserName,
Classification = 1,
Gender = user.Gender
};
}
public async Task AppVerifyAsync(AppVerifyRequestDto dto)
{
// 1️⃣ 查询最新版本
var latest = await _context.Set()
.Where(x => x.ApplyName == dto.ApplyName
&& x.DeviceType == dto.DeviceType
&& x.HardwareType == dto.HardwareType
&& x.OperatingSystem == dto.OperatingSystem
&& x.Status == 1
&& x.PublishStatus == 1)
.OrderByDescending(x => x.IsLatest)
.ThenByDescending(x => x.VersionCode)
.FirstOrDefaultAsync();
// 2️⃣ 没有配置版本 → 不更新
if (latest == null)
{
return new AppVerifyResponseDto
{
VersionNumber = dto.VersionNumber,
NeedForcedUpdating = 0,
UpdateUrl = null,
HardwareType = dto.HardwareType,
ApplyName = dto.ApplyName
};
}
// 3️⃣ 版本比较(必须用 VersionCode)
int currentVersionCode = ParseVersionCode(dto.VersionNumber);
bool needUpdate = latest.VersionCode > currentVersionCode;
if (!needUpdate)
{
return new AppVerifyResponseDto
{
VersionNumber = dto.VersionNumber,
NeedForcedUpdating = 0,
UpdateUrl = null,
HardwareType = dto.HardwareType,
ApplyName = dto.ApplyName
};
}
// 4️⃣ 是否强制升级
bool needForce = latest.NeedForcedUpdating == 1;
// 最低版本限制(强制升级)
if (!string.IsNullOrEmpty(latest.MinSupportVersion))
{
if (CompareVersion(dto.VersionNumber, latest.MinSupportVersion) < 0)
{
needForce = true;
}
}
// 5️⃣ 返回结果
return new AppVerifyResponseDto
{
VersionNumber = latest.VersionNumber,
NeedForcedUpdating = needForce ? 1 : 0,
UpdateUrl = latest.UpdateUrl,
HardwareType = latest.HardwareType,
ApplyName = latest.ApplyName
};
}
///
/// 视频回放上传
///
///
///
public async Task DeviceVideoUploadAsync(DeviceVideoUploadRequestDto dto)
{
if (dto.File == null || dto.File.Length == 0)
return false;
// 1️⃣ 生成OSS路径(按我之前给你的规范)
var path = $"Upload/device/{dto.DeviceType}/{dto.DeviceSerial}/video/{dto.VideoSerial}/";
// 2️⃣ 上传到OSS
var url = ALiYunOss.Upload(dto.File, path, dto.VideoSerial);
if (string.IsNullOrEmpty(url))
return false;
// 3️⃣ 入库
var entity = new YL_DeviceVideo
{
DeviceSerial = dto.DeviceSerial,
DeviceType = dto.DeviceType,
VideoSerial = dto.VideoSerial,
VideoUrl = url,
Timestamp = dto.Timestamp,
CreateTime = DateTime.Now,
Status = 1
};
_context.Set().Add(entity);
await _context.SaveChangesAsync();
return true;
}
public async Task GetUserDetailAsync(string deviceSerial, int userId)
{
var orgId = await GetOrgIdByDeviceAsync(deviceSerial);
if (!orgId.HasValue) return null;
string schoolCode = await _context.School.Where(x => x.Id == orgId).Select(x => x.SchoolCode).FirstAsync();
var s = await _context.Student.FirstOrDefaultAsync(x => x.Id == userId && x.SchoolCode == schoolCode);
if (s == null) return null;
var dto = new DeviceSyncUserDto
{
UserId = s.Id,
UserType = 2,
Username = s.StudentNo,
Nickname = s.StudentName,
OrganizationId = s.ClassId ?? 0,
OrganizationName = s.ClassName ?? "",
GradeName = "",
FacePictureUrl = s.Photo ?? "",
Identity = "学生",
Gender = s.Sex == 1 ? "男" : "女",
Birthday = s.Birthday.HasValue ? s.Birthday.Value.ToString("yyyy-MM-dd") : "",
UserSerial = s.StudentNo
};
var c = await _context.Class.FindAsync(dto.OrganizationId);
if (c != null)
{
dto.OrganizationName = c.ClassName ?? "";
dto.GradeName = c.GradeName ?? "";
}
return dto;
}
private static (DateTime? start, DateTime? end) GetDateRange(int dateType, string queryStart, string queryEnd)
{
var now = DateTime.Now;
return dateType switch
{
1 => (now.Date, now.Date),
2 => (now.AddDays(-(int)now.DayOfWeek + 1).Date, now.Date),
3 => (new DateTime(now.Year, now.Month, 1), now.Date),
4 => (now.Month >= 9 ? new DateTime(now.Year, 9, 1) : new DateTime(now.Year - 1, 9, 1), now.Date),
5 => (DateTime.TryParse(queryStart, out var s) ? s : (DateTime?)null, DateTime.TryParse(queryEnd, out var e) ? e : (DateTime?)null),
_ => (null, null)
};
}
private int CompareVersion(string v1, string v2)
{
if (string.IsNullOrEmpty(v1) || string.IsNullOrEmpty(v2))
return 0;
var arr1 = v1.Split('.');
var arr2 = v2.Split('.');
int len = Math.Max(arr1.Length, arr2.Length);
for (int i = 0; i < len; i++)
{
int num1 = i < arr1.Length ? int.Parse(arr1[i]) : 0;
int num2 = i < arr2.Length ? int.Parse(arr2[i]) : 0;
if (num1 > num2) return 1;
if (num1 < num2) return -1;
}
return 0;
}
private int ParseVersionCode(string version)
{
if (string.IsNullOrEmpty(version))
return 0;
var parts = version.Split('.');
int code = 0;
for (int i = 0; i < parts.Length; i++)
{
if (int.TryParse(parts[i], out int num))
{
code = code * 100 + num;
}
}
return code;
}
}
}