feat: 适配供应商发货接口并支持单订单发货
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
<appSettings>
|
||||
<!-- API工厂配置 -->
|
||||
<add key="ApiBaseUrl" value="https://api.it120.cc" />
|
||||
<add key="CommonApiBaseUrl" value="https://common.apifm.com" />
|
||||
<add key="SubDomain" value="let5see" />
|
||||
|
||||
<!-- 同步配置 -->
|
||||
|
||||
@@ -7,6 +7,9 @@ namespace PackagingMallShipper.Helpers
|
||||
public static string ApiBaseUrl =>
|
||||
ConfigurationManager.AppSettings["ApiBaseUrl"] ?? "https://user.api.it120.cc";
|
||||
|
||||
public static string CommonApiBaseUrl =>
|
||||
ConfigurationManager.AppSettings["CommonApiBaseUrl"] ?? "https://common.apifm.com";
|
||||
|
||||
public static string SubDomain =>
|
||||
ConfigurationManager.AppSettings["SubDomain"] ?? "vv125s";
|
||||
|
||||
@@ -23,5 +26,10 @@ namespace PackagingMallShipper.Helpers
|
||||
{
|
||||
return $"{ApiBaseUrl}/{SubDomain}{endpoint}";
|
||||
}
|
||||
|
||||
public static string GetCommonApiUrl(string endpoint)
|
||||
{
|
||||
return $"{CommonApiBaseUrl}{endpoint}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.SQLite;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
@@ -22,37 +23,38 @@ namespace PackagingMallShipper.Services
|
||||
public ShipService(IAuthService authService)
|
||||
{
|
||||
_authService = authService;
|
||||
_httpClient = new HttpClient();
|
||||
_httpClient.Timeout = TimeSpan.FromSeconds(30);
|
||||
_httpClient = new HttpClient
|
||||
{
|
||||
Timeout = TimeSpan.FromSeconds(30)
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<ShipResult> ShipOrderAsync(ShipOrderRequest request)
|
||||
{
|
||||
var token = _authService.GetToken();
|
||||
if (string.IsNullOrEmpty(token))
|
||||
throw new UnauthorizedAccessException("未登录");
|
||||
throw new UnauthorizedAccessException("未登录,请先登录");
|
||||
|
||||
UpdateLocalOrderStatus(request.OrderId, "shipping");
|
||||
|
||||
try
|
||||
{
|
||||
var url = AppConfig.GetApiUrl($"/order/delivery") +
|
||||
$"?orderId={request.OrderId}" +
|
||||
$"&expressType={request.ExpressCompanyId}" +
|
||||
$"&shipperCode={Uri.EscapeDataString(request.TrackingNumber)}";
|
||||
var query = $"?id={request.OrderId}" +
|
||||
$"&expressCompanyId={request.ExpressCompanyId}" +
|
||||
$"&number={Uri.EscapeDataString(request.TrackingNumber)}";
|
||||
|
||||
var url = AppConfig.GetCommonApiUrl("/apifmUser/fsmRepair/fahuo") + query;
|
||||
|
||||
_httpClient.DefaultRequestHeaders.Clear();
|
||||
_httpClient.DefaultRequestHeaders.Add("X-Token", token);
|
||||
|
||||
var response = await _httpClient.PostAsync(url, null);
|
||||
var json = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<ApiResponse<object>>(json);
|
||||
Debug.WriteLine($"[发货请求] URL: {url}");
|
||||
var result = await PostShipRequestAsync(url);
|
||||
|
||||
if (result?.Code != 0)
|
||||
throw new Exception(result?.Msg ?? "发货失败");
|
||||
|
||||
UpdateLocalOrderAfterShip(request);
|
||||
|
||||
return new ShipResult { Success = true };
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -73,7 +75,7 @@ namespace PackagingMallShipper.Services
|
||||
Results = new List<ShipOrderResult>()
|
||||
};
|
||||
|
||||
int completed = 0;
|
||||
var completed = 0;
|
||||
|
||||
using (var semaphore = new SemaphoreSlim(concurrency))
|
||||
{
|
||||
@@ -130,6 +132,15 @@ namespace PackagingMallShipper.Services
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<ApiResponse<object>> PostShipRequestAsync(string url)
|
||||
{
|
||||
var response = await _httpClient.PostAsync(url, null);
|
||||
var json = await response.Content.ReadAsStringAsync();
|
||||
Debug.WriteLine($"[发货响应] URL: {url}");
|
||||
Debug.WriteLine($"[发货响应] HTTP: {response.StatusCode}, body: {json}");
|
||||
return JsonConvert.DeserializeObject<ApiResponse<object>>(json);
|
||||
}
|
||||
|
||||
private void UpdateLocalOrderStatus(int orderId, string status, string errorMsg = null)
|
||||
{
|
||||
using (var conn = SqliteHelper.GetConnection())
|
||||
@@ -165,8 +176,7 @@ namespace PackagingMallShipper.Services
|
||||
using (var cmd = new SQLiteCommand(sql, conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@expressId", request.ExpressCompanyId);
|
||||
cmd.Parameters.AddWithValue("@expressName",
|
||||
ExpressCompanies.GetName(request.ExpressCompanyId));
|
||||
cmd.Parameters.AddWithValue("@expressName", ExpressCompanies.GetName(request.ExpressCompanyId));
|
||||
cmd.Parameters.AddWithValue("@trackingNumber", request.TrackingNumber);
|
||||
cmd.Parameters.AddWithValue("@dateShip", DateTime.Now);
|
||||
cmd.Parameters.AddWithValue("@now", DateTime.Now);
|
||||
|
||||
@@ -11,6 +11,7 @@ using Microsoft.Win32;
|
||||
using PackagingMallShipper.Helpers;
|
||||
using PackagingMallShipper.Models;
|
||||
using PackagingMallShipper.Services;
|
||||
using PackagingMallShipper.Views;
|
||||
|
||||
namespace PackagingMallShipper.ViewModels
|
||||
{
|
||||
@@ -633,6 +634,57 @@ namespace PackagingMallShipper.ViewModels
|
||||
"提示", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task ShipSingleOrder(Order order)
|
||||
{
|
||||
if (order == null || order.Status != 1) return;
|
||||
|
||||
var dialog = new ShippingDialog(order);
|
||||
var activeWindow = Application.Current.Windows.OfType<Window>().FirstOrDefault(w => w.IsActive)
|
||||
?? Application.Current.Windows.OfType<Window>().FirstOrDefault(w => w.IsVisible);
|
||||
if (activeWindow != null)
|
||||
dialog.Owner = activeWindow;
|
||||
|
||||
if (dialog.ShowDialog() == true)
|
||||
{
|
||||
IsBusy = true;
|
||||
StatusMessage = $"正在发货 {order.OrderNumber}...";
|
||||
|
||||
try
|
||||
{
|
||||
var request = new ShipOrderRequest
|
||||
{
|
||||
OrderId = order.Id,
|
||||
OrderNumber = order.OrderNumber,
|
||||
ExpressCompanyId = dialog.SelectedExpressId,
|
||||
TrackingNumber = dialog.TrackingNumber
|
||||
};
|
||||
|
||||
var result = await _shipService.ShipOrderAsync(request);
|
||||
if (result.Success)
|
||||
{
|
||||
StatusMessage = $"订单 {order.OrderNumber} 发货成功";
|
||||
await RefreshOrdersAsync();
|
||||
await UpdateCountsAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
StatusMessage = $"发货失败: {result.Message}";
|
||||
MessageBox.Show($"发货失败: {result.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
StatusMessage = $"发货失败: {ex.Message}";
|
||||
MessageBox.Show($"发货失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsBusy = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task UpdateCountsAsync()
|
||||
{
|
||||
try
|
||||
|
||||
@@ -100,12 +100,10 @@
|
||||
Width="90" Height="30" Margin="0,0,5,0"
|
||||
IsEnabled="{Binding IsBusy, Converter={StaticResource InverseBool}}"/>
|
||||
|
||||
<!-- 暂时禁用导入发货功能
|
||||
<Button Content="📥 导入发货" Command="{Binding ImportAndShipCommand}"
|
||||
Width="90" Height="30"
|
||||
Background="#52C41A" Foreground="White" BorderThickness="0"
|
||||
IsEnabled="{Binding IsBusy, Converter={StaticResource InverseBool}}"/>
|
||||
-->
|
||||
</StackPanel>
|
||||
|
||||
<!-- 订单列表 -->
|
||||
@@ -163,6 +161,37 @@
|
||||
Width="70"/>
|
||||
|
||||
<DataGridTextColumn Header="快递单号" Binding="{Binding TrackingNumber}" Width="150"/>
|
||||
|
||||
<DataGridTemplateColumn Header="操作" Width="80">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<Button Content="发货"
|
||||
Command="{Binding DataContext.ShipSingleOrderCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}"
|
||||
CommandParameter="{Binding}"
|
||||
Padding="8,2" Cursor="Hand"
|
||||
Background="#1890FF" Foreground="White" BorderThickness="0">
|
||||
<Button.Style>
|
||||
<Style TargetType="Button">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Status}" Value="2">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Status}" Value="3">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Status}" Value="4">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Status}" Value="-1">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Button.Style>
|
||||
</Button>
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="填写发货信息"
|
||||
Height="280" Width="400"
|
||||
Height="320" Width="400"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
ResizeMode="NoResize"
|
||||
ShowInTaskbar="False">
|
||||
|
||||
Reference in New Issue
Block a user