工单
This commit is contained in:
@@ -23,12 +23,12 @@ import {
|
|||||||
CheckCircle,
|
CheckCircle,
|
||||||
User,
|
User,
|
||||||
MapPin,
|
MapPin,
|
||||||
MoreHorizontal,
|
|
||||||
ChevronLeft,
|
ChevronLeft,
|
||||||
ChevronRight,
|
ChevronRight,
|
||||||
Wrench,
|
Wrench,
|
||||||
|
Edit,
|
||||||
} from "lucide-react"
|
} from "lucide-react"
|
||||||
import { apiGet, apiPost } from "../../lib/services/api"
|
import { apiGet, apiPost, apiPut } from "../../lib/services/api"
|
||||||
|
|
||||||
// 商户数据类型接口
|
// 商户数据类型接口
|
||||||
interface ProvinceMerchant {
|
interface ProvinceMerchant {
|
||||||
@@ -157,6 +157,8 @@ export default function WorkOrdersPage() {
|
|||||||
const [statusFilter, setStatusFilter] = useState("all")
|
const [statusFilter, setStatusFilter] = useState("all")
|
||||||
const [workerFilter, setWorkerFilter] = useState("all")
|
const [workerFilter, setWorkerFilter] = useState("all")
|
||||||
const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false)
|
const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false)
|
||||||
|
const [isEditDialogOpen, setIsEditDialogOpen] = useState(false)
|
||||||
|
const [editingWorkOrder, setEditingWorkOrder] = useState<WorkOrder | null>(null)
|
||||||
const [workOrders, setWorkOrders] = useState<WorkOrder[]>([])
|
const [workOrders, setWorkOrders] = useState<WorkOrder[]>([])
|
||||||
const [loadingWorkOrders, setLoadingWorkOrders] = useState(false)
|
const [loadingWorkOrders, setLoadingWorkOrders] = useState(false)
|
||||||
const [totalWorkOrders, setTotalWorkOrders] = useState(0)
|
const [totalWorkOrders, setTotalWorkOrders] = useState(0)
|
||||||
@@ -302,6 +304,27 @@ export default function WorkOrdersPage() {
|
|||||||
}} />
|
}} />
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
|
{/* 编辑工单对话框 */}
|
||||||
|
<Dialog open={isEditDialogOpen} onOpenChange={setIsEditDialogOpen}>
|
||||||
|
<DialogContent className="max-w-2xl max-h-[90vh] overflow-y-auto">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>编辑工单</DialogTitle>
|
||||||
|
<DialogDescription>修改工单信息</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
{editingWorkOrder && (
|
||||||
|
<EditWorkOrderForm
|
||||||
|
workOrder={editingWorkOrder}
|
||||||
|
onClose={() => {
|
||||||
|
setIsEditDialogOpen(false)
|
||||||
|
setEditingWorkOrder(null)
|
||||||
|
fetchWorkOrders(currentPage, pageSize)
|
||||||
|
fetchStatusCounts()
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Stats Cards */}
|
{/* Stats Cards */}
|
||||||
@@ -503,8 +526,15 @@ export default function WorkOrdersPage() {
|
|||||||
</div>
|
</div>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Button variant="ghost" size="sm">
|
<Button
|
||||||
<MoreHorizontal className="h-4 w-4" />
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => {
|
||||||
|
setEditingWorkOrder(item)
|
||||||
|
setIsEditDialogOpen(true)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Edit className="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
@@ -692,7 +722,7 @@ function CreateWorkOrderForm({ onClose }: { onClose: () => void }) {
|
|||||||
|
|
||||||
// 厨房自动灭火设备 - kitchen_automatic_fire_extinguisher
|
// 厨房自动灭火设备 - kitchen_automatic_fire_extinguisher
|
||||||
if (equipmentType === "kitchen_automatic_fire_extinguisher" || equipmentType === "厨房自动灭火设备") {
|
if (equipmentType === "kitchen_automatic_fire_extinguisher" || equipmentType === "厨房自动灭火设备") {
|
||||||
return ["故障检测", "故障维修", "设备安装", "预防性维护", "设备改造", "设备拆除", "更换药剂"]
|
return ["故障检测", "故障维修", "设备安装", "设备改造", "设备拆除", "更换药剂"]
|
||||||
}
|
}
|
||||||
|
|
||||||
// 动火离人 - fire_extinguisher
|
// 动火离人 - fire_extinguisher
|
||||||
@@ -701,7 +731,7 @@ function CreateWorkOrderForm({ onClose }: { onClose: () => void }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 默认返回所有类型
|
// 默认返回所有类型
|
||||||
return ["故障检测", "故障维修", "设备安装", "预防性维护", "设备改造", "设备拆除", "更换药剂"]
|
return ["故障检测", "故障维修", "设备安装", "设备改造", "设备拆除", "更换药剂"]
|
||||||
}
|
}
|
||||||
|
|
||||||
// 切换工人选择
|
// 切换工人选择
|
||||||
@@ -965,3 +995,383 @@ function CreateWorkOrderForm({ onClose }: { onClose: () => void }) {
|
|||||||
</form>
|
</form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function EditWorkOrderForm({ workOrder, onClose }: { workOrder: WorkOrder; onClose: () => void }) {
|
||||||
|
const [formData, setFormData] = useState({
|
||||||
|
type: workOrder.workOrderType || "",
|
||||||
|
assignee: workOrder.workersId ? workOrder.workersId.split(",") : [] as string[],
|
||||||
|
description: workOrder.remark || "",
|
||||||
|
status: workOrder.status || "1",
|
||||||
|
})
|
||||||
|
|
||||||
|
const [selectedMerchant, setSelectedMerchant] = useState("")
|
||||||
|
const [availableEquipment, setAvailableEquipment] = useState<Equipment[]>([])
|
||||||
|
const [merchants, setMerchants] = useState<ProvinceMerchant[]>([])
|
||||||
|
const [workers, setWorkers] = useState<Worker[]>([])
|
||||||
|
const [loadingWorkers, setLoadingWorkers] = useState(false)
|
||||||
|
const [submitting, setSubmitting] = useState(false)
|
||||||
|
const [isWorkerSelectOpen, setIsWorkerSelectOpen] = useState(false)
|
||||||
|
|
||||||
|
// 初始化表单数据
|
||||||
|
useEffect(() => {
|
||||||
|
// 查找商户
|
||||||
|
const findMerchant = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiGet('/back/general/provinceMerchants')
|
||||||
|
if (response.code === 200) {
|
||||||
|
const merchantList = response.data || []
|
||||||
|
setMerchants(merchantList)
|
||||||
|
// 根据商户名称或ID查找对应的商户
|
||||||
|
const foundMerchant = merchantList.find((m: ProvinceMerchant) =>
|
||||||
|
m.merchantName === workOrder.merchantName ||
|
||||||
|
m.merchantsId === workOrder.merchantUserId ||
|
||||||
|
m.id === workOrder.merchantUserId
|
||||||
|
)
|
||||||
|
if (foundMerchant) {
|
||||||
|
setSelectedMerchant(foundMerchant.id)
|
||||||
|
// 获取该商户的设备列表
|
||||||
|
const merchantIdForEquipment = foundMerchant.merchantsId || foundMerchant.id
|
||||||
|
await fetchMerchantEquipments(merchantIdForEquipment)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取商户列表失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取工人列表
|
||||||
|
const loadWorkers = async () => {
|
||||||
|
setLoadingWorkers(true)
|
||||||
|
try {
|
||||||
|
const response = await apiGet('/back/workers/dis')
|
||||||
|
if (response.code === 200) {
|
||||||
|
const workerList = response.data || []
|
||||||
|
setWorkers(workerList)
|
||||||
|
// 根据工人名称匹配已选中的工人
|
||||||
|
if (workOrder.workerName) {
|
||||||
|
const workerNames = workOrder.workerName.split(",")
|
||||||
|
const matchedWorkerIds = workerList
|
||||||
|
.filter((w: Worker) => workerNames.includes(w.name))
|
||||||
|
.map((w: Worker) => w.id)
|
||||||
|
setFormData(prev => ({ ...prev, assignee: matchedWorkerIds }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取工人列表失败:', error)
|
||||||
|
} finally {
|
||||||
|
setLoadingWorkers(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
findMerchant()
|
||||||
|
loadWorkers()
|
||||||
|
}, [workOrder])
|
||||||
|
|
||||||
|
// 获取商户设备列表
|
||||||
|
const fetchMerchantEquipments = async (merchantId: string) => {
|
||||||
|
try {
|
||||||
|
const response = await apiGet(`/back/equipment/list?pageNum=1&pageSize=9999&merchantId=${merchantId}`)
|
||||||
|
if (response.code === 200) {
|
||||||
|
const equipmentList = response.rows || []
|
||||||
|
setAvailableEquipment(equipmentList)
|
||||||
|
// 查找当前工单对应的设备
|
||||||
|
const foundEquipment = equipmentList.find((e: Equipment) =>
|
||||||
|
e.equipmentId === workOrder.equipmentId
|
||||||
|
)
|
||||||
|
if (foundEquipment) {
|
||||||
|
setFormData(prev => ({ ...prev, type: workOrder.workOrderType || "" }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取设备列表失败:', error)
|
||||||
|
setAvailableEquipment([])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 点击外部关闭下拉框
|
||||||
|
useEffect(() => {
|
||||||
|
const handleClickOutside = (event: MouseEvent) => {
|
||||||
|
if (isWorkerSelectOpen) {
|
||||||
|
const target = event.target as HTMLElement
|
||||||
|
if (!target.closest('.worker-select-container')) {
|
||||||
|
setIsWorkerSelectOpen(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('mousedown', handleClickOutside)
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener('mousedown', handleClickOutside)
|
||||||
|
}
|
||||||
|
}, [isWorkerSelectOpen])
|
||||||
|
|
||||||
|
// 根据设备类型获取可用的工单类型
|
||||||
|
const getAvailableWorkOrderTypes = () => {
|
||||||
|
if (!workOrder.equipmentId) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectedEquipment = availableEquipment.find(e => e.equipmentId === workOrder.equipmentId)
|
||||||
|
if (!selectedEquipment) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
const equipmentType = selectedEquipment.equipmentType
|
||||||
|
|
||||||
|
// 厨房自动灭火设备
|
||||||
|
if (equipmentType === "kitchen_automatic_fire_extinguisher" || equipmentType === "厨房自动灭火设备") {
|
||||||
|
return ["故障检测", "故障维修", "设备安装", "设备改造", "设备拆除", "更换药剂"]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 动火离人
|
||||||
|
if (equipmentType === "fire_extinguisher" || equipmentType === "动火离人") {
|
||||||
|
return ["故障维修", "设备安装", "设备改造", "设备拆除"]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认返回所有类型
|
||||||
|
return ["故障检测", "故障维修", "设备安装", "设备改造", "设备拆除", "更换药剂"]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切换工人选择
|
||||||
|
const toggleWorkerSelection = (workerId: string) => {
|
||||||
|
setFormData(prev => ({
|
||||||
|
...prev,
|
||||||
|
assignee: prev.assignee.includes(workerId)
|
||||||
|
? prev.assignee.filter(id => id !== workerId)
|
||||||
|
: [...prev.assignee, workerId]
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取选中工人的显示文本
|
||||||
|
const getSelectedWorkersText = () => {
|
||||||
|
if (formData.assignee.length === 0) return "选择维修工人"
|
||||||
|
if (formData.assignee.length === 1) {
|
||||||
|
const worker = workers.find(w => w.id === formData.assignee[0])
|
||||||
|
return worker ? worker.name : "1位工人"
|
||||||
|
}
|
||||||
|
return `已选择 ${formData.assignee.length} 位工人`
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
if (formData.assignee.length === 0) {
|
||||||
|
alert('请至少选择一位工人')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setSubmitting(true)
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 找到选中的商户信息
|
||||||
|
const selectedMerchantObj = merchants.find(m => m.id === selectedMerchant)
|
||||||
|
// 找到选中的设备信息
|
||||||
|
const selectedEquipmentObj = availableEquipment.find(e => e.equipmentId === workOrder.equipmentId)
|
||||||
|
// 找到所有选中的工人信息
|
||||||
|
const selectedWorkers = workers.filter(w => formData.assignee.includes(w.id))
|
||||||
|
|
||||||
|
if (!selectedMerchantObj || !selectedEquipmentObj || selectedWorkers.length === 0) {
|
||||||
|
alert('无法获取完整的商户、设备或工人信息')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 拼接工人ID(使用逗号分隔)
|
||||||
|
const workersIds = selectedWorkers.map(w => w.workersId || "").join(",")
|
||||||
|
// 拼接工人名称(使用逗号分隔)
|
||||||
|
const workerNames = selectedWorkers.map(w => w.name).join(",")
|
||||||
|
// 拼接工人电话(使用逗号分隔)
|
||||||
|
const workerPhones = selectedWorkers.map(w => w.phone).join(",")
|
||||||
|
// 使用第一个工人的经销商ID
|
||||||
|
const distributorUserId = selectedWorkers[0].distributorUserId || ""
|
||||||
|
|
||||||
|
// 构建API请求数据
|
||||||
|
const requestData = {
|
||||||
|
id: workOrder.id,
|
||||||
|
merchantUserId: selectedMerchantObj.merchantsId || workOrder.merchantUserId,
|
||||||
|
distributorUserId: distributorUserId || workOrder.distributorUserId,
|
||||||
|
workersId: workersIds,
|
||||||
|
workOrderNumber: workOrder.workOrderNumber,
|
||||||
|
workOrderType: formData.type,
|
||||||
|
workOrderSubtype: workOrder.workOrderSubtype || "",
|
||||||
|
equipmentId: workOrder.equipmentId,
|
||||||
|
equipmentName: selectedEquipmentObj.equipmentName || workOrder.equipmentName,
|
||||||
|
merchantName: selectedMerchantObj.merchantName || workOrder.merchantName,
|
||||||
|
merchantLocation: selectedMerchantObj.mallLocation || workOrder.merchantLocation || "",
|
||||||
|
merchantAddress: selectedMerchantObj.fullAddress || workOrder.merchantAddress,
|
||||||
|
merchantCity: selectedMerchantObj.city || workOrder.merchantCity || "",
|
||||||
|
merchantDistrict: selectedMerchantObj.district || workOrder.merchantDistrict || "",
|
||||||
|
responsiblePerson: selectedMerchantObj.contactPerson || workOrder.responsiblePerson,
|
||||||
|
responsibleVirtualPhone: selectedMerchantObj.contactPhone || workOrder.responsibleVirtualPhone,
|
||||||
|
workerVirtualPhone: workerPhones,
|
||||||
|
workerName: workerNames,
|
||||||
|
status: formData.status,
|
||||||
|
createdDate: workOrder.createdDate,
|
||||||
|
completedDate: workOrder.completedDate || "",
|
||||||
|
remark: formData.description
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('更新工单请求数据:', requestData)
|
||||||
|
|
||||||
|
const response = await apiPut('/back/orders', requestData)
|
||||||
|
|
||||||
|
if (response.code === 200) {
|
||||||
|
alert('工单更新成功!')
|
||||||
|
onClose()
|
||||||
|
} else {
|
||||||
|
alert(`更新工单失败: ${response.msg || '未知错误'}`)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('更新工单失败:', error)
|
||||||
|
alert('更新工单失败,请稍后重试')
|
||||||
|
} finally {
|
||||||
|
setSubmitting(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form onSubmit={handleSubmit} className="space-y-4">
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label>商户信息</Label>
|
||||||
|
<div className="p-3 bg-gray-50 rounded-md">
|
||||||
|
<div className="text-sm font-medium">{workOrder.merchantName}</div>
|
||||||
|
<div className="text-xs text-gray-500 mt-1">{workOrder.merchantLocation || "无商场"}</div>
|
||||||
|
<div className="text-xs text-gray-500">{workOrder.merchantAddress}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label>设备信息</Label>
|
||||||
|
<div className="p-3 bg-gray-50 rounded-md">
|
||||||
|
<div className="text-sm font-medium">{workOrder.equipmentName}</div>
|
||||||
|
<div className="text-xs text-gray-500 mt-1">设备ID: {workOrder.equipmentId}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label>工单编号</Label>
|
||||||
|
<div className="p-3 bg-gray-50 rounded-md">
|
||||||
|
<div className="text-sm font-medium">{workOrder.workOrderNumber}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="type">工单类型</Label>
|
||||||
|
<Select
|
||||||
|
value={formData.type}
|
||||||
|
onValueChange={(value) => setFormData({ ...formData, type: value })}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="w-full">
|
||||||
|
<SelectValue placeholder="选择类型" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent className="max-h-[300px]">
|
||||||
|
{getAvailableWorkOrderTypes().map((type) => (
|
||||||
|
<SelectItem key={type} value={type}>
|
||||||
|
{type}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="status">工单状态</Label>
|
||||||
|
<Select
|
||||||
|
value={formData.status}
|
||||||
|
onValueChange={(value) => setFormData({ ...formData, status: value })}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="w-full">
|
||||||
|
<SelectValue placeholder="选择状态" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent className="max-h-[300px]">
|
||||||
|
<SelectItem value="1">待接单</SelectItem>
|
||||||
|
<SelectItem value="2">已接单</SelectItem>
|
||||||
|
<SelectItem value="3">订单进行中</SelectItem>
|
||||||
|
<SelectItem value="4">订单维修中</SelectItem>
|
||||||
|
<SelectItem value="5">核对检测信息</SelectItem>
|
||||||
|
<SelectItem value="6">待商户签字</SelectItem>
|
||||||
|
<SelectItem value="7">订单已完成</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="assignee">分配工人(可多选)</Label>
|
||||||
|
<div className="relative worker-select-container">
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="outline"
|
||||||
|
className="w-full justify-between"
|
||||||
|
onClick={() => {
|
||||||
|
setIsWorkerSelectOpen(!isWorkerSelectOpen)
|
||||||
|
if (!isWorkerSelectOpen && workers.length === 0 && !loadingWorkers) {
|
||||||
|
// 已经在useEffect中加载了
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className="truncate">{loadingWorkers ? "加载中..." : getSelectedWorkersText()}</span>
|
||||||
|
<ChevronRight className={`h-4 w-4 ml-2 transition-transform ${isWorkerSelectOpen ? 'rotate-90' : ''}`} />
|
||||||
|
</Button>
|
||||||
|
{isWorkerSelectOpen && (
|
||||||
|
<div className="absolute z-50 w-full mt-1 bg-white border rounded-md shadow-lg max-h-[300px] overflow-y-auto">
|
||||||
|
{workers.length === 0 ? (
|
||||||
|
<div className="p-4 text-center text-gray-500">暂无工人数据</div>
|
||||||
|
) : (
|
||||||
|
<div className="p-2">
|
||||||
|
{workers.map((worker) => (
|
||||||
|
<div
|
||||||
|
key={worker.id}
|
||||||
|
className="flex items-center space-x-2 p-2 hover:bg-gray-100 rounded cursor-pointer"
|
||||||
|
onClick={() => toggleWorkerSelection(worker.id)}
|
||||||
|
>
|
||||||
|
<div className={`w-4 h-4 border rounded flex items-center justify-center ${
|
||||||
|
formData.assignee.includes(worker.id) ? 'bg-blue-600 border-blue-600' : 'border-gray-300'
|
||||||
|
}`}>
|
||||||
|
{formData.assignee.includes(worker.id) && (
|
||||||
|
<svg className="w-3 h-3 text-white" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<span className="text-sm flex-1">
|
||||||
|
{worker.name} - {worker.province} ({worker.phone})
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{formData.assignee.length > 0 && (
|
||||||
|
<div className="text-xs text-gray-500 mt-1">
|
||||||
|
已选择: {workers.filter(w => formData.assignee.includes(w.id)).map(w => w.name).join(", ")}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="description">工单描述</Label>
|
||||||
|
<Textarea
|
||||||
|
id="description"
|
||||||
|
placeholder="请描述需要执行的工作内容..."
|
||||||
|
value={formData.description}
|
||||||
|
onChange={(e) => setFormData({ ...formData, description: e.target.value })}
|
||||||
|
rows={3}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex justify-end space-x-2">
|
||||||
|
<Button type="button" variant="outline" onClick={onClose} disabled={submitting}>
|
||||||
|
取消
|
||||||
|
</Button>
|
||||||
|
<Button type="submit" disabled={submitting}>
|
||||||
|
{submitting ? "更新中..." : "更新工单"}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user