|
|
@@ -0,0 +1,590 @@
|
|
|
+import React, { useState, useEffect } from 'react';
|
|
|
+import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
|
+import { Button } from '@d8d/shared-ui-components/components/ui/button';
|
|
|
+import {
|
|
|
+ Dialog,
|
|
|
+ DialogContent,
|
|
|
+ DialogDescription,
|
|
|
+ DialogFooter,
|
|
|
+ DialogHeader,
|
|
|
+ DialogTitle,
|
|
|
+} from '@d8d/shared-ui-components/components/ui/dialog';
|
|
|
+import {
|
|
|
+ Form,
|
|
|
+ FormControl,
|
|
|
+ FormDescription,
|
|
|
+ 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 { Input } from '@d8d/shared-ui-components/components/ui/input';
|
|
|
+import { Textarea } from '@d8d/shared-ui-components/components/ui/textarea';
|
|
|
+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 { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@d8d/shared-ui-components/components/ui/card';
|
|
|
+import { Separator } from '@d8d/shared-ui-components/components/ui/separator';
|
|
|
+import { useForm } from 'react-hook-form';
|
|
|
+import { zodResolver } from '@hookform/resolvers/zod';
|
|
|
+import { z } from 'zod';
|
|
|
+import { toast } from 'sonner';
|
|
|
+import { FileText, Trash2, Eye, User, Plus } from 'lucide-react';
|
|
|
+import { FileSelector } from '@d8d/file-management-ui/components';
|
|
|
+import { AssetType, AssetFileType } from '@d8d/allin-order-module';
|
|
|
+import { orderClient } from '../api/orderClient';
|
|
|
+import type { OrderPersonAssetListItem } from '../api/types';
|
|
|
+
|
|
|
+// 资产关联表单Schema
|
|
|
+const assetAssociationSchema = z.object({
|
|
|
+ orderId: z.number().int().positive(),
|
|
|
+ personId: z.number().int().positive('请选择残疾人'),
|
|
|
+ assetType: z.nativeEnum(AssetType),
|
|
|
+ assetFileType: z.nativeEnum(AssetFileType),
|
|
|
+ fileId: z.number().int().positive('请选择文件'),
|
|
|
+ relatedTime: z.string().datetime('请选择有效的关联时间'),
|
|
|
+ remark: z.string().optional(),
|
|
|
+});
|
|
|
+
|
|
|
+type AssetAssociationFormValues = z.infer<typeof assetAssociationSchema>;
|
|
|
+
|
|
|
+interface OrderPersonAssetAssociationProps {
|
|
|
+ orderId: number;
|
|
|
+ personId?: number;
|
|
|
+ open: boolean;
|
|
|
+ onOpenChange: (open: boolean) => void;
|
|
|
+ onSuccess?: () => void;
|
|
|
+}
|
|
|
+
|
|
|
+// 残疾人信息接口(需要从订单人员接口获取)
|
|
|
+interface DisabledPersonInfo {
|
|
|
+ id: number;
|
|
|
+ name: string;
|
|
|
+ disabilityId: string;
|
|
|
+ disabilityType: string;
|
|
|
+ disabilityLevel: string;
|
|
|
+}
|
|
|
+
|
|
|
+export const OrderPersonAssetAssociation: React.FC<OrderPersonAssetAssociationProps> = ({
|
|
|
+ orderId,
|
|
|
+ personId,
|
|
|
+ open,
|
|
|
+ onOpenChange,
|
|
|
+ onSuccess,
|
|
|
+}) => {
|
|
|
+ const queryClient = useQueryClient();
|
|
|
+ const [isSubmitting, setIsSubmitting] = useState(false);
|
|
|
+ const [selectedPerson, setSelectedPerson] = useState<DisabledPersonInfo | null>(null);
|
|
|
+ const [showAssetForm, setShowAssetForm] = useState(false);
|
|
|
+
|
|
|
+ // 初始化表单
|
|
|
+ const form = useForm<AssetAssociationFormValues>({
|
|
|
+ resolver: zodResolver(assetAssociationSchema),
|
|
|
+ defaultValues: {
|
|
|
+ orderId,
|
|
|
+ personId: personId || 0,
|
|
|
+ assetType: AssetType.OTHER,
|
|
|
+ assetFileType: AssetFileType.IMAGE,
|
|
|
+ fileId: 0,
|
|
|
+ relatedTime: new Date().toISOString(),
|
|
|
+ remark: '',
|
|
|
+ },
|
|
|
+ });
|
|
|
+
|
|
|
+ // 查询订单人员列表(这里需要根据实际API调整)
|
|
|
+ const { data: orderPersonsData, isLoading: isLoadingPersons } = useQuery({
|
|
|
+ queryKey: ['order-persons', orderId],
|
|
|
+ queryFn: async () => {
|
|
|
+ // 这里应该调用订单人员查询API
|
|
|
+ // 暂时返回模拟数据
|
|
|
+ return {
|
|
|
+ data: [
|
|
|
+ { id: 1, name: '张三', disabilityId: 'C123456', disabilityType: '肢体残疾', disabilityLevel: '二级' },
|
|
|
+ { id: 2, name: '李四', disabilityId: 'C234567', disabilityType: '视力残疾', disabilityLevel: '三级' },
|
|
|
+ { id: 3, name: '王五', disabilityId: 'C345678', disabilityType: '听力残疾', disabilityLevel: '一级' },
|
|
|
+ ] as DisabledPersonInfo[]
|
|
|
+ };
|
|
|
+ },
|
|
|
+ enabled: open,
|
|
|
+ });
|
|
|
+
|
|
|
+ // 查询订单人员资产列表
|
|
|
+ const { data: assetsData, isLoading: isLoadingAssets, refetch: refetchAssets } = useQuery({
|
|
|
+ queryKey: ['order-assets', orderId, selectedPerson?.id],
|
|
|
+ queryFn: async () => {
|
|
|
+ const response = await orderClient.assets.query.$get({
|
|
|
+ query: {
|
|
|
+ orderId,
|
|
|
+ personId: selectedPerson?.id,
|
|
|
+ page: 1,
|
|
|
+ limit: 100, // 注意:后端API使用limit而不是pageSize
|
|
|
+ },
|
|
|
+ });
|
|
|
+ if (!response.ok) {
|
|
|
+ const error = await response.json();
|
|
|
+ throw new Error(error.message || '查询资产失败');
|
|
|
+ }
|
|
|
+ return response.json();
|
|
|
+ },
|
|
|
+ enabled: open && !!selectedPerson,
|
|
|
+ });
|
|
|
+
|
|
|
+ // 创建资产关联Mutation
|
|
|
+ const createMutation = useMutation({
|
|
|
+ mutationFn: async (data: AssetAssociationFormValues) => {
|
|
|
+ const response = await orderClient.assets.create.$post({
|
|
|
+ json: data,
|
|
|
+ });
|
|
|
+ if (!response.ok) {
|
|
|
+ const error = await response.json();
|
|
|
+ throw new Error(error.message || '创建资产关联失败');
|
|
|
+ }
|
|
|
+ return response.json();
|
|
|
+ },
|
|
|
+ onSuccess: () => {
|
|
|
+ toast.success('资产关联创建成功');
|
|
|
+ queryClient.invalidateQueries({ queryKey: ['order-assets'] });
|
|
|
+ refetchAssets();
|
|
|
+ setShowAssetForm(false);
|
|
|
+ form.reset();
|
|
|
+ onSuccess?.();
|
|
|
+ },
|
|
|
+ onError: (error: Error) => {
|
|
|
+ toast.error(`创建资产关联失败: ${error.message}`);
|
|
|
+ },
|
|
|
+ });
|
|
|
+
|
|
|
+ // 删除资产关联Mutation
|
|
|
+ const deleteMutation = useMutation({
|
|
|
+ mutationFn: async (assetId: number) => {
|
|
|
+ const response = await orderClient.assets.delete[':id'].$delete({
|
|
|
+ param: { id: assetId },
|
|
|
+ });
|
|
|
+ if (!response.ok) {
|
|
|
+ const error = await response.json();
|
|
|
+ throw new Error(error.message || '删除资产关联失败');
|
|
|
+ }
|
|
|
+ return response.json();
|
|
|
+ },
|
|
|
+ onSuccess: () => {
|
|
|
+ toast.success('资产删除成功');
|
|
|
+ queryClient.invalidateQueries({ queryKey: ['order-assets'] });
|
|
|
+ refetchAssets();
|
|
|
+ },
|
|
|
+ onError: (error: Error) => {
|
|
|
+ toast.error(`删除资产关联失败: ${error.message}`);
|
|
|
+ },
|
|
|
+ });
|
|
|
+
|
|
|
+ // 处理表单提交
|
|
|
+ const onSubmit = async (data: AssetAssociationFormValues) => {
|
|
|
+ setIsSubmitting(true);
|
|
|
+ try {
|
|
|
+ await createMutation.mutateAsync(data);
|
|
|
+ } finally {
|
|
|
+ setIsSubmitting(false);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 处理文件选择
|
|
|
+ const handleFileChange = (fileId: number | null | number[]) => {
|
|
|
+ if (fileId !== null && !Array.isArray(fileId)) {
|
|
|
+ form.setValue('fileId', fileId, { shouldValidate: true });
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 处理残疾人选择
|
|
|
+ const handlePersonSelect = (person: DisabledPersonInfo) => {
|
|
|
+ setSelectedPerson(person);
|
|
|
+ form.setValue('personId', person.id, { shouldValidate: true });
|
|
|
+ setShowAssetForm(false);
|
|
|
+ };
|
|
|
+
|
|
|
+ // 处理添加资产
|
|
|
+ const handleAddAsset = () => {
|
|
|
+ if (!selectedPerson) {
|
|
|
+ toast.error('请先选择残疾人');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ setShowAssetForm(true);
|
|
|
+ };
|
|
|
+
|
|
|
+ // 处理删除资产
|
|
|
+ const handleDeleteAsset = (assetId: number) => {
|
|
|
+ if (window.confirm('确定要删除这个资产吗?')) {
|
|
|
+ deleteMutation.mutate(assetId);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 资产类型选项
|
|
|
+ const assetTypeOptions = [
|
|
|
+ { value: AssetType.DISABILITY_CERT, label: '残疾证明' },
|
|
|
+ { value: AssetType.TAX, label: '税务文件' },
|
|
|
+ { value: AssetType.SALARY, label: '薪资单' },
|
|
|
+ { value: AssetType.JOB_RESULT, label: '工作成果' },
|
|
|
+ { value: AssetType.CONTRACT_SIGN, label: '合同签署' },
|
|
|
+ { value: AssetType.OTHER, label: '其他' },
|
|
|
+ ];
|
|
|
+
|
|
|
+ // 资产文件类型选项
|
|
|
+ const assetFileTypeOptions = [
|
|
|
+ { value: AssetFileType.IMAGE, label: '图片' },
|
|
|
+ { value: AssetFileType.VIDEO, label: '视频' },
|
|
|
+ ];
|
|
|
+
|
|
|
+ // 获取资产类型标签
|
|
|
+ const getAssetTypeLabel = (type: string) => {
|
|
|
+ const option = assetTypeOptions.find(opt => opt.value === type as AssetType);
|
|
|
+ return option?.label || type;
|
|
|
+ };
|
|
|
+
|
|
|
+ // 获取资产文件类型标签
|
|
|
+ const getAssetFileTypeLabel = (type: string) => {
|
|
|
+ const option = assetFileTypeOptions.find(opt => opt.value === type as AssetFileType);
|
|
|
+ return option?.label || type;
|
|
|
+ };
|
|
|
+
|
|
|
+ // 重置表单
|
|
|
+ const resetForm = () => {
|
|
|
+ form.reset({
|
|
|
+ orderId,
|
|
|
+ personId: selectedPerson?.id || 0,
|
|
|
+ assetType: AssetType.OTHER,
|
|
|
+ assetFileType: AssetFileType.IMAGE,
|
|
|
+ fileId: 0,
|
|
|
+ relatedTime: new Date().toISOString(),
|
|
|
+ remark: '',
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ // 当对话框关闭时重置状态
|
|
|
+ useEffect(() => {
|
|
|
+ if (!open) {
|
|
|
+ setSelectedPerson(null);
|
|
|
+ setShowAssetForm(false);
|
|
|
+ resetForm();
|
|
|
+ }
|
|
|
+ }, [open]);
|
|
|
+
|
|
|
+ // 如果传入personId,自动选择该残疾人
|
|
|
+ useEffect(() => {
|
|
|
+ if (open && personId && orderPersonsData?.data) {
|
|
|
+ const person = orderPersonsData.data.find(p => p.id === personId);
|
|
|
+ if (person) {
|
|
|
+ handlePersonSelect(person);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, [open, personId, orderPersonsData]);
|
|
|
+
|
|
|
+ return (
|
|
|
+ <Dialog open={open} onOpenChange={onOpenChange}>
|
|
|
+ <DialogContent className="sm:max-w-[900px] max-h-[90vh] overflow-y-auto">
|
|
|
+ <DialogHeader>
|
|
|
+ <DialogTitle>订单人员资产管理</DialogTitle>
|
|
|
+ <DialogDescription>
|
|
|
+ 为订单中的残疾人管理资产文件(残疾证明、税务文件、薪资单等)
|
|
|
+ </DialogDescription>
|
|
|
+ </DialogHeader>
|
|
|
+
|
|
|
+ <div className="space-y-6">
|
|
|
+ {/* 残疾人选择区域 */}
|
|
|
+ <Card>
|
|
|
+ <CardHeader>
|
|
|
+ <CardTitle className="text-lg flex items-center">
|
|
|
+ <User className="mr-2 h-5 w-5" />
|
|
|
+ 选择残疾人
|
|
|
+ </CardTitle>
|
|
|
+ <CardDescription>
|
|
|
+ 从订单已添加的残疾人列表中选择
|
|
|
+ </CardDescription>
|
|
|
+ </CardHeader>
|
|
|
+ <CardContent>
|
|
|
+ {isLoadingPersons ? (
|
|
|
+ <div className="text-center py-4">加载残疾人列表...</div>
|
|
|
+ ) : orderPersonsData?.data && orderPersonsData.data.length > 0 ? (
|
|
|
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
|
|
|
+ {orderPersonsData.data.map((person) => (
|
|
|
+ <Card
|
|
|
+ key={person.id}
|
|
|
+ className={`cursor-pointer transition-colors ${selectedPerson?.id === person.id ? 'border-primary bg-primary/5' : 'hover:bg-accent'}`}
|
|
|
+ onClick={() => handlePersonSelect(person)}
|
|
|
+ >
|
|
|
+ <CardContent className="p-4">
|
|
|
+ <div className="font-medium">{person.name}</div>
|
|
|
+ <div className="text-sm text-muted-foreground mt-1">
|
|
|
+ <div>残疾证号: {person.disabilityId}</div>
|
|
|
+ <div>残疾类型: {person.disabilityType}</div>
|
|
|
+ <div>残疾等级: {person.disabilityLevel}</div>
|
|
|
+ </div>
|
|
|
+ </CardContent>
|
|
|
+ </Card>
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
+ ) : (
|
|
|
+ <div className="text-center py-4 text-muted-foreground">
|
|
|
+ 暂无残疾人数据
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+ </CardContent>
|
|
|
+ </Card>
|
|
|
+
|
|
|
+ {selectedPerson && (
|
|
|
+ <>
|
|
|
+ <Separator />
|
|
|
+
|
|
|
+ {/* 当前选择的残疾人信息 */}
|
|
|
+ <Card>
|
|
|
+ <CardHeader>
|
|
|
+ <CardTitle className="text-lg flex items-center justify-between">
|
|
|
+ <div className="flex items-center">
|
|
|
+ <User className="mr-2 h-5 w-5" />
|
|
|
+ {selectedPerson.name} 的资产文件
|
|
|
+ </div>
|
|
|
+ <Button onClick={handleAddAsset} size="sm">
|
|
|
+ <Plus className="mr-2 h-4 w-4" />
|
|
|
+ 添加资产
|
|
|
+ </Button>
|
|
|
+ </CardTitle>
|
|
|
+ <CardDescription>
|
|
|
+ 残疾证号: {selectedPerson.disabilityId} | 残疾类型: {selectedPerson.disabilityType} | 残疾等级: {selectedPerson.disabilityLevel}
|
|
|
+ </CardDescription>
|
|
|
+ </CardHeader>
|
|
|
+ </Card>
|
|
|
+
|
|
|
+ {/* 资产表格 */}
|
|
|
+ {isLoadingAssets ? (
|
|
|
+ <div className="text-center py-8">加载资产数据...</div>
|
|
|
+ ) : assetsData?.data && assetsData.data.length > 0 ? (
|
|
|
+ <div className="border rounded-md">
|
|
|
+ <Table>
|
|
|
+ <TableHeader>
|
|
|
+ <TableRow>
|
|
|
+ <TableHead>资产类型</TableHead>
|
|
|
+ <TableHead>文件类型</TableHead>
|
|
|
+ <TableHead>关联时间</TableHead>
|
|
|
+ <TableHead>备注</TableHead>
|
|
|
+ <TableHead>操作</TableHead>
|
|
|
+ </TableRow>
|
|
|
+ </TableHeader>
|
|
|
+ <TableBody>
|
|
|
+ {assetsData.data.map((asset) => (
|
|
|
+ <TableRow key={asset.id}>
|
|
|
+ <TableCell>
|
|
|
+ <Badge variant="outline">
|
|
|
+ {getAssetTypeLabel(asset.assetType)}
|
|
|
+ </Badge>
|
|
|
+ </TableCell>
|
|
|
+ <TableCell>
|
|
|
+ <Badge variant="secondary">
|
|
|
+ {getAssetFileTypeLabel(asset.assetFileType)}
|
|
|
+ </Badge>
|
|
|
+ </TableCell>
|
|
|
+ <TableCell>
|
|
|
+ {new Date(asset.relatedTime).toLocaleString()}
|
|
|
+ </TableCell>
|
|
|
+ <TableCell className="max-w-[200px] truncate">
|
|
|
+ {asset.remark || '-'}
|
|
|
+ </TableCell>
|
|
|
+ <TableCell>
|
|
|
+ <div className="flex space-x-2">
|
|
|
+ <Button
|
|
|
+ variant="ghost"
|
|
|
+ size="sm"
|
|
|
+ onClick={() => window.open(`/api/files/${asset.fileId}/download`, '_blank')}
|
|
|
+ >
|
|
|
+ <Eye className="h-4 w-4" />
|
|
|
+ </Button>
|
|
|
+ <Button
|
|
|
+ variant="ghost"
|
|
|
+ size="sm"
|
|
|
+ onClick={() => handleDeleteAsset(asset.id)}
|
|
|
+ disabled={deleteMutation.isPending}
|
|
|
+ >
|
|
|
+ <Trash2 className="h-4 w-4" />
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ </TableCell>
|
|
|
+ </TableRow>
|
|
|
+ ))}
|
|
|
+ </TableBody>
|
|
|
+ </Table>
|
|
|
+ </div>
|
|
|
+ ) : (
|
|
|
+ <div className="text-center py-8 border rounded-md">
|
|
|
+ <FileText className="h-12 w-12 mx-auto text-muted-foreground mb-2" />
|
|
|
+ <div className="text-muted-foreground">暂无资产文件</div>
|
|
|
+ <div className="text-sm text-muted-foreground mt-1">
|
|
|
+ 点击"添加资产"按钮为残疾人上传资产文件
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+
|
|
|
+ {/* 添加资产表单 */}
|
|
|
+ {showAssetForm && (
|
|
|
+ <Card>
|
|
|
+ <CardHeader>
|
|
|
+ <CardTitle className="text-lg">添加资产文件</CardTitle>
|
|
|
+ <CardDescription>
|
|
|
+ 为 {selectedPerson.name} 上传资产文件
|
|
|
+ </CardDescription>
|
|
|
+ </CardHeader>
|
|
|
+ <CardContent>
|
|
|
+ <Form {...form}>
|
|
|
+ <form onSubmit={form.handleSubmit(onSubmit, (errors) => console.debug('表单验证错误:', errors))} className="space-y-4">
|
|
|
+ <div className="grid grid-cols-2 gap-4">
|
|
|
+ <FormField
|
|
|
+ control={form.control}
|
|
|
+ name="assetType"
|
|
|
+ render={({ field }) => (
|
|
|
+ <FormItem>
|
|
|
+ <FormLabel>资产类型</FormLabel>
|
|
|
+ <Select onValueChange={field.onChange} defaultValue={field.value}>
|
|
|
+ <FormControl>
|
|
|
+ <SelectTrigger>
|
|
|
+ <SelectValue placeholder="选择资产类型" />
|
|
|
+ </SelectTrigger>
|
|
|
+ </FormControl>
|
|
|
+ <SelectContent>
|
|
|
+ {assetTypeOptions.map((option) => (
|
|
|
+ <SelectItem key={option.value} value={option.value}>
|
|
|
+ {option.label}
|
|
|
+ </SelectItem>
|
|
|
+ ))}
|
|
|
+ </SelectContent>
|
|
|
+ </Select>
|
|
|
+ <FormMessage />
|
|
|
+ </FormItem>
|
|
|
+ )}
|
|
|
+ />
|
|
|
+
|
|
|
+ <FormField
|
|
|
+ control={form.control}
|
|
|
+ name="assetFileType"
|
|
|
+ render={({ field }) => (
|
|
|
+ <FormItem>
|
|
|
+ <FormLabel>文件类型</FormLabel>
|
|
|
+ <Select onValueChange={field.onChange} defaultValue={field.value}>
|
|
|
+ <FormControl>
|
|
|
+ <SelectTrigger>
|
|
|
+ <SelectValue placeholder="选择文件类型" />
|
|
|
+ </SelectTrigger>
|
|
|
+ </FormControl>
|
|
|
+ <SelectContent>
|
|
|
+ {assetFileTypeOptions.map((option) => (
|
|
|
+ <SelectItem key={option.value} value={option.value}>
|
|
|
+ {option.label}
|
|
|
+ </SelectItem>
|
|
|
+ ))}
|
|
|
+ </SelectContent>
|
|
|
+ </Select>
|
|
|
+ <FormMessage />
|
|
|
+ </FormItem>
|
|
|
+ )}
|
|
|
+ />
|
|
|
+
|
|
|
+ <div className="col-span-2">
|
|
|
+ <FormField
|
|
|
+ control={form.control}
|
|
|
+ name="fileId"
|
|
|
+ render={({ field }) => (
|
|
|
+ <FormItem>
|
|
|
+ <FormLabel>文件选择</FormLabel>
|
|
|
+ <FormControl>
|
|
|
+ <FileSelector
|
|
|
+ value={field.value || null}
|
|
|
+ onChange={handleFileChange}
|
|
|
+ accept="image/*,application/pdf,.doc,.docx,.xls,.xlsx,.txt"
|
|
|
+ filterType="all"
|
|
|
+ placeholder="选择或上传文件"
|
|
|
+ title="选择资产文件"
|
|
|
+ description="上传新文件或从已有文件中选择"
|
|
|
+ />
|
|
|
+ </FormControl>
|
|
|
+ <FormDescription>
|
|
|
+ 支持图片、PDF、Word、Excel、文本等格式文件
|
|
|
+ </FormDescription>
|
|
|
+ <FormMessage />
|
|
|
+ </FormItem>
|
|
|
+ )}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <FormField
|
|
|
+ control={form.control}
|
|
|
+ name="relatedTime"
|
|
|
+ render={({ field }) => (
|
|
|
+ <FormItem>
|
|
|
+ <FormLabel>关联时间</FormLabel>
|
|
|
+ <FormControl>
|
|
|
+ <Input
|
|
|
+ type="datetime-local"
|
|
|
+ {...field}
|
|
|
+ value={field.value ? field.value.slice(0, 16) : ''}
|
|
|
+ onChange={(e) => field.onChange(e.target.value + ':00.000Z')}
|
|
|
+ />
|
|
|
+ </FormControl>
|
|
|
+ <FormMessage />
|
|
|
+ </FormItem>
|
|
|
+ )}
|
|
|
+ />
|
|
|
+
|
|
|
+ <div className="col-span-2">
|
|
|
+ <FormField
|
|
|
+ control={form.control}
|
|
|
+ name="remark"
|
|
|
+ render={({ field }) => (
|
|
|
+ <FormItem>
|
|
|
+ <FormLabel>备注</FormLabel>
|
|
|
+ <FormControl>
|
|
|
+ <Textarea
|
|
|
+ placeholder="请输入备注信息"
|
|
|
+ className="min-h-[80px]"
|
|
|
+ {...field}
|
|
|
+ />
|
|
|
+ </FormControl>
|
|
|
+ <FormMessage />
|
|
|
+ </FormItem>
|
|
|
+ )}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div className="flex justify-end space-x-2">
|
|
|
+ <Button
|
|
|
+ type="button"
|
|
|
+ variant="outline"
|
|
|
+ onClick={() => setShowAssetForm(false)}
|
|
|
+ disabled={isSubmitting}
|
|
|
+ >
|
|
|
+ 取消
|
|
|
+ </Button>
|
|
|
+ <Button type="submit" disabled={isSubmitting}>
|
|
|
+ {isSubmitting ? '提交中...' : '添加资产'}
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ </form>
|
|
|
+ </Form>
|
|
|
+ </CardContent>
|
|
|
+ </Card>
|
|
|
+ )}
|
|
|
+ </>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <DialogFooter>
|
|
|
+ <Button variant="outline" onClick={() => onOpenChange(false)}>
|
|
|
+ 关闭
|
|
|
+ </Button>
|
|
|
+ </DialogFooter>
|
|
|
+ </DialogContent>
|
|
|
+ </Dialog>
|
|
|
+ );
|
|
|
+};
|
|
|
+
|
|
|
+export default OrderPersonAssetAssociation;
|