diff --git a/CoreCms.Net.Configuration/GlobalEnumVars.cs b/CoreCms.Net.Configuration/GlobalEnumVars.cs index 4de6a65..f0fe2fc 100644 --- a/CoreCms.Net.Configuration/GlobalEnumVars.cs +++ b/CoreCms.Net.Configuration/GlobalEnumVars.cs @@ -2397,6 +2397,31 @@ namespace CoreCms.Net.Configuration /// [Description("退款通知")] refund, + /// + /// 预订成功通知 + /// + [Description("预订成功通知")] + reservation_success, + /// + /// 预约信息变更通知 + /// + [Description("预约信息变更通知")] + reservation_change, + /// + /// 预约提醒 + /// + [Description("预约提醒")] + reservation_reminder, + /// + /// 预约通知 + /// + [Description("预约通知")] + reservation_notice, + /// + /// 扣款通知 + /// + [Description("扣款通知")] + deduction_notice, } #endregion diff --git a/CoreCms.Net.IServices/WeChat/ICoreCmsUserWeChatMsgTemplateServices.cs b/CoreCms.Net.IServices/WeChat/ICoreCmsUserWeChatMsgTemplateServices.cs index 943e858..985bff6 100644 --- a/CoreCms.Net.IServices/WeChat/ICoreCmsUserWeChatMsgTemplateServices.cs +++ b/CoreCms.Net.IServices/WeChat/ICoreCmsUserWeChatMsgTemplateServices.cs @@ -10,6 +10,9 @@ using CoreCms.Net.Model.Entities; +using System.Collections.Generic; +using System.Threading.Tasks; + namespace CoreCms.Net.IServices { /// @@ -17,5 +20,11 @@ namespace CoreCms.Net.IServices /// public interface ICoreCmsUserWeChatMsgTemplateServices : IBaseServices { + + /// + /// + /// + /// + Task> GetListAsync(); } } \ No newline at end of file diff --git a/CoreCms.Net.Services/WeChat/CoreCmsUserWeChatMsgTemplateServices.cs b/CoreCms.Net.Services/WeChat/CoreCmsUserWeChatMsgTemplateServices.cs index d60e0bd..5fed70b 100644 --- a/CoreCms.Net.Services/WeChat/CoreCmsUserWeChatMsgTemplateServices.cs +++ b/CoreCms.Net.Services/WeChat/CoreCmsUserWeChatMsgTemplateServices.cs @@ -9,7 +9,10 @@ ***********************************************************************/ using System; +using System.Collections.Generic; using System.Threading.Tasks; + +using CoreCms.Net.Caching.AutoMate.RedisCache; using CoreCms.Net.Configuration; using CoreCms.Net.IRepository; using CoreCms.Net.IRepository.UnitOfWork; @@ -27,12 +30,36 @@ namespace CoreCms.Net.Services { private readonly ICoreCmsUserWeChatMsgTemplateRepository _dal; private readonly IUnitOfWork _unitOfWork; - public CoreCmsUserWeChatMsgTemplateServices(IUnitOfWork unitOfWork, ICoreCmsUserWeChatMsgTemplateRepository dal) + private readonly IRedisOperationRepository _redisOperationRepository; + public CoreCmsUserWeChatMsgTemplateServices(IUnitOfWork unitOfWork, ICoreCmsUserWeChatMsgTemplateRepository dal, + IRedisOperationRepository redisOperationRepository + ) { this._dal = dal; base.BaseDal = dal; _unitOfWork = unitOfWork; + _redisOperationRepository = redisOperationRepository; } + public async Task> GetListAsync() + { + var key = $"cache:CoreCmsUserWeChatMsgTemplate"; + var list = await _redisOperationRepository.Get>(key); + if (list == null) + { + List strings = new + List{ + GlobalEnumVars.WeChatMsgTemplateType.reservation_success.ToString(), + GlobalEnumVars.WeChatMsgTemplateType.reservation_change.ToString(), + GlobalEnumVars.WeChatMsgTemplateType.reservation_reminder.ToString(), + GlobalEnumVars.WeChatMsgTemplateType.reservation_notice.ToString(), + GlobalEnumVars.WeChatMsgTemplateType.deduction_notice.ToString(), + GlobalEnumVars.WeChatMsgTemplateType.refund.ToString(), + }; + list = await _dal.QueryListByClauseAsync(it => strings.Contains(it.templateTitle)); + await _redisOperationRepository.Set(key, list, TimeSpan.FromMinutes(10)); + } + return list; + } } } diff --git a/CoreCms.Net.Web.Admin/Controllers/WeChat/CoreCmsUserWeChatMsgTemplateController.cs b/CoreCms.Net.Web.Admin/Controllers/WeChat/CoreCmsUserWeChatMsgTemplateController.cs index 6f6c2c6..c8d295a 100644 --- a/CoreCms.Net.Web.Admin/Controllers/WeChat/CoreCmsUserWeChatMsgTemplateController.cs +++ b/CoreCms.Net.Web.Admin/Controllers/WeChat/CoreCmsUserWeChatMsgTemplateController.cs @@ -30,6 +30,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; using NPOI.HSSF.UserModel; using SqlSugar; +using CoreCms.Net.Caching.AutoMate.RedisCache; namespace CoreCms.Net.Web.Admin.Controllers { @@ -45,16 +46,18 @@ namespace CoreCms.Net.Web.Admin.Controllers { private readonly IWebHostEnvironment _webHostEnvironment; private readonly ICoreCmsUserWeChatMsgTemplateServices _coreCmsUserWeChatMsgTemplateServices; - + private readonly IRedisOperationRepository _redisOperationRepository; /// /// 构造函数 /// public CoreCmsUserWeChatMsgTemplateController(IWebHostEnvironment webHostEnvironment , ICoreCmsUserWeChatMsgTemplateServices coreCmsUserWeChatMsgTemplateServices + , IRedisOperationRepository redisOperationRepository ) { _webHostEnvironment = webHostEnvironment; _coreCmsUserWeChatMsgTemplateServices = coreCmsUserWeChatMsgTemplateServices; + _redisOperationRepository = redisOperationRepository; } #region 首页数据============================================================ @@ -72,12 +75,19 @@ namespace CoreCms.Net.Web.Admin.Controllers var data = await _coreCmsUserWeChatMsgTemplateServices.QueryAsync(); - var order = data.Find(p => p.templateTitle == GlobalEnumVars.WeChatMsgTemplateType.order.ToString()); - var cancel = data.Find(p => p.templateTitle == GlobalEnumVars.WeChatMsgTemplateType.cancel.ToString()); - var pay = data.Find(p => p.templateTitle == GlobalEnumVars.WeChatMsgTemplateType.pay.ToString()); - var ship = data.Find(p => p.templateTitle == GlobalEnumVars.WeChatMsgTemplateType.ship.ToString()); - var aftersale = data.Find(p => p.templateTitle == GlobalEnumVars.WeChatMsgTemplateType.aftersale.ToString()); - var refund = data.Find(p => p.templateTitle == GlobalEnumVars.WeChatMsgTemplateType.refund.ToString()); + var order = data.Find(p => p.templateTitle == GlobalEnumVars.WeChatMsgTemplateType.order.ToString()) ?? new CoreCmsUserWeChatMsgTemplate(); + var cancel = data.Find(p => p.templateTitle == GlobalEnumVars.WeChatMsgTemplateType.cancel.ToString()) ?? new CoreCmsUserWeChatMsgTemplate(); + var pay = data.Find(p => p.templateTitle == GlobalEnumVars.WeChatMsgTemplateType.pay.ToString()) ?? new CoreCmsUserWeChatMsgTemplate(); + var ship = data.Find(p => p.templateTitle == GlobalEnumVars.WeChatMsgTemplateType.ship.ToString()) ?? new CoreCmsUserWeChatMsgTemplate(); + var aftersale = data.Find(p => p.templateTitle == GlobalEnumVars.WeChatMsgTemplateType.aftersale.ToString()) ?? new CoreCmsUserWeChatMsgTemplate(); + var refund = data.Find(p => p.templateTitle == GlobalEnumVars.WeChatMsgTemplateType.refund.ToString()) ?? new CoreCmsUserWeChatMsgTemplate(); + var reservation_success = data.Find(p => p.templateTitle == GlobalEnumVars.WeChatMsgTemplateType.reservation_success.ToString()) ?? new CoreCmsUserWeChatMsgTemplate(); + var reservation_change = data.Find(p => p.templateTitle == GlobalEnumVars.WeChatMsgTemplateType.reservation_change.ToString()) ?? new CoreCmsUserWeChatMsgTemplate(); + var reservation_reminder = data.Find(p => p.templateTitle == GlobalEnumVars.WeChatMsgTemplateType.reservation_reminder.ToString()) ?? new CoreCmsUserWeChatMsgTemplate(); + + var reservation_notice = data.Find(p => p.templateTitle == GlobalEnumVars.WeChatMsgTemplateType.reservation_notice.ToString()) ?? new CoreCmsUserWeChatMsgTemplate(); + + var deduction_notice = data.Find(p => p.templateTitle == GlobalEnumVars.WeChatMsgTemplateType.deduction_notice.ToString()) ?? new CoreCmsUserWeChatMsgTemplate(); jm.data = new { @@ -86,7 +96,12 @@ namespace CoreCms.Net.Web.Admin.Controllers pay, ship, aftersale, - refund + refund, + reservation_success, + reservation_change, + reservation_reminder, + reservation_notice, + deduction_notice }; return jm; @@ -139,6 +154,9 @@ namespace CoreCms.Net.Web.Admin.Controllers } //事物处理过程开始 var data = await _coreCmsUserWeChatMsgTemplateServices.QueryAsync(); + var updateList = new List(); + var insertList = new List(); + foreach (var item in data) { var o = entity.list.Find(p => p.templateTitle == item.templateTitle); @@ -150,14 +168,48 @@ namespace CoreCms.Net.Web.Admin.Controllers item.data03 = o.data03.Trim(); item.data04 = o.data04.Trim(); item.data05 = o.data05.Trim(); + updateList.Add(item); } } - var bl = await _coreCmsUserWeChatMsgTemplateServices.UpdateAsync(data); + // 处理新增的记录 + foreach (var o in entity.list) + { + var existingItem = data.Find(p => p.templateTitle == o.templateTitle); + if (existingItem == null) + { + var newItem = new CoreCmsUserWeChatMsgTemplate + { + templateTitle = o.templateTitle, + templateId = o.templateId.Trim(), + data01 = o.data01.Trim(), + data02 = o.data02.Trim(), + data03 = o.data03.Trim(), + data04 = o.data04.Trim(), + data05 = o.data05.Trim(), + templateDes = "", + description = "", + sortId = 0 + }; + insertList.Add(newItem); + } + } + + var bl = true; + if (updateList.Count > 0) + { + bl = await _coreCmsUserWeChatMsgTemplateServices.UpdateAsync(updateList); + } + if (bl && insertList.Count > 0) + { + var insertResult = await _coreCmsUserWeChatMsgTemplateServices.InsertAsync(insertList); + bl = insertResult > 0; + } jm.code = bl ? 0 : 1; jm.msg = bl ? GlobalConstVars.EditSuccess : GlobalConstVars.EditFailure; jm.otherData = entity; - + var key = $"cache:CoreCmsUserWeChatMsgTemplate"; + await _redisOperationRepository.Remove(key); return jm; } #endregion diff --git a/CoreCms.Net.Web.Admin/wwwroot/views/shop/message/wechatappletsmessage/index.html b/CoreCms.Net.Web.Admin/wwwroot/views/shop/message/wechatappletsmessage/index.html index 875eee0..4d72b03 100644 --- a/CoreCms.Net.Web.Admin/wwwroot/views/shop/message/wechatappletsmessage/index.html +++ b/CoreCms.Net.Web.Admin/wwwroot/views/shop/message/wechatappletsmessage/index.html @@ -19,24 +19,24 @@
微信小程序订阅消息
- 案例使用的小程序类目是:商家自营 > 食品,其他类目可以对应取舍,只要字段名称大体符合表述即可。
- 1、下单通知:指下单成功后反馈给用户的提醒,一般使用【新订单提醒】模板。
- 2、催付通知:指下单成功后一定时间内没有付款,定时任务自动推送提醒消息,一般使用【待付款提醒】模板。
- 3、支付通知:指下单成功并支付成功后的提醒,一般使用【订单支付成功通知】模板。
- 4、发货通知:指由商家对订单进行发货处理,填写快递单号后的提醒,一般使用【订单发货通知】模板。
- 5、售后通知:当客户对订单申请了售后,后台对售后订单进行审核处理的提醒,一般使用【订单售后审核通知】模板。
- 6、退款通知:对于审核通过后的订单,如果商家财务模块做了退款处理,则会进行提醒,一般使用【退款通知】模板。
+ 案例使用的小程序类目是:商家自营 > 生活服务,其他类目可以对应取舍,只要字段名称大体符合表述即可。
+ 1、预订成功通知:指用户预订成功后反馈给用户的提醒,一般使用【预订成功通知】模板。
+ 2、预约信息变更通知:指预约信息发生变更时的提醒,一般使用【预约信息变更通知】模板。
+ 3、预约提醒:指预约开始前的提醒,一般使用【预约提醒】模板。
+ 4、预约通知:指预约确认后的通知,一般使用【预约通知】模板。
+ 5、扣款通知:指扣款成功后的提醒,一般使用【扣款通知】模板。
+ 6、退款通知:指退款成功后的提醒,一般使用【退款通知】模板。
    -
  • 下单通知
  • -
  • 催付通知
  • -
  • 支付通知
  • -
  • 发货通知
  • -
  • 售后通知
  • +
  • 预订成功通知
  • +
  • 预约信息变更通知
  • +
  • 预约提醒
  • +
  • 预约通知
  • +
  • 扣款通知
  • 退款通知
