调整挂单统计,修改删除区域报错
This commit is contained in:
@@ -33,6 +33,10 @@ public class guadanGuestQueryController: ApiController
|
|||||||
{
|
{
|
||||||
query = query.Where(guest => guest.CheckInAt == search.searchCheckInDate);
|
query = query.Where(guest => guest.CheckInAt == search.searchCheckInDate);
|
||||||
}
|
}
|
||||||
|
if(search.searchCheckOutDate != null)
|
||||||
|
{
|
||||||
|
query = query.Where(guest => guest.CheckOutAt == search.searchCheckOutDate);
|
||||||
|
}
|
||||||
if(search.searchCheckInDateStart != null)
|
if(search.searchCheckInDateStart != null)
|
||||||
{
|
{
|
||||||
query = query.Where(guest => guest.CheckInAt >= search.searchCheckInDateStart);
|
query = query.Where(guest => guest.CheckInAt >= search.searchCheckInDateStart);
|
||||||
@@ -116,7 +116,7 @@ public class guadanOrderGuestController : ApiController
|
|||||||
return BadRequest("床位在該時間段內已被占用");
|
return BadRequest("床位在該時間段內已被占用");
|
||||||
if (model.followerNum.HasValue)
|
if (model.followerNum.HasValue)
|
||||||
{
|
{
|
||||||
if (_db.GuaDanOrderGuest.Any(a => a.FollowerNum == model.followerNum
|
if (_db.GuaDanOrderGuest.Any(a => a.FollowerNum == model.followerNum
|
||||||
&& a.GuaDanOrderNo == model.orderNo
|
&& a.GuaDanOrderNo == model.orderNo
|
||||||
&& a.StatusCode != "404"
|
&& a.StatusCode != "404"
|
||||||
))
|
))
|
||||||
@@ -330,31 +330,31 @@ public class guadanOrderGuestController : ApiController
|
|||||||
[Route("api/guadanorderguest/xuzhu")]
|
[Route("api/guadanorderguest/xuzhu")]
|
||||||
public async Task<IHttpActionResult> ExtendStay([FromBody] XuZhuModel model)
|
public async Task<IHttpActionResult> ExtendStay([FromBody] XuZhuModel model)
|
||||||
{
|
{
|
||||||
//续住方法
|
//續住方法
|
||||||
if (model == null)
|
if (model == null)
|
||||||
return BadRequest("请求数据为空");
|
return BadRequest("請求數據為空");
|
||||||
|
|
||||||
if (model.GuestUuid == Guid.Empty || model.GuestBedUuid == Guid.Empty)
|
if (model.GuestUuid == Guid.Empty || model.GuestBedUuid == Guid.Empty)
|
||||||
return BadRequest("GuestUuid 或 GuestBedUuid 无效");
|
return BadRequest("GuestUuid 或 GuestBedUuid 無效");
|
||||||
var guest= await _db.GuaDanOrderGuest.FindAsync(model.GuestUuid);
|
var guest = await _db.GuaDanOrderGuest.FindAsync(model.GuestUuid);
|
||||||
if (guest == null)
|
if (guest == null)
|
||||||
{
|
{
|
||||||
return BadRequest("挂单不存在");
|
return BadRequest("掛單不存在");
|
||||||
}
|
}
|
||||||
if(guest.BedUuid != model.GuestBedUuid)
|
if (guest.BedUuid != model.GuestBedUuid)
|
||||||
{
|
{
|
||||||
return BadRequest("床位不正确");
|
return BadRequest("床位不正確");
|
||||||
}
|
}
|
||||||
var bedIsCanUse = await RegionAndRoomAndBedSchedule.IsBedAvailableAsync(_db,model.GuestBedUuid, model.CurrentCheckoutDate, model.NewCheckoutDate);
|
var bedIsCanUse = await RegionAndRoomAndBedSchedule.IsBedAvailableAsync(_db, model.GuestBedUuid, model.CurrentCheckoutDate, model.NewCheckoutDate);
|
||||||
if(!bedIsCanUse)
|
if (!bedIsCanUse)
|
||||||
{
|
{
|
||||||
return BadRequest("该床位在续住时间段内被预定,无法续住");
|
return BadRequest("該床位在續住時間段內被預定,無法續住");
|
||||||
}
|
}
|
||||||
|
|
||||||
var newStartDate = model.CurrentCheckoutDate.Date;
|
var newStartDate = model.CurrentCheckoutDate.Date;
|
||||||
var newEndDate = model.NewCheckoutDate.Date.AddDays(-1);
|
var newEndDate = model.NewCheckoutDate.Date.AddDays(-1);
|
||||||
if (newEndDate < newStartDate)
|
if (newEndDate < newStartDate)
|
||||||
return BadRequest("续住日期区间无效");
|
return BadRequest("續住日期區間無效");
|
||||||
for (var date = newStartDate; date <= newEndDate; date = date.AddDays(1))
|
for (var date = newStartDate; date <= newEndDate; date = date.AddDays(1))
|
||||||
{
|
{
|
||||||
var newSchedule = new RegionAndRoomAndBedSchedule
|
var newSchedule = new RegionAndRoomAndBedSchedule
|
||||||
@@ -364,8 +364,8 @@ public class guadanOrderGuestController : ApiController
|
|||||||
TargetUuid = model.GuestBedUuid,
|
TargetUuid = model.GuestBedUuid,
|
||||||
GuaDanOrderGuestUuid = model.GuestUuid,
|
GuaDanOrderGuestUuid = model.GuestUuid,
|
||||||
ScheduleDate = date,
|
ScheduleDate = date,
|
||||||
Title = "续住挂单", // 一天一条,开始和结束是同一天
|
Title = "續住掛單", // 一天一條,開始和結束是同一天
|
||||||
Description = "续住挂单",
|
Description = "續住掛單",
|
||||||
UseType = 30,
|
UseType = 30,
|
||||||
CreatedAt = DateTime.UtcNow
|
CreatedAt = DateTime.UtcNow
|
||||||
};
|
};
|
||||||
@@ -373,8 +373,8 @@ public class guadanOrderGuestController : ApiController
|
|||||||
_db.RegionAndRoomAndBedSchedule.Add(newSchedule);
|
_db.RegionAndRoomAndBedSchedule.Add(newSchedule);
|
||||||
}
|
}
|
||||||
guest.CheckOutAt = model.NewCheckoutDate.Date;
|
guest.CheckOutAt = model.NewCheckoutDate.Date;
|
||||||
await _db.SaveChangesAsync(); // 保存数据库操作
|
await _db.SaveChangesAsync(); // 保存資料庫操作
|
||||||
return Ok(new { message = "续住成功" });
|
return Ok(new { message = "續住成功" });
|
||||||
}
|
}
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[Route("api/guadanorderguest/cancel")]
|
[Route("api/guadanorderguest/cancel")]
|
||||||
@@ -495,13 +495,13 @@ public class guadanOrderGuestController : ApiController
|
|||||||
|
|
||||||
//更新未來排程為取消
|
//更新未來排程為取消
|
||||||
var latestCheckoutStr = _db.GuadanTimeSetting
|
var latestCheckoutStr = _db.GuadanTimeSetting
|
||||||
.Select(a => a.LatestCheckOut) // 字符串 "HH:mm"
|
.Select(a => a.LatestCheckOut) // 字串 "HH:mm"
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
|
|
||||||
TimeSpan? latestCheckoutTime = null;
|
TimeSpan? latestCheckoutTime = null;
|
||||||
if (!string.IsNullOrEmpty(latestCheckoutStr))
|
if (!string.IsNullOrEmpty(latestCheckoutStr))
|
||||||
{
|
{
|
||||||
// 尝试解析字符串
|
// 嘗試解析字串
|
||||||
if (TimeSpan.TryParse(latestCheckoutStr, out var ts))
|
if (TimeSpan.TryParse(latestCheckoutStr, out var ts))
|
||||||
{
|
{
|
||||||
latestCheckoutTime = ts;
|
latestCheckoutTime = ts;
|
||||||
@@ -588,7 +588,7 @@ public class guadanOrderGuestController : ApiController
|
|||||||
if (guest.BedUuid != null)
|
if (guest.BedUuid != null)
|
||||||
{
|
{
|
||||||
var bed = _db.RegionRoomBed.FirstOrDefault(b => b.Uuid == guest.BedUuid);
|
var bed = _db.RegionRoomBed.FirstOrDefault(b => b.Uuid == guest.BedUuid);
|
||||||
if(bed == null)
|
if (bed == null)
|
||||||
{
|
{
|
||||||
return BadRequest("入住床位不存在");
|
return BadRequest("入住床位不存在");
|
||||||
}
|
}
|
||||||
@@ -598,10 +598,10 @@ public class guadanOrderGuestController : ApiController
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return BadRequest($"当前床位状态:{bed.RegionRoomBedStatus.Name} 不能入住");
|
return BadRequest($"當前床位狀態:{bed.RegionRoomBedStatus.Name} 不能入住");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(guest.BedUuid == null)
|
else if (guest.BedUuid == null)
|
||||||
{
|
{
|
||||||
return BadRequest("入住床位不存在");
|
return BadRequest("入住床位不存在");
|
||||||
}
|
}
|
||||||
@@ -653,10 +653,10 @@ public class guadanOrderGuestController : ApiController
|
|||||||
}
|
}
|
||||||
public class XuZhuModel
|
public class XuZhuModel
|
||||||
{
|
{
|
||||||
public Guid GuestUuid { get; set; } // 不可为空
|
public Guid GuestUuid { get; set; } // 不可為空
|
||||||
public Guid GuestBedUuid { get; set; } // 不可为空
|
public Guid GuestBedUuid { get; set; } // 不可為空
|
||||||
public DateTime CurrentCheckoutDate { get; set; } // 当前退房时间
|
public DateTime CurrentCheckoutDate { get; set; } // 當前退房時間
|
||||||
public DateTime NewCheckoutDate { get; set; } // 新退房时间
|
public DateTime NewCheckoutDate { get; set; } // 新退房時間
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -21,39 +21,49 @@ public class guadanStatisticsController: ApiController
|
|||||||
//挂单统计:房间,床位,挂单笔数,挂单人数的统计
|
//挂单统计:房间,床位,挂单笔数,挂单人数的统计
|
||||||
|
|
||||||
var now = DateTime.Now;
|
var now = DateTime.Now;
|
||||||
var roomCount = await _db.Room.Where(a => a.IsDeleted == false).CountAsync();
|
var guadanTotalCount = await _db.GuaDanOrder
|
||||||
var rooms = await _db.Room.Include(r => r.RegionRoomBed).ToListAsync();
|
.Where(a => a.IsDeleted == false)
|
||||||
|
.Where(a => a.IsCancel == false)
|
||||||
var emptyRoomCount = rooms
|
.CountAsync();
|
||||||
.Where(r => r.RegionRoomBed.All(b => b.IsAvailableDuring(now, now, _db))) // 這裡就能用方法
|
var guadanCurrentCount = await _db.GuaDanOrderGuest
|
||||||
.Count();
|
.Where(guest => guest.StatusCode != "403")
|
||||||
var bedCount = await _db.RegionRoomBed.Where(a => a.IsDeleted == false).CountAsync();
|
.Where(guest => guest.StatusCode != "404")
|
||||||
var maleBedCount = await _db.RegionRoomBed.Where(a => a.IsDeleted == false && a.Gender == true).CountAsync();
|
.Select(guest => guest.GuaDanOrderNo)
|
||||||
var femaleBedCount = await _db.RegionRoomBed.Where(a => a.IsDeleted == false && a.Gender == false).CountAsync();
|
.Distinct()
|
||||||
|
.CountAsync();
|
||||||
var guadanTotalCount = await _db.GuaDanOrder.Where(a => a.IsDeleted == false).CountAsync();
|
var guadanPeopleTotal = await _db.GuaDanOrderGuest
|
||||||
var guadanPeopleTotal = await _db.GuaDanOrderGuest.Where(a => a.IsDeleted == false).CountAsync();
|
.Where(a => a.IsDeleted == false)
|
||||||
var guadanPeopleMale = await _db.GuaDanOrderGuest.Where(a => a.IsDeleted == false && a.followers.sex == "男眾").CountAsync();
|
.Where(guest => guest.StatusCode != "404")
|
||||||
var guadanPeopleFemale = await _db.GuaDanOrderGuest.Where(a => a.IsDeleted == false && a.followers.sex == "女眾").CountAsync();
|
.CountAsync();
|
||||||
dynamic bedCounts = await RegionAndRoomAndBedSchedule.GetAvailableBedCountsAsync(_db, DateTime.Now, DateTime.Now);
|
var guadanPeopleMale = await _db.GuaDanOrderGuest
|
||||||
var guadanCurrentCount = await _db.GuaDanOrder.Where(a => now < a.EndDate).CountAsync();
|
.Where(guest => guest.StatusCode != "404")
|
||||||
var guadanPeopleCurrent = await _db.GuaDanOrderGuest.Where( a => a.CheckOutAt > now).CountAsync();
|
.Where(a => a.IsDeleted == false && a.followers.sex == "男眾")
|
||||||
var guadanPeopleCurrentMale = await _db.GuaDanOrderGuest.Where(a => a.CheckOutAt > now && a.followers.sex == "男眾").CountAsync();
|
.CountAsync();
|
||||||
var guadanPeopleCurrentFemale = await _db.GuaDanOrderGuest.Where(a => a.CheckOutAt > now && a.followers.sex == "女眾").CountAsync();
|
var guadanPeopleFemale = await _db.GuaDanOrderGuest
|
||||||
|
.Where(guest => guest.StatusCode != "404")
|
||||||
|
.Where(a => a.IsDeleted == false && a.followers.sex == "女眾")
|
||||||
|
.CountAsync();
|
||||||
|
var guadanPeopleCurrent = await _db.GuaDanOrderGuest
|
||||||
|
.Where(a => a.IsDeleted == false)
|
||||||
|
.Where(guest => guest.StatusCode != "404")
|
||||||
|
.Where(guest => guest.StatusCode != "403")
|
||||||
|
.Where( a => a.CheckOutAt >= now.Date)
|
||||||
|
.CountAsync();
|
||||||
|
var guadanPeopleCurrentMale = await _db.GuaDanOrderGuest
|
||||||
|
.Where(a => a.IsDeleted == false)
|
||||||
|
.Where(guest => guest.StatusCode != "404")
|
||||||
|
.Where(guest => guest.StatusCode != "403")
|
||||||
|
.Where(a => a.CheckOutAt >= now.Date && a.followers.sex == "男眾")
|
||||||
|
.CountAsync();
|
||||||
|
var guadanPeopleCurrentFemale = await _db.GuaDanOrderGuest
|
||||||
|
.Where(a => a.IsDeleted == false)
|
||||||
|
.Where(guest => guest.StatusCode != "404")
|
||||||
|
.Where(guest => guest.StatusCode != "403")
|
||||||
|
.Where(a => a.CheckOutAt >= now.Date && a.followers.sex == "女眾")
|
||||||
|
.CountAsync();
|
||||||
|
|
||||||
var result = new
|
var result = new
|
||||||
{
|
{
|
||||||
roomStatistics = new
|
|
||||||
{
|
|
||||||
roomCount = roomCount,
|
|
||||||
emptyRoomCount = emptyRoomCount,
|
|
||||||
bedCount = bedCount,
|
|
||||||
maleBedCount = maleBedCount,
|
|
||||||
femaleBedCount = femaleBedCount,
|
|
||||||
emptyBedCount = bedCounts.male + bedCounts.female,
|
|
||||||
emptyMaleBedCount = bedCounts.male,
|
|
||||||
emptyFemaleBedCount = bedCounts.female
|
|
||||||
},
|
|
||||||
guadanStatistics = new
|
guadanStatistics = new
|
||||||
{
|
{
|
||||||
guadanTotalCount = guadanTotalCount, // 总挂单次数
|
guadanTotalCount = guadanTotalCount, // 总挂单次数
|
||||||
@@ -61,7 +71,7 @@ public class guadanStatisticsController: ApiController
|
|||||||
guadanPeopleTotal = guadanPeopleTotal, // 总挂单人数
|
guadanPeopleTotal = guadanPeopleTotal, // 总挂单人数
|
||||||
guadanPeopleMale = guadanPeopleMale,
|
guadanPeopleMale = guadanPeopleMale,
|
||||||
guadanPeopleFemale = guadanPeopleFemale,
|
guadanPeopleFemale = guadanPeopleFemale,
|
||||||
guadanPeopleCurrent = guadanPeopleCurrent, // 当前挂单人数
|
guadanPeopleCurrent = guadanPeopleCurrent, // 已預約掛單人數
|
||||||
guadanPeopleCurrentMale = guadanPeopleCurrentMale,
|
guadanPeopleCurrentMale = guadanPeopleCurrentMale,
|
||||||
guadanPeopleCurrentFemale = guadanPeopleCurrentFemale
|
guadanPeopleCurrentFemale = guadanPeopleCurrentFemale
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,16 +63,6 @@ public class guadanStatisticsTableController: ApiController
|
|||||||
.OrderBy(x => x.date)
|
.OrderBy(x => x.date)
|
||||||
.ToList();
|
.ToList();
|
||||||
var todayDate = DateTime.Today;
|
var todayDate = DateTime.Today;
|
||||||
dynamic today = statistics.FirstOrDefault(x => x.date == todayDate);
|
|
||||||
|
|
||||||
if (today == null)
|
|
||||||
{
|
|
||||||
var todayCount = _db.RegionAndRoomAndBedSchedule
|
|
||||||
.Where(s => s.ScheduleDate == todayDate && !s.IsCancel)
|
|
||||||
.Count();
|
|
||||||
|
|
||||||
today = new { date = todayDate, todaytotalbookers = todayCount };
|
|
||||||
}
|
|
||||||
|
|
||||||
var bedcount = _db.RegionRoomBed
|
var bedcount = _db.RegionRoomBed
|
||||||
.Where(a => a.IsDeleted == false)
|
.Where(a => a.IsDeleted == false)
|
||||||
@@ -83,11 +73,6 @@ public class guadanStatisticsTableController: ApiController
|
|||||||
bedcount,
|
bedcount,
|
||||||
roomcount,
|
roomcount,
|
||||||
statistics,
|
statistics,
|
||||||
today,
|
|
||||||
totalbookers = _db.RegionAndRoomAndBedSchedule
|
|
||||||
.Where(s => s.IsCancel == false)
|
|
||||||
.Where(s => s.ScheduleDate >= DateTime.Today)
|
|
||||||
.Count(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return Ok(result);
|
return Ok(result);
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ public class regionController : ApiController
|
|||||||
&& (s.ScheduleDate == null
|
&& (s.ScheduleDate == null
|
||||||
|| (s.ScheduleDate >= startDate)))
|
|| (s.ScheduleDate >= startDate)))
|
||||||
.Where(s => s.GuaDanOrderGuest.StatusCode != "403" && s.GuaDanOrderGuest.StatusCode != "404")
|
.Where(s => s.GuaDanOrderGuest.StatusCode != "403" && s.GuaDanOrderGuest.StatusCode != "404")
|
||||||
.OrderByDescending(a => a.ScheduleDate)
|
.OrderBy(a => a.ScheduleDate)
|
||||||
.Select(s => new
|
.Select(s => new
|
||||||
{
|
{
|
||||||
s.Uuid,
|
s.Uuid,
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
<nav>
|
<nav>
|
||||||
<a href="create.aspx" class="btn btn-primary" >新建掛單</a>
|
<a href="create.aspx" class="btn btn-primary" >新建掛單</a>
|
||||||
</nav>
|
</nav>
|
||||||
|
<div class="me-10">
|
||||||
|
<button class="btn btn-primary" type="button">查询</button>
|
||||||
|
</div>
|
||||||
</asp:Content>
|
</asp:Content>
|
||||||
<asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
|
<asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
|
||||||
|
|
||||||
@@ -27,10 +30,10 @@
|
|||||||
{{item.status}}
|
{{item.status}}
|
||||||
</template>
|
</template>
|
||||||
<template #item.start_date="{item}">
|
<template #item.start_date="{item}">
|
||||||
{{item.start_date | timeString('YYYY/MM/DD HH:mm')}}
|
{{item.start_date | timeString('YYYY/MM/DD')}}
|
||||||
</template>
|
</template>
|
||||||
<template #item.end_date="{item}">
|
<template #item.end_date="{item}">
|
||||||
{{item.end_date | timeString('YYYY/MM/DD HH:mm')}}
|
{{item.end_date | timeString('YYYY/MM/DD')}}
|
||||||
</template>
|
</template>
|
||||||
<template #item.created_at="{item}">
|
<template #item.created_at="{item}">
|
||||||
{{item.created_at | timeString('YYYY/MM/DD HH:mm')}}
|
{{item.created_at | timeString('YYYY/MM/DD HH:mm')}}
|
||||||
@@ -43,6 +46,7 @@
|
|||||||
<confirm-modal ref="confirmModal"></confirm-modal>
|
<confirm-modal ref="confirmModal"></confirm-modal>
|
||||||
</asp:Content>
|
</asp:Content>
|
||||||
<asp:Content ID="Content4" ContentPlaceHolderID="offCanvasRight" Runat="Server">
|
<asp:Content ID="Content4" ContentPlaceHolderID="offCanvasRight" Runat="Server">
|
||||||
|
<div>test</div>
|
||||||
</asp:Content>
|
</asp:Content>
|
||||||
<asp:Content ID="Content5" ContentPlaceHolderID="footer_script" Runat="Server">
|
<asp:Content ID="Content5" ContentPlaceHolderID="footer_script" Runat="Server">
|
||||||
<script>
|
<script>
|
||||||
|
|||||||
@@ -1,143 +0,0 @@
|
|||||||
<%@ Page Title="" Language="C#" MasterPageFile="~/admin/Templates/TBS5ADM001/MasterPage.master" AutoEventWireup="true" CodeFile="statistics.aspx.cs" Inherits="admin_guadan_statistics" %>
|
|
||||||
|
|
||||||
<asp:Content ID="Content1" ContentPlaceHolderID="page_header" Runat="Server">
|
|
||||||
</asp:Content>
|
|
||||||
<asp:Content ID="Content2" ContentPlaceHolderID="page_nav" Runat="Server">
|
|
||||||
</asp:Content>
|
|
||||||
<asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
|
|
||||||
<div class="container my-4">
|
|
||||||
<!-- 客房统计 -->
|
|
||||||
<div class="row row-cols-2 row-cols-sm-3 row-cols-md-4 row-cols-lg-5 g-3">
|
|
||||||
<div class="col">
|
|
||||||
<div class="p-3 bg-light text-center rounded shadow" style="min-height: 180px;">
|
|
||||||
<div class="fs-2">🏠</div>
|
|
||||||
<div class="text-muted small mt-1">总房间数量</div>
|
|
||||||
<div class="fw-bold fs-5 mt-1">{{ roomStatistics.roomCount }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col">
|
|
||||||
<div class="p-3 bg-light text-center rounded shadow" style="min-height: 180px;">
|
|
||||||
<div class="fs-2">🚪</div>
|
|
||||||
<div class="text-muted small mt-1">空房间数量</div>
|
|
||||||
<div class="fw-bold fs-5 mt-1">{{ roomStatistics.emptyRoomCount }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col">
|
|
||||||
<div class="p-3 bg-light text-center rounded shadow" style="min-height: 180px;">
|
|
||||||
<div class="fs-2">🛏️</div>
|
|
||||||
<div class="text-muted small mt-1">总床位数量</div>
|
|
||||||
<div class="fw-bold fs-5 mt-1">
|
|
||||||
{{ roomStatistics.bedCount }} (男:{{ roomStatistics.maleBedCount }},女:{{ roomStatistics.femaleBedCount }})
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col">
|
|
||||||
<div class="p-3 bg-light text-center rounded shadow" style="min-height: 180px;">
|
|
||||||
<div class="fs-2">🛌</div>
|
|
||||||
<div class="text-muted small mt-1">可用空床</div>
|
|
||||||
<div class="fw-bold fs-5 mt-1">
|
|
||||||
{{ roomStatistics.emptyBedCount }} (男:{{ roomStatistics.emptyMaleBedCount }},女:{{ roomStatistics.emptyFemaleBedCount }})
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 挂单统计 -->
|
|
||||||
<div class="row row-cols-2 row-cols-sm-3 row-cols-md-4 row-cols-lg-5 g-3 mt-1">
|
|
||||||
<div class="col">
|
|
||||||
<div class="p-3 bg-light text-center rounded shadow" style="min-height: 180px;">
|
|
||||||
<div class="fs-2">📝</div>
|
|
||||||
<div class="text-muted small mt-1">总挂单次数</div>
|
|
||||||
<div class="fw-bold fs-5 mt-1">{{ guadanStatistics.guadanTotalCount }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col">
|
|
||||||
<div class="p-3 bg-light text-center rounded shadow" style="min-height: 180px;">
|
|
||||||
<div class="fs-2">📋</div>
|
|
||||||
<div class="text-muted small mt-1">当前挂单数量</div>
|
|
||||||
<div class="fw-bold fs-5 mt-1">{{ guadanStatistics.guadanCurrentCount }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col">
|
|
||||||
<div class="p-3 bg-light text-center rounded shadow" style="min-height: 180px;">
|
|
||||||
<div class="fs-2">👥</div>
|
|
||||||
<div class="text-muted small mt-1">总挂单人数</div>
|
|
||||||
<div class="fw-bold fs-5 mt-1">
|
|
||||||
{{ guadanStatistics.guadanPeopleTotal }} (男:{{ guadanStatistics.guadanPeopleMale }},女:{{ guadanStatistics.guadanPeopleFemale }})
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col">
|
|
||||||
<div class="p-3 bg-light text-center rounded shadow" style="min-height: 180px;">
|
|
||||||
<div class="fs-2">👨👩</div>
|
|
||||||
<div class="text-muted small mt-1">当前挂单人数</div>
|
|
||||||
<div class="fw-bold fs-5 mt-1">
|
|
||||||
{{ guadanStatistics.guadanPeopleCurrent }} (男:{{ guadanStatistics.guadanPeopleCurrentMale }},女:{{ guadanStatistics.guadanPeopleCurrentFemale }})
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</asp:Content>
|
|
||||||
<asp:Content ID="Content4" ContentPlaceHolderID="offCanvasRight" Runat="Server">
|
|
||||||
</asp:Content>
|
|
||||||
<asp:Content ID="Content5" ContentPlaceHolderID="footer_script" Runat="Server">
|
|
||||||
<script>
|
|
||||||
new Vue({
|
|
||||||
el: '#app',
|
|
||||||
vuetify: new Vuetify(vuetify_options),
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
roomStatistics: {
|
|
||||||
roomCount: 0,
|
|
||||||
emptyRoomCount: 0,
|
|
||||||
bedCount: 0,
|
|
||||||
maleBedCount: 0,
|
|
||||||
femaleBedCount: 0,
|
|
||||||
emptyBedCount: 0,
|
|
||||||
emptyMaleBedCount: 0,
|
|
||||||
emptyFemaleBedCount: 0
|
|
||||||
},
|
|
||||||
guadanStatistics: {
|
|
||||||
guadanTotalCount: 0,
|
|
||||||
guadanCurrentCount: 0,
|
|
||||||
guadanPeopleTotal: 0,
|
|
||||||
guadanPeopleMale: 0,
|
|
||||||
guadanPeopleFemale: 0,
|
|
||||||
guadanPeopleCurrent: 0,
|
|
||||||
guadanPeopleCurrentMale: 0,
|
|
||||||
guadanPeopleCurrentFemale: 0
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
GetGuadanStatistics() {
|
|
||||||
axios.get('/api/guadanStatistics/GetGuadanStatistics')
|
|
||||||
.then((res) => {
|
|
||||||
this.roomStatistics = res.data.roomStatistics;
|
|
||||||
this.guadanStatistics = res.data.guadanStatistics;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.GetGuadanStatistics();
|
|
||||||
|
|
||||||
// 每两分钟更新一次 (2 * 60 * 1000 毫秒)
|
|
||||||
setInterval(() => {
|
|
||||||
this.GetGuadanStatistics();
|
|
||||||
}, 1 * 60 * 1000);
|
|
||||||
},
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
</asp:Content>
|
|
||||||
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Web;
|
|
||||||
using System.Web.UI;
|
|
||||||
using System.Web.UI.WebControls;
|
|
||||||
|
|
||||||
public partial class admin_guadan_statistics : MyWeb.config
|
|
||||||
{
|
|
||||||
protected void Page_Load(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -9,41 +9,56 @@
|
|||||||
<div class="section mb-6">
|
<div class="section mb-6">
|
||||||
<v-card outlined class="pa-1">
|
<v-card outlined class="pa-1">
|
||||||
<v-card-title class="headline grey--text text--darken-2">
|
<v-card-title class="headline grey--text text--darken-2">
|
||||||
今日使用情况
|
掛單統計
|
||||||
</v-card-title>
|
</v-card-title>
|
||||||
<v-divider class="mb-4"></v-divider>
|
<v-divider class="mb-4"></v-divider>
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<div class="d-flex flex-wrap justify-space-around">
|
<div class="row row-cols-2 row-cols-sm-3 row-cols-md-4 row-cols-lg-5 g-3 mt-1">
|
||||||
<v-card class="ma-2 pa-3 text-center" color="#e3f2fd" outlined>
|
<div class="col">
|
||||||
<div class="subtitle-1 font-weight-bold">总预订人数</div>
|
<div class="p-3 bg-light text-center rounded shadow" style="min-height: 180px;">
|
||||||
<div class="headline">{{totalbookers }}</div>
|
<div class="fs-2">📝</div>
|
||||||
</v-card>
|
<div class="text-muted small mt-1">总挂单次数</div>
|
||||||
<v-card class="ma-2 pa-3 text-center" color="#e3f2fd" outlined>
|
<div class="fw-bold fs-5 mt-1">{{ guadanStatistics.guadanTotalCount }}</div>
|
||||||
<div class="subtitle-1 font-weight-bold">今日预订人数</div>
|
</div>
|
||||||
<div class="headline">{{today.todaytotalbookers }}</div>
|
</div>
|
||||||
</v-card>
|
|
||||||
<v-card class="ma-2 pa-3 text-center" color="#e3f2fd" outlined>
|
<div class="col">
|
||||||
<div class="subtitle-1 font-weight-bold">今日已入住人数</div>
|
<div class="p-3 bg-light text-center rounded shadow" style="min-height: 180px;">
|
||||||
<div class="headline">{{today.checkin }}</div>
|
<div class="fs-2">📋</div>
|
||||||
</v-card>
|
<div class="text-muted small mt-1">当前挂单数量</div>
|
||||||
<v-card class="ma-2 pa-3 text-center" color="#e3f2fd" outlined>
|
<div class="fw-bold fs-5 mt-1">{{ guadanStatistics.guadanCurrentCount }}</div>
|
||||||
<div class="subtitle-1 font-weight-bold">今日待入住人数</div>
|
</div>
|
||||||
<div class="headline">{{today.todaytotalbookers - today.checkin }}</div>
|
</div>
|
||||||
</v-card>
|
|
||||||
<v-card class="ma-2 pa-3 text-center" color="#fce4ec" outlined>
|
<div class="col">
|
||||||
<div class="subtitle-1 font-weight-bold">空床數</div>
|
<div class="p-3 bg-light text-center rounded shadow" style="min-height: 180px;">
|
||||||
<div class="headline">{{ bedcount - today.todaytotalbookers}}</div>
|
<div class="fs-2">👥</div>
|
||||||
</v-card>
|
<div class="text-muted small mt-1">总挂单人数</div>
|
||||||
|
<div class="fw-bold fs-5 mt-1">
|
||||||
|
{{ guadanStatistics.guadanPeopleTotal }} (男:{{ guadanStatistics.guadanPeopleMale }},女:{{ guadanStatistics.guadanPeopleFemale }})
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col">
|
||||||
|
<div class="p-3 bg-light text-center rounded shadow" style="min-height: 180px;">
|
||||||
|
<div class="fs-2">👨👩</div>
|
||||||
|
<div class="text-muted small mt-1">已預約掛單人數</div>
|
||||||
|
<div class="fw-bold fs-5 mt-1">
|
||||||
|
{{ guadanStatistics.guadanPeopleCurrent }} (男:{{ guadanStatistics.guadanPeopleCurrentMale }},女:{{ guadanStatistics.guadanPeopleCurrentFemale }})
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
</v-card>
|
</v-card>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 近期床位使用統計 -->
|
<!-- 近期床位使用統計 -->
|
||||||
<div class="section container">
|
<div class="section container">
|
||||||
|
|
||||||
<!-- 日期筛选区 -->
|
<!-- 日期筛选区 -->
|
||||||
<div class="d-flex align-center flex-wrap" style="gap: 12px;">
|
<div class="d-flex align-center flex-wrap" style="gap: 5px;">
|
||||||
<!-- 开始日期 -->
|
<!-- 开始日期 -->
|
||||||
<v-menu
|
<v-menu
|
||||||
ref="menu1"
|
ref="menu1"
|
||||||
@@ -100,6 +115,12 @@
|
|||||||
>
|
>
|
||||||
查詢
|
查詢
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
<v-btn
|
||||||
|
color="primary"
|
||||||
|
style="align-self: stretch;"
|
||||||
|
@click="exportStatisticsToExcel">
|
||||||
|
導出下面表格數據到Excel
|
||||||
|
</v-btn>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -119,6 +140,16 @@
|
|||||||
<template #item.date="{ item }">
|
<template #item.date="{ item }">
|
||||||
<span>{{ item.date | timeString('YYYY-MM-DD') }}</span>
|
<span>{{ item.date | timeString('YYYY-MM-DD') }}</span>
|
||||||
</template>
|
</template>
|
||||||
|
<template #item.todaytotalbookers="{item}">
|
||||||
|
<span>
|
||||||
|
{{item?.todaytotalbookers + '(男' + '女)'}}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template #item.checkin="{item}">
|
||||||
|
<span>
|
||||||
|
{{item?.checkin + '(男' + '女)'}}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
<template #item.bedusagerate="{ item }">
|
<template #item.bedusagerate="{ item }">
|
||||||
{{ ((item.todaytotalbookers / bedcount) * 100).toFixed(2) + '%' }}
|
{{ ((item.todaytotalbookers / bedcount) * 100).toFixed(2) + '%' }}
|
||||||
</template>
|
</template>
|
||||||
@@ -154,14 +185,22 @@
|
|||||||
{ text: '可用床位', value: 'availableBeds' },
|
{ text: '可用床位', value: 'availableBeds' },
|
||||||
{ text: '床位利用率', value: 'bedusagerate' }
|
{ text: '床位利用率', value: 'bedusagerate' }
|
||||||
],
|
],
|
||||||
today: {},
|
|
||||||
totalbookers: 0,
|
|
||||||
startDate: null,
|
startDate: null,
|
||||||
endDate: null,
|
endDate: null,
|
||||||
menu1: false,
|
menu1: false,
|
||||||
menu2: false,
|
menu2: false,
|
||||||
bedcount: 0,
|
bedcount: 0,
|
||||||
roomcount: 0,
|
roomcount: 0,
|
||||||
|
guadanStatistics: {
|
||||||
|
guadanTotalCount: 0,
|
||||||
|
guadanCurrentCount: 0,
|
||||||
|
guadanPeopleTotal: 0,
|
||||||
|
guadanPeopleMale: 0,
|
||||||
|
guadanPeopleFemale: 0,
|
||||||
|
guadanPeopleCurrent: 0,
|
||||||
|
guadanPeopleCurrentMale: 0,
|
||||||
|
guadanPeopleCurrentFemale: 0
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -176,18 +215,52 @@
|
|||||||
this.items = res.data.statistics;
|
this.items = res.data.statistics;
|
||||||
this.roomcount = res.data.roomcount;
|
this.roomcount = res.data.roomcount;
|
||||||
this.bedcount = res.data.bedcount;
|
this.bedcount = res.data.bedcount;
|
||||||
this.today = res.data.today;
|
|
||||||
this.totalbookers = res.data.totalbookers;
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
exportStatisticsToExcel() {
|
||||||
|
if (!this.items || !this.items.length) {
|
||||||
|
console.warn("没有数据可导出");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 取 items 数组并格式化
|
||||||
|
const sheetData = this.items.map(item => ({
|
||||||
|
日期: item.date.split('T')[0], // 格式化成 YYYY-MM-DD
|
||||||
|
预订人数: item.todaytotalbookers,
|
||||||
|
入住人数: item.checkin
|
||||||
|
}));
|
||||||
|
|
||||||
|
// 2. 转换成 XLSX Sheet
|
||||||
|
const ws = XLSX.utils.json_to_sheet(sheetData);
|
||||||
|
|
||||||
|
// 3. 创建 Workbook 并添加 Sheet
|
||||||
|
const wb = XLSX.utils.book_new();
|
||||||
|
XLSX.utils.book_append_sheet(wb, ws, "统计数据");
|
||||||
|
|
||||||
|
// 4. 写入 Excel 并下载
|
||||||
|
const wbout = XLSX.write(wb, { bookType: "xlsx", type: "array" });
|
||||||
|
saveAs(new Blob([wbout], { type: "application/octet-stream" }), "statistics.xlsx");
|
||||||
|
},
|
||||||
|
GetGuadanStatistics() {
|
||||||
|
axios.get('/api/guadanStatistics/GetGuadanStatistics')
|
||||||
|
.then((res) => {
|
||||||
|
this.guadanStatistics = res.data.guadanStatistics;
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.getList();
|
this.getList();
|
||||||
|
this.GetGuadanStatistics();
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
<!-- CDN 方式引入 XLSX 和 FileSaver -->
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"></script>
|
||||||
|
|
||||||
</asp:Content>
|
</asp:Content>
|
||||||
|
|
||||||
|
|||||||
@@ -171,43 +171,49 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<v-dialog v-model="bedSchedule.dialogVisible" max-width="900">
|
<v-dialog v-model="bedSchedule.dialogVisible" max-width="900px">
|
||||||
<v-card>
|
<v-card
|
||||||
<v-card-title>
|
style="min-height:50vh; max-height:80vh; display:flex; flex-direction:column;"
|
||||||
<span class="text-h6">床位排程明細 - {{ bedSchedule.selectedBed?.name }}</span>
|
>
|
||||||
<v-spacer></v-spacer>
|
<v-card-title>
|
||||||
<v-btn icon @click="closeBedSchedule">
|
<span class="text-h6">床位排程明細 - {{ bedSchedule.selectedBed?.name }}</span>
|
||||||
<v-icon>mdi-close</v-icon>
|
<v-spacer></v-spacer>
|
||||||
</v-btn>
|
<v-btn icon @click="closeBedSchedule"><v-icon>mdi-close</v-icon></v-btn>
|
||||||
</v-card-title>
|
</v-card-title>
|
||||||
|
|
||||||
<v-card-text>
|
<!-- 关键改动:flex:1 1 auto; min-height:0; overflow-y:auto -->
|
||||||
<v-data-table
|
<v-card-text style="flex:1 1 auto; min-height:0; overflow-y:auto;">
|
||||||
:headers="bedSchedule.scheduleHeaders"
|
<div style="min-height:0;">
|
||||||
:items="bedSchedule.selectedBed?.schedules || []"
|
<v-data-table
|
||||||
class="elevation-1"
|
:headers="bedSchedule.scheduleHeaders"
|
||||||
dense
|
:items="bedSchedule.selectedBed?.schedules || []"
|
||||||
hide-default-footer
|
:items-per-page="9999"
|
||||||
:items-per-page="5"
|
class="elevation-1"
|
||||||
>
|
dense
|
||||||
<template #item.scheduleDate="{item}">
|
hide-default-footer
|
||||||
{{item.scheduledate|timeString('YYYY-MM-DD')}}
|
>
|
||||||
</template>
|
<template #item.scheduleDate="{item}">
|
||||||
<template #item.actions =" {item}">
|
{{ item.scheduledate | timeString('YYYY-MM-DD') }}
|
||||||
<a :href="'/admin/guadan/create.aspx?orderId='+item.guaDanOrderNo" class="btn btn-primary">查看掛單</a>
|
</template>
|
||||||
</template>
|
<template #item.actions="{item}">
|
||||||
</v-data-table>
|
<a :href="'/admin/guadan/create.aspx?orderId='+item.guaDanOrderNo" class="btn btn-primary">
|
||||||
</v-card-text>
|
查看掛單
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
</v-data-table>
|
||||||
|
</div>
|
||||||
|
</v-card-text>
|
||||||
|
|
||||||
<v-card-actions>
|
|
||||||
<v-spacer></v-spacer>
|
|
||||||
<v-btn text color="primary" @click="closeBedSchedule">關閉</v-btn>
|
|
||||||
</v-card-actions>
|
|
||||||
</v-card>
|
|
||||||
</v-dialog>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<v-card-actions>
|
||||||
|
<v-spacer></v-spacer>
|
||||||
|
<v-btn text color="primary" @click="closeBedSchedule">關閉</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-card>
|
||||||
|
</v-dialog>
|
||||||
|
|
||||||
|
</div>
|
||||||
</asp:Content>
|
</asp:Content>
|
||||||
<asp:Content ID="Content4" ContentPlaceHolderID="offCanvasRight" Runat="Server">
|
<asp:Content ID="Content4" ContentPlaceHolderID="offCanvasRight" Runat="Server">
|
||||||
</asp:Content>
|
</asp:Content>
|
||||||
|
|||||||
@@ -582,6 +582,7 @@
|
|||||||
this.selectedType = 'region';
|
this.selectedType = 'region';
|
||||||
this.selectedRegionId = region.uuid;
|
this.selectedRegionId = region.uuid;
|
||||||
this.currentSelectRegion = region;
|
this.currentSelectRegion = region;
|
||||||
|
console.log(this.currentSelectRegion)
|
||||||
this.currentSelectRoom = null;
|
this.currentSelectRoom = null;
|
||||||
this.resetRoomForm();
|
this.resetRoomForm();
|
||||||
this.form = {
|
this.form = {
|
||||||
@@ -664,7 +665,7 @@
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
confirmDeleteRegion() {
|
confirmDeleteRegion() {
|
||||||
axios.post('/api/region/delete', { statuscode: this.form.statuscode })
|
axios.post('/api/region/delete', { Uuid: this.form.uuid })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.showDeleteModal = false;
|
this.showDeleteModal = false;
|
||||||
this.$refs.messageModal.open({
|
this.$refs.messageModal.open({
|
||||||
|
|||||||
Reference in New Issue
Block a user