From 7cf247a87381fb40231996e5d99ed31496dd4ed7 Mon Sep 17 00:00:00 2001 From: zpc Date: Fri, 28 Mar 2025 02:39:13 +0800 Subject: [PATCH] 312 --- .../ShengShengBuXi.ConsoleApp.sln | 24 + ShengShengBuXi/Hubs/AudioHub.cs | 164 +++++ ShengShengBuXi/Models/MonitorText.cs | 60 ++ ShengShengBuXi/Pages/Admin.cshtml | 683 ++++++++++++------ ShengShengBuXi/Pages/Index.cshtml | 94 ++- ShengShengBuXi/ShengShengBuXi.csproj | 3 + ShengShengBuXi/config/display.json | 25 + 7 files changed, 839 insertions(+), 214 deletions(-) create mode 100644 ShengShengBuXi.ConsoleApp/ShengShengBuXi.ConsoleApp.sln create mode 100644 ShengShengBuXi/Models/MonitorText.cs create mode 100644 ShengShengBuXi/config/display.json diff --git a/ShengShengBuXi.ConsoleApp/ShengShengBuXi.ConsoleApp.sln b/ShengShengBuXi.ConsoleApp/ShengShengBuXi.ConsoleApp.sln new file mode 100644 index 0000000..1dd4426 --- /dev/null +++ b/ShengShengBuXi.ConsoleApp/ShengShengBuXi.ConsoleApp.sln @@ -0,0 +1,24 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.2.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShengShengBuXi.ConsoleApp", "ShengShengBuXi.ConsoleApp.csproj", "{FE0A1BEA-BEF1-CDEB-D076-0AD5E44F7491}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FE0A1BEA-BEF1-CDEB-D076-0AD5E44F7491}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FE0A1BEA-BEF1-CDEB-D076-0AD5E44F7491}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FE0A1BEA-BEF1-CDEB-D076-0AD5E44F7491}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FE0A1BEA-BEF1-CDEB-D076-0AD5E44F7491}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {9BAF9C30-5594-4165-981C-6FACBF081E8D} + EndGlobalSection +EndGlobal diff --git a/ShengShengBuXi/Hubs/AudioHub.cs b/ShengShengBuXi/Hubs/AudioHub.cs index dd89499..3287b26 100644 --- a/ShengShengBuXi/Hubs/AudioHub.cs +++ b/ShengShengBuXi/Hubs/AudioHub.cs @@ -7,6 +7,7 @@ using Microsoft.Extensions.Logging; using System.IO; using System.Linq; using System.Collections.Generic; +using System.Text.Json; using Newtonsoft.Json; @@ -91,7 +92,99 @@ namespace ShengShengBuXi.Hubs /// private static readonly int _sentenceHistoryLimit = 20; + // 客户端注册信息 + private static Dictionary _clientsDict = new Dictionary(); + // 用于线程安全访问 + private static object _clientsLock = new object(); + + // 文本显示队列 + private static List _displayTextList = new List(); + private static object _displayTextListLock = new object(); + + // 监控文本列表 private static List _monitorTextList = new List(); + private static object _monitorTextListLock = new object(); + + // 配置信息 + private static string _displayConfig = "{}"; + private static object _displayConfigLock = new object(); + + // 管理员配置保存路径 + private static readonly string ConfigDirectory = Path.Combine(Directory.GetCurrentDirectory(), "config"); + private static readonly string DisplayConfigPath = Path.Combine(ConfigDirectory, "display.json"); + + // 用于初始化配置 + static AudioHub() + { + // 确保配置目录存在 + if (!Directory.Exists(ConfigDirectory)) + { + Directory.CreateDirectory(ConfigDirectory); + } + + // 加载显示配置 + LoadDisplayConfig(); + } + + // 加载显示配置 + private static void LoadDisplayConfig() + { + try + { + if (File.Exists(DisplayConfigPath)) + { + string configJson = File.ReadAllText(DisplayConfigPath); + lock (_displayConfigLock) + { + _displayConfig = configJson; + } + Console.WriteLine("加载显示配置成功"); + } + else + { + // 创建默认配置 + string defaultConfig = @"{ + ""leftContainer"": { + ""turnPageHeight"": 0.8, + ""fontSize"": ""16px"", + ""typewriterSpeed"": 50 + }, + ""rightContainer"": { + ""fontSize"": ""24px"", + ""fontWeight"": ""normal"", + ""fontStyle"": ""normal"", + ""typewriterSpeed"": 50 + }, + ""waterEffect"": { + ""enabled"": true, + ""minInterval"": 800, + ""maxInterval"": 2000, + ""simultaneousDrops"": 3, + ""fadeOutSpeed"": 0.1, + ""centerBias"": 0.5, + ""largeDrop"": { + ""probability"": 0.2, + ""size"": 9 + } + } + }"; + + lock (_displayConfigLock) + { + _displayConfig = defaultConfig; + } + + // 保存默认配置 + File.WriteAllText(DisplayConfigPath, defaultConfig); + Console.WriteLine("创建默认显示配置成功"); + } + } + catch (Exception ex) + { + Console.WriteLine($"加载显示配置出错: {ex.Message}"); + } + } + /// /// 初始化音频Hub /// @@ -1328,5 +1421,76 @@ namespace ShengShengBuXi.Hubs _logger.LogInformation($"客户端获取当前显示模式: {Context.ConnectionId}, 类型: {clientInfo.ClientType}"); return _configurationService.CurrentConfig.DisplayType; } + + /// + /// 获取显示配置 + /// + /// 显示配置的JSON字符串 + public string GetDisplayConfig() + { + lock (_displayConfigLock) + { + return _displayConfig; + } + } + + /// + /// 保存显示配置 + /// + /// 配置的JSON字符串 + /// 是否保存成功 + public async Task SaveDisplayConfig(string configJson) + { + try + { + // 尝试解析JSON以验证格式 + JsonDocument.Parse(configJson); + + // 保存到文件 + await File.WriteAllTextAsync(DisplayConfigPath, configJson); + + // 更新内存中的配置 + lock (_displayConfigLock) + { + _displayConfig = configJson; + } + + // 通知所有显示客户端 + await NotifyDisplayConfig(); + + return true; + } + catch (Exception ex) + { + Console.WriteLine($"保存显示配置出错: {ex.Message}"); + return false; + } + } + + /// + /// 通知所有显示客户端更新配置 + /// + private async Task NotifyDisplayConfig() + { + string configJson; + lock (_displayConfigLock) + { + configJson = _displayConfig; + } + + List displayClientIds = new List(); + lock (_clients) + { + displayClientIds = _clients + .Where(c => c.Value.ClientType.ToString() == "Display") + .Select(c => c.Key) + .ToList(); + } + + foreach (var clientId in displayClientIds) + { + await Clients.Client(clientId).SendAsync("ReceiveDisplayConfig", configJson); + } + } } } \ No newline at end of file diff --git a/ShengShengBuXi/Models/MonitorText.cs b/ShengShengBuXi/Models/MonitorText.cs new file mode 100644 index 0000000..61ed737 --- /dev/null +++ b/ShengShengBuXi/Models/MonitorText.cs @@ -0,0 +1,60 @@ +using System; + +namespace ShengShengBuXi.Models +{ + /// + /// 监控文本模型 + /// + public class MonitorText + { + /// + /// 唯一标识符 + /// + public Guid Id { get; set; } + + /// + /// 显示文本内容 + /// + public string Text { get; set; } + + /// + /// 创建时间 + /// + public DateTime Timestamp { get; set; } + + /// + /// 是否来自真实用户(否则为系统预设文本) + /// + public bool IsRealUser { get; set; } + + /// + /// 原始语音识别结果ID(如果有) + /// + public string RecognitionId { get; set; } + + /// + /// 文本优先级(真实用户优先显示) + /// + public int Priority => IsRealUser ? 10 : 1; + + /// + /// 是否处理过 + /// + public bool IsProcessed { get; set; } = false; + + /// + /// 处理后的文字 + /// + public string CompletedText { get; set; } + + /// + /// 录音文件路径 + /// + public string RecordingPath { get; set; } + + /// + /// 识别文字的文件的路径 + /// + public string TextFilePath { get; set; } + } +} \ No newline at end of file diff --git a/ShengShengBuXi/Pages/Admin.cshtml b/ShengShengBuXi/Pages/Admin.cshtml index 9478b49..cdb67ee 100644 --- a/ShengShengBuXi/Pages/Admin.cshtml +++ b/ShengShengBuXi/Pages/Admin.cshtml @@ -40,6 +40,9 @@ +
@@ -80,7 +83,7 @@
- +
拨号配置
@@ -244,7 +247,7 @@
- + - +
@@ -294,6 +297,128 @@ + + +
+
+
+ + + +
+ +
+
+ +
+
+
+
左侧容器配置
+
+
+
+ + +
页面高度比例,值范围0.1-1.0
+
+
+ + +
左侧历史记录字体大小,例如16px
+
+
+ + +
数值越小,打字效果速度越快
+
+
+
+
+ + +
+
+
+
右侧容器配置
+
+
+
+ + +
右侧主要显示文本的字体大小
+
+
+ + +
+
+ + +
+
+ + +
数值越小,打字效果速度越快
+
+
+
+
+ + +
+
+
+
水波纹效果配置
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
0表示随机,1表示集中在中心
+
+
+ + +
+
+ + +
+
+
+
+
+ +
+
@@ -302,20 +427,20 @@ @section Scripts { - @* *@ +@* *@ - + } \ No newline at end of file diff --git a/ShengShengBuXi/Pages/Index.cshtml b/ShengShengBuXi/Pages/Index.cshtml index 2b7f906..1000d75 100644 --- a/ShengShengBuXi/Pages/Index.cshtml +++ b/ShengShengBuXi/Pages/Index.cshtml @@ -155,10 +155,7 @@ size: 80 // 大涟漪的大小 } }, - // 预设的中文句子数组 - sentences: [ - - ] + }; let currentSentenceIndex = 0; // 当前句子索引 @@ -354,6 +351,19 @@ displayText(text); }); + // 接收显示配置的处理函数 + hubConnection.on("ReceiveDisplayConfig", function (configJson) { + console.log("收到显示配置"); + try { + const newConfig = JSON.parse(configJson); + // 更新全局配置 + updateConfig(newConfig); + console.log("已更新显示配置"); + } catch (error) { + console.error("解析显示配置失败:", error); + } + }); + // 启动连接 hubConnection.start() .then(function () { @@ -362,6 +372,19 @@ hubConnection.invoke("RegisterClient", 3, "Display") .then(function() { console.log("注册为显示客户端成功"); + // 获取显示配置 + return hubConnection.invoke("GetDisplayConfig"); + }) + .then(function(configJson) { + if(configJson) { + console.log("已获取显示配置"); + try { + const config = JSON.parse(configJson); + updateConfig(config); + } catch (error) { + console.error("解析显示配置失败:", error); + } + } // 开始接收显示文本 return hubConnection.invoke("StartReceivingDisplayText"); }) @@ -369,7 +392,7 @@ console.log("开始接收显示文本"); }) .catch(function(err) { - console.error("注册客户端失败:", err); + console.error("客户端操作失败:", err); }); }) .catch(function (err) { @@ -385,6 +408,67 @@ }); } + // 更新配置 + function updateConfig(newConfig) { + // 更新左侧容器配置 + if (newConfig.leftContainer) { + CONFIG.leftContainer.turnPageHeight = newConfig.leftContainer.turnPageHeight || CONFIG.leftContainer.turnPageHeight; + CONFIG.leftContainer.fontSize = newConfig.leftContainer.fontSize || CONFIG.leftContainer.fontSize; + CONFIG.leftContainer.typewriterSpeed = newConfig.leftContainer.typewriterSpeed || CONFIG.leftContainer.typewriterSpeed; + + // 应用字体大小到CSS + document.documentElement.style.setProperty('--left-font-size', CONFIG.leftContainer.fontSize); + } + + // 更新右侧容器配置 + if (newConfig.rightContainer) { + CONFIG.rightContainer.fontSize = newConfig.rightContainer.fontSize || CONFIG.rightContainer.fontSize; + CONFIG.rightContainer.fontWeight = newConfig.rightContainer.fontWeight || CONFIG.rightContainer.fontWeight; + CONFIG.rightContainer.fontStyle = newConfig.rightContainer.fontStyle || CONFIG.rightContainer.fontStyle; + CONFIG.rightContainer.typewriterSpeed = newConfig.rightContainer.typewriterSpeed || CONFIG.rightContainer.typewriterSpeed; + + // 应用到CSS + document.documentElement.style.setProperty('--right-font-size', CONFIG.rightContainer.fontSize); + document.documentElement.style.setProperty('--right-font-weight', CONFIG.rightContainer.fontWeight); + document.documentElement.style.setProperty('--right-font-style', CONFIG.rightContainer.fontStyle); + } + + // 更新水波纹效果配置 + if (newConfig.waterEffect) { + CONFIG.waterEffect.enabled = newConfig.waterEffect.enabled !== undefined ? newConfig.waterEffect.enabled : CONFIG.waterEffect.enabled; + CONFIG.waterEffect.minInterval = newConfig.waterEffect.minInterval || CONFIG.waterEffect.minInterval; + CONFIG.waterEffect.maxInterval = newConfig.waterEffect.maxInterval || CONFIG.waterEffect.maxInterval; + CONFIG.waterEffect.simultaneousDrops = newConfig.waterEffect.simultaneousDrops || CONFIG.waterEffect.simultaneousDrops; + CONFIG.waterEffect.fadeOutSpeed = newConfig.waterEffect.fadeOutSpeed || CONFIG.waterEffect.fadeOutSpeed; + CONFIG.waterEffect.centerBias = newConfig.waterEffect.centerBias !== undefined ? newConfig.waterEffect.centerBias : CONFIG.waterEffect.centerBias; + + if (newConfig.waterEffect.largeDrop) { + CONFIG.waterEffect.largeDrop.probability = newConfig.waterEffect.largeDrop.probability !== undefined ? + newConfig.waterEffect.largeDrop.probability : CONFIG.waterEffect.largeDrop.probability; + CONFIG.waterEffect.largeDrop.size = newConfig.waterEffect.largeDrop.size || CONFIG.waterEffect.largeDrop.size; + } + + // 应用水波纹效果配置 + if ($('.water-effect').data('ripples')) { + // 如果ripples已初始化,先销毁 + $('.water-effect').ripples('destroy'); + } + + if (CONFIG.waterEffect.enabled) { + $('.water-effect').show(); + $('.water-effect').ripples({ + resolution: 1024, + dropRadius: 1.5, + perturbance: 0 + }); + } else { + $('.water-effect').hide(); + } + } + + console.log("配置已更新:", CONFIG); + } + // 页面加载完成后初始化 $(window).ready(function () { $('#magazine').turn({ diff --git a/ShengShengBuXi/ShengShengBuXi.csproj b/ShengShengBuXi/ShengShengBuXi.csproj index 1cb67e9..0b15afa 100644 --- a/ShengShengBuXi/ShengShengBuXi.csproj +++ b/ShengShengBuXi/ShengShengBuXi.csproj @@ -10,6 +10,9 @@ + + Always + PreserveNewest diff --git a/ShengShengBuXi/config/display.json b/ShengShengBuXi/config/display.json new file mode 100644 index 0000000..3b2c76a --- /dev/null +++ b/ShengShengBuXi/config/display.json @@ -0,0 +1,25 @@ +{ + "leftContainer": { + "turnPageHeight": 0.55, + "fontSize": "16px", + "typewriterSpeed": 50 + }, + "rightContainer": { + "fontSize": "40px", + "fontWeight": "700", + "fontStyle": "italic", + "typewriterSpeed": 330 + }, + "waterEffect": { + "enabled": true, + "minInterval": 1600, + "maxInterval": 8000, + "simultaneousDrops": 2, + "fadeOutSpeed": 2000, + "centerBias": 0.6, + "largeDrop": { + "probability": 0.2, + "size": 80 + } + } +} \ No newline at end of file