From 21fa32265540ccaaf8d7b1a4a1af76ba0a9f46bc Mon Sep 17 00:00:00 2001 From: populus Date: Sun, 19 Sep 2021 10:57:00 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E5=9F=BA?= =?UTF-8?q?=E7=A1=80=E7=89=88steps-guide=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/steps-guide/index.ts | 18 ++++++++ devui/steps-guide/src/steps-guide-types.ts | 16 +++++++ devui/steps-guide/src/steps-guide.scss | 27 +++++++++++ devui/steps-guide/src/steps-guide.tsx | 42 +++++++++++++++++ sites/components/steps-guide/index.md | 53 ++++++++++++++++++++++ 5 files changed, 156 insertions(+) create mode 100644 devui/steps-guide/index.ts create mode 100644 devui/steps-guide/src/steps-guide-types.ts create mode 100644 devui/steps-guide/src/steps-guide.scss create mode 100644 devui/steps-guide/src/steps-guide.tsx create mode 100644 sites/components/steps-guide/index.md diff --git a/devui/steps-guide/index.ts b/devui/steps-guide/index.ts new file mode 100644 index 00000000..62154caf --- /dev/null +++ b/devui/steps-guide/index.ts @@ -0,0 +1,18 @@ +import type { App } from 'vue' +import StepsGuide from './src/steps-guide' + +StepsGuide.install = function(app: App): void { + app.component(StepsGuide.name, StepsGuide) +} + +export { StepsGuide } + +export default { + title: 'StepsGuide 操作指引', + category: '导航', + status: '开发中', // TODO: 组件若开发完成则填入"已完成",并删除该注释 + install(app: App): void { + + app.use(StepsGuide as any) + } +} diff --git a/devui/steps-guide/src/steps-guide-types.ts b/devui/steps-guide/src/steps-guide-types.ts new file mode 100644 index 00000000..7c91f834 --- /dev/null +++ b/devui/steps-guide/src/steps-guide-types.ts @@ -0,0 +1,16 @@ +import type { ExtractPropTypes } from 'vue' + +// PropType +// export interface StepItem { +// title: string // 引导标题 +// content: string // 引导介绍内容 +// } +export const stepsGuideProps = { + /* test: { + type: Object as PropType<{ xxx: xxx }> + } */ + title: String, + content: String +} as const + +export type StepsGuideProps = ExtractPropTypes diff --git a/devui/steps-guide/src/steps-guide.scss b/devui/steps-guide/src/steps-guide.scss new file mode 100644 index 00000000..d8a65717 --- /dev/null +++ b/devui/steps-guide/src/steps-guide.scss @@ -0,0 +1,27 @@ +// @import '../style/theme/color'; +// @import '../style/theme/shadow'; +// @import '../style/theme/corner'; +// @import '../style/core/_font'; +.d-steps-guide { + width: 400px; + min-height: 160px; + // background: $devui-brand; + // box-shadow: $devui-shadow-length-feedback-overlay rgba(81, 112, 255, 0.3); + // border-radius: $devui-border-radius-feedback; + // font-size: $devui-font-size; + // color: $devui-light-text; + background: rgb(94, 124, 224); + box-shadow: rgba(81, 112, 255, 0.3) 0 4px 16px 0; + border-radius: 4px; + font-size: 12px; + color: rgb(255, 255, 255); + padding: 20px; + position: absolute; + + .devui-title { + // font-size: $devui-font-size-page-title; + opacity: 1; + margin: 0 0 20px 0; + padding: 0; + } +} diff --git a/devui/steps-guide/src/steps-guide.tsx b/devui/steps-guide/src/steps-guide.tsx new file mode 100644 index 00000000..b6766b29 --- /dev/null +++ b/devui/steps-guide/src/steps-guide.tsx @@ -0,0 +1,42 @@ +import './steps-guide.scss' + +import { defineComponent, Teleport, ref, onMounted, reactive } from 'vue' +import { stepsGuideProps, StepsGuideProps } from './steps-guide-types' + +// +export default defineComponent({ + name: 'DStepsGuide', + props: stepsGuideProps, + emits: [], + setup(props: StepsGuideProps, ctx) { + console.log(props, ctx, Teleport) + const containerRef = ref(null) + const position = reactive({ + left: '', + top: '', + zIndex: 1100 + }) + onMounted(() => { + const triggerElement = containerRef.value.firstElementChild + const targetRect = triggerElement.getBoundingClientRect(); + position.left = targetRect.left + triggerElement.clientWidth / 2 + 'px' + position.top = targetRect.top + triggerElement.clientHeight / 2 + 'px' + }) + return () => + (
+ {/* 指引位置默认只允许存在根元素 */} + { ctx.slots.default()[0] } + +
+
+
+
+
+

{ props.title }

+
{ props.content }
+
+
+
+
) + } +}) diff --git a/sites/components/steps-guide/index.md b/sites/components/steps-guide/index.md new file mode 100644 index 00000000..37ef2d86 --- /dev/null +++ b/sites/components/steps-guide/index.md @@ -0,0 +1,53 @@ +# steps-guide 操作指引 + +引导用户了解业务使用逻辑组件。 + +### 何时使用 + +业务推出新特性,或复杂的业务逻辑需要指引用户时使用。 + +### 基本用法 +设定一组操作指引信息顺序显示。 + + Step 1 + +
+ +### 弹出位置 +总共支持 8 个弹出位置。 +
+ +### 自定义 +自定义操作指引信息弹出的位置和元素。 + +
+ +```html + + +``` + + + + +### API + +d-slider 参数 + +| 参数 | 类型 | 默认 | 说明 | 跳转 | +| --------- | ------- | ----- | ------------------------------------------------------------------- | ---- | +| steps | array | [] | 可选,滑动输入条的最大值 |[基本用法](#基本用法) | + -- Gitee From bc0c7fdccf4a733d05a6a2207c0443c1a04ac129 Mon Sep 17 00:00:00 2001 From: populus Date: Thu, 23 Sep 2021 23:59:15 +0800 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20=E5=88=A0=E9=99=A4=E9=9D=9E?= =?UTF-8?q?=E5=BF=85=E8=A6=81=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/steps-guide/src/steps-guide-types.ts | 8 --- devui/steps-guide/src/steps-guide.scss | 10 ---- devui/steps-guide/src/steps-guide.tsx | 6 ++- sites/components/steps-guide/index.md | 60 ++++++++++++++++++++++ 4 files changed, 64 insertions(+), 20 deletions(-) create mode 100644 sites/components/steps-guide/index.md diff --git a/devui/steps-guide/src/steps-guide-types.ts b/devui/steps-guide/src/steps-guide-types.ts index 7c91f834..86f03e8a 100644 --- a/devui/steps-guide/src/steps-guide-types.ts +++ b/devui/steps-guide/src/steps-guide-types.ts @@ -1,14 +1,6 @@ import type { ExtractPropTypes } from 'vue' -// PropType -// export interface StepItem { -// title: string // 引导标题 -// content: string // 引导介绍内容 -// } export const stepsGuideProps = { - /* test: { - type: Object as PropType<{ xxx: xxx }> - } */ title: String, content: String } as const diff --git a/devui/steps-guide/src/steps-guide.scss b/devui/steps-guide/src/steps-guide.scss index d8a65717..cd6ce11b 100644 --- a/devui/steps-guide/src/steps-guide.scss +++ b/devui/steps-guide/src/steps-guide.scss @@ -1,15 +1,6 @@ -// @import '../style/theme/color'; -// @import '../style/theme/shadow'; -// @import '../style/theme/corner'; -// @import '../style/core/_font'; .d-steps-guide { width: 400px; min-height: 160px; - // background: $devui-brand; - // box-shadow: $devui-shadow-length-feedback-overlay rgba(81, 112, 255, 0.3); - // border-radius: $devui-border-radius-feedback; - // font-size: $devui-font-size; - // color: $devui-light-text; background: rgb(94, 124, 224); box-shadow: rgba(81, 112, 255, 0.3) 0 4px 16px 0; border-radius: 4px; @@ -19,7 +10,6 @@ position: absolute; .devui-title { - // font-size: $devui-font-size-page-title; opacity: 1; margin: 0 0 20px 0; padding: 0; diff --git a/devui/steps-guide/src/steps-guide.tsx b/devui/steps-guide/src/steps-guide.tsx index b6766b29..9b2f777e 100644 --- a/devui/steps-guide/src/steps-guide.tsx +++ b/devui/steps-guide/src/steps-guide.tsx @@ -10,12 +10,14 @@ export default defineComponent({ emits: [], setup(props: StepsGuideProps, ctx) { console.log(props, ctx, Teleport) + const teleport = Teleport const containerRef = ref(null) const position = reactive({ left: '', top: '', zIndex: 1100 }) + onMounted(() => { const triggerElement = containerRef.value.firstElementChild const targetRect = triggerElement.getBoundingClientRect(); @@ -26,7 +28,7 @@ export default defineComponent({ (
{/* 指引位置默认只允许存在根元素 */} { ctx.slots.default()[0] } - +
@@ -36,7 +38,7 @@ export default defineComponent({
{ props.content }
- + ) } }) diff --git a/sites/components/steps-guide/index.md b/sites/components/steps-guide/index.md new file mode 100644 index 00000000..cac07f08 --- /dev/null +++ b/sites/components/steps-guide/index.md @@ -0,0 +1,60 @@ +# steps-guide 操作指引 + +引导用户了解业务使用逻辑组件。 + +### 何时使用 + +业务推出新特性,或复杂的业务逻辑需要指引用户时使用。 + +### 基本用法 +设定一组操作指引信息顺序显示。 + + Step 1 + +
+ + Step 2 + +
+ +### 弹出位置 +总共支持 8 个弹出位置。 +
+ +### 自定义 +自定义操作指引信息弹出的位置和元素。 + +
+ +```html + + +``` + + + + +### API + +d-slider 参数 + +| 参数 | 类型 | 默认 | 说明 | 跳转 | +| --------- | ------- | ----- | ------------------------------------------------------------------- | ---- | +| steps | array | [] | 必选,操作指引步骤数组 |[基本用法](#基本用法) | + -- Gitee From 9975f7bb60d902153aa77818f5e9b8bc67c1b22e Mon Sep 17 00:00:00 2001 From: populus Date: Sun, 26 Sep 2021 00:59:09 +0800 Subject: [PATCH 3/4] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0steps-guide?= =?UTF-8?q?=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/steps-guide/src/steps-guide-types.ts | 11 ++-- devui/steps-guide/src/steps-guide.scss | 55 +++++++++++++++++- devui/steps-guide/src/steps-guide.tsx | 67 ++++++++++++++++------ docs/components/steps-guide/index.md | 27 +++++---- sites/components/steps-guide/index.md | 60 ------------------- 5 files changed, 123 insertions(+), 97 deletions(-) delete mode 100644 sites/components/steps-guide/index.md diff --git a/devui/steps-guide/src/steps-guide-types.ts b/devui/steps-guide/src/steps-guide-types.ts index 86f03e8a..bcbfc363 100644 --- a/devui/steps-guide/src/steps-guide-types.ts +++ b/devui/steps-guide/src/steps-guide-types.ts @@ -1,8 +1,11 @@ -import type { ExtractPropTypes } from 'vue' - +import type { ExtractPropTypes, PropType } from 'vue' +type Step = { + title: string + content: string + selector: string +} export const stepsGuideProps = { - title: String, - content: String + steps: Array as PropType } as const export type StepsGuideProps = ExtractPropTypes diff --git a/devui/steps-guide/src/steps-guide.scss b/devui/steps-guide/src/steps-guide.scss index cd6ce11b..ff35008d 100644 --- a/devui/steps-guide/src/steps-guide.scss +++ b/devui/steps-guide/src/steps-guide.scss @@ -1,11 +1,15 @@ +$devui-font-size: 12px; +$devui-border-radius: 4px; +$devui-light-text: #ffffff; + .d-steps-guide { width: 400px; min-height: 160px; background: rgb(94, 124, 224); box-shadow: rgba(81, 112, 255, 0.3) 0 4px 16px 0; - border-radius: 4px; - font-size: 12px; - color: rgb(255, 255, 255); + border-radius: $devui-border-radius; + font-size: $devui-font-size; + color: $devui-light-text; padding: 20px; position: absolute; @@ -15,3 +19,48 @@ padding: 0; } } + +.devui-ctrl { + display: flex; + flex-wrap: wrap; + + .devui-dots { + color: $devui-light-text; + position: relative; + top: 25px; + font-size: $devui-font-size; + height: 30px; + + > em { + opacity: 0.2; + margin: 0 5px 0 2px; + + &.devui-active { + opacity: 1; + } + } + } + + .devui-guide-btn { + display: flex; + flex-flow: row nowrap; + flex-grow: 1; + justify-content: flex-end; + padding: 20px 0 0 0; + white-space: nowrap; + + > div { + color: $devui-light-text; + background: rgba(255, 255, 255, 0.1); + border-radius: $devui-border-radius; + padding: 5px 15px; + cursor: pointer; + margin-left: 10px; + + &.devui-prev-step { + background: none; + border: solid 1px rgba(255, 255, 255, 0.1); + } + } + } +} diff --git a/devui/steps-guide/src/steps-guide.tsx b/devui/steps-guide/src/steps-guide.tsx index 9b2f777e..0a5a9910 100644 --- a/devui/steps-guide/src/steps-guide.tsx +++ b/devui/steps-guide/src/steps-guide.tsx @@ -1,6 +1,6 @@ import './steps-guide.scss' -import { defineComponent, Teleport, ref, onMounted, reactive } from 'vue' +import { defineComponent, Teleport, ref, onMounted, reactive, computed } from 'vue' import { stepsGuideProps, StepsGuideProps } from './steps-guide-types' // @@ -9,9 +9,10 @@ export default defineComponent({ props: stepsGuideProps, emits: [], setup(props: StepsGuideProps, ctx) { - console.log(props, ctx, Teleport) const teleport = Teleport - const containerRef = ref(null) + const stepsCount = computed(() => props.steps.length - 1) + const stepIndex = ref(0), showSteps = ref(true) + let stepsNodes const position = reactive({ left: '', top: '', @@ -19,26 +20,54 @@ export default defineComponent({ }) onMounted(() => { - const triggerElement = containerRef.value.firstElementChild + stepsNodes = props.steps.map(step => document.querySelector(step.selector)) + updateGuidePosition() + }) + function updateGuidePosition(){ + const triggerElement = stepsNodes[stepIndex.value] const targetRect = triggerElement.getBoundingClientRect(); position.left = targetRect.left + triggerElement.clientWidth / 2 + 'px' position.top = targetRect.top + triggerElement.clientHeight / 2 + 'px' - }) - return () => - (
- {/* 指引位置默认只允许存在根元素 */} - { ctx.slots.default()[0] } - -
-
-
-
-
-

