UserBasicForm.tsx
4.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// REQ-USR-001 / REQ-USR-002: 用户单据表单网格(3 列布局,8 字段 + 员工联动 + 前置校验,BR1-BR9)
import { Form, Input, Select, Checkbox, type FormInstance } from 'antd';
import type { EmployeeOption } from '../../../api/types';
import {
USER_TYPE_OPTIONS,
LANGUAGE_OPTIONS,
USERNAME_PATTERN,
LABEL_CREATE_TIME,
LABEL_CREATOR,
LABEL_EMPLOYEE,
LABEL_USERNAME,
LABEL_USER_TYPE,
LABEL_LANGUAGE,
LABEL_USER_NO,
LABEL_CAN_MODIFY_BILL,
TEXT_CREATOR_PLACEHOLDER,
MSG_USERNAME_FORMAT,
MSG_USERNAME_REQUIRED,
MSG_USERNO_REQUIRED,
MSG_USERTYPE_REQUIRED,
MSG_LANGUAGE_REQUIRED,
type UserFormValues,
} from './constants';
import styles from './UserDetail.module.css';
export interface UserBasicFormProps {
form: FormInstance<UserFormValues>;
mode: 'create' | 'edit';
employees: EmployeeOption[];
readonlyCreateTime?: string;
readonlyCreator?: string;
onSelectEmployee(value: number | null): void;
}
const toEnumOptions = (arr: readonly string[]) => arr.map((v) => ({ value: v, label: v }));
export default function UserBasicForm({
form,
mode,
employees,
readonlyCreateTime,
readonlyCreator,
onSelectEmployee,
}: UserBasicFormProps) {
void form; // 表单由父级 Form 实例驱动(受控 initialValues / validate / submit)
const creatorText =
mode === 'edit' ? readonlyCreator || '' : TEXT_CREATOR_PLACEHOLDER;
const createTimeText = mode === 'edit' ? readonlyCreateTime || '' : '';
return (
<div className={styles.formGrid}>
{/* 创建时间(只读,BR1) */}
<Form.Item label={LABEL_CREATE_TIME}>
<div className={styles.readonlyField} data-testid="field-createtime">
{createTimeText}
</div>
</Form.Item>
{/* 制单人(只读,BR2) */}
<Form.Item label={LABEL_CREATOR}>
<div className={styles.readonlyField} data-testid="field-creator">
{creatorText}
</div>
</Form.Item>
{/* 员工名(Select,选中联动带出用户名/用户号,BR5) */}
<Form.Item label={LABEL_EMPLOYEE} name="iEmployeeId">
<Select
allowClear
placeholder="请选择员工"
options={employees.map((e) => ({ value: e.value, label: e.label }))}
onChange={(v) => onSelectEmployee((v as number | undefined) ?? null)}
virtual={false}
data-testid="select-employee"
/>
</Form.Item>
{/* 用户名(create 可编辑必填 + 格式校验;edit 只读,BR3) */}
<Form.Item
label={LABEL_USERNAME}
name="sUserName"
rules={
mode === 'create'
? [
{ required: true, message: MSG_USERNAME_REQUIRED },
{ pattern: USERNAME_PATTERN, message: MSG_USERNAME_FORMAT },
]
: []
}
>
<Input disabled={mode === 'edit'} data-testid="field-username" />
</Form.Item>
{/* 类型(Select 枚举,create 默认普通用户,BR6) */}
<Form.Item
label={LABEL_USER_TYPE}
name="sUserType"
rules={[{ required: true, message: MSG_USERTYPE_REQUIRED }]}
>
<Select
options={toEnumOptions(USER_TYPE_OPTIONS)}
virtual={false}
data-testid="select-usertype"
/>
</Form.Item>
{/* 语言(Select 枚举,必填,BR7) */}
<Form.Item
label={LABEL_LANGUAGE}
name="sLanguage"
rules={[{ required: true, message: MSG_LANGUAGE_REQUIRED }]}
>
<Select
options={toEnumOptions(LANGUAGE_OPTIONS)}
placeholder="请选择语言"
virtual={false}
data-testid="select-language"
/>
</Form.Item>
{/* 用户号(必填,BR4,可由员工名联动带出,BR5) */}
<Form.Item
label={LABEL_USER_NO}
name="sUserNo"
rules={[{ required: true, message: MSG_USERNO_REQUIRED }]}
>
<Input data-testid="field-userno" />
</Form.Item>
{/* 单据修改权限(Checkbox,默认否,BR8) */}
<Form.Item label={LABEL_CAN_MODIFY_BILL} name="iCanModifyBill" valuePropName="checked">
<Checkbox data-testid="field-canmodify" />
</Form.Item>
</div>
);
}