diff --git a/Kx.SeaTime.sln.DotSettings.user b/Kx.SeaTime.sln.DotSettings.user index 9879620..d9b405e 100644 --- a/Kx.SeaTime.sln.DotSettings.user +++ b/Kx.SeaTime.sln.DotSettings.user @@ -4,7 +4,9 @@ ForceIncluded ForceIncluded ForceIncluded + ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded \ No newline at end of file diff --git a/Service/Application.Domain.Entity/game/user/unit_user_message.cs b/Service/Application.Domain.Entity/game/user/unit_user_message.cs new file mode 100644 index 0000000..6b49b2a --- /dev/null +++ b/Service/Application.Domain.Entity/game/user/unit_user_message.cs @@ -0,0 +1,63 @@ +using SqlSugar; +using System; + +namespace Application.Domain.Entity +{ + [Tenant("Kg.SeaTime.Game")] + public class unit_user_message + { + /// + /// msgId + /// + [SugarColumn(IsPrimaryKey = true)] + public long msgId { get; set; } + + /// + /// userId + /// + [SugarColumn(Length = 50, IsNullable = true)] + public string? userId { get; set; } + + /// + /// sendId + /// + [SugarColumn(Length = 50, IsNullable = true)] + public string? sendId { get; set; } + + /// + /// sign + /// + [SugarColumn(IsNullable = true)] + public string? sign { get; set; } + + /// + /// isRead + /// + [SugarColumn(IsNullable = true)] + public int? isRead { get; set; } + + /// + /// status + /// + [SugarColumn(IsNullable = true)] + public int? status { get; set; } + + /// + /// addTime + /// + [SugarColumn(IsNullable = true)] + public DateTime? addTime { get; set; } + + /// + /// endTime + /// + [SugarColumn(IsNullable = true)] + public long? endTime { get; set; } + + /// + /// 会话ID + /// + [SugarColumn(Length = 100, IsNullable = true)] + public string? talkId { get; set; } + } +} \ No newline at end of file diff --git a/Service/Application.Domain.Entity/log/db/game_mall_log.cs b/Service/Application.Domain.Entity/log/db/game_mall_log.cs new file mode 100644 index 0000000..374724f --- /dev/null +++ b/Service/Application.Domain.Entity/log/db/game_mall_log.cs @@ -0,0 +1,69 @@ +using SqlSugar; +using System; + +namespace Application.Domain.Entity +{ + [Tenant("Kg.SeaTime.Log")] + public class game_mall_log + { + /// + /// logId + /// + [SugarColumn(IsPrimaryKey = true, Length = 50)] + public string logId { get; set; } + + /// + /// mallId + /// + [SugarColumn(Length = 50, IsNullable = true)] + public string? mallId { get; set; } + + /// + /// type + /// + [SugarColumn(Length = 50, IsNullable = true)] + public string? type { get; set; } + + /// + /// pars + /// + [SugarColumn(Length = 50, IsNullable = true)] + public Int32? pars { get; set; } + + /// + /// count + /// + [SugarColumn(IsNullable = true)] + public int? count { get; set; } + + /// + /// price + /// + [SugarColumn(IsNullable = true)] + public long? price { get; set; } + + /// + /// payType + /// + [SugarColumn(Length = 50, IsNullable = true)] + public string? payType { get; set; } + + /// + /// userId + /// + [SugarColumn(Length = 50, IsNullable = true)] + public string? userId { get; set; } + + /// + /// addTime + /// + [SugarColumn(IsNullable = true)] + public DateTime? addTime { get; set; } + + /// + /// endTime + /// + [SugarColumn(IsNullable = true)] + public DateTime? endTime { get; set; } + } +} \ No newline at end of file diff --git a/Service/Application.Domain.Entity/game/user/unit_user_acc_log.cs b/Service/Application.Domain.Entity/log/db/unit_user_acc_log.cs similarity index 97% rename from Service/Application.Domain.Entity/game/user/unit_user_acc_log.cs rename to Service/Application.Domain.Entity/log/db/unit_user_acc_log.cs index 48124dc..df2c098 100644 --- a/Service/Application.Domain.Entity/game/user/unit_user_acc_log.cs +++ b/Service/Application.Domain.Entity/log/db/unit_user_acc_log.cs @@ -3,7 +3,7 @@ using System; namespace Application.Domain.Entity { - [Tenant("Kg.SeaTime.Game")] + [Tenant("Kg.SeaTime.Log")] public class unit_user_acc_log { /// diff --git a/Service/Application.Domain.Entity/game/user/unit_user_weight_log.cs b/Service/Application.Domain.Entity/log/db/unit_user_weight_log.cs similarity index 97% rename from Service/Application.Domain.Entity/game/user/unit_user_weight_log.cs rename to Service/Application.Domain.Entity/log/db/unit_user_weight_log.cs index c2544a2..697aaba 100644 --- a/Service/Application.Domain.Entity/game/user/unit_user_weight_log.cs +++ b/Service/Application.Domain.Entity/log/db/unit_user_weight_log.cs @@ -3,7 +3,7 @@ using System; namespace Application.Domain.Entity { - [Tenant("Kg.SeaTime.Game")] + [Tenant("Kg.SeaTime.Log")] public class unit_user_weight_log { /// diff --git a/Service/Application.Domain.Entity/resource/game/game_mall.cs b/Service/Application.Domain.Entity/resource/game/game_mall.cs new file mode 100644 index 0000000..b9094f9 --- /dev/null +++ b/Service/Application.Domain.Entity/resource/game/game_mall.cs @@ -0,0 +1,69 @@ +using SqlSugar; +using System; + +namespace Application.Domain.Entity +{ + [Tenant("Kg.SeaTime.Resource")] + public class game_mall + { + /// + /// mallId + /// + [SugarColumn(IsPrimaryKey = true, Length = 50)] + public string mallId { get; set; } + + /// + /// areaId + /// + [SugarColumn(Length = 50, IsNullable = true)] + public string? areaId { get; set; } + + /// + /// name + /// + [SugarColumn(Length = 50, IsNullable = true)] + public string? name { get; set; } + + /// + /// type + /// + [SugarColumn(Length = 50, IsNullable = true)] + public string? type { get; set; } + + /// + /// goodsId + /// + [SugarColumn(IsNullable = true)] + public int? goodsId { get; set; } + + /// + /// price + /// + [SugarColumn(IsNullable = true)] + public long? price { get; set; } + + /// + /// payType + /// + [SugarColumn(Length = 50, IsNullable = true)] + public string? payType { get; set; } + + /// + /// sort + /// + [SugarColumn(IsNullable = true)] + public int? sort { get; set; } + + /// + /// addTime + /// + [SugarColumn(IsNullable = true)] + public DateTime? addTime { get; set; } + + /// + /// endTime + /// + [SugarColumn(IsNullable = true)] + public DateTime? endTime { get; set; } + } +} \ No newline at end of file diff --git a/Service/Application.Domain.Entity/view/MessageView.cs b/Service/Application.Domain.Entity/view/MessageView.cs new file mode 100644 index 0000000..1a5e19f --- /dev/null +++ b/Service/Application.Domain.Entity/view/MessageView.cs @@ -0,0 +1,7 @@ +namespace Application.Domain.Entity; + +public class MessageView +{ + public string sign { get; set; } + public UserModel user { get; set;} +} \ No newline at end of file diff --git a/Service/Application.Domain/Services/Interface/Pub/IGameMallService.cs b/Service/Application.Domain/Services/Interface/Pub/IGameMallService.cs new file mode 100644 index 0000000..bd6f8f3 --- /dev/null +++ b/Service/Application.Domain/Services/Interface/Pub/IGameMallService.cs @@ -0,0 +1,8 @@ +namespace Application.Domain; + +public interface IGameMallService +{ + Task> GetMallData(int area, string type, int page, int limit, RefAsync total); + Task GetMallInfo(string mallId); + Task AddLog(game_mall mall, string userId, int count); +} \ No newline at end of file diff --git a/Service/Application.Domain/Services/Interface/Pub/IMessageService.cs b/Service/Application.Domain/Services/Interface/Pub/IMessageService.cs new file mode 100644 index 0000000..0d99597 --- /dev/null +++ b/Service/Application.Domain/Services/Interface/Pub/IMessageService.cs @@ -0,0 +1,22 @@ +namespace Application.Domain; + +public interface IMessageService +{ + Task GetNoReadCount(string userId); + + #region 私聊消息 + + string GetTalkId(string userId, string otId); + Task> GetUserNoReadData(string talkId); + + Task> GetUserMessageData(string talkId, int page, int limit, + RefAsync total); + Task> GetUserMessage(string userId, int type, int page, int limit, + RefAsync total); + + Task SendMsg(string sendId, string toUser, string msg); + Task SetMsgRead(List msgIds, string userId); + Task DeleteMsgByTalkId(string talkId, string userId); + + #endregion +} \ No newline at end of file diff --git a/Service/Application.Domain/Services/Service/Pub/GameMallService.cs b/Service/Application.Domain/Services/Service/Pub/GameMallService.cs new file mode 100644 index 0000000..328d6a1 --- /dev/null +++ b/Service/Application.Domain/Services/Service/Pub/GameMallService.cs @@ -0,0 +1,40 @@ +namespace Application.Domain; + +public class GameMallService(ISqlSugarClient DbClient, IRedisCache redis) : IGameMallService, ITransient +{ + public async Task> GetMallData(int area, string type, int page, int limit, RefAsync total) + { + DateTime onTime = DateTime.Now; + string _area = area.ToString(); + var db = DbClient.AsTenant().GetConnectionWithAttr(); + return await db.Queryable().Where(it => + it.endTime > onTime && (it.areaId.Contains("0") || it.areaId.Contains(_area))) + .WhereIF(type=="0",it=>it.payType=="cowry") + .WhereIF(type=="1",it=>it.payType=="gold") + .OrderBy(it=>it.sort,OrderByType.Asc) + .ToPageListAsync(page, limit, total); + } + + public async Task GetMallInfo(string mallId) + { + var db = DbClient.AsTenant().GetConnectionWithAttr(); + return await db.Queryable().Where(it => it.mallId == mallId).SingleAsync(); + } + + public async Task AddLog(game_mall mall, string userId, int count) + { + game_mall_log log = new game_mall_log(); + log.logId = StringAssist.NewGuid; + log.mallId = mall.mallId; + log.type = mall.type; + log.pars = mall.goodsId; + log.count = count; + log.price = mall.price; + log.payType = mall.payType; + log.userId = userId; + log.addTime = DateTime.Now; + log.endTime = DateTime.Now.AddDays(30); + var db = DbClient.AsTenant().GetConnectionWithAttr(); + return await db.Insertable(log).ExecuteCommandAsync() > 0; + } +} \ No newline at end of file diff --git a/Service/Application.Domain/Services/Service/Pub/MessageService.cs b/Service/Application.Domain/Services/Service/Pub/MessageService.cs new file mode 100644 index 0000000..b4ff8b1 --- /dev/null +++ b/Service/Application.Domain/Services/Service/Pub/MessageService.cs @@ -0,0 +1,166 @@ +namespace Application.Domain; + +public class MessageService(ISqlSugarClient DbClient, IRedisCache redis) : IMessageService, ITransient +{ + public async Task GetNoReadCount(string userId) + { + string key = string.Format(UserCache.BaseCacheKeys, "Message", "Count"); + if (await redis.HExistsHashAsync(key, userId)) + { + return await redis.GetHashAsync(key, userId); + } + + int result = 0; + //普通消息 + int noRead = await GetUserNoReadDataCountByUserId(userId); + result += noRead; + //邮件详细 + //通知消息 + await redis.AddHashAsync(key, userId, result); + return result; + } + + private async Task ClearMessageCache(string userId) + { + string key = string.Format(UserCache.BaseCacheKeys, "Message", "Count"); + await redis.DelHashAsync(key, userId); + } + + #region 私信消息 + + public string GetTalkId(string userId, string otId) + { + return $"{userId}_{otId}"; + } + + private List GetTalkIdToUserId(string talkId) + { + return talkId.Split('_').ToList(); + } + + private async Task GetUserNoReadDataCountByUserId(string userId) + { + var db = DbClient.AsTenant().GetConnectionScopeWithAttr(); + return await db.Queryable() + .Where(it => it.status == 1 && it.userId == userId && it.isRead == 0).CountAsync(); + } + + public async Task> GetUserNoReadData(string talkId) + { + var db = DbClient.AsTenant().GetConnectionScopeWithAttr(); + return await db.Queryable() + .Where(it => it.status == 1 && it.talkId == talkId && it.isRead == 0) + .OrderByDescending(it => it.addTime).ToListAsync(); + } + + public async Task> GetUserMessageData(string talkId, int page, int limit, + RefAsync total) + { + var db = DbClient.AsTenant().GetConnectionScopeWithAttr(); + return await db.Queryable() + .Where(it => it.status == 1 && it.talkId == talkId) + .OrderByDescending(it => it.addTime) + .ToPageListAsync(page, limit, total); + } + + /// + /// 获取最新对话列表 + /// + /// + /// + /// + /// + /// + /// + public async Task> GetUserMessage(string userId, int type, int page, int limit, + RefAsync total) + { + var db = DbClient.AsTenant().GetConnectionScopeWithAttr(); + var talkData = await db.Queryable() + .GroupBy(it => new { it.talkId }) + .Where(it => it.userId == userId && it.status == 1) + .WhereIF(type == 0, it => it.isRead == 0) + .OrderByDescending(it => it.addTime) + .Select(it => new { mgsId = SqlFunc.AggregateMax(it.msgId) }) + .ToPageListAsync(page, limit, total); + + List result = new List(); + foreach (var item in talkData) + { + MessageView temp = new MessageView(); + var msgInfo = await db.Queryable().Where(it => it.msgId == item.mgsId).SingleAsync(); + temp.sign = msgInfo.sign; + var users = GetTalkIdToUserId(msgInfo.talkId); + temp.user = await UserModelTool.GetUserView(users[1]); + result.Add(temp); + } + + return result; + } + + public async Task SendMsg(string sendId, string toUser, string msg) + { + List adds = new List(); + unit_user_message message = new unit_user_message(); + message.msgId = SnowflakeAssist.NextId(); + message.userId = toUser; + message.sendId = sendId; + message.sign = msg; + message.isRead = 0; + message.status = 1; + message.addTime = DateTime.Now; + message.endTime = TimeExtend.GetTimeStampBySeconds(DateTime.Now.AddDays(90)); + message.talkId = GetTalkId(toUser, sendId); + adds.Add(message); + if (sendId != "0") + { + message = new unit_user_message(); + message.msgId = SnowflakeAssist.NextId(); + message.userId = sendId; + message.sendId = sendId; + message.sign = msg; + message.isRead = 1; + message.status = 1; + message.addTime = DateTime.Now; + message.endTime = TimeExtend.GetTimeStampBySeconds(DateTime.Now.AddDays(90)); + message.talkId = GetTalkId(sendId, toUser); + adds.Add(message); + } + + var db = DbClient.AsTenant().GetConnectionScopeWithAttr(); + bool result = await db.Insertable(adds).ExecuteCommandAsync() > 0; + if (result) + { + await ClearMessageCache(toUser); + } + + return result; + } + + public async Task SetMsgRead(List msgIds, string userId) + { + var db = DbClient.AsTenant().GetConnectionScopeWithAttr(); + bool result = await db.Updateable().SetColumns(it => it.isRead == 1) + .Where(it => msgIds.Contains(it.msgId)).ExecuteCommandAsync() > 0; + if (result) + { + await ClearMessageCache(userId); + } + } + + public async Task DeleteMsgByTalkId(string talkId, string userId) + { + var db = DbClient.AsTenant().GetConnectionScopeWithAttr(); + bool result = await db.Updateable().SetColumns(it => it.status == 0) + .Where(it => it.talkId == talkId && it.status == 1).ExecuteCommandAsync() > + 0; + if (result) + { + await ClearMessageCache(userId); + } + + return result; + } + + #endregion +} \ No newline at end of file diff --git a/Service/Application.Domain/Services/Service/User/UnitUserAccService.cs b/Service/Application.Domain/Services/Service/User/UnitUserAccService.cs index 5a2cac0..cd74126 100644 --- a/Service/Application.Domain/Services/Service/User/UnitUserAccService.cs +++ b/Service/Application.Domain/Services/Service/User/UnitUserAccService.cs @@ -70,9 +70,9 @@ public class UnitUserAccService(ISqlSugarClient DbClient, IRedisCache redis) : I userAccLog.name = name; userAccLog.amount = count; userAccLog.addTime = DateTime.Now; - userAccLog.endTime = DateTime.Now.AddDays(3); + userAccLog.endTime = DateTime.Now.AddDays(30); userAccLog.remark = remark; - await db.Insertable(userAccLog).ExecuteCommandAsync(); + await AddLog(userAccLog); } await DbClient.AsTenant().CommitTranAsync(); @@ -102,6 +102,11 @@ public class UnitUserAccService(ISqlSugarClient DbClient, IRedisCache redis) : I return result; } + private async Task AddLog(unit_user_acc_log log) + { + var db = DbClient.AsTenant().GetConnectionWithAttr(); + await db.Insertable(log).ExecuteCommandAsync(); + } public async Task GetUserCopperInfo(string userId) { diff --git a/Service/Application.Domain/Tool/Base/GameTool.cs b/Service/Application.Domain/Tool/Base/GameTool.cs index 7b486aa..4730921 100644 --- a/Service/Application.Domain/Tool/Base/GameTool.cs +++ b/Service/Application.Domain/Tool/Base/GameTool.cs @@ -34,8 +34,8 @@ public class GameTool public static bool AreaVerify(int area, string areas) { - List onArea = new List() { "0", area.ToString() }; - return onArea.Any(it => areas.Contains(it)); + List okArea = areas.Split(',').ToList(); + return okArea.Any(it => it == "0" || it == area.ToString()); } public static string GetCurrencyName(string payCode) diff --git a/Service/Application.Domain/Tool/ModelTool/UserModelTool.cs b/Service/Application.Domain/Tool/ModelTool/UserModelTool.cs index b96c197..c9188b0 100644 --- a/Service/Application.Domain/Tool/ModelTool/UserModelTool.cs +++ b/Service/Application.Domain/Tool/ModelTool/UserModelTool.cs @@ -11,22 +11,33 @@ public class UserModelTool public static async Task GetUserView(string userId,bool addIcon=false) { UserModel result = new UserModel(); - var userService = App.GetService(); - var userInfo = await userService.GetUserInfoByUserId(userId); - if (userInfo != null) + if (userId == "0") { - result.userNo = userInfo.userNo; - result.nick = userInfo.nick; - result.sex = userInfo.sex; - result.headImg = userInfo.headImg; - result.area = (int)userInfo.areaId; + result.userNo = "0"; + result.nick = "海精灵"; + result.sex = "女"; + result.headImg = ""; + result.area = 0; result.icon = ""; - if (addIcon)//获取图标信息 + } + else + { + var userService = App.GetService(); + var userInfo = await userService.GetUserInfoByUserId(userId); + if (userInfo != null) { + result.userNo = userInfo.userNo; + result.nick = userInfo.nick; + result.sex = userInfo.sex; + result.headImg = userInfo.headImg; + result.area = (int)userInfo.areaId; result.icon = ""; + if (addIcon)//获取图标信息 + { + result.icon = ""; + } } } - return result; } } \ No newline at end of file diff --git a/Service/Application.Web/Controllers/Map/MapController.cs b/Service/Application.Web/Controllers/Map/MapController.cs index 14359c4..f08690e 100644 --- a/Service/Application.Web/Controllers/Map/MapController.cs +++ b/Service/Application.Web/Controllers/Map/MapController.cs @@ -15,14 +15,16 @@ public class MapController : ControllerBase private readonly IGameMapService _mapService; private readonly IGameChatService _chatService; private readonly IUnitUserAttrService _attrService; + private readonly IMessageService _messageService; public MapController(IUnitUserService userService, IGameMapService mapService, IGameChatService chatService, - IUnitUserAttrService attrService) + IUnitUserAttrService attrService,IMessageService messageService) { _userService = userService; _mapService = mapService; _chatService = chatService; _attrService = attrService; + _messageService = messageService; } /// @@ -79,6 +81,7 @@ public class MapController : ControllerBase var cityInfo = await _mapService.GetCityInfo((int)mapInfo.cityId); //城市信息 var cityShow = await _mapService.GetCityShowMap(cityInfo.cityId); //城内地图 + int noReadMsg = await _messageService.GetNoReadCount(userId); #region 更新在线 string ip = ComHelper.GetClientUserIp(HttpContext); @@ -86,7 +89,7 @@ public class MapController : ControllerBase #endregion - object ret = new { mapInfo, cityInfo, npcData, chatData, cityShow, nearUser }; + object ret = new { mapInfo, cityInfo, npcData, chatData, cityShow, nearUser,noReadMsg }; return PoAction.Ok(ret); } diff --git a/Service/Application.Web/Controllers/Pub/MallController.cs b/Service/Application.Web/Controllers/Pub/MallController.cs new file mode 100644 index 0000000..b185ed3 --- /dev/null +++ b/Service/Application.Web/Controllers/Pub/MallController.cs @@ -0,0 +1,86 @@ +using Microsoft.AspNetCore.Mvc; + +namespace Application.Web.Controllers.Pub; + +/// +/// 商城接口 +/// +[Route("[controller]/[action]")] +[ApiController] +[Authorize] +public class MallController : ControllerBase +{ + private readonly IGameMallService _mallService; + private readonly IUnitUserAccService _accService; + + public MallController(IGameMallService mallService, IUnitUserAccService accService) + { + _mallService = mallService; + _accService = accService; + } + + /// + /// 获取商城列表 + /// + /// + /// + /// + [HttpGet] + public async Task GetMall(string type, int page) + { + int area = StateHelper.areaId; + string userId = StateHelper.userId; + var accInfo = await _accService.GetUserAccInfo(userId); + RefAsync total = 0; + var data = await _mallService.GetMallData(area, type, page, 10, total); + return PoAction.Ok(new { data, total = total.Value, accInfo.gold, accInfo.cowry }); + } + + /// + /// 购买物品 + /// + /// + /// + [HttpPost] + public async Task Buy([FromBody] MallBuyParms parms) + { + string userId = StateHelper.userId; + int area = StateHelper.areaId; + parms.count = parms.count < 1 ? 1 : parms.count; + var mallInfo = await _mallService.GetMallInfo(parms.id); + if (mallInfo == null) + { + return PoAction.Message("商品已下架!"); + } + + if (mallInfo.endTime < DateTime.Now) + { + return PoAction.Message("商品已下架!"); + } + + if (GameTool.AreaVerify(area, mallInfo.areaId) == false) + { + return PoAction.Message("商品已下架!"); + } + + var myAcc = await _accService.GetUserAccInfo(userId, mallInfo.payType); + long need = (long)mallInfo.price * parms.count; + if (myAcc < need) + { + return PoAction.Message($"您的{GameTool.GetCurrencyName(mallInfo.payType)}不足!"); + } + + if (await _accService.UpdateUserAcc(userId, 0, mallInfo.payType, need, nameof(AccEnum.Name.系统商城), "系统商店购买")) + { + if (await _mallService.AddLog(mallInfo, userId, parms.count)) + { + await GameBus.UpdateBag(userId, 1, mallInfo.type, mallInfo.goodsId.ToString(), parms.count, "系统商店购买"); + } + return PoAction.Ok(true); + } + else + { + return PoAction.Message("购买失败,请稍后尝试!"); + } + } +} \ No newline at end of file diff --git a/Service/Application.Web/Controllers/Pub/MessageController.cs b/Service/Application.Web/Controllers/Pub/MessageController.cs new file mode 100644 index 0000000..fa0afb3 --- /dev/null +++ b/Service/Application.Web/Controllers/Pub/MessageController.cs @@ -0,0 +1,196 @@ +using Microsoft.AspNetCore.Mvc; + +namespace Application.Web.Controllers.Pub; + +/// +/// 消息接口 +/// +[Route("[controller]/[action]")] +[ApiController] +[Authorize] +public class MessageController : ControllerBase +{ + private readonly IMessageService _messageService; + private readonly IUnitUserService _userService; + + public MessageController(IMessageService messageService, IUnitUserService userService) + { + _messageService = messageService; + _userService = userService; + } + + /// + /// 获取消息 + /// + /// + /// + /// + [HttpGet] + public async Task GetMessageData(int type, int page) + { + string userId = StateHelper.userId; + RefAsync total = 0; + if (type == 0) + { + var data = await _messageService.GetUserMessage(userId, 0, page, 10, total); + return PoAction.Ok(new { data, total = total.Value }); + } + else if (type == 1) + { + var data = await _messageService.GetUserMessage(userId, 1, page, 10, total); + return PoAction.Ok(new { data, total = total.Value }); + } + else + { + return PoAction.Ok(new { data = new List(), total = total.Value }); + } + } + + /// + /// 获取消息界面 + /// + /// + /// + [HttpGet] + public async Task GetReadInfo(int no) + { + string userId = StateHelper.userId; + UserModel user = new UserModel(); + string talkId = string.Empty; + if (no == 0) + { + user = await UserModelTool.GetUserView("0"); + talkId = _messageService.GetTalkId(userId, "0"); + } + else + { + var userInfo = await _userService.GetUserInfoByUserNo(no.ToString()); + if (userInfo == null) + { + return PoAction.Message("玩家不存在!"); + } + + talkId = _messageService.GetTalkId(userId, userInfo.userId); + user = await UserModelTool.GetUserView(userInfo.userId); + } + + + var noRead = await _messageService.GetUserNoReadData(talkId); //未读消息 + if (noRead.Count > 0) + { + List msgIds = noRead.Select(it => it.msgId).ToList(); + await _messageService.SetMsgRead(msgIds, userId); + } + + RefAsync total = 0; + var logs = await _messageService.GetUserMessageData(talkId, 1, 5, total); //消息记录 + return PoAction.Ok(new { user, data = noRead, logs }); + } + + /// + /// 发送消息 + /// + /// + /// + [HttpPost] + public async Task SendMsg([FromBody] SendMsgParms parms) + { + if (string.IsNullOrEmpty(parms.sign)) + { + return PoAction.Message("消息内容不能为空!"); + } + + string userId = StateHelper.userId; + int areaId = StateHelper.areaId; + + var toUser = await _userService.GetUserInfoByUserNo(parms.no.ToString()); + if (toUser == null) + { + return PoAction.Message("玩家不存在!", 100); + } + + if (toUser.areaId != areaId) + { + return PoAction.Message("暂不支持漫游消息!"); + } + + parms.sign = StringAssist.NoHTML(parms.sign); + if (await _messageService.SendMsg(userId, toUser.userId, parms.sign)) + { + return PoAction.Ok(true); + } + else + { + return PoAction.Message("发送失败,请稍后尝试"); + } + } + + /// + /// 聊天记录 + /// + /// + /// + /// + [HttpGet] + public async Task MessageLog(int no, int page) + { + string userId = StateHelper.userId; + UserModel user = new UserModel(); + string talkId = string.Empty; + if (no == 0) + { + user = await UserModelTool.GetUserView("0"); + talkId = _messageService.GetTalkId(userId, "0"); + } + else + { + var userInfo = await _userService.GetUserInfoByUserNo(no.ToString()); + if (userInfo == null) + { + return PoAction.Message("玩家不存在!"); + } + + talkId = _messageService.GetTalkId(userId, userInfo.userId); + user = await UserModelTool.GetUserView(userInfo.userId); + } + + RefAsync total = 0; + var logs = await _messageService.GetUserMessageData(talkId, page, 10, total); //消息记录 + return PoAction.Ok(new { user, data = logs, total = total.Value }); + } + + /// + /// 删除对话 + /// + /// + /// + [HttpGet] + public async Task DeleteMsg(int no) + { + string userId = StateHelper.userId; + string talkId = string.Empty; + if (no == 0) + { + talkId = _messageService.GetTalkId(userId, "0"); + } + else + { + var userInfo = await _userService.GetUserInfoByUserNo(no.ToString()); + if (userInfo == null) + { + return PoAction.Message("玩家不存在!"); + } + + talkId = _messageService.GetTalkId(userId, userInfo.userId); + } + + if (await _messageService.DeleteMsgByTalkId(talkId, userId)) + { + return PoAction.Ok(true); + } + else + { + return PoAction.Message("删除失败,请稍后尝试!"); + } + } +} \ No newline at end of file diff --git a/Service/Application.Web/Controllers/User/UserController.cs b/Service/Application.Web/Controllers/User/UserController.cs index b956143..a621d1b 100644 --- a/Service/Application.Web/Controllers/User/UserController.cs +++ b/Service/Application.Web/Controllers/User/UserController.cs @@ -63,6 +63,10 @@ public class UserController : ControllerBase { return PoAction.Message("用户本身!", 101); } + if (userInfo.areaId != StateHelper.areaId) + { + return PoAction.Message("玩家不存在!", 102); + } object user = new { userInfo.userNo, userInfo.nick, userInfo.sex, userInfo.sign }; var attrInfo = await _attrService.GetUserAttrModel(userInfo.userId); //基础属性 diff --git a/Service/Application.Web/Model/RequestParms/Mall/MallBuyParms.cs b/Service/Application.Web/Model/RequestParms/Mall/MallBuyParms.cs new file mode 100644 index 0000000..9280492 --- /dev/null +++ b/Service/Application.Web/Model/RequestParms/Mall/MallBuyParms.cs @@ -0,0 +1,7 @@ +namespace Application.Web; + +public class MallBuyParms +{ + public string id { get; set; } + public int count { get; set; } +} \ No newline at end of file diff --git a/Service/Application.Web/Model/RequestParms/Message/SendMsgParms.cs b/Service/Application.Web/Model/RequestParms/Message/SendMsgParms.cs new file mode 100644 index 0000000..d19040f --- /dev/null +++ b/Service/Application.Web/Model/RequestParms/Message/SendMsgParms.cs @@ -0,0 +1,7 @@ +namespace Application.Web; + +public class SendMsgParms +{ + public int no { get; set; } + public string sign { get; set; } +} \ No newline at end of file diff --git a/Web/nuxt.config.ts b/Web/nuxt.config.ts index c4c65c8..d35e6a9 100644 --- a/Web/nuxt.config.ts +++ b/Web/nuxt.config.ts @@ -58,7 +58,7 @@ export default defineNuxtConfig({ }, }, - css: ['~/assets/css/style.css'], + css: ['~/assets/css/style.css','~/assets/css/home.css'], compatibilityDate: '2024-04-03', }) diff --git a/Web/public/css/images/home/bar.gif b/Web/public/css/images/home/bar.gif new file mode 100644 index 0000000..44ebdbe Binary files /dev/null and b/Web/public/css/images/home/bar.gif differ diff --git a/Web/public/css/images/home/btn_b_gold.gif b/Web/public/css/images/home/btn_b_gold.gif new file mode 100644 index 0000000..4725603 Binary files /dev/null and b/Web/public/css/images/home/btn_b_gold.gif differ diff --git a/Web/public/css/images/home/btn_l_gray.gif b/Web/public/css/images/home/btn_l_gray.gif new file mode 100644 index 0000000..342c754 Binary files /dev/null and b/Web/public/css/images/home/btn_l_gray.gif differ diff --git a/Web/public/css/images/home/btn_m_gray.gif b/Web/public/css/images/home/btn_m_gray.gif new file mode 100644 index 0000000..f6db12d Binary files /dev/null and b/Web/public/css/images/home/btn_m_gray.gif differ diff --git a/Web/public/css/images/home/btn_s_gray.gif b/Web/public/css/images/home/btn_s_gray.gif new file mode 100644 index 0000000..5bf9b0b Binary files /dev/null and b/Web/public/css/images/home/btn_s_gray.gif differ diff --git a/Web/public/css/images/home/unit/bao.jpg b/Web/public/css/images/home/unit/bao.jpg new file mode 100644 index 0000000..5f8bd04 Binary files /dev/null and b/Web/public/css/images/home/unit/bao.jpg differ diff --git a/Web/src/assets/css/home.css b/Web/src/assets/css/home.css new file mode 100644 index 0000000..38c5593 --- /dev/null +++ b/Web/src/assets/css/home.css @@ -0,0 +1,508 @@ +.tw_icon { + max-width: 20px; + max-height: 20px; +} + +.replies_em { + max-height: 30px; + max-width: 30px; +} + +.roleitem { + margin-left: 10px; +} + +video { + max-height: 211px; + height: 211px; + background-color: black; + width: 100%; + background-repeat: no-repeat; + background-size: cover; +} + +audio { + max-width: 680px; + max-height: 350px; +} + +.icon_s { + max-width: 30px; + max-height: 30px; +} + +.clear { + height: 15px; +} + +.site-icon { + width: 16px; + height: 16px; +} + +.deep { + background: #E3EEF8; + border: 1px solid #9FC6EC; + border-left: none; + border-right: none; +} + +.nick { + color: #0051a4; + font-size: 17px; +} + +.ta-border { + font-size: 13px; + width: 98%; + height: 30px; + margin: 0 0 5px 0; + border: 1px solid #9FC6EC; +} + +.user-info { + padding: 3px 5px; +} + + .user-info a { + font-size: 13px; + padding-right: 1px; + } + + .user-info img { + margin-right: 1px; + vertical-align: middle; + } + +.user-title img { + margin-bottom: -5px; +} + +textarea { + font-size: 13px; + width: 98%; + margin: 0 0 5px 0; + border: 1px solid #9FC6EC; +} + +#footer { + padding: 5px; + background: #E3EEF8; + border-top: 1px solid #9FC6EC; +} + + #footer a { + font-size: 17px; + color: #0051A4; + } + +.ipt-txt { + height: 18px; + margin: 0 3px 0 0; + border: 1px solid #b1d5e5; +} + +.ipt-s { + width: 40px; +} + +.seperate { + margin: 0 2px; +} + +.ipt-btn-gray-s { + width: 40px; + height: 20px; + border: none; + background: url(/css/images/home/btn_s_gray.gif) no-repeat; +} + +.ipt-btn-gray-m { + width: 60px; + height: 20px; + border: none; + background: url(/css/images/home/btn_m_gray.gif) no-repeat; +} + +.ipt-btn-gray-l { + width: 80px; + height: 20px; + border: none; + background: url(/css/images/home/btn_l_gray.gif) no-repeat; +} + +.ipt-btn-gold-b { + width: 61px; + height: 21px; + font-size: 13px; + border: none; + background: url(/css/images/home/btn_b_gold.gif) no-repeat; + color: #af4c00; + margin-top: 5px; +} + +.main-nav { + padding: 1px 0 0 12px; + background-color: #4c95e7; +} + + .main-nav p { + height: 30px; + line-height: 30px; + } + + .main-nav p a { + margin: 0 7px 0 0; + color: #fff; + } + +.forum-title { + margin: 8px 0 2px; + padding: 0 5px; + height: 20px,auto; + line-height: 20px; + color: #000; + font-weight: bold; + white-space: nowrap; + text-overflow: ellipsis; + -o-text-overflow: ellipsis; + overflow: hidden; +} + +.module-title { + margin: 9px 0 0px; + padding: 0 5px; + height: 20px; + line-height: 20px; + border-bottom: 4px solid #9FC6EC; + color: #000; + font-weight: bold; + padding-bottom: 3px; +} + + .module-title a { + color: #0051A4; + } + + .module-title span { + font-weight: normal; + /* font-size: 13px; + margin: 0 0 0 10px;*/ + } + + .module-title span a { + color: #0051A4; + } + +.module-content { + line-height: 1.6; + padding: 3px 5px; + word-wrap: break-word; +} + + .module-content a { + color: #0051A4; + } + + .module-content img { + margin-right: 2px; + vertical-align: middle; + } + +.list { + padding: 0 5px; + line-height: 1.3; +} + +.module-page { + padding: 5px; +} + +.crumb-nav { + height: 22px; + padding: 0 3px; + background: #71afe3 url(/css/images/home/bar.gif) repeat-x; + line-height: 22px; + color: #fff; +} + + .crumb-nav a { + color: #fff; + } + + .crumb-nav .current { + color: #98d2ff; + } + +.bottom-crumb-nav { + padding: 0 5px; + border-top: 1px solid #eee; + line-height: 1.3; +} + +.bottom-crumb-nav-sim { + padding: 0 5px; + line-height: 1.3; +} + +.bottom-module { + padding: 5px; + line-height: 1.3; +} + +.crumb-nav-large { + height: 25px; + padding: 0 5px; + background: #71afe3 url(/css/images/home/bar.gif) repeat-x; + line-height: 25px; + color: #fff; +} + + .crumb-nav-large a { + color: #fff; + } + + .crumb-nav-large .current { + color: #98d2ff; + } + +.txt-fade { + color: #999; + font-size: 13px; +} + +.txt-bold { + font-weight: bold; +} + +.txt-slim { + font-weight: 300; +} + +.txt-emphasis { + color: #B1761A; +} + +.spacing-3 { + padding-top: 3px; + padding-bottom: 3px; +} + +.spacing-5 { + padding-top: 5px; + padding-bottom: 5px; +} + +.tab-5 { + padding-left: 5px; + padding-right: 5px; +} + +.border-btm { + border-bottom: 1px solid #E3E6EB; +} + +.tips { + background: #FFF2BD; + border-top: 1px solid #ffd56a; + border-bottom: 1px solid #ffd56a; + line-height: 1.5; + padding: 3px 5px; + color: #738698; +} + + .tips p { + padding: 0 0 0 14px; + background: url(/css/images/home/bg_module_content_list_dot_01.gif) 4px 9px no-repeat; + } + + .tips img { + padding: 0; + vertical-align: middle; + } + +.login-tips { + background: #FFF9B7; + padding: 3px 5px; + border-top: 1px solid #ccc; + border-bottom: 1px solid #ccc; + line-height: 1.5; +} + + .login-tips img { + margin-right: 2px; + vertical-align: middle; + } + + .login-tips span { + margin-left: 14px; + } + +.annc-border { + border-bottom: 1px solid #ccc; +} + +.user-title { + margin-top: 5px; + padding: 5px; + font-weight: bold; +} + +.user-stat { + padding: 5px; + background: #e4eff9; + line-height: 1.5; +} + +.write-mood { + padding: 5px; + background: #e4eff9; + line-height: 1.5; + border-top: 1px solid #9FC6EC; + border-bottom: 1px solid #9FC6EC; +} + +.tool-box { + background-color: #f0f0f0; + border-top: 1px solid #dedede; + border-bottom: 1px solid #dedede; + line-height: 1.3; + padding: 3px 5px; + color: #FFAA22; +} + +.ipt-nick { + width: 120px; +} + +.ipt-y { + width: 40px; + text-align: center; +} + +.ipt-m, .ipt-d { + width: 20px; + text-align: center; +} + +.ipt-intro { + width: 180px; +} + +.msg_tail { + text-align: right; +} + +.note { + background: #FFF9B7; + border-bottom: 1px solid #9FC6EC; + border-top: 1px solid #ffd56a; + line-height: 1.5; + padding: 3px 5px; +} + + .note p { + padding: 0 0 0 14px; + background: url(/css/images/home/bg_module_content_list_dot_01.gif) 4px 9px no-repeat; + } + + .note img { + padding: 0; + vertical-align: middle; + } + +.imgBar60 { + width: 60px; + height: 60px; +} + +.imgBarMaxHeight { + max-width: 100%; + max-height: 80px; +} + +.guess-tag { + background: coral; + color: #fff; + display: inline-block; + margin-right: 5px; + padding: 4px; + height: initial; + vertical-align: 1px; + text-align: center; + font-size: 12px; + line-height: 10px; +} + +.guess-m { + background-color: red; + color: #fff; + display: inline-block; + margin-right: 5px; + padding: 4px; + height: initial; + vertical-align: 1px; + text-align: center; + font-size: 12px; + line-height: 10px; +} + +.guess-v { + background-color: dodgerblue; + color: #fff; + display: inline-block; + margin-right: 5px; + padding: 4px; + height: initial; + vertical-align: 1px; + text-align: center; + font-size: 12px; + line-height: 10px; +} + +.conter { + width: 100%; + height: 350px; + border: 1px solid #000; + margin: 0px auto; + padding: 0px; + padding-bottom: 30px; +} + + .conter h1 { + height: 20px; + font-size: 12px; + background: #CC6600; + line-height: 20px; + text-indent: 5px; + margin-top: 0px; + } + + .conter iframe { + width: 100%; + height: 100%; + border: 0; + } + +.redBox { + background: url('/css/images/home/unit/bao.jpg') no-repeat; + width: 180px; + height: 65px; + display: inline-block; +} + +.redBox_title { + position: relative; + top: 3px; + left: 40px; + font-size: 12px; + color: white +} + +.redBox_tips { + position: relative; + top: -3px; + left: 40px; + font-size: 12px; + color: white +} \ No newline at end of file diff --git a/Web/src/assets/css/style.css b/Web/src/assets/css/style.css index 26a422e..cd475e5 100644 --- a/Web/src/assets/css/style.css +++ b/Web/src/assets/css/style.css @@ -97,7 +97,9 @@ a:focus { margin-right: 2px; vertical-align: middle; } - +.border-btm { + border-bottom: 1px solid #E3E6EB; +} .input { line-height: 30px; } diff --git a/Web/src/composables/LocalStorageHelper.ts b/Web/src/composables/LocalStorageHelper.ts index 90246ff..fd08777 100644 --- a/Web/src/composables/LocalStorageHelper.ts +++ b/Web/src/composables/LocalStorageHelper.ts @@ -7,6 +7,7 @@ export class LocalStorageHelper { } public static SetOnNpc(npcId: String) { LocalStorageExtend.Set(this.key, npcId); - } + } + } \ No newline at end of file diff --git a/Web/src/layouts/default.vue b/Web/src/layouts/default.vue index 0c906bf..527d72b 100644 --- a/Web/src/layouts/default.vue +++ b/Web/src/layouts/default.vue @@ -1,8 +1,7 @@ + \ No newline at end of file diff --git a/Web/src/pages/map/index.vue b/Web/src/pages/map/index.vue index ead271d..0dcc58e 100644 --- a/Web/src/pages/map/index.vue +++ b/Web/src/pages/map/index.vue @@ -6,7 +6,7 @@ {{ cityInfo.cityName }}·{{ mapInfo.mapName }} 刷新 任务 - 消息 + 消息{{ messageCount > 0 ? "(" + messageCount + ")" : "" }}
@@ -20,7 +20,7 @@
- {{ item.npcName }}{{ item.tips }} + {{ item.npcName }}{{ item.tips }}
@@ -91,8 +91,9 @@ const npcData = ref>([]); const chatData = ref>([]); const cityShow = ref>([]); const mapUser = ref>([]); +const messageCount = ref(0); // 城内地图显示 -const showCity = ref(false) +const showCity = ref(false); onMounted(async () => { try { @@ -113,6 +114,7 @@ const BindData = async (map: string): Promise => { chatData.value = result.data.chatData; cityShow.value = result.data.cityShow; mapUser.value = result.data.nearUser; + messageCount.value = result.data.noReadMsg; MapVent(result.data.mapInfo.near); onMap.value = mapInfo.value.mapId; console.log(result.data); diff --git a/Web/src/pages/message/index.vue b/Web/src/pages/message/index.vue index 41a40c8..ee1d4c1 100644 --- a/Web/src/pages/message/index.vue +++ b/Web/src/pages/message/index.vue @@ -1 +1,87 @@ - \ No newline at end of file + + \ No newline at end of file diff --git a/Web/src/pages/message/log.vue b/Web/src/pages/message/log.vue new file mode 100644 index 0000000..7541ca0 --- /dev/null +++ b/Web/src/pages/message/log.vue @@ -0,0 +1,60 @@ + + \ No newline at end of file diff --git a/Web/src/pages/message/read.vue b/Web/src/pages/message/read.vue new file mode 100644 index 0000000..7d38b4c --- /dev/null +++ b/Web/src/pages/message/read.vue @@ -0,0 +1,114 @@ + + \ No newline at end of file diff --git a/Web/src/pages/user/user.vue b/Web/src/pages/user/user.vue index 0c73190..08d8a51 100644 --- a/Web/src/pages/user/user.vue +++ b/Web/src/pages/user/user.vue @@ -1,6 +1,6 @@