feat(成品入库): 实现分页查询功能并优化界面交互

- 为成品入库模块添加分页查询功能
- 重构查询服务支持分页数据返回
- 优化主界面布局和交互逻辑
- 改进打印预览对话框状态显示
- 添加分页控件和相关命令处理
This commit is contained in:
赵正易 2025-11-18 17:21:45 +08:00
parent 539abee410
commit ca3e27a566
9 changed files with 639 additions and 354 deletions

View File

@ -193,7 +193,7 @@ namespace RIZO_Application.Models.Model
public string Remark { get; set; } = string.Empty;
}
public class FinishedProductQueryDto
public class FinishedProductQueryDto: PagerInfo
{
public DateTime? StartTime { get; set; }
public DateTime? EndTime { get; set; }

View File

@ -1,4 +1,5 @@
using SqlSugar;
using RIZO_Application.Models.Model;
using SqlSugar;
using SqlSugar.IOC;
using System;
using System.Collections.Generic;
@ -58,4 +59,30 @@ namespace RIZO_Application.Repository
return await Context.Deleteable<T>().In(id).ExecuteCommandAsync() > 0;
}
}
/// <summary>
/// 分页查询扩展
/// </summary>
public static class QueryableExtension
{
/// <summary>
/// 读取列表
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source">查询表单式</param>
/// <param name="parm">分页参数</param>
/// <returns></returns>
public static PagedInfo<T> ToPage<T>(this ISugarQueryable<T> source, PagerInfo parm)
{
var page = new PagedInfo<T>();
var total = 0;
page.PageSize = parm.PageSize;
page.PageIndex = parm.PageNum;
page.Result = source
//.OrderByIF(parm.Sort.IsNotEmpty(), $"{parm.Sort.ToSqlFilter()} {(!string.IsNullOrWhiteSpace(parm.SortType) && parm.SortType.Contains("desc") ? "desc" : "asc")}")
.ToPageList(parm.PageNum, parm.PageSize, ref total);
page.TotalNum = total;
return page;
}
}
}

View File

@ -10,6 +10,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\RIZO_Application.Models\RIZO_Application.Models.csproj" />
<ProjectReference Include="..\RIZO_Application\RIZO_Application.Infrastructure\RIZO_Application.Infrastructure.csproj" />
</ItemGroup>

View File

