first commit
This commit is contained in:
103
uni_modules/tdesign-uniapp/components/guide/README.en-US.md
Normal file
103
uni_modules/tdesign-uniapp/components/guide/README.en-US.md
Normal file
@@ -0,0 +1,103 @@
|
||||
:: BASE_DOC ::
|
||||
|
||||
## API
|
||||
|
||||
### Guide Props
|
||||
|
||||
name | type | default | description | required
|
||||
-- | -- | -- | -- | --
|
||||
custom-style | Object | - | CSS(Cascading Style Sheets) | N
|
||||
back-button-props | Object | - | Typescript:`ButtonProps` | N
|
||||
counter | String / Function | - | Typescript:`string \| ((params: { total: number; current: number }) => string)` | N
|
||||
current | Number | - | `v-model:current` is supported | N
|
||||
default-current | Number | - | uncontrolled property | N
|
||||
finish-button-props | Object | - | Typescript:`ButtonProps` | N
|
||||
hide-back | Boolean | false | \- | N
|
||||
hide-counter | Boolean | false | \- | N
|
||||
hide-skip | Boolean | false | \- | N
|
||||
highlight-padding | Number | 16 | \- | N
|
||||
mode | String | popover | options: popover/dialog | N
|
||||
next-button-props | Object | - | Typescript:`ButtonProps`,[Button API Documents](./button?tab=api)。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/guide/type.ts) | N
|
||||
show-overlay | Boolean | true | \- | N
|
||||
skip-button-props | Object | - | Typescript:`ButtonProps` | N
|
||||
steps | Array | - | Typescript:`Array<GuideStep>` | N
|
||||
using-custom-navbar | Boolean | false | \- | N
|
||||
z-index | Number | 999999 | \- | N
|
||||
|
||||
### Guide Events
|
||||
|
||||
name | params | description
|
||||
-- | -- | --
|
||||
back | `(context: { e: MouseEvent, current: number, total: number })` | \-
|
||||
change | `(current: number, context?: { e: MouseEvent, total: number })` | \-
|
||||
finish | `(context: { e: MouseEvent, current: number, total: number })` | \-
|
||||
next-step-click | `(context: { e: MouseEvent, next: number, current: number, total: number })` | \-
|
||||
skip | `(context: { e: MouseEvent, current: number, total: number })` | \-
|
||||
|
||||
### Guide External Classes
|
||||
|
||||
className | Description
|
||||
-- | --
|
||||
t-class | \-
|
||||
t-class-back | \-
|
||||
t-class-body | \-
|
||||
t-class-finish | \-
|
||||
t-class-footer | \-
|
||||
t-class-next | \-
|
||||
t-class-popover | \-
|
||||
t-class-reference | \-
|
||||
t-class-skip | \-
|
||||
t-class-title | \-
|
||||
t-class-tooltip | \-
|
||||
|
||||
### GuideStep
|
||||
|
||||
name | type | default | description | required
|
||||
-- | -- | -- | -- | --
|
||||
back-button-props | Object | - | Typescript:`ButtonProps` | N
|
||||
body | String | - | \- | N
|
||||
element | Function | - | required。Typescript:`StepElement` `type StepElement = () => Promise<WechatMiniprogram.BoundingClientRectCallbackResult>`。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/guide/type.ts) | Y
|
||||
finish-button-props | Object | - | Typescript:`ButtonProps` | N
|
||||
highlight-padding | Number | - | \- | N
|
||||
mode | String | - | options: popover/dialog | N
|
||||
next-button-props | Object | - | Typescript:`ButtonProps` | N
|
||||
offset | Array | - | this api is in discussing. do not use it。Typescript:`Array<string \| number>` | N
|
||||
placement | String | 'top' | Typescript:`StepPopoverPlacement ` `type StepPopoverPlacement = 'top'\|'left'\|'right'\|'bottom'\|'top-left'\|'top-right'\|'bottom-left'\|'bottom-right'\|'left-top'\|'left-bottom'\|'right-top'\|'right-bottom'\|'center'`。[see more ts definition](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/guide/type.ts) | N
|
||||
show-overlay | Boolean | true | \- | N
|
||||
skip-button-props | Object | - | Typescript:`ButtonProps` | N
|
||||
title | String | - | title of current step | N
|
||||
|
||||
### CSS Variables
|
||||
|
||||
The component provides the following CSS variables, which can be used to customize styles.
|
||||
Name | Default Value | Description
|
||||
-- | -- | --
|
||||
--td-guide-body-color | @text-color-secondary | -
|
||||
--td-guide-dialog-body-font | @font-body-large | -
|
||||
--td-guide-dialog-body-margin-top | 16rpx | -
|
||||
--td-guide-dialog-body-text-align | center | -
|
||||
--td-guide-dialog-border-radius | @radius-extraLarge | -
|
||||
--td-guide-dialog-footer-button-padding | 0 @spacer-3 | -
|
||||
--td-guide-dialog-padding | @spacer-3 0 | -
|
||||
--td-guide-dialog-title-font | @font-title-large | -
|
||||
--td-guide-dialog-title-text-align | center | -
|
||||
--td-guide-dialog-width | 622rpx | -
|
||||
--td-guide-footer-button-space | @spacer-1 | -
|
||||
--td-guide-footer-margin-top | @spacer-3 | -
|
||||
--td-guide-footer-text-align | right | -
|
||||
--td-guide-popover-bg-color | @bg-color-container | -
|
||||
--td-guide-popover-body-font | @font-body-medium | -
|
||||
--td-guide-popover-body-margin-top | 8rpx | -
|
||||
--td-guide-popover-body-text-align | left | -
|
||||
--td-guide-popover-border | 2rpx solid @component-border | -
|
||||
--td-guide-popover-border-radius | @radius-large | -
|
||||
--td-guide-popover-max-width | 540rpx | -
|
||||
--td-guide-popover-min-width | 480rpx | -
|
||||
--td-guide-popover-padding | @spacer-2 | -
|
||||
--td-guide-popover-shadow | @shadow-3 | -
|
||||
--td-guide-popover-title-font | @font-title-medium | -
|
||||
--td-guide-popover-title-text-align | left | -
|
||||
--td-guide-reference-border | 4rpx solid @brand-color | -
|
||||
--td-guide-reference-border-radius | @radius-default | -
|
||||
--td-guide-reference-mask-color | @font-gray-2 | -
|
||||
--td-guide-title-color | @text-color-primary | -
|
||||
140
uni_modules/tdesign-uniapp/components/guide/README.md
Normal file
140
uni_modules/tdesign-uniapp/components/guide/README.md
Normal file
@@ -0,0 +1,140 @@
|
||||
---
|
||||
title: Guide 按钮
|
||||
description: 逐步骤进行指引或解释说明的组件,常用于用户不熟悉的或需进行特别强调的页面。
|
||||
spline: base
|
||||
isComponent: true
|
||||
---
|
||||
|
||||
|
||||
|
||||
## 引入
|
||||
|
||||
可在 `main.ts` 或在需要使用的页面或组件中引入。
|
||||
|
||||
```js
|
||||
import TGuide from '@tdesign/uniapp/guide/guide.vue';
|
||||
```
|
||||
|
||||
### 01 组件类型
|
||||
|
||||
#### 基础按钮
|
||||
|
||||
{{ base }}
|
||||
|
||||
#### 不带遮罩的引导
|
||||
|
||||
{{ no-mask }}
|
||||
|
||||
#### 弹窗形式的引导
|
||||
|
||||
{{ dialog }}
|
||||
|
||||
#### 气泡与弹窗混合的引导
|
||||
|
||||
{{ multiple }}
|
||||
|
||||
#### 自定义气泡
|
||||
|
||||
{{ content }}
|
||||
|
||||
## API
|
||||
|
||||
### Guide Props
|
||||
|
||||
名称 | 类型 | 默认值 | 描述 | 必传
|
||||
-- | -- | -- | -- | --
|
||||
custom-style | Object | - | 自定义样式 | N
|
||||
back-button-props | Object | - | 透传 返回按钮 的全部属性,示例:`{ content: '返回', theme: 'default' }`。TS 类型:`ButtonProps` | N
|
||||
counter | String / Function | - | 用于自定义渲染计数部分。TS 类型:`string \| ((params: { total: number; current: number }) => string)` | N
|
||||
current | Number | - | 当前步骤,即整个引导的进度。-1 则不展示,用于需要中断展示的场景。支持语法糖 `v-model:current` | N
|
||||
default-current | Number | - | 当前步骤,即整个引导的进度。-1 则不展示,用于需要中断展示的场景。非受控属性 | N
|
||||
finish-button-props | Object | - | 透传 完成按钮 的全部属性,示例:`{ content: '完成', theme: 'primary' }`。TS 类型:`ButtonProps` | N
|
||||
hide-back | Boolean | false | 是否隐藏返回按钮 | N
|
||||
hide-counter | Boolean | false | 是否隐藏计数 | N
|
||||
hide-skip | Boolean | false | 是否隐藏跳过按钮 | N
|
||||
highlight-padding | Number | 16 | 高亮框的内边距,单位rpx | N
|
||||
mode | String | popover | 引导框的类型。可选项:popover/dialog | N
|
||||
next-button-props | Object | - | 透传 下一步按钮 的全部属性,示例:{ content: '下一步', theme: 'primary' }。TS 类型:`ButtonProps`,[Button API Documents](./button?tab=api)。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/guide/type.ts) | N
|
||||
show-overlay | Boolean | true | 是否出现遮罩层 | N
|
||||
skip-button-props | Object | - | 透传 跳过按钮 的全部属性,{ content: '跳过', theme: 'default' }。TS 类型:`ButtonProps` | N
|
||||
steps | Array | - | 用于定义每个步骤的内容,包括高亮的节点、相对位置和具体的文案内容等。TS 类型:`Array<GuideStep>` | N
|
||||
using-custom-navbar | Boolean | false | 是否使用了自定义导航栏 | N
|
||||
z-index | Number | 999999 | 提示框的层级 | N
|
||||
|
||||
### Guide Events
|
||||
|
||||
名称 | 参数 | 描述
|
||||
-- | -- | --
|
||||
back | `(context: { e: MouseEvent, current: number, total: number })` | 点击返回按钮时触发
|
||||
change | `(current: number, context?: { e: MouseEvent, total: number })` | 当前步骤发生变化时触发
|
||||
finish | `(context: { e: MouseEvent, current: number, total: number })` | 点击完成按钮时触发
|
||||
next-step-click | `(context: { e: MouseEvent, next: number, current: number, total: number })` | 点击下一步时触发
|
||||
skip | `(context: { e: MouseEvent, current: number, total: number })` | 点击跳过按钮时触发
|
||||
|
||||
### Guide External Classes
|
||||
|
||||
类名 | 描述
|
||||
-- | --
|
||||
t-class | 根节点样式类
|
||||
t-class-back | 返回按钮样式类
|
||||
t-class-body | 高亮框提示内容主体样式类
|
||||
t-class-finish | 结束按钮样式类
|
||||
t-class-footer | 高亮框底部操作区域样式类
|
||||
t-class-next | 下一步按钮样式类
|
||||
t-class-popover | 引导框样式类
|
||||
t-class-reference | 高亮框样式类
|
||||
t-class-skip | 跳过按钮样式类
|
||||
t-class-title | 高亮框提示内容标题样式类
|
||||
t-class-tooltip | 高亮框提示内容区域样式类
|
||||
|
||||
### GuideStep
|
||||
|
||||
名称 | 类型 | 默认值 | 描述 | 必传
|
||||
-- | -- | -- | -- | --
|
||||
back-button-props | Object | - | 用于自定义当前引导框的返回按钮的内容。TS 类型:`ButtonProps` | N
|
||||
body | String | - | 当前步骤提示框的内容,支持插槽:slot="body-{{index}}" (1、当要显示body-{{index}}插槽时,请将body设置为空;2、当要显示content-{{index}}插槽完全自定义内容时,请将body和title都设置为空) | N
|
||||
element | Function | - | 必需。高亮的节点。示例: `() => new Promise((resolve) => this.createSelectorQuery().select('#tdesign').boundingClientRect((rect) => resolve(rect)).exec())`。TS 类型:`StepElement` `type StepElement = () => Promise<WechatMiniprogram.BoundingClientRectCallbackResult>`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/guide/type.ts) | Y
|
||||
finish-button-props | Object | - | 透传 完成 的全部属性,示例:`{ content: '完成', theme: 'primary' }`。TS 类型:`ButtonProps` | N
|
||||
highlight-padding | Number | - | 高亮框的内边距,单位rpx | N
|
||||
mode | String | - | 引导框的类型。可选项:popover/dialog | N
|
||||
next-button-props | Object | - | 用于自定义当前引导框的下一步按钮的内容。TS 类型:`ButtonProps` | N
|
||||
offset | Array | - | 相对于 placement 的偏移量[left, top],默认单位rpx,示例:[-10, 20] 或 ['10px', '8px'] 或 ['20rpx', '16rpx'] (仅当 `mode` 为 `popover` 时生效)。TS 类型:`Array<string \| number>` | N
|
||||
placement | String | 'top' | 引导框相对于高亮元素出现的位置,(仅当 `mode` 为 `popover` 时生效)。TS 类型:`StepPopoverPlacement ` `type StepPopoverPlacement = 'top'\|'left'\|'right'\|'bottom'\|'top-left'\|'top-right'\|'bottom-left'\|'bottom-right'\|'left-top'\|'left-bottom'\|'right-top'\|'right-bottom'\|'center'`。[详细类型定义](https://github.com/Tencent/tdesign-miniprogram/tree/develop/packages/uniapp-components/guide/type.ts) | N
|
||||
show-overlay | Boolean | true | 是否出现遮罩层 | N
|
||||
skip-button-props | Object | - | 用于自定义当前步骤引导框的跳过按钮的内容。TS 类型:`ButtonProps` | N
|
||||
title | String | - | 当前步骤的标题内容,支持插槽:slot="title-{{index}}" (1、当要显示body-{{index}}插槽时,请将title设置为空;2、当要显示content-{{index}}插槽完全自定义内容时,请将body和title都设置为空) | N
|
||||
|
||||
### CSS Variables
|
||||
|
||||
组件提供了下列 CSS 变量,可用于自定义样式。
|
||||
名称 | 默认值 | 描述
|
||||
-- | -- | --
|
||||
--td-guide-body-color | @text-color-secondary | -
|
||||
--td-guide-dialog-body-font | @font-body-large | -
|
||||
--td-guide-dialog-body-margin-top | 16rpx | -
|
||||
--td-guide-dialog-body-text-align | center | -
|
||||
--td-guide-dialog-border-radius | @radius-extraLarge | -
|
||||
--td-guide-dialog-footer-button-padding | 0 @spacer-3 | -
|
||||
--td-guide-dialog-padding | @spacer-3 0 | -
|
||||
--td-guide-dialog-title-font | @font-title-large | -
|
||||
--td-guide-dialog-title-text-align | center | -
|
||||
--td-guide-dialog-width | 622rpx | -
|
||||
--td-guide-footer-button-space | @spacer-1 | -
|
||||
--td-guide-footer-margin-top | @spacer-3 | -
|
||||
--td-guide-footer-text-align | right | -
|
||||
--td-guide-popover-bg-color | @bg-color-container | -
|
||||
--td-guide-popover-body-font | @font-body-medium | -
|
||||
--td-guide-popover-body-margin-top | 8rpx | -
|
||||
--td-guide-popover-body-text-align | left | -
|
||||
--td-guide-popover-border | 2rpx solid @component-border | -
|
||||
--td-guide-popover-border-radius | @radius-large | -
|
||||
--td-guide-popover-max-width | 540rpx | -
|
||||
--td-guide-popover-min-width | 480rpx | -
|
||||
--td-guide-popover-padding | @spacer-2 | -
|
||||
--td-guide-popover-shadow | @shadow-3 | -
|
||||
--td-guide-popover-title-font | @font-title-medium | -
|
||||
--td-guide-popover-title-text-align | left | -
|
||||
--td-guide-reference-border | 4rpx solid @brand-color | -
|
||||
--td-guide-reference-border-radius | @radius-default | -
|
||||
--td-guide-reference-mask-color | @font-gray-2 | -
|
||||
--td-guide-title-color | @text-color-primary | -
|
||||
325
uni_modules/tdesign-uniapp/components/guide/content.vue
Normal file
325
uni_modules/tdesign-uniapp/components/guide/content.vue
Normal file
@@ -0,0 +1,325 @@
|
||||
<template>
|
||||
<!-- #ifdef VUE2 -->
|
||||
<view>
|
||||
<!-- #endif -->
|
||||
<slot
|
||||
v-if="!title && !body"
|
||||
:name="'content-' + current"
|
||||
/>
|
||||
<block v-else>
|
||||
<view :class="tClassTooltip">
|
||||
<view
|
||||
v-if="title"
|
||||
:class="tClassTitle + ' ' + classPrefix + '__title--' + modeType"
|
||||
>
|
||||
{{ title }}
|
||||
</view>
|
||||
<slot
|
||||
v-else
|
||||
:name="'title-' + current"
|
||||
/>
|
||||
<view
|
||||
v-if="body"
|
||||
:class="tClassBody + ' ' + classPrefix + '__body--' + modeType"
|
||||
>
|
||||
{{ body }}
|
||||
</view>
|
||||
<slot
|
||||
v-else
|
||||
:name="'body-' + current"
|
||||
/>
|
||||
</view>
|
||||
<view
|
||||
v-if="current !== -1"
|
||||
:class="tClassFooter + ' ' + classPrefix + '__footer ' + classPrefix + '__footer--' + modeType"
|
||||
>
|
||||
<block
|
||||
v-if="current < steps.length - 1 && !hideSkip"
|
||||
name="button"
|
||||
>
|
||||
<t-button
|
||||
:t-id="skipButton.tId"
|
||||
:custom-style="skipButton.style"
|
||||
:block="skipButton.block"
|
||||
:t-class="useVirtualHost ? skipButton.tClass : ''"
|
||||
:class="!useVirtualHost ? skipButton.tClass : ''"
|
||||
:disabled="skipButton.disabled"
|
||||
:data-type="skipButton.dataType"
|
||||
:data-extra="skipButton.dataExtra"
|
||||
:custom-dataset="skipButton.customDataset"
|
||||
:content="skipButton.content"
|
||||
:icon="skipButton.icon"
|
||||
:loading="skipButton.loading"
|
||||
:loading-props="skipButton.loadingProps"
|
||||
:theme="skipButton.theme"
|
||||
:ghost="skipButton.ghost"
|
||||
:shape="skipButton.shape"
|
||||
:size="skipButton.size"
|
||||
:variant="skipButton.variant"
|
||||
:open-type="skipButton.openType"
|
||||
:hover-class="skipButton.hoverClass"
|
||||
:hover-stop-propagation="skipButton.hoverStopPropagation"
|
||||
:hover-start-time="skipButton.hoverStartTime"
|
||||
:hover-stay-time="skipButton.hoverStayTime"
|
||||
:lang="skipButton.lang"
|
||||
:session-from="skipButton.sessionFrom"
|
||||
:send-message-title="skipButton.sendMessageTitle"
|
||||
:send-message-path="skipButton.sendMessagePath"
|
||||
:send-message-img="skipButton.sendMessageImg"
|
||||
:app-parameter="skipButton.appParameter"
|
||||
:show-message-card="skipButton.showMessageCard"
|
||||
:aria-label="skipButton.ariaLabel"
|
||||
@click="(e) => onTplButtonTap(e, { type: skipButton.type })"
|
||||
@getuserinfo="(e) => onTplButtonTap(e, { type: skipButton.type })"
|
||||
@contact="(e) => onTplButtonTap(e, { type: skipButton.type })"
|
||||
@getphonenumber="(e) => onTplButtonTap(e, { type: skipButton.type })"
|
||||
@error="(e) => onTplButtonTap(e, { type: skipButton.type })"
|
||||
@opensetting="(e) => onTplButtonTap(e, { type: skipButton.type })"
|
||||
@launchapp="(e) => onTplButtonTap(e, { type: skipButton.type })"
|
||||
@agreeprivacyauthorization="(e) => onTplButtonTap(e, { type: skipButton.type })"
|
||||
/>
|
||||
</block>
|
||||
<block
|
||||
v-else-if="current === steps.length - 1 && !hideBack"
|
||||
name="button"
|
||||
>
|
||||
<t-button
|
||||
:t-id="backButton.tId"
|
||||
:custom-style="backButton.style"
|
||||
:block="backButton.block"
|
||||
:t-class="useVirtualHost ? backButton.tClass : ''"
|
||||
:class="!useVirtualHost ? backButton.tClass : ''"
|
||||
:disabled="backButton.disabled"
|
||||
:data-type="backButton.dataType"
|
||||
:data-extra="backButton.dataExtra"
|
||||
:custom-dataset="backButton.customDataset"
|
||||
:content="backButton.content"
|
||||
:icon="backButton.icon"
|
||||
:loading="backButton.loading"
|
||||
:loading-props="backButton.loadingProps"
|
||||
:theme="backButton.theme"
|
||||
:ghost="backButton.ghost"
|
||||
:shape="backButton.shape"
|
||||
:size="backButton.size"
|
||||
:variant="backButton.variant"
|
||||
:open-type="backButton.openType"
|
||||
:hover-class="backButton.hoverClass"
|
||||
:hover-stop-propagation="backButton.hoverStopPropagation"
|
||||
:hover-start-time="backButton.hoverStartTime"
|
||||
:hover-stay-time="backButton.hoverStayTime"
|
||||
:lang="backButton.lang"
|
||||
:session-from="backButton.sessionFrom"
|
||||
:send-message-title="backButton.sendMessageTitle"
|
||||
:send-message-path="backButton.sendMessagePath"
|
||||
:send-message-img="backButton.sendMessageImg"
|
||||
:app-parameter="backButton.appParameter"
|
||||
:show-message-card="backButton.showMessageCard"
|
||||
:aria-label="backButton.ariaLabel"
|
||||
@click="(e) => onTplButtonTap(e, { type: backButton.type })"
|
||||
@getuserinfo="(e) => onTplButtonTap(e, { type: backButton.type })"
|
||||
@contact="(e) => onTplButtonTap(e, { type: backButton.type })"
|
||||
@getphonenumber="(e) => onTplButtonTap(e, { type: backButton.type })"
|
||||
@error="(e) => onTplButtonTap(e, { type: backButton.type })"
|
||||
@opensetting="(e) => onTplButtonTap(e, { type: backButton.type })"
|
||||
@launchapp="(e) => onTplButtonTap(e, { type: backButton.type })"
|
||||
@agreeprivacyauthorization="(e) => onTplButtonTap(e, { type: backButton.type })"
|
||||
/>
|
||||
</block>
|
||||
<block
|
||||
v-if="current < steps.length - 1"
|
||||
name="button"
|
||||
>
|
||||
<t-button
|
||||
:t-id="nextButton.tId"
|
||||
:custom-style="nextButton.style"
|
||||
:block="nextButton.block"
|
||||
:t-class="useVirtualHost ? nextButton.tClass : ''"
|
||||
:class="!useVirtualHost ? nextButton.tClass : ''"
|
||||
:disabled="nextButton.disabled"
|
||||
:data-type="nextButton.dataType"
|
||||
:data-extra="nextButton.dataExtra"
|
||||
:custom-dataset="nextButton.customDataset"
|
||||
:content="nextButton.content"
|
||||
:icon="nextButton.icon"
|
||||
:loading="nextButton.loading"
|
||||
:loading-props="nextButton.loadingProps"
|
||||
:theme="nextButton.theme"
|
||||
:ghost="nextButton.ghost"
|
||||
:shape="nextButton.shape"
|
||||
:size="nextButton.size"
|
||||
:variant="nextButton.variant"
|
||||
:open-type="nextButton.openType"
|
||||
:hover-class="nextButton.hoverClass"
|
||||
:hover-stop-propagation="nextButton.hoverStopPropagation"
|
||||
:hover-start-time="nextButton.hoverStartTime"
|
||||
:hover-stay-time="nextButton.hoverStayTime"
|
||||
:lang="nextButton.lang"
|
||||
:session-from="nextButton.sessionFrom"
|
||||
:send-message-title="nextButton.sendMessageTitle"
|
||||
:send-message-path="nextButton.sendMessagePath"
|
||||
:send-message-img="nextButton.sendMessageImg"
|
||||
:app-parameter="nextButton.appParameter"
|
||||
:show-message-card="nextButton.showMessageCard"
|
||||
:aria-label="nextButton.ariaLabel"
|
||||
@click="(e) => onTplButtonTap(e, { type: nextButton.type })"
|
||||
@getuserinfo="(e) => onTplButtonTap(e, { type: nextButton.type })"
|
||||
@contact="(e) => onTplButtonTap(e, { type: nextButton.type })"
|
||||
@getphonenumber="(e) => onTplButtonTap(e, { type: nextButton.type })"
|
||||
@error="(e) => onTplButtonTap(e, { type: nextButton.type })"
|
||||
@opensetting="(e) => onTplButtonTap(e, { type: nextButton.type })"
|
||||
@launchapp="(e) => onTplButtonTap(e, { type: nextButton.type })"
|
||||
@agreeprivacyauthorization="(e) => onTplButtonTap(e, { type: nextButton.type })"
|
||||
/>
|
||||
</block>
|
||||
<block
|
||||
v-else
|
||||
name="button"
|
||||
>
|
||||
<t-button
|
||||
:t-id="finishButton.tId"
|
||||
:custom-style="finishButton.style"
|
||||
:block="finishButton.block"
|
||||
:t-class="useVirtualHost ? finishButton.tClass : ''"
|
||||
:class="!useVirtualHost ? finishButton.tClass : ''"
|
||||
:disabled="finishButton.disabled"
|
||||
:data-type="finishButton.dataType"
|
||||
:data-extra="finishButton.dataExtra"
|
||||
:custom-dataset="finishButton.customDataset"
|
||||
:content="finishButton.content"
|
||||
:icon="finishButton.icon"
|
||||
:loading="finishButton.loading"
|
||||
:loading-props="finishButton.loadingProps"
|
||||
:theme="finishButton.theme"
|
||||
:ghost="finishButton.ghost"
|
||||
:shape="finishButton.shape"
|
||||
:size="finishButton.size"
|
||||
:variant="finishButton.variant"
|
||||
:open-type="finishButton.openType"
|
||||
:hover-class="finishButton.hoverClass"
|
||||
:hover-stop-propagation="finishButton.hoverStopPropagation"
|
||||
:hover-start-time="finishButton.hoverStartTime"
|
||||
:hover-stay-time="finishButton.hoverStayTime"
|
||||
:lang="finishButton.lang"
|
||||
:session-from="finishButton.sessionFrom"
|
||||
:send-message-title="finishButton.sendMessageTitle"
|
||||
:send-message-path="finishButton.sendMessagePath"
|
||||
:send-message-img="finishButton.sendMessageImg"
|
||||
:app-parameter="finishButton.appParameter"
|
||||
:show-message-card="finishButton.showMessageCard"
|
||||
:aria-label="finishButton.ariaLabel"
|
||||
@click="(e) => onTplButtonTap(e, { type: finishButton.type })"
|
||||
@getuserinfo="(e) => onTplButtonTap(e, { type: finishButton.type })"
|
||||
@contact="(e) => onTplButtonTap(e, { type: finishButton.type })"
|
||||
@getphonenumber="(e) => onTplButtonTap(e, { type: finishButton.type })"
|
||||
@error="(e) => onTplButtonTap(e, { type: finishButton.type })"
|
||||
@opensetting="(e) => onTplButtonTap(e, { type: finishButton.type })"
|
||||
@launchapp="(e) => onTplButtonTap(e, { type: finishButton.type })"
|
||||
@agreeprivacyauthorization="(e) => onTplButtonTap(e, { type: finishButton.type })"
|
||||
/>
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
<!-- #ifdef VUE2 -->
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
<script>
|
||||
import TButton from '../button/button.vue';
|
||||
import { canUseVirtualHost } from '../common/version';
|
||||
|
||||
|
||||
export default {
|
||||
options: {
|
||||
styleIsolation: 'shared',
|
||||
},
|
||||
components: {
|
||||
TButton,
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
body: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
current: {
|
||||
type: [String, Number],
|
||||
default: '',
|
||||
},
|
||||
classPrefix: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
prefix: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
tClassTooltip: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
tClassBody: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
tClassTitle: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
tClassFooter: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
skipButton: {
|
||||
type: [Object, null],
|
||||
default: null,
|
||||
},
|
||||
backButton: {
|
||||
type: [Object, null],
|
||||
default: null,
|
||||
},
|
||||
nextButton: {
|
||||
type: [Object, null],
|
||||
default: null,
|
||||
},
|
||||
finishButton: {
|
||||
type: [Object, null],
|
||||
default: null,
|
||||
},
|
||||
modeType: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
hideSkip: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
hideBack: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
steps: {
|
||||
type: Array,
|
||||
default: () => ([]),
|
||||
},
|
||||
},
|
||||
emits: [
|
||||
'onTplButtonTap',
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
useVirtualHost: canUseVirtualHost(),
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onTplButtonTap(...args) {
|
||||
this.$emit('onTplButtonTap', ...args);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
@import './guide.css';
|
||||
</style>
|
||||
64
uni_modules/tdesign-uniapp/components/guide/guide.css
Normal file
64
uni_modules/tdesign-uniapp/components/guide/guide.css
Normal file
@@ -0,0 +1,64 @@
|
||||
.t-guide__reference {
|
||||
position: absolute;
|
||||
box-shadow: 0 0 0 0 var(--td-guide-reference-mask-color, var(--td-font-gray-2, rgba(0, 0, 0, 0.6))), var(--td-guide-reference-mask-color, var(--td-font-gray-2, rgba(0, 0, 0, 0.6))) 0 0 0 5000px;
|
||||
border-radius: var(--td-guide-reference-border-radius, var(--td-radius-default, 12rpx));
|
||||
transition: all var(--td-anim-duration-base, 0.2s) var(--td-anim-time-fn-ease-out, cubic-bezier(0, 0, 0.15, 1));
|
||||
}
|
||||
.t-guide__reference--nonoverlay {
|
||||
box-shadow: none;
|
||||
border: var(--td-guide-reference-border, 4rpx solid var(--td-brand-color, var(--td-primary-color-7, #0052d9)));
|
||||
}
|
||||
.t-guide__container {
|
||||
display: inline-block;
|
||||
}
|
||||
.t-guide__container--popover {
|
||||
background-color: var(--td-guide-popover-bg-color, var(--td-bg-color-container, var(--td-font-white-1, #ffffff)));
|
||||
border: var(--td-guide-popover-border, 2rpx solid var(--td-component-border, var(--td-gray-color-4, #dcdcdc)));
|
||||
border-radius: var(--td-guide-popover-border-radius, var(--td-radius-large, 18rpx));
|
||||
box-shadow: var(--td-guide-popover-shadow, var(--td-shadow-3, 0 6px 30px 5px rgba(0, 0, 0, 0.05), 0 16px 24px 2px rgba(0, 0, 0, 0.04), 0 8px 10px -5px rgba(0, 0, 0, 0.08)));
|
||||
padding: var(--td-guide-popover-padding, var(--td-spacer-2, 32rpx));
|
||||
min-width: var(--td-guide-popover-min-width, 480rpx);
|
||||
max-width: var(--td-guide-popover-max-width, 540rpx);
|
||||
}
|
||||
.t-guide__container--dialog {
|
||||
background-color: var(--td-guide-popover-bg-color, var(--td-bg-color-container, var(--td-font-white-1, #ffffff)));
|
||||
border-radius: var(--td-guide-dialog-border-radius, var(--td-radius-extraLarge, 24rpx));
|
||||
padding: var(--td-guide-dialog-padding, var(--td-spacer-3, 48rpx) 0);
|
||||
width: var(--td-guide-dialog-width, 622rpx);
|
||||
}
|
||||
.t-guide__title--popover {
|
||||
text-align: var(--td-guide-popover-title-text-align, left);
|
||||
color: var(--td-guide-title-color, var(--td-text-color-primary, var(--td-font-gray-1, rgba(0, 0, 0, 0.9))));
|
||||
font: var(--td-guide-popover-title-font, var(--td-font-title-medium, 600 32rpx / 48rpx var(--td-font-family, PingFang SC, Microsoft YaHei, Arial Regular)));
|
||||
}
|
||||
.t-guide__title--dialog {
|
||||
text-align: var(--td-guide-dialog-title-text-align, center);
|
||||
color: var(--td-guide-title-color, var(--td-text-color-primary, var(--td-font-gray-1, rgba(0, 0, 0, 0.9))));
|
||||
font: var(--td-guide-dialog-title-font, var(--td-font-title-large, 600 36rpx / 52rpx var(--td-font-family, PingFang SC, Microsoft YaHei, Arial Regular)));
|
||||
}
|
||||
.t-guide__body--popover {
|
||||
margin-top: var(--td-guide-popover-body-margin-top, 8rpx);
|
||||
text-align: var(--td-guide-popover-body-text-align, left);
|
||||
color: var(--td-guide-body-color, var(--td-text-color-secondary, var(--td-font-gray-2, rgba(0, 0, 0, 0.6))));
|
||||
font: var(--td-guide-popover-body-font, var(--td-font-body-medium, 28rpx / 44rpx var(--td-font-family, PingFang SC, Microsoft YaHei, Arial Regular)));
|
||||
}
|
||||
.t-guide__body--dialog {
|
||||
margin-top: var(--td-guide-dialog-body-margin-top, 16rpx);
|
||||
text-align: var(--td-guide-dialog-body-text-align, center);
|
||||
color: var(--td-guide-body-color, var(--td-text-color-secondary, var(--td-font-gray-2, rgba(0, 0, 0, 0.6))));
|
||||
font: var(--td-guide-dialog-body-font, var(--td-font-body-large, 32rpx / 48rpx var(--td-font-family, PingFang SC, Microsoft YaHei, Arial Regular)));
|
||||
}
|
||||
.t-guide__footer {
|
||||
text-align: var(--td-guide-footer-text-align, right);
|
||||
margin-top: var(--td-guide-footer-margin-top, var(--td-spacer-3, 48rpx));
|
||||
}
|
||||
.t-guide__footer :deep(.t-guide__button + .t-guide__button) {
|
||||
margin-left: var(--td-guide-footer-button-space, var(--td-spacer-1, 24rpx));
|
||||
}
|
||||
.t-guide__footer--dialog {
|
||||
display: flex;
|
||||
padding: var(--td-guide-dialog-footer-button-padding, 0 var(--td-spacer-3, 48rpx));
|
||||
}
|
||||
.t-guide__footer--dialog :deep(.t-guide__button:last-child) {
|
||||
flex-grow: 1;
|
||||
}
|
||||
544
uni_modules/tdesign-uniapp/components/guide/guide.vue
Normal file
544
uni_modules/tdesign-uniapp/components/guide/guide.vue
Normal file
@@ -0,0 +1,544 @@
|
||||
<template>
|
||||
<view>
|
||||
<t-overlay
|
||||
v-if="modeType === 'popover'"
|
||||
:visible="visible"
|
||||
:using-custom-navbar="usingCustomNavbar"
|
||||
:custom-navbar-height="customNavbarHeight"
|
||||
background-color="transparent"
|
||||
:z-index="zIndex"
|
||||
>
|
||||
<view :class="tClass + ' ' + classPrefix">
|
||||
<view
|
||||
:class="tClassReference + ' ' + classPrefix + '__reference ' + (nonOverlay ? classPrefix + '__reference--nonoverlay' : '')"
|
||||
:style="referenceStyle"
|
||||
/>
|
||||
<view
|
||||
:class="tClassPopover + ' ' + classPrefix + '__container ' + (title || body ? classPrefix + '__container--' + modeType : '')"
|
||||
:style="popoverStyle"
|
||||
>
|
||||
<ContentComp
|
||||
:title="title"
|
||||
:body="body"
|
||||
:current="_current"
|
||||
:class-prefix="classPrefix"
|
||||
:prefix="prefix"
|
||||
:skip-button="skipButton"
|
||||
:back-button="backButton"
|
||||
:next-button="nextButton"
|
||||
:finish-button="finishButton"
|
||||
:mode-type="modeType"
|
||||
:hide-skip="hideSkip"
|
||||
:hide-back="hideBack"
|
||||
:steps="steps"
|
||||
:t-class-tooltip="tClassTooltip"
|
||||
:t-class-body="tClassBody"
|
||||
:t-class-title="tClassTitle"
|
||||
:t-class-footer="tClassFooter"
|
||||
@onTplButtonTap="onTplButtonTap"
|
||||
>
|
||||
<template #content-0>
|
||||
<slot name="content-0" />
|
||||
</template>
|
||||
<template #content-1>
|
||||
<slot name="content-1" />
|
||||
</template>
|
||||
<template #content-2>
|
||||
<slot name="content-2" />
|
||||
</template>
|
||||
<template #content-3>
|
||||
<slot name="content-3" />
|
||||
</template>
|
||||
<template #content-4>
|
||||
<slot name="content-4" />
|
||||
</template>
|
||||
<template #content-5>
|
||||
<slot name="content-5" />
|
||||
</template>
|
||||
<template #content-6>
|
||||
<slot name="content-6" />
|
||||
</template>
|
||||
|
||||
<template #title-0>
|
||||
<slot name="title-0" />
|
||||
</template>
|
||||
<template #title-1>
|
||||
<slot name="title-1" />
|
||||
</template>
|
||||
<template #title-2>
|
||||
<slot name="title-2" />
|
||||
</template>
|
||||
<template #title-3>
|
||||
<slot name="title-3" />
|
||||
</template>
|
||||
<template #title-4>
|
||||
<slot name="title-4" />
|
||||
</template>
|
||||
<template #title-5>
|
||||
<slot name="title-5" />
|
||||
</template>
|
||||
<template #title-6>
|
||||
<slot name="title-6" />
|
||||
</template>
|
||||
|
||||
<template #body-0>
|
||||
<slot name="body-0" />
|
||||
</template>
|
||||
<template #body-1>
|
||||
<slot name="body-1" />
|
||||
</template>
|
||||
<template #body-2>
|
||||
<slot name="body-2" />
|
||||
</template>
|
||||
<template #body-3>
|
||||
<slot name="body-3" />
|
||||
</template>
|
||||
<template #body-4>
|
||||
<slot name="body-4" />
|
||||
</template>
|
||||
<template #body-5>
|
||||
<slot name="body-5" />
|
||||
</template>
|
||||
<template #body-6>
|
||||
<slot name="body-6" />
|
||||
</template>
|
||||
</ContentComp>
|
||||
</view>
|
||||
</view>
|
||||
</t-overlay>
|
||||
<t-popup
|
||||
v-else-if="modeType === 'dialog'"
|
||||
:visible="visible"
|
||||
:show-overlay="!nonOverlay"
|
||||
:using-custom-navbar="usingCustomNavbar"
|
||||
:custom-navbar-height="customNavbarHeight"
|
||||
:z-index="zIndex"
|
||||
placement="center"
|
||||
>
|
||||
<view :class="tClass + ' ' + classPrefix">
|
||||
<view :class="tClassPopover + ' ' + classPrefix + '__container ' + (title || body ? classPrefix + '__container--' + modeType : '')">
|
||||
<ContentComp
|
||||
:title="title"
|
||||
:body="body"
|
||||
:current="_current"
|
||||
:class-prefix="classPrefix"
|
||||
:prefix="prefix"
|
||||
:skip-button="skipButton"
|
||||
:back-button="backButton"
|
||||
:next-button="nextButton"
|
||||
:finish-button="finishButton"
|
||||
:mode-type="modeType"
|
||||
:hide-skip="hideSkip"
|
||||
:hide-back="hideBack"
|
||||
:steps="steps"
|
||||
:t-class-tooltip="tClassTooltip"
|
||||
:t-class-body="tClassBody"
|
||||
:t-class-title="tClassTitle"
|
||||
:t-class-footer="tClassFooter"
|
||||
@onTplButtonTap="onTplButtonTap"
|
||||
>
|
||||
<template #content-0>
|
||||
<slot name="content-0" />
|
||||
</template>
|
||||
<template #content-1>
|
||||
<slot name="content-1" />
|
||||
</template>
|
||||
<template #content-2>
|
||||
<slot name="content-2" />
|
||||
</template>
|
||||
<template #content-3>
|
||||
<slot name="content-3" />
|
||||
</template>
|
||||
<template #content-4>
|
||||
<slot name="content-4" />
|
||||
</template>
|
||||
<template #content-5>
|
||||
<slot name="content-5" />
|
||||
</template>
|
||||
<template #content-6>
|
||||
<slot name="content-6" />
|
||||
</template>
|
||||
|
||||
<template #title-0>
|
||||
<slot name="title-0" />
|
||||
</template>
|
||||
<template #title-1>
|
||||
<slot name="title-1" />
|
||||
</template>
|
||||
<template #title-2>
|
||||
<slot name="title-2" />
|
||||
</template>
|
||||
<template #title-3>
|
||||
<slot name="title-3" />
|
||||
</template>
|
||||
<template #title-4>
|
||||
<slot name="title-4" />
|
||||
</template>
|
||||
<template #title-5>
|
||||
<slot name="title-5" />
|
||||
</template>
|
||||
<template #title-6>
|
||||
<slot name="title-6" />
|
||||
</template>
|
||||
|
||||
<template #body-0>
|
||||
<slot name="body-0" />
|
||||
</template>
|
||||
<template #body-1>
|
||||
<slot name="body-1" />
|
||||
</template>
|
||||
<template #body-2>
|
||||
<slot name="body-2" />
|
||||
</template>
|
||||
<template #body-3>
|
||||
<slot name="body-3" />
|
||||
</template>
|
||||
<template #body-4>
|
||||
<slot name="body-4" />
|
||||
</template>
|
||||
<template #body-5>
|
||||
<slot name="body-5" />
|
||||
</template>
|
||||
<template #body-6>
|
||||
<slot name="body-6" />
|
||||
</template>
|
||||
</ContentComp>
|
||||
</view>
|
||||
</view>
|
||||
</t-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import TOverlay from '../overlay/overlay';
|
||||
import TButton from '../button/button';
|
||||
import TPopup from '../popup/popup';
|
||||
import { uniComponent } from '../common/src/index';
|
||||
import props from './props';
|
||||
import { prefix } from '../common/config';
|
||||
import { isFunction, isNumeric } from '../common/validator';
|
||||
import { debounce, getRect, rpx2px, styles, unitConvert, nextTick, systemInfo, coalesce } from '../common/utils';
|
||||
import ContentComp from './content.vue';
|
||||
|
||||
import useCustomNavbar from '../mixins/using-custom-navbar';
|
||||
|
||||
const name = `${prefix}-guide`;
|
||||
|
||||
let that;
|
||||
|
||||
export default uniComponent({
|
||||
name,
|
||||
options: {
|
||||
styleIsolation: 'shared',
|
||||
},
|
||||
controlledProps: [
|
||||
{
|
||||
key: 'current',
|
||||
event: 'change',
|
||||
},
|
||||
],
|
||||
externalClasses: [
|
||||
`${prefix}-class`,
|
||||
`${prefix}-class-reference`,
|
||||
`${prefix}-class-popover`,
|
||||
|
||||
`${prefix}-class-tooltip`,
|
||||
`${prefix}-class-title`,
|
||||
`${prefix}-class-body`,
|
||||
`${prefix}-class-footer`,
|
||||
|
||||
`${prefix}-class-skip`,
|
||||
`${prefix}-class-next`,
|
||||
`${prefix}-class-back`,
|
||||
`${prefix}-class-finish`,
|
||||
],
|
||||
mixins: [
|
||||
useCustomNavbar,
|
||||
],
|
||||
components: {
|
||||
TOverlay,
|
||||
TButton,
|
||||
TPopup,
|
||||
ContentComp,
|
||||
},
|
||||
props: {
|
||||
...props,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
prefix,
|
||||
classPrefix: name,
|
||||
visible: false,
|
||||
_current: -1,
|
||||
_steps: [],
|
||||
referenceStyle: '',
|
||||
popoverStyle: '',
|
||||
title: '',
|
||||
body: '',
|
||||
nonOverlay: false,
|
||||
modeType: '',
|
||||
|
||||
skipButton: {},
|
||||
backButton: {},
|
||||
nextButton: {},
|
||||
finishButton: {},
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
steps: {
|
||||
handler() {
|
||||
this._init();
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
current: {
|
||||
handler(v) {
|
||||
this._current = v;
|
||||
},
|
||||
},
|
||||
_current: '_init',
|
||||
showOverlay: '_init',
|
||||
},
|
||||
created() {
|
||||
that = this;
|
||||
// this._init =
|
||||
this._getPlacement = this.getPlacement();
|
||||
},
|
||||
mounted() {
|
||||
this._init();
|
||||
},
|
||||
methods: {
|
||||
_init: debounce(() => that.init(), 20),
|
||||
async init() {
|
||||
console.log('doing init');
|
||||
const { steps } = this;
|
||||
const { _current } = this;
|
||||
const step = steps[_current];
|
||||
if (!step) {
|
||||
this.visible = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const modeType = (coalesce(step.mode, this.mode)) === 'dialog' ? 'dialog' : 'popover';
|
||||
const showOverlay = coalesce(step.showOverlay, this.showOverlay);
|
||||
this.nonOverlay = !showOverlay;
|
||||
this.modeType = modeType;
|
||||
|
||||
|
||||
// if (current === _current) return;
|
||||
if (modeType === 'popover') {
|
||||
const rect = await step.element();
|
||||
console.log('rect', rect);
|
||||
if (!rect) return;
|
||||
const highlightPadding = rpx2px(coalesce(step.highlightPadding, this.highlightPadding));
|
||||
const referenceTop = rect.top - highlightPadding;
|
||||
const referenceRight = systemInfo.windowWidth - rect.right - highlightPadding;
|
||||
const referenceLeft = rect.left - highlightPadding;
|
||||
const referenceWidth = rect.width + 2 * highlightPadding;
|
||||
const referenceHeight = rect.height + 2 * highlightPadding;
|
||||
|
||||
const style = {
|
||||
top: `${referenceTop}px`,
|
||||
right: `${referenceRight}px`,
|
||||
left: `${referenceLeft}px`,
|
||||
width: `${referenceWidth}px`,
|
||||
height: `${referenceHeight}px`,
|
||||
};
|
||||
this._steps = this.steps;
|
||||
// this._current = this.current;
|
||||
this.visible = true;
|
||||
this.referenceStyle = styles(style);
|
||||
this.title = coalesce(step.title, '');
|
||||
this.body = coalesce(step.body, '');
|
||||
this.makeButtonProps(step, 'popover');
|
||||
|
||||
const popoverStyle = await this.placementOffset(step, style);
|
||||
this.popoverStyle = popoverStyle;
|
||||
} else {
|
||||
this._steps = this.steps;
|
||||
// this._current = this.current;
|
||||
this.visible = true;
|
||||
this.title = coalesce(step.title, '');
|
||||
this.body = coalesce(step.body, '');
|
||||
this.makeButtonProps(step, 'dialog');
|
||||
}
|
||||
},
|
||||
async placementOffset({ placement, offset }, place) {
|
||||
await nextTick();
|
||||
const rect = await getRect(this, `.${name}__container`);
|
||||
const style = this._getPlacement[placement]?.(rect, place, offset);
|
||||
return styles({ position: 'absolute', ...style });
|
||||
},
|
||||
makeButtonProps(step, mode) {
|
||||
const {
|
||||
tClassSkip,
|
||||
tClassNext,
|
||||
tClassBack,
|
||||
tClassFinish,
|
||||
} = this;
|
||||
let skipButton = coalesce(step.skipButtonProps, this.skipButtonProps);
|
||||
const size = mode === 'popover' ? 'extra-small' : 'medium';
|
||||
skipButton = {
|
||||
theme: 'light',
|
||||
content: '跳过',
|
||||
size,
|
||||
...skipButton,
|
||||
tClass: `${tClassSkip} ${name}__button ${skipButton?.class || ''}`,
|
||||
type: 'skip',
|
||||
};
|
||||
let nextButton = coalesce(step.nextButtonProps, this.nextButtonProps);
|
||||
nextButton = {
|
||||
theme: 'primary',
|
||||
content: '下一步',
|
||||
size,
|
||||
...nextButton,
|
||||
tClass: `${tClassNext} ${name}__button ${nextButton?.class || ''}`,
|
||||
type: 'next',
|
||||
};
|
||||
nextButton = { ...nextButton, content: this.buttonContent(nextButton) };
|
||||
let backButton = coalesce(step.backButtonProps, this.backButtonProps);
|
||||
backButton = {
|
||||
theme: 'light',
|
||||
content: '返回',
|
||||
size,
|
||||
...backButton,
|
||||
tClass: `${tClassBack} ${name}__button ${backButton?.class || ''}`,
|
||||
type: 'back',
|
||||
};
|
||||
let finishButton = coalesce(step.finishButtonProps, this.finishButtonProps);
|
||||
finishButton = {
|
||||
theme: 'primary',
|
||||
content: '完成',
|
||||
size,
|
||||
...finishButton,
|
||||
tClass: `${tClassFinish} ${name}__button ${finishButton?.class || ''}`,
|
||||
type: 'finish',
|
||||
};
|
||||
finishButton = { ...finishButton, content: this.buttonContent(finishButton) };
|
||||
|
||||
this.skipButton = skipButton;
|
||||
this.nextButton = nextButton;
|
||||
this.backButton = backButton;
|
||||
this.finishButton = finishButton;
|
||||
},
|
||||
renderCounter() {
|
||||
const { steps, _current, counter } = this;
|
||||
const stepsTotal = steps.length;
|
||||
const innerCurrent = _current + 1;
|
||||
const popupSlotCounter = isFunction(counter) ? counter({ total: stepsTotal, current: innerCurrent }) : counter;
|
||||
return counter ? popupSlotCounter : `(${innerCurrent}/${stepsTotal})`;
|
||||
},
|
||||
buttonContent(button) {
|
||||
const { hideCounter } = this;
|
||||
return `${button.content.replace(/ \(.*?\)/, '')} ${hideCounter ? '' : this.renderCounter()}`;
|
||||
},
|
||||
onTplButtonTap(e, { type }) {
|
||||
console.log('onTplButtonTap.type', type);
|
||||
const params = { e, current: this._current, total: this.steps.length };
|
||||
switch (type) {
|
||||
case 'next':
|
||||
this.$emit('next-step-click', { next: this._current + 1, ...params });
|
||||
// this.setData({ current: this..current + 1 });
|
||||
this._current = this._current + 1;
|
||||
break;
|
||||
case 'skip':
|
||||
this.$emit('skip', params);
|
||||
// this.setData({ current: -1 });
|
||||
this._current = -1;
|
||||
break;
|
||||
case 'back':
|
||||
this.$emit('back', params);
|
||||
// this.setData({ current: 0 });
|
||||
this._current = 0;
|
||||
break;
|
||||
case 'finish':
|
||||
this.$emit('finish', params);
|
||||
// this.setData({ current: -1 });
|
||||
this._current = -1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
console.log('_current', this._current);
|
||||
this.$emit('change', { current: this._current });
|
||||
},
|
||||
getPlacement() {
|
||||
const space = rpx2px(32);
|
||||
const offsetLeft = offset => unitConvert(isNumeric(offset?.[0]) ? `${offset?.[0]}rpx` : offset?.[0] || 0);
|
||||
const offsetTop = offset => unitConvert(isNumeric(offset?.[1]) ? `${offset?.[1]}rpx` : offset?.[1] || 0);
|
||||
const left = place => parseFloat(place.left);
|
||||
const right = place => parseFloat(place.right);
|
||||
const top = place => parseFloat(place.top);
|
||||
const height = place => parseFloat(place.height);
|
||||
const width = place => parseFloat(place.width);
|
||||
return {
|
||||
center: (rect, place, offset) => ({
|
||||
top: `${Math.max(height(place) + top(place) + space + offsetTop(offset), 1)}px`,
|
||||
left: `${Math.max(width(place) / 2 + left(place) - rect.width / 2 + offsetLeft(offset), 1)}px`,
|
||||
}),
|
||||
bottom: (rect, place, offset) => ({
|
||||
top: `${Math.max(height(place) + top(place) + space + offsetTop(offset), 1)}px`,
|
||||
left: `${Math.max(width(place) / 2 + left(place) - rect.width / 2 + offsetLeft(offset), 1)}px`,
|
||||
}),
|
||||
'bottom-left': (rect, place, offset) => ({
|
||||
top: `${Math.max(height(place) + top(place) + space + offsetTop(offset), 1)}px`,
|
||||
left: `${Math.max(left(place) + offsetLeft(offset), 1)}px`,
|
||||
}),
|
||||
'bottom-right': (rect, place, offset) => ({
|
||||
top: `${Math.max(height(place) + top(place) + space + offsetTop(offset), 1)}px`,
|
||||
right: `${Math.max(right(place) - offsetLeft(offset), 1)}px`,
|
||||
}),
|
||||
left: (rect, place, offset) => ({
|
||||
top: `${Math.max(height(place) / 2 + top(place) - rect.height / 2 + offsetTop(offset), 1)}px`,
|
||||
right: `${Math.max(width(place) + right(place) + space - offsetLeft(offset), 1)}px`,
|
||||
}),
|
||||
'left-top': (rect, place, offset) => ({
|
||||
top: `${Math.max(top(place) + offsetTop(offset), 1)}px`,
|
||||
right: `${Math.max(width(place) + right(place) + space - offsetLeft(offset), 1)}px`,
|
||||
}),
|
||||
'left-bottom': (rect, place, offset) => ({
|
||||
top: `${Math.max(top(place) + height(place) - rect.height - offsetTop(offset), 1)}px`,
|
||||
right: `${Math.max(width(place) + right(place) + space - offsetLeft(offset), 1)}px`,
|
||||
}),
|
||||
right: (rect, place, offset) => ({
|
||||
top: `${Math.max(height(place) / 2 + top(place) - rect.height / 2 + offsetTop(offset), 1)}px`,
|
||||
left: `${Math.max(left(place) + width(place) + space + offsetLeft(offset), 1)}px`,
|
||||
}),
|
||||
'right-top': (rect, place, offset) => ({
|
||||
top: `${Math.max(top(place) + offsetTop(offset), 1)}px`,
|
||||
left: `${Math.max(left(place) + width(place) + space + offsetLeft(offset), 1)}px`,
|
||||
}),
|
||||
'right-bottom': (rect, place, offset) => ({
|
||||
top: `${Math.max(top(place) + height(place) - rect.height - offsetTop(offset), 1)}px`,
|
||||
left: `${Math.max(left(place) + width(place) + space + offsetLeft(offset), 1)}px`,
|
||||
}),
|
||||
top: (rect, place, offset) => ({
|
||||
top: `${Math.max(top(place) - rect.height - space + offsetTop(offset), 1)}px`,
|
||||
left: `${Math.max(width(place) / 2 + left(place) - rect.width / 2 + offsetLeft(offset), 1)}px`,
|
||||
}),
|
||||
'top-left': (rect, place, offset) => ({
|
||||
top: `${Math.max(top(place) - rect.height - space + offsetTop(offset), 1)}px`,
|
||||
left: `${Math.max(left(place) + offsetLeft(offset), 1)}px`,
|
||||
}),
|
||||
'top-right': (rect, place, offset) => ({
|
||||
top: `${Math.max(top(place) - rect.height - space + offsetTop(offset), 1)}px`,
|
||||
right: `${Math.max(right(place) - offsetLeft(offset), 1)}px`,
|
||||
}),
|
||||
};
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
</script>
|
||||
<style scoped>
|
||||
@import './guide.css';
|
||||
</style>
|
||||
<style scoped lang="less">
|
||||
.t-guide__footer--dialog {
|
||||
// 适配 QQ 小程序等
|
||||
display: inline-flex;
|
||||
.t-button {
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
98
uni_modules/tdesign-uniapp/components/guide/props.ts
Normal file
98
uni_modules/tdesign-uniapp/components/guide/props.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
/* eslint-disable */
|
||||
|
||||
/**
|
||||
* 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC
|
||||
* */
|
||||
|
||||
import type { TdGuideProps } from './type';
|
||||
export default {
|
||||
/** 透传 返回按钮 的全部属性,示例:`{ content: '返回', theme: 'default' }` */
|
||||
backButtonProps: {
|
||||
type: Object,
|
||||
},
|
||||
/** 用于自定义渲染计数部分 */
|
||||
counter: {
|
||||
type: [String, Function],
|
||||
},
|
||||
/** 当前步骤,即整个引导的进度。-1 则不展示,用于需要中断展示的场景 */
|
||||
current: {
|
||||
type: Number,
|
||||
},
|
||||
/** 当前步骤,即整个引导的进度。-1 则不展示,用于需要中断展示的场景,非受控属性 */
|
||||
defaultCurrent: {
|
||||
type: Number,
|
||||
},
|
||||
/** 透传 完成按钮 的全部属性,示例:`{ content: '完成', theme: 'primary' }` */
|
||||
finishButtonProps: {
|
||||
type: Object,
|
||||
},
|
||||
/** 是否隐藏返回按钮 */
|
||||
hideBack: Boolean,
|
||||
/** 是否隐藏计数 */
|
||||
hideCounter: Boolean,
|
||||
/** 是否隐藏跳过按钮 */
|
||||
hideSkip: Boolean,
|
||||
/** 高亮框的内边距,单位rpx */
|
||||
highlightPadding: {
|
||||
type: Number,
|
||||
default: 16,
|
||||
},
|
||||
/** 引导框的类型 */
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'popover' as TdGuideProps['mode'],
|
||||
validator(val: TdGuideProps['mode']): boolean {
|
||||
if (!val) return true;
|
||||
return ['popover', 'dialog'].includes(val);
|
||||
},
|
||||
},
|
||||
/** 透传 下一步按钮 的全部属性,示例:{ content: '下一步', theme: 'primary' } */
|
||||
nextButtonProps: {
|
||||
type: Object,
|
||||
},
|
||||
/** 是否出现遮罩层 */
|
||||
showOverlay: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
/** 透传 跳过按钮 的全部属性,{ content: '跳过', theme: 'default' } */
|
||||
skipButtonProps: {
|
||||
type: Object,
|
||||
},
|
||||
/** 用于定义每个步骤的内容,包括高亮的节点、相对位置和具体的文案内容等 */
|
||||
steps: {
|
||||
type: Array,
|
||||
},
|
||||
/** 是否使用了自定义导航栏 */
|
||||
usingCustomNavbar: Boolean,
|
||||
/** 提示框的层级 */
|
||||
zIndex: {
|
||||
type: Number,
|
||||
default: 999999,
|
||||
},
|
||||
/** 点击返回按钮时触发 */
|
||||
onBack: {
|
||||
type: Function,
|
||||
default: () => ({}),
|
||||
},
|
||||
/** 当前步骤发生变化时触发 */
|
||||
onChange: {
|
||||
type: Function,
|
||||
default: () => ({}),
|
||||
},
|
||||
/** 点击完成按钮时触发 */
|
||||
onFinish: {
|
||||
type: Function,
|
||||
default: () => ({}),
|
||||
},
|
||||
/** 点击下一步时触发 */
|
||||
onNextStepClick: {
|
||||
type: Function,
|
||||
default: () => ({}),
|
||||
},
|
||||
/** 点击跳过按钮时触发 */
|
||||
onSkip: {
|
||||
type: Function,
|
||||
default: () => ({}),
|
||||
},
|
||||
};
|
||||
174
uni_modules/tdesign-uniapp/components/guide/type.ts
Normal file
174
uni_modules/tdesign-uniapp/components/guide/type.ts
Normal file
@@ -0,0 +1,174 @@
|
||||
/* eslint-disable */
|
||||
|
||||
/**
|
||||
* 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC
|
||||
* */
|
||||
|
||||
import type { TdButtonProps as ButtonProps } from '../button/type';
|
||||
|
||||
export interface TdGuideProps {
|
||||
/**
|
||||
* 透传 返回按钮 的全部属性,示例:`{ content: '返回', theme: 'default' }`
|
||||
*/
|
||||
backButtonProps?: ButtonProps;
|
||||
/**
|
||||
* 用于自定义渲染计数部分
|
||||
*/
|
||||
counter?: string | ((params: { total: number; current: number }) => string);
|
||||
/**
|
||||
* 当前步骤,即整个引导的进度。-1 则不展示,用于需要中断展示的场景
|
||||
*/
|
||||
current?: number;
|
||||
/**
|
||||
* 当前步骤,即整个引导的进度。-1 则不展示,用于需要中断展示的场景,非受控属性
|
||||
*/
|
||||
defaultCurrent?: number;
|
||||
/**
|
||||
* 透传 完成按钮 的全部属性,示例:`{ content: '完成', theme: 'primary' }`
|
||||
*/
|
||||
finishButtonProps?: ButtonProps;
|
||||
/**
|
||||
* 是否隐藏返回按钮
|
||||
* @default false
|
||||
*/
|
||||
hideBack?: boolean;
|
||||
/**
|
||||
* 是否隐藏计数
|
||||
* @default false
|
||||
*/
|
||||
hideCounter?: boolean;
|
||||
/**
|
||||
* 是否隐藏跳过按钮
|
||||
* @default false
|
||||
*/
|
||||
hideSkip?: boolean;
|
||||
/**
|
||||
* 高亮框的内边距,单位rpx
|
||||
* @default 16
|
||||
*/
|
||||
highlightPadding?: number;
|
||||
/**
|
||||
* 引导框的类型
|
||||
* @default popover
|
||||
*/
|
||||
mode?: 'popover' | 'dialog';
|
||||
/**
|
||||
* 透传 下一步按钮 的全部属性,示例:{ content: '下一步', theme: 'primary' }
|
||||
*/
|
||||
nextButtonProps?: ButtonProps;
|
||||
/**
|
||||
* 是否出现遮罩层
|
||||
* @default true
|
||||
*/
|
||||
showOverlay?: boolean;
|
||||
/**
|
||||
* 透传 跳过按钮 的全部属性,{ content: '跳过', theme: 'default' }
|
||||
*/
|
||||
skipButtonProps?: ButtonProps;
|
||||
/**
|
||||
* 用于定义每个步骤的内容,包括高亮的节点、相对位置和具体的文案内容等
|
||||
*/
|
||||
steps?: Array<GuideStep>;
|
||||
/**
|
||||
* 是否使用了自定义导航栏
|
||||
* @default false
|
||||
*/
|
||||
usingCustomNavbar?: boolean;
|
||||
/**
|
||||
* 提示框的层级
|
||||
* @default 999999
|
||||
*/
|
||||
zIndex?: number;
|
||||
/**
|
||||
* 点击返回按钮时触发
|
||||
*/
|
||||
onBack?: (context: { e: MouseEvent; current: number; total: number }) => void;
|
||||
/**
|
||||
* 当前步骤发生变化时触发
|
||||
*/
|
||||
onChange?: (current: number, context?: { e: MouseEvent; total: number }) => void;
|
||||
/**
|
||||
* 点击完成按钮时触发
|
||||
*/
|
||||
onFinish?: (context: { e: MouseEvent; current: number; total: number }) => void;
|
||||
/**
|
||||
* 点击下一步时触发
|
||||
*/
|
||||
onNextStepClick?: (context: { e: MouseEvent; next: number; current: number; total: number }) => void;
|
||||
/**
|
||||
* 点击跳过按钮时触发
|
||||
*/
|
||||
onSkip?: (context: { e: MouseEvent; current: number; total: number }) => void;
|
||||
}
|
||||
|
||||
export interface GuideStep {
|
||||
/**
|
||||
* 用于自定义当前引导框的返回按钮的内容
|
||||
*/
|
||||
backButtonProps?: ButtonProps;
|
||||
/**
|
||||
* 当前步骤提示框的内容,支持插槽:slot="body-{{index}}" (1、当要显示body-{{index}}插槽时,请将body设置为空;2、当要显示content-{{index}}插槽完全自定义内容时,请将body和title都设置为空)
|
||||
* @default ''
|
||||
*/
|
||||
body?: string;
|
||||
/**
|
||||
* 高亮的节点。示例: `() => new Promise((resolve) => this.createSelectorQuery().select('#tdesign').boundingClientRect((rect) => resolve(rect)).exec())`
|
||||
*/
|
||||
element: StepElement;
|
||||
/**
|
||||
* 透传 完成 的全部属性,示例:`{ content: '完成', theme: 'primary' }`
|
||||
*/
|
||||
finishButtonProps?: ButtonProps;
|
||||
/**
|
||||
* 高亮框的内边距,单位rpx
|
||||
*/
|
||||
highlightPadding?: number;
|
||||
/**
|
||||
* 引导框的类型
|
||||
*/
|
||||
mode?: 'popover' | 'dialog';
|
||||
/**
|
||||
* 用于自定义当前引导框的下一步按钮的内容
|
||||
*/
|
||||
nextButtonProps?: ButtonProps;
|
||||
/**
|
||||
* 相对于 placement 的偏移量[left, top],默认单位rpx,示例:[-10, 20] 或 ['10px', '8px'] 或 ['20rpx', '16rpx'] (仅当 `mode` 为 `popover` 时生效)
|
||||
*/
|
||||
offset?: Array<string | number>;
|
||||
/**
|
||||
* 引导框相对于高亮元素出现的位置,(仅当 `mode` 为 `popover` 时生效)
|
||||
* @default 'top'
|
||||
*/
|
||||
placement?: StepPopoverPlacement;
|
||||
/**
|
||||
* 是否出现遮罩层
|
||||
* @default true
|
||||
*/
|
||||
showOverlay?: boolean;
|
||||
/**
|
||||
* 用于自定义当前步骤引导框的跳过按钮的内容
|
||||
*/
|
||||
skipButtonProps?: ButtonProps;
|
||||
/**
|
||||
* 当前步骤的标题内容,支持插槽:slot="title-{{index}}" (1、当要显示body-{{index}}插槽时,请将title设置为空;2、当要显示content-{{index}}插槽完全自定义内容时,请将body和title都设置为空)
|
||||
* @default ''
|
||||
*/
|
||||
title?: string;
|
||||
}
|
||||
|
||||
export type StepElement = () => any;
|
||||
|
||||
export type StepPopoverPlacement =
|
||||
| 'top'
|
||||
| 'left'
|
||||
| 'right'
|
||||
| 'bottom'
|
||||
| 'top-left'
|
||||
| 'top-right'
|
||||
| 'bottom-left'
|
||||
| 'bottom-right'
|
||||
| 'left-top'
|
||||
| 'left-bottom'
|
||||
| 'right-top'
|
||||
| 'right-bottom'
|
||||
| 'center';
|
||||
Reference in New Issue
Block a user