293 lines
11 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 Microsoft.AspNetCore.Mvc;
using YD_Event.Application.Client.Dtos;
using YD_Event.Core.Entities;
using YD_Event.Core.Enum;
using SqlSugar;
using Furion.DatabaseAccessor;
using Microsoft.AspNetCore.Authorization;
using System.Security.Claims;
using Furion.FriendlyException;
namespace YD_Event.Application.Client;
/// <summary>
/// 小程序-个人中心接口
/// </summary>
[ApiDescriptionSettings("微信小程序接口")]
public class MyController : IDynamicApiController
{
private readonly ISqlSugarRepository<YD_Event.Core.Entities.AppUser> _appUserRepository;
private readonly ISqlSugarRepository<YD_Event.Core.Entities.Team> _teamRepository;
private readonly ISqlSugarRepository<EventCertificate> _certificateRepository;
private readonly ISqlSugarRepository<PointsRecord> _pointsRecordRepository;
private readonly ISqlSugarRepository<YD_Event.Core.Entities.Order> _orderRepository;
private readonly ISqlSugarRepository<EventRegistration> _registrationRepository;
private readonly ISqlSugarRepository<EventInfo> _eventRepository;
private readonly IHttpContextAccessor _httpContextAccessor;
public MyController(
ISqlSugarRepository<YD_Event.Core.Entities.AppUser> appUserRepository,
ISqlSugarRepository<YD_Event.Core.Entities.Team> teamRepository,
ISqlSugarRepository<EventCertificate> certificateRepository,
ISqlSugarRepository<PointsRecord> pointsRecordRepository,
ISqlSugarRepository<YD_Event.Core.Entities.Order> orderRepository,
ISqlSugarRepository<EventRegistration> registrationRepository,
ISqlSugarRepository<EventInfo> eventRepository,
IHttpContextAccessor httpContextAccessor)
{
_appUserRepository = appUserRepository;
_teamRepository = teamRepository;
_certificateRepository = certificateRepository;
_pointsRecordRepository = pointsRecordRepository;
_orderRepository = orderRepository;
_registrationRepository = registrationRepository;
_eventRepository = eventRepository;
_httpContextAccessor = httpContextAccessor;
}
private long GetCurrentUserId()
{
var userIdStr = _httpContextAccessor.HttpContext?.User?.FindFirst(AuthClaimsConst.AuthIdKey)?.Value;
if (string.IsNullOrEmpty(userIdStr) || !long.TryParse(userIdStr, out long userId))
{
throw Oops.Bah("未登录或登录已失效");
}
return userId;
}
/// <summary>
/// 获取个人主页信息
/// </summary>
/// <returns></returns>
[HttpGet("profile")]
public async Task<MyProfileDto> GetProfile()
{
var userId = GetCurrentUserId();
// 注意:AuthAccount.Id 和 AppUser.UserId 关联。这里假设登录的是 AuthAccount,需要查 AppUser
// 实际上 AppUser 表的 UserId 字段关联的是 AuthAccount 的 Id。
// 但 AppUser 本身也有 Id。
// 业务逻辑通常是:一个 AuthAccount 对应一个 AppUser。
var user = await _appUserRepository.GetFirstAsync(u => u.UserId == userId);
if (user == null) throw Oops.Bah("用户信息不存在");
// 统计证书数量
var certCount = await _certificateRepository.CountAsync(c => c.CreatedUserId == userId && c.CertificateStatus == 2);
// 积分 (需计算积分总和,PointsRecord 表有 Points 字段,Type 1-加 2-减)
// 简单计算:Sum(Type=1) - Sum(Type=2)
var pointsIn = await _pointsRecordRepository.AsQueryable().Where(p => p.UserId == userId && p.Type == PointsOperationType.Acquire).SumAsync(p => p.Points);
var pointsOut = await _pointsRecordRepository.AsQueryable().Where(p => p.UserId == userId && p.Type == PointsOperationType.Consume).SumAsync(p => p.Points);
var pointsBalance = (int)(pointsIn - pointsOut);
// 认证状态: AuditStatus: 0-待提交, 1-待审核, 2-通过, 3-拒绝.
int authStatus = 0;
if (string.IsNullOrEmpty(user.Name) || string.IsNullOrEmpty(user.IdCardNumber))
{
authStatus = 0; // 未认证
}
else if (user.AuditStatus == AuditStatus.Pass)
{
authStatus = 1; // 已认证
}
else if (user.AuditStatus == AuditStatus.PendingAudit)
{
authStatus = 2; // 审核中
}
else
{
authStatus = 3; // 失败/其他
}
return new MyProfileDto
{
NickName = user.NickName ?? "微信用户",
Avatar = user.Avatar ?? "",
Mobile = MaskMobile(user.Mobile),
Points = pointsBalance,
CertificateCount = certCount,
AuthStatus = authStatus
};
}
/// <summary>
/// 获取实名认证信息
/// </summary>
/// <returns></returns>
[HttpGet("auth")]
public async Task<MyAuthInfoDto> GetAuthInfo()
{
var userId = GetCurrentUserId();
var user = await _appUserRepository.GetFirstAsync(u => u.UserId == userId);
if (user == null) throw Oops.Bah("用户信息不存在");
return new MyAuthInfoDto
{
Name = user.Name,
Mobile = user.Mobile,
IdCardNumber = user.IdCardNumber, // 可以在前端脱敏
IdCardImageUrl = user.IdCardImageUrl,
AuditStatus = user.AuditStatus,
AuditRemark = user.AuditRemark
};
}
/// <summary>
/// 提交实名认证
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("auth")]
public async Task<bool> SubmitAuth([FromBody] SubmitAuthInput input)
{
var userId = GetCurrentUserId();
var user = await _appUserRepository.GetFirstAsync(u => u.UserId == userId);
if (user == null) throw Oops.Bah("用户信息不存在");
if (user.AuditStatus == AuditStatus.Pass) throw Oops.Bah("已通过实名认证,无需重复提交");
if (user.AuditStatus == AuditStatus.PendingAudit) throw Oops.Bah("审核中,请勿重复提交");
user.Name = input.Name;
user.Mobile = input.Mobile;
user.IdCardNumber = input.IdCardNumber;
user.IdCardImageUrl = input.IdCardImageUrl;
user.AuditStatus = AuditStatus.PendingAudit; // 提交后变更为待审核
user.UpdatedTime = DateTime.Now;
return await _appUserRepository.UpdateAsync(user);
}
/// <summary>
/// 我的团队列表
/// </summary>
/// <returns></returns>
[HttpGet("teams")]
public async Task<PageResult<MyTeamDto>> GetTeams([FromQuery] MyPageInput input)
{
var userId = GetCurrentUserId();
// 逻辑:查找我是创建人(队长) 或 队员的团队
// 目前 Team 表只有 CreatedUserId,假设 CreatedUserId 就是队长。
// 如果有 TeamMember 表关联队员,需要联表。目前假设只查我创建的团队(根据原型图"我的团队"通常指我管理的)。
// 如果原型包含"我加入的",需要查 TeamMember。
// 鉴于 TeamMember 实体未直接给出,这里先查 CreatedUserId = userId
var query = _teamRepository.AsQueryable()
.Where(t => t.CreatedUserId == userId && !t.DeleteMark)
.Select(t => new MyTeamDto
{
Id = t.Id,
Name = t.Name,
IsLeader = true,
MemberCount = 0 // 暂无 Member 表关联,置为 0 或需扩展
});
return await query.ToPagedListAsync(input);
}
/// <summary>
/// 我的证书列表
/// </summary>
/// <returns></returns>
[HttpGet("certificates")]
public async Task<PageResult<MyCertificateDto>> GetCertificates([FromQuery] MyPageInput input)
{
var userId = GetCurrentUserId();
// 联表查询 EventInfo 获取赛事名称
var query = _certificateRepository.AsQueryable()
.LeftJoin<EventInfo>((c, e) => c.EventId == e.Id)
.Where(c => c.CreatedUserId == userId && c.CertificateStatus == 2 && !c.DeleteMark)
.Select((c, e) => new MyCertificateDto
{
Id = c.Id,
EventName = e.EventName,
ProjectName = c.GroupName, // 暂时用 GroupName 代替 ProjectName,具体看 ProjectId 关联
CertificateName = "荣誉证书", // 此时可根据 CertificateType 转义
CertificateUrl = c.CertificateUrl,
IssuedTime = c.IssuedTime
})
.OrderByDescending(c => c.IssuedTime);
return await query.ToPagedListAsync(input);
}
/// <summary>
/// 我的积分记录
/// </summary>
/// <returns></returns>
[HttpGet("points")]
public async Task<PageResult<MyPointsRecordDto>> GetPoints([FromQuery] MyPageInput input)
{
var userId = GetCurrentUserId();
var query = _pointsRecordRepository.AsQueryable()
.Where(p => p.UserId == userId && !p.DeleteMark)
.Select(p => new MyPointsRecordDto
{
Id = p.Id,
Title = p.Remark ?? (p.Type == PointsOperationType.Acquire ? "获取积分" : "消耗积分"),
Points = p.Points,
Type = (int)p.Type,
CreatedTime = p.CreatedTime
})
.OrderByDescending(p => p.CreatedTime);
return await query.ToPagedListAsync(input);
}
/// <summary>
/// 我的订单列表
/// </summary>
/// <returns></returns>
[HttpGet("orders")]
public async Task<PageResult<MyOrderDto>> GetOrders([FromQuery] MyPageInput input)
{
var userId = GetCurrentUserId();
var query = _orderRepository.AsQueryable()
.LeftJoin<EventInfo>((o, e) => o.EventId == e.Id)
.Where(o => o.CreatedUserId == userId && !o.DeleteMark)
.Select((o, e) => new MyOrderDto
{
Id = o.Id,
OrderNo = o.OrderNo,
EventName = e.EventName,
Amount = o.ActualAmount,
Status = (int)o.OrderStatus,
CreatedTime = o.CreatedTime
})
.OrderByDescending(o => o.CreatedTime);
return await query.ToPagedListAsync(input);
}
/// <summary>
/// 我的参赛记录
/// </summary>
/// <returns></returns>
[HttpGet("registrations")]
public async Task<PageResult<MyRegistrationDto>> GetRegistrations([FromQuery] MyPageInput input)
{
var userId = GetCurrentUserId();
var query = _registrationRepository.AsQueryable()
.LeftJoin<EventInfo>((r, e) => r.EventId == e.Id)
.Where(r => r.CreatedUserId == userId && !r.DeleteMark)
.Select((r, e) => new MyRegistrationDto
{
Id = r.Id,
EventName = e.EventName,
TeamName = r.TeamName,
Status = r.RegistrationStatus,
RegistrationTime = r.RegistrationTime,
ProjectNames = "" // 暂空,需联表 EventRegistrationItem
})
.OrderByDescending(r => r.RegistrationTime);
return await query.ToPagedListAsync(input);
}
private string MaskMobile(string mobile)
{
if (string.IsNullOrEmpty(mobile) || mobile.Length < 7) return mobile;
return mobile.Substring(0, 3) + "****" + mobile.Substring(7);
}
}