@ticatec/uniface-element 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/README.md +320 -1
  2. package/README_CN.md +392 -0
  3. package/dist/accordion/Accordion.svelte +1 -1
  4. package/dist/action-bar/ActionBar.svelte +7 -1
  5. package/dist/attachment-files/FileRender.svelte +1 -1
  6. package/dist/attachment-files/FileUploadBar.svelte +7 -6
  7. package/dist/attachment-files/FileUploadPanel.svelte +2 -2
  8. package/dist/base-calendar/DateContext.js +5 -4
  9. package/dist/base-calendar/YearPickupPanel.svelte +4 -4
  10. package/dist/card/Card.svelte +1 -1
  11. package/dist/card/Card.svelte.d.ts +1 -1
  12. package/dist/cascade-options-select/CascadeOptionSelect.svelte +2 -3
  13. package/dist/cascade-options-select/CascadeOptionSelect.svelte.d.ts +46 -1
  14. package/dist/cascade-options-select/CascadePanel.svelte +1 -1
  15. package/dist/checkbox/CheckBox.svelte +1 -1
  16. package/dist/color-picker/ColorPicker.svelte +9 -9
  17. package/dist/color-picker/ColorPicker.svelte.d.ts +0 -2
  18. package/dist/color-picker/ColorPickerPanel.svelte +11 -15
  19. package/dist/color-picker/ColorPickerPanel.svelte.d.ts +1 -1
  20. package/dist/common/CommonPicker.svelte +2 -2
  21. package/dist/common/CommonPicker.svelte.d.ts +1 -1
  22. package/dist/common/MouseClickHandler.d.ts +1 -1
  23. package/dist/common/Popover.svelte +28 -6
  24. package/dist/common/Popover.svelte.d.ts +9 -3
  25. package/dist/common/uniface-utils.js +6 -4
  26. package/dist/common-editor/CommonEditor.svelte +1 -1
  27. package/dist/common-editor/CommonEditor.svelte.d.ts +1 -1
  28. package/dist/common-editor/NumberInput.svelte +1 -1
  29. package/dist/common-editor/NumberInput.svelte.d.ts +1 -1
  30. package/dist/concise-data-table/ConciseListTable.svelte +7 -2
  31. package/dist/concise-data-table/ConciseListTable.svelte.d.ts +1 -0
  32. package/dist/concise-data-table/DataRow.svelte +1 -1
  33. package/dist/concise-data-table/TableOptions.d.ts +1 -1
  34. package/dist/data-table/DataTable.svelte +1 -1
  35. package/dist/data-table/parts/ActionsPanel.svelte +4 -3
  36. package/dist/data-table/parts/ActionsRow.svelte +3 -3
  37. package/dist/data-table/parts/ContentPanel.svelte +3 -2
  38. package/dist/data-table/parts/FixedColumnsPanel.svelte +0 -1
  39. package/dist/data-table/parts/FixedColumnsPanel.svelte.d.ts +1 -2
  40. package/dist/data-table/parts/FixedHeaderPanel.svelte +2 -2
  41. package/dist/data-table/parts/FixedRow.svelte +2 -1
  42. package/dist/data-table/parts/FixedRow.svelte.d.ts +1 -1
  43. package/dist/data-table/parts/HrefCell.svelte +23 -2
  44. package/dist/data-table/parts/PopupMenu.svelte +25 -2
  45. package/dist/data-table/parts/PopupMenu.svelte.d.ts +8 -1
  46. package/dist/date-picker/DatePicker.svelte +0 -1
  47. package/dist/date-picker/DateTimePicker.svelte +3 -3
  48. package/dist/date-picker/ScrollBar.svelte +4 -7
  49. package/dist/date-range/DateRangeEditor.svelte +1 -1
  50. package/dist/dialog/CommonDialog.svelte +8 -5
  51. package/dist/dialog/CommonDialog.svelte.d.ts +2 -1
  52. package/dist/dialog/Dialog.svelte +37 -12
  53. package/dist/dialog/Dialog.svelte.d.ts +4 -3
  54. package/dist/dialog/DialogBoard.svelte +11 -8
  55. package/dist/dialog/DialogWrapper.svelte +10 -0
  56. package/dist/{common-editor/DateInput.svelte.d.ts → dialog/DialogWrapper.svelte.d.ts} +6 -13
  57. package/dist/dialog/Dialogs.js +1 -1
  58. package/dist/dialog/ModalResult.d.ts +5 -0
  59. package/dist/dialog/ModalResult.js +5 -0
  60. package/dist/drawer/Drawer.svelte +1 -1
  61. package/dist/form-field/FormField.svelte +2 -1
  62. package/dist/form-field/FormField.svelte.d.ts +1 -0
  63. package/dist/form-panel/flex-row-form/FormContainer.svelte +1 -1
  64. package/dist/form-panel/grid-form/EmptyCell.svelte +8 -7
  65. package/dist/form-panel/grid-form/EmptyCell.svelte.d.ts +2 -2
  66. package/dist/form-panel/grid-form/GridField.svelte +1 -1
  67. package/dist/i18nRes/i18nRes.d.ts +2 -0
  68. package/dist/i18nRes/i18nRes.js +44 -0
  69. package/dist/i18nRes/index.d.ts +2 -0
  70. package/dist/i18nRes/index.js +2 -0
  71. package/dist/image-files/ImageFilesField.svelte +1 -1
  72. package/dist/indicator/IndicatorBoard.svelte +1 -1
  73. package/dist/inline-cell-editor/InvalidEditor.svelte +1 -0
  74. package/dist/input-options-select/InputOptionsSelect.svelte +6 -6
  75. package/dist/input-options-select/InputOptionsSelect.svelte.d.ts +1 -1
  76. package/dist/layout/flex/FlexBlock.svelte +1 -1
  77. package/dist/lookup-editor/LookupEditor.svelte +1 -1
  78. package/dist/memo-editor/MemoEditor.svelte +2 -2
  79. package/dist/message-box/IMessageBox.d.ts +2 -4
  80. package/dist/message-box/IMessageBox.js +4 -6
  81. package/dist/message-box/MessageBoxBoard.svelte +1 -3
  82. package/dist/options-multi-select/OptionsMultiSelect.svelte +1 -1
  83. package/dist/prompts-text-editor/PromptsTextEditor.svelte +2 -2
  84. package/dist/prompts-text-editor/PromptsTextEditor.svelte.d.ts +1 -1
  85. package/dist/property-editor/PropertyEditor.svelte +3 -3
  86. package/dist/text-editor/PasswordEditor.svelte +1 -1
  87. package/dist/transfer/Transfer.svelte +17 -12
  88. package/dist/transfer/Transfer.svelte.d.ts +0 -1
  89. package/dist/unit-number-editor/UnitNumberEditor.svelte +2 -2
  90. package/docs/buttons/cn/ActionBar.md +459 -0
  91. package/docs/buttons/cn/Button.md +228 -0
  92. package/docs/buttons/cn/IconButton.md +294 -0
  93. package/docs/buttons/cn/README.md +600 -0
  94. package/docs/buttons/cn/TextButton.md +163 -0
  95. package/docs/buttons/en/ActionBar.md +459 -0
  96. package/docs/buttons/en/Button.md +228 -0
  97. package/docs/buttons/en/IconButton.md +294 -0
  98. package/docs/buttons/en/README.md +600 -0
  99. package/docs/buttons/en/TextButton.md +163 -0
  100. package/docs/containers/cn/accordion.md +622 -0
  101. package/docs/containers/cn/box.md +445 -0
  102. package/docs/containers/cn/card.md +404 -0
  103. package/docs/containers/cn/page.md +576 -0
  104. package/docs/containers/cn/tabs.md +686 -0
  105. package/docs/containers/en/accordion.md +622 -0
  106. package/docs/containers/en/box.md +445 -0
  107. package/docs/containers/en/card.md +404 -0
  108. package/docs/containers/en/page.md +576 -0
  109. package/docs/containers/en/tabs.md +686 -0
  110. package/docs/data-display/cn/concise-data-table.md +731 -0
  111. package/docs/data-display/cn/listbox.md +786 -0
  112. package/docs/data-display/cn/treeview.md +863 -0
  113. package/docs/data-display/en/concise-data-table.md +732 -0
  114. package/docs/data-display/en/listbox.md +786 -0
  115. package/docs/data-display/en/treeview.md +863 -0
  116. package/docs/data-table/cn/README.md +596 -0
  117. package/docs/data-table/en/README.md +596 -0
  118. package/docs/dialog/cn/README.md +767 -0
  119. package/docs/dialog/en/README.md +767 -0
  120. package/docs/form/cn/README.md +847 -0
  121. package/docs/form/en/README.md +847 -0
  122. package/docs/form-components/cn/README.md +495 -0
  123. package/docs/form-components/cn/attachmentfilesfield.md +757 -0
  124. package/docs/form-components/cn/cascade-options-select.md +374 -0
  125. package/docs/form-components/cn/checkbox.md +58 -0
  126. package/docs/form-components/cn/date-picker.md +138 -0
  127. package/docs/form-components/cn/datetime-picker.md +228 -0
  128. package/docs/form-components/cn/group-checkbox.md +405 -0
  129. package/docs/form-components/cn/group-radiobox.md +525 -0
  130. package/docs/form-components/cn/imagefilesfield.md +651 -0
  131. package/docs/form-components/cn/input-options-select.md +250 -0
  132. package/docs/form-components/cn/lookup-editor.md +406 -0
  133. package/docs/form-components/cn/memoeditor.md +409 -0
  134. package/docs/form-components/cn/number-editor.md +261 -0
  135. package/docs/form-components/cn/options-multi-select.md +177 -0
  136. package/docs/form-components/cn/options-select.md +83 -0
  137. package/docs/form-components/cn/passwordeditor.md +538 -0
  138. package/docs/form-components/cn/prompts-text-editor.md +241 -0
  139. package/docs/form-components/cn/radiobutton.md +84 -0
  140. package/docs/form-components/cn/switch.md +178 -0
  141. package/docs/form-components/cn/text-editor.md +142 -0
  142. package/docs/form-components/cn/time-editor.md +159 -0
  143. package/docs/form-components/cn/unit-number-editor.md +164 -0
  144. package/docs/form-components/en/README.md +463 -0
  145. package/docs/form-components/en/attachmentfilesfield.md +757 -0
  146. package/docs/form-components/en/cascade-options-select.md +358 -0
  147. package/docs/form-components/en/checkbox.md +59 -0
  148. package/docs/form-components/en/date-picker.md +138 -0
  149. package/docs/form-components/en/datetime-picker.md +228 -0
  150. package/docs/form-components/en/group-checkbox.md +395 -0
  151. package/docs/form-components/en/group-radiobox.md +498 -0
  152. package/docs/form-components/en/imagefilesfield.md +651 -0
  153. package/docs/form-components/en/input-options-select.md +239 -0
  154. package/docs/form-components/en/lookup-editor.md +389 -0
  155. package/docs/form-components/en/memoeditor.md +409 -0
  156. package/docs/form-components/en/number-editor.md +249 -0
  157. package/docs/form-components/en/options-multi-select.md +177 -0
  158. package/docs/form-components/en/options-select.md +83 -0
  159. package/docs/form-components/en/passwordeditor.md +538 -0
  160. package/docs/form-components/en/prompts-text-editor.md +241 -0
  161. package/docs/form-components/en/radiobutton.md +84 -0
  162. package/docs/form-components/en/switch.md +180 -0
  163. package/docs/form-components/en/text-editor.md +142 -0
  164. package/docs/form-components/en/time-editor.md +159 -0
  165. package/docs/form-components/en/unit-number-editor.md +164 -0
  166. package/docs/form-layout/cn/criteria-field.md +652 -0
  167. package/docs/form-layout/cn/flex-form.md +454 -0
  168. package/docs/form-layout/cn/flex-row-form.md +542 -0
  169. package/docs/form-layout/cn/form-field.md +923 -0
  170. package/docs/form-layout/cn/grid-form.md +676 -0
  171. package/docs/form-layout/en/criteria-field.md +652 -0
  172. package/docs/form-layout/en/flex-form.md +454 -0
  173. package/docs/form-layout/en/flex-row-form.md +542 -0
  174. package/docs/form-layout/en/form-field.md +923 -0
  175. package/docs/form-layout/en/grid-form.md +676 -0
  176. package/docs/global/cn/README.md +534 -0
  177. package/docs/global/en/README.md +534 -0
  178. package/docs/layout/cn/classiclayout.md +460 -0
  179. package/docs/layout/cn/headerlayout.md +524 -0
  180. package/docs/layout/cn/sidebarlayout.md +263 -0
  181. package/docs/layout/en/classiclayout.md +951 -0
  182. package/docs/layout/en/headerlayout.md +524 -0
  183. package/docs/layout/en/sidebarlayout.md +262 -0
  184. package/docs/misc/cn/README.md +1217 -0
  185. package/docs/misc/en/README.md +1217 -0
  186. package/docs/navigation/cn/breadcrumb.md +291 -0
  187. package/docs/navigation/cn/navigator.md +322 -0
  188. package/docs/navigation/cn/navigatormenu.md +512 -0
  189. package/docs/navigation/cn/progressbar.md +199 -0
  190. package/docs/navigation/cn/progressstepbar.md +299 -0
  191. package/docs/navigation/en/breadcrumb.md +291 -0
  192. package/docs/navigation/en/navigator.md +322 -0
  193. package/docs/navigation/en/navigatormenu.md +512 -0
  194. package/docs/navigation/en/progressbar.md +199 -0
  195. package/docs/navigation/en/progressstepbar.md +299 -0
  196. package/docs/search-filters/cn/daterange.md +1156 -0
  197. package/docs/search-filters/cn/numberrange.md +688 -0
  198. package/docs/search-filters/cn/searchbox.md +1582 -0
  199. package/docs/search-filters/en/daterange.md +1156 -0
  200. package/docs/search-filters/en/numberrange.md +688 -0
  201. package/docs/search-filters/en/searchbox.md +1582 -0
  202. package/package.json +53 -13
  203. package/dist/common-editor/DateInput.svelte +0 -27
  204. package/dist/i18n_resources/index.d.ts +0 -3
  205. package/dist/i18n_resources/index.js +0 -3
  206. /package/dist/{i18n_resources → i18nRes}/uniface_cn_resource.d.ts +0 -0
  207. /package/dist/{i18n_resources → i18nRes}/uniface_cn_resource.js +0 -0
  208. /package/dist/{i18n_resources → i18nRes}/uniface_en_resource.d.ts +0 -0
  209. /package/dist/{i18n_resources → i18nRes}/uniface_en_resource.js +0 -0
