作者 李壮

outbound

正在显示 45 个修改的文件 包含 448 行增加429 行删除
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 {
@@ -27,7 +26,7 @@ namespace IndustrialControl @@ -27,7 +26,7 @@ namespace IndustrialControl
27 builder.Services.AddSingleton<IConfigLoader, ConfigLoader>(); 26 builder.Services.AddSingleton<IConfigLoader, ConfigLoader>();
28 builder.Services.AddSingleton<LogService>(); 27 builder.Services.AddSingleton<LogService>();
29 builder.Services.AddSingleton<IDialogService, DialogService>(); 28 builder.Services.AddSingleton<IDialogService, DialogService>();
30 - 29 +
31 30
32 // 扫码服务 31 // 扫码服务
33 builder.Services.AddSingleton<ScanService>(); 32 builder.Services.AddSingleton<ScanService>();
@@ -7,7 +7,7 @@ public class ServerSettings @@ -7,7 +7,7 @@ public class ServerSettings
7 } 7 }
8 public class ApiEndpoints 8 public class ApiEndpoints
9 { 9 {
10 - public string Login { get; set; } 10 + public string Login { get; set; }
11 } 11 }
12 public class LoggingSettings 12 public class LoggingSettings
13 { 13 {
@@ -51,7 +51,7 @@ public record InboundScannedRow( @@ -51,7 +51,7 @@ public record InboundScannedRow(
51 string MaterialName, 51 string MaterialName,
52 int Qty, 52 int Qty,
53 string Spec, 53 string Spec,
54 - bool ScanStatus, 54 + bool ScanStatus,
55 string? WarehouseCode 55 string? WarehouseCode
56 ); 56 );
57 57
1 -namespace IndustrialControl.Pages;  
2 -public partial class AdminPage : ContentPage  
3 -{ public AdminPage(ViewModels.AdminViewModel vm) 1 +namespace IndustrialControl.Pages;
  2 +public partial class AdminPage : ContentPage
  3 +{
  4 + public AdminPage(ViewModels.AdminViewModel vm)
4 { InitializeComponent(); BindingContext = vm; } 5 { InitializeComponent(); BindingContext = vm; }
5 } 6 }
@@ -60,7 +60,7 @@ @@ -60,7 +60,7 @@
60 await Shell.Current.GoToAsync(nameof(WorkOrderSearchPage)); 60 await Shell.Current.GoToAsync(nameof(WorkOrderSearchPage));
61 ((CheckBox)sender).IsChecked = false; 61 ((CheckBox)sender).IsChecked = false;
62 } 62 }
63 - 63 +
64 // 新增:退出登录 64 // 新增:退出登录
65 private async void OnLogoutClicked(object? sender, EventArgs e) 65 private async void OnLogoutClicked(object? sender, EventArgs e)
66 { 66 {
1 -namespace IndustrialControl.Pages;  
2 -public partial class LoginPage : ContentPage  
3 -{ public LoginPage(ViewModels.LoginViewModel vm) 1 +namespace IndustrialControl.Pages;
  2 +public partial class LoginPage : ContentPage
  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 }
@@ -99,7 +99,7 @@ public partial class OutboundMoldPage : ContentPage @@ -99,7 +99,7 @@ public partial class OutboundMoldPage : ContentPage
99 /// <summary> 99 /// <summary>
100 /// 确认入库按钮点击 100 /// 确认入库按钮点击
101 /// </summary> 101 /// </summary>
102 - async void OnConfirmClicked(object sender, EventArgs e) 102 + async void OnConfirmClicked(object sender, EventArgs e)
103 { 103 {
104 var ok = await _vm.ConfirmOutboundAsync(); 104 var ok = await _vm.ConfirmOutboundAsync();
105 if (ok) 105 if (ok)
@@ -50,29 +50,29 @@ public partial class OutboundMoldSearchPage : ContentPage @@ -50,29 +50,29 @@ public partial class OutboundMoldSearchPage : ContentPage
50 50
51 // 点整张卡片跳转(推荐) 51 // 点整张卡片跳转(推荐)
52 52
53 -private async void OnOrderTapped(object sender, TappedEventArgs e)  
54 -{  
55 - try 53 + private async void OnOrderTapped(object sender, TappedEventArgs e)
56 { 54 {
57 - if (e.Parameter is not MoldDto item) return; 55 + try
  56 + {
  57 + if (e.Parameter is not MoldDto item) return;
58 58
59 - var json = JsonSerializer.Serialize(item); 59 + var json = JsonSerializer.Serialize(item);
60 60
61 - await Shell.Current.GoToAsync(  
62 - nameof(MoldOutboundExecutePage),  
63 - new Dictionary<string, object?>  
64 - {  
65 - // 执行页用 IQueryAttributable 接收:key 必须叫 "orderDto"  
66 - ["orderDto"] = json  
67 - });  
68 - }  
69 - catch (Exception ex)  
70 - {  
71 - await DisplayAlert("导航失败", ex.Message, "确定"); 61 + await Shell.Current.GoToAsync(
  62 + nameof(MoldOutboundExecutePage),
  63 + new Dictionary<string, object?>
  64 + {
  65 + // 执行页用 IQueryAttributable 接收:key 必须叫 "orderDto"
  66 + ["orderDto"] = json
  67 + });
  68 + }
  69 + catch (Exception ex)
  70 + {
  71 + await DisplayAlert("导航失败", ex.Message, "确定");
  72 + }
72 } 73 }
73 -}  
74 74
75 75
76 -private async void OnScanHintClicked(object sender, EventArgs e)  
77 - => await DisplayAlert("提示", "此按钮预留摄像头扫码;硬件扫描直接扣扳机。", "确定"); 76 + private async void OnScanHintClicked(object sender, EventArgs e)
  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,29 +50,29 @@ public partial class WorkOrderSearchPage : ContentPage @@ -50,29 +50,29 @@ public partial class WorkOrderSearchPage : ContentPage
50 50
51 // 点整张卡片跳转(推荐) 51 // 点整张卡片跳转(推荐)
52 52
53 -private async void OnOrderTapped(object sender, TappedEventArgs e)  
54 -{  
55 - try 53 + private async void OnOrderTapped(object sender, TappedEventArgs e)
56 { 54 {
57 - if (e.Parameter is not WorkOrderDto item) return; 55 + try
  56 + {
  57 + if (e.Parameter is not WorkOrderDto item) return;
58 58
59 - var json = JsonSerializer.Serialize(item); 59 + var json = JsonSerializer.Serialize(item);
60 60
61 - await Shell.Current.GoToAsync(  
62 - nameof(MoldOutboundExecutePage),  
63 - new Dictionary<string, object?>  
64 - {  
65 - // 执行页用 IQueryAttributable 接收:key 必须叫 "orderDto"  
66 - ["orderDto"] = json  
67 - });  
68 - }  
69 - catch (Exception ex)  
70 - {  
71 - await DisplayAlert("导航失败", ex.Message, "确定"); 61 + await Shell.Current.GoToAsync(
  62 + nameof(MoldOutboundExecutePage),
  63 + new Dictionary<string, object?>
  64 + {
  65 + // 执行页用 IQueryAttributable 接收:key 必须叫 "orderDto"
  66 + ["orderDto"] = json
  67 + });
  68 + }
  69 + catch (Exception ex)
  70 + {
  71 + await DisplayAlert("导航失败", ex.Message, "确定");
  72 + }
72 } 73 }
73 -}  
74 74
75 75
76 -private async void OnScanHintClicked(object sender, EventArgs e)  
77 - => await DisplayAlert("提示", "此按钮预留摄像头扫码;硬件扫描直接扣扳机。", "确定"); 76 + private async void OnScanHintClicked(object sender, EventArgs e)
  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;
@@ -9,7 +9,7 @@ public partial class InboundMaterialSearchPage : ContentPage @@ -9,7 +9,7 @@ public partial class InboundMaterialSearchPage : ContentPage
9 public InboundMaterialSearchPage(InboundMaterialSearchViewModel vm, ScanService scanSvc) 9 public InboundMaterialSearchPage(InboundMaterialSearchViewModel vm, ScanService scanSvc)
10 { 10 {
11 _vm = vm; 11 _vm = vm;
12 - 12 +
13 BindingContext = vm; 13 BindingContext = vm;
14 _scanSvc = scanSvc; 14 _scanSvc = scanSvc;
15 InitializeComponent(); 15 InitializeComponent();
@@ -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
@@ -14,7 +14,7 @@ public interface IInboundMaterialService @@ -14,7 +14,7 @@ public interface IInboundMaterialService
14 string orderType, 14 string orderType,
15 string[] orderTypeList, 15 string[] orderTypeList,
16 CancellationToken ct = default); 16 CancellationToken ct = default);
17 - 17 +
18 Task<IReadOnlyList<InboundPendingRow>> GetInStockDetailAsync(string instockId, CancellationToken ct = default); 18 Task<IReadOnlyList<InboundPendingRow>> GetInStockDetailAsync(string instockId, CancellationToken ct = default);
19 Task<IReadOnlyList<InboundScannedRow>> GetInStockScanDetailAsync(string instockId, CancellationToken ct = default); 19 Task<IReadOnlyList<InboundScannedRow>> GetInStockScanDetailAsync(string instockId, CancellationToken ct = default);
20 /// <summary>扫描条码入库</summary> 20 /// <summary>扫描条码入库</summary>
@@ -32,10 +32,10 @@ public interface IInboundMaterialService @@ -32,10 +32,10 @@ public interface IInboundMaterialService
32 // 新增:按你截图的真实接口返回结构(树形) 32 // 新增:按你截图的真实接口返回结构(树形)
33 Task<List<LocationNodeDto>> GetLocationTreeAsync(CancellationToken ct = default); 33 Task<List<LocationNodeDto>> GetLocationTreeAsync(CancellationToken ct = default);
34 34
35 - Task<List<BinInfo>> GetBinsByLayerAsync(  
36 - string warehouseCode, string layer,  
37 - int pageNo = 1, int pageSize = 50, int status = 1,  
38 - CancellationToken ct = default); 35 + Task<List<BinInfo>> GetBinsByLayerAsync(
  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;
@@ -16,13 +14,13 @@ namespace IndustrialControl.Services @@ -16,13 +14,13 @@ namespace IndustrialControl.Services
16 Task<DictBundle> GetMoldDictsAsync(CancellationToken ct = default); 14 Task<DictBundle> GetMoldDictsAsync(CancellationToken ct = default);
17 Task<WorkflowResp?> GetMoldWorkflowAsync(string id, CancellationToken ct = default); 15 Task<WorkflowResp?> GetMoldWorkflowAsync(string id, CancellationToken ct = default);
18 Task<PageResp<ProcessTask>?> PageWorkProcessTasksAsync(string workOrderNo, int pageNo = 1, int pageSize = 50, CancellationToken ct = default); 16 Task<PageResp<ProcessTask>?> PageWorkProcessTasksAsync(string workOrderNo, int pageNo = 1, int pageSize = 50, CancellationToken ct = default);
19 - // Task<IEnumerable<MoldOrderSummary>> ListInboundOrdersAsync(  
20 - //string? orderNoOrBarcode,  
21 - //DateTime startDate,  
22 - //DateTime endDate,  
23 - //string orderType,  
24 - //string[] orderTypeList,  
25 - //CancellationToken ct = default); 17 + // Task<IEnumerable<MoldOrderSummary>> ListInboundOrdersAsync(
  18 + //string? orderNoOrBarcode,
  19 + //DateTime startDate,
  20 + //DateTime endDate,
  21 + //string orderType,
  22 + //string[] orderTypeList,
  23 + //CancellationToken ct = default);
26 24
27 Task<IReadOnlyList<InboundScannedRow>> GetInStockScanDetailAsync(string instockId, CancellationToken ct = default); 25 Task<IReadOnlyList<InboundScannedRow>> GetInStockScanDetailAsync(string instockId, CancellationToken ct = default);
28 /// <summary>扫描条码入库</summary> 26 /// <summary>扫描条码入库</summary>
@@ -92,10 +90,10 @@ namespace IndustrialControl.Services @@ -92,10 +90,10 @@ namespace IndustrialControl.Services
92 } 90 }
93 private static string BuildQuery(IDictionary<string, string> p) 91 private static string BuildQuery(IDictionary<string, string> p)
94 => string.Join("&", p.Select(kv => $"{Uri.EscapeDataString(kv.Key)}={Uri.EscapeDataString(kv.Value)}")); 92 => string.Join("&", p.Select(kv => $"{Uri.EscapeDataString(kv.Key)}={Uri.EscapeDataString(kv.Value)}"));
95 - // using System.Text.Json;  
96 - // using System.Text; 93 + // using System.Text.Json;
  94 + // using System.Text;
97 95
98 - public async Task<WorkOrderPageResult> GetMoldsAsync(MoldQuery q, CancellationToken ct = default) 96 + public async Task<WorkOrderPageResult> GetMoldsAsync(MoldQuery q, CancellationToken ct = default)
99 { 97 {
100 // 1) 先把所有要传的参数放进字典(只加有值的) 98 // 1) 先把所有要传的参数放进字典(只加有值的)
101 var p = new Dictionary<string, string> 99 var p = new Dictionary<string, string>
@@ -141,76 +139,76 @@ namespace IndustrialControl.Services @@ -141,76 +139,76 @@ namespace IndustrialControl.Services
141 } 139 }
142 140
143 141
144 - /// <summary>  
145 - /// 工单流程:/getMoldWorkflow?id=...  
146 - /// 返回 result 为数组(statusValue/statusName/statusTime)  
147 - /// </summary>  
148 - public async Task<WorkflowResp?> GetMoldWorkflowAsync(string id, CancellationToken ct = default)  
149 - {  
150 - var p = new Dictionary<string, string> { ["id"] = id?.Trim() ?? "" };  
151 - var url = _workflowEndpoint + "?" + BuildQuery(p); 142 + /// <summary>
  143 + /// 工单流程:/getMoldWorkflow?id=...
  144 + /// 返回 result 为数组(statusValue/statusName/statusTime)
  145 + /// </summary>
  146 + public async Task<WorkflowResp?> GetMoldWorkflowAsync(string id, CancellationToken ct = default)
  147 + {
  148 + var p = new Dictionary<string, string> { ["id"] = id?.Trim() ?? "" };
  149 + var url = _workflowEndpoint + "?" + BuildQuery(p);
152 150
153 - using var req = new HttpRequestMessage(HttpMethod.Get, url);  
154 - System.Diagnostics.Debug.WriteLine("[MoldApi] GET " + url); 151 + using var req = new HttpRequestMessage(HttpMethod.Get, url);
  152 + System.Diagnostics.Debug.WriteLine("[MoldApi] GET " + url);
155 153
156 - using var httpResp = await _http.SendAsync(req, ct);  
157 - var json = await httpResp.Content.ReadAsStringAsync(ct);  
158 - System.Diagnostics.Debug.WriteLine("[MoldApi] Resp(getMoldWorkflow): " + json[..Math.Min(300, json.Length)] + "..."); 154 + using var httpResp = await _http.SendAsync(req, ct);
  155 + var json = await httpResp.Content.ReadAsStringAsync(ct);
  156 + System.Diagnostics.Debug.WriteLine("[MoldApi] Resp(getMoldWorkflow): " + json[..Math.Min(300, json.Length)] + "...");
159 157
160 - if (!httpResp.IsSuccessStatusCode)  
161 - return new WorkflowResp { success = false, message = $"HTTP {(int)httpResp.StatusCode}" }; 158 + if (!httpResp.IsSuccessStatusCode)
  159 + return new WorkflowResp { success = false, message = $"HTTP {(int)httpResp.StatusCode}" };
162 160
163 - var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };  
164 - var resp = JsonSerializer.Deserialize<WorkflowResp>(json, options) ?? new WorkflowResp();  
165 - return resp;  
166 - } 161 + var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
  162 + var resp = JsonSerializer.Deserialize<WorkflowResp>(json, options) ?? new WorkflowResp();
  163 + return resp;
  164 + }
167 165
168 - /// <summary>  
169 - /// 工序分页:/pageWorkProcessTasks?pageNo=&pageSize=&workOrderNo=  
170 - /// 返回分页结构,数据在 result.records[]  
171 - /// </summary>  
172 - public async Task<PageResp<ProcessTask>?> PageWorkProcessTasksAsync(  
173 - string workOrderNo, int pageNo = 1, int pageSize = 50, CancellationToken ct = default)  
174 - {  
175 - var p = new Dictionary<string, string> 166 + /// <summary>
  167 + /// 工序分页:/pageWorkProcessTasks?pageNo=&pageSize=&workOrderNo=
  168 + /// 返回分页结构,数据在 result.records[]
  169 + /// </summary>
  170 + public async Task<PageResp<ProcessTask>?> PageWorkProcessTasksAsync(
  171 + string workOrderNo, int pageNo = 1, int pageSize = 50, CancellationToken ct = default)
176 { 172 {
177 - ["pageNo"] = pageNo.ToString(),  
178 - ["pageSize"] = pageSize.ToString()  
179 - };  
180 - if (!string.IsNullOrWhiteSpace(workOrderNo)) p["workOrderNo"] = workOrderNo.Trim(); 173 + var p = new Dictionary<string, string>
  174 + {
  175 + ["pageNo"] = pageNo.ToString(),
  176 + ["pageSize"] = pageSize.ToString()
  177 + };
  178 + if (!string.IsNullOrWhiteSpace(workOrderNo)) p["workOrderNo"] = workOrderNo.Trim();
181 179
182 - var url = _processTasksEndpoint + "?" + BuildQuery(p); 180 + var url = _processTasksEndpoint + "?" + BuildQuery(p);
183 181
184 - using var req = new HttpRequestMessage(HttpMethod.Get, url);  
185 - System.Diagnostics.Debug.WriteLine("[MoldApi] GET " + url); 182 + using var req = new HttpRequestMessage(HttpMethod.Get, url);
  183 + System.Diagnostics.Debug.WriteLine("[MoldApi] GET " + url);
186 184
187 - using var httpResp = await _http.SendAsync(req, ct);  
188 - var json = await httpResp.Content.ReadAsStringAsync(ct);  
189 - System.Diagnostics.Debug.WriteLine("[MoldApi] Resp(pageWorkProcessTasks): " + json[..Math.Min(300, json.Length)] + "..."); 185 + using var httpResp = await _http.SendAsync(req, ct);
  186 + var json = await httpResp.Content.ReadAsStringAsync(ct);
  187 + System.Diagnostics.Debug.WriteLine("[MoldApi] Resp(pageWorkProcessTasks): " + json[..Math.Min(300, json.Length)] + "...");
190 188
191 - if (!httpResp.IsSuccessStatusCode)  
192 - return new PageResp<ProcessTask> { success = false, message = $"HTTP {(int)httpResp.StatusCode}" }; 189 + if (!httpResp.IsSuccessStatusCode)
  190 + return new PageResp<ProcessTask> { success = false, message = $"HTTP {(int)httpResp.StatusCode}" };
193 191
194 - var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };  
195 - var resp = JsonSerializer.Deserialize<PageResp<ProcessTask>>(json, options) ?? new PageResp<ProcessTask>(); 192 + var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
  193 + var resp = JsonSerializer.Deserialize<PageResp<ProcessTask>>(json, options) ?? new PageResp<ProcessTask>();
196 194
197 - // 兼容 result.records(你的实际返回就是 records,结构示例如你发的 JSON)  
198 - // 如果后端某些场景包在 result.list.records,也一并兼容  
199 - var nested = resp.result?.records ?? resp.result?.records;  
200 - if (nested is not null && resp.result is not null)  
201 - {  
202 - if (resp.result.records is null || resp.result.records.Count == 0)  
203 - resp.result.records = nested; 195 + // 兼容 result.records(你的实际返回就是 records,结构示例如你发的 JSON)
  196 + // 如果后端某些场景包在 result.list.records,也一并兼容
  197 + var nested = resp.result?.records ?? resp.result?.records;
  198 + if (nested is not null && resp.result is not null)
  199 + {
  200 + if (resp.result.records is null || resp.result.records.Count == 0)
  201 + resp.result.records = nested;
204 202
205 - if (resp.result.pageNo == 0 && resp.result is not null) resp.result.pageNo = resp.result.pageNo;  
206 - if (resp.result.pageSize == 0 && resp.result is not null) resp.result.pageSize = resp.result.pageSize;  
207 - if (resp.result.total == 0 && resp.result is not null) resp.result.total = resp.result.total;  
208 - } 203 + if (resp.result.pageNo == 0 && resp.result is not null) resp.result.pageNo = resp.result.pageNo;
  204 + if (resp.result.pageSize == 0 && resp.result is not null) resp.result.pageSize = resp.result.pageSize;
  205 + if (resp.result.total == 0 && resp.result is not null) resp.result.total = resp.result.total;
  206 + }
209 207
210 - return resp;  
211 - } 208 + return resp;
  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);
@@ -385,7 +383,7 @@ public async Task<DictBundle> GetMoldDictsAsync(CancellationToken ct = default) @@ -385,7 +383,7 @@ public async Task<DictBundle> GetMoldDictsAsync(CancellationToken ct = default)
385 public string? lineName { get; set; } 383 public string? lineName { get; set; }
386 public string? workShop { get; set; } 384 public string? workShop { get; set; }
387 public string? workShopName { get; set; } 385 public string? workShopName { get; set; }
388 - public string? urgent { get; set; } 386 + public string? urgent { get; set; }
389 387
390 // ★ 这些时间都是 "yyyy-MM-dd HH:mm:ss" 字符串 388 // ★ 这些时间都是 "yyyy-MM-dd HH:mm:ss" 字符串
391 public string? schemeStartDate { get; set; } 389 public string? schemeStartDate { get; set; }
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
@@ -52,12 +51,12 @@ namespace IndustrialControl.Services @@ -52,12 +51,12 @@ namespace IndustrialControl.Services
52 (string?)cfg?["apiEndpoints"]?["workOrder"]?["dictList"] 51 (string?)cfg?["apiEndpoints"]?["workOrder"]?["dictList"]
53 ?? "/normalService/pda/pmsWorkOrder/getWorkOrderDictList"; 52 ?? "/normalService/pda/pmsWorkOrder/getWorkOrderDictList";
54 } 53 }
55 - private static string BuildQuery(IDictionary<string, string> p)  
56 - => string.Join("&", p.Select(kv => $"{Uri.EscapeDataString(kv.Key)}={Uri.EscapeDataString(kv.Value)}"));  
57 - // using System.Text.Json;  
58 - // using System.Text; 54 + private static string BuildQuery(IDictionary<string, string> p)
  55 + => string.Join("&", p.Select(kv => $"{Uri.EscapeDataString(kv.Key)}={Uri.EscapeDataString(kv.Value)}"));
  56 + // using System.Text.Json;
  57 + // using System.Text;