{ props.title }

-
{ props.content }
+ } + function renderPrev(){ + return stepIndex.value > 0 ?
{ '上一步' }
: null + } + function renderNext(){ + return stepIndex.value === stepsCount.value ? +
{ '我知道啦' }
: +
{ '我知道啦,继续' }
+ } + function prevStep(){ + stepIndex.value-- + updateGuidePosition() + } + function nextStep(){ + stepIndex.value++ + updateGuidePosition() + } + function closeSteps(){ + showSteps.value = false + } + return () => showSteps.value ? + ( +
+
+
+
+
+

{ props.steps[stepIndex.value].title }

+
{ props.steps[stepIndex.value].content }
+
+
+ +
+
+ { renderPrev() } + { renderNext() } +
- -
) +
+ ) : null } }) diff --git a/docs/components/steps-guide/index.md b/docs/components/steps-guide/index.md index 37ef2d86..ae11156a 100644 --- a/docs/components/steps-guide/index.md +++ b/docs/components/steps-guide/index.md @@ -8,11 +8,13 @@ ### 基本用法 设定一组操作指引信息顺序显示。 - - Step 1 - +Step 1
- +Step 2 +
+Step 3 +
+ ### 弹出位置 总共支持 8 个弹出位置。
@@ -31,13 +33,16 @@ -``` - - - - -### API - -d-slider 参数 - -| 参数 | 类型 | 默认 | 说明 | 跳转 | -| --------- | ------- | ----- | ------------------------------------------------------------------- | ---- | -| steps | array | [] | 必选,操作指引步骤数组 |[基本用法](#基本用法) | - -- Gitee From c309e65aea3a664da3e9a117ea3645102c27241a Mon Sep 17 00:00:00 2001 From: populus Date: Sun, 3 Oct 2021 16:29:01 +0800 Subject: [PATCH 4/4] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E5=9F=BA?= =?UTF-8?q?=E7=A1=80=E7=89=88steps-guide=E7=BB=84=E4=BB=B6=E5=8F=8Ademo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/steps-guide/src/steps-guide-types.ts | 12 +- devui/steps-guide/src/steps-guide.scss | 255 ++++++++++++++++++--- devui/steps-guide/src/steps-guide.tsx | 69 +++++- docs/components/steps-guide/index.md | 170 +++++++++++--- 4 files changed, 429 insertions(+), 77 deletions(-) diff --git a/devui/steps-guide/src/steps-guide-types.ts b/devui/steps-guide/src/steps-guide-types.ts index bcbfc363..c162691a 100644 --- a/devui/steps-guide/src/steps-guide-types.ts +++ b/devui/steps-guide/src/steps-guide-types.ts @@ -1,8 +1,16 @@ import type { ExtractPropTypes, PropType } from 'vue' -type Step = { +type positionType = 'top-left' | 'top' | 'top-right' | 'left' | 'right' | 'bottom-left' | 'bottom' | 'bottom-right' +export type positionConf = { + left: number + top: number + type: string +} +export type Step = { title: string content: string - selector: string + trigger: string + target?: string + position?: positionType | positionConf } export const stepsGuideProps = { steps: Array as PropType diff --git a/devui/steps-guide/src/steps-guide.scss b/devui/steps-guide/src/steps-guide.scss index ff35008d..a9f035a8 100644 --- a/devui/steps-guide/src/steps-guide.scss +++ b/devui/steps-guide/src/steps-guide.scss @@ -1,66 +1,249 @@ $devui-font-size: 12px; $devui-border-radius: 4px; $devui-light-text: #ffffff; +$devui-brand:#5e7ce0; +$devui-shadow-length-feedback-overlay: var(--devui-shadow-length-feedback-overlay, 0 4px 16px 0); +$devui-border-radius-feedback: var(--devui-border-radius-feedback, 4px); +$devui-font-size-page-title: 12px; .d-steps-guide { width: 400px; min-height: 160px; - background: rgb(94, 124, 224); - box-shadow: rgba(81, 112, 255, 0.3) 0 4px 16px 0; - border-radius: $devui-border-radius; + background: $devui-brand; + box-shadow: $devui-shadow-length-feedback-overlay rgba(81, 112, 255, 0.3); + border-radius: $devui-border-radius-feedback; font-size: $devui-font-size; color: $devui-light-text; padding: 20px; position: absolute; .devui-title { + font-size: $devui-font-size-page-title; opacity: 1; margin: 0 0 20px 0; padding: 0; } -} -.devui-ctrl { - display: flex; - flex-wrap: wrap; + > .devui-arrow, + > .devui-arrow::after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; + } - .devui-dots { - color: $devui-light-text; - position: relative; - top: 25px; - font-size: $devui-font-size; - height: 30px; + > .devui-arrow { + border-width: 8px; + } - > em { - opacity: 0.2; - margin: 0 5px 0 2px; + &.left > .devui-arrow { + top: 23px; + right: -6px; + margin-top: -3px; + border-right-width: 0; + transform: rotate(-135deg); + border-left-color: $devui-brand; + } - &.devui-active { - opacity: 1; - } - } + &.top > .devui-arrow, + &.top-left > .devui-arrow, + &.top-right > .devui-arrow { + bottom: -6px; + border-bottom-width: 0; + border-top-color: $devui-brand; + transform: rotate(135deg); + } + + &.top > .devui-arrow { + left: calc(50% - 4px); + } + + &.top-left > .devui-arrow { + left: 23px; + } + + &.top-right > .devui-arrow { + right: 23px; + transform: rotate(-135deg); + } + + &.right > .devui-arrow { + top: 23px; + left: -6px; + margin-top: -3px; + border-left-width: 0; + transform: rotate(135deg); + border-right-color: $devui-brand; + } + + &.bottom > .devui-arrow, + &.bottom-left > .devui-arrow, + &.bottom-right > .devui-arrow { + top: -6px; + margin-left: 3px; + border-top-width: 0; + border-bottom-color: $devui-brand; + } + + &.bottom > .devui-arrow { + left: calc(50% - 4px); + transform: rotate(-135deg); + } + + &.bottom-right > .devui-arrow { + right: 23px; + transform: rotate(135deg); + } + + &.bottom-left > .devui-arrow { + left: 23px; + transform: rotate(-135deg); + } + + > .devui-shining-dot, + .devui-shining-plus { + position: absolute; + background: $devui-brand; + width: 6px; + height: 6px; + border-radius: $devui-border-radius-feedback; + } + + &.left > .devui-shining-dot, + &.left > .devui-shining-plus { + top: 21px; + right: -30px; + } + + &.right > .devui-shining-dot, + &.right > .devui-shining-plus { + top: 21px; + left: -30px; + } + + &.top > .devui-shining-dot, + &.top > .devui-shining-plus { + left: calc(50% - 3px); + bottom: -30px; } - .devui-guide-btn { - display: flex; - flex-flow: row nowrap; - flex-grow: 1; - justify-content: flex-end; - padding: 20px 0 0 0; - white-space: nowrap; + &.top-left > .devui-shining-dot, + &.top-left > .devui-shining-plus { + left: 21px; + bottom: -30px; + } - > div { - color: $devui-light-text; - background: rgba(255, 255, 255, 0.1); - border-radius: $devui-border-radius; - padding: 5px 15px; + &.top-right > .devui-shining-dot, + &.top-right > .devui-shining-plus { + right: 21px; + bottom: -30px; + } + + &.bottom > .devui-shining-dot, + &.bottom > .devui-shining-plus { + left: calc(50% - 3px); + top: -30px; + } + + &.bottom-right > .devui-shining-dot, + &.bottom-right > .devui-shining-plus { + top: -30px; + right: 21px; + } + + &.bottom-left > .devui-shining-dot, + &.bottom-left > .devui-shining-plus { + top: -30px; + left: 21px; + } + + .devui-shining-plus { + animation: devui-glow 2s 0s infinite; + } + + .devui-guide-container { + position: relative; + + > .icon-close { + position: absolute; + top: 0; + right: 0; cursor: pointer; - margin-left: 10px; + } + + .devui-ctrl { + display: flex; + flex-wrap: wrap; + + .devui-dots { + color: $devui-light-text; + position: relative; + top: 25px; + font-size: $devui-font-size; + height: 30px; + + > em { + opacity: 0.2; + margin: 0 5px 0 2px; - &.devui-prev-step { - background: none; - border: solid 1px rgba(255, 255, 255, 0.1); + &.devui-active { + opacity: 1; + } + } + } + + .devui-guide-btn { + display: flex; + flex-flow: row nowrap; + flex-grow: 1; + justify-content: flex-end; + padding: 20px 0 0 0; + white-space: nowrap; + + > div { + color: $devui-light-text; + background: rgba(255, 255, 255, 0.1); + border-radius: $devui-border-radius; + padding: 5px 15px; + cursor: pointer; + margin-left: 10px; + + &.devui-prev-step { + background: none; + border: solid 1px rgba(255, 255, 255, 0.1); + } + } } } } } + +/* 以下定义动画帧 */ +@keyframes devui-glow { + 0% { + transform: scale(1); + opacity: 0.5; + } + + 25% { + transform: scale(2); + opacity: 0.3; + } + + 50% { + transform: scale(3); + opacity: 0.1; + } + + 75% { + transform: scale(2); + opacity: 0.3; + } + + 100% { + transform: scale(1); + opacity: 0.5; + } +} diff --git a/devui/steps-guide/src/steps-guide.tsx b/devui/steps-guide/src/steps-guide.tsx index 0a5a9910..afaf9076 100644 --- a/devui/steps-guide/src/steps-guide.tsx +++ b/devui/steps-guide/src/steps-guide.tsx @@ -1,33 +1,78 @@ import './steps-guide.scss' import { defineComponent, Teleport, ref, onMounted, reactive, computed } from 'vue' -import { stepsGuideProps, StepsGuideProps } from './steps-guide-types' +import { stepsGuideProps, StepsGuideProps, Step, positionConf } from './steps-guide-types' -// export default defineComponent({ name: 'DStepsGuide', props: stepsGuideProps, emits: [], setup(props: StepsGuideProps, ctx) { const teleport = Teleport + const stepsRef = ref(null) const stepsCount = computed(() => props.steps.length - 1) const stepIndex = ref(0), showSteps = ref(true) - let stepsNodes + const currentStep = computed(() => { + const _step = props.steps[stepIndex.value] + _step.position = _step.position || 'top' + return _step + }) + const guideClassName = ['d-steps-guide'] const position = reactive({ left: '', top: '', zIndex: 1100 }) - onMounted(() => { - stepsNodes = props.steps.map(step => document.querySelector(step.selector)) updateGuidePosition() }) function updateGuidePosition(){ - const triggerElement = stepsNodes[stepIndex.value] - const targetRect = triggerElement.getBoundingClientRect(); - position.left = targetRect.left + triggerElement.clientWidth / 2 + 'px' - position.top = targetRect.top + triggerElement.clientHeight / 2 + 'px' + const baseTop = window.pageYOffset - document.documentElement.clientTop + const baseLeft = window.pageXOffset - document.documentElement.clientLeft + const currentStepPosition = currentStep.value.position + let left, top + // 自定义 position位置 + if(typeof currentStepPosition !== 'string'){ + guideClassName[1] = currentStepPosition.type + + left = currentStepPosition.left + top = currentStepPosition.top + } else { + guideClassName[1] = currentStepPosition + const stepGuideElement = stepsRef.value + const triggerSelector = currentStep.value.target || currentStep.value.trigger + const triggerElement = document.querySelector(triggerSelector) + const targetRect = triggerElement.getBoundingClientRect() + left = targetRect.left + triggerElement.clientWidth / 2 - stepGuideElement.clientWidth / 2 + baseLeft + top = targetRect.top + triggerElement.clientHeight / 2 - stepGuideElement.clientHeight / 2 + baseTop + const positionTypes = currentStepPosition.split('-') + switch(positionTypes[0]){ + case 'top': + top += (-stepGuideElement.clientHeight / 2 - triggerElement.clientHeight) + break + case 'bottom': + top += (stepGuideElement.clientHeight / 2 + triggerElement.clientHeight) + break + case 'left': + top += (stepGuideElement.clientHeight / 2 - triggerElement.clientHeight) + left += (-stepGuideElement.clientWidth / 2 - triggerElement.clientWidth / 2) + break + case 'right': + top += (stepGuideElement.clientHeight / 2 - triggerElement.clientHeight) + left += (stepGuideElement.clientWidth / 2 + triggerElement.clientWidth / 2) + break + } + switch(positionTypes[1]){ + case 'left': + left += (stepGuideElement.clientWidth / 2 - triggerElement.clientWidth / 2) + break + case 'right': + left += (-stepGuideElement.clientWidth / 2 + triggerElement.clientWidth / 2) + break + } + } + position.left = left + 'px' + position.top = top + 'px' } function renderPrev(){ return stepIndex.value > 0 ?
{ '上一步' }
: null @@ -50,13 +95,13 @@ export default defineComponent({ } return () => showSteps.value ? ( -
+
-

{ props.steps[stepIndex.value].title }

-
{ props.steps[stepIndex.value].content }
+

{ currentStep.value.title }

+
{ currentStep.value.content }
diff --git a/docs/components/steps-guide/index.md b/docs/components/steps-guide/index.md index ae11156a..d62c463c 100644 --- a/docs/components/steps-guide/index.md +++ b/docs/components/steps-guide/index.md @@ -8,51 +8,167 @@ ### 基本用法 设定一组操作指引信息顺序显示。 -Step 1 -
-Step 2 -
-Step 3 -
- +:::demo +```vue + + + +``` +::: + ### 弹出位置 总共支持 8 个弹出位置。 -
- -### 自定义 -自定义操作指引信息弹出的位置和元素。 - -
- -```html +:::demo +```vue - + ``` +::: - - +``` +::: ### API d-steps-guide 参数 -| 参数 | 类型 | 默认 | 说明 | 跳转 | -| --------- | ------- | ----- | ------------------------------------------------------------------- | ---- | -| steps | array | [] | 必选,操作指引步骤数组 |[基本用法](#基本用法) | +| 参数 | 类型 | 默认 | 说明 | 跳转 | +| ----- | ----- | ---- | ---------------------- | --------------------- | +| steps | array | Step[] | 必选,操作指引步骤数组 | [基本用法](#基本用法) | -- Gitee