diff --git a/OshimaServers/Service/CSBettingService.cs b/OshimaServers/Service/CSBettingService.cs index c5c0b16..0a04f6c 100644 --- a/OshimaServers/Service/CSBettingService.cs +++ b/OshimaServers/Service/CSBettingService.cs @@ -127,6 +127,67 @@ namespace Oshima.FunGame.WebAPI.Services return (header.ToString() + matches.ToString(), totalPages); } + /// + /// 获取所有比赛列表(赛程),按开始时间排序,支持分页 + /// + public static (string, int) GetAllMatches(int page, int pageSize) + { + using SQLHelper? sql = Factory.OpenFactory.GetSQLHelper(); + if (sql == null) return ("数据库连接失败。", 0); + + UpdateStatuses(sql); + + // 总数 + sql.ExecuteDataSet("SELECT COUNT(*) FROM csbetting_matches"); + int total = sql.Success ? Convert.ToInt32(sql.DataSet.Tables[0].Rows[0][0]) : 0; + int totalPages = (int)Math.Ceiling(total / (double)pageSize); + if (page > totalPages) page = totalPages; + if (page < 1) page = 1; + if (total == 0) + return ("暂无比赛赛程。", 1); + + int offset = (page - 1) * pageSize; + sql.Parameters["@offset"] = offset; + sql.Parameters["@limit"] = pageSize; + + sql.ExecuteDataSet($@" + SELECT m.id, m.team1_name, m.team2_name, m.status, m.start_time, m.stage, + e.name AS event_name, e.id AS event_id + FROM csbetting_matches m + LEFT JOIN csbetting_events e ON m.event_id = e.id + ORDER BY + CASE m.status WHEN 1 THEN 0 WHEN 0 THEN 1 ELSE 2 END, + m.start_time ASC + LIMIT @limit OFFSET @offset"); + + if (!sql.Success || sql.DataSet.Tables.Count == 0 || sql.DataSet.Tables[0].Rows.Count == 0) + return ("暂无比赛赛程。", 1); + + StringBuilder sb = new(); + sb.AppendLine($"📅 比赛赛程{(totalPages > 1 ? $"(第 {page}/{totalPages} 页)" : "")}"); + + foreach (DataRow row in sql.DataSet.Tables[0].Rows) + { + int id = Convert.ToInt32(row["id"]); + string t1 = row["team1_name"].ToString() ?? ""; + string t2 = row["team2_name"].ToString() ?? ""; + int status = Convert.ToInt32(row["status"]); + DateTime start = Convert.ToDateTime(row["start_time"]); + string stage = row["stage"]?.ToString() ?? ""; + string eventName = row["event_name"]?.ToString() ?? ""; + long eventId = Convert.ToInt64(row["event_id"]); + + string statusStr = status switch { 0 => "未开始", 1 => "进行中", 2 => "已结束", _ => "未知" }; + string matchLabel = $"{t1} vs {t2}".CreateCmdInput($"比赛详情 {id}"); + + sb.Append($"[{id}] {matchLabel}"); + if (!string.IsNullOrWhiteSpace(eventName)) sb.Append($" ({eventName.CreateCmdInput($"赛事详情 {eventId}")}{(!string.IsNullOrWhiteSpace(stage) ? $" - {stage}" : "")})"); + sb.AppendLine($" | {statusStr} | {start:MM-dd HH:mm}"); + } + + return (sb.ToString().TrimEnd(), totalPages); + } + public static string GetMatchDetail(int matchId, out int status) { status = 0; @@ -147,6 +208,7 @@ namespace Oshima.FunGame.WebAPI.Services DateTime deadline = Convert.ToDateTime(row["bet_deadline"]); string stage = row["stage"].ToString() ?? ""; string available = row["available_options"]?.ToString() ?? "[]"; + string description = row["description"].ToString() ?? ""; string result = row["result"] != DBNull.Value ? row["result"].ToString() ?? "" : ""; long winner = row["winner"] != DBNull.Value ? Convert.ToInt64(row["winner"]) : 0; decimal team1Odds = Convert.ToDecimal(row["team1_win_odds"]); @@ -176,8 +238,8 @@ namespace Oshima.FunGame.WebAPI.Services if (status == 0) { sb.AppendLine($"可用选项:"); - if (available.Contains("team1_win")) sb.AppendLine($" - {t1}胜 (x {team1Odds})"); - if (available.Contains("team2_win")) sb.AppendLine($" - {t2}胜 (x {team2Odds})"); + if (available.Contains("team1_win")) sb.AppendLine($" - 队伍1 {t1} 胜 (x {team1Odds})"); + if (available.Contains("team2_win")) sb.AppendLine($" - 队伍2 {t2} 胜 (x {team2Odds})"); if (available.Contains("score")) sb.AppendLine($" - 精确比分 (x 4)"); if (available.Contains("mvp")) sb.AppendLine($" - 赛事MVP (x 3.5)"); } @@ -188,7 +250,12 @@ namespace Oshima.FunGame.WebAPI.Services if (winner != 3) sb.AppendLine($"结果:{result}"); } - return sb.ToString().Trim(); + if (!string.IsNullOrWhiteSpace(description)) + { + sb.AppendLine($"> 📝 {description}\r\n"); + } + + return sb.ToString(); } return "数据库连接失败。"; } @@ -420,7 +487,8 @@ namespace Oshima.FunGame.WebAPI.Services return ("你还没有任何竞猜记录。", 1); StringBuilder sb = new(); - sb.AppendLine($"我的竞猜{(paged && totalPages > 1 ? $"(第 {page}/{totalPages} 页)" : "")}"); + if (mid > 0) sb.Append("你的本场竞猜记录:\r\n> "); + else sb.Append($"我的竞猜{(paged && totalPages > 1 ? $"(第 {page}/{totalPages} 页)" : "")}\r\n> "); foreach (DataRow row in sql.DataSet.Tables[0].Rows) { int matchId = Convert.ToInt32(row["match_id"]); diff --git a/OshimaWebAPI/Constant/CSBetting.sql b/OshimaWebAPI/Constant/CSBetting.sql index c9e78ac..63cc425 100644 --- a/OshimaWebAPI/Constant/CSBetting.sql +++ b/OshimaWebAPI/Constant/CSBetting.sql @@ -67,3 +67,7 @@ CREATE TABLE IF NOT EXISTS `csbetting_matches` ( ALTER TABLE `csbetting_matches` ADD COLUMN `team1_win_odds` DECIMAL(5,2) NOT NULL DEFAULT 2.50 COMMENT '队伍1胜赔率' AFTER `available_options`, ADD COLUMN `team2_win_odds` DECIMAL(5,2) NOT NULL DEFAULT 2.50 COMMENT '队伍2胜赔率' AFTER `team1_win_odds`; + +-- 为比赛表添加描述字段 +ALTER TABLE `csbetting_matches` + ADD COLUMN `description` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '比赛描述信息' AFTER `team2_win_odds`; diff --git a/OshimaWebAPI/Controllers/CSBettingController.cs b/OshimaWebAPI/Controllers/CSBettingController.cs index cd0a1b3..51443b8 100644 --- a/OshimaWebAPI/Controllers/CSBettingController.cs +++ b/OshimaWebAPI/Controllers/CSBettingController.cs @@ -44,11 +44,24 @@ namespace Oshima.FunGame.WebAPI.Controllers return new BotReply { Markdown = new MarkdownMessage { Content = content }, Keyboard = kb }; } + /// + /// 获取所有比赛赛程 + /// + [AllowAnonymous] + [HttpGet("matches")] + public BotReply GetAllMatches([FromQuery] int page = 1, [FromQuery] int pageSize = 10) + { + var (content, totalPages) = CSBettingService.GetAllMatches(page, pageSize); + KeyboardMessage kb = new(); + if (totalPages > 1) kb = new KeyboardMessage().AddPaginationRow("赛程 ", page, totalPages); + return new BotReply { Markdown = new MarkdownMessage { Content = content }, Keyboard = kb }; + } + [AllowAnonymous] [HttpGet("match/{matchId:int}")] public BotReply GetMatchDetail(int matchId) { - return new BotReply { Markdown = new MarkdownMessage { Content = CSBettingService.GetMatchDetail(matchId, out int status) + (status == 0 ? $"\r\n竞猜指令:{"竞猜".CreateCmdInput()} <比赛ID> <选项> <{General.GameplayEquilibriumConstant.InGameCurrency}数>\r\n👇🏻 点击下方按钮快速竞猜" : "")} }; + return new BotReply { Markdown = new MarkdownMessage { Content = CSBettingService.GetMatchDetail(matchId, out int status) + (status == 0 ? $"竞猜指令:{"竞猜".CreateCmdInput()} <比赛ID> <选项> <{General.GameplayEquilibriumConstant.InGameCurrency}数>\r\n👇🏻 点击下方按钮快速竞猜" : "")} }; } [AllowAnonymous] diff --git a/OshimaWebAPI/Services/CSBettingInputHandler.cs b/OshimaWebAPI/Services/CSBettingInputHandler.cs index e49e7ed..c8e6e1f 100644 --- a/OshimaWebAPI/Services/CSBettingInputHandler.cs +++ b/OshimaWebAPI/Services/CSBettingInputHandler.cs @@ -19,6 +19,8 @@ namespace Oshima.FunGame.WebAPI.Services { Content = "🎮 CS赛事竞猜帮助:\r\n" + $"✨ {"赛事列表".CreateCmdInput()} - 查看所有赛事\r\n" + + $"✨ {"比赛列表".CreateCmdInput()} - 查看所有比赛\r\n" + + $"✨ {"创建存档".CreateCmdInput()} - 创建存档后可竞猜\r\n" + $"✨ {"我的竞猜".CreateCmdInput()} - 查看我的投注记录\r\n" + $"✨ {"竞猜领奖".CreateCmdInput()} - 领取竞猜奖励\r\n" + $"✨ {"比赛详情".CreateCmdInput()} - 查看单场比赛并投注" @@ -26,6 +28,8 @@ namespace Oshima.FunGame.WebAPI.Services Keyboard = new KeyboardMessage() .AppendButtons(2, Button.CreateCmdButton("📋 赛事列表", "赛事列表"), + Button.CreateCmdButton("📅 比赛列表", "比赛列表"), + Button.CreateCmdButton("⚙️ 创建存档", "创建存档"), Button.CreateCmdButton("📜 我的竞猜", "我的竞猜"), Button.CreateCmdButton("💰 竞猜领奖", "竞猜领奖"), Button.CreateCmdButton("❓ 竞猜帮助", "竞猜帮助")) @@ -38,13 +42,33 @@ namespace Oshima.FunGame.WebAPI.Services if (e.Detail.StartsWith("赛事列表")) { int page = 1; - string[] parts = e.Detail.Split(' ', StringSplitOptions.RemoveEmptyEntries); - if (parts.Length > 1 && int.TryParse(parts[1], out int p)) page = p; - BotReply reply = BettingController.GetEventsOverview(page); // 需要Controller增加page参数的方法 + string detail = e.Detail.Replace("赛事列表", "").Trim(); + System.Text.RegularExpressions.Match match = GetFirstNumber().Match(detail); + if (match.Success && int.TryParse(match.Value, out int p)) page = p; + BotReply reply = BettingController.GetEventsOverview(page); await SendAsync(e, "CS赛事竞猜", reply); return true; } + // 赛程:显示所有比赛 + if (e.Detail.StartsWith("赛程") || e.Detail.StartsWith("比赛列表")) + { + int page = 1; + string detail = e.Detail.Replace("赛程", "").Replace("比赛列表", "").Trim(); + System.Text.RegularExpressions.Match match = GetFirstNumber().Match(detail); + if (match.Success && int.TryParse(match.Value, out int p)) page = p; + + BotReply reply = BettingController.GetAllMatches(page); + reply.Keyboard ??= new KeyboardMessage(); + reply.Keyboard.AppendButtonsWithNewRow(2, + Button.CreateCmdButton("📋 赛事列表", "赛事列表"), + Button.CreateCmdButton("📅 比赛列表", "比赛列表"), + Button.CreateCmdButton("📜 我的竞猜", "我的竞猜"), + Button.CreateCmdButton("❓ 竞猜帮助", "竞猜帮助")); + await SendAsync(e, "比赛赛程", reply); + return true; + } + if (e.Detail.StartsWith("比赛详情")) { string detail = e.Detail.Replace("比赛详情", "").Trim(); @@ -63,12 +87,14 @@ namespace Oshima.FunGame.WebAPI.Services } kb.AppendButtonsWithNewRow(2, Button.CreateCmdButton("📋 赛事列表", "赛事列表"), - Button.CreateCmdButton("💰 竞猜领奖", "竞猜领奖")); + Button.CreateCmdButton("📅 比赛列表", "比赛列表"), + Button.CreateCmdButton("💰 竞猜领奖", "竞猜领奖"), + Button.CreateCmdButton("❓ 竞猜帮助", "竞猜帮助")); reply.Keyboard = kb; BotReply reply2 = BettingController.GetMyBets(uid, mid: matchId); if (reply.Markdown != null && reply.Markdown.Content != null && !(reply2.Markdown?.Content?.Equals("你还没有任何竞猜记录。") ?? true)) { - reply.Markdown.Content = $"{reply.Markdown.Content.Trim()}\r\n你的本场竞猜记录:\r\n{reply2.Markdown.Content}"; + reply.Markdown.Content = $"{reply.Markdown.Content.Trim()}\r\n{reply2.Markdown.Content}"; } await SendAsync(e, "CS赛事竞猜", reply); } @@ -93,8 +119,8 @@ namespace Oshima.FunGame.WebAPI.Services BotReply reply = BettingController.GetEventDetail(eventId, page); reply.Keyboard ??= new KeyboardMessage(); reply.Keyboard.AppendButtonsWithNewRow(2, - Button.CreateCmdButton("🔍 比赛详情 ", "比赛详情 ", enter: false), Button.CreateCmdButton("📋 赛事列表", "赛事列表"), + Button.CreateCmdButton("📅 比赛列表", "比赛列表"), Button.CreateCmdButton("📜 我的竞猜", "我的竞猜"), Button.CreateCmdButton("💰 竞猜领奖", "竞猜领奖")); await SendAsync(e, "CS赛事竞猜", reply); @@ -110,7 +136,9 @@ namespace Oshima.FunGame.WebAPI.Services Keyboard = new KeyboardMessage() .AppendButtons(2, Button.CreateCmdButton("📋 赛事列表", "赛事列表"), - Button.CreateCmdButton("❓ 竞猜帮助", "竞猜帮助")) + Button.CreateCmdButton("📅 比赛列表", "比赛列表"), + Button.CreateCmdButton("❓ 竞猜帮助", "竞猜帮助"), + Button.CreateCmdButton("📜 我的竞猜", "我的竞猜")) }; await SendAsync(e, "CS赛事竞猜", reply); } @@ -120,13 +148,15 @@ namespace Oshima.FunGame.WebAPI.Services if (e.Detail.StartsWith("我的竞猜")) { int page = 1; - string[] parts = e.Detail.Split(' ', StringSplitOptions.RemoveEmptyEntries); - if (parts.Length > 1 && int.TryParse(parts[1], out int p)) page = p; + string detail = e.Detail.Replace("我的竞猜", "").Trim(); + System.Text.RegularExpressions.Match match = GetFirstNumber().Match(detail); + if (match.Success && int.TryParse(match.Value, out int p)) page = p; BotReply reply = BettingController.GetMyBets(uid, page); reply.Keyboard ??= new KeyboardMessage(); reply.Keyboard.AppendButtonsWithNewRow(2, Button.CreateCmdButton("💰 竞猜领奖", "竞猜领奖", enter: true), Button.CreateCmdButton("📋 赛事列表", "赛事列表"), + Button.CreateCmdButton("📅 比赛列表", "比赛列表"), Button.CreateCmdButton("❓ 竞猜帮助", "竞猜帮助")); if (reply.Markdown?.Content?.Contains("创建存档") ?? false) { @@ -142,7 +172,8 @@ namespace Oshima.FunGame.WebAPI.Services reply.Keyboard = new KeyboardMessage() .AppendButtons(2, Button.CreateCmdButton("📜 我的竞猜", "我的竞猜"), - Button.CreateCmdButton("📋 赛事列表", "赛事列表")); + Button.CreateCmdButton("📋 赛事列表", "赛事列表"), + Button.CreateCmdButton("📅 比赛列表", "比赛列表")); if (reply.Markdown?.Content?.Contains("创建存档") ?? false) { reply.Keyboard.AppendButtons(2, Button.CreateCmdButton("⚙️ 创建存档", "创建存档")); @@ -172,6 +203,7 @@ namespace Oshima.FunGame.WebAPI.Services kb.AppendButtons(2, Button.CreateCmdButton("📜 我的竞猜", "我的竞猜"), Button.CreateCmdButton("📋 赛事列表", "赛事列表"), + Button.CreateCmdButton("📅 比赛列表", "比赛列表"), Button.CreateCmdButton("❓ 竞猜帮助", "竞猜帮助")); if (reply.Markdown?.Content?.Contains("创建存档") ?? false) @@ -209,6 +241,7 @@ namespace Oshima.FunGame.WebAPI.Services reply.Keyboard = new KeyboardMessage() .AppendButtons(2, Button.CreateCmdButton("📋 赛事列表", "赛事列表"), + Button.CreateCmdButton("📅 比赛列表", "比赛列表"), Button.CreateCmdButton("⚙️ 继续结算", "结算比赛 ", enter: false)); await SendAsync(e, "CS赛事竞猜", reply); } @@ -396,5 +429,8 @@ namespace Oshima.FunGame.WebAPI.Services return false; } + + [System.Text.RegularExpressions.GeneratedRegex(@"\d+")] + private static partial System.Text.RegularExpressions.Regex GetFirstNumber(); } }