diff --git a/packages/devui-vue/devui/steps-guide/directive/steps-guide.ts b/packages/devui-vue/devui/steps-guide/directive/steps-guide.ts new file mode 100644 index 0000000000000000000000000000000000000000..cc2088fc41cceba3e36fbbcfce394ede637fb943 --- /dev/null +++ b/packages/devui-vue/devui/steps-guide/directive/steps-guide.ts @@ -0,0 +1,7 @@ +export default { + mounted(el: HTMLElement, binding, vNode) { + }, + updated(el: HTMLElement, binding) { + } + } + \ No newline at end of file diff --git a/packages/devui-vue/devui/steps-guide/hooks/use-steps-guide-ctrl.ts b/packages/devui-vue/devui/steps-guide/hooks/use-steps-guide-ctrl.ts index 9c1b13a906e7d05082915e363a21dacddd82d9bc..e7ca9d2aa6af5bb977c9853637147310aec13d3d 100644 --- a/packages/devui-vue/devui/steps-guide/hooks/use-steps-guide-ctrl.ts +++ b/packages/devui-vue/devui/steps-guide/hooks/use-steps-guide-ctrl.ts @@ -1,25 +1,40 @@ -import { ref, nextTick } from 'vue' +import { ref, nextTick, computed, WritableComputedRef, SetupContext } from 'vue' +import { StepsGuideProps, Step } from '../src/steps-guide-types' -export function useStepsGuideCtrl(stepsCount, stepIndex, updateGuidePosition) { - const showSteps = ref(true) - const closeSteps = ():void => { - showSteps.value = false +export function useStepsGuideCtrl( + props: StepsGuideProps, + ctx: SetupContext<('guide-close'|'update:stepIndex')[]>, + updateGuidePosition: Function, + stepIndex: WritableComputedRef + ) { + const stepsCount = computed(() => props.steps.length) + + const closeGuide = () => { + // 缓存关闭前的index, 并在关闭后触发事件 + const _index = stepIndex.value + stepIndex.value = -1 + nextTick(() => { + ctx.emit('guide-close', _index) + }) } const setCurrentIndex = (index:number):void => { - if (index > stepsCount.value || index < 0) index = 0 - stepIndex.value = index - if (!showSteps.value) { - showSteps.value = true + if(index !== -1 && props.stepChange()){ + if(index > -1 && index < stepsCount.value) { + stepIndex.value = index + console.log(stepIndex.value, index, stepsCount.value) nextTick(() => { + console.log(stepIndex.value, index, stepsCount.value) updateGuidePosition() }) } else { - updateGuidePosition() + console.error(`stepIndex is not within the value range`) } + } + if(index === -1) closeGuide() } return { - showSteps, - closeSteps, + stepsCount, + closeGuide, setCurrentIndex } } \ No newline at end of file diff --git a/packages/devui-vue/devui/steps-guide/hooks/use-steps-guide-position.ts b/packages/devui-vue/devui/steps-guide/hooks/use-steps-guide-position.ts index 6120300ee6ee1e5ec239de11419aa95a81c50f17..146ce4381794ebaa7cff581d4b95e7e8aa62c7e6 100644 --- a/packages/devui-vue/devui/steps-guide/hooks/use-steps-guide-position.ts +++ b/packages/devui-vue/devui/steps-guide/hooks/use-steps-guide-position.ts @@ -1,21 +1,19 @@ -import { Ref, ref, reactive, computed, nextTick } from 'vue' -import { Step, positionConf } from '../src/steps-guide-types' +import { ref, reactive, ComputedRef, nextTick } from 'vue' +import { Step, positionConf, StepsGuideProps } from '../src/steps-guide-types' -export function useStepsGuideNav(steps: Step[], stepIndex:Ref) { - - const currentStep = computed(() => { - const _step = steps[stepIndex.value] - _step.position = _step.position || 'top' - return _step - }) +export function useStepsGuidePosition( + props: StepsGuideProps, + currentStep: ComputedRef) { const guideClassList = ['devui-steps-guide'] const stepsRef = ref(null) const guidePosition = reactive({ left: '', top: '', - zIndex: 1100 + zIndex: props.zIndex }) + const updateGuidePosition = () => { + if(!currentStep.value) return; const baseTop = window.pageYOffset - document.documentElement.clientTop const baseLeft = window.pageXOffset - document.documentElement.clientLeft const currentStepPosition:positionConf = currentStep.value.position @@ -63,13 +61,14 @@ export function useStepsGuideNav(steps: Step[], stepIndex:Ref) { } guidePosition.left = _left + 'px' guidePosition.top = _top + 'px' - nextTick(() => { - // 位置更新后滚动视图 - stepGuideElement.scrollIntoView({behavior: "smooth", block: "nearest", inline: "nearest"}) - }) + if(props.scrollToTargetSwitch) { + nextTick(() => { + // 位置更新后滚动视图 + stepGuideElement.scrollIntoView({behavior: "smooth", block: "nearest", inline: "nearest"}) + }) + } } return { - currentStep, stepsRef, guidePosition, guideClassList, diff --git a/packages/devui-vue/devui/steps-guide/index.ts b/packages/devui-vue/devui/steps-guide/index.ts index 3e41d4912f03cb0733cabf48331284f71b49e903..f783ba87f370259b9443387b7eb206cd88794a9b 100644 --- a/packages/devui-vue/devui/steps-guide/index.ts +++ b/packages/devui-vue/devui/steps-guide/index.ts @@ -1,6 +1,7 @@ import type { App } from 'vue' import StepsGuide from './src/steps-guide' +import StepsGuideDirective from './directive/steps-guide' StepsGuide.install = function(app: App): void { app.component(StepsGuide.name, StepsGuide) } @@ -10,8 +11,9 @@ export { StepsGuide } export default { title: 'StepsGuide 操作指引', category: '导航', - status: '50%', + status: '80%', install(app: App): void { app.use(StepsGuide as any) + app.directive('StepsGuide', StepsGuideDirective) } } diff --git a/packages/devui-vue/devui/steps-guide/src/steps-guide-types.ts b/packages/devui-vue/devui/steps-guide/src/steps-guide-types.ts index 6c712312b44318ff434c7a147053621fcb008516..83219f7933c0b565ff2384ac18e12c3a1091769e 100644 --- a/packages/devui-vue/devui/steps-guide/src/steps-guide-types.ts +++ b/packages/devui-vue/devui/steps-guide/src/steps-guide-types.ts @@ -14,6 +14,10 @@ export type Step = { } export const stepsGuideProps = { steps: Array as PropType, + stepIndex: { + type: Number, + default: undefined + }, showClose: { type: Boolean, default: true @@ -21,6 +25,20 @@ export const stepsGuideProps = { showDots: { type: Boolean, default: true + }, + scrollToTargetSwitch: { + type: Boolean, + default: true + }, + zIndex: { + type: Number, + default: 1100 + }, + stepChange: { + type: Function, + default(){ + return true + } } } as const diff --git a/packages/devui-vue/devui/steps-guide/src/steps-guide.tsx b/packages/devui-vue/devui/steps-guide/src/steps-guide.tsx index 93cf84bde5af5c8d04b8d810404c949f10fdd881..14c621ce736f61686a3d0ce019933a206799b36d 100644 --- a/packages/devui-vue/devui/steps-guide/src/steps-guide.tsx +++ b/packages/devui-vue/devui/steps-guide/src/steps-guide.tsx @@ -1,77 +1,70 @@ import './steps-guide.scss' +import { computed, ref, defineComponent, Teleport, onMounted } from 'vue' +import { stepsGuideProps, StepsGuideProps, Step } from './steps-guide-types' +import { useStepsGuidePosition, useStepsGuideCtrl } from '../hooks' -import { defineComponent, Teleport, ref, onMounted, computed } from 'vue' -import { stepsGuideProps, StepsGuideProps } from './steps-guide-types' -import { useStepsGuideNav, useStepsGuideCtrl } from '../hooks' export default defineComponent({ name: 'DStepsGuide', props: stepsGuideProps, - emits: [], + emits: ['guide-close', 'update:stepIndex'], setup(props: StepsGuideProps, ctx) { - const stepsCount = computed(() => props.steps.length - 1) - const stepIndex = ref(0) + const stepIndexData = ref((props.stepIndex ?? 0) as number) + const stepIndex = computed({ + set: val => { + if(props.stepIndex != null) { + ctx.emit('update:stepIndex', val) + } + stepIndexData.value = val + }, + get: () => stepIndexData.value + }) + const currentStep = computed(() => { + const _step = props.steps[stepIndex.value] + if(_step) _step.position = _step.position || 'top' + return _step + }) + const { - currentStep, stepsRef, guidePosition, guideClassList, - updateGuidePosition } = useStepsGuideNav(props.steps, stepIndex) - const { showSteps, - closeSteps, - setCurrentIndex } = useStepsGuideCtrl(stepsCount, stepIndex, updateGuidePosition) + updateGuidePosition } = useStepsGuidePosition(props, currentStep) + const { + stepsCount, + closeGuide, + setCurrentIndex } = useStepsGuideCtrl(props, ctx, updateGuidePosition, stepIndex) onMounted(() => { updateGuidePosition() }) - - return { - stepsCount, - stepIndex, - showSteps, - guidePosition, - guideClassList, - stepsRef, - currentStep, - setCurrentIndex, - closeSteps - } - }, - render(props) { - const { showSteps, - guidePosition, - guideClassList, - currentStep, - stepIndex, - stepsCount, - setCurrentIndex, - closeSteps, - showClose, - showDots } = props - - return showSteps ? + ctx.expose({ + closeGuide, + setCurrentIndex + }) + return () => stepIndex.value > -1 && stepsCount.value > 0 ? ( -
+
-

{currentStep.title}

- {showClose ?
: null} -
{currentStep.content}
+

{currentStep.value.title}

+ {props.showClose ?
: null} +
{currentStep.value.content}
{ - showDots ? + props.showDots ?
{props.steps.map((step, index) => { - return + return })}
: null }
- {stepIndex > 0 ?
setCurrentIndex(--props.stepIndex)}>{'上一步'}
: null} - {stepIndex === stepsCount ? -
{'我知道啦'}
: -
{ setCurrentIndex(++props.stepIndex) }}>{'我知道啦,继续'}
} + {stepIndex.value > 0 ?
setCurrentIndex(stepIndex.value - 1)}>{'上一步'}
: null} + {stepIndex.value === stepsCount.value - 1 ? +
{'我知道啦'}
: +
{ setCurrentIndex(stepIndex.value + 1) }}>{'我知道啦,继续'}
}
diff --git a/packages/devui-vue/docs/components/steps-guide/index.md b/packages/devui-vue/docs/components/steps-guide/index.md index 4744d655014125029c194ed6273c4848e6937098..3c6973d94abbeaf3ed7f9465810394f971632c42 100644 --- a/packages/devui-vue/docs/components/steps-guide/index.md +++ b/packages/devui-vue/docs/components/steps-guide/index.md @@ -11,25 +11,94 @@ :::demo ```vue