- 新增二维码生成端点,自动检测局域网 IP,前端扫一扫即可打开网站 - 提取 IApiResponse 接口,ServiceRequestBinder 支持强类型请求 DTO 绑定 - FileStream 端点迁移至 AppEndpoints 统一注册,管道支持 FileStreamResponse 原始文件返回 - 文件库端点全面使用 MapGet<TService, TRequest> 泛型注册 - 移除 Avalonia-API/Extensions 中的业务端点文件,统一由 Services 层管理
47 lines
1.7 KiB
C#
47 lines
1.7 KiB
C#
using Avalonia_Common.Core;
|
|
using Avalonia_Services.Core;
|
|
using QRCoder;
|
|
using System.Net;
|
|
using System.Net.NetworkInformation;
|
|
using System.Net.Sockets;
|
|
|
|
namespace Avalonia_Services.Services.QrCode
|
|
{
|
|
public sealed class QrCodeService : IQrCodeService
|
|
{
|
|
public Task<object?> GenerateQrCodeAsync(ServiceEndpointContext ctx)
|
|
{
|
|
var ip = GetLanIpAddress();
|
|
if (ip is null)
|
|
throw new InvalidOperationException("无法获取局域网IP地址");
|
|
|
|
var url = $"http://{ip}:5206";
|
|
var base64 = GeneratePngBase64(url);
|
|
return Task.FromResult<object?>(ResponseHelper.Ok(new QrCodeResponse(url, base64)));
|
|
}
|
|
|
|
private static string GeneratePngBase64(string content)
|
|
{
|
|
using var generator = new QRCodeGenerator();
|
|
using var data = generator.CreateQrCode(content, QRCodeGenerator.ECCLevel.Q);
|
|
using var png = new PngByteQRCode(data);
|
|
var bytes = png.GetGraphic(20);
|
|
return $"data:image/png;base64,{Convert.ToBase64String(bytes)}";
|
|
}
|
|
|
|
private static string? GetLanIpAddress()
|
|
{
|
|
return NetworkInterface.GetAllNetworkInterfaces()
|
|
.Where(ni => ni.OperationalStatus == OperationalStatus.Up
|
|
&& ni.NetworkInterfaceType != NetworkInterfaceType.Loopback)
|
|
.SelectMany(ni => ni.GetIPProperties().UnicastAddresses)
|
|
.Select(ua => ua.Address)
|
|
.FirstOrDefault(ip =>
|
|
ip.AddressFamily == AddressFamily.InterNetwork
|
|
&& !IPAddress.IsLoopback(ip)
|
|
&& !ip.ToString().StartsWith("169.254"))
|
|
?.ToString();
|
|
}
|
|
}
|
|
}
|