@@ -0,0 +1,923 @@
1
+ # FormField 组件
2
+
3
+ 表单字段组件,提供带标签、错误提示和必填标识的表单字段容器,是表单构建的核心组件。
4
+
5
+ ## 属性
6
+
7
+ | 属性 | 类型 | 默认值 | 描述 |
8
+ |------|------|--------|------|
9
+ | `label` | `string` | `'Label:'` | 字段标签文本 |
10
+ | `style` | `string` | `''` | 自定义样式 |
11
+ | `label$style` | `string \| null` | `null` | 标签样式 |
12
+ | `required` | `boolean` | `false` | 是否必填字段 |
13
+ | `error` | `string \| null` | `null` | 错误提示信息 |
14
+ | `labelSuffix` | `string` | `':'` | 标签后缀 |
15
+ | `label$alignment` | `'center' \| 'top'` | `'center'` | 标签对齐方式 |
16
+ | `class` | `string` | `''` | CSS类名 |
17
+
18
+ ## 使用示例
19
+
20
+ ### 基础表单字段
21
+
22
+ ```svelte
23
+ <script lang="ts">
24
+ import FormField, TextEditor, NumberEditor, DatePicker from '@ticatec/uniface-element/FormField, TextEditor, NumberEditor, DatePicker';
25
+
26
+ interface UserForm {
27
+ name: string;
28
+ age: number | null;
29
+ email: string;
30
+ birthDate: Date | null;
31
+ }
32
+
33
+ let userForm: UserForm = {
34
+ name: '',
35
+ age: null,
36
+ email: '',
37
+ birthDate: null
38
+ };
39
+ </script>
40
+
41
+ <!-- 基础字段 -->
42
+ <FormField label="姓名">
43
+ <TextEditor
44
+ variant="outlined"
45
+ bind:value={userForm.name}
46
+ placeholder="请输入姓名"
47
+ />
48
+ </FormField>
49
+
50
+ <!-- 数字字段 -->
51
+ <FormField label="年龄">
52
+ <NumberEditor
53
+ variant="outlined"
54
+ bind:value={userForm.age}
55
+ min={1}
56
+ max={120}
57
+ placeholder="请输入年龄"
58
+ />
59
+ </FormField>
60
+
61
+ <!-- 邮箱字段 -->
62
+ <FormField label="邮箱">
63
+ <TextEditor
64
+ variant="outlined"
65
+ bind:value={userForm.email}
66
+ placeholder="请输入邮箱地址"
67
+ />
68
+ </FormField>
69
+
70
+ <!-- 日期字段 -->
71
+ <FormField label="出生日期">
72
+ <DatePicker variant="outlined" bind:value={userForm.birthDate} />
73
+ </FormField>
74
+ ```
75
+
76
+ ### 必填字段和验证
77
+
78
+ ```svelte
79
+ <script lang="ts">
80
+ import FormField, TextEditor, OptionsSelect from '@ticatec/uniface-element/FormField, TextEditor, OptionsSelect';
81
+
82
+ interface RegistrationForm {
83
+ username: string;
84
+ password: string;
85
+ email: string;
86
+ gender: string;
87
+ }
88
+
89
+ let registrationForm: RegistrationForm = {
90
+ username: '',
91
+ password: '',
92
+ email: '',
93
+ gender: ''
94
+ };
95
+
96
+ let errors: Record<string, string> = {};
97
+
98
+ const genderOptions = [
99
+ { code: 'male', text: '男' },
100
+ { code: 'female', text: '女' },
101
+ { code: 'other', text: '其他' }
102
+ ];
103
+
104
+ const validateForm = (): void => {
105
+ errors = {};
106
+
107
+ if (!registrationForm.username) {
108
+ errors.username = '用户名不能为空';
109
+ } else if (registrationForm.username.length < 3) {
110
+ errors.username = '用户名至少需要3个字符';
111
+ }
112
+
113
+ if (!registrationForm.password) {
114
+ errors.password = '密码不能为空';
115
+ } else if (registrationForm.password.length < 8) {
116
+ errors.password = '密码至少需要8个字符';
117
+ }
118
+
119
+ if (!registrationForm.email) {
120
+ errors.email = '邮箱不能为空';
121
+ } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(registrationForm.email)) {
122
+ errors.email = '请输入有效的邮箱地址';
123
+ }
124
+ };
125
+
126
+ const handleSubmit = (): void => {
127
+ validateForm();
128
+ if (Object.keys(errors).length === 0) {
129
+ console.log('表单提交成功', registrationForm);
130
+ }
131
+ };
132
+ </script>
133
+
134
+ <div class="registration-form">
135
+ <h3>用户注册</h3>
136
+
137
+ <!-- 必填用户名字段 -->
138
+ <FormField required label="用户名" error={errors.username}>
139
+ <TextEditor
140
+ variant="outlined"
141
+ bind:value={registrationForm.username}
142
+ placeholder="请输入用户名"
143
+ on:input={() => errors.username = ''}
144
+ />
145
+ </FormField>
146
+
147
+ <!-- 必填密码字段 -->
148
+ <FormField required label="密码" error={errors.password}>
149
+ <TextEditor
150
+ variant="outlined"
151
+ type="password"
152
+ bind:value={registrationForm.password}
153
+ placeholder="请输入密码"
154
+ on:input={() => errors.password = ''}
155
+ />
156
+ </FormField>
157
+
158
+ <!-- 必填邮箱字段 -->
159
+ <FormField required label="邮箱地址" error={errors.email}>
160
+ <TextEditor
161
+ variant="outlined"
162
+ bind:value={registrationForm.email}
163
+ placeholder="请输入邮箱地址"
164
+ on:input={() => errors.email = ''}
165
+ />
166
+ </FormField>
167
+
168
+ <!-- 可选性别字段 -->
169
+ <FormField label="性别">
170
+ <OptionsSelect
171
+ variant="outlined"
172
+ options={genderOptions}
173
+ keyField="code"
174
+ textField="text"
175
+ bind:value={registrationForm.gender}
176
+ placeholder="请选择性别"
177
+ />
178
+ </FormField>
179
+
180
+ <div class="form-actions">
181
+ <button type="button" class="btn-primary" on:click={handleSubmit}>
182
+ 注册
183
+ </button>
184
+ </div>
185
+ </div>
186
+
187
+ <style>
188
+ .registration-form {
189
+ max-width: 400px;
190
+ margin: 0 auto;
191
+ padding: 30px;
192
+ background: #f8f9fa;
193
+ border-radius: 8px;
194
+ }
195
+
196
+ .registration-form h3 {
197
+ margin-bottom: 25px;
198
+ text-align: center;
199
+ color: #495057;
200
+ }
201
+
202
+ .form-actions {
203
+ margin-top: 25px;
204
+ text-align: center;
205
+ }
206
+
207
+ .btn-primary {
208
+ padding: 12px 40px;
209
+ background: #007bff;
210
+ color: white;
211
+ border: none;
212
+ border-radius: 4px;
213
+ font-size: 16px;
214
+ cursor: pointer;
215
+ }
216
+
217
+ .btn-primary:hover {
218
+ background: #0056b3;
219
+ }
220
+ </style>
221
+ ```
222
+
223
+ ### 自定义标签样式和对齐
224
+
225
+ ```svelte
226
+ <script lang="ts">
227
+ import FormField, TextEditor, MemoEditor from '@ticatec/uniface-element/FormField, TextEditor, MemoEditor';
228
+
229
+ let contactData = {
230
+ name: '',
231
+ company: '',
232
+ position: '',
233
+ description: ''
234
+ };
235
+ </script>
236
+
237
+ <div class="contact-form">
238
+ <h3>联系人信息</h3>
239
+
240
+ <!-- 重要字段标签样式 -->
241
+ <FormField
242
+ required
243
+ label="姓名"
244
+ label$style="color: #dc3545; font-weight: 600; font-size: 16px;"
245
+ labelSuffix="*"
246
+ >
247
+ <TextEditor
248
+ variant="outlined"
249
+ bind:value={contactData.name}
250
+ placeholder="请输入联系人姓名"
251
+ />
252
+ </FormField>
253
+
254
+ <!-- 普通字段标签样式 -->
255
+ <FormField
256
+ label="公司名称"
257
+ label$style="color: #28a745; font-weight: 500;"
258
+ >
259
+ <TextEditor
260
+ variant="outlined"
261
+ bind:value={contactData.company}
262
+ placeholder="请输入公司名称"
263
+ />
264
+ </FormField>
265
+
266
+ <!-- 自定义标签颜色 -->
267
+ <FormField
268
+ label="职位"
269
+ label$style="color: #6f42c1; font-style: italic;"
270
+ >
271
+ <TextEditor
272
+ variant="outlined"
273
+ bind:value={contactData.position}
274
+ placeholder="请输入职位"
275
+ />
276
+ </FormField>
277
+
278
+ <!-- 顶部对齐的多行文本 -->
279
+ <FormField
280
+ label="详细描述"
281
+ label$alignment="top"
282
+ label$style="color: #495057; font-weight: 500; padding-top: 8px;"
283
+ >
284
+ <MemoEditor
285
+ variant="outlined"
286
+ bind:value={contactData.description}
287
+ placeholder="请输入详细描述"
288
+ rows={4}
289
+ maxLength={500}
290
+ showIndicator
291
+ />
292
+ </FormField>
293
+ </div>
294
+
295
+ <style>
296
+ .contact-form {
297
+ max-width: 600px;
298
+ margin: 0 auto;
299
+ padding: 30px;
300
+ }
301
+
302
+ .contact-form h3 {
303
+ margin-bottom: 25px;
304
+ color: #495057;
305
+ border-bottom: 2px solid #007bff;
306
+ padding-bottom: 10px;
307
+ }
308
+ </style>
309
+ ```
310
+
311
+ ### 长标签文本处理
312
+
313
+ ```svelte
314
+ <script lang="ts">
315
+ import FormField, TextEditor, CheckBox from '@ticatec/uniface-element/FormField, TextEditor, CheckBox';
316
+
317
+ let advancedSettings = {
318
+ serverEndpoint: '',
319
+ apiKey: '',
320
+ enableLogging: false,
321
+ autoRetry: false
322
+ };
323
+ </script>
324
+
325
+ <div class="settings-form">
326
+ <h3>高级设置</h3>
327
+
328
+ <!-- 长标签自动省略 -->
329
+ <FormField
330
+ label="服务器端点URL地址(支持HTTP和HTTPS协议)"
331
+ required
332
+ >
333
+ <TextEditor
334
+ variant="outlined"
335
+ bind:value={advancedSettings.serverEndpoint}
336
+ placeholder="请输入服务器端点URL"
337
+ />
338
+ </FormField>
339
+
340
+ <!-- 长标签使用自定义样式 -->
341
+ <FormField
342
+ label="API密钥(用于身份验证和访问控制)"
343
+ label$style="font-size: 14px; line-height: 1.2; white-space: normal;"
344
+ required
345
+ >
346
+ <TextEditor
347
+ variant="outlined"
348
+ type="password"
349
+ bind:value={advancedSettings.apiKey}
350
+ placeholder="请输入API密钥"
351
+ />
352
+ </FormField>
353
+
354
+ <!-- 开关类型字段 -->
355
+ <FormField label="启用详细日志记录功能" labelSuffix="">
356
+ <CheckBox
357
+ label="记录所有API请求和响应详情"
358
+ bind:value={advancedSettings.enableLogging}
359
+ />
360
+ </FormField>
361
+
362
+ <!-- 开关类型字段 -->
363
+ <FormField label="启用自动重试机制" labelSuffix="">
364
+ <CheckBox
365
+ label="当请求失败时自动重试最多3次"
366
+ bind:value={advancedSettings.autoRetry}
367
+ />
368
+ </FormField>
369
+ </div>
370
+
371
+ <style>
372
+ .settings-form {
373
+ max-width: 700px;
374
+ margin: 0 auto;
375
+ padding: 30px;
376
+ background: white;
377
+ border-radius: 8px;
378
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
379
+ }
380
+
381
+ .settings-form h3 {
382
+ margin-bottom: 25px;
383
+ color: #333;
384
+ font-size: 20px;
385
+ }
386
+ </style>
387
+ ```
388
+
389
+ ### 表单字段组合使用
390
+
391
+ ```svelte
392
+ <script lang="ts">
393
+ import FormField, TextEditor, NumberEditor, DatePicker, OptionsSelect, CheckBox from '@ticatec/uniface-element/FormField, TextEditor, NumberEditor, DatePicker, OptionsSelect, CheckBox';
394
+
395
+ interface EmployeeForm {
396
+ personalInfo: {
397
+ firstName: string;
398
+ lastName: string;
399
+ email: string;
400
+ phone: string;
401
+ birthDate: Date | null;
402
+ };
403
+ workInfo: {
404
+ employeeId: string;
405
+ department: string;
406
+ position: string;
407
+ salary: number | null;
408
+ startDate: Date | null;
409
+ };
410
+ settings: {
411
+ receiveEmails: boolean;
412
+ isManager: boolean;
413
+ };
414
+ }
415
+
416
+ let employeeForm: EmployeeForm = {
417
+ personalInfo: {
418
+ firstName: '',
419
+ lastName: '',
420
+ email: '',
421
+ phone: '',
422
+ birthDate: null
423
+ },
424
+ workInfo: {
425
+ employeeId: '',
426
+ department: '',
427
+ position: '',
428
+ salary: null,
429
+ startDate: null
430
+ },
431
+ settings: {
432
+ receiveEmails: true,
433
+ isManager: false
434
+ }
435
+ };
436
+
437
+ let validationErrors: Record<string, string> = {};
438
+
439
+ const departments = [
440
+ { code: 'engineering', text: '工程部' },
441
+ { code: 'marketing', text: '市场部' },
442
+ { code: 'sales', text: '销售部' },
443
+ { code: 'hr', text: '人事部' }
444
+ ];
445
+
446
+ const validateForm = (): boolean => {
447
+ validationErrors = {};
448
+
449
+ if (!employeeForm.personalInfo.firstName) {
450
+ validationErrors.firstName = '姓氏不能为空';
451
+ }
452
+
453
+ if (!employeeForm.personalInfo.lastName) {
454
+ validationErrors.lastName = '名字不能为空';
455
+ }
456
+
457
+ if (!employeeForm.personalInfo.email) {
458
+ validationErrors.email = '邮箱不能为空';
459
+ } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(employeeForm.personalInfo.email)) {
460
+ validationErrors.email = '请输入有效的邮箱地址';
461
+ }
462
+
463
+ if (!employeeForm.workInfo.employeeId) {
464
+ validationErrors.employeeId = '员工ID不能为空';
465
+ }
466
+
467
+ return Object.keys(validationErrors).length === 0;
468
+ };
469
+
470
+ const handleSave = (): void => {
471
+ if (validateForm()) {
472
+ console.log('员工信息保存成功', employeeForm);
473
+ alert('员工信息已保存');
474
+ }
475
+ };
476
+
477
+ const clearFieldError = (field: string): void => {
478
+ if (validationErrors[field]) {
479
+ validationErrors = { ...validationErrors };
480
+ delete validationErrors[field];
481
+ }
482
+ };
483
+ </script>
484
+
485
+ <div class="employee-form">
486
+ <h2>员工信息管理</h2>
487
+
488
+ <!-- 个人信息部分 -->
489
+ <section class="form-section">
490
+ <h3>个人信息</h3>
491
+
492
+ <div class="form-row">
493
+ <div class="form-col">
494
+ <FormField required label="姓" error={validationErrors.firstName}>
495
+ <TextEditor
496
+ variant="outlined"
497
+ bind:value={employeeForm.personalInfo.firstName}
498
+ placeholder="请输入姓氏"
499
+ on:input={() => clearFieldError('firstName')}
500
+ />
501
+ </FormField>
502
+ </div>
503
+
504
+ <div class="form-col">
505
+ <FormField required label="名" error={validationErrors.lastName}>
506
+ <TextEditor
507
+ variant="outlined"
508
+ bind:value={employeeForm.personalInfo.lastName}
509
+ placeholder="请输入名字"
510
+ on:input={() => clearFieldError('lastName')}
511
+ />
512
+ </FormField>
513
+ </div>
514
+ </div>
515
+
516
+ <FormField required label="邮箱地址" error={validationErrors.email}>
517
+ <TextEditor
518
+ variant="outlined"
519
+ bind:value={employeeForm.personalInfo.email}
520
+ placeholder="请输入邮箱地址"
521
+ on:input={() => clearFieldError('email')}
522
+ />
523
+ </FormField>
524
+
525
+ <FormField label="联系电话">
526
+ <TextEditor
527
+ variant="outlined"
528
+ bind:value={employeeForm.personalInfo.phone}
529
+ placeholder="请输入联系电话"
530
+ />
531
+ </FormField>
532
+
533
+ <FormField label="出生日期">
534
+ <DatePicker
535
+ variant="outlined"
536
+ bind:value={employeeForm.personalInfo.birthDate}
537
+ />
538
+ </FormField>
539
+ </section>
540
+
541
+ <!-- 工作信息部分 -->
542
+ <section class="form-section">
543
+ <h3>工作信息</h3>
544
+
545
+ <FormField required label="员工ID" error={validationErrors.employeeId}>
546
+ <TextEditor
547
+ variant="outlined"
548
+ bind:value={employeeForm.workInfo.employeeId}
549
+ placeholder="请输入员工ID"
550
+ on:input={() => clearFieldError('employeeId')}
551
+ />
552
+ </FormField>
553
+
554
+ <div class="form-row">
555
+ <div class="form-col">
556
+ <FormField label="部门">
557
+ <OptionsSelect
558
+ variant="outlined"
559
+ options={departments}
560
+ keyField="code"
561
+ textField="text"
562
+ bind:value={employeeForm.workInfo.department}
563
+ placeholder="请选择部门"
564
+ />
565
+ </FormField>
566
+ </div>
567
+
568
+ <div class="form-col">
569
+ <FormField label="职位">
570
+ <TextEditor
571
+ variant="outlined"
572
+ bind:value={employeeForm.workInfo.position}
573
+ placeholder="请输入职位"
574
+ />
575
+ </FormField>
576
+ </div>
577
+ </div>
578
+
579
+ <div class="form-row">
580
+ <div class="form-col">
581
+ <FormField label="薪资">
582
+ <NumberEditor
583
+ variant="outlined"
584
+ bind:value={employeeForm.workInfo.salary}
585
+ min={0}
586
+ precision={0}
587
+ placeholder="请输入薪资"
588
+ />
589
+ </FormField>
590
+ </div>
591
+
592
+ <div class="form-col">
593
+ <FormField label="入职日期">
594
+ <DatePicker
595
+ variant="outlined"
596
+ bind:value={employeeForm.workInfo.startDate}
597
+ />
598
+ </FormField>
599
+ </div>
600
+ </div>
601
+ </section>
602
+
603
+ <!-- 设置选项部分 -->
604
+ <section class="form-section">
605
+ <h3>账户设置</h3>
606
+
607
+ <FormField label="通知偏好" labelSuffix="">
608
+ <CheckBox
609
+ label="接收邮件通知"
610
+ bind:value={employeeForm.settings.receiveEmails}
611
+ />
612
+ </FormField>
613
+
614
+ <FormField label="权限设置" labelSuffix="">
615
+ <CheckBox
616
+ label="管理员权限"
617
+ bind:value={employeeForm.settings.isManager}
618
+ />
619
+ </FormField>
620
+ </section>
621
+
622
+ <!-- 操作按钮 -->
623
+ <div class="form-actions">
624
+ <button type="button" class="btn-secondary">
625
+ 取消
626
+ </button>
627
+ <button type="button" class="btn-primary" on:click={handleSave}>
628
+ 保存员工信息
629
+ </button>
630
+ </div>
631
+ </div>
632
+
633
+ <style>
634
+ .employee-form {
635
+ max-width: 800px;
636
+ margin: 0 auto;
637
+ padding: 30px;
638
+ background: white;
639
+ border-radius: 12px;
640
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
641
+ }
642
+
643
+ .employee-form h2 {
644
+ margin-bottom: 30px;
645
+ text-align: center;
646
+ color: #333;
647
+ font-size: 24px;
648
+ }
649
+
650
+ .form-section {
651
+ margin-bottom: 35px;
652
+ padding: 25px;
653
+ border: 1px solid #dee2e6;
654
+ border-radius: 8px;
655
+ background: #f8f9fa;
656
+ }
657
+
658
+ .form-section h3 {
659
+ margin: 0 0 20px 0;
660
+ color: #495057;
661
+ font-size: 18px;
662
+ border-bottom: 2px solid #007bff;
663
+ padding-bottom: 8px;
664
+ }
665
+
666
+ .form-row {
667
+ display: grid;
668
+ grid-template-columns: 1fr 1fr;
669
+ gap: 20px;
670
+ margin-bottom: 16px;
671
+ }
672
+
673
+ .form-col {
674
+ min-width: 0;
675
+ }
676
+
677
+ .form-actions {
678
+ display: flex;
679
+ gap: 15px;
680
+ justify-content: center;
681
+ padding-top: 25px;
682
+ border-top: 1px solid #dee2e6;
683
+ }
684
+
685
+ .btn-primary, .btn-secondary {
686
+ padding: 12px 24px;
687
+ border: none;
688
+ border-radius: 6px;
689
+ font-size: 14px;
690
+ font-weight: 500;
691
+ cursor: pointer;
692
+ transition: all 0.2s;
693
+ }
694
+
695
+ .btn-primary {
696
+ background: #007bff;
697
+ color: white;
698
+ }
699
+
700
+ .btn-secondary {
701
+ background: #6c757d;
702
+ color: white;
703
+ }
704
+
705
+ .btn-primary:hover {
706
+ background: #0056b3;
707
+ transform: translateY(-1px);
708
+ }
709
+
710
+ .btn-secondary:hover {
711
+ background: #545b62;
712
+ transform: translateY(-1px);
713
+ }
714
+
715
+ @media (max-width: 768px) {
716
+ .form-row {
717
+ grid-template-columns: 1fr;
718
+ gap: 16px;
719
+ }
720
+
721
+ .employee-form {
722
+ padding: 20px;
723
+ }
724
+
725
+ .form-section {
726
+ padding: 20px;
727
+ }
728
+ }
729
+ </style>
730
+ ```
731
+
732
+ ## 标签对齐方式
733
+
734
+ ### 居中对齐(默认)
735
+ ```svelte
736
+ <FormField label="姓名" label$alignment="center">
737
+ <TextEditor />
738
+ </FormField>
739
+ ```
740
+
741
+ ### 顶部对齐
742
+ ```svelte
743
+ <!-- 适用于多行输入控件 -->
744
+ <FormField label="详细描述" label$alignment="top">
745
+ <MemoEditor rows={4} />
746
+ </FormField>
747
+ ```
748
+
749
+ ## 错误提示处理
750
+
751
+ ```svelte
752
+ <script lang="ts">
753
+ let formData = { email: '' };
754
+ let errors: Record<string, string> = {};
755
+
756
+ const validateEmail = (): void => {
757
+ if (!formData.email) {
758
+ errors.email = '邮箱不能为空';
759
+ } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
760
+ errors.email = '请输入有效的邮箱地址';
761
+ } else {
762
+ delete errors.email;
763
+ errors = { ...errors };
764
+ }
765
+ };
766
+ </script>
767
+
768
+ <FormField required label="邮箱" error={errors.email}>
769
+ <TextEditor
770
+ bind:value={formData.email}
771
+ on:blur={validateEmail}
772
+ />
773
+ </FormField>
774
+ ```
775
+
776
+ ## 样式定制
777
+
778
+ ```css
779
+ /* 表单字段容器 */
780
+ :global(.uniface-form-field) {
781
+ margin-bottom: 20px;
782
+ }
783
+
784
+ /* 表单内容区域 */
785
+ :global(.uniface-form-field .form-content) {
786
+ display: flex;
787
+ flex-direction: column;
788
+ gap: 8px;
789
+ }
790
+
791
+ /* 标签样式 */
792
+ :global(.uniface-form-field .field-label) {
793
+ font-weight: 500;
794
+ color: #495057;
795
+ margin-bottom: 4px;
796
+ }
797
+
798
+ /* 必填标识样式 */
799
+ :global(.uniface-form-field .required-indicator) {
800
+ color: #dc3545;
801
+ margin-right: 4px;
802
+ }
803
+
804
+ /* 顶部对齐标签 */
805
+ :global(.uniface-form-field .field-label.vert-top) {
806
+ align-self: flex-start;
807
+ }
808
+
809
+ /* 错误提示样式 */
810
+ :global(.uniface-form-field .field-hint) {
811
+ color: #dc3545;
812
+ font-size: 12px;
813
+ margin-top: 4px;
814
+ }
815
+
816
+ /* 字段内容区域 */
817
+ :global(.uniface-form-field .field) {
818
+ flex: 1;
819
+ }
820
+
821
+ /* 水平布局样式 */
822
+ :global(.field-layout-horizontal .uniface-form-field .form-content) {
823
+ flex-direction: row;
824
+ align-items: center;
825
+ gap: 12px;
826
+ }
827
+
828
+ :global(.field-layout-horizontal .uniface-form-field .field-label) {
829
+ flex-shrink: 0;
830
+ margin-bottom: 0;
831
+ min-width: 120px;
832
+ }
833
+
834
+ /* 响应式样式 */
835
+ @media (max-width: 768px) {
836
+ :global(.field-layout-horizontal .uniface-form-field .form-content) {
837
+ flex-direction: column;
838
+ align-items: stretch;
839
+ }
840
+
841
+ :global(.field-layout-horizontal .uniface-form-field .field-label) {
842
+ min-width: auto;
843
+ margin-bottom: 4px;
844
+ }
845
+ }
846
+ ```
847
+
848
+ ## 最佳实践
849
+
850
+ ### 1. 合理使用必填标识
851
+ ```svelte
852
+ <!-- 必须填写的字段 -->
853
+ <FormField required label="用户名">
854
+ <TextEditor />
855
+ </FormField>
856
+
857
+ <!-- 可选字段 -->
858
+ <FormField label="昵称">
859
+ <TextEditor />
860
+ </FormField>
861
+ ```
862
+
863
+ ### 2. 及时显示验证错误
864
+ ```svelte
865
+ <script lang="ts">
866
+ const clearError = (field: string): void => {
867
+ if (errors[field]) {
868
+ delete errors[field];
869
+ errors = { ...errors };
870
+ }
871
+ };
872
+ </script>
873
+
874
+ <FormField required label="邮箱" error={errors.email}>
875
+ <TextEditor
876
+ bind:value={formData.email}
877
+ on:input={() => clearError('email')}
878
+ />
879
+ </FormField>
880
+ ```
881
+
882
+ ### 3. 选择合适的标签对齐方式
883
+ ```svelte
884
+ <!-- 单行输入:使用居中对齐 -->
885
+ <FormField label="姓名" label$alignment="center">
886
+ <TextEditor />
887
+ </FormField>
888
+
889
+ <!-- 多行输入:使用顶部对齐 -->
890
+ <FormField label="备注" label$alignment="top">
891
+ <MemoEditor rows={3} />
892
+ </FormField>
893
+ ```
894
+
895
+ ### 4. 自定义标签样式
896
+ ```svelte
897
+ <!-- 重要字段突出显示 -->
898
+ <FormField
899
+ required
900
+ label="密码"
901
+ label$style="color: #dc3545; font-weight: 600;"
902
+ >
903
+ <TextEditor type="password" />
904
+ </FormField>
905
+
906
+ <!-- 次要字段淡化显示 -->
907
+ <FormField
908
+ label="备注"
909
+ label$style="color: #6c757d; font-size: 14px;"
910
+ >
911
+ <TextEditor />
912
+ </FormField>
913
+ ```
914
+
915
+ ## 组件优势
916
+
917
+ 1. **完整的字段功能** - 提供标签、必填标识、错误提示的完整字段支持
918
+ 2. **灵活的布局选项** - 支持标签的居中和顶部对齐方式
919
+ 3. **丰富的样式定制** - 支持标签样式、后缀和整体样式的定制
920
+ 4. **完善的验证支持** - 内置错误提示显示机制
921
+ 5. **响应式友好** - 支持水平和垂直布局的响应式切换
922
+ 6. **易于集成** - 与所有表单控件无缝配合使用
923
+ 7. **一致性保证** - 统一的字段样式和行为规范