InboundMaterialViewModel.cs 9.8 KB
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Collections.ObjectModel;
using IndustrialControl.Services;
using System.Threading.Tasks;

namespace IndustrialControl.ViewModels
{
    public partial class InboundMaterialViewModel : ObservableObject
    {
        [ObservableProperty] private string? scanCode;
        private readonly IWarehouseDataService _warehouseSvc;
        public ObservableCollection<string> AvailableBins { get; set; } = new ObservableCollection<string>
{
    "CK1_A201",
    "CK1_A202",
    "CK1_A203",
    "CK1_A204"
};
        public ObservableCollection<OutScannedItem> ScannedList { get; } 
        public ObservableCollection<PendingItem> PendingList { get; set; }

        [ObservableProperty]
        private OutScannedItem? selectedScanItem;

        public InboundMaterialViewModel(IWarehouseDataService warehouseSvc)
        {
            _warehouseSvc = warehouseSvc;

            // 初始化命令
            ShowPendingCommand = new RelayCommand(() => SwitchTab(true));
            ShowScannedCommand = new RelayCommand(() => SwitchTab(false));
            ConfirmCommand = new AsyncRelayCommand(ConfirmInboundAsync);

            // 默认显示待入库明细
            IsPendingVisible = true;
            IsScannedVisible = false;

            // 测试数据(上线可去掉)
            PendingList = new ObservableCollection<PendingItem>
            {
                new PendingItem { Name="物料1", Spec="XXX", PendingQty=100, Bin="CK1_A201", ScannedQty=80 },
                new PendingItem { Name="物料2", Spec="YYY", PendingQty=50, Bin="CK1_A202", ScannedQty=0 }
            };

            ScannedList = new ObservableCollection<OutScannedItem>
            {
                new OutScannedItem { IsSelected=false, Barcode="FSC2025060300001", Name="物料1", Spec="XXX", Bin="CK1_A201", Qty=1 },
                new OutScannedItem { IsSelected=false, Barcode="FSC2025060300002", Name="物料1", Spec="XXX", Bin="请选择", Qty=1 }
            };
        }

        // 基础信息
        [ObservableProperty] private string orderNo;
        [ObservableProperty] private string linkedDeliveryNo;
        [ObservableProperty] private string linkedPurchaseNo;
        [ObservableProperty] private string supplier;

        // Tab 显示控制
        [ObservableProperty] private bool isPendingVisible;
        [ObservableProperty] private bool isScannedVisible;

        // Tab 按钮颜色
        [ObservableProperty] private string pendingTabColor = "#E6F2FF";
        [ObservableProperty] private string scannedTabColor = "White";
        [ObservableProperty] private string pendingTextColor = "#007BFF";
        [ObservableProperty] private string scannedTextColor = "#333333";

        // 列表数据


        // 命令
        public IRelayCommand ShowPendingCommand { get; }
        public IRelayCommand ShowScannedCommand { get; }
        public IAsyncRelayCommand ConfirmCommand { get; }

        /// <summary>
        /// 切换 Tab
        /// </summary>
        private void SwitchTab(bool showPending)
        {
            IsPendingVisible = showPending;
            IsScannedVisible = !showPending;

            if (showPending)
            {
                PendingTabColor = "#E6F2FF";
                ScannedTabColor = "White";
                PendingTextColor = "#007BFF";
                ScannedTextColor = "#333333";
            }
            else
            {
                PendingTabColor = "White";
                ScannedTabColor = "#E6F2FF";
                PendingTextColor = "#333333";
                ScannedTextColor = "#007BFF";
            }
        }

        /// <summary>
        /// 清空扫描记录
        /// </summary>
        public void ClearScan()
        {
            ScannedList.Clear();
        }

        /// <summary>
        /// 清空所有数据
        /// </summary>
        public void ClearAll()
        {
            OrderNo = string.Empty;
            LinkedDeliveryNo = string.Empty;
            LinkedPurchaseNo = string.Empty;
            Supplier = string.Empty;
            PendingList.Clear();
            ScannedList.Clear();
        }

        [RelayCommand]
        private async Task PassScan()   // 绑定到 XAML 的 PassScanCommand
        {
            var selected = ScannedList.Where(x => x.IsSelected).ToList();

            if (selected.Count == 0)
            {
                await ShowTip("请先勾选一行记录。");
                return;
            }
            if (selected.Count > 1)
            {
                await ShowTip("一次只能操作一行,请只勾选一行。");
                return;
            }

            var row = selected[0];
            row.Qty += 1;
            row.Qty -= 1;
            // 确保本行已变绿(如果你的行颜色基于 IsSelected)
            if (!row.IsSelected) row.IsSelected = true;
            SelectedScanItem = row;

        }

