@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
@@ -6,27 +6,146 @@ import { jsx, jsxs } from 'react/jsx-runtime';
6
6
  const PICKER_LINE_HEIGHT = 34; // px
7
7
  const PICKER_VISIBLE_ITEMS = 7; // 可见行数
8
8
  const PICKER_BLANK_ITEMS = 3; // 空白行数
9
- // 辅助函数:获取系统信息的 lengthScaleRatio 并设置 targetScrollTop
10
- const setTargetScrollTopWithScale = (setTargetScrollTop, baseValue, randomOffset) => {
11
- Taro.getSystemInfo({
12
- success: res => {
13
- var _a;
14
- // 使用类型断言访问可能不存在的 lengthScaleRatio 属性
15
- const lengthScaleRatio = (_a = res.lengthScaleRatio) !== null && _a !== void 0 ? _a : 1;
16
- if (!res.lengthScaleRatio) {
17
- console.warn('Taro.getSystemInfo: lengthScaleRatio 不存在,使用默认值 1');
18
- }
19
- const scaledValue = baseValue * lengthScaleRatio;
20
- const finalValue = randomOffset !== undefined ? scaledValue + randomOffset : scaledValue;
21
- setTargetScrollTop(finalValue);
22
- },
23
- fail: err => {
24
- console.error('获取系统信息失败:', err);
25
- // 失败时使用默认值 1
26
- const finalValue = randomOffset !== undefined ? baseValue + randomOffset : baseValue;
27
- setTargetScrollTop(finalValue);
9
+ const getIndicatorStyle = lineColor => {
10
+ return {
11
+ borderTopColor: lineColor,
12
+ borderBottomColor: lineColor
13
+ };
14
+ };
15
+ // 大屏方案版本要求
16
+ const MIN_DESIGN_APP_VERSION = 16;
17
+ const MIN_APP_VERSION = '15.7.0';
18
+ // semver 版本比较
19
+ const isAppVersionAtLeast = (version, min) => {
20
+ var _a, _b;
21
+ if (!version || typeof version !== 'string') return false;
22
+ const parts = v => {
23
+ const m = String(v).trim().match(/^(\d+)(?:\.(\d+))?(?:\.(\d+))?/);
24
+ if (!m) return [];
25
+ return [parseInt(m[1], 10) || 0, parseInt(m[2] || '0', 10) || 0, parseInt(m[3] || '0', 10) || 0];
26
+ };
27
+ const a = parts(version);
28
+ const b = parts(min);
29
+ if (a.length === 0) return false;
30
+ if (b.length === 0) return true;
31
+ for (let i = 0; i < Math.max(a.length, b.length); i++) {
32
+ const da = (_a = a[i]) !== null && _a !== void 0 ? _a : 0;
33
+ const db = (_b = b[i]) !== null && _b !== void 0 ? _b : 0;
34
+ if (da > db) return true;
35
+ if (da < db) return false;
36
+ }
37
+ return true;
38
+ };
39
+ // 读取 JDMobileConfig,异常时返回 undefined
40
+ const tryGetMobileConfigSync = opt => {
41
+ var _a;
42
+ try {
43
+ const fn = (_a = Taro.JDMobileConfig) === null || _a === void 0 ? void 0 : _a.getMobileConfigSync;
44
+ if (typeof fn !== 'function') return undefined;
45
+ return fn(opt);
46
+ } catch (_b) {
47
+ return undefined;
48
+ }
49
+ };
50
+ // 判断是否启用测量值缩放适配(true=启用, false=使用系统侧缩放)
51
+ const resolveUseMeasuredScale = res => {
52
+ // H5/weapp 不参与大屏系数
53
+ if (process.env.TARO_ENV === 'h5' || process.env.TARO_ENV === 'weapp') {
54
+ return false;
55
+ }
56
+ // 条件1: designAppVersion < 16,不满足则使用系统侧缩放
57
+ const designAppVersionRaw = res.designAppVersion;
58
+ const designAppVersionMajor = designAppVersionRaw != null ? parseInt(String(designAppVersionRaw).trim(), 10) : Number.NaN;
59
+ if (!Number.isFinite(designAppVersionMajor) || designAppVersionMajor < MIN_DESIGN_APP_VERSION) {
60
+ return false;
61
+ }
62
+ // 条件2: appVersion < 15.7.0,不满足则使用系统侧缩放
63
+ if (!isAppVersionAtLeast(res.version, MIN_APP_VERSION)) {
64
+ return false;
65
+ }
66
+ // 条件3: 平台判断
67
+ const platform = String(res.platform || '').toLowerCase();
68
+ if (platform === 'harmony') {
69
+ return true;
70
+ }
71
+ if (platform === 'android') {
72
+ const raw = tryGetMobileConfigSync({
73
+ space: 'taro',
74
+ configName: 'config',
75
+ key: 'disableFixBoundingScaleRatio'
76
+ });
77
+ return raw !== 1 && raw !== '1';
78
+ }
79
+ if (platform === 'ios') {
80
+ const raw = tryGetMobileConfigSync({
81
+ space: 'Taro',
82
+ configName: 'excutor',
83
+ key: 'disableBoundingScaleRatio'
84
+ });
85
+ return raw !== 1 && raw !== '1';
86
+ }
87
+ return false;
88
+ };
89
+ // 辅助函数:计算 lengthScaleRatio
90
+ const calculateLengthScaleRatio = res => {
91
+ let lengthScaleRatio = res === null || res === void 0 ? void 0 : res.lengthScaleRatio;
92
+ if (lengthScaleRatio == null || lengthScaleRatio === 0) {
93
+ console.warn('Taro.getSystemInfo: lengthScaleRatio 不存在,使用计算值');
94
+ lengthScaleRatio = 1;
95
+ if (res.windowWidth < 320) {
96
+ lengthScaleRatio = res.windowWidth / 320;
97
+ } else if (res.windowWidth >= 400 && res.windowWidth < 600) {
98
+ lengthScaleRatio = res.windowWidth / 400;
28
99
  }
29
- });
100
+ const shortSide = res.windowWidth < res.windowHeight ? res.windowWidth : res.windowHeight;
101
+ const isBigScreen = shortSide >= 600;
102
+ if (isBigScreen) {
103
+ lengthScaleRatio = shortSide / 720;
104
+ }
105
+ }
106
+ return lengthScaleRatio;
107
+ };
108
+ // 辅助函数:获取系统信息的 lengthScaleRatio 并设置 targetScrollTop
109
+ const setTargetScrollTopWithScale = function (setTargetScrollTop, baseValue, randomOffset) {
110
+ let lengthScaleRatio = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1;
111
+ // H5 和 weapp 不参与放大计算,直接使用 baseValue
112
+ if (process.env.TARO_ENV === 'h5' || process.env.TARO_ENV === 'weapp') {
113
+ const finalValue = randomOffset !== undefined ? baseValue + randomOffset : baseValue;
114
+ setTargetScrollTop(finalValue);
115
+ return;
116
+ }
117
+ if (process.env.TARO_PLATFORM === 'harmony') {
118
+ const scaledValue = baseValue;
119
+ const finalValue = randomOffset !== undefined ? scaledValue + randomOffset : scaledValue;
120
+ setTargetScrollTop(finalValue);
121
+ } else {
122
+ const scaledValue = baseValue * lengthScaleRatio;
123
+ const finalValue = randomOffset !== undefined ? scaledValue + randomOffset : scaledValue;
124
+ setTargetScrollTop(finalValue);
125
+ }
126
+ };
127
+ // 根据 scrollTop 计算选中索引
128
+ // 系统侧缩放模式:scrollHeight 已被系统缩放,直接相除即可
129
+ // 自行缩放模式:需要除以 ratio 换算(harmony 特殊处理,ratio 已内嵌在 itemHeight 中)
130
+ const getSelectedIndex = function (scrollTop, itemHeight) {
131
+ let lengthScaleRatio = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
132
+ let useMeasuredScale = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
133
+ if (!useMeasuredScale || process.env.TARO_PLATFORM === 'harmony') {
134
+ return Math.round(scrollTop / itemHeight);
135
+ }
136
+ return Math.round(scrollTop / lengthScaleRatio / itemHeight);
137
+ };
138
+ // 计算单项高度(返回设计稿值)
139
+ const calculateItemHeight = function (scrollView, lengthScaleRatio) {
140
+ let useMeasuredScale = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
141
+ if (process.env.TARO_PLATFORM === 'harmony') {
142
+ return useMeasuredScale ? PICKER_LINE_HEIGHT * lengthScaleRatio : PICKER_LINE_HEIGHT;
143
+ }
144
+ if (scrollView && (scrollView === null || scrollView === void 0 ? void 0 : scrollView.scrollHeight)) {
145
+ return useMeasuredScale ? scrollView.scrollHeight / lengthScaleRatio / scrollView.childNodes.length : scrollView.scrollHeight / scrollView.childNodes.length;
146
+ }
147
+ console.warn('Height measurement anomaly');
148
+ return PICKER_LINE_HEIGHT;
30
149
  };
31
150
  function PickerGroupBasic(props) {
32
151
  const {
@@ -39,6 +158,7 @@ function PickerGroupBasic(props) {
39
158
  // 使用selectedIndex参数,默认为0
40
159
  colors = {}
41
160
  } = props;
161
+ const indicatorStyle = colors.lineColor ? getIndicatorStyle(colors.lineColor) : null;
42
162
  const [targetScrollTop, setTargetScrollTop] = React.useState(0);
43
163
  const scrollViewRef = React.useRef(null);
44
164
  const itemRefs = React.useRef([]);
@@ -46,26 +166,31 @@ function PickerGroupBasic(props) {
46
166
  const [currentIndex, setCurrentIndex] = React.useState(selectedIndex);
47
167
  // 触摸状态用于优化用户体验
48
168
  const [isTouching, setIsTouching] = React.useState(false);
169
+ const lengthScaleRatioRef = React.useRef(1);
170
+ const useMeasuredScaleRef = React.useRef(false);
49
171
  const itemHeightRef = React.useRef(PICKER_LINE_HEIGHT);
172
+ // 初始化时计算 lengthScaleRatio 并判定缩放模式
50
173
  React.useEffect(() => {
51
- var _a;
52
- if (process.env.TARO_PLATFORM !== 'harmony') {
53
- if (scrollViewRef.current && ((_a = scrollViewRef.current) === null || _a === void 0 ? void 0 : _a.scrollHeigh)) {
54
- itemHeightRef.current = scrollViewRef.current.scrollHeight / scrollViewRef.current.childNodes.length;
55
- } else {
56
- console.warn('Height measurement anomaly');
174
+ Taro.getSystemInfo({
175
+ success: res => {
176
+ lengthScaleRatioRef.current = calculateLengthScaleRatio(res);
177
+ useMeasuredScaleRef.current = resolveUseMeasuredScale(res);
178
+ itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
179
+ },
180
+ fail: () => {
181
+ lengthScaleRatioRef.current = 1;
182
+ useMeasuredScaleRef.current = false;
57
183
  }
58
- }
184
+ });
185
+ }, []);
186
+ React.useEffect(() => {
187
+ itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
59
188
  }, [range.length]); // 只在range长度变化时重新计算
60
- // 获取选中的索引
61
- const getSelectedIndex = scrollTop => {
62
- return Math.round(scrollTop / itemHeightRef.current);
63
- };
64
189
  // 当selectedIndex变化时,调整滚动位置
65
190
  React.useEffect(() => {
66
191
  if (scrollViewRef.current && range.length > 0 && !isTouching) {
67
192
  const baseValue = selectedIndex * itemHeightRef.current;
68
- setTargetScrollTopWithScale(setTargetScrollTop, baseValue);
193
+ setTargetScrollTopWithScale(setTargetScrollTop, baseValue, undefined, lengthScaleRatioRef.current);
69
194
  setCurrentIndex(selectedIndex);
70
195
  }
71
196
  }, [selectedIndex, range]);
@@ -82,16 +207,17 @@ function PickerGroupBasic(props) {
82
207
  isCenterTimerId.current = setTimeout(() => {
83
208
  if (!scrollViewRef.current) return;
84
209
  const scrollTop = scrollViewRef.current.scrollTop;
85
- const newIndex = getSelectedIndex(scrollTop);
210
+ const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
86
211
  setIsTouching(false);
87
212
  const baseValue = newIndex * itemHeightRef.current;
88
213
  const randomOffset = Math.random() * 0.001; // 随机数为了在一个项内滚动时强制刷新
89
- setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset);
214
+ setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset, lengthScaleRatioRef.current);
90
215
  updateIndex(newIndex, columnId);
91
216
  onColumnChange === null || onColumnChange === void 0 ? void 0 : onColumnChange({
92
217
  columnId,
93
218
  index: newIndex
94
219
  });
220
+ isCenterTimerId.current = null;
95
221
  }, 100);
96
222
  };
97
223
  // 滚动处理 - 在滚动时计算索引然后更新选中项样式
@@ -102,7 +228,7 @@ function PickerGroupBasic(props) {
102
228
  isCenterTimerId.current = null;
103
229
  }
104
230
  const scrollTop = scrollViewRef.current.scrollTop;
105
- const newIndex = getSelectedIndex(scrollTop);
231
+ const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
106
232
  if (newIndex !== currentIndex) {
107
233
  setCurrentIndex(newIndex);
108
234
  }
@@ -137,7 +263,10 @@ function PickerGroupBasic(props) {
137
263
  children: [/*#__PURE__*/jsx(View, {
138
264
  className: "taro-picker__mask"
139
265
  }), /*#__PURE__*/jsx(View, {
140
- className: "taro-picker__indicator"
266
+ className: "taro-picker__indicator",
267
+ ...(indicatorStyle ? {
268
+ style: indicatorStyle
269
+ } : {})
141
270
  }), /*#__PURE__*/jsx(ScrollView, {
142
271
  ref: scrollViewRef,
143
272
  scrollY: true,
@@ -165,30 +294,37 @@ function PickerGroupTime(props) {
165
294
  selectedIndex = 0,
166
295
  colors = {}
167
296
  } = props;
297
+ const indicatorStyle = colors.lineColor ? getIndicatorStyle(colors.lineColor) : null;
168
298
  const [targetScrollTop, setTargetScrollTop] = React.useState(0);
169
299
  const scrollViewRef = React.useRef(null);
170
300
  const itemRefs = React.useRef([]);
171
301
  const [currentIndex, setCurrentIndex] = React.useState(selectedIndex);
172
302
  const [isTouching, setIsTouching] = React.useState(false);
303
+ const lengthScaleRatioRef = React.useRef(1);
304
+ const useMeasuredScaleRef = React.useRef(false);
173
305
  const itemHeightRef = React.useRef(PICKER_LINE_HEIGHT);
306
+ // 初始化时计算 lengthScaleRatio 并判定缩放模式
174
307
  React.useEffect(() => {
175
- var _a;
176
- if (process.env.TARO_PLATFORM !== 'harmony') {
177
- if (scrollViewRef.current && ((_a = scrollViewRef.current) === null || _a === void 0 ? void 0 : _a.scrollHeigh)) {
178
- itemHeightRef.current = scrollViewRef.current.scrollHeight / scrollViewRef.current.childNodes.length;
179
- } else {
180
- console.warn('Height measurement anomaly');
308
+ Taro.getSystemInfo({
309
+ success: res => {
310
+ lengthScaleRatioRef.current = calculateLengthScaleRatio(res);
311
+ useMeasuredScaleRef.current = resolveUseMeasuredScale(res);
312
+ itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
313
+ },
314
+ fail: () => {
315
+ lengthScaleRatioRef.current = 1;
316
+ useMeasuredScaleRef.current = false;
181
317
  }
182
- }
318
+ });
319
+ }, []);
320
+ React.useEffect(() => {
321
+ itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
183
322
  }, [range.length]); // 只在range长度变化时重新计算
184
- const getSelectedIndex = scrollTop => {
185
- return Math.round(scrollTop / itemHeightRef.current);
186
- };
187
323
  // 当selectedIndex变化时,调整滚动位置
188
324
  React.useEffect(() => {
189
325
  if (scrollViewRef.current && range.length > 0 && !isTouching) {
190
326
  const baseValue = selectedIndex * itemHeightRef.current;
191
- setTargetScrollTopWithScale(setTargetScrollTop, baseValue);
327
+ setTargetScrollTopWithScale(setTargetScrollTop, baseValue, undefined, lengthScaleRatioRef.current);
192
328
  setCurrentIndex(selectedIndex);
193
329
  }
194
330
  }, [selectedIndex, range]);
@@ -205,7 +341,7 @@ function PickerGroupTime(props) {
205
341
  isCenterTimerId.current = setTimeout(() => {
206
342
  if (!scrollViewRef.current) return;
207
343
  const scrollTop = scrollViewRef.current.scrollTop;
208
- const newIndex = getSelectedIndex(scrollTop);
344
+ const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
209
345
  setIsTouching(false);
210
346
  // 调用updateIndex执行限位逻辑,获取是否触发了限位
211
347
  const isLimited = Boolean(updateIndex(newIndex, columnId, true));
@@ -213,8 +349,9 @@ function PickerGroupTime(props) {
213
349
  if (!isLimited) {
214
350
  const baseValue = newIndex * itemHeightRef.current;
215
351
  const randomOffset = Math.random() * 0.001;
216
- setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset);
352
+ setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset, lengthScaleRatioRef.current);
217
353
  }
354
+ isCenterTimerId.current = null;
218
355
  }, 100);
219
356
  };
220
357
  // 滚动处理
@@ -225,7 +362,7 @@ function PickerGroupTime(props) {
225
362
  isCenterTimerId.current = null;
226
363
  }
227
364
  const scrollTop = scrollViewRef.current.scrollTop;
228
- const newIndex = getSelectedIndex(scrollTop);
365
+ const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
229
366
  if (newIndex !== currentIndex) {
230
367
  setCurrentIndex(newIndex);
231
368
  }
@@ -260,7 +397,10 @@ function PickerGroupTime(props) {
260
397
  children: [/*#__PURE__*/jsx(View, {
261
398
  className: "taro-picker__mask"
262
399
  }), /*#__PURE__*/jsx(View, {
263
- className: "taro-picker__indicator"
400
+ className: "taro-picker__indicator",
401
+ ...(indicatorStyle ? {
402
+ style: indicatorStyle
403
+ } : {})
264
404
  }), /*#__PURE__*/jsx(ScrollView, {
265
405
  ref: scrollViewRef,
266
406
  scrollY: true,
@@ -287,29 +427,36 @@ function PickerGroupDate(props) {
287
427
  selectedIndex = 0,
288
428
  colors = {}
289
429
  } = props;
430
+ const indicatorStyle = colors.lineColor ? getIndicatorStyle(colors.lineColor) : null;
290
431
  const [targetScrollTop, setTargetScrollTop] = React.useState(0);
291
432
  const scrollViewRef = React.useRef(null);
292
433
  const [currentIndex, setCurrentIndex] = React.useState(selectedIndex);
293
434
  const [isTouching, setIsTouching] = React.useState(false);
435
+ const lengthScaleRatioRef = React.useRef(1);
436
+ const useMeasuredScaleRef = React.useRef(false);
294
437
  const itemHeightRef = React.useRef(PICKER_LINE_HEIGHT);
438
+ // 初始化时计算 lengthScaleRatio 并判定缩放模式
295
439
  React.useEffect(() => {
296
- var _a;
297
- if (process.env.TARO_PLATFORM !== 'harmony') {
298
- if (scrollViewRef.current && ((_a = scrollViewRef.current) === null || _a === void 0 ? void 0 : _a.scrollHeigh)) {
299
- itemHeightRef.current = scrollViewRef.current.scrollHeight / scrollViewRef.current.childNodes.length;
300
- } else {
301
- console.warn('Height measurement anomaly');
440
+ Taro.getSystemInfo({
441
+ success: res => {
442
+ lengthScaleRatioRef.current = calculateLengthScaleRatio(res);
443
+ useMeasuredScaleRef.current = resolveUseMeasuredScale(res);
444
+ itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
445
+ },
446
+ fail: () => {
447
+ lengthScaleRatioRef.current = 1;
448
+ useMeasuredScaleRef.current = false;
302
449
  }
303
- }
450
+ });
451
+ }, []);
452
+ React.useEffect(() => {
453
+ itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
304
454
  }, [range.length]); // 只在range长度变化时重新计算
305
- const getSelectedIndex = scrollTop => {
306
- return Math.round(scrollTop / itemHeightRef.current);
307
- };
308
455
  // 当selectedIndex变化时,调整滚动位置
309
456
  React.useEffect(() => {
310
457
  if (scrollViewRef.current && range.length > 0 && !isTouching) {
311
458
  const baseValue = selectedIndex * itemHeightRef.current;
312
- setTargetScrollTopWithScale(setTargetScrollTop, baseValue);
459
+ setTargetScrollTopWithScale(setTargetScrollTop, baseValue, undefined, lengthScaleRatioRef.current);
313
460
  setCurrentIndex(selectedIndex);
314
461
  }
315
462
  }, [selectedIndex, range]);
@@ -326,11 +473,11 @@ function PickerGroupDate(props) {
326
473
  isCenterTimerId.current = setTimeout(() => {
327
474
  if (!scrollViewRef.current) return;
328
475
  const scrollTop = scrollViewRef.current.scrollTop;
329
- const newIndex = getSelectedIndex(scrollTop);
476
+ const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
330
477
  setIsTouching(false);
331
478
  const baseValue = newIndex * itemHeightRef.current;
332
479
  const randomOffset = Math.random() * 0.001; // 随机数为了在一个项内滚动时强制刷新
333
- setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset);
480
+ setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset, lengthScaleRatioRef.current);
334
481
  // 更新日期值
335
482
  if (updateDay) {
336
483
  // 解析文本中的数字(移除年、月、日等后缀)
@@ -338,6 +485,7 @@ function PickerGroupDate(props) {
338
485
  const numericValue = parseInt(valueText.replace(/[^0-9]/g, ''));
339
486
  updateDay(isNaN(numericValue) ? 0 : numericValue, parseInt(columnId));
340
487
  }
488
+ isCenterTimerId.current = null;
341
489
  }, 100);
342
490
  };
343
491
  // 滚动处理
@@ -348,7 +496,7 @@ function PickerGroupDate(props) {
348
496
  isCenterTimerId.current = null;
349
497
  }
350
498
  const scrollTop = scrollViewRef.current.scrollTop;
351
- const newIndex = getSelectedIndex(scrollTop);
499
+ const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
352
500
  if (newIndex !== currentIndex) {
353
501
  setCurrentIndex(newIndex);
354
502
  }
@@ -381,7 +529,10 @@ function PickerGroupDate(props) {
381
529
  children: [/*#__PURE__*/jsx(View, {
382
530
  className: "taro-picker__mask"
383
531
  }), /*#__PURE__*/jsx(View, {
384
- className: "taro-picker__indicator"
532
+ className: "taro-picker__indicator",
533
+ ...(indicatorStyle ? {
534
+ style: indicatorStyle
535
+ } : {})
385
536
  }), /*#__PURE__*/jsx(ScrollView, {
386
537
  ref: scrollViewRef,
387
538
  scrollY: true,
@@ -410,30 +561,37 @@ function PickerGroupRegion(props) {
410
561
  // 使用selectedIndex参数,默认为0
411
562
  colors = {}
412
563
  } = props;
564
+ const indicatorStyle = colors.lineColor ? getIndicatorStyle(colors.lineColor) : null;
413
565
  const scrollViewRef = React.useRef(null);
414
566
  const [targetScrollTop, setTargetScrollTop] = React.useState(0);
415
567
  const [currentIndex, setCurrentIndex] = React.useState(selectedIndex);
416
568
  const [isTouching, setIsTouching] = React.useState(false);
569
+ const lengthScaleRatioRef = React.useRef(1);
570
+ const useMeasuredScaleRef = React.useRef(false);
417
571
  const itemHeightRef = React.useRef(PICKER_LINE_HEIGHT);
418
572
  const isUserBeginScrollRef = React.useRef(false);
573
+ // 初始化时计算 lengthScaleRatio 并判定缩放模式
419
574
  React.useEffect(() => {
420
- var _a;
421
- if (process.env.TARO_PLATFORM !== 'harmony') {
422
- if (scrollViewRef.current && ((_a = scrollViewRef.current) === null || _a === void 0 ? void 0 : _a.scrollHeigh)) {
423
- itemHeightRef.current = scrollViewRef.current.scrollHeight / scrollViewRef.current.childNodes.length;
424
- } else {
425
- console.warn('Height measurement anomaly');
575
+ Taro.getSystemInfo({
576
+ success: res => {
577
+ lengthScaleRatioRef.current = calculateLengthScaleRatio(res);
578
+ useMeasuredScaleRef.current = resolveUseMeasuredScale(res);
579
+ itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
580
+ },
581
+ fail: () => {
582
+ lengthScaleRatioRef.current = 1;
583
+ useMeasuredScaleRef.current = false;
426
584
  }
427
- }
585
+ });
586
+ }, []);
587
+ React.useEffect(() => {
588
+ itemHeightRef.current = calculateItemHeight(scrollViewRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
428
589
  }, [range.length]); // 只在range长度变化时重新计算
429
- const getSelectedIndex = scrollTop => {
430
- return Math.round(scrollTop / itemHeightRef.current);
431
- };
432
590
  // 当selectedIndex变化时,调整滚动位置
433
591
  React.useEffect(() => {
434
592
  if (scrollViewRef.current && range.length > 0 && !isTouching) {
435
593
  const baseValue = selectedIndex * itemHeightRef.current;
436
- setTargetScrollTopWithScale(setTargetScrollTop, baseValue);
594
+ setTargetScrollTopWithScale(setTargetScrollTop, baseValue, undefined, lengthScaleRatioRef.current);
437
595
  setCurrentIndex(selectedIndex);
438
596
  }
439
597
  }, [selectedIndex, range]);
@@ -449,11 +607,11 @@ function PickerGroupRegion(props) {
449
607
  isCenterTimerId.current = setTimeout(() => {
450
608
  if (!scrollViewRef.current) return;
451
609
  const scrollTop = scrollViewRef.current.scrollTop;
452
- const newIndex = getSelectedIndex(scrollTop);
610
+ const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
453
611
  setIsTouching(false);
454
612
  const baseValue = newIndex * itemHeightRef.current;
455
613
  const randomOffset = Math.random() * 0.001; // 随机数为了在一个项内滚动时强制刷新
456
- setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset);
614
+ setTargetScrollTopWithScale(setTargetScrollTop, baseValue, randomOffset, lengthScaleRatioRef.current);
457
615
  updateIndex(newIndex, columnId, false, isUserBeginScrollRef.current);
458
616
  }, 100);
459
617
  };
@@ -465,7 +623,7 @@ function PickerGroupRegion(props) {
465
623
  isCenterTimerId.current = null;
466
624
  }
467
625
  const scrollTop = scrollViewRef.current.scrollTop;
468
- const newIndex = getSelectedIndex(scrollTop);
626
+ const newIndex = getSelectedIndex(scrollTop, itemHeightRef.current, lengthScaleRatioRef.current, useMeasuredScaleRef.current);
469
627
  if (newIndex !== currentIndex) {
470
628
  setCurrentIndex(newIndex);
471
629
  }
@@ -499,7 +657,10 @@ function PickerGroupRegion(props) {
499
657
  children: [/*#__PURE__*/jsx(View, {
500
658
  className: "taro-picker__mask"
501
659
  }), /*#__PURE__*/jsx(View, {
502
- className: "taro-picker__indicator"
660
+ className: "taro-picker__indicator",
661
+ ...(indicatorStyle ? {
662
+ style: indicatorStyle
663
+ } : {})
503
664
  }), /*#__PURE__*/jsx(ScrollView, {
504
665
  ref: scrollViewRef,
505
666
  scrollY: true,