|
@@ -4,7 +4,7 @@ import { useForm } from 'react-hook-form';
|
|
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
|
import { format } from 'date-fns';
|
|
import { format } from 'date-fns';
|
|
|
import { toast } from 'sonner';
|
|
import { toast } from 'sonner';
|
|
|
-import { Search, Edit, Eye, Package, Truck } from 'lucide-react';
|
|
|
|
|
|
|
+import { Search, Edit, Eye, Package, Truck, Check } from 'lucide-react';
|
|
|
|
|
|
|
|
|
|
|
|
|
// 使用共享UI组件包的具体路径导入
|
|
// 使用共享UI组件包的具体路径导入
|
|
@@ -18,6 +18,16 @@ import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '
|
|
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@d8d/shared-ui-components/components/ui/select';
|
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@d8d/shared-ui-components/components/ui/select';
|
|
|
import { Textarea } from '@d8d/shared-ui-components/components/ui/textarea';
|
|
import { Textarea } from '@d8d/shared-ui-components/components/ui/textarea';
|
|
|
import { Skeleton } from '@d8d/shared-ui-components/components/ui/skeleton';
|
|
import { Skeleton } from '@d8d/shared-ui-components/components/ui/skeleton';
|
|
|
|
|
+import {
|
|
|
|
|
+ Command,
|
|
|
|
|
+ CommandEmpty,
|
|
|
|
|
+ CommandGroup,
|
|
|
|
|
+ CommandInput,
|
|
|
|
|
+ CommandItem,
|
|
|
|
|
+ CommandList,
|
|
|
|
|
+ CommandSeparator,
|
|
|
|
|
+} from '@d8d/shared-ui-components/components/ui/command';
|
|
|
|
|
+import { Popover, PopoverContent, PopoverTrigger } from '@d8d/shared-ui-components/components/ui/popover';
|
|
|
|
|
|
|
|
// 简单分页组件
|
|
// 简单分页组件
|
|
|
const DataTablePagination = ({
|
|
const DataTablePagination = ({
|
|
@@ -89,108 +99,8 @@ type DeliveryRequest = {
|
|
|
};
|
|
};
|
|
|
type DeliveryResponse = any;
|
|
type DeliveryResponse = any;
|
|
|
|
|
|
|
|
-// 微信服务消息通知配置类型 - 参考useShareAppMessage的设计模式
|
|
|
|
|
-interface WechatServiceMessageConfig {
|
|
|
|
|
- openid: string;
|
|
|
|
|
- templateId: string;
|
|
|
|
|
- page?: string;
|
|
|
|
|
- data: Record<string, { value: string }>;
|
|
|
|
|
- miniprogramState?: 'developer' | 'trial' | 'formal';
|
|
|
|
|
- tenantId?: number; // 添加tenantId参数
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// 微信服务消息通知结果类型
|
|
|
|
|
-interface WechatServiceMessageResult {
|
|
|
|
|
- success: boolean;
|
|
|
|
|
- message: string;
|
|
|
|
|
- data?: any;
|
|
|
|
|
- error?: any;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// 微信服务消息通知函数 - 参考useShareAppMessage的简洁设计模式
|
|
|
|
|
-const sendWechatServiceMessage = async (config: WechatServiceMessageConfig): Promise<WechatServiceMessageResult> => {
|
|
|
|
|
- try {
|
|
|
|
|
- console.debug('准备发送微信服务消息:', config);
|
|
|
|
|
-
|
|
|
|
|
- // 调用后端微信API
|
|
|
|
|
- const response = await fetch('/api/v1/auth/send-template-message', {
|
|
|
|
|
- method: 'POST',
|
|
|
|
|
- headers: {
|
|
|
|
|
- 'Content-Type': 'application/json',
|
|
|
|
|
- },
|
|
|
|
|
- body: JSON.stringify({
|
|
|
|
|
- openid: config.openid,
|
|
|
|
|
- templateId: config.templateId,
|
|
|
|
|
- data: config.data,
|
|
|
|
|
- page: config.page || 'pages/index/index',
|
|
|
|
|
- miniprogramState: config.miniprogramState || 'formal',
|
|
|
|
|
- tenantId: config.tenantId
|
|
|
|
|
- }),
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- if (!response.ok) {
|
|
|
|
|
- const errorText = await response.text();
|
|
|
|
|
- console.error('微信服务消息API调用失败:', {
|
|
|
|
|
- status: response.status,
|
|
|
|
|
- statusText: response.statusText,
|
|
|
|
|
- error: errorText
|
|
|
|
|
- });
|
|
|
|
|
- return {
|
|
|
|
|
- success: false,
|
|
|
|
|
- message: `微信服务消息发送失败: ${response.status}`,
|
|
|
|
|
- error: errorText
|
|
|
|
|
- };
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- const result = await response.json();
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- console.debug('微信服务消息发送成功:', result);
|
|
|
|
|
-
|
|
|
|
|
- return {
|
|
|
|
|
- success: true,
|
|
|
|
|
- message: '微信服务消息发送成功',
|
|
|
|
|
- data: result
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- console.error('发送微信服务消息时出错:', error);
|
|
|
|
|
- return {
|
|
|
|
|
- success: false,
|
|
|
|
|
- message: '微信服务消息发送失败',
|
|
|
|
|
- error
|
|
|
|
|
- };
|
|
|
|
|
- }
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-// 格式化微信日期时间
|
|
|
|
|
-const formatWechatDate = (isoDateString: string | null | undefined): string => {
|
|
|
|
|
- try {
|
|
|
|
|
- // 如果日期字符串为空,使用当前时间
|
|
|
|
|
- const date = isoDateString ? new Date(isoDateString) : new Date();
|
|
|
|
|
- // 微信date类型格式:YYYY年MM月DD日 HH:mm
|
|
|
|
|
- const year = date.getFullYear();
|
|
|
|
|
- const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
|
|
|
- const day = String(date.getDate()).padStart(2, '0');
|
|
|
|
|
- const hours = String(date.getHours()).padStart(2, '0');
|
|
|
|
|
- const minutes = String(date.getMinutes()).padStart(2, '0');
|
|
|
|
|
-
|
|
|
|
|
- return `${year}年${month}月${day}日 ${hours}:${minutes}`;
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- console.error('格式化微信日期失败:', error, isoDateString);
|
|
|
|
|
- // 返回当前时间的格式化版本作为备用
|
|
|
|
|
- const now = new Date();
|
|
|
|
|
- const year = now.getFullYear();
|
|
|
|
|
- const month = String(now.getMonth() + 1).padStart(2, '0');
|
|
|
|
|
- const day = String(now.getDate()).padStart(2, '0');
|
|
|
|
|
- const hours = String(now.getHours()).padStart(2, '0');
|
|
|
|
|
- const minutes = String(now.getMinutes()).padStart(2, '0');
|
|
|
|
|
- return `${year}年${month}月${day}日 ${hours}:${minutes}`;
|
|
|
|
|
- }
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-// 获取微信小店快递公司列表
|
|
|
|
|
-const getWechatDeliveryCompanies = async (tenantId?: number): Promise<{ success: boolean; message: string; data?: any }> => {
|
|
|
|
|
|
|
+// 快递公司列表
|
|
|
|
|
+const getWechatDeliveryCompanies = async (tenantId?: number): Promise<{ success: boolean; message: string; data?: any; error?: any }> => {
|
|
|
try {
|
|
try {
|
|
|
console.debug('准备获取微信小店快递公司列表:', { tenantId });
|
|
console.debug('准备获取微信小店快递公司列表:', { tenantId });
|
|
|
|
|
|
|
@@ -254,77 +164,52 @@ const getWechatDeliveryCompanies = async (tenantId?: number): Promise<{ success:
|
|
|
};
|
|
};
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
+
|
|
|
|
|
|
|
|
-// 调用微信小店发货API
|
|
|
|
|
-const sendWechatShopDelivery = async (order: OrderResponse, deliveryData: DeliveryRequest): Promise<{ success: boolean; message: string; data?: any }> => {
|
|
|
|
|
- try {
|
|
|
|
|
- console.debug('准备调用微信小店发货API:', {
|
|
|
|
|
- orderId: order.id,
|
|
|
|
|
- orderNo: order.orderNo,
|
|
|
|
|
- deliveryType: deliveryData.deliveryType,
|
|
|
|
|
- deliveryCompany: deliveryData.deliveryCompany,
|
|
|
|
|
- deliveryNo: deliveryData.deliveryNo,
|
|
|
|
|
- tenantId: order.tenantId
|
|
|
|
|
- });
|
|
|
|
|
|
|
+// 生成商品描述信息,截取110个字
|
|
|
|
|
+const generateItemDesc = (order: OrderResponse): string => {
|
|
|
|
|
+ if (!order.orderGoods || order.orderGoods.length === 0) {
|
|
|
|
|
+ return '商品信息';
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // 调用后端微信小店发货API
|
|
|
|
|
- const response = await fetch('/api/v1/auth/send-wechat-shop-delivery', {
|
|
|
|
|
- method: 'POST',
|
|
|
|
|
- headers: {
|
|
|
|
|
- 'Content-Type': 'application/json',
|
|
|
|
|
- },
|
|
|
|
|
- body: JSON.stringify({
|
|
|
|
|
- orderId: order.id,
|
|
|
|
|
- orderNo: order.orderNo,
|
|
|
|
|
- deliveryType: deliveryData.deliveryType,
|
|
|
|
|
- deliveryCompany: deliveryData.deliveryCompany || null,
|
|
|
|
|
- deliveryNo: deliveryData.deliveryNo || null,
|
|
|
|
|
- tenantId: order.tenantId
|
|
|
|
|
- }),
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ // 构建商品描述:商品1名称×数量, 商品2名称×数量, ...
|
|
|
|
|
+ const itemDescriptions = order.orderGoods.map(item => {
|
|
|
|
|
+ return `${item.goodsName}×${item.num}`;
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
- if (!response.ok) {
|
|
|
|
|
- const errorText = await response.text();
|
|
|
|
|
- console.error('微信小店发货API调用失败:', {
|
|
|
|
|
- status: response.status,
|
|
|
|
|
- statusText: response.statusText,
|
|
|
|
|
- error: errorText
|
|
|
|
|
- });
|
|
|
|
|
- return {
|
|
|
|
|
- success: false,
|
|
|
|
|
- message: `微信小店发货失败: ${response.status}`,
|
|
|
|
|
- error: errorText
|
|
|
|
|
- };
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ let itemDesc = itemDescriptions.join(', ');
|
|
|
|
|
|
|
|
- const result = await response.json();
|
|
|
|
|
- console.debug('微信小店发货成功:', result);
|
|
|
|
|
|
|
+ // 截取110个字(中文字符)
|
|
|
|
|
+ if (itemDesc.length > 110) {
|
|
|
|
|
+ itemDesc = itemDesc.substring(0, 110) + '...';
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- return {
|
|
|
|
|
- success: true,
|
|
|
|
|
- message: '微信小店发货成功',
|
|
|
|
|
- data: result
|
|
|
|
|
- };
|
|
|
|
|
|
|
+ console.debug('生成的商品描述:', {
|
|
|
|
|
+ originalLength: itemDescriptions.join(', ').length,
|
|
|
|
|
+ truncatedLength: itemDesc.length,
|
|
|
|
|
+ itemDesc
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- console.error('调用微信小店发货API时出错:', error);
|
|
|
|
|
- return {
|
|
|
|
|
- success: false,
|
|
|
|
|
- message: '微信小店发货失败',
|
|
|
|
|
- error
|
|
|
|
|
- };
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ return itemDesc;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
// 调用微信小程序发货信息录入API
|
|
// 调用微信小程序发货信息录入API
|
|
|
-const uploadShippingInfoToWechat = async (order: OrderResponse, deliveryData: DeliveryRequest, tenantId?: number): Promise<{ success: boolean; message: string; data?: any }> => {
|
|
|
|
|
|
|
+const uploadShippingInfoToWechat = async (
|
|
|
|
|
+ order: OrderResponse,
|
|
|
|
|
+ deliveryData: DeliveryRequest,
|
|
|
|
|
+ tenantId?: number
|
|
|
|
|
+): Promise<{ success: boolean; message: string; data?: any; error?: any }> => {
|
|
|
try {
|
|
try {
|
|
|
|
|
+ // 生成商品描述
|
|
|
|
|
+ const itemDesc = generateItemDesc(order);
|
|
|
|
|
+
|
|
|
console.debug('准备调用微信小程序发货信息录入API:', {
|
|
console.debug('准备调用微信小程序发货信息录入API:', {
|
|
|
orderId: order.id,
|
|
orderId: order.id,
|
|
|
orderNo: order.orderNo,
|
|
orderNo: order.orderNo,
|
|
|
deliveryType: deliveryData.deliveryType,
|
|
deliveryType: deliveryData.deliveryType,
|
|
|
deliveryCompany: deliveryData.deliveryCompany,
|
|
deliveryCompany: deliveryData.deliveryCompany,
|
|
|
deliveryNo: deliveryData.deliveryNo,
|
|
deliveryNo: deliveryData.deliveryNo,
|
|
|
|
|
+ itemDesc,
|
|
|
tenantId: tenantId || order.tenantId
|
|
tenantId: tenantId || order.tenantId
|
|
|
});
|
|
});
|
|
|
|
|
|
|
@@ -335,12 +220,15 @@ const uploadShippingInfoToWechat = async (order: OrderResponse, deliveryData: De
|
|
|
switch (deliveryData.deliveryType) {
|
|
switch (deliveryData.deliveryType) {
|
|
|
case 1: // 物流快递
|
|
case 1: // 物流快递
|
|
|
if (deliveryData.deliveryCompany && deliveryData.deliveryNo) {
|
|
if (deliveryData.deliveryCompany && deliveryData.deliveryNo) {
|
|
|
- // 注意:这里需要将快递公司名称转换为微信小店支持的delivery_id
|
|
|
|
|
- // 实际项目中需要维护一个快递公司映射表,这里暂时使用快递公司名称
|
|
|
|
|
|
|
+ // deliveryCompany现在存储的是delivery_id
|
|
|
expressInfo = {
|
|
expressInfo = {
|
|
|
- deliveryId: deliveryData.deliveryCompany, // 临时使用公司名称,实际应该用ID
|
|
|
|
|
|
|
+ deliveryId: deliveryData.deliveryCompany, // 直接使用ID
|
|
|
waybillId: deliveryData.deliveryNo
|
|
waybillId: deliveryData.deliveryNo
|
|
|
};
|
|
};
|
|
|
|
|
+ console.debug('使用快递公司ID:', {
|
|
|
|
|
+ deliveryId: deliveryData.deliveryCompany,
|
|
|
|
|
+ deliveryNo: deliveryData.deliveryNo
|
|
|
|
|
+ });
|
|
|
}
|
|
}
|
|
|
break;
|
|
break;
|
|
|
case 2: // 同城配送
|
|
case 2: // 同城配送
|
|
@@ -368,6 +256,7 @@ const uploadShippingInfoToWechat = async (order: OrderResponse, deliveryData: De
|
|
|
expressInfo,
|
|
expressInfo,
|
|
|
localDeliveryInfo,
|
|
localDeliveryInfo,
|
|
|
isAllDelivered: true,
|
|
isAllDelivered: true,
|
|
|
|
|
+ itemDesc, // 商品描述,最多110个字
|
|
|
tenantId: tenantId || order.tenantId
|
|
tenantId: tenantId || order.tenantId
|
|
|
}),
|
|
}),
|
|
|
});
|
|
});
|
|
@@ -405,73 +294,7 @@ const uploadShippingInfoToWechat = async (order: OrderResponse, deliveryData: De
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-// 发货成功微信通知函数 - 使用新的配置化设计
|
|
|
|
|
-const sendDeliverySuccessNotification = async (order: OrderResponse, deliveryData: DeliveryRequest): Promise<WechatServiceMessageResult> => {
|
|
|
|
|
- // 检查是否有用户信息和openid
|
|
|
|
|
- if (!order.user || !order.user.id) {
|
|
|
|
|
- console.warn('订单没有用户信息,无法发送微信通知');
|
|
|
|
|
- return { success: false, message: '订单没有用户信息,无法发送微信通知' };
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 检查用户是否有openid(微信小程序用户)
|
|
|
|
|
- if (!order.user.openid) {
|
|
|
|
|
- console.warn('用户没有绑定微信小程序,无法发送微信通知', {
|
|
|
|
|
- userId: order.user.id,
|
|
|
|
|
- username: order.user.username
|
|
|
|
|
- });
|
|
|
|
|
- return { success: false, message: '用户没有绑定微信小程序,无法发送微信通知' };
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 检查用户是否已订阅发货通知
|
|
|
|
|
- if (order.user.hasSubscribedDeliveryNotice !== true) {
|
|
|
|
|
- console.debug('用户未订阅发货通知,跳过发送微信通知', {
|
|
|
|
|
- userId: order.user.id,
|
|
|
|
|
- username: order.user.username,
|
|
|
|
|
- hasSubscribedDeliveryNotice: order.user.hasSubscribedDeliveryNotice
|
|
|
|
|
- });
|
|
|
|
|
- return {
|
|
|
|
|
- success: false,
|
|
|
|
|
- message: '用户未订阅发货通知,跳过发送微信通知',
|
|
|
|
|
- data: { skipped: true, reason: 'user_not_subscribed' }
|
|
|
|
|
- };
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- console.debug('用户已订阅发货通知,准备发送微信通知', {
|
|
|
|
|
- userId: order.user.id,
|
|
|
|
|
- username: order.user.username,
|
|
|
|
|
- openid: order.user.openid?.substring(0, 10) + '...' // 部分隐藏openid
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- // 构建微信服务消息配置 - 参考useShareAppMessage的配置对象模式
|
|
|
|
|
- const config: WechatServiceMessageConfig = {
|
|
|
|
|
- openid: order.user.openid,
|
|
|
|
|
- templateId: 'T00N0Wq3ECjksXSvPWUBgOUukl1TCE7PhxqeDnFPfso', // 发货成功通知模板ID
|
|
|
|
|
- page: 'pages/order/detail/index', // 点击跳转到订单详情页
|
|
|
|
|
- data: {
|
|
|
|
|
- // 根据实际微信模板字段配置
|
|
|
|
|
- character_string7: {
|
|
|
|
|
- value: `${order.orderNo}`
|
|
|
|
|
- },
|
|
|
|
|
- date6: {
|
|
|
|
|
- value: formatWechatDate(deliveryData.deliveryTime)
|
|
|
|
|
- },
|
|
|
|
|
- amount9: {
|
|
|
|
|
- value: `¥${order.payAmount.toFixed(2)}`
|
|
|
|
|
- },
|
|
|
|
|
- phrase12: {
|
|
|
|
|
- value: deliveryTypeMap[deliveryData.deliveryType as keyof typeof deliveryTypeMap]?.label || '未知'
|
|
|
|
|
- },
|
|
|
|
|
- thing4: {
|
|
|
|
|
- value: (deliveryData.deliveryRemark || '请收到货/提货后及时确认收货,2天后将自动确认收货,如有异常请及时进行交易投诉。').substring(0, 20)
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- miniprogramState: 'formal',
|
|
|
|
|
- tenantId: order.tenantId // 从订单数据中获取tenantId
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- // 调用微信服务消息函数
|
|
|
|
|
- return await sendWechatServiceMessage(config);
|
|
|
|
|
-};
|
|
|
|
|
|
|
+
|
|
|
|
|
|
|
|
// 状态映射
|
|
// 状态映射
|
|
|
const orderStatusMap = {
|
|
const orderStatusMap = {
|
|
@@ -530,7 +353,7 @@ export const OrderManagement = () => {
|
|
|
// 发货表单实例
|
|
// 发货表单实例
|
|
|
const deliveryForm = useForm<DeliveryRequest>({
|
|
const deliveryForm = useForm<DeliveryRequest>({
|
|
|
defaultValues: {
|
|
defaultValues: {
|
|
|
- deliveryType: 2, // 2表示同城配送
|
|
|
|
|
|
|
+ deliveryType: 1,
|
|
|
deliveryCompany: '__select__',
|
|
deliveryCompany: '__select__',
|
|
|
deliveryNo: '',
|
|
deliveryNo: '',
|
|
|
deliveryRemark: '',
|
|
deliveryRemark: '',
|
|
@@ -655,44 +478,40 @@ export const OrderManagement = () => {
|
|
|
const handleDeliveryOrder = async (order: OrderResponse) => {
|
|
const handleDeliveryOrder = async (order: OrderResponse) => {
|
|
|
setDeliveringOrder(order);
|
|
setDeliveringOrder(order);
|
|
|
deliveryForm.reset({
|
|
deliveryForm.reset({
|
|
|
- deliveryType: 2, // 2表示同城配送
|
|
|
|
|
|
|
+ deliveryType: 1,
|
|
|
deliveryCompany: '__select__',
|
|
deliveryCompany: '__select__',
|
|
|
deliveryNo: '',
|
|
deliveryNo: '',
|
|
|
deliveryRemark: '',
|
|
deliveryRemark: '',
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
- // // 获取快递公司列表
|
|
|
|
|
- // setLoadingCompanies(true);
|
|
|
|
|
- // try {
|
|
|
|
|
- // const result = await getWechatDeliveryCompanies(order.tenantId);
|
|
|
|
|
- // console.log("result:",result);
|
|
|
|
|
- // const resdata = result.data;
|
|
|
|
|
- // if (result.success && resdata.data?.company_list) {
|
|
|
|
|
- // const companyList = resdata.data.company_list;
|
|
|
|
|
- // setDeliveryCompanies(companyList);
|
|
|
|
|
-
|
|
|
|
|
- // // 如果有快递公司列表,自动选中第一个
|
|
|
|
|
- // if (companyList.length > 0) {
|
|
|
|
|
- // // 延迟设置,确保组件已经渲染
|
|
|
|
|
- // setTimeout(() => {
|
|
|
|
|
- // deliveryForm.setValue('deliveryCompany', companyList[0].delivery_name);
|
|
|
|
|
- // }, 0);
|
|
|
|
|
- // }
|
|
|
|
|
- // } else {
|
|
|
|
|
- // console.warn('获取快递公司列表失败或为空:', result);
|
|
|
|
|
- // setDeliveryCompanies([]);
|
|
|
|
|
- // // 如果获取失败,显示提示信息
|
|
|
|
|
- // if (resdata.message && !resdata.message.includes('获取快递公司列表成功')) {
|
|
|
|
|
- // toast.warning(`获取快递公司列表失败: ${resdata.message},请手动输入快递公司名称`);
|
|
|
|
|
- // }
|
|
|
|
|
- // }
|
|
|
|
|
- // } catch (error) {
|
|
|
|
|
- // console.error('获取快递公司列表时出错:', error);
|
|
|
|
|
- // setDeliveryCompanies([]);
|
|
|
|
|
- // toast.warning('获取快递公司列表失败,请手动输入快递公司名称');
|
|
|
|
|
- // } finally {
|
|
|
|
|
- // setLoadingCompanies(false);
|
|
|
|
|
- // }
|
|
|
|
|
|
|
+ // 获取快递公司列表
|
|
|
|
|
+ setLoadingCompanies(true);
|
|
|
|
|
+ try {
|
|
|
|
|
+ const result = await getWechatDeliveryCompanies(order.tenantId);
|
|
|
|
|
+ const resdata =result.data;
|
|
|
|
|
+ console.log("result:",result);
|
|
|
|
|
+ if (resdata.success && resdata.data?.company_list) {
|
|
|
|
|
+ const companyList = resdata.data.company_list;
|
|
|
|
|
+ setDeliveryCompanies(companyList);
|
|
|
|
|
+
|
|
|
|
|
+ // 如果有快递公司列表,自动选中第一个
|
|
|
|
|
+ if (companyList.length > 0) {
|
|
|
|
|
+ // 延迟设置,确保组件已经渲染
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ deliveryForm.setValue('deliveryCompany', companyList[0].delivery_id);
|
|
|
|
|
+ }, 0);
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ console.warn('获取快递公司列表失败或为空:', resdata);
|
|
|
|
|
+ setDeliveryCompanies([]);
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('获取快递公司列表时出错:', error);
|
|
|
|
|
+ setDeliveryCompanies([]);
|
|
|
|
|
+ toast.warning('获取快递公司列表失败,请手动输入快递公司名称');
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ setLoadingCompanies(false);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
setDeliveryModalOpen(true);
|
|
setDeliveryModalOpen(true);
|
|
|
};
|
|
};
|
|
@@ -800,31 +619,6 @@ export const OrderManagement = () => {
|
|
|
console.debug("信用支付订单(payType=3),跳过微信小程序发货信息录入");
|
|
console.debug("信用支付订单(payType=3),跳过微信小程序发货信息录入");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-
|
|
|
|
|
- // 发货成功后发送微信服务消息通知 - 使用新的配置化设计
|
|
|
|
|
- // try {
|
|
|
|
|
- // const notificationResult = await sendDeliverySuccessNotification(deliveringOrder, data);
|
|
|
|
|
-
|
|
|
|
|
- // // 根据通知结果记录不同的日志
|
|
|
|
|
- // if (notificationResult.success) {
|
|
|
|
|
- // console.debug('微信发货通知发送成功:', notificationResult);
|
|
|
|
|
- // } else if (notificationResult.data?.skipped) {
|
|
|
|
|
- // // 用户未订阅,这是正常情况,记录为debug级别
|
|
|
|
|
- // console.debug('用户未订阅发货通知,跳过发送:', {
|
|
|
|
|
- // userId: deliveringOrder.user?.id,
|
|
|
|
|
- // username: deliveringOrder.user?.username,
|
|
|
|
|
- // reason: notificationResult.data.reason
|
|
|
|
|
- // });
|
|
|
|
|
- // } else {
|
|
|
|
|
- // // 其他原因导致的失败,记录为warn级别
|
|
|
|
|
- // console.warn('微信发货通知发送失败,但发货成功:', notificationResult);
|
|
|
|
|
- // // 可以在这里添加额外的处理,比如记录到日志系统
|
|
|
|
|
- // }
|
|
|
|
|
- // } catch (notificationError) {
|
|
|
|
|
- // console.error('发送微信发货通知时发生异常:', notificationError);
|
|
|
|
|
- // // 不阻止发货成功,只记录错误
|
|
|
|
|
- // }
|
|
|
|
|
-
|
|
|
|
|
} else {
|
|
} else {
|
|
|
// 先尝试获取响应文本,避免JSON解析错误
|
|
// 先尝试获取响应文本,避免JSON解析错误
|
|
|
let errorText = '';
|
|
let errorText = '';
|
|
@@ -1508,10 +1302,10 @@ export const OrderManagement = () => {
|
|
|
</SelectTrigger>
|
|
</SelectTrigger>
|
|
|
</FormControl>
|
|
</FormControl>
|
|
|
<SelectContent>
|
|
<SelectContent>
|
|
|
- {/* <SelectItem value="1">物流快递</SelectItem> */}
|
|
|
|
|
|
|
+ <SelectItem value="1">物流快递</SelectItem>
|
|
|
<SelectItem value="2">同城配送</SelectItem>
|
|
<SelectItem value="2">同城配送</SelectItem>
|
|
|
- <SelectItem value="3">用户自提</SelectItem>
|
|
|
|
|
- <SelectItem value="4">虚拟发货</SelectItem>
|
|
|
|
|
|
|
+ <SelectItem value="3">虚拟发货</SelectItem>
|
|
|
|
|
+ <SelectItem value="4">用户自提</SelectItem>
|
|
|
</SelectContent>
|
|
</SelectContent>
|
|
|
</Select>
|
|
</Select>
|
|
|
<FormMessage />
|
|
<FormMessage />
|
|
@@ -1525,10 +1319,79 @@ export const OrderManagement = () => {
|
|
|
control={deliveryForm.control}
|
|
control={deliveryForm.control}
|
|
|
name="deliveryCompany"
|
|
name="deliveryCompany"
|
|
|
render={({ field }) => (
|
|
render={({ field }) => (
|
|
|
- <FormItem>
|
|
|
|
|
|
|
+ <FormItem className="flex flex-col">
|
|
|
<FormLabel>快递公司</FormLabel>
|
|
<FormLabel>快递公司</FormLabel>
|
|
|
- {deliveryForm.watch('deliveryCompany') === '__manual__' ? (
|
|
|
|
|
- <>
|
|
|
|
|
|
|
+ <Popover>
|
|
|
|
|
+ <PopoverTrigger asChild>
|
|
|
|
|
+ <FormControl>
|
|
|
|
|
+ <Button
|
|
|
|
|
+ variant="outline"
|
|
|
|
|
+ role="combobox"
|
|
|
|
|
+ className="w-full justify-between"
|
|
|
|
|
+ disabled={loadingCompanies}
|
|
|
|
|
+ data-testid="delivery-company-select"
|
|
|
|
|
+ >
|
|
|
|
|
+ {field.value === '__manual__'
|
|
|
|
|
+ ? "手动输入"
|
|
|
|
|
+ : field.value && field.value !== '__select__'
|
|
|
|
|
+ ? deliveryCompanies.find(
|
|
|
|
|
+ (company) => company.delivery_id === field.value
|
|
|
|
|
+ )?.delivery_name || field.value // 如果是手动输入的名称,显示名称
|
|
|
|
|
+ : loadingCompanies
|
|
|
|
|
+ ? "加载中..."
|
|
|
|
|
+ : "选择快递公司"}
|
|
|
|
|
+ <Search className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </FormControl>
|
|
|
|
|
+ </PopoverTrigger>
|
|
|
|
|
+ <PopoverContent className="w-full p-0">
|
|
|
|
|
+ <Command>
|
|
|
|
|
+ <CommandInput
|
|
|
|
|
+ placeholder="搜索快递公司..."
|
|
|
|
|
+ className="h-9"
|
|
|
|
|
+ />
|
|
|
|
|
+ <CommandList>
|
|
|
|
|
+ <CommandEmpty>未找到匹配的快递公司</CommandEmpty>
|
|
|
|
|
+ <CommandGroup>
|
|
|
|
|
+ {deliveryCompanies.map((company) => (
|
|
|
|
|
+ <CommandItem
|
|
|
|
|
+ key={company.delivery_id}
|
|
|
|
|
+ value={company.delivery_name} // 搜索时使用名称
|
|
|
|
|
+ onSelect={() => {
|
|
|
|
|
+ field.onChange(company.delivery_id); // 存储ID
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ {company.delivery_name}
|
|
|
|
|
+ {company.delivery_id === field.value && (
|
|
|
|
|
+ <Check className="ml-auto h-4 w-4" />
|
|
|
|
|
+ )}
|
|
|
|
|
+ </CommandItem>
|
|
|
|
|
+ ))}
|
|
|
|
|
+ </CommandGroup>
|
|
|
|
|
+ {deliveryCompanies.length === 0 && !loadingCompanies && (
|
|
|
|
|
+ <>
|
|
|
|
|
+ <CommandSeparator />
|
|
|
|
|
+ <CommandGroup>
|
|
|
|
|
+ <CommandItem
|
|
|
|
|
+ value="手动输入"
|
|
|
|
|
+ onSelect={() => {
|
|
|
|
|
+ // 切换到手动输入模式,使用特殊值标识
|
|
|
|
|
+ field.onChange('__manual__');
|
|
|
|
|
+ }}
|
|
|
|
|
+ className="text-muted-foreground"
|
|
|
|
|
+ >
|
|
|
|
|
+ 手动输入快递公司名称
|
|
|
|
|
+ </CommandItem>
|
|
|
|
|
+ </CommandGroup>
|
|
|
|
|
+ </>
|
|
|
|
|
+ )}
|
|
|
|
|
+ </CommandList>
|
|
|
|
|
+ </Command>
|
|
|
|
|
+ </PopoverContent>
|
|
|
|
|
+ </Popover>
|
|
|
|
|
+ {/* 手动输入框 */}
|
|
|
|
|
+ {field.value === '__manual__' && (
|
|
|
|
|
+ <div className="mt-2">
|
|
|
<div className="flex gap-2 mb-2">
|
|
<div className="flex gap-2 mb-2">
|
|
|
<Button
|
|
<Button
|
|
|
type="button"
|
|
type="button"
|
|
@@ -1543,44 +1406,15 @@ export const OrderManagement = () => {
|
|
|
<Input
|
|
<Input
|
|
|
placeholder="请输入快递公司名称"
|
|
placeholder="请输入快递公司名称"
|
|
|
data-testid="delivery-company-manual-input"
|
|
data-testid="delivery-company-manual-input"
|
|
|
- value={field.value === '__manual__' ? '' : field.value}
|
|
|
|
|
- onChange={(e) => field.onChange(e.target.value)}
|
|
|
|
|
|
|
+ onChange={(e) => {
|
|
|
|
|
+ // 手动输入时,我们需要存储公司名称
|
|
|
|
|
+ // 但为了区分,我们可以存储为对象或特殊格式
|
|
|
|
|
+ // 这里简单处理:如果输入不为空,存储为字符串
|
|
|
|
|
+ field.onChange(e.target.value);
|
|
|
|
|
+ }}
|
|
|
/>
|
|
/>
|
|
|
</FormControl>
|
|
</FormControl>
|
|
|
- </>
|
|
|
|
|
- ) : (
|
|
|
|
|
- <Select
|
|
|
|
|
- onValueChange={field.onChange}
|
|
|
|
|
- value={field.value || ''}
|
|
|
|
|
- disabled={loadingCompanies}
|
|
|
|
|
- >
|
|
|
|
|
- <FormControl>
|
|
|
|
|
- <SelectTrigger data-testid="delivery-company-select">
|
|
|
|
|
- <SelectValue placeholder={
|
|
|
|
|
- loadingCompanies ? "加载中..." : "选择快递公司"
|
|
|
|
|
- } />
|
|
|
|
|
- </SelectTrigger>
|
|
|
|
|
- </FormControl>
|
|
|
|
|
- <SelectContent>
|
|
|
|
|
- <SelectItem value="__select__">请选择快递公司</SelectItem>
|
|
|
|
|
- {deliveryCompanies.map((company) => (
|
|
|
|
|
- <SelectItem
|
|
|
|
|
- key={company.delivery_id}
|
|
|
|
|
- value={company.delivery_name}
|
|
|
|
|
- >
|
|
|
|
|
- {company.delivery_name}
|
|
|
|
|
- </SelectItem>
|
|
|
|
|
- ))}
|
|
|
|
|
- {deliveryCompanies.length === 0 && !loadingCompanies && (
|
|
|
|
|
- <>
|
|
|
|
|
- <SelectItem value="no_data" disabled>
|
|
|
|
|
- 暂无快递公司数据(API未授权)
|
|
|
|
|
- </SelectItem>
|
|
|
|
|
- <SelectItem value="__manual__">手动输入快递公司</SelectItem>
|
|
|
|
|
- </>
|
|
|
|
|
- )}
|
|
|
|
|
- </SelectContent>
|
|
|
|
|
- </Select>
|
|
|
|
|
|
|
+ </div>
|
|
|
)}
|
|
)}
|
|
|
<FormMessage />
|
|
<FormMessage />
|
|
|
</FormItem>
|
|
</FormItem>
|