diff --git a/packages/components/calendar/calendar.ts b/packages/components/calendar/calendar.ts index 31fb5ed82..28abdfa20 100644 --- a/packages/components/calendar/calendar.ts +++ b/packages/components/calendar/calendar.ts @@ -167,14 +167,16 @@ export default class Calendar extends SuperComponent { updateActionButton(value: Date) { const _min = this.getCurrentYearAndMonth(this.base.minDate); const _max = this.getCurrentYearAndMonth(this.base.maxDate); + const _value = this.getCurrentYearAndMonth(value); const _minTimestamp = new Date(_min.year, _min.month, 1).getTime(); const _maxTimestamp = new Date(_max.year, _max.month, 1).getTime(); + const _dateValue = new Date(_value.year, _value.month, 1); - const _prevYearTimestamp = getPrevYear(value).getTime(); - const _prevMonthTimestamp = getPrevMonth(value).getTime(); - const _nextMonthTimestamp = getNextMonth(value).getTime(); - const _nextYearTimestamp = getNextYear(value).getTime(); + const _prevYearTimestamp = getPrevYear(_dateValue).getTime(); + const _prevMonthTimestamp = getPrevMonth(_dateValue).getTime(); + const _nextMonthTimestamp = getNextMonth(_dateValue).getTime(); + const _nextYearTimestamp = getNextYear(_dateValue).getTime(); const preYearBtnDisable = _prevYearTimestamp < _minTimestamp || _prevMonthTimestamp < _minTimestamp; const prevMonthBtnDisable = _prevMonthTimestamp < _minTimestamp; diff --git a/packages/components/calendar/utils.ts b/packages/components/calendar/utils.ts index 431d65ced..be804f076 100644 --- a/packages/components/calendar/utils.ts +++ b/packages/components/calendar/utils.ts @@ -1,14 +1,12 @@ export function getMonthByOffset(date: Date, offset: number) { const _date = new Date(date); _date.setMonth(_date.getMonth() + offset); - _date.setDate(1); return _date; } export function getYearByOffset(date: Date, offset: number) { const _date = new Date(date); _date.setFullYear(_date.getFullYear() + offset); - _date.setDate(1); return _date; } diff --git a/packages/components/drawer/README.en-US.md b/packages/components/drawer/README.en-US.md index acd5f1bcf..b47489897 100644 --- a/packages/components/drawer/README.en-US.md +++ b/packages/components/drawer/README.en-US.md @@ -10,15 +10,23 @@ style | Object | - | CSS(Cascading Style Sheets) | N custom-style | Object | - | CSS(Cascading Style Sheets),used to set style on virtual component | N close-on-overlay-click | Boolean | true | \- | N destroy-on-close | Boolean | false | \- | N -footer | Slot | - | `0.29.0`。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/components/common/common.ts) | N + items | Array | - | Typescript:`DrawerItem[]` `interface DrawerItem { title: string; icon: string; }`。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/components/drawer/type.ts) | N +overlay-props | Object | {} | Typescript:`OverlayProps`,[Overlay API Documents](./overlay?tab=api)。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/components/drawer/type.ts) | N placement | String | right | options: left/right | N show-overlay | Boolean | true | \- | N -title | String / Slot | - | `0.29.0`。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/components/common/common.ts) | N +title | String | - | `0.29.0` | N using-custom-navbar | Boolean | false | \- | N visible | Boolean | false | \- | N z-index | Number | 11500 | \- | N +### Drawer Slots + +name | Description +-- | -- +footer | `0.29.0` +title | `0.29.0` + ### Drawer Events name | params | description diff --git a/packages/components/drawer/README.md b/packages/components/drawer/README.md index f146a2f20..470cfe06e 100644 --- a/packages/components/drawer/README.md +++ b/packages/components/drawer/README.md @@ -53,15 +53,23 @@ style | Object | - | 样式 | N custom-style | Object | - | 样式,一般用于开启虚拟化组件节点场景 | N close-on-overlay-click | Boolean | true | 点击蒙层时是否触发抽屉关闭事件 | N destroy-on-close | Boolean | false | 抽屉关闭时是否销毁节点 | N -footer | Slot | - | `0.29.0`。抽屉的底部。[通用类型定义](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/components/common/common.ts) | N + items | Array | - | 抽屉里的列表项。TS 类型:`DrawerItem[]` `interface DrawerItem { title: string; icon: string; }`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/components/drawer/type.ts) | N +overlay-props | Object | {} | 遮罩层的属性,透传至 overlay。TS 类型:`OverlayProps`,[Overlay API Documents](./overlay?tab=api)。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/components/drawer/type.ts) | N placement | String | right | 抽屉方向。可选项:left/right | N show-overlay | Boolean | true | 是否显示遮罩层 | N -title | String / Slot | - | `0.29.0`。抽屉的标题。[通用类型定义](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/components/common/common.ts) | N +title | String | - | `0.29.0`。抽屉的标题 | N using-custom-navbar | Boolean | false | 是否使用了自定义导航栏 | N visible | Boolean | false | 组件是否可见 | N z-index | Number | 11500 | 抽屉层级,样式默认为 11500 | N +### Drawer Slots + +名称 | 描述 +-- | -- +footer | `0.29.0`。抽屉的底部 +title | `0.29.0`。抽屉的标题 + ### Drawer Events 名称 | 参数 | 描述 diff --git a/packages/components/drawer/drawer.ts b/packages/components/drawer/drawer.ts index d702f0226..24c720614 100644 --- a/packages/components/drawer/drawer.ts +++ b/packages/components/drawer/drawer.ts @@ -24,7 +24,7 @@ export default class Drawer extends SuperComponent { methods = { // closeOnOverlayClick为true时才能触发popup的visible-change事件 - visibleChange({ detail }) { + onVisibleChange({ detail }) { const { visible } = detail; const { showOverlay } = this.data; @@ -41,7 +41,7 @@ export default class Drawer extends SuperComponent { } }, - itemClick(detail) { + onItemClick(detail) { const { index, item } = detail.currentTarget.dataset; this.triggerEvent('item-click', { index, item }); diff --git a/packages/components/drawer/drawer.wxml b/packages/components/drawer/drawer.wxml index a7ff8ac21..da2e75c0e 100644 --- a/packages/components/drawer/drawer.wxml +++ b/packages/components/drawer/drawer.wxml @@ -4,13 +4,14 @@ wx:if="{{!destroyOnClose || visible}}" style="{{_._style([style, customStyle])}}" class="class" - bind:visible-change="visibleChange" visible="{{visible}}" - zIndex="{{zIndex}}" - usingCustomNavbar="{{usingCustomNavbar}}" + z-index="{{zIndex}}" + using-custom-navbar="{{usingCustomNavbar}}" placement="{{placement == 'right' ? 'right' : 'left'}}" - showOverlay="{{showOverlay}}" - closeOnOverlayClick="{{closeOnOverlayClick}}" + show-overlay="{{showOverlay}}" + overlay-props="{{overlayProps}}" + close-on-click-overlay="{{closeOnOverlayClick}}" + bind:visible-change="onVisibleChange" > @@ -26,9 +27,9 @@ wx:key="index" data-item="{{item}}" data-index="{{index}}" - bindtap="itemClick" aria-role="{{ ariaRole || 'button' }}" aria-label="{{item.title}}" + bindtap="onItemClick" > diff --git a/packages/components/drawer/props.ts b/packages/components/drawer/props.ts index 5932ffdc7..2301b86ce 100644 --- a/packages/components/drawer/props.ts +++ b/packages/components/drawer/props.ts @@ -20,6 +20,11 @@ const props: TdDrawerProps = { items: { type: Array, }, + /** 遮罩层的属性,透传至 overlay */ + overlayProps: { + type: Object, + value: {}, + }, /** 抽屉方向 */ placement: { type: String, diff --git a/packages/components/drawer/type.ts b/packages/components/drawer/type.ts index 18a201399..5c8b2c3c7 100644 --- a/packages/components/drawer/type.ts +++ b/packages/components/drawer/type.ts @@ -4,6 +4,8 @@ * 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC * */ +import { OverlayProps } from '../overlay/index'; + export interface TdDrawerProps { /** * 点击蒙层时是否触发抽屉关闭事件 @@ -28,6 +30,14 @@ export interface TdDrawerProps { type: ArrayConstructor; value?: DrawerItem[]; }; + /** + * 遮罩层的属性,透传至 overlay + * @default {} + */ + overlayProps?: { + type: ObjectConstructor; + value?: OverlayProps; + }; /** * 抽屉方向 * @default right diff --git a/packages/components/dropdown-menu/README.en-US.md b/packages/components/dropdown-menu/README.en-US.md index 8d6fb8a0e..84a5fcf7b 100644 --- a/packages/components/dropdown-menu/README.en-US.md +++ b/packages/components/dropdown-menu/README.en-US.md @@ -83,7 +83,6 @@ Name | Default Value | Description --td-dropdown-menu-height | 96rpx | - --td-dropdown-menu-icon-size | 40rpx | - --td-dropdown-body-max-height | 560rpx | - ---td-dropdown-menu-bg-color | @bg-color-container | - --td-tree-bg-color | @bg-color-container | - --td-tree-item-active-color | @brand-color | - --td-tree-item-font-size | 32rpx | - diff --git a/packages/components/dropdown-menu/README.md b/packages/components/dropdown-menu/README.md index 5f8254380..04a1de89c 100644 --- a/packages/components/dropdown-menu/README.md +++ b/packages/components/dropdown-menu/README.md @@ -130,7 +130,6 @@ t-class-footer | 底部样式类 --td-dropdown-menu-height | 96rpx | - --td-dropdown-menu-icon-size | 40rpx | - --td-dropdown-body-max-height | 560rpx | - ---td-dropdown-menu-bg-color | @bg-color-container | - --td-tree-bg-color | @bg-color-container | - --td-tree-item-active-color | @brand-color | - --td-tree-item-font-size | 32rpx | - diff --git a/packages/components/form-item/README.en-US.md b/packages/components/form-item/README.en-US.md index 34f3a9863..47d91d17c 100644 --- a/packages/components/form-item/README.en-US.md +++ b/packages/components/form-item/README.en-US.md @@ -18,3 +18,13 @@ name | String | - | \- | N required-mark | Boolean | undefined | \- | N rules | Array | - | Typescript:`Array` | N show-error-message | Boolean | undefined | \- | N + +### CSS Variables + +The component provides the following CSS variables, which can be used to customize styles. +Name | Default Value | Description +-- | -- | -- +--td-form-item-horizontal-padding | 32rpx | - +--td-form-item-justify-content | space-between | - +--td-form-item-label-width | 160rpx | - +--td-form-item-vertical-padding | 32rpx | - \ No newline at end of file diff --git a/packages/components/form-item/README.md b/packages/components/form-item/README.md index cc29a0cee..2af592d0c 100644 --- a/packages/components/form-item/README.md +++ b/packages/components/form-item/README.md @@ -18,3 +18,13 @@ name | String | - | 表单字段名称 | N required-mark | Boolean | undefined | 是否显示必填符号(*),优先级高于 Form.requiredMark | N rules | Array | - | 【开发中】 | N show-error-message | Boolean | undefined | 校验不通过时,是否显示错误提示信息,优先级高于 `Form.showErrorMessage` | N + +### CSS Variables + +组件提供了下列 CSS 变量,可用于自定义样式。 +名称 | 默认值 | 描述 +-- | -- | -- +--td-form-item-horizontal-padding | 32rpx | - +--td-form-item-justify-content | space-between | - +--td-form-item-label-width | 160rpx | - +--td-form-item-vertical-padding | 32rpx | - \ No newline at end of file diff --git a/packages/components/form/README.en-US.md b/packages/components/form/README.en-US.md index 35133baa8..d9dd7e007 100644 --- a/packages/components/form/README.en-US.md +++ b/packages/components/form/README.en-US.md @@ -106,3 +106,17 @@ telnumber | String | - | \- | N url | String | - | \- | N validator | String | - | \- | N whitespace | String | - | \- | N + +### CSS Variables + +The component provides the following CSS variables, which can be used to customize styles. +Name | Default Value | Description +-- | -- | -- +--td-form-bg-color | @bg-color-container | - +--td-form-border-radius | 0 | - +--td-form-padding | 0 | - +--td-form-readonly-bg-color | @bg-color-secondarycontainer | - +--td-form-item-horizontal-padding | 32rpx | - +--td-form-item-justify-content | space-between | - +--td-form-item-label-width | 160rpx | - +--td-form-item-vertical-padding | 32rpx | - \ No newline at end of file diff --git a/packages/components/form/README.md b/packages/components/form/README.md index 05303fca1..2fafc98e1 100644 --- a/packages/components/form/README.md +++ b/packages/components/form/README.md @@ -106,3 +106,17 @@ telnumber | String | - | 手机号号码校验不通过时的表单项显示文 url | String | - | 链接校验规则不通过时的表单项显示文案,全局配置默认是:`'请输入正确的${name}'` | N validator | String | - | 自定义校验规则校验不通过时的表单项显示文案,全局配置默认是:'${name}不符合要求' | N whitespace | String | - | 值为空格校验不通过时表单项显示文案,全局配置默认是:`'${name}不能为空` | N + +### CSS Variables + +组件提供了下列 CSS 变量,可用于自定义样式。 +名称 | 默认值 | 描述 +-- | -- | -- +--td-form-bg-color | @bg-color-container | - +--td-form-border-radius | 0 | - +--td-form-padding | 0 | - +--td-form-readonly-bg-color | @bg-color-secondarycontainer | - +--td-form-item-horizontal-padding | 32rpx | - +--td-form-item-justify-content | space-between | - +--td-form-item-label-width | 160rpx | - +--td-form-item-vertical-padding | 32rpx | - \ No newline at end of file diff --git a/packages/components/guide/guide.ts b/packages/components/guide/guide.ts index be78706eb..991da05f4 100644 --- a/packages/components/guide/guide.ts +++ b/packages/components/guide/guide.ts @@ -189,22 +189,22 @@ export default class Guide extends SuperComponent { }, onTplButtonTap(e) { const { type } = e.target.dataset; - const parmas = { e, current: this.data.current, total: this.data.steps.length }; + const params = { e, current: this.data.current, total: this.data.steps.length }; switch (type) { case 'next': - this.triggerEvent('next-step-click', { next: this.data.current + 1, ...parmas }); + this.triggerEvent('next-step-click', { next: this.data.current + 1, ...params }); this.setData({ current: this.data.current + 1 }); break; case 'skip': - this.triggerEvent('skip', parmas); + this.triggerEvent('skip', params); this.setData({ current: -1 }); break; case 'back': - this.triggerEvent('back', parmas); + this.triggerEvent('back', params); this.setData({ current: 0 }); break; case 'finish': - this.triggerEvent('finish', parmas); + this.triggerEvent('finish', params); this.setData({ current: -1 }); break; default: diff --git a/packages/components/indexes-anchor/README.en-US.md b/packages/components/indexes-anchor/README.en-US.md index 4abdff508..aabb00390 100644 --- a/packages/components/indexes-anchor/README.en-US.md +++ b/packages/components/indexes-anchor/README.en-US.md @@ -22,4 +22,4 @@ Name | Default Value | Description --td-indexes-anchor-font-size | 28rpx | - --td-indexes-anchor-line-height | 44rpx | - --td-indexes-anchor-padding | 8rpx 32rpx | - ---td-indexes-anchor-top | 0 | - +--td-indexes-anchor-top | 0 | - \ No newline at end of file diff --git a/packages/components/indexes-anchor/README.md b/packages/components/indexes-anchor/README.md index dd3602224..3d3c880e1 100644 --- a/packages/components/indexes-anchor/README.md +++ b/packages/components/indexes-anchor/README.md @@ -26,4 +26,4 @@ t-class | 根节点样式类 --td-indexes-anchor-font-size | 28rpx | - --td-indexes-anchor-line-height | 44rpx | - --td-indexes-anchor-padding | 8rpx 32rpx | - ---td-indexes-anchor-top | 0 | - +--td-indexes-anchor-top | 0 | - \ No newline at end of file diff --git a/packages/components/indexes/_example/base/index.js b/packages/components/indexes/_example/base/index.js index dd328c298..92e209bf3 100644 --- a/packages/components/indexes/_example/base/index.js +++ b/packages/components/indexes/_example/base/index.js @@ -1,6 +1,6 @@ Page({ data: { - defaultCurrent: 'B', + current: 'B', indexList: [], list: [ { @@ -104,7 +104,9 @@ Page({ onChange(e) { const { index } = e.detail; - + this.setData({ + current: index, + }); console.log('change:', index); }, diff --git a/packages/components/indexes/_example/base/index.wxml b/packages/components/indexes/_example/base/index.wxml index 3bccf74e3..7eee8f0b1 100644 --- a/packages/components/indexes/_example/base/index.wxml +++ b/packages/components/indexes/_example/base/index.wxml @@ -2,7 +2,7 @@ `; +exports[`Watermark Watermark layout demo works fine 1`] = ` + + + Rectangular Grid 矩形布局 + + + + + + Hexagonal Grid 六边形网格 + + + + + +`; + exports[`Watermark Watermark move-image demo works fine 1`] = ` { mapper.forEach((demoName) => { diff --git a/packages/components/watermark/_example/layout/index.js b/packages/components/watermark/_example/layout/index.js new file mode 100644 index 000000000..b3f9d70c1 --- /dev/null +++ b/packages/components/watermark/_example/layout/index.js @@ -0,0 +1,5 @@ +Component({ + data: { + watermark: { text: '文字水印' }, + }, +}); diff --git a/packages/components/watermark/_example/layout/index.json b/packages/components/watermark/_example/layout/index.json new file mode 100644 index 000000000..7e02fb1a8 --- /dev/null +++ b/packages/components/watermark/_example/layout/index.json @@ -0,0 +1,7 @@ +{ + "component": true, + "styleIsolation": "apply-shared", + "usingComponents": { + "t-watermark": "tdesign-miniprogram/watermark/watermark" + } +} diff --git a/packages/components/watermark/_example/layout/index.wxml b/packages/components/watermark/_example/layout/index.wxml new file mode 100644 index 000000000..01d2f9889 --- /dev/null +++ b/packages/components/watermark/_example/layout/index.wxml @@ -0,0 +1,9 @@ +Rectangular Grid 矩形布局 + + + + +Hexagonal Grid 六边形网格 + + + diff --git a/packages/components/watermark/_example/layout/index.wxss b/packages/components/watermark/_example/layout/index.wxss new file mode 100644 index 000000000..e69de29bb diff --git a/packages/components/watermark/_example/watermark.json b/packages/components/watermark/_example/watermark.json index 4424cd9de..04afe42a4 100644 --- a/packages/components/watermark/_example/watermark.json +++ b/packages/components/watermark/_example/watermark.json @@ -7,6 +7,7 @@ "multi-line-gray-watermark": "./multi-line-gray", "move-text-watermark": "./move-text", "move-image-watermark": "./move-image", - "gray-watermark": "./gray" + "gray-watermark": "./gray", + "layout": "./layout" } } diff --git a/packages/components/watermark/_example/watermark.wxml b/packages/components/watermark/_example/watermark.wxml index 4c4264418..c72118b3e 100644 --- a/packages/components/watermark/_example/watermark.wxml +++ b/packages/components/watermark/_example/watermark.wxml @@ -28,4 +28,7 @@ + + + diff --git a/packages/components/watermark/props.ts b/packages/components/watermark/props.ts index c6df0f41e..19d60f47d 100644 --- a/packages/components/watermark/props.ts +++ b/packages/components/watermark/props.ts @@ -24,6 +24,11 @@ const props: TdWatermarkProps = { type: Boolean, value: true, }, + /** 水印的布局方式,rectangular:矩形,即横平竖直的水印;hexagonal:六边形,即错位的水印 */ + layout: { + type: String, + value: 'rectangular', + }, /** 行间距,只作用在多行(`content` 配置为数组)情况下 */ lineSpace: { type: Number, diff --git a/packages/components/watermark/type.ts b/packages/components/watermark/type.ts index 54f677a7a..9047aea52 100644 --- a/packages/components/watermark/type.ts +++ b/packages/components/watermark/type.ts @@ -35,6 +35,14 @@ export interface TdWatermarkProps { type: BooleanConstructor; value?: boolean; }; + /** + * 水印的布局方式,rectangular:矩形,即横平竖直的水印;hexagonal:六边形,即错位的水印 + * @default rectangular + */ + layout?: { + type: StringConstructor; + value?: 'rectangular' | 'hexagonal'; + }; /** * 行间距,只作用在多行(`content` 配置为数组)情况下 * @default 16 diff --git a/packages/components/watermark/utils/generateBase64Url.ts b/packages/components/watermark/utils/generateBase64Url.ts index 68c4487c5..e8d1bb40a 100644 --- a/packages/components/watermark/utils/generateBase64Url.ts +++ b/packages/components/watermark/utils/generateBase64Url.ts @@ -2,45 +2,133 @@ import { systemInfo } from '../../common/utils'; export default function generateBase64Url( canvas, - { width, height, gapX, gapY, offsetLeft, offsetTop, rotate, alpha, watermarkContent, lineSpace, watermarkColor }, + { + width, + height, + gapX, + gapY, + offsetLeft, + offsetTop, + rotate, + alpha, + watermarkContent, + lineSpace, + watermarkColor, + layout, + }, onFinish, ) { + const isHexagonal = layout === 'hexagonal'; + const ctx = canvas.getContext('2d'); + if (!ctx) { console.warn('当前环境不支持Canvas, 无法绘制水印'); onFinish(''); return; } + const ratio = systemInfo.pixelRatio || 1; + + let actualBackgroundSize = { + width: gapX + width, + }; + const canvasWidth = (gapX + width) * ratio; const canvasHeight = (gapY + height) * ratio; + const markWidth = width * ratio; + const markHeight = height * ratio; + + const dislocationRotateX = canvasWidth; + const dislocationRotateY = canvasHeight; + const dislocationDrawX = (gapX + width) * ratio; + const dislocationDrawY = (gapY + height) * ratio; + canvas.width = canvasWidth; canvas.height = canvasHeight; + if (isHexagonal) { + canvas.width = canvasWidth * 2; + canvas.height = canvasHeight * 2; + + // 两倍宽度+间距 + actualBackgroundSize = { + width: gapX + width * 2 + width / 2, + }; + } + ctx.translate(offsetLeft * ratio, offsetTop * ratio); - ctx.rotate((Math.PI / 180) * Number(rotate)); ctx.globalAlpha = alpha; - const markWidth = width * ratio; - const markHeight = height * ratio; - ctx.fillStyle = 'transparent'; ctx.fillRect(0, 0, markWidth, markHeight); + // 元素中心为旋转点执行旋转 + const drawRotate = (ctx: CanvasRenderingContext2D, x: number, y: number, rotate: number) => { + ctx.translate(x, y); + ctx.rotate((Math.PI / 180) * Number(rotate)); + ctx.translate(-x, -y); + }; + + // 绘制文字 + const drawText = ( + ctx: CanvasRenderingContext2D, + x: number, + y: number, + markHeight: number, + text: string, + fontWeight: string, + fontSize: number, + fontFamily: string, + fillStyle: string, + ) => { + ctx.font = `normal normal ${fontWeight} ${fontSize * ratio}px/${markHeight}px ${fontFamily}`; + ctx.fillStyle = fillStyle; + ctx.textAlign = 'start'; + ctx.textBaseline = 'top'; + + ctx.fillText(text, x, y); + }; + const contents = Array.isArray(watermarkContent) ? watermarkContent : [{ ...watermarkContent }]; let top = 0; + let imageLoadCount = 0; + let totalImages = 0; + + // 预处理 contents.forEach((item) => { + item.top = top; if (item.url) { - const { url, isGrayscale = false } = item; - item.top = top; top += height; - const image = canvas.createImage(); - image.src = url; - image.onload = () => { - ctx.drawImage(image, 0, item.top * ratio, width * ratio, height * ratio); + totalImages += isHexagonal ? 2 : 1; // hexagonal布局需要绘制两次 + } else if (item.text) { + top += lineSpace; + } + }); + + // 绘制水印内容 + const renderWatermarkItem = ( + item, + offsetX: number = 0, + offsetY: number = 0, + rotateX: number = 0, + rotateY: number = 0, + ) => { + if (item.url) { + const { url, isGrayscale = false } = item; + const img = canvas.createImage(); + img.crossOrigin = 'anonymous'; + img.referrerPolicy = 'no-referrer'; + img.src = url; + img.onload = () => { + ctx.save?.(); + drawRotate(ctx, rotateX, rotateY, rotate); + + // TODO:其他技术栈修复了「灰度效果只影响图片,不影响文字」的bug,因为小程序不能创建临时canvas,暂时没有想到比较优雅的解决方案 if (isGrayscale) { + ctx.drawImage(img, offsetX, offsetY + item.top * ratio, width * ratio, height * ratio); const imgData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height); const pixels = imgData.data; for (let i = 0; i < pixels.length; i += 4) { @@ -50,20 +138,43 @@ export default function generateBase64Url( pixels[i + 2] = lightness; } ctx.putImageData(imgData, 0, 0); + } else { + ctx.drawImage(img, offsetX, offsetY + item.top * ratio, width * ratio, height * ratio); + } + + ctx.restore?.(); + + // 图片加载完成再返回 + imageLoadCount += 1; + if (imageLoadCount === totalImages) { + onFinish(canvas.toDataURL(), actualBackgroundSize); } - onFinish(canvas.toDataURL()); }; } else if (item.text) { - const { text, fontColor = watermarkColor, fontSize = 16, fontFamily = undefined, fontWeight = 'normal' } = item; - item.top = top; - top += lineSpace; - const markSize = Number(fontSize) * ratio; - ctx.font = `normal normal ${fontWeight} ${markSize}px/${markHeight}px ${fontFamily}`; - ctx.textAlign = 'start'; - ctx.textBaseline = 'top'; - ctx.fillStyle = fontColor; - ctx.fillText(text, 0, item.top * ratio); + const { text, fontSize = 16, fontFamily = 'normal', fontWeight = 'normal' } = item; + const fillStyle = item?.fontColor || watermarkColor; + + ctx.save?.(); + drawRotate(ctx, rotateX, rotateY, rotate); + drawText(ctx, offsetX, offsetY + item.top * ratio, markHeight, text, fontWeight, fontSize, fontFamily, fillStyle); + ctx.restore?.(); } + }; + + // 矩形水印 + contents.forEach((item) => { + renderWatermarkItem(item, 0, 0, 0, 0); }); - onFinish(canvas.toDataURL()); + + // 六边形水印 + if (isHexagonal) { + contents.forEach((item) => { + renderWatermarkItem(item, dislocationDrawX, dislocationDrawY, dislocationRotateX, dislocationRotateY); + }); + } + + // 没有图片 + if (totalImages === 0) { + onFinish(canvas.toDataURL(), actualBackgroundSize); + } } diff --git a/packages/components/watermark/watermark.ts b/packages/components/watermark/watermark.ts index ddb2ab7ef..62872102b 100644 --- a/packages/components/watermark/watermark.ts +++ b/packages/components/watermark/watermark.ts @@ -26,7 +26,7 @@ export default class Watermark extends SuperComponent { }; observers = { - 'watermarkContent, movable, rotate, x, y, width, height, alpha, lineSpace, moveInterval, zIndex, rotate, offset, removable, isRepeat'() { + 'watermarkContent, movable, rotate, x, y, width, height, alpha, lineSpace, moveInterval, zIndex, rotate, offset, removable, isRepeat, layout'() { this.renderWatermark(); }, }; @@ -66,8 +66,9 @@ export default class Watermark extends SuperComponent { offsetLeft: offsetLeft, offsetTop: offsetTop, watermarkColor: this.watermarkColor(), + layout: props.layout, }; - generateBase64Url(canvas, bgImageOptions, (base64Url) => { + generateBase64Url(canvas, bgImageOptions, (base64Url, backgroundSize) => { let animationVars = {}; if (props.movable) { const { left0, left25, left50, left75, top0, top25, top50, top75 } = randomMovingStyle(); @@ -93,7 +94,7 @@ export default class Watermark extends SuperComponent { bottom: 0, width: '100%', height: '100%', - backgroundSize: `${gapX + props.width}px`, + backgroundSize: `${backgroundSize?.width || gapX.value + props.width}px`, pointerEvents: 'none', backgroundRepeat: props.movable ? 'no-repeat' : 'repeat', backgroundImage: `url('${base64Url}')`, diff --git a/packages/tdesign-miniprogram-chat/CHANGELOG.md b/packages/tdesign-miniprogram-chat/CHANGELOG.md index 0f79adb99..28d1f0e96 100644 --- a/packages/tdesign-miniprogram-chat/CHANGELOG.md +++ b/packages/tdesign-miniprogram-chat/CHANGELOG.md @@ -6,4 +6,36 @@ docClass: timeline --- +## 🌈 1.11.0 `2025-10-20` +### 🚀 Features +- `Watermark`: 新增 `Watermark` 水印组件 @Wesley-0808 ([#3799](https://github.com/Tencent/tdesign-miniprogram/pull/3799)) +- `Textarea`: 改用伪元素实现边框,避免占位 @anlyyao ([#3878](https://github.com/Tencent/tdesign-miniprogram/pull/3878)) +- `SideBarItem`: + - 新增默认插槽,可自定义侧边栏子项内容 @anlyyao ([#3875](https://github.com/Tencent/tdesign-miniprogram/pull/3875)) + - 支持由标签内容撑开高度 @anlyyao ([#3985](https://github.com/Tencent/tdesign-miniprogram/pull/3985)) +- `Swiper`: 新增 `animationfinish` 事件 @anlyyao ([#3885](https://github.com/Tencent/tdesign-miniprogram/pull/3885)) +- `Textarea`: 组件 `CSS Vars` 新增 `--td-textarea-padding` @anlyyao ([#3937](https://github.com/Tencent/tdesign-miniprogram/pull/3937)) +- `PickerItem`: 子项支持 `icon` 属性 @anlyyao ([#3930](https://github.com/Tencent/tdesign-miniprogram/pull/3930)) +- `Upload`: `click` 事件新增 `index` 参数 @anlyyao ([#3942](https://github.com/Tencent/tdesign-miniprogram/pull/3942)) +- `Slider`: `label` 属性支持函数类型,用于自定义滑块当前值文本 @anlyyao ([#3928](https://github.com/Tencent/tdesign-miniprogram/pull/3928)) +- `Drawer`: 新增 `overlayProps` 属性 @anlyyao ([#3978](https://github.com/Tencent/tdesign-miniprogram/pull/3978)) +- `QRCode`: 新增外部样式类 `t-class-canvas` @anlyyao ([#3956](https://github.com/Tencent/tdesign-miniprogram/pull/3956)) +### 🐞 Bug Fixes +- `DateTimePicker`: 修复 `showWeek` 模式下日(`date`)列表未正确排除 `start` 和 `end`、且 `steps` 步长无效的问题 @composable-tu ([#3861](https://github.com/Tencent/tdesign-miniprogram/pull/3861)) +- `Message`: 修复 `error` 主题图标错误 @anlyyao ([#3879](https://github.com/Tencent/tdesign-miniprogram/pull/3879)) +- `PullDownRefresh`: 修复 `t-class-loading` 配置不生效的问题 @betavs ([#3896](https://github.com/Tencent/tdesign-miniprogram/pull/3896)) +- `Input`: 修复在 `skyline` 和 `type = 'nickname'` 场景下,`change` 事件无效的问题 @anlyyao ([#3858](https://github.com/Tencent/tdesign-miniprogram/pull/3858)) +- `StepItem`: 修复 `title` 和 `description` 之间的间距错误 @anlyyao ([#3898](https://github.com/Tencent/tdesign-miniprogram/pull/3898)) +- `Skeleton`: 修复 `row-col` 中的选项为数字时无法实现多列效果的问题 @betavs ([#3932](https://github.com/Tencent/tdesign-miniprogram/pull/3932)) +- `TabBar`: 修复在 `Skyline` 渲染引擎下, `change` 事件无效的问题 @anlyyao ([#3926](https://github.com/Tencent/tdesign-miniprogram/pull/3926)) +- `Checkbox`: 修复 `icon` 属性使用 `svg` 资源时在 `iOS` 上不显示 @anlyyao ([#3929](https://github.com/Tencent/tdesign-miniprogram/pull/3929)) +- `Slider`: 修复动态更新 `value` 无效的问题 @anlyyao ([#3954](https://github.com/Tencent/tdesign-miniprogram/pull/3954)) +- `DropdownItem`: 修复在 `iOS 26` 中弹窗定位不准 @anlyyao ([#3953](https://github.com/Tencent/tdesign-miniprogram/pull/3953)) +- `Toast`: 修复 `showOverlay` 和 `preventScrollThrough` 均为 `true` 时,遮罩背景色错误 @anlyyao ([#3948](https://github.com/Tencent/tdesign-miniprogram/pull/3948)) +- `SideBar`: 修复禁用态颜色错误 @novlan1 ([#3982](https://github.com/Tencent/tdesign-miniprogram/pull/3982)) +- `Calendar`: 修复翻页按钮状态错误 @anlyyao ([#3996](https://github.com/Tencent/tdesign-miniprogram/pull/3996)) +- `ImageViewer`: 修复背景色错误问题 @novlan1 ([#3881](https://github.com/Tencent/tdesign-miniprogram/pull/3881)) +- `QRCode`: 修复中心二维码位置偏移 @SinzoL ([#3899](https://github.com/Tencent/tdesign-miniprogram/pull/3899)) + + ## 🌈 首发 diff --git a/packages/tdesign-miniprogram-chat/site/vite.config.ts b/packages/tdesign-miniprogram-chat/site/vite.config.ts index 5732296b5..984d67d57 100644 --- a/packages/tdesign-miniprogram-chat/site/vite.config.ts +++ b/packages/tdesign-miniprogram-chat/site/vite.config.ts @@ -13,7 +13,7 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url)); const publicPathMap: Record = { preview: '/', - production: '/miniprogram-chat/', + production: 'https://static.tdesign.tencent.com/miniprogram-chat/', }; // https://vitejs.dev/config/ diff --git a/packages/tdesign-miniprogram/CHANGELOG.md b/packages/tdesign-miniprogram/CHANGELOG.md index 0c47c776f..90b999f6d 100644 --- a/packages/tdesign-miniprogram/CHANGELOG.md +++ b/packages/tdesign-miniprogram/CHANGELOG.md @@ -6,6 +6,38 @@ docClass: timeline --- +## 🌈 1.11.0 `2025-10-20` +### 🚀 Features +- `Watermark`: 新增 `Watermark` 水印组件 @Wesley-0808 ([#3799](https://github.com/Tencent/tdesign-miniprogram/pull/3799)) +- `Textarea`: 改用伪元素实现边框,避免占位 @anlyyao ([#3878](https://github.com/Tencent/tdesign-miniprogram/pull/3878)) +- `SideBarItem`: + - 新增默认插槽,可自定义侧边栏子项内容 @anlyyao ([#3875](https://github.com/Tencent/tdesign-miniprogram/pull/3875)) + - 支持由标签内容撑开高度 @anlyyao ([#3985](https://github.com/Tencent/tdesign-miniprogram/pull/3985)) +- `Swiper`: 新增 `animationfinish` 事件 @anlyyao ([#3885](https://github.com/Tencent/tdesign-miniprogram/pull/3885)) +- `Textarea`: 组件 `CSS Vars` 新增 `--td-textarea-padding` @anlyyao ([#3937](https://github.com/Tencent/tdesign-miniprogram/pull/3937)) +- `PickerItem`: 子项支持 `icon` 属性 @anlyyao ([#3930](https://github.com/Tencent/tdesign-miniprogram/pull/3930)) +- `Upload`: `click` 事件新增 `index` 参数 @anlyyao ([#3942](https://github.com/Tencent/tdesign-miniprogram/pull/3942)) +- `Slider`: `label` 属性支持函数类型,用于自定义滑块当前值文本 @anlyyao ([#3928](https://github.com/Tencent/tdesign-miniprogram/pull/3928)) +- `Drawer`: 新增 `overlayProps` 属性 @anlyyao ([#3978](https://github.com/Tencent/tdesign-miniprogram/pull/3978)) +- `QRCode`: 新增外部样式类 `t-class-canvas` @anlyyao ([#3956](https://github.com/Tencent/tdesign-miniprogram/pull/3956)) +### 🐞 Bug Fixes +- `DateTimePicker`: 修复 `showWeek` 模式下日(`date`)列表未正确排除 `start` 和 `end`、且 `steps` 步长无效的问题 @composable-tu ([#3861](https://github.com/Tencent/tdesign-miniprogram/pull/3861)) +- `Message`: 修复 `error` 主题图标错误 @anlyyao ([#3879](https://github.com/Tencent/tdesign-miniprogram/pull/3879)) +- `PullDownRefresh`: 修复 `t-class-loading` 配置不生效的问题 @betavs ([#3896](https://github.com/Tencent/tdesign-miniprogram/pull/3896)) +- `Input`: 修复在 `skyline` 和 `type = 'nickname'` 场景下,`change` 事件无效的问题 @anlyyao ([#3858](https://github.com/Tencent/tdesign-miniprogram/pull/3858)) +- `StepItem`: 修复 `title` 和 `description` 之间的间距错误 @anlyyao ([#3898](https://github.com/Tencent/tdesign-miniprogram/pull/3898)) +- `Skeleton`: 修复 `row-col` 中的选项为数字时无法实现多列效果的问题 @betavs ([#3932](https://github.com/Tencent/tdesign-miniprogram/pull/3932)) +- `TabBar`: 修复在 `Skyline` 渲染引擎下, `change` 事件无效的问题 @anlyyao ([#3926](https://github.com/Tencent/tdesign-miniprogram/pull/3926)) +- `Checkbox`: 修复 `icon` 属性使用 `svg` 资源时在 `iOS` 上不显示 @anlyyao ([#3929](https://github.com/Tencent/tdesign-miniprogram/pull/3929)) +- `Slider`: 修复动态更新 `value` 无效的问题 @anlyyao ([#3954](https://github.com/Tencent/tdesign-miniprogram/pull/3954)) +- `DropdownItem`: 修复在 `iOS 26` 中弹窗定位不准 @anlyyao ([#3953](https://github.com/Tencent/tdesign-miniprogram/pull/3953)) +- `Toast`: 修复 `showOverlay` 和 `preventScrollThrough` 均为 `true` 时,遮罩背景色错误 @anlyyao ([#3948](https://github.com/Tencent/tdesign-miniprogram/pull/3948)) +- `SideBar`: 修复禁用态颜色错误 @novlan1 ([#3982](https://github.com/Tencent/tdesign-miniprogram/pull/3982)) +- `Calendar`: 修复翻页按钮状态错误 @anlyyao ([#3996](https://github.com/Tencent/tdesign-miniprogram/pull/3996)) +- `ImageViewer`: 修复背景色错误问题 @novlan1 ([#3881](https://github.com/Tencent/tdesign-miniprogram/pull/3881)) +- `QRCode`: 修复中心二维码位置偏移 @SinzoL ([#3899](https://github.com/Tencent/tdesign-miniprogram/pull/3899)) + + ## 🌈 1.10.1 `2025-08-22` ### 🚀 Features - `Textarea`: 新增 `cursorColor` 属性,仅在 `Skyline` 下有效 @anlyyao ([#3832](https://github.com/Tencent/tdesign-miniprogram/pull/3832)) @@ -1116,4 +1148,4 @@ docClass: timeline - `Rate`: 修复半选时 tips 的图标 @LeeJim ([#1490](https://github.com/Tencent/tdesign-miniprogram/pull/1490)) ## 🌈 0.x `2021-11-25 - 2023-01-09` -前往 [GitHub](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/tdesign-miniprogram/CHANGELOG-0.x.md) 查看 `0.x` 更新日志 \ No newline at end of file +前往 [GitHub](https://github.com/Tencent/tdesign-miniprogram/blob/develop/packages/tdesign-miniprogram/CHANGELOG-0.x.md) 查看 `0.x` 更新日志 diff --git a/packages/tdesign-miniprogram/example/components/demo-block/index.less b/packages/tdesign-miniprogram/example/components/demo-block/index.less index e29dd1d6b..1c6251f5d 100644 --- a/packages/tdesign-miniprogram/example/components/demo-block/index.less +++ b/packages/tdesign-miniprogram/example/components/demo-block/index.less @@ -37,7 +37,7 @@ } } - &__slot { + &__slot:not(:empty) { margin-top: @spacer-2; &.with-padding { diff --git a/packages/tdesign-miniprogram/package.json b/packages/tdesign-miniprogram/package.json index 52ae064af..7dea1fa2a 100644 --- a/packages/tdesign-miniprogram/package.json +++ b/packages/tdesign-miniprogram/package.json @@ -1,6 +1,6 @@ { "name": "tdesign-miniprogram", - "version": "1.11.0-beta.2", + "version": "1.11.0", "title": "tdesign-miniprogram", "description": "TDesign Component for miniprogram", "main": "miniprogram_dist/index.js", diff --git a/packages/tdesign-miniprogram/site/docs/dark-mode.md b/packages/tdesign-miniprogram/site/docs/dark-mode.md index e60d46e53..2ca42da3c 100644 --- a/packages/tdesign-miniprogram/site/docs/dark-mode.md +++ b/packages/tdesign-miniprogram/site/docs/dark-mode.md @@ -19,7 +19,7 @@ spline: design-mode ## 实现方案 -TDesign Minirogram 基于 Design Token 变量和媒体查询 `prefers-color-scheme` 实现了深色模式。默认情况下,每个组件自带了组件级别 light 样式变量,无需手动引入。如需使用深色模式,请按照以下步骤操作。 +TDesign Miniprogram 基于 Design Token 变量和媒体查询 `prefers-color-scheme` 实现了深色模式。默认情况下,每个组件自带了组件级别 light 样式变量,无需手动引入。如需使用深色模式,请按照以下步骤操作。 ## 使用方式 diff --git a/packages/tdesign-miniprogram/site/docs/overview.en-US.md b/packages/tdesign-miniprogram/site/docs/overview.en-US.md index 309d76bd7..07dcf1d04 100644 --- a/packages/tdesign-miniprogram/site/docs/overview.en-US.md +++ b/packages/tdesign-miniprogram/site/docs/overview.en-US.md @@ -235,7 +235,7 @@ spline: explain -