59 58
60 - public async Task<WorkOrderPageResult> GetWorkOrdersAsync(WorkOrderQuery q, CancellationToken ct = default) 59 + public async Task<WorkOrderPageResult> GetWorkOrdersAsync(WorkOrderQuery q, CancellationToken ct = default)
61 { 60 {
62 // 1) 先把所有要传的参数放进字典(只加有值的) 61 // 1) 先把所有要传的参数放进字典(只加有值的)
63 var p = new Dictionary<string, string> 62 var p = new Dictionary<string, string>
@@ -103,76 +102,76 @@ namespace IndustrialControl.Services @@ -103,76 +102,76 @@ namespace IndustrialControl.Services
103 } 102 }
104 103
105 104
106 - /// <summary>  
107 - /// 工单流程:/getWorkOrderWorkflow?id=...  
108 - /// 返回 result 为数组(statusValue/statusName/statusTime)  
109 - /// </summary>  
110 - public async Task<WorkflowResp?> GetWorkOrderWorkflowAsync(string id, CancellationToken ct = default)  
111 - {  
112 - var p = new Dictionary<string, string> { ["id"] = id?.Trim() ?? "" };  
113 - var url = _workflowEndpoint + "?" + BuildQuery(p); 105 + /// <summary>
  106 + /// 工单流程:/getWorkOrderWorkflow?id=...
  107 + /// 返回 result 为数组(statusValue/statusName/statusTime)
  108 + /// </summary>
  109 + public async Task<WorkflowResp?> GetWorkOrderWorkflowAsync(string id, CancellationToken ct = default)
  110 + {
  111 + var p = new Dictionary<string, string> { ["id"] = id?.Trim() ?? "" };
  112 + var url = _workflowEndpoint + "?" + BuildQuery(p);
114 113
115 - using var req = new HttpRequestMessage(HttpMethod.Get, url);  
116 - System.Diagnostics.Debug.WriteLine("[WorkOrderApi] GET " + url); 114 + using var req = new HttpRequestMessage(HttpMethod.Get, url);
  115 + System.Diagnostics.Debug.WriteLine("[WorkOrderApi] GET " + url);
117 116
118 - using var httpResp = await _http.SendAsync(req, ct);  
119 - var json = await httpResp.Content.ReadAsStringAsync(ct);  
120 - System.Diagnostics.Debug.WriteLine("[WorkOrderApi] Resp(getWorkOrderWorkflow): " + json[..Math.Min(300, json.Length)] + "..."); 117 + using var httpResp = await _http.SendAsync(req, ct);
  118 + var json = await httpResp.Content.ReadAsStringAsync(ct);
  119 + System.Diagnostics.Debug.WriteLine("[WorkOrderApi] Resp(getWorkOrderWorkflow): " + json[..Math.Min(300, json.Length)] + "...");
121 120
122 - if (!httpResp.IsSuccessStatusCode)  
123 - return new WorkflowResp { success = false, message = $"HTTP {(int)httpResp.StatusCode}" }; 121 + if (!httpResp.IsSuccessStatusCode)
  122 + return new WorkflowResp { success = false, message = $"HTTP {(int)httpResp.StatusCode}" };
124 123
125 - var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };  
126 - var resp = JsonSerializer.Deserialize<WorkflowResp>(json, options) ?? new WorkflowResp();  
127 - return resp;  
128 - } 124 + var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
  125 + var resp = JsonSerializer.Deserialize<WorkflowResp>(json, options) ?? new WorkflowResp();
  126 + return resp;
  127 + }
