OutboundFinishedViewModel.cs 11.5 KB
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using IndustrialControl.Services;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;

namespace IndustrialControl.ViewModels
{
    public partial class OutboundFinishedViewModel : ObservableObject
    {
        [ObservableProperty] private string? scanCode;
        private readonly IOutboundMaterialService _warehouseSvc;

        // === 基础信息(由搜索页带入) ===
        [ObservableProperty] private string? outstockId;
        [ObservableProperty] private string? outstockNo;
        [ObservableProperty] private string? orderType;
        [ObservableProperty] private string? orderTypeName;
        [ObservableProperty] private string? purchaseNo;
        [ObservableProperty] private string? supplierName;
        [ObservableProperty] private string? createdTime;
        [ObservableProperty] private string? requisitionMaterialNo;
        [ObservableProperty] private string? returnNo;
        [ObservableProperty] private string? workOrderNo;
        // 列表数据源
        public ObservableCollection<string> AvailableBins { get; } = new();
        public ObservableCollection<OutScannedItem> ScannedList { get; } = new();
        public ObservableCollection<PendingItem> PendingList { get; } = new();

        [ObservableProperty] private OutScannedItem? selectedScanItem;

        // Tab 控制
        [ObservableProperty] private bool isPendingVisible = true;
        [ObservableProperty] private bool isScannedVisible = false;

        // 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; }

        public OutboundFinishedViewModel(IOutboundMaterialService warehouseSvc)
        {
            _warehouseSvc = warehouseSvc;
            ShowPendingCommand = new RelayCommand(() => SwitchTab(true));
            ShowScannedCommand = new RelayCommand(() => SwitchTab(false));
            //ConfirmCommand = new AsyncRelayCommand(ConfirmInboundAsync);
        }

