作者 李壮

outbound

正在显示 45 个修改的文件 包含 211 行增加192 行删除
1 -using Microsoft.Extensions.DependencyInjection;  
2 -  
3 namespace IndustrialControl; 1 namespace IndustrialControl;
4 2
5 public partial class App : Application 3 public partial class App : Application
1 -using Microsoft.Extensions.DependencyInjection;  
2 -  
3 -namespace IndustrialControl; 1 +namespace IndustrialControl;
4 2
5 public partial class AppShell : Shell 3 public partial class AppShell : Shell
6 { 4 {
1 <Project Sdk="Microsoft.NET.Sdk"> 1 <Project Sdk="Microsoft.NET.Sdk">
2 2
3 <PropertyGroup> 3 <PropertyGroup>
4 - <TargetFrameworks>net8.0-android;net8.0-ios;net8.0-maccatalyst</TargetFrameworks> 4 + <TargetFrameworks>net8.0-android</TargetFrameworks>
5 <TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-windows10.0.19041.0</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 --> 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> --> 7 <!-- <TargetFrameworks>$(TargetFrameworks);net8.0-tizen</TargetFrameworks> -->
@@ -36,6 +36,7 @@ @@ -36,6 +36,7 @@
36 <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.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> 37 <TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
38 <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion> 38 <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion>
  39 + <SkipValidateMauiImplicitPackageReferences>true</SkipValidateMauiImplicitPackageReferences>
39 </PropertyGroup> 40 </PropertyGroup>
40 <!-- Debug 下:关裁剪、关AOT、关链接器;仅安卓生效 --> 41 <!-- Debug 下:关裁剪、关AOT、关链接器;仅安卓生效 -->
41 <PropertyGroup Condition="'$(Configuration)'=='Debug' and $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'"> 42 <PropertyGroup Condition="'$(Configuration)'=='Debug' and $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">
1 -using Microsoft.Extensions.Logging;  
2 -using Microsoft.Extensions.DependencyInjection; 1 +using CommunityToolkit.Maui;
3 using IndustrialControl.Services; 2 using IndustrialControl.Services;
4 -using CommunityToolkit.Maui;  
5 using IndustrialControl.ViewModels; 3 using IndustrialControl.ViewModels;
  4 +using Microsoft.Extensions.Logging;
6 5
7 namespace IndustrialControl 6 namespace IndustrialControl
8 { 7 {
1 namespace IndustrialControl.Pages; 1 namespace IndustrialControl.Pages;
2 public partial class AdminPage : ContentPage 2 public partial class AdminPage : ContentPage
3 -{ public AdminPage(ViewModels.AdminViewModel vm) 3 +{
  4 + public AdminPage(ViewModels.AdminViewModel vm)
4 { InitializeComponent(); BindingContext = vm; } 5 { InitializeComponent(); BindingContext = vm; }
5 } 6 }
1 namespace IndustrialControl.Pages; 1 namespace IndustrialControl.Pages;
2 public partial class LoginPage : ContentPage 2 public partial class LoginPage : ContentPage
3 -{ public LoginPage(ViewModels.LoginViewModel vm) 3 +{
  4 + public LoginPage(ViewModels.LoginViewModel vm)
4 { InitializeComponent(); BindingContext = vm; } 5 { InitializeComponent(); BindingContext = vm; }
5 } 6 }
@@ -2,7 +2,7 @@ namespace IndustrialControl.Pages; @@ -2,7 +2,7 @@ namespace IndustrialControl.Pages;
2 2
3 public partial class LogsPage : ContentPage 3 public partial class LogsPage : ContentPage
4 { 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(); } 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 } 8 }
@@ -50,8 +50,8 @@ public partial class OutboundMoldSearchPage : ContentPage @@ -50,8 +50,8 @@ public partial class OutboundMoldSearchPage : ContentPage
50 50
51 // 点整张卡片跳转(推荐) 51 // 点整张卡片跳转(推荐)
52 52
53 -private async void OnOrderTapped(object sender, TappedEventArgs e)  
54 -{ 53 + private async void OnOrderTapped(object sender, TappedEventArgs e)
  54 + {
55 try 55 try
56 { 56 {
57 if (e.Parameter is not MoldDto item) return; 57 if (e.Parameter is not MoldDto item) return;
@@ -70,9 +70,9 @@ private async void OnOrderTapped(object sender, TappedEventArgs e) @@ -70,9 +70,9 @@ private async void OnOrderTapped(object sender, TappedEventArgs e)
70 { 70 {
71 await DisplayAlert("导航失败", ex.Message, "确定"); 71 await DisplayAlert("导航失败", ex.Message, "确定");
72 } 72 }
73 -} 73 + }
74 74
75 75
76 -private async void OnScanHintClicked(object sender, EventArgs e) 76 + private async void OnScanHintClicked(object sender, EventArgs e)
77 => await DisplayAlert("提示", "此按钮预留摄像头扫码;硬件扫描直接扣扳机。", "确定"); 77 => await DisplayAlert("提示", "此按钮预留摄像头扫码;硬件扫描直接扣扳机。", "确定");
78 } 78 }
1 -using System.Text.Json;  
2 -using IndustrialControl.Models; 1 +using IndustrialControl.Models;
3 using IndustrialControl.ViewModels; 2 using IndustrialControl.ViewModels;
  3 +using System.Text.Json;
4 4
5 namespace IndustrialControl.Pages; 5 namespace IndustrialControl.Pages;
6 6
@@ -50,8 +50,8 @@ public partial class WorkOrderSearchPage : ContentPage @@ -50,8 +50,8 @@ public partial class WorkOrderSearchPage : ContentPage
50 50
51 // 点整张卡片跳转(推荐) 51 // 点整张卡片跳转(推荐)
52 52
53 -private async void OnOrderTapped(object sender, TappedEventArgs e)  
54 -{ 53 + private async void OnOrderTapped(object sender, TappedEventArgs e)
  54 + {
55 try 55 try
56 { 56 {
57 if (e.Parameter is not WorkOrderDto item) return; 57 if (e.Parameter is not WorkOrderDto item) return;
@@ -70,9 +70,9 @@ private async void OnOrderTapped(object sender, TappedEventArgs e) @@ -70,9 +70,9 @@ private async void OnOrderTapped(object sender, TappedEventArgs e)
70 { 70 {
71 await DisplayAlert("导航失败", ex.Message, "确定"); 71 await DisplayAlert("导航失败", ex.Message, "确定");
72 } 72 }
73 -} 73 + }
74 74
75 75
76 -private async void OnScanHintClicked(object sender, EventArgs e) 76 + private async void OnScanHintClicked(object sender, EventArgs e)
77 => await DisplayAlert("提示", "此按钮预留摄像头扫码;硬件扫描直接扣扳机。", "确定"); 77 => await DisplayAlert("提示", "此按钮预留摄像头扫码;硬件扫描直接扣扳机。", "确定");
78 } 78 }
1 -using System.Collections.ObjectModel;  
2 -using IndustrialControl.Models;  
3 -using IndustrialControl.Services; 1 +using IndustrialControl.Models;
  2 +using System.Collections.ObjectModel;
4 3
5 namespace IndustrialControl.Pages; 4 namespace IndustrialControl.Pages;
6 5
1 using IndustrialControl.Models; 1 using IndustrialControl.Models;
2 -using IndustrialControl.Services;  
3 using IndustrialControl.ViewModels; 2 using IndustrialControl.ViewModels;
4 3
5 namespace IndustrialControl.Pages; 4 namespace IndustrialControl.Pages;
@@ -55,7 +55,7 @@ @@ -55,7 +55,7 @@
55 <Label.FormattedText> 55 <Label.FormattedText>
56 <FormattedString> 56 <FormattedString>
57 <Span Text="客户:" FontAttributes="Bold"/> 57 <Span Text="客户:" FontAttributes="Bold"/>
58 - <Span Text="{Binding PurchaseNo}"/> 58 + <Span Text="{Binding Customer}"/>
59 </FormattedString> 59 </FormattedString>
60 </Label.FormattedText> 60 </Label.FormattedText>
61 </Label> 61 </Label>
@@ -65,7 +65,7 @@ @@ -65,7 +65,7 @@
65 <Label.FormattedText> 65 <Label.FormattedText>
66 <FormattedString> 66 <FormattedString>
67 <Span Text="要求发货时间:" FontAttributes="Bold"/> 67 <Span Text="要求发货时间:" FontAttributes="Bold"/>
68 - <Span Text="{Binding SupplierName}"/> 68 + <Span Text="{Binding ExpectedDeliveryTime}"/>
69 </FormattedString> 69 </FormattedString>
70 </Label.FormattedText> 70 </Label.FormattedText>
71 </Label> 71 </Label>
@@ -74,7 +74,7 @@ @@ -74,7 +74,7 @@
74 <Label.FormattedText> 74 <Label.FormattedText>
75 <FormattedString> 75 <FormattedString>
76 <Span Text="关联销售单:" FontAttributes="Bold"/> 76 <Span Text="关联销售单:" FontAttributes="Bold"/>
77 - <Span Text="{Binding SupplierName}"/> 77 + <Span Text="{Binding saleNo}"/>
78 </FormattedString> 78 </FormattedString>
79 </Label.FormattedText> 79 </Label.FormattedText>
80 </Label> 80 </Label>
@@ -83,7 +83,7 @@ @@ -83,7 +83,7 @@
83 <Label.FormattedText> 83 <Label.FormattedText>
84 <FormattedString> 84 <FormattedString>
85 <Span Text="发货单备注:" FontAttributes="Bold"/> 85 <Span Text="发货单备注:" FontAttributes="Bold"/>
86 - <Span Text="{Binding SupplierName}"/> 86 + <Span Text="{Binding DeliveryMemo}"/>
87 </FormattedString> 87 </FormattedString>
88 </Label.FormattedText> 88 </Label.FormattedText>
89 </Label> 89 </Label>
@@ -150,11 +150,12 @@ @@ -150,11 +150,12 @@
150 </CollectionView> 150 </CollectionView>
151 151
152 <!-- 扫描明细表头 --> 152 <!-- 扫描明细表头 -->
153 - <Grid Grid.Row="1" ColumnDefinitions="40,*,*,*" BackgroundColor="#F2F2F2" IsVisible="{Binding IsScannedVisible}" Padding="8"> 153 + <Grid Grid.Row="1" ColumnDefinitions="40,*,*,*,*" BackgroundColor="#F2F2F2" IsVisible="{Binding IsScannedVisible}" Padding="8">
154 <Label Text="选择" FontAttributes="Bold" /> 154 <Label Text="选择" FontAttributes="Bold" />
155 <Label Grid.Column="1" Text="物料名称" FontAttributes="Bold" /> 155 <Label Grid.Column="1" Text="物料名称" FontAttributes="Bold" />
156 <Label Grid.Column="2" Text="条码" FontAttributes="Bold" /> 156 <Label Grid.Column="2" Text="条码" FontAttributes="Bold" />
157 - <Label Grid.Column="3" Text="数量" FontAttributes="Bold" /> 157 + <Label Grid.Column="3" Text="出库数量" FontAttributes="Bold" />
  158 + <Label Grid.Column="4" Text="数量" FontAttributes="Bold" />
158 </Grid> 159 </Grid>
159 160
160 <!-- 扫描明细列表 --> 161 <!-- 扫描明细列表 -->
@@ -165,7 +166,7 @@ @@ -165,7 +166,7 @@
165 SelectedItem="{Binding SelectedScanItem, Mode=TwoWay}"> 166 SelectedItem="{Binding SelectedScanItem, Mode=TwoWay}">
166 <CollectionView.ItemTemplate> 167 <CollectionView.ItemTemplate>
167 <DataTemplate> 168 <DataTemplate>
168 - <Grid ColumnDefinitions="40,*,*,*" Padding="8" BackgroundColor="White"> 169 + <Grid ColumnDefinitions="40,*,*,*,*" Padding="8" BackgroundColor="White">
169 <Grid.Triggers> 170 <Grid.Triggers>
170 <!-- ScanStatus = true → 绿色 --> 171 <!-- ScanStatus = true → 绿色 -->
171 <DataTrigger TargetType="Grid" Binding="{Binding ScanStatus}" Value="True"> 172 <DataTrigger TargetType="Grid" Binding="{Binding ScanStatus}" Value="True">
@@ -176,7 +177,8 @@ @@ -176,7 +177,8 @@
176 <CheckBox IsChecked="{Binding IsSelected}" /> 177 <CheckBox IsChecked="{Binding IsSelected}" />
177 <Label Grid.Column="1" Text="{Binding Name}" /> 178 <Label Grid.Column="1" Text="{Binding Name}" />
178 <Label Grid.Column="2" Text="{Binding Barcode}" /> 179 <Label Grid.Column="2" Text="{Binding Barcode}" />
179 - <Entry Grid.Column="3" 180 + <Label Grid.Column="3" Text="{Binding OutstockQty}" />
  181 + <Entry Grid.Column="4"
180 Keyboard="Numeric" 182 Keyboard="Numeric"
181 HorizontalTextAlignment="Center" 183 HorizontalTextAlignment="Center"
182 WidthRequest="64" 184 WidthRequest="64"
@@ -5,24 +5,22 @@ namespace IndustrialControl.Pages; @@ -5,24 +5,22 @@ namespace IndustrialControl.Pages;
5 5
6 [QueryProperty(nameof(OutstockId), "outstockId")] 6 [QueryProperty(nameof(OutstockId), "outstockId")]
7 [QueryProperty(nameof(OutstockNo), "outstockNo")] 7 [QueryProperty(nameof(OutstockNo), "outstockNo")]
8 -[QueryProperty(nameof(OrderType), "orderType")]  
9 -[QueryProperty(nameof(OrderTypeName), "orderTypeName")]  
10 -[QueryProperty(nameof(RequisitionMaterialNo), "requisitionMaterialNo")]  
11 -[QueryProperty(nameof(ReturnNo), "returnNo")]  
12 [QueryProperty(nameof(DeliveryNo), "deliveryNo")] 8 [QueryProperty(nameof(DeliveryNo), "deliveryNo")]
13 -[QueryProperty(nameof(CreatedTime), "createdTime")] 9 +[QueryProperty(nameof(Customer), "customer")]
  10 +[QueryProperty(nameof(ExpectedDeliveryTime), "expectedDeliveryTime")]
  11 +[QueryProperty(nameof(SaleNo), "saleNo")]
  12 +[QueryProperty(nameof(DeliveryMemo), "deliveryMemo")]
14 public partial class OutboundFinishedPage : ContentPage 13 public partial class OutboundFinishedPage : ContentPage
15 { 14 {
16 private readonly ScanService _scanSvc; 15 private readonly ScanService _scanSvc;
17 private readonly OutboundFinishedViewModel _vm; 16 private readonly OutboundFinishedViewModel _vm;
18 public string? OutstockId { get; set; } 17 public string? OutstockId { get; set; }
19 public string? OutstockNo { get; set; } 18 public string? OutstockNo { get; set; }
20 - public string? OrderType { get; set; }  
21 - public string? OrderTypeName { get; set; }  
22 - public string? RequisitionMaterialNo { get; set; }  
23 - public string? ReturnNo { get; set; } 19 + public string? Customer { get; set; }
  20 + public string? ExpectedDeliveryTime { get; set; }
24 public string? DeliveryNo { get; set; } 21 public string? DeliveryNo { get; set; }
25 - public string? CreatedTime { get; set; } 22 + public string? SaleNo { get; set; }
  23 + public string? DeliveryMemo { get; set; }
26 private readonly IDialogService _dialogs; 24 private readonly IDialogService _dialogs;
27 25
28 public OutboundFinishedPage(OutboundFinishedViewModel vm, ScanService scanSvc, IDialogService dialogs) 26 public OutboundFinishedPage(OutboundFinishedViewModel vm, ScanService scanSvc, IDialogService dialogs)
@@ -51,12 +49,11 @@ public partial class OutboundFinishedPage : ContentPage @@ -51,12 +49,11 @@ public partial class OutboundFinishedPage : ContentPage
51 await _vm.InitializeFromSearchAsync( 49 await _vm.InitializeFromSearchAsync(
52 outstockId: OutstockId ?? "", 50 outstockId: OutstockId ?? "",
53 outstockNo: OutstockNo ?? "", 51 outstockNo: OutstockNo ?? "",
54 - orderType: OrderType ?? "",  
55 - orderTypeName: OrderTypeName ?? "",  
56 - requisitionMaterialNo: RequisitionMaterialNo ?? "",  
57 - returnNo: ReturnNo ?? "",  
58 deliveryNo: DeliveryNo ?? "", 52 deliveryNo: DeliveryNo ?? "",
59 - createdTime: CreatedTime ?? "" 53 + customer: Customer ?? "",
  54 + expectedDeliveryTime: ExpectedDeliveryTime ?? "",
  55 + saleNo: SaleNo ?? "",
  56 + deliveryMemo: DeliveryMemo ?? ""
60 ); 57 );
61 } 58 }
62 59
@@ -55,7 +55,7 @@ @@ -55,7 +55,7 @@
55 <Label Grid.Row="2" Grid.Column="1" Text="{Binding deliveryNo}" /> 55 <Label Grid.Row="2" Grid.Column="1" Text="{Binding deliveryNo}" />
56 56
57 <Label Grid.Row="3" Grid.Column="0" Text="关联销售号:" FontAttributes="Bold"/> 57 <Label Grid.Row="3" Grid.Column="0" Text="关联销售号:" FontAttributes="Bold"/>
58 - <Label Grid.Row="3" Grid.Column="1" Text="{Binding arrivalNo}" /> 58 + <Label Grid.Row="3" Grid.Column="1" Text="{Binding saleNo}" />
59 59
60 <Label Grid.Row="4" Grid.Column="0" Text="创建日期:" FontAttributes="Bold"/> 60 <Label Grid.Row="4" Grid.Column="0" Text="创建日期:" FontAttributes="Bold"/>
61 <Label Grid.Row="4" Grid.Column="1" Text="{Binding createdTime}" /> 61 <Label Grid.Row="4" Grid.Column="1" Text="{Binding createdTime}" />
@@ -65,7 +65,7 @@ @@ -65,7 +65,7 @@
65 <Label.FormattedText> 65 <Label.FormattedText>
66 <FormattedString> 66 <FormattedString>
67 <Span Text="出库单备注:" FontAttributes="Bold"/> 67 <Span Text="出库单备注:" FontAttributes="Bold"/>
68 - <Span Text="{Binding SupplierName}"/> 68 + <Span Text="{Binding Memo}"/>
69 </FormattedString> 69 </FormattedString>
70 </Label.FormattedText> 70 </Label.FormattedText>
71 </Label> 71 </Label>
@@ -133,11 +133,12 @@ @@ -133,11 +133,12 @@
133 </CollectionView> 133 </CollectionView>
134 134
135 <!-- 扫描明细表头 --> 135 <!-- 扫描明细表头 -->
136 - <Grid Grid.Row="1" ColumnDefinitions="40,*,*,*" BackgroundColor="#F2F2F2" IsVisible="{Binding IsScannedVisible}" Padding="8"> 136 + <Grid Grid.Row="1" ColumnDefinitions="40,*,*,*,*" BackgroundColor="#F2F2F2" IsVisible="{Binding IsScannedVisible}" Padding="8">
137 <Label Text="选择" FontAttributes="Bold" /> 137 <Label Text="选择" FontAttributes="Bold" />
138 <Label Grid.Column="1" Text="物料名称" FontAttributes="Bold" /> 138 <Label Grid.Column="1" Text="物料名称" FontAttributes="Bold" />
139 <Label Grid.Column="2" Text="条码" FontAttributes="Bold" /> 139 <Label Grid.Column="2" Text="条码" FontAttributes="Bold" />
140 - <Label Grid.Column="3" Text="数量" FontAttributes="Bold" /> 140 + <Label Grid.Column="3" Text="出库数量" FontAttributes="Bold" />
  141 + <Label Grid.Column="4" Text="数量" FontAttributes="Bold" />
141 </Grid> 142 </Grid>
142 143
143 <!-- 扫描明细列表 --> 144 <!-- 扫描明细列表 -->
@@ -148,7 +149,7 @@ @@ -148,7 +149,7 @@
148 SelectedItem="{Binding SelectedScanItem, Mode=TwoWay}"> 149 SelectedItem="{Binding SelectedScanItem, Mode=TwoWay}">
149 <CollectionView.ItemTemplate> 150 <CollectionView.ItemTemplate>
150 <DataTemplate> 151 <DataTemplate>
151 - <Grid ColumnDefinitions="40,*,*,*" Padding="8" BackgroundColor="White"> 152 + <Grid ColumnDefinitions="40,*,*,*,*" Padding="8" BackgroundColor="White">
152 <Grid.Triggers> 153 <Grid.Triggers>
153 <!-- ScanStatus = true → 绿色 --> 154 <!-- ScanStatus = true → 绿色 -->
154 <DataTrigger TargetType="Grid" Binding="{Binding ScanStatus}" Value="True"> 155 <DataTrigger TargetType="Grid" Binding="{Binding ScanStatus}" Value="True">
@@ -159,7 +160,8 @@ @@ -159,7 +160,8 @@
159 <CheckBox IsChecked="{Binding IsSelected}" /> 160 <CheckBox IsChecked="{Binding IsSelected}" />
160 <Label Grid.Column="1" Text="{Binding Name}" /> 161 <Label Grid.Column="1" Text="{Binding Name}" />
161 <Label Grid.Column="2" Text="{Binding Barcode}" /> 162 <Label Grid.Column="2" Text="{Binding Barcode}" />
162 - <Entry Grid.Column="3" 163 + <Label Grid.Column="3" Text="{Binding OutstockQty}" />
  164 + <Entry Grid.Column="4"
163 Keyboard="Numeric" 165 Keyboard="Numeric"
164 HorizontalTextAlignment="Center" 166 HorizontalTextAlignment="Center"
165 WidthRequest="64" 167 WidthRequest="64"
@@ -5,24 +5,18 @@ namespace IndustrialControl.Pages; @@ -5,24 +5,18 @@ namespace IndustrialControl.Pages;
5 5
6 [QueryProperty(nameof(OutstockId), "outstockId")] 6 [QueryProperty(nameof(OutstockId), "outstockId")]
7 [QueryProperty(nameof(OutstockNo), "outstockNo")] 7 [QueryProperty(nameof(OutstockNo), "outstockNo")]
8 -[QueryProperty(nameof(OrderType), "orderType")]  
9 -[QueryProperty(nameof(OrderTypeName), "orderTypeName")]  
10 [QueryProperty(nameof(RequisitionMaterialNo), "requisitionMaterialNo")] 8 [QueryProperty(nameof(RequisitionMaterialNo), "requisitionMaterialNo")]
11 -[QueryProperty(nameof(ReturnNo), "returnNo")]  
12 -[QueryProperty(nameof(DeliveryNo), "deliveryNo")]  
13 -[QueryProperty(nameof(CreatedTime), "createdTime")] 9 +[QueryProperty(nameof(WorkOrderNo), "workOrderNo")]
  10 +[QueryProperty(nameof(Memo), "memo")]
14 public partial class OutboundMaterialPage : ContentPage 11 public partial class OutboundMaterialPage : ContentPage
15 { 12 {
16 private readonly ScanService _scanSvc; 13 private readonly ScanService _scanSvc;
17 private readonly OutboundMaterialViewModel _vm; 14 private readonly OutboundMaterialViewModel _vm;
18 public string? OutstockId { get; set; } 15 public string? OutstockId { get; set; }
19 public string? OutstockNo { get; set; } 16 public string? OutstockNo { get; set; }
20 - public string? OrderType { get; set; }  
21 - public string? OrderTypeName { get; set; }  
22 public string? RequisitionMaterialNo { get; set; } 17 public string? RequisitionMaterialNo { get; set; }
23 - public string? ReturnNo { get; set; }  
24 - public string? DeliveryNo { get; set; }  
25 - public string? CreatedTime { get; set; } 18 + public string? WorkOrderNo { get; set; }
  19 + public string? Memo { get; set; }
26 private readonly IDialogService _dialogs; 20 private readonly IDialogService _dialogs;
27 21
28 public OutboundMaterialPage(OutboundMaterialViewModel vm, ScanService scanSvc, IDialogService dialogs) 22 public OutboundMaterialPage(OutboundMaterialViewModel vm, ScanService scanSvc, IDialogService dialogs)
@@ -51,12 +45,9 @@ public partial class OutboundMaterialPage : ContentPage @@ -51,12 +45,9 @@ public partial class OutboundMaterialPage : ContentPage
51 await _vm.InitializeFromSearchAsync( 45 await _vm.InitializeFromSearchAsync(
52 outstockId: OutstockId ?? "", 46 outstockId: OutstockId ?? "",
53 outstockNo: OutstockNo ?? "", 47 outstockNo: OutstockNo ?? "",
54 - orderType: OrderType ?? "",  
55 - orderTypeName: OrderTypeName ?? "",  
56 requisitionMaterialNo: RequisitionMaterialNo ?? "", 48 requisitionMaterialNo: RequisitionMaterialNo ?? "",
57 - returnNo: ReturnNo ?? "",  
58 - deliveryNo: DeliveryNo ?? "",  
59 - createdTime: CreatedTime ?? "" 49 + workOrderNo: WorkOrderNo ?? "",
  50 + memo: Memo ?? ""
60 ); 51 );
61 } 52 }
62 53
1 -using Microsoft.UI.Xaml;  
2 -  
3 -// To learn more about WinUI, the WinUI project structure, 1 +// To learn more about WinUI, the WinUI project structure,
4 // and more about our project templates, see: http://aka.ms/winui-project-info. 2 // and more about our project templates, see: http://aka.ms/winui-project-info.
5 3
6 namespace IndustrialControl.WinUI 4 namespace IndustrialControl.WinUI
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
  3 +<Project>
  4 + <PropertyGroup>
  5 + <Configuration>Release</Configuration>
  6 + <Platform>Any CPU</Platform>
  7 + <PublishDir>bin\Release\net8.0-android\publish\</PublishDir>
  8 + <PublishProtocol>FileSystem</PublishProtocol>
  9 + <_TargetId>Folder</_TargetId>
  10 + </PropertyGroup>
  11 +</Project>
1 // Services/AuthHeaderHandler.cs 1 // Services/AuthHeaderHandler.cs
2 -using System.Net;  
3 using System.Net.Http.Headers; 2 using System.Net.Http.Headers;
4 3
5 namespace IndustrialControl.Services 4 namespace IndustrialControl.Services
1 -using System.Text.Json;  
2 using IndustrialControl.Models; 1 using IndustrialControl.Models;
  2 +using System.Text.Json;
3 3
4 namespace IndustrialControl.Services; 4 namespace IndustrialControl.Services;
5 5
1 -using Microsoft.Maui.Dispatching; 1 +using IndustrialControl.Models;
2 using IndustrialControl.Pages; 2 using IndustrialControl.Pages;
3 -using IndustrialControl.Models;  
4 3
5 namespace IndustrialControl.Services; 4 namespace IndustrialControl.Services;
6 5
@@ -33,9 +33,9 @@ public interface IInboundMaterialService @@ -33,9 +33,9 @@ public interface IInboundMaterialService
33 Task<List<LocationNodeDto>> GetLocationTreeAsync(CancellationToken ct = default); 33 Task<List<LocationNodeDto>> GetLocationTreeAsync(CancellationToken ct = default);
34 34
35 Task<List<BinInfo>> GetBinsByLayerAsync( 35 Task<List<BinInfo>> GetBinsByLayerAsync(
36 - string warehouseCode, string layer,  
37 - int pageNo = 1, int pageSize = 50, int status = 1,  
38 - CancellationToken ct = default); 36 +string warehouseCode, string layer,
  37 +int pageNo = 1, int pageSize = 50, int status = 1,
  38 +CancellationToken ct = default);
39 39
40 /// <summary>更新扫描明细的库位(/normalService/pda/wmsMaterialInstock/updateLocation)</summary> 40 /// <summary>更新扫描明细的库位(/normalService/pda/wmsMaterialInstock/updateLocation)</summary>
41 Task<SimpleOk> UpdateInstockLocationAsync( 41 Task<SimpleOk> UpdateInstockLocationAsync(
1 using IndustrialControl.Models; 1 using IndustrialControl.Models;
2 -using IndustrialControl.ViewModels;  
3 -using System.Net.Http.Json;  
4 using System.Text; 2 using System.Text;
5 using System.Text.Json; 3 using System.Text.Json;
6 using System.Text.Json.Nodes; 4 using System.Text.Json.Nodes;
@@ -210,7 +208,7 @@ namespace IndustrialControl.Services @@ -210,7 +208,7 @@ namespace IndustrialControl.Services
210 return resp; 208 return resp;
211 } 209 }
212 210
213 -public async Task<DictBundle> GetMoldDictsAsync(CancellationToken ct = default) 211 + public async Task<DictBundle> GetMoldDictsAsync(CancellationToken ct = default)
214 { 212 {
215 using var req = new HttpRequestMessage(HttpMethod.Get, _dictEndpoint); 213 using var req = new HttpRequestMessage(HttpMethod.Get, _dictEndpoint);
216 using var res = await _http.SendAsync(req, ct); 214 using var res = await _http.SendAsync(req, ct);
1 -using System.Net.Http.Json;  
2 -using System.Text.Json; 1 +using System.Text.Json;
3 using System.Text.Json.Nodes; 2 using System.Text.Json.Nodes;
4 3
5 namespace IndustrialControl.Services 4 namespace IndustrialControl.Services
@@ -172,7 +171,7 @@ namespace IndustrialControl.Services @@ -172,7 +171,7 @@ namespace IndustrialControl.Services
172 return resp; 171 return resp;
173 } 172 }
174 173
175 -public async Task<DictBundle> GetWorkOrderDictsAsync(CancellationToken ct = default) 174 + public async Task<DictBundle> GetWorkOrderDictsAsync(CancellationToken ct = default)
176 { 175 {
177 using var req = new HttpRequestMessage(HttpMethod.Get, _dictEndpoint); 176 using var req = new HttpRequestMessage(HttpMethod.Get, _dictEndpoint);
178 using var res = await _http.SendAsync(req, ct); 177 using var res = await _http.SendAsync(req, ct);
@@ -337,14 +336,14 @@ public async Task<DictBundle> GetWorkOrderDictsAsync(CancellationToken ct = defa @@ -337,14 +336,14 @@ public async Task<DictBundle> GetWorkOrderDictsAsync(CancellationToken ct = defa
337 public List<DictItem> AuditStatus { get; set; } = new(); 336 public List<DictItem> AuditStatus { get; set; } = new();
338 public List<DictItem> Urgent { get; set; } = new(); 337 public List<DictItem> Urgent { get; set; } = new();
339 } 338 }
340 -public sealed class WorkflowResp { public bool success { get; set; } public string? message { get; set; } public int code { get; set; } public List<WorkflowItem>? result { get; set; } }  
341 -public sealed class WorkflowItem { public string? statusValue { get; set; } public string? statusName { get; set; } public string? statusTime { get; set; } } 339 + public sealed class WorkflowResp { public bool success { get; set; } public string? message { get; set; } public int code { get; set; } public List<WorkflowItem>? result { get; set; } }
  340 + public sealed class WorkflowItem { public string? statusValue { get; set; } public string? statusName { get; set; } public string? statusTime { get; set; } }
342 341
343 -public sealed class PageResp<T> { public bool success { get; set; } public string? message { get; set; } public int code { get; set; } public PageResult<T>? result { get; set; } }  
344 -public sealed class PageResult<T> { public int pageNo { get; set; } public int pageSize { get; set; } public int total { get; set; } public List<T>? records { get; set; } } 342 + public sealed class PageResp<T> { public bool success { get; set; } public string? message { get; set; } public int code { get; set; } public PageResult<T>? result { get; set; } }
  343 + public sealed class PageResult<T> { public int pageNo { get; set; } public int pageSize { get; set; } public int total { get; set; } public List<T>? records { get; set; } }
345 344
346 -public sealed class ProcessTask  
347 -{ 345 + public sealed class ProcessTask
  346 + {
348 public string? id { get; set; } 347 public string? id { get; set; }
349 public string? processCode { get; set; } 348 public string? processCode { get; set; }
350 public string? processName { get; set; } 349 public string? processName { get; set; }
@@ -354,5 +353,5 @@ public sealed class ProcessTask @@ -354,5 +353,5 @@ public sealed class ProcessTask
354 public string? endDate { get; set; } 353 public string? endDate { get; set; }
355 public int? sortNumber { get; set; } 354 public int? sortNumber { get; set; }
356 public string? auditStatus { get; set; } 355 public string? auditStatus { get; set; }
357 -} 356 + }
358 } 357 }
1 using IndustrialControl.Models; 1 using IndustrialControl.Models;
2 using IndustrialControl.ViewModels; 2 using IndustrialControl.ViewModels;
3 -using System.Net.Http;  
4 using System.Text; 3 using System.Text;
5 using System.Text.Json; 4 using System.Text.Json;
6 using System.Text.Json.Nodes; 5 using System.Text.Json.Nodes;
7 -using System.Text.Json.Serialization;  
8 6
9 namespace IndustrialControl.Services; 7 namespace IndustrialControl.Services;
10 8
@@ -153,8 +151,8 @@ public sealed class InboundMaterialService : IInboundMaterialService @@ -153,8 +151,8 @@ public sealed class InboundMaterialService : IInboundMaterialService
153 orderType: x.orderType ?? "", 151 orderType: x.orderType ?? "",
154 orderTypeName: x.orderTypeName ?? "", 152 orderTypeName: x.orderTypeName ?? "",
155 purchaseNo: x.purchaseNo ?? "", 153 purchaseNo: x.purchaseNo ?? "",
156 - arrivalNo: x.arrivalNo ?? "",  
157 supplierName: x.supplierName ?? "", 154 supplierName: x.supplierName ?? "",
  155 + arrivalNo: x.arrivalNo ?? "",
158 workOrderNo: x.workOrderNo ?? "", 156 workOrderNo: x.workOrderNo ?? "",
159 materialName: x.materialName ?? "", 157 materialName: x.materialName ?? "",
160 instockQty: ToInt(x.instockQty), 158 instockQty: ToInt(x.instockQty),
@@ -220,8 +218,8 @@ public sealed class InboundMaterialService : IInboundMaterialService @@ -220,8 +218,8 @@ public sealed class InboundMaterialService : IInboundMaterialService
220 MaterialName: (x.materialName ?? string.Empty).Trim(), 218 MaterialName: (x.materialName ?? string.Empty).Trim(),
221 Qty: ToInt(x.qty), 219 Qty: ToInt(x.qty),
222 Spec: (x.spec ?? string.Empty).Trim(), 220 Spec: (x.spec ?? string.Empty).Trim(),
223 - ScanStatus :x.scanStatus ?? false,  
224 - WarehouseCode :x.warehouseCode?.Trim() 221 + ScanStatus: x.scanStatus ?? false,
  222 + WarehouseCode: x.warehouseCode?.Trim()
225 )).ToList(); 223 )).ToList();
226 224
227 return list; 225 return list;
@@ -452,25 +450,25 @@ public sealed class InboundMaterialService : IInboundMaterialService @@ -452,25 +450,25 @@ public sealed class InboundMaterialService : IInboundMaterialService
452 450
453 // ====== DTO(按接口示例字段) ====== 451 // ====== DTO(按接口示例字段) ======
454 public class GetInStockReq 452 public class GetInStockReq
455 - { 453 +{
456 public string? createdTime { get; set; } 454 public string? createdTime { get; set; }
457 public string? endTime { get; set; } 455 public string? endTime { get; set; }
458 public string? instockNo { get; set; } 456 public string? instockNo { get; set; }
459 public string? orderType { get; set; } 457 public string? orderType { get; set; }
460 public string? startTime { get; set; } 458 public string? startTime { get; set; }
461 - } 459 +}
462 460
463 - public class GetInStockResp  
464 - { 461 +public class GetInStockResp
  462 +{
465 public int code { get; set; } 463 public int code { get; set; }
466 public long costTime { get; set; } 464 public long costTime { get; set; }
467 public string? message { get; set; } 465 public string? message { get; set; }
468 public bool success { get; set; } 466 public bool success { get; set; }
469 public List<GetInStockItem>? result { get; set; } 467 public List<GetInStockItem>? result { get; set; }
470 - } 468 +}
471 469
472 - public class GetInStockItem  
473 - { 470 +public class GetInStockItem
  471 +{
474 public string? arrivalNo { get; set; } 472 public string? arrivalNo { get; set; }
475 public string? createdTime { get; set; } 473 public string? createdTime { get; set; }
476 public string? instockId { get; set; } 474 public string? instockId { get; set; }
@@ -478,7 +476,7 @@ public class GetInStockReq @@ -478,7 +476,7 @@ public class GetInStockReq
478 public string? orderType { get; set; } 476 public string? orderType { get; set; }
479 public string? purchaseNo { get; set; } 477 public string? purchaseNo { get; set; }
480 public string? supplierName { get; set; } 478 public string? supplierName { get; set; }
481 - } 479 +}
482 public sealed class GetInStockDetailResp 480 public sealed class GetInStockDetailResp
483 { 481 {
484 public bool success { get; set; } 482 public bool success { get; set; }
@@ -504,55 +502,55 @@ public sealed class GetInStockDetailItem @@ -504,55 +502,55 @@ public sealed class GetInStockDetailItem
504 502
505 503
506 public class ScanRow 504 public class ScanRow
507 - { 505 +{
508 public string? barcode { get; set; } 506 public string? barcode { get; set; }
509 public string? instockId { get; set; } 507 public string? instockId { get; set; }
510 public string? location { get; set; } 508 public string? location { get; set; }
511 public string? materialName { get; set; } 509 public string? materialName { get; set; }
512 public string? qty { get; set; } 510 public string? qty { get; set; }
513 public string? spec { get; set; } 511 public string? spec { get; set; }
514 - } 512 +}
515 513
516 - public class ScanByBarcodeResp  
517 - { 514 +public class ScanByBarcodeResp
  515 +{
518 public int code { get; set; } 516 public int code { get; set; }
519 public long costTime { get; set; } 517 public long costTime { get; set; }
520 public string? message { get; set; } 518 public string? message { get; set; }
521 public object? result { get; set; } // 文档里 result 只是 bool/无结构,这里占位 519 public object? result { get; set; } // 文档里 result 只是 bool/无结构,这里占位
522 public bool success { get; set; } 520 public bool success { get; set; }
523 - }  
524 - public class ScanConfirmResp  
525 - { 521 +}
  522 +public class ScanConfirmResp
  523 +{
526 public int code { get; set; } 524 public int code { get; set; }
527 public long costTime { get; set; } 525 public long costTime { get; set; }
528 public string? message { get; set; } 526 public string? message { get; set; }
529 public object? result { get; set; } 527 public object? result { get; set; }
530 public bool success { get; set; } 528 public bool success { get; set; }
531 - }  
532 - public class CancelScanResp  
533 - { 529 +}
  530 +public class CancelScanResp
  531 +{
534 public int code { get; set; } 532 public int code { get; set; }
535 public long costTime { get; set; } 533 public long costTime { get; set; }
536 public string? message { get; set; } 534 public string? message { get; set; }
537 public object? result { get; set; } 535 public object? result { get; set; }
538 public bool success { get; set; } 536 public bool success { get; set; }
539 - }  
540 - public class ConfirmResp  
541 - { 537 +}
  538 +public class ConfirmResp
  539 +{
542 public int code { get; set; } 540 public int code { get; set; }
543 public long costTime { get; set; } 541 public long costTime { get; set; }
544 public string? message { get; set; } 542 public string? message { get; set; }
545 public bool? result { get; set; } 543 public bool? result { get; set; }
546 public bool? success { get; set; } 544 public bool? success { get; set; }
547 - }  
548 - public class JudgeScanAllResp  
549 - { 545 +}
  546 +public class JudgeScanAllResp
  547 +{
550 public int code { get; set; } 548 public int code { get; set; }
551 public long costTime { get; set; } 549 public long costTime { get; set; }
552 public string? message { get; set; } 550 public string? message { get; set; }
553 public bool success { get; set; } 551 public bool success { get; set; }
554 public bool? result { get; set; } // 文档中为布尔 552 public bool? result { get; set; } // 文档中为布尔
555 - } 553 +}
556 public class GetInStockPageResp 554 public class GetInStockPageResp
557 { 555 {
558 public int code { get; set; } 556 public int code { get; set; }
1 using IndustrialControl.Models; 1 using IndustrialControl.Models;
2 using IndustrialControl.ViewModels; 2 using IndustrialControl.ViewModels;
3 -using System.Net.Http;  
4 using System.Text; 3 using System.Text;
5 using System.Text.Json; 4 using System.Text.Json;
6 using System.Text.Json.Nodes; 5 using System.Text.Json.Nodes;
7 -using System.Text.Json.Serialization;  
8 6
9 namespace IndustrialControl.Services; 7 namespace IndustrialControl.Services;
10 8
@@ -151,9 +149,14 @@ public sealed class OutboundMaterialService : IOutboundMaterialService @@ -151,9 +149,14 @@ public sealed class OutboundMaterialService : IOutboundMaterialService
151 orderType: x.orderType ?? "", 149 orderType: x.orderType ?? "",
152 orderTypeName: x.orderTypeName ?? "", 150 orderTypeName: x.orderTypeName ?? "",
153 workOrderNo: x.workOrderNo ?? "", 151 workOrderNo: x.workOrderNo ?? "",
  152 + returnNo: x.returnNo ?? "",
  153 + deliveryNo: x.deliveryNo ?? "",
154 requisitionMaterialNo: x.requisitionMaterialNo ?? "", 154 requisitionMaterialNo: x.requisitionMaterialNo ?? "",
155 - returnNo:x.returnNo ?? "",  
156 - deliveryNo:x.deliveryNo ?? "", 155 + customer: x.customer ?? "",
  156 + deliveryMemo: x.deliveryMemo ?? "",
  157 + expectedDeliveryTime: x.expectedDeliveryTime ?? "",
  158 + memo: x.memo ?? "",
  159 + saleNo: x.saleNo ?? "",
157 createdTime: x.createdTime ?? "" 160 createdTime: x.createdTime ?? ""
158 )); 161 ));
159 } 162 }
@@ -436,6 +439,11 @@ public sealed class OutboundMaterialService : IOutboundMaterialService @@ -436,6 +439,11 @@ public sealed class OutboundMaterialService : IOutboundMaterialService
436 public string? requisitionMaterialNo { get; set; } 439 public string? requisitionMaterialNo { get; set; }
437 public string? returnNo { get; set; } 440 public string? returnNo { get; set; }
438 public string? deliveryNo { get; set; } 441 public string? deliveryNo { get; set; }
  442 + public string? customer { get; set; }
  443 + public string? deliveryMemo { get; set; }
  444 + public string? expectedDeliveryTime { get; set; }
  445 + public string? memo { get; set; }
  446 + public string? saleNo { get; set; }
