@tarojs/components-react 4.1.9-beta.1 → 4.1.9-beta.1-patch.1

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 (32) hide show
  1. package/dist/components/picker/index.js +22 -3
  2. package/dist/components/picker/index.js.map +1 -1
  3. package/dist/components/picker/picker-group.js +242 -81
  4. package/dist/components/picker/picker-group.js.map +1 -1
  5. package/dist/components/scroll-view/index.js +104 -30
  6. package/dist/components/scroll-view/index.js.map +1 -1
  7. package/dist/contexts/ScrollElementContext.js +6 -0
  8. package/dist/contexts/ScrollElementContext.js.map +1 -0
  9. package/dist/index.css +1 -1
  10. package/dist/index.js +1 -0
  11. package/dist/index.js.map +1 -1
  12. package/dist/original/components/picker/index.js +22 -3
  13. package/dist/original/components/picker/index.js.map +1 -1
  14. package/dist/original/components/picker/picker-group.js +242 -81
  15. package/dist/original/components/picker/picker-group.js.map +1 -1
  16. package/dist/original/components/picker/style/index.scss +146 -46
  17. package/dist/original/components/scroll-view/index.js +104 -30
  18. package/dist/original/components/scroll-view/index.js.map +1 -1
  19. package/dist/original/contexts/ScrollElementContext.js +6 -0
  20. package/dist/original/contexts/ScrollElementContext.js.map +1 -0
  21. package/dist/original/index.js +1 -0
  22. package/dist/original/index.js.map +1 -1
  23. package/dist/solid/components/picker/index.js +33 -14
  24. package/dist/solid/components/picker/index.js.map +1 -1
  25. package/dist/solid/components/picker/picker-group.js +243 -86
  26. package/dist/solid/components/picker/picker-group.js.map +1 -1
  27. package/dist/solid/components/scroll-view/index.js +109 -35
  28. package/dist/solid/components/scroll-view/index.js.map +1 -1
  29. package/dist/solid/contexts/ScrollElementContext.js +6 -0
  30. package/dist/solid/contexts/ScrollElementContext.js.map +1 -0
  31. package/dist/solid/index.css +1 -1
  32. package/package.json +6 -6
@@ -1,4 +1,4 @@
1
- import { createComponent } from 'solid-js/web';
1
+ import { createComponent, mergeProps } from 'solid-js/web';
2
2
  import { View, ScrollView } from '@tarojs/components';
3
3
  import Taro from '@tarojs/taro';
4
4
  import * as React from 'react';
@@ -7,27 +7,146 @@ import * as React from 'react';
7
7
  const PICKER_LINE_HEIGHT = 34; // px
8
8
  const PICKER_VISIBLE_ITEMS = 7; // 可见行数
9
9
  const PICKER_BLANK_ITEMS = 3; // 空白行数