        // ================ 初始化入口(页面 OnAppearing 调用) ================
        public async Task InitializeFromSearchAsync(
            string outstockId, string outstockNo, string orderType, string orderTypeName,
            string purchaseNo, string supplierName, string createdTime)
        {
            // 1) 基础信息
            OutstockId = outstockId;
            OutstockNo = outstockNo;
            OrderType = orderType;
            OrderTypeName = orderTypeName;
            PurchaseNo = purchaseNo;
            SupplierName = supplierName;
            CreatedTime = createdTime;

            // 2) 下拉库位(如无接口可留空或使用后端返回的 location 聚合)
            AvailableBins.Clear();

            // 3) 拉取两张表
            await LoadPendingAsync();
            await LoadScannedAsync();

            // 默认显示“待入库明细”
            SwitchTab(true);
        }

        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";
            }
        }

        private async Task LoadPendingAsync()
        {
            PendingList.Clear();
            if (string.IsNullOrWhiteSpace(OutstockId)) return;

            var rows = await _warehouseSvc.GetOutStockDetailAsync(OutstockId!);
            foreach (var r in rows)
            {
                PendingList.Add(new PendingItem
                {
                    Name = r.MaterialName ?? "",
                    Spec = r.Spec ?? "",
                    PendingQty = r.PendingQty,
                    Bin = string.IsNullOrWhiteSpace(r.Location) ? "请选择" : r.Location!,
                    ScannedQty = r.ScannedQty
                });

                // 聚合可选库位
                if (!string.IsNullOrWhiteSpace(r.Location) && !AvailableBins.Contains(r.Location))
                    AvailableBins.Add(r.Location);
            }
        }

        private async Task LoadScannedAsync()
        {
            ScannedList.Clear();
            if (string.IsNullOrWhiteSpace(OutstockId)) return;

            var rows = await _warehouseSvc.GetOutStockScanDetailAsync(OutstockId!);
            foreach (var r in rows)
            {
                ScannedList.Add(new OutScannedItem
                {
                    IsSelected = false,
                    Barcode = r.Barcode ?? "",
                    Name = r.MaterialName ?? "",
                    Spec = r.Spec ?? "",
                    Bin = string.IsNullOrWhiteSpace(r.Location) ? "请选择" : r.Location!,
                    Qty = r.Qty
                });

                if (!string.IsNullOrWhiteSpace(r.Location) && !AvailableBins.Contains(r.Location))
                    AvailableBins.Add(r.Location);
            }
        }

        [RelayCommand]
        private async Task PassScan()
        {
            if (string.IsNullOrWhiteSpace(OutstockId))
            {
                await ShowTip("缺少 OutstockId,无法确认。请从查询页进入。");
                return;
            }

            // 依旧要求只能选中一行,作为“操作目标”的 UI 约束(接口本身仅需 instockId)
            var selected = ScannedList.Where(x => x.IsSelected).ToList();
            if (selected.Count != 1)
            {
                await ShowTip(selected.Count == 0 ? "请先勾选一条已扫描记录。" : "一次只能操作一条记录。");
                return;
            }
            var selectedBarcode = selected[0].Barcode;

            // 调用确认接口
            var resp = await _warehouseSvc.ScanConfirmAsync(OutstockId!);
            if (!resp.Succeeded)
            {
                await ShowTip(string.IsNullOrWhiteSpace(resp.Message) ? "扫描通过失败,请重试。" : resp.Message!);
                return;
            }

            // 成功:刷新两张表
            await LoadPendingAsync();
            await LoadScannedAsync();

            // 友好:恢复选中刚才那条(如果还在列表里)
            var hit = ScannedList.FirstOrDefault(x =>
                string.Equals(x.Barcode, selectedBarcode, StringComparison.OrdinalIgnoreCase));
            if (hit != null) { hit.IsSelected = true; SelectedScanItem = hit; }

            await ShowTip("已确认通过。");
        }


        [RelayCommand]
        private async Task CancelScan()
        {
            if (string.IsNullOrWhiteSpace(OutstockId))
            {
                await ShowTip("缺少 OutstockId,无法取消。请从查询页进入。");
                return;
            }

            // 依旧限制一次只操作一条(接口本身只要 instockId,这里是 UI 规范)
            var selected = ScannedList.Where(x => x.IsSelected).ToList();
            if (selected.Count != 1)
            {
                await ShowTip(selected.Count == 0 ? "请先勾选一条已扫描记录。" : "一次只能操作一条记录。");
                return;
            }
            var selectedBarcode = selected[0].Barcode;

            var resp = await _warehouseSvc.CancelScanAsync(OutstockId!);
            if (!resp.Succeeded)
            {
                await ShowTip(string.IsNullOrWhiteSpace(resp.Message) ? "取消扫描失败,请重试。" : resp.Message!);
                return;
            }

            // 成功后以服务端为准刷新两张表
            await LoadPendingAsync();
            await LoadScannedAsync();

            // 友好:若那条还在列表里,恢复选中
            var hit = ScannedList.FirstOrDefault(x =>
                string.Equals(x.Barcode, selectedBarcode, StringComparison.OrdinalIgnoreCase));
            if (hit != null) { hit.IsSelected = true; SelectedScanItem = hit; }

            await ShowTip("已取消扫描。");
        }


        public async Task HandleScannedAsync(string data, string symbology)
        {
            var barcode = (data ?? string.Empty).Trim();
            if (string.IsNullOrWhiteSpace(barcode))
            {
                await ShowTip("无效条码。");
                return;
            }

            if (string.IsNullOrWhiteSpace(OutstockId))
            {
                await ShowTip("缺少 OutstockId,无法入库。请从查询页进入。");
                return;
            }

            // 调用扫码入库接口
            var resp = await _warehouseSvc.OutStockByBarcodeAsync(OutstockId!, barcode);

            if (!resp.Succeeded)
            {
                await ShowTip(string.IsNullOrWhiteSpace(resp.Message) ? "入库失败,请重试或检查条码。" : resp.Message!);
                return;
            }

            // 成功 → 刷新“待入库明细”和“已扫描明细”
            await LoadPendingAsync();
            await LoadScannedAsync();

            // UI 友好:尝试高亮刚扫的那一条
            var hit = ScannedList.FirstOrDefault(x => string.Equals(x.Barcode, barcode, StringComparison.OrdinalIgnoreCase));
            if (hit != null)
            {
                hit.IsSelected = true;
                SelectedScanItem = hit;
                // 切到“已扫描”页签更直观(可选)
                // SwitchTab(false);
            }
        }


        private Task ShowTip(string message) =>
            Shell.Current?.DisplayAlert("提示", message, "确定") ?? Task.CompletedTask;


        public void ClearScan() => ScannedList.Clear();
        public void ClearAll()
        {
            PendingList.Clear();
            ScannedList.Clear();
        }

        public void SetItemBin(object row, string bin)
        {
            if (row is OutScannedItem item) { item.Bin = bin; return; }
            var barcode = row?.GetType().GetProperty("Barcode")?.GetValue(row)?.ToString();
            if (!string.IsNullOrWhiteSpace(barcode))
            {
                var target = ScannedList.FirstOrDefault(x => x.Barcode == barcode);
                if (target != null) target.Bin = bin;
            }
        }

        public async Task<bool> ConfirmInboundAsync()
        {
            if (string.IsNullOrWhiteSpace(OutstockId))
            {
                await ShowTip("缺少 OutstockId,无法确认入库。请从查询页进入。");
                return false;
            }

            var r = await _warehouseSvc.ConfirmOutstockAsync(OutstockId!);
            if (!r.Succeeded)
            {
                await ShowTip(string.IsNullOrWhiteSpace(r.Message) ? "确认入库失败,请重试。" : r.Message!);
                return false;
            }

            // 成功:可选刷新一次,以服务端为准;随后按钮事件里会 ClearAll()
            await LoadPendingAsync();
            await LoadScannedAsync();
            return true;
        }

    }


}