Data Display17

+

Data Display18

+ +

Feedback10

diff --git a/packages/tdesign-miniprogram/site/docs/overview.md b/packages/tdesign-miniprogram/site/docs/overview.md index bad1152de..227b0b87c 100644 --- a/packages/tdesign-miniprogram/site/docs/overview.md +++ b/packages/tdesign-miniprogram/site/docs/overview.md @@ -234,7 +234,7 @@ spline: explain -

数据展示17

+

数据展示18

+ +

反馈12

diff --git a/packages/tdesign-miniprogram/site/scripts/generate-css-vars.mjs b/packages/tdesign-miniprogram/site/scripts/generate-css-vars.mjs index 9b1b5ace6..2c1a04d64 100644 --- a/packages/tdesign-miniprogram/site/scripts/generate-css-vars.mjs +++ b/packages/tdesign-miniprogram/site/scripts/generate-css-vars.mjs @@ -3,8 +3,8 @@ import resolveCwd from './utils.mjs'; const COMPONENT_NAME = process.argv[process.argv.indexOf('--NAME') + 1]; // 在 --NAME 后面 const ROOT_DIR = COMPONENT_NAME.includes('chat') - ? resolveCwd('/packages/pro-components') - : resolveCwd('/packages/components'); + ? resolveCwd('../../../packages/pro-components') + : resolveCwd('../../../packages/components'); const combine = { avatar: ['avatar-group', 'avatar'], @@ -37,6 +37,7 @@ const getAllComponentName = async (dirPath) => { const generateCssVariables = async (componentName) => { const lessPath = []; + const parsedKeys = []; let cssVariableBodyContent = ''; if (combine[componentName]) { @@ -53,18 +54,27 @@ const generateCssVariables = async (componentName) => { const fileContents = await Promise.all(validPaths.map((item) => fs.promises.readFile(item, 'utf8'))); fileContents.forEach((file) => { - const matchReg = /(?<=var)[\s\S]*?(?=;)/g; + const matchReg = /(?<=var)\([\s\S]*?(?=;)/g; const list = file.match(matchReg)?.sort(); - list?.forEach((item, index) => { - cssVariableBodyContent += `${item.slice(1, item.indexOf(',')).trim()} | ${item + list?.forEach((item) => { + const key = item.slice(1, item.indexOf(',')).trim() + const value = item .slice(item.indexOf(',') + 2, item.length - 1) - .trim()} | -${index === list.length - 1 ? '' : ' \n'}`; + .trim(); + if (!key || !value) { + throw new Error('⚠️ 解析失败,请检查 less 文件') + } + if (!parsedKeys.includes(key)) { + parsedKeys.push(key); + cssVariableBodyContent += `${key} | ${value} | -${' \n'}`; + } + }); }); - return cssVariableBodyContent; + return cssVariableBodyContent.trimEnd(); }; /** @@ -99,7 +109,7 @@ const processAllComponents = async () => { let COMPONENT_NAMES = []; if (COMPONENT_NAME === 'all') { - COMPONENT_NAMES = await getAllComponentName(resolveCwd(ROOT_DIR)); + COMPONENT_NAMES = await getAllComponentName(ROOT_DIR); } else { COMPONENT_NAMES = [COMPONENT_NAME]; } diff --git a/packages/tdesign-miniprogram/site/vite.config.ts b/packages/tdesign-miniprogram/site/vite.config.ts index 3c812fd86..8c2134fb4 100644 --- a/packages/tdesign-miniprogram/site/vite.config.ts +++ b/packages/tdesign-miniprogram/site/vite.config.ts @@ -13,7 +13,7 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url)); const publicPathMap: Record = { preview: '/', - production: '/miniprogram/', + production: 'https://static.tdesign.tencent.com/miniprogram/', }; // https://vitejs.dev/config/ diff --git a/script/gulpfile.example.js b/script/gulpfile.example.js index 5dd3ad22b..6f3f58a33 100644 --- a/script/gulpfile.example.js +++ b/script/gulpfile.example.js @@ -6,9 +6,10 @@ const rename = require('gulp-rename'); const gulpLess = require('gulp-less'); const sourcemaps = require('gulp-sourcemaps'); const plumber = require('gulp-plumber'); -const packageJSON = require('../package.json'); const base = require('./gulpfile.base'); +const PACKAGE_NAME = 'tdesign-miniprogram'; + /* config */ const src = 'packages/tdesign-miniprogram/example'; const dist = '_example'; @@ -47,7 +48,7 @@ const since = (task) => (file) => gulp.lastRun(task) > file.stat.ctime ? gulp.la * 将 packages/tdesign-miniprogram/miniprogram_dist 同步至 _example/miniprogram_npm * */ const input = 'packages/tdesign-miniprogram/miniprogram_dist'; -const output = `_example/miniprogram_npm/${packageJSON.name}`; +const output = `_example/miniprogram_npm/${PACKAGE_NAME}`; const syncDist = () => gulp .src(`${input}/**`, { base: input, since: since(syncDist) })