import { useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { format } from 'date-fns';
import { toast } from 'sonner';
import { Search, Edit, Eye } from 'lucide-react';
// 使用共享UI组件包的具体路径导入
import { Button } from '@d8d/shared-ui-components/components/ui/button';
import { Input } from '@d8d/shared-ui-components/components/ui/input';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@d8d/shared-ui-components/components/ui/card';
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@d8d/shared-ui-components/components/ui/table';
import { Badge } from '@d8d/shared-ui-components/components/ui/badge';
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@d8d/shared-ui-components/components/ui/dialog';
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@d8d/shared-ui-components/components/ui/form';
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 { Skeleton } from '@d8d/shared-ui-components/components/ui/skeleton';
// 简单分页组件
const DataTablePagination = ({
currentPage,
pageSize,
totalCount,
onPageChange
}: {
currentPage: number;
pageSize: number;
totalCount: number;
onPageChange: (page: number, limit: number) => void;
}) => {
const totalPages = Math.ceil(totalCount / pageSize);
return (
共 {totalCount} 条记录
第 {currentPage} 页,共 {totalPages} 页
);
};
import { adminOrderClient } from '../api';
import type { InferRequestType, InferResponseType } from 'hono/client';
import { UpdateOrderDto } from '@d8d/orders-module/schemas';
// 类型定义
type OrderResponse = InferResponseType['data'][0];
type UpdateRequest = InferRequestType['json'];
// 状态映射
const orderStatusMap = {
0: { label: '未发货', color: 'warning' },
1: { label: '已发货', color: 'info' },
2: { label: '收货成功', color: 'success' },
3: { label: '已退货', color: 'destructive' },
} as const;
const payStatusMap = {
0: { label: '未支付', color: 'warning' },
1: { label: '支付中', color: 'info' },
2: { label: '支付成功', color: 'success' },
3: { label: '已退款', color: 'secondary' },
4: { label: '支付失败', color: 'destructive' },
5: { label: '订单关闭', color: 'destructive' },
} as const;
const orderTypeMap = {
1: { label: '实物订单', color: 'default' },
2: { label: '虚拟订单', color: 'secondary' },
} as const;
export const OrderManagement = () => {
const [searchParams, setSearchParams] = useState({
page: 1,
limit: 10,
search: '',
status: 'all',
payStatus: 'all',
});
const [isModalOpen, setIsModalOpen] = useState(false);
const [editingOrder, setEditingOrder] = useState(null);
const [detailModalOpen, setDetailModalOpen] = useState(false);
const [selectedOrder, setSelectedOrder] = useState(null);
// 表单实例
const updateForm = useForm({
resolver: zodResolver(UpdateOrderDto),
defaultValues: {},
});
// 数据查询
const { data, isLoading, refetch } = useQuery({
queryKey: ['orders', searchParams],
queryFn: async () => {
const filters: any = {};
if (searchParams.status !== 'all') {
filters.state = parseInt(searchParams.status);
}
if (searchParams.payStatus !== 'all') {
filters.payState = parseInt(searchParams.payStatus);
}
const res = await adminOrderClient.$get({
query: {
page: searchParams.page,
pageSize: searchParams.limit,
keyword: searchParams.search,
...(Object.keys(filters).length > 0 && { filters: JSON.stringify(filters) }),
}
});
if (res.status !== 200) throw new Error('获取订单列表失败');
return await res.json();
}
});
// 处理搜索
const handleSearch = () => {
setSearchParams(prev => ({ ...prev, page: 1 }));
};
// 处理编辑订单
const handleEditOrder = (order: OrderResponse) => {
setEditingOrder(order);
updateForm.reset({
state: order.state,
payState: order.payState,
remark: order.remark || '',
});
setIsModalOpen(true);
};
// 处理查看详情
const handleViewDetails = (order: OrderResponse) => {
setSelectedOrder(order);
setDetailModalOpen(true);
};
// 处理更新订单
const handleUpdateSubmit = async (data: UpdateRequest) => {
if (!editingOrder) return;
try {
const res = await adminOrderClient[':id']['$put']({
param: { id: editingOrder.id.toString() },
json: data,
});
if (res.status === 200) {
toast.success('订单更新成功');
setIsModalOpen(false);
refetch();
} else {
const error = await res.json();
toast.error(error.message || '更新失败');
}
} catch (error) {
console.error('更新订单失败:', error);
toast.error('更新失败,请重试');
}
};
// 格式化金额
const formatAmount = (amount: number) => {
return `¥${amount.toFixed(2)}`;
};
// 获取状态颜色
const getStatusBadge = (status: number, type: 'order' | 'pay') => {
const map = type === 'order' ? orderStatusMap : payStatusMap;
const config = map[status as keyof typeof map] || { label: '未知', color: 'default' };
return {config.label};
};
// 骨架屏 - 只覆盖表格区域,搜索区域保持可用
if (isLoading) {
return (
{/* 页面标题 */}
{/* 搜索区域 - 保持可用 */}
订单列表
查看和管理所有订单
{/* 表格骨架屏 */}
订单号
用户信息
收货人
金额
订单状态
支付状态
创建时间
操作
{[...Array(5)].map((_, i) => (
))}
{/* 分页骨架屏 */}
);
}
return (
{/* 页面标题 */}
{/* 搜索区域 */}
订单列表
查看和管理所有订单
{/* 数据表格 */}
订单号
用户信息
收货人
金额
订单状态
支付状态
创建时间
操作
{data?.data.map((order) => (
{order.orderNo}
{orderTypeMap[order.orderType as keyof typeof orderTypeMap]?.label}
{order.user?.username || '-'}
{order.userPhone}
{order.recevierName || '-'}
{order.receiverMobile}
{formatAmount(order.payAmount)}
{formatAmount(order.amount)}
{getStatusBadge(order.state, 'order')}
{getStatusBadge(order.payState, 'pay')}
{format(new Date(order.createdAt), 'yyyy-MM-dd HH:mm')}
))}
{data?.data.length === 0 && !isLoading && (
)}
setSearchParams(prev => ({ ...prev, page, limit }))}
/>
{/* 编辑订单模态框 */}
{/* 订单详情模态框 */}
);
};