更新时间
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useState } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../ui/card";
|
||||
import { Button } from "../ui/button";
|
||||
import { Input } from "../ui/input";
|
||||
@@ -6,134 +6,79 @@ import { Badge } from "../ui/badge";
|
||||
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "../ui/dialog";
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "../ui/table";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../ui/select";
|
||||
import { Search, Eye, Download, FileText, CheckCircle, User, Building } from "lucide-react";
|
||||
import { Search, Eye, Download, FileText, CheckCircle, User, Building, ChevronLeft, ChevronRight } from "lucide-react";
|
||||
import { apiGet } from "../../lib/services/api";
|
||||
|
||||
interface ArchivedWorkOrder {
|
||||
id: string;
|
||||
title: string;
|
||||
merchant: string;
|
||||
equipment: string;
|
||||
worker: string;
|
||||
dealer: string;
|
||||
completedDate: string;
|
||||
archiveDate: string;
|
||||
status: "completed";
|
||||
priority: "high" | "medium" | "low";
|
||||
signatures: {
|
||||
worker: {
|
||||
name: string;
|
||||
signature: string;
|
||||
timestamp: string;
|
||||
photos: string[];
|
||||
};
|
||||
merchant: {
|
||||
name: string;
|
||||
signature: string;
|
||||
timestamp: string;
|
||||
};
|
||||
dealerAdmin: {
|
||||
name: string;
|
||||
signature: string;
|
||||
timestamp: string;
|
||||
};
|
||||
};
|
||||
workDetails: {
|
||||
description: string;
|
||||
beforePhotos: string[];
|
||||
afterPhotos: string[];
|
||||
materials: string[];
|
||||
notes: string;
|
||||
};
|
||||
workOrderNumber: string;
|
||||
workOrderType: string;
|
||||
merchantName: string;
|
||||
equipmentName: string;
|
||||
workerName: string;
|
||||
priority: string;
|
||||
completedDate: string | null;
|
||||
createdDate: string;
|
||||
status: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
merchantAddress: string;
|
||||
responsiblePerson: string;
|
||||
responsibleVirtualPhone: string;
|
||||
workerVirtualPhone: string;
|
||||
frontImg: string;
|
||||
openImg: string;
|
||||
ropeReImg: string;
|
||||
hostReImg: string;
|
||||
otherImg: string;
|
||||
repairImg: string;
|
||||
repairVideo: string;
|
||||
needRepair: boolean;
|
||||
equNormal: boolean;
|
||||
}
|
||||
|
||||
export default function WorkOrderArchivePage() {
|
||||
const [archivedOrders, setArchivedOrders] = useState<ArchivedWorkOrder[]>([
|
||||
{
|
||||
id: "WO-2024-001",
|
||||
title: "干粉灭火器年检",
|
||||
merchant: "星巴克咖啡店",
|
||||
equipment: "干粉灭火器-001",
|
||||
worker: "张师傅",
|
||||
dealer: "华东经销商",
|
||||
completedDate: "2024-01-15",
|
||||
archiveDate: "2024-01-16",
|
||||
status: "completed",
|
||||
priority: "medium",
|
||||
signatures: {
|
||||
worker: {
|
||||
name: "张师傅",
|
||||
signature: "/placeholder.svg?height=100&width=200",
|
||||
timestamp: "2024-01-15 14:30:00",
|
||||
photos: ["/placeholder.svg?height=300&width=400", "/placeholder.svg?height=300&width=400"],
|
||||
},
|
||||
merchant: {
|
||||
name: "李经理",
|
||||
signature: "/placeholder.svg?height=100&width=200",
|
||||
timestamp: "2024-01-15 15:00:00",
|
||||
},
|
||||
dealerAdmin: {
|
||||
name: "王主管",
|
||||
signature: "/placeholder.svg?height=100&width=200",
|
||||
timestamp: "2024-01-15 16:00:00",
|
||||
},
|
||||
},
|
||||
workDetails: {
|
||||
description: "对干粉灭火器进行年度检测,检查压力表、安全销、喷嘴等部件",
|
||||
beforePhotos: ["/placeholder.svg?height=300&width=400", "/placeholder.svg?height=300&width=400"],
|
||||
afterPhotos: ["/placeholder.svg?height=300&width=400", "/placeholder.svg?height=300&width=400"],
|
||||
materials: ["压力表", "安全销", "检测标签"],
|
||||
notes: "设备状态良好,已更换压力表,贴上检测合格标签",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "WO-2024-002",
|
||||
title: "烟感器故障维修",
|
||||
merchant: "麦当劳餐厅",
|
||||
equipment: "烟感器-025",
|
||||
worker: "李师傅",
|
||||
dealer: "华南经销商",
|
||||
completedDate: "2024-01-12",
|
||||
archiveDate: "2024-01-13",
|
||||
status: "completed",
|
||||
priority: "high",
|
||||
signatures: {
|
||||
worker: {
|
||||
name: "李师傅",
|
||||
signature: "/placeholder.svg?height=100&width=200",
|
||||
timestamp: "2024-01-12 11:45:00",
|
||||
photos: ["/placeholder.svg?height=300&width=400", "/placeholder.svg?height=300&width=400"],
|
||||
},
|
||||
merchant: {
|
||||
name: "陈店长",
|
||||
signature: "/placeholder.svg?height=100&width=200",
|
||||
timestamp: "2024-01-12 12:15:00",
|
||||
},
|
||||
dealerAdmin: {
|
||||
name: "赵经理",
|
||||
signature: "/placeholder.svg?height=100&width=200",
|
||||
timestamp: "2024-01-12 13:00:00",
|
||||
},
|
||||
},
|
||||
workDetails: {
|
||||
description: "烟感器报警异常,需要更换传感器模块",
|
||||
beforePhotos: ["/placeholder.svg?height=300&width=400", "/placeholder.svg?height=300&width=400"],
|
||||
afterPhotos: ["/placeholder.svg?height=300&width=400", "/placeholder.svg?height=300&width=400"],
|
||||
materials: ["传感器模块", "电池", "固定螺丝"],
|
||||
notes: "已更换传感器模块,测试正常,设备恢复正常工作",
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const [archivedOrders, setArchivedOrders] = useState<ArchivedWorkOrder[]>([]);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [statusFilter, setStatusFilter] = useState("all");
|
||||
const [selectedOrder, setSelectedOrder] = useState<ArchivedWorkOrder | null>(null);
|
||||
const [isDetailDialogOpen, setIsDetailDialogOpen] = useState(false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [pagination, setPagination] = useState({
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
total: 0
|
||||
});
|
||||
|
||||
// 获取归档工单列表
|
||||
const fetchArchivedOrders = async (pageNum = 1, pageSize = 10) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const response = await apiGet(`/client/work/list?queryStaus=6&pageNum=${pageNum}&pageSize=${pageSize}`);
|
||||
if (response.code === 200) {
|
||||
setArchivedOrders(response.data || []);
|
||||
setPagination({
|
||||
pageNum,
|
||||
pageSize,
|
||||
total: parseInt(response.total) || 0
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取归档工单列表失败:', error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchArchivedOrders();
|
||||
}, []);
|
||||
|
||||
const filteredOrders = archivedOrders.filter((order) => {
|
||||
const matchesSearch =
|
||||
order.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
order.merchant.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
order.id.toLowerCase().includes(searchTerm.toLowerCase());
|
||||
order.workOrderType.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
order.merchantName.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
order.workOrderNumber.toLowerCase().includes(searchTerm.toLowerCase());
|
||||
const matchesStatus = statusFilter === "all" || order.status === statusFilter;
|
||||
return matchesSearch && matchesStatus;
|
||||
});
|
||||
@@ -145,11 +90,11 @@ export default function WorkOrderArchivePage() {
|
||||
|
||||
const getPriorityColor = (priority: string) => {
|
||||
switch (priority) {
|
||||
case "high":
|
||||
case "1":
|
||||
return "bg-red-100 text-red-800";
|
||||
case "medium":
|
||||
case "2":
|
||||
return "bg-yellow-100 text-yellow-800";
|
||||
case "low":
|
||||
case "3":
|
||||
return "bg-green-100 text-green-800";
|
||||
default:
|
||||
return "bg-gray-100 text-gray-800";
|
||||
@@ -158,11 +103,11 @@ export default function WorkOrderArchivePage() {
|
||||
|
||||
const getPriorityText = (priority: string) => {
|
||||
switch (priority) {
|
||||
case "high":
|
||||
case "1":
|
||||
return "高";
|
||||
case "medium":
|
||||
case "2":
|
||||
return "中";
|
||||
case "low":
|
||||
case "3":
|
||||
return "低";
|
||||
default:
|
||||
return "未知";
|
||||
@@ -190,7 +135,7 @@ export default function WorkOrderArchivePage() {
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-gray-600">归档总数</p>
|
||||
<p className="text-3xl font-bold">1,248</p>
|
||||
<p className="text-3xl font-bold">{pagination.total}</p>
|
||||
</div>
|
||||
<FileText className="h-8 w-8 text-blue-500" />
|
||||
</div>
|
||||
@@ -201,8 +146,8 @@ export default function WorkOrderArchivePage() {
|
||||
<CardContent className="p-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-gray-600">本月归档</p>
|
||||
<p className="text-3xl font-bold">156</p>
|
||||
<p className="text-sm font-medium text-gray-600">当前页</p>
|
||||
<p className="text-3xl font-bold">{archivedOrders.length}</p>
|
||||
</div>
|
||||
<CheckCircle className="h-8 w-8 text-green-500" />
|
||||
</div>
|
||||
@@ -213,8 +158,8 @@ export default function WorkOrderArchivePage() {
|
||||
<CardContent className="p-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-gray-600">完整签字</p>
|
||||
<p className="text-3xl font-bold">98.5%</p>
|
||||
<p className="text-sm font-medium text-gray-600">页码</p>
|
||||
<p className="text-3xl font-bold">{pagination.pageNum}/{Math.ceil(pagination.total / pagination.pageSize)}</p>
|
||||
</div>
|
||||
<User className="h-8 w-8 text-purple-500" />
|
||||
</div>
|
||||
@@ -225,8 +170,8 @@ export default function WorkOrderArchivePage() {
|
||||
<CardContent className="p-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm font-medium text-gray-600">存储容量</p>
|
||||
<p className="text-3xl font-bold">2.4GB</p>
|
||||
<p className="text-sm font-medium text-gray-600">每页数量</p>
|
||||
<p className="text-3xl font-bold">{pagination.pageSize}</p>
|
||||
</div>
|
||||
<Building className="h-8 w-8 text-orange-500" />
|
||||
</div>
|
||||
@@ -279,37 +224,78 @@ export default function WorkOrderArchivePage() {
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{filteredOrders.map((order) => (
|
||||
<TableRow key={order.id}>
|
||||
<TableCell className="font-medium">{order.id}</TableCell>
|
||||
<TableCell>{order.title}</TableCell>
|
||||
<TableCell>{order.merchant}</TableCell>
|
||||
<TableCell>{order.equipment}</TableCell>
|
||||
<TableCell>{order.worker}</TableCell>
|
||||
<TableCell>
|
||||
<Badge className={getPriorityColor(order.priority)}>{getPriorityText(order.priority)}</Badge>
|
||||
</TableCell>
|
||||
<TableCell>{order.completedDate}</TableCell>
|
||||
<TableCell>{order.archiveDate}</TableCell>
|
||||
<TableCell>
|
||||
<Button variant="outline" size="sm" onClick={() => openDetailDialog(order)}>
|
||||
<Eye className="h-4 w-4 mr-1" />
|
||||
查看详情
|
||||
</Button>
|
||||
{loading ? (
|
||||
<TableRow>
|
||||
<TableCell colSpan={9} className="text-center py-8">
|
||||
<div className="text-gray-500">加载中...</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
) : filteredOrders.length === 0 ? (
|
||||
<TableRow>
|
||||
<TableCell colSpan={9} className="text-center py-8">
|
||||
<div className="text-gray-500">暂无数据</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
) : (
|
||||
filteredOrders.map((order) => (
|
||||
<TableRow key={order.id}>
|
||||
<TableCell className="font-medium">{order.workOrderNumber}</TableCell>
|
||||
<TableCell>{order.workOrderType}</TableCell>
|
||||
<TableCell>{order.merchantName}</TableCell>
|
||||
<TableCell>{order.equipmentName}</TableCell>
|
||||
<TableCell>{order.workerName}</TableCell>
|
||||
<TableCell>
|
||||
<Badge className={getPriorityColor(order.priority)}>{getPriorityText(order.priority)}</Badge>
|
||||
</TableCell>
|
||||
<TableCell>{order.updatedAt}</TableCell>
|
||||
<TableCell>{order.updatedAt}</TableCell>
|
||||
<TableCell>
|
||||
<Button variant="outline" size="sm" onClick={() => openDetailDialog(order)}>
|
||||
<Eye className="h-4 w-4 mr-1" />
|
||||
查看详情
|
||||
</Button>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
|
||||
{/* Pagination */}
|
||||
<div className="flex items-center justify-between mt-4">
|
||||
<div className="text-sm text-gray-600">
|
||||
共 {pagination.total} 条记录,当前第 {pagination.pageNum} 页,共 {Math.ceil(pagination.total / pagination.pageSize)} 页
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => fetchArchivedOrders(pagination.pageNum - 1, pagination.pageSize)}
|
||||
disabled={pagination.pageNum === 1 || loading}
|
||||
>
|
||||
<ChevronLeft className="h-4 w-4" />
|
||||
上一页
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => fetchArchivedOrders(pagination.pageNum + 1, pagination.pageSize)}
|
||||
disabled={pagination.pageNum >= Math.ceil(pagination.total / pagination.pageSize) || loading}
|
||||
>
|
||||
下一页
|
||||
<ChevronRight className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Detail Dialog */}
|
||||
<Dialog open={isDetailDialogOpen} onOpenChange={setIsDetailDialogOpen}>
|
||||
<DialogContent className="max-w-4xl max-h-[80vh] overflow-y-auto">
|
||||
<DialogContent className="max-w-7xl sm:max-w-7xl max-h-[90vh] overflow-y-auto w-[95vw]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>工单归档详情 - {selectedOrder?.id}</DialogTitle>
|
||||
<DialogDescription>查看完整的工单执行记录和签字确认</DialogDescription>
|
||||
<DialogTitle>工单归档详情 - {selectedOrder?.workOrderNumber}</DialogTitle>
|
||||
<DialogDescription>查看完整的工单执行记录</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
{selectedOrder && (
|
||||
@@ -322,49 +308,40 @@ export default function WorkOrderArchivePage() {
|
||||
<CardContent>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">工单标题</p>
|
||||
<p className="font-medium">{selectedOrder.title}</p>
|
||||
<p className="text-sm text-gray-600">工单编号</p>
|
||||
<p className="font-medium">{selectedOrder.workOrderNumber}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">工单类型</p>
|
||||
<p className="font-medium">{selectedOrder.workOrderType}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">商户名称</p>
|
||||
<p className="font-medium">{selectedOrder.merchant}</p>
|
||||
<p className="font-medium">{selectedOrder.merchantName}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">设备信息</p>
|
||||
<p className="font-medium">{selectedOrder.equipment}</p>
|
||||
<p className="font-medium">{selectedOrder.equipmentName}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">经销商</p>
|
||||
<p className="font-medium">{selectedOrder.dealer}</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Work Details */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-lg">作业详情</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">作业描述</p>
|
||||
<p className="font-medium">{selectedOrder.workDetails.description}</p>
|
||||
<p className="text-sm text-gray-600">维修工人</p>
|
||||
<p className="font-medium">{selectedOrder.workerName}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">使用材料</p>
|
||||
<div className="flex flex-wrap gap-2 mt-1">
|
||||
{selectedOrder.workDetails.materials.map((material, index) => (
|
||||
<Badge key={index} variant="outline">
|
||||
{material}
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
<p className="text-sm text-gray-600">优先级</p>
|
||||
<Badge className={getPriorityColor(selectedOrder.priority)}>{getPriorityText(selectedOrder.priority)}</Badge>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">作业备注</p>
|
||||
<p className="font-medium">{selectedOrder.workDetails.notes}</p>
|
||||
<p className="text-sm text-gray-600">负责人</p>
|
||||
<p className="font-medium">{selectedOrder.responsiblePerson}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">联系电话</p>
|
||||
<p className="font-medium">{selectedOrder.responsibleVirtualPhone}</p>
|
||||
</div>
|
||||
<div className="col-span-2">
|
||||
<p className="text-sm text-gray-600">地址</p>
|
||||
<p className="font-medium">{selectedOrder.merchantAddress}</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
@@ -376,90 +353,127 @@ export default function WorkOrderArchivePage() {
|
||||
<CardTitle className="text-lg">作业照片</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="grid grid-cols-2 gap-6">
|
||||
<div>
|
||||
<p className="text-sm text-gray-600 mb-2">作业前照片</p>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
{selectedOrder.workDetails.beforePhotos.map((photo, index) => (
|
||||
<img
|
||||
key={index}
|
||||
src={photo || "/placeholder.svg"}
|
||||
alt={`作业前照片 ${index + 1}`}
|
||||
className="w-full h-32 object-cover rounded border"
|
||||
/>
|
||||
))}
|
||||
<div className="space-y-4">
|
||||
{selectedOrder.frontImg && (
|
||||
<div>
|
||||
<p className="text-sm text-gray-600 mb-2">正面照</p>
|
||||
<div className="grid grid-cols-4 gap-2">
|
||||
{selectedOrder.frontImg.split(',').filter(url => url.trim()).map((photo, index) => (
|
||||
<img
|
||||
key={index}
|
||||
src={photo || "/placeholder.svg"}
|
||||
alt={`正面照 ${index + 1}`}
|
||||
className="w-full h-32 object-cover rounded border"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-600 mb-2">作业后照片</p>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
{selectedOrder.workDetails.afterPhotos.map((photo, index) => (
|
||||
<img
|
||||
key={index}
|
||||
src={photo || "/placeholder.svg"}
|
||||
alt={`作业后照片 ${index + 1}`}
|
||||
className="w-full h-32 object-cover rounded border"
|
||||
/>
|
||||
))}
|
||||
)}
|
||||
{selectedOrder.openImg && (
|
||||
<div>
|
||||
<p className="text-sm text-gray-600 mb-2">开箱照</p>
|
||||
<div className="grid grid-cols-4 gap-2">
|
||||
{selectedOrder.openImg.split(',').filter(url => url.trim()).map((photo, index) => (
|
||||
<img
|
||||
key={index}
|
||||
src={photo || "/placeholder.svg"}
|
||||
alt={`开箱照 ${index + 1}`}
|
||||
className="w-full h-32 object-cover rounded border"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{selectedOrder.ropeReImg && (
|
||||
<div>
|
||||
<p className="text-sm text-gray-600 mb-2">绳索恢复照</p>
|
||||
<div className="grid grid-cols-4 gap-2">
|
||||
{selectedOrder.ropeReImg.split(',').filter(url => url.trim()).map((photo, index) => (
|
||||
<img
|
||||
key={index}
|
||||
src={photo || "/placeholder.svg"}
|
||||
alt={`绳索恢复 ${index + 1}`}
|
||||
className="w-full h-32 object-cover rounded border"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{selectedOrder.hostReImg && (
|
||||
<div>
|
||||
<p className="text-sm text-gray-600 mb-2">主机恢复照</p>
|
||||
<div className="grid grid-cols-4 gap-2">
|
||||
{selectedOrder.hostReImg.split(',').filter(url => url.trim()).map((photo, index) => (
|
||||
<img
|
||||
key={index}
|
||||
src={photo || "/placeholder.svg"}
|
||||
alt={`主机恢复 ${index + 1}`}
|
||||
className="w-full h-32 object-cover rounded border"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{selectedOrder.otherImg && (
|
||||
<div>
|
||||
<p className="text-sm text-gray-600 mb-2">其他照片</p>
|
||||
<div className="grid grid-cols-4 gap-2">
|
||||
{selectedOrder.otherImg.split(',').filter(url => url.trim()).map((photo, index) => (
|
||||
<img
|
||||
key={index}
|
||||
src={photo || "/placeholder.svg"}
|
||||
alt={`其他照片 ${index + 1}`}
|
||||
className="w-full h-32 object-cover rounded border"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{selectedOrder.repairImg && (
|
||||
<div>
|
||||
<p className="text-sm text-gray-600 mb-2">维修照片</p>
|
||||
<div className="grid grid-cols-4 gap-2">
|
||||
{selectedOrder.repairImg.split(',').filter(url => url.trim()).map((photo, index) => (
|
||||
<img
|
||||
key={index}
|
||||
src={photo || "/placeholder.svg"}
|
||||
alt={`维修照片 ${index + 1}`}
|
||||
className="w-full h-32 object-cover rounded border"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Signatures */}
|
||||
{/* Status Info */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-lg">签字确认</CardTitle>
|
||||
<CardTitle className="text-lg">状态信息</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
{/* Worker Signature */}
|
||||
<div className="space-y-3">
|
||||
<h4 className="font-medium text-green-700">维修工人确认</h4>
|
||||
<div className="border rounded p-3">
|
||||
<p className="text-sm text-gray-600">签字人:{selectedOrder.signatures.worker.name}</p>
|
||||
<p className="text-sm text-gray-600">时间:{selectedOrder.signatures.worker.timestamp}</p>
|
||||
<div className="mt-2">
|
||||
<img
|
||||
src={selectedOrder.signatures.worker.signature || "/placeholder.svg"}
|
||||
alt="工人签字"
|
||||
className="w-full h-16 object-contain border rounded"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">是否需要维修</p>
|
||||
<Badge variant={selectedOrder.needRepair ? "destructive" : "outline"}>
|
||||
{selectedOrder.needRepair ? "需要维修" : "无需维修"}
|
||||
</Badge>
|
||||
</div>
|
||||
|
||||
{/* Merchant Signature */}
|
||||
<div className="space-y-3">
|
||||
<h4 className="font-medium text-blue-700">商户负责人验收</h4>
|
||||
<div className="border rounded p-3">
|
||||
<p className="text-sm text-gray-600">签字人:{selectedOrder.signatures.merchant.name}</p>
|
||||
<p className="text-sm text-gray-600">时间:{selectedOrder.signatures.merchant.timestamp}</p>
|
||||
<div className="mt-2">
|
||||
<img
|
||||
src={selectedOrder.signatures.merchant.signature || "/placeholder.svg"}
|
||||
alt="商户签字"
|
||||
className="w-full h-16 object-contain border rounded"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">设备是否正常</p>
|
||||
<Badge variant={selectedOrder.equNormal ? "default" : "destructive"}>
|
||||
{selectedOrder.equNormal ? "正常" : "异常"}
|
||||
</Badge>
|
||||
</div>
|
||||
|
||||
{/* Dealer Admin Signature */}
|
||||
<div className="space-y-3">
|
||||
<h4 className="font-medium text-purple-700">经销商管理员确认</h4>
|
||||
<div className="border rounded p-3">
|
||||
<p className="text-sm text-gray-600">签字人:{selectedOrder.signatures.dealerAdmin.name}</p>
|
||||
<p className="text-sm text-gray-600">时间:{selectedOrder.signatures.dealerAdmin.timestamp}</p>
|
||||
<div className="mt-2">
|
||||
<img
|
||||
src={selectedOrder.signatures.dealerAdmin.signature || "/placeholder.svg"}
|
||||
alt="经销商管理员签字"
|
||||
className="w-full h-16 object-contain border rounded"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">创建时间</p>
|
||||
<p className="font-medium">{selectedOrder.createdAt}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">更新时间</p>
|
||||
<p className="font-medium">{selectedOrder.updatedAt}</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
|
Reference in New Issue
Block a user