@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,688 @@
1
+ # NumberRange 数值范围组件
2
+
3
+ 一个数值范围输入组件,允许用户指定两个数字之间的范围,通常用于按数值条件过滤数据,如价格范围、年龄范围或数量过滤器。
4
+
5
+ ## 概述
6
+
7
+ NumberRange 组件为选择数值范围提供了直观的界面,具有内置验证、自动范围约束和清除功能。它具有两个相互连接的数字输入框,可以智能地相互验证,确保"从"值始终小于或等于"到"值。非常适合搜索过滤器、数据查询和任何需要数值范围选择的应用程序。
8
+
9
+ ## 安装
10
+
11
+ ```typescript
12
+ import NumberRange from '@ticatec/uniface-element/NumberRange';
13
+ import type { OnChangeHandler } from '@ticatec/uniface-element/NumberRange';
14
+ ```
15
+
16
+ ## 基本用法
17
+
18
+ ```svelte
19
+ <script lang="ts">
20
+ import NumberRange from '@ticatec/uniface-element/NumberRange';
21
+
22
+ let fromValue: number = 0;
23
+ let toValue: number = 100;
24
+ </script>
25
+
26
+ <NumberRange
27
+ bind:fromValue
28
+ bind:toValue
29
+ variant="outlined"
30
+ />
31
+ ```
32
+
33
+ ## 属性
34
+
35
+ | 属性 | 类型 | 默认值 | 描述 |
36
+ |------|------|--------|------|
37
+ | `variant` | `'' \| 'plain' \| 'outlined' \| 'filled'` | `''` | 视觉样式变体 |
38
+ | `compact` | `boolean` | `false` | 启用紧凑布局以适应密集表单 |
39
+ | `class` | `string` | `''` | 额外的 CSS 类名 |
40
+ | `style` | `string` | `''` | 自定义内联样式 |
41
+ | `min` | `number \| null` | `null` | 全局最小允许值 |
42
+ | `max` | `number \| null` | `null` | 全局最大允许值 |
43
+ | `fromValue` | `number` | - | 范围的起始值(可绑定) |
44
+ | `toValue` | `number` | - | 范围的结束值(可绑定) |
45
+ | `allowNegative` | `boolean` | `false` | 在输入框中允许负数 |
46
+
47
+ ## 功能特性
48
+
49
+ - **智能验证**:自动验证范围约束(从 ≤ 到)
50
+ - **跨字段限制**:"从"值设置"到"的最大值,"到"值设置"从"的最小值
51
+ - **清除功能**:当存在值时显示的内置清除按钮
52
+ - **自动聚焦**:清除值后聚焦第一个输入框
53
+ - **负数支持**:可选支持负数范围
54
+ - **一致样式**:通过变体支持与其他表单组件匹配
55
+
56
+ ## 类型定义
57
+
58
+ ```typescript
59
+ /**
60
+ * 变更事件处理器类型
61
+ */
62
+ type OnChangeHandler<T> = (value: T) => void;
63
+ ```
64
+
65
+ ## 使用示例
66
+
67
+ ### 价格范围过滤器
68
+
69
+ ```svelte
70
+ <script lang="ts">
71
+ import NumberRange from '@ticatec/uniface-element/NumberRange';
72
+
73
+ let minPrice: number = 0;
74
+ let maxPrice: number = 1000;
75
+
76
+ // 响应式语句处理价格范围变化
77
+ $: if (minPrice !== undefined && maxPrice !== undefined) {
78
+ filterProductsByPrice(minPrice, maxPrice);
79
+ }
80
+
81
+ function filterProductsByPrice(min: number, max: number) {
82
+ console.log(`过滤产品价格范围:¥${min} 到 ¥${max}`);
83
+ // 在此实现过滤逻辑
84
+ }
85
+
86
+ function resetPriceFilter() {
87
+ minPrice = 0;
88
+ maxPrice = 1000;
89
+ }
90
+ </script>
91
+
92
+ <div class="price-filter">
93
+ <h3>价格范围</h3>
94
+
95
+ <NumberRange
96
+ bind:fromValue={minPrice}
97
+ bind:toValue={maxPrice}
98
+ variant="outlined"
99
+ min={0}
100
+ max={10000}
101
+ style="width: 300px;"
102
+ />
103
+
104
+ <div class="price-display">
105
+ <span class="price-label">
106
+ ¥{minPrice?.toLocaleString() || 0} - ¥{maxPrice?.toLocaleString() || 0}
107
+ </span>
108
+ </div>
109
+
110
+ <button class="reset-btn" on:click={resetPriceFilter}>
111
+ 重置过滤器
112
+ </button>
113
+ </div>
114
+
115
+ <style>
116
+ .price-filter {
117
+ padding: 16px;
118
+ background: #f8f9fa;
119
+ border-radius: 8px;
120
+ max-width: 400px;
121
+ }
122
+
123
+ .price-filter h3 {
124
+ margin: 0 0 12px 0;
125
+ color: #333;
126
+ font-size: 1.1rem;
127
+ }
128
+
129
+ .price-display {
130
+ margin: 12px 0;
131
+ text-align: center;
132
+ }
133
+
134
+ .price-label {
135
+ font-weight: 500;
136
+ color: #007bff;
137
+ font-size: 1.1rem;
138
+ }
139
+
140
+ .reset-btn {
141
+ width: 100%;
142
+ padding: 8px 16px;
143
+ background: #6c757d;
144
+ color: white;
145
+ border: none;
146
+ border-radius: 4px;
147
+ cursor: pointer;
148
+ margin-top: 8px;
149
+ }
150
+
151
+ .reset-btn:hover {
152
+ background: #5a6268;
153
+ }
154
+ </style>
155
+ ```
156
+
157
+ ### 年龄范围选择器
158
+
159
+ ```svelte
160
+ <script lang="ts">
161
+ import NumberRange from '@ticatec/uniface-element/NumberRange';
162
+
163
+ let minAge: number = 18;
164
+ let maxAge: number = 65;
165
+ let selectedProfiles = [];
166
+
167
+ // 按年龄过滤用户资料的函数
168
+ function filterProfilesByAge(min: number, max: number) {
169
+ // 模拟资料数据
170
+ const allProfiles = [
171
+ { id: 1, name: '张小明', age: 25 },
172
+ { id: 2, name: '李小红', age: 35 },
173
+ { id: 3, name: '王小刚', age: 45 },
174
+ { id: 4, name: '赵小丽', age: 28 },
175
+ { id: 5, name: '陈小华', age: 52 }
176
+ ];
177
+
178
+ selectedProfiles = allProfiles.filter(profile =>
179
+ profile.age >= min && profile.age <= max
180
+ );
181
+ }
182
+
183
+ // 初始加载和值变化时进行过滤
184
+ $: filterProfilesByAge(minAge || 0, maxAge || 100);
185
+ </script>
186
+
187
+ <div class="age-filter-demo">
188
+ <div class="filter-section">
189
+ <h3>按年龄范围过滤</h3>
190
+
191
+ <NumberRange
192
+ bind:fromValue={minAge}
193
+ bind:toValue={maxAge}
194
+ variant="filled"
195
+ min={16}
196
+ max={100}
197
+ style="width: 250px;"
198
+ compact={true}
199
+ />
200
+
201
+ <div class="age-summary">
202
+ <p>显示年龄 {minAge} 到 {maxAge} 岁的资料</p>
203
+ <p class="result-count">找到 {selectedProfiles.length} 个资料</p>
204
+ </div>
205
+ </div>
206
+
207
+ <div class="results-section">
208
+ <h4>匹配的资料</h4>
209
+ {#if selectedProfiles.length > 0}
210
+ <div class="profiles-grid">
211
+ {#each selectedProfiles as profile}
212
+ <div class="profile-card">
213
+ <div class="profile-name">{profile.name}</div>
214
+ <div class="profile-age">年龄: {profile.age}</div>
215
+ </div>
216
+ {/each}
217
+ </div>
218
+ {:else}
219
+ <p class="no-results">没有资料匹配所选年龄范围</p>
220
+ {/if}
221
+ </div>
222
+ </div>
223
+
224
+ <style>
225
+ .age-filter-demo {
226
+ max-width: 600px;
227
+ margin: 0 auto;
228
+ padding: 20px;
229
+ }
230
+
231
+ .filter-section {
232
+ background: #ffffff;
233
+ padding: 20px;
234
+ border-radius: 8px;
235
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
236
+ margin-bottom: 20px;
237
+ }
238
+
239
+ .filter-section h3 {
240
+ margin: 0 0 16px 0;
241
+ color: #333;
242
+ }
243
+
244
+ .age-summary {
245
+ margin-top: 12px;
246
+ padding: 12px;
247
+ background: #e3f2fd;
248
+ border-radius: 4px;
249
+ text-align: center;
250
+ }
251
+
252
+ .result-count {
253
+ font-weight: 600;
254
+ color: #1976d2;
255
+ margin: 4px 0 0 0;
256
+ }
257
+
258
+ .results-section h4 {
259
+ margin: 0 0 16px 0;
260
+ color: #333;
261
+ }
262
+
263
+ .profiles-grid {
264
+ display: grid;
265
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
266
+ gap: 12px;
267
+ }
268
+
269
+ .profile-card {
270
+ padding: 16px;
271
+ background: #f8f9fa;
272
+ border-radius: 6px;
273
+ border-left: 4px solid #007bff;
274
+ }
275
+
276
+ .profile-name {
277
+ font-weight: 500;
278
+ color: #333;
279
+ margin-bottom: 4px;
280
+ }
281
+
282
+ .profile-age {
283
+ color: #666;
284
+ font-size: 0.9rem;
285
+ }
286
+
287
+ .no-results {
288
+ text-align: center;
289
+ color: #666;
290
+ font-style: italic;
291
+ padding: 40px 20px;
292
+ }
293
+ </style>
294
+ ```
295
+
296
+ ### 库存范围查询
297
+
298
+ ```svelte
299
+ <script lang="ts">
300
+ import NumberRange from '@ticatec/uniface-element/NumberRange';
301
+
302
+ let minQuantity: number = 0;
303
+ let maxQuantity: number = 500;
304
+
305
+ // 模拟库存数据
306
+ let inventoryItems = [
307
+ { id: 'A001', name: 'Widget Alpha', quantity: 45, category: '电子产品' },
308
+ { id: 'B002', name: 'Gadget Beta', quantity: 120, category: '工具' },
309
+ { id: 'C003', name: 'Device Gamma', quantity: 8, category: '电子产品' },
310
+ { id: 'D004', name: 'Tool Delta', quantity: 300, category: '工具' },
311
+ { id: 'E005', name: 'Part Epsilon', quantity: 750, category: '配件' }
312
+ ];
313
+
314
+ let filteredItems = [];
315
+
316
+ function applyQuantityFilter() {
317
+ filteredItems = inventoryItems.filter(item =>
318
+ item.quantity >= (minQuantity || 0) &&
319
+ item.quantity <= (maxQuantity || Infinity)
320
+ );
321
+ }
322
+
323
+ // 当范围变化时应用过滤器
324
+ $: {
325
+ minQuantity, maxQuantity;
326
+ applyQuantityFilter();
327
+ }
328
+
329
+ function exportResults() {
330
+ const csvContent = [
331
+ 'ID,名称,数量,类别',
332
+ ...filteredItems.map(item =>
333
+ `${item.id},${item.name},${item.quantity},${item.category}`
334
+ )
335
+ ].join('\n');
336
+
337
+ console.log('导出数据:', csvContent);
338
+ alert('数据已导出到控制台');
339
+ }
340
+
341
+ // 预定义范围预设
342
+ const presets = [
343
+ { label: '低库存 (0-50)', min: 0, max: 50 },
344
+ { label: '中等库存 (51-200)', min: 51, max: 200 },
345
+ { label: '高库存 (201-500)', min: 201, max: 500 },
346
+ { label: '库存过多 (500+)', min: 500, max: 1000 }
347
+ ];
348
+
349
+ function applyPreset(preset) {
350
+ minQuantity = preset.min;
351
+ maxQuantity = preset.max;
352
+ }
353
+ </script>
354
+
355
+ <div class="inventory-query">
356
+ <header class="query-header">
357
+ <h2>库存数量过滤器</h2>
358
+ <p>按数量范围过滤库存物品</p>
359
+ </header>
360
+
361
+ <div class="filter-controls">
362
+ <div class="range-input-section">
363
+ <label>数量范围:</label>
364
+ <NumberRange
365
+ bind:fromValue={minQuantity}
366
+ bind:toValue={maxQuantity}
367
+ variant="outlined"
368
+ min={0}
369
+ max={1000}
370
+ style="width: 280px;"
371
+ />
372
+ </div>
373
+
374
+ <div class="presets-section">
375
+ <label>快速预设:</label>
376
+ <div class="preset-buttons">
377
+ {#each presets as preset}
378
+ <button
379
+ class="preset-btn"
380
+ on:click={() => applyPreset(preset)}
381
+ >
382
+ {preset.label}
383
+ </button>
384
+ {/each}
385
+ </div>
386
+ </div>
387
+ </div>
388
+
389
+ <div class="results-section">
390
+ <div class="results-header">
391
+ <h3>结果 ({filteredItems.length} 项)</h3>
392
+ {#if filteredItems.length > 0}
393
+ <button class="export-btn" on:click={exportResults}>
394
+ 导出 CSV
395
+ </button>
396
+ {/if}
397
+ </div>
398
+
399
+ <div class="results-table">
400
+ {#if filteredItems.length > 0}
401
+ <table>
402
+ <thead>
403
+ <tr>
404
+ <th>物品 ID</th>
405
+ <th>名称</th>
406
+ <th>数量</th>
407
+ <th>类别</th>
408
+ <th>状态</th>
409
+ </tr>
410
+ </thead>
411
+ <tbody>
412
+ {#each filteredItems as item}
413
+ <tr>
414
+ <td class="item-id">{item.id}</td>
415
+ <td class="item-name">{item.name}</td>
416
+ <td class="item-quantity">{item.quantity}</td>
417
+ <td class="item-category">{item.category}</td>
418
+ <td class="item-status">
419
+ <span class="status-badge status-{item.quantity < 50 ? 'low' : item.quantity < 200 ? 'medium' : 'high'}">
420
+ {item.quantity < 50 ? '低' : item.quantity < 200 ? '中' : '高'}
421
+ </span>
422
+ </td>
423
+ </tr>
424
+ {/each}
425
+ </tbody>
426
+ </table>
427
+ {:else}
428
+ <div class="no-results">
429
+ <p>在指定数量范围内未找到库存物品。</p>
430
+ <p class="suggestion">尝试调整范围或使用预设过滤器。</p>
431
+ </div>
432
+ {/if}
433
+ </div>
434
+ </div>
435
+ </div>
436
+
437
+ <style>
438
+ .inventory-query {
439
+ max-width: 900px;
440
+ margin: 0 auto;
441
+ padding: 20px;
442
+ }
443
+
444
+ .query-header {
445
+ text-align: center;
446
+ margin-bottom: 30px;
447
+ }
448
+
449
+ .query-header h2 {
450
+ color: #333;
451
+ margin: 0 0 8px 0;
452
+ }
453
+
454
+ .query-header p {
455
+ color: #666;
456
+ margin: 0;
457
+ }
458
+
459
+ .filter-controls {
460
+ display: flex;
461
+ flex-wrap: wrap;
462
+ gap: 30px;
463
+ align-items: flex-end;
464
+ margin-bottom: 30px;
465
+ padding: 20px;
466
+ background: #f8f9fa;
467
+ border-radius: 8px;
468
+ }
469
+
470
+ .range-input-section,
471
+ .presets-section {
472
+ flex: 1;
473
+ min-width: 250px;
474
+ }
475
+
476
+ .range-input-section label,
477
+ .presets-section label {
478
+ display: block;
479
+ font-weight: 500;
480
+ margin-bottom: 8px;
481
+ color: #333;
482
+ }
483
+
484
+ .preset-buttons {
485
+ display: flex;
486
+ flex-wrap: wrap;
487
+ gap: 8px;
488
+ }
489
+
490
+ .preset-btn {
491
+ padding: 6px 12px;
492
+ background: #e9ecef;
493
+ border: 1px solid #ced4da;
494
+ border-radius: 4px;
495
+ cursor: pointer;
496
+ font-size: 0.875rem;
497
+ transition: all 0.2s;
498
+ }
499
+
500
+ .preset-btn:hover {
501
+ background: #dee2e6;
502
+ border-color: #adb5bd;
503
+ }
504
+
505
+ .results-section {
506
+ background: white;
507
+ border-radius: 8px;
508
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
509
+ overflow: hidden;
510
+ }
511
+
512
+ .results-header {
513
+ display: flex;
514
+ justify-content: space-between;
515
+ align-items: center;
516
+ padding: 20px;
517
+ background: #f8f9fa;
518
+ border-bottom: 1px solid #dee2e6;
519
+ }
520
+
521
+ .results-header h3 {
522
+ margin: 0;
523
+ color: #333;
524
+ }
525
+
526
+ .export-btn {
527
+ padding: 8px 16px;
528
+ background: #007bff;
529
+ color: white;
530
+ border: none;
531
+ border-radius: 4px;
532
+ cursor: pointer;
533
+ font-size: 0.875rem;
534
+ }
535
+
536
+ .export-btn:hover {
537
+ background: #0056b3;
538
+ }
539
+
540
+ .results-table {
541
+ padding: 20px;
542
+ }
543
+
544
+ table {
545
+ width: 100%;
546
+ border-collapse: collapse;
547
+ }
548
+
549
+ th, td {
550
+ text-align: left;
551
+ padding: 12px;
552
+ border-bottom: 1px solid #dee2e6;
553
+ }
554
+
555
+ th {
556
+ font-weight: 600;
557
+ color: #333;
558
+ background: #f8f9fa;
559
+ }
560
+
561
+ .item-id {
562
+ font-family: monospace;
563
+ font-weight: 500;
564
+ }
565
+
566
+ .item-quantity {
567
+ text-align: right;
568
+ font-weight: 500;
569
+ }
570
+
571
+ .status-badge {
572
+ padding: 4px 8px;
573
+ border-radius: 12px;
574
+ font-size: 0.75rem;
575
+ font-weight: 500;
576
+ }
577
+
578
+ .status-low {
579
+ background: #ffebee;
580
+ color: #c62828;
581
+ }
582
+
583
+ .status-medium {
584
+ background: #fff3e0;
585
+ color: #ef6c00;
586
+ }
587
+
588
+ .status-high {
589
+ background: #e8f5e8;
590
+ color: #2e7d32;
591
+ }
592
+
593
+ .no-results {
594
+ text-align: center;
595
+ padding: 60px 20px;
596
+ color: #666;
597
+ }
598
+
599
+ .suggestion {
600
+ font-size: 0.9rem;
601
+ color: #888;
602
+ margin-top: 8px;
603
+ }
604
+
605
+ @media (max-width: 768px) {
606
+ .filter-controls {
607
+ flex-direction: column;
608
+ align-items: stretch;
609
+ }
610
+
611
+ .preset-buttons {
612
+ justify-content: center;
613
+ }
614
+
615
+ .results-header {
616
+ flex-direction: column;
617
+ gap: 12px;
618
+ align-items: stretch;
619
+ }
620
+
621
+ table {
622
+ font-size: 0.875rem;
623
+ }
624
+
625
+ th, td {
626
+ padding: 8px;
627
+ }
628
+ }
629
+ </style>
630
+ ```
631
+
632
+ ## 样式
633
+
634
+ NumberRange 组件使用以下 CSS 类:
635
+
636
+ ```css
637
+ .uniface-range-editor {
638
+ /* 主要范围容器 */
639
+ display: flex;
640
+ align-items: center;
641
+ gap: 8px;
642
+ }
643
+
644
+ .uniface-range-editor .range-divider {
645
+ /* 从/到输入框之间的分隔符 */
646
+ color: var(--uniface-editor-border-color, #dee2e6);
647
+ }
648
+
649
+ .uniface-range-editor .action-icon {
650
+ /* 清除按钮样式 */
651
+ cursor: pointer;
652
+ opacity: 0.6;
653
+ transition: opacity 0.2s;
654
+ }
655
+
656
+ .uniface-range-editor .action-icon:hover {
657
+ opacity: 1;
658
+ }
659
+ ```
660
+
661
+ ## API 参考
662
+
663
+ ### NumberRange 组件属性
664
+
665
+ ```typescript
666
+ interface NumberRangeProps {
667
+ variant?: '' | 'plain' | 'outlined' | 'filled'; // 视觉样式变体
668
+ compact?: boolean; // 紧凑布局模式
669
+ class?: string; // CSS 类名
670
+ style?: string; // 自定义内联样式
671
+ min?: number | null; // 全局最小值
672
+ max?: number | null; // 全局最大值
673
+ fromValue: number; // 范围起始值
674
+ toValue: number; // 范围结束值
675
+ allowNegative?: boolean; // 允许负数
676
+ }
677
+ ```
678
+
679
+ ## 最佳实践
680
+
681
+ 1. **验证** - 始终绑定 `fromValue` 和 `toValue` 以实现正确的范围验证
682
+ 2. **限制** - 设置适当的 `min` 和 `max` 值以引导用户输入
683
+ 3. **用户反馈** - 提供所选范围值的清晰指示
684
+ 4. **可访问性** - 确保足够的颜色对比度和键盘导航
685
+ 5. **移动支持** - 在触摸设备上测试输入行为
686
+ 6. **数据类型** - 在响应式语句中优雅处理 undefined/null 值
687
+ 7. **性能** - 对大数据集的过滤操作进行防抖处理
688
+ 8. **清除功能** - 依赖内置清除按钮以保持一致的用户体验