Coreshop/CoreCms.Net.Web.WebApi/Controllers/SQController.cs
2025-09-15 17:51:30 +08:00

734 lines
26 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 AutoMapper;
using CoreCms.Net.Auth.HttpContextUser;
using CoreCms.Net.IRepository.UnitOfWork;
using CoreCms.Net.IServices;
using CoreCms.Net.Model.Entities;
using CoreCms.Net.Model.Entities.Expression;
using CoreCms.Net.Model.ViewModels.Basics;
using CoreCms.Net.Model.ViewModels.SQ;
using CoreCms.Net.Model.ViewModels.UI;
using CoreCms.Net.Services;
using CoreCms.Net.Services.SQ;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using NPOI.SS.Formula.Functions;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using CoreCms.Net.Services.SQ;
using CoreCms.Net.Utility.Extensions;
using ToolGood.Words.internals;
using NPOI.SS.Formula.PTG;
using NPOI.OpenXmlFormats.Dml;
using Humanizer;
namespace CoreCms.Net.Web.WebApi.Controllers;
/// <summary>
/// 预约接口
/// </summary>
[Route("api/[controller]/[action]")]
[ApiController]
public class SQController : ControllerBase
{
private readonly IWebHostEnvironment _webHostEnvironment;
private readonly ISQReservationsServices _SQReservationsServices;
private readonly ISQRoomsServices _SQRoomsServices;
private readonly ISysDictionaryDataServices _sysDictionaryDataServices;
private readonly ISysDictionaryServices _sysDictionaryServices;
private readonly ISQReservationParticipantsServices _SQReservationParticipantsServices;
private readonly IMapper _mapper;
private readonly ICoreCmsUserServices _userServices;
private readonly IHttpContextUser _user;
private readonly SqlSugarScope _dbBase;
private readonly ICoreCmsUserBlacklistServices _coreCmsUserBlacklistServices;
private readonly ISQReservationReputationServices _sQReservationReputationServices;
private readonly ISQReservationEvaluateServices _sQReservationEvaluateServices;
private readonly ISQRoomUnavailableTimesServices _sQRoomUnavailableTimesServices;
/// <summary>
/// 构造函数
///</summary>
public SQController(IWebHostEnvironment webHostEnvironment
, ISQReservationsServices SQReservationsServices
, ISQRoomsServices SQRoomsServices
, ISysDictionaryServices sysDictionaryServices
, ISysDictionaryDataServices sysDictionaryDataServices
, ISQReservationParticipantsServices sQReservationParticipantsServices
, IMapper mapper
, ICoreCmsUserServices userServices
, IHttpContextUser user
, IUnitOfWork unitOfWork
, ICoreCmsUserBlacklistServices coreCmsUserBlacklistServices
,
ISQReservationEvaluateServices sQReservationEvaluateServices
,
ISQReservationReputationServices sQReservationReputationServices
,
ISQRoomUnavailableTimesServices sQRoomUnavailableTimesServices
)
{
_webHostEnvironment = webHostEnvironment;
_SQReservationsServices = SQReservationsServices;
_SQRoomsServices = SQRoomsServices;
_sysDictionaryServices = sysDictionaryServices;
_sysDictionaryDataServices = sysDictionaryDataServices;
_SQReservationParticipantsServices = sQReservationParticipantsServices;
_mapper = mapper;
_userServices = userServices;
_user = user;
_dbBase = unitOfWork.GetDbClient();
_coreCmsUserBlacklistServices = coreCmsUserBlacklistServices;
_sQReservationEvaluateServices = sQReservationEvaluateServices;
_sQReservationReputationServices = sQReservationReputationServices;
_sQRoomUnavailableTimesServices = sQRoomUnavailableTimesServices;
}
/// <summary>
/// 我的预约记录
/// </summary>
/// <param name="type">0 参与者1发起者</param>
/// <param name="index">起始页</param>
/// <param name="size">页大小</param>
/// <returns></returns>
[HttpGet]
[Authorize]
public async Task<WebApiDto> GetMyReservation([FromQuery] int type = 0, [FromQuery] int index = 1, [FromQuery] int size = 10)
{
var userId = _user.ID;
var list = await _dbBase.Ado.SqlQueryAsync<SQReservationsMyDto>($"select r.*,p.id pid, p.status pstatus,p.join_time, p.quit_time ,p.is_refund from SQReservationParticipants p inner join SQReservations r on p.reservation_id=r.id where p.user_id={userId} and p.role={type} order by p.id desc OFFSET {(index - 1) * size} ROWS FETCH NEXT {size} ROWS ONLY");
if (list != null && list.Count > 0)
{
var roomList = await _SQRoomsServices.GetRoomList();
// 转为基类列表
var baseList = list.Cast<SQReservationsBaseDto>().ToList();
await baseList.LoadSQReservationParticipantsApiDto(userId, _dbBase, _coreCmsUserBlacklistServices, roomList, _mapper);
}
return new WebApiDto()
{
Data = list,
Code = 0,
};
}
/// <summary>
/// 获取正在进行的预约
/// </summary>
/// <returns></returns>
[HttpGet]
[Authorize]
public async Task<WebApiDto> GetMyUseReservation()
{
var userId = _user.ID;
var list = await _dbBase.Ado.SqlQueryAsync<SQReservationsApiDto>($"select top 3 r.* from SQReservations r left join SQReservationParticipants p on r.id=p.reservation_id where r.status<2 and p.user_id={userId} and p.status=0 order by r.start_time ");
if (list != null && list.Count > 0)
{
var roomList = await _SQRoomsServices.GetRoomList();
// 转为基类列表
var baseList = list.Cast<SQReservationsBaseDto>().ToList();
await baseList.LoadSQReservationParticipantsApiDto(userId, _dbBase, _coreCmsUserBlacklistServices, roomList, _mapper);
}
return new WebApiDto()
{
Data = list,
Code = 0,
};
}
/// <summary>
/// 首页预约列表
/// </summary>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <returns></returns>
[HttpGet]
public async Task<WebApiDto> GetReservationList([FromQuery] int pageIndex = 1, [FromQuery] int pageSize = 20)
{
var userId = _user.ID;
var now = DateTime.Now;
var roomList = await _SQRoomsServices.GetRoomList();
var where = PredicateBuilder.True<SQReservations>();
where = where.And(it => it.end_time > now);
where = where.And(it => it.status < 2);
var list = await _SQReservationsServices.QueryPageAsync(where, it => it.start_time, OrderByType.Asc, pageIndex, pageSize, true);
var pageList = _mapper.Map<List<SQReservationsApiDto>>(list);
if (pageList != null && pageList.Count > 0)
{
// 转为基类列表
var baseList = pageList.Cast<SQReservationsBaseDto>().ToList();
await baseList.LoadSQReservationParticipantsApiDto(userId, _dbBase, _coreCmsUserBlacklistServices, roomList, _mapper);
}
return new WebApiDto()
{
Data = pageList,
Code = 0,
Msg = "ok",
};
}
/// <summary>
/// 获取预约评价
/// </summary>
/// <param name="reId"></param>
/// <returns></returns>
[HttpGet]
[Authorize]
public async Task<WebApiDto> GetEvaluateServices([FromQuery] int reId)
{
var userId = _user.ID;
var list = await _sQReservationEvaluateServices.QueryListByClauseAsync(it => it.reservation_id == reId && it.user_id == userId);
var participants = await _dbBase.Ado.SqlQueryAsync<SQReservationParticipantsApiDto>($"select p.id,p.reservation_id,p.status,p.join_time,p.user_id, p.role,u.nickName UserName,u.avatarImage AvatarImage,ISNULL(u.play_level,4) play_level,ISNULL(u.skills_level,4) skills_level from SQReservationParticipants p inner join CoreCmsUser u on p.user_id=u.id where p.status=0 and p.reservation_id ={reId} and p.is_arrive=1 ");
if (participants == null || participants.Count == 0)
{
return new WebApiDto()
{
Code = 0,
Data = null
};
}
var userBlack = await _coreCmsUserBlacklistServices.GetUserBlacklists(userId);
List<object> obj = new List<object>();
foreach (var item in participants)
{
if (item.user_id == userId)
{
continue;
}
var is_evaluate = false;
decimal play_level = 0;
decimal skills_level = 0;
decimal user_play_level = 4;
decimal user_skills_level = 4;
DateTime? now = null;
var userBlackStatus = false;
if (list.Count > 0)
{
var e = list.Find(it => it.to_user_id == item.user_id);
if (e != null)
{
is_evaluate = true;
play_level = e.play_level;
skills_level = e.skills_level;
now = e.created_at;
user_play_level = e.play_level;
user_skills_level = e.skills_level;
}
}
if (userBlack.Count > 0)
{
if (userBlack.Any(it => it == item.user_id))
{
userBlackStatus = true;
}
}
var o = new
{
item.UserName,
item.user_id,
item.AvatarImage,
userBlackStatus,
user_play_level,
user_skills_level,
is_evaluate,
play_level,
skills_level,
evaluate_at = now
};
obj.Add(o);
}
return new WebApiDto()
{
Code = 0,
Data = obj
};
}
/// <summary>
/// 评价用户
/// </summary>
/// <param name="evaluate"></param>
/// <returns></returns>
[HttpPost]
[Authorize]
public async Task<WebApiDto> AddEvaluateServices([FromBody] SQReservationEvaluateDto evaluate)
{
var userId = _user.ID;
var reId = evaluate.reservation_id;
var list = await _sQReservationEvaluateServices.QueryListByClauseAsync(it => it.reservation_id == reId && it.user_id == userId);
var participants = await _dbBase.Ado.SqlQueryAsync<SQReservationParticipantsApiEavDto>($"select p.id,p.reservation_id,p.status,p.join_time,p.user_id, p.role,u.nickName UserName,u.avatarImage AvatarImage,ISNULL(u.play_level,4) play_level,ISNULL(u.skills_level,4) skills_level from SQReservationParticipants p inner join CoreCmsUser u on p.user_id=u.id where p.status=0 and p.reservation_id ={reId} and p.is_arrive=1 ");
if (participants == null)
{
return new WebApiDto()
{
Code = 0,
Data = null
};
}
List<object> obj = new List<object>();
var p = participants.Find(it => it.user_id == evaluate.to_user_id);
if (p == null)
{
return new WebApiDto()
{
Code = 500,
Data = null,
Msg = "未找到对局记录"
};
}
SQReservationEvaluate sQReservationEvaluate = new SQReservationEvaluate()
{
created_at = DateTime.Now,
play_level = evaluate.play_level,
reservation_id = evaluate.reservation_id,
role = p.role,
skills_level = evaluate.skills_level,
to_user_id = evaluate.to_user_id,
user_id = userId,
};
await _sQReservationEvaluateServices.InsertAsync(sQReservationEvaluate);
var play_level = _dbBase.Ado.SqlQuerySingle<SQReservationEvaluateFDto>($"select ISNULL(sum(play_level),0) level,count(1) rs_count from SQReservationEvaluate where to_user_id={evaluate.to_user_id} ");
var skills_level = _dbBase.Ado.SqlQuerySingle<SQReservationEvaluateFDto>($"select ISNULL(sum(skills_level),0) level,count(1) rs_count from SQReservationEvaluate where to_user_id={evaluate.to_user_id} ");
//先加4
play_level.level += 4;
if (play_level.rs_count > 0)
{
if (play_level.rs_count == 1)
{
play_level.rs_count++;
}
play_level.level = play_level.level / play_level.rs_count;
}
//先加4
skills_level.level += 4;
if (skills_level.rs_count > 0)
{
if (skills_level.rs_count == 1)
{
skills_level.rs_count++;
}
skills_level.level = skills_level.level / skills_level.rs_count;
}
if (play_level.rs_count > 0 || skills_level.rs_count > 0)
{
await _userServices.UpdateAsync(it => new CoreCmsUser
{
play_level = play_level.level,
skills_level = skills_level.level
}, it => it.id == evaluate.to_user_id);
}
return new WebApiDto()
{
Code = 0,
Data = null,
Msg = "评价成功"
};
}
/// <summary>
/// 获取我的声誉记录
/// </summary>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <returns></returns>
[HttpGet]
[Authorize]
public async Task<WebApiDto> GetReputationByUser([FromQuery] int pageIndex = 1, [FromQuery] int pageSize = 20)
{
var list = await _sQReservationReputationServices.QueryPageAsync(it => it.user_id == _user.ID, it => it.created_at, OrderByType.Desc, pageIndex, pageSize, true);
var o = new List<object>();
foreach (var item in list)
{
var c = new
{
item.created_at,
reputation_value = item.reputation_value.ToString("#.#"),
title = item.remark
};
o.Add(c);
}
return new WebApiDto()
{
Code = 0,
Data = o,
Msg = "ok",
};
}
/// <summary>
/// 获取评价我的记录
/// </summary>
/// <param name="pageIndex">页码</param>
/// <param name="pageSize">每页数量</param>
/// <returns></returns>
[HttpGet]
[Authorize]
public async Task<WebApiDto> GetEvaluateToMe([FromQuery] int pageIndex = 1, [FromQuery] int pageSize = 20)
{
var userId = _user.ID;
var list = await _sQReservationEvaluateServices.QueryPageAsync(
it => it.to_user_id == userId,
it => it.created_at,
OrderByType.Desc,
pageIndex,
pageSize,
true
);
return new WebApiDto()
{
Code = 0,
Data = list,
Msg = "ok"
};
}
/// <summary>
/// 获取可预约的房间列表
/// </summary>
/// <param name="startTime">开始时间 时间戳</param>
/// <param name="endTime">结束时间 时间戳</param>
/// <returns></returns>
[HttpGet]
public async Task<WebApiDto> GetReservationRoomList([FromQuery] long startTime, [FromQuery] long endTime)
{
if (startTime == 0 || endTime == 0)
{
return new WebApiDto()
{
Code = 500,
Data = null,
Msg = "参数错误"
};
}
// 时间戳转DateTime
var start = DateTimeOffset.FromUnixTimeSeconds(startTime).DateTime;
var end = DateTimeOffset.FromUnixTimeSeconds(endTime).DateTime;
// 1. 查询所有可用房间
var allRooms = await _SQRoomsServices.GetRoomList();
// 2. 查询有不可用时间段冲突的房间
var unavailableRoomIds = (await _sQRoomUnavailableTimesServices.QueryListByClauseAsync(
t => t.start_time < end && t.end_time > start
)).Select(t => t.room_id).Distinct().ToList();
// 3. 查询已被预约的房间(未取消的预约,时间有重叠)
var reservedRoomIds = (await _SQReservationsServices.QueryListByClauseAsync(
r => r.status < 2 && r.start_time < end && r.end_time > start
)).Select(r => r.room_id).Distinct().ToList();
// 4. 可预约房间 = 所有可用房间 - 不可用房间 - 已预约房间
var availableRooms = allRooms
.Where(r => r.status == true && !unavailableRoomIds.Contains(r.id) && !reservedRoomIds.Contains(r.id))
.OrderBy(r => r.name)
.Select(it => new { name = it.name + $" {it.price_per_hour.ToString("#.##")}/小时", it.id, it.capacity })
.ToList();
return new WebApiDto()
{
Code = 0,
Data = availableRooms,
Msg = "ok"
};
}
/// <summary>
/// 用户预约接口
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
[HttpPost]
[Authorize]
public async Task<WebApiDto> AddSQReservation([FromBody] SQReservationsAddDto dto)
{
var userId = _user.ID;
var start_time = DateTimeOffset.FromUnixTimeSeconds(dto.start_time).AddHours(8).DateTime;
var end_time = DateTimeOffset.FromUnixTimeSeconds(dto.end_time).AddHours(8).DateTime;
// 1. 参数校验
if (dto == null || dto.room_id <= 0 || start_time >= end_time)
{
return new WebApiDto()
{
Code = 500,
Data = null,
Msg = "参数错误"
};
}
// 2. 检查房间是否存在
var room = await _SQRoomsServices.QueryByClauseAsync(r => r.id == dto.room_id, r => r.id, OrderByType.Asc);
if (room == null)
{
return new WebApiDto()
{
Code = 500,
Data = null,
Msg = "房间不存在"
};
}
// 3. 检查房间是否可预约(不可用时间段)
var hasUnavailable = await _sQRoomUnavailableTimesServices.QueryListByClauseAsync(
t => t.room_id == dto.room_id && t.start_time < end_time && t.end_time > start_time,
t => t.id, OrderByType.Asc);
if (hasUnavailable != null && hasUnavailable.Count > 0)
{
return new WebApiDto()
{
Code = 500,
Data = null,
Msg = "该时间段房间不可预约"
};
}
// 2.1 校验用户是否有其它预约时间冲突
// 2.1 校验用户是否有其它预约时间冲突(只查未开始或正在进行中的预约)
var now = DateTime.Now;
var hasConflict = await _SQReservationParticipantsServices.QueryMuchAsync<SQReservationParticipants, SQReservations, int>(
(p, r) => new object[]
{
JoinType.Inner, p.reservation_id == r.id
},
(p, r) => r.id,
(p, r) =>
p.user_id == userId &&
p.status == 0 && // 只查未退出
r.status < 2 && // 只查未取消/未结束
r.end_time > now && // 只查未结束
r.start_time < end_time && r.end_time > start_time // 时间有重叠
);
if (hasConflict != null && hasConflict.Count > 0)
{
return new WebApiDto
{
Code = 402,
Data = null,
Msg = "您有其它预约时间冲突,无法创建该预约!"
};
}
// 4. 检查房间是否已被预约(未取消的预约,时间有重叠)
var hasReserved = await _SQReservationsServices.QueryListByClauseAsync(
r => r.room_id == dto.room_id && r.status < 2 && r.start_time < end_time && r.end_time > start_time,
r => r.id, OrderByType.Asc);
if (hasReserved != null && hasReserved.Count > 0)
{
return new WebApiDto()
{
Code = 500,
Data = null,
Msg = "该时间段房间已被预约"
};
}
// 5. 创建预约记录
var reservation = new SQReservations
{
room_id = dto.room_id,
room_name = room.name,
start_time = start_time,
end_time = end_time,
game_type = dto.game_type,
created_at = DateTime.Now,
updated_at = DateTime.Now,
credit_limit = dto.credit_limit,
player_count = dto.player_count,
deposit_fee = dto.deposit_fee,
duration_minutes = dto.duration_minutes,
extra_info = dto.extra_info,
game_rule = dto.game_rule,
gender_limit = dto.gender_limit,
is_smoking = dto.is_smoking,
max_age = dto.max_age,
min_age = dto.min_age,
remarks = "",
status = 0,
title = dto.title,
// 其他字段可根据需要补充
};
var reservationId = await _dbBase.Insertable(reservation).ExecuteReturnIdentityAsync();
if (reservationId <= 0)
{
return new WebApiDto()
{
Code = 500,
Data = null,
Msg = "预约失败"
};
}
// 6. 创建预约参与人记录发起者role=1
var participant = new SQReservationParticipants
{
reservation_id = reservationId,
user_id = userId,
join_time = DateTime.Now,
role = 1,
status = 0,
is_refund = dto.deposit_fee > 0 ? 1 : 0,
important_data = dto.important_data
};
await _SQReservationParticipantsServices.InsertAsync(participant);
return new WebApiDto()
{
Code = 0,
Data = new { reservation_id = reservationId },
Msg = "预约成功"
};
}
/// <summary>
/// 用户加入预约接口
/// </summary>
/// <param name="dto">预约</param>
/// <returns></returns>
[HttpPost]
[Authorize]
public async Task<WebApiDto> JoinReservation([FromBody] SQReservationParticipantsAddDto dto)
{
var userId = _user.ID;
var reservationId = dto.ReservationsId;
// 1. 校验预约是否存在且未结束
var reservation = await _SQReservationsServices.QueryByClauseAsync(
r => r.id == reservationId && r.end_time > DateTime.Now && r.status < 2,
r => r.id, OrderByType.Asc);
if (reservation == null)
{
return new WebApiDto
{
Code = 404,
Data = null,
Msg = "预约不存在或已结束"
};
}
// 2. 校验用户是否已加入该预约
var exists = await _SQReservationParticipantsServices.QueryByClauseAsync(
p => p.reservation_id == reservationId && p.user_id == userId,
p => p.id, OrderByType.Asc);
if (exists != null)
{
return new WebApiDto
{
Code = 400,
Data = null,
Msg = "您已加入该预约"
};
}
// 2.1 校验用户是否有其它预约时间冲突
// 2.1 校验用户是否有其它预约时间冲突(只查未开始或正在进行中的预约)
var now = DateTime.Now;
var hasConflict = await _SQReservationParticipantsServices.QueryMuchAsync<SQReservationParticipants, SQReservations, int>(
(p, r) => new object[]
{
JoinType.Inner, p.reservation_id == r.id
},
(p, r) => r.id,
(p, r) =>
p.user_id == userId &&
p.status == 0 && // 只查未退出
r.status < 2 && // 只查未取消/未结束
r.end_time > now && // 只查未结束
r.start_time < reservation.end_time && r.end_time > reservation.start_time // 时间有重叠
);
if (hasConflict != null && hasConflict.Count > 0)
{
return new WebApiDto
{
Code = 402,
Data = null,
Msg = "您有其它预约时间冲突,无法加入该预约"
};
}
//// 查询用户所有未结束的预约参与记录
//var userReservations = await _SQReservationParticipantsServices.QueryListByClauseAsync(
// p => p.user_id == userId && p.status == 0, // 只查未退出的
// p => p.id, OrderByType.Asc);
//if (userReservations != null && userReservations.Count > 0)
//{
// // 获取这些预约的ID
// var reservationIds = userReservations.Select(p => p.reservation_id).ToList();
// // 查询这些预约的时间段
// var reservations = await _SQReservationsServices.QueryListByClauseAsync(
// r => reservationIds.Contains(r.id) && r.status < 2 && r.end_time > DateTime.Now,
// r => r.id, OrderByType.Asc);
// // 检查时间是否有重叠
// foreach (var r in reservations)
// {
// if (r.start_time < reservation.end_time && r.end_time > reservation.start_time)
// {
// return new WebApiDto
// {
// Code = 402,
// Data = null,
// Msg = "您有其它预约时间冲突,无法加入该预约"
// };
// }
// }
//}
//3.校验预约是否已满(如有容量限制,可补充)
var participantsCount = await _SQReservationParticipantsServices.QueryListByClauseAsync(
p => p.reservation_id == reservationId, p => p.id, OrderByType.Asc);
if (participantsCount.Count >= reservation.player_count)
{
return new WebApiDto()
{
Code = 401,
Data = null,
Msg = "预约已满"
};
}
// 4. 插入参与人记录
var participant = new SQReservationParticipants
{
reservation_id = reservationId,
user_id = userId,
join_time = DateTime.Now,
role = 0, // 0为参与者
status = 0,
is_refund = reservation.deposit_fee > 0 ? 1 : 0,
important_data = dto.important_data
};
await _SQReservationParticipantsServices.InsertAsync(participant);
return new WebApiDto
{
Code = 0,
Data = null,
Msg = "加入预约成功"
};
}
}