# 包装商城 - 轻量级订单发货客户端技术方案 > **创建日期**: 2025-12-17 > **更新日期**: 2025-12-17 > **项目名称**: 包装商城发货助手 > **项目定位**: 面向子账号管理员的轻量级桌面客户端,专注订单发货流程 > **开发策略**: 并行开发(当前项目补充发货API + 独立客户端) --- ## 一、项目概述 ### 1.1 背景 包装商城管理系统(Web端)已具备完整的订单同步、查询、导出功能,但**缺少发货功能**。一线发货人员需要: - 快速查看待发货订单 - 批量填写快递单号并发货 - Excel导出/导入发货数据 - 离线环境下也能操作 ### 1.2 目标用户 - **子账号管理员**:各分公司/门店的发货专员 - **使用场景**:日常发货操作、批量处理、数据导出 ### 1.3 核心功能 | 功能模块 | 描述 | 优先级 | |---------|------|:------:| | 子账号登录 | API工厂认证 + 本地会话 | P0 | | 订单列表 | 本地缓存 + 增量同步 | P0 | | 单个发货 | 填写快递单号发货 | P0 | | 批量发货 | 多订单同时发货 | P0 | | Excel导出 | 导出待发货订单 | P1 | | Excel导入 | 导入快递单号批量发货 | P1 | | 离线操作 | 本地SQLite支持 | P2 | --- ## 二、技术选型 ### 2.1 技术栈 | 层级 | 选型 | 版本 | 理由 | |-----|------|------|------| | **桌面框架** | WPF | .NET Framework 4.8 | Win7原生支持、性能极佳、微软官方维护 | | **开发语言** | C# | 7.3 | 强类型、性能优秀、生态成熟 | | **UI风格** | Modern WPF | MaterialDesign/MahApps | 现代Windows风格 | | **架构模式** | MVVM | CommunityToolkit.Mvvm | 解耦视图与逻辑 | | **本地数据库** | SQLite | System.Data.SQLite | 零配置、单文件、高性能 | | **Excel处理** | ClosedXML | 0.102.x | 功能完整、无COM依赖 | | **HTTP客户端** | HttpClient | 内置 | 原生支持、异步友好 | | **JSON处理** | Newtonsoft.Json | 13.x | 功能强大、兼容性好 | ### 2.2 为什么选择 WPF + .NET Framework 4.8? ``` ✅ Win7原生支持 - Windows 7 SP1 已内置 .NET Framework 4.8,无需安装运行时 ✅ 性能极佳 - 原生编译,启动时间 <1秒 ✅ 内存占用低 - ~50MB(vs Electron ~200MB) ✅ 包体极小 - ~5MB(vs Electron ~150MB) ✅ 微软官方维护 - 长期支持,稳定可靠 ✅ XAML布局 - 声明式UI,易于维护 ✅ 开发工具成熟 - Visual Studio 2019 完美支持 ✅ AI友好 - C#/WPF 是 AI 非常擅长的技术栈 ``` ### 2.3 为什么选择 SQLite? ``` ✅ 零配置 - 无需安装数据库服务,开箱即用 ✅ 单文件 - 数据库即文件,便于备份和迁移 ✅ 高性能 - 本地读写,10万+订单秒级查询 ✅ 离线支持 - 无网络时仍可查看缓存数据 ✅ 跨平台 - Windows/Mac/Linux 通用 ✅ 嵌入式 - 随应用打包,无额外依赖 ``` ### 2.4 与当前Web项目的关系 ``` ┌─────────────────────────────────────────────────────────────┐ │ API工厂 (远程) │ │ user.api.it120.cc / common.apifm.com │ └────────────────────────┬────────────────────────────────────┘ │ ┌───────────────┼───────────────┐ │ │ │ ▼ ▼ ▼ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ 当前Web项目 │ │ 轻量级客户端 │ │ 其他客户端 │ │ (管理后台) │ │ (发货专用) │ │ (未来) │ │ │ │ │ │ │ │ MySQL本地缓存│ │ SQLite本地 │ │ ... │ └─────────────┘ └─────────────┘ └─────────────┘ ``` **共用API工厂接口,数据一致性由API工厂保证。** --- ## 三、系统架构 ### 3.1 整体架构(WPF MVVM) ``` ┌─────────────────────────────────────────────────────────────┐ │ 桌面客户端 (WPF + .NET Framework 4.8) │ ├─────────────────────────────────────────────────────────────┤ │ 视图层 (Views/XAML) │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ LoginWindow │ │OrderListView│ │ShippingView │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ ├─────────────────────────────────────────────────────────────┤ │ 视图模型层 (ViewModels) │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ LoginVM │ │ OrderListVM │ │ ShippingVM │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ ├─────────────────────────────────────────────────────────────┤ │ 服务层 (Services) │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ AuthService │ │ OrderService│ │ ShipService │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ ┌─────────────┐ ┌─────────────┐ │ │ │ SyncService │ │ExcelService │ │ │ └─────────────┘ └─────────────┘ │ ├─────────────────────────────────────────────────────────────┤ │ 数据访问层 │ │ ┌─────────────────────┐ ┌─────────────────────┐ │ │ │ SQLite │ │ ApiFactoryClient │ │ │ │ (System.Data.SQLite)│ │ 远程API调用 │ │ │ └─────────────────────┘ └─────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ ``` ### 3.2 MVVM数据绑定 ```csharp // ViewModel -> View 数据绑定示例 // 使用 CommunityToolkit.Mvvm (兼容 .NET Framework 4.8) using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using System.Collections.ObjectModel; using System.Threading.Tasks; public partial class OrderListViewModel : ObservableObject { private readonly IOrderService _orderService; private readonly IShipService _shipService; [ObservableProperty] private ObservableCollection _orders = new ObservableCollection(); [ObservableProperty] private bool _isLoading; [ObservableProperty] private string _searchText = ""; [ObservableProperty] private int _selectedStatus = 1; // 默认待发货 public OrderListViewModel(IOrderService orderService, IShipService shipService) { _orderService = orderService; _shipService = shipService; } [RelayCommand] private async Task RefreshOrdersAsync() { IsLoading = true; try { var result = await _orderService.GetOrdersAsync(SelectedStatus, SearchText); Orders.Clear(); foreach (var order in result) { Orders.Add(order); } } finally { IsLoading = false; } } [RelayCommand] private async Task ShipOrderAsync(Order order) { if (order == null) return; var dialog = new ShippingDialog(order); if (dialog.ShowDialog() == true) { await _shipService.ShipOrderAsync(new ShipOrderRequest { OrderId = order.Id, ExpressCompanyId = dialog.SelectedExpressId, TrackingNumber = dialog.TrackingNumber }); await RefreshOrdersAsync(); } } } ``` ### 3.3 XAML视图示例 ```xml