@ -1,95 +1,78 @@
using System;
using System.Collections.Generic;
using System.Drawing.Printing;
using System.Net.Http;
using System.Text;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using Prism.Events;
using RIZO_Application.Core;
using RIZO_Application.Infrastructure.CustomAttribute;
using RIZO_Application.Infrastructure.Model;
using RIZO_Application.Models;
using RIZO_Application.Models.Model;
using RIZO_Application.Modules.ModuleName.Services.IServices;
using RIZO_Application.Repository;
using SqlSugar;
using SqlSugar.IOC;
using RIZO_Application.Infrastructure.CustomAttribute;
using RIZO_Application.Infrastructure.Model;
namespace RIZO_Application.Modules.ModuleName.Services
{
[AppService(
ServiceType = typeof(IFinishedProductService),
Lifetime = ServiceLifetime.Singleton
)]
public class FinishedProductService
: BaseRepository<ProFinishedProductReceipt>,
IFinishedProductService
[AppService(ServiceType = typeof(IFinishedProductService), Lifetime = ServiceLifetime.Transient)]
public class FinishedProductService : BaseRepository<ProFinishedProductReceipt>, IFinishedProductService
{
private readonly HttpClient _httpClient;
private readonly IEventAggregator _eventAggregator;
private readonly IPrintService _printService;
private readonly SqlSugarClient _db;
private readonly bool _useMockData = false;
private readonly string _labelFrom; // 改为在构造函数中初始化
private readonly List<ProFinishedProductReceipt> _mockData;
private readonly bool _useMockData = false; // 控制是否使用模拟数据
private readonly string _labelFrom = PrintConfigs.Current.LabelFrom;
public FinishedProductService(IEventAggregator eventAggregator, IPrintService printService)
public FinishedProductService(IEventAggregator eventAggregator)
{
_httpClient = new HttpClient();
_httpClient.BaseAddress = new Uri(ServerConfigs.Current.ServerPath); // 设置默认请求地址前缀
_eventAggregator = eventAggregator;
_printService = printService;
_mockData = GenerateMockData();
// 安全地获取标签来源配置
_labelFrom = PrintConfigs.Current?.LabelFrom ?? "全部";
}
// 初始化模拟数据
_mockData = new List<ProFinishedProductReceipt>
private List<ProFinishedProductReceipt> GenerateMockData()
{
var mockData = new List<ProFinishedProductReceipt>();
var random = new Random();
// 生成30条测试数据分布在不同的日期
for (int i = 1; i <= 30; i++)
{
new ProFinishedProductReceipt
var daysOffset = random.Next(-30, 1); // 最近30天内的数据
var createdTime = DateTime.Now.AddDays(daysOffset);
var receiptDate = createdTime.Date;
var statuses = new[] { "SUBMITTED", "APPROVED", "COMPLETED" };
var printStatuses = new[] { "全部", "未打印", "已打印" };
var receiptTypes = new[] { "全部", "正常入库", "返工入库", "其他入库" };
var labelFroms = new[] { "全部", "GP12", "后道", "产线" };
mockData.Add(new ProFinishedProductReceipt
{
ReceiptNo = "RK202511140001",
WorkOrder = "W20251114001",
Description = "T1EJ左后门把手-新卡其白",
PartNumber = "220707",
PackageCount = 8,
PackageNum = 465,
BatchCode = "20240501001",
WarehouseCode = "A1-01-01",
CreatedBy = "admin",
ProductionTime = DateTime.Now.AddDays(-1),
LabelPrintStatus = "未打印",
ReceiptNo = $"RK{receiptDate:yyyyMMdd}{i:D4}",
ReceiptDate = receiptDate,
ReceiptType = receiptTypes[random.Next(receiptTypes.Length)],
WorkOrder = $"WO{receiptDate:yyyyMMdd}{random.Next(100, 999)}",
Description = $"产品{random.Next(1, 10)}入库",
PartNumber = $"PART{random.Next(100, 999):D3}",
PackageCount = random.Next(5, 50),
PackageNum = 1,
BatchCode = $"BATCH{random.Next(1, 20):D3}",
WarehouseCode = $"WH{random.Next(1, 5):D3}",
CreatedBy = new[] { "张三", "李四", "王五", "赵六" }[random.Next(4)],
CreatedTime = createdTime,
ProductionTime = receiptDate.AddHours(random.Next(8, 18)),
Status = statuses[random.Next(statuses.Length)],
LabelPrintStatus = printStatuses[random.Next(printStatuses.Length)],
LabelFrom = labelFroms[random.Next(labelFroms.Length)],
Remark = "正常入库"
},
new ProFinishedProductReceipt
{
ReceiptNo = "RK202511140002",
WorkOrder = "W20251114002",
Description = "T1EJ右前门把手-右舵-新卡其白",
PartNumber = "221353",
PackageCount = 7,
PackageNum = 458,
BatchCode = "20240502001",
WarehouseCode = "A1-02-01",
CreatedBy = "admin",
ProductionTime = DateTime.Now,
LabelPrintStatus = "未打印",
Remark = "正常入库"
},
new ProFinishedProductReceipt
{
ReceiptNo = "RK202511140003",
WorkOrder = "W20251114003",
Description = "T1EJ右前门把手-左舵-新卡其白",
PartNumber = "220701",
PackageCount = 7,
PackageNum = 475,
BatchCode = "20240502002",
WarehouseCode = "A1-02-02",
CreatedBy = "admin",
ProductionTime = DateTime.Now,
LabelPrintStatus = "未打印",
Remark = "正常入库"
}
};
});
}
return mockData;
}
public async Task<IEnumerable<ProFinishedProductReceipt>> GetFinishedProductsAsync(
@ -143,6 +126,86 @@ namespace RIZO_Application.Modules.ModuleName.Services
}
}
public async Task<PagedInfo<ProFinishedProductReceipt>> GetFinishedProductsPagedAsync(FinishedProductQueryDto query)
{
try
{
if (_useMockData)
{
_eventAggregator.GetEvent<SystemLogEvent>().Publish("使用模拟数据获取分页成品入库单");
// 模拟分页逻辑
var queryable = _mockData.AsQueryable();
// 应用查询条件
if (!string.IsNullOrEmpty(query.LabelFrom) && query.LabelFrom != "全部")
{
queryable = queryable.Where(x => x.LabelFrom == query.LabelFrom);
}
if (!string.IsNullOrEmpty(query.LabelPrintStatus) && query.LabelPrintStatus != "全部")
{
queryable = queryable.Where(x => x.LabelPrintStatus == query.LabelPrintStatus);
}
if (query.StartTime.HasValue && query.StartTime.Value > DateTime.MinValue)
{
queryable = queryable.Where(x => x.CreatedTime >= query.StartTime.Value);
}
if (query.EndTime.HasValue && query.EndTime.Value > DateTime.MinValue)
{
var endDateInclusive = query.EndTime.Value.AddDays(1);
queryable = queryable.Where(x => x.CreatedTime <= endDateInclusive);
}
var totalCount = queryable.Count();
var items = queryable
.OrderByDescending(x => x.ReceiptNo)
.Skip((query.PageNum - 1) * query.PageSize)
.Take(query.PageSize)
.ToList();
return new PagedInfo<ProFinishedProductReceipt> {
PageIndex = query.PageNum,
PageSize = query.PageSize,
TotalNum = totalCount,
Result = items
};
}
else
{
DateTime? endDateInclusive = null;
if (query.EndTime.HasValue)
{
endDateInclusive = query.EndTime.Value.AddDays(1);
}
var total = 0;
var result = Context
.Queryable<ProFinishedProductReceipt>()
.WhereIF(!string.IsNullOrEmpty(query.LabelFrom) && query.LabelFrom != "全部", it => it.LabelFrom == query.LabelFrom)
.WhereIF(!string.IsNullOrEmpty(query.LabelPrintStatus) && query.LabelPrintStatus != "全部", it => it.LabelPrintStatus == query.LabelPrintStatus)
.WhereIF(query.StartTime.HasValue && query.StartTime.Value > DateTime.MinValue, it => it.CreatedTime >= query.StartTime.Value)
.WhereIF(query.EndTime.HasValue && query.EndTime.Value > DateTime.MinValue, it => it.CreatedTime <= endDateInclusive)
.OrderByDescending(it => it.ReceiptNo)
.ToPage(query);
return result;
}
}
catch (Exception ex)
{
_eventAggregator.GetEvent<SystemLogEvent>().Publish($"获取分页成品入库单失败: {ex.Message}");
return new PagedInfo<ProFinishedProductReceipt>
{
PageIndex = query.PageNum,
PageSize = query.PageSize,
TotalNum = 0,
Result = new List<ProFinishedProductReceipt>()
};
}
}
public async Task<ProFinishedProductReceipt> GetFinishedProductByReceiptNoAsync(string receiptNo)
{
try
@ -201,7 +264,7 @@ namespace RIZO_Application.Modules.ModuleName.Services
}
else
{
if (product.ReceiptNo.IsNullOrEmpty())
if (string.IsNullOrEmpty(product.ReceiptNo))
{
_eventAggregator.GetEvent<SystemLogEvent>().Publish($"添加成品入库单失败: 未填写入库单号");
return false;
@ -306,13 +369,13 @@ namespace RIZO_Application.Modules.ModuleName.Services
{
if (_useMockData)
{
var product = _mockData.Find(p => p.ReceiptNo == receiptNo);
if (product != null)
var index = _mockData.FindIndex(p => p.ReceiptNo == receiptNo);
if (index != -1)
{
_mockData.Remove(product);
_mockData.RemoveAt(index);
_eventAggregator
.GetEvent<SystemLogEvent>()
.Publish($"模拟删除成品入库单成功: {product.WorkOrder}");
.Publish($"模拟删除成品入库单成功: {receiptNo}");
return await Task.FromResult(true);
}
return await Task.FromResult(false);
@ -343,62 +406,34 @@ namespace RIZO_Application.Modules.ModuleName.Services
{
try
{
var product = await GetFinishedProductByReceiptNoAsync(receiptNo);
if (product == null)
if (_useMockData)
{
_eventAggregator.GetEvent<SystemLogEvent>().Publish("未找到要打印的成品入库单");
return false;
}
// 创建打印参数
var printDto = new PrintDto
{
Path = PrintConfigs.Current.BaseLabelPath,
SiteNo = product.SiteNo,
Name = $"成品入库单_{product.WorkOrder}",
LabelFrom = product.LabelFrom,
PartNumber = product.PartNumber,
Description = product.Description,
Color = product.Color,
Specification = product.Specification,
WorkOrder = product.WorkOrder,
PackageCode = product.PackageCode,
Team = product.Team,
Sort = 1, // 默认流水号
ProductionTime = product.ProductionTime?.ToString("yyyy-MM-dd HH:mm:ss") ?? "",
BatchCode = product.BatchCode,
PackageCout = product.PackageCount ?? 0,
PackageNum = product.PackageNum ?? 0,
LabelCode = product.LabelCode,
LabelType = 1, // 默认标签类型
CreatedTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
};
// 执行打印
bool success = await _printService.PrintLabelAsync(printDto);
// 如果打印成功,更新状态为已打印
if (success)
{
product.LabelPrintStatus = "已打印";
int recordUpdate = Context.Updateable(product).IgnoreColumns(ignoreAllNullColumns:true).ExecuteCommand();
ProFinishedProductReceiptLog finishedProductReceiptLog = new ProFinishedProductReceiptLog
var product = _mockData.Find(p => p.ReceiptNo == receiptNo);
if (product != null)
{
ReceiptNo = product.ReceiptNo,
OperatedBy = product.LabelFrom,
OperatedTime = DateTime.Now,
OperationType = "PRINT",
OperationContent = recordUpdate > 0 ? "入库单打印成功" : "入库单打印失败",
OperationResult = recordUpdate > 0 ? "SUCCESS" : "FAIL",
Remark = ""
};
Context.Insertable(finishedProductReceiptLog).ExecuteCommand();
_eventAggregator
.GetEvent<SystemLogEvent>()
.Publish($"更新成品入库单状态为已打印: {product.ReceiptNo}");
product.LabelPrintStatus = "已打印";
_eventAggregator
.GetEvent<SystemLogEvent>()
.Publish($"模拟打印成品入库单成功: {receiptNo}");
return await Task.FromResult(true);
}
return await Task.FromResult(false);
}
else
{
int result = Context
.Updateable<ProFinishedProductReceipt>()
.SetColumns(it => new ProFinishedProductReceipt { LabelPrintStatus = "已打印" })
.Where(it => it.ReceiptNo == receiptNo)
.ExecuteCommand();
if (result > 0)
{
_eventAggregator
.GetEvent<SystemLogEvent>()
.Publish($"打印成品入库单成功: {receiptNo}");
}
return result > 0;
}
return success;
}
catch (Exception ex)
{

View File

@ -7,6 +7,7 @@ namespace RIZO_Application.Modules.ModuleName.Services.IServices
public interface IFinishedProductService
{
Task<IEnumerable<ProFinishedProductReceipt>> GetFinishedProductsAsync(FinishedProductQueryDto query);
Task<PagedInfo<ProFinishedProductReceipt>> GetFinishedProductsPagedAsync(FinishedProductQueryDto query);
Task<ProFinishedProductReceipt> GetFinishedProductByReceiptNoAsync(string receiptNo);
Task<bool> AddFinishedProductAsync(ProFinishedProductReceipt product);
Task<bool> UpdateFinishedProductAsync(ProFinishedProductReceipt product);

View File

@ -34,13 +34,13 @@ namespace RIZO_Application.Modules.ModuleName.ViewModels
public DeleteConfirmDialogViewModel(IFinishedProductService finishedProductService)
{
_finishedProductService = finishedProductService;
ConfirmCommand = new DelegateCommand(ConfirmDelete);
ConfirmCommand = new DelegateCommand(async () => await ConfirmDeleteAsync());
CancelCommand = new DelegateCommand(Cancel);
}
private void ConfirmDelete()
private async System.Threading.Tasks.Task ConfirmDeleteAsync()
{
var success = _finishedProductService.DeleteFinishedProductAsync(Product.ReceiptNo).Result;
var success = await _finishedProductService.DeleteFinishedProductAsync(Product.ReceiptNo);
if (success) {
var result = new DialogResult(ButtonResult.OK, new DialogParameters { { "Product", Product } });
RequestClose?.Invoke(result);

View File

@ -1,232 +1,408 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using Prism.Regions;
using Prism.Services.Dialogs;
using RIZO_Application.Core;
using RIZO_Application.Core.Mvvm;
using RIZO_Application.Infrastructure.Model;
using RIZO_Application.Models.Model;
using RIZO_Application.Modules.ModuleName.Services.IServices;
using RIZO_Application.Services.Interfaces;
namespace RIZO_Application.Modules.ModuleName.ViewModels
{
public class MainControlViewModel : RegionViewModelBase
{
private readonly IPrintService _printService;
private readonly IFinishedProductService _finishedProductService;
private readonly IEventAggregator _eventAggregator;
private readonly IDialogService _dialogService;
private readonly string _labelFrom = PrintConfigs.Current.LabelFrom;
private string _message;
public string Message
#region
private ObservableCollection<ProFinishedProductReceipt> _finishedProducts;
public ObservableCollection<ProFinishedProductReceipt> FinishedProducts
{
get { return _message; }
set { SetProperty(ref _message, value); }
get => _finishedProducts;
set => SetProperty(ref _finishedProducts, value);
}
private List<ProFinishedProductReceipt> _finishedProducts;
public List<ProFinishedProductReceipt> FinishedProducts
private FinishedProductQueryDto _queryDto;
public FinishedProductQueryDto QueryDto
{
get { return _finishedProducts; }
set { SetProperty(ref _finishedProducts, value); }
get => _queryDto;
set => SetProperty(ref _queryDto, value);
}
private ProFinishedProductReceipt _selectedProduct;
public ProFinishedProductReceipt SelectedProduct
private DateTime _startDate;
private bool _isInitialized = false; // 添加初始化标志
public DateTime StartDate
{
get { return _selectedProduct; }
set { SetProperty(ref _selectedProduct, value); }
get => _startDate;
set
{
SetProperty(ref _startDate, value);
if (_isInitialized) // 只有在初始化完成后才触发搜索
{
Task.Run(async () => await SearchProductsAsync());
}
}
}
// 搜索条件属性
private DateTime? _startDate;
public DateTime? StartDate
private DateTime _endDate;
public DateTime EndDate
{
get { return _startDate; }
set { SetProperty(ref _startDate, value); }
}
private DateTime? _endDate;
public DateTime? EndDate
{
get { return _endDate; }
set { SetProperty(ref _endDate, value); }
get => _endDate;
set
{
SetProperty(ref _endDate, value);
if (_isInitialized) // 只有在初始化完成后才触发搜索
{
Task.Run(async () => await SearchProductsAsync());
}
}
}
private string _selectedCategory;
public string SelectedCategory
{
get { return _selectedCategory; }
set { SetProperty(ref _selectedCategory, value); }
}
private ObservableCollection<string> _categories;
public ObservableCollection<string> Categories
{
get { return _categories; }
set { SetProperty(ref _categories, value); }
}
private ObservableCollection<string> _statusList;
public ObservableCollection<string> StatusList
{
get { return _statusList; }
set { SetProperty(ref _statusList, value); }
get => _selectedCategory;
set
{
SetProperty(ref _selectedCategory, value);
if (_isInitialized) // 只有在初始化完成后才触发搜索
{
Task.Run(async () => await SearchProductsAsync());
}
}
}
private string _selectedStatus;
public string SelectedStatus
{
get { return _selectedStatus; }
set { SetProperty(ref _selectedStatus, value); }
get => _selectedStatus;
set
{
SetProperty(ref _selectedStatus, value);
if (_isInitialized) // 只有在初始化完成后才触发搜索
{
Task.Run(async () => await SearchProductsAsync());
}
}
}
// 命令定义
public ICommand LoadFinishedProductsCommand { get; private set; }
private string _searchText;
public string SearchText
{
get => _searchText;
set => SetProperty(ref _searchText, value);
}
private bool _isLoading;
public bool IsLoading
{
get => _isLoading;
set => SetProperty(ref _isLoading, value);
}
#region
private ObservableCollection<string> _categories;
public ObservableCollection<string> Categories
{
get => _categories;
set => SetProperty(ref _categories, value);
}
private ObservableCollection<string> _statusList;
public ObservableCollection<string> StatusList
{
get => _statusList;
set => SetProperty(ref _statusList, value);
}
#endregion
#region
private int _currentPage = 1;
public int CurrentPage
{
get => _currentPage;
set
{
if (SetProperty(ref _currentPage, value))
{
// 当页码改变时,通知相关属性更新
RaisePropertyChanged(nameof(HasPreviousPage));
RaisePropertyChanged(nameof(HasNextPage));
}
}
}
private int _pageSize = 20;
public int PageSize
{
get => _pageSize;
set => SetProperty(ref _pageSize, value);
}
private int _totalItems;
public int TotalItems
{
get => _totalItems;
set
{
if (SetProperty(ref _totalItems, value))
{
// 当总记录数改变时,重新计算总页数并通知相关属性更新
TotalPages = (int)Math.Ceiling((double)_totalItems / _pageSize);
}
}
}
private int _totalPages;
public int TotalPages
{
get => _totalPages;
set
{
if (SetProperty(ref _totalPages, value))
{
// 当总页数改变时,通知相关属性更新
RaisePropertyChanged(nameof(HasPreviousPage));
RaisePropertyChanged(nameof(HasNextPage));
}
}
}
public bool HasPreviousPage => CurrentPage > 1;
public bool HasNextPage => CurrentPage < TotalPages;
#endregion
#endregion
#region
public ICommand SearchCommand { get; private set; }
public ICommand ResetCommand { get; private set; }
public ICommand RefreshCommand { get; private set; }
public ICommand PreviousPageCommand { get; private set; }
public ICommand NextPageCommand { get; private set; }
public ICommand GoToPageCommand { get; private set; }
public ICommand AddProductCommand { get; private set; }
public ICommand EditProductCommand { get; private set; }
public ICommand DeleteProductCommand { get; private set; }
public ICommand PrintProductCommand { get; private set; }
public ICommand SearchCommand { get; private set; }
#endregion
public MainControlViewModel(
IRegionManager regionManager,
IEventAggregator eventAggregator,
IMessageService messageService,
IPrintService printService,
IFinishedProductService finishedProductService,
IEventAggregator eventAggregator,
IDialogService dialogService
)
: base(regionManager)
{
_printService = printService;
_eventAggregator = eventAggregator;
_finishedProductService = finishedProductService;
_eventAggregator = eventAggregator;
_dialogService = dialogService;
Message = messageService.GetMessage();
// 初始化搜索条件
StatusList = new ObservableCollection<string> { "全部", "已打印", "未打印" };
Categories = new ObservableCollection<string> { "全部", "GP12", "后道", "产线" };
SelectedStatus = "全部"; // 默认选中全部
SelectedCategory = _labelFrom; // 默认选中配置
InitializeCommands();
InitializeData();
// 标记初始化完成
_isInitialized = true;
// 进入系统时默认搜索(延迟执行,确保所有依赖项已初始化)
Task.Run(async () =>
{
await Task.Delay(100); // 短暂延迟确保UI完全加载
await LoadFinishedProductsAsync();
});
}
// 初始化命令
LoadFinishedProductsCommand = new DelegateCommand(async () => await LoadFinishedProductsAsync());
AddProductCommand = new DelegateCommand(AddProduct);
EditProductCommand = new DelegateCommand(EditProduct, CanExecuteEditDeletePrint).ObservesProperty(() => SelectedProduct);
DeleteProductCommand = new DelegateCommand(async () => await DeleteProductAsync(), CanExecuteEditDeletePrint).ObservesProperty(() => SelectedProduct);
PrintProductCommand = new DelegateCommand(async () => await PrintProductAsync(), CanExecuteEditDeletePrint).ObservesProperty(() => SelectedProduct);
private void InitializeCommands()
{
SearchCommand = new DelegateCommand(async () => await SearchProductsAsync());
ResetCommand = new DelegateCommand(ResetSearchCriteria);
RefreshCommand = new DelegateCommand(async () => await LoadFinishedProductsAsync());
PreviousPageCommand = new DelegateCommand(async () => await GoToPageAsync(CurrentPage - 1), () => HasPreviousPage);
NextPageCommand = new DelegateCommand(async () => await GoToPageAsync(CurrentPage + 1), () => HasNextPage);
GoToPageCommand = new DelegateCommand(async () => await GoToPageAsync(CurrentPage));
AddProductCommand = new DelegateCommand(AddProduct);
EditProductCommand = new DelegateCommand<ProFinishedProductReceipt>(EditProduct);
DeleteProductCommand = new DelegateCommand<ProFinishedProductReceipt>(DeleteProduct);
PrintProductCommand = new DelegateCommand<ProFinishedProductReceipt>(PrintProduct);
// 安全地设置默认值避免PrintConfigs.Current为null时的空引用异常
SelectedCategory = PrintConfigs.Current?.LabelFrom ?? "全部";
SelectedStatus = "未打印";
}
public override void OnNavigatedTo(NavigationContext navigationContext)
private void InitializeData()
{
// 页面加载时获取数据
LoadFinishedProductsCommand.Execute(null);
}
private async System.Threading.Tasks.Task LoadFinishedProductsAsync()
{
FinishedProductQueryDto query = new FinishedProductQueryDto
StartDate = DateTime.Today;
EndDate = DateTime.Today;
QueryDto = new FinishedProductQueryDto
{
StartTime = _startDate,
EndTime = _endDate,
LabelFrom = SelectedCategory,
LabelPrintStatus = SelectedStatus
StartTime = StartDate,
EndTime = EndDate,
PageNum = CurrentPage,
PageSize = PageSize
};
// 初始化类别列表
Categories = new ObservableCollection<string>
{
"全部",
"GP12",
"后道",
"产线"
};
// 初始化状态列表
StatusList = new ObservableCollection<string>
{
"全部",
"未打印",
"已打印"
};
FinishedProducts = (List<ProFinishedProductReceipt>)await _finishedProductService.GetFinishedProductsAsync(query);
}
private async System.Threading.Tasks.Task SearchProductsAsync()
private async Task LoadFinishedProductsAsync()
{
FinishedProductQueryDto query = new FinishedProductQueryDto
IsLoading = true;
try
{
StartTime = _startDate,
EndTime = _endDate,
LabelFrom = SelectedCategory,
LabelPrintStatus = SelectedStatus
};
// 获取所有产品
var allProducts = (List<ProFinishedProductReceipt>)await _finishedProductService.GetFinishedProductsAsync(query);
// 更新查询条件
QueryDto.StartTime = StartDate;
QueryDto.EndTime = EndDate;
QueryDto.LabelFrom = SelectedCategory;
QueryDto.LabelPrintStatus = SelectedStatus;
QueryDto.PageNum = CurrentPage;
QueryDto.PageSize = PageSize;
var pagedResult = await _finishedProductService.GetFinishedProductsPagedAsync(QueryDto);
FinishedProducts = new ObservableCollection<ProFinishedProductReceipt>(pagedResult.Result);
TotalItems = pagedResult.TotalNum;
// 确保当前页码在有效范围内
if (CurrentPage > TotalPages && TotalPages > 0)
{
CurrentPage = TotalPages;
await LoadFinishedProductsAsync(); // 重新加载正确页码的数据
return;
}
// 显式刷新命令的可执行状态 - 确保按钮状态正确更新
((DelegateCommand)PreviousPageCommand).RaiseCanExecuteChanged();
((DelegateCommand)NextPageCommand).RaiseCanExecuteChanged();
}
catch (Exception ex)
{
_eventAggregator.GetEvent<SystemLogEvent>().Publish($"加载成品入库单失败: {ex.Message}");
FinishedProducts = new ObservableCollection<ProFinishedProductReceipt>();
TotalItems = 0;
// TotalPages 现在会在 TotalItems 设置为 0 时自动计算为 0
CurrentPage = 1;
// 异常情况下也要刷新命令状态
((DelegateCommand)PreviousPageCommand).RaiseCanExecuteChanged();
((DelegateCommand)NextPageCommand).RaiseCanExecuteChanged();
}
finally
{
IsLoading = false;
}
}
private async Task SearchProductsAsync()
{
CurrentPage = 1; // 搜索时重置到第一页
// 应用搜索条件
var filteredProducts = allProducts.AsEnumerable();
// 更新查询条件
QueryDto.StartTime = StartDate;
QueryDto.EndTime = EndDate;
QueryDto.LabelFrom = SelectedCategory;
QueryDto.LabelPrintStatus = SelectedStatus;
QueryDto.PageNum = CurrentPage;
QueryDto.PageSize = PageSize;
// 状态过滤
//if (!string.IsNullOrEmpty(SelectedStatus) && SelectedStatus != "全部")
//{
//filteredProducts = filteredProducts.Where(p => p.LabelPrintStatus == SelectedStatus);
//}
FinishedProducts = filteredProducts.ToList();
await LoadFinishedProductsAsync();
}
private void ResetSearchCriteria()
{
StartDate = DateTime.Today;
EndDate = DateTime.Today;
SelectedCategory = null;
SelectedStatus = null;
SearchText = string.Empty;
CurrentPage = 1;
}
private async Task GoToPageAsync(int page)
{
if (page >= 1 && page <= TotalPages)
{
CurrentPage = page;
await LoadFinishedProductsAsync();
}
}
private void AddProduct()
{
var parameters = new DialogParameters();
_dialogService.ShowDialog("AddProductDialog", parameters, async r =>
_dialogService.ShowDialog("AddProductDialog", new DialogParameters(), async result =>
{
if (r.Result == ButtonResult.OK)
if (result.Result == ButtonResult.OK)
{
// 重新加载产品列表
await LoadFinishedProductsAsync();
}
});
}
private void EditProduct()
private void EditProduct(ProFinishedProductReceipt product)
{
var parameters = new DialogParameters();
parameters.Add("Product", SelectedProduct);
_dialogService.ShowDialog("EditProductDialog", parameters, async r =>
if (product == null) return;
var parameters = new DialogParameters { { "Product", product } };
_dialogService.ShowDialog("EditProductDialog", parameters, async result =>
{
if (r.Result == ButtonResult.OK)
if (result.Result == ButtonResult.OK)
{
// 重新加载产品列表
await LoadFinishedProductsAsync();
}
});
}
private async System.Threading.Tasks.Task DeleteProductAsync()
private void DeleteProduct(ProFinishedProductReceipt product)
{
var parameters = new DialogParameters();
parameters.Add("Product", SelectedProduct);
parameters.Add("Message", "确定要删除选中的产品吗?");
_dialogService.ShowDialog("DeleteConfirmDialog", parameters, async r =>
if (product == null) return;
var parameters = new DialogParameters { { "Product", product } };
_dialogService.ShowDialog("DeleteConfirmDialog", parameters, async result =>
{
if (r.Result == ButtonResult.OK)
if (result.Result == ButtonResult.OK)
{
// 重新加载产品列表
await LoadFinishedProductsAsync();
}
});
}
private async System.Threading.Tasks.Task PrintProductAsync()
private void PrintProduct(ProFinishedProductReceipt product)
{
var parameters = new DialogParameters();
parameters.Add("Product", SelectedProduct);
_dialogService.ShowDialog("PrintPreviewDialog", parameters, async r =>
if (product == null) return;
var parameters = new DialogParameters { { "Product", product } };
_dialogService.ShowDialog("PrintPreviewDialog", parameters, async result =>
{
if (r.Result == ButtonResult.OK)
if (result.Result == ButtonResult.OK)
{
// 打印逻辑已在弹窗中处理
// 重新加载产品列表
await LoadFinishedProductsAsync();
}
});
}
private bool CanExecuteEditDeletePrint()
{
return SelectedProduct != null;
}
}
}

View File

@ -18,6 +18,13 @@ namespace RIZO_Application.Modules.ModuleName.ViewModels
set { SetProperty(ref _product, value); }
}
private string _printStatus;
public string PrintStatus
{
get { return _printStatus; }
set { SetProperty(ref _printStatus, value); }
}
public string Title { get; private set; } = "打印预览";
public event System.Action<IDialogResult> RequestClose;
@ -28,23 +35,24 @@ namespace RIZO_Application.Modules.ModuleName.ViewModels
public PrintPreviewDialogViewModel(IFinishedProductService finishedProductService)
{
_finishedProductService = finishedProductService;
PrintCommand = new DelegateCommand(async () => await PrintProductAsync());
CloseCommand = new DelegateCommand(CloseDialog);
PrintCommand = new DelegateCommand(async () => await PrintAsync());
CloseCommand = new DelegateCommand(Close);
}
private async System.Threading.Tasks.Task PrintProductAsync()
private async System.Threading.Tasks.Task PrintAsync()
{
if (Product != null)
PrintStatus = "正在打印...";
var success = await _finishedProductService.PrintFinishedProductAsync(Product.ReceiptNo);
PrintStatus = success ? "打印成功" : "打印失败";
if (success)
{
var success = await _finishedProductService.PrintFinishedProductAsync(Product.ReceiptNo);
if (success)
{
RequestClose?.Invoke(new DialogResult(ButtonResult.OK));
}
var result = new DialogResult(ButtonResult.OK, new DialogParameters { { "Product", Product } });
RequestClose?.Invoke(result);
}
}
private void CloseDialog()
private void Close()
{
RequestClose?.Invoke(new DialogResult(ButtonResult.Cancel));
}
@ -63,6 +71,7 @@ namespace RIZO_Application.Modules.ModuleName.ViewModels
if (parameters.ContainsKey("Product"))
{
Product = parameters.GetValue<ProFinishedProductReceipt>("Product");
PrintStatus = "准备打印";
}
}
}

View File

@ -17,96 +17,132 @@
<StackPanel Orientation="Vertical" Margin="8">
<GroupBox Width="Auto" HorizontalAlignment="Stretch" Header="成品入库打印清单"
Padding="10" Margin="16">
<ContentControl>
<StackPanel>
<!-- 顶部按钮栏 -->
<StackPanel Orientation="Horizontal" Margin="0,0,0,10">
<Button Content="增加" Command="{Binding AddProductCommand}"
Margin="0,0,10,0" Padding="8,4" >
<Button.ToolTip>
<ToolTip>增加新的成品入库单</ToolTip>
</Button.ToolTip>
</Button>
</StackPanel>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- 搜索条件 -->
<StackPanel Orientation="Horizontal" Margin="0,0,0,15" VerticalAlignment="Center">
<TextBlock Text="日期区间:" Margin="0,0,5,0" VerticalAlignment="Center"/>
<DatePicker SelectedDate="{Binding StartDate}" Margin="0,0,5,0" Width="150"/>
<TextBlock Text="至" Margin="5,0,5,0" VerticalAlignment="Center"/>
<DatePicker SelectedDate="{Binding EndDate}" Margin="0,0,15,0" Width="150"/>
<TextBlock Text="类别:" Margin="0,0,5,0" VerticalAlignment="Center"/>
<ComboBox ItemsSource="{Binding Categories}" SelectedItem="{Binding SelectedCategory}"
Margin="0,0,15,0" Width="120"/>
<TextBlock Text="状态:" Margin="0,0,5,0" VerticalAlignment="Center"/>
<ComboBox ItemsSource="{Binding StatusList}" SelectedItem="{Binding SelectedStatus}"
Margin="0,0,15,0" Width="100"/>
<Button Content="搜索" Command="{Binding SearchCommand}" Padding="8,4" Width="80"/>
</StackPanel>
<!-- 数据表格 -->
<DataGrid ItemsSource="{Binding FinishedProducts}"
SelectedItem="{Binding SelectedProduct}"
AutoGenerateColumns="False"
CanUserAddRows="False"
IsReadOnly="False"
SelectionMode="Single"
SelectionUnit="FullRow"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<DataGrid.Columns>
<!-- 工单信息列 -->
<DataGridTextColumn Header="入库单号" Binding="{Binding ReceiptNo}" Width="160" />
<DataGridTextColumn Header="产线工单号" Binding="{Binding WorkOrder}" Width="120" />
<DataGridTextColumn Header="产品名称" Binding="{Binding Description}" Width="150" />
<DataGridTextColumn Header="产品编码" Binding="{Binding PartNumber}" Width="120" />
<DataGridTextColumn Header="箱数" Binding="{Binding PackageCount}" Width="80" />
<DataGridTextColumn Header="产品数" Binding="{Binding PackageNum}" Width="80" />
<DataGridTextColumn Header="批次号" Binding="{Binding BatchCode}" Width="120" />
<DataGridTextColumn Header="仓库位置" Binding="{Binding WarehouseCode}" Width="120" />
<DataGridTextColumn Header="操作人" Binding="{Binding CreatedBy}" Width="100" />
<DataGridTemplateColumn Header="状态" Width="120">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Border Background="{Binding LabelPrintStatus, Converter={StaticResource StatusToColorConverter}}"
CornerRadius="12"
Padding="8,4"
HorizontalAlignment="Center">
<TextBlock Text="{Binding LabelPrintStatus}"
Foreground="White"
FontWeight="Bold"
HorizontalAlignment="Center"/>
</Border>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="备注" Binding="{Binding Remark}" Width="*" />
<!-- 操作按钮列 -->
<DataGridTemplateColumn Header="操作" Width="240">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Button Content="修改" Command="{Binding DataContext.EditProductCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}"
Margin="0,0,5,0" Padding="6,2" Width="60">
</Button>
<Button Content="删除" Command="{Binding DataContext.DeleteProductCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}"
Margin="0,0,5,0" Padding="6,2" Width="60" Background="#FFE53935" Foreground="White">
</Button>
<Button Content="打印" Command="{Binding DataContext.PrintProductCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}"
Padding="6,2" Width="60" Background="#FF4CAF50" Foreground="White">
</Button>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<!-- 顶部按钮栏 -->
<StackPanel Grid.Row="0" Orientation="Horizontal" Margin="0,0,0,10">
<Button Content="增加" Command="{Binding AddProductCommand}"
Margin="0,0,10,0" Padding="8,4" >
<Button.ToolTip>
<ToolTip>增加新的成品入库单</ToolTip>
</Button.ToolTip>
</Button>
</StackPanel>
</ContentControl>
<!-- 搜索条件 -->
<StackPanel Grid.Row="1" Orientation="Horizontal" Margin="0,0,0,15" VerticalAlignment="Center">
<TextBlock Text="日期区间:" Margin="0,0,5,0" VerticalAlignment="Center"/>
<DatePicker SelectedDate="{Binding StartDate}" Margin="0,0,5,0" Width="150"/>
<TextBlock Text="至" Margin="5,0,5,0" VerticalAlignment="Center"/>
<DatePicker SelectedDate="{Binding EndDate}" Margin="0,0,15,0" Width="150"/>
<TextBlock Text="类别:" Margin="0,0,5,0" VerticalAlignment="Center"/>
<ComboBox ItemsSource="{Binding Categories}" SelectedItem="{Binding SelectedCategory}"
Margin="0,0,15,0" Width="120"/>
<TextBlock Text="状态:" Margin="0,0,5,0" VerticalAlignment="Center"/>
<ComboBox ItemsSource="{Binding StatusList}" SelectedItem="{Binding SelectedStatus}"
Margin="0,0,15,0" Width="100"/>
<Button Content="搜索" Command="{Binding SearchCommand}" Padding="8,4" Width="80"/>
</StackPanel>
<!-- 数据表格 -->
<DataGrid Grid.Row="2" ItemsSource="{Binding FinishedProducts}"
SelectedItem="{Binding SelectedProduct}"
AutoGenerateColumns="False"
CanUserAddRows="False"
IsReadOnly="False"
SelectionMode="Single"
SelectionUnit="FullRow"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
MinHeight="400"
MaxHeight="550">
<DataGrid.Columns>
<!-- 工单信息列 -->
<DataGridTextColumn Header="入库单号" Binding="{Binding ReceiptNo}" Width="160" />
<DataGridTextColumn Header="产线工单号" Binding="{Binding WorkOrder}" Width="120" />
<DataGridTextColumn Header="产品名称" Binding="{Binding Description}" Width="150" />
<DataGridTextColumn Header="产品编码" Binding="{Binding PartNumber}" Width="120" />
<DataGridTextColumn Header="箱数" Binding="{Binding PackageCount}" Width="80" />
<DataGridTextColumn Header="产品数" Binding="{Binding PackageNum}" Width="80" />
<DataGridTextColumn Header="批次号" Binding="{Binding BatchCode}" Width="120" />
<DataGridTextColumn Header="仓库位置" Binding="{Binding WarehouseCode}" Width="120" />
<DataGridTextColumn Header="操作人" Binding="{Binding CreatedBy}" Width="100" />
<DataGridTemplateColumn Header="状态" Width="120">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Border Background="{Binding LabelPrintStatus, Converter={StaticResource StatusToColorConverter}}"
CornerRadius="12"
Padding="8,4"
HorizontalAlignment="Center">
<TextBlock Text="{Binding LabelPrintStatus}"
Foreground="White"
FontWeight="Bold"
HorizontalAlignment="Center"/>
</Border>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="备注" Binding="{Binding Remark}" Width="*" />
<!-- 操作按钮列 -->
<DataGridTemplateColumn Header="操作" Width="240">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Button Content="修改" Command="{Binding DataContext.EditProductCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}"
CommandParameter="{Binding}"
Margin="0,0,5,0" Padding="6,2" Width="60">
</Button>
<Button Content="删除" Command="{Binding DataContext.DeleteProductCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}"
CommandParameter="{Binding}"
Margin="0,0,5,0" Padding="6,2" Width="60" Background="#FFE53935" Foreground="White">
</Button>
<Button Content="打印" Command="{Binding DataContext.PrintProductCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}"
CommandParameter="{Binding}"
Padding="6,2" Width="60" Background="#FF4CAF50" Foreground="White">
</Button>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<!-- 分页控件 -->
<StackPanel Grid.Row="3" Orientation="Horizontal" Margin="0,10,0,0" HorizontalAlignment="Center">
<Button Content="上一页" Command="{Binding PreviousPageCommand}"
Margin="0,0,5,0" Padding="8,4" Width="80"/>
<TextBlock Text="第" Margin="10,0,5,0" VerticalAlignment="Center"/>
<TextBox Text="{Binding CurrentPage, UpdateSourceTrigger=PropertyChanged}"
Margin="0,0,5,0" Width="40" HorizontalContentAlignment="Center"
VerticalAlignment="Center"/>
<TextBlock Text="页" Margin="0,0,10,0" VerticalAlignment="Center"/>
<TextBlock Text="共" Margin="0,0,5,0" VerticalAlignment="Center"/>
<TextBlock Text="{Binding TotalPages}" Margin="0,0,5,0" VerticalAlignment="Center"/>
<TextBlock Text="页" Margin="0,0,10,0" VerticalAlignment="Center"/>
<TextBlock Text="共" Margin="10,0,5,0" VerticalAlignment="Center"/>
<TextBlock Text="{Binding TotalItems}" Margin="0,0,5,0" VerticalAlignment="Center"/>
<TextBlock Text="条记录" Margin="0,0,15,0" VerticalAlignment="Center"/>
<Button Content="下一页" Command="{Binding NextPageCommand}"
Margin="0,0,5,0" Padding="8,4" Width="80"/>
<Button Content="跳转" Command="{Binding GoToPageCommand}"
Margin="10,0,0,0" Padding="8,4" Width="60"/>
</StackPanel>
</Grid>
</GroupBox>
</StackPanel>
</UserControl>