439 public string? createdTime { get; set; } 447 public string? createdTime { get; set; }
440 } 448 }
441 public sealed class GetOutStockScanDetailResp 449 public sealed class GetOutStockScanDetailResp
1 -using System; 1 +// File: Services/ScanService.cs
  2 +using System;
2 using Microsoft.Maui.Controls; 3 using Microsoft.Maui.Controls;
3 4
4 #if ANDROID 5 #if ANDROID
5 using Android.Content; 6 using Android.Content;
6 -using Android.Util; // ✅ 用于 Log  
7 -using IndustrialControl.Droid; // 需要 DynamicScanReceiver 7 +using Android.Util;
  8 +using IndustrialControl.Droid; // 引用 DynamicScanReceiver
8 #endif 9 #endif
9 10
10 namespace IndustrialControl.Services 11 namespace IndustrialControl.Services
11 { 12 {
  13 + /// <summary>
  14 + /// 统一的扫码服务:支持软键盘回车、手动发布、以及 Android 广播动态接收
  15 + /// </summary>
12 public class ScanService 16 public class ScanService
13 { 17 {
14 - public event Action<string, string>? Scanned; 18 + public event Action<string, string?>? Scanned;
15 19
  20 + /// <summary>可选:前缀过滤(匹配到则裁剪)</summary>
16 public string? Prefix { get; set; } 21 public string? Prefix { get; set; }
  22 +
  23 + /// <summary>可选:后缀过滤(匹配到则裁剪)</summary>
17 public string? Suffix { get; set; } 24 public string? Suffix { get; set; }
  25 +
  26 + /// <summary>去抖间隔(毫秒):相同码在该间隔内只触发一次</summary>
18 public int DebounceMs { get; set; } = 250; 27 public int DebounceMs { get; set; } = 250;
19 28
20 private string? _lastData; 29 private string? _lastData;
21 private DateTime _lastAt = DateTime.MinValue; 30 private DateTime _lastAt = DateTime.MinValue;
22 31
  32 + // 约定的广播/键名(与你的设备或发送方对齐)
23 public const string BroadcastAction = "lc"; 33 public const string BroadcastAction = "lc";
24 public const string DataKey = "data"; 34 public const string DataKey = "data";
25 public const string TypeKey = "SCAN_BARCODE_TYPE_NAME"; 35 public const string TypeKey = "SCAN_BARCODE_TYPE_NAME";
26 36
  37 + /// <summary>
  38 + /// 绑定一个 Entry:回车或换行时触发扫码
  39 + /// </summary>
27 public void Attach(Entry entry) 40 public void Attach(Entry entry)
28 { 41 {
  42 + // 回车(Completed)
29 entry.Completed += (s, e) => 43 entry.Completed += (s, e) =>
30 { 44 {
31 var data = entry.Text?.Trim(); 45 var data = entry.Text?.Trim();
@@ -34,11 +48,12 @@ namespace IndustrialControl.Services @@ -34,11 +48,12 @@ namespace IndustrialControl.Services
34 #if ANDROID 48 #if ANDROID
35 Log.Info("ScanService", $"[Attach] Entry.Completed -> {data}"); 49 Log.Info("ScanService", $"[Attach] Entry.Completed -> {data}");
36 #endif 50 #endif
37 - Scanned?.Invoke(data, "kbd"); 51 + FilterAndRaise(data, "kbd");
38 entry.Text = string.Empty; 52 entry.Text = string.Empty;
39 } 53 }
40 }; 54 };
41 55
  56 + // 文本变化:遇到 \n/\r 也触发
42 entry.TextChanged += (s, e) => 57 entry.TextChanged += (s, e) =>
43 { 58 {
44 if (string.IsNullOrEmpty(e.NewTextValue)) return; 59 if (string.IsNullOrEmpty(e.NewTextValue)) return;
@@ -49,24 +64,30 @@ namespace IndustrialControl.Services @@ -49,24 +64,30 @@ namespace IndustrialControl.Services
49 #if ANDROID 64 #if ANDROID
50 Log.Info("ScanService", $"[Attach] Entry.TextChanged -> {data}"); 65 Log.Info("ScanService", $"[Attach] Entry.TextChanged -> {data}");
51 #endif 66 #endif
52 - Scanned?.Invoke(data, "kbd"); 67 + FilterAndRaise(data, "kbd");
53 entry.Text = string.Empty; 68 entry.Text = string.Empty;
54 } 69 }
55 }; 70 };
56 } 71 }
57 72
58 - public void Publish(string code, string type = "") 73 + /// <summary>
  74 + /// 代码侧模拟一次扫码(用于调试/联调)
  75 + /// </summary>
  76 + public void Publish(string code, string? type = null)
