mahjong_group/server/CoreCms.Net.Services/SQ/SQRoomsServices.cs
2026-01-01 14:35:52 +08:00

485 lines
20 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.

/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2025/9/2 12:47:30
* Description: 暂无
***********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading.Tasks;
using CoreCms.Net.Caching.AutoMate.RedisCache;
using CoreCms.Net.Configuration;
using CoreCms.Net.IRepository;
using CoreCms.Net.IRepository.UnitOfWork;
using CoreCms.Net.IServices;
using CoreCms.Net.Model.Entities;
using CoreCms.Net.Model.ViewModels.Basics;
using CoreCms.Net.Model.ViewModels.UI;
using CoreCms.Net.Model.ViewModels.SQ;
using CoreCms.Net.Utility.Helper;
using SqlSugar;
using System.Linq;
namespace CoreCms.Net.Services
{
/// <summary>
/// 房间表 接口实现
/// </summary>
public class SQRoomsServices : BaseServices<SQRooms>, ISQRoomsServices
{
private readonly ISQRoomsRepository _dal;
private readonly IUnitOfWork _unitOfWork;
private readonly IRedisOperationRepository _redisOperationRepository;
private readonly ISQRoomPricingServices _pricingServices;
private readonly ISQReservationsServices _reservationsServices;
private readonly ISQRoomUnavailableTimesServices _unavailableTimesServices;
public SQRoomsServices(IUnitOfWork unitOfWork, ISQRoomsRepository dal,
IRedisOperationRepository redisOperationRepository,
ISQRoomPricingServices pricingServices,
ISQReservationsServices reservationsServices,
ISQRoomUnavailableTimesServices unavailableTimesServices)
{
this._dal = dal;
base.BaseDal = dal;
_unitOfWork = unitOfWork;
_redisOperationRepository = redisOperationRepository;
_pricingServices = pricingServices;
_reservationsServices = reservationsServices;
_unavailableTimesServices = unavailableTimesServices;
}
#region ==========================================================
/// <summary>
/// 重写异步插入方法
/// </summary>
/// <param name="entity">实体数据</param>
/// <returns></returns>
public new async Task<AdminUiCallBack> InsertAsync(SQRooms entity)
{
return await _dal.InsertAsync(entity);
}
/// <summary>
/// 重写异步更新方法方法
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public new async Task<AdminUiCallBack> UpdateAsync(SQRooms entity)
{
return await _dal.UpdateAsync(entity);
}
/// <summary>
/// 重写异步更新方法方法
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public new async Task<AdminUiCallBack> UpdateAsync(List<SQRooms> entity)
{
return await _dal.UpdateAsync(entity);
}
/// <summary>
/// 重写删除指定ID的数据
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public new async Task<AdminUiCallBack> DeleteByIdAsync(object id)
{
return await _dal.DeleteByIdAsync(id);
}
/// <summary>
/// 重写删除指定ID集合的数据(批量删除)
/// </summary>
/// <param name="ids"></param>
/// <returns></returns>
public new async Task<AdminUiCallBack> DeleteByIdsAsync(int[] ids)
{
return await _dal.DeleteByIdsAsync(ids);
}
#endregion
#region ==========================================================
/// <summary>
/// 获取缓存的所有数据
/// </summary>
/// <returns></returns>
public async Task<List<SQRooms>> GetCaChe()
{
return await _dal.GetCaChe();
}
/// <summary>
/// 更新cache
/// </summary>
public async Task<List<SQRooms>> UpdateCaChe()
{
return await _dal.UpdateCaChe();
}
#endregion
#region
/// <summary>
/// 重写根据条件查询分页数据
/// </summary>
/// <param name="predicate">判断集合</param>
/// <param name="orderByType">排序方式</param>
/// <param name="pageIndex">当前页面索引</param>
/// <param name="pageSize">分布大小</param>
/// <param name="orderByExpression"></param>
/// <param name="blUseNoLock">是否使用WITH(NOLOCK)</param>
/// <returns></returns>
public new async Task<IPageList<SQRooms>> QueryPageAsync(Expression<Func<SQRooms, bool>> predicate,
Expression<Func<SQRooms, object>> orderByExpression, OrderByType orderByType, int pageIndex = 1,
int pageSize = 20, bool blUseNoLock = false)
{
return await _dal.QueryPageAsync(predicate, orderByExpression, orderByType, pageIndex, pageSize, blUseNoLock);
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public async Task<List<SQRooms>> GetRoomList()
{
var key = $"room:GetRoomList";
var list = await _redisOperationRepository.Get<List<SQRooms>>(key);
if (list == null)
{
list = await _dal.QueryAsync(true);
await _redisOperationRepository.Set(key, list, TimeSpan.FromSeconds(60));
}
return list;
}
#endregion
#region
/// <summary>
/// 获取房间列表及时段状态
/// </summary>
public async Task<List<SQRoomListDto>> GetRoomListWithSlotsAsync(DateTime date, bool showOnlyAvailable = false, int? currentTimeSlot = null)
{
var dayStart = date.Date;
var dayEnd = dayStart.AddDays(1).AddSeconds(-1);
var now = DateTime.Now;
// 查询所有可用房间
var allRooms = await _dal.QueryListByClauseAsync(r => r.status == true, r => r.sort_order ?? r.id, OrderByType.Asc);
if (allRooms == null || allRooms.Count == 0)
{
return new List<SQRoomListDto>();
}
var result = new List<SQRoomListDto>();
foreach (var room in allRooms)
{
var roomDto = new SQRoomListDto
{
id = room.id,
name = room.name,
room_type_name = room.room_type_name ?? room.room_type,
image_url = room.image_url,
capacity = room.capacity,
description = room.description,
status = GlobalConstVars.RoomStatusAvailable,
is_available = true,
can_reserve = false,
time_slots = new List<SQTimeSlotDto>()
};
// 获取房间所有时段的价格配置
var pricingList = await _pricingServices.GetRoomAllPricingAsync(room.id, date);
// 查询当天的预约记录
var reservations = await _reservationsServices.QueryListByClauseAsync(
r => r.room_id == room.id && r.status < 3 && r.start_time < dayEnd && r.end_time > dayStart,
r => r.start_time, OrderByType.Asc);
// 查询不可用时段
var unavailableTimes = await _unavailableTimesServices.QueryListByClauseAsync(
t => t.room_id == room.id && t.start_time < dayEnd && t.end_time > dayStart,
t => t.start_time, OrderByType.Asc);
// 构建4个时段的状态
for (int slotType = 0; slotType <= 3; slotType++)
{
var (slotStart, slotEnd) = TimeSlotHelper.GetTimeRange(dayStart, slotType);
var pricing = pricingList.FirstOrDefault(p => p.time_slot_type == slotType);
var slotDto = new SQTimeSlotDto
{
slot_type = slotType,
slot_name = TimeSlotHelper.GetTimeSlotName(slotType),
status = GlobalConstVars.RoomStatusAvailable,
standard_price = pricing?.standard_price ?? 0,
member_price = pricing?.member_price ?? 0,
price_desc_standard = pricing?.price_desc_standard,
price_desc_member = pricing?.price_desc_member
};
// 检查时段是否已过期(仅当查询日期是今天时)
bool isPassed = dayStart.Date == DateTime.Today && TimeSlotHelper.IsTimeSlotPassed(dayStart, slotType);
if (isPassed)
{
// 时段已过期,标记为不可用
slotDto.status = GlobalConstVars.RoomStatusUnavailable;
}
else
{
// 检查不可用时段,并获取禁用类型
var unavailableRecord = unavailableTimes?.FirstOrDefault(u =>
(u.time_slot_type.HasValue && u.time_slot_type.Value == slotType) ||
(u.start_time < slotEnd && u.end_time > slotStart));
if (unavailableRecord != null)
{
slotDto.status = GlobalConstVars.RoomStatusUnavailable;
slotDto.unavailable_type = unavailableRecord.type; // 设置禁用类型
}
else
{
// 检查是否已预约
bool isReserved = reservations?.Any(r =>
r.start_time < slotEnd && r.end_time > slotStart) ?? false;
if (isReserved)
{
slotDto.status = GlobalConstVars.RoomStatusReserved;
// 检查是否正在使用中
bool isUsing = reservations.Any(r => r.start_time <= now && r.end_time > now);
if (isUsing && dayStart.Date == DateTime.Today)
{
slotDto.status = GlobalConstVars.RoomStatusUsing;
roomDto.status = GlobalConstVars.RoomStatusUsing;
roomDto.is_available = false;
}
}
else if (slotDto.status == GlobalConstVars.RoomStatusAvailable)
{
roomDto.can_reserve = true;
}
}
}
roomDto.time_slots.Add(slotDto);
}
// 设置价格说明(使用第一个可用时段的价格作为展示)
var firstPricing = pricingList.FirstOrDefault();
if (firstPricing != null)
{
roomDto.standard_price_desc = firstPricing.price_desc_standard;
roomDto.member_price_desc = firstPricing.price_desc_member;
}
// 如果启用筛选,只显示指定时段可用的房间
if (showOnlyAvailable && currentTimeSlot.HasValue)
{
var currentSlot = roomDto.time_slots.FirstOrDefault(s => s.slot_type == currentTimeSlot.Value);
if (currentSlot == null || currentSlot.status != GlobalConstVars.RoomStatusAvailable)
{
continue;
}
}
result.Add(roomDto);
}
return result;
}
/// <summary>
/// 获取房间详情
/// </summary>
public async Task<SQRoomDetailDto> GetRoomDetailAsync(int roomId, DateTime date)
{
// 1. 查询房间信息
var room = await _dal.QueryByIdAsync(roomId);
if (room == null)
{
return null;
}
// 2. 确定查询日期范围
var dayStart = date.Date;
var dayEnd = dayStart.AddDays(1).AddSeconds(-1);
var now = DateTime.Now;
// 3. 构建房间详情DTO
var roomDetail = new SQRoomDetailDto
{
id = room.id,
name = room.name,
room_type = room.room_type,
room_type_name = room.room_type_name ?? room.room_type,
image_url = room.image_url,
price_per_hour = room.price_per_hour,
capacity = room.capacity,
description = room.description,
status = GlobalConstVars.RoomStatusAvailable,
is_available = true,
can_reserve = false
};
// 4. 解析多图image_detailed_url按逗号分割
if (!string.IsNullOrEmpty(room.image_detailed_url))
{
roomDetail.images = room.image_detailed_url
.Split(',', StringSplitOptions.RemoveEmptyEntries)
.Select(img => img.Trim())
.ToList();
}
// 5. 解析设施列表amenities按逗号分割
if (!string.IsNullOrEmpty(room.amenities))
{
roomDetail.amenities = room.amenities
.Split(',', StringSplitOptions.RemoveEmptyEntries)
.Select(a => a.Trim())
.ToList();
}
// 6. 获取房间所有时段的价格配置
var pricingList = await _pricingServices.GetRoomAllPricingAsync(room.id, date);
// 7. 查询当天的预约记录
var reservations = await _reservationsServices.QueryListByClauseAsync(
r => r.room_id == roomId && r.status < 3 && r.start_time < dayEnd && r.end_time > dayStart,
r => r.start_time, OrderByType.Asc);
// 8. 查询不可用时段
var unavailableTimes = await _unavailableTimesServices.QueryListByClauseAsync(
t => t.room_id == roomId && t.start_time < dayEnd && t.end_time > dayStart,
t => t.start_time, OrderByType.Asc);
// 9. 构建4个时段的状态与列表接口逻辑一致并整合预约信息
for (int slotType = 0; slotType <= 3; slotType++)
{
var (slotStart, slotEnd) = TimeSlotHelper.GetTimeRange(dayStart, slotType);
var pricing = pricingList.FirstOrDefault(p => p.time_slot_type == slotType);
var slotDto = new SQTimeSlotDto
{
slot_type = slotType,
slot_name = TimeSlotHelper.GetTimeSlotName(slotType),
status = GlobalConstVars.RoomStatusAvailable,
standard_price = pricing?.standard_price ?? 0,
member_price = pricing?.member_price ?? 0,
price_desc_standard = pricing?.price_desc_standard,
price_desc_member = pricing?.price_desc_member
};
// 检查时段是否已过期(仅当查询日期是今天时)
bool isPassed = dayStart.Date == DateTime.Today && TimeSlotHelper.IsTimeSlotPassed(dayStart, slotType);
if (isPassed)
{
// 时段已过期,标记为不可用
slotDto.status = GlobalConstVars.RoomStatusUnavailable;
}
else
{
// 检查不可用时段
bool isUnavailable = unavailableTimes?.Any(u =>
(u.time_slot_type.HasValue && u.time_slot_type.Value == slotType) ||
(u.start_time < slotEnd && u.end_time > slotStart)) ?? false;
if (isUnavailable)
{
slotDto.status = GlobalConstVars.RoomStatusUnavailable;
}
else
{
// 查找属于该时段的预约(预约时间与时段有重叠)
var slotReservations = reservations?.Where(r =>
r.start_time < slotEnd && r.end_time > slotStart).ToList() ?? new List<SQReservations>();
if (slotReservations.Count > 0)
{
slotDto.status = GlobalConstVars.RoomStatusReserved;
// 检查是否正在使用中
bool isUsing = slotReservations.Any(r => r.start_time <= now && r.end_time > now);
if (isUsing && dayStart.Date == DateTime.Today)
{
slotDto.status = GlobalConstVars.RoomStatusUsing;
roomDetail.status = GlobalConstVars.RoomStatusUsing;
roomDetail.is_available = false;
}
// 填充该时段内的预约信息
slotDto.reservations = slotReservations.Select(r => new SQTimeSlotReservationDto
{
reservation_id = r.id,
start_time = r.start_time.ToString("yyyy-MM-dd HH:mm:ss"),
end_time = r.end_time.ToString("yyyy-MM-dd HH:mm:ss"),
status = r.status,
title = r.title,
game_type = r.game_type
}).ToList();
}
else if (slotDto.status == GlobalConstVars.RoomStatusAvailable)
{
roomDetail.can_reserve = true;
}
}
}
roomDetail.time_slots.Add(slotDto);
}
// 10. 设置价格说明(使用第一个可用时段的价格作为展示)
var firstPricing = pricingList.FirstOrDefault();
if (firstPricing != null)
{
roomDetail.standard_price_desc = firstPricing.price_desc_standard;
roomDetail.member_price_desc = firstPricing.price_desc_member;
}
// 11. 填充今日预约情况(保留兼容性,但建议使用 time_slots 中的 reservations
if (reservations != null && reservations.Count > 0)
{
roomDetail.today_reservations = reservations.Select(r => new SQRoomDetailReservationDto
{
start_time = r.start_time.ToString("yyyy-MM-dd HH:mm:ss"),
end_time = r.end_time.ToString("yyyy-MM-dd HH:mm:ss"),
status = r.status
}).ToList();
}
// 12. 最终状态检查:如果有任何不可用时段,设置整体状态
if (unavailableTimes != null && unavailableTimes.Count > 0)
{
// 只有当所有时段都不可用时,才设置为 unavailable
bool allUnavailable = roomDetail.time_slots.All(s => s.status == GlobalConstVars.RoomStatusUnavailable);
if (allUnavailable)
{
roomDetail.status = GlobalConstVars.RoomStatusUnavailable;
roomDetail.is_available = false;
}
}
return roomDetail;
}
#endregion
}
}