@ticatec/uniface-element 0.2.3 → 0.3.0

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 (178) hide show
  1. package/dist/accordion/README.md +169 -0
  2. package/dist/accordion/README_CN.md +176 -0
  3. package/dist/action-bar/README.md +275 -0
  4. package/dist/action-bar/README_CN.md +285 -0
  5. package/dist/app-layout/README.md +374 -0
  6. package/dist/app-layout/README_CN.md +381 -0
  7. package/dist/app-top-bar/README.md +357 -0
  8. package/dist/app-top-bar/README_CN.md +365 -0
  9. package/dist/attachment-files/AttachmentFilesField.svelte +67 -1
  10. package/dist/attachment-files/AttachmentFilesField.svelte.d.ts +8 -1
  11. package/dist/base-calendar/CalendarBase.svelte +0 -3
  12. package/dist/box/README.md +385 -0
  13. package/dist/box/README_CN.md +393 -0
  14. package/dist/breadcrumbs/README.md +442 -0
  15. package/dist/breadcrumbs/README_CN.md +442 -0
  16. package/dist/button/Button.svelte +27 -7
  17. package/dist/button/Button.svelte.d.ts +3 -1
  18. package/dist/button/IconButton.svelte +26 -6
  19. package/dist/button/IconButton.svelte.d.ts +3 -1
  20. package/dist/button/IconButton_README.md +513 -0
  21. package/dist/button/IconButton_README_CN.md +513 -0
  22. package/dist/button/README.md +428 -0
  23. package/dist/button/README_CN.md +428 -0
  24. package/dist/button/TextButton.svelte +26 -6
  25. package/dist/button/TextButton.svelte.d.ts +3 -1
  26. package/dist/button/TextButton_README.md +571 -0
  27. package/dist/button/TextButton_README_CN.md +571 -0
  28. package/dist/card/README.md +666 -0
  29. package/dist/card/README_CN.md +666 -0
  30. package/dist/cascade-options-select/CascadeOptionSelect.svelte +43 -7
  31. package/dist/cascade-options-select/CascadeOptionSelect.svelte.d.ts +3 -4
  32. package/dist/cascade-options-select/README.md +663 -2
  33. package/dist/cascade-options-select/README_CN.md +664 -0
  34. package/dist/checkbox/CheckBox.svelte +20 -6
  35. package/dist/checkbox/CheckBox.svelte.d.ts +4 -2
  36. package/dist/checkbox/README.md +562 -0
  37. package/dist/checkbox/README_CN.md +727 -0
  38. package/dist/common-editor/NumberInput.svelte +39 -26
  39. package/dist/common-editor/NumberInput.svelte.d.ts +5 -1
  40. package/dist/concise-data-table/ConciseListTable.svelte +133 -36
  41. package/dist/concise-data-table/ConciseListTable.svelte.d.ts +8 -1
  42. package/dist/concise-data-table/DataCell.svelte +5 -6
  43. package/dist/concise-data-table/DataRow.svelte +22 -2
  44. package/dist/concise-data-table/DataRow.svelte.d.ts +1 -0
  45. package/dist/concise-data-table/README.md +606 -0
  46. package/dist/concise-data-table/README_CN.md +611 -0
  47. package/dist/context-menu/ContextMenu.svelte +138 -21
  48. package/dist/context-menu/ContextMenu.svelte.d.ts +5 -0
  49. package/dist/context-menu/ContextMenuItem.d.ts +20 -4
  50. package/dist/context-menu/README.md +551 -0
  51. package/dist/context-menu/README_CN.md +551 -0
  52. package/dist/criteria-field/CriteriaField.svelte +3 -5
  53. package/dist/criteria-field/README.md +532 -0
  54. package/dist/criteria-field/README_CN.md +532 -0
  55. package/dist/data-table/README.md +712 -0
  56. package/dist/data-table/README_CN.md +712 -0
  57. package/dist/date-picker/DatePicker.svelte +44 -7
  58. package/dist/date-picker/DatePicker.svelte.d.ts +3 -4
  59. package/dist/date-picker/DateTimePicker.svelte +32 -8
  60. package/dist/date-picker/DateTimePicker.svelte.d.ts +3 -4
  61. package/dist/date-picker/README.md +326 -0
  62. package/dist/date-picker/README_CN.md +316 -0
  63. package/dist/date-picker/ScrollBar.svelte +18 -8
  64. package/dist/date-picker/ScrollBar.svelte.d.ts +1 -1
  65. package/dist/date-picker/TimePanel.svelte +5 -5
  66. package/dist/date-picker/TimePanel.svelte.d.ts +1 -1
  67. package/dist/date-range/README.md +374 -0
  68. package/dist/date-range/README_CN.md +374 -0
  69. package/dist/dialog/DialogBoard.svelte +1 -1
  70. package/dist/dialog/README.md +596 -0
  71. package/dist/dialog/README_CN.md +596 -0
  72. package/dist/drawer/README.md +679 -1
  73. package/dist/drawer/README_CN.md +679 -0
  74. package/dist/group-box/group-check-box/GroupCheckBox.svelte +62 -5
  75. package/dist/group-box/group-check-box/GroupCheckBox.svelte.d.ts +7 -2
  76. package/dist/group-box/group-check-box/README.md +749 -0
  77. package/dist/group-box/group-check-box/README_CN.md +750 -0
  78. package/dist/group-box/group-radio-box/GroupRadioBox.svelte +69 -4
  79. package/dist/group-box/group-radio-box/GroupRadioBox.svelte.d.ts +8 -2
  80. package/dist/group-box/group-radio-box/README.md +920 -0
  81. package/dist/group-box/group-radio-box/README_CN.md +920 -0
  82. package/dist/image-files/README.md +1346 -0
  83. package/dist/image-files/README_CN.md +1346 -0
  84. package/dist/input-options-select/InputOptionsSelect.svelte +161 -65
  85. package/dist/input-options-select/InputOptionsSelect.svelte.d.ts +4 -1
  86. package/dist/lib/forwardAllEvents.d.ts +3 -0
  87. package/dist/lib/forwardAllEvents.js +24 -0
  88. package/dist/list-box/README.md +579 -0
  89. package/dist/list-box/README_CN.md +682 -0
  90. package/dist/lookup-editor/LookupEditor.svelte +15 -3
  91. package/dist/lookup-editor/LookupEditor.svelte.d.ts +3 -4
  92. package/dist/lookup-editor/README.md +684 -0
  93. package/dist/lookup-editor/README_CN.md +684 -0
  94. package/dist/memo-editor/MemoEditor.svelte +77 -27
  95. package/dist/memo-editor/MemoEditor.svelte.d.ts +6 -3
  96. package/dist/memo-editor/README.md +819 -0
  97. package/dist/memo-editor/README_CN.md +819 -0
  98. package/dist/message-box/README.md +398 -0
  99. package/dist/message-box/README_CN.md +398 -0
  100. package/dist/number-editor/NumberEditor.svelte +2 -2
  101. package/dist/number-editor/NumberEditor.svelte.d.ts +1 -1
  102. package/dist/number-editor/README.md +353 -22
  103. package/dist/number-editor/README_CN.md +357 -0
  104. package/dist/number-range/README.md +443 -0
  105. package/dist/number-range/README_CN.md +443 -0
  106. package/dist/options-multi-select/OptionsMultiSelect.svelte +87 -12
  107. package/dist/options-multi-select/OptionsMultiSelect.svelte.d.ts +3 -1
  108. package/dist/options-multi-select/README.md +480 -0
  109. package/dist/options-multi-select/README_CN.md +480 -0
  110. package/dist/options-select/OptionsSelect.svelte +36 -5
  111. package/dist/options-select/OptionsSelect.svelte.d.ts +3 -4
  112. package/dist/options-select/README.md +632 -0
  113. package/dist/options-select/README_CN.md +632 -0
  114. package/dist/page/README.md +605 -0
  115. package/dist/page/README_CN.md +605 -0
  116. package/dist/pagination/README.md +946 -0
  117. package/dist/pagination/README_CN.md +946 -0
  118. package/dist/pagination-panel/README.md +1075 -0
  119. package/dist/pagination-panel/README_CN.md +1075 -0
  120. package/dist/popup-hint/README.md +841 -0
  121. package/dist/popup-hint/README_CN.md +840 -0
  122. package/dist/progress-bar/README.md +242 -0
  123. package/dist/progress-bar/README_CN.md +242 -0
  124. package/dist/progress-step-bar/README.md +316 -0
  125. package/dist/progress-step-bar/README_CN.md +316 -0
  126. package/dist/prompts-text-editor/PromptsTextEditor.svelte +6 -3
  127. package/dist/prompts-text-editor/PromptsTextEditor.svelte.d.ts +3 -1
  128. package/dist/prompts-text-editor/README.md +329 -0
  129. package/dist/prompts-text-editor/README_CN.md +329 -0
  130. package/dist/property-editor/README.md +969 -0
  131. package/dist/property-editor/README_CN.md +969 -0
  132. package/dist/radio-button/README.md +372 -0
  133. package/dist/radio-button/README_CN.md +372 -0
  134. package/dist/radio-button/RadioButton.svelte +32 -3
  135. package/dist/radio-button/RadioButton.svelte.d.ts +12 -1
  136. package/dist/search-box/README.md +425 -0
  137. package/dist/search-box/README_CN.md +424 -0
  138. package/dist/search-box/SearchBox.svelte +22 -6
  139. package/dist/search-box/SearchBox.svelte.d.ts +4 -1
  140. package/dist/tabs/README.md +919 -0
  141. package/dist/tabs/README_CN.md +920 -0
  142. package/dist/tag/README.md +922 -0
  143. package/dist/tag/README_CN.md +922 -0
  144. package/dist/text-editor/PasswordEditor.svelte +17 -2
  145. package/dist/text-editor/PasswordEditor.svelte.d.ts +3 -3
  146. package/dist/text-editor/PasswordEditor_README.md +551 -0
  147. package/dist/text-editor/PasswordEditor_README_CN.md +551 -0
  148. package/dist/text-editor/README.md +466 -0
  149. package/dist/text-editor/README_CN.md +466 -0
  150. package/dist/text-editor/TextEditor.svelte +51 -19
  151. package/dist/text-editor/TextEditor.svelte.d.ts +0 -1
  152. package/dist/ticatec-uniface-web.css +1 -0
  153. package/dist/time-editor/README.md +498 -24
  154. package/dist/time-editor/README_CN.md +498 -0
  155. package/dist/time-editor/TimeEditor.svelte +7 -3
  156. package/dist/time-editor/TimeEditor.svelte.d.ts +3 -1
  157. package/dist/toast/README.md +667 -0
  158. package/dist/toast/README_CN.md +667 -0
  159. package/dist/transfer/README.md +795 -0
  160. package/dist/transfer/Transfer.svelte +6 -4
  161. package/dist/transfer/Transfer.svelte.d.ts +3 -1
  162. package/dist/tree-view/README.md +761 -0
  163. package/dist/tree-view/README_CN.md +761 -0
  164. package/dist/tree-view/TreeView.svelte +5 -3
  165. package/dist/tree-view/TreeView.svelte.d.ts +3 -1
  166. package/dist/unit-number-editor/README.md +546 -20
  167. package/dist/unit-number-editor/README_CN.md +525 -0
  168. package/dist/unit-number-editor/UnitNumberEditor.svelte +62 -8
  169. package/dist/unit-number-editor/UnitNumberEditor.svelte.d.ts +5 -1
  170. package/docs/form-field/cn/README_CN.md +364 -0
  171. package/docs/form-field/en/README.md +364 -0
  172. package/docs/form-panel/flex-form/cn/README_CN.md +586 -0
  173. package/docs/form-panel/flex-form/en/README.md +586 -0
  174. package/docs/form-panel/flex-row-form/cn/README_CN.md +787 -0
  175. package/docs/form-panel/flex-row-form/en/README.md +787 -0
  176. package/docs/form-panel/grid-form/en/README.md +744 -0
  177. package/package.json +1 -1
  178. package/dist/drawer/README-CN.md +0 -1
