321
This commit is contained in:
parent
3857ecad81
commit
0173638400
|
|
@ -17,6 +17,7 @@ using CoreCms.Net.Model.Entities;
|
||||||
using CoreCms.Net.Model.Entities.Expression;
|
using CoreCms.Net.Model.Entities.Expression;
|
||||||
using CoreCms.Net.Model.FromBody;
|
using CoreCms.Net.Model.FromBody;
|
||||||
using CoreCms.Net.Model.ViewModels.UI;
|
using CoreCms.Net.Model.ViewModels.UI;
|
||||||
|
using CoreCms.Net.Model.ViewModels.SQ;
|
||||||
using CoreCms.Net.Utility.Extensions;
|
using CoreCms.Net.Utility.Extensions;
|
||||||
using CoreCms.Net.Utility.Helper;
|
using CoreCms.Net.Utility.Helper;
|
||||||
using CoreCms.Net.Web.Admin.Infrastructure;
|
using CoreCms.Net.Web.Admin.Infrastructure;
|
||||||
|
|
@ -30,11 +31,14 @@ using NPOI.HSSF.UserModel;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using NLog;
|
||||||
|
using AutoMapper;
|
||||||
|
|
||||||
namespace CoreCms.Net.Web.Admin.Controllers
|
namespace CoreCms.Net.Web.Admin.Controllers
|
||||||
{
|
{
|
||||||
|
|
@ -50,16 +54,31 @@ namespace CoreCms.Net.Web.Admin.Controllers
|
||||||
{
|
{
|
||||||
private readonly IWebHostEnvironment _webHostEnvironment;
|
private readonly IWebHostEnvironment _webHostEnvironment;
|
||||||
private readonly ISQRoomPricingServices _SQRoomPricingServices;
|
private readonly ISQRoomPricingServices _SQRoomPricingServices;
|
||||||
|
private readonly ISQRoomsServices _SQRoomsServices;
|
||||||
|
private readonly ISQReservationsServices _SQReservationsServices;
|
||||||
|
private readonly ISQReservationParticipantsServices _SQReservationParticipantsServices;
|
||||||
|
private readonly ICoreCmsUserServices _userServices;
|
||||||
|
private readonly IMapper _mapper;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构造函数
|
/// 构造函数
|
||||||
///</summary>
|
///</summary>
|
||||||
public SQRoomPricingController(IWebHostEnvironment webHostEnvironment
|
public SQRoomPricingController(IWebHostEnvironment webHostEnvironment
|
||||||
, ISQRoomPricingServices SQRoomPricingServices
|
, ISQRoomPricingServices SQRoomPricingServices
|
||||||
|
, ISQRoomsServices SQRoomsServices
|
||||||
|
, ISQReservationsServices SQReservationsServices
|
||||||
|
, ISQReservationParticipantsServices SQReservationParticipantsServices
|
||||||
|
, ICoreCmsUserServices userServices
|
||||||
|
, IMapper mapper
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
_webHostEnvironment = webHostEnvironment;
|
_webHostEnvironment = webHostEnvironment;
|
||||||
_SQRoomPricingServices = SQRoomPricingServices;
|
_SQRoomPricingServices = SQRoomPricingServices;
|
||||||
|
_SQRoomsServices = SQRoomsServices;
|
||||||
|
_SQReservationsServices = SQReservationsServices;
|
||||||
|
_SQReservationParticipantsServices = SQReservationParticipantsServices;
|
||||||
|
_userServices = userServices;
|
||||||
|
_mapper = mapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region 获取列表============================================================
|
#region 获取列表============================================================
|
||||||
|
|
@ -820,6 +839,265 @@ namespace CoreCms.Net.Web.Admin.Controllers
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region 获取房间时段状态============================================================
|
||||||
|
// GET: Api/SQRoomPricing/GetRoomListWithSlots
|
||||||
|
/// <summary>
|
||||||
|
/// 获取房间列表及时段状态(用于日历视图)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="date">日期</param>
|
||||||
|
/// <param name="showOnlyAvailable">是否只显示可用房间</param>
|
||||||
|
/// <param name="currentTimeSlot">当前时段</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet]
|
||||||
|
[AllowAnonymous]
|
||||||
|
[Description("获取房间列表及时段状态")]
|
||||||
|
public async Task<AdminUiCallBack> GetRoomListWithSlots([FromQuery] string date, [FromQuery] bool showOnlyAvailable = false, [FromQuery] int? currentTimeSlot = null)
|
||||||
|
{
|
||||||
|
var jm = new AdminUiCallBack();
|
||||||
|
|
||||||
|
// 验证日期参数
|
||||||
|
if (string.IsNullOrEmpty(date))
|
||||||
|
{
|
||||||
|
jm.msg = "请提供日期参数";
|
||||||
|
return jm;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!DateTime.TryParse(date, out DateTime dateValue))
|
||||||
|
{
|
||||||
|
jm.msg = "日期格式不正确";
|
||||||
|
return jm;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用服务获取数据
|
||||||
|
var result = await _SQRoomsServices.GetRoomListWithSlotsAsync(dateValue, showOnlyAvailable, currentTimeSlot);
|
||||||
|
|
||||||
|
jm.code = 0;
|
||||||
|
jm.msg = "获取成功";
|
||||||
|
jm.data = result;
|
||||||
|
|
||||||
|
return jm;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 获取日期详情============================================================
|
||||||
|
// GET: Api/SQRoomPricing/GetDateDetails
|
||||||
|
/// <summary>
|
||||||
|
/// 获取指定日期和房间的详细信息(用于日历视图点击日期)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="date">日期</param>
|
||||||
|
/// <param name="roomId">房间ID</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet]
|
||||||
|
[AllowAnonymous]
|
||||||
|
[Description("获取日期详情")]
|
||||||
|
public async Task<AdminUiCallBack> GetDateDetails([FromQuery] string date, [FromQuery] int roomId)
|
||||||
|
{
|
||||||
|
var jm = new AdminUiCallBack();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 验证参数
|
||||||
|
if (string.IsNullOrEmpty(date))
|
||||||
|
{
|
||||||
|
jm.msg = "请提供日期参数";
|
||||||
|
return jm;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (roomId <= 0)
|
||||||
|
{
|
||||||
|
jm.msg = "请提供房间ID";
|
||||||
|
return jm;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!DateTime.TryParse(date, out DateTime dateValue))
|
||||||
|
{
|
||||||
|
jm.msg = "日期格式不正确";
|
||||||
|
return jm;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取房间信息
|
||||||
|
var room = await _SQRoomsServices.QueryByIdAsync(roomId);
|
||||||
|
if (room == null)
|
||||||
|
{
|
||||||
|
jm.msg = "房间不存在";
|
||||||
|
return jm;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取该日期该房间的时段状态
|
||||||
|
var roomListWithSlots = await _SQRoomsServices.GetRoomListWithSlotsAsync(dateValue, false, null);
|
||||||
|
var roomData = roomListWithSlots?.FirstOrDefault(r => r.id == roomId);
|
||||||
|
|
||||||
|
// 获取该日期该房间的预约列表
|
||||||
|
var startTime = dateValue.Date;
|
||||||
|
var endTime = dateValue.Date.AddDays(1);
|
||||||
|
var reservations = await _SQReservationsServices.QueryListByClauseAsync(
|
||||||
|
p => p.room_id == roomId &&
|
||||||
|
p.start_time >= startTime &&
|
||||||
|
p.start_time < endTime &&
|
||||||
|
p.status != 4, // 排除已取消的预约
|
||||||
|
p => p.start_time,
|
||||||
|
OrderByType.Asc
|
||||||
|
);
|
||||||
|
|
||||||
|
// 查询所有预约的参与者
|
||||||
|
var reservationIds = reservations.Select(r => r.id).ToList();
|
||||||
|
List<SQReservationParticipants> allParticipants = new List<SQReservationParticipants>();
|
||||||
|
List<CoreCmsUser> userList = new List<CoreCmsUser>();
|
||||||
|
|
||||||
|
if (reservationIds.Any())
|
||||||
|
{
|
||||||
|
allParticipants = await _SQReservationParticipantsServices.QueryListByClauseAsync(
|
||||||
|
p => reservationIds.Contains(p.reservation_id),
|
||||||
|
p => p.role,
|
||||||
|
OrderByType.Desc,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
// 查询所有参与者的用户信息
|
||||||
|
var userIds = allParticipants.Select(p => p.user_id).Distinct().ToList();
|
||||||
|
if (userIds.Any())
|
||||||
|
{
|
||||||
|
userList = await _userServices.QueryListByClauseAsync(
|
||||||
|
u => userIds.Contains(u.id),
|
||||||
|
u => u.id,
|
||||||
|
OrderByType.Asc,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理时段数据,添加参与者头像和数量
|
||||||
|
var enhancedTimeSlots = new List<object>();
|
||||||
|
if (roomData?.time_slots != null)
|
||||||
|
{
|
||||||
|
foreach (var slot in roomData.time_slots)
|
||||||
|
{
|
||||||
|
// 获取该时段的所有预约
|
||||||
|
var slotReservations = reservations.Where(r =>
|
||||||
|
r.time_slot_type.HasValue && r.time_slot_type.Value == slot.slot_type
|
||||||
|
).ToList();
|
||||||
|
|
||||||
|
// 获取该时段所有预约的参与者(正常状态)
|
||||||
|
var slotReservationIds = slotReservations.Select(r => r.id).ToList();
|
||||||
|
var slotParticipants = allParticipants.Where(p =>
|
||||||
|
slotReservationIds.Contains(p.reservation_id) && p.status == 0
|
||||||
|
).ToList();
|
||||||
|
|
||||||
|
// 提取头像列表
|
||||||
|
var avatars = slotParticipants
|
||||||
|
.Select(p => userList.FirstOrDefault(u => u.id == p.user_id)?.avatarImage)
|
||||||
|
.Where(avatar => !string.IsNullOrEmpty(avatar))
|
||||||
|
.Distinct()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
enhancedTimeSlots.Add(new
|
||||||
|
{
|
||||||
|
slot_type = slot.slot_type,
|
||||||
|
slot_name = slot.slot_name,
|
||||||
|
status = slot.status,
|
||||||
|
price_desc_standard = slot.price_desc_standard,
|
||||||
|
price_desc_member = slot.price_desc_member,
|
||||||
|
reservation_count = slotParticipants.Count,
|
||||||
|
participant_avatars = avatars
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按时段分组预约
|
||||||
|
var reservationsBySlot = new Dictionary<int, List<object>>();
|
||||||
|
for (int i = 0; i <= 3; i++)
|
||||||
|
{
|
||||||
|
reservationsBySlot[i] = new List<object>();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var reservation in reservations)
|
||||||
|
{
|
||||||
|
// 确定预约所属时段
|
||||||
|
int slotType = reservation.time_slot_type ?? GetTimeSlotTypeFromTime(reservation.start_time);
|
||||||
|
|
||||||
|
// 获取该预约的参与者
|
||||||
|
var participants = allParticipants.Where(p => p.reservation_id == reservation.id)
|
||||||
|
.OrderBy(p => p.role == 1 ? 0 : 1) // 发起者优先
|
||||||
|
.ThenBy(p => p.status) // 正常状态优先
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var participantsDto = _mapper.Map<List<SQReservationParticipantsDto>>(participants);
|
||||||
|
|
||||||
|
// 填充用户信息
|
||||||
|
foreach (var p in participantsDto)
|
||||||
|
{
|
||||||
|
var user = userList.FirstOrDefault(u => u.id == p.user_id);
|
||||||
|
if (user != null)
|
||||||
|
{
|
||||||
|
p.UserName = user.nickName;
|
||||||
|
p.AvatarImage = user.avatarImage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reservationsBySlot[slotType].Add(new
|
||||||
|
{
|
||||||
|
id = reservation.id,
|
||||||
|
title = reservation.title,
|
||||||
|
player_count = reservation.player_count,
|
||||||
|
deposit_fee = reservation.deposit_fee,
|
||||||
|
latest_arrival_time = reservation.latest_arrival_time?.ToString("yyyy-MM-dd HH:mm:ss"),
|
||||||
|
game_type = reservation.game_type,
|
||||||
|
game_rule = reservation.game_rule,
|
||||||
|
start_time = reservation.start_time.ToString("yyyy-MM-dd HH:mm:ss"),
|
||||||
|
end_time = reservation.end_time.ToString("yyyy-MM-dd HH:mm:ss"),
|
||||||
|
status = reservation.status,
|
||||||
|
participants = participantsDto.Select(p => new
|
||||||
|
{
|
||||||
|
id = p.id,
|
||||||
|
user_id = p.user_id,
|
||||||
|
user_name = p.UserName,
|
||||||
|
avatar_image = p.AvatarImage,
|
||||||
|
join_time = p.join_time.ToString("yyyy-MM-dd HH:mm:ss"),
|
||||||
|
role = p.role,
|
||||||
|
quit_time = p.quit_time?.ToString("yyyy-MM-dd HH:mm:ss"),
|
||||||
|
status = p.status,
|
||||||
|
is_refund = p.is_refund,
|
||||||
|
remarks = p.remarks
|
||||||
|
}).ToList()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建返回数据
|
||||||
|
var result = new
|
||||||
|
{
|
||||||
|
date = date,
|
||||||
|
room_id = roomId,
|
||||||
|
room_name = room.name,
|
||||||
|
time_slots = enhancedTimeSlots,
|
||||||
|
reservations_by_slot = reservationsBySlot
|
||||||
|
};
|
||||||
|
|
||||||
|
jm.code = 0;
|
||||||
|
jm.msg = "获取成功";
|
||||||
|
jm.data = result;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
jm.msg = "获取数据时发生错误:" + ex.Message;
|
||||||
|
NLogUtil.WriteAll(LogLevel.Error, LogType.Web, "获取日期详情", "GetDateDetails", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return jm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据时间判断时段类型
|
||||||
|
/// </summary>
|
||||||
|
private int GetTimeSlotTypeFromTime(DateTime time)
|
||||||
|
{
|
||||||
|
var hour = time.Hour;
|
||||||
|
if (hour >= 0 && hour < 6) return 0; // 凌晨 00:00-06:00
|
||||||
|
if (hour >= 6 && hour < 12) return 1; // 上午 06:00-12:00
|
||||||
|
if (hour >= 12 && hour < 18) return 2; // 下午 12:00-18:00
|
||||||
|
return 3; // 晚上 18:00-24:00
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4013,7 +4013,7 @@
|
||||||
|
|
||||||
</summary>
|
</summary>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:CoreCms.Net.Web.Admin.Controllers.SQRoomPricingController.#ctor(Microsoft.AspNetCore.Hosting.IWebHostEnvironment,CoreCms.Net.IServices.ISQRoomPricingServices)">
|
<member name="M:CoreCms.Net.Web.Admin.Controllers.SQRoomPricingController.#ctor(Microsoft.AspNetCore.Hosting.IWebHostEnvironment,CoreCms.Net.IServices.ISQRoomPricingServices,CoreCms.Net.IServices.ISQRoomsServices,CoreCms.Net.IServices.ISQReservationsServices,CoreCms.Net.IServices.ISQReservationParticipantsServices,CoreCms.Net.IServices.ICoreCmsUserServices,AutoMapper.IMapper)">
|
||||||
<summary>
|
<summary>
|
||||||
构造函数
|
构造函数
|
||||||
</summary>
|
</summary>
|
||||||
|
|
@ -4098,6 +4098,28 @@
|
||||||
<param name="entity"></param>
|
<param name="entity"></param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="M:CoreCms.Net.Web.Admin.Controllers.SQRoomPricingController.GetRoomListWithSlots(System.String,System.Boolean,System.Nullable{System.Int32})">
|
||||||
|
<summary>
|
||||||
|
获取房间列表及时段状态(用于日历视图)
|
||||||
|
</summary>
|
||||||
|
<param name="date">日期</param>
|
||||||
|
<param name="showOnlyAvailable">是否只显示可用房间</param>
|
||||||
|
<param name="currentTimeSlot">当前时段</param>
|
||||||
|
<returns></returns>
|
||||||
|
</member>
|
||||||
|
<member name="M:CoreCms.Net.Web.Admin.Controllers.SQRoomPricingController.GetDateDetails(System.String,System.Int32)">
|
||||||
|
<summary>
|
||||||
|
获取指定日期和房间的详细信息(用于日历视图点击日期)
|
||||||
|
</summary>
|
||||||
|
<param name="date">日期</param>
|
||||||
|
<param name="roomId">房间ID</param>
|
||||||
|
<returns></returns>
|
||||||
|
</member>
|
||||||
|
<member name="M:CoreCms.Net.Web.Admin.Controllers.SQRoomPricingController.GetTimeSlotTypeFromTime(System.DateTime)">
|
||||||
|
<summary>
|
||||||
|
根据时间判断时段类型
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
<member name="T:CoreCms.Net.Web.Admin.Controllers.SQRoomsController">
|
<member name="T:CoreCms.Net.Web.Admin.Controllers.SQRoomsController">
|
||||||
<summary>
|
<summary>
|
||||||
房间表
|
房间表
|
||||||
|
|
|
||||||
|
|
@ -749,6 +749,8 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//执行单个删除
|
//执行单个删除
|
||||||
function doDelete(obj) {
|
function doDelete(obj) {
|
||||||
coreHelper.Post("Api/SQReservations/DoDelete", { id: obj.data.id }, function (e) {
|
coreHelper.Post("Api/SQReservations/DoDelete", { id: obj.data.id }, function (e) {
|
||||||
|
|
|
||||||
|
|
@ -9,30 +9,183 @@
|
||||||
<!--当前位置结束-->
|
<!--当前位置结束-->
|
||||||
<style>
|
<style>
|
||||||
/* 重写样式 */
|
/* 重写样式 */
|
||||||
|
.calendar-view {
|
||||||
|
display: none;
|
||||||
|
padding: 20px;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding: 15px;
|
||||||
|
background: #f8f8f8;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-header h3 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-nav button {
|
||||||
|
margin: 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(7, 1fr);
|
||||||
|
gap: 10px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-weekday {
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 10px;
|
||||||
|
background: #f0f0f0;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-day {
|
||||||
|
border: 1px solid #e6e6e6;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 10px;
|
||||||
|
min-height: 140px;
|
||||||
|
background: #fff;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-day:hover {
|
||||||
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-day.empty {
|
||||||
|
background: #fafafa;
|
||||||
|
border-color: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-day.today {
|
||||||
|
border-color: #009688;
|
||||||
|
background: #f0fffe;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-day-header {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-day-price {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-day-member {
|
||||||
|
display: inline-block;
|
||||||
|
background: #ff5722;
|
||||||
|
color: #fff;
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-size: 11px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-day-slots {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 4px;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-slot {
|
||||||
|
font-size: 11px;
|
||||||
|
padding: 3px 5px;
|
||||||
|
border-radius: 3px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-slot.available {
|
||||||
|
background: #e8f5e9;
|
||||||
|
color: #4caf50;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-slot.unavailable {
|
||||||
|
background: #ffebee;
|
||||||
|
color: #f44336;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-slot.reserved {
|
||||||
|
background: #fff3e0;
|
||||||
|
color: #ff9800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-slot.using {
|
||||||
|
background: #a3a9ac1e;
|
||||||
|
color: #ff9800;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<script type="text/html" template lay-type="Post" lay-url="Api/SQRoomPricing/GetIndex" lay-done="layui.data.done(d);">
|
<script type="text/html" template lay-type="Post" lay-url="Api/SQRoomPricing/GetIndex" lay-done="layui.data.done(d);">
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<div class="table-body">
|
|
||||||
<table id="LAY-app-SQRoomPricing-tableBox" lay-filter="LAY-app-SQRoomPricing-tableBox"></table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script type="text/html" id="LAY-app-SQRoomPricing-toolbar">
|
<!-- 独立的搜索工具栏 -->
|
||||||
|
<div class="layui-card" style="margin-bottom: 10px;">
|
||||||
|
<div class="layui-card-body">
|
||||||
<div class="layui-form coreshop-toolbar-search-form">
|
<div class="layui-form coreshop-toolbar-search-form">
|
||||||
<div class="layui-form-item">
|
<div class="layui-form-item" style="margin-bottom: 0;">
|
||||||
<div class="layui-inline">
|
<div class="layui-inline">
|
||||||
<label class="layui-form-label" for="room_id">房间号</label>
|
<label class="layui-form-label" for="room_id">房间号</label>
|
||||||
<div class="layui-input-inline">
|
<div class="layui-input-inline">
|
||||||
<select name="room_id" id="search_room_id">
|
<select name="room_id" id="search_room_id" lay-filter="search_room_id">
|
||||||
<option value="">请选择房间号</option>
|
<option value="">请选择房间号</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layui-inline">
|
<div class="layui-inline" id="table-view-search-btn">
|
||||||
<button class="layui-btn layui-btn-sm" lay-submit lay-filter="LAY-app-SQRoomPricing-search"><i class="layui-icon layui-icon-search"></i>筛选</button>
|
<button class="layui-btn layui-btn-sm" lay-submit lay-filter="LAY-app-SQRoomPricing-search"><i class="layui-icon layui-icon-search"></i>筛选</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="layui-inline">
|
||||||
|
<button class="layui-btn layui-btn-sm layui-btn-normal" id="toggleViewBtn" type="button">
|
||||||
|
<i class="layui-icon layui-icon-date"></i>切换日历视图
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="table-body" id="table-view">
|
||||||
|
<table id="LAY-app-SQRoomPricing-tableBox" lay-filter="LAY-app-SQRoomPricing-tableBox"></table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="calendar-view" id="calendar-view">
|
||||||
|
<div class="calendar-header">
|
||||||
|
<div class="calendar-nav">
|
||||||
|
<button class="layui-btn layui-btn-sm" id="prevMonthBtn">
|
||||||
|
<i class="layui-icon layui-icon-left"></i> 上一月
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<h3 id="currentMonthTitle"></h3>
|
||||||
|
<div class="calendar-nav">
|
||||||
|
<button class="layui-btn layui-btn-sm" id="nextMonthBtn">
|
||||||
|
下一月 <i class="layui-icon layui-icon-right"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="calendar-grid" id="calendarGrid">
|
||||||
|
<!-- 日历将通过JavaScript动态生成 -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/html" id="LAY-app-SQRoomPricing-toolbar">
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type="text/html" id="LAY-app-SQRoomPricing-pagebar">
|
<script type="text/html" id="LAY-app-SQRoomPricing-pagebar">
|
||||||
|
|
@ -66,6 +219,9 @@
|
||||||
var indexData;
|
var indexData;
|
||||||
var debug= layui.setter.debug;
|
var debug= layui.setter.debug;
|
||||||
var roomOptions = []; // 定义在外部作用域,供表格templet使用
|
var roomOptions = []; // 定义在外部作用域,供表格templet使用
|
||||||
|
var currentView = 'table'; // 当前视图:table 或 calendar
|
||||||
|
var currentMonth = new Date(); // 当前显示的月份
|
||||||
|
var selectedRoomId = null; // 选中的房间ID
|
||||||
|
|
||||||
layui.data.done = function (d) {
|
layui.data.done = function (d) {
|
||||||
//开启调试情况下获取接口赋值数据
|
//开启调试情况下获取接口赋值数据
|
||||||
|
|
@ -117,7 +273,7 @@
|
||||||
pagebar: '#LAY-app-SQRoomPricing-pagebar',
|
pagebar: '#LAY-app-SQRoomPricing-pagebar',
|
||||||
className: 'pagebarbox',
|
className: 'pagebarbox',
|
||||||
defaultToolbar: ['filter', 'print', 'exports'],
|
defaultToolbar: ['filter', 'print', 'exports'],
|
||||||
height: 'full-127',//面包屑142px,搜索框4行172,3行137,2行102,1行67
|
height: 'full-210',//面包屑142px + 独立搜索栏68px = 210px
|
||||||
page: true,
|
page: true,
|
||||||
limit: 30,
|
limit: 30,
|
||||||
limits: [10, 15, 20, 25, 30, 50, 100, 200],
|
limits: [10, 15, 20, 25, 30, 50, 100, 200],
|
||||||
|
|
@ -385,10 +541,547 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// 视图切换功能
|
||||||
|
$('#toggleViewBtn').on('click', function() {
|
||||||
|
if (currentView === 'table') {
|
||||||
|
// 切换到日历视图
|
||||||
|
currentView = 'calendar';
|
||||||
|
$('#table-view').hide();
|
||||||
|
$('#calendar-view').show();
|
||||||
|
$('#table-view-search-btn').hide();
|
||||||
|
$(this).html('<i class="layui-icon layui-icon-template"></i>切换表格视图');
|
||||||
|
|
||||||
|
// 获取当前选中的房间ID
|
||||||
|
var currentRoomId = $('#search_room_id').val();
|
||||||
|
|
||||||
|
// 如果没有选择房间,默认选择第一个
|
||||||
|
if (!currentRoomId && roomOptions.length > 0) {
|
||||||
|
selectedRoomId = roomOptions[0].id;
|
||||||
|
$('#search_room_id').val(selectedRoomId);
|
||||||
|
form.render('select');
|
||||||
|
} else {
|
||||||
|
selectedRoomId = currentRoomId ? parseInt(currentRoomId) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
console.log('切换到日历视图,选中房间ID:', selectedRoomId);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderCalendar();
|
||||||
|
} else {
|
||||||
|
// 切换到表格视图
|
||||||
|
currentView = 'table';
|
||||||
|
$('#table-view').show();
|
||||||
|
$('#calendar-view').hide();
|
||||||
|
$('#table-view-search-btn').show();
|
||||||
|
$(this).html('<i class="layui-icon layui-icon-date"></i>切换日历视图');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监听房间选择变化(日历视图)
|
||||||
|
form.on('select(search_room_id)', function(data) {
|
||||||
|
if (currentView === 'calendar') {
|
||||||
|
selectedRoomId = data.value ? parseInt(data.value) : null;
|
||||||
|
if (debug) {
|
||||||
|
console.log('房间选择变化,新房间ID:', selectedRoomId);
|
||||||
|
}
|
||||||
|
if (selectedRoomId) {
|
||||||
|
renderCalendar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 上一月按钮
|
||||||
|
$('#prevMonthBtn').on('click', function() {
|
||||||
|
currentMonth.setMonth(currentMonth.getMonth() - 1);
|
||||||
|
renderCalendar();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 下一月按钮
|
||||||
|
$('#nextMonthBtn').on('click', function() {
|
||||||
|
currentMonth.setMonth(currentMonth.getMonth() + 1);
|
||||||
|
renderCalendar();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 渲染日历
|
||||||
|
function renderCalendar() {
|
||||||
|
if (!selectedRoomId) {
|
||||||
|
layer.msg('请先选择房间');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var year = currentMonth.getFullYear();
|
||||||
|
var month = currentMonth.getMonth();
|
||||||
|
|
||||||
|
// 更新标题
|
||||||
|
$('#currentMonthTitle').text(year + '年 ' + (month + 1) + '月');
|
||||||
|
|
||||||
|
// 获取当月第一天和最后一天
|
||||||
|
var firstDay = new Date(year, month, 1);
|
||||||
|
var lastDay = new Date(year, month + 1, 0);
|
||||||
|
var firstDayOfWeek = firstDay.getDay() || 7; // 周日为0,转换为7
|
||||||
|
var daysInMonth = lastDay.getDate();
|
||||||
|
|
||||||
|
// 清空日历
|
||||||
|
var calendarGrid = $('#calendarGrid');
|
||||||
|
calendarGrid.empty();
|
||||||
|
|
||||||
|
// 添加星期标题
|
||||||
|
var weekdays = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];
|
||||||
|
weekdays.forEach(function(day) {
|
||||||
|
calendarGrid.append('<div class="calendar-weekday">' + day + '</div>');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 添加空白日期(第一天之前)
|
||||||
|
for (var i = 1; i < firstDayOfWeek; i++) {
|
||||||
|
calendarGrid.append('<div class="calendar-day empty"></div>');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 先渲染所有日期框架(显示日期号和加载提示)
|
||||||
|
for (var day = 1; day <= daysInMonth; day++) {
|
||||||
|
var currentDate = new Date(year, month, day);
|
||||||
|
var dateStr = formatDate(currentDate);
|
||||||
|
var isToday = dateStr === formatDate(new Date());
|
||||||
|
|
||||||
|
var dayHtml = '<div class="calendar-day' + (isToday ? ' today' : '') + '" data-date="' + dateStr + '" style="cursor:pointer;">';
|
||||||
|
dayHtml += '<div class="calendar-day-header">' + day + '号</div>';
|
||||||
|
dayHtml += '<div style="text-align:center;color:#999;padding:20px 0;">加载中...</div>';
|
||||||
|
dayHtml += '</div>';
|
||||||
|
calendarGrid.append(dayHtml);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 绑定日期点击事件
|
||||||
|
$('#calendarGrid').off('click', '.calendar-day').on('click', '.calendar-day', function() {
|
||||||
|
var clickedDate = $(this).attr('data-date');
|
||||||
|
if (clickedDate && !$(this).hasClass('empty')) {
|
||||||
|
showDateDetails(clickedDate);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 异步加载数据并更新
|
||||||
|
var startDate = new Date(year, month, 1);
|
||||||
|
var endDate = new Date(year, month + 1, 0);
|
||||||
|
loadMonthData(selectedRoomId, startDate, endDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载月度数据
|
||||||
|
function loadMonthData(roomId, startDate, endDate) {
|
||||||
|
var daysToLoad = [];
|
||||||
|
|
||||||
|
// 生成日期列表
|
||||||
|
var currentDate = new Date(startDate);
|
||||||
|
while (currentDate <= endDate) {
|
||||||
|
daysToLoad.push(new Date(currentDate));
|
||||||
|
currentDate.setDate(currentDate.getDate() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
console.log('开始加载数据,房间ID:', roomId, '日期数量:', daysToLoad.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量加载数据,每个日期加载完成后立即更新
|
||||||
|
daysToLoad.forEach(function(date) {
|
||||||
|
var dateStr = formatDate(date);
|
||||||
|
var url = layui.setter.apiUrl + "Api/SQRoomPricing/GetRoomListWithSlots?date=" + encodeURIComponent(dateStr) + "&showOnlyAvailable=false";
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
console.log('请求URL:', url);
|
||||||
|
}
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: url,
|
||||||
|
type: 'GET',
|
||||||
|
dataType: 'json',
|
||||||
|
success: function(e) {
|
||||||
|
if (debug) {
|
||||||
|
console.log('日期:', dateStr, '返回数据:', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
var dayElement = $('#calendarGrid').find('.calendar-day[data-date="' + dateStr + '"]');
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
console.log('查找元素:', dateStr, '找到:', dayElement.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dayElement.length === 0) {
|
||||||
|
console.warn('未找到日期元素:', dateStr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清空加载提示(保留日期标题)
|
||||||
|
dayElement.find('div:not(.calendar-day-header)').remove();
|
||||||
|
|
||||||
|
if (e.code === 0 && e.data && Array.isArray(e.data)) {
|
||||||
|
// 注意:roomId 可能是字符串,需要类型转换比较
|
||||||
|
var roomData = e.data.find(function(r) {
|
||||||
|
return r.id == roomId || r.id == parseInt(roomId);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
console.log('查找房间:', roomId, '找到:', roomData ? '是' : '否');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (roomData && roomData.time_slots && Array.isArray(roomData.time_slots)) {
|
||||||
|
var dayContentHtml = '';
|
||||||
|
|
||||||
|
// 显示价格信息
|
||||||
|
var firstSlot = roomData.time_slots[0];
|
||||||
|
if (firstSlot && firstSlot.standard_price) {
|
||||||
|
dayContentHtml += '<div class="calendar-day-price">' + firstSlot.standard_price + '元/时段</div>';
|
||||||
|
}
|
||||||
|
if (firstSlot && firstSlot.member_price > 0) {
|
||||||
|
dayContentHtml += '<div class="calendar-day-member">会员价</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示时段状态
|
||||||
|
dayContentHtml += '<div class="calendar-day-slots">';
|
||||||
|
roomData.time_slots.forEach(function(slot) {
|
||||||
|
var statusClass = 'unavailable';
|
||||||
|
var statusIcon = '✗';
|
||||||
|
|
||||||
|
if (slot.status === 'available') {
|
||||||
|
statusClass = 'available';
|
||||||
|
statusIcon = '◯';
|
||||||
|
} else if (slot.status === 'reserved') {
|
||||||
|
statusClass = 'reserved';
|
||||||
|
statusIcon = '✓ ';
|
||||||
|
}else if( slot.status === 'using'){
|
||||||
|
statusClass = 'using';
|
||||||
|
statusIcon = '✗';
|
||||||
|
}
|
||||||
|
|
||||||
|
dayContentHtml += '<div class="calendar-slot ' + statusClass + '">' +
|
||||||
|
slot.slot_name + statusIcon + '</div>';
|
||||||
|
});
|
||||||
|
dayContentHtml += '</div>';
|
||||||
|
|
||||||
|
dayElement.append(dayContentHtml);
|
||||||
|
} else {
|
||||||
|
dayElement.append('<div style="text-align:center;color:#999;padding:10px 0;">无房间数据</div>');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var errorMsg = e.msg || '加载失败';
|
||||||
|
dayElement.append('<div style="text-align:center;color:#f44336;padding:10px 0;">' + errorMsg + '</div>');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function(xhr, status, error) {
|
||||||
|
console.error('请求失败:', dateStr, status, error);
|
||||||
|
var dayElement = $('#calendarGrid').find('.calendar-day[data-date="' + dateStr + '"]');
|
||||||
|
if (dayElement.length > 0) {
|
||||||
|
dayElement.find('div:not(.calendar-day-header)').remove();
|
||||||
|
dayElement.append('<div style="text-align:center;color:#f44336;padding:10px 0;">网络错误</div>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化日期为 YYYY-MM-DD
|
||||||
|
function formatDate(date) {
|
||||||
|
var year = date.getFullYear();
|
||||||
|
var month = (date.getMonth() + 1).toString().padStart(2, '0');
|
||||||
|
var day = date.getDate().toString().padStart(2, '0');
|
||||||
|
return year + '-' + month + '-' + day;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 展示日期详情弹窗
|
||||||
|
function showDateDetails(dateStr) {
|
||||||
|
if (!selectedRoomId) {
|
||||||
|
layer.msg('请先选择房间');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找对应的房间名称
|
||||||
|
var selectedRoom = roomOptions.find(function(r) {
|
||||||
|
return r.id == selectedRoomId;
|
||||||
|
});
|
||||||
|
var roomName = selectedRoom ? selectedRoom.name : '未知房间';
|
||||||
|
|
||||||
|
// 显示加载提示
|
||||||
|
var loadingIndex = layer.load(1, { shade: [0.1, '#fff'] });
|
||||||
|
|
||||||
|
// 请求详细数据
|
||||||
|
var url = layui.setter.apiUrl + "Api/SQRoomPricing/GetDateDetails?date=" + encodeURIComponent(dateStr) + "&roomId=" + selectedRoomId;
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: url,
|
||||||
|
type: 'GET',
|
||||||
|
dataType: 'json',
|
||||||
|
success: function(e) {
|
||||||
|
layer.close(loadingIndex);
|
||||||
|
|
||||||
|
if (e.code === 0 && e.data) {
|
||||||
|
var data = e.data;
|
||||||
|
|
||||||
|
// 构建弹窗内容
|
||||||
|
var content = '<div style="padding: 20px;">';
|
||||||
|
|
||||||
|
// 日期和房间信息
|
||||||
|
content += '<div class="layui-row">';
|
||||||
|
content += ' <div class="layui-col-md12">';
|
||||||
|
content += ' <div class="layui-card">';
|
||||||
|
content += ' <div class="layui-card-header"><h3>日期信息</h3></div>';
|
||||||
|
content += ' <div class="layui-card-body">';
|
||||||
|
content += ' <div class="layui-row">';
|
||||||
|
content += ' <div class="layui-col-md6">';
|
||||||
|
content += ' <p><strong>日期:</strong>' + dateStr + '</p>';
|
||||||
|
content += ' <p><strong>房间:</strong>' + roomName + '</p>';
|
||||||
|
content += ' </div>';
|
||||||
|
content += ' <div class="layui-col-md6">';
|
||||||
|
content += ' <p><strong>星期:</strong>' + getWeekDay(dateStr) + '</p>';
|
||||||
|
content += ' </div>';
|
||||||
|
content += ' </div>';
|
||||||
|
content += ' </div>';
|
||||||
|
content += ' </div>';
|
||||||
|
content += ' </div>';
|
||||||
|
content += '</div>';
|
||||||
|
|
||||||
|
// 时段详情
|
||||||
|
if (data.time_slots && data.time_slots.length > 0) {
|
||||||
|
content += '<div class="layui-row" style="margin-top: 20px;">';
|
||||||
|
content += ' <div class="layui-col-md12">';
|
||||||
|
content += ' <div class="layui-card">';
|
||||||
|
content += ' <div class="layui-card-header"><h3>时段详情</h3></div>';
|
||||||
|
content += ' <div class="layui-card-body">';
|
||||||
|
content += ' <table id="dateDetailsTable" lay-filter="dateDetailsTable"></table>';
|
||||||
|
content += ' </div>';
|
||||||
|
content += ' </div>';
|
||||||
|
content += ' </div>';
|
||||||
|
content += '</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 预约详情列表(按时段分组)
|
||||||
|
content += '<div id="reservationsBySlot"></div>';
|
||||||
|
|
||||||
|
content += '</div>';
|
||||||
|
|
||||||
|
// 弹出窗口
|
||||||
|
layer.open({
|
||||||
|
type: 1,
|
||||||
|
title: roomName + ' - ' + dateStr + ' 详情',
|
||||||
|
area: ['1200px', '90%'],
|
||||||
|
content: content,
|
||||||
|
success: function(layero, index) {
|
||||||
|
// 渲染时段详情表格
|
||||||
|
if (data.time_slots && data.time_slots.length > 0) {
|
||||||
|
var tableData = data.time_slots.map(function(slot) {
|
||||||
|
return {
|
||||||
|
slot_name: slot.slot_name || '',
|
||||||
|
status: slot.status || '',
|
||||||
|
price_desc_standard: slot.price_desc_standard || '',
|
||||||
|
price_desc_member: slot.price_desc_member || '',
|
||||||
|
participant_avatars: slot.participant_avatars || [],
|
||||||
|
reservation_count: slot.reservation_count || 0
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
table.render({
|
||||||
|
elem: '#dateDetailsTable',
|
||||||
|
data: tableData,
|
||||||
|
page: false,
|
||||||
|
cols: [[
|
||||||
|
{ field: 'slot_name', title: '时段', width: 100 },
|
||||||
|
{
|
||||||
|
field: 'status',
|
||||||
|
title: '状态',
|
||||||
|
width: 100,
|
||||||
|
templet: function(d) {
|
||||||
|
var statusText = '';
|
||||||
|
var statusColor = '';
|
||||||
|
if (d.status === 'available') {
|
||||||
|
statusText = '可用';
|
||||||
|
statusColor = '#5FB878';
|
||||||
|
} else if (d.status === 'reserved') {
|
||||||
|
statusText = '已预约';
|
||||||
|
statusColor = '#FFB800';
|
||||||
|
} else if (d.status === 'using') {
|
||||||
|
statusText = '使用中';
|
||||||
|
statusColor = '#999';
|
||||||
|
} else if (d.status === 'unavailable') {
|
||||||
|
statusText = '不可用';
|
||||||
|
statusColor = '#FF5722';
|
||||||
|
} else {
|
||||||
|
statusText = d.status;
|
||||||
|
statusColor = '#999';
|
||||||
|
}
|
||||||
|
return '<span style="background: ' + statusColor + '; color: white; padding: 2px 8px; border-radius: 3px; font-size: 12px;">' + statusText + '</span>';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ field: 'price_desc_standard', title: '普通价格描述', width: 150 },
|
||||||
|
{ field: 'price_desc_member', title: '会员价格描述', width: 150 },
|
||||||
|
{
|
||||||
|
field: 'participant_avatars',
|
||||||
|
title: '预约人头像',
|
||||||
|
width: 200,
|
||||||
|
templet: function(d) {
|
||||||
|
if (!d.participant_avatars || d.participant_avatars.length === 0) {
|
||||||
|
return '<span style="color: #999;">无</span>';
|
||||||
|
}
|
||||||
|
var html = '<div style="display: flex; gap: 4px; flex-wrap: wrap;">';
|
||||||
|
d.participant_avatars.forEach(function(avatar) {
|
||||||
|
html += '<img src="' + avatar + '" style="width:28px;height:28px;border-radius:50%;object-fit:cover;" onerror="this.src=\'/images/default-avatar.png\'" />';
|
||||||
|
});
|
||||||
|
html += '</div>';
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ field: 'reservation_count', title: '预约人数', width: 100 }
|
||||||
|
]]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 渲染按时段分组的预约详情
|
||||||
|
if (data.reservations_by_slot) {
|
||||||
|
var slotNames = ['凌晨', '上午', '下午', '晚上'];
|
||||||
|
var reservationsBySlotContainer = $('#reservationsBySlot');
|
||||||
|
|
||||||
|
for (var slotType = 0; slotType <= 3; slotType++) {
|
||||||
|
var slotReservations = data.reservations_by_slot[slotType];
|
||||||
|
|
||||||
|
if (slotReservations && slotReservations.length > 0) {
|
||||||
|
// 时段标题
|
||||||
|
var slotHtml = '<div class="layui-row" style="margin-top: 20px;">';
|
||||||
|
slotHtml += ' <div class="layui-col-md12">';
|
||||||
|
slotHtml += ' <h3 style="padding: 10px; background: #f8f8f8; border-left: 4px solid #009688;">预约详情列表(' + slotNames[slotType] + ')</h3>';
|
||||||
|
|
||||||
|
// 遍历该时段的每个预约
|
||||||
|
slotReservations.forEach(function(reservation, idx) {
|
||||||
|
slotHtml += ' <div class="layui-card" style="margin-top: 10px;">';
|
||||||
|
slotHtml += ' <div class="layui-card-header">';
|
||||||
|
slotHtml += ' <div class="layui-row">';
|
||||||
|
slotHtml += ' <div class="layui-col-md3"><strong>组局名称:</strong>' + (reservation.title || '无') + '</div>';
|
||||||
|
slotHtml += ' <div class="layui-col-md2"><strong>参与人数:</strong>' + (reservation.player_count || 0) + '人</div>';
|
||||||
|
slotHtml += ' <div class="layui-col-md2"><strong>鸽子费:</strong>' + (reservation.deposit_fee || 0) + '元</div>';
|
||||||
|
slotHtml += ' <div class="layui-col-md3"><strong>最晚到店:</strong>' + (reservation.latest_arrival_time || '无') + '</div>';
|
||||||
|
slotHtml += ' </div>';
|
||||||
|
slotHtml += ' <div class="layui-row" style="margin-top: 5px;">';
|
||||||
|
slotHtml += ' <div class="layui-col-md3"><strong>玩法类型:</strong>' + (reservation.game_type || '无') + '</div>';
|
||||||
|
slotHtml += ' <div class="layui-col-md3"><strong>具体规则:</strong>' + (reservation.game_rule || '无') + '</div>';
|
||||||
|
slotHtml += ' <div class="layui-col-md4"><strong>开始时间:</strong>' + (reservation.start_time || '无') + '</div>';
|
||||||
|
slotHtml += ' </div>';
|
||||||
|
slotHtml += ' </div>';
|
||||||
|
slotHtml += ' <div class="layui-card-body">';
|
||||||
|
slotHtml += ' <table id="participantsTable_' + slotType + '_' + reservation.id + '" lay-filter="participantsTable_' + slotType + '_' + reservation.id + '"></table>';
|
||||||
|
slotHtml += ' </div>';
|
||||||
|
slotHtml += ' </div>';
|
||||||
|
});
|
||||||
|
|
||||||
|
slotHtml += ' </div>';
|
||||||
|
slotHtml += '</div>';
|
||||||
|
|
||||||
|
reservationsBySlotContainer.append(slotHtml);
|
||||||
|
|
||||||
|
// 渲染每个预约的参与者表格
|
||||||
|
slotReservations.forEach(function(reservation, idx) {
|
||||||
|
var participants = reservation.participants || [];
|
||||||
|
|
||||||
|
table.render({
|
||||||
|
elem: '#participantsTable_' + slotType + '_' + reservation.id,
|
||||||
|
data: participants,
|
||||||
|
page: false,
|
||||||
|
cols: [[
|
||||||
|
{ field: 'id', title: 'ID', width: 60 },
|
||||||
|
{ field: 'user_id', title: '用户ID', width: 80 },
|
||||||
|
{ field: 'user_name', title: '用户昵称', width: 120 },
|
||||||
|
{
|
||||||
|
field: 'avatar_image',
|
||||||
|
title: '用户头像',
|
||||||
|
width: 80,
|
||||||
|
templet: function(d) {
|
||||||
|
if (d.avatar_image) {
|
||||||
|
return '<img src="' + d.avatar_image + '" style="width:40px;height:40px;border-radius:50%;object-fit:cover;" onerror="this.src=\'/images/default-avatar.png\'" />';
|
||||||
|
}
|
||||||
|
return '<span style="color: #999;">无</span>';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ field: 'join_time', title: '参与时间', width: 150 },
|
||||||
|
{
|
||||||
|
field: 'role',
|
||||||
|
title: '角色',
|
||||||
|
width: 80,
|
||||||
|
templet: function(d) {
|
||||||
|
return d.role === 1 ? '<span style="color: #ff5722;">发起者</span>' : '参与者';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ field: 'quit_time', title: '退出时间', width: 150 },
|
||||||
|
{
|
||||||
|
field: 'is_refund',
|
||||||
|
title: '鸽子费状态',
|
||||||
|
width: 100,
|
||||||
|
templet: function(d) {
|
||||||
|
var refundText = '';
|
||||||
|
var refundColor = '';
|
||||||
|
switch(d.is_refund) {
|
||||||
|
case 0:
|
||||||
|
refundText = '无需退款';
|
||||||
|
refundColor = '#999';
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
refundText = '未付鸽子费';
|
||||||
|
refundColor = '#1E9FFF';
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
refundText = '已付鸽子费';
|
||||||
|
refundColor = '#FFB800';
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
refundText = '退款中';
|
||||||
|
refundColor = '#5FB878';
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
refundText = '退款成功';
|
||||||
|
refundColor = '#5FB878';
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
refundText = '退款失败';
|
||||||
|
refundColor = '#FF5722';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
refundText = '未知状态';
|
||||||
|
refundColor = '#999';
|
||||||
|
}
|
||||||
|
return '<span style="background: ' + refundColor + '; color: white; padding: 2px 6px; border-radius: 3px; font-size: 12px;">' + refundText + '</span>';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ field: 'remarks', title: '备注', minWidth: 150 }
|
||||||
|
]]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
layer.msg(e.msg || '获取数据失败');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function(xhr, status, error) {
|
||||||
|
layer.close(loadingIndex);
|
||||||
|
console.error('请求失败:', status, error);
|
||||||
|
layer.msg('获取数据失败,请稍后重试');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取星期几
|
||||||
|
function getWeekDay(dateStr) {
|
||||||
|
var date = new Date(dateStr);
|
||||||
|
var weekDays = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
|
||||||
|
return weekDays[date.getDay()];
|
||||||
|
}
|
||||||
|
|
||||||
//重载form
|
//重载form
|
||||||
form.render();
|
form.render();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 查看预约详情(全局函数,供表格调用)
|
||||||
|
function viewReservationDetail(reservationId) {
|
||||||
|
// 跳转到预约管理页面或打开预约详情弹窗
|
||||||
|
layer.msg('预约ID: ' + reservationId + ',可跳转到预约详情页面');
|
||||||
|
// 实际使用时可以调用预约详情接口
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!--设置是否启用-->
|
<!--设置是否启用-->
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user