59 { 77 {
60 #if ANDROID 78 #if ANDROID
61 Log.Info("ScanService", $"[Publish] 模拟扫码 -> {code}, type={type}"); 79 Log.Info("ScanService", $"[Publish] 模拟扫码 -> {code}, type={type}");
62 #endif 80 #endif
63 - FilterAndRaise(code, type); 81 + FilterAndRaise(code, type ?? string.Empty);
64 } 82 }
65 83
  84 + /// <summary>
  85 + /// 开始监听 Android 广播(动态注册)
  86 + /// </summary>
66 public void StartListening() 87 public void StartListening()
67 { 88 {
68 #if ANDROID 89 #if ANDROID
69 - Android.Util.Log.Info("ScanService", "[StartListening] ENTER"); 90 + Log.Info("ScanService", "[StartListening] ENTER");
70 if (_receiver != null) return; 91 if (_receiver != null) return;
71 92
72 _receiver = new DynamicScanReceiver(); 93 _receiver = new DynamicScanReceiver();
@@ -79,6 +100,9 @@ namespace IndustrialControl.Services @@ -79,6 +100,9 @@ namespace IndustrialControl.Services
79 #endif 100 #endif
80 } 101 }
81 102
  103 + /// <summary>
  104 + /// 停止监听 Android 广播(反注册)
  105 + /// </summary>
