import React, { useState } from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { format } from 'date-fns'; import { zhCN } from 'date-fns/locale'; import { toast } from 'sonner'; import { Plus, Search, Edit, Trash2, MapPin } from 'lucide-react'; import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import type { InferRequestType, InferResponseType } from 'hono/client'; import { deliveryAddressClient } from '@/client/api'; import { CreateDeliveryAddressDto, UpdateDeliveryAddressDto } from '@/server/modules/delivery-address/delivery-address.schema'; import { Button } from '@/client/components/ui/button'; import { Input } from '@/client/components/ui/input'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/client/components/ui/card'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/client/components/ui/table'; import { Badge } from '@/client/components/ui/badge'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/client/components/ui/dialog'; import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from '@/client/components/ui/form'; import { Switch } from '@/client/components/ui/switch'; import { Skeleton } from '@/client/components/ui/skeleton'; import { DataTablePagination } from '@/client/admin-shadcn/components/DataTablePagination'; import { UserSelector } from '@/client/admin-shadcn/components/UserSelector'; // 类型定义 type DeliveryAddressResponse = InferResponseType['data'][0]; type CreateRequest = InferRequestType['json']; type UpdateRequest = InferRequestType['json']; // 表单schema const createFormSchema = CreateDeliveryAddressDto; const updateFormSchema = UpdateDeliveryAddressDto; export const DeliveryAddressesPage = () => { const queryClient = useQueryClient(); // 状态管理 const [searchParams, setSearchParams] = useState({ page: 1, limit: 10, search: '', userId: undefined as number | undefined, }); const [isModalOpen, setIsModalOpen] = useState(false); const [editingAddress, setEditingAddress] = useState(null); const [isCreateForm, setIsCreateForm] = useState(true); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const [addressToDelete, setAddressToDelete] = useState(null); // 表单实例 const createForm = useForm({ resolver: zodResolver(createFormSchema), defaultValues: { userId: 0, name: '', phone: '', address: '', receiverProvince: 0, receiverCity: 0, receiverDistrict: 0, receiverTown: 0, isDefault: 0, }, }); const updateForm = useForm({ resolver: zodResolver(updateFormSchema), }); // 数据查询 const { data, isLoading, refetch } = useQuery({ queryKey: ['delivery-addresses', searchParams], queryFn: async () => { const res = await deliveryAddressClient.$get({ query: { page: searchParams.page, pageSize: searchParams.limit, keyword: searchParams.search, ...(searchParams.userId && { userId: searchParams.userId }), } }); if (res.status !== 200) throw new Error('获取收货地址列表失败'); return await res.json(); } }); // 创建地址 const createMutation = useMutation({ mutationFn: async (data: CreateRequest) => { const res = await deliveryAddressClient.$post({ json: data }); if (res.status !== 201) throw new Error('创建失败'); return await res.json(); }, onSuccess: () => { toast.success('收货地址创建成功'); setIsModalOpen(false); refetch(); createForm.reset(); }, onError: (error) => { toast.error(error.message || '创建失败'); } }); // 更新地址 const updateMutation = useMutation({ mutationFn: async ({ id, data }: { id: number; data: UpdateRequest }) => { const res = await deliveryAddressClient[':id']['$put']({ param: { id: id.toString() }, json: data, }); if (res.status !== 200) throw new Error('更新失败'); return await res.json(); }, onSuccess: () => { toast.success('收货地址更新成功'); setIsModalOpen(false); refetch(); }, onError: (error) => { toast.error(error.message || '更新失败'); } }); // 删除地址 const deleteMutation = useMutation({ mutationFn: async (id: number) => { const res = await deliveryAddressClient[':id']['$delete']({ param: { id: id.toString() }, }); if (res.status !== 204) throw new Error('删除失败'); }, onSuccess: () => { toast.success('收货地址删除成功'); setDeleteDialogOpen(false); refetch(); }, onError: (error) => { toast.error(error.message || '删除失败'); } }); // 业务逻辑函数 const handleSearch = () => { setSearchParams(prev => ({ ...prev, page: 1 })); }; const handleCreateAddress = () => { setIsCreateForm(true); setEditingAddress(null); createForm.reset(); setIsModalOpen(true); }; const handleEditAddress = (address: DeliveryAddressResponse) => { setIsCreateForm(false); setEditingAddress(address); updateForm.reset({ name: address.name, phone: address.phone, address: address.address, receiverProvince: address.receiverProvince, receiverCity: address.receiverCity, receiverDistrict: address.receiverDistrict, receiverTown: address.receiverTown, isDefault: address.isDefault, }); setIsModalOpen(true); }; const handleDeleteAddress = (id: number) => { setAddressToDelete(id); setDeleteDialogOpen(true); }; const confirmDelete = () => { if (addressToDelete) { deleteMutation.mutate(addressToDelete); } }; const handleCreateSubmit = (data: CreateRequest) => { createMutation.mutate(data); }; const handleUpdateSubmit = (data: UpdateRequest) => { if (editingAddress) { updateMutation.mutate({ id: editingAddress.id, data }); } }; // 状态显示 const getStatusBadge = (status: number) => { switch (status) { case 1: return 正常; case 2: return 禁用; case 3: return 删除; default: return 未知; } }; const getIsDefaultBadge = (isDefault: number) => { return isDefault === 1 ? ( 默认 ) : ( 非默认 ); }; // 加载状态 if (isLoading) { return (
{[...Array(5)].map((_, i) => (
))}
); } return (
{/* 页面标题 */}

用户收货地址

管理用户的收货地址信息

{/* 搜索区域 */} 搜索筛选 根据条件筛选收货地址
setSearchParams(prev => ({ ...prev, search: e.target.value }))} className="pl-8" />
setSearchParams(prev => ({ ...prev, userId: value }))} placeholder="选择用户" />
{/* 数据表格 */} 收货地址列表 共 {data?.pagination.total || 0} 条记录
ID 用户 收货人 手机号 地址 状态 默认 创建时间 操作 {data?.data.map((address) => ( {address.id} {address.user?.username || '-'} {address.name} {address.phone} {address.address} {getStatusBadge(address.state)} {getIsDefaultBadge(address.isDefault)} {format(new Date(address.createdAt), 'yyyy-MM-dd HH:mm', { locale: zhCN })}
))}
{data?.data.length === 0 && !isLoading && (

暂无收货地址数据

)} setSearchParams(prev => ({ ...prev, page, limit }))} />
{/* 创建/编辑模态框 */} {isCreateForm ? '创建收货地址' : '编辑收货地址'} {isCreateForm ? '创建一个新的收货地址' : '编辑现有收货地址信息'} {isCreateForm ? (
( 用户* )} />
( 收货人姓名* )} /> ( 手机号* )} />
( 详细地址* )} />
( 省份ID )} /> ( 城市ID )} /> ( 区县ID )} /> ( 街道ID )} />
(
设为默认地址 将此地址设为用户的默认收货地址
field.onChange(checked ? 1 : 0)} />
)} /> ) : (
( 收货人姓名* )} /> ( 手机号* )} /> ( 详细地址* )} />
( 省份ID )} /> ( 城市ID )} /> ( 区县ID )} /> ( 街道ID )} />
(
设为默认地址 将此地址设为用户的默认收货地址
field.onChange(checked ? 1 : 0)} />
)} /> )}
{/* 删除确认对话框 */} 确认删除 确定要删除这个收货地址吗?此操作无法撤销。
); };