Browse Source

123131

feature/MultiClientLog
root 1 month ago
parent
commit
3dc18504e2
  1. 24
      LTEMvcApp/Controllers/MessageController.cs
  2. 47
      LTEMvcApp/Views/Home/ClientMessages.cshtml

24
LTEMvcApp/Controllers/MessageController.cs

@ -7,6 +7,7 @@ using System.Threading.Tasks;
using System.Threading;
using System.IO;
using System.Text;
using System.Linq;
namespace LTEMvcApp.Controllers
{
@ -333,15 +334,32 @@ namespace LTEMvcApp.Controllers
{
try
{
if (messages == null || messages.Count == 0)
{
_logger.LogDebug("跳过空消息列表的日志写入: {MessageType}", messageType);
return;
}
var validMessages = messages.Where(msg => !string.IsNullOrWhiteSpace(msg)).ToList();
if (validMessages.Count == 0)
{
_logger.LogDebug("跳过无效消息的日志写入: {MessageType}", messageType);
return;
}
var logBuilder = new StringBuilder();
var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
foreach (var message in messages)
foreach (var message in validMessages)
{
logBuilder.AppendLine($"[{timestamp}] [{address}] [{messageType}] {message}");
logBuilder.AppendLine(new string('-', 80));
}
await System.IO.File.AppendAllTextAsync(logFilePath, logBuilder.ToString(), Encoding.UTF8);
_logger.LogDebug("已记录 {Count} 条 {MessageType} 消息到文件: {FilePath}", messages.Count, messageType, logFilePath);
if (logBuilder.Length > 0)
{
await System.IO.File.AppendAllTextAsync(logFilePath, logBuilder.ToString(), Encoding.UTF8);
_logger.LogDebug("已记录 {Count} 条 {MessageType} 消息到文件: {FilePath}", validMessages.Count, messageType, logFilePath);
}
}
catch (Exception ex)
{

47
LTEMvcApp/Views/Home/ClientMessages.cshtml

@ -169,6 +169,7 @@
<h3 class="card-title">客户端消息队列 - @address</h3>
<div class="card-tools">
<span id="connection-status" class="badge badge-secondary">正在连接...</span>
<span id="message-status" class="badge badge-info ml-2" style="display: none;">等待消息...</span>
<button id="refreshLogFiles" class="btn btn-outline-primary btn-sm">
<i class="fas fa-sync-alt"></i> 刷新日志文件
</button>
@ -180,7 +181,14 @@
<div class="card-body p-0">
<!-- 日志文件管理面板 -->
<div class="log-files-panel">
<h5><i class="fas fa-file-alt"></i> 消息日志文件管理</h5>
<div class="d-flex justify-content-between align-items-center mb-2">
<h5><i class="fas fa-file-alt"></i> 消息日志文件管理</h5>
<div id="logStats" class="text-muted small">
<span id="totalFiles">0</span> 个文件 |
<span id="totalSize">0</span> KB |
<span id="lastUpdate">-</span>
</div>
</div>
<div id="logFilesContainer">
<div class="text-muted">正在加载日志文件列表...</div>
</div>
@ -322,8 +330,20 @@
if (response.files && response.files.length > 0) {
const filesHtml = response.files.map(file => createLogFileItemHtml(file)).join('');
$('#logFilesContainer').html(filesHtml);
// 更新统计信息
const totalSize = response.files.reduce((sum, file) => sum + file.size, 0);
const totalSizeKB = Math.round(totalSize / 1024 * 100) / 100;
const nonEmptyFiles = response.files.filter(file => file.size > 0).length;
$('#totalFiles').text(`${nonEmptyFiles}/${response.files.length}`);
$('#totalSize').text(totalSizeKB);
$('#lastUpdate').text(new Date().toLocaleTimeString());
} else {
$('#logFilesContainer').html('<div class="text-muted">暂无日志文件</div>');
$('#totalFiles').text('0/0');
$('#totalSize').text('0');
$('#lastUpdate').text(new Date().toLocaleTimeString());
}
})
.fail(function(xhr) {
@ -335,19 +355,23 @@
function createLogFileItemHtml(file) {
const sizeKB = Math.round(file.size / 1024 * 100) / 100;
const lastModified = new Date(file.lastModified).toLocaleString();
const isEmpty = file.size === 0;
const statusClass = isEmpty ? 'text-muted' : 'text-success';
const statusText = isEmpty ? '空文件' : '有数据';
return `
<div class="log-file-item">
<div class="d-flex justify-content-between align-items-start">
<div>
<strong>${file.fileName}</strong>
<span class="badge badge-${isEmpty ? 'secondary' : 'success'} ml-2">${statusText}</span>
<br>
<small class="text-muted">
类型: ${file.type} | 大小: ${sizeKB} KB | 修改时间: ${lastModified}
</small>
</div>
<div class="log-file-actions">
<button class="btn btn-outline-primary btn-sm" onclick="viewLogContent('${file.fileName}')">
<button class="btn btn-outline-primary btn-sm" onclick="viewLogContent('${file.fileName}')" ${isEmpty ? 'disabled' : ''}>
<i class="fas fa-eye"></i> 查看
</button>
<button class="btn btn-outline-warning btn-sm" onclick="clearLogFile('${file.fileName}')">
@ -440,10 +464,12 @@
function initializeEventSource() {
const source = new EventSource(`/api/message/${encodeURIComponent(address)}/stream`);
const statusBadge = $('#connection-status');
const messageStatusBadge = $('#message-status');
source.addEventListener('open', function(e) {
console.log("SSE connection opened.");
statusBadge.removeClass('badge-secondary badge-danger').addClass('badge-success').text('已连接');
messageStatusBadge.show().removeClass('badge-success badge-warning').addClass('badge-info').text('等待消息...');
// 重置数据和视图
sentMessagesData = [];
@ -456,6 +482,22 @@
const data = JSON.parse(e.data);
const isSent = data.type === 'sent';
// 更新消息状态
if (data.newCount > 0) {
messageStatusBadge.removeClass('badge-info badge-warning').addClass('badge-success')
.text(`收到 ${data.newCount} 条新${isSent ? '发送' : '接收'}消息`);
// 3秒后恢复等待状态
setTimeout(() => {
if (sentMessagesData.length === 0 && receivedMessagesData.length === 0) {
messageStatusBadge.removeClass('badge-success').addClass('badge-info').text('等待消息...');
} else {
messageStatusBadge.removeClass('badge-success').addClass('badge-warning')
.text(`总计: 发送${sentMessagesData.length}条, 接收${receivedMessagesData.length}条`);
}
}, 3000);
}
const clusterize = isSent ? sentClusterize : receivedClusterize;
const dataArray = isSent ? sentMessagesData : receivedMessagesData;
const scrollArea = isSent ? $('#sentScrollArea') : $('#receivedScrollArea');
@ -490,6 +532,7 @@
source.addEventListener('error', function(e) {
statusBadge.removeClass('badge-success').addClass('badge-danger').text('连接断开');
messageStatusBadge.hide();
console.error("SSE connection error/closed.", e);
});
}

Loading…
Cancel
Save