@tdesign/uniapp 0.7.2 → 0.8.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 (199) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +32 -2
  3. package/dist/action-sheet/README.md +1 -1
  4. package/dist/action-sheet/action-sheet.vue +158 -150
  5. package/dist/action-sheet/props.ts +2 -2
  6. package/dist/action-sheet/type.ts +1 -1
  7. package/dist/avatar/avatar.vue +89 -87
  8. package/dist/avatar-group/avatar-group.vue +69 -67
  9. package/dist/back-top/back-top.vue +60 -58
  10. package/dist/badge/badge.vue +69 -59
  11. package/dist/button/button.vue +121 -116
  12. package/dist/button/props.ts +2 -2
  13. package/dist/button/type.ts +1 -1
  14. package/dist/calendar/calendar-header.vue +4 -4
  15. package/dist/calendar/calendar.vue +308 -297
  16. package/dist/calendar/template.vue +1 -1
  17. package/dist/cascader/README.en-US.md +2 -1
  18. package/dist/cascader/README.md +2 -1
  19. package/dist/cascader/cascader.vue +340 -328
  20. package/dist/cascader/props.ts +6 -1
  21. package/dist/cascader/type.ts +6 -0
  22. package/dist/cell/cell.vue +127 -121
  23. package/dist/cell-group/cell-group.vue +32 -30
  24. package/dist/check-tag/check-tag.vue +73 -71
  25. package/dist/checkbox/README.en-US.md +6 -6
  26. package/dist/checkbox/README.md +5 -5
  27. package/dist/checkbox/checkbox.vue +127 -127
  28. package/dist/checkbox/props.ts +6 -6
  29. package/dist/checkbox/type.ts +6 -4
  30. package/dist/checkbox-group/checkbox-group.vue +175 -173
  31. package/dist/checkbox-group/props.ts +6 -6
  32. package/dist/checkbox-group/type.ts +6 -4
  33. package/dist/col/col.vue +26 -24
  34. package/dist/collapse/collapse.vue +83 -81
  35. package/dist/collapse-panel/collapse-panel.vue +121 -119
  36. package/dist/collapse-panel/props.ts +4 -4
  37. package/dist/collapse-panel/type.ts +2 -2
  38. package/dist/color-picker/README.md +1 -1
  39. package/dist/color-picker/color-picker.vue +324 -322
  40. package/dist/color-picker/props.ts +2 -2
  41. package/dist/color-picker/template.vue +14 -10
  42. package/dist/common/common.ts +1 -0
  43. package/dist/common/style/theme/index.css +57 -61
  44. package/dist/common/utils.js +7 -2
  45. package/dist/common/validator.js +172 -0
  46. package/dist/config-provider/README.en-US.md +184 -0
  47. package/dist/config-provider/README.md +234 -0
  48. package/dist/config-provider/config-provider.vue +105 -0
  49. package/dist/config-provider/config-store.js +70 -0
  50. package/dist/config-provider/props.ts +16 -0
  51. package/dist/config-provider/reactive-state.js +39 -0
  52. package/dist/config-provider/type.ts +401 -0
  53. package/dist/config-provider/use-config.js +29 -0
  54. package/dist/config-provider/utils.js +29 -0
  55. package/dist/count-down/count-down.vue +98 -97
  56. package/dist/date-time-picker/date-time-picker.vue +410 -395
  57. package/dist/demo/demo.vue +1 -0
  58. package/dist/dialog/dialog.vue +176 -173
  59. package/dist/divider/divider.vue +38 -36
  60. package/dist/draggable/draggable.vue +60 -58
  61. package/dist/drawer/README.md +1 -1
  62. package/dist/drawer/drawer.vue +48 -46
  63. package/dist/dropdown-item/dropdown-item.vue +209 -207
  64. package/dist/dropdown-item/props.ts +4 -4
  65. package/dist/dropdown-item/type.ts +3 -3
  66. package/dist/dropdown-menu/dropdown-menu.vue +93 -99
  67. package/dist/empty/empty.vue +43 -42
  68. package/dist/fab/fab.vue +88 -86
  69. package/dist/footer/footer.vue +36 -34
  70. package/dist/form/README.en-US.md +17 -24
  71. package/dist/form/README.md +18 -25
  72. package/dist/form/form.css +1 -166
  73. package/dist/form/form.vue +251 -236
  74. package/dist/form/props.ts +2 -21
  75. package/dist/form/type.ts +7 -70
  76. package/dist/form-item/README.en-US.md +4 -5
  77. package/dist/form-item/README.md +4 -5
  78. package/dist/form-item/form-item.css +69 -96
  79. package/dist/form-item/form-item.vue +315 -336
  80. package/dist/form-item/form-model.ts +125 -173
  81. package/dist/form-item/props.ts +4 -17
  82. package/dist/form-item/type.ts +43 -1
  83. package/dist/grid/grid.vue +53 -51
  84. package/dist/grid-item/grid-item.vue +121 -119
  85. package/dist/guide/README.md +1 -1
  86. package/dist/guide/guide.vue +281 -277
  87. package/dist/icon/README.md +2 -4
  88. package/dist/icon/icon.vue +78 -76
  89. package/dist/image/README.md +1 -1
  90. package/dist/image/image.vue +103 -101
  91. package/dist/image-viewer/image-viewer.vue +160 -158
  92. package/dist/image-viewer/props.ts +2 -2
  93. package/dist/image-viewer/type.ts +1 -1
  94. package/dist/index.js +3 -0
  95. package/dist/indexes/indexes.vue +264 -267
  96. package/dist/indexes-anchor/indexes-anchor.vue +41 -41
  97. package/dist/input/input.vue +192 -192
  98. package/dist/input/props.ts +6 -6
  99. package/dist/input/type.ts +3 -3
  100. package/dist/link/link.vue +73 -71
  101. package/dist/loading/loading.vue +59 -59
  102. package/dist/locale/ar_KW.ts +157 -0
  103. package/dist/locale/en_US.ts +146 -0
  104. package/dist/locale/it_IT.ts +145 -0
  105. package/dist/locale/ja_JP.ts +132 -0
  106. package/dist/locale/ko_KR.ts +132 -0
  107. package/dist/locale/ru_RU.ts +157 -0
  108. package/dist/locale/zh_CN.ts +133 -0
  109. package/dist/locale/zh_TW.ts +132 -0
  110. package/dist/message/message.vue +181 -173
  111. package/dist/message/props.ts +2 -2
  112. package/dist/message/type.ts +1 -1
  113. package/dist/message-item/message-item.vue +192 -184
  114. package/dist/mixins/using-config.js +39 -0
  115. package/dist/navbar/navbar.vue +201 -199
  116. package/dist/notice-bar/notice-bar.vue +175 -171
  117. package/dist/notice-bar/props.ts +2 -2
  118. package/dist/notice-bar/type.ts +1 -1
  119. package/dist/npm/dayjs/esm/locale/ar.js +81 -0
  120. package/dist/npm/dayjs/esm/locale/it.js +39 -0
  121. package/dist/overlay/overlay.vue +50 -48
  122. package/dist/picker/picker.vue +168 -161
  123. package/dist/picker-item/picker-item.vue +269 -269
  124. package/dist/popover/README.md +1 -1
  125. package/dist/popover/popover.vue +262 -261
  126. package/dist/popover/props.ts +4 -4
  127. package/dist/popover/type.ts +2 -2
  128. package/dist/popup/popup.vue +46 -45
  129. package/dist/progress/README.md +1 -1
  130. package/dist/progress/progress.vue +76 -76
  131. package/dist/pull-down-refresh/props.ts +2 -2
  132. package/dist/pull-down-refresh/pull-down-refresh.vue +240 -234
  133. package/dist/pull-down-refresh/type.ts +1 -1
  134. package/dist/qrcode/README.md +1 -1
  135. package/dist/qrcode/components/qrcode-canvas/qrcode-canvas.vue +340 -338
  136. package/dist/qrcode/components/qrcode-status/qrcode-status.vue +6 -6
  137. package/dist/qrcode/qrcode.vue +93 -87
  138. package/dist/radio/props.ts +6 -6
  139. package/dist/radio/radio.vue +118 -120
  140. package/dist/radio/type.ts +3 -3
  141. package/dist/radio-group/props.ts +4 -4
  142. package/dist/radio-group/radio-group.vue +136 -134
  143. package/dist/radio-group/type.ts +4 -4
  144. package/dist/rate/computed.js +2 -2
  145. package/dist/rate/props.ts +4 -4
  146. package/dist/rate/rate.vue +155 -154
  147. package/dist/rate/type.ts +2 -2
  148. package/dist/result/result.vue +41 -39
  149. package/dist/row/row.vue +38 -36
  150. package/dist/scroll-view/scroll-view.vue +24 -22
  151. package/dist/search/props.ts +2 -2
  152. package/dist/search/search.vue +127 -125
  153. package/dist/search/type.ts +1 -1
  154. package/dist/side-bar/side-bar.vue +57 -55
  155. package/dist/side-bar-item/side-bar-item.vue +86 -86
  156. package/dist/skeleton/skeleton.vue +126 -124
  157. package/dist/slider/README.md +1 -1
  158. package/dist/slider/props.ts +2 -2
  159. package/dist/slider/slider.vue +457 -457
  160. package/dist/slider/type.ts +1 -1
  161. package/dist/step-item/step-item.vue +77 -75
  162. package/dist/stepper/props.ts +2 -2
  163. package/dist/stepper/stepper.vue +168 -149
  164. package/dist/stepper/type.ts +1 -1
  165. package/dist/steps/props.ts +2 -2
  166. package/dist/steps/steps.vue +83 -81
  167. package/dist/steps/type.ts +1 -1
  168. package/dist/sticky/sticky.vue +104 -102
  169. package/dist/swipe-cell/swipe-cell.vue +91 -89
  170. package/dist/swiper/README.md +1 -1
  171. package/dist/swiper/swiper.vue +91 -89
  172. package/dist/swiper-nav/swiper-nav.vue +38 -36
  173. package/dist/switch/props.ts +2 -2
  174. package/dist/switch/switch.vue +62 -62
  175. package/dist/switch/type.ts +1 -1
  176. package/dist/tab-bar/tab-bar.vue +88 -86
  177. package/dist/tab-bar-item/tab-bar-item.vue +85 -82
  178. package/dist/tab-panel/tab-panel.vue +66 -64
  179. package/dist/tabs/tabs.vue +294 -287
  180. package/dist/tag/tag.vue +79 -77
  181. package/dist/textarea/props.ts +6 -6
  182. package/dist/textarea/textarea.vue +127 -126
  183. package/dist/textarea/type.ts +3 -3
  184. package/dist/toast/toast.vue +107 -106
  185. package/dist/transition/transition.vue +30 -28
  186. package/dist/tree-select/tree-select.vue +151 -151
  187. package/dist/types/config-provider.d.ts +7 -0
  188. package/dist/types/index.d.ts +2 -0
  189. package/dist/types/popover.d.ts +7 -0
  190. package/dist/upload/README.en-US.md +13 -14
  191. package/dist/upload/README.md +11 -12
  192. package/dist/upload/props.ts +2 -4
  193. package/dist/upload/type.ts +12 -11
  194. package/dist/upload/upload.css +1 -1
  195. package/dist/upload/upload.vue +672 -512
  196. package/dist/watermark/watermark.vue +151 -149
  197. package/global.d.ts +2 -0
  198. package/package.json +16 -2
  199. package/dist/form/form-item-props.ts +0 -56
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <view
3
- :style="tools._style([customStyle, 'height:' + itemHeight * visibleItemCount + 'px'])"
4
- :class="tools.cls(classPrefix + '__group', []) + ' ' + tClass"
3
+ :style="'' + tools._style([customStyle, 'height:' + itemHeight * visibleItemCount + 'px'])"
4
+ :class="'' + tools.cls(classPrefix + '__group', []) + ' ' + tClass"
5
5
  @touchstart="onTouchStart"
