Files
xyou f70b061d1a
CI / Go Backend (push) Canceled after 0s
feat: 项目初始化 + 3D方块世界原型 + AI助搭系统
初始化 monorepo: Go后端(7微服务) + Unity客户端(9模块) + 启动器

HTML5原型: Three.js 3D体素世界, Perlin噪声地形, 原版材质, 22种方块

Minecraft创造模式背包: 双栏布局, 拖拽移动物品, 方向性元件引脚

AI助搭策划文档 + 客户端/服务端骨架 + Docker Compose + CI
2026-08-08 14:07:56 +08:00

154 lines
4.4 KiB
C#

using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using PCL.Core.App;
using PCL.Core.App.Essentials;
using PCL.Core.App.IoC;
using PCL.Core.App.Localization;
using PCL.Core.UI;
namespace PCL.Core.Logging;
[LifecycleService(LifecycleState.Loading, Priority = int.MaxValue)]
public class LogService : ILifecycleLogService
{
private static LifecycleContext? _context;
private static Logger? _logger;
private static bool _wrapperRegistered;
private LogService()
{
_context = Lifecycle.GetContext(this);
}
private static LifecycleContext Context => _context!;
public static Logger Logger => _logger!;
public string Identifier => "log";
public string Name => "日志服务";
public bool SupportAsync => false;
public Task StartAsync()
{
Context.Trace("正在初始化 Logger 实例");
var config = new LoggerConfiguration(Path.Combine(Basics.ExecutableDirectory, "PCL", "Log"));
_logger = new Logger(config);
Context.Trace("正在注册日志事件");
LogWrapper.OnLog += _OnWrapperLog;
_wrapperRegistered = true;
return Task.CompletedTask;
}
public async Task StopAsync()
{
if (_wrapperRegistered)
LogWrapper.OnLog -= _OnWrapperLog;
if (_logger is not null)
await _logger.DisposeAsync().ConfigureAwait(false);
}
public void OnLog(LifecycleLogItem item)
{
_LogAction(item.Level, item.ActionLevel, item.ComposeMessage(), item.Message, item.Exception);
}
private static void _LogAction(
LogLevel level,
ActionLevel actionLevel,
string formatted,
string plain,
Exception? ex)
{
if (ex is not null)
TelemetryService.ReportException(ex, plain, level);
// log
#if !TRACE
if (actionLevel != ActionLevel.TraceLog)
#endif
Logger.Log(formatted);
switch (actionLevel)
{
case <= ActionLevel.NormalLog:
return;
// hint
case ActionLevel.Hint or ActionLevel.HintErr:
HintWrapper.Show(
plain,
actionLevel == ActionLevel.Hint ? HintTheme.Info : HintTheme.Error);
break;
// message box
case ActionLevel.MsgBox or ActionLevel.MsgBoxErr:
{
var theme = actionLevel == ActionLevel.MsgBoxErr
? MsgBoxTheme.Error
: MsgBoxTheme.Info;
var caption = ex is null
? null
: Lang.Text("SystemDialog.Error.Unexpected.Title");
var message = _ComposeUserError(plain, ex);
if (actionLevel == ActionLevel.MsgBoxErr)
message = Lang.Text("SystemDialog.Error.Message.WithLogExportGuidance", message);
MsgBoxWrapper.Show(message, caption, theme, false);
break;
}
// fatal message box
case ActionLevel.MsgBoxFatal:
{
var message = Lang.Text(
"SystemDialog.Fatal.Message.WithFeedbackGuidance",
_ComposeUserError(plain, ex));
MessageBox.Show(
message,
Lang.Text("SystemDialog.Fatal.Title"),
MessageBoxButton.OK,
MessageBoxImage.Error);
break;
}
}
}
private static string _ComposeUserError(string plain, Exception? exception)
{
var summary = string.IsNullOrWhiteSpace(plain)
? Lang.Text("SystemDialog.Error.Unexpected.Message")
: plain;
return exception is null
? summary
: ExceptionDetails.Compose(summary, exception);
}
private static void _OnWrapperLog(
LogLevel level,
string msg,
string? module,
Exception? ex)
{
var thread = Thread.CurrentThread.Name ?? $"#{Environment.CurrentManagedThreadId}";
if (module is not null) module = $"[{module}] ";
var result = $"[{DateTime.Now:HH:mm:ss.fff}] [{level.PrintName()}] [{thread}] {module}{msg}";
_LogAction(
level,
level.DefaultActionLevel(),
ex is null
? result
: $"{result}\n{ex}",
msg,
ex);
}
}