diff --git a/src/components/pages/EquipmentPage.tsx b/src/components/pages/EquipmentPage.tsx index 9277c6e..afb0a57 100644 --- a/src/components/pages/EquipmentPage.tsx +++ b/src/components/pages/EquipmentPage.tsx @@ -16,7 +16,7 @@ import { DialogTrigger, } from "../ui/dialog" import { Plus, Download, MapPin, Calendar, Shield, ChevronLeft, ChevronRight, Minus, Plus as PlusIcon, Search } from "lucide-react" -import { apiGet, apiPost, apiPut } from "../../lib/services/api" +import { apiGet, apiPost, apiPut, apiExportFile } from "../../lib/services/api" // 商户数据类型(根据新接口返回格式定义) interface ProvinceMerchant { @@ -98,6 +98,7 @@ export default function EquipmentPage() { const [loadingStats, setLoadingStats] = useState(false) const [merchantSearchForAdd, setMerchantSearchForAdd] = useState("") const [merchantSearchForEdit, setMerchantSearchForEdit] = useState("") + const [isExporting, setIsExporting] = useState(false) // 获取设备统计数据 const fetchEquipmentStats = async () => { @@ -534,6 +535,29 @@ export default function EquipmentPage() { } } + // 导出设备数据 + const handleExportEquipment = async () => { + setIsExporting(true) + try { + // 构建导出参数(包含当前搜索条件) + const exportParams = { + equipmentId: equipmentIdSearch.trim() || undefined, + equipmentName: equipmentNameSearch.trim() || undefined, + status: statusFilter !== "all" ? statusFilter : undefined, + } + + // 调用导出接口 + await apiExportFile('/back/equipment/export', exportParams, `设备列表_${new Date().toISOString().split('T')[0]}.xlsx`) + + console.log('导出设备数据成功') + } catch (error) { + console.error('导出设备数据失败:', error) + alert('导出失败:' + (error instanceof Error ? error.message : '未知错误')) + } finally { + setIsExporting(false) + } + } + // 直接使用从API返回的数据,不再进行前端过滤 const filteredEquipment = equipmentList @@ -1228,9 +1252,14 @@ export default function EquipmentPage() { 已到期 - diff --git a/src/components/pages/MerchantsPage.tsx b/src/components/pages/MerchantsPage.tsx index 84efb31..803a4b7 100644 --- a/src/components/pages/MerchantsPage.tsx +++ b/src/components/pages/MerchantsPage.tsx @@ -15,7 +15,7 @@ import { DialogTitle, } from "../ui/dialog" import { Plus, Search, Filter, Download, Store, Eye, Building2, MapPin, ChevronLeft, ChevronRight, Edit } from "lucide-react" -import { apiGet, apiPost, apiPut } from "../../lib/services/api" +import { apiGet, apiPost, apiPut, apiExportFile } from "../../lib/services/api" // 总商户数据类型 interface TotalMerchant { @@ -87,6 +87,7 @@ export default function MerchantsPage() { countExpire: 0 }) const [loadingUserEquipmentCount, setLoadingUserEquipmentCount] = useState(false) + const [isExporting, setIsExporting] = useState(false) const [newMerchant, setNewMerchant] = useState({ name: "", @@ -571,6 +572,30 @@ export default function MerchantsPage() { } } + // 导出商户数据 + const handleExportMerchants = async () => { + setIsExporting(true) + try { + // 构建导出参数(包含当前搜索条件) + const exportParams = { + merchantName: merchantNameSearch.trim() || undefined, + contactPerson: contactPersonSearch.trim() || undefined, + contactPhone: contactPhoneSearch.trim() || undefined, + equipmentStatus: statusFilter !== "all" ? statusFilter : undefined, + } + + // 调用导出接口 + await apiExportFile('/back/merchants/export', exportParams, `商户列表_${new Date().toISOString().split('T')[0]}.xlsx`) + + console.log('导出商户数据成功') + } catch (error) { + console.error('导出商户数据失败:', error) + alert('导出失败:' + (error instanceof Error ? error.message : '未知错误')) + } finally { + setIsExporting(false) + } + } + // 提交编辑 const handleUpdateMerchant = async () => { if (!editMerchant.name || !editMerchant.contact || !editMerchant.phone) { @@ -740,9 +765,13 @@ export default function MerchantsPage() { - diff --git a/src/components/pages/WorkOrderArchivePage.tsx b/src/components/pages/WorkOrderArchivePage.tsx index 8b614f6..b9ace56 100644 --- a/src/components/pages/WorkOrderArchivePage.tsx +++ b/src/components/pages/WorkOrderArchivePage.tsx @@ -1,4 +1,5 @@ import { useState, useEffect } from "react"; +import { useSearchParams } from "react-router-dom"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../ui/card"; import { Button } from "../ui/button"; import { Input } from "../ui/input"; @@ -47,6 +48,7 @@ interface ArchivedWorkOrder { } export default function WorkOrderArchivePage() { + const [searchParams, setSearchParams] = useSearchParams(); const [archivedOrders, setArchivedOrders] = useState([]); const [searchTerm, setSearchTerm] = useState(""); const [statusFilter, setStatusFilter] = useState("all"); @@ -81,14 +83,15 @@ export default function WorkOrderArchivePage() { }; // 获取归档工单列表 - const fetchArchivedOrders = async (pageNum = 1, pageSize = 10) => { + const fetchArchivedOrders = async (pageNum = 1, pageSize = 10, searchValue?: string) => { setLoading(true); try { let url = `/back/workOrderArchive/list?pageNum=${pageNum}&pageSize=${pageSize}`; - // 添加工单编号搜索参数 - if (searchTerm.trim()) { - url += `&workOrderNumber=${encodeURIComponent(searchTerm.trim())}`; + // 添加工单编号搜索参数,优先使用传入的搜索值,否则使用 state 中的 searchTerm + const searchValueToUse = searchValue !== undefined ? searchValue : searchTerm; + if (searchValueToUse.trim()) { + url += `&workOrderNumber=${encodeURIComponent(searchValueToUse.trim())}`; } // 添加合格/不合格筛选参数 @@ -112,9 +115,25 @@ export default function WorkOrderArchivePage() { } }; + // 从 URL 参数中读取工单号并设置搜索词 + useEffect(() => { + const workOrderNumber = searchParams.get('workOrderNumber'); + if (workOrderNumber) { + setSearchTerm(workOrderNumber); + // 立即搜索,不等待防抖 + fetchArchivedOrders(1, 10, workOrderNumber); + // 清除 URL 参数,避免刷新时重复搜索 + setSearchParams({}, { replace: true }); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [searchParams]); + useEffect(() => { fetchArchiveCount(); - fetchArchivedOrders(1, 10); + // 只有在没有 URL 参数时才执行初始加载(避免与上面的 useEffect 重复) + if (!searchParams.get('workOrderNumber')) { + fetchArchivedOrders(1, 10); + } }, []); // 监听搜索词和筛选条件变化,重新请求数据 diff --git a/src/components/pages/WorkOrdersPage.tsx b/src/components/pages/WorkOrdersPage.tsx index e024bfe..5bf066e 100644 --- a/src/components/pages/WorkOrdersPage.tsx +++ b/src/components/pages/WorkOrdersPage.tsx @@ -1,4 +1,5 @@ import React, { useState, useEffect } from "react" +import { useNavigate } from "react-router-dom" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../ui/card" import { Button } from "../ui/button" import { Input } from "../ui/input" @@ -27,6 +28,7 @@ import { ChevronRight, Wrench, Edit, + FileText, } from "lucide-react" import { apiGet, apiPost, apiPut } from "../../lib/services/api" @@ -153,6 +155,7 @@ interface WorkOrder { } export default function WorkOrdersPage() { + const navigate = useNavigate() const [searchTerm, setSearchTerm] = useState("") const [statusFilter, setStatusFilter] = useState("all") const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false) @@ -502,16 +505,30 @@ export default function WorkOrdersPage() { - +
+ + {item.status === "7" && ( + + )} +
)) @@ -540,16 +557,30 @@ export default function WorkOrdersPage() {
{item.equipmentName}
设备: {item.equipmentId}
- +
+ + {item.status === "7" && ( + + )} +