From ad638218c703c0de43816ca65eca227aa3a7cd5a Mon Sep 17 00:00:00 2001 From: wangxq Date: Mon, 16 Sep 2024 15:50:15 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E2=9C=A8=20=E6=96=B0=E5=A2=9Etour?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E5=BC=95=E5=AF=BC=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/component/tour.md | 164 ++++++++++++++++ src/pages.json | 14 +- src/pages/index/Index.vue | 4 + src/pages/tour/Index.vue | 102 ++++++++++ .../components/wd-tour/index.scss | 125 ++++++++++++ .../components/wd-tour/types.ts | 121 ++++++++++++ .../components/wd-tour/wd-tour.vue | 183 ++++++++++++++++++ 7 files changed, 711 insertions(+), 2 deletions(-) create mode 100644 docs/component/tour.md create mode 100644 src/pages/tour/Index.vue create mode 100644 src/uni_modules/wot-design-uni/components/wd-tour/index.scss create mode 100644 src/uni_modules/wot-design-uni/components/wd-tour/types.ts create mode 100644 src/uni_modules/wot-design-uni/components/wd-tour/wd-tour.vue diff --git a/docs/component/tour.md b/docs/component/tour.md new file mode 100644 index 000000000..71e8461cf --- /dev/null +++ b/docs/component/tour.md @@ -0,0 +1,164 @@ + + +# Tour 引导 + +用于引导用户了解产品功能的气泡组件。 + +## 基本用法 + +在每一步中设置 target 目标元素的 id ,Tour 组件则会根据设置的 id 值进行查找。 + +:::warning 因微信小程序的特殊性,不建议直接将 `id` 绑定到自定义组件上面,最好是在外面嵌套一层 `view`。 ::: + +```html + + + + 点击试试 + + + + + 点击试试 + + + + + +``` + +```typescript +const show = ref(false) + +const steps = ref([ + { target: 'step-a', content: '这是第一步' }, + { target: 'step-b', content: '这是第二步' } +]) +``` + +## 类型 Type + +引导类型分为 `step` 和 `card` 两种,默认为 `step` 分步骤引导类型。`card`为单条引导,即没有操作步骤展示。 + +无论使用哪种方式,基本数据类型需要保持一致。 + +```typescript +// step多步骤引导 +const steps = ref([ + { target: 'step-a', content: '这是第一步' }, + { target: 'step-b', content: '这是第二步' } +]) + +// card 单条引导 +const steps = ref([{ target: 'step-a', content: '这是一个单条引导' }]) +``` + +## 自定义样式 + +每一条引导步骤可以通过 `popupStyle` 和 `contentStyle`来自定义样式,使用时尽量避免覆盖默认必要参数`width`、`height`、`top`、`left`、`right`。 + +```html + + + + 点击试试 + + + + + +``` + +```typescript +const show = ref(false) + +const steps = ref([ + { + target: 'step-a', + content: '自定义样式内容', + // 自定义引导区域样式 + popupStyle: { + borderRadius: '18px', + padding: '5px' + }, + // 自定义提示内容样式 + contentStyle: { + color: '#fff' + } + } +]) +``` + +## 自定义内容 + +通过 `slot` 插槽可自定义气泡弹出层内容。 + +```html + + 点击试试 + + + + // 此处也可以通过作用域插槽拿到传入的内容 + + +``` + +```typescript +const show = ref(false) + +const steps = ref([{ target: 'step-a', content: '这是一个单条引导' }]) +``` + +## Tour Attributes + +| 参数 | 说明 | 类型 | 可选值 | 默认值 | 最低版本 | +| ------------------- | --------------------------------------------------------------------------- | ------- | ------------ | ------ | -------- | +| v-model | 手动状态是否可见 | boolean | true / false | false | - | +| type | 引导类型 | string | step / card | step | - | +| steps | 数据集,详细见下面 数据格式 | array | - | - | - | +| current | 指定当前步骤 (type = step 时生效),可以操作引导步骤继续进行 | number | - | 0 | - | +| nextStepTxt | 多步骤引导时,指定`上一步`按钮展示文字(也可通过插槽`prev-step`自定义内容) | string | - | 上一步 | - | +| prevStepTxt | 多步骤引导时,指定`下一步`按钮展示文字(也可通过插槽`next-step`自定义内容) | string | - | 下一步 | - | +| completeTxt | 多步骤引导时,指定`完成`按钮展示文字(也可通过插槽`end-step`自定义内容) | string | - | 完成 | - | +| showPrevStep | 多步骤引导时,是否展示`上一步`按钮 | boolean | true / false | true | - | +| showProgress | 多步骤引导时,是否展示步骤进度 | boolean | true / false | true | - | +| mask | 是否显示遮罩层 | boolean | true / false | true | - | +| arrow | 气泡框是否显示 指向箭头 | boolean | true / false | true | - | +| showClose | 多步骤引导时,是否显示关闭按钮 | boolean | true / false | true | - | +| closeOnClickOverlay | 点击遮罩层是否可关闭引导 | boolean | true / false | true | - | +| bgColor | 自定义气泡弹框背景色(也可通过自定义插槽 `content`自定义) | string | - | #fff | - | + +## Step 数据格式 + +| 类名 | 说明 | 类型 | 是否必填 | 最低版本 | +| ------------ | ------------------ | ------ | -------- | -------- | +| target | 元素根节 id | string | 是 | - | +| content | 引导内容 | string | - | - | +| contentStyle | 自定义气泡框样式 | string | - | - | +| popupStyle | 自定义引导区域样式 | string | - | - | + +## Slot + +| name | 说明 | 最低版本 | +| ------------- | ---------------------- | -------- | +| content | 气泡弹框内容自定义样式 | - | +| prev-step | 上一步按钮自定义区域 | - | +| next-step | 下一步按钮自定义区域 | - | +| end-step | 完成按钮自定义区域 | - | +| step-progress | 步骤进度自定义区域 | - | + +## Events + +| 事件名称 | 说明 | 回调参数 | 最低版本 | +| -------- | -------------- | -------- | -------- | +| close | 隐藏时触发 | - | - | +| change | 步骤变化时触发 | - | - | + +## Tour 外部样式类 + +| 类名 | 说明 | 最低版本 | +| ------------ | ---------- | -------- | +| custom-class | 根节点样式 | - | diff --git a/src/pages.json b/src/pages.json index 5c5bb5be0..6ef6eed39 100644 --- a/src/pages.json +++ b/src/pages.json @@ -1,5 +1,6 @@ { - "pages": [{ + "pages": [ + { "path": "pages/index/Index", "name": "index", "style": { @@ -194,7 +195,6 @@ "path": "pages/notify/Index", "name": "toast", "style": { - "mp-alipay": { "allowsBounceVertical": "NO" }, @@ -752,6 +752,16 @@ "navigationBarTitleText": "NumberKeyboard 数字键盘" } }, + { + "path": "pages/tour/Index", + "name": "tour", + "style": { + "mp-alipay": { + "allowsBounceVertical": "NO" + }, + "navigationBarTitleText": "Tour 引导" + } + }, { "path": "pages/gap/Index", "name": "gap", diff --git a/src/pages/index/Index.vue b/src/pages/index/Index.vue index f62e92ede..54b66af68 100644 --- a/src/pages/index/Index.vue +++ b/src/pages/index/Index.vue @@ -289,6 +289,10 @@ const list = ref([ { id: 'numberKeyboard', name: 'NumberKeyboard 数字键盘' + }, + { + id: 'tour', + name: 'tour 引导' } ] }, diff --git a/src/pages/tour/Index.vue b/src/pages/tour/Index.vue new file mode 100644 index 000000000..d496c9d50 --- /dev/null +++ b/src/pages/tour/Index.vue @@ -0,0 +1,102 @@ + + + + diff --git a/src/uni_modules/wot-design-uni/components/wd-tour/index.scss b/src/uni_modules/wot-design-uni/components/wd-tour/index.scss new file mode 100644 index 000000000..c021170dc --- /dev/null +++ b/src/uni_modules/wot-design-uni/components/wd-tour/index.scss @@ -0,0 +1,125 @@ +@import './../common/abstracts/_mixin.scss'; +@import './../common/abstracts/variable.scss'; + +@mixin position-bottom($horizontal-position: left, $offset: 20px) { + &::before { + top: auto; + bottom: -20px; + border-bottom-color: transparent; + border-top-color: var(--wd-bg-color); + @if ($horizontal-position== 'left') { + left: $offset; + } @else { + left: auto; + right: $offset; + } + } +} + +.wot-theme-dark { + @include b(tour) { + color: $-dark-color3; + @include e(mask) { + box-shadow: 0px 0px 0px 150vh rgb(0, 0, 0, 0.85); + } + @include e(popup) { + background-color: $-dark-background7; + @include when(arrow) { + &::before { + border-bottom-color: $-dark-background7; + } + } + } + } +} + +@include b(tour) { + @include e(masked) { + position: fixed; + width: 100vh; + height: 100vh; + z-index: 2000; + top: 0; + left: 0; + background: transparent; + } + @include e(popup) { + --wd-bg-color: $-color-white; + position: fixed; + z-index: 2001; + border-radius: 10rpx; + background-color: var(--wd-bg-color); + @include when(arrow) { + &::before { + content: ''; + width: 0; + height: 0; + border: 10px solid transparent; + border-bottom-color: var(--wd-bg-color); + position: absolute; + top: -20px; + left: 20px; + } + @include m(left-top) { + &::before { + left: 20px; + } + } + @include m(right-top) { + &::before { + left: auto; + right: 20px; + } + } + @include m(left-bottom) { + @include position-bottom('left'); + } + @include m(right-bottom) { + @include position-bottom('right'); + } + } + } + @include e(mask) { + position: fixed; + width: 100px; + height: 50px; + box-shadow: 0px 0px 0px 150vh $-font-gray-2; + border-radius: 10px; + z-index: 1002; + @include when(none) { + box-shadow: none; + } + } + @include e(content) { + display: block; + padding: 10px 12px; + @include m(top) { + display: block; + text-align: right; + @include when(title) { + margin-bottom: 5px; + } + } + @include m(inner) { + margin: 5px 0 10px; + font-size: 14px; + @include when(title) { + margin: 0; + } + } + @include m(bottom) { + margin-top: 10px; + display: flex; + align-items: center; + justify-content: space-between; + } + @include m(bottom-init) { + margin: 0 10px; + } + @include m(bottom-operate) { + display: flex; + justify-content: flex-end; + gap: 5px; + } + } +} diff --git a/src/uni_modules/wot-design-uni/components/wd-tour/types.ts b/src/uni_modules/wot-design-uni/components/wd-tour/types.ts new file mode 100644 index 000000000..4621ecfae --- /dev/null +++ b/src/uni_modules/wot-design-uni/components/wd-tour/types.ts @@ -0,0 +1,121 @@ +import type { PropType } from 'vue' +import { baseProps, makeBooleanProp, makeNumberProp, makeStringProp } from '../common/props' + +/** + * 引导类型: step分步骤 card卡片 + */ +export type TTourType = 'step' | 'card' + +/** + * 数据配置参数 + */ +export interface IStepOptions { + /** + * 引导目标元素,可以是元素选择器,也可以是元素对象 + */ + target: Element | string + /** + *引导内容 + */ + content?: string + /** + * 自定义内容样式 + */ + contentStyle?: Record + /** + * 自定义引导样式 + */ + popupStyle?: Record +} + +/** + * 节点信息参数 + */ + +export interface IRect { + width?: T + height?: T + top?: T + right?: T + bottom?: T + left?: T + maxWidth?: any +} + +export const tourOptions = { + ...baseProps, + + /** + * 是否显示步骤引导 + * 类型:boolean + */ + modelValue: makeBooleanProp(false), + /** + * 引导类型,step步骤引导 card卡片引导,默认为 step + * 类型:string + */ + type: { + type: String as PropType, + default: 'step' + }, + /** + * 引导数据配置 + * 类型:Array + */ + steps: { + type: Array as PropType, + default: () => [] + }, + /** + * 当前步骤,默认为0 + * 类型:number + */ + current: makeNumberProp(0), + /** + * 上一步引导标题 + * 类型:string + */ + nextStepTxt: makeStringProp('下一步'), + /** + * 下一步引导标题 + * 类型:string + */ + prevStepTxt: makeStringProp('上一步'), + /** + * 完成引导标题 + * 类型:string + */ + completeTxt: makeStringProp('完成'), + /** + * 是否显示上一步按钮 + * 类型:boolean + */ + showPrevStep: makeBooleanProp(true), + /** + * 遮罩层是否显示,默认为true + * 类型:boolean + */ + mask: makeBooleanProp(true), + + /** + * 内容框是否显示指示箭头 + */ + arrow: makeBooleanProp(true), + + /** + * 是否显示关闭按钮 + */ + showClose: makeBooleanProp(true), + /** + * 点击遮罩层是否关闭 + */ + closeOnClickOverlay: makeBooleanProp(true), + /** + * 背景色 + */ + bgColor: makeStringProp('#fff'), + /** + * 步骤进度 + */ + showProgress: makeBooleanProp(true) +} diff --git a/src/uni_modules/wot-design-uni/components/wd-tour/wd-tour.vue b/src/uni_modules/wot-design-uni/components/wd-tour/wd-tour.vue new file mode 100644 index 000000000..c6f804ca9 --- /dev/null +++ b/src/uni_modules/wot-design-uni/components/wd-tour/wd-tour.vue @@ -0,0 +1,183 @@ + + + + + + +