/*********************************************************************** * Project: CoreCms * ProjectName: 核心内容管理系统 * Web: https://www.corecms.net * Author: 大灰灰 * Email: jianweie@163.com * CreateTime: 2025/9/2 17:54:05 * Description: 暂无 ***********************************************************************/ using System; using System.ComponentModel; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; using CoreCms.Net.Configuration; using CoreCms.Net.Model.Entities; using CoreCms.Net.Model.Entities.Expression; using CoreCms.Net.Model.FromBody; using CoreCms.Net.Model.ViewModels.UI; using CoreCms.Net.Filter; using CoreCms.Net.Loging; using CoreCms.Net.IServices; using CoreCms.Net.Utility.Helper; using CoreCms.Net.Utility.Extensions; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; using NPOI.HSSF.UserModel; using SqlSugar; using CoreCms.Net.Web.Admin.Infrastructure; using CoreCms.Net.Services; using System.Collections.Generic; using AutoMapper; using CoreCms.Net.Model.ViewModels.SQ; using CoreCms.Net.IRepository.UnitOfWork; namespace CoreCms.Net.Web.Admin.Controllers { /// /// 预约表 /// [Description("预约表")] [Route("api/[controller]/[action]")] [ApiController] [RequiredErrorForAdmin] [Authorize] public class SQReservationsController : 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 ISQEarningsServices _sQEarningsServices; private readonly ISQMessageServices _sQMessageServices; private readonly IUnitOfWork _unitOfWork; /// /// 构造函数 /// public SQReservationsController(IWebHostEnvironment webHostEnvironment , ISQReservationsServices SQReservationsServices , ISQRoomsServices SQRoomsServices , ISysDictionaryServices sysDictionaryServices , ISysDictionaryDataServices sysDictionaryDataServices , ISQReservationParticipantsServices sQReservationParticipantsServices , IMapper mapper , ICoreCmsUserServices userServices , ISQEarningsServices sQEarningsServices , ISQMessageServices sQMessageServices , IUnitOfWork unitOfWork ) { _webHostEnvironment = webHostEnvironment; _SQReservationsServices = SQReservationsServices; _SQRoomsServices = SQRoomsServices; _sysDictionaryServices = sysDictionaryServices; _sysDictionaryDataServices = sysDictionaryDataServices; _SQReservationParticipantsServices = sQReservationParticipantsServices; _mapper = mapper; _userServices = userServices; _sQEarningsServices = sQEarningsServices; _sQMessageServices = sQMessageServices; _unitOfWork = unitOfWork; } #region 获取列表============================================================ // POST: Api/SQReservations/GetPageList /// /// 获取列表 /// /// [HttpPost] [Description("获取列表")] public async Task GetPageList() { var jm = new AdminUiCallBack(); var pageCurrent = Request.Form["page"].FirstOrDefault().ObjectToInt(1); var pageSize = Request.Form["limit"].FirstOrDefault().ObjectToInt(30); var where = PredicateBuilder.True(); //获取排序字段 var orderField = Request.Form["orderField"].FirstOrDefault(); Expression> orderEx = orderField switch { "id" => p => p.id, "title" => p => p.title, "room_id" => p => p.room_id, "room_name" => p => p.room_name, "start_time" => p => p.start_time, "end_time" => p => p.end_time, "duration_minutes" => p => p.duration_minutes, "player_count" => p => p.player_count, "game_type" => p => p.game_type, "game_rule" => p => p.game_rule, "extra_info" => p => p.extra_info, "is_smoking" => p => p.is_smoking, "gender_limit" => p => p.gender_limit, "credit_limit" => p => p.credit_limit, "min_age" => p => p.min_age, "max_age" => p => p.max_age, "deposit_fee" => p => p.deposit_fee, "status" => p => p.status, "created_at" => p => p.created_at, "updated_at" => p => p.updated_at, _ => p => p.id }; //设置排序方式 var orderDirection = Request.Form["orderDirection"].FirstOrDefault(); var orderBy = orderDirection switch { "asc" => OrderByType.Asc, "desc" => OrderByType.Desc, _ => OrderByType.Desc }; //查询筛选 //预约ID int var id = Request.Form["id"].FirstOrDefault().ObjectToInt(0); if (id > 0) { where = where.And(p => p.id == id); } //组局名称 nvarchar var title = Request.Form["title"].FirstOrDefault(); if (!string.IsNullOrEmpty(title)) { where = where.And(p => p.title.Contains(title)); } //房间ID int var room_id = Request.Form["room_id"].FirstOrDefault().ObjectToInt(0); if (room_id > 0) { where = where.And(p => p.room_id == room_id); } //房间名称(冗余存储,比如 304号-大包,30元/小时) nvarchar var room_name = Request.Form["room_name"].FirstOrDefault(); if (!string.IsNullOrEmpty(room_name)) { where = where.And(p => p.room_name.Contains(room_name)); } //开始时间 datetime var start_time = Request.Form["start_time"].FirstOrDefault(); if (!string.IsNullOrEmpty(start_time)) { if (start_time.Contains("到")) { var dts = start_time.Split("到"); var dtStart = dts[0].Trim().ObjectToDate(); where = where.And(p => p.start_time > dtStart); var dtEnd = dts[1].Trim().ObjectToDate(); where = where.And(p => p.start_time < dtEnd); } else { var dt = start_time.ObjectToDate(); where = where.And(p => p.start_time > dt); } } //结束时间 datetime var end_time = Request.Form["end_time"].FirstOrDefault(); if (!string.IsNullOrEmpty(end_time)) { if (end_time.Contains("到")) { var dts = end_time.Split("到"); var dtStart = dts[0].Trim().ObjectToDate(); where = where.And(p => p.end_time > dtStart); var dtEnd = dts[1].Trim().ObjectToDate(); where = where.And(p => p.end_time < dtEnd); } else { var dt = end_time.ObjectToDate(); where = where.And(p => p.end_time > dt); } } //时长(分钟) int var duration_minutes = Request.Form["duration_minutes"].FirstOrDefault().ObjectToInt(0); if (duration_minutes > 0) { where = where.And(p => p.duration_minutes == duration_minutes); } //人数 int var player_count = Request.Form["player_count"].FirstOrDefault().ObjectToInt(0); if (player_count > 0) { where = where.And(p => p.player_count == player_count); } //玩法类型(如:补克) nvarchar var game_type = Request.Form["game_type"].FirstOrDefault(); if (!string.IsNullOrEmpty(game_type)) { where = where.And(p => p.game_type.Contains(game_type)); } //具体规则(如:斗地主) nvarchar var game_rule = Request.Form["game_rule"].FirstOrDefault(); if (!string.IsNullOrEmpty(game_rule)) { where = where.And(p => p.game_rule.Contains(game_rule)); } //其他补充 nvarchar var extra_info = Request.Form["extra_info"].FirstOrDefault(); if (!string.IsNullOrEmpty(extra_info)) { where = where.And(p => p.extra_info.Contains(extra_info)); } //是否禁烟:0=不限制,1=禁烟,2=不禁烟 int var is_smoking = Request.Form["is_smoking"].FirstOrDefault().ObjectToInt(0); if (is_smoking > 0) { where = where.And(p => p.is_smoking == is_smoking); } //性别限制:0=不限,1=男,2=女 int var gender_limit = Request.Form["gender_limit"].FirstOrDefault().ObjectToInt(0); if (gender_limit > 0) { where = where.And(p => p.gender_limit == gender_limit); } //最低信誉分 decimal var credit_limit = Request.Form["credit_limit"].FirstOrDefault().ObjectToDecimal(0); if (credit_limit > 0) { where = where.And(p => p.credit_limit == credit_limit); } //最小年龄限制 int var min_age = Request.Form["min_age"].FirstOrDefault().ObjectToInt(0); if (min_age > 0) { where = where.And(p => p.min_age == min_age); } //最大年龄限制,0=不限 int var max_age = Request.Form["max_age"].FirstOrDefault().ObjectToInt(0); if (max_age > 0) { where = where.And(p => p.max_age == max_age); } //鸽子费(保证金) decimal var deposit_fee = Request.Form["deposit_fee"].FirstOrDefault().ObjectToDecimal(0); if (deposit_fee > 0) { where = where.And(p => p.deposit_fee == deposit_fee); } //状态:0=待开始,1=进行中,2=已结束,3=取消 int var status = Request.Form["status"].FirstOrDefault().ObjectToInt(0); if (status > 0) { where = where.And(p => p.status == status); } //创建时间 datetime var created_at = Request.Form["created_at"].FirstOrDefault(); if (!string.IsNullOrEmpty(created_at)) { if (created_at.Contains("到")) { var dts = created_at.Split("到"); var dtStart = dts[0].Trim().ObjectToDate(); where = where.And(p => p.created_at > dtStart); var dtEnd = dts[1].Trim().ObjectToDate(); where = where.And(p => p.created_at < dtEnd); } else { var dt = created_at.ObjectToDate(); where = where.And(p => p.created_at > dt); } } //更新时间 datetime var updated_at = Request.Form["updated_at"].FirstOrDefault(); if (!string.IsNullOrEmpty(updated_at)) { if (updated_at.Contains("到")) { var dts = updated_at.Split("到"); var dtStart = dts[0].Trim().ObjectToDate(); where = where.And(p => p.updated_at > dtStart); var dtEnd = dts[1].Trim().ObjectToDate(); where = where.And(p => p.updated_at < dtEnd); } else { var dt = updated_at.ObjectToDate(); where = where.And(p => p.updated_at > dt); } } //获取数据 var list = await _SQReservationsServices.QueryPageAsync(where, orderEx, orderBy, pageCurrent, pageSize, true); var pageList = _mapper.Map>(list); var rIds = list.Select(it => it.id).ToList(); if (rIds != null && rIds.Count > 0) { var participants = await _SQReservationParticipantsServices.QueryListByClauseAsync(it => rIds.Contains(it.reservation_id), "", true); List userList = new List(); if (participants != null && participants.Count > 0) { var userIds = participants.Select(it => it.user_id).ToList(); userList = await _userServices.QueryListByClauseAsync(it => userIds.Contains(it.id), "", true); } foreach (var item in pageList) { var temp = participants.Where(it => it.reservation_id == item.id).OrderBy(it => it.role).ThenBy(it => it.status).ToList(); var dto = _mapper.Map>(temp); if (userList != null && userList.Count > 0) { foreach (var p in dto) { var u = userList.FirstOrDefault(it => it.id == p.user_id); if (u != null) { p.UserName = u.nickName; p.AvatarImage = u.avatarImage; } } } item.Participants = dto; } } //返回数据 jm.data = pageList; jm.code = 0; jm.count = list.TotalCount; jm.msg = "数据调用成功!"; return jm; } #endregion #region 首页数据============================================================ // POST: Api/SQReservations/GetIndex /// /// 首页数据 /// /// [HttpPost] [Description("首页数据")] public AdminUiCallBack GetIndex() { var list = _SQRoomsServices.QueryListByClause(it => it.status); var data = list.Select(it => new { it.name, it.id }).ToList(); var dic = _sysDictionaryServices.QueryListByClause(it => !it.deleted, it => it.sortNumber , OrderByType.Asc); var dicData = _sysDictionaryDataServices.QueryListByClause(it => !it.deleted); var options = new List(); foreach (var item in dic) { var d = dicData.Where(it => it.dictId == item.id).Select(it => new { name = it.dictDataName, it.id }).ToList(); options.Add(new { name = item.dictName, item.id, children = d }); } //返回数据 var jm = new AdminUiCallBack { code = 0, msg = "" }; jm.data = new { roomOptions = data, dicOptions = options }; return jm; } #endregion #region 创建数据============================================================ // POST: Api/SQReservations/GetCreate /// /// 创建数据 /// /// [HttpPost] [Description("创建数据")] public AdminUiCallBack GetCreate() { //返回数据 var jm = new AdminUiCallBack { code = 0 }; return jm; } #endregion #region 创建提交============================================================ // POST: Api/SQReservations/DoCreate /// /// 创建提交 /// /// /// [HttpPost] [Description("创建提交")] public async Task DoCreate([FromBody] SQReservations entity) { entity.created_at = DateTime.Now; entity.updated_at = DateTime.Now; entity.remarks = "后台管理手动创建!"; var jm = await _SQReservationsServices.InsertAsync(entity); return jm; } #endregion #region 编辑数据============================================================ // POST: Api/SQReservations/GetEdit /// /// 编辑数据 /// /// /// [HttpPost] [Description("编辑数据")] public async Task GetEdit([FromBody] FMIntId entity) { var jm = new AdminUiCallBack(); var model = await _SQReservationsServices.QueryByIdAsync(entity.id, false); if (model == null) { jm.msg = "不存在此信息"; return jm; } jm.code = 0; jm.data = model; return jm; } #endregion #region 编辑提交============================================================ // POST: Api/SQReservations/Edit /// /// 编辑提交 /// /// /// [HttpPost] [Description("编辑提交")] public async Task DoEdit([FromBody] SQReservations entity) { var e = _SQReservationsServices.QueryById(entity.id); if (e == null) { throw new ArgumentNullException("未找到数据"); } entity.created_at = e.created_at; entity.remarks = e.remarks; entity.updated_at = DateTime.Now; var jm = await _SQReservationsServices.UpdateAsync(entity); return jm; } #endregion #region 删除数据============================================================ // POST: Api/SQReservations/DoDelete/10 /// /// 单选删除 /// /// /// [HttpPost] [Description("单选删除")] public async Task DoDelete([FromBody] FMIntId entity) { var jm = new AdminUiCallBack(); var model = await _SQReservationsServices.ExistsAsync(p => p.id == entity.id, true); if (!model) { jm.msg = GlobalConstVars.DataisNo; return jm; } jm = await _SQReservationsServices.DeleteByIdAsync(entity.id); return jm; } #endregion #region 批量删除============================================================ // POST: Api/SQReservations/DoBatchDelete/10,11,20 /// /// 批量删除 /// /// /// [HttpPost] [Description("批量删除")] public async Task DoBatchDelete([FromBody] FMArrayIntIds entity) { var jm = await _SQReservationsServices.DeleteByIdsAsync(entity.id); return jm; } #endregion #region 预览数据============================================================ // POST: Api/SQReservations/GetDetails/10 /// /// 预览数据 /// /// /// [HttpPost] [Description("预览数据")] public async Task GetDetails([FromBody] FMIntId entity) { var jm = new AdminUiCallBack(); var model = await _SQReservationsServices.QueryByIdAsync(entity.id, false); if (model == null) { jm.msg = "不存在此信息"; return jm; } jm.code = 0; jm.data = model; return jm; } #endregion #region 选择导出============================================================ // POST: Api/SQReservations/SelectExportExcel/10 /// /// 选择导出 /// /// /// [HttpPost] [Description("选择导出")] public async Task SelectExportExcel([FromBody] FMArrayIntIds entity) { var jm = new AdminUiCallBack(); //创建Excel文件的对象 var book = new HSSFWorkbook(); //添加一个sheet var mySheet = book.CreateSheet("Sheet1"); //获取list数据 var listModel = await _SQReservationsServices.QueryListByClauseAsync(p => entity.id.Contains(p.id), p => p.id, OrderByType.Asc, true); //给sheet1添加第一行的头部标题 var headerRow = mySheet.CreateRow(0); var headerStyle = ExcelHelper.GetHeaderStyle(book); var cell0 = headerRow.CreateCell(0); cell0.SetCellValue("预约ID"); cell0.CellStyle = headerStyle; mySheet.SetColumnWidth(0, 10 * 256); var cell1 = headerRow.CreateCell(1); cell1.SetCellValue("组局名称"); cell1.CellStyle = headerStyle; mySheet.SetColumnWidth(1, 10 * 256); var cell2 = headerRow.CreateCell(2); cell2.SetCellValue("房间ID"); cell2.CellStyle = headerStyle; mySheet.SetColumnWidth(2, 10 * 256); var cell3 = headerRow.CreateCell(3); cell3.SetCellValue("房间名称"); cell3.CellStyle = headerStyle; mySheet.SetColumnWidth(3, 10 * 256); var cell4 = headerRow.CreateCell(4); cell4.SetCellValue("开始时间"); cell4.CellStyle = headerStyle; mySheet.SetColumnWidth(4, 10 * 256); var cell5 = headerRow.CreateCell(5); cell5.SetCellValue("结束时间"); cell5.CellStyle = headerStyle; mySheet.SetColumnWidth(5, 10 * 256); var cell6 = headerRow.CreateCell(6); cell6.SetCellValue("时长(分钟)"); cell6.CellStyle = headerStyle; mySheet.SetColumnWidth(6, 10 * 256); var cell7 = headerRow.CreateCell(7); cell7.SetCellValue("人数"); cell7.CellStyle = headerStyle; mySheet.SetColumnWidth(7, 10 * 256); var cell8 = headerRow.CreateCell(8); cell8.SetCellValue("玩法类型"); cell8.CellStyle = headerStyle; mySheet.SetColumnWidth(8, 10 * 256); var cell9 = headerRow.CreateCell(9); cell9.SetCellValue("具体规则"); cell9.CellStyle = headerStyle; mySheet.SetColumnWidth(9, 10 * 256); var cell10 = headerRow.CreateCell(10); cell10.SetCellValue("其他补充"); cell10.CellStyle = headerStyle; mySheet.SetColumnWidth(10, 10 * 256); var cell11 = headerRow.CreateCell(11); cell11.SetCellValue("是否禁烟"); cell11.CellStyle = headerStyle; mySheet.SetColumnWidth(11, 10 * 256); var cell12 = headerRow.CreateCell(12); cell12.SetCellValue("性别限制"); cell12.CellStyle = headerStyle; mySheet.SetColumnWidth(12, 10 * 256); var cell13 = headerRow.CreateCell(13); cell13.SetCellValue("最低信誉分"); cell13.CellStyle = headerStyle; mySheet.SetColumnWidth(13, 10 * 256); var cell14 = headerRow.CreateCell(14); cell14.SetCellValue("最小年龄限制"); cell14.CellStyle = headerStyle; mySheet.SetColumnWidth(14, 10 * 256); var cell15 = headerRow.CreateCell(15); cell15.SetCellValue("最大年龄限制"); cell15.CellStyle = headerStyle; mySheet.SetColumnWidth(15, 10 * 256); var cell16 = headerRow.CreateCell(16); cell16.SetCellValue("鸽子费"); cell16.CellStyle = headerStyle; mySheet.SetColumnWidth(16, 10 * 256); var cell17 = headerRow.CreateCell(17); cell17.SetCellValue("状态"); cell17.CellStyle = headerStyle; mySheet.SetColumnWidth(17, 10 * 256); var cell18 = headerRow.CreateCell(18); cell18.SetCellValue("创建时间"); cell18.CellStyle = headerStyle; mySheet.SetColumnWidth(18, 10 * 256); var cell19 = headerRow.CreateCell(19); cell19.SetCellValue("更新时间"); cell19.CellStyle = headerStyle; mySheet.SetColumnWidth(19, 10 * 256); headerRow.Height = 30 * 20; var commonCellStyle = ExcelHelper.GetCommonStyle(book); //将数据逐步写入sheet1各个行 for (var i = 0; i < listModel.Count; i++) { var rowTemp = mySheet.CreateRow(i + 1); var rowTemp0 = rowTemp.CreateCell(0); rowTemp0.SetCellValue(listModel[i].id.ToString()); rowTemp0.CellStyle = commonCellStyle; var rowTemp1 = rowTemp.CreateCell(1); rowTemp1.SetCellValue(listModel[i].title.ToString()); rowTemp1.CellStyle = commonCellStyle; var rowTemp2 = rowTemp.CreateCell(2); rowTemp2.SetCellValue(listModel[i].room_id.ToString()); rowTemp2.CellStyle = commonCellStyle; var rowTemp3 = rowTemp.CreateCell(3); rowTemp3.SetCellValue(listModel[i].room_name.ToString()); rowTemp3.CellStyle = commonCellStyle; var rowTemp4 = rowTemp.CreateCell(4); rowTemp4.SetCellValue(listModel[i].start_time.ToString()); rowTemp4.CellStyle = commonCellStyle; var rowTemp5 = rowTemp.CreateCell(5); rowTemp5.SetCellValue(listModel[i].end_time.ToString()); rowTemp5.CellStyle = commonCellStyle; var rowTemp6 = rowTemp.CreateCell(6); rowTemp6.SetCellValue(listModel[i].duration_minutes.ToString()); rowTemp6.CellStyle = commonCellStyle; var rowTemp7 = rowTemp.CreateCell(7); rowTemp7.SetCellValue(listModel[i].player_count.ToString()); rowTemp7.CellStyle = commonCellStyle; var rowTemp8 = rowTemp.CreateCell(8); rowTemp8.SetCellValue(listModel[i].game_type.ToString()); rowTemp8.CellStyle = commonCellStyle; var rowTemp9 = rowTemp.CreateCell(9); rowTemp9.SetCellValue(listModel[i].game_rule.ToString()); rowTemp9.CellStyle = commonCellStyle; var rowTemp10 = rowTemp.CreateCell(10); rowTemp10.SetCellValue(listModel[i].extra_info.ToString()); rowTemp10.CellStyle = commonCellStyle; var rowTemp11 = rowTemp.CreateCell(11); rowTemp11.SetCellValue(listModel[i].is_smoking.ToString()); rowTemp11.CellStyle = commonCellStyle; var rowTemp12 = rowTemp.CreateCell(12); rowTemp12.SetCellValue(listModel[i].gender_limit.ToString()); rowTemp12.CellStyle = commonCellStyle; var rowTemp13 = rowTemp.CreateCell(13); rowTemp13.SetCellValue(listModel[i].credit_limit.ToString()); rowTemp13.CellStyle = commonCellStyle; var rowTemp14 = rowTemp.CreateCell(14); rowTemp14.SetCellValue(listModel[i].min_age.ToString()); rowTemp14.CellStyle = commonCellStyle; var rowTemp15 = rowTemp.CreateCell(15); rowTemp15.SetCellValue(listModel[i].max_age.ToString()); rowTemp15.CellStyle = commonCellStyle; var rowTemp16 = rowTemp.CreateCell(16); rowTemp16.SetCellValue(listModel[i].deposit_fee.ToString()); rowTemp16.CellStyle = commonCellStyle; var rowTemp17 = rowTemp.CreateCell(17); rowTemp17.SetCellValue(listModel[i].status.ToString()); rowTemp17.CellStyle = commonCellStyle; var rowTemp18 = rowTemp.CreateCell(18); rowTemp18.SetCellValue(listModel[i].created_at.ToString()); rowTemp18.CellStyle = commonCellStyle; var rowTemp19 = rowTemp.CreateCell(19); rowTemp19.SetCellValue(listModel[i].updated_at.ToString()); rowTemp19.CellStyle = commonCellStyle; } // 导出excel string webRootPath = _webHostEnvironment.WebRootPath; string tpath = "/files/" + DateTime.Now.ToString("yyyy-MM-dd") + "/"; string fileName = DateTime.Now.ToString("yyyyMMddHHmmssfff") + "-SQReservations导出(选择结果).xls"; string filePath = webRootPath + tpath; DirectoryInfo di = new DirectoryInfo(filePath); if (!di.Exists) { di.Create(); } FileStream fileHssf = new FileStream(filePath + fileName, FileMode.Create); book.Write(fileHssf); fileHssf.Close(); jm.code = 0; jm.msg = GlobalConstVars.ExcelExportSuccess; jm.data = tpath + fileName; return jm; } #endregion #region 查询导出============================================================ // POST: Api/SQReservations/QueryExportExcel/10 /// /// 查询导出 /// /// [HttpPost] [Description("查询导出")] public async Task QueryExportExcel() { var jm = new AdminUiCallBack(); var where = PredicateBuilder.True(); //查询筛选 //预约ID int var id = Request.Form["id"].FirstOrDefault().ObjectToInt(0); if (id > 0) { where = where.And(p => p.id == id); } //组局名称 nvarchar var title = Request.Form["title"].FirstOrDefault(); if (!string.IsNullOrEmpty(title)) { where = where.And(p => p.title.Contains(title)); } //房间ID int var room_id = Request.Form["room_id"].FirstOrDefault().ObjectToInt(0); if (room_id > 0) { where = where.And(p => p.room_id == room_id); } //房间名称(冗余存储,比如 304号-大包,30元/小时) nvarchar var room_name = Request.Form["room_name"].FirstOrDefault(); if (!string.IsNullOrEmpty(room_name)) { where = where.And(p => p.room_name.Contains(room_name)); } //开始时间 datetime var start_time = Request.Form["start_time"].FirstOrDefault(); if (!string.IsNullOrEmpty(start_time)) { var dt = start_time.ObjectToDate(); where = where.And(p => p.start_time > dt); } //结束时间 datetime var end_time = Request.Form["end_time"].FirstOrDefault(); if (!string.IsNullOrEmpty(end_time)) { var dt = end_time.ObjectToDate(); where = where.And(p => p.end_time > dt); } //时长(分钟) int var duration_minutes = Request.Form["duration_minutes"].FirstOrDefault().ObjectToInt(0); if (duration_minutes > 0) { where = where.And(p => p.duration_minutes == duration_minutes); } //人数 int var player_count = Request.Form["player_count"].FirstOrDefault().ObjectToInt(0); if (player_count > 0) { where = where.And(p => p.player_count == player_count); } //玩法类型(如:补克) nvarchar var game_type = Request.Form["game_type"].FirstOrDefault(); if (!string.IsNullOrEmpty(game_type)) { where = where.And(p => p.game_type.Contains(game_type)); } //具体规则(如:斗地主) nvarchar var game_rule = Request.Form["game_rule"].FirstOrDefault(); if (!string.IsNullOrEmpty(game_rule)) { where = where.And(p => p.game_rule.Contains(game_rule)); } //其他补充 nvarchar var extra_info = Request.Form["extra_info"].FirstOrDefault(); if (!string.IsNullOrEmpty(extra_info)) { where = where.And(p => p.extra_info.Contains(extra_info)); } //是否禁烟:0=不限制,1=禁烟,2=不禁烟 int var is_smoking = Request.Form["is_smoking"].FirstOrDefault().ObjectToInt(0); if (is_smoking > 0) { where = where.And(p => p.is_smoking == is_smoking); } //性别限制:0=不限,1=男,2=女 int var gender_limit = Request.Form["gender_limit"].FirstOrDefault().ObjectToInt(0); if (gender_limit > 0) { where = where.And(p => p.gender_limit == gender_limit); } //最低信誉分 decimal var credit_limit = Request.Form["credit_limit"].FirstOrDefault().ObjectToDecimal(0); if (credit_limit > 0) { where = where.And(p => p.credit_limit == credit_limit); } //最小年龄限制 int var min_age = Request.Form["min_age"].FirstOrDefault().ObjectToInt(0); if (min_age > 0) { where = where.And(p => p.min_age == min_age); } //最大年龄限制,0=不限 int var max_age = Request.Form["max_age"].FirstOrDefault().ObjectToInt(0); if (max_age > 0) { where = where.And(p => p.max_age == max_age); } //鸽子费(保证金) decimal var deposit_fee = Request.Form["deposit_fee"].FirstOrDefault().ObjectToDecimal(0); if (deposit_fee > 0) { where = where.And(p => p.deposit_fee == deposit_fee); } //状态:0=待开始,1=进行中,2=已结束,3=取消 int var status = Request.Form["status"].FirstOrDefault().ObjectToInt(0); if (status > 0) { where = where.And(p => p.status == status); } //创建时间 datetime var created_at = Request.Form["created_at"].FirstOrDefault(); if (!string.IsNullOrEmpty(created_at)) { var dt = created_at.ObjectToDate(); where = where.And(p => p.created_at > dt); } //更新时间 datetime var updated_at = Request.Form["updated_at"].FirstOrDefault(); if (!string.IsNullOrEmpty(updated_at)) { var dt = updated_at.ObjectToDate(); where = where.And(p => p.updated_at > dt); } //获取数据 //创建Excel文件的对象 var book = new HSSFWorkbook(); //添加一个sheet var mySheet = book.CreateSheet("Sheet1"); //获取list数据 var listModel = await _SQReservationsServices.QueryListByClauseAsync(where, p => p.id, OrderByType.Asc, true); //给sheet1添加第一行的头部标题 var headerRow = mySheet.CreateRow(0); var headerStyle = ExcelHelper.GetHeaderStyle(book); var cell0 = headerRow.CreateCell(0); cell0.SetCellValue("预约ID"); cell0.CellStyle = headerStyle; mySheet.SetColumnWidth(0, 10 * 256); var cell1 = headerRow.CreateCell(1); cell1.SetCellValue("组局名称"); cell1.CellStyle = headerStyle; mySheet.SetColumnWidth(1, 10 * 256); var cell2 = headerRow.CreateCell(2); cell2.SetCellValue("房间ID"); cell2.CellStyle = headerStyle; mySheet.SetColumnWidth(2, 10 * 256); var cell3 = headerRow.CreateCell(3); cell3.SetCellValue("房间名称"); cell3.CellStyle = headerStyle; mySheet.SetColumnWidth(3, 10 * 256); var cell4 = headerRow.CreateCell(4); cell4.SetCellValue("开始时间"); cell4.CellStyle = headerStyle; mySheet.SetColumnWidth(4, 10 * 256); var cell5 = headerRow.CreateCell(5); cell5.SetCellValue("结束时间"); cell5.CellStyle = headerStyle; mySheet.SetColumnWidth(5, 10 * 256); var cell6 = headerRow.CreateCell(6); cell6.SetCellValue("时长(分钟)"); cell6.CellStyle = headerStyle; mySheet.SetColumnWidth(6, 10 * 256); var cell7 = headerRow.CreateCell(7); cell7.SetCellValue("人数"); cell7.CellStyle = headerStyle; mySheet.SetColumnWidth(7, 10 * 256); var cell8 = headerRow.CreateCell(8); cell8.SetCellValue("玩法类型"); cell8.CellStyle = headerStyle; mySheet.SetColumnWidth(8, 10 * 256); var cell9 = headerRow.CreateCell(9); cell9.SetCellValue("具体规则"); cell9.CellStyle = headerStyle; mySheet.SetColumnWidth(9, 10 * 256); var cell10 = headerRow.CreateCell(10); cell10.SetCellValue("其他补充"); cell10.CellStyle = headerStyle; mySheet.SetColumnWidth(10, 10 * 256); var cell11 = headerRow.CreateCell(11); cell11.SetCellValue("是否禁烟"); cell11.CellStyle = headerStyle; mySheet.SetColumnWidth(11, 10 * 256); var cell12 = headerRow.CreateCell(12); cell12.SetCellValue("性别"); cell12.CellStyle = headerStyle; mySheet.SetColumnWidth(12, 10 * 256); var cell13 = headerRow.CreateCell(13); cell13.SetCellValue("最低信誉分"); cell13.CellStyle = headerStyle; mySheet.SetColumnWidth(13, 10 * 256); var cell14 = headerRow.CreateCell(14); cell14.SetCellValue("最小年龄限制"); cell14.CellStyle = headerStyle; mySheet.SetColumnWidth(14, 10 * 256); var cell15 = headerRow.CreateCell(15); cell15.SetCellValue("最大年龄限制"); cell15.CellStyle = headerStyle; mySheet.SetColumnWidth(15, 10 * 256); var cell16 = headerRow.CreateCell(16); cell16.SetCellValue("鸽子费"); cell16.CellStyle = headerStyle; mySheet.SetColumnWidth(16, 10 * 256); var cell17 = headerRow.CreateCell(17); cell17.SetCellValue("状态"); cell17.CellStyle = headerStyle; mySheet.SetColumnWidth(17, 10 * 256); var cell18 = headerRow.CreateCell(18); cell18.SetCellValue("创建时间"); cell18.CellStyle = headerStyle; mySheet.SetColumnWidth(18, 10 * 256); var cell19 = headerRow.CreateCell(19); cell19.SetCellValue("更新时间"); cell19.CellStyle = headerStyle; mySheet.SetColumnWidth(19, 10 * 256); headerRow.Height = 30 * 20; var commonCellStyle = ExcelHelper.GetCommonStyle(book); //将数据逐步写入sheet1各个行 for (var i = 0; i < listModel.Count; i++) { var rowTemp = mySheet.CreateRow(i + 1); var rowTemp0 = rowTemp.CreateCell(0); rowTemp0.SetCellValue(listModel[i].id.ToString()); rowTemp0.CellStyle = commonCellStyle; var rowTemp1 = rowTemp.CreateCell(1); rowTemp1.SetCellValue(listModel[i].title.ToString()); rowTemp1.CellStyle = commonCellStyle; var rowTemp2 = rowTemp.CreateCell(2); rowTemp2.SetCellValue(listModel[i].room_id.ToString()); rowTemp2.CellStyle = commonCellStyle; var rowTemp3 = rowTemp.CreateCell(3); rowTemp3.SetCellValue(listModel[i].room_name.ToString()); rowTemp3.CellStyle = commonCellStyle; var rowTemp4 = rowTemp.CreateCell(4); rowTemp4.SetCellValue(listModel[i].start_time.ToString()); rowTemp4.CellStyle = commonCellStyle; var rowTemp5 = rowTemp.CreateCell(5); rowTemp5.SetCellValue(listModel[i].end_time.ToString()); rowTemp5.CellStyle = commonCellStyle; var rowTemp6 = rowTemp.CreateCell(6); rowTemp6.SetCellValue(listModel[i].duration_minutes.ToString()); rowTemp6.CellStyle = commonCellStyle; var rowTemp7 = rowTemp.CreateCell(7); rowTemp7.SetCellValue(listModel[i].player_count.ToString()); rowTemp7.CellStyle = commonCellStyle; var rowTemp8 = rowTemp.CreateCell(8); rowTemp8.SetCellValue(listModel[i].game_type.ToString()); rowTemp8.CellStyle = commonCellStyle; var rowTemp9 = rowTemp.CreateCell(9); rowTemp9.SetCellValue(listModel[i].game_rule.ToString()); rowTemp9.CellStyle = commonCellStyle; var rowTemp10 = rowTemp.CreateCell(10); rowTemp10.SetCellValue(listModel[i].extra_info.ToString()); rowTemp10.CellStyle = commonCellStyle; var rowTemp11 = rowTemp.CreateCell(11); rowTemp11.SetCellValue(listModel[i].is_smoking.ToString()); rowTemp11.CellStyle = commonCellStyle; var rowTemp12 = rowTemp.CreateCell(12); rowTemp12.SetCellValue(listModel[i].gender_limit.ToString()); rowTemp12.CellStyle = commonCellStyle; var rowTemp13 = rowTemp.CreateCell(13); rowTemp13.SetCellValue(listModel[i].credit_limit.ToString()); rowTemp13.CellStyle = commonCellStyle; var rowTemp14 = rowTemp.CreateCell(14); rowTemp14.SetCellValue(listModel[i].min_age.ToString()); rowTemp14.CellStyle = commonCellStyle; var rowTemp15 = rowTemp.CreateCell(15); rowTemp15.SetCellValue(listModel[i].max_age.ToString()); rowTemp15.CellStyle = commonCellStyle; var rowTemp16 = rowTemp.CreateCell(16); rowTemp16.SetCellValue(listModel[i].deposit_fee.ToString()); rowTemp16.CellStyle = commonCellStyle; var rowTemp17 = rowTemp.CreateCell(17); rowTemp17.SetCellValue(listModel[i].status.ToString()); rowTemp17.CellStyle = commonCellStyle; var rowTemp18 = rowTemp.CreateCell(18); rowTemp18.SetCellValue(listModel[i].created_at.ToString()); rowTemp18.CellStyle = commonCellStyle; var rowTemp19 = rowTemp.CreateCell(19); rowTemp19.SetCellValue(listModel[i].updated_at.ToString()); rowTemp19.CellStyle = commonCellStyle; } // 写入到excel string webRootPath = _webHostEnvironment.WebRootPath; string tpath = "/files/" + DateTime.Now.ToString("yyyy-MM-dd") + "/"; string fileName = DateTime.Now.ToString("yyyyMMddHHmmssfff") + "-SQReservations导出(查询结果).xls"; string filePath = webRootPath + tpath; DirectoryInfo di = new DirectoryInfo(filePath); if (!di.Exists) { di.Create(); } FileStream fileHssf = new FileStream(filePath + fileName, FileMode.Create); book.Write(fileHssf); fileHssf.Close(); jm.code = 0; jm.msg = GlobalConstVars.ExcelExportSuccess; jm.data = tpath + fileName; return jm; } #endregion #region 强制退出参与者====================================================== [HttpPost] [Description("强制退出参与者")] public AdminUiCallBack ForceExitParticipant([FromBody] FMIntId entity) { var jm = new AdminUiCallBack(); if (entity.id > 0) { var re = _SQReservationParticipantsServices.QueryById(entity.id); if (re != null) { re.status = 1; re.remarks = $"后台于{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}强制退出!"; if (re.is_refund == 1) { re.is_refund = 2; } _SQReservationParticipantsServices.Update(re); jm.msg = "强制退出成功"; jm.code = 0; } } return jm; } #endregion #region 解散预约====================================================== // POST: Api/SQReservations/DissolveReservation /// /// 后台解散预约(强制取消整个组局) /// /// 预约ID /// [HttpPost] [Description("解散预约")] public async Task DissolveReservation([FromBody] FMIntId entity) { var jm = new AdminUiCallBack(); if (entity == null || entity.id <= 0) { jm.msg = "参数错误"; return jm; } // 查询预约信息 var reservation = await _SQReservationsServices.QueryByClauseAsync(r => r.id == entity.id); if (reservation == null) { jm.msg = "预约不存在"; return jm; } // 检查预约状态 if (reservation.status >= 3) // 3=已结束,4=已取消 { jm.msg = "该预约已结束或已取消,无法再次解散"; return jm; } // 1. 更新预约状态为已取消 var updateResult = await _SQReservationsServices.UpdateAsync( it => new SQReservations { status = 4, // 已取消 updated_at = DateTime.Now, remarks = $"后台于{DateTime.Now:yyyy-MM-dd HH:mm:ss}强制解散" }, it => it.id == entity.id); if (!updateResult) { jm.msg = "解散预约失败"; return jm; } // 2. 有押金时,已支付押金(is_refund=2)的参与者标记为发起退款(is_refund=3) if (reservation.deposit_fee.HasValue && reservation.deposit_fee.Value > 0) { await _SQReservationParticipantsServices.UpdateAsync( it => new SQReservationParticipants { is_refund = 3 // 发起退款 }, it => it.reservation_id == entity.id && it.status == 0 && it.is_refund == 2 && it.paymentId != null && it.paymentId != ""); } // 3. 所有参与者标记为已退出 await _SQReservationParticipantsServices.UpdateAsync( it => new SQReservationParticipants { status = 1, // 已退出 quit_time = DateTime.Now, remarks = $"后台于{DateTime.Now:yyyy-MM-dd HH:mm:ss}强制解散组局" }, it => it.reservation_id == entity.id && it.status == 0); jm.code = 0; jm.msg = "解散预约成功"; return jm; } #endregion #region 请出参与者====================================================== // POST: Api/SQReservations/KickParticipant /// /// 后台请出参与者(如果是发起者则解散整个组局) /// /// 参与者ID /// [HttpPost] [Description("请出参与者")] public async Task KickParticipant([FromBody] FMIntId entity) { var jm = new AdminUiCallBack(); if (entity == null || entity.id <= 0) { jm.msg = "参数错误"; return jm; } // 查询参与者信息 var participant = await _SQReservationParticipantsServices.QueryByClauseAsync(p => p.id == entity.id); if (participant == null) { jm.msg = "参与者不存在"; return jm; } // 检查参与者状态 if (participant.status == 1) { jm.msg = "该参与者已退出"; return jm; } // 查询预约信息 var reservation = await _SQReservationsServices.QueryByClauseAsync(r => r.id == participant.reservation_id); if (reservation == null) { jm.msg = "预约不存在"; return jm; } // 检查预约状态 if (reservation.status >= 3) { jm.msg = "该预约已结束或已取消"; return jm; } // 如果是发起者,解散整个组局 if (participant.role == 1) { // 调用解散预约逻辑 return await DissolveReservation(new FMIntId { id = reservation.id }); } // 普通参与者:标记为已退出 participant.status = 1; participant.quit_time = DateTime.Now; participant.remarks = $"后台于{DateTime.Now:yyyy-MM-dd HH:mm:ss}请出组局"; // 有押金且已支付时,标记为发起退款 if (reservation.deposit_fee.HasValue && reservation.deposit_fee.Value > 0 && participant.is_refund == 2 && !string.IsNullOrEmpty(participant.paymentId)) { participant.is_refund = 3; // 发起退款 } var updateResult = await _SQReservationParticipantsServices.UpdateAsync(participant); if (updateResult.code != 0) { jm.msg = "请出参与者失败"; return jm; } jm.code = 0; jm.msg = "请出参与者成功"; return jm; } #endregion #region SearchUsers // POST: Api/SQReservations/SearchUsers /// /// 搜索用户 /// /// [HttpPost] [Description("搜索用户")] public async Task SearchUsers() { var jm = new AdminUiCallBack(); var pageCurrent = Request.Form["page"].FirstOrDefault().ObjectToInt(1); var pageSize = Request.Form["limit"].FirstOrDefault().ObjectToInt(10); var searchText = Request.Form["searchText"].FirstOrDefault(); var where = PredicateBuilder.True(); // 搜索条件 if (!string.IsNullOrEmpty(searchText)) { // 支持按用户名、昵称、手机号搜索 where = where.And(p => p.userName.Contains(searchText) || p.nickName.Contains(searchText) || p.mobile.Contains(searchText) || p.id.ToString().Contains(searchText)); } // 只查询正常状态的用户 where = where.And(p => p.isDelete == false); var list = await _userServices.QueryPageAsync(where, p => p.id, OrderByType.Desc, pageCurrent, pageSize); jm.code = 0; jm.count = list.TotalCount; jm.msg = "查询成功"; jm.data = list.Select(p => new { id = p.id, userName = p.userName, nickName = p.nickName, mobile = p.mobile }).ToList(); return jm; } // POST: Api/SQReservations/AddParticipant /// /// 添加参与者 /// /// [HttpPost] [Description("添加参与者")] public async Task AddParticipant([FromBody] FMAddParticipant entity) { var jm = new AdminUiCallBack(); try { // 验证参数 if (entity.reservationId <= 0 || entity.userId <= 0) { jm.msg = "参数错误"; return jm; } // 检查预约是否存在 var reservation = await _SQReservationsServices.QueryByIdAsync(entity.reservationId); if (reservation == null) { jm.msg = "预约不存在"; return jm; } // 检查用户是否存在 var user = await _userServices.QueryByIdAsync(entity.userId); if (user == null) { jm.msg = "用户不存在"; return jm; } // 检查用户是否已经是参与者 var existingParticipant = await _SQReservationParticipantsServices.QueryListByClauseAsync(p => p.reservation_id == entity.reservationId && p.user_id == entity.userId); if (existingParticipant.Any()) { jm.msg = "该用户已经是参与者"; return jm; } // 创建新的参与者记录 var participant = new SQReservationParticipants { reservation_id = entity.reservationId, user_id = entity.userId, role = 0, // 0=参与者 join_time = DateTime.Now, status = 0, // 0=正常 is_refund = 0, // 0=无需退款 remarks = $"后台于{DateTime.Now:yyyy-MM-dd HH:mm:ss}添加" }; var result = await _SQReservationParticipantsServices.InsertAsync(participant); if (result.code == 0) { jm.code = 0; jm.msg = "添加参与者成功"; } else { jm.msg = "添加参与者失败"; } } catch (Exception ex) { jm.msg = "添加参与者时发生错误:" + ex.Message; } return jm; } // POST: Api/SQReservations/BecomeInitiator /// /// 设置发起者 /// /// [HttpPost] [Description("设置发起者")] public async Task BecomeInitiator([FromBody] FMBecomeInitiator entity) { var jm = new AdminUiCallBack(); try { // 验证参数 if (entity.reservationId <= 0 || entity.participantId <= 0 || entity.userId <= 0) { jm.msg = "参数错误"; return jm; } // 检查预约是否存在 var reservation = await _SQReservationsServices.QueryByIdAsync(entity.reservationId); if (reservation == null) { jm.msg = "预约不存在"; return jm; } // 检查参与者是否存在 var participant = await _SQReservationParticipantsServices.QueryByIdAsync(entity.participantId); if (participant == null) { jm.msg = "参与者不存在"; return jm; } // 检查用户是否存在 var user = await _userServices.QueryByIdAsync(entity.userId); if (user == null) { jm.msg = "用户不存在"; return jm; } // 检查该预约是否已有发起者 var existingInitiator = await _SQReservationParticipantsServices.QueryListByClauseAsync(p => p.reservation_id == entity.reservationId && p.role == 1); // 1=发起者 if (existingInitiator.Any()) { // 如果已有发起者,将其改为参与者 var oldInitiator = existingInitiator.First(); oldInitiator.role = 0; // 0=参与者 oldInitiator.remarks = $"后台于{DateTime.Now:yyyy-MM-dd HH:mm:ss}将原发起者改为参与者"; await _SQReservationParticipantsServices.UpdateAsync(oldInitiator); } // 将指定参与者设置为发起者 participant.role = 1; // 1=发起者 participant.remarks = $"后台于{DateTime.Now:yyyy-MM-dd HH:mm:ss}设置为发起者"; var result = await _SQReservationParticipantsServices.UpdateAsync(participant); if (result.code == 0) { jm.code = 0; jm.msg = "设置发起者成功"; } else { jm.msg = "设置发起者失败"; } } catch (Exception ex) { jm.msg = "设置发起者时发生错误:" + ex.Message; } return jm; } #endregion #region 鸽子费审核功能====================================================== /// /// 获取鸽子费待审核列表 /// /// [HttpPost] [Description("获取鸽子费待审核列表")] public async Task GetPigeonFeeAuditList() { var jm = new AdminUiCallBack(); var pageCurrent = Request.Form["page"].FirstOrDefault().ObjectToInt(1); var pageSize = Request.Form["limit"].FirstOrDefault().ObjectToInt(30); // 筛选条件 var reservationId = Request.Form["reservation_id"].FirstOrDefault().ObjectToInt(0); var userId = Request.Form["user_id"].FirstOrDefault().ObjectToInt(0); var keyword = Request.Form["keyword"].FirstOrDefault(); // 用户昵称或手机号 // 预约时间筛选 var startTimeBegin = Request.Form["start_time_begin"].FirstOrDefault(); var startTimeEnd = Request.Form["start_time_end"].FirstOrDefault(); // 标记时间筛选 var markTimeBegin = Request.Form["mark_time_begin"].FirstOrDefault(); var markTimeEnd = Request.Form["mark_time_end"].FirstOrDefault(); // 构建SQL查询 - 查询 is_arrive=2(未赴约待审核)且 status=0(未退出)且预约有鸽子费的参与者 var sql = @" SELECT p.id AS participant_id, p.reservation_id, r.title AS reservation_title, p.user_id, u.nickName AS nick_name, u.mobile, ISNULL(r.deposit_fee, 0) AS deposit_fee, r.start_time, r.end_time, r.room_name, (SELECT TOP 1 check_reservation FROM SQReservationParticipants WHERE reservation_id = p.reservation_id AND role = 1) AS mark_time, p.is_arrive FROM SQReservationParticipants p INNER JOIN SQReservations r ON p.reservation_id = r.id INNER JOIN CoreCmsUser u ON p.user_id = u.id WHERE p.is_arrive = 2 AND p.status = 0 AND ISNULL(r.deposit_fee, 0) > 0"; // 添加筛选条件 if (reservationId > 0) { sql += $" AND p.reservation_id = {reservationId}"; } if (userId > 0) { sql += $" AND p.user_id = {userId}"; } if (!string.IsNullOrEmpty(keyword)) { sql += $" AND (u.nickName LIKE '%{keyword}%' OR u.mobile LIKE '%{keyword}%')"; } if (!string.IsNullOrEmpty(startTimeBegin)) { var dt = startTimeBegin.ObjectToDate(); sql += $" AND r.start_time >= '{dt:yyyy-MM-dd HH:mm:ss}'"; } if (!string.IsNullOrEmpty(startTimeEnd)) { var dt = startTimeEnd.ObjectToDate(); sql += $" AND r.start_time <= '{dt:yyyy-MM-dd HH:mm:ss}'"; } if (!string.IsNullOrEmpty(markTimeBegin)) { var dt = markTimeBegin.ObjectToDate(); sql += $" AND (SELECT TOP 1 check_reservation FROM SQReservationParticipants WHERE reservation_id = p.reservation_id AND role = 1) >= '{dt:yyyy-MM-dd HH:mm:ss}'"; } if (!string.IsNullOrEmpty(markTimeEnd)) { var dt = markTimeEnd.ObjectToDate(); sql += $" AND (SELECT TOP 1 check_reservation FROM SQReservationParticipants WHERE reservation_id = p.reservation_id AND role = 1) <= '{dt:yyyy-MM-dd HH:mm:ss}'"; } // 获取总数 var countSql = $"SELECT COUNT(1) FROM ({sql}) AS t"; var totalCount = await _unitOfWork.GetDbClient().Ado.GetIntAsync(countSql); // 分页排序 sql += $" ORDER BY (SELECT TOP 1 check_reservation FROM SQReservationParticipants WHERE reservation_id = p.reservation_id AND role = 1) DESC"; sql += $" OFFSET {(pageCurrent - 1) * pageSize} ROWS FETCH NEXT {pageSize} ROWS ONLY"; var list = await _unitOfWork.GetDbClient().Ado.SqlQueryAsync(sql); jm.data = list; jm.code = 0; jm.count = totalCount; jm.msg = "数据调用成功!"; return jm; } /// /// 审核通过 - 扣除鸽子费并分配给已赴约用户 /// /// 审核请求参数 /// [HttpPost] [Description("鸽子费审核通过")] public async Task ApprovePigeonFee([FromBody] PigeonFeeAuditRequestDto request) { var jm = new AdminUiCallBack(); if (request == null || request.participant_id <= 0 || request.reservation_id <= 0) { jm.msg = "参数错误"; return jm; } // 获取当前登录管理员ID var operatorId = HttpContext.User.Claims.FirstOrDefault(c => c.Type == "id")?.Value.ObjectToInt(0) ?? 0; // 查询参与者信息 var participant = await _SQReservationParticipantsServices.QueryByClauseAsync( p => p.id == request.participant_id && p.reservation_id == request.reservation_id); if (participant == null) { jm.msg = "参与者记录不存在"; return jm; } // 检查状态是否为待审核 if (participant.is_arrive != 2) { jm.msg = "该用户不是待审核状态"; return jm; } // 查询预约信息 var reservation = await _SQReservationsServices.QueryByClauseAsync(r => r.id == request.reservation_id); if (reservation == null) { jm.msg = "预约不存在"; return jm; } // 获取鸽子费金额 var depositFee = reservation.deposit_fee ?? 0; if (depositFee <= 0) { jm.msg = "该预约没有鸽子费"; return jm; } // 获取未赴约用户信息(用于消息通知) var absentUser = await _userServices.QueryByIdAsync(participant.user_id); var absentUserName = absentUser?.nickName ?? $"用户{participant.user_id}"; // 获取发起者签到时间 var initiatorParticipant = await _SQReservationParticipantsServices.QueryByClauseAsync( p => p.reservation_id == request.reservation_id && p.role == 1); var checkTime = initiatorParticipant?.check_reservation; // 查询符合条件的已赴约用户(排除发起者和未赴约用户本人) // 条件:is_arrive=1, status=0, join_time < 签到时间, role != 1(排除发起者) var eligibleParticipantsSql = $@" SELECT p.*, u.nickName, u.mobile FROM SQReservationParticipants p INNER JOIN CoreCmsUser u ON p.user_id = u.id WHERE p.reservation_id = {request.reservation_id} AND p.is_arrive = 1 AND p.status = 0 AND p.role != 1"; // 如果有签到时间,则只选择签到之前加入的参与者 if (checkTime.HasValue) { eligibleParticipantsSql += $" AND p.join_time < '{checkTime.Value:yyyy-MM-dd HH:mm:ss}'"; } var eligibleParticipants = await _unitOfWork.GetDbClient().Ado.SqlQueryAsync(eligibleParticipantsSql); var participantCount = eligibleParticipants?.Count ?? 0; try { _unitOfWork.BeginTran(); // 1. 更新未赴约用户状态为已审核 await _SQReservationParticipantsServices.UpdateAsync( it => new SQReservationParticipants { is_arrive = 3 // 未赴约,已审核 }, it => it.id == request.participant_id); // 2. 如果有符合条件的已赴约用户,分配鸽子费 if (participantCount > 0) { // 计算每人分得金额(保留两位小数,四舍五入) var amountPerPerson = Math.Round(depositFee / participantCount, 2, MidpointRounding.AwayFromZero); foreach (var ep in eligibleParticipants) { int epUserId = (int)ep.user_id; string epNickName = ep.nickName ?? $"用户{epUserId}"; // 为每个用户创建收益记录 var earningsResult = await _sQEarningsServices.AddEarningsAsync( userId: epUserId, reservationId: request.reservation_id, roomId: reservation.room_id, roomNumber: reservation.room_id.ToString(), roomName: reservation.room_name, roomFee: 0, // 鸽子费不涉及房费 earnings: amountPerPerson, type: 2, // 鸽子费类型 remark: "未赴约用户鸽子费分配", operatorId: operatorId); // 发送消息给分到钱的用户 await _sQMessageServices.SendSystemNoticeAsync( epUserId, "鸽子费分配通知", $"{absentUserName} 未能按时参加预约,您收到鸽子费{amountPerPerson}元", relatedType: 1, // 组局 relatedId: request.reservation_id); } } // 3. 发送消息给未赴约用户 await _sQMessageServices.SendSystemNoticeAsync( participant.user_id, "鸽子费扣除通知", $"您未按时参加预约,鸽子费已扣除{depositFee}元。", relatedType: 1, // 组局 relatedId: request.reservation_id); _unitOfWork.CommitTran(); jm.code = 0; jm.msg = participantCount > 0 ? $"审核通过,鸽子费{depositFee}元已分配给{participantCount}位已赴约用户" : "审核通过,但没有符合条件的已赴约用户分配鸽子费"; } catch (Exception ex) { _unitOfWork.RollbackTran(); jm.msg = "审核失败:" + ex.Message; } return jm; } /// /// 审核未通过 - 退还鸽子费 /// /// 审核请求参数 /// [HttpPost] [Description("鸽子费审核未通过")] public async Task RejectPigeonFee([FromBody] PigeonFeeAuditRequestDto request) { var jm = new AdminUiCallBack(); if (request == null || request.participant_id <= 0 || request.reservation_id <= 0) { jm.msg = "参数错误"; return jm; } // 查询参与者信息 var participant = await _SQReservationParticipantsServices.QueryByClauseAsync( p => p.id == request.participant_id && p.reservation_id == request.reservation_id); if (participant == null) { jm.msg = "参与者记录不存在"; return jm; } // 检查状态是否为待审核 if (participant.is_arrive != 2) { jm.msg = "该用户不是待审核状态"; return jm; } // 查询预约信息 var reservation = await _SQReservationsServices.QueryByClauseAsync(r => r.id == request.reservation_id); if (reservation == null) { jm.msg = "预约不存在"; return jm; } try { _unitOfWork.BeginTran(); // 1. 更新参与者状态 // is_arrive = 1(已赴约) // status = 0(正常,未退出) // is_refund = 3(发起退款,由退款任务处理) await _SQReservationParticipantsServices.UpdateAsync( it => new SQReservationParticipants { is_arrive = 1, // 已赴约 status = 0, // 正常 is_refund = 3 // 发起退款 }, it => it.id == request.participant_id); // 2. 发送消息给用户 await _sQMessageServices.SendSystemNoticeAsync( participant.user_id, "鸽子费审核结果", "您的鸽子费已原路退回。", relatedType: 1, // 组局 relatedId: request.reservation_id); _unitOfWork.CommitTran(); jm.code = 0; jm.msg = "审核未通过,鸽子费将原路退回"; } catch (Exception ex) { _unitOfWork.RollbackTran(); jm.msg = "审核失败:" + ex.Message; } return jm; } #endregion } }