10
- // 辅助函数:获取系统信息的 lengthScaleRatio 并设置 targetScrollTop
11
- const setTargetScrollTopWithScale = (setTargetScrollTop, baseValue, randomOffset) => {
12
- Taro.getSystemInfo({
13
- success: res => {
14
- var _a;
15
- // 使用类型断言访问可能不存在的 lengthScaleRatio 属性
16
- const lengthScaleRatio = (_a = res.lengthScaleRatio) !== null && _a !== void 0 ? _a : 1;
17
- if (!res.lengthScaleRatio) {
18
- console.warn('Taro.getSystemInfo: lengthScaleRatio 不存在,使用默认值 1');
19
- }
20
- const scaledValue = baseValue * lengthScaleRatio;
21
- const finalValue = randomOffset !== undefined ? scaledValue + randomOffset : scaledValue;
22
- setTargetScrollTop(finalValue);
23
- },
24
- fail: err => {
25
- console.error('获取系统信息失败:', err);
26
- // 失败时使用默认值 1
27
- const finalValue = randomOffset !== undefined ? baseValue + randomOffset : baseValue;
28
- setTargetScrollTop(finalValue);
10
+ const getIndicatorStyle = lineColor => {
11
+ return {
12
+ borderTopColor: lineColor,
13
+ borderBottomColor: lineColor
14
+ };
15
+ };
16
+ // 大屏方案版本要求
17
+ const MIN_DESIGN_APP_VERSION = 16;
18
+ const MIN_APP_VERSION = '15.7.0';
19
+ // semver 版本比较
20
+ const isAppVersionAtLeast = (version, min) => {
21
+ var _a, _b;
22
+ if (!version || typeof version !== 'string') return false;
23
+ const parts = v => {
24
+ const m = String(v).trim().match(/^(\d+)(?:\.(\d+))?(?:\.(\d+))?/);
25
+ if (!m) return [];
26
+ return [parseInt(m[1], 10) || 0, parseInt(m[2] || '0', 10) || 0, parseInt(m[3] || '0', 10) || 0];
27
+ };
28
+ const a = parts(version);
29
+ const b = parts(min);
30
+ if (a.length === 0) return false;
31
+ if (b.length === 0) return true;
32
+ for (let i = 0; i < Math.max(a.length, b.length); i++) {
33
+ const da = (_a = a[i]) !== null && _a !== void 0 ? _a : 0;
34
+ const db = (_b = b[i]) !== null && _b !== void 0 ? _b : 0;
35
+ if (da > db) return true;
36
+ if (da < db) return false;
37
+ }
38
+ return true;
39
+ };
40
+ // 读取 JDMobileConfig,异常时返回 undefined
41
+ const tryGetMobileConfigSync = opt => {
42
+ var _a;
43
+ try {
44
+ const fn = (_a = Taro.JDMobileConfig) === null || _a === void 0 ? void 0 : _a.getMobileConfigSync;
45
+ if (typeof fn !== 'function') return undefined;
46
+ return fn(opt);
47
+ } catch (_b) {
48
+ return undefined;
49
+ }
50
+ };
51
+ // 判断是否启用测量值缩放适配(true=启用, false=使用系统侧缩放)
52
+ const resolveUseMeasuredScale = res => {
53
+ // H5/weapp 不参与大屏系数
54
+ if (process.env.TARO_ENV === 'h5' || process.env.TARO_ENV === 'weapp') {
55
+ return false;
56
+ }
57
+ // 条件1: designAppVersion < 16,不满足则使用系统侧缩放
58
+ const designAppVersionRaw = res.designAppVersion;
59
+ const designAppVersionMajor = designAppVersionRaw != null ? parseInt(String(designAppVersionRaw).trim(), 10) : Number.NaN;
60
+ if (!Number.isFinite(designAppVersionMajor) || designAppVersionMajor < MIN_DESIGN_APP_VERSION) {
61
+ return false;
62
+ }
63
+ // 条件2: appVersion < 15.7.0,不满足则使用系统侧缩放
64
+ if (!isAppVersionAtLeast(res.version, MIN_APP_VERSION)) {
65
+ return false;
66
+ }
67
+ // 条件3: 平台判断
68
+ const platform = String(res.platform || '').toLowerCase();
69
+ if (platform === 'harmony') {
70
+ return true;
71
+ }
72
+ if (platform === 'android') {
73
+ const raw = tryGetMobileConfigSync({
74
+ space: 'taro',
75
+ configName: 'config',
76
+ key: 'disableFixBoundingScaleRatio'
77
+ });
78
+ return raw !== 1 && raw !== '1';
79
+ }
80
+ if (platform === 'ios') {
81
+ const raw = tryGetMobileConfigSync({
82
+ space: 'Taro',
83
+ configName: 'excutor',
84
+ key: 'disableBoundingScaleRatio'
85
+ });
86
+ return raw !== 1 && raw !== '1';
87
+ }
88
+ return false;
89
+ };
90
+ // 辅助函数:计算 lengthScaleRatio
91
+ const calculateLengthScaleRatio = res => {
92
+ let lengthScaleRatio = res === null || res === void 0 ? void 0 : res.lengthScaleRatio;
93
+ if (lengthScaleRatio == null || lengthScaleRatio === 0) {
94
+ console.warn('Taro.getSystemInfo: lengthScaleRatio 不存在,使用计算值');
95
+ lengthScaleRatio = 1;
96
+ if (res.windowWidth < 320) {
97
+ lengthScaleRatio = res.windowWidth / 320;
98
+ } else if (res.windowWidth >= 400 && res.windowWidth < 600) {
99
+ lengthScaleRatio = res.windowWidth / 400;
100
+ }
101
+ const shortSide = res.windowWidth < res.windowHeight ? res.windowWidth : res.windowHeight;
102
+ const isBigScreen = shortSide >= 600;
103
+ if (isBigScreen) {
104
+ lengthScaleRatio = shortSide / 720;
29
105
  }
30
- });
106
+ }
107
+ return lengthScaleRatio;
108
+ };
109
+ // 辅助函数:获取系统信息的 lengthScaleRatio 并设置 targetScrollTop
110
+ const setTargetScrollTopWithScale = function (setTargetScrollTop, baseValue, randomOffset) {
111
+ let lengthScaleRatio = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1;
112
+ // H5 和 weapp 不参与放大计算,直接使用 baseValue
113
+ if (process.env.TARO_ENV === 'h5' || process.env.TARO_ENV === 'weapp') {
114
+ const finalValue = randomOffset !== undefined ? baseValue + randomOffset : baseValue;
115
+ setTargetScrollTop(finalValue);
116
+ return;
117
+ }
118
+ if (process.env.TARO_PLATFORM === 'harmony') {
119
+ const scaledValue = baseValue;
120
+ const finalValue = randomOffset !== undefined ? scaledValue + randomOffset : scaledValue;
121
+ setTargetScrollTop(finalValue);
122
+ } else {
123
+ const scaledValue = baseValue * lengthScaleRatio;
124
+ const finalValue = randomOffset !== undefined ? scaledValue + randomOffset : scaledValue;
125
+ setTargetScrollTop(finalValue);
126
+ }
127
+ };
128
+ // 根据 scrollTop 计算选中索引
129
+ // 系统侧缩放模式:scrollHeight 已被系统缩放,直接相除即可
130
+ // 自行缩放模式:需要除以 ratio 换算(harmony 特殊处理,ratio 已内嵌在 itemHeight 中)
131
+ const getSelectedIndex = function (scrollTop, itemHeight) {
132
+ let lengthScaleRatio = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
133
+ let useMeasuredScale = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
134
+ if (!useMeasuredScale || process.env.TARO_PLATFORM === 'harmony') {
135
+ return Math.round(scrollTop / itemHeight);
136
+ }
137
+ return Math.round(scrollTop / lengthScaleRatio / itemHeight);
138
+ };
139
+ // 计算单项高度(返回设计稿值)
140
+ const calculateItemHeight = function (scrollView, lengthScaleRatio) {
141
+ let useMeasuredScale = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
142
+ if (process.env.TARO_PLATFORM === 'harmony') {
143
+ return useMeasuredScale ? PICKER_LINE_HEIGHT * lengthScaleRatio : PICKER_LINE_HEIGHT;
144
+ }
145
+ if (scrollView && (scrollView === null || scrollView === void 0 ? void 0 : scrollView.scrollHeight)) {
146
+ return useMeasuredScale ? scrollView.scrollHeight / lengthScaleRatio / scrollView.childNodes.length : scrollView.scrollHeight / scrollView.childNodes.length;
147
+ }
148
+ console.warn('Height measurement anomaly');
149
+ return PICKER_LINE_HEIGHT;
31
150
  };
32
151
  function PickerGroupBasic(props) {
33
152
  const {
@@ -40,6 +159,7 @@ function PickerGroupBasic(props) {
40
159
  // 使用selectedIndex参数,默认为0
41
160
  colors = {}
42
161
  } = props;
162
+ const indicatorStyle = colors.lineColor ? getIndicatorStyle(colors.lineColor) : null;
43
163
  const [targetScrollTop, setTargetScrollTop] = React.useState(0);
44
164
  const scrollViewRef = React.useRef(null);
45
165
  const itemRefs = React.useRef([]);
@@ -47,26 +167,31 @@ function PickerGroupBasic(props) {
47
167
  const [currentIndex, setCurrentIndex] = React.useState(selectedIndex);
48
168
  // 触摸状态用于优化用户体验
49
169
  const [isTouching, setIsTouching] = React.useState(false);
170
+ const lengthScaleRatioRef = React.useRef(1);
171
+ const useMeasuredScaleRef = React.useRef(false);
50
172
  const itemHeightRef = React.useRef(PICKER_LINE_HEIGHT);
173
+ // 初始化时计算 lengthScaleRatio 并判定缩放模式
51
174
  React.useEffect(() => {
52
- var _a;
53
- if (process.env.TARO_PLATFORM !== 'harmony') {
54
- if (scrollViewRef.current && ((_a = scrollViewRef.current) === null || _a === void 0 ? void 0 : _a.scrollHeigh)) {
55
- itemHeightRef.current = scrollViewRef.current.scrollHeight / scrollViewRef.current.childNodes.length;
56
- } else {
57
- console.warn('Height measurement anomaly');
175
+ Taro.getSystemInfo({
176
+ success: res => {
177
+ lengthScaleRatioRef.current = calculateLengthScaleRatio(res);
178
+ useMeasuredScaleRef.current = resolveUseMeasuredScale(res);
179
+ itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
180
+ },
181
+ fail: () => {
182
+ lengthScaleRatioRef.current = 1;
183
+ useMeasuredScaleRef.current = false;
58
184
  }
59
- }
185
+ });
186
+ }, []);
187
+ React.useEffect(() => {
188
+ itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
60
189
  }, [range.length]); // 只在range长度变化时重新计算
61
- // 获取选中的索引
62
- const getSelectedIndex = scrollTop => {
63
- return Math.round(scrollTop / itemHeightRef.current);
64
- };
65
190
  // 当selectedIndex变化时,调整滚动位置
66
191
  React.useEffect(() => {
67
192
  if (scrollViewRef.current && range.length > 0 && !isTouching) {
68
193
  const baseValue = selectedIndex * itemHeightRef.current;
69
- setTargetScrollTopWithScale(setTargetScrollTop, baseValue);
194
+ setTargetScrollTopWithScale(setTargetScrollTop, baseValue, undefined, lengthScaleRatioRef.current);
70
195
  setCurrentIndex(selectedIndex);
71
196
  }
72
197
  }, [selectedIndex, range]);
@@ -83,16 +208,17 @@ function PickerGroupBasic(props) {
83
208
  isCenterTimerId.current = setTimeout(() => {
84
209
  if (!scrollViewRef.current) return;
85
210
  const scrollTop = scrollViewRef.current.scrollTop;
86
- const newIndex = getSelectedIndex(scrollTop);
211
+ const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
87
212
  setIsTouching(false);
88
213
  const baseValue = newIndex * itemHeightRef.current;
89
214
  const randomOffset = Math.random() * 0.001; // 随机数为了在一个项内滚动时强制刷新
90
- setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset);
215
+ setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset, lengthScaleRatioRef.current);
91
216
  updateIndex(newIndex, columnId);
92
217
  onColumnChange === null || onColumnChange === void 0 ? void 0 : onColumnChange({
93
218
  columnId,
94
219
  index: newIndex
95
220
  });
221
+ isCenterTimerId.current = null;
96
222
  }, 100);
97
223
  };
98
224
  // 滚动处理 - 在滚动时计算索引然后更新选中项样式
@@ -103,7 +229,7 @@ function PickerGroupBasic(props) {
103
229
  isCenterTimerId.current = null;
104
230
  }
105
231
  const scrollTop = scrollViewRef.current.scrollTop;
106
- const newIndex = getSelectedIndex(scrollTop);
232
+ const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
107
233
  if (newIndex !== currentIndex) {
108
234
  setCurrentIndex(newIndex);
109
235
  }
@@ -143,9 +269,11 @@ function PickerGroupBasic(props) {
143
269
  get children() {
144
270
  return [createComponent(View, {
145
271
  className: "taro-picker__mask"
146
- }), createComponent(View, {
272
+ }), createComponent(View, mergeProps({
147
273
  className: "taro-picker__indicator"
148
- }), createComponent(ScrollView, {
274
+ }, indicatorStyle ? {
275
+ style: indicatorStyle
276
+ } : {})), createComponent(ScrollView, {
149
277
  ref: scrollViewRef,
150
278
  scrollY: true,
151
279
  showScrollbar: false,
@@ -173,30 +301,37 @@ function PickerGroupTime(props) {
173
301
  selectedIndex = 0,
174
302
  colors = {}
175
303
  } = props;
304
+ const indicatorStyle = colors.lineColor ? getIndicatorStyle(colors.lineColor) : null;
176
305
  const [targetScrollTop, setTargetScrollTop] = React.useState(0);
177
306
  const scrollViewRef = React.useRef(null);
178
307
  const itemRefs = React.useRef([]);
179
308
  const [currentIndex, setCurrentIndex] = React.useState(selectedIndex);
180
309
  const [isTouching, setIsTouching] = React.useState(false);
310
+ const lengthScaleRatioRef = React.useRef(1);
311
+ const useMeasuredScaleRef = React.useRef(false);
181
312
  const itemHeightRef = React.useRef(PICKER_LINE_HEIGHT);
313
+ // 初始化时计算 lengthScaleRatio 并判定缩放模式
182
314
  React.useEffect(() => {
183
- var _a;
184
- if (process.env.TARO_PLATFORM !== 'harmony') {
185
- if (scrollViewRef.current && ((_a = scrollViewRef.current) === null || _a === void 0 ? void 0 : _a.scrollHeigh)) {
186
- itemHeightRef.current = scrollViewRef.current.scrollHeight / scrollViewRef.current.childNodes.length;
187
- } else {
188
- console.warn('Height measurement anomaly');
315
+ Taro.getSystemInfo({
316
+ success: res => {
317
+ lengthScaleRatioRef.current = calculateLengthScaleRatio(res);
318
+ useMeasuredScaleRef.current = resolveUseMeasuredScale(res);
319
+ itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
320
+ },
321
+ fail: () => {
322
+ lengthScaleRatioRef.current = 1;
323
+ useMeasuredScaleRef.current = false;
189
324
  }
190
- }
325
+ });
326
+ }, []);
327
+ React.useEffect(() => {
328
+ itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
191
329
  }, [range.length]); // 只在range长度变化时重新计算
192
- const getSelectedIndex = scrollTop => {
193
- return Math.round(scrollTop / itemHeightRef.current);
194
- };
195
330
  // 当selectedIndex变化时,调整滚动位置
196
331
  React.useEffect(() => {
197
332
  if (scrollViewRef.current && range.length > 0 && !isTouching) {
198
333
  const baseValue = selectedIndex * itemHeightRef.current;
199
- setTargetScrollTopWithScale(setTargetScrollTop, baseValue);
334
+ setTargetScrollTopWithScale(setTargetScrollTop, baseValue, undefined, lengthScaleRatioRef.current);
200
335
  setCurrentIndex(selectedIndex);
201
336
  }
202
337
  }, [selectedIndex, range]);
@@ -213,7 +348,7 @@ function PickerGroupTime(props) {
213
348
  isCenterTimerId.current = setTimeout(() => {
214
349
  if (!scrollViewRef.current) return;
215
350
  const scrollTop = scrollViewRef.current.scrollTop;
216
- const newIndex = getSelectedIndex(scrollTop);
351
+ const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
217
352
  setIsTouching(false);
218
353
  // 调用updateIndex执行限位逻辑,获取是否触发了限位
219
354
  const isLimited = Boolean(updateIndex(newIndex, columnId, true));
@@ -221,8 +356,9 @@ function PickerGroupTime(props) {
221
356
  if (!isLimited) {
222
357
  const baseValue = newIndex * itemHeightRef.current;
223
358
  const randomOffset = Math.random() * 0.001;
224
- setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset);
359
+ setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset, lengthScaleRatioRef.current);
225
360
  }
361
+ isCenterTimerId.current = null;
226
362
  }, 100);
227
363
  };
228
364
  // 滚动处理
@@ -233,7 +369,7 @@ function PickerGroupTime(props) {
233
369
  isCenterTimerId.current = null;
234
370
  }
235
371
  const scrollTop = scrollViewRef.current.scrollTop;
236
- const newIndex = getSelectedIndex(scrollTop);
372
+ const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
237
373
  if (newIndex !== currentIndex) {
238
374
  setCurrentIndex(newIndex);
239
375
  }
@@ -273,9 +409,11 @@ function PickerGroupTime(props) {
273
409
  get children() {
274
410
  return [createComponent(View, {
275
411
  className: "taro-picker__mask"
276
- }), createComponent(View, {
412
+ }), createComponent(View, mergeProps({
277
413
  className: "taro-picker__indicator"
278
- }), createComponent(ScrollView, {
414
+ }, indicatorStyle ? {
415
+ style: indicatorStyle
416
+ } : {})), createComponent(ScrollView, {
279
417
  ref: scrollViewRef,
280
418
  scrollY: true,
281
419
  showScrollbar: false,
@@ -302,29 +440,36 @@ function PickerGroupDate(props) {
302
440
  selectedIndex = 0,
303
441
  colors = {}
304
442
  } = props;
443
+ const indicatorStyle = colors.lineColor ? getIndicatorStyle(colors.lineColor) : null;
305
444
  const [targetScrollTop, setTargetScrollTop] = React.useState(0);
306
445
  const scrollViewRef = React.useRef(null);
307
446
  const [currentIndex, setCurrentIndex] = React.useState(selectedIndex);
308
447
  const [isTouching, setIsTouching] = React.useState(false);
448
+ const lengthScaleRatioRef = React.useRef(1);
449
+ const useMeasuredScaleRef = React.useRef(false);
309
450
  const itemHeightRef = React.useRef(PICKER_LINE_HEIGHT);
451
+ // 初始化时计算 lengthScaleRatio 并判定缩放模式
310
452
  React.useEffect(() => {
311
- var _a;
312
- if (process.env.TARO_PLATFORM !== 'harmony') {
313
- if (scrollViewRef.current && ((_a = scrollViewRef.current) === null || _a === void 0 ? void 0 : _a.scrollHeigh)) {
314
- itemHeightRef.current = scrollViewRef.current.scrollHeight / scrollViewRef.current.childNodes.length;
315
- } else {
316
- console.warn('Height measurement anomaly');
453
+ Taro.getSystemInfo({
454
+ success: res => {
455
+ lengthScaleRatioRef.current = calculateLengthScaleRatio(res);
456
+ useMeasuredScaleRef.current = resolveUseMeasuredScale(res);
457
+ itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
458
+ },
459
+ fail: () => {
460
+ lengthScaleRatioRef.current = 1;
461
+ useMeasuredScaleRef.current = false;
317
462
  }
318
- }
463
+ });
464
+ }, []);
465
+ React.useEffect(() => {
466
+ itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
319
467
  }, [range.length]); // 只在range长度变化时重新计算
320
- const getSelectedIndex = scrollTop => {
321
- return Math.round(scrollTop / itemHeightRef.current);
322
- };
323
468
  // 当selectedIndex变化时,调整滚动位置
324
469
  React.useEffect(() => {
325
470
  if (scrollViewRef.current && range.length > 0 && !isTouching) {
326
471
  const baseValue = selectedIndex * itemHeightRef.current;
327
- setTargetScrollTopWithScale(setTargetScrollTop, baseValue);
472
+ setTargetScrollTopWithScale(setTargetScrollTop, baseValue, undefined, lengthScaleRatioRef.current);
328
473
  setCurrentIndex(selectedIndex);
329
474
  }
330
475
  }, [selectedIndex, range]);
@@ -341,11 +486,11 @@ function PickerGroupDate(props) {
341
486
  isCenterTimerId.current = setTimeout(() => {
342
487
  if (!scrollViewRef.current) return;
343
488
  const scrollTop = scrollViewRef.current.scrollTop;
344
- const newIndex = getSelectedIndex(scrollTop);
489
+ const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
345
490
  setIsTouching(false);
346
491
  const baseValue = newIndex * itemHeightRef.current;
347
492
  const randomOffset = Math.random() * 0.001; // 随机数为了在一个项内滚动时强制刷新
348
- setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset);
493
+ setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset, lengthScaleRatioRef.current);
349
494
  // 更新日期值
350
495
  if (updateDay) {
351
496
  // 解析文本中的数字(移除年、月、日等后缀)
@@ -353,6 +498,7 @@ function PickerGroupDate(props) {
353
498
  const numericValue = parseInt(valueText.replace(/[^0-9]/g, ''));
354
499
  updateDay(isNaN(numericValue) ? 0 : numericValue, parseInt(columnId));
355
500
  }
501
+ isCenterTimerId.current = null;
356
502
  }, 100);
357
503
  };
358
504
  // 滚动处理
@@ -363,7 +509,7 @@ function PickerGroupDate(props) {
363
509
  isCenterTimerId.current = null;
364
510
  }
365
511
  const scrollTop = scrollViewRef.current.scrollTop;
366
- const newIndex = getSelectedIndex(scrollTop);
512
+ const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
367
513
  if (newIndex !== currentIndex) {
368
514
  setCurrentIndex(newIndex);
369
515
  }
@@ -401,9 +547,11 @@ function PickerGroupDate(props) {
401
547
  get children() {
402
548
  return [createComponent(View, {
403
549
  className: "taro-picker__mask"
404
- }), createComponent(View, {
550
+ }), createComponent(View, mergeProps({
405
551
  className: "taro-picker__indicator"
406
- }), createComponent(ScrollView, {
552
+ }, indicatorStyle ? {
553
+ style: indicatorStyle
554
+ } : {})), createComponent(ScrollView, {
407
555
  ref: scrollViewRef,
408
556
  scrollY: true,
409
557
  showScrollbar: false,
@@ -432,30 +580,37 @@ function PickerGroupRegion(props) {
432
580
  // 使用selectedIndex参数,默认为0
433
581
  colors = {}
434
582
  } = props;
583
+ const indicatorStyle = colors.lineColor ? getIndicatorStyle(colors.lineColor) : null;
435
584
  const scrollViewRef = React.useRef(null);
436
585
  const [targetScrollTop, setTargetScrollTop] = React.useState(0);
437
586
  const [currentIndex, setCurrentIndex] = React.useState(selectedIndex);
438
587
  const [isTouching, setIsTouching] = React.useState(false);
588
+ const lengthScaleRatioRef = React.useRef(1);
589
+ const useMeasuredScaleRef = React.useRef(false);
439
590
  const itemHeightRef = React.useRef(PICKER_LINE_HEIGHT);
440
591
  const isUserBeginScrollRef = React.useRef(false);
592
+ // 初始化时计算 lengthScaleRatio 并判定缩放模式
441
593
  React.useEffect(() => {
442
- var _a;
443
- if (process.env.TARO_PLATFORM !== 'harmony') {
444
- if (scrollViewRef.current && ((_a = scrollViewRef.current) === null || _a === void 0 ? void 0 : _a.scrollHeigh)) {
445
- itemHeightRef.current = scrollViewRef.current.scrollHeight / scrollViewRef.current.childNodes.length;
446
- } else {
447
- console.warn('Height measurement anomaly');
594
+ Taro.getSystemInfo({
595
+ success: res => {
596
+ lengthScaleRatioRef.current = calculateLengthScaleRatio(res);
597
+ useMeasuredScaleRef.current = resolveUseMeasuredScale(res);
598
+ itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
599
+ },
600
+ fail: () => {
601
+ lengthScaleRatioRef.current = 1;
602
+ useMeasuredScaleRef.current = false;
448
603
  }
449
- }
604
+ });
605
+ }, []);
606
+ React.useEffect(() => {
607
+ itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
450
608
  }, [range.length]); // 只在range长度变化时重新计算
451
- const getSelectedIndex = scrollTop => {
452
- return Math.round(scrollTop / itemHeightRef.current);
453
- };
454
609
  // 当selectedIndex变化时,调整滚动位置
455
610
  React.useEffect(() => {
456
611
  if (scrollViewRef.current && range.length > 0 && !isTouching) {
457
612
  const baseValue = selectedIndex * itemHeightRef.current;
458
- setTargetScrollTopWithScale(setTargetScrollTop, baseValue);
613
+ setTargetScrollTopWithScale(setTargetScrollTop, baseValue, undefined, lengthScaleRatioRef.current);
459
614
  setCurrentIndex(selectedIndex);
460
615
  }
461
616
  }, [selectedIndex, range]);
@@ -471,11 +626,11 @@ function PickerGroupRegion(props) {
471
626
  isCenterTimerId.current = setTimeout(() => {
472
627
  if (!scrollViewRef.current) return;
473
628
  const scrollTop = scrollViewRef.current.scrollTop;
474
- const newIndex = getSelectedIndex(scrollTop);
629
+ const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
475
630
  setIsTouching(false);
476
631
  const baseValue = newIndex * itemHeightRef.current;
477
632
  const randomOffset = Math.random() * 0.001; // 随机数为了在一个项内滚动时强制刷新
478
- setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset);
633
+ setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset, lengthScaleRatioRef.current);
479
634
  updateIndex(newIndex, columnId, false, isUserBeginScrollRef.current);
480
635
  }, 100);
481
636
  };
@@ -487,7 +642,7 @@ function PickerGroupRegion(props) {
487
642
  isCenterTimerId.current = null;
488
643
  }
489
644
  const scrollTop = scrollViewRef.current.scrollTop;
490
- const newIndex = getSelectedIndex(scrollTop);
645
+ const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
491
646
  if (newIndex !== currentIndex) {
492
647
  setCurrentIndex(newIndex);
493
648
  }
@@ -526,9 +681,11 @@ function PickerGroupRegion(props) {
526
681
  get children() {
527
682
  return [createComponent(View, {
528
683
  className: "taro-picker__mask"
529
- }), createComponent(View, {
684
+ }), createComponent(View, mergeProps({
530
685
  className: "taro-picker__indicator"
531
- }), createComponent(ScrollView, {
686
+ }, indicatorStyle ? {
687
+ style: indicatorStyle
688
+ } : {})), createComponent(ScrollView, {
532
689
  ref: scrollViewRef,
533
690
  scrollY: true,
534
691
  showScrollbar: false,