6
6
  @touchmove.stop.prevent="onTouchMove"
7
7
  @touchend="onTouchEnd"
@@ -9,9 +9,7 @@
9
9
  >
10
10
  <view
11
11
  :class="classPrefix + '__wrapper'"
12
- :style="
13
- 'transition: transform ' + duration + 'ms cubic-bezier(0.215, 0.61, 0.355, 1); transform: translate3d(0, ' + offset + 'px, 0); padding: ' + wrapperPaddingY + 'px 0'
14
- "
12
+ :style="'transition: transform ' + duration + 'ms cubic-bezier(0.215, 0.61, 0.355, 1); transform: translate3d(0, ' + offset + 'px, 0); padding: ' + wrapperPaddingY + 'px 0'"
15
13
  >
16
14
  <!-- 虚拟滚动:占位容器(撑开总高度) -->
17
15
  <view
@@ -23,7 +21,7 @@
23
21
  <view
24
22
  v-for="(option, index) in visibleOptions"
25
23
  :key="index"
26
- :class="tools.cls(classPrefix + '__item', [['active', curIndex == virtualStartIndex + index]])"
24
+ :class="'' + tools.cls(classPrefix + '__item', [['active', curIndex == virtualStartIndex + index]])"
27
25
  :style="'height: ' + itemHeight + 'px'"