        [RelayCommand]
        private async Task CancelScan() // 绑定到 XAML 的 CancelScanCommand
        {
            var selected = ScannedList.Where(x => x.IsSelected).ToList();

            if (selected.Count == 0)
            {
                await ShowTip("请先勾选一行记录。");
                return;
            }
            if (selected.Count > 1)
            {
                await ShowTip("一次只能操作一行,请只勾选一行。");
                return;
            }

            var row = selected[0];
            if (row.Qty <= 0)
            {
                await ShowTip("该行数量已为 0,无法再减少。");
                return;
            }

            row.Qty -= 1;

            // 如果希望数量减到 0 时取消高亮,可打开下一行
            // if (row.Qty == 0) row.IsSelected = false;
        }

        public async Task HandleScannedAsync(string data, string symbology)
        {
            // TODO: 你的规则(判断是订单号/物料码/包装码等)
            //      然后:查询接口 / 加入列表 / 自动提交
            await Task.CompletedTask;
        }
        private Task ShowTip(string message) =>
        Shell.Current?.DisplayAlert("提示", message, "确定") ?? Task.CompletedTask;

        /// <summary>
        /// 确认入库逻辑
        /// </summary>
        public async Task<bool> ConfirmInboundAsync()
        {
            if (string.IsNullOrWhiteSpace(OrderNo))
                return false;

            var result = await _warehouseSvc.ConfirmInboundAsync(OrderNo,
                ScannedList.Select(x => new ScanItem(0, x.Barcode, x.Bin, x.Qty)));

            return result.Succeeded;
        }

        public async Task LoadOrderAsync(string orderNo)
        {
            // 0) 清空旧数据
            ClearAll();

            // 1) 基础信息
            var order = await _warehouseSvc.GetInboundOrderAsync(orderNo);
            OrderNo = order.OrderNo;
            Supplier = order.Supplier ?? string.Empty;
            LinkedDeliveryNo = order.LinkedNo ?? string.Empty;     // 到货/交货单
            LinkedPurchaseNo = order is { } ? LinkedPurchaseNo : ""; // 你没有就留空

            // 2) 预入库库位:从接口取(先 mock),用于行内 Picker
            //    (你已经在 IWarehouseDataService 里加了 ListInboundBinsAsync)
            try
            {
                var bins = await _warehouseSvc.ListInboundBinsAsync(orderNo);
                AvailableBins.Clear();
                foreach (var b in bins) AvailableBins.Add(b);
            }
            catch
            {
                // 兜底:本地 mock,避免空集合导致 Picker 无选项
                AvailableBins.Clear();
                foreach (var b in new[] { "CK1_A201", "CK1_A202", "CK1_A203", "CK1_A204" })
                    AvailableBins.Add(b);
            }
            var defaultBin = AvailableBins.FirstOrDefault() ?? "CK1_A201";

            // 3) 待入库明细:如果暂时没有后端接口,这里先 mock 多行,便于 UI 联调
            PendingList.Clear();
            // 你原来只加了 1 行,这里多给两行方便测试
            PendingList.Add(new PendingItem { Name = "物料X", Spec = "型号X", PendingQty = order.ExpectedQty, Bin = defaultBin, ScannedQty = 0 });
            PendingList.Add(new PendingItem { Name = "物料Y", Spec = "型号Y", PendingQty = Math.Max(10, order.ExpectedQty / 2), Bin = defaultBin, ScannedQty = 0 });
            PendingList.Add(new PendingItem { Name = "物料Z", Spec = "型号Z", PendingQty = 8, Bin = defaultBin, ScannedQty = 0 });

            // 4) 扫描明细初始化(为空即可;也可以放 1~2 条便于测试)
            ScannedList.Clear();
            // 可选:放两条测试数据,验证“库位下拉/数量可编辑”
            ScannedList.Add(new OutScannedItem { IsSelected = false, Barcode = "FSC2025060300001", Name = "物料X", Spec = "型号X", Bin = defaultBin, Qty = 1 });
            ScannedList.Add(new OutScannedItem { IsSelected = false, Barcode = "FSC2025060300002", Name = "物料Y", Spec = "型号Y", Bin = defaultBin, Qty = 2 });

            // 5) 默认展示“待入库明细”页签
            SwitchTab(true);
        }



    }

    // 待入库明细模型
    public class PendingItem
    {
        public string Name { get; set; }
        public string Spec { get; set; }
        public int PendingQty { get; set; }
        public string Bin { get; set; }
        public int ScannedQty { get; set; }
    }

    // 扫描明细模型
    public partial class OutScannedItem : ObservableObject
    {
        [ObservableProperty] private bool isSelected;
        [ObservableProperty] private string barcode;
        [ObservableProperty] private string name;
        [ObservableProperty] private string spec;
        [ObservableProperty] private string bin;
        [ObservableProperty] private int qty;
    }

}