82 public void StopListening() 106 public void StopListening()
83 { 107 {
84 #if ANDROID 108 #if ANDROID
@@ -100,19 +124,22 @@ namespace IndustrialControl.Services @@ -100,19 +124,22 @@ namespace IndustrialControl.Services
100 #endif 124 #endif
101 } 125 }
102 126
103 - private bool FilterAndRaise(string data, string type) 127 + /// <summary>
  128 + /// 统一过滤 + 去抖 + 触发事件
  129 + /// </summary>
  130 + private bool FilterAndRaise(string data, string? type)
104 { 131 {
105 - if (!string.IsNullOrEmpty(Prefix) && data.StartsWith(Prefix)) 132 + if (!string.IsNullOrEmpty(Prefix) && data.StartsWith(Prefix, StringComparison.Ordinal))
106 data = data.Substring(Prefix.Length); 133 data = data.Substring(Prefix.Length);
107 134
108 - if (!string.IsNullOrEmpty(Suffix) && data.EndsWith(Suffix)) 135 + if (!string.IsNullOrEmpty(Suffix) && data.EndsWith(Suffix, StringComparison.Ordinal))
109 data = data.Substring(0, data.Length - Suffix.Length); 136 data = data.Substring(0, data.Length - Suffix.Length);
110 137
111 var now = DateTime.UtcNow; 138 var now = DateTime.UtcNow;
112 if (_lastData == data && (now - _lastAt).TotalMilliseconds < DebounceMs) 139 if (_lastData == data && (now - _lastAt).TotalMilliseconds < DebounceMs)
113 { 140 {
114 #if ANDROID 141 #if ANDROID
115 - Log.Info("ScanService", $"[FilterAndRaise] 数据去抖: {data}"); 142 + Log.Info("ScanService", $"[FilterAndRaise] 去抖丢弃: {data}");
116 #endif 143 #endif
117 return false; 144 return false;
118 } 145 }
@@ -121,7 +148,7 @@ namespace IndustrialControl.Services @@ -121,7 +148,7 @@ namespace IndustrialControl.Services
121 _lastAt = now; 148 _lastAt = now;
122 149
123 #if ANDROID 150 #if ANDROID
124 - Log.Info("ScanService", $"[FilterAndRaise] 最终触发 -> {data}, type={type}"); 151 + Log.Info("ScanService", $"[FilterAndRaise] 触发 -> {data}, type={type}");
125 #endif 152 #endif
126 Scanned?.Invoke(data, type); 153 Scanned?.Invoke(data, type);
127 return true; 154 return true;
@@ -131,9 +158,9 @@ namespace IndustrialControl.Services @@ -131,9 +158,9 @@ namespace IndustrialControl.Services
131 private DynamicScanReceiver? _receiver; 158 private DynamicScanReceiver? _receiver;
132 private IntentFilter? _filter; 159 private IntentFilter? _filter;
133 160
134 - private void OnScannedFromPlatform(string data, string type) 161 + private void OnScannedFromPlatform(string data, string? type)
135 { 162 {
136 - Log.Info("ScanService", $"[OnScannedFromPlatform] 原始数据 -> {data}, type={type}"); 163 + Log.Info("ScanService", $"[OnScannedFromPlatform] 原始 -> {data}, type={type}");
137 FilterAndRaise(data, type); 164 FilterAndRaise(data, type);
138 } 165 }
139 #endif 166 #endif
1 // Utils/TokenStorage.cs 1 // Utils/TokenStorage.cs
2 -using Microsoft.Maui.Storage;  
3 -  
4 namespace IndustrialControl; 2 namespace IndustrialControl;
5 3
6 public static class TokenStorage 4 public static class TokenStorage
1 using CommunityToolkit.Mvvm.ComponentModel; 1 using CommunityToolkit.Mvvm.ComponentModel;
2 using CommunityToolkit.Mvvm.Input; 2 using CommunityToolkit.Mvvm.Input;
3 -using System.Collections.ObjectModel;  
4 -using IndustrialControl.Services;  
5 using IndustrialControl.Pages; // 用于弹出 BinPickerPage / BinListPage 3 using IndustrialControl.Pages; // 用于弹出 BinPickerPage / BinListPage
6 - 4 +using IndustrialControl.Services;
  5 +using System.Collections.ObjectModel;
  6 +using ConfirmDetail = IndustrialControl.Services.InStockDetail;
7 // 使用服务层 DTO,避免 VM 内重复定义 7 // 使用服务层 DTO,避免 VM 内重复定义
8 using ConfirmReq = IndustrialControl.Services.InStockConfirmReq; 8 using ConfirmReq = IndustrialControl.Services.InStockConfirmReq;
9 -using ConfirmDetail = IndustrialControl.Services.InStockDetail;  
10 9
11 namespace IndustrialControl.ViewModels 10 namespace IndustrialControl.ViewModels
12 { 11 {
@@ -130,7 +130,7 @@ namespace IndustrialControl.ViewModels @@ -130,7 +130,7 @@ namespace IndustrialControl.ViewModels
130 LineName = r.lineName ?? "", 130 LineName = r.lineName ?? "",
131 Status = statusName, 131 Status = statusName,
132 Urgent = urgentName, 132 Urgent = urgentName,
133 - CurQty =(int?)r.curQty, 133 + CurQty = (int?)r.curQty,
134 CreateDate = createdAt?.ToString("yyyy-MM-dd") ?? (r.createdTime ?? ""), 134 CreateDate = createdAt?.ToString("yyyy-MM-dd") ?? (r.createdTime ?? ""),
135 BomCode = r.bomCode, // e.g. "BOM00000006" 135 BomCode = r.bomCode, // e.g. "BOM00000006"
136 RouteName = r.routeName, // e.g. "午餐肉罐头测试工序调整" 136 RouteName = r.routeName, // e.g. "午餐肉罐头测试工序调整"
1 using CommunityToolkit.Mvvm.ComponentModel; 1 using CommunityToolkit.Mvvm.ComponentModel;
2 using CommunityToolkit.Mvvm.Input; 2 using CommunityToolkit.Mvvm.Input;
3 -using System.Collections.ObjectModel;  
4 using IndustrialControl.Services; 3 using IndustrialControl.Services;
  4 +using System.Collections.ObjectModel;
5 5
6 namespace IndustrialControl.ViewModels 6 namespace IndustrialControl.ViewModels
7 { 7 {
@@ -129,7 +129,7 @@ namespace IndustrialControl.ViewModels @@ -129,7 +129,7 @@ namespace IndustrialControl.ViewModels
129 LineName = r.lineName ?? "", 129 LineName = r.lineName ?? "",
130 Status = statusName, 130 Status = statusName,
131 Urgent = urgentName, 131 Urgent = urgentName,
132 - CurQty =(int?)r.curQty, 132 + CurQty = (int?)r.curQty,
133 CreateDate = createdAt?.ToString("yyyy-MM-dd") ?? (r.createdTime ?? ""), 133 CreateDate = createdAt?.ToString("yyyy-MM-dd") ?? (r.createdTime ?? ""),
134 BomCode = r.bomCode, // e.g. "BOM00000006" 134 BomCode = r.bomCode, // e.g. "BOM00000006"
135 RouteName = r.routeName, // e.g. "午餐肉罐头测试工序调整" 135 RouteName = r.routeName, // e.g. "午餐肉罐头测试工序调整"
1 using CommunityToolkit.Mvvm.ComponentModel; 1 using CommunityToolkit.Mvvm.ComponentModel;
2 using CommunityToolkit.Mvvm.Input; 2 using CommunityToolkit.Mvvm.Input;
3 -using System.Collections.ObjectModel;  
4 -using IndustrialControl.Services;  
5 using IndustrialControl.Models; 3 using IndustrialControl.Models;
  4 +using IndustrialControl.Services;
  5 +using System.Collections.ObjectModel;
6 6
7 namespace IndustrialControl.ViewModels 7 namespace IndustrialControl.ViewModels
8 { 8 {
1 using CommunityToolkit.Mvvm.ComponentModel; 1 using CommunityToolkit.Mvvm.ComponentModel;
2 using CommunityToolkit.Mvvm.Input; 2 using CommunityToolkit.Mvvm.Input;
3 -using System.Collections.ObjectModel;  
4 -using IndustrialControl.Services;  
5 using IndustrialControl.Models; 3 using IndustrialControl.Models;
  4 +using IndustrialControl.Services;
  5 +using System.Collections.ObjectModel;
6 6
7 namespace IndustrialControl.ViewModels 7 namespace IndustrialControl.ViewModels
8 { 8 {
@@ -44,7 +44,7 @@ namespace IndustrialControl.ViewModels @@ -44,7 +44,7 @@ namespace IndustrialControl.ViewModels
44 // ================ 初始化入口(页面 OnAppearing 调用) ================ 44 // ================ 初始化入口(页面 OnAppearing 调用) ================
45 public async Task InitializeFromSearchAsync( 45 public async Task InitializeFromSearchAsync(
46 string instockId, string instockNo, string orderType, string orderTypeName, 46 string instockId, string instockNo, string orderType, string orderTypeName,
47 - string purchaseNo, string supplierName, string createdTime,string workOrderNo,string materialName,int instockQty) 47 + string purchaseNo, string supplierName, string createdTime, string workOrderNo, string materialName, int instockQty)
48 { 48 {
49 // 1) 基础信息 49 // 1) 基础信息
50 InstockId = instockId; 50 InstockId = instockId;
1 using CommunityToolkit.Mvvm.ComponentModel; 1 using CommunityToolkit.Mvvm.ComponentModel;
2 using CommunityToolkit.Mvvm.Input; 2 using CommunityToolkit.Mvvm.Input;
3 -using System.Collections.ObjectModel;  
4 -using IndustrialControl.Services;  
5 using IndustrialControl.Models; 3 using IndustrialControl.Models;
  4 +using IndustrialControl.Services;
  5 +using System.Collections.ObjectModel;
6 6
7 namespace IndustrialControl.ViewModels 7 namespace IndustrialControl.ViewModels
8 { 8 {
@@ -14,12 +14,11 @@ namespace IndustrialControl.ViewModels @@ -14,12 +14,11 @@ namespace IndustrialControl.ViewModels
14 // === 基础信息(由搜索页带入) === 14 // === 基础信息(由搜索页带入) ===
15 [ObservableProperty] private string? outstockId; 15 [ObservableProperty] private string? outstockId;
16 [ObservableProperty] private string? outstockNo; 16 [ObservableProperty] private string? outstockNo;
17 - [ObservableProperty] private string? orderType;  
18 - [ObservableProperty] private string? orderTypeName;  
19 - [ObservableProperty] private string? requisitionMaterialNo;  
20 - [ObservableProperty] private string? returnNo;  
21 [ObservableProperty] private string? deliveryNo; 17 [ObservableProperty] private string? deliveryNo;
22 - [ObservableProperty] private string? createdTime; 18 + [ObservableProperty] private string? customer;
  19 + [ObservableProperty] private string? expectedDeliveryTime;
  20 + [ObservableProperty] private string? saleNo;
  21 + [ObservableProperty] private string? deliveryMemo;
23 22
24 // 列表数据源 23 // 列表数据源
25 public ObservableCollection<string> AvailableBins { get; } = new(); 24 public ObservableCollection<string> AvailableBins { get; } = new();
@@ -51,18 +50,17 @@ namespace IndustrialControl.ViewModels @@ -51,18 +50,17 @@ namespace IndustrialControl.ViewModels
51 50
52 // ================ 初始化入口(页面 OnAppearing 调用) ================ 51 // ================ 初始化入口(页面 OnAppearing 调用) ================
53 public async Task InitializeFromSearchAsync( 52 public async Task InitializeFromSearchAsync(
54 - string outstockId, string outstockNo, string orderType, string orderTypeName,  
55 - string requisitionMaterialNo, string returnNo, string deliveryNo, string createdTime) 53 + string outstockId, string outstockNo, string deliveryNo, string customer,
  54 + string expectedDeliveryTime, string saleNo, string deliveryMemo)
56 { 55 {
57 // 1) 基础信息 56 // 1) 基础信息
58 OutstockId = outstockId; 57 OutstockId = outstockId;
59 OutstockNo = outstockNo; 58 OutstockNo = outstockNo;
60 - OrderType = orderType;  
61 - OrderTypeName = orderTypeName;  
62 - RequisitionMaterialNo = requisitionMaterialNo;  
63 - ReturnNo = returnNo;  
64 DeliveryNo = deliveryNo; 59 DeliveryNo = deliveryNo;
65 - CreatedTime = createdTime; 60 + Customer = customer;
  61 + ExpectedDeliveryTime = expectedDeliveryTime;
  62 + SaleNo = saleNo;
  63 + DeliveryMemo = deliveryMemo;
66 64
67 // 2) 下拉库位(如无接口可留空或使用后端返回的 location 聚合) 65 // 2) 下拉库位(如无接口可留空或使用后端返回的 location 聚合)
68 AvailableBins.Clear(); 66 AvailableBins.Clear();
@@ -77,12 +77,9 @@ public partial class OutboundMaterialSearchViewModel : ObservableObject @@ -77,12 +77,9 @@ public partial class OutboundMaterialSearchViewModel : ObservableObject
77 { 77 {
78 ["outstockId"] = o.outstockId, 78 ["outstockId"] = o.outstockId,
79 ["outstockNo"] = o.outstockNo, 79 ["outstockNo"] = o.outstockNo,
80 - ["orderType"] = o.orderType,  
81 - ["orderTypeName"] = o.orderTypeName,  
82 ["requisitionMaterialNo"] = o.requisitionMaterialNo, 80 ["requisitionMaterialNo"] = o.requisitionMaterialNo,
83 - ["returnNo"] = o.returnNo,  
84 - ["deliveryNo"] = o.deliveryNo,  
85 - ["createdTime"] = o.createdTime 81 + ["workOrderNo"] = o.workOrderNo,
  82 + ["memo"] = o.memo
86 }); 83 });
87 84
88 } 85 }
@@ -101,5 +98,10 @@ public record OutboundOrderSummary( @@ -101,5 +98,10 @@ public record OutboundOrderSummary(
101 string returnNo, 98 string returnNo,
102 string deliveryNo, 99 string deliveryNo,
103 string requisitionMaterialNo, 100 string requisitionMaterialNo,
  101 + string customer,
  102 + string deliveryMemo,
  103 + string expectedDeliveryTime,
  104 + string memo,
  105 + string saleNo,
104 string createdTime 106 string createdTime
105 ); 107 );
1 using CommunityToolkit.Mvvm.ComponentModel; 1 using CommunityToolkit.Mvvm.ComponentModel;
2 using CommunityToolkit.Mvvm.Input; 2 using CommunityToolkit.Mvvm.Input;
3 -using System.Collections.ObjectModel;  
4 -using IndustrialControl.Services;  
5 using IndustrialControl.Models; 3 using IndustrialControl.Models;
  4 +using IndustrialControl.Services;
  5 +using System.Collections.ObjectModel;
6 6
7 namespace IndustrialControl.ViewModels 7 namespace IndustrialControl.ViewModels
8 { 8 {
@@ -14,12 +14,9 @@ namespace IndustrialControl.ViewModels @@ -14,12 +14,9 @@ namespace IndustrialControl.ViewModels
14 // === 基础信息(由搜索页带入) === 14 // === 基础信息(由搜索页带入) ===
15 [ObservableProperty] private string? outstockId; 15 [ObservableProperty] private string? outstockId;
16 [ObservableProperty] private string? outstockNo; 16 [ObservableProperty] private string? outstockNo;
17 - [ObservableProperty] private string? orderType;  
18 - [ObservableProperty] private string? orderTypeName;  
19 [ObservableProperty] private string? requisitionMaterialNo; 17 [ObservableProperty] private string? requisitionMaterialNo;
20 - [ObservableProperty] private string? returnNo;  
21 - [ObservableProperty] private string? deliveryNo;  
22 - [ObservableProperty] private string? createdTime; 18 + [ObservableProperty] private string? workOrderNo;
  19 + [ObservableProperty] private string? memo;
23 20
24 // 列表数据源 21 // 列表数据源
25 public ObservableCollection<string> AvailableBins { get; } = new(); 22 public ObservableCollection<string> AvailableBins { get; } = new();
@@ -51,18 +48,17 @@ namespace IndustrialControl.ViewModels @@ -51,18 +48,17 @@ namespace IndustrialControl.ViewModels
51 48
52 // ================ 初始化入口(页面 OnAppearing 调用) ================ 49 // ================ 初始化入口(页面 OnAppearing 调用) ================
53 public async Task InitializeFromSearchAsync( 50 public async Task InitializeFromSearchAsync(
54 - string outstockId, string outstockNo, string orderType, string orderTypeName,  
55 - string requisitionMaterialNo, string returnNo,string deliveryNo, string createdTime) 51 + string outstockId, string outstockNo,
  52 + string requisitionMaterialNo, string workOrderNo, string memo)
56 { 53 {
  54 +
57 // 1) 基础信息 55 // 1) 基础信息
58 OutstockId = outstockId; 56 OutstockId = outstockId;
59 OutstockNo = outstockNo; 57 OutstockNo = outstockNo;
60 - OrderType = orderType;  
61 - OrderTypeName = orderTypeName;  
62 RequisitionMaterialNo = requisitionMaterialNo; 58 RequisitionMaterialNo = requisitionMaterialNo;
63 - ReturnNo = returnNo;  
64 - DeliveryNo = deliveryNo;  
65 - CreatedTime = createdTime; 59 + WorkOrderNo = workOrderNo;
  60 + Memo = memo;
  61 +
66 62
67 // 2) 下拉库位(如无接口可留空或使用后端返回的 location 聚合) 63 // 2) 下拉库位(如无接口可留空或使用后端返回的 location 聚合)
68 AvailableBins.Clear(); 64 AvailableBins.Clear();
  1 +{ "sdk": { "version": "8.0.414" } }