129 128
130 - /// <summary>  
131 - /// 工序分页:/pageWorkProcessTasks?pageNo=&pageSize=&workOrderNo=  
132 - /// 返回分页结构,数据在 result.records[]  
133 - /// </summary>  
134 - public async Task<PageResp<ProcessTask>?> PageWorkProcessTasksAsync(  
135 - string workOrderNo, int pageNo = 1, int pageSize = 50, CancellationToken ct = default)  
136 - {  
137 - var p = new Dictionary<string, string> 129 + /// <summary>
  130 + /// 工序分页:/pageWorkProcessTasks?pageNo=&pageSize=&workOrderNo=
  131 + /// 返回分页结构,数据在 result.records[]
  132 + /// </summary>
  133 + public async Task<PageResp<ProcessTask>?> PageWorkProcessTasksAsync(
  134 + string workOrderNo, int pageNo = 1, int pageSize = 50, CancellationToken ct = default)
138 { 135 {
139 - ["pageNo"] = pageNo.ToString(),  
140 - ["pageSize"] = pageSize.ToString()  
141 - };  
142 - if (!string.IsNullOrWhiteSpace(workOrderNo)) p["workOrderNo"] = workOrderNo.Trim(); 136 + var p = new Dictionary<string, string>
  137 + {
  138 + ["pageNo"] = pageNo.ToString(),
  139 + ["pageSize"] = pageSize.ToString()
  140 + };
  141 + if (!string.IsNullOrWhiteSpace(workOrderNo)) p["workOrderNo"] = workOrderNo.Trim();
143 142
144 - var url = _processTasksEndpoint + "?" + BuildQuery(p); 143 + var url = _processTasksEndpoint + "?" + BuildQuery(p);
145 144
146 - using var req = new HttpRequestMessage(HttpMethod.Get, url);  
147 - System.Diagnostics.Debug.WriteLine("[WorkOrderApi] GET " + url); 145 + using var req = new HttpRequestMessage(HttpMethod.Get, url);
  146 + System.Diagnostics.Debug.WriteLine("[WorkOrderApi] GET " + url);
148 147
149 - using var httpResp = await _http.SendAsync(req, ct);  
150 - var json = await httpResp.Content.ReadAsStringAsync(ct);  
151 - System.Diagnostics.Debug.WriteLine("[WorkOrderApi] Resp(pageWorkProcessTasks): " + json[..Math.Min(300, json.Length)] + "..."); 148 + using var httpResp = await _http.SendAsync(req, ct);
  149 + var json = await httpResp.Content.ReadAsStringAsync(ct);
  150 + System.Diagnostics.Debug.WriteLine("[WorkOrderApi] Resp(pageWorkProcessTasks): " + json[..Math.Min(300, json.Length)] + "...");
  151 +
  152 + if (!httpResp.IsSuccessStatusCode)
  153 + return new PageResp<ProcessTask> { success = false, message = $"HTTP {(int)httpResp.StatusCode}" };
152 154
153 - if (!httpResp.IsSuccessStatusCode)  
154 - return new PageResp<ProcessTask> { success = false, message = $"HTTP {(int)httpResp.StatusCode}" }; 155 + var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
  156 + var resp = JsonSerializer.Deserialize<PageResp<ProcessTask>>(json, options) ?? new PageResp<ProcessTask>();
155 157
156 - var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };  
157 - var resp = JsonSerializer.Deserialize<PageResp<ProcessTask>>(json, options) ?? new PageResp<ProcessTask>(); 158 + // 兼容 result.records(你的实际返回就是 records,结构示例如你发的 JSON)
  159 + // 如果后端某些场景包在 result.list.records,也一并兼容
  160 + var nested = resp.result?.records ?? resp.result?.records;
  161 + if (nested is not null && resp.result is not null)
  162 + {
  163 + if (resp.result.records is null || resp.result.records.Count == 0)
  164 + resp.result.records = nested;
158 165
159 - // 兼容 result.records(你的实际返回就是 records,结构示例如你发的 JSON)  
160 - // 如果后端某些场景包在 result.list.records,也一并兼容  
161 - var nested = resp.result?.records ?? resp.result?.records;  
162 - if (nested is not null && resp.result is not null)  
163 - {  
164 - if (resp.result.records is null || resp.result.records.Count == 0)  
165 - resp.result.records = nested; 166 + if (resp.result.pageNo == 0 && resp.result is not null) resp.result.pageNo = resp.result.pageNo;
  167 + if (resp.result.pageSize == 0 && resp.result is not null) resp.result.pageSize = resp.result.pageSize;
  168 + if (resp.result.total == 0 && resp.result is not null) resp.result.total = resp.result.total;
  169 + }
166 170
167 - if (resp.result.pageNo == 0 && resp.result is not null) resp.result.pageNo = resp.result.pageNo;  
168 - if (resp.result.pageSize == 0 && resp.result is not null) resp.result.pageSize = resp.result.pageSize;  
169 - if (resp.result.total == 0 && resp.result is not null) resp.result.total = resp.result.total; 171 + return resp;
170 } 172 }
171 173
172 - return resp;  
173 - }  
174 -  
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);
@@ -257,7 +256,7 @@ public async Task<DictBundle> GetWorkOrderDictsAsync(CancellationToken ct = defa @@ -257,7 +256,7 @@ public async Task<DictBundle> GetWorkOrderDictsAsync(CancellationToken ct = defa
257 public string? lineName { get; set; } 256 public string? lineName { get; set; }
258 public string? workShop { get; set; } 257 public string? workShop { get; set; }
259 public string? workShopName { get; set; } 258 public string? workShopName { get; set; }
260 - public string? urgent { get; set; } 259 + public string? urgent { get; set; }
261 260
262 // ★ 这些时间都是 "yyyy-MM-dd HH:mm:ss" 字符串 261 // ★ 这些时间都是 "yyyy-MM-dd HH:mm:ss" 字符串
263 public string? schemeStartDate { get; set; } 262 public string? schemeStartDate { get; set; }
@@ -337,22 +336,22 @@ public async Task<DictBundle> GetWorkOrderDictsAsync(CancellationToken ct = defa @@ -337,22 +336,22 @@ 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 -{  
348 - public string? id { get; set; }  
349 - public string? processCode { get; set; }  
350 - public string? processName { get; set; }  
351 - public decimal? scheQty { get; set; }  
352 - public decimal? completedQty { get; set; }  
353 - public string? startDate { get; set; }  
354 - public string? endDate { get; set; }  
355 - public int? sortNumber { get; set; }  
356 - public string? auditStatus { get; set; }  
357 -} 345 + public sealed class ProcessTask
  346 + {
  347 + public string? id { get; set; }
  348 + public string? processCode { get; set; }
  349 + public string? processName { get; set; }
  350 + public decimal? scheQty { get; set; }
  351 + public decimal? completedQty { get; set; }
  352 + public string? startDate { get; set; }
  353 + public string? endDate { get; set; }
  354 + public int? sortNumber { get; set; }
  355 + public string? auditStatus { get; set; }
  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,11 +151,11 @@ public sealed class InboundMaterialService : IInboundMaterialService @@ -153,11 +151,11 @@ 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 ?? "",
158 - workOrderNo: x.workOrderNo ?? "",  
159 - materialName: x.materialName ?? "",  
160 - instockQty: ToInt(x.instockQty), 155 + arrivalNo: x.arrivalNo ?? "",
  156 + workOrderNo: x.workOrderNo ?? "",
  157 + materialName: x.materialName ?? "",
  158 + instockQty: ToInt(x.instockQty),
161 createdTime: x.createdTime ?? "" 159 createdTime: x.createdTime ?? ""
162 )); 160 ));
163 } 161 }
@@ -178,7 +176,7 @@ public sealed class InboundMaterialService : IInboundMaterialService @@ -178,7 +176,7 @@ public sealed class InboundMaterialService : IInboundMaterialService
178 176
179 if (dto?.success != true || dto.result is null || dto.result.Count == 0) 177 if (dto?.success != true || dto.result is null || dto.result.Count == 0)
180 return Array.Empty<InboundPendingRow>(); 178 return Array.Empty<InboundPendingRow>();
181 - 179 +
182 // ⚠️ 接口没有 barcode,这里先用空串;如需展示可以改成 x.materialCode 或 x.stockBatch 180 // ⚠️ 接口没有 barcode,这里先用空串;如需展示可以改成 x.materialCode 或 x.stockBatch
183 var list = dto.result.Select(x => new InboundPendingRow( 181 var list = dto.result.Select(x => new InboundPendingRow(
184 Barcode: string.Empty, // 或 $"{x.materialCode}" / $"{x.stockBatch}" 182 Barcode: string.Empty, // 或 $"{x.materialCode}" / $"{x.stockBatch}"
@@ -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,33 +450,33 @@ public sealed class InboundMaterialService : IInboundMaterialService @@ -452,33 +450,33 @@ public sealed class InboundMaterialService : IInboundMaterialService
452 450
453 // ====== DTO(按接口示例字段) ====== 451 // ====== DTO(按接口示例字段) ======
454 public class GetInStockReq 452 public class GetInStockReq
455 - {  
456 - public string? createdTime { get; set; }  
457 - public string? endTime { get; set; }  
458 - public string? instockNo { get; set; }  
459 - public string? orderType { get; set; }  
460 - public string? startTime { get; set; }  
461 - } 453 +{
  454 + public string? createdTime { get; set; }
  455 + public string? endTime { get; set; }
  456 + public string? instockNo { get; set; }
  457 + public string? orderType { get; set; }
  458 + public string? startTime { get; set; }
  459 +}
462 460
463 - public class GetInStockResp  
464 - {  
465 - public int code { get; set; }  
466 - public long costTime { get; set; }  
467 - public string? message { get; set; }  
468 - public bool success { get; set; }  
469 - public List<GetInStockItem>? result { get; set; }  
470 - } 461 +public class GetInStockResp
  462 +{
  463 + public int code { get; set; }
  464 + public long costTime { get; set; }
  465 + public string? message { get; set; }
  466 + public bool success { get; set; }
  467 + public List<GetInStockItem>? result { get; set; }
  468 +}
471 469
472 - public class GetInStockItem  
473 - {  
474 - public string? arrivalNo { get; set; }  
475 - public string? createdTime { get; set; }  
476 - public string? instockId { get; set; }  
477 - public string? instockNo { get; set; }  
478 - public string? orderType { get; set; }  
479 - public string? purchaseNo { get; set; }  
480 - public string? supplierName { get; set; }  
481 - } 470 +public class GetInStockItem
  471 +{
  472 + public string? arrivalNo { get; set; }
  473 + public string? createdTime { get; set; }
  474 + public string? instockId { get; set; }
  475 + public string? instockNo { get; set; }
  476 + public string? orderType { get; set; }
  477 + public string? purchaseNo { get; set; }
  478 + public string? supplierName { get; set; }
  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 - {  
508 - public string? barcode { get; set; }  
509 - public string? instockId { get; set; }  
510 - public string? location { get; set; }  
511 - public string? materialName { get; set; }  
512 - public string? qty { get; set; }  
513 - public string? spec { get; set; }  
514 - } 505 +{
  506 + public string? barcode { get; set; }
  507 + public string? instockId { get; set; }
  508 + public string? location { get; set; }
  509 + public string? materialName { get; set; }
  510 + public string? qty { get; set; }
  511 + public string? spec { get; set; }
  512 +}
515 513
516 - public class ScanByBarcodeResp  
517 - {  
518 - public int code { get; set; }  
519 - public long costTime { get; set; }  
520 - public string? message { get; set; }  
521 - public object? result { get; set; } // 文档里 result 只是 bool/无结构,这里占位  
522 - public bool success { get; set; }  
523 - }  
524 - public class ScanConfirmResp  
525 - {  
526 - public int code { get; set; }  
527 - public long costTime { get; set; }  
528 - public string? message { get; set; }  
529 - public object? result { get; set; }  
530 - public bool success { get; set; }  
531 - }  
532 - public class CancelScanResp  
533 - {  
534 - public int code { get; set; }  
535 - public long costTime { get; set; }  
536 - public string? message { get; set; }  
537 - public object? result { get; set; }  
538 - public bool success { get; set; }  
539 - }  
540 - public class ConfirmResp  
541 - {  
542 - public int code { get; set; }  
543 - public long costTime { get; set; }  
544 - public string? message { get; set; }  
545 - public bool? result { get; set; }  
546 - public bool? success { get; set; }  
547 - }  
548 - public class JudgeScanAllResp  
549 - {  
550 - public int code { get; set; }  
551 - public long costTime { get; set; }  
552 - public string? message { get; set; }  
553 - public bool success { get; set; }  
554 - public bool? result { get; set; } // 文档中为布尔  
555 - } 514 +public class ScanByBarcodeResp
  515 +{
  516 + public int code { get; set; }
  517 + public long costTime { get; set; }
  518 + public string? message { get; set; }
  519 + public object? result { get; set; } // 文档里 result 只是 bool/无结构,这里占位
  520 + public bool success { get; set; }
  521 +}
  522 +public class ScanConfirmResp
  523 +{
  524 + public int code { get; set; }
  525 + public long costTime { get; set; }
  526 + public string? message { get; set; }
  527 + public object? result { get; set; }
  528 + public bool success { get; set; }
  529 +}
  530 +public class CancelScanResp
  531 +{
  532 + public int code { get; set; }
  533 + public long costTime { get; set; }
  534 + public string? message { get; set; }
  535 + public object? result { get; set; }
  536 + public bool success { get; set; }
  537 +}
  538 +public class ConfirmResp
  539 +{
  540 + public int code { get; set; }
  541 + public long costTime { get; set; }
  542 + public string? message { get; set; }
  543 + public bool? result { get; set; }
  544 + public bool? success { get; set; }
  545 +}
  546 +public class JudgeScanAllResp
  547 +{
  548 + public int code { get; set; }
  549 + public long costTime { get; set; }
  550 + public string? message { get; set; }
  551 + public bool success { get; set; }
  552 + public bool? result { get; set; } // 文档中为布尔
  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,11 +158,11 @@ namespace IndustrialControl.Services @@ -131,11 +158,11 @@ 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
140 } 167 }
141 -} 168 +}
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 {
@@ -108,7 +108,7 @@ namespace IndustrialControl.ViewModels @@ -108,7 +108,7 @@ namespace IndustrialControl.ViewModels
108 return; 108 return;
109 } 109 }
110 110
111 - 111 +
112 await ShowTip("已取消扫描。"); 112 await ShowTip("已取消扫描。");
113 } 113 }
114 114
@@ -137,7 +137,7 @@ namespace IndustrialControl.ViewModels @@ -137,7 +137,7 @@ namespace IndustrialControl.ViewModels
137 return; 137 return;
138 } 138 }
139 139
140 - 140 +
141 } 141 }
142 142
143 143
@@ -162,7 +162,7 @@ namespace IndustrialControl.ViewModels @@ -162,7 +162,7 @@ namespace IndustrialControl.ViewModels
162 return false; 162 return false;
163 } 163 }
164 164
165 - 165 +
166 166
167 return true; 167 return true;
168 } 168 }
@@ -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 {
@@ -82,9 +82,9 @@ public partial class InboundProductionSearchViewModel : ObservableObject @@ -82,9 +82,9 @@ public partial class InboundProductionSearchViewModel : ObservableObject
82 ["supplierName"] = o.supplierName, 82 ["supplierName"] = o.supplierName,
83 ["arrivalNo"] = o.arrivalNo, 83 ["arrivalNo"] = o.arrivalNo,
84 ["instockQty"] = o.instockQty, 84 ["instockQty"] = o.instockQty,
85 - ["materialName"] = o.materialName,  
86 - ["workOrderNo"] = o.workOrderNo,  
87 - ["createdTime"] = o.createdTime 85 + ["materialName"] = o.materialName,
  86 + ["workOrderNo"] = o.workOrderNo,
  87 + ["createdTime"] = o.createdTime
88 }); 88 });
89 89
90 } 90 }
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();
@@ -111,7 +109,7 @@ namespace IndustrialControl.ViewModels @@ -111,7 +109,7 @@ namespace IndustrialControl.ViewModels
111 Qty = r.Qty 109 Qty = r.Qty
112 }); 110 });
113 111
114 - 112 +
115 // 聚合可选库位 113 // 聚合可选库位
116 if (!string.IsNullOrWhiteSpace(r.Location) && !AvailableBins.Contains(r.Location)) 114 if (!string.IsNullOrWhiteSpace(r.Location) && !AvailableBins.Contains(r.Location))
117 AvailableBins.Add(r.Location); 115 AvailableBins.Add(r.Location);
@@ -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();
@@ -374,6 +370,6 @@ namespace IndustrialControl.ViewModels @@ -374,6 +370,6 @@ namespace IndustrialControl.ViewModels
374 public int OutstockQty { get; set; } //出库数量 370 public int OutstockQty { get; set; } //出库数量
375 public int Qty { get; set; } //已扫描数 371 public int Qty { get; set; } //已扫描数
376 public string Bin { get; set; } = "请选择"; 372 public string Bin { get; set; } = "请选择";
377 - 373 +
378 } 374 }
379 } 375 }
  1 +{ "sdk": { "version": "8.0.414" } }