From de620a625ca10af3bcdbbdcc46691271eba79be0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=A8=E6=BA=AA?= <84778445+yuxi-ovo@users.noreply.github.com> Date: Thu, 23 Jul 2026 17:13:04 +0800 Subject: [PATCH 1/5] =?UTF-8?q?fix(swiper):=20=E4=BF=AE=E5=A4=8D=E5=9C=A8?= =?UTF-8?q?=E4=B8=A4=E5=BC=A0=E5=9B=BE=E7=89=87=E4=B8=8B=E7=9A=84=E8=BD=AE?= =?UTF-8?q?=E6=92=AD=E5=88=87=E6=8D=A2=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/components/swiper/swiper.tsx | 35 ++++++++++++--------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/packages/components/swiper/swiper.tsx b/packages/components/swiper/swiper.tsx index 3fe67ef755..50c48551f1 100644 --- a/packages/components/swiper/swiper.tsx +++ b/packages/components/swiper/swiper.tsx @@ -136,32 +136,35 @@ export default defineComponent({ }; const swiperTo = (index: number, context: { source: SwiperChangeSource }) => { - let targetIndex = index % swiperItemLength.value; + const length = swiperItemLength.value; + let targetIndex = ((index % length) + length) % length; navActiveIndex.value = targetIndex; emit('update:current', targetIndex); props.onChange?.(targetIndex, context); isSwitching.value = true; - if (props.animation === 'slide' && swiperItemLength.value > 1 && props.type !== 'card') { + if (props.animation === 'slide' && length > 1 && props.type !== 'card') { targetIndex = index; isBeginToEnd = false; isEndToBegin = false; - if (index >= swiperItemLength.value) { + + // 最后一张点击下一张:进入尾部克隆的第一张 + if (index >= length) { clearTimer(); setTimeout(() => { isEndToBegin = true; currentIndex.value = 0; }, props.duration); } - if (currentIndex.value === 0) { - if (swiperItemLength.value >= 2 && index === swiperItemLength.value - 1) { - targetIndex = -1; - navActiveIndex.value = swiperItemLength.value - 1; - clearTimer(); - setTimeout(() => { - isBeginToEnd = true; - currentIndex.value = swiperItemLength.value - 1; - }, props.duration); - } + + // 第一张点击上一张:进入头部克隆的最后一张 + if (index < 0) { + targetIndex = -1; + navActiveIndex.value = length - 1; + clearTimer(); + setTimeout(() => { + isBeginToEnd = true; + currentIndex.value = length - 1; + }, props.duration); } } currentIndex.value = targetIndex; @@ -221,12 +224,6 @@ export default defineComponent({ }; const goPrevious = (context: { source: SwiperChangeSource }) => { if (isSwitching.value) return; - if (currentIndex.value - 1 < 0) { - if (props.animation === 'slide' && swiperItemLength.value === 2) { - return swiperTo(0, context); - } - return swiperTo(swiperItemLength.value - 1, context); - } return swiperTo(currentIndex.value - 1, context); }; const renderPagination = () => { From 07136a55ce1021d6e76c265c5e59b518b0911854 Mon Sep 17 00:00:00 2001 From: tdesign-bot Date: Thu, 23 Jul 2026 11:26:47 +0000 Subject: [PATCH 2/5] chore: stash changelog [ci skip] --- packages/tdesign-vue-next/.changelog/pr-6830.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 packages/tdesign-vue-next/.changelog/pr-6830.md diff --git a/packages/tdesign-vue-next/.changelog/pr-6830.md b/packages/tdesign-vue-next/.changelog/pr-6830.md new file mode 100644 index 0000000000..8378c25c40 --- /dev/null +++ b/packages/tdesign-vue-next/.changelog/pr-6830.md @@ -0,0 +1,6 @@ +--- +pr_number: 6830 +contributor: yuxi-ovo +--- + +- fix(Swiper): 修复只有两个轮播图内容场景下切换逻辑错误的问题 @yuxi-ovo ([#6830](https://github.com/Tencent/tdesign-vue-next/pull/6830)) From c600d972f5f4ddcfaa6402b3126c2cbcb5b5091e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=A8=E6=BA=AA?= <84778445+yuxi-ovo@users.noreply.github.com> Date: Mon, 27 Jul 2026 15:21:42 +0800 Subject: [PATCH 3/5] feat(color-picker): add native EyeDropper API support --- .../color-picker/color-picker-panel-props.ts | 5 +++ .../color-picker/components/panel/index.tsx | 21 +++++++++ packages/components/color-picker/props.ts | 5 +++ packages/components/color-picker/type.ts | 3 +- .../color-picker/utils/eyedropper.ts | 45 +++++++++++++++++++ 5 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 packages/components/color-picker/utils/eyedropper.ts diff --git a/packages/components/color-picker/color-picker-panel-props.ts b/packages/components/color-picker/color-picker-panel-props.ts index db17d95655..f755e5cbdf 100644 --- a/packages/components/color-picker/color-picker-panel-props.ts +++ b/packages/components/color-picker/color-picker-panel-props.ts @@ -68,6 +68,11 @@ export default { type: String, default: '', }, + /** 是否显示拾色器功能 */ + showEyeDropper: { + type: Boolean, + default: true, + }, /** 选中的色值发生变化时触发,第一个参数 `value` 表示新色值,`context.color` 表示当前调色板控制器的色值,`context.trigger` 表示触发颜色变化的来源 */ onChange: Function as PropType, /** 调色板控制器的值变化时触发,`context.color` 指调色板控制器的值 */ diff --git a/packages/components/color-picker/components/panel/index.tsx b/packages/components/color-picker/components/panel/index.tsx index 9688bab301..30cd40230f 100644 --- a/packages/components/color-picker/components/panel/index.tsx +++ b/packages/components/color-picker/components/panel/index.tsx @@ -9,6 +9,8 @@ import { GradientColorPoint, initColorFormat, TD_COLOR_USED_COLORS_MAX_SIZE, + // PR合并后需要从子包导入 + // getEyeDropper, } from '@tdesign/common-js/color-picker/index'; import { useCommonClassName, useConfig, useDefaultValue, useVModel } from '@tdesign/shared-hooks'; import props from '../../color-picker-panel-props'; @@ -22,6 +24,9 @@ import HueSlider from './hue'; import LinearGradient from './linear-gradient'; import SaturationPanel from './saturation'; import SwatchesPanel from './swatches'; +// PR合并后需要删除这个导入语句 +import { getEyeDropper } from '../../utils/eyedropper'; +import { SipIcon } from 'tdesign-icons-vue-next'; export default defineComponent({ name: 'ColorPanel', @@ -229,6 +234,17 @@ export default defineComponent({ emitColorChange(trigger); }; + const openEyeDropper = async (trigger?: ColorPickerChangeTrigger): Promise => { + const eyeDropper = getEyeDropper(); + + const result = await eyeDropper.open(); + if (!result) { + return; + } + color.value.update(result.sRGBHex); + emitColorChange(trigger); + }; + return () => { const baseProps = { color: color.value, @@ -317,6 +333,11 @@ export default defineComponent({ /> ) : null} + {props.showEyeDropper ? ( +
openEyeDropper('eyedropper')}> + +
+ ) : null} diff --git a/packages/components/color-picker/props.ts b/packages/components/color-picker/props.ts index f0757763bc..aa69d411ca 100644 --- a/packages/components/color-picker/props.ts +++ b/packages/components/color-picker/props.ts @@ -93,6 +93,11 @@ export default { type: String, default: '', }, + /** 是否显示拾色器功能 */ + showEyeDropper: { + type: Boolean, + default: true, + }, /** 选中的色值发生变化时触发,第一个参数 `value` 表示新色值,`context.color` 表示当前调色板控制器的色值,`context.trigger` 表示触发颜色变化的来源 */ onChange: Function as PropType, /** 清空按钮点击时触发 */ diff --git a/packages/components/color-picker/type.ts b/packages/components/color-picker/type.ts index dae9992b4b..986150523d 100644 --- a/packages/components/color-picker/type.ts +++ b/packages/components/color-picker/type.ts @@ -198,7 +198,8 @@ export type ColorPickerChangeTrigger = | 'palette-alpha-bar' | 'input' | 'preset' - | 'recent'; + | 'recent' + | 'eyedropper'; export interface ColorObject { alpha: number; diff --git a/packages/components/color-picker/utils/eyedropper.ts b/packages/components/color-picker/utils/eyedropper.ts new file mode 100644 index 0000000000..8b49b21ffb --- /dev/null +++ b/packages/components/color-picker/utils/eyedropper.ts @@ -0,0 +1,45 @@ +/** + * @see https://developer.mozilla.org/zh-CN/docs/Web/API/EyeDropper + * PR合并后 该文件可以删除 + * */ + +declare global { + interface Window { + EyeDropper?: new () => { + open(options?: EyeDropperOpenOptions): Promise; + }; + } +} + +export interface EyeDropperOpenResult { + sRGBHex: string; +} + +export interface EyeDropperOpenOptions { + signal?: AbortSignal; +} + +export const getEyeDropper = () => { + if (typeof window === 'undefined') return undefined; + + const EyeDropperClass = window.EyeDropper; + if (EyeDropperClass === undefined) { + // 浏览器不支持 EyeDropper 兼容性:https://developer.mozilla.org/zh-CN/docs/Web/API/EyeDropper#%E6%B5%8F%E8%A7%88%E5%99%A8%E5%85%BC%E5%AE%B9%E6%80%A7 + return undefined; + } + + const eyeDropper = new EyeDropperClass(); + const originOpen = eyeDropper.open.bind(eyeDropper); + eyeDropper.open = async (options?: EyeDropperOpenOptions) => { + try { + return await originOpen(options); + } catch (e) { + // 用户取消操作 + if (e instanceof DOMException && e.name === 'AbortError') { + return undefined; + } + throw e; + } + }; + return eyeDropper; +}; From 2b03b7eced027e4644a549a7dbabd9b08c95fcd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=A8=E6=BA=AA?= <84778445+yuxi-ovo@users.noreply.github.com> Date: Mon, 27 Jul 2026 16:15:16 +0800 Subject: [PATCH 4/5] test: update snapshots --- .../color-picker-panel.test.tsx.snap | 136 ++++++++++++++++++ 1 file changed, 136 insertions(+) diff --git a/packages/components/color-picker/__tests__/__snapshots__/color-picker-panel.test.tsx.snap b/packages/components/color-picker/__tests__/__snapshots__/color-picker-panel.test.tsx.snap index 5150da8729..ec4d41c0ae 100644 --- a/packages/components/color-picker/__tests__/__snapshots__/color-picker-panel.test.tsx.snap +++ b/packages/components/color-picker/__tests__/__snapshots__/color-picker-panel.test.tsx.snap @@ -123,6 +123,40 @@ exports[`ColorPickerPanel > :props > :colorModes[monochrome,linear-gradient] 1`] style="background: rgb(0, 31, 151);" /> +
+ + + + + + + +
:props > :colorModes[monochrome,linear-gradient] 2`] class="t-color-picker__sliders-preview-inner" />
+
+ + + + + + + +
:props > :colorModes[monochrome,linear-gradient] 3`] class="t-color-picker__sliders-preview-inner" />
+
+ + + + + + + +
:ui > :mount 1`] = ` style="background: rgb(0, 31, 151);" />
+
+ + + + + + + +
Date: Wed, 29 Jul 2026 10:41:04 +0000 Subject: [PATCH 5/5] chore: update common to PR 2647 --- packages/common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/common b/packages/common index 5aedfdf7ab..4f8e9bfadf 160000 --- a/packages/common +++ b/packages/common @@ -1 +1 @@ -Subproject commit 5aedfdf7ab0457141b0a886d2126e22bbdb42cae +Subproject commit 4f8e9bfadf5aec9c6bd48fde0ee046156d6baac6