casualroom/apps/fenghuo/web/components/profile/profile-sheet.tsx

1291 lines
74 KiB
TypeScript
Raw Permalink Normal View History

2025-07-28 07:50:50 +08:00
'use client';
import * as React from 'react';
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
import { CalendarIcon, Plus, Trash2 } from 'lucide-react';
import { IconChevronDown, IconCheck, IconX } from '@tabler/icons-react';
import {
Sheet,
SheetContent,
SheetDescription,
SheetHeader,
SheetTitle,
SheetFooter,
} from '@nice/ui/components/sheet';
import { Button } from '@nice/ui/components/button';
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@nice/ui/components/form';
import { Input } from '@nice/ui/components/input';
import { Textarea } from '@nice/ui/components/textarea';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@nice/ui/components/select';
import { Calendar } from '@nice/ui/components/calendar';
import { Popover, PopoverContent, PopoverTrigger } from '@nice/ui/components/popover';
import { DateTimePicker } from '@nice/ui/components/date-time-picker';
import {
Command,
CommandEmpty,
CommandGroup,
CommandItem,
CommandList,
} from '@nice/ui/components/command';
import { Card, CardContent, CardHeader, CardTitle } from '@nice/ui/components/card';
import { cn } from '@nice/ui/lib/utils';
import { DeptSelect, DutySelect } from '@/components/selector';
import { AvatarUpload } from '@/components/common/avatar-upload';
import { Education, EducationForm, PoliticalStatus, TrainType, AppraisalLevel, ProfileMetadata } from '@fenghuo/common';
import { useProfile } from './profile-provider';
import { useTranslation } from '@nice/i18n';
// 定义表单验证模式
const createProfileFormSchema = (t: (key: string) => string) => z.object({
// 基本信息
name: z.string().min(1, t('profile.profile_sheet.validation.name_required')),
gender: z.number().min(1).max(2),
idNum: z.string().min(15, t('profile.profile_sheet.validation.id_number_min_length')),
paperId: z.string().min(1, t('profile.profile_sheet.validation.certificate_number_required')), // 改为必选
avatar: z.string().optional(), // 添加头像字段,可选
command: z.string(), // 添加编制命令字段
birthday: z.date().optional(), // 添加生日字段
// 入职信息 - 改为必选
hireDate: z.date({ required_error: t('profile.profile_sheet.validation.hire_date_required') }),
relativeHireDate: z.date().optional(),
// 身份信息 - 改为必选
identity: z.string().min(1, t('profile.profile_sheet.validation.identity_required')),
level: z.string().min(1, t('profile.profile_sheet.validation.rank_required')),
levelDate: z.date({ required_error: t('profile.profile_sheet.validation.rank_time_required') }),
// 职务信息 - 改为必选
dutyCode: z.string().optional(),
dutyLevel: z.string().optional(), // 改为非必选
dutyName: z.string().min(1, t('profile.profile_sheet.validation.duty_name_required')),
// 组织信息 - 改为必选
organizationId: z.string().min(1, t('profile.profile_sheet.validation.organization_required')),
// 元数据
metadata: z.object({
ethnicity: z.string().optional(),
bloodType: z.string().optional(),
proxyDuty: z.string().optional(),
isRehire: z.boolean().optional(),
isExtendedDeparture: z.boolean().optional(),
positionYear: z.number().optional(),
politicalStatus: z.string().optional(),
partyPosition: z.string().optional(),
native: z.object({
province: z.string().optional(),
city: z.string().optional(),
county: z.string().optional(),
}).optional(),
education: z.string().optional(),
educationForm: z.string().optional(),
isGraduate: z.boolean().optional(),
schoolMajor: z.string().optional(),
drills: z.number().optional(),
train: z.array(z.object({
type: z.string().optional(),
location: z.string().optional(),
major: z.string().optional(),
})).optional(),
appraisal: z.array(z.object({
level: z.string().optional(),
job: z.string().optional(),
})).optional(),
foreignLanguage: z.string().optional(),
reward: z.string().optional(),
punish: z.string().optional(),
remark: z.string().optional(),
}).optional(),
});
// 职务水平选择器组件
interface DutyLevelSelectProps {
value?: string;
onValueChange?: (value: string) => void;
placeholder?: string;
className?: string;
disabled?: boolean;
}
function DutyLevelSelect({
value,
onValueChange,
placeholder = '请选择职务水平',
className,
disabled = false,
}: DutyLevelSelectProps) {
const { t } = useTranslation();
const [open, setOpen] = React.useState(false);
// 职务水平选项
const dutyLevelOptions = [
{ value: '1', label: t('profile.profile_sheet.duty_level_primary') },
{ value: '2', label: t('profile.profile_sheet.duty_level_middle') },
{ value: '3', label: t('profile.profile_sheet.duty_level_high') },
];
// 获取当前选中的选项
const selectedOption = dutyLevelOptions.find(option => option.value === value);
// 处理选择逻辑
const handleSelect = (selectedValue: string) => {
if (!onValueChange) return;
// 如果点击的是当前已选中的值,则清空选择
if (value === selectedValue) {
onValueChange('');
} else {
onValueChange(selectedValue);
}
setOpen(false);
};
// 清除选择
const handleClear = (e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
onValueChange?.('');
};
return (
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
role="combobox"
aria-expanded={open}
className={cn(
'w-full justify-between text-left font-normal',
!selectedOption && 'text-muted-foreground',
className,
)}
disabled={disabled}
>
<span className="truncate">
{selectedOption ? selectedOption.label : placeholder}
</span>
<div className="flex items-center gap-1 shrink-0">
{selectedOption && (
<div
role="button"
tabIndex={0}
onClick={handleClear}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
handleClear(e as any);
}
}}
className="flex items-center justify-center w-4 h-4 rounded-sm hover:bg-muted/50 text-muted-foreground hover:text-foreground transition-colors"
aria-label={t('common.clear_selection')}
>
<IconX className="h-3 w-3" />
</div>
)}
<IconChevronDown className="h-4 w-4 shrink-0 opacity-50" />
</div>
</Button>
</PopoverTrigger>
<PopoverContent className="w-full p-0" style={{ width: 'var(--radix-popover-trigger-width)' }} align="start">
<Command>
<CommandList>
<CommandEmpty>{t('profile.profile_sheet.duty_level_not_found')}</CommandEmpty>
<CommandGroup>
{dutyLevelOptions.map((option) => (
<CommandItem
key={option.value}
value={option.value}
onSelect={() => handleSelect(option.value)}
className={cn(
'flex items-center justify-between cursor-pointer',
'hover:bg-accent hover:text-accent-foreground',
value === option.value && 'bg-accent text-accent-foreground',
)}
>
<span>{option.label}</span>
{value === option.value && (
<IconCheck className="h-4 w-4 text-primary" />
)}
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
);
}
export function ProfileSheet() {
const { t } = useTranslation();
const {
isSheetOpen,
setIsSheetOpen,
editingProfile,
sheetMode,
handleSubmitEmployee,
} = useProfile();
// 创建动态的表单验证模式
const profileFormSchema = React.useMemo(() => createProfileFormSchema(t), [t]);
type ProfileFormValues = z.infer<typeof profileFormSchema>;
const form = useForm<ProfileFormValues>({
resolver: zodResolver(profileFormSchema),
defaultValues: {
name: '',
gender: 1,
idNum: '',
paperId: '',
avatar: '',
command: '',
birthday: undefined,
hireDate: undefined, // 改为 undefined保持一致性
relativeHireDate: undefined, // 改为 undefined保持一致性
identity: '',
level: '',
levelDate: undefined, // 改为 undefined保持一致性
dutyCode: '',
dutyLevel: '',
dutyName: '',
organizationId: '',
metadata: {
ethnicity: '',
bloodType: '',
proxyDuty: '',
isRehire: false,
isExtendedDeparture: false,
positionYear: undefined,
politicalStatus: '',
partyPosition: '',
native: {
province: '',
city: '',
county: '',
},
education: '',
educationForm: '',
isGraduate: false,
schoolMajor: '',
drills: undefined,
train: [{ type: '', location: '', major: '' }],
appraisal: [{ level: '', job: '' }],
foreignLanguage: '',
reward: '',
punish: '',
remark: '',
},
},
});
// 当编辑数据变化时,回显数据
React.useEffect(() => {
if (editingProfile && sheetMode === 'edit') {
const metadata = editingProfile.metadata as ProfileMetadata;
form.reset({
name: editingProfile.name || '',
gender: editingProfile.gender || 1,
idNum: editingProfile.idNum || '',
paperId: editingProfile.paperId || '',
avatar: editingProfile.avatar || '',
birthday: editingProfile.birthday ? new Date(editingProfile.birthday) : undefined,
command: editingProfile.command || '',
hireDate: editingProfile.hireDate ? new Date(editingProfile.hireDate) : undefined,
relativeHireDate: editingProfile.relativeHireDate ? new Date(editingProfile.relativeHireDate) : undefined,
identity: editingProfile.identity || '',
level: editingProfile.level || '',
levelDate: editingProfile.levelDate ? new Date(editingProfile.levelDate) : undefined,
dutyCode: editingProfile.dutyCode || '',
dutyLevel: editingProfile.dutyLevel?.toString() || '',
dutyName: editingProfile.dutyName || '',
organizationId: editingProfile.organizationId || '',
metadata: {
ethnicity: metadata?.ethnicity || '',
bloodType: metadata?.bloodType || '',
proxyDuty: metadata?.proxyDuty || '',
isRehire: metadata?.isRehire || false,
isExtendedDeparture: metadata?.isExtendedDeparture || false,
positionYear: metadata?.positionYear,
politicalStatus: metadata?.politicalStatus || '',
partyPosition: metadata?.partyPosition || '',
native: {
province: metadata?.native?.province || '',
city: metadata?.native?.city || '',
county: metadata?.native?.county || '',
},
education: metadata?.education || '',
educationForm: metadata?.educationForm || '',
isGraduate: metadata?.isGraduate || false,
schoolMajor: metadata?.schoolMajor || '',
drills: metadata?.drills,
train: metadata?.train || [{ type: '', location: '', major: '' }],
appraisal: metadata?.appraisal || [{ level: '', job: '' }],
foreignLanguage: metadata?.foreignLanguage || '',
reward: metadata?.reward || '',
punish: metadata?.punish || '',
remark: metadata?.remark || '',
},
});
} else if (sheetMode === 'create') {
// 创建模式时重置表单 - 保持与 defaultValues 一致
form.reset({
name: '',
gender: 1,
idNum: '',
paperId: '',
avatar: '',
birthday: undefined,
command: '',
hireDate: undefined,
relativeHireDate: undefined,
identity: '',
level: '',
levelDate: undefined,
dutyCode: '',
dutyLevel: '',
dutyName: '',
organizationId: '',
metadata: {
ethnicity: '',
bloodType: '',
proxyDuty: '',
isRehire: false,
isExtendedDeparture: false,
positionYear: undefined,
politicalStatus: '',
partyPosition: '',
native: {
province: '',
city: '',
county: '',
},
education: '',
educationForm: '',
isGraduate: false,
schoolMajor: '',
drills: undefined,
train: [{ type: '', location: '', major: '' }],
appraisal: [{ level: '', job: '' }],
foreignLanguage: '',
reward: '',
punish: '',
remark: '',
},
});
}
}, [editingProfile, sheetMode, form]);
// 处理 Sheet 开关状态变化
const handleOpenChange = (newOpen: boolean) => {
setIsSheetOpen(newOpen);
// 当 Sheet 关闭时清空表单
if (!newOpen) {
form.reset();
}
};
const handleSubmit = (data: ProfileFormValues) => {
handleSubmitEmployee(data);
setIsSheetOpen(false);
form.reset();
};
const addTrainExperience = () => {
const current = form.getValues('metadata.train') || [];
form.setValue('metadata.train', [...current, { type: '', location: '', major: '' }]);
};
const removeTrainExperience = (index: number) => {
const current = form.getValues('metadata.train') || [];
form.setValue('metadata.train', current.filter((_, i) => i !== index));
};
const addAppraisalExperience = () => {
const current = form.getValues('metadata.appraisal') || [];
form.setValue('metadata.appraisal', [...current, { level: '', job: '' }]);
};
const removeAppraisalExperience = (index: number) => {
const current = form.getValues('metadata.appraisal') || [];
form.setValue('metadata.appraisal', current.filter((_, i) => i !== index));
};
const politicalStatusOptions = Object.values(PoliticalStatus);
const educationFormOptions = Object.values(EducationForm);
const trainTypeOptions = Object.values(TrainType);
const appraisalLevelOptions = Object.values(AppraisalLevel);
const educationOptions = Object.values(Education);
return (
<Sheet open={isSheetOpen} onOpenChange={handleOpenChange}>
<SheetContent side="right" className="w-1/3 min-w-[600px] p-3 overflow-y-auto mb-2">
<SheetHeader>
<SheetTitle>
{sheetMode === 'edit'
? t('profile.profile_sheet.title_edit')
: t('profile.profile_sheet.title_add')
}
</SheetTitle>
<SheetDescription>
{sheetMode === 'edit'
? t('profile.profile_sheet.description_edit')
: t('profile.profile_sheet.description_add')
}{t('profile.profile_sheet.required_fields_note')}
</SheetDescription>
</SheetHeader>
<Form {...form}>
<form onSubmit={form.handleSubmit(handleSubmit)} className="space-y-2">
{/* 基本信息 */}
<Card>
<CardHeader>
<CardTitle className="text-lg">{t('profile.profile_sheet.basic_info')}</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
{/* 头像和表单字段 */}
<div className="flex gap-4 items-start">
{/* 头像上传区域 - 3:4 长方形 */}
<div className="flex-shrink-0">
<FormField
control={form.control}
name="avatar"
render={({ field }) => (
<FormItem>
<FormControl>
<AvatarUpload
value={field.value}
onChange={field.onChange}
className="w-24 h-32"
placeholder={t('common.upload_avatar')}
accept="image/*"
maxSize={10 * 1024 * 1024} // 10MB
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* 表单字段区域 */}
<div className="flex-1 space-y-4">
{/* 姓名和性别 */}
<div className="grid grid-cols-2 gap-4">
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.name') + ' *'}</FormLabel>
<FormControl>
<Input placeholder={t('profile.profile_sheet.placeholders.name')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="gender"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.gender') + ' *'}</FormLabel>
<Select
onValueChange={(value) => field.onChange(Number(value))}
value={field.value?.toString() || ''}
>
<FormControl>
<SelectTrigger>
<SelectValue placeholder={t('profile.profile_sheet.placeholders.gender')} />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value="1">{t('common.male')}</SelectItem>
<SelectItem value="2">{t('common.female')}</SelectItem>
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* 身份证号和证件号 */}
<div className="grid grid-cols-2 gap-4">
<FormField
control={form.control}
name="idNum"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.id_number') + ' *'}</FormLabel>
<FormControl>
<Input placeholder={t('profile.profile_sheet.placeholders.id_number')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="paperId"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.certificate_number') + ' *'}</FormLabel>
<FormControl>
<Input placeholder={t('profile.profile_sheet.placeholders.certificate_number')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
</div>
</div>
{/* 编制命令 - 占据一整行 */}
<FormField
control={form.control}
name="command"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.formation_command') + ' *'}</FormLabel>
<FormControl>
<Input placeholder={t('profile.profile_sheet.placeholders.formation_command')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</CardContent>
</Card>
{/* 组织信息 */}
<Card>
<CardHeader>
<CardTitle className="text-lg">{t('profile.profile_sheet.organization_info')}</CardTitle>
</CardHeader>
<CardContent>
<FormField
control={form.control}
name="organizationId"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.organization') + ' *'}</FormLabel>
<FormControl>
<DeptSelect
value={field.value}
onValueChange={field.onChange}
placeholder={t('profile.profile_sheet.placeholders.organization')}
className="w-full border border-[#EBEFF5]"
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</CardContent>
</Card>
{/* 职务信息 */}
<Card>
<CardHeader>
<CardTitle className="text-lg">{t('profile.profile_sheet.duty_info')}</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid grid-cols-3 gap-4">
<FormField
control={form.control}
name="dutyName"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.duty_name') + ' *'}</FormLabel>
<FormControl>
<DutySelect
value={field.value}
onChange={field.onChange}
placeholder={t('profile.profile_sheet.placeholders.duty_name')}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="dutyCode"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.duty_code')}</FormLabel>
<FormControl>
<Input placeholder={t('profile.profile_sheet.placeholders.duty_code')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="dutyLevel"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.duty_level')}</FormLabel>
<FormControl>
<DutyLevelSelect
value={field.value}
onValueChange={field.onChange}
placeholder={t('profile.profile_sheet.duty_level_placeholder')}
className="w-full border border-[#EBEFF5]"
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
</CardContent>
</Card>
{/* 身份信息 */}
<Card>
<CardHeader>
<CardTitle className="text-lg">{t('profile.profile_sheet.identity_info')}</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid grid-cols-3 gap-4">
<FormField
control={form.control}
name="identity"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.identity') + ' *'}</FormLabel>
<FormControl>
<Input placeholder={t('profile.profile_sheet.placeholders.identity')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="level"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.rank') + ' *'}</FormLabel>
<FormControl>
<Input placeholder={t('profile.profile_sheet.placeholders.rank')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="levelDate"
render={({ field }) => (
<FormItem className="flex flex-col">
<FormLabel>{t('profile.profile_sheet.rank_time') + ' *'}</FormLabel>
<Popover>
<PopoverTrigger asChild>
<FormControl>
<Button
variant="outline"
className={cn(
"w-full pl-3 text-left font-normal border border-[#EBEFF5]",
!field.value && "text-muted-foreground"
)}
>
{field.value ? (
dayjs(field.value).format("YYYY-MM-DD")
) : (
<span>{t('common.select_date')}</span>
)}
<CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
selected={field.value}
onSelect={field.onChange}
disabled={(date) =>
date > new Date() || date < new Date("1900-01-01")
}
initialFocus
/>
</PopoverContent>
</Popover>
<FormMessage />
</FormItem>
)}
/>
</div>
</CardContent>
</Card>
{/* 入职信息 */}
<Card>
<CardHeader>
<CardTitle className="text-lg">{t('profile.profile_sheet.hire_info')}</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<FormField
control={form.control}
name="hireDate"
render={({ field }) => (
<FormItem className="flex flex-col">
<FormLabel>{t('profile.profile_sheet.hire_date') + ' *'}</FormLabel>
<Popover>
<PopoverTrigger asChild>
<FormControl>
<Button
variant="outline"
className={cn(
"w-full pl-3 text-left font-normal border border-[#EBEFF5]",
!field.value && "text-muted-foreground"
)}
>
{field.value ? (
dayjs(field.value).format("YYYY-MM-DD")
) : (
<span>{t('common.select_date')}</span>
)}
<CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
selected={field.value}
onSelect={field.onChange}
disabled={(date) =>
date > new Date() || date < new Date("1900-01-01")
}
initialFocus
/>
</PopoverContent>
</Popover>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="relativeHireDate"
render={({ field }) => (
<FormItem className="flex flex-col">
<FormLabel>{t('profile.profile_sheet.relative_hire_time')}</FormLabel>
<Popover>
<PopoverTrigger asChild>
<FormControl>
<Button
variant="outline"
className={cn(
"w-full pl-3 text-left font-normal border border-[#EBEFF5]",
!field.value && "text-muted-foreground"
)}
>
{field.value ? (
dayjs(field.value).format("YYYY-MM-DD")
) : (
<span>{t('common.select_date')}</span>
)}
<CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
selected={field.value}
onSelect={field.onChange}
disabled={(date) =>
date > new Date() || date < new Date("1900-01-01")
}
initialFocus
/>
</PopoverContent>
</Popover>
<FormMessage />
</FormItem>
)}
/>
</div>
</CardContent>
</Card>
{/* 详细信息 */}
<Card>
<CardHeader>
<CardTitle className="text-lg">{t('profile.profile_sheet.detailed_info')}</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
{/* 基本详细信息 */}
<div className="grid grid-cols-3 gap-4">
<FormField
control={form.control}
name="metadata.ethnicity"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.ethnicity')}</FormLabel>
<FormControl>
<Input placeholder={t('profile.profile_sheet.placeholders.ethnicity')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="birthday"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.birth_date')}</FormLabel>
<FormControl>
<DateTimePicker
value={field.value}
onChange={field.onChange}
placeholder={t('profile.profile_sheet.placeholders.birth_date')}
showTime={false}
maxDate={new Date()}
minDate={new Date("1900-01-01")}
dateFormat="YYYY-MM-DD"
className='border border-[#EBEFF5]'
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="metadata.bloodType"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.blood_type')}</FormLabel>
<Select onValueChange={field.onChange} value={field.value || ''}>
<FormControl className='w-full' >
<SelectTrigger>
<SelectValue placeholder={t('profile.profile_sheet.placeholders.blood_type')} />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value="A">{t('profile.profile_sheet.blood_types.a')}</SelectItem>
<SelectItem value="B">{t('profile.profile_sheet.blood_types.b')}</SelectItem>
<SelectItem value="AB">{t('profile.profile_sheet.blood_types.ab')}</SelectItem>
<SelectItem value="O">{t('profile.profile_sheet.blood_types.o')}</SelectItem>
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* 政治面貌 */}
<div className="grid grid-cols-2 gap-4">
<FormField
control={form.control}
name="metadata.politicalStatus"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.political_status')}</FormLabel>
<Select onValueChange={field.onChange} value={field.value || ''}>
<FormControl className='w-full'>
<SelectTrigger>
<SelectValue placeholder={t('profile.profile_sheet.placeholders.political_status')} />
</SelectTrigger>
</FormControl>
<SelectContent>
{politicalStatusOptions.map((status) => (
<SelectItem key={status} value={status}>
{status}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="metadata.partyPosition"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.party_position')}</FormLabel>
<FormControl>
<Input placeholder={t('profile.profile_sheet.placeholders.party_position')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* 籍贯 */}
<div className="space-y-2">
<FormLabel>{t('profile.profile_sheet.native_place')}</FormLabel>
<div className="grid grid-cols-3 gap-4">
<FormField
control={form.control}
name="metadata.native.province"
render={({ field }) => (
<FormItem>
<FormControl>
<Input placeholder={t('profile.profile_sheet.province')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="metadata.native.city"
render={({ field }) => (
<FormItem>
<FormControl>
<Input placeholder={t('profile.profile_sheet.city')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="metadata.native.county"
render={({ field }) => (
<FormItem>
<FormControl>
<Input placeholder={t('profile.profile_sheet.county')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
</div>
{/* 学历信息 */}
<div className="grid grid-cols-3 gap-4">
<FormField
control={form.control}
name="metadata.education"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.education')}</FormLabel>
<Select onValueChange={field.onChange} value={field.value || ''}>
<FormControl className='w-full'>
<SelectTrigger>
<SelectValue placeholder={t('profile.profile_sheet.placeholders.education')} />
</SelectTrigger>
</FormControl>
<SelectContent>
{educationOptions.map((education) => (
<SelectItem key={education} value={education}>
{education}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="metadata.educationForm"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.education_form')}</FormLabel>
<Select onValueChange={field.onChange} value={field.value || ''}>
<FormControl className='w-full'>
<SelectTrigger>
<SelectValue placeholder={t('profile.profile_sheet.placeholders.education_form')} />
</SelectTrigger>
</FormControl>
<SelectContent>
{educationFormOptions.map((form) => (
<SelectItem key={form} value={form}>
{form}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="metadata.schoolMajor"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.school_major')}</FormLabel>
<FormControl className='w-full'>
<Input placeholder={t('profile.profile_sheet.placeholders.school_major')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* 其他信息 */}
<div className="grid grid-cols-2 gap-4">
<FormField
control={form.control}
name="metadata.positionYear"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.position_year')}</FormLabel>
<FormControl>
<Input
type="number"
placeholder={t('profile.profile_sheet.placeholders.position_year')}
{...field}
onChange={(e) => field.onChange(e.target.value ? Number(e.target.value) : undefined)}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="metadata.foreignLanguage"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.foreign_language')}</FormLabel>
<FormControl>
<Input placeholder={t('profile.profile_sheet.placeholders.foreign_language')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
{/* 培训经历 */}
<div className="space-y-4">
<div className="flex items-center justify-between">
<FormLabel>{t('profile.profile_sheet.train_experience')}</FormLabel>
<Button className='border border-[#5D6E89]' type="button" variant="outline" size="sm" onClick={addTrainExperience}>
<Plus className="w-4 h-4 mr-2" />
{t('profile.profile_sheet.add_train')}
</Button>
</div>
{form.watch('metadata.train')?.map((_, index) => (
<Card key={index} className="p-4">
<div className="flex items-center justify-between mb-4">
<h4 className="text-sm font-medium">{t('profile.profile_sheet.train_experience')} {index + 1}</h4>
{index > 0 && (
<Button
type="button"
variant="ghost"
size="sm"
onClick={() => removeTrainExperience(index)}
>
<Trash2 className="w-4 h-4" />
</Button>
)}
</div>
<div className="grid grid-cols-2 gap-4">
<FormField
control={form.control}
name={`metadata.train.${index}.type`}
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.train_type')}</FormLabel>
<Select onValueChange={field.onChange} value={field.value || ''}>
<FormControl className='w-full'>
<SelectTrigger>
<SelectValue placeholder={t('profile.profile_sheet.placeholders.train_type')} />
</SelectTrigger>
</FormControl>
<SelectContent>
{trainTypeOptions.map((type) => (
<SelectItem key={type} value={type}>
{type}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name={`metadata.train.${index}.location`}
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.train_location')}</FormLabel>
<FormControl>
<Input placeholder={t('profile.profile_sheet.placeholders.train_location')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
<FormField
control={form.control}
name={`metadata.train.${index}.major`}
render={({ field }) => (
<FormItem className="mt-4">
<FormLabel>{t('profile.profile_sheet.train_major')}</FormLabel>
<FormControl>
<Input placeholder={t('profile.profile_sheet.placeholders.train_major')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</Card>
))}
</div>
{/* 考核经历 */}
<div className="space-y-4">
<div className="flex items-center justify-between">
<FormLabel>{t('profile.profile_sheet.appraisal_experience')}</FormLabel>
<Button className='border border-[#5D6E89]' type="button" variant="outline" size="sm" onClick={addAppraisalExperience}>
<Plus className="w-4 h-4 mr-2" />
{t('profile.profile_sheet.add_appraisal')}
</Button>
</div>
{form.watch('metadata.appraisal')?.map((_, index) => (
<Card key={index} className="p-4">
<div className="flex items-center justify-between mb-4">
<h4 className="text-sm font-medium">{t('profile.profile_sheet.appraisal_experience')} {index + 1}</h4>
{index > 0 && (
<Button
type="button"
variant="ghost"
size="sm"
onClick={() => removeAppraisalExperience(index)}
>
<Trash2 className="w-4 h-4" />
</Button>
)}
</div>
<div className="grid grid-cols-2 gap-4">
<FormField
control={form.control}
name={`metadata.appraisal.${index}.level`}
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.appraisal_level')}</FormLabel>
<Select onValueChange={field.onChange} value={field.value || ''}>
<FormControl className='w-full'>
<SelectTrigger>
<SelectValue placeholder={t('profile.profile_sheet.placeholders.appraisal_level')} />
</SelectTrigger>
</FormControl>
<SelectContent>
{appraisalLevelOptions.map((level) => (
<SelectItem key={level} value={level}>
{level}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name={`metadata.appraisal.${index}.job`}
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.appraisal_job')}</FormLabel>
<FormControl>
<Input placeholder={t('profile.profile_sheet.placeholders.appraisal_job')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
</Card>
))}
</div>
{/* 奖励 - 独占一行 */}
<FormField
control={form.control}
name="metadata.reward"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.reward')}</FormLabel>
<FormControl>
<Textarea placeholder={t('profile.profile_sheet.placeholders.reward')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
{/* 处分 - 独占一行 */}
<FormField
control={form.control}
name="metadata.punish"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.punish')}</FormLabel>
<FormControl>
<Textarea placeholder={t('profile.profile_sheet.placeholders.punish')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="metadata.remark"
render={({ field }) => (
<FormItem>
<FormLabel>{t('profile.profile_sheet.remark')}</FormLabel>
<FormControl>
<Textarea placeholder={t('profile.profile_sheet.placeholders.remark')} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</CardContent>
</Card>
<SheetFooter className="gap-2">
<Button type="submit">
{t('common.confirm')}
</Button>
</SheetFooter>
</form>
</Form>
</SheetContent>
</Sheet>
);
}