28
26
  :data-index="virtualStartIndex + index"
29
27
  @tap="onClickItem"
@@ -49,7 +47,7 @@
49
47
  <view
50
48
  v-for="(option, index) in visibleOptions"
51
49
  :key="index"
52
- :class="tools.cls(classPrefix + '__item', [['active', curIndex == index]])"
50
+ :class="'' + tools.cls(classPrefix + '__item', [['active', curIndex == index]])"
53
51
  :style="'height: ' + itemHeight + 'px'"
54
52
  :data-index="index"
55
53
  @click="onClickItem"
@@ -116,329 +114,331 @@ const momentum = (distance, duration) => {
116
114
  return nDistance;
117
115
  };
118
116
 
119
- export default uniComponent({
120
- name,
117
+ export default {
121
118
  components: {
122
119
  TIcon,
123
120
  },
124
- options: {
125
- styleIsolation: 'shared',
126
- virtualHost: true,
127
- },
128
- externalClasses: [
129
- `${prefix}-class`,
130
- ],
131
- mixins: [
132
- ChildrenMixin(RELATION_MAP.PickerItem),
133
- ],
134
- props: {
135
- ...props,
136
- useSlots: {
137
- type: Boolean,
138
- value: true,
139
- },
140
- },
141
- data() {
142
- return {
143
- prefix,
144
- classPrefix: name,
145
- offset: 0, // 滚动偏移量
146
- duration: 0, // 滚动动画延迟
147
- value: '',
148
- curIndex: 0,
149
- columnIndex: 0,
150
- keys: {},
151
- formatOptions: props.options.value,
152
- tools,
153
-
154
- enableVirtualScroll: false,
155
- visibleOptions: [],
156
- virtualStartIndex: 0,
157
- virtualOffsetY: 0,
158
- totalHeight: 0,
159
- itemHeight: 40,
160
- visibleItemCount: 5,
161
- wrapperPaddingY: 72,
162
- };
163
- },
164
- watch: {
121
+ ...uniComponent({
122
+ name,
165
123
  options: {
166
- handler() {
167
- this.update();
124
+ styleIsolation: 'shared',
125
+ virtualHost: true,
126
+ },
127
+ externalClasses: [
128
+ `${prefix}-class`,
129
+ ],
130
+ mixins: [
131
+ ChildrenMixin(RELATION_MAP.PickerItem),
132
+ ],
133
+ props: {
134
+ ...props,
135
+ useSlots: {
136
+ type: Boolean,
137
+ value: true,
168
138
  },
169
- immediate: true,
170
139
  },
171
- keys: {
172
- handler() {
173
- this.update();
140
+ data() {
141
+ return {
142
+ prefix,
143
+ classPrefix: name,
144
+ offset: 0, // 滚动偏移量
145
+ duration: 0, // 滚动动画延迟
146
+ value: '',
147
+ curIndex: 0,
148
+ columnIndex: 0,
149
+ keys: {},
150
+ formatOptions: props.options.value,
151
+ tools,
152
+
153
+ enableVirtualScroll: false,
154
+ visibleOptions: [],
155
+ virtualStartIndex: 0,
156
+ virtualOffsetY: 0,
157
+ totalHeight: 0,
158
+ itemHeight: 40,
159
+ visibleItemCount: 5,
160
+ wrapperPaddingY: 72,
161
+ };
162
+ },
163
+ watch: {
164
+ options: {
165
+ handler() {
166
+ this.update();
167
+ },
168
+ immediate: true,
169
+ },
170
+ keys: {
171
+ handler() {
172
+ this.update();
173
+ },
174
+ immediate: true,
174
175
  },
175
- immediate: true,
176
176
  },
177
- },
178
- created() {
179
- this.StartY = 0;
180
- this.StartOffset = 0;
181
- this.startTime = 0;
182
- this._animationTimer = null; // 动画期间更新虚拟滚动的定时器
183
- },
184
- mounted() {
177
+ created() {
178
+ this.StartY = 0;
179
+ this.StartOffset = 0;
180
+ this.startTime = 0;
181
+ this._animationTimer = null; // 动画期间更新虚拟滚动的定时器
182
+ },
183
+ mounted() {
185
184
 
186
- },
185
+ },
187
186
 
188
- beforeUnmount() {
187
+ beforeUnmount() {
189
188
  // 清理定时器,防止内存泄漏
190
- if (this._animationTimer) {
191
- clearInterval(this._animationTimer);
192
- this._animationTimer = null;
193
- }
194
- },
195
-
196
- methods: {
197
- onClickItem(event) {
198
- const { index: clickIndex } = event.currentTarget.dataset;
199
- const { itemHeight } = this;
200
- const index = range(clickIndex, 0, this.getCount() - 1);
201
-
202
- if (index !== this._selectedIndex) {
203
- this.offset = -index * itemHeight;
204
- this.curIndex = index;
205
- this.duration = 200;
189
+ if (this._animationTimer) {
190
+ clearInterval(this._animationTimer);
191
+ this._animationTimer = null;
206
192
  }
207
-
208
- this.updateSelected(index, true);
209
193
  },
210
194
 
211
- onTouchStart(event) {
212
- this.StartY = event.touches[0].clientY;
213
- this.StartOffset = this.offset;
214
- this.startTime = Date.now();
215
- this.duration = 0;
216
- },
195
+ methods: {
196
+ onClickItem(event) {
197
+ const { index: clickIndex } = event.currentTarget.dataset;
198
+ const { itemHeight } = this;
199
+ const index = range(clickIndex, 0, this.getCount() - 1);
217
200
 
218
- onTouchMove(event) {
219
- const { StartY, StartOffset } = this;
220
- const { itemHeight } = this;
201
+ if (index !== this._selectedIndex) {
202
+ this.offset = -index * itemHeight;
203
+ this.curIndex = index;
204
+ this.duration = 200;
205
+ }
221
206
 
222
- // 偏移增量
223
- const deltaY = event.touches[0].clientY - StartY;
224
- const newOffset = range(StartOffset + deltaY, -(this.getCount() - 1) * itemHeight, 0);
207
+ this.updateSelected(index, true);
208
+ },
225
209
 
226
- // touchMove 期间只更新 offset,不更新虚拟滚动数据
227
- // 虚拟滚动数据在 touchEnd 时统一更新,避免频繁 setData 导致掉帧
228
- this.offset = newOffset;
229
- },
210
+ onTouchStart(event) {
211
+ this.StartY = event.touches[0].clientY;
212
+ this.StartOffset = this.offset;
213
+ this.startTime = Date.now();
214
+ this.duration = 0;
215
+ },
230
216
 
231
- onTouchEnd(event) {
232
- const { offset, itemHeight, enableVirtualScroll, formatOptions } = this;
233
- const { startTime } = this;
234
- if (offset === this.StartOffset) {
235
- return;
236
- }
217
+ onTouchMove(event) {
218
+ const { StartY, StartOffset } = this;
219
+ const { itemHeight } = this;
237
220
 
238
- // 判断是否需要惯性滚动
239
- let distance = 0;
240
- const move = event.changedTouches[0].clientY - this.StartY;
241
- const moveTime = Date.now() - startTime;
242
- if (moveTime < INERTIA_TIME && Math.abs(move) > INERTIA_DISTANCE) {
243
- distance = momentum(move, moveTime);
244
- }
221
+ // 偏移增量
222
+ const deltaY = event.touches[0].clientY - StartY;
223
+ const newOffset = range(StartOffset + deltaY, -(this.getCount() - 1) * itemHeight, 0);
245
224
 
246
- // 调整偏移量
247
- const newOffset = range(offset + distance, -this.getCount() * itemHeight, 0);
248
- const index = range(Math.round(-newOffset / itemHeight), 0, this.getCount() - 1);
249
- const finalOffset = -index * itemHeight;
250
-
251
- // 动态计算动画时长:根据滑动距离调整,距离越大时长越长,但有上限
252
- const scrollDistance = Math.abs(finalOffset - offset);
253
- const scrollItems = scrollDistance / itemHeight;
254
- const animationDuration = Math.min(
255
- ANIMATION_DURATION_MAX,
256
- ANIMATION_DURATION_BASE + scrollItems * 30, // 每滑动一个选项增加30ms
257
- );
258
-
259
- // 判断是否为快速惯性滚动(用于决定缓冲区大小)
260
- const isFastInertia = Math.abs(distance) > itemHeight * 3;
261
- // 根据是否快速惯性滚动选择缓冲区大小
262
- const bufferCount = isFastInertia ? VIRTUAL_SCROLL_CONFIG.FAST_SCROLL_BUFFER : VIRTUAL_SCROLL_CONFIG.BUFFER_COUNT;
263
-
264
- // 清除之前的动画更新定时器
265
- if (this._animationTimer) {
266
- clearInterval(this._animationTimer);
267
- this._animationTimer = null;
268
- }
225
+ // touchMove 期间只更新 offset,不更新虚拟滚动数据
226
+ // 虚拟滚动数据在 touchEnd 时统一更新,避免频繁 setData 导致掉帧
227
+ this.offset = newOffset;
228
+ },
269
229
 
270
- // 性能优化:直接赋值更新所有状态
271
- this.offset = finalOffset;
272
- this.duration = animationDuration;
273
- this.curIndex = index;
230
+ onTouchEnd(event) {
231
+ const { offset, itemHeight, enableVirtualScroll, formatOptions } = this;
232
+ const { startTime } = this;
233
+ if (offset === this.StartOffset) {
234
+ return;
235
+ }
236
+
237
+ // 判断是否需要惯性滚动
238
+ let distance = 0;
239
+ const move = event.changedTouches[0].clientY - this.StartY;
240
+ const moveTime = Date.now() - startTime;
241
+ if (moveTime < INERTIA_TIME && Math.abs(move) > INERTIA_DISTANCE) {
242
+ distance = momentum(move, moveTime);
243
+ }
244
+
245
+ // 调整偏移量
246
+ const newOffset = range(offset + distance, -this.getCount() * itemHeight, 0);
247
+ const index = range(Math.round(-newOffset / itemHeight), 0, this.getCount() - 1);
248
+ const finalOffset = -index * itemHeight;
249
+
250
+ // 动态计算动画时长:根据滑动距离调整,距离越大时长越长,但有上限
251
+ const scrollDistance = Math.abs(finalOffset - offset);
252
+ const scrollItems = scrollDistance / itemHeight;
253
+ const animationDuration = Math.min(
254
+ ANIMATION_DURATION_MAX,
255
+ ANIMATION_DURATION_BASE + scrollItems * 30, // 每滑动一个选项增加30ms
256
+ );
257
+
258
+ // 判断是否为快速惯性滚动(用于决定缓冲区大小)
259
+ const isFastInertia = Math.abs(distance) > itemHeight * 3;
260
+ // 根据是否快速惯性滚动选择缓冲区大小
261
+ const bufferCount = isFastInertia ? VIRTUAL_SCROLL_CONFIG.FAST_SCROLL_BUFFER : VIRTUAL_SCROLL_CONFIG.BUFFER_COUNT;
262
+
263
+ // 清除之前的动画更新定时器
264
+ if (this._animationTimer) {
265
+ clearInterval(this._animationTimer);
266
+ this._animationTimer = null;
267
+ }
268
+
269
+ // 性能优化:直接赋值更新所有状态
270
+ this.offset = finalOffset;
271
+ this.duration = animationDuration;
272
+ this.curIndex = index;
274
273
 
275
- // 虚拟滚动:预先计算覆盖动画全程的可见范围,避免动画期间频繁更新
276
- if (enableVirtualScroll) {
274
+ // 虚拟滚动:预先计算覆盖动画全程的可见范围,避免动画期间频繁更新
275
+ if (enableVirtualScroll) {
277
276
  // 计算当前位置和目标位置的索引范围
278
- const currentIndex = Math.floor(Math.abs(offset) / itemHeight);
279
- const targetIndex = index;
277
+ const currentIndex = Math.floor(Math.abs(offset) / itemHeight);
278
+ const targetIndex = index;
280
279
 
281
- // 计算覆盖动画全程的可见范围(从当前位置到目标位置)
282
- const minIndex = Math.min(currentIndex, targetIndex);
283
- const maxIndex = Math.max(currentIndex, targetIndex);
280
+ // 计算覆盖动画全程的可见范围(从当前位置到目标位置)
281
+ const minIndex = Math.min(currentIndex, targetIndex);
282
+ const maxIndex = Math.max(currentIndex, targetIndex);
284
283
 
285
- // 使用缓冲区扩展范围,确保动画过程中不会出现空白
286
- const animationStartIndex = Math.max(0, minIndex - bufferCount);
287
- const animationEndIndex = Math.min(formatOptions.length, maxIndex + this.visibleItemCount + bufferCount);
284
+ // 使用缓冲区扩展范围,确保动画过程中不会出现空白
285
+ const animationStartIndex = Math.max(0, minIndex - bufferCount);
286
+ const animationEndIndex = Math.min(formatOptions.length, maxIndex + this.visibleItemCount + bufferCount);
288
287
 
289
- this.visibleOptions = formatOptions.slice(animationStartIndex, animationEndIndex);
290
- this.virtualStartIndex = animationStartIndex;
291
- this.virtualOffsetY = animationStartIndex * itemHeight;
288
+ this.visibleOptions = formatOptions.slice(animationStartIndex, animationEndIndex);
289
+ this.virtualStartIndex = animationStartIndex;
290
+ this.virtualOffsetY = animationStartIndex * itemHeight;
292
291
 
293
- // 使用 nextTick 确保 DOM 更新后再执行后续操作
294
- nextTick().then(() => {
292
+ // 使用 nextTick 确保 DOM 更新后再执行后续操作
293
+ nextTick().then(() => {
295
294
  // 动画结束后,精确更新虚拟滚动视图到最终位置
296
- const visibleRange = this.computeVirtualRange(finalOffset, formatOptions.length, itemHeight, false);
297
- this.visibleOptions = formatOptions.slice(visibleRange.startIndex, visibleRange.endIndex);
298
- this.virtualStartIndex = visibleRange.startIndex;
299
- this.virtualOffsetY = visibleRange.startIndex * itemHeight;
300
- });
301
- }
302
-
303
- if (index === this._selectedIndex) return;
304
- this.updateSelected(index, true);
305
- },
306
-
307
- formatOption(options, columnIndex, format) {
308
- if (typeof format !== 'function') return options;
295
+ const visibleRange = this.computeVirtualRange(finalOffset, formatOptions.length, itemHeight, false);
296
+ this.visibleOptions = formatOptions.slice(visibleRange.startIndex, visibleRange.endIndex);
297
+ this.virtualStartIndex = visibleRange.startIndex;
298
+ this.virtualOffsetY = visibleRange.startIndex * itemHeight;
299
+ });
300
+ }
301
+
302
+ if (index === this._selectedIndex) return;
303
+ this.updateSelected(index, true);
304
+ },
309
305
 
310
- return options.map(ele => format(ele, columnIndex));
311
- },
306
+ formatOption(options, columnIndex, format) {
307
+ if (typeof format !== 'function') return options;
312
308
 
313
- updateSelected(index, trigger) {
314
- const { columnIndex, keys, formatOptions } = this;
315
- this._selectedIndex = index;
316
- this._selectedValue = formatOptions[index]?.[keys?.value];
317
- this._selectedLabel = formatOptions[index]?.[keys?.label];
309
+ return options.map(ele => format(ele, columnIndex));
310
+ },
318
311
 
319
- if (trigger) {
320
- this[RELATION_MAP.PickerItem]?.triggerColumnChange({
321
- index,
322
- column: columnIndex,
323
- });
324
- }
325
- },
312
+ updateSelected(index, trigger) {
313
+ const { columnIndex, keys, formatOptions } = this;
314
+ this._selectedIndex = index;
315
+ this._selectedValue = formatOptions[index]?.[keys?.value];
316
+ this._selectedLabel = formatOptions[index]?.[keys?.label];
317
+
318
+ if (trigger) {
319
+ this[RELATION_MAP.PickerItem]?.triggerColumnChange({
320
+ index,
321
+ column: columnIndex,
322
+ });
323
+ }
324
+ },
326
325
 
327
- // 刷新选中状态
328
- update() {
329
- const { options, value, keys, format, columnIndex, itemHeight, visibleItemCount } = this;
326
+ // 刷新选中状态
327
+ update() {
328
+ const { options, value, keys, format, columnIndex, itemHeight, visibleItemCount } = this;
330
329
 
331
- const formatOptions = this.formatOption(options, columnIndex, format);
332
- const optionsCount = formatOptions.length;
330
+ const formatOptions = this.formatOption(options, columnIndex, format);
331
+ const optionsCount = formatOptions.length;
333
332
 
334
- // 判断是否启用虚拟滚动
335
- const enableVirtualScroll = optionsCount >= VIRTUAL_SCROLL_CONFIG.ENABLE_THRESHOLD;
333
+ // 判断是否启用虚拟滚动
334
+ const enableVirtualScroll = optionsCount >= VIRTUAL_SCROLL_CONFIG.ENABLE_THRESHOLD;
336
335
 
337
- // 大数据量优化:使用 Map 快速查找索引
338
- let index = -1;
339
- if (optionsCount > 500) {
336
+ // 大数据量优化:使用 Map 快速查找索引
337
+ let index = -1;
338
+ if (optionsCount > 500) {
340
339
  // 构建临时 Map(只在查找时构建,不缓存)
341
- const valueMap = new Map(formatOptions.map((item, idx) => [item[keys?.value], idx]));
342
- index = valueMap.get(value) ?? -1;
343
- } else {
344
- index = formatOptions.findIndex(item => item[keys?.value] === value);
345
- }
346
- const selectedIndex = index > 0 ? index : 0;
347
-
348
- // 计算wrapper的padding,确保选中项居中显示
349
- const wrapperPaddingY = ((visibleItemCount - 1) / 2) * itemHeight;
350
-
351
- // 直接赋值更新所有状态
352
- this.formatOptions = formatOptions;
353
- this.offset = -selectedIndex * itemHeight;
354
- this.curIndex = selectedIndex;
355
- this.enableVirtualScroll = enableVirtualScroll;
356
- this.totalHeight = optionsCount * itemHeight;
357
- this.wrapperPaddingY = wrapperPaddingY;
358
-
359
- // 如果启用虚拟滚动,计算可见选项
360
- if (enableVirtualScroll) {
361
- const visibleRange = this.computeVirtualRange(-selectedIndex * itemHeight, optionsCount, itemHeight);
362
- this.visibleOptions = formatOptions.slice(visibleRange.startIndex, visibleRange.endIndex);
363
- this.virtualStartIndex = visibleRange.startIndex;
364
- this.virtualOffsetY = visibleRange.startIndex * itemHeight;
365
- } else {
340
+ const valueMap = new Map(formatOptions.map((item, idx) => [item[keys?.value], idx]));
341
+ index = valueMap.get(value) ?? -1;
342
+ } else {
343
+ index = formatOptions.findIndex(item => item[keys?.value] === value);
344
+ }
345
+ const selectedIndex = index > 0 ? index : 0;
346
+
347
+ // 计算wrapper的padding,确保选中项居中显示
348
+ const wrapperPaddingY = ((visibleItemCount - 1) / 2) * itemHeight;
349
+
350
+ // 直接赋值更新所有状态
351
+ this.formatOptions = formatOptions;
352
+ this.offset = -selectedIndex * itemHeight;
353
+ this.curIndex = selectedIndex;
354
+ this.enableVirtualScroll = enableVirtualScroll;
355
+ this.totalHeight = optionsCount * itemHeight;
356
+ this.wrapperPaddingY = wrapperPaddingY;
357
+
358
+ // 如果启用虚拟滚动,计算可见选项
359
+ if (enableVirtualScroll) {
360
+ const visibleRange = this.computeVirtualRange(-selectedIndex * itemHeight, optionsCount, itemHeight);
361
+ this.visibleOptions = formatOptions.slice(visibleRange.startIndex, visibleRange.endIndex);
362
+ this.virtualStartIndex = visibleRange.startIndex;
363
+ this.virtualOffsetY = visibleRange.startIndex * itemHeight;
364
+ } else {
366
365
  // 不启用虚拟滚动时,visibleOptions 等于 formatOptions
367
- this.visibleOptions = formatOptions;
368
- this.virtualStartIndex = 0;
369
- this.virtualOffsetY = 0;
370
- }
366
+ this.visibleOptions = formatOptions;
367
+ this.virtualStartIndex = 0;
368
+ this.virtualOffsetY = 0;
369
+ }
371
370
 
372
- nextTick().then(() => {
373
- this.updateSelected(selectedIndex, false);
374
- });
375
- },
371
+ nextTick().then(() => {
372
+ this.updateSelected(selectedIndex, false);
373
+ });
374
+ },
376
375
 
377
- /**
376
+ /**
378
377
  * 计算虚拟滚动的可见范围
379
378
  * @param offset 当前滚动偏移量
380
379
  * @param totalCount 总选项数量
381
380
  * @param itemHeight 单个选项高度
382
381
  * @param isFastScroll 是否为快速滑动
383
382
  */
384
- computeVirtualRange(offset, totalCount, itemHeight, isFastScroll = false) {
385
- const scrollTop = Math.abs(offset);
386
- const { BUFFER_COUNT, FAST_SCROLL_BUFFER } = VIRTUAL_SCROLL_CONFIG;
387
- const { visibleItemCount } = this;
383
+ computeVirtualRange(offset, totalCount, itemHeight, isFastScroll = false) {
384
+ const scrollTop = Math.abs(offset);
385
+ const { BUFFER_COUNT, FAST_SCROLL_BUFFER } = VIRTUAL_SCROLL_CONFIG;
386
+ const { visibleItemCount } = this;
388
387
 
389
- // 根据滑动速度动态调整缓冲区大小
390
- const bufferCount = isFastScroll ? FAST_SCROLL_BUFFER : BUFFER_COUNT;
388
+ // 根据滑动速度动态调整缓冲区大小
389
+ const bufferCount = isFastScroll ? FAST_SCROLL_BUFFER : BUFFER_COUNT;
391
390
 
392
- // 计算当前可见区域的中心索引
393
- const centerIndex = Math.floor(scrollTop / itemHeight);
391
+ // 计算当前可见区域的中心索引
392
+ const centerIndex = Math.floor(scrollTop / itemHeight);
394
393
 
395
- // 计算起始索引(减去缓冲区)
396
- const startIndex = Math.max(0, centerIndex - bufferCount);
397
- // 计算结束索引(加上可见数量和缓冲区)
398
- const endIndex = Math.min(totalCount, centerIndex + visibleItemCount + bufferCount);
394
+ // 计算起始索引(减去缓冲区)
395
+ const startIndex = Math.max(0, centerIndex - bufferCount);
396
+ // 计算结束索引(加上可见数量和缓冲区)
397
+ const endIndex = Math.min(totalCount, centerIndex + visibleItemCount + bufferCount);
399
398
 
400
- return { startIndex, endIndex };
401
- },
399
+ return { startIndex, endIndex };
400
+ },
402
401
 
403
- /**
402
+ /**
404
403
  * 更新虚拟滚动的可见选项
405
404
  * @param offset 当前滚动偏移量(可选,不传则使用 data.offset)
406
405
  * @param isFastScroll 是否为快速滑动
407
406
  */
408
- updateVisibleOptions(offset, isFastScroll = false) {
409
- const { formatOptions, itemHeight, enableVirtualScroll } = this;
407
+ updateVisibleOptions(offset, isFastScroll = false) {
408
+ const { formatOptions, itemHeight, enableVirtualScroll } = this;
410
409
 
411
- if (!enableVirtualScroll) return;
410
+ if (!enableVirtualScroll) return;
412
411
 
413
- const currentOffset = offset !== undefined ? offset : this.offset;
414
- const visibleRange = this.computeVirtualRange(currentOffset, formatOptions.length, itemHeight, isFastScroll);
412
+ const currentOffset = offset !== undefined ? offset : this.offset;
413
+ const visibleRange = this.computeVirtualRange(currentOffset, formatOptions.length, itemHeight, isFastScroll);
415
414
 
416
- // 只有当可见范围发生变化时才更新
417
- if (
418
- visibleRange.startIndex !== this.virtualStartIndex
415
+ // 只有当可见范围发生变化时才更新
416
+ if (
417
+ visibleRange.startIndex !== this.virtualStartIndex
419
418
  || visibleRange.endIndex !== this.virtualStartIndex + this.visibleOptions.length
420
- ) {
421
- this.visibleOptions = formatOptions.slice(visibleRange.startIndex, visibleRange.endIndex);
422
- this.virtualStartIndex = visibleRange.startIndex;
423
- this.virtualOffsetY = visibleRange.startIndex * itemHeight;
424
- }
425
- },
419
+ ) {
420
+ this.visibleOptions = formatOptions.slice(visibleRange.startIndex, visibleRange.endIndex);
421
+ this.virtualStartIndex = visibleRange.startIndex;
422
+ this.virtualOffsetY = visibleRange.startIndex * itemHeight;
423
+ }
424
+ },
426
425
 
427
- getCount() {
428
- return this.options?.length;
429
- },
426
+ getCount() {
427
+ return this.options?.length;
428
+ },
430
429
 
431
- getCurrentSelected() {
432
- const { offset, itemHeight, formatOptions, keys } = this;
433
- const currentIndex = Math.max(0, Math.min(Math.round(-offset / itemHeight), this.getCount() - 1));
430
+ getCurrentSelected() {
431
+ const { offset, itemHeight, formatOptions, keys } = this;
432
+ const currentIndex = Math.max(0, Math.min(Math.round(-offset / itemHeight), this.getCount() - 1));
434
433
 
435
- return {
436
- index: currentIndex,
437
- value: formatOptions[currentIndex]?.[keys?.value],
438
- label: formatOptions[currentIndex]?.[keys?.label],
439
- };
434
+ return {
435
+ index: currentIndex,
436
+ value: formatOptions[currentIndex]?.[keys?.value],
437
+ label: formatOptions[currentIndex]?.[keys?.label],
438
+ };
439
+ },
440
440
  },
441
- },
442
- });
441
+ }),
442
+ };
443
443
  </script>
444
444
  <style scoped src="./picker-item.css"></style>
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: Popover 弹出气泡
3
3
  description: 用于文字提示的气泡框。
4
- spline: data
4
+ spline: message
5
5
  isComponent: true
6
6
  ---
7
7