You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
157 lines
4.1 KiB
Vue
157 lines
4.1 KiB
Vue
<template>
|
|
<view
|
|
v-if="currentStatus"
|
|
:class="`wd-step ${customClass} ${currentStatus ? 'is-' + currentStatus : ''} ${canAlignCenter ? 'is-center' : ''} ${
|
|
vertical ? 'is-vertical' : ''
|
|
}`"
|
|
:style="styles"
|
|
>
|
|
<view :class="`wd-step__header ${dot ? 'is-dot' : ''}`">
|
|
<view :class="`wd-step__icon ${dot ? 'is-dot' : !!icon || iconSlot ? 'is-icon' : 'is-text'}`">
|
|
<view v-if="dot" class="wd-step__dot"></view>
|
|
<slot v-else-if="iconSlot" name="icon" />
|
|
<wd-icon v-else-if="icon" class="wd-step__icon-inner" :name="icon" />
|
|
<view v-else class="wd-step__icon-outer">
|
|
<wd-icon v-if="currentStatus === 'finished'" name="check-bold" />
|
|
<wd-icon v-else-if="currentStatus === 'error'" name="close-bold" />
|
|
<text v-else>{{ index + 1 }}</text>
|
|
</view>
|
|
</view>
|
|
<view v-if="index < childrenLength - 1" class="wd-step__line"></view>
|
|
</view>
|
|
<view class="wd-step__content">
|
|
<view :class="`wd-step__title ${descriptionSlot || description ? 'is-description' : ''}`">
|
|
<slot v-if="titleSlot" name="title" />
|
|
<text v-else>{{ currentTitle }}</text>
|
|
</view>
|
|
<view v-if="descriptionSlot || description" class="wd-step__description">
|
|
<slot v-if="descriptionSlot" />
|
|
<text v-else>{{ description }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
<script lang="ts">
|
|
export default {
|
|
name: 'wd-step',
|
|
options: {
|
|
addGlobalClass: true,
|
|
virtualHost: true,
|
|
styleIsolation: 'shared'
|
|
}
|
|
}
|
|
</script>
|
|
<script lang="ts" setup>
|
|
import { getCurrentInstance, inject, onBeforeMount, ref } from 'vue'
|
|
|
|
type StepStatus = 'finished' | 'process' | 'error'
|
|
|
|
interface Props {
|
|
customClass?: string
|
|
customStyle?: string
|
|
title?: string
|
|
description?: string
|
|
icon?: string
|
|
status?: StepStatus
|
|
iconSlot?: boolean
|
|
titleSlot?: boolean
|
|
descriptionSlot?: boolean
|
|
}
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
customClass: '',
|
|
customStyle: '',
|
|
iconSlot: false,
|
|
titleSlot: false,
|
|
descriptionSlot: false
|
|
})
|
|
|
|
const index = ref<number>(-1)
|
|
const styles = ref<string>('')
|
|
const currentStatus = ref<string>('')
|
|
const currentTitle = ref<string>('')
|
|
const canAlignCenter = ref<boolean>(false)
|
|
const vertical = ref<boolean>(false)
|
|
const dot = ref<boolean>(false)
|
|
const childrenLength = ref<number>(0)
|
|
|
|
const parent = inject<any>('wdsteps')
|
|
const { proxy } = getCurrentInstance() as any
|
|
|
|
onBeforeMount(() => {
|
|
if (parent) {
|
|
parent.$.exposed.setChild && parent.$.exposed.setChild(proxy)
|
|
}
|
|
})
|
|
|
|
/**
|
|
* 父组件设置子组件样式
|
|
* @param v vertical
|
|
* @param d dot
|
|
* @param c canAlignCenter
|
|
*/
|
|
function setStyleFromParent(v: boolean, d: boolean, c: boolean) {
|
|
vertical.value = v
|
|
dot.value = d
|
|
canAlignCenter.value = c
|
|
}
|
|
|
|
function getIndex() {
|
|
const index = parent.$.exposed.children.findIndex((child: { $: { uid: any } }) => {
|
|
return child.$.uid === proxy.$.uid
|
|
})
|
|
return index
|
|
}
|
|
|
|
function getStyles() {
|
|
const { vertical, space } = parent
|
|
if (vertical) {
|
|
return space ? `height: ${space}` : ''
|
|
} else {
|
|
return `width: ${space || 100 / parent.$.exposed.children.length + '%'}`
|
|
}
|
|
}
|
|
function getCurrentStatus(index: number) {
|
|
if (props.status) {
|
|
return props.status
|
|
}
|
|
|
|
const { active } = parent
|
|
|
|
if (active > index) {
|
|
return 'finished'
|
|
} else if (active === index) {
|
|
return 'process'
|
|
} else {
|
|
return 'wait'
|
|
}
|
|
}
|
|
function getCurrentTitle(currentStatus: string) {
|
|
if (props.title) return props.title
|
|
|
|
switch (currentStatus) {
|
|
case 'finished':
|
|
return '已完成'
|
|
case 'error':
|
|
return '失败'
|
|
case 'process':
|
|
return '进行中'
|
|
case 'wait':
|
|
default:
|
|
return '未开始'
|
|
}
|
|
}
|
|
function setIndexAndStatus() {
|
|
index.value = getIndex()
|
|
currentStatus.value = getCurrentStatus(index.value)
|
|
currentTitle.value = getCurrentTitle(currentStatus.value)
|
|
styles.value = getStyles()
|
|
childrenLength.value = parent.$.exposed.children.length
|
|
}
|
|
|
|
defineExpose({ setIndexAndStatus, setStyleFromParent })
|
|
</script>
|
|
<style lang="scss" scoped>
|
|
@import './index.scss';
|
|
</style>
|