正在显示
55 个修改的文件
包含
3083 行增加
和
0 行删除
.gitignore
0 → 100644
| 1 | +## 忽略编译输出 | ||
| 2 | +bin/ | ||
| 3 | +obj/ | ||
| 4 | +[Bb]uild/ | ||
| 5 | +[Bb]in/ | ||
| 6 | +[Oo]bj/ | ||
| 7 | + | ||
| 8 | +## Visual Studio 相关 | ||
| 9 | +.vs/ | ||
| 10 | +*.user | ||
| 11 | +*.suo | ||
| 12 | +*.userosscache | ||
| 13 | +*.sln.docstates | ||
| 14 | + | ||
| 15 | +## Rider / JetBrains | ||
| 16 | +.idea/ | ||
| 17 | +*.sln.iml | ||
| 18 | + | ||
| 19 | +## MAUI 平台输出 | ||
| 20 | +# Android | ||
| 21 | +*.apk | ||
| 22 | +*.aab | ||
| 23 | +platforms/android/ | ||
| 24 | +**/bin/Debug/ | ||
| 25 | +**/bin/Release/ | ||
| 26 | + | ||
| 27 | +# iOS / MacCatalyst | ||
| 28 | +*.app | ||
| 29 | +*.ipa | ||
| 30 | +*.dSYM | ||
| 31 | +platforms/ios/ | ||
| 32 | +platforms/maccatalyst/ | ||
| 33 | + | ||
| 34 | +# Windows | ||
| 35 | +*.appx | ||
| 36 | +*.appxbundle | ||
| 37 | +*.msix | ||
| 38 | +*.msixbundle | ||
| 39 | +AppPackages/ | ||
| 40 | + | ||
| 41 | +## 日志文件 | ||
| 42 | +*.log | ||
| 43 | + | ||
| 44 | +## 临时文件 | ||
| 45 | +~* | ||
| 46 | +*.tmp | ||
| 47 | +*.temp | ||
| 48 | + | ||
| 49 | +## 备份文件 | ||
| 50 | +*.bak | ||
| 51 | +*.backup | ||
| 52 | + | ||
| 53 | +## NuGet | ||
| 54 | +*.nupkg | ||
| 55 | +*.snupkg | ||
| 56 | +# 包缓存目录 | ||
| 57 | +packages/ | ||
| 58 | +# NuGet 本地源 | ||
| 59 | +.nuget/ | ||
| 60 | + | ||
| 61 | +## 发布/打包文件 | ||
| 62 | +publish/ | ||
| 63 | +artifacts/ | ||
| 64 | + | ||
| 65 | +## 配置文件(用户环境相关) | ||
| 66 | +appsettings.Development.json | ||
| 67 | +appsettings.Local.json | ||
| 68 | +local.settings.json | ||
| 69 | + | ||
| 70 | +## 其他 | ||
| 71 | +# macOS | ||
| 72 | +.DS_Store | ||
| 73 | +# Windows 缩略图 | ||
| 74 | +Thumbs.db |
App.xaml
0 → 100644
| 1 | +<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui" | ||
| 2 | + xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | ||
| 3 | + x:Class="IndustrialControl.App"> | ||
| 4 | + <Application.Resources> | ||
| 5 | + <ResourceDictionary> | ||
| 6 | + <Style x:Key="BlueCardStyle" TargetType="Frame"> | ||
| 7 | + <Setter Property="CornerRadius" Value="12"/> | ||
| 8 | + <Setter Property="Padding" Value="15"/> | ||
| 9 | + <Setter Property="HasShadow" Value="True"/> | ||
| 10 | + <Setter Property="BackgroundColor" Value="#1976D2"/> | ||
| 11 | + <Setter Property="VisualStateManager.VisualStateGroups"> | ||
| 12 | + <Setter.Value> | ||
| 13 | + <VisualStateGroupList> | ||
| 14 | + <VisualStateGroup Name="CommonStates"> | ||
| 15 | + <VisualState Name="Normal"> | ||
| 16 | + <VisualState.Setters> | ||
| 17 | + <Setter Property="BackgroundColor" Value="#1976D2"/> | ||
| 18 | + </VisualState.Setters> | ||
| 19 | + </VisualState> | ||
| 20 | + <VisualState Name="Pressed"> | ||
| 21 | + <VisualState.Setters> | ||
| 22 | + <Setter Property="BackgroundColor" Value="#2196F3"/> | ||
| 23 | + </VisualState.Setters> | ||
| 24 | + </VisualState> | ||
| 25 | + </VisualStateGroup> | ||
| 26 | + </VisualStateGroupList> | ||
| 27 | + </Setter.Value> | ||
| 28 | + </Setter> | ||
| 29 | + </Style> | ||
| 30 | + | ||
| 31 | + </ResourceDictionary> | ||
| 32 | + </Application.Resources> | ||
| 33 | +</Application> |
App.xaml.cs
0 → 100644
AppShell.xaml
0 → 100644
AppShell.xaml.cs
0 → 100644
| 1 | +using Microsoft.Extensions.DependencyInjection; | ||
| 2 | +using Microsoft.Maui.Controls; | ||
| 3 | + | ||
| 4 | +namespace IndustrialControl | ||
| 5 | +{ | ||
| 6 | + public partial class AppShell : Shell | ||
| 7 | + { | ||
| 8 | + public AppShell(IServiceProvider sp) | ||
| 9 | + { | ||
| 10 | + InitializeComponent(); | ||
| 11 | + | ||
| 12 | + // Tab: 登录 | ||
| 13 | + var login = new ShellContent | ||
| 14 | + { | ||
| 15 | + Title = "登录", | ||
| 16 | + Route = "Login", | ||
| 17 | + ContentTemplate = new DataTemplate(() => sp.GetRequiredService<Pages.LoginPage>()) | ||
| 18 | + }; | ||
| 19 | + | ||
| 20 | + // Tab: 主页 | ||
| 21 | + var home = new ShellContent | ||
| 22 | + { | ||
| 23 | + Title = "主页", | ||
| 24 | + Route = "Home", | ||
| 25 | + ContentTemplate = new DataTemplate(() => sp.GetRequiredService<Pages.HomePage>()) | ||
| 26 | + }; | ||
| 27 | + | ||
| 28 | + // Tab: 管理员 | ||
| 29 | + var admin = new ShellContent | ||
| 30 | + { | ||
| 31 | + Title = "管理员", | ||
| 32 | + Route = "Admin", | ||
| 33 | + ContentTemplate = new DataTemplate(() => sp.GetRequiredService<Pages.AdminPage>()) | ||
| 34 | + }; | ||
| 35 | + | ||
| 36 | + // Tab: 日志 | ||
| 37 | + var logs = new ShellContent | ||
| 38 | + { | ||
| 39 | + Title = "日志", | ||
| 40 | + Route = "Logs", | ||
| 41 | + ContentTemplate = new DataTemplate(() => sp.GetRequiredService<Pages.LogsPage>()) | ||
| 42 | + }; | ||
| 43 | + | ||
| 44 | + var tabBar = new TabBar(); | ||
| 45 | + tabBar.Items.Add(login); | ||
| 46 | + tabBar.Items.Add(home); | ||
| 47 | + tabBar.Items.Add(admin); | ||
| 48 | + tabBar.Items.Add(logs); | ||
| 49 | + | ||
| 50 | + Items.Add(tabBar); | ||
| 51 | + | ||
| 52 | + Routing.RegisterRoute(nameof(Pages.InboundMaterialPage), typeof(Pages.InboundMaterialPage)); | ||
| 53 | + Routing.RegisterRoute(nameof(Pages.InboundProductionPage), typeof(Pages.InboundProductionPage)); | ||
| 54 | + Routing.RegisterRoute(nameof(Pages.OutboundMaterialPage), typeof(Pages.OutboundMaterialPage)); | ||
| 55 | + Routing.RegisterRoute(nameof(Pages.OutboundFinishedPage), typeof(Pages.OutboundFinishedPage)); | ||
| 56 | + } | ||
| 57 | + } | ||
| 58 | +} |
IndustrialControl.csproj
0 → 100644
| 1 | +<Project Sdk="Microsoft.NET.Sdk"> | ||
| 2 | + | ||
| 3 | + <PropertyGroup> | ||
| 4 | + <TargetFrameworks>net8.0-android;net8.0-ios;net8.0-maccatalyst</TargetFrameworks> | ||
| 5 | + <TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-windows10.0.19041.0</TargetFrameworks> | ||
| 6 | + <!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET --> | ||
| 7 | + <!-- <TargetFrameworks>$(TargetFrameworks);net8.0-tizen</TargetFrameworks> --> | ||
| 8 | + | ||
| 9 | + <!-- Note for MacCatalyst: | ||
| 10 | + The default runtime is maccatalyst-x64, except in Release config, in which case the default is maccatalyst-x64;maccatalyst-arm64. | ||
| 11 | + When specifying both architectures, use the plural <RuntimeIdentifiers> instead of the singular <RuntimeIdentifier>. | ||
| 12 | + The Mac App Store will NOT accept apps with ONLY maccatalyst-arm64 indicated; | ||
| 13 | + either BOTH runtimes must be indicated or ONLY macatalyst-x64. --> | ||
| 14 | + <!-- For example: <RuntimeIdentifiers>maccatalyst-x64;maccatalyst-arm64</RuntimeIdentifiers> --> | ||
| 15 | + | ||
| 16 | + <OutputType>Exe</OutputType> | ||
| 17 | + <RootNamespace>IndustrialControl</RootNamespace> | ||
| 18 | + <UseMaui>true</UseMaui> | ||
| 19 | + <SingleProject>true</SingleProject> | ||
| 20 | + <ImplicitUsings>enable</ImplicitUsings> | ||
| 21 | + <Nullable>enable</Nullable> | ||
| 22 | + | ||
| 23 | + <!-- Display name --> | ||
| 24 | + <ApplicationTitle>IndustrialControl</ApplicationTitle> | ||
| 25 | + | ||
| 26 | + <!-- App Identifier --> | ||
| 27 | + <ApplicationId>com.companyname.industrialcontrol</ApplicationId> | ||
| 28 | + | ||
| 29 | + <!-- Versions --> | ||
| 30 | + <ApplicationDisplayVersion>1.0</ApplicationDisplayVersion> | ||
| 31 | + <ApplicationVersion>1</ApplicationVersion> | ||
| 32 | + | ||
| 33 | + <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">11.0</SupportedOSPlatformVersion> | ||
| 34 | + <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">13.1</SupportedOSPlatformVersion> | ||
| 35 | + <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion> | ||
| 36 | + <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion> | ||
| 37 | + <TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion> | ||
| 38 | + <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion> | ||
| 39 | + </PropertyGroup> | ||
| 40 | + | ||
| 41 | + <ItemGroup> | ||
| 42 | + <!-- App Icon --> | ||
| 43 | + <MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" /> | ||
| 44 | + | ||
| 45 | + <!-- Splash Screen --> | ||
| 46 | + <MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" /> | ||
| 47 | + | ||
| 48 | + <!-- Images --> | ||
| 49 | + <MauiImage Include="Resources\Images\*" /> | ||
| 50 | + <MauiImage Update="Resources\Images\dotnet_bot.png" Resize="True" BaseSize="300,185" /> | ||
| 51 | + | ||
| 52 | + <!-- Custom Fonts --> | ||
| 53 | + <MauiFont Include="Resources\Fonts\*" /> | ||
| 54 | + | ||
| 55 | + <!-- Raw Assets (also remove the "Resources\Raw" prefix) --> | ||
| 56 | + <MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" /> | ||
| 57 | + </ItemGroup> | ||
| 58 | + | ||
| 59 | + <ItemGroup> | ||
| 60 | + <PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" /> | ||
| 61 | + <PackageReference Include="Microsoft.Maui.Controls" Version="8.0.0"/> | ||
| 62 | + <PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="8.0.0" /> | ||
| 63 | + <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.1" /> | ||
| 64 | + </ItemGroup> | ||
| 65 | + | ||
| 66 | + <ItemGroup> | ||
| 67 | + <MauiXaml Update="App.xaml"> | ||
| 68 | + <Generator>MSBuild:Compile</Generator> | ||
| 69 | + </MauiXaml> | ||
| 70 | + <MauiXaml Update="Pages\AdminPage.xaml"> | ||
| 71 | + <Generator>MSBuild:Compile</Generator> | ||
| 72 | + </MauiXaml> | ||
| 73 | + <MauiXaml Update="Pages\HomePage.xaml"> | ||
| 74 | + <Generator>MSBuild:Compile</Generator> | ||
| 75 | + </MauiXaml> | ||
| 76 | + <MauiXaml Update="Pages\InboundMaterialPage.xaml"> | ||
| 77 | + <Generator>MSBuild:Compile</Generator> | ||
| 78 | + </MauiXaml> | ||
| 79 | + <MauiXaml Update="Pages\InboundProductionPage.xaml"> | ||
| 80 | + <Generator>MSBuild:Compile</Generator> | ||
| 81 | + </MauiXaml> | ||
| 82 | + <MauiXaml Update="Pages\LoginPage.xaml"> | ||
| 83 | + <Generator>MSBuild:Compile</Generator> | ||
| 84 | + </MauiXaml> | ||
| 85 | + <MauiXaml Update="Pages\LogsPage.xaml"> | ||
| 86 | + <Generator>MSBuild:Compile</Generator> | ||
| 87 | + </MauiXaml> | ||
| 88 | + <MauiXaml Update="Pages\OutboundFinishedPage.xaml"> | ||
| 89 | + <Generator>MSBuild:Compile</Generator> | ||
| 90 | + </MauiXaml> | ||
| 91 | + <MauiXaml Update="Pages\OutboundMaterialPage.xaml"> | ||
| 92 | + <Generator>MSBuild:Compile</Generator> | ||
| 93 | + </MauiXaml> | ||
| 94 | + </ItemGroup> | ||
| 95 | + | ||
| 96 | +</Project> |
IndustrialControl.sln
0 → 100644
| 1 | + | ||
| 2 | +Microsoft Visual Studio Solution File, Format Version 12.00 | ||
| 3 | +# Visual Studio Version 17 | ||
| 4 | +VisualStudioVersion = 17.0.31903.59 | ||
| 5 | +MinimumVisualStudioVersion = 10.0.40219.1 | ||
| 6 | +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IndustrialControl", "IndustrialControl.csproj", "{A54387CA-553D-4CE0-B86C-08A45497D703}" | ||
| 7 | +EndProject | ||
| 8 | +Global | ||
| 9 | + GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
| 10 | + Debug|Any CPU = Debug|Any CPU | ||
| 11 | + Debug|x64 = Debug|x64 | ||
| 12 | + Debug|x86 = Debug|x86 | ||
| 13 | + Release|Any CPU = Release|Any CPU | ||
| 14 | + Release|x64 = Release|x64 | ||
| 15 | + Release|x86 = Release|x86 | ||
| 16 | + EndGlobalSection | ||
| 17 | + GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
| 18 | + {A54387CA-553D-4CE0-B86C-08A45497D703}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
| 19 | + {A54387CA-553D-4CE0-B86C-08A45497D703}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
| 20 | + {A54387CA-553D-4CE0-B86C-08A45497D703}.Debug|x64.ActiveCfg = Debug|Any CPU | ||
| 21 | + {A54387CA-553D-4CE0-B86C-08A45497D703}.Debug|x64.Build.0 = Debug|Any CPU | ||
| 22 | + {A54387CA-553D-4CE0-B86C-08A45497D703}.Debug|x86.ActiveCfg = Debug|Any CPU | ||
| 23 | + {A54387CA-553D-4CE0-B86C-08A45497D703}.Debug|x86.Build.0 = Debug|Any CPU | ||
| 24 | + {A54387CA-553D-4CE0-B86C-08A45497D703}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
| 25 | + {A54387CA-553D-4CE0-B86C-08A45497D703}.Release|Any CPU.Build.0 = Release|Any CPU | ||
| 26 | + {A54387CA-553D-4CE0-B86C-08A45497D703}.Release|x64.ActiveCfg = Release|Any CPU | ||
| 27 | + {A54387CA-553D-4CE0-B86C-08A45497D703}.Release|x64.Build.0 = Release|Any CPU | ||
| 28 | + {A54387CA-553D-4CE0-B86C-08A45497D703}.Release|x86.ActiveCfg = Release|Any CPU | ||
| 29 | + {A54387CA-553D-4CE0-B86C-08A45497D703}.Release|x86.Build.0 = Release|Any CPU | ||
| 30 | + EndGlobalSection | ||
| 31 | + GlobalSection(SolutionProperties) = preSolution | ||
| 32 | + HideSolutionNode = FALSE | ||
| 33 | + EndGlobalSection | ||
| 34 | +EndGlobal |
MauiProgram.cs
0 → 100644
| 1 | +using Microsoft.Extensions.Logging; | ||
| 2 | +using Microsoft.Extensions.DependencyInjection; | ||
| 3 | +using IndustrialControl.Services; | ||
| 4 | + | ||
| 5 | +namespace IndustrialControl | ||
| 6 | +{ | ||
| 7 | + public static class MauiProgram | ||
| 8 | + { | ||
| 9 | + public static MauiApp CreateMauiApp() | ||
| 10 | + { | ||
| 11 | + var builder = MauiApp.CreateBuilder(); | ||
| 12 | + builder | ||
| 13 | + .UseMauiApp<App>() | ||
| 14 | + .ConfigureFonts(fonts => | ||
| 15 | + { | ||
| 16 | + fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); | ||
| 17 | + fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); | ||
| 18 | + }); | ||
| 19 | + builder.Services.AddSingleton<AppShell>(); | ||
| 20 | + // 注册 ConfigLoader | ||
| 21 | + builder.Services.AddSingleton<Services.ConfigLoader>(); | ||
| 22 | + builder.Services.AddSingleton<Services.LogService>(); | ||
| 23 | + builder.Services.AddSingleton<IWarehouseDataService, MockWarehouseDataService>(); | ||
| 24 | + | ||
| 25 | + // 扫码服务 | ||
| 26 | + builder.Services.AddSingleton<ScanService>(); | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + // ===== 注册 ViewModels ===== | ||
| 30 | + builder.Services.AddTransient<ViewModels.LoginViewModel>(); | ||
| 31 | + builder.Services.AddTransient<ViewModels.HomeViewModel>(); | ||
| 32 | + builder.Services.AddTransient<ViewModels.AdminViewModel>(); | ||
| 33 | + builder.Services.AddTransient<ViewModels.LogsViewModel>(); | ||
| 34 | + builder.Services.AddTransient<ViewModels.InboundMaterialViewModel>(); | ||
| 35 | + builder.Services.AddTransient<ViewModels.InboundProductionViewModel>(); | ||
| 36 | + builder.Services.AddTransient<ViewModels.OutboundMaterialViewModel>(); | ||
| 37 | + builder.Services.AddTransient<ViewModels.OutboundFinishedViewModel>(); | ||
| 38 | + | ||
| 39 | + // ===== 注册 Pages(DI 创建)===== | ||
| 40 | + builder.Services.AddTransient<Pages.LoginPage>(); | ||
| 41 | + builder.Services.AddTransient<Pages.HomePage>(); | ||
| 42 | + builder.Services.AddTransient<Pages.AdminPage>(); | ||
| 43 | + builder.Services.AddTransient<Pages.LogsPage>(); | ||
| 44 | + | ||
| 45 | + // 注册需要路由的页面 | ||
| 46 | + builder.Services.AddTransient<Pages.InboundMaterialPage>(); | ||
| 47 | + builder.Services.AddTransient<Pages.InboundProductionPage>(); | ||
| 48 | + builder.Services.AddTransient<Pages.OutboundMaterialPage>(); | ||
| 49 | + builder.Services.AddTransient<Pages.OutboundFinishedPage>(); | ||
| 50 | + | ||
| 51 | +#if DEBUG | ||
| 52 | + builder.Logging.AddDebug(); | ||
| 53 | +#endif | ||
| 54 | + | ||
| 55 | + return builder.Build(); | ||
| 56 | + } | ||
| 57 | + } | ||
| 58 | +} |
Models/AppConfig.cs
0 → 100644
| 1 | +namespace IndustrialControl.Models; | ||
| 2 | + | ||
| 3 | +public class ServerSettings | ||
| 4 | +{ | ||
| 5 | + public string IpAddress { get; set; } = "192.168.1.100"; | ||
| 6 | + public int Port { get; set; } = 8080; | ||
| 7 | +} | ||
| 8 | +public class ApiEndpoints | ||
| 9 | +{ | ||
| 10 | + public string Login { get; set; } = "/sso/login"; | ||
| 11 | +} | ||
| 12 | +public class LoggingSettings | ||
| 13 | +{ | ||
| 14 | + public string Level { get; set; } = "Information"; | ||
| 15 | +} | ||
| 16 | +public class AppConfig | ||
| 17 | +{ | ||
| 18 | + public int SchemaVersion { get; set; } = 3; | ||
| 19 | + public ServerSettings Server { get; set; } = new(); | ||
| 20 | + public ApiEndpoints ApiEndpoints { get; set; } = new(); | ||
| 21 | + public LoggingSettings Logging { get; set; } = new(); | ||
| 22 | +} |
Models/ScanLine.cs
0 → 100644
Pages/AdminPage.xaml
0 → 100644
| 1 | +<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" | ||
| 2 | + xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | ||
| 3 | + x:Class="IndustrialControl.Pages.AdminPage" | ||
| 4 | + Title="管理员设置"> | ||
| 5 | + <ScrollView> | ||
| 6 | + <VerticalStackLayout Padding="24" Spacing="12"> | ||
| 7 | + <Label Text="配置版本(只读)" /> | ||
| 8 | + <Entry Text="{Binding SchemaVersion}" IsReadOnly="True"/> | ||
| 9 | + <Label Text="后端 IP 地址" /> | ||
| 10 | + <Entry Text="{Binding IpAddress}" Keyboard="Numeric"/> | ||
| 11 | + <Label Text="端口号" /> | ||
| 12 | + <Entry Text="{Binding Port}" Keyboard="Numeric"/> | ||
| 13 | + <Frame BackgroundColor="#eef" Padding="8"> | ||
| 14 | + <Label Text="{Binding BaseUrl}" /> | ||
| 15 | + </Frame> | ||
| 16 | + <HorizontalStackLayout Spacing="12" Margin="0,12,0,0"> | ||
| 17 | + <Button Text="保存" Command="{Binding SaveCommand}"/> | ||
| 18 | + <Button Text="从包内默认重载" Command="{Binding ResetToPackageCommand}"/> | ||
| 19 | + </HorizontalStackLayout> | ||
| 20 | + </VerticalStackLayout> | ||
| 21 | + </ScrollView> | ||
| 22 | +</ContentPage> |
Pages/AdminPage.xaml.cs
0 → 100644
Pages/HomePage.xaml
0 → 100644
| 1 | +<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" | ||
| 2 | + xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | ||
| 3 | + x:Class="IndustrialControl.Pages.HomePage" | ||
| 4 | + Title="仓储作业"> | ||
| 5 | + | ||
| 6 | + <VerticalStackLayout Padding="24" Spacing="16"> | ||
| 7 | + <Frame Style="{StaticResource BlueCardStyle}"> | ||
| 8 | + <Label Text="物料入库" FontSize="18" TextColor="White" VerticalTextAlignment="Center"/> | ||
| 9 | + <Frame.GestureRecognizers> | ||
| 10 | + <TapGestureRecognizer Tapped="OnInMat" NumberOfTapsRequired="1" /> | ||
| 11 | + </Frame.GestureRecognizers> | ||
| 12 | + </Frame> | ||
| 13 | + | ||
| 14 | + <Frame Style="{StaticResource BlueCardStyle}"> | ||
| 15 | + <Label Text="生产入库" FontSize="18" TextColor="White" VerticalTextAlignment="Center"/> | ||
| 16 | + <Frame.GestureRecognizers> | ||
| 17 | + <TapGestureRecognizer Tapped="OnInProd" NumberOfTapsRequired="1" /> | ||
| 18 | + </Frame.GestureRecognizers> | ||
| 19 | + </Frame> | ||
| 20 | + | ||
| 21 | + <Frame Style="{StaticResource BlueCardStyle}"> | ||
| 22 | + <Label Text="物料出库" FontSize="18" TextColor="White" VerticalTextAlignment="Center"/> | ||
| 23 | + <Frame.GestureRecognizers> | ||
| 24 | + <TapGestureRecognizer Tapped="OnOutMat" NumberOfTapsRequired="1" /> | ||
| 25 | + </Frame.GestureRecognizers> | ||
| 26 | + </Frame> | ||
| 27 | + | ||
| 28 | + <Frame Style="{StaticResource BlueCardStyle}"> | ||
| 29 | + <Label Text="成品出库/装货" FontSize="18" TextColor="White" VerticalTextAlignment="Center"/> | ||
| 30 | + <Frame.GestureRecognizers> | ||
| 31 | + <TapGestureRecognizer Tapped="OnOutFinished" NumberOfTapsRequired="1" /> | ||
| 32 | + </Frame.GestureRecognizers> | ||
| 33 | + </Frame> | ||
| 34 | + | ||
| 35 | + </VerticalStackLayout> | ||
| 36 | +</ContentPage> |
Pages/HomePage.xaml.cs
0 → 100644
| 1 | +namespace IndustrialControl.Pages | ||
| 2 | +{ | ||
| 3 | + public partial class HomePage : ContentPage | ||
| 4 | + { | ||
| 5 | + public HomePage() | ||
| 6 | + { | ||
| 7 | + InitializeComponent(); | ||
| 8 | + } | ||
| 9 | + | ||
| 10 | + private async void OnInMat(object sender, EventArgs e) | ||
| 11 | + { | ||
| 12 | + await Shell.Current.GoToAsync(nameof(InboundMaterialPage)); | ||
| 13 | + } | ||
| 14 | + | ||
| 15 | + private async void OnInProd(object sender, EventArgs e) | ||
| 16 | + { | ||
| 17 | + await Shell.Current.GoToAsync(nameof(InboundProductionPage)); | ||
| 18 | + } | ||
| 19 | + | ||
| 20 | + private async void OnOutMat(object sender, EventArgs e) | ||
| 21 | + { | ||
| 22 | + await Shell.Current.GoToAsync(nameof(OutboundMaterialPage)); | ||
| 23 | + } | ||
| 24 | + | ||
| 25 | + private async void OnOutFinished(object sender, EventArgs e) | ||
| 26 | + { | ||
| 27 | + await Shell.Current.GoToAsync(nameof(OutboundFinishedPage)); | ||
| 28 | + } | ||
| 29 | + } | ||
| 30 | +} |
Pages/InboundMaterialPage.xaml
0 → 100644
| 1 | +<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" | ||
| 2 | + xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | ||
| 3 | + x:Class="IndustrialControl.Pages.InboundMaterialPage" | ||
| 4 | + BackgroundColor="White"> | ||
| 5 | + | ||
| 6 | + <Grid RowDefinitions="Auto,Auto,Auto,*,Auto"> | ||
| 7 | + | ||
| 8 | + <!-- 顶部蓝色标题栏 --> | ||
| 9 | + <Grid BackgroundColor="#007BFF" HeightRequest="60" Padding="16,0"> | ||
| 10 | + <Label Text="仓储管理系统" | ||
| 11 | + VerticalOptions="Center" | ||
| 12 | + TextColor="White" | ||
| 13 | + FontSize="18" | ||
| 14 | + FontAttributes="Bold"/> | ||
| 15 | + </Grid> | ||
| 16 | + | ||
| 17 | + <!-- 入库单/条码扫描 --> | ||
| 18 | + <Grid Grid.Row="1" ColumnDefinitions="*,60" Padding="16,8"> | ||
| 19 | + <Entry x:Name="ScanEntry" | ||
| 20 | + Placeholder="请输入/扫描单号/物料/包装条码" | ||
| 21 | + FontSize="14" | ||
| 22 | + VerticalOptions="Center" | ||
| 23 | + BackgroundColor="White" | ||
| 24 | + HeightRequest="40" | ||
| 25 | + Text="{Binding ScanCode}" /> | ||
| 26 | + <ImageButton Grid.Column="1" | ||
| 27 | + Source="scan.png" | ||
| 28 | + BackgroundColor="#E6F2FF" | ||
| 29 | + CornerRadius="4" | ||
| 30 | + Padding="10" | ||
| 31 | + Clicked="OnScanClicked"/> | ||
| 32 | + </Grid> | ||
| 33 | + | ||
| 34 | + <!-- 基础信息 --> | ||
| 35 | + <Frame Grid.Row="2" Margin="16,0" Padding="8" BorderColor="#CCCCCC" BackgroundColor="White"> | ||
| 36 | + <Grid RowDefinitions="Auto,Auto" ColumnDefinitions="Auto,*,Auto,*" ColumnSpacing="8" RowSpacing="6"> | ||
| 37 | + | ||
| 38 | + <!-- 第一行 --> | ||
| 39 | + <Label Grid.Row="0" Grid.Column="0" Text="入库单号:" FontAttributes="Bold" /> | ||
| 40 | + <Label Grid.Row="0" Grid.Column="1" Text="{Binding OrderNo}" LineBreakMode="TailTruncation" /> | ||
| 41 | + <Label Grid.Row="0" Grid.Column="2" Text="关联到货单号:" FontAttributes="Bold" /> | ||
| 42 | + <Label Grid.Row="0" Grid.Column="3" Text="{Binding LinkedDeliveryNo}" LineBreakMode="TailTruncation" /> | ||
| 43 | + | ||
| 44 | + <!-- 第二行 --> | ||
| 45 | + <Label Grid.Row="1" Grid.Column="0" Text="关联采购单:" FontAttributes="Bold" /> | ||
| 46 | + <Label Grid.Row="1" Grid.Column="1" Text="{Binding LinkedPurchaseNo}" LineBreakMode="TailTruncation" /> | ||
| 47 | + <Label Grid.Row="1" Grid.Column="2" Text="供应商:" FontAttributes="Bold" /> | ||
| 48 | + <Label Grid.Row="1" Grid.Column="3" Text="{Binding Supplier}" LineBreakMode="TailTruncation" /> | ||
| 49 | + </Grid> | ||
| 50 | + </Frame> | ||
| 51 | + | ||
| 52 | + <!-- Tab切换 --> | ||
| 53 | + <Grid Grid.Row="3" RowDefinitions="Auto,Auto,*" Margin="0"> | ||
| 54 | + <Grid ColumnDefinitions="*,*" BackgroundColor="White"> | ||
| 55 | + <Button Text="待入库明细" | ||
| 56 | + Command="{Binding ShowPendingCommand}" | ||
| 57 | + BackgroundColor="{Binding PendingTabColor}" | ||
| 58 | + TextColor="{Binding PendingTextColor}" /> | ||
| 59 | + <Button Text="扫描明细" | ||
| 60 | + Grid.Column="1" | ||
| 61 | + Command="{Binding ShowScannedCommand}" | ||
| 62 | + BackgroundColor="{Binding ScannedTabColor}" | ||
| 63 | + TextColor="{Binding ScannedTextColor}" /> | ||
| 64 | + </Grid> | ||
| 65 | + | ||
| 66 | + <!-- 待入库明细表头 --> | ||
| 67 | + <Grid Grid.Row="1" ColumnDefinitions="*,*,*,*,*" BackgroundColor="#F2F2F2" IsVisible="{Binding IsPendingVisible}" Padding="8"> | ||
| 68 | + <Label Text="物料名称" FontAttributes="Bold" /> | ||
| 69 | + <Label Grid.Column="1" Text="规格" FontAttributes="Bold" /> | ||
| 70 | + <Label Grid.Column="2" Text="待入库数量" FontAttributes="Bold" /> | ||
| 71 | + <Label Grid.Column="3" Text="预入库库位" FontAttributes="Bold" /> | ||
| 72 | + <Label Grid.Column="4" Text="已扫描数量" FontAttributes="Bold" /> | ||
| 73 | + </Grid> | ||
| 74 | + | ||
| 75 | + <!-- 待入库明细列表 --> | ||
| 76 | + <CollectionView Grid.Row="2" | ||
| 77 | + ItemsSource="{Binding PendingList}" | ||
| 78 | + IsVisible="{Binding IsPendingVisible}" | ||
| 79 | + SelectionMode="Single"> | ||
| 80 | + <CollectionView.ItemTemplate> | ||
| 81 | + <DataTemplate> | ||
| 82 | + <Grid ColumnDefinitions="*,*,*,*,*" Padding="8" BackgroundColor="White"> | ||
| 83 | + <VisualStateManager.VisualStateGroups> | ||
| 84 | + <VisualStateGroup Name="CommonStates"> | ||
| 85 | + <VisualState Name="Normal"> | ||
| 86 | + <VisualState.Setters> | ||
| 87 | + <Setter Property="BackgroundColor" Value="White"/> | ||
| 88 | + </VisualState.Setters> | ||
| 89 | + </VisualState> | ||
| 90 | + <VisualState Name="Selected"> | ||
| 91 | + <VisualState.Setters> | ||
| 92 | + <Setter Property="BackgroundColor" Value="#CCFFCC"/> | ||
| 93 | + </VisualState.Setters> | ||
| 94 | + </VisualState> | ||
| 95 | + </VisualStateGroup> | ||
| 96 | + </VisualStateManager.VisualStateGroups> | ||
| 97 | + <Label Text="{Binding Name}" /> | ||
| 98 | + <Label Grid.Column="1" Text="{Binding Spec}" /> | ||
| 99 | + <Label Grid.Column="2" Text="{Binding PendingQty}" /> | ||
| 100 | + <Label Grid.Column="3" Text="{Binding Bin}" /> | ||
| 101 | + <Label Grid.Column="4" Text="{Binding ScannedQty}" /> | ||
| 102 | + </Grid> | ||
| 103 | + </DataTemplate> | ||
| 104 | + </CollectionView.ItemTemplate> | ||
| 105 | + </CollectionView> | ||
| 106 | + | ||
| 107 | + <!-- 扫描明细表头 --> | ||
| 108 | + <Grid Grid.Row="1" ColumnDefinitions="40,*,*,*,*,*" BackgroundColor="#F2F2F2" IsVisible="{Binding IsScannedVisible}" Padding="8"> | ||
| 109 | + <Label Text="选择" FontAttributes="Bold" /> | ||
| 110 | + <Label Grid.Column="1" Text="条码" FontAttributes="Bold" /> | ||
| 111 | + <Label Grid.Column="2" Text="物料名称" FontAttributes="Bold" /> | ||
| 112 | + <Label Grid.Column="3" Text="规格" FontAttributes="Bold" /> | ||
| 113 | + <Label Grid.Column="4" Text="入库库位" FontAttributes="Bold" /> | ||
| 114 | + <Label Grid.Column="5" Text="数量" FontAttributes="Bold" /> | ||
| 115 | + </Grid> | ||
| 116 | + | ||
| 117 | + <!-- 扫描明细列表 --> | ||
| 118 | + <!-- 扫描明细列表 --> | ||
| 119 | + <CollectionView Grid.Row="2" | ||
| 120 | + ItemsSource="{Binding ScannedList}" | ||
| 121 | + IsVisible="{Binding IsScannedVisible}" | ||
| 122 | + SelectionMode="Single"> | ||
| 123 | + <CollectionView.ItemTemplate> | ||
| 124 | + <DataTemplate> | ||
| 125 | + <Grid ColumnDefinitions="40,*,*,*,*,*" Padding="8" BackgroundColor="White"> | ||
| 126 | + <VisualStateManager.VisualStateGroups> | ||
| 127 | + <VisualStateGroup Name="CommonStates"> | ||
| 128 | + <VisualState Name="Normal"> | ||
| 129 | + <VisualState.Setters> | ||
| 130 | + <Setter Property="BackgroundColor" Value="White"/> | ||
| 131 | + </VisualState.Setters> | ||
| 132 | + </VisualState> | ||
| 133 | + <VisualState Name="Selected"> | ||
| 134 | + <VisualState.Setters> | ||
| 135 | + <Setter Property="BackgroundColor" Value="#CCFFCC"/> | ||
| 136 | + </VisualState.Setters> | ||
| 137 | + </VisualState> | ||
| 138 | + </VisualStateGroup> | ||
| 139 | + </VisualStateManager.VisualStateGroups> | ||
| 140 | + | ||
| 141 | + <CheckBox IsChecked="{Binding IsSelected}" /> | ||
| 142 | + <Label Grid.Column="1" Text="{Binding Barcode}" /> | ||
| 143 | + <Label Grid.Column="2" Text="{Binding Name}" /> | ||
| 144 | + <Label Grid.Column="3" Text="{Binding Spec}" /> | ||
| 145 | + | ||
| 146 | + <!-- 改成 Picker --> | ||
| 147 | + <Picker Grid.Column="4" | ||
| 148 | + ItemsSource="{Binding Source={RelativeSource AncestorType={x:Type ContentPage}}, Path=BindingContext.AvailableBins}" | ||
| 149 | + SelectedItem="{Binding Bin, Mode=TwoWay}" | ||
| 150 | + FontSize="14" | ||
| 151 | + Title="请选择" | ||
| 152 | + HorizontalOptions="FillAndExpand" /> | ||
| 153 | + | ||
| 154 | + <Label Grid.Column="5" Text="{Binding Qty}" /> | ||
| 155 | + </Grid> | ||
| 156 | + </DataTemplate> | ||
| 157 | + </CollectionView.ItemTemplate> | ||
| 158 | + </CollectionView> | ||
| 159 | + | ||
| 160 | + </Grid> | ||
| 161 | + | ||
| 162 | + <!-- 底部按钮 --> | ||
| 163 | + <!-- 底部按钮 --> | ||
| 164 | + <Grid Grid.Row="4" ColumnDefinitions="*,*,*" Padding="16,8" ColumnSpacing="10"> | ||
| 165 | + | ||
| 166 | + <!-- 扫描通过 --> | ||
| 167 | + <Grid BackgroundColor="#4CAF50" | ||
| 168 | + HorizontalOptions="Fill" | ||
| 169 | + VerticalOptions="Fill"> | ||
| 170 | + <Grid.GestureRecognizers> | ||
| 171 | + <TapGestureRecognizer Command="{Binding PassScanCommand}" /> | ||
| 172 | + </Grid.GestureRecognizers> | ||
| 173 | + <StackLayout Orientation="Horizontal" | ||
| 174 | + HorizontalOptions="Center" | ||
| 175 | + VerticalOptions="Center"> | ||
| 176 | + <Image Source="pass.png" HeightRequest="20" WidthRequest="20" /> | ||
| 177 | + <Label Text="扫描通过" | ||
| 178 | + Margin="5,0,0,0" | ||
| 179 | + VerticalOptions="Center" | ||
| 180 | + TextColor="White" /> | ||
| 181 | + </StackLayout> | ||
| 182 | + </Grid> | ||
| 183 | + | ||
| 184 | + <!-- 取消扫描 --> | ||
| 185 | + <Grid Grid.Column="1" | ||
| 186 | + BackgroundColor="#F44336" | ||
| 187 | + HorizontalOptions="Fill" | ||
| 188 | + VerticalOptions="Fill"> | ||
| 189 | + <Grid.GestureRecognizers> | ||
| 190 | + <TapGestureRecognizer Command="{Binding CancelScanCommand}" /> | ||
| 191 | + </Grid.GestureRecognizers> | ||
| 192 | + <StackLayout Orientation="Horizontal" | ||
| 193 | + HorizontalOptions="Center" | ||
| 194 | + VerticalOptions="Center"> | ||
| 195 | + <Image Source="cancel.png" HeightRequest="20" WidthRequest="20" /> | ||
| 196 | + <Label Text="取消扫描" | ||
| 197 | + Margin="5,0,0,0" | ||
| 198 | + VerticalOptions="Center" | ||
| 199 | + TextColor="White" /> | ||
| 200 | + </StackLayout> | ||
| 201 | + </Grid> | ||
| 202 | + | ||
| 203 | + <!-- 确认入库 --> | ||
| 204 | + <Grid Grid.Column="2" | ||
| 205 | + BackgroundColor="#2196F3" | ||
| 206 | + HorizontalOptions="Fill" | ||
| 207 | + VerticalOptions="Fill"> | ||
| 208 | + <Grid.GestureRecognizers> | ||
| 209 | + <TapGestureRecognizer Command="{Binding ConfirmCommand}" /> | ||
| 210 | + </Grid.GestureRecognizers> | ||
| 211 | + <StackLayout Orientation="Horizontal" | ||
| 212 | + HorizontalOptions="Center" | ||
| 213 | + VerticalOptions="Center"> | ||
| 214 | + <Image Source="confirm.png" HeightRequest="20" WidthRequest="20" /> | ||
| 215 | + <Label Text="确认入库" | ||
| 216 | + Margin="5,0,0,0" | ||
| 217 | + VerticalOptions="Center" | ||
| 218 | + TextColor="White" /> | ||
| 219 | + </StackLayout> | ||
| 220 | + </Grid> | ||
| 221 | + | ||
| 222 | + </Grid> | ||
| 223 | + | ||
| 224 | + </Grid> | ||
| 225 | +</ContentPage> |
Pages/InboundMaterialPage.xaml.cs
0 → 100644
| 1 | +using IndustrialControl.Services; | ||
| 2 | +using IndustrialControl.ViewModels; | ||
| 3 | + | ||
| 4 | +namespace IndustrialControl.Pages; | ||
| 5 | + | ||
| 6 | +public partial class InboundMaterialPage : ContentPage | ||
| 7 | +{ | ||
| 8 | + private readonly ScanService _scanSvc; | ||
| 9 | + private readonly InboundMaterialViewModel _vm; | ||
| 10 | + | ||
| 11 | + public InboundMaterialPage(InboundMaterialViewModel vm, ScanService scanSvc) | ||
| 12 | + { | ||
| 13 | + InitializeComponent(); | ||
| 14 | + BindingContext = vm; | ||
| 15 | + _scanSvc = scanSvc; | ||
| 16 | + _vm = vm; | ||
| 17 | + } | ||
| 18 | + | ||
| 19 | + protected override void OnAppearing() | ||
| 20 | + { | ||
| 21 | + base.OnAppearing(); | ||
| 22 | + _scanSvc.Attach(ScanEntry); | ||
| 23 | + ScanEntry.Focus(); | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + /// <summary> | ||
| 27 | + /// 清空扫描记录 | ||
| 28 | + /// </summary> | ||
| 29 | + void OnClearClicked(object sender, EventArgs e) | ||
| 30 | + { | ||
| 31 | + _vm.ClearScan(); | ||
| 32 | + ScanEntry.Text = string.Empty; | ||
| 33 | + ScanEntry.Focus(); | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + /// <summary> | ||
| 37 | + /// 预留摄像头扫码 | ||
| 38 | + /// </summary> | ||
| 39 | + async void OnScanClicked(object sender, EventArgs e) | ||
| 40 | + { | ||
| 41 | + await DisplayAlert("提示", "此按钮预留摄像头扫码;硬件扫描直接扣扳机。", "确定"); | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + /// <summary> | ||
| 45 | + /// 扫描通过按钮点击 | ||
| 46 | + /// </summary> | ||
| 47 | + void OnPassScanClicked(object sender, EventArgs e) | ||
| 48 | + { | ||
| 49 | + _vm.PassSelectedScan(); | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + /// <summary> | ||
| 53 | + /// 取消扫描按钮点击 | ||
| 54 | + /// </summary> | ||
| 55 | + void OnCancelScanClicked(object sender, EventArgs e) | ||
| 56 | + { | ||
| 57 | + _vm.CancelSelectedScan(); | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + /// <summary> | ||
| 61 | + /// 确认入库按钮点击 | ||
| 62 | + /// </summary> | ||
| 63 | + async void OnConfirmClicked(object sender, EventArgs e) | ||
| 64 | + { | ||
| 65 | + var ok = await _vm.ConfirmInboundAsync(); | ||
| 66 | + if (ok) | ||
| 67 | + { | ||
| 68 | + await DisplayAlert("提示", "入库成功", "确定"); | ||
| 69 | + _vm.ClearAll(); | ||
| 70 | + } | ||
| 71 | + else | ||
| 72 | + { | ||
| 73 | + await DisplayAlert("提示", "入库失败,请检查数据", "确定"); | ||
| 74 | + } | ||
| 75 | + } | ||
| 76 | +} |
Pages/InboundProductionPage.xaml
0 → 100644
| 1 | +<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" | ||
| 2 | + xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | ||
| 3 | + x:Class="IndustrialControl.Pages.InboundProductionPage" | ||
| 4 | + BackgroundColor="White"> | ||
| 5 | + | ||
| 6 | + <Grid RowDefinitions="Auto,Auto,Auto,*,Auto"> | ||
| 7 | + | ||
| 8 | + <!-- 顶部蓝色标题栏 --> | ||
| 9 | + <Grid BackgroundColor="#007BFF" HeightRequest="60" Padding="16,0"> | ||
| 10 | + <Label Text="仓储管理系统" | ||
| 11 | + VerticalOptions="Center" | ||
| 12 | + TextColor="White" | ||
| 13 | + FontSize="18" | ||
| 14 | + FontAttributes="Bold"/> | ||
| 15 | + </Grid> | ||
| 16 | + | ||
| 17 | + <!-- 入库单/条码扫描 --> | ||
| 18 | + <Grid Grid.Row="1" ColumnDefinitions="*,60" Padding="16,8"> | ||
| 19 | + <Entry x:Name="ScanEntry" | ||
| 20 | + Placeholder="请扫描入库单/产品/包装条码" | ||
| 21 | + FontSize="14" | ||
| 22 | + VerticalOptions="Center" | ||
| 23 | + BackgroundColor="White" | ||
| 24 | + HeightRequest="40" | ||
| 25 | + Text="{Binding ScanCode}" /> | ||
| 26 | + <ImageButton Grid.Column="1" | ||
| 27 | + Source="scan.png" | ||
| 28 | + BackgroundColor="#E6F2FF" | ||
| 29 | + CornerRadius="4" | ||
| 30 | + Padding="10" | ||
| 31 | + Clicked="OnScanClicked"/> | ||
| 32 | + </Grid> | ||
| 33 | + | ||
| 34 | + <!-- 基础信息 --> | ||
| 35 | + <Frame Grid.Row="2" Margin="16,0" Padding="8" BorderColor="#CCCCCC" BackgroundColor="White"> | ||
| 36 | + <Grid RowDefinitions="Auto,Auto" ColumnDefinitions="Auto,*,Auto,*" ColumnSpacing="8" RowSpacing="6"> | ||
| 37 | + <Label Grid.Row="0" Grid.Column="0" Text="入库单号:" FontAttributes="Bold" /> | ||
| 38 | + <Label Grid.Row="0" Grid.Column="1" Text="{Binding OrderNo}" LineBreakMode="TailTruncation" /> | ||
| 39 | + <Label Grid.Row="0" Grid.Column="2" Text="工单号:" FontAttributes="Bold" /> | ||
| 40 | + <Label Grid.Row="0" Grid.Column="3" Text="{Binding WorkOrderNo}" LineBreakMode="TailTruncation" /> | ||
| 41 | + | ||
| 42 | + <Label Grid.Row="1" Grid.Column="0" Text="产品名称:" FontAttributes="Bold" /> | ||
| 43 | + <Label Grid.Row="1" Grid.Column="1" Text="{Binding ProductName}" LineBreakMode="TailTruncation" /> | ||
| 44 | + <Label Grid.Row="1" Grid.Column="2" Text="待入库数:" FontAttributes="Bold" /> | ||
| 45 | + <Label Grid.Row="1" Grid.Column="3" Text="{Binding PendingQty}" LineBreakMode="TailTruncation" /> | ||
| 46 | + </Grid> | ||
| 47 | + </Frame> | ||
| 48 | + | ||
| 49 | + <!-- 扫描明细 --> | ||
| 50 | + <Grid Grid.Row="3" RowDefinitions="Auto,*" Margin="0"> | ||
| 51 | + <!-- 表头 --> | ||
| 52 | + <Grid ColumnDefinitions="40,*,*,*" BackgroundColor="#F2F2F2" Padding="8"> | ||
| 53 | + <Label Text="选择" FontAttributes="Bold" /> | ||
| 54 | + <Label Grid.Column="1" Text="条码" FontAttributes="Bold" /> | ||
| 55 | + <Label Grid.Column="2" Text="入库库位" FontAttributes="Bold" /> | ||
| 56 | + <Label Grid.Column="3" Text="产品数量" FontAttributes="Bold" /> | ||
| 57 | + </Grid> | ||
| 58 | + | ||
| 59 | + <!-- 数据列表 --> | ||
| 60 | + <CollectionView Grid.Row="1" | ||
| 61 | + ItemsSource="{Binding Lines}" | ||
| 62 | + SelectionMode="Single"> | ||
| 63 | + <CollectionView.ItemTemplate> | ||
| 64 | + <DataTemplate> | ||
| 65 | + <Grid ColumnDefinitions="40,*,*,*" Padding="8" BackgroundColor="White"> | ||
| 66 | + <VisualStateManager.VisualStateGroups> | ||
| 67 | + <VisualStateGroup Name="CommonStates"> | ||
| 68 | + <VisualState Name="Normal"> | ||
| 69 | + <VisualState.Setters> | ||
| 70 | + <Setter Property="BackgroundColor" Value="White"/> | ||
| 71 | + </VisualState.Setters> | ||
| 72 | + </VisualState> | ||
| 73 | + <VisualState Name="Selected"> | ||
| 74 | + <VisualState.Setters> | ||
| 75 | + <Setter Property="BackgroundColor" Value="#CCFFCC"/> | ||
| 76 | + </VisualState.Setters> | ||
| 77 | + </VisualState> | ||
| 78 | + </VisualStateGroup> | ||
| 79 | + </VisualStateManager.VisualStateGroups> | ||
| 80 | + | ||
| 81 | + <CheckBox IsChecked="{Binding IsSelected}" /> | ||
| 82 | + <Label Grid.Column="1" Text="{Binding Barcode}" /> | ||
| 83 | + <!-- 库位改成 Picker --> | ||
| 84 | + <Picker Grid.Column="2" | ||
| 85 | + ItemsSource="{Binding Source={RelativeSource AncestorType={x:Type ContentPage}}, Path=BindingContext.AvailableBins}" | ||
| 86 | + SelectedItem="{Binding Bin, Mode=TwoWay}" | ||
| 87 | + FontSize="14" | ||
| 88 | + Title="请选择" | ||
| 89 | + HorizontalOptions="FillAndExpand" /> | ||
| 90 | + <Label Grid.Column="3" Text="{Binding Qty}" /> | ||
| 91 | + </Grid> | ||
| 92 | + </DataTemplate> | ||
| 93 | + </CollectionView.ItemTemplate> | ||
| 94 | + </CollectionView> | ||
| 95 | + </Grid> | ||
| 96 | + | ||
| 97 | + <!-- 底部按钮 --> | ||
| 98 | + <Grid Grid.Row="4" ColumnDefinitions="*,*,*" Padding="16,8" ColumnSpacing="10"> | ||
| 99 | + | ||
| 100 | + <!-- 扫描通过 --> | ||
| 101 | + <Grid BackgroundColor="#4CAF50" | ||
| 102 | + HorizontalOptions="Fill" | ||
| 103 | + VerticalOptions="Fill"> | ||
| 104 | + <Grid.GestureRecognizers> | ||
| 105 | + <TapGestureRecognizer Command="{Binding PassScanCommand}" /> | ||
| 106 | + </Grid.GestureRecognizers> | ||
| 107 | + <StackLayout Orientation="Horizontal" | ||
| 108 | + HorizontalOptions="Center" | ||
| 109 | + VerticalOptions="Center"> | ||
| 110 | + <Image Source="pass.png" HeightRequest="20" WidthRequest="20" /> | ||
| 111 | + <Label Text="扫描通过" | ||
| 112 | + Margin="5,0,0,0" | ||
| 113 | + VerticalOptions="Center" | ||
| 114 | + TextColor="White" /> | ||
| 115 | + </StackLayout> | ||
| 116 | + </Grid> | ||
| 117 | + | ||
| 118 | + <!-- 取消扫描 --> | ||
| 119 | + <Grid Grid.Column="1" | ||
| 120 | + BackgroundColor="#F44336" | ||
| 121 | + HorizontalOptions="Fill" | ||
| 122 | + VerticalOptions="Fill"> | ||
| 123 | + <Grid.GestureRecognizers> | ||
| 124 | + <TapGestureRecognizer Command="{Binding CancelScanCommand}" /> | ||
| 125 | + </Grid.GestureRecognizers> | ||
| 126 | + <StackLayout Orientation="Horizontal" | ||
| 127 | + HorizontalOptions="Center" | ||
| 128 | + VerticalOptions="Center"> | ||
| 129 | + <Image Source="cancel.png" HeightRequest="20" WidthRequest="20" /> | ||
| 130 | + <Label Text="取消扫描" | ||
| 131 | + Margin="5,0,0,0" | ||
| 132 | + VerticalOptions="Center" | ||
| 133 | + TextColor="White" /> | ||
| 134 | + </StackLayout> | ||
| 135 | + </Grid> | ||
| 136 | + | ||
| 137 | + <!-- 确认入库 --> | ||
| 138 | + <Grid Grid.Column="2" | ||
| 139 | + BackgroundColor="#2196F3" | ||
| 140 | + HorizontalOptions="Fill" | ||
| 141 | + VerticalOptions="Fill"> | ||
| 142 | + <Grid.GestureRecognizers> | ||
| 143 | + <TapGestureRecognizer Command="{Binding ConfirmCommand}" /> | ||
| 144 | + </Grid.GestureRecognizers> | ||
| 145 | + <StackLayout Orientation="Horizontal" | ||
| 146 | + HorizontalOptions="Center" | ||
| 147 | + VerticalOptions="Center"> | ||
| 148 | + <Image Source="confirm.png" HeightRequest="20" WidthRequest="20" /> | ||
| 149 | + <Label Text="确认入库" | ||
| 150 | + Margin="5,0,0,0" | ||
| 151 | + VerticalOptions="Center" | ||
| 152 | + TextColor="White" /> | ||
| 153 | + </StackLayout> | ||
| 154 | + </Grid> | ||
| 155 | + | ||
| 156 | + </Grid> | ||
| 157 | + </Grid> | ||
| 158 | +</ContentPage> |
Pages/InboundProductionPage.xaml.cs
0 → 100644
| 1 | +using IndustrialControl.Services; | ||
| 2 | +using IndustrialControl.ViewModels; | ||
| 3 | + | ||
| 4 | +namespace IndustrialControl.Pages | ||
| 5 | +{ | ||
| 6 | + public partial class InboundProductionPage : ContentPage | ||
| 7 | + { | ||
| 8 | + private readonly ScanService _scanSvc; | ||
| 9 | + private readonly InboundProductionViewModel _vm; | ||
| 10 | + | ||
| 11 | + public InboundProductionPage(InboundProductionViewModel vm, ScanService scanSvc) | ||
| 12 | + { | ||
| 13 | + InitializeComponent(); | ||
| 14 | + BindingContext = vm; | ||
| 15 | + _scanSvc = scanSvc; | ||
| 16 | + _vm = vm; | ||
| 17 | + } | ||
| 18 | + | ||
| 19 | + protected override void OnAppearing() | ||
| 20 | + { | ||
| 21 | + base.OnAppearing(); | ||
| 22 | + _scanSvc.Attach(ScanEntry); | ||
| 23 | + ScanEntry.Focus(); | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + /// <summary> | ||
| 27 | + /// 清空扫描记录 | ||
| 28 | + /// </summary> | ||
| 29 | + void OnClearClicked(object sender, EventArgs e) | ||
| 30 | + { | ||
| 31 | + _vm.ClearScan(); | ||
| 32 | + ScanEntry.Text = string.Empty; | ||
| 33 | + ScanEntry.Focus(); | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + /// <summary> | ||
| 37 | + /// 预留摄像头扫码 | ||
| 38 | + /// </summary> | ||
| 39 | + async void OnScanClicked(object sender, EventArgs e) | ||
| 40 | + { | ||
| 41 | + await DisplayAlert("提示", "此按钮预留摄像头扫码;硬件扫描直接扣扳机。", "确定"); | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + /// <summary> | ||
| 45 | + /// 扫描通过 | ||
| 46 | + /// </summary> | ||
| 47 | + void OnPassScanClicked(object sender, EventArgs e) | ||
| 48 | + { | ||
| 49 | + _vm.PassSelectedScan(); | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + /// <summary> | ||
| 53 | + /// 取消扫描 | ||
| 54 | + /// </summary> | ||
| 55 | + void OnCancelScanClicked(object sender, EventArgs e) | ||
| 56 | + { | ||
| 57 | + _vm.CancelSelectedScan(); | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + /// <summary> | ||
| 61 | + /// 确认入库 | ||
| 62 | + /// </summary> | ||
| 63 | + async void OnConfirmClicked(object sender, EventArgs e) | ||
| 64 | + { | ||
| 65 | + var ok = await _vm.ConfirmInboundAsync(); | ||
| 66 | + if (ok) | ||
| 67 | + { | ||
| 68 | + await DisplayAlert("提示", "入库成功", "确定"); | ||
| 69 | + _vm.ClearAll(); | ||
| 70 | + } | ||
| 71 | + else | ||
| 72 | + { | ||
| 73 | + await DisplayAlert("提示", "入库失败,请检查数据", "确定"); | ||
| 74 | + } | ||
| 75 | + } | ||
| 76 | + } | ||
| 77 | +} |
Pages/LoginPage.xaml
0 → 100644
| 1 | +<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" | ||
| 2 | + xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | ||
| 3 | + xmlns:pages="clr-namespace:IndustrialControl.Pages" | ||
| 4 | + x:Class="IndustrialControl.Pages.LoginPage" | ||
| 5 | + Title="登录"> | ||
| 6 | + <Grid Padding="24" RowDefinitions="Auto,*"> | ||
| 7 | + <VerticalStackLayout Spacing="12"> | ||
| 8 | + <Label Text="联创数智管家" FontAttributes="Bold" FontSize="28"/> | ||
| 9 | + <Entry Placeholder="请输入用户名" Text="{Binding UserName}"/> | ||
| 10 | + <Entry Placeholder="请输入登录密码" IsPassword="True" Text="{Binding Password}"/> | ||
| 11 | + <Button Text="登录" Command="{Binding LoginCommand}"/> | ||
| 12 | + </VerticalStackLayout> | ||
| 13 | + </Grid> | ||
| 14 | +</ContentPage> |
Pages/LoginPage.xaml.cs
0 → 100644
Pages/LogsPage.xaml
0 → 100644
| 1 | +<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" | ||
| 2 | + xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | ||
| 3 | + x:Class="IndustrialControl.Pages.LogsPage" | ||
| 4 | + Title="实时日志"> | ||
| 5 | + <Grid RowDefinitions="Auto,*" Padding="12"> | ||
| 6 | + <Label Text="当日日志(自动刷新)" FontAttributes="Bold"/> | ||
| 7 | + <ScrollView Grid.Row="1"> | ||
| 8 | + <Label Text="{Binding LogText}" FontFamily="monospace"/> | ||
| 9 | + </ScrollView> | ||
| 10 | + </Grid> | ||
| 11 | +</ContentPage> |
Pages/LogsPage.xaml.cs
0 → 100644
| 1 | +namespace IndustrialControl.Pages; | ||
| 2 | + | ||
| 3 | +public partial class LogsPage : ContentPage | ||
| 4 | +{ | ||
| 5 | + public LogsPage(ViewModels.LogsViewModel vm){ InitializeComponent(); BindingContext = vm; } | ||
| 6 | + protected override void OnAppearing(){ base.OnAppearing(); if(BindingContext is ViewModels.LogsViewModel vm) vm.OnAppearing(); } | ||
| 7 | + protected override void OnDisappearing(){ base.OnDisappearing(); if(BindingContext is ViewModels.LogsViewModel vm) vm.OnDisappearing(); } | ||
| 8 | +} |
Pages/OutboundFinishedPage.xaml
0 → 100644
| 1 | +<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" | ||
| 2 | + xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | ||
| 3 | + x:Class="IndustrialControl.Pages.OutboundFinishedPage" | ||
| 4 | + BackgroundColor="White"> | ||
| 5 | + | ||
| 6 | + <Grid RowDefinitions="Auto,Auto,Auto,*,Auto"> | ||
| 7 | + | ||
| 8 | + <!-- 顶部蓝色标题栏 --> | ||
| 9 | + <Grid BackgroundColor="#007BFF" HeightRequest="60" Padding="16,0"> | ||
| 10 | + <Label Text="仓储管理系统" | ||
| 11 | + VerticalOptions="Center" | ||
| 12 | + TextColor="White" | ||
| 13 | + FontSize="18" | ||
| 14 | + FontAttributes="Bold"/> | ||
| 15 | + </Grid> | ||
| 16 | + | ||
| 17 | + <!-- 出库单/发货单扫描 --> | ||
| 18 | + <Grid Grid.Row="1" ColumnDefinitions="*,60" Padding="16,8"> | ||
| 19 | + <Entry x:Name="ScanEntry" | ||
| 20 | + Placeholder="请输入/扫描出库单号/产品条码" | ||
| 21 | + FontSize="14" | ||
| 22 | + VerticalOptions="Center" | ||
| 23 | + BackgroundColor="White" | ||
| 24 | + HeightRequest="40" | ||
| 25 | + Text="{Binding OrderNo}" /> | ||
| 26 | + <ImageButton Grid.Column="1" | ||
| 27 | + Source="scan.png" | ||
| 28 | + BackgroundColor="#E6F2FF" | ||
| 29 | + CornerRadius="4" | ||
| 30 | + Padding="10" | ||
| 31 | + Clicked="OnScanClicked"/> | ||
| 32 | + </Grid> | ||
| 33 | + | ||
| 34 | + <!-- 基础信息 --> | ||
| 35 | + <Frame Grid.Row="2" Margin="16,0" Padding="8" BorderColor="#CCCCCC" BackgroundColor="White"> | ||
| 36 | + <Grid RowDefinitions="Auto,Auto,Auto,Auto" | ||
| 37 | + ColumnDefinitions="Auto,* ,Auto,*" | ||
| 38 | + ColumnSpacing="8" | ||
| 39 | + RowSpacing="6"> | ||
| 40 | + | ||
| 41 | + <!-- 出库单号(独占一行) --> | ||
| 42 | + <Label Grid.Row="0" Grid.Column="0" Text="出库单号:" FontAttributes="Bold" VerticalOptions="Center" /> | ||
| 43 | + <Label Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="3" | ||
| 44 | + Text="{Binding OrderNo}" VerticalOptions="Center" /> | ||
| 45 | + | ||
| 46 | + <!-- 发货单号 + 客户 --> | ||
| 47 | + <Label Grid.Row="1" Grid.Column="0" Text="发货单号:" FontAttributes="Bold" VerticalOptions="Center" /> | ||
| 48 | + <Label Grid.Row="1" Grid.Column="1" Text="{Binding DeliveryNo}" VerticalOptions="Center" /> | ||
| 49 | + <Label Grid.Row="1" Grid.Column="2" Text="客户:" FontAttributes="Bold" VerticalOptions="Center" /> | ||
| 50 | + <Label Grid.Row="1" Grid.Column="3" Text="{Binding Customer}" VerticalOptions="Center" /> | ||
| 51 | + | ||
| 52 | + <!-- 要求发货时间 + 关联销售单 --> | ||
| 53 | + <Label Grid.Row="2" Grid.Column="0" Text="要求发货时间:" FontAttributes="Bold" VerticalOptions="Center" /> | ||
| 54 | + <Label Grid.Row="2" Grid.Column="1" Text="{Binding DeliveryTime}" VerticalOptions="Center" /> | ||
| 55 | + <Label Grid.Row="2" Grid.Column="2" Text="关联销售单:" FontAttributes="Bold" VerticalOptions="Center" /> | ||
| 56 | + <Label Grid.Row="2" Grid.Column="3" Text="{Binding SalesOrder}" VerticalOptions="Center" /> | ||
| 57 | + | ||
| 58 | + <!-- 发货单备注(独占一行) --> | ||
| 59 | + <Label Grid.Row="3" Grid.Column="0" Text="发货单备注:" FontAttributes="Bold" VerticalOptions="Center" /> | ||
| 60 | + <Label Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="3" | ||
| 61 | + Text="{Binding Remark}" VerticalOptions="Center" /> | ||
| 62 | + | ||
| 63 | + </Grid> | ||
| 64 | + </Frame> | ||
| 65 | + | ||
| 66 | + | ||
| 67 | + | ||
| 68 | + <!-- Tab切换 + 表格 --> | ||
| 69 | + <Grid Grid.Row="3" RowDefinitions="Auto,Auto,*" Margin="0"> | ||
| 70 | + <!-- Tab --> | ||
| 71 | + <Grid ColumnDefinitions="*,*" BackgroundColor="White"> | ||
| 72 | + <Button Text="出库单明细" | ||
| 73 | + BackgroundColor="{Binding PendingTabColor}" | ||
| 74 | + TextColor="{Binding PendingTextColor}" | ||
| 75 | + Clicked="OnPendingTabClicked"/> | ||
| 76 | + <Button Text="扫描明细" | ||
| 77 | + Grid.Column="1" | ||
| 78 | + BackgroundColor="{Binding ScannedTabColor}" | ||
| 79 | + TextColor="{Binding ScannedTextColor}" | ||
| 80 | + Clicked="OnScannedTabClicked"/> | ||
| 81 | + </Grid> | ||
| 82 | + | ||
| 83 | + <!-- 出库单明细表头 --> | ||
| 84 | + <!-- 出库单明细表头 --> | ||
| 85 | + <Grid Grid.Row="1" | ||
| 86 | + ColumnDefinitions="2*,2*,1.5*,2*,2*,1.5*,1.5*" | ||
| 87 | + BackgroundColor="#F2F2F2" | ||
| 88 | + IsVisible="{Binding IsPendingVisible}" | ||
| 89 | + Padding="4" | ||
| 90 | + HeightRequest="50"> | ||
| 91 | + <Label Text="产品名称" FontAttributes="Bold" | ||
| 92 | + HorizontalTextAlignment="Center" | ||
| 93 | + VerticalTextAlignment="Center" | ||
| 94 | + LineBreakMode="WordWrap"/> | ||
| 95 | + <Label Grid.Column="1" Text="产品编码" FontAttributes="Bold" | ||
| 96 | + HorizontalTextAlignment="Center" | ||
| 97 | + VerticalTextAlignment="Center" | ||
| 98 | + LineBreakMode="WordWrap"/> | ||
| 99 | + <Label Grid.Column="2" Text="规格" FontAttributes="Bold" | ||
| 100 | + HorizontalTextAlignment="Center" | ||
| 101 | + VerticalTextAlignment="Center" | ||
| 102 | + LineBreakMode="WordWrap"/> | ||
| 103 | + <Label Grid.Column="3" Text="出库库位" FontAttributes="Bold" | ||
| 104 | + HorizontalTextAlignment="Center" | ||
| 105 | + VerticalTextAlignment="Center" | ||
| 106 | + LineBreakMode="WordWrap"/> | ||
| 107 | + <Label Grid.Column="4" Text="生产批号" FontAttributes="Bold" | ||
| 108 | + HorizontalTextAlignment="Center" | ||
| 109 | + VerticalTextAlignment="Center" | ||
| 110 | + LineBreakMode="WordWrap"/> | ||
| 111 | + <Label Grid.Column="5" Text="出库数量" FontAttributes="Bold" | ||
| 112 | + HorizontalTextAlignment="Center" | ||
| 113 | + VerticalTextAlignment="Center" | ||
| 114 | + LineBreakMode="WordWrap"/> | ||
| 115 | + <Label Grid.Column="6" Text="已扫描数" FontAttributes="Bold" | ||
| 116 | + HorizontalTextAlignment="Center" | ||
| 117 | + VerticalTextAlignment="Center" | ||
| 118 | + LineBreakMode="WordWrap"/> | ||
| 119 | + </Grid> | ||
| 120 | + | ||
| 121 | + <!-- 出库单明细列表 --> | ||
| 122 | + <CollectionView Grid.Row="2" | ||
| 123 | + ItemsSource="{Binding PendingList}" | ||
| 124 | + IsVisible="{Binding IsPendingVisible}"> | ||
| 125 | + <CollectionView.ItemTemplate> | ||
| 126 | + <DataTemplate> | ||
| 127 | + <Grid ColumnDefinitions="2*,2*,1.5*,2*,2*,1.5*,1.5*" | ||
| 128 | + Padding="4" | ||
| 129 | + BackgroundColor="White"> | ||
| 130 | + <Label Text="{Binding Name}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 131 | + <Label Grid.Column="1" Text="{Binding Code}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 132 | + <Label Grid.Column="2" Text="{Binding Spec}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 133 | + <Label Grid.Column="3" Text="{Binding Bin}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 134 | + <Label Grid.Column="4" Text="{Binding BatchNo}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 135 | + <Label Grid.Column="5" Text="{Binding OutQty}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 136 | + <Label Grid.Column="6" Text="{Binding ScannedQty}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 137 | + </Grid> | ||
| 138 | + </DataTemplate> | ||
| 139 | + </CollectionView.ItemTemplate> | ||
| 140 | + </CollectionView> | ||
| 141 | + | ||
| 142 | + | ||
| 143 | + <!-- 扫描明细表头 --> | ||
| 144 | + <Grid Grid.Row="1" | ||
| 145 | + ColumnDefinitions="40,*,*,*" | ||
| 146 | + BackgroundColor="#F2F2F2" | ||
| 147 | + IsVisible="{Binding IsScannedVisible}" | ||
| 148 | + Padding="4" | ||
| 149 | + HeightRequest="30"> | ||
| 150 | + <Label Text="选择" FontAttributes="Bold" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" LineBreakMode="NoWrap"/> | ||
| 151 | + <Label Grid.Column="1" Text="条码" FontAttributes="Bold" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" LineBreakMode="NoWrap"/> | ||
| 152 | + <Label Grid.Column="2" Text="产品名称" FontAttributes="Bold" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" LineBreakMode="NoWrap"/> | ||
| 153 | + <Label Grid.Column="3" Text="数量" FontAttributes="Bold" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" LineBreakMode="NoWrap"/> | ||
| 154 | + </Grid> | ||
| 155 | + | ||
| 156 | + <!-- 扫描明细列表 --> | ||
| 157 | + <CollectionView Grid.Row="2" | ||
| 158 | + ItemsSource="{Binding ScannedList}" | ||
| 159 | + IsVisible="{Binding IsScannedVisible}"> | ||
| 160 | + <CollectionView.ItemTemplate> | ||
| 161 | + <DataTemplate> | ||
| 162 | + <Grid ColumnDefinitions="40,*,*,*" Padding="4" BackgroundColor="White"> | ||
| 163 | + <CheckBox IsChecked="{Binding IsSelected}" HorizontalOptions="Center" VerticalOptions="Center" /> | ||
| 164 | + <Label Grid.Column="1" Text="{Binding Barcode}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" /> | ||
| 165 | + <Label Grid.Column="2" Text="{Binding Name}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" /> | ||
| 166 | + <Label Grid.Column="3" Text="{Binding Qty}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" /> | ||
| 167 | + </Grid> | ||
| 168 | + </DataTemplate> | ||
| 169 | + </CollectionView.ItemTemplate> | ||
| 170 | + </CollectionView> | ||
| 171 | + </Grid> | ||
| 172 | + | ||
| 173 | + | ||
| 174 | + <!-- 底部按钮 --> | ||
| 175 | + <Grid Grid.Row="4" ColumnDefinitions="*,*,*" Padding="16,8" ColumnSpacing="10"> | ||
| 176 | + | ||
| 177 | + <!-- 扫描通过 --> | ||
| 178 | + <HorizontalStackLayout BackgroundColor="#4CAF50" | ||
| 179 | + Padding="10" | ||
| 180 | + HorizontalOptions="FillAndExpand" | ||
| 181 | + VerticalOptions="Center" | ||
| 182 | + Grid.Column="0"> | ||
| 183 | + <Image Source="pass.png" WidthRequest="20" HeightRequest="20" /> | ||
| 184 | + <Label Text="扫描通过" | ||
| 185 | + VerticalOptions="Center" | ||
| 186 | + HorizontalOptions="Center" | ||
| 187 | + TextColor="White" | ||
| 188 | + Margin="5,0,0,0" /> | ||
| 189 | + <HorizontalStackLayout.GestureRecognizers> | ||
| 190 | + <TapGestureRecognizer Command="{Binding PassScanCommand}" /> | ||
| 191 | + </HorizontalStackLayout.GestureRecognizers> | ||
| 192 | + </HorizontalStackLayout> | ||
| 193 | + | ||
| 194 | + <!-- 取消扫描 --> | ||
| 195 | + <HorizontalStackLayout BackgroundColor="#F44336" | ||
| 196 | + Padding="10" | ||
| 197 | + HorizontalOptions="FillAndExpand" | ||
| 198 | + VerticalOptions="Center" | ||
| 199 | + Grid.Column="1"> | ||
| 200 | + <Image Source="cancel.png" WidthRequest="20" HeightRequest="20" /> | ||
| 201 | + <Label Text="取消扫描" | ||
| 202 | + VerticalOptions="Center" | ||
| 203 | + HorizontalOptions="Center" | ||
| 204 | + TextColor="White" | ||
| 205 | + Margin="5,0,0,0" /> | ||
| 206 | + <HorizontalStackLayout.GestureRecognizers> | ||
| 207 | + <TapGestureRecognizer Command="{Binding CancelScanCommand}" /> | ||
| 208 | + </HorizontalStackLayout.GestureRecognizers> | ||
| 209 | + </HorizontalStackLayout> | ||
| 210 | + | ||
| 211 | + <!-- 确认出库 --> | ||
| 212 | + <HorizontalStackLayout BackgroundColor="#2196F3" | ||
| 213 | + Padding="10" | ||
| 214 | + HorizontalOptions="FillAndExpand" | ||
| 215 | + VerticalOptions="Center" | ||
| 216 | + Grid.Column="2"> | ||
| 217 | + <Image Source="confirm.png" WidthRequest="20" HeightRequest="20" /> | ||
| 218 | + <Label Text="确认出库" | ||
| 219 | + VerticalOptions="Center" | ||
| 220 | + HorizontalOptions="Center" | ||
| 221 | + TextColor="White" | ||
| 222 | + Margin="5,0,0,0" /> | ||
| 223 | + <HorizontalStackLayout.GestureRecognizers> | ||
| 224 | + <TapGestureRecognizer Command="{Binding ConfirmCommand}" /> | ||
| 225 | + </HorizontalStackLayout.GestureRecognizers> | ||
| 226 | + </HorizontalStackLayout> | ||
| 227 | + | ||
| 228 | + </Grid> | ||
| 229 | + | ||
| 230 | + </Grid> | ||
| 231 | +</ContentPage> |
Pages/OutboundFinishedPage.xaml.cs
0 → 100644
| 1 | +using IndustrialControl.Services; | ||
| 2 | +using IndustrialControl.ViewModels; | ||
| 3 | + | ||
| 4 | +namespace IndustrialControl.Pages | ||
| 5 | +{ | ||
| 6 | + public partial class OutboundFinishedPage : ContentPage | ||
| 7 | + { | ||
| 8 | + private readonly ScanService _scanSvc; | ||
| 9 | + private readonly OutboundFinishedViewModel _vm; | ||
| 10 | + | ||
| 11 | + public OutboundFinishedPage(OutboundFinishedViewModel vm, ScanService scanSvc) | ||
| 12 | + { | ||
| 13 | + InitializeComponent(); | ||
| 14 | + BindingContext = vm; | ||
| 15 | + _scanSvc = scanSvc; | ||
| 16 | + _vm = vm; | ||
| 17 | + } | ||
| 18 | + | ||
| 19 | + protected override void OnAppearing() | ||
| 20 | + { | ||
| 21 | + base.OnAppearing(); | ||
| 22 | + _scanSvc.Attach(ScanEntry); | ||
| 23 | + ScanEntry.Focus(); | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + /// <summary> | ||
| 27 | + /// 清空扫描记录 | ||
| 28 | + /// </summary> | ||
| 29 | + void OnClearClicked(object sender, EventArgs e) | ||
| 30 | + { | ||
| 31 | + _vm.ClearScan(); | ||
| 32 | + ScanEntry.Text = string.Empty; | ||
| 33 | + ScanEntry.Focus(); | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + /// <summary> | ||
| 37 | + /// 预留摄像头扫码 | ||
| 38 | + /// </summary> | ||
| 39 | + async void OnScanClicked(object sender, EventArgs e) | ||
| 40 | + { | ||
| 41 | + await DisplayAlert("提示", "此按钮预留摄像头扫码;硬件扫描直接扣扳机。", "确定"); | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + /// <summary> | ||
| 45 | + /// 点击“出库单明细”Tab | ||
| 46 | + /// </summary> | ||
| 47 | + void OnPendingTabClicked(object sender, EventArgs e) | ||
| 48 | + { | ||
| 49 | + _vm.ShowPendingCommand.Execute(null); | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + /// <summary> | ||
| 53 | + /// 点击“扫描明细”Tab | ||
| 54 | + /// </summary> | ||
| 55 | + void OnScannedTabClicked(object sender, EventArgs e) | ||
| 56 | + { | ||
| 57 | + _vm.ShowScannedCommand.Execute(null); | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + /// <summary> | ||
| 61 | + /// 扫描通过 | ||
| 62 | + /// </summary> | ||
| 63 | + void OnPassScanClicked(object sender, EventArgs e) | ||
| 64 | + { | ||
| 65 | + _vm.PassScanCommand.Execute(null); | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + /// <summary> | ||
| 69 | + /// 取消扫描 | ||
| 70 | + /// </summary> | ||
| 71 | + void OnCancelScanClicked(object sender, EventArgs e) | ||
| 72 | + { | ||
| 73 | + _vm.CancelScanCommand.Execute(null); | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + /// <summary> | ||
| 77 | + /// 确认出库 | ||
| 78 | + /// </summary> | ||
| 79 | + async void OnConfirmClicked(object sender, EventArgs e) | ||
| 80 | + { | ||
| 81 | + _vm.ConfirmCommand.Execute(null); | ||
| 82 | + } | ||
| 83 | + } | ||
| 84 | +} |
Pages/OutboundMaterialPage.xaml
0 → 100644
| 1 | +<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" | ||
| 2 | + xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | ||
| 3 | + x:Class="IndustrialControl.Pages.OutboundMaterialPage" | ||
| 4 | + BackgroundColor="White"> | ||
| 5 | + | ||
| 6 | + <Grid RowDefinitions="Auto,Auto,Auto,*,Auto"> | ||
| 7 | + | ||
| 8 | + <!-- 顶部蓝色标题栏 --> | ||
| 9 | + <Grid BackgroundColor="#007BFF" HeightRequest="60" Padding="16,0"> | ||
| 10 | + <Label Text="仓储管理系统" | ||
| 11 | + VerticalOptions="Center" | ||
| 12 | + TextColor="White" | ||
| 13 | + FontSize="18" | ||
| 14 | + FontAttributes="Bold"/> | ||
| 15 | + </Grid> | ||
| 16 | + | ||
| 17 | + <!-- 出库单/条码扫描 --> | ||
| 18 | + <Grid Grid.Row="1" ColumnDefinitions="*,60" Padding="16,8"> | ||
| 19 | + <Entry x:Name="ScanEntry" | ||
| 20 | + Placeholder="请扫描出库单/产品/包装条码" | ||
| 21 | + FontSize="14" | ||
| 22 | + VerticalOptions="Center" | ||
| 23 | + BackgroundColor="White" | ||
| 24 | + HeightRequest="40" | ||
| 25 | + Text="{Binding ScanCode}" /> | ||
| 26 | + <ImageButton Grid.Column="1" | ||
| 27 | + Source="scan.png" | ||
| 28 | + BackgroundColor="#E6F2FF" | ||
| 29 | + CornerRadius="4" | ||
| 30 | + Padding="10" | ||
| 31 | + Clicked="OnScanClicked"/> | ||
| 32 | + </Grid> | ||
| 33 | + | ||
| 34 | + <!-- 基础信息 --> | ||
| 35 | + <Frame Grid.Row="2" Margin="16,0" Padding="8" BorderColor="#CCCCCC" BackgroundColor="White"> | ||
| 36 | + <Grid RowDefinitions="Auto,Auto,Auto,Auto" ColumnDefinitions="Auto,*" ColumnSpacing="8" RowSpacing="6"> | ||
| 37 | + | ||
| 38 | + <!-- 出库单号 --> | ||
| 39 | + <Label Grid.Row="0" Grid.Column="0" Text="出库单号:" FontAttributes="Bold"/> | ||
| 40 | + <Label Grid.Row="0" Grid.Column="1" Text="{Binding OrderNo}" LineBreakMode="CharacterWrap"/> | ||
| 41 | + | ||
| 42 | + <!-- 发货单号 + 客户 --> | ||
| 43 | + <Label Grid.Row="1" Grid.Column="0" Text="发货单号:" FontAttributes="Bold"/> | ||
| 44 | + <Label Grid.Row="1" Grid.Column="1" Text="{Binding DeliveryNo}" LineBreakMode="CharacterWrap"/> | ||
| 45 | + <Label Grid.Row="1" Grid.Column="2" Text="客户:" FontAttributes="Bold"/> | ||
| 46 | + <Label Grid.Row="1" Grid.Column="3" Text="{Binding CustomerName}" LineBreakMode="CharacterWrap"/> | ||
| 47 | + | ||
| 48 | + <!-- 发货时间 + 关联销售单 --> | ||
| 49 | + <Label Grid.Row="2" Grid.Column="0" Text="发货时间:" FontAttributes="Bold"/> | ||
| 50 | + <Label Grid.Row="2" Grid.Column="1" Text="{Binding DeliveryTime}" LineBreakMode="CharacterWrap"/> | ||
| 51 | + <Label Grid.Row="2" Grid.Column="2" Text="关联销售单:" FontAttributes="Bold"/> | ||
| 52 | + <Label Grid.Row="2" Grid.Column="3" Text="{Binding LinkedOrderNo}" LineBreakMode="CharacterWrap"/> | ||
| 53 | + | ||
| 54 | + <!-- 发货单备注 --> | ||
| 55 | + <Label Grid.Row="3" Grid.Column="0" Text="发货单备注:" FontAttributes="Bold"/> | ||
| 56 | + <Label Grid.Row="3" Grid.Column="1" Text="{Binding Remark}" LineBreakMode="WordWrap"/> | ||
| 57 | + </Grid> | ||
| 58 | + </Frame> | ||
| 59 | + | ||
| 60 | + <!-- Tab + 列表 --> | ||
| 61 | + <Grid Grid.Row="3" RowDefinitions="Auto,Auto,*"> | ||
| 62 | + | ||
| 63 | + <!-- Tab --> | ||
| 64 | + <Grid ColumnDefinitions="*,*" BackgroundColor="White"> | ||
| 65 | + <Button Text="出库单明细" | ||
| 66 | + BackgroundColor="{Binding PendingTabColor}" | ||
| 67 | + TextColor="{Binding PendingTextColor}" | ||
| 68 | + Clicked="OnPendingTabClicked"/> | ||
| 69 | + <Button Text="扫描明细" | ||
| 70 | + Grid.Column="1" | ||
| 71 | + BackgroundColor="{Binding ScannedTabColor}" | ||
| 72 | + TextColor="{Binding ScannedTextColor}" | ||
| 73 | + Clicked="OnScannedTabClicked"/> | ||
| 74 | + </Grid> | ||
| 75 | + | ||
| 76 | + <!-- 出库单明细表头 --> | ||
| 77 | + <Grid Grid.Row="1" | ||
| 78 | + ColumnDefinitions="2*,2*,1.5*,1.5*,1.5*,1.5*,1.5*" | ||
| 79 | + BackgroundColor="#F2F2F2" | ||
| 80 | + IsVisible="{Binding IsPendingVisible}" | ||
| 81 | + Padding="4"> | ||
| 82 | + <Label Text="产品名称" FontAttributes="Bold" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 83 | + <Label Grid.Column="1" Text="产品编码" FontAttributes="Bold" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 84 | + <Label Grid.Column="2" Text="规格" FontAttributes="Bold" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 85 | + <Label Grid.Column="3" Text="出库库位" FontAttributes="Bold" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 86 | + <Label Grid.Column="4" Text="批次号" FontAttributes="Bold" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 87 | + <Label Grid.Column="5" Text="出库数量" FontAttributes="Bold" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 88 | + <Label Grid.Column="6" Text="已扫描数" FontAttributes="Bold" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 89 | + </Grid> | ||
| 90 | + | ||
| 91 | + <!-- 出库单明细列表 --> | ||
| 92 | + <CollectionView Grid.Row="2" | ||
| 93 | + ItemsSource="{Binding PendingList}" | ||
| 94 | + IsVisible="{Binding IsPendingVisible}"> | ||
| 95 | + <CollectionView.ItemTemplate> | ||
| 96 | + <DataTemplate> | ||
| 97 | + <Grid ColumnDefinitions="2*,2*,1.5*,1.5*,1.5*,1.5*,1.5*" Padding="4" BackgroundColor="White"> | ||
| 98 | + <Label Text="{Binding Name}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 99 | + <Label Grid.Column="1" Text="{Binding Code}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 100 | + <Label Grid.Column="2" Text="{Binding Spec}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 101 | + <Label Grid.Column="3" Text="{Binding Bin}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 102 | + <Label Grid.Column="4" Text="{Binding BatchNo}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 103 | + <Label Grid.Column="5" Text="{Binding OutQty}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 104 | + <Label Grid.Column="6" Text="{Binding ScannedQty}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 105 | + </Grid> | ||
| 106 | + </DataTemplate> | ||
| 107 | + </CollectionView.ItemTemplate> | ||
| 108 | + </CollectionView> | ||
| 109 | + | ||
| 110 | + <!-- 扫描明细表头 --> | ||
| 111 | + <Grid Grid.Row="1" | ||
| 112 | + ColumnDefinitions="40,*,*,*" | ||
| 113 | + BackgroundColor="#F2F2F2" | ||
| 114 | + IsVisible="{Binding IsScannedVisible}" | ||
| 115 | + Padding="4"> | ||
| 116 | + <Label Text="选择" FontAttributes="Bold" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 117 | + <Label Grid.Column="1" Text="条码" FontAttributes="Bold" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 118 | + <Label Grid.Column="2" Text="物料名称" FontAttributes="Bold" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 119 | + <Label Grid.Column="3" Text="数量" FontAttributes="Bold" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 120 | + </Grid> | ||
| 121 | + | ||
| 122 | + <!-- 扫描明细列表 --> | ||
| 123 | + <CollectionView Grid.Row="2" | ||
| 124 | + ItemsSource="{Binding ScannedList}" | ||
| 125 | + IsVisible="{Binding IsScannedVisible}"> | ||
| 126 | + <CollectionView.ItemTemplate> | ||
| 127 | + <DataTemplate> | ||
| 128 | + <Grid ColumnDefinitions="40,*,*,*" Padding="4" BackgroundColor="White"> | ||
| 129 | + <CheckBox IsChecked="{Binding IsSelected}" HorizontalOptions="Center" VerticalOptions="Center"/> | ||
| 130 | + <Label Grid.Column="1" Text="{Binding Barcode}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 131 | + <Label Grid.Column="2" Text="{Binding Name}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 132 | + <Label Grid.Column="3" Text="{Binding Qty}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center"/> | ||
| 133 | + </Grid> | ||
| 134 | + </DataTemplate> | ||
| 135 | + </CollectionView.ItemTemplate> | ||
| 136 | + </CollectionView> | ||
| 137 | + </Grid> | ||
| 138 | + | ||
| 139 | + <!-- 底部按钮 --> | ||
| 140 | + <Grid Grid.Row="4" ColumnDefinitions="*,*,*" Padding="16,8" ColumnSpacing="10"> | ||
| 141 | + <Button Text="扫描通过" BackgroundColor="#4CAF50" TextColor="White" Clicked="OnPassScanClicked"/> | ||
| 142 | + <Button Grid.Column="1" Text="取消扫描" BackgroundColor="#F44336" TextColor="White" Clicked="OnCancelScanClicked"/> | ||
| 143 | + <Button Grid.Column="2" Text="确认出库" BackgroundColor="#2196F3" TextColor="White" Clicked="OnConfirmClicked"/> | ||
| 144 | + </Grid> | ||
| 145 | + | ||
| 146 | + </Grid> | ||
| 147 | +</ContentPage> |
Pages/OutboundMaterialPage.xaml.cs
0 → 100644
| 1 | +using IndustrialControl.Services; | ||
| 2 | +using IndustrialControl.ViewModels; | ||
| 3 | + | ||
| 4 | +namespace IndustrialControl.Pages | ||
| 5 | +{ | ||
| 6 | + public partial class OutboundMaterialPage : ContentPage | ||
| 7 | + { | ||
| 8 | + private readonly ScanService _scanSvc; | ||
| 9 | + private readonly OutboundMaterialViewModel _vm; | ||
| 10 | + | ||
| 11 | + public OutboundMaterialPage(OutboundMaterialViewModel vm, ScanService scanSvc) | ||
| 12 | + { | ||
| 13 | + InitializeComponent(); | ||
| 14 | + BindingContext = vm; | ||
| 15 | + _scanSvc = scanSvc; | ||
| 16 | + _vm = vm; | ||
| 17 | + } | ||
| 18 | + | ||
| 19 | + protected override void OnAppearing() | ||
| 20 | + { | ||
| 21 | + base.OnAppearing(); | ||
| 22 | + _scanSvc.Attach(ScanEntry); | ||
| 23 | + ScanEntry.Focus(); | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + // Tab切换 | ||
| 27 | + void OnPendingTabClicked(object sender, EventArgs e) | ||
| 28 | + { | ||
| 29 | + _vm.IsPendingVisible = true; | ||
| 30 | + _vm.IsScannedVisible = false; | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + void OnScannedTabClicked(object sender, EventArgs e) | ||
| 34 | + { | ||
| 35 | + _vm.IsPendingVisible = false; | ||
| 36 | + _vm.IsScannedVisible = true; | ||
| 37 | + } | ||
| 38 | + | ||
| 39 | + // 清空扫描记录 | ||
| 40 | + void OnClearClicked(object sender, EventArgs e) | ||
| 41 | + { | ||
| 42 | + _vm.ClearScan(); | ||
| 43 | + ScanEntry.Text = string.Empty; | ||
| 44 | + ScanEntry.Focus(); | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + // 摄像头扫码按钮 | ||
| 48 | + async void OnScanClicked(object sender, EventArgs e) | ||
| 49 | + { | ||
| 50 | + await DisplayAlert("提示", "此按钮预留摄像头扫码;硬件扫描直接扣扳机。", "确定"); | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + // 扫描通过 | ||
| 54 | + void OnPassScanClicked(object sender, EventArgs e) | ||
| 55 | + { | ||
| 56 | + _vm.PassSelectedScan(); | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + // 取消扫描 | ||
| 60 | + void OnCancelScanClicked(object sender, EventArgs e) | ||
| 61 | + { | ||
| 62 | + _vm.CancelSelectedScan(); | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + // 确认出库 | ||
| 66 | + async void OnConfirmClicked(object sender, EventArgs e) | ||
| 67 | + { | ||
| 68 | + var ok = await _vm.ConfirmOutboundAsync(); | ||
| 69 | + if (ok) | ||
| 70 | + { | ||
| 71 | + await DisplayAlert("提示", "出库成功", "确定"); | ||
| 72 | + _vm.ClearAll(); | ||
| 73 | + } | ||
| 74 | + else | ||
| 75 | + { | ||
| 76 | + await DisplayAlert("提示", "出库失败,请检查数据", "确定"); | ||
| 77 | + } | ||
| 78 | + } | ||
| 79 | + } | ||
| 80 | +} |
Platforms/Tizen/Main.cs
0 → 100644
| 1 | +using System; | ||
| 2 | +using Microsoft.Maui; | ||
| 3 | +using Microsoft.Maui.Hosting; | ||
| 4 | + | ||
| 5 | +namespace IndustrialControl | ||
| 6 | +{ | ||
| 7 | + internal class Program : MauiApplication | ||
| 8 | + { | ||
| 9 | + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); | ||
| 10 | + | ||
| 11 | + static void Main(string[] args) | ||
| 12 | + { | ||
| 13 | + var app = new Program(); | ||
| 14 | + app.Run(args); | ||
| 15 | + } | ||
| 16 | + } | ||
| 17 | +} |
Platforms/Tizen/tizen-manifest.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="utf-8"?> | ||
| 2 | +<manifest package="maui-application-id-placeholder" version="0.0.0" api-version="8" xmlns="http://tizen.org/ns/packages"> | ||
| 3 | + <profile name="common" /> | ||
| 4 | + <ui-application appid="maui-application-id-placeholder" exec="IndustrialControl.dll" multiple="false" nodisplay="false" taskmanage="true" type="dotnet" launch_mode="single"> | ||
| 5 | + <label>maui-application-title-placeholder</label> | ||
| 6 | + <icon>maui-appicon-placeholder</icon> | ||
| 7 | + <metadata key="http://tizen.org/metadata/prefer_dotnet_aot" value="true" /> | ||
| 8 | + </ui-application> | ||
| 9 | + <shortcut-list /> | ||
| 10 | + <privileges> | ||
| 11 | + <privilege>http://tizen.org/privilege/internet</privilege> | ||
| 12 | + </privileges> | ||
| 13 | + <dependencies /> | ||
| 14 | + <provides-appdefined-privileges /> | ||
| 15 | +</manifest> |
Platforms/Windows/App.xaml
0 → 100644
| 1 | +<maui:MauiWinUIApplication | ||
| 2 | + x:Class="IndustrialControl.WinUI.App" | ||
| 3 | + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||
| 4 | + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||
| 5 | + xmlns:maui="using:Microsoft.Maui" | ||
| 6 | + xmlns:local="using:IndustrialControl.WinUI"> | ||
| 7 | + | ||
| 8 | +</maui:MauiWinUIApplication> |
Platforms/Windows/App.xaml.cs
0 → 100644
| 1 | +using Microsoft.UI.Xaml; | ||
| 2 | + | ||
| 3 | +// To learn more about WinUI, the WinUI project structure, | ||
| 4 | +// and more about our project templates, see: http://aka.ms/winui-project-info. | ||
| 5 | + | ||
| 6 | +namespace IndustrialControl.WinUI | ||
| 7 | +{ | ||
| 8 | + /// <summary> | ||
| 9 | + /// Provides application-specific behavior to supplement the default Application class. | ||
| 10 | + /// </summary> | ||
| 11 | + public partial class App : MauiWinUIApplication | ||
| 12 | + { | ||
| 13 | + /// <summary> | ||
| 14 | + /// Initializes the singleton application object. This is the first line of authored code | ||
| 15 | + /// executed, and as such is the logical equivalent of main() or WinMain(). | ||
| 16 | + /// </summary> | ||
| 17 | + public App() | ||
| 18 | + { | ||
| 19 | + this.InitializeComponent(); | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); | ||
| 23 | + } | ||
| 24 | + | ||
| 25 | +} |
Platforms/Windows/Package.appxmanifest
0 → 100644
| 1 | +<?xml version="1.0" encoding="utf-8"?> | ||
| 2 | +<Package | ||
| 3 | + xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" | ||
| 4 | + xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" | ||
| 5 | + xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" | ||
| 6 | + xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" | ||
| 7 | + IgnorableNamespaces="uap rescap"> | ||
| 8 | + | ||
| 9 | + <Identity Name="maui-package-name-placeholder" Publisher="CN=User Name" Version="0.0.0.0" /> | ||
| 10 | + | ||
| 11 | + <mp:PhoneIdentity PhoneProductId="51796DCC-E64D-4816-833F-CF9CE3D4BEEA" PhonePublisherId="00000000-0000-0000-0000-000000000000"/> | ||
| 12 | + | ||
| 13 | + <Properties> | ||
| 14 | + <DisplayName>$placeholder$</DisplayName> | ||
| 15 | + <PublisherDisplayName>User Name</PublisherDisplayName> | ||
| 16 | + <Logo>$placeholder$.png</Logo> | ||
| 17 | + </Properties> | ||
| 18 | + | ||
| 19 | + <Dependencies> | ||
| 20 | + <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" /> | ||
| 21 | + <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" /> | ||
| 22 | + </Dependencies> | ||
| 23 | + | ||
| 24 | + <Resources> | ||
| 25 | + <Resource Language="x-generate" /> | ||
| 26 | + </Resources> | ||
| 27 | + | ||
| 28 | + <Applications> | ||
| 29 | + <Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="$targetentrypoint$"> | ||
| 30 | + <uap:VisualElements | ||
| 31 | + DisplayName="$placeholder$" | ||
| 32 | + Description="$placeholder$" | ||
| 33 | + Square150x150Logo="$placeholder$.png" | ||
| 34 | + Square44x44Logo="$placeholder$.png" | ||
| 35 | + BackgroundColor="transparent"> | ||
| 36 | + <uap:DefaultTile Square71x71Logo="$placeholder$.png" Wide310x150Logo="$placeholder$.png" Square310x310Logo="$placeholder$.png" /> | ||
| 37 | + <uap:SplashScreen Image="$placeholder$.png" /> | ||
| 38 | + </uap:VisualElements> | ||
| 39 | + </Application> | ||
| 40 | + </Applications> | ||
| 41 | + | ||
| 42 | + <Capabilities> | ||
| 43 | + <rescap:Capability Name="runFullTrust" /> | ||
| 44 | + </Capabilities> | ||
| 45 | + | ||
| 46 | +</Package> |
Platforms/Windows/app.manifest
0 → 100644
| 1 | +<?xml version="1.0" encoding="utf-8"?> | ||
| 2 | +<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"> | ||
| 3 | + <assemblyIdentity version="1.0.0.0" name="IndustrialControl.WinUI.app"/> | ||
| 4 | + | ||
| 5 | + <application xmlns="urn:schemas-microsoft-com:asm.v3"> | ||
| 6 | + <windowsSettings> | ||
| 7 | + <!-- The combination of below two tags have the following effect: | ||
| 8 | + 1) Per-Monitor for >= Windows 10 Anniversary Update | ||
| 9 | + 2) System < Windows 10 Anniversary Update | ||
| 10 | + --> | ||
| 11 | + <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware> | ||
| 12 | + <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness> | ||
| 13 | + </windowsSettings> | ||
| 14 | + </application> | ||
| 15 | +</assembly> |
Properties/launchSettings.json
0 → 100644
Resources/AppIcon/appicon.svg
0 → 100644
Resources/AppIcon/appiconfg.svg
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
| 2 | +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||
| 3 | +<svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"> | ||
| 4 | + <path d="m 105.50037,281.60863 c -2.70293,0 -5.00091,-0.90042 -6.893127,-2.70209 -1.892214,-1.84778 -2.837901,-4.04181 -2.837901,-6.58209 0,-2.58722 0.945687,-4.80389 2.837901,-6.65167 1.892217,-1.84778 4.190197,-2.77167 6.893127,-2.77167 2.74819,0 5.06798,0.92389 6.96019,2.77167 1.93749,1.84778 2.90581,4.06445 2.90581,6.65167 0,2.54028 -0.96832,4.73431 -2.90581,6.58209 -1.89221,1.80167 -4.212,2.70209 -6.96019,2.70209 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" /> | ||
| 5 | + <path d="M 213.56111,280.08446 H 195.99044 L 149.69953,207.0544 c -1.17121,-1.84778 -2.14037,-3.76515 -2.90581,-5.75126 h -0.40578 c 0.36051,2.12528 0.54076,6.67515 0.54076,13.6496 v 65.13172 h -15.54349 v -99.36009 h 18.71925 l 44.7374,71.29798 c 1.89222,2.95695 3.1087,4.98917 3.64945,6.09751 h 0.26996 c -0.45021,-2.6325 -0.67573,-7.09015 -0.67573,-13.37293 v -64.02256 h 15.47557 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" /> | ||
| 6 | + <path d="m 289.25134,280.08446 h -54.40052 v -99.36009 h 52.23835 v 13.99669 h -36.15411 v 28.13085 h 33.31621 v 13.9271 h -33.31621 v 29.37835 h 38.31628 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" /> | ||
| 7 | + <path d="M 366.56466,194.72106 H 338.7222 v 85.3634 h -16.08423 v -85.3634 h -27.77455 v -13.99669 h 71.70124 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" /> | ||
| 8 | +</svg> |
Resources/Fonts/OpenSans-Regular.ttf
0 → 100644
不能预览此文件类型
Resources/Fonts/OpenSans-Semibold.ttf
0 → 100644
不能预览此文件类型
Resources/Images/dotnet_bot.png
0 → 100644
68.2 KB
Resources/Raw/AboutAssets.txt
0 → 100644
| 1 | +Any raw assets you want to be deployed with your application can be placed in | ||
| 2 | +this directory (and child directories). Deployment of the asset to your application | ||
| 3 | +is automatically handled by the following `MauiAsset` Build Action within your `.csproj`. | ||
| 4 | + | ||
| 5 | + <MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" /> | ||
| 6 | + | ||
| 7 | +These files will be deployed with your package and will be accessible using Essentials: | ||
| 8 | + | ||
| 9 | + async Task LoadMauiAsset() | ||
| 10 | + { | ||
| 11 | + using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt"); | ||
| 12 | + using var reader = new StreamReader(stream); | ||
| 13 | + | ||
| 14 | + var contents = reader.ReadToEnd(); | ||
| 15 | + } |
Resources/Raw/appconfig.json
0 → 100644
Resources/Splash/splash.svg
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
| 2 | +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> | ||
| 3 | +<svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"> | ||
| 4 | + <path d="m 105.50037,281.60863 c -2.70293,0 -5.00091,-0.90042 -6.893127,-2.70209 -1.892214,-1.84778 -2.837901,-4.04181 -2.837901,-6.58209 0,-2.58722 0.945687,-4.80389 2.837901,-6.65167 1.892217,-1.84778 4.190197,-2.77167 6.893127,-2.77167 2.74819,0 5.06798,0.92389 6.96019,2.77167 1.93749,1.84778 2.90581,4.06445 2.90581,6.65167 0,2.54028 -0.96832,4.73431 -2.90581,6.58209 -1.89221,1.80167 -4.212,2.70209 -6.96019,2.70209 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" /> | ||
| 5 | + <path d="M 213.56111,280.08446 H 195.99044 L 149.69953,207.0544 c -1.17121,-1.84778 -2.14037,-3.76515 -2.90581,-5.75126 h -0.40578 c 0.36051,2.12528 0.54076,6.67515 0.54076,13.6496 v 65.13172 h -15.54349 v -99.36009 h 18.71925 l 44.7374,71.29798 c 1.89222,2.95695 3.1087,4.98917 3.64945,6.09751 h 0.26996 c -0.45021,-2.6325 -0.67573,-7.09015 -0.67573,-13.37293 v -64.02256 h 15.47557 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" /> | ||
| 6 | + <path d="m 289.25134,280.08446 h -54.40052 v -99.36009 h 52.23835 v 13.99669 h -36.15411 v 28.13085 h 33.31621 v 13.9271 h -33.31621 v 29.37835 h 38.31628 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" /> | ||
| 7 | + <path d="M 366.56466,194.72106 H 338.7222 v 85.3634 h -16.08423 v -85.3634 h -27.77455 v -13.99669 h 71.70124 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" /> | ||
| 8 | +</svg> |
Resources/Styles/Colors.xaml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8" ?> | ||
| 2 | +<?xaml-comp compile="true" ?> | ||
| 3 | +<ResourceDictionary | ||
| 4 | + xmlns="http://schemas.microsoft.com/dotnet/2021/maui" | ||
| 5 | + xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"> | ||
| 6 | + | ||
| 7 | + <!-- Note: For Android please see also Platforms\Android\Resources\values\colors.xml --> | ||
| 8 | + | ||
| 9 | + <Color x:Key="Primary">#512BD4</Color> | ||
| 10 | + <Color x:Key="PrimaryDark">#ac99ea</Color> | ||
| 11 | + <Color x:Key="PrimaryDarkText">#242424</Color> | ||
| 12 | + <Color x:Key="Secondary">#DFD8F7</Color> | ||
| 13 | + <Color x:Key="SecondaryDarkText">#9880e5</Color> | ||
| 14 | + <Color x:Key="Tertiary">#2B0B98</Color> | ||
| 15 | + | ||
| 16 | + <Color x:Key="White">White</Color> | ||
| 17 | + <Color x:Key="Black">Black</Color> | ||
| 18 | + <Color x:Key="Magenta">#D600AA</Color> | ||
| 19 | + <Color x:Key="MidnightBlue">#190649</Color> | ||
| 20 | + <Color x:Key="OffBlack">#1f1f1f</Color> | ||
| 21 | + | ||
| 22 | + <Color x:Key="Gray100">#E1E1E1</Color> | ||
| 23 | + <Color x:Key="Gray200">#C8C8C8</Color> | ||
| 24 | + <Color x:Key="Gray300">#ACACAC</Color> | ||
| 25 | + <Color x:Key="Gray400">#919191</Color> | ||
| 26 | + <Color x:Key="Gray500">#6E6E6E</Color> | ||
| 27 | + <Color x:Key="Gray600">#404040</Color> | ||
| 28 | + <Color x:Key="Gray900">#212121</Color> | ||
| 29 | + <Color x:Key="Gray950">#141414</Color> | ||
| 30 | + | ||
| 31 | + <SolidColorBrush x:Key="PrimaryBrush" Color="{StaticResource Primary}"/> | ||
| 32 | + <SolidColorBrush x:Key="SecondaryBrush" Color="{StaticResource Secondary}"/> | ||
| 33 | + <SolidColorBrush x:Key="TertiaryBrush" Color="{StaticResource Tertiary}"/> | ||
| 34 | + <SolidColorBrush x:Key="WhiteBrush" Color="{StaticResource White}"/> | ||
| 35 | + <SolidColorBrush x:Key="BlackBrush" Color="{StaticResource Black}"/> | ||
| 36 | + | ||
| 37 | + <SolidColorBrush x:Key="Gray100Brush" Color="{StaticResource Gray100}"/> | ||
| 38 | + <SolidColorBrush x:Key="Gray200Brush" Color="{StaticResource Gray200}"/> | ||
| 39 | + <SolidColorBrush x:Key="Gray300Brush" Color="{StaticResource Gray300}"/> | ||
| 40 | + <SolidColorBrush x:Key="Gray400Brush" Color="{StaticResource Gray400}"/> | ||
| 41 | + <SolidColorBrush x:Key="Gray500Brush" Color="{StaticResource Gray500}"/> | ||
| 42 | + <SolidColorBrush x:Key="Gray600Brush" Color="{StaticResource Gray600}"/> | ||
| 43 | + <SolidColorBrush x:Key="Gray900Brush" Color="{StaticResource Gray900}"/> | ||
| 44 | + <SolidColorBrush x:Key="Gray950Brush" Color="{StaticResource Gray950}"/> | ||
| 45 | +</ResourceDictionary> |
Resources/Styles/Styles.xaml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8" ?> | ||
| 2 | +<?xaml-comp compile="true" ?> | ||
| 3 | +<ResourceDictionary | ||
| 4 | + xmlns="http://schemas.microsoft.com/dotnet/2021/maui" | ||
| 5 | + xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"> | ||
| 6 | + | ||
| 7 | + <Style TargetType="ActivityIndicator"> | ||
| 8 | + <Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> | ||
| 9 | + </Style> | ||
| 10 | + | ||
| 11 | + <Style TargetType="IndicatorView"> | ||
| 12 | + <Setter Property="IndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}"/> | ||
| 13 | + <Setter Property="SelectedIndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray100}}"/> | ||
| 14 | + </Style> | ||
| 15 | + | ||
| 16 | + <Style TargetType="Border"> | ||
| 17 | + <Setter Property="Stroke" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" /> | ||
| 18 | + <Setter Property="StrokeShape" Value="Rectangle"/> | ||
| 19 | + <Setter Property="StrokeThickness" Value="1"/> | ||
| 20 | + </Style> | ||
| 21 | + | ||
| 22 | + <Style TargetType="BoxView"> | ||
| 23 | + <Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" /> | ||
| 24 | + </Style> | ||
| 25 | + | ||
| 26 | + <Style TargetType="Button"> | ||
| 27 | + <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource PrimaryDarkText}}" /> | ||
| 28 | + <Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource PrimaryDark}}" /> | ||
| 29 | + <Setter Property="FontFamily" Value="OpenSansRegular"/> | ||
| 30 | + <Setter Property="FontSize" Value="14"/> | ||
| 31 | + <Setter Property="BorderWidth" Value="0"/> | ||
| 32 | + <Setter Property="CornerRadius" Value="8"/> | ||
| 33 | + <Setter Property="Padding" Value="14,10"/> | ||
| 34 | + <Setter Property="MinimumHeightRequest" Value="44"/> | ||
| 35 | + <Setter Property="MinimumWidthRequest" Value="44"/> | ||
| 36 | + <Setter Property="VisualStateManager.VisualStateGroups"> | ||
| 37 | + <VisualStateGroupList> | ||
| 38 | + <VisualStateGroup x:Name="CommonStates"> | ||
| 39 | + <VisualState x:Name="Normal" /> | ||
| 40 | + <VisualState x:Name="Disabled"> | ||
| 41 | + <VisualState.Setters> | ||
| 42 | + <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" /> | ||
| 43 | + <Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" /> | ||
| 44 | + </VisualState.Setters> | ||
| 45 | + </VisualState> | ||
| 46 | + <VisualState x:Name="PointerOver" /> | ||
| 47 | + </VisualStateGroup> | ||
| 48 | + </VisualStateGroupList> | ||
| 49 | + </Setter> | ||
| 50 | + </Style> | ||
| 51 | + | ||
| 52 | + <Style TargetType="CheckBox"> | ||
| 53 | + <Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> | ||
| 54 | + <Setter Property="MinimumHeightRequest" Value="44"/> | ||
| 55 | + <Setter Property="MinimumWidthRequest" Value="44"/> | ||
| 56 | + <Setter Property="VisualStateManager.VisualStateGroups"> | ||
| 57 | + <VisualStateGroupList> | ||
| 58 | + <VisualStateGroup x:Name="CommonStates"> | ||
| 59 | + <VisualState x:Name="Normal" /> | ||
| 60 | + <VisualState x:Name="Disabled"> | ||
| 61 | + <VisualState.Setters> | ||
| 62 | + <Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> | ||
| 63 | + </VisualState.Setters> | ||
| 64 | + </VisualState> | ||
| 65 | + </VisualStateGroup> | ||
| 66 | + </VisualStateGroupList> | ||
| 67 | + </Setter> | ||
| 68 | + </Style> | ||
| 69 | + | ||
| 70 | + <Style TargetType="DatePicker"> | ||
| 71 | + <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" /> | ||
| 72 | + <Setter Property="BackgroundColor" Value="Transparent" /> | ||
| 73 | + <Setter Property="FontFamily" Value="OpenSansRegular"/> | ||
| 74 | + <Setter Property="FontSize" Value="14"/> | ||
| 75 | + <Setter Property="MinimumHeightRequest" Value="44"/> | ||
| 76 | + <Setter Property="MinimumWidthRequest" Value="44"/> | ||
| 77 | + <Setter Property="VisualStateManager.VisualStateGroups"> | ||
| 78 | + <VisualStateGroupList> | ||
| 79 | + <VisualStateGroup x:Name="CommonStates"> | ||
| 80 | + <VisualState x:Name="Normal" /> | ||
| 81 | + <VisualState x:Name="Disabled"> | ||
| 82 | + <VisualState.Setters> | ||
| 83 | + <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" /> | ||
| 84 | + </VisualState.Setters> | ||
| 85 | + </VisualState> | ||
| 86 | + </VisualStateGroup> | ||
| 87 | + </VisualStateGroupList> | ||
| 88 | + </Setter> | ||
| 89 | + </Style> | ||
| 90 | + | ||
| 91 | + <Style TargetType="Editor"> | ||
| 92 | + <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" /> | ||
| 93 | + <Setter Property="BackgroundColor" Value="Transparent" /> | ||
| 94 | + <Setter Property="FontFamily" Value="OpenSansRegular"/> | ||
| 95 | + <Setter Property="FontSize" Value="14" /> | ||
| 96 | + <Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" /> | ||
| 97 | + <Setter Property="MinimumHeightRequest" Value="44"/> | ||
| 98 | + <Setter Property="MinimumWidthRequest" Value="44"/> | ||
| 99 | + <Setter Property="VisualStateManager.VisualStateGroups"> | ||
| 100 | + <VisualStateGroupList> | ||
| 101 | + <VisualStateGroup x:Name="CommonStates"> | ||
| 102 | + <VisualState x:Name="Normal" /> | ||
| 103 | + <VisualState x:Name="Disabled"> | ||
| 104 | + <VisualState.Setters> | ||
| 105 | + <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> | ||
| 106 | + </VisualState.Setters> | ||
| 107 | + </VisualState> | ||
| 108 | + </VisualStateGroup> | ||
| 109 | + </VisualStateGroupList> | ||
| 110 | + </Setter> | ||
| 111 | + </Style> | ||
| 112 | + | ||
| 113 | + <Style TargetType="Entry"> | ||
| 114 | + <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" /> | ||
| 115 | + <Setter Property="BackgroundColor" Value="Transparent" /> | ||
| 116 | + <Setter Property="FontFamily" Value="OpenSansRegular"/> | ||
| 117 | + <Setter Property="FontSize" Value="14" /> | ||
| 118 | + <Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" /> | ||
| 119 | + <Setter Property="MinimumHeightRequest" Value="44"/> | ||
| 120 | + <Setter Property="MinimumWidthRequest" Value="44"/> | ||
| 121 | + <Setter Property="VisualStateManager.VisualStateGroups"> | ||
| 122 | + <VisualStateGroupList> | ||
| 123 | + <VisualStateGroup x:Name="CommonStates"> | ||
| 124 | + <VisualState x:Name="Normal" /> | ||
| 125 | + <VisualState x:Name="Disabled"> | ||
| 126 | + <VisualState.Setters> | ||
| 127 | + <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> | ||
| 128 | + </VisualState.Setters> | ||
| 129 | + </VisualState> | ||
| 130 | + </VisualStateGroup> | ||
| 131 | + </VisualStateGroupList> | ||
| 132 | + </Setter> | ||
| 133 | + </Style> | ||
| 134 | + | ||
| 135 | + <Style TargetType="Frame"> | ||
| 136 | + <Setter Property="HasShadow" Value="False" /> | ||
| 137 | + <Setter Property="BorderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" /> | ||
| 138 | + <Setter Property="CornerRadius" Value="8" /> | ||
| 139 | + <Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" /> | ||
| 140 | + </Style> | ||
| 141 | + | ||
| 142 | + <Style TargetType="ImageButton"> | ||
| 143 | + <Setter Property="Opacity" Value="1" /> | ||
| 144 | + <Setter Property="BorderColor" Value="Transparent"/> | ||
| 145 | + <Setter Property="BorderWidth" Value="0"/> | ||
| 146 | + <Setter Property="CornerRadius" Value="0"/> | ||
| 147 | + <Setter Property="MinimumHeightRequest" Value="44"/> | ||
| 148 | + <Setter Property="MinimumWidthRequest" Value="44"/> | ||
| 149 | + <Setter Property="VisualStateManager.VisualStateGroups"> | ||
| 150 | + <VisualStateGroupList> | ||
| 151 | + <VisualStateGroup x:Name="CommonStates"> | ||
| 152 | + <VisualState x:Name="Normal" /> | ||
| 153 | + <VisualState x:Name="Disabled"> | ||
| 154 | + <VisualState.Setters> | ||
| 155 | + <Setter Property="Opacity" Value="0.5" /> | ||
| 156 | + </VisualState.Setters> | ||
| 157 | + </VisualState> | ||
| 158 | + <VisualState x:Name="PointerOver" /> | ||
| 159 | + </VisualStateGroup> | ||
| 160 | + </VisualStateGroupList> | ||
| 161 | + </Setter> | ||
| 162 | + </Style> | ||
| 163 | + | ||
| 164 | + <Style TargetType="Label"> | ||
| 165 | + <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" /> | ||
| 166 | + <Setter Property="BackgroundColor" Value="Transparent" /> | ||
| 167 | + <Setter Property="FontFamily" Value="OpenSansRegular" /> | ||
| 168 | + <Setter Property="FontSize" Value="14" /> | ||
| 169 | + <Setter Property="VisualStateManager.VisualStateGroups"> | ||
| 170 | + <VisualStateGroupList> | ||
| 171 | + <VisualStateGroup x:Name="CommonStates"> | ||
| 172 | + <VisualState x:Name="Normal" /> | ||
| 173 | + <VisualState x:Name="Disabled"> | ||
| 174 | + <VisualState.Setters> | ||
| 175 | + <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> | ||
| 176 | + </VisualState.Setters> | ||
| 177 | + </VisualState> | ||
| 178 | + </VisualStateGroup> | ||
| 179 | + </VisualStateGroupList> | ||
| 180 | + </Setter> | ||
| 181 | + </Style> | ||
| 182 | + | ||
| 183 | + <Style TargetType="Span"> | ||
| 184 | + <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" /> | ||
| 185 | + </Style> | ||
| 186 | + | ||
| 187 | + <Style TargetType="Label" x:Key="Headline"> | ||
| 188 | + <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource MidnightBlue}, Dark={StaticResource White}}" /> | ||
| 189 | + <Setter Property="FontSize" Value="32" /> | ||
| 190 | + <Setter Property="HorizontalOptions" Value="Center" /> | ||
| 191 | + <Setter Property="HorizontalTextAlignment" Value="Center" /> | ||
| 192 | + </Style> | ||
| 193 | + | ||
| 194 | + <Style TargetType="Label" x:Key="SubHeadline"> | ||
| 195 | + <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource MidnightBlue}, Dark={StaticResource White}}" /> | ||
| 196 | + <Setter Property="FontSize" Value="24" /> | ||
| 197 | + <Setter Property="HorizontalOptions" Value="Center" /> | ||
| 198 | + <Setter Property="HorizontalTextAlignment" Value="Center" /> | ||
| 199 | + </Style> | ||
| 200 | + | ||
| 201 | + <Style TargetType="ListView"> | ||
| 202 | + <Setter Property="SeparatorColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" /> | ||
| 203 | + <Setter Property="RefreshControlColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" /> | ||
| 204 | + </Style> | ||
| 205 | + | ||
| 206 | + <Style TargetType="Picker"> | ||
| 207 | + <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" /> | ||
| 208 | + <Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" /> | ||
| 209 | + <Setter Property="BackgroundColor" Value="Transparent" /> | ||
| 210 | + <Setter Property="FontFamily" Value="OpenSansRegular"/> | ||
| 211 | + <Setter Property="FontSize" Value="14"/> | ||
| 212 | + <Setter Property="MinimumHeightRequest" Value="44"/> | ||
| 213 | + <Setter Property="MinimumWidthRequest" Value="44"/> | ||
| 214 | + <Setter Property="VisualStateManager.VisualStateGroups"> | ||
| 215 | + <VisualStateGroupList> | ||
| 216 | + <VisualStateGroup x:Name="CommonStates"> | ||
| 217 | + <VisualState x:Name="Normal" /> | ||
| 218 | + <VisualState x:Name="Disabled"> | ||
| 219 | + <VisualState.Setters> | ||
| 220 | + <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> | ||
| 221 | + <Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> | ||
| 222 | + </VisualState.Setters> | ||
| 223 | + </VisualState> | ||
| 224 | + </VisualStateGroup> | ||
| 225 | + </VisualStateGroupList> | ||
| 226 | + </Setter> | ||
| 227 | + </Style> | ||
| 228 | + | ||
| 229 | + <Style TargetType="ProgressBar"> | ||
| 230 | + <Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> | ||
| 231 | + <Setter Property="VisualStateManager.VisualStateGroups"> | ||
| 232 | + <VisualStateGroupList> | ||
| 233 | + <VisualStateGroup x:Name="CommonStates"> | ||
| 234 | + <VisualState x:Name="Normal" /> | ||
| 235 | + <VisualState x:Name="Disabled"> | ||
| 236 | + <VisualState.Setters> | ||
| 237 | + <Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> | ||
| 238 | + </VisualState.Setters> | ||
| 239 | + </VisualState> | ||
| 240 | + </VisualStateGroup> | ||
| 241 | + </VisualStateGroupList> | ||
| 242 | + </Setter> | ||
| 243 | + </Style> | ||
| 244 | + | ||
| 245 | + <Style TargetType="RadioButton"> | ||
| 246 | + <Setter Property="BackgroundColor" Value="Transparent"/> | ||
| 247 | + <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" /> | ||
| 248 | + <Setter Property="FontFamily" Value="OpenSansRegular"/> | ||
| 249 | + <Setter Property="FontSize" Value="14"/> | ||
| 250 | + <Setter Property="MinimumHeightRequest" Value="44"/> | ||
| 251 | + <Setter Property="MinimumWidthRequest" Value="44"/> | ||
| 252 | + <Setter Property="VisualStateManager.VisualStateGroups"> | ||
| 253 | + <VisualStateGroupList> | ||
| 254 | + <VisualStateGroup x:Name="CommonStates"> | ||
| 255 | + <VisualState x:Name="Normal" /> | ||
| 256 | + <VisualState x:Name="Disabled"> | ||
| 257 | + <VisualState.Setters> | ||
| 258 | + <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> | ||
| 259 | + </VisualState.Setters> | ||
| 260 | + </VisualState> | ||
| 261 | + </VisualStateGroup> | ||
| 262 | + </VisualStateGroupList> | ||
| 263 | + </Setter> | ||
| 264 | + </Style> | ||
| 265 | + | ||
| 266 | + <Style TargetType="RefreshView"> | ||
| 267 | + <Setter Property="RefreshColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" /> | ||
| 268 | + </Style> | ||
| 269 | + | ||
| 270 | + <Style TargetType="SearchBar"> | ||
| 271 | + <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" /> | ||
| 272 | + <Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" /> | ||
| 273 | + <Setter Property="CancelButtonColor" Value="{StaticResource Gray500}" /> | ||
| 274 | + <Setter Property="BackgroundColor" Value="Transparent" /> | ||
| 275 | + <Setter Property="FontFamily" Value="OpenSansRegular" /> | ||
| 276 | + <Setter Property="FontSize" Value="14" /> | ||
| 277 | + <Setter Property="MinimumHeightRequest" Value="44"/> | ||
| 278 | + <Setter Property="MinimumWidthRequest" Value="44"/> | ||
| 279 | + <Setter Property="VisualStateManager.VisualStateGroups"> | ||
| 280 | + <VisualStateGroupList> | ||
| 281 | + <VisualStateGroup x:Name="CommonStates"> | ||
| 282 | + <VisualState x:Name="Normal" /> | ||
| 283 | + <VisualState x:Name="Disabled"> | ||
| 284 | + <VisualState.Setters> | ||
| 285 | + <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> | ||
| 286 | + <Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> | ||
| 287 | + </VisualState.Setters> | ||
| 288 | + </VisualState> | ||
| 289 | + </VisualStateGroup> | ||
| 290 | + </VisualStateGroupList> | ||
| 291 | + </Setter> | ||
| 292 | + </Style> | ||
| 293 | + | ||
| 294 | + <Style TargetType="SearchHandler"> | ||
| 295 | + <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" /> | ||
| 296 | + <Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" /> | ||
| 297 | + <Setter Property="BackgroundColor" Value="Transparent" /> | ||
| 298 | + <Setter Property="FontFamily" Value="OpenSansRegular" /> | ||
| 299 | + <Setter Property="FontSize" Value="14" /> | ||
| 300 | + <Setter Property="VisualStateManager.VisualStateGroups"> | ||
| 301 | + <VisualStateGroupList> | ||
| 302 | + <VisualStateGroup x:Name="CommonStates"> | ||
| 303 | + <VisualState x:Name="Normal" /> | ||
| 304 | + <VisualState x:Name="Disabled"> | ||
| 305 | + <VisualState.Setters> | ||
| 306 | + <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> | ||
| 307 | + <Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> | ||
| 308 | + </VisualState.Setters> | ||
| 309 | + </VisualState> | ||
| 310 | + </VisualStateGroup> | ||
| 311 | + </VisualStateGroupList> | ||
| 312 | + </Setter> | ||
| 313 | + </Style> | ||
| 314 | + | ||
| 315 | + <Style TargetType="Shadow"> | ||
| 316 | + <Setter Property="Radius" Value="15" /> | ||
| 317 | + <Setter Property="Opacity" Value="0.5" /> | ||
| 318 | + <Setter Property="Brush" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource White}}" /> | ||
| 319 | + <Setter Property="Offset" Value="10,10" /> | ||
| 320 | + </Style> | ||
| 321 | + | ||
| 322 | + <Style TargetType="Slider"> | ||
| 323 | + <Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> | ||
| 324 | + <Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" /> | ||
| 325 | + <Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> | ||
| 326 | + <Setter Property="VisualStateManager.VisualStateGroups"> | ||
| 327 | + <VisualStateGroupList> | ||
| 328 | + <VisualStateGroup x:Name="CommonStates"> | ||
| 329 | + <VisualState x:Name="Normal" /> | ||
| 330 | + <VisualState x:Name="Disabled"> | ||
| 331 | + <VisualState.Setters> | ||
| 332 | + <Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/> | ||
| 333 | + <Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/> | ||
| 334 | + <Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/> | ||
| 335 | + </VisualState.Setters> | ||
| 336 | + </VisualState> | ||
| 337 | + </VisualStateGroup> | ||
| 338 | + </VisualStateGroupList> | ||
| 339 | + </Setter> | ||
| 340 | + </Style> | ||
| 341 | + | ||
| 342 | + <Style TargetType="SwipeItem"> | ||
| 343 | + <Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" /> | ||
| 344 | + </Style> | ||
| 345 | + | ||
| 346 | + <Style TargetType="Switch"> | ||
| 347 | + <Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> | ||
| 348 | + <Setter Property="ThumbColor" Value="{StaticResource White}" /> | ||
| 349 | + <Setter Property="VisualStateManager.VisualStateGroups"> | ||
| 350 | + <VisualStateGroupList> | ||
| 351 | + <VisualStateGroup x:Name="CommonStates"> | ||
| 352 | + <VisualState x:Name="Normal" /> | ||
| 353 | + <VisualState x:Name="Disabled"> | ||
| 354 | + <VisualState.Setters> | ||
| 355 | + <Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> | ||
| 356 | + <Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> | ||
| 357 | + </VisualState.Setters> | ||
| 358 | + </VisualState> | ||
| 359 | + <VisualState x:Name="On"> | ||
| 360 | + <VisualState.Setters> | ||
| 361 | + <Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Secondary}, Dark={StaticResource Gray200}}" /> | ||
| 362 | + <Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" /> | ||
| 363 | + </VisualState.Setters> | ||
| 364 | + </VisualState> | ||
| 365 | + <VisualState x:Name="Off"> | ||
| 366 | + <VisualState.Setters> | ||
| 367 | + <Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray400}, Dark={StaticResource Gray500}}" /> | ||
| 368 | + </VisualState.Setters> | ||
| 369 | + </VisualState> | ||
| 370 | + </VisualStateGroup> | ||
| 371 | + </VisualStateGroupList> | ||
| 372 | + </Setter> | ||
| 373 | + </Style> | ||
| 374 | + | ||
| 375 | + <Style TargetType="TimePicker"> | ||
| 376 | + <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" /> | ||
| 377 | + <Setter Property="BackgroundColor" Value="Transparent"/> | ||
| 378 | + <Setter Property="FontFamily" Value="OpenSansRegular"/> | ||
| 379 | + <Setter Property="FontSize" Value="14"/> | ||
| 380 | + <Setter Property="MinimumHeightRequest" Value="44"/> | ||
| 381 | + <Setter Property="MinimumWidthRequest" Value="44"/> | ||
| 382 | + <Setter Property="VisualStateManager.VisualStateGroups"> | ||
| 383 | + <VisualStateGroupList> | ||
| 384 | + <VisualStateGroup x:Name="CommonStates"> | ||
| 385 | + <VisualState x:Name="Normal" /> | ||
| 386 | + <VisualState x:Name="Disabled"> | ||
| 387 | + <VisualState.Setters> | ||
| 388 | + <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" /> | ||
| 389 | + </VisualState.Setters> | ||
| 390 | + </VisualState> | ||
| 391 | + </VisualStateGroup> | ||
| 392 | + </VisualStateGroupList> | ||
| 393 | + </Setter> | ||
| 394 | + </Style> | ||
| 395 | + | ||
| 396 | + <Style TargetType="Page" ApplyToDerivedTypes="True"> | ||
| 397 | + <Setter Property="Padding" Value="0"/> | ||
| 398 | + <Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" /> | ||
| 399 | + </Style> | ||
| 400 | + | ||
| 401 | + <Style TargetType="Shell" ApplyToDerivedTypes="True"> | ||
| 402 | + <Setter Property="Shell.BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" /> | ||
| 403 | + <Setter Property="Shell.ForegroundColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource SecondaryDarkText}}" /> | ||
| 404 | + <Setter Property="Shell.TitleColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource SecondaryDarkText}}" /> | ||
| 405 | + <Setter Property="Shell.DisabledColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" /> | ||
| 406 | + <Setter Property="Shell.UnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray200}}" /> | ||
| 407 | + <Setter Property="Shell.NavBarHasShadow" Value="False" /> | ||
| 408 | + <Setter Property="Shell.TabBarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" /> | ||
| 409 | + <Setter Property="Shell.TabBarForegroundColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" /> | ||
| 410 | + <Setter Property="Shell.TabBarTitleColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" /> | ||
| 411 | + <Setter Property="Shell.TabBarUnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" /> | ||
| 412 | + </Style> | ||
| 413 | + | ||
| 414 | + <Style TargetType="NavigationPage"> | ||
| 415 | + <Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" /> | ||
| 416 | + <Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" /> | ||
| 417 | + <Setter Property="IconColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" /> | ||
| 418 | + </Style> | ||
| 419 | + | ||
| 420 | + <Style TargetType="TabbedPage"> | ||
| 421 | + <Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Gray950}}" /> | ||
| 422 | + <Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" /> | ||
| 423 | + <Setter Property="UnselectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" /> | ||
| 424 | + <Setter Property="SelectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" /> | ||
| 425 | + </Style> | ||
| 426 | + | ||
| 427 | +</ResourceDictionary> |
Services/ConfigLoader.cs
0 → 100644
| 1 | +using System.Text.Json; | ||
| 2 | +using IndustrialControl.Models; | ||
| 3 | + | ||
| 4 | +namespace IndustrialControl.Services; | ||
| 5 | + | ||
| 6 | +public class ConfigLoader | ||
| 7 | +{ | ||
| 8 | + public const string FileName = "appconfig.json"; | ||
| 9 | + private readonly string _configPath = Path.Combine(FileSystem.AppDataDirectory, FileName); | ||
| 10 | + | ||
| 11 | + private readonly JsonSerializerOptions _jsonOptions = new() | ||
| 12 | + { | ||
| 13 | + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, | ||
| 14 | + WriteIndented = true | ||
| 15 | + }; | ||
| 16 | + | ||
| 17 | + public event Action? ConfigChanged; | ||
| 18 | + | ||
| 19 | + public AppConfig Current { get; private set; } = new AppConfig(); | ||
| 20 | + | ||
| 21 | + public string BaseUrl => $"http://{Current.Server.IpAddress}:{Current.Server.Port}"; | ||
| 22 | + | ||
| 23 | + public ConfigLoader() | ||
| 24 | + { | ||
| 25 | + Task.Run(EnsureConfigIsLatestAsync).Wait(); | ||
| 26 | + } | ||
| 27 | + | ||
| 28 | + public async Task EnsureConfigIsLatestAsync() | ||
| 29 | + { | ||
| 30 | + using var pkgStream = await FileSystem.OpenAppPackageFileAsync(FileName); | ||
| 31 | + using var pkgReader = new StreamReader(pkgStream); | ||
| 32 | + var pkgJson = await pkgReader.ReadToEndAsync(); | ||
| 33 | + var pkgCfg = JsonSerializer.Deserialize<AppConfig>(pkgJson, _jsonOptions) ?? new AppConfig(); | ||
| 34 | + | ||
| 35 | + if (!File.Exists(_configPath)) | ||
| 36 | + { | ||
| 37 | + Directory.CreateDirectory(Path.GetDirectoryName(_configPath)!); | ||
| 38 | + await File.WriteAllTextAsync(_configPath, pkgJson); | ||
| 39 | + Current = pkgCfg; | ||
| 40 | + return; | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + var currJson = await File.ReadAllTextAsync(_configPath); | ||
| 44 | + var currCfg = JsonSerializer.Deserialize<AppConfig>(currJson, _jsonOptions) ?? new AppConfig(); | ||
| 45 | + | ||
| 46 | + if (currCfg.SchemaVersion < pkgCfg.SchemaVersion) | ||
| 47 | + { | ||
| 48 | + pkgCfg.Server = currCfg.Server; | ||
| 49 | + Current = pkgCfg; | ||
| 50 | + await SaveAsync(Current, fireChanged: false); | ||
| 51 | + } | ||
| 52 | + else | ||
| 53 | + { | ||
| 54 | + currCfg.ApiEndpoints ??= pkgCfg.ApiEndpoints; | ||
| 55 | + currCfg.Logging ??= pkgCfg.Logging; | ||
| 56 | + currCfg.Server ??= currCfg.Server ?? new ServerSettings(); | ||
| 57 | + Current = currCfg; | ||
| 58 | + } | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + public async Task SaveAsync(AppConfig cfg, bool fireChanged = true) | ||
| 62 | + { | ||
| 63 | + var json = JsonSerializer.Serialize(cfg, _jsonOptions); | ||
| 64 | + await File.WriteAllTextAsync(_configPath, json); | ||
| 65 | + Current = cfg; | ||
| 66 | + if (fireChanged) ConfigChanged?.Invoke(); | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + public async Task<AppConfig> ReloadAsync() | ||
| 70 | + { | ||
| 71 | + var json = await File.ReadAllTextAsync(_configPath); | ||
| 72 | + Current = JsonSerializer.Deserialize<AppConfig>(json, _jsonOptions) ?? new AppConfig(); | ||
| 73 | + ConfigChanged?.Invoke(); | ||
| 74 | + return Current; | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + public string GetConfigPath() => _configPath; | ||
| 78 | +} |
Services/LogService.cs
0 → 100644
| 1 | +namespace IndustrialControl.Services; | ||
| 2 | + | ||
| 3 | +public class LogService : IDisposable | ||
| 4 | +{ | ||
| 5 | + private readonly string _logsDir = Path.Combine(FileSystem.AppDataDirectory, "logs"); | ||
| 6 | + private readonly TimeSpan _interval = TimeSpan.FromMilliseconds(800); | ||
| 7 | + private CancellationTokenSource? _cts; | ||
| 8 | + | ||
| 9 | + public event Action<string>? LogTextUpdated; | ||
| 10 | + | ||
| 11 | + public string TodayLogPath => Path.Combine(_logsDir, $"gr-{DateTime.Now:yyyy-MM-dd}.txt"); | ||
| 12 | + | ||
| 13 | + public void Start() | ||
| 14 | + { | ||
| 15 | + Stop(); | ||
| 16 | + _cts = new CancellationTokenSource(); | ||
| 17 | + _ = Task.Run(() => LoopAsync(_cts.Token)); | ||
| 18 | + } | ||
| 19 | + | ||
| 20 | + public void Stop() | ||
| 21 | + { | ||
| 22 | + _cts?.Cancel(); | ||
| 23 | + _cts?.Dispose(); | ||
| 24 | + _cts = null; | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + private async Task LoopAsync(CancellationToken token) | ||
| 28 | + { | ||
| 29 | + Directory.CreateDirectory(_logsDir); | ||
| 30 | + string last = string.Empty; | ||
| 31 | + while (!token.IsCancellationRequested) | ||
| 32 | + { | ||
| 33 | + try | ||
| 34 | + { | ||
| 35 | + if (File.Exists(TodayLogPath)) | ||
| 36 | + { | ||
| 37 | + var text = await File.ReadAllTextAsync(TodayLogPath, token); | ||
| 38 | + if (!string.Equals(text, last, StringComparison.Ordinal)) | ||
| 39 | + { | ||
| 40 | + last = text; | ||
| 41 | + LogTextUpdated?.Invoke(text); | ||
| 42 | + } | ||
| 43 | + } | ||
| 44 | + } | ||
| 45 | + catch { } | ||
| 46 | + await Task.Delay(_interval, token); | ||
| 47 | + } | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + public void Dispose() => Stop(); | ||
| 51 | +} |
Services/MockWarehouseDataService.cs
0 → 100644
| 1 | +namespace IndustrialControl.Services; | ||
| 2 | + | ||
| 3 | +public interface IWarehouseDataService | ||
| 4 | +{ | ||
| 5 | + Task<InboundOrder> GetInboundOrderAsync(string orderNo); | ||
| 6 | + Task<SimpleOk> ConfirmInboundAsync(string orderNo, IEnumerable<ScanItem> items); | ||
| 7 | + | ||
| 8 | + Task<SimpleOk> ConfirmInboundProductionAsync(string orderNo, IEnumerable<ScanItem> items); | ||
| 9 | + Task<SimpleOk> ConfirmOutboundMaterialAsync(string orderNo, IEnumerable<ScanItem> items); | ||
| 10 | + Task<SimpleOk> ConfirmOutboundFinishedAsync(string orderNo, IEnumerable<ScanItem> items); | ||
| 11 | +} | ||
| 12 | + | ||
| 13 | +public record InboundOrder(string OrderNo, string Supplier, string LinkedNo, int ExpectedQty); | ||
| 14 | +public record ScanItem(int Index, string Barcode, string? Bin, int Qty); | ||
| 15 | +public record SimpleOk(bool Succeeded, string? Message = null); | ||
| 16 | + | ||
| 17 | +public class MockWarehouseDataService : IWarehouseDataService | ||
| 18 | +{ | ||
| 19 | + private readonly Random _rand = new(); | ||
| 20 | + | ||
| 21 | + public Task<InboundOrder> GetInboundOrderAsync(string orderNo) | ||
| 22 | + => Task.FromResult(new InboundOrder(orderNo, "供应商/客户:XXXX", "关联单:CGD2736273", _rand.Next(10, 80))); | ||
| 23 | + | ||
| 24 | + public Task<SimpleOk> ConfirmInboundAsync(string orderNo, IEnumerable<ScanItem> items) | ||
| 25 | + => Task.FromResult(new SimpleOk(true, $"入库成功:{items.Count()} 条")); | ||
| 26 | + | ||
| 27 | + public Task<SimpleOk> ConfirmInboundProductionAsync(string orderNo, IEnumerable<ScanItem> items) | ||
| 28 | + => Task.FromResult(new SimpleOk(true, $"生产入库成功:{items.Count()} 条")); | ||
| 29 | + | ||
| 30 | + public Task<SimpleOk> ConfirmOutboundMaterialAsync(string orderNo, IEnumerable<ScanItem> items) | ||
| 31 | + => Task.FromResult(new SimpleOk(true, $"物料出库成功:{items.Count()} 条")); | ||
| 32 | + | ||
| 33 | + public Task<SimpleOk> ConfirmOutboundFinishedAsync(string orderNo, IEnumerable<ScanItem> items) | ||
| 34 | + => Task.FromResult(new SimpleOk(true, $"成品出库成功:{items.Count()} 条")); | ||
| 35 | +} |
Services/ScanService.cs
0 → 100644
| 1 | +using CommunityToolkit.Mvvm.Messaging; | ||
| 2 | + | ||
| 3 | +namespace IndustrialControl.Services; | ||
| 4 | + | ||
| 5 | +public record ScanMessage(string Data); | ||
| 6 | + | ||
| 7 | +public class ScanService | ||
| 8 | +{ | ||
| 9 | + public void Publish(string data) | ||
| 10 | + { | ||
| 11 | + if (string.IsNullOrWhiteSpace(data)) return; | ||
| 12 | + MainThread.BeginInvokeOnMainThread(() => | ||
| 13 | + WeakReferenceMessenger.Default.Send(new ScanMessage(data.Trim()))); | ||
| 14 | + } | ||
| 15 | + | ||
| 16 | + public void Attach(Entry entry) | ||
| 17 | + { | ||
| 18 | + entry.Completed += (s, e) => Publish(((Entry)s!).Text ?? string.Empty); | ||
| 19 | + } | ||
| 20 | +} |
ViewModels/AdminViewModel.cs
0 → 100644
| 1 | +using CommunityToolkit.Mvvm.ComponentModel; | ||
| 2 | +using CommunityToolkit.Mvvm.Input; | ||
| 3 | +using IndustrialControl.Models; | ||
| 4 | +using IndustrialControl.Services; | ||
| 5 | + | ||
| 6 | +namespace IndustrialControl.ViewModels; | ||
| 7 | + | ||
| 8 | +public partial class AdminViewModel : ObservableObject | ||
| 9 | +{ | ||
| 10 | + private readonly ConfigLoader _cfg; | ||
| 11 | + | ||
| 12 | + [ObservableProperty] private int schemaVersion; | ||
| 13 | + [ObservableProperty] private string ipAddress = ""; | ||
| 14 | + [ObservableProperty] private int port; | ||
| 15 | + [ObservableProperty] private string baseUrl = ""; | ||
| 16 | + | ||
| 17 | + public AdminViewModel(ConfigLoader cfg) | ||
| 18 | + { | ||
| 19 | + _cfg = cfg; | ||
| 20 | + LoadFromConfig(); | ||
| 21 | + _cfg.ConfigChanged += () => LoadFromConfig(); | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | + private void LoadFromConfig() | ||
| 25 | + { | ||
| 26 | + var c = _cfg.Current; | ||
| 27 | + SchemaVersion = c.SchemaVersion; | ||
| 28 | + IpAddress = c.Server.IpAddress; | ||
| 29 | + Port = c.Server.Port; | ||
| 30 | + BaseUrl = _cfg.BaseUrl; | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + [RelayCommand] | ||
| 34 | + public async Task SaveAsync() | ||
| 35 | + { | ||
| 36 | + var c = _cfg.Current; | ||
| 37 | + c.Server.IpAddress = IpAddress.Trim(); | ||
| 38 | + c.Server.Port = Port; | ||
| 39 | + await _cfg.SaveAsync(c); | ||
| 40 | + BaseUrl = _cfg.BaseUrl; | ||
| 41 | + await Shell.Current.DisplayAlert("已保存", "配置已保存,可立即生效。", "确定"); | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + [RelayCommand] | ||
| 45 | + public async Task ResetToPackageAsync() | ||
| 46 | + { | ||
| 47 | + await _cfg.EnsureConfigIsLatestAsync(); | ||
| 48 | + await _cfg.ReloadAsync(); | ||
| 49 | + await Shell.Current.DisplayAlert("已重载", "已从包内默认配置重载/合并。", "确定"); | ||
| 50 | + } | ||
| 51 | +} |
ViewModels/HomeViewModel.cs
0 → 100644
| 1 | +namespace IndustrialControl.ViewModels; public partial class HomeViewModel { } |
ViewModels/InboundMaterialViewModel.cs
0 → 100644
| 1 | +using CommunityToolkit.Mvvm.ComponentModel; | ||
| 2 | +using CommunityToolkit.Mvvm.Input; | ||
| 3 | +using System.Collections.ObjectModel; | ||
| 4 | +using IndustrialControl.Services; | ||
| 5 | +using System.Threading.Tasks; | ||
| 6 | + | ||
| 7 | +namespace IndustrialControl.ViewModels | ||
| 8 | +{ | ||
| 9 | + public partial class InboundMaterialViewModel : ObservableObject | ||
| 10 | + { | ||
| 11 | + private readonly IWarehouseDataService _warehouseSvc; | ||
| 12 | + public ObservableCollection<string> AvailableBins { get; set; } = new ObservableCollection<string> | ||
| 13 | +{ | ||
| 14 | + "CK1_A201", | ||
| 15 | + "CK1_A202", | ||
| 16 | + "CK1_A203", | ||
| 17 | + "CK1_A204" | ||
| 18 | +}; | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + public InboundMaterialViewModel(IWarehouseDataService warehouseSvc) | ||
| 22 | + { | ||
| 23 | + _warehouseSvc = warehouseSvc; | ||
| 24 | + | ||
| 25 | + // 初始化命令 | ||
| 26 | + ShowPendingCommand = new RelayCommand(() => SwitchTab(true)); | ||
| 27 | + ShowScannedCommand = new RelayCommand(() => SwitchTab(false)); | ||
| 28 | + ConfirmCommand = new AsyncRelayCommand(ConfirmInboundAsync); | ||
| 29 | + | ||
| 30 | + // 默认显示待入库明细 | ||
| 31 | + IsPendingVisible = true; | ||
| 32 | + IsScannedVisible = false; | ||
| 33 | + | ||
| 34 | + // 测试数据(上线可去掉) | ||
| 35 | + PendingList = new ObservableCollection<PendingItem> | ||
| 36 | + { | ||
| 37 | + new PendingItem { Name="物料1", Spec="XXX", PendingQty=100, Bin="CK1_A201", ScannedQty=80 }, | ||
| 38 | + new PendingItem { Name="物料2", Spec="YYY", PendingQty=50, Bin="CK1_A202", ScannedQty=0 } | ||
| 39 | + }; | ||
| 40 | + | ||
| 41 | + ScannedList = new ObservableCollection<OutScannedItem> | ||
| 42 | + { | ||
| 43 | + new OutScannedItem { IsSelected=false, Barcode="FSC2025060300001", Name="物料1", Spec="XXX", Bin="CK1_A201", Qty=1 }, | ||
| 44 | + new OutScannedItem { IsSelected=false, Barcode="FSC2025060300002", Name="物料1", Spec="XXX", Bin="请选择", Qty=1 } | ||
| 45 | + }; | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + // 基础信息 | ||
| 49 | + [ObservableProperty] private string orderNo; | ||
| 50 | + [ObservableProperty] private string linkedDeliveryNo; | ||
| 51 | + [ObservableProperty] private string linkedPurchaseNo; | ||
| 52 | + [ObservableProperty] private string supplier; | ||
| 53 | + | ||
| 54 | + // Tab 显示控制 | ||
| 55 | + [ObservableProperty] private bool isPendingVisible; | ||
| 56 | + [ObservableProperty] private bool isScannedVisible; | ||
| 57 | + | ||
| 58 | + // Tab 按钮颜色 | ||
| 59 | + [ObservableProperty] private string pendingTabColor = "#E6F2FF"; | ||
| 60 | + [ObservableProperty] private string scannedTabColor = "White"; | ||
| 61 | + [ObservableProperty] private string pendingTextColor = "#007BFF"; | ||
| 62 | + [ObservableProperty] private string scannedTextColor = "#333333"; | ||
| 63 | + | ||
| 64 | + // 列表数据 | ||
| 65 | + public ObservableCollection<PendingItem> PendingList { get; set; } | ||
| 66 | + public ObservableCollection<OutScannedItem> ScannedList { get; set; } | ||
| 67 | + | ||
| 68 | + // 命令 | ||
| 69 | + public IRelayCommand ShowPendingCommand { get; } | ||
| 70 | + public IRelayCommand ShowScannedCommand { get; } | ||
| 71 | + public IAsyncRelayCommand ConfirmCommand { get; } | ||
| 72 | + | ||
| 73 | + /// <summary> | ||
| 74 | + /// 切换 Tab | ||
| 75 | + /// </summary> | ||
| 76 | + private void SwitchTab(bool showPending) | ||
| 77 | + { | ||
| 78 | + IsPendingVisible = showPending; | ||
| 79 | + IsScannedVisible = !showPending; | ||
| 80 | + | ||
| 81 | + if (showPending) | ||
| 82 | + { | ||
| 83 | + PendingTabColor = "#E6F2FF"; | ||
| 84 | + ScannedTabColor = "White"; | ||
| 85 | + PendingTextColor = "#007BFF"; | ||
| 86 | + ScannedTextColor = "#333333"; | ||
| 87 | + } | ||
| 88 | + else | ||
| 89 | + { | ||
| 90 | + PendingTabColor = "White"; | ||
| 91 | + ScannedTabColor = "#E6F2FF"; | ||
| 92 | + PendingTextColor = "#333333"; | ||
| 93 | + ScannedTextColor = "#007BFF"; | ||
| 94 | + } | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | + /// <summary> | ||
| 98 | + /// 清空扫描记录 | ||
| 99 | + /// </summary> | ||
| 100 | + public void ClearScan() | ||
| 101 | + { | ||
| 102 | + ScannedList.Clear(); | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + /// <summary> | ||
| 106 | + /// 清空所有数据 | ||
| 107 | + /// </summary> | ||
| 108 | + public void ClearAll() | ||
| 109 | + { | ||
| 110 | + OrderNo = string.Empty; | ||
| 111 | + LinkedDeliveryNo = string.Empty; | ||
| 112 | + LinkedPurchaseNo = string.Empty; | ||
| 113 | + Supplier = string.Empty; | ||
| 114 | + PendingList.Clear(); | ||
| 115 | + ScannedList.Clear(); | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | + /// <summary> | ||
| 119 | + /// 扫描通过逻辑 | ||
| 120 | + /// </summary> | ||
| 121 | + public void PassSelectedScan() | ||
| 122 | + { | ||
| 123 | + foreach (var item in ScannedList) | ||
| 124 | + { | ||
| 125 | + if (item.IsSelected) | ||
| 126 | + { | ||
| 127 | + // 这里可以做业务处理,比如更新状态 | ||
| 128 | + } | ||
| 129 | + } | ||
| 130 | + } | ||
| 131 | + | ||
| 132 | + /// <summary> | ||
| 133 | + /// 取消扫描逻辑 | ||
| 134 | + /// </summary> | ||
| 135 | + public void CancelSelectedScan() | ||
| 136 | + { | ||
| 137 | + for (int i = ScannedList.Count - 1; i >= 0; i--) | ||
| 138 | + { | ||
| 139 | + if (ScannedList[i].IsSelected) | ||
| 140 | + { | ||
| 141 | + ScannedList.RemoveAt(i); | ||
| 142 | + } | ||
| 143 | + } | ||
| 144 | + } | ||
| 145 | + | ||
| 146 | + /// <summary> | ||
| 147 | + /// 确认入库逻辑 | ||
| 148 | + /// </summary> | ||
| 149 | + public async Task<bool> ConfirmInboundAsync() | ||
| 150 | + { | ||
| 151 | + if (string.IsNullOrWhiteSpace(OrderNo)) | ||
| 152 | + return false; | ||
| 153 | + | ||
| 154 | + var result = await _warehouseSvc.ConfirmInboundAsync(OrderNo, | ||
| 155 | + ScannedList.Select(x => new ScanItem(0, x.Barcode, x.Bin, x.Qty))); | ||
| 156 | + | ||
| 157 | + return result.Succeeded; | ||
| 158 | + } | ||
| 159 | + } | ||
| 160 | + | ||
| 161 | + // 待入库明细模型 | ||
| 162 | + public class PendingItem | ||
| 163 | + { | ||
| 164 | + public string Name { get; set; } | ||
| 165 | + public string Spec { get; set; } | ||
| 166 | + public int PendingQty { get; set; } | ||
| 167 | + public string Bin { get; set; } | ||
| 168 | + public int ScannedQty { get; set; } | ||
| 169 | + } | ||
| 170 | + | ||
| 171 | + // 扫描明细模型 | ||
| 172 | + public class OutScannedItem | ||
| 173 | + { | ||
| 174 | + public bool IsSelected { get; set; } | ||
| 175 | + public string Barcode { get; set; } | ||
| 176 | + public string Name { get; set; } | ||
| 177 | + public string Spec { get; set; } | ||
| 178 | + public string Bin { get; set; } | ||
| 179 | + public int Qty { get; set; } | ||
| 180 | + } | ||
| 181 | + | ||
| 182 | +} |
ViewModels/InboundProductionViewModel.cs
0 → 100644
| 1 | +using CommunityToolkit.Mvvm.ComponentModel; | ||
| 2 | +using CommunityToolkit.Mvvm.Input; | ||
| 3 | +using System.Collections.ObjectModel; | ||
| 4 | +using IndustrialControl.Services; | ||
| 5 | +using System.Threading.Tasks; | ||
| 6 | + | ||
| 7 | +namespace IndustrialControl.ViewModels | ||
| 8 | +{ | ||
| 9 | + public partial class InboundProductionViewModel : ObservableObject | ||
| 10 | + { | ||
| 11 | + private readonly IWarehouseDataService _warehouseSvc; | ||
| 12 | + | ||
| 13 | + public InboundProductionViewModel(IWarehouseDataService warehouseSvc) | ||
| 14 | + { | ||
| 15 | + _warehouseSvc = warehouseSvc; | ||
| 16 | + | ||
| 17 | + ConfirmCommand = new AsyncRelayCommand(ConfirmInboundAsync); | ||
| 18 | + | ||
| 19 | + // 测试数据 | ||
| 20 | + Lines = new ObservableCollection<ProductionScanItem> | ||
| 21 | + { | ||
| 22 | + new ProductionScanItem { IsSelected = false, Barcode="FSC2025060300001", Bin="CK1_A201", Qty=1 }, | ||
| 23 | + new ProductionScanItem { IsSelected = false, Barcode="FSC2025060300002", Bin="CK1_A201", Qty=1 } | ||
| 24 | + }; | ||
| 25 | + | ||
| 26 | + AvailableBins = new ObservableCollection<string> | ||
| 27 | + { | ||
| 28 | + "CK1_A201", "CK1_A202", "CK1_A203" | ||
| 29 | + }; | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + // 基础信息 | ||
| 33 | + [ObservableProperty] private string orderNo; | ||
| 34 | + [ObservableProperty] private string workOrderNo; | ||
| 35 | + [ObservableProperty] private string productName; | ||
| 36 | + [ObservableProperty] private int pendingQty; | ||
| 37 | + | ||
| 38 | + public ObservableCollection<ProductionScanItem> Lines { get; set; } | ||
| 39 | + public ObservableCollection<string> AvailableBins { get; set; } | ||
| 40 | + | ||
| 41 | + public IAsyncRelayCommand ConfirmCommand { get; } | ||
| 42 | + | ||
| 43 | + public void ClearScan() | ||
| 44 | + { | ||
| 45 | + Lines.Clear(); | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + public void ClearAll() | ||
| 49 | + { | ||
| 50 | + OrderNo = string.Empty; | ||
| 51 | + WorkOrderNo = string.Empty; | ||
| 52 | + ProductName = string.Empty; | ||
| 53 | + PendingQty = 0; | ||
| 54 | + Lines.Clear(); | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + public void PassSelectedScan() | ||
| 58 | + { | ||
| 59 | + foreach (var item in Lines) | ||
| 60 | + { | ||
| 61 | + if (item.IsSelected) | ||
| 62 | + { | ||
| 63 | + // 扫描通过处理 | ||
| 64 | + } | ||
| 65 | + } | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + public void CancelSelectedScan() | ||
| 69 | + { | ||
| 70 | + for (int i = Lines.Count - 1; i >= 0; i--) | ||
| 71 | + { | ||
| 72 | + if (Lines[i].IsSelected) | ||
| 73 | + Lines.RemoveAt(i); | ||
| 74 | + } | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + public async Task<bool> ConfirmInboundAsync() | ||
| 78 | + { | ||
| 79 | + if (string.IsNullOrWhiteSpace(OrderNo)) | ||
| 80 | + return false; | ||
| 81 | + | ||
| 82 | + var result = await _warehouseSvc.ConfirmInboundProductionAsync(OrderNo, | ||
| 83 | + Lines.Select(x => new ScanItem(0, x.Barcode, x.Bin, x.Qty))); | ||
| 84 | + | ||
| 85 | + return result.Succeeded; | ||
| 86 | + } | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + public class ProductionScanItem | ||
| 90 | + { | ||
| 91 | + public bool IsSelected { get; set; } | ||
| 92 | + public string Barcode { get; set; } | ||
| 93 | + public string Bin { get; set; } | ||
| 94 | + public int Qty { get; set; } | ||
| 95 | + } | ||
| 96 | +} |
ViewModels/LoginViewModel.cs
0 → 100644
| 1 | +using CommunityToolkit.Mvvm.ComponentModel; | ||
| 2 | +using CommunityToolkit.Mvvm.Input; | ||
| 3 | + | ||
| 4 | +namespace IndustrialControl.ViewModels; | ||
| 5 | + | ||
| 6 | +public partial class LoginViewModel : ObservableObject | ||
| 7 | +{ | ||
| 8 | + [ObservableProperty] private string userName = string.Empty; | ||
| 9 | + [ObservableProperty] private string password = string.Empty; | ||
| 10 | + [ObservableProperty] private bool isBusy; | ||
| 11 | + | ||
| 12 | + [RelayCommand] | ||
| 13 | + public async Task LoginAsync() | ||
| 14 | + { | ||
| 15 | + if (IsBusy) return; IsBusy = true; | ||
| 16 | + try | ||
| 17 | + { | ||
| 18 | + await Task.Delay(200); // mock | ||
| 19 | + await Shell.Current.GoToAsync("//Home"); | ||
| 20 | + } | ||
| 21 | + catch (Exception ex) | ||
| 22 | + { | ||
| 23 | + await Application.Current.MainPage.DisplayAlert("登录失败", ex.Message, "确定"); | ||
| 24 | + } | ||
| 25 | + finally { IsBusy = false; } | ||
| 26 | + } | ||
| 27 | +} |
ViewModels/LogsViewModel.cs
0 → 100644
| 1 | +using CommunityToolkit.Mvvm.ComponentModel; | ||
| 2 | +using IndustrialControl.Services; | ||
| 3 | + | ||
| 4 | +namespace IndustrialControl.ViewModels; | ||
| 5 | + | ||
| 6 | +public partial class LogsViewModel : ObservableObject | ||
| 7 | +{ | ||
| 8 | + private readonly LogService _logSvc; | ||
| 9 | + | ||
| 10 | + [ObservableProperty] private string logText = "日志初始化中..."; | ||
| 11 | + | ||
| 12 | + public string TodayPath => _logSvc.TodayLogPath; | ||
| 13 | + | ||
| 14 | + public LogsViewModel(LogService logSvc) | ||
| 15 | + { | ||
| 16 | + _logSvc = logSvc; | ||
| 17 | + _logSvc.LogTextUpdated += text => LogText = text; | ||
| 18 | + } | ||
| 19 | + | ||
| 20 | + public void OnAppearing() => _logSvc.Start(); | ||
| 21 | + public void OnDisappearing() => _logSvc.Stop(); | ||
| 22 | +} |
ViewModels/OutboundFinishedViewModel.cs
0 → 100644
| 1 | +using CommunityToolkit.Mvvm.ComponentModel; | ||
| 2 | +using CommunityToolkit.Mvvm.Input; | ||
| 3 | +using System.Collections.ObjectModel; | ||
| 4 | +using System.Linq; | ||
| 5 | +using System.Threading.Tasks; | ||
| 6 | + | ||
| 7 | +namespace IndustrialControl.ViewModels | ||
| 8 | +{ | ||
| 9 | + public partial class OutboundFinishedViewModel : ObservableObject | ||
| 10 | + { | ||
| 11 | + #region 基础信息 | ||
| 12 | + [ObservableProperty] private string orderNo; | ||
| 13 | + [ObservableProperty] private string deliveryNo; | ||
| 14 | + [ObservableProperty] private string deliveryTime; | ||
| 15 | + [ObservableProperty] private string remark; | ||
| 16 | + #endregion | ||
| 17 | + | ||
| 18 | + #region Tab 状态 | ||
| 19 | + [ObservableProperty] private bool isPendingVisible = true; | ||
| 20 | + [ObservableProperty] private bool isScannedVisible = false; | ||
| 21 | + | ||
| 22 | + [ObservableProperty] private string pendingTabColor = "#2196F3"; | ||
| 23 | + [ObservableProperty] private string pendingTextColor = "White"; | ||
| 24 | + [ObservableProperty] private string scannedTabColor = "White"; | ||
| 25 | + [ObservableProperty] private string scannedTextColor = "Black"; | ||
| 26 | + #endregion | ||
| 27 | + | ||
| 28 | + #region 数据集合 | ||
| 29 | + public ObservableCollection<OutPendingItem> PendingList { get; } = new(); | ||
| 30 | + public ObservableCollection<OutboundScannedItem> ScannedList { get; } = new(); | ||
| 31 | + #endregion | ||
| 32 | + | ||
| 33 | + public OutboundFinishedViewModel() | ||
| 34 | + { | ||
| 35 | + // 测试数据 | ||
| 36 | + OrderNo = "CK20250001"; | ||
| 37 | + DeliveryNo = "FH20250088"; | ||
| 38 | + DeliveryTime = "2025-08-15"; | ||
| 39 | + Remark = "优先出库"; | ||
| 40 | + | ||
| 41 | + PendingList.Add(new OutPendingItem { Name = "成品A", Code = "CP001", Spec = "规格1", Bin = "A01", BatchNo = "B20250815", OutQty = 10 }); | ||
| 42 | + PendingList.Add(new OutPendingItem { Name = "成品B", Code = "CP002", Spec = "规格2", Bin = "A02", BatchNo = "B20250815", OutQty = 5 }); | ||
| 43 | + | ||
| 44 | + ScannedList.Add(new OutboundScannedItem { Barcode = "BC0001", Name = "成品A", Qty = 2 }); | ||
| 45 | + ScannedList.Add(new OutboundScannedItem { Barcode = "BC0002", Name = "成品B", Qty = 1 }); | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + #region Tab 切换命令 | ||
| 49 | + [RelayCommand] | ||
| 50 | + private void ShowPending() | ||
| 51 | + { | ||
| 52 | + IsPendingVisible = true; | ||
| 53 | + IsScannedVisible = false; | ||
| 54 | + PendingTabColor = "#2196F3"; | ||
| 55 | + PendingTextColor = "White"; | ||
| 56 | + ScannedTabColor = "White"; | ||
| 57 | + ScannedTextColor = "Black"; | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + [RelayCommand] | ||
| 61 | + private void ShowScanned() | ||
| 62 | + { | ||
| 63 | + IsPendingVisible = false; | ||
| 64 | + IsScannedVisible = true; | ||
| 65 | + PendingTabColor = "White"; | ||
| 66 | + PendingTextColor = "Black"; | ||
| 67 | + ScannedTabColor = "#2196F3"; | ||
| 68 | + ScannedTextColor = "White"; | ||
| 69 | + } | ||
| 70 | + #endregion | ||
| 71 | + | ||
| 72 | + #region 底部按钮命令 | ||
| 73 | + [RelayCommand] | ||
| 74 | + private void PassScan() | ||
| 75 | + { | ||
| 76 | + var selected = ScannedList.Where(s => s.IsSelected).ToList(); | ||
| 77 | + if (!selected.Any()) return; | ||
| 78 | + | ||
| 79 | + foreach (var item in selected) | ||
| 80 | + { | ||
| 81 | + // 模拟通过逻辑 | ||
| 82 | + item.IsSelected = false; | ||
| 83 | + } | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | + [RelayCommand] | ||
| 87 | + private void CancelScan() | ||
| 88 | + { | ||
| 89 | + var selected = ScannedList.Where(s => s.IsSelected).ToList(); | ||
| 90 | + if (!selected.Any()) return; | ||
| 91 | + | ||
| 92 | + foreach (var item in selected) | ||
| 93 | + { | ||
| 94 | + ScannedList.Remove(item); | ||
| 95 | + } | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | + [RelayCommand] | ||
| 99 | + private async Task Confirm() | ||
| 100 | + { | ||
| 101 | + // 模拟提交 | ||
| 102 | + await Task.Delay(300); | ||
| 103 | + // 这里你可以加出库成功提示逻辑 | ||
| 104 | + ClearAll(); | ||
| 105 | + } | ||
| 106 | + #endregion | ||
| 107 | + | ||
| 108 | + #region 其他方法 | ||
| 109 | + public void ClearAll() | ||
| 110 | + { | ||
| 111 | + PendingList.Clear(); | ||
| 112 | + ScannedList.Clear(); | ||
| 113 | + OrderNo = string.Empty; | ||
| 114 | + DeliveryNo = string.Empty; | ||
| 115 | + DeliveryTime = string.Empty; | ||
| 116 | + Remark = string.Empty; | ||
| 117 | + } | ||
| 118 | + public void ClearScan() | ||
| 119 | + { | ||
| 120 | + ScannedList.Clear(); | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + #endregion | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + public class OutPendingItem | ||
| 127 | + { | ||
| 128 | + public string Name { get; set; } | ||
| 129 | + public string Code { get; set; } | ||
| 130 | + public string Spec { get; set; } | ||
| 131 | + public string Bin { get; set; } | ||
| 132 | + public string BatchNo { get; set; } | ||
| 133 | + public int OutQty { get; set; } | ||
| 134 | + } | ||
| 135 | + | ||
| 136 | + public class OutboundScannedItem | ||
| 137 | + { | ||
| 138 | + public bool IsSelected { get; set; } | ||
| 139 | + public string Barcode { get; set; } | ||
| 140 | + public string Name { get; set; } | ||
| 141 | + public int Qty { get; set; } | ||
| 142 | + } | ||
| 143 | +} |
ViewModels/OutboundMaterialViewModel.cs
0 → 100644
| 1 | +using CommunityToolkit.Mvvm.ComponentModel; | ||
| 2 | +using CommunityToolkit.Mvvm.Input; | ||
| 3 | +using System.Collections.ObjectModel; | ||
| 4 | +using System.Threading.Tasks; | ||
| 5 | +using System.Linq; | ||
| 6 | +using System.Windows.Input; | ||
| 7 | +using Microsoft.Maui.Graphics; | ||
| 8 | + | ||
| 9 | +namespace IndustrialControl.ViewModels | ||
| 10 | +{ | ||
| 11 | + public partial class OutboundMaterialViewModel : ObservableObject | ||
| 12 | + { | ||
| 13 | + // ===== 基础信息 ===== | ||
| 14 | + [ObservableProperty] private string orderNo; | ||
| 15 | + [ObservableProperty] private string deliveryNo; | ||
| 16 | + [ObservableProperty] private string customerName; | ||
| 17 | + [ObservableProperty] private string deliveryTime; | ||
| 18 | + [ObservableProperty] private string linkedOrderNo; | ||
| 19 | + [ObservableProperty] private string remark; | ||
| 20 | + | ||
| 21 | + // ===== Tab 切换状态 ===== | ||
| 22 | + [ObservableProperty] private bool isPendingVisible = true; | ||
| 23 | + [ObservableProperty] private bool isScannedVisible = false; | ||
| 24 | + | ||
| 25 | + [ObservableProperty] private Color pendingTabColor = Colors.LightBlue; | ||
| 26 | + [ObservableProperty] private Color pendingTextColor = Colors.White; | ||
| 27 | + [ObservableProperty] private Color scannedTabColor = Colors.White; | ||
| 28 | + [ObservableProperty] private Color scannedTextColor = Colors.Black; | ||
| 29 | + | ||
| 30 | + // ===== 列表数据 ===== | ||
| 31 | + public ObservableCollection<OutboundPendingItem> PendingList { get; set; } = new(); | ||
| 32 | + public ObservableCollection<ScannedItem> ScannedList { get; set; } = new(); | ||
| 33 | + | ||
| 34 | + // ===== 扫码输入 ===== | ||
| 35 | + [ObservableProperty] private string scanCode; | ||
| 36 | + | ||
| 37 | + public OutboundMaterialViewModel() | ||
| 38 | + { | ||
| 39 | + LoadSampleData(); | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + private void LoadSampleData() | ||
| 43 | + { | ||
| 44 | + // 基础信息示例 | ||
| 45 | + OrderNo = "XXXXX"; | ||
| 46 | + DeliveryNo = "SCGD20250601002"; | ||
| 47 | + CustomerName = "CGD2736273"; | ||
| 48 | + DeliveryTime = "2025-08-15"; | ||
| 49 | + LinkedOrderNo = "CGD2736273"; | ||
| 50 | + Remark = "优先出库"; | ||
| 51 | + | ||
| 52 | + // 出库单明细 | ||
| 53 | + PendingList.Add(new OutboundPendingItem { Name = "产品1", Code = "XXX", Spec = "A101", Bin = "A101", BatchNo = "B20250815", OutQty = 10, ScannedQty = 10 }); | ||
| 54 | + PendingList.Add(new OutboundPendingItem { Name = "产品2", Code = "YYY", Spec = "A102", Bin = "A102", BatchNo = "B20250815", OutQty = 5, ScannedQty = 2 }); | ||
| 55 | + PendingList.Add(new OutboundPendingItem { Name = "产品3", Code = "ZZZ", Spec = "A103", Bin = "A103", BatchNo = "B20250815", OutQty = 8, ScannedQty = 0 }); | ||
| 56 | + | ||
| 57 | + // 扫描明细 | ||
| 58 | + ScannedList.Add(new ScannedItem { Barcode = "FSC2025060300001", Name = "XXXX", Qty = 1, IsSelected = true }); | ||
| 59 | + ScannedList.Add(new ScannedItem { Barcode = "FSC2025060300002", Name = "XXXX", Qty = 1, IsSelected = true }); | ||
| 60 | + ScannedList.Add(new ScannedItem { Barcode = "FSC2025060300003", Name = "XXXX", Qty = 1, IsSelected = false }); | ||
| 61 | + ScannedList.Add(new ScannedItem { Barcode = "FSC2025060300004", Name = "XXXX", Qty = 1, IsSelected = false }); | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + // ===== 操作方法 ===== | ||
| 65 | + public void ClearScan() | ||
| 66 | + { | ||
| 67 | + ScanCode = string.Empty; | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + public void ClearAll() | ||
| 71 | + { | ||
| 72 | + PendingList.Clear(); | ||
| 73 | + ScannedList.Clear(); | ||
| 74 | + ScanCode = string.Empty; | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + public void PassSelectedScan() | ||
| 78 | + { | ||
| 79 | + foreach (var item in ScannedList.Where(s => s.IsSelected)) | ||
| 80 | + { | ||
| 81 | + // 逻辑示例:标记为已通过(这里可加业务处理) | ||
| 82 | + } | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + public void CancelSelectedScan() | ||
| 86 | + { | ||
| 87 | + var toRemove = ScannedList.Where(s => s.IsSelected).ToList(); | ||
| 88 | + foreach (var item in toRemove) | ||
| 89 | + ScannedList.Remove(item); | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + public async Task<bool> ConfirmOutboundAsync() | ||
| 93 | + { | ||
| 94 | + // 模拟出库确认逻辑 | ||
| 95 | + await Task.Delay(500); // 模拟网络延迟 | ||
| 96 | + return true; | ||
| 97 | + } | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + // 出库单明细数据模型 | ||
| 101 | + public class OutboundPendingItem | ||
| 102 | + { | ||
| 103 | + public string Name { get; set; } | ||
| 104 | + public string Code { get; set; } | ||
| 105 | + public string Spec { get; set; } | ||
| 106 | + public string Bin { get; set; } | ||
| 107 | + public string BatchNo { get; set; } | ||
| 108 | + public int OutQty { get; set; } | ||
| 109 | + public int ScannedQty { get; set; } | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | + // 扫描明细数据模型 | ||
| 113 | + public class ScannedItem | ||
| 114 | + { | ||
| 115 | + public bool IsSelected { get; set; } | ||
| 116 | + public string Barcode { get; set; } | ||
| 117 | + public string Name { get; set; } | ||
| 118 | + public int Qty { get; set; } | ||
| 119 | + } | ||
| 120 | +} |
-
请 注册 或 登录 后发表评论