@@ -46,37 +46,31 @@ 模板ID:
- +
- +
- +
- +
- +
- +
- +
- +
- -
-
-
- -
- +
@@ -84,115 +78,139 @@
- + +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+
+ +
+
- +
- +
- +
- +
- +
- -
-
-
-
-
- -
- +
- +
- -
-
-
- -
- -
-
-
- -
- -
-
-
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- +
@@ -204,33 +222,21 @@
- +
- -
-
-
- -
- +
- +
- +
- -
-
-
- -
- +
@@ -280,7 +286,7 @@ var field = data.field; //获取提交的字段 var list = [] - var titlearr = ['order', 'cancel', 'pay', 'ship', 'aftersale', 'refund'] + var titlearr = ['reservation_success', 'reservation_change', 'reservation_reminder', 'reservation_notice', 'deduction_notice', 'refund'] for (var i = 0; i < 6; i++) { var paramsModel = {}; var str = 'setting[' + i + ']' diff --git a/CoreCms.Net.Web.WebApi/Controllers/CommonController.cs b/CoreCms.Net.Web.WebApi/Controllers/CommonController.cs index a461fe3..1d8f71c 100644 --- a/CoreCms.Net.Web.WebApi/Controllers/CommonController.cs +++ b/CoreCms.Net.Web.WebApi/Controllers/CommonController.cs @@ -61,6 +61,7 @@ namespace CoreCms.Net.Web.WebApi.Controllers private readonly ISysDictionaryDataServices _sysDictionaryDataServices; private readonly ISysDictionaryServices _sysDictionaryServices; private readonly ISQReservationParticipantsServices _SQReservationParticipantsServices; + private readonly ICoreCmsUserWeChatMsgTemplateServices _coreCmsUserWeChatMsgTemplateServices; /// /// 构造函数 /// @@ -73,6 +74,7 @@ namespace CoreCms.Net.Web.WebApi.Controllers ISysDictionaryDataServices sysDictionaryDataServices, ISysDictionaryServices sysDictionaryServices, ISQReservationParticipantsServices SQReservationParticipantsServices + , ICoreCmsUserWeChatMsgTemplateServices coreCmsUserWeChatMsgTemplateServices ) { _webHostEnvironment = webHostEnvironment; @@ -86,6 +88,7 @@ namespace CoreCms.Net.Web.WebApi.Controllers _sysDictionaryDataServices = sysDictionaryDataServices; _sysDictionaryServices = sysDictionaryServices; _SQReservationParticipantsServices = SQReservationParticipantsServices; + _coreCmsUserWeChatMsgTemplateServices = coreCmsUserWeChatMsgTemplateServices; } @@ -127,8 +130,21 @@ namespace CoreCms.Net.Web.WebApi.Controllers //var entId = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.EntId); //客服ID var userAgreementId = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.UserAgreementId).ObjectToInt(3); //用户协议 var privacyPolicyId = CommonHelper.GetConfigDictionary(allConfigs, SystemSettingConstVars.PrivacyPolicyId).ObjectToInt(4); //隐私政策 - - + List templateList = new List(); + var template = await _coreCmsUserWeChatMsgTemplateServices.GetListAsync(); + if (template != null) + { + var f = template.OrderBy(it => it.sortId).Select(it => new { it.templateId, desc = it.templateDes, type = it.templateTitle }).ToList(); + foreach (var item in f) + { + templateList.Add(new + { + item.templateId, + item.desc, + item.type + }); + } + } var dic = await _sysDictionaryServices.QueryListByClauseAsync(it => !it.deleted, it => it.sortNumber , OrderByType.Asc); var dicData = await _sysDictionaryDataServices.QueryListByClauseAsync(it => !it.deleted); @@ -156,7 +172,8 @@ namespace CoreCms.Net.Web.WebApi.Controllers aboutArticleId, userAgreementId, privacyPolicyId, - playingMethodOptions = options + playingMethodOptions = options, + subscribeMessage = template }; jm.Data = data; return jm; diff --git a/CoreCms.Net.Web.WebApi/Controllers/SQController.cs b/CoreCms.Net.Web.WebApi/Controllers/SQController.cs index 742fd1f..9b67c53 100644 --- a/CoreCms.Net.Web.WebApi/Controllers/SQController.cs +++ b/CoreCms.Net.Web.WebApi/Controllers/SQController.cs @@ -431,7 +431,7 @@ ISQRoomUnavailableTimesServices sQRoomUnavailableTimesServices // 3. 查询已被预约的房间(未取消的预约,时间有重叠) var reservedRoomIds = (await _SQReservationsServices.QueryListByClauseAsync( - r => r.status < 3 && r.start_time < end && r.end_time > start + r => r.status < 2 && r.start_time < end && r.end_time > start )).Select(r => r.room_id).Distinct().ToList(); // 4. 可预约房间 = 所有可用房间 - 不可用房间 - 已预约房间 @@ -456,15 +456,172 @@ ISQRoomUnavailableTimesServices sQRoomUnavailableTimesServices /// /// [HttpPost] + [Authorize] public async Task AddSQReservation([FromBody] SQReservationsAddDto dto) { + var userId = _user.ID; + // 1. 参数校验 + if (dto == null || dto.room_id <= 0 || dto.start_time >= dto.end_time) + { + return new WebApiDto() + { + Code = 500, + Data = null, + Msg = "参数错误" + }; + } + + // 2. 检查房间是否存在 + var room = await _SQRoomsServices.QueryByClauseAsync(r => r.id == dto.room_id, r => r.id, OrderByType.Asc); + if (room == null) + { + return new WebApiDto() + { + Code = 500, + Data = null, + Msg = "房间不存在" + }; + } + + // 3. 检查房间是否可预约(不可用时间段) + var hasUnavailable = await _sQRoomUnavailableTimesServices.QueryListByClauseAsync( + t => t.room_id == dto.room_id && t.start_time < dto.end_time && t.end_time > dto.start_time, + t => t.id, OrderByType.Asc); + if (hasUnavailable != null && hasUnavailable.Count > 0) + { + return new WebApiDto() + { + Code = 500, + Data = null, + Msg = "该时间段房间不可预约" + }; + } + + // 4. 检查房间是否已被预约(未取消的预约,时间有重叠) + var hasReserved = await _SQReservationsServices.QueryListByClauseAsync( + r => r.room_id == dto.room_id && r.status < 2 && r.start_time < dto.end_time && r.end_time > dto.start_time, + r => r.id, OrderByType.Asc); + if (hasReserved != null && hasReserved.Count > 0) + { + return new WebApiDto() + { + Code = 500, + Data = null, + Msg = "该时间段房间已被预约" + }; + } + + // 5. 创建预约记录 + var reservation = new SQReservations + { + room_id = dto.room_id, + room_name = room.name, + start_time = dto.start_time, + end_time = dto.end_time, + game_type = dto.game_type, + created_at = DateTime.Now, + updated_at = DateTime.Now, + // 其他字段可根据需要补充 + }; + var reservationId = await _dbBase.Insertable(reservation).ExecuteReturnIdentityAsync(); + if (reservationId <= 0) + { + return new WebApiDto() + { + Code = 500, + Data = null, + Msg = "预约失败" + }; + } + + // 6. 创建预约参与人记录(发起者,role=1) + var participant = new SQReservationParticipants + { + reservation_id = reservationId, + user_id = userId, + join_time = DateTime.Now, + role = 1, + status = 0, + is_refund = dto.deposit_fee > 0 ? 1 : 0, + }; + await _SQReservationParticipantsServices.InsertAsync(participant); return new WebApiDto() { - Code = 500, + Code = 0, + Data = new { reservation_id = reservationId }, + Msg = "预约成功" + }; + } + /// + /// 用户加入预约接口 + /// + /// 预约ID + /// + [HttpPost] + [Authorize] + public async Task JoinReservation([FromBody] int reservationId) + { + var userId = _user.ID; + + // 1. 校验预约是否存在且未结束 + var reservation = await _SQReservationsServices.QueryByClauseAsync( + r => r.id == reservationId && r.end_time > DateTime.Now && r.status < 2, + r => r.id, OrderByType.Asc); + if (reservation == null) + { + return new WebApiDto + { + Code = 404, + Data = null, + Msg = "预约不存在或已结束" + }; + } + + // 2. 校验用户是否已加入该预约 + var exists = await _SQReservationParticipantsServices.QueryByClauseAsync( + p => p.reservation_id == reservationId && p.user_id == userId, + p => p.id, OrderByType.Asc); + if (exists != null) + { + return new WebApiDto + { + Code = 400, + Data = null, + Msg = "您已加入该预约" + }; + } + + //3.校验预约是否已满(如有容量限制,可补充) + var participantsCount = await _SQReservationParticipantsServices.QueryListByClauseAsync( + p => p.reservation_id == reservationId, p => p.id, OrderByType.Asc); + if (participantsCount.Count >= reservation.player_count) + { + return new WebApiDto() + { + Code = 401, + Data = null, + Msg = "预约已满" + }; + } + + // 4. 插入参与人记录 + var participant = new SQReservationParticipants + { + reservation_id = reservationId, + user_id = userId, + join_time = DateTime.Now, + role = 0, // 0为参与者 + status = 0 + }; + await _SQReservationParticipantsServices.InsertAsync(participant); + + return new WebApiDto + { + Code = 0, Data = null, - Msg = "预约功能暂未开放" + Msg = "加入预约成功" }; }