@@ -0,0 +1,1075 @@
1
+ # 分页面板组件
2
+
3
+ 一个全面的分页控制面板,集成了页面导航、每页行数选择和总记录数显示,提供统一的界面。
4
+
5
+ ## 功能
6
+
7
+ - **完整分页**:包括页面导航、行数选择器和摘要信息
8
+ - **可自定义行数选项**:配置可用的每页行数选项
9
+ - **总信息显示**:显示总记录数,支持自定义格式
10
+ - **多种对齐方式**:支持左对齐、右对齐和居中对齐
11
+ - **尺寸变体**:提供普通和大尺寸选项
12
+ - **样式集成**:继承基础分页组件的样式
13
+ - **自定义信息生成器**:支持灵活的总信息显示格式
14
+ - **事件处理**:分别处理页面更改和行数更改事件
15
+
16
+ ## 安装
17
+
18
+ ```bash
19
+ npm install @ticatec/uniface-element
20
+ ```
21
+
22
+ ## 基本用法
23
+
24
+ ```svelte
25
+ <script>
26
+ import PaginationPanel from '@ticatec/uniface-element/PaginationPanel';
27
+
28
+ let currentPage = 1;
29
+ let totalPages = 10;
30
+ let totalRecords = 250;
31
+ let rowsPerPage = 25;
32
+
33
+ function handlePageChange(page) {
34
+ currentPage = page;
35
+ console.log('页面更改为:', page);
36
+ }
37
+
38
+ function handleRowCountChange(rows) {
39
+ rowsPerPage = rows;
40
+ // 根据新的行数重新计算总页数
41
+ totalPages = Math.ceil(totalRecords / rows);
42
+ currentPage = 1; // 重置为第一页
43
+ console.log('每页行数更改为:', rows);
44
+ }
45
+ </script>
46
+
47
+ <PaginationPanel
48
+ pageNo={currentPage}
49
+ pageCount={totalPages}
50
+ total={totalRecords}
51
+ rowCount={rowsPerPage}
52
+ onPageChange={handlePageChange}
53
+ onRowCountChanged={handleRowCountChange}
54
+ />
55
+ ```
56
+
57
+ ## API 参考
58
+
59
+ ### 属性
60
+
61
+ | 属性 | 类型 | 默认值 | 描述 |
62
+ |------|------|---------|-------------|
63
+ | `pageNo` | `number` | `1` | 当前活动页面编号 |
64
+ | `pageCount` | `number` | `0` | 总页面数 |
65
+ | `total` | `number` | `null` | 总记录数 |
66
+ | `rowCount` | `number` | `25` | 当前每页行数设置 |
67
+ | `rowsSet` | `Array<number>` | `[25, 50, 100]` | 可用的每页行数选项 |
68
+ | `type` | `'plain' \| 'round' \| 'circle'` | `'round'` | 视觉样式变体 |
69
+ | `page$style` | `string` | `''` | 分页组件的自定义 CSS 样式 |
70
+ | `big` | `boolean` | `false` | 启用较大尺寸变体 |
71
+ | `rowCountLabel` | `string` | `'Rows/Page'` | 每页行数选择器的标签 |
72
+ | `align` | `'left' \| 'right' \| ''` | `''` | 面板对齐方式 |
73
+ | `generateInfo` | `GenerateTotalInfo \| null` | `null` | 自定义生成总信息文本的函数 |
74
+ | `onPageChange` | `OnPageChange` | `undefined` | 页面更改事件处理程序 |
75
+ | `onRowCountChanged` | `OnRowCountChanged` | `undefined` | 行数更改事件处理程序 |
76
+
77
+ ### 类型
78
+
79
+ ```typescript
80
+ export type OnPageChange = (page: number) => void;
81
+ export type OnRowCountChanged = (rows: number) => void;
82
+ export type GenerateTotalInfo = (total: number, pageCount: number, pageNo: number, rows: number) => string;
83
+ ```
84
+
85
+ ## 示例
86
+
87
+ ### 带完整分页的数据表格
88
+
89
+ ```svelte
90
+ <script>
91
+ import PaginationPanel from '@ticatec/uniface-element/PaginationPanel';
92
+
93
+ let users = [];
94
+ let currentPage = 1;
95
+ let totalPages = 1;
96
+ let totalUsers = 0;
97
+ let rowsPerPage = 25;
98
+ let loading = false;
99
+
100
+ async function loadUsers(page = 1, rows = 25) {
101
+ loading = true;
102
+
103
+ try {
104
+ // 模拟 API 调用
105
+ await new Promise(resolve => setTimeout(resolve, 500));
106
+
107
+ // 模拟数据
108
+ totalUsers = 237; // API 返回的总记录数
109
+ totalPages = Math.ceil(totalUsers / rows);
110
+ currentPage = page;
111
+
112
+ const startIndex = (page - 1) * rows;
113
+ users = Array.from({ length: Math.min(rows, totalUsers - startIndex) }, (_, i) => ({
114
+ id: startIndex + i + 1,
115
+ name: `用户 ${startIndex + i + 1}`,
116
+ email: `user${startIndex + i + 1}@example.com`,
117
+ role: ['管理员', '用户', '审核者'][Math.floor(Math.random() * 3)],
118
+ status: Math.random() > 0.2 ? '活跃' : '非活跃'
119
+ }));
120
+ } finally {
121
+ loading = false;
122
+ }
123
+ }
124
+
125
+ function handlePageChange(page) {
126
+ loadUsers(page, rowsPerPage);
127
+ }
128
+
129
+ function handleRowCountChange(rows) {
130
+ rowsPerPage = rows;
131
+ loadUsers(1, rows); // 重置为第一页
132
+ }
133
+
134
+ // 自定义用户信息生成器
135
+ function generateUserInfo(total, pageCount, pageNo, rows) {
136
+ const start = (pageNo - 1) * rows + 1;
137
+ const end = Math.min(pageNo * rows, total);
138
+ return `显示 <b>${start}-${end}</b> 共 <b>${total}</b> 个用户`;
139
+ }
140
+
141
+ // 加载初始数据
142
+ loadUsers(currentPage, rowsPerPage);
143
+ </script>
144
+
145
+ <div class="user-management">
146
+ <h2>用户管理</h2>
147
+
148
+ {#if loading}
149
+ <div class="loading">加载用户中...</div>
150
+ {:else}
151
+ <table class="users-table">
152
+ <thead>
153
+ <tr>
154
+ <th>ID</th>
155
+ <th>姓名</th>
156
+ <th>邮箱</th>
157
+ <th>角色</th>
158
+ <th>状态</th>
159
+ </tr>
160
+ </thead>
161
+ <tbody>
162
+ {#each users as user}
163
+ <tr>
164
+ <td>{user.id}</td>
165
+ <td>{user.name}</td>
166
+ <td>{user.email}</td>
167
+ <td>{user.role}</td>
168
+ <td class="status {user.status === '活跃' ? 'active' : 'inactive'}">{user.status}</td>
169
+ </tr>
170
+ {/each}
171
+ </tbody>
172
+ </table>
173
+ {/if}
174
+
175
+ <PaginationPanel
176
+ pageNo={currentPage}
177
+ pageCount={totalPages}
178
+ total={totalUsers}
179
+ rowCount={rowsPerPage}
180
+ rowsSet={[10, 25, 50, 100]}
181
+ rowCountLabel="每页用户数"
182
+ generateInfo={generateUserInfo}
183
+ onPageChange={handlePageChange}
184
+ onRowCountChanged={handleRowCountChange}
185
+ align="right"
186
+ />
187
+ </div>
188
+
189
+ <style>
190
+ .user-management {
191
+ max-width: 1200px;
192
+ margin: 0 auto;
193
+ padding: 20px;
194
+ }
195
+
196
+ .loading {
197
+ text-align: center;
198
+ padding: 40px;
199
+ color: #666;
200
+ }
201
+
202
+ .users-table {
203
+ width: 100%;
204
+ border-collapse: collapse;
205
+ margin-bottom: 20px;
206
+ }
207
+
208
+ .users-table th,
209
+ .users-table td {
210
+ padding: 12px;
211
+ text-align: left;
212
+ border-bottom: 1px solid #ddd;
213
+ }
214
+
215
+ .users-table th {
216
+ background-color: #f8f9fa;
217
+ font-weight: 600;
218
+ }
219
+
220
+ .status.active {
221
+ color: #28a745;
222
+ }
223
+
224
+ .status.inactive {
225
+ color: #dc3545;
226
+ }
227
+ </style>
228
+ ```
229
+
230
+ ### 带自定义样式的产品目录
231
+
232
+ ```svelte
233
+ <script>
234
+ import PaginationPanel from '@ticatec/uniface-element/PaginationPanel';
235
+
236
+ let products = [];
237
+ let currentPage = 1;
238
+ let totalPages = 1;
239
+ let totalProducts = 0;
240
+ let rowsPerPage = 12;
241
+ let category = 'all';
242
+
243
+ const categories = {
244
+ all: '所有产品',
245
+ electronics: '电子产品',
246
+ clothing: '服装',
247
+ books: '书籍'
248
+ };
249
+
250
+ async function loadProducts(page = 1, rows = 12, cat = 'all') {
251
+ // 模拟带类别过滤的 API 调用
252
+ const categoryTotals = {
253
+ all: 180,
254
+ electronics: 45,
255
+ clothing: 67,
256
+ books: 68
257
+ };
258
+
259
+ totalProducts = categoryTotals[cat];
260
+ totalPages = Math.ceil(totalProducts / rows);
261
+ currentPage = page;
262
+
263
+ const startIndex = (page - 1) * rows;
264
+ products = Array.from({ length: Math.min(rows, totalProducts - startIndex) }, (_, i) => ({
265
+ id: startIndex + i + 1,
266
+ name: `${categories[cat]} 产品 ${startIndex + i + 1}`,
267
+ price: (Math.random() * 200 + 20).toFixed(2),
268
+ image: `https://picsum.photos/200/200?random=${startIndex + i + 1}`,
269
+ rating: (Math.random() * 2 + 3).toFixed(1)
270
+ }));
271
+ }
272
+
273
+ function handlePageChange(page) {
274
+ loadProducts(page, rowsPerPage, category);
275
+ }
276
+
277
+ function handleRowCountChange(rows) {
278
+ rowsPerPage = rows;
279
+ loadProducts(1, rows, category);
280
+ }
281
+
282
+ function handleCategoryChange() {
283
+ loadProducts(1, rowsPerPage, category);
284
+ }
285
+
286
+ // 自定义产品信息生成器
287
+ function generateProductInfo(total, pageCount, pageNo, rows) {
288
+ return `
289
+ <span style="color: #007bff;">第 ${pageNo} 页</span> 共
290
+ <span style="color: #007bff;">${pageCount} 页</span> •
291
+ <span style="color: #28a745;">${total}</span> 个产品
292
+ `;
293
+ }
294
+
295
+ // 加载初始产品
296
+ loadProducts(currentPage, rowsPerPage, category);
297
+ </script>
298
+
299
+ <div class="product-catalog">
300
+ <div class="catalog-header">
301
+ <h2>产品目录</h2>
302
+ <div class="category-filter">
303
+ <label>类别:</label>
304
+ <select bind:value={category} on:change={handleCategoryChange}>
305
+ {#each Object.entries(categories) as [key, value]}
306
+ <option value={key}>{value}</option>
307
+ {/each}
308
+ </select>
309
+ </div>
310
+ </div>
311
+
312
+ <div class="products-grid">
313
+ {#each products as product}
314
+ <div class="product-card">
315
+ <img src={product.image} alt={product.name} />
316
+ <h3>{product.name}</h3>
317
+ <div class="product-info">
318
+ <span class="price">${product.price}</span>
319
+ <span class="rating">⭐ {product.rating}</span>
320
+ </div>
321
+ </div>
322
+ {/each}
323
+ </div>
324
+
325
+ <PaginationPanel
326
+ pageNo={currentPage}
327
+ pageCount={totalPages}
328
+ total={totalProducts}
329
+ rowCount={rowsPerPage}
330
+ rowsSet={[6, 12, 24, 48]}
331
+ rowCountLabel="每页产品数"
332
+ generateInfo={generateProductInfo}
333
+ onPageChange={handlePageChange}
334
+ onRowCountChanged={handleRowCountChange}
335
+ type="round"
336
+ big
337
+ />
338
+ </div>
339
+
340
+ <style>
341
+ .product-catalog {
342
+ max-width: 1200px;
343
+ margin: 0 auto;
344
+ padding: 20px;
345
+ }
346
+
347
+ .catalog-header {
348
+ display: flex;
349
+ justify-content: space-between;
350
+ align-items: center;
351
+ margin-bottom: 30px;
352
+ }
353
+
354
+ .category-filter {
355
+ display: flex;
356
+ align-items: center;
357
+ gap: 10px;
358
+ }
359
+
360
+ .category-filter select {
361
+ padding: 8px 12px;
362
+ border: 1px solid #ddd;
363
+ border-radius: 4px;
364
+ }
365
+
366
+ .products-grid {
367
+ display: grid;
368
+ grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
369
+ gap: 24px;
370
+ margin-bottom: 40px;
371
+ min-height: 400px;
372
+ }
373
+
374
+ .product-card {
375
+ border: 1px solid #ddd;
376
+ border-radius: 8px;
377
+ padding: 16px;
378
+ text-align: center;
379
+ transition: transform 0.2s;
380
+ }
381
+
382
+ .product-card:hover {
383
+ transform: translateY(-2px);
384
+ box-shadow: 0 4px 12px rgba(0,0,0,0.1);
385
+ }
386
+
387
+ .product-card img {
388
+ width: 100%;
389
+ height: 200px;
390
+ object-fit: cover;
391
+ border-radius: 4px;
392
+ margin-bottom: 12px;
393
+ }
394
+
395
+ .product-card h3 {
396
+ margin: 0 0 12px 0;
397
+ font-size: 16px;
398
+ }
399
+
400
+ .product-info {
401
+ display: flex;
402
+ justify-content: space-between;
403
+ align-items: center;
404
+ }
405
+
406
+ .price {
407
+ font-size: 18px;
408
+ font-weight: bold;
409
+ color: #007bff;
410
+ }
411
+
412
+ .rating {
413
+ color: #ff9500;
414
+ }
415
+ </style>
416
+ ```
417
+
418
+ ### 报告仪表盘
419
+
420
+ ```svelte
421
+ <script>
422
+ import PaginationPanel from '@ticatec/uniface-element/PaginationPanel';
423
+
424
+ let reports = [];
425
+ let currentPage = 1;
426
+ let totalPages = 1;
427
+ let totalReports = 0;
428
+ let rowsPerPage = 15;
429
+ let dateRange = 'week';
430
+
431
+ async function loadReports(page = 1, rows = 15, range = 'week') {
432
+ // 模拟根据日期范围加载报告
433
+ const rangeTotals = {
434
+ today: 23,
435
+ week: 156,
436
+ month: 642,
437
+ year: 7834
438
+ };
439
+
440
+ totalReports = rangeTotals[range];
441
+ totalPages = Math.ceil(totalReports / rows);
442
+ currentPage = page;
443
+
444
+ const startIndex = (page - 1) * rows;
445
+ reports = Array.from({ length: Math.min(rows, totalReports - startIndex) }, (_, i) => ({
446
+ id: `RPT-${String(startIndex + i + 1).padStart(4, '0')}`,
447
+ title: `报告 ${startIndex + i + 1}`,
448
+ type: ['销售', '分析', '性能', '用户活动'][Math.floor(Math.random() * 4)],
449
+ createdAt: new Date(Date.now() - Math.random() * 30 * 24 * 60 * 60 * 1000).toLocaleDateString(),
450
+ status: ['已完成', '处理中', '失败'][Math.floor(Math.random() * 3)],
451
+ size: `${(Math.random() * 10 + 0.5).toFixed(1)} MB`
452
+ }));
453
+ }
454
+
455
+ function handlePageChange(page) {
456
+ loadReports(page, rowsPerPage, dateRange);
457
+ }
458
+
459
+ function handleRowCountChange(rows) {
460
+ rowsPerPage = rows;
461
+ loadReports(1, rows, dateRange);
462
+ }
463
+
464
+ function handleDateRangeChange() {
465
+ loadReports(1, rowsPerPage, dateRange);
466
+ }
467
+
468
+ // 自定义报告信息生成器
469
+ function generateReportInfo(total, pageCount, pageNo, rows) {
470
+ const start = (pageNo - 1) * rows + 1;
471
+ const end = Math.min(pageNo * rows, total);
472
+ return `
473
+ <div style="display: flex; align-items: center; gap: 16px;">
474
+ <span>报告 <b>${start}-${end}</b> 共 <b>${total}</b></span>
475
+ <span style="color: #666;">•</span>
476
+ <span style="color: #007bff;">第 ${pageNo}/${pageCount} 页</span>
477
+ </div>
478
+ `;
479
+ }
480
+
481
+ // 加载初始报告
482
+ loadReports(currentPage, rowsPerPage, dateRange);
483
+ </script>
484
+
485
+ <div class="reports-dashboard">
486
+ <div class="dashboard-header">
487
+ <h2>报告仪表盘</h2>
488
+ <div class="date-filter">
489
+ <label>时间范围:</label>
490
+ <select bind:value={dateRange} on:change={handleDateRangeChange}>
491
+ <option value="today">今天</option>
492
+ <option value="week">本周</option>
493
+ <option value="month">本月</option>
494
+ <option value="year">本年</option>
495
+ </select>
496
+ </div>
497
+ </div>
498
+
499
+ <div class="reports-table-container">
500
+ <table class="reports-table">
501
+ <thead>
502
+ <tr>
503
+ <th>报告 ID</th>
504
+ <th>标题</th>
505
+ <th>类型</th>
506
+ <th>创建时间</th>
507
+ <th>状态</th>
508
+ <th>大小</th>
509
+ <th>操作</th>
510
+ </tr>
511
+ </thead>
512
+ <tbody>
513
+ {#each reports as report}
514
+ <tr>
515
+ <td><code>{report.id}</code></td>
516
+ <td>{report.title}</td>
517
+ <td><span class="badge type-{report.type.toLowerCase().replace(' ', '-')}">{report.type}</span></td>
518
+ <td>{report.createdAt}</td>
519
+ <td><span class="status status-{report.status === '已完成' ? 'completed' : report.status === '处理中' ? 'processing' : 'failed'}">{report.status}</span></td>
520
+ <td>{report.size}</td>
521
+ <td>
522
+ <button class="action-btn download">下载</button>
523
+ <button class="action-btn delete">删除</button>
524
+ </td>
525
+ </tr>
526
+ {/each}
527
+ </tbody>
528
+ </table>
529
+ </div>
530
+
531
+ <PaginationPanel
532
+ pageNo={currentPage}
533
+ pageCount={totalPages}
534
+ total={totalReports}
535
+ rowCount={rowsPerPage}
536
+ rowsSet={[10, 15, 25, 50]}
537
+ rowCountLabel="每页报告数"
538
+ generateInfo={generateReportInfo}
539
+ onPageChange={handlePageChange}
540
+ onRowCountChanged={handleRowCountChange}
541
+ type="plain"
542
+ align="left"
543
+ />
544
+ </div>
545
+
546
+ <style>
547
+ .reports-dashboard {
548
+ max-width: 1400px;
549
+ margin: 0 auto;
550
+ padding: 20px;
551
+ }
552
+
553
+ .dashboard-header {
554
+ display: flex;
555
+ justify-content: space-between;
556
+ align-items: center;
557
+ margin-bottom: 30px;
558
+ }
559
+
560
+ .date-filter {
561
+ display: flex;
562
+ align-items: center;
563
+ gap: 10px;
564
+ }
565
+
566
+ .date-filter select {
567
+ padding: 8px 12px;
568
+ border: 1px solid #ddd;
569
+ border-radius: 4px;
570
+ }
571
+
572
+ .reports-table-container {
573
+ overflow-x: auto;
574
+ margin-bottom: 20px;
575
+ }
576
+
577
+ .reports-table {
578
+ width: 100%;
579
+ border-collapse: collapse;
580
+ min-width: 800px;
581
+ }
582
+
583
+ .reports-table th,
584
+ .reports-table td {
585
+ padding: 12px;
586
+ text-align: left;
587
+ border-bottom: 1px solid #ddd;
588
+ }
589
+
590
+ .reports-table th {
591
+ background-color: #f8f9fa;
592
+ font-weight: 600;
593
+ position: sticky;
594
+ top: 0;
595
+ }
596
+
597
+ .badge {
598
+ padding: 4px 8px;
599
+ border-radius: 12px;
600
+ font-size: 12px;
601
+ font-weight: 600;
602
+ text-transform: uppercase;
603
+ }
604
+
605
+ .badge.type-销售 { background: #e3f2fd; color: #1976d2; }
606
+ .badge.type-分析 { background: #f3e5f5; color: #7b1fa2; }
607
+ .badge.type-性能 { background: #e8f5e8; color: #388e3c; }
608
+ .badge.type-用户活动 { background: #fff3e0; color: #f57c00; }
609
+
610
+ .status {
611
+ font-weight: 600;
612
+ }
613
+
614
+ .status.status-completed { color: #28a745; }
615
+ .status.status-processing { color: #ffc107; }
616
+ .status.status-failed { color: #dc3545; }
617
+
618
+ .action-btn {
619
+ padding: 4px 8px;
620
+ margin: 0 2px;
621
+ border: none;
622
+ border-radius: 4px;
623
+ cursor: pointer;
624
+ font-size: 12px;
625
+ }
626
+
627
+ .action-btn.download {
628
+ background: #007bff;
629
+ color: white;
630
+ }
631
+
632
+ .action-btn.delete {
633
+ background: #dc3545;
634
+ color: white;
635
+ }
636
+ </style>
637
+ ```
638
+
639
+ ### 大数据集日志查看器
640
+
641
+ ```svelte
642
+ <script>
643
+ import PaginationPanel from '@ticatec/uniface-element/PaginationPanel';
644
+
645
+ let logs = [];
646
+ let currentPage = 1;
647
+ let totalPages = 1;
648
+ let totalLogs = 0;
649
+ let rowsPerPage = 50;
650
+ let logLevel = 'all';
651
+ let searchTerm = '';
652
+
653
+ const logLevels = ['all', 'error', 'warning', 'info', 'debug'];
654
+
655
+ async function loadLogs(page = 1, rows = 50, level = 'all', search = '') {
656
+ // 模拟大型日志数据集
657
+ const levelMultipliers = {
658
+ all: 1,
659
+ error: 0.1,
660
+ warning: 0.15,
661
+ info: 0.6,
662
+ debug: 0.15
663
+ };
664
+
665
+ const baseLogs = 15000;
666
+ totalLogs = Math.floor(baseLogs * (level === 'all' ? 1 : levelMultipliers[level]));
667
+
668
+ if (search) {
669
+ totalLogs = Math.floor(totalLogs * 0.2); // 模拟搜索过滤
670
+ }
671
+
672
+ totalPages = Math.ceil(totalLogs / rows);
673
+ currentPage = page;
674
+
675
+ const startIndex = (page - 1) * rows;
676
+ logs = Array.from({ length: Math.min(rows, totalLogs - startIndex) }, (_, i) => {
677
+ const logIndex = startIndex + i + 1;
678
+ const levels = level === 'all' ? ['error', 'warning', 'info', 'debug'] : [level];
679
+ const randomLevel = levels[Math.floor(Math.random() * levels.length)];
680
+
681
+ return {
682
+ id: logIndex,
683
+ timestamp: new Date(Date.now() - Math.random() * 7 * 24 * 60 * 60 * 1000).toISOString(),
684
+ level: randomLevel,
685
+ message: search
686
+ ? `日志消息 ${logIndex} 包含 "${search}" 及附加详情`
687
+ : `日志消息 ${logIndex} - ${randomLevel} 级别事件发生`,
688
+ source: ['认证', 'API', '数据库', '缓存', '队列'][Math.floor(Math.random() * 5)]
689
+ };
690
+ });
691
+ }
692
+
693
+ function handlePageChange(page) {
694
+ loadLogs(page, rowsPerPage, logLevel, searchTerm);
695
+ }
696
+
697
+ function handleRowCountChange(rows) {
698
+ rowsPerPage = rows;
699
+ loadLogs(1, rows, logLevel, searchTerm);
700
+ }
701
+
702
+ function handleLevelChange() {
703
+ loadLogs(1, rowsPerPage, logLevel, searchTerm);
704
+ }
705
+
706
+ function handleSearch() {
707
+ loadLogs(1, rowsPerPage, logLevel, searchTerm);
708
+ }
709
+
710
+ // 自定义日志信息生成器
711
+ function generateLogInfo(total, pageCount, pageNo, rows) {
712
+ const start = (pageNo - 1) * rows + 1;
713
+ const end = Math.min(pageNo * rows, total);
714
+ return `
715
+ <div style="font-family: monospace; font-size: 12px;">
716
+ 日志 ${start.toLocaleString()}-${end.toLocaleString()} 共 ${total.toLocaleString()} • 第 ${pageNo}/${pageCount} 页
717
+ </div>
718
+ `;
719
+ }
720
+
721
+ // 加载初始日志
722
+ loadLogs(currentPage, rowsPerPage, logLevel, searchTerm);
723
+ </script>
724
+
725
+ <div class="log-viewer">
726
+ <div class="log-controls">
727
+ <h2>系统日志</h2>
728
+ <div class="filters">
729
+ <div class="filter-group">
730
+ <label>级别:</label>
731
+ <select bind:value={logLevel} on:change={handleLevelChange}>
732
+ {#each logLevels as level}
733
+ <option value={level}>{level.toUpperCase()}</option>
734
+ {/each}
735
+ </select>
736
+ </div>
737
+ <div class="filter-group">
738
+ <label>搜索:</label>
739
+ <input
740
+ type="text"
741
+ bind:value={searchTerm}
742
+ placeholder="搜索日志..."
743
+ on:keydown={(e) => e.key === 'Enter' && handleSearch()}
744
+ />
745
+ <button on:click={handleSearch}>搜索</button>
746
+ </div>
747
+ </div>
748
+ </div>
749
+
750
+ <div class="logs-container">
751
+ {#each logs as log}
752
+ <div class="log-entry level-{log.level}">
753
+ <div class="log-header">
754
+ <span class="timestamp">{new Date(log.timestamp).toLocaleString()}</span>
755
+ <span class="level level-{log.level}">{log.level.toUpperCase()}</span>
756
+ <span class="source">[{log.source}]</span>
757
+ </div>
758
+ <div class="log-message">{log.message}</div>
759
+ </div>
760
+ {/each}
761
+ </div>
762
+
763
+ <PaginationPanel
764
+ pageNo={currentPage}
765
+ pageCount={totalPages}
766
+ total={totalLogs}
767
+ rowCount={rowsPerPage}
768
+ rowsSet={[25, 50, 100, 200]}
769
+ rowCountLabel="每页日志数"
770
+ generateInfo={generateLogInfo}
771
+ onPageChange={handlePageChange}
772
+ onRowCountChanged={handleRowCountChange}
773
+ type="circle"
774
+ />
775
+ </div>
776
+
777
+ <style>
778
+ .log-viewer {
779
+ max-width: 1200px;
780
+ margin: 0 auto;
781
+ padding: 20px;
782
+ }
783
+
784
+ .log-controls {
785
+ margin-bottom: 20px;
786
+ }
787
+
788
+ .log-controls h2 {
789
+ margin: 0 0 16px 0;
790
+ }
791
+
792
+ .filters {
793
+ display: flex;
794
+ gap: 20px;
795
+ align-items: center;
796
+ flex-wrap: wrap;
797
+ }
798
+
799
+ .filter-group {
800
+ display: flex;
801
+ align-items: center;
802
+ gap: 8px;
803
+ }
804
+
805
+ .filter-group select,
806
+ .filter-group input {
807
+ padding: 6px 10px;
808
+ border: 1px solid #ddd;
809
+ border-radius: 4px;
810
+ }
811
+
812
+ .filter-group button {
813
+ padding: 6px 12px;
814
+ background: #007bff;
815
+ color: white;
816
+ border: none;
817
+ border-radius: 4px;
818
+ cursor: pointer;
819
+ }
820
+
821
+ .logs-container {
822
+ background: #1e1e1e;
823
+ border-radius: 8px;
824
+ padding: 16px;
825
+ margin-bottom: 20px;
826
+ max-height: 600px;
827
+ overflow-y: auto;
828
+ font-family: 'Courier New', monospace;
829
+ }
830
+
831
+ .log-entry {
832
+ margin-bottom: 12px;
833
+ padding: 8px;
834
+ border-radius: 4px;
835
+ border-left: 4px solid;
836
+ }
837
+
838
+ .log-entry.level-error {
839
+ background: rgba(220, 53, 69, 0.1);
840
+ border-left-color: #dc3545;
841
+ }
842
+
843
+ .log-entry.level-warning {
844
+ background: rgba(255, 193, 7, 0.1);
845
+ border-left-color: #ffc107;
846
+ }
847
+
848
+ .log-entry.level-info {
849
+ background: rgba(0, 123, 255, 0.1);
850
+ border-left-color: #007bff;
851
+ }
852
+
853
+ .log-entry.level-debug {
854
+ background: rgba(108, 117, 125, 0.1);
855
+ border-left-color: #6c757d;
856
+ }
857
+
858
+ .log-header {
859
+ display: flex;
860
+ gap: 12px;
861
+ align-items: center;
862
+ margin-bottom: 4px;
863
+ font-size: 12px;
864
+ }
865
+
866
+ .timestamp {
867
+ color: #adb5bd;
868
+ }
869
+
870
+ .level {
871
+ font-weight: bold;
872
+ padding: 2px 6px;
873
+ border-radius: 3px;
874
+ font-size: 10px;
875
+ }
876
+
877
+ .level.level-error { background: #dc3545; color: white; }
878
+ .level.level-warning { background: #ffc107; color: black; }
879
+ .level.level-info { background: #007bff; color: white; }
880
+ .level.level-debug { background: #6c757d; color: white; }
881
+
882
+ .source {
883
+ color: #28a745;
884
+ }
885
+
886
+ .log-message {
887
+ color: #f8f9fa;
888
+ font-size: 13px;
889
+ line-height: 1.4;
890
+ }
891
+ </style>
892
+ ```
893
+
894
+ ### 移动响应式面板
895
+
896
+ ```svelte
897
+ <script>
898
+ import PaginationPanel from '@ticatec/uniface-element/PaginationPanel';
899
+ import { onMount } from 'svelte';
900
+
901
+ let currentPage = 1;
902
+ let totalPages = 15;
903
+ let totalItems = 300;
904
+ let rowsPerPage = 20;
905
+ let isMobile = false;
906
+
907
+ onMount(() => {
908
+ const checkMobile = () => {
909
+ isMobile = window.innerWidth < 768;
910
+ };
911
+
912
+ checkMobile();
913
+ window.addEventListener('resize', checkMobile);
914
+
915
+ return () => window.removeEventListener('resize', checkMobile);
916
+ });
917
+
918
+ function handlePageChange(page) {
919
+ currentPage = page;
920
+ }
921
+
922
+ function handleRowCountChange(rows) {
923
+ rowsPerPage = rows;
924
+ totalPages = Math.ceil(totalItems / rows);
925
+ currentPage = 1;
926
+ }
927
+
928
+ // 移动端友好的信息生成器
929
+ function generateMobileInfo(total, pageCount, pageNo, rows) {
930
+ if (isMobile) {
931
+ return `<div style="font-size: 12px; text-align: center;">${pageNo}/${pageCount} • ${total} 项</div>`;
932
+ }
933
+ return `显示 ${(pageNo - 1) * rows + 1}-${Math.min(pageNo * rows, total)} 共 ${total} 项`;
934
+ }
935
+ </script>
936
+
937
+ <div class="mobile-demo">
938
+ <h2>移动响应式分页</h2>
939
+ <p>调整浏览器大小以查看移动端适配效果</p>
940
+
941
+ <div class="content-grid">
942
+ {#each Array(rowsPerPage) as _, i}
943
+ <div class="content-item">
944
+ 项目 {(currentPage - 1) * rowsPerPage + i + 1}
945
+ </div>
946
+ {/each}
947
+ </div>
948
+
949
+ <PaginationPanel
950
+ pageNo={currentPage}
951
+ pageCount={totalPages}
952
+ total={totalItems}
953
+ rowCount={rowsPerPage}
954
+ rowsSet={isMobile ? [10, 20] : [10, 20, 50]}
955
+ rowCountLabel={isMobile ? "每页" : "每页项目数"}
956
+ generateInfo={generateMobileInfo}
957
+ onPageChange={handlePageChange}
958
+ onRowCountChanged={handleRowCountChange}
959
+ type="round"
960
+ big={!isMobile}
961
+ align={isMobile ? "" : "right"}
962
+ />
963
+ </div>
964
+
965
+ <style>
966
+ .mobile-demo {
967
+ max-width: 800px;
968
+ margin: 0 auto;
969
+ padding: 20px;
970
+ }
971
+
972
+ .content-grid {
973
+ display: grid;
974
+ grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
975
+ gap: 16px;
976
+ margin-bottom: 30px;
977
+ }
978
+
979
+ .content-item {
980
+ padding: 20px;
981
+ background: #f8f9fa;
982
+ border: 1px solid #dee2e6;
983
+ border-radius: 8px;
984
+ text-align: center;
985
+ }
986
+
987
+ @media (max-width: 767px) {
988
+ .content-grid {
989
+ grid-template-columns: 1fr 1fr;
990
+ gap: 12px;
991
+ }
992
+
993
+ .content-item {
994
+ padding: 16px;
995
+ font-size: 14px;
996
+ }
997
+ }
998
+ </style>
999
+ ```
1000
+
1001
+ ## 最佳实践
1002
+
1003
+ 1. **数据加载**:在页面切换期间实现适当的加载状态
1004
+ 2. **URL 同步**:保持 URL 参数与分页状态同步
1005
+ 3. **性能**:对大型数据集使用高效的数据获取策略
1006
+ 4. **用户体验**:提供有关当前状态和总项目数的清晰反馈
1007
+ 5. **移动优化**:为移动设备适配行数选项和信息显示
1008
+ 6. **可访问性**:确保所有控件支持键盘操作
1009
+ 7. **错误处理**:优雅处理 API 失败,提供重试选项
1010
+
1011
+ ## 样式
1012
+
1013
+ 分页面板组件结合了多个子组件的样式:
1014
+
1015
+ ```css
1016
+ .uniface-pagination-panel {
1017
+ display: flex;
1018
+ align-items: center;
1019
+ justify-content: space-between;
1020
+ gap: 16px;
1021
+ padding: 16px 0;
1022
+ }
1023
+
1024
+ .uniface-pagination-panel.left {
1025
+ justify-content: flex-start;
1026
+ }
1027
+
1028
+ .uniface-pagination-panel.right {
1029
+ justify-content: flex-end;
1030
+ }
1031
+
1032
+ .page-options {
1033
+ display: flex;
1034
+ align-items: center;
1035
+ gap: 8px;
1036
+ font-size: 14px;
1037
+ }
1038
+
1039
+ .pagination {
1040
+ flex: 0 0 auto;
1041
+ }
1042
+
1043
+ .pagination-info {
1044
+ font-size: 14px;
1045
+ color: #666;
1046
+ }
1047
+
1048
+ /* 移动响应式 */
1049
+ @media (max-width: 767px) {
1050
+ .uniface-pagination-panel {
1051
+ flex-direction: column;
1052
+ gap: 12px;
1053
+ }
1054
+
1055
+ .page-options,
1056
+ .pagination-info {
1057
+ font-size: 12px;
1058
+ }
1059
+ }
1060
+ ```
1061
+
1062
+ ## 可访问性
1063
+
1064
+ - 全面支持键盘导航
1065
+ - 为所有交互元素提供 ARIA 标签
1066
+ - 页面更改的屏幕阅读器通知
1067
+ - 高对比度模式兼容性
1068
+ - 控件之间的焦点管理
1069
+
1070
+ ## 相关组件
1071
+
1072
+ - [分页](../pagination/README.md) - 核心分页组件
1073
+ - [选项单选](../options-select/README.md) - 行数选择器
1074
+ - [数据表格](../data-table/README.md) - 带分页的数据表格
1075
+ - [按钮](../button/README.md) - 用于自定义分页操作