新增RemoteWebApp项目

This commit is contained in:
Diego
2025-07-17 23:41:11 +08:00
parent 788a8b670d
commit 4707ce6d58
13 changed files with 203 additions and 48 deletions

View File

@@ -51,7 +51,7 @@ namespace Photino.Blazor
app.Initialize(sp, RootComponents);
return app;
}
public PhotinoBlazorApp Build(IServiceProvider serviceProvider = null)
public PhotinoBlazorApp Build(IServiceProvider serviceProvider)
{
// register root components with DI container
// Services.AddSingleton(RootComponents);

View File

@@ -1,9 +1,9 @@
<Project>
<PropertyGroup>
<PluginVersion>10.9.40</PluginVersion>
<ProPluginVersion>10.9.40</ProPluginVersion>
<DefaultVersion>10.9.40</DefaultVersion>
<PluginVersion>10.9.41</PluginVersion>
<ProPluginVersion>10.9.41</ProPluginVersion>
<DefaultVersion>10.9.41</DefaultVersion>
<AuthenticationVersion>2.9.18</AuthenticationVersion>
<SourceGeneratorVersion>10.9.18</SourceGeneratorVersion>
<NET8Version>8.0.18</NET8Version>

View File

@@ -77,7 +77,7 @@ internal sealed class Program
hybridApp.MainWindow.SetUseOsDefaultLocation(false);
hybridApp.MainWindow.SetUseOsDefaultSize(false);
hybridApp.MainWindow.SetSize(new System.Drawing.Size(1920, 1080));
hybridApp.MainWindow.SetTitle("ThingsGateway.Hybrid");
hybridApp.MainWindow.SetTitle("ThingsGateway.Debug.Photino");
hybridApp.MainWindow.SetIconFile("favicon.ico");

View File

@@ -12,7 +12,7 @@
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.2">
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

View File

@@ -103,12 +103,12 @@ internal sealed class Program
var hybridApp = builder.Build(app.Services);
hybridApp.MainWindow.ContextMenuEnabled = false;
hybridApp.MainWindow.DevToolsEnabled = true;
hybridApp.MainWindow.DevToolsEnabled = false;
hybridApp.MainWindow.GrantBrowserPermissions = true;
hybridApp.MainWindow.SetUseOsDefaultLocation(false);
hybridApp.MainWindow.SetUseOsDefaultSize(false);
hybridApp.MainWindow.SetSize(new System.Drawing.Size(1920, 1080));
hybridApp.MainWindow.SetTitle("ThingsGateway.Hybrid");
hybridApp.MainWindow.SetTitle("ThingsGateway.Photino");
hybridApp.MainWindow.SetIconFile("favicon.ico");
AppDomain.CurrentDomain.UnhandledException += (sender, error) =>

View File

@@ -4,7 +4,7 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
<title>ThingsGateway.Hybrid</title>
<title>ThingsGateway.Photino</title>
<base href="/" />
<link rel="icon" href="favicon.ico" type="image/x-icon">

View File

@@ -0,0 +1,61 @@
//------------------------------------------------------------------------------
// 此代码版权声明为全文件覆盖,如有原作者特别声明,会在下方手动补充
// 此代码版权除特别声明外的代码归作者本人Diego所有
// 源代码使用协议遵循本仓库的开源协议及附加协议
// Gitee源代码仓库https://gitee.com/diego2098/ThingsGateway
// Github源代码仓库https://github.com/kimdiego2098/ThingsGateway
// 使用文档https://thingsgateway.cn/
// QQ群605534569
//------------------------------------------------------------------------------
using Photino.NET;
using System.Text;
using System.Xml;
namespace ThingsGateway.Server;
internal sealed class Program
{
[STAThread]
private static void Main(string[] args)
{
//当前工作目录设为程序集的基目录
System.IO.Directory.SetCurrentDirectory(AppContext.BaseDirectory);
// 增加中文编码支持
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
var doc = new XmlDocument();
doc.Load("appsettings.xml");
string? url = doc.SelectSingleNode("/settings/urls")?.InnerText;
string? title = doc.SelectSingleNode("/settings/windowTitle")?.InnerText;
var window = new PhotinoWindow();
window.Load(url); // 👈 直接加载远程地址
window.ContextMenuEnabled = false;
window.DevToolsEnabled = false;
window.GrantBrowserPermissions = true;
window.SetUseOsDefaultLocation(false);
window.SetUseOsDefaultSize(false);
window.SetSize(new System.Drawing.Size(1920, 1080));
window.SetTitle(title);
window.SetIconFile("favicon.ico");
AppDomain.CurrentDomain.UnhandledException += (sender, error) =>
{
};
window.WindowClosing += (sender, e) =>
{
return false;
};
window.WaitForClose();
Thread.Sleep(2000);
}
}

View File

@@ -0,0 +1,57 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<Import Project="..\Version.props" />
<ItemGroup>
<PackageReference Include="Photino.NET" Version="4.0.16" />
</ItemGroup>
<ItemGroup>
<!--<Content Include="..\ThingsGateway.Server\wwwroot\favicon.ico" Link="wwwroot\favicon.ico">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="..\ThingsGateway.Server\wwwroot\favicon.png" Link="wwwroot\favicon.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>-->
<Content Include="appsettings.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<None Update="favicon.ico">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<PropertyGroup>
<TargetFrameworks>net8.0;net9.0;</TargetFrameworks>
<CustomTargetFramework>$(TargetFramework)</CustomTargetFramework>
<OutputType>WinExe</OutputType>
<OpenApiGenerateDocuments>false</OpenApiGenerateDocuments>
<SatelliteResourceLanguages>zh-Hans;en-US</SatelliteResourceLanguages>
<PublishReadyToRunComposite>true</PublishReadyToRunComposite>
<ApplicationIcon>favicon.ico</ApplicationIcon>
<!--<PublishAot>true</PublishAot>-->
<CETCompat>false</CETCompat>
<PublishAot>true</PublishAot>
<DebugType>none</DebugType>
<EmbedAllSources>false</EmbedAllSources>
<EmitDebugInformation>false</EmitDebugInformation>
<!--动态适用GC-->
<GarbageCollectionAdaptationMode>1</GarbageCollectionAdaptationMode>
<!--使用工作站GC-->
<!--<ServerGarbageCollection>true</ServerGarbageCollection>-->
<!--<PlatformTarget>x86</PlatformTarget>-->
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<settings>
<urls>http://localhost:5000</urls>
<windowTitle>ThingsGateway.RemoteWebApp</windowTitle>
</settings>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -21,14 +21,36 @@
<link rel="apple-touch-icon" href="favicon.png">
<base href="/" />
<title>ThingsGateway</title>
<link rel="stylesheet" href=@($"_content/BootstrapBlazor.FontAwesome/css/font-awesome.min.css?v={this.GetType().Assembly.GetName().Version}") />
@{
#if !NET8_0
}
<link rel="stylesheet" href=@(Assets[$"_content/BootstrapBlazor.FontAwesome/css/font-awesome.min.css"]) />
<link rel="stylesheet" href=@(Assets[$"_content/BootstrapBlazor/css/bootstrap.blazor.bundle.min.css"]) />
<link rel="stylesheet" href=@(Assets[$"_content/BootstrapBlazor/css/motronic.min.css"]) />
<link rel="stylesheet" href=@(Assets[$"ThingsGateway.Server.styles.css"]) />
<link rel="stylesheet" href=@(Assets[$"{WebsiteConst.DefaultResourceUrl}css/site.css"]) />
<link rel="stylesheet" href=@(Assets[$"{WebsiteConst.DefaultResourceUrl}css/devui.css"]) />
<ImportMap />
@{
#else
}
<link rel="stylesheet" href=@($"_content/BootstrapBlazor.FontAwesome/css/font-awesome.min.css?v={this.GetType().Assembly.GetName().Version}") />
<link rel="stylesheet" href=@($"_content/BootstrapBlazor/css/bootstrap.blazor.bundle.min.css?v={this.GetType().Assembly.GetName().Version}") />
<link rel="stylesheet" href=@($"_content/BootstrapBlazor/css/motronic.min.css?v={this.GetType().Assembly.GetName().Version}") />
<link rel="stylesheet" href=@($"ThingsGateway.Server.styles.css?v={this.GetType().Assembly.GetName().Version}") />
<link rel="stylesheet" href=@($"{WebsiteConst.DefaultResourceUrl}css/site.css?v={this.GetType().Assembly.GetName().Version}") />
<link rel="stylesheet" href=@($"{WebsiteConst.DefaultResourceUrl}css/devui.css?v={this.GetType().Assembly.GetName().Version}") />
@{
#endif
}
@* <script src=@($"{WebsiteConst.DefaultResourceUrl}js/theme.js") type="module"></script><!-- 初始主题 --> *@
<!-- PWA Manifest -->
<link rel="stylesheet" href=@($"{WebsiteConst.DefaultResourceUrl}css/devui.css?v={this.GetType().Assembly.GetName().Version}") />
<link rel="manifest" href="./manifest.json" />
<HeadOutlet @rendermode="new InteractiveServerRenderMode(false)" />
</head>
@@ -40,47 +62,13 @@
<BlazorReconnector @rendermode="new InteractiveServerRenderMode(false)" />
<script src=@($"_content/BootstrapBlazor/js/bootstrap.blazor.bundle.min.js?v={this.GetType().Assembly.GetName().Version}")></script>
<script src=@($"{WebsiteConst.DefaultResourceUrl}js/culture.js?v={this.GetType().Assembly.GetName().Version}")></script>
<script src="_content/BootstrapBlazor/js/bootstrap.blazor.bundle.min.js"></script>
<script src=@($"{WebsiteConst.DefaultResourceUrl}js/culture.js")></script>
<script src="_framework/blazor.web.js"></script>
<!-- PWA Service Worker -->
<script type="text/javascript">'serviceWorker' in navigator && navigator.serviceWorker.register('./service-worker.js')</script>
<script>
let installPromptTriggered = false;
function getCookie(name) {
const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
return match ? match[2] : null;
}
function hasShownInstallPrompt() {
return getCookie("tgPWAInstallPromptShown") === "true";
}
function markInstallPromptShown() {
document.cookie = "tgPWAInstallPromptShown=true; max-age=31536000; path=/";
}
window.addEventListener('beforeinstallprompt', (e) => {
e.preventDefault();
if (!hasShownInstallPrompt() && !installPromptTriggered) {
installPromptTriggered = true;
setTimeout(() => {
e.prompt()
.then(() => e.userChoice)
.then(choiceResult => {
markInstallPromptShown();
})
.catch(err => {
});
}, 2000); // 延迟 2 秒提示
} else {
// console.log("已提示过安装,不再弹出");
}
});
</script>
<script src="pwa-install.js"></script>
</body>

View File

@@ -0,0 +1,10 @@

@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using static Microsoft.AspNetCore.Components.Web.RenderMode
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using System.Net.Http
@using System.Net.Http.Json

View File

@@ -0,0 +1,34 @@
let installPromptTriggered = false;
function getCookie(name) {
const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
return match ? match[2] : null;
}
function hasShownInstallPrompt() {
return getCookie("tgPWAInstallPromptShown") === "true";
}
function markInstallPromptShown() {
document.cookie = "tgPWAInstallPromptShown=true; max-age=31536000; path=/";
}
window.addEventListener('beforeinstallprompt', (e) => {
e.preventDefault();
if (!hasShownInstallPrompt() && !installPromptTriggered) {
installPromptTriggered = true;
setTimeout(() => {
e.prompt()
.then(() => e.userChoice)
.then(choiceResult => {
markInstallPromptShown();
})
.catch(err => {
// 可选错误处理
});
}, 2000); // 延迟 2 秒提示
} else {
// console.log("已提示过安装,不再弹出");
}
});