|
|
@@ -21,8 +21,9 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@
|
|
|
import { Popover, PopoverContent, PopoverTrigger } from '@d8d/shared-ui-components/components/ui/popover';
|
|
|
import { Calendar } from '@d8d/shared-ui-components/components/ui/calendar';
|
|
|
import { cn } from '@d8d/shared-ui-components/utils/cn';
|
|
|
-import { DisabledStatus } from '@d8d/shared-types';
|
|
|
+import { DisabledStatus, UserType, TypeNameMap } from '@d8d/shared-types';
|
|
|
import { CompanySelectorWrapper } from './CompanySelectorWrapper';
|
|
|
+import { DisabledPersonSelectorWrapper } from './DisabledPersonSelectorWrapper';
|
|
|
|
|
|
// 使用RPC方式提取类型
|
|
|
type CreateUserRequest = InferRequestType<typeof userClient.index.$post>['json'];
|
|
|
@@ -64,7 +65,9 @@ export const UserManagement = () => {
|
|
|
phone: null,
|
|
|
name: null,
|
|
|
password: '',
|
|
|
+ userType: UserType.ADMIN,
|
|
|
companyId: null,
|
|
|
+ personId: null,
|
|
|
isDisabled: DisabledStatus.ENABLED,
|
|
|
},
|
|
|
});
|
|
|
@@ -78,7 +81,9 @@ export const UserManagement = () => {
|
|
|
phone: null,
|
|
|
name: null,
|
|
|
password: '',
|
|
|
+ userType: UserType.ADMIN,
|
|
|
companyId: null,
|
|
|
+ personId: null,
|
|
|
isDisabled: 0,
|
|
|
},
|
|
|
});
|
|
|
@@ -187,7 +192,9 @@ export const UserManagement = () => {
|
|
|
phone: null,
|
|
|
name: null,
|
|
|
password: '',
|
|
|
+ userType: UserType.ADMIN,
|
|
|
companyId: null,
|
|
|
+ personId: null,
|
|
|
isDisabled: DisabledStatus.ENABLED,
|
|
|
});
|
|
|
setIsModalOpen(true);
|
|
|
@@ -204,7 +211,9 @@ export const UserManagement = () => {
|
|
|
phone: user.phone,
|
|
|
name: user.name,
|
|
|
avatarFileId: user.avatarFileId,
|
|
|
+ userType: user.userType || UserType.ADMIN,
|
|
|
companyId: user.companyId,
|
|
|
+ personId: user.personId || null,
|
|
|
isDisabled: user.isDisabled,
|
|
|
});
|
|
|
setIsModalOpen(true);
|
|
|
@@ -285,6 +294,8 @@ export const UserManagement = () => {
|
|
|
<Skeleton className="h-4 flex-1" />
|
|
|
<Skeleton className="h-4 flex-1" />
|
|
|
<Skeleton className="h-4 flex-1" />
|
|
|
+ <Skeleton className="h-4 flex-1" />
|
|
|
+ <Skeleton className="h-4 flex-1" />
|
|
|
<Skeleton className="h-4 w-16" />
|
|
|
</div>
|
|
|
))}
|
|
|
@@ -507,7 +518,9 @@ export const UserManagement = () => {
|
|
|
<TableHead>昵称</TableHead>
|
|
|
<TableHead>邮箱</TableHead>
|
|
|
<TableHead>真实姓名</TableHead>
|
|
|
+ <TableHead>用户类型</TableHead>
|
|
|
<TableHead>关联企业</TableHead>
|
|
|
+ <TableHead>关联残疾人</TableHead>
|
|
|
<TableHead>角色</TableHead>
|
|
|
<TableHead>状态</TableHead>
|
|
|
<TableHead>创建时间</TableHead>
|
|
|
@@ -518,7 +531,7 @@ export const UserManagement = () => {
|
|
|
{isLoading ? (
|
|
|
// 显示表格骨架屏
|
|
|
<TableRow>
|
|
|
- <TableCell colSpan={10} className="p-4">
|
|
|
+ <TableCell colSpan={12} className="p-4">
|
|
|
{renderTableSkeleton()}
|
|
|
</TableCell>
|
|
|
</TableRow>
|
|
|
@@ -547,7 +560,19 @@ export const UserManagement = () => {
|
|
|
<TableCell>{user.nickname || '-'}</TableCell>
|
|
|
<TableCell>{user.email || '-'}</TableCell>
|
|
|
<TableCell>{user.name || '-'}</TableCell>
|
|
|
+ <TableCell>
|
|
|
+ <Badge
|
|
|
+ variant={
|
|
|
+ user.userType === UserType.ADMIN ? 'destructive' :
|
|
|
+ user.userType === UserType.EMPLOYER ? 'default' :
|
|
|
+ 'secondary'
|
|
|
+ }
|
|
|
+ >
|
|
|
+ {TypeNameMap[user.userType || UserType.ADMIN]}
|
|
|
+ </Badge>
|
|
|
+ </TableCell>
|
|
|
<TableCell>{user.company?.companyName || '无'}</TableCell>
|
|
|
+ <TableCell>{user.person ? user.person.name : '-'}</TableCell>
|
|
|
<TableCell>
|
|
|
<Badge
|
|
|
variant={user.roles?.some((role) => role.name === 'admin') ? 'destructive' : 'default'}
|
|
|
@@ -725,28 +750,104 @@ export const UserManagement = () => {
|
|
|
)}
|
|
|
/>
|
|
|
|
|
|
+ {/* 用户类型选择器 */}
|
|
|
<FormField
|
|
|
control={createForm.control}
|
|
|
- name="companyId"
|
|
|
+ name="userType"
|
|
|
render={({ field }) => (
|
|
|
<FormItem>
|
|
|
- <FormLabel>关联企业</FormLabel>
|
|
|
- <FormControl>
|
|
|
- <CompanySelectorWrapper
|
|
|
- value={field.value}
|
|
|
- onChange={field.onChange}
|
|
|
- placeholder="请选择关联企业(可选)"
|
|
|
- data-testid="company-selector"
|
|
|
- />
|
|
|
- </FormControl>
|
|
|
+ <FormLabel className="flex items-center">
|
|
|
+ 用户类型
|
|
|
+ <span className="text-red-500 ml-1">*</span>
|
|
|
+ </FormLabel>
|
|
|
+ <Select
|
|
|
+ onValueChange={(value) => {
|
|
|
+ field.onChange(value);
|
|
|
+ // 切换用户类型时清空不相关字段
|
|
|
+ if (value !== UserType.EMPLOYER) {
|
|
|
+ createForm.setValue('companyId', null);
|
|
|
+ }
|
|
|
+ if (value !== UserType.TALENT) {
|
|
|
+ createForm.setValue('personId', null);
|
|
|
+ }
|
|
|
+ }}
|
|
|
+ defaultValue={field.value}
|
|
|
+ >
|
|
|
+ <FormControl>
|
|
|
+ <SelectTrigger data-testid="user-type-select">
|
|
|
+ <SelectValue placeholder="请选择用户类型" />
|
|
|
+ </SelectTrigger>
|
|
|
+ </FormControl>
|
|
|
+ <SelectContent>
|
|
|
+ <SelectItem value={UserType.ADMIN}>管理员</SelectItem>
|
|
|
+ <SelectItem value={UserType.EMPLOYER}>企业用户</SelectItem>
|
|
|
+ <SelectItem value={UserType.TALENT}>人才用户</SelectItem>
|
|
|
+ </SelectContent>
|
|
|
+ </Select>
|
|
|
<FormDescription>
|
|
|
- 为用户分配关联的企业,留空表示不关联任何企业
|
|
|
+ 选择用户类型以确定系统权限和功能访问范围
|
|
|
</FormDescription>
|
|
|
<FormMessage />
|
|
|
</FormItem>
|
|
|
)}
|
|
|
/>
|
|
|
|
|
|
+ {/* 企业选择器 - 仅当用户类型为企业用户时显示 */}
|
|
|
+ {createForm.watch('userType') === UserType.EMPLOYER && (
|
|
|
+ <FormField
|
|
|
+ control={createForm.control}
|
|
|
+ name="companyId"
|
|
|
+ render={({ field }) => (
|
|
|
+ <FormItem>
|
|
|
+ <FormLabel className="flex items-center">
|
|
|
+ 关联企业
|
|
|
+ <span className="text-red-500 ml-1">*</span>
|
|
|
+ </FormLabel>
|
|
|
+ <FormControl>
|
|
|
+ <CompanySelectorWrapper
|
|
|
+ value={field.value}
|
|
|
+ onChange={field.onChange}
|
|
|
+ placeholder="请选择关联企业"
|
|
|
+ data-testid="company-selector"
|
|
|
+ />
|
|
|
+ </FormControl>
|
|
|
+ <FormDescription>
|
|
|
+ 企业用户必须关联一个企业
|
|
|
+ </FormDescription>
|
|
|
+ <FormMessage />
|
|
|
+ </FormItem>
|
|
|
+ )}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+
|
|
|
+ {/* 残疾人选择器 - 仅当用户类型为人才用户时显示 */}
|
|
|
+ {createForm.watch('userType') === UserType.TALENT && (
|
|
|
+ <FormField
|
|
|
+ control={createForm.control}
|
|
|
+ name="personId"
|
|
|
+ render={({ field }) => (
|
|
|
+ <FormItem>
|
|
|
+ <FormLabel className="flex items-center">
|
|
|
+ 关联残疾人
|
|
|
+ <span className="text-red-500 ml-1">*</span>
|
|
|
+ </FormLabel>
|
|
|
+ <FormControl>
|
|
|
+ <DisabledPersonSelectorWrapper
|
|
|
+ value={field.value ?? null}
|
|
|
+ onChange={field.onChange}
|
|
|
+ placeholder="请选择残疾人"
|
|
|
+ data-testid="disabled-person-selector"
|
|
|
+ />
|
|
|
+ </FormControl>
|
|
|
+ <FormDescription>
|
|
|
+ 人才用户必须关联一个残疾人记录
|
|
|
+ </FormDescription>
|
|
|
+ <FormMessage />
|
|
|
+ </FormItem>
|
|
|
+ )}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+
|
|
|
<FormField
|
|
|
control={createForm.control}
|
|
|
name="isDisabled"
|
|
|
@@ -868,28 +969,104 @@ export const UserManagement = () => {
|
|
|
)}
|
|
|
/>
|
|
|
|
|
|
+ {/* 用户类型选择器 - 编辑表单 */}
|
|
|
<FormField
|
|
|
control={updateForm.control}
|
|
|
- name="companyId"
|
|
|
+ name="userType"
|
|
|
render={({ field }) => (
|
|
|
<FormItem>
|
|
|
- <FormLabel>关联企业</FormLabel>
|
|
|
- <FormControl>
|
|
|
- <CompanySelectorWrapper
|
|
|
- value={field.value}
|
|
|
- onChange={field.onChange}
|
|
|
- placeholder="请选择关联企业(可选)"
|
|
|
- data-testid="company-selector-edit"
|
|
|
- />
|
|
|
- </FormControl>
|
|
|
+ <FormLabel className="flex items-center">
|
|
|
+ 用户类型
|
|
|
+ <span className="text-red-500 ml-1">*</span>
|
|
|
+ </FormLabel>
|
|
|
+ <Select
|
|
|
+ onValueChange={(value) => {
|
|
|
+ field.onChange(value);
|
|
|
+ // 切换用户类型时清空不相关字段
|
|
|
+ if (value !== UserType.EMPLOYER) {
|
|
|
+ updateForm.setValue('companyId', null);
|
|
|
+ }
|
|
|
+ if (value !== UserType.TALENT) {
|
|
|
+ updateForm.setValue('personId', null);
|
|
|
+ }
|
|
|
+ }}
|
|
|
+ value={field.value}
|
|
|
+ >
|
|
|
+ <FormControl>
|
|
|
+ <SelectTrigger data-testid="user-type-select-edit">
|
|
|
+ <SelectValue placeholder="请选择用户类型" />
|
|
|
+ </SelectTrigger>
|
|
|
+ </FormControl>
|
|
|
+ <SelectContent>
|
|
|
+ <SelectItem value={UserType.ADMIN}>管理员</SelectItem>
|
|
|
+ <SelectItem value={UserType.EMPLOYER}>企业用户</SelectItem>
|
|
|
+ <SelectItem value={UserType.TALENT}>人才用户</SelectItem>
|
|
|
+ </SelectContent>
|
|
|
+ </Select>
|
|
|
<FormDescription>
|
|
|
- 为用户分配关联的企业,留空表示不关联任何企业
|
|
|
+ 选择用户类型以确定系统权限和功能访问范围
|
|
|
</FormDescription>
|
|
|
<FormMessage />
|
|
|
</FormItem>
|
|
|
)}
|
|
|
/>
|
|
|
|
|
|
+ {/* 企业选择器 - 仅当用户类型为企业用户时显示 */}
|
|
|
+ {updateForm.watch('userType') === UserType.EMPLOYER && (
|
|
|
+ <FormField
|
|
|
+ control={updateForm.control}
|
|
|
+ name="companyId"
|
|
|
+ render={({ field }) => (
|
|
|
+ <FormItem>
|
|
|
+ <FormLabel className="flex items-center">
|
|
|
+ 关联企业
|
|
|
+ <span className="text-red-500 ml-1">*</span>
|
|
|
+ </FormLabel>
|
|
|
+ <FormControl>
|
|
|
+ <CompanySelectorWrapper
|
|
|
+ value={field.value}
|
|
|
+ onChange={field.onChange}
|
|
|
+ placeholder="请选择关联企业"
|
|
|
+ data-testid="company-selector-edit"
|
|
|
+ />
|
|
|
+ </FormControl>
|
|
|
+ <FormDescription>
|
|
|
+ 企业用户必须关联一个企业
|
|
|
+ </FormDescription>
|
|
|
+ <FormMessage />
|
|
|
+ </FormItem>
|
|
|
+ )}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+
|
|
|
+ {/* 残疾人选择器 - 仅当用户类型为人才用户时显示 */}
|
|
|
+ {updateForm.watch('userType') === UserType.TALENT && (
|
|
|
+ <FormField
|
|
|
+ control={updateForm.control}
|
|
|
+ name="personId"
|
|
|
+ render={({ field }) => (
|
|
|
+ <FormItem>
|
|
|
+ <FormLabel className="flex items-center">
|
|
|
+ 关联残疾人
|
|
|
+ <span className="text-red-500 ml-1">*</span>
|
|
|
+ </FormLabel>
|
|
|
+ <FormControl>
|
|
|
+ <DisabledPersonSelectorWrapper
|
|
|
+ value={field.value ?? null}
|
|
|
+ onChange={field.onChange}
|
|
|
+ placeholder="请选择残疾人"
|
|
|
+ data-testid="disabled-person-selector-edit"
|
|
|
+ />
|
|
|
+ </FormControl>
|
|
|
+ <FormDescription>
|
|
|
+ 人才用户必须关联一个残疾人记录
|
|
|
+ </FormDescription>
|
|
|
+ <FormMessage />
|
|
|
+ </FormItem>
|
|
|
+ )}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+
|
|
|
<FormField
|
|
|
control={updateForm.control}
|
|
